]> granicus.if.org Git - sudo/commitdiff
Modify the authentication API such that the init and cleanup functions
authorTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 27 Sep 2011 20:29:27 +0000 (16:29 -0400)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 27 Sep 2011 20:29:27 +0000 (16:29 -0400)
are always called, regardless of whether or not we are going to
verify a password.  This is needed for proper PAM session support.

--HG--
branch : 1.7

15 files changed:
auth/API
auth/bsdauth.c
auth/fwtk.c
auth/kerb4.c
auth/kerb5.c
auth/pam.c
auth/passwd.c
auth/secureware.c
auth/securid.c
auth/securid5.c
auth/sudo_auth.c
auth/sudo_auth.h
check.c
sudo.c
sudo.h

index fd183fe8421054c9f3350adf5dd78a1b8d0bd000..d1535cb95423e03ffc551c2a74a933a23410e434 100644 (file)
--- a/auth/API
+++ b/auth/API
@@ -12,7 +12,7 @@ typedef struct sudo_auth {
     char *name;                        /* name of the method in string form */
     void *data;                 /* method-specific data pointer */
 
-    int (*init) __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+    int (*init) __P((struct passwd *pw, sudo_auth *auth));
     int (*setup) __P((struct passwd *pw, char **prompt, sudo_auth *auth));
     int (*verify) __P((struct passwd *pw, char *p, sudo_auth *auth));
     int (*cleanup) __P((struct passwd *pw, sudo_auth *auth));
@@ -61,11 +61,10 @@ The member functions can return the following values:
 
 The functions in the struct are as follows:
 
-    int init(struct passwd *pw, char **prompt, sudo_auth *auth)
+    int init(struct passwd *pw, sudo_auth *auth)
         Function to do any one-time initialization for the auth
         method.  All of the "init" functions are run before anything
-        else.  A pointer to the prompt string may be used to add
-        method-specific info to the prompt.
+        else.
 
     int setup(struct passwd *pw, char **prompt, sudo_auth *auth)
         Function to do method-specific setup.  All the "setup"
index 727df13b08fab31533f4665ae5fa9037ee27bfab..fd244a7d83224da8fa85172898ab01de5b25d3e6 100644 (file)
@@ -54,9 +54,8 @@
 extern char *login_style;              /* from sudo.c */
 
 int
-bsdauth_init(pw, promptp, auth)
+bsdauth_init(pw, auth)
     struct passwd *pw;
-    char **promptp;
     sudo_auth *auth;
 {
     static auth_session_t *as;
index f1c164e976aee026a9cc66b7d8cedd4a42d88cad..2764fd5ed5060c70ffd8609607cd02bb87b7d427 100644 (file)
@@ -50,9 +50,8 @@
 #include "sudo_auth.h"
 
 int
-fwtk_init(pw, promptp, auth)
+fwtk_init(pw, auth)
     struct passwd *pw;
-    char **promptp;
     sudo_auth *auth;
 {
     static Cfg *confp;                 /* Configuration entry struct */
index 883035d95dbbd74626e73a4cf184794bb4a73ed2..a1bcfb8e20a3e8949e2fc128500b381b6ab56505 100644 (file)
@@ -48,9 +48,8 @@
 #include "sudo_auth.h"
 
 int
-kerb4_init(pw, promptp, auth)
+kerb4_init(pw, auth)
     struct passwd *pw;
-    char **promptp;
     sudo_auth *auth;
 {
     static char realm[REALM_SZ];
index 4ce04aa1287de9e0bf0fa5e796ddbc052a87661b..9582c6f5cb9a8d690ae921a9ac8c31cf3a0f4f4d 100644 (file)
@@ -90,17 +90,54 @@ krb5_get_init_creds_opt_free(opts)
 #endif
 
 int
-kerb5_init(pw, promptp, auth)
+kerb5_setup(pw, promptp, auth)
     struct passwd *pw;
     char **promptp;
     sudo_auth *auth;
+{
+    static char        *krb5_prompt;
+
+    if (krb5_prompt == NULL) {
+       krb5_context    sudo_context;
+       krb5_principal  princ;
+       char            *pname;
+       krb5_error_code error;
+
+       sudo_context = ((sudo_krb5_datap) auth->data)->sudo_context;
+       princ = ((sudo_krb5_datap) auth->data)->princ;
+
+       /*
+        * Really, we need to tell the caller not to prompt for password. The
+        * 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,
+                     "%s: unable to unparse princ ('%s'): %s", auth->name,
+                     pw->pw_name, error_message(error));
+           return AUTH_FAILURE;
+       }
+
+       /* Only rewrite prompt if user didn't specify their own. */
+       /*if (!strcmp(prompt, PASSPROMPT)) { */
+           easprintf(&krb5_prompt, "Password for %s: ", pname);
+       /*}*/
+       free(pname);
+    }
+    *promptp = krb5_prompt;
+
+    return AUTH_SUCCESS;
+}
+
+int
+kerb5_init(pw, auth)
+    struct passwd *pw;
+    sudo_auth *auth;
 {
     krb5_context       sudo_context;
     krb5_ccache                ccache;
     krb5_principal     princ;
     krb5_error_code    error;
     char               cache_name[64];
-    char               *pname;
 
     auth->data = (void *) &sudo_krb5_data; /* Stash all our data here */
 
@@ -122,25 +159,6 @@ kerb5_init(pw, promptp, auth)
     }
     princ = sudo_krb5_data.princ;
 
-    /*
-     * Really, we need to tell the caller not to prompt for password.
-     * The API does not currently provide this unless the auth is standalone.
-     */
-#if 1
-    if ((error = krb5_unparse_name(sudo_context, princ, &pname))) {
-       log_error(NO_EXIT|NO_MAIL,
-                 "%s: unable to unparse princ ('%s'): %s", auth->name,
-                 pw->pw_name, error_message(error));
-       return AUTH_FAILURE;
-    }
-
-    /* Only rewrite prompt if user didn't specify their own. */
-    /*if (!strcmp(prompt, PASSPROMPT)) { */
-       easprintf(promptp, "Password for %s: ", pname);
-    /*}*/
-    free(pname);
-#endif
-
     (void) snprintf(cache_name, sizeof(cache_name), "MEMORY:sudocc_%ld",
                    (long) getpid());
     if ((error = krb5_cc_resolve(sudo_context, cache_name,
index 265de36e3ca47838f0e8270fea716eb6ae2cb01d..39d658e5d3188fcc88d12d818ea5f0eba6c4d2de 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999-2005, 2007-2010 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 1999-2005, 2007-2011 Todd C. Miller <Todd.Miller@courtesan.com>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -78,12 +78,11 @@ 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)
+pam_init(pw, auth)
     struct passwd *pw;
-    char **promptp;
     sudo_auth *auth;
 {
     static struct pam_conv pam_conv;
@@ -194,11 +193,12 @@ pam_cleanup(pw, auth)
 {
     int *pam_status = (int *) auth->data;
 
-    /* If successful, we can't close the session until pam_prep_user() */
-    if (auth->status == AUTH_SUCCESS)
+    /* If successful, we can't close the session until pam_end_session() */
+    if (*pam_status == AUTH_SUCCESS)
        return AUTH_SUCCESS;
 
     *pam_status = pam_end(pamh, *pam_status | PAM_DATA_SILENT);
+    pamh = NULL;
     return *pam_status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE;
 }
 
@@ -206,11 +206,20 @@ int
 pam_begin_session(pw)
     struct passwd *pw;
 {
-    int status =  PAM_SUCCESS;
+    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);
+    /*
+     * 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;
+    }
 
     /*
      * Update PAM_USER to reference the user we are running the command
@@ -230,25 +239,35 @@ pam_begin_session(pw)
 
 #ifndef NO_PAM_SESSION
     status = pam_open_session(pamh, 0);
-     if (status != PAM_SUCCESS) {
+    if (status != PAM_SUCCESS) {
        (void) pam_end(pamh, status | PAM_DATA_SILENT);
        pamh = NULL;
     }
 #endif
+
+done:
     return status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE;
 }
 
 int
-pam_end_session()
+pam_end_session(pw)
+    struct passwd *pw;
 {
     int status = PAM_SUCCESS;
 
     if (pamh != NULL) {
 #ifndef NO_PAM_SESSION
-       (void) pam_close_session(pamh, 0);
+       /*
+        * Update PAM_USER to reference the user we are running the command
+        * as to match the call to pam_open_session().
+        */
+       (void) pam_set_item(pamh, PAM_USER, pw->pw_name);
+       (void) pam_close_session(pamh, PAM_SILENT);
 #endif
        status = pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT);
+       pamh = NULL;
     }
+
     return status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE;
 }
 
index 8835c0363c96529c1a24fec428186218b8912b92..0cee8a3035a07204e4f545c64b59077c5f367feb 100644 (file)
@@ -50,9 +50,8 @@
 #define HAS_AGEINFO(p, l)      (l == 18 && p[DESLEN] == ',')
 
 int
-passwd_init(pw, promptp, auth)
+passwd_init(pw, auth)
     struct passwd *pw;
-    char **promptp;
     sudo_auth *auth;
 {
 #ifdef HAVE_SKEYACCESS
index c1c43d04cf8cfd331df7032b83a5ee21701e12c1..57a032f71cb430b11941fb2a0bb7d4ca38a9a0c1 100644 (file)
@@ -53,9 +53,8 @@
 #include "sudo_auth.h"
 
 int
-secureware_init(pw, promptp, auth)
+secureware_init(pw, auth)
     struct passwd *pw;
-    char **promptp;
     sudo_auth *auth;
 {
 #ifdef __alpha
index 83ff94c139aa2dd8615e76579081171f90920dad..ceaddc6722814bb2808269742eed91b270a032e1 100644 (file)
@@ -56,9 +56,8 @@
 union config_record configure;
 
 int
-securid_init(pw, promptp, auth)
+securid_init(pw, auth)
     struct passwd *pw;
-    char **promptp;
     sudo_auth *auth;
 {
     static struct SD_CLIENT sd_dat;            /* SecurID data block */
index 6880c1a1d79b90df833401767897da50ad3b55a4..7ec7dcdf8ec008c88d1f7da16078b67a2b4262ca 100644 (file)
@@ -59,7 +59,6 @@
  * securid_init - Initialises communications with ACE server
  * Arguments in:
  *     pw - UNUSED
- *     promptp - UNUSED
  *     auth - sudo authentication structure
  *
  * Results out:
@@ -68,9 +67,8 @@
  *                   success.
  */
 int
-securid_init(pw, promptp, auth)
+securid_init(pw, auth)
     struct passwd *pw;
-    char **promptp;
     sudo_auth *auth;
 {
     static SDI_HANDLE sd_dat;                  /* SecurID handle */
index 42455ee31640ae8343e9d3f32594b1d29b3548a1..6885f0fa098c7a11b2a2e342b5a4febeebe097f9 100644 (file)
@@ -68,7 +68,7 @@ sudo_auth auth_switch[] = {
     AUTH_ENTRY(0, "kerb4", kerb4_init, NULL, kerb4_verify, NULL)
 #  endif
 #  ifdef HAVE_KERB5
-    AUTH_ENTRY(0, "kerb5", kerb5_init, NULL, kerb5_verify, kerb5_cleanup)
+    AUTH_ENTRY(0, "kerb5", kerb5_init, kerb5_setup, kerb5_verify, kerb5_cleanup)
 #  endif
 #  ifdef HAVE_SKEY
     AUTH_ENTRY(0, "S/Key", NULL, rfc1938_setup, rfc1938_verify, NULL)
@@ -80,6 +80,71 @@ sudo_auth auth_switch[] = {
     AUTH_ENTRY(0, NULL, NULL, NULL, NULL, NULL)
 };
 
+void
+sudo_auth_init(pw)
+    struct passwd *pw;
+{
+    sudo_auth *auth;
+    int status;
+
+    if (auth_switch[0].name == NULL)
+       return;
+
+    /* Set FLAG_ONEANDONLY if there is only one auth method. */
+    if (auth_switch[1].name == NULL)
+       SET(auth_switch[0].flags, FLAG_ONEANDONLY);
+
+    /* Initialize auth methods and unconfigure the method if necessary. */
+    for (auth = auth_switch; auth->name; auth++) {
+       if (auth->init && IS_CONFIGURED(auth)) {
+           if (NEEDS_USER(auth))
+               set_perms(PERM_USER);
+
+           status = (auth->init)(pw, auth);
+
+           if (NEEDS_USER(auth))
+               set_perms(PERM_ROOT);
+
+           if (status == AUTH_FAILURE)
+               CLR(auth->flags, FLAG_CONFIGURED);
+           else if (status == AUTH_FATAL) {    /* XXX log */
+#ifdef HAVE_BSM_AUDIT
+               audit_failure(NewArgv, "authentication failure");
+#endif
+               exit(1);                /* assume error msg already printed */
+           }
+       }
+    }
+}
+
+void
+sudo_auth_cleanup(pw)
+    struct passwd *pw;
+{
+    sudo_auth *auth;
+    int status;
+
+    /* Call cleanup routines. */
+    for (auth = auth_switch; auth->name; auth++) {
+       if (auth->cleanup && IS_CONFIGURED(auth)) {
+           if (NEEDS_USER(auth))
+               set_perms(PERM_USER);
+
+           status = (auth->cleanup)(pw, auth);
+
+           if (NEEDS_USER(auth))
+               set_perms(PERM_ROOT);
+
+           if (status == AUTH_FATAL) { /* XXX log */
+#ifdef HAVE_BSM_AUDIT
+               audit_failure(NewArgv, "authentication failure");
+#endif
+               exit(1);                /* assume error msg already printed */
+           }
+       }
+    }
+}
+
 void
 verify_user(pw, prompt)
     struct passwd *pw;
@@ -113,31 +178,6 @@ verify_user(pw, prompt)
            "--disable-authentication configure option.");
     }
 
-    /* Set FLAG_ONEANDONLY if there is only one auth method. */
-    if (auth_switch[1].name == NULL)
-       SET(auth_switch[0].flags, FLAG_ONEANDONLY);
-
-    /* Initialize auth methods and unconfigure the method if necessary. */
-    for (auth = auth_switch; auth->name; auth++) {
-       if (auth->init && IS_CONFIGURED(auth)) {
-           if (NEEDS_USER(auth))
-               set_perms(PERM_USER);
-
-           status = (auth->init)(pw, &prompt, auth);
-           if (status == AUTH_FAILURE)
-               CLR(auth->flags, FLAG_CONFIGURED);
-           else if (status == AUTH_FATAL) {    /* XXX log */
-#ifdef HAVE_BSM_AUDIT
-               audit_failure(NewArgv, "authentication failure");
-#endif
-               exit(1);                /* assume error msg already printed */
-           }
-
-           if (NEEDS_USER(auth))
-               set_perms(PERM_ROOT);
-       }
-    }
-
     while (--counter) {
        /* Do any per-method setup and unconfigure the method if needed */
        for (auth = auth_switch; auth->name; auth++) {
@@ -146,6 +186,10 @@ verify_user(pw, prompt)
                    set_perms(PERM_USER);
 
                status = (auth->setup)(pw, &prompt, auth);
+
+               if (NEEDS_USER(auth))
+                   set_perms(PERM_ROOT);
+
                if (status == AUTH_FAILURE)
                    CLR(auth->flags, FLAG_CONFIGURED);
                else if (status == AUTH_FATAL) {/* XXX log */
@@ -154,9 +198,6 @@ verify_user(pw, prompt)
 #endif
                    exit(1);            /* assume error msg already printed */
                }
-
-               if (NEEDS_USER(auth))
-                   set_perms(PERM_ROOT);
            }
        }
 
@@ -182,7 +223,7 @@ verify_user(pw, prompt)
                set_perms(PERM_ROOT);
 
            if (auth->status != AUTH_FAILURE)
-               goto cleanup;
+               goto done;
        }
 #ifndef AUTH_STANDALONE
        if (p == NULL)
@@ -193,26 +234,7 @@ verify_user(pw, prompt)
            pass_warn(stderr);
     }
 
-cleanup:
-    /* Call cleanup routines. */
-    for (auth = auth_switch; auth->name; auth++) {
-       if (auth->cleanup && IS_CONFIGURED(auth)) {
-           if (NEEDS_USER(auth))
-               set_perms(PERM_USER);
-
-           status = (auth->cleanup)(pw, auth);
-           if (status == AUTH_FATAL) { /* XXX log */
-#ifdef HAVE_BSM_AUDIT
-               audit_failure(NewArgv, "authentication failure");
-#endif
-               exit(1);                /* assume error msg already printed */
-           }
-
-           if (NEEDS_USER(auth))
-               set_perms(PERM_ROOT);
-       }
-    }
-
+done:
     switch (success) {
        case AUTH_SUCCESS:
            (void) sigaction(SIGTSTP, &osa, NULL);
index 50249552b597be3fa75e5330e3ed47fbb52abfbd..f75212503c2b9202c6bf99d8de185d4f862f0656 100644 (file)
@@ -28,7 +28,7 @@ typedef struct sudo_auth {
     short status;              /* status from verify routine */
     char *name;                        /* name of the method as a string */
     void *data;                        /* method-specific data pointer */
-    int (*init) __P((struct passwd *pw, char **prompt, struct sudo_auth *auth));
+    int (*init) __P((struct passwd *pw, struct sudo_auth *auth));
     int (*setup) __P((struct passwd *pw, char **prompt, struct sudo_auth *auth));
     int (*verify) __P((struct passwd *pw, char *p, struct sudo_auth *auth));
     int (*cleanup) __P((struct passwd *pw, struct sudo_auth *auth));
@@ -46,10 +46,10 @@ typedef struct sudo_auth {
 #define IS_ONEANDONLY(x)       ((x)->flags & FLAG_ONEANDONLY)
 
 /* Prototypes for standalone methods */
-int fwtk_init __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+int fwtk_init __P((struct passwd *pw, sudo_auth *auth));
 int fwtk_verify __P((struct passwd *pw, char *prompt, sudo_auth *auth));
 int fwtk_cleanup __P((struct passwd *pw, sudo_auth *auth));
-int pam_init __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+int pam_init __P((struct passwd *pw, sudo_auth *auth));
 int pam_verify __P((struct passwd *pw, char *prompt, sudo_auth *auth));
 int pam_cleanup __P((struct passwd *pw, sudo_auth *auth));
 int sia_setup __P((struct passwd *pw, char **prompt, sudo_auth *auth));
@@ -57,27 +57,28 @@ int sia_verify __P((struct passwd *pw, char *prompt, sudo_auth *auth));
 int sia_cleanup __P((struct passwd *pw, sudo_auth *auth));
 int aixauth_verify __P((struct passwd *pw, char *pass, sudo_auth *auth));
 int aixauth_cleanup __P((struct passwd *pw, sudo_auth *auth));
-int bsdauth_init __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+int bsdauth_init __P((struct passwd *pw, sudo_auth *auth));
 int bsdauth_verify __P((struct passwd *pw, char *prompt, sudo_auth *auth));
 int bsdauth_cleanup __P((struct passwd *pw, sudo_auth *auth));
 
 /* Prototypes for normal methods */
-int passwd_init __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+int passwd_init __P((struct passwd *pw, sudo_auth *auth));
 int passwd_verify __P((struct passwd *pw, char *pass, sudo_auth *auth));
 int passwd_cleanup __P((struct passwd *pw, sudo_auth *auth));
-int secureware_init __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+int secureware_init __P((struct passwd *pw, sudo_auth *auth));
 int secureware_verify __P((struct passwd *pw, char *pass, sudo_auth *auth));
 int secureware_cleanup __P((struct passwd *pw, sudo_auth *auth));
 int rfc1938_setup __P((struct passwd *pw, char **prompt, sudo_auth *auth));
 int rfc1938_verify __P((struct passwd *pw, char *pass, sudo_auth *auth));
 int afs_verify __P((struct passwd *pw, char *pass, sudo_auth *auth));
 int dce_verify __P((struct passwd *pw, char *pass, sudo_auth *auth));
-int kerb4_init __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+int kerb4_init __P((struct passwd *pw, sudo_auth *auth));
 int kerb4_verify __P((struct passwd *pw, char *pass, sudo_auth *auth));
-int kerb5_init __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+int kerb5_init __P((struct passwd *pw, sudo_auth *auth));
+int kerb5_setup __P((struct passwd *pw, char **prompt, sudo_auth *auth));
 int kerb5_verify __P((struct passwd *pw, char *pass, sudo_auth *auth));
 int kerb5_cleanup __P((struct passwd *pw, sudo_auth *auth));
-int securid_init __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+int securid_init __P((struct passwd *pw, sudo_auth *auth));
 int securid_setup __P((struct passwd *pw, char **prompt, sudo_auth *auth));
 int securid_verify __P((struct passwd *pw, char *pass, sudo_auth *auth));
 
diff --git a/check.c b/check.c
index 035d4b6bcf20785ed4d55e9983b1ecc6323cc2b7..c2cfa32520ffa7644c559053762583fa0d359ec4 100644 (file)
--- a/check.c
+++ b/check.c
@@ -101,6 +101,7 @@ check_user(validated, mode)
     int validated;
     int mode;
 {
+    struct passwd *auth_pw;
     char *timestampdir = NULL;
     char *timestampfile = NULL;
     char *prompt;
@@ -116,6 +117,10 @@ check_user(validated, mode)
            ctim_get(&sb, &tty_info.ctime);
     }
 
+    /* Init authentication system regardless of whether we need a password. */
+    auth_pw = get_authpw();
+    sudo_auth_init(auth_pw);
+
     /* Always prompt for a password when -k was specified with the command. */
     if (ISSET(mode, MODE_INVALIDATE)) {
        SET(validated, FLAG_CHECK_USER);
@@ -127,7 +132,7 @@ check_user(validated, mode)
        if (user_uid == 0 || (user_uid == runas_pw->pw_uid &&
            (!runas_gr || user_in_group(sudo_user.pw, runas_gr->gr_name))) ||
            user_is_exempt())
-           return;
+           goto done;
     }
 
     build_timestamp(&timestampdir, &timestampfile);
@@ -135,8 +140,6 @@ check_user(validated, mode)
        TS_MAKE_DIRS);
 
     if (status != TS_CURRENT || ISSET(validated, FLAG_CHECK_USER)) {
-       struct passwd *auth_pw;
-
        /* Bail out if we are non-interactive and a password is required */
        if (ISSET(mode, MODE_NONINTERACTIVE))
            errorx(1, "sorry, a password is required to run %s", getprogname());
@@ -165,15 +168,17 @@ check_user(validated, mode)
        prompt = expand_prompt(user_prompt ? user_prompt : def_passprompt,
            user_name, user_shost);
 
-       auth_pw = get_authpw();
        verify_user(auth_pw, prompt);
-       pw_delref(auth_pw);
     }
     /* Only update timestamp if user was validated. */
     if (ISSET(validated, VALIDATE_OK) && !ISSET(mode, MODE_INVALIDATE) && status != TS_ERROR)
        update_timestamp(timestampdir, timestampfile);
     efree(timestampdir);
     efree(timestampfile);
+
+done:
+    sudo_auth_cleanup(auth_pw);
+    pw_delref(auth_pw);
 }
 
 /*
diff --git a/sudo.c b/sudo.c
index 6f7e054817642b385a8794a2a98b23cfd022cde4..f494a61e2d17e4d0006ab0d3fd1b154a785f5456 100644 (file)
--- a/sudo.c
+++ b/sudo.c
@@ -968,7 +968,7 @@ run_command(path, argv, envp, uid, dowait)
        break;
     }
 #ifdef HAVE_PAM
-    pam_end_session();
+    pam_end_session(runas_pw);
 #endif /* HAVE_PAM */
 #ifdef _PATH_SUDO_IO_LOGDIR
     io_log_close();
diff --git a/sudo.h b/sudo.h
index acd23633b4c42b595778db435b7bf2c775969581..bbb80ac232a7ac4cb766b14daa18cf066b62f4dc 100644 (file)
--- a/sudo.h
+++ b/sudo.h
@@ -270,7 +270,7 @@ void io_nextid __P((void));
 
 /* pam.c */
 int pam_begin_session  __P((struct passwd *));
-int pam_end_session    __P((void));
+int pam_end_session    __P((struct passwd *));
 
 /* parse.c */
 int sudo_file_open     __P((struct sudo_nss *));
@@ -328,6 +328,8 @@ void set_fqdn               __P((void));
 void verify_user       __P((struct passwd *, char *));
 void pass_warn         __P((FILE *));
 void dump_auth_methods __P((void));
+void sudo_auth_init    __P((struct passwd *));
+void sudo_auth_cleanup __P((struct passwd *));
 
 /* sudo_nss.c */
 void display_privs     __P((struct sudo_nss_list *, struct passwd *));