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