summaryrefslogtreecommitdiff
path: root/source3/passdb
diff options
context:
space:
mode:
Diffstat (limited to 'source3/passdb')
-rw-r--r--source3/passdb/pdb_interface.c401
-rw-r--r--source3/passdb/pdb_ldap.c469
2 files changed, 717 insertions, 153 deletions
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 */