From f0ed0440c4d3b8736eb5e1ceba8b9257eb29cee3 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 13 Feb 2006 15:12:22 +0000 Subject: r13492: As noone objected on the mailing-list: 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 | 47 +++++++++++++++++++++++++++++++++++---- source3/nsswitch/winbindd_group.c | 2 +- source3/nsswitch/winbindd_pam.c | 13 +++++++++-- source3/nsswitch/winbindd_user.c | 2 +- source3/nsswitch/winbindd_util.c | 9 ++++---- 5 files changed, 61 insertions(+), 12 deletions(-) (limited to 'source3/nsswitch') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 3848612c47..35f0efbcbd 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -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. diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c index a328cebac4..1ddc734703 100644 --- a/source3/nsswitch/winbindd_group.c +++ b/source3/nsswitch/winbindd_group.c @@ -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; diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c index 5f84d138e6..47b8d7bbd5 100644 --- a/source3/nsswitch/winbindd_pam.c +++ b/source3/nsswitch/winbindd_pam.c @@ -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); diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c index 9670bf534c..227163b447 100644 --- a/source3/nsswitch/winbindd_user.c +++ b/source3/nsswitch/winbindd_user.c @@ -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; diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c index b92ee0de82..349ca21652 100644 --- a/source3/nsswitch/winbindd_util.c +++ b/source3/nsswitch/winbindd_util.c @@ -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)); -- cgit