This patch will upgrade Sudo version 1.6.3 to version 1.6.3 patchlevel 7. To apply: cd sudo-1.6.3 patch -p1 < sudo-1.6.3p7.patch diff -ur sudo-1.6.3/CHANGES sudo-1.6.3p7/CHANGES --- sudo-1.6.3/CHANGES Sun Mar 26 19:43:27 2000 +++ sudo-1.6.3p7/CHANGES Fri Mar 2 07:12:26 2001 @@ -1297,3 +1297,35 @@ not being used correctly and the entry was being applied globally. Sudo 1.6.3 released. + +409) Fixed targetpw, rootpw, and runaspw options when used with non-passwd + authentication (pam, etc). + +Sudo 1.6.3p1 released. + +410) When the targetpw flag is set, use the target username as part + of the timestamp path. + +Sudo 1.6.3p2 released. + +411) Fixed a bug that prevented the -H option from being useful. + +Sudo 1.6.3p3 released. + +412) Fixed a case where a string was used after it has been freed. + +Sudo 1.6.3p4 released. + +413) Fixed listpw and verifypw sudoers options. + +414) Do not write NUL when writing passwd prompt; hag@linnaean.org. + +Sudo 1.6.3p5 released. + +415) Fix word splitting bug that caused a segv for very long command line args. + +Sudo 1.6.3p6 released. + +416) Fix negation of path-type Defaults entries in a boolean context. + +Sudo 1.6.3p7 released. diff -ur sudo-1.6.3/alloc.c sudo-1.6.3p7/alloc.c --- sudo-1.6.3/alloc.c Sat Jul 31 10:19:44 1999 +++ sudo-1.6.3p7/alloc.c Wed May 10 21:24:50 2000 @@ -121,7 +121,7 @@ * easprintf() calls vasprintf() and exits with an error if vasprintf() * returns -1 (out of memory). */ -void +int #ifdef __STDC__ easprintf(char **ret, const char *fmt, ...) #else @@ -148,21 +148,24 @@ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]); exit(1); } + return(len); } /* * evasprintf() calls vasprintf() and exits with an error if vasprintf() * returns -1 (out of memory). */ -void +int evasprintf(ret, format, args) char **ret; const char *format; va_list args; { + int len; - if (vasprintf(ret, format, args) == -1) { + if ((len = vasprintf(ret, format, args)) == -1) { (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]); exit(1); } + return(len); } diff -ur sudo-1.6.3/auth/sudo_auth.c sudo-1.6.3p7/auth/sudo_auth.c --- sudo-1.6.3/auth/sudo_auth.c Mon Mar 6 12:42:21 2000 +++ sudo-1.6.3p7/auth/sudo_auth.c Tue May 9 10:10:42 2000 @@ -95,7 +95,8 @@ int nil_pw; /* I hate resorting to globals like this... */ void -verify_user(prompt) +verify_user(pw, prompt) + struct passwd *pw; char *prompt; { short counter = def_ival(I_PW_TRIES) + 1; @@ -121,7 +122,7 @@ if (NEEDS_USER(auth)) set_perms(PERM_USER, 0); - status = (auth->init)(sudo_user.pw, &prompt, auth); + status = (auth->init)(pw, &prompt, auth); if (status == AUTH_FAILURE) auth->flags &= ~FLAG_CONFIGURED; else if (status == AUTH_FATAL) /* XXX log */ @@ -139,7 +140,7 @@ if (NEEDS_USER(auth)) set_perms(PERM_USER, 0); - status = (auth->setup)(sudo_user.pw, &prompt, auth); + status = (auth->setup)(pw, &prompt, auth); if (status == AUTH_FAILURE) auth->flags &= ~FLAG_CONFIGURED; else if (status == AUTH_FATAL) /* XXX log */ @@ -169,7 +170,7 @@ if (NEEDS_USER(auth)) set_perms(PERM_USER, 0); - success = auth->status = (auth->verify)(sudo_user.pw, p, auth); + success = auth->status = (auth->verify)(pw, p, auth); if (NEEDS_USER(auth)) set_perms(PERM_ROOT, 0); @@ -199,7 +200,7 @@ if (NEEDS_USER(auth)) set_perms(PERM_USER, 0); - status = (auth->cleanup)(sudo_user.pw, auth); + status = (auth->cleanup)(pw, auth); if (status == AUTH_FATAL) /* XXX log */ exit(1); /* assume error msg already printed */ diff -ur sudo-1.6.3/check.c sudo-1.6.3p7/check.c --- sudo-1.6.3/check.c Tue Feb 15 16:36:03 2000 +++ sudo-1.6.3p7/check.c Wed May 10 21:24:50 2000 @@ -102,7 +102,7 @@ prompt = expand_prompt(user_prompt ? user_prompt : def_str(I_PASSPROMPT), user_name, user_shost); - verify_user(prompt); + verify_user(auth_pw, prompt); } if (status != TS_ERROR) update_timestamp(timestampdir, timestampfile); @@ -251,8 +251,18 @@ char **timestampdir; char **timestampfile; { - char *dirparent = def_str(I_TIMESTAMPDIR); + char *dirparent; + int len; + dirparent = def_str(I_TIMESTAMPDIR); + len = easprintf(timestampdir, "%s/%s", dirparent, user_name); + if (len >= MAXPATHLEN) + log_error(0, "timestamp path too long: %s", timestampdir); + + /* + * Timestamp file may be a file in the directory or NUL to use + * the directory as the timestamp. + */ if (def_flag(I_TTY_TICKETS)) { char *p; @@ -260,17 +270,20 @@ p++; else p = user_tty; - if (strlen(dirparent) + strlen(user_name) + strlen(p) + 3 > MAXPATHLEN) - log_error(0, "timestamp path too long: %s/%s/%s", dirparent, - user_name, p); - easprintf(timestampdir, "%s/%s", dirparent, user_name); - easprintf(timestampfile, "%s/%s/%s", dirparent, user_name, p); - } else { - if (strlen(dirparent) + strlen(user_name) + 2 > MAXPATHLEN) - log_error(0, "timestamp path too long: %s/%s", dirparent, user_name); - easprintf(timestampdir, "%s/%s", dirparent, user_name); + if (def_flag(I_TARGETPW)) + len = easprintf(timestampfile, "%s/%s/%s:%s", dirparent, user_name, + p, *user_runas); + else + len = easprintf(timestampfile, "%s/%s/%s", dirparent, user_name, p); + if (len >= MAXPATHLEN) + log_error(0, "timestamp path too long: %s", timestampfile); + } else if (def_flag(I_TARGETPW)) { + len = easprintf(timestampfile, "%s/%s/%s", dirparent, user_name, + *user_runas); + if (len >= MAXPATHLEN) + log_error(0, "timestamp path too long: %s", timestampfile); + } else *timestampfile = NULL; - } } /* diff -ur sudo-1.6.3/defaults.c sudo-1.6.3p7/defaults.c --- sudo-1.6.3/defaults.c Wed Mar 22 16:40:09 2000 +++ sudo-1.6.3p7/defaults.c Fri Mar 2 07:10:42 2001 @@ -408,7 +408,7 @@ return(FALSE); } } - if ((cur->type & T_PATH) && *val != '/') { + if ((cur->type & T_PATH) && val && *val != '/') { (void) fprintf(stderr, "%s: values for `%s' must start with a '/'\n", Argv[0], var); diff -ur sudo-1.6.3/getspwuid.c sudo-1.6.3p7/getspwuid.c --- sudo-1.6.3/getspwuid.c Fri Feb 18 10:56:26 2000 +++ sudo-1.6.3p7/getspwuid.c Tue May 9 10:10:42 2000 @@ -93,7 +93,8 @@ /* * Local functions not visible outside getspwuid.c */ -static char *sudo_getshell __P((struct passwd *)); +static char *sudo_getshell __P((struct passwd *)); +static struct passwd *sudo_pwdup __P((struct passwd *)); /* @@ -191,14 +192,11 @@ * Dynamically allocate space for a struct password and the constituent parts * that we care about. Fills in pw_passwd from shadow file if necessary. */ -struct passwd * -sudo_getpwuid(uid) - uid_t uid; +static struct passwd * +sudo_pwdup(pw) + struct passwd *pw; { - struct passwd *pw, *local_pw; - - if ((pw = getpwuid(uid)) == NULL) - return(NULL); + struct passwd *local_pw; /* Allocate space for a local copy of pw. */ local_pw = (struct passwd *) emalloc(sizeof(struct passwd)); @@ -217,4 +215,36 @@ local_pw->pw_passwd = estrdup(sudo_getepw(pw)); return(local_pw); +} + +/* + * Get a password entry by uid and allocate space for it. + * Fills in pw_passwd from shadow file if necessary. + */ +struct passwd * +sudo_getpwuid(uid) + uid_t uid; +{ + struct passwd *pw; + + if ((pw = getpwuid(uid)) == NULL) + return(NULL); + else + return(sudo_pwdup(pw)); +} + +/* + * Get a password entry by name and allocate space for it. + * Fills in pw_passwd from shadow file if necessary. + */ +struct passwd * +sudo_getpwnam(name) + const char *name; +{ + struct passwd *pw; + + if ((pw = getpwnam(name)) == NULL) + return(NULL); + else + return(sudo_pwdup(pw)); } diff -ur sudo-1.6.3/logging.c sudo-1.6.3p7/logging.c --- sudo-1.6.3/logging.c Mon Mar 13 09:05:05 2000 +++ sudo-1.6.3p7/logging.c Mon Feb 19 08:09:25 2001 @@ -112,7 +112,8 @@ /* * Log the full line, breaking into multiple syslog(3) calls if necessary */ - for (p = msg, count = 0; count < strlen(msg) / MAXSYSLOGLEN + 1; count++) { + for (p = msg, count = 0; *p && count < strlen(msg) / MAXSYSLOGLEN + 1; + count++) { if (strlen(p) > MAXSYSLOGLEN) { /* * Break up the line into what will fit on one syslog(3) line @@ -135,7 +136,7 @@ *tmp = save; /* restore saved character */ /* Eliminate leading whitespace */ - for (p = tmp; *p != ' '; p++) + for (p = tmp; *p != ' ' && *p !='\0'; p++) ; } else { if (count == 0) diff -ur sudo-1.6.3/parse.c sudo-1.6.3p7/parse.c --- sudo-1.6.3/parse.c Wed Mar 22 21:38:19 2000 +++ sudo-1.6.3p7/parse.c Fri Aug 11 13:47:00 2000 @@ -112,10 +112,11 @@ * allowed to run the specified command on this host as the target user. */ int -sudoers_lookup(pwflags) - int pwflags; +sudoers_lookup(sudo_mode) + int sudo_mode; { int error; + int pwcheck; /* Become sudoers file owner */ set_perms(PERM_SUDOERS, 0); @@ -128,8 +129,9 @@ /* Allocate space for data structures in the parser. */ init_parser(); - /* For most pwflags to be useful we need to keep more state around. */ - if (pwflags && pwflags != PWCHECK_NEVER && pwflags != PWCHECK_ALWAYS) + /* If pwcheck *could* be PWCHECK_ALL or PWCHECK_ANY, keep more state. */ + if (!(sudo_mode & MODE_RUN) && sudo_mode != MODE_KILL && + sudo_mode != MODE_INVALIDATE) keepall = TRUE; /* Need to be root while stat'ing things in the parser. */ @@ -144,6 +146,26 @@ return(VALIDATE_ERROR); /* + * The pw options may have changed during sudoers parse so we + * wait until now to set this. + */ + switch (sudo_mode) { + case MODE_VALIDATE: + pwcheck = def_ival(I_VERIFYPW); + break; + case MODE_LIST: + pwcheck = def_ival(I_LISTPW); + break; + case MODE_KILL: + case MODE_INVALIDATE: + pwcheck = PWCHECK_NEVER; + break; + default: + pwcheck = 0; + break; +} + + /* * Assume the worst. If the stack is empty the user was * not mentioned at all. */ @@ -151,7 +173,7 @@ error = VALIDATE_NOT_OK; else error = VALIDATE_NOT_OK | FLAG_NOPASS; - if (pwflags) { + if (pwcheck) { error |= FLAG_NO_CHECK; } else { error |= FLAG_NO_HOST; @@ -160,14 +182,14 @@ } /* - * Only check the actual command if pwflags flag is not set. + * Only check the actual command if pwcheck flag is not set. * It is set for the "validate", "list" and "kill" pseudo-commands. * Always check the host and user. */ - if (pwflags) { + if (pwcheck) { int nopass, found; - if (pwflags == PWCHECK_NEVER || !def_flag(I_AUTHENTICATE)) + if (pwcheck == PWCHECK_NEVER || !def_flag(I_AUTHENTICATE)) nopass = FLAG_NOPASS; else nopass = -1; @@ -175,9 +197,9 @@ while (top) { if (host_matches == TRUE) { found = 1; - if (pwflags == PWCHECK_ANY && no_passwd == TRUE) + if (pwcheck == PWCHECK_ANY && no_passwd == TRUE) nopass = FLAG_NOPASS; - else if (pwflags == PWCHECK_ALL && nopass != 0) + else if (pwcheck == PWCHECK_ALL && nopass != 0) nopass = (no_passwd == TRUE) ? FLAG_NOPASS : 0; } top--; diff -ur sudo-1.6.3/sudo.c sudo-1.6.3p7/sudo.c --- sudo-1.6.3/sudo.c Fri Mar 24 13:13:12 2000 +++ sudo-1.6.3p7/sudo.c Fri Aug 11 13:44:54 2000 @@ -115,8 +115,9 @@ static void add_env __P((int)); static void clean_env __P((char **, struct env_table *)); static void initial_setup __P((void)); -static void update_epasswd __P((void)); +static struct passwd *get_authpw __P((void)); extern struct passwd *sudo_getpwuid __P((uid_t)); +extern struct passwd *sudo_getpwnam __P((const char *)); extern void list_matches __P((void)); /* @@ -127,6 +128,7 @@ int NewArgc = 0; char **NewArgv = NULL; struct sudo_user sudo_user; +struct passwd *auth_pw; FILE *sudoers_fp = NULL; struct interface *interfaces; int num_interfaces; @@ -174,7 +176,6 @@ int fd; int cmnd_status; int sudo_mode; - int sudoers_flags; #ifdef POSIX_SIGNALS sigset_t set, oset; #else @@ -229,7 +230,6 @@ /* Setup defaults data structures. */ init_defaults(); - sudoers_flags = 0; if (sudo_mode & MODE_SHELL) user_cmnd = "shell"; else @@ -248,12 +248,10 @@ break; case MODE_VALIDATE: user_cmnd = "validate"; - sudoers_flags = def_ival(I_VERIFYPW); break; case MODE_KILL: case MODE_INVALIDATE: user_cmnd = "kill"; - sudoers_flags = PWCHECK_NEVER; break; case MODE_LISTDEFS: list_options(); @@ -262,7 +260,6 @@ case MODE_LIST: user_cmnd = "list"; printmatches = 1; - sudoers_flags = def_ival(I_LISTPW); break; } @@ -281,7 +278,7 @@ add_env(!(sudo_mode & MODE_SHELL)); /* add in SUDO_* envariables */ /* Validate the user but don't search for pseudo-commands. */ - validated = sudoers_lookup(sudoers_flags); + validated = sudoers_lookup(sudo_mode); /* This goes after the sudoers parse since we honor sudoers options. */ if (sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE) { @@ -316,8 +313,8 @@ (void) close(fd); } - /* Update encrypted password in user_password if sudoers said to. */ - update_epasswd(); + /* Fill in passwd struct based on user we are authenticating as. */ + auth_pw = get_authpw(); /* Require a password unless the NOPASS tag was set. */ if (!(validated & FLAG_NOPASS)) @@ -342,10 +339,6 @@ exit(0); } - /* Set $HOME for `sudo -H' */ - if ((sudo_mode & MODE_RESET_HOME) && runas_homedir) - (void) sudo_setenv("HOME", runas_homedir); - /* This *must* have been set if we got a match but... */ if (safe_cmnd == NULL) { log_error(MSG_ONLY, @@ -384,6 +377,10 @@ /* Become specified user or root. */ set_perms(PERM_RUNAS, sudo_mode); + /* Set $HOME for `sudo -H'. Only valid at PERM_RUNAS. */ + if ((sudo_mode & MODE_RESET_HOME) && runas_homedir) + (void) sudo_setenv("HOME", runas_homedir); + #ifndef PROFILING if ((sudo_mode & MODE_BACKGROUND) && fork() > 0) exit(0); @@ -1167,39 +1164,35 @@ } /* - * If the sudoers file says to prompt for a different user's password, - * update the encrypted password in user_passwd accordingly. + * Get passwd entry for the user we are going to authenticate as. + * By default, this is the user invoking sudo... */ -static void -update_epasswd() +static struct passwd * +get_authpw() { struct passwd *pw; - /* We may be configured to prompt for a password other than the user's */ if (def_ival(I_ROOTPW)) { - if ((pw = getpwuid(0)) == NULL) + if ((pw = sudo_getpwuid(0)) == NULL) log_error(0, "uid 0 does not exist in the passwd file!"); - free(user_passwd); - user_passwd = estrdup(sudo_getepw(pw)); } else if (def_ival(I_RUNASPW)) { - if ((pw = getpwnam(def_str(I_RUNAS_DEF))) == NULL) + if ((pw = sudo_getpwnam(def_str(I_RUNAS_DEF))) == NULL) log_error(0, "user %s does not exist in the passwd file!", def_str(I_RUNAS_DEF)); - free(user_passwd); - user_passwd = estrdup(sudo_getepw(pw)); } else if (def_ival(I_TARGETPW)) { if (**user_runas == '#') { - if ((pw = getpwuid(atoi(*user_runas + 1))) == NULL) + if ((pw = sudo_getpwuid(atoi(*user_runas + 1))) == NULL) log_error(0, "uid %s does not exist in the passwd file!", user_runas); } else { - if ((pw = getpwnam(*user_runas)) == NULL) + if ((pw = sudo_getpwnam(*user_runas)) == NULL) log_error(0, "user %s does not exist in the passwd file!", user_runas); } - free(user_passwd); - user_passwd = estrdup(sudo_getepw(pw)); - } + } else + pw = sudo_user.pw; + + return(pw); } /* diff -ur sudo-1.6.3/sudo.h sudo-1.6.3p7/sudo.h --- sudo-1.6.3/sudo.h Mon Mar 6 21:29:46 2000 +++ sudo-1.6.3p7/sudo.h Wed May 10 21:24:50 2000 @@ -196,7 +196,7 @@ char *tgetpass __P((const char *, int, int)); int find_path __P((char *, char **)); void check_user __P((void)); -void verify_user __P((char *)); +void verify_user __P((struct passwd *, char *)); int sudoers_lookup __P((int)); void set_perms __P((int, int)); void remove_timestamp __P((int)); @@ -208,8 +208,8 @@ VOID *emalloc __P((size_t)); VOID *erealloc __P((VOID *, size_t)); char *estrdup __P((const char *)); -void easprintf __P((char **, const char *, ...)); -void evasprintf __P((char **, const char *, va_list)); +int easprintf __P((char **, const char *, ...)); +int evasprintf __P((char **, const char *, va_list)); void dump_defaults __P((void)); void dump_auth_methods __P((void)); int lock_file __P((int, int)); @@ -222,6 +222,7 @@ /* Only provide extern declarations outside of sudo.c. */ #ifndef _SUDO_SUDO_C extern struct sudo_user sudo_user; +extern struct passwd *auth_pw; extern int Argc; extern char **Argv; diff -ur sudo-1.6.3/tgetpass.c sudo-1.6.3p7/tgetpass.c --- sudo-1.6.3/tgetpass.c Sat Feb 26 20:48:56 2000 +++ sudo-1.6.3p7/tgetpass.c Fri Aug 11 13:44:00 2000 @@ -128,7 +128,7 @@ } if (prompt) - (void) write(output, prompt, strlen(prompt) + 1); + (void) write(output, prompt, strlen(prompt)); /* Turn echo off/on as specified by flags. */ (void) term_getattr(input, &oterm); diff -ur sudo-1.6.3/version.h sudo-1.6.3p7/version.h --- sudo-1.6.3/version.h Tue Feb 15 17:07:28 2000 +++ sudo-1.6.3p7/version.h Fri Mar 2 07:14:16 2001 @@ -37,6 +37,6 @@ #ifndef _SUDO_VERSION_H #define _SUDO_VERSION_H -static const char version[] = "1.6.3"; +static const char version[] = "1.6.3p7"; #endif /* _SUDO_VERSION_H */ diff -ur sudo-1.6.3/visudo.c sudo-1.6.3p7/visudo.c --- sudo-1.6.3/visudo.c Wed Mar 22 21:38:22 2000 +++ sudo-1.6.3p7/visudo.c Sun Jun 4 20:39:01 2000 @@ -214,7 +214,6 @@ /* Parse sudoers to pull in editor and env_editor conf values. */ if ((yyin = fopen(stmp, "r"))) { yyout = stdout; - init_defaults(); init_parser(); yyparse(); parse_error = FALSE; @@ -230,7 +229,7 @@ */ if (!def_flag(I_ENV_EDITOR) || (!(Editor = getenv("EDITOR")) && !(Editor = getenv("VISUAL")))) - Editor = def_str(I_EDITOR); + Editor = estrdup(def_str(I_EDITOR)); /* * Edit the temp file and parse it (for sanity checking) @@ -286,6 +285,7 @@ } /* Clean slate for each parse */ + user_runas = NULL; init_defaults(); init_parser();