]> granicus.if.org Git - sudo/commitdiff
Add open/close session to sudo auth, only used by PAM.
authorTodd C. Miller <Todd.Miller@courtesan.com>
Wed, 26 May 2010 21:57:47 +0000 (17:57 -0400)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Wed, 26 May 2010 21:57:47 +0000 (17:57 -0400)
This allows us to open (and close) the PAM session from sudoers.

plugins/sudoers/auth/pam.c
plugins/sudoers/auth/sudo_auth.c
plugins/sudoers/auth/sudo_auth.h
plugins/sudoers/set_perms.c
plugins/sudoers/sudoers.c
plugins/sudoers/sudoers.h

index 3c569c908e1791e434ea3435e417bcb5df029b24..62727defb4474d6c36d92d13648c82feebb4e5b9 100644 (file)
@@ -81,7 +81,7 @@ static int gotintr;
 #define PAM_DATA_SILENT        0
 #endif
 
-static pam_handle_t *pamh;     /* global due to pam_prep_user() */
+static pam_handle_t *pamh;
 
 int
 pam_init(pw, promptp, auth)
@@ -189,7 +189,7 @@ pam_cleanup(pw, auth)
 {
     int *pam_status = (int *) auth->data;
 
-    /* If successful, we can't close the session until pam_prep_user() */
+    /* If successful, we can't close the session until pam_end_session() */
     if (auth->status == AUTH_SUCCESS)
        return(AUTH_SUCCESS);
 
@@ -198,10 +198,11 @@ pam_cleanup(pw, auth)
 }
 
 int
-pam_prep_user(pw)
+pam_begin_session(pw, auth)
     struct passwd *pw;
+    sudo_auth *auth;
 {
-    int eval;
+    int status;
 
     if (pamh == NULL)
        pam_init(pw, NULL, NULL);
@@ -229,17 +230,25 @@ pam_prep_user(pw)
      * can at least cause pam_limits to be run by opening and then
      * immediately closing the session.
      */
-    if ((eval = pam_open_session(pamh, 0)) != PAM_SUCCESS) {
-       (void) pam_end(pamh, eval | PAM_DATA_SILENT);
-       return(AUTH_FAILURE);
-    }
+    status = pam_open_session(pamh, 0);
+    if (status != PAM_SUCCESS)
+       (void) pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT);
+#endif
+    return(status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE);
+}
+
+int
+pam_end_session(auth)
+    sudo_auth *auth;
+{
+    int status;
+
+#ifndef NO_PAM_SESSION
     (void) pam_close_session(pamh, 0);
 #endif
 
-    if (pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT) == PAM_SUCCESS)
-       return(AUTH_SUCCESS);
-    else
-       return(AUTH_FAILURE);
+    status = pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT);
+    return(status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE);
 }
 
 /*
index 3990d7e7b88c62aeb25fbfafde5ba1172c0733a8..75436dbf62e23916845b1dde0f3f520f1da3480d 100644 (file)
@@ -57,33 +57,37 @@ sudo_auth auth_switch[] = {
     AUTH_STANDALONE
 #else
 #  ifndef WITHOUT_PASSWD
-    AUTH_ENTRY(0, "passwd", passwd_init, NULL, passwd_verify, NULL)
+    AUTH_ENTRY(0, "passwd", passwd_init, NULL, passwd_verify, NULL, NULL, NULL)
 #  endif
 #  if defined(HAVE_GETPRPWNAM) && !defined(WITHOUT_PASSWD)
-    AUTH_ENTRY(0, "secureware", secureware_init, NULL, secureware_verify, NULL)
+    AUTH_ENTRY(0, "secureware", secureware_init, NULL, secureware_verify, NULL, NULL, NULL)
 #  endif
 #  ifdef HAVE_AFS
-    AUTH_ENTRY(0, "afs", NULL, NULL, afs_verify, NULL)
+    AUTH_ENTRY(0, "afs", NULL, NULL, afs_verify, NULL, NULL, NULL)
 #  endif
 #  ifdef HAVE_DCE
-    AUTH_ENTRY(0, "dce", NULL, NULL, dce_verify, NULL)
+    AUTH_ENTRY(0, "dce", NULL, NULL, dce_verify, NULL, NULL, NULL)
 #  endif
 #  ifdef HAVE_KERB4
-    AUTH_ENTRY(0, "kerb4", kerb4_init, NULL, kerb4_verify, NULL)
+    AUTH_ENTRY(0, "kerb4", kerb4_init, NULL, kerb4_verify, NULL, NULL, NULL)
 #  endif
 #  ifdef HAVE_KERB5
-    AUTH_ENTRY(0, "kerb5", kerb5_init, NULL, kerb5_verify, kerb5_cleanup)
+    AUTH_ENTRY(0, "kerb5", kerb5_init, NULL, kerb5_verify, kerb5_cleanup, NULL, NULL)
 #  endif
 #  ifdef HAVE_SKEY
-    AUTH_ENTRY(0, "S/Key", NULL, rfc1938_setup, rfc1938_verify, NULL)
+    AUTH_ENTRY(0, "S/Key", NULL, rfc1938_setup, rfc1938_verify, NULL, NULL, NULL)
 #  endif
 #  ifdef HAVE_OPIE
-    AUTH_ENTRY(0, "OPIE", NULL, rfc1938_setup, rfc1938_verify, NULL)
+    AUTH_ENTRY(0, "OPIE", NULL, rfc1938_setup, rfc1938_verify, NULL, NULL, NULL)
 #  endif
 #endif /* AUTH_STANDALONE */
