From 71f982c9f2f450d660406d6015ff9756bf317218 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 2 Jan 2002 07:27:33 +0000 Subject: Make user enumeration work for w2k and win9x. This means different return sizes depending on client bugs. This sucks :-(. Jeremy. (This used to be commit f6592628eb526c487069bb3fcd809aca930e668e) --- source3/rpc_server/srv_samr_nt.c | 156 +++++++++++++++++++++------------------ 1 file changed, 85 insertions(+), 71 deletions(-) (limited to 'source3/rpc_server/srv_samr_nt.c') diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index 17d5f2eb6a..febbf21f67 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -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; idisp_info.num_account; i++) + for (i=0; idisp_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; idisp_info.num_account; i++) + for (i=0; idisp_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. */ -- cgit