1 /*
2  * SPDX-License-Identifier: ISC
3  *
4  * Copyright (c) 2019-2021 Todd C. Miller <Todd.Miller@sudo.ws>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include "config.h"
20 
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <netinet/in.h>
25 
26 #include <errno.h>
27 #include <ctype.h>
28 #include <fcntl.h>
29 #include <limits.h>
30 #include <netdb.h>
31 #ifdef HAVE_STDBOOL_H
32 # include <stdbool.h>
33 #else
34 # include "compat/stdbool.h"
35 #endif
36 #include <stddef.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <syslog.h>
41 #include <time.h>
42 #include <unistd.h>
43 #include <grp.h>
44 #include <pwd.h>
45 #ifndef HAVE_GETADDRINFO
46 # include "compat/getaddrinfo.h"
47 #endif
48 
49 #include "pathnames.h"
50 #include "sudo_compat.h"
51 #include "sudo_debug.h"
52 #include "sudo_eventlog.h"
53 #include "sudo_fatal.h"
54 #include "sudo_gettext.h"
55 #include "sudo_iolog.h"
56 #include "sudo_util.h"
57 
58 #include "log_server.pb-c.h"
59 #include "logsrvd.h"
60 
61 #if defined(HAVE_OPENSSL)
62 # define DEFAULT_CA_CERT_PATH       "/etc/ssl/sudo/cacert.pem"
63 # define DEFAULT_SERVER_CERT_PATH   "/etc/ssl/sudo/certs/logsrvd_cert.pem"
64 # define DEFAULT_SERVER_KEY_PATH    "/etc/ssl/sudo/private/logsrvd_key.pem"
65 
66 /* Evaluates to true if at least one TLS field is set, else false. */
67 # define TLS_CONFIGURED(_s)						\
68     ((_s).tls_key_path != NULL || (_s).tls_cert_path != NULL ||		\
69      (_s).tls_cacert_path != NULL || (_s).tls_dhparams_path != NULL ||	\
70      (_s).tls_ciphers_v12 != NULL || (_s).tls_ciphers_v13 != NULL ||	\
71      (_s).tls_verify != -1)
72 
73 /* Evaluates to the relay-specific TLS setting, falling back to server. */
74 # define TLS_RELAY_STR(_c, _f)	\
75     ((_c)->relay._f != NULL ? (_c)->relay._f : (_c)->server._f)
76 
77 # define TLS_RELAY_INT(_c, _f)	\
78     ((_c)->relay._f != -1 ? (_c)->relay._f : (_c)->server._f)
79 #endif
80 
81 enum server_log_type {
82     SERVER_LOG_NONE,
83     SERVER_LOG_STDERR,
84     SERVER_LOG_SYSLOG,
85     SERVER_LOG_FILE
86 };
87 
88 struct logsrvd_config;
89 typedef bool (*logsrvd_conf_cb_t)(struct logsrvd_config *, const char *, size_t);
90 
91 struct logsrvd_config_entry {
92     char *conf_str;
93     logsrvd_conf_cb_t setter;
94     size_t offset;
95 };
96 
97 struct logsrvd_config_section {
98     char *name;
99     struct logsrvd_config_entry *entries;
100 };
101 
102 struct address_list_container {
103     unsigned int refcnt;
104     struct server_address_list addrs;
105 };
106 
107 static struct logsrvd_config {
108     struct logsrvd_config_server {
109         struct address_list_container addresses;
110         struct timespec timeout;
111         bool tcp_keepalive;
112 	enum server_log_type log_type;
113 	FILE *log_stream;
114 	char *log_file;
115 	char *pid_file;
116 #if defined(HAVE_OPENSSL)
117 	char *tls_key_path;
118 	char *tls_cert_path;
119 	char *tls_cacert_path;
120 	char *tls_dhparams_path;
121 	char *tls_ciphers_v12;
122 	char *tls_ciphers_v13;
123 	int tls_check_peer;
124 	int tls_verify;
125 	SSL_CTX *ssl_ctx;
126 #endif
127     } server;
128     struct logsrvd_config_relay {
129         struct address_list_container relays;
130         struct timespec connect_timeout;
131         struct timespec timeout;
132 	time_t retry_interval;
133 	char *relay_dir;
134         bool tcp_keepalive;
135 	bool store_first;
136 #if defined(HAVE_OPENSSL)
137 	char *tls_key_path;
138 	char *tls_cert_path;
139 	char *tls_cacert_path;
140 	char *tls_dhparams_path;
141 	char *tls_ciphers_v12;
142 	char *tls_ciphers_v13;
143 	int tls_check_peer;
144 	int tls_verify;
145 	SSL_CTX *ssl_ctx;
146 #endif
147     } relay;
148     struct logsrvd_config_iolog {
149 	bool compress;
150 	bool flush;
151 	bool gid_set;
152 	uid_t uid;
153 	gid_t gid;
154 	mode_t mode;
155 	unsigned int maxseq;
156 	char *iolog_dir;
157 	char *iolog_file;
158     } iolog;
159     struct logsrvd_config_eventlog {
160 	int log_type;
161         bool log_exit;
162 	enum eventlog_format log_format;
163     } eventlog;
164     struct logsrvd_config_syslog {
165 	unsigned int maxlen;
166 	int server_facility;
167 	int facility;
168 	int acceptpri;
169 	int rejectpri;
170 	int alertpri;
171     } syslog;
172     struct logsrvd_config_logfile {
173 	char *path;
174 	char *time_format;
175 	FILE *stream;
176     } logfile;
177 } *logsrvd_config;
178 
179 static bool logsrvd_warn_enable_stderr = true;
180 
181 /* eventlog getters */
182 bool
logsrvd_conf_log_exit(void)183 logsrvd_conf_log_exit(void)
184 {
185     return logsrvd_config->eventlog.log_exit;
186 }
187 
188 /* iolog getters */
189 uid_t
logsrvd_conf_iolog_uid(void)190 logsrvd_conf_iolog_uid(void)
191 {
192     return logsrvd_config->iolog.uid;
193 }
194 
195 gid_t
logsrvd_conf_iolog_gid(void)196 logsrvd_conf_iolog_gid(void)
197 {
198     return logsrvd_config->iolog.gid;
199 }
200 
201 mode_t
logsrvd_conf_iolog_mode(void)202 logsrvd_conf_iolog_mode(void)
203 {
204     return logsrvd_config->iolog.mode;
205 }
206 
207 const char *
logsrvd_conf_iolog_dir(void)208 logsrvd_conf_iolog_dir(void)
209 {
210     return logsrvd_config->iolog.iolog_dir;
211 }
212 
213 const char *
logsrvd_conf_iolog_file(void)214 logsrvd_conf_iolog_file(void)
215 {
216     return logsrvd_config->iolog.iolog_file;
217 }
218 
219 /* server getters */
220 struct server_address_list *
logsrvd_conf_server_listen_address(void)221 logsrvd_conf_server_listen_address(void)
222 {
223     return &logsrvd_config->server.addresses.addrs;
224 }
225 
226 bool
logsrvd_conf_server_tcp_keepalive(void)227 logsrvd_conf_server_tcp_keepalive(void)
228 {
229     return logsrvd_config->server.tcp_keepalive;
230 }
231 
232 const char *
logsrvd_conf_pid_file(void)233 logsrvd_conf_pid_file(void)
234 {
235     return logsrvd_config->server.pid_file;
236 }
237 
238 struct timespec *
logsrvd_conf_server_timeout(void)239 logsrvd_conf_server_timeout(void)
240 {
241     if (sudo_timespecisset(&logsrvd_config->server.timeout)) {
242         return &logsrvd_config->server.timeout;
243     }
244 
245     return NULL;
246 }
247 
248 #if defined(HAVE_OPENSSL)
249 SSL_CTX *
logsrvd_server_tls_ctx(void)250 logsrvd_server_tls_ctx(void)
251 {
252     return logsrvd_config->server.ssl_ctx;
253 }
254 
255 bool
logsrvd_conf_server_tls_check_peer(void)256 logsrvd_conf_server_tls_check_peer(void)
257 {
258     return logsrvd_config->server.tls_check_peer;
259 }
260 #endif
261 
262 /* relay getters */
263 struct server_address_list *
logsrvd_conf_relay_address(void)264 logsrvd_conf_relay_address(void)
265 {
266     return &logsrvd_config->relay.relays.addrs;
267 }
268 
269 const char *
logsrvd_conf_relay_dir(void)270 logsrvd_conf_relay_dir(void)
271 {
272     return logsrvd_config->relay.relay_dir;
273 }
274 
275 bool
logsrvd_conf_relay_store_first(void)276 logsrvd_conf_relay_store_first(void)
277 {
278     return logsrvd_config->relay.store_first;
279 }
280 
281 bool
logsrvd_conf_relay_tcp_keepalive(void)282 logsrvd_conf_relay_tcp_keepalive(void)
283 {
284     return logsrvd_config->relay.tcp_keepalive;
285 }
286 
287 struct timespec *
logsrvd_conf_relay_timeout(void)288 logsrvd_conf_relay_timeout(void)
289 {
290     if (sudo_timespecisset(&logsrvd_config->relay.timeout)) {
291         return &logsrvd_config->relay.timeout;
292     }
293 
294     return NULL;
295 }
296 
297 struct timespec *
logsrvd_conf_relay_connect_timeout(void)298 logsrvd_conf_relay_connect_timeout(void)
299 {
300     if (sudo_timespecisset(&logsrvd_config->relay.connect_timeout)) {
301         return &logsrvd_config->relay.connect_timeout;
302     }
303 
304     return NULL;
305 }
306 
307 time_t
logsrvd_conf_relay_retry_interval(void)308 logsrvd_conf_relay_retry_interval(void)
309 {
310     return logsrvd_config->relay.retry_interval;
311 }
312 
313 #if defined(HAVE_OPENSSL)
314 SSL_CTX *
logsrvd_relay_tls_ctx(void)315 logsrvd_relay_tls_ctx(void)
316 {
317     if (logsrvd_config->relay.ssl_ctx != NULL)
318 	return logsrvd_config->relay.ssl_ctx;
319     return logsrvd_config->server.ssl_ctx;
320 }
321 
322 bool
logsrvd_conf_relay_tls_check_peer(void)323 logsrvd_conf_relay_tls_check_peer(void)
324 {
325     if (logsrvd_config->relay.tls_check_peer != -1)
326 	return logsrvd_config->relay.tls_check_peer;
327     return logsrvd_config->server.tls_check_peer;
328 }
329 #endif
330 
331 /* I/O log callbacks */
332 static bool
cb_iolog_dir(struct logsrvd_config * config,const char * path,size_t offset)333 cb_iolog_dir(struct logsrvd_config *config, const char *path, size_t offset)
334 {
335     debug_decl(cb_iolog_dir, SUDO_DEBUG_UTIL);
336 
337     free(config->iolog.iolog_dir);
338     if ((config->iolog.iolog_dir = strdup(path)) == NULL) {
339 	sudo_warn(NULL);
340 	debug_return_bool(false);
341     }
342     debug_return_bool(true);
343 }
344 
345 static bool
cb_iolog_file(struct logsrvd_config * config,const char * path,size_t offset)346 cb_iolog_file(struct logsrvd_config *config, const char *path, size_t offset)
347 {
348     debug_decl(cb_iolog_file, SUDO_DEBUG_UTIL);
349 
350     free(config->iolog.iolog_file);
351     if ((config->iolog.iolog_file = strdup(path)) == NULL) {
352 	sudo_warn(NULL);
353 	debug_return_bool(false);
354     }
355     debug_return_bool(true);
356 }
357 
358 static bool
cb_iolog_compress(struct logsrvd_config * config,const char * str,size_t offset)359 cb_iolog_compress(struct logsrvd_config *config, const char *str, size_t offset)
360 {
361     int val;
362     debug_decl(cb_iolog_compress, SUDO_DEBUG_UTIL);
363 
364     if ((val = sudo_strtobool(str)) == -1)
365 	debug_return_bool(false);
366 
367     config->iolog.compress = val;
368     debug_return_bool(true);
369 }
370 
371 static bool
cb_iolog_flush(struct logsrvd_config * config,const char * str,size_t offset)372 cb_iolog_flush(struct logsrvd_config *config, const char *str, size_t offset)
373 {
374     int val;
375     debug_decl(cb_iolog_flush, SUDO_DEBUG_UTIL);
376 
377     if ((val = sudo_strtobool(str)) == -1)
378 	debug_return_bool(false);
379 
380     config->iolog.flush = val;
381     debug_return_bool(true);
382 }
383 
384 static bool
cb_iolog_user(struct logsrvd_config * config,const char * user,size_t offset)385 cb_iolog_user(struct logsrvd_config *config, const char *user, size_t offset)
386 {
387     struct passwd *pw;
388     debug_decl(cb_iolog_user, SUDO_DEBUG_UTIL);
389 
390     if ((pw = getpwnam(user)) == NULL) {
391 	sudo_warnx(U_("unknown user %s"), user);
392 	debug_return_bool(false);
393     }
394     config->iolog.uid = pw->pw_uid;
395     if (!config->iolog.gid_set)
396 	config->iolog.gid = pw->pw_gid;
397 
398     debug_return_bool(true);
399 }
400 
401 static bool
cb_iolog_group(struct logsrvd_config * config,const char * group,size_t offset)402 cb_iolog_group(struct logsrvd_config *config, const char *group, size_t offset)
403 {
404     struct group *gr;
405     debug_decl(cb_iolog_group, SUDO_DEBUG_UTIL);
406 
407     if ((gr = getgrnam(group)) == NULL) {
408 	sudo_warnx(U_("unknown group %s"), group);
409 	debug_return_bool(false);
410     }
411     config->iolog.gid = gr->gr_gid;
412     config->iolog.gid_set = true;
413 
414     debug_return_bool(true);
415 }
416 
417 static bool
cb_iolog_mode(struct logsrvd_config * config,const char * str,size_t offset)418 cb_iolog_mode(struct logsrvd_config *config, const char *str, size_t offset)
419 {
420     const char *errstr;
421     mode_t mode;
422     debug_decl(cb_iolog_mode, SUDO_DEBUG_UTIL);
423 
424     mode = sudo_strtomode(str, &errstr);
425     if (errstr != NULL) {
426 	sudo_warnx(U_("unable to parse iolog mode %s"), str);
427 	debug_return_bool(false);
428     }
429     config->iolog.mode = mode;
430     debug_return_bool(true);
431 }
432 
433 static bool
cb_iolog_maxseq(struct logsrvd_config * config,const char * str,size_t offset)434 cb_iolog_maxseq(struct logsrvd_config *config, const char *str, size_t offset)
435 {
436     const char *errstr;
437     unsigned int value;
438     debug_decl(cb_iolog_maxseq, SUDO_DEBUG_UTIL);
439 
440     value = sudo_strtonum(str, 0, SESSID_MAX, &errstr);
441     if (errstr != NULL) {
442         if (errno != ERANGE) {
443 	    sudo_warnx(U_("invalid value for %s: %s"), "maxseq", errstr);
444             debug_return_bool(false);
445         }
446         /* Out of range, clamp to SESSID_MAX as documented. */
447         value = SESSID_MAX;
448     }
449     config->iolog.maxseq = value;
450     debug_return_bool(true);
451 }
452 
453 /* Server callbacks */
454 static bool
append_address(struct server_address_list * addresses,const char * str,bool allow_wildcard)455 append_address(struct server_address_list *addresses, const char *str,
456     bool allow_wildcard)
457 {
458     struct addrinfo hints, *res, *res0 = NULL;
459     char *sa_str = NULL, *sa_host = NULL;
460     char *copy, *host, *port;
461     bool tls, ret = false;
462     int error;
463     debug_decl(append_address, SUDO_DEBUG_UTIL);
464 
465     if ((copy = strdup(str)) == NULL) {
466 	sudo_warn(NULL);
467 	debug_return_bool(false);
468     }
469 
470     /* Parse host[:port] */
471     if (!iolog_parse_host_port(copy, &host, &port, &tls, DEFAULT_PORT,
472 	    DEFAULT_PORT_TLS))
473 	goto done;
474     if (host[0] == '*' && host[1] == '\0') {
475 	if (!allow_wildcard)
476 	    goto done;
477 	host = NULL;
478     }
479 
480 #if !defined(HAVE_OPENSSL)
481     if (tls) {
482 	sudo_warnx("%s", U_("TLS not supported"));
483 	goto done;
484     }
485 #endif
486 
487     /* Only make a single copy of the string + host for all addresses. */
488     if ((sa_str = sudo_rcstr_dup(str)) == NULL)	{
489 	sudo_warn(NULL);
490 	goto done;
491     }
492     if (host != NULL && (sa_host = sudo_rcstr_dup(host)) == NULL) {
493 	sudo_warn(NULL);
494 	goto done;
495     }
496 
497     /* Resolve host (and port if it is a service). */
498     memset(&hints, 0, sizeof(hints));
499     hints.ai_family = AF_UNSPEC;
500     hints.ai_socktype = SOCK_STREAM;
501     hints.ai_flags = AI_PASSIVE;
502     error = getaddrinfo(host, port, &hints, &res0);
503     if (error != 0) {
504 	sudo_gai_warn(error, U_("%s:%s"), host ? host : "*", port);
505 	goto done;
506     }
507     for (res = res0; res != NULL; res = res->ai_next) {
508 	struct server_address *addr;
509 
510 	if ((addr = malloc(sizeof(*addr))) == NULL) {
511 	    sudo_warn(NULL);
512 	    goto done;
513 	}
514 	addr->sa_str = sudo_rcstr_addref(sa_str);
515 	addr->sa_host = sudo_rcstr_addref(sa_host);
516 
517 	memcpy(&addr->sa_un, res->ai_addr, res->ai_addrlen);
518 	addr->sa_size = res->ai_addrlen;
519 	addr->tls = tls;
520 	TAILQ_INSERT_TAIL(addresses, addr, entries);
521     }
522 
523     ret = true;
524 done:
525     sudo_rcstr_delref(sa_str);
526     sudo_rcstr_delref(sa_host);
527     if (res0 != NULL)
528 	freeaddrinfo(res0);
529     free(copy);
530     debug_return_bool(ret);
531 }
532 
533 static bool
cb_server_listen_address(struct logsrvd_config * config,const char * str,size_t offset)534 cb_server_listen_address(struct logsrvd_config *config, const char *str, size_t offset)
535 {
536     return append_address(&config->server.addresses.addrs, str, true);
537 }
538 
539 static bool
cb_server_timeout(struct logsrvd_config * config,const char * str,size_t offset)540 cb_server_timeout(struct logsrvd_config *config, const char *str, size_t offset)
541 {
542     int timeout;
543     const char* errstr;
544     debug_decl(cb_server_timeout, SUDO_DEBUG_UTIL);
545 
546     timeout = sudo_strtonum(str, 0, UINT_MAX, &errstr);
547     if (errstr != NULL)
548 	debug_return_bool(false);
549 
550     config->server.timeout.tv_sec = timeout;
551 
552     debug_return_bool(true);
553 }
554 
555 static bool
cb_server_keepalive(struct logsrvd_config * config,const char * str,size_t offset)556 cb_server_keepalive(struct logsrvd_config *config, const char *str, size_t offset)
557 {
558     int val;
559     debug_decl(cb_server_keepalive, SUDO_DEBUG_UTIL);
560 
561     if ((val = sudo_strtobool(str)) == -1)
562 	debug_return_bool(false);
563 
564     config->server.tcp_keepalive = val;
565     debug_return_bool(true);
566 }
567 
568 static bool
cb_server_pid_file(struct logsrvd_config * config,const char * str,size_t offset)569 cb_server_pid_file(struct logsrvd_config *config, const char *str, size_t offset)
570 {
571     char *copy = NULL;
572     debug_decl(cb_server_pid_file, SUDO_DEBUG_UTIL);
573 
574     /* An empty value means to disable the pid file. */
575     if (*str != '\0') {
576 	if (*str != '/') {
577 	    sudo_warnx(U_("%s: not a fully qualified path"), str);
578 	    debug_return_bool(false);
579 	}
580 	if ((copy = strdup(str)) == NULL) {
581 	    sudo_warn(NULL);
582 	    debug_return_bool(false);
583 	}
584     }
585 
586     free(config->server.pid_file);
587     config->server.pid_file = copy;
588 
589     debug_return_bool(true);
590 }
591 
592 static bool
cb_server_log(struct logsrvd_config * config,const char * str,size_t offset)593 cb_server_log(struct logsrvd_config *config, const char *str, size_t offset)
594 {
595     char *copy = NULL;
596     enum server_log_type log_type = SERVER_LOG_NONE;
597     debug_decl(cb_server_log, SUDO_DEBUG_UTIL);
598 
599     /* An empty value means to disable the server log. */
600     if (*str != '\0') {
601 	if (*str != '/') {
602 	    log_type = SERVER_LOG_FILE;
603 	    if ((copy = strdup(str)) == NULL) {
604 		sudo_warn(NULL);
605 		debug_return_bool(false);
606 	    }
607 	} else if (strcmp(str, "stderr") == 0) {
608 	    log_type = SERVER_LOG_STDERR;
609 	} else if (strcmp(str, "syslog") == 0) {
610 	    log_type = SERVER_LOG_SYSLOG;
611 	} else {
612 	    debug_return_bool(false);
613 	}
614     }
615 
616     free(config->server.log_file);
617     config->server.log_file = copy;
618     config->server.log_type = log_type;
619 
620     debug_return_bool(true);
621 }
622 
623 #if defined(HAVE_OPENSSL)
624 static bool
cb_tls_key(struct logsrvd_config * config,const char * path,size_t offset)625 cb_tls_key(struct logsrvd_config *config, const char *path, size_t offset)
626 {
627     char **p = (char **)((char *)config + offset);
628     debug_decl(cb_tls_key, SUDO_DEBUG_UTIL);
629 
630     free(*p);
631     if ((*p = strdup(path)) == NULL) {
632         sudo_warn(NULL);
633         debug_return_bool(false);
634     }
635     debug_return_bool(true);
636 }
637 
638 static bool
cb_tls_cacert(struct logsrvd_config * config,const char * path,size_t offset)639 cb_tls_cacert(struct logsrvd_config *config, const char *path, size_t offset)
640 {
641     char **p = (char **)((char *)config + offset);
642     debug_decl(cb_tls_cacert, SUDO_DEBUG_UTIL);
643 
644     free(*p);
645     if ((*p = strdup(path)) == NULL) {
646         sudo_warn(NULL);
647         debug_return_bool(false);
648     }
649     debug_return_bool(true);
650 }
651 
652 static bool
cb_tls_cert(struct logsrvd_config * config,const char * path,size_t offset)653 cb_tls_cert(struct logsrvd_config *config, const char *path, size_t offset)
654 {
655     char **p = (char **)((char *)config + offset);
656     debug_decl(cb_tls_cert, SUDO_DEBUG_UTIL);
657 
658     free(*p);
659     if ((*p = strdup(path)) == NULL) {
660         sudo_warn(NULL);
661         debug_return_bool(false);
662     }
663     debug_return_bool(true);
664 }
665 
666 static bool
cb_tls_dhparams(struct logsrvd_config * config,const char * path,size_t offset)667 cb_tls_dhparams(struct logsrvd_config *config, const char *path, size_t offset)
668 {
669     char **p = (char **)((char *)config + offset);
670     debug_decl(cb_tls_dhparams, SUDO_DEBUG_UTIL);
671 
672     free(*p);
673     if ((*p = strdup(path)) == NULL) {
674         sudo_warn(NULL);
675         debug_return_bool(false);
676     }
677     debug_return_bool(true);
678 }
679 
680 static bool
cb_tls_ciphers12(struct logsrvd_config * config,const char * str,size_t offset)681 cb_tls_ciphers12(struct logsrvd_config *config, const char *str, size_t offset)
682 {
683     char **p = (char **)((char *)config + offset);
684     debug_decl(cb_tls_ciphers12, SUDO_DEBUG_UTIL);
685 
686     free(*p);
687     if ((*p = strdup(str)) == NULL) {
688         sudo_warn(NULL);
689         debug_return_bool(false);
690     }
691     debug_return_bool(true);
692 }
693 
694 static bool
cb_tls_ciphers13(struct logsrvd_config * config,const char * str,size_t offset)695 cb_tls_ciphers13(struct logsrvd_config *config, const char *str, size_t offset)
696 {
697     char **p = (char **)((char *)config + offset);
698     debug_decl(cb_tls_ciphers13, SUDO_DEBUG_UTIL);
699 
700     free(*p);
701     if ((*p = strdup(str)) == NULL) {
702         sudo_warn(NULL);
703         debug_return_bool(false);
704     }
705     debug_return_bool(true);
706 }
707 
708 static bool
cb_tls_verify(struct logsrvd_config * config,const char * str,size_t offset)709 cb_tls_verify(struct logsrvd_config *config, const char *str, size_t offset)
710 {
711     int *p = (int *)((char *)config + offset);
712     int val;
713     debug_decl(cb_tls_verify, SUDO_DEBUG_UTIL);
714 
715     if ((val = sudo_strtobool(str)) == -1)
716 	debug_return_bool(false);
717 
718     *p = val;
719     debug_return_bool(true);
720 }
721 
722 static bool
cb_tls_checkpeer(struct logsrvd_config * config,const char * str,size_t offset)723 cb_tls_checkpeer(struct logsrvd_config *config, const char *str, size_t offset)
724 {
725     int *p = (int *)((char *)config + offset);
726     int val;
727     debug_decl(cb_tls_checkpeer, SUDO_DEBUG_UTIL);
728 
729     if ((val = sudo_strtobool(str)) == -1)
730 	debug_return_bool(false);
731 
732     *p = val;
733     debug_return_bool(true);
734 }
735 #endif
736 
737 /* relay callbacks */
738 static bool
cb_relay_host(struct logsrvd_config * config,const char * str,size_t offset)739 cb_relay_host(struct logsrvd_config *config, const char *str, size_t offset)
740 {
741     return append_address(&config->relay.relays.addrs, str, false);
742 }
743 
744 static bool
cb_relay_timeout(struct logsrvd_config * config,const char * str,size_t offset)745 cb_relay_timeout(struct logsrvd_config *config, const char *str, size_t offset)
746 {
747     int timeout;
748     const char* errstr;
749     debug_decl(cb_relay_timeout, SUDO_DEBUG_UTIL);
750 
751     timeout = sudo_strtonum(str, 0, UINT_MAX, &errstr);
752     if (errstr != NULL)
753 	debug_return_bool(false);
754 
755     config->server.timeout.tv_sec = timeout;
756 
757     debug_return_bool(true);
758 }
759 
760 static bool
cb_relay_connect_timeout(struct logsrvd_config * config,const char * str,size_t offset)761 cb_relay_connect_timeout(struct logsrvd_config *config, const char *str, size_t offset)
762 {
763     int timeout;
764     const char* errstr;
765     debug_decl(cb_relay_connect_timeout, SUDO_DEBUG_UTIL);
766 
767     timeout = sudo_strtonum(str, 0, UINT_MAX, &errstr);
768     if (errstr != NULL)
769 	debug_return_bool(false);
770 
771     config->relay.connect_timeout.tv_sec = timeout;
772 
773     debug_return_bool(true);
774 }
775 
776 static bool
cb_relay_dir(struct logsrvd_config * config,const char * str,size_t offset)777 cb_relay_dir(struct logsrvd_config *config, const char *str, size_t offset)
778 {
779     char *copy = NULL;
780     debug_decl(cb_relay_dir, SUDO_DEBUG_UTIL);
781 
782     if ((copy = strdup(str)) == NULL) {
783 	sudo_warn(NULL);
784 	debug_return_bool(false);
785     }
786 
787     free(config->relay.relay_dir);
788     config->relay.relay_dir = copy;
789 
790     debug_return_bool(true);
791 }
792 
793 static bool
cb_relay_store_first(struct logsrvd_config * config,const char * str,size_t offset)794 cb_relay_store_first(struct logsrvd_config *config, const char *str, size_t offset)
795 {
796     int val;
797     debug_decl(cb_relay_store_first, SUDO_DEBUG_UTIL);
798 
799     if ((val = sudo_strtobool(str)) == -1)
800 	debug_return_bool(false);
801 
802     config->relay.store_first = val;
803     debug_return_bool(true);
804 }
805 
806 static bool
cb_relay_keepalive(struct logsrvd_config * config,const char * str,size_t offset)807 cb_relay_keepalive(struct logsrvd_config *config, const char *str, size_t offset)
808 {
809     int val;
810     debug_decl(cb_relay_keepalive, SUDO_DEBUG_UTIL);
811 
812     if ((val = sudo_strtobool(str)) == -1)
813 	debug_return_bool(false);
814 
815     config->relay.tcp_keepalive = val;
816     debug_return_bool(true);
817 }
818 
819 /* eventlog callbacks */
820 static bool
cb_eventlog_type(struct logsrvd_config * config,const char * str,size_t offset)821 cb_eventlog_type(struct logsrvd_config *config, const char *str, size_t offset)
822 {
823     debug_decl(cb_eventlog_type, SUDO_DEBUG_UTIL);
824 
825     if (strcmp(str, "none") == 0)
826 	config->eventlog.log_type = EVLOG_NONE;
827     else if (strcmp(str, "syslog") == 0)
828 	config->eventlog.log_type = EVLOG_SYSLOG;
829     else if (strcmp(str, "logfile") == 0)
830 	config->eventlog.log_type = EVLOG_FILE;
831     else
832 	debug_return_bool(false);
833 
834     debug_return_bool(true);
835 }
836 
837 static bool
cb_eventlog_format(struct logsrvd_config * config,const char * str,size_t offset)838 cb_eventlog_format(struct logsrvd_config *config, const char *str, size_t offset)
839 {
840     debug_decl(cb_eventlog_format, SUDO_DEBUG_UTIL);
841 
842     if (strcmp(str, "json") == 0)
843 	config->eventlog.log_format = EVLOG_JSON;
844     else if (strcmp(str, "sudo") == 0)
845 	config->eventlog.log_format = EVLOG_SUDO;
846     else
847 	debug_return_bool(false);
848 
849     debug_return_bool(true);
850 }
851 
852 static bool
cb_eventlog_exit(struct logsrvd_config * config,const char * str,size_t offset)853 cb_eventlog_exit(struct logsrvd_config *config, const char *str, size_t offset)
854 {
855     int val;
856     debug_decl(cb_eventlog_exit, SUDO_DEBUG_UTIL);
857 
858     if ((val = sudo_strtobool(str)) == -1)
859 	debug_return_bool(false);
860 
861     config->eventlog.log_exit = val;
862     debug_return_bool(true);
863 }
864 
865 /* syslog callbacks */
866 static bool
cb_syslog_maxlen(struct logsrvd_config * config,const char * str,size_t offset)867 cb_syslog_maxlen(struct logsrvd_config *config, const char *str, size_t offset)
868 {
869     unsigned int maxlen;
870     const char *errstr;
871     debug_decl(cb_syslog_maxlen, SUDO_DEBUG_UTIL);
872 
873     maxlen = sudo_strtonum(str, 1, UINT_MAX, &errstr);
874     if (errstr != NULL)
875 	debug_return_bool(false);
876 
877     config->syslog.maxlen = maxlen;
878 
879     debug_return_bool(true);
880 }
881 
882 static bool
cb_syslog_server_facility(struct logsrvd_config * config,const char * str,size_t offset)883 cb_syslog_server_facility(struct logsrvd_config *config, const char *str, size_t offset)
884 {
885     int logfac;
886     debug_decl(cb_syslog_server_facility, SUDO_DEBUG_UTIL);
887 
888     if (!sudo_str2logfac(str, &logfac)) {
889 	sudo_warnx(U_("unknown syslog facility %s"), str);
890 	debug_return_bool(false);
891     }
892 
893     config->syslog.server_facility = logfac;
894 
895     debug_return_bool(true);
896 }
897 
898 static bool
cb_syslog_facility(struct logsrvd_config * config,const char * str,size_t offset)899 cb_syslog_facility(struct logsrvd_config *config, const char *str, size_t offset)
900 {
901     int logfac;
902     debug_decl(cb_syslog_facility, SUDO_DEBUG_UTIL);
903 
904     if (!sudo_str2logfac(str, &logfac)) {
905 	sudo_warnx(U_("unknown syslog facility %s"), str);
906 	debug_return_bool(false);
907     }
908 
909     config->syslog.facility = logfac;
910 
911     debug_return_bool(true);
912 }
913 
914 static bool
cb_syslog_acceptpri(struct logsrvd_config * config,const char * str,size_t offset)915 cb_syslog_acceptpri(struct logsrvd_config *config, const char *str, size_t offset)
916 {
917     int logpri;
918     debug_decl(cb_syslog_acceptpri, SUDO_DEBUG_UTIL);
919 
920     if (!sudo_str2logpri(str, &logpri)) {
921 	sudo_warnx(U_("unknown syslog priority %s"), str);
922 	debug_return_bool(false);
923     }
924 
925     config->syslog.acceptpri = logpri;
926 
927     debug_return_bool(true);
928 }
929 
930 static bool
cb_syslog_rejectpri(struct logsrvd_config * config,const char * str,size_t offset)931 cb_syslog_rejectpri(struct logsrvd_config *config, const char *str, size_t offset)
932 {
933     int logpri;
934     debug_decl(cb_syslog_rejectpri, SUDO_DEBUG_UTIL);
935 
936     if (!sudo_str2logpri(str, &logpri)) {
937 	sudo_warnx(U_("unknown syslog priority %s"), str);
938 	debug_return_bool(false);
939     }
940 
941     config->syslog.rejectpri = logpri;
942 
943     debug_return_bool(true);
944 }
945 
946 static bool
cb_syslog_alertpri(struct logsrvd_config * config,const char * str,size_t offset)947 cb_syslog_alertpri(struct logsrvd_config *config, const char *str, size_t offset)
948 {
949     int logpri;
950     debug_decl(cb_syslog_alertpri, SUDO_DEBUG_UTIL);
951 
952     if (!sudo_str2logpri(str, &logpri)) {
953 	sudo_warnx(U_("unknown syslog priority %s"), str);
954 	debug_return_bool(false);
955     }
956 
957     config->syslog.alertpri = logpri;
958 
959     debug_return_bool(true);
960 }
961 
962 /* logfile callbacks */
963 static bool
cb_logfile_path(struct logsrvd_config * config,const char * str,size_t offset)964 cb_logfile_path(struct logsrvd_config *config, const char *str, size_t offset)
965 {
966     char *copy = NULL;
967     debug_decl(cb_logfile_path, SUDO_DEBUG_UTIL);
968 
969     if (*str != '/') {
970 	debug_return_bool(false);
971 	sudo_warnx(U_("%s: not a fully qualified path"), str);
972 	debug_return_bool(false);
973     }
974     if ((copy = strdup(str)) == NULL) {
975 	sudo_warn(NULL);
976 	debug_return_bool(false);
977     }
978 
979     free(config->logfile.path);
980     config->logfile.path = copy;
981 
982     debug_return_bool(true);
983 }
984 
985 static bool
cb_logfile_time_format(struct logsrvd_config * config,const char * str,size_t offset)986 cb_logfile_time_format(struct logsrvd_config *config, const char *str, size_t offset)
987 {
988     char *copy = NULL;
989     debug_decl(cb_logfile_time_format, SUDO_DEBUG_UTIL);
990 
991     if ((copy = strdup(str)) == NULL) {
992 	sudo_warn(NULL);
993 	debug_return_bool(false);
994     }
995 
996     free(config->logfile.time_format);
997     config->logfile.time_format = copy;
998 
999     debug_return_bool(true);
1000 }
1001 
1002 void
address_list_addref(struct server_address_list * al)1003 address_list_addref(struct server_address_list *al)
1004 {
1005     struct address_list_container *container =
1006 	__containerof(al, struct address_list_container, addrs);
1007     container->refcnt++;
1008 }
1009 
1010 void
address_list_delref(struct server_address_list * al)1011 address_list_delref(struct server_address_list *al)
1012 {
1013     struct address_list_container *container =
1014 	__containerof(al, struct address_list_container, addrs);
1015     if (--container->refcnt == 0) {
1016 	struct server_address *addr;
1017 	while ((addr = TAILQ_FIRST(al))) {
1018 	    TAILQ_REMOVE(al, addr, entries);
1019 	    sudo_rcstr_delref(addr->sa_str);
1020 	    sudo_rcstr_delref(addr->sa_host);
1021 	    free(addr);
1022 	}
1023     }
1024 }
1025 
1026 static struct logsrvd_config_entry server_conf_entries[] = {
1027     { "listen_address", cb_server_listen_address },
1028     { "timeout", cb_server_timeout },
1029     { "tcp_keepalive", cb_server_keepalive },
1030     { "pid_file", cb_server_pid_file },
1031     { "server_log", cb_server_log },
1032 #if defined(HAVE_OPENSSL)
1033     { "tls_key", cb_tls_key, offsetof(struct logsrvd_config, server.tls_key_path) },
1034     { "tls_cacert", cb_tls_cacert, offsetof(struct logsrvd_config, server.tls_cacert_path) },
1035     { "tls_cert", cb_tls_cert, offsetof(struct logsrvd_config, server.tls_cert_path) },
1036     { "tls_dhparams", cb_tls_dhparams, offsetof(struct logsrvd_config, server.tls_dhparams_path) },
1037     { "tls_ciphers_v12", cb_tls_ciphers12, offsetof(struct logsrvd_config, server.tls_ciphers_v12) },
1038     { "tls_ciphers_v13", cb_tls_ciphers13, offsetof(struct logsrvd_config, server.tls_ciphers_v13) },
1039     { "tls_checkpeer", cb_tls_checkpeer, offsetof(struct logsrvd_config, server.tls_check_peer) },
1040     { "tls_verify", cb_tls_verify, offsetof(struct logsrvd_config, server.tls_verify) },
1041 #endif
1042     { NULL }
1043 };
1044 
1045 static struct logsrvd_config_entry relay_conf_entries[] = {
1046     { "relay_host", cb_relay_host },
1047     { "timeout", cb_relay_timeout },
1048     { "connect_timeout", cb_relay_connect_timeout },
1049     { "relay_dir", cb_relay_dir },
1050     { "store_first", cb_relay_store_first },
1051     { "tcp_keepalive", cb_relay_keepalive },
1052 #if defined(HAVE_OPENSSL)
1053     { "tls_key", cb_tls_key, offsetof(struct logsrvd_config, relay.tls_key_path) },
1054     { "tls_cacert", cb_tls_cacert, offsetof(struct logsrvd_config, relay.tls_cacert_path) },
1055     { "tls_cert", cb_tls_cert, offsetof(struct logsrvd_config, relay.tls_cert_path) },
1056     { "tls_dhparams", cb_tls_dhparams, offsetof(struct logsrvd_config, relay.tls_dhparams_path) },
1057     { "tls_ciphers_v12", cb_tls_ciphers12, offsetof(struct logsrvd_config, relay.tls_ciphers_v12) },
1058     { "tls_ciphers_v13", cb_tls_ciphers13, offsetof(struct logsrvd_config, relay.tls_ciphers_v13) },
1059     { "tls_checkpeer", cb_tls_checkpeer, offsetof(struct logsrvd_config, relay.tls_check_peer) },
1060     { "tls_verify", cb_tls_verify, offsetof(struct logsrvd_config, relay.tls_verify) },
1061 #endif
1062     { NULL }
1063 };
1064 
1065 static struct logsrvd_config_entry iolog_conf_entries[] = {
1066     { "iolog_dir", cb_iolog_dir },
1067     { "iolog_file", cb_iolog_file },
1068     { "iolog_flush", cb_iolog_flush },
1069     { "iolog_compress", cb_iolog_compress },
1070     { "iolog_user", cb_iolog_user },
1071     { "iolog_group", cb_iolog_group },
1072     { "iolog_mode", cb_iolog_mode },
1073     { "maxseq", cb_iolog_maxseq },
1074     { NULL }
1075 };
1076 
1077 static struct logsrvd_config_entry eventlog_conf_entries[] = {
1078     { "log_type", cb_eventlog_type },
1079     { "log_format", cb_eventlog_format },
1080     { "log_exit", cb_eventlog_exit },
1081     { NULL }
1082 };
1083 
1084 static struct logsrvd_config_entry syslog_conf_entries[] = {
1085     { "maxlen", cb_syslog_maxlen },
1086     { "server_facility", cb_syslog_server_facility },
1087     { "facility", cb_syslog_facility },
1088     { "reject_priority", cb_syslog_rejectpri },
1089     { "accept_priority", cb_syslog_acceptpri },
1090     { "alert_priority", cb_syslog_alertpri },
1091     { NULL }
1092 };
1093 
1094 static struct logsrvd_config_entry logfile_conf_entries[] = {
1095     { "path", cb_logfile_path },
1096     { "time_format", cb_logfile_time_format },
1097     { NULL }
1098 };
1099 
1100 static struct logsrvd_config_section logsrvd_config_sections[] = {
1101     { "server", server_conf_entries },
1102     { "relay", relay_conf_entries },
1103     { "iolog", iolog_conf_entries },
1104     { "eventlog", eventlog_conf_entries },
1105     { "syslog", syslog_conf_entries },
1106     { "logfile", logfile_conf_entries },
1107     { NULL }
1108 };
1109 
1110 static bool
logsrvd_conf_parse(struct logsrvd_config * config,FILE * fp,const char * path)1111 logsrvd_conf_parse(struct logsrvd_config *config, FILE *fp, const char *path)
1112 {
1113     struct logsrvd_config_section *conf_section = NULL;
1114     unsigned int lineno = 0;
1115     size_t linesize = 0;
1116     char *line = NULL;
1117     bool ret = false;
1118     debug_decl(logsrvd_conf_parse, SUDO_DEBUG_UTIL);
1119 
1120     while (sudo_parseln(&line, &linesize, &lineno, fp, 0) != -1) {
1121 	struct logsrvd_config_entry *entry;
1122 	char *ep, *val;
1123 
1124 	/* Skip blank, comment or invalid lines. */
1125 	if (*line == '\0' || *line == ';')
1126 	    continue;
1127 
1128 	/* New section */
1129 	if (line[0] == '[') {
1130 	    char *section_name = line + 1;
1131 	    char *cp = strchr(section_name, ']');
1132 	    if (cp == NULL) {
1133 		sudo_warnx(U_("%s:%d unmatched '[': %s"),
1134 		    path, lineno, line);
1135 		goto done;
1136 	    }
1137 	    *cp = '\0';
1138 	    for (conf_section = logsrvd_config_sections; conf_section->name != NULL;
1139 		    conf_section++) {
1140 		if (strcasecmp(section_name, conf_section->name) == 0)
1141 		    break;
1142 	    }
1143 	    if (conf_section->name == NULL) {
1144 		sudo_warnx(U_("%s:%d invalid config section: %s"),
1145 		    path, lineno, section_name);
1146 		goto done;
1147 	    }
1148 	    continue;
1149 	}
1150 
1151 	if ((ep = strchr(line, '=')) == NULL) {
1152 	    sudo_warnx(U_("%s:%d invalid configuration line: %s"),
1153 		path, lineno, line);
1154 	    goto done;
1155 	}
1156 
1157 	if (conf_section == NULL) {
1158 	    sudo_warnx(U_("%s:%d expected section name: %s"),
1159 		path, lineno, line);
1160 	    goto done;
1161 	}
1162 
1163 	val = ep + 1;
1164 	while (isspace((unsigned char)*val))
1165 	    val++;
1166 	while (ep > line && isspace((unsigned char)ep[-1]))
1167 	    ep--;
1168 	*ep = '\0';
1169 	for (entry = conf_section->entries; entry->conf_str != NULL; entry++) {
1170 	    if (strcasecmp(line, entry->conf_str) == 0) {
1171 		if (!entry->setter(config, val, entry->offset)) {
1172 		    sudo_warnx(U_("invalid value for %s: %s"),
1173 			entry->conf_str, val);
1174 		    goto done;
1175 		}
1176 		break;
1177 	    }
1178 	}
1179 	if (entry->conf_str == NULL) {
1180 	    sudo_warnx(U_("%s:%d [%s] illegal key: %s"), path, lineno,
1181 		conf_section->name, line);
1182 	    goto done;
1183 	}
1184     }
1185     ret = true;
1186 
1187 done:
1188     free(line);
1189     debug_return_bool(ret);
1190 }
1191 
1192 static FILE *
logsrvd_open_log_file(const char * path,int flags)1193 logsrvd_open_log_file(const char *path, int flags)
1194 {
1195     mode_t oldmask;
1196     FILE *fp = NULL;
1197     const char *omode;
1198     int fd;
1199     debug_decl(logsrvd_open_log_file, SUDO_DEBUG_UTIL);
1200 
1201     if (ISSET(flags, O_APPEND)) {
1202 	omode = "a";
1203     } else {
1204 	omode = "w";
1205     }
1206     oldmask = umask(S_IRWXG|S_IRWXO);
1207     fd = open(path, flags, S_IRUSR|S_IWUSR);
1208     (void)umask(oldmask);
1209     if (fd == -1 || (fp = fdopen(fd, omode)) == NULL) {
1210 	sudo_warn(U_("unable to open log file %s"), path);
1211 	if (fd != -1)
1212 	    close(fd);
1213     }
1214 
1215     debug_return_ptr(fp);
1216 }
1217 
1218 static FILE *
logsrvd_open_eventlog(struct logsrvd_config * config)1219 logsrvd_open_eventlog(struct logsrvd_config *config)
1220 {
1221     int flags;
1222     debug_decl(logsrvd_open_eventlog, SUDO_DEBUG_UTIL);
1223 
1224     /* Cannot append to a JSON file. */
1225     if (config->eventlog.log_format == EVLOG_JSON) {
1226 	flags = O_RDWR|O_CREAT;
1227     } else {
1228 	flags = O_WRONLY|O_APPEND|O_CREAT;
1229     }
1230     debug_return_ptr(logsrvd_open_log_file(config->logfile.path, flags));
1231 }
1232 
1233 static FILE *
logsrvd_stub_open_log(int type,const char * logfile)1234 logsrvd_stub_open_log(int type, const char *logfile)
1235 {
1236     /* Actual open already done by logsrvd_open_eventlog() */
1237     return logsrvd_config->logfile.stream;
1238 }
1239 
1240 static void
logsrvd_stub_close_log(int type,FILE * fp)1241 logsrvd_stub_close_log(int type, FILE *fp)
1242 {
1243     return;
1244 }
1245 
1246 /* Set eventlog configuration settings from on logsrvd config. */
1247 static void
logsrvd_conf_eventlog_setconf(struct logsrvd_config * config)1248 logsrvd_conf_eventlog_setconf(struct logsrvd_config *config)
1249 {
1250     debug_decl(logsrvd_conf_eventlog_setconf, SUDO_DEBUG_UTIL);
1251 
1252     eventlog_set_type(config->eventlog.log_type);
1253     eventlog_set_format(config->eventlog.log_format);
1254     eventlog_set_syslog_acceptpri(config->syslog.acceptpri);
1255     eventlog_set_syslog_rejectpri(config->syslog.rejectpri);
1256     eventlog_set_syslog_alertpri(config->syslog.alertpri);
1257     eventlog_set_syslog_maxlen(config->syslog.maxlen);
1258     eventlog_set_logpath(config->logfile.path);
1259     eventlog_set_time_fmt(config->logfile.time_format);
1260     eventlog_set_open_log(logsrvd_stub_open_log);
1261     eventlog_set_close_log(logsrvd_stub_close_log);
1262 
1263     debug_return;
1264 }
1265 
1266 /*
1267  * Conversation function for use by sudo_warn/sudo_fatal.
1268  * Logs to stdout/stderr.
1269  */
1270 static int
logsrvd_conv_stderr(int num_msgs,const struct sudo_conv_message msgs[],struct sudo_conv_reply replies[],struct sudo_conv_callback * callback)1271 logsrvd_conv_stderr(int num_msgs, const struct sudo_conv_message msgs[],
1272     struct sudo_conv_reply replies[], struct sudo_conv_callback *callback)
1273 {
1274     int i;
1275     debug_decl(logsrvd_conv_stderr, SUDO_DEBUG_UTIL);
1276 
1277     for (i = 0; i < num_msgs; i++) {
1278 	if (fputs(msgs[i].msg, stderr) == EOF)
1279 	    debug_return_int(-1);
1280     }
1281 
1282     debug_return_int(0);
1283 }
1284 
1285 /*
1286  * Conversation function for use by sudo_warn/sudo_fatal.
1287  * Acts as a no-op log sink.
1288  */
1289 static int
logsrvd_conv_none(int num_msgs,const struct sudo_conv_message msgs[],struct sudo_conv_reply replies[],struct sudo_conv_callback * callback)1290 logsrvd_conv_none(int num_msgs, const struct sudo_conv_message msgs[],
1291     struct sudo_conv_reply replies[], struct sudo_conv_callback *callback)
1292 {
1293     /* Also write to stderr if still in the foreground. */
1294     if (logsrvd_warn_enable_stderr) {
1295 	(void)logsrvd_conv_stderr(num_msgs, msgs, replies, callback);
1296     }
1297 
1298     return 0;
1299 }
1300 
1301 /*
1302  * Conversation function for use by sudo_warn/sudo_fatal.
1303  * Logs to syslog.
1304  */
1305 static int
logsrvd_conv_syslog(int num_msgs,const struct sudo_conv_message msgs[],struct sudo_conv_reply replies[],struct sudo_conv_callback * callback)1306 logsrvd_conv_syslog(int num_msgs, const struct sudo_conv_message msgs[],
1307     struct sudo_conv_reply replies[], struct sudo_conv_callback *callback)
1308 {
1309     char *buf = NULL, *cp = NULL;
1310     const char *progname;
1311     size_t proglen, bufsize = 0;
1312     int i;
1313     debug_decl(logsrvd_conv_syslog, SUDO_DEBUG_UTIL);
1314 
1315     if (logsrvd_config == NULL) {
1316 	debug_return_int(logsrvd_conv_stderr(num_msgs, msgs, replies, callback));
1317     }
1318 
1319     /* Also write to stderr if still in the foreground. */
1320     if (logsrvd_warn_enable_stderr) {
1321 	(void)logsrvd_conv_stderr(num_msgs, msgs, replies, callback);
1322     }
1323 
1324     /*
1325      * Concat messages into a flag string that we can syslog.
1326      */
1327     progname = getprogname();
1328     proglen = strlen(progname);
1329     for (i = 0; i < num_msgs; i++) {
1330 	const char *msg = msgs[i].msg;
1331 	size_t len = strlen(msg);
1332 	size_t used = (size_t)(cp - buf);
1333 
1334 	/* Strip leading "sudo_logsrvd: " prefix. */
1335 	if (strncmp(msg, progname, proglen) == 0) {
1336 	    msg += proglen;
1337 	    len -= proglen;
1338 	    if (len == 0) {
1339 		/* Skip over ": " string that follows program name. */
1340 		if (i + 1 < num_msgs && strcmp(msgs[i + 1].msg, ": ") == 0) {
1341 		    i++;
1342 		    continue;
1343 		}
1344 	    } else if (msg[0] == ':' && msg[1] == ' ') {
1345 		/* Handle "progname: " */
1346 		msg += 2;
1347 		len -= 2;
1348 	    }
1349 	}
1350 
1351 	/* Strip off trailing newlines. */
1352 	while (len > 1 && msg[len - 1] == '\n')
1353 	    len--;
1354 	if (len == 0)
1355 	    continue;
1356 
1357 	if (len >= bufsize - used) {
1358 	    bufsize += 1024;
1359 	    char *tmp = realloc(buf, bufsize);
1360 	    if (tmp == NULL) {
1361 		sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
1362 		free(buf);
1363 		debug_return_int(-1);
1364 	    }
1365 	    buf = tmp;
1366 	    cp = tmp + used;
1367 	}
1368 	memcpy(cp, msg, len);
1369 	cp[len] = '\0';
1370 	cp += len;
1371     }
1372     if (buf != NULL) {
1373 	openlog(progname, 0, logsrvd_config->syslog.server_facility);
1374 	syslog(LOG_ERR, "%s", buf);
1375 	free(buf);
1376 
1377 	/* Restore old syslog settings. */
1378 	if (logsrvd_config->eventlog.log_type == EVLOG_SYSLOG)
1379 	    openlog("sudo", 0, logsrvd_config->syslog.facility);
1380     }
1381 
1382     debug_return_int(0);
1383 }
1384 
1385 /*
1386  * Conversation function for use by sudo_warn/sudo_fatal.
1387  * Logs to an already-open log file.
1388  */
1389 static int
logsrvd_conv_logfile(int num_msgs,const struct sudo_conv_message msgs[],struct sudo_conv_reply replies[],struct sudo_conv_callback * callback)1390 logsrvd_conv_logfile(int num_msgs, const struct sudo_conv_message msgs[],
1391     struct sudo_conv_reply replies[], struct sudo_conv_callback *callback)
1392 {
1393     const char *progname;
1394     size_t proglen;
1395     int i;
1396     debug_decl(logsrvd_conv_logfile, SUDO_DEBUG_UTIL);
1397 
1398     if (logsrvd_config == NULL) {
1399 	debug_return_int(logsrvd_conv_stderr(num_msgs, msgs, replies, callback));
1400     }
1401 
1402     /* Also write to stderr if still in the foreground. */
1403     if (logsrvd_warn_enable_stderr) {
1404 	(void)logsrvd_conv_stderr(num_msgs, msgs, replies, callback);
1405     }
1406 
1407     if (logsrvd_config->server.log_stream == NULL) {
1408 	errno = EBADF;
1409 	debug_return_int(-1);
1410     }
1411 
1412     progname = getprogname();
1413     proglen = strlen(progname);
1414     for (i = 0; i < num_msgs; i++) {
1415 	const char *msg = msgs[i].msg;
1416 	size_t len = strlen(msg);
1417 
1418 	/* Strip leading "sudo_logsrvd: " prefix. */
1419 	if (strncmp(msg, progname, proglen) == 0) {
1420 	    msg += proglen;
1421 	    len -= proglen;
1422 	    if (len == 0) {
1423 		/* Skip over ": " string that follows program name. */
1424 		if (i + 1 < num_msgs && strcmp(msgs[i + 1].msg, ": ") == 0) {
1425 		    i++;
1426 		    continue;
1427 		}
1428 	    } else if (msg[0] == ':' && msg[1] == ' ') {
1429 		/* Handle "progname: " */
1430 		msg += 2;
1431 		len -= 2;
1432 	    }
1433 	}
1434 
1435 	if (fwrite(msg, len, 1, logsrvd_config->server.log_stream) != 1)
1436 	    debug_return_int(-1);
1437     }
1438 
1439     debug_return_int(0);
1440 }
1441 
1442 /* Free the specified struct logsrvd_config and its contents. */
1443 static void
logsrvd_conf_free(struct logsrvd_config * config)1444 logsrvd_conf_free(struct logsrvd_config *config)
1445 {
1446     debug_decl(logsrvd_conf_free, SUDO_DEBUG_UTIL);
1447 
1448     if (config == NULL)
1449 	debug_return;
1450 
1451     /* struct logsrvd_config_server */
1452     address_list_delref(&config->server.addresses.addrs);
1453     free(config->server.pid_file);
1454     free(config->server.log_file);
1455     if (config->server.log_stream != NULL)
1456 	fclose(config->server.log_stream);
1457 #if defined(HAVE_OPENSSL)
1458     free(config->server.tls_key_path);
1459     free(config->server.tls_cert_path);
1460     free(config->server.tls_cacert_path);
1461     free(config->server.tls_dhparams_path);
1462     free(config->server.tls_ciphers_v12);
1463     free(config->server.tls_ciphers_v13);
1464 
1465     if (config->server.ssl_ctx != NULL)
1466 	SSL_CTX_free(config->server.ssl_ctx);
1467 #endif
1468 
1469     /* struct logsrvd_config_relay */
1470     address_list_delref(&config->relay.relays.addrs);
1471     free(config->relay.relay_dir);
1472 #if defined(HAVE_OPENSSL)
1473     free(config->relay.tls_key_path);
1474     free(config->relay.tls_cert_path);
1475     free(config->relay.tls_cacert_path);
1476     free(config->relay.tls_dhparams_path);
1477     free(config->relay.tls_ciphers_v12);
1478     free(config->relay.tls_ciphers_v13);
1479 
1480     if (config->relay.ssl_ctx != NULL)
1481 	SSL_CTX_free(config->relay.ssl_ctx);
1482 #endif
1483 
1484     /* struct logsrvd_config_iolog */
1485     free(config->iolog.iolog_dir);
1486     free(config->iolog.iolog_file);
1487 
1488     /* struct logsrvd_config_logfile */
1489     free(config->logfile.path);
1490     free(config->logfile.time_format);
1491     if (config->logfile.stream != NULL)
1492 	fclose(config->logfile.stream);
1493 
1494     free(config);
1495 
1496     debug_return;
1497 }
1498 
1499 /* Allocate a new struct logsrvd_config and set default values. */
1500 static struct logsrvd_config *
logsrvd_conf_alloc(void)1501 logsrvd_conf_alloc(void)
1502 {
1503     struct logsrvd_config *config;
1504     debug_decl(logsrvd_conf_alloc, SUDO_DEBUG_UTIL);
1505 
1506     if ((config = calloc(1, sizeof(*config))) == NULL) {
1507 	sudo_warn(NULL);
1508 	debug_return_ptr(NULL);
1509     }
1510 
1511     /* Relay defaults */
1512     TAILQ_INIT(&config->relay.relays.addrs);
1513     config->relay.relays.refcnt = 1;
1514     config->relay.timeout.tv_sec = DEFAULT_SOCKET_TIMEOUT_SEC;
1515     config->relay.connect_timeout.tv_sec = DEFAULT_SOCKET_TIMEOUT_SEC;
1516     config->relay.tcp_keepalive = true;
1517     config->relay.retry_interval = 30;
1518     if (!cb_relay_dir(config, _PATH_SUDO_RELAY_DIR, 0))
1519 	goto bad;
1520 #if defined(HAVE_OPENSSL)
1521     config->relay.tls_verify = -1;
1522     config->relay.tls_check_peer = -1;
1523 #endif
1524 
1525     /* Server defaults */
1526     TAILQ_INIT(&config->server.addresses.addrs);
1527     config->server.addresses.refcnt = 1;
1528     config->server.timeout.tv_sec = DEFAULT_SOCKET_TIMEOUT_SEC;
1529     config->server.tcp_keepalive = true;
1530     config->server.log_type = SERVER_LOG_SYSLOG;
1531     config->server.pid_file = strdup(_PATH_SUDO_LOGSRVD_PID);
1532     if (config->server.pid_file == NULL) {
1533 	sudo_warn(NULL);
1534 	goto bad;
1535     }
1536 
1537 #if defined(HAVE_OPENSSL)
1538     /*
1539      * Only set default CA and cert paths if the files actually exist.
1540      * This ensures we don't enable TLS by default when it is not configured.
1541      */
1542     if (access(DEFAULT_CA_CERT_PATH, R_OK) == 0) {
1543 	config->server.tls_cacert_path = strdup(DEFAULT_CA_CERT_PATH);
1544 	if (config->server.tls_cacert_path == NULL) {
1545 	    sudo_warn(NULL);
1546 	    goto bad;
1547 	}
1548     }
1549     if (access(DEFAULT_SERVER_CERT_PATH, R_OK) == 0) {
1550 	config->server.tls_cert_path = strdup(DEFAULT_SERVER_CERT_PATH);
1551 	if (config->server.tls_cert_path == NULL) {
1552 	    sudo_warn(NULL);
1553 	    goto bad;
1554 	}
1555     }
1556     config->server.tls_key_path = strdup(DEFAULT_SERVER_KEY_PATH);
1557     if (config->server.tls_key_path == NULL) {
1558 	sudo_warn(NULL);
1559 	goto bad;
1560     }
1561     config->server.tls_verify = true;
1562     config->server.tls_check_peer = false;
1563 #endif
1564 
1565     /* I/O log defaults */
1566     config->iolog.compress = false;
1567     config->iolog.flush = true;
1568     config->iolog.mode = S_IRUSR|S_IWUSR;
1569     config->iolog.maxseq = SESSID_MAX;
1570     if (!cb_iolog_dir(config, _PATH_SUDO_IO_LOGDIR, 0))
1571 	goto bad;
1572     if (!cb_iolog_file(config, "%{seq}", 0))
1573 	goto bad;
1574     config->iolog.uid = ROOT_UID;
1575     config->iolog.gid = ROOT_GID;
1576     config->iolog.gid_set = false;
1577 
1578     /* Event log defaults */
1579     config->eventlog.log_type = EVLOG_SYSLOG;
1580     config->eventlog.log_format = EVLOG_SUDO;
1581     config->eventlog.log_exit = false;
1582 
1583     /* Syslog defaults */
1584     config->syslog.maxlen = 960;
1585     config->syslog.server_facility = LOG_DAEMON;
1586     if (!cb_syslog_facility(config, LOGFAC, 0)) {
1587 	sudo_warnx(U_("unknown syslog facility %s"), LOGFAC);
1588 	goto bad;
1589     }
1590     if (!cb_syslog_acceptpri(config, PRI_SUCCESS, 0)) {
1591 	sudo_warnx(U_("unknown syslog priority %s"), PRI_SUCCESS);
1592 	goto bad;
1593     }
1594     if (!cb_syslog_rejectpri(config, PRI_FAILURE, 0)) {
1595 	sudo_warnx(U_("unknown syslog priority %s"), PRI_FAILURE);
1596 	goto bad;
1597     }
1598     if (!cb_syslog_alertpri(config, PRI_FAILURE, 0)) {
1599 	sudo_warnx(U_("unknown syslog priority %s"), PRI_FAILURE);
1600 	goto bad;
1601     }
1602 
1603     /* Log file defaults */
1604     if (!cb_logfile_time_format(config, "%h %e %T", 0))
1605 	goto bad;
1606     if (!cb_logfile_path(config, _PATH_SUDO_LOGFILE, 0))
1607 	goto bad;
1608 
1609     debug_return_ptr(config);
1610 bad:
1611     logsrvd_conf_free(config);
1612     debug_return_ptr(NULL);
1613 }
1614 
1615 static bool
logsrvd_conf_apply(struct logsrvd_config * config)1616 logsrvd_conf_apply(struct logsrvd_config *config)
1617 {
1618 #if defined(HAVE_OPENSSL)
1619     struct server_address *addr;
1620 #endif
1621     debug_decl(logsrvd_conf_apply, SUDO_DEBUG_UTIL);
1622 
1623     /* There can be multiple addresses so we can't set a default earlier. */
1624     if (TAILQ_EMPTY(&config->server.addresses.addrs)) {
1625 	/* Enable plaintext listender. */
1626 	if (!cb_server_listen_address(config, "*:" DEFAULT_PORT, 0))
1627 	    debug_return_bool(false);
1628 #if defined(HAVE_OPENSSL)
1629 	/* If a certificate was specified, enable the TLS listener too. */
1630 	if (config->server.tls_cert_path != NULL) {
1631 	    if (!cb_server_listen_address(config, "*:" DEFAULT_PORT_TLS "(tls)", 0))
1632 		debug_return_bool(false);
1633 	}
1634     } else {
1635 	/* Check that TLS configuration is valid. */
1636 	TAILQ_FOREACH(addr, &config->server.addresses.addrs, entries) {
1637 	    if (!addr->tls)
1638 		continue;
1639 	    /*
1640 	     * If a TLS listener was explicitly enabled but the cert path
1641 	     * was not, use the default.
1642 	     */
1643 	    if (config->server.tls_cert_path == NULL) {
1644 		config->server.tls_cert_path =
1645 		    strdup(DEFAULT_SERVER_CERT_PATH);
1646 		if (config->server.tls_cert_path == NULL) {
1647 		    sudo_warn(NULL);
1648 		    debug_return_bool(false);
1649 		}
1650 	    }
1651 	    break;
1652 	}
1653 #endif /* HAVE_OPENSSL */
1654     }
1655 
1656 #if defined(HAVE_OPENSSL)
1657     TAILQ_FOREACH(addr, &config->server.addresses.addrs, entries) {
1658 	if (!addr->tls)
1659 	    continue;
1660         /* Create a TLS context for the server. */
1661 	config->server.ssl_ctx = init_tls_context(
1662 	    config->server.tls_cacert_path, config->server.tls_cert_path,
1663 	    config->server.tls_key_path, config->server.tls_dhparams_path,
1664 	    config->server.tls_ciphers_v12, config->server.tls_ciphers_v13,
1665 	    config->server.tls_verify);
1666 	if (config->server.ssl_ctx == NULL) {
1667 	    sudo_warnx(U_("unable to initialize server TLS context"));
1668 	    debug_return_bool(false);
1669 	}
1670 	break;
1671     }
1672 
1673     if (TLS_CONFIGURED(config->relay)) {
1674 	TAILQ_FOREACH(addr, &config->relay.relays.addrs, entries) {
1675 	    if (!addr->tls)
1676 		continue;
1677 	    /* Create a TLS context for the relay. */
1678 	    config->relay.ssl_ctx = init_tls_context(
1679 		TLS_RELAY_STR(config, tls_cacert_path),
1680 		TLS_RELAY_STR(config, tls_cert_path),
1681 		TLS_RELAY_STR(config, tls_key_path),
1682 		TLS_RELAY_STR(config, tls_dhparams_path),
1683 		TLS_RELAY_STR(config, tls_ciphers_v12),
1684 		TLS_RELAY_STR(config, tls_ciphers_v13),
1685 		TLS_RELAY_INT(config, tls_verify));
1686 	    if (config->relay.ssl_ctx == NULL) {
1687 		sudo_warnx(U_("unable to initialize relay TLS context"));
1688 		debug_return_bool(false);
1689 	    }
1690 	    break;
1691 	}
1692     }
1693 #endif /* HAVE_OPENSSL */
1694 
1695     /* Clear store_first if not relaying. */
1696     if (TAILQ_EMPTY(&config->relay.relays.addrs))
1697 	config->relay.store_first = false;
1698 
1699     /* Open server log if specified. */
1700     switch (config->server.log_type) {
1701     case SERVER_LOG_SYSLOG:
1702 	sudo_warn_set_conversation(logsrvd_conv_syslog);
1703 	break;
1704     case SERVER_LOG_FILE:
1705 	config->server.log_stream =
1706 	    logsrvd_open_log_file(config->server.log_file, O_WRONLY|O_APPEND|O_CREAT);
1707 	if (config->server.log_stream == NULL)
1708 	    debug_return_bool(false);
1709 	sudo_warn_set_conversation(logsrvd_conv_logfile);
1710 	break;
1711     case SERVER_LOG_NONE:
1712 	sudo_warn_set_conversation(logsrvd_conv_none);
1713 	break;
1714     case SERVER_LOG_STDERR:
1715 	/* Default is stderr. */
1716 	sudo_warn_set_conversation(NULL);
1717 	break;
1718     default:
1719 	sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
1720 	    "cannot open unknown log type %d", config->eventlog.log_type);
1721 	break;
1722     }
1723 
1724     /* Open event log if specified. */
1725     switch (config->eventlog.log_type) {
1726     case EVLOG_SYSLOG:
1727 	openlog("sudo", 0, config->syslog.facility);
1728 	break;
1729     case EVLOG_FILE:
1730 	config->logfile.stream = logsrvd_open_eventlog(config);
1731 	if (config->logfile.stream == NULL)
1732 	    debug_return_bool(false);
1733 	break;
1734     case EVLOG_NONE:
1735 	break;
1736     default:
1737 	sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
1738 	    "cannot open unknown log type %d", config->eventlog.log_type);
1739 	break;
1740     }
1741 
1742     /* Set I/O log library settings */
1743     iolog_set_defaults();
1744     iolog_set_compress(config->iolog.compress);
1745     iolog_set_flush(config->iolog.flush);
1746     iolog_set_owner(config->iolog.uid, config->iolog.gid);
1747     iolog_set_mode(config->iolog.mode);
1748     iolog_set_maxseq(config->iolog.maxseq);
1749 
1750     /* Set event log config */
1751     logsrvd_conf_eventlog_setconf(config);
1752 
1753     logsrvd_conf_free(logsrvd_config);
1754     logsrvd_config = config;
1755 
1756     debug_return_bool(true);
1757 }
1758 
1759 /*
1760  * Read .ini style logsrvd.conf file.
1761  * Note that we use '#' not ';' for the comment character.
1762  */
1763 bool
logsrvd_conf_read(const char * path)1764 logsrvd_conf_read(const char *path)
1765 {
1766     struct logsrvd_config *config;
1767     bool ret = false;
1768     FILE *fp = NULL;
1769     debug_decl(logsrvd_conf_read, SUDO_DEBUG_UTIL);
1770 
1771     config = logsrvd_conf_alloc();
1772 
1773     if ((fp = fopen(path, "r")) == NULL) {
1774 	if (errno != ENOENT) {
1775 	    sudo_warn("%s", path);
1776 	    goto done;
1777 	}
1778     } else {
1779 	if (!logsrvd_conf_parse(config, fp, path))
1780 	    goto done;
1781     }
1782 
1783     /* Install new config */
1784     if (logsrvd_conf_apply(config)) {
1785 	config = NULL;
1786 	ret = true;
1787     }
1788 
1789 done:
1790     logsrvd_conf_free(config);
1791     if (fp != NULL)
1792 	fclose(fp);
1793     debug_return_bool(ret);
1794 }
1795 
1796 void
logsrvd_conf_cleanup(void)1797 logsrvd_conf_cleanup(void)
1798 {
1799     debug_decl(logsrvd_conf_cleanup, SUDO_DEBUG_UTIL);
1800 
1801     logsrvd_conf_free(logsrvd_config);
1802     logsrvd_config = NULL;
1803 
1804     debug_return;
1805 }
1806 
1807 void
logsrvd_warn_stderr(bool enabled)1808 logsrvd_warn_stderr(bool enabled)
1809 {
1810     logsrvd_warn_enable_stderr = enabled;
1811 }
1812