diff options
author | Andrew Bartlett <abartlet@samba.org> | 2004-01-08 08:19:18 +0000 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2004-01-08 08:19:18 +0000 |
commit | 7d068355aae99060acac03c6633509545aa782a4 (patch) | |
tree | fe5606d8c17978e6ff793d9dfe80668c4697acfc /source3/nsswitch | |
parent | c69e4746d08fb90d77cbe58b29801e25999b5774 (diff) | |
download | samba-7d068355aae99060acac03c6633509545aa782a4.tar.gz samba-7d068355aae99060acac03c6633509545aa782a4.tar.bz2 samba-7d068355aae99060acac03c6633509545aa782a4.zip |
This merges in my 'always use ADS' patch. Tested on a mix of NT and ADS
domains, this patch ensures that we always use the ADS backend when
security=ADS, and the remote server is capable.
The routines used for this behaviour have been upgraded to modern Samba
codeing standards.
This is a change in behaviour for mixed mode domains, and if the trusted
domain cannot be reached with our current krb5.conf file, we will show
that domain as disconnected.
This is in line with existing behaviour for native mode domains, and for
our primary domain.
As a consequence of testing this patch, I found that our kerberos error
handling was well below par - we would often throw away useful error
values. These changes move more routines to ADS_STATUS to return
kerberos errors.
Also found when valgrinding the setup, fix a few memory leaks.
While sniffing the resultant connections, I noticed we would query our
list of trusted domains twice - so I have reworked some of the code to
avoid that.
Andrew Bartlett
(This used to be commit 7c34de8096b86d2869e7177420fe129bd0c7541d)
Diffstat (limited to 'source3/nsswitch')
-rw-r--r-- | source3/nsswitch/wbinfo.c | 14 | ||||
-rw-r--r-- | source3/nsswitch/winbindd.c | 2 | ||||
-rw-r--r-- | source3/nsswitch/winbindd.h | 3 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_cache.c | 4 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_cm.c | 103 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_misc.c | 1 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_nss.h | 3 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_rpc.c | 13 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_util.c | 39 |
9 files changed, 146 insertions, 36 deletions
diff --git a/source3/nsswitch/wbinfo.c b/source3/nsswitch/wbinfo.c index 74f341a490..c7dc89d43f 100644 --- a/source3/nsswitch/wbinfo.c +++ b/source3/nsswitch/wbinfo.c @@ -298,18 +298,20 @@ static BOOL wbinfo_domain_info(const char *domain_name) /* Display response */ - d_printf("Name : %s\n", response.data.domain_info.name); - d_printf("Alt_Name: %s\n", response.data.domain_info.alt_name); + d_printf("Name : %s\n", response.data.domain_info.name); + d_printf("Alt_Name : %s\n", response.data.domain_info.alt_name); - d_printf("SID : %s\n", response.data.domain_info.sid); + d_printf("SID : %s\n", response.data.domain_info.sid); - d_printf("Native : %s\n", + d_printf("Active Directory : %s\n", + response.data.domain_info.active_directory ? "Yes" : "No"); + d_printf("Native : %s\n", response.data.domain_info.native_mode ? "Yes" : "No"); - d_printf("Primary : %s\n", + d_printf("Primary : %s\n", response.data.domain_info.primary ? "Yes" : "No"); - d_printf("Sequence: %d\n", response.data.domain_info.sequence_number); + d_printf("Sequence : %d\n", response.data.domain_info.sequence_number); return True; } diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c index 8ce528d2b0..4d5b08b4ec 100644 --- a/source3/nsswitch/winbindd.c +++ b/source3/nsswitch/winbindd.c @@ -935,6 +935,8 @@ int main(int argc, char **argv) netsamlogon_cache_init(); /* Non-critical */ + init_domain_list(); + /* Loop waiting for requests */ process_loop(); diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h index 5dbe422bc1..7c8e6256e1 100644 --- a/source3/nsswitch/winbindd.h +++ b/source3/nsswitch/winbindd.h @@ -95,7 +95,8 @@ struct winbindd_domain { fstring alt_name; /* alt Domain name (if any) */ DOM_SID sid; /* SID for this domain */ BOOL native_mode; /* is this a win2k domain in native mode ? */ - BOOL primary; /* is this our primary domain ? */ + BOOL active_directory; /* is this a win2k active directory ? */ + BOOL primary; /* is this our primary domain ? */ /* Lookup methods for this domain (LDAP or RPC) */ struct winbindd_methods *methods; diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c index 2df2ea6374..8dec89a6aa 100644 --- a/source3/nsswitch/winbindd_cache.c +++ b/source3/nsswitch/winbindd_cache.c @@ -112,7 +112,9 @@ static struct winbind_cache *get_cache(struct winbindd_domain *domain) break; } - if ( domain->native_mode ) { + /* if it have either of the indications of ADS, + use ads_methods */ + if ( domain->active_directory || domain->native_mode ) { domain->backend = &ads_methods; break; } diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c index 2b561be31d..53c91c01c7 100644 --- a/source3/nsswitch/winbindd_cm.c +++ b/source3/nsswitch/winbindd_cm.c @@ -174,16 +174,19 @@ static NTSTATUS cm_open_connection(const struct winbindd_domain *domain, const i if ((lp_security() == SEC_ADS) && (new_conn->cli->protocol >= PROTOCOL_NT1 && new_conn->cli->capabilities & CAP_EXTENDED_SECURITY)) { + ADS_STATUS ads_status; new_conn->cli->use_kerberos = True; DEBUG(5, ("connecting to %s from %s with kerberos principal [%s]\n", new_conn->controller, global_myname(), machine_krb5_principal)); - result = NT_STATUS_OK; - - if (!NT_STATUS_IS_OK(result = cli_session_setup_spnego(new_conn->cli, machine_krb5_principal, - machine_password, - lp_workgroup()))) { - DEBUG(4,("failed kerberos session setup with %s\n", nt_errstr(result))); + ads_status = cli_session_setup_spnego(new_conn->cli, machine_krb5_principal, + machine_password, + lp_workgroup()); + if (!ADS_ERR_OK(ads_status)) { + DEBUG(4,("failed kerberos session setup with %s\n", ads_errstr(ads_status))); + result = ads_ntstatus(ads_status); + } else { + result = NT_STATUS_OK; } } new_conn->cli->use_kerberos = False; @@ -405,46 +408,116 @@ static NTSTATUS get_connection_from_cache(struct winbindd_domain *domain, const } /********************************************************************************** + We can 'sense' certain things about the DC by it's replies to certain questions. + + This tells us if this particular remote server is Active Directory, and if it is + native mode. **********************************************************************************/ -BOOL cm_check_for_native_mode_win2k( struct winbindd_domain *domain ) +void set_dc_type_and_flags( struct winbindd_domain *domain ) { NTSTATUS result; struct winbindd_cm_conn conn; DS_DOMINFO_CTR ctr; - BOOL ret = False; + TALLOC_CTX *mem_ctx; ZERO_STRUCT( conn ); ZERO_STRUCT( ctr ); + domain->native_mode = False; + domain->active_directory = False; if ( !NT_STATUS_IS_OK(result = cm_open_connection(domain, PI_LSARPC_DS, &conn)) ) { - DEBUG(5, ("cm_check_for_native_mode_win2k: Could not open a connection to %s for PIPE_LSARPC (%s)\n", + DEBUG(5, ("set_dc_type_and_flags: Could not open a connection to %s for PIPE_LSARPC (%s)\n", domain->name, nt_errstr(result))); - return False; + return; } if ( conn.cli ) { if ( !NT_STATUS_IS_OK(cli_ds_getprimarydominfo( conn.cli, conn.cli->mem_ctx, DsRolePrimaryDomainInfoBasic, &ctr)) ) { - ret = False; goto done; } } if ( (ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) && !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) ) - ret = True; + domain->native_mode = True; -done: + /* Cheat - shut down the DS pipe, and open LSA */ + + cli_nt_session_close(conn.cli); + + if ( cli_nt_session_open (conn.cli, PI_LSARPC) ) { + char *domain_name = NULL; + char *dns_name = NULL; + DOM_SID *dom_sid = NULL; + + mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n", domain->name); + if (!mem_ctx) { + DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n")); + return; + } + + result = cli_lsa_open_policy2(conn.cli, mem_ctx, True, + SEC_RIGHTS_MAXIMUM_ALLOWED, + &conn.pol); + + if (NT_STATUS_IS_OK(result)) { + /* This particular query is exactly what Win2k clients use + to determine that the DC is active directory */ + result = cli_lsa_query_info_policy2(conn.cli, mem_ctx, + &conn.pol, + 12, &domain_name, + &dns_name, NULL, + NULL, &dom_sid); + } + + if (NT_STATUS_IS_OK(result)) { + if (domain_name) + fstrcpy(domain->name, domain_name); + + if (dns_name) + fstrcpy(domain->alt_name, dns_name); + if (dom_sid) + sid_copy(&domain->sid, dom_sid); + + domain->active_directory = True; + } else { + + result = cli_lsa_open_policy(conn.cli, mem_ctx, True, + SEC_RIGHTS_MAXIMUM_ALLOWED, + &conn.pol); + + if (!NT_STATUS_IS_OK(result)) + goto done; + + result = cli_lsa_query_info_policy(conn.cli, mem_ctx, + &conn.pol, 5, &domain_name, + &dom_sid); + + if (NT_STATUS_IS_OK(result)) { + if (domain_name) + fstrcpy(domain->name, domain_name); + + if (dom_sid) + sid_copy(&domain->sid, dom_sid); + } + } + } + +done: + /* close the connection; no other cals use this pipe and it is called only on reestablishing the domain list --jerry */ - + if ( conn.cli ) cli_shutdown( conn.cli ); - return ret; + talloc_destroy(mem_ctx); + + return; } diff --git a/source3/nsswitch/winbindd_misc.c b/source3/nsswitch/winbindd_misc.c index 95ca57a5e3..18478992f3 100644 --- a/source3/nsswitch/winbindd_misc.c +++ b/source3/nsswitch/winbindd_misc.c @@ -223,6 +223,7 @@ enum winbindd_result winbindd_domain_info(struct winbindd_cli_state *state) sid_string_static(&domain->sid)); state->response.data.domain_info.native_mode = domain->native_mode; + state->response.data.domain_info.active_directory = domain->active_directory; state->response.data.domain_info.primary = domain->primary; state->response.data.domain_info.sequence_number = diff --git a/source3/nsswitch/winbindd_nss.h b/source3/nsswitch/winbindd_nss.h index 0dd00e9b39..0d110b8afa 100644 --- a/source3/nsswitch/winbindd_nss.h +++ b/source3/nsswitch/winbindd_nss.h @@ -36,7 +36,7 @@ /* Update this when you change the interface. */ -#define WINBIND_INTERFACE_VERSION 8 +#define WINBIND_INTERFACE_VERSION 9 /* Socket commands */ @@ -272,6 +272,7 @@ struct winbindd_response { fstring alt_name; fstring sid; BOOL native_mode; + BOOL active_directory; BOOL primary; uint32 sequence_number; } domain_info; diff --git a/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c index f619aa3564..21e0c3092e 100644 --- a/source3/nsswitch/winbindd_rpc.c +++ b/source3/nsswitch/winbindd_rpc.c @@ -950,7 +950,8 @@ static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid) NTSTATUS result = NT_STATUS_UNSUCCESSFUL; TALLOC_CTX *mem_ctx; CLI_POLICY_HND *hnd; - fstring level5_dom; + char *level5_dom; + DOM_SID *alloc_sid; int retry; DEBUG(3,("rpc: domain_sid\n")); @@ -965,9 +966,17 @@ static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid) goto done; result = cli_lsa_query_info_policy(hnd->cli, mem_ctx, - &hnd->pol, 0x05, level5_dom, sid); + &hnd->pol, 0x05, &level5_dom, &alloc_sid); } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); + if (NT_STATUS_IS_OK(result)) { + if (alloc_sid) { + sid_copy(sid, alloc_sid); + } else { + result = NT_STATUS_NO_MEMORY; + } + } + done: talloc_destroy(mem_ctx); return result; diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c index 18946652e2..29a4ca93eb 100644 --- a/source3/nsswitch/winbindd_util.c +++ b/source3/nsswitch/winbindd_util.c @@ -49,6 +49,14 @@ static const fstring name_deadbeef = "<deadbeef>"; static struct winbindd_domain *_domain_list; +/** + When was the last scan of trusted domains done? + + 0 == not ever +*/ + +static time_t last_trustdom_scan; + struct winbindd_domain *domain_list(void) { /* Initialise list */ @@ -83,6 +91,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const { struct winbindd_domain *domain; const char *alternative_name = NULL; + static const DOM_SID null_sid; /* ignore alt_name if we are not in an AD domain */ @@ -103,6 +112,13 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const return domain; } } + if (sid) { + if (sid_equal(sid, &null_sid) ) { + + } else if (sid_equal(sid, &domain->sid)) { + return domain; + } + } } /* Create new domain entry */ @@ -134,12 +150,14 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const sid_copy(&domain->sid, sid); } - /* see if this is a native mode win2k domain */ + /* set flags about native_mode, active_directory */ - domain->native_mode = cm_check_for_native_mode_win2k( domain ); + set_dc_type_and_flags( domain ); - DEBUG(3,("add_trusted_domain: %s is a %s mode domain\n", domain->name, - domain->native_mode ? "native" : "mixed (or NT4)" )); + DEBUG(3,("add_trusted_domain: %s is an %s %s domain\n", domain->name, + domain->active_directory ? "ADS" : "NT4", + domain->native_mode ? "native mode" : + ((domain->active_directory && !domain->native_mode) ? "mixed mode" : ""))); /* Link to domain list */ DLIST_ADD(_domain_list, domain); @@ -157,13 +175,12 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const void rescan_trusted_domains( void ) { - static time_t last_scan; time_t now = time(NULL); struct winbindd_domain *mydomain = NULL; /* see if the time has come... */ - if ( (now > last_scan) && ((now-last_scan) < WINBINDD_RESCAN_FREQ) ) + if ( (now > last_trustdom_scan) && ((now-last_trustdom_scan) < WINBINDD_RESCAN_FREQ) ) return; if ( (mydomain = find_our_domain()) == NULL ) { @@ -175,7 +192,7 @@ void rescan_trusted_domains( void ) add_trusted_domains( mydomain ); - last_scan = now; + last_trustdom_scan = now; return; } @@ -222,7 +239,7 @@ void add_trusted_domains( struct winbindd_domain *domain ) for(i = 0; i < num_domains; i++) { DEBUG(10,("Found domain %s\n", names[i])); add_trusted_domain(names[i], alt_names?alt_names[i]:NULL, - domain->methods, &dom_sids[i]); + domain->methods, &dom_sids[i]); /* if the SID was empty, we better set it now */ @@ -264,7 +281,7 @@ BOOL init_domain_list(void) /* Free existing list */ free_domain_list(); - /* Add ourselves as the first entry. It *must* be the first entry */ + /* Add ourselves as the first entry. */ domain = add_trusted_domain( lp_workgroup(), lp_realm(), &cache_methods, NULL); @@ -287,7 +304,9 @@ BOOL init_domain_list(void) /* do an initial scan for trusted domains */ add_trusted_domains(domain); - + + /* avoid rescanning this right away */ + last_trustdom_scan = time(NULL); return True; } |