diff options
-rw-r--r-- | source3/auth/auth.c | 12 | ||||
-rw-r--r-- | source3/auth/auth_domain.c | 3 | ||||
-rw-r--r-- | source3/auth/auth_util.c | 8 | ||||
-rw-r--r-- | source3/lib/system_smbd.c | 24 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_cm.c | 3 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_group.c | 11 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_pam.c | 62 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_user.c | 11 | ||||
-rw-r--r-- | source3/rpc_server/srv_netlog_nt.c | 2 |
9 files changed, 108 insertions, 28 deletions
diff --git a/source3/auth/auth.c b/source3/auth/auth.c index 25b856cd57..c50fc1a9b7 100644 --- a/source3/auth/auth.c +++ b/source3/auth/auth.c @@ -269,9 +269,15 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context, } talloc_destroy(mem_ctx); - - if (NT_STATUS_IS_OK(nt_status)) - break; + + /* this sucks. Somehow we have to know if an authentication module is + authoritative for a user. Fixme!!! --jerry */ + + if ( NT_STATUS_IS_OK(nt_status) || + NT_STATUS_V(nt_status) == NT_STATUS_V(NT_STATUS_WRONG_PASSWORD) ) + { + break; + } } if (NT_STATUS_IS_OK(nt_status)) { diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index 84453ac3b5..39ec864f75 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -346,6 +346,8 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, user_info->lm_resp, user_info->nt_resp, &info3); + release_server_mutex(); + if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0,("domain_client_validate: unable to validate password " "for user %s in domain %s to Domain controller %s. " @@ -386,7 +388,6 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, cli_nt_session_close(cli); cli_ulogoff(cli); cli_shutdown(cli); - release_server_mutex(); return nt_status; } diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index fe4900f9f4..71fdb0050b 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -1031,15 +1031,17 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } - /* now that we have a SAM_ACCOUNT that looks real, make a server_info - to wrap it in, and use pass it on down */ - if (!NT_STATUS_IS_OK(nt_status = make_server_info(server_info))) { DEBUG(4, ("make_server_info failed!\n")); pdb_free_sam(&sam_account); return nt_status; } + /* save this here to _net_sam_logon() doesn't fail (it assumes a + valid SAM_ACCOUNT) */ + + (*server_info)->sam_account = sam_account; + /* Fill in the unix info we found on the way */ (*server_info)->sam_fill_level = SAM_FILL_ALL; diff --git a/source3/lib/system_smbd.c b/source3/lib/system_smbd.c index 3ae0a6395e..ca78031660 100644 --- a/source3/lib/system_smbd.c +++ b/source3/lib/system_smbd.c @@ -107,13 +107,31 @@ static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups, in int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grpcnt) { + char *p; + int retval; + + DEBUG(10,("sys_getgrouplist: user [%s]\n", user)); + + /* see if we should disable winbindd lookups for local users */ + if ( (p = strchr(user, *lp_winbind_separator())) == NULL ) { + if ( setenv(WINBINDD_DONT_ENV, "1", True) == -1 ) + DEBUG(0,("sys_getgroup_list: Insufficient environment space for %s\n", + WINBINDD_DONT_ENV)); + else + DEBUG(10,("sys_getgrouplist(): disabled winbindd for group lookup [user == %s]\n", + user)); + } + #ifdef HAVE_GETGROUPLIST - return getgrouplist(user, gid, groups, grpcnt); + retval = getgrouplist(user, gid, groups, grpcnt); #else - int retval; become_root(); retval = getgrouplist_internals(user, gid, groups, grpcnt); unbecome_root(); - return retval; #endif + + /* allow winbindd lookups */ + unsetenv( WINBINDD_DONT_ENV ); + + return retval; } diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c index 9f5bf3f11a..0cb0f0cb99 100644 --- a/source3/nsswitch/winbindd_cm.c +++ b/source3/nsswitch/winbindd_cm.c @@ -559,6 +559,9 @@ NTSTATUS cm_get_netlogon_cli(const char *domain, if (!(got_mutex = secrets_named_mutex(lock_name, WINBIND_SERVER_MUTEX_WAIT_TIME))) { DEBUG(0,("cm_get_netlogon_cli: mutex grab failed for %s\n", conn->controller)); } + + if ( sec_channel_type == SEC_CHAN_DOMAIN ) + snprintf(conn->cli->mach_acct, sizeof(conn->cli->mach_acct) - 1, "%s$", lp_workgroup()); result = cli_nt_establish_netlogon(conn->cli, sec_channel_type, trust_passwd); diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c index e4b0e78e2e..265297ca08 100644 --- a/source3/nsswitch/winbindd_group.c +++ b/source3/nsswitch/winbindd_group.c @@ -213,6 +213,17 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state) if (!parse_domain_user(tmp, name_domain, name_group)) return WINBINDD_ERROR; + /* don't handle our own domain if we are a DC. This code handles cases where + the account doesn't exist anywhere and gets passed on down the NSS layer */ + + if ( ((lp_server_role() == ROLE_DOMAIN_PDC) || (lp_server_role()==ROLE_DOMAIN_BDC)) && + strequal(name_domain, lp_workgroup()) ) + { + DEBUG(7,("winbindd_getgrnam: rejecting getpwnam() for %s\\%s since I am on the PDC for this domain\n", + name_domain, name_group)); + return WINBINDD_ERROR; + } + /* Get info for the domain */ if ((domain = find_domain_from_name(name_domain)) == NULL) { diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c index 7b93015b5d..a3b0849721 100644 --- a/source3/nsswitch/winbindd_pam.c +++ b/source3/nsswitch/winbindd_pam.c @@ -235,11 +235,52 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) DEBUG(3, ("[%5d]: pam auth crap domain: %s user: %s\n", state->pid, domain, user)); + + /* check our role as a domain member first */ + if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) { + if ( !lp_allow_trusted_domains() && !strequal(domain, lp_workgroup()) ) { + DEBUG(5,("winbindd_pam_auth_crap: failing autghentication becuase of disallowed trust domains\n")); + result = NT_STATUS_LOGON_FAILURE; + goto done; + } + + contact_domain = domain; - if (lp_allow_trusted_domains() && (state->request.data.auth_crap.flags & WINBIND_PAM_CONTACT_TRUSTDOM)) { + /* + * Get the machine account password for the domain to contact. + * This is either our own domain for a workstation, or possibly + * any domain for a PDC with trusted domains. + */ + + if (!secrets_fetch_trust_account_password (contact_domain, + trust_passwd, + &last_change_time, + &sec_channel_type)) { + DEBUG(0, ("winbindd_pam_auth_crap: could not fetch trust account " + "password for domain %s\n", contact_domain)); + result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + goto done; + } + } + else if ( lp_allow_trusted_domains() ) { + /* if we are not a domain member, then we must be a DC. Must never + see a logon for our domain */ + DOM_SID sid; + char *pwd; contact_domain = domain; - } else { - contact_domain = lp_workgroup(); + + if (!secrets_fetch_trusted_domain_password (contact_domain, + &pwd, &sid, + &last_change_time)) { + DEBUG(0, ("winbindd_pam_auth_crap: could not fetch trust account " + "password for domain %s\n", contact_domain)); + result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + goto done; + } + sec_channel_type = SEC_CHAN_DOMAIN; + E_md4hash(pwd, trust_passwd); + SAFE_FREE(pwd); + } if (*state->request.data.auth_crap.workstation) { @@ -264,21 +305,6 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) lm_resp = data_blob_talloc(mem_ctx, state->request.data.auth_crap.lm_resp, state->request.data.auth_crap.lm_resp_len); nt_resp = data_blob_talloc(mem_ctx, state->request.data.auth_crap.nt_resp, state->request.data.auth_crap.nt_resp_len); - /* - * Get the machine account password for the domain to contact. - * This is either our own domain for a workstation, or possibly - * any domain for a PDC with trusted domains. - */ - - if (!secrets_fetch_trust_account_password ( - contact_domain, trust_passwd, &last_change_time, - &sec_channel_type)) { - DEBUG(0, ("winbindd_pam_auth: could not fetch trust account " - "password for domain %s\n", contact_domain)); - result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - goto done; - } - do { ZERO_STRUCT(info3); ZERO_STRUCT(ret_creds); diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c index ccfddc83ba..518f335f27 100644 --- a/source3/nsswitch/winbindd_user.c +++ b/source3/nsswitch/winbindd_user.c @@ -115,6 +115,17 @@ enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state) name_user)) return WINBINDD_ERROR; + /* don't handle our own domain if we are a DC. This code handles cases where + the account doesn't exist anywhere and gets passed on down the NSS layer */ + + if ( ((lp_server_role() == ROLE_DOMAIN_PDC) || (lp_server_role()==ROLE_DOMAIN_BDC)) && + strequal(name_domain, lp_workgroup()) ) + { + DEBUG(7,("winbindd_getpwnam: rejecting getpwnam() for %s\\%s since I am on the PDC for this domain\n", + name_domain, name_user)); + return WINBINDD_ERROR; + } + if ((domain = find_domain_from_name(name_domain)) == NULL) { DEBUG(5, ("no such domain: %s\n", name_domain)); return WINBINDD_ERROR; diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c index aa573b8154..738ededde1 100644 --- a/source3/rpc_server/srv_netlog_nt.c +++ b/source3/rpc_server/srv_netlog_nt.c @@ -644,7 +644,9 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * p->dc.sess_key)) { status = NT_STATUS_NO_MEMORY; } else { + become_root(); status = auth_context->check_ntlm_password(auth_context, user_info, &server_info); + unbecome_root(); } (auth_context->free)(&auth_context); |