From 62d399f3cf588b8b2f31672111ac67034009ee78 Mon Sep 17 00:00:00 2001 From: Jean-François Micouleau Date: Mon, 9 Jul 2001 18:25:40 +0000 Subject: add query user info level 20 (for RAS) add query dominfo level 5 some cleanup, don't free talloced memory. implement delete domain and local groups. J.F. (This used to be commit 3f14dda2a21850edfd540be2624867e5f70a382c) --- source3/include/rpc_samr.h | 18 ++++ source3/rpc_parse/parse_samr.c | 84 +++++++++++++++ source3/rpc_server/srv_samr_nt.c | 217 +++++++++++++++++++++++++++++++++++---- 3 files changed, 297 insertions(+), 22 deletions(-) (limited to 'source3') diff --git a/source3/include/rpc_samr.h b/source3/include/rpc_samr.h index cdfb19580d..f31beaaf84 100644 --- a/source3/include/rpc_samr.h +++ b/source3/include/rpc_samr.h @@ -330,6 +330,15 @@ typedef struct sam_user_info_21 } SAM_USER_INFO_21; +/* SAM_USER_INFO_20 */ +typedef struct sam_user_info_20 +{ + UNIHDR hdr_munged_dial ; /* munged path name and dial-back tel number */ + + UNISTR2 uni_munged_dial ; /* munged path name and dial-back tel number */ + +} SAM_USER_INFO_20; + /* SAM_USER_INFO_12 */ typedef struct sam_user_info_12 { @@ -501,6 +510,13 @@ typedef struct sam_unknown_info_12_inf } SAM_UNK_INFO_12; +typedef struct sam_unknown_info_5_inf +{ + UNIHDR hdr_server; /* server name unicode header */ + UNISTR2 uni_server; /* server name unicode string */ + +} SAM_UNK_INFO_5; + typedef struct sam_unknown_info_2_inf { uint32 unknown_0; /* 0x0000 0000 */ @@ -548,6 +564,7 @@ typedef struct sam_unknown_ctr_info SAM_UNK_INFO_1 inf1; SAM_UNK_INFO_2 inf2; SAM_UNK_INFO_3 inf3; + SAM_UNK_INFO_5 inf5; SAM_UNK_INFO_6 inf6; SAM_UNK_INFO_7 inf7; SAM_UNK_INFO_12 inf12; @@ -1189,6 +1206,7 @@ typedef struct sam_userinfo_ctr_info SAM_USER_INFO_10 *id10; /* auth-level 0x10 */ SAM_USER_INFO_11 *id11; /* auth-level 0x11 */ SAM_USER_INFO_12 *id12; /* auth-level 0x12 */ + SAM_USER_INFO_20 *id20; /* auth-level 20 */ SAM_USER_INFO_21 *id21; /* auth-level 21 */ SAM_USER_INFO_23 *id23; /* auth-level 0x17 */ SAM_USER_INFO_24 *id24; /* auth-level 0x18 */ diff --git a/source3/rpc_parse/parse_samr.c b/source3/rpc_parse/parse_samr.c index a7d758ea1b..76ec35e9c7 100644 --- a/source3/rpc_parse/parse_samr.c +++ b/source3/rpc_parse/parse_samr.c @@ -593,6 +593,40 @@ static BOOL sam_io_unk_info12(char *desc, SAM_UNK_INFO_12 * u_12, return True; } +/******************************************************************* +inits a structure. +********************************************************************/ +void init_unk_info5(SAM_UNK_INFO_5 * u_5,char *server) +{ + int len_server = strlen(server); + + init_uni_hdr(&u_5->hdr_server, len_server); + + init_unistr2(&u_5->uni_server, server, len_server); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ + +static BOOL sam_io_unk_info5(char *desc, SAM_UNK_INFO_5 * u_5, + prs_struct *ps, int depth) +{ + if (u_5 == NULL) + return False; + + prs_debug(ps, depth, desc, "sam_io_unk_info5"); + depth++; + + if(!smb_io_unihdr("hdr_server", &u_5->hdr_server, ps, depth)) + return False; + + if(!smb_io_unistr2("uni_server", &u_5->uni_server, u_5->hdr_server.buffer, ps, depth)) + return False; + + return True; +} + /******************************************************************* inits a structure. ********************************************************************/ @@ -781,6 +815,10 @@ BOOL samr_io_r_query_dom_info(char *desc, SAMR_R_QUERY_DOMAIN_INFO * r_u, if(!sam_io_unk_info6("unk_inf6",&r_u->ctr->info.inf6, ps,depth)) return False; break; + case 0x05: + if(!sam_io_unk_info5("unk_inf5",&r_u->ctr->info.inf5, ps,depth)) + return False; + break; case 0x03: if(!sam_io_unk_info3("unk_inf3",&r_u->ctr->info.inf3, ps,depth)) return False; @@ -5930,6 +5968,42 @@ static BOOL sam_io_user_info21(char *desc, SAM_USER_INFO_21 * usr, return True; } +void init_sam_user_info20A(SAM_USER_INFO_20 *usr, SAM_ACCOUNT *pw) +{ + int len_munged_dial; + char* munged_dial = pdb_get_munged_dial(pw); + + len_munged_dial = munged_dial != NULL ? strlen(munged_dial )+1 : 0; + init_uni_hdr(&usr->hdr_munged_dial, len_munged_dial); + init_unistr2(&usr->uni_munged_dial, munged_dial, len_munged_dial); + +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ + +static BOOL sam_io_user_info20(char *desc, SAM_USER_INFO_20 *usr, + prs_struct *ps, int depth) +{ + if (usr == NULL) + return False; + + prs_debug(ps, depth, desc, "sam_io_user_info20"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!smb_io_unihdr("hdr_munged_dial ", &usr->hdr_munged_dial, ps, depth)) /* wkstas user can log on from */ + return False; + + if(!smb_io_unistr2("uni_munged_dial ", &usr->uni_munged_dial,usr->hdr_munged_dial.buffer, ps, depth)) /* worksations user can log on from */ + return False; + + return True; +} + /******************************************************************* inits a SAM_USERINFO_CTR structure. ********************************************************************/ @@ -6087,6 +6161,16 @@ static BOOL samr_io_userinfo_ctr(char *desc, SAM_USERINFO_CTR **ppctr, } ret = sam_io_user_info12("", ctr->info.id12, ps, depth); break; + case 20: + if (UNMARSHALLING(ps)) + ctr->info.id20 = (SAM_USER_INFO_20 *)prs_alloc_mem(ps,sizeof(SAM_USER_INFO_20)); + + if (ctr->info.id20 == NULL) { + DEBUG(2,("samr_io_userinfo_ctr: info pointer not initialised\n")); + return False; + } + ret = sam_io_user_info20("", ctr->info.id20, ps, depth); + break; case 21: if (UNMARSHALLING(ps)) ctr->info.id21 = (SAM_USER_INFO_21 *)prs_alloc_mem(ps,sizeof(SAM_USER_INFO_21)); diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index 829218008d..95caa1dda8 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -181,14 +181,17 @@ static uint32 jf_get_sampwd_entries(SAM_USER_INFO_21 *pw_buf, int start_idx, int user_name_len; int full_name_len; - if (acb_mask != 0 && !(pdb_get_acct_ctrl(pwd) & acb_mask)) + if (acb_mask != 0 && !(pdb_get_acct_ctrl(pwd) & acb_mask)) { + pdb_reset_sam(pwd); continue; + } if (start_idx > 0) { /* skip the requested number of entries. not very efficient, but hey... */ start_idx--; + pdb_reset_sam(pwd); continue; } @@ -671,6 +674,9 @@ static void make_user_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, UNISTR return; } + ZERO_STRUCTP(sam); + ZERO_STRUCTP(uni_name); + for (i = 0; i < num_sam_entries; i++) { int len = pass[i].uni_user_name.uni_str_len; @@ -793,7 +799,7 @@ static BOOL get_group_alias_entries(TALLOC_CTX *ctx, DOMAIN_GRP **d_grp, DOM_SID /* well-known aliases */ if (sid_equal(sid, &global_sid_Builtin) && !lp_hide_local_users()) { - enum_group_mapping(SID_NAME_WKN_GRP, &map, &num_entries, ENUM_ONLY_MAPPED); + enum_group_mapping(SID_NAME_WKN_GRP, &map, &num_entries, ENUM_ALL_MAPPED); *d_grp=(DOMAIN_GRP *)talloc(ctx, num_entries*sizeof(DOMAIN_GRP)); if (*d_grp==NULL) @@ -877,6 +883,7 @@ static BOOL get_group_alias_entries(TALLOC_CTX *ctx, DOMAIN_GRP **d_grp, DOM_SID fstrcpy((*d_grp)[num_entries].name, smap.nt_name); (*d_grp)[num_entries].rid = trid; num_entries++; + DEBUG(10,("get_group_alias_entries: added entry %d, rid:%d\n", num_entries, trid)); } grent_free(glist); @@ -884,32 +891,45 @@ static BOOL get_group_alias_entries(TALLOC_CTX *ctx, DOMAIN_GRP **d_grp, DOM_SID *p_num_entries = num_entries; - return True; + DEBUG(10,("get_group_alias_entries: returning %d entries\n", *p_num_entries)); + + return NT_STATUS_NO_PROBLEMO; } /******************************************************************* Get the group entries - similar to get_sampwd_entries(). ********************************************************************/ -static BOOL get_group_domain_entries(TALLOC_CTX *ctx, DOMAIN_GRP **d_grp, DOM_SID *sid, uint32 start_idx, +static uint32 get_group_domain_entries(TALLOC_CTX *ctx, DOMAIN_GRP **d_grp, DOM_SID *sid, uint32 start_idx, uint32 *p_num_entries, uint32 max_entries) { GROUP_MAP *map=NULL; int i; + uint32 group_entries = 0; uint32 num_entries = 0; *p_num_entries = 0; - enum_group_mapping(SID_NAME_DOM_GRP, &map, &num_entries, ENUM_ONLY_MAPPED); + enum_group_mapping(SID_NAME_DOM_GRP, &map, &group_entries, ENUM_ONLY_MAPPED); + + num_entries=group_entries-start_idx; + + /* limit the number of entries */ + if (num_entries>max_entries) { + DEBUG(5,("Limiting to %d entries\n", max_entries)); + num_entries=max_entries; + } *d_grp=(DOMAIN_GRP *)talloc(ctx, num_entries*sizeof(DOMAIN_GRP)); - if (*d_grp==NULL) - return False; + if (num_entries!=0 && *d_grp==NULL){ + safe_free(map); + return NT_STATUS_NO_MEMORY; + } for (i=0; imem_ctx, &r_u->sam, &r_u->uni_grp_name, num_entries, grp); - safe_free(grp); - init_samr_r_enum_dom_groups(r_u, q_u->start_idx, num_entries); DEBUG(5,("samr_enum_dom_groups: %d\n", __LINE__)); @@ -973,12 +991,12 @@ uint32 _samr_enum_dom_aliases(pipes_struct *p, SAMR_Q_ENUM_DOM_ALIASES *q_u, SAM sid_to_string(sid_str, &sid); DEBUG(5,("samr_reply_enum_dom_aliases: sid %s\n", sid_str)); - if (!get_group_alias_entries(p->mem_ctx, &grp, &sid, q_u->start_idx, &num_entries, MAX_SAM_ENTRIES)) + if (get_group_alias_entries(p->mem_ctx, &grp, &sid, q_u->start_idx, &num_entries, MAX_SAM_ENTRIES)!=NT_STATUS_NO_PROBLEMO) return NT_STATUS_ACCESS_DENIED; make_group_sam_entry_list(p->mem_ctx, &r_u->sam, &r_u->uni_grp_name, num_entries, grp); - safe_free(grp); + /*safe_free(grp);*/ init_samr_r_enum_dom_aliases(r_u, q_u->start_idx, num_entries); @@ -1014,9 +1032,13 @@ uint32 _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, SAMR_R_ /* decide how many entries to get depending on the max_entries and max_size passed by client */ + DEBUG(5, ("samr_reply_query_dispinfo: max_entries before %d\n", q_u->max_entries)); + if(q_u->max_entries > MAX_SAM_ENTRIES) q_u->max_entries = MAX_SAM_ENTRIES; + DEBUG(5, ("samr_reply_query_dispinfo: max_entries after %d\n", q_u->max_entries)); + /* Get what we need from the password database */ switch (q_u->switch_level) { case 0x2: @@ -1095,7 +1117,6 @@ uint32 _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, SAMR_R_ if (!(ctr->sam.info3 = (SAM_DISPINFO_3 *)talloc(p->mem_ctx,sizeof(SAM_DISPINFO_3)))) return NT_STATUS_NO_MEMORY; disp_ret = init_sam_dispinfo_3(p->mem_ctx, ctr->sam.info3, &num_entries, &data_size, q_u->start_idx, grps); - safe_free(grps); if (disp_ret != NT_STATUS_NO_PROBLEMO) return disp_ret; break; @@ -1110,7 +1131,6 @@ uint32 _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, SAMR_R_ if (!(ctr->sam.info5 = (SAM_DISPINFO_5 *)talloc(p->mem_ctx,sizeof(SAM_DISPINFO_5)))) return NT_STATUS_NO_MEMORY; disp_ret = init_sam_dispinfo_5(p->mem_ctx, ctr->sam.info5, &num_entries, &data_size, q_u->start_idx, grps); - safe_free(grps); if (disp_ret != NT_STATUS_NO_PROBLEMO) return disp_ret; break; @@ -1371,7 +1391,7 @@ static BOOL make_samr_lookup_rids(TALLOC_CTX *ctx, uint32 num_names, fstring nam uint32 _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOKUP_RIDS *r_u) { fstring group_names[MAX_SAM_ENTRIES]; - uint32 group_attrs[MAX_SAM_ENTRIES]; + uint32 *group_attrs = NULL; UNIHDR *hdr_name = NULL; UNISTR2 *uni_name = NULL; DOM_SID pol_sid; @@ -1391,6 +1411,11 @@ uint32 _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOKUP DEBUG(5,("_samr_lookup_rids: truncating entries to %d\n", num_rids)); } + if (num_rids) { + if ((group_attrs = (uint32 *)talloc(p->mem_ctx, num_rids * sizeof(uint32))) == NULL) + return NT_STATUS_NO_MEMORY; + } + r_u->status = NT_STATUS_NONE_MAPPED; for (i = 0; i < num_rids; i++) { @@ -1410,6 +1435,7 @@ uint32 _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOKUP r_u->status = NT_STATUS_NOPROBLEMO; group_attrs[i] = (uint32)type; fstrcpy(group_names[i],tmpname); + DEBUG(5,("_samr_lookup_rids: %s:%d\n", group_names[i], group_attrs[i])); } } } @@ -1509,6 +1535,7 @@ static BOOL get_user_info_10(SAM_USER_INFO_10 *id10, uint32 user_rid) DEBUG(3,("User:[%s]\n", pdb_get_username(smbpass) )); + ZERO_STRUCTP(id10); init_sam_user_info10(id10, pdb_get_acct_ctrl(smbpass) ); samr_clear_sam_passwd(smbpass); @@ -1554,6 +1581,7 @@ static uint32 get_user_info_12(pipes_struct *p, SAM_USER_INFO_12 * id12, uint32 return NT_STATUS_ACCOUNT_DISABLED; } + ZERO_STRUCTP(id12); init_sam_user_info12(id12, pdb_get_lanman_passwd(smbpass), pdb_get_nt_passwd(smbpass)); pdb_free_sam(smbpass); @@ -1561,6 +1589,44 @@ static uint32 get_user_info_12(pipes_struct *p, SAM_USER_INFO_12 * id12, uint32 return NT_STATUS_NOPROBLEMO; } +/************************************************************************* + get_user_info_20 + *************************************************************************/ + +static BOOL get_user_info_20(SAM_USER_INFO_20 *id20, uint32 user_rid) +{ + SAM_ACCOUNT *sampass=NULL; + BOOL ret; + + if (!pdb_rid_is_user(user_rid)) { + DEBUG(4,("RID 0x%x is not a user RID\n", user_rid)); + return False; + } + + pdb_init_sam(&sampass); + + become_root(); + ret = pdb_getsampwrid(sampass, user_rid); + unbecome_root(); + + if (ret == False) { + DEBUG(4,("User 0x%x not found\n", user_rid)); + pdb_free_sam(sampass); + return False; + } + + samr_clear_sam_passwd(sampass); + + DEBUG(3,("User:[%s]\n", pdb_get_username(sampass) )); + + ZERO_STRUCTP(id20); + init_sam_user_info20A(id20, sampass); + + pdb_free_sam(sampass); + + return True; +} + /************************************************************************* get_user_info_21 *************************************************************************/ @@ -1591,6 +1657,7 @@ static BOOL get_user_info_21(SAM_USER_INFO_21 *id21, uint32 user_rid) DEBUG(3,("User:[%s]\n", pdb_get_username(sampass) )); + ZERO_STRUCTP(id21); init_sam_user_info21A(id21, sampass); pdb_free_sam(sampass); @@ -1654,6 +1721,7 @@ uint32 _samr_query_userinfo(pipes_struct *p, SAMR_Q_QUERY_USERINFO *q_u, SAMR_R_ (*ctr-> info. id11)); + ZERO_STRUCTP(ctr->info.id11); init_sam_user_info11(ctr->info.id11, &expire, "BROOKFIELDS$", /* name */ 0x03ef, /* user rid */ @@ -1673,6 +1741,14 @@ uint32 _samr_query_userinfo(pipes_struct *p, SAMR_Q_QUERY_USERINFO *q_u, SAMR_R_ return r_u->status; break; + case 20: + ctr->info.id20 = (SAM_USER_INFO_20 *)talloc(p->mem_ctx,sizeof(SAM_USER_INFO_20)); + if (ctr->info.id20 == NULL) + return NT_STATUS_NO_MEMORY; + if (!get_user_info_20(ctr->info.id20, rid)) + return NT_STATUS_NO_SUCH_USER; + break; + case 21: ctr->info.id21 = (SAM_USER_INFO_21 *)talloc(p->mem_ctx,sizeof(SAM_USER_INFO_21)); if (ctr->info.id21 == NULL) @@ -1775,6 +1851,9 @@ uint32 _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SAMR case 0x03: init_unk_info3(&ctr->info.inf3); break; + case 0x05: + init_unk_info5(&ctr->info.inf5, global_myname); + break; case 0x06: init_unk_info6(&ctr->info.inf6); break; @@ -2819,8 +2898,55 @@ uint32 _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAMR_ uint32 _samr_delete_dom_group(pipes_struct *p, SAMR_Q_DELETE_DOM_GROUP *q_u, SAMR_R_DELETE_DOM_GROUP *r_u) { - DEBUG(0,("_samr_delete_dom_group: Not yet implemented.\n")); - return False; + DOM_SID group_sid; + DOM_SID dom_sid; + uint32 group_rid; + fstring group_sid_str; + gid_t gid; + struct group *grp; + GROUP_MAP map; + + DEBUG(5, ("samr_delete_dom_group: %d\n", __LINE__)); + + /* Find the policy handle. Open a policy on it. */ + if (!get_lsa_policy_samr_sid(p, &q_u->group_pol, &group_sid)) + return NT_STATUS_INVALID_HANDLE; + + sid_copy(&dom_sid, &group_sid); + sid_to_string(group_sid_str, &dom_sid); + sid_split_rid(&dom_sid, &group_rid); + + DEBUG(10, ("sid is %s\n", group_sid_str)); + + /* we check if it's our SID before deleting */ + if (!sid_equal(&dom_sid, &global_sam_sid)) + return NT_STATUS_NO_SUCH_GROUP; + + DEBUG(10, ("lookup on Domain SID\n")); + + if(!get_domain_group_from_sid(group_sid, &map)) + return NT_STATUS_NO_SUCH_ALIAS; + + gid=map.gid; + + /* check if group really exists */ + if ( (grp=getgrgid(gid)) == NULL) + return NT_STATUS_NO_SUCH_GROUP; + + /* we can delete the UNIX group */ + smb_delete_group(grp->gr_name); + + /* check if the group has been successfully deleted */ + if ( (grp=getgrgid(gid)) != NULL) + return NT_STATUS_ACCESS_DENIED; + + if(!group_map_remove(group_sid)) + return NT_STATUS_ACCESS_DENIED; + + if (!close_policy_hnd(p, &q_u->group_pol)) + return NT_STATUS_OBJECT_NAME_INVALID; + + return NT_STATUS_NOPROBLEMO; } /********************************************************************* @@ -2829,8 +2955,55 @@ uint32 _samr_delete_dom_group(pipes_struct *p, SAMR_Q_DELETE_DOM_GROUP *q_u, SAM uint32 _samr_delete_dom_alias(pipes_struct *p, SAMR_Q_DELETE_DOM_ALIAS *q_u, SAMR_R_DELETE_DOM_ALIAS *r_u) { - DEBUG(0,("_samr_delete_dom_alias: Not yet implemented.\n")); - return False; + DOM_SID alias_sid; + DOM_SID dom_sid; + uint32 alias_rid; + fstring alias_sid_str; + gid_t gid; + struct group *grp; + GROUP_MAP map; + + DEBUG(5, ("_samr_delete_dom_alias: %d\n", __LINE__)); + + /* Find the policy handle. Open a policy on it. */ + if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid)) + return NT_STATUS_INVALID_HANDLE; + + sid_copy(&dom_sid, &alias_sid); + sid_to_string(alias_sid_str, &dom_sid); + sid_split_rid(&dom_sid, &alias_rid); + + DEBUG(10, ("sid is %s\n", alias_sid_str)); + + /* we check if it's our SID before deleting */ + if (!sid_equal(&dom_sid, &global_sam_sid)) + return NT_STATUS_NO_SUCH_ALIAS; + + DEBUG(10, ("lookup on Local SID\n")); + + if(!get_local_group_from_sid(alias_sid, &map)) + return NT_STATUS_NO_SUCH_ALIAS; + + gid=map.gid; + + /* check if group really exists */ + if ( (grp=getgrgid(gid)) == NULL) + return NT_STATUS_NO_SUCH_ALIAS; + + /* we can delete the UNIX group */ + smb_delete_group(grp->gr_name); + + /* check if the group has been successfully deleted */ + if ( (grp=getgrgid(gid)) != NULL) + return NT_STATUS_ACCESS_DENIED; + + /* don't check if we removed it as it could be an un-mapped group */ + group_map_remove(alias_sid); + + if (!close_policy_hnd(p, &q_u->alias_pol)) + return NT_STATUS_OBJECT_NAME_INVALID; + + return NT_STATUS_NOPROBLEMO; } /********************************************************************* -- cgit