[PATCHES] idmap_rfc2307 with test

Christof Schmitt christof.schmitt at us.ibm.com
Mon Mar 4 15:09:41 MST 2013


On Sat, Mar 02, 2013 at 11:35:04AM +1100, Andrew Bartlett wrote:
> On Sat, 2013-03-02 at 10:29 +1100, Andrew Bartlett wrote:
> > Some more challenges:
> > 
> > called with: SAMBADOMAIN Administrator 2000000 Domain Users 2000001
> > ou=idmap,dc=samba,dc=example,dc=com
> > UNEXPECTED(failure): idmap.rfc2307.add ldap prefix(s3member_rfc2307)
> > REASON: _StringException: _StringException: ltdb: tdb(./st/dc/private/sam.ldb): tdb_open_ex: could not open file ./st/dc/private/sam.ldb: No such file or directory
> > 
> > Unable to open tdb './st/dc/private/sam.ldb'
> > Failed to connect to './st/dc/private/sam.ldb' with backend 'tdb': Unable to open tdb './st/dc/private/sam.ldb'
> > Failed to connect to ./st/dc/private/sam.ldb - Unable to open tdb './st/dc/private/sam.ldb'
> > 
> > The tests fail autobuild (you can run an autobuild locally
> > with ./script/autobuild.py), because you assume ./st. 
> > 
> > 
> > We want the ability to change that in the future, so you need to use
> > things like the PREFIX variable to find the files, or connect to the DB
> > over LDAP (this we prefer because it makes it easier to run the same
> > test against a real windows DC).  (The path in autobuild is ./bin/ab to
> > trip up this kind of mistake).
> > 
> > Can you fix that up for me, and re-submit?
> 
> Also please delete the objects added once the test is over, and delete
> them before the test starts.  This will allow the test to be run
> multiple times in 'make testenv' without difficulty, when debugging
> issues.

Thanks for pointing out those issues. Here is the updated patch
series. I removed the LD_LIBRARY_PATH patch, since it is not needed.
The testcase now connects to the LDAP server instead of accessing the
local file, and it deletes the records before and after the test.

Regards,

-- 
Christof Schmitt || IBM || SONAS System Development || Tucson, AZ
christof.schmitt at us.ibm.com  ||  +1-520-799-2469  (T/L: 321-2469)
-------------- next part --------------
>From 4b943df2293529682db5f4584633dc7fcaaac809 Mon Sep 17 00:00:00 2001
From: Christof Schmitt <christof.schmitt at us.ibm.com>
Date: Thu, 21 Feb 2013 12:30:48 -0700
Subject: [PATCH 01/10] s3-winbindd: Move common code for LDAP id mapping to idmap_utils

idmap_ad and idmap_ldap use the same helper functions and the same
maximum query size. Move the code to idmap_utils so that it can be
shared by every module issuing LDAP queries.
---
 source3/winbindd/idmap_ad.c    |   43 +++---------------------------------
 source3/winbindd/idmap_ldap.c  |   46 +--------------------------------------
 source3/winbindd/idmap_proto.h |    6 +++++
 source3/winbindd/idmap_util.c  |   41 +++++++++++++++++++++++++++++++++++
 4 files changed, 53 insertions(+), 83 deletions(-)

diff --git a/source3/winbindd/idmap_ad.c b/source3/winbindd/idmap_ad.c
index bfe7d4b..d6f31ba 100644
--- a/source3/winbindd/idmap_ad.c
+++ b/source3/winbindd/idmap_ad.c
@@ -41,7 +41,6 @@
 
 #define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
 
-#define IDMAP_AD_MAX_IDS 30
 #define CHECK_ALLOC_DONE(mem) do { \
      if (!mem) { \
            DEBUG(0, ("Out of memory!\n")); \
@@ -250,40 +249,6 @@ static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom)
 }
 
 /************************************************************************
- Search up to IDMAP_AD_MAX_IDS entries in maps for a match.
- ***********************************************************************/
-
-static struct id_map *find_map_by_id(struct id_map **maps, enum id_type type, uint32_t id)
-{
-	int i;
-
-	for (i = 0; maps[i] && i<IDMAP_AD_MAX_IDS; i++) {
-		if ((maps[i]->xid.type == type) && (maps[i]->xid.id == id)) {
-			return maps[i];
-		}
-	}
-
-	return NULL;	
-}
-
-/************************************************************************
- Search up to IDMAP_AD_MAX_IDS entries in maps for a match
- ***********************************************************************/
-
-static struct id_map *find_map_by_sid(struct id_map **maps, struct dom_sid *sid)
-{
-	int i;
-
-	for (i = 0; maps[i] && i<IDMAP_AD_MAX_IDS; i++) {
-		if (dom_sid_equal(maps[i]->sid, sid)) {
-			return maps[i];
-		}
-	}
-
-	return NULL;	
-}
-
-/************************************************************************
  ***********************************************************************/
 
 static NTSTATUS idmap_ad_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids)
