]> granicus.if.org Git - sudo/commitdiff
Defer call to pam_close_session() until after the command finishes
authorTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 8 Jun 2010 19:56:49 +0000 (15:56 -0400)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 8 Jun 2010 19:56:49 +0000 (15:56 -0400)
if there is a monitor process.

--HG--
branch : 1.7

TODO
auth/pam.c
exec.c
exec_pty.c
set_perms.c
sudo.c
sudo.h

diff --git a/TODO b/TODO
index 5baf74c4532080b2e4dd30b6da9165eff28ba1f6..85a76d4a8bb8c4eb3643ac38305b947cb3f11848 100644 (file)
--- a/TODO
+++ b/TODO
@@ -188,10 +188,6 @@ TODO list (most will be addressed in sudo 2.0)
 
 65) See http://iase.disa.mil/stigs/whitepaper/sudowhitepaper-042304.doc
 
-66) Add a session mode where sudo allocates a pty and logs everything
-    that occurs ala script(1).  Logs should be replayable via
-    scriptreplay.pl.  See linux script's -t option for timing info.
+66) Update Active Directory instructions based on Alain Roy's info
 
-67) Update Active Directory instructions based on Alain Roy's info
-
-68) Add support for multiple LDAP trees; from Joachim Henke
+67) Add support for multiple LDAP trees; from Joachim Henke
index f9fa26d34387cc3ea6d6dec2d61ad99be3f9a2f4..57add9ff2711e0db038206873738a372192e9eb9 100644 (file)
@@ -199,11 +199,12 @@ pam_cleanup(pw, auth)
 }
 
 int
-pam_prep_user(pw)
+pam_begin_session(pw)
     struct passwd *pw;
 {
-    int eval;
+    int status =  PAM_SUCCESS;
 
+    /* If the user did not have to authenticate there is no pam handle yet. */
     if (pamh == NULL)
        pam_init(pw, NULL, NULL);
 
@@ -224,23 +225,27 @@ pam_prep_user(pw)
     (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.
-     */
-    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, status | PAM_DATA_SILENT);
+       pamh = NULL;
     }
-    (void) pam_close_session(pamh, 0);
 #endif
+    return(status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE);
+}
 
-    if (pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT) == PAM_SUCCESS)
-       return(AUTH_SUCCESS);
-    else
-       return(AUTH_FAILURE);
+int
+pam_end_session()
+{
+    int status = PAM_SUCCESS;
+
+    if (pamh != NULL) {
+#ifndef NO_PAM_SESSION
+       (void) pam_close_session(pamh, 0);
+#endif
+       status = pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT);
+    }
+    return(status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE);
 }
 
 /*
diff --git a/exec.c b/exec.c
index 54aa145f5fa7012823fafe40ddb78d6ab85480a3..6c0ae4c2a146c6429e62314d4efef63128af4221 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -127,7 +127,7 @@ static int fork_cmnd(path, argv, envp, sv, rbac_enabled)
        if (rbac_enabled)
            selinux_setup(user_role, user_type, user_ttypath, -1);
 #endif
-       if (exec_setup() == TRUE) {
+       if (exec_setup(PERM_DOWAIT) == TRUE) {
            /* headed for execve() */
            closefrom(def_closefrom);
 #ifdef HAVE_SELINUX
