r22710: Support one-way trusts.
authorGerald Carter <jerry@samba.org>
Sun, 6 May 2007 20:16:12 +0000 (20:16 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:21:49 +0000 (12:21 -0500)
* 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.

source/nsswitch/winbindd_ads.c
source/nsswitch/winbindd_async.c
source/nsswitch/winbindd_cache.c
source/nsswitch/winbindd_dual.c
source/nsswitch/winbindd_pam.c
source/nsswitch/winbindd_rpc.c
source/nsswitch/winbindd_user.c
source/nsswitch/winbindd_util.c

index 4b6bca78344477485021f382a1344606839d8777..1f9748c37319306b67c9db2b50da9b951c42cc15 100644 (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)) ) {
index 1a68005efc8b8c286d5cd96f3584c188fc9eb28a..b674ef6ceec83ed9d3f76311f54cebdc6e2f157a 100644 (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,
index 7538cddbdffbad852909cfa76336ae118e2556b2..ceeb4988c2175aa7c55a8c033ccd761967578085 100644 (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);
index 8d475e6c9f9e95e7a179ecf7c71b8fc035e4c049..aa6b356679e87996770c54b70a1a30ee3bfcd5ba 100644 (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");
index 97c1ac4b9c392d701065ea5793676cb8beb4e50c..eb2da870c35422d723287155835c74deea3e6d7d 100644 (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);
index a66b05b79177f7f1156a9496d49fd674dc5ca5a6..0fafff196b38efd9d900b32fe26275ddc3f5e4d5 100644 (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;
index ce677198fff3c352ae1b2cf36769842d2a4aefcf..74dc291e0186ecdb7edea7635dbdaa57e9a30319 100644 (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);
 }
 
index d58fffd0dbe49fad00a756dfbf4624a424ccb1e8..231e11ae458e50d6e666e9b63cf7bf0224462d01 100644 (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 
  *