summaryrefslogtreecommitdiff
path: root/source4/libcli/ldap
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2007-11-29 08:00:04 +0100
committerStefan Metzmacher <metze@samba.org>2007-12-21 05:46:44 +0100
commit364266e22a08e730f2442cf87ec385620cff2700 (patch)
treede8e5ce9f54c4353761314e42f2b335f1da7ea21 /source4/libcli/ldap
parent26ae331f75317bfc0a4787d3960a861b25225615 (diff)
downloadsamba-364266e22a08e730f2442cf87ec385620cff2700.tar.gz
samba-364266e22a08e730f2442cf87ec385620cff2700.tar.bz2
samba-364266e22a08e730f2442cf87ec385620cff2700.zip
r26192: 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 (This used to be commit 833dfc2f2af84c45f954e428c9ea6babf100ba92)
Diffstat (limited to 'source4/libcli/ldap')
-rw-r--r--source4/libcli/ldap/ldap.c13
-rw-r--r--source4/libcli/ldap/ldap.h2
-rw-r--r--source4/libcli/ldap/ldap_client.c15
-rw-r--r--source4/libcli/ldap/ldap_controls.c18
4 files changed, 45 insertions, 3 deletions
diff --git a/source4/libcli/ldap/ldap.c b/source4/libcli/ldap/ldap.c
index 11689fbd79..34d715e3e5 100644
--- a/source4/libcli/ldap/ldap.c
+++ b/source4/libcli/ldap/ldap.c
@@ -1325,10 +1325,12 @@ NTSTATUS ldap_decode(struct asn1_data *data, struct ldap_message *msg)
}
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 @@ NTSTATUS ldap_decode(struct asn1_data *data, struct ldap_message *msg)
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 @@ NTSTATUS ldap_decode(struct asn1_data *data, struct ldap_message *msg)
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 @@ NTSTATUS ldap_decode(struct asn1_data *data, struct ldap_message *msg)
}
msg->controls = ctrl;
+ msg->controls_decoded = decoded;
asn1_end_tag(data);
}
diff --git a/source4/libcli/ldap/ldap.h b/source4/libcli/ldap/ldap.h
index e89322213a..6f5e86744e 100644
--- a/source4/libcli/ldap/ldap.h
+++ b/source4/libcli/ldap/ldap.h
@@ -240,11 +240,13 @@ union ldap_Request {
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;
diff --git a/source4/libcli/ldap/ldap_client.c b/source4/libcli/ldap/ldap_client.c
index fcb2d92214..41e9c37196 100644
--- a/source4/libcli/ldap/ldap_client.c
+++ b/source4/libcli/ldap/ldap_client.c
@@ -116,6 +116,7 @@ static void ldap_error_handler(void *private_data, NTSTATUS status)
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 @@ static void ldap_match_message(struct ldap_connection *conn, struct ldap_message
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,
diff --git a/source4/libcli/ldap/ldap_controls.c b/source4/libcli/ldap/ldap_controls.c
index b7fd1ce178..34e5cccf75 100644
--- a/source4/libcli/ldap/ldap_controls.c
+++ b/source4/libcli/ldap/ldap_controls.c
@@ -156,9 +156,16 @@ static bool decode_server_sort_request(void *mem_ctx, DATA_BLOB in, void **out)
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,7 +724,14 @@ static bool encode_server_sort_request(void *mem_ctx, void *in, DATA_BLOB *out)
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;