Make user enumeration work for w2k and win9x.
authorJeremy Allison <jra@samba.org>
Wed, 2 Jan 2002 07:27:33 +0000 (07:27 +0000)
committerJeremy Allison <jra@samba.org>
Wed, 2 Jan 2002 07:27:33 +0000 (07:27 +0000)
This means different return sizes depending on client bugs. This sucks :-(.
Jeremy.

source/include/rpc_samr.h
source/rpc_server/srv_samr_nt.c

index 36c9f6982149de07b54b9b79a1e6e7dd3908c81d..59325ca88d44130cc6b154a269593e703145a896 100644 (file)
@@ -646,7 +646,10 @@ typedef struct r_samr_open_domain_info
 
 } SAMR_R_OPEN_DOMAIN;
 
-#define MAX_SAM_ENTRIES 0x400
+#define MAX_SAM_ENTRIES_W2K 0x400
+#define MAX_SAM_ENTRIES_W95 50
+/* The following should be the greater of the preceeding two. */
+#define MAX_SAM_ENTRIES MAX_SAM_ENTRIES_W2K
 
 typedef struct samr_entry_info
 {
index 17d5f2eb6a91805bb61409ffb2059e46a1584ac9..febbf21f6722f918fe8518d0bac4da112f8502b3 100644 (file)
@@ -6,7 +6,7 @@
  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
  *  Copyright (C) Paul Ashton                       1997.
  *  Copyright (C) Marc Jacobsen                            1999.
- *  Copyright (C) Jeremy Allison                    2001.
+ *  Copyright (C) Jeremy Allison               2001-2002.
  *  Copyright (C) Jean François Micouleau      1998-2001.
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -42,10 +42,10 @@ extern rid_name builtin_alias_rids[];
 
 typedef struct _disp_info {
        BOOL user_dbloaded;
-       BOOL group_dbloaded;
-       uint32 num_account;
-       uint32 total_size;
+       uint32 num_user_account;
        DISP_USER_INFO *disp_user_info;
+       BOOL group_dbloaded;
+       uint32 num_group_account;
        DISP_GROUP_INFO *disp_group_info;
 } DISP_INFO;
 
@@ -56,6 +56,28 @@ struct samr_info {
        DISP_INFO disp_info;
 };
 
+/*******************************************************************
+ Create a samr_info struct.
+********************************************************************/
+
+static struct samr_info *get_samr_info_by_sid(DOM_SID *psid)
+{
+       struct samr_info *info;
+       fstring sid_str;
+
+       if ((info = (struct samr_info *)malloc(sizeof(struct samr_info))) == NULL)
+               return NULL;
+
+       ZERO_STRUCTP(info);
+       if (psid) {
+               DEBUG(10,("get_samr_info_by_sid: created new info for sid %s\n", sid_to_string(sid_str, psid) ));
+               sid_copy( &info->sid, psid);
+       } else {
+               DEBUG(10,("get_samr_info_by_sid: created new info for NULL sid.\n"));
+       }
+       return info;
+}
+
 /*******************************************************************
  Function to free the per handle data.
  ********************************************************************/
@@ -64,14 +86,14 @@ static void free_samr_db(struct samr_info *info)
        int i;
 
        if (info->disp_info.group_dbloaded) {
-               for (i=0; i<info->disp_info.num_account; i++)
+               for (i=0; i<info->disp_info.num_group_account; i++)
                        SAFE_FREE(info->disp_info.disp_group_info[i].grp);
 
                SAFE_FREE(info->disp_info.disp_group_info);
        }
 
        if (info->disp_info.user_dbloaded){
-               for (i=0; i<info->disp_info.num_account; i++)
+               for (i=0; i<info->disp_info.num_user_account; i++)
                        pdb_free_sam(&info->disp_info.disp_user_info[i].sam);
 
                SAFE_FREE(info->disp_info.disp_user_info);
@@ -79,8 +101,8 @@ static void free_samr_db(struct samr_info *info)
 
        info->disp_info.user_dbloaded=False;
        info->disp_info.group_dbloaded=False;
-       info->disp_info.num_account=0;
-       info->disp_info.total_size=0;
+       info->disp_info.num_group_account=0;
+       info->disp_info.num_user_account=0;
 }
 
 
@@ -89,7 +111,7 @@ static void free_samr_info(void *ptr)
        struct samr_info *info=(struct samr_info *) ptr;
 
        free_samr_db(info);
-       SAFE_FREE(ptr);
+       SAFE_FREE(info);
 }
 
 /*******************************************************************
@@ -114,8 +136,10 @@ static void samr_clear_sam_passwd(SAM_ACCOUNT *sam_pass)
        if (!sam_pass)
                return;
 
-       if (sam_pass->lm_pw) memset(sam_pass->lm_pw, '\0', 16);
-       if (sam_pass->nt_pw) memset(sam_pass->nt_pw, '\0', 16);
+       if (sam_pass->lm_pw)
+               memset(sam_pass->lm_pw, '\0', 16);
+       if (sam_pass->nt_pw)
+               memset(sam_pass->nt_pw, '\0', 16);
 }
 
 
@@ -146,11 +170,11 @@ static NTSTATUS load_sampwd_entries(struct samr_info *info, uint16 acb_mask)
                }
 
                /* Realloc some memory for the array of ptr to the SAM_ACCOUNT structs */
