summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/auth/auth.c12
-rw-r--r--source3/auth/auth_domain.c3
-rw-r--r--source3/auth/auth_util.c8
-rw-r--r--source3/lib/system_smbd.c24
-rw-r--r--source3/nsswitch/winbindd_cm.c3
-rw-r--r--source3/nsswitch/winbindd_group.c11
-rw-r--r--source3/nsswitch/winbindd_pam.c62
-rw-r--r--source3/nsswitch/winbindd_user.c11
-rw-r--r--source3/rpc_server/srv_netlog_nt.c2
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);