summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2004-04-20 02:37:49 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 10:51:17 -0500
commitf7cf0aaa6f5cb10f2a52b2b76efc0e4dbe6bea91 (patch)
treec6f53f29576d7e8cf96233c768cfa3dd3d932215
parent1f7900ebda8a89f71a6e7293b151effbc6c86d6f (diff)
downloadsamba-f7cf0aaa6f5cb10f2a52b2b76efc0e4dbe6bea91.tar.gz
samba-f7cf0aaa6f5cb10f2a52b2b76efc0e4dbe6bea91.tar.bz2
samba-f7cf0aaa6f5cb10f2a52b2b76efc0e4dbe6bea91.zip
r294: checking in volker's winbindd patches; tested on domain members (Samba and AD) as well as on a Samba DC
(This used to be commit 157d53782d6a7d0b7e30676a674ff2a25a15369c)
-rw-r--r--source3/nsswitch/winbindd.c2
-rw-r--r--source3/nsswitch/winbindd.h3
-rw-r--r--source3/nsswitch/winbindd_ads.c46
-rw-r--r--source3/nsswitch/winbindd_cache.c25
-rw-r--r--source3/nsswitch/winbindd_cm.c80
-rw-r--r--source3/nsswitch/winbindd_group.c17
-rw-r--r--source3/nsswitch/winbindd_passdb.c60
-rw-r--r--source3/nsswitch/winbindd_rpc.c21
-rw-r--r--source3/nsswitch/winbindd_sid.c8
-rw-r--r--source3/nsswitch/winbindd_user.c2
-rw-r--r--source3/nsswitch/winbindd_util.c104
11 files changed, 239 insertions, 129 deletions
diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c
index 283b2e4a89..a98bd29406 100644
--- a/source3/nsswitch/winbindd.c
+++ b/source3/nsswitch/winbindd.c
@@ -880,6 +880,8 @@ int main(int argc, char **argv)
if (!idmap_init(lp_idmap_backend()))
return 1;
+ generate_wellknown_sids();
+
/* Unblock all signals we are interested in as they may have been
blocked by the parent process. */
diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h
index 5c05a1b045..e884ea8380 100644
--- a/source3/nsswitch/winbindd.h
+++ b/source3/nsswitch/winbindd.h
@@ -94,6 +94,7 @@ struct winbindd_domain {
fstring name; /* Domain name */
fstring alt_name; /* alt Domain name (if any) */
DOM_SID sid; /* SID for this domain */
+ BOOL initialized; /* Did we already ask for the domain mode? */
BOOL native_mode; /* is this a win2k domain in native mode ? */
BOOL active_directory; /* is this a win2k active directory ? */
BOOL primary; /* is this our primary domain ? */
@@ -149,6 +150,7 @@ struct winbindd_methods {
/* convert one user or group name to a sid */
NTSTATUS (*name_to_sid)(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
+ const char *domain_name,
const char *name,
DOM_SID *sid,
enum SID_NAME_USE *type);
@@ -157,6 +159,7 @@ struct winbindd_methods {
NTSTATUS (*sid_to_name)(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
const DOM_SID *sid,
+ char **domain_name,
char **name,
enum SID_NAME_USE *type);
diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c
index cd8b8e0e24..2d3a9e760c 100644
--- a/source3/nsswitch/winbindd_ads.c
+++ b/source3/nsswitch/winbindd_ads.c
@@ -323,48 +323,6 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
return NT_STATUS_OK;
}
-/* convert a single name to a sid in a domain */
-static NTSTATUS name_to_sid(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- const char *name,
- DOM_SID *sid,
- enum SID_NAME_USE *type)
-{
- ADS_STRUCT *ads;
-
- DEBUG(3,("ads: name_to_sid\n"));
-
- ads = ads_cached_connection(domain);
-
- if (!ads) {
- domain->last_status = NT_STATUS_SERVER_DISABLED;
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- return ads_name_to_sid(ads, name, sid, type);
-}
-
-/* convert a sid to a user or group name */
-static NTSTATUS sid_to_name(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- const DOM_SID *sid,
- char **name,
- enum SID_NAME_USE *type)
-{
- ADS_STRUCT *ads = NULL;
- DEBUG(3,("ads: sid_to_name\n"));
-
- ads = ads_cached_connection(domain);
-
- if (!ads) {
- domain->last_status = NT_STATUS_SERVER_DISABLED;
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- return ads_sid_to_name(ads, mem_ctx, sid, name, type);
-}
-
-
/* convert a DN to a name, SID and name type
this might become a major speed bottleneck if groups have
lots of users, in which case we could cache the results
@@ -1004,8 +962,8 @@ struct winbindd_methods ads_methods = {
query_user_list,
enum_dom_groups,
enum_local_groups,
- name_to_sid,
- sid_to_name,
+ msrpc_name_to_sid,
+ msrpc_sid_to_name,
query_user,
lookup_usergroups,
lookup_groupmem,
diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c
index 43a0f9cf39..e10fa2255c 100644
--- a/source3/nsswitch/winbindd_cache.c
+++ b/source3/nsswitch/winbindd_cache.c
@@ -595,7 +595,7 @@ static void centry_end(struct cache_entry *centry, const char *format, ...)
}
static void wcache_save_name_to_sid(struct winbindd_domain *domain,
- NTSTATUS status,
+ NTSTATUS status, const char *domain_name,
const char *name, const DOM_SID *sid,
enum SID_NAME_USE type)
{
@@ -610,13 +610,13 @@ static void wcache_save_name_to_sid(struct winbindd_domain *domain,
centry_put_sid(centry, sid);
fstrcpy(uname, name);
strupper_m(uname);
- centry_end(centry, "NS/%s/%s", domain->name, uname);
+ centry_end(centry, "NS/%s/%s", domain_name, uname);
DEBUG(10,("wcache_save_name_to_sid: %s -> %s\n", uname, sid_string));
centry_free(centry);
}
static void wcache_save_sid_to_name(struct winbindd_domain *domain, NTSTATUS status,
- const DOM_SID *sid, const char *name, enum SID_NAME_USE type)
+ const DOM_SID *sid, const char *domain_name, const char *name, enum SID_NAME_USE type)
{
struct cache_entry *centry;
fstring sid_string;
@@ -626,6 +626,7 @@ static void wcache_save_sid_to_name(struct winbindd_domain *domain, NTSTATUS sta
return;
if (NT_STATUS_IS_OK(status)) {
centry_put_uint32(centry, type);
+ centry_put_string(centry, domain_name);
centry_put_string(centry, name);
}
centry_end(centry, "SN/%s", sid_to_string(sid_string, sid));
@@ -743,10 +744,12 @@ do_query:
/* when the backend is consistent we can pre-prime some mappings */
wcache_save_name_to_sid(domain, NT_STATUS_OK,
(*info)[i].acct_name,
+ domain->name,
(*info)[i].user_sid,
SID_NAME_USER);
wcache_save_sid_to_name(domain, NT_STATUS_OK,
(*info)[i].user_sid,
+ domain->name,
(*info)[i].acct_name,
SID_NAME_USER);
wcache_save_user(domain, NT_STATUS_OK, &(*info)[i]);
@@ -918,6 +921,7 @@ skip_save:
/* convert a single name to a sid in a domain */
static NTSTATUS name_to_sid(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
+ const char *domain_name,
const char *name,
DOM_SID *sid,
enum SID_NAME_USE *type)
@@ -933,7 +937,7 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
fstrcpy(uname, name);
strupper_m(uname);
- centry = wcache_fetch(cache, domain, "NS/%s/%s", domain->name, uname);
+ centry = wcache_fetch(cache, domain, "NS/%s/%s", domain_name, uname);
if (!centry)
goto do_query;
*type = (enum SID_NAME_USE)centry_uint32(centry);
@@ -969,10 +973,10 @@ do_query:
DEBUG(10,("name_to_sid: [Cached] - doing backend query for name for domain %s\n",
domain->name ));
- status = domain->backend->name_to_sid(domain, mem_ctx, name, sid, type);
+ status = domain->backend->name_to_sid(domain, mem_ctx, domain_name, name, sid, type);
/* and save it */
- wcache_save_name_to_sid(domain, status, name, sid, *type);
+ wcache_save_name_to_sid(domain, status, domain_name, name, sid, *type);
/* We can't save the sid to name mapping as we don't know the
correct case of the name without looking it up */
@@ -985,6 +989,7 @@ do_query:
static NTSTATUS sid_to_name(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
const DOM_SID *sid,
+ char **domain_name,
char **name,
enum SID_NAME_USE *type)
{
@@ -1001,6 +1006,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
goto do_query;
if (NT_STATUS_IS_OK(centry->status)) {
*type = (enum SID_NAME_USE)centry_uint32(centry);
+ *domain_name = centry_string(centry, mem_ctx);
*name = centry_string(centry, mem_ctx);
}
status = centry->status;
@@ -1013,6 +1019,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
do_query:
*name = NULL;
+ *domain_name = NULL;
/* If the seq number check indicated that there is a problem
* with this DC, then return that status... except for
@@ -1028,12 +1035,12 @@ do_query:
DEBUG(10,("sid_to_name: [Cached] - doing backend query for name for domain %s\n",
domain->name ));
- status = domain->backend->sid_to_name(domain, mem_ctx, sid, name, type);
+ status = domain->backend->sid_to_name(domain, mem_ctx, sid, domain_name, name, type);
/* and save it */
refresh_sequence_number(domain, False);
- wcache_save_sid_to_name(domain, status, sid, *name, *type);
- wcache_save_name_to_sid(domain, status, *name, sid, *type);
+ wcache_save_sid_to_name(domain, status, sid, *domain_name, *name, *type);
+ wcache_save_name_to_sid(domain, status, *domain_name, *name, sid, *type);
return status;
}
diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c
index 56810f221e..eda962088d 100644
--- a/source3/nsswitch/winbindd_cm.c
+++ b/source3/nsswitch/winbindd_cm.c
@@ -77,6 +77,9 @@ struct winbindd_cm_conn {
static struct winbindd_cm_conn *cm_conns = NULL;
+static NTSTATUS get_connection_from_cache(struct winbindd_domain *domain,
+ const char *pipe_name,
+ struct winbindd_cm_conn **conn_out);
/* Choose between anonymous or authenticated connections. We need to use
an authenticated connection if DCs have the RestrictAnonymous registry
@@ -133,6 +136,53 @@ static NTSTATUS setup_schannel(struct cli_state *cli)
return ret;
}
+static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
+ fstring dcname, struct in_addr *dc_ip)
+{
+ struct winbindd_domain *our_domain;
+ NTSTATUS result;
+ struct winbindd_cm_conn *conn;
+ TALLOC_CTX *mem_ctx;
+
+ fstring tmp;
+ char *p;
+
+ if (IS_DC)
+ return False;
+
+ if (domain->primary)
+ return False;
+
+ if ((our_domain = find_our_domain()) == NULL)
+ return False;
+
+ result = get_connection_from_cache(our_domain, PIPE_NETLOGON, &conn);
+ if (!NT_STATUS_IS_OK(result))
+ return False;
+
+ if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL)
+ return False;
+
+ result = cli_netlogon_getdcname(conn->cli, mem_ctx, domain->name, tmp);
+
+ talloc_destroy(mem_ctx);
+
+ if (!NT_STATUS_IS_OK(result))
+ return False;
+
+ /* cli_netlogon_getdcname gives us a name with \\ */
+ p = tmp;
+ if (*p == '\\') p+=1;
+ if (*p == '\\') p+=1;
+
+ fstrcpy(dcname, p);
+
+ if (!resolve_name(dcname, dc_ip, 0x20))
+ return False;
+
+ return True;
+}
+
/* Open a connction to the remote server, cache failures for 30 seconds */
static NTSTATUS cm_open_connection(const struct winbindd_domain *domain, const int pipe_index,
@@ -148,15 +198,19 @@ static NTSTATUS cm_open_connection(const struct winbindd_domain *domain, const i
ZERO_STRUCT(dc_ip);
fstrcpy(new_conn->domain, domain->name);
-
- /* connection failure cache has been moved inside of get_dc_name
- so we can deal with half dead DC's --jerry */
- if (!get_dc_name(domain->name, domain->alt_name[0] ? domain->alt_name : NULL,
- new_conn->controller, &dc_ip)) {
- result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
- add_failed_connection_entry(domain->name, "", result);
- return result;
+ if (!get_dc_name_via_netlogon(domain, new_conn->controller, &dc_ip)) {
+
+ /* connection failure cache has been moved inside of
+ get_dc_name so we can deal with half dead DC's --jerry */
+
+ if (!get_dc_name(domain->name, domain->alt_name[0] ?
+ domain->alt_name : NULL,
+ new_conn->controller, &dc_ip)) {
+ result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
+ add_failed_connection_entry(domain->name, "", result);
+ return result;
+ }
}
/* Initialise SMB connection */
@@ -282,7 +336,7 @@ static NTSTATUS cm_open_connection(const struct winbindd_domain *domain, const i
failed. This allows existing setups to continue working,
while solving the win2003 '100 user' limit for systems that
are joined properly */
- if (NT_STATUS_IS_OK(result)) {
+ if (NT_STATUS_IS_OK(result) && (domain->primary)) {
NTSTATUS status = setup_schannel(new_conn->cli);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3,("schannel refused - continuing without schannel (%s)\n",
@@ -461,10 +515,16 @@ void set_dc_type_and_flags( struct winbindd_domain *domain )
domain->native_mode = False;
domain->active_directory = False;
+
+ if (domain->internal) {
+ domain->initialized = True;
+ return;
+ }
if ( !NT_STATUS_IS_OK(result = cm_open_connection(domain, PI_LSARPC_DS, &conn)) ) {
DEBUG(5, ("set_dc_type_and_flags: Could not open a connection to %s for PIPE_LSARPC (%s)\n",
domain->name, nt_errstr(result)));
+ domain->initialized = True;
return;
}
@@ -551,6 +611,8 @@ done:
cli_shutdown( conn.cli );
talloc_destroy(mem_ctx);
+
+ domain->initialized = True;
return;
}
diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c
index 8f5306321a..ec77d2db34 100644
--- a/source3/nsswitch/winbindd_group.c
+++ b/source3/nsswitch/winbindd_group.c
@@ -292,7 +292,7 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state)
/* Get rid and name type from name */
- if (!winbindd_lookup_sid_by_name(domain, name_group, &group_sid,
+ if (!winbindd_lookup_sid_by_name(domain, domain->name, name_group, &group_sid,
&name_type)) {
DEBUG(1, ("group %s in domain %s does not exist\n",
name_group, name_domain));
@@ -446,17 +446,16 @@ enum winbindd_result winbindd_setgrent(struct winbindd_cli_state *state)
for (domain = domain_list(); domain != NULL; domain = domain->next) {
struct getent_state *domain_state;
-
+ /* Create a state record for this domain */
+
/* don't add our domaina if we are a PDC or if we
are a member of a Samba domain */
- if ( (IS_DC || lp_winbind_trusted_domains_only())
- && domain->primary )
+ if ( lp_winbind_trusted_domains_only() && domain->primary )
{
continue;
}
- /* Create a state record for this domain */
if ((domain_state = (struct getent_state *)
malloc(sizeof(struct getent_state))) == NULL) {
@@ -945,12 +944,10 @@ static void add_gids_from_sid(DOM_SID *sid, gid_t **gids, int *num)
if (NT_STATUS_IS_OK(idmap_sid_to_gid(sid, &gid, 0)))
add_gid_to_array_unique(gid, gids, num);
- /* Don't expand aliases if not explicitly activated -- for now */
- /* we don't support windows local nested groups if we are a DC.
- refer to to sid_to_gid() in the smbd server code to see why
+ /* Don't expand aliases if not explicitly activated -- for now
-- jerry */
- if (!lp_winbind_nested_groups() || IS_DC)
+ if (!lp_winbind_nested_groups())
return;
/* Add nested group memberships */
@@ -1021,7 +1018,7 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
/* Get rid and name type from name. The following costs 1 packet */
- if (!winbindd_lookup_sid_by_name(domain, name_user, &user_sid,
+ if (!winbindd_lookup_sid_by_name(domain, domain->name, name_user, &user_sid,
&name_type)) {
DEBUG(1, ("user '%s' does not exist\n", name_user));
goto done;
diff --git a/source3/nsswitch/winbindd_passdb.c b/source3/nsswitch/winbindd_passdb.c
index 36f5297efe..12f5e0bae2 100644
--- a/source3/nsswitch/winbindd_passdb.c
+++ b/source3/nsswitch/winbindd_passdb.c
@@ -52,6 +52,7 @@ add_expanded_sid(const DOM_SID *sid, char **members, int *num_members)
struct winbindd_domain *domain;
int i;
+ char *domain_name = NULL;
char *name = NULL;
enum SID_NAME_USE type;
@@ -72,7 +73,7 @@ add_expanded_sid(const DOM_SID *sid, char **members, int *num_members)
sid_copy(&dom_sid, sid);
sid_split_rid(&dom_sid, &rid);
- domain = find_domain_from_sid(&dom_sid);
+ domain = find_lookup_domain_from_sid(sid);
if (domain == NULL) {
DEBUG(3, ("Could not find domain for sid %s\n",
@@ -81,7 +82,7 @@ add_expanded_sid(const DOM_SID *sid, char **members, int *num_members)
}
result = domain->methods->sid_to_name(domain, mem_ctx, sid,
- &name, &type);
+ &domain_name, &name, &type);
if (!NT_STATUS_IS_OK(result)) {
DEBUG(3, ("sid_to_name failed for sid %s\n",
@@ -92,7 +93,7 @@ add_expanded_sid(const DOM_SID *sid, char **members, int *num_members)
DEBUG(10, ("Found name %s, type %d\n", name, type));
if (type == SID_NAME_USER) {
- add_member(domain->name, name, members, num_members);
+ add_member(domain_name, name, members, num_members);
goto done;
}
@@ -102,7 +103,15 @@ add_expanded_sid(const DOM_SID *sid, char **members, int *num_members)
goto done;
}
- /* Expand the domain group */
+ /* Expand the domain group, this must be done via the target domain */
+
+ domain = find_domain_from_sid(sid);
+
+ if (domain == NULL) {
+ DEBUG(3, ("Could not find domain from SID %s\n",
+ sid_string_static(sid)));
+ goto done;
+ }
result = domain->methods->lookup_groupmem(domain, mem_ctx,
sid, &num_names,
@@ -221,6 +230,7 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
/* convert a single name to a sid in a domain */
static NTSTATUS name_to_sid(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
+ const char *domain_name,
const char *name,
DOM_SID *sid,
enum SID_NAME_USE *type)
@@ -240,6 +250,7 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
static NTSTATUS sid_to_name(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
const DOM_SID *sid,
+ char **domain_name,
char **name,
enum SID_NAME_USE *type)
{
@@ -250,6 +261,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
if (!pdb_get_aliasinfo(sid, &info))
return NT_STATUS_NONE_MAPPED;
+ *domain_name = talloc_strdup(mem_ctx, domain->name);
*name = talloc_strdup(mem_ctx, info.acct_name);
*type = SID_NAME_ALIAS;
@@ -300,7 +312,45 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
char ***alt_names,
DOM_SID **dom_sids)
{
- return NT_STATUS_OK;
+ NTSTATUS nt_status;
+ int enum_ctx = 0;
+ int num_sec_domains;
+ TRUSTDOM **domains;
+ *num_domains = 0;
+ *names = NULL;
+ *alt_names = NULL;
+ *dom_sids = NULL;
+ do {
+ int i;
+ nt_status = secrets_get_trusted_domains(mem_ctx, &enum_ctx, 1,
+ &num_sec_domains,
+ &domains);
+ *names = talloc_realloc(mem_ctx, *names,
+ sizeof(*names) *
+ (num_sec_domains + *num_domains));
+ *alt_names = talloc_realloc(mem_ctx, *alt_names,
+ sizeof(*alt_names) *
+ (num_sec_domains + *num_domains));
+ *dom_sids = talloc_realloc(mem_ctx, *dom_sids,
+ sizeof(**dom_sids) *
+ (num_sec_domains + *num_domains));
+
+ for (i=0; i< num_sec_domains; i++) {
+ if (pull_ucs2_talloc(mem_ctx, &(*names)[*num_domains],
+ domains[i]->name) == -1) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ (*alt_names)[*num_domains] = NULL;
+ (*dom_sids)[*num_domains] = domains[i]->sid;
+ (*num_domains)++;
+ }
+
+ } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
+
+ if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_MORE_ENTRIES)) {
+ return NT_STATUS_OK;
+ }
+ return nt_status;
}
/* find the domain sid for a domain */
diff --git a/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c
index 25d5f64df6..7668844920 100644
--- a/source3/nsswitch/winbindd_rpc.c
+++ b/source3/nsswitch/winbindd_rpc.c
@@ -274,8 +274,9 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
}
/* convert a single name to a sid in a domain */
-static NTSTATUS name_to_sid(struct winbindd_domain *domain,
+NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
+ const char *domain_name,
const char *name,
DOM_SID *sid,
enum SID_NAME_USE *type)
@@ -289,14 +290,14 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
DEBUG(3,("rpc: name_to_sid name=%s\n", name));
- full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain->name, name);
+ full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
if (!full_name) {
DEBUG(0, ("talloc_asprintf failed!\n"));
return NT_STATUS_NO_MEMORY;
}
- DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", name, domain->name ));
+ DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", name, domain_name ));
retry = 0;
do {
@@ -322,9 +323,10 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
/*
convert a domain SID to a user or group name
*/
-static NTSTATUS sid_to_name(struct winbindd_domain *domain,
+NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
const DOM_SID *sid,
+ char **domain_name,
char **name,
enum SID_NAME_USE *type)
{
@@ -350,14 +352,9 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
if (NT_STATUS_IS_OK(result)) {
*type = (enum SID_NAME_USE)types[0];
+ *domain_name = domains[0];
*name = names[0];
DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
-
- /* Paranoia */
- if (!strequal(domain->name, domains[0])) {
- DEBUG(1, ("domain name from domain param and PDC lookup return differ! (%s vs %s)\n", domain->name, domains[0]));
- return NT_STATUS_UNSUCCESSFUL;
- }
}
return result;
@@ -995,8 +992,8 @@ struct winbindd_methods msrpc_methods = {
query_user_list,
enum_dom_groups,
enum_local_groups,
- name_to_sid,
- sid_to_name,
+ msrpc_name_to_sid,
+ msrpc_sid_to_name,
query_user,
lookup_usergroups,
lookup_groupmem,
diff --git a/source3/nsswitch/winbindd_sid.c b/source3/nsswitch/winbindd_sid.c
index d4206558c5..61da9b3d92 100644
--- a/source3/nsswitch/winbindd_sid.c
+++ b/source3/nsswitch/winbindd_sid.c
@@ -95,14 +95,14 @@ enum winbindd_result winbindd_lookupname(struct winbindd_cli_state *state)
DEBUG(3, ("[%5lu]: lookupname %s%s%s\n", (unsigned long)state->pid,
name_domain, lp_winbind_separator(), name_user));
- if ((domain = find_domain_from_name(name_domain)) == NULL) {
+ if ((domain = find_lookup_domain_from_name(name_domain)) == NULL) {
DEBUG(0, ("could not find domain entry for domain %s\n",
name_domain));
return WINBINDD_ERROR;
}
/* Lookup name from PDC using lsa_lookup_names() */
- if (!winbindd_lookup_sid_by_name(domain, name_user, &sid, &type)) {
+ if (!winbindd_lookup_sid_by_name(domain, name_domain, name_user, &sid, &type)) {
return WINBINDD_ERROR;
}
@@ -335,7 +335,7 @@ enum winbindd_result winbindd_uid_to_sid(struct winbindd_cli_state *state)
return WINBINDD_ERROR;
}
- if ( !winbindd_lookup_sid_by_name(domain, pw->pw_name, &sid, &type) )
+ if ( !winbindd_lookup_sid_by_name(domain, domain->name, pw->pw_name, &sid, &type) )
return WINBINDD_ERROR;
if ( type != SID_NAME_USER )
@@ -405,7 +405,7 @@ enum winbindd_result winbindd_gid_to_sid(struct winbindd_cli_state *state)
return WINBINDD_ERROR;
}
- if ( !winbindd_lookup_sid_by_name(domain, grp->gr_name, &sid, &type) )
+ if ( !winbindd_lookup_sid_by_name(domain, domain->name, grp->gr_name, &sid, &type) )
return WINBINDD_ERROR;
if ( type!=SID_NAME_DOM_GRP && type!=SID_NAME_ALIAS )
diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c
index d08377c888..d10fd5664b 100644
--- a/source3/nsswitch/winbindd_user.c
+++ b/source3/nsswitch/winbindd_user.c
@@ -153,7 +153,7 @@ enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state)
/* Get rid and name type from name */
- if (!winbindd_lookup_sid_by_name(domain, name_user, &user_sid, &name_type)) {
+ if (!winbindd_lookup_sid_by_name(domain, domain->name, name_user, &user_sid, &name_type)) {
DEBUG(1, ("user '%s' does not exist\n", name_user));
return WINBINDD_ERROR;
}
diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c
index 7e3fd99dac..96b8ed8c93 100644
--- a/source3/nsswitch/winbindd_util.c
+++ b/source3/nsswitch/winbindd_util.c
@@ -85,13 +85,15 @@ void free_domain_list(void)
static BOOL is_internal_domain(const DOM_SID *sid)
{
- DOM_SID tmp_sid;
+ extern DOM_SID global_sid_Builtin;
- if (sid_equal(sid, get_global_sam_sid()))
+ if (sid == NULL)
+ return False;
+
+ if (sid_compare_domain(sid, get_global_sam_sid()) == 0)
return True;
- string_to_sid(&tmp_sid, "S-1-5-32");
- if (sid_equal(sid, &tmp_sid))
+ if (sid_compare_domain(sid, &global_sid_Builtin) == 0)
return True;
return False;
@@ -160,15 +162,11 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
domain->internal = is_internal_domain(sid);
domain->sequence_number = DOM_SEQUENCE_NONE;
domain->last_seq_check = 0;
+ domain->initialized = False;
if (sid) {
sid_copy(&domain->sid, sid);
}
- /* set flags about native_mode, active_directory */
-
- if (!domain->internal)
- set_dc_type_and_flags( domain );
-
DEBUG(3,("add_trusted_domain: %s is an %s %s domain\n", domain->name,
domain->active_directory ? "ADS" : "NT4",
domain->native_mode ? "native mode" :
@@ -190,6 +188,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
static void add_trusted_domains( struct winbindd_domain *domain )
{
+ extern struct winbindd_methods cache_methods;
TALLOC_CTX *mem_ctx;
NTSTATUS result;
time_t t;
@@ -226,7 +225,7 @@ static 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]);
+ &cache_methods, &dom_sids[i]);
/* if the SID was empty, we better set it now */
@@ -290,16 +289,28 @@ void rescan_trusted_domains( void )
/* Look up global info for the winbind daemon */
BOOL init_domain_list(void)
{
+ extern DOM_SID global_sid_Builtin;
extern struct winbindd_methods cache_methods;
+ extern struct winbindd_methods passdb_methods;
struct winbindd_domain *domain;
/* Free existing list */
free_domain_list();
/* Add ourselves as the first entry. */
+
+ if (IS_DC) {
+ domain = add_trusted_domain(get_global_sam_name(), NULL,
+ &passdb_methods, get_global_sam_sid());
+ } else {
- domain = add_trusted_domain( lp_workgroup(), lp_realm(), &cache_methods, NULL);
+ domain = add_trusted_domain( lp_workgroup(), lp_realm(),
+ &cache_methods, NULL);
+ /* set flags about native_mode, active_directory */
+ set_dc_type_and_flags(domain);
+ }
+
domain->primary = True;
/* get any alternate name for the primary domain */
@@ -320,27 +331,15 @@ BOOL init_domain_list(void)
/* do an initial scan for trusted domains */
add_trusted_domains(domain);
- /* Don't expand aliases if not explicitly activated -- for now */
- /* we don't support windows local nested groups if we are a DC.
- refer to to sid_to_gid() in the smbd server code to see why
- -- jerry */
-
- if (lp_winbind_nested_groups() || IS_DC) {
+ /* Add our local SAM domains */
- /* Add our local SAM domains */
- DOM_SID sid;
- extern struct winbindd_methods passdb_methods;
- struct winbindd_domain *dom;
+ add_trusted_domain("BUILTIN", NULL, &passdb_methods,
+ &global_sid_Builtin);
- string_to_sid(&sid, "S-1-5-32");
-
- dom = add_trusted_domain("BUILTIN", NULL, &passdb_methods,
- &sid);
-
- dom = add_trusted_domain(get_global_sam_name(), NULL,
- &passdb_methods,
- get_global_sam_sid());
+ if (!IS_DC) {
+ add_trusted_domain(get_global_sam_name(), NULL,
+ &passdb_methods, get_global_sam_sid());
}
/* avoid rescanning this right away */
@@ -369,6 +368,9 @@ 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) ||
(domain->alt_name[0] && strequal(domain_name, domain->alt_name))) {
+ if (!domain->initialized)
+ set_dc_type_and_flags(domain);
+
return domain;
}
}
@@ -387,8 +389,11 @@ struct winbindd_domain *find_domain_from_sid(const DOM_SID *sid)
/* Search through list */
for (domain = domain_list(); domain != NULL; domain = domain->next) {
- if (sid_compare_domain(sid, &domain->sid) == 0)
+ if (sid_compare_domain(sid, &domain->sid) == 0) {
+ if (!domain->initialized)
+ set_dc_type_and_flags(domain);
return domain;
+ }
}
/* Not found */
@@ -414,21 +419,49 @@ struct winbindd_domain *find_our_domain(void)
return NULL;
}
+/* Find the appropriate domain to lookup a name or SID */
+
+struct winbindd_domain *find_lookup_domain_from_sid(const DOM_SID *sid)
+{
+ /* A DC can't ask the local smbd for remote SIDs, here winbindd is the
+ * one to contact the external DC's. On member servers the internal
+ * domains are different: These are part of the local SAM. */
+
+ if (IS_DC || is_internal_domain(sid))
+ return find_domain_from_sid(sid);
+
+ /* On a member server a query for SID or name can always go to our
+ * primary DC. */
+
+ return find_our_domain();
+}
+
+struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name)
+{
+ if (IS_DC || strequal(domain_name, "BUILTIN") ||
+ strequal(domain_name, get_global_sam_name()))
+ return find_domain_from_name(domain_name);
+
+ return find_our_domain();
+}
+
/* Lookup a sid in a domain from a name */
BOOL winbindd_lookup_sid_by_name(struct winbindd_domain *domain,
+ const char *domain_name,
const char *name, DOM_SID *sid,
enum SID_NAME_USE *type)
{
NTSTATUS result;
TALLOC_CTX *mem_ctx;
- mem_ctx = talloc_init("lookup_sid_by_name for %s\n", name);
+ mem_ctx = talloc_init("lookup_sid_by_name for %s\\%s\n",
+ domain_name, name);
if (!mem_ctx)
return False;
/* Lookup name */
- result = domain->methods->name_to_sid(domain, mem_ctx, name, sid, type);
+ result = domain->methods->name_to_sid(domain, mem_ctx, domain_name, name, sid, type);
talloc_destroy(mem_ctx);
@@ -457,12 +490,13 @@ BOOL winbindd_lookup_name_by_sid(DOM_SID *sid,
enum SID_NAME_USE *type)
{
char *names;
+ char *dom_names;
NTSTATUS result;
TALLOC_CTX *mem_ctx;
BOOL rv = False;
struct winbindd_domain *domain;
- domain = find_domain_from_sid(sid);
+ domain = find_lookup_domain_from_sid(sid);
if (!domain) {
DEBUG(1,("Can't find domain from sid\n"));
@@ -474,12 +508,12 @@ BOOL winbindd_lookup_name_by_sid(DOM_SID *sid,
if (!(mem_ctx = talloc_init("winbindd_lookup_name_by_sid")))
return False;
- result = domain->methods->sid_to_name(domain, mem_ctx, sid, &names, type);
+ result = domain->methods->sid_to_name(domain, mem_ctx, sid, &dom_names, &names, type);
/* Return name and type if successful */
if ((rv = NT_STATUS_IS_OK(result))) {
- fstrcpy(dom_name, domain->name);
+ fstrcpy(dom_name, dom_names);
fstrcpy(name, names);
} else {
*type = SID_NAME_UNKNOWN;