2 * Copyright (c) 1999-2005, 2007-2011
3 * Todd C. Miller <Todd.Miller@courtesan.com>
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 * Sponsored in part by the Defense Advanced Research Projects
18 * Agency (DARPA) and Air Force Research Laboratory, Air Force
19 * Materiel Command, USAF, under agreement number F39502-99-1-0512.
24 #include <sys/types.h>
25 #include <sys/param.h>
34 #endif /* STDC_HEADERS */
37 #endif /* HAVE_STRING_H */
40 #endif /* HAVE_STRINGS_H */
43 #endif /* HAVE_UNISTD_H */
52 * For converting between syslog numbers and strings.
59 #ifdef LOG_NFACILITIES
60 static struct strmap facilities[] = {
62 { "authpriv", LOG_AUTHPRIV },
65 { "daemon", LOG_DAEMON },
67 { "local0", LOG_LOCAL0 },
68 { "local1", LOG_LOCAL1 },
69 { "local2", LOG_LOCAL2 },
70 { "local3", LOG_LOCAL3 },
71 { "local4", LOG_LOCAL4 },
72 { "local5", LOG_LOCAL5 },
73 { "local6", LOG_LOCAL6 },
74 { "local7", LOG_LOCAL7 },
77 #endif /* LOG_NFACILITIES */
79 static struct strmap priorities[] = {
80 { "alert", LOG_ALERT },
82 { "debug", LOG_DEBUG },
83 { "emerg", LOG_EMERG },
86 { "notice", LOG_NOTICE },
87 { "warning", LOG_WARNING },
94 static bool store_int(char *, struct sudo_defs_types *, int);
95 static bool store_list(char *, struct sudo_defs_types *, int);
96 static bool store_mode(char *, struct sudo_defs_types *, int);
97 static bool store_str(char *, struct sudo_defs_types *, int);
98 static bool store_syslogfac(char *, struct sudo_defs_types *, int);
99 static bool store_syslogpri(char *, struct sudo_defs_types *, int);
100 static bool store_tuple(char *, struct sudo_defs_types *, int);
101 static bool store_uint(char *, struct sudo_defs_types *, int);
102 static bool store_float(char *, struct sudo_defs_types *, int);
103 static void list_op(char *, size_t, struct sudo_defs_types *, enum list_ops);
104 static const char *logfac2str(int);
105 static const char *logpri2str(int);
108 * Table describing compile-time and run-time options.
110 #include <def_data.c>
113 * Print version and configure info.
118 struct sudo_defs_types *cur;
119 struct list_member *item;
120 struct def_values *def;
122 debug_decl(dump_defaults, SUDO_DEBUG_DEFAULTS)
124 for (cur = sudo_defs_table; cur->name; cur++) {
127 switch (cur->type & T_MASK) {
130 sudo_printf(SUDO_CONV_INFO_MSG, "%s\n", desc);
133 if (cur->sd_un.str) {
134 sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.str);
135 sudo_printf(SUDO_CONV_INFO_MSG, "\n");
139 if (cur->sd_un.ival) {
140 sudo_printf(SUDO_CONV_INFO_MSG, desc,
141 logfac2str(cur->sd_un.ival));
142 sudo_printf(SUDO_CONV_INFO_MSG, "\n");
146 if (cur->sd_un.ival) {
147 sudo_printf(SUDO_CONV_INFO_MSG, desc,
148 logpri2str(cur->sd_un.ival));
149 sudo_printf(SUDO_CONV_INFO_MSG, "\n");
154 sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.ival);
155 sudo_printf(SUDO_CONV_INFO_MSG, "\n");
158 sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.fval);
159 sudo_printf(SUDO_CONV_INFO_MSG, "\n");
162 sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.mode);
163 sudo_printf(SUDO_CONV_INFO_MSG, "\n");
166 if (cur->sd_un.list) {
167 sudo_printf(SUDO_CONV_INFO_MSG, "%s\n", desc);
168 for (item = cur->sd_un.list; item; item = item->next) {
169 sudo_printf(SUDO_CONV_INFO_MSG,
170 "\t%s\n", item->value);
175 for (def = cur->values; def->sval; def++) {
176 if (cur->sd_un.ival == def->ival) {
177 sudo_printf(SUDO_CONV_INFO_MSG, desc, def->sval);
181 sudo_printf(SUDO_CONV_INFO_MSG, "\n");
190 * Sets/clears an entry in the defaults structure
191 * If a variable that takes a value is used in a boolean
192 * context with op == 0, disable that variable.
193 * Eg. you may want to turn off logging to a file for some hosts.
194 * This is only meaningful for variables that are *optional*.
197 set_default(char *var, char *val, int op)
199 struct sudo_defs_types *cur;
201 debug_decl(set_default, SUDO_DEBUG_DEFAULTS)
203 for (cur = sudo_defs_table, num = 0; cur->name; cur++, num++) {
204 if (strcmp(var, cur->name) == 0)
208 warningx(_("unknown defaults entry `%s'"), var);
209 debug_return_bool(false);
212 switch (cur->type & T_MASK) {
214 if (!store_syslogfac(val, cur, op)) {
216 warningx(_("value `%s' is invalid for option `%s'"),
219 warningx(_("no value specified for `%s'"), var);
220 debug_return_bool(false);
224 if (!store_syslogpri(val, cur, op)) {
226 warningx(_("value `%s' is invalid for option `%s'"),
229 warningx(_("no value specified for `%s'"), var);
230 debug_return_bool(false);
235 /* Check for bogus boolean usage or lack of a value. */
236 if (!ISSET(cur->type, T_BOOL) || op != false) {
237 warningx(_("no value specified for `%s'"), var);
238 debug_return_bool(false);
241 if (ISSET(cur->type, T_PATH) && val && *val != '/') {
242 warningx(_("values for `%s' must start with a '/'"), var);
243 debug_return_bool(false);
245 if (!store_str(val, cur, op)) {
246 warningx(_("value `%s' is invalid for option `%s'"), val, var);
247 debug_return_bool(false);
252 /* Check for bogus boolean usage or lack of a value. */
253 if (!ISSET(cur->type, T_BOOL) || op != false) {
254 warningx(_("no value specified for `%s'"), var);
255 debug_return_bool(false);
258 if (!store_int(val, cur, op)) {
259 warningx(_("value `%s' is invalid for option `%s'"), val, var);
260 debug_return_bool(false);
265 /* Check for bogus boolean usage or lack of a value. */
266 if (!ISSET(cur->type, T_BOOL) || op != false) {
267 warningx(_("no value specified for `%s'"), var);
268 debug_return_bool(false);
271 if (!store_uint(val, cur, op)) {
272 warningx(_("value `%s' is invalid for option `%s'"), val, var);
273 debug_return_bool(false);
278 /* Check for bogus boolean usage or lack of a value. */
279 if (!ISSET(cur->type, T_BOOL) || op != false) {
280 warningx(_("no value specified for `%s'"), var);
281 debug_return_bool(false);
284 if (!store_float(val, cur, op)) {
285 warningx(_("value `%s' is invalid for option `%s'"), val, var);
286 debug_return_bool(false);
291 /* Check for bogus boolean usage or lack of a value. */
292 if (!ISSET(cur->type, T_BOOL) || op != false) {
293 warningx(_("no value specified for `%s'"), var);
294 debug_return_bool(false);
297 if (!store_mode(val, cur, op)) {
298 warningx(_("value `%s' is invalid for option `%s'"), val, var);
299 debug_return_bool(false);
304 warningx(_("option `%s' does not take a value"), var);
305 debug_return_bool(false);
307 cur->sd_un.flag = op;
311 /* Check for bogus boolean usage or lack of a value. */
312 if (!ISSET(cur->type, T_BOOL) || op != false) {
313 warningx(_("no value specified for `%s'"), var);
314 debug_return_bool(false);
317 if (!store_list(val, cur, op)) {
318 warningx(_("value `%s' is invalid for option `%s'"), val, var);
319 debug_return_bool(false);
323 if (!val && !ISSET(cur->type, T_BOOL)) {
324 warningx(_("no value specified for `%s'"), var);
325 debug_return_bool(false);
327 if (!store_tuple(val, cur, op)) {
328 warningx(_("value `%s' is invalid for option `%s'"), val, var);
329 debug_return_bool(false);
334 debug_return_bool(true);
338 * Set default options to compiled-in values.
339 * Any of these may be overridden at runtime by a "Defaults" file.
344 static int firsttime = 1;
345 struct sudo_defs_types *def;
346 debug_decl(init_defaults, SUDO_DEBUG_DEFAULTS)
348 /* Clear any old settings. */
350 for (def = sudo_defs_table; def->name; def++) {
351 switch (def->type & T_MASK) {
353 efree(def->sd_un.str);
354 def->sd_un.str = NULL;
357 list_op(NULL, 0, def, freeall);
360 zero_bytes(&def->sd_un, sizeof(def->sd_un));
364 /* First initialize the flags. */
365 #ifdef LONG_OTP_PROMPT
366 def_long_otp_prompt = true;
368 #ifdef IGNORE_DOT_PATH
369 def_ignore_dot = true;
371 #ifdef ALWAYS_SEND_MAIL
372 def_mail_always = true;
374 #ifdef SEND_MAIL_WHEN_NO_USER
375 def_mail_no_user = true;
377 #ifdef SEND_MAIL_WHEN_NO_HOST
378 def_mail_no_host = true;
380 #ifdef SEND_MAIL_WHEN_NOT_OK
381 def_mail_no_perms = true;
383 #ifndef NO_TTY_TICKETS
384 def_tty_tickets = true;
389 #ifndef NO_AUTHENTICATION
390 def_authenticate = true;
393 def_root_sudo = true;
398 #ifdef SHELL_IF_NO_ARGS
399 def_shell_noargs = true;
401 #ifdef SHELL_SETS_HOME
404 #ifndef DONT_LEAK_PATH_INFO
405 def_path_info = true;
414 def_env_editor = true;
416 #ifdef UMASK_OVERRIDE
417 def_umask_override = true;
419 def_iolog_file = estrdup("%{seq}");
420 def_iolog_dir = estrdup(_PATH_SUDO_IO_LOGDIR);
421 def_sudoers_locale = estrdup("C");
422 def_env_reset = ENV_RESET;
423 def_set_logname = true;
424 def_closefrom = STDERR_FILENO + 1;
426 /* Syslog options need special care since they both strings and ints */
427 #if (LOGGING & SLOG_SYSLOG)
428 (void) store_syslogfac(LOGFAC, &sudo_defs_table[I_SYSLOG], true);
429 (void) store_syslogpri(PRI_SUCCESS, &sudo_defs_table[I_SYSLOG_GOODPRI],
431 (void) store_syslogpri(PRI_FAILURE, &sudo_defs_table[I_SYSLOG_BADPRI],
435 /* Password flags also have a string and integer component. */
436 (void) store_tuple("any", &sudo_defs_table[I_LISTPW], true);
437 (void) store_tuple("all", &sudo_defs_table[I_VERIFYPW], true);
439 /* Then initialize the int-like things. */
441 def_umask = SUDO_UMASK;
445 def_loglinelen = MAXLOGFILELEN;
446 def_timestamp_timeout = TIMEOUT;
447 def_passwd_timeout = PASSWORD_TIMEOUT;
448 def_passwd_tries = TRIES_FOR_PASSWORD;
450 def_compress_io = true;
453 /* Now do the strings */
454 def_mailto = estrdup(MAILTO);
455 def_mailsub = estrdup(_(MAILSUBJECT));
456 def_badpass_message = estrdup(_(INCORRECT_PASSWORD));
457 def_timestampdir = estrdup(_PATH_SUDO_TIMEDIR);
458 def_passprompt = estrdup(_(PASSPROMPT));
459 def_runas_default = estrdup(RUNAS_DEFAULT);
460 #ifdef _PATH_SUDO_SENDMAIL
461 def_mailerpath = estrdup(_PATH_SUDO_SENDMAIL);
462 def_mailerflags = estrdup("-t");
464 #if (LOGGING & SLOG_FILE)
465 def_logfile = estrdup(_PATH_SUDO_LOGFILE);
468 def_exempt_group = estrdup(EXEMPTGROUP);
471 def_secure_path = estrdup(SECURE_PATH);
473 def_editor = estrdup(EDITOR);
476 /* Finally do the lists (currently just environment tables). */
485 * Update the defaults based on what was set by sudoers.
486 * Pass in an OR'd list of which default types to update.
489 update_defaults(int what)
491 struct defaults *def;
493 debug_decl(update_defaults, SUDO_DEBUG_DEFAULTS)
495 tq_foreach_fwd(&defaults, def) {
498 if (ISSET(what, SETDEF_GENERIC) &&
499 !set_default(def->var, def->val, def->op))
503 if (ISSET(what, SETDEF_USER) &&
504 userlist_matches(sudo_user.pw, &def->binding) == ALLOW &&
505 !set_default(def->var, def->val, def->op))
509 if (ISSET(what, SETDEF_RUNAS) &&
510 runaslist_matches(&def->binding, NULL) == ALLOW &&
511 !set_default(def->var, def->val, def->op))
515 if (ISSET(what, SETDEF_HOST) &&
516 hostlist_matches(&def->binding) == ALLOW &&
517 !set_default(def->var, def->val, def->op))
521 if (ISSET(what, SETDEF_CMND) &&
522 cmndlist_matches(&def->binding) == ALLOW &&
523 !set_default(def->var, def->val, def->op))
528 debug_return_bool(rc);
532 store_int(char *val, struct sudo_defs_types *def, int op)
536 debug_decl(store_int, SUDO_DEBUG_DEFAULTS)
541 l = strtol(val, &endp, 10);
543 debug_return_bool(false);
544 /* XXX - should check against INT_MAX */
545 def->sd_un.ival = (int)l;
548 debug_return_bool(def->callback(val));
549 debug_return_bool(true);
553 store_uint(char *val, struct sudo_defs_types *def, int op)
557 debug_decl(store_uint, SUDO_DEBUG_DEFAULTS)
562 l = strtol(val, &endp, 10);
563 if (*endp != '\0' || l < 0)
564 debug_return_bool(false);
565 /* XXX - should check against INT_MAX */
566 def->sd_un.ival = (unsigned int)l;
569 debug_return_bool(def->callback(val));
570 debug_return_bool(true);
574 store_float(char *val, struct sudo_defs_types *def, int op)
578 debug_decl(store_float, SUDO_DEBUG_DEFAULTS)
581 def->sd_un.fval = 0.0;
583 d = strtod(val, &endp);
585 debug_return_bool(false);
586 /* XXX - should check against HUGE_VAL */
590 debug_return_bool(def->callback(val));
591 debug_return_bool(true);
595 store_tuple(char *val, struct sudo_defs_types *def, int op)
597 struct def_values *v;
598 debug_decl(store_tuple, SUDO_DEBUG_DEFAULTS)
601 * Since enums are really just ints we store the value as an ival.
602 * In the future, there may be multiple enums for different tuple
603 * types we want to avoid and special knowledge of the tuple type.
604 * This does assume that the first entry in the tuple enum will
605 * be the equivalent to a boolean "false".
608 def->sd_un.ival = (op == false) ? 0 : 1;
610 for (v = def->values; v->sval != NULL; v++) {
611 if (strcmp(v->sval, val) == 0) {
612 def->sd_un.ival = v->ival;
617 debug_return_bool(false);
620 debug_return_bool(def->callback(val));
621 debug_return_bool(true);
625 store_str(char *val, struct sudo_defs_types *def, int op)
627 debug_decl(store_str, SUDO_DEBUG_DEFAULTS)
629 efree(def->sd_un.str);
631 def->sd_un.str = NULL;
633 def->sd_un.str = estrdup(val);
635 debug_return_bool(def->callback(val));
636 debug_return_bool(true);
640 store_list(char *str, struct sudo_defs_types *def, int op)
643 debug_decl(store_list, SUDO_DEBUG_DEFAULTS)
645 /* Remove all old members. */
646 if (op == false || op == true)
647 list_op(NULL, 0, def, freeall);
649 /* Split str into multiple space-separated words and act on each one. */
653 /* Remove leading blanks, if nothing but blanks we are done. */
654 for (start = end; isblank((unsigned char)*start); start++)
659 /* Find end position and perform operation. */
660 for (end = start; *end && !isblank((unsigned char)*end); end++)
662 list_op(start, end - start, def, op == '-' ? delete : add);
663 } while (*end++ != '\0');
665 debug_return_bool(true);
669 store_syslogfac(char *val, struct sudo_defs_types *def, int op)
672 debug_decl(store_syslogfac, SUDO_DEBUG_DEFAULTS)
675 def->sd_un.ival = false;
676 debug_return_bool(true);
678 #ifdef LOG_NFACILITIES
680 debug_return_bool(false);
681 for (fac = facilities; fac->name && strcmp(val, fac->name); fac++)
683 if (fac->name == NULL)
684 debug_return_bool(false); /* not found */
686 def->sd_un.ival = fac->num;
688 def->sd_un.ival = -1;
689 #endif /* LOG_NFACILITIES */
690 debug_return_bool(true);
696 #ifdef LOG_NFACILITIES
698 debug_decl(logfac2str, SUDO_DEBUG_DEFAULTS)
700 for (fac = facilities; fac->name && fac->num != n; fac++)
702 debug_return_str(fac->name);
705 #endif /* LOG_NFACILITIES */
709 store_syslogpri(char *val, struct sudo_defs_types *def, int op)
712 debug_decl(store_syslogpri, SUDO_DEBUG_DEFAULTS)
714 if (op == false || !val)
715 debug_return_bool(false);
717 for (pri = priorities; pri->name && strcmp(val, pri->name); pri++)
719 if (pri->name == NULL)
720 debug_return_bool(false); /* not found */
722 def->sd_un.ival = pri->num;
723 debug_return_bool(true);
730 debug_decl(logpri2str, SUDO_DEBUG_DEFAULTS)
732 for (pri = priorities; pri->name && pri->num != n; pri++)
734 debug_return_str(pri->name);
738 store_mode(char *val, struct sudo_defs_types *def, int op)
742 debug_decl(store_mode, SUDO_DEBUG_DEFAULTS)
745 def->sd_un.mode = (mode_t)0777;
747 l = strtol(val, &endp, 8);
748 if (*endp != '\0' || l < 0 || l > 0777)
749 debug_return_bool(false);
750 def->sd_un.mode = (mode_t)l;
753 debug_return_bool(def->callback(val));
754 debug_return_bool(true);
758 list_op(char *val, size_t len, struct sudo_defs_types *def, enum list_ops op)
760 struct list_member *cur, *prev, *tmp;
761 debug_decl(list_op, SUDO_DEBUG_DEFAULTS)
764 for (cur = def->sd_un.list; cur; ) {
770 def->sd_un.list = NULL;
774 for (cur = def->sd_un.list, prev = NULL; cur; prev = cur, cur = cur->next) {
775 if ((strncmp(cur->value, val, len) == 0 && cur->value[len] == '\0')) {
778 debug_return; /* already exists */
782 prev->next = cur->next;
784 def->sd_un.list = cur->next;
791 /* Add new node to the head of the list. */
793 cur = emalloc(sizeof(struct list_member));
794 cur->value = emalloc(len + 1);
795 (void) memcpy(cur->value, val, len);
796 cur->value[len] = '\0';
797 cur->next = def->sd_un.list;
798 def->sd_un.list = cur;