From 02f37dc2dae4e96c4892f33767ca42e9033ad302 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Tue, 30 Dec 2003 22:31:30 +0000 Subject: [PATCH] Add support for tuples in def_data.in; these are implemented as an enum type. Currently there is only a single tuple enum but in the future we may have one tuple enum per T_TUPLE entry in def_data.in. Currently listpw, verifypw and lecture are tuples. This avoids the need to have two entries (one ival, one str) for pwflags and syslog values. lecture is now a tuple with the following values: never, once, always We no longer use both an int and string entry for syslog facilities and priorities. Instead, there are logfac2str() and logpri2str() functions that get used when we need to print the string values. --- check.c | 27 +++--- def_data.c | 155 ++++++++++++++++++---------------- def_data.h | 234 ++++++++++++++++++++++++++-------------------------- def_data.in | 25 ++---- defaults.c | 200 +++++++++++++++++++++++--------------------- defaults.h | 21 ++--- logging.c | 8 +- mkdefaults | 106 +++++++++++++++++------- parse.c | 21 ++--- sudo.c | 8 +- sudo.h | 29 ++----- 11 files changed, 444 insertions(+), 390 deletions(-) diff --git a/check.c b/check.c index 2a8cfe8d5..b2cf13e25 100644 --- a/check.c +++ b/check.c @@ -89,7 +89,7 @@ static const char rcsid[] = "$Sudo$"; static void build_timestamp __P((char **, char **)); static int timestamp_status __P((char *, char *, char *, int)); static char *expand_prompt __P((char *, char *, char *)); -static void lecture __P((void)); +static void lecture __P((int)); static void update_timestamp __P((char *, char *)); /* @@ -97,7 +97,8 @@ static void update_timestamp __P((char *, char *)); * verify who he/she is. */ void -check_user() +check_user(override) + int override; { char *timestampdir = NULL; char *timestampfile = NULL; @@ -109,9 +110,8 @@ check_user() build_timestamp(×tampdir, ×tampfile); status = timestamp_status(timestampdir, timestampfile, user_name, TRUE); - if (status != TS_CURRENT) { - if (status == TS_MISSING || status == TS_ERROR) - lecture(); /* first time through they get a lecture */ + if (override || status != TS_CURRENT) { + lecture(status); /* Expand any escapes in the prompt. */ prompt = expand_prompt(user_prompt ? user_prompt : def_passprompt, @@ -131,18 +131,21 @@ check_user() * TODO: allow the user to specify a file name instead. */ static void -lecture() +lecture(status) + int status; { - if (def_lecture) { - (void) fputs("\n\ + if (def_lecture == never || + (def_lecture == once && status != TS_MISSING && status != TS_ERROR)) + return; + + (void) fputs("\n\ We trust you have received the usual lecture from the local System\n\ Administrator. It usually boils down to these two things:\n\ \n\ - #1) Respect the privacy of others.\n\ - #2) Think before you type.\n\n", - stderr); - } + #1) Respect the privacy of others.\n\ + #2) Think before you type.\n\n", + stderr); } /* diff --git a/def_data.c b/def_data.c index c565b8739..4ec5b29a7 100644 --- a/def_data.c +++ b/def_data.c @@ -1,181 +1,192 @@ +static struct def_values def_data_lecture[] = { + { "never", never }, + { "once", once }, + { "always", always }, + { NULL, 0 }, +}; + +static struct def_values def_data_listpw[] = { + { "never", never }, + { "any", any }, + { "all", all }, + { "always", always }, + { NULL, 0 }, +}; + +static struct def_values def_data_verifypw[] = { + { "never", never }, + { "any", any }, + { "all", all }, + { "always", always }, + { NULL, 0 }, +}; + struct sudo_defs_types sudo_defs_table[] = { { - "syslog_ifac", T_UINT, - NULL - }, { - "syslog_igoodpri", T_UINT, - NULL - }, { - "syslog_ibadpri", T_UINT, - NULL - }, { "syslog", T_LOGFAC|T_BOOL, - "Syslog facility if syslog is being used for logging: %s" + "Syslog facility if syslog is being used for logging: %s", }, { "syslog_goodpri", T_LOGPRI, - "Syslog priority to use when user authenticates successfully: %s" + "Syslog priority to use when user authenticates successfully: %s", }, { "syslog_badpri", T_LOGPRI, - "Syslog priority to use when user authenticates unsuccessfully: %s" + "Syslog priority to use when user authenticates unsuccessfully: %s", }, { "long_otp_prompt", T_FLAG, - "Put OTP prompt on its own line" + "Put OTP prompt on its own line", }, { "ignore_dot", T_FLAG, - "Ignore '.' in $PATH" + "Ignore '.' in $PATH", }, { "mail_always", T_FLAG, - "Always send mail when sudo is run" + "Always send mail when sudo is run", }, { "mail_badpass", T_FLAG, - "Send mail if user authentication fails" + "Send mail if user authentication fails", }, { "mail_no_user", T_FLAG, - "Send mail if the user is not in sudoers" + "Send mail if the user is not in sudoers", }, { "mail_no_host", T_FLAG, - "Send mail if the user is not in sudoers for this host" + "Send mail if the user is not in sudoers for this host", }, { "mail_no_perms", T_FLAG, - "Send mail if the user is not allowed to run a command" + "Send mail if the user is not allowed to run a command", }, { "tty_tickets", T_FLAG, - "Use a separate timestamp for each user/tty combo" + "Use a separate timestamp for each user/tty combo", }, { - "lecture", T_FLAG, - "Lecture user the first time they run sudo" + "lecture", T_TUPLE|T_BOOL, + "Lecture user the first time they run sudo", + def_data_lecture, }, { "authenticate", T_FLAG, - "Require users to authenticate by default" + "Require users to authenticate by default", }, { "root_sudo", T_FLAG, - "Root may run sudo" + "Root may run sudo", }, { "log_host", T_FLAG, - "Log the hostname in the (non-syslog) log file" + "Log the hostname in the (non-syslog) log file", }, { "log_year", T_FLAG, - "Log the year in the (non-syslog) log file" + "Log the year in the (non-syslog) log file", }, { "shell_noargs", T_FLAG, - "If sudo is invoked with no arguments, start a shell" + "If sudo is invoked with no arguments, start a shell", }, { "set_home", T_FLAG, - "Set $HOME to the target user when starting a shell with -s" + "Set $HOME to the target user when starting a shell with -s", }, { "always_set_home", T_FLAG, - "Always set $HOME to the target user's home directory" + "Always set $HOME to the target user's home directory", }, { "path_info", T_FLAG, - "Allow some information gathering to give useful error messages" + "Allow some information gathering to give useful error messages", }, { "fqdn", T_FLAG, - "Require fully-qualified hostnames in the sudoers file" + "Require fully-qualified hostnames in the sudoers file", }, { "insults", T_FLAG, - "Insult the user when they enter an incorrect password" + "Insult the user when they enter an incorrect password", }, { "requiretty", T_FLAG, - "Only allow the user to run sudo if they have a tty" + "Only allow the user to run sudo if they have a tty", }, { "env_editor", T_FLAG, - "Visudo will honor the EDITOR environment variable" + "Visudo will honor the EDITOR environment variable", }, { "rootpw", T_FLAG, - "Prompt for root's password, not the users's" + "Prompt for root's password, not the users's", }, { "runaspw", T_FLAG, - "Prompt for the runas_default user's password, not the users's" + "Prompt for the runas_default user's password, not the users's", }, { "targetpw", T_FLAG, - "Prompt for the target user's password, not the users's" + "Prompt for the target user's password, not the users's", }, { "use_loginclass", T_FLAG, - "Apply defaults in the target user's login class if there is one" + "Apply defaults in the target user's login class if there is one", }, { "set_logname", T_FLAG, - "Set the LOGNAME and USER environment variables" + "Set the LOGNAME and USER environment variables", }, { "stay_setuid", T_FLAG, - "Only set the effective uid to the target user, not the real uid" + "Only set the effective uid to the target user, not the real uid", }, { "env_reset", T_FLAG, - "Reset the environment to a default set of variables" + "Reset the environment to a default set of variables", }, { "preserve_groups", T_FLAG, - "Don't initialize the group vector to that of the target user" + "Don't initialize the group vector to that of the target user", }, { "loglinelen", T_UINT|T_BOOL, - "Length at which to wrap log file lines (0 for no wrap): %d" + "Length at which to wrap log file lines (0 for no wrap): %d", }, { "timestamp_timeout", T_INT|T_BOOL, - "Authentication timestamp timeout: %d minutes" + "Authentication timestamp timeout: %d minutes", }, { "passwd_timeout", T_UINT|T_BOOL, - "Password prompt timeout: %d minutes" + "Password prompt timeout: %d minutes", }, { "passwd_tries", T_UINT, - "Number of tries to enter a password: %d" + "Number of tries to enter a password: %d", }, { "umask", T_MODE|T_BOOL, - "Umask to use or 0777 to use user's: 0%o" + "Umask to use or 0777 to use user's: 0%o", }, { "logfile", T_STR|T_BOOL|T_PATH, - "Path to log file: %s" + "Path to log file: %s", }, { "mailerpath", T_STR|T_BOOL|T_PATH, - "Path to mail program: %s" + "Path to mail program: %s", }, { "mailerflags", T_STR|T_BOOL, - "Flags for mail program: %s" + "Flags for mail program: %s", }, { "mailto", T_STR|T_BOOL, - "Address to send mail to: %s" + "Address to send mail to: %s", }, { "mailsub", T_STR, - "Subject line for mail messages: %s" + "Subject line for mail messages: %s", }, { "badpass_message", T_STR, - "Incorrect password message: %s" + "Incorrect password message: %s", }, { "timestampdir", T_STR|T_PATH, - "Path to authentication timestamp dir: %s" + "Path to authentication timestamp dir: %s", }, { "timestampowner", T_STR, - "Owner of the authentication timestamp dir: %s" + "Owner of the authentication timestamp dir: %s", }, { "exempt_group", T_STR|T_BOOL, - "Users in this group are exempt from password and PATH requirements: %s" + "Users in this group are exempt from password and PATH requirements: %s", }, { "passprompt", T_STR, - "Default password prompt: %s" + "Default password prompt: %s", }, { "runas_default", T_STR, - "Default user to run commands as: %s" + "Default user to run commands as: %s", }, { "editor", T_STR|T_PATH, - "Path to the editor for use by visudo: %s" + "Path to the editor for use by visudo: %s", }, { "env_check", T_LIST|T_BOOL, - "Environment variables to check for sanity:" + "Environment variables to check for sanity:", }, { "env_delete", T_LIST|T_BOOL, - "Environment variables to remove:" + "Environment variables to remove:", }, { "env_keep", T_LIST|T_BOOL, - "Environment variables to preserve:" - }, { - "listpw_i", T_UINT, - NULL - }, { - "verifypw_i", T_UINT, - NULL + "Environment variables to preserve:", }, { - "listpw", T_PWFLAG, - "When to require a password for 'list' pseudocommand: %s" + "listpw", T_TUPLE|T_BOOL, + "When to require a password for 'list' pseudocommand: %s", + def_data_listpw, }, { - "verifypw", T_PWFLAG, - "When to require a password for 'verify' pseudocommand: %s" + "verifypw", T_TUPLE|T_BOOL, + "When to require a password for 'verify' pseudocommand: %s", + def_data_verifypw, }, { NULL, 0, NULL } diff --git a/def_data.h b/def_data.h index 7ea14cbda..d51e021d2 100644 --- a/def_data.h +++ b/def_data.h @@ -1,118 +1,116 @@ -#define def_syslog_ifac (sudo_defs_table[0].sd_un.ival) -#define I_SYSLOG_IFAC 0 -#define def_syslog_igoodpri (sudo_defs_table[1].sd_un.ival) -#define I_SYSLOG_IGOODPRI 1 -#define def_syslog_ibadpri (sudo_defs_table[2].sd_un.ival) -#define I_SYSLOG_IBADPRI 2 -#define def_syslog (sudo_defs_table[3].sd_un.str) -#define I_SYSLOG 3 -#define def_syslog_goodpri (sudo_defs_table[4].sd_un.str) -#define I_SYSLOG_GOODPRI 4 -#define def_syslog_badpri (sudo_defs_table[5].sd_un.str) -#define I_SYSLOG_BADPRI 5 -#define def_long_otp_prompt (sudo_defs_table[6].sd_un.flag) -#define I_LONG_OTP_PROMPT 6 -#define def_ignore_dot (sudo_defs_table[7].sd_un.flag) -#define I_IGNORE_DOT 7 -#define def_mail_always (sudo_defs_table[8].sd_un.flag) -#define I_MAIL_ALWAYS 8 -#define def_mail_badpass (sudo_defs_table[9].sd_un.flag) -#define I_MAIL_BADPASS 9 -#define def_mail_no_user (sudo_defs_table[10].sd_un.flag) -#define I_MAIL_NO_USER 10 -#define def_mail_no_host (sudo_defs_table[11].sd_un.flag) -#define I_MAIL_NO_HOST 11 -#define def_mail_no_perms (sudo_defs_table[12].sd_un.flag) -#define I_MAIL_NO_PERMS 12 -#define def_tty_tickets (sudo_defs_table[13].sd_un.flag) -#define I_TTY_TICKETS 13 -#define def_lecture (sudo_defs_table[14].sd_un.flag) -#define I_LECTURE 14 -#define def_authenticate (sudo_defs_table[15].sd_un.flag) -#define I_AUTHENTICATE 15 -#define def_root_sudo (sudo_defs_table[16].sd_un.flag) -#define I_ROOT_SUDO 16 -#define def_log_host (sudo_defs_table[17].sd_un.flag) -#define I_LOG_HOST 17 -#define def_log_year (sudo_defs_table[18].sd_un.flag) -#define I_LOG_YEAR 18 -#define def_shell_noargs (sudo_defs_table[19].sd_un.flag) -#define I_SHELL_NOARGS 19 -#define def_set_home (sudo_defs_table[20].sd_un.flag) -#define I_SET_HOME 20 -#define def_always_set_home (sudo_defs_table[21].sd_un.flag) -#define I_ALWAYS_SET_HOME 21 -#define def_path_info (sudo_defs_table[22].sd_un.flag) -#define I_PATH_INFO 22 -#define def_fqdn (sudo_defs_table[23].sd_un.flag) -#define I_FQDN 23 -#define def_insults (sudo_defs_table[24].sd_un.flag) -#define I_INSULTS 24 -#define def_requiretty (sudo_defs_table[25].sd_un.flag) -#define I_REQUIRETTY 25 -#define def_env_editor (sudo_defs_table[26].sd_un.flag) -#define I_ENV_EDITOR 26 -#define def_rootpw (sudo_defs_table[27].sd_un.flag) -#define I_ROOTPW 27 -#define def_runaspw (sudo_defs_table[28].sd_un.flag) -#define I_RUNASPW 28 -#define def_targetpw (sudo_defs_table[29].sd_un.flag) -#define I_TARGETPW 29 -#define def_use_loginclass (sudo_defs_table[30].sd_un.flag) -#define I_USE_LOGINCLASS 30 -#define def_set_logname (sudo_defs_table[31].sd_un.flag) -#define I_SET_LOGNAME 31 -#define def_stay_setuid (sudo_defs_table[32].sd_un.flag) -#define I_STAY_SETUID 32 -#define def_env_reset (sudo_defs_table[33].sd_un.flag) -#define I_ENV_RESET 33 -#define def_preserve_groups (sudo_defs_table[34].sd_un.flag) -#define I_PRESERVE_GROUPS 34 -#define def_loglinelen (sudo_defs_table[35].sd_un.ival) -#define I_LOGLINELEN 35 -#define def_timestamp_timeout (sudo_defs_table[36].sd_un.ival) -#define I_TIMESTAMP_TIMEOUT 36 -#define def_passwd_timeout (sudo_defs_table[37].sd_un.ival) -#define I_PASSWD_TIMEOUT 37 -#define def_passwd_tries (sudo_defs_table[38].sd_un.ival) -#define I_PASSWD_TRIES 38 -#define def_umask (sudo_defs_table[39].sd_un.mode) -#define I_UMASK 39 -#define def_logfile (sudo_defs_table[40].sd_un.str) -#define I_LOGFILE 40 -#define def_mailerpath (sudo_defs_table[41].sd_un.str) -#define I_MAILERPATH 41 -#define def_mailerflags (sudo_defs_table[42].sd_un.str) -#define I_MAILERFLAGS 42 -#define def_mailto (sudo_defs_table[43].sd_un.str) -#define I_MAILTO 43 -#define def_mailsub (sudo_defs_table[44].sd_un.str) -#define I_MAILSUB 44 -#define def_badpass_message (sudo_defs_table[45].sd_un.str) -#define I_BADPASS_MESSAGE 45 -#define def_timestampdir (sudo_defs_table[46].sd_un.str) -#define I_TIMESTAMPDIR 46 -#define def_timestampowner (sudo_defs_table[47].sd_un.str) -#define I_TIMESTAMPOWNER 47 -#define def_exempt_group (sudo_defs_table[48].sd_un.str) -#define I_EXEMPT_GROUP 48 -#define def_passprompt (sudo_defs_table[49].sd_un.str) -#define I_PASSPROMPT 49 -#define def_runas_default (sudo_defs_table[50].sd_un.str) -#define I_RUNAS_DEFAULT 50 -#define def_editor (sudo_defs_table[51].sd_un.str) -#define I_EDITOR 51 -#define def_env_check (sudo_defs_table[52].sd_un.list) -#define I_ENV_CHECK 52 -#define def_env_delete (sudo_defs_table[53].sd_un.list) -#define I_ENV_DELETE 53 -#define def_env_keep (sudo_defs_table[54].sd_un.list) -#define I_ENV_KEEP 54 -#define def_listpw_i (sudo_defs_table[55].sd_un.ival) -#define I_LISTPW_I 55 -#define def_verifypw_i (sudo_defs_table[56].sd_un.ival) -#define I_VERIFYPW_I 56 -#define def_listpw (sudo_defs_table[57].sd_un.str) -#define I_LISTPW 57 -#define def_verifypw (sudo_defs_table[58].sd_un.str) -#define I_VERIFYPW 58 +#define def_syslog (sudo_defs_table[0].sd_un.ival) +#define I_SYSLOG 0 +#define def_syslog_goodpri (sudo_defs_table[1].sd_un.ival) +#define I_SYSLOG_GOODPRI 1 +#define def_syslog_badpri (sudo_defs_table[2].sd_un.ival) +#define I_SYSLOG_BADPRI 2 +#define def_long_otp_prompt (sudo_defs_table[3].sd_un.flag) +#define I_LONG_OTP_PROMPT 3 +#define def_ignore_dot (sudo_defs_table[4].sd_un.flag) +#define I_IGNORE_DOT 4 +#define def_mail_always (sudo_defs_table[5].sd_un.flag) +#define I_MAIL_ALWAYS 5 +#define def_mail_badpass (sudo_defs_table[6].sd_un.flag) +#define I_MAIL_BADPASS 6 +#define def_mail_no_user (sudo_defs_table[7].sd_un.flag) +#define I_MAIL_NO_USER 7 +#define def_mail_no_host (sudo_defs_table[8].sd_un.flag) +#define I_MAIL_NO_HOST 8 +#define def_mail_no_perms (sudo_defs_table[9].sd_un.flag) +#define I_MAIL_NO_PERMS 9 +#define def_tty_tickets (sudo_defs_table[10].sd_un.flag) +#define I_TTY_TICKETS 10 +#define def_lecture (sudo_defs_table[11].sd_un.tuple) +#define I_LECTURE 11 +#define def_authenticate (sudo_defs_table[12].sd_un.flag) +#define I_AUTHENTICATE 12 +#define def_root_sudo (sudo_defs_table[13].sd_un.flag) +#define I_ROOT_SUDO 13 +#define def_log_host (sudo_defs_table[14].sd_un.flag) +#define I_LOG_HOST 14 +#define def_log_year (sudo_defs_table[15].sd_un.flag) +#define I_LOG_YEAR 15 +#define def_shell_noargs (sudo_defs_table[16].sd_un.flag) +#define I_SHELL_NOARGS 16 +#define def_set_home (sudo_defs_table[17].sd_un.flag) +#define I_SET_HOME 17 +#define def_always_set_home (sudo_defs_table[18].sd_un.flag) +#define I_ALWAYS_SET_HOME 18 +#define def_path_info (sudo_defs_table[19].sd_un.flag) +#define I_PATH_INFO 19 +#define def_fqdn (sudo_defs_table[20].sd_un.flag) +#define I_FQDN 20 +#define def_insults (sudo_defs_table[21].sd_un.flag) +#define I_INSULTS 21 +#define def_requiretty (sudo_defs_table[22].sd_un.flag) +#define I_REQUIRETTY 22 +#define def_env_editor (sudo_defs_table[23].sd_un.flag) +#define I_ENV_EDITOR 23 +#define def_rootpw (sudo_defs_table[24].sd_un.flag) +#define I_ROOTPW 24 +#define def_runaspw (sudo_defs_table[25].sd_un.flag) +#define I_RUNASPW 25 +#define def_targetpw (sudo_defs_table[26].sd_un.flag) +#define I_TARGETPW 26 +#define def_use_loginclass (sudo_defs_table[27].sd_un.flag) +#define I_USE_LOGINCLASS 27 +#define def_set_logname (sudo_defs_table[28].sd_un.flag) +#define I_SET_LOGNAME 28 +#define def_stay_setuid (sudo_defs_table[29].sd_un.flag) +#define I_STAY_SETUID 29 +#define def_env_reset (sudo_defs_table[30].sd_un.flag) +#define I_ENV_RESET 30 +#define def_preserve_groups (sudo_defs_table[31].sd_un.flag) +#define I_PRESERVE_GROUPS 31 +#define def_loglinelen (sudo_defs_table[32].sd_un.ival) +#define I_LOGLINELEN 32 +#define def_timestamp_timeout (sudo_defs_table[33].sd_un.ival) +#define I_TIMESTAMP_TIMEOUT 33 +#define def_passwd_timeout (sudo_defs_table[34].sd_un.ival) +#define I_PASSWD_TIMEOUT 34 +#define def_passwd_tries (sudo_defs_table[35].sd_un.ival) +#define I_PASSWD_TRIES 35 +#define def_umask (sudo_defs_table[36].sd_un.mode) +#define I_UMASK 36 +#define def_logfile (sudo_defs_table[37].sd_un.str) +#define I_LOGFILE 37 +#define def_mailerpath (sudo_defs_table[38].sd_un.str) +#define I_MAILERPATH 38 +#define def_mailerflags (sudo_defs_table[39].sd_un.str) +#define I_MAILERFLAGS 39 +#define def_mailto (sudo_defs_table[40].sd_un.str) +#define I_MAILTO 40 +#define def_mailsub (sudo_defs_table[41].sd_un.str) +#define I_MAILSUB 41 +#define def_badpass_message (sudo_defs_table[42].sd_un.str) +#define I_BADPASS_MESSAGE 42 +#define def_timestampdir (sudo_defs_table[43].sd_un.str) +#define I_TIMESTAMPDIR 43 +#define def_timestampowner (sudo_defs_table[44].sd_un.str) +#define I_TIMESTAMPOWNER 44 +#define def_exempt_group (sudo_defs_table[45].sd_un.str) +#define I_EXEMPT_GROUP 45 +#define def_passprompt (sudo_defs_table[46].sd_un.str) +#define I_PASSPROMPT 46 +#define def_runas_default (sudo_defs_table[47].sd_un.str) +#define I_RUNAS_DEFAULT 47 +#define def_editor (sudo_defs_table[48].sd_un.str) +#define I_EDITOR 48 +#define def_env_check (sudo_defs_table[49].sd_un.list) +#define I_ENV_CHECK 49 +#define def_env_delete (sudo_defs_table[50].sd_un.list) +#define I_ENV_DELETE 50 +#define def_env_keep (sudo_defs_table[51].sd_un.list) +#define I_ENV_KEEP 51 +#define def_listpw (sudo_defs_table[52].sd_un.tuple) +#define I_LISTPW 52 +#define def_verifypw (sudo_defs_table[53].sd_un.tuple) +#define I_VERIFYPW 53 + +enum def_tupple { + never, + once, + always, + any, + all, +}; diff --git a/def_data.in b/def_data.in index b23e63b35..66710616e 100644 --- a/def_data.in +++ b/def_data.in @@ -4,17 +4,9 @@ # var_name # TYPE # description (or NULL) +# array of struct def_values if TYPE == T_TUPLE # -syslog_ifac - T_UINT - NULL -syslog_igoodpri - T_UINT - NULL -syslog_ibadpri - T_UINT - NULL syslog T_LOGFAC|T_BOOL "Syslog facility if syslog is being used for logging: %s" @@ -49,8 +41,9 @@ tty_tickets T_FLAG "Use a separate timestamp for each user/tty combo" lecture - T_FLAG + T_TUPLE|T_BOOL "Lecture user the first time they run sudo" + never once always authenticate T_FLAG "Require users to authenticate by default" @@ -171,15 +164,11 @@ env_delete env_keep T_LIST|T_BOOL "Environment variables to preserve:" -listpw_i - T_UINT - NULL -verifypw_i - T_UINT - NULL listpw - T_PWFLAG + T_TUPLE|T_BOOL "When to require a password for 'list' pseudocommand: %s" + never any all always verifypw - T_PWFLAG + T_TUPLE|T_BOOL "When to require a password for 'verify' pseudocommand: %s" + never any all always diff --git a/defaults.c b/defaults.c index f56fd3d9f..fd57a3b13 100644 --- a/defaults.c +++ b/defaults.c @@ -118,14 +118,16 @@ extern int sudolineno; * Local prototypes. */ static int store_int __P((char *, struct sudo_defs_types *, int)); -static int store_uint __P((char *, struct sudo_defs_types *, int)); +static int store_list __P((char *, struct sudo_defs_types *, int)); +static int store_mode __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)); -static int store_pwflag __P((char *, struct sudo_defs_types *, int)); -static int store_list __P((char *, struct sudo_defs_types *, int)); +static int store_tuple __P((char *, struct sudo_defs_types *, int)); +static int store_uint __P((char *, struct sudo_defs_types *, int)); static void list_op __P((char *, size_t, struct sudo_defs_types *, enum list_ops)); +static const char *logfac2str __P((int)); +static const char *logpri2str __P((int)); /* * Table describing compile-time and run-time options. @@ -140,6 +142,7 @@ dump_defaults() { struct sudo_defs_types *cur; struct list_member *item; + struct def_values *def; for (cur = sudo_defs_table; cur->name; cur++) { if (cur->desc) { @@ -149,14 +152,23 @@ dump_defaults() puts(cur->desc); break; case T_STR: - case T_LOGFAC: - case T_LOGPRI: - case T_PWFLAG: if (cur->sd_un.str) { (void) printf(cur->desc, cur->sd_un.str); putchar('\n'); } break; + case T_LOGFAC: + if (cur->sd_un.ival) { + (void) printf(cur->desc, logfac2str(cur->sd_un.ival)); + putchar('\n'); + } + break; + case T_LOGPRI: + if (cur->sd_un.ival) { + (void) printf(cur->desc, logpri2str(cur->sd_un.ival)); + putchar('\n'); + } + break; case T_UINT: case T_INT: (void) printf(cur->desc, cur->sd_un.ival); @@ -173,6 +185,15 @@ dump_defaults() printf("\t%s\n", item->value); } break; + case T_TUPLE: + for (def = cur->values; def->sval; def++) { + if (cur->sd_un.ival == def->ival) { + (void) printf(cur->desc, def->sval); + break; + } + } + putchar('\n'); + break; } } } @@ -254,16 +275,6 @@ set_default(var, val, op) return(FALSE); } break; - case T_PWFLAG: - if (!store_pwflag(val, cur, op)) { - if (val) - warnx("value `%s' is invalid for option `%s'", val, var); - else - warnx("no value specified for `%s' on line %d", - var, sudolineno); - return(FALSE); - } - break; case T_STR: if (!val) { /* Check for bogus boolean usage or lack of a value. */ @@ -349,6 +360,21 @@ set_default(var, val, op) warnx("value `%s' is invalid for option `%s'", val, var); return(FALSE); } + break; + case T_TUPLE: + if (!val) { + /* Check for bogus boolean usage or lack of a value. */ + if (!(cur->type & T_BOOL) || op != FALSE) { + warnx("no value specified for `%s' on line %d", + var, sudolineno); + return(FALSE); + } + } + if (!store_tuple(val, cur, op)) { + warnx("value `%s' is invalid for option `%s'", val, var); + return(FALSE); + } + break; } return(TRUE); @@ -369,9 +395,6 @@ init_defaults() for (def = sudo_defs_table; def->name; def++) switch (def->type & T_MASK) { case T_STR: - case T_LOGFAC: - case T_LOGPRI: - case T_PWFLAG: if (def->sd_un.str) { free(def->sd_un.str); def->sd_un.str = NULL; @@ -406,7 +429,7 @@ init_defaults() def_tty_tickets = TRUE; #endif #ifndef NO_LECTURE - def_lecture = TRUE; + def_lecture = once; #endif #ifndef NO_AUTHENTICATION def_authenticate = TRUE; @@ -447,8 +470,8 @@ init_defaults() #endif /* Password flags also have a string and integer component. */ - (void) store_pwflag("any", &sudo_defs_table[I_LISTPW], TRUE); - (void) store_pwflag("all", &sudo_defs_table[I_VERIFYPW], TRUE); + (void) store_tuple("any", &sudo_defs_table[I_LISTPW], TRUE); + (void) store_tuple("all", &sudo_defs_table[I_VERIFYPW], TRUE); /* Then initialize the int-like things. */ #ifdef SUDO_UMASK @@ -536,6 +559,36 @@ store_uint(val, def, op) return(TRUE); } +static int +store_tuple(val, def, op) + char *val; + struct sudo_defs_types *def; + int op; +{ + struct def_values *v; + + /* + * Since enums are really just ints we store the value as an ival. + * In the future, there may be multiple enums for different tuple + * types we want to avoid and special knowledge of the tuple type. + * This does assume that the first entry in the tuple enum will + * be the equivalent to a boolean "false". + */ + if (op == FALSE) { + def->sd_un.ival = 0; + } else { + for (v = def->values; v != NULL; v++) { + if (strcmp(v->sval, val) == 0) { + def->sd_un.ival = v->ival; + break; + } + } + if (v == NULL) + return(FALSE); + } + return(TRUE); +} + static int store_str(val, def, op) char *val; @@ -592,10 +645,7 @@ store_syslogfac(val, def, op) struct strmap *fac; if (op == FALSE) { - if (def->sd_un.str) { - free(def->sd_un.str); - def->sd_un.str = NULL; - } + def->sd_un.ival = FALSE; return(TRUE); } #ifdef LOG_NFACILITIES @@ -606,19 +656,28 @@ store_syslogfac(val, def, op) 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; + def->sd_un.ival = fac->num; #else - if (def->sd_un.str) - free(def->sd_un.str); - def->sd_un.str = estrdup("default"); + def->sd_un.ival = -1; #endif /* LOG_NFACILITIES */ return(TRUE); } +static const char * +logfac2str(n) + int n; +{ +#ifdef LOG_NFACILITIES + struct strmap *fac; + + for (fac = facilities; fac->name && fac->num != n; fac++) + ; + return (fac->name); +#else + return ("default"); +#endif /* LOG_NFACILITIES */ +} + static int store_syslogpri(val, def, op) char *val; @@ -626,30 +685,30 @@ store_syslogpri(val, def, op) int op; { struct strmap *pri; - struct sudo_defs_types *idef; if (op == FALSE || !val) return(FALSE); - if (def == &sudo_defs_table[I_SYSLOG_GOODPRI]) - idef = &sudo_defs_table[I_GOODPRI]; - else if (def == &sudo_defs_table[I_SYSLOG_BADPRI]) - 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; + def->sd_un.ival = pri->num; return(TRUE); } +static const char * +logpri2str(n) + int n; +{ + struct strmap *pri; + + for (pri = priorities; pri->name && pri->num != n; pri++) + ; + return (pri->name); +} + static int store_mode(val, def, op) char *val; @@ -670,53 +729,6 @@ store_mode(val, def, op) return(TRUE); } -static int -store_pwflag(val, def, op) - char *val; - struct sudo_defs_types *def; - int op; -{ - int isub, flags; - - if (strcmp(def->name, "verifypw") == 0) - isub = I_VERIFYPW_I; - else - isub = I_LISTPW_I; - - /* Handle !foo. */ - if (op == FALSE) { - if (def->sd_un.str) { - free(def->sd_un.str); - def->sd_un.str = NULL; - } - def->sd_un.str = estrdup("never"); - sudo_defs_table[isub].sd_un.ival = PWCHECK_NEVER; - return(TRUE); - } - if (!val) - return(FALSE); - - /* Convert strings to integer values. */ - if (strcmp(val, "all") == 0) - flags = PWCHECK_ALL; - else if (strcmp(val, "any") == 0) - flags = PWCHECK_ANY; - else if (strcmp(val, "never") == 0) - flags = PWCHECK_NEVER; - else if (strcmp(val, "always") == 0) - flags = PWCHECK_ALWAYS; - else - return(FALSE); - - /* Store both name and number. */ - if (def->sd_un.str) - free(def->sd_un.str); - def->sd_un.str = estrdup(val); - sudo_defs_table[isub].sd_un.ival = flags; - - return(TRUE); -} - static void list_op(val, len, def, op) char *val; diff --git a/defaults.h b/defaults.h index 216323eb1..e39a8a105 100644 --- a/defaults.h +++ b/defaults.h @@ -41,11 +41,18 @@ #ifndef _SUDO_DEFAULTS_H #define _SUDO_DEFAULTS_H +#include + struct list_member { char *value; struct list_member *next; }; +struct def_values { + char *sval; /* string value */ + int ival; /* actually an enum */ +}; + enum list_ops { add, delete, @@ -59,9 +66,11 @@ struct sudo_defs_types { char *name; int type; char *desc; + struct def_values *values; union { int flag; int ival; + enum def_tupple tuple; char *str; mode_t mode; struct list_member *list; @@ -89,8 +98,8 @@ struct sudo_defs_types { #define T_LOGFAC 0x007 #undef T_LOGPRI #define T_LOGPRI 0x008 -#undef T_PWFLAG -#define T_PWFLAG 0x009 +#undef T_TUPLE +#define T_TUPLE 0x009 #undef T_MASK #define T_MASK 0x0FF #undef T_BOOL @@ -98,14 +107,6 @@ struct sudo_defs_types { #undef T_PATH #define T_PATH 0x200 -/* - * Indexes into sudo_defs_table - */ -#include -#define I_LOGFAC I_SYSLOG_IFAC -#define I_GOODPRI I_SYSLOG_IGOODPRI -#define I_BADPRI I_SYSLOG_IBADPRI - /* * Prototypes */ diff --git a/logging.c b/logging.c index 1e2995e40..c11ebc400 100644 --- a/logging.c +++ b/logging.c @@ -116,7 +116,7 @@ mysyslog(pri, fmt, va_alist) va_start(ap); #endif #ifdef LOG_NFACILITIES - openlog("sudo", 0, def_syslog_ifac); + openlog("sudo", 0, def_syslog); #else openlog("sudo", 0); #endif @@ -299,9 +299,9 @@ log_auth(status, inform_user) int pri; if (status & VALIDATE_OK) - pri = def_syslog_igoodpri; + pri = def_syslog_goodpri; else - pri = def_syslog_ibadpri; + pri = def_syslog_badpri; /* Set error message, if any. */ if (status & VALIDATE_OK) @@ -424,7 +424,7 @@ log_error(va_alist) * Log to syslog and/or a file. */ if (def_syslog) - do_syslog(def_syslog_ibadpri, logline); + do_syslog(def_syslog_badpri, logline); if (def_logfile) do_logfile(logline); diff --git a/mkdefaults b/mkdefaults index 819cdc04d..53830fb6a 100755 --- a/mkdefaults +++ b/mkdefaults @@ -7,6 +7,7 @@ # var_name # TYPE # description (or NULL) +# array of struct def_values if TYPE == T_TUPLE # Deal with optional -o (output) argument if ($#ARGV > 0 && $ARGV[0] eq "-o") { @@ -31,64 +32,113 @@ open(IN, "<$infile") || die "$0: can't open $infile: $!\n"; open(HEADER, ">$header") || die "$0: can't open $header: $!\n"; open(CFILE, ">$cfile") || die "$0: can't open $cfile: $!\n"; -print CFILE "struct sudo_defs_types sudo_defs_table[] = {\n {\n"; - -$count = -1; +$count = 0; +@tuple_values = ( "never" ); +@records = (); while() { chomp; + s/\s*#.*$//; next if /^\s*$/; - next if /^\s*#/; if (/^\S/) { - # Print last record - &print_record() if defined($var); + # Store previous record and begin new one + $records[$count++] = [$var, $type, $desc, $values] if defined($var); $var = $_; - ($type, $desc) = (undef, undef); - $count++; + $type = ''; + $desc = undef; + $values = undef; + $field = 0; } else { + $field++; s/^\s+//; s/\s+$//; die "$0: syntax error near line $.\n" if - defined($type) && defined($desc); - next if /^NULL$/; - if (defined($type)) { - # Strip leading and trailing double quote and escape the rest - s/^"//; - s/"$//; - s/"/\\"/g; - $desc = "\"$_\""; - } else { + $field > 2 + ($type =~ /^T_TUPLE/); + if ($field == 1) { + # type $type = $_; + } elsif ($field == 2) { + # description + if ($_ eq "NULL") { + $desc = "NULL"; + } else { + # Strip leading and trailing double quote and escape the rest + s/^"//; + s/"$//; + s/"/\\"/g; + $desc = "\"$_\""; + } + } elsif ($field == 3) { + $values = [ split ]; + foreach $v (@$values) { + push(@tuple_values, $v) unless grep(/^$v$/, @tuple_values); + } } } } -&print_record(); +$records[$count++] = [$var, $type, $desc, $values] if defined($var); + +# Print out value arrays +for ($i = 0; $i < $count; $i++) { + if (defined($records[$i]->[3])) { + die "Values list specified for non-tupple\n" unless + $records[$i]->[1] =~ /^T_TUPLE/; + printf CFILE "static struct def_values def_data_%s[] = {\n", $records[$i]->[0]; + foreach (@{$records[$i]->[3]}) { + print CFILE " { \"$_\", $_ },\n"; + } + print CFILE " { NULL, 0 },\n"; + print CFILE "};\n\n"; + } +} + +# Print each record +print CFILE "struct sudo_defs_types sudo_defs_table[] = {\n {\n"; +for ($i = 0; $i < $count; $i++) { + &print_record($records[$i], $i); +} print CFILE "\tNULL, 0, NULL\n }\n};\n"; +# Print out def_tuple +if (@tuple_values) { + print HEADER "\nenum def_tupple {\n"; + foreach (@tuple_values) { + print HEADER "\t$_,\n"; + } + print HEADER "};\n"; +} + close(IN); close(HEADER); close(CFILE); sub print_record { - my ($v, $defname); + my ($rec, $recnum) = @_; + my ($i, $v, $defname); # each variable gets a macro to access its value - for ($type) { + for ($rec->[1]) { if (/^T_U?INT/) { $v = "ival"; } - elsif (/^(T_STR|T_PWFLAG|T_LOG)/) { $v = "str"; } + elsif (/^T_STR/) { $v = "str"; } elsif (/^T_FLAG/) { $v = "flag"; } elsif (/^T_MODE/) { $v = "mode"; } elsif (/^T_LIST/) { $v = "list"; } + elsif (/^T_LOGFAC/) { $v = "ival"; } + elsif (/^T_LOGPRI/) { $v = "ival"; } + elsif (/^T_TUPLE/) { $v = "tuple"; } else { die "$0: unknown defaults type: $type\n"; } } - printf HEADER "#define %-24s(sudo_defs_table[$count].sd_un.${v})\n", - "def_${var}"; + printf HEADER "#define %-24s(sudo_defs_table[$recnum].sd_un.${v})\n", + "def_$rec->[0]"; - $defname = "I_" . uc($var); - printf HEADER "#define %-24s%d", $defname, $count; - #print HEADER "\t/* $desc */" if defined($desc); + $defname = "I_" . uc($rec->[0]); + printf HEADER "#define %-24s%d", $defname, $recnum; + #print HEADER "\t/* $rec->[2] */" if defined($rec->[2]); print HEADER "\n"; - $desc = "NULL" unless defined($desc); - print CFILE "\t\"$var\", $type,\n\t$desc\n }, {\n"; + print CFILE "\t\"$rec->[0]\", $rec->[1],\n\t$rec->[2],\n"; + if (defined($rec->[3])) { + printf CFILE "\tdef_data_$rec->[0],\n"; + } + print CFILE " }, {\n"; } diff --git a/parse.c b/parse.c index 25087687e..4ea278421 100644 --- a/parse.c +++ b/parse.c @@ -124,9 +124,8 @@ int sudoers_lookup(pwflag) int pwflag; { - int error; - int pwcheck; - int nopass; + int error, nopass; + enum def_tupple pwcheck; /* Become sudoers file owner */ set_perms(PERM_SUDOERS); @@ -139,7 +138,7 @@ sudoers_lookup(pwflag) /* Allocate space for data structures in the parser. */ init_parser(); - /* If pwcheck *could* be PWCHECK_ALL or PWCHECK_ANY, keep more state. */ + /* If pwcheck *could* be "all" or "any", keep more state. */ if (pwflag > 0) keepall = TRUE; @@ -159,7 +158,7 @@ sudoers_lookup(pwflag) * wait until now to set this. */ if (pwflag) - pwcheck = (pwflag == -1) ? PWCHECK_NEVER : sudo_defs_table[pwflag].sd_un.ival; + pwcheck = (pwflag == -1) ? never : sudo_defs_table[pwflag].sd_un.tuple; else pwcheck = 0; @@ -180,23 +179,25 @@ sudoers_lookup(pwflag) } /* - * Only check the actual command if pwcheck flag is not set. + * Only check the actual command if pwflag is not set. * It is set for the "validate", "list" and "kill" pseudo-commands. * Always check the host and user. */ nopass = -1; - if (pwcheck) { + if (pwflag) { int found; - if (pwcheck == PWCHECK_NEVER || !def_authenticate) + if (pwcheck == always && def_authenticate) + nopass = FLAG_CHECK_USER; + else if (pwcheck == never || !def_authenticate) nopass = FLAG_NOPASS; found = 0; while (top) { if (host_matches == TRUE) { found = 1; - if (pwcheck == PWCHECK_ANY && no_passwd == TRUE) + if (pwcheck == any && no_passwd == TRUE) nopass = FLAG_NOPASS; - else if (pwcheck == PWCHECK_ALL && nopass != 0) + else if (pwcheck == all && nopass != 0) nopass = (no_passwd == TRUE) ? FLAG_NOPASS : 0; } top--; diff --git a/sudo.c b/sudo.c index 45d9a9374..3d4e98963 100644 --- a/sudo.c +++ b/sudo.c @@ -235,7 +235,7 @@ main(argc, argv, envp) break; case MODE_VALIDATE: user_cmnd = "validate"; - pwflag = I_VERIFYPW_I; + pwflag = I_VERIFYPW; break; case MODE_KILL: case MODE_INVALIDATE: @@ -248,7 +248,7 @@ main(argc, argv, envp) break; case MODE_LIST: user_cmnd = "list"; - pwflag = I_LISTPW_I; + pwflag = I_LISTPW; printmatches = 1; break; } @@ -355,9 +355,9 @@ main(argc, argv, envp) /* Fill in passwd struct based on user we are authenticating as. */ auth_pw = get_authpw(); - /* Require a password unless the NOPASS tag was set. */ + /* Require a password if sudoers says so. */ if (!(validated & FLAG_NOPASS)) - check_user(); + check_user(validated & FLAG_CHECK_USER); /* Build up custom environment that avoids any nasty bits. */ new_environ = rebuild_env(sudo_mode, envp); diff --git a/sudo.h b/sudo.h index 4cc1ac3f4..31fca998c 100644 --- a/sudo.h +++ b/sudo.h @@ -71,13 +71,14 @@ struct sudo_user { * Note: cannot use '0' as a value here. */ /* XXX - VALIDATE_SUCCESS and VALIDATE_FAILURE instead? */ -#define VALIDATE_ERROR 0x01 -#define VALIDATE_OK 0x02 -#define VALIDATE_NOT_OK 0x04 -#define FLAG_NOPASS 0x10 -#define FLAG_NO_USER 0x20 -#define FLAG_NO_HOST 0x40 -#define FLAG_NO_CHECK 0x80 +#define VALIDATE_ERROR 0x001 +#define VALIDATE_OK 0x002 +#define VALIDATE_NOT_OK 0x004 +#define FLAG_CHECK_USER 0x010 +#define FLAG_NOPASS 0x020 +#define FLAG_NO_USER 0x040 +#define FLAG_NO_HOST 0x080 +#define FLAG_NO_CHECK 0x100 /* * Boolean values @@ -159,18 +160,6 @@ struct sudo_user { #define SUDO_TLOCK 2 /* test & lock a file (non-blocking) */ #define SUDO_UNLOCK 4 /* unlock a file */ -/* - * Flags for sudoers_lookup: - * PASSWD_NEVER: user never has to give a passwd - * PASSWD_ALL: no passwd needed if all entries for host have NOPASSWD flag - * PASSWD_ANY: no passwd needed if any entry for host has a NOPASSWD flag - * PASSWD_ALWAYS: passwd always needed - */ -#define PWCHECK_NEVER 0x01 -#define PWCHECK_ALL 0x02 -#define PWCHECK_ANY 0x04 -#define PWCHECK_ALWAYS 0x08 - /* * Flags for tgetpass() */ @@ -209,7 +198,7 @@ size_t strlcpy __P((char *, const char *, size_t)); char *sudo_goodpath __P((const char *)); char *tgetpass __P((const char *, int, int)); int find_path __P((char *, char **, char *)); -void check_user __P((void)); +void check_user __P((int)); void verify_user __P((struct passwd *, char *)); int sudoers_lookup __P((int)); void set_perms_nosuid __P((int)); -- 2.50.1