static bool test_sids2unixids1(TALLOC_CTX *memctx, struct idmap_domain *dom) { NTSTATUS status; struct id_map uid_map, gid_map, **test_maps; ZERO_STRUCT(uid_map); ZERO_STRUCT(gid_map); /* create two mappings for a UID and GID */ uid_map.sid = dom_sid_parse_talloc(memctx, DOM_SID4 "-1000"); uid_map.xid.type = ID_TYPE_UID; gid_map.sid = dom_sid_parse_talloc(memctx, DOM_SID4 "-1001"); gid_map.xid.type = ID_TYPE_GID; status = idmap_tdb_common_new_mapping(dom, &uid_map); if(!NT_STATUS_IS_OK(status)) { DEBUG(0, ("test_sids2unixids1: could not create uid map!\n")); return false; } status = idmap_tdb_common_new_mapping(dom, &gid_map); if(!NT_STATUS_IS_OK(status)) { DEBUG(0, ("test_sids2unixids1: could not create gid map!\n")); return false; } /* now read them back */ test_maps = talloc_zero_array(memctx, struct id_map*, 3); test_maps[0] = talloc(test_maps, struct id_map); test_maps[1] = talloc(test_maps, struct id_map); test_maps[2] = NULL; test_maps[0]->sid = talloc(test_maps, struct dom_sid); test_maps[1]->sid = talloc(test_maps, struct dom_sid); sid_copy(test_maps[0]->sid, uid_map.sid); sid_copy(test_maps[1]->sid, gid_map.sid); status = idmap_tdb_common_sids_to_unixids(dom, test_maps); if(!NT_STATUS_IS_OK(status)) { DEBUG(0, ("test_sids2sunixids1: sids2unixids failed!\n")); talloc_free(test_maps); return false; } if(test_maps[0]->xid.id!=uid_map.xid.id || test_maps[1]->xid.id!=gid_map.xid.id ) { DEBUG(0, ("test_sids2unixids1: sid2unixid returned wrong xid!\n")); talloc_free(test_maps); return false; } DEBUG(0, ("test_sids2unixids1: PASSED!\n")); talloc_free(test_maps); return true; }
bool pdb_set_group_sid(struct samu *sampass, const DOM_SID *g_sid, enum pdb_value_state flag) { gid_t gid; if (!g_sid) return False; if ( !(sampass->group_sid = TALLOC_P( sampass, DOM_SID )) ) { return False; } /* if we cannot resolve the SID to gid, then just ignore it and store DOMAIN_USERS as the primary groupSID */ if ( sid_to_gid( g_sid, &gid ) ) { sid_copy(sampass->group_sid, g_sid); } else { sid_copy( sampass->group_sid, get_global_sam_sid() ); sid_append_rid( sampass->group_sid, DOMAIN_GROUP_RID_USERS ); } DEBUG(10, ("pdb_set_group_sid: setting group sid %s\n", sid_string_dbg(sampass->group_sid))); return pdb_set_init_flags(sampass, PDB_GROUPSID, flag); }
/** * Turn struct ifs_identity into SID */ static bool onefs_identity_to_sid(struct ifs_identity *id, struct dom_sid *sid) { if (!id || !sid) return false; if (id->type >= IFS_ID_TYPE_LAST) return false; switch (id->type) { case IFS_ID_TYPE_UID: uid_to_sid(sid, id->id.uid); break; case IFS_ID_TYPE_GID: gid_to_sid(sid, id->id.gid); break; case IFS_ID_TYPE_EVERYONE: sid_copy(sid, &global_sid_World); break; case IFS_ID_TYPE_NULL: sid_copy(sid, &global_sid_NULL); break; case IFS_ID_TYPE_CREATOR_OWNER: sid_copy(sid, &global_sid_Creator_Owner); break; case IFS_ID_TYPE_CREATOR_GROUP: sid_copy(sid, &global_sid_Creator_Group); break; default: DEBUG(0, ("Unknown identity type: %d\n", id->type)); return false; } return true; }
static bool swap_sid_in_acl( struct security_descriptor *sd, struct dom_sid *s1, struct dom_sid *s2 ) { struct security_acl *theacl; int i; bool update = False; verbose_output(" Owner SID: %s\n", sid_string_tos(sd->owner_sid)); if ( dom_sid_equal( sd->owner_sid, s1 ) ) { sid_copy( sd->owner_sid, s2 ); update = True; verbose_output(" New Owner SID: %s\n", sid_string_tos(sd->owner_sid)); } verbose_output(" Group SID: %s\n", sid_string_tos(sd->group_sid)); if ( dom_sid_equal( sd->group_sid, s1 ) ) { sid_copy( sd->group_sid, s2 ); update = True; verbose_output(" New Group SID: %s\n", sid_string_tos(sd->group_sid)); } theacl = sd->dacl; verbose_output(" DACL: %d entries:\n", theacl->num_aces); for ( i=0; i<theacl->num_aces; i++ ) { verbose_output(" Trustee SID: %s\n", sid_string_tos(&theacl->aces[i].trustee)); if ( dom_sid_equal( &theacl->aces[i].trustee, s1 ) ) { sid_copy( &theacl->aces[i].trustee, s2 ); update = True; verbose_output(" New Trustee SID: %s\n", sid_string_tos(&theacl->aces[i].trustee)); } } #if 0 theacl = sd->sacl; verbose_output(" SACL: %d entries: \n", theacl->num_aces); for ( i=0; i<theacl->num_aces; i++ ) { verbose_output(" Trustee SID: %s\n", sid_string_tos(&theacl->aces[i].trustee)); if ( dom_sid_equal( &theacl->aces[i].trustee, s1 ) ) { sid_copy( &theacl->aces[i].trustee, s2 ); update = True; verbose_output(" New Trustee SID: %s\n", sid_string_tos(&theacl->aces[i].trustee)); } } #endif return update; }
void generate_wellknown_sids(void) { static BOOL initialised = False; if (initialised) return; /* SECURITY_NULL_SID_AUTHORITY */ string_to_sid(&global_sid_NULL, "S-1-0-0"); /* SECURITY_WORLD_SID_AUTHORITY */ string_to_sid(&global_sid_World_Domain, "S-1-1"); string_to_sid(&global_sid_World, "S-1-1-0"); /* SECURITY_CREATOR_SID_AUTHORITY */ string_to_sid(&global_sid_Creator_Owner_Domain, "S-1-3"); string_to_sid(&global_sid_Creator_Owner, "S-1-3-0"); string_to_sid(&global_sid_Creator_Group, "S-1-3-1"); /* SECURITY_NT_AUTHORITY */ string_to_sid(&global_sid_NT_Authority, "S-1-5"); string_to_sid(&global_sid_Network, "S-1-5-2"); string_to_sid(&global_sid_Anonymous, "S-1-5-7"); string_to_sid(&global_sid_Authenticated_Users, "S-1-5-11"); string_to_sid(&global_sid_System, "S-1-5-18"); /* SECURITY_BUILTIN_DOMAIN_RID */ string_to_sid(&global_sid_Builtin, "S-1-5-32"); string_to_sid(&global_sid_Builtin_Administrators, "S-1-5-32-544"); string_to_sid(&global_sid_Builtin_Users, "S-1-5-32-545"); string_to_sid(&global_sid_Builtin_Guests, "S-1-5-32-546"); string_to_sid(&global_sid_Builtin_Power_Users, "S-1-5-32-547"); string_to_sid(&global_sid_Builtin_Account_Operators, "S-1-5-32-548"); string_to_sid(&global_sid_Builtin_Server_Operators, "S-1-5-32-549"); string_to_sid(&global_sid_Builtin_Print_Operators, "S-1-5-32-550"); string_to_sid(&global_sid_Builtin_Backup_Operators, "S-1-5-32-551"); string_to_sid(&global_sid_Builtin_Replicator, "S-1-5-32-552"); /* Create the anon token. */ sid_copy( &anonymous_token.user_sids[0], &global_sid_World); sid_copy( &anonymous_token.user_sids[1], &global_sid_Network); sid_copy( &anonymous_token.user_sids[2], &global_sid_Anonymous); /* Create the system token. */ sid_copy( &system_token.user_sids[0], &global_sid_System); initialised = True; }
static bool get_group_map_from_sid(DOM_SID sid, GROUP_MAP *map) { TDB_DATA dbuf; char *key; int ret = 0; /* the key is the SID, retrieving is direct */ key = group_mapping_key(talloc_tos(), &sid); if (key == NULL) { return false; } dbuf = dbwrap_fetch_bystring(db, key, key); if (dbuf.dptr == NULL) { TALLOC_FREE(key); return false; } ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff", &map->gid, &map->sid_name_use, &map->nt_name, &map->comment); TALLOC_FREE(key); if ( ret == -1 ) { DEBUG(3,("get_group_map_from_sid: tdb_unpack failure\n")); return false; } sid_copy(&map->sid, &sid); return true; }
BOOL secrets_store_trusted_domain_password(const char* domain, smb_ucs2_t *uni_dom_name, size_t uni_name_len, const char* pwd, DOM_SID sid) { /* packing structures */ pstring pass_buf; int pass_len = 0; int pass_buf_len = sizeof(pass_buf); struct trusted_dom_pass pass; ZERO_STRUCT(pass); /* unicode domain name and its length */ if (!uni_dom_name) return False; strncpy_w(pass.uni_name, uni_dom_name, sizeof(pass.uni_name) - 1); pass.uni_name_len = uni_name_len; /* last change time */ pass.mod_time = time(NULL); /* password of the trust */ pass.pass_len = strlen(pwd); fstrcpy(pass.pass, pwd); /* domain sid */ sid_copy(&pass.domain_sid, &sid); pass_len = tdb_trusted_dom_pass_pack(pass_buf, pass_buf_len, &pass); return secrets_store(trustdom_keystr(domain), (void *)&pass_buf, pass_len); }
static NTSTATUS name_to_sid(struct rpc_pipe_client *pipe_hnd, TALLOC_CTX *mem_ctx, struct dom_sid *sid, const char *name) { struct policy_handle pol; enum lsa_SidType *sid_types; NTSTATUS status, result; struct dom_sid *sids; struct dcerpc_binding_handle *b = pipe_hnd->binding_handle; /* maybe its a raw SID */ if ( strncmp(name, "S-", 2) == 0 && string_to_sid(sid, name) ) { return NT_STATUS_OK; } status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true, SEC_FLAG_MAXIMUM_ALLOWED, &pol); if ( !NT_STATUS_IS_OK(status) ) return status; status = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &pol, 1, &name, NULL, 1, &sids, &sid_types); if ( NT_STATUS_IS_OK(status) ) sid_copy( sid, &sids[0] ); dcerpc_lsa_Close(b, mem_ctx, &pol, &result); return status; }
BOOL pdb_set_group_sid_from_rid (struct samu *sampass, uint32 grid, enum pdb_value_state flag) { DOM_SID g_sid; const DOM_SID *global_sam_sid; if (!sampass) return False; if (!(global_sam_sid = get_global_sam_sid())) { DEBUG(1, ("pdb_set_user_sid_from_rid: Could not read global sam sid!\n")); return False; } sid_copy(&g_sid, global_sam_sid); if (!sid_append_rid(&g_sid, grid)) return False; if (!pdb_set_group_sid(sampass, &g_sid, flag)) return False; DEBUG(10, ("pdb_set_group_sid_from_rid:\n\tsetting group sid %s from rid %d\n", sid_string_static(&g_sid), grid)); return True; }
BOOL map_name_to_wellknown_sid(DOM_SID *sid, enum SID_NAME_USE *use, const char *name) { int i, j; if (!sid_name_map_initialized) init_sid_name_map(); DEBUG(10,("map_name_to_wellknown_sid: looking up %s\n", name)); for (i=0; sid_name_map[i].sid != NULL; i++) { const known_sid_users *users = sid_name_map[i].known_users; if (users == NULL) continue; for (j=0; users[j].known_user_name != NULL; j++) { if ( strequal(users[j].known_user_name, name) ) { sid_copy(sid, sid_name_map[i].sid); sid_append_rid(sid, users[j].rid); *use = users[j].sid_name_use; return True; } } } return False; }
BOOL winbind_gid_to_sid(DOM_SID *sid, gid_t gid) { struct winbindd_request request; struct winbindd_response response; int result; if (!sid) return False; /* Initialise request */ ZERO_STRUCT(request); ZERO_STRUCT(response); request.data.gid = gid; /* Make request */ result = winbindd_request(WINBINDD_GID_TO_SID, &request, &response); /* Copy out result */ if (result == NSS_STATUS_SUCCESS) { if (!string_to_sid(sid, response.data.sid.sid)) return False; } else { sid_copy(sid, &global_sid_NULL); } return (result == NSS_STATUS_SUCCESS); }
static void store_gid_sid_cache(const DOM_SID *psid, const enum SID_NAME_USE sidtype, gid_t gid) { struct gid_sid_cache *pc; if (n_gid_sid_cache >= MAX_GID_SID_CACHE_SIZE && n_gid_sid_cache > TURNOVER_GID_SID_CACHE_SIZE) { /* Delete the last TURNOVER_GID_SID_CACHE_SIZE entries. */ struct gid_sid_cache *pc_next; size_t i; for (i = 0, pc = gid_sid_cache_head; i < (n_gid_sid_cache - TURNOVER_GID_SID_CACHE_SIZE); i++, pc = pc->next) ; for(; pc; pc = pc_next) { pc_next = pc->next; DLIST_REMOVE(gid_sid_cache_head,pc); SAFE_FREE(pc); n_gid_sid_cache--; } } pc = (struct gid_sid_cache *)malloc(sizeof(struct gid_sid_cache)); if (!pc) return; pc->gid = gid; sid_copy(&pc->sid, psid); pc->sidtype = sidtype; DLIST_ADD(gid_sid_cache_head, pc); n_gid_sid_cache++; }
static NTSTATUS name_to_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx, DOM_SID *sid, const char *name) { POLICY_HND pol; uint32 *sid_types; NTSTATUS result; DOM_SID *sids; /* maybe its a raw SID */ if ( strncmp(name, "S-", 2) == 0 && string_to_sid(sid, name) ) { return NT_STATUS_OK; } result = cli_lsa_open_policy(cli, mem_ctx, True, SEC_RIGHTS_MAXIMUM_ALLOWED, &pol); if ( !NT_STATUS_IS_OK(result) ) return result; result = cli_lsa_lookup_names(cli, mem_ctx, &pol, 1, &name, &sids, &sid_types); if ( NT_STATUS_IS_OK(result) ) sid_copy( sid, &sids[0] ); cli_lsa_close(cli, mem_ctx, &pol); return result; }
NTSTATUS net_rpc_lookup_name(struct net_context *c, TALLOC_CTX *mem_ctx, struct cli_state *cli, const char *name, const char **ret_domain, const char **ret_name, DOM_SID *ret_sid, enum lsa_SidType *ret_type) { struct rpc_pipe_client *lsa_pipe; POLICY_HND pol; NTSTATUS result = NT_STATUS_OK; const char **dom_names; DOM_SID *sids; enum lsa_SidType *types; ZERO_STRUCT(pol); result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, &lsa_pipe); if (!NT_STATUS_IS_OK(result)) { d_fprintf(stderr, "Could not initialise lsa pipe\n"); return result; } result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, false, SEC_RIGHTS_MAXIMUM_ALLOWED, &pol); if (!NT_STATUS_IS_OK(result)) { d_fprintf(stderr, "open_policy failed: %s\n", nt_errstr(result)); return result; } result = rpccli_lsa_lookup_names(lsa_pipe, mem_ctx, &pol, 1, &name, &dom_names, 1, &sids, &types); if (!NT_STATUS_IS_OK(result)) { /* This can happen easily, don't log an error */ goto done; } if (ret_domain != NULL) { *ret_domain = dom_names[0]; } if (ret_name != NULL) { *ret_name = talloc_strdup(mem_ctx, name); } if (ret_sid != NULL) { sid_copy(ret_sid, &sids[0]); } if (ret_type != NULL) { *ret_type = types[0]; } done: if (is_valid_policy_hnd(&pol)) { rpccli_lsa_Close(lsa_pipe, mem_ctx, &pol); } TALLOC_FREE(lsa_pipe); return result; }
static NTSTATUS name_to_sid(struct rpc_pipe_client *pipe_hnd, TALLOC_CTX *mem_ctx, DOM_SID *sid, const char *name) { struct policy_handle pol; enum lsa_SidType *sid_types; NTSTATUS result; DOM_SID *sids; /* maybe its a raw SID */ if ( strncmp(name, "S-", 2) == 0 && string_to_sid(sid, name) ) { return NT_STATUS_OK; } result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true, SEC_FLAG_MAXIMUM_ALLOWED, &pol); if ( !NT_STATUS_IS_OK(result) ) return result; result = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &pol, 1, &name, NULL, 1, &sids, &sid_types); if ( NT_STATUS_IS_OK(result) ) sid_copy( sid, &sids[0] ); rpccli_lsa_Close(pipe_hnd, mem_ctx, &pol); return result; }
/* convert a single name to a sid in a domain */ static NTSTATUS sam_name_to_sid(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const char *domain_name, const char *name, uint32_t flags, struct dom_sid *psid, enum lsa_SidType *ptype) { struct rpc_pipe_client *lsa_pipe; struct policy_handle lsa_policy; struct dom_sid sid; enum lsa_SidType type; TALLOC_CTX *tmp_ctx; NTSTATUS status, result; struct dcerpc_binding_handle *b = NULL; DEBUG(3,("sam_name_to_sid\n")); ZERO_STRUCT(lsa_policy); tmp_ctx = talloc_stackframe(); if (tmp_ctx == NULL) { return NT_STATUS_NO_MEMORY; } status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy); if (!NT_STATUS_IS_OK(status)) { goto done; } b = lsa_pipe->binding_handle; status = rpc_name_to_sid(tmp_ctx, lsa_pipe, &lsa_policy, domain_name, name, flags, &sid, &type); if (!NT_STATUS_IS_OK(status)) { goto done; } if (psid) { sid_copy(psid, &sid); } if (ptype) { *ptype = type; } done: if (b && is_valid_policy_hnd(&lsa_policy)) { dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result); } TALLOC_FREE(tmp_ctx); return status; }
bool sid_check_is_in_our_domain(const struct dom_sid *sid) { struct dom_sid dom_sid; sid_copy(&dom_sid, sid); sid_split_rid(&dom_sid, NULL); return sid_check_is_domain(&dom_sid); }
bool sid_check_is_in_our_domain(const DOM_SID *sid) { DOM_SID dom_sid; uint32 rid; sid_copy(&dom_sid, sid); sid_split_rid(&dom_sid, &rid); return sid_check_is_domain(&dom_sid); }
/******************************************************************* copy a SEC_ACE structure. ********************************************************************/ void sec_ace_copy(SEC_ACE *ace_dest, SEC_ACE *ace_src) { ace_dest->type = ace_src->type; ace_dest->flags = ace_src->flags; ace_dest->size = ace_src->size; ace_dest->access_mask = ace_src->access_mask; ace_dest->object = ace_src->object; sid_copy(&ace_dest->trustee, &ace_src->trustee); }
bool sid_check_is_in_unix_groups(const DOM_SID *sid) { DOM_SID dom_sid; uint32 rid; sid_copy(&dom_sid, sid); sid_split_rid(&dom_sid, &rid); return sid_check_is_unix_groups(&dom_sid); }
BOOL sid_check_is_in_our_domain(const DOM_SID *sid) { DOM_SID dom_sid; uint32 rid; sid_copy(&dom_sid, sid); sid_split_rid(&dom_sid, &rid); return sid_equal(&dom_sid, get_global_sam_sid()); }
void init_sec_ace(SEC_ACE *t, const DOM_SID *sid, uint8 type, SEC_ACCESS mask, uint8 flag) { t->type = type; t->flags = flag; t->size = sid_size(sid) + 8; t->access_mask = mask; ZERO_STRUCTP(&t->trustee); sid_copy(&t->trustee, sid); }
BOOL sid_check_is_in_builtin(const DOM_SID *sid) { DOM_SID dom_sid; uint32 rid; sid_copy(&dom_sid, sid); sid_split_rid(&dom_sid, &rid); return sid_equal(&dom_sid, &global_sid_Builtin); }
/******************************************************************* copy a SEC_ACE structure. ********************************************************************/ void sec_ace_copy(SEC_ACE *ace_dest, SEC_ACE *ace_src) { ace_dest->type = ace_src->type; ace_dest->flags = ace_src->flags; ace_dest->size = ace_src->size; ace_dest->access_mask = ace_src->access_mask; ace_dest->obj_flags = ace_src->obj_flags; memcpy(&ace_dest->obj_guid, &ace_src->obj_guid, sizeof(struct GUID)); memcpy(&ace_dest->inh_guid, &ace_src->inh_guid, sizeof(struct GUID)); sid_copy(&ace_dest->trustee, &ace_src->trustee); }
void init_sec_ace(SEC_ACE *t, const DOM_SID *sid, enum security_ace_type type, uint32 mask, uint8 flag) { t->type = type; t->flags = flag; t->size = ndr_size_dom_sid(sid, 0) + 8; t->access_mask = mask; ZERO_STRUCTP(&t->trustee); sid_copy(&t->trustee, sid); }
/******************************************************************* copy a SEC_ACE structure. ********************************************************************/ void sec_ace_copy(SEC_ACE *ace_dest, SEC_ACE *ace_src) { ace_dest->type = ace_src->type; ace_dest->flags = ace_src->flags; ace_dest->size = ace_src->size; ace_dest->info.mask = ace_src->info.mask; ace_dest->obj_flags = ace_src->obj_flags; memcpy(&ace_dest->obj_guid, &ace_src->obj_guid, GUID_SIZE); memcpy(&ace_dest->inh_guid, &ace_src->inh_guid, GUID_SIZE); sid_copy(&ace_dest->trustee, &ace_src->trustee); }
void add_sid_to_array(const DOM_SID *sid, DOM_SID **sids, int *num) { *sids = SMB_REALLOC_ARRAY(*sids, DOM_SID, (*num)+1); if (*sids == NULL) return; sid_copy(&((*sids)[*num]), sid); *num += 1; return; }
static NTSTATUS libnetapi_lsa_lookup_names3(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *lsa_pipe, const char *name, struct dom_sid *sid) { NTSTATUS status, result; struct policy_handle lsa_handle; struct dcerpc_binding_handle *b = lsa_pipe->binding_handle; struct lsa_RefDomainList *domains = NULL; struct lsa_TransSidArray3 sids; uint32_t count = 0; struct lsa_String names; uint32_t num_names = 1; if (!sid || !name) { return NT_STATUS_INVALID_PARAMETER; } ZERO_STRUCT(sids); init_lsa_String(&names, name); status = rpccli_lsa_open_policy2(lsa_pipe, mem_ctx, false, SEC_STD_READ_CONTROL | LSA_POLICY_VIEW_LOCAL_INFORMATION | LSA_POLICY_LOOKUP_NAMES, &lsa_handle); NT_STATUS_NOT_OK_RETURN(status); status = dcerpc_lsa_LookupNames3(b, mem_ctx, &lsa_handle, num_names, &names, &domains, &sids, LSA_LOOKUP_NAMES_ALL, /* sure ? */ &count, 0, 0, &result); NT_STATUS_NOT_OK_RETURN(status); NT_STATUS_NOT_OK_RETURN(result); if (count != 1 || sids.count != 1) { return NT_STATUS_INVALID_NETWORK_RESPONSE; } sid_copy(sid, sids.sids[0].sid); return NT_STATUS_OK; }
bool pdb_set_user_sid(struct samu *sampass, const DOM_SID *u_sid, enum pdb_value_state flag) { if (!u_sid) return False; sid_copy(&sampass->user_sid, u_sid); DEBUG(10, ("pdb_set_user_sid: setting user sid %s\n", sid_string_dbg(&sampass->user_sid))); return pdb_set_init_flags(sampass, PDB_USERSID, flag); }
void add_sid_to_array(const DOM_SID *sid, DOM_SID **sids, int *num) { *sids = Realloc(*sids, ((*num)+1) * sizeof(DOM_SID)); if (*sids == NULL) return; sid_copy(&((*sids)[*num]), sid); *num += 1; return; }