1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-10 01:18:15 +03:00

r22710: Support one-way trusts.

* Rely on the fact that name2sid will work for any name
  in a trusted domain will work against our primary domain
  (even in the absense of an incoming trust path)

* Only logons will reliably work and the idmap backend
  is responsible for being able to manage id's without contacting
  the trusted domain

* "getent passwd" and "getent group" for trusted users and groups
  will work but we cannot get the group membership of a user in any
  fashion without the user first logging on (via NTLM or krb5)
  and the netsamlogon_cache being updated.
This commit is contained in:
Gerald Carter 2007-05-06 20:16:12 +00:00 committed by Gerald (Jerry) Carter
parent 3d2123383d
commit dee2bce2af
8 changed files with 290 additions and 20 deletions

View File

@ -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)) ) {

View File

@ -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,

View File

@ -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);

View File

@ -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");

View File

@ -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);

View File

@ -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;

View File

@ -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);
}

View File

@ -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
*