summaryrefslogtreecommitdiff
path: root/source3/winbindd/idmap_adex/gc_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/winbindd/idmap_adex/gc_util.c')
-rw-r--r--source3/winbindd/idmap_adex/gc_util.c862
1 files changed, 0 insertions, 862 deletions
diff --git a/source3/winbindd/idmap_adex/gc_util.c b/source3/winbindd/idmap_adex/gc_util.c
deleted file mode 100644
index 461a2e679b..0000000000
--- a/source3/winbindd/idmap_adex/gc_util.c
+++ /dev/null
@@ -1,862 +0,0 @@
-/*
- * idmap_adex: Global Catalog search interface
- *
- * Copyright (C) Gerald (Jerry) Carter 2007-2008
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "includes.h"
-#include "ads.h"
-#include "idmap.h"
-#include "idmap_adex.h"
-#include "libads/cldap.h"
-#include "../libcli/ldap/ldap_ndr.h"
-
-#undef DBGC_CLASS
-#define DBGC_CLASS DBGC_IDMAP
-
-static struct gc_info *_gc_server_list = NULL;
-
-
-/**********************************************************************
- *********************************************************************/
-
-static struct gc_info *gc_list_head(void)
-{
- return _gc_server_list;
-}
-
-/**********************************************************************
- Checks if either of the domains is a subdomain of the other
- *********************************************************************/
-
-static bool is_subdomain(const char* a, const char *b)
-{
- char *s;
- TALLOC_CTX *frame = talloc_stackframe();
- char *x, *y;
- bool ret = false;
-
- /* Trivial cases */
-
- if (!a && !b)
- return true;
-
- if (!a || !b)
- return false;
-
- /* Normalize the case */
-
- x = talloc_strdup(frame, a);
- y = talloc_strdup(frame, b);
- if (!x || !y) {
- ret = false;
- goto done;
- }
-
- strupper_m(x);
- strupper_m(y);
-
- /* Exact match */
-
- if (strcmp(x, y) == 0) {
- ret = true;
- goto done;
- }
-
- /* Check for trailing substrings */
-
- s = strstr_m(x, y);
- if (s && (strlen(s) == strlen(y))) {
- ret = true;
- goto done;
- }
-
- s = strstr_m(y, x);
- if (s && (strlen(s) == strlen(x))) {
- ret = true;
- goto done;
- }
-
-done:
- talloc_destroy(frame);
-
- return ret;
-}
-
-/**********************************************************************
- *********************************************************************/
-
- NTSTATUS gc_find_forest_root(struct gc_info *gc, const char *domain)
-{
- ADS_STRUCT *ads = NULL;
- ADS_STATUS ads_status;
- NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
- struct NETLOGON_SAM_LOGON_RESPONSE_EX cldap_reply;
- TALLOC_CTX *frame = talloc_stackframe();
- struct sockaddr_storage ss;
-
- if (!gc || !domain) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- ZERO_STRUCT(cldap_reply);
-
- ads = ads_init(domain, NULL, NULL);
- BAIL_ON_PTR_ERROR(ads, nt_status);
-
- ads->auth.flags = ADS_AUTH_NO_BIND;
- ads_status = ads_connect(ads);
- if (!ADS_ERR_OK(ads_status)) {
- DEBUG(4, ("find_forest_root: ads_connect(%s) failed! (%s)\n",
- domain, ads_errstr(ads_status)));
- }
- nt_status = ads_ntstatus(ads_status);
- BAIL_ON_NTSTATUS_ERROR(nt_status);
-
- if (!resolve_name(ads->config.ldap_server_name, &ss, 0x20, true)) {
- DEBUG(5,("gc_find_forest_root: unable to resolve name %s\n",
- ads->config.ldap_server_name));
- nt_status = NT_STATUS_IO_TIMEOUT;
- /* This matches the old code which did the resolve in
- * ads_cldap_netlogon_5 */
- BAIL_ON_NTSTATUS_ERROR(nt_status);
- }
-
- if (!ads_cldap_netlogon_5(frame,
- &ss,
- ads->config.realm,
- &cldap_reply))
- {
- DEBUG(4,("find_forest_root: Failed to get a CLDAP reply from %s!\n",
- ads->server.ldap_server));
- nt_status = NT_STATUS_IO_TIMEOUT;
- BAIL_ON_NTSTATUS_ERROR(nt_status);
- }
-
- gc->forest_name = talloc_strdup(gc, cldap_reply.forest);
- BAIL_ON_PTR_ERROR(gc->forest_name, nt_status);
-
-done:
- if (ads) {
- ads_destroy(&ads);
- }
-
- return nt_status;
-}
-
-/**********************************************************************
- *********************************************************************/
-
-static NTSTATUS gc_add_forest(const char *domain)
-{
- NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
- struct gc_info *gc = NULL;
- struct gc_info *find_gc = NULL;
- char *dn;
- ADS_STRUCT *ads = NULL;
- struct likewise_cell *primary_cell = NULL;
-
- primary_cell = cell_list_head();
- if (!primary_cell) {
- nt_status = NT_STATUS_INVALID_SERVER_STATE;
- BAIL_ON_NTSTATUS_ERROR(nt_status);
- }
-
- /* Check for duplicates based on domain name first as this
- requires no connection */
-
- find_gc = gc_list_head();
- while (find_gc) {
- if (strequal (find_gc->forest_name, domain))
- break;
- find_gc = find_gc->next;
- }
-
- if (find_gc) {
- DEBUG(10,("gc_add_forest: %s already in list\n", find_gc->forest_name));
- return NT_STATUS_OK;
- }
-
- if ((gc = talloc_zero(NULL, struct gc_info)) == NULL) {
- nt_status = NT_STATUS_NO_MEMORY;
- BAIL_ON_NTSTATUS_ERROR(nt_status);
- }
-
- /* Query the rootDSE for the forest root naming conect first.
- Check that the a GC server for the forest has not already
- been added */
-
- nt_status = gc_find_forest_root(gc, domain);
- BAIL_ON_NTSTATUS_ERROR(nt_status);
-
- find_gc = gc_list_head();
- while (find_gc) {
- if (strequal (find_gc->forest_name, gc->forest_name))
- break;
- find_gc = find_gc->next;
- }
-
- if (find_gc) {
- DEBUG(10,("gc_add_forest: Forest %s already in list\n",
- find_gc->forest_name));
- return NT_STATUS_OK;
- }
-
- /* Not found, so add it here. Make sure we connect to
- a DC in _this_ domain and not the forest root. */
-
- dn = ads_build_dn(gc->forest_name);
- BAIL_ON_PTR_ERROR(dn, nt_status);
-
- gc->search_base = talloc_strdup(gc, dn);
- SAFE_FREE(dn);
- BAIL_ON_PTR_ERROR(gc->search_base, nt_status);
-
-#if 0
- /* Can't use cell_connect_dn() here as there is no way to
- specifiy the LWCELL_FLAG_GC_CELL flag setting for cell_connect() */
-
- nt_status = cell_connect_dn(&gc->forest_cell, gc->search_base);
- BAIL_ON_NTSTATUS_ERROR(nt_status);
-#else
-
- gc->forest_cell = cell_new();
- BAIL_ON_PTR_ERROR(gc->forest_cell, nt_status);
-
- /* Set the DNS domain, dn, etc ... and add it to the list */
-
- cell_set_dns_domain(gc->forest_cell, gc->forest_name);
- cell_set_dn(gc->forest_cell, gc->search_base);
- cell_set_flags(gc->forest_cell, LWCELL_FLAG_GC_CELL);
-#endif
-
- /* It is possible to belong to a non-forest cell and a
- non-provisioned forest (at our domain levele). In that
- case, we should just inherit the flags from our primary
- cell since the GC searches will match our own schema
- model. */
-
- if (strequal(primary_cell->forest_name, gc->forest_name)
- || is_subdomain(primary_cell->dns_domain, gc->forest_name))
- {
- cell_set_flags(gc->forest_cell, cell_flags(primary_cell));
- } else {
- /* outside of our domain */
-
- nt_status = cell_connect(gc->forest_cell);
- BAIL_ON_NTSTATUS_ERROR(nt_status);
-
- nt_status = cell_lookup_settings(gc->forest_cell);
- BAIL_ON_NTSTATUS_ERROR(nt_status);
-
- /* Drop the connection now that we have the settings */
-
- ads = cell_connection(gc->forest_cell);
- ads_destroy(&ads);
- cell_set_connection(gc->forest_cell, NULL);
- }
-
- DLIST_ADD_END(_gc_server_list, gc, struct gc_info*);
-
- DEBUG(10,("gc_add_forest: Added %s to Global Catalog list of servers\n",
- gc->forest_name));
-
- nt_status = NT_STATUS_OK;
-
-done:
- if (!NT_STATUS_IS_OK(nt_status)) {
- talloc_destroy(gc);
- DEBUG(3,("LWI: Failed to add new GC connection for %s (%s)\n",
- domain, nt_errstr(nt_status)));
- }
-
- return nt_status;
-}
-
-/**********************************************************************
- *********************************************************************/
-
-static void gc_server_list_destroy(void)
-{
- struct gc_info *gc = gc_list_head();
-
- while (gc) {
- struct gc_info *p = gc->next;
-
- cell_destroy(gc->forest_cell);
- talloc_destroy(gc);
-
- gc = p;
- }
-
- _gc_server_list = NULL;
-
- return;
-}
-
-/**********************************************************************
- Setup the initial list of forests and initial the forest cell
- settings for each. FIXME!!!
- *********************************************************************/
-
- NTSTATUS gc_init_list(void)
-{
- NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
- struct winbindd_tdc_domain *domains = NULL;
- size_t num_domains = 0;
- int i;
-
- if (_gc_server_list != NULL) {
- gc_server_list_destroy();
- }
-
- if (!wcache_tdc_fetch_list(&domains, &num_domains)) {
- nt_status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
- BAIL_ON_NTSTATUS_ERROR(nt_status);
- }
-
- /* Find our forest first. Have to try all domains here starting
- with our own. gc_add_forest() filters duplicates */
-
- nt_status = gc_add_forest(lp_realm());
- WARN_ON_NTSTATUS_ERROR(nt_status);
-
- for (i=0; i<num_domains; i++) {
- uint32_t flags = (NETR_TRUST_FLAG_IN_FOREST);
-
- /* I think we should be able to break out of loop once
- we add a GC for our forest and not have to test every one.
- In fact, this entire loop is probably irrelevant since
- the GC location code should always find a GC given lp_realm().
- Will have to spend time testing before making the change.
- --jerry */
-
- if ((domains[i].trust_flags & flags) == flags) {
- nt_status = gc_add_forest(domains[i].dns_name);
- WARN_ON_NTSTATUS_ERROR(nt_status);
- /* Don't BAIL here since not every domain may
- have a GC server */
- }
- }
-
- /* Now add trusted forests. gc_add_forest() will filter out
- duplicates. Check everything with an incoming trust path
- that is not in our own forest. */
-
- for (i=0; i<num_domains; i++) {
- uint32_t flags = domains[i].trust_flags;
- uint32_t attribs = domains[i].trust_attribs;
-
- /* Skip non_AD domains */
-
- if (strlen(domains[i].dns_name) == 0) {
- continue;
- }
-
- /* Only add a GC for a forest outside of our own.
- Ignore QUARANTINED/EXTERNAL trusts */
-
- if ((flags & NETR_TRUST_FLAG_INBOUND)
- && !(flags & NETR_TRUST_FLAG_IN_FOREST)
- && (attribs & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE))
- {
- nt_status = gc_add_forest(domains[i].dns_name);
- WARN_ON_NTSTATUS_ERROR(nt_status);
- }
- }
-
- nt_status = NT_STATUS_OK;
-
-done:
- if (!NT_STATUS_IS_OK(nt_status)) {
- DEBUG(2,("LWI: Failed to initialized GC list (%s)\n",
- nt_errstr(nt_status)));
- }
-
- TALLOC_FREE(domains);
-
- return nt_status;
-}
-
-
-/**********************************************************************
- *********************************************************************/
-
- struct gc_info *gc_search_start(void)
-{
- NTSTATUS nt_status = NT_STATUS_OK;
- struct gc_info *gc = gc_list_head();
-
- if (!gc) {
- nt_status = gc_init_list();
- BAIL_ON_NTSTATUS_ERROR(nt_status);
-
- gc = gc_list_head();
- }
-
-done:
- if (!NT_STATUS_IS_OK(nt_status)) {
- DEBUG(2,("LWI: Failed to initialize GC list (%s)\n",
- nt_errstr(nt_status)));
- }
-
- return gc;
-}
-
-/**********************************************************************
- Search Global Catalog. Always search our own forest. The flags set
- controls whether or not we search cross forest. Assume that the
- resulting set is always returned from one GC so that we don't have to
- both combining the LDAPMessage * results
- *********************************************************************/
-
- NTSTATUS gc_search_forest(struct gc_info *gc,
- LDAPMessage **msg,
- const char *filter)
-{
- NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
- ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
- const char *attrs[] = {"*", NULL};
- LDAPMessage *m = NULL;
-
- if (!gc || !msg || !filter) {
- nt_status = NT_STATUS_INVALID_PARAMETER;
- BAIL_ON_NTSTATUS_ERROR(nt_status);
- }
-
- /* When you have multiple domain trees in a forest, the
- GC will search all naming contexts when you send it
- and empty ("") base search suffix. Tested against
- Windows 2003. */
-
- ads_status = cell_do_search(gc->forest_cell, "",
- LDAP_SCOPE_SUBTREE, filter, attrs, &m);
- nt_status = ads_ntstatus(ads_status);
- BAIL_ON_NTSTATUS_ERROR(nt_status);
-
- *msg = m;
-
-done:
- if (!NT_STATUS_IS_OK(nt_status)) {
- DEBUG(2,("LWI: Forest wide search %s failed (%s)\n",
- filter, nt_errstr(nt_status)));
- }
-
- return nt_status;
-}
-
-/**********************************************************************
- Search all forests via GC and return the results in an array of
- ADS_STRUCT/LDAPMessage pairs.
- *********************************************************************/
-
- NTSTATUS gc_search_all_forests(const char *filter,
- ADS_STRUCT ***ads_list,
- LDAPMessage ***msg_list,
- int *num_resp, uint32_t flags)
-{
- NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
- struct gc_info *gc = NULL;
- uint32_t test_flags = ADEX_GC_SEARCH_CHECK_UNIQUE;
-
- *ads_list = NULL;
- *msg_list = NULL;
- *num_resp = 0;
-
- if ((gc = gc_search_start()) == NULL) {
- nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
- BAIL_ON_NTSTATUS_ERROR(nt_status);
- }
-
- while (gc) {
- LDAPMessage *m = NULL;
-
- nt_status = gc_search_forest(gc, &m, filter);
- if (!NT_STATUS_IS_OK(nt_status)) {
- gc = gc->next;
- continue;
- }
-
- nt_status = add_ads_result_to_array(cell_connection(gc->forest_cell),
- m, ads_list, msg_list,
- num_resp);
- BAIL_ON_NTSTATUS_ERROR(nt_status);
-
- /* If there can only be one match, then we are done */
-
- if ((*num_resp > 0) && ((flags & test_flags) == test_flags)) {
- break;
- }
-
- gc = gc->next;
- }
-
- if (*num_resp == 0) {
- nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
- BAIL_ON_NTSTATUS_ERROR(nt_status);
- }
-
- nt_status = NT_STATUS_OK;
-
-done:
- return nt_status;
-}
-
-/**********************************************************************
- Search all forests via GC and return the results in an array of
- ADS_STRUCT/LDAPMessage pairs.
- *********************************************************************/
-
- NTSTATUS gc_search_all_forests_unique(const char *filter,
- ADS_STRUCT **ads,
- LDAPMessage **msg)
-{
- ADS_STRUCT **ads_list = NULL;
- LDAPMessage **msg_list = NULL;
- int num_resp;
- NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
-
- nt_status = gc_search_all_forests(filter, &ads_list,
- &msg_list, &num_resp,
- ADEX_GC_SEARCH_CHECK_UNIQUE);
- BAIL_ON_NTSTATUS_ERROR(nt_status);
-
- nt_status = check_result_unique(ads_list[0], msg_list[0]);
- BAIL_ON_NTSTATUS_ERROR(nt_status);
-
- *ads = ads_list[0];
- *msg = msg_list[0];
-
-done:
- /* Be care that we don't free the msg result being returned */
-
- if (!NT_STATUS_IS_OK(nt_status)) {
- free_result_array(ads_list, msg_list, num_resp);
- } else {
- talloc_destroy(ads_list);
- talloc_destroy(msg_list);
- }
-
- return nt_status;
-}
-
-/*********************************************************************
- ********************************************************************/
-
- NTSTATUS gc_name_to_sid(const char *domain,
- const char *name,
- struct dom_sid *sid,
- enum lsa_SidType *sid_type)
-{
- TALLOC_CTX *frame = talloc_stackframe();
- char *p, *name_user;
- NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
- char *name_filter;
- ADS_STRUCT *ads = NULL;
- LDAPMessage *msg = NULL;
- LDAPMessage *e = NULL;
- char *dn = NULL;
- char *dns_domain = NULL;
- ADS_STRUCT **ads_list = NULL;
- LDAPMessage **msg_list = NULL;
- int num_resp = 0;
- int i;
-
- /* Strip the "DOMAIN\" prefix if necessary and search for
- a matching sAMAccountName in the forest */
-
- if ((p = strchr_m( name, '\\' )) == NULL)
- name_user = talloc_strdup( frame, name );
- else
- name_user = talloc_strdup( frame, p+1 );
- BAIL_ON_PTR_ERROR(name_user, nt_status);
-
- name_filter = talloc_asprintf(frame, "(sAMAccountName=%s)", name_user);
- BAIL_ON_PTR_ERROR(name_filter, nt_status);
-
- nt_status = gc_search_all_forests(name_filter, &ads_list,
- &msg_list, &num_resp, 0);
- BAIL_ON_NTSTATUS_ERROR(nt_status);
-
- /* Assume failure until we know otherwise*/
-
- nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
-
- /* Match the domain name from the DN */
-
- for (i=0; i<num_resp; i++) {
- ads = ads_list[i];
- msg = msg_list[i];
-
- e = ads_first_entry(ads, msg);
- while (e) {
- struct winbindd_tdc_domain *domain_rec;
-
- dn = ads_get_dn(ads, frame, e);
- BAIL_ON_PTR_ERROR(dn, nt_status);
-
- dns_domain = cell_dn_to_dns(dn);
- TALLOC_FREE(dn);
- BAIL_ON_PTR_ERROR(dns_domain, nt_status);
-
- domain_rec = wcache_tdc_fetch_domain(frame, dns_domain);
- SAFE_FREE(dns_domain);
-
- /* Ignore failures and continue the search */
-
- if (!domain_rec) {
- e = ads_next_entry(ads, e);
- continue;
- }
-
- /* Check for a match on the domain name */
-
- if (strequal(domain, domain_rec->domain_name)) {
- if (!ads_pull_sid(ads, e, "objectSid", sid)) {
- nt_status = NT_STATUS_INVALID_SID;
- BAIL_ON_NTSTATUS_ERROR(nt_status);
- }
-
- talloc_destroy(domain_rec);
-
- nt_status = get_sid_type(ads, msg, sid_type);
- BAIL_ON_NTSTATUS_ERROR(nt_status);
-
- /* We're done! */
- nt_status = NT_STATUS_OK;
- break;
- }
-
- /* once more around thew merry-go-round */
-
- talloc_destroy(domain_rec);
- e = ads_next_entry(ads, e);
- }
- }
-
-done:
- free_result_array(ads_list, msg_list, num_resp);
- talloc_destroy(frame);
-
- return nt_status;
-}
-
-/********************************************************************
- Pull an attribute string value
- *******************************************************************/
-
-static NTSTATUS get_object_account_name(ADS_STRUCT *ads,
- LDAPMessage *msg,
- char **name)
-{
- NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
- char *sam_name = NULL;
- struct winbindd_tdc_domain *domain_rec = NULL;
- char *dns_domain = NULL;
- char *dn = NULL;
- TALLOC_CTX *frame = talloc_stackframe();
- int len;
-
- /* Check parameters */
-
- if (!ads || !msg || !name) {
- nt_status = NT_STATUS_INVALID_PARAMETER;
- BAIL_ON_NTSTATUS_ERROR(nt_status);
- }
-
- /* get the name and domain */
-
- dn = ads_get_dn(ads, frame, msg);
- BAIL_ON_PTR_ERROR(dn, nt_status);
-
- DEBUG(10,("get_object_account_name: dn = \"%s\"\n", dn));
-
- dns_domain = cell_dn_to_dns(dn);
- TALLOC_FREE(dn);
- BAIL_ON_PTR_ERROR(dns_domain, nt_status);
-
- domain_rec = wcache_tdc_fetch_domain(frame, dns_domain);
- SAFE_FREE(dns_domain);
-
- if (!domain_rec) {
- nt_status = NT_STATUS_TRUSTED_DOMAIN_FAILURE;
- BAIL_ON_NTSTATUS_ERROR(nt_status);
- }
-
- sam_name = ads_pull_string(ads, frame, msg, "sAMAccountName");
- BAIL_ON_PTR_ERROR(sam_name, nt_status);
-
- len = asprintf(name, "%s\\%s", domain_rec->domain_name, sam_name);
- if (len == -1) {
- *name = NULL;
- BAIL_ON_PTR_ERROR((*name), nt_status);
- }
-
- nt_status = NT_STATUS_OK;
-
-done:
- talloc_destroy(frame);
-
- return nt_status;
-}
-
-/*********************************************************************
- ********************************************************************/
-
- NTSTATUS gc_sid_to_name(const struct dom_sid *sid,
- char **name,
- enum lsa_SidType *sid_type)
-{
- TALLOC_CTX *frame = talloc_stackframe();
- NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
- char *filter;
- ADS_STRUCT *ads = NULL;
- LDAPMessage *msg = NULL;
- char *sid_string;
-
- *name = NULL;
-
- sid_string = ldap_encode_ndr_dom_sid(frame, sid);
- BAIL_ON_PTR_ERROR(sid_string, nt_status);
-
- filter = talloc_asprintf(frame, "(objectSid=%s)", sid_string);
- TALLOC_FREE(sid_string);
- BAIL_ON_PTR_ERROR(filter, nt_status);
-
- nt_status = gc_search_all_forests_unique(filter, &ads, &msg);
- BAIL_ON_NTSTATUS_ERROR(nt_status);
-
- nt_status = get_object_account_name(ads, msg, name);
- BAIL_ON_NTSTATUS_ERROR(nt_status);
-
- nt_status = get_sid_type(ads, msg, sid_type);
- BAIL_ON_NTSTATUS_ERROR(nt_status);
-
-done:
- ads_msgfree(ads, msg);
- talloc_destroy(frame);
-
- return nt_status;
-}
-
-/**********************************************************************
- *********************************************************************/
-
- NTSTATUS add_ads_result_to_array(ADS_STRUCT *ads,
- LDAPMessage *msg,
- ADS_STRUCT ***ads_list,
- LDAPMessage ***msg_list,
- int *size)
-{
- NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
- ADS_STRUCT **ads_tmp = NULL;
- LDAPMessage **msg_tmp = NULL;
- int count = *size;
-
- if (!ads || !msg) {
- nt_status = NT_STATUS_INVALID_PARAMETER;
- BAIL_ON_NTSTATUS_ERROR(nt_status);
- }
-
-#if 0
- /* Don't add a response with no entries */
-
- if (ads_count_replies(ads, msg) == 0) {
- return NT_STATUS_OK;
- }
-#endif
-
- if (count == 0) {
- ads_tmp = talloc_array(NULL, ADS_STRUCT*, 1);
- BAIL_ON_PTR_ERROR(ads_tmp, nt_status);
-
- msg_tmp = talloc_array(NULL, LDAPMessage*, 1);
- BAIL_ON_PTR_ERROR(msg_tmp, nt_status);
- } else {
- ads_tmp = talloc_realloc(*ads_list, *ads_list, ADS_STRUCT*,
- count+1);
- BAIL_ON_PTR_ERROR(ads_tmp, nt_status);
-
- msg_tmp = talloc_realloc(*msg_list, *msg_list, LDAPMessage*,
- count+1);
- BAIL_ON_PTR_ERROR(msg_tmp, nt_status);
- }
-
- ads_tmp[count] = ads;
- msg_tmp[count] = msg;
- count++;
-
- *ads_list = ads_tmp;
- *msg_list = msg_tmp;
- *size = count;
-
- nt_status = NT_STATUS_OK;
-
-done:
- if (!NT_STATUS_IS_OK(nt_status)) {
- talloc_destroy(ads_tmp);
- talloc_destroy(msg_tmp);
- }
-
- return nt_status;
-}
-
-/**********************************************************************
- Frees search results. Do not free the ads_list as these are
- references back to the GC search structures.
- *********************************************************************/
-
- void free_result_array(ADS_STRUCT **ads_list,
- LDAPMessage **msg_list,
- int num_resp)
-{
- int i;
-
- for (i=0; i<num_resp; i++) {
- ads_msgfree(ads_list[i], msg_list[i]);
- }
-
- talloc_destroy(ads_list);
- talloc_destroy(msg_list);
-}
-
-/**********************************************************************
- Check that we have exactly one entry from the search
- *********************************************************************/
-
- NTSTATUS check_result_unique(ADS_STRUCT *ads, LDAPMessage *msg)
-{
- NTSTATUS nt_status;
- int count;
-
- count = ads_count_replies(ads, msg);
-
- if (count <= 0) {
- nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
- BAIL_ON_NTSTATUS_ERROR(nt_status);
- }
-
- if (count > 1) {
- nt_status = NT_STATUS_DUPLICATE_NAME;
- BAIL_ON_NTSTATUS_ERROR(nt_status);
- }
-
- nt_status = NT_STATUS_OK;
-
-done:
- return nt_status;
-}