mirror of
https://github.com/samba-team/samba.git
synced 2025-12-09 00:23:50 +03:00
* fix RemoveSidForeignDomain() ; bug 252
* don't fall back to unmapped UNIX group for get_local_group_from_sid() * remove an extra become/unbecome_root() pair from group enumeration
This commit is contained in:
@@ -547,27 +547,28 @@ BOOL get_domain_group_from_sid(DOM_SID sid, GROUP_MAP *map)
|
|||||||
|
|
||||||
BOOL get_local_group_from_sid(DOM_SID sid, GROUP_MAP *map)
|
BOOL get_local_group_from_sid(DOM_SID sid, GROUP_MAP *map)
|
||||||
{
|
{
|
||||||
struct group *grp;
|
|
||||||
|
|
||||||
if(!init_group_mapping()) {
|
if(!init_group_mapping()) {
|
||||||
DEBUG(0,("failed to initialize group mapping"));
|
DEBUG(0,("failed to initialize group mapping"));
|
||||||
return(False);
|
return(False);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The group is in the mapping table */
|
/* The group is in the mapping table */
|
||||||
if(pdb_getgrsid(map, sid)) {
|
|
||||||
if (map->sid_name_use!=SID_NAME_ALIAS) {
|
if( !pdb_getgrsid(map, sid) )
|
||||||
return False;
|
return False;
|
||||||
}
|
|
||||||
|
|
||||||
if (map->gid==-1) {
|
if ( (map->sid_name_use != SID_NAME_ALIAS)
|
||||||
return False;
|
|| (map->gid == -1)
|
||||||
}
|
|| (getgrgid(map->gid) == NULL) )
|
||||||
|
{
|
||||||
if ( (grp=getgrgid(map->gid)) == NULL) {
|
return False;
|
||||||
return False;
|
}
|
||||||
}
|
|
||||||
} else {
|
#if 0 /* JERRY */
|
||||||
|
/* local groups only exist in the group mapping DB so this
|
||||||
|
is not necessary */
|
||||||
|
|
||||||
|
else {
|
||||||
/* the group isn't in the mapping table.
|
/* the group isn't in the mapping table.
|
||||||
* make one based on the unix information */
|
* make one based on the unix information */
|
||||||
uint32 alias_rid;
|
uint32 alias_rid;
|
||||||
@@ -588,6 +589,7 @@ BOOL get_local_group_from_sid(DOM_SID sid, GROUP_MAP *map)
|
|||||||
|
|
||||||
sid_copy(&map->sid, &sid);
|
sid_copy(&map->sid, &sid);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ SamrTestPrivateFunctionsUser
|
|||||||
#define SAMR_UNKNOWN_2a 0x2a
|
#define SAMR_UNKNOWN_2a 0x2a
|
||||||
#define SAMR_UNKNOWN_2b 0x2b
|
#define SAMR_UNKNOWN_2b 0x2b
|
||||||
#define SAMR_GET_USRDOM_PWINFO 0x2c
|
#define SAMR_GET_USRDOM_PWINFO 0x2c
|
||||||
#define SAMR_REMOVE_USER_FOREIGN_DOMAIN 0x2d
|
#define SAMR_REMOVE_SID_FOREIGN_DOMAIN 0x2d
|
||||||
#define SAMR_UNKNOWN_2E 0x2e /* looks like an alias for SAMR_QUERY_DOMAIN_INFO */
|
#define SAMR_UNKNOWN_2E 0x2e /* looks like an alias for SAMR_QUERY_DOMAIN_INFO */
|
||||||
#define SAMR_UNKNOWN_2f 0x2f
|
#define SAMR_UNKNOWN_2f 0x2f
|
||||||
#define SAMR_QUERY_DISPINFO3 0x30 /* Alias for SAMR_QUERY_DISPINFO
|
#define SAMR_QUERY_DISPINFO3 0x30 /* Alias for SAMR_QUERY_DISPINFO
|
||||||
@@ -1790,21 +1790,21 @@ typedef struct r_samr_chgpasswd_user_info
|
|||||||
} SAMR_R_CHGPASSWD_USER;
|
} SAMR_R_CHGPASSWD_USER;
|
||||||
|
|
||||||
|
|
||||||
/* SAMR_Q_REMOVE_USER_FOREIGN_DOMAIN */
|
/* SAMR_Q_REMOVE_SID_FOREIGN_DOMAIN */
|
||||||
typedef struct q_samr_remove_user_foreign_domain_info
|
typedef struct q_samr_remove_sid_foreign_domain_info
|
||||||
{
|
{
|
||||||
POLICY_HND dom_pol; /* policy handle */
|
POLICY_HND dom_pol; /* policy handle */
|
||||||
DOM_SID2 sid; /* SID */
|
DOM_SID2 sid; /* SID */
|
||||||
|
|
||||||
} SAMR_Q_REMOVE_USER_FOREIGN_DOMAIN;
|
} SAMR_Q_REMOVE_SID_FOREIGN_DOMAIN;
|
||||||
|
|
||||||
|
|
||||||
/* SAMR_R_REMOVE_USER_FOREIGN_DOMAIN */
|
/* SAMR_R_REMOVE_SID_FOREIGN_DOMAIN */
|
||||||
typedef struct r_samr_remove_user_foreign_domain_info
|
typedef struct r_samr_remove_sid_foreign_domain_info
|
||||||
{
|
{
|
||||||
NTSTATUS status; /* return status */
|
NTSTATUS status; /* return status */
|
||||||
|
|
||||||
} SAMR_R_REMOVE_USER_FOREIGN_DOMAIN;
|
} SAMR_R_REMOVE_SID_FOREIGN_DOMAIN;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -181,9 +181,9 @@ BOOL samr_io_r_lookup_domain(const char *desc, SAMR_R_LOOKUP_DOMAIN * r_u,
|
|||||||
reads or writes a structure.
|
reads or writes a structure.
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
|
|
||||||
void init_samr_q_remove_user_foreign_domain(SAMR_Q_REMOVE_USER_FOREIGN_DOMAIN * q_u, POLICY_HND *dom_pol, DOM_SID *sid)
|
void init_samr_q_remove_sid_foreign_domain(SAMR_Q_REMOVE_SID_FOREIGN_DOMAIN * q_u, POLICY_HND *dom_pol, DOM_SID *sid)
|
||||||
{
|
{
|
||||||
DEBUG(5, ("samr_init_samr_q_remove_user_foreign_domain\n"));
|
DEBUG(5, ("samr_init_samr_q_remove_sid_foreign_domain\n"));
|
||||||
|
|
||||||
q_u->dom_pol = *dom_pol;
|
q_u->dom_pol = *dom_pol;
|
||||||
init_dom_sid2(&q_u->sid, sid);
|
init_dom_sid2(&q_u->sid, sid);
|
||||||
@@ -193,13 +193,13 @@ void init_samr_q_remove_user_foreign_domain(SAMR_Q_REMOVE_USER_FOREIGN_DOMAIN *
|
|||||||
reads or writes a structure.
|
reads or writes a structure.
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
|
|
||||||
BOOL samr_io_q_remove_user_foreign_domain(const char *desc, SAMR_Q_REMOVE_USER_FOREIGN_DOMAIN * q_u,
|
BOOL samr_io_q_remove_sid_foreign_domain(const char *desc, SAMR_Q_REMOVE_SID_FOREIGN_DOMAIN * q_u,
|
||||||
prs_struct *ps, int depth)
|
prs_struct *ps, int depth)
|
||||||
{
|
{
|
||||||
if (q_u == NULL)
|
if (q_u == NULL)
|
||||||
return False;
|
return False;
|
||||||
|
|
||||||
prs_debug(ps, depth, desc, "samr_io_q_remove_user_foreign_domain");
|
prs_debug(ps, depth, desc, "samr_io_q_remove_sid_foreign_domain");
|
||||||
depth++;
|
depth++;
|
||||||
|
|
||||||
if(!prs_align(ps))
|
if(!prs_align(ps))
|
||||||
@@ -221,13 +221,13 @@ BOOL samr_io_q_remove_user_foreign_domain(const char *desc, SAMR_Q_REMOVE_USER_F
|
|||||||
reads or writes a structure.
|
reads or writes a structure.
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
|
|
||||||
BOOL samr_io_r_remove_user_foreign_domain(const char *desc, SAMR_R_REMOVE_USER_FOREIGN_DOMAIN * r_u,
|
BOOL samr_io_r_remove_sid_foreign_domain(const char *desc, SAMR_R_REMOVE_SID_FOREIGN_DOMAIN * r_u,
|
||||||
prs_struct *ps, int depth)
|
prs_struct *ps, int depth)
|
||||||
{
|
{
|
||||||
if (r_u == NULL)
|
if (r_u == NULL)
|
||||||
return False;
|
return False;
|
||||||
|
|
||||||
prs_debug(ps, depth, desc, "samr_io_r_remove_user_foreign_domain");
|
prs_debug(ps, depth, desc, "samr_io_r_remove_sid_foreign_domain");
|
||||||
depth++;
|
depth++;
|
||||||
|
|
||||||
if(!prs_align(ps))
|
if(!prs_align(ps))
|
||||||
|
|||||||
@@ -1343,13 +1343,13 @@ static BOOL api_samr_open_group(pipes_struct *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
api_samr_remove_user_foreign_domain
|
api_samr_remove_sid_foreign_domain
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
|
|
||||||
static BOOL api_samr_remove_user_foreign_domain(pipes_struct *p)
|
static BOOL api_samr_remove_sid_foreign_domain(pipes_struct *p)
|
||||||
{
|
{
|
||||||
SAMR_Q_REMOVE_USER_FOREIGN_DOMAIN q_u;
|
SAMR_Q_REMOVE_SID_FOREIGN_DOMAIN q_u;
|
||||||
SAMR_R_REMOVE_USER_FOREIGN_DOMAIN r_u;
|
SAMR_R_REMOVE_SID_FOREIGN_DOMAIN r_u;
|
||||||
|
|
||||||
prs_struct *data = &p->in_data.data;
|
prs_struct *data = &p->in_data.data;
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
prs_struct *rdata = &p->out_data.rdata;
|
||||||
@@ -1357,15 +1357,15 @@ static BOOL api_samr_remove_user_foreign_domain(pipes_struct *p)
|
|||||||
ZERO_STRUCT(q_u);
|
ZERO_STRUCT(q_u);
|
||||||
ZERO_STRUCT(r_u);
|
ZERO_STRUCT(r_u);
|
||||||
|
|
||||||
if (!samr_io_q_remove_user_foreign_domain("", &q_u, data, 0)) {
|
if (!samr_io_q_remove_sid_foreign_domain("", &q_u, data, 0)) {
|
||||||
DEBUG(0,("api_samr_remove_user_foreign_domain: unable to unmarshall SAMR_Q_REMOVE_USER_FOREIGN_DOMAIN.\n"));
|
DEBUG(0,("api_samr_remove_sid_foreign_domain: unable to unmarshall SAMR_Q_REMOVE_SID_FOREIGN_DOMAIN.\n"));
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
r_u.status = _samr_remove_user_foreign_domain(p, &q_u, &r_u);
|
r_u.status = _samr_remove_sid_foreign_domain(p, &q_u, &r_u);
|
||||||
|
|
||||||
if (!samr_io_r_remove_user_foreign_domain("", &r_u, rdata, 0)) {
|
if (!samr_io_r_remove_sid_foreign_domain("", &r_u, rdata, 0)) {
|
||||||
DEBUG(0,("api_samr_remove_user_foreign_domain: unable to marshall SAMR_R_REMOVE_USER_FOREIGN_DOMAIN.\n"));
|
DEBUG(0,("api_samr_remove_sid_foreign_domain: unable to marshall SAMR_R_REMOVE_SID_FOREIGN_DOMAIN.\n"));
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1483,7 +1483,7 @@ static struct api_struct api_samr_cmds [] =
|
|||||||
{"SAMR_OPEN_ALIAS" , SAMR_OPEN_ALIAS , api_samr_open_alias },
|
{"SAMR_OPEN_ALIAS" , SAMR_OPEN_ALIAS , api_samr_open_alias },
|
||||||
{"SAMR_OPEN_GROUP" , SAMR_OPEN_GROUP , api_samr_open_group },
|
{"SAMR_OPEN_GROUP" , SAMR_OPEN_GROUP , api_samr_open_group },
|
||||||
{"SAMR_OPEN_DOMAIN" , SAMR_OPEN_DOMAIN , api_samr_open_domain },
|
{"SAMR_OPEN_DOMAIN" , SAMR_OPEN_DOMAIN , api_samr_open_domain },
|
||||||
{"SAMR_REMOVE_USER_FOREIGN_DOMAIN" , SAMR_REMOVE_USER_FOREIGN_DOMAIN , api_samr_remove_user_foreign_domain },
|
{"SAMR_REMOVE_SID_FOREIGN_DOMAIN" , SAMR_REMOVE_SID_FOREIGN_DOMAIN , api_samr_remove_sid_foreign_domain },
|
||||||
{"SAMR_LOOKUP_DOMAIN" , SAMR_LOOKUP_DOMAIN , api_samr_lookup_domain },
|
{"SAMR_LOOKUP_DOMAIN" , SAMR_LOOKUP_DOMAIN , api_samr_lookup_domain },
|
||||||
|
|
||||||
{"SAMR_QUERY_SEC_OBJECT" , SAMR_QUERY_SEC_OBJECT , api_samr_query_sec_obj },
|
{"SAMR_QUERY_SEC_OBJECT" , SAMR_QUERY_SEC_OBJECT , api_samr_query_sec_obj },
|
||||||
|
|||||||
@@ -1384,8 +1384,6 @@ NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LO
|
|||||||
|
|
||||||
DEBUG(5,("_samr_lookup_names: looking name on SID %s\n", sid_to_string(sid_str, &pol_sid)));
|
DEBUG(5,("_samr_lookup_names: looking name on SID %s\n", sid_to_string(sid_str, &pol_sid)));
|
||||||
|
|
||||||
become_root(); /* local_lookup_name can require root privs */
|
|
||||||
|
|
||||||
for (i = 0; i < num_rids; i++) {
|
for (i = 0; i < num_rids; i++) {
|
||||||
fstring name;
|
fstring name;
|
||||||
DOM_SID sid;
|
DOM_SID sid;
|
||||||
@@ -1421,8 +1419,6 @@ NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LO
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unbecome_root();
|
|
||||||
|
|
||||||
init_samr_r_lookup_names(p->mem_ctx, r_u, num_rids, rid, (uint32 *)type, r_u->status);
|
init_samr_r_lookup_names(p->mem_ctx, r_u, num_rids, rid, (uint32 *)type, r_u->status);
|
||||||
|
|
||||||
DEBUG(5,("_samr_lookup_names: %d\n", __LINE__));
|
DEBUG(5,("_samr_lookup_names: %d\n", __LINE__));
|
||||||
@@ -4256,75 +4252,114 @@ NTSTATUS _samr_open_group(pipes_struct *p, SAMR_Q_OPEN_GROUP *q_u, SAMR_R_OPEN_G
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
_samr_remove_user_foreign_domain
|
_samr_remove_sid_foreign_domain
|
||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
|
|
||||||
NTSTATUS _samr_remove_user_foreign_domain(pipes_struct *p,
|
NTSTATUS _samr_remove_sid_foreign_domain(pipes_struct *p,
|
||||||
SAMR_Q_REMOVE_USER_FOREIGN_DOMAIN *q_u,
|
SAMR_Q_REMOVE_SID_FOREIGN_DOMAIN *q_u,
|
||||||
SAMR_R_REMOVE_USER_FOREIGN_DOMAIN *r_u)
|
SAMR_R_REMOVE_SID_FOREIGN_DOMAIN *r_u)
|
||||||
{
|
{
|
||||||
DOM_SID user_sid, dom_sid;
|
DOM_SID delete_sid, alias_sid;
|
||||||
SAM_ACCOUNT *sam_pass=NULL;
|
SAM_ACCOUNT *sam_pass=NULL;
|
||||||
uint32 acc_granted;
|
uint32 acc_granted;
|
||||||
|
GROUP_MAP map;
|
||||||
|
BOOL is_user = False;
|
||||||
|
NTSTATUS result;
|
||||||
|
enum SID_NAME_USE type = SID_NAME_UNKNOWN;
|
||||||
|
|
||||||
sid_copy( &user_sid, &q_u->sid.sid );
|
sid_copy( &delete_sid, &q_u->sid.sid );
|
||||||
|
|
||||||
DEBUG(5,("_samr_remove_user_foreign_domain: removing user [%s]\n",
|
DEBUG(5,("_samr_remove_sid_foreign_domain: removing SID [%s]\n",
|
||||||
sid_string_static(&user_sid)));
|
sid_string_static(&delete_sid)));
|
||||||
|
|
||||||
/* Find the policy handle. Open a policy on it. */
|
/* Find the policy handle. Open a policy on it. */
|
||||||
|
|
||||||
if (!get_lsa_policy_samr_sid(p, &q_u->dom_pol, &dom_sid, &acc_granted))
|
if (!get_lsa_policy_samr_sid(p, &q_u->dom_pol, &alias_sid, &acc_granted))
|
||||||
return NT_STATUS_INVALID_HANDLE;
|
return NT_STATUS_INVALID_HANDLE;
|
||||||
|
|
||||||
|
result = access_check_samr_function(acc_granted, STD_RIGHT_DELETE_ACCESS,
|
||||||
|
"_samr_remove_sid_foreign_domain");
|
||||||
|
|
||||||
if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted,
|
if (!NT_STATUS_IS_OK(result))
|
||||||
STD_RIGHT_DELETE_ACCESS, "_samr_remove_user_foreign_domain")))
|
return result;
|
||||||
{
|
|
||||||
return r_u->status;
|
DEBUG(8, ("_samr_remove_sid_foreign_domain:sid is %s\n",
|
||||||
}
|
sid_string_static(&alias_sid)));
|
||||||
|
|
||||||
if ( !sid_check_is_in_our_domain(&user_sid) ) {
|
/* make sure we can handle this */
|
||||||
DEBUG(5,("_samr_remove_user_foreign_domain: user not is our domain!\n"));
|
|
||||||
return NT_STATUS_NO_SUCH_USER;
|
if ( sid_check_is_domain(&alias_sid) )
|
||||||
|
type = SID_NAME_DOM_GRP;
|
||||||
|
else if ( sid_check_is_builtin(&alias_sid) )
|
||||||
|
type = SID_NAME_ALIAS;
|
||||||
|
|
||||||
|
if ( type == SID_NAME_UNKNOWN ) {
|
||||||
|
DEBUG(10, ("_samr_remove_sid_foreign_domain: can't operate on what we don't own!\n"));
|
||||||
|
return NT_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if the user exists before trying to delete */
|
/* check if the user exists before trying to delete */
|
||||||
|
|
||||||
pdb_init_sam(&sam_pass);
|
pdb_init_sam(&sam_pass);
|
||||||
|
|
||||||
if ( !pdb_getsampwsid(sam_pass, &user_sid) ) {
|
if ( pdb_getsampwsid(sam_pass, &delete_sid) ) {
|
||||||
|
is_user = True;
|
||||||
|
} else {
|
||||||
|
/* maybe it is a group */
|
||||||
|
if( !pdb_getgrsid(&map, delete_sid) ) {
|
||||||
|
DEBUG(3,("_samr_remove_sid_foreign_domain: %s is not a user or a group!\n",
|
||||||
|
sid_string_static(&delete_sid)));
|
||||||
|
result = NT_STATUS_INVALID_SID;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DEBUG(5,("_samr_remove_user_foreign_domain:User %s doesn't exist.\n",
|
/* we can only delete a user from a group since we don't have
|
||||||
sid_string_static(&user_sid)));
|
nested groups anyways. So in the latter case, just say OK */
|
||||||
|
|
||||||
|
if ( is_user ) {
|
||||||
|
GROUP_MAP *mappings = NULL;
|
||||||
|
uint32 num_groups, i;
|
||||||
|
struct group *grp2;
|
||||||
|
|
||||||
|
if ( pdb_enum_group_mapping(type, &mappings, &num_groups, False) && num_groups>0 ) {
|
||||||
|
|
||||||
|
/* interate over the groups */
|
||||||
|
for ( i=0; i<num_groups; i++ ) {
|
||||||
|
|
||||||
|
grp2 = getgrgid(mappings[i].gid);
|
||||||
|
|
||||||
|
if ( !grp2 ) {
|
||||||
|
DEBUG(0,("_samr_remove_sid_foreign_domain: group mapping without UNIX group!\n"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
pdb_free_sam(&sam_pass);
|
if ( !user_in_unix_group_list(pdb_get_username(sam_pass), grp2->gr_name) )
|
||||||
|
continue;
|
||||||
return NT_STATUS_NO_SUCH_USER;
|
|
||||||
}
|
smb_delete_user_group(grp2->gr_name, pdb_get_username(sam_pass));
|
||||||
|
|
||||||
/*
|
if ( user_in_unix_group_list(pdb_get_username(sam_pass), grp2->gr_name) ) {
|
||||||
* delete the unix side
|
/* should we fail here ? */
|
||||||
*
|
DEBUG(0,("_samr_remove_sid_foreign_domain: Delete user [%s] from group [%s] failed!\n",
|
||||||
* note: we don't check if the delete really happened
|
pdb_get_username(sam_pass), grp2->gr_name ));
|
||||||
* as the script is not necessary present
|
continue;
|
||||||
* and maybe the sysadmin doesn't want to delete the unix side
|
}
|
||||||
*/
|
|
||||||
|
DEBUG(10,("_samr_remove_sid_foreign_domain: Removed user [%s] from group [%s]!\n",
|
||||||
smb_delete_user(pdb_get_username(sam_pass));
|
pdb_get_username(sam_pass), grp2->gr_name ));
|
||||||
|
}
|
||||||
/* and delete the samba side */
|
|
||||||
|
SAFE_FREE(mappings);
|
||||||
if ( !pdb_delete_sam_account(sam_pass) ) {
|
}
|
||||||
|
|
||||||
DEBUG(5,("_samr_delete_dom_user:Failed to delete entry for user %s.\n", pdb_get_username(sam_pass)));
|
|
||||||
pdb_free_sam(&sam_pass);
|
|
||||||
|
|
||||||
return NT_STATUS_CANNOT_DELETE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result = NT_STATUS_OK;
|
||||||
|
done:
|
||||||
|
|
||||||
pdb_free_sam(&sam_pass);
|
pdb_free_sam(&sam_pass);
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
|
|||||||
@@ -382,7 +382,7 @@ BOOL get_domain_user_groups(TALLOC_CTX *ctx, int *numgroups, DOM_GID **pgids, SA
|
|||||||
done:
|
done:
|
||||||
*pgids=gids;
|
*pgids=gids;
|
||||||
*numgroups=cur_gid;
|
*numgroups=cur_gid;
|
||||||
safe_free(map);
|
SAFE_FREE(map);
|
||||||
|
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user