initialized in the "init" or "setup" routines.
Possible values of sudo_auth.flags:
- FLAG_ROOT Whether or not the auth functions should run with
- an euid of 0 or the uid of the invoking user.
+ FLAG_USER Whether or not the auth functions should run with
+ the euid of the invoking user instead of 0.
FLAG_CONFIGURED If set then the auth method is assumed to have been
configured successfully. All auth methods start out
#elif defined(HAVE_FOOAUTH)
# define AUTH_STANDALONE \
- AUTH_ENTRY(FLAG_ROOT, "foo", \
+ AUTH_ENTRY(0, "foo", \
foo_init, foo_setup, foo_verify, foo_cleanup)
-If the method doesn't need to run as root, replace FLAG_ROOT with 0.
-If you don't have a init/setup/cleanup routine, just use a NULL for that
-field.
+If the method needs to run as the user, not root, replace the first
+parameter to AUTH_ENTRY (0) with FLAG_USER. If you don't have a
+init/setup/cleanup routine, just use a NULL for that field.
For a normal authentication method, add it to the ``auth_switch'' in
sudo_auth.c. If ``fooauth'' is a normal auth method, its entry
would look like:
# ifdef HAVE_FOOAUTH
- AUTH_ENTRY(FLAG_ROOT, "foo", foo_init, foo_setup, foo_verify, foo_cleanup)
+ AUTH_ENTRY(0, "foo", foo_init, foo_setup, foo_verify, foo_cleanup)
# endif
-Again, if the method doesn't need to run as root, replace FLAG_ROOT
-with 0. Likewise, if you don't have a init/setup/cleanup routine,
+Again, if the method doesn't need to run as root, replace the 0 with
+FLAG_USER. Likewise, if you don't have a init/setup/cleanup routine,
just use a NULL for that field.
NOTE: You should not make a method both ``standalone'' and
AUTH_STANDALONE
#else
# ifndef WITHOUT_PASSWD
- AUTH_ENTRY(FLAG_ROOT, "passwd", NULL, NULL, passwd_verify, NULL)
+ AUTH_ENTRY(0, "passwd", NULL, NULL, passwd_verify, NULL)
# endif
# if defined(HAVE_SECUREWARE) && !defined(WITHOUT_PASSWD)
- AUTH_ENTRY(FLAG_ROOT, "secureware", secureware_init, NULL, secureware_verify, NULL)
+ AUTH_ENTRY(0, "secureware", secureware_init, NULL, secureware_verify, NULL)
# endif
# ifdef HAVE_AFS
- AUTH_ENTRY(FLAG_ROOT, "afs", NULL, NULL, afs_verify, NULL)
+ AUTH_ENTRY(0, "afs", NULL, NULL, afs_verify, NULL)
# endif
# ifdef HAVE_KERB4
- AUTH_ENTRY(FLAG_ROOT, "kerb4", kerb4_init, NULL, kerb4_verify, NULL)
+ AUTH_ENTRY(0, "kerb4", kerb4_init, NULL, kerb4_verify, NULL)
# endif
# ifdef HAVE_KERB5
- AUTH_ENTRY(FLAG_ROOT, "kerb5", kerb5_init, NULL, kerb5_verify, NULL)
+ AUTH_ENTRY(0, "kerb5", kerb5_init, NULL, kerb5_verify, NULL)
# endif
# ifdef HAVE_SKEY
- AUTH_ENTRY(FLAG_ROOT, "S/Key", NULL, rfc1938_setup, rfc1938_verify, NULL)
+ AUTH_ENTRY(0, "S/Key", NULL, rfc1938_setup, rfc1938_verify, NULL)
# endif
# ifdef HAVE_OPIE
- AUTH_ENTRY(FLAG_ROOT, "OPIE", NULL, rfc1938_setup, rfc1938_verify, NULL)
+ AUTH_ENTRY(0, "OPIE", NULL, rfc1938_setup, rfc1938_verify, NULL)
# endif
#endif /* AUTH_STANDALONE */
AUTH_ENTRY(0, NULL, NULL, NULL, NULL, NULL)
/* Initialize auth methods and unconfigure the method if necessary. */
for (auth = auth_switch; auth->name; auth++) {
if (auth->init && IS_CONFIGURED(auth)) {
- if (NEEDS_ROOT(auth))
- set_perms(PERM_ROOT, 0);
+ if (NEEDS_USER(auth))
+ set_perms(PERM_USER, 0);
status = (auth->init)(sudo_user.pw, &user_prompt, auth);
if (status == AUTH_FAILURE)
else if (status == AUTH_FATAL) /* XXX log */
exit(1); /* assume error msg already printed */
- if (NEEDS_ROOT(auth))
- set_perms(PERM_USER, 0);
+ if (NEEDS_USER(auth))
+ set_perms(PERM_ROOT, 0);
}
}
/* Do any per-method setup and unconfigure the method if needed */
for (auth = auth_switch; auth->name; auth++) {
if (auth->setup && IS_CONFIGURED(auth)) {
- if (NEEDS_ROOT(auth))
- set_perms(PERM_ROOT, 0);
+ if (NEEDS_USER(auth))
+ set_perms(PERM_USER, 0);
status = (auth->setup)(sudo_user.pw, &user_prompt, auth);
if (status == AUTH_FAILURE)
else if (status == AUTH_FATAL) /* XXX log */
exit(1); /* assume error msg already printed */
- if (NEEDS_ROOT(auth))
- set_perms(PERM_USER, 0);
+ if (NEEDS_USER(auth))
+ set_perms(PERM_ROOT, 0);
}
}
if (!IS_CONFIGURED(auth))
continue;
- if (NEEDS_ROOT(auth))
- set_perms(PERM_ROOT, 0);
+ if (NEEDS_USER(auth))
+ set_perms(PERM_USER, 0);
success = auth->status = (auth->verify)(sudo_user.pw, p, auth);
(void) memset(p, 0, strlen(p));
- if (NEEDS_ROOT(auth))
- set_perms(PERM_USER, 0);
+ if (NEEDS_USER(auth))
+ set_perms(PERM_ROOT, 0);
if (auth->status != AUTH_FAILURE)
goto cleanup;
/* Call cleanup routines. */
for (auth = auth_switch; auth->name; auth++) {
if (auth->cleanup && IS_CONFIGURED(auth)) {
- if (NEEDS_ROOT(auth))
- set_perms(PERM_ROOT, 0);
+ if (NEEDS_USER(auth))
+ set_perms(PERM_USER, 0);
status = (auth->cleanup)(sudo_user.pw, auth);
if (status == AUTH_FATAL) /* XXX log */
exit(1); /* assume error msg already printed */
- if (NEEDS_ROOT(auth))
- set_perms(PERM_USER, 0);
+ if (NEEDS_USER(auth))
+ set_perms(PERM_ROOT, 0);
}
}
/* Values for sudo_auth.flags. */
/* XXX - these names are too long for my liking */
-#define FLAG_ROOT 0x01 /* functions must run as root */
+#define FLAG_USER 0x01 /* functions must run as root */
#define FLAG_CONFIGURED 0x02 /* method configured ok */
#define FLAG_ONEANDONLY 0x04 /* one and only auth method */
/* Shortcuts for using the flags above. */
-#define NEEDS_ROOT(x) ((x)->flags & FLAG_ROOT)
+#define NEEDS_USER(x) ((x)->flags & FLAG_USER)
#define IS_CONFIGURED(x) ((x)->flags & FLAG_CONFIGURED)
#define IS_ONEANDONLY(x) ((x)->flags & FLAG_ONEANDONLY)
/* Some methods cannots (or should not) interoperate with any others */
#if defined(HAVE_PAM)
# define AUTH_STANDALONE \
- AUTH_ENTRY(FLAG_ROOT, "pam", \
+ AUTH_ENTRY(0, "pam", \
pam_init, NULL, pam_verify, pam_cleanup)
#elif defined(HAVE_SECURID)
# define AUTH_STANDALONE \
- AUTH_ENTRY(FLAG_ROOT, "SecurId", \
+ AUTH_ENTRY(0, "SecurId",
securid_init, securid_setup, securid_verify, NULL)
#elif defined(HAVE_SIA)
# define AUTH_STANDALONE \
- AUTH_ENTRY(FLAG_ROOT, "sia", \
+ AUTH_ENTRY(0, "sia", \
NULL, sia_setup, sia_verify, sia_cleanup)
#elif defined(HAVE_DCE)
# define AUTH_STANDALONE \
- AUTH_ENTRY(FLAG_ROOT, "dce", \
+ AUTH_ENTRY(0, "dce", \
NULL, NULL, dce_verify, NULL)
#elif defined(HAVE_AUTHENTICATE)
# define AUTH_STANDALONE \
- AUTH_ENTRY(FLAG_ROOT, "aixauth", \
+ AUTH_ENTRY(0, "aixauth", \
NULL, NULL, aixauth_verify, NULL)
#elif defined(HAVE_FWTK)
# define AUTH_STANDALONE \
- AUTH_ENTRY(FLAG_ROOT, "fwtk", fwtk_init, \
+ AUTH_ENTRY(0, "fwtk", fwtk_init, \
NULL, fwtk_verify, fwtk_cleanup)
#endif
char *timestampfile;
{
- set_perms(PERM_ROOT, 0); /* become root */
-
if (touch(timestampfile ? timestampfile : timestampdir, time(NULL)) == -1) {
if (timestampfile) {
int fd = open(timestampfile, O_WRONLY|O_CREAT|O_TRUNC, 0600);
log_error(NO_EXIT|USE_ERRNO, "Can't mkdir %s", timestampdir);
}
}
-
- set_perms(PERM_USER, 0); /* relinquish root */
}
/*
time_t now;
int status = TS_ERROR; /* assume the worst */
- set_perms(PERM_ROOT, 0); /* become root */
-
/*
* Sanity check _PATH_SUDO_TIMEDIR and make it if it doesn't already exist.
* We start out assuming the worst (that the dir is not sane) and
status = TS_MISSING;
}
}
- if (status == TS_ERROR) {
- set_perms(PERM_USER, 0); /* relinquish root */
+ if (status == TS_ERROR)
return(status);
- }
/*
* Sanity check the user's ticket dir. We start by downgrading
}
}
- set_perms(PERM_USER, 0); /* relinquish root */
return(status);
}
status = timestamp_status(timestampdir, timestampfile, user_name, FALSE);
if (status == TS_OLD || status == TS_CURRENT) {
ts = timestampfile ? timestampfile : timestampdir;
- set_perms(PERM_ROOT, 0); /* become root */
if (remove) {
if (timestampfile)
status = unlink(timestampfile);
(void) fprintf(stderr, "%s: can't reset %s to epoch: %s\n",
Argv[0], ts, strerror(errno));
}
- set_perms(PERM_USER, 0); /* relinquish root */
}
(void) free(timestampdir);
path = estrdup(path);
origpath = path;
- /* XXX use strtok() */
do {
if ((n = strchr(path, ':')))
*n = '\0';
const char *path;
{
struct stat sb;
- int err;
/* Check for brain damage */
if (path == NULL || path[0] == '\0')
return(NULL);
- /* Do the stat() as root. */
- set_perms(PERM_ROOT, 0);
- err = stat(path, &sb);
- set_perms(PERM_USER, 0);
-
- /* stat() failed */
- if (err)
+ if (stat(path, &sb))
return(NULL);
/* Make sure path describes an executable regular file. */
FILE *fp;
mode_t oldmask;
time_t now;
- int oldeuid = geteuid();
int maxlen = MAXLOGFILELEN;
now = time((time_t) 0);
- /* Become root if we are not already. */
- if (oldeuid)
- set_perms(PERM_ROOT, 0);
-
oldmask = umask(077);
fp = fopen(_PATH_SUDO_LOGFILE, "a");
(void) umask(oldmask);
(void) lock_file(fileno(fp), SUDO_UNLOCK);
(void) fclose(fp);
}
-
- if (oldeuid)
- set_perms(PERM_USER, 0); /* relinquish root */
}
#endif /* LOGGING & SLOG_FILE */
mail_auth(status, logline); /* send mail based on status */
/* Inform the user if they failed to authenticate. */
- if (inform_user) {
+ if (inform_user && (status & VALIDATE_NOT_OK)) {
if (status & FLAG_NO_USER)
(void) fprintf(stderr, "%s is not in the sudoers file. %s",
user_name, "This incident will be reported.\n");
else if (status & FLAG_NO_HOST)
(void) fprintf(stderr, "%s is not allowed to run sudo on %s. %s",
user_name, user_shost, "This incident will be reported.\n");
- else if (status & VALIDATE_NOT_OK)
+ else
(void) fprintf(stderr,
"Sorry, user %s is not allowed to execute '%s%s%s' as %s on %s.\n",
user_name, user_cmnd, user_args ? " " : "",
user_args ? user_args : "", user_runas, user_host);
- else
- (void) fprintf(stderr, "An unknown error has occurred.\n");
}
/*
fmt = va_arg(ap, const char *);
#endif
+ /* Become root if we are not already to avoid user control */
+ if (geteuid() != 0)
+ set_perms(PERM_ROOT, 0);
+
/* Expand printf-style format + args. */
evasprintf(&message, fmt, ap);
va_end(ap);
free(message);
}
+/*
+ * Send a message to ALERTMAIL
+ */
#ifdef _PATH_SENDMAIL
static void
send_mail(line)
user_name, line);
fclose(mail);
reapchild(0);
- exit(0);
+ _exit(0);
} else {
/* Parent, just return unless there is an error. */
if (pid == -1) {
{
int mail_mask;
+ /* If any of these bits are set in status, we send mail. */
mail_mask = VALIDATE_ERROR;
#ifdef SEND_MAIL_WHEN_OK
mail_mask |= VALIDATE_OK;
yyin = sudoers_fp;
yyout = stdout;
- /*
- * Allocate space for data structures in the parser.
- */
+ /* Allocate space for data structures in the parser. */
init_parser();
- /*
- * Need to be root while stat'ing things in the parser.
- */
+ /* Need to be root while stat'ing things in the parser. */
set_perms(PERM_ROOT, 0);
error = yyparse();
- /*
- * Don't need to keep this open...
- */
+ /* Close the sudoers file now that we are done with it. */
(void) fclose(sudoers_fp);
sudoers_fp = NULL;
- /* relinquish extra privs */
- set_perms(PERM_USER, 0);
-
if (error || parse_error)
return(VALIDATE_ERROR);
}
/*
- * Only check the actual command if the check_cmnd
- * flag is set. It is not set for the "validate"
- * and "list" pseudo-commands. Always check the
- * host and user.
+ * Only check the actual command if the check_cmnd flag is set.
+ * It is not set for the "validate" and "list" pseudo-commands.
+ * Always check the host and user.
*/
if (check_cmnd == FALSE)
while (top) {
cmnd_status = init_vars(sudo_mode);
- set_perms(PERM_USER, sudo_mode);
+ /* At this point, ruid == euid == 0 */
check_sudoers(); /* check mode/owner on _PATH_SUDOERS */
* Fix the mode and group on sudoers file from old default.
* Only works if filesystem is readable/writable by root.
*/
- set_perms(PERM_ROOT, 0);
if ((rootstat = lstat(_PATH_SUDOERS, &statbuf)) == 0 &&
SUDOERS_UID == statbuf.st_uid && SUDOERS_MODE != 0400 &&
(statbuf.st_mode & 0007777) == 0400) {
log_error(USE_ERRNO, "can't open %s", _PATH_SUDOERS);
}
- set_perms(PERM_ROOT, 0);
- set_perms(PERM_USER, 0);
+ set_perms(PERM_ROOT, 0); /* change back to root */
}
/*