]> granicus.if.org Git - sudo/commitdiff
Add init_session function to struct policy_plugin that gets called
authorTodd C. Miller <Todd.Miller@courtesan.com>
Thu, 27 May 2010 18:46:39 +0000 (14:46 -0400)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Thu, 27 May 2010 18:46:39 +0000 (14:46 -0400)
before the uid/gid/etc changes.  A struct passwd pointer is passed in,which may be NULL if the user does not exist in the passwd database.The sudoers module uses init_session to open the pam session as needed.

include/sudo_plugin.h
plugins/sudoers/auth/pam.c
plugins/sudoers/auth/sudo_auth.c
plugins/sudoers/sudoers.c
plugins/sudoers/sudoers.h
src/script.c
src/sudo.c

index 4423883462f3fdb69667dd9b2e532746d97170e4..0bbb7a35de098dca452e81f1560cc264fbe14f35 100644 (file)
@@ -52,6 +52,7 @@ typedef int (*sudo_conv_t)(int num_msgs, const struct sudo_conv_message msgs[],
 typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...);
 
 /* Policy plugin type and defines */
+struct passwd;
 struct policy_plugin {
 #define SUDO_POLICY_PLUGIN     1
     unsigned int type; /* always SUDO_POLICY_PLUGIN */
@@ -68,6 +69,7 @@ struct policy_plugin {
        const char *list_user);
     int (*validate)(void);
     void (*invalidate)(int remove);
+    int (*init_session)(struct passwd *pwd);
 };
 
 /* I/O plugin type and defines */
index 62727defb4474d6c36d92d13648c82feebb4e5b9..ea0a5e142cc7d735066c257b2e6e3c5e583c1541 100644 (file)
@@ -202,8 +202,22 @@ pam_begin_session(pw, auth)
     struct passwd *pw;
     sudo_auth *auth;
 {
-    int status;
+    int status = PAM_SUCCESS;
 
+    /*
+     * If there is no valid user we cannot open a PAM session.
+     * This is not an error as sudo can run commands with arbitrary
+     * uids, it just means we are done from a session management standpoint.
+     */
+    if (pw == NULL) {
+       if (pamh != NULL) {
+           (void) pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT);
+           pamh = NULL;
+       }
+       goto done;
+    }
+
+    /* If the user did not have to authenticate there is no pam handle yet. */
     if (pamh == NULL)
        pam_init(pw, NULL, NULL);
 
@@ -224,16 +238,14 @@ pam_begin_session(pw, auth)
     (void) pam_setcred(pamh, PAM_ESTABLISH_CRED);
 
 #ifndef NO_PAM_SESSION
-    /*
-     * To fully utilize PAM sessions we would need to keep a
-     * sudo process around until the command exits.  However, we
-     * can at least cause pam_limits to be run by opening and then
-     * immediately closing the session.
-     */
     status = pam_open_session(pamh, 0);
-    if (status != PAM_SUCCESS)
+    if (status != PAM_SUCCESS) {
        (void) pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT);
+       pamh = NULL;
+    }
 #endif
+
+done:
     return(status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE);
 }
 
@@ -241,13 +253,14 @@ int
 pam_end_session(auth)
     sudo_auth *auth;
 {
-    int status;
+    int status = PAM_SUCCESS;
 
+    if (pamh) {
 #ifndef NO_PAM_SESSION
-    (void) pam_close_session(pamh, 0);
+       (void) pam_close_session(pamh, PAM_SILENT);
 #endif
-
-    status = pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT);
+       status = pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT);
+    }
     return(status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE);
 }
 
index 75436dbf62e23916845b1dde0f3f520f1da3480d..e674ce4a0c64ed3b601790f79ea143f3f397f8e3 100644 (file)
@@ -234,7 +234,7 @@ cleanup:
     return rval;
 }
 
-int begin_session(struct passwd *pw)
+int auth_begin_session(struct passwd *pw)
 {
     sudo_auth *auth;
     int status;
@@ -251,7 +251,7 @@ int begin_session(struct passwd *pw)
     return TRUE;
 }
 
