added info level 3 to samrgetgroupinfo. I don't know what the value is.
authorJean-François Micouleau <jfm@samba.org>
Mon, 10 Dec 2001 15:03:16 +0000 (15:03 +0000)
committerJean-François Micouleau <jfm@samba.org>
Mon, 10 Dec 2001 15:03:16 +0000 (15:03 +0000)
It's just to keep usermanager happy ;-)

clean up a bit samr_query_aliasinfo to return the group description

added: samr_del_aliasmem, samr_del_groupmem and samr_del_domuser

with the correct scripts, you can now entirely manage the users from
usermanager ! Closer to full PDC every day ;-)

        J.F.
(This used to be commit 0a727afc669704cda9b44d44dbac9e989e906ae3)

source3/auth/auth_util.c
source3/include/rpc_samr.h
source3/rpc_parse/parse_samr.c
source3/rpc_server/srv_samr_nt.c

index fed4efd36c6a37e2d151a6cd6e51d85b42ddd54b..04b3cbbecf4dda36a62ebb4e1d960ad9d205990f 100644 (file)
@@ -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;
index 0d0dd7237c16d94db4b613cc1b0bd1368fc9b1f7..07c50d82d51239382d32164de168d6306e19940d 100644 (file)
@@ -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;
index 6f47cd64e6e0e318297131667dd0543c886d12c8..0c6bcdafb87161bd7b03a1f96aca02c953e3a988 100644 (file)
@@ -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;
 
@@ -2198,6 +2199,38 @@ BOOL samr_io_group_info1(char *desc, GROUP_INFO1 * gr1,
        return True;
 }
 
+/*******************************************************************
+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;
 
index 3c82924f1e594e095264a0def3e86f6fd4863d16..042978495aa2b427f41cd79a4d1b771c0e385b6b 100644 (file)
@@ -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);