@@ -337,7 +302,7 @@ static NTSTATUS idmap_ad_unixids_to_sids(struct idmap_domain *dom, struct id_map
 
 again:
 	bidx = idx;
-	for (i = 0; (i < IDMAP_AD_MAX_IDS) && ids[idx]; i++, idx++) {
+	for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
 		switch (ids[idx]->xid.type) {
 		case ID_TYPE_UID:     
 			if ( ! u_filter) {
@@ -462,7 +427,7 @@ again:
 			continue;
 		}
 
-		map = find_map_by_id(&ids[bidx], type, id);
+		map = idmap_find_map_by_id(&ids[bidx], type, id);
 		if (!map) {
 			DEBUG(2, ("WARNING: couldn't match result with requested ID\n"));
 			continue;
@@ -567,7 +532,7 @@ again:
 	CHECK_ALLOC_DONE(filter);
 
 	bidx = idx;
-	for (i = 0; (i < IDMAP_AD_MAX_IDS) && ids[idx]; i++, idx++) {
+	for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
 
 		ids[idx]->status = ID_UNKNOWN;
 
@@ -617,7 +582,7 @@ again:
 			continue;
 		}
 
-		map = find_map_by_sid(&ids[bidx], &sid);
+		map = idmap_find_map_by_sid(&ids[bidx], &sid);
 		if (!map) {
 			DEBUG(2, ("WARNING: couldn't match result with requested SID\n"));
 			continue;
diff --git a/source3/winbindd/idmap_ldap.c b/source3/winbindd/idmap_ldap.c
index 0c58bf4..03872e7 100644
--- a/source3/winbindd/idmap_ldap.c
+++ b/source3/winbindd/idmap_ldap.c
@@ -663,34 +663,10 @@ static NTSTATUS idmap_ldap_new_mapping(struct idmap_domain *dom, struct id_map *
 	return ret;
 }
 
-
-/* max number of ids requested per batch query */
-#define IDMAP_LDAP_MAX_IDS 30
-
 /**********************************
  lookup a set of unix ids.
 **********************************/
 
-/* this function searches up to IDMAP_LDAP_MAX_IDS entries
- * in maps for a match */
-static struct id_map *find_map_by_id(struct id_map **maps,
-				     enum id_type type,
-				     uint32_t id)
-{
-	int i;
-
-	for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
-		if (maps[i] == NULL) { /* end of the run */
-			return NULL;
-		}
-		if ((maps[i]->xid.type == type) && (maps[i]->xid.id == id)) {
-			return maps[i];
-		}
-	}
-
-	return NULL;
-}
-
 static NTSTATUS idmap_ldap_unixids_to_sids(struct idmap_domain *dom,
 					   struct id_map **ids)
 {
@@ -846,7 +822,7 @@ again:
 		}
 		TALLOC_FREE(tmp);
 
-		map = find_map_by_id(&ids[bidx], type, id);
+		map = idmap_find_map_by_id(&ids[bidx], type, id);
 		if (!map) {
 			DEBUG(2, ("WARNING: couldn't match sid (%s) "
 				  "with requested ids\n", sidstr));
@@ -903,24 +879,6 @@ done:
  lookup a set of sids.
 **********************************/
 
-/* this function searches up to IDMAP_LDAP_MAX_IDS entries
- * in maps for a match */
-static struct id_map *find_map_by_sid(struct id_map **maps, struct dom_sid *sid)
-{
-	int i;
-
-	for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
-		if (maps[i] == NULL) { /* end of the run */
-			return NULL;
-		}
-		if (dom_sid_equal(maps[i]->sid, sid)) {
-			return maps[i];
-		}
-	}
-
-	return NULL;
-}
-
 static NTSTATUS idmap_ldap_sids_to_unixids(struct idmap_domain *dom,
 					   struct id_map **ids)
 {
@@ -1053,7 +1011,7 @@ again:
 			continue;
 		}
 
-		map = find_map_by_sid(&ids[bidx], &sid);
+		map = idmap_find_map_by_sid(&ids[bidx], &sid);
 		if (!map) {
 			DEBUG(2, ("WARNING: couldn't find entry sid (%s) "
 				  "in ids", sidstr));
diff --git a/source3/winbindd/idmap_proto.h b/source3/winbindd/idmap_proto.h
index 892b258..a709807 100644
--- a/source3/winbindd/idmap_proto.h
+++ b/source3/winbindd/idmap_proto.h
@@ -54,5 +54,11 @@ NTSTATUS idmap_tdb_init(void);
 NTSTATUS idmap_uid_to_sid(const char *domname, struct dom_sid *sid, uid_t uid);
 NTSTATUS idmap_gid_to_sid(const char *domname, struct dom_sid *sid, gid_t gid);
 bool idmap_unix_id_is_in_range(uint32_t id, struct idmap_domain *dom);
+struct id_map *idmap_find_map_by_id(struct id_map **maps, enum id_type type,
+				    uint32_t id);
+struct id_map *idmap_find_map_by_sid(struct id_map **maps, struct dom_sid *sid);
+
+/* max number of ids requested per LDAP batch query */
+#define IDMAP_LDAP_MAX_IDS 30
 
 #endif /* _WINBINDD_IDMAP_PROTO_H_ */
diff --git a/source3/winbindd/idmap_util.c b/source3/winbindd/idmap_util.c
index 9d9ada7..cbad91d 100644
--- a/source3/winbindd/idmap_util.c
+++ b/source3/winbindd/idmap_util.c
@@ -172,3 +172,44 @@ bool idmap_unix_id_is_in_range(uint32_t id, struct idmap_domain *dom)
 
 	return true;
 }
+
+/**
+ * Helper for unixids_to_sids: find entry by id in mapping array,
+ * search up to IDMAP_AD_MAX_IDS entries
+ */
+struct id_map *idmap_find_map_by_id(struct id_map **maps, enum id_type type,
+				    uint32_t id)
+{
+	int i;
+
+	for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
+		if (maps[i] == NULL) { /* end of the run */
+			return NULL;
+		}
+		if ((maps[i]->xid.type == type) && (maps[i]->xid.id == id)) {
+			return maps[i];
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * Helper for sids_to_unix_ids: find entry by SID in mapping array,
+ * search up to IDMAP_AD_MAX_IDS entries
+ */
+struct id_map *idmap_find_map_by_sid(struct id_map **maps, struct dom_sid *sid)
+{
+	int i;
+
+	for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
+		if (maps[i] == NULL) { /* end of the run */
+			return NULL;
+		}
+		if (dom_sid_equal(maps[i]->sid, sid)) {
+			return maps[i];
+		}
+	}
+
+	return NULL;
+}
-- 
1.7.1


>From 9c66c7471ca8dbe20bf6dbd8b6758f0e95e948e8 Mon Sep 17 00:00:00 2001
From: Christof Schmitt <christof.schmitt at us.ibm.com>
Date: Thu, 21 Feb 2013 12:31:19 -0700
Subject: [PATCH 02/10] s3-winbindd: Move idmap_fetch_secret to idmap_utils.c for reuse

---
 source3/winbindd/idmap_ldap.c  |   24 ------------------------
 source3/winbindd/idmap_proto.h |    2 ++
 source3/winbindd/idmap_util.c  |   25 +++++++++++++++++++++++++
 3 files changed, 27 insertions(+), 24 deletions(-)

diff --git a/source3/winbindd/idmap_ldap.c b/source3/winbindd/idmap_ldap.c
index 03872e7..0520f21 100644
--- a/source3/winbindd/idmap_ldap.c
+++ b/source3/winbindd/idmap_ldap.c
@@ -39,30 +39,6 @@
 #include "smbldap.h"
 #include "passdb/pdb_ldap_schema.h"
 
-static char *idmap_fetch_secret(const char *backend,
-				const char *domain, const char *identity)
-{
-	char *tmp, *ret;
-	int r;
-
-	r = asprintf(&tmp, "IDMAP_%s_%s", backend, domain);
-
-	if (r < 0)
-		return NULL;
-
-	/* make sure the key is case insensitive */
-	if (!strupper_m(tmp)) {
-		SAFE_FREE(tmp);
-		return NULL;
-	}
-
-	ret = secrets_fetch_generic(tmp, identity);
-
-	SAFE_FREE(tmp);
-
-	return ret;
-}
-
 struct idmap_ldap_context {
 	struct smbldap_state *smbldap_state;
 	char *url;
diff --git a/source3/winbindd/idmap_proto.h b/source3/winbindd/idmap_proto.h
index a709807..f7af8ed 100644
--- a/source3/winbindd/idmap_proto.h
+++ b/source3/winbindd/idmap_proto.h
@@ -57,6 +57,8 @@ bool idmap_unix_id_is_in_range(uint32_t id, struct idmap_domain *dom);
 struct id_map *idmap_find_map_by_id(struct id_map **maps, enum id_type type,
 				    uint32_t id);
 struct id_map *idmap_find_map_by_sid(struct id_map **maps, struct dom_sid *sid);
+char *idmap_fetch_secret(const char *backend, const char *domain,
+			 const char *identity);
 
 /* max number of ids requested per LDAP batch query */
 #define IDMAP_LDAP_MAX_IDS 30
diff --git a/source3/winbindd/idmap_util.c b/source3/winbindd/idmap_util.c
index cbad91d..a068298 100644
--- a/source3/winbindd/idmap_util.c
+++ b/source3/winbindd/idmap_util.c
@@ -24,6 +24,7 @@
 #include "idmap.h"
 #include "idmap_cache.h"
 #include "../libcli/security/security.h"
+#include "secrets.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_IDMAP
@@ -213,3 +214,27 @@ struct id_map *idmap_find_map_by_sid(struct id_map **maps, struct dom_sid *sid)
 
 	return NULL;
 }
+
+char *idmap_fetch_secret(const char *backend, const char *domain,
+			 const char *identity)
+{
+	char *tmp, *ret;
+	int r;
+
+	r = asprintf(&tmp, "IDMAP_%s_%s", backend, domain);
+
+	if (r < 0)
+		return NULL;
+
+	/* make sure the key is case insensitive */
+	if (!strupper_m(tmp)) {
+		SAFE_FREE(tmp);
+		return NULL;
+	}
+
+	ret = secrets_fetch_generic(tmp, identity);
+
+	SAFE_FREE(tmp);
+
+	return ret;
+}
-- 
1.7.1


>From 3165fae1de8be7fc3202acb01dfe155b92d6fbd1 Mon Sep 17 00:00:00 2001
From: Christof Schmitt <christof.schmitt at us.ibm.com>
Date: Thu, 21 Feb 2013 12:31:28 -0700
Subject: [PATCH 03/10] s3-winbindd: Move code for verifying ADS connection to common helper function

---
 source3/winbindd/idmap_ad.c       |   26 +----------------
 source3/winbindd/winbindd_ads.c   |   54 ++++++++++++++++++++++--------------
 source3/winbindd/winbindd_proto.h |    6 ++++
 3 files changed, 41 insertions(+), 45 deletions(-)

diff --git a/source3/winbindd/idmap_ad.c b/source3/winbindd/idmap_ad.c
index d6f31ba..0e00a34 100644
--- a/source3/winbindd/idmap_ad.c
+++ b/source3/winbindd/idmap_ad.c
@@ -39,8 +39,6 @@
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_IDMAP
 
-#define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
-
 #define CHECK_ALLOC_DONE(mem) do { \
      if (!mem) { \
            DEBUG(0, ("Out of memory!\n")); \
@@ -74,29 +72,9 @@ static ADS_STATUS ad_idmap_cached_connection_internal(struct idmap_domain *dom)
 
 	ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);
 
+	ads_cached_connection_reuse(&ctx->ads);
 	if (ctx->ads != NULL) {
-
-		time_t expire;
-		time_t now = time(NULL);
-
-		ads = ctx->ads;
-
-		expire = MIN(ads->auth.tgt_expire, ads->auth.tgs_expire);
-
-		/* check for a valid structure */
-		DEBUG(7, ("Current tickets expire in %d seconds (at %d, time is now %d)\n",
-			  (uint32)expire-(uint32)now, (uint32) expire, (uint32) now));
-
-		if ( ads->config.realm && (expire > time(NULL))) {
-			return ADS_SUCCESS;
-		} else {
-			/* we own this ADS_STRUCT so make sure it goes away */
-			DEBUG(7,("Deleting expired krb5 credential cache\n"));
-			ads->is_mine = True;
-			ads_destroy( &ads );
-			ads_kdestroy(WINBIND_CCACHE_NAME);
-			ctx->ads = NULL;
-		}
+		return ADS_SUCCESS;
 	}
 
 	/* we don't want this to affect the users ccache */
diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c
index 921d408..ea6170d 100644
--- a/source3/winbindd/winbindd_ads.c
+++ b/source3/winbindd/winbindd_ads.c
@@ -40,43 +40,55 @@
 
 extern struct winbindd_methods reconnect_methods;
 
-/*
-  return our ads connections structure for a domain. We keep the connection
-  open to make things faster
-*/
-static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
+/**
+ * Check if cached connection can be reused. If the connection cannot
+ * be reused the ADS_STRUCT is freed and the pointer is set to NULL.
+ */
+void ads_cached_connection_reuse(ADS_STRUCT **adsp)
 {
-	ADS_STRUCT *ads;
-	ADS_STATUS status;
-	fstring dc_name;
-	struct sockaddr_storage dc_ss;
-
-	DEBUG(10,("ads_cached_connection\n"));
 
-	if (domain->private_data) {
+	ADS_STRUCT *ads = *adsp;
 
+	if (ads != NULL) {
 		time_t expire;
 		time_t now = time(NULL);
 
-		/* check for a valid structure */
-		ads = (ADS_STRUCT *)domain->private_data;
-
 		expire = MIN(ads->auth.tgt_expire, ads->auth.tgs_expire);
 
-		DEBUG(7, ("Current tickets expire in %d seconds (at %d, time is now %d)\n",
-			  (uint32)expire-(uint32)now, (uint32) expire, (uint32) now));
+		DEBUG(7, ("Current tickets expire in %d seconds (at %d, time "
+			  "is now %d)\n", (uint32)expire - (uint32)now,
+			  (uint32) expire, (uint32) now));
 
 		if ( ads->config.realm && (expire > now)) {
-			return ads;
+			return;
 		} else {
 			/* we own this ADS_STRUCT so make sure it goes away */
 			DEBUG(7,("Deleting expired krb5 credential cache\n"));
 			ads->is_mine = True;
 			ads_destroy( &ads );
-			ads_kdestroy("MEMORY:winbind_ccache");
-			domain->private_data = NULL;
+			ads_kdestroy(WINBIND_CCACHE_NAME);
+			*adsp = NULL;
 		}
 	}
+}
+
+/*
+  return our ads connections structure for a domain. We keep the connection
+  open to make things faster
+*/
+static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
+{
+	ADS_STRUCT *ads;
+	ADS_STATUS status;
+	fstring dc_name;
+	struct sockaddr_storage dc_ss;
+
+	DEBUG(10,("ads_cached_connection\n"));
+	ads_cached_connection_reuse((ADS_STRUCT **)&domain->private_data);
+
+	if (domain->private_data) {
+		return (ADS_STRUCT *)domain->private_data;
+	}
 
 	ads = ads_init(domain->alt_name, domain->name, NULL);
 	if (!ads) {
@@ -1282,7 +1294,7 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
 			ads = (ADS_STRUCT *)domain->private_data;
 			ads->is_mine = True;
 			ads_destroy(&ads);
-			ads_kdestroy("MEMORY:winbind_ccache");
+			ads_kdestroy(WINBIND_CCACHE_NAME);
 			domain->private_data = NULL;
 		}
 	}
diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h
index 00b7c32..0d75791 100644
--- a/source3/winbindd/winbindd_proto.h
+++ b/source3/winbindd/winbindd_proto.h
@@ -23,6 +23,8 @@
 #ifndef _WINBINDD_PROTO_H_
 #define _WINBINDD_PROTO_H_
 
+#include "ads.h"
+
 /* The following definitions come from winbindd/winbindd.c  */
 struct messaging_context *winbind_messaging_context(void);
 void request_error(struct winbindd_cli_state *state);
@@ -890,4 +892,8 @@ NTSTATUS open_internal_samr_conn(TALLOC_CTX *mem_ctx,
 				 struct rpc_pipe_client **samr_pipe,
 				 struct policy_handle *samr_domain_hnd);
 
+/* The following definitions come from winbindd/winbindd_ads.c  */
+#define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
+void ads_cached_connection_reuse(ADS_STRUCT **ads);
+
 #endif /*  _WINBINDD_PROTO_H_  */
-- 
1.7.1


>From 03183525048fc537a3db330f5f452aba00222273 Mon Sep 17 00:00:00 2001
From: Christof Schmitt <christof.schmitt at us.ibm.com>
Date: Thu, 21 Feb 2013 12:31:37 -0700
Subject: [PATCH 04/10] s3-winbindd: Use common helper function for connecting to ADS

---
 source3/winbindd/idmap_ad.c       |   41 ++-----------
 source3/winbindd/winbindd_ads.c   |  125 ++++++++++++++++++++++---------------
 source3/winbindd/winbindd_proto.h |    7 ++
 3 files changed, 87 insertions(+), 86 deletions(-)

diff --git a/source3/winbindd/idmap_ad.c b/source3/winbindd/idmap_ad.c
index 0e00a34..5b9c377 100644
--- a/source3/winbindd/idmap_ad.c
+++ b/source3/winbindd/idmap_ad.c
@@ -58,13 +58,8 @@ struct idmap_ad_context {
 
 static ADS_STATUS ad_idmap_cached_connection_internal(struct idmap_domain *dom)
 {
-	ADS_STRUCT *ads;
-	ADS_STATUS status;
-	fstring dc_name;
-	struct sockaddr_storage dc_ip;
 	struct idmap_ad_context *ctx;
-	char *ldap_server = NULL;
-	char *realm = NULL;
+	char *ldap_server, *realm, *password;
 	struct winbindd_domain *wb_dom;
 
 	DEBUG(10, ("ad_idmap_cached_connection: called for domain '%s'\n",
@@ -77,9 +72,6 @@ static ADS_STATUS ad_idmap_cached_connection_internal(struct idmap_domain *dom)
 		return ADS_SUCCESS;
 	}
 
-	/* we don't want this to affect the users ccache */
-	setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1);
-
 	/*
 	 * At this point we only have the NetBIOS domain name.
 	 * Check if we can get server nam and realm from SAF cache
@@ -99,35 +91,12 @@ static ADS_STATUS ad_idmap_cached_connection_internal(struct idmap_domain *dom)
 		realm = wb_dom->alt_name;
 	}
 
-	if ( (ads = ads_init(realm, dom->name, ldap_server)) == NULL ) {
-		DEBUG(1,("ads_init failed\n"));
-		return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
-	}
-
 	/* the machine acct password might have change - fetch it every time */
-	SAFE_FREE(ads->auth.password);
-	ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
-
-	SAFE_FREE(ads->auth.realm);
-	ads->auth.realm = SMB_STRDUP(lp_realm());
-
-	/* setup server affinity */
-
-	get_dc_name(dom->name, realm, dc_name, &dc_ip );
-
-	status = ads_connect(ads);
-	if (!ADS_ERR_OK(status)) {
-		DEBUG(1, ("ad_idmap_cached_connection_internal: failed to "
-			  "connect to AD\n"));
-		ads_destroy(&ads);
-		return status;
-	}
-
-	ads->is_mine = False;
-
-	ctx->ads = ads;
+	password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
+	realm = SMB_STRDUP(lp_realm());
 
-	return ADS_SUCCESS;
+	return ads_cached_connection_connect(&ctx->ads, realm, dom->name,
+					     ldap_server, password, realm, 0);
 }
 
 /************************************************************************
diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c
index ea6170d..ffc62ba 100644
--- a/source3/winbindd/winbindd_ads.c
+++ b/source3/winbindd/winbindd_ads.c
@@ -72,16 +72,73 @@ void ads_cached_connection_reuse(ADS_STRUCT **adsp)
 	}
 }
 
+ADS_STATUS ads_cached_connection_connect(ADS_STRUCT **adsp,
+					 const char *dom_name_alt,
+					 const char *dom_name,
+					 const char *ldap_server,
+					 char *password,
+					 char *realm,
+					 time_t renewable)
+{
+	ADS_STRUCT *ads;
+	ADS_STATUS status;
+	struct sockaddr_storage dc_ss;
+	fstring dc_name;
+
+	/* we don't want this to affect the users ccache */
+	setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1);
+
+	ads = ads_init(dom_name_alt, dom_name, ldap_server);
+	if (!ads) {
+		DEBUG(1,("ads_init for domain %s failed\n", dom_name));
+		return ADS_ERROR(LDAP_NO_MEMORY);
+	}
+
+	SAFE_FREE(ads->auth.password);
+	SAFE_FREE(ads->auth.realm);
+
+	ads->auth.renewable = renewable;
+	ads->auth.password = password;
+	ads->auth.realm = realm;
+
+	ads->auth.realm = SMB_STRDUP(realm);
+	if (!strupper_m(ads->auth.realm)) {
+		ads_destroy(&ads);
+		return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
+	}
+
+	/* Setup the server affinity cache.  We don't reaally care
+	   about the name.  Just setup affinity and the KRB5_CONFIG
+	   file. */
+	get_dc_name(ads->server.workgroup, ads->server.realm, dc_name, &dc_ss);
+
+	status = ads_connect(ads);
+	if (!ADS_ERR_OK(status)) {
+		DEBUG(1,("ads_connect for domain %s failed: %s\n",
+			 dom_name, ads_errstr(status)));
+		ads_destroy(&ads);
+		return status;
+	}
+
+	/* set the flag that says we don't own the memory even
+	   though we do so that ads_destroy() won't destroy the
+	   structure we pass back by reference */
+
+	ads->is_mine = False;
+
+	*adsp = ads;
+
+	return status;
+}
+
 /*
   return our ads connections structure for a domain. We keep the connection
   open to make things faster
 */
 static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
 {
-	ADS_STRUCT *ads;
 	ADS_STATUS status;
-	fstring dc_name;
-	struct sockaddr_storage dc_ss;
+	char *password, *realm;
 
 	DEBUG(10,("ads_cached_connection\n"));
 	ads_cached_connection_reuse((ADS_STRUCT **)&domain->private_data);
@@ -90,37 +147,22 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
 		return (ADS_STRUCT *)domain->private_data;
 	}
 
-	ads = ads_init(domain->alt_name, domain->name, NULL);
-	if (!ads) {
-		DEBUG(1,("ads_init for domain %s failed\n", domain->name));
-		return NULL;
-	}
-
-	/* we don't want ads operations to affect the default ccache */
-	ads->auth.ccache_name = SMB_STRDUP("MEMORY:winbind_ccache");
-
 	/* the machine acct password might have change - fetch it every time */
 
-	SAFE_FREE(ads->auth.password);
-	SAFE_FREE(ads->auth.realm);
-
 	if ( IS_DC ) {
 
-		if ( !pdb_get_trusteddom_pw( domain->name, &ads->auth.password, NULL, NULL ) ) {
-			ads_destroy( &ads );
-			return NULL;
-		}
-		ads->auth.realm = SMB_STRDUP( ads->server.realm );
-		if (!strupper_m( ads->auth.realm )) {
-			ads_destroy( &ads );
+		if ( !pdb_get_trusteddom_pw( domain->name, &password, NULL,
+					     NULL ) ) {
 			return NULL;
 		}
+		realm = NULL;
 	}
 	else {
 		struct winbindd_domain *our_domain = domain;
 
-		ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
 
+		password = secrets_fetch_machine_password(lp_workgroup(), NULL,
+							  NULL);
 		/* always give preference to the alt_name in our
 		   primary domain if possible */
 
@@ -128,30 +170,21 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
 			our_domain = find_our_domain();
 
 		if ( our_domain->alt_name[0] != '\0' ) {
-			ads->auth.realm = SMB_STRDUP( our_domain->alt_name );
-			if (!strupper_m( ads->auth.realm )) {
-				ads_destroy( &ads );
-				return NULL;
-			}
+			realm = SMB_STRDUP( our_domain->alt_name );
 		}
 		else
-			ads->auth.realm = SMB_STRDUP( lp_realm() );
+			realm = SMB_STRDUP( lp_realm() );
 	}
 
-	ads->auth.renewable = WINBINDD_PAM_AUTH_KRB5_RENEW_TIME;
+	status = ads_cached_connection_connect(
+					(ADS_STRUCT **)&domain->private_data,
+					domain->alt_name,
+					domain->name, NULL,
+					password, realm,
+					WINBINDD_PAM_AUTH_KRB5_RENEW_TIME);
 
-	/* Setup the server affinity cache.  We don't reaally care
-	   about the name.  Just setup affinity and the KRB5_CONFIG
-	   file. */
-
-	get_dc_name( ads->server.workgroup, ads->server.realm, dc_name, &dc_ss );
-
-	status = ads_connect(ads);
-	if (!ADS_ERR_OK(status) || !ads->config.realm) {
-		DEBUG(1,("ads_connect for domain %s failed: %s\n",
-			 domain->name, ads_errstr(status)));
-		ads_destroy(&ads);
 
+	if (!ADS_ERR_OK(status)) {
 		/* if we get ECONNREFUSED then it might be a NT4
                    server, fall back to MSRPC */
 		if (status.error_type == ENUM_ADS_ERROR_SYSTEM &&
@@ -163,17 +196,9 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
 		return NULL;
 	}
 
-	/* set the flag that says we don't own the memory even
-	   though we do so that ads_destroy() won't destroy the
-	   structure we pass back by reference */
-
-	ads->is_mine = False;
-
-	domain->private_data = (void *)ads;
-	return ads;
+	return (ADS_STRUCT *)domain->private_data;
 }
 
-
 /* Query display info for a realm. This is the basic user list fn */
 static NTSTATUS query_user_list(struct winbindd_domain *domain,
 			       TALLOC_CTX *mem_ctx,
diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h
index 0d75791..8bd7a39 100644
--- a/source3/winbindd/winbindd_proto.h
+++ b/source3/winbindd/winbindd_proto.h
@@ -895,5 +895,12 @@ NTSTATUS open_internal_samr_conn(TALLOC_CTX *mem_ctx,
 /* The following definitions come from winbindd/winbindd_ads.c  */
 #define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
 void ads_cached_connection_reuse(ADS_STRUCT **ads);
+ADS_STATUS ads_cached_connection_connect(ADS_STRUCT **adsp,
+					 const char *dom_name_alt,
+					 const char *dom_name,
+					 const char *ldap_server,
+					 char *password,
+					 char *realm,
+					 time_t renewable);
 
 #endif /*  _WINBINDD_PROTO_H_  */
-- 
1.7.1


>From ee4b5bc8ee5212f3500cb68de6c3f0e6b194cc38 Mon Sep 17 00:00:00 2001
From: Christof Schmitt <christof.schmitt at us.ibm.com>
Date: Thu, 21 Feb 2013 12:31:41 -0700
Subject: [PATCH 05/10] s3-winbindd: Move connection to AD server from idmap_ad

Having this in a common place allows reuse by other idmap modules.
---
 source3/winbindd/idmap_ad.c       |   49 +++------------------------------
 source3/winbindd/winbindd_ads.c   |   55 +++++++++++++++++++++++++++++++-----
 source3/winbindd/winbindd_proto.h |   10 +------
 3 files changed, 52 insertions(+), 62 deletions(-)

diff --git a/source3/winbindd/idmap_ad.c b/source3/winbindd/idmap_ad.c
index 5b9c377..5bafa90 100644
--- a/source3/winbindd/idmap_ad.c
+++ b/source3/winbindd/idmap_ad.c
@@ -56,58 +56,17 @@ struct idmap_ad_context {
 /************************************************************************
  ***********************************************************************/
 
-static ADS_STATUS ad_idmap_cached_connection_internal(struct idmap_domain *dom)
+static ADS_STATUS ad_idmap_cached_connection(struct idmap_domain *dom)
 {
-	struct idmap_ad_context *ctx;
-	char *ldap_server, *realm, *password;
-	struct winbindd_domain *wb_dom;
+	ADS_STATUS status;
+	struct idmap_ad_context * ctx;
 
 	DEBUG(10, ("ad_idmap_cached_connection: called for domain '%s'\n",
 		   dom->name));
 
 	ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);
 
-	ads_cached_connection_reuse(&ctx->ads);
-	if (ctx->ads != NULL) {
-		return ADS_SUCCESS;
-	}
-
-	/*
-	 * At this point we only have the NetBIOS domain name.
-	 * Check if we can get server nam and realm from SAF cache
-	 * and the domain list.
-	 */
-	ldap_server = saf_fetch(dom->name);
-	DEBUG(10, ("ldap_server from saf cache: '%s'\n", ldap_server?ldap_server:""));
-
-	wb_dom = find_domain_from_name_noinit(dom->name);
-	if (wb_dom == NULL) {
-		DEBUG(10, ("find_domain_from_name_noinit did not find domain '%s'\n",
-			   dom->name));
-		realm = NULL;
-	} else {
-		DEBUG(10, ("find_domain_from_name_noinit found realm '%s' for "
-			  " domain '%s'\n", wb_dom->alt_name, dom->name));
-		realm = wb_dom->alt_name;
-	}
-
-	/* the machine acct password might have change - fetch it every time */
-	password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
-	realm = SMB_STRDUP(lp_realm());
-
-	return ads_cached_connection_connect(&ctx->ads, realm, dom->name,
-					     ldap_server, password, realm, 0);
-}
-
-/************************************************************************
- ***********************************************************************/
-
-static ADS_STATUS ad_idmap_cached_connection(struct idmap_domain *dom)
-{
-	ADS_STATUS status;
-	struct idmap_ad_context * ctx;
-
-	status = ad_idmap_cached_connection_internal(dom);
+	status = ads_idmap_cached_connection(&ctx->ads, dom->name);
 	if (!ADS_ERR_OK(status)) {
 		return status;
 	}
diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c
index ffc62ba..2dcd07d 100644
--- a/source3/winbindd/winbindd_ads.c
+++ b/source3/winbindd/winbindd_ads.c
@@ -40,11 +40,13 @@
 
 extern struct winbindd_methods reconnect_methods;
 
+#define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
+
 /**
  * Check if cached connection can be reused. If the connection cannot
  * be reused the ADS_STRUCT is freed and the pointer is set to NULL.
  */
-void ads_cached_connection_reuse(ADS_STRUCT **adsp)
+static void ads_cached_connection_reuse(ADS_STRUCT **adsp)
 {
 
 	ADS_STRUCT *ads = *adsp;
@@ -72,13 +74,13 @@ void ads_cached_connection_reuse(ADS_STRUCT **adsp)
 	}
 }
 
-ADS_STATUS ads_cached_connection_connect(ADS_STRUCT **adsp,
-					 const char *dom_name_alt,
-					 const char *dom_name,
-					 const char *ldap_server,
-					 char *password,
-					 char *realm,
-					 time_t renewable)
+static ADS_STATUS ads_cached_connection_connect(ADS_STRUCT **adsp,
+						const char *dom_name_alt,
+						const char *dom_name,
+						const char *ldap_server,
+						char *password,
+						char *realm,
+						time_t renewable)
 {
 	ADS_STRUCT *ads;
 	ADS_STATUS status;
@@ -131,6 +133,43 @@ ADS_STATUS ads_cached_connection_connect(ADS_STRUCT **adsp,
 	return status;
 }
 
+ADS_STATUS ads_idmap_cached_connection(ADS_STRUCT **adsp, const char *dom_name)
+{
+	char *ldap_server, *realm, *password;
+	struct winbindd_domain *wb_dom;
+
+	ads_cached_connection_reuse(adsp);
+	if (*adsp != NULL) {
+		return ADS_SUCCESS;
+	}
+
+	/*
+	 * At this point we only have the NetBIOS domain name.
+	 * Check if we can get server nam and realm from SAF cache
+	 * and the domain list.
+	 */
+	ldap_server = saf_fetch(dom_name);
+	DEBUG(10, ("ldap_server from saf cache: '%s'\n",
+		   ldap_server ? ldap_server : ""));
+
+	wb_dom = find_domain_from_name_noinit(dom_name);
+	if (wb_dom == NULL) {
+		DEBUG(10, ("could not find domain '%s'\n", dom_name));
+		realm = NULL;
+	} else {
+		DEBUG(10, ("find_domain_from_name_noinit found realm '%s' for "
+			  " domain '%s'\n", wb_dom->alt_name, dom_name));
+		realm = wb_dom->alt_name;
+	}
+
+	/* the machine acct password might have change - fetch it every time */
+	password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
+	realm = SMB_STRDUP(lp_realm());
+
+	return ads_cached_connection_connect(adsp, realm, dom_name, ldap_server,
+					     password, realm, 0);
+}
+
 /*
   return our ads connections structure for a domain. We keep the connection
   open to make things faster
diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h
index 8bd7a39..b07f303 100644
--- a/source3/winbindd/winbindd_proto.h
+++ b/source3/winbindd/winbindd_proto.h
@@ -893,14 +893,6 @@ NTSTATUS open_internal_samr_conn(TALLOC_CTX *mem_ctx,
 				 struct policy_handle *samr_domain_hnd);
 
 /* The following definitions come from winbindd/winbindd_ads.c  */
-#define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
-void ads_cached_connection_reuse(ADS_STRUCT **ads);
-ADS_STATUS ads_cached_connection_connect(ADS_STRUCT **adsp,
-					 const char *dom_name_alt,
-					 const char *dom_name,
-					 const char *ldap_server,
-					 char *password,
-					 char *realm,
-					 time_t renewable);
+ADS_STATUS ads_idmap_cached_connection(ADS_STRUCT **adsp, const char *dom_name);
 
 #endif /*  _WINBINDD_PROTO_H_  */
-- 
1.7.1


>From a5892eaede1bd21163a205110beb1bf4f5615f95 Mon Sep 17 00:00:00 2001
From: Christof Schmitt <christof.schmitt at us.ibm.com>
Date: Thu, 21 Feb 2013 12:32:37 -0700
Subject: [PATCH 06/10] s3-winbindd: Add new module idmap_rfc2307

This module allows querying id mappings from LDAP servers as described
in RFC 2307. The LDAP records can be queried from an Active Directory
Server or from a stand-alone LDAP server.
---
 source3/Makefile.in              |    4 +
 source3/configure.in             |    1 +
 source3/winbindd/idmap_rfc2307.c |  870 ++++++++++++++++++++++++++++++++++++++
 source3/winbindd/wscript_build   |   10 +
 source3/wscript                  |    2 +-
 5 files changed, 886 insertions(+), 1 deletions(-)
 create mode 100644 source3/winbindd/idmap_rfc2307.c

diff --git a/source3/Makefile.in b/source3/Makefile.in
index 90f12b7..194cba7 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -2694,6 +2694,10 @@ bin/ad. at SHLIBEXT@: $(BINARY_PREREQS) winbindd/idmap_ad.o
 	@echo "Building plugin $@"
 	@$(SHLD_MODULE) winbindd/idmap_ad.o
 
+bin/rfc2307. at SHLIBEXT@: $(BINARY_PREREQS) winbindd/idmap_rfc2307.o
+	@echo "Building plugin $@"
+	@$(SHLD_MODULE) winbindd/idmap_rfc2307.o
+
 bin/hash. at SHLIBEXT@: $(BINARY_PREREQS) $(IDMAP_HASH_OBJ)
 	@echo "Building plugin $@"
 	@$(SHLD_MODULE) $(IDMAP_HASH_OBJ)
diff --git a/source3/configure.in b/source3/configure.in
index 552535b..d3d74a9 100644
--- a/source3/configure.in
+++ b/source3/configure.in
@@ -6382,6 +6382,7 @@ SMB_MODULE(idmap_nss, winbindd/idmap_nss.o, "bin/nss.$SHLIBEXT", IDMAP)
 SMB_MODULE(idmap_rid, winbindd/idmap_rid.o, "bin/rid.$SHLIBEXT", IDMAP)
 SMB_MODULE(idmap_autorid, winbindd/idmap_autorid.o, "bin/autorid.$SHLIBEXT", IDMAP)
 SMB_MODULE(idmap_ad, winbindd/idmap_ad.o, "bin/ad.$SHLIBEXT", IDMAP)
+SMB_MODULE(idmap_rfc2307, winbindd/idmap_rfc2307.o, "bin/rfc2307.$SHLIBEXT", IDMAP)
 SMB_MODULE(idmap_hash, \$(IDMAP_HASH_OBJ), "bin/hash.$SHLIBEXT", IDMAP)
 SMB_SUBSYSTEM(IDMAP, winbindd/idmap.o)
 
diff --git a/source3/winbindd/idmap_rfc2307.c b/source3/winbindd/idmap_rfc2307.c
new file mode 100644
index 0000000..2b7a593
--- /dev/null
+++ b/source3/winbindd/idmap_rfc2307.c
@@ -0,0 +1,870 @@
+/*
+ * Unix SMB/CIFS implementation.
+ *
+ * Id mapping using LDAP records as defined in RFC 2307
+ *
+ * The SID<->uid/gid mapping is performed in two steps: 1) Query the
+ * AD server for the name<->sid mapping. 2) Query an LDAP server
+ * according to RFC 2307 for the name<->uid/gid mapping.
+ *
+ * Copyright (C) Christof Schmitt 2012,2013
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+#include "winbindd.h"
+#include "ads.h"
+#include "idmap.h"
+#include "smbldap.h"
+#include "nsswitch/winbind_client.h"
+#include "lib/winbind_util.h"
+
+/*
+ * Config and connection info per domain.
+ */
+struct idmap_rfc2307_context {
+	const char *bind_path_user;
+	const char *bind_path_group;
+	const char *ldap_domain;
+	bool cn_realm;
+	bool user_cn;
+	const char *realm;
+
+	/*
+	 * Pointer to ldap struct in ads or smbldap_state, has to be
+	 * updated after connecting to server
+	 */
+	LDAP *ldap;
+
+	/* Optional function to check connection to server */
+	NTSTATUS (*check_connection)(struct idmap_domain *dom);
+
+	/* Issue ldap query */
+	NTSTATUS (*search)(struct idmap_rfc2307_context *ctx,
+			   const char *bind_path, const char *expr,
+			   const char **attrs, LDAPMessage **res);
+
+	/* Access to LDAP in AD server */
+	ADS_STRUCT *ads;
+
+	/* Access to stand-alone LDAP server */
+	struct smbldap_state *smbldap_state;
+};
+
+/*
+ * backend functions for LDAP queries through ADS
+ */
+
+static NTSTATUS idmap_rfc2307_ads_check_connection(struct idmap_domain *dom)
+{
+	struct idmap_rfc2307_context *ctx;
+	const char *dom_name = dom->name;
+	ADS_STATUS status;
+
+	DEBUG(10, ("ad_idmap_cached_connection: called for domain '%s'\n",
+		   dom->name));
+
+	ctx = talloc_get_type(dom->private_data, struct idmap_rfc2307_context);
+	dom_name = ctx->ldap_domain ? ctx->ldap_domain : dom->name;
+
+	status = ads_idmap_cached_connection(&ctx->ads, dom_name);
+	if (ADS_ERR_OK(status)) {
+		ctx->ldap = ctx->ads->ldap.ld;
+		if (ctx->cn_realm) {
+			ctx->realm = ctx->ads->server.realm;
+		}
+	} else {
+		DEBUG(1, ("Could not connect to domain %s: %s\n", dom->name,
+			  ads_errstr(status)));
+	}
+
+	return ads_ntstatus(status);
+}
+
+static NTSTATUS idmap_rfc2307_ads_search(struct idmap_rfc2307_context *ctx,
+					 const char *bind_path,
+					 const char *expr,
+					 const char **attrs,
+					 LDAPMessage **result)
+{
+	ADS_STATUS status;
+
+	status = ads_do_search_retry(ctx->ads, bind_path,
+				     LDAP_SCOPE_SUBTREE, expr, attrs, result);
+	return ads_ntstatus(status);
+}
+
+static NTSTATUS idmap_rfc2307_init_ads(struct idmap_rfc2307_context *ctx,
+				       const char *cfg_opt)
+{
+	const char *ldap_domain;
+
+	ctx->search = idmap_rfc2307_ads_search;
+	ctx->check_connection = idmap_rfc2307_ads_check_connection;
+
+	ldap_domain = lp_parm_const_string(-1, cfg_opt, "ldap_domain",
+					      NULL);
+	if (ldap_domain) {
+		ctx->ldap_domain = talloc_strdup(ctx, ldap_domain);
+		if (ctx->ldap_domain == NULL) {
+			return NT_STATUS_NO_MEMORY;
+		}
+	}
+
+	return NT_STATUS_OK;
+}
+
+/*
+ * backend function for LDAP queries through stand-alone LDAP server
+ */
+
+static NTSTATUS idmap_rfc2307_ldap_search(struct idmap_rfc2307_context *ctx,
+					  const char *bind_path,
+					  const char *expr,
+					  const char **attrs,
+					  LDAPMessage **result)
+{
+	int ret;
+
+	ret = smbldap_search(ctx->smbldap_state, bind_path, LDAP_SCOPE_SUBTREE,
+			     expr, attrs, 0, result);
+	ctx->ldap = ctx->smbldap_state->ldap_struct;
+
+	if (ret == LDAP_SUCCESS) {
+		return NT_STATUS_OK;
+	}
+
+	return NT_STATUS_LDAP(ret);
+}
+
+static bool idmap_rfc2307_get_uint32(LDAP *ldap, LDAPMessage *entry,
+				     const char *field, uint32 *value)
+{
+	bool b;
+	char str[20];
+
+	b = smbldap_get_single_attribute(ldap, entry, field, str, sizeof(str));
+
+	if (b) {
+		*value = atoi(str);
+	}
+
+	return b;
+}
+
+static NTSTATUS idmap_rfc2307_init_ldap(struct idmap_rfc2307_context *ctx,
+					struct idmap_domain *dom,
+					const char *config_option)
+{
+	NTSTATUS ret;
+	char *url;
+	char *secret = NULL;
+	const char *ldap_url, *user_dn, *ldap_realm;
+	TALLOC_CTX *mem_ctx = ctx;
+
+	ldap_url = lp_parm_const_string(-1, config_option, "ldap_url", NULL);
+	if (!ldap_url) {
+		DEBUG(1, ("ERROR: missing idmap ldap url\n"));
+		return NT_STATUS_UNSUCCESSFUL;
+	}
+
+	url = talloc_strdup(talloc_tos(), ldap_url);
+
+	user_dn = lp_parm_const_string(-1, config_option, "ldap_user_dn", NULL);
+	if (user_dn) {
+		secret = idmap_fetch_secret("ldap", dom->name, user_dn);
+		if (!secret) {
+			ret = NT_STATUS_ACCESS_DENIED;
+			goto done;
+		}
+	}
+
+	/* assume anonymous if we don't have a specified user */
+	ret = smbldap_init(mem_ctx, winbind_event_context(), url,
+			   (user_dn == NULL), user_dn, secret,
+			   &ctx->smbldap_state);
+	SAFE_FREE(secret);
+	if (!NT_STATUS_IS_OK(ret)) {
+		DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n", url));
+		goto done;
+	}
+
+	ctx->search = idmap_rfc2307_ldap_search;
+
+	if (ctx->cn_realm) {
+		ldap_realm = lp_parm_const_string(-1, config_option,
+						  "ldap_realm", NULL);
+		if (!ldap_realm) {
+			DEBUG(1, ("ERROR: cn_realm set, "
+				  "but ldap_realm is missing\n"));
+			ret = NT_STATUS_UNSUCCESSFUL;
+			goto done;
+		}
+		ctx->realm = talloc_strdup(mem_ctx, ldap_realm);
+		if (!ctx->realm) {
+			ret = NT_STATUS_NO_MEMORY;
+		}
+	}
+
+done:
+	talloc_free(url);
+	return ret;
+}
+
+/*
+ * common code for stand-alone LDAP and ADS
+ */
+
+static void idmap_rfc2307_map_sid_results(struct idmap_rfc2307_context *ctx,
+					  TALLOC_CTX *mem_ctx,
+					  struct id_map **ids,
+					  LDAPMessage *result,
+					  const char *dom_name,
+					  const char **attrs, int type)
+{
+	int count, i;
+	LDAPMessage *entry;
+
+	count = ldap_count_entries(ctx->ldap, result);
+
+	for (i = 0; i < count; i++) {
+		char *name;
+		enum lsa_SidType lsa_type;
+		struct id_map *map;
+		uint32_t id;
+		bool b;
+
+		if (i == 0) {
+			entry = ldap_first_entry(ctx->ldap, result);
+		} else {
+			entry = ldap_next_entry(ctx->ldap, result);
+		}
+		if (!entry) {
+			DEBUG(2, ("Unable to fetch entry.\n"));
+			break;
+		}
+
+		name = smbldap_talloc_single_attribute(ctx->ldap, entry,
+						       attrs[0], mem_ctx);
+		if (!name) {
+			DEBUG(1, ("Could not get user name\n"));
+			continue;
+		}
+
+		b = idmap_rfc2307_get_uint32(ctx->ldap, entry, attrs[1], &id);
+		if (!b) {
+			DEBUG(1, ("Could not pull id for record %s\n", name));
+			continue;
+		}
+
+		map = idmap_find_map_by_id(ids, type, id);
+		if (!map) {
+			DEBUG(1, ("Could not find id %d, name %s\n", id, name));
+			continue;
+		}
+
+		if (ctx->cn_realm) {
+			/* Strip @realm from user or group name */
+			char *delim;
+
+			delim = strchr(name, '@');
+			if (delim) {
+				*delim = '\0';
+			}
+		}
+
+		/* by default calls to winbindd are disabled
+		   the following call will not recurse so this is safe */
+		(void)winbind_on();
+		/* Lookup name from PDC using lsa_lookup_names() */
+		b = winbind_lookup_name(dom_name, name, map->sid, &lsa_type);
+		(void)winbind_off();
+
+		if (!b) {
+			DEBUG(1, ("SID lookup failed for id %d, %s\n",
+				  id, name));
+			continue;
+		}
+
+		if (type == ID_TYPE_UID && lsa_type != SID_NAME_USER) {
+			DEBUG(1, ("Wrong type %d for user name %s\n",
+				  type, name));
+			continue;
+		}
+
+		if (type == ID_TYPE_GID && lsa_type != SID_NAME_DOM_GRP &&
+		    lsa_type != SID_NAME_ALIAS &&
+		    lsa_type != SID_NAME_WKN_GRP) {
+			DEBUG(1, ("Wrong type %d for group name %s\n",
+				  type, name));
+			continue;
+		}
+
+		map->status = ID_MAPPED;
+	}
+}
+
+/*
+ * Map unixids to names and then to sids.
+ */
+static NTSTATUS idmap_rfc2307_unixids_to_sids(struct idmap_domain *dom,
+					      struct id_map **ids)
+{
+	struct idmap_rfc2307_context *ctx;
+	char *fltr_usr = NULL, *fltr_grp = NULL;
+	TALLOC_CTX *mem_ctx;
+	int cnt_usr = 0, cnt_grp = 0, idx = 0, bidx = 0;
+	LDAPMessage *result = NULL;
+	NTSTATUS ret;
+
+	ctx = talloc_get_type(dom->private_data, struct idmap_rfc2307_context);
+	mem_ctx = talloc_new(ctx);
+	if (!mem_ctx) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	if (ctx->check_connection) {
+		ret = ctx->check_connection(dom);
+		if (!NT_STATUS_IS_OK(ret)) {
+			goto out;
+		}
+	}
+
+again:
+	bidx = idx;
+
+	if (!fltr_usr) {
+		/* prepare new user query, see getpwuid() in RFC2307 */
+		fltr_usr = talloc_asprintf(mem_ctx,
+					     "(&(objectClass=posixAccount)(|");
+	}
+
+	if (!fltr_grp) {
+		/* prepare new group query, see getgrgid() in RFC2307 */
+		fltr_grp = talloc_asprintf(mem_ctx,
+					     "(&(objectClass=posixGroup)(|");
+	}
+
+	if (!fltr_usr || !fltr_grp) {
+		ret = NT_STATUS_NO_MEMORY;
+		goto out;
+	}
+
+	while (cnt_usr < IDMAP_LDAP_MAX_IDS &&
+	       cnt_grp < IDMAP_LDAP_MAX_IDS && ids[idx]) {
+
+		switch (ids[idx]->xid.type) {
+		case ID_TYPE_UID:
+			fltr_usr = talloc_asprintf_append_buffer(fltr_usr,
+					"(uidNumber=%d)", ids[idx]->xid.id);
+			cnt_usr++;
+			break;
+		case ID_TYPE_GID:
+			fltr_grp = talloc_asprintf_append_buffer(fltr_grp,
+					"(gidNumber=%d))", ids[idx]->xid.id);
+			cnt_grp++;
+			break;
+		default:
+			DEBUG(3, ("Error: unknown ID type %d\n",
+				  ids[idx]->xid.type));
+			ret = NT_STATUS_UNSUCCESSFUL;
+			goto out;
+		}
+
+		if (!fltr_usr || !fltr_grp) {
+			ret = NT_STATUS_NO_MEMORY;
+			goto out;
+		}
+
+		idx++;
+	}
+
+	if (cnt_usr == IDMAP_LDAP_MAX_IDS || (cnt_usr != 0 && !ids[idx])) {
+		const char *attrs[] = { NULL, /* uid or cn */
+					"uidNumber",
+					NULL };
+
+		fltr_usr = talloc_strdup_append(fltr_usr, "))");
+		if (!fltr_usr) {
+			ret = NT_STATUS_NO_MEMORY;
+			goto out;
+		}
+
+		attrs[0] = ctx->user_cn ? "cn" : "uid";
+		ret = ctx->search(ctx, ctx->bind_path_user, fltr_usr, attrs,
+				  &result);
+		if (!NT_STATUS_IS_OK(ret)) {
+			goto out;
+		}
+
+		idmap_rfc2307_map_sid_results(ctx, mem_ctx, &ids[bidx], result,
+					      dom->name, attrs, ID_TYPE_UID);
+		cnt_usr = 0;
+		TALLOC_FREE(fltr_usr);
+	}
+
+	if (cnt_grp == IDMAP_LDAP_MAX_IDS || (cnt_grp != 0 && !ids[idx])) {
+		const char *attrs[] = { "cn", "gidNumber", NULL };
+
+		fltr_grp = talloc_strdup_append(fltr_grp, "))");
+		if (!fltr_grp) {
+			ret = NT_STATUS_NO_MEMORY;
+			goto out;
+		}
+		ret = ctx->search(ctx, ctx->bind_path_group, fltr_grp, attrs,
+				  &result);
+		if (!NT_STATUS_IS_OK(ret)) {
+			goto out;
+		}
+
+		idmap_rfc2307_map_sid_results(ctx, mem_ctx, &ids[bidx], result,
+					      dom->name, attrs, ID_TYPE_GID);
+		cnt_grp = 0;
+		TALLOC_FREE(fltr_grp);
+	}
+
+	if (ids[idx]) {
+		goto again;
+	}
+
+	ret = NT_STATUS_OK;
+
+out:
+	talloc_free(mem_ctx);
+	return ret;
+}
+
+struct idmap_rfc2307_map {
+	struct id_map *map;
+	const char *name;
+	enum id_type type;
+};
+
+/*
+ * Lookup names for SIDS and store the data in the local mapping
+ * array.
+ */
+static NTSTATUS idmap_rfc_2307_sids_to_names(TALLOC_CTX *mem_ctx,
+					     struct id_map **ids,
+					     struct idmap_rfc2307_map *maps,
+					     struct idmap_rfc2307_context *ctx)
+{
+	int i;
+
+	for (i = 0; ids[i]; i++) {
+		const char *domain, *name;
+		enum lsa_SidType lsa_type;
+		struct id_map *id = ids[i];
+		struct idmap_rfc2307_map *map = &maps[i];
+		bool b;
+
+		/* by default calls to winbindd are disabled
+		   the following call will not recurse so this is safe */
+		(void)winbind_on();
+		b = winbind_lookup_sid(mem_ctx, ids[i]->sid, &domain, &name,
+				       &lsa_type);
+		(void)winbind_off();
+
+		if (!b) {
+			DEBUG(1, ("Lookup sid %s failed.\n",
+				  sid_string_dbg(ids[i]->sid)));
+			continue;
+		}
+
+		switch(lsa_type) {
+		case SID_NAME_USER:
+			id->xid.type = map->type = ID_TYPE_UID;
+			if (ctx->user_cn && ctx->cn_realm) {
+				name = talloc_asprintf(mem_ctx, "%s@%s",
+						       name, ctx->realm);
+			}
+			id->xid.type = map->type = ID_TYPE_UID;
+			break;
+
+		case SID_NAME_DOM_GRP:
+		case SID_NAME_ALIAS:
+		case SID_NAME_WKN_GRP:
+			if (ctx->cn_realm) {
+				name = talloc_asprintf(mem_ctx, "%s@%s",
+						       name, ctx->realm);
+			}
+			id->xid.type = map->type = ID_TYPE_GID;
+			break;
+
+		default:
+			DEBUG(1, ("Unknown lsa type %d for sid %s\n",
+				  lsa_type, sid_string_dbg(id->sid)));
+			id->status = ID_UNMAPPED;
+			continue;
+		}
+
+		map->map = id;
+		id->status = ID_UNKNOWN;
+		map->name = strupper_talloc(mem_ctx, name);
+
+		if (!map->name) {
+			return NT_STATUS_NO_MEMORY;
+		}
+	}
+
+	return NT_STATUS_OK;
+}
+
+/*
+ * Find id_map entry by looking up the name in the internal
+ * mapping array.
+ */
+static struct id_map* idmap_rfc2307_find_map(struct idmap_rfc2307_map *maps,
+					     enum id_type type,
+					     const char *name)
+{
+	int i;
+
+	DEBUG(10, ("Looking for name %s, type %d\n", name, type));
+
+	for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
+		if (maps[i].map == NULL) { /* end of the run */
+			return NULL;
+		}
+		DEBUG(10, ("Entry %d: name %s, type %d\n",
+			   i, maps[i].name, maps[i].type));
+		if (type == maps[i].type && strcmp(name, maps[i].name) == 0) {
+			return maps[i].map;
+		}
+	}
+
+	return NULL;
+}
+
+static void idmap_rfc2307_map_xid_results(struct idmap_rfc2307_context *ctx,
+					  TALLOC_CTX *mem_ctx,
+					  struct id_map **ids,
+					  struct idmap_rfc2307_map *maps,
+					  LDAPMessage *result,
+					  struct idmap_domain *dom,
+					  const char **attrs, enum id_type type)
+{
+	int count, i;
+	LDAPMessage *entry;
+
+	count = ldap_count_entries(ctx->ldap, result);
+
+	for (i = 0; i < count; i++) {
+		uint32_t id;
+		char *name;
+		bool b;
+		struct id_map *id_map;
+
+		if (i == 0) {
+			entry = ldap_first_entry(ctx->ldap, result);
+		} else {
+			entry = ldap_next_entry(ctx->ldap, result);
+		}
+		if (!entry) {
+			DEBUG(2, ("Unable to fetch entry.\n"));
+			break;
+		}
+
+		name = smbldap_talloc_single_attribute(ctx->ldap, entry,
+						       attrs[0], mem_ctx);
+		if (!name) {
+			DEBUG(1, ("Could not get user name\n"));
+			continue;
+		}
+
+		b = idmap_rfc2307_get_uint32(ctx->ldap, entry, attrs[1], &id);
+		if (!b) {
+			DEBUG(5, ("Could not pull id for record %s\n", name));
+			continue;
+		}
+
+		if (!idmap_unix_id_is_in_range(id, dom)) {
+			DEBUG(5, ("Requested id (%u) out of range (%u - %u).\n",
+				  id, dom->low_id, dom->high_id));
+			continue;
+		}
+
+		if (!strupper_m(name)) {
+			DEBUG(5, ("Could not convert %s to uppercase\n", name));
+			continue;
+		}
+		id_map = idmap_rfc2307_find_map(maps, type, name);
+		if (!id_map) {
+			DEBUG(0, ("Could not find mapping entry for name %s\n",
+				  name));
+			continue;
+		}
+
+		id_map->xid.id = id;
+		id_map->status = ID_MAPPED;
+	}
+}
+
+/*
+ * Map sids to names and then to unixids.
+ */
+static NTSTATUS idmap_rfc2307_sids_to_unixids(struct idmap_domain *dom,
+					      struct id_map **ids)
+{
+	struct idmap_rfc2307_context *ctx;
+	TALLOC_CTX *mem_ctx;
+	struct idmap_rfc2307_map *int_maps;
+	int cnt_usr = 0, cnt_grp = 0, idx = 0, bidx = 0;
+	char *fltr_usr = NULL, *fltr_grp = NULL;
+	NTSTATUS ret;
+	int i;
+
+	ctx = talloc_get_type(dom->private_data, struct idmap_rfc2307_context);
+	mem_ctx = talloc_new(talloc_tos());
+	if (!mem_ctx) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	if (ctx->check_connection) {
+		ret = ctx->check_connection(dom);
+		if (!NT_STATUS_IS_OK(ret)) {
+			goto out;
+		}
+	}
+
+	for (i = 0; ids[i]; i++);
+	int_maps = talloc_zero_array(mem_ctx, struct idmap_rfc2307_map, i);
+	if (!int_maps) {
+		ret = NT_STATUS_NO_MEMORY;
+		goto out;
+	}
+
+	ret = idmap_rfc_2307_sids_to_names(mem_ctx, ids, int_maps, ctx);
+	if (!NT_STATUS_IS_OK(ret)) {
+		goto out;
+	}
+
+again:
+	if (!fltr_usr) {
+		/* prepare new user query, see getpwuid() in RFC2307 */
+		fltr_usr = talloc_asprintf(mem_ctx,
+					     "(&(objectClass=posixAccount)(|");
+	}
+
+	if (!fltr_grp) {
+		/* prepare new group query, see getgrgid() in RFC2307 */
+		fltr_grp = talloc_asprintf(mem_ctx,
+					     "(&(objectClass=posixGroup)(|");
+	}
+
+	if (!fltr_usr || !fltr_grp) {
+		ret = NT_STATUS_NO_MEMORY;
+		goto out;
+	}
+
+	while (cnt_usr < IDMAP_LDAP_MAX_IDS &&
+	       cnt_grp < IDMAP_LDAP_MAX_IDS && ids[idx]) {
+		struct id_map *id = ids[idx];
+		struct idmap_rfc2307_map *map = &int_maps[idx];
+
+		switch(id->xid.type) {
+		case ID_TYPE_UID:
+			fltr_usr = talloc_asprintf_append_buffer(fltr_usr,
+				     "(%s=%s)", (ctx->user_cn ? "cn" : "uid"),
+				      map->name);
+			cnt_usr++;
+			break;
+
+		case ID_TYPE_GID:
+			fltr_grp = talloc_asprintf_append_buffer(fltr_grp,
+					 "(cn=%s)", map->name);
+			cnt_grp++;
+			break;
+
+		default:
+			DEBUG(10, ("Nothing to do for SID %s, "
+				   "previous name lookup failed\n",
+				   sid_string_dbg(map->map->sid)));
+		}
+
+		if (!fltr_usr || !fltr_grp) {
+			ret = NT_STATUS_NO_MEMORY;
+			goto out;
+		}
+
+		idx++;
+	}
+
+	if (cnt_usr == IDMAP_LDAP_MAX_IDS || (cnt_usr != 0 && !ids[idx])) {
+		const char *attrs[] = { NULL, /* uid or cn */
+					"uidNumber",
+					NULL };
+		LDAPMessage *result;
+
+		fltr_usr = talloc_strdup_append(fltr_usr, "))");
+		if (!fltr_usr) {
+			ret = NT_STATUS_NO_MEMORY;
+			goto out;
+		}
+
+		attrs[0] = ctx->user_cn ? "cn" : "uid";
+		ret = ctx->search(ctx, ctx->bind_path_user, fltr_usr, attrs,
+				  &result);
+		if (!NT_STATUS_IS_OK(ret)) {
+			goto out;
+		}
+
+		idmap_rfc2307_map_xid_results(ctx, mem_ctx, &ids[bidx],
+					      int_maps, result, dom,
+					      attrs, ID_TYPE_UID);
+
+		cnt_usr = 0;
+		TALLOC_FREE(fltr_usr);
+	}
+
+	if (cnt_grp == IDMAP_LDAP_MAX_IDS || (cnt_grp != 0 && !ids[idx])) {
+		const char *attrs[] = {"cn", "gidNumber", NULL };
+		LDAPMessage *result;
+
+		fltr_grp = talloc_strdup_append(fltr_grp, "))");
+		if (!fltr_grp) {
+			ret = NT_STATUS_NO_MEMORY;
+			goto out;
+		}
+
+		ret = ctx->search(ctx, ctx->bind_path_group, fltr_grp, attrs,
+				  &result);
+		if (!NT_STATUS_IS_OK(ret)) {
+			goto out;
+		}
+
+		idmap_rfc2307_map_xid_results(ctx, mem_ctx, &ids[bidx],
+					      int_maps, result, dom,
+					      attrs, ID_TYPE_GID);
+		cnt_grp = 0;
+		TALLOC_FREE(fltr_grp);
+	}
+
+	if (ids[idx]) {
+		goto again;
+	}
+
+	ret = NT_STATUS_OK;
+
+out:
+	talloc_free(mem_ctx);
+	return ret;
+}
+
+static int idmap_rfc2307_context_destructor(struct idmap_rfc2307_context *ctx)
+{
+	if (ctx->ads != NULL) {
+		/* we own this ADS_STRUCT so make sure it goes away */
+		ctx->ads->is_mine = True;
+		ads_destroy( &ctx->ads );
+		ctx->ads = NULL;
+	}
+
+	if (ctx->smbldap_state != NULL) {
+		smbldap_free_struct(&ctx->smbldap_state);
+	}
+
+	return 0;
+}
+
+static NTSTATUS idmap_rfc2307_initialize(struct idmap_domain *domain)
+{
+	struct idmap_rfc2307_context *ctx;
+	char *cfg_opt;
+	const char *bind_path_user, *bind_path_group, *ldap_server;
+	NTSTATUS status;
+
+	ctx = talloc_zero(domain, struct idmap_rfc2307_context);
+	if (ctx == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+	talloc_set_destructor(ctx, idmap_rfc2307_context_destructor);
+
+	cfg_opt = talloc_asprintf(ctx, "idmap config %s", domain->name);
+	if (cfg_opt == NULL) {
+		status = NT_STATUS_NO_MEMORY;
+		goto err;
+	}
+
+	bind_path_user = lp_parm_const_string(-1, cfg_opt, "bind_path_user",
+					      NULL);
+	if (bind_path_user) {
+		ctx->bind_path_user = talloc_strdup(ctx, bind_path_user);
+		if (ctx->bind_path_user == NULL) {
+			status = NT_STATUS_NO_MEMORY;
+			goto err;
+		}
+	} else {
+		status = NT_STATUS_INVALID_PARAMETER;
+		goto err;
+	}
+
+	bind_path_group = lp_parm_const_string(-1, cfg_opt, "bind_path_group",
+					       NULL);
+	if (bind_path_group) {
+		ctx->bind_path_group = talloc_strdup(ctx, bind_path_group);
+		if (ctx->bind_path_group == NULL) {
+			status = NT_STATUS_NO_MEMORY;
+			goto err;
+		}
+	} else {
+		status = NT_STATUS_INVALID_PARAMETER;
+		goto err;
+	}
+
+	ldap_server = lp_parm_const_string(-1, cfg_opt, "ldap_server", NULL);
+	if (!ldap_server) {
+		status = NT_STATUS_INVALID_PARAMETER;
+		goto err;
+	}
+
+	if (strcmp(ldap_server, "stand-alone") == 0) {
+		status = idmap_rfc2307_init_ldap(ctx, domain, cfg_opt);
+
+	} else if (strcmp(ldap_server, "ad") == 0) {
+		status = idmap_rfc2307_init_ads(ctx, cfg_opt);
+
+	} else {
+		status = NT_STATUS_INVALID_PARAMETER;
+	}
+
+	if (!NT_STATUS_IS_OK(status)) {
+		goto err;
+	}
+
+	ctx->cn_realm = lp_parm_bool(-1, cfg_opt, "cn_realm", false);
+	ctx->user_cn = lp_parm_bool(-1, cfg_opt, "user_cn", false);
+
+	domain->private_data = ctx;
+	talloc_free(cfg_opt);
+	return NT_STATUS_OK;
+
+err:
+	talloc_free(cfg_opt);
+	talloc_free(ctx);
+	return status;
+}
+
+static struct idmap_methods rfc2307_methods = {
+	.init = idmap_rfc2307_initialize,
+	.unixids_to_sids = idmap_rfc2307_unixids_to_sids,
+	.sids_to_unixids = idmap_rfc2307_sids_to_unixids,
+};
+
+NTSTATUS idmap_rfc2307_init(void)
+{
+	return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "rfc2307",
+				  &rfc2307_methods);
+}
diff --git a/source3/winbindd/wscript_build b/source3/winbindd/wscript_build
index 7e80727..aacd859 100644
--- a/source3/winbindd/wscript_build
+++ b/source3/winbindd/wscript_build
@@ -1,6 +1,7 @@
 #!/usr/bin/env python
 
 IDMAP_AD_SRC = '''idmap_ad.c'''
+IDMAP_RFC2307_SRC = '''idmap_rfc2307.c'''
 IDMAP_RID_SRC = '''idmap_rid.c'''
 IDMAP_PASSDB_SRC = '''idmap_passdb.c'''
 IDMAP_LDAP_SRC = '''idmap_ldap.c'''
@@ -43,6 +44,15 @@ bld.SAMBA3_MODULE('idmap_ad',
                  internal_module=bld.SAMBA3_IS_STATIC_MODULE('idmap_ad'),
                  enabled=bld.SAMBA3_IS_ENABLED_MODULE('idmap_ad') and bld.CONFIG_SET("HAVE_LDAP"))
 
+bld.SAMBA3_MODULE('idmap_rfc2307',
+                 subsystem='idmap',
+                 allow_undefined_symbols=True,
+                 source=IDMAP_RFC2307_SRC,
+                 init_function='',
+                 deps='ads',
+                 internal_module=bld.SAMBA3_IS_STATIC_MODULE('idmap_rfc2307'),
+                 enabled=bld.SAMBA3_IS_ENABLED_MODULE('idmap_rfc2307') and bld.CONFIG_SET("HAVE_LDAP"))
+
 bld.SAMBA3_MODULE('idmap_rid',
                  subsystem='idmap',
                  allow_undefined_symbols=True,
diff --git a/source3/wscript b/source3/wscript
index 7a99dc1..9424b1c 100644
--- a/source3/wscript
+++ b/source3/wscript
@@ -1693,7 +1693,7 @@ main() {
 				      vfs_commit
                                       vfs_crossrename vfs_linux_xfs_sgid
                                       vfs_time_audit idmap_autorid idmap_tdb2
-                                      idmap_rid idmap_hash'''))
+                                      idmap_rid idmap_hash idmap_rfc2307'''))
 
     if Options.options.developer:
         default_static_modules.extend(TO_LIST('charset_weird'))
-- 
1.7.1


>From cf8085bcdfe7abc6284bce098463b985a9ef8378 Mon Sep 17 00:00:00 2001
From: Christof Schmitt <christof.schmitt at us.ibm.com>
Date: Thu, 21 Feb 2013 12:32:54 -0700
Subject: [PATCH 07/10] s3-docs: Add manpage for idmap_rfc2307 module

---
 docs-xml/manpages/idmap_rfc2307.8.xml |  165 +++++++++++++++++++++++++++++++++
 docs-xml/wscript_build                |    1 +
 2 files changed, 166 insertions(+), 0 deletions(-)
 create mode 100644 docs-xml/manpages/idmap_rfc2307.8.xml

diff --git a/docs-xml/manpages/idmap_rfc2307.8.xml b/docs-xml/manpages/idmap_rfc2307.8.xml
new file mode 100644
index 0000000..f680945
--- /dev/null
+++ b/docs-xml/manpages/idmap_rfc2307.8.xml
@@ -0,0 +1,165 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">
+<refentry id="idmap_rfc2307.8">
+
+<refmeta>
+	<refentrytitle>idmap_rfc2307</refentrytitle>
+	<manvolnum>8</manvolnum>
+	<refmiscinfo class="source">Samba</refmiscinfo>
+	<refmiscinfo class="manual">System Administration tools</refmiscinfo>
+	<refmiscinfo class="version">4.0</refmiscinfo>
+</refmeta>
+
+<refnamediv>
+	<refname>idmap_rfc2307</refname>
+	<refpurpose>Samba's idmap_rfc2307 Backend for Winbind</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv>
+	<title>DESCRIPTION</title>
+
+	<para>The idmap_rfc2307 plugin provides a way for winbind to
+	read id mappings from records in an LDAP server as defined in
+	RFC 2307. The LDAP server can be stand-alone or the LDAP
+	server provided by the AD server. An AD server is always
+	required to provide the mapping between name and SID, and the
+	LDAP server is queried for the mapping between name and
+	uid/gid. This module implements only the "idmap"
+	API, and is READONLY.</para>
+
+	<para>Mappings must be provided in advance by the
+	administrator by creating the user accounts in the Active
+	Directory server and the posixAccount and posixGroup objects
+	in the LDAP server. The names in the Active Directory server
+	and in the LDAP server have to be the same.</para>
+
+	<para>This id mapping approach allows the reuse of existing
+	LDAP authentication servers that store records in the RFC 2307
+	format.</para>
+</refsynopsisdiv>
+
+<refsect1>
+	<title>IDMAP OPTIONS</title>
+
+	<variablelist>
+		<varlistentry>
+			<term>range = low - high</term>
+			<listitem><para> Defines the available
+			matching UID and GID range for which the
+			backend is authoritative. Note that the range
+			acts as a filter. If specified any UID or GID
+			stored in AD that fall outside the range is
+			ignored and the corresponding map is
+			discarded. It is intended as a way to avoid
+			accidental UID/GID overlaps between local and
+			remotely defined IDs.</para></listitem>
+		</varlistentry>
+		<varlistentry>
+			<term>ldap_server = <ad | stand-alone ></term>
+			<listitem><para>Defines the type of LDAP
+			server to use. This can either be the LDAP
+			server provided by the Active Directory server
+			(ad) or a stand-alone LDAP
+			server.</para></listitem>
+		</varlistentry>
+		<varlistentry>
+			<term>bind_path_user</term>
+			<listitem><para>Specifies the bind path where
+			user objects can be found in the LDAP
+			server.</para></listitem>
+		</varlistentry>
+		<varlistentry>
+			<term>bind_path_group</term>
+			<listitem><para>Specifies the bind path where
+			group objects can be found in the LDAP
+			server.</para></listitem>
+		</varlistentry>
+		<varlistentry>
+			<term>user_cn = <yes | no></term>
+			<listitem><para>Query cn attribute instead of
+			uid attribute for the user name in LDAP. This
+			option is not required, the default is
+			no.</para></listitem>
+		</varlistentry>
+		<varlistentry>
+			<term>cn_realm = <yes | no></term>
+			<listitem><para>Append @realm to cn for groups
+			(and users if user_cn is set) in
+			LDAP. This option is not required, the default
+			is no.</para></listitem>
+		</varlistentry>
+		<varlistentry>
+			<term>ldap_domain</term>
+			<listitem><para>When using the LDAP server in
+			the Active Directory server, this allows to
+			specify the domain where to access the Active
+			Directory server. This allows using trust
+			relationships while keeping all RFC 2307
+			records in one place. This parameter is
+			optional, the default is to access the AD
+			server in the current domain to query LDAP
+			records.</para></listitem>
+		</varlistentry>
+		<varlistentry>
+			<term>ldap_url</term>
+			<listitem><para>When using a stand-alone LDAP
+			server, this parameter specifies the ldap URL
+			for accessing the LDAP
+			server.</para></listitem>
+		</varlistentry>
+		<varlistentry>
+			<term>ldap_user_dn</term>
+			<listitem><para>Defines the user DN to be used
+			for authentication.  The secret for
+			authenticating this user should be stored with
+			net idmap secret (see
+			<citerefentry><refentrytitle>net</refentrytitle>
+			<manvolnum>8</manvolnum></citerefentry>). If
+			absent, an anonymous bind will be
+			performed.</para></listitem>
+		</varlistentry>
+		<varlistentry>
+			<term>ldap_realm</term>
+			<listitem><para>Defines the realm to use in
+			the user and group names. This is only
+			required when using cn_realm together with a
+			stand-alone ldap server.</para></listitem>
+		</varlistentry>
+	</variablelist>
+</refsect1>
+
+<refsect1>
+	<title>EXAMPLES</title>
+
+	<para>The following example shows how to retrieve id mappings
+	from a stand-alone LDAP server.  This example also shows how
+	to leave a small non conflicting range for local id allocation
+	that may be used in internal backends like BUILTIN.</para>
+
+	<programlisting>
+	[global]
+	idmap config * : backend = tdb
+	idmap config * : range = 1000000-1999999
+
+	idmap config DOMAIN : backend = rfc2307
+	idmap config DOMAIN : range = 2000000-2999999
+	idmap config DOMAIN : ldap_server = stand-alone
+	idmap config DOMAIN : ldap_url = ldap://ldap1.example.com
+	idmap config DOMAIN : ldap_user_dn = cn=ldapmanager,dc=example,dc=com
+	idmap config DOMAIN : bind_path_user = ou=People,dc=example,dc=com
+	idmap config DOMAIN : bind_path_group = ou=Group,dc=example,dc=com
+	</programlisting>
+</refsect1>
+
+<refsect1>
+	<title>AUTHOR</title>
+
+	<para>
+	The original Samba software and related utilities
+	were created by Andrew Tridgell. Samba is now developed
+	by the Samba Team as an Open Source project similar
+	to the way the Linux kernel is developed.
+	</para>
+</refsect1>
+
+</refentry>
diff --git a/docs-xml/wscript_build b/docs-xml/wscript_build
index 25e381e..0c6d4a4 100644
--- a/docs-xml/wscript_build
+++ b/docs-xml/wscript_build
@@ -12,6 +12,7 @@ manpages='''
          manpages/idmap_hash.8
          manpages/idmap_ldap.8
          manpages/idmap_nss.8
+         manpages/idmap_rfc2307.8
          manpages/idmap_rid.8
          manpages/idmap_tdb.8
          manpages/idmap_tdb2.8
-- 
1.7.1


>From 0a1037429476a1405023f6bf7586775051aa82f4 Mon Sep 17 00:00:00 2001
From: Christof Schmitt <christof.schmitt at us.ibm.com>
Date: Thu, 21 Feb 2013 12:33:13 -0700
Subject: [PATCH 08/10] s3-net: Allow setting the ldap password for idmap_rfc2307

---
 source3/utils/net_idmap.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/source3/utils/net_idmap.c b/source3/utils/net_idmap.c
index bdc4879..fbeca3e 100644
--- a/source3/utils/net_idmap.c
+++ b/source3/utils/net_idmap.c
@@ -634,9 +634,11 @@ static int net_idmap_secret(struct net_context *c, int argc, const char **argv)
 	backend = talloc_strdup(ctx, lp_parm_const_string(-1, opt, "backend", "tdb"));
 	ALLOC_CHECK(backend);
 
-	if ( ( ! backend) || ( ! strequal(backend, "ldap"))) {
+	if ((!backend) || (!strequal(backend, "ldap") &&
+			   !strequal(backend, "rfc2307"))) {
 		d_fprintf(stderr,
-			  _("The only currently supported backend is LDAP\n"));
+			  _("The only currently supported backend are LDAP "
+			    "and rfc2307\n"));
 		talloc_free(ctx);
 		return -1;
 	}
-- 
1.7.1


>From 904fa4ea323317a02746cac445a4699b57178f4a Mon Sep 17 00:00:00 2001
From: Christof Schmitt <christof.schmitt at us.ibm.com>
Date: Thu, 21 Feb 2013 12:33:19 -0700
Subject: [PATCH 09/10] packaging(RHEL-CTDB): Add idmap_rfc2307 module

---
 packaging/RHEL-CTDB/configure.rpm |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/packaging/RHEL-CTDB/configure.rpm b/packaging/RHEL-CTDB/configure.rpm
index f16b352..398a3f9 100755
--- a/packaging/RHEL-CTDB/configure.rpm
+++ b/packaging/RHEL-CTDB/configure.rpm
@@ -24,7 +24,7 @@ else
 	CC="gcc"
 fi
 
-shared_modules="idmap_rid,idmap_ad,idmap_tdb2"
+shared_modules="idmap_rid,idmap_ad,idmap_tdb2,idmap_rfc2307"
 
 if test "x$BUILD_GPFS" != "xno"; then
 	shared_modules="${shared_modules},vfs_gpfs,vfs_tsmsm"
-- 
1.7.1


>From 586fffe5f62ed32bf11e9d93eb550689e6e30740 Mon Sep 17 00:00:00 2001
From: Christof Schmitt <christof.schmitt at us.ibm.com>
Date: Thu, 21 Feb 2013 12:33:23 -0700
Subject: [PATCH 10/10] Add testcase for idmap_rfc2307 module

Create a new test environment with 'idmap config DOMAIN : backend =
rfc2307'. A new test script adds LDAP records and queries them again for
the mapped uid and gid.
---
 nsswitch/tests/test_idmap_rfc2307.sh |   94 ++++++++++++++++++++++++++++++++++
 selftest/target/Samba.pm             |    1 +
 selftest/target/Samba3.pm            |   79 ++++++++++++++++++++++++++++
 selftest/target/Samba4.pm            |    6 ++
 source3/selftest/tests.py            |    6 ++-
 5 files changed, 185 insertions(+), 1 deletions(-)
 create mode 100755 nsswitch/tests/test_idmap_rfc2307.sh

diff --git a/nsswitch/tests/test_idmap_rfc2307.sh b/nsswitch/tests/test_idmap_rfc2307.sh
new file mode 100755
index 0000000..b9efd34
--- /dev/null
+++ b/nsswitch/tests/test_idmap_rfc2307.sh
@@ -0,0 +1,94 @@
+#!/bin/sh
+# Test id mapping through idmap_rfc2307 module
+if [ $# -lt 9 ]; then
+	echo Usage: $0 DOMAIN USERNAME UID GROUPNAME GID LDAPPREFIX DC_SERVER DC_USERNAME DC_PASSWORD
+	exit 1
+fi
+
+DOMAIN="$1"
+USERNAME="$2"
+USERUID="$3"
+GROUPNAME="$4"
+GROUPGID="$5"
+LDAPPREFIX="$6"
+DC_SERVER="$7"
+DC_USERNAME="$8"
+DC_PASSWORD="$9"
+
+echo called with: $1 $2 $3 $4 $5 $6 $7 $8 $9
+
+wbinfo="$VALGRIND $BINDIR/wbinfo"
+ldbadd="$BINDIR/ldbadd"
+ldbdel="$BINDIR/ldbdel"
+failed=0
+
+. `dirname $0`/../../testprogs/blackbox/subunit.sh
+
+# Delete LDAP records
+$VALGRIND $ldbdel -H ldap://$DC_SERVER -U$DOMAIN/$DC_USERNAME%$DC_PASSWORD "cn=$USERNAME,$LDAPPREFIX"
+$VALGRIND $ldbdel -H ldap://$DC_SERVER -U$DOMAIN/$DC_USERNAME%$DC_PASSWORD "cn=$GROUPNAME,$LDAPPREFIX"
+$VALGRIND $ldbdel -H ldap://$DC_SERVER -U$DOMAIN/$DC_USERNAME%$DC_PASSWORD "$LDAPPREFIX"
+
+# Add id mapping information to LDAP
+
+cat > $PREFIX/tmpldb <<EOF
+dn: $LDAPPREFIX
+objectclass: organizationalUnit
+EOF
+
+testit "add ldap prefix" $VALGRIND $ldbadd -H ldap://$DC_SERVER -U$DOMAIN/$DC_USERNAME%$DC_PASSWORD $PREFIX/tmpldb
+
+cat > $PREFIX/tmpldb <<EOF
+dn: cn=$USERNAME,$LDAPPREFIX
+objectClass: organizationalPerson
+objectClass: posixAccount
+ou: People
+cn: $USERNAME
+uid: $USERNAME
+uidNumber: $USERUID
+gidNumber: 1
+homeDirectory: /home/admin
+EOF
+
+testit "add ldap user mapping record" $VALGRIND $ldbadd -H ldap://$DC_SERVER -U$DOMAIN/$DC_USERNAME%$DC_PASSWORD $PREFIX/tmpldb
+
+cat > $PREFIX/tmpldb <<EOF
+dn: cn=$GROUPNAME,$LDAPPREFIX
+objectClass: posixGroup
+objectClass: groupOfNames
+cn: $GROUPNAME
+gidNumber: $GROUPGID
+member: cn=$USERNAME,$LDAPPREFIX
+EOF
+
+testit "add ldap group mapping record" $VALGRIND $ldbadd -H ldap://$DC_SERVER -U$DOMAIN/$DC_USERNAME%$DC_PASSWORD $PREFIX/tmpldb
+
+rm -f $PREFIX/tmpldbmodify
+
+testit "wbinfo --name-to-sid" $wbinfo --name-to-sid "$DOMAIN\\$USERNAME" || failed=$(expr $failed + 1)
+user_sid=$($wbinfo -n "$DOMAIN\\$USERNAME" | cut -d " " -f1)
+echo "$DOMAIN\\$USERNAME resolved to $user_sid"
+
+testit "wbinfo --sid-to-uid=$user_sid" $wbinfo --sid-to-uid=$user_sid || failed=$(expr $failed + 1)
+user_uid=$($wbinfo --sid-to-uid=$user_sid | cut -d " " -f1)
+echo "$DOMAIN\\$USERNAME resolved to $user_uid"
+
+testit "test $user_uid -eq $USERUID" test $user_uid -eq $USERUID || failed=$(expr $failed + 1)
+
+# Not sure how to get group names with spaces to resolve through testit
+#testit "wbinfo --name-to-sid" $wbinfo --name-to-sid="$DOMAIN\\$GROUPNAME" || failed=$(expr $failed + 1)
+group_sid=$($wbinfo --name-to-sid="$DOMAIN\\$GROUPNAME" | cut -d " " -f1)
+echo "$DOMAIN\\$GROUPNAME resolved to $group_sid"
+
+testit "wbinfo --sid-to-gid=$group_sid" $wbinfo --sid-to-gid=$group_sid || failed=$(expr $failed + 1)
+group_gid=$($wbinfo --sid-to-gid=$group_sid | cut -d " " -f1)
+echo "$DOMAIN\\$GROUPNAME resolved to $group_gid"
+
+testit "test $group_gid -eq $GROUPGID" test $group_gid -eq $GROUPGID || failed=$(expr $failed + 1)
+
+# Delete LDAP records
+$VALGRIND $ldbdel -H ldap://$DC_SERVER -U$DOMAIN/$DC_USERNAME%$DC_PASSWORD "cn=$USERNAME,$LDAPPREFIX"
+$VALGRIND $ldbdel -H ldap://$DC_SERVER -U$DOMAIN/$DC_USERNAME%$DC_PASSWORD "cn=$GROUPNAME,$LDAPPREFIX"
+$VALGRIND $ldbdel -H ldap://$DC_SERVER -U$DOMAIN/$DC_USERNAME%$DC_PASSWORD "$LDAPPREFIX"
+
+exit $failed
diff --git a/selftest/target/Samba.pm b/selftest/target/Samba.pm
index d811053..fc81629 100644
--- a/selftest/target/Samba.pm
+++ b/selftest/target/Samba.pm
@@ -171,6 +171,7 @@ sub get_interface($)
     $interfaces{"localsubdc"} = 31;
     $interfaces{"chgdcpass"} = 32;
     $interfaces{"promotedvdc"} = 33;
+    $interfaces{"s3member_rfc2307"} = 34;
 
     # update lib/socket_wrapper/socket_wrapper.c
     #  #define MAX_WRAPPED_INTERFACES 32
diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index c71419d..31a6f0c 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -331,6 +331,85 @@ sub setup_admember($$$$)
 	return $ret;
 }
 
+sub setup_admember_rfc2307($$$$)
+{
+	my ($self, $prefix, $dcvars) = @_;
+
+	# If we didn't build with ADS, pretend this env was never available
+	if (not $self->have_ads()) {
+	        return "UNKNOWN";
+	}
+
+	print "PROVISIONING S3 AD MEMBER...";
+
+	my $member_options = "
+	security = ads
+	server signing = on
+        workgroup = $dcvars->{DOMAIN}
+        realm = $dcvars->{REALM}
+        idmap config $dcvars->{DOMAIN} : backend = rfc2307
+        idmap config $dcvars->{DOMAIN} : range = 2000000-2999999
+        idmap config $dcvars->{DOMAIN} : ldap_server = ad
+        idmap config $dcvars->{DOMAIN} : bind_path_user = ou=idmap,dc=samba,dc=example,dc=com
+        idmap config $dcvars->{DOMAIN} : bind_path_group = ou=idmap,dc=samba,dc=example,dc=com
+";
+
+	my $ret = $self->provision($prefix,
+				   "LOCALADMEMBER",
+				   "loCalMemberPass",
+				   $member_options);
+
+	$ret or return undef;
+
+	close(USERMAP);
+	$ret->{DOMAIN} = $dcvars->{DOMAIN};
+	$ret->{REALM} = $dcvars->{REALM};
+
+	my $ctx;
+	my $prefix_abs = abs_path($prefix);
+	$ctx = {};
+	$ctx->{krb5_conf} = "$prefix_abs/lib/krb5.conf";
+	$ctx->{domain} = $dcvars->{DOMAIN};
+	$ctx->{realm} = $dcvars->{REALM};
+	$ctx->{dnsname} = lc($dcvars->{REALM});
+	$ctx->{kdc_ipv4} = $dcvars->{SERVER_IP};
+	Samba::mk_krb5_conf($ctx, "");
+
+	$ret->{KRB5_CONFIG} = $ctx->{krb5_conf};
+
+	my $net = Samba::bindir_path($self, "net");
+	my $cmd = "";
+	$cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
+	$cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
+	$cmd .= "$net join $ret->{CONFIGURATION}";
+	$cmd .= " -U$dcvars->{USERNAME}\%$dcvars->{PASSWORD}";
+
+	if (system($cmd) != 0) {
+	    warn("Join failed\n$cmd");
+	    return undef;
+	}
+
+	# We need world access to this share, as otherwise the domain
+	# administrator from the AD domain provided by Samba4 can't
+	# access the share for tests.
+	chmod 0777, "$prefix/share";
+
+	if (not $self->check_or_start($ret, "yes", "yes", "yes")) {
+		return undef;
+	}
+
+	$ret->{DC_SERVER} = $dcvars->{SERVER};
+	$ret->{DC_SERVER_IP} = $dcvars->{SERVER_IP};
+	$ret->{DC_NETBIOSNAME} = $dcvars->{NETBIOSNAME};
+	$ret->{DC_USERNAME} = $dcvars->{USERNAME};
+	$ret->{DC_PASSWORD} = $dcvars->{PASSWORD};
+
+	# Special case, this is called from Samba4.pm but needs to use the Samba3 check_env and get_log_env
+	$ret->{target} = $self;
+
+	return $ret;
+}
+
 sub setup_simpleserver($$)
 {
 	my ($self, $path) = @_;
diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm
index e9e0037..090be04 100644
--- a/selftest/target/Samba4.pm
+++ b/selftest/target/Samba4.pm
@@ -1661,6 +1661,12 @@ sub setup_env($$$)
 		return $target3->setup_admember("$path/s3member", $self->{vars}->{dc}, 29);
 	} elsif ($envname eq "plugin_s4_dc") {
 		return $self->setup_plugin_s4_dc("$path/plugin_s4_dc");
+	} elsif ($envname eq "s3member_rfc2307") {
+		if (not defined($self->{vars}->{dc})) {
+			$self->setup_dc("$path/dc");
+		}
+		return $target3->setup_admember_rfc2307("$path/s3member",
+							$self->{vars}->{dc}, 34);
 	} else {
 		return "UNKNOWN";
 	}
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index 44efe18..740bd4a 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -278,6 +278,8 @@ local = ["local.nss-wrapper", "local.ndr"]
 
 winbind = ["winbind.struct", "winbind.wbclient", "winbind.pac"]
 
+idmap = [ "idmap.rfc2307" ]
+
 rap = ["rap.basic", "rap.rpc", "rap.printing", "rap.sam"]
 
 unix = ["unix.info2", "unix.whoami"]
@@ -286,7 +288,7 @@ nbt = ["nbt.dgram" ]
 
 libsmbclient = ["libsmbclient"]
 
-tests= base + raw + smb2 + rpc + unix + local + winbind + rap + nbt + libsmbclient
+tests= base + raw + smb2 + rpc + unix + local + winbind + rap + nbt + libsmbclient + idmap
 
 for t in tests:
     if t == "base.delaywrite":
@@ -338,6 +340,8 @@ for t in tests:
         plansmbtorture4testsuite(t, "s3dc", '//$SERVER_IP/valid-users-tmp -U$USERNAME%$PASSWORD')
         plansmbtorture4testsuite(t, "s3dc", '//$SERVER_IP/write-list-tmp -U$USERNAME%$PASSWORD')
         plansmbtorture4testsuite(t, "plugin_s4_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD')
+    elif t == "idmap.rfc2307":
+        plantestsuite(t, "s3member_rfc2307", [os.path.join(samba3srcdir, "../nsswitch/tests/test_idmap_rfc2307.sh"), '$DOMAIN', 'Administrator', '2000000', '"Domain Users"', '2000001', 'ou=idmap,dc=samba,dc=example,dc=com', '$DC_SERVER', '$DC_USERNAME', '$DC_PASSWORD'])
     else:
         plansmbtorture4testsuite(t, "s3dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD')
         plansmbtorture4testsuite(t, "plugin_s4_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD')
-- 
1.7.1



More information about the samba-technical mailing list