-int end_session(void)
+int auth_end_session(void)
 {
     sudo_auth *auth;
     int status;
index a729f2ade16491b0a1be15147a783939194afc5e..77cf08c55f931286b0162cfca09b148a3f077eed 100644 (file)
@@ -276,7 +276,20 @@ 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();
+
+    /* Close the session we opened in sudoers_policy_init_session(). */
+    if (ISSET(sudo_mode, MODE_RUN|MODE_EDIT))
+       (void)auth_end_session();
+}
+
+/*
+ * The init_session function is called before executing the command
+ * and before uid/gid changes occur.
+ */
+static int
+sudoers_policy_init_session(struct passwd *pwd)
+{
+    return auth_begin_session(pwd);
 }
 
 static int
@@ -628,15 +641,6 @@ 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;
 }
@@ -1438,7 +1442,8 @@ struct policy_plugin sudoers_policy = {
     sudoers_policy_check,
     sudoers_policy_list,
     sudoers_policy_validate,
-    sudoers_policy_invalidate
+    sudoers_policy_invalidate,
+    sudoers_policy_init_session
 };
 
 struct io_plugin sudoers_io = {
index c7252d05293ae5371b4d6447f2761c3eb166cc08..9b738581bf579efe95aa484fe88586240d0dafd6 100644 (file)
@@ -210,8 +210,8 @@ int user_is_exempt(void);
 
 /* sudo_auth.c */
 int verify_user(struct passwd *, char *);
-int begin_session(struct passwd *);
-int end_session();
+int auth_begin_session(struct passwd *);
+int auth_end_session();
 
 #ifdef HAVE_LDAP
 /* ldap.c */
index 4a0e351e0b9786574a95de28a55b0613a1c790d9..48e933f7302ed9d0d0f64ee385eb4ae2325c3ebc 100644 (file)
@@ -639,7 +639,7 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
        close(sv[0]);
        fcntl(sv[1], F_SETFD, FD_CLOEXEC);
        /* XXX - defer call to exec_setup() until my_execve()? */
-       if (exec_setup(details) == 0) {
+       if (exec_setup(details) == TRUE) {
            /* headed for execve() */
            if (log_io) {
                /* Close the other end of the stdin/stdout/stderr pipes. */
index 0046173812ca870f1ef600c7e41ab99a4b725700..577397b8399c44ad472e9cbec4f85f6f099496b5 100644 (file)
@@ -651,13 +651,23 @@ cleanup(int gotsignal)
 
 /*
  * Setup the execution environment immediately prior to the call to execve()
+ * Returns TRUE on success and FALSE on failure.
  */
 int
 exec_setup(struct command_details *details)
 {
+    int rval = FALSE;
     struct passwd *pw;
 
     pw = getpwuid(details->euid);
+
+    /* Call policy plugin's session init before other setup occurs. */
+    if (policy_plugin.u.policy->init_session) {
+       /* The session init code is expected to print an error as needed. */
+       if (policy_plugin.u.policy->init_session(pw) != TRUE)
+           goto done;
+    }
+
     if (pw != NULL) {
 #ifdef HAVE_GETUSERATTR
        aix_setlimits(pw->pw_name);
@@ -732,15 +742,7 @@ exec_setup(struct command_details *details)
            goto done;
        }
     }
-    if (details->cwd) {
-       /* cwd is relative to the new root, if any */
-       if (chdir(details->cwd) != 0) {
-           warning("unable to change directory to %s", details->cwd);
-           goto done;
-       }
-    }
 
-    /* Must set uids last */
 #ifdef HAVE_SETRESUID
     if (setresuid(details->uid, details->euid, details->euid) != 0) {
        warning("unable to change to runas uid");
@@ -758,10 +760,19 @@ exec_setup(struct command_details *details)
     }
 #endif /* !HAVE_SETRESUID && !HAVE_SETREUID */
 
-    errno = 0;
+    /* Set cwd after uid to avoid permissions problems. */
+    if (details->cwd) {
+       /* Note: cwd is relative to the new root, if any. */
+       if (chdir(details->cwd) != 0) {
+           warning("unable to change directory to %s", details->cwd);
+           goto done;
+       }
+    }
+
+    rval = TRUE;
 
 done:
-    return errno;
+    return rval;
 }
 
 /*