diff options
-rw-r--r-- | source3/auth/auth_util.c | 2 | ||||
-rw-r--r-- | source3/include/rpc_samr.h | 11 | ||||
-rw-r--r-- | source3/rpc_parse/parse_samr.c | 50 | ||||
-rw-r--r-- | source3/rpc_server/srv_samr_nt.c | 176 |
4 files changed, 217 insertions, 22 deletions
diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index fed4efd36c..04b3cbbecf 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -50,7 +50,7 @@ static int smb_create_user(const char *unix_user, const char *homedir) Delete a UNIX user on demand. ****************************************************************************/ -static int smb_delete_user(char *unix_user) +int smb_delete_user(char *unix_user) { pstring del_script; int ret; diff --git a/source3/include/rpc_samr.h b/source3/include/rpc_samr.h index 0d0dd7237c..07c50d82d5 100644 --- a/source3/include/rpc_samr.h +++ b/source3/include/rpc_samr.h @@ -1033,6 +1033,12 @@ typedef struct samr_group_info1 } GROUP_INFO1; +typedef struct samr_group_info3 +{ + uint32 unknown_1; /* 0x0000 0003 - number of group members? */ + +} GROUP_INFO3; + typedef struct samr_group_info4 { UNIHDR hdr_acct_desc; @@ -1044,12 +1050,12 @@ typedef struct samr_group_info4 typedef struct group_info_ctr { uint16 switch_value1; - uint16 switch_value2; union { - GROUP_INFO4 info4; GROUP_INFO1 info1; + GROUP_INFO3 info3; + GROUP_INFO4 info4; } group; @@ -1488,7 +1494,6 @@ typedef struct r_samr_query_groupmem_info typedef struct q_samr_del_group_mem_info { POLICY_HND pol; /* policy handle */ - uint32 rid; /* rid */ } SAMR_Q_DEL_GROUPMEM; diff --git a/source3/rpc_parse/parse_samr.c b/source3/rpc_parse/parse_samr.c index 6f47cd64e6..0c6bcdafb8 100644 --- a/source3/rpc_parse/parse_samr.c +++ b/source3/rpc_parse/parse_samr.c @@ -352,6 +352,7 @@ void init_samr_r_get_usrdom_pwinfo(SAMR_R_GET_USRDOM_PWINFO *r_u, NTSTATUS statu * but for trusts. */ r_u->unknown_1 = 0x01D1; + r_u->unknown_1 = 0x0015; r_u->unknown_2 = 0x00000000; @@ -2199,6 +2200,38 @@ BOOL samr_io_group_info1(char *desc, GROUP_INFO1 * gr1, } /******************************************************************* +inits a GROUP_INFO3 structure. +********************************************************************/ + +void init_samr_group_info3(GROUP_INFO3 *gr3) +{ + DEBUG(5, ("init_samr_group_info3\n")); + + gr3->unknown_1 = 0x3; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ + +BOOL samr_io_group_info3(char *desc, GROUP_INFO3 *gr3, prs_struct *ps, int depth) +{ + if (gr3 == NULL) + return False; + + prs_debug(ps, depth, desc, "samr_io_group_info3"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!prs_uint32("unknown_1", ps, depth, &gr3->unknown_1)) + return False; + + return True; +} + +/******************************************************************* inits a GROUP_INFO4 structure. ********************************************************************/ @@ -2255,18 +2288,18 @@ static BOOL samr_group_info_ctr(char *desc, GROUP_INFO_CTR **ctr, if(!prs_uint16("switch_value1", ps, depth, &(*ctr)->switch_value1)) return False; - if(!prs_uint16("switch_value2", ps, depth, &(*ctr)->switch_value2)) - return False; switch ((*ctr)->switch_value1) { case 1: - if(!samr_io_group_info1("group_info1", - &(*ctr)->group.info1, ps, depth)) + if(!samr_io_group_info1("group_info1", &(*ctr)->group.info1, ps, depth)) + return False; + break; + case 3: + if(!samr_io_group_info3("group_info3", &(*ctr)->group.info3, ps, depth)) return False; break; case 4: - if(!samr_io_group_info4("group_info4", - &(*ctr)->group.info4, ps, depth)) + if(!samr_io_group_info4("group_info4", &(*ctr)->group.info4, ps, depth)) return False; break; default: @@ -2407,6 +2440,9 @@ BOOL samr_io_r_delete_dom_group(char *desc, SAMR_R_DELETE_DOM_GROUP * r_u, if(!prs_align(ps)) return False; + if(!smb_io_pol_hnd("pol", &r_u->pol, ps, depth)) + return False; + if(!prs_ntstatus("status", ps, depth, &r_u->status)) return False; @@ -4760,6 +4796,8 @@ BOOL samr_io_r_delete_dom_user(char *desc, SAMR_R_DELETE_DOM_USER * r_u, if(!prs_align(ps)) return False; + if(!smb_io_pol_hnd("pol", &r_u->pol, ps, depth)) + return False; if(!prs_ntstatus("status", ps, depth, &r_u->status)) return False; diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index 3c82924f1e..042978495a 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -1181,10 +1181,8 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, SAMR_ NTSTATUS _samr_query_aliasinfo(pipes_struct *p, SAMR_Q_QUERY_ALIASINFO *q_u, SAMR_R_QUERY_ALIASINFO *r_u) { - fstring alias_desc = "Local Unix group"; - fstring alias=""; - enum SID_NAME_USE type; struct samr_info *info = NULL; + GROUP_MAP map; r_u->status = NT_STATUS_OK; @@ -1198,14 +1196,14 @@ NTSTATUS _samr_query_aliasinfo(pipes_struct *p, SAMR_Q_QUERY_ALIASINFO *q_u, SAM !sid_check_is_in_builtin(&info->sid)) return NT_STATUS_OBJECT_TYPE_MISMATCH; - if(!local_lookup_sid(&info->sid, alias, &type)) + if(!get_local_group_from_sid(info->sid, &map, MAPPING_WITHOUT_PRIV)) return NT_STATUS_NO_SUCH_ALIAS; switch (q_u->switch_level) { case 3: r_u->ptr = 1; r_u->ctr.switch_value1 = 3; - init_samr_alias_info3(&r_u->ctr.alias.info3, alias_desc); + init_samr_alias_info3(&r_u->ctr.alias.info3, map.comment); break; default: return NT_STATUS_INVALID_INFO_CLASS; @@ -2981,8 +2979,62 @@ NTSTATUS _samr_add_aliasmem(pipes_struct *p, SAMR_Q_ADD_ALIASMEM *q_u, SAMR_R_AD NTSTATUS _samr_del_aliasmem(pipes_struct *p, SAMR_Q_DEL_ALIASMEM *q_u, SAMR_R_DEL_ALIASMEM *r_u) { - DEBUG(0,("_samr_del_aliasmem: Not yet implemented.\n")); - return NT_STATUS_NOT_IMPLEMENTED; + DOM_SID alias_sid; + fstring alias_sid_str; + struct group *grp; + fstring grp_name; + uint32 rid; + GROUP_MAP map; + SAM_ACCOUNT *sam_pass=NULL; + + /* 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_to_string(alias_sid_str, &alias_sid); + DEBUG(10, ("_samr_del_aliasmem:sid is %s\n", alias_sid_str)); + + if (!sid_check_is_in_our_domain(&alias_sid) && + !sid_check_is_in_builtin(&alias_sid)) { + DEBUG(10, ("_samr_del_aliasmem:invalid alias group\n")); + return NT_STATUS_NO_SUCH_ALIAS; + } + + if( !get_local_group_from_sid(alias_sid, &map, MAPPING_WITHOUT_PRIV)) + return NT_STATUS_NO_SUCH_ALIAS; + + if ((grp=getgrgid(map.gid)) == NULL) + return NT_STATUS_NO_SUCH_ALIAS; + + /* we need to copy the name otherwise it's overloaded in user_in_group_list */ + fstrcpy(grp_name, grp->gr_name); + + sid_peek_rid(&q_u->sid.sid, &rid); + + /* check if the user exists before trying to remove it from the group */ + pdb_init_sam(&sam_pass); + if(!pdb_getsampwrid(sam_pass, rid)) { + DEBUG(5,("_samr_del_aliasmem:User %d doesn't exist.\n", sam_pass->username)); + pdb_free_sam(&sam_pass); + return NT_STATUS_NO_SUCH_USER; + } + + /* if the user is not in the group */ + if(!user_in_group_list(sam_pass->username, grp_name)) { + pdb_free_sam(&sam_pass); + return NT_STATUS_MEMBER_IN_ALIAS; + } + + smb_delete_user_group(grp_name, sam_pass->username); + + /* check if the user has been removed then ... */ + if(user_in_group_list(sam_pass->username, grp_name)) { + pdb_free_sam(&sam_pass); + return NT_STATUS_MEMBER_NOT_IN_ALIAS; /* don't know what to reply else */ + } + + pdb_free_sam(&sam_pass); + return NT_STATUS_OK; } /********************************************************************* @@ -3047,8 +3099,62 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DEL_GROUPMEM *r_u) { - DEBUG(0,("_samr_del_groupmem: Not yet implemented.\n")); - return NT_STATUS_NOT_IMPLEMENTED; + DOM_SID group_sid; + SAM_ACCOUNT *sam_pass=NULL; + uint32 rid; + GROUP_MAP map; + fstring grp_name; + struct group *grp; + + /* + * delete the group member named q_u->rid + * who is a member of the sid associated with the handle + * the rid is a user's rid as the group is a domain group. + */ + + /* Find the policy handle. Open a policy on it. */ + if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid)) + return NT_STATUS_INVALID_HANDLE; + + if(!sid_check_is_in_our_domain(&group_sid)) + return NT_STATUS_NO_SUCH_GROUP; + + rid=q_u->rid; + + if(!get_domain_group_from_sid(group_sid, &map, MAPPING_WITHOUT_PRIV)) + return NT_STATUS_NO_SUCH_GROUP; + + if ((grp=getgrgid(map.gid)) == NULL) + return NT_STATUS_NO_SUCH_GROUP; + + /* we need to copy the name otherwise it's overloaded in user_in_group_list */ + fstrcpy(grp_name, grp->gr_name); + + /* check if the user exists before trying to remove it from the group */ + pdb_init_sam(&sam_pass); + if(!pdb_getsampwrid(sam_pass, rid)) { + DEBUG(5,("User %d doesn't exist.\n", sam_pass->username)); + pdb_free_sam(&sam_pass); + return NT_STATUS_NO_SUCH_USER; + } + + /* if the user is not in the group */ + if(!user_in_group_list(sam_pass->username, grp_name)) { + pdb_free_sam(&sam_pass); + return NT_STATUS_MEMBER_NOT_IN_GROUP; + } + + smb_delete_user_group(grp_name, sam_pass->username); + + /* check if the user has been removed then ... */ + if(user_in_group_list(sam_pass->username, grp_name)) { + pdb_free_sam(&sam_pass); + return NT_STATUS_ACCESS_DENIED; /* don't know what to reply else */ + } + + pdb_free_sam(&sam_pass); + return NT_STATUS_OK; + } /********************************************************************* @@ -3057,8 +3163,50 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAMR_R_DELETE_DOM_USER *r_u ) { - DEBUG(0,("_samr_delete_dom_user: Not yet implemented.\n")); - return NT_STATUS_NOT_IMPLEMENTED; + DOM_SID user_sid; + SAM_ACCOUNT *sam_pass=NULL; + uint32 rid; + + DEBUG(5, ("_samr_delete_dom_user: %d\n", __LINE__)); + + /* Find the policy handle. Open a policy on it. */ + if (!get_lsa_policy_samr_sid(p, &q_u->user_pol, &user_sid)) + return NT_STATUS_INVALID_HANDLE; + + if (!sid_check_is_in_our_domain(&user_sid)) + return NT_STATUS_CANNOT_DELETE; + + sid_peek_rid(&user_sid, &rid); + + /* check if the user exists before trying to delete */ + pdb_init_sam(&sam_pass); + if(!pdb_getsampwrid(sam_pass, rid)) { + DEBUG(5,("_samr_delete_dom_user:User %d doesn't exist.\n", sam_pass->username)); + pdb_free_sam(&sam_pass); + return NT_STATUS_NO_SUCH_USER; + } + + /* delete the unix side */ + /* + * note: we don't check if the delete really happened + * as the script is not necessary present + * and maybe the sysadmin doesn't want to delete the unix side + */ + smb_delete_user(sam_pass->username); + + /* and delete the samba side */ + if (!pdb_delete_sam_account(sam_pass->username)) { + DEBUG(5,("_samr_delete_dom_user:Failed to delete entry for user %s.\n", sam_pass->username)); + pdb_free_sam(&sam_pass); + return NT_STATUS_CANNOT_DELETE; + } + + pdb_free_sam(&sam_pass); + + if (!close_policy_hnd(p, &q_u->user_pol)) + return NT_STATUS_OBJECT_NAME_INVALID; + + return NT_STATUS_OK; } /********************************************************************* @@ -3094,7 +3242,7 @@ NTSTATUS _samr_delete_dom_group(pipes_struct *p, SAMR_Q_DELETE_DOM_GROUP *q_u, S DEBUG(10, ("lookup on Domain SID\n")); if(!get_domain_group_from_sid(group_sid, &map, MAPPING_WITHOUT_PRIV)) - return NT_STATUS_NO_SUCH_ALIAS; + return NT_STATUS_NO_SUCH_GROUP; gid=map.gid; @@ -3327,6 +3475,10 @@ NTSTATUS _samr_query_groupinfo(pipes_struct *p, SAMR_Q_QUERY_GROUPINFO *q_u, SAM init_samr_group_info1(&ctr->group.info1, map.nt_name, map.comment, num_uids); SAFE_FREE(uid); break; + case 3: + ctr->switch_value1 = 3; + init_samr_group_info3(&ctr->group.info3); + break; case 4: ctr->switch_value1 = 4; init_samr_group_info4(&ctr->group.info4, map.comment); |