-    AUTH_ENTRY(0, NULL, NULL, NULL, NULL, NULL)
+    AUTH_ENTRY(0, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
 };
 
+extern char **NewArgv; /* XXX - for auditing */
+
+static void pass_warn(void);
+
 int
 verify_user(struct passwd *pw, char *prompt)
 {
@@ -93,7 +97,6 @@ verify_user(struct passwd *pw, char *prompt)
     char *p;
     sudo_auth *auth;
     sigaction_t sa, osa;
-    extern char **NewArgv; /* XXX */
 
     /* Enable suspend during password entry. */
     sigemptyset(&sa.sa_mask);
@@ -181,9 +184,7 @@ verify_user(struct passwd *pw, char *prompt)
        if (p)
            zero_bytes(p, strlen(p));
 #endif
-       /* XXX - need way to know if askpass was used */
-       //if (!ISSET(tgetpass_flags, TGP_ASKPASS))
-           pass_warn();
+       pass_warn();
     }
 
 cleanup:
@@ -233,7 +234,40 @@ cleanup:
     return rval;
 }
 
-void
+int begin_session(struct passwd *pw)
+{
+    sudo_auth *auth;
+    int status;
+
+    for (auth = auth_switch; auth->name; auth++) {
+       if (auth->begin_session && IS_CONFIGURED(auth)) {
+           status = (auth->begin_session)(pw, auth);
+           if (status == AUTH_FATAL) { /* XXX log */
+               audit_failure(NewArgv, "authentication failure");
+               return -1;              /* assume error msg already printed */
+           }
+       }
+    }
+    return TRUE;
+}
+
+int end_session(void)
+{
+    sudo_auth *auth;
+    int status;
+
+    for (auth = auth_switch; auth->name; auth++) {
+       if (auth->end_session && IS_CONFIGURED(auth)) {
+           status = (auth->end_session)(auth);
+           if (status == AUTH_FATAL) { /* XXX log */
+               return -1;              /* assume error msg already printed */
+           }
+       }
+    }
+    return TRUE;
+}
+
+static void
 pass_warn(void)
 {
     struct sudo_conv_message msg[2];
index 494b98eb6a61cacf0348db7a870a55bfdce2d9f3..ef1bad2e7b14f77adfd7a3243b431b55e983bd23 100644 (file)
@@ -32,6 +32,8 @@ typedef struct sudo_auth {
     int (*setup)(struct passwd *pw, char **prompt, struct sudo_auth *auth);
     int (*verify)(struct passwd *pw, char *p, struct sudo_auth *auth);
     int (*cleanup)(struct passwd *pw, struct sudo_auth *auth);
+    int (*begin_session)(struct passwd *pw, struct sudo_auth *auth);
+    int (*end_session)(struct sudo_auth *auth);
 } sudo_auth;
 
 /* Values for sudo_auth.flags.  */
@@ -58,6 +60,8 @@ int fwtk_cleanup(struct passwd *pw, sudo_auth *auth);
 int pam_init(struct passwd *pw, char **prompt, sudo_auth *auth);
 int pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth);
 int pam_cleanup(struct passwd *pw, sudo_auth *auth);
+int pam_begin_session(struct passwd *pw, sudo_auth *auth);
+int pam_end_session(sudo_auth *auth);
 int sia_setup(struct passwd *pw, char **prompt, sudo_auth *auth);
 int sia_verify(struct passwd *pw, char *prompt, sudo_auth *auth);
 int sia_cleanup(struct passwd *pw, sudo_auth *auth);
@@ -86,34 +90,34 @@ int securid_setup(struct passwd *pw, char **prompt, sudo_auth *auth);
 int securid_verify(struct passwd *pw, char *pass, sudo_auth *auth);
 
 /* Fields: need_root, name, init, setup, verify, cleanup */
-#define AUTH_ENTRY(r, n, i, s, v, c) \
-       { (r|FLAG_CONFIGURED), AUTH_FAILURE, n, NULL, i, s, v, c },
+#define AUTH_ENTRY(r, n, i, s, v, c, b, e) \
+       { (r|FLAG_CONFIGURED), AUTH_FAILURE, n, NULL, i, s, v, c , b, e },
 
