Coverage Report

Created: 2025-11-24 06:36

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