svn commit: samba r26192 - in branches/SAMBA_4_0: source/dsdb/samdb/ldb_modules source/lib/ldb/common source/libcli/ldap testprogs/blackbox

abartlet at samba.org abartlet at samba.org
Thu Nov 29 08:00:06 GMT 2007


Author: abartlet
Date: 2007-11-29 08:00:04 +0000 (Thu, 29 Nov 2007)
New Revision: 26192

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=26192

Log:
Handle, test and implement the style of extended_dn requiest that MMC uses.

It appears that the control value is optional, implying type 0 responses. 

Failing to parse this was causing LDAP disconnects with 'unavailable
critical extension'.

Andrew Bartlett

Modified:
   branches/SAMBA_4_0/source/dsdb/samdb/ldb_modules/extended_dn.c
   branches/SAMBA_4_0/source/lib/ldb/common/ldb_controls.c
   branches/SAMBA_4_0/source/libcli/ldap/ldap.c
   branches/SAMBA_4_0/source/libcli/ldap/ldap.h
   branches/SAMBA_4_0/source/libcli/ldap/ldap_client.c
   branches/SAMBA_4_0/source/libcli/ldap/ldap_controls.c
   branches/SAMBA_4_0/testprogs/blackbox/test_ldb.sh


Changeset:
Modified: branches/SAMBA_4_0/source/dsdb/samdb/ldb_modules/extended_dn.c
===================================================================
--- branches/SAMBA_4_0/source/dsdb/samdb/ldb_modules/extended_dn.c	2007-11-29 01:36:41 UTC (rev 26191)
+++ branches/SAMBA_4_0/source/dsdb/samdb/ldb_modules/extended_dn.c	2007-11-29 08:00:04 UTC (rev 26192)
@@ -104,35 +104,58 @@
 	const struct ldb_val *val;
 	struct GUID guid;
 	struct dom_sid *sid;
+	const DATA_BLOB *guid_blob;
+	const DATA_BLOB *sid_blob;
 	char *object_guid;
 	char *object_sid;
 	char *new_dn;
 
-	/* retrieve object_guid */
-	guid = samdb_result_guid(msg, "objectGUID");
-	object_guid = GUID_string(msg, &guid);
-	if (!object_guid)
+	guid_blob = ldb_msg_find_ldb_val(msg, "objectGUID");
+	sid_blob = ldb_msg_find_ldb_val(msg, "objectSID");
+
+	if (!guid_blob)
 		return false;
 
