summaryrefslogtreecommitdiff
path: root/source3/nsswitch/winbindd_pam.c
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2004-01-05 04:10:28 +0000
committerAndrew Bartlett <abartlet@samba.org>2004-01-05 04:10:28 +0000
commita7f8c26d24b78dc6a0f829cf7b53112e5ddbdeda (patch)
tree7452bffcb646e5c1fb4c02d43b61645733c5c97e /source3/nsswitch/winbindd_pam.c
parent72de1cd0f7701cb0b66c4eebc0c103a6b62c1cd7 (diff)
downloadsamba-a7f8c26d24b78dc6a0f829cf7b53112e5ddbdeda.tar.gz
samba-a7f8c26d24b78dc6a0f829cf7b53112e5ddbdeda.tar.bz2
samba-a7f8c26d24b78dc6a0f829cf7b53112e5ddbdeda.zip
Change our Domain controller lookup routines to more carefully seperate
DNS names (realms) from NetBIOS domain names. Until now, we would experience delays as we broadcast lookups for DNS names onto the local network segments. Now if DNS comes back negative, we fall straight back to looking up the short name. Andrew Bartlett (This used to be commit 32397c8b01f1dec7b05140d210bb32f836a80ca6)
Diffstat (limited to 'source3/nsswitch/winbindd_pam.c')
-rw-r--r--source3/nsswitch/winbindd_pam.c118
1 files changed, 73 insertions, 45 deletions
diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c
index 54513b1bc1..196ceea9a0 100644
--- a/source3/nsswitch/winbindd_pam.c
+++ b/source3/nsswitch/winbindd_pam.c
@@ -75,7 +75,7 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state)
int attempts = 0;
unsigned char local_lm_response[24];
unsigned char local_nt_response[24];
- const char *contact_domain;
+ struct winbindd_domain *contact_domain;
BOOL retry;
/* Ensure null termination */
@@ -107,21 +107,15 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state)
lm_resp = data_blob_talloc(mem_ctx, local_lm_response, sizeof(local_lm_response));
nt_resp = data_blob_talloc(mem_ctx, local_nt_response, sizeof(local_nt_response));
- if ( !get_trust_pw(name_domain, trust_passwd, &last_change_time, &sec_channel_type) ) {
- result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
- goto done;
- }
-
/* what domain should we contact? */
if ( IS_DC ) {
- if (!find_domain_from_name(name_domain)) {
- DEBUG(3, ("Cannot change password for [%s] -> [%s]\\[%s] as %s is not a trusted domain\n",
+ if (!(contact_domain = find_domain_from_name(name_domain))) {
+ DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n",
state->request.data.auth.user, name_domain, name_user, name_domain));
result = NT_STATUS_NO_SUCH_USER;
goto done;
}
- contact_domain = name_domain;
} else {
if (is_myname(name_domain)) {
@@ -129,8 +123,20 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state)
result = NT_STATUS_NO_SUCH_USER;
goto done;
}
- contact_domain = lp_workgroup();
+
+ if (!(contact_domain = find_our_domain())) {
+ DEBUG(1, ("Authenticatoin for [%s] -> [%s]\\[%s] in our domain failed - we can't find our domain!\n",
+ state->request.data.auth.user, name_domain, name_user));
+ result = NT_STATUS_NO_SUCH_USER;
+ goto done;
+ }
+ }
+
+ if ( !get_trust_pw(contact_domain->name, trust_passwd, &last_change_time, &sec_channel_type) ) {
+ result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+ goto done;
}
+
/* check authentication loop */
do {
@@ -194,7 +200,10 @@ done:
state->response.data.auth.nt_status = NT_STATUS_V(result);
fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result));
- fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result));
+
+ /* we might have given a more useful error above */
+ if (!*state->response.data.auth.error_string)
+ fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result));
state->response.data.auth.pam_error = nt_status_to_pam(result);
DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Plain-text authentication for user %s returned %s (PAM: %d)\n",
@@ -221,10 +230,10 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
NET_USER_INFO_3 info3;
struct cli_state *cli = NULL;
TALLOC_CTX *mem_ctx = NULL;
- char *user = NULL;
- const char *domain = NULL;
+ char *name_user = NULL;
+ const char *name_domain = NULL;
const char *workstation;
- const char *contact_domain;
+ struct winbindd_domain *contact_domain;
DOM_CRED ret_creds;
int attempts = 0;
BOOL retry;
@@ -255,7 +264,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
goto done;
}
- if (pull_utf8_talloc(mem_ctx, &user, state->request.data.auth_crap.user) == (size_t)-1) {
+ if (pull_utf8_talloc(mem_ctx, &name_user, state->request.data.auth_crap.user) == (size_t)-1) {
DEBUG(0, ("winbindd_pam_auth_crap: pull_utf8_talloc failed!\n"));
result = NT_STATUS_UNSUCCESSFUL;
goto done;
@@ -268,24 +277,19 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
result = NT_STATUS_UNSUCCESSFUL;
goto done;
}
- domain = dom;
+ name_domain = dom;
} else if (lp_winbind_use_default_domain()) {
- domain = lp_workgroup();
+ name_domain = lp_workgroup();
} else {
DEBUG(5,("no domain specified with username (%s) - failing auth\n",
- user));
- result = NT_STATUS_INVALID_PARAMETER;
+ name_user));
+ result = NT_STATUS_NO_SUCH_USER;
goto done;
}
DEBUG(3, ("[%5lu]: pam auth crap domain: %s user: %s\n", (unsigned long)state->pid,
- domain, user));
+ name_domain, name_user));
- if ( !get_trust_pw(domain, trust_passwd, &last_change_time, &sec_channel_type) ) {
- result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
- goto done;
- }
-
if (*state->request.data.auth_crap.workstation) {
char *wrk = NULL;
if (pull_utf8_talloc(mem_ctx, &wrk, state->request.data.auth_crap.workstation) == (size_t)-1) {
@@ -312,23 +316,37 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
/* what domain should we contact? */
+
+ /* what domain should we contact? */
+
if ( IS_DC ) {
- if (!find_domain_from_name(domain)) {
- DEBUG(3, ("Cannot change password for [%s] -> [%s]\\[%s] as %s is not a trusted domain\n",
- state->request.data.auth.user, domain, user, domain));
+ if (!(contact_domain = find_domain_from_name(name_domain))) {
+ DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n",
+ state->request.data.auth.user, name_domain, name_user, name_domain));
result = NT_STATUS_NO_SUCH_USER;
goto done;
}
- contact_domain = domain;
+
} else {
- if (is_myname(domain)) {
- DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", domain));
+ if (is_myname(name_domain)) {
+ DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", name_domain));
result = NT_STATUS_NO_SUCH_USER;
goto done;
}
- contact_domain = lp_workgroup();
+
+ if (!(contact_domain = find_our_domain())) {
+ DEBUG(1, ("Authenticatoin for [%s] -> [%s]\\[%s] in our domain failed - we can't find our domain!\n",
+ state->request.data.auth.user, name_domain, name_user));
+ result = NT_STATUS_NO_SUCH_USER;
+ goto done;
+ }
}
+ if ( !get_trust_pw(contact_domain->name, trust_passwd, &last_change_time, &sec_channel_type) ) {
+ result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+ goto done;
+ }
+
do {
ZERO_STRUCT(info3);
ZERO_STRUCT(ret_creds);
@@ -345,7 +363,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
result = cli_netlogon_sam_network_logon(cli, mem_ctx,
&ret_creds,
- user, domain,
+ name_user, name_domain,
workstation,
state->request.data.auth_crap.chal,
lm_resp, nt_resp,
@@ -369,7 +387,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
if ( NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED) ) {
DEBUG(3,("winbindd_pam_auth_crap: sam_logon returned ACCESS_DENIED. Maybe the trust account "
"password was changed and we didn't know it. Killing connections to domain %s\n",
- domain));
+ contact_domain->name));
winbindd_cm_flush();
retry = True;
cli = NULL;
@@ -381,7 +399,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
if (NT_STATUS_IS_OK(result)) {
netsamlogon_cache_store( cli->mem_ctx, &info3 );
- wcache_invalidate_samlogon(find_domain_from_name(domain), &info3);
+ wcache_invalidate_samlogon(find_domain_from_name(name_domain), &info3);
if (state->request.flags & WBFLAG_PAM_INFO3_NDR) {
result = append_info3_as_ndr(mem_ctx, state, &info3);
@@ -393,12 +411,12 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
const char *nt_username, *nt_domain;
if (!(nt_username = unistr2_tdup(mem_ctx, &(info3.uni_user_name)))) {
/* If the server didn't give us one, just use the one we sent them */
- nt_username = user;
+ nt_username = name_user;
}
if (!(nt_domain = unistr2_tdup(mem_ctx, &(info3.uni_logon_dom)))) {
/* If the server didn't give us one, just use the one we sent them */
- nt_domain = domain;
+ nt_domain = name_domain;
}
fill_domain_username(username_out, nt_domain, nt_username);
@@ -437,8 +455,8 @@ done:
DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2,
("NTLM CRAP authentication for user [%s]\\[%s] returned %s (PAM: %d)\n",
- domain,
- user,
+ name_domain,
+ name_user,
state->response.data.auth.nt_status_string,
state->response.data.auth.pam_error));
@@ -456,10 +474,19 @@ enum winbindd_result winbindd_pam_chauthtok(struct winbindd_cli_state *state)
char *oldpass, *newpass;
fstring domain, user;
CLI_POLICY_HND *hnd;
+ TALLOC_CTX *mem_ctx;
+ struct winbindd_domain *contact_domain;
DEBUG(3, ("[%5lu]: pam chauthtok %s\n", (unsigned long)state->pid,
state->request.data.chauthtok.user));
+ if (!(mem_ctx = talloc_init("winbind password change for (utf8) %s",
+ state->request.data.chauthtok.user))) {
+ DEBUG(0, ("winbindd_pam_auth_crap: could not talloc_init()!\n"));
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
/* Setup crap */
if (state == NULL)
@@ -467,7 +494,7 @@ enum winbindd_result winbindd_pam_chauthtok(struct winbindd_cli_state *state)
parse_domain_user(state->request.data.chauthtok.user, domain, user);
- if (!find_domain_from_name(domain)) {
+ if (!(contact_domain = find_domain_from_name(domain))) {
DEBUG(3, ("Cannot change password for [%s] -> [%s]\\[%s] as %s is not a trusted domain\n",
state->request.data.chauthtok.user, domain, user, domain));
result = NT_STATUS_NO_SUCH_USER;
@@ -481,17 +508,15 @@ enum winbindd_result winbindd_pam_chauthtok(struct winbindd_cli_state *state)
/* Get sam handle */
- if ( NT_STATUS_IS_ERR(result = cm_get_sam_handle(domain, &hnd)) ) {
+ if ( NT_STATUS_IS_ERR(result = cm_get_sam_handle(contact_domain, &hnd)) ) {
DEBUG(1, ("could not get SAM handle on DC for %s\n", domain));
goto done;
}
- if (!cli_oem_change_password(hnd->cli, user, newpass, oldpass)) {
+ if (!NT_STATUS_IS_OK(result = cli_samr_chgpasswd_user(hnd->cli, mem_ctx,
+ user, newpass, oldpass))) {
DEBUG(1, ("password change failed for user %s/%s\n", domain,
user));
- result = NT_STATUS_WRONG_PASSWORD;
- } else {
- result = NT_STATUS_OK;
}
done:
@@ -507,5 +532,8 @@ done:
state->response.data.auth.nt_status_string,
state->response.data.auth.pam_error));
+ if (mem_ctx)
+ talloc_destroy(mem_ctx);
+
return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
}