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