From: Todd C. Miller Date: Fri, 30 Mar 2012 17:53:19 +0000 (-0400) Subject: Remove the NO_EXIT flag to log_error() and add a log_fatal() function X-Git-Tag: SUDO_1_7_9p1~16 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6ffa802069d9770a5431a8139ce2e435f0e871a8;p=sudo Remove the NO_EXIT flag to log_error() and add a log_fatal() function that exits and is marked no_return. Fixes false positives from static analyzers and is easier for humans to read too. --HG-- branch : 1.7 --- diff --git a/auth/bsdauth.c b/auth/bsdauth.c index e255afa08..18c78f773 100644 --- a/auth/bsdauth.c +++ b/auth/bsdauth.c @@ -75,13 +75,13 @@ bsdauth_init(pw, auth) 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; @@ -90,7 +90,7 @@ bsdauth_init(pw, auth) /* 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; @@ -99,7 +99,7 @@ bsdauth_init(pw, auth) 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; @@ -173,7 +173,7 @@ bsdauth_verify(pw, prompt, auth) 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; } diff --git a/auth/kerb5.c b/auth/kerb5.c index 9582c6f5c..d07e90af6 100644 --- a/auth/kerb5.c +++ b/auth/kerb5.c @@ -111,7 +111,7 @@ kerb5_setup(pw, promptp, auth) * 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; @@ -152,7 +152,7 @@ kerb5_init(pw, auth) 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; @@ -163,7 +163,7 @@ kerb5_init(pw, auth) (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; @@ -213,7 +213,7 @@ kerb5_verify(pw, pass, auth) /* 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; @@ -229,7 +229,7 @@ kerb5_verify(pw, pass, auth) 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; @@ -242,11 +242,11 @@ kerb5_verify(pw, pass, auth) /* 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)); } @@ -314,7 +314,7 @@ verify_krb_v5_tgt(sudo_context, cred, auth_name) */ 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; @@ -329,7 +329,7 @@ verify_krb_v5_tgt(sudo_context, cred, auth_name) 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; diff --git a/auth/pam.c b/auth/pam.c index 89e9fa99e..f55a83263 100644 --- a/auth/pam.c +++ b/auth/pam.c @@ -100,7 +100,7 @@ pam_init(pw, auth) 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; } @@ -146,11 +146,11 @@ pam_verify(pw, prompt, auth) 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, @@ -158,14 +158,14 @@ pam_verify(pw, prompt, auth) 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; @@ -181,7 +181,7 @@ pam_verify(pw, prompt, auth) 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; } } diff --git a/auth/sia.c b/auth/sia.c index 6c972c635..1e1c91f2d 100644 --- a/auth/sia.c +++ b/auth/sia.c @@ -99,7 +99,7 @@ sia_setup(pw, promptp, auth) 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; } diff --git a/auth/sudo_auth.c b/auth/sudo_auth.c index 6885f0fa0..5fb0843d1 100644 --- a/auth/sudo_auth.c +++ b/auth/sudo_auth.c @@ -172,7 +172,7 @@ verify_user(pw, prompt) #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."); @@ -249,7 +249,7 @@ done: #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"); } diff --git a/bsm_audit.c b/bsm_audit.c index 94ed4a8bf..24a3f64b7 100644 --- a/bsm_audit.c +++ b/bsm_audit.c @@ -42,7 +42,7 @@ # 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) @@ -55,10 +55,10 @@ 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; @@ -84,7 +84,7 @@ bsm_audit_success(char **exec_args) 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; @@ -95,9 +95,9 @@ bsm_audit_success(char **exec_args) 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); @@ -106,24 +106,24 @@ bsm_audit_success(char **exec_args) * 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 @@ -145,42 +145,42 @@ bsm_audit_failure(char **exec_args, char const *const fmt, va_list ap) 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"); } diff --git a/check.c b/check.c index 466e7fe31..2b3ee053c 100644 --- a/check.c +++ b/check.c @@ -151,7 +151,7 @@ check_user(validated, mode) /* 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. */ @@ -159,7 +159,7 @@ check_user(validated, mode) 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"); } } @@ -236,17 +236,17 @@ update_timestamp(timestampdir, timestampfile) */ 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) @@ -408,7 +408,7 @@ build_timestamp(timestampdir, timestampfile) 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 @@ -427,12 +427,12 @@ build_timestamp(timestampdir, timestampfile) 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; } @@ -465,14 +465,14 @@ timestamp_status(timestampdir, timestampfile, user, flags) */ 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 { @@ -481,12 +481,12 @@ timestamp_status(timestampdir, timestampfile, user, flags) 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; @@ -512,14 +512,14 @@ timestamp_status(timestampdir, timestampfile, user, flags) 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 { @@ -528,7 +528,7 @@ timestamp_status(timestampdir, timestampfile, user, flags) 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; @@ -539,7 +539,7 @@ timestamp_status(timestampdir, timestampfile, user, flags) 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); } } @@ -554,18 +554,18 @@ timestamp_status(timestampdir, timestampfile, user, flags) 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); @@ -596,7 +596,7 @@ timestamp_status(timestampdir, timestampfile, user, flags) } } } 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; } } @@ -619,7 +619,7 @@ timestamp_status(timestampdir, timestampfile, user, flags) */ 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) @@ -664,7 +664,7 @@ remove_timestamp(remove) 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; } @@ -727,13 +727,13 @@ get_authpw() 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; diff --git a/env.c b/env.c index 9e5a9fd89..8a7ba5315 100644 --- a/env.c +++ b/env.c @@ -901,7 +901,7 @@ insert_env_vars(env_vars) /* * 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) @@ -947,7 +947,7 @@ 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); diff --git a/iolog.c b/iolog.c index 131770ec3..e6fb5997d 100644 --- a/iolog.c +++ b/iolog.c @@ -101,9 +101,9 @@ io_nextid() */ 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); } @@ -113,21 +113,21 @@ io_nextid() 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++; @@ -147,7 +147,7 @@ io_nextid() /* 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); } @@ -160,7 +160,7 @@ build_idpath(pathbuf, pathsize) 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. @@ -170,7 +170,7 @@ build_idpath(pathbuf, pathsize) 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); } /* @@ -180,9 +180,9 @@ build_idpath(pathbuf, pathsize) 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] = '/'; } @@ -234,47 +234,47 @@ io_log_open() 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 */ diff --git a/logging.c b/logging.c index 5d349f7a7..dba5fe1e5 100644 --- a/logging.c +++ b/logging.c @@ -324,32 +324,24 @@ log_allowed(status) 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; @@ -383,11 +375,54 @@ log_error(flags, fmt, va_alist) 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 diff --git a/logging.h b/logging.h index 619773445..fc40b3470 100644 --- a/logging.h +++ b/logging.h @@ -30,12 +30,11 @@ #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 @@ -58,6 +57,9 @@ void log_allowed __P((int)); 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)); diff --git a/parse.c b/parse.c index bfd6a6cf5..96b02ab7b 100644 --- a/parse.c +++ b/parse.c @@ -116,10 +116,10 @@ sudo_file_parse(nss) 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; } diff --git a/set_perms.c b/set_perms.c index 719b7b81d..23736d241 100644 --- a/set_perms.c +++ b/set_perms.c @@ -513,7 +513,7 @@ runas_setgroups() 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); @@ -522,14 +522,14 @@ runas_setgroups() 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 */ } } @@ -538,7 +538,7 @@ static void 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 diff --git a/sudo.c b/sudo.c index 3cdc3b708..4aa774266 100644 --- a/sudo.c +++ b/sudo.c @@ -300,11 +300,11 @@ main(argc, argv, envp) 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 */ @@ -321,7 +321,7 @@ main(argc, argv, envp) 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 */ @@ -410,7 +410,7 @@ main(argc, argv, envp) 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; } @@ -424,7 +424,7 @@ main(argc, argv, envp) 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); } @@ -480,7 +480,7 @@ main(argc, argv, envp) /* 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); @@ -700,9 +700,9 @@ init_vars(envp) 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); @@ -710,18 +710,18 @@ init_vars(envp) 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. @@ -862,7 +862,7 @@ set_cmnd(sudo_mode) 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; } @@ -1056,28 +1056,28 @@ open_sudoers(sudoers, doedit, keepopen) 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; } @@ -1182,21 +1182,11 @@ static void 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) @@ -1211,7 +1201,15 @@ set_loginclass(pw) /* 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; } } @@ -1244,8 +1242,7 @@ set_fqdn() #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); @@ -1282,7 +1279,7 @@ set_runaspw(user) } 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); } } } @@ -1302,7 +1299,7 @@ set_runasgr(group) 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); } } diff --git a/sudo_nss.c b/sudo_nss.c index f9dc1128d..9ee73b079 100644 --- a/sudo_nss.c +++ b/sudo_nss.c @@ -215,13 +215,13 @@ reset_groups(pw) 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();