[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Wed Feb 24 14:17:50 MST 2010


The branch, master has been updated
       via  fc4c839... s4:DNS update - change "i" to be unsigned
       via  ec536a0... s4:ldap_server - make it "signed-safe"
       via  e912d50... s4:auth - make some parts "signed-safe"
       via  f10fc7c... s4:cldap_server - make it "signed-safe"
       via  68caf90... s4:torture/ldap/basic.c - add a basic test for referral return
       via  0be57c7... s4:partition DSDB module - Generate basic referrals
       via  cd5b542... s4:partition DSDB module - change the search and domain scope control handling
       via  545889a... s4:LDAP server - Enable support for returning referrals through it
       via  0efa8f4... s4:SAMLDB module - ignore referrals
      from  f09802c... s4:netlogon remove wrong ZERO_STRUCT of output

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit fc4c839bc839faadefc3283d2c2bdfc6d5279c9b
Author: Matthias Dieter Wallnöfer <mwallnoefer at yahoo.de>
Date:   Thu Feb 11 11:49:26 2010 +0100

    s4:DNS update - change "i" to be unsigned
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>

commit ec536a0121a752b9211ba258ed015a821b8391ba
Author: Matthias Dieter Wallnöfer <mwallnoefer at yahoo.de>
Date:   Sat Nov 7 21:21:26 2009 +0100

    s4:ldap_server - make it "signed-safe"
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>

commit e912d507093b7c22130158ef0bf2c0c4ffc78bac
Author: Matthias Dieter Wallnöfer <mwallnoefer at yahoo.de>
Date:   Sat Nov 7 21:20:12 2009 +0100

    s4:auth - make some parts "signed-safe"
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>

commit f10fc7c16e3c71603e34c58fc0329f6d01d89603
Author: Matthias Dieter Wallnöfer <mwallnoefer at yahoo.de>
Date:   Sat Nov 7 21:20:56 2009 +0100

    s4:cldap_server - make it "signed-safe"
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>

commit 68caf9060621b8c0da183c38a9288a2c0a53b087
Author: Matthias Dieter Wallnöfer <mwallnoefer at yahoo.de>
Date:   Sun Feb 21 20:36:34 2010 +0100

    s4:torture/ldap/basic.c - add a basic test for referral return
    
    I implemented this referral test in C since the LDB python API isn't capable
    to extract referrals from search result sets (there the result sets are simple
    lists which contain only the matching entries).
    
    First I enhanced the RootDSE test to return all partition base DNs in a new
    null-terminated list "partitions". Then I used this in my referrals test which
    I've implemented in the LDB api since I needed some certain DN functions.

commit 0be57c747825737fa9d64411223e693b055b5f8f
Author: Matthias Dieter Wallnöfer <mwallnoefer at yahoo.de>
Date:   Sat Feb 20 22:07:12 2010 +0100

    s4:partition DSDB module - Generate basic referrals
    
    This is a first, very basic implementation of the referrals (more informations
    at MS-ADTS 3.1.1.4.6 and 3.1.1.3.4.1.12).
    
    To have the full referral support (and to always point to the right host) the
    full implementation using DNS will be needed (at the moment we always point to
    the main DC which is referenceable through the DNS domainname).
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>

commit cd5b5428781128b11de6bb3270828cc83a45cc03
Author: Matthias Dieter Wallnöfer <mwallnoefer at yahoo.de>
Date:   Mon Feb 22 11:19:10 2010 +0100

    s4:partition DSDB module - change the search and domain scope control handling
    
    The domain scope control is always removed, from the search one only the two
    interesting flags (which are handled) and it is marked as non-critical.
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>

commit 545889a048da0bc58c4a4db4500839ab050518fa
Author: Matthias Dieter Wallnöfer <mwallnoefer at yahoo.de>
Date:   Sun Feb 21 11:56:12 2010 +0100

    s4:LDAP server - Enable support for returning referrals through it
    
    This is needed for my work regarding the referrals when the domain scope control
    isn't specified.
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>

commit 0efa8f4fbb3206512c69d74024c7a937ee035285
Author: Matthias Dieter Wallnöfer <mwallnoefer at yahoo.de>
Date:   Tue Feb 23 17:59:55 2010 +0100

    s4:SAMLDB module - ignore referrals
    
    They don't cause any harm to our functionality - so ignore them were not needed.
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 source4/auth/sam.c                         |    7 +-
 source4/auth/system_session.c              |    8 +-
 source4/cldap_server/cldap_server.c        |    2 +-
 source4/cldap_server/netlogon.c            |    2 +-
 source4/dsdb/dns/dns_update.c              |    3 +-
 source4/dsdb/samdb/ldb_modules/partition.c |  237 +++++++++++++++++++---------
 source4/dsdb/samdb/ldb_modules/partition.h |    1 +
 source4/dsdb/samdb/ldb_modules/samldb.c    |   11 +-
 source4/ldap_server/ldap_backend.c         |   32 +++-
 source4/ldap_server/ldap_extended.c        |    2 +-
 source4/ldap_server/ldap_server.c          |    3 +-
 source4/torture/ldap/basic.c               |  222 +++++++++++++++++++++++++-
 12 files changed, 428 insertions(+), 102 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/auth/sam.c b/source4/auth/sam.c
index 7d2f249..3ded739 100644
--- a/source4/auth/sam.c
+++ b/source4/auth/sam.c
@@ -299,10 +299,11 @@ static bool sids_contains_sid(const struct dom_sid **sids, const int num_sids,
 static NTSTATUS authsam_expand_nested_groups(struct ldb_context *sam_ctx,
 	const struct dom_sid *sid, const bool only_childs,
 	TALLOC_CTX *res_sids_ctx, struct dom_sid ***res_sids,
-	int *num_res_sids)
+	unsigned int *num_res_sids)
 {
 	const char * const attrs[] = { "memberOf", NULL };
-	int i, ret;
+	unsigned int i;
+	int ret;
 	bool already_there;
 	struct ldb_dn *tmp_dn;
 	struct dom_sid *tmp_sid;
@@ -390,7 +391,7 @@ _PUBLIC_ NTSTATUS authsam_make_server_info(TALLOC_CTX *mem_ctx,
 	struct dom_sid *primary_group_sid;
 	/* SID structures for the expanded group memberships */
 	struct dom_sid **groupSIDs = NULL, **groupSIDs_2 = NULL;
-	int num_groupSIDs = 0, num_groupSIDs_2 = 0, i;
+	unsigned int num_groupSIDs = 0, num_groupSIDs_2 = 0, i;
 	uint32_t userAccountControl;
 
 	server_info = talloc(mem_ctx, struct auth_serversupplied_info);
diff --git a/source4/auth/system_session.c b/source4/auth/system_session.c
index 765f53a..a1b0460 100644
--- a/source4/auth/system_session.c
+++ b/source4/auth/system_session.c
@@ -38,13 +38,13 @@
 static NTSTATUS create_token(TALLOC_CTX *mem_ctx, 
 			       struct dom_sid *user_sid,
 			       struct dom_sid *group_sid, 
-			       int n_groupSIDs,
+			       unsigned int n_groupSIDs,
 			       struct dom_sid **groupSIDs, 
 			       bool is_authenticated,
 			       struct security_token **token)
 {
 	struct security_token *ptoken;
-	int i;
+	unsigned int i;
 
 	ptoken = security_token_initialise(mem_ctx);
 	NT_STATUS_HAVE_NO_MEMORY(ptoken);
@@ -325,12 +325,12 @@ NTSTATUS auth_system_server_info(TALLOC_CTX *mem_ctx, const char *netbios_name,
 static NTSTATUS create_admin_token(TALLOC_CTX *mem_ctx,
 				   struct dom_sid *user_sid,
 				   struct dom_sid *group_sid,
-				   int n_groupSIDs,
+				   unsigned int n_groupSIDs,
 				   struct dom_sid **groupSIDs,
 				   struct security_token **token)
 {
 	struct security_token *ptoken;
-	int i;
+	unsigned int i;
 
 	ptoken = security_token_initialise(mem_ctx);
 	NT_STATUS_HAVE_NO_MEMORY(ptoken);
diff --git a/source4/cldap_server/cldap_server.c b/source4/cldap_server/cldap_server.c
index 25c5c9a..da59e0c 100644
--- a/source4/cldap_server/cldap_server.c
+++ b/source4/cldap_server/cldap_server.c
@@ -151,7 +151,7 @@ static NTSTATUS cldapd_startup_interfaces(struct cldapd_server *cldapd, struct l
 	int num_interfaces;
 	TALLOC_CTX *tmp_ctx = talloc_new(cldapd);
 	NTSTATUS status;
-	int i;
+	unsigned int i;
 
 	num_interfaces = iface_count(ifaces);
 
diff --git a/source4/cldap_server/netlogon.c b/source4/cldap_server/netlogon.c
index 7072953..e6a4ab3 100644
--- a/source4/cldap_server/netlogon.c
+++ b/source4/cldap_server/netlogon.c
@@ -340,7 +340,7 @@ void cldapd_netlogon_request(struct cldap_socket *cldap,
 			     struct ldb_parse_tree *tree,
 			     struct tsocket_address *src)
 {
-	int i;
+	unsigned int i;
 	const char *domain = NULL;
 	const char *host = NULL;
 	const char *user = NULL;
diff --git a/source4/dsdb/dns/dns_update.c b/source4/dsdb/dns/dns_update.c
index 0f5de36..82cb715 100644
--- a/source4/dsdb/dns/dns_update.c
+++ b/source4/dsdb/dns/dns_update.c
@@ -85,7 +85,8 @@ static void dnsupdate_rebuild(struct dnsupdate_service *service)
 	int ret;
 	struct ldb_result *res;
 	const char *tmp_path, *path;
-	int fd, i;
+	int fd;
+	unsigned int i;
 	const char *attrs[] = { "sAMAccountName", NULL };
 	const char *realm = lp_realm(service->task->lp_ctx);
 	TALLOC_CTX *tmp_ctx = talloc_new(service);
diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c
index 9bd4578..9d59b54 100644
--- a/source4/dsdb/samdb/ldb_modules/partition.c
+++ b/source4/dsdb/samdb/ldb_modules/partition.c
@@ -43,6 +43,8 @@ struct partition_context {
 	struct part_request *part_req;
 	int num_requests;
 	int finished_requests;
+
+	const char **referrals;
 };
 
 static struct partition_context *partition_init_ctx(struct ldb_module *module, struct ldb_request *req)
@@ -197,6 +199,19 @@ static int partition_req_callback(struct ldb_request *req,
 
 		ac->finished_requests++;
 		if (ac->finished_requests == ac->num_requests) {
+			/* Send back referrals if they do exist (search ops) */
+			if (ac->referrals != NULL) {
+				const char **ref;
+				for (ref = ac->referrals; *ref != NULL; ++ref) {
+					ret = ldb_module_send_referral(ac->req,
+								       talloc_strdup(ac->req, *ref));
+					if (ret != LDB_SUCCESS) {
+						return ldb_module_done(ac->req, NULL, NULL,
+								       ret);
+					}
+				}
+			}
+
 			/* this was the last one, call callback */
 			return ldb_module_done(ac->req, ares->controls,
 					       ares->response, 
@@ -434,22 +449,22 @@ static int partition_replicate(struct ldb_module *module, struct ldb_request *re
 /* search */
 static int partition_search(struct ldb_module *module, struct ldb_request *req)
 {
-	int ret;
 	struct ldb_control **saved_controls;
 	/* Find backend */
 	struct partition_private_data *data = talloc_get_type(module->private_data, 
 							      struct partition_private_data);
-
-	/* issue request */
-
-	/* (later) consider if we should be searching multiple
-	 * partitions (for 'invisible' partition behaviour */
+	struct partition_context *ac;
+	struct ldb_context *ldb;
+	struct loadparm_context *lp_ctx;
 
 	struct ldb_control *search_control = ldb_request_get_control(req, LDB_CONTROL_SEARCH_OPTIONS_OID);
 	struct ldb_control *domain_scope_control = ldb_request_get_control(req, LDB_CONTROL_DOMAIN_SCOPE_OID);
 	
 	struct ldb_search_options_control *search_options = NULL;
 	struct dsdb_partition *p;
+	unsigned int i, j;
+	int ret;
+	bool domain_scope = false, phantom_root = false;
 	
 	ret = partition_reload_if_required(module, data);
 	if (ret != LDB_SUCCESS) {
@@ -464,111 +479,179 @@ static int partition_search(struct ldb_module *module, struct ldb_request *req)
 		return ldb_next_request(p->module, req);		
 	}
 
-
+	/* Get back the search options from the search control, and mark it as
+	 * non-critical (to make backends and also dcpromo happy).
+	 */
 	if (search_control) {
 		search_options = talloc_get_type(search_control->data, struct ldb_search_options_control);
+		search_control->critical = 0;
+
 	}
 
-	/* Remove the domain_scope control, so we don't confuse a backend server */
+	/* Remove the "domain_scope" control, so we don't confuse a backend
+	 * server */
 	if (domain_scope_control && !save_controls(domain_scope_control, req, &saved_controls)) {
 		ldb_oom(ldb_module_get_ctx(module));
 		return LDB_ERR_OPERATIONS_ERROR;
 	}
 
-	/*
-	 * for now pass down the LDB_CONTROL_SEARCH_OPTIONS_OID control
-	 * down as uncritical to make windows 2008 dcpromo happy.
-	 */
-	if (search_control) {
-		search_control->critical = 0;
+	/* Locate the options */
+	domain_scope = (search_options
+		&& (search_options->search_options & LDB_SEARCH_OPTION_DOMAIN_SCOPE))
+		|| domain_scope_control;
+	phantom_root = search_options
+		&& (search_options->search_options & LDB_SEARCH_OPTION_PHANTOM_ROOT);
+
+	/* Remove handled options from the search control flag */
+	if (search_options) {
+		search_options->search_options = search_options->search_options
+			& ~LDB_SEARCH_OPTION_DOMAIN_SCOPE
+			& ~LDB_SEARCH_OPTION_PHANTOM_ROOT;
 	}
 
-	/* TODO:
-	 * Generate referrals (look for a partition under this DN) if we don't
-	 * have the LDB_CONTROL_DOMAIN_SCOPE_OID control specified.
-	 */
-	
-	if (search_options && (search_options->search_options & LDB_SEARCH_OPTION_PHANTOM_ROOT)) {
-		int i;
-		struct partition_context *ac;
+	if (!data || !data->partitions) {
+		return ldb_next_request(module, req);
+	}
 
-		if ((search_options->search_options & ~LDB_SEARCH_OPTION_PHANTOM_ROOT) == 0) {
-			/* We have processed this flag, so we are done with this control now */
+	ac = partition_init_ctx(module, req);
+	if (!ac) {
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
 
-			/* Remove search control, so we don't confuse a backend server */
-			if (search_control && !save_controls(search_control, req, &saved_controls)) {
-				ldb_oom(ldb_module_get_ctx(module));
-				return LDB_ERR_OPERATIONS_ERROR;
-			}
-		}
+	ldb = ldb_module_get_ctx(ac->module);
+	lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
+						struct loadparm_context);
 
-		ac = partition_init_ctx(module, req);
-		if (!ac) {
-			return LDB_ERR_OPERATIONS_ERROR;
-		}
+	/* Search from the base DN */
+	if (ldb_dn_is_null(req->op.search.base)) {
+		return partition_send_all(module, ac, req);
+	}
 
-		/* Search from the base DN */
-		if (!req->op.search.base || ldb_dn_is_null(req->op.search.base)) {
-			return partition_send_all(module, ac, req);
-		}
-		for (i=0; data && data->partitions && data->partitions[i]; i++) {
-			bool match = false, stop = false;
-			/* Find all partitions under the search base 
-			   
-			   we match if:
-
-			      1) the DN we are looking for exactly matches the partition
-		             or
-			      2) the DN we are looking for is a parent of the partition and it isn't
-                                 a scope base search
-                             or
-			      3) the DN we are looking for is a child of the partition
+	for (i=0; data->partitions[i]; i++) {
+		bool match = false, stop = false;
+
+		if (phantom_root) {
+			/* Phantom root: Find all partitions under the
+			 * search base. We match if:
+			 *
+			 * 1) the DN we are looking for exactly matches a
+			 *    certain partition and always stop
+			 * 2) the DN we are looking for is a parent of certain
+			 *    partitions and it isn't a scope base search
+			 * 3) the DN we are looking for is a child of a certain
+			 *    partition and always stop
+			 *    - we don't need to go any further up in the
+			 *    hierarchy!
 			 */
-			if (ldb_dn_compare(data->partitions[i]->ctrl->dn, req->op.search.base) == 0) {
+			if (ldb_dn_compare(data->partitions[i]->ctrl->dn,
+					   req->op.search.base) == 0) {
 				match = true;
 				stop = true;
 			}
-			if (!match && 
-			    (ldb_dn_compare_base(req->op.search.base, data->partitions[i]->ctrl->dn) == 0 &&
+			if (!match &&
+			    (ldb_dn_compare_base(req->op.search.base,
+						 data->partitions[i]->ctrl->dn) == 0 &&
 			     req->op.search.scope != LDB_SCOPE_BASE)) {
 				match = true;
 			}
 			if (!match &&
-			    ldb_dn_compare_base(data->partitions[i]->ctrl->dn, req->op.search.base) == 0) {
+			    ldb_dn_compare_base(data->partitions[i]->ctrl->dn,
+						req->op.search.base) == 0) {
 				match = true;
 				stop = true; /* note that this relies on partition ordering */
 			}
-			if (match) {
-				ret = partition_prep_request(ac, data->partitions[i]);
-				if (ret != LDB_SUCCESS) {
-					return ret;
+		} else {
+			/* Domain scope: Find all partitions under the search
+			 * base.
+			 *
+			 * We generate referral candidates if we haven't
+			 * specified the domain scope control, haven't a base
+			 * search* scope and the DN we are looking for is a real
+			 * predecessor of certain partitions. When a new
+			 * referral candidate is nearer to the DN than an
+			 * existing one delete the latter (we want to have only
+			 * the closest ones). When we checked this for all
+			 * candidates we have the final referrals.
+			 *
+			 * We match if the DN we are looking for is a child of
+			 * a certain partition or the partition
+			 * DN itself - we don't need to go any further
+			 * up in the hierarchy!
+			 */
+			if ((!domain_scope) &&
+			    (req->op.search.scope != LDB_SCOPE_BASE) &&
+			    (ldb_dn_compare_base(req->op.search.base,
+						 data->partitions[i]->ctrl->dn) == 0) &&
+			    (ldb_dn_compare(req->op.search.base,
+					    data->partitions[i]->ctrl->dn) != 0)) {
+				char *ref = talloc_asprintf(ac,
+							    "ldap://%s/%s%s",
+							    lp_dnsdomain(lp_ctx),
+							    ldb_dn_get_linearized(data->partitions[i]->ctrl->dn),
+							    req->op.search.scope == LDB_SCOPE_ONELEVEL ? "??base" : "");
+
+				if (ref == NULL) {
+					ldb_oom(ldb);
+					return LDB_ERR_OPERATIONS_ERROR;
 				}
-			}
-			if (stop) break;
-		}
 
-		/* Perhaps we didn't match any partitions.  Try the main partition, only */
-		if (ac->num_requests == 0) {
-			talloc_free(ac);
-			return ldb_next_request(module, req);
-		}
+				/* Initialise the referrals list */
+				if (ac->referrals == NULL) {
+					ac->referrals = (const char **) str_list_make_empty(ac);
+					if (ac->referrals == NULL) {
+						ldb_oom(ldb);
+						return LDB_ERR_OPERATIONS_ERROR;
+					}
+				}
 
-		/* fire the first one */
-		return partition_call_first(ac);
-	} else {
-		/* Handle this like all other requests */
-		if (search_control && (search_options->search_options & ~LDB_SEARCH_OPTION_PHANTOM_ROOT) == 0) {
-			/* We have processed this flag, so we are done with this control now */
+				/* Check if the new referral candidate is
+				 * closer to the base DN than already
+				 * saved ones and delete the latters */
+				j = 0;
+				while (ac->referrals[j] != NULL) {
+					if (strstr(ac->referrals[j],
+						   ldb_dn_get_linearized(data->partitions[i]->ctrl->dn)) != NULL) {
+						str_list_remove(ac->referrals,
+								ac->referrals[j]);
+					} else {
+						++j;
+					}
+				}
 
-			/* Remove search control, so we don't confuse a backend server */
-			if (search_control && !save_controls(search_control, req, &saved_controls)) {
-				ldb_oom(ldb_module_get_ctx(module));
-				return LDB_ERR_OPERATIONS_ERROR;
+				/* Add our new candidate */
+				ac->referrals = str_list_add(ac->referrals, ref);
+
+				talloc_free(ref);
+
+				if (ac->referrals == NULL) {
+					ldb_oom(ldb);
+					return LDB_ERR_OPERATIONS_ERROR;
+				}
+			}
+			if (ldb_dn_compare_base(data->partitions[i]->ctrl->dn, req->op.search.base) == 0) {
+				match = true;
+				stop = true; /* note that this relies on partition ordering */
+			}
+		}
+
+		if (match) {
+			ret = partition_prep_request(ac, data->partitions[i]);
+			if (ret != LDB_SUCCESS) {
+				return ret;
 			}
 		}
 
-		return partition_replicate(module, req, req->op.search.base);
+		if (stop) break;
+	}
+
+	/* Perhaps we didn't match any partitions. Try the main partition */
+	if (ac->num_requests == 0) {
+		talloc_free(ac);
+		return ldb_next_request(module, req);
 	}
+
+	/* fire the first one */
+	return partition_call_first(ac);
 }
 
 /* add */
diff --git a/source4/dsdb/samdb/ldb_modules/partition.h b/source4/dsdb/samdb/ldb_modules/partition.h
index 1d4e8e4..594634c 100644
--- a/source4/dsdb/samdb/ldb_modules/partition.h
+++ b/source4/dsdb/samdb/ldb_modules/partition.h
@@ -25,6 +25,7 @@
 #include "dsdb/samdb/samdb.h"
 #include "dsdb/samdb/ldb_modules/util.h"
 #include "system/locale.h"
+#include "param/param.h"
 
 struct dsdb_partition {
 	struct ldb_module *module;
diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c
index 6420e05..24d1450 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -210,9 +210,10 @@ static int samldb_check_samAccountName_callback(struct ldb_request *req,
                                        LDB_ERR_ENTRY_ALREADY_EXISTS);
 
 	case LDB_REPLY_REFERRAL:
-		/* this should not happen */
-		return ldb_module_done(ac->req, NULL, NULL,
-                                       LDB_ERR_OPERATIONS_ERROR);
+		/* ignore */
+		talloc_free(ares);
+		ret = LDB_SUCCESS;
+		break;
 
 	case LDB_REPLY_DONE:
 		/* not found, go on */
@@ -610,9 +611,9 @@ static int samldb_find_for_defaultObjectCategory_callback(struct ldb_request *re
 		break;
 
 	case LDB_REPLY_REFERRAL:
-		/* this should not happen */
+		/* ignore */
 		talloc_free(ares);
-		ret = LDB_ERR_OPERATIONS_ERROR;
+		ret = LDB_SUCCESS;
 		break;
 
 	case LDB_REPLY_DONE:
diff --git a/source4/ldap_server/ldap_backend.c b/source4/ldap_server/ldap_backend.c
index 689fd31..3e802a7 100644
--- a/source4/ldap_server/ldap_backend.c
+++ b/source4/ldap_server/ldap_backend.c
@@ -237,7 +237,7 @@ NTSTATUS ldapsrv_backend_Init(struct ldapsrv_connection *conn)
 		struct gensec_security_ops **backends = gensec_security_all();
 		struct gensec_security_ops **ops
 			= gensec_use_kerberos_mechs(conn, backends, conn->server_credentials);
-		int i, j = 0;
+		unsigned int i, j = 0;
 		for (i = 0; ops && ops[i]; i++) {
 			if (!lp_parm_bool(conn->lp_ctx,  NULL, "gensec", ops[i]->name, ops[i]->enabled))
 				continue;
@@ -336,7 +336,7 @@ static NTSTATUS ldapsrv_SearchRequest(struct ldapsrv_call *call)
 	int success_limit = 1;
 	int result = -1;
 	int ldb_ret = -1;
-	int i, j;
+	unsigned int i, j;
 	int extended_type = 1;
 
 	DEBUG(10, ("SearchRequest"));
@@ -475,6 +475,28 @@ static NTSTATUS ldapsrv_SearchRequest(struct ldapsrv_call *call)
 queue_reply:
 			ldapsrv_queue_reply(call, ent_r);
 		}
+
+		/* Send back referrals if they do exist (search operations) */
+		if (res->refs != NULL) {
+			char **ref;
+			struct ldap_SearchResRef *ent_ref;
+
+			for (ref = res->refs; *ref != NULL; ++ref) {
+				ent_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultReference);
+				NT_STATUS_HAVE_NO_MEMORY(ent_r);
+
+				/* Better to have the whole referrals kept here,
+				 * than to find someone further up didn't put
+				 * a value in the right spot in the talloc tree
+				 */
+				talloc_steal(ent_r, *ref);
+
+				ent_ref = &ent_r->msg->r.SearchResultReference;


-- 
Samba Shared Repository


More information about the samba-cvs mailing list