-	if (remove_guid)
-		ldb_msg_remove_attr(msg, "objectGUID");
-
-	/* retrieve object_sid */
-	object_sid = NULL;
-	sid = samdb_result_dom_sid(msg, msg, "objectSID");
-	if (sid) {
-		object_sid = dom_sid_string(msg, sid);
-		if (!object_sid)
-			return false;
-
-		if (remove_sid)
-			ldb_msg_remove_attr(msg, "objectSID");
-	}
-
-	/* TODO: handle type */
 	switch (type) {
 		case 0:
+			/* return things in hexadecimal format */
+			if (sid_blob) {
+				const char *lower_guid_hex = strlower_talloc(msg, data_blob_hex_string(msg, guid_blob));
+				const char *lower_sid_hex = strlower_talloc(msg, data_blob_hex_string(msg, sid_blob));
+				if (!lower_guid_hex || !lower_sid_hex) {
+					return false;
+				}
+				new_dn = talloc_asprintf(msg, "<GUID=%s>;<SID=%s>;%s",
+							 lower_guid_hex, 
+							 lower_sid_hex,
+							 ldb_dn_get_linearized(msg->dn));
+			} else {
+				const char *lower_guid_hex = strlower_talloc(msg, data_blob_hex_string(msg, guid_blob));
+				if (!lower_guid_hex) {
+					return false;
+				}
+				new_dn = talloc_asprintf(msg, "<GUID=%s>;%s",
+							 lower_guid_hex, 
+							 ldb_dn_get_linearized(msg->dn));
+			}
+
+			break;
 		case 1:
+			/* retrieve object_guid */
+			guid = samdb_result_guid(msg, "objectGUID");
+			object_guid = GUID_string(msg, &guid);
+			
+			/* retrieve object_sid */
+			object_sid = NULL;
+			sid = samdb_result_dom_sid(msg, msg, "objectSID");
+			if (sid) {
+				object_sid = dom_sid_string(msg, sid);
+				if (!object_sid)
+					return false;
+				
+			}
+			
+			/* Normal, sane format */
 			if (object_sid) {
 				new_dn = talloc_asprintf(msg, "<GUID=%s>;<SID=%s>;%s",
 							 object_guid, object_sid,
@@ -147,9 +170,18 @@
 			return false;
 	}
 
-	if (!new_dn)
+	if (!new_dn) {
 		return false;
+	}
 
+	if (remove_guid) {
+		ldb_msg_remove_attr(msg, "objectGUID");
+	}
+
+	if (sid_blob && remove_sid) {
+		ldb_msg_remove_attr(msg, "objectSID");
+	}
+
 	msg->dn = ldb_dn_new(msg, ldb, new_dn);
 	if (! ldb_dn_validate(msg->dn))
 		return false;
@@ -201,7 +233,7 @@
 static int extended_search(struct ldb_module *module, struct ldb_request *req)
 {
 	struct ldb_control *control;
-	struct ldb_extended_dn_control *extended_ctrl;
+	struct ldb_extended_dn_control *extended_ctrl = NULL;
 	struct ldb_control **saved_controls;
 	struct extended_context *ac;
 	struct ldb_request *down_req;
@@ -215,9 +247,11 @@
 		return ldb_next_request(module, req);
 	}
 
-	extended_ctrl = talloc_get_type(control->data, struct ldb_extended_dn_control);
-	if (!extended_ctrl) {
-		return LDB_ERR_PROTOCOL_ERROR;
+	if (control->data) {
+		extended_ctrl = talloc_get_type(control->data, struct ldb_extended_dn_control);
+		if (!extended_ctrl) {
+			return LDB_ERR_PROTOCOL_ERROR;
+		}
 	}
 
 	ac = talloc(req, struct extended_context);
@@ -231,7 +265,11 @@
 	ac->attrs = req->op.search.attrs;
 	ac->remove_guid = false;
 	ac->remove_sid = false;
-	ac->extended_type = extended_ctrl->type;
+	if (extended_ctrl) {
+		ac->extended_type = extended_ctrl->type;
+	} else {
+		ac->extended_type = 0;
+	}
 
 	down_req = talloc_zero(req, struct ldb_request);
 	if (down_req == NULL) {

Modified: branches/SAMBA_4_0/source/lib/ldb/common/ldb_controls.c
===================================================================
--- branches/SAMBA_4_0/source/lib/ldb/common/ldb_controls.c	2007-11-29 01:36:41 UTC (rev 26191)
+++ branches/SAMBA_4_0/source/lib/ldb/common/ldb_controls.c	2007-11-29 08:00:04 UTC (rev 26192)
@@ -291,12 +291,22 @@
 			p = &(control_strings[i][12]);
 			ret = sscanf(p, "%d:%d", &crit, &type);
 			if ((ret != 2) || (crit < 0) || (crit > 1) || (type < 0) || (type > 1)) {
-				error_string = talloc_asprintf(mem_ctx, "invalid extended_dn control syntax\n");
-				error_string = talloc_asprintf_append(error_string, " syntax: crit(b):type(b)\n");
-				error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
-				ldb_set_errstring(ldb, error_string);
-				talloc_free(error_string);
-				return NULL;
+				ret = sscanf(p, "%d", &crit);
+				if ((ret != 1) || (crit < 0) || (crit > 1)) {
+					error_string = talloc_asprintf(mem_ctx, "invalid extended_dn control syntax\n");
+					error_string = talloc_asprintf_append(error_string, " syntax: crit(b)[:type(i)]\n");
+					error_string = talloc_asprintf_append(error_string, "   note: b = boolean\n");
+					error_string = talloc_asprintf_append(error_string, "         i = integer\n");
+					error_string = talloc_asprintf_append(error_string, "   valid values are: 0 - hexadecimal representation\n");
+					error_string = talloc_asprintf_append(error_string, "                     1 - normal string representation");
+					ldb_set_errstring(ldb, error_string);
+					talloc_free(error_string);
+					return NULL;
+				}
+				control = NULL;
+			} else {
+				control = talloc(ctrl, struct ldb_extended_dn_control);
+				control->type = type;
 			}
 
 			ctrl[i] = talloc(ctrl, struct ldb_control);
@@ -306,9 +316,7 @@
 			}
 			ctrl[i]->oid = LDB_CONTROL_EXTENDED_DN_OID;
 			ctrl[i]->critical = crit;
-			control = talloc(ctrl[i], struct ldb_extended_dn_control);
-			control->type = type;
-			ctrl[i]->data = control;
+			ctrl[i]->data = talloc_steal(ctrl[i], control);
 
 			continue;
 		}

Modified: branches/SAMBA_4_0/source/libcli/ldap/ldap.c
===================================================================
--- branches/SAMBA_4_0/source/libcli/ldap/ldap.c	2007-11-29 01:36:41 UTC (rev 26191)
+++ branches/SAMBA_4_0/source/libcli/ldap/ldap.c	2007-11-29 08:00:04 UTC (rev 26192)
@@ -1325,10 +1325,12 @@
 	}
 
 	msg->controls = NULL;
+	msg->controls_decoded = NULL;
 
 	if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
 		int i = 0;
 		struct ldb_control **ctrl = NULL;
+		bool *decoded = NULL;
 
 		asn1_start_tag(data, ASN1_CONTEXT(0));
 
@@ -1341,6 +1343,11 @@
 				return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
 			}
 
