2 * Copyright (c) 1999-2001 Todd C. Miller <Todd.Miller@courtesan.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
19 * 4. Products derived from this software may not be called "Sudo" nor
20 * may "Sudo" appear in their names without specific prior written
21 * permission from the author.
23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
25 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
26 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 #include <sys/types.h>
38 #include <sys/param.h>
47 #endif /* STDC_HEADERS */
51 # ifdef HAVE_STRINGS_H
54 #endif /* HAVE_STRING_H */
57 #endif /* HAVE_UNISTD_H */
63 static const char rcsid[] = "$Sudo: defaults.c,v 1.38 2001/12/30 18:40:09 millert Exp $";
67 * For converting between syslog numbers and strings.
74 #ifdef LOG_NFACILITIES
75 static struct strmap facilities[] = {
77 { "authpriv", LOG_AUTHPRIV },
80 { "daemon", LOG_DAEMON },
82 { "local0", LOG_LOCAL0 },
83 { "local1", LOG_LOCAL1 },
84 { "local2", LOG_LOCAL2 },
85 { "local3", LOG_LOCAL3 },
86 { "local4", LOG_LOCAL4 },
87 { "local5", LOG_LOCAL5 },
88 { "local6", LOG_LOCAL6 },
89 { "local7", LOG_LOCAL7 },
92 #endif /* LOG_NFACILITIES */
94 static struct strmap priorities[] = {
95 { "alert", LOG_ALERT },
97 { "debug", LOG_DEBUG },
98 { "emerg", LOG_EMERG },
100 { "info", LOG_INFO },
101 { "notice", LOG_NOTICE },
102 { "warning", LOG_WARNING },
106 extern int sudolineno;
111 static int store_int __P((char *, struct sudo_defs_types *, int));
112 static int store_uint __P((char *, struct sudo_defs_types *, int));
113 static int store_str __P((char *, struct sudo_defs_types *, int));
114 static int store_syslogfac __P((char *, struct sudo_defs_types *, int));
115 static int store_syslogpri __P((char *, struct sudo_defs_types *, int));
116 static int store_mode __P((char *, struct sudo_defs_types *, int));
117 static int store_pwflag __P((char *, struct sudo_defs_types *, int));
118 static int store_list __P((char *, struct sudo_defs_types *, int));
119 static void list_op __P((char *, size_t, struct sudo_defs_types *, enum list_ops));
122 * Table describing compile-time and run-time options.
124 #include <def_data.c>
127 * Print version and configure info.
132 struct sudo_defs_types *cur;
133 struct list_member *item;
135 for (cur = sudo_defs_table; cur->name; cur++) {
137 switch (cur->type & T_MASK) {
146 if (cur->sd_un.str) {
147 (void) printf(cur->desc, cur->sd_un.str);
153 (void) printf(cur->desc, cur->sd_un.ival);
157 (void) printf(cur->desc, cur->sd_un.mode);
161 if (cur->sd_un.list) {
163 for (item = cur->sd_un.list; item; item = item->next)
164 printf("\t%s\n", item->value);
173 * List each option along with its description.
178 struct sudo_defs_types *cur;
181 (void) puts("Available options in a sudoers ``Defaults'' line:\n");
182 for (cur = sudo_defs_table; cur->name; cur++) {
183 if (cur->name && cur->desc) {
184 switch (cur->type & T_MASK) {
186 (void) printf("%s: %s\n", cur->name, cur->desc);
189 p = strrchr(cur->desc, ':');
191 (void) printf("%s: %.*s\n", cur->name,
192 (int) (p - cur->desc), cur->desc);
194 (void) printf("%s: %s\n", cur->name, cur->desc);
202 * Sets/clears an entry in the defaults structure
203 * If a variable that takes a value is used in a boolean
204 * context with op == 0, disable that variable.
205 * Eg. you may want to turn off logging to a file for some hosts.
206 * This is only meaningful for variables that are *optional*.
209 set_default(var, val, op)
212 int op; /* TRUE or FALSE */
214 struct sudo_defs_types *cur;
217 for (cur = sudo_defs_table, num = 0; cur->name; cur++, num++) {
218 if (strcmp(var, cur->name) == 0)
222 (void) fprintf(stderr,
223 "%s: unknown defaults entry `%s' referenced near line %d\n", Argv[0],
228 switch (cur->type & T_MASK) {
230 if (!store_syslogfac(val, cur, op)) {
232 (void) fprintf(stderr,
233 "%s: value '%s' is invalid for option '%s'\n", Argv[0],
236 (void) fprintf(stderr,
237 "%s: no value specified for `%s' on line %d\n", Argv[0],
243 if (!store_syslogpri(val, cur, op)) {
245 (void) fprintf(stderr,
246 "%s: value '%s' is invalid for option '%s'\n", Argv[0],
249 (void) fprintf(stderr,
250 "%s: no value specified for `%s' on line %d\n", Argv[0],
256 if (!store_pwflag(val, cur, op)) {
258 (void) fprintf(stderr,
259 "%s: value '%s' is invalid for option '%s'\n", Argv[0],
262 (void) fprintf(stderr,
263 "%s: no value specified for `%s' on line %d\n", Argv[0],
270 /* Check for bogus boolean usage or lack of a value. */
271 if (!(cur->type & T_BOOL) || op != FALSE) {
272 (void) fprintf(stderr,
273 "%s: no value specified for `%s' on line %d\n", Argv[0],
278 if ((cur->type & T_PATH) && val && *val != '/') {
279 (void) fprintf(stderr,
280 "%s: values for `%s' must start with a '/'\n", Argv[0],
284 if (!store_str(val, cur, op)) {
285 (void) fprintf(stderr,
286 "%s: value '%s' is invalid for option '%s'\n", Argv[0],
293 /* Check for bogus boolean usage or lack of a value. */
294 if (!(cur->type & T_BOOL) || op != FALSE) {
295 (void) fprintf(stderr,
296 "%s: no value specified for `%s' on line %d\n", Argv[0],
301 if (!store_int(val, cur, op)) {
302 (void) fprintf(stderr,
303 "%s: value '%s' is invalid for option '%s'\n", Argv[0],
310 /* Check for bogus boolean usage or lack of a value. */
311 if (!(cur->type & T_BOOL) || op != FALSE) {
312 (void) fprintf(stderr,
313 "%s: no value specified for `%s' on line %d\n", Argv[0],
318 if (!store_uint(val, cur, op)) {
319 (void) fprintf(stderr,
320 "%s: value '%s' is invalid for option '%s'\n", Argv[0],
327 /* Check for bogus boolean usage or lack of a value. */
328 if (!(cur->type & T_BOOL) || op != FALSE) {
329 (void) fprintf(stderr,
330 "%s: no value specified for `%s' on line %d\n", Argv[0],
335 if (!store_mode(val, cur, op)) {
336 (void) fprintf(stderr,
337 "%s: value '%s' is invalid for option '%s'\n", Argv[0],
344 (void) fprintf(stderr,
345 "%s: option `%s' does not take a value on line %d\n",
346 Argv[0], var, sudolineno);
349 cur->sd_un.flag = op;
351 /* Special action for I_FQDN. Move to own switch if we get more */
352 if (num == I_FQDN && op)
357 /* Check for bogus boolean usage or lack of a value. */
358 if (!(cur->type & T_BOOL) || op != FALSE) {
359 (void) fprintf(stderr,
360 "%s: no value specified for `%s' on line %d\n", Argv[0],
365 if (!store_list(val, cur, op)) {
366 (void) fprintf(stderr,
367 "%s: value '%s' is invalid for option '%s'\n", Argv[0],
377 * Set default options to compiled-in values.
378 * Any of these may be overridden at runtime by a "Defaults" file.
383 static int firsttime = 1;
384 struct sudo_defs_types *def;
386 /* Free any strings that were set. */
388 for (def = sudo_defs_table; def->name; def++)
389 switch (def->type & T_MASK) {
394 if (def->sd_un.str) {
395 free(def->sd_un.str);
396 def->sd_un.str = NULL;
400 list_op(NULL, 0, def, freeall);
405 /* First initialize the flags. */
406 #ifdef LONG_OTP_PROMPT
407 def_flag(I_LONG_OTP_PROMPT) = TRUE;
409 #ifdef IGNORE_DOT_PATH
410 def_flag(I_IGNORE_DOT) = TRUE;
412 #ifdef ALWAYS_SEND_MAIL
413 def_flag(I_MAIL_ALWAYS) = TRUE;
415 #ifdef SEND_MAIL_WHEN_NO_USER
416 def_flag(I_MAIL_NO_USER) = TRUE;
418 #ifdef SEND_MAIL_WHEN_NO_HOST
419 def_flag(I_MAIL_NO_HOST) = TRUE;
421 #ifdef SEND_MAIL_WHEN_NOT_OK
422 def_flag(I_MAIL_NO_PERMS) = TRUE;
424 #ifdef USE_TTY_TICKETS
425 def_flag(I_TTY_TICKETS) = TRUE;
428 def_flag(I_LECTURE) = TRUE;
430 #ifndef NO_AUTHENTICATION
431 def_flag(I_AUTHENTICATE) = TRUE;
434 def_flag(I_ROOT_SUDO) = TRUE;
437 def_flag(I_LOG_HOST) = TRUE;
439 #ifdef SHELL_IF_NO_ARGS
440 def_flag(I_SHELL_NOARGS) = TRUE;
442 #ifdef SHELL_SETS_HOME
443 def_flag(I_SET_HOME) = TRUE;
445 #ifndef DONT_LEAK_PATH_INFO
446 def_flag(I_PATH_INFO) = TRUE;
449 def_flag(I_FQDN) = TRUE;
452 def_flag(I_INSULTS) = TRUE;
455 def_flag(I_ENV_EDITOR) = TRUE;
457 def_flag(I_SET_LOGNAME) = TRUE;
459 /* Syslog options need special care since they both strings and ints */
460 #if (LOGGING & SLOG_SYSLOG)
461 (void) store_syslogfac(LOGFAC, &sudo_defs_table[I_SYSLOG], TRUE);
462 (void) store_syslogpri(PRI_SUCCESS, &sudo_defs_table[I_SYSLOG_GOODPRI],
464 (void) store_syslogpri(PRI_FAILURE, &sudo_defs_table[I_SYSLOG_BADPRI],
468 /* Password flags also have a string and integer component. */
469 (void) store_pwflag("any", &sudo_defs_table[I_LISTPW], TRUE);
470 (void) store_pwflag("all", &sudo_defs_table[I_VERIFYPW], TRUE);
472 /* Then initialize the int-like things. */
474 def_mode(I_UMASK) = SUDO_UMASK;
476 def_mode(I_UMASK) = 0777;
478 def_ival(I_LOGLINELEN) = MAXLOGFILELEN;
479 def_ival(I_TIMESTAMP_TIMEOUT) = TIMEOUT;
480 def_ival(I_PASSWD_TIMEOUT) = PASSWORD_TIMEOUT;
481 def_ival(I_PASSWD_TRIES) = TRIES_FOR_PASSWORD;
483 /* Now do the strings */
484 def_str(I_MAILTO) = estrdup(MAILTO);
485 def_str(I_MAILSUB) = estrdup(MAILSUBJECT);
486 def_str(I_BADPASS_MESSAGE) = estrdup(INCORRECT_PASSWORD);
487 def_str(I_TIMESTAMPDIR) = estrdup(_PATH_SUDO_TIMEDIR);
488 def_str(I_PASSPROMPT) = estrdup(PASSPROMPT);
489 def_str(I_RUNAS_DEFAULT) = estrdup(RUNAS_DEFAULT);
490 #ifdef _PATH_SUDO_SENDMAIL
491 def_str(I_MAILERPATH) = estrdup(_PATH_SUDO_SENDMAIL);
492 def_str(I_MAILERFLAGS) = estrdup("-t");
494 #if (LOGGING & SLOG_FILE)
495 def_str(I_LOGFILE) = estrdup(_PATH_SUDO_LOGFILE);
498 def_str(I_EXEMPT_GROUP) = estrdup(EXEMPTGROUP);
500 def_str(I_EDITOR) = estrdup(EDITOR);
502 /* Finally do the lists (currently just environment tables). */
506 * The following depend on the above values.
507 * We use a pointer to the string so that if its
508 * value changes we get the change.
510 if (user_runas == NULL)
511 user_runas = &def_str(I_RUNAS_DEFAULT);
517 store_int(val, def, op)
519 struct sudo_defs_types *def;
528 l = strtol(val, &endp, 10);
531 /* XXX - should check against INT_MAX */
532 def->sd_un.ival = (unsigned int)l;
538 store_uint(val, def, op)
540 struct sudo_defs_types *def;
549 l = strtol(val, &endp, 10);
550 if (*endp != '\0' || l < 0)
552 /* XXX - should check against INT_MAX */
553 def->sd_un.ival = (unsigned int)l;
559 store_str(val, def, op)
561 struct sudo_defs_types *def;
566 free(def->sd_un.str);
568 def->sd_un.str = NULL;
570 def->sd_un.str = estrdup(val);
575 store_list(str, def, op)
577 struct sudo_defs_types *def;
582 /* Remove all old members. */
583 if (op == FALSE || op == TRUE)
584 list_op(NULL, 0, def, freeall);
586 /* Split str into multiple space-separated words and act on each one. */
590 /* Remove leading blanks, if nothing but blanks we are done. */
591 for (start = end; isblank(*start); start++)
596 /* Find end position and perform operation. */
597 for (end = start; *end && !isblank(*end); end++)
599 list_op(start, end - start, def, op == '-' ? delete : add);
600 } while (*end++ != '\0');
606 store_syslogfac(val, def, op)
608 struct sudo_defs_types *def;
614 if (def->sd_un.str) {
615 free(def->sd_un.str);
616 def->sd_un.str = NULL;
620 #ifdef LOG_NFACILITIES
623 for (fac = facilities; fac->name && strcmp(val, fac->name); fac++)
625 if (fac->name == NULL)
626 return(FALSE); /* not found */
628 /* Store both name and number. */
630 free(def->sd_un.str);
631 def->sd_un.str = estrdup(fac->name);
632 sudo_defs_table[I_LOGFAC].sd_un.ival = fac->num;
635 free(def->sd_un.str);
636 def->sd_un.str = estrdup("default");
637 #endif /* LOG_NFACILITIES */
642 store_syslogpri(val, def, op)
644 struct sudo_defs_types *def;
648 struct sudo_defs_types *idef;
650 if (op == FALSE || !val)
652 if (def == &sudo_defs_table[I_SYSLOG_GOODPRI])
653 idef = &sudo_defs_table[I_GOODPRI];
654 else if (def == &sudo_defs_table[I_SYSLOG_BADPRI])
655 idef = &sudo_defs_table[I_BADPRI];
659 for (pri = priorities; pri->name && strcmp(val, pri->name); pri++)
661 if (pri->name == NULL)
662 return(FALSE); /* not found */
664 /* Store both name and number. */
666 free(def->sd_un.str);
667 def->sd_un.str = estrdup(pri->name);
668 idef->sd_un.ival = pri->num;
673 store_mode(val, def, op)
675 struct sudo_defs_types *def;
682 def->sd_un.mode = (mode_t)0777;
684 l = strtol(val, &endp, 8);
685 if (*endp != '\0' || l < 0 || l > 0777)
687 def->sd_un.mode = (mode_t)l;
693 store_pwflag(val, def, op)
695 struct sudo_defs_types *def;
700 if (strcmp(def->name, "verifypw") == 0)
707 if (def->sd_un.str) {
708 free(def->sd_un.str);
709 def->sd_un.str = NULL;
711 def->sd_un.str = estrdup("never");
712 sudo_defs_table[isub].sd_un.ival = PWCHECK_NEVER;
718 /* Convert strings to integer values. */
719 if (strcmp(val, "all") == 0)
721 else if (strcmp(val, "any") == 0)
723 else if (strcmp(val, "never") == 0)
724 flags = PWCHECK_NEVER;
725 else if (strcmp(val, "always") == 0)
726 flags = PWCHECK_ALWAYS;
730 /* Store both name and number. */
732 free(def->sd_un.str);
733 def->sd_un.str = estrdup(val);
734 sudo_defs_table[isub].sd_un.ival = flags;
740 list_op(val, len, def, op)
743 struct sudo_defs_types *def;
746 struct list_member *cur, *prev, *tmp;
749 for (cur = def->sd_un.list; cur; ) {
755 def->sd_un.list = NULL;
759 for (cur = def->sd_un.list, prev = NULL; cur; prev = cur, cur = cur->next) {
760 if ((strncmp(cur->value, val, len) == 0 && cur->value[len] == '\0')) {
763 return; /* already exists */
767 prev->next = cur->next;
769 def->sd_un.list = cur->next;
776 /* Add new node to the head of the list. */
778 cur = emalloc(sizeof(struct list_member));
779 cur->value = emalloc(len + 1);
780 (void) memcpy(cur->value, val, len);
781 cur->value[len] = '\0';
782 cur->next = def->sd_un.list;
783 def->sd_un.list = cur;