From 6190f376c1e6e752b87d99e241a8f9f1cdd5e7ad Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Wed, 24 Mar 2004 23:06:34 +0000 Subject: [PATCH] If the user specified a uid with the -u flag and the uid exists in the passwd file, set runas_user to the name, not the uid. When comparing usernames in sudoers, if a name is really a uid (starts with '#') compare it numerically to pw_uid. --- parse.c | 27 +++++++++++++++++++++++---- parse.h | 3 ++- parse.yacc | 16 +++++++++------- sudo.c | 2 ++ testsudoers.c | 17 ++++++++++++++++- visudo.c | 14 ++++++++++++-- 6 files changed, 64 insertions(+), 15 deletions(-) diff --git a/parse.c b/parse.c index 64a9fbec3..33a77021b 100644 --- a/parse.c +++ b/parse.c @@ -437,17 +437,36 @@ hostname_matches(shost, lhost, pattern) } } +/* + * Returns TRUE if the user/uid from sudoers matches the specified user/uid, + * else returns FALSE. + */ +int +userpw_matches(sudoers_user, user, pw) + char *sudoers_user; + char *user; + struct passwd *pw; +{ + if (pw != NULL && *sudoers_user == '#') { + uid_t uid = atoi(sudoers_user + 1); + if (uid == pw->pw_uid) + return(1); + } + return(strcmp(sudoers_user, user) == 0); +} + /* * Returns TRUE if the given user belongs to the named group, * else returns FALSE. + * XXX - reduce the number of passwd/group lookups */ int -usergr_matches(group, user) +usergr_matches(group, user, pw) char *group; char *user; + struct passwd *pw; { struct group *grp; - struct passwd *pw; gid_t pw_gid; char **cur; @@ -455,8 +474,8 @@ usergr_matches(group, user) if (*group++ != '%') return(FALSE); - /* look up user's primary gid in the passwd file (XXX - reduce lookups) */ - if ((pw = getpwnam(user)) == NULL) + /* look up user's primary gid in the passwd file */ + if (pw == NULL && (pw = getpwnam(user)) == NULL) return(FALSE); pw_gid = pw->pw_gid; diff --git a/parse.h b/parse.h index 1f49c0be3..dc0bec937 100644 --- a/parse.h +++ b/parse.h @@ -96,6 +96,7 @@ int addr_matches __P((char *)); int command_matches __P((char *, char *, char *, char *)); int hostname_matches __P((char *, char *, char *)); int netgr_matches __P((char *, char *, char *, char *)); -int usergr_matches __P((char *, char *)); +int userpw_matches __P((char *, char *, struct passwd *)); +int usergr_matches __P((char *, char *, struct passwd *)); #endif /* _SUDO_PARSE_H */ diff --git a/parse.yacc b/parse.yacc index f4e1cc4c2..e4c7f184e 100644 --- a/parse.yacc +++ b/parse.yacc @@ -483,9 +483,11 @@ runasspec : /* empty */ { * If this is the first entry in a command list * then check against default runas user. */ - if (runas_matches == -1) - runas_matches = (strcmp(*user_runas, - def_runas_default) == 0); + if (runas_matches == -1) { + runas_matches = + userpw_matches(def_runas_default, + *user_runas, runas_pw); + } } | RUNAS runaslist { runas_matches = ($2 == TRUE ? TRUE : FALSE); @@ -525,7 +527,7 @@ runasuser : WORD { user_matches == TRUE) append_runas($1, ", "); } - if (strcmp($1, *user_runas) == 0) + if (userpw_matches($1, *user_runas, runas_pw)) $$ = TRUE; else $$ = -1; @@ -539,7 +541,7 @@ runasuser : WORD { user_matches == TRUE) append_runas($1, ", "); } - if (usergr_matches($1, *user_runas)) + if (usergr_matches($1, *user_runas, runas_pw)) $$ = TRUE; else $$ = -1; @@ -818,14 +820,14 @@ opuser : user { ; user : WORD { - if (strcmp($1, user_name) == 0) + if (userpw_matches($1, user_name, sudo_user.pw)) $$ = TRUE; else $$ = -1; free($1); } | USERGROUP { - if (usergr_matches($1, user_name)) + if (usergr_matches($1, user_name, sudo_user.pw)) $$ = TRUE; else $$ = -1; diff --git a/sudo.c b/sudo.c index fa053a913..427d58b24 100644 --- a/sudo.c +++ b/sudo.c @@ -574,6 +574,8 @@ init_vars(sudo_mode) log_error(USE_ERRNO|MSG_ONLY, "can't get hostname"); set_runaspw(*user_runas); /* may call log_error() */ + if (*user_runas[0] == '#' && runas_pw->pw_name && runas_pw->pw_name[0]) + *user_runas = estrdup(runas_pw->pw_name); /* * Get current working directory. Try as user, fall back to root. diff --git a/testsudoers.c b/testsudoers.c index ce7d24f09..72067a077 100644 --- a/testsudoers.c +++ b/testsudoers.c @@ -236,9 +236,24 @@ hostname_matches(shost, lhost, pattern) } int -usergr_matches(group, user) +userpw_matches(sudoers_user, user, pw) + char *sudoers_user; + char *user; + struct passwd *pw; +{ + if (pw != NULL && *sudoers_user == '#') { + uid_t uid = atoi(sudoers_user + 1); + if (uid == pw->pw_uid) + return(1); + } + return(strcmp(sudoers_user, user) == 0); +} + +int +usergr_matches(group, user, pw) char *group; char *user; + struct passwd *pw; { struct group *grp; char **cur; diff --git a/visudo.c b/visudo.c index 113995552..75943cc34 100644 --- a/visudo.c +++ b/visudo.c @@ -82,7 +82,8 @@ int command_matches __P((char *, char *, char *, char *)); int addr_matches __P((char *)); int hostname_matches __P((char *, char *, char *)); int netgr_matches __P((char *, char *, char *, char *)); -int usergr_matches __P((char *, char *)); +int usergr_matches __P((char *, char *, struct passwd *)); +int userpw_matches __P((char *, char *, struct passwd *)); void init_parser __P((void)); void yyrestart __P((FILE *)); @@ -496,8 +497,17 @@ hostname_matches(s, l, p) } int -usergr_matches(g, u) +usergr_matches(g, u, pw) char *g, *u; + struct passwd *pw; +{ + return(TRUE); +} + +int +userpw_matches(s, u, pw) + char *s, *u; + struct passwd *pw; { return(TRUE); } -- 2.40.0