1 /*
2 * Copyright (C) 2013, 2014, 2015 Nikos Mavrogiannopoulos
3 * Copyright (C) 2014, 2015 Red Hat, Inc.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <config.h>
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <sys/types.h>
26 #include <sys/uio.h>
27 #include <sys/select.h>
28 #include <sys/wait.h>
29 #include <fcntl.h>
30 #include <sys/socket.h>
31 #include <netdb.h>
32 #include <system.h>
33 #include <errno.h>
34 #include <limits.h>
35 #include <sys/ioctl.h>
36 #include <gnutls/gnutls.h>
37 #include <gnutls/crypto.h>
38 #include <tlslib.h>
39 #include <sys/un.h>
40 #include <cloexec.h>
41 #include "common.h"
42 #include "str.h"
43 #include "setproctitle.h"
44 #include <sec-mod.h>
45 #include <route-add.h>
46 #include <ip-lease.h>
47 #include <proc-search.h>
48 #include <ipc.pb-c.h>
49 #include <script-list.h>
50 #include <inttypes.h>
51 #include <ev.h>
52
53 #ifdef HAVE_MALLOC_TRIM
54 # include <malloc.h>
55 #endif
56
57 #include <vpn.h>
58 #include <tun.h>
59 #include <main.h>
60 #include <main-ban.h>
61 #include <ccan/list/list.h>
62
new_proc(main_server_st * s,pid_t pid,int cmd_fd,struct sockaddr_storage * remote_addr,socklen_t remote_addr_len,struct sockaddr_storage * our_addr,socklen_t our_addr_len,uint8_t * sid,size_t sid_size)63 struct proc_st *new_proc(main_server_st * s, pid_t pid, int cmd_fd,
64 struct sockaddr_storage *remote_addr, socklen_t remote_addr_len,
65 struct sockaddr_storage *our_addr, socklen_t our_addr_len,
66 uint8_t *sid, size_t sid_size)
67 {
68 struct proc_st *ctmp;
69
70 ctmp = talloc_zero(s, struct proc_st);
71 if (ctmp == NULL)
72 return NULL;
73
74 ctmp->pid = pid;
75 ctmp->tun_lease.fd = -1;
76 ctmp->fd = cmd_fd;
77 set_cloexec_flag (cmd_fd, 1);
78 ctmp->conn_time = time(0);
79
80 memcpy(&ctmp->remote_addr, remote_addr, remote_addr_len);
81 ctmp->remote_addr_len = remote_addr_len;
82
83 memcpy(&ctmp->our_addr, our_addr, our_addr_len);
84 ctmp->our_addr_len = our_addr_len;
85
86 list_add(&s->proc_list.head, &(ctmp->list));
87
88 /* initially we put into the "default" vhost cgroup. We
89 * will change cgroup once it is known which vhost this
90 * proc belongs to */
91 put_into_cgroup(s, GETCONFIG(s)->cgroup, pid);
92 s->stats.active_clients++;
93
94 return ctmp;
95 }
96
97 /* k: whether to kill the process
98 */
remove_proc(main_server_st * s,struct proc_st * proc,unsigned flags)99 void remove_proc(main_server_st * s, struct proc_st *proc, unsigned flags)
100 {
101 pid_t pid;
102
103 ev_io_stop(main_loop, &proc->io);
104 ev_child_stop(main_loop, &proc->ev_child);
105
106 list_del(&proc->list);
107 s->stats.active_clients--;
108
109 if ((flags&RPROC_KILL) && proc->pid != -1 && proc->pid != 0)
110 kill(proc->pid, SIGTERM);
111
112 /* close any pending sessions */
113 if (proc->active_sid && !(flags & RPROC_QUIT)) {
114 if (session_close(&(s->sec_mod_instances[proc->sec_mod_instance_index]), proc) < 0) {
115 mslog(s, proc, LOG_ERR, "error closing session (communication with sec-mod issue)");
116 exit(1);
117 }
118 }
119
120 mslog(s, proc, discon_reason_to_log_level(proc->discon_reason), "user disconnected (reason: %s, rx: %"PRIu64", tx: %"PRIu64")",
121 discon_reason_to_str(proc->discon_reason), proc->bytes_in, proc->bytes_out);
122
123 pid = remove_from_script_list(s, proc);
124 if (proc->status == PS_AUTH_COMPLETED || pid > 0) {
125 if (pid > 0) {
126 int wstatus;
127 /* we were called during the connect script being run.
128 * wait for it to finish and if it returns zero run the
129 * disconnect script */
130 if (waitpid(pid, &wstatus, 0) > 0) {
131 if (WEXITSTATUS(wstatus) == 0)
132 user_disconnected(s, proc);
133 }
134 } else { /* pid > 0 or status == PS_AUTH_COMPLETED are mutually exclusive
135 * since PS_AUTH_COMPLETED is set only after a successful script run.
136 */
137 user_disconnected(s, proc);
138 }
139 }
140
141 /* close the intercomm fd */
142 if (proc->fd >= 0)
143 close(proc->fd);
144 proc->fd = -1;
145 proc->pid = -1;
146
147 remove_iroutes(s, proc);
148
149 if (proc->ipv4 || proc->ipv6)
150 remove_ip_leases(s, proc);
151
152 close_tun(s, proc);
153 proc_table_del(s, proc);
154 if (proc->config_usage_count && *proc->config_usage_count > 0) {
155 (*proc->config_usage_count)--;
156 }
157
158 safe_memset(proc->sid, 0, sizeof(proc->sid));
159 talloc_free(proc);
160 }
161
162