-               if (info->disp_info.num_account % MAX_SAM_ENTRIES == 0) {
+               if (info->disp_info.num_user_account % MAX_SAM_ENTRIES == 0) {
                
                        DEBUG(10,("load_sampwd_entries: allocating more memory\n"));
                        pwd_array=(DISP_USER_INFO *)Realloc(info->disp_info.disp_user_info, 
-                                         (info->disp_info.num_account+MAX_SAM_ENTRIES)*sizeof(DISP_USER_INFO));
+                                         (info->disp_info.num_user_account+MAX_SAM_ENTRIES)*sizeof(DISP_USER_INFO));
 
                        if (pwd_array==NULL)
                                return NT_STATUS_NO_MEMORY;
@@ -159,11 +183,11 @@ static NTSTATUS load_sampwd_entries(struct samr_info *info, uint16 acb_mask)
                }
        
                /* link the SAM_ACCOUNT to the array */
-               info->disp_info.disp_user_info[info->disp_info.num_account].sam=pwd;
+               info->disp_info.disp_user_info[info->disp_info.num_user_account].sam=pwd;
 
-               DEBUG(10,("load_sampwd_entries: entry: %d\n", info->disp_info.num_account));
+               DEBUG(10,("load_sampwd_entries: entry: %d\n", info->disp_info.num_user_account));
 
-               info->disp_info.num_account++;  
+               info->disp_info.num_user_account++;     
        }
 
        pdb_endsampwent();
@@ -194,9 +218,9 @@ static NTSTATUS load_group_domain_entries(struct samr_info *info, DOM_SID *sid)
 
        enum_group_mapping(SID_NAME_DOM_GRP, &map, (int *)&group_entries, ENUM_ONLY_MAPPED, MAPPING_WITHOUT_PRIV);
 
-       info->disp_info.num_account=group_entries;
+       info->disp_info.num_group_account=group_entries;
 
