diff options
Diffstat (limited to 'source3/passdb')
-rw-r--r-- | source3/passdb/pdb_interface.c | 401 | ||||
-rw-r--r-- | source3/passdb/pdb_ldap.c | 469 |
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 */ |