From 28aa4bff8d6be031c6089fe5c7ab010f1cc48340 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 14 Sep 2007 12:03:58 +0000 Subject: r25154: move winbindd code into winbindd/ metze (This used to be commit 3ac7566ae14c48ff9b0f6b232e0ec4b2f73df558) --- source3/winbindd/winbindd_pam.c | 2382 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 2382 insertions(+) create mode 100644 source3/winbindd/winbindd_pam.c (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c new file mode 100644 index 0000000000..50b24864b5 --- /dev/null +++ b/source3/winbindd/winbindd_pam.c @@ -0,0 +1,2382 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon - pam auth funcions + + Copyright (C) Andrew Tridgell 2000 + Copyright (C) Tim Potter 2001 + Copyright (C) Andrew Bartlett 2001-2002 + Copyright (C) Guenther Deschner 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "winbindd.h" +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, + struct winbindd_cli_state *state, + NET_USER_INFO_3 *info3) +{ + fstring str_sid; + + state->response.data.auth.info3.logon_time = + nt_time_to_unix(info3->logon_time); + state->response.data.auth.info3.logoff_time = + nt_time_to_unix(info3->logoff_time); + state->response.data.auth.info3.kickoff_time = + nt_time_to_unix(info3->kickoff_time); + state->response.data.auth.info3.pass_last_set_time = + nt_time_to_unix(info3->pass_last_set_time); + state->response.data.auth.info3.pass_can_change_time = + nt_time_to_unix(info3->pass_can_change_time); + state->response.data.auth.info3.pass_must_change_time = + nt_time_to_unix(info3->pass_must_change_time); + + state->response.data.auth.info3.logon_count = info3->logon_count; + state->response.data.auth.info3.bad_pw_count = info3->bad_pw_count; + + state->response.data.auth.info3.user_rid = info3->user_rid; + state->response.data.auth.info3.group_rid = info3->group_rid; + sid_to_string(str_sid, &(info3->dom_sid.sid)); + fstrcpy(state->response.data.auth.info3.dom_sid, str_sid); + + state->response.data.auth.info3.num_groups = info3->num_groups; + state->response.data.auth.info3.user_flgs = info3->user_flgs; + + state->response.data.auth.info3.acct_flags = info3->acct_flags; + state->response.data.auth.info3.num_other_sids = info3->num_other_sids; + + unistr2_to_ascii(state->response.data.auth.info3.user_name, + &info3->uni_user_name, -1); + unistr2_to_ascii(state->response.data.auth.info3.full_name, + &info3->uni_full_name, -1); + unistr2_to_ascii(state->response.data.auth.info3.logon_script, + &info3->uni_logon_script, -1); + unistr2_to_ascii(state->response.data.auth.info3.profile_path, + &info3->uni_profile_path, -1); + unistr2_to_ascii(state->response.data.auth.info3.home_dir, + &info3->uni_home_dir, -1); + unistr2_to_ascii(state->response.data.auth.info3.dir_drive, + &info3->uni_dir_drive, -1); + + unistr2_to_ascii(state->response.data.auth.info3.logon_srv, + &info3->uni_logon_srv, -1); + unistr2_to_ascii(state->response.data.auth.info3.logon_dom, + &info3->uni_logon_dom, -1); + + return NT_STATUS_OK; +} + +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, False)) { + prs_mem_free(&ps); + return NT_STATUS_UNSUCCESSFUL; + } + + size = prs_data_size(&ps); + SAFE_FREE(state->response.extra_data.data); + state->response.extra_data.data = SMB_MALLOC(size); + if (!state->response.extra_data.data) { + prs_mem_free(&ps); + return NT_STATUS_NO_MEMORY; + } + memset( state->response.extra_data.data, '\0', size ); + prs_copy_all_data_out((char *)state->response.extra_data.data, &ps); + state->response.length += size; + prs_mem_free(&ps); + return NT_STATUS_OK; +} + +static NTSTATUS append_unix_username(TALLOC_CTX *mem_ctx, + struct winbindd_cli_state *state, + const NET_USER_INFO_3 *info3, + const char *name_domain, + const char *name_user) +{ + /* We've been asked to return the unix username, per + 'winbind use default domain' settings and the like */ + + fstring username_out; + const char *nt_username, *nt_domain; + + 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 = name_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 = name_user; + } + + fill_domain_username(username_out, nt_domain, nt_username, + True); + + DEBUG(5,("Setting unix username to [%s]\n", username_out)); + + SAFE_FREE(state->response.extra_data.data); + state->response.extra_data.data = SMB_STRDUP(username_out); + if (!state->response.extra_data.data) { + return NT_STATUS_NO_MEMORY; + } + state->response.length += + strlen((const char *)state->response.extra_data.data)+1; + + return NT_STATUS_OK; +} + +static NTSTATUS append_afs_token(TALLOC_CTX *mem_ctx, + struct winbindd_cli_state *state, + const NET_USER_INFO_3 *info3, + const char *name_domain, + const char *name_user) +{ + char *afsname = NULL; + char *cell; + + afsname = talloc_strdup(mem_ctx, lp_afs_username_map()); + if (afsname == NULL) { + return NT_STATUS_NO_MEMORY; + } + + afsname = talloc_string_sub(mem_ctx, + lp_afs_username_map(), + "%D", name_domain); + afsname = talloc_string_sub(mem_ctx, afsname, + "%u", name_user); + afsname = talloc_string_sub(mem_ctx, afsname, + "%U", name_user); + + { + DOM_SID user_sid; + fstring sidstr; + + sid_copy(&user_sid, &info3->dom_sid.sid); + sid_append_rid(&user_sid, info3->user_rid); + sid_to_string(sidstr, &user_sid); + afsname = talloc_string_sub(mem_ctx, afsname, + "%s", sidstr); + } + + if (afsname == NULL) { + return NT_STATUS_NO_MEMORY; + } + + strlower_m(afsname); + + DEBUG(10, ("Generating token for user %s\n", afsname)); + + cell = strchr(afsname, '@'); + + if (cell == NULL) { + return NT_STATUS_NO_MEMORY; + } + + *cell = '\0'; + cell += 1; + + /* Append an AFS token string */ + SAFE_FREE(state->response.extra_data.data); + state->response.extra_data.data = + afs_createtoken_str(afsname, cell); + + if (state->response.extra_data.data != NULL) { + state->response.length += + strlen((const char *)state->response.extra_data.data)+1; + } + + return NT_STATUS_OK; +} + +static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, + NET_USER_INFO_3 *info3, + const char *group_sid) +/** + * Check whether a user belongs to a group or list of groups. + * + * @param mem_ctx talloc memory context. + * @param info3 user information, including group membership info. + * @param group_sid One or more groups , separated by commas. + * + * @return NT_STATUS_OK on success, + * NT_STATUS_LOGON_FAILURE if the user does not belong, + * or other NT_STATUS_IS_ERR(status) for other kinds of failure. + */ +{ + DOM_SID *require_membership_of_sid; + size_t num_require_membership_of_sid; + fstring req_sid; + const char *p; + DOM_SID sid; + size_t i; + struct nt_user_token *token; + NTSTATUS status; + + /* Parse the 'required group' SID */ + + if (!group_sid || !group_sid[0]) { + /* NO sid supplied, all users may access */ + return NT_STATUS_OK; + } + + if (!(token = TALLOC_ZERO_P(mem_ctx, struct nt_user_token))) { + DEBUG(0, ("talloc failed\n")); + return NT_STATUS_NO_MEMORY; + } + + num_require_membership_of_sid = 0; + require_membership_of_sid = NULL; + + p = group_sid; + + while (next_token(&p, req_sid, ",", sizeof(req_sid))) { + if (!string_to_sid(&sid, req_sid)) { + DEBUG(0, ("check_info3_in_group: could not parse %s " + "as a SID!", req_sid)); + return NT_STATUS_INVALID_PARAMETER; + } + + if (!add_sid_to_array(mem_ctx, &sid, + &require_membership_of_sid, + &num_require_membership_of_sid)) { + DEBUG(0, ("add_sid_to_array failed\n")); + return NT_STATUS_NO_MEMORY; + } + } + + status = sid_array_from_info3(mem_ctx, info3, + &token->user_sids, + &token->num_sids, + True); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (!NT_STATUS_IS_OK(status = add_aliases(get_global_sam_sid(), + token)) + || !NT_STATUS_IS_OK(status = add_aliases(&global_sid_Builtin, + token))) { + DEBUG(3, ("could not add aliases: %s\n", + nt_errstr(status))); + return status; + } + + debug_nt_user_token(DBGC_CLASS, 10, token); + + for (i=0; irequest.flags & WBFLAG_PAM_CONTACT_TRUSTDOM) { + domain = find_domain_from_name_noinit(domain_name); + if (domain == NULL) { + DEBUG(3, ("Authentication for domain [%s] skipped " + "as it is not a trusted domain\n", + domain_name)); + } else { + return domain; + } + } + + return find_our_domain(); +} + +static void set_auth_errors(struct winbindd_response *resp, NTSTATUS result) +{ + resp->data.auth.nt_status = NT_STATUS_V(result); + fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result)); + + /* we might have given a more useful error above */ + if (*resp->data.auth.error_string == '\0') + fstrcpy(resp->data.auth.error_string, + get_friendly_nt_error_msg(result)); + resp->data.auth.pam_error = nt_status_to_pam(result); +} + +static NTSTATUS fillup_password_policy(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + struct winbindd_methods *methods; + NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + SAM_UNK_INFO_1 password_policy; + + if ( !winbindd_can_contact_domain( domain ) ) { + DEBUG(5,("fillup_password_policy: No inbound trust to " + "contact domain %s\n", domain->name)); + return NT_STATUS_NOT_SUPPORTED; + } + + methods = domain->methods; + + status = methods->password_policy(domain, state->mem_ctx, &password_policy); + if (NT_STATUS_IS_ERR(status)) { + return status; + } + + state->response.data.auth.policy.min_length_password = + password_policy.min_length_password; + state->response.data.auth.policy.password_history = + password_policy.password_history; + state->response.data.auth.policy.password_properties = + password_policy.password_properties; + state->response.data.auth.policy.expire = + nt_time_to_unix_abs(&(password_policy.expire)); + state->response.data.auth.policy.min_passwordage = + nt_time_to_unix_abs(&(password_policy.min_passwordage)); + + return NT_STATUS_OK; +} + +static NTSTATUS get_max_bad_attempts_from_lockout_policy(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint16 *max_allowed_bad_attempts) +{ + struct winbindd_methods *methods; + NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + SAM_UNK_INFO_12 lockout_policy; + + *max_allowed_bad_attempts = 0; + + methods = domain->methods; + + status = methods->lockout_policy(domain, mem_ctx, &lockout_policy); + if (NT_STATUS_IS_ERR(status)) { + return status; + } + + *max_allowed_bad_attempts = lockout_policy.bad_attempt_lockout; + + return NT_STATUS_OK; +} + +static NTSTATUS get_pwd_properties(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 *password_properties) +{ + struct winbindd_methods *methods; + NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + SAM_UNK_INFO_1 password_policy; + + *password_properties = 0; + + methods = domain->methods; + + status = methods->password_policy(domain, mem_ctx, &password_policy); + if (NT_STATUS_IS_ERR(status)) { + return status; + } + + *password_properties = password_policy.password_properties; + + return NT_STATUS_OK; +} + +#ifdef HAVE_KRB5 + +static const char *generate_krb5_ccache(TALLOC_CTX *mem_ctx, + const char *type, + uid_t uid, + BOOL *internal_ccache) +{ + /* accept FILE and WRFILE as krb5_cc_type from the client and then + * build the full ccname string based on the user's uid here - + * Guenther*/ + + const char *gen_cc = NULL; + + *internal_ccache = True; + + if (uid == -1) { + goto memory_ccache; + } + + if (!type || type[0] == '\0') { + goto memory_ccache; + } + + if (strequal(type, "FILE")) { + gen_cc = talloc_asprintf(mem_ctx, "FILE:/tmp/krb5cc_%d", uid); + } else if (strequal(type, "WRFILE")) { + gen_cc = talloc_asprintf(mem_ctx, "WRFILE:/tmp/krb5cc_%d", uid); + } else { + DEBUG(10,("we don't allow to set a %s type ccache\n", type)); + goto memory_ccache; + } + + *internal_ccache = False; + goto done; + + memory_ccache: + gen_cc = talloc_strdup(mem_ctx, "MEMORY:winbindd_pam_ccache"); + + done: + if (gen_cc == NULL) { + DEBUG(0,("out of memory\n")); + return NULL; + } + + DEBUG(10,("using ccache: %s %s\n", gen_cc, *internal_ccache ? "(internal)":"")); + + return gen_cc; +} + +static void setup_return_cc_name(struct winbindd_cli_state *state, const char *cc) +{ + const char *type = state->request.data.auth.krb5_cc_type; + + state->response.data.auth.krb5ccname[0] = '\0'; + + if (type[0] == '\0') { + return; + } + + if (!strequal(type, "FILE") && + !strequal(type, "WRFILE")) { + DEBUG(10,("won't return krbccname for a %s type ccache\n", + type)); + return; + } + + fstrcpy(state->response.data.auth.krb5ccname, cc); +} + +#endif + +static uid_t get_uid_from_state(struct winbindd_cli_state *state) +{ + uid_t uid = -1; + + uid = state->request.data.auth.uid; + + if (uid < 0) { + DEBUG(1,("invalid uid: '%d'\n", uid)); + return -1; + } + return uid; +} + +/********************************************************************** + Authenticate a user with a clear text password using Kerberos and fill up + ccache if required + **********************************************************************/ + +static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain, + struct winbindd_cli_state *state, + NET_USER_INFO_3 **info3) +{ +#ifdef HAVE_KRB5 + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + krb5_error_code krb5_ret; + const char *cc = NULL; + const char *principal_s = NULL; + const char *service = NULL; + char *realm = NULL; + fstring name_domain, name_user; + time_t ticket_lifetime = 0; + time_t renewal_until = 0; + uid_t uid = -1; + ADS_STRUCT *ads; + time_t time_offset = 0; + BOOL internal_ccache = True; + + ZERO_STRUCTP(info3); + + *info3 = NULL; + + /* 1st step: + * prepare a krb5_cc_cache string for the user */ + + uid = get_uid_from_state(state); + if (uid == -1) { + DEBUG(0,("no valid uid\n")); + } + + cc = generate_krb5_ccache(state->mem_ctx, + state->request.data.auth.krb5_cc_type, + state->request.data.auth.uid, + &internal_ccache); + if (cc == NULL) { + return NT_STATUS_NO_MEMORY; + } + + + /* 2nd step: + * get kerberos properties */ + + if (domain->private_data) { + ads = (ADS_STRUCT *)domain->private_data; + time_offset = ads->auth.time_offset; + } + + + /* 3rd step: + * do kerberos auth and setup ccache as the user */ + + parse_domain_user(state->request.data.auth.user, name_domain, name_user); + + realm = domain->alt_name; + strupper_m(realm); + + principal_s = talloc_asprintf(state->mem_ctx, "%s@%s", name_user, realm); + if (principal_s == NULL) { + return NT_STATUS_NO_MEMORY; + } + + service = talloc_asprintf(state->mem_ctx, "%s/%s@%s", KRB5_TGS_NAME, realm, realm); + if (service == NULL) { + return NT_STATUS_NO_MEMORY; + } + + /* if this is a user ccache, we need to act as the user to let the krb5 + * library handle the chown, etc. */ + + /************************ ENTERING NON-ROOT **********************/ + + if (!internal_ccache) { + set_effective_uid(uid); + DEBUG(10,("winbindd_raw_kerberos_login: uid is %d\n", uid)); + } + + result = kerberos_return_info3_from_pac(state->mem_ctx, + principal_s, + state->request.data.auth.pass, + time_offset, + &ticket_lifetime, + &renewal_until, + cc, + True, + True, + WINBINDD_PAM_AUTH_KRB5_RENEW_TIME, + info3); + if (!internal_ccache) { + gain_root_privilege(); + } + + /************************ RETURNED TO ROOT **********************/ + + if (!NT_STATUS_IS_OK(result)) { + goto failed; + } + + DEBUG(10,("winbindd_raw_kerberos_login: winbindd validated ticket of %s\n", + principal_s)); + + /* if we had a user's ccache then return that string for the pam + * environment */ + + if (!internal_ccache) { + + setup_return_cc_name(state, cc); + + result = add_ccache_to_list(principal_s, + cc, + service, + state->request.data.auth.user, + realm, + uid, + time(NULL), + ticket_lifetime, + renewal_until, + False); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("winbindd_raw_kerberos_login: failed to add ccache to list: %s\n", + nt_errstr(result))); + } + } else { + + /* need to delete the memory cred cache, it is not used anymore */ + + krb5_ret = ads_kdestroy(cc); + if (krb5_ret) { + DEBUG(3,("winbindd_raw_kerberos_login: " + "could not destroy krb5 credential cache: " + "%s\n", error_message(krb5_ret))); + } + + } + + return NT_STATUS_OK; + +failed: + + /* we could have created a new credential cache with a valid tgt in it + * but we werent able to get or verify the service ticket for this + * local host and therefor didn't get the PAC, we need to remove that + * cache entirely now */ + + krb5_ret = ads_kdestroy(cc); + if (krb5_ret) { + DEBUG(3,("winbindd_raw_kerberos_login: " + "could not destroy krb5 credential cache: " + "%s\n", error_message(krb5_ret))); + } + + if (!NT_STATUS_IS_OK(remove_ccache(state->request.data.auth.user))) { + DEBUG(3,("winbindd_raw_kerberos_login: " + "could not remove ccache for user %s\n", + state->request.data.auth.user)); + } + + return result; +#else + return NT_STATUS_NOT_SUPPORTED; +#endif /* HAVE_KRB5 */ +} + +/**************************************************************** +****************************************************************/ + +static BOOL check_request_flags(uint32_t flags) +{ + uint32_t flags_edata = WBFLAG_PAM_AFS_TOKEN | + WBFLAG_PAM_UNIX_NAME | + WBFLAG_PAM_INFO3_NDR; + + if ( ( (flags & flags_edata) == WBFLAG_PAM_AFS_TOKEN) || + ( (flags & flags_edata) == WBFLAG_PAM_INFO3_NDR) || + ( (flags & flags_edata) == WBFLAG_PAM_UNIX_NAME) || + !(flags & flags_edata) ) { + return True; + } + + DEBUG(1,("check_request_flags: invalid request flags\n")); + + return False; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS append_data(struct winbindd_cli_state *state, + NET_USER_INFO_3 *info3, + const char *name_domain, + const char *name_user) +{ + NTSTATUS result; + uint32_t flags = state->request.flags; + + if (flags & WBFLAG_PAM_USER_SESSION_KEY) { + memcpy(state->response.data.auth.user_session_key, + info3->user_sess_key, + sizeof(state->response.data.auth.user_session_key) + /* 16 */); + } + + if (flags & WBFLAG_PAM_LMKEY) { + memcpy(state->response.data.auth.first_8_lm_hash, + info3->lm_sess_key, + sizeof(state->response.data.auth.first_8_lm_hash) + /* 8 */); + } + + if (flags & WBFLAG_PAM_INFO3_TEXT) { + result = append_info3_as_txt(state->mem_ctx, state, info3); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("Failed to append INFO3 (TXT): %s\n", + nt_errstr(result))); + return result; + } + } + + /* currently, anything from here on potentially overwrites extra_data. */ + + if (flags & WBFLAG_PAM_INFO3_NDR) { + result = append_info3_as_ndr(state->mem_ctx, state, info3); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("Failed to append INFO3 (NDR): %s\n", + nt_errstr(result))); + return result; + } + } + + if (flags & WBFLAG_PAM_UNIX_NAME) { + result = append_unix_username(state->mem_ctx, state, info3, + name_domain, name_user); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("Failed to append Unix Username: %s\n", + nt_errstr(result))); + return result; + } + } + + if (flags & WBFLAG_PAM_AFS_TOKEN) { + result = append_afs_token(state->mem_ctx, state, info3, + name_domain, name_user); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("Failed to append AFS token: %s\n", + nt_errstr(result))); + return result; + } + } + + return NT_STATUS_OK; +} + +void winbindd_pam_auth(struct winbindd_cli_state *state) +{ + struct winbindd_domain *domain; + fstring name_domain, name_user; + NTSTATUS result; + + /* 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, ("[%5lu]: pam auth %s\n", (unsigned long)state->pid, + state->request.data.auth.user)); + + if (!check_request_flags(state->request.flags)) { + result = NT_STATUS_INVALID_PARAMETER_MIX; + goto done; + } + + /* Parse domain and username */ + + ws_name_return( state->request.data.auth.user, WB_REPLACE_CHAR ); + + if (!canonicalize_username(state->request.data.auth.user, + name_domain, name_user)) { + result = NT_STATUS_NO_SUCH_USER; + goto done; + } + + domain = find_auth_domain(state, name_domain); + + if (domain == NULL) { + result = NT_STATUS_NO_SUCH_USER; + goto done; + } + + sendto_domain(state, domain); + return; + done: + set_auth_errors(&state->response, result); + 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); +} + +NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, + struct winbindd_cli_state *state, + NET_USER_INFO_3 **info3) +{ + NTSTATUS result = NT_STATUS_LOGON_FAILURE; + uint16 max_allowed_bad_attempts; + fstring name_domain, name_user; + DOM_SID sid; + enum lsa_SidType type; + uchar new_nt_pass[NT_HASH_LEN]; + const uint8 *cached_nt_pass; + const uint8 *cached_salt; + NET_USER_INFO_3 *my_info3; + time_t kickoff_time, must_change_time; + BOOL password_good = False; +#ifdef HAVE_KRB5 + struct winbindd_tdc_domain *tdc_domain = NULL; +#endif + + *info3 = NULL; + + ZERO_STRUCTP(info3); + + DEBUG(10,("winbindd_dual_pam_auth_cached\n")); + + /* Parse domain and username */ + + parse_domain_user(state->request.data.auth.user, name_domain, name_user); + + + if (!lookup_cached_name(state->mem_ctx, + name_domain, + name_user, + &sid, + &type)) { + DEBUG(10,("winbindd_dual_pam_auth_cached: no such user in the cache\n")); + return NT_STATUS_NO_SUCH_USER; + } + + if (type != SID_NAME_USER) { + DEBUG(10,("winbindd_dual_pam_auth_cached: not a user (%s)\n", sid_type_lookup(type))); + return NT_STATUS_LOGON_FAILURE; + } + + result = winbindd_get_creds(domain, + state->mem_ctx, + &sid, + &my_info3, + &cached_nt_pass, + &cached_salt); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("winbindd_dual_pam_auth_cached: failed to get creds: %s\n", nt_errstr(result))); + return result; + } + + *info3 = my_info3; + + E_md4hash(state->request.data.auth.pass, new_nt_pass); + + dump_data_pw("new_nt_pass", new_nt_pass, NT_HASH_LEN); + dump_data_pw("cached_nt_pass", cached_nt_pass, NT_HASH_LEN); + if (cached_salt) { + dump_data_pw("cached_salt", cached_salt, NT_HASH_LEN); + } + + if (cached_salt) { + /* In this case we didn't store the nt_hash itself, + but the MD5 combination of salt + nt_hash. */ + uchar salted_hash[NT_HASH_LEN]; + E_md5hash(cached_salt, new_nt_pass, salted_hash); + + password_good = (memcmp(cached_nt_pass, salted_hash, NT_HASH_LEN) == 0) ? + True : False; + } else { + /* Old cached cred - direct store of nt_hash (bad bad bad !). */ + password_good = (memcmp(cached_nt_pass, new_nt_pass, NT_HASH_LEN) == 0) ? + True : False; + } + + if (password_good) { + + /* User *DOES* know the password, update logon_time and reset + * bad_pw_count */ + + my_info3->user_flgs |= LOGON_CACHED_ACCOUNT; + + if (my_info3->acct_flags & ACB_AUTOLOCK) { + return NT_STATUS_ACCOUNT_LOCKED_OUT; + } + + if (my_info3->acct_flags & ACB_DISABLED) { + return NT_STATUS_ACCOUNT_DISABLED; + } + + if (my_info3->acct_flags & ACB_WSTRUST) { + return NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT; + } + + if (my_info3->acct_flags & ACB_SVRTRUST) { + return NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT; + } + + if (my_info3->acct_flags & ACB_DOMTRUST) { + return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT; + } + + if (!(my_info3->acct_flags & ACB_NORMAL)) { + DEBUG(0,("winbindd_dual_pam_auth_cached: whats wrong with that one?: 0x%08x\n", + my_info3->acct_flags)); + return NT_STATUS_LOGON_FAILURE; + } + + kickoff_time = nt_time_to_unix(my_info3->kickoff_time); + if (kickoff_time != 0 && time(NULL) > kickoff_time) { + return NT_STATUS_ACCOUNT_EXPIRED; + } + + must_change_time = nt_time_to_unix(my_info3->pass_must_change_time); + if (must_change_time != 0 && must_change_time < time(NULL)) { + /* we allow grace logons when the password has expired */ + my_info3->user_flgs |= LOGON_GRACE_LOGON; + /* return NT_STATUS_PASSWORD_EXPIRED; */ + goto success; + } + +#ifdef HAVE_KRB5 + if ((state->request.flags & WBFLAG_PAM_KRB5) && + ((tdc_domain = wcache_tdc_fetch_domain(state->mem_ctx, name_domain)) != NULL) && + (tdc_domain->trust_type & DS_DOMAIN_TRUST_TYPE_UPLEVEL)) { + + uid_t uid = -1; + const char *cc = NULL; + char *realm = NULL; + const char *principal_s = NULL; + const char *service = NULL; + BOOL internal_ccache = False; + + uid = get_uid_from_state(state); + if (uid == -1) { + DEBUG(0,("winbindd_dual_pam_auth_cached: invalid uid\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + cc = generate_krb5_ccache(state->mem_ctx, + state->request.data.auth.krb5_cc_type, + state->request.data.auth.uid, + &internal_ccache); + if (cc == NULL) { + return NT_STATUS_NO_MEMORY; + } + + realm = domain->alt_name; + strupper_m(realm); + + principal_s = talloc_asprintf(state->mem_ctx, "%s@%s", name_user, realm); + if (principal_s == NULL) { + return NT_STATUS_NO_MEMORY; + } + + service = talloc_asprintf(state->mem_ctx, "%s/%s@%s", KRB5_TGS_NAME, realm, realm); + if (service == NULL) { + return NT_STATUS_NO_MEMORY; + } + + if (!internal_ccache) { + + setup_return_cc_name(state, cc); + + result = add_ccache_to_list(principal_s, + cc, + service, + state->request.data.auth.user, + domain->alt_name, + uid, + time(NULL), + time(NULL) + lp_winbind_cache_time(), + time(NULL) + WINBINDD_PAM_AUTH_KRB5_RENEW_TIME, + True); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("winbindd_dual_pam_auth_cached: failed " + "to add ccache to list: %s\n", + nt_errstr(result))); + } + } + } +#endif /* HAVE_KRB5 */ + success: + /* FIXME: we possibly should handle logon hours as well (does xp when + * offline?) see auth/auth_sam.c:sam_account_ok for details */ + + unix_to_nt_time(&my_info3->logon_time, time(NULL)); + my_info3->bad_pw_count = 0; + + result = winbindd_update_creds_by_info3(domain, + state->mem_ctx, + state->request.data.auth.user, + state->request.data.auth.pass, + my_info3); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(1,("winbindd_dual_pam_auth_cached: failed to update creds: %s\n", + nt_errstr(result))); + return result; + } + + return NT_STATUS_OK; + + } + + /* User does *NOT* know the correct password, modify info3 accordingly */ + + /* failure of this is not critical */ + result = get_max_bad_attempts_from_lockout_policy(domain, state->mem_ctx, &max_allowed_bad_attempts); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("winbindd_dual_pam_auth_cached: failed to get max_allowed_bad_attempts. " + "Won't be able to honour account lockout policies\n")); + } + + /* increase counter */ + my_info3->bad_pw_count++; + + if (max_allowed_bad_attempts == 0) { + goto failed; + } + + /* lockout user */ + if (my_info3->bad_pw_count >= max_allowed_bad_attempts) { + + uint32 password_properties; + + result = get_pwd_properties(domain, state->mem_ctx, &password_properties); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("winbindd_dual_pam_auth_cached: failed to get password properties.\n")); + } + + if ((my_info3->user_rid != DOMAIN_USER_RID_ADMIN) || + (password_properties & DOMAIN_LOCKOUT_ADMINS)) { + my_info3->acct_flags |= ACB_AUTOLOCK; + } + } + +failed: + result = winbindd_update_creds_by_info3(domain, + state->mem_ctx, + state->request.data.auth.user, + NULL, + my_info3); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(0,("winbindd_dual_pam_auth_cached: failed to update creds %s\n", + nt_errstr(result))); + } + + return NT_STATUS_LOGON_FAILURE; +} + +NTSTATUS winbindd_dual_pam_auth_kerberos(struct winbindd_domain *domain, + struct winbindd_cli_state *state, + NET_USER_INFO_3 **info3) +{ + struct winbindd_domain *contact_domain; + fstring name_domain, name_user; + NTSTATUS result; + + DEBUG(10,("winbindd_dual_pam_auth_kerberos\n")); + + /* Parse domain and username */ + + parse_domain_user(state->request.data.auth.user, name_domain, name_user); + + /* what domain should we contact? */ + + if ( IS_DC ) { + 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; + } + + } else { + 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 = find_domain_from_name(name_domain); + if (contact_domain == NULL) { + 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)); + + contact_domain = find_our_domain(); + } + } + + if (contact_domain->initialized && + contact_domain->active_directory) { + goto try_login; + } + + if (!contact_domain->initialized) { + init_dc_connection(contact_domain); + } + + if (!contact_domain->active_directory) { + DEBUG(3,("krb5 auth requested but domain is not Active Directory\n")); + return NT_STATUS_INVALID_LOGON_TYPE; + } +try_login: + result = winbindd_raw_kerberos_login(contact_domain, state, info3); +done: + return result; +} + +NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, + struct winbindd_cli_state *state, + NET_USER_INFO_3 **info3) +{ + + struct rpc_pipe_client *netlogon_pipe; + uchar chal[8]; + DATA_BLOB lm_resp; + DATA_BLOB nt_resp; + int attempts = 0; + unsigned char local_lm_response[24]; + unsigned char local_nt_response[24]; + struct winbindd_domain *contact_domain; + fstring name_domain, name_user; + BOOL retry; + NTSTATUS result; + NET_USER_INFO_3 *my_info3; + + ZERO_STRUCTP(info3); + + *info3 = NULL; + + my_info3 = TALLOC_ZERO_P(state->mem_ctx, NET_USER_INFO_3); + if (my_info3 == NULL) { + return NT_STATUS_NO_MEMORY; + } + + + DEBUG(10,("winbindd_dual_pam_auth_samlogon\n")); + + /* Parse domain and username */ + + parse_domain_user(state->request.data.auth.user, name_domain, name_user); + + /* do password magic */ + + + generate_random_buffer(chal, 8); + if (lp_client_ntlmv2_auth()) { + DATA_BLOB server_chal; + DATA_BLOB names_blob; + DATA_BLOB nt_response; + DATA_BLOB lm_response; + server_chal = data_blob_talloc(state->mem_ctx, chal, 8); + + /* note that the 'workgroup' here is a best guess - we don't know + the server's domain at this point. The 'server name' is also + dodgy... + */ + names_blob = NTLMv2_generate_names_blob(global_myname(), lp_workgroup()); + + if (!SMBNTLMv2encrypt(name_user, name_domain, + state->request.data.auth.pass, + &server_chal, + &names_blob, + &lm_response, &nt_response, NULL)) { + data_blob_free(&names_blob); + data_blob_free(&server_chal); + DEBUG(0, ("winbindd_pam_auth: SMBNTLMv2encrypt() failed!\n")); + result = NT_STATUS_NO_MEMORY; + goto done; + } + data_blob_free(&names_blob); + data_blob_free(&server_chal); + lm_resp = data_blob_talloc(state->mem_ctx, lm_response.data, + lm_response.length); + nt_resp = data_blob_talloc(state->mem_ctx, nt_response.data, + nt_response.length); + data_blob_free(&lm_response); + data_blob_free(&nt_response); + + } else { + if (lp_client_lanman_auth() + && SMBencrypt(state->request.data.auth.pass, + chal, + local_lm_response)) { + lm_resp = data_blob_talloc(state->mem_ctx, + local_lm_response, + sizeof(local_lm_response)); + } else { + lm_resp = data_blob_null; + } + SMBNTencrypt(state->request.data.auth.pass, + chal, + local_nt_response); + + nt_resp = data_blob_talloc(state->mem_ctx, + local_nt_response, + sizeof(local_nt_response)); + } + + /* what domain should we contact? */ + + if ( IS_DC ) { + 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; + } + + } else { + 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 = find_our_domain(); + } + + /* check authentication loop */ + + do { + NTSTATUS (*logon_fn)(struct rpc_pipe_client + *cli, TALLOC_CTX *mem_ctx, + uint32 logon_parameters, + const char *server, + const char *username, + const char *domain, + const char *workstation, + const uint8 chal[8], + DATA_BLOB lm_response, + DATA_BLOB nt_response, + NET_USER_INFO_3 *info3); + + ZERO_STRUCTP(my_info3); + retry = False; + + result = cm_connect_netlogon(contact_domain, &netlogon_pipe); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(3, ("could not open handle to NETLOGON pipe\n")); + goto done; + } + + logon_fn = contact_domain->can_do_samlogon_ex + ? rpccli_netlogon_sam_network_logon_ex + : rpccli_netlogon_sam_network_logon; + + result = logon_fn(netlogon_pipe, + state->mem_ctx, + 0, + contact_domain->dcname, /* server name */ + name_user, /* user name */ + name_domain, /* target domain */ + global_myname(), /* workstation */ + chal, + lm_resp, + nt_resp, + my_info3); + + if ((NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) + && contact_domain->can_do_samlogon_ex) { + DEBUG(3, ("Got a DC that can not do NetSamLogonEx, " + "retrying with NetSamLogon\n")); + contact_domain->can_do_samlogon_ex = False; + retry = True; + continue; + } + + attempts += 1; + + /* We have to try a second time as cm_connect_netlogon + might not yet have noticed that the DC has killed + our connection. */ + + if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) { + retry = True; + continue; + } + + /* if we get access denied, a possible cause was that we had + and open connection to the DC, but someone changed our + machine account password out from underneath us using 'net + rpc changetrustpw' */ + + if ( NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) ) { + DEBUG(3,("winbindd_pam_auth: sam_logon returned " + "ACCESS_DENIED. Maybe the trust account " + "password was changed and we didn't know it. " + "Killing connections to domain %s\n", + name_domain)); + invalidate_cm_connection(&contact_domain->conn); + retry = True; + } + + } while ( (attempts < 2) && retry ); + + /* handle the case where a NT4 DC does not fill in the acct_flags in + * the samlogon reply info3. When accurate info3 is required by the + * caller, we look up the account flags ourselve - gd */ + + if ((state->request.flags & WBFLAG_PAM_INFO3_TEXT) && + (my_info3->acct_flags == 0) && NT_STATUS_IS_OK(result)) { + + struct rpc_pipe_client *samr_pipe; + POLICY_HND samr_domain_handle, user_pol; + SAM_USERINFO_CTR *user_ctr; + NTSTATUS status_tmp; + uint32 acct_flags; + + ZERO_STRUCT(user_ctr); + + status_tmp = cm_connect_sam(contact_domain, state->mem_ctx, + &samr_pipe, &samr_domain_handle); + + if (!NT_STATUS_IS_OK(status_tmp)) { + DEBUG(3, ("could not open handle to SAMR pipe: %s\n", + nt_errstr(status_tmp))); + goto done; + } + + status_tmp = rpccli_samr_open_user(samr_pipe, state->mem_ctx, + &samr_domain_handle, + MAXIMUM_ALLOWED_ACCESS, + my_info3->user_rid, &user_pol); + + if (!NT_STATUS_IS_OK(status_tmp)) { + DEBUG(3, ("could not open user handle on SAMR pipe: %s\n", + nt_errstr(status_tmp))); + goto done; + } + + status_tmp = rpccli_samr_query_userinfo(samr_pipe, state->mem_ctx, + &user_pol, 16, &user_ctr); + + if (!NT_STATUS_IS_OK(status_tmp)) { + DEBUG(3, ("could not query user info on SAMR pipe: %s\n", + nt_errstr(status_tmp))); + rpccli_samr_close(samr_pipe, state->mem_ctx, &user_pol); + goto done; + } + + acct_flags = user_ctr->info.id16->acb_info; + + if (acct_flags == 0) { + rpccli_samr_close(samr_pipe, state->mem_ctx, &user_pol); + goto done; + } + + my_info3->acct_flags = acct_flags; + + DEBUG(10,("successfully retrieved acct_flags 0x%x\n", acct_flags)); + + rpccli_samr_close(samr_pipe, state->mem_ctx, &user_pol); + } + + *info3 = my_info3; +done: + return result; +} + +enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + NTSTATUS result = NT_STATUS_LOGON_FAILURE; + NTSTATUS krb5_result = NT_STATUS_OK; + fstring name_domain, name_user; + NET_USER_INFO_3 *info3 = NULL; + + /* 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, ("[%5lu]: dual pam auth %s\n", (unsigned long)state->pid, + state->request.data.auth.user)); + + if (!check_request_flags(state->request.flags)) { + result = NT_STATUS_INVALID_PARAMETER_MIX; + goto done; + } + + /* 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,("winbindd_dual_pam_auth: domain: %s last was %s\n", domain->name, domain->online ? "online":"offline")); + + /* Check for Kerberos authentication */ + if (domain->online && (state->request.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 (state->request.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->user_flgs |= 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 && (state->request.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->dom_sid.sid, + info3->user_rid); + cache_name2sid(domain, name_domain, name_user, + SID_NAME_USER, &user_sid); + } + + /* Check if the user is in the right group */ + + if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, info3, + state->request.data.auth.require_membership_of_sid))) { + 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 ((state->request.flags & WBFLAG_PAM_CACHED_LOGIN)) { + + /* Store in-memory creds for single-signon using ntlm_auth. */ + result = winbindd_add_memory_creds(state->request.data.auth.user, + get_uid_from_state(state), + state->request.data.auth.pass); + + 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, + state->request.data.auth.user, + state->request.data.auth.pass, + info3, NULL); + if (!NT_STATUS_IS_OK(result)) { + + /* Release refcount. */ + winbindd_delete_memory_creds(state->request.data.auth.user); + + DEBUG(10,("Failed to store creds: %s\n", nt_errstr(result))); + goto done; + } + } + } + + 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)); + + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} + + +/********************************************************************** + Challenge Response Authentication Protocol +**********************************************************************/ + +void winbindd_pam_auth_crap(struct winbindd_cli_state *state) +{ + struct winbindd_domain *domain = NULL; + const char *domain_name = NULL; + NTSTATUS result; + + if (!check_request_flags(state->request.flags)) { + result = NT_STATUS_INVALID_PARAMETER_MIX; + goto done; + } + + if (!state->privileged) { + char *error_string = NULL; + DEBUG(2, ("winbindd_pam_auth_crap: non-privileged access " + "denied. !\n")); + DEBUGADD(2, ("winbindd_pam_auth_crap: Ensure permissions " + "on %s are set correctly.\n", + get_winbind_priv_pipe_dir())); + /* send a better message than ACCESS_DENIED */ + error_string = talloc_asprintf(state->mem_ctx, + "winbind client not authorized " + "to use winbindd_pam_auth_crap." + " Ensure permissions on %s " + "are set correctly.", + get_winbind_priv_pipe_dir()); + fstrcpy(state->response.data.auth.error_string, error_string); + result = NT_STATUS_ACCESS_DENIED; + goto done; + } + + /* Ensure null termination */ + state->request.data.auth_crap.user + [sizeof(state->request.data.auth_crap.user)-1]=0; + state->request.data.auth_crap.domain + [sizeof(state->request.data.auth_crap.domain)-1]=0; + + DEBUG(3, ("[%5lu]: pam auth crap domain: [%s] user: %s\n", + (unsigned long)state->pid, + state->request.data.auth_crap.domain, + state->request.data.auth_crap.user)); + + if (*state->request.data.auth_crap.domain != '\0') { + domain_name = state->request.data.auth_crap.domain; + } else if (lp_winbind_use_default_domain()) { + domain_name = lp_workgroup(); + } + + if (domain_name != NULL) + domain = find_auth_domain(state, domain_name); + + if (domain != NULL) { + sendto_domain(state, domain); + return; + } + + result = NT_STATUS_NO_SUCH_USER; + + done: + set_auth_errors(&state->response, result); + DEBUG(5, ("CRAP authentication for %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)); + request_error(state); + return; +} + + +enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + NTSTATUS result; + NET_USER_INFO_3 info3; + struct rpc_pipe_client *netlogon_pipe; + const char *name_user = NULL; + const char *name_domain = NULL; + const char *workstation; + struct winbindd_domain *contact_domain; + int attempts = 0; + BOOL retry; + + DATA_BLOB lm_resp, nt_resp; + + /* This is child-only, so no check for privileged access is needed + anymore */ + + /* Ensure null termination */ + state->request.data.auth_crap.user[sizeof(state->request.data.auth_crap.user)-1]=0; + state->request.data.auth_crap.domain[sizeof(state->request.data.auth_crap.domain)-1]=0; + + if (!check_request_flags(state->request.flags)) { + result = NT_STATUS_INVALID_PARAMETER_MIX; + goto done; + } + + name_user = state->request.data.auth_crap.user; + + if (*state->request.data.auth_crap.domain) { + name_domain = state->request.data.auth_crap.domain; + } else if (lp_winbind_use_default_domain()) { + name_domain = lp_workgroup(); + } else { + DEBUG(5,("no domain specified with username (%s) - failing auth\n", + 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, + name_domain, name_user)); + + if (*state->request.data.auth_crap.workstation) { + workstation = state->request.data.auth_crap.workstation; + } 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; + } + + lm_resp = data_blob_talloc(state->mem_ctx, state->request.data.auth_crap.lm_resp, + state->request.data.auth_crap.lm_resp_len); + nt_resp = data_blob_talloc(state->mem_ctx, state->request.data.auth_crap.nt_resp, + state->request.data.auth_crap.nt_resp_len); + + /* what domain should we contact? */ + + if ( IS_DC ) { + 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_crap.user, name_domain, name_user, name_domain)); + result = NT_STATUS_NO_SUCH_USER; + goto done; + } + } else { + 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 = find_our_domain(); + } + + do { + NTSTATUS (*logon_fn)(struct rpc_pipe_client + *cli, TALLOC_CTX *mem_ctx, + uint32 logon_parameters, + const char *server, + const char *username, + const char *domain, + const char *workstation, + const uint8 chal[8], + DATA_BLOB lm_response, + DATA_BLOB nt_response, + NET_USER_INFO_3 *info3); + + ZERO_STRUCT(info3); + retry = False; + + netlogon_pipe = NULL; + result = cm_connect_netlogon(contact_domain, &netlogon_pipe); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(3, ("could not open handle to NETLOGON pipe (error: %s)\n", + nt_errstr(result))); + goto done; + } + + logon_fn = contact_domain->can_do_samlogon_ex + ? rpccli_netlogon_sam_network_logon_ex + : rpccli_netlogon_sam_network_logon; + + result = logon_fn(netlogon_pipe, + state->mem_ctx, + state->request.data.auth_crap.logon_parameters, + contact_domain->dcname, + name_user, + name_domain, + /* Bug #3248 - found by Stefan Burkei. */ + workstation, /* We carefully set this above so use it... */ + state->request.data.auth_crap.chal, + lm_resp, + nt_resp, + &info3); + + if ((NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) + && contact_domain->can_do_samlogon_ex) { + DEBUG(3, ("Got a DC that can not do NetSamLogonEx, " + "retrying with NetSamLogon\n")); + contact_domain->can_do_samlogon_ex = False; + retry = True; + continue; + } + + attempts += 1; + + /* We have to try a second time as cm_connect_netlogon + might not yet have noticed that the DC has killed + our connection. */ + + if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) { + retry = True; + continue; + } + + /* if we get access denied, a possible cause was that we had and open + connection to the DC, but someone changed our machine account password + out from underneath us using 'net rpc changetrustpw' */ + + if ( NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) ) { + DEBUG(3,("winbindd_pam_auth: sam_logon returned " + "ACCESS_DENIED. Maybe the trust account " + "password was changed and we didn't know it. " + "Killing connections to domain %s\n", + name_domain)); + invalidate_cm_connection(&contact_domain->conn); + retry = True; + } + + } while ( (attempts < 2) && retry ); + + if (NT_STATUS_IS_OK(result)) { + + netsamlogon_cache_store(name_user, &info3); + wcache_invalidate_samlogon(find_domain_from_name(name_domain), &info3); + + /* Check if the user is in the right group */ + + if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, &info3, + state->request.data.auth_crap.require_membership_of_sid))) { + DEBUG(3, ("User %s is not in the required group (%s), so " + "crap authentication is rejected\n", + state->request.data.auth_crap.user, + state->request.data.auth_crap.require_membership_of_sid)); + goto done; + } + + result = append_data(state, &info3, name_domain, name_user); + if (!NT_STATUS_IS_OK(result)) { + goto done; + } + } + +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; + } + + if (state->request.flags & WBFLAG_PAM_NT_STATUS_SQUASH) { + result = nt_status_squash(result); + } + + 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, + ("NTLM CRAP authentication for user [%s]\\[%s] returned %s (PAM: %d)\n", + name_domain, + name_user, + state->response.data.auth.nt_status_string, + state->response.data.auth.pam_error)); + + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} + +/* Change a user password */ + +void winbindd_pam_chauthtok(struct winbindd_cli_state *state) +{ + fstring domain, user; + struct winbindd_domain *contact_domain; + + DEBUG(3, ("[%5lu]: pam chauthtok %s\n", (unsigned long)state->pid, + state->request.data.chauthtok.user)); + + /* Setup crap */ + + ws_name_return( state->request.data.auth.user, WB_REPLACE_CHAR ); + + if (!canonicalize_username(state->request.data.chauthtok.user, domain, user)) { + set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER); + DEBUG(5, ("winbindd_pam_chauthtok: canonicalize_username %s failed with %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; + } + + contact_domain = find_domain_from_name(domain); + if (!contact_domain) { + set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER); + 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)); + request_error(state); + return; + } + + sendto_domain(state, contact_domain); +} + +enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact_domain, + struct winbindd_cli_state *state) +{ + char *oldpass; + char *newpass = NULL; + POLICY_HND dom_pol; + struct rpc_pipe_client *cli; + BOOL got_info = False; + SAM_UNK_INFO_1 info; + SAMR_CHANGE_REJECT reject; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + fstring domain, user; + + DEBUG(3, ("[%5lu]: dual pam chauthtok %s\n", (unsigned long)state->pid, + state->request.data.auth.user)); + + if (!parse_domain_user(state->request.data.chauthtok.user, domain, user)) { + goto done; + } + + /* Change password */ + + oldpass = state->request.data.chauthtok.oldpass; + newpass = state->request.data.chauthtok.newpass; + + /* Initialize reject reason */ + state->response.data.auth.reject_reason = Undefined; + + /* Get sam handle */ + + result = cm_connect_sam(contact_domain, state->mem_ctx, &cli, + &dom_pol); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(1, ("could not get SAM handle on DC for %s\n", domain)); + goto done; + } + + result = rpccli_samr_chgpasswd3(cli, state->mem_ctx, user, newpass, oldpass, &info, &reject); + + /* Windows 2003 returns NT_STATUS_PASSWORD_RESTRICTION */ + + if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION) ) { + state->response.data.auth.policy.min_length_password = + info.min_length_password; + state->response.data.auth.policy.password_history = + info.password_history; + state->response.data.auth.policy.password_properties = + info.password_properties; + state->response.data.auth.policy.expire = + nt_time_to_unix_abs(&info.expire); + state->response.data.auth.policy.min_passwordage = + nt_time_to_unix_abs(&info.min_passwordage); + + state->response.data.auth.reject_reason = + reject.reject_reason; + + got_info = True; + } + + /* only fallback when the chgpasswd3 call is not supported */ + if ((NT_STATUS_EQUAL(result, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR))) || + (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) || + (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED))) { + + DEBUG(10,("Password change with chgpasswd3 failed with: %s, retrying chgpasswd_user\n", + nt_errstr(result))); + + result = rpccli_samr_chgpasswd_user(cli, state->mem_ctx, user, newpass, oldpass); + + /* Windows 2000 returns NT_STATUS_ACCOUNT_RESTRICTION. + Map to the same status code as Windows 2003. */ + + if ( NT_STATUS_EQUAL(NT_STATUS_ACCOUNT_RESTRICTION, result ) ) { + result = NT_STATUS_PASSWORD_RESTRICTION; + } + } + +done: + + if (NT_STATUS_IS_OK(result) && (state->request.flags & WBFLAG_PAM_CACHED_LOGIN)) { + + /* Update the single sign-on memory creds. */ + result = winbindd_replace_memory_creds(state->request.data.chauthtok.user, + newpass); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("Failed to replace memory creds: %s\n", nt_errstr(result))); + goto process_result; + } + + if (lp_winbind_offline_logon()) { + result = winbindd_update_creds_by_name(contact_domain, + state->mem_ctx, user, + newpass); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("Failed to store creds: %s\n", nt_errstr(result))); + goto process_result; + } + } + } + + if (!NT_STATUS_IS_OK(result) && !got_info && contact_domain) { + + NTSTATUS policy_ret; + + policy_ret = fillup_password_policy(contact_domain, state); + + /* failure of this is non critical, it will just provide no + * additional information to the client why the change has + * failed - Guenther */ + + if (!NT_STATUS_IS_OK(policy_ret)) { + DEBUG(10,("Failed to get password policies: %s\n", nt_errstr(policy_ret))); + goto process_result; + } + } + +process_result: + + 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)); + state->response.data.auth.pam_error = nt_status_to_pam(result); + + DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, + ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n", + domain, + user, + state->response.data.auth.nt_status_string, + state->response.data.auth.pam_error)); + + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} + +void winbindd_pam_logoff(struct winbindd_cli_state *state) +{ + struct winbindd_domain *domain; + fstring name_domain, user; + uid_t caller_uid = (uid_t)-1; + uid_t request_uid = state->request.data.logoff.uid; + + DEBUG(3, ("[%5lu]: pam logoff %s\n", (unsigned long)state->pid, + state->request.data.logoff.user)); + + /* Ensure null termination */ + state->request.data.logoff.user + [sizeof(state->request.data.logoff.user)-1]='\0'; + + state->request.data.logoff.krb5ccname + [sizeof(state->request.data.logoff.krb5ccname)-1]='\0'; + + if (request_uid == (gid_t)-1) { + goto failed; + } + + if (!canonicalize_username(state->request.data.logoff.user, name_domain, user)) { + goto failed; + } + + if ((domain = find_auth_domain(state, name_domain)) == NULL) { + goto failed; + } + + if ((sys_getpeereid(state->sock, &caller_uid)) != 0) { + DEBUG(1,("winbindd_pam_logoff: failed to check peerid: %s\n", + strerror(errno))); + goto failed; + } + + switch (caller_uid) { + case -1: + goto failed; + case 0: + /* root must be able to logoff any user - gd */ + state->request.data.logoff.uid = request_uid; + break; + default: + if (caller_uid != request_uid) { + DEBUG(1,("winbindd_pam_logoff: caller requested invalid uid\n")); + goto failed; + } + state->request.data.logoff.uid = caller_uid; + break; + } + + sendto_domain(state, domain); + return; + + failed: + set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER); + DEBUG(5, ("Pam Logoff for %s returned %s " + "(PAM: %d)\n", + state->request.data.logoff.user, + state->response.data.auth.nt_status_string, + state->response.data.auth.pam_error)); + request_error(state); + return; +} + +enum winbindd_result winbindd_dual_pam_logoff(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + NTSTATUS result = NT_STATUS_NOT_SUPPORTED; + + DEBUG(3, ("[%5lu]: pam dual logoff %s\n", (unsigned long)state->pid, + state->request.data.logoff.user)); + + if (!(state->request.flags & WBFLAG_PAM_KRB5)) { + result = NT_STATUS_OK; + goto process_result; + } + + if (state->request.data.logoff.krb5ccname[0] == '\0') { + result = NT_STATUS_OK; + goto process_result; + } + +#ifdef HAVE_KRB5 + + if (state->request.data.logoff.uid < 0) { + DEBUG(0,("winbindd_pam_logoff: invalid uid\n")); + goto process_result; + } + + /* what we need here is to find the corresponding krb5 ccache name *we* + * created for a given username and destroy it */ + + if (!ccache_entry_exists(state->request.data.logoff.user)) { + result = NT_STATUS_OK; + DEBUG(10,("winbindd_pam_logoff: no entry found.\n")); + goto process_result; + } + + if (!ccache_entry_identical(state->request.data.logoff.user, + state->request.data.logoff.uid, + state->request.data.logoff.krb5ccname)) { + DEBUG(0,("winbindd_pam_logoff: cached entry differs.\n")); + goto process_result; + } + + result = remove_ccache(state->request.data.logoff.user); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(0,("winbindd_pam_logoff: failed to remove ccache: %s\n", + nt_errstr(result))); + goto process_result; + } + +#else + result = NT_STATUS_NOT_SUPPORTED; +#endif + +process_result: + + winbindd_delete_memory_creds(state->request.data.logoff.user); + + 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)); + state->response.data.auth.pam_error = nt_status_to_pam(result); + + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} + +/* Change user password with auth crap*/ + +void winbindd_pam_chng_pswd_auth_crap(struct winbindd_cli_state *state) +{ + struct winbindd_domain *domain = NULL; + const char *domain_name = NULL; + + /* Ensure null termination */ + state->request.data.chng_pswd_auth_crap.user[ + sizeof(state->request.data.chng_pswd_auth_crap.user)-1]=0; + state->request.data.chng_pswd_auth_crap.domain[ + sizeof(state->request.data.chng_pswd_auth_crap.domain)-1]=0; + + DEBUG(3, ("[%5lu]: pam change pswd auth crap domain: %s user: %s\n", + (unsigned long)state->pid, + state->request.data.chng_pswd_auth_crap.domain, + state->request.data.chng_pswd_auth_crap.user)); + + if (*state->request.data.chng_pswd_auth_crap.domain != '\0') { + domain_name = state->request.data.chng_pswd_auth_crap.domain; + } else if (lp_winbind_use_default_domain()) { + domain_name = lp_workgroup(); + } + + if (domain_name != NULL) + domain = find_domain_from_name(domain_name); + + if (domain != NULL) { + DEBUG(7, ("[%5lu]: pam auth crap changing pswd in domain: " + "%s\n", (unsigned long)state->pid,domain->name)); + sendto_domain(state, domain); + return; + } + + set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER); + DEBUG(5, ("CRAP change password for %s\\%s returned %s (PAM: %d)\n", + state->request.data.chng_pswd_auth_crap.domain, + state->request.data.chng_pswd_auth_crap.user, + state->response.data.auth.nt_status_string, + state->response.data.auth.pam_error)); + request_error(state); + return; +} + +enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domain *domainSt, struct winbindd_cli_state *state) +{ + NTSTATUS result; + DATA_BLOB new_nt_password; + DATA_BLOB old_nt_hash_enc; + DATA_BLOB new_lm_password; + DATA_BLOB old_lm_hash_enc; + fstring domain,user; + POLICY_HND dom_pol; + struct winbindd_domain *contact_domain = domainSt; + struct rpc_pipe_client *cli; + + /* Ensure null termination */ + state->request.data.chng_pswd_auth_crap.user[ + sizeof(state->request.data.chng_pswd_auth_crap.user)-1]=0; + state->request.data.chng_pswd_auth_crap.domain[ + sizeof(state->request.data.chng_pswd_auth_crap.domain)-1]=0; + *domain = 0; + *user = 0; + + DEBUG(3, ("[%5lu]: pam change pswd auth crap domain: %s user: %s\n", + (unsigned long)state->pid, + state->request.data.chng_pswd_auth_crap.domain, + state->request.data.chng_pswd_auth_crap.user)); + + if (lp_winbind_offline_logon()) { + DEBUG(0,("Refusing password change as winbind offline logons are enabled. ")); + DEBUGADD(0,("Changing passwords here would risk inconsistent logons\n")); + result = NT_STATUS_ACCESS_DENIED; + goto done; + } + + if (*state->request.data.chng_pswd_auth_crap.domain) { + fstrcpy(domain,state->request.data.chng_pswd_auth_crap.domain); + } else { + parse_domain_user(state->request.data.chng_pswd_auth_crap.user, + domain, user); + + if(!*domain) { + DEBUG(3,("no domain specified with username (%s) - " + "failing auth\n", + state->request.data.chng_pswd_auth_crap.user)); + result = NT_STATUS_NO_SUCH_USER; + goto done; + } + } + + if (!*domain && lp_winbind_use_default_domain()) { + fstrcpy(domain,(char *)lp_workgroup()); + } + + if(!*user) { + fstrcpy(user, state->request.data.chng_pswd_auth_crap.user); + } + + DEBUG(3, ("[%5lu]: pam auth crap domain: %s user: %s\n", + (unsigned long)state->pid, domain, user)); + + /* Change password */ + new_nt_password = data_blob_talloc( + state->mem_ctx, + state->request.data.chng_pswd_auth_crap.new_nt_pswd, + state->request.data.chng_pswd_auth_crap.new_nt_pswd_len); + + old_nt_hash_enc = data_blob_talloc( + state->mem_ctx, + state->request.data.chng_pswd_auth_crap.old_nt_hash_enc, + state->request.data.chng_pswd_auth_crap.old_nt_hash_enc_len); + + if(state->request.data.chng_pswd_auth_crap.new_lm_pswd_len > 0) { + new_lm_password = data_blob_talloc( + state->mem_ctx, + state->request.data.chng_pswd_auth_crap.new_lm_pswd, + state->request.data.chng_pswd_auth_crap.new_lm_pswd_len); + + old_lm_hash_enc = data_blob_talloc( + state->mem_ctx, + state->request.data.chng_pswd_auth_crap.old_lm_hash_enc, + state->request.data.chng_pswd_auth_crap.old_lm_hash_enc_len); + } else { + new_lm_password.length = 0; + old_lm_hash_enc.length = 0; + } + + /* Get sam handle */ + + result = cm_connect_sam(contact_domain, state->mem_ctx, &cli, &dom_pol); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(1, ("could not get SAM handle on DC for %s\n", domain)); + goto done; + } + + result = rpccli_samr_chng_pswd_auth_crap( + cli, state->mem_ctx, user, new_nt_password, old_nt_hash_enc, + new_lm_password, old_lm_hash_enc); + + 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)); + state->response.data.auth.pam_error = nt_status_to_pam(result); + + DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, + ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n", + domain, user, + state->response.data.auth.nt_status_string, + state->response.data.auth.pam_error)); + + return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; +} -- cgit From 4fab9cf625278dd032a808b5c1bb8f2aec1bd0f2 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 21 Sep 2007 09:52:28 +0000 Subject: r25272: Fix a bunch of callers of pull_ucs2 that passed -1 for dest_len. Michael (This used to be commit a4f53fe22569a63fe7b196971ac6c28a676ee4e8) --- source3/winbindd/winbindd_pam.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 50b24864b5..c4db691d05 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -61,22 +61,22 @@ static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, state->response.data.auth.info3.num_other_sids = info3->num_other_sids; unistr2_to_ascii(state->response.data.auth.info3.user_name, - &info3->uni_user_name, -1); + &info3->uni_user_name, sizeof(fstring)); unistr2_to_ascii(state->response.data.auth.info3.full_name, - &info3->uni_full_name, -1); + &info3->uni_full_name, sizeof(fstring)); unistr2_to_ascii(state->response.data.auth.info3.logon_script, - &info3->uni_logon_script, -1); + &info3->uni_logon_script, sizeof(fstring)); unistr2_to_ascii(state->response.data.auth.info3.profile_path, - &info3->uni_profile_path, -1); + &info3->uni_profile_path, sizeof(fstring)); unistr2_to_ascii(state->response.data.auth.info3.home_dir, - &info3->uni_home_dir, -1); + &info3->uni_home_dir, sizeof(fstring)); unistr2_to_ascii(state->response.data.auth.info3.dir_drive, - &info3->uni_dir_drive, -1); + &info3->uni_dir_drive, sizeof(fstring)); unistr2_to_ascii(state->response.data.auth.info3.logon_srv, - &info3->uni_logon_srv, -1); + &info3->uni_logon_srv, sizeof(fstring)); unistr2_to_ascii(state->response.data.auth.info3.logon_dom, - &info3->uni_logon_dom, -1); + &info3->uni_logon_dom, sizeof(fstring)); return NT_STATUS_OK; } -- cgit From c1284b8eb8585f05a49866d2f93d25f5665b5cf8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 21 Sep 2007 09:58:36 +0000 Subject: r25273: unistrX_to_ascii calls pull_ucs2 - ensure it's never called with -1 (these calls were wrong anyway, target was an fstring, not a pstring). Found by Michael Adam , now to check all other uses. Michael - this version uses sizeof(target) not sizeof(fstring). This way is more future proof. Jeremy. (This used to be commit 9ed3046633b6949c68c9aed61b8e9444601cf101) --- source3/winbindd/winbindd_pam.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index c4db691d05..8f78209586 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -61,22 +61,22 @@ static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, state->response.data.auth.info3.num_other_sids = info3->num_other_sids; unistr2_to_ascii(state->response.data.auth.info3.user_name, - &info3->uni_user_name, sizeof(fstring)); + &info3->uni_user_name, sizeof(state->response.data.auth.info3.user_name)); unistr2_to_ascii(state->response.data.auth.info3.full_name, - &info3->uni_full_name, sizeof(fstring)); + &info3->uni_full_name, sizeof(state->response.data.auth.info3.full_name)); unistr2_to_ascii(state->response.data.auth.info3.logon_script, - &info3->uni_logon_script, sizeof(fstring)); + &info3->uni_logon_script, sizeof(state->response.data.auth.info3.logon_script)); unistr2_to_ascii(state->response.data.auth.info3.profile_path, - &info3->uni_profile_path, sizeof(fstring)); + &info3->uni_profile_path, sizeof(state->response.data.auth.info3.profile_path)); unistr2_to_ascii(state->response.data.auth.info3.home_dir, - &info3->uni_home_dir, sizeof(fstring)); + &info3->uni_home_dir, sizeof(state->response.data.auth.info3.home_dir)); unistr2_to_ascii(state->response.data.auth.info3.dir_drive, - &info3->uni_dir_drive, sizeof(fstring)); + &info3->uni_dir_drive, sizeof(state->response.data.auth.info3.dir_drive)); unistr2_to_ascii(state->response.data.auth.info3.logon_srv, - &info3->uni_logon_srv, sizeof(fstring)); + &info3->uni_logon_srv, sizeof(state->response.data.auth.info3.logon_srv)); unistr2_to_ascii(state->response.data.auth.info3.logon_dom, - &info3->uni_logon_dom, sizeof(fstring)); + &info3->uni_logon_dom, sizeof(state->response.data.auth.info3.logon_dom)); return NT_STATUS_OK; } -- cgit From 6873d5446e4cee76b022bfc0d33e9e8380e796c0 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 21 Sep 2007 12:24:43 +0000 Subject: r25287: Eliminate a handful of red bars and overly long lines I just came across. Michael (This used to be commit bf12f0c0f843f088c7fa2d1eca3298a3d76e9761) --- source3/winbindd/winbindd_pam.c | 72 +++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 32 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 8f78209586..f823e1d7b2 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -7,17 +7,17 @@ Copyright (C) Tim Potter 2001 Copyright (C) Andrew Bartlett 2001-2002 Copyright (C) Guenther Deschner 2005 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see . */ @@ -27,23 +27,23 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND -static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, - struct winbindd_cli_state *state, - NET_USER_INFO_3 *info3) +static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, + struct winbindd_cli_state *state, + NET_USER_INFO_3 *info3) { fstring str_sid; - state->response.data.auth.info3.logon_time = + state->response.data.auth.info3.logon_time = nt_time_to_unix(info3->logon_time); - state->response.data.auth.info3.logoff_time = + state->response.data.auth.info3.logoff_time = nt_time_to_unix(info3->logoff_time); - state->response.data.auth.info3.kickoff_time = + state->response.data.auth.info3.kickoff_time = nt_time_to_unix(info3->kickoff_time); - state->response.data.auth.info3.pass_last_set_time = + state->response.data.auth.info3.pass_last_set_time = nt_time_to_unix(info3->pass_last_set_time); - state->response.data.auth.info3.pass_can_change_time = + state->response.data.auth.info3.pass_can_change_time = nt_time_to_unix(info3->pass_can_change_time); - state->response.data.auth.info3.pass_must_change_time = + state->response.data.auth.info3.pass_must_change_time = nt_time_to_unix(info3->pass_must_change_time); state->response.data.auth.info3.logon_count = info3->logon_count; @@ -60,30 +60,38 @@ static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, state->response.data.auth.info3.acct_flags = info3->acct_flags; state->response.data.auth.info3.num_other_sids = info3->num_other_sids; - unistr2_to_ascii(state->response.data.auth.info3.user_name, - &info3->uni_user_name, sizeof(state->response.data.auth.info3.user_name)); - unistr2_to_ascii(state->response.data.auth.info3.full_name, - &info3->uni_full_name, sizeof(state->response.data.auth.info3.full_name)); - unistr2_to_ascii(state->response.data.auth.info3.logon_script, - &info3->uni_logon_script, sizeof(state->response.data.auth.info3.logon_script)); - unistr2_to_ascii(state->response.data.auth.info3.profile_path, - &info3->uni_profile_path, sizeof(state->response.data.auth.info3.profile_path)); - unistr2_to_ascii(state->response.data.auth.info3.home_dir, - &info3->uni_home_dir, sizeof(state->response.data.auth.info3.home_dir)); - unistr2_to_ascii(state->response.data.auth.info3.dir_drive, - &info3->uni_dir_drive, sizeof(state->response.data.auth.info3.dir_drive)); - - unistr2_to_ascii(state->response.data.auth.info3.logon_srv, - &info3->uni_logon_srv, sizeof(state->response.data.auth.info3.logon_srv)); - unistr2_to_ascii(state->response.data.auth.info3.logon_dom, - &info3->uni_logon_dom, sizeof(state->response.data.auth.info3.logon_dom)); + unistr2_to_ascii(state->response.data.auth.info3.user_name, + &info3->uni_user_name, + sizeof(state->response.data.auth.info3.user_name)); + unistr2_to_ascii(state->response.data.auth.info3.full_name, + &info3->uni_full_name, + sizeof(state->response.data.auth.info3.full_name)); + unistr2_to_ascii(state->response.data.auth.info3.logon_script, + &info3->uni_logon_script, + sizeof(state->response.data.auth.info3.logon_script)); + unistr2_to_ascii(state->response.data.auth.info3.profile_path, + &info3->uni_profile_path, + sizeof(state->response.data.auth.info3.profile_path)); + unistr2_to_ascii(state->response.data.auth.info3.home_dir, + &info3->uni_home_dir, + sizeof(state->response.data.auth.info3.home_dir)); + unistr2_to_ascii(state->response.data.auth.info3.dir_drive, + &info3->uni_dir_drive, + sizeof(state->response.data.auth.info3.dir_drive)); + + unistr2_to_ascii(state->response.data.auth.info3.logon_srv, + &info3->uni_logon_srv, + sizeof(state->response.data.auth.info3.logon_srv)); + unistr2_to_ascii(state->response.data.auth.info3.logon_dom, + &info3->uni_logon_dom, + sizeof(state->response.data.auth.info3.logon_dom)); return NT_STATUS_OK; } -static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx, - struct winbindd_cli_state *state, - NET_USER_INFO_3 *info3) +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; -- cgit From e5a951325a6cac8567af3a66de6d2df577508ae4 Mon Sep 17 00:00:00 2001 From: "Gerald (Jerry) Carter" Date: Wed, 10 Oct 2007 15:34:30 -0500 Subject: [GLUE] Rsync SAMBA_3_2_0 SVN r25598 in order to create the v3-2-test branch. (This used to be commit 5c6c8e1fe93f340005110a7833946191659d88ab) --- source3/winbindd/winbindd_pam.c | 78 ++++++++--------------------------------- 1 file changed, 14 insertions(+), 64 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index f823e1d7b2..78128521c4 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1261,17 +1261,6 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, /* check authentication loop */ do { - NTSTATUS (*logon_fn)(struct rpc_pipe_client - *cli, TALLOC_CTX *mem_ctx, - uint32 logon_parameters, - const char *server, - const char *username, - const char *domain, - const char *workstation, - const uint8 chal[8], - DATA_BLOB lm_response, - DATA_BLOB nt_response, - NET_USER_INFO_3 *info3); ZERO_STRUCTP(my_info3); retry = False; @@ -1283,11 +1272,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, goto done; } - logon_fn = contact_domain->can_do_samlogon_ex - ? rpccli_netlogon_sam_network_logon_ex - : rpccli_netlogon_sam_network_logon; - - result = logon_fn(netlogon_pipe, + result = rpccli_netlogon_sam_network_logon(netlogon_pipe, state->mem_ctx, 0, contact_domain->dcname, /* server name */ @@ -1298,16 +1283,6 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, lm_resp, nt_resp, my_info3); - - if ((NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) - && contact_domain->can_do_samlogon_ex) { - DEBUG(3, ("Got a DC that can not do NetSamLogonEx, " - "retrying with NetSamLogon\n")); - contact_domain->can_do_samlogon_ex = False; - retry = True; - continue; - } - attempts += 1; /* We have to try a second time as cm_connect_netlogon @@ -1803,18 +1778,6 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, } do { - NTSTATUS (*logon_fn)(struct rpc_pipe_client - *cli, TALLOC_CTX *mem_ctx, - uint32 logon_parameters, - const char *server, - const char *username, - const char *domain, - const char *workstation, - const uint8 chal[8], - DATA_BLOB lm_response, - DATA_BLOB nt_response, - NET_USER_INFO_3 *info3); - ZERO_STRUCT(info3); retry = False; @@ -1827,32 +1790,19 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, goto done; } - logon_fn = contact_domain->can_do_samlogon_ex - ? rpccli_netlogon_sam_network_logon_ex - : rpccli_netlogon_sam_network_logon; - - result = logon_fn(netlogon_pipe, - state->mem_ctx, - state->request.data.auth_crap.logon_parameters, - contact_domain->dcname, - name_user, - name_domain, - /* Bug #3248 - found by Stefan Burkei. */ - workstation, /* We carefully set this above so use it... */ - state->request.data.auth_crap.chal, - lm_resp, - nt_resp, - &info3); - - if ((NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) - && contact_domain->can_do_samlogon_ex) { - DEBUG(3, ("Got a DC that can not do NetSamLogonEx, " - "retrying with NetSamLogon\n")); - contact_domain->can_do_samlogon_ex = False; - retry = True; - continue; - } - + result = rpccli_netlogon_sam_network_logon(netlogon_pipe, + state->mem_ctx, + state->request.data.auth_crap.logon_parameters, + contact_domain->dcname, + name_user, + name_domain, + /* Bug #3248 - found by Stefan Burkei. */ + workstation, /* We carefully set this above so use it... */ + state->request.data.auth_crap.chal, + lm_resp, + nt_resp, + &info3); + attempts += 1; /* We have to try a second time as cm_connect_netlogon -- cgit From 30191d1a5704ad2b158386b511558972d539ce47 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Oct 2007 17:40:25 -0700 Subject: RIP BOOL. Convert BOOL -> bool. I found a few interesting bugs in various places whilst doing this (places that assumed BOOL == int). I also need to fix the Samba4 pidl generation (next checkin). Jeremy. (This used to be commit f35a266b3cbb3e5fa6a86be60f34fe340a3ca71f) --- source3/winbindd/winbindd_pam.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 78128521c4..640eb5a519 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -444,7 +444,7 @@ static NTSTATUS get_pwd_properties(struct winbindd_domain *domain, static const char *generate_krb5_ccache(TALLOC_CTX *mem_ctx, const char *type, uid_t uid, - BOOL *internal_ccache) + bool *internal_ccache) { /* accept FILE and WRFILE as krb5_cc_type from the client and then * build the full ccname string based on the user's uid here - @@ -545,7 +545,7 @@ static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain, uid_t uid = -1; ADS_STRUCT *ads; time_t time_offset = 0; - BOOL internal_ccache = True; + bool internal_ccache = True; ZERO_STRUCTP(info3); @@ -695,7 +695,7 @@ failed: /**************************************************************** ****************************************************************/ -static BOOL check_request_flags(uint32_t flags) +static bool check_request_flags(uint32_t flags) { uint32_t flags_edata = WBFLAG_PAM_AFS_TOKEN | WBFLAG_PAM_UNIX_NAME | @@ -846,7 +846,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, const uint8 *cached_salt; NET_USER_INFO_3 *my_info3; time_t kickoff_time, must_change_time; - BOOL password_good = False; + bool password_good = False; #ifdef HAVE_KRB5 struct winbindd_tdc_domain *tdc_domain = NULL; #endif @@ -967,7 +967,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, char *realm = NULL; const char *principal_s = NULL; const char *service = NULL; - BOOL internal_ccache = False; + bool internal_ccache = False; uid = get_uid_from_state(state); if (uid == -1) { @@ -1161,7 +1161,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, unsigned char local_nt_response[24]; struct winbindd_domain *contact_domain; fstring name_domain, name_user; - BOOL retry; + bool retry; NTSTATUS result; NET_USER_INFO_3 *my_info3; @@ -1707,7 +1707,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, const char *workstation; struct winbindd_domain *contact_domain; int attempts = 0; - BOOL retry; + bool retry; DATA_BLOB lm_resp, nt_resp; @@ -1927,7 +1927,7 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact char *newpass = NULL; POLICY_HND dom_pol; struct rpc_pipe_client *cli; - BOOL got_info = False; + bool got_info = False; SAM_UNK_INFO_1 info; SAMR_CHANGE_REJECT reject; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; -- cgit From 6b6655edd90850d09c7711fc3b9fe98271e3e625 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 27 Nov 2007 14:35:30 -0800 Subject: Remove pstrings from everything except srv_spoolss_nt.c. Jeremy. (This used to be commit 0002a9e96b0ef78316295a6eb94ff29b64e2f988) --- source3/winbindd/winbindd_pam.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 640eb5a519..4b052a8576 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -129,14 +129,14 @@ static NTSTATUS append_unix_username(TALLOC_CTX *mem_ctx, fstring username_out; const char *nt_username, *nt_domain; - if (!(nt_domain = unistr2_tdup(mem_ctx, + if (!(nt_domain = unistr2_to_ascii_talloc(mem_ctx, &info3->uni_logon_dom))) { /* If the server didn't give us one, just use the one * we sent them */ nt_domain = name_domain; } - if (!(nt_username = unistr2_tdup(mem_ctx, + if (!(nt_username = unistr2_to_ascii_talloc(mem_ctx, &info3->uni_user_name))) { /* If the server didn't give us one, just use the one * we sent them */ -- cgit From 42cfffae80480eae4381902fff3f7c61f858a933 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 7 Dec 2007 17:32:32 -0800 Subject: Remove next_token - all uses must now be next_token_talloc. No more temptations to use static length strings. Jeremy. (This used to be commit ec003f39369910dee852b7cafb883ddaa321c2de) --- source3/winbindd/winbindd_pam.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 4b052a8576..4eda0fcada 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -222,9 +222,9 @@ static NTSTATUS append_afs_token(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } -static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, +static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, NET_USER_INFO_3 *info3, - const char *group_sid) + const char *group_sid) /** * Check whether a user belongs to a group or list of groups. * @@ -239,15 +239,16 @@ static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, { DOM_SID *require_membership_of_sid; size_t num_require_membership_of_sid; - fstring req_sid; + char *req_sid; const char *p; DOM_SID sid; size_t i; struct nt_user_token *token; + TALLOC_CTX *frame = NULL; NTSTATUS status; /* Parse the 'required group' SID */ - + if (!group_sid || !group_sid[0]) { /* NO sid supplied, all users may access */ return NT_STATUS_OK; @@ -263,10 +264,12 @@ static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, p = group_sid; - while (next_token(&p, req_sid, ",", sizeof(req_sid))) { + frame = talloc_stackframe(); + while (next_token_talloc(frame, &p, &req_sid, ",")) { if (!string_to_sid(&sid, req_sid)) { DEBUG(0, ("check_info3_in_group: could not parse %s " "as a SID!", req_sid)); + TALLOC_FREE(frame); return NT_STATUS_INVALID_PARAMETER; } @@ -274,10 +277,13 @@ static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, &require_membership_of_sid, &num_require_membership_of_sid)) { DEBUG(0, ("add_sid_to_array failed\n")); + TALLOC_FREE(frame); return NT_STATUS_NO_MEMORY; } } + TALLOC_FREE(frame); + status = sid_array_from_info3(mem_ctx, info3, &token->user_sids, &token->num_sids, -- cgit From 900288a2b86abd247f9eb4cd15dc5617a17cfef1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 15 Dec 2007 21:11:36 +0100 Subject: Replace sid_string_static by sid_string_dbg in DEBUGs (This used to be commit bb35e794ec129805e874ceba882bcc1e84791a09) --- source3/winbindd/winbindd_pam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 4eda0fcada..8a372a3a8c 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -304,7 +304,7 @@ static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, debug_nt_user_token(DBGC_CLASS, 10, token); for (i=0; i Date: Sat, 15 Dec 2007 22:47:30 +0100 Subject: s/sid_to_string/sid_to_fstring/ least surprise for callers (This used to be commit eb523ba77697346a365589101aac379febecd546) --- source3/winbindd/winbindd_pam.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 8a372a3a8c..5133239258 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -51,7 +51,7 @@ static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, state->response.data.auth.info3.user_rid = info3->user_rid; state->response.data.auth.info3.group_rid = info3->group_rid; - sid_to_string(str_sid, &(info3->dom_sid.sid)); + sid_to_fstring(str_sid, &(info3->dom_sid.sid)); fstrcpy(state->response.data.auth.info3.dom_sid, str_sid); state->response.data.auth.info3.num_groups = info3->num_groups; @@ -187,7 +187,7 @@ static NTSTATUS append_afs_token(TALLOC_CTX *mem_ctx, sid_copy(&user_sid, &info3->dom_sid.sid); sid_append_rid(&user_sid, info3->user_rid); - sid_to_string(sidstr, &user_sid); + sid_to_fstring(sidstr, &user_sid); afsname = talloc_string_sub(mem_ctx, afsname, "%s", sidstr); } -- cgit From e3bb148b941e67b5caea3db2c8ef9efc984598fa Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 19 Dec 2007 17:53:14 +0100 Subject: Only retrieve password policies in pam_auth when WBFLAG_PAM_GET_PWD_POLICY is set. This essentially re-establishes r14496 (2155bb0535656f294bd054d6a0a7d16a9a71c31b) which was undone in r17723 (43bd8c00abb38eb23a1497a255d194fb1bbffffb) for reasons that are unclear to me. Maybe I am being too naive. Now we do again only retrieve the password policy when called from the pam_winbind module. This fixes logons delegated to AD trusted domain controllers: We need to connect to the sam to retrieve the password policy. But auhtenticated session setup is not possible when contacting the trusted domain dc and afterwards, SamrConnect also fails with whatever credentials and method used. Michael (This used to be commit 6d765e0de523211a2d0b43a2c4c4117f5f0c662f) --- source3/winbindd/winbindd_pam.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 5133239258..7a9014a82f 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1593,13 +1593,16 @@ process_result: } } - 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; + 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; -- cgit From f3603d5a5ab878d45b67bf0f33e2beca50d0af2d Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 9 Jan 2008 00:11:31 +0100 Subject: Convert add_sid_to_array() add_sid_to_array_unique() to return NTSTATUS. Michael (This used to be commit 6b2b9a60ef857ec31da5fea631535205fbdede4a) --- source3/winbindd/winbindd_pam.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 7a9014a82f..525096b0a2 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -273,12 +273,13 @@ static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, return NT_STATUS_INVALID_PARAMETER; } - if (!add_sid_to_array(mem_ctx, &sid, - &require_membership_of_sid, - &num_require_membership_of_sid)) { + status = add_sid_to_array(mem_ctx, &sid, + &require_membership_of_sid, + &num_require_membership_of_sid); + if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("add_sid_to_array failed\n")); TALLOC_FREE(frame); - return NT_STATUS_NO_MEMORY; + return status; } } -- cgit From a92eb76688600efbf4a4056c2543f348e2fee8aa Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 17 Jan 2008 10:24:34 +0100 Subject: Finally enable pidl generated SAMR & NETLOGON headers and clients. Guenther (This used to be commit f7100156a7df7ac3ae84e45a47153b38d9375215) --- source3/winbindd/winbindd_pam.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 525096b0a2..0c75cb17a9 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -923,7 +923,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, /* User *DOES* know the password, update logon_time and reset * bad_pw_count */ - my_info3->user_flgs |= LOGON_CACHED_ACCOUNT; + my_info3->user_flgs |= NETLOGON_CACHED_ACCOUNT; if (my_info3->acct_flags & ACB_AUTOLOCK) { return NT_STATUS_ACCOUNT_LOCKED_OUT; @@ -959,7 +959,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, must_change_time = nt_time_to_unix(my_info3->pass_must_change_time); if (must_change_time != 0 && must_change_time < time(NULL)) { /* we allow grace logons when the password has expired */ - my_info3->user_flgs |= LOGON_GRACE_LOGON; + my_info3->user_flgs |= NETLOGON_GRACE_LOGON; /* return NT_STATUS_PASSWORD_EXPIRED; */ goto success; } @@ -1075,7 +1075,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, } if ((my_info3->user_rid != DOMAIN_USER_RID_ADMIN) || - (password_properties & DOMAIN_LOCKOUT_ADMINS)) { + (password_properties & DOMAIN_PASSWORD_LOCKOUT_ADMINS)) { my_info3->acct_flags |= ACB_AUTOLOCK; } } -- cgit From 2b9ed4700ad42e627919dc372adcb5b5188e9fa0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 18 Jan 2008 08:39:47 +0100 Subject: winbindd: remove useless strcpy metze (This used to be commit df08708fc1e8fc8e15b36db29faf35ae5ae64b65) --- source3/winbindd/winbindd_pam.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 0c75cb17a9..98c9ae2ffe 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -31,8 +31,6 @@ static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, struct winbindd_cli_state *state, NET_USER_INFO_3 *info3) { - fstring str_sid; - state->response.data.auth.info3.logon_time = nt_time_to_unix(info3->logon_time); state->response.data.auth.info3.logoff_time = @@ -51,8 +49,7 @@ static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, state->response.data.auth.info3.user_rid = info3->user_rid; state->response.data.auth.info3.group_rid = info3->group_rid; - sid_to_fstring(str_sid, &(info3->dom_sid.sid)); - fstrcpy(state->response.data.auth.info3.dom_sid, str_sid); + sid_to_fstring(state->response.data.auth.info3.dom_sid, &(info3->dom_sid.sid)); state->response.data.auth.info3.num_groups = info3->num_groups; state->response.data.auth.info3.user_flgs = info3->user_flgs; -- cgit From 80b2e330f939d9877352f8fbdbec3a4e0e395c7b Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 29 Jan 2008 17:49:38 +0100 Subject: Remove include/rpc_ds.h and all references to it completly. Jerry, please have a look if you're fine with that. Guenther (This used to be commit beae25c808a3a03d645f247e9befcd05e3ecca2c) --- source3/winbindd/winbindd_pam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 98c9ae2ffe..ea9a07d388 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -964,7 +964,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, #ifdef HAVE_KRB5 if ((state->request.flags & WBFLAG_PAM_KRB5) && ((tdc_domain = wcache_tdc_fetch_domain(state->mem_ctx, name_domain)) != NULL) && - (tdc_domain->trust_type & DS_DOMAIN_TRUST_TYPE_UPLEVEL)) { + (tdc_domain->trust_type & NETR_TRUST_TYPE_UPLEVEL)) { uid_t uid = -1; const char *cc = NULL; -- cgit From 5334b364c21599fe055b32bbbd1e8cf7488b1fa7 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 30 Jan 2008 12:39:20 +0100 Subject: Remove rpccli_samr_close and use pidl generated function instead. Guenther (This used to be commit 64f0889401855ab76953bfae5db4fe4df19ad8a5) --- source3/winbindd/winbindd_pam.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index ea9a07d388..59ca15a623 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1356,14 +1356,14 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, if (!NT_STATUS_IS_OK(status_tmp)) { DEBUG(3, ("could not query user info on SAMR pipe: %s\n", nt_errstr(status_tmp))); - rpccli_samr_close(samr_pipe, state->mem_ctx, &user_pol); + rpccli_samr_Close(samr_pipe, state->mem_ctx, &user_pol); goto done; } acct_flags = user_ctr->info.id16->acb_info; if (acct_flags == 0) { - rpccli_samr_close(samr_pipe, state->mem_ctx, &user_pol); + rpccli_samr_Close(samr_pipe, state->mem_ctx, &user_pol); goto done; } @@ -1371,7 +1371,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, DEBUG(10,("successfully retrieved acct_flags 0x%x\n", acct_flags)); - rpccli_samr_close(samr_pipe, state->mem_ctx, &user_pol); + rpccli_samr_Close(samr_pipe, state->mem_ctx, &user_pol); } *info3 = my_info3; -- cgit From 37b56c0113263a741c62100cd4b13388cb2a83fa Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 1 Feb 2008 11:57:53 +0100 Subject: Use rpccli_samr_OpenUser() all over the place. Guenther (This used to be commit da90eb7653554d242da83ed98adae35ced3a2938) --- source3/winbindd/winbindd_pam.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 59ca15a623..14b1621fc9 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1339,10 +1339,11 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, goto done; } - status_tmp = rpccli_samr_open_user(samr_pipe, state->mem_ctx, - &samr_domain_handle, - MAXIMUM_ALLOWED_ACCESS, - my_info3->user_rid, &user_pol); + status_tmp = rpccli_samr_OpenUser(samr_pipe, state->mem_ctx, + &samr_domain_handle, + MAXIMUM_ALLOWED_ACCESS, + my_info3->user_rid, + &user_pol); if (!NT_STATUS_IS_OK(status_tmp)) { DEBUG(3, ("could not open user handle on SAMR pipe: %s\n", -- cgit From 30dcc73d969a0761605e8649d68dc83ba24b9d67 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 28 Jan 2008 17:47:41 +0100 Subject: Fix a typo in a debug message. Michael (This used to be commit 3865a7e6a19630f8a90140accf4a6e93d4f70e6c) --- source3/winbindd/winbindd_pam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 14b1621fc9..9435a328dd 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -324,7 +324,7 @@ struct winbindd_domain *find_auth_domain(struct winbindd_cli_state *state, if (IS_DC) { domain = find_domain_from_name_noinit(domain_name); if (domain == NULL) { - DEBUG(3, ("Authentication for domain [%s] refused" + DEBUG(3, ("Authentication for domain [%s] refused " "as it is not a trusted domain\n", domain_name)); } -- cgit From 742fd39b7a9ecfe30b01e323a9ce1c2375c5d076 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 5 Feb 2008 17:25:07 +0100 Subject: Use rpccli_samr_QueryDomainInfo() in winbindd. Guenther (This used to be commit dd9fa33e968d4e641460fe1c6beb05dfe12fa918) --- source3/winbindd/winbindd_pam.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 9435a328dd..c1a277f9b5 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -370,7 +370,7 @@ static NTSTATUS fillup_password_policy(struct winbindd_domain *domain, { struct winbindd_methods *methods; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - SAM_UNK_INFO_1 password_policy; + struct samr_DomInfo1 password_policy; if ( !winbindd_can_contact_domain( domain ) ) { DEBUG(5,("fillup_password_policy: No inbound trust to " @@ -386,28 +386,28 @@ static NTSTATUS fillup_password_policy(struct winbindd_domain *domain, } state->response.data.auth.policy.min_length_password = - password_policy.min_length_password; + password_policy.min_password_length; state->response.data.auth.policy.password_history = - password_policy.password_history; + password_policy.password_history_length; state->response.data.auth.policy.password_properties = password_policy.password_properties; state->response.data.auth.policy.expire = - nt_time_to_unix_abs(&(password_policy.expire)); - state->response.data.auth.policy.min_passwordage = - nt_time_to_unix_abs(&(password_policy.min_passwordage)); + nt_time_to_unix_abs((NTTIME *)&(password_policy.max_password_age)); + state->response.data.auth.policy.min_passwordage = + nt_time_to_unix_abs((NTTIME *)&(password_policy.min_password_age)); return NT_STATUS_OK; } static NTSTATUS get_max_bad_attempts_from_lockout_policy(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, - uint16 *max_allowed_bad_attempts) + uint16 *lockout_threshold) { struct winbindd_methods *methods; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - SAM_UNK_INFO_12 lockout_policy; + struct samr_DomInfo12 lockout_policy; - *max_allowed_bad_attempts = 0; + *lockout_threshold = 0; methods = domain->methods; @@ -416,7 +416,7 @@ static NTSTATUS get_max_bad_attempts_from_lockout_policy(struct winbindd_domain return status; } - *max_allowed_bad_attempts = lockout_policy.bad_attempt_lockout; + *lockout_threshold = lockout_policy.lockout_threshold; return NT_STATUS_OK; } @@ -427,7 +427,7 @@ static NTSTATUS get_pwd_properties(struct winbindd_domain *domain, { struct winbindd_methods *methods; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - SAM_UNK_INFO_1 password_policy; + struct samr_DomInfo1 password_policy; *password_properties = 0; -- cgit From 9c22a27aadd191d68a34dc2289f3d92dddf42d11 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 5 Feb 2008 20:14:54 +0100 Subject: Let rpccli_samr_chgpasswd3 use rpccli_samr_ChangePasswordUser3 internally. Guenther (This used to be commit ffbfd19ad7065caf05688c5748178d30115d47f4) --- source3/winbindd/winbindd_pam.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index c1a277f9b5..759adb366e 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1936,8 +1936,8 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact POLICY_HND dom_pol; struct rpc_pipe_client *cli; bool got_info = False; - SAM_UNK_INFO_1 info; - SAMR_CHANGE_REJECT reject; + struct samr_DomInfo1 *info = NULL; + struct samr_ChangeReject *reject = NULL; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; fstring domain, user; @@ -1965,24 +1965,29 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact goto done; } - result = rpccli_samr_chgpasswd3(cli, state->mem_ctx, user, newpass, oldpass, &info, &reject); + result = rpccli_samr_chgpasswd3(cli, state->mem_ctx, + user, + newpass, + oldpass, + &info, + &reject); /* Windows 2003 returns NT_STATUS_PASSWORD_RESTRICTION */ if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION) ) { - state->response.data.auth.policy.min_length_password = - info.min_length_password; - state->response.data.auth.policy.password_history = - info.password_history; - state->response.data.auth.policy.password_properties = - info.password_properties; - state->response.data.auth.policy.expire = - nt_time_to_unix_abs(&info.expire); - state->response.data.auth.policy.min_passwordage = - nt_time_to_unix_abs(&info.min_passwordage); - - state->response.data.auth.reject_reason = - reject.reject_reason; + state->response.data.auth.policy.min_length_password = + info->min_password_length; + state->response.data.auth.policy.password_history = + info->password_history_length; + state->response.data.auth.policy.password_properties = + info->password_properties; + state->response.data.auth.policy.expire = + nt_time_to_unix_abs((NTTIME *)&info->max_password_age); + state->response.data.auth.policy.min_passwordage = + nt_time_to_unix_abs((NTTIME *)&info->min_password_age); + + state->response.data.auth.reject_reason = + reject->reason; got_info = True; } -- cgit From 4c42f7999a876db0ec7e93f60354ef51290ad11e Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 12 Feb 2008 18:13:30 +0100 Subject: Use rpccli_samr_QueryUserInfo in net and winbindd. Guenther (This used to be commit a9ff6760901a489ff8877717bdd5a2218154498f) --- source3/winbindd/winbindd_pam.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 759adb366e..dd27ad62f3 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1324,12 +1324,10 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, struct rpc_pipe_client *samr_pipe; POLICY_HND samr_domain_handle, user_pol; - SAM_USERINFO_CTR *user_ctr; + union samr_UserInfo *info = NULL; NTSTATUS status_tmp; uint32 acct_flags; - ZERO_STRUCT(user_ctr); - status_tmp = cm_connect_sam(contact_domain, state->mem_ctx, &samr_pipe, &samr_domain_handle); @@ -1351,8 +1349,10 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, goto done; } - status_tmp = rpccli_samr_query_userinfo(samr_pipe, state->mem_ctx, - &user_pol, 16, &user_ctr); + status_tmp = rpccli_samr_QueryUserInfo(samr_pipe, state->mem_ctx, + &user_pol, + 16, + &info); if (!NT_STATUS_IS_OK(status_tmp)) { DEBUG(3, ("could not query user info on SAMR pipe: %s\n", @@ -1361,7 +1361,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, goto done; } - acct_flags = user_ctr->info.id16->acb_info; + acct_flags = info->info16.acct_flags; if (acct_flags == 0) { rpccli_samr_Close(samr_pipe, state->mem_ctx, &user_pol); -- cgit From 3649f728ed3a449622c4e1dbc3ebf4c3536b72f7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 18 Jan 2008 08:43:45 +0100 Subject: winbindd: add rids and other_sids arrays in WBFLAG_PAM_INFO3_TEXT mode metze (This used to be commit c5e6dd1ca9611e2830ff773875998c01bf779a64) --- source3/winbindd/winbindd_pam.c | 44 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index dd27ad62f3..e3574bbcd6 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -31,6 +31,10 @@ static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, struct winbindd_cli_state *state, NET_USER_INFO_3 *info3) { + char *ex; + size_t size; + uint32_t i; + state->response.data.auth.info3.logon_time = nt_time_to_unix(info3->logon_time); state->response.data.auth.info3.logoff_time = @@ -83,6 +87,42 @@ static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, &info3->uni_logon_dom, sizeof(state->response.data.auth.info3.logon_dom)); + ex = talloc_strdup(mem_ctx, ""); + NT_STATUS_HAVE_NO_MEMORY(ex); + + for (i=0; i < info3->num_groups; i++) { + ex = talloc_asprintf_append_buffer(ex, "0x%08X:0x%08X\n", + info3->gids[i].g_rid, + info3->gids[i].attr); + NT_STATUS_HAVE_NO_MEMORY(ex); + } + + for (i=0; i < info3->num_other_sids; i++) { + char *sid; + + sid = dom_sid_string(mem_ctx, &info3->other_sids[i].sid); + NT_STATUS_HAVE_NO_MEMORY(sid); + + ex = talloc_asprintf_append_buffer(ex, "%s:0x%08X\n", + sid, + info3->other_sids_attrib[i]); + NT_STATUS_HAVE_NO_MEMORY(ex); + + talloc_free(sid); + } + + size = talloc_get_size(ex); + + SAFE_FREE(state->response.extra_data.data); + state->response.extra_data.data = SMB_MALLOC(size); + if (!state->response.extra_data.data) { + return NT_STATUS_NO_MEMORY; + } + memcpy(state->response.extra_data.data, ex, size); + talloc_free(ex); + + state->response.length += size; + return NT_STATUS_OK; } @@ -703,16 +743,18 @@ static bool check_request_flags(uint32_t flags) { uint32_t flags_edata = WBFLAG_PAM_AFS_TOKEN | WBFLAG_PAM_UNIX_NAME | + WBFLAG_PAM_INFO3_TEXT | WBFLAG_PAM_INFO3_NDR; if ( ( (flags & flags_edata) == WBFLAG_PAM_AFS_TOKEN) || ( (flags & flags_edata) == WBFLAG_PAM_INFO3_NDR) || + ( (flags & flags_edata) == WBFLAG_PAM_INFO3_TEXT)|| ( (flags & flags_edata) == WBFLAG_PAM_UNIX_NAME) || !(flags & flags_edata) ) { return True; } - DEBUG(1,("check_request_flags: invalid request flags\n")); + DEBUG(1,("check_request_flags: invalid request flags[0x%08X]\n",flags)); return False; } -- cgit From c6f82f1cc4a08138e5b78d1504ac4f9ea44f81ee Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Sun, 17 Feb 2008 02:04:52 +0100 Subject: Getting rid of net_io_user_info3() when sending an NDR encoded netr_SamInfo3. Guenther (This used to be commit f22ba8aee2ff90e9e34db066d506fec24c52379f) --- source3/winbindd/winbindd_pam.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index e3574bbcd6..ad87fd2c67 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -128,29 +128,31 @@ static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx, struct winbindd_cli_state *state, - NET_USER_INFO_3 *info3) + struct netr_SamInfo3 *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, False)) { - prs_mem_free(&ps); - return NT_STATUS_UNSUCCESSFUL; + DATA_BLOB blob; + enum ndr_err_code ndr_err; + + ndr_err = ndr_push_struct_blob(&blob, mem_ctx, info3, + (ndr_push_flags_fn_t)ndr_push_netr_SamInfo3); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(0,("append_info3_as_ndr: failed to append\n")); + return ndr_map_error2ntstatus(ndr_err); } - size = prs_data_size(&ps); SAFE_FREE(state->response.extra_data.data); - state->response.extra_data.data = SMB_MALLOC(size); + state->response.extra_data.data = SMB_MALLOC(blob.length); if (!state->response.extra_data.data) { - prs_mem_free(&ps); + data_blob_free(&blob); return NT_STATUS_NO_MEMORY; } - memset( state->response.extra_data.data, '\0', size ); - prs_copy_all_data_out((char *)state->response.extra_data.data, &ps); - state->response.length += size; - prs_mem_free(&ps); + + memset(state->response.extra_data.data, '\0', blob.length); + memcpy(state->response.extra_data.data, blob.data, blob.length); + state->response.length += blob.length; + + data_blob_free(&blob); + return NT_STATUS_OK; } -- cgit From c25958a046bbcfc13db200430e505ac4ee9b3f27 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Sun, 17 Feb 2008 02:08:12 +0100 Subject: Use netr_SamInfo3 everywhere in winbindd. Guenther (This used to be commit d9502eb75395131d5a8130ff2c4ebace106cb974) --- source3/winbindd/winbindd_pam.c | 203 ++++++++++++++++++---------------------- 1 file changed, 93 insertions(+), 110 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index ad87fd2c67..79b4c764c3 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -29,83 +29,75 @@ static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, struct winbindd_cli_state *state, - NET_USER_INFO_3 *info3) + struct netr_SamInfo3 *info3) { char *ex; size_t size; uint32_t i; state->response.data.auth.info3.logon_time = - nt_time_to_unix(info3->logon_time); + nt_time_to_unix(info3->base.last_logon); state->response.data.auth.info3.logoff_time = - nt_time_to_unix(info3->logoff_time); + nt_time_to_unix(info3->base.last_logoff); state->response.data.auth.info3.kickoff_time = - nt_time_to_unix(info3->kickoff_time); + nt_time_to_unix(info3->base.acct_expiry); state->response.data.auth.info3.pass_last_set_time = - nt_time_to_unix(info3->pass_last_set_time); + nt_time_to_unix(info3->base.last_password_change); state->response.data.auth.info3.pass_can_change_time = - nt_time_to_unix(info3->pass_can_change_time); + nt_time_to_unix(info3->base.allow_password_change); state->response.data.auth.info3.pass_must_change_time = - nt_time_to_unix(info3->pass_must_change_time); - - state->response.data.auth.info3.logon_count = info3->logon_count; - state->response.data.auth.info3.bad_pw_count = info3->bad_pw_count; - - state->response.data.auth.info3.user_rid = info3->user_rid; - state->response.data.auth.info3.group_rid = info3->group_rid; - sid_to_fstring(state->response.data.auth.info3.dom_sid, &(info3->dom_sid.sid)); - - state->response.data.auth.info3.num_groups = info3->num_groups; - state->response.data.auth.info3.user_flgs = info3->user_flgs; - - state->response.data.auth.info3.acct_flags = info3->acct_flags; - state->response.data.auth.info3.num_other_sids = info3->num_other_sids; - - unistr2_to_ascii(state->response.data.auth.info3.user_name, - &info3->uni_user_name, - sizeof(state->response.data.auth.info3.user_name)); - unistr2_to_ascii(state->response.data.auth.info3.full_name, - &info3->uni_full_name, - sizeof(state->response.data.auth.info3.full_name)); - unistr2_to_ascii(state->response.data.auth.info3.logon_script, - &info3->uni_logon_script, - sizeof(state->response.data.auth.info3.logon_script)); - unistr2_to_ascii(state->response.data.auth.info3.profile_path, - &info3->uni_profile_path, - sizeof(state->response.data.auth.info3.profile_path)); - unistr2_to_ascii(state->response.data.auth.info3.home_dir, - &info3->uni_home_dir, - sizeof(state->response.data.auth.info3.home_dir)); - unistr2_to_ascii(state->response.data.auth.info3.dir_drive, - &info3->uni_dir_drive, - sizeof(state->response.data.auth.info3.dir_drive)); - - unistr2_to_ascii(state->response.data.auth.info3.logon_srv, - &info3->uni_logon_srv, - sizeof(state->response.data.auth.info3.logon_srv)); - unistr2_to_ascii(state->response.data.auth.info3.logon_dom, - &info3->uni_logon_dom, - sizeof(state->response.data.auth.info3.logon_dom)); + nt_time_to_unix(info3->base.force_password_change); + + state->response.data.auth.info3.logon_count = info3->base.logon_count; + state->response.data.auth.info3.bad_pw_count = info3->base.bad_password_count; + + state->response.data.auth.info3.user_rid = info3->base.rid; + state->response.data.auth.info3.group_rid = info3->base.primary_gid; + sid_to_fstring(state->response.data.auth.info3.dom_sid, info3->base.domain_sid); + + state->response.data.auth.info3.num_groups = info3->base.groups.count; + state->response.data.auth.info3.user_flgs = info3->base.user_flags; + + state->response.data.auth.info3.acct_flags = info3->base.acct_flags; + state->response.data.auth.info3.num_other_sids = info3->sidcount; + + fstrcpy(state->response.data.auth.info3.user_name, + info3->base.account_name.string); + fstrcpy(state->response.data.auth.info3.full_name, + info3->base.full_name.string); + fstrcpy(state->response.data.auth.info3.logon_script, + info3->base.logon_script.string); + fstrcpy(state->response.data.auth.info3.profile_path, + info3->base.profile_path.string); + fstrcpy(state->response.data.auth.info3.home_dir, + info3->base.home_directory.string); + fstrcpy(state->response.data.auth.info3.dir_drive, + info3->base.home_drive.string); + + fstrcpy(state->response.data.auth.info3.logon_srv, + info3->base.logon_server.string); + fstrcpy(state->response.data.auth.info3.logon_dom, + info3->base.domain.string); ex = talloc_strdup(mem_ctx, ""); NT_STATUS_HAVE_NO_MEMORY(ex); - for (i=0; i < info3->num_groups; i++) { + for (i=0; i < info3->base.groups.count; i++) { ex = talloc_asprintf_append_buffer(ex, "0x%08X:0x%08X\n", - info3->gids[i].g_rid, - info3->gids[i].attr); + info3->base.groups.rids[i].rid, + info3->base.groups.rids[i].attributes); NT_STATUS_HAVE_NO_MEMORY(ex); } - for (i=0; i < info3->num_other_sids; i++) { + for (i=0; i < info3->sidcount; i++) { char *sid; - sid = dom_sid_string(mem_ctx, &info3->other_sids[i].sid); + sid = dom_sid_string(mem_ctx, info3->sids[i].sid); NT_STATUS_HAVE_NO_MEMORY(sid); ex = talloc_asprintf_append_buffer(ex, "%s:0x%08X\n", sid, - info3->other_sids_attrib[i]); + info3->sids[i].attributes); NT_STATUS_HAVE_NO_MEMORY(ex); talloc_free(sid); @@ -158,7 +150,7 @@ static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx, static NTSTATUS append_unix_username(TALLOC_CTX *mem_ctx, struct winbindd_cli_state *state, - const NET_USER_INFO_3 *info3, + const struct netr_SamInfo3 *info3, const char *name_domain, const char *name_user) { @@ -168,15 +160,15 @@ static NTSTATUS append_unix_username(TALLOC_CTX *mem_ctx, fstring username_out; const char *nt_username, *nt_domain; - if (!(nt_domain = unistr2_to_ascii_talloc(mem_ctx, - &info3->uni_logon_dom))) { + nt_domain = talloc_strdup(mem_ctx, info3->base.domain.string); + if (!nt_domain) { /* If the server didn't give us one, just use the one * we sent them */ nt_domain = name_domain; } - if (!(nt_username = unistr2_to_ascii_talloc(mem_ctx, - &info3->uni_user_name))) { + nt_username = talloc_strdup(mem_ctx, info3->base.account_name.string); + if (!nt_username) { /* If the server didn't give us one, just use the one * we sent them */ nt_username = name_user; @@ -200,7 +192,7 @@ static NTSTATUS append_unix_username(TALLOC_CTX *mem_ctx, static NTSTATUS append_afs_token(TALLOC_CTX *mem_ctx, struct winbindd_cli_state *state, - const NET_USER_INFO_3 *info3, + const struct netr_SamInfo3 *info3, const char *name_domain, const char *name_user) { @@ -224,8 +216,8 @@ static NTSTATUS append_afs_token(TALLOC_CTX *mem_ctx, DOM_SID user_sid; fstring sidstr; - sid_copy(&user_sid, &info3->dom_sid.sid); - sid_append_rid(&user_sid, info3->user_rid); + sid_copy(&user_sid, info3->base.domain_sid); + sid_append_rid(&user_sid, info3->base.rid); sid_to_fstring(sidstr, &user_sid); afsname = talloc_string_sub(mem_ctx, afsname, "%s", sidstr); @@ -262,7 +254,7 @@ static NTSTATUS append_afs_token(TALLOC_CTX *mem_ctx, } static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, - NET_USER_INFO_3 *info3, + struct netr_SamInfo3 *info3, const char *group_sid) /** * Check whether a user belongs to a group or list of groups. @@ -576,7 +568,7 @@ static uid_t get_uid_from_state(struct winbindd_cli_state *state) static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain, struct winbindd_cli_state *state, - NET_USER_INFO_3 **info3) + struct netr_SamInfo3 **info3) { #ifdef HAVE_KRB5 NTSTATUS result = NT_STATUS_UNSUCCESSFUL; @@ -765,7 +757,7 @@ static bool check_request_flags(uint32_t flags) ****************************************************************/ static NTSTATUS append_data(struct winbindd_cli_state *state, - NET_USER_INFO_3 *info3, + struct netr_SamInfo3 *info3, const char *name_domain, const char *name_user) { @@ -774,14 +766,14 @@ static NTSTATUS append_data(struct winbindd_cli_state *state, if (flags & WBFLAG_PAM_USER_SESSION_KEY) { memcpy(state->response.data.auth.user_session_key, - info3->user_sess_key, + info3->base.key.key, sizeof(state->response.data.auth.user_session_key) /* 16 */); } if (flags & WBFLAG_PAM_LMKEY) { memcpy(state->response.data.auth.first_8_lm_hash, - info3->lm_sess_key, + info3->base.LMSessKey.key, sizeof(state->response.data.auth.first_8_lm_hash) /* 8 */); } @@ -882,7 +874,7 @@ void winbindd_pam_auth(struct winbindd_cli_state *state) NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, struct winbindd_cli_state *state, - NET_USER_INFO_3 **info3) + struct netr_SamInfo3 **info3) { NTSTATUS result = NT_STATUS_LOGON_FAILURE; uint16 max_allowed_bad_attempts; @@ -892,7 +884,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, uchar new_nt_pass[NT_HASH_LEN]; const uint8 *cached_nt_pass; const uint8 *cached_salt; - NET_USER_INFO_3 *my_info3; + struct netr_SamInfo3 *my_info3; time_t kickoff_time, must_change_time; bool password_good = False; #ifdef HAVE_KRB5 @@ -964,43 +956,43 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, /* User *DOES* know the password, update logon_time and reset * bad_pw_count */ - my_info3->user_flgs |= NETLOGON_CACHED_ACCOUNT; + my_info3->base.user_flags |= NETLOGON_CACHED_ACCOUNT; - if (my_info3->acct_flags & ACB_AUTOLOCK) { + if (my_info3->base.acct_flags & ACB_AUTOLOCK) { return NT_STATUS_ACCOUNT_LOCKED_OUT; } - if (my_info3->acct_flags & ACB_DISABLED) { + if (my_info3->base.acct_flags & ACB_DISABLED) { return NT_STATUS_ACCOUNT_DISABLED; } - if (my_info3->acct_flags & ACB_WSTRUST) { + if (my_info3->base.acct_flags & ACB_WSTRUST) { return NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT; } - if (my_info3->acct_flags & ACB_SVRTRUST) { + if (my_info3->base.acct_flags & ACB_SVRTRUST) { return NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT; } - if (my_info3->acct_flags & ACB_DOMTRUST) { + if (my_info3->base.acct_flags & ACB_DOMTRUST) { return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT; } - if (!(my_info3->acct_flags & ACB_NORMAL)) { + if (!(my_info3->base.acct_flags & ACB_NORMAL)) { DEBUG(0,("winbindd_dual_pam_auth_cached: whats wrong with that one?: 0x%08x\n", - my_info3->acct_flags)); + my_info3->base.acct_flags)); return NT_STATUS_LOGON_FAILURE; } - kickoff_time = nt_time_to_unix(my_info3->kickoff_time); + kickoff_time = nt_time_to_unix(my_info3->base.acct_expiry); if (kickoff_time != 0 && time(NULL) > kickoff_time) { return NT_STATUS_ACCOUNT_EXPIRED; } - must_change_time = nt_time_to_unix(my_info3->pass_must_change_time); + must_change_time = nt_time_to_unix(my_info3->base.force_password_change); if (must_change_time != 0 && must_change_time < time(NULL)) { /* we allow grace logons when the password has expired */ - my_info3->user_flgs |= NETLOGON_GRACE_LOGON; + my_info3->base.user_flags |= NETLOGON_GRACE_LOGON; /* return NT_STATUS_PASSWORD_EXPIRED; */ goto success; } @@ -1071,8 +1063,8 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, /* FIXME: we possibly should handle logon hours as well (does xp when * offline?) see auth/auth_sam.c:sam_account_ok for details */ - unix_to_nt_time(&my_info3->logon_time, time(NULL)); - my_info3->bad_pw_count = 0; + unix_to_nt_time(&my_info3->base.last_logon, time(NULL)); + my_info3->base.bad_password_count = 0; result = winbindd_update_creds_by_info3(domain, state->mem_ctx, @@ -1099,14 +1091,14 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, } /* increase counter */ - my_info3->bad_pw_count++; + my_info3->base.bad_password_count++; if (max_allowed_bad_attempts == 0) { goto failed; } /* lockout user */ - if (my_info3->bad_pw_count >= max_allowed_bad_attempts) { + if (my_info3->base.bad_password_count >= max_allowed_bad_attempts) { uint32 password_properties; @@ -1115,9 +1107,9 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, DEBUG(10,("winbindd_dual_pam_auth_cached: failed to get password properties.\n")); } - if ((my_info3->user_rid != DOMAIN_USER_RID_ADMIN) || + if ((my_info3->base.rid != DOMAIN_USER_RID_ADMIN) || (password_properties & DOMAIN_PASSWORD_LOCKOUT_ADMINS)) { - my_info3->acct_flags |= ACB_AUTOLOCK; + my_info3->base.acct_flags |= ACB_AUTOLOCK; } } @@ -1138,7 +1130,7 @@ failed: NTSTATUS winbindd_dual_pam_auth_kerberos(struct winbindd_domain *domain, struct winbindd_cli_state *state, - NET_USER_INFO_3 **info3) + struct netr_SamInfo3 **info3) { struct winbindd_domain *contact_domain; fstring name_domain, name_user; @@ -1197,7 +1189,7 @@ done: NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, struct winbindd_cli_state *state, - NET_USER_INFO_3 **info3) + struct netr_SamInfo3 **info3) { struct rpc_pipe_client *netlogon_pipe; @@ -1211,18 +1203,10 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, fstring name_domain, name_user; bool retry; NTSTATUS result; - NET_USER_INFO_3 *my_info3; - - ZERO_STRUCTP(info3); + struct netr_SamInfo3 *my_info3 = NULL; *info3 = NULL; - my_info3 = TALLOC_ZERO_P(state->mem_ctx, NET_USER_INFO_3); - if (my_info3 == NULL) { - return NT_STATUS_NO_MEMORY; - } - - DEBUG(10,("winbindd_dual_pam_auth_samlogon\n")); /* Parse domain and username */ @@ -1330,7 +1314,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, chal, lm_resp, nt_resp, - my_info3); + &my_info3); attempts += 1; /* We have to try a second time as cm_connect_netlogon @@ -1364,7 +1348,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, * caller, we look up the account flags ourselve - gd */ if ((state->request.flags & WBFLAG_PAM_INFO3_TEXT) && - (my_info3->acct_flags == 0) && NT_STATUS_IS_OK(result)) { + (my_info3->base.acct_flags == 0) && NT_STATUS_IS_OK(result)) { struct rpc_pipe_client *samr_pipe; POLICY_HND samr_domain_handle, user_pol; @@ -1384,7 +1368,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, status_tmp = rpccli_samr_OpenUser(samr_pipe, state->mem_ctx, &samr_domain_handle, MAXIMUM_ALLOWED_ACCESS, - my_info3->user_rid, + my_info3->base.rid, &user_pol); if (!NT_STATUS_IS_OK(status_tmp)) { @@ -1412,7 +1396,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, goto done; } - my_info3->acct_flags = acct_flags; + my_info3->base.acct_flags = acct_flags; DEBUG(10,("successfully retrieved acct_flags 0x%x\n", acct_flags)); @@ -1430,8 +1414,8 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, NTSTATUS result = NT_STATUS_LOGON_FAILURE; NTSTATUS krb5_result = NT_STATUS_OK; fstring name_domain, name_user; - NET_USER_INFO_3 *info3 = NULL; - + struct netr_SamInfo3 *info3 = NULL; + /* Ensure null termination */ state->request.data.auth.user[sizeof(state->request.data.auth.user)-1]='\0'; @@ -1526,7 +1510,7 @@ sam_logon: 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->user_flgs |= LOGON_KRB5_FAIL_CLOCK_SKEW; + info3->base.user_flags |= LOGON_KRB5_FAIL_CLOCK_SKEW; } goto process_result; } @@ -1586,8 +1570,8 @@ process_result: the cache entry by storing the seq_num for the wrong domain). */ if ( domain->primary ) { - sid_compose(&user_sid, &info3->dom_sid.sid, - info3->user_rid); + sid_compose(&user_sid, info3->base.domain_sid, + info3->base.rid); cache_name2sid(domain, name_domain, name_user, SID_NAME_USER, &user_sid); } @@ -1752,7 +1736,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, struct winbindd_cli_state *state) { NTSTATUS result; - NET_USER_INFO_3 info3; + struct netr_SamInfo3 *info3 = NULL; struct rpc_pipe_client *netlogon_pipe; const char *name_user = NULL; const char *name_domain = NULL; @@ -1830,7 +1814,6 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, } do { - ZERO_STRUCT(info3); retry = False; netlogon_pipe = NULL; @@ -1884,12 +1867,12 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, if (NT_STATUS_IS_OK(result)) { - netsamlogon_cache_store(name_user, &info3); - wcache_invalidate_samlogon(find_domain_from_name(name_domain), &info3); + netsamlogon_cache_store(name_user, info3); + wcache_invalidate_samlogon(find_domain_from_name(name_domain), info3); /* Check if the user is in the right group */ - if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, &info3, + if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, info3, state->request.data.auth_crap.require_membership_of_sid))) { DEBUG(3, ("User %s is not in the required group (%s), so " "crap authentication is rejected\n", @@ -1898,7 +1881,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, goto done; } - result = append_data(state, &info3, name_domain, name_user); + result = append_data(state, info3, name_domain, name_user); if (!NT_STATUS_IS_OK(result)) { goto done; } -- cgit From 76de025c724d68bef1b81c8ec6081db5e0f19c4a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 28 Feb 2008 13:29:47 +0100 Subject: winbind: use a struct element for WBFLAG_PAM_UNIX_NAME To not conflict with WBFLAG_PAM_INFO3_TEXT. This should fix pam_winbind. metze (This used to be commit 1b8ed6c0ffb2548442bb7e9d848117ce9b1c65c0) --- source3/winbindd/winbindd_pam.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 79b4c764c3..ef5a312eea 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -157,7 +157,6 @@ static NTSTATUS append_unix_username(TALLOC_CTX *mem_ctx, /* We've been asked to return the unix username, per 'winbind use default domain' settings and the like */ - fstring username_out; const char *nt_username, *nt_domain; nt_domain = talloc_strdup(mem_ctx, info3->base.domain.string); @@ -174,18 +173,11 @@ static NTSTATUS append_unix_username(TALLOC_CTX *mem_ctx, nt_username = name_user; } - fill_domain_username(username_out, nt_domain, nt_username, - True); + fill_domain_username(state->response.data.auth.unix_username, + nt_domain, nt_username, True); - DEBUG(5,("Setting unix username to [%s]\n", username_out)); - - SAFE_FREE(state->response.extra_data.data); - state->response.extra_data.data = SMB_STRDUP(username_out); - if (!state->response.extra_data.data) { - return NT_STATUS_NO_MEMORY; - } - state->response.length += - strlen((const char *)state->response.extra_data.data)+1; + DEBUG(5,("Setting unix username to [%s]\n", + state->response.data.auth.unix_username)); return NT_STATUS_OK; } @@ -736,14 +728,12 @@ failed: static bool check_request_flags(uint32_t flags) { uint32_t flags_edata = WBFLAG_PAM_AFS_TOKEN | - WBFLAG_PAM_UNIX_NAME | WBFLAG_PAM_INFO3_TEXT | WBFLAG_PAM_INFO3_NDR; if ( ( (flags & flags_edata) == WBFLAG_PAM_AFS_TOKEN) || ( (flags & flags_edata) == WBFLAG_PAM_INFO3_NDR) || ( (flags & flags_edata) == WBFLAG_PAM_INFO3_TEXT)|| - ( (flags & flags_edata) == WBFLAG_PAM_UNIX_NAME) || !(flags & flags_edata) ) { return True; } -- cgit From ca63c6e0796454c18a1d580df99cbd6d05f60672 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 19 Mar 2008 16:09:37 +0100 Subject: Merge dd9e0bea31751 from 3-0-ctdb -- use NetSamLogonEx when possible NetSamLogonEx has the advantage that it does not use the credential chain (This used to be commit cfceb063f559f8549b8f24ce347be213c89303b0) --- source3/winbindd/winbindd_pam.c | 95 +++++++++++++++++++++++++++++++---------- 1 file changed, 72 insertions(+), 23 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index ef5a312eea..c56eb1b3f8 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1283,6 +1283,17 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, /* check authentication loop */ do { + NTSTATUS (*logon_fn)(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + uint32 logon_parameters, + const char *server, + const char *username, + const char *domain, + const char *workstation, + const uint8 chal[8], + DATA_BLOB lm_response, + DATA_BLOB nt_response, + struct netr_SamInfo3 **info3); ZERO_STRUCTP(my_info3); retry = False; @@ -1294,19 +1305,32 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, goto done; } - result = rpccli_netlogon_sam_network_logon(netlogon_pipe, - state->mem_ctx, - 0, - contact_domain->dcname, /* server name */ - name_user, /* user name */ - name_domain, /* target domain */ - global_myname(), /* workstation */ - chal, - lm_resp, - nt_resp, - &my_info3); + logon_fn = contact_domain->can_do_samlogon_ex + ? rpccli_netlogon_sam_network_logon_ex + : rpccli_netlogon_sam_network_logon; + + result = logon_fn(netlogon_pipe, + state->mem_ctx, + 0, + contact_domain->dcname, /* server name */ + name_user, /* user name */ + name_domain, /* target domain */ + global_myname(), /* workstation */ + chal, + lm_resp, + nt_resp, + &my_info3); attempts += 1; + if ((NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) + && contact_domain->can_do_samlogon_ex) { + DEBUG(3, ("Got a DC that can not do NetSamLogonEx, " + "retrying with NetSamLogon\n")); + contact_domain->can_do_samlogon_ex = False; + retry = True; + continue; + } + /* We have to try a second time as cm_connect_netlogon might not yet have noticed that the DC has killed our connection. */ @@ -1804,6 +1828,18 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, } do { + NTSTATUS (*logon_fn)(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + uint32 logon_parameters, + const char *server, + const char *username, + const char *domain, + const char *workstation, + const uint8 chal[8], + DATA_BLOB lm_response, + DATA_BLOB nt_response, + struct netr_SamInfo3 **info3); + retry = False; netlogon_pipe = NULL; @@ -1815,18 +1851,31 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, goto done; } - result = rpccli_netlogon_sam_network_logon(netlogon_pipe, - state->mem_ctx, - state->request.data.auth_crap.logon_parameters, - contact_domain->dcname, - name_user, - name_domain, - /* Bug #3248 - found by Stefan Burkei. */ - workstation, /* We carefully set this above so use it... */ - state->request.data.auth_crap.chal, - lm_resp, - nt_resp, - &info3); + logon_fn = contact_domain->can_do_samlogon_ex + ? rpccli_netlogon_sam_network_logon_ex + : rpccli_netlogon_sam_network_logon; + + result = logon_fn(netlogon_pipe, + state->mem_ctx, + state->request.data.auth_crap.logon_parameters, + contact_domain->dcname, + name_user, + name_domain, + /* Bug #3248 - found by Stefan Burkei. */ + workstation, /* We carefully set this above so use it... */ + state->request.data.auth_crap.chal, + lm_resp, + nt_resp, + &info3); + + if ((NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) + && contact_domain->can_do_samlogon_ex) { + DEBUG(3, ("Got a DC that can not do NetSamLogonEx, " + "retrying with NetSamLogon\n")); + contact_domain->can_do_samlogon_ex = False; + retry = True; + continue; + } attempts += 1; -- cgit From 689cd9e1012bba0a4e9a7da4bbf8b2833e0f1684 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 25 Mar 2008 22:21:50 +0100 Subject: Fix a segfault When we get a NT_STATUS_WRONG_PASSWORD for example, my_info3 is not initialized at all. So first check that we have NT_STATUS_IS_OK(status) before we dereference my_info3. (This used to be commit 559cd9e5a7fac3ce3769d457132cdcb28569b93d) --- source3/winbindd/winbindd_pam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index c56eb1b3f8..5712f08603 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1362,7 +1362,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, * caller, we look up the account flags ourselve - gd */ if ((state->request.flags & WBFLAG_PAM_INFO3_TEXT) && - (my_info3->base.acct_flags == 0) && NT_STATUS_IS_OK(result)) { + NT_STATUS_IS_OK(result) && (my_info3->base.acct_flags == 0)) { struct rpc_pipe_client *samr_pipe; POLICY_HND samr_domain_handle, user_pol; -- cgit From cba8dcf759a2a0ed10060a19e9676bd1872ded67 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 27 Mar 2008 12:02:18 +0100 Subject: Move LOGON_KRB5_FAIL_CLOCK_SKEW to winbindd_pam. Guenther (This used to be commit fa64c76ac8e54f385f277b5b39be70075b2eeee0) --- source3/winbindd/winbindd_pam.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 5712f08603..63127cbfcd 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -27,6 +27,8 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND +#define LOGON_KRB5_FAIL_CLOCK_SKEW 0x02000000 + static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, struct winbindd_cli_state *state, struct netr_SamInfo3 *info3) -- cgit From 9c169e9e42b58e7b6c4b37f57d4649daea7593e5 Mon Sep 17 00:00:00 2001 From: "Gerald W. Carter" Date: Thu, 27 Mar 2008 11:56:29 -0500 Subject: Don't fill password policy structure for any domain other than our own. The samr connects will fail. This is not independent of the CONTACT_TRUSTDOM flag neede by krb5 logins. (This used to be commit 4de4949e3bfcfb2169c329f19cb76936d9043d50) --- source3/winbindd/winbindd_pam.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 63127cbfcd..3b13a9269a 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1638,12 +1638,24 @@ process_result: if (state->request.flags & WBFLAG_PAM_GET_PWD_POLICY) { - result = fillup_password_policy(domain, state); - + struct winbindd_domain *our_domain = find_our_domain(); + + /* This is not entiurely correct I believe, but it is + consistent. Only apply the password policy settings + too warn users for our own domain. Cannot obtain these + from trusted DCs all the time so don't do it at all. + -- jerry */ + + result = NT_STATUS_NOT_SUPPORTED; + if (our_domain == domain ) { +a result = fillup_password_policy(our_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))); + DEBUG(10,("Failed to get password policies for domain %s: %s\n", + domain->name, nt_errstr(result))); goto done; } } -- cgit From 1b9c4763eec7770008d85796dc5a05c3f5739042 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 27 Mar 2008 18:05:02 +0100 Subject: Fix typo. Guenther (This used to be commit fed644372916a5e565e4f5352aab61b39a3a42a0) --- source3/winbindd/winbindd_pam.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 3b13a9269a..972a3bf3b9 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1639,18 +1639,18 @@ process_result: if (state->request.flags & WBFLAG_PAM_GET_PWD_POLICY) { struct winbindd_domain *our_domain = find_our_domain(); - - /* This is not entiurely correct I believe, but it is + + /* This is not entirely correct I believe, but it is consistent. Only apply the password policy settings too warn users for our own domain. Cannot obtain these from trusted DCs all the time so don't do it at all. -- jerry */ - result = NT_STATUS_NOT_SUPPORTED; + result = NT_STATUS_NOT_SUPPORTED; if (our_domain == domain ) { -a result = fillup_password_policy(our_domain, state); + result = fillup_password_policy(our_domain, state); } - + if (!NT_STATUS_IS_OK(result) && !NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED) ) { -- cgit From bea4541e11f0664aaa8b62d525e0a02b14fc3afa Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 4 Apr 2008 02:53:40 +0200 Subject: Use sid_array_from_info3 in lookup_usergroups_cached(). Guenther (This used to be commit 65b4cb20ea3fb806cfd50281e08f32bea70fafce) --- source3/winbindd/winbindd_pam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 972a3bf3b9..bc27f3db20 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -313,7 +313,7 @@ static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, status = sid_array_from_info3(mem_ctx, info3, &token->user_sids, &token->num_sids, - True); + true, false); if (!NT_STATUS_IS_OK(status)) { return status; } -- cgit From 154f4837b3169ddf6c61f87b9d28c257f69d35bf Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 21 Apr 2008 17:48:31 +0200 Subject: Add in a nice big comment explaining why SamLogonEx matters. Andrew Bartlett (This used to be commit 87232351b5e66728f8d602259961909e8c1dfcb6) --- source3/winbindd/winbindd_pam.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index bc27f3db20..2de10a9f10 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1307,6 +1307,27 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, goto done; } + /* It is really important to try SamLogonEx here, + * because in a clustered environment, we want to use + * one machine account from multiple physical + * computers. + * + * With a normal SamLogon call, we must keep the + * credentials chain updated and intact between all + * users of the machine account (which would imply + * cross-node communication for every NTLM logon). + * + * (The credentials chain is not per NETLOGON pipe + * connection, but globally on the server/client pair + * by machine name). + * + * When using SamLogonEx, the credentials are not + * supplied, but the session key is implied by the + * wrapping SamLogon context. + * + * -- abartlet 21 April 2008 + */ + logon_fn = contact_domain->can_do_samlogon_ex ? rpccli_netlogon_sam_network_logon_ex : rpccli_netlogon_sam_network_logon; -- cgit From cfde5c8d478ced2b02e1711aeee6f609c5e97e4a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 22 May 2008 14:19:14 -0700 Subject: Get rid of "shadowed local var" warnings with gcc. Jeremy. (This used to be commit 0bc18967aa7cb6f4debeaa48be81d0e48a7d9503) --- source3/winbindd/winbindd_pam.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 2de10a9f10..f548a04d35 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1290,12 +1290,12 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, uint32 logon_parameters, const char *server, const char *username, - const char *domain, + const char *ldomain, const char *workstation, - const uint8 chal[8], + const uint8 lchal[8], DATA_BLOB lm_response, DATA_BLOB nt_response, - struct netr_SamInfo3 **info3); + struct netr_SamInfo3 **linfo3); ZERO_STRUCTP(my_info3); retry = False; @@ -1868,12 +1868,12 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, uint32 logon_parameters, const char *server, const char *username, - const char *domain, - const char *workstation, - const uint8 chal[8], + const char *ldomain, + const char *lworkstation, + const uint8 lchal[8], DATA_BLOB lm_response, DATA_BLOB nt_response, - struct netr_SamInfo3 **info3); + struct netr_SamInfo3 **linfo3); retry = False; -- cgit From 059293cbf4553a3b4dbfe78dcadb362ec344ef3b Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 25 Jun 2008 10:35:59 +0200 Subject: rename rpccli_samr_chgpasswd_user to rpccli_samr_chgpasswd_user2. Guenther (This used to be commit 5b4650d56c04be0c498413f17afb2cf6d0e7d548) --- source3/winbindd/winbindd_pam.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index f548a04d35..40bd869433 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -2093,15 +2093,15 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact got_info = True; } - /* only fallback when the chgpasswd3 call is not supported */ + /* only fallback when the chgpasswd_user3 call is not supported */ if ((NT_STATUS_EQUAL(result, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR))) || (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) || (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED))) { - DEBUG(10,("Password change with chgpasswd3 failed with: %s, retrying chgpasswd_user\n", + DEBUG(10,("Password change with chgpasswd3 failed with: %s, retrying chgpasswd_user2\n", nt_errstr(result))); - result = rpccli_samr_chgpasswd_user(cli, state->mem_ctx, user, newpass, oldpass); + result = rpccli_samr_chgpasswd_user2(cli, state->mem_ctx, user, newpass, oldpass); /* Windows 2000 returns NT_STATUS_ACCOUNT_RESTRICTION. Map to the same status code as Windows 2003. */ -- cgit From 14d500c0e7e4261fa8d9dbc12e14d79a424059c3 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 25 Jun 2008 21:49:57 +0200 Subject: rename rpccli_samr_chgpasswd3 to rpccli_samr_chgpasswd_user3. Guenther (This used to be commit b1209a039b45985e0b28777e04cba5bcc3de061e) --- source3/winbindd/winbindd_pam.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 40bd869433..f7001f7716 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -2066,12 +2066,12 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact goto done; } - result = rpccli_samr_chgpasswd3(cli, state->mem_ctx, - user, - newpass, - oldpass, - &info, - &reject); + result = rpccli_samr_chgpasswd_user3(cli, state->mem_ctx, + user, + newpass, + oldpass, + &info, + &reject); /* Windows 2003 returns NT_STATUS_PASSWORD_RESTRICTION */ @@ -2098,7 +2098,7 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) || (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED))) { - DEBUG(10,("Password change with chgpasswd3 failed with: %s, retrying chgpasswd_user2\n", + DEBUG(10,("Password change with chgpasswd_user3 failed with: %s, retrying chgpasswd_user2\n", nt_errstr(result))); result = rpccli_samr_chgpasswd_user2(cli, state->mem_ctx, user, newpass, oldpass); -- cgit From 06b3a79d1fb2b66c39e0d8667c5904bfaff26b03 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 7 Jul 2008 11:26:16 -0700 Subject: Allow authentication and memory credential refresh after password change from gdm/xdm. Patch from boyang . Jeremy. (This used to be commit 8cfc6afc7b4a6af9aea5f5a7cb5af7e3218c2d75) --- source3/winbindd/winbindd_pam.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index f7001f7716..c26f552d31 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -2114,11 +2114,21 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact done: if (NT_STATUS_IS_OK(result) && (state->request.flags & WBFLAG_PAM_CACHED_LOGIN)) { - + /* Update the single sign-on memory creds. */ result = winbindd_replace_memory_creds(state->request.data.chauthtok.user, newpass); + /* When we login from gdm or xdm and password expires, + * we change password, but there are no memory crendentials + * So, winbindd_replace_memory_creds() returns + * NT_STATUS_OBJECT_NAME_NOT_FOUND. This is not a failure. + * --- BoYang + * */ + if (NT_STATUS_EQUAL(result, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { + result = NT_STATUS_OK; + } + if (!NT_STATUS_IS_OK(result)) { DEBUG(10,("Failed to replace memory creds: %s\n", nt_errstr(result))); goto process_result; @@ -2128,12 +2138,23 @@ done: result = winbindd_update_creds_by_name(contact_domain, state->mem_ctx, user, newpass); + /* Again, this happens when we login from gdm or xdm + * and the password expires, *BUT* cached crendentials + * doesn't exist. winbindd_update_creds_by_name() + * returns NT_STATUS_NO_SUCH_USER. + * This is not a failure. + * --- BoYang + * */ + if (NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_USER)) { + result = NT_STATUS_OK; + } + if (!NT_STATUS_IS_OK(result)) { DEBUG(10,("Failed to store creds: %s\n", nt_errstr(result))); goto process_result; } } - } + } if (!NT_STATUS_IS_OK(result) && !got_info && contact_domain) { -- cgit From 06d0790c0799112b89534a646e78d0cb38b06e20 Mon Sep 17 00:00:00 2001 From: Zach Loafman Date: Thu, 3 Jul 2008 22:53:42 -0700 Subject: Fix various build warnings This fixes various build warnings on our platform. I'm sure I haven't caught them all, but it's a start. (This used to be commit 6b73f259cb67d9dda9127907d706f9244a871fa3) --- source3/winbindd/winbindd_pam.c | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index c26f552d31..0f9f1e1621 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1179,6 +1179,18 @@ done: return result; } +typedef NTSTATUS (*netlogon_fn_t)(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + uint32 logon_parameters, + const char *server, + const char *username, + const char *domain, + const char *workstation, + const uint8 chal[8], + DATA_BLOB lm_response, + DATA_BLOB nt_response, + struct netr_SamInfo3 **info3); + NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, struct winbindd_cli_state *state, struct netr_SamInfo3 **info3) @@ -1285,17 +1297,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, /* check authentication loop */ do { - NTSTATUS (*logon_fn)(struct rpc_pipe_client *cli, - TALLOC_CTX *mem_ctx, - uint32 logon_parameters, - const char *server, - const char *username, - const char *ldomain, - const char *workstation, - const uint8 lchal[8], - DATA_BLOB lm_response, - DATA_BLOB nt_response, - struct netr_SamInfo3 **linfo3); + netlogon_fn_t logon_fn; ZERO_STRUCTP(my_info3); retry = False; @@ -1863,17 +1865,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, } do { - NTSTATUS (*logon_fn)(struct rpc_pipe_client *cli, - TALLOC_CTX *mem_ctx, - uint32 logon_parameters, - const char *server, - const char *username, - const char *ldomain, - const char *lworkstation, - const uint8 lchal[8], - DATA_BLOB lm_response, - DATA_BLOB nt_response, - struct netr_SamInfo3 **linfo3); + netlogon_fn_t logon_fn; retry = False; -- cgit From 9f28b99ba8c3fa36abc775880a2571dad1c01c10 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 19 Aug 2008 01:18:24 +0200 Subject: winbindd: kill some trailing/leading whitespace. Guenther (This used to be commit b5bb7844952a87b123551b478b60bfe232afc308) --- source3/winbindd/winbindd_pam.c | 318 ++++++++++++++++++++-------------------- 1 file changed, 159 insertions(+), 159 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 0f9f1e1621..01cdc4d2e9 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -310,8 +310,8 @@ static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, TALLOC_FREE(frame); - status = sid_array_from_info3(mem_ctx, info3, - &token->user_sids, + status = sid_array_from_info3(mem_ctx, info3, + &token->user_sids, &token->num_sids, true, false); if (!NT_STATUS_IS_OK(status)) { @@ -338,13 +338,13 @@ static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } } - + /* Do not distinguish this error from a wrong username/pw */ return NT_STATUS_LOGON_FAILURE; } -struct winbindd_domain *find_auth_domain(struct winbindd_cli_state *state, +struct winbindd_domain *find_auth_domain(struct winbindd_cli_state *state, const char *domain_name) { struct winbindd_domain *domain; @@ -353,7 +353,7 @@ struct winbindd_domain *find_auth_domain(struct winbindd_cli_state *state, domain = find_domain_from_name_noinit(domain_name); if (domain == NULL) { DEBUG(3, ("Authentication for domain [%s] refused " - "as it is not a trusted domain\n", + "as it is not a trusted domain\n", domain_name)); } return domain; @@ -370,12 +370,12 @@ struct winbindd_domain *find_auth_domain(struct winbindd_cli_state *state, if (state->request.flags & WBFLAG_PAM_CONTACT_TRUSTDOM) { domain = find_domain_from_name_noinit(domain_name); if (domain == NULL) { - DEBUG(3, ("Authentication for domain [%s] skipped " - "as it is not a trusted domain\n", + DEBUG(3, ("Authentication for domain [%s] skipped " + "as it is not a trusted domain\n", domain_name)); } else { return domain; - } + } } return find_our_domain(); @@ -387,7 +387,7 @@ static void set_auth_errors(struct winbindd_response *resp, NTSTATUS result) fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result)); /* we might have given a more useful error above */ - if (*resp->data.auth.error_string == '\0') + if (*resp->data.auth.error_string == '\0') fstrcpy(resp->data.auth.error_string, get_friendly_nt_error_msg(result)); resp->data.auth.pam_error = nt_status_to_pam(result); @@ -402,9 +402,9 @@ static NTSTATUS fillup_password_policy(struct winbindd_domain *domain, if ( !winbindd_can_contact_domain( domain ) ) { DEBUG(5,("fillup_password_policy: No inbound trust to " - "contact domain %s\n", domain->name)); + "contact domain %s\n", domain->name)); return NT_STATUS_NOT_SUPPORTED; - } + } methods = domain->methods; @@ -427,8 +427,8 @@ static NTSTATUS fillup_password_policy(struct winbindd_domain *domain, return NT_STATUS_OK; } -static NTSTATUS get_max_bad_attempts_from_lockout_policy(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, +static NTSTATUS get_max_bad_attempts_from_lockout_policy(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, uint16 *lockout_threshold) { struct winbindd_methods *methods; @@ -449,8 +449,8 @@ static NTSTATUS get_max_bad_attempts_from_lockout_policy(struct winbindd_domain return NT_STATUS_OK; } -static NTSTATUS get_pwd_properties(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, +static NTSTATUS get_pwd_properties(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, uint32 *password_properties) { struct winbindd_methods *methods; @@ -473,7 +473,7 @@ static NTSTATUS get_pwd_properties(struct winbindd_domain *domain, #ifdef HAVE_KRB5 -static const char *generate_krb5_ccache(TALLOC_CTX *mem_ctx, +static const char *generate_krb5_ccache(TALLOC_CTX *mem_ctx, const char *type, uid_t uid, bool *internal_ccache) @@ -532,11 +532,11 @@ static void setup_return_cc_name(struct winbindd_cli_state *state, const char *c if (!strequal(type, "FILE") && !strequal(type, "WRFILE")) { - DEBUG(10,("won't return krbccname for a %s type ccache\n", + DEBUG(10,("won't return krbccname for a %s type ccache\n", type)); return; } - + fstrcpy(state->response.data.auth.krb5ccname, cc); } @@ -582,8 +582,8 @@ static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain, ZERO_STRUCTP(info3); *info3 = NULL; - - /* 1st step: + + /* 1st step: * prepare a krb5_cc_cache string for the user */ uid = get_uid_from_state(state); @@ -593,31 +593,31 @@ static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain, cc = generate_krb5_ccache(state->mem_ctx, state->request.data.auth.krb5_cc_type, - state->request.data.auth.uid, + state->request.data.auth.uid, &internal_ccache); if (cc == NULL) { return NT_STATUS_NO_MEMORY; } - /* 2nd step: + /* 2nd step: * get kerberos properties */ - + if (domain->private_data) { ads = (ADS_STRUCT *)domain->private_data; - time_offset = ads->auth.time_offset; + time_offset = ads->auth.time_offset; } - /* 3rd step: + /* 3rd step: * do kerberos auth and setup ccache as the user */ parse_domain_user(state->request.data.auth.user, name_domain, name_user); realm = domain->alt_name; strupper_m(realm); - - principal_s = talloc_asprintf(state->mem_ctx, "%s@%s", name_user, realm); + + principal_s = talloc_asprintf(state->mem_ctx, "%s@%s", name_user, realm); if (principal_s == NULL) { return NT_STATUS_NO_MEMORY; } @@ -665,7 +665,7 @@ static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain, * environment */ if (!internal_ccache) { - + setup_return_cc_name(state, cc); result = add_ccache_to_list(principal_s, @@ -676,11 +676,11 @@ static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain, uid, time(NULL), ticket_lifetime, - renewal_until, + renewal_until, False); if (!NT_STATUS_IS_OK(result)) { - DEBUG(10,("winbindd_raw_kerberos_login: failed to add ccache to list: %s\n", + DEBUG(10,("winbindd_raw_kerberos_login: failed to add ccache to list: %s\n", nt_errstr(result))); } } else { @@ -836,7 +836,7 @@ void winbindd_pam_auth(struct winbindd_cli_state *state) } /* Parse domain and username */ - + ws_name_return( state->request.data.auth.user, WB_REPLACE_CHAR ); if (!canonicalize_username(state->request.data.auth.user, @@ -869,7 +869,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, struct netr_SamInfo3 **info3) { NTSTATUS result = NT_STATUS_LOGON_FAILURE; - uint16 max_allowed_bad_attempts; + uint16 max_allowed_bad_attempts; fstring name_domain, name_user; DOM_SID sid; enum lsa_SidType type; @@ -890,7 +890,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, DEBUG(10,("winbindd_dual_pam_auth_cached\n")); /* Parse domain and username */ - + parse_domain_user(state->request.data.auth.user, name_domain, name_user); @@ -908,10 +908,10 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, return NT_STATUS_LOGON_FAILURE; } - result = winbindd_get_creds(domain, - state->mem_ctx, - &sid, - &my_info3, + result = winbindd_get_creds(domain, + state->mem_ctx, + &sid, + &my_info3, &cached_nt_pass, &cached_salt); if (!NT_STATUS_IS_OK(result)) { @@ -947,31 +947,31 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, /* User *DOES* know the password, update logon_time and reset * bad_pw_count */ - + my_info3->base.user_flags |= NETLOGON_CACHED_ACCOUNT; - + if (my_info3->base.acct_flags & ACB_AUTOLOCK) { return NT_STATUS_ACCOUNT_LOCKED_OUT; } - + if (my_info3->base.acct_flags & ACB_DISABLED) { return NT_STATUS_ACCOUNT_DISABLED; } - + if (my_info3->base.acct_flags & ACB_WSTRUST) { return NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT; } - + if (my_info3->base.acct_flags & ACB_SVRTRUST) { return NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT; } - + if (my_info3->base.acct_flags & ACB_DOMTRUST) { return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT; } if (!(my_info3->base.acct_flags & ACB_NORMAL)) { - DEBUG(0,("winbindd_dual_pam_auth_cached: whats wrong with that one?: 0x%08x\n", + DEBUG(0,("winbindd_dual_pam_auth_cached: whats wrong with that one?: 0x%08x\n", my_info3->base.acct_flags)); return NT_STATUS_LOGON_FAILURE; } @@ -988,7 +988,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, /* return NT_STATUS_PASSWORD_EXPIRED; */ goto success; } - + #ifdef HAVE_KRB5 if ((state->request.flags & WBFLAG_PAM_KRB5) && ((tdc_domain = wcache_tdc_fetch_domain(state->mem_ctx, name_domain)) != NULL) && @@ -1113,7 +1113,7 @@ failed: my_info3); if (!NT_STATUS_IS_OK(result)) { - DEBUG(0,("winbindd_dual_pam_auth_cached: failed to update creds %s\n", + DEBUG(0,("winbindd_dual_pam_auth_cached: failed to update creds %s\n", nt_errstr(result))); } @@ -1121,7 +1121,7 @@ failed: } NTSTATUS winbindd_dual_pam_auth_kerberos(struct winbindd_domain *domain, - struct winbindd_cli_state *state, + struct winbindd_cli_state *state, struct netr_SamInfo3 **info3) { struct winbindd_domain *contact_domain; @@ -1129,38 +1129,38 @@ NTSTATUS winbindd_dual_pam_auth_kerberos(struct winbindd_domain *domain, NTSTATUS result; DEBUG(10,("winbindd_dual_pam_auth_kerberos\n")); - + /* Parse domain and username */ - + parse_domain_user(state->request.data.auth.user, name_domain, name_user); /* what domain should we contact? */ - + if ( IS_DC ) { 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)); + 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; } - + } else { 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 = find_domain_from_name(name_domain); if (contact_domain == NULL) { - 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)); + 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)); contact_domain = find_our_domain(); } } - if (contact_domain->initialized && + if (contact_domain->initialized && contact_domain->active_directory) { goto try_login; } @@ -1212,13 +1212,13 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, *info3 = NULL; DEBUG(10,("winbindd_dual_pam_auth_samlogon\n")); - + /* Parse domain and username */ - + parse_domain_user(state->request.data.auth.user, name_domain, name_user); /* do password magic */ - + generate_random_buffer(chal, 8); if (lp_client_ntlmv2_auth()) { @@ -1226,17 +1226,17 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, DATA_BLOB names_blob; DATA_BLOB nt_response; DATA_BLOB lm_response; - server_chal = data_blob_talloc(state->mem_ctx, chal, 8); - + server_chal = data_blob_talloc(state->mem_ctx, chal, 8); + /* note that the 'workgroup' here is a best guess - we don't know the server's domain at this point. The 'server name' is also - dodgy... + dodgy... */ names_blob = NTLMv2_generate_names_blob(global_myname(), lp_workgroup()); - - if (!SMBNTLMv2encrypt(name_user, name_domain, - state->request.data.auth.pass, - &server_chal, + + if (!SMBNTLMv2encrypt(name_user, name_domain, + state->request.data.auth.pass, + &server_chal, &names_blob, &lm_response, &nt_response, NULL)) { data_blob_free(&names_blob); @@ -1255,35 +1255,35 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, data_blob_free(&nt_response); } else { - if (lp_client_lanman_auth() - && SMBencrypt(state->request.data.auth.pass, - chal, + if (lp_client_lanman_auth() + && SMBencrypt(state->request.data.auth.pass, + chal, local_lm_response)) { - lm_resp = data_blob_talloc(state->mem_ctx, - local_lm_response, + lm_resp = data_blob_talloc(state->mem_ctx, + local_lm_response, sizeof(local_lm_response)); } else { lm_resp = data_blob_null; } - SMBNTencrypt(state->request.data.auth.pass, + SMBNTencrypt(state->request.data.auth.pass, chal, local_nt_response); - nt_resp = data_blob_talloc(state->mem_ctx, - local_nt_response, + nt_resp = data_blob_talloc(state->mem_ctx, + local_nt_response, sizeof(local_nt_response)); } - + /* what domain should we contact? */ - + if ( IS_DC ) { 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)); + 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; } - + } else { if (is_myname(name_domain)) { DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", name_domain)); @@ -1312,7 +1312,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, /* It is really important to try SamLogonEx here, * because in a clustered environment, we want to use * one machine account from multiple physical - * computers. + * computers. * * With a normal SamLogon call, we must keep the * credentials chain updated and intact between all @@ -1326,7 +1326,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, * When using SamLogonEx, the credentials are not * supplied, but the session key is implied by the * wrapping SamLogon context. - * + * * -- abartlet 21 April 2008 */ @@ -1364,12 +1364,12 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, retry = True; continue; } - + /* if we get access denied, a possible cause was that we had and open connection to the DC, but someone changed our machine account password out from underneath us using 'net rpc changetrustpw' */ - + if ( NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) ) { DEBUG(3,("winbindd_pam_auth: sam_logon returned " "ACCESS_DENIED. Maybe the trust account " @@ -1378,15 +1378,15 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, name_domain)); invalidate_cm_connection(&contact_domain->conn); retry = True; - } - + } + } while ( (attempts < 2) && retry ); /* handle the case where a NT4 DC does not fill in the acct_flags in * the samlogon reply info3. When accurate info3 is required by the * caller, we look up the account flags ourselve - gd */ - if ((state->request.flags & WBFLAG_PAM_INFO3_TEXT) && + if ((state->request.flags & WBFLAG_PAM_INFO3_TEXT) && NT_STATUS_IS_OK(result) && (my_info3->base.acct_flags == 0)) { struct rpc_pipe_client *samr_pipe; @@ -1395,11 +1395,11 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, NTSTATUS status_tmp; uint32 acct_flags; - status_tmp = cm_connect_sam(contact_domain, state->mem_ctx, + status_tmp = cm_connect_sam(contact_domain, state->mem_ctx, &samr_pipe, &samr_domain_handle); if (!NT_STATUS_IS_OK(status_tmp)) { - DEBUG(3, ("could not open handle to SAMR pipe: %s\n", + DEBUG(3, ("could not open handle to SAMR pipe: %s\n", nt_errstr(status_tmp))); goto done; } @@ -1448,10 +1448,10 @@ done: } enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, - struct winbindd_cli_state *state) + struct winbindd_cli_state *state) { NTSTATUS result = NT_STATUS_LOGON_FAILURE; - NTSTATUS krb5_result = NT_STATUS_OK; + NTSTATUS krb5_result = NT_STATUS_OK; fstring name_domain, name_user; struct netr_SamInfo3 *info3 = NULL; @@ -1470,7 +1470,7 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, } /* 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); @@ -1494,11 +1494,11 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, /* Check for Kerberos authentication */ if (domain->online && (state->request.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")); @@ -1512,7 +1512,7 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, 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; + goto cached_logon; } /* there are quite some NT_STATUS errors where there is no @@ -1531,7 +1531,7 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, NT_STATUS_EQUAL(result, NT_STATUS_WRONG_PASSWORD)) { goto process_result; } - + if (state->request.flags & WBFLAG_PAM_FALLBACK_AFTER_KRB5) { DEBUG(3,("falling back to samlogon\n")); goto sam_logon; @@ -1544,7 +1544,7 @@ 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 */ @@ -1552,18 +1552,18 @@ sam_logon: info3->base.user_flags |= LOGON_KRB5_FAIL_CLOCK_SKEW; } goto process_result; - } + } - DEBUG(10,("winbindd_dual_pam_auth_samlogon failed: %s\n", + 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)) + 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; + goto cached_logon; } if (domain->online) { @@ -1574,9 +1574,9 @@ sam_logon: cached_logon: /* Check for Cached logons */ - if (!domain->online && (state->request.flags & WBFLAG_PAM_CACHED_LOGIN) && + if (!domain->online && (state->request.flags & WBFLAG_PAM_CACHED_LOGIN) && lp_winbind_offline_logon()) { - + result = winbindd_dual_pam_auth_cached(domain, state, &info3); if (NT_STATUS_IS_OK(result)) { @@ -1591,7 +1591,7 @@ cached_logon: process_result: if (NT_STATUS_IS_OK(result)) { - + DOM_SID user_sid; /* In all codepaths where result == NT_STATUS_OK info3 must have @@ -1608,19 +1608,19 @@ process_result: 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 ) { + if ( domain->primary ) { sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid); - cache_name2sid(domain, name_domain, name_user, + cache_name2sid(domain, name_domain, name_user, SID_NAME_USER, &user_sid); } - + /* Check if the user is in the right group */ if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, info3, state->request.data.auth.require_membership_of_sid))) { 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.user, state->request.data.auth.require_membership_of_sid)); goto done; } @@ -1665,8 +1665,8 @@ process_result: /* This is not entirely correct I believe, but it is consistent. Only apply the password policy settings - too warn users for our own domain. Cannot obtain these - from trusted DCs all the time so don't do it at all. + too warn users for our own domain. Cannot obtain these + from trusted DCs all the time so don't do it at all. -- jerry */ result = NT_STATUS_NOT_SUPPORTED; @@ -1674,16 +1674,16 @@ process_result: result = fillup_password_policy(our_domain, state); } - if (!NT_STATUS_IS_OK(result) - && !NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED) ) + if (!NT_STATUS_IS_OK(result) + && !NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED) ) { - DEBUG(10,("Failed to get password policies for domain %s: %s\n", + DEBUG(10,("Failed to get password policies for domain %s: %s\n", domain->name, nt_errstr(result))); goto done; } } - result = NT_STATUS_OK; + result = NT_STATUS_OK; } done: @@ -1692,26 +1692,26 @@ done: (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) + 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, + 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)); + state->response.data.auth.pam_error)); return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } /********************************************************************** - Challenge Response Authentication Protocol + Challenge Response Authentication Protocol **********************************************************************/ void winbindd_pam_auth_crap(struct winbindd_cli_state *state) @@ -1775,7 +1775,7 @@ void winbindd_pam_auth_crap(struct winbindd_cli_state *state) set_auth_errors(&state->response, result); DEBUG(5, ("CRAP authentication for %s\\%s returned %s (PAM: %d)\n", state->request.data.auth_crap.domain, - state->request.data.auth_crap.user, + state->request.data.auth_crap.user, state->response.data.auth.nt_status_string, state->response.data.auth.pam_error)); request_error(state); @@ -1784,7 +1784,7 @@ void winbindd_pam_auth_crap(struct winbindd_cli_state *state) enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, - struct winbindd_cli_state *state) + struct winbindd_cli_state *state) { NTSTATUS result; struct netr_SamInfo3 *info3 = NULL; @@ -1817,7 +1817,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, } else if (lp_winbind_use_default_domain()) { name_domain = lp_workgroup(); } else { - DEBUG(5,("no domain specified with username (%s) - failing auth\n", + DEBUG(5,("no domain specified with username (%s) - failing auth\n", name_user)); result = NT_STATUS_NO_SUCH_USER; goto done; @@ -1825,7 +1825,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, DEBUG(3, ("[%5lu]: pam auth crap domain: %s user: %s\n", (unsigned long)state->pid, name_domain, name_user)); - + if (*state->request.data.auth_crap.workstation) { workstation = state->request.data.auth_crap.workstation; } else { @@ -1834,8 +1834,8 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, 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, + 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; @@ -1847,11 +1847,11 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, state->request.data.auth_crap.nt_resp_len); /* what domain should we contact? */ - + if ( IS_DC ) { 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_crap.user, name_domain, name_user, name_domain)); + DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n", + state->request.data.auth_crap.user, name_domain, name_user, name_domain)); result = NT_STATUS_NO_SUCH_USER; goto done; } @@ -1887,7 +1887,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, state->request.data.auth_crap.logon_parameters, contact_domain->dcname, name_user, - name_domain, + name_domain, /* Bug #3248 - found by Stefan Burkei. */ workstation, /* We carefully set this above so use it... */ state->request.data.auth_crap.chal, @@ -1918,7 +1918,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, /* if we get access denied, a possible cause was that we had and open connection to the DC, but someone changed our machine account password out from underneath us using 'net rpc changetrustpw' */ - + if ( NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) ) { DEBUG(3,("winbindd_pam_auth: sam_logon returned " "ACCESS_DENIED. Maybe the trust account " @@ -1927,7 +1927,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, name_domain)); invalidate_cm_connection(&contact_domain->conn); retry = True; - } + } } while ( (attempts < 2) && retry ); @@ -1942,7 +1942,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, state->request.data.auth_crap.require_membership_of_sid))) { DEBUG(3, ("User %s is not in the required group (%s), so " "crap authentication is rejected\n", - state->request.data.auth_crap.user, + state->request.data.auth_crap.user, state->request.data.auth_crap.require_membership_of_sid)); goto done; } @@ -1974,12 +1974,12 @@ done: } state->response.data.auth.pam_error = nt_status_to_pam(result); - DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, - ("NTLM CRAP authentication for user [%s]\\[%s] returned %s (PAM: %d)\n", + DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, + ("NTLM CRAP authentication for user [%s]\\[%s] returned %s (PAM: %d)\n", name_domain, name_user, state->response.data.auth.nt_status_string, - state->response.data.auth.pam_error)); + state->response.data.auth.pam_error)); return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } @@ -2002,7 +2002,7 @@ void winbindd_pam_chauthtok(struct winbindd_cli_state *state) set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER); DEBUG(5, ("winbindd_pam_chauthtok: canonicalize_username %s failed with %s" "(PAM: %d)\n", - state->request.data.auth.user, + state->request.data.auth.user, state->response.data.auth.nt_status_string, state->response.data.auth.pam_error)); request_error(state); @@ -2012,8 +2012,8 @@ void winbindd_pam_chauthtok(struct winbindd_cli_state *state) contact_domain = find_domain_from_name(domain); if (!contact_domain) { set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER); - 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)); + 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)); request_error(state); return; } @@ -2092,18 +2092,18 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact DEBUG(10,("Password change with chgpasswd_user3 failed with: %s, retrying chgpasswd_user2\n", nt_errstr(result))); - + result = rpccli_samr_chgpasswd_user2(cli, state->mem_ctx, user, newpass, oldpass); /* Windows 2000 returns NT_STATUS_ACCOUNT_RESTRICTION. Map to the same status code as Windows 2003. */ if ( NT_STATUS_EQUAL(NT_STATUS_ACCOUNT_RESTRICTION, result ) ) { - result = NT_STATUS_PASSWORD_RESTRICTION; + result = NT_STATUS_PASSWORD_RESTRICTION; } } -done: +done: if (NT_STATUS_IS_OK(result) && (state->request.flags & WBFLAG_PAM_CACHED_LOGIN)) { @@ -2151,7 +2151,7 @@ done: if (!NT_STATUS_IS_OK(result) && !got_info && contact_domain) { NTSTATUS policy_ret; - + policy_ret = fillup_password_policy(contact_domain, state); /* failure of this is non critical, it will just provide no @@ -2171,12 +2171,12 @@ process_result: 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, - ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n", + DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, + ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n", domain, user, state->response.data.auth.nt_status_string, - state->response.data.auth.pam_error)); + state->response.data.auth.pam_error)); return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } @@ -2211,7 +2211,7 @@ void winbindd_pam_logoff(struct winbindd_cli_state *state) } if ((sys_getpeereid(state->sock, &caller_uid)) != 0) { - DEBUG(1,("winbindd_pam_logoff: failed to check peerid: %s\n", + DEBUG(1,("winbindd_pam_logoff: failed to check peerid: %s\n", strerror(errno))); goto failed; } @@ -2247,7 +2247,7 @@ void winbindd_pam_logoff(struct winbindd_cli_state *state) } enum winbindd_result winbindd_dual_pam_logoff(struct winbindd_domain *domain, - struct winbindd_cli_state *state) + struct winbindd_cli_state *state) { NTSTATUS result = NT_STATUS_NOT_SUPPORTED; @@ -2265,7 +2265,7 @@ enum winbindd_result winbindd_dual_pam_logoff(struct winbindd_domain *domain, } #ifdef HAVE_KRB5 - + if (state->request.data.logoff.uid < 0) { DEBUG(0,("winbindd_pam_logoff: invalid uid\n")); goto process_result; @@ -2280,7 +2280,7 @@ enum winbindd_result winbindd_dual_pam_logoff(struct winbindd_domain *domain, goto process_result; } - if (!ccache_entry_identical(state->request.data.logoff.user, + if (!ccache_entry_identical(state->request.data.logoff.user, state->request.data.logoff.uid, state->request.data.logoff.krb5ccname)) { DEBUG(0,("winbindd_pam_logoff: cached entry differs.\n")); @@ -2322,12 +2322,12 @@ void winbindd_pam_chng_pswd_auth_crap(struct winbindd_cli_state *state) sizeof(state->request.data.chng_pswd_auth_crap.user)-1]=0; state->request.data.chng_pswd_auth_crap.domain[ sizeof(state->request.data.chng_pswd_auth_crap.domain)-1]=0; - + DEBUG(3, ("[%5lu]: pam change pswd auth crap domain: %s user: %s\n", (unsigned long)state->pid, state->request.data.chng_pswd_auth_crap.domain, state->request.data.chng_pswd_auth_crap.user)); - + if (*state->request.data.chng_pswd_auth_crap.domain != '\0') { domain_name = state->request.data.chng_pswd_auth_crap.domain; } else if (lp_winbind_use_default_domain()) { @@ -2347,7 +2347,7 @@ void winbindd_pam_chng_pswd_auth_crap(struct winbindd_cli_state *state) set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER); DEBUG(5, ("CRAP change password for %s\\%s returned %s (PAM: %d)\n", state->request.data.chng_pswd_auth_crap.domain, - state->request.data.chng_pswd_auth_crap.user, + state->request.data.chng_pswd_auth_crap.user, state->response.data.auth.nt_status_string, state->response.data.auth.pam_error)); request_error(state); @@ -2373,7 +2373,7 @@ enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domai sizeof(state->request.data.chng_pswd_auth_crap.domain)-1]=0; *domain = 0; *user = 0; - + DEBUG(3, ("[%5lu]: pam change pswd auth crap domain: %s user: %s\n", (unsigned long)state->pid, state->request.data.chng_pswd_auth_crap.domain, @@ -2411,7 +2411,7 @@ enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domai DEBUG(3, ("[%5lu]: pam auth crap domain: %s user: %s\n", (unsigned long)state->pid, domain, user)); - + /* Change password */ new_nt_password = data_blob_talloc( state->mem_ctx, @@ -2450,18 +2450,18 @@ enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domai cli, state->mem_ctx, user, new_nt_password, old_nt_hash_enc, new_lm_password, old_lm_hash_enc); - done: + 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)); state->response.data.auth.pam_error = nt_status_to_pam(result); - DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, - ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n", + DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, + ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n", domain, user, state->response.data.auth.nt_status_string, - state->response.data.auth.pam_error)); + state->response.data.auth.pam_error)); return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } -- cgit From 4289e4b87805b95c4147cfd4cce4abbf19cd7f05 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 19 Aug 2008 18:31:10 +0200 Subject: winbindd: fill_in_password_policy (to avoid redundant code). Guenther (This used to be commit dbfa7ba14c9f1a4d7a1e7205dd0b3ea2fc2e6131) --- source3/winbindd/winbindd_pam.c | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 01cdc4d2e9..a808b37791 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -393,6 +393,21 @@ static void set_auth_errors(struct winbindd_response *resp, NTSTATUS result) resp->data.auth.pam_error = nt_status_to_pam(result); } +static void fill_in_password_policy(struct winbindd_response *r, + const struct samr_DomInfo1 *p) +{ + r->data.auth.policy.min_length_password = + p->min_password_length; + r->data.auth.policy.password_history = + p->password_history_length; + r->data.auth.policy.password_properties = + p->password_properties; + r->data.auth.policy.expire = + nt_time_to_unix_abs((NTTIME *)&(p->max_password_age)); + r->data.auth.policy.min_passwordage = + nt_time_to_unix_abs((NTTIME *)&(p->min_password_age)); +} + static NTSTATUS fillup_password_policy(struct winbindd_domain *domain, struct winbindd_cli_state *state) { @@ -413,16 +428,7 @@ static NTSTATUS fillup_password_policy(struct winbindd_domain *domain, return status; } - state->response.data.auth.policy.min_length_password = - password_policy.min_password_length; - state->response.data.auth.policy.password_history = - password_policy.password_history_length; - state->response.data.auth.policy.password_properties = - password_policy.password_properties; - state->response.data.auth.policy.expire = - nt_time_to_unix_abs((NTTIME *)&(password_policy.max_password_age)); - state->response.data.auth.policy.min_passwordage = - nt_time_to_unix_abs((NTTIME *)&(password_policy.min_password_age)); + fill_in_password_policy(&state->response, &password_policy); return NT_STATUS_OK; } @@ -2068,16 +2074,8 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact /* Windows 2003 returns NT_STATUS_PASSWORD_RESTRICTION */ if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION) ) { - state->response.data.auth.policy.min_length_password = - info->min_password_length; - state->response.data.auth.policy.password_history = - info->password_history_length; - state->response.data.auth.policy.password_properties = - info->password_properties; - state->response.data.auth.policy.expire = - nt_time_to_unix_abs((NTTIME *)&info->max_password_age); - state->response.data.auth.policy.min_passwordage = - nt_time_to_unix_abs((NTTIME *)&info->min_password_age); + + fill_in_password_policy(&state->response, info); state->response.data.auth.reject_reason = reject->reason; -- cgit From d9484d43318e5456ed9d177a399850bd6f949fcd Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 19 Aug 2008 18:31:35 +0200 Subject: winbindd: use set_auth_errors (avoid code duplication). Guenther (This used to be commit ae35a5110ea03d8ff27f320cdc685e5623715a2a) --- source3/winbindd/winbindd_pam.c | 34 ++++++---------------------------- 1 file changed, 6 insertions(+), 28 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index a808b37791..1cddfe391f 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1699,13 +1699,7 @@ done: 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); + set_auth_errors(&state->response, 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, @@ -1971,14 +1965,7 @@ done: result = nt_status_squash(result); } - 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); + set_auth_errors(&state->response, result); DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("NTLM CRAP authentication for user [%s]\\[%s] returned %s (PAM: %d)\n", @@ -2164,10 +2151,7 @@ done: process_result: - 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)); - state->response.data.auth.pam_error = nt_status_to_pam(result); + set_auth_errors(&state->response, result); DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n", @@ -2300,10 +2284,7 @@ process_result: winbindd_delete_memory_creds(state->request.data.logoff.user); - 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)); - state->response.data.auth.pam_error = nt_status_to_pam(result); + set_auth_errors(&state->response, result); return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } @@ -2449,11 +2430,8 @@ enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domai new_lm_password, old_lm_hash_enc); 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)); - state->response.data.auth.pam_error = nt_status_to_pam(result); + + set_auth_errors(&state->response, result); DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n", -- cgit From 477e6bb40d83dc53829cd8bdbb15ca9759872ca5 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 19 Aug 2008 18:03:13 +0200 Subject: winbindd: consistently use false/true. Guenther (This used to be commit e8619121d16d086f1ab186051d0ecdc83c02e5b5) --- source3/winbindd/winbindd_pam.c | 54 ++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 27 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 1cddfe391f..4beef852e9 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -176,7 +176,7 @@ static NTSTATUS append_unix_username(TALLOC_CTX *mem_ctx, } fill_domain_username(state->response.data.auth.unix_username, - nt_domain, nt_username, True); + nt_domain, nt_username, true); DEBUG(5,("Setting unix username to [%s]\n", state->response.data.auth.unix_username)); @@ -490,7 +490,7 @@ static const char *generate_krb5_ccache(TALLOC_CTX *mem_ctx, const char *gen_cc = NULL; - *internal_ccache = True; + *internal_ccache = true; if (uid == -1) { goto memory_ccache; @@ -509,7 +509,7 @@ static const char *generate_krb5_ccache(TALLOC_CTX *mem_ctx, goto memory_ccache; } - *internal_ccache = False; + *internal_ccache = false; goto done; memory_ccache: @@ -583,7 +583,7 @@ static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain, uid_t uid = -1; ADS_STRUCT *ads; time_t time_offset = 0; - bool internal_ccache = True; + bool internal_ccache = true; ZERO_STRUCTP(info3); @@ -650,8 +650,8 @@ static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain, &ticket_lifetime, &renewal_until, cc, - True, - True, + true, + true, WINBINDD_PAM_AUTH_KRB5_RENEW_TIME, info3); if (!internal_ccache) { @@ -683,7 +683,7 @@ static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain, time(NULL), ticket_lifetime, renewal_until, - False); + false); if (!NT_STATUS_IS_OK(result)) { DEBUG(10,("winbindd_raw_kerberos_login: failed to add ccache to list: %s\n", @@ -743,12 +743,12 @@ static bool check_request_flags(uint32_t flags) ( (flags & flags_edata) == WBFLAG_PAM_INFO3_NDR) || ( (flags & flags_edata) == WBFLAG_PAM_INFO3_TEXT)|| !(flags & flags_edata) ) { - return True; + return true; } DEBUG(1,("check_request_flags: invalid request flags[0x%08X]\n",flags)); - return False; + return false; } /**************************************************************** @@ -884,7 +884,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, const uint8 *cached_salt; struct netr_SamInfo3 *my_info3; time_t kickoff_time, must_change_time; - bool password_good = False; + bool password_good = false; #ifdef HAVE_KRB5 struct winbindd_tdc_domain *tdc_domain = NULL; #endif @@ -942,11 +942,11 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, E_md5hash(cached_salt, new_nt_pass, salted_hash); password_good = (memcmp(cached_nt_pass, salted_hash, NT_HASH_LEN) == 0) ? - True : False; + true : false; } else { /* Old cached cred - direct store of nt_hash (bad bad bad !). */ password_good = (memcmp(cached_nt_pass, new_nt_pass, NT_HASH_LEN) == 0) ? - True : False; + true : false; } if (password_good) { @@ -1005,7 +1005,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, char *realm = NULL; const char *principal_s = NULL; const char *service = NULL; - bool internal_ccache = False; + bool internal_ccache = false; uid = get_uid_from_state(state); if (uid == -1) { @@ -1047,7 +1047,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, time(NULL), time(NULL) + lp_winbind_cache_time(), time(NULL) + WINBINDD_PAM_AUTH_KRB5_RENEW_TIME, - True); + true); if (!NT_STATUS_IS_OK(result)) { DEBUG(10,("winbindd_dual_pam_auth_cached: failed " @@ -1306,7 +1306,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, netlogon_fn_t logon_fn; ZERO_STRUCTP(my_info3); - retry = False; + retry = false; result = cm_connect_netlogon(contact_domain, &netlogon_pipe); @@ -1357,8 +1357,8 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, && contact_domain->can_do_samlogon_ex) { DEBUG(3, ("Got a DC that can not do NetSamLogonEx, " "retrying with NetSamLogon\n")); - contact_domain->can_do_samlogon_ex = False; - retry = True; + contact_domain->can_do_samlogon_ex = false; + retry = true; continue; } @@ -1367,7 +1367,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, our connection. */ if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) { - retry = True; + retry = true; continue; } @@ -1383,7 +1383,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, "Killing connections to domain %s\n", name_domain)); invalidate_cm_connection(&contact_domain->conn); - retry = True; + retry = true; } } while ( (attempts < 2) && retry ); @@ -1481,7 +1481,7 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, parse_domain_user(state->request.data.auth.user, name_domain, name_user); - if (domain->online == False) { + 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 @@ -1867,7 +1867,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, do { netlogon_fn_t logon_fn; - retry = False; + retry = false; netlogon_pipe = NULL; result = cm_connect_netlogon(contact_domain, &netlogon_pipe); @@ -1899,8 +1899,8 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, && contact_domain->can_do_samlogon_ex) { DEBUG(3, ("Got a DC that can not do NetSamLogonEx, " "retrying with NetSamLogon\n")); - contact_domain->can_do_samlogon_ex = False; - retry = True; + contact_domain->can_do_samlogon_ex = false; + retry = true; continue; } @@ -1911,7 +1911,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, our connection. */ if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) { - retry = True; + retry = true; continue; } @@ -1926,7 +1926,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, "Killing connections to domain %s\n", name_domain)); invalidate_cm_connection(&contact_domain->conn); - retry = True; + retry = true; } } while ( (attempts < 2) && retry ); @@ -2021,7 +2021,7 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact char *newpass = NULL; POLICY_HND dom_pol; struct rpc_pipe_client *cli; - bool got_info = False; + bool got_info = false; struct samr_DomInfo1 *info = NULL; struct samr_ChangeReject *reject = NULL; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; @@ -2067,7 +2067,7 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact state->response.data.auth.reject_reason = reject->reason; - got_info = True; + got_info = true; } /* only fallback when the chgpasswd_user3 call is not supported */ -- cgit From 66fa77ba9ed50b114131b0c071dbe1fcb658b755 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 25 Aug 2008 13:15:41 +0200 Subject: winbindd: move set_auth_errors to util functions. Guenther (This used to be commit ae3fa60c4546c7420722d8f422c22bbfd623ff5b) --- source3/winbindd/winbindd_pam.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 4beef852e9..a7911f60aa 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -381,18 +381,6 @@ struct winbindd_domain *find_auth_domain(struct winbindd_cli_state *state, return find_our_domain(); } -static void set_auth_errors(struct winbindd_response *resp, NTSTATUS result) -{ - resp->data.auth.nt_status = NT_STATUS_V(result); - fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result)); - - /* we might have given a more useful error above */ - if (*resp->data.auth.error_string == '\0') - fstrcpy(resp->data.auth.error_string, - get_friendly_nt_error_msg(result)); - resp->data.auth.pam_error = nt_status_to_pam(result); -} - static void fill_in_password_policy(struct winbindd_response *r, const struct samr_DomInfo1 *p) { -- cgit From 29af730964e567a8391ee381aae3b9aaa7e5e7e1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 27 Aug 2008 17:29:10 -0700 Subject: Fix the wcache_invalidate_samlogon calls. Jeremy. (This used to be commit 7c820899ed1364fdaeb7b49e8ddd839e67397ec0) --- source3/winbindd/winbindd_pam.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/winbindd/winbindd_pam.c') diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index a7911f60aa..d4a2e3ed79 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1595,8 +1595,8 @@ process_result: goto done; } - netsamlogon_cache_store(name_user, info3); wcache_invalidate_samlogon(find_domain_from_name(name_domain), info3); + netsamlogon_cache_store(name_user, info3); /* save name_to_sid info as early as possible (only if this is our primary domain so we don't invalidate @@ -1921,8 +1921,8 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, if (NT_STATUS_IS_OK(result)) { - netsamlogon_cache_store(name_user, info3); wcache_invalidate_samlogon(find_domain_from_name(name_domain), info3); + netsamlogon_cache_store(name_user, info3); /* Check if the user is in the right group */ -- cgit