-       grp_array=(DISP_GROUP_INFO *)malloc(info->disp_info.num_account*sizeof(DISP_GROUP_INFO));
+       grp_array=(DISP_GROUP_INFO *)malloc(info->disp_info.num_group_account*sizeof(DISP_GROUP_INFO));
 
        if (group_entries!=0 && grp_array==NULL) {
                SAFE_FREE(map);
@@ -337,12 +361,9 @@ NTSTATUS _samr_open_domain(pipes_struct *p, SAMR_Q_OPEN_DOMAIN *q_u, SAMR_R_OPEN
                return NT_STATUS_INVALID_HANDLE;
 
        /* associate the domain SID with the (unique) handle. */
-       if ((info = (struct samr_info *)malloc(sizeof(struct samr_info))) == NULL)
+       if ((info = get_samr_info_by_sid(&q_u->dom_sid.sid))==NULL)
                return NT_STATUS_NO_MEMORY;
 
-       ZERO_STRUCTP(info);
-       info->sid = q_u->dom_sid.sid;
-
        /* get a (unique) handle.  open a policy on it. */
        if (!create_policy_hnd(p, &r_u->domain_pol, free_samr_info, (void *)info))
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
@@ -847,8 +868,12 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, SAMR_
 
        SAM_DISPINFO_CTR *ctr;
        uint32 temp_size=0, total_data_size=0;
-       uint32 i;
        NTSTATUS disp_ret;
+       uint32 num_account = 0;
+       enum remote_arch_types ra_type = get_remote_arch();
+       int max_sam_entries;
+
+       max_sam_entries = (ra_type == RA_WIN95) ? MAX_SAM_ENTRIES_W95 : MAX_SAM_ENTRIES_W2K;
 
        DEBUG(5, ("samr_reply_query_dispinfo: %d\n", __LINE__));
        r_u->status = NT_STATUS_OK;
@@ -904,12 +929,14 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, SAMR_
                                DEBUG(5, ("_samr_query_dispinfo: load_sampwd_entries failed\n"));
                                return r_u->status;
                        }
+                       num_account = info->disp_info.num_user_account;
                        break;
                case 0x3:
                case 0x5:
                        r_u->status = load_group_domain_entries(info, &info->sid);
                        if (NT_STATUS_IS_ERR(r_u->status))
                                return r_u->status;
+                       num_account = info->disp_info.num_group_account;
                        break;
                default:
                        DEBUG(0,("_samr_query_dispinfo: Unknown info level (%u)\n", (unsigned int)q_u->switch_level ));
@@ -917,19 +944,19 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, SAMR_
        }
 
        /* first limit the number of entries we will return */
-       if(max_entries > MAX_SAM_ENTRIES) {
-               DEBUG(5, ("samr_reply_query_dispinfo: client requested %d entries, limiting to %d\n", max_entries, MAX_SAM_ENTRIES));
-               max_entries = MAX_SAM_ENTRIES;
+       if(max_entries > max_sam_entries) {
+               DEBUG(5, ("samr_reply_query_dispinfo: client requested %d entries, limiting to %d\n", max_entries, max_sam_entries));
+               max_entries = max_sam_entries;
        }
 
-       if (enum_context > info->disp_info.num_account) {
+       if (enum_context > num_account) {
                DEBUG(5, ("samr_reply_query_dispinfo: enumeration handle over total entries\n"));
                return NT_STATUS_OK;
        }
 
        /* verify we won't overflow */
-       if (max_entries > info->disp_info.num_account-enum_context) {
-               max_entries = info->disp_info.num_account-enum_context;
+       if (max_entries > num_account-enum_context) {
+               max_entries = num_account-enum_context;
                DEBUG(5, ("samr_reply_query_dispinfo: only %d entries to return\n", max_entries));
        }
 
@@ -1000,9 +1027,9 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, SAMR_
        }
 
        /* calculate the total size */
-       total_data_size=info->disp_info.num_account*struct_size;
+       total_data_size=num_account*struct_size;
 
-       if (enum_context+max_entries < info->disp_info.num_account)
+       if (enum_context+max_entries < num_account)
                r_u->status = STATUS_MORE_ENTRIES;
 
        DEBUG(5, ("_samr_query_dispinfo: %d\n", __LINE__));
@@ -1013,7 +1040,6 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, SAMR_
 
 }
 
-
 /*******************************************************************
  samr_reply_query_aliasinfo
  ********************************************************************/
@@ -1380,12 +1406,9 @@ NTSTATUS _api_samr_open_user(pipes_struct *p, SAMR_Q_OPEN_USER *q_u, SAMR_R_OPEN
                return NT_STATUS_NO_SUCH_USER;
 
        /* associate the user's SID with the new handle. */
-       if ((info = (struct samr_info *)malloc(sizeof(struct samr_info))) == NULL)
+       if ((info = get_samr_info_by_sid(&sid)) == NULL)
                return NT_STATUS_NO_MEMORY;
 
-       ZERO_STRUCTP(info);
-       info->sid = sid;
-
        /* get a (unique) handle.  open a policy on it. */
        if (!create_policy_hnd(p, user_pol, free_samr_info, (void *)info))
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
@@ -1778,7 +1801,7 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
                                DEBUG(5, ("_samr_query_dispinfo: load_sampwd_entries failed\n"));
                                return r_u->status;
                        }
-                       num_users=info->disp_info.num_account;
+                       num_users=info->disp_info.num_user_account;
                        free_samr_db(info);
                        
                        r_u->status=load_group_domain_entries(info, &global_sam_sid);
@@ -1786,7 +1809,7 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
                                DEBUG(5, ("_samr_query_dispinfo: load_group_domain_entries failed\n"));
                                return r_u->status;
                        }
