static void set_runasgr __P((char *));
static void set_runaspw __P((char *));
static void show_version __P((void));
-static struct passwd *get_authpw __P((void));
static void create_admin_success_flag __P((void));
extern int sudo_edit __P((int, char **, char **));
int run_command __P((const char *path, char *argv[], char *envp[], uid_t uid, int dowait)); /* XXX should be in sudo.h */
char *prev_user;
int user_closefrom = -1;
struct sudo_user sudo_user;
-struct passwd *auth_pw, *list_pw;
+struct passwd *list_pw;
struct interface *interfaces;
int num_interfaces;
int tgetpass_flags;
show_version();
break;
case MODE_HELP:
- usage(0);
+ help();
break;
case MODE_VALIDATE:
case MODE_VALIDATE|MODE_INVALIDATE:
/* Update initial shell now that runas is set. */
if (ISSET(sudo_mode, MODE_LOGIN_SHELL))
- NewArgv[0] = runas_pw->pw_shell;
+ NewArgv[0] = estrdup(runas_pw->pw_shell);
/* This goes after sudoers is parsed since it may have timestamp options. */
if (sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE) {
log_error(0, "timestamp owner (%s): No such user",
def_timestampowner);
timestamp_uid = pw->pw_uid;
+ pw_delref(pw);
}
/* If given the -P option, set the "preserve_groups" flag. */
/* Build a new environment that avoids any nasty bits. */
rebuild_env(def_noexec);
- /* Fill in passwd struct based on user we are authenticating as. */
- auth_pw = get_authpw();
-
/* Require a password if sudoers says so. */
if (def_authenticate)
check_user(validated, sudo_mode);
struct passwd *pw;
if ((pw = sudo_getpwnam(prev_user)) != NULL) {
+ if (sudo_user.pw != NULL)
+ pw_delref(sudo_user.pw);
sudo_user.pw = pw;
#ifdef HAVE_MBR_CHECK_MEMBERSHIP
mbr_uid_to_uuid(user_uid, user_uuid);
#endif
/* Deferred exit due to sudo_ldap_close() */
- if (ISSET(sudo_mode, (MODE_VALIDATE|MODE_CHECK|MODE_LIST)))
+ if (ISSET(sudo_mode, (MODE_VALIDATE|MODE_CHECK|MODE_LIST))) {
+ if (list_pw != NULL)
+ pw_delref(list_pw);
exit(rc);
+ }
/* Must audit before uid change. */
audit_success(NewArgv);
exit(0); /* not reached */
}
+/*
+ * Escape any non-alpha numeric or blank characters to make sure
+ * they are not interpreted specially by the shell.
+ */
+static char *
+escape_cmnd(src)
+ const char *src;
+{
+ char *cmnd, *dst;
+
+ /* Worst case scenario, we have to escape everything. */
+ cmnd = dst = emalloc((2 * strlen(src)) + 1);
+ while (*src != '\0') {
+ if (!isalnum((unsigned char)*src) && !isspace((unsigned char)*src) &&
+ *src != '_' && *src != '-') {
+ /* quote potential meta character */
+ *dst++ = '\\';
+ }
+ *dst++ = *src++;
+ }
+ *dst++ = '\0';
+
+ return cmnd;
+}
+
/*
* Initialize timezone, set umask, fill in ``sudo_user'' struct and
* load the ``interfaces'' array.
}
/*
- * Get a local copy of the user's struct passwd with the shadow password
- * if necessary. It is assumed that euid is 0 at this point so we
- * can read the shadow passwd file if necessary.
+ * Stash a local copy of the user's struct passwd.
*/
if ((sudo_user.pw = sudo_getpwuid(getuid())) == NULL) {
/* Need to make a fake struct passwd for logging to work. */
char pw_name[MAX_UID_T_LEN + 1];
pw.pw_uid = getuid();
- (void) snprintf(pw_name, sizeof(pw_name), "%lu",
- (unsigned long) pw.pw_uid);
+ (void) snprintf(pw_name, sizeof(pw_name), "%u",
+ (unsigned int) pw.pw_uid);
pw.pw_name = pw_name;
sudo_user.pw = &pw;
av[0] = user_shell; /* may be updated later */
if (NewArgc > 0) {
- size_t cmnd_size = 1024;
- char *cmnd, *src, *dst, **ap;
-
+ size_t cmnd_size;
+ char *cmnd, *src, *dst, *end;
+ cmnd_size = (size_t) (NewArgv[NewArgc - 1] - NewArgv[0]) +
+ strlen(NewArgv[NewArgc - 1]) + 1;
cmnd = dst = emalloc(cmnd_size);
- for (ap = NewArgv; *ap != NULL; ap++) {
- for (src = *ap; *src != '\0'; src++) {
- /* reserve room for an escaped char + space */
- if (cmnd_size < (dst - cmnd) + 3) {
- char *new_cmnd;
- cmnd_size <<= 1;
- new_cmnd = erealloc(cmnd, cmnd_size);
- dst = new_cmnd + (dst - cmnd);
- cmnd = new_cmnd;
- }
- if (isalnum((unsigned char)*src) || *src == '_' || *src == '-') {
- *dst++ = *src;
- } else {
- /* quote potential meta character */
- *dst++ = '\\';
- *dst++ = *src;
- }
- }
- *dst++ = ' ';
- }
- if (cmnd != dst)
- dst--; /* replace last space with a NUL */
+ src = NewArgv[0];
+ for (end = src + cmnd_size - 1; src < end; src++, dst++)
+ *dst = *src == '\0' ? ' ' : *src;
*dst = '\0';
av[1] = "-c";
av[2] = cmnd;
if (!runas_user && !runas_group)
set_runaspw(def_runas_default); /* may have been updated above */
- return(rval);
+ return rval;
}
/*
}
#endif
- /* Close the password and group files and free up memory. */
- sudo_endpwent();
- sudo_endgrent();
-
/*
* For sudoedit, the command runas a the user with no additional setup.
*/
}
#endif
+ /* Close the password and group files and free up memory. */
+ sudo_endpwent();
+ sudo_endgrent();
+ pw_delref(sudo_user.pw);
+ pw_delref(runas_pw);
+ if (runas_gr != NULL)
+ gr_delref(runas_gr);
+
rval = TRUE;
done:
- return(rval);
+ return rval;
}
/*
cstat.type = CMD_INVALID;
cstat.val = 0;
+ /* Escape meta chars if running a shell with args. */
+ if (ISSET(sudo_mode, MODE_SHELL) && argv[1] != NULL) {
+ char *cmnd = argv[2];
+ argv[2] = escape_cmnd(cmnd);
+ efree(cmnd);
+ }
+
sudo_execve(path, argv, envp, uid, &cstat, dowait,
ISSET(sudo_mode, MODE_BACKGROUND));
#ifdef _PATH_SUDO_IO_LOGDIR
io_log_close();
#endif
- return(exitcode);
+ sudo_endpwent();
+ sudo_endgrent();
+ pw_delref(sudo_user.pw);
+ pw_delref(runas_pw);
+ if (runas_gr != NULL)
+ gr_delref(runas_gr);
+ return exitcode;
}
/*
log_error(USE_ERRNO|NO_EXIT, "can't stat %s", sudoers);
else if (!S_ISREG(statbuf.st_mode))
log_error(NO_EXIT, "%s is not a regular file", sudoers);
- else if ((statbuf.st_mode & 07777) != SUDOERS_MODE)
+ else if ((statbuf.st_mode & 07577) != SUDOERS_MODE)
log_error(NO_EXIT, "%s is mode 0%o, should be 0%o", sudoers,
(unsigned int) (statbuf.st_mode & 07777),
(unsigned int) SUDOERS_MODE);
else if (statbuf.st_uid != SUDOERS_UID)
- log_error(NO_EXIT, "%s is owned by uid %lu, should be %lu", sudoers,
- (unsigned long) statbuf.st_uid, (unsigned long) SUDOERS_UID);
+ log_error(NO_EXIT, "%s is owned by uid %u, should be %u", sudoers,
+ (unsigned int) statbuf.st_uid, (unsigned int) SUDOERS_UID);
else if (statbuf.st_gid != SUDOERS_GID)
- log_error(NO_EXIT, "%s is owned by gid %lu, should be %lu", sudoers,
- (unsigned long) statbuf.st_gid, (unsigned long) SUDOERS_GID);
+ log_error(NO_EXIT, "%s is owned by gid %u, should be %u", sudoers,
+ (unsigned int) statbuf.st_gid, (unsigned int) SUDOERS_GID);
else if ((fp = fopen(sudoers, "r")) == NULL)
log_error(USE_ERRNO|NO_EXIT, "can't open %s", sudoers);
else {
}
set_perms(PERM_ROOT); /* change back to root */
- return(fp);
+ return fp;
}
/*
initial_setup()
{
int miss[3], devnull = -1;
+ sigset_t mask;
#if defined(__linux__) || (defined(RLIMIT_CORE) && !defined(SUDO_DEVEL))
struct rlimit rl;
#endif
+ /* Reset signal mask. */
+ (void) sigemptyset(&mask);
+ (void) sigprocmask(SIG_SETMASK, &mask, NULL);
+
#if defined(__linux__)
/*
* Unlimit the number of processes since Linux's setuid() will
}
/*
- * Get passwd entry for the user we are going to run commands as.
- * By default, this is "root". Updates runas_pw as a side effect.
+ * Get passwd entry for the user we are going to run commands as
+ * and store it in runas_pw. By default, commands run as "root".
*/
static void
set_runaspw(user)
char *user;
{
+ if (runas_pw != NULL)
+ pw_delref(runas_pw);
if (*user == '#') {
if ((runas_pw = sudo_getpwuid(atoi(user + 1))) == NULL)
runas_pw = sudo_fakepwnam(user, runas_gr ? runas_gr->gr_gid : 0);
}
/*
- * Get group entry for the group we are going to run commands as.
- * Updates runas_pw as a side effect.
+ * Get group entry for the group we are going to run commands as
+ * and store it in runas_gr.
*/
static void
set_runasgr(group)
char *group;
{
+ if (runas_gr != NULL)
+ gr_delref(runas_gr);
if (*group == '#') {
if ((runas_gr = sudo_getgrgid(atoi(group + 1))) == NULL)
runas_gr = sudo_fakegrnam(group);
}
}
-/*
- * Get passwd entry for the user we are going to authenticate as.
- * By default, this is the user invoking sudo. In the most common
- * case, this matches sudo_user.pw or runas_pw.
- */
-static struct passwd *
-get_authpw()
-{
- struct passwd *pw;
-
- if (def_rootpw) {
- if ((pw = sudo_getpwuid(0)) == NULL)
- log_error(0, "unknown uid: 0");
- } else if (def_runaspw) {
- if ((pw = sudo_getpwnam(def_runas_default)) == NULL)
- log_error(0, "unknown user: %s", def_runas_default);
- } else if (def_targetpw) {
- if (runas_pw->pw_name == NULL)
- log_error(NO_MAIL|MSG_ONLY, "unknown uid: %lu",
- (unsigned long) runas_pw->pw_uid);
- pw = runas_pw;
- } else
- pw = sudo_user.pw;
-
- return(pw);
-}
-
/*
* Cleanup hook for error()/errorx()
*/