1 /*-
2  * SSLsplit - transparent SSL/TLS interception
3  * https://www.roe.ch/SSLsplit
4  *
5  * Copyright (c) 2009-2019, Daniel Roethlisberger <daniel@roe.ch>.
6  * Copyright (c) 2017-2021, Soner Tari <sonertari@gmail.com>.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met:
11  * 1. Redistributions of source code must retain the above copyright notice,
12  *    this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  *    this list of conditions and the following disclaimer in the documentation
15  *    and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include "privsep.h"
31 
32 #include "sys.h"
33 #include "util.h"
34 #include "log.h"
35 #include "attrib.h"
36 #include "defaults.h"
37 
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <sys/select.h>
41 #include <sys/wait.h>
42 #include <netinet/in.h>
43 #include <signal.h>
44 #include <unistd.h>
45 #include <stdlib.h>
46 #include <stdio.h>
47 #include <string.h>
48 #include <errno.h>
49 #include <libgen.h>
50 #include <fcntl.h>
51 
52 
53 /*
54  * Privilege separation functionality.
55  *
56  * The server code has limitations on the internal functionality that can be
57  * used, namely only those that are initialized before forking.
58  */
59 
60 /* maximal message sizes */
61 #define PRIVSEP_MAX_REQ_SIZE	512	/* arbitrary limit */
62 #define PRIVSEP_MAX_ANS_SIZE	(1+sizeof(int))
63 /* command byte */
64 #define PRIVSEP_REQ_CLOSE	0	/* closing command socket */
65 #define PRIVSEP_REQ_OPENFILE	1	/* open content log file */
66 #define PRIVSEP_REQ_OPENFILE_P	2	/* open content log file w/mkpath */
67 #define PRIVSEP_REQ_OPENSOCK	3	/* open socket and pass fd */
68 #define PRIVSEP_REQ_CERTFILE	4	/* open cert file in certgendir */
69 #ifndef WITHOUT_USERAUTH
70 #define PRIVSEP_REQ_UPDATE_ATIME	5	/* update ip,user atime */
71 #endif /* !WITHOUT_USERAUTH */
72 /* response byte */
73 #define PRIVSEP_ANS_SUCCESS	0	/* success */
74 #define PRIVSEP_ANS_UNK_CMD	1	/* unknown command */
75 #define PRIVSEP_ANS_INVALID	2	/* invalid message */
76 #define PRIVSEP_ANS_DENIED	3	/* request denied */
77 #define PRIVSEP_ANS_SYS_ERR	4	/* system error; arg=errno */
78 
79 /* Whether we short-circuit calls to privsep_client_* directly to
80  * privsep_server_* within the client process, bypassing the privilege
81  * separation mechanism; this is a performance optimization for use cases
82  * where the user chooses performance over security, especially with options
83  * that require privsep operations for each connection passing through.
84  * In the current implementation, for consistency, we still fork normally, but
85  * will not actually send any privsep requests to the parent process. */
86 static int privsep_fastpath;
87 
88 /* communication with signal handler */
89 static volatile sig_atomic_t received_sighup;
90 static volatile sig_atomic_t received_sigint;
91 static volatile sig_atomic_t received_sigquit;
92 static volatile sig_atomic_t received_sigterm;
93 static volatile sig_atomic_t received_sigchld;
94 static volatile sig_atomic_t received_sigusr1;
95 /* write end of pipe used for unblocking select */
96 static volatile sig_atomic_t selfpipe_wrfd;
97 
98 static void
privsep_server_signal_handler(int sig)99 privsep_server_signal_handler(int sig)
100 {
101 	int saved_errno;
102 
103 	saved_errno = errno;
104 
105 #ifdef DEBUG_PRIVSEP_SERVER
106 	log_dbg_printf("privsep_server_signal_handler\n");
107 #endif /* DEBUG_PRIVSEP_SERVER */
108 
109 	switch (sig) {
110 	case SIGHUP:
111 		received_sighup = 1;
112 		break;
113 	case SIGINT:
114 		received_sigint = 1;
115 		break;
116 	case SIGQUIT:
117 		received_sigquit = 1;
118 		break;
119 	case SIGTERM:
120 		received_sigterm = 1;
121 		break;
122 	case SIGCHLD:
123 		received_sigchld = 1;
124 		break;
125 	case SIGUSR1:
126 		received_sigusr1 = 1;
127 		break;
128 	}
129 	if (selfpipe_wrfd != -1) {
130 		ssize_t n;
131 
132 #ifdef DEBUG_PRIVSEP_SERVER
133 		log_dbg_printf("writing to selfpipe_wrfd %i\n", selfpipe_wrfd);
134 #endif /* DEBUG_PRIVSEP_SERVER */
135 		do {
136 			n = write(selfpipe_wrfd, "!", 1);
137 		} while (n == -1 && errno == EINTR);
138 		if (n == -1) {
139 			log_err_level_printf(LOG_CRIT, "Failed to write from signal handler: "
140 			               "%s (%i)\n", strerror(errno), errno);
141 			/* ignore error */
142 		}
143 #ifdef DEBUG_PRIVSEP_SERVER
144 	} else {
145 		log_dbg_printf("selfpipe_wrfd is %i - not writing\n", selfpipe_wrfd);
146 #endif /* DEBUG_PRIVSEP_SERVER */
147 	}
148 	errno = saved_errno;
149 }
150 
151 static int WUNRES
privsep_server_openfile_verify(global_t * global,const char * fn,UNUSED int mkpath)152 privsep_server_openfile_verify(global_t *global, const char *fn, UNUSED int mkpath)
153 {
154 	/* Prefix must match one of the active log files that use privsep. */
155 	do {
156 		if (global->contentlog) {
157 			if (strstr(fn, global->contentlog_isspec
158 			               ? global->contentlog_basedir
159 			               : global->contentlog) == fn)
160 				break;
161 		}
162 		if (global->pcaplog) {
163 			if (strstr(fn, global->pcaplog_isspec
164 			               ? global->pcaplog_basedir
165 			               : global->pcaplog) == fn)
166 				break;
167 		}
168 		if (global->connectlog) {
169 			if (strstr(fn, global->connectlog) == fn)
170 				break;
171 		}
172 		if (global->masterkeylog) {
173 			if (strstr(fn, global->masterkeylog) == fn)
174 				break;
175 		}
176 		return -1;
177 	} while (0);
178 
179 	/* Path must not contain dot-dot to prevent escaping the prefix. */
180 	if (strstr(fn, "/../"))
181 		return -1;
182 
183 	return 0;
184 }
185 
186 static int WUNRES
privsep_server_openfile(const char * fn,int mkpath)187 privsep_server_openfile(const char *fn, int mkpath)
188 {
189 	int fd, tmp;
190 
191 	if (mkpath) {
192 		char *filedir, *fn2;
193 
194 		fn2 = strdup(fn);
195 		if (!fn2) {
196 			tmp = errno;
197 			log_err_level_printf(LOG_CRIT, "Could not duplicate filname: %s (%i)\n",
198 			               strerror(errno), errno);
199 			errno = tmp;
200 			return -1;
201 		}
202 		filedir = dirname(fn2);
203 		if (!filedir) {
204 			tmp = errno;
205 			log_err_level_printf(LOG_CRIT, "Could not get dirname: %s (%i)\n",
206 			               strerror(errno), errno);
207 			free(fn2);
208 			errno = tmp;
209 			return -1;
210 		}
211 		if (sys_mkpath(filedir, DFLT_DIRMODE) == -1) {
212 			tmp = errno;
213 			log_err_level_printf(LOG_CRIT, "Could not create directory '%s': %s (%i)\n",
214 			               filedir, strerror(errno), errno);
215 			free(fn2);
216 			errno = tmp;
217 			return -1;
218 		}
219 		free(fn2);
220 	}
221 
222 	fd = open(fn, O_RDWR|O_CREAT, DFLT_FILEMODE);
223 	if (fd == -1) {
224 		tmp = errno;
225 		log_err_level_printf(LOG_CRIT, "Failed to open '%s': %s (%i)\n",
226 		               fn, strerror(errno), errno);
227 		errno = tmp;
228 		return -1;
229 	}
230 	if (lseek(fd, 0, SEEK_END) == -1) {
231 		tmp = errno;
232 		log_err_level_printf(LOG_CRIT, "Failed to seek on '%s': %s (%i)\n",
233 		               fn, strerror(errno), errno);
234 		errno = tmp;
235 		return -1;
236 	}
237 	return fd;
238 }
239 
240 static int WUNRES
privsep_server_opensock_verify(global_t * global,void * arg)241 privsep_server_opensock_verify(global_t *global, void *arg)
242 {
243 	/* This check is safe, because modifications of the spec in the child
244 	 * process do not affect the copy of the spec here in the parent. */
245 	for (proxyspec_t *spec = global->spec; spec; spec = spec->next) {
246 		if (spec == arg)
247 			return 0;
248 	}
249 	return 1;
250 }
251 
252 static int WUNRES
privsep_server_opensock(const proxyspec_t * spec)253 privsep_server_opensock(const proxyspec_t *spec)
254 {
255 	evutil_socket_t fd;
256 	int on = 1;
257 	int rv;
258 
259 	fd = socket(spec->listen_addr.ss_family, SOCK_STREAM, IPPROTO_TCP);
260 	if (fd == -1) {
261 		log_err_level_printf(LOG_CRIT, "Error from socket(): %s (%i)\n",
262 		               strerror(errno), errno);
263 		evutil_closesocket(fd);
264 		return -1;
265 	}
266 
267 	rv = evutil_make_socket_nonblocking(fd);
268 	if (rv == -1) {
269 		log_err_level_printf(LOG_CRIT, "Error making socket nonblocking: %s (%i)\n",
270 		               strerror(errno), errno);
271 		evutil_closesocket(fd);
272 		return -1;
273 	}
274 
275 	rv = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&on, sizeof(on));
276 	if (rv == -1) {
277 		log_err_level_printf(LOG_CRIT, "Error from setsockopt(SO_KEEPALIVE): %s (%i)\n",
278 		               strerror(errno), errno);
279 		evutil_closesocket(fd);
280 		return -1;
281 	}
282 
283 	rv = evutil_make_listen_socket_reuseable(fd);
284 	if (rv == -1) {
285 		log_err_level_printf(LOG_CRIT, "Error from setsockopt(SO_REUSABLE): %s\n",
286 		               strerror(errno));
287 		evutil_closesocket(fd);
288 		return -1;
289 	}
290 
291 	if (spec->natsocket && (spec->natsocket(fd) == -1)) {
292 		log_err_level_printf(LOG_CRIT, "Error from spec->natsocket()\n");
293 		evutil_closesocket(fd);
294 		return -1;
295 	}
296 
297 	rv = bind(fd, (struct sockaddr *)&spec->listen_addr,
298 	          spec->listen_addrlen);
299 	if (rv == -1) {
300 		log_err_level_printf(LOG_CRIT, "Error from bind(): %s\n", strerror(errno));
301 		evutil_closesocket(fd);
302 		return -1;
303 	}
304 
305 	return fd;
306 }
307 
308 static int WUNRES
privsep_server_certfile_verify(global_t * global,const char * fn)309 privsep_server_certfile_verify(global_t *global, const char *fn)
310 {
311 	if (!global->certgendir)
312 		return -1;
313 	if (strstr(fn, global->certgendir) != fn || strstr(fn, "/../"))
314 		return -1;
315 	return 0;
316 }
317 
318 static int WUNRES
privsep_server_certfile(const char * fn)319 privsep_server_certfile(const char *fn)
320 {
321 	int fd;
322 
323 	fd = open(fn, O_WRONLY|O_CREAT|O_EXCL, DFLT_FILEMODE);
324 	if (fd == -1 && errno != EEXIST) {
325 		log_err_level_printf(LOG_CRIT, "Failed to open '%s': %s (%i)\n",
326 		               fn, strerror(errno), errno);
327 		return -1;
328 	}
329 	return fd;
330 }
331 
332 #ifndef WITHOUT_USERAUTH
333 static int WUNRES
privsep_server_update_atime(global_t * global,const userdbkeys_t * keys)334 privsep_server_update_atime(global_t *global, const userdbkeys_t *keys)
335 {
336 	time_t atime = time(NULL);
337 	// @todo Do we really need to reset the stmt, as we always reset while returning?
338 	sqlite3_reset(global->update_user_atime);
339 	sqlite3_bind_int(global->update_user_atime, 1, atime);
340 	sqlite3_bind_text(global->update_user_atime, 2, keys->ip, -1, NULL);
341 	sqlite3_bind_text(global->update_user_atime, 3, keys->user, -1, NULL);
342 	sqlite3_bind_text(global->update_user_atime, 4, keys->ether, -1, NULL);
343 
344 	int rc = sqlite3_step(global->update_user_atime);
345 
346 	// Do not retry in case we cannot acquire db file or database: SQLITE_BUSY or SQLITE_LOCKED respectively
347 	// No need to waste resources, atime update is not so critical
348 	if (rc == SQLITE_DONE) {
349 		log_dbg_printf("privsep_server_update_atime: Updated atime of user %s=%lld\n", keys->user, (long long)atime);
350 	} else {
351 		log_err_printf("Error updating user atime: %s\n", sqlite3_errmsg(global->userdb));
352 	}
353 	sqlite3_reset(global->update_user_atime);
354 	return 0;
355 }
356 #endif /* !WITHOUT_USERAUTH */
357 
358 /*
359  * Handle a single request on a readable server socket.
360  * Returns 0 on success, 1 on EOF and -1 on error.
361  */
362 static int WUNRES
privsep_server_handle_req(global_t * global,int srvsock)363 privsep_server_handle_req(global_t *global, int srvsock)
364 {
365 	char req[PRIVSEP_MAX_REQ_SIZE];
366 	char ans[PRIVSEP_MAX_ANS_SIZE];
367 	ssize_t n;
368 	int mkpath = 0;
369 
370 	if ((n = sys_recvmsgfd(srvsock, req, sizeof(req),
371 	                       NULL)) == -1) {
372 		if (errno == EPIPE || errno == ECONNRESET) {
373 			/* unfriendly EOF, leave server */
374 			return 1;
375 		}
376 		log_err_level_printf(LOG_CRIT, "Failed to receive msg: %s (%i)\n",
377 		               strerror(errno), errno);
378 		return -1;
379 	}
380 	if (n == 0) {
381 		/* EOF, leave server; will not happen for SOCK_DGRAM sockets */
382 		return 1;
383 	}
384 	log_dbg_printf("Received privsep req type %02x sz %zd on srvsock %i\n",
385 	               req[0], n, srvsock);
386 	switch (req[0]) {
387 	case PRIVSEP_REQ_CLOSE: {
388 		/* client indicates EOF through close message */
389 		return 1;
390 	}
391 	case PRIVSEP_REQ_OPENFILE_P:
392 		mkpath = 1;
393 		/* fall through */
394 	case PRIVSEP_REQ_OPENFILE: {
395 		char *fn;
396 		int fd;
397 
398 		if (n < 2) {
399 			ans[0] = PRIVSEP_ANS_INVALID;
400 			if (sys_sendmsgfd(srvsock, ans, 1, -1) == -1) {
401 				log_err_level_printf(LOG_CRIT, "Sending message failed: %s (%i"
402 				               ")\n", strerror(errno), errno);
403 				return -1;
404 			}
405 		}
406 		if (!(fn = malloc(n))) {
407 			ans[0] = PRIVSEP_ANS_SYS_ERR;
408 			*((int*)&ans[1]) = errno;
409 			if (sys_sendmsgfd(srvsock, ans, 1 + sizeof(int),
410 			                  -1) == -1) {
411 				log_err_level_printf(LOG_CRIT, "Sending message failed: %s (%i"
412 				               ")\n", strerror(errno), errno);
413 				return -1;
414 			}
415 			return 0;
416 		}
417 		memcpy(fn, req + 1, n - 1);
418 		fn[n - 1] = '\0';
419 		if (privsep_server_openfile_verify(global, fn, mkpath) == -1) {
420 			free(fn);
421 			ans[0] = PRIVSEP_ANS_DENIED;
422 			if (sys_sendmsgfd(srvsock, ans, 1, -1) == -1) {
423 				log_err_level_printf(LOG_CRIT, "Sending message failed: %s (%i"
424 				               ")\n", strerror(errno), errno);
425 				return -1;
426 			}
427 			return 0;
428 		}
429 		if ((fd = privsep_server_openfile(fn, mkpath)) == -1) {
430 			free(fn);
431 			ans[0] = PRIVSEP_ANS_SYS_ERR;
432 			*((int*)&ans[1]) = errno;
433 			if (sys_sendmsgfd(srvsock, ans, 1 + sizeof(int),
434 			                  -1) == -1) {
435 				log_err_level_printf(LOG_CRIT, "Sending message failed: %s (%i"
436 				               ")\n", strerror(errno), errno);
437 				return -1;
438 			}
439 			return 0;
440 		} else {
441 			free(fn);
442 			ans[0] = PRIVSEP_ANS_SUCCESS;
443 			if (sys_sendmsgfd(srvsock, ans, 1, fd) == -1) {
444 				close(fd);
445 				log_err_level_printf(LOG_CRIT, "Sending message failed: %s (%i"
446 				               ")\n", strerror(errno), errno);
447 				return -1;
448 			}
449 			close(fd);
450 			return 0;
451 		}
452 		/* not reached */
453 		break;
454 	}
455 	case PRIVSEP_REQ_OPENSOCK: {
456 		proxyspec_t *arg;
457 		int s;
458 
459 		if (n != sizeof(char) + sizeof(arg)) {
460 			ans[0] = PRIVSEP_ANS_INVALID;
461 			if (sys_sendmsgfd(srvsock, ans, 1, -1) == -1) {
462 				log_err_level_printf(LOG_CRIT, "Sending message failed: %s (%i"
463 				               ")\n", strerror(errno), errno);
464 				return -1;
465 			}
466 			return 0;
467 		}
468 		arg = *(proxyspec_t**)(&req[1]);
469 		if (privsep_server_opensock_verify(global, arg) == -1) {
470 			ans[0] = PRIVSEP_ANS_DENIED;
471 			if (sys_sendmsgfd(srvsock, ans, 1, -1) == -1) {
472 				log_err_level_printf(LOG_CRIT, "Sending message failed: %s (%i"
473 				               ")\n", strerror(errno), errno);
474 				return -1;
475 			}
476 			return 0;
477 		}
478 		if ((s = privsep_server_opensock(arg)) == -1) {
479 			ans[0] = PRIVSEP_ANS_SYS_ERR;
480 			*((int*)&ans[1]) = errno;
481 			if (sys_sendmsgfd(srvsock, ans, 1 + sizeof(int),
482 			                  -1) == -1) {
483 				log_err_level_printf(LOG_CRIT, "Sending message failed: %s (%i"
484 				               ")\n", strerror(errno), errno);
485 				return -1;
486 			}
487 			return 0;
488 		} else {
489 			ans[0] = PRIVSEP_ANS_SUCCESS;
490 			if (sys_sendmsgfd(srvsock, ans, 1, s) == -1) {
491 				evutil_closesocket(s);
492 				log_err_level_printf(LOG_CRIT, "Sending message failed: %s (%i"
493 				               ")\n", strerror(errno), errno);
494 				return -1;
495 			}
496 			evutil_closesocket(s);
497 			return 0;
498 		}
499 		/* not reached */
500 		break;
501 	}
502 #ifndef WITHOUT_USERAUTH
503 	case PRIVSEP_REQ_UPDATE_ATIME: {
504 		userdbkeys_t arg;
505 
506 		if (n != sizeof(char) + sizeof(userdbkeys_t)) {
507 			ans[0] = PRIVSEP_ANS_INVALID;
508 			if (sys_sendmsgfd(srvsock, ans, 1, -1) == -1) {
509 				log_err_level_printf(LOG_CRIT, "Sending message failed: %s (%i"
510 				               ")\n", strerror(errno), errno);
511 				return -1;
512 			}
513 			return 0;
514 		}
515 		arg = *(userdbkeys_t*)(&req[1]);
516 		if (privsep_server_update_atime(global, &arg) == -1) {
517 			ans[0] = PRIVSEP_ANS_SYS_ERR;
518 			*((int*)&ans[1]) = errno;
519 			if (sys_sendmsgfd(srvsock, ans, 1 + sizeof(int),
520 			                  -1) == -1) {
521 				log_err_level_printf(LOG_CRIT, "Sending message failed: %s (%i"
522 				               ")\n", strerror(errno), errno);
523 				return -1;
524 			}
525 			return 0;
526 		} else {
527 			ans[0] = PRIVSEP_ANS_SUCCESS;
528 			// @attention Pass -1 as the 4th param, otherwise passing 0 opens an stdin (fd 0), causing fd leak
529 			if (sys_sendmsgfd(srvsock, ans, 1, -1) == -1) {
530 				log_err_level_printf(LOG_CRIT, "Sending message failed: %s (%i"
531 				               ")\n", strerror(errno), errno);
532 				return -1;
533 			}
534 			return 0;
535 		}
536 		/* not reached */
537 		break;
538 	}
539 #endif /* !WITHOUT_USERAUTH */
540 	case PRIVSEP_REQ_CERTFILE: {
541 		char *fn;
542 		int fd;
543 
544 		if (n < 2) {
545 			ans[0] = PRIVSEP_ANS_INVALID;
546 			if (sys_sendmsgfd(srvsock, ans, 1, -1) == -1) {
547 				log_err_level_printf(LOG_CRIT, "Sending message failed: %s (%i"
548 				               ")\n", strerror(errno), errno);
549 				return -1;
550 			}
551 		}
552 		if (!(fn = malloc(n))) {
553 			ans[0] = PRIVSEP_ANS_SYS_ERR;
554 			*((int*)&ans[1]) = errno;
555 			if (sys_sendmsgfd(srvsock, ans, 1 + sizeof(int),
556 			                  -1) == -1) {
557 				log_err_level_printf(LOG_CRIT, "Sending message failed: %s (%i"
558 				               ")\n", strerror(errno), errno);
559 				return -1;
560 			}
561 			return 0;
562 		}
563 		memcpy(fn, req + 1, n - 1);
564 		fn[n - 1] = '\0';
565 		if (privsep_server_certfile_verify(global, fn) == -1) {
566 			free(fn);
567 			ans[0] = PRIVSEP_ANS_DENIED;
568 			if (sys_sendmsgfd(srvsock, ans, 1, -1) == -1) {
569 				log_err_level_printf(LOG_CRIT, "Sending message failed: %s (%i"
570 				               ")\n", strerror(errno), errno);
571 				return -1;
572 			}
573 			return 0;
574 		}
575 		if ((fd = privsep_server_certfile(fn)) == -1) {
576 			free(fn);
577 			ans[0] = PRIVSEP_ANS_SYS_ERR;
578 			*((int*)&ans[1]) = errno;
579 			if (sys_sendmsgfd(srvsock, ans, 1 + sizeof(int),
580 			                  -1) == -1) {
581 				log_err_level_printf(LOG_CRIT, "Sending message failed: %s (%i"
582 				               ")\n", strerror(errno), errno);
583 				return -1;
584 			}
585 			return 0;
586 		} else {
587 			free(fn);
588 			ans[0] = PRIVSEP_ANS_SUCCESS;
589 			if (sys_sendmsgfd(srvsock, ans, 1, fd) == -1) {
590 				close(fd);
591 				log_err_level_printf(LOG_CRIT, "Sending message failed: %s (%i"
592 				               ")\n", strerror(errno), errno);
593 				return -1;
594 			}
595 			close(fd);
596 			return 0;
597 		}
598 		/* not reached */
599 		break;
600 	}
601 	default:
602 		ans[0] = PRIVSEP_ANS_UNK_CMD;
603 		if (sys_sendmsgfd(srvsock, ans, 1, -1) == -1) {
604 			log_err_level_printf(LOG_CRIT, "Sending message failed: %s (%i"
605 			               ")\n", strerror(errno), errno);
606 			return -1;
607 		}
608 	}
609 	return 0;
610 }
611 
612 /*
613  * Privilege separation server (main privileged monitor loop)
614  *
615  * sigpipe is the self-pipe trick pipe used for communicating signals to
616  * the main event loop and break out of select() without race conditions.
617  * srvsock[] is a dynamic array of connected privsep server sockets to serve.
618  * Caller is responsible for freeing memory after returning, if necessary.
619  * childpid is the pid of the child process to forward signals to.
620  *
621  * Returns 0 on a successful clean exit and -1 on errors.
622  */
623 static int
privsep_server(global_t * global,int sigpipe,int srvsock[],size_t nsrvsock,pid_t childpid)624 privsep_server(global_t *global, int sigpipe, int srvsock[], size_t nsrvsock,
625                pid_t childpid)
626 {
627 	int srveof[nsrvsock];
628 	size_t i = 0;
629 
630 	for (i = 0; i < nsrvsock; i++) {
631 		srveof[i] = 0;
632 	}
633 
634 	for (;;) {
635 		fd_set readfds;
636 		int maxfd, rv;
637 
638 #ifdef DEBUG_PRIVSEP_SERVER
639 		log_dbg_printf("privsep_server select()\n");
640 #endif /* DEBUG_PRIVSEP_SERVER */
641 		do {
642 			FD_ZERO(&readfds);
643 			FD_SET(sigpipe, &readfds);
644 			maxfd = sigpipe;
645 			for (i = 0; i < nsrvsock; i++) {
646 				if (!srveof[i]) {
647 					FD_SET(srvsock[i], &readfds);
648 					maxfd = util_max(maxfd, srvsock[i]);
649 				}
650 			}
651 			rv = select(maxfd + 1, &readfds, NULL, NULL, NULL);
652 #ifdef DEBUG_PRIVSEP_SERVER
653 			log_dbg_printf("privsep_server woke up (1)\n");
654 #endif /* DEBUG_PRIVSEP_SERVER */
655 		} while (rv == -1 && errno == EINTR);
656 		if (rv == -1) {
657 			log_err_level_printf(LOG_CRIT, "select() failed: %s (%i)\n",
658 			               strerror(errno), errno);
659 			return -1;
660 		}
661 #ifdef DEBUG_PRIVSEP_SERVER
662 		log_dbg_printf("privsep_server woke up (2)\n");
663 #endif /* DEBUG_PRIVSEP_SERVER */
664 
665 		if (FD_ISSET(sigpipe, &readfds)) {
666 			char buf[16];
667 			ssize_t n;
668 			/* first drain the signal pipe, then deal with
669 			 * all the individual signal flags */
670 			n = read(sigpipe, buf, sizeof(buf));
671 			if (n == -1) {
672 				log_err_level_printf(LOG_CRIT, "read(sigpipe) failed:"
673 				               " %s (%i)\n",
674 				               strerror(errno), errno);
675 				return -1;
676 			}
677 			if (received_sigquit) {
678 				if (kill(childpid, SIGQUIT) == -1) {
679 					log_err_level_printf(LOG_CRIT, "kill(%i,SIGQUIT) "
680 					               "failed: %s (%i)\n",
681 					               childpid,
682 					               strerror(errno), errno);
683 				}
684 				received_sigquit = 0;
685 			}
686 			if (received_sigterm) {
687 				if (kill(childpid, SIGTERM) == -1) {
688 					log_err_level_printf(LOG_CRIT, "kill(%i,SIGTERM) "
689 					               "failed: %s (%i)\n",
690 					               childpid,
691 					               strerror(errno), errno);
692 				}
693 				received_sigterm = 0;
694 			}
695 			if (received_sighup) {
696 				if (kill(childpid, SIGHUP) == -1) {
697 					log_err_level_printf(LOG_CRIT, "kill(%i,SIGHUP) "
698 					               "failed: %s (%i)\n",
699 					               childpid,
700 					               strerror(errno), errno);
701 				}
702 				received_sighup = 0;
703 			}
704 			if (received_sigusr1) {
705 				if (kill(childpid, SIGUSR1) == -1) {
706 					log_err_level_printf(LOG_CRIT, "kill(%i,SIGUSR1) "
707 					               "failed: %s (%i)\n",
708 					               childpid,
709 					               strerror(errno), errno);
710 				}
711 				received_sigusr1 = 0;
712 			}
713 			if (received_sigint) {
714 				/* if we don't detach from the TTY, the
715 				 * child process receives SIGINT directly */
716 				if (global->detach) {
717 					if (kill(childpid, SIGINT) == -1) {
718 						log_err_level_printf(LOG_CRIT, "kill(%i,SIGINT"
719 						               ") failed: "
720 						               "%s (%i)\n",
721 						               childpid,
722 						               strerror(errno),
723 						               errno);
724 					}
725 				}
726 				received_sigint = 0;
727 			}
728 			if (received_sigchld) {
729 				/* break the loop; because we are using
730 				 * SOCKET_DGRAM we don't get EOF conditions
731 				 * on the disconnected socket ends here
732 				 * unless we attempt to write or read, so
733 				 * we depend on SIGCHLD to notify us of
734 				 * our child erroring out or crashing */
735 				break;
736 			}
737 		}
738 
739 		for (i = 0; i < nsrvsock; i++) {
740 			if (FD_ISSET(srvsock[i], &readfds)) {
741 				int rv = privsep_server_handle_req(global,
742 				                                   srvsock[i]);
743 				if (rv == -1) {
744 					log_err_level_printf(LOG_CRIT, "Failed to handle "
745 					               "privsep req "
746 					               "on srvsock %i\n",
747 					               srvsock[i]);
748 					return -1;
749 				}
750 				if (rv == 1) {
751 #ifdef DEBUG_PRIVSEP_SERVER
752 					log_dbg_printf("srveof[%zu]=1\n", i);
753 #endif /* DEBUG_PRIVSEP_SERVER */
754 					srveof[i] = 1;
755 				}
756 			}
757 		}
758 
759 		/*
760 		 * We cannot exit as long as we need the signal handling,
761 		 * which is as long as the child process is running.
762 		 * The only way out of here is receiving SIGCHLD.
763 		 */
764 	}
765 
766 	return 0;
767 }
768 
769 int
privsep_client_openfile(int clisock,const char * fn,int mkpath)770 privsep_client_openfile(int clisock, const char *fn, int mkpath)
771 {
772 	char ans[PRIVSEP_MAX_ANS_SIZE];
773 	char req[1 + strlen(fn)];
774 	int fd = -1;
775 	ssize_t n;
776 
777 	if (privsep_fastpath)
778 		return privsep_server_openfile(fn, mkpath);
779 
780 	req[0] = mkpath ? PRIVSEP_REQ_OPENFILE_P : PRIVSEP_REQ_OPENFILE;
781 	memcpy(req + 1, fn, sizeof(req) - 1);
782 
783 	if (sys_sendmsgfd(clisock, req, sizeof(req), -1) == -1) {
784 		return -1;
785 	}
786 
787 	if ((n = sys_recvmsgfd(clisock, ans, sizeof(ans), &fd)) == -1) {
788 		return -1;
789 	}
790 
791 	if (n < 1) {
792 		errno = EINVAL;
793 		return -1;
794 	}
795 
796 	switch (ans[0]) {
797 	case PRIVSEP_ANS_SUCCESS:
798 		break;
799 	case PRIVSEP_ANS_DENIED:
800 		errno = EACCES;
801 		return -1;
802 	case PRIVSEP_ANS_SYS_ERR:
803 		if (n < (ssize_t)(1 + sizeof(int))) {
804 			errno = EINVAL;
805 			return -1;
806 		}
807 		errno = *((int*)&ans[1]);
808 		return -1;
809 	case PRIVSEP_ANS_UNK_CMD:
810 	case PRIVSEP_ANS_INVALID:
811 	default:
812 		errno = EINVAL;
813 		return -1;
814 	}
815 
816 	return fd;
817 }
818 
819 int
privsep_client_opensock(int clisock,const proxyspec_t * spec)820 privsep_client_opensock(int clisock, const proxyspec_t *spec)
821 {
822 	char ans[PRIVSEP_MAX_ANS_SIZE];
823 	char req[1 + sizeof(spec)];
824 	int fd = -1;
825 	ssize_t n;
826 
827 	if (privsep_fastpath)
828 		return privsep_server_opensock(spec);
829 
830 	req[0] = PRIVSEP_REQ_OPENSOCK;
831 	*((const proxyspec_t **)&req[1]) = spec;
832 
833 	if (sys_sendmsgfd(clisock, req, sizeof(req), -1) == -1) {
834 		return -1;
835 	}
836 
837 	if ((n = sys_recvmsgfd(clisock, ans, sizeof(ans), &fd)) == -1) {
838 		return -1;
839 	}
840 
841 	if (n < 1) {
842 		errno = EINVAL;
843 		return -1;
844 	}
845 
846 	switch (ans[0]) {
847 	case PRIVSEP_ANS_SUCCESS:
848 		break;
849 	case PRIVSEP_ANS_DENIED:
850 		errno = EACCES;
851 		return -1;
852 	case PRIVSEP_ANS_SYS_ERR:
853 		if (n < (ssize_t)(1 + sizeof(int))) {
854 			errno = EINVAL;
855 			return -1;
856 		}
857 		errno = *((int*)&ans[1]);
858 		return -1;
859 	case PRIVSEP_ANS_UNK_CMD:
860 	case PRIVSEP_ANS_INVALID:
861 	default:
862 		errno = EINVAL;
863 		return -1;
864 	}
865 
866 	return fd;
867 }
868 
869 int
privsep_client_certfile(int clisock,const char * fn)870 privsep_client_certfile(int clisock, const char *fn)
871 {
872 	char ans[PRIVSEP_MAX_ANS_SIZE];
873 	char req[1 + strlen(fn)];
874 	int fd = -1;
875 	ssize_t n;
876 
877 	if (privsep_fastpath)
878 		return privsep_server_certfile(fn);
879 
880 	req[0] = PRIVSEP_REQ_CERTFILE;
881 	memcpy(req + 1, fn, sizeof(req) - 1);
882 
883 	if (sys_sendmsgfd(clisock, req, sizeof(req), -1) == -1) {
884 		return -1;
885 	}
886 
887 	if ((n = sys_recvmsgfd(clisock, ans, sizeof(ans), &fd)) == -1) {
888 		return -1;
889 	}
890 
891 	if (n < 1) {
892 		errno = EINVAL;
893 		return -1;
894 	}
895 
896 	switch (ans[0]) {
897 	case PRIVSEP_ANS_SUCCESS:
898 		break;
899 	case PRIVSEP_ANS_DENIED:
900 		errno = EACCES;
901 		return -1;
902 	case PRIVSEP_ANS_SYS_ERR:
903 		if (n < (ssize_t)(1 + sizeof(int))) {
904 			errno = EINVAL;
905 			return -1;
906 		}
907 		errno = *((int*)&ans[1]);
908 		return -1;
909 	case PRIVSEP_ANS_UNK_CMD:
910 	case PRIVSEP_ANS_INVALID:
911 	default:
912 		errno = EINVAL;
913 		return -1;
914 	}
915 
916 	return fd;
917 }
918 
919 int
privsep_client_close(int clisock)920 privsep_client_close(int clisock)
921 {
922 	char req[1];
923 
924 	req[0] = PRIVSEP_REQ_CLOSE;
925 
926 	if (sys_sendmsgfd(clisock, req, sizeof(req), -1) == -1) {
927 		close(clisock);
928 		return -1;
929 	}
930 
931 	close(clisock);
932 	return 0;
933 }
934 
935 #ifndef WITHOUT_USERAUTH
936 int
privsep_client_update_atime(int clisock,const userdbkeys_t * keys)937 privsep_client_update_atime(int clisock, const userdbkeys_t *keys)
938 {
939 	char ans[PRIVSEP_MAX_ANS_SIZE];
940 	char req[1 + sizeof(userdbkeys_t)];
941 	ssize_t n;
942 
943 	req[0] = PRIVSEP_REQ_UPDATE_ATIME;
944 	// @attention Do not typecast, but memcpy
945 	//*((const userdbkeys_t **)&req[1]) = keys;
946 	memcpy(req + 1, keys, sizeof(req) - 1);
947 
948 	if (sys_sendmsgfd(clisock, req, sizeof(req), -1) == -1) {
949 		return -1;
950 	}
951 
952 	// @attention Pass NULL as the 4th param, otherwise other privsep calls cannot get the fds they request
953 	if ((n = sys_recvmsgfd(clisock, ans, sizeof(ans), NULL)) == -1) {
954 		return -1;
955 	}
956 
957 	if (n < 1) {
958 		errno = EINVAL;
959 		return -1;
960 	}
961 
962 	switch (ans[0]) {
963 	case PRIVSEP_ANS_SUCCESS:
964 		break;
965 	case PRIVSEP_ANS_DENIED:
966 		errno = EACCES;
967 		return -1;
968 	case PRIVSEP_ANS_SYS_ERR:
969 		if (n < (ssize_t)(1 + sizeof(int))) {
970 			errno = EINVAL;
971 			return -1;
972 		}
973 		errno = *((int*)&ans[1]);
974 		return -1;
975 	case PRIVSEP_ANS_UNK_CMD:
976 	case PRIVSEP_ANS_INVALID:
977 	default:
978 		errno = EINVAL;
979 		return -1;
980 	}
981 	// Does not return an fd
982 	return 0;
983 }
984 #endif /* !WITHOUT_USERAUTH */
985 
986 /*
987  * Fork and set up privilege separated monitor process.
988  * Returns -1 on error before forking, 1 as parent, or 0 as child.
989  * The array of clisock's will get filled with nclisock privsep client
990  * sockets only for the child; on error and in the parent process it
991  * will not be touched.
992  */
993 int
privsep_fork(global_t * global,int clisock[],size_t nclisock,int * parent_rv)994 privsep_fork(global_t *global, int clisock[], size_t nclisock, int *parent_rv)
995 {
996 	int selfpipev[2]; /* self-pipe trick: signal handler -> select */
997 	int chldpipev[2]; /* el cheapo interprocess sync early after fork */
998 	int sockcliv[nclisock][2];
999 	pid_t pid;
1000 
1001 	if (!global->dropuser) {
1002 		log_dbg_printf("Privsep fastpath enabled\n");
1003 		privsep_fastpath = 1;
1004 	} else {
1005 		log_dbg_printf("Privsep fastpath disabled\n");
1006 		privsep_fastpath = 0;
1007 	}
1008 
1009 	received_sigquit = 0;
1010 	received_sighup = 0;
1011 	received_sigint = 0;
1012 	received_sigchld = 0;
1013 	received_sigusr1 = 0;
1014 
1015 	if (pipe(selfpipev) == -1) {
1016 		log_err_level_printf(LOG_CRIT, "Failed to create self-pipe: %s (%i)\n",
1017 		               strerror(errno), errno);
1018 		return -1;
1019 	}
1020 	log_dbg_printf("Created self-pipe [r=%i,w=%i]\n",
1021 	               selfpipev[0], selfpipev[1]);
1022 
1023 	if (pipe(chldpipev) == -1) {
1024 		log_err_level_printf(LOG_CRIT, "Failed to create chld-pipe: %s (%i)\n",
1025 		               strerror(errno), errno);
1026 		return -1;
1027 	}
1028 	log_dbg_printf("Created chld-pipe [r=%i,w=%i]\n",
1029 	               chldpipev[0], chldpipev[1]);
1030 
1031 	for (size_t i = 0; i < nclisock; i++) {
1032 		if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sockcliv[i]) == -1) {
1033 			log_err_level_printf(LOG_CRIT, "Failed to create socket pair %zu: "
1034 			               "%s (%i)\n", i, strerror(errno), errno);
1035 			return -1;
1036 		}
1037 		log_dbg_printf("Created socketpair %zu [p=%i,c=%i]\n",
1038 		               i, sockcliv[i][0], sockcliv[i][1]);
1039 	}
1040 
1041 	log_dbg_printf("Privsep parent pid %i\n", getpid());
1042 	pid = fork();
1043 	if (pid == -1) {
1044 		log_err_level_printf(LOG_CRIT, "Failed to fork: %s (%i)\n",
1045 		               strerror(errno), errno);
1046 		close(selfpipev[0]);
1047 		close(selfpipev[1]);
1048 		close(chldpipev[0]);
1049 		close(chldpipev[1]);
1050 		for (size_t i = 0; i < nclisock; i++) {
1051 			close(sockcliv[i][0]);
1052 			close(sockcliv[i][1]);
1053 		}
1054 		return -1;
1055 	} else if (pid == 0) {
1056 		/* child */
1057 		close(selfpipev[0]);
1058 		close(selfpipev[1]);
1059 		for (size_t i = 0; i < nclisock; i++)
1060 			close(sockcliv[i][0]);
1061 		/* wait until parent has installed signal handlers,
1062 		 * intentionally ignoring errors */
1063 		char buf[1];
1064 		ssize_t n;
1065 		close(chldpipev[1]);
1066 		do {
1067 			n = read(chldpipev[0], buf, sizeof(buf));
1068 		} while (n == -1 && errno == EINTR);
1069 		close(chldpipev[0]);
1070 		log_dbg_printf("Privsep child pid %i\n", getpid());
1071 		/* return the privsep client sockets */
1072 		for (size_t i = 0; i < nclisock; i++)
1073 			clisock[i] = sockcliv[i][1];
1074 		return 0;
1075 	}
1076 	/* parent */
1077 	for (size_t i = 0; i < nclisock; i++)
1078 		close(sockcliv[i][1]);
1079 	selfpipe_wrfd = selfpipev[1];
1080 
1081 	/* close file descriptors opened by preinit's only needed in client;
1082 	 * we still call the preinit's before forking in order to provide
1083 	 * better user feedback and less privsep complexity */
1084 	nat_preinit_undo();
1085 	log_preinit_undo();
1086 
1087 	/* If the child exits before the parent installs the signal handler
1088 	 * here, we have a race condition; this is solved by the client
1089 	 * blocking on the reading end of a pipe (chldpipev[0]). */
1090 	if (signal(SIGHUP, privsep_server_signal_handler) == SIG_ERR) {
1091 		log_err_level_printf(LOG_CRIT, "Failed to install SIGHUP handler: %s (%i)\n",
1092 		               strerror(errno), errno);
1093 		return -1;
1094 	}
1095 	if (signal(SIGINT, privsep_server_signal_handler) == SIG_ERR) {
1096 		log_err_level_printf(LOG_CRIT, "Failed to install SIGINT handler: %s (%i)\n",
1097 		               strerror(errno), errno);
1098 		return -1;
1099 	}
1100 	if (signal(SIGTERM, privsep_server_signal_handler) == SIG_ERR) {
1101 		log_err_level_printf(LOG_CRIT, "Failed to install SIGTERM handler: %s (%i)\n",
1102 		               strerror(errno), errno);
1103 		return -1;
1104 	}
1105 	if (signal(SIGQUIT, privsep_server_signal_handler) == SIG_ERR) {
1106 		log_err_level_printf(LOG_CRIT, "Failed to install SIGQUIT handler: %s (%i)\n",
1107 		               strerror(errno), errno);
1108 		return -1;
1109 	}
1110 	if (signal(SIGUSR1, privsep_server_signal_handler) == SIG_ERR) {
1111 		log_err_level_printf(LOG_CRIT, "Failed to install SIGUSR1 handler: %s (%i)\n",
1112 		               strerror(errno), errno);
1113 		return -1;
1114 	}
1115 	if (signal(SIGCHLD, privsep_server_signal_handler) == SIG_ERR) {
1116 		log_err_level_printf(LOG_CRIT, "Failed to install SIGCHLD handler: %s (%i)\n",
1117 		               strerror(errno), errno);
1118 		return -1;
1119 	}
1120 
1121 	/* unblock the child */
1122 	close(chldpipev[0]);
1123 	close(chldpipev[1]);
1124 
1125 	int socksrv[nclisock];
1126 	for (size_t i = 0; i < nclisock; i++)
1127 		socksrv[i] = sockcliv[i][0];
1128 	if (privsep_server(global, selfpipev[0], socksrv, nclisock, pid) == -1) {
1129 		log_err_level_printf(LOG_CRIT, "Privsep server failed: %s (%i)\n",
1130 		               strerror(errno), errno);
1131 		/* fall through */
1132 	}
1133 #ifdef DEBUG_PRIVSEP_SERVER
1134 	log_dbg_printf("privsep_server exited\n");
1135 #endif /* DEBUG_PRIVSEP_SERVER */
1136 
1137 	for (size_t i = 0; i < nclisock; i++)
1138 		close(sockcliv[i][0]);
1139 	selfpipe_wrfd = -1; /* tell signal handler not to write anymore */
1140 	close(selfpipev[0]);
1141 	close(selfpipev[1]);
1142 
1143 	int status;
1144 	pid_t wpid;
1145 	wpid = wait(&status);
1146 	if (wpid != pid) {
1147 		/* should never happen, warn if it does anyway */
1148 		log_err_printf("Child pid %lld != expected %lld from wait(2)\n",
1149 		               (long long)wpid, (long long)pid);
1150 	}
1151 	if (WIFEXITED(status)) {
1152 		if (WEXITSTATUS(status) != 0) {
1153 			log_err_level_printf(LOG_CRIT, "Child pid %lld exited with status %d\n",
1154 			               (long long)wpid, WEXITSTATUS(status));
1155 		} else {
1156 			log_dbg_printf("Child pid %lld exited with status %d\n",
1157 			               (long long)wpid, WEXITSTATUS(status));
1158 		}
1159 		*parent_rv = WEXITSTATUS(status);
1160 	} else if (WIFSIGNALED(status)) {
1161 		log_err_level_printf(LOG_CRIT, "Child pid %lld killed by signal %d\n",
1162 		               (long long)wpid, WTERMSIG(status));
1163 		*parent_rv = 128 + WTERMSIG(status);
1164 	} else {
1165 		/* can only happen with WUNTRACED option or active tracing */
1166 		log_err_level_printf(LOG_CRIT, "Child pid %lld neither exited nor killed\n",
1167 		               (long long)wpid);
1168 	}
1169 
1170 	return 1;
1171 }
1172 
1173 /* vim: set noet ft=c: */
1174 
1175 
1176 
1177