summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/nsswitch/winbindd.c6
-rw-r--r--source3/nsswitch/winbindd.h43
-rw-r--r--source3/nsswitch/winbindd_group.c51
-rw-r--r--source3/nsswitch/winbindd_misc.c9
-rw-r--r--source3/nsswitch/winbindd_proto.h7
-rw-r--r--source3/nsswitch/winbindd_user.c32
-rw-r--r--source3/nsswitch/winbindd_util.c145
7 files changed, 179 insertions, 114 deletions
diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c
index 01cd0eb55d..bd995611cd 100644
--- a/source3/nsswitch/winbindd.c
+++ b/source3/nsswitch/winbindd.c
@@ -834,10 +834,10 @@ int main(int argc, char **argv)
secrets_init();
/* Get list of domains we look up requests for. This includes the
- domain which we are a member of as well as any trusted
- domains. */
+ domain which we are a member of as well as any trusted
+ domains. */
- get_domain_info();
+ init_domain_list();
ZERO_STRUCT(server_state);
diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h
index 74206da9ef..a8b9980be3 100644
--- a/source3/nsswitch/winbindd.h
+++ b/source3/nsswitch/winbindd.h
@@ -52,7 +52,7 @@ struct getent_state {
void *sam_entries;
uint32 sam_entry_index, num_sam_entries;
BOOL got_sam_entries;
- struct winbindd_domain *domain;
+ fstring domain_name;
};
/* Storage for cached getpwent() user entries */
@@ -82,6 +82,31 @@ typedef struct {
uint32 group_rid; /* primary group */
} WINBIND_USERINFO;
+/* Structures to hold per domain information */
+
+struct winbindd_domain {
+ fstring name; /* Domain name */
+ fstring full_name; /* full Domain name (realm) */
+ DOM_SID sid; /* SID for this domain */
+
+ /* Lookup methods for this domain (LDAP or RPC) */
+
+ struct winbindd_methods *methods;
+
+ /* Private data for the backends (used for connection cache) */
+
+ void *private;
+
+ /* Sequence number stuff */
+
+ time_t last_seq_check;
+ uint32 sequence_number;
+
+ /* Linked list info */
+
+ struct winbindd_domain *prev, *next;
+};
+
/* per-domain methods. This is how LDAP vs RPC is selected
*/
struct winbindd_methods {
@@ -150,22 +175,6 @@ struct winbindd_methods {
DOM_SID *sid);
};
-/* Structures to hold per domain information */
-struct winbindd_domain {
- fstring name; /* Domain name */
- fstring full_name; /* full Domain name (realm) */
- DOM_SID sid; /* SID for this domain */
- struct winbindd_methods *methods; /* lookup methods for
- this domain (LDAP or
- RPC) */
- void *private; /* private data for the backends (used for connection cache) */
- time_t last_seq_check;
- uint32 sequence_number;
- struct winbindd_domain *prev, *next; /* Linked list info */
-};
-
-extern struct winbindd_domain *domain_list; /* List of domains we know */
-
/* Used to glue a policy handle and cli_state together */
typedef struct {
diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c
index ff15611fba..cd4254acfc 100644
--- a/source3/nsswitch/winbindd_group.c
+++ b/source3/nsswitch/winbindd_group.c
@@ -352,10 +352,7 @@ enum winbindd_result winbindd_setgrent(struct winbindd_cli_state *state)
/* Create sam pipes for each domain we know about */
- if (domain_list == NULL)
- get_domain_info();
-
- for (domain = domain_list; domain != NULL; domain = domain->next) {
+ for (domain = domain_list(); domain != NULL; domain = domain->next) {
struct getent_state *domain_state;
/* Skip domains other than WINBINDD_DOMAIN environment
@@ -373,7 +370,7 @@ enum winbindd_result winbindd_setgrent(struct winbindd_cli_state *state)
ZERO_STRUCTP(domain_state);
- domain_state->domain = domain;
+ fstrcpy(domain_state->domain_name, domain->name);
/* Add to list of open domains */
@@ -410,12 +407,13 @@ static BOOL get_sam_group_entries(struct getent_state *ent)
TALLOC_CTX *mem_ctx;
BOOL result = False;
struct acct_info *sam_grp_entries = NULL;
+ struct winbindd_domain *domain;
if (ent->got_sam_entries)
return False;
if (!(mem_ctx = talloc_init_named("get_sam_group_entries(%s)",
- ent->domain->name)))
+ ent->domain_name)))
return False;
/* Free any existing group info */
@@ -425,12 +423,18 @@ static BOOL get_sam_group_entries(struct getent_state *ent)
ent->got_sam_entries = True;
/* Enumerate domain groups */
+
num_entries = 0;
- status = ent->domain->methods->enum_dom_groups(ent->domain,
- mem_ctx,
- &num_entries,
- &sam_grp_entries);
+ if (!(domain = find_domain_from_name(ent->domain_name))) {
+ DEBUG(3, ("no such domain %s in get_sam_group_entries\n", ent->domain_name));
+ goto done;
+ }
+
+ status = domain->methods->enum_dom_groups(domain,
+ mem_ctx,
+ &num_entries,
+ &sam_grp_entries);
if (!NT_STATUS_IS_OK(status)) {
result = False;
@@ -438,6 +442,7 @@ static BOOL get_sam_group_entries(struct getent_state *ent)
}
/* Copy entries into return buffer */
+
if (num_entries) {
name_list = malloc(sizeof(struct acct_info) * num_entries);
memcpy(name_list, sam_grp_entries,
@@ -447,6 +452,7 @@ static BOOL get_sam_group_entries(struct getent_state *ent)
ent->num_sam_entries = num_entries;
/* Fill in remaining fields */
+
ent->sam_entries = name_list;
ent->sam_entry_index = 0;
@@ -512,7 +518,7 @@ enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state)
while(ent && !get_sam_group_entries(ent)) {
struct getent_state *next_ent;
- DEBUG(10, ("freeing state info for domain %s\n", ent->domain->name));
+ DEBUG(10, ("freeing state info for domain %s\n", ent->domain_name));
/* Free state information for this domain */
@@ -536,7 +542,7 @@ enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state)
/* Lookup group info */
if (!winbindd_idmap_get_gid_from_rid(
- ent->domain->name,
+ ent->domain_name,
name_list[ent->sam_entry_index].rid,
&group_gid)) {
@@ -553,7 +559,7 @@ enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state)
/* Fill in group entry */
slprintf(domain_group_name, sizeof(domain_group_name) - 1,
- "%s%s%s", ent->domain->name, lp_winbind_separator(),
+ "%s%s%s", ent->domain_name, lp_winbind_separator(),
name_list[ent->sam_entry_index].acct_name);
result = fill_grent(&group_list[group_list_ndx],
@@ -562,9 +568,19 @@ enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state)
/* Fill in group membership entry */
if (result) {
+ struct winbindd_domain *domain;
+
+ if (!(domain =
+ find_domain_from_name(ent->domain_name))) {
+ DEBUG(3, ("No such domain %s in winbindd_getgrent\n", ent->domain_name));
+ result = False;
+ goto done;
+ }
+
/* Get group membership */
+
result = fill_grent_mem(
- ent->domain,
+ domain,
name_list[ent->sam_entry_index].rid,
SID_NAME_DOM_GRP,
&group_list[group_list_ndx].num_gr_mem,
@@ -673,10 +689,7 @@ enum winbindd_result winbindd_list_groups(struct winbindd_cli_state *state)
/* Enumerate over trusted domains */
- if (domain_list == NULL)
- get_domain_info();
-
- for (domain = domain_list; domain; domain = domain->next) {
+ for (domain = domain_list(); domain; domain = domain->next) {
struct getent_state groups;
ZERO_STRUCT(groups);
@@ -689,7 +702,7 @@ enum winbindd_result winbindd_list_groups(struct winbindd_cli_state *state)
/* Get list of sam groups */
ZERO_STRUCT(groups);
- groups.domain = domain;
+ fstrcpy(groups.domain_name, domain->name);
get_sam_group_entries(&groups);
diff --git a/source3/nsswitch/winbindd_misc.c b/source3/nsswitch/winbindd_misc.c
index d820bb35dc..883f9a4e22 100644
--- a/source3/nsswitch/winbindd_misc.c
+++ b/source3/nsswitch/winbindd_misc.c
@@ -104,10 +104,13 @@ enum winbindd_result winbindd_list_trusted_domains(struct winbindd_cli_state
DEBUG(3, ("[%5d]: list trusted domains\n", state->pid));
- if (domain_list == NULL)
- get_domain_info();
+ /* We need to refresh the trusted domain list as the domains may
+ have changed since we last looked. There may be a sequence
+ number or something we should use but I haven't found it yet. */
- for(domain = domain_list; domain; domain = domain->next) {
+ init_domain_list();
+
+ for(domain = domain_list(); domain; domain = domain->next) {
/* Skip own domain */
diff --git a/source3/nsswitch/winbindd_proto.h b/source3/nsswitch/winbindd_proto.h
index fa5fec1b48..bfadcc9a6c 100644
--- a/source3/nsswitch/winbindd_proto.h
+++ b/source3/nsswitch/winbindd_proto.h
@@ -102,11 +102,14 @@ enum winbindd_result winbindd_list_users(struct winbindd_cli_state *state);
/* The following definitions come from nsswitch/winbindd_util.c */
+struct winbindd_domain *domain_list(void);
+void free_domain_list(void);
+BOOL init_domain_list(void);
struct winbindd_domain *find_domain_from_name(char *domain_name);
struct winbindd_domain *find_domain_from_sid(DOM_SID *sid);
-BOOL get_domain_info(void);
BOOL winbindd_lookup_sid_by_name(struct winbindd_domain *domain,
- const char *name, DOM_SID *sid, enum SID_NAME_USE *type);
+ const char *name, DOM_SID *sid,
+ enum SID_NAME_USE *type);
BOOL winbindd_lookup_name_by_sid(DOM_SID *sid,
fstring name,
enum SID_NAME_USE *type);
diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c
index b5f9436de5..e5cacbb989 100644
--- a/source3/nsswitch/winbindd_user.c
+++ b/source3/nsswitch/winbindd_user.c
@@ -281,10 +281,7 @@ enum winbindd_result winbindd_setpwent(struct winbindd_cli_state *state)
/* Create sam pipes for each domain we know about */
- if (domain_list == NULL)
- get_domain_info();
-
- for(domain = domain_list; domain != NULL; domain = domain->next) {
+ for(domain = domain_list(); domain != NULL; domain = domain->next) {
struct getent_state *domain_state;
/*
@@ -305,7 +302,7 @@ enum winbindd_result winbindd_setpwent(struct winbindd_cli_state *state)
ZERO_STRUCTP(domain_state);
- domain_state->domain = domain;
+ fstrcpy(domain_state->domain_name, domain->name);
/* Add to list of open domains */
@@ -342,6 +339,7 @@ static BOOL get_sam_user_entries(struct getent_state *ent)
struct getpwent_user *name_list = NULL;
BOOL result = False;
TALLOC_CTX *mem_ctx;
+ struct winbindd_domain *domain;
struct winbindd_methods *methods;
int i;
@@ -349,10 +347,16 @@ static BOOL get_sam_user_entries(struct getent_state *ent)
return False;
if (!(mem_ctx = talloc_init_named("get_sam_user_entries(%s)",
- ent->domain->name)))
+ ent->domain_name)))
return False;
- methods = ent->domain->methods;
+ if (!(domain = find_domain_from_name(ent->domain_name))) {
+ DEBUG(3, ("no such domain %s in get_sam_user_entries\n",
+ ent->domain_name));
+ return False;
+ }
+
+ methods = domain->methods;
/* Free any existing user info */
@@ -360,10 +364,11 @@ static BOOL get_sam_user_entries(struct getent_state *ent)
ent->num_sam_entries = 0;
/* Call query_user_list to get a list of usernames and user rids */
+
num_entries = 0;
- status = methods->query_user_list(ent->domain, mem_ctx,
- &num_entries, &info);
+ status = methods->query_user_list(domain, mem_ctx, &num_entries,
+ &info);
if (num_entries) {
struct getpwent_user *tnl;
@@ -496,11 +501,11 @@ enum winbindd_result winbindd_getpwent(struct winbindd_cli_state *state)
/* Lookup user info */
slprintf(domain_user_name, sizeof(domain_user_name) - 1,
- "%s%s%s", ent->domain->name, sep,
+ "%s%s%s", ent->domain_name, sep,
name_list[ent->sam_entry_index].name);
result = winbindd_fill_pwent(
- ent->domain->name,
+ ent->domain_name,
domain_user_name,
name_list[ent->sam_entry_index].user_rid,
name_list[ent->sam_entry_index].group_rid,
@@ -547,10 +552,7 @@ enum winbindd_result winbindd_list_users(struct winbindd_cli_state *state)
/* Enumerate over trusted domains */
- if (domain_list == NULL)
- get_domain_info();
-
- for (domain = domain_list; domain; domain = domain->next) {
+ for (domain = domain_list(); domain; domain = domain->next) {
NTSTATUS status;
struct winbindd_methods *methods;
int i;
diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c
index 3086795a49..f90e89c23f 100644
--- a/source3/nsswitch/winbindd_util.c
+++ b/source3/nsswitch/winbindd_util.c
@@ -36,53 +36,39 @@
*
* Correct code should never look at a field that has this value.
**/
+
static const fstring name_deadbeef = "<deadbeef>";
+/* The list of trusted domains. Note that the list can be deleted and
+ recreated using the init_domain_list() function so pointers to
+ individual winbindd_domain structures cannot be made. Keep a copy of
+ the domain name instead. */
-/* Globals for domain list stuff */
-struct winbindd_domain *domain_list = NULL;
+static struct winbindd_domain *_domain_list;
-/* Given a domain name, return the struct winbindd domain info for it
- if it is actually working. */
-
-struct winbindd_domain *find_domain_from_name(char *domain_name)
+struct winbindd_domain *domain_list(void)
{
- struct winbindd_domain *domain;
-
- if (domain_list == NULL)
- get_domain_info();
+ /* Initialise list */
- /* Search through list */
+ if (!_domain_list)
+ init_domain_list();
- for (domain = domain_list; domain != NULL; domain = domain->next) {
- if (strcasecmp(domain_name, domain->name) == 0 ||
- strcasecmp(domain_name, domain->full_name) == 0)
- return domain;
- }
-
- /* Not found */
-
- return NULL;
+ return _domain_list;
}
-/* Given a domain sid, return the struct winbindd domain info for it */
+/* Free all entries in the trusted domain list */
-struct winbindd_domain *find_domain_from_sid(DOM_SID *sid)
+void free_domain_list(void)
{
- struct winbindd_domain *domain;
-
- if (domain_list == NULL)
- get_domain_info();
-
- /* Search through list */
- for (domain = domain_list; domain != NULL; domain = domain->next) {
- if (sid_compare_domain(sid, &domain->sid) == 0)
- return domain;
+ struct winbindd_domain *domain = _domain_list;
+
+ while(domain) {
+ struct winbindd_domain *next = domain->next;
+
+ DLIST_REMOVE(_domain_list, domain);
+ SAFE_FREE(domain);
+ domain = next;
}
-
- /* Not found */
-
- return NULL;
}
/* Add a trusted domain to our list of domains */
@@ -92,7 +78,10 @@ static struct winbindd_domain *add_trusted_domain(char *domain_name,
{
struct winbindd_domain *domain;
- for (domain = domain_list; domain; domain = domain->next) {
+ /* 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));
@@ -117,14 +106,14 @@ static struct winbindd_domain *add_trusted_domain(char *domain_name,
/* Link to domain list */
- DLIST_ADD(domain_list, domain);
+ DLIST_ADD(_domain_list, domain);
return domain;
}
/* Look up global info for the winbind daemon */
-BOOL get_domain_info(void)
+BOOL init_domain_list(void)
{
NTSTATUS result;
TALLOC_CTX *mem_ctx;
@@ -134,13 +123,20 @@ BOOL get_domain_info(void)
char **names;
int num_domains = 0;
- if (!(mem_ctx = talloc_init_named("get_domain_info")))
+ 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);
- /* now we *must* get the domain sid for our primary domain. Go into a holding
- pattern until that is available */
+ /* Now we *must* get the domain sid for our primary domain. Go into
+ a holding pattern until that is available */
+
result = cache_methods.domain_sid(domain, &domain->sid);
while (!NT_STATUS_IS_OK(result)) {
sleep(10);
@@ -179,10 +175,49 @@ BOOL get_domain_info(void)
return True;
}
+/* Given a domain name, return the struct winbindd domain info for it
+ if it is actually working. */
+
+struct winbindd_domain *find_domain_from_name(char *domain_name)
+{
+ struct winbindd_domain *domain;
+
+ /* Search through list */
+
+ for (domain = domain_list(); domain != NULL; domain = domain->next) {
+ if (strequal(domain_name, domain->name) ||
+ strequal(domain_name, domain->full_name))
+ return domain;
+ }
+
+ /* Not found */
+
+ return NULL;
+}
+
+/* Given a domain sid, return the struct winbindd domain info for it */
+
+struct winbindd_domain *find_domain_from_sid(DOM_SID *sid)
+{
+ struct winbindd_domain *domain;
+
+ /* Search through list */
+
+ for (domain = domain_list(); domain != NULL; domain = domain->next) {
+ if (sid_compare_domain(sid, &domain->sid) == 0)
+ return domain;
+ }
+
+ /* Not found */
+
+ return NULL;
+}
/* Lookup a sid in a domain from a name */
+
BOOL winbindd_lookup_sid_by_name(struct winbindd_domain *domain,
- const char *name, DOM_SID *sid, enum SID_NAME_USE *type)
+ const char *name, DOM_SID *sid,
+ enum SID_NAME_USE *type)
{
NTSTATUS result;
@@ -282,19 +317,19 @@ void free_getent_state(struct getent_state *state)
BOOL winbindd_param_init(void)
{
- /* Parse winbind uid and winbind_gid parameters */
-
- if (!lp_winbind_uid(&server_state.uid_low, &server_state.uid_high)) {
- DEBUG(0, ("winbind uid range missing or invalid\n"));
- return False;
- }
-
- if (!lp_winbind_gid(&server_state.gid_low, &server_state.gid_high)) {
- DEBUG(0, ("winbind gid range missing or invalid\n"));
- return False;
- }
-
- return True;
+ /* Parse winbind uid and winbind_gid parameters */
+
+ if (!lp_winbind_uid(&server_state.uid_low, &server_state.uid_high)) {
+ DEBUG(0, ("winbind uid range missing or invalid\n"));
+ return False;
+ }
+
+ if (!lp_winbind_gid(&server_state.gid_low, &server_state.gid_high)) {
+ DEBUG(0, ("winbind gid range missing or invalid\n"));
+ return False;
+ }
+
+ return True;
}
/* Check if a domain is present in a comma-separated list of domains */