else
state.lc = login_getclass(pw->pw_uid ? LOGIN_DEFCLASS : LOGIN_DEFROOTCLASS);
if (state.lc == NULL) {
- log_error(USE_ERRNO|NO_EXIT|NO_MAIL,
+ log_error(USE_ERRNO|NO_MAIL,
"unable to get login class for user %s", pw->pw_name);
return AUTH_FATAL;
}
if ((state.as = auth_open()) == NULL) {
- log_error(USE_ERRNO|NO_EXIT|NO_MAIL,
+ log_error(USE_ERRNO|NO_MAIL,
"unable to begin bsd authentication");
login_close(state.lc);
return AUTH_FATAL;
/* XXX - maybe sanity check the auth style earlier? */
login_style = login_getstyle(state.lc, login_style, "auth-sudo");
if (login_style == NULL) {
- log_error(NO_EXIT|NO_MAIL, "invalid authentication type");
+ log_error(NO_MAIL, "invalid authentication type");
auth_close(state.as);
login_close(state.lc);
return AUTH_FATAL;
if (auth_setitem(state.as, AUTHV_STYLE, login_style) < 0 ||
auth_setitem(state.as, AUTHV_NAME, pw->pw_name) < 0 ||
auth_setitem(state.as, AUTHV_CLASS, login_class) < 0) {
- log_error(NO_EXIT|NO_MAIL, "unable to setup authentication");
+ log_error(NO_MAIL, "unable to setup authentication");
auth_close(state.as);
login_close(state.lc);
return AUTH_FATAL;
return AUTH_INTR;
if ((s = auth_getvalue(as, "errormsg")) != NULL)
- log_error(NO_EXIT|NO_MAIL, "%s", s);
+ log_error(NO_MAIL, "%s", s);
return AUTH_FAILURE;
}
* API does not currently provide this unless the auth is standalone.
*/
if ((error = krb5_unparse_name(sudo_context, princ, &pname))) {
- log_error(NO_EXIT|NO_MAIL,
+ log_error(NO_MAIL,
"%s: unable to unparse princ ('%s'): %s", auth->name,
pw->pw_name, error_message(error));
return AUTH_FAILURE;
if ((error = krb5_parse_name(sudo_context, pw->pw_name,
&(sudo_krb5_data.princ)))) {
- log_error(NO_EXIT|NO_MAIL,
+ log_error(NO_MAIL,
"%s: unable to parse '%s': %s", auth->name, pw->pw_name,
error_message(error));
return AUTH_FAILURE;
(long) getpid());
if ((error = krb5_cc_resolve(sudo_context, cache_name,
&(sudo_krb5_data.ccache)))) {
- log_error(NO_EXIT|NO_MAIL,
+ log_error(NO_MAIL,
"%s: unable to resolve ccache: %s", auth->name,
error_message(error));
return AUTH_FAILURE;
/* Set default flags based on the local config file. */
error = krb5_get_init_creds_opt_alloc(sudo_context, &opts);
if (error) {
- log_error(NO_EXIT|NO_MAIL,
+ log_error(NO_MAIL,
"%s: unable to allocate options: %s", auth->name,
error_message(error));
goto done;
NULL, 0, NULL, opts))) {
/* Don't print error if just a bad password */
if (error != KRB5KRB_AP_ERR_BAD_INTEGRITY)
- log_error(NO_EXIT|NO_MAIL,
+ log_error(NO_MAIL,
"%s: unable to get credentials: %s", auth->name,
error_message(error));
goto done;
/* Store cred in cred cache. */
if ((error = krb5_cc_initialize(sudo_context, ccache, princ))) {
- log_error(NO_EXIT|NO_MAIL,
+ log_error(NO_MAIL,
"%s: unable to initialize ccache: %s", auth->name,
error_message(error));
} else if ((error = krb5_cc_store_cred(sudo_context, ccache, creds))) {
- log_error(NO_EXIT|NO_MAIL,
+ log_error(NO_MAIL,
"%s: unable to store cred in ccache: %s", auth->name,
error_message(error));
}
*/
if ((error = krb5_sname_to_principal(sudo_context, NULL, NULL,
KRB5_NT_SRV_HST, &server))) {
- log_error(NO_EXIT|NO_MAIL,
+ log_error(NO_MAIL,
"%s: unable to get host principal: %s", auth_name,
error_message(error));
return -1;
NULL, &vopt);
krb5_free_principal(sudo_context, server);
if (error)
- log_error(NO_EXIT|NO_MAIL,
+ log_error(NO_MAIL,
"%s: Cannot verify TGT! Possible attack!: %s", auth_name,
error_message(error));
return error;
pam_status = pam_start("sudo", pw->pw_name, &pam_conv, &pamh);
if (pam_status != PAM_SUCCESS) {
- log_error(USE_ERRNO|NO_EXIT|NO_MAIL, "unable to initialize PAM");
+ log_error(USE_ERRNO|NO_MAIL, "unable to initialize PAM");
return AUTH_FATAL;
}
case PAM_SUCCESS:
return AUTH_SUCCESS;
case PAM_AUTH_ERR:
- log_error(NO_EXIT|NO_MAIL,
+ log_error(NO_MAIL,
"account validation failure, is your account locked?");
return AUTH_FATAL;
case PAM_NEW_AUTHTOK_REQD:
- log_error(NO_EXIT|NO_MAIL, "%s, %s",
+ log_error(NO_MAIL, "%s, %s",
"Account or password is expired",
"reset your password and try again");
*pam_status = pam_chauthtok(pamh,
if (*pam_status == PAM_SUCCESS)
return AUTH_SUCCESS;
if ((s = pam_strerror(pamh, *pam_status)))
- log_error(NO_EXIT|NO_MAIL, "pam_chauthtok: %s", s);
+ log_error(NO_MAIL, "pam_chauthtok: %s", s);
return AUTH_FAILURE;
case PAM_AUTHTOK_EXPIRED:
- log_error(NO_EXIT|NO_MAIL,
+ log_error(NO_MAIL,
"Password expired, contact your system administrator");
return AUTH_FATAL;
case PAM_ACCT_EXPIRED:
- log_error(NO_EXIT|NO_MAIL, "%s %s",
+ log_error(NO_MAIL, "%s %s",
"Account expired or PAM config lacks an \"account\"",
"section for sudo, contact your system administrator");
return AUTH_FATAL;
return AUTH_FAILURE;
default:
if ((s = pam_strerror(pamh, *pam_status)))
- log_error(NO_EXIT|NO_MAIL, "pam_authenticate: %s", s);
+ log_error(NO_MAIL, "pam_authenticate: %s", s);
return AUTH_FATAL;
}
}
if (sia_ses_init(&siah, Argc, Argv, NULL, pw->pw_name, ttyname(0), 1, NULL)
!= SIASUCCESS) {
- log_error(USE_ERRNO|NO_EXIT|NO_MAIL,
+ log_error(USE_ERRNO|NO_MAIL,
"unable to initialize SIA session");
return AUTH_FATAL;
}
#ifdef HAVE_BSM_AUDIT
audit_failure(NewArgv, "no authentication methods");
#endif
- log_error(0, "%s %s %s",
+ log_fatal(0, "%s %s %s",
"There are no authentication methods compiled into sudo!",
"If you want to turn off authentication, use the",
"--disable-authentication configure option.");
#ifdef HAVE_BSM_AUDIT
audit_failure(NewArgv, "authentication failure");
#endif
- log_error(flags, "%d incorrect password attempt%s",
+ log_fatal(flags, "%d incorrect password attempt%s",
def_passwd_tries - counter,
(def_passwd_tries - counter == 1) ? "" : "s");
}
# define AUDIT_NOT_CONFIGURED ENOSYS
#endif
-void log_error(int flags, const char *fmt, ...) __attribute__((__noreturn__));
+void log_fatal(int flags, const char *fmt, ...) __attribute__((__noreturn__));
static int
audit_sudo_selected(int sf)
if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) < 0) {
if (errno == ENOSYS) {
if (getaudit(&ainfo) < 0)
- log_error(0, "getaudit: failed");
+ log_fatal(0, "getaudit: failed");
mask = &ainfo.ai_mask;
} else
- log_error(0, "getaudit: failed");
+ log_fatal(0, "getaudit: failed");
} else
mask = &ainfo_addr.ai_mask;
sorf = (sf == 0) ? AU_PRS_SUCCESS : AU_PRS_FAILURE;
if (auditon(A_GETCOND, (caddr_t)&au_cond, sizeof(long)) < 0) {
if (errno == AUDIT_NOT_CONFIGURED)
return;
- log_error(0, "Could not determine audit condition");
+ log_fatal(0, "Could not determine audit condition");
}
if (au_cond == AUC_NOAUDIT)
return;
if (!audit_sudo_selected(0))
return;
if (getauid(&auid) < 0)
- log_error(0, "getauid failed");
+ log_fatal(0, "getauid failed");
if ((aufd = au_open()) == -1)
- log_error(0, "au_open: failed");
+ log_fatal(0, "au_open: failed");
if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) == 0) {
tok = au_to_subject_ex(auid, geteuid(), getegid(), getuid(),
getuid(), pid, pid, &ainfo_addr.ai_termid);
* NB: We should probably watch out for ERANGE here.
*/
if (getaudit(&ainfo) < 0)
- log_error(0, "getaudit: failed");
+ log_fatal(0, "getaudit: failed");
tok = au_to_subject(auid, geteuid(), getegid(), getuid(),
getuid(), pid, pid, &ainfo.ai_termid);
} else
- log_error(0, "getaudit: failed");
+ log_fatal(0, "getaudit: failed");
if (tok == NULL)
- log_error(0, "au_to_subject: failed");
+ log_fatal(0, "au_to_subject: failed");
au_write(aufd, tok);
tok = au_to_exec_args(exec_args);
if (tok == NULL)
- log_error(0, "au_to_exec_args: failed");
+ log_fatal(0, "au_to_exec_args: failed");
au_write(aufd, tok);
tok = au_to_return32(0, 0);
if (tok == NULL)
- log_error(0, "au_to_return32: failed");
+ log_fatal(0, "au_to_return32: failed");
au_write(aufd, tok);
if (au_close(aufd, 1, AUE_sudo) == -1)
- log_error(0, "unable to commit audit record");
+ log_fatal(0, "unable to commit audit record");
}
void
if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) {
if (errno == AUDIT_NOT_CONFIGURED)
return;
- log_error(0, "Could not determine audit condition");
+ log_fatal(0, "Could not determine audit condition");
}
if (au_cond == AUC_NOAUDIT)
return;
if (!audit_sudo_selected(1))
return;
if (getauid(&auid) < 0)
- log_error(0, "getauid: failed");
+ log_fatal(0, "getauid: failed");
if ((aufd = au_open()) == -1)
- log_error(0, "au_open: failed");
+ log_fatal(0, "au_open: failed");
if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) == 0) {
tok = au_to_subject_ex(auid, geteuid(), getegid(), getuid(),
getuid(), pid, pid, &ainfo_addr.ai_termid);
} else if (errno == ENOSYS) {
if (getaudit(&ainfo) < 0)
- log_error(0, "getaudit: failed");
+ log_fatal(0, "getaudit: failed");
tok = au_to_subject(auid, geteuid(), getegid(), getuid(),
getuid(), pid, pid, &ainfo.ai_termid);
} else
- log_error(0, "getaudit: failed");
+ log_fatal(0, "getaudit: failed");
if (tok == NULL)
- log_error(0, "au_to_subject: failed");
+ log_fatal(0, "au_to_subject: failed");
au_write(aufd, tok);
tok = au_to_exec_args(exec_args);
if (tok == NULL)
- log_error(0, "au_to_exec_args: failed");
+ log_fatal(0, "au_to_exec_args: failed");
au_write(aufd, tok);
(void) vsnprintf(text, sizeof(text), fmt, ap);
tok = au_to_text(text);
if (tok == NULL)
- log_error(0, "au_to_text: failed");
+ log_fatal(0, "au_to_text: failed");
au_write(aufd, tok);
tok = au_to_return32(EPERM, 1);
if (tok == NULL)
- log_error(0, "au_to_return32: failed");
+ log_fatal(0, "au_to_return32: failed");
au_write(aufd, tok);
if (au_close(aufd, 1, AUE_sudo) == -1)
- log_error(0, "unable to commit audit record");
+ log_fatal(0, "unable to commit audit record");
}
/* If user specified -A, make sure we have an askpass helper. */
if (ISSET(tgetpass_flags, TGP_ASKPASS)) {
if (user_askpass == NULL)
- log_error(NO_MAIL,
+ log_fatal(NO_MAIL,
"no askpass program specified, try setting SUDO_ASKPASS");
} else if (!ISSET(tgetpass_flags, TGP_STDIN)) {
/* If no tty but DISPLAY is set, use askpass if we have it. */
if (user_askpass && user_display && *user_display != '\0') {
SET(tgetpass_flags, TGP_ASKPASS);
} else if (!def_visiblepw) {
- log_error(NO_MAIL,
+ log_fatal(NO_MAIL,
"no tty present and no askpass program specified");
}
}
*/
int fd = open(timestampfile, O_WRONLY|O_CREAT, 0600);
if (fd == -1)
- log_error(NO_EXIT|USE_ERRNO, "Can't open %s", timestampfile);
+ log_error(USE_ERRNO, "Can't open %s", timestampfile);
else {
lock_file(fd, SUDO_LOCK);
if (write(fd, &tty_info, sizeof(tty_info)) != sizeof(tty_info))
- log_error(NO_EXIT|USE_ERRNO, "Can't write %s", timestampfile);
+ log_error(USE_ERRNO, "Can't write %s", timestampfile);
close(fd);
}
} else {
if (touch(-1, timestampdir, NULL) == -1) {
if (mkdir(timestampdir, 0700) == -1)
- log_error(NO_EXIT|USE_ERRNO, "Can't mkdir %s", timestampdir);
+ log_error(USE_ERRNO, "Can't mkdir %s", timestampdir);
}
}
if (timestamp_uid != 0)
dirparent = def_timestampdir;
len = easprintf(timestampdir, "%s/%s", dirparent, user_name);
if (len >= PATH_MAX)
- log_error(0, "timestamp path too long: %s", *timestampdir);
+ log_fatal(0, "timestamp path too long: %s", *timestampdir);
/*
* Timestamp file may be a file in the directory or NUL to use
else
len = easprintf(timestampfile, "%s/%s/%s", dirparent, user_name, p);
if (len >= PATH_MAX)
- log_error(0, "timestamp path too long: %s", *timestampfile);
+ log_fatal(0, "timestamp path too long: %s", *timestampfile);
} else if (def_targetpw) {
len = easprintf(timestampfile, "%s/%s/%s", dirparent, user_name,
runas_pw->pw_name);
if (len >= PATH_MAX)
- log_error(0, "timestamp path too long: %s", *timestampfile);
+ log_fatal(0, "timestamp path too long: %s", *timestampfile);
} else
*timestampfile = NULL;
}
*/
if (lstat(dirparent, &sb) == 0) {
if (!S_ISDIR(sb.st_mode))
- log_error(NO_EXIT, "%s exists but is not a directory (0%o)",
+ log_error(0, "%s exists but is not a directory (0%o)",
dirparent, (unsigned int) sb.st_mode);
else if (sb.st_uid != timestamp_uid)
- log_error(NO_EXIT, "%s owned by uid %u, should be uid %u",
+ log_error(0, "%s owned by uid %u, should be uid %u",
dirparent, (unsigned int) sb.st_uid,
(unsigned int) timestamp_uid);
else if ((sb.st_mode & 0000022))
- log_error(NO_EXIT,
+ log_error(0,
"%s writable by non-owner (0%o), should be mode 0700",
dirparent, (unsigned int) sb.st_mode);
else {
status = TS_MISSING;
}
} else if (errno != ENOENT) {
- log_error(NO_EXIT|USE_ERRNO, "can't stat %s", dirparent);
+ log_error(USE_ERRNO, "can't stat %s", dirparent);
} else {
/* No dirparent, try to make one. */
if (ISSET(flags, TS_MAKE_DIRS)) {
if (mkdir(dirparent, S_IRWXU))
- log_error(NO_EXIT|USE_ERRNO, "can't mkdir %s",
+ log_error(USE_ERRNO, "can't mkdir %s",
dirparent);
else
status = TS_MISSING;
if (unlink(timestampdir) == 0)
status = TS_MISSING;
} else
- log_error(NO_EXIT, "%s exists but is not a directory (0%o)",
+ log_error(0, "%s exists but is not a directory (0%o)",
timestampdir, (unsigned int) sb.st_mode);
} else if (sb.st_uid != timestamp_uid)
- log_error(NO_EXIT, "%s owned by uid %u, should be uid %u",
+ log_error(0, "%s owned by uid %u, should be uid %u",
timestampdir, (unsigned int) sb.st_uid,
(unsigned int) timestamp_uid);
else if ((sb.st_mode & 0000022))
- log_error(NO_EXIT,
+ log_error(0,
"%s writable by non-owner (0%o), should be mode 0700",
timestampdir, (unsigned int) sb.st_mode);
else {
status = TS_OLD; /* do date check later */
}
} else if (errno != ENOENT) {
- log_error(NO_EXIT|USE_ERRNO, "can't stat %s", timestampdir);
+ log_error(USE_ERRNO, "can't stat %s", timestampdir);
} else
status = TS_MISSING;
if (status == TS_MISSING && timestampfile && ISSET(flags, TS_MAKE_DIRS)) {
if (mkdir(timestampdir, S_IRWXU) == -1) {
status = TS_ERROR;
- log_error(NO_EXIT|USE_ERRNO, "can't mkdir %s", timestampdir);
+ log_error(USE_ERRNO, "can't mkdir %s", timestampdir);
}
}
if (lstat(timestampfile, &sb) == 0) {
if (!S_ISREG(sb.st_mode)) {
status = TS_ERROR;
- log_error(NO_EXIT, "%s exists but is not a regular file (0%o)",
+ log_error(0, "%s exists but is not a regular file (0%o)",
timestampfile, (unsigned int) sb.st_mode);
} else {
/* If bad uid or file mode, complain and kill the bogus file. */
if (sb.st_uid != timestamp_uid) {
- log_error(NO_EXIT,
+ log_error(0,
"%s owned by uid %u, should be uid %u",
timestampfile, (unsigned int) sb.st_uid,
(unsigned int) timestamp_uid);
(void) unlink(timestampfile);
} else if ((sb.st_mode & 0000022)) {
- log_error(NO_EXIT,
+ log_error(0,
"%s writable by non-owner (0%o), should be mode 0600",
timestampfile, (unsigned int) sb.st_mode);
(void) unlink(timestampfile);
}
}
} else if (errno != ENOENT) {
- log_error(NO_EXIT|USE_ERRNO, "can't stat %s", timestampfile);
+ log_error(USE_ERRNO, "can't stat %s", timestampfile);
status = TS_ERROR;
}
}
*/
if (mtime.tv_sec > now + 60 * def_timestamp_timeout * 2) {
time_t tv_sec = (time_t)mtime.tv_sec;
- log_error(NO_EXIT,
+ log_error(0,
"timestamp too far in the future: %20.20s",
4 + ctime(&tv_sec));
if (timestampfile)
else
status = rmdir(timestampdir);
if (status == -1 && errno != ENOENT) {
- log_error(NO_EXIT, "can't remove %s (%s), will reset to Epoch",
+ log_error(0, "can't remove %s (%s), will reset to Epoch",
path, strerror(errno));
remove = FALSE;
}
if (def_rootpw) {
if ((pw = sudo_getpwuid(0)) == NULL)
- log_error(0, "unknown uid: 0");
+ log_fatal(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);
+ log_fatal(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: %u",
+ log_fatal(NO_MAIL|MSG_ONLY, "unknown uid: %u",
(unsigned int) runas_pw->pw_uid);
pw_addref(runas_pw);
pw = runas_pw;
/*
* Validate the list of environment variables passed in on the command
* line against env_delete, env_check, and env_keep.
- * Calls log_error() if any specified variables are not allowed.
+ * Calls log_fatal() if any specified variables are not allowed.
*/
void
validate_env_vars(env_vars)
}
if (bad != NULL) {
bad[blen - 2] = '\0'; /* remove trailing ", " */
- log_error(NO_MAIL,
+ log_fatal(NO_MAIL,
"sorry, you are not allowed to set the following environment variables: %s", bad);
/* NOTREACHED */
efree(bad);
*/
if (stat(def_iolog_dir, &sb) != 0) {
if (mkdir(def_iolog_dir, S_IRWXU) != 0)
- log_error(USE_ERRNO, "Can't mkdir %s", def_iolog_dir);
+ log_fatal(USE_ERRNO, "Can't mkdir %s", def_iolog_dir);
} else if (!S_ISDIR(sb.st_mode)) {
- log_error(0, "%s exists but is not a directory (0%o)",
+ log_fatal(0, "%s exists but is not a directory (0%o)",
def_iolog_dir, (unsigned int) sb.st_mode);
}
len = snprintf(pathbuf, sizeof(pathbuf), "%s/seq", def_iolog_dir);
if (len <= 0 || len >= sizeof(pathbuf)) {
errno = ENAMETOOLONG;
- log_error(USE_ERRNO, "%s/seq", pathbuf);
+ log_fatal(USE_ERRNO, "%s/seq", pathbuf);
}
fd = open(pathbuf, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
if (fd == -1)
- log_error(USE_ERRNO, "cannot open %s", pathbuf);
+ log_fatal(USE_ERRNO, "cannot open %s", pathbuf);
lock_file(fd, SUDO_LOCK);
/* Read seq number (base 36). */
nread = read(fd, buf, sizeof(buf));
if (nread != 0) {
if (nread == -1)
- log_error(USE_ERRNO, "cannot read %s", pathbuf);
+ log_fatal(USE_ERRNO, "cannot read %s", pathbuf);
id = strtoul(buf, &ep, 36);
if (buf == ep || id >= SESSID_MAX)
- log_error(0, "invalid sequence number %s", pathbuf);
+ log_fatal(0, "invalid sequence number %s", pathbuf);
}
id++;
/* Rewind and overwrite old seq file. */
if (lseek(fd, 0, SEEK_SET) == (off_t)-1 || write(fd, buf, 7) != 7)
- log_error(USE_ERRNO, "Can't write to %s", pathbuf);
+ log_fatal(USE_ERRNO, "Can't write to %s", pathbuf);
close(fd);
}
int i, len;
if (sudo_user.sessid[0] == '\0')
- log_error(0, "tried to build a session id path without a session id");
+ log_fatal(0, "tried to build a session id path without a session id");
/*
* Path is of the form /var/log/sudo-io/00/00/01.
sudo_user.sessid[3], sudo_user.sessid[4], sudo_user.sessid[5]);
if (len <= 0 && len >= pathsize) {
errno = ENAMETOOLONG;
- log_error(USE_ERRNO, "%s/%s", def_iolog_dir, sudo_user.sessid);
+ log_fatal(USE_ERRNO, "%s/%s", def_iolog_dir, sudo_user.sessid);
}
/*
pathbuf[len - i] = '\0';
if (stat(pathbuf, &sb) != 0) {
if (mkdir(pathbuf, S_IRWXU) != 0)
- log_error(USE_ERRNO, "Can't mkdir %s", pathbuf);
+ log_fatal(USE_ERRNO, "Can't mkdir %s", pathbuf);
} else if (!S_ISDIR(sb.st_mode)) {
- log_error(0, "%s: %s", pathbuf, strerror(ENOTDIR));
+ log_fatal(0, "%s: %s", pathbuf, strerror(ENOTDIR));
}
pathbuf[len - i] = '/';
}
return -1;
if (mkdir(pathbuf, S_IRUSR|S_IWUSR|S_IXUSR) != 0)
- log_error(USE_ERRNO, "Can't mkdir %s", pathbuf);
+ log_fatal(USE_ERRNO, "Can't mkdir %s", pathbuf);
/*
* We create 7 files: a log file, a timing file and 5 for input/output.
*/
io_logfile = open_io_fd(pathbuf, len, "/log", FALSE);
if (io_logfile == NULL)
- log_error(USE_ERRNO, "Can't create %s", pathbuf);
+ log_fatal(USE_ERRNO, "Can't create %s", pathbuf);
io_fds[IOFD_TIMING].v = open_io_fd(pathbuf, len, "/timing", def_compress_io);
if (io_fds[IOFD_TIMING].v == NULL)
- log_error(USE_ERRNO, "Can't create %s", pathbuf);
+ log_fatal(USE_ERRNO, "Can't create %s", pathbuf);
if (def_log_input) {
io_fds[IOFD_TTYIN].v = open_io_fd(pathbuf, len, "/ttyin", def_compress_io);
if (io_fds[IOFD_TTYIN].v == NULL)
- log_error(USE_ERRNO, "Can't create %s", pathbuf);
+ log_fatal(USE_ERRNO, "Can't create %s", pathbuf);
}
if (def_log_output) {
io_fds[IOFD_TTYOUT].v = open_io_fd(pathbuf, len, "/ttyout", def_compress_io);
if (io_fds[IOFD_TTYOUT].v == NULL)
- log_error(USE_ERRNO, "Can't create %s", pathbuf);
+ log_fatal(USE_ERRNO, "Can't create %s", pathbuf);
}
if (def_log_input) {
io_fds[IOFD_STDIN].v = open_io_fd(pathbuf, len, "/stdin", def_compress_io);
if (io_fds[IOFD_STDIN].v == NULL)
- log_error(USE_ERRNO, "Can't create %s", pathbuf);
+ log_fatal(USE_ERRNO, "Can't create %s", pathbuf);
}
if (def_log_output) {
io_fds[IOFD_STDOUT].v = open_io_fd(pathbuf, len, "/stdout", def_compress_io);
if (io_fds[IOFD_STDOUT].v == NULL)
- log_error(USE_ERRNO, "Can't create %s", pathbuf);
+ log_fatal(USE_ERRNO, "Can't create %s", pathbuf);
}
if (def_log_output) {
io_fds[IOFD_STDERR].v = open_io_fd(pathbuf, len, "/stderr", def_compress_io);
if (io_fds[IOFD_STDERR].v == NULL)
- log_error(USE_ERRNO, "Can't create %s", pathbuf);
+ log_fatal(USE_ERRNO, "Can't create %s", pathbuf);
}
/* So we can block tty-generated signals */
efree(logline);
}
-void
-#ifdef __STDC__
-log_error(int flags, const char *fmt, ...)
-#else
-log_error(flags, fmt, va_alist)
+/*
+ * Perform logging for log_error()/log_fatal()
+ */
+static void
+vlog_error(flags, fmt, ap)
int flags;
const char *fmt;
- va_dcl
-#endif
+ va_list ap;
{
int serrno = errno;
char *message;
char *logline;
- va_list ap;
-#ifdef __STDC__
- va_start(ap, fmt);
-#else
- va_start(ap);
-#endif
/* Become root if we are not already to avoid user interference */
set_perms(PERM_ROOT|PERM_NOEXIT);
/* Expand printf-style format + args. */
evasprintf(&message, fmt, ap);
- va_end(ap);
if (ISSET(flags, MSG_ONLY))
logline = message;
do_logfile(logline);
efree(logline);
+}
- if (!ISSET(flags, NO_EXIT)) {
- cleanup(0);
- exit(1);
- }
+void
+#ifdef __STDC__
+log_error(int flags, const char *fmt, ...)
+#else
+log_error(flags, fmt, va_alist)
+ int flags;
+ const char *fmt;
+ va_dcl
+#endif
+{
+ va_list ap;
+
+ /* Log the error. */
+#ifdef __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ vlog_error(flags, fmt, ap);
+ va_end(ap);
+}
+
+void
+#ifdef __STDC__
+log_fatal(int flags, const char *fmt, ...)
+#else
+log_fatal(flags, fmt, va_alist)
+ int flags;
+ const char *fmt;
+ va_dcl
+#endif
+{
+ va_list ap;
+
+ /* Log the error. */
+#ifdef __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ vlog_error(flags, fmt, ap);
+ va_end(ap);
+
+ /* Clean up and exit. */
+ cleanup(0);
+ exit(1);
}
#define MAX_MAILFLAGS 63
#define SLOG_FILE 0x02
#define SLOG_BOTH 0x03
-/* Flags for log_error() */
+/* Flags for log_error()/log_fatal() */
#define MSG_ONLY 0x01
#define USE_ERRNO 0x02
#define NO_MAIL 0x04
-#define NO_EXIT 0x08
-#define NO_STDERR 0x10
+#define NO_STDERR 0x08
/*
* Maximum number of characters to log per entry. The syslogger
void log_denial __P((int, int));
void log_error __P((int flags, const char *fmt, ...))
__printflike(2, 3);
+void log_fatal __P((int flags, const char *fmt, ...))
+ __printflike(2, 3)
+ __attribute__((__noreturn__));
RETSIGTYPE reapchild __P((int));
void writeln_wrap __P((FILE *, char *, size_t, size_t));
yyin = nss->handle;
if (yyparse() != 0 || parse_error) {
if (errorlineno != -1) {
- log_error(NO_EXIT, "parse error in %s near line %d",
+ log_error(0, "parse error in %s near line %d",
errorfile, errorlineno);
} else {
- log_error(NO_EXIT, "parse error in %s", errorfile);
+ log_error(0, "parse error in %s", errorfile);
}
return -1;
}
aix_setauthdb(pw->pw_name);
# endif
if (initgroups(pw->pw_name, pw->pw_gid) < 0)
- log_error(USE_ERRNO|MSG_ONLY, "can't set runas group vector");
+ log_fatal(USE_ERRNO|MSG_ONLY, "can't set runas group vector");
# ifdef HAVE_GETGROUPS
if (groups) {
efree(groups);
if ((ngroups = getgroups(0, NULL)) > 0) {
groups = emalloc2(ngroups, sizeof(GETGROUPS_T));
if (getgroups(ngroups, groups) < 0)
- log_error(USE_ERRNO|MSG_ONLY, "can't get runas group vector");
+ log_fatal(USE_ERRNO|MSG_ONLY, "can't get runas group vector");
}
# ifdef HAVE_SETAUTHDB
aix_restoreauthdb();
# endif
} else {
if (setgroups(ngroups, groups) < 0)
- log_error(USE_ERRNO|MSG_ONLY, "can't set runas group vector");
+ log_fatal(USE_ERRNO|MSG_ONLY, "can't set runas group vector");
# endif /* HAVE_GETGROUPS */
}
}
restore_groups()
{
if (user_ngroups >= 0 && setgroups(user_ngroups, user_groups) < 0)
- log_error(USE_ERRNO|MSG_ONLY, "can't reset user group vector");
+ log_fatal(USE_ERRNO|MSG_ONLY, "can't reset user group vector");
}
#else
if (nss->open(nss) == 0 && nss->parse(nss) == 0) {
sources++;
if (nss->setdefs(nss) != 0)
- log_error(NO_STDERR|NO_EXIT, "problem with defaults entries");
+ log_error(NO_STDERR, "problem with defaults entries");
}
}
if (sources == 0)
- log_error(0, "no valid sudoers sources found, quitting");
+ log_fatal(0, "no valid sudoers sources found, quitting");
/* XXX - collect post-sudoers parse settings into a function */
set_runaspw(runas_user ? runas_user : def_runas_default);
if (!update_defaults(SETDEF_RUNAS))
- log_error(NO_STDERR|NO_EXIT, "problem with defaults entries");
+ log_error(NO_STDERR, "problem with defaults entries");
if (def_fqdn)
set_fqdn(); /* deferred until after sudoers is parsed */
timestamp_uid = pw->pw_uid;
pw_delref(pw);
} else {
- log_error(NO_EXIT, "timestamp owner (%s): No such user",
+ log_error(0, "timestamp owner (%s): No such user",
def_timestampowner);
timestamp_uid = ROOT_UID;
}
if (def_requiretty) {
if ((fd = open(_PATH_TTY, O_RDWR|O_NOCTTY)) == -1) {
audit_failure(NewArgv, "no tty");
- log_error(NO_MAIL, "sorry, you must have a tty to run sudo");
+ log_fatal(NO_MAIL, "sorry, you must have a tty to run sudo");
} else
(void) close(fd);
}
/* If user specified env vars make sure sudoers allows it. */
if (ISSET(sudo_mode, MODE_RUN) && !def_setenv) {
if (ISSET(sudo_mode, MODE_PRESERVE_ENV))
- log_error(NO_MAIL,
+ log_fatal(NO_MAIL,
"sorry, you are not allowed to preserve the environment");
else
validate_env_vars(sudo_user.env_vars);
if (sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE)
errorx(1, "unknown uid: %u", (unsigned int) uid);
- /* Need to make a fake struct passwd for the call to log_error(). */
+ /* Need to make a fake struct passwd for the call to log_fatal(). */
sudo_user.pw = sudo_fakepwuid(uid, gid);
- log_error(0, "unknown uid: %u", (unsigned int) uid);
+ log_fatal(0, "unknown uid: %u", (unsigned int) uid);
}
#ifdef HAVE_MBR_CHECK_MEMBERSHIP
mbr_uid_to_uuid(user_uid, user_uuid);
if (user_shell == NULL || *user_shell == '\0')
user_shell = estrdup(sudo_user.pw->pw_shell);
- /* It is now safe to use log_error() and set_perms() */
+ /* It is now safe to use log_fatal() and set_perms() */
#ifdef HAVE_GETGROUPS
if ((user_ngroups = getgroups(0, NULL)) > 0) {
user_groups = emalloc2(user_ngroups, sizeof(GETGROUPS_T));
if (getgroups(user_ngroups, user_groups) < 0)
- log_error(USE_ERRNO|MSG_ONLY, "can't get group vector");
+ log_fatal(USE_ERRNO|MSG_ONLY, "can't get group vector");
}
#endif
if (nohostname)
- log_error(USE_ERRNO|MSG_ONLY, "can't get hostname");
+ log_fatal(USE_ERRNO|MSG_ONLY, "can't get hostname");
/*
* Get current working directory. Try as user, fall back to root.
user_base = user_cmnd;
if (!update_defaults(SETDEF_CMND))
- log_error(NO_STDERR|NO_EXIT, "problem with defaults entries");
+ log_error(NO_STDERR, "problem with defaults entries");
return rval;
}
set_perms(PERM_SUDOERS);
if (rootstat != 0 && stat_sudoers(sudoers, &statbuf) != 0)
- log_error(USE_ERRNO|NO_EXIT, "can't stat %s", sudoers);
+ log_error(USE_ERRNO, "can't stat %s", sudoers);
else if (!S_ISREG(statbuf.st_mode))
- log_error(NO_EXIT, "%s is not a regular file", sudoers);
+ log_error(0, "%s is not a regular file", sudoers);
else if ((statbuf.st_mode & 07577) != (SUDOERS_MODE & 07577))
- log_error(NO_EXIT, "%s is mode 0%o, should be 0%o", sudoers,
+ log_error(0, "%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 %u, should be %u", sudoers,
+ log_error(0, "%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 && ISSET(statbuf.st_mode, S_IRGRP|S_IWGRP))
- log_error(NO_EXIT, "%s is owned by gid %u, should be %u", sudoers,
+ log_error(0, "%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);
+ log_error(USE_ERRNO, "can't open %s", sudoers);
else {
/*
* Make sure we can actually read sudoers so we can present the
* user with a reasonable error message (unlike the lexer).
*/
if (statbuf.st_size != 0 && fgetc(fp) == EOF) {
- log_error(USE_ERRNO|NO_EXIT, "can't read %s", sudoers);
+ log_error(USE_ERRNO, "can't read %s", sudoers);
fclose(fp);
fp = NULL;
}
set_loginclass(pw)
struct passwd *pw;
{
- int errflags;
+ const int errflags = NO_MAIL|MSG_ONLY;
if (!def_use_loginclass)
return;
- /*
- * Don't make it a fatal error if the user didn't specify the login
- * class themselves. We do this because if login.conf gets
- * corrupted we want the admin to be able to use sudo to fix it.
- */
- if (login_class)
- errflags = NO_MAIL|MSG_ONLY;
- else
- errflags = NO_MAIL|MSG_ONLY|NO_EXIT;
-
if (login_class && strcmp(login_class, "-") != 0) {
if (user_uid != 0 &&
strcmp(runas_user ? runas_user : def_runas_default, "root") != 0)
/* Make sure specified login class is valid. */
lc = login_getclass(login_class);
if (!lc || !lc->lc_class || strcmp(lc->lc_class, login_class) != 0) {
- log_error(errflags, "unknown login class: %s", login_class);
+ /*
+ * Don't make it a fatal error if the user didn't specify the login
+ * class themselves. We do this because if login.conf gets
+ * corrupted we want the admin to be able to use sudo to fix it.
+ */
+ if (login_class)
+ log_fatal(errflags, "unknown login class: %s", login_class);
+ else
+ log_error(errflags, "unknown login class: %s", login_class);
def_use_loginclass = FALSE;
}
}
#else
if (!(hp = gethostbyname(user_host))) {
#endif
- log_error(MSG_ONLY|NO_EXIT,
- "unable to resolve host %s", user_host);
+ log_error(MSG_ONLY, "unable to resolve host %s", user_host);
} else {
if (user_shost != user_host)
efree(user_shost);
} else {
if ((runas_pw = sudo_getpwnam(user)) == NULL) {
audit_failure(NewArgv, "unknown user: %s", user);
- log_error(NO_MAIL|MSG_ONLY, "unknown user: %s", user);
+ log_fatal(NO_MAIL|MSG_ONLY, "unknown user: %s", user);
}
}
}
runas_gr = sudo_fakegrnam(group);
} else {
if ((runas_gr = sudo_getgrnam(group)) == NULL)
- log_error(NO_MAIL|MSG_ONLY, "unknown group: %s", group);
+ log_fatal(NO_MAIL|MSG_ONLY, "unknown group: %s", group);
}
}
aix_setauthdb(pw->pw_name);
# endif
if (initgroups(pw->pw_name, pw->pw_gid) == -1)
- log_error(USE_ERRNO|MSG_ONLY, "can't reset group vector");
+ log_fatal(USE_ERRNO|MSG_ONLY, "can't reset group vector");
efree(user_groups);
user_groups = NULL;
if ((user_ngroups = getgroups(0, NULL)) > 0) {
user_groups = emalloc2(user_ngroups, sizeof(GETGROUPS_T));
if (getgroups(user_ngroups, user_groups) < 0)
- log_error(USE_ERRNO|MSG_ONLY, "can't get group vector");
+ log_fatal(USE_ERRNO|MSG_ONLY, "can't get group vector");
}
# ifdef HAVE_SETAUTHDB
aix_restoreauthdb();