summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/groupdb/mapping.c47
-rw-r--r--source3/include/passdb.h86
-rw-r--r--source3/include/smb_macros.h3
-rw-r--r--source3/include/smbldap.h1
-rw-r--r--source3/lib/smbldap.c158
-rw-r--r--source3/lib/util.c50
-rw-r--r--source3/nsswitch/winbindd_passdb.c34
-rw-r--r--source3/param/loadparm.c4
-rw-r--r--source3/passdb/pdb_interface.c401
-rw-r--r--source3/passdb/pdb_ldap.c469
-rw-r--r--source3/rpc_parse/parse_samr.c221
-rw-r--r--source3/rpc_server/srv_samr_nt.c818
12 files changed, 1317 insertions, 975 deletions
diff --git a/source3/groupdb/mapping.c b/source3/groupdb/mapping.c
index 6e9d9b8e6c..459c66bdf7 100644
--- a/source3/groupdb/mapping.c
+++ b/source3/groupdb/mapping.c
@@ -1247,53 +1247,6 @@ NTSTATUS pdb_default_delete_alias(struct pdb_methods *methods,
NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
}
-NTSTATUS pdb_default_enum_aliases(struct pdb_methods *methods,
- const DOM_SID *sid,
- uint32 start_idx, uint32 max_entries,
- uint32 *num_aliases,
- struct acct_info **info)
-{
- GROUP_MAP *map;
- int i, num_maps;
- enum SID_NAME_USE type = SID_NAME_UNKNOWN;
-
- if (sid_compare(sid, get_global_sam_sid()) == 0)
- type = SID_NAME_ALIAS;
-
- if (sid_compare(sid, &global_sid_Builtin) == 0)
- type = SID_NAME_WKN_GRP;
-
- if (!pdb_enum_group_mapping(type, &map, &num_maps, False) ||
- (num_maps == 0)) {
- *num_aliases = 0;
- *info = NULL;
- goto done;
- }
-
- if (start_idx > num_maps) {
- *num_aliases = 0;
- *info = NULL;
- goto done;
- }
-
- *num_aliases = num_maps - start_idx;
-
- if (*num_aliases > max_entries)
- *num_aliases = max_entries;
-
- *info = SMB_MALLOC_ARRAY(struct acct_info, *num_aliases);
-
- for (i=0; i<*num_aliases; i++) {
- fstrcpy((*info)[i].acct_name, map[i+start_idx].nt_name);
- fstrcpy((*info)[i].acct_desc, map[i+start_idx].comment);
- sid_peek_rid(&map[i].sid, &(*info)[i+start_idx].rid);
- }
-
- done:
- SAFE_FREE(map);
- return NT_STATUS_OK;
-}
-
NTSTATUS pdb_default_get_aliasinfo(struct pdb_methods *methods,
const DOM_SID *sid,
struct acct_info *info)
diff --git a/source3/include/passdb.h b/source3/include/passdb.h
index 624f0c5fea..0c816271b0 100644
--- a/source3/include/passdb.h
+++ b/source3/include/passdb.h
@@ -232,6 +232,30 @@ struct acct_info
uint32 rid; /* domain-relative RID */
};
+struct samr_displayentry {
+ uint32 rid;
+ uint16 acct_flags;
+ const char *account_name;
+ const char *fullname;
+ const char *description;
+};
+
+enum pdb_search_type {
+ PDB_USER_SEARCH,
+ PDB_GROUP_SEARCH,
+ PDB_ALIAS_SEARCH
+};
+
+struct pdb_search {
+ TALLOC_CTX *mem_ctx;
+ enum pdb_search_type type;
+ struct samr_displayentry *cache;
+ uint32 num_entries;
+ ssize_t cache_size;
+ BOOL search_ended;
+ void *private;
+};
+
/*****************************************************************
Functions to be implemented by the new (v2) passdb API
****************************************************************/
@@ -310,12 +334,6 @@ typedef struct pdb_context
NTSTATUS (*pdb_delete_alias)(struct pdb_context *context,
const DOM_SID *sid);
- NTSTATUS (*pdb_enum_aliases)(struct pdb_context *context,
- const DOM_SID *domain_sid,
- uint32 start_idx, uint32 num_entries,
- uint32 *num_aliases,
- struct acct_info **aliases);
-
NTSTATUS (*pdb_get_aliasinfo)(struct pdb_context *context,
const DOM_SID *sid,
struct acct_info *info);
@@ -352,6 +370,20 @@ typedef struct pdb_context
const char ***names,
uint32 **attrs);
+ BOOL (*pdb_search_users)(struct pdb_context *context,
+ struct pdb_search *search,
+ uint16 acct_flags);
+ BOOL (*pdb_search_groups)(struct pdb_context *context,
+ struct pdb_search *search);
+ BOOL (*pdb_search_aliases)(struct pdb_context *context,
+ struct pdb_search *search,
+ const DOM_SID *sid);
+ BOOL (*pdb_search_next_entry)(struct pdb_context *context,
+ struct pdb_search *search,
+ struct samr_displayentry *entry);
+ void (*pdb_search_end)(struct pdb_context *context,
+ struct pdb_search *search);
+
void (*free_fn)(struct pdb_context **);
TALLOC_CTX *mem_ctx;
@@ -426,11 +458,6 @@ typedef struct pdb_methods
NTSTATUS (*delete_alias)(struct pdb_methods *methods,
const DOM_SID *sid);
- NTSTATUS (*enum_aliases)(struct pdb_methods *methods,
- const DOM_SID *domain_sid,
- uint32 start_idx, uint32 max_entries,
- uint32 *num_aliases, struct acct_info **info);
-
NTSTATUS (*get_aliasinfo)(struct pdb_methods *methods,
const DOM_SID *sid,
struct acct_info *info);
@@ -461,6 +488,20 @@ typedef struct pdb_methods
const char ***names,
uint32 **attrs);
+ BOOL (*search_users)(struct pdb_methods *methods,
+ struct pdb_search *search,
+ uint16 acct_flags);
+ BOOL (*search_groups)(struct pdb_methods *methods,
+ struct pdb_search *search);
+ BOOL (*search_aliases)(struct pdb_methods *methods,
+ struct pdb_search *search,
+ const DOM_SID *sid);
+ BOOL (*search_next_entry)(struct pdb_methods *methods,
+ struct pdb_search *search,
+ struct samr_displayentry *entry);
+ void (*search_end)(struct pdb_methods *methods,
+ struct pdb_search *search);
+
void *private_data; /* Private data of some kind */
void (*free_private_data)(void **);
@@ -480,27 +521,4 @@ struct pdb_init_function_entry {
enum sql_search_field { SQL_SEARCH_NONE = 0, SQL_SEARCH_USER_SID = 1, SQL_SEARCH_USER_NAME = 2};
-struct samr_displayentry {
- uint32 rid;
- uint16 acct_flags;
- const char *account_name;
- const char *fullname;
- const char *description;
-};
-
-enum pdb_search_type {
- PDB_USER_SEARCH,
- PDB_GROUP_SEARCH,
- PDB_ALIAS_SEARCH
-};
-
-struct pdb_search {
- TALLOC_CTX *mem_ctx;
- enum pdb_search_type type;
- struct samr_displayentry *cache;
- uint32 cache_size;
- BOOL search_ended;
- void *private;
-};
-
#endif /* _PASSDB_H */
diff --git a/source3/include/smb_macros.h b/source3/include/smb_macros.h
index b7a3a68bec..04616eb8ab 100644
--- a/source3/include/smb_macros.h
+++ b/source3/include/smb_macros.h
@@ -362,4 +362,7 @@ do { \
(*(num)) += 1; \
} while (0)
+#define ADD_TO_LARGE_ARRAY(mem_ctx, type, elem, array, num, size) \
+ add_to_large_array((mem_ctx), sizeof(type), &(elem), (void **)(array), (num), (size));
+
#endif /* _SMB_MACROS_H */
diff --git a/source3/include/smbldap.h b/source3/include/smbldap.h
index e6a6a1b7c6..b54b3f4325 100644
--- a/source3/include/smbldap.h
+++ b/source3/include/smbldap.h
@@ -185,5 +185,6 @@ struct ldapsam_privates {
struct smbldap_state;
#define LDAP_CONNECT_DEFAULT_TIMEOUT 15
+#define LDAP_PAGE_SIZE 1024
#endif /* _SMBLDAP_H */
diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c
index cf2f03e0a2..e2d78e0ecc 100644
--- a/source3/lib/smbldap.c
+++ b/source3/lib/smbldap.c
@@ -856,6 +856,7 @@ static int smbldap_connect_system(struct smbldap_state *ldap_state, LDAP * ldap_
}
ldap_state->num_failures = 0;
+ ldap_state->paged_results = False;
ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
@@ -864,7 +865,8 @@ static int smbldap_connect_system(struct smbldap_state *ldap_state, LDAP * ldap_
}
DEBUG(3, ("ldap_connect_system: succesful connection to the LDAP server\n"));
- DEBUGADD(3, ("ldap_connect_system: LDAP server %s support paged results\n", ldap_state->paged_results?"does":"does not"));
+ DEBUGADD(10, ("ldap_connect_system: LDAP server %s support paged results\n",
+ ldap_state->paged_results ? "does" : "does not"));
return rc;
}
@@ -1022,20 +1024,22 @@ static int another_ldap_try(struct smbldap_state *ldap_state, int *rc,
/*********************************************************************
********************************************************************/
-int smbldap_search(struct smbldap_state *ldap_state,
- const char *base, int scope, const char *filter,
- const char *attrs[], int attrsonly,
- LDAPMessage **res)
+static int smbldap_search_ext(struct smbldap_state *ldap_state,
+ const char *base, int scope, const char *filter,
+ const char *attrs[], int attrsonly,
+ LDAPControl **sctrls, LDAPControl **cctrls,
+ int sizelimit, LDAPMessage **res)
{
int rc = LDAP_SERVER_DOWN;
int attempts = 0;
char *utf8_filter;
time_t endtime = time(NULL)+lp_ldap_timeout();
+ struct timeval timeout;
SMB_ASSERT(ldap_state);
- DEBUG(5,("smbldap_search: base => [%s], filter => [%s], scope => [%d]\n",
- base, filter, scope));
+ DEBUG(5,("smbldap_search_ext: base => [%s], filter => [%s], "
+ "scope => [%d]\n", base, filter, scope));
if (ldap_state->last_rebind.tv_sec > 0) {
struct timeval tval;
@@ -1053,9 +1057,10 @@ int smbldap_search(struct smbldap_state *ldap_state,
if (sleep_time > 0) {
/* we wait for the LDAP replication */
- DEBUG(5,("smbldap_search: waiting %d milliseconds for LDAP replication.\n",sleep_time));
+ DEBUG(5,("smbldap_search_ext: waiting %d milliseconds "
+ "for LDAP replication.\n",sleep_time));
smb_msleep(sleep_time);
- DEBUG(5,("smbldap_search: go on!\n"));
+ DEBUG(5,("smbldap_search_ext: go on!\n"));
}
ZERO_STRUCT(ldap_state->last_rebind);
}
@@ -1064,13 +1069,138 @@ int smbldap_search(struct smbldap_state *ldap_state,
return LDAP_NO_MEMORY;
}
+ /* Setup timeout for the ldap_search_ext_s call - local and remote. */
+ timeout.tv_sec = lp_ldap_timeout();
+ timeout.tv_usec = 0;
+
+ /* Setup alarm timeout.... Do we need both of these ? JRA.
+ * Yes, I think we do need both of these. The server timeout only
+ * covers the case where the server's operation takes too long. It
+ * does not cover the case where the request hangs on its way to the
+ * server. The server side timeout is not strictly necessary, it's
+ * just a bit more kind to the server. VL. */
+
+ got_alarm = 0;
+ CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
+ alarm(lp_ldap_timeout());
+ /* End setup timeout. */
+
while (another_ldap_try(ldap_state, &rc, &attempts, endtime))
- rc = ldap_search_s(ldap_state->ldap_struct, base, scope,
- utf8_filter,
- CONST_DISCARD(char **, attrs),
- attrsonly, res);
-
+ rc = ldap_search_ext_s(ldap_state->ldap_struct, base, scope,
+ utf8_filter,
+ CONST_DISCARD(char **, attrs),
+ attrsonly, sctrls, cctrls, &timeout,
+ sizelimit, res);
+
SAFE_FREE(utf8_filter);
+
+ /* Teardown timeout. */
+ CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN);
+ alarm(0);
+
+ if (got_alarm != 0)
+ return LDAP_TIMELIMIT_EXCEEDED;
+
+ return rc;
+}
+
+int smbldap_search(struct smbldap_state *ldap_state,
+ const char *base, int scope, const char *filter,
+ const char *attrs[], int attrsonly,
+ LDAPMessage **res)
+{
+ return smbldap_search_ext(ldap_state, base, scope, filter, attrs,
+ attrsonly, NULL, NULL, LDAP_NO_LIMIT, res);
+}
+
+int smbldap_search_paged(struct smbldap_state *ldap_state,
+ const char *base, int scope, const char *filter,
+ const char **attrs, int attrsonly, int pagesize,
+ LDAPMessage **res, void **cookie)
+{
+ LDAPControl pr;
+ LDAPControl **rcontrols;
+ LDAPControl *controls[2] = { NULL, NULL};
+ BerElement *cookie_be = NULL;
+ struct berval *cookie_bv = NULL;
+ int tmp = 0, i, rc;
+ BOOL critical = True;
+
+ *res = NULL;
+
+ DEBUG(3,("smbldap_search_paged: base => [%s], filter => [%s],"
+ "scope => [%d], pagesize => [%d]\n",
+ base, filter, scope, pagesize));
+
+ cookie_be = ber_alloc_t(LBER_USE_DER);
+ if (cookie_be == NULL) {
+ DEBUG(0,("smbldap_create_page_control: ber_alloc_t returns "
+ "NULL\n"));
+ return LDAP_NO_MEMORY;
+ }
+
+ /* construct cookie */
+ if (*cookie != NULL) {
+ ber_printf(cookie_be, "{iO}", (ber_int_t) pagesize, *cookie);
+ ber_bvfree(*cookie); /* don't need it from last time */
+ *cookie = NULL;
+ } else {
+ ber_printf(cookie_be, "{io}", (ber_int_t) pagesize, "", 0);
+ }
+ ber_flatten(cookie_be, &cookie_bv);
+
+ pr.ldctl_oid = CONST_DISCARD(char *, ADS_PAGE_CTL_OID);
+ pr.ldctl_iscritical = (char) critical;
+ pr.ldctl_value.bv_len = cookie_bv->bv_len;
+ pr.ldctl_value.bv_val = cookie_bv->bv_val;
+
+ controls[0] = &pr;
+ controls[1] = NULL;
+
+ rc = smbldap_search_ext(ldap_state, base, scope, filter, attrs,
+ 0, controls, NULL, LDAP_NO_LIMIT, res);
+
+ ber_free(cookie_be, 1);
+ ber_bvfree(cookie_bv);
+
+ if (rc != 0) {
+ DEBUG(3,("smbldap_search_paged: smbldap_search_ext(%s) "
+ "failed with [%s]\n", filter, ldap_err2string(rc)));
+ goto done;
+ }
+
+ DEBUG(3,("smbldap_search_paged: search was successfull\n"));
+
+ rc = ldap_parse_result(ldap_state->ldap_struct, *res, NULL, NULL,
+ NULL, NULL, &rcontrols, 0);
+ if (rc != 0) {
+ DEBUG(3,("smbldap_search_paged: ldap_parse_result failed " \
+ "with [%s]\n", ldap_err2string(rc)));
+ goto done;
+ }
+
+ if (rcontrols == NULL)
+ goto done;
+
+ for (i=0; rcontrols[i]; i++) {
+
+ if (strcmp(ADS_PAGE_CTL_OID, rcontrols[i]->ldctl_oid) != 0)
+ continue;
+
+ cookie_be = ber_init(&rcontrols[i]->ldctl_value);
+ ber_scanf(cookie_be,"{iO}", &tmp, &cookie_bv);
+ /* the berval is the cookie, but must be freed when it is all
+ done */
+ if (cookie_bv->bv_len)
+ *cookie=ber_bvdup(cookie_bv);
+ else
+ *cookie=NULL;
+ ber_bvfree(cookie_bv);
+ ber_free(cookie_be, 1);
+ break;
+ }
+ ldap_controls_free(rcontrols);
+done:
return rc;
}
diff --git a/source3/lib/util.c b/source3/lib/util.c
index d244e390d2..52cf15da1e 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -978,6 +978,56 @@ void *realloc_array(void *p,size_t el_size, unsigned int count)
}
/****************************************************************************
+ (Hopefully) efficient array append
+****************************************************************************/
+void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size,
+ void *element, void **array, uint32 *num_elements,
+ ssize_t *array_size)
+{
+ if (*array_size == -1)
+ return;
+
+ if (*array == NULL) {
+ if (*array_size == 0)
+ *array_size = 128;
+
+ if (mem_ctx != NULL)
+ *array = talloc_array(mem_ctx, element_size,
+ *array_size);
+ else
+ *array = malloc_array(element_size, *array_size);
+
+ if (*array == NULL)
+ goto error;
+ }
+
+ if (*num_elements == *array_size) {
+ *array_size *= 2;
+
+ if (mem_ctx != NULL)
+ *array = talloc_realloc_array(mem_ctx, *array,
+ element_size,
+ *array_size);
+ else
+ *array = realloc_array(*array, element_size,
+ *array_size);
+
+ if (*array == NULL)
+ goto error;
+ }
+
+ memcpy((char *)(*array) + element_size*(*num_elements),
+ element, element_size);
+ *num_elements += 1;
+
+ return;
+
+ error:
+ *num_elements = 0;
+ *array_size = -1;
+}
+
+/****************************************************************************
Free memory, checks for NULL.
Use directly SAFE_FREE()
Exists only because we need to pass a function pointer somewhere --SSS
diff --git a/source3/nsswitch/winbindd_passdb.c b/source3/nsswitch/winbindd_passdb.c
index bd15777bd3..23a56e4ea6 100644
--- a/source3/nsswitch/winbindd_passdb.c
+++ b/source3/nsswitch/winbindd_passdb.c
@@ -207,23 +207,33 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
uint32 *num_entries,
struct acct_info **info)
{
- struct acct_info *talloced_info;
+ struct pdb_search *search;
+ struct samr_displayentry *aliases;
+ int i;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
- /* Hmm. One billion aliases should be enough for a start */
+ search = pdb_search_aliases(&domain->sid);
+ if (search == NULL) goto done;
- if (!pdb_enum_aliases(&domain->sid, 0, 1000000000,
- num_entries, info)) {
- /* Nothing to report, just exit. */
- return NT_STATUS_OK;
- }
+ *num_entries = pdb_search_entries(search, 0, 0xffffffff, &aliases);
+ if (*num_entries == 0) goto done;
- talloced_info = (struct acct_info *)TALLOC_MEMDUP(mem_ctx, *info,
- *num_entries * sizeof(struct acct_info));
+ *info = TALLOC_ARRAY(mem_ctx, struct acct_info, *num_entries);
+ if (*info == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
- SAFE_FREE(*info);
- *info = talloced_info;
+ for (i=0; i<*num_entries; i++) {
+ fstrcpy((*info)[i].acct_name, aliases[i].account_name);
+ fstrcpy((*info)[i].acct_desc, aliases[i].description);
+ (*info)[i].rid = aliases[i].rid;
+ }
- return NT_STATUS_OK;
+ result = NT_STATUS_OK;
+ done:
+ pdb_search_destroy(search);
+ return result;
}
/* convert a single name to a sid in a domain */
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index 619a9ccb3d..06070b0700 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -246,6 +246,7 @@ typedef struct
int ldap_passwd_sync;
int ldap_replication_sleep;
int ldap_timeout; /* This is initialised in init_globals */
+ int ldap_page_size;
BOOL ldap_delete_dn;
BOOL bMsAddPrinterWizard;
BOOL bDNSproxy;
@@ -1121,6 +1122,7 @@ static struct parm_struct parm_table[] = {
{"ldap suffix", P_STRING, P_GLOBAL, &Globals.szLdapSuffix, NULL, NULL, FLAG_ADVANCED},
{"ldap ssl", P_ENUM, P_GLOBAL, &Globals.ldap_ssl, NULL, enum_ldap_ssl, FLAG_ADVANCED},
{"ldap timeout", P_INTEGER, P_GLOBAL, &Globals.ldap_timeout, NULL, NULL, FLAG_ADVANCED},
+ {"ldap page size", P_INTEGER, P_GLOBAL, &Globals.ldap_page_size, NULL, NULL, FLAG_ADVANCED},
{"ldap user suffix", P_STRING, P_GLOBAL, &Globals.szLdapUserSuffix, NULL, NULL, FLAG_ADVANCED},
{N_("Miscellaneous Options"), P_SEP, P_SEPARATOR},
@@ -1512,6 +1514,7 @@ static void init_globals(void)
Globals.ldap_delete_dn = False;
Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
Globals.ldap_timeout = LDAP_CONNECT_DEFAULT_TIMEOUT;
+ Globals.ldap_page_size = LDAP_PAGE_SIZE;
/* This is what we tell the afs client. in reality we set the token
* to never expire, though, when this runs out the afs client will
@@ -1770,6 +1773,7 @@ FN_GLOBAL_INTEGER(lp_ldap_passwd_sync, &Globals.ldap_passwd_sync)
FN_GLOBAL_BOOL(lp_ldap_delete_dn, &Globals.ldap_delete_dn)
FN_GLOBAL_INTEGER(lp_ldap_replication_sleep, &Globals.ldap_replication_sleep)
FN_GLOBAL_INTEGER(lp_ldap_timeout, &Globals.ldap_timeout)
+FN_GLOBAL_INTEGER(lp_ldap_page_size, &Globals.ldap_page_size)
FN_GLOBAL_STRING(lp_add_share_cmd, &Globals.szAddShareCommand)
FN_GLOBAL_STRING(lp_change_share_cmd, &Globals.szChangeShareCommand)
FN_GLOBAL_STRING(lp_delete_share_cmd, &Globals.szDeleteShareCommand)
diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c
index 301dc101eb..edcd1c9222 100644
--- a/source3/passdb/pdb_interface.c
+++ b/source3/passdb/pdb_interface.c
@@ -549,24 +549,6 @@ static NTSTATUS context_delete_alias(struct pdb_context *context,
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)
@@ -683,6 +665,68 @@ static NTSTATUS context_lookup_rids(struct pdb_context *context,
rids, names, attrs);
}
+static BOOL context_search_users(struct pdb_context *context,
+ struct pdb_search *search, uint16 acct_flags)
+{
+ if ((!context) || (!context->pdb_methods)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return False;
+ }
+
+ return context->pdb_methods->search_users(context->pdb_methods,
+ search, acct_flags);
+}
+
+static BOOL context_search_groups(struct pdb_context *context,
+ struct pdb_search *search)
+{
+ if ((!context) || (!context->pdb_methods)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return False;
+ }
+
+ return context->pdb_methods->search_groups(context->pdb_methods,
+ search);
+}
+
+static BOOL context_search_aliases(struct pdb_context *context,
+ struct pdb_search *search,
+ const DOM_SID *sid)
+{
+ if ((!context) || (!context->pdb_methods)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return False;
+ }
+
+ return context->pdb_methods->search_aliases(context->pdb_methods,
+ search, sid);
+}
+
+static BOOL context_search_next_entry(struct pdb_context *context,
+ struct pdb_search *search,
+ struct samr_displayentry *entry)
+{
+ if ((!context) || (!context->pdb_methods)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return False;
+ }
+
+ return context->pdb_methods->search_next_entry(context->pdb_methods,
+ search, entry);
+}
+
+static void context_search_end(struct pdb_context *context,
+ struct pdb_search *search)
+{
+ if ((!context) || (!context->pdb_methods)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return;
+ }
+
+ context->pdb_methods->search_end(context->pdb_methods, search);
+ return;
+}
+
/******************************************************************
Free and cleanup a pdb context, any associated data and anything
that the attached modules might have associated.
@@ -805,7 +849,6 @@ static NTSTATUS make_pdb_context(struct pdb_context **context)
(*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;
@@ -814,6 +857,12 @@ static NTSTATUS make_pdb_context(struct pdb_context **context)
(*context)->pdb_enum_alias_memberships = context_enum_alias_memberships;
(*context)->pdb_lookup_rids = context_lookup_rids;
+ (*context)->pdb_search_users = context_search_users;
+ (*context)->pdb_search_groups = context_search_groups;
+ (*context)->pdb_search_aliases = context_search_aliases;
+ (*context)->pdb_search_next_entry = context_search_next_entry;
+ (*context)->pdb_search_end = context_search_end;
+
(*context)->free_fn = free_pdb_context;
return NT_STATUS_OK;
@@ -1199,22 +1248,6 @@ BOOL pdb_delete_alias(const DOM_SID *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);
@@ -1543,56 +1576,6 @@ NTSTATUS pdb_default_lookup_rids(struct pdb_methods *methods,
return result;
}
-NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods)
-{
- *methods = TALLOC_P(mem_ctx, struct pdb_methods);
-
- if (!*methods) {
- return NT_STATUS_NO_MEMORY;
- }
-
- ZERO_STRUCTP(*methods);
-
- (*methods)->setsampwent = pdb_default_setsampwent;
- (*methods)->endsampwent = pdb_default_endsampwent;
- (*methods)->getsampwent = pdb_default_getsampwent;
- (*methods)->getsampwnam = pdb_default_getsampwnam;
- (*methods)->getsampwsid = pdb_default_getsampwsid;
- (*methods)->add_sam_account = pdb_default_add_sam_account;
- (*methods)->update_sam_account = pdb_default_update_sam_account;
- (*methods)->delete_sam_account = pdb_default_delete_sam_account;
- (*methods)->update_login_attempts = pdb_default_update_login_attempts;
-
- (*methods)->getgrsid = pdb_default_getgrsid;
- (*methods)->getgrgid = pdb_default_getgrgid;
- (*methods)->getgrnam = pdb_default_getgrnam;
- (*methods)->add_group_mapping_entry = pdb_default_add_group_mapping_entry;
- (*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)->enum_group_members = pdb_default_enum_group_members;
- (*methods)->enum_group_memberships = pdb_default_enum_group_memberships;
- (*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;
- (*methods)->lookup_rids = pdb_default_lookup_rids;
-
- return NT_STATUS_OK;
-}
-
-struct pdb_search *pdb_search_users(uint16 acct_flags);
-struct pdb_search *pdb_search_groups(void);
-struct pdb_search *pdb_search_aliases(const DOM_SID *sid);
-uint32 pdb_search_entries(struct pdb_search *search, uint32 start_idx, uint32 max_entries, struct samr_displayentry **result);
-void pdb_search_destroy(struct pdb_search *search);
-
static struct pdb_search *pdb_search_init(enum pdb_search_type type)
{
TALLOC_CTX *mem_ctx;
@@ -1613,6 +1596,7 @@ static struct pdb_search *pdb_search_init(enum pdb_search_type type)
result->mem_ctx = mem_ctx;
result->type = type;
result->cache = NULL;
+ result->num_entries = 0;
result->cache_size = 0;
result->search_ended = False;
@@ -1631,12 +1615,18 @@ static void fill_displayentry(TALLOC_CTX *mem_ctx, uint32 rid,
if (account_name != NULL)
entry->account_name = talloc_strdup(mem_ctx, account_name);
+ else
+ entry->account_name = "";
if (fullname != NULL)
entry->fullname = talloc_strdup(mem_ctx, fullname);
+ else
+ entry->fullname = "";
if (description != NULL)
entry->description = talloc_strdup(mem_ctx, description);
+ else
+ entry->description = "";
}
static BOOL user_search_in_progress = False;
@@ -1644,40 +1634,38 @@ struct user_search {
uint16 acct_flags;
};
-struct pdb_search *pdb_search_users(uint16 acct_flags)
+static BOOL pdb_default_search_users(struct pdb_methods *methods,
+ struct pdb_search *search,
+ uint16 acct_flags)
{
- struct pdb_search *result;
struct user_search *state;
if (user_search_in_progress) {
DEBUG(1, ("user search in progress\n"));
- return NULL;
+ return False;
}
- if (!pdb_setsampwent(False, acct_flags))
- return NULL;
+ if (!pdb_setsampwent(False, acct_flags)) {
+ DEBUG(5, ("Could not start search\n"));
+ return False;
+ }
user_search_in_progress = True;
- result = pdb_search_init(PDB_USER_SEARCH);
- if (result == NULL)
- return NULL;
-
- state = TALLOC_P(result->mem_ctx, struct user_search);
+ state = TALLOC_P(search->mem_ctx, struct user_search);
if (state == NULL) {
DEBUG(0, ("talloc failed\n"));
- talloc_destroy(result->mem_ctx);
- return NULL;
+ return False;
}
state->acct_flags = acct_flags;
- result->private = state;
- return result;
+ search->private = state;
+ return True;
}
-static BOOL pdb_search_entry_users(struct pdb_search *s, TALLOC_CTX *mem_ctx,
- struct samr_displayentry *entry)
+static BOOL pdb_search_next_entry_users(struct pdb_search *s,
+ struct samr_displayentry *entry)
{
struct user_search *state = s->private;
SAM_ACCOUNT *user = NULL;
@@ -1701,7 +1689,7 @@ static BOOL pdb_search_entry_users(struct pdb_search *s, TALLOC_CTX *mem_ctx,
goto next;
}
- fill_displayentry(mem_ctx, pdb_get_user_rid(user),
+ fill_displayentry(s->mem_ctx, pdb_get_user_rid(user),
pdb_get_acct_ctrl(user), pdb_get_username(user),
pdb_get_fullname(user), pdb_get_acct_desc(user),
entry);
@@ -1721,36 +1709,30 @@ struct group_search {
int num_groups, current_group;
};
-struct pdb_search *pdb_search_groups(void)
+static BOOL pdb_default_search_groups(struct pdb_methods *methods,
+ struct pdb_search *search)
{
- struct pdb_search *result;
struct group_search *state;
- result = pdb_search_init(PDB_GROUP_SEARCH);
- if (result == NULL)
- return NULL;
-
- state = TALLOC_P(result->mem_ctx, struct group_search);
+ state = TALLOC_P(search->mem_ctx, struct group_search);
if (state == NULL) {
DEBUG(0, ("talloc failed\n"));
- talloc_destroy(result->mem_ctx);
- return NULL;
+ return False;
}
if (!pdb_enum_group_mapping(SID_NAME_DOM_GRP, &state->groups,
&state->num_groups, True)) {
DEBUG(0, ("Could not enum groups\n"));
- talloc_destroy(result->mem_ctx);
- return NULL;
+ return False;
}
state->current_group = 0;
- result->private = state;
- return result;
+ search->private = state;
+ return True;
}
-static BOOL pdb_search_entry_group(struct pdb_search *s, TALLOC_CTX *mem_ctx,
- struct samr_displayentry *entry)
+static BOOL pdb_search_next_entry_group(struct pdb_search *s,
+ struct samr_displayentry *entry)
{
struct group_search *state = s->private;
uint32 rid;
@@ -1761,7 +1743,7 @@ static BOOL pdb_search_entry_group(struct pdb_search *s, TALLOC_CTX *mem_ctx,
sid_peek_rid(&map->sid, &rid);
- fill_displayentry(mem_ctx, rid, 0, map->nt_name, NULL, map->comment,
+ fill_displayentry(s->mem_ctx, rid, 0, map->nt_name, NULL, map->comment,
entry);
state->current_group += 1;
@@ -1779,51 +1761,43 @@ struct alias_search {
int num_aliases, current_alias;
};
-struct pdb_search *pdb_search_aliases(const DOM_SID *sid)
+static BOOL pdb_default_search_aliases(struct pdb_methods *methods,
+ struct pdb_search *search,
+ const DOM_SID *sid)
{
- struct pdb_search *result;
struct alias_search *state;
enum SID_NAME_USE type = SID_NAME_UNKNOWN;
- DOM_SID builtin_sid;
if (sid_equal(sid, get_global_sam_sid()))
type = SID_NAME_ALIAS;
- string_to_sid(&builtin_sid, "S-1-5-32");
-
- if (sid_equal(sid, &builtin_sid))
+ if (sid_equal(sid, &global_sid_Builtin))
type = SID_NAME_WKN_GRP;
if (type == SID_NAME_UNKNOWN) {
DEBUG(3, ("unknown domain sid: %s\n", sid_string_static(sid)));
- return NULL;
+ return False;
}
- result = pdb_search_init(PDB_ALIAS_SEARCH);
- if (result == NULL)
- return NULL;
-
- state = TALLOC_P(result->mem_ctx, struct alias_search);
+ state = TALLOC_P(search->mem_ctx, struct alias_search);
if (state == NULL) {
DEBUG(0, ("talloc failed\n"));
- talloc_destroy(result->mem_ctx);
- return NULL;
+ return False;
}
if (!pdb_enum_group_mapping(type, &state->aliases,
&state->num_aliases, False)) {
DEBUG(0, ("Could not enum aliases\n"));
- talloc_destroy(result->mem_ctx);
- return NULL;
+ return False;
}
state->current_alias = 0;
- result->private = state;
- return result;
+ search->private = state;
+ return True;
}
-static BOOL pdb_search_entry_alias(struct pdb_search *s, TALLOC_CTX *mem_ctx,
- struct samr_displayentry *entry)
+static BOOL pdb_search_next_entry_alias(struct pdb_search *s,
+ struct samr_displayentry *entry)
{
struct alias_search *state = s->private;
uint32 rid;
@@ -1834,7 +1808,7 @@ static BOOL pdb_search_entry_alias(struct pdb_search *s, TALLOC_CTX *mem_ctx,
sid_peek_rid(&map->sid, &rid);
- fill_displayentry(mem_ctx, rid, 0, map->nt_name, NULL, map->comment,
+ fill_displayentry(s->mem_ctx, rid, 0, map->nt_name, NULL, map->comment,
entry);
state->current_alias += 1;
@@ -1847,19 +1821,20 @@ static void pdb_search_end_aliases(struct pdb_search *search)
SAFE_FREE(state->aliases);
}
-static BOOL pdb_search_entry(struct pdb_search *search, TALLOC_CTX *mem_ctx,
- struct samr_displayentry *entry)
+static BOOL pdb_default_search_next_entry(struct pdb_methods *pdb_methods,
+ struct pdb_search *search,
+ struct samr_displayentry *entry)
{
BOOL result = False;
switch (search->type) {
case PDB_USER_SEARCH:
- result = pdb_search_entry_users(search, mem_ctx, entry);
+ result = pdb_search_next_entry_users(search, entry);
break;
case PDB_GROUP_SEARCH:
- result = pdb_search_entry_group(search, mem_ctx, entry);
+ result = pdb_search_next_entry_group(search, entry);
break;
case PDB_ALIAS_SEARCH:
- result = pdb_search_entry_alias(search, mem_ctx, entry);
+ result = pdb_search_next_entry_alias(search, entry);
break;
default:
DEBUG(0, ("unknown search type: %d\n", search->type));
@@ -1868,7 +1843,18 @@ static BOOL pdb_search_entry(struct pdb_search *search, TALLOC_CTX *mem_ctx,
return result;
}
-static void pdb_search_end(struct pdb_search *search)
+static BOOL pdb_search_next_entry(struct pdb_search *search,
+ struct samr_displayentry *entry)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (pdb_context == NULL) return False;
+
+ return pdb_context->pdb_search_next_entry(pdb_context, search, entry);
+}
+
+static void pdb_default_search_end(struct pdb_methods *pdb_methods,
+ struct pdb_search *search)
{
switch (search->type) {
case PDB_USER_SEARCH:
@@ -1886,29 +1872,90 @@ static void pdb_search_end(struct pdb_search *search)
}
}
+static void pdb_search_end(struct pdb_search *search)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (pdb_context == NULL) return;
+
+ pdb_context->pdb_search_end(pdb_context, search);
+}
+
static struct samr_displayentry *pdb_search_getentry(struct pdb_search *search,
uint32 idx)
{
- if (idx < search->cache_size)
+ if (idx < search->num_entries)
return &search->cache[idx];
if (search->search_ended)
return NULL;
- while (idx >= search->cache_size) {
+ while (idx >= search->num_entries) {
struct samr_displayentry entry;
- if (!pdb_search_entry(search, search->mem_ctx, &entry)) {
+ if (!pdb_search_next_entry(search, &entry)) {
pdb_search_end(search);
search->search_ended = True;
break;
}
- ADD_TO_ARRAY(search->mem_ctx, struct samr_displayentry,
- entry, &search->cache, &search->cache_size);
+ ADD_TO_LARGE_ARRAY(search->mem_ctx, struct samr_displayentry,
+ entry, &search->cache, &search->num_entries,
+ &search->cache_size);
+ }
+
+ return (search->num_entries > idx) ? &search->cache[idx] : NULL;
+}
+
+struct pdb_search *pdb_search_users(uint16 acct_flags)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_search *result;
+
+ if (pdb_context == NULL) return NULL;
+
+ result = pdb_search_init(PDB_USER_SEARCH);
+ if (result == NULL) return NULL;
+
+ if (!pdb_context->pdb_search_users(pdb_context, result, acct_flags)) {
+ talloc_destroy(result->mem_ctx);
+ return NULL;
+ }
+ return result;
+}
+
+struct pdb_search *pdb_search_groups(void)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_search *result;
+
+ if (pdb_context == NULL) return NULL;
+
+ result = pdb_search_init(PDB_GROUP_SEARCH);
+ if (result == NULL) return NULL;
+
+ if (!pdb_context->pdb_search_groups(pdb_context, result)) {
+ talloc_destroy(result->mem_ctx);
+ return NULL;
}
+ return result;
+}
+
+struct pdb_search *pdb_search_aliases(const DOM_SID *sid)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_search *result;
- return (search->cache_size > idx) ? &search->cache[idx] : NULL;
+ if (pdb_context == NULL) return NULL;
+
+ result = pdb_search_init(PDB_ALIAS_SEARCH);
+ if (result == NULL) return NULL;
+
+ if (!pdb_context->pdb_search_aliases(pdb_context, result, sid)) {
+ talloc_destroy(result->mem_ctx);
+ return NULL;
+ }
+ return result;
}
uint32 pdb_search_entries(struct pdb_search *search,
@@ -1928,10 +1975,10 @@ uint32 pdb_search_entries(struct pdb_search *search,
if (end_entry != NULL)
return max_entries;
- if (start_idx >= search->cache_size)
+ if (start_idx >= search->num_entries)
return 0;
- return search->cache_size - start_idx;
+ return search->num_entries - start_idx;
}
void pdb_search_destroy(struct pdb_search *search)
@@ -1944,3 +1991,51 @@ void pdb_search_destroy(struct pdb_search *search)
talloc_destroy(search->mem_ctx);
}
+
+NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods)
+{
+ *methods = TALLOC_P(mem_ctx, struct pdb_methods);
+
+ if (!*methods) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ZERO_STRUCTP(*methods);
+
+ (*methods)->setsampwent = pdb_default_setsampwent;
+ (*methods)->endsampwent = pdb_default_endsampwent;
+ (*methods)->getsampwent = pdb_default_getsampwent;
+ (*methods)->getsampwnam = pdb_default_getsampwnam;
+ (*methods)->getsampwsid = pdb_default_getsampwsid;
+ (*methods)->add_sam_account = pdb_default_add_sam_account;
+ (*methods)->update_sam_account = pdb_default_update_sam_account;
+ (*methods)->delete_sam_account = pdb_default_delete_sam_account;
+ (*methods)->update_login_attempts = pdb_default_update_login_attempts;
+
+ (*methods)->getgrsid = pdb_default_getgrsid;
+ (*methods)->getgrgid = pdb_default_getgrgid;
+ (*methods)->getgrnam = pdb_default_getgrnam;
+ (*methods)->add_group_mapping_entry = pdb_default_add_group_mapping_entry;
+ (*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)->enum_group_members = pdb_default_enum_group_members;
+ (*methods)->enum_group_memberships = pdb_default_enum_group_memberships;
+ (*methods)->find_alias = pdb_default_find_alias;
+ (*methods)->create_alias = pdb_default_create_alias;
+ (*methods)->delete_alias = pdb_default_delete_alias;
+ (*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;
+ (*methods)->lookup_rids = pdb_default_lookup_rids;
+ (*methods)->search_users = pdb_default_search_users;
+ (*methods)->search_groups = pdb_default_search_groups;
+ (*methods)->search_aliases = pdb_default_search_aliases;
+ (*methods)->search_next_entry = pdb_default_search_next_entry;
+ (*methods)->search_end = pdb_default_search_end;
+
+ return NT_STATUS_OK;
+}
diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c
index 3899949058..752eb878b1 100644
--- a/source3/passdb/pdb_ldap.c
+++ b/source3/passdb/pdb_ldap.c
@@ -3323,6 +3323,470 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
return result;
}
+char *get_ldap_filter(TALLOC_CTX *mem_ctx, const char *username)
+{
+ char *filter = NULL;
+ char *escaped = NULL;
+ char *result = NULL;
+
+ asprintf(&filter, "(&%s(objectclass=sambaSamAccount))",
+ lp_ldap_filter());
+ if (filter == NULL) goto done;
+
+ escaped = escape_ldap_string_alloc(username);
+ if (escaped == NULL) goto done;
+
+ filter = realloc_string_sub(filter, "%u", username);
+ result = talloc_strdup(mem_ctx, filter);
+
+ done:
+ SAFE_FREE(filter);
+ SAFE_FREE(escaped);
+
+ return result;
+}
+
+const char **talloc_attrs(TALLOC_CTX *mem_ctx, ...)
+{
+ int i, num = 0;
+ va_list ap;
+ const char **result;
+
+ va_start(ap, mem_ctx);
+ while (va_arg(ap, const char *) != NULL)
+ num += 1;
+ va_end(ap);
+
+ result = TALLOC_ARRAY(mem_ctx, const char *, num+1);
+
+ va_start(ap, mem_ctx);
+ for (i=0; i<num; i++)
+ result[i] = talloc_strdup(mem_ctx, va_arg(ap, const char*));
+ va_end(ap);
+
+ result[num] = NULL;
+ return result;
+}
+
+struct ldap_search_state {
+ struct smbldap_state *connection;
+
+ uint16 acct_flags;
+
+ const char *base;
+ int scope;
+ const char *filter;
+ const char **attrs;
+ int attrsonly;
+ void *pagedresults_cookie;
+
+ LDAPMessage *entries, *current_entry;
+ BOOL (*ldap2displayentry)(struct ldap_search_state *state,
+ TALLOC_CTX *mem_ctx,
+ LDAP *ld, LDAPMessage *entry,
+ struct samr_displayentry *result);
+};
+
+static BOOL ldapsam_search_firstpage(struct pdb_search *search)
+{
+ struct ldap_search_state *state = search->private;
+ LDAP *ld = state->connection->ldap_struct;
+ int rc = LDAP_OPERATIONS_ERROR;
+
+ state->entries = NULL;
+
+ if (state->connection->paged_results) {
+ rc = smbldap_search_paged(state->connection, state->base,
+ state->scope, state->filter,
+ state->attrs, state->attrsonly,
+ lp_ldap_page_size(), &state->entries,
+ &state->pagedresults_cookie);
+ }
+
+ if ((rc != LDAP_SUCCESS) || (state->entries == NULL)) {
+
+ if (state->entries != NULL) {
+ /* Left over from unsuccessful paged attempt */
+ ldap_msgfree(state->entries);
+ state->entries = NULL;
+ }
+
+ rc = smbldap_search(state->connection, state->base,
+ state->scope, state->filter, state->attrs,
+ state->attrsonly, &state->entries);
+
+ if ((rc != LDAP_SUCCESS) || (state->entries == NULL))
+ return False;
+
+ /* Ok, the server was lying. It told us it could do paged
+ * searches when it could not. */
+ state->connection->paged_results = False;
+ }
+
+ state->current_entry = ldap_first_entry(ld, state->entries);
+
+ if (state->current_entry == NULL) {
+ ldap_msgfree(state->entries);
+ state->entries = NULL;
+ }
+
+ return True;
+}
+
+static BOOL ldapsam_search_nextpage(struct pdb_search *search)
+{
+ struct ldap_search_state *state = search->private;
+ LDAP *ld = state->connection->ldap_struct;
+ int rc;
+
+ if (!state->connection->paged_results) {
+ /* There is no next page when there are no paged results */
+ return False;
+ }
+
+ rc = smbldap_search_paged(state->connection, state->base,
+ state->scope, state->filter, state->attrs,
+ state->attrsonly, lp_ldap_page_size(),
+ &state->entries,
+ &state->pagedresults_cookie);
+
+ if ((rc != LDAP_SUCCESS) || (state->entries == NULL))
+ return False;
+
+ state->current_entry = ldap_first_entry(ld, state->entries);
+
+ if (state->current_entry == NULL) {
+ ldap_msgfree(state->entries);
+ state->entries = NULL;
+ }
+
+ return True;
+}
+
+static BOOL ldapsam_search_next_entry(struct pdb_methods *methods,
+ struct pdb_search *search,
+ struct samr_displayentry *entry)
+{
+ struct ldap_search_state *state = search->private;
+ LDAP *ld = state->connection->ldap_struct;
+ BOOL result;
+
+ retry:
+ if ((state->entries == NULL) && (state->pagedresults_cookie == NULL))
+ return False;
+
+ if ((state->entries == NULL) &&
+ !ldapsam_search_nextpage(search))
+ return False;
+
+ result = state->ldap2displayentry(state, search->mem_ctx, ld,
+ state->current_entry, entry);
+
+ if (!result) {
+ char *dn;
+ dn = ldap_get_dn(ld, state->current_entry);
+ DEBUG(5, ("Skipping entry %s\n", dn != NULL ? dn : "<NULL>"));
+ if (dn != NULL) ldap_memfree(dn);
+ }
+
+ state->current_entry = ldap_next_entry(ld, state->current_entry);
+
+ if (state->current_entry == NULL) {
+ ldap_msgfree(state->entries);
+ state->entries = NULL;
+ }
+
+ if (!result) goto retry;
+
+ return True;
+}
+
+static void ldapsam_search_end(struct pdb_methods *methods,
+ struct pdb_search *search)
+{
+ struct ldap_search_state *state = search->private;
+ int rc;
+
+ if (state->pagedresults_cookie == NULL)
+ return;
+
+ if (state->entries != NULL)
+ ldap_msgfree(state->entries);
+
+ state->entries = NULL;
+ state->current_entry = NULL;
+
+ if (!state->connection->paged_results)
+ return;
+
+ /* Tell the LDAP server we're not interested in the rest anymore. */
+
+ rc = smbldap_search_paged(state->connection, state->base, state->scope,
+ state->filter, state->attrs,
+ state->attrsonly, 0, &state->entries,
+ &state->pagedresults_cookie);
+
+ if (rc != LDAP_SUCCESS)
+ DEBUG(5, ("Could not end search properly\n"));
+
+ return;
+}
+
+static BOOL ldapuser2displayentry(struct ldap_search_state *state,
+ TALLOC_CTX *mem_ctx,
+ LDAP *ld, LDAPMessage *entry,
+ struct samr_displayentry *result)
+{
+ char **vals;
+ DOM_SID sid;
+ uint16 acct_flags;
+
+ vals = ldap_get_values(ld, entry, "sambaAcctFlags");
+ if ((vals == NULL) || (vals[0] == NULL)) {
+ DEBUG(5, ("\"sambaAcctFlags\" not found\n"));
+ return False;
+ }
+ acct_flags = pdb_decode_acct_ctrl(vals[0]);
+ ldap_value_free(vals);
+
+ if ((state->acct_flags != 0) &&
+ ((state->acct_flags & acct_flags) == 0))
+ return False;
+
+ result->acct_flags = acct_flags;
+ result->account_name = "";
+ result->fullname = "";
+ result->description = "";
+
+ vals = ldap_get_values(ld, entry, "uid");
+ if ((vals == NULL) || (vals[0] == NULL)) {
+ DEBUG(5, ("\"uid\" not found\n"));
+ return False;
+ }
+ pull_utf8_talloc(mem_ctx,
+ CONST_DISCARD(char **, &result->account_name),
+ vals[0]);
+ ldap_value_free(vals);
+
+ vals = ldap_get_values(ld, entry, "displayName");
+ if ((vals == NULL) || (vals[0] == NULL))
+ DEBUG(8, ("\"displayName\" not found\n"));
+ else
+ pull_utf8_talloc(mem_ctx,
+ CONST_DISCARD(char **, &result->fullname),
+ vals[0]);
+ ldap_value_free(vals);
+
+ vals = ldap_get_values(ld, entry, "description");
+ if ((vals == NULL) || (vals[0] == NULL))
+ DEBUG(8, ("\"description\" not found\n"));
+ else
+ pull_utf8_talloc(mem_ctx,
+ CONST_DISCARD(char **, &result->description),
+ vals[0]);
+ ldap_value_free(vals);
+
+ if ((result->account_name == NULL) ||
+ (result->fullname == NULL) ||
+ (result->description == NULL)) {
+ DEBUG(0, ("talloc failed\n"));
+ return False;
+ }
+
+ vals = ldap_get_values(ld, entry, "sambaSid");
+ if ((vals == NULL) || (vals[0] == NULL)) {
+ DEBUG(0, ("\"objectSid\" not found\n"));
+ return False;
+ }
+
+ if (!string_to_sid(&sid, vals[0])) {
+ DEBUG(0, ("Could not convert %s to SID\n", vals[0]));
+ ldap_value_free(vals);
+ return False;
+ }
+ ldap_value_free(vals);
+
+ if (!sid_peek_check_rid(get_global_sam_sid(), &sid, &result->rid)) {
+ DEBUG(0, ("%s is not our domain\n", vals[0]));
+ return False;
+ }
+
+ return True;
+}
+
+
+static BOOL ldapsam_search_users(struct pdb_methods *methods,
+ struct pdb_search *search,
+ uint16 acct_flags)
+{
+ struct ldapsam_privates *ldap_state = methods->private_data;
+ struct ldap_search_state *state;
+
+ state = TALLOC_P(search->mem_ctx, struct ldap_search_state);
+ if (state == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ return False;
+ }
+
+ state->connection = ldap_state->smbldap_state;
+
+ if ((acct_flags != 0) && ((acct_flags & ACB_NORMAL) != 0))
+ state->base = lp_ldap_user_suffix();
+ else if ((acct_flags != 0) &&
+ ((acct_flags & (ACB_WSTRUST|ACB_SVRTRUST)) != 0))
+ state->base = lp_ldap_machine_suffix();
+ else
+ state->base = lp_ldap_suffix();
+
+ state->acct_flags = acct_flags;
+ state->base = talloc_strdup(search->mem_ctx, state->base);
+ state->scope = LDAP_SCOPE_SUBTREE;
+ state->filter = get_ldap_filter(search->mem_ctx, "*");
+ state->attrs = talloc_attrs(search->mem_ctx, "uid", "sambaSid",
+ "displayName", "description",
+ "sambaAcctFlags", NULL);
+ state->attrsonly = 0;
+ state->pagedresults_cookie = NULL;
+ state->entries = NULL;
+ state->ldap2displayentry = ldapuser2displayentry;
+
+ if ((state->filter == NULL) || (state->attrs == NULL)) {
+ DEBUG(0, ("talloc failed\n"));
+ return False;
+ }
+
+ search->private = state;
+
+ return ldapsam_search_firstpage(search);
+}
+
+static BOOL ldapgroup2displayentry(struct ldap_search_state *state,
+ TALLOC_CTX *mem_ctx,
+ LDAP *ld, LDAPMessage *entry,
+ struct samr_displayentry *result)
+{
+ char **vals;
+ DOM_SID sid;
+
+ result->account_name = "";
+ result->fullname = "";
+ result->description = "";
+
+ vals = ldap_get_values(ld, entry, "cn");
+ if ((vals == NULL) || (vals[0] == NULL)) {
+ DEBUG(5, ("\"cn\" not found\n"));
+ return False;
+ }
+ pull_utf8_talloc(mem_ctx,
+ CONST_DISCARD(char **, &result->account_name),
+ vals[0]);
+ ldap_value_free(vals);
+
+ vals = ldap_get_values(ld, entry, "displayName");
+ if ((vals == NULL) || (vals[0] == NULL))
+ DEBUG(8, ("\"displayName\" not found\n"));
+ else
+ pull_utf8_talloc(mem_ctx,
+ CONST_DISCARD(char **, &result->fullname),
+ vals[0]);
+ ldap_value_free(vals);
+
+ vals = ldap_get_values(ld, entry, "description");
+ if ((vals == NULL) || (vals[0] == NULL))
+ DEBUG(8, ("\"description\" not found\n"));
+ else
+ pull_utf8_talloc(mem_ctx,
+ CONST_DISCARD(char **, &result->description),
+ vals[0]);
+ ldap_value_free(vals);
+
+ if ((result->account_name == NULL) ||
+ (result->fullname == NULL) ||
+ (result->description == NULL)) {
+ DEBUG(0, ("talloc failed\n"));
+ return False;
+ }
+
+ vals = ldap_get_values(ld, entry, "sambaSid");
+ if ((vals == NULL) || (vals[0] == NULL)) {
+ DEBUG(0, ("\"objectSid\" not found\n"));
+ return False;
+ }
+
+ if (!string_to_sid(&sid, vals[0])) {
+ DEBUG(0, ("Could not convert %s to SID\n", vals[0]));
+ return False;
+ }
+
+ if (!sid_peek_check_rid(get_global_sam_sid(), &sid, &result->rid)) {
+ DEBUG(0, ("%s is not our domain\n", vals[0]));
+ return False;
+ }
+ ldap_value_free(vals);
+
+ return True;
+}
+
+static BOOL ldapsam_search_grouptype(struct pdb_methods *methods,
+ struct pdb_search *search,
+ enum SID_NAME_USE type)
+{
+ struct ldapsam_privates *ldap_state = methods->private_data;
+ struct ldap_search_state *state;
+
+ state = TALLOC_P(search->mem_ctx, struct ldap_search_state);
+ if (state == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ return False;
+ }
+
+ state->connection = ldap_state->smbldap_state;
+
+ state->base = talloc_strdup(search->mem_ctx, lp_ldap_group_suffix());
+ state->connection = ldap_state->smbldap_state;
+ state->scope = LDAP_SCOPE_SUBTREE;
+ state->filter = talloc_asprintf(search->mem_ctx,
+ "(&(objectclass=sambaGroupMapping)"
+ "(sambaGroupType=%d))", type);
+ state->attrs = talloc_attrs(search->mem_ctx, "cn", "sambaSid",
+ "displayName", "description", NULL);
+ state->attrsonly = 0;
+ state->pagedresults_cookie = NULL;
+ state->entries = NULL;
+ state->ldap2displayentry = ldapgroup2displayentry;
+
+ if ((state->filter == NULL) || (state->attrs == NULL)) {
+ DEBUG(0, ("talloc failed\n"));
+ return False;
+ }
+
+ search->private = state;
+
+ return ldapsam_search_firstpage(search);
+}
+
+static BOOL ldapsam_search_groups(struct pdb_methods *methods,
+ struct pdb_search *search)
+{
+ return ldapsam_search_grouptype(methods, search, SID_NAME_DOM_GRP);
+}
+
+static BOOL ldapsam_search_aliases(struct pdb_methods *methods,
+ struct pdb_search *search,
+ const DOM_SID *sid)
+{
+ if (sid_check_is_domain(sid))
+ return ldapsam_search_grouptype(methods, search,
+ SID_NAME_ALIAS);
+
+ if (sid_check_is_builtin(sid))
+ return ldapsam_search_grouptype(methods, search,
+ SID_NAME_WKN_GRP);
+
+ DEBUG(5, ("Don't know SID %s\n", sid_string_static(sid)));
+ return False;
+}
+
/**********************************************************************
Housekeeping
*********************************************************************/
@@ -3381,6 +3845,11 @@ static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **
(*pdb_method)->enum_group_members = ldapsam_enum_group_members;
(*pdb_method)->enum_group_memberships = ldapsam_enum_group_memberships;
(*pdb_method)->lookup_rids = ldapsam_lookup_rids;
+ (*pdb_method)->search_users = ldapsam_search_users;
+ (*pdb_method)->search_groups = ldapsam_search_groups;
+ (*pdb_method)->search_aliases = ldapsam_search_aliases;
+ (*pdb_method)->search_next_entry = ldapsam_search_next_entry;
+ (*pdb_method)->search_end = ldapsam_search_end;
/* TODO: Setup private data and free */
diff --git a/source3/rpc_parse/parse_samr.c b/source3/rpc_parse/parse_samr.c
index 14d4bb9fdf..d3f709c352 100644
--- a/source3/rpc_parse/parse_samr.c
+++ b/source3/rpc_parse/parse_samr.c
@@ -1516,75 +1516,42 @@ BOOL samr_io_q_query_dispinfo(const char *desc, SAMR_Q_QUERY_DISPINFO * q_e,
inits a SAM_DISPINFO_1 structure.
********************************************************************/
-NTSTATUS init_sam_dispinfo_1(TALLOC_CTX *ctx, SAM_DISPINFO_1 *sam, uint32 num_entries,
- uint32 start_idx, SAM_ACCOUNT *disp_user_info,
- DOM_SID *domain_sid)
+NTSTATUS init_sam_dispinfo_1(TALLOC_CTX *ctx, SAM_DISPINFO_1 **sam,
+ uint32 num_entries, uint32 start_idx,
+ struct samr_displayentry *entries)
{
uint32 i;
- SAM_ACCOUNT *pwd = NULL;
- ZERO_STRUCTP(sam);
-
DEBUG(10, ("init_sam_dispinfo_1: num_entries: %d\n", num_entries));
if (num_entries==0)
return NT_STATUS_OK;
- sam->sam=TALLOC_ARRAY(ctx, SAM_ENTRY1, num_entries);
- if (!sam->sam)
+ *sam = TALLOC_ZERO_ARRAY(ctx, SAM_DISPINFO_1, num_entries);
+ if (*sam == NULL)
return NT_STATUS_NO_MEMORY;
- sam->str=TALLOC_ARRAY(ctx, SAM_STR1, num_entries);
- if (!sam->str)
+ (*sam)->sam=TALLOC_ARRAY(ctx, SAM_ENTRY1, num_entries);
+ if ((*sam)->sam == NULL)
return NT_STATUS_NO_MEMORY;
- ZERO_STRUCTP(sam->sam);
- ZERO_STRUCTP(sam->str);
+ (*sam)->str=TALLOC_ARRAY(ctx, SAM_STR1, num_entries);
+ if ((*sam)->str == NULL)
+ return NT_STATUS_NO_MEMORY;
for (i = 0; i < num_entries ; i++) {
- const char *username;
- const char *fullname;
- const char *acct_desc;
- uint32 user_rid;
- const DOM_SID *user_sid;
- fstring user_sid_string, domain_sid_string;
-
- DEBUG(11, ("init_sam_dispinfo_1: entry: %d\n",i));
-
- pwd=&disp_user_info[i+start_idx];
-
- username = pdb_get_username(pwd);
- fullname = pdb_get_fullname(pwd);
- acct_desc = pdb_get_acct_desc(pwd);
-
- if (!username)
- username = "";
-
- if (!fullname)
- fullname = "";
-
- if (!acct_desc)
- acct_desc = "";
-
- user_sid = pdb_get_user_sid(pwd);
-
- if (!sid_peek_check_rid(domain_sid, user_sid, &user_rid)) {
- DEBUG(0, ("init_sam_dispinfo_1: User %s has SID %s, which conflicts with "
- "the domain sid %s. Failing operation.\n",
- username,
- sid_to_string(user_sid_string, user_sid),
- sid_to_string(domain_sid_string, domain_sid)));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- init_unistr2(&sam->str[i].uni_acct_name, pdb_get_username(pwd), UNI_FLAGS_NONE);
- init_unistr2(&sam->str[i].uni_full_name, pdb_get_fullname(pwd), UNI_FLAGS_NONE);
- init_unistr2(&sam->str[i].uni_acct_desc, pdb_get_acct_desc(pwd), UNI_FLAGS_NONE);
-
- init_sam_entry1(&sam->sam[i], start_idx + i + 1,
- &sam->str[i].uni_acct_name, &sam->str[i].uni_full_name, &sam->str[i].uni_acct_desc,
- user_rid, pdb_get_acct_ctrl(pwd));
-
+ init_unistr2(&(*sam)->str[i].uni_acct_name,
+ entries[i].account_name, UNI_FLAGS_NONE);
+ init_unistr2(&(*sam)->str[i].uni_full_name,
+ entries[i].fullname, UNI_FLAGS_NONE);
+ init_unistr2(&(*sam)->str[i].uni_acct_desc,
+ entries[i].description, UNI_FLAGS_NONE);
+
+ init_sam_entry1(&(*sam)->sam[i], start_idx+i+1,
+ &(*sam)->str[i].uni_acct_name,
+ &(*sam)->str[i].uni_full_name,
+ &(*sam)->str[i].uni_acct_desc,
+ entries[i].rid, entries[i].acct_flags);
}
return NT_STATUS_OK;
@@ -1639,58 +1606,39 @@ static BOOL sam_io_sam_dispinfo_1(const char *desc, SAM_DISPINFO_1 * sam,
inits a SAM_DISPINFO_2 structure.
********************************************************************/
-NTSTATUS init_sam_dispinfo_2(TALLOC_CTX *ctx, SAM_DISPINFO_2 *sam, uint32 num_entries,
- uint32 start_idx, SAM_ACCOUNT *disp_user_info,
- DOM_SID *domain_sid )
+NTSTATUS init_sam_dispinfo_2(TALLOC_CTX *ctx, SAM_DISPINFO_2 **sam,
+ uint32 num_entries, uint32 start_idx,
+ struct samr_displayentry *entries)
{
uint32 i;
- SAM_ACCOUNT *pwd = NULL;
- ZERO_STRUCTP(sam);
-
DEBUG(10, ("init_sam_dispinfo_2: num_entries: %d\n", num_entries));
if (num_entries==0)
return NT_STATUS_OK;
- if (!(sam->sam=TALLOC_ARRAY(ctx, SAM_ENTRY2, num_entries)))
+ *sam = TALLOC_ZERO_ARRAY(ctx, SAM_DISPINFO_2, num_entries);
+ if (*sam == NULL)
return NT_STATUS_NO_MEMORY;
- if (!(sam->str=TALLOC_ARRAY(ctx, SAM_STR2, num_entries)))
+ (*sam)->sam = TALLOC_ARRAY(ctx, SAM_ENTRY2, num_entries);
+ if ((*sam)->sam == NULL)
return NT_STATUS_NO_MEMORY;
- ZERO_STRUCTP(sam->sam);
- ZERO_STRUCTP(sam->str);
+ (*sam)->str=TALLOC_ARRAY(ctx, SAM_STR2, num_entries);
+ if ((*sam)->str == NULL)
+ return NT_STATUS_NO_MEMORY;
for (i = 0; i < num_entries; i++) {
- uint32 user_rid;
- const DOM_SID *user_sid;
- const char *username;
- const char *acct_desc;
- fstring user_sid_string, domain_sid_string;
-
- DEBUG(11, ("init_sam_dispinfo_2: entry: %d\n",i));
- pwd=&disp_user_info[i+start_idx];
-
- username = pdb_get_username(pwd);
- acct_desc = pdb_get_acct_desc(pwd);
- user_sid = pdb_get_user_sid(pwd);
-
- if (!sid_peek_check_rid(domain_sid, user_sid, &user_rid)) {
- DEBUG(0, ("init_sam_dispinfo_2: User %s has SID %s, which conflicts with "
- "the domain sid %s. Failing operation.\n",
- username,
- sid_to_string(user_sid_string, user_sid),
- sid_to_string(domain_sid_string, domain_sid)));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- init_unistr2(&sam->str[i].uni_srv_name, username, UNI_FLAGS_NONE);
- init_unistr2(&sam->str[i].uni_srv_desc, acct_desc, UNI_FLAGS_NONE);
-
- init_sam_entry2(&sam->sam[i], start_idx + i + 1,
- &sam->str[i].uni_srv_name, &sam->str[i].uni_srv_desc,
- user_rid, pdb_get_acct_ctrl(pwd));
+ init_unistr2(&(*sam)->str[i].uni_srv_name,
+ entries[i].account_name, UNI_FLAGS_NONE);
+ init_unistr2(&(*sam)->str[i].uni_srv_desc,
+ entries[i].description, UNI_FLAGS_NONE);
+
+ init_sam_entry2(&(*sam)->sam[i], start_idx + i + 1,
+ &(*sam)->str[i].uni_srv_name,
+ &(*sam)->str[i].uni_srv_desc,
+ entries[i].rid, entries[i].acct_flags);
}
return NT_STATUS_OK;
@@ -1747,37 +1695,39 @@ static BOOL sam_io_sam_dispinfo_2(const char *desc, SAM_DISPINFO_2 * sam,
inits a SAM_DISPINFO_3 structure.
********************************************************************/
-NTSTATUS init_sam_dispinfo_3(TALLOC_CTX *ctx, SAM_DISPINFO_3 *sam, uint32 num_entries,
- uint32 start_idx, DOMAIN_GRP *disp_group_info)
+NTSTATUS init_sam_dispinfo_3(TALLOC_CTX *ctx, SAM_DISPINFO_3 **sam,
+ uint32 num_entries, uint32 start_idx,
+ struct samr_displayentry *entries)
{
uint32 i;
- ZERO_STRUCTP(sam);
-
DEBUG(5, ("init_sam_dispinfo_3: num_entries: %d\n", num_entries));
if (num_entries==0)
return NT_STATUS_OK;
- if (!(sam->sam=TALLOC_ARRAY(ctx, SAM_ENTRY3, num_entries)))
+ *sam = TALLOC_ZERO_ARRAY(ctx, SAM_DISPINFO_3, num_entries);
+ if (*sam == NULL)
return NT_STATUS_NO_MEMORY;
- if (!(sam->str=TALLOC_ARRAY(ctx, SAM_STR3, num_entries)))
+ if (!((*sam)->sam=TALLOC_ARRAY(ctx, SAM_ENTRY3, num_entries)))
return NT_STATUS_NO_MEMORY;
- ZERO_STRUCTP(sam->sam);
- ZERO_STRUCTP(sam->str);
+ if (!((*sam)->str=TALLOC_ARRAY(ctx, SAM_STR3, num_entries)))
+ return NT_STATUS_NO_MEMORY;
for (i = 0; i < num_entries; i++) {
- DOMAIN_GRP *grp = &disp_group_info[i+start_idx];
-
DEBUG(11, ("init_sam_dispinfo_3: entry: %d\n",i));
- init_unistr2(&sam->str[i].uni_grp_name, grp->name, UNI_FLAGS_NONE);
- init_unistr2(&sam->str[i].uni_grp_desc, grp->comment, UNI_FLAGS_NONE);
+ init_unistr2(&(*sam)->str[i].uni_grp_name,
+ entries[i].account_name, UNI_FLAGS_NONE);
+ init_unistr2(&(*sam)->str[i].uni_grp_desc,
+ entries[i].description, UNI_FLAGS_NONE);
- init_sam_entry3(&sam->sam[i], start_idx + i + 1, &sam->str[i].uni_grp_name,
- &sam->str[i].uni_grp_desc, grp->rid);
+ init_sam_entry3(&(*sam)->sam[i], start_idx+i+1,
+ &(*sam)->str[i].uni_grp_name,
+ &(*sam)->str[i].uni_grp_desc,
+ entries[i].rid);
}
return NT_STATUS_OK;
@@ -1834,38 +1784,40 @@ static BOOL sam_io_sam_dispinfo_3(const char *desc, SAM_DISPINFO_3 * sam,
inits a SAM_DISPINFO_4 structure.
********************************************************************/
-NTSTATUS init_sam_dispinfo_4(TALLOC_CTX *ctx, SAM_DISPINFO_4 *sam, uint32 num_entries,
- uint32 start_idx, SAM_ACCOUNT *disp_user_info)
+NTSTATUS init_sam_dispinfo_4(TALLOC_CTX *ctx, SAM_DISPINFO_4 **sam,
+ uint32 num_entries, uint32 start_idx,
+ struct samr_displayentry *entries)
{
- uint32 len_sam_name;
uint32 i;
- SAM_ACCOUNT *pwd = NULL;
- ZERO_STRUCTP(sam);
-
DEBUG(5, ("init_sam_dispinfo_4: num_entries: %d\n", num_entries));
if (num_entries==0)
return NT_STATUS_OK;
- if (!(sam->sam=TALLOC_ARRAY(ctx, SAM_ENTRY4, num_entries)))
+ *sam = TALLOC_ZERO_ARRAY(ctx, SAM_DISPINFO_4, num_entries);
+ if (*sam == NULL)
return NT_STATUS_NO_MEMORY;
- if (!(sam->str=TALLOC_ARRAY(ctx, SAM_STR4, num_entries)))
+ (*sam)->sam = TALLOC_ARRAY(ctx, SAM_ENTRY4, num_entries);
+ if ((*sam)->sam == NULL)
return NT_STATUS_NO_MEMORY;
- ZERO_STRUCTP(sam->sam);
- ZERO_STRUCTP(sam->str);
+ (*sam)->str=TALLOC_ARRAY(ctx, SAM_STR4, num_entries);
+ if ((*sam)->str == NULL)
+ return NT_STATUS_NO_MEMORY;
for (i = 0; i < num_entries; i++) {
- DEBUG(11, ("init_sam_dispinfo_2: entry: %d\n",i));
- pwd=&disp_user_info[i+start_idx];
+ size_t len_sam_name = strlen(entries[i].account_name);
- len_sam_name = strlen(pdb_get_username(pwd));
+ DEBUG(11, ("init_sam_dispinfo_2: entry: %d\n",i));
- init_sam_entry4(&sam->sam[i], start_idx + i + 1, len_sam_name);
+ init_sam_entry4(&(*sam)->sam[i], start_idx + i + 1,
+ len_sam_name);
- init_string2(&sam->str[i].acct_name, pdb_get_username(pwd), len_sam_name+1, len_sam_name);
+ init_string2(&(*sam)->str[i].acct_name,
+ entries[i].account_name, len_sam_name+1,
+ len_sam_name);
}
return NT_STATUS_OK;
@@ -1921,37 +1873,36 @@ static BOOL sam_io_sam_dispinfo_4(const char *desc, SAM_DISPINFO_4 * sam,
inits a SAM_DISPINFO_5 structure.
********************************************************************/
-NTSTATUS init_sam_dispinfo_5(TALLOC_CTX *ctx, SAM_DISPINFO_5 *sam, uint32 num_entries,
- uint32 start_idx, DOMAIN_GRP *disp_group_info)
+NTSTATUS init_sam_dispinfo_5(TALLOC_CTX *ctx, SAM_DISPINFO_5 **sam,
+ uint32 num_entries, uint32 start_idx,
+ struct samr_displayentry *entries)
{
uint32 len_sam_name;
uint32 i;
- ZERO_STRUCTP(sam);
-
DEBUG(5, ("init_sam_dispinfo_5: num_entries: %d\n", num_entries));
if (num_entries==0)
return NT_STATUS_OK;
- if (!(sam->sam=TALLOC_ARRAY(ctx, SAM_ENTRY5, num_entries)))
+ *sam = TALLOC_ZERO_ARRAY(ctx, SAM_DISPINFO_5, num_entries);
+ if (*sam == NULL)
return NT_STATUS_NO_MEMORY;
- if (!(sam->str=TALLOC_ARRAY(ctx, SAM_STR5, num_entries)))
+ if (!((*sam)->sam=TALLOC_ARRAY(ctx, SAM_ENTRY5, num_entries)))
return NT_STATUS_NO_MEMORY;
- ZERO_STRUCTP(sam->sam);
- ZERO_STRUCTP(sam->str);
+ if (!((*sam)->str=TALLOC_ARRAY(ctx, SAM_STR5, num_entries)))
+ return NT_STATUS_NO_MEMORY;
for (i = 0; i < num_entries; i++) {
- DOMAIN_GRP *grp = &disp_group_info[i+start_idx];
-
DEBUG(11, ("init_sam_dispinfo_5: entry: %d\n",i));
- len_sam_name = strlen(grp->name);
+ len_sam_name = strlen(entries[i].account_name);
- init_sam_entry5(&sam->sam[i], start_idx + i + 1, len_sam_name);
- init_string2(&sam->str[i].grp_name, grp->name, len_sam_name+1, len_sam_name);
+ init_sam_entry5(&(*sam)->sam[i], start_idx+i+1, len_sam_name);
+ init_string2(&(*sam)->str[i].grp_name, entries[i].account_name,
+ len_sam_name+1, len_sam_name);
}
return NT_STATUS_OK;
diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c
index 84c78eab64..fe54476cc9 100644
--- a/source3/rpc_server/srv_samr_nt.c
+++ b/source3/rpc_server/srv_samr_nt.c
@@ -43,14 +43,12 @@ extern rid_name domain_group_rids[];
extern rid_name domain_alias_rids[];
extern rid_name builtin_alias_rids[];
-
-typedef struct _disp_info {
- BOOL user_dbloaded;
- uint32 num_user_account;
- SAM_ACCOUNT *disp_user_info;
- BOOL group_dbloaded;
- uint32 num_group_account;
- DOMAIN_GRP *disp_group_info;
+typedef struct disp_info {
+ struct pdb_search *users;
+ struct pdb_search *machines;
+ struct pdb_search *groups;
+ struct pdb_search *aliases;
+ struct pdb_search *builtins;
} DISP_INFO;
struct samr_info {
@@ -238,10 +236,9 @@ static struct samr_info *get_samr_info_by_sid(DOM_SID *psid)
mem_ctx = talloc_init("samr_info for domain sid %s", sid_str);
- if ((info = TALLOC_P(mem_ctx, struct samr_info)) == NULL)
+ if ((info = TALLOC_ZERO_P(mem_ctx, struct samr_info)) == NULL)
return NULL;
- ZERO_STRUCTP(info);
DEBUG(10,("get_samr_info_by_sid: created new info for sid %s\n", sid_str));
if (psid) {
sid_copy( &info->sid, psid);
@@ -256,33 +253,22 @@ static struct samr_info *get_samr_info_by_sid(DOM_SID *psid)
Function to free the per handle data.
********************************************************************/
-static void free_samr_users(struct samr_info *info)
-{
- int i;
-
- if (info->disp_info.user_dbloaded){
- for (i=0; i<info->disp_info.num_user_account; i++) {
- SAM_ACCOUNT *sam = &info->disp_info.disp_user_info[i];
- /* Not really a free, actually a 'clear' */
- pdb_free_sam(&sam);
- }
- }
- info->disp_info.user_dbloaded=False;
- info->disp_info.num_user_account=0;
-}
-
/*******************************************************************
Function to free the per handle data.
********************************************************************/
static void free_samr_db(struct samr_info *info)
{
- /* Groups are talloced */
-
- free_samr_users(info);
-
- info->disp_info.group_dbloaded=False;
- info->disp_info.num_group_account=0;
+ pdb_search_destroy(info->disp_info.users);
+ info->disp_info.users = NULL;
+ pdb_search_destroy(info->disp_info.machines);
+ info->disp_info.machines = NULL;
+ pdb_search_destroy(info->disp_info.groups);
+ info->disp_info.groups = NULL;
+ pdb_search_destroy(info->disp_info.aliases);
+ info->disp_info.aliases = NULL;
+ pdb_search_destroy(info->disp_info.builtins);
+ info->disp_info.builtins = NULL;
}
static void free_samr_info(void *ptr)
@@ -309,154 +295,30 @@ static void samr_clear_sam_passwd(SAM_ACCOUNT *sam_pass)
pdb_set_nt_passwd(sam_pass, NULL, PDB_DEFAULT);
}
-
-static NTSTATUS load_sampwd_entries(struct samr_info *info, uint16 acb_mask, BOOL only_machines)
+static uint32 count_sam_users(struct disp_info *info, uint16 acct_flags)
{
- SAM_ACCOUNT *pwd = NULL;
- SAM_ACCOUNT *pwd_array = NULL;
- NTSTATUS nt_status = NT_STATUS_OK;
- TALLOC_CTX *mem_ctx = info->mem_ctx;
- uint16 query_acb_mask = acb_mask;
-
- DEBUG(10,("load_sampwd_entries\n"));
-
- /* if the snapshoot is already loaded, return */
- if ((info->disp_info.user_dbloaded==True)
- && (info->acb_mask == acb_mask)
- && (info->only_machines == only_machines)) {
- DEBUG(10,("load_sampwd_entries: already in memory\n"));
- return NT_STATUS_OK;
- }
-
- free_samr_users(info);
-
- if (only_machines) {
- query_acb_mask |= ACB_WSTRUST;
- query_acb_mask |= ACB_SVRTRUST;
- }
-
- if (!pdb_setsampwent(False, query_acb_mask)) {
- DEBUG(0, ("load_sampwd_entries: Unable to open passdb.\n"));
- return NT_STATUS_ACCESS_DENIED;
- }
-
- for (; (NT_STATUS_IS_OK(nt_status = pdb_init_sam_talloc(mem_ctx, &pwd)))
- && pdb_getsampwent(pwd) == True; pwd=NULL) {
-
- if (only_machines) {
- if (!((pdb_get_acct_ctrl(pwd) & ACB_WSTRUST)
- || (pdb_get_acct_ctrl(pwd) & ACB_SVRTRUST))) {
- DEBUG(5,("load_sampwd_entries: '%s' is not a machine account - ACB: %x - skipping\n", pdb_get_username(pwd), acb_mask));
- pdb_free_sam(&pwd);
- continue;
- }
- } else {
- if (acb_mask != 0 && !(pdb_get_acct_ctrl(pwd) & acb_mask)) {
- pdb_free_sam(&pwd);
- DEBUG(5,(" acb_mask %x reject\n", acb_mask));
- continue;
- }
- }
-
- /* Realloc some memory for the array of ptr to the SAM_ACCOUNT structs */
- if (info->disp_info.num_user_account % MAX_SAM_ENTRIES == 0) {
-
- DEBUG(10,("load_sampwd_entries: allocating more memory\n"));
- pwd_array=TALLOC_REALLOC_ARRAY(mem_ctx, info->disp_info.disp_user_info, SAM_ACCOUNT,
- info->disp_info.num_user_account+MAX_SAM_ENTRIES);
-
- if (pwd_array==NULL)
- return NT_STATUS_NO_MEMORY;
-
- info->disp_info.disp_user_info=pwd_array;
- }
-
- /* Copy the SAM_ACCOUNT into the array */
- info->disp_info.disp_user_info[info->disp_info.num_user_account]=*pwd;
-
- DEBUG(10,("load_sampwd_entries: entry: %d\n", info->disp_info.num_user_account));
-
- info->disp_info.num_user_account++;
- }
-
- pdb_endsampwent();
-
- /* the snapshoot is in memory, we're ready to enumerate fast */
-
- info->acb_mask = acb_mask;
- info->only_machines = only_machines;
- info->disp_info.user_dbloaded=True;
-
- DEBUG(10,("load_sampwd_entries: done\n"));
-
- return nt_status;
+ struct samr_displayentry *entry;
+ if (info->users == NULL)
+ info->users = pdb_search_users(acct_flags);
+ if (info->users == NULL)
+ return 0;
+ /* Fetch the last possible entry, thus trigger an enumeration */
+ pdb_search_entries(info->users, 0xffffffff, 1, &entry);
+ return info->users->num_entries;
}
-static NTSTATUS load_group_domain_entries(struct samr_info *info, DOM_SID *sid)
+static uint32 count_sam_groups(struct disp_info *info)
{
- GROUP_MAP *map=NULL;
- DOMAIN_GRP *grp_array = NULL;
- uint32 group_entries = 0;
- uint32 i;
- TALLOC_CTX *mem_ctx = info->mem_ctx;
- BOOL ret;
-
- DEBUG(10,("load_group_domain_entries\n"));
-
- /* if the snapshoot is already loaded, return */
- if (info->disp_info.group_dbloaded==True) {
- DEBUG(10,("load_group_domain_entries: already in memory\n"));
- return NT_STATUS_OK;
- }
-
- if (sid_equal(sid, &global_sid_Builtin)) {
- /* No domain groups for now in the BUILTIN domain */
- info->disp_info.num_group_account=0;
- info->disp_info.disp_group_info=NULL;
- info->disp_info.group_dbloaded=True;
- return NT_STATUS_OK;
- }
-
- become_root();
- ret = pdb_enum_group_mapping(SID_NAME_DOM_GRP, &map, (int *)&group_entries, ENUM_ONLY_MAPPED);
- unbecome_root();
-
- if ( !ret ) {
- DEBUG(1, ("load_group_domain_entries: pdb_enum_group_mapping() failed!\n"));
- return NT_STATUS_NO_MEMORY;
- }
-
-
- info->disp_info.num_group_account=group_entries;
-
- grp_array=TALLOC_ARRAY(mem_ctx, DOMAIN_GRP, info->disp_info.num_group_account);
- if (group_entries!=0 && grp_array==NULL) {
- DEBUG(1, ("load_group_domain_entries: talloc() failed for grp_array!\n"));
- SAFE_FREE(map);
- return NT_STATUS_NO_MEMORY;
- }
-
- info->disp_info.disp_group_info=grp_array;
-
- for (i=0; i<group_entries; i++) {
- fstrcpy(grp_array[i].name, map[i].nt_name);
- fstrcpy(grp_array[i].comment, map[i].comment);
- sid_split_rid(&map[i].sid, &grp_array[i].rid);
- grp_array[i].attr=SID_NAME_DOM_GRP;
- }
-
- SAFE_FREE(map);
-
- /* the snapshoot is in memory, we're ready to enumerate fast */
-
- info->disp_info.group_dbloaded=True;
-
- DEBUG(10,("load_group_domain_entries: done\n"));
-
- return NT_STATUS_OK;
+ struct samr_displayentry *entry;
+ if (info->groups == NULL)
+ info->groups = pdb_search_groups();
+ if (info->groups == NULL)
+ return 0;
+ /* Fetch the last possible entry, thus trigger an enumeration */
+ pdb_search_entries(info->groups, 0xffffffff, 1, &entry);
+ return info->groups->num_entries;
}
-
/*******************************************************************
_samr_close_hnd
********************************************************************/
@@ -656,20 +518,14 @@ NTSTATUS _samr_query_sec_obj(pipes_struct *p, SAMR_Q_QUERY_SEC_OBJ *q_u, SAMR_R_
makes a SAM_ENTRY / UNISTR2* structure from a user list.
********************************************************************/
-static NTSTATUS make_user_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, UNISTR2 **uni_name_pp,
- uint32 num_entries, uint32 start_idx, SAM_ACCOUNT *disp_user_info,
- DOM_SID *domain_sid)
+static NTSTATUS make_user_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp,
+ UNISTR2 **uni_name_pp,
+ uint32 num_entries, uint32 start_idx,
+ struct samr_displayentry *entries)
{
uint32 i;
SAM_ENTRY *sam;
UNISTR2 *uni_name;
- SAM_ACCOUNT *pwd = NULL;
- UNISTR2 uni_temp_name;
- const char *temp_name;
- const DOM_SID *user_sid;
- uint32 user_rid;
- fstring user_sid_string;
- fstring domain_sid_string;
*sam_pp = NULL;
*uni_name_pp = NULL;
@@ -687,31 +543,20 @@ static NTSTATUS make_user_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, UN
}
for (i = 0; i < num_entries; i++) {
- pwd = &disp_user_info[i+start_idx];
- temp_name = pdb_get_username(pwd);
-
+ UNISTR2 uni_temp_name;
/*
* usrmgr expects a non-NULL terminated string with
* trust relationships
*/
- if (pdb_get_acct_ctrl(pwd) & ACB_DOMTRUST) {
- init_unistr2(&uni_temp_name, temp_name, UNI_FLAGS_NONE);
+ if (entries[i].acct_flags & ACB_DOMTRUST) {
+ init_unistr2(&uni_temp_name, entries[i].account_name,
+ UNI_FLAGS_NONE);
} else {
- init_unistr2(&uni_temp_name, temp_name, UNI_STR_TERMINATE);
+ init_unistr2(&uni_temp_name, entries[i].account_name,
+ UNI_STR_TERMINATE);
}
- user_sid = pdb_get_user_sid(pwd);
-
- if (!sid_peek_check_rid(domain_sid, user_sid, &user_rid)) {
- DEBUG(0, ("make_user_sam_entry_list: User %s has SID %s, which conflicts with "
- "the domain sid %s. Failing operation.\n",
- temp_name,
- sid_to_string(user_sid_string, user_sid),
- sid_to_string(domain_sid_string, domain_sid)));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- init_sam_entry(&sam[i], &uni_temp_name, user_rid);
+ init_sam_entry(&sam[i], &uni_temp_name, entries[i].rid);
copy_unistr2(&uni_name[i], &uni_temp_name);
}
@@ -728,15 +573,12 @@ NTSTATUS _samr_enum_dom_users(pipes_struct *p, SAMR_Q_ENUM_DOM_USERS *q_u,
SAMR_R_ENUM_DOM_USERS *r_u)
{
struct samr_info *info = NULL;
- uint32 struct_size=0x20; /* W2K always reply that, client doesn't care */
int num_account;
uint32 enum_context=q_u->start_idx;
- uint32 max_size=q_u->max_size;
- uint32 temp_size;
enum remote_arch_types ra_type = get_remote_arch();
int max_sam_entries = (ra_type == RA_WIN95) ? MAX_SAM_ENTRIES_W95 : MAX_SAM_ENTRIES_W2K;
uint32 max_entries = max_sam_entries;
- DOM_SID domain_sid;
+ struct samr_displayentry *entries = NULL;
r_u->status = NT_STATUS_OK;
@@ -744,8 +586,6 @@ NTSTATUS _samr_enum_dom_users(pipes_struct *p, SAMR_Q_ENUM_DOM_USERS *q_u,
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
return NT_STATUS_INVALID_HANDLE;
- domain_sid = info->sid;
-
if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(info->acc_granted,
SA_RIGHT_DOMAIN_ENUM_ACCOUNTS,
"_samr_enum_dom_users"))) {
@@ -755,60 +595,36 @@ NTSTATUS _samr_enum_dom_users(pipes_struct *p, SAMR_Q_ENUM_DOM_USERS *q_u,
DEBUG(5,("_samr_enum_dom_users: %d\n", __LINE__));
become_root();
- r_u->status=load_sampwd_entries(info, q_u->acb_mask, False);
+ if (info->disp_info.users == NULL)
+ info->disp_info.users = pdb_search_users(q_u->acb_mask);
+ if (info->disp_info.users == NULL)
+ return NT_STATUS_ACCESS_DENIED;
+ num_account = pdb_search_entries(info->disp_info.users,
+ enum_context, max_entries,
+ &entries);
unbecome_root();
-
- if (!NT_STATUS_IS_OK(r_u->status))
- return r_u->status;
-
- num_account = info->disp_info.num_user_account;
- if (enum_context > num_account) {
- DEBUG(5, ("_samr_enum_dom_users: enumeration handle over total entries\n"));
+ if (num_account == 0) {
+ DEBUG(5, ("_samr_enum_dom_users: enumeration handle over "
+ "total entries\n"));
return NT_STATUS_OK;
}
- /* verify we won't overflow */
- if (max_entries > num_account-enum_context) {
- max_entries = num_account-enum_context;
- DEBUG(5, ("_samr_enum_dom_users: only %d entries to return\n", max_entries));
- }
-
- /* calculate the size and limit on the number of entries we will return */
- temp_size=max_entries*struct_size;
-
- if (temp_size>max_size) {
- max_entries=MIN((max_size/struct_size),max_entries);;
- DEBUG(5, ("_samr_enum_dom_users: buffer size limits to only %d entries\n", max_entries));
- }
-
- /*
- * Note from JRA. total_entries is not being used here. Currently if there is a
- * large user base then it looks like NT will enumerate until get_sampwd_entries
- * returns False due to num_entries being zero. This will cause an access denied
- * return. I don't think this is right and needs further investigation. Note that
- * this is also the same in the TNG code (I don't think that has been tested with
- * a very large user list as MAX_SAM_ENTRIES is set to 600).
- *
- * I also think that one of the 'num_entries' return parameters is probably
- * the "max entries" parameter - but in the TNG code they're all currently set to the same
- * value (again I think this is wrong).
- */
-
- r_u->status = make_user_sam_entry_list(p->mem_ctx, &r_u->sam, &r_u->uni_acct_name,
- max_entries, enum_context,
- info->disp_info.disp_user_info,
- &domain_sid);
+ r_u->status = make_user_sam_entry_list(p->mem_ctx, &r_u->sam,
+ &r_u->uni_acct_name,
+ num_account, enum_context,
+ entries);
if (!NT_STATUS_IS_OK(r_u->status))
return r_u->status;
- if (enum_context+max_entries < num_account)
+ if (max_entries <= num_account)
r_u->status = STATUS_MORE_ENTRIES;
DEBUG(5, ("_samr_enum_dom_users: %d\n", __LINE__));
- init_samr_r_enum_dom_users(r_u, q_u->start_idx + max_entries, max_entries);
+ init_samr_r_enum_dom_users(r_u, q_u->start_idx + num_account,
+ num_account);
DEBUG(5,("_samr_enum_dom_users: %d\n", __LINE__));
@@ -819,8 +635,10 @@ NTSTATUS _samr_enum_dom_users(pipes_struct *p, SAMR_Q_ENUM_DOM_USERS *q_u,
makes a SAM_ENTRY / UNISTR2* structure from a group list.
********************************************************************/
-static void make_group_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, UNISTR2 **uni_name_pp,
- uint32 num_sam_entries, DOMAIN_GRP *grp)
+static void make_group_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp,
+ UNISTR2 **uni_name_pp,
+ uint32 num_sam_entries,
+ struct samr_displayentry *entries)
{
uint32 i;
SAM_ENTRY *sam;
@@ -844,8 +662,9 @@ static void make_group_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, UNIST
/*
* JRA. I think this should include the null. TNG does not.
*/
- init_unistr2(&uni_name[i], grp[i].name, UNI_STR_TERMINATE);
- init_sam_entry(&sam[i], &uni_name[i], grp[i].rid);
+ init_unistr2(&uni_name[i], entries[i].account_name,
+ UNI_STR_TERMINATE);
+ init_sam_entry(&sam[i], &uni_name[i], entries[i].rid);
}
*sam_pp = sam;
@@ -853,179 +672,107 @@ static void make_group_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, UNIST
}
/*******************************************************************
- Get the group entries - similar to get_sampwd_entries().
- ******************************************************************/
-
-static NTSTATUS get_group_domain_entries( TALLOC_CTX *ctx,
- DOMAIN_GRP **d_grp, DOM_SID *sid, uint32 start_idx,
- uint32 *p_num_entries, uint32 max_entries )
-{
- GROUP_MAP *map=NULL;
- int i;
- uint32 group_entries = 0;
- uint32 num_entries = 0;
- NTSTATUS result = NT_STATUS_OK;
-
- *p_num_entries = 0;
-
- /* access checks for the users were performed higher up. become/unbecome_root()
- needed for some passdb backends to enumerate groups */
-
- become_root();
- pdb_enum_group_mapping(SID_NAME_DOM_GRP, &map, (int *)&group_entries,
- ENUM_ONLY_MAPPED);
- unbecome_root();
-
- num_entries=group_entries-start_idx;
-
- /* limit the number of entries */
- if (num_entries>max_entries) {
- DEBUG(5,("Limiting to %d entries\n", max_entries));
- num_entries=max_entries;
- result = STATUS_MORE_ENTRIES;
- }
-
- *d_grp=TALLOC_ZERO_ARRAY(ctx, DOMAIN_GRP, num_entries);
- if (num_entries!=0 && *d_grp==NULL){
- SAFE_FREE(map);
- return NT_STATUS_NO_MEMORY;
- }
-
- for (i=0; i<num_entries; i++) {
- fstrcpy((*d_grp)[i].name, map[i+start_idx].nt_name);
- fstrcpy((*d_grp)[i].comment, map[i+start_idx].comment);
- sid_split_rid(&map[i+start_idx].sid, &(*d_grp)[i].rid);
- (*d_grp)[i].attr=SID_NAME_DOM_GRP;
- }
-
- SAFE_FREE(map);
-
- *p_num_entries = num_entries;
-
- DEBUG(10,("get_group_domain_entries: returning %d entries\n",
- *p_num_entries));
-
- return result;
-}
-
-/*******************************************************************
- Wrapper for enumerating local groups
- ******************************************************************/
-
-static NTSTATUS get_alias_entries( TALLOC_CTX *ctx, DOMAIN_GRP **d_grp,
- const DOM_SID *sid, uint32 start_idx,
- uint32 *p_num_entries, uint32 max_entries )
-{
- struct acct_info *info;
- int i;
- BOOL res;
-
- become_root();
- res = pdb_enum_aliases(sid, start_idx, max_entries,
- p_num_entries, &info);
- unbecome_root();
-
- if (!res)
- return NT_STATUS_ACCESS_DENIED;
-
- if (*p_num_entries == 0)
- return NT_STATUS_OK;
-
- *d_grp = TALLOC_ARRAY(ctx, DOMAIN_GRP, *p_num_entries);
-
- if (*d_grp == NULL) {
- SAFE_FREE(info);
- return NT_STATUS_NO_MEMORY;
- }
-
- for (i=0; i<*p_num_entries; i++) {
- fstrcpy((*d_grp)[i].name, info[i].acct_name);
- fstrcpy((*d_grp)[i].comment, info[i].acct_desc);
- (*d_grp)[i].rid = info[i].rid;
- (*d_grp)[i].attr = SID_NAME_ALIAS;
- }
-
- SAFE_FREE(info);
- return NT_STATUS_OK;
-}
-
-/*******************************************************************
samr_reply_enum_dom_groups
********************************************************************/
NTSTATUS _samr_enum_dom_groups(pipes_struct *p, SAMR_Q_ENUM_DOM_GROUPS *q_u, SAMR_R_ENUM_DOM_GROUPS *r_u)
{
- DOMAIN_GRP *grp=NULL;
- uint32 num_entries;
- DOM_SID sid;
- uint32 acc_granted;
+ struct samr_info *info = NULL;
+ struct samr_displayentry *groups;
+ uint32 num_groups;
r_u->status = NT_STATUS_OK;
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid, &acc_granted))
+ /* find the policy handle. open a policy on it. */
+ if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
return NT_STATUS_INVALID_HANDLE;
-
- if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_DOMAIN_ENUM_ACCOUNTS, "_samr_enum_dom_groups"))) {
+
+ r_u->status = access_check_samr_function(info->acc_granted,
+ SA_RIGHT_DOMAIN_ENUM_ACCOUNTS,
+ "_samr_enum_dom_groups");
+ if (!NT_STATUS_IS_OK(r_u->status))
return r_u->status;
- }
DEBUG(5,("samr_reply_enum_dom_groups: %d\n", __LINE__));
/* the domain group array is being allocated in the function below */
- r_u->status = get_group_domain_entries(p->mem_ctx, &grp, &sid,
- q_u->start_idx, &num_entries,
- MAX_SAM_ENTRIES);
- if (!NT_STATUS_IS_OK(r_u->status) &&
- !NT_STATUS_EQUAL(r_u->status, STATUS_MORE_ENTRIES))
- return r_u->status;
+ become_root();
+ if (info->disp_info.groups == NULL)
+ info->disp_info.groups = pdb_search_groups();
+ unbecome_root();
+ if (info->disp_info.groups == NULL)
+ return NT_STATUS_ACCESS_DENIED;
+
+ become_root();
+ num_groups = pdb_search_entries(info->disp_info.groups, q_u->start_idx,
+ MAX_SAM_ENTRIES, &groups);
+ unbecome_root();
+
make_group_sam_entry_list(p->mem_ctx, &r_u->sam, &r_u->uni_grp_name,
- num_entries, grp);
+ num_groups, groups);
- init_samr_r_enum_dom_groups(r_u, q_u->start_idx+num_entries,
- num_entries);
+ init_samr_r_enum_dom_groups(r_u, q_u->start_idx, num_groups);
DEBUG(5,("samr_enum_dom_groups: %d\n", __LINE__));
return r_u->status;
}
-
/*******************************************************************
samr_reply_enum_dom_aliases
********************************************************************/
NTSTATUS _samr_enum_dom_aliases(pipes_struct *p, SAMR_Q_ENUM_DOM_ALIASES *q_u, SAMR_R_ENUM_DOM_ALIASES *r_u)
{
- DOMAIN_GRP *grp=NULL;
- uint32 num_entries = 0;
- fstring sid_str;
- DOM_SID sid;
+ struct samr_info *info;
+ struct samr_displayentry *aliases;
+ struct pdb_search **search = NULL;
+ uint32 num_aliases = 0;
NTSTATUS status;
- uint32 acc_granted;
-
+
r_u->status = NT_STATUS_OK;
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid, &acc_granted))
+ /* find the policy handle. open a policy on it. */
+ if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
return NT_STATUS_INVALID_HANDLE;
- if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_DOMAIN_ENUM_ACCOUNTS, "_samr_enum_dom_aliases"))) {
+ r_u->status = access_check_samr_function(info->acc_granted,
+ SA_RIGHT_DOMAIN_ENUM_ACCOUNTS,
+ "_samr_enum_dom_aliases");
+ if (!NT_STATUS_IS_OK(r_u->status))
return r_u->status;
- }
-
- sid_to_string(sid_str, &sid);
- DEBUG(5,("samr_reply_enum_dom_aliases: sid %s\n", sid_str));
- status = get_alias_entries(p->mem_ctx, &grp, &sid, q_u->start_idx,
- &num_entries, MAX_SAM_ENTRIES);
- if (!NT_STATUS_IS_OK(status)) return status;
+ DEBUG(5,("samr_reply_enum_dom_aliases: sid %s\n",
+ sid_string_static(&info->sid)));
+
+ if (sid_check_is_domain(&info->sid))
+ search = &info->disp_info.aliases;
+ if (sid_check_is_builtin(&info->sid))
+ search = &info->disp_info.builtins;
+
+ if (search == NULL) return NT_STATUS_INVALID_HANDLE;
+
+ become_root();
+ if (*search == NULL)
+ *search = pdb_search_aliases(&info->sid);
+ unbecome_root();
+
+ if (*search == NULL) return NT_STATUS_ACCESS_DENIED;
- make_group_sam_entry_list(p->mem_ctx, &r_u->sam, &r_u->uni_grp_name, num_entries, grp);
+ become_root();
+ num_aliases = pdb_search_entries(*search, q_u->start_idx,
+ MAX_SAM_ENTRIES, &aliases);
+ unbecome_root();
+
+ make_group_sam_entry_list(p->mem_ctx, &r_u->sam, &r_u->uni_grp_name,
+ num_aliases, aliases);
- /*safe_free(grp);*/
+ if (!NT_STATUS_IS_OK(status)) return status;
- init_samr_r_enum_dom_aliases(r_u, q_u->start_idx + num_entries, num_entries);
+ init_samr_r_enum_dom_aliases(r_u, q_u->start_idx + num_aliases,
+ num_aliases);
DEBUG(5,("samr_enum_dom_aliases: %d\n", __LINE__));
@@ -1053,6 +800,7 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u,
enum remote_arch_types ra_type = get_remote_arch();
int max_sam_entries = (ra_type == RA_WIN95) ? MAX_SAM_ENTRIES_W95 : MAX_SAM_ENTRIES_W2K;
DOM_SID domain_sid;
+ struct samr_displayentry *entries = NULL;
DEBUG(5, ("samr_reply_query_dispinfo: %d\n", __LINE__));
r_u->status = NT_STATUS_OK;
@@ -1091,68 +839,29 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u,
* JFM, 12/20/2001
*/
- /* Get what we need from the password database */
- switch (q_u->switch_level) {
- case 0x1:
- /* When playing with usrmgr, this is necessary
- if you want immediate refresh after editing
- a user. I would like to do this after the
- setuserinfo2, but we do not have access to
- the domain handle in that call, only to the
- user handle. Where else does this hurt?
- -- Volker
- */
-#if 0
- /* We cannot do this here - it kills performace. JRA. */
- free_samr_users(info);
-#endif
- case 0x2:
- case 0x4:
- become_root();
- /* Level 2 is for all machines, otherwise only 'normal' users */
- r_u->status=load_sampwd_entries(info, ACB_NORMAL, q_u->switch_level==2);
- unbecome_root();
- if (!NT_STATUS_IS_OK(r_u->status)) {
- DEBUG(5, ("_samr_query_dispinfo: load_sampwd_entries failed\n"));
- return r_u->status;
- }
- num_account = info->disp_info.num_user_account;
- break;
- case 0x3:
- case 0x5:
- r_u->status = load_group_domain_entries(info, &info->sid);
- if (!NT_STATUS_IS_OK(r_u->status))
- return r_u->status;
- num_account = info->disp_info.num_group_account;
- break;
- default:
- DEBUG(0,("_samr_query_dispinfo: Unknown info level (%u)\n", (unsigned int)q_u->switch_level ));
- return NT_STATUS_INVALID_INFO_CLASS;
+ if ((q_u->switch_level < 1) || (q_u->switch_level > 5)) {
+ DEBUG(0,("_samr_query_dispinfo: Unknown info level (%u)\n",
+ (unsigned int)q_u->switch_level ));
+ return NT_STATUS_INVALID_INFO_CLASS;
}
/* first limit the number of entries we will return */
if(max_entries > max_sam_entries) {
- DEBUG(5, ("samr_reply_query_dispinfo: client requested %d entries, limiting to %d\n", max_entries, max_sam_entries));
+ DEBUG(5, ("samr_reply_query_dispinfo: client requested %d "
+ "entries, limiting to %d\n", max_entries,
+ max_sam_entries));
max_entries = max_sam_entries;
}
- if (enum_context > num_account) {
- DEBUG(5, ("samr_reply_query_dispinfo: enumeration handle over total entries\n"));
- return NT_STATUS_NO_MORE_ENTRIES;
- }
-
- /* verify we won't overflow */
- if (max_entries > num_account-enum_context) {
- max_entries = num_account-enum_context;
- DEBUG(5, ("samr_reply_query_dispinfo: only %d entries to return\n", max_entries));
- }
+ /* calculate the size and limit on the number of entries we will
+ * return */
- /* calculate the size and limit on the number of entries we will return */
temp_size=max_entries*struct_size;
if (temp_size>max_size) {
max_entries=MIN((max_size/struct_size),max_entries);;
- DEBUG(5, ("samr_reply_query_dispinfo: buffer size limits to only %d entries\n", max_entries));
+ DEBUG(5, ("samr_reply_query_dispinfo: buffer size limits to "
+ "only %d entries\n", max_entries));
}
if (!(ctr = TALLOC_ZERO_P(p->mem_ctx,SAM_DISPINFO_CTR)))
@@ -1160,61 +869,80 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u,
ZERO_STRUCTP(ctr);
+ become_root();
+
+ switch (q_u->switch_level) {
+ case 0x1:
+ case 0x4:
+ if (info->disp_info.users == NULL)
+ info->disp_info.users = pdb_search_users(ACB_NORMAL);
+ if (info->disp_info.users == NULL)
+ return NT_STATUS_ACCESS_DENIED;
+ num_account = pdb_search_entries(info->disp_info.users,
+ enum_context, max_entries,
+ &entries);
+ break;
+ case 0x2:
+ if (info->disp_info.machines == NULL)
+ info->disp_info.machines =
+ pdb_search_users(ACB_WSTRUST|ACB_SVRTRUST);
+ if (info->disp_info.machines == NULL)
+ return NT_STATUS_ACCESS_DENIED;
+ num_account = pdb_search_entries(info->disp_info.machines,
+ enum_context, max_entries,
+ &entries);
+ break;
+ case 0x3:
+ case 0x5:
+ if (info->disp_info.groups == NULL)
+ info->disp_info.groups = pdb_search_groups();
+ if (info->disp_info.groups == NULL)
+ return NT_STATUS_ACCESS_DENIED;
+ num_account = pdb_search_entries(info->disp_info.groups,
+ enum_context, max_entries,
+ &entries);
+ break;
+ default:
+ smb_panic("info class changed");
+ break;
+ }
+ unbecome_root();
+
/* Now create reply structure */
switch (q_u->switch_level) {
case 0x1:
- if (max_entries) {
- if (!(ctr->sam.info1 = TALLOC_ZERO_ARRAY(p->mem_ctx,SAM_DISPINFO_1,max_entries)))
- return NT_STATUS_NO_MEMORY;
- }
- disp_ret = init_sam_dispinfo_1(p->mem_ctx, ctr->sam.info1, max_entries, enum_context,
- info->disp_info.disp_user_info, &domain_sid);
- if (!NT_STATUS_IS_OK(disp_ret))
- return disp_ret;
+ disp_ret = init_sam_dispinfo_1(p->mem_ctx, &ctr->sam.info1,
+ num_account, enum_context,
+ entries);
break;
case 0x2:
- if (max_entries) {
- if (!(ctr->sam.info2 = TALLOC_ZERO_ARRAY(p->mem_ctx,SAM_DISPINFO_2,max_entries)))
- return NT_STATUS_NO_MEMORY;
- }
- disp_ret = init_sam_dispinfo_2(p->mem_ctx, ctr->sam.info2, max_entries, enum_context,
- info->disp_info.disp_user_info, &domain_sid);
- if (!NT_STATUS_IS_OK(disp_ret))
- return disp_ret;
+ disp_ret = init_sam_dispinfo_2(p->mem_ctx, &ctr->sam.info2,
+ num_account, enum_context,
+ entries);
break;
case 0x3:
- if (max_entries) {
- if (!(ctr->sam.info3 = TALLOC_ZERO_ARRAY(p->mem_ctx,SAM_DISPINFO_3,max_entries)))
- return NT_STATUS_NO_MEMORY;
- }
- disp_ret = init_sam_dispinfo_3(p->mem_ctx, ctr->sam.info3, max_entries, enum_context, info->disp_info.disp_group_info);
- if (!NT_STATUS_IS_OK(disp_ret))
- return disp_ret;
+ disp_ret = init_sam_dispinfo_3(p->mem_ctx, &ctr->sam.info3,
+ num_account, enum_context,
+ entries);
break;
case 0x4:
- if (max_entries) {
- if (!(ctr->sam.info4 = TALLOC_ZERO_ARRAY(p->mem_ctx,SAM_DISPINFO_4,max_entries)))
- return NT_STATUS_NO_MEMORY;
- }
- disp_ret = init_sam_dispinfo_4(p->mem_ctx, ctr->sam.info4, max_entries, enum_context, info->disp_info.disp_user_info);
- if (!NT_STATUS_IS_OK(disp_ret))
- return disp_ret;
+ disp_ret = init_sam_dispinfo_4(p->mem_ctx, &ctr->sam.info4,
+ num_account, enum_context,
+ entries);
break;
case 0x5:
- if (max_entries) {
- if (!(ctr->sam.info5 = TALLOC_ZERO_ARRAY(p->mem_ctx,SAM_DISPINFO_5,max_entries)))
- return NT_STATUS_NO_MEMORY;
- }
- disp_ret = init_sam_dispinfo_5(p->mem_ctx, ctr->sam.info5, max_entries, enum_context, info->disp_info.disp_group_info);
- if (!NT_STATUS_IS_OK(disp_ret))
- return disp_ret;
+ disp_ret = init_sam_dispinfo_5(p->mem_ctx, &ctr->sam.info5,
+ num_account, enum_context,
+ entries);
break;
-
default:
- ctr->sam.info = NULL;
- return NT_STATUS_INVALID_INFO_CLASS;
+ smb_panic("info class changed");
+ break;
}
+ if (!NT_STATUS_IS_OK(disp_ret))
+ return disp_ret;
+
/* calculate the total size */
total_data_size=num_account*struct_size;
@@ -1223,7 +951,9 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u,
DEBUG(5, ("_samr_query_dispinfo: %d\n", __LINE__));
- init_samr_r_query_dispinfo(r_u, max_entries, total_data_size, temp_size, q_u->switch_level, ctr, r_u->status);
+ init_samr_r_query_dispinfo(r_u, num_account, total_data_size,
+ temp_size, q_u->switch_level, ctr,
+ r_u->status);
return r_u->status;
@@ -2106,23 +1836,11 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
flag, nt_expire, nt_min_age);
break;
case 0x02:
- become_root();
- r_u->status=load_sampwd_entries(info, ACB_NORMAL, False);
+ become_root();
+ num_users=count_sam_users(&info->disp_info,
+ ACB_NORMAL);
+ num_groups=count_sam_groups(&info->disp_info);
unbecome_root();
- if (!NT_STATUS_IS_OK(r_u->status)) {
- DEBUG(5, ("_samr_query_dispinfo: load_sampwd_entries failed\n"));
- return r_u->status;
- }
- num_users=info->disp_info.num_user_account;
- free_samr_db(info);
-
- r_u->status=load_group_domain_entries(info, get_global_sam_sid());
- if (!NT_STATUS_IS_OK(r_u->status)) {
- DEBUG(5, ("_samr_query_dispinfo: load_group_domain_entries failed\n"));
- return r_u->status;
- }
- num_groups=info->disp_info.num_group_account;
- free_samr_db(info);
account_policy_get(AP_TIME_TO_LOGOUT, &account_policy_temp);
u_logout = account_policy_temp;
@@ -4380,13 +4098,9 @@ NTSTATUS _samr_remove_sid_foreign_domain(pipes_struct *p,
SAMR_Q_REMOVE_SID_FOREIGN_DOMAIN *q_u,
SAMR_R_REMOVE_SID_FOREIGN_DOMAIN *r_u)
{
- DOM_SID delete_sid, alias_sid;
- SAM_ACCOUNT *sam_pass=NULL;
+ DOM_SID delete_sid, domain_sid;
uint32 acc_granted;
- GROUP_MAP map;
- BOOL is_user = False;
NTSTATUS result;
- enum SID_NAME_USE type = SID_NAME_UNKNOWN;
sid_copy( &delete_sid, &q_u->sid.sid );
@@ -4395,7 +4109,8 @@ NTSTATUS _samr_remove_sid_foreign_domain(pipes_struct *p,
/* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->dom_pol, &alias_sid, &acc_granted))
+ if (!get_lsa_policy_samr_sid(p, &q_u->dom_pol, &domain_sid,
+ &acc_granted))
return NT_STATUS_INVALID_HANDLE;
result = access_check_samr_function(acc_granted, STD_RIGHT_DELETE_ACCESS,
@@ -4405,80 +4120,33 @@ NTSTATUS _samr_remove_sid_foreign_domain(pipes_struct *p,
return result;
DEBUG(8, ("_samr_remove_sid_foreign_domain:sid is %s\n",
- sid_string_static(&alias_sid)));
-
- /* make sure we can handle this */
-
- 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;
- }
+ sid_string_static(&domain_sid)));
- /* check if the user exists before trying to delete */
-
- pdb_init_sam(&sam_pass);
-
- 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;
- }
- }
-
/* we can only delete a user from a group since we don't have
nested groups anyways. So in the latter case, just say OK */
-
- if ( is_user ) {
- GROUP_MAP *mappings = NULL;
- int 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;
- }
-
- if ( !user_in_unix_group_list(pdb_get_username(sam_pass), grp2->gr_name) )
- continue;
-
- 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) ) {
- /* should we fail here ? */
- DEBUG(0,("_samr_remove_sid_foreign_domain: Delete user [%s] from group [%s] failed!\n",
- pdb_get_username(sam_pass), grp2->gr_name ));
- continue;
- }
-
- DEBUG(10,("_samr_remove_sid_foreign_domain: Removed user [%s] from group [%s]!\n",
- pdb_get_username(sam_pass), grp2->gr_name ));
- }
-
- SAFE_FREE(mappings);
- }
+ /* TODO: The above comment nowadays is bogus. Since we have nested
+ * groups now, and aliases members are never reported out of the unix
+ * group membership, the "just say OK" makes this call a no-op. For
+ * us. This needs fixing however. */
+
+ /* I've only ever seen this in the wild when deleting a user from
+ * usrmgr.exe. domain_sid is the builtin domain, and the sid to delete
+ * is the user about to be deleted. I very much suspect this is the
+ * only application of this call. To verify this, let people report
+ * other cases. */
+
+ if (!sid_check_is_builtin(&domain_sid)) {
+ DEBUG(1,("_samr_remove_sid_foreign_domain: domain_sid = %s, "
+ "global_sam_sid() = %s\n",
+ sid_string_static(&domain_sid),
+ sid_string_static(get_global_sam_sid())));
+ DEBUGADD(1,("please report to samba-technical@samba.org!\n"));
+ return NT_STATUS_OK;
}
-
- result = NT_STATUS_OK;
-done:
- pdb_free_sam(&sam_pass);
+
+ result = NT_STATUS_OK;
return result;
}
@@ -4545,21 +4213,11 @@ NTSTATUS _samr_unknown_2e(pipes_struct *p, SAMR_Q_UNKNOWN_2E *q_u, SAMR_R_UNKNOW
break;
case 0x02:
become_root();
- r_u->status=load_sampwd_entries(info, ACB_NORMAL, False);
+ num_users = count_sam_users(&info->disp_info,
+ ACB_NORMAL);
+ num_groups = count_sam_groups(&info->disp_info);
unbecome_root();
- if (!NT_STATUS_IS_OK(r_u->status)) {
- DEBUG(5, ("_samr_unknown_2e: load_sampwd_entries failed\n"));
- return r_u->status;
- }
- num_users=info->disp_info.num_user_account;
- free_samr_db(info);
-
- r_u->status=load_group_domain_entries(info, get_global_sam_sid());
- if (NT_STATUS_IS_ERR(r_u->status)) {
- DEBUG(5, ("_samr_unknown_2e: load_group_domain_entries failed\n"));
- return r_u->status;
- }
- num_groups=info->disp_info.num_group_account;
+
free_samr_db(info);
account_policy_get(AP_TIME_TO_LOGOUT, &account_policy_temp);