r21887: Fix annoying bug where in a pam_close_session (or a pam_setcred with the
authorGünther Deschner <gd@samba.org>
Tue, 20 Mar 2007 12:44:40 +0000 (12:44 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:18:44 +0000 (12:18 -0500)
PAM_DELETE_CREDS flag set) any user could delete krb5 credential caches.
Make sure that only root can do this.

Jerry, Jeremy, please check.

Guenther

source/nsswitch/winbindd_pam.c

index 6fdead59821db65ac5ed0ef61464a443f48d106e..6ee548292ccf6d2342e3c47db4c2f0ddc735546b 100644 (file)
@@ -2092,7 +2092,9 @@ void winbindd_pam_logoff(struct winbindd_cli_state *state)
 {
        struct winbindd_domain *domain;
        fstring name_domain, user;
-       
+       uid_t caller_uid = (uid_t)-1;
+       uid_t request_uid = state->request.data.logoff.uid;
+
        DEBUG(3, ("[%5lu]: pam logoff %s\n", (unsigned long)state->pid,
                state->request.data.logoff.user));
 
@@ -2103,6 +2105,10 @@ void winbindd_pam_logoff(struct winbindd_cli_state *state)
        state->request.data.logoff.krb5ccname
                [sizeof(state->request.data.logoff.krb5ccname)-1]='\0';
 
+       if (request_uid == (gid_t)-1) {
+               goto failed;
+       }
+
        if (!canonicalize_username(state->request.data.logoff.user, name_domain, user)) {
                goto failed;
        }
@@ -2111,6 +2117,28 @@ void winbindd_pam_logoff(struct winbindd_cli_state *state)
                goto failed;
        }
 
+       if ((sys_getpeereid(state->sock, &caller_uid)) != 0) {
+               DEBUG(1,("winbindd_pam_logoff: failed to check peerid: %s\n", 
+                       strerror(errno)));
+               goto failed;
+       }
+
+       switch (caller_uid) {
+               case -1:
+                       goto failed;
+               case 0:
+                       /* root must be able to logoff any user - gd */
+                       state->request.data.logoff.uid = request_uid;
+                       break;
+               default:
+                       if (caller_uid != request_uid) {
+                               DEBUG(1,("winbindd_pam_logoff: caller requested invalid uid\n"));
+                               goto failed;
+                       }
+                       state->request.data.logoff.uid = caller_uid;
+                       break;
+       }
+
        sendto_domain(state, domain);
        return;