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)
* 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)
}
/* 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 */
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.
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;
/* 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);
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;
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;
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));