]> granicus.if.org Git - sudo/commitdiff
Fetch the login class for the user we authenticate specifically
authorTodd C. Miller <Todd.Miller@courtesan.com>
Thu, 12 Jan 2012 19:23:42 +0000 (14:23 -0500)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Thu, 12 Jan 2012 19:23:42 +0000 (14:23 -0500)
when using BSD authentication. That user may have a different login
class than what we will use to run the command. When setting the
login class for the command, use the target user's struct passwd,
not the invoking user's.

--HG--
branch : 1.7

auth/bsdauth.c
sudo.c

index fd244a7d83224da8fa85172898ab01de5b25d3e6..e255afa086797ab67859133890dd209da7a692a8 100644 (file)
 #include "sudo.h"
 #include "sudo_auth.h"
 
+#ifndef LOGIN_DEFROOTCLASS
+# define LOGIN_DEFROOTCLASS    "daemon"
+#endif
+
 extern char *login_style;              /* from sudo.c */
 
+struct bsdauth_state {
+    auth_session_t *as;
+    login_cap_t *lc;
+};
+
 int
 bsdauth_init(pw, auth)
     struct passwd *pw;
     sudo_auth *auth;
 {
-    static auth_session_t *as;
-    extern login_cap_t *lc;                    /* from sudo.c */
+    static struct bsdauth_state state;
+
+    /* Get login class based on auth user, which may not be invoking user. */
+    if (pw->pw_class && *pw->pw_class)
+       state.lc = login_getclass(pw->pw_class);
+    else
+       state.lc = login_getclass(pw->pw_uid ? LOGIN_DEFCLASS : LOGIN_DEFROOTCLASS);
+    if (state.lc == NULL) {
+       log_error(USE_ERRNO|NO_EXIT|NO_MAIL,
+           "unable to get login class for user %s", pw->pw_name);
+       return AUTH_FATAL;
+    }
 
-    if ((as = auth_open()) == NULL) {
+    if ((state.as = auth_open()) == NULL) {
        log_error(USE_ERRNO|NO_EXIT|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(lc, login_style, "auth-sudo");
+    login_style = login_getstyle(state.lc, login_style, "auth-sudo");
     if (login_style == NULL) {
        log_error(NO_EXIT|NO_MAIL, "invalid authentication type");
-       auth_close(as);
+       auth_close(state.as);
+       login_close(state.lc);
        return AUTH_FATAL;
     }
 
-     if (auth_setitem(as, AUTHV_STYLE, login_style) < 0 ||
-       auth_setitem(as, AUTHV_NAME, pw->pw_name) < 0 ||
-       auth_setitem(as, AUTHV_CLASS, login_class) < 0) {
+     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");
-       auth_close(as);
+       auth_close(state.as);
+       login_close(state.lc);
        return AUTH_FATAL;
     }
 
-    auth->data = (void *) as;
+    auth->data = (void *) &state;
     return AUTH_SUCCESS;
 }
 
@@ -98,7 +120,7 @@ bsdauth_verify(pw, prompt, auth)
     size_t len;
     int authok = 0;
     sigaction_t sa, osa;
-    auth_session_t *as = (auth_session_t *) auth->data;
+    auth_session_t *as = ((struct bsdauth_state *) auth->data)->as;
 
     /* save old signal handler */
     sigemptyset(&sa.sa_mask);
@@ -160,9 +182,12 @@ bsdauth_cleanup(pw, auth)
     struct passwd *pw;
     sudo_auth *auth;
 {
-    auth_session_t *as = (auth_session_t *) auth->data;
+    struct bsdauth_state *state = auth->data;
 
-    auth_close(as);
+    if (state != NULL) {
+       auth_close(state->as);
+       login_close(state->lc);
+    }
 
     return AUTH_SUCCESS;
 }
diff --git a/sudo.c b/sudo.c
index f494a61e2d17e4d0006ab0d3fd1b154a785f5456..87728abdfa2099bdf3a1177e3179ff5a97021116 100644 (file)
--- a/sudo.c
+++ b/sudo.c
@@ -309,7 +309,7 @@ main(argc, argv, envp)
        set_fqdn();     /* deferred until after sudoers is parsed */
 
     /* Set login class if applicable. */
-    set_loginclass(sudo_user.pw);
+    set_loginclass(runas_pw ? runas_pw : sudo_user.pw);
 
     /* Update initial shell now that runas is set. */
     if (ISSET(sudo_mode, MODE_LOGIN_SHELL))
@@ -1131,6 +1131,9 @@ set_loginclass(pw)
 {
     int errflags;
 
+    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
@@ -1152,12 +1155,13 @@ set_loginclass(pw)
                (pw->pw_uid == 0) ? LOGIN_DEFROOTCLASS : LOGIN_DEFCLASS;
     }
 
+    /* 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);
-       if (!lc)
-           lc = login_getclass(NULL);  /* needed for login_getstyle() later */
+       def_use_loginclass = FALSE;
     }
+    login_close(lc);
 }
 #else
 static void