From 44ce5720def9fb6104ac5b942c19c902581a336e Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Mon, 26 Mar 2012 10:59:14 -0400 Subject: [PATCH] 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. --- plugins/sudoers/auth/bsdauth.c | 10 ++--- plugins/sudoers/auth/kerb5.c | 18 ++++----- plugins/sudoers/auth/pam.c | 14 +++---- plugins/sudoers/auth/sia.c | 2 +- plugins/sudoers/auth/sudo_auth.c | 6 +-- plugins/sudoers/bsm_audit.c | 44 ++++++++++----------- plugins/sudoers/check.c | 46 +++++++++++----------- plugins/sudoers/env.c | 4 +- plugins/sudoers/iolog.c | 46 +++++++++++----------- plugins/sudoers/logging.c | 47 +++++++++++++++++----- plugins/sudoers/logging.h | 6 +-- plugins/sudoers/parse.c | 4 +- plugins/sudoers/set_perms.c | 2 +- plugins/sudoers/sudoers.c | 67 +++++++++++++++----------------- 14 files changed, 170 insertions(+), 146 deletions(-) diff --git a/plugins/sudoers/auth/bsdauth.c b/plugins/sudoers/auth/bsdauth.c index 5e90898aa..3597e56ee 100644 --- a/plugins/sudoers/auth/bsdauth.c +++ b/plugins/sudoers/auth/bsdauth.c @@ -74,13 +74,13 @@ bsdauth_init(struct passwd *pw, sudo_auth *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); debug_return_int(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); debug_return_int(AUTH_FATAL); @@ -89,7 +89,7 @@ bsdauth_init(struct passwd *pw, sudo_auth *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); debug_return_int(AUTH_FATAL); @@ -98,7 +98,7 @@ bsdauth_init(struct passwd *pw, sudo_auth *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); debug_return_int(AUTH_FATAL); @@ -170,7 +170,7 @@ bsdauth_verify(struct passwd *pw, char *prompt, sudo_auth *auth) debug_return_int(AUTH_INTR); if ((s = auth_getvalue(as, "errormsg")) != NULL) - log_error(NO_EXIT|NO_MAIL, "%s", s); + log_error(NO_MAIL, "%s", s); debug_return_int(AUTH_FAILURE); } diff --git a/plugins/sudoers/auth/kerb5.c b/plugins/sudoers/auth/kerb5.c index 3ba7b8c5b..ab47c190c 100644 --- a/plugins/sudoers/auth/kerb5.c +++ b/plugins/sudoers/auth/kerb5.c @@ -113,7 +113,7 @@ sudo_krb5_setup(struct passwd *pw, char **promptp, sudo_auth *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)); debug_return_int(AUTH_FAILURE); @@ -156,7 +156,7 @@ sudo_krb5_init(struct passwd *pw, sudo_auth *auth) error = krb5_parse_name(sudo_context, pname, &(sudo_krb5_data.princ)); if (error) { - log_error(NO_EXIT|NO_MAIL, + log_error(NO_MAIL, _("%s: unable to parse '%s': %s"), auth->name, pname, error_message(error)); goto done; @@ -166,7 +166,7 @@ sudo_krb5_init(struct passwd *pw, sudo_auth *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)); goto done; @@ -214,7 +214,7 @@ sudo_krb5_verify(struct passwd *pw, char *pass, sudo_auth *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; @@ -230,7 +230,7 @@ sudo_krb5_verify(struct passwd *pw, char *pass, sudo_auth *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; @@ -243,11 +243,11 @@ sudo_krb5_verify(struct passwd *pw, char *pass, sudo_auth *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)); } @@ -312,7 +312,7 @@ verify_krb_v5_tgt(krb5_context sudo_context, krb5_creds *cred, char *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)); debug_return_int(-1); @@ -327,7 +327,7 @@ verify_krb_v5_tgt(krb5_context sudo_context, krb5_creds *cred, char *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)); debug_return_int(error); diff --git a/plugins/sudoers/auth/pam.c b/plugins/sudoers/auth/pam.c index 5006e4bad..64ac30a80 100644 --- a/plugins/sudoers/auth/pam.c +++ b/plugins/sudoers/auth/pam.c @@ -97,7 +97,7 @@ sudo_pam_init(struct passwd *pw, sudo_auth *auth) #endif 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")); debug_return_int(AUTH_FATAL); } @@ -141,25 +141,25 @@ sudo_pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth) case PAM_SUCCESS: debug_return_int(AUTH_SUCCESS); case PAM_AUTH_ERR: - log_error(NO_EXIT|NO_MAIL, _("account validation failure, " + log_error(NO_MAIL, _("account validation failure, " "is your account locked?")); debug_return_int(AUTH_FATAL); case PAM_NEW_AUTHTOK_REQD: - log_error(NO_EXIT|NO_MAIL, _("Account or password is " + log_error(NO_MAIL, _("Account or password is " "expired, reset your password and try again")); *pam_status = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK); if (*pam_status == PAM_SUCCESS) debug_return_int(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); debug_return_int(AUTH_FAILURE); case PAM_AUTHTOK_EXPIRED: - log_error(NO_EXIT|NO_MAIL, + log_error(NO_MAIL, _("Password expired, contact your system administrator")); debug_return_int(AUTH_FATAL); case PAM_ACCT_EXPIRED: - log_error(NO_EXIT|NO_MAIL, + log_error(NO_MAIL, _("Account expired or PAM config lacks an \"account\" " "section for sudo, contact your system administrator")); debug_return_int(AUTH_FATAL); @@ -175,7 +175,7 @@ sudo_pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth) debug_return_int(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); debug_return_int(AUTH_FATAL); } } diff --git a/plugins/sudoers/auth/sia.c b/plugins/sudoers/auth/sia.c index c5b93926f..d9f685e17 100644 --- a/plugins/sudoers/auth/sia.c +++ b/plugins/sudoers/auth/sia.c @@ -105,7 +105,7 @@ sudo_sia_setup(struct passwd *pw, char **promptp, sudo_auth *auth) if (sia_ses_init(&siah, sudo_argc, sudo_argv, NULL, pw->pw_name, user_ttypath, 1, NULL) != SIASUCCESS) { - log_error(USE_ERRNO|NO_EXIT|NO_MAIL, + log_error(USE_ERRNO|NO_MAIL, _("unable to initialize SIA session")); debug_return_int(AUTH_FATAL); } diff --git a/plugins/sudoers/auth/sudo_auth.c b/plugins/sudoers/auth/sudo_auth.c index b914f3973..3216582d4 100644 --- a/plugins/sudoers/auth/sudo_auth.c +++ b/plugins/sudoers/auth/sudo_auth.c @@ -114,7 +114,7 @@ sudo_auth_init(struct passwd *pw) standalone = IS_STANDALONE(&auth_switch[0]); if (standalone && auth_switch[1].name != NULL) { audit_failure(NewArgv, "invalid authentication methods"); - log_error(0, _("Invalid authentication methods compiled into sudo! " + log_fatal(0, _("Invalid authentication methods compiled into sudo! " "You may mix standalone and non-standalone authentication.")); debug_return_int(-1); } @@ -195,7 +195,7 @@ verify_user(struct passwd *pw, char *prompt) /* XXX - check FLAG_DISABLED too */ if (auth_switch[0].name == NULL) { audit_failure(NewArgv, "no authentication methods"); - log_error(0, + log_fatal(0, _("There are no authentication methods compiled into sudo! " "If you want to turn off authentication, use the " "--disable-authentication configure option.")); @@ -268,7 +268,7 @@ done: flags = 0; else flags = NO_MAIL; - log_error(flags, ngettext("%d incorrect password attempt", + log_fatal(flags, ngettext("%d incorrect password attempt", "%d incorrect password attempts", def_passwd_tries - counter), def_passwd_tries - counter); } diff --git a/plugins/sudoers/bsm_audit.c b/plugins/sudoers/bsm_audit.c index 0ce6caf71..f30eab433 100644 --- a/plugins/sudoers/bsm_audit.c +++ b/plugins/sudoers/bsm_audit.c @@ -44,7 +44,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) @@ -58,10 +58,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; @@ -88,7 +88,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) debug_return; @@ -99,9 +99,9 @@ bsm_audit_success(char **exec_args) if (!audit_sudo_selected(0)) debug_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); @@ -110,24 +110,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")); debug_return; } @@ -151,43 +151,43 @@ 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) debug_return; - log_error(0, _("Could not determine audit condition")); + log_fatal(0, _("Could not determine audit condition")); } if (au_cond == AUC_NOAUDIT) debug_return; if (!audit_sudo_selected(1)) debug_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")); debug_return; } diff --git a/plugins/sudoers/check.c b/plugins/sudoers/check.c index 2850fe83a..ddb61d9d7 100644 --- a/plugins/sudoers/check.c +++ b/plugins/sudoers/check.c @@ -246,11 +246,11 @@ update_timestamp(char *timestampdir, char *timestampfile) */ int fd = open(timestampfile, O_WRONLY|O_CREAT, 0600); if (fd == -1) - log_error(NO_EXIT|USE_ERRNO, _("unable to open %s"), timestampfile); + log_error(USE_ERRNO, _("unable to 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, _("unable to write to %s"), + log_error(USE_ERRNO, _("unable to write to %s"), timestampfile); } close(fd); @@ -258,7 +258,7 @@ update_timestamp(char *timestampdir, char *timestampfile) } else { if (touch(-1, timestampdir, NULL) == -1) { if (mkdir(timestampdir, 0700) == -1) { - log_error(NO_EXIT|USE_ERRNO, _("unable to mkdir %s"), + log_error(USE_ERRNO, _("unable to mkdir %s"), timestampdir); } } @@ -453,7 +453,7 @@ build_timestamp(char **timestampdir, char **timestampfile) debug_return_int(len); bad: - log_error(0, _("timestamp path too long: %s"), *timestampfile); + log_fatal(0, _("timestamp path too long: %s"), *timestampfile); debug_return_int(-1); } @@ -482,14 +482,14 @@ timestamp_status(char *timestampdir, char *timestampfile, char *user, int 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 { @@ -498,12 +498,12 @@ timestamp_status(char *timestampdir, char *timestampfile, char *user, int flags) status = TS_MISSING; } } else if (errno != ENOENT) { - log_error(NO_EXIT|USE_ERRNO, _("unable to stat %s"), dirparent); + log_error(USE_ERRNO, _("unable to 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, _("unable to mkdir %s"), + log_error(USE_ERRNO, _("unable to mkdir %s"), dirparent); else status = TS_MISSING; @@ -526,14 +526,14 @@ timestamp_status(char *timestampdir, char *timestampfile, char *user, int 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 { @@ -542,7 +542,7 @@ timestamp_status(char *timestampdir, char *timestampfile, char *user, int flags) status = TS_OLD; /* do date check later */ } } else if (errno != ENOENT) { - log_error(NO_EXIT|USE_ERRNO, _("unable to stat %s"), timestampdir); + log_error(USE_ERRNO, _("unable to stat %s"), timestampdir); } else status = TS_MISSING; @@ -553,7 +553,7 @@ timestamp_status(char *timestampdir, char *timestampfile, char *user, int 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, _("unable to mkdir %s"), timestampdir); + log_error(USE_ERRNO, _("unable to mkdir %s"), timestampdir); } } @@ -568,18 +568,18 @@ timestamp_status(char *timestampdir, char *timestampfile, char *user, int 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); @@ -610,7 +610,7 @@ timestamp_status(char *timestampdir, char *timestampfile, char *user, int flags) } } } else if (errno != ENOENT) { - log_error(NO_EXIT|USE_ERRNO, _("unable to stat %s"), timestampfile); + log_error(USE_ERRNO, _("unable to stat %s"), timestampfile); status = TS_ERROR; } } @@ -633,7 +633,7 @@ timestamp_status(char *timestampdir, char *timestampfile, char *user, int 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) @@ -680,7 +680,7 @@ remove_timestamp(bool remove) else status = rmdir(timestampdir); if (status == -1 && errno != ENOENT) { - log_error(NO_EXIT, + log_error(0, _("unable to remove %s (%s), will reset to the epoch"), path, strerror(errno)); remove = false; @@ -749,13 +749,13 @@ get_authpw(void) if (def_rootpw) { if ((pw = sudo_getpwuid(ROOT_UID)) == NULL) - log_error(0, _("unknown uid: %u"), ROOT_UID); + log_fatal(0, _("unknown uid: %u"), ROOT_UID); } 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/plugins/sudoers/env.c b/plugins/sudoers/env.c index de3fcba0d..32d06049d 100644 --- a/plugins/sudoers/env.c +++ b/plugins/sudoers/env.c @@ -870,7 +870,7 @@ insert_env_vars(char * const envp[]) /* * 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(char * const env_vars[]) @@ -914,7 +914,7 @@ validate_env_vars(char * const 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/plugins/sudoers/iolog.c b/plugins/sudoers/iolog.c index 1f591e924..f265920e1 100644 --- a/plugins/sudoers/iolog.c +++ b/plugins/sudoers/iolog.c @@ -120,9 +120,9 @@ mkdir_parents(char *path) *slash = '\0'; if (stat(path, &sb) != 0) { if (mkdir(path, S_IRWXU) != 0) - log_error(USE_ERRNO, _("unable to mkdir %s"), path); + log_fatal(USE_ERRNO, _("unable to mkdir %s"), path); } else if (!S_ISDIR(sb.st_mode)) { - log_error(0, _("%s: %s"), path, strerror(ENOTDIR)); + log_fatal(0, _("%s: %s"), path, strerror(ENOTDIR)); } *slash = '/'; } @@ -153,9 +153,9 @@ io_nextid(char *iolog_dir, char sessid[7]) mkdir_parents(iolog_dir); if (stat(iolog_dir, &sb) != 0) { if (mkdir(iolog_dir, S_IRWXU) != 0) - log_error(USE_ERRNO, _("unable to mkdir %s"), iolog_dir); + log_fatal(USE_ERRNO, _("unable to mkdir %s"), 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)"), iolog_dir, (unsigned int) sb.st_mode); } @@ -165,21 +165,21 @@ io_nextid(char *iolog_dir, char sessid[7]) len = snprintf(pathbuf, sizeof(pathbuf), "%s/seq", 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, _("unable to open %s"), pathbuf); + log_fatal(USE_ERRNO, _("unable to 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, _("unable to read %s"), pathbuf); + log_fatal(USE_ERRNO, _("unable to 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++; @@ -199,7 +199,7 @@ io_nextid(char *iolog_dir, char sessid[7]) /* Rewind and overwrite old seq file. */ if (lseek(fd, 0, SEEK_SET) == (off_t)-1 || write(fd, buf, 7) != 7) - log_error(USE_ERRNO, _("unable to write to %s"), pathbuf); + log_fatal(USE_ERRNO, _("unable to write to %s"), pathbuf); close(fd); debug_return; @@ -218,7 +218,7 @@ mkdir_iopath(const char *iolog_path, char *pathbuf, size_t pathsize) len = strlcpy(pathbuf, iolog_path, pathsize); if (len >= pathsize) { errno = ENAMETOOLONG; - log_error(USE_ERRNO, "%s", iolog_path); + log_fatal(USE_ERRNO, "%s", iolog_path); } /* @@ -228,10 +228,10 @@ mkdir_iopath(const char *iolog_path, char *pathbuf, size_t pathsize) mkdir_parents(pathbuf); if (len >= 6 && strcmp(&pathbuf[len - 6], "XXXXXX") == 0) { if (mkdtemp(pathbuf) == NULL) - log_error(USE_ERRNO, _("unable to create %s"), pathbuf); + log_fatal(USE_ERRNO, _("unable to create %s"), pathbuf); } else { if (mkdir(pathbuf, S_IRWXU) != 0) - log_error(USE_ERRNO, _("unable to create %s"), pathbuf); + log_fatal(USE_ERRNO, _("unable to create %s"), pathbuf); } debug_return_size_t(len); @@ -439,7 +439,7 @@ sudoers_io_open(unsigned int version, sudo_conv_t conversation, debug_return_bool(true); if (sigsetjmp(error_jmp, 1)) { - /* called via error(), errorx() or log_error() */ + /* called via error(), errorx() or log_fatal() */ rval = -1; goto done; } @@ -496,18 +496,18 @@ sudoers_io_open(unsigned int version, sudo_conv_t conversation, */ io_logfile = open_io_fd(pathbuf, len, "/log", false); if (io_logfile == NULL) - log_error(USE_ERRNO, _("unable to create %s"), pathbuf); + log_fatal(USE_ERRNO, _("unable to create %s"), pathbuf); io_fds[IOFD_TIMING].v = open_io_fd(pathbuf, len, "/timing", iolog_compress); if (io_fds[IOFD_TIMING].v == NULL) - log_error(USE_ERRNO, _("unable to create %s"), pathbuf); + log_fatal(USE_ERRNO, _("unable to create %s"), pathbuf); if (details.iolog_ttyin) { io_fds[IOFD_TTYIN].v = open_io_fd(pathbuf, len, "/ttyin", iolog_compress); if (io_fds[IOFD_TTYIN].v == NULL) - log_error(USE_ERRNO, _("unable to create %s"), pathbuf); + log_fatal(USE_ERRNO, _("unable to create %s"), pathbuf); } else { sudoers_io.log_ttyin = NULL; } @@ -515,7 +515,7 @@ sudoers_io_open(unsigned int version, sudo_conv_t conversation, io_fds[IOFD_STDIN].v = open_io_fd(pathbuf, len, "/stdin", iolog_compress); if (io_fds[IOFD_STDIN].v == NULL) - log_error(USE_ERRNO, _("unable to create %s"), pathbuf); + log_fatal(USE_ERRNO, _("unable to create %s"), pathbuf); } else { sudoers_io.log_stdin = NULL; } @@ -523,7 +523,7 @@ sudoers_io_open(unsigned int version, sudo_conv_t conversation, io_fds[IOFD_TTYOUT].v = open_io_fd(pathbuf, len, "/ttyout", iolog_compress); if (io_fds[IOFD_TTYOUT].v == NULL) - log_error(USE_ERRNO, _("unable to create %s"), pathbuf); + log_fatal(USE_ERRNO, _("unable to create %s"), pathbuf); } else { sudoers_io.log_ttyout = NULL; } @@ -531,7 +531,7 @@ sudoers_io_open(unsigned int version, sudo_conv_t conversation, io_fds[IOFD_STDOUT].v = open_io_fd(pathbuf, len, "/stdout", iolog_compress); if (io_fds[IOFD_STDOUT].v == NULL) - log_error(USE_ERRNO, _("unable to create %s"), pathbuf); + log_fatal(USE_ERRNO, _("unable to create %s"), pathbuf); } else { sudoers_io.log_stdout = NULL; } @@ -539,7 +539,7 @@ sudoers_io_open(unsigned int version, sudo_conv_t conversation, io_fds[IOFD_STDERR].v = open_io_fd(pathbuf, len, "/stderr", iolog_compress); if (io_fds[IOFD_STDERR].v == NULL) - log_error(USE_ERRNO, _("unable to create %s"), pathbuf); + log_fatal(USE_ERRNO, _("unable to create %s"), pathbuf); } else { sudoers_io.log_stderr = NULL; } @@ -581,7 +581,7 @@ sudoers_io_close(int exit_status, int error) debug_decl(sudoers_io_close, SUDO_DEBUG_PLUGIN) if (sigsetjmp(error_jmp, 1)) { - /* called via error(), errorx() or log_error() */ + /* called via error(), errorx() or log_fatal() */ debug_return; } @@ -604,7 +604,7 @@ sudoers_io_version(int verbose) debug_decl(sudoers_io_version, SUDO_DEBUG_PLUGIN) if (sigsetjmp(error_jmp, 1)) { - /* called via error(), errorx() or log_error() */ + /* called via error(), errorx() or log_fatal() */ debug_return_bool(-1); } @@ -626,7 +626,7 @@ sudoers_io_log(const char *buf, unsigned int len, int idx) gettimeofday(&now, NULL); if (sigsetjmp(error_jmp, 1)) { - /* called via error(), errorx() or log_error() */ + /* called via error(), errorx() or log_fatal() */ debug_return_bool(-1); } diff --git a/plugins/sudoers/logging.c b/plugins/sudoers/logging.c index 395f83b41..c6cff0be8 100644 --- a/plugins/sudoers/logging.c +++ b/plugins/sudoers/logging.c @@ -325,18 +325,18 @@ log_allowed(int status) debug_return; } -void -log_error(int flags, const char *fmt, ...) +/* + * Perform logging for log_error()/log_fatal() + */ +static void +vlog_error(int flags, const char *fmt, va_list ap) { int serrno = errno; char *logline, *message; - va_list ap; - debug_decl(log_error, SUDO_DEBUG_LOGGING) + debug_decl(vlog_error, SUDO_DEBUG_LOGGING) /* Expand printf-style format + args. */ - va_start(ap, fmt); evasprintf(&message, fmt, ap); - va_end(ap); /* Become root if we are not already to avoid user interference */ set_perms(PERM_ROOT|PERM_NOEXIT); @@ -376,13 +376,40 @@ log_error(int flags, const char *fmt, ...) restore_perms(); - if (!ISSET(flags, NO_EXIT)) { - plugin_cleanup(0); - siglongjmp(error_jmp, 1); - } debug_return; } +void +log_error(int flags, const char *fmt, ...) +{ + va_list ap; + debug_decl(log_error, SUDO_DEBUG_LOGGING) + + /* Log the error. */ + va_start(ap, fmt); + vlog_error(flags, fmt, ap); + va_end(ap); + + debug_return; +} + +void +log_fatal(int flags, const char *fmt, ...) +{ + va_list ap; + debug_decl(log_error, SUDO_DEBUG_LOGGING) + + /* Log the error. */ + va_start(ap, fmt); + vlog_error(flags, fmt, ap); + va_end(ap); + + /* Exit the plugin. */ + plugin_cleanup(0); + sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys); + siglongjmp(error_jmp, 1); +} + #define MAX_MAILFLAGS 63 /* diff --git a/plugins/sudoers/logging.h b/plugins/sudoers/logging.h index 7a89738c3..d8611ec08 100644 --- a/plugins/sudoers/logging.h +++ b/plugins/sudoers/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 @@ -57,6 +56,7 @@ void audit_failure(char *[], char const * const, ...); void log_allowed(int); void log_denial(int, int); void log_error(int flags, const char *fmt, ...) __printflike(2, 3); +void log_fatal(int flags, const char *fmt, ...) __printflike(2, 3) __attribute__((__noreturn__)); void reapchild(int); void writeln_wrap(FILE *fp, char *line, size_t len, size_t maxlen); diff --git a/plugins/sudoers/parse.c b/plugins/sudoers/parse.c index 66385f07a..4937145f5 100644 --- a/plugins/sudoers/parse.c +++ b/plugins/sudoers/parse.c @@ -120,10 +120,10 @@ sudo_file_parse(struct sudo_nss *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); } debug_return_int(-1); } diff --git a/plugins/sudoers/set_perms.c b/plugins/sudoers/set_perms.c index e3269f2cd..7a2036a00 100644 --- a/plugins/sudoers/set_perms.c +++ b/plugins/sudoers/set_perms.c @@ -1511,7 +1511,7 @@ runas_setgroups(void) aix_restoreauthdb(); #endif if (sudo_setgroups(grlist->ngids, grlist->gids) < 0) - log_error(USE_ERRNO|MSG_ONLY, _("unable to set runas group vector")); + log_fatal(USE_ERRNO|MSG_ONLY, _("unable to set runas group vector")); debug_return_ptr(grlist); } #endif /* HAVE_SETRESUID || HAVE_SETREUID || HAVE_SETEUID */ diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c index 26bb926ed..3f86ea19f 100644 --- a/plugins/sudoers/sudoers.c +++ b/plugins/sudoers/sudoers.c @@ -158,7 +158,7 @@ sudoers_policy_open(unsigned int version, sudo_conv_t conversation, args = NULL; if (sigsetjmp(error_jmp, 1)) { - /* called via error(), errorx() or log_error() */ + /* called via error(), errorx() or log_fatal() */ rewind_perms(); debug_return_bool(-1); } @@ -205,7 +205,7 @@ sudoers_policy_open(unsigned int version, sudo_conv_t conversation, 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) { @@ -236,7 +236,7 @@ sudoers_policy_open(unsigned int version, sudo_conv_t conversation, 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 */ @@ -255,7 +255,7 @@ sudoers_policy_close(int exit_status, int error_code) debug_decl(sudoers_policy_close, SUDO_DEBUG_PLUGIN) if (sigsetjmp(error_jmp, 1)) { - /* called via error(), errorx() or log_error() */ + /* called via error(), errorx() or log_fatal() */ debug_return; } @@ -292,7 +292,7 @@ sudoers_policy_init_session(struct passwd *pwd, char **user_env[]) user_env = NULL; if (sigsetjmp(error_jmp, 1)) { - /* called via error(), errorx() or log_error() */ + /* called via error(), errorx() or log_fatal() */ return -1; } @@ -312,7 +312,7 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[], debug_decl(sudoers_policy_main, SUDO_DEBUG_PLUGIN) if (sigsetjmp(error_jmp, 1)) { - /* error recovery via error(), errorx() or log_error() */ + /* error recovery via error(), errorx() or log_fatal() */ rval = -1; goto done; } @@ -416,7 +416,7 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[], else pw = sudo_getpwnam(def_timestampowner); if (!pw) - log_error(0, _("timestamp owner (%s): No such user"), + log_fatal(0, _("timestamp owner (%s): No such user"), def_timestampowner); timestamp_uid = pw->pw_uid; pw_delref(pw); @@ -852,9 +852,9 @@ init_vars(char * const envp[]) if (sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE) errorx(1, _("unknown uid: %u"), (unsigned int) user_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_fakepwnamid(user_name, user_uid, user_gid); - log_error(0, _("unknown uid: %u"), (unsigned int) user_uid); + log_fatal(0, _("unknown uid: %u"), (unsigned int) user_uid); /* NOTREACHED */ } @@ -867,7 +867,7 @@ init_vars(char * const envp[]) /* Set runas callback. */ sudo_defs_table[I_RUNAS_DEFAULT].callback = cb_runas_default; - /* It is now safe to use log_error() and set_perms() */ + /* It is now safe to use log_fatal() and set_perms() */ debug_return; } @@ -952,7 +952,7 @@ set_cmnd(void) 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")); debug_return_int(rval); } @@ -973,14 +973,14 @@ open_sudoers(const char *sudoers, bool doedit, bool *keepopen) switch (sudo_secure_file(sudoers, sudoers_uid, sudoers_gid, &sb)) { case SUDO_PATH_SECURE: if ((fp = fopen(sudoers, "r")) == NULL) { - log_error(USE_ERRNO|NO_EXIT, _("unable to open %s"), sudoers); + log_error(USE_ERRNO, _("unable to 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 (sb.st_size != 0 && fgetc(fp) == EOF) { - log_error(USE_ERRNO|NO_EXIT, _("unable to read %s"), + log_error(USE_ERRNO, _("unable to read %s"), sudoers); fclose(fp); fp = NULL; @@ -992,20 +992,20 @@ open_sudoers(const char *sudoers, bool doedit, bool *keepopen) } break; case SUDO_PATH_MISSING: - log_error(USE_ERRNO|NO_EXIT, _("unable to stat %s"), sudoers); + log_error(USE_ERRNO, _("unable to stat %s"), sudoers); break; case SUDO_PATH_BAD_TYPE: - log_error(NO_EXIT, _("%s is not a regular file"), sudoers); + log_error(0, _("%s is not a regular file"), sudoers); break; case SUDO_PATH_WRONG_OWNER: - log_error(NO_EXIT, _("%s is owned by uid %u, should be %u"), + log_error(0, _("%s is owned by uid %u, should be %u"), sudoers, (unsigned int) sb.st_uid, (unsigned int) sudoers_uid); break; case SUDO_PATH_WORLD_WRITABLE: - log_error(NO_EXIT, _("%s is world writable"), sudoers); + log_error(0, _("%s is world writable"), sudoers); break; case SUDO_PATH_GROUP_WRITABLE: - log_error(NO_EXIT, _("%s is owned by gid %u, should be %u"), + log_error(0, _("%s is owned by gid %u, should be %u"), sudoers, (unsigned int) sb.st_gid, (unsigned int) sudoers_gid); break; default: @@ -1022,23 +1022,13 @@ open_sudoers(const char *sudoers, bool doedit, bool *keepopen) static void set_loginclass(struct passwd *pw) { - int errflags; + const int errflags = NO_MAIL|MSG_ONLY; login_cap_t *lc; debug_decl(set_loginclass, SUDO_DEBUG_PLUGIN) if (!def_use_loginclass) debug_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) @@ -1053,7 +1043,15 @@ set_loginclass(struct passwd *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; } login_close(lc); @@ -1080,8 +1078,7 @@ set_fqdn(void) hint.ai_family = PF_UNSPEC; hint.ai_flags = AI_CANONNAME; if (getaddrinfo(user_host, NULL, &hint, &res0) != 0) { - 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); @@ -1112,7 +1109,7 @@ set_runaspw(const char *user) runas_pw = sudo_fakepwnam(user, runas_gr ? runas_gr->gr_gid : 0); } else { if ((runas_pw = sudo_getpwnam(user)) == NULL) - log_error(NO_MAIL|MSG_ONLY, _("unknown user: %s"), user); + log_fatal(NO_MAIL|MSG_ONLY, _("unknown user: %s"), user); } debug_return; } @@ -1133,7 +1130,7 @@ set_runasgr(const char *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); } debug_return; } @@ -1178,7 +1175,7 @@ sudoers_policy_version(int verbose) debug_decl(sudoers_policy_version, SUDO_DEBUG_PLUGIN) if (sigsetjmp(error_jmp, 1)) { - /* error recovery via error(), errorx() or log_error() */ + /* error recovery via error(), errorx() or log_fatal() */ debug_return_bool(-1); } -- 2.40.0