s4:libcli/ldap: remove reference to DEBUG()
[Samba/gbeck.git] / source4 / libcli / ldap / ldap_message.c
blobd8bbf426342c5c857152cf81a80ede565f756638
1 /*
2 Unix SMB/CIFS mplementation.
3 LDAP protocol helper functions for SAMBA
5 Copyright (C) Andrew Tridgell 2004
6 Copyright (C) Volker Lendecke 2004
7 Copyright (C) Stefan Metzmacher 2004
8 Copyright (C) Simo Sorce 2004
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "../lib/util/asn1.h"
27 #include "libcli/ldap/ldap.h"
28 #include "libcli/ldap/ldap_proto.h"
30 _PUBLIC_ struct ldap_message *new_ldap_message(TALLOC_CTX *mem_ctx)
32 return talloc_zero(mem_ctx, struct ldap_message);
36 static bool add_value_to_attrib(TALLOC_CTX *mem_ctx, struct ldb_val *value,
37 struct ldb_message_element *attrib)
39 attrib->values = talloc_realloc(mem_ctx,
40 attrib->values,
41 DATA_BLOB,
42 attrib->num_values+1);
43 if (attrib->values == NULL)
44 return false;
46 attrib->values[attrib->num_values].data = talloc_steal(attrib->values,
47 value->data);
48 attrib->values[attrib->num_values].length = value->length;
49 attrib->num_values += 1;
50 return true;
53 static bool add_attrib_to_array_talloc(TALLOC_CTX *mem_ctx,
54 const struct ldb_message_element *attrib,
55 struct ldb_message_element **attribs,
56 int *num_attribs)
58 *attribs = talloc_realloc(mem_ctx,
59 *attribs,
60 struct ldb_message_element,
61 *num_attribs+1);
63 if (*attribs == NULL)
64 return false;
66 (*attribs)[*num_attribs] = *attrib;
67 talloc_steal(*attribs, attrib->values);
68 talloc_steal(*attribs, attrib->name);
69 *num_attribs += 1;
70 return true;
73 static bool add_mod_to_array_talloc(TALLOC_CTX *mem_ctx,
74 struct ldap_mod *mod,
75 struct ldap_mod **mods,
76 int *num_mods)
78 *mods = talloc_realloc(mem_ctx, *mods, struct ldap_mod, (*num_mods)+1);
80 if (*mods == NULL)
81 return false;
83 (*mods)[*num_mods] = *mod;
84 *num_mods += 1;
85 return true;
88 static bool ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree)
90 int i;
92 switch (tree->operation) {
93 case LDB_OP_AND:
94 case LDB_OP_OR:
95 asn1_push_tag(data, ASN1_CONTEXT(tree->operation==LDB_OP_AND?0:1));
96 for (i=0; i<tree->u.list.num_elements; i++) {
97 if (!ldap_push_filter(data, tree->u.list.elements[i])) {
98 return false;
101 asn1_pop_tag(data);
102 break;
104 case LDB_OP_NOT:
105 asn1_push_tag(data, ASN1_CONTEXT(2));
106 if (!ldap_push_filter(data, tree->u.isnot.child)) {
107 return false;
109 asn1_pop_tag(data);
110 break;
112 case LDB_OP_EQUALITY:
113 /* equality test */
114 asn1_push_tag(data, ASN1_CONTEXT(3));
115 asn1_write_OctetString(data, tree->u.equality.attr,
116 strlen(tree->u.equality.attr));
117 asn1_write_OctetString(data, tree->u.equality.value.data,
118 tree->u.equality.value.length);
119 asn1_pop_tag(data);
120 break;
122 case LDB_OP_SUBSTRING:
124 SubstringFilter ::= SEQUENCE {
125 type AttributeDescription,
126 -- at least one must be present
127 substrings SEQUENCE OF CHOICE {
128 initial [0] LDAPString,
129 any [1] LDAPString,
130 final [2] LDAPString } }
132 asn1_push_tag(data, ASN1_CONTEXT(4));
133 asn1_write_OctetString(data, tree->u.substring.attr, strlen(tree->u.substring.attr));
134 asn1_push_tag(data, ASN1_SEQUENCE(0));
135 i = 0;
136 if ( ! tree->u.substring.start_with_wildcard) {
137 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
138 asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i]);
139 asn1_pop_tag(data);
140 i++;
142 while (tree->u.substring.chunks[i]) {
143 int ctx;
145 if (( ! tree->u.substring.chunks[i + 1]) &&
146 (tree->u.substring.end_with_wildcard == 0)) {
147 ctx = 2;
148 } else {
149 ctx = 1;
151 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(ctx));
152 asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i]);
153 asn1_pop_tag(data);
154 i++;
156 asn1_pop_tag(data);
157 asn1_pop_tag(data);
158 break;
160 case LDB_OP_GREATER:
161 /* greaterOrEqual test */
162 asn1_push_tag(data, ASN1_CONTEXT(5));
163 asn1_write_OctetString(data, tree->u.comparison.attr,
164 strlen(tree->u.comparison.attr));
165 asn1_write_OctetString(data, tree->u.comparison.value.data,
166 tree->u.comparison.value.length);
167 asn1_pop_tag(data);
168 break;
170 case LDB_OP_LESS:
171 /* lessOrEqual test */
172 asn1_push_tag(data, ASN1_CONTEXT(6));
173 asn1_write_OctetString(data, tree->u.comparison.attr,
174 strlen(tree->u.comparison.attr));
175 asn1_write_OctetString(data, tree->u.comparison.value.data,
176 tree->u.comparison.value.length);
177 asn1_pop_tag(data);
178 break;
180 case LDB_OP_PRESENT:
181 /* present test */
182 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(7));
183 asn1_write_LDAPString(data, tree->u.present.attr);
184 asn1_pop_tag(data);
185 return !data->has_error;
187 case LDB_OP_APPROX:
188 /* approx test */
189 asn1_push_tag(data, ASN1_CONTEXT(8));
190 asn1_write_OctetString(data, tree->u.comparison.attr,
191 strlen(tree->u.comparison.attr));
192 asn1_write_OctetString(data, tree->u.comparison.value.data,
193 tree->u.comparison.value.length);
194 asn1_pop_tag(data);
195 break;
197 case LDB_OP_EXTENDED:
199 MatchingRuleAssertion ::= SEQUENCE {
200 matchingRule [1] MatchingRuleID OPTIONAL,
201 type [2] AttributeDescription OPTIONAL,
202 matchValue [3] AssertionValue,
203 dnAttributes [4] BOOLEAN DEFAULT FALSE
206 asn1_push_tag(data, ASN1_CONTEXT(9));
207 if (tree->u.extended.rule_id) {
208 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1));
209 asn1_write_LDAPString(data, tree->u.extended.rule_id);
210 asn1_pop_tag(data);
212 if (tree->u.extended.attr) {
213 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(2));
214 asn1_write_LDAPString(data, tree->u.extended.attr);
215 asn1_pop_tag(data);
217 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(3));
218 asn1_write_DATA_BLOB_LDAPString(data, &tree->u.extended.value);
219 asn1_pop_tag(data);
220 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(4));
221 asn1_write_uint8(data, tree->u.extended.dnAttributes);
222 asn1_pop_tag(data);
223 asn1_pop_tag(data);
224 break;
226 default:
227 return false;
229 return !data->has_error;
232 static void ldap_encode_response(struct asn1_data *data, struct ldap_Result *result)
234 asn1_write_enumerated(data, result->resultcode);
235 asn1_write_OctetString(data, result->dn,
236 (result->dn) ? strlen(result->dn) : 0);
237 asn1_write_OctetString(data, result->errormessage,
238 (result->errormessage) ?
239 strlen(result->errormessage) : 0);
240 if (result->referral) {
241 asn1_push_tag(data, ASN1_CONTEXT(3));
242 asn1_write_OctetString(data, result->referral,
243 strlen(result->referral));
244 asn1_pop_tag(data);
248 _PUBLIC_ bool ldap_encode(struct ldap_message *msg, DATA_BLOB *result, TALLOC_CTX *mem_ctx)
250 struct asn1_data *data = asn1_init(mem_ctx);
251 int i, j;
253 if (!data) return false;
255 asn1_push_tag(data, ASN1_SEQUENCE(0));
256 asn1_write_Integer(data, msg->messageid);
258 switch (msg->type) {
259 case LDAP_TAG_BindRequest: {
260 struct ldap_BindRequest *r = &msg->r.BindRequest;
261 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
262 asn1_write_Integer(data, r->version);
263 asn1_write_OctetString(data, r->dn,
264 (r->dn != NULL) ? strlen(r->dn) : 0);
266 switch (r->mechanism) {
267 case LDAP_AUTH_MECH_SIMPLE:
268 /* context, primitive */
269 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
270 asn1_write(data, r->creds.password,
271 strlen(r->creds.password));
272 asn1_pop_tag(data);
273 break;
274 case LDAP_AUTH_MECH_SASL:
275 /* context, constructed */
276 asn1_push_tag(data, ASN1_CONTEXT(3));
277 asn1_write_OctetString(data, r->creds.SASL.mechanism,
278 strlen(r->creds.SASL.mechanism));
279 if (r->creds.SASL.secblob) {
280 asn1_write_OctetString(data, r->creds.SASL.secblob->data,
281 r->creds.SASL.secblob->length);
283 asn1_pop_tag(data);
284 break;
285 default:
286 return false;
289 asn1_pop_tag(data);
290 break;
292 case LDAP_TAG_BindResponse: {
293 struct ldap_BindResponse *r = &msg->r.BindResponse;
294 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
295 ldap_encode_response(data, &r->response);
296 if (r->SASL.secblob) {
297 asn1_write_ContextSimple(data, 7, r->SASL.secblob);
299 asn1_pop_tag(data);
300 break;
302 case LDAP_TAG_UnbindRequest: {
303 /* struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
304 break;
306 case LDAP_TAG_SearchRequest: {
307 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
308 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
309 asn1_write_OctetString(data, r->basedn, strlen(r->basedn));
310 asn1_write_enumerated(data, r->scope);
311 asn1_write_enumerated(data, r->deref);
312 asn1_write_Integer(data, r->sizelimit);
313 asn1_write_Integer(data, r->timelimit);
314 asn1_write_BOOLEAN(data, r->attributesonly);
316 if (!ldap_push_filter(data, r->tree)) {
317 return false;
320 asn1_push_tag(data, ASN1_SEQUENCE(0));
321 for (i=0; i<r->num_attributes; i++) {
322 asn1_write_OctetString(data, r->attributes[i],
323 strlen(r->attributes[i]));
325 asn1_pop_tag(data);
326 asn1_pop_tag(data);
327 break;
329 case LDAP_TAG_SearchResultEntry: {
330 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
331 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
332 asn1_write_OctetString(data, r->dn, strlen(r->dn));
333 asn1_push_tag(data, ASN1_SEQUENCE(0));
334 for (i=0; i<r->num_attributes; i++) {
335 struct ldb_message_element *attr = &r->attributes[i];
336 asn1_push_tag(data, ASN1_SEQUENCE(0));
337 asn1_write_OctetString(data, attr->name,
338 strlen(attr->name));
339 asn1_push_tag(data, ASN1_SEQUENCE(1));
340 for (j=0; j<attr->num_values; j++) {
341 asn1_write_OctetString(data,
342 attr->values[j].data,
343 attr->values[j].length);
345 asn1_pop_tag(data);
346 asn1_pop_tag(data);
348 asn1_pop_tag(data);
349 asn1_pop_tag(data);
350 break;
352 case LDAP_TAG_SearchResultDone: {
353 struct ldap_Result *r = &msg->r.SearchResultDone;
354 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
355 ldap_encode_response(data, r);
356 asn1_pop_tag(data);
357 break;
359 case LDAP_TAG_ModifyRequest: {
360 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
361 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
362 asn1_write_OctetString(data, r->dn, strlen(r->dn));
363 asn1_push_tag(data, ASN1_SEQUENCE(0));
365 for (i=0; i<r->num_mods; i++) {
366 struct ldb_message_element *attrib = &r->mods[i].attrib;
367 asn1_push_tag(data, ASN1_SEQUENCE(0));
368 asn1_write_enumerated(data, r->mods[i].type);
369 asn1_push_tag(data, ASN1_SEQUENCE(0));
370 asn1_write_OctetString(data, attrib->name,
371 strlen(attrib->name));
372 asn1_push_tag(data, ASN1_SET);
373 for (j=0; j<attrib->num_values; j++) {
374 asn1_write_OctetString(data,
375 attrib->values[j].data,
376 attrib->values[j].length);
379 asn1_pop_tag(data);
380 asn1_pop_tag(data);
381 asn1_pop_tag(data);
384 asn1_pop_tag(data);
385 asn1_pop_tag(data);
386 break;
388 case LDAP_TAG_ModifyResponse: {
389 struct ldap_Result *r = &msg->r.ModifyResponse;
390 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
391 ldap_encode_response(data, r);
392 asn1_pop_tag(data);
393 break;
395 case LDAP_TAG_AddRequest: {
396 struct ldap_AddRequest *r = &msg->r.AddRequest;
397 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
398 asn1_write_OctetString(data, r->dn, strlen(r->dn));
399 asn1_push_tag(data, ASN1_SEQUENCE(0));
401 for (i=0; i<r->num_attributes; i++) {
402 struct ldb_message_element *attrib = &r->attributes[i];
403 asn1_push_tag(data, ASN1_SEQUENCE(0));
404 asn1_write_OctetString(data, attrib->name,
405 strlen(attrib->name));
406 asn1_push_tag(data, ASN1_SET);
407 for (j=0; j<r->attributes[i].num_values; j++) {
408 asn1_write_OctetString(data,
409 attrib->values[j].data,
410 attrib->values[j].length);
412 asn1_pop_tag(data);
413 asn1_pop_tag(data);
415 asn1_pop_tag(data);
416 asn1_pop_tag(data);
417 break;
419 case LDAP_TAG_AddResponse: {
420 struct ldap_Result *r = &msg->r.AddResponse;
421 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
422 ldap_encode_response(data, r);
423 asn1_pop_tag(data);
424 break;
426 case LDAP_TAG_DelRequest: {
427 struct ldap_DelRequest *r = &msg->r.DelRequest;
428 asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type));
429 asn1_write(data, r->dn, strlen(r->dn));
430 asn1_pop_tag(data);
431 break;
433 case LDAP_TAG_DelResponse: {
434 struct ldap_Result *r = &msg->r.DelResponse;
435 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
436 ldap_encode_response(data, r);
437 asn1_pop_tag(data);
438 break;
440 case LDAP_TAG_ModifyDNRequest: {
441 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
442 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
443 asn1_write_OctetString(data, r->dn, strlen(r->dn));
444 asn1_write_OctetString(data, r->newrdn, strlen(r->newrdn));
445 asn1_write_BOOLEAN(data, r->deleteolddn);
446 if (r->newsuperior) {
447 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
448 asn1_write(data, r->newsuperior,
449 strlen(r->newsuperior));
450 asn1_pop_tag(data);
452 asn1_pop_tag(data);
453 break;
455 case LDAP_TAG_ModifyDNResponse: {
456 struct ldap_Result *r = &msg->r.ModifyDNResponse;
457 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
458 ldap_encode_response(data, r);
459 asn1_pop_tag(data);
460 break;
462 case LDAP_TAG_CompareRequest: {
463 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
464 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
465 asn1_write_OctetString(data, r->dn, strlen(r->dn));
466 asn1_push_tag(data, ASN1_SEQUENCE(0));
467 asn1_write_OctetString(data, r->attribute,
468 strlen(r->attribute));
469 asn1_write_OctetString(data, r->value.data,
470 r->value.length);
471 asn1_pop_tag(data);
472 asn1_pop_tag(data);
473 break;
475 case LDAP_TAG_CompareResponse: {
476 struct ldap_Result *r = &msg->r.ModifyDNResponse;
477 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
478 ldap_encode_response(data, r);
479 asn1_pop_tag(data);
480 break;
482 case LDAP_TAG_AbandonRequest: {
483 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
484 asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type));
485 asn1_write_implicit_Integer(data, r->messageid);
486 asn1_pop_tag(data);
487 break;
489 case LDAP_TAG_SearchResultReference: {
490 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
491 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
492 asn1_write_OctetString(data, r->referral, strlen(r->referral));
493 asn1_pop_tag(data);
494 break;
496 case LDAP_TAG_ExtendedRequest: {
497 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
498 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
499 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
500 asn1_write(data, r->oid, strlen(r->oid));
501 asn1_pop_tag(data);
502 if (r->value) {
503 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1));
504 asn1_write(data, r->value->data, r->value->length);
505 asn1_pop_tag(data);
507 asn1_pop_tag(data);
508 break;
510 case LDAP_TAG_ExtendedResponse: {
511 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
512 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
513 ldap_encode_response(data, &r->response);
514 if (r->oid) {
515 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(10));
516 asn1_write(data, r->oid, strlen(r->oid));
517 asn1_pop_tag(data);
519 if (r->value) {
520 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(11));
521 asn1_write(data, r->value->data, r->value->length);
522 asn1_pop_tag(data);
524 asn1_pop_tag(data);
525 break;
527 default:
528 return false;
531 if (msg->controls != NULL) {
532 asn1_push_tag(data, ASN1_CONTEXT(0));
534 for (i = 0; msg->controls[i] != NULL; i++) {
535 if (!ldap_encode_control(mem_ctx, data, msg->controls[i])) {
536 return false;
540 asn1_pop_tag(data);
543 asn1_pop_tag(data);
545 if (data->has_error) {
546 asn1_free(data);
547 return false;
550 *result = data_blob_talloc(mem_ctx, data->data, data->length);
551 asn1_free(data);
552 return true;
555 static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
556 DATA_BLOB blob)
558 char *result = talloc_array(mem_ctx, char, blob.length+1);
559 memcpy(result, blob.data, blob.length);
560 result[blob.length] = '\0';
561 return result;
564 bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
565 struct asn1_data *data,
566 const char **result)
568 DATA_BLOB string;
569 if (!asn1_read_OctetString(data, mem_ctx, &string))
570 return false;
571 *result = blob2string_talloc(mem_ctx, string);
572 data_blob_free(&string);
573 return true;
576 static void ldap_decode_response(TALLOC_CTX *mem_ctx,
577 struct asn1_data *data,
578 struct ldap_Result *result)
580 asn1_read_enumerated(data, &result->resultcode);
581 asn1_read_OctetString_talloc(mem_ctx, data, &result->dn);
582 asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage);
583 if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
584 asn1_start_tag(data, ASN1_CONTEXT(3));
585 asn1_read_OctetString_talloc(mem_ctx, data, &result->referral);
586 asn1_end_tag(data);
587 } else {
588 result->referral = NULL;
592 static struct ldb_val **ldap_decode_substring(TALLOC_CTX *mem_ctx, struct ldb_val **chunks, int chunk_num, char *value)
595 chunks = talloc_realloc(mem_ctx, chunks, struct ldb_val *, chunk_num + 2);
596 if (chunks == NULL) {
597 return NULL;
600 chunks[chunk_num] = talloc(mem_ctx, struct ldb_val);
601 if (chunks[chunk_num] == NULL) {
602 return NULL;
605 chunks[chunk_num]->data = (uint8_t *)talloc_strdup(mem_ctx, value);
606 if (chunks[chunk_num]->data == NULL) {
607 return NULL;
609 chunks[chunk_num]->length = strlen(value);
611 chunks[chunk_num + 1] = '\0';
613 return chunks;
618 parse the ASN.1 formatted search string into a ldb_parse_tree
620 static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
621 struct asn1_data *data)
623 uint8_t filter_tag;
624 struct ldb_parse_tree *ret;
626 if (!asn1_peek_uint8(data, &filter_tag)) {
627 return NULL;
630 filter_tag &= 0x1f; /* strip off the asn1 stuff */
632 ret = talloc(mem_ctx, struct ldb_parse_tree);
633 if (ret == NULL) return NULL;
635 switch(filter_tag) {
636 case 0:
637 case 1:
638 /* AND or OR of one or more filters */
639 ret->operation = (filter_tag == 0)?LDB_OP_AND:LDB_OP_OR;
640 ret->u.list.num_elements = 0;
641 ret->u.list.elements = NULL;
643 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
644 goto failed;
647 while (asn1_tag_remaining(data) > 0) {
648 struct ldb_parse_tree *subtree;
649 subtree = ldap_decode_filter_tree(ret, data);
650 if (subtree == NULL) {
651 goto failed;
653 ret->u.list.elements =
654 talloc_realloc(ret, ret->u.list.elements,
655 struct ldb_parse_tree *,
656 ret->u.list.num_elements+1);
657 if (ret->u.list.elements == NULL) {
658 goto failed;
660 talloc_steal(ret->u.list.elements, subtree);
661 ret->u.list.elements[ret->u.list.num_elements] = subtree;
662 ret->u.list.num_elements++;
664 if (!asn1_end_tag(data)) {
665 goto failed;
667 break;
669 case 2:
670 /* 'not' operation */
671 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
672 goto failed;
675 ret->operation = LDB_OP_NOT;
676 ret->u.isnot.child = ldap_decode_filter_tree(ret, data);
677 if (ret->u.isnot.child == NULL) {
678 goto failed;
680 if (!asn1_end_tag(data)) {
681 goto failed;
683 break;
685 case 3: {
686 /* equalityMatch */
687 const char *attrib;
688 DATA_BLOB value;
690 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
691 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
692 asn1_read_OctetString(data, mem_ctx, &value);
693 asn1_end_tag(data);
694 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
695 goto failed;
698 ret->operation = LDB_OP_EQUALITY;
699 ret->u.equality.attr = talloc_steal(ret, attrib);
700 ret->u.equality.value.data = talloc_steal(ret, value.data);
701 ret->u.equality.value.length = value.length;
702 break;
704 case 4: {
705 /* substrings */
706 DATA_BLOB attr;
707 uint8_t subs_tag;
708 char *value;
709 int chunk_num = 0;
711 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
712 goto failed;
714 if (!asn1_read_OctetString(data, mem_ctx, &attr)) {
715 goto failed;
718 ret->operation = LDB_OP_SUBSTRING;
719 ret->u.substring.attr = talloc_strndup(ret, (char *)attr.data, attr.length);
720 ret->u.substring.chunks = NULL;
721 ret->u.substring.start_with_wildcard = 1;
722 ret->u.substring.end_with_wildcard = 1;
724 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
725 goto failed;
728 while (asn1_tag_remaining(data)) {
729 asn1_peek_uint8(data, &subs_tag);
730 subs_tag &= 0x1f; /* strip off the asn1 stuff */
731 if (subs_tag > 2) goto failed;
733 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(subs_tag));
734 asn1_read_LDAPString(data, mem_ctx, &value);
735 asn1_end_tag(data);
737 switch (subs_tag) {
738 case 0:
739 if (ret->u.substring.chunks != NULL) {
740 /* initial value found in the middle */
741 goto failed;
744 ret->u.substring.chunks = ldap_decode_substring(ret, NULL, 0, value);
745 if (ret->u.substring.chunks == NULL) {
746 goto failed;
749 ret->u.substring.start_with_wildcard = 0;
750 chunk_num = 1;
751 break;
753 case 1:
754 if (ret->u.substring.end_with_wildcard == 0) {
755 /* "any" value found after a "final" value */
756 goto failed;
759 ret->u.substring.chunks = ldap_decode_substring(ret,
760 ret->u.substring.chunks,
761 chunk_num,
762 value);
763 if (ret->u.substring.chunks == NULL) {
764 goto failed;
767 chunk_num++;
768 break;
770 case 2:
771 ret->u.substring.chunks = ldap_decode_substring(ret,
772 ret->u.substring.chunks,
773 chunk_num,
774 value);
775 if (ret->u.substring.chunks == NULL) {
776 goto failed;
779 ret->u.substring.end_with_wildcard = 0;
780 break;
782 default:
783 goto failed;
788 if (!asn1_end_tag(data)) { /* SEQUENCE */
789 goto failed;
792 if (!asn1_end_tag(data)) {
793 goto failed;
795 break;
797 case 5: {
798 /* greaterOrEqual */
799 const char *attrib;
800 DATA_BLOB value;
802 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
803 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
804 asn1_read_OctetString(data, mem_ctx, &value);
805 asn1_end_tag(data);
806 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
807 goto failed;
810 ret->operation = LDB_OP_GREATER;
811 ret->u.comparison.attr = talloc_steal(ret, attrib);
812 ret->u.comparison.value.data = talloc_steal(ret, value.data);
813 ret->u.comparison.value.length = value.length;
814 break;
816 case 6: {
817 /* lessOrEqual */
818 const char *attrib;
819 DATA_BLOB value;
821 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
822 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
823 asn1_read_OctetString(data, mem_ctx, &value);
824 asn1_end_tag(data);
825 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
826 goto failed;
829 ret->operation = LDB_OP_LESS;
830 ret->u.comparison.attr = talloc_steal(ret, attrib);
831 ret->u.comparison.value.data = talloc_steal(ret, value.data);
832 ret->u.comparison.value.length = value.length;
833 break;
835 case 7: {
836 /* Normal presence, "attribute=*" */
837 char *attr;
839 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(filter_tag))) {
840 goto failed;
842 if (!asn1_read_LDAPString(data, ret, &attr)) {
843 goto failed;
846 ret->operation = LDB_OP_PRESENT;
847 ret->u.present.attr = talloc_steal(ret, attr);
849 if (!asn1_end_tag(data)) {
850 goto failed;
852 break;
854 case 8: {
855 /* approx */
856 const char *attrib;
857 DATA_BLOB value;
859 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
860 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
861 asn1_read_OctetString(data, mem_ctx, &value);
862 asn1_end_tag(data);
863 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
864 goto failed;
867 ret->operation = LDB_OP_APPROX;
868 ret->u.comparison.attr = talloc_steal(ret, attrib);
869 ret->u.comparison.value.data = talloc_steal(ret, value.data);
870 ret->u.comparison.value.length = value.length;
871 break;
873 case 9: {
874 char *oid = NULL, *attr = NULL, *value;
875 uint8_t dnAttributes;
876 /* an extended search */
877 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
878 goto failed;
881 /* FIXME: read carefully rfc2251.txt there are a number of 'MUST's
882 we need to check we properly implement --SSS */
883 /* either oid or type must be defined */
884 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
885 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(1));
886 asn1_read_LDAPString(data, ret, &oid);
887 asn1_end_tag(data);
889 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(2))) { /* optional */
890 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(2));
891 asn1_read_LDAPString(data, ret, &attr);
892 asn1_end_tag(data);
894 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(3));
895 asn1_read_LDAPString(data, ret, &value);
896 asn1_end_tag(data);
897 /* dnAttributes is marked as BOOLEAN DEFAULT FALSE
898 it is not marked as OPTIONAL but openldap tools
899 do not set this unless it is to be set as TRUE
900 NOTE: openldap tools do not work with AD as it
901 seems that AD always requires the dnAttributes
902 boolean value to be set */
903 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(4))) {
904 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(4));
905 asn1_read_uint8(data, &dnAttributes);
906 asn1_end_tag(data);
907 } else {
908 dnAttributes = 0;
910 if ((oid == NULL && attr == NULL) || (value == NULL)) {
911 goto failed;
914 if (oid) {
915 ret->operation = LDB_OP_EXTENDED;
917 /* From the RFC2251: If the type field is
918 absent and matchingRule is present, the matchValue is compared
919 against all attributes in an entry which support that matchingRule
921 if (attr) {
922 ret->u.extended.attr = talloc_steal(ret, attr);
923 } else {
924 ret->u.extended.attr = talloc_strdup(ret, "*");
926 ret->u.extended.rule_id = talloc_steal(ret, oid);
927 ret->u.extended.value.data = talloc_steal(ret, value);
928 ret->u.extended.value.length = strlen(value);
929 ret->u.extended.dnAttributes = dnAttributes;
930 } else {
931 ret->operation = LDB_OP_EQUALITY;
932 ret->u.equality.attr = talloc_steal(ret, attr);
933 ret->u.equality.value.data = talloc_steal(ret, value);
934 ret->u.equality.value.length = strlen(value);
936 if (!asn1_end_tag(data)) {
937 goto failed;
939 break;
942 default:
943 goto failed;
946 return ret;
948 failed:
949 talloc_free(ret);
950 return NULL;
953 /* Decode a single LDAP attribute, possibly containing multiple values */
954 static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
955 struct ldb_message_element *attrib)
957 asn1_start_tag(data, ASN1_SEQUENCE(0));
958 asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name);
959 asn1_start_tag(data, ASN1_SET);
960 while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
961 DATA_BLOB blob;
962 asn1_read_OctetString(data, mem_ctx, &blob);
963 add_value_to_attrib(mem_ctx, &blob, attrib);
965 asn1_end_tag(data);
966 asn1_end_tag(data);
970 /* Decode a set of LDAP attributes, as found in the dereference control */
971 void ldap_decode_attribs_bare(TALLOC_CTX *mem_ctx, struct asn1_data *data,
972 struct ldb_message_element **attributes,
973 int *num_attributes)
975 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
976 struct ldb_message_element attrib;
977 ZERO_STRUCT(attrib);
978 ldap_decode_attrib(mem_ctx, data, &attrib);
979 add_attrib_to_array_talloc(mem_ctx, &attrib,
980 attributes, num_attributes);
984 /* Decode a set of LDAP attributes, as found in a search entry */
985 static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
986 struct ldb_message_element **attributes,
987 int *num_attributes)
989 asn1_start_tag(data, ASN1_SEQUENCE(0));
990 ldap_decode_attribs_bare(mem_ctx, data,
991 attributes, num_attributes);
992 asn1_end_tag(data);
995 /* This routine returns LDAP status codes */
997 _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, struct ldap_message *msg)
999 uint8_t tag;
1001 asn1_start_tag(data, ASN1_SEQUENCE(0));
1002 asn1_read_Integer(data, &msg->messageid);
1004 if (!asn1_peek_uint8(data, &tag))
1005 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1007 switch(tag) {
1009 case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
1010 struct ldap_BindRequest *r = &msg->r.BindRequest;
1011 msg->type = LDAP_TAG_BindRequest;
1012 asn1_start_tag(data, tag);
1013 asn1_read_Integer(data, &r->version);
1014 asn1_read_OctetString_talloc(msg, data, &r->dn);
1015 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
1016 int pwlen;
1017 r->creds.password = "";
1018 r->mechanism = LDAP_AUTH_MECH_SIMPLE;
1019 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1020 pwlen = asn1_tag_remaining(data);
1021 if (pwlen == -1) {
1022 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1024 if (pwlen != 0) {
1025 char *pw = talloc_array(msg, char, pwlen+1);
1026 if (!pw) {
1027 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1029 asn1_read(data, pw, pwlen);
1030 pw[pwlen] = '\0';
1031 r->creds.password = pw;
1033 asn1_end_tag(data);
1034 } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
1035 asn1_start_tag(data, ASN1_CONTEXT(3));
1036 r->mechanism = LDAP_AUTH_MECH_SASL;
1037 asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism);
1038 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) { /* optional */
1039 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1040 asn1_read_OctetString(data, msg, &tmp_blob);
1041 r->creds.SASL.secblob = talloc(msg, DATA_BLOB);
1042 if (!r->creds.SASL.secblob) {
1043 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1045 *r->creds.SASL.secblob = data_blob_talloc(r->creds.SASL.secblob,
1046 tmp_blob.data, tmp_blob.length);
1047 data_blob_free(&tmp_blob);
1048 } else {
1049 r->creds.SASL.secblob = NULL;
1051 asn1_end_tag(data);
1052 } else {
1053 /* Neither Simple nor SASL bind */
1054 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1056 asn1_end_tag(data);
1057 break;
1060 case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
1061 struct ldap_BindResponse *r = &msg->r.BindResponse;
1062 msg->type = LDAP_TAG_BindResponse;
1063 asn1_start_tag(data, tag);
1064 ldap_decode_response(msg, data, &r->response);
1065 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
1066 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1067 asn1_read_ContextSimple(data, 7, &tmp_blob);
1068 r->SASL.secblob = talloc(msg, DATA_BLOB);
1069 if (!r->SASL.secblob) {
1070 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1072 *r->SASL.secblob = data_blob_talloc(r->SASL.secblob,
1073 tmp_blob.data, tmp_blob.length);
1074 data_blob_free(&tmp_blob);
1075 } else {
1076 r->SASL.secblob = NULL;
1078 asn1_end_tag(data);
1079 break;
1082 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
1083 msg->type = LDAP_TAG_UnbindRequest;
1084 asn1_start_tag(data, tag);
1085 asn1_end_tag(data);
1086 break;
1089 case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
1090 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
1091 msg->type = LDAP_TAG_SearchRequest;
1092 asn1_start_tag(data, tag);
1093 asn1_read_OctetString_talloc(msg, data, &r->basedn);
1094 asn1_read_enumerated(data, (int *)&(r->scope));
1095 asn1_read_enumerated(data, (int *)&(r->deref));
1096 asn1_read_Integer(data, &r->sizelimit);
1097 asn1_read_Integer(data, &r->timelimit);
1098 asn1_read_BOOLEAN(data, &r->attributesonly);
1100 r->tree = ldap_decode_filter_tree(msg, data);
1101 if (r->tree == NULL) {
1102 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1105 asn1_start_tag(data, ASN1_SEQUENCE(0));
1107 r->num_attributes = 0;
1108 r->attributes = NULL;
1110 while (asn1_tag_remaining(data) > 0) {
1112 const char *attr;
1113 if (!asn1_read_OctetString_talloc(msg, data,
1114 &attr))
1115 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1116 if (!add_string_to_array(msg, attr,
1117 &r->attributes,
1118 &r->num_attributes))
1119 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1122 asn1_end_tag(data);
1123 asn1_end_tag(data);
1124 break;
1127 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1128 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1129 msg->type = LDAP_TAG_SearchResultEntry;
1130 r->attributes = NULL;
1131 r->num_attributes = 0;
1132 asn1_start_tag(data, tag);
1133 asn1_read_OctetString_talloc(msg, data, &r->dn);
1134 ldap_decode_attribs(msg, data, &r->attributes,
1135 &r->num_attributes);
1136 asn1_end_tag(data);
1137 break;
1140 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1141 struct ldap_Result *r = &msg->r.SearchResultDone;
1142 msg->type = LDAP_TAG_SearchResultDone;
1143 asn1_start_tag(data, tag);
1144 ldap_decode_response(msg, data, r);
1145 asn1_end_tag(data);
1146 break;
1149 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1150 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
1151 msg->type = LDAP_TAG_SearchResultReference;
1152 asn1_start_tag(data, tag);
1153 asn1_read_OctetString_talloc(msg, data, &r->referral);
1154 asn1_end_tag(data);
1155 break;
1158 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1159 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1160 msg->type = LDAP_TAG_ModifyRequest;
1161 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
1162 asn1_read_OctetString_talloc(msg, data, &r->dn);
1163 asn1_start_tag(data, ASN1_SEQUENCE(0));
1165 r->num_mods = 0;
1166 r->mods = NULL;
1168 while (asn1_tag_remaining(data) > 0) {
1169 struct ldap_mod mod;
1170 int v;
1171 ZERO_STRUCT(mod);
1172 asn1_start_tag(data, ASN1_SEQUENCE(0));
1173 asn1_read_enumerated(data, &v);
1174 mod.type = v;
1175 ldap_decode_attrib(msg, data, &mod.attrib);
1176 asn1_end_tag(data);
1177 if (!add_mod_to_array_talloc(msg, &mod,
1178 &r->mods, &r->num_mods)) {
1179 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1183 asn1_end_tag(data);
1184 asn1_end_tag(data);
1185 break;
1188 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1189 struct ldap_Result *r = &msg->r.ModifyResponse;
1190 msg->type = LDAP_TAG_ModifyResponse;
1191 asn1_start_tag(data, tag);
1192 ldap_decode_response(msg, data, r);
1193 asn1_end_tag(data);
1194 break;
1197 case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1198 struct ldap_AddRequest *r = &msg->r.AddRequest;
1199 msg->type = LDAP_TAG_AddRequest;
1200 asn1_start_tag(data, tag);
1201 asn1_read_OctetString_talloc(msg, data, &r->dn);
1203 r->attributes = NULL;
1204 r->num_attributes = 0;
1205 ldap_decode_attribs(msg, data, &r->attributes,
1206 &r->num_attributes);
1208 asn1_end_tag(data);
1209 break;
1212 case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1213 struct ldap_Result *r = &msg->r.AddResponse;
1214 msg->type = LDAP_TAG_AddResponse;
1215 asn1_start_tag(data, tag);
1216 ldap_decode_response(msg, data, r);
1217 asn1_end_tag(data);
1218 break;
1221 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1222 struct ldap_DelRequest *r = &msg->r.DelRequest;
1223 int len;
1224 char *dn;
1225 msg->type = LDAP_TAG_DelRequest;
1226 asn1_start_tag(data,
1227 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
1228 len = asn1_tag_remaining(data);
1229 if (len == -1) {
1230 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1232 dn = talloc_array(msg, char, len+1);
1233 if (dn == NULL)
1234 break;
1235 asn1_read(data, dn, len);
1236 dn[len] = '\0';
1237 r->dn = dn;
1238 asn1_end_tag(data);
1239 break;
1242 case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1243 struct ldap_Result *r = &msg->r.DelResponse;
1244 msg->type = LDAP_TAG_DelResponse;
1245 asn1_start_tag(data, tag);
1246 ldap_decode_response(msg, data, r);
1247 asn1_end_tag(data);
1248 break;
1251 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1252 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1253 msg->type = LDAP_TAG_ModifyDNRequest;
1254 asn1_start_tag(data,
1255 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
1256 asn1_read_OctetString_talloc(msg, data, &r->dn);
1257 asn1_read_OctetString_talloc(msg, data, &r->newrdn);
1258 asn1_read_BOOLEAN(data, &r->deleteolddn);
1259 r->newsuperior = NULL;
1260 if (asn1_tag_remaining(data) > 0) {
1261 int len;
1262 char *newsup;
1263 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1264 len = asn1_tag_remaining(data);
1265 if (len == -1) {
1266 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1268 newsup = talloc_array(msg, char, len+1);
1269 if (newsup == NULL) {
1270 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1272 asn1_read(data, newsup, len);
1273 newsup[len] = '\0';
1274 r->newsuperior = newsup;
1275 asn1_end_tag(data);
1277 asn1_end_tag(data);
1278 break;
1281 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1282 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1283 msg->type = LDAP_TAG_ModifyDNResponse;
1284 asn1_start_tag(data, tag);
1285 ldap_decode_response(msg, data, r);
1286 asn1_end_tag(data);
1287 break;
1290 case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1291 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1292 msg->type = LDAP_TAG_CompareRequest;
1293 asn1_start_tag(data,
1294 ASN1_APPLICATION(LDAP_TAG_CompareRequest));
1295 asn1_read_OctetString_talloc(msg, data, &r->dn);
1296 asn1_start_tag(data, ASN1_SEQUENCE(0));
1297 asn1_read_OctetString_talloc(msg, data, &r->attribute);
1298 asn1_read_OctetString(data, msg, &r->value);
1299 if (r->value.data) {
1300 talloc_steal(msg, r->value.data);
1302 asn1_end_tag(data);
1303 asn1_end_tag(data);
1304 break;
1307 case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1308 struct ldap_Result *r = &msg->r.CompareResponse;
1309 msg->type = LDAP_TAG_CompareResponse;
1310 asn1_start_tag(data, tag);
1311 ldap_decode_response(msg, data, r);
1312 asn1_end_tag(data);
1313 break;
1316 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1317 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1318 msg->type = LDAP_TAG_AbandonRequest;
1319 asn1_start_tag(data, tag);
1320 asn1_read_implicit_Integer(data, &r->messageid);
1321 asn1_end_tag(data);
1322 break;
1325 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1326 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1327 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1329 msg->type = LDAP_TAG_ExtendedRequest;
1330 asn1_start_tag(data,tag);
1331 if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
1332 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1334 r->oid = blob2string_talloc(msg, tmp_blob);
1335 data_blob_free(&tmp_blob);
1336 if (!r->oid) {
1337 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1340 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1341 asn1_read_ContextSimple(data, 1, &tmp_blob);
1342 r->value = talloc(msg, DATA_BLOB);
1343 if (!r->value) {
1344 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1346 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1347 data_blob_free(&tmp_blob);
1348 } else {
1349 r->value = NULL;
1352 asn1_end_tag(data);
1353 break;
1356 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1357 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1358 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1360 msg->type = LDAP_TAG_ExtendedResponse;
1361 asn1_start_tag(data, tag);
1362 ldap_decode_response(msg, data, &r->response);
1364 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(10))) {
1365 asn1_read_ContextSimple(data, 1, &tmp_blob);
1366 r->oid = blob2string_talloc(msg, tmp_blob);
1367 data_blob_free(&tmp_blob);
1368 if (!r->oid) {
1369 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1371 } else {
1372 r->oid = NULL;
1375 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(11))) {
1376 asn1_read_ContextSimple(data, 1, &tmp_blob);
1377 r->value = talloc(msg, DATA_BLOB);
1378 if (!r->value) {
1379 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1381 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1382 data_blob_free(&tmp_blob);
1383 } else {
1384 r->value = NULL;
1387 asn1_end_tag(data);
1388 break;
1390 default:
1391 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1394 msg->controls = NULL;
1395 msg->controls_decoded = NULL;
1397 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1398 int i = 0;
1399 struct ldb_control **ctrl = NULL;
1400 bool *decoded = NULL;
1402 asn1_start_tag(data, ASN1_CONTEXT(0));
1404 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1405 DATA_BLOB value;
1406 /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1408 ctrl = talloc_realloc(msg, ctrl, struct ldb_control *, i+2);
1409 if (!ctrl) {
1410 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1413 decoded = talloc_realloc(msg, decoded, bool, i+1);
1414 if (!decoded) {
1415 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1418 ctrl[i] = talloc(ctrl, struct ldb_control);
1419 if (!ctrl[i]) {
1420 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1423 if (!ldap_decode_control_wrapper(ctrl, data, ctrl[i], &value)) {
1424 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1427 if (!ldap_decode_control_value(ctrl, value, ctrl[i])) {
1428 if (ctrl[i]->critical) {
1429 ctrl[i]->data = NULL;
1430 decoded[i] = false;
1431 i++;
1432 } else {
1433 talloc_free(ctrl[i]);
1434 ctrl[i] = NULL;
1436 } else {
1437 decoded[i] = true;
1438 i++;
1442 if (ctrl != NULL) {
1443 ctrl[i] = NULL;
1446 msg->controls = ctrl;
1447 msg->controls_decoded = decoded;
1449 asn1_end_tag(data);
1452 asn1_end_tag(data);
1453 if ((data->has_error) || (data->nesting != NULL)) {
1454 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1456 return NT_STATUS_OK;
1461 return NT_STATUS_OK if a blob has enough bytes in it to be a full
1462 ldap packet. Set packet_size if true.
1464 NTSTATUS ldap_full_packet(void *private_data, DATA_BLOB blob, size_t *packet_size)
1466 return asn1_full_tag(blob, ASN1_SEQUENCE(0), packet_size);