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