r13492: As noone objected on the mailing-list:
authorGünther Deschner <gd@samba.org>
Mon, 13 Feb 2006 15:12:22 +0000 (15:12 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:10:06 +0000 (11:10 -0500)
Fix parse_domain_user to fail when splitting a full name like "DOM\user"
when "winbind use default domain" and "winbind trusted domains only" are
not enabled.

This allows pam_winbind to behave correctly when more modules are
stacked in the "account" or "password" PAM facility. pam_winbindd calls
WINBINDD_GETPWNAM which can decide whether or not a user is a winbind
user and return correct PAM error codes.

Guenther
(This used to be commit e6d52c1e9d8cec7be6d552c2a67a392df21c3ec9)

source3/nsswitch/pam_winbind.c
source3/nsswitch/winbindd_group.c
source3/nsswitch/winbindd_pam.c
source3/nsswitch/winbindd_user.c
source3/nsswitch/winbindd_util.c

index 3848612c47d0a80f236b4d5a690020633d83eb77..35f0efbcbdfa6e52a043c4eff02b721474dc880c 100644 (file)
@@ -566,10 +566,38 @@ static int winbind_chauthtok_request(pam_handle_t * pamh,
  *      0  = OK
  *     -1  = System error
  */
-static int valid_user(const char *user)
+static int valid_user(const char *user, pam_handle_t *pamh, int ctrl)
 {
-       if (getpwnam(user)) return 0;
-       return 1;
+       /* check not only if the user is available over NSS calls, also make
+        * sure it's really a winbind user, this is important when stacking PAM
+        * modules in the 'account' or 'password' facility. */
+
+       struct passwd *pwd = NULL;
+       struct winbindd_request request;
+       struct winbindd_response response;
+       int ret;
+
+       ZERO_STRUCT(request);
+       ZERO_STRUCT(response);
+
+       pwd = getpwnam(user);
+       if (pwd == NULL) {
+               return 1;
+       }
+
+       fstrcpy(request.data.username, user);
+
+       ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_GETPWNAM, &request, &response, user);
+
+       switch (ret) {
+               case PAM_USER_UNKNOWN:
+                       return 1;
+               case PAM_SUCCESS:
+                       return 0;
+               default:
+                       break;
+       }
+       return -1;
 }
 
 static char *_pam_delete(register char *xx)
@@ -897,7 +925,7 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
        }
 
        /* Verify the username */
-       retval = valid_user(username);
+       retval = valid_user(username, pamh, ctrl);
        switch (retval) {
        case -1:
                /* some sort of system error. The log was already printed */
@@ -1123,6 +1151,17 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
                return retval;
        }
 
+       /* check if this is really a user in winbindd, not only in NSS */
+       retval = valid_user(user, pamh, ctrl);
+       switch (retval) {
+               case 1:
+                       return PAM_USER_UNKNOWN;
+               case -1:
+                       return PAM_SYSTEM_ERR;
+               default:
+                       break;
+       }
+               
        /*
         * obtain and verify the current password (OLDAUTHTOK) for
         * the user.
index a328cebac4f0fe3852a75cc73d1029aa83b21628..1ddc734703f4ebfeb8e16884c82027920694df22 100644 (file)
@@ -992,7 +992,7 @@ void winbindd_getgroups(struct winbindd_cli_state *state)
        if (!parse_domain_user_talloc(state->mem_ctx,
                                      state->request.data.username,
                                      &s->domname, &s->username)) {
-               DEBUG(0, ("Could not parse domain user: %s\n",
+               DEBUG(5, ("Could not parse domain user: %s\n",
                          state->request.data.username));
                request_error(state);
                return;
index 5f84d138e6d86fcedde3885d37d9c43d0449a5c7..47b8d7bbd597a39493c3ac72f7de0b34fa006e40 100644 (file)
@@ -633,8 +633,17 @@ void winbindd_pam_auth(struct winbindd_cli_state *state)
 
        /* Parse domain and username */
        
-       parse_domain_user(state->request.data.auth.user,
-                         name_domain, name_user);
+       if (!parse_domain_user(state->request.data.auth.user,
+                              name_domain, name_user)) {
+               set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER);
+               DEBUG(5, ("Plain text authentication for %s returned %s "
+                         "(PAM: %d)\n",
+                         state->request.data.auth.user, 
+                         state->response.data.auth.nt_status_string,
+                         state->response.data.auth.pam_error));
+               request_error(state);
+               return;
+       }
 
        domain = find_auth_domain(state, name_domain);
 
index 9670bf534cb9fc9356c8c93d9f7fae6dace602b3..227163b44720d71ccac4b422290387a2fcc0070a 100644 (file)
@@ -337,7 +337,7 @@ void winbindd_getpwnam(struct winbindd_cli_state *state)
 
        if (!parse_domain_user(state->request.data.username, domname,
                               username)) {
-               DEBUG(0, ("Could not parse domain user: %s\n",
+               DEBUG(5, ("Could not parse domain user: %s\n",
                          state->request.data.username));
                request_error(state);
                return;
index b92ee0de825f8a3c19116fcf13a248a3f457fa64..349ca21652b6f8a1e269adf4748cf6d4d0a73a40 100644 (file)
@@ -835,10 +835,9 @@ BOOL parse_domain_user(const char *domuser, fstring domain, fstring user)
                if ( assume_domain(lp_workgroup())) {
                        fstrcpy(domain, lp_workgroup());
                } else {
-                       fstrcpy( domain, get_global_sam_name() ); 
+                       return False;
                }
-       } 
-       else {
+       } else {
                fstrcpy(user, p+1);
                fstrcpy(domain, domuser);
                domain[PTR_DIFF(p, domuser)] = 0;
@@ -853,7 +852,9 @@ BOOL parse_domain_user_talloc(TALLOC_CTX *mem_ctx, const char *domuser,
                              char **domain, char **user)
 {
        fstring fstr_domain, fstr_user;
-       parse_domain_user(domuser, fstr_domain, fstr_user);
+       if (!parse_domain_user(domuser, fstr_domain, fstr_user)) {
+               return False;
+       }
        *domain = talloc_strdup(mem_ctx, fstr_domain);
        *user = talloc_strdup(mem_ctx, fstr_user);
        return ((*domain != NULL) && (*user != NULL));