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:" + "Environment variables to preserve:", }, { - "listpw_i", T_UINT, - NULL + "listpw", T_TUPLE|T_BOOL, + "When to require a password for 'list' pseudocommand: %s", + def_data_listpw, }, { - "verifypw_i", T_UINT, - NULL - }, { - "listpw", T_PWFLAG, - "When to require a password for 'list' pseudocommand: %s" - }, { - "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));