-/* Some methods cannots (or should not) interoperate with any others */
+/* Some methods cannot (or should not) interoperate with any others */
 #if defined(HAVE_PAM)
 #  define AUTH_STANDALONE \
        AUTH_ENTRY(0, "pam", \
-           pam_init, NULL, pam_verify, pam_cleanup)
+           pam_init, NULL, pam_verify, pam_cleanup, pam_begin_session, pam_end_session)
 #elif defined(HAVE_SECURID)
 #  define AUTH_STANDALONE \
        AUTH_ENTRY(0, "SecurId", \
-           securid_init, securid_setup, securid_verify, NULL)
+           securid_init, securid_setup, securid_verify, NULL, NULL, NULL)
 #elif defined(HAVE_SIA_SES_INIT)
 #  define AUTH_STANDALONE \
        AUTH_ENTRY(0, "sia", \
-           NULL, sia_setup, sia_verify, sia_cleanup)
+           NULL, sia_setup, sia_verify, sia_cleanup, NULL, NULL)
 #elif defined(HAVE_AIXAUTH)
 #  define AUTH_STANDALONE \
        AUTH_ENTRY(0, "aixauth", \
-           NULL, NULL, aixauth_verify, aixauth_cleanup)
+           NULL, NULL, aixauth_verify, aixauth_cleanup, NULL, NULL)
 #elif defined(HAVE_FWTK)
 #  define AUTH_STANDALONE \
        AUTH_ENTRY(0, "fwtk", \
-           fwtk_init, NULL, fwtk_verify, fwtk_cleanup)
+           fwtk_init, NULL, fwtk_verify, fwtk_cleanup, NULL, NULL)
 #elif defined(HAVE_BSD_AUTH_H)
 #  define AUTH_STANDALONE \
        AUTH_ENTRY(0, "bsdauth", \
-           bsdauth_init, NULL, bsdauth_verify, bsdauth_cleanup)
+           bsdauth_init, NULL, bsdauth_verify, bsdauth_cleanup, NULL, NULL)
 #endif
 
 #endif /* SUDO_AUTH_H */
index a9e12344a0cd845745f87b3c823cf6401bfdf8bc..ff149c5df3b3feb35a0b68196b0861333f3cb42d 100644 (file)
@@ -60,9 +60,6 @@
 /*
  * Prototypes
  */
-#if 0
-static void runas_setup(void);
-#endif
 static void runas_setgroups(void);
 
 /*
@@ -969,51 +966,3 @@ runas_setgroups()
 }
 
 #endif /* HAVE_INITGROUPS */
-
-#if 0
-static void
-runas_setup()
-{
-    gid_t gid;
-#ifdef HAVE_LOGIN_CAP_H
-    int flags;
-    extern login_cap_t *lc;
-#endif
-
-    if (runas_pw->pw_name != NULL) {
-       gid = runas_gr ? runas_gr->gr_gid : runas_pw->pw_gid;
-#ifdef HAVE_GETUSERATTR
-       aix_setlimits(runas_pw->pw_name);
-#endif
-#ifdef HAVE_PAM
-       /* XXX - move this */
-       pam_prep_user(runas_pw);
-#endif /* HAVE_PAM */
-
-#ifdef HAVE_LOGIN_CAP_H
-       if (def_use_loginclass) {
-           /*
-             * We only use setusercontext() to set the nice value and rlimits.
-            */
-           flags = LOGIN_SETRESOURCES|LOGIN_SETPRIORITY;
-           if (setusercontext(lc, runas_pw, runas_pw->pw_uid, flags)) {
-               if (runas_pw->pw_uid != ROOT_UID)
-                   error(1, "unable to set user context");
-               else
-                   warning("unable to set user context");
-           }
-       }
-#endif /* HAVE_LOGIN_CAP_H */
-       /*
-        * Initialize group vector
-        */
-       runas_setgroups();
-#ifdef HAVE_SETEUID
-       if (setegid(gid))
-           warning("cannot set egid to runas gid");
-#endif
-       if (setgid(gid))
-           warning("cannot set gid to runas gid");
-    }
-}
-#endif
index b867d81bb64dfc13cf97a4230590b4bfff325388..a729f2ade16491b0a1be15147a783939194afc5e 100644 (file)
@@ -276,6 +276,7 @@ sudoers_policy_close(int exit_status, int error_code)
     /* We do not currently log the exit status. */
     if (error_code)
        warningx("unable to execute %s: %s", safe_cmnd, strerror(error_code));
+    end_session();
 }
 
 static int
@@ -627,6 +628,15 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
 
     restore_perms();
 
+    /*
+     * Ideally we would like to do session setup (currently only PAM)
+     * from inside sudo itself, but this should be close enough.
+     */
+    if (ISSET(sudo_mode, MODE_RUN))
+       rval = begin_session(runas_pw);
+    if (ISSET(sudo_mode, MODE_EDIT))
+       rval = begin_session(sudo_user.pw);
+
 done:
     return rval;
 }
index 0b76617024a910b0cd3466a70e1921263ac56090..c7252d05293ae5371b4d6447f2761c3eb166cc08 100644 (file)
@@ -210,7 +210,8 @@ int user_is_exempt(void);
 
 /* sudo_auth.c */
 int verify_user(struct passwd *, char *);
-void pass_warn(void);
+int begin_session(struct passwd *);
+int end_session();
 
 #ifdef HAVE_LDAP
 /* ldap.c */