diff options
author | Andrew Bartlett <abartlet@samba.org> | 2002-07-31 12:05:30 +0000 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2002-07-31 12:05:30 +0000 |
commit | 2d67a683b735d50f411a4bee9ee5ec17e9a60015 (patch) | |
tree | c63912f150f6bf879f1690a0c1f101554cee17a8 /source3/nsswitch/winbindd_pam.c | |
parent | 2307a6f50469b08054fad714ede98ca86fe30dcf (diff) | |
download | samba-2d67a683b735d50f411a4bee9ee5ec17e9a60015.tar.gz samba-2d67a683b735d50f411a4bee9ee5ec17e9a60015.tar.bz2 samba-2d67a683b735d50f411a4bee9ee5ec17e9a60015.zip |
Winbind updates!
This updates the 'winbind' authentication module and winbind's 'PAM' (actually
netlogon) code to allow smbd to cache connections to the DC.
This is particulary relevent when we need mutex locks already - there is no
parallelism to be gained anyway.
The winbind code authenticates the user, and if successful, passes back the
'info3' struct describing the user. smbd then interprets that in exactly the
same way as an 'ntdomain' logon.
Also, add parinoia to winbind about null termination.
Andrew Bartlett
(This used to be commit 167f122b670d4ef67d78e6f79a2bae3f6e8d67df)
Diffstat (limited to 'source3/nsswitch/winbindd_pam.c')
-rw-r--r-- | source3/nsswitch/winbindd_pam.c | 135 |
1 files changed, 107 insertions, 28 deletions
diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c index a73b2ccd29..a8b508a49c 100644 --- a/source3/nsswitch/winbindd_pam.c +++ b/source3/nsswitch/winbindd_pam.c @@ -23,17 +23,41 @@ */ #include "winbindd.h" - #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND + +static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx, + struct winbindd_cli_state *state, + NET_USER_INFO_3 *info3) +{ + prs_struct ps; + uint32 size; + if (!prs_init(&ps, 256 /* Random, non-zero number */, mem_ctx, MARSHALL)) { + return NT_STATUS_NO_MEMORY; + } + if (!net_io_user_info3("", info3, &ps, 1, 3)) { + prs_mem_free(&ps); + return NT_STATUS_UNSUCCESSFUL; + } + + size = prs_data_size(&ps); + state->response.extra_data = memdup(prs_data_p(&ps), size); + if (!state->response.extra_data) { + prs_mem_free(&ps); + return NT_STATUS_NO_MEMORY; + } + state->response.length += size; + prs_mem_free(&ps); + return NT_STATUS_OK; +} + /* Return a password structure from a username. */ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) { NTSTATUS result; fstring name_domain, name_user; - int passlen; unsigned char trust_passwd[16]; time_t last_change_time; uint32 smb_uid_low; @@ -46,6 +70,12 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) extern pstring global_myname; + /* Ensure null termination */ + state->request.data.auth.user[sizeof(state->request.data.auth.user)-1]='\0'; + + /* Ensure null termination */ + state->request.data.auth.pass[sizeof(state->request.data.auth.pass)-1]='\0'; + DEBUG(3, ("[%5d]: pam auth %s\n", state->pid, state->request.data.auth.user)); @@ -64,8 +94,6 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) goto done; } - passlen = strlen(state->request.data.auth.pass); - { unsigned char local_lm_response[24]; unsigned char local_nt_response[24]; @@ -140,34 +168,67 @@ 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; - const char *domain = NULL; + char *user = NULL; + char *domain = NULL; + char *contact_domain; + char *workstation; DATA_BLOB lm_resp, nt_resp; extern pstring global_myname; - DEBUG(3, ("[%5d]: pam auth crap domain: %s user: %s\n", state->pid, - state->request.data.auth_crap.domain, state->request.data.auth_crap.user)); + /* Ensure null termination */ + state->request.data.auth_crap.user[sizeof(state->request.data.auth_crap.user)-1]='\0'; + + /* Ensure null termination */ + state->request.data.auth_crap.domain[sizeof(state->request.data.auth_crap.domain)-1]='\0'; - if (!(mem_ctx = talloc_init_named("winbind pam auth crap for %s", state->request.data.auth.user))) { + if (!(mem_ctx = talloc_init_named("winbind pam auth crap for (utf8) %s", state->request.data.auth.user))) { DEBUG(0, ("winbindd_pam_auth_crap: could not talloc_init()!\n")); result = NT_STATUS_NO_MEMORY; goto done; } + if (pull_utf8_talloc(mem_ctx, &user, state->request.data.auth_crap.user) < 0) { + DEBUG(0, ("winbindd_pam_auth_crap: pull_utf8_talloc failed!\n")); + } + if (*state->request.data.auth_crap.domain) { - domain = talloc_strdup(mem_ctx, state->request.data.auth_crap.domain); + if (pull_utf8_talloc(mem_ctx, &domain, state->request.data.auth_crap.domain) < 0) { + DEBUG(0, ("winbindd_pam_auth_crap: pull_utf8_talloc failed!\n")); + } } else if (lp_winbind_use_default_domain()) { - domain = talloc_strdup(mem_ctx, lp_workgroup()); + domain = lp_workgroup(); } else { - DEBUG(5,("no domain specified with username (%s) - failing auth\n", state->request.data.auth.user)); + DEBUG(5,("no domain specified with username (%s) - failing auth\n", + user)); result = NT_STATUS_INVALID_PARAMETER; goto done; } - if (!domain) { - DEBUG(0,("winbindd_pam_auth_crap: talloc_strdup failed!\n")); - result = NT_STATUS_NO_MEMORY; + DEBUG(3, ("[%5d]: pam auth crap domain: %s user: %s\n", state->pid, + domain, user)); + + if (lp_allow_trusted_domains() && (state->request.data.auth_crap.flags & WINBIND_PAM_CONTACT_TRUSTDOM)) { + contact_domain = domain; + } else { + contact_domain = lp_workgroup(); + } + + if (*state->request.data.auth_crap.workstation) { + if (pull_utf8_talloc(mem_ctx, &workstation, state->request.data.auth_crap.workstation) < 0) { + DEBUG(0, ("winbindd_pam_auth_crap: pull_utf8_talloc failed!\n")); + } + } else { + workstation = global_myname; + } + + if (state->request.data.auth_crap.lm_resp_len > sizeof(state->request.data.auth_crap.lm_resp) + || state->request.data.auth_crap.nt_resp_len > sizeof(state->request.data.auth_crap.nt_resp)) { + DEBUG(0, ("winbindd_pam_auth_crap: invalid password length %u/%u\n", + state->request.data.auth_crap.lm_resp_len, + state->request.data.auth_crap.nt_resp_len)); + result = NT_STATUS_INVALID_PARAMETER; goto done; } @@ -175,13 +236,15 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) nt_resp = data_blob_talloc(mem_ctx, state->request.data.auth_crap.nt_resp, state->request.data.auth_crap.nt_resp_len); /* - * Get the machine account password for our primary domain + * Get the machine account password for the domain to contact. + * This is either our own domain for a workstation, or possibly + * any domain for a PDC with trusted domains. */ - if (!secrets_fetch_trust_account_password( - lp_workgroup(), trust_passwd, &last_change_time)) { + if (!secrets_fetch_trust_account_password ( + contact_domain, trust_passwd, &last_change_time)) { DEBUG(0, ("winbindd_pam_auth: could not fetch trust account " - "password for domain %s\n", lp_workgroup())); + "password for domain %s\n", contact_domain)); result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; goto done; } @@ -189,7 +252,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) ZERO_STRUCT(info3); /* Don't shut this down - it belongs to the connection cache code */ - result = cm_get_netlogon_cli(lp_workgroup(), trust_passwd, &cli); + result = cm_get_netlogon_cli(contact_domain, trust_passwd, &cli); if (!NT_STATUS_IS_OK(result)) { DEBUG(3, ("could not open handle to NETLOGON pipe (error: %s)\n", nt_errstr(result))); @@ -197,27 +260,43 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) } result = cli_netlogon_sam_network_logon(cli, mem_ctx, - state->request.data.auth_crap.user, domain, - global_myname, state->request.data.auth_crap.chal, + user, domain, + workstation, state->request.data.auth_crap.chal, lm_resp, nt_resp, &info3); if (NT_STATUS_IS_OK(result)) { uni_group_cache_store_netlogon(mem_ctx, &info3); + if (state->request.data.auth_crap.flags & WINBIND_PAM_INFO3_NDR) { + result = append_info3_as_ndr(mem_ctx, state, &info3); + } + +#if 0 + /* we don't currently do this stuff right */ + if (state->request.data.auth_crap.flags & WINBIND_PAM_NTKEY) { + SMB_ASSERT(sizeof(state->response.data.auth.nt_session_key) == sizeof(info3.user_sess_key)); + memcpy(state->response.data.auth.nt_session_key, info3.user_sess_key, sizeof(state->response.data.auth.nt_session_key) /* 16 */); + } + if (state->request.data.auth_crap.flags & WINBIND_PAM_LMKEY) { + SMB_ASSERT(sizeof(state->response.data.auth.nt_session_key) <= sizeof(info3.user_sess_key)); + memcpy(state->response.data.auth.first_8_lm_hash, info3.padding, sizeof(state->response.data.auth.nt_session_key) /* 16 */); + } +#endif } 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, nt_errstr(result)); + push_utf8_fstring(state->response.data.auth.nt_status_string, nt_errstr(result)); + push_utf8_fstring(state->response.data.auth.error_string, nt_errstr(result)); state->response.data.auth.pam_error = nt_status_to_pam(result); - DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("NTLM CRAP authenticaion for user [%s]\\[%s] returned %s (PAM: %d)\n", - state->request.data.auth_crap.domain, - state->request.data.auth_crap.user, - state->response.data.auth.nt_status_string, - state->response.data.auth.pam_error)); + DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, + ("NTLM CRAP authenticaion for user [%s]\\[%s] returned %s (PAM: %d)\n", + domain, + user, + state->response.data.auth.nt_status_string, + state->response.data.auth.pam_error)); if (mem_ctx) talloc_destroy(mem_ctx); |