1 /*
2  * Copyright (c) 2021 Todd C. Miller <Todd.Miller@sudo.ws>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #include <config.h>
18 
19 #include <sys/types.h>
20 #include <sys/socket.h>
21 #include <netinet/in.h>
22 #include <arpa/inet.h>
23 
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #if defined(HAVE_STDINT_H)
28 # include <stdint.h>
29 #elif defined(HAVE_INTTYPES_H)
30 # include <inttypes.h>
31 #endif
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <netdb.h>
35 #include <unistd.h>
36 #include <string.h>
37 #ifndef HAVE_GETADDRINFO
38 # include "compat/getaddrinfo.h"
39 #endif
40 
41 #include "sudoers.h"
42 #include "interfaces.h"
43 
44 extern char **environ;
45 extern sudo_dso_public struct policy_plugin sudoers_policy;
46 
47 const char *path_plugin_dir = _PATH_SUDO_PLUGIN_DIR;
48 char *audit_msg;
49 
50 static int pass;
51 
52 static FILE *
open_data(const uint8_t * data,size_t size)53 open_data(const uint8_t *data, size_t size)
54 {
55 #ifdef HAVE_FMEMOPEN
56     /* Operate in-memory. */
57     return fmemopen((void *)data, size, "r");
58 #else
59     char tempfile[] = "/tmp/sudoers.XXXXXX";
60     size_t nwritten;
61     int fd;
62 
63     /* Use (unlinked) temporary file. */
64     fd = mkstemp(tempfile);
65     if (fd == -1)
66 	return NULL;
67     unlink(tempfile);
68     nwritten = write(fd, data, size);
69     if (nwritten != size) {
70 	close(fd);
71 	return NULL;
72     }
73     lseek(fd, 0, SEEK_SET);
74     return fdopen(fd, "r");
75 #endif
76 }
77 
78 /*
79  * Array that gets resized as needed.
80  */
81 struct dynamic_array {
82     char **entries;
83     size_t len;
84     size_t size;
85 };
86 
87 static void
free_strvec(char ** vec)88 free_strvec(char **vec)
89 {
90     int i;
91 
92     for (i = 0; vec[i] != NULL; i++)
93 	free(vec[i]);
94 }
95 
96 static void
free_dynamic_array(struct dynamic_array * arr)97 free_dynamic_array(struct dynamic_array *arr)
98 {
99     if (arr->entries != NULL) {
100 	free_strvec(arr->entries);
101 	free(arr->entries);
102     }
103     memset(arr, 0, sizeof(*arr));
104 }
105 
106 static bool
push(struct dynamic_array * arr,const char * entry)107 push(struct dynamic_array *arr, const char *entry)
108 {
109     char *copy = NULL;
110 
111     if (entry != NULL) {
112 	if ((copy = strdup(entry)) == NULL)
113 	    return false;
114     }
115 
116     if (arr->len + (entry != NULL) >= arr->size) {
117 	char **tmp = reallocarray(arr->entries, arr->size + 128, sizeof(char *));
118 	if (tmp == NULL) {
119 	    free(copy);
120 	    return false;
121 	}
122 	arr->entries = tmp;
123 	arr->size += 128;
124     }
125     if (copy != NULL)
126 	arr->entries[arr->len++] = copy;
127     arr->entries[arr->len] = NULL;
128 
129     return true;
130 }
131 
132 static int
fuzz_conversation(int num_msgs,const struct sudo_conv_message msgs[],struct sudo_conv_reply replies[],struct sudo_conv_callback * callback)133 fuzz_conversation(int num_msgs, const struct sudo_conv_message msgs[],
134     struct sudo_conv_reply replies[], struct sudo_conv_callback *callback)
135 {
136     return 0;
137 }
138 
139 static int
fuzz_printf(int msg_type,const char * fmt,...)140 fuzz_printf(int msg_type, const char *fmt, ...)
141 {
142     return 0;
143 }
144 
145 int
fuzz_hook_stub(struct sudo_hook * hook)146 fuzz_hook_stub(struct sudo_hook *hook)
147 {
148     return 0;
149 }
150 
151 /*
152  * The fuzzing environment may not have DNS available, this may result
153  * in long delays that cause a timeout when fuzzing.  This getaddrinfo()
154  * can look up "localhost" and returns an error for anything else.
155  */
156 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
157 int
158 # ifdef HAVE_GETADDRINFO
getaddrinfo(const char * nodename,const char * servname,const struct addrinfo * hints,struct addrinfo ** res)159 getaddrinfo(
160 # else
161 sudo_getaddrinfo(
162 # endif
163     const char *nodename, const char *servname,
164     const struct addrinfo *hints, struct addrinfo **res)
165 {
166     struct addrinfo *ai;
167     struct in_addr addr;
168 
169     /* Stub getaddrinfo(3) to avoid a DNS timeout in CIfuzz. */
170     if (strcmp(nodename, "localhost") != 0 || servname != NULL)
171 	return EAI_FAIL;
172 
173     /* Hard-code localhost. */
174     ai = calloc(1, sizeof(*ai) + sizeof(struct sockaddr_in));
175     if (ai == NULL)
176 	return EAI_MEMORY;
177     ai->ai_canonname = strdup("localhost");
178     if (ai == NULL) {
179 	free(ai);
180 	return EAI_MEMORY;
181     }
182     ai->ai_family = AF_INET;
183     ai->ai_protocol = IPPROTO_TCP;
184     ai->ai_addrlen = sizeof(struct sockaddr_in);
185     ai->ai_addr = (struct sockaddr *)(ai + 1);
186     inet_pton(AF_INET, "127.0.0.1", &addr);
187     ((struct sockaddr_in *)ai->ai_addr)->sin_family = AF_INET;
188     ((struct sockaddr_in *)ai->ai_addr)->sin_addr = addr;
189     *res = ai;
190     return 0;
191 }
192 
193 void
194 # ifdef HAVE_GETADDRINFO
freeaddrinfo(struct addrinfo * ai)195 freeaddrinfo(struct addrinfo *ai)
196 # else
197 sudo_freeaddrinfo(struct addrinfo *ai)
198 # endif
199 {
200     struct addrinfo *next;
201 
202     while (ai != NULL) {
203 	next = ai->ai_next;
204 	free(ai->ai_canonname);
205 	free(ai);
206 	ai = next;
207     }
208 }
209 #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
210 
211 enum fuzz_policy_pass {
212     PASS_NONE,
213     PASS_VERSION,
214     PASS_CHECK_LOG_LOCAL,
215     PASS_CHECK_LOG_REMOTE,
216     PASS_CHECK_NOT_FOUND,
217     PASS_CHECK_NOT_FOUND_DOT,
218     PASS_LIST,
219     PASS_LIST_OTHER,
220     PASS_LIST_CHECK,
221     PASS_VALIDATE,
222     PASS_INVALIDATE
223 };
224 
225 int
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)226 LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
227 {
228     struct dynamic_array plugin_args = { NULL };
229     struct dynamic_array settings = { NULL };
230     struct dynamic_array user_info = { NULL };
231     struct dynamic_array argv = { NULL };
232     struct dynamic_array env_add = { NULL };
233     char **command_info = NULL, **argv_out = NULL, **user_env_out = NULL;
234     const char *errstr = NULL;
235     const int num_passes = 10;
236     char *line = NULL;
237     size_t linesize = 0;
238     ssize_t linelen;
239     int res = 1;
240     FILE *fp;
241 
242     fp = open_data(data, size);
243     if (fp == NULL)
244         return 0;
245 
246     setprogname("fuzz_policy");
247     sudoers_debug_register(getprogname(), NULL);
248 
249     /* user_info and settings must be non-NULL (even if empty). */
250     push(&user_info, NULL);
251     push(&settings, NULL);
252 
253     /* Iterate over each line of data. */
254     while ((linelen = getdelim(&line, &linesize, '\n', fp)) != -1) {
255 	if (line[linelen - 1] == '\n')
256 	    line[linelen - 1] = '\0';
257 
258 	/* Skip comments and blank lines. */
259 	if (line[0] == '#' || line[0] == '\0')
260 	    continue;
261 
262 	/* plugin args */
263 	if (strncmp(line, "error_recovery=", sizeof("error_recovery=") - 1) == 0) {
264 	    push(&plugin_args, line);
265 	    continue;
266 	}
267 	if (strncmp(line, "sudoers_file=", sizeof("sudoers_file=") - 1) == 0) {
268 	    push(&plugin_args, line);
269 	    continue;
270 	}
271 	if (strncmp(line, "sudoers_mode=", sizeof("sudoers_mode=") - 1) == 0) {
272 	    push(&plugin_args, line);
273 	    continue;
274 	}
275 	if (strncmp(line, "sudoers_gid=", sizeof("sudoers_gid=") - 1) == 0) {
276 	    push(&plugin_args, line);
277 	    continue;
278 	}
279 	if (strncmp(line, "sudoers_uid=", sizeof("sudoers_uid=") - 1) == 0) {
280 	    push(&plugin_args, line);
281 	    continue;
282 	}
283 	if (strncmp(line, "ldap_conf=", sizeof("ldap_conf=") - 1) == 0) {
284 	    push(&plugin_args, line);
285 	    continue;
286 	}
287 	if (strncmp(line, "ldap_secret=", sizeof("ldap_secret=") - 1) == 0) {
288 	    push(&plugin_args, line);
289 	    continue;
290 	}
291 
292 	/* user info */
293 	if (strncmp(line, "user=", sizeof("user=") - 1) == 0) {
294 	    push(&user_info, line);
295 	    continue;
296 	}
297 	if (strncmp(line, "uid=", sizeof("uid=") - 1) == 0) {
298 	    push(&user_info, line);
299 	    continue;
300 	}
301 	if (strncmp(line, "gid=", sizeof("gid=") - 1) == 0) {
302 	    push(&user_info, line);
303 	    continue;
304 	}
305 	if (strncmp(line, "groups=", sizeof("groups=") - 1) == 0) {
306 	    push(&user_info, line);
307 	    continue;
308 	}
309 	if (strncmp(line, "cwd=", sizeof("cwd=") - 1) == 0) {
310 	    push(&user_info, line);
311 	    continue;
312 	}
313 	if (strncmp(line, "tty=", sizeof("tty=") - 1) == 0) {
314 	    push(&user_info, line);
315 	    continue;
316 	}
317 	if (strncmp(line, "host=", sizeof("host=") - 1) == 0) {
318 	    push(&user_info, line);
319 	    continue;
320 	}
321 	if (strncmp(line, "lines=", sizeof("lines=") - 1) == 0) {
322 	    push(&user_info, line);
323 	    continue;
324 	}
325 	if (strncmp(line, "cols=", sizeof("cols=") - 1) == 0) {
326 	    push(&user_info, line);
327 	    continue;
328 	}
329 	if (strncmp(line, "sid=", sizeof("sid=") - 1) == 0) {
330 	    push(&user_info, line);
331 	    continue;
332 	}
333 	if (strncmp(line, "umask=", sizeof("umask=") - 1) == 0) {
334 	    push(&user_info, line);
335 	    continue;
336 	}
337 	if (strncmp(line, "rlimit_", sizeof("rlimit_") - 1) == 0) {
338 	    push(&user_info, line);
339 	    continue;
340 	}
341 
342 	/* First argv entry is the command, the rest are args. */
343 	if (strncmp(line, "argv=", sizeof("argv=") - 1) == 0) {
344 	    push(&argv, line);
345 	    continue;
346 	}
347 
348 	/* Additional environment variables to add. */
349 	if (strncmp(line, "env=", sizeof("env=") - 1) == 0) {
350 	    push(&env_add, line);
351 	    continue;
352 	}
353 
354 	/* Treat anything else as a setting. */
355 	push(&settings, line);
356     }
357     fclose(fp);
358     free(line);
359     line = NULL;
360 
361     /* Exercise code paths that use KRB5CCNAME and SUDO_PROMPT. */
362     putenv("KRB5CCNAME=/tmp/krb5cc_123456");
363     putenv("SUDO_PROMPT=[sudo] password for %p: ");
364 
365     sudoers_policy.register_hooks(SUDO_API_VERSION, fuzz_hook_stub);
366 
367     for (pass = 1; res == 1 && pass <= num_passes; pass++) {
368 	/* Call policy open function */
369 	res = sudoers_policy.open(SUDO_API_VERSION, fuzz_conversation,
370 	    fuzz_printf, settings.entries, user_info.entries, environ,
371 	    plugin_args.entries, &errstr);
372 	if (res == 1) {
373 	    if (argv.len == 0) {
374 		/* Must have a command to check. */
375 		push(&argv, "/usr/bin/id");
376 	    }
377 
378 	    switch (pass) {
379 	    case PASS_NONE:
380 		break;
381 	    case PASS_VERSION:
382 		/* sudo -V */
383 		sudoers_policy.show_version(true);
384 		break;
385 	    case PASS_CHECK_LOG_LOCAL: {
386 		/* sudo command w/ local I/O logging (MODE_RUN) */
387 		sudoers_policy.check_policy(argv.len, argv.entries,
388 		    env_add.entries, &command_info, &argv_out, &user_env_out,
389 		    &errstr);
390 		/* call check_policy() again to check for leaks. */
391 		sudoers_policy.check_policy(argv.len, argv.entries,
392 		    env_add.entries, &command_info, &argv_out, &user_env_out,
393 		    &errstr);
394 		/* sudo_auth_begin_session() is stubbed out below. */
395 		sudoers_policy.init_session(NULL, NULL, NULL);
396 		break;
397 	    }
398 	    case PASS_CHECK_LOG_REMOTE:
399 		/* sudo command w/ remote I/O logging (MODE_RUN) */
400 		sudoers_policy.check_policy(argv.len, argv.entries,
401 		    env_add.entries, &command_info, &argv_out, &user_env_out,
402 		    &errstr);
403 		/* call check_policy() again to check for leaks. */
404 		sudoers_policy.check_policy(argv.len, argv.entries,
405 		    env_add.entries, &command_info, &argv_out, &user_env_out,
406 		    &errstr);
407 		/* sudo_auth_begin_session() is stubbed out below. */
408 		sudoers_policy.init_session(NULL, NULL, NULL);
409 		break;
410 	    case PASS_CHECK_NOT_FOUND:
411 		/* sudo command (not found) */
412 		sudoers_policy.check_policy(argv.len, argv.entries,
413 		    env_add.entries, &command_info, &argv_out, &user_env_out,
414 		    &errstr);
415 		/* sudo_auth_begin_session() is stubbed out below. */
416 		sudoers_policy.init_session(NULL, NULL, NULL);
417 		break;
418 	    case PASS_CHECK_NOT_FOUND_DOT:
419 		/* sudo command (found but in cwd) */
420 		sudoers_policy.check_policy(argv.len, argv.entries,
421 		    env_add.entries, &command_info, &argv_out, &user_env_out,
422 		    &errstr);
423 		/* call check_policy() again to check for leaks. */
424 		sudoers_policy.check_policy(argv.len, argv.entries,
425 		    env_add.entries, &command_info, &argv_out, &user_env_out,
426 		    &errstr);
427 		/* sudo_auth_begin_session() is stubbed out below. */
428 		sudoers_policy.init_session(NULL, NULL, NULL);
429 		break;
430 	    case PASS_LIST:
431 		/* sudo -l (MODE_LIST) */
432 		sudoers_policy.list(0, NULL, false, NULL, &errstr);
433 		/* call list() again to check for leaks. */
434 		sudoers_policy.list(0, NULL, false, NULL, &errstr);
435 		break;
436 	    case PASS_LIST_OTHER:
437 		/* sudo -l -U root (MODE_LIST) */
438 		sudoers_policy.list(0, NULL, false, "root", &errstr);
439 		/* call list() again to check for leaks. */
440 		sudoers_policy.list(0, NULL, false, "root", &errstr);
441 		break;
442 	    case PASS_LIST_CHECK:
443 		/* sudo -l command (MODE_CHECK) */
444 		sudoers_policy.list(argv.len, argv.entries, false, NULL,
445 		    &errstr);
446 		/* call list() again to check for leaks. */
447 		sudoers_policy.list(argv.len, argv.entries, false, NULL,
448 		    &errstr);
449 		break;
450 	    case PASS_VALIDATE:
451 		/* sudo -v (MODE_VALIDATE) */
452 		sudoers_policy.validate(&errstr);
453 		/* call validate() again to check for leaks. */
454 		sudoers_policy.validate(&errstr);
455 		break;
456 	    case PASS_INVALIDATE:
457 		/* sudo -k */
458 		sudoers_policy.invalidate(false);
459 		/* call invalidate() again to check for leaks. */
460 		sudoers_policy.invalidate(false);
461 		break;
462 	    }
463 	}
464 
465 	/* Free resources. */
466 	if (sudoers_policy.close != NULL)
467 	    sudoers_policy.close(0, 0);
468 	else
469 	    sudoers_cleanup();
470 
471 	/* Call a second time to free old env pointer. */
472 	env_init(NULL);
473     }
474 
475     sudoers_policy.deregister_hooks(SUDO_API_VERSION, fuzz_hook_stub);
476     sudoers_gc_run();
477 
478     free_dynamic_array(&plugin_args);
479     free_dynamic_array(&settings);
480     free_dynamic_array(&user_info);
481     free_dynamic_array(&argv);
482     free_dynamic_array(&env_add);
483 
484     sudoers_debug_deregister();
485 
486     fflush(stdout);
487 
488     return 0;
489 }
490 
491 /* STUB */
492 bool
user_is_exempt(void)493 user_is_exempt(void)
494 {
495     return false;
496 }
497 
498 /* STUB */
499 bool
set_interfaces(const char * ai)500 set_interfaces(const char *ai)
501 {
502     return true;
503 }
504 
505 /* STUB */
506 void
dump_interfaces(const char * ai)507 dump_interfaces(const char *ai)
508 {
509     return;
510 }
511 
512 /* STUB */
513 void
dump_auth_methods(void)514 dump_auth_methods(void)
515 {
516     return;
517 }
518 
519 /* STUB */
520 int
sudo_auth_begin_session(struct passwd * pw,char ** user_env[])521 sudo_auth_begin_session(struct passwd *pw, char **user_env[])
522 {
523     return 1;
524 }
525 
526 /* STUB */
527 int
sudo_auth_end_session(struct passwd * pw)528 sudo_auth_end_session(struct passwd *pw)
529 {
530     return 1;
531 }
532 
533 /* STUB */
534 bool
sudo_auth_needs_end_session(void)535 sudo_auth_needs_end_session(void)
536 {
537     return false;
538 }
539 
540 /* STUB */
541 int
timestamp_remove(bool unlink_it)542 timestamp_remove(bool unlink_it)
543 {
544     return true;
545 }
546 
547 /* STUB */
548 int
create_admin_success_flag(void)549 create_admin_success_flag(void)
550 {
551     return true;
552 }
553 
554 /* STUB */
555 static int
sudo_file_open(struct sudo_nss * nss)556 sudo_file_open(struct sudo_nss *nss)
557 {
558     return 0;
559 }
560 
561 /* STUB */
562 static int
sudo_file_close(struct sudo_nss * nss)563 sudo_file_close(struct sudo_nss *nss)
564 {
565     return 0;
566 }
567 
568 /* STUB */
569 static struct sudoers_parse_tree *
sudo_file_parse(struct sudo_nss * nss)570 sudo_file_parse(struct sudo_nss *nss)
571 {
572     static struct sudoers_parse_tree parse_tree;
573 
574     return &parse_tree;
575 }
576 
577 /* STUB */
578 static int
sudo_file_query(struct sudo_nss * nss,struct passwd * pw)579 sudo_file_query(struct sudo_nss *nss, struct passwd *pw)
580 {
581     return 0;
582 }
583 
584 /* STUB */
585 static int
sudo_file_getdefs(struct sudo_nss * nss)586 sudo_file_getdefs(struct sudo_nss *nss)
587 {
588     /* Set some Defaults */
589     set_default("log_input", NULL, true, "sudoers", 1, 1, false);
590     set_default("log_output", NULL, true, "sudoers", 1, 1, false);
591     set_default("env_file", "/dev/null", true, "sudoers", 1, 1, false);
592     set_default("restricted_env_file", "/dev/null", true, "sudoers", 1, 1, false);
593     set_default("exempt_group", "sudo", true, "sudoers", 1, 1, false);
594     set_default("runchroot", "/", true, "sudoers", 1, 1, false);
595     set_default("runcwd", "~", true, "sudoers", 1, 1, false);
596     set_default("fqdn", NULL, true, "sudoers", 1, 1, false);
597     set_default("runas_default", "root", true, "sudoers", 1, 1, false);
598     set_default("tty_tickets", NULL, true, "sudoers", 1, 1, false);
599     set_default("umask", "022", true, "sudoers", 1, 1, false);
600     set_default("logfile", "/var/log/sudo", true, "sudoers", 1, 1, false);
601     set_default("syslog", "auth", true, "sudoers", 1, 1, false);
602     set_default("syslog_goodpri", "notice", true, "sudoers", 1, 1, false);
603     set_default("syslog_badpri", "alert", true, "sudoers", 1, 1, false);
604     set_default("syslog_maxlen", "2048", true, "sudoers", 1, 1, false);
605     set_default("loglinelen", "0", true, "sudoers", 1, 1, false);
606     set_default("log_year", NULL, true, "sudoers", 1, 1, false);
607     set_default("log_host", NULL, true, "sudoers", 1, 1, false);
608     set_default("mailerpath", NULL, false, "sudoers", 1, 1, false);
609     set_default("mailerflags", "-t", true, "sudoers", 1, 1, false);
610     set_default("mailto", "root@localhost", true, "sudoers", 1, 1, false);
611     set_default("mailfrom", "sudo@sudo.ws", true, "sudoers", 1, 1, false);
612     set_default("mailsub", "Someone has been naughty on %h", true, "sudoers", 1, 1, false);
613     set_default("timestampowner", "#0", true, "sudoers", 1, 1, false);
614     set_default("compress_io", NULL, true, "sudoers", 1, 1, false);
615     set_default("iolog_flush", NULL, true, "sudoers", 1, 1, false);
616     set_default("iolog_flush", NULL, true, "sudoers", 1, 1, false);
617     set_default("maxseq", "2176782336", true, "sudoers", 1, 1, false);
618     set_default("sudoedit_checkdir", NULL, false, "sudoers", 1, 1, false);
619     set_default("sudoedit_follow", NULL, true, "sudoers", 1, 1, false);
620     set_default("ignore_iolog_errors", NULL, true, "sudoers", 1, 1, false);
621     set_default("ignore_iolog_errors", NULL, true, "sudoers", 1, 1, false);
622     set_default("noexec", NULL, true, "sudoers", 1, 1, false);
623     set_default("exec_background", NULL, true, "sudoers", 1, 1, false);
624     set_default("use_pty", NULL, true, "sudoers", 1, 1, false);
625     set_default("utmp_runas", NULL, true, "sudoers", 1, 1, false);
626     set_default("iolog_mode", "0640", true, "sudoers", 1, 1, false);
627     set_default("iolog_user", NULL, false, "sudoers", 1, 1, false);
628     set_default("iolog_group", NULL, false, "sudoers", 1, 1, false);
629     if (pass != PASS_CHECK_LOG_LOCAL) {
630 	set_default("log_servers", "localhost", true, "sudoers", 1, 1, false);
631 	set_default("log_server_timeout", "30", true, "sudoers", 1, 1, false);
632 	set_default("log_server_cabundle", "/etc/ssl/cacert.pem", true, "sudoers", 1, 1, false);
633 	set_default("log_server_peer_cert", "/etc/ssl/localhost.crt", true, "sudoers", 1, 1, false);
634 	set_default("log_server_peer_key", "/etc/ssl/private/localhost.key", true, "sudoers", 1, 1, false);
635     }
636 
637     return 0;
638 }
639 
640 static struct sudo_nss sudo_nss_file = {
641     { NULL, NULL },
642     sudo_file_open,
643     sudo_file_close,
644     sudo_file_parse,
645     sudo_file_query,
646     sudo_file_getdefs
647 };
648 
649 struct sudo_nss_list *
sudo_read_nss(void)650 sudo_read_nss(void)
651 {
652     static struct sudo_nss_list snl = TAILQ_HEAD_INITIALIZER(snl);
653 
654     if (TAILQ_EMPTY(&snl))
655 	TAILQ_INSERT_TAIL(&snl, &sudo_nss_file, entries);
656 
657     return &snl;
658 }
659 
660 /* STUB */
661 int
check_user(int validated,int mode)662 check_user(int validated, int mode)
663 {
664     return true;
665 }
666 
667 /* STUB */
668 bool
check_user_shell(const struct passwd * pw)669 check_user_shell(const struct passwd *pw)
670 {
671     return true;
672 }
673 
674 /* STUB */
675 void
group_plugin_unload(void)676 group_plugin_unload(void)
677 {
678     return;
679 }
680 
681 bool
log_warning(int flags,const char * fmt,...)682 log_warning(int flags, const char *fmt, ...)
683 {
684     va_list ap;
685 
686     /* Just display on stderr. */
687     va_start(ap, fmt);
688     sudo_vwarn_nodebug(fmt, ap);
689     va_end(ap);
690 
691     return true;
692 }
693 
694 bool
log_warningx(int flags,const char * fmt,...)695 log_warningx(int flags, const char *fmt, ...)
696 {
697     va_list ap;
698 
699     /* Just display on stderr. */
700     va_start(ap, fmt);
701     sudo_vwarnx_nodebug(fmt, ap);
702     va_end(ap);
703 
704     return true;
705 }
706 
707 bool
gai_log_warning(int flags,int errnum,const char * fmt,...)708 gai_log_warning(int flags, int errnum, const char *fmt, ...)
709 {
710     va_list ap;
711 
712     /* Note: ignores errnum */
713     va_start(ap, fmt);
714     sudo_vwarnx_nodebug(fmt, ap);
715     va_end(ap);
716 
717     return true;
718 }
719 
720 /* STUB */
721 bool
log_denial(int status,bool inform_user)722 log_denial(int status, bool inform_user)
723 {
724     return true;
725 }
726 
727 /* STUB */
728 bool
log_failure(int status,int flags)729 log_failure(int status, int flags)
730 {
731     return true;
732 }
733 
734 /* STUB */
735 bool
log_exit_status(int exit_status)736 log_exit_status(int exit_status)
737 {
738     return true;
739 }
740 
741 /* STUB */
742 int
audit_failure(char * const argv[],char const * const fmt,...)743 audit_failure(char *const argv[], char const *const fmt, ...)
744 {
745     return 0;
746 }
747 
748 /* STUB */
749 int
sudoers_lookup(struct sudo_nss_list * snl,struct passwd * pw,int * cmnd_status,int pwflag)750 sudoers_lookup(struct sudo_nss_list *snl, struct passwd *pw, int *cmnd_status,
751     int pwflag)
752 {
753     return VALIDATE_SUCCESS;
754 }
755 
756 /* STUB */
757 int
display_cmnd(struct sudo_nss_list * snl,struct passwd * pw)758 display_cmnd(struct sudo_nss_list *snl, struct passwd *pw)
759 {
760     return true;
761 }
762 
763 /* STUB */
764 int
display_privs(struct sudo_nss_list * snl,struct passwd * pw,bool verbose)765 display_privs(struct sudo_nss_list *snl, struct passwd *pw, bool verbose)
766 {
767     return true;
768 }
769 
770 /* STUB */
771 int
find_path(const char * infile,char ** outfile,struct stat * sbp,const char * path,const char * runchroot,int ignore_dot,char * const * allowlist)772 find_path(const char *infile, char **outfile, struct stat *sbp,
773     const char *path, const char *runchroot, int ignore_dot,
774     char * const *allowlist)
775 {
776     switch (pass) {
777     case PASS_CHECK_NOT_FOUND:
778 	return NOT_FOUND;
779     case PASS_CHECK_NOT_FOUND_DOT:
780 	return NOT_FOUND_DOT;
781     default:
782 	if (infile[0] == '/') {
783 	    *outfile = strdup(infile);
784 	} else {
785 	    if (asprintf(outfile, "/usr/bin/%s", infile) == -1)
786 		*outfile = NULL;
787 	}
788 	if (*outfile == NULL)
789 	    return NOT_FOUND_ERROR;
790 	return FOUND;
791     }
792 }
793 
794 /* STUB */
795 bool
expand_iolog_path(const char * inpath,char * path,size_t pathlen,const struct iolog_path_escape * escapes,void * closure)796 expand_iolog_path(const char *inpath, char *path, size_t pathlen,
797     const struct iolog_path_escape *escapes, void *closure)
798 {
799     return strlcpy(path, inpath, pathlen) < pathlen;
800 }
801 
802 /* STUB */
803 bool
iolog_nextid(char * iolog_dir,char sessid[7])804 iolog_nextid(char *iolog_dir, char sessid[7])
805 {
806     strlcpy(sessid, "000001", 7);
807     return true;
808 }
809 
810 /* STUB */
811 bool
cb_maxseq(const union sudo_defs_val * sd_un)812 cb_maxseq(const union sudo_defs_val *sd_un)
813 {
814     return true;
815 }
816 
817 /* STUB */
818 bool
cb_iolog_user(const union sudo_defs_val * sd_un)819 cb_iolog_user(const union sudo_defs_val *sd_un)
820 {
821     return true;
822 }
823 
824 /* STUB */
825 bool
cb_iolog_group(const union sudo_defs_val * sd_un)826 cb_iolog_group(const union sudo_defs_val *sd_un)
827 {
828     return true;
829 }
830 
831 /* STUB */
832 bool
cb_iolog_mode(const union sudo_defs_val * sd_un)833 cb_iolog_mode(const union sudo_defs_val *sd_un)
834 {
835     return true;
836 }
837 
838 /* STUB */
839 bool
cb_group_plugin(const union sudo_defs_val * sd_un)840 cb_group_plugin(const union sudo_defs_val *sd_un)
841 {
842     return true;
843 }
844