+			decoded = talloc_realloc(msg, decoded, bool, i+1);
+			if (!decoded) {
+				return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
+			}
+
 			ctrl[i] = talloc(ctrl, struct ldb_control);
 			if (!ctrl[i]) {
 				return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
@@ -1352,12 +1359,15 @@
 			
 			if (!ldap_decode_control_value(ctrl, value, ctrl[i])) {
 				if (ctrl[i]->critical) {
-					return NT_STATUS_LDAP(LDAP_UNAVAILABLE_CRITICAL_EXTENSION);
+					ctrl[i]->data = NULL;
+					decoded[i] = false;
+					i++;
 				} else {
 					talloc_free(ctrl[i]);
 					ctrl[i] = NULL;
 				}
 			} else {
+				decoded[i] = true;
 				i++;
 			}
 		}
@@ -1367,6 +1377,7 @@
 		}
 
 		msg->controls = ctrl;
+		msg->controls_decoded = decoded;
 
 		asn1_end_tag(data);
 	}

Modified: branches/SAMBA_4_0/source/libcli/ldap/ldap.h
===================================================================
--- branches/SAMBA_4_0/source/libcli/ldap/ldap.h	2007-11-29 01:36:41 UTC (rev 26191)
+++ branches/SAMBA_4_0/source/libcli/ldap/ldap.h	2007-11-29 08:00:04 UTC (rev 26192)
@@ -240,11 +240,13 @@
 	struct ldap_ExtendedResponse 	ExtendedResponse;
 };
 
+
 struct ldap_message {
 	int                     messageid;
 	enum ldap_request_tag   type;
 	union ldap_Request      r;
 	struct ldb_control    **controls;
+	bool                   *controls_decoded;
 };
 
 struct event_context;

