summaryrefslogtreecommitdiff
path: root/source3/passdb
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2004-04-07 12:43:44 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 10:51:10 -0500
commit7af3777ab32ee220700ed3367d07ca18b2bbdd47 (patch)
tree73589edee11ba3560ce092b3ac438c8111a65880 /source3/passdb
parentf79e40072a963fd3b9698fa26c4e4dc135ab8c3e (diff)
downloadsamba-7af3777ab32ee220700ed3367d07ca18b2bbdd47.tar.gz
samba-7af3777ab32ee220700ed3367d07ca18b2bbdd47.tar.bz2
samba-7af3777ab32ee220700ed3367d07ca18b2bbdd47.zip
r116: volker's patch for local group and group nesting
(This used to be commit b393469d9581f20e4d4c52633b952ee984cca36f)
Diffstat (limited to 'source3/passdb')
-rw-r--r--source3/passdb/pdb_interface.c300
-rw-r--r--source3/passdb/pdb_ldap.c288
-rw-r--r--source3/passdb/util_sam_sid.c13
3 files changed, 599 insertions, 2 deletions
diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c
index 06097d3557..a3b2706c35 100644
--- a/source3/passdb/pdb_interface.c
+++ b/source3/passdb/pdb_interface.c
@@ -452,6 +452,156 @@ static NTSTATUS context_enum_group_mapping(struct pdb_context *context,
num_entries, unix_only);
}
+static NTSTATUS context_find_alias(struct pdb_context *context,
+ const char *name, DOM_SID *sid)
+{
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+
+ if ((!context) || (!context->pdb_methods)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return ret;
+ }
+
+ return context->pdb_methods->find_alias(context->pdb_methods,
+ name, sid);
+}
+
+static NTSTATUS context_create_alias(struct pdb_context *context,
+ const char *name, uint32 *rid)
+{
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+
+ if ((!context) || (!context->pdb_methods)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return ret;
+ }
+
+ return context->pdb_methods->create_alias(context->pdb_methods,
+ name, rid);
+}
+
+static NTSTATUS context_delete_alias(struct pdb_context *context,
+ const DOM_SID *sid)
+{
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+
+ if ((!context) || (!context->pdb_methods)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return ret;
+ }
+
+ return context->pdb_methods->delete_alias(context->pdb_methods, sid);
+}
+
+static NTSTATUS context_enum_aliases(struct pdb_context *context,
+ const DOM_SID *sid,
+ uint32 start_idx, uint32 max_entries,
+ uint32 *num_aliases,
+ struct acct_info **info)
+{
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+
+ if ((!context) || (!context->pdb_methods)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return ret;
+ }
+
+ return context->pdb_methods->enum_aliases(context->pdb_methods,
+ sid, start_idx, max_entries,
+ num_aliases, info);
+}
+
+static NTSTATUS context_get_aliasinfo(struct pdb_context *context,
+ const DOM_SID *sid,
+ struct acct_info *info)
+{
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+
+ if ((!context) || (!context->pdb_methods)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return ret;
+ }
+
+ return context->pdb_methods->get_aliasinfo(context->pdb_methods,
+ sid, info);
+}
+
+static NTSTATUS context_set_aliasinfo(struct pdb_context *context,
+ const DOM_SID *sid,
+ struct acct_info *info)
+{
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+
+ if ((!context) || (!context->pdb_methods)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return ret;
+ }
+
+ return context->pdb_methods->set_aliasinfo(context->pdb_methods,
+ sid, info);
+}
+
+static NTSTATUS context_add_aliasmem(struct pdb_context *context,
+ const DOM_SID *alias,
+ const DOM_SID *member)
+{
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+
+ if ((!context) || (!context->pdb_methods)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return ret;
+ }
+
+ return context->pdb_methods->add_aliasmem(context->pdb_methods,
+ alias, member);
+}
+
+static NTSTATUS context_del_aliasmem(struct pdb_context *context,
+ const DOM_SID *alias,
+ const DOM_SID *member)
+{
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+
+ if ((!context) || (!context->pdb_methods)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return ret;
+ }
+
+ return context->pdb_methods->del_aliasmem(context->pdb_methods,
+ alias, member);
+}
+
+static NTSTATUS context_enum_aliasmem(struct pdb_context *context,
+ const DOM_SID *alias, DOM_SID **members,
+ int *num)
+{
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+
+ if ((!context) || (!context->pdb_methods)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return ret;
+ }
+
+ return context->pdb_methods->enum_aliasmem(context->pdb_methods,
+ alias, members, num);
+}
+
+static NTSTATUS context_enum_alias_memberships(struct pdb_context *context,
+ const DOM_SID *sid,
+ DOM_SID **aliases, int *num)
+{
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+
+ if ((!context) || (!context->pdb_methods)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return ret;
+ }
+
+ return context->pdb_methods->
+ enum_alias_memberships(context->pdb_methods, sid, aliases,
+ num);
+}
+
/******************************************************************
Free and cleanup a pdb context, any associated data and anything
that the attached modules might have associated.
@@ -568,6 +718,17 @@ static NTSTATUS make_pdb_context(struct pdb_context **context)
(*context)->pdb_delete_group_mapping_entry = context_delete_group_mapping_entry;
(*context)->pdb_enum_group_mapping = context_enum_group_mapping;
+ (*context)->pdb_find_alias = context_find_alias;
+ (*context)->pdb_create_alias = context_create_alias;
+ (*context)->pdb_delete_alias = context_delete_alias;
+ (*context)->pdb_enum_aliases = context_enum_aliases;
+ (*context)->pdb_get_aliasinfo = context_get_aliasinfo;
+ (*context)->pdb_set_aliasinfo = context_set_aliasinfo;
+ (*context)->pdb_add_aliasmem = context_add_aliasmem;
+ (*context)->pdb_del_aliasmem = context_del_aliasmem;
+ (*context)->pdb_enum_aliasmem = context_enum_aliasmem;
+ (*context)->pdb_enum_alias_memberships = context_enum_alias_memberships;
+
(*context)->free_fn = free_pdb_context;
return NT_STATUS_OK;
@@ -850,6 +1011,135 @@ BOOL pdb_enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap,
rmap, num_entries, unix_only));
}
+BOOL pdb_find_alias(const char *name, DOM_SID *sid)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return False;
+ }
+
+ return NT_STATUS_IS_OK(pdb_context->pdb_find_alias(pdb_context,
+ name, sid));
+}
+
+BOOL pdb_create_alias(const char *name, uint32 *rid)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return False;
+ }
+
+ return NT_STATUS_IS_OK(pdb_context->pdb_create_alias(pdb_context,
+ name, rid));
+}
+
+BOOL pdb_delete_alias(const DOM_SID *sid)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return False;
+ }
+
+ return NT_STATUS_IS_OK(pdb_context->pdb_delete_alias(pdb_context,
+ sid));
+
+}
+
+BOOL pdb_enum_aliases(const DOM_SID *sid, uint32 start_idx, uint32 max_entries,
+ uint32 *num_aliases, struct acct_info **info)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return False;
+ }
+
+ return NT_STATUS_IS_OK(pdb_context->pdb_enum_aliases(pdb_context, sid,
+ start_idx,
+ max_entries,
+ num_aliases,
+ info));
+}
+
+BOOL pdb_get_aliasinfo(const DOM_SID *sid, struct acct_info *info)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return False;
+ }
+
+ return NT_STATUS_IS_OK(pdb_context->pdb_get_aliasinfo(pdb_context, sid,
+ info));
+}
+
+BOOL pdb_set_aliasinfo(const DOM_SID *sid, struct acct_info *info)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return False;
+ }
+
+ return NT_STATUS_IS_OK(pdb_context->pdb_set_aliasinfo(pdb_context, sid,
+ info));
+}
+
+BOOL pdb_add_aliasmem(const DOM_SID *alias, const DOM_SID *member)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return False;
+ }
+
+ return NT_STATUS_IS_OK(pdb_context->
+ pdb_add_aliasmem(pdb_context, alias, member));
+}
+
+BOOL pdb_del_aliasmem(const DOM_SID *alias, const DOM_SID *member)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return False;
+ }
+
+ return NT_STATUS_IS_OK(pdb_context->
+ pdb_del_aliasmem(pdb_context, alias, member));
+}
+
+BOOL pdb_enum_aliasmem(const DOM_SID *alias,
+ DOM_SID **members, int *num_members)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return False;
+ }
+
+ return NT_STATUS_IS_OK(pdb_context->
+ pdb_enum_aliasmem(pdb_context, alias,
+ members, num_members));
+}
+
+BOOL pdb_enum_alias_memberships(const DOM_SID *sid,
+ DOM_SID **aliases, int *num)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return False;
+ }
+
+ return NT_STATUS_IS_OK(pdb_context->
+ pdb_enum_alias_memberships(pdb_context, sid,
+ aliases, num));
+}
+
/***************************************************************
Initialize the static context (at smbd startup etc).
@@ -933,6 +1223,16 @@ NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods)
(*methods)->update_group_mapping_entry = pdb_default_update_group_mapping_entry;
(*methods)->delete_group_mapping_entry = pdb_default_delete_group_mapping_entry;
(*methods)->enum_group_mapping = pdb_default_enum_group_mapping;
+ (*methods)->find_alias = pdb_default_find_alias;
+ (*methods)->create_alias = pdb_default_create_alias;
+ (*methods)->delete_alias = pdb_default_delete_alias;
+ (*methods)->enum_aliases = pdb_default_enum_aliases;
+ (*methods)->get_aliasinfo = pdb_default_get_aliasinfo;
+ (*methods)->set_aliasinfo = pdb_default_set_aliasinfo;
+ (*methods)->add_aliasmem = pdb_default_add_aliasmem;
+ (*methods)->del_aliasmem = pdb_default_del_aliasmem;
+ (*methods)->enum_aliasmem = pdb_default_enum_aliasmem;
+ (*methods)->enum_alias_memberships = pdb_default_alias_memberships;
return NT_STATUS_OK;
}
diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c
index 307d187f66..15635a034c 100644
--- a/source3/passdb/pdb_ldap.c
+++ b/source3/passdb/pdb_ldap.c
@@ -1989,8 +1989,8 @@ static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state,
{
pstring filter;
- pstr_sprintf(filter, "(&(objectClass=%s)(%s=%lu))",
- LDAP_OBJ_POSIXGROUP,
+ pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%lu))",
+ LDAP_OBJ_POSIXGROUP, LDAP_OBJ_IDMAP_ENTRY,
get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
(unsigned long)gid);
@@ -2032,6 +2032,37 @@ static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
if ( count == 0 ) {
+ /* There's no posixGroup account, let's try to find an
+ * appropriate idmap entry for aliases */
+
+ pstring suffix;
+ pstring filter;
+ char **attr_list;
+
+ ldap_msgfree(result);
+
+ pstrcpy( suffix, lp_ldap_idmap_suffix() );
+ pstr_sprintf(filter, "(&(objectClass=%s)(%s=%u))",
+ LDAP_OBJ_IDMAP_ENTRY, LDAP_ATTRIBUTE_GIDNUMBER,
+ map->gid);
+
+ attr_list = get_attr_list( sidmap_attr_list );
+ rc = smbldap_search(ldap_state->smbldap_state, suffix,
+ LDAP_SCOPE_SUBTREE, filter, attr_list,
+ 0, &result);
+
+ free_attr_list(attr_list);
+
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(3,("Failure looking up entry (%s)\n",
+ ldap_err2string(rc) ));
+ ldap_msgfree(result);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+
+ count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
+ if ( count == 0 ) {
ldap_msgfree(result);
return NT_STATUS_UNSUCCESSFUL;
}
@@ -2306,6 +2337,254 @@ static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
return NT_STATUS_OK;
}
+static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods,
+ const DOM_SID *alias,
+ const DOM_SID *member,
+ int modop)
+{
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)methods->private_data;
+ char *dn;
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry = NULL;
+ int count;
+ LDAPMod **mods = NULL;
+ int rc;
+
+ pstring filter;
+
+ pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%s))",
+ LDAP_OBJ_GROUPMAP, LDAP_OBJ_IDMAP_ENTRY,
+ get_attr_key2string(groupmap_attr_list,
+ LDAP_ATTR_GROUP_SID),
+ sid_string_static(alias));
+
+ if (ldapsam_search_one_group(ldap_state, filter,
+ &result) != LDAP_SUCCESS)
+ return NT_STATUS_NO_SUCH_ALIAS;
+
+ count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
+ result);
+
+ if (count < 1) {
+ DEBUG(4, ("ldapsam_add_aliasmem: Did not find alias\n"));
+ ldap_msgfree(result);
+ return NT_STATUS_NO_SUCH_ALIAS;
+ }
+
+ if (count > 1) {
+ DEBUG(1, ("ldapsam_getgroup: Duplicate entries for filter %s: "
+ "count=%d\n", filter, count));
+ ldap_msgfree(result);
+ return NT_STATUS_NO_SUCH_ALIAS;
+ }
+
+ entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
+ result);
+
+ if (!entry) {
+ ldap_msgfree(result);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
+ if (!dn) {
+ ldap_msgfree(result);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ smbldap_set_mod(&mods, modop,
+ get_attr_key2string(groupmap_attr_list,
+ LDAP_ATTR_SID_LIST),
+ sid_string_static(member));
+
+ rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
+
+ ldap_mods_free(mods, True);
+ ldap_msgfree(result);
+
+ if (rc != LDAP_SUCCESS) {
+ char *ld_error = NULL;
+ ldap_get_option(ldap_state->smbldap_state->ldap_struct,
+ LDAP_OPT_ERROR_STRING,&ld_error);
+
+ DEBUG(0, ("ldapsam_delete_entry: Could not delete attributes "
+ "for %s, error: %s (%s)\n", dn, ldap_err2string(rc),
+ ld_error?ld_error:"unknown"));
+ SAFE_FREE(ld_error);
+ SAFE_FREE(dn);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ SAFE_FREE(dn);
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS ldapsam_add_aliasmem(struct pdb_methods *methods,
+ const DOM_SID *alias,
+ const DOM_SID *member)
+{
+ return ldapsam_modify_aliasmem(methods, alias, member, LDAP_MOD_ADD);
+}
+
+static NTSTATUS ldapsam_del_aliasmem(struct pdb_methods *methods,
+ const DOM_SID *alias,
+ const DOM_SID *member)
+{
+ return ldapsam_modify_aliasmem(methods, alias, member,
+ LDAP_MOD_DELETE);
+}
+
+static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods,
+ const DOM_SID *alias, DOM_SID **members,
+ int *num_members)
+{
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)methods->private_data;
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry = NULL;
+ int count;
+ char **values;
+ int i;
+ pstring filter;
+
+ *members = NULL;
+ *num_members = 0;
+
+ pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%s))",
+ LDAP_OBJ_GROUPMAP, LDAP_OBJ_IDMAP_ENTRY,
+ get_attr_key2string(groupmap_attr_list,
+ LDAP_ATTR_GROUP_SID),
+ sid_string_static(alias));
+
+ if (ldapsam_search_one_group(ldap_state, filter,
+ &result) != LDAP_SUCCESS)
+ return NT_STATUS_NO_SUCH_ALIAS;
+
+ count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
+ result);
+
+ if (count < 1) {
+ DEBUG(4, ("ldapsam_add_aliasmem: Did not find alias\n"));
+ ldap_msgfree(result);
+ return NT_STATUS_NO_SUCH_ALIAS;
+ }
+
+ if (count > 1) {
+ DEBUG(1, ("ldapsam_getgroup: Duplicate entries for filter %s: "
+ "count=%d\n", filter, count));
+ ldap_msgfree(result);
+ return NT_STATUS_NO_SUCH_ALIAS;
+ }
+
+ entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
+ result);
+
+ if (!entry) {
+ ldap_msgfree(result);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ values = ldap_get_values(ldap_state->smbldap_state->ldap_struct,
+ entry,
+ get_attr_key2string(groupmap_attr_list,
+ LDAP_ATTR_SID_LIST));
+
+ if (values == NULL) {
+ ldap_msgfree(result);
+ return NT_STATUS_OK;
+ }
+
+ count = ldap_count_values(values);
+
+ for (i=0; i<count; i++) {
+ DOM_SID member;
+
+ if (!string_to_sid(&member, values[i]))
+ continue;
+
+ add_sid_to_array(&member, members, num_members);
+ }
+
+ ldap_value_free(values);
+ ldap_msgfree(result);
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods,
+ const DOM_SID *sid,
+ DOM_SID **aliases, int *num)
+{
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)methods->private_data;
+
+ fstring sid_string;
+ const char *attrs[] = { LDAP_ATTRIBUTE_SID, NULL };
+
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry = NULL;
+ int count;
+ int rc;
+ pstring filter;
+
+ sid_to_string(sid_string, sid);
+ pstr_sprintf(filter, "(&(|(objectclass=%s)(objectclass=%s))(%s=%s))",
+ LDAP_OBJ_GROUPMAP, LDAP_OBJ_IDMAP_ENTRY,
+ get_attr_key2string(groupmap_attr_list,
+ LDAP_ATTR_SID_LIST), sid_string);
+
+ rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_group_suffix(),
+ LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result);
+
+ if (rc != LDAP_SUCCESS)
+ return NT_STATUS_UNSUCCESSFUL;
+
+ *aliases = NULL;
+ *num = 0;
+
+ count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
+ result);
+
+ if (count < 1) {
+ ldap_msgfree(result);
+ return NT_STATUS_OK;
+ }
+
+
+ for (entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
+ result);
+ entry != NULL;
+ entry = ldap_next_entry(ldap_state->smbldap_state->ldap_struct,
+ entry))
+ {
+ DOM_SID alias;
+ char **vals;
+ vals = ldap_get_values(ldap_state->smbldap_state->ldap_struct,
+ entry, LDAP_ATTRIBUTE_SID);
+
+ if (vals == NULL)
+ continue;
+
+ if (vals[0] == NULL) {
+ ldap_value_free(vals);
+ continue;
+ }
+
+ if (!string_to_sid(&alias, vals[0])) {
+ ldap_value_free(vals);
+ continue;
+ }
+
+ add_sid_to_array(&alias, aliases, num);
+ ldap_value_free(vals);
+ }
+
+ ldap_msgfree(result);
+ return NT_STATUS_OK;
+}
+
/**********************************************************************
Housekeeping
*********************************************************************/
@@ -2444,6 +2723,11 @@ static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_met
(*pdb_method)->name = "ldapsam";
+ (*pdb_method)->add_aliasmem = ldapsam_add_aliasmem;
+ (*pdb_method)->del_aliasmem = ldapsam_del_aliasmem;
+ (*pdb_method)->enum_aliasmem = ldapsam_enum_aliasmem;
+ (*pdb_method)->enum_alias_memberships = ldapsam_alias_memberships;
+
ldap_state = (*pdb_method)->private_data;
ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT;
diff --git a/source3/passdb/util_sam_sid.c b/source3/passdb/util_sam_sid.c
index f6cc2491a8..63ef5914af 100644
--- a/source3/passdb/util_sam_sid.c
+++ b/source3/passdb/util_sam_sid.c
@@ -305,3 +305,16 @@ BOOL map_name_to_wellknown_sid(DOM_SID *sid, enum SID_NAME_USE *use, const char
return False;
}
+
+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;
+}