@@ -187,7 +187,7 @@ sudo_execve(path, argv, envp, uid, cstat, dowait)
      * If we don't need to wait for the command to finish, just exec it.
      */
     if (!dowait) {
-       exec_setup();
+       exec_setup(0);
        closefrom(def_closefrom);
        my_execve(path, argv, envp);
        cstat->type = CMD_ERRNO;
index c97abbec492bbf4c7d86c3ea41d5ed7d0706d7e5..aefdd75b2d08c452eeb2002da90103a3a253410a 100644 (file)
@@ -463,7 +463,7 @@ fork_pty(path, argv, envp, sv, rbac_enabled, maxfd)
        if (rbac_enabled)
            selinux_setup(user_role, user_type, slavename, io_fds[SFD_SLAVE]);
 #endif
-       if (exec_setup() == TRUE) {
+       if (exec_setup(PERM_DOWAIT) == TRUE) {
            /* Close the other end of the stdin/stdout/stderr pipes and exec. */
            if (io_pipe[STDIN_FILENO][1])
                close(io_pipe[STDIN_FILENO][1]);
index 99b310d9ccd5eb868c85af8261014a1da6682533..53557302162e69f9fb2bb2f7ea46cf651683c226 100644 (file)
@@ -60,7 +60,7 @@
 /*
  * Prototypes
  */
-static void runas_setup                __P((void));
+static void runas_setup                __P((int));
 static void runas_setgroups    __P((void));
 static void restore_groups     __P((void));
 
@@ -78,9 +78,10 @@ set_perms(perm)
     int perm;
 {
     const char *errstr;
-    int noexit;
+    int noexit, dowait;
 
     noexit = ISSET(perm, PERM_NOEXIT);
+    dowait = ISSET(perm, PERM_DOWAIT);
     CLR(perm, PERM_MASK);
 
     if (perm == current_perm)
@@ -127,7 +128,7 @@ set_perms(perm)
 
        case PERM_FULL_RUNAS:
                                /* headed for exec(), assume euid == ROOT_UID */
-                               runas_setup();
+                               runas_setup(dowait);
                                if (setresuid(def_stay_setuid ?
                                    user_uid : runas_pw->pw_uid,
                                    runas_pw->pw_uid, runas_pw->pw_uid)) {
@@ -192,9 +193,10 @@ set_perms(perm)
     int perm;
 {
     const char *errstr;
-    int noexit;
+    int noexit, dowait;
 
     noexit = ISSET(perm, PERM_NOEXIT);
+    dowait = ISSET(perm, PERM_DOWAIT);
     CLR(perm, PERM_MASK);
 
     if (perm == current_perm)
@@ -245,7 +247,7 @@ set_perms(perm)
 
        case PERM_FULL_RUNAS:
                                /* headed for exec(), assume euid == ROOT_UID */
-                               runas_setup();
+                               runas_setup(dowait);
                                if (setreuid(def_stay_setuid ? user_uid :
                                    runas_pw->pw_uid, runas_pw->pw_uid)) {
                                    errstr = "unable to change to runas uid";
@@ -307,9 +309,10 @@ set_perms(perm)
     int perm;
 {
     const char *errstr;
-    int noexit;
+    int noexit, dowait;
 
     noexit = ISSET(perm, PERM_NOEXIT);
+    dowait = ISSET(perm, PERM_DOWAIT);
     CLR(perm, PERM_MASK);
 
     if (perm == current_perm)
@@ -366,7 +369,7 @@ set_perms(perm)
 
        case PERM_FULL_RUNAS:
                                /* headed for exec() */
-                               runas_setup();
+                               runas_setup(dowait);
                                if (setuid(runas_pw->pw_uid)) {
                                    errstr = "unable to change to runas uid";
                                    goto bad;
@@ -426,9 +429,10 @@ set_perms(perm)
     int perm;
 {
     const char *errstr;
-    int noexit;
+    int noexit, dowait;
 
     noexit = ISSET(perm, PERM_NOEXIT);
+    dowait = ISSET(perm, PERM_DOWAIT);
     CLR(perm, PERM_MASK);
 
     if (perm == current_perm)
@@ -453,7 +457,7 @@ set_perms(perm)
                                break;
                                
        case PERM_FULL_RUNAS:
-                               runas_setup();
+                               runas_setup(dowait);
                                if (setuid(runas_pw->pw_uid)) {
                                    errstr = "unable to change to runas uid";
                                    goto bad;
@@ -538,7 +542,8 @@ restore_groups()
 #endif /* HAVE_INITGROUPS */
 
 static void
-runas_setup()
+runas_setup(dowait)
+    int dowait;
 {
     gid_t gid;
 #ifdef HAVE_LOGIN_CAP_H
@@ -552,7 +557,9 @@ runas_setup()
        aix_setlimits(runas_pw->pw_name);
 #endif
 #ifdef HAVE_PAM
-       pam_prep_user(runas_pw);
+       pam_begin_session(runas_pw);
+       if (!dowait)
+           pam_end_session();
 #endif /* HAVE_PAM */
 
 #ifdef HAVE_LOGIN_CAP_H
diff --git a/sudo.c b/sudo.c
index eaa388f5fdd209fa8d2b01807492ecfa71eead5c..f3a05be0cc3988f5a2dc3a42665824e3c7957dd9 100644 (file)
--- a/sudo.c
+++ b/sudo.c
@@ -808,7 +808,8 @@ set_cmnd(sudo_mode)
  * Returns TRUE on success and FALSE on failure.
  */
 int
-exec_setup()
+exec_setup(flags)
+    int flags;
 {
     int rval = FALSE;
 
@@ -847,7 +848,7 @@ exec_setup()
 #endif /* RLIMIT_CORE && !SUDO_DEVEL */
 
     if (ISSET(sudo_mode, MODE_RUN))
-       set_perms(PERM_FULL_RUNAS);
+       set_perms(PERM_FULL_RUNAS|flags);
 
     if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
        /* Change to target user's homedir. */
@@ -916,6 +917,9 @@ run_command(path, argv, envp, uid, dowait)
        warningx("unexpected child termination condition: %d", cstat.type);
        break;
     }
+#ifdef HAVE_PAM
+    pam_end_session();
+#endif /* HAVE_PAM */
 #ifdef _PATH_SUDO_IO_LOGDIR
     io_log_close();
 #endif
diff --git a/sudo.h b/sudo.h
index e07876ef3e8b02931b22a782fc856000a8bef58f..e9ea962172be750b0e72e88264afcfd802aac670 100644 (file)
--- a/sudo.h
+++ b/sudo.h
@@ -148,6 +148,7 @@ struct command_status {
 #define PERM_FULL_RUNAS          0x05
 #define PERM_TIMESTAMP           0x06
 #define PERM_NOEXIT              0x10 /* flag */
+#define PERM_DOWAIT              0x20 /* flag */
 #define PERM_MASK                0xf0
 
 /*
@@ -285,7 +286,8 @@ int sudo_ldap_display_bound_defaults __P((struct sudo_nss *, struct passwd *, st
 int sudo_ldap_display_privs __P((struct sudo_nss *, struct passwd *, struct lbuf *));
 
 /* pam.c */
-int pam_prep_user      __P((struct passwd *));
+int pam_begin_session  __P((struct passwd *));
+int pam_end_session    __P((void));
 
 /* parse.c */
 int sudo_file_open     __P((struct sudo_nss *));
@@ -330,7 +332,7 @@ int set_perms               __P((int));
 
 /* sudo.c */
 FILE *open_sudoers     __P((const char *, int, int *));
-int exec_setup __P((void));
+int exec_setup         __P((int));
 void cleanup           __P((int));
 void set_fqdn          __P((void));