summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/nsswitch/winbindd_ads.c113
-rw-r--r--source3/nsswitch/winbindd_async.c6
-rw-r--r--source3/nsswitch/winbindd_cache.c14
-rw-r--r--source3/nsswitch/winbindd_dual.c8
-rw-r--r--source3/nsswitch/winbindd_pam.c6
-rw-r--r--source3/nsswitch/winbindd_rpc.c83
-rw-r--r--source3/nsswitch/winbindd_user.c37
-rw-r--r--source3/nsswitch/winbindd_util.c43
8 files changed, 290 insertions, 20 deletions
diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c
index 4b6bca7834..1f9748c373 100644
--- a/source3/nsswitch/winbindd_ads.c
+++ b/source3/nsswitch/winbindd_ads.c
@@ -168,6 +168,12 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
DEBUG(3,("ads: query_user_list\n"));
+ if ( !winbindd_can_contact_domain( domain ) ) {
+ DEBUG(10,("query_user_list: No incoming trust for domain %s\n",
+ domain->name));
+ return NT_STATUS_OK;
+ }
+
ads = ads_cached_connection(domain);
if (!ads) {
@@ -213,7 +219,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
name = ads_pull_username(ads, mem_ctx, msg);
if ( ads_pull_sid( ads, msg, "objectSid", &user_sid ) ) {
- status = nss_get_info( domain->name, &user_sid, mem_ctx,
+ status = nss_get_info_cached( domain, &user_sid, mem_ctx,
ads, msg, &homedir, &shell, &gecos,
&primary_gid );
}
@@ -274,6 +280,12 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
DEBUG(3,("ads: enum_dom_groups\n"));
+ if ( !winbindd_can_contact_domain( domain ) ) {
+ DEBUG(10,("enum_dom_groups: No incoming trust for domain %s\n",
+ domain->name));
+ return NT_STATUS_OK;
+ }
+
/* only grab domain local groups for our domain */
if ( domain->active_directory && strequal(lp_realm(), domain->alt_name) ) {
enum_dom_local_groups = True;
@@ -449,9 +461,64 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
char *sidstr;
uint32 group_rid;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ uint32 user_rid;
+ NET_USER_INFO_3 *user;
DEBUG(3,("ads: query_user\n"));
+ info->homedir = NULL;
+ info->shell = NULL;
+ info->primary_gid = (gid_t)-1;
+
+ /* try netsamlogon cache first */
+
+ if ( (user = netsamlogon_cache_get( mem_ctx, sid )) != NULL )
+ {
+
+ DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
+ sid_string_static(sid)));
+
+ sid_compose(&info->user_sid, &domain->sid, user_rid);
+ sid_compose(&info->group_sid, &domain->sid, user->group_rid);
+
+ info->acct_name = unistr2_tdup(mem_ctx, &user->uni_user_name);
+ info->full_name = unistr2_tdup(mem_ctx, &user->uni_full_name);
+
+ nss_get_info_cached( domain, sid, mem_ctx, NULL, NULL,
+ &info->homedir, &info->shell, &info->full_name,
+ &info->primary_gid );
+
+ SAFE_FREE(user);
+
+ return NT_STATUS_OK;
+ }
+
+ if ( !winbindd_can_contact_domain(domain)) {
+ DEBUG(8,("query_user: No incoming trust from domain %s\n",
+ domain->name));
+
+ /* We still need to generate some basic information
+ about the user even if we cannot contact the
+ domain. Most of this stuff we can deduce. */
+
+ sid_copy( &info->user_sid, sid );
+
+ /* Assume "Domain Users" for the primary group */
+
+ sid_compose(&info->group_sid, &domain->sid, DOMAIN_GROUP_RID_USERS );
+
+ /* Try to fill in what the nss_info backend can do */
+
+ nss_get_info_cached( domain, sid, mem_ctx, NULL, NULL,
+ &info->homedir, &info->shell, &info->full_name,
+ &info->primary_gid );
+
+ status = NT_STATUS_OK;
+ goto done;
+ }
+
+ /* no cache...do the query */
+
if ( (ads = ads_cached_connection(domain)) == NULL ) {
domain->last_status = NT_STATUS_SERVER_DISABLED;
goto done;
@@ -477,9 +544,9 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
info->acct_name = ads_pull_username(ads, mem_ctx, msg);
- info->primary_gid = (gid_t)-1;
- nss_get_info( domain->name, sid, mem_ctx, ads, msg,
- &info->homedir, &info->shell, &info->full_name, &info->primary_gid );
+ nss_get_info_cached( domain, sid, mem_ctx, ads, msg,
+ &info->homedir, &info->shell, &info->full_name,
+ &info->primary_gid );
if (info->full_name == NULL) {
info->full_name = ads_pull_string(ads, mem_ctx, msg, "name");
@@ -525,6 +592,12 @@ static NTSTATUS lookup_usergroups_member(struct winbindd_domain *domain,
DEBUG(3,("ads: lookup_usergroups_member\n"));
+ if ( !winbindd_can_contact_domain( domain ) ) {
+ DEBUG(10,("lookup_usergroups_members: No incoming trust for domain %s\n",
+ domain->name));
+ return NT_STATUS_OK;
+ }
+
ads = ads_cached_connection(domain);
if (!ads) {
@@ -620,6 +693,12 @@ static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain,
DEBUG(3,("ads: lookup_usergroups_memberof\n"));
+ if ( !winbindd_can_contact_domain( domain ) ) {
+ DEBUG(10,("lookup_usergroups_memberof: No incoming trust for domain %s\n",
+ domain->name));
+ return NT_STATUS_OK;
+ }
+
ads = ads_cached_connection(domain);
if (!ads) {
@@ -726,6 +805,15 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
return NT_STATUS_OK;
}
+ if ( !winbindd_can_contact_domain( domain ) ) {
+ DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
+ domain->name));
+
+ /* Tell the cache manager not to remember this one */
+
+ return NT_STATUS_SYNCHRONIZATION_REQUIRED;
+ }
+
ads = ads_cached_connection(domain);
if (!ads) {
@@ -866,6 +954,12 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
*num_names = 0;
+ if ( !winbindd_can_contact_domain( domain ) ) {
+ DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
+ domain->name));
+ return NT_STATUS_OK;
+ }
+
ads = ads_cached_connection(domain);
if (!ads) {
@@ -982,6 +1076,13 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
DEBUG(3,("ads: fetch sequence_number for %s\n", domain->name));
+ if ( !winbindd_can_contact_domain( domain ) ) {
+ DEBUG(10,("sequence: No incoming trust for domain %s\n",
+ domain->name));
+ *seq = time(NULL);
+ return NT_STATUS_OK;
+ }
+
*seq = DOM_SEQUENCE_NONE;
ads = ads_cached_connection(domain);
@@ -1024,7 +1125,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
struct rpc_pipe_client *cli;
uint32 fr_flags = (DS_DOMAIN_IN_FOREST | DS_DOMAIN_TREE_ROOT);
int ret_count;
-
+
DEBUG(3,("ads: trusted_domains\n"));
*num_domains = 0;
@@ -1063,7 +1164,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
}
if ( NT_STATUS_IS_OK(result) && count) {
-
+
/* Allocate memory for trusted domain names and sids */
if ( !(*names = TALLOC_ARRAY(mem_ctx, char *, count)) ) {
diff --git a/source3/nsswitch/winbindd_async.c b/source3/nsswitch/winbindd_async.c
index 1a68005efc..b674ef6cee 100644
--- a/source3/nsswitch/winbindd_async.c
+++ b/source3/nsswitch/winbindd_async.c
@@ -1494,6 +1494,12 @@ static void query_user_recv(TALLOC_CTX *mem_ctx, BOOL success,
return;
}
+ if (response->result != WINBINDD_OK) {
+ DEBUG(5, ("query_user returned an error\n"));
+ cont(private_data, False, NULL, NULL, NULL, NULL, -1, -1);
+ return;
+ }
+
cont(private_data, True, response->data.user_info.acct_name,
response->data.user_info.full_name,
response->data.user_info.homedir,
diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c
index 7538cddbdf..ceeb4988c2 100644
--- a/source3/nsswitch/winbindd_cache.c
+++ b/source3/nsswitch/winbindd_cache.c
@@ -483,9 +483,17 @@ static void refresh_sequence_number(struct winbindd_domain *domain, BOOL force)
goto done;
/* important! make sure that we know if this is a native
- mode domain or not */
+ mode domain or not. And that we can contact it. */
+
+ if ( winbindd_can_contact_domain( domain ) ) {
+ status = domain->backend->sequence_number(domain,
+ &domain->sequence_number);
+ } else {
+ /* just use the current time */
+ status = NT_STATUS_OK;
+ domain->sequence_number = time(NULL);
+ }
- status = domain->backend->sequence_number(domain, &domain->sequence_number);
/* the above call could have set our domain->backend to NULL when
* coming from offline to online mode, make sure to reinitialize the
@@ -2197,7 +2205,7 @@ void wcache_invalidate_cache(void)
}
}
-static BOOL init_wcache(void)
+BOOL init_wcache(void)
{
if (wcache == NULL) {
wcache = SMB_XMALLOC_P(struct winbind_cache);
diff --git a/source3/nsswitch/winbindd_dual.c b/source3/nsswitch/winbindd_dual.c
index 8d475e6c9f..aa6b356679 100644
--- a/source3/nsswitch/winbindd_dual.c
+++ b/source3/nsswitch/winbindd_dual.c
@@ -653,6 +653,14 @@ static void account_lockout_policy_handler(struct event_context *ctx,
TALLOC_FREE(child->lockout_policy_event);
}
+ if ( !winbindd_can_contact_domain( child->domain ) ) {
+ DEBUG(10,("account_lockout_policy_handler: Removing myself since I "
+ "do not have an incoming trust to domain %s\n",
+ child->domain->name));
+
+ return;
+ }
+
methods = child->domain->methods;
mem_ctx = talloc_init("account_lockout_policy_handler ctx");
diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c
index 97c1ac4b9c..eb2da870c3 100644
--- a/source3/nsswitch/winbindd_pam.c
+++ b/source3/nsswitch/winbindd_pam.c
@@ -312,6 +312,12 @@ static NTSTATUS fillup_password_policy(struct winbindd_domain *domain,
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);
diff --git a/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c
index a66b05b791..0fafff196b 100644
--- a/source3/nsswitch/winbindd_rpc.c
+++ b/source3/nsswitch/winbindd_rpc.c
@@ -48,6 +48,12 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
*num_entries = 0;
*info = NULL;
+ if ( !winbindd_can_contact_domain( domain ) ) {
+ DEBUG(10,("query_user_list: No incoming trust for domain %s\n",
+ domain->name));
+ return NT_STATUS_OK;
+ }
+
result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
if (!NT_STATUS_IS_OK(result))
return result;
@@ -140,6 +146,12 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
DEBUG(3,("rpc: enum_dom_groups\n"));
+ if ( !winbindd_can_contact_domain( domain ) ) {
+ DEBUG(10,("enum_domain_groups: No incoming trust for domain %s\n",
+ domain->name));
+ return NT_STATUS_OK;
+ }
+
status = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
if (!NT_STATUS_IS_OK(status))
return status;
@@ -196,6 +208,12 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
DEBUG(3,("rpc: enum_local_groups\n"));
+ if ( !winbindd_can_contact_domain( domain ) ) {
+ DEBUG(10,("enum_local_groups: No incoming trust for domain %s\n",
+ domain->name));
+ return NT_STATUS_OK;
+ }
+
result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
if (!NT_STATUS_IS_OK(result))
return result;
@@ -305,13 +323,20 @@ NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
domain->name ));
result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
- if (!NT_STATUS_IS_OK(result))
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(2,("msrpc_sid_to_name: cm_connect_lsa() failed (%s)\n",
+ nt_errstr(result)));
return result;
+ }
+
result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
1, sid, &domains, &names, &types);
- if (!NT_STATUS_IS_OK(result))
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(2,("msrpc_sid_to_name: rpccli_lsa_lookup_sids() failed (%s)\n",
+ nt_errstr(result)));
return result;
+ }
*type = (enum lsa_SidType)types[0];
*domain_name = domains[0];
@@ -401,6 +426,10 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
return NT_STATUS_UNSUCCESSFUL;
+ user_info->homedir = NULL;
+ user_info->shell = NULL;
+ user_info->primary_gid = (gid_t)-1;
+
/* try netsamlogon cache first */
if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
@@ -418,12 +447,14 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
user_info->full_name = unistr2_tdup(mem_ctx,
&user->uni_full_name);
- user_info->homedir = NULL;
- user_info->shell = NULL;
- user_info->primary_gid = (gid_t)-1;
-
TALLOC_FREE(user);
+
+ return NT_STATUS_OK;
+ }
+ if ( !winbindd_can_contact_domain( domain ) ) {
+ DEBUG(10,("query_user: No incoming trust for domain %s\n",
+ domain->name));
return NT_STATUS_OK;
}
@@ -496,6 +527,15 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
return NT_STATUS_OK;
}
+ if ( !winbindd_can_contact_domain( domain ) ) {
+ DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
+ domain->name));
+
+ /* Tell the cache manager not to remember this one */
+
+ return NT_STATUS_SYNCHRONIZATION_REQUIRED;
+ }
+
/* no cache; hit the wire */
result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
@@ -552,6 +592,12 @@ NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
DEBUG(3,("rpc: lookup_useraliases\n"));
+ if ( !winbindd_can_contact_domain( domain ) ) {
+ DEBUG(10,("msrpc_lookup_useraliases: No incoming trust for domain %s\n",
+ domain->name));
+ return NT_STATUS_OK;
+ }
+
result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
if (!NT_STATUS_IS_OK(result))
return result;
@@ -638,6 +684,12 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
sid_to_string(sid_string, group_sid)));
+ if ( !winbindd_can_contact_domain( domain ) ) {
+ DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
+ domain->name));
+ return NT_STATUS_OK;
+ }
+
if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
return NT_STATUS_UNSUCCESSFUL;
@@ -822,6 +874,13 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
+ if ( !winbindd_can_contact_domain( domain ) ) {
+ DEBUG(10,("sequence_number: No incoming trust for domain %s\n",
+ domain->name));
+ *seq = time(NULL);
+ return NT_STATUS_OK;
+ }
+
*seq = DOM_SEQUENCE_NONE;
if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
@@ -967,6 +1026,12 @@ NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
+ if ( !winbindd_can_contact_domain( domain ) ) {
+ DEBUG(10,("msrpc_lockout_policy: No incoming trust for domain %s\n",
+ domain->name));
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
if (!NT_STATUS_IS_OK(result)) {
goto done;
@@ -999,6 +1064,12 @@ NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
+ if ( !winbindd_can_contact_domain( domain ) ) {
+ DEBUG(10,("msrpc_password_policy: No incoming trust for domain %s\n",
+ domain->name));
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
if (!NT_STATUS_IS_OK(result)) {
goto done;
diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c
index ce677198ff..74dc291e01 100644
--- a/source3/nsswitch/winbindd_user.c
+++ b/source3/nsswitch/winbindd_user.c
@@ -239,7 +239,30 @@ static void getpwsid_queryuser_recv(void *private_data, BOOL success,
return;
}
+ if ( acct_name && *acct_name ) {
fstrcpy( username, acct_name );
+ } else {
+ char *domain_name = NULL;
+ enum lsa_SidType type;
+ char *user_name = NULL;
+ struct winbindd_domain *domain = NULL;
+
+ domain = find_lookup_domain_from_sid(&s->user_sid);
+ winbindd_lookup_name_by_sid(s->state->mem_ctx, domain,
+ &s->user_sid, &domain_name,
+ &user_name, &type );
+
+ /* If this still fails we ar4e done. Just error out */
+ if ( !user_name ) {
+ DEBUG(5,("Could not obtain a name for SID %s\n",
+ sid_string_static(&s->user_sid)));
+ request_error(s->state);
+ return;
+ }
+
+ fstrcpy( username, user_name );
+ }
+
strlower_m( username );
s->username = talloc_strdup(s->state->mem_ctx, username);
@@ -360,11 +383,14 @@ void winbindd_getpwnam(struct winbindd_cli_state *state)
domain = find_domain_from_name(domname);
if (domain == NULL) {
- DEBUG(7, ("could not find domain entry for domain %s\n",
- domname));
+ DEBUG(7, ("could not find domain entry for domain %s. "
+ "Using primary domain\n", domname));
+ if ( (domain = find_our_domain()) == NULL ) {
+ DEBUG(0,("Cannot find my primary domain structure!\n"));
request_error(state);
return;
}
+ }
if ( strequal(domname, lp_workgroup()) && lp_winbind_trusted_domains_only() ) {
DEBUG(7,("winbindd_getpwnam: My domain -- rejecting getpwnam() for %s\\%s.\n",
@@ -384,6 +410,7 @@ static void getpwnam_name2sid_recv(void *private_data, BOOL success,
{
struct winbindd_cli_state *state =
(struct winbindd_cli_state *)private_data;
+ fstring domname, username;
if (!success) {
DEBUG(5, ("Could not lookup name for user %s\n",
@@ -398,6 +425,12 @@ static void getpwnam_name2sid_recv(void *private_data, BOOL success,
return;
}
+ if ( parse_domain_user(state->request.data.username, domname, username) ) {
+ check_domain_trusted( domname, sid );
+ }
+
+
+
winbindd_getpwsid(state, sid);
}
diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c
index d58fffd0db..231e11ae45 100644
--- a/source3/nsswitch/winbindd_util.c
+++ b/source3/nsswitch/winbindd_util.c
@@ -554,11 +554,11 @@ enum winbindd_result init_child_connection(struct winbindd_domain *domain,
state->continuation = continuation;
state->private_data = private_data;
- if (IS_DC || domain->primary) {
+ if (IS_DC || domain->primary || domain->internal ) {
/* The primary domain has to find the DC name itself */
request->cmd = WINBINDD_INIT_CONNECTION;
fstrcpy(request->domain_name, domain->name);
- request->data.init_conn.is_primary = True;
+ request->data.init_conn.is_primary = domain->internal ? False : True;
fstrcpy(request->data.init_conn.dcname, "");
async_request(mem_ctx, &domain->child, request, response,
init_child_recv, state);
@@ -572,7 +572,6 @@ enum winbindd_result init_child_connection(struct winbindd_domain *domain,
fstrcpy(request->domain_name, domain->name);
request_domain = find_our_domain();
-
async_domain_request(mem_ctx, request_domain, request, response,
init_child_getdc_recv, state);
return WINBINDD_PENDING;
@@ -728,6 +727,44 @@ BOOL init_domain_list(void)
return True;
}
+void check_domain_trusted( const char *name, const DOM_SID *user_sid )
+{
+ struct winbindd_domain *domain;
+ DOM_SID dom_sid;
+ uint32 rid;
+
+ domain = find_domain_from_name_noinit( name );
+ if ( domain )
+ return;
+
+ sid_copy( &dom_sid, user_sid );
+ if ( !sid_split_rid( &dom_sid, &rid ) )
+ return;
+
+ /* add the newly discovered trusted domain */
+
+ domain = add_trusted_domain( name, NULL, &cache_methods,
+ &dom_sid);
+
+ if ( !domain )
+ return;
+
+ /* assume this is a trust from a one-way transitive
+ forest trust */
+
+ domain->active_directory = True;
+ domain->domain_flags = DS_DOMAIN_DIRECT_OUTBOUND;
+ domain->domain_type = DS_DOMAIN_TRUST_TYPE_UPLEVEL;
+ domain->internal = False;
+ domain->online = True;
+
+ setup_domain_child(domain, &domain->child, NULL);
+
+ wcache_tdc_add_domain( domain );
+
+ return;
+}
+
/**
* Given a domain name, return the struct winbindd domain info for it
*