From 49c857ffb8aab9a281a9bc945c5161b109cc8145 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 14 Mar 2008 11:07:55 +0100 Subject: [PATCH] compat_auth_plain dummy... --- source/winbindd/winbindd_pam.c | 247 ++++++++++++++++++++++++++++++++- 1 file changed, 246 insertions(+), 1 deletion(-) diff --git a/source/winbindd/winbindd_pam.c b/source/winbindd/winbindd_pam.c index dafe92f5973..9637d2a8abf 100644 --- a/source/winbindd/winbindd_pam.c +++ b/source/winbindd/winbindd_pam.c @@ -1741,7 +1741,252 @@ static void ndr_child_auth_compat_auth_plain(struct winbindd_domain *domain, struct winbindd_cli_state *state, struct winbind_auth *r) { - r->out.result = WINBIND_STATUS_NOT_IMPLEMENTED; + NTSTATUS result = NT_STATUS_LOGON_FAILURE; + NTSTATUS krb5_result = NT_STATUS_OK; + fstring name_domain, name_user; + fstring full_account_name; + struct netr_SamInfo3 *info3 = NULL; + struct winbind_auth_compat_auth_plain_req *in; + + in = &r->in.req.compat_auth_plain; + + DEBUG(3, ("comapt auth plain account[%s] domain[%s]\n", + in->account_name, + in->domain_name?in->domain_name:"(NULL)")); + + /* Parse domain and username */ + +// ws_name_return( state->request.data.auth.user, WB_REPLACE_CHAR ); + +// parse_domain_user(state->request.data.auth.user, name_domain, name_user); + + if (domain->online == False) { + result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; + if (domain->startup) { + /* Logons are very important to users. If we're offline and + we get a request within the first 30 seconds of startup, + try very hard to find a DC and go online. */ + + DEBUG(10,("winbindd_dual_pam_auth: domain: %s offline and auth " + "request in startup mode.\n", domain->name )); + + winbindd_flush_negative_conn_cache(domain); + result = init_dc_connection(domain); + } + } + + DEBUG(10,("compat_auth_plain: domain: %s last was %s\n", domain->name, domain->online ? "online":"offline")); + + /* Check for Kerberos authentication */ + if (domain->online && (in->flags & WBFLAG_PAM_KRB5)) { + + result = winbindd_dual_pam_auth_kerberos(domain, state, &info3); + /* save for later */ + krb5_result = result; + + + if (NT_STATUS_IS_OK(result)) { + DEBUG(10,("winbindd_dual_pam_auth_kerberos succeeded\n")); + goto process_result; + } else { + DEBUG(10,("winbindd_dual_pam_auth_kerberos failed: %s\n", nt_errstr(result))); + } + + if (NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS) || + NT_STATUS_EQUAL(result, NT_STATUS_IO_TIMEOUT) || + NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) { + DEBUG(10,("winbindd_dual_pam_auth_kerberos setting domain to offline\n")); + set_domain_offline( domain ); + goto cached_logon; + } + + /* there are quite some NT_STATUS errors where there is no + * point in retrying with a samlogon, we explictly have to take + * care not to increase the bad logon counter on the DC */ + + if (NT_STATUS_EQUAL(result, NT_STATUS_ACCOUNT_DISABLED) || + NT_STATUS_EQUAL(result, NT_STATUS_ACCOUNT_EXPIRED) || + NT_STATUS_EQUAL(result, NT_STATUS_ACCOUNT_LOCKED_OUT) || + NT_STATUS_EQUAL(result, NT_STATUS_INVALID_LOGON_HOURS) || + NT_STATUS_EQUAL(result, NT_STATUS_INVALID_WORKSTATION) || + NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE) || + NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_USER) || + NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_EXPIRED) || + NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_MUST_CHANGE) || + NT_STATUS_EQUAL(result, NT_STATUS_WRONG_PASSWORD)) { + goto process_result; + } + + if (in->flags & WBFLAG_PAM_FALLBACK_AFTER_KRB5) { + DEBUG(3,("falling back to samlogon\n")); + goto sam_logon; + } else { + goto cached_logon; + } + } + +sam_logon: + /* Check for Samlogon authentication */ + if (domain->online) { + result = winbindd_dual_pam_auth_samlogon(domain, state, &info3); + + if (NT_STATUS_IS_OK(result)) { + DEBUG(10,("winbindd_dual_pam_auth_samlogon succeeded\n")); + /* add the Krb5 err if we have one */ + if ( NT_STATUS_EQUAL(krb5_result, NT_STATUS_TIME_DIFFERENCE_AT_DC ) ) { + info3->base.user_flags |= LOGON_KRB5_FAIL_CLOCK_SKEW; + } + goto process_result; + } + + DEBUG(10,("winbindd_dual_pam_auth_samlogon failed: %s\n", + nt_errstr(result))); + + if (NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS) || + NT_STATUS_EQUAL(result, NT_STATUS_IO_TIMEOUT) || + NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) + { + DEBUG(10,("winbindd_dual_pam_auth_samlogon setting domain to offline\n")); + set_domain_offline( domain ); + goto cached_logon; + } + + if (domain->online) { + /* We're still online - fail. */ + goto done; + } + } + +cached_logon: + /* Check for Cached logons */ + if (!domain->online && (in->flags & WBFLAG_PAM_CACHED_LOGIN) && + lp_winbind_offline_logon()) { + + result = winbindd_dual_pam_auth_cached(domain, state, &info3); + + if (NT_STATUS_IS_OK(result)) { + DEBUG(10,("winbindd_dual_pam_auth_cached succeeded\n")); + goto process_result; + } else { + DEBUG(10,("winbindd_dual_pam_auth_cached failed: %s\n", nt_errstr(result))); + goto done; + } + } + +process_result: + + if (NT_STATUS_IS_OK(result)) { + + DOM_SID user_sid; + + /* In all codepaths where result == NT_STATUS_OK info3 must have + been initialized. */ + if (!info3) { + result = NT_STATUS_INTERNAL_ERROR; + goto done; + } + + netsamlogon_cache_store(name_user, info3); + wcache_invalidate_samlogon(find_domain_from_name(name_domain), info3); + + /* save name_to_sid info as early as possible (only if + this is our primary domain so we don't invalidate + the cache entry by storing the seq_num for the wrong + domain). */ + if ( domain->primary ) { + sid_compose(&user_sid, info3->base.domain_sid, + info3->base.rid); + cache_name2sid(domain, name_domain, name_user, + SID_NAME_USER, &user_sid); + } + + /* Check if the user is in the right group */ + + result = check_info3_in_groups(state->mem_ctx, info3, + in->num_require_membership_of_sids, + in->require_membership_of_sids); + if (!NT_STATUS_IS_OK(result)) { +// DEBUG(3, ("User %s is not in the required group (%s), so plaintext authentication is rejected\n", +// state->request.data.auth.user, +// state->request.data.auth.require_membership_of_sid)); + goto done; + } + + result = append_data(state, info3, name_domain, name_user); + if (!NT_STATUS_IS_OK(result)) { + goto done; + } + + if ((in->flags & WBFLAG_PAM_CACHED_LOGIN)) { + + /* Store in-memory creds for single-signon using ntlm_auth. */ + result = winbindd_add_memory_creds(full_account_name, + get_uid_from_state(state), + in->password); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("Failed to store memory creds: %s\n", nt_errstr(result))); + goto done; + } + + if (lp_winbind_offline_logon()) { + result = winbindd_store_creds(domain, + state->mem_ctx, + full_account_name, + in->password, + info3, NULL); + if (!NT_STATUS_IS_OK(result)) { + + /* Release refcount. */ + winbindd_delete_memory_creds(full_account_name); + + DEBUG(10,("Failed to store creds: %s\n", nt_errstr(result))); + goto done; + } + } + } + + + if (state->request.flags & WBFLAG_PAM_GET_PWD_POLICY) { + result = fillup_password_policy(domain, state); + + if (!NT_STATUS_IS_OK(result) + && !NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED) ) + { + DEBUG(10,("Failed to get password policies: %s\n", nt_errstr(result))); + goto done; + } + } + + result = NT_STATUS_OK; + } + +done: + /* give us a more useful (more correct?) error code */ + if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) || + (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) { + result = NT_STATUS_NO_LOGON_SERVERS; + } + + state->response.data.auth.nt_status = NT_STATUS_V(result); + fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(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", + state->request.data.auth.user, + state->response.data.auth.nt_status_string, + state->response.data.auth.pam_error)); + + if (!NT_STATUS_IS_OK(result)) { + r->out.result = WINBIND_STATUS_FOOBAR; + return; + } + + r->out.result = WINBIND_STATUS_OK; } -- 2.34.1