-                       num_groups=info->disp_info.num_account;
+                       num_groups=info->disp_info.num_group_account;
                        free_samr_db(info);
                        
                        /* The time call below is to get a sequence number for the sam. FIXME !!! JRA. */
@@ -1961,7 +1984,7 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_
        }
 
        /* associate the user's SID with the new handle. */
-       if ((info = (struct samr_info *)malloc(sizeof(struct samr_info))) == NULL) {
+       if ((info = get_samr_info_by_sid(&sid)) == NULL) {
                pdb_free_sam(&sam_pass);
                return NT_STATUS_NO_MEMORY;
        }
@@ -1996,10 +2019,9 @@ NTSTATUS _samr_connect_anon(pipes_struct *p, SAMR_Q_CONNECT_ANON *q_u, SAMR_R_CO
     r_u->status = NT_STATUS_OK;
 
     /* associate the user's SID with the new handle. */
-    if ((info = (struct samr_info *)malloc(sizeof(struct samr_info))) == NULL)
+    if ((info = get_samr_info_by_sid(NULL)) == NULL)
         return NT_STATUS_NO_MEMORY;
 
-    ZERO_STRUCTP(info);
     info->status = q_u->unknown_0;
 
     /* get a (unique) handle.  open a policy on it. */
@@ -2022,10 +2044,9 @@ NTSTATUS _samr_connect(pipes_struct *p, SAMR_Q_CONNECT *q_u, SAMR_R_CONNECT *r_u
     r_u->status = NT_STATUS_OK;
 
     /* associate the user's SID with the new handle. */
-    if ((info = (struct samr_info *)malloc(sizeof(struct samr_info))) == NULL)
+       if ((info = get_samr_info_by_sid(NULL)) == NULL)
         return NT_STATUS_NO_MEMORY;
 
-    ZERO_STRUCTP(info);
     info->status = q_u->access_mask;
 
     /* get a (unique) handle.  open a policy on it. */
@@ -2147,12 +2168,9 @@ NTSTATUS _api_samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OP
         */
 
        /* associate the user's SID with the new handle. */
-       if ((info = (struct samr_info *)malloc(sizeof(struct samr_info))) == NULL)
+       if ((info = get_samr_info_by_sid(&sid)) == NULL)
                return NT_STATUS_NO_MEMORY;
 
-       ZERO_STRUCTP(info);
-       info->sid = sid;
-
        /* get a (unique) handle.  open a policy on it. */
        if (!create_policy_hnd(p, alias_pol, free_samr_info, (void *)info))
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
@@ -3229,18 +3247,16 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S
        r_u->rid=pdb_gid_to_group_rid(grp->gr_gid);
 
        /* add the group to the mapping table */
+       sid_copy(&info_sid, &global_sam_sid);
+       sid_append_rid(&info_sid, r_u->rid);
+       sid_to_string(sid_string, &info_sid);
+
        if(!add_initial_entry(grp->gr_gid, sid_string, SID_NAME_DOM_GRP, name, NULL, priv_set, PR_ACCESS_FROM_NETWORK))
                return NT_STATUS_ACCESS_DENIED;
 
-       if ((info = (struct samr_info *)malloc(sizeof(struct samr_info))) == NULL)
+       if ((info = get_samr_info_by_sid(&info_sid)) == NULL)
                return NT_STATUS_NO_MEMORY;
 
-       ZERO_STRUCTP(info);
-
-       sid_copy(&info_sid, &global_sam_sid);
-       sid_append_rid(&info->sid, r_u->rid);
-       sid_to_string(sid_string, &info->sid);
-
        /* get a (unique) handle.  open a policy on it. */
        if (!create_policy_hnd(p, &r_u->pol, free_samr_info, (void *)info))
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
@@ -3255,6 +3271,7 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S
 NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, SAMR_R_CREATE_DOM_ALIAS *r_u)
 {
        DOM_SID dom_sid;
+       DOM_SID info_sid;
        fstring name;
        fstring sid_string;
        struct group *grp;
@@ -3287,19 +3304,17 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S
 
        r_u->rid=pdb_gid_to_group_rid(grp->gr_gid);
 
-       if ((info = (struct samr_info *)malloc(sizeof(struct samr_info))) == NULL)
-               return NT_STATUS_NO_MEMORY;
-
-       ZERO_STRUCTP(info);
-
-       sid_copy(&info->sid, &global_sam_sid);
-       sid_append_rid(&info->sid, r_u->rid);
-       sid_to_string(sid_string, &info->sid);
+       sid_copy(&info_sid, &global_sam_sid);
+       sid_append_rid(&info_sid, r_u->rid);
+       sid_to_string(sid_string, &info_sid);
 
        /* add the group to the mapping table */
        if(!add_initial_entry(grp->gr_gid, sid_string, SID_NAME_ALIAS, name, NULL, priv_set, PR_ACCESS_FROM_NETWORK))
                return NT_STATUS_ACCESS_DENIED;
 
+       if ((info = get_samr_info_by_sid(&info_sid)) == NULL)
+               return NT_STATUS_NO_MEMORY;
+
        /* get a (unique) handle.  open a policy on it. */
        if (!create_policy_hnd(p, &r_u->alias_pol, free_samr_info, (void *)info))
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
@@ -3455,6 +3470,7 @@ NTSTATUS _samr_get_dom_pwinfo(pipes_struct *p, SAMR_Q_GET_DOM_PWINFO *q_u, SAMR_
 NTSTATUS _samr_open_group(pipes_struct *p, SAMR_Q_OPEN_GROUP *q_u, SAMR_R_OPEN_GROUP *r_u)
 {
        DOM_SID sid;
+       DOM_SID info_sid;
        GROUP_MAP map;
        struct samr_info *info;
        fstring sid_string;
@@ -3466,14 +3482,12 @@ NTSTATUS _samr_open_group(pipes_struct *p, SAMR_Q_OPEN_GROUP *q_u, SAMR_R_OPEN_G
        if (!sid_equal(&sid, &global_sam_sid))
                return NT_STATUS_ACCESS_DENIED;
 
-       if ((info = (struct samr_info *)malloc(sizeof(struct samr_info))) == NULL)
-               return NT_STATUS_NO_MEMORY;
-
-       ZERO_STRUCTP(info);
+       sid_copy(&info_sid, &global_sam_sid);
+       sid_append_rid(&info_sid, q_u->rid_group);
+       sid_to_string(sid_string, &info_sid);
 
-       sid_copy(&info->sid, &global_sam_sid);
-       sid_append_rid(&info->sid, q_u->rid_group);
-       sid_to_string(sid_string, &info->sid);
+       if ((info = get_samr_info_by_sid(&info_sid)) == NULL)
+               return NT_STATUS_NO_MEMORY;
 
        DEBUG(10, ("_samr_open_group:Opening SID: %s\n", sid_string));
 
@@ -3554,7 +3568,7 @@ NTSTATUS _samr_unknown_2e(pipes_struct *p, SAMR_Q_UNKNOWN_2E *q_u, SAMR_R_UNKNOW
                                DEBUG(5, ("_samr_query_dispinfo: load_sampwd_entries failed\n"));
                                return r_u->status;
                        }
-                       num_users=info->disp_info.num_account;
+                       num_users=info->disp_info.num_user_account;
                        free_samr_db(info);
                        
                        r_u->status=load_group_domain_entries(info, &global_sam_sid);
@@ -3562,7 +3576,7 @@ NTSTATUS _samr_unknown_2e(pipes_struct *p, SAMR_Q_UNKNOWN_2E *q_u, SAMR_R_UNKNOW
                                DEBUG(5, ("_samr_query_dispinfo: load_group_domain_entries failed\n"));
                                return r_u->status;
                        }
-                       num_groups=info->disp_info.num_account;
+                       num_groups=info->disp_info.num_group_account;
                        free_samr_db(info);
 
                        /* The time call below is to get a sequence number for the sam. FIXME !!! JRA. */