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