added a query_user backend
authorAndrew Tridgell <tridge@samba.org>
Tue, 4 Dec 2001 06:17:39 +0000 (06:17 +0000)
committerAndrew Tridgell <tridge@samba.org>
Tue, 4 Dec 2001 06:17:39 +0000 (06:17 +0000)
fixed a winbindd crash when the group membership can't be looked up
(This used to be commit 088f4cc5be4a1a38781e4d019146d53993ed8c6f)

source3/nsswitch/winbindd.h
source3/nsswitch/winbindd_ads.c
source3/nsswitch/winbindd_group.c
source3/nsswitch/winbindd_proto.h
source3/nsswitch/winbindd_rpc.c
source3/nsswitch/winbindd_user.c
source3/nsswitch/winbindd_util.c

index a3c9d0afb713c40f504b4d258516073356e8fdf8..01d334d4eb782d0c1072dd8a2bd609f8e2dbb61c 100644 (file)
@@ -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 */
index 287151abd7ae5205f1e6f43f4d139a78c3d95f0e..d86c498cfeb4f40ec6214c2ce9df6e2e4eb4b681 100644 (file)
@@ -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
index f71cdb7ece72f34bc21ea7d9bcf842fe71ea2055..07f30f0acc3ee65b2c50c52302fd43c0fd82db2a 100644 (file)
@@ -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);
index 260985ec585ca8c521380a068f7af6c63876c1ea..1d553fdcebc1862daf2a03756ea74f2d1f4c843b 100644 (file)
@@ -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,
index e4654254cb0a72602c3274e4d43eb301f1bbf6f2..b92e4561850c2499b40ee81319a55ed4efc463e9 100644 (file)
@@ -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
 };
 
index ebd9503c7cb7fd00b177c58ce9c2940fd3059f59..c8d9ce299f2b6046b6c0b773fc5dd873d697349e 100644 (file)
@@ -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;
 }
 
index 900fc900bfedb009f9a6ea5beeb5687e0c8f0cf1..d6f4ca0bcf4ad9b782e7d3447d2c38848bfdc41e 100644 (file)
@@ -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,