summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2001-12-04 06:17:39 +0000
committerAndrew Tridgell <tridge@samba.org>2001-12-04 06:17:39 +0000
commit8e8ce079b8c54b257111537d487a5419ce0d1479 (patch)
tree9938c5011a2259b69f576acb6e6fe687a9be5945
parentde98a82052f7f8dbd0785d8d5e26f84e19c32252 (diff)
downloadsamba-8e8ce079b8c54b257111537d487a5419ce0d1479.tar.gz
samba-8e8ce079b8c54b257111537d487a5419ce0d1479.tar.bz2
samba-8e8ce079b8c54b257111537d487a5419ce0d1479.zip
added a query_user backend
fixed a winbindd crash when the group membership can't be looked up (This used to be commit 088f4cc5be4a1a38781e4d019146d53993ed8c6f)
-rw-r--r--source3/nsswitch/winbindd.h7
-rw-r--r--source3/nsswitch/winbindd_ads.c75
-rw-r--r--source3/nsswitch/winbindd_group.c9
-rw-r--r--source3/nsswitch/winbindd_proto.h3
-rw-r--r--source3/nsswitch/winbindd_rpc.c59
-rw-r--r--source3/nsswitch/winbindd_user.c58
-rw-r--r--source3/nsswitch/winbindd_util.c55
7 files changed, 169 insertions, 97 deletions
diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h
index a3c9d0afb7..01d334d4eb 100644
--- a/source3/nsswitch/winbindd.h
+++ b/source3/nsswitch/winbindd.h
@@ -109,6 +109,13 @@ struct winbindd_methods {
DOM_SID *sid,
char **name,
enum SID_NAME_USE *type);
+
+ /* query_user is a bit strange. The backend has a choice of
+ doing the lookup by user name or rid */
+ NTSTATUS (*query_user)(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const char *user_name, uint32 user_rid,
+ WINBIND_USERINFO *user_info);
};
/* Structures to hold per domain information */
diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c
index 287151abd7..d86c498cfe 100644
--- a/source3/nsswitch/winbindd_ads.c
+++ b/source3/nsswitch/winbindd_ads.c
@@ -271,6 +271,76 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
return NT_STATUS_OK;
}
+/* Lookup user information from a rid or username. */
+static NTSTATUS query_user(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const char *user_name, uint32 user_rid,
+ WINBIND_USERINFO *info)
+{
+ ADS_STRUCT *ads;
+ const char *attrs[] = {"sAMAccountName", "name", "objectSid", "primaryGroupID",
+ "userAccountControl", NULL};
+ int rc, count;
+ void *msg;
+ char *exp;
+ DOM_SID sid;
+ fstring dom2, name2;
+
+ /* sigh. Need to fix interface to give us a raw name */
+ parse_domain_user(user_name, dom2, name2);
+
+ DEBUG(3,("ads: query_user\n"));
+
+ ads = ads_init(NULL, NULL, NULL);
+ if (!ads) {
+ DEBUG(1,("ads_init failed\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ rc = ads_connect(ads);
+ if (rc) {
+ DEBUG(1,("query_user ads_connect: %s\n", ads_errstr(rc)));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ asprintf(&exp, "(sAMAccountName=%s)", name2);
+ rc = ads_search(ads, &msg, exp, attrs);
+ free(exp);
+ if (rc) {
+ DEBUG(1,("query_user(%s) ads_search: %s\n", user_name, ads_errstr(rc)));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ count = ads_count_replies(ads, msg);
+ if (count != 1) {
+ DEBUG(1,("query_user(%s): Not found\n", user_name));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ info->acct_name = ads_pull_string(ads, mem_ctx, msg, "sAMAccountName");
+ info->full_name = ads_pull_string(ads, mem_ctx, msg, "name");
+ if (!ads_pull_sid(ads, msg, "objectSid", &sid)) {
+ DEBUG(1,("No sid for %s !?\n", user_name));
+ goto error;
+ }
+ if (!ads_pull_uint32(ads, msg, "primaryGroupID", &info->group_rid)) {
+ DEBUG(1,("No primary group for %s !?\n", user_name));
+ goto error;
+ }
+
+ if (!sid_peek_rid(&sid, &info->user_rid)) {
+ DEBUG(1,("No rid for %s !?\n", user_name));
+ goto error;
+ }
+
+ ads_destroy(&ads);
+
+ return NT_STATUS_OK;
+error:
+ ads_destroy(&ads);
+ return NT_STATUS_UNSUCCESSFUL;
+}
+
/* the ADS backend methods are exposed via this structure */
struct winbindd_methods ads_methods = {
query_user_list,
@@ -278,8 +348,9 @@ struct winbindd_methods ads_methods = {
name_to_sid,
/* I can't see a good way to do a sid to name mapping with ldap,
and MS servers always allow RPC for this (even in native mode) so
- just use RPC. Maybe that's why they allow it? */
- winbindd_rpc_sid_to_name
+ just use RPC for sid_to_name. Maybe that's why they allow it? */
+ winbindd_rpc_sid_to_name,
+ query_user
};
#endif
diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c
index f71cdb7ece..07f30f0acc 100644
--- a/source3/nsswitch/winbindd_group.c
+++ b/source3/nsswitch/winbindd_group.c
@@ -614,6 +614,8 @@ enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state)
fstring domain_group_name;
uint32 result;
gid_t group_gid;
+ int gr_mem_len;
+ char *gr_mem, *new_gr_mem_list;
/* Do we need to fetch another chunk of groups? */
@@ -678,20 +680,17 @@ enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state)
/* Fill in group membership entry */
if (result) {
- int gr_mem_len;
- char *gr_mem, *new_gr_mem_list;
-
/* Get group membership */
-
result = fill_grent_mem(
ent->domain,
name_list[ent->sam_entry_index].rid,
SID_NAME_DOM_GRP,
&group_list[group_list_ndx].num_gr_mem,
&gr_mem, &gr_mem_len);
+ }
+ if (result) {
/* Append to group membership list */
-
new_gr_mem_list = Realloc(
gr_mem_list,
gr_mem_list_len + gr_mem_len);
diff --git a/source3/nsswitch/winbindd_proto.h b/source3/nsswitch/winbindd_proto.h
index 260985ec58..1d553fdceb 100644
--- a/source3/nsswitch/winbindd_proto.h
+++ b/source3/nsswitch/winbindd_proto.h
@@ -145,9 +145,6 @@ BOOL winbindd_lookup_sid_by_name(struct winbindd_domain *domain,
BOOL winbindd_lookup_name_by_sid(DOM_SID *sid,
fstring name,
enum SID_NAME_USE *type);
-BOOL winbindd_lookup_userinfo(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx, uint32 user_rid,
- SAM_USERINFO_CTR **user_info);
BOOL winbindd_lookup_usergroups(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
uint32 user_rid, uint32 *num_groups,
diff --git a/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c
index e4654254cb..b92e456185 100644
--- a/source3/nsswitch/winbindd_rpc.c
+++ b/source3/nsswitch/winbindd_rpc.c
@@ -184,12 +184,69 @@ NTSTATUS winbindd_rpc_sid_to_name(struct winbindd_domain *domain,
return status;
}
+/* Lookup user information from a rid or username. */
+static NTSTATUS query_user(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const char *user_name, uint32 user_rid,
+ WINBIND_USERINFO *user_info)
+{
+ CLI_POLICY_HND *hnd;
+ NTSTATUS result;
+ POLICY_HND dom_pol, user_pol;
+ BOOL got_dom_pol = False, got_user_pol = False;
+ SAM_USERINFO_CTR *ctr;
+
+ /* Get sam handle */
+ if (!(hnd = cm_get_sam_handle(domain->name)))
+ goto done;
+
+ /* Get domain handle */
+
+ result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &domain->sid, &dom_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ got_dom_pol = True;
+
+ /* Get user handle */
+ result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
+ SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Get user info */
+ result = cli_samr_query_userinfo(hnd->cli, mem_ctx, &user_pol,
+ 0x15, &ctr);
+
+ cli_samr_close(hnd->cli, mem_ctx, &user_pol);
+
+ user_info->acct_name = talloc_strdup(mem_ctx, user_name);
+ user_info->group_rid = ctr->info.id21->group_rid;
+ user_info->full_name = unistr2_tdup(mem_ctx,
+ &ctr->info.id21->uni_full_name);
+
+ done:
+ /* Clean up policy handles */
+ if (got_user_pol)
+ cli_samr_close(hnd->cli, mem_ctx, &user_pol);
+
+ if (got_dom_pol)
+ cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
+
+ return result;
+}
+
/* the rpc backend methods are exposed via this structure */
struct winbindd_methods msrpc_methods = {
query_user_list,
enum_dom_groups,
name_to_sid,
- winbindd_rpc_sid_to_name
+ winbindd_rpc_sid_to_name,
+ query_user
};
diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c
index ebd9503c7c..c8d9ce299f 100644
--- a/source3/nsswitch/winbindd_user.c
+++ b/source3/nsswitch/winbindd_user.c
@@ -99,10 +99,11 @@ static struct winbindd_pw negative_pw_cache_entry;
enum winbindd_result winbindd_getpwnam_from_user(struct winbindd_cli_state *state)
{
- uint32 user_rid, group_rid;
- SAM_USERINFO_CTR *user_info;
+ uint32 user_rid;
+ WINBIND_USERINFO user_info;
DOM_SID user_sid;
- fstring name_domain, name_user, name, gecos_name;
+ NTSTATUS status;
+ fstring name_domain, name_user, name;
enum SID_NAME_USE name_type;
struct winbindd_domain *domain;
TALLOC_CTX *mem_ctx;
@@ -163,30 +164,27 @@ enum winbindd_result winbindd_getpwnam_from_user(struct winbindd_cli_state *stat
}
sid_split_rid(&user_sid, &user_rid);
-
- if (!winbindd_lookup_userinfo(domain, mem_ctx, user_rid, &user_info)) {
+
+ status = domain->methods->query_user(domain, mem_ctx, name_user, user_rid,
+ &user_info);
+ if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("pwnam_from_user(): error getting user info for "
"user '%s'\n", name_user));
winbindd_store_user_cache_entry(domain, name_user, &negative_pw_cache_entry);
+ talloc_destroy(mem_ctx);
return WINBINDD_ERROR;
}
- group_rid = user_info->info.id21->group_rid;
-
- unistr2_to_ascii(gecos_name, &user_info->info.id21->uni_full_name,
- sizeof(gecos_name) - 1);
-
- talloc_destroy(mem_ctx);
- user_info = NULL;
-
- /* Now take all this information and fill in a passwd structure */
-
+ /* Now take all this information and fill in a passwd structure */
if (!winbindd_fill_pwent(name_domain, state->request.data.username,
- user_rid, group_rid, gecos_name,
+ user_rid, user_info.group_rid, user_info.full_name,
&state->response.data.pw)) {
winbindd_store_user_cache_entry(domain, name_user, &negative_pw_cache_entry);
+ talloc_destroy(mem_ctx);
return WINBINDD_ERROR;
}
+
+ talloc_destroy(mem_ctx);
winbindd_store_user_cache_entry(domain, name_user, &state->response.data.pw);
@@ -199,12 +197,13 @@ enum winbindd_result winbindd_getpwnam_from_uid(struct winbindd_cli_state *state
{
DOM_SID user_sid;
struct winbindd_domain *domain;
- uint32 user_rid, group_rid;
- fstring user_name, gecos_name;
+ uint32 user_rid;
+ fstring user_name;
enum SID_NAME_USE name_type;
- SAM_USERINFO_CTR *user_info;
+ WINBIND_USERINFO user_info;
gid_t gid;
TALLOC_CTX *mem_ctx;
+ NTSTATUS status;
/* Bug out if the uid isn't in the winbind range */
@@ -262,37 +261,34 @@ enum winbindd_result winbindd_getpwnam_from_uid(struct winbindd_cli_state *state
return WINBINDD_ERROR;
}
- if (!winbindd_lookup_userinfo(domain, mem_ctx, user_rid, &user_info)) {
+ status = domain->methods->query_user(domain, mem_ctx, user_name, user_rid,
+ &user_info);
+ if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("pwnam_from_uid(): error getting user info for "
"user '%s'\n", user_name));
winbindd_store_uid_cache_entry(domain, state->request.data.uid, &negative_pw_cache_entry);
return WINBINDD_ERROR;
}
- group_rid = user_info->info.id21->group_rid;
- unistr2_to_ascii(gecos_name, &user_info->info.id21->uni_full_name,
- sizeof(gecos_name) - 1);
-
- talloc_destroy(mem_ctx);
- user_info = NULL;
-
/* Resolve gid number */
- if (!winbindd_idmap_get_gid_from_rid(domain->name, group_rid, &gid)) {
+ if (!winbindd_idmap_get_gid_from_rid(domain->name, user_info.group_rid, &gid)) {
DEBUG(1, ("error getting group id for user %s\n", user_name));
return WINBINDD_ERROR;
}
/* Fill in password structure */
- if (!winbindd_fill_pwent(domain->name, user_name, user_rid, group_rid,
- gecos_name, &state->response.data.pw)) {
+ if (!winbindd_fill_pwent(domain->name, user_name, user_rid, user_info.group_rid,
+ user_info.full_name, &state->response.data.pw)) {
winbindd_store_uid_cache_entry(domain, state->request.data.uid, &negative_pw_cache_entry);
return WINBINDD_ERROR;
}
winbindd_store_uid_cache_entry(domain, state->request.data.uid, &state->response.data.pw);
-
+
+ talloc_destroy(mem_ctx);
+
return WINBINDD_OK;
}
diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c
index 900fc900bf..d6f4ca0bcf 100644
--- a/source3/nsswitch/winbindd_util.c
+++ b/source3/nsswitch/winbindd_util.c
@@ -478,61 +478,6 @@ BOOL winbindd_lookup_name_by_sid(DOM_SID *sid,
return rv;
}
-/* Lookup user information from a rid */
-
-BOOL winbindd_lookup_userinfo(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx, uint32 user_rid,
- SAM_USERINFO_CTR **user_info)
-{
- CLI_POLICY_HND *hnd;
- uint16 info_level = 0x15;
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
- uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
- POLICY_HND dom_pol, user_pol;
- BOOL got_dom_pol = False, got_user_pol = False;
-
- /* Get sam handle */
-
- if (!(hnd = cm_get_sam_handle(domain->name)))
- goto done;
-
- /* Get domain handle */
-
- result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
- des_access, &domain->sid, &dom_pol);
-
- if (!NT_STATUS_IS_OK(result))
- goto done;
-
- got_dom_pol = True;
-
- /* Get user handle */
-
- result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
- des_access, user_rid, &user_pol);
-
- if (!NT_STATUS_IS_OK(result))
- goto done;
-
- /* Get user info */
-
- result = cli_samr_query_userinfo(hnd->cli, mem_ctx, &user_pol,
- info_level, user_info);
-
- cli_samr_close(hnd->cli, mem_ctx, &user_pol);
-
- done:
- /* Clean up policy handles */
-
- if (got_user_pol)
- cli_samr_close(hnd->cli, mem_ctx, &user_pol);
-
- if (got_dom_pol)
- cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
-
- return NT_STATUS_IS_OK(result);
-}
-
/* Lookup groups a user is a member of. I wish Unix had a call like this! */
BOOL winbindd_lookup_usergroups(struct winbindd_domain *domain,