summaryrefslogtreecommitdiff
path: root/source3/nsswitch
diff options
context:
space:
mode:
Diffstat (limited to 'source3/nsswitch')
-rw-r--r--source3/nsswitch/winbindd.h8
-rw-r--r--source3/nsswitch/winbindd_ads.c119
-rw-r--r--source3/nsswitch/winbindd_cache.c15
-rw-r--r--source3/nsswitch/winbindd_cm.c22
-rw-r--r--source3/nsswitch/winbindd_rpc.c15
-rw-r--r--source3/nsswitch/winbindd_util.c118
6 files changed, 172 insertions, 125 deletions
diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h
index 11d399be49..dd92ecefe6 100644
--- a/source3/nsswitch/winbindd.h
+++ b/source3/nsswitch/winbindd.h
@@ -88,7 +88,7 @@ typedef struct {
struct winbindd_domain {
fstring name; /* Domain name */
- fstring full_name; /* full Domain name (realm) */
+ fstring alt_name; /* alt Domain name (if any) */
DOM_SID sid; /* SID for this domain */
/* Lookup methods for this domain (LDAP or RPC) */
@@ -170,11 +170,15 @@ struct winbindd_methods {
TALLOC_CTX *mem_ctx,
uint32 *num_domains,
char ***names,
+ char ***alt_names,
DOM_SID **dom_sids);
/* find the domain sid */
NTSTATUS (*domain_sid)(struct winbindd_domain *domain,
DOM_SID *sid);
+
+ /* setup the list of alternate names for the domain, if any */
+ NTSTATUS (*alternate_name)(struct winbindd_domain *domain);
};
/* Used to glue a policy handle and cli_state together */
@@ -190,6 +194,8 @@ typedef struct {
#include "rpc_client.h"
#define WINBINDD_ESTABLISH_LOOP 30
+#define WINBINDD_RESCAN_FREQ 300
+
#define DOM_SEQUENCE_NONE ((uint32)-1)
/* SETENV */
diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c
index b61348adfe..b0b70178a4 100644
--- a/source3/nsswitch/winbindd_ads.c
+++ b/source3/nsswitch/winbindd_ads.c
@@ -61,8 +61,8 @@ ADS_STATUS ads_do_search_retry(ADS_STRUCT *ads, const char *bind_path, int scope
if (*res) ads_msgfree(ads, *res);
*res = NULL;
- DEBUG(3,("Reopening ads connection to %s after error %s\n",
- ads->ldap_server, ads_errstr(status)));
+ DEBUG(3,("Reopening ads connection to realm '%s' after error %s\n",
+ ads->config.realm, ads_errstr(status)));
if (ads->ld) {
ldap_unbind(ads->ld);
}
@@ -87,7 +87,7 @@ ADS_STATUS ads_search_retry(ADS_STRUCT *ads, void **res,
const char *exp,
const char **attrs)
{
- return ads_do_search_retry(ads, ads->bind_path, LDAP_SCOPE_SUBTREE,
+ return ads_do_search_retry(ads, ads->config.bind_path, LDAP_SCOPE_SUBTREE,
exp, attrs, res);
}
@@ -108,8 +108,6 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
ADS_STRUCT *ads;
ADS_STATUS status;
char *ccache;
- struct in_addr server_ip;
- char *sname;
if (domain->private) {
return (ADS_STRUCT *)domain->private;
@@ -120,30 +118,23 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
SETENV("KRB5CCNAME", ccache, 1);
unlink(ccache);
- if (resolve_name(domain->name, &server_ip, 0x1b)) {
- sname = inet_ntoa(server_ip);
- } else if (resolve_name(domain->name, &server_ip, 0x1c)) {
- sname = inet_ntoa(server_ip);
- } else {
- if (strcasecmp(domain->name, lp_workgroup()) != 0) {
- DEBUG(1,("can't find domain controller for %s\n", domain->name));
- return NULL;
- }
- sname = NULL;
- }
-
- ads = ads_init(primary_realm, domain->name, NULL, NULL, NULL);
+ ads = ads_init(domain->alt_name, domain->name, NULL);
if (!ads) {
DEBUG(1,("ads_init for domain %s failed\n", domain->name));
return NULL;
}
/* the machine acct password might have change - fetch it every time */
- SAFE_FREE(ads->password);
- ads->password = secrets_fetch_machine_password();
+ SAFE_FREE(ads->auth.password);
+ ads->auth.password = secrets_fetch_machine_password();
+
+ if (primary_realm) {
+ SAFE_FREE(ads->auth.realm);
+ ads->auth.realm = strdup(primary_realm);
+ }
status = ads_connect(ads);
- if (!ADS_ERR_OK(status) || !ads->realm) {
+ if (!ADS_ERR_OK(status) || !ads->config.realm) {
extern struct winbindd_methods msrpc_methods;
DEBUG(1,("ads_connect for domain %s failed: %s\n",
domain->name, ads_errstr(status)));
@@ -161,11 +152,9 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
/* remember our primary realm for trusted domain support */
if (!primary_realm) {
- primary_realm = strdup(ads->realm);
+ primary_realm = strdup(ads->config.realm);
}
- fstrcpy(domain->full_name, ads->server_realm);
-
domain->private = (void *)ads;
return ads;
}
@@ -405,7 +394,7 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
/* accept either the win2000 or the pre-win2000 username */
asprintf(&exp, "(|(sAMAccountName=%s)(userPrincipalName=%s@%s))",
- name, name, ads->realm);
+ name, name, ads->config.realm);
rc = ads_search_retry(ads, &res, exp, attrs);
free(exp);
if (!ADS_ERR_OK(rc)) {
@@ -535,49 +524,6 @@ failed:
return False;
}
-
-/* convert a sid to a distnguished name */
-static NTSTATUS sid_to_distinguished_name(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- DOM_SID *sid,
- char **dn)
-{
- ADS_STRUCT *ads = NULL;
- const char *attrs[] = {"distinguishedName", NULL};
- ADS_STATUS rc;
- void *msg = NULL;
- char *exp;
- char *sidstr;
- NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
-
- DEBUG(3,("ads: sid_to_distinguished_name\n"));
-
- ads = ads_cached_connection(domain);
- if (!ads) goto done;
-
- sidstr = sid_binstring(sid);
- asprintf(&exp, "(objectSid=%s)", sidstr);
- rc = ads_search_retry(ads, &msg, exp, attrs);
- free(exp);
- free(sidstr);
- if (!ADS_ERR_OK(rc)) {
- DEBUG(1,("sid_to_distinguished_name ads_search: %s\n", ads_errstr(rc)));
- goto done;
- }
-
- *dn = ads_pull_string(ads, mem_ctx, msg, "distinguishedName");
-
- status = NT_STATUS_OK;
-
- DEBUG(3,("ads sid_to_distinguished_name mapped %s\n", *dn));
-
-done:
- if (msg) ads_msgfree(ads, msg);
-
- return status;
-}
-
-
/* Lookup user information from a rid */
static NTSTATUS query_user(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
@@ -831,6 +777,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
uint32 *num_domains,
char ***names,
+ char ***alt_names,
DOM_SID **dom_sids)
{
ADS_STRUCT *ads;
@@ -842,7 +789,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
ads = ads_cached_connection(domain);
if (!ads) return NT_STATUS_UNSUCCESSFUL;
- rc = ads_trusted_domains(ads, mem_ctx, num_domains, names, dom_sids);
+ rc = ads_trusted_domains(ads, mem_ctx, num_domains, names, alt_names, dom_sids);
return ads_ntstatus(rc);
}
@@ -867,6 +814,37 @@ static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
return ads_ntstatus(rc);
}
+
+/* find alternate names list for the domain - for ADS this is the
+ netbios name */
+static NTSTATUS alternate_name(struct winbindd_domain *domain)
+{
+ ADS_STRUCT *ads;
+ ADS_STATUS rc;
+ TALLOC_CTX *ctx;
+ char *workgroup;
+
+ ads = ads_cached_connection(domain);
+ if (!ads) return NT_STATUS_UNSUCCESSFUL;
+
+ if (!(ctx = talloc_init_named("alternate_name"))) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ rc = ads_workgroup_name(ads, ctx, &workgroup);
+
+ if (ADS_ERR_OK(rc)) {
+ fstrcpy(domain->name, workgroup);
+ fstrcpy(domain->alt_name, ads->config.realm);
+ strupper(domain->alt_name);
+ strupper(domain->name);
+ }
+
+ talloc_destroy(ctx);
+
+ return ads_ntstatus(rc);
+}
+
/* the ADS backend methods are exposed via this structure */
struct winbindd_methods ads_methods = {
True,
@@ -879,7 +857,8 @@ struct winbindd_methods ads_methods = {
lookup_groupmem,
sequence_number,
trusted_domains,
- domain_sid
+ domain_sid,
+ alternate_name
};
#endif
diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c
index a607727867..060139af3e 100644
--- a/source3/nsswitch/winbindd_cache.c
+++ b/source3/nsswitch/winbindd_cache.c
@@ -873,13 +873,14 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
uint32 *num_domains,
char ***names,
+ char ***alt_names,
DOM_SID **dom_sids)
{
struct winbind_cache *cache = get_cache(domain);
/* we don't cache this call */
return cache->backend->trusted_domains(domain, mem_ctx, num_domains,
- names, dom_sids);
+ names, alt_names, dom_sids);
}
/* find the domain sid */
@@ -891,6 +892,15 @@ static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
return cache->backend->domain_sid(domain, sid);
}
+/* find the alternate names for the domain, if any */
+static NTSTATUS alternate_name(struct winbindd_domain *domain)
+{
+ struct winbind_cache *cache = get_cache(domain);
+
+ /* we don't cache this call */
+ return cache->backend->alternate_name(domain);
+}
+
/* the ADS backend methods are exposed via this structure */
struct winbindd_methods cache_methods = {
True,
@@ -903,5 +913,6 @@ struct winbindd_methods cache_methods = {
lookup_groupmem,
sequence_number,
trusted_domains,
- domain_sid
+ domain_sid,
+ alternate_name
};
diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c
index 3175860a79..be28984791 100644
--- a/source3/nsswitch/winbindd_cm.c
+++ b/source3/nsswitch/winbindd_cm.c
@@ -97,12 +97,15 @@ struct get_dc_name_cache {
static BOOL cm_ads_find_dc(const char *domain, struct in_addr *dc_ip, fstring srv_name)
{
ADS_STRUCT *ads;
- ads = ads_init_simple();
+ ads = ads_init(domain, domain, NULL);
if (!ads) {
return False;
}
- DEBUG(4,("cm_ads_find_dc: realm=%s\n", ads->realm));
+ /* we don't need to bind, just connect */
+ ads->auth.no_bind = 1;
+
+ DEBUG(4,("cm_ads_find_dc: domain=%s\n", domain));
#ifdef HAVE_ADS
/* a full ads_connect() is actually overkill, as we don't srictly need
@@ -111,15 +114,15 @@ static BOOL cm_ads_find_dc(const char *domain, struct in_addr *dc_ip, fstring sr
ads_connect(ads);
#endif
- fstrcpy(srv_name, ads->ldap_server_name);
+ if (!ads->config.realm) {
+ return False;
+ }
+
+ fstrcpy(srv_name, ads->config.ldap_server_name);
strupper(srv_name);
*dc_ip = ads->ldap_ip;
ads_destroy(&ads);
- if (!*srv_name || is_zero_ip(*dc_ip)) {
- return False;
- }
-
DEBUG(4,("cm_ads_find_dc: using server='%s' IP=%s\n",
srv_name, inet_ntoa(*dc_ip)));
@@ -247,9 +250,12 @@ static BOOL cm_get_dc_name(const char *domain, fstring srv_name, struct in_addr
zero_ip(&dc_ip);
+ ret = False;
if (lp_security() == SEC_ADS) {
ret = cm_ads_find_dc(domain, &dc_ip, srv_name);
- } else {
+ }
+ if (!ret) {
+ /* fall back on rpc methods if the ADS methods fail */
ret = cm_rpc_find_dc(domain, &dc_ip, srv_name);
}
diff --git a/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c
index 2bb0e8c49f..5ec34f663d 100644
--- a/source3/nsswitch/winbindd_rpc.c
+++ b/source3/nsswitch/winbindd_rpc.c
@@ -575,22 +575,23 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
uint32 *num_domains,
char ***names,
+ char ***alt_names,
DOM_SID **dom_sids)
{
CLI_POLICY_HND *hnd;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
uint32 enum_ctx = 0;
- uint32 pref_num_domains = 5;
DEBUG(3,("rpc: trusted_domains\n"));
*num_domains = 0;
+ *alt_names = NULL;
if (!(hnd = cm_get_lsa_handle(lp_workgroup())))
goto done;
result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx,
- &hnd->pol, &enum_ctx, &pref_num_domains,
+ &hnd->pol, &enum_ctx,
num_domains, names, dom_sids);
done:
return result;
@@ -621,6 +622,13 @@ done:
return status;
}
+/* find alternate names list for the domain - none for rpc */
+static NTSTATUS alternate_name(struct winbindd_domain *domain)
+{
+ return NT_STATUS_OK;
+}
+
+
/* the rpc backend methods are exposed via this structure */
struct winbindd_methods msrpc_methods = {
False,
@@ -633,5 +641,6 @@ struct winbindd_methods msrpc_methods = {
lookup_groupmem,
sequence_number,
trusted_domains,
- domain_sid
+ domain_sid,
+ alternate_name
};
diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c
index b927380af8..daa3abb340 100644
--- a/source3/nsswitch/winbindd_util.c
+++ b/source3/nsswitch/winbindd_util.c
@@ -74,19 +74,17 @@ void free_domain_list(void)
}
/* Add a trusted domain to our list of domains */
-
-static struct winbindd_domain *add_trusted_domain(char *domain_name,
- struct winbindd_methods *methods)
+static struct winbindd_domain *add_trusted_domain(const char *domain_name, const char *alt_name,
+ struct winbindd_methods *methods,
+ DOM_SID *sid)
{
struct winbindd_domain *domain;
/* We can't call domain_list() as this function is called from
init_domain_list() and we'll get stuck in a loop. */
-
for (domain = _domain_list; domain; domain = domain->next) {
- if (strcmp(domain_name, domain->name) == 0) {
- DEBUG(3, ("domain %s already in domain list\n",
- domain_name));
+ if (strcmp(domain_name, domain->name) == 0 ||
+ strcmp(domain_name, domain->alt_name) == 0) {
return domain;
}
}
@@ -101,40 +99,95 @@ static struct winbindd_domain *add_trusted_domain(char *domain_name,
ZERO_STRUCTP(domain);
+ /* prioritise the short name */
+ if (strchr_m(domain_name, '.') && alt_name && *alt_name) {
+ fstrcpy(domain->name, alt_name);
+ fstrcpy(domain->alt_name, domain_name);
+ } else {
fstrcpy(domain->name, domain_name);
+ if (alt_name) {
+ fstrcpy(domain->alt_name, alt_name);
+ }
+ }
+
domain->methods = methods;
domain->sequence_number = DOM_SEQUENCE_NONE;
domain->last_seq_check = 0;
+ if (sid) {
+ sid_copy(&domain->sid, sid);
+ }
/* Link to domain list */
-
DLIST_ADD(_domain_list, domain);
+ DEBUG(1,("Added domain %s %s %s\n",
+ domain->name, domain->alt_name,
+ sid?sid_string_static(&domain->sid):""));
+
return domain;
}
-/* Look up global info for the winbind daemon */
+/*
+ rescan our domains looking for new trusted domains
+ */
+void rescan_trusted_domains(void)
+{
+ struct winbindd_domain *domain;
+ TALLOC_CTX *mem_ctx;
+ static time_t last_scan;
+ time_t t = time(NULL);
+
+ /* ony rescan every few minutes */
+ if ((unsigned)(t - last_scan) < WINBINDD_RESCAN_FREQ) {
+ return;
+ }
+ last_scan = time(NULL);
+
+ DEBUG(1, ("scanning trusted domain list\n"));
+
+ if (!(mem_ctx = talloc_init_named("init_domain_list")))
+ return;
+
+ for (domain = _domain_list; domain; domain = domain->next) {
+ NTSTATUS result;
+ char **names;
+ char **alt_names;
+ int num_domains = 0;
+ DOM_SID *dom_sids;
+ int i;
+
+ result = domain->methods->trusted_domains(domain, mem_ctx, &num_domains,
+ &names, &alt_names, &dom_sids);
+ if (!NT_STATUS_IS_OK(result)) {
+ continue;
+ }
+
+ /* Add each domain to the trusted domain list. Each domain inherits
+ the access methods of its parent */
+ 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]);
+ }
+ }
+
+ talloc_destroy(mem_ctx);
+}
+
+/* Look up global info for the winbind daemon */
BOOL init_domain_list(void)
{
NTSTATUS result;
- TALLOC_CTX *mem_ctx;
extern struct winbindd_methods cache_methods;
struct winbindd_domain *domain;
- DOM_SID *dom_sids;
- char **names;
- uint32 num_domains = 0;
-
- if (!(mem_ctx = talloc_init_named("init_domain_list")))
- return False;
/* Free existing list */
-
free_domain_list();
/* Add ourselves as the first entry */
-
- domain = add_trusted_domain(lp_workgroup(), &cache_methods);
+ domain = add_trusted_domain(lp_workgroup(), NULL, &cache_methods, NULL);
/* Now we *must* get the domain sid for our primary domain. Go into
a holding pattern until that is available */
@@ -147,29 +200,12 @@ BOOL init_domain_list(void)
result = cache_methods.domain_sid(domain, &domain->sid);
}
- DEBUG(1,("Added domain %s (%s)\n",
- domain->name,
- sid_string_static(&domain->sid)));
-
- DEBUG(1, ("getting trusted domain list\n"));
+ /* get any alternate name for the primary domain */
+ cache_methods.alternate_name(domain);
- result = cache_methods.trusted_domains(domain, mem_ctx, &num_domains,
- &names, &dom_sids);
+ /* do an initial scan for trusted domains */
+ rescan_trusted_domains();
- /* Add each domain to the trusted domain list */
- if (NT_STATUS_IS_OK(result)) {
- int i;
- for(i = 0; i < num_domains; i++) {
- domain = add_trusted_domain(names[i], &cache_methods);
- if (!domain) continue;
- sid_copy(&domain->sid, &dom_sids[i]);
- DEBUG(1,("Added domain %s (%s)\n",
- domain->name,
- sid_string_static(&domain->sid)));
- }
- }
-
- talloc_destroy(mem_ctx);
return True;
}
@@ -184,7 +220,7 @@ struct winbindd_domain *find_domain_from_name(const char *domain_name)
for (domain = domain_list(); domain != NULL; domain = domain->next) {
if (strequal(domain_name, domain->name) ||
- strequal(domain_name, domain->full_name))
+ (domain->alt_name[0] && strequal(domain_name, domain->alt_name)))
return domain;
}