summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/auth/auth_util.c2
-rw-r--r--source3/include/rpc_samr.h11
-rw-r--r--source3/rpc_parse/parse_samr.c50
-rw-r--r--source3/rpc_server/srv_samr_nt.c176
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);