diff options
author | 1999-11-18 16:29:01 +0000 | |
---|---|---|
committer | 1999-11-18 16:29:01 +0000 | |
commit | ee4a81dac7260aeb8b39c7b51d451b215a8821f1 (patch) | |
tree | e7ce36a1f0161cd43c76d6b6cc71a3721ed0b8cc /usr.bin/sudo/defaults.c | |
parent | more %d vs. %s in fmt-strings (diff) | |
download | wireguard-openbsd-ee4a81dac7260aeb8b39c7b51d451b215a8821f1.tar.xz wireguard-openbsd-ee4a81dac7260aeb8b39c7b51d451b215a8821f1.zip |
sudo 1.6, now with a BSD license
Diffstat (limited to 'usr.bin/sudo/defaults.c')
-rw-r--r-- | usr.bin/sudo/defaults.c | 679 |
1 files changed, 679 insertions, 0 deletions
diff --git a/usr.bin/sudo/defaults.c b/usr.bin/sudo/defaults.c new file mode 100644 index 00000000000..11b57d6cc11 --- /dev/null +++ b/usr.bin/sudo/defaults.c @@ -0,0 +1,679 @@ +/* + * Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. Products derived from this software may not be called "Sudo" nor + * may "Sudo" appear in their names without specific prior written + * permission from the author. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include <stdio.h> +#ifdef STDC_HEADERS +#include <stdlib.h> +#endif /* STDC_HEADERS */ +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif /* HAVE_UNISTD_H */ +#ifdef HAVE_STRING_H +#include <string.h> +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +#include <strings.h> +#endif /* HAVE_STRINGS_H */ +#include <sys/types.h> +#include <sys/param.h> + +#include "sudo.h" + +#ifndef lint +static const char rcsid[] = "$Sudo: defaults.c,v 1.12 1999/11/05 22:11:55 millert Exp $"; +#endif /* lint */ + +/* + * For converting between syslog numbers and strings. + */ +struct strmap { + char *name; + int num; +}; + +#ifdef LOG_NFACILITIES +static struct strmap facilities[] = { +#ifdef LOG_AUTHPRIV + { "authpriv", LOG_AUTHPRIV }, +#endif + { "auth", LOG_AUTH }, + { "daemon", LOG_DAEMON }, + { "user", LOG_USER }, + { "local0", LOG_LOCAL0 }, + { "local1", LOG_LOCAL1 }, + { "local2", LOG_LOCAL2 }, + { "local3", LOG_LOCAL3 }, + { "local4", LOG_LOCAL4 }, + { "local5", LOG_LOCAL5 }, + { "local6", LOG_LOCAL6 }, + { "local7", LOG_LOCAL7 }, + { NULL, -1 } +}; +#endif /* LOG_NFACILITIES */ + +static struct strmap priorities[] = { + { "alert", LOG_ALERT }, + { "crit", LOG_CRIT }, + { "debug", LOG_DEBUG }, + { "emerg", LOG_EMERG }, + { "err", LOG_ERR }, + { "info", LOG_INFO }, + { "notice", LOG_NOTICE }, + { "warning", LOG_WARNING }, + { NULL, -1 } +}; + +extern int sudolineno; + +/* + * Local prototypes. + */ +static int store_int __P((char *, struct sudo_defs_types *, int)); +static int store_str __P((char *, struct sudo_defs_types *, int)); +static int store_syslogfac __P((char *, struct sudo_defs_types *, int)); +static int store_syslogpri __P((char *, struct sudo_defs_types *, int)); +static int store_mode __P((char *, struct sudo_defs_types *, int)); + +/* + * Table describing compile-time and run-time options. + */ +struct sudo_defs_types sudo_defs_table[] = { + { + "syslog_ifac", T_INT, { 0 }, + NULL + }, { + "syslog_igoodpri", T_INT, { 0 }, + NULL + }, { + "syslog_ibadpri", T_INT, { 0 }, + NULL + }, { + "syslog", T_LOGFAC|T_BOOL, { 0 }, + "Syslog facility if syslog is being used for logging: %s" + }, { + "syslog_goodpri", T_LOGPRI, { 0 }, + "Syslog priority to use when user authenticates successfully: %s" + }, { + "syslog_badpri", T_LOGPRI, { 0 }, + "Syslog priority to use when user authenticates unsuccessfully: %s" + }, { + "long_otp_prompt", T_FLAG, { 0 }, + "Put OTP prompt on its own line" + }, { + "ignore_dot", T_FLAG, { 0 }, + "Ignore '.' in $PATH" + }, { + "mail_always", T_FLAG, { 0 }, + "Always send mail when sudo is run" + }, { + "mail_no_user", T_FLAG, { 0 }, + "Send mail if the user is not in sudoers" + }, { + "mail_no_host", T_FLAG, { 0 }, + "Send mail if the user is not in sudoers for this host" + }, { + "mail_no_perms", T_FLAG, { 0 }, + "Send mail if the user is not allowed to run a command" + }, { + "tty_tickets", T_FLAG, { 0 }, + "Use a separate timestamp for each user/tty combo" + }, { + "lecture", T_FLAG, { 0 }, + "Lecture user the first time they run sudo" + }, { + "authenticate", T_FLAG, { 0 }, + "Require users to authenticate by default" + }, { + "root_sudo", T_FLAG, { 0 }, + "Root may run sudo" + }, { + "log_host", T_FLAG, { 0 }, + "Log the hostname in the (non-syslog) log file" + }, { + "log_year", T_FLAG, { 0 }, + "Log the year in the (non-syslog) log file" + }, { + "shell_noargs", T_FLAG, { 0 }, + "If sudo is invoked with no arguments, start a shell" + }, { + "set_home", T_FLAG, { 0 }, + "Set $HOME to the target user when starting a shell with -s" + }, { + "path_info", T_FLAG, { 0 }, + "Allow some information gathering to give useful error messages" + }, { + "fqdn", T_FLAG, { 0 }, + "Require fully-qualified hsotnames in the sudoers file" + }, { + "insults", T_FLAG, { 0 }, + "Insult the user when they enter an incorrect password" + }, { + "requiretty", T_FLAG, { 0 }, + "Only allow the user to run sudo if they have a tty" + }, { + "loglinelen", T_INT|T_BOOL, { 0 }, + "Length at which to wrap log file lines (0 for no wrap): %d" + }, { + "timestamp_timeout", T_INT|T_BOOL, { 0 }, + "Authentication timestamp timeout: %d minutes" + }, { + "passwd_timeout", T_INT|T_BOOL, { 0 }, + "Password prompt timeout: %d minutes" + }, { + "passwd_tries", T_INT, { 0 }, + "Number of tries to enter a password: %d" + }, { + "umask", T_MODE|T_BOOL, { 0 }, + "Umask to use or 0777 to use user's: 0%o" + }, { + "logfile", T_STR|T_BOOL|T_PATH, { 0 }, + "Path to log file: %s" + }, { + "mailerpath", T_STR|T_BOOL|T_PATH, { 0 }, + "Path to mail program: %s" + }, { + "mailerflags", T_STR|T_BOOL, { 0 }, + "Flags for mail program: %s" + }, { + "mailto", T_STR|T_BOOL, { 0 }, + "Address to send mail to: %s" + }, { + "mailsub", T_STR, { 0 }, + "Subject line for mail messages: %s" + }, { + "badpass_message", T_STR, { 0 }, + "Incorrect password message: %s" + }, { + "timestampdir", T_STR|T_PATH, { 0 }, + "Path to authentication timestamp dir: %s" + }, { + "exempt_group", T_STR|T_BOOL, { 0 }, + "Users in this group are exempt from password and PATH requirements: %s" + }, { + "passprompt", T_STR, { 0 }, + "Default password prompt: %s" + }, { + "runas_default", T_STR, { 0 }, + "Default user to run commands as: %s" + }, { + "secure_path", T_STR|T_BOOL, { 0 }, + "Value to override user's $PATH with: %s" + }, { + NULL, 0, { 0 }, NULL + } +}; + +/* + * Print version and configure info. + */ +void +dump_defaults() +{ + struct sudo_defs_types *cur; + + for (cur = sudo_defs_table; cur->name; cur++) { + if (cur->desc) { + switch (cur->type & T_MASK) { + case T_FLAG: + if (cur->sd_un.flag) + puts(cur->desc); + break; + case T_STR: + case T_LOGFAC: + case T_LOGPRI: + if (cur->sd_un.str) { + (void) printf(cur->desc, cur->sd_un.str); + putchar('\n'); + } + break; + case T_INT: + (void) printf(cur->desc, cur->sd_un.ival); + putchar('\n'); + break; + case T_MODE: + (void) printf(cur->desc, cur->sd_un.mode); + putchar('\n'); + break; + } + } + } + +#ifdef ENV_EDITOR + (void) printf("Default editor for visudo: %s\n", EDITOR); +#else + (void) printf("Editor for visudo: %s\n", EDITOR); +#endif +} + +/* + * List each option along with its description. + */ +void +list_options() +{ + struct sudo_defs_types *cur; + char *p; + + (void) puts("Available options in a sudoers ``Defaults'' line:\n"); + for (cur = sudo_defs_table; cur->name; cur++) { + if (cur->name && cur->desc) { + switch (cur->type & T_MASK) { + case T_FLAG: + (void) printf("%s: %s\n", cur->name, cur->desc); + break; + default: + p = strrchr(cur->desc, ':'); + if (p) + (void) printf("%s: %.*s\n", cur->name, p - cur->desc, + cur->desc); + else + (void) printf("%s: %s\n", cur->name, cur->desc); + break; + } + } + } +} + +/* + * Sets/clears an entry in the defaults structure + * If a variable that takes a value is used in a boolean + * context with op == 0, disable that variable. + * Eg. you may want to turn off logging to a file for some hosts. + * This is only meaningful for variables that are *optional*. + */ +int +set_default(var, val, op) + char *var; + char *val; + int op; /* TRUE or FALSE */ +{ + struct sudo_defs_types *cur; + + for (cur = sudo_defs_table; cur->name; cur++) { + if (strcmp(var, cur->name) == 0) + break; + } + if (!cur->name) { + (void) fprintf(stderr, + "%s: unknown defaults entry `%s' referenced near line %d\n", Argv[0], + var, sudolineno); + return(FALSE); + } + + switch (cur->type & T_MASK) { + case T_LOGFAC: + if (!store_syslogfac(val, cur, op)) { + if (val) + (void) fprintf(stderr, + "%s: value '%s' is invalid for option '%s'\n", Argv[0], + val, var); + else + (void) fprintf(stderr, + "%s: no value specified for `%s' on line %d\n", Argv[0], + var, sudolineno); + return(FALSE); + } + break; + case T_LOGPRI: + if (!store_syslogpri(val, cur, op)) { + if (val) + (void) fprintf(stderr, + "%s: value '%s' is invalid for option '%s'\n", Argv[0], + val, var); + else + (void) fprintf(stderr, + "%s: no value specified for `%s' on line %d\n", Argv[0], + var, sudolineno); + return(FALSE); + } + break; + case T_STR: + if (!val) { + /* Check for bogus boolean usage or lack of a value. */ + if (!(cur->type & T_BOOL) || op != FALSE) { + (void) fprintf(stderr, + "%s: no value specified for `%s' on line %d\n", Argv[0], + var, sudolineno); + return(FALSE); + } + } + if ((cur->type & T_PATH) && *val != '/') { + (void) fprintf(stderr, + "%s: values for `%s' must start with a '/'\n", Argv[0], + var); + return(FALSE); + } + if (!store_str(val, cur, op)) { + (void) fprintf(stderr, + "%s: value '%s' is invalid for option '%s'\n", Argv[0], + val, var); + return(FALSE); + } + break; + case T_INT: + if (!val) { + /* Check for bogus boolean usage or lack of a value. */ + if (!(cur->type & T_BOOL) || op != FALSE) { + (void) fprintf(stderr, + "%s: no value specified for `%s' on line %d\n", Argv[0], + var, sudolineno); + return(FALSE); + } + } + if (!store_int(val, cur, op)) { + (void) fprintf(stderr, + "%s: value '%s' is invalid for option '%s'\n", Argv[0], + val, var); + return(FALSE); + } + break; + case T_MODE: + if (!val) { + /* Check for bogus boolean usage or lack of a value. */ + if (!(cur->type & T_BOOL) || op != FALSE) { + (void) fprintf(stderr, + "%s: no value specified for `%s' on line %d\n", Argv[0], + var, sudolineno); + return(FALSE); + } + } + if (!store_mode(val, cur, op)) { + (void) fprintf(stderr, + "%s: value '%s' is invalid for option '%s'\n", Argv[0], + val, var); + return(FALSE); + } + break; + case T_FLAG: + if (val) { + (void) fprintf(stderr, + "%s: option `%s' does not take a value on line %d\n", + Argv[0], var, sudolineno); + return(FALSE); + } + cur->sd_un.flag = op; + break; + } + + return(TRUE); +} + +/* + * Set default options to compiled-in values. + * Any of these may be overridden at runtime by a "Defaults" file. + */ +void +init_defaults() +{ + static int firsttime = 1; + struct sudo_defs_types *def; + + /* Free any strings that were set. */ + if (!firsttime) { + for (def = sudo_defs_table; def->name; def++) + switch (def->type & T_MASK) { + case T_STR: + case T_LOGFAC: + case T_LOGPRI: + if (def->sd_un.str) { + free(def->sd_un.str); + def->sd_un.str = NULL; + } + break; + } + } + + /* First initialize the flags. */ +#ifdef LONG_OTP_PROMPT + def_flag(I_LONG_OTP_PROMPT) = TRUE; +#endif +#ifdef IGNORE_DOT_PATH + def_flag(I_IGNORE_DOT) = TRUE; +#endif +#ifdef ALWAYS_SEND_MAIL + def_flag(I_MAIL_ALWAYS) = TRUE; +#endif +#ifdef SEND_MAIL_WHEN_NO_USER + def_flag(I_MAIL_NOUSER) = TRUE; +#endif +#ifdef SEND_MAIL_WHEN_NO_HOST + def_flag(I_MAIL_NOHOST) = TRUE; +#endif +#ifdef SEND_MAIL_WHEN_NOT_OK + def_flag(I_MAIL_NOPERMS) = TRUE; +#endif +#ifdef USE_TTY_TICKETS + def_flag(I_TTY_TICKETS) = TRUE; +#endif +#ifndef NO_LECTURE + def_flag(I_LECTURE) = TRUE; +#endif +#ifndef NO_AUTHENTICATION + def_flag(I_AUTHENTICATE) = TRUE; +#endif +#ifndef NO_ROOT_SUDO + def_flag(I_ROOT_SUDO) = TRUE; +#endif +#ifdef HOST_IN_LOG + def_flag(I_LOG_HOST) = TRUE; +#endif +#ifdef SHELL_IF_NO_ARGS + def_flag(I_SHELL_NOARGS) = TRUE; +#endif +#ifdef SHELL_SETS_HOME + def_flag(I_SET_HOME) = TRUE; +#endif +#ifndef DONT_LEAK_PATH_INFO + def_flag(I_PATH_INFO) = TRUE; +#endif +#ifdef FQDN + def_flag(I_FQDN) = TRUE; +#endif +#ifdef USE_INSULTS + def_flag(I_INSULTS) = TRUE; +#endif + + /* Syslog options need special care since they both strings and ints */ +#if (LOGGING & SLOG_SYSLOG) + (void) store_syslogfac(LOGFAC, &sudo_defs_table[I_LOGFACSTR], TRUE); + (void) store_syslogpri(PRI_SUCCESS, &sudo_defs_table[I_GOODPRISTR], TRUE); + (void) store_syslogpri(PRI_FAILURE, &sudo_defs_table[I_BADPRISTR], TRUE); +#endif + + /* Then initialize the int-like things. */ +#ifdef SUDO_UMASK + def_mode(I_UMASK) = SUDO_UMASK; +#else + def_mode(I_UMASK) = 0777; +#endif + def_ival(I_LOGLEN) = MAXLOGFILELEN; + def_ival(I_TS_TIMEOUT) = TIMEOUT; + def_ival(I_PW_TIMEOUT) = PASSWORD_TIMEOUT; + def_ival(I_PW_TRIES) = TRIES_FOR_PASSWORD; + + /* Finally do the strings */ + def_str(I_MAILTO) = estrdup(MAILTO); + def_str(I_MAILSUB) = estrdup(MAILSUBJECT); + def_str(I_BADPASS_MSG) = estrdup(INCORRECT_PASSWORD); + def_str(I_TIMESTAMPDIR) = estrdup(_PATH_SUDO_TIMEDIR); + def_str(I_PASSPROMPT) = estrdup(PASSPROMPT); + def_str(I_RUNAS_DEF) = estrdup(RUNAS_DEFAULT); +#ifdef _PATH_SENDMAIL + def_str(I_MAILERPATH) = estrdup(_PATH_SENDMAIL); + def_str(I_MAILERFLAGS) = estrdup("-t"); +#endif +#if (LOGGING & SLOG_FILE) + def_str(I_LOGFILE) = estrdup(_PATH_SUDO_LOGFILE); +#endif +#ifdef EXEMPTGROUP + def_str(I_EXEMPT_GRP) = estrdup(EXEMPTGROUP); +#endif +#ifdef SECURE_PATH + def_str(I_SECURE_PATH) = estrdup(SECURE_PATH); +#endif + + /* + * The following depend on the above values. + * We use a pointer to the string so that if its + * value changes we get the change. + */ + if (user_runas == NULL) + user_runas = &def_str(I_RUNAS_DEF); + + firsttime = 0; +} + +static int +store_int(val, def, op) + char *val; + struct sudo_defs_types *def; + int op; +{ + char *endp; + long l; + + if (op == FALSE) { + def->sd_un.ival = 0; + } else { + l = strtol(val, &endp, 10); + if (*endp != '\0' || l < 0) + return(FALSE); + /* XXX - should check against INT_MAX */ + def->sd_un.ival = (unsigned int)l; + } + return(TRUE); +} + +static int +store_str(val, def, op) + char *val; + struct sudo_defs_types *def; + int op; +{ + + if (def->sd_un.str) + free(def->sd_un.str); + if (op == FALSE) + def->sd_un.str = NULL; + else + def->sd_un.str = estrdup(val); + return(TRUE); +} + +static int +store_syslogfac(val, def, op) + char *val; + struct sudo_defs_types *def; + int op; +{ + struct strmap *fac; + + if (op == FALSE) { + free(def->sd_un.str); + def->sd_un.str = NULL; + return(TRUE); + } +#ifdef LOG_NFACILITIES + if (!val) + return(FALSE); + for (fac = facilities; fac->name && strcmp(val, fac->name); fac++) + ; + if (fac->name == NULL) + return(FALSE); /* not found */ + + /* Store both name and number. */ + if (def->sd_un.str) + free(def->sd_un.str); + def->sd_un.str = estrdup(fac->name); + sudo_defs_table[I_LOGFAC].sd_un.ival = fac->num; +#else + if (def->sd_un.str) + free(def->sd_un.str); + def->sd_un.str = estrdup("default"); +#endif /* LOG_NFACILITIES */ + return(TRUE); +} + +static int +store_syslogpri(val, def, op) + char *val; + struct sudo_defs_types *def; + int op; +{ + struct strmap *pri; + struct sudo_defs_types *idef; + + if (op == FALSE || !val) + return(FALSE); + if (def == &sudo_defs_table[I_GOODPRISTR]) + idef = &sudo_defs_table[I_GOODPRI]; + else if (def == &sudo_defs_table[I_BADPRISTR]) + idef = &sudo_defs_table[I_BADPRI]; + else + return(FALSE); + + for (pri = priorities; pri->name && strcmp(val, pri->name); pri++) + ; + if (pri->name == NULL) + return(FALSE); /* not found */ + + /* Store both name and number. */ + if (def->sd_un.str) + free(def->sd_un.str); + def->sd_un.str = estrdup(pri->name); + idef->sd_un.ival = pri->num; + return(TRUE); +} + +static int +store_mode(val, def, op) + char *val; + struct sudo_defs_types *def; + int op; +{ + char *endp; + long l; + + if (op == FALSE) { + def->sd_un.mode = (mode_t)0777; + } else { + l = strtol(val, &endp, 8); + if (*endp != '\0' || l < 0 || l >= 0777) + return(FALSE); + def->sd_un.mode = (mode_t)l; + } + return(TRUE); +} |