diff options
author | Volker Lendecke <vlendec@samba.org> | 2005-04-15 13:41:49 +0000 |
---|---|---|
committer | Volker Lendecke <vlendec@samba.org> | 2005-04-15 13:41:49 +0000 |
commit | 594ecd201b5a6aba12039657cd8fcde8c65049f1 (patch) | |
tree | b6d9cb9c0d1c7650f6dcec46316ac5b9dbbd3fed /source/passdb | |
parent | b28d1f4fa991c11c490619b78782b2f0bf741658 (diff) | |
download | samba-594ecd201b5a6aba12039657cd8fcde8c65049f1.tar.gz samba-594ecd201b5a6aba12039657cd8fcde8c65049f1.tar.xz samba-594ecd201b5a6aba12039657cd8fcde8c65049f1.zip |
r6351: This is quite a large and intrusive patch, but there are not many pieces that
can be taken out of it, so I decided to commit this in one lump. It changes
the passdb enumerating functions to use ldap paged results where possible. In
particular the samr calls querydispinfo, enumdomusers and friends have
undergone significant internal changes. I have tested this extensively with
rpcclient and a bit with usrmgr.exe. More tests and the merge to trunk will
follow later.
The code is based on a first implementation by Günther Deschner, but has
evolved quite a bit since then.
Volker
Diffstat (limited to 'source/passdb')
-rw-r--r-- | source/passdb/pdb_interface.c | 401 | ||||
-rw-r--r-- | source/passdb/pdb_ldap.c | 469 |
2 files changed, 717 insertions, 153 deletions
diff --git a/source/passdb/pdb_interface.c b/source/passdb/pdb_interface.c index 301dc101eb4..edcd1c92223 100644 --- a/source/passdb/pdb_interface.c +++ b/source/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/source/passdb/pdb_ldap.c b/source/passdb/pdb_ldap.c index 3899949058a..752eb878b19 100644 --- a/source/passdb/pdb_ldap.c +++ b/source/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 */ |