Modified: branches/SAMBA_4_0/source/libcli/ldap/ldap_client.c
===================================================================
--- branches/SAMBA_4_0/source/libcli/ldap/ldap_client.c	2007-11-29 01:36:41 UTC (rev 26191)
+++ branches/SAMBA_4_0/source/libcli/ldap/ldap_client.c	2007-11-29 08:00:04 UTC (rev 26192)
@@ -116,6 +116,7 @@
 static void ldap_match_message(struct ldap_connection *conn, struct ldap_message *msg)
 {
 	struct ldap_request *req;
+	int i;
 
 	for (req=conn->pending; req; req=req->next) {
 		if (req->messageid == msg->messageid) break;
@@ -132,6 +133,20 @@
 		return;
 	}
 
+	/* Check for undecoded critical extensions */
+	for (i=0; msg->controls && msg->controls[i]; i++) {
+		if (!msg->controls_decoded[i] && 
+		    msg->controls[i]->critical) {
+			req->status = NT_STATUS_LDAP(LDAP_UNAVAILABLE_CRITICAL_EXTENSION);
+			req->state = LDAP_REQUEST_DONE;
+			DLIST_REMOVE(conn->pending, req);
+			if (req->async.fn) {
+				req->async.fn(req);
+			}
+			return;
+		}
+	}
+
 	/* add to the list of replies received */
 	talloc_steal(req, msg);
 	req->replies = talloc_realloc(req, req->replies, 

Modified: branches/SAMBA_4_0/source/libcli/ldap/ldap_controls.c
===================================================================
--- branches/SAMBA_4_0/source/libcli/ldap/ldap_controls.c	2007-11-29 01:36:41 UTC (rev 26191)
+++ branches/SAMBA_4_0/source/libcli/ldap/ldap_controls.c	2007-11-29 08:00:04 UTC (rev 26192)
@@ -156,9 +156,16 @@
 
 static bool decode_extended_dn_request(void *mem_ctx, DATA_BLOB in, void **out)
 {
-	struct asn1_data *data = asn1_init(mem_ctx);
+	struct asn1_data *data;
 	struct ldb_extended_dn_control *ledc;
 
+	/* The content of this control is optional */
+	if (in.length == 0) {
+		*out = NULL;
+		return true;
+	}
+
+	data = asn1_init(mem_ctx);
 	if (!data) return false;
 
 	if (!asn1_load(data, in)) {
@@ -717,8 +724,15 @@
 static bool encode_extended_dn_request(void *mem_ctx, void *in, DATA_BLOB *out)
 {
 	struct ldb_extended_dn_control *ledc = talloc_get_type(in, struct ldb_extended_dn_control);
-	struct asn1_data *data = asn1_init(mem_ctx);
+	struct asn1_data *data;
 
+	if (!in) {
+		*out = data_blob(NULL, 0);
+		return true;
+	}
+
+	data = asn1_init(mem_ctx);
+
 	if (!data) return false;
 
 	if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {

Modified: branches/SAMBA_4_0/testprogs/blackbox/test_ldb.sh
===================================================================
--- branches/SAMBA_4_0/testprogs/blackbox/test_ldb.sh	2007-11-29 01:36:41 UTC (rev 26191)
+++ branches/SAMBA_4_0/testprogs/blackbox/test_ldb.sh	2007-11-29 08:00:04 UTC (rev 26192)
@@ -71,11 +71,21 @@
 fi
 
 echo "Test Extended DN Control"
+nentries=`bin/ldbsearch $options $CONFIGURATION -H $p://$SERVER --controls=extended_dn:1 '(objectclass=user)' | grep sAMAccountName | wc -l`
+if [ $nentries -lt 1 ]; then
+echo "Extended DN Control test returned 0 items"
+failed=`expr $failed + 1`
+fi
 nentries=`bin/ldbsearch $options $CONFIGURATION -H $p://$SERVER --controls=extended_dn:1:0 '(objectclass=user)' | grep sAMAccountName | wc -l`
 if [ $nentries -lt 1 ]; then
 echo "Extended DN Control test returned 0 items"
 failed=`expr $failed + 1`
 fi
+nentries=`bin/ldbsearch $options $CONFIGURATION -H $p://$SERVER --controls=extended_dn:1:1 '(objectclass=user)' | grep sAMAccountName | wc -l`
+if [ $nentries -lt 1 ]; then
+echo "Extended DN Control test returned 0 items"
+failed=`expr $failed + 1`
+fi
 
 echo "Test Domain scope Control"
 nentries=`bin/ldbsearch $options $CONFIGURATION -H $p://$SERVER --controls=domain_scope:1 '(objectclass=user)' | grep sAMAccountName | wc -l`



More information about the samba-cvs mailing list