r21511: this seems to be the nicer fix for the problem with
[Samba.git] / source / libcli / ldap / ldap.c
blob5a7174b41dbadc095533517ad27484b654351f9e
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 2 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, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "includes.h"
27 #include "libcli/util/asn_1.h"
28 #include "libcli/ldap/ldap.h"
31 static BOOL ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree)
33 int i;
35 switch (tree->operation) {
36 case LDB_OP_AND:
37 case LDB_OP_OR:
38 asn1_push_tag(data, ASN1_CONTEXT(tree->operation==LDB_OP_AND?0:1));
39 for (i=0; i<tree->u.list.num_elements; i++) {
40 if (!ldap_push_filter(data, tree->u.list.elements[i])) {
41 return False;
44 asn1_pop_tag(data);
45 break;
47 case LDB_OP_NOT:
48 asn1_push_tag(data, ASN1_CONTEXT(2));
49 if (!ldap_push_filter(data, tree->u.isnot.child)) {
50 return False;
52 asn1_pop_tag(data);
53 break;
55 case LDB_OP_EQUALITY:
56 /* equality test */
57 asn1_push_tag(data, ASN1_CONTEXT(3));
58 asn1_write_OctetString(data, tree->u.equality.attr,
59 strlen(tree->u.equality.attr));
60 asn1_write_OctetString(data, tree->u.equality.value.data,
61 tree->u.equality.value.length);
62 asn1_pop_tag(data);
63 break;
65 case LDB_OP_SUBSTRING:
67 SubstringFilter ::= SEQUENCE {
68 type AttributeDescription,
69 -- at least one must be present
70 substrings SEQUENCE OF CHOICE {
71 initial [0] LDAPString,
72 any [1] LDAPString,
73 final [2] LDAPString } }
75 asn1_push_tag(data, ASN1_CONTEXT(4));
76 asn1_write_OctetString(data, tree->u.substring.attr, strlen(tree->u.substring.attr));
77 asn1_push_tag(data, ASN1_SEQUENCE(0));
78 i = 0;
79 if ( ! tree->u.substring.start_with_wildcard) {
80 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
81 asn1_write_LDAPString(data, (char *)tree->u.substring.chunks[i]->data);
82 asn1_pop_tag(data);
83 i++;
85 while (tree->u.substring.chunks[i]) {
86 int ctx;
88 if (( ! tree->u.substring.chunks[i + 1]) &&
89 (tree->u.substring.end_with_wildcard == 0)) {
90 ctx = 2;
91 } else {
92 ctx = 1;
94 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(ctx));
95 asn1_write_LDAPString(data, (char *)tree->u.substring.chunks[i]->data);
96 asn1_pop_tag(data);
97 i++;
99 asn1_pop_tag(data);
100 asn1_pop_tag(data);
101 break;
103 case LDB_OP_GREATER:
104 /* greaterOrEqual test */
105 asn1_push_tag(data, ASN1_CONTEXT(5));
106 asn1_write_OctetString(data, tree->u.comparison.attr,
107 strlen(tree->u.comparison.attr));
108 asn1_write_OctetString(data, tree->u.comparison.value.data,
109 tree->u.comparison.value.length);
110 asn1_pop_tag(data);
111 break;
113 case LDB_OP_LESS:
114 /* lessOrEqual test */
115 asn1_push_tag(data, ASN1_CONTEXT(6));
116 asn1_write_OctetString(data, tree->u.comparison.attr,
117 strlen(tree->u.comparison.attr));
118 asn1_write_OctetString(data, tree->u.comparison.value.data,
119 tree->u.comparison.value.length);
120 asn1_pop_tag(data);
121 break;
123 case LDB_OP_PRESENT:
124 /* present test */
125 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(7));
126 asn1_write_LDAPString(data, tree->u.present.attr);
127 asn1_pop_tag(data);
128 return !data->has_error;
130 case LDB_OP_APPROX:
131 /* approx test */
132 asn1_push_tag(data, ASN1_CONTEXT(8));
133 asn1_write_OctetString(data, tree->u.comparison.attr,
134 strlen(tree->u.comparison.attr));
135 asn1_write_OctetString(data, tree->u.comparison.value.data,
136 tree->u.comparison.value.length);
137 asn1_pop_tag(data);
138 break;
140 case LDB_OP_EXTENDED:
142 MatchingRuleAssertion ::= SEQUENCE {
143 matchingRule [1] MatchingRuleID OPTIONAL,
144 type [2] AttributeDescription OPTIONAL,
145 matchValue [3] AssertionValue,
146 dnAttributes [4] BOOLEAN DEFAULT FALSE
149 asn1_push_tag(data, ASN1_CONTEXT(9));
150 if (tree->u.extended.rule_id) {
151 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1));
152 asn1_write_LDAPString(data, tree->u.extended.rule_id);
153 asn1_pop_tag(data);
155 if (tree->u.extended.attr) {
156 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(2));
157 asn1_write_LDAPString(data, tree->u.extended.attr);
158 asn1_pop_tag(data);
160 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(3));
161 asn1_write_LDAPString(data, (char *)tree->u.extended.value.data);
162 asn1_pop_tag(data);
163 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(4));
164 asn1_write_uint8(data, tree->u.extended.dnAttributes);
165 asn1_pop_tag(data);
166 asn1_pop_tag(data);
167 break;
169 default:
170 return False;
172 return !data->has_error;
175 static void ldap_encode_response(struct asn1_data *data, struct ldap_Result *result)
177 asn1_write_enumerated(data, result->resultcode);
178 asn1_write_OctetString(data, result->dn,
179 (result->dn) ? strlen(result->dn) : 0);
180 asn1_write_OctetString(data, result->errormessage,
181 (result->errormessage) ?
182 strlen(result->errormessage) : 0);
183 if (result->referral) {
184 asn1_push_tag(data, ASN1_CONTEXT(3));
185 asn1_write_OctetString(data, result->referral,
186 strlen(result->referral));
187 asn1_pop_tag(data);
191 BOOL ldap_encode(struct ldap_message *msg, DATA_BLOB *result, TALLOC_CTX *mem_ctx)
193 struct asn1_data data;
194 int i, j;
196 ZERO_STRUCT(data);
197 asn1_push_tag(&data, ASN1_SEQUENCE(0));
198 asn1_write_Integer(&data, msg->messageid);
200 switch (msg->type) {
201 case LDAP_TAG_BindRequest: {
202 struct ldap_BindRequest *r = &msg->r.BindRequest;
203 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
204 asn1_write_Integer(&data, r->version);
205 asn1_write_OctetString(&data, r->dn,
206 (r->dn != NULL) ? strlen(r->dn) : 0);
208 switch (r->mechanism) {
209 case LDAP_AUTH_MECH_SIMPLE:
210 /* context, primitive */
211 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
212 asn1_write(&data, r->creds.password,
213 strlen(r->creds.password));
214 asn1_pop_tag(&data);
215 break;
216 case LDAP_AUTH_MECH_SASL:
217 /* context, constructed */
218 asn1_push_tag(&data, ASN1_CONTEXT(3));
219 asn1_write_OctetString(&data, r->creds.SASL.mechanism,
220 strlen(r->creds.SASL.mechanism));
221 if (r->creds.SASL.secblob) {
222 asn1_write_OctetString(&data, r->creds.SASL.secblob->data,
223 r->creds.SASL.secblob->length);
225 asn1_pop_tag(&data);
226 break;
227 default:
228 return False;
231 asn1_pop_tag(&data);
232 break;
234 case LDAP_TAG_BindResponse: {
235 struct ldap_BindResponse *r = &msg->r.BindResponse;
236 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
237 ldap_encode_response(&data, &r->response);
238 if (r->SASL.secblob) {
239 asn1_write_ContextSimple(&data, 7, r->SASL.secblob);
241 asn1_pop_tag(&data);
242 break;
244 case LDAP_TAG_UnbindRequest: {
245 /* struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
246 break;
248 case LDAP_TAG_SearchRequest: {
249 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
250 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
251 asn1_write_OctetString(&data, r->basedn, strlen(r->basedn));
252 asn1_write_enumerated(&data, r->scope);
253 asn1_write_enumerated(&data, r->deref);
254 asn1_write_Integer(&data, r->sizelimit);
255 asn1_write_Integer(&data, r->timelimit);
256 asn1_write_BOOLEAN(&data, r->attributesonly);
258 if (!ldap_push_filter(&data, r->tree)) {
259 return False;
262 asn1_push_tag(&data, ASN1_SEQUENCE(0));
263 for (i=0; i<r->num_attributes; i++) {
264 asn1_write_OctetString(&data, r->attributes[i],
265 strlen(r->attributes[i]));
267 asn1_pop_tag(&data);
268 asn1_pop_tag(&data);
269 break;
271 case LDAP_TAG_SearchResultEntry: {
272 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
273 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
274 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
275 asn1_push_tag(&data, ASN1_SEQUENCE(0));
276 for (i=0; i<r->num_attributes; i++) {
277 struct ldb_message_element *attr = &r->attributes[i];
278 asn1_push_tag(&data, ASN1_SEQUENCE(0));
279 asn1_write_OctetString(&data, attr->name,
280 strlen(attr->name));
281 asn1_push_tag(&data, ASN1_SEQUENCE(1));
282 for (j=0; j<attr->num_values; j++) {
283 asn1_write_OctetString(&data,
284 attr->values[j].data,
285 attr->values[j].length);
287 asn1_pop_tag(&data);
288 asn1_pop_tag(&data);
290 asn1_pop_tag(&data);
291 asn1_pop_tag(&data);
292 break;
294 case LDAP_TAG_SearchResultDone: {
295 struct ldap_Result *r = &msg->r.SearchResultDone;
296 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
297 ldap_encode_response(&data, r);
298 asn1_pop_tag(&data);
299 break;
301 case LDAP_TAG_ModifyRequest: {
302 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
303 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
304 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
305 asn1_push_tag(&data, ASN1_SEQUENCE(0));
307 for (i=0; i<r->num_mods; i++) {
308 struct ldb_message_element *attrib = &r->mods[i].attrib;
309 asn1_push_tag(&data, ASN1_SEQUENCE(0));
310 asn1_write_enumerated(&data, r->mods[i].type);
311 asn1_push_tag(&data, ASN1_SEQUENCE(0));
312 asn1_write_OctetString(&data, attrib->name,
313 strlen(attrib->name));
314 asn1_push_tag(&data, ASN1_SET);
315 for (j=0; j<attrib->num_values; j++) {
316 asn1_write_OctetString(&data,
317 attrib->values[j].data,
318 attrib->values[j].length);
321 asn1_pop_tag(&data);
322 asn1_pop_tag(&data);
323 asn1_pop_tag(&data);
326 asn1_pop_tag(&data);
327 asn1_pop_tag(&data);
328 break;
330 case LDAP_TAG_ModifyResponse: {
331 struct ldap_Result *r = &msg->r.ModifyResponse;
332 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
333 ldap_encode_response(&data, r);
334 asn1_pop_tag(&data);
335 break;
337 case LDAP_TAG_AddRequest: {
338 struct ldap_AddRequest *r = &msg->r.AddRequest;
339 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
340 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
341 asn1_push_tag(&data, ASN1_SEQUENCE(0));
343 for (i=0; i<r->num_attributes; i++) {
344 struct ldb_message_element *attrib = &r->attributes[i];
345 asn1_push_tag(&data, ASN1_SEQUENCE(0));
346 asn1_write_OctetString(&data, attrib->name,
347 strlen(attrib->name));
348 asn1_push_tag(&data, ASN1_SET);
349 for (j=0; j<r->attributes[i].num_values; j++) {
350 asn1_write_OctetString(&data,
351 attrib->values[j].data,
352 attrib->values[j].length);
354 asn1_pop_tag(&data);
355 asn1_pop_tag(&data);
357 asn1_pop_tag(&data);
358 asn1_pop_tag(&data);
359 break;
361 case LDAP_TAG_AddResponse: {
362 struct ldap_Result *r = &msg->r.AddResponse;
363 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
364 ldap_encode_response(&data, r);
365 asn1_pop_tag(&data);
366 break;
368 case LDAP_TAG_DelRequest: {
369 struct ldap_DelRequest *r = &msg->r.DelRequest;
370 asn1_push_tag(&data, ASN1_APPLICATION_SIMPLE(msg->type));
371 asn1_write(&data, r->dn, strlen(r->dn));
372 asn1_pop_tag(&data);
373 break;
375 case LDAP_TAG_DelResponse: {
376 struct ldap_Result *r = &msg->r.DelResponse;
377 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
378 ldap_encode_response(&data, r);
379 asn1_pop_tag(&data);
380 break;
382 case LDAP_TAG_ModifyDNRequest: {
383 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
384 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
385 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
386 asn1_write_OctetString(&data, r->newrdn, strlen(r->newrdn));
387 asn1_write_BOOLEAN(&data, r->deleteolddn);
388 if (r->newsuperior) {
389 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
390 asn1_write(&data, r->newsuperior,
391 strlen(r->newsuperior));
392 asn1_pop_tag(&data);
394 asn1_pop_tag(&data);
395 break;
397 case LDAP_TAG_ModifyDNResponse: {
398 struct ldap_Result *r = &msg->r.ModifyDNResponse;
399 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
400 ldap_encode_response(&data, r);
401 asn1_pop_tag(&data);
402 break;
404 case LDAP_TAG_CompareRequest: {
405 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
406 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
407 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
408 asn1_push_tag(&data, ASN1_SEQUENCE(0));
409 asn1_write_OctetString(&data, r->attribute,
410 strlen(r->attribute));
411 asn1_write_OctetString(&data, r->value.data,
412 r->value.length);
413 asn1_pop_tag(&data);
414 asn1_pop_tag(&data);
415 break;
417 case LDAP_TAG_CompareResponse: {
418 struct ldap_Result *r = &msg->r.ModifyDNResponse;
419 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
420 ldap_encode_response(&data, r);
421 asn1_pop_tag(&data);
422 break;
424 case LDAP_TAG_AbandonRequest: {
425 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
426 asn1_push_tag(&data, ASN1_APPLICATION_SIMPLE(msg->type));
427 asn1_write_implicit_Integer(&data, r->messageid);
428 asn1_pop_tag(&data);
429 break;
431 case LDAP_TAG_SearchResultReference: {
432 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
433 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
434 asn1_write_OctetString(&data, r->referral, strlen(r->referral));
435 asn1_pop_tag(&data);
436 break;
438 case LDAP_TAG_ExtendedRequest: {
439 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
440 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
441 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
442 asn1_write(&data, r->oid, strlen(r->oid));
443 asn1_pop_tag(&data);
444 if (r->value) {
445 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(1));
446 asn1_write(&data, r->value->data, r->value->length);
447 asn1_pop_tag(&data);
449 asn1_pop_tag(&data);
450 break;
452 case LDAP_TAG_ExtendedResponse: {
453 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
454 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
455 ldap_encode_response(&data, &r->response);
456 if (r->oid) {
457 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(10));
458 asn1_write(&data, r->oid, strlen(r->oid));
459 asn1_pop_tag(&data);
461 if (r->value) {
462 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(11));
463 asn1_write(&data, r->value->data, r->value->length);
464 asn1_pop_tag(&data);
466 asn1_pop_tag(&data);
467 break;
469 default:
470 return False;
473 if (msg->controls != NULL) {
474 asn1_push_tag(&data, ASN1_CONTEXT(0));
476 for (i = 0; msg->controls[i] != NULL; i++) {
477 if (!ldap_encode_control(mem_ctx, &data, msg->controls[i])) {
478 return False;
482 asn1_pop_tag(&data);
485 asn1_pop_tag(&data);
487 if (data.has_error) {
488 asn1_free(&data);
489 return False;
492 *result = data_blob_talloc(mem_ctx, data.data, data.length);
493 asn1_free(&data);
494 return True;
497 static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
498 DATA_BLOB blob)
500 char *result = talloc_size(mem_ctx, blob.length+1);
501 memcpy(result, blob.data, blob.length);
502 result[blob.length] = '\0';
503 return result;
506 static BOOL asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
507 struct asn1_data *data,
508 const char **result)
510 DATA_BLOB string;
511 if (!asn1_read_OctetString(data, &string))
512 return False;
513 *result = blob2string_talloc(mem_ctx, string);
514 data_blob_free(&string);
515 return True;
518 static void ldap_decode_response(TALLOC_CTX *mem_ctx,
519 struct asn1_data *data,
520 struct ldap_Result *result)
522 asn1_read_enumerated(data, &result->resultcode);
523 asn1_read_OctetString_talloc(mem_ctx, data, &result->dn);
524 asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage);
525 if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
526 asn1_start_tag(data, ASN1_CONTEXT(3));
527 asn1_read_OctetString_talloc(mem_ctx, data, &result->referral);
528 asn1_end_tag(data);
529 } else {
530 result->referral = NULL;
534 static struct ldb_val **ldap_decode_substring(TALLOC_CTX *mem_ctx, struct ldb_val **chunks, int chunk_num, char *value)
537 chunks = talloc_realloc(mem_ctx, chunks, struct ldb_val *, chunk_num + 2);
538 if (chunks == NULL) {
539 return NULL;
542 chunks[chunk_num] = talloc(mem_ctx, struct ldb_val);
543 if (chunks[chunk_num] == NULL) {
544 return NULL;
547 chunks[chunk_num]->data = (uint8_t *)talloc_strdup(mem_ctx, value);
548 if (chunks[chunk_num]->data == NULL) {
549 return NULL;
551 chunks[chunk_num]->length = strlen(value);
553 chunks[chunk_num + 1] = '\0';
555 return chunks;
560 parse the ASN.1 formatted search string into a ldb_parse_tree
562 static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
563 struct asn1_data *data)
565 uint8_t filter_tag;
566 struct ldb_parse_tree *ret;
568 if (!asn1_peek_uint8(data, &filter_tag)) {
569 return NULL;
572 filter_tag &= 0x1f; /* strip off the asn1 stuff */
574 ret = talloc(mem_ctx, struct ldb_parse_tree);
575 if (ret == NULL) return NULL;
577 switch(filter_tag) {
578 case 0:
579 case 1:
580 /* AND or OR of one or more filters */
581 ret->operation = (filter_tag == 0)?LDB_OP_AND:LDB_OP_OR;
582 ret->u.list.num_elements = 0;
583 ret->u.list.elements = NULL;
585 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
586 goto failed;
589 while (asn1_tag_remaining(data) > 0) {
590 struct ldb_parse_tree *subtree;
591 subtree = ldap_decode_filter_tree(ret, data);
592 if (subtree == NULL) {
593 goto failed;
595 ret->u.list.elements =
596 talloc_realloc(ret, ret->u.list.elements,
597 struct ldb_parse_tree *,
598 ret->u.list.num_elements+1);
599 if (ret->u.list.elements == NULL) {
600 goto failed;
602 talloc_steal(ret->u.list.elements, subtree);
603 ret->u.list.elements[ret->u.list.num_elements] = subtree;
604 ret->u.list.num_elements++;
606 if (!asn1_end_tag(data)) {
607 goto failed;
609 break;
611 case 2:
612 /* 'not' operation */
613 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
614 goto failed;
617 ret->operation = LDB_OP_NOT;
618 ret->u.isnot.child = ldap_decode_filter_tree(ret, data);
619 if (ret->u.isnot.child == NULL) {
620 goto failed;
622 if (!asn1_end_tag(data)) {
623 goto failed;
625 break;
627 case 3: {
628 /* equalityMatch */
629 const char *attrib;
630 DATA_BLOB value;
632 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
633 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
634 asn1_read_OctetString(data, &value);
635 asn1_end_tag(data);
636 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
637 goto failed;
640 ret->operation = LDB_OP_EQUALITY;
641 ret->u.equality.attr = talloc_steal(ret, attrib);
642 ret->u.equality.value.data = talloc_steal(ret, value.data);
643 ret->u.equality.value.length = value.length;
644 break;
646 case 4: {
647 /* substrings */
648 DATA_BLOB attr;
649 uint8_t subs_tag;
650 char *value;
651 int chunk_num = 0;
653 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
654 goto failed;
656 if (!asn1_read_OctetString(data, &attr)) {
657 goto failed;
660 ret->operation = LDB_OP_SUBSTRING;
661 ret->u.substring.attr = talloc_strndup(ret, (char *)attr.data, attr.length);
662 ret->u.substring.chunks = NULL;
663 ret->u.substring.start_with_wildcard = 1;
664 ret->u.substring.end_with_wildcard = 1;
666 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
667 goto failed;
670 while (asn1_tag_remaining(data)) {
671 asn1_peek_uint8(data, &subs_tag);
672 subs_tag &= 0x1f; /* strip off the asn1 stuff */
673 if (subs_tag > 2) goto failed;
675 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(subs_tag));
676 asn1_read_LDAPString(data, &value);
677 asn1_end_tag(data);
679 switch (subs_tag) {
680 case 0:
681 if (ret->u.substring.chunks != NULL) {
682 /* initial value found in the middle */
683 goto failed;
686 ret->u.substring.chunks = ldap_decode_substring(ret, NULL, 0, value);
687 if (ret->u.substring.chunks == NULL) {
688 goto failed;
691 ret->u.substring.start_with_wildcard = 0;
692 chunk_num = 1;
693 break;
695 case 1:
696 if (ret->u.substring.end_with_wildcard == 0) {
697 /* "any" value found after a "final" value */
698 goto failed;
701 ret->u.substring.chunks = ldap_decode_substring(ret,
702 ret->u.substring.chunks,
703 chunk_num,
704 value);
705 if (ret->u.substring.chunks == NULL) {
706 goto failed;
709 chunk_num++;
710 break;
712 case 2:
713 ret->u.substring.chunks = ldap_decode_substring(ret,
714 ret->u.substring.chunks,
715 chunk_num,
716 value);
717 if (ret->u.substring.chunks == NULL) {
718 goto failed;
721 ret->u.substring.end_with_wildcard = 0;
722 break;
724 default:
725 goto failed;
730 if (!asn1_end_tag(data)) { /* SEQUENCE */
731 goto failed;
734 if (!asn1_end_tag(data)) {
735 goto failed;
737 break;
739 case 5: {
740 /* greaterOrEqual */
741 const char *attrib;
742 DATA_BLOB value;
744 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
745 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
746 asn1_read_OctetString(data, &value);
747 asn1_end_tag(data);
748 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
749 goto failed;
752 ret->operation = LDB_OP_GREATER;
753 ret->u.comparison.attr = talloc_steal(ret, attrib);
754 ret->u.comparison.value.data = talloc_steal(ret, value.data);
755 ret->u.comparison.value.length = value.length;
756 break;
758 case 6: {
759 /* lessOrEqual */
760 const char *attrib;
761 DATA_BLOB value;
763 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
764 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
765 asn1_read_OctetString(data, &value);
766 asn1_end_tag(data);
767 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
768 goto failed;
771 ret->operation = LDB_OP_LESS;
772 ret->u.comparison.attr = talloc_steal(ret, attrib);
773 ret->u.comparison.value.data = talloc_steal(ret, value.data);
774 ret->u.comparison.value.length = value.length;
775 break;
777 case 7: {
778 /* Normal presence, "attribute=*" */
779 char *attr;
781 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(filter_tag))) {
782 goto failed;
784 if (!asn1_read_LDAPString(data, &attr)) {
785 goto failed;
788 ret->operation = LDB_OP_PRESENT;
789 ret->u.present.attr = talloc_steal(ret, attr);
791 if (!asn1_end_tag(data)) {
792 goto failed;
794 break;
796 case 8: {
797 /* approx */
798 const char *attrib;
799 DATA_BLOB value;
801 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
802 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
803 asn1_read_OctetString(data, &value);
804 asn1_end_tag(data);
805 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
806 goto failed;
809 ret->operation = LDB_OP_APPROX;
810 ret->u.comparison.attr = talloc_steal(ret, attrib);
811 ret->u.comparison.value.data = talloc_steal(ret, value.data);
812 ret->u.comparison.value.length = value.length;
813 break;
815 case 9: {
816 char *oid = NULL, *attr = NULL, *value;
817 uint8_t dnAttributes;
818 /* an extended search */
819 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
820 goto failed;
823 /* FIXME: read carefully rfc2251.txt there are a number of 'MUST's
824 we need to check we properly implement --SSS */
825 /* either oid or type must be defined */
826 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
827 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(1));
828 asn1_read_LDAPString(data, &oid);
829 asn1_end_tag(data);
831 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(2))) { /* optional */
832 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(2));
833 asn1_read_LDAPString(data, &attr);
834 asn1_end_tag(data);
836 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(3));
837 asn1_read_LDAPString(data, &value);
838 asn1_end_tag(data);
839 /* dnAttributes is marked as BOOLEAN DEFAULT FALSE
840 it is not marked as OPTIONAL but openldap tools
841 do not set this unless it is to be set as TRUE
842 NOTE: openldap tools do not work with AD as it
843 seems that AD always requires the dnAttributes
844 boolean value to be set */
845 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(4))) {
846 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(4));
847 asn1_read_uint8(data, &dnAttributes);
848 asn1_end_tag(data);
849 } else {
850 dnAttributes = 0;
852 if ((oid == NULL && attr == NULL) || (value == NULL)) {
853 goto failed;
856 if (oid) {
857 ret->operation = LDB_OP_EXTENDED;
859 /* From the RFC2251: If the type field is
860 absent and matchingRule is present, the matchValue is compared
861 against all attributes in an entry which support that matchingRule
863 if (attr) {
864 ret->u.extended.attr = talloc_steal(ret, attr);
865 } else {
866 ret->u.extended.attr = talloc_strdup(ret, "*");
868 ret->u.extended.rule_id = talloc_steal(ret, oid);
869 ret->u.extended.value.data = talloc_steal(ret, value);
870 ret->u.extended.value.length = strlen(value);
871 ret->u.extended.dnAttributes = dnAttributes;
872 } else {
873 ret->operation = LDB_OP_EQUALITY;
874 ret->u.equality.attr = talloc_steal(ret, attr);
875 ret->u.equality.value.data = talloc_steal(ret, value);
876 ret->u.equality.value.length = strlen(value);
878 if (!asn1_end_tag(data)) {
879 goto failed;
881 break;
884 default:
885 DEBUG(0,("Unsupported LDAP filter operation 0x%x\n", filter_tag));
886 goto failed;
889 return ret;
891 failed:
892 talloc_free(ret);
893 return NULL;
897 static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
898 struct ldb_message_element *attrib)
900 asn1_start_tag(data, ASN1_SEQUENCE(0));
901 asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name);
902 asn1_start_tag(data, ASN1_SET);
903 while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
904 DATA_BLOB blob;
905 asn1_read_OctetString(data, &blob);
906 add_value_to_attrib(mem_ctx, &blob, attrib);
908 asn1_end_tag(data);
909 asn1_end_tag(data);
913 static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
914 struct ldb_message_element **attributes,
915 int *num_attributes)
917 asn1_start_tag(data, ASN1_SEQUENCE(0));
918 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
919 struct ldb_message_element attrib;
920 ZERO_STRUCT(attrib);
921 ldap_decode_attrib(mem_ctx, data, &attrib);
922 add_attrib_to_array_talloc(mem_ctx, &attrib,
923 attributes, num_attributes);
925 asn1_end_tag(data);
928 BOOL ldap_decode(struct asn1_data *data, struct ldap_message *msg)
930 uint8_t tag;
932 asn1_start_tag(data, ASN1_SEQUENCE(0));
933 asn1_read_Integer(data, &msg->messageid);
935 if (!asn1_peek_uint8(data, &tag))
936 return False;
938 switch(tag) {
940 case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
941 struct ldap_BindRequest *r = &msg->r.BindRequest;
942 msg->type = LDAP_TAG_BindRequest;
943 asn1_start_tag(data, tag);
944 asn1_read_Integer(data, &r->version);
945 asn1_read_OctetString_talloc(msg, data, &r->dn);
946 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
947 int pwlen;
948 r->creds.password = "";
949 r->mechanism = LDAP_AUTH_MECH_SIMPLE;
950 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
951 pwlen = asn1_tag_remaining(data);
952 if (pwlen == -1) {
953 return False;
955 if (pwlen != 0) {
956 char *pw = talloc_size(msg, pwlen+1);
957 if (!pw) {
958 return False;
960 asn1_read(data, pw, pwlen);
961 pw[pwlen] = '\0';
962 r->creds.password = pw;
964 asn1_end_tag(data);
965 } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
966 asn1_start_tag(data, ASN1_CONTEXT(3));
967 r->mechanism = LDAP_AUTH_MECH_SASL;
968 asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism);
969 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) { /* optional */
970 DATA_BLOB tmp_blob = data_blob(NULL, 0);
971 asn1_read_OctetString(data, &tmp_blob);
972 r->creds.SASL.secblob = talloc(msg, DATA_BLOB);
973 if (!r->creds.SASL.secblob) {
974 return False;
976 *r->creds.SASL.secblob = data_blob_talloc(r->creds.SASL.secblob,
977 tmp_blob.data, tmp_blob.length);
978 data_blob_free(&tmp_blob);
979 } else {
980 r->creds.SASL.secblob = NULL;
982 asn1_end_tag(data);
983 } else {
984 /* Neither Simple nor SASL bind */
985 return False;
987 asn1_end_tag(data);
988 break;
991 case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
992 struct ldap_BindResponse *r = &msg->r.BindResponse;
993 msg->type = LDAP_TAG_BindResponse;
994 asn1_start_tag(data, tag);
995 ldap_decode_response(msg, data, &r->response);
996 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
997 DATA_BLOB tmp_blob = data_blob(NULL, 0);
998 asn1_read_ContextSimple(data, 7, &tmp_blob);
999 r->SASL.secblob = talloc(msg, DATA_BLOB);
1000 if (!r->SASL.secblob) {
1001 return False;
1003 *r->SASL.secblob = data_blob_talloc(r->SASL.secblob,
1004 tmp_blob.data, tmp_blob.length);
1005 data_blob_free(&tmp_blob);
1006 } else {
1007 r->SASL.secblob = NULL;
1009 asn1_end_tag(data);
1010 break;
1013 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
1014 msg->type = LDAP_TAG_UnbindRequest;
1015 asn1_start_tag(data, tag);
1016 asn1_end_tag(data);
1017 break;
1020 case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
1021 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
1022 msg->type = LDAP_TAG_SearchRequest;
1023 asn1_start_tag(data, tag);
1024 asn1_read_OctetString_talloc(msg, data, &r->basedn);
1025 asn1_read_enumerated(data, (int *)&(r->scope));
1026 asn1_read_enumerated(data, (int *)&(r->deref));
1027 asn1_read_Integer(data, &r->sizelimit);
1028 asn1_read_Integer(data, &r->timelimit);
1029 asn1_read_BOOLEAN(data, &r->attributesonly);
1031 r->tree = ldap_decode_filter_tree(msg, data);
1032 if (r->tree == NULL) {
1033 return False;
1036 asn1_start_tag(data, ASN1_SEQUENCE(0));
1038 r->num_attributes = 0;
1039 r->attributes = NULL;
1041 while (asn1_tag_remaining(data) > 0) {
1042 const char *attr;
1043 if (!asn1_read_OctetString_talloc(msg, data,
1044 &attr))
1045 return False;
1046 if (!add_string_to_array(msg, attr,
1047 &r->attributes,
1048 &r->num_attributes))
1049 return False;
1052 asn1_end_tag(data);
1053 asn1_end_tag(data);
1054 break;
1057 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1058 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1059 msg->type = LDAP_TAG_SearchResultEntry;
1060 r->attributes = NULL;
1061 r->num_attributes = 0;
1062 asn1_start_tag(data, tag);
1063 asn1_read_OctetString_talloc(msg, data, &r->dn);
1064 ldap_decode_attribs(msg, data, &r->attributes,
1065 &r->num_attributes);
1066 asn1_end_tag(data);
1067 break;
1070 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1071 struct ldap_Result *r = &msg->r.SearchResultDone;
1072 msg->type = LDAP_TAG_SearchResultDone;
1073 asn1_start_tag(data, tag);
1074 ldap_decode_response(msg, data, r);
1075 asn1_end_tag(data);
1076 break;
1079 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1080 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
1081 msg->type = LDAP_TAG_SearchResultReference;
1082 asn1_start_tag(data, tag);
1083 asn1_read_OctetString_talloc(msg, data, &r->referral);
1084 asn1_end_tag(data);
1085 break;
1088 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1089 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1090 msg->type = LDAP_TAG_ModifyRequest;
1091 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
1092 asn1_read_OctetString_talloc(msg, data, &r->dn);
1093 asn1_start_tag(data, ASN1_SEQUENCE(0));
1095 r->num_mods = 0;
1096 r->mods = NULL;
1098 while (asn1_tag_remaining(data) > 0) {
1099 struct ldap_mod mod;
1100 int v;
1101 ZERO_STRUCT(mod);
1102 asn1_start_tag(data, ASN1_SEQUENCE(0));
1103 asn1_read_enumerated(data, &v);
1104 mod.type = v;
1105 ldap_decode_attrib(msg, data, &mod.attrib);
1106 asn1_end_tag(data);
1107 if (!add_mod_to_array_talloc(msg, &mod,
1108 &r->mods, &r->num_mods)) {
1109 return False;
1113 asn1_end_tag(data);
1114 asn1_end_tag(data);
1115 break;
1118 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1119 struct ldap_Result *r = &msg->r.ModifyResponse;
1120 msg->type = LDAP_TAG_ModifyResponse;
1121 asn1_start_tag(data, tag);
1122 ldap_decode_response(msg, data, r);
1123 asn1_end_tag(data);
1124 break;
1127 case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1128 struct ldap_AddRequest *r = &msg->r.AddRequest;
1129 msg->type = LDAP_TAG_AddRequest;
1130 asn1_start_tag(data, tag);
1131 asn1_read_OctetString_talloc(msg, data, &r->dn);
1133 r->attributes = NULL;
1134 r->num_attributes = 0;
1135 ldap_decode_attribs(msg, data, &r->attributes,
1136 &r->num_attributes);
1138 asn1_end_tag(data);
1139 break;
1142 case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1143 struct ldap_Result *r = &msg->r.AddResponse;
1144 msg->type = LDAP_TAG_AddResponse;
1145 asn1_start_tag(data, tag);
1146 ldap_decode_response(msg, data, r);
1147 asn1_end_tag(data);
1148 break;
1151 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1152 struct ldap_DelRequest *r = &msg->r.DelRequest;
1153 int len;
1154 char *dn;
1155 msg->type = LDAP_TAG_DelRequest;
1156 asn1_start_tag(data,
1157 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
1158 len = asn1_tag_remaining(data);
1159 if (len == -1) {
1160 return False;
1162 dn = talloc_size(msg, len+1);
1163 if (dn == NULL)
1164 break;
1165 asn1_read(data, dn, len);
1166 dn[len] = '\0';
1167 r->dn = dn;
1168 asn1_end_tag(data);
1169 break;
1172 case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1173 struct ldap_Result *r = &msg->r.DelResponse;
1174 msg->type = LDAP_TAG_DelResponse;
1175 asn1_start_tag(data, tag);
1176 ldap_decode_response(msg, data, r);
1177 asn1_end_tag(data);
1178 break;
1181 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1182 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1183 msg->type = LDAP_TAG_ModifyDNRequest;
1184 asn1_start_tag(data,
1185 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
1186 asn1_read_OctetString_talloc(msg, data, &r->dn);
1187 asn1_read_OctetString_talloc(msg, data, &r->newrdn);
1188 asn1_read_BOOLEAN(data, &r->deleteolddn);
1189 r->newsuperior = NULL;
1190 if (asn1_tag_remaining(data) > 0) {
1191 int len;
1192 char *newsup;
1193 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1194 len = asn1_tag_remaining(data);
1195 if (len == -1) {
1196 return False;
1198 newsup = talloc_size(msg, len+1);
1199 if (newsup == NULL) {
1200 return False;
1202 asn1_read(data, newsup, len);
1203 newsup[len] = '\0';
1204 r->newsuperior = newsup;
1205 asn1_end_tag(data);
1207 asn1_end_tag(data);
1208 break;
1211 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1212 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1213 msg->type = LDAP_TAG_ModifyDNResponse;
1214 asn1_start_tag(data, tag);
1215 ldap_decode_response(msg, data, r);
1216 asn1_end_tag(data);
1217 break;
1220 case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1221 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1222 msg->type = LDAP_TAG_CompareRequest;
1223 asn1_start_tag(data,
1224 ASN1_APPLICATION(LDAP_TAG_CompareRequest));
1225 asn1_read_OctetString_talloc(msg, data, &r->dn);
1226 asn1_start_tag(data, ASN1_SEQUENCE(0));
1227 asn1_read_OctetString_talloc(msg, data, &r->attribute);
1228 asn1_read_OctetString(data, &r->value);
1229 if (r->value.data) {
1230 talloc_steal(msg, r->value.data);
1232 asn1_end_tag(data);
1233 asn1_end_tag(data);
1234 break;
1237 case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1238 struct ldap_Result *r = &msg->r.CompareResponse;
1239 msg->type = LDAP_TAG_CompareResponse;
1240 asn1_start_tag(data, tag);
1241 ldap_decode_response(msg, data, r);
1242 asn1_end_tag(data);
1243 break;
1246 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1247 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1248 msg->type = LDAP_TAG_AbandonRequest;
1249 asn1_start_tag(data, tag);
1250 asn1_read_implicit_Integer(data, &r->messageid);
1251 asn1_end_tag(data);
1252 break;
1255 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1256 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1257 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1259 msg->type = LDAP_TAG_ExtendedRequest;
1260 asn1_start_tag(data,tag);
1261 if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
1262 return False;
1264 r->oid = blob2string_talloc(msg, tmp_blob);
1265 data_blob_free(&tmp_blob);
1266 if (!r->oid) {
1267 return False;
1270 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1271 asn1_read_ContextSimple(data, 1, &tmp_blob);
1272 r->value = talloc(msg, DATA_BLOB);
1273 if (!r->value) {
1274 return False;
1276 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1277 data_blob_free(&tmp_blob);
1278 } else {
1279 r->value = NULL;
1282 asn1_end_tag(data);
1283 break;
1286 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1287 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1288 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1290 msg->type = LDAP_TAG_ExtendedResponse;
1291 asn1_start_tag(data, tag);
1292 ldap_decode_response(msg, data, &r->response);
1294 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(10))) {
1295 asn1_read_ContextSimple(data, 1, &tmp_blob);
1296 r->oid = blob2string_talloc(msg, tmp_blob);
1297 data_blob_free(&tmp_blob);
1298 if (!r->oid) {
1299 return False;
1301 } else {
1302 r->oid = NULL;
1305 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(11))) {
1306 asn1_read_ContextSimple(data, 1, &tmp_blob);
1307 r->value = talloc(msg, DATA_BLOB);
1308 if (!r->value) {
1309 return False;
1311 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1312 data_blob_free(&tmp_blob);
1313 } else {
1314 r->value = NULL;
1317 asn1_end_tag(data);
1318 break;
1320 default:
1321 return False;
1324 msg->controls = NULL;
1326 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1327 int i;
1328 struct ldb_control **ctrl = NULL;
1330 asn1_start_tag(data, ASN1_CONTEXT(0));
1332 for (i=0; asn1_peek_tag(data, ASN1_SEQUENCE(0)); i++) {
1333 /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1335 ctrl = talloc_realloc(msg, ctrl, struct ldb_control *, i+2);
1336 if (!ctrl) {
1337 return False;
1340 ctrl[i] = talloc(ctrl, struct ldb_control);
1341 if (!ctrl[i]) {
1342 return False;
1345 if (!ldap_decode_control(ctrl, data, ctrl[i])) {
1346 return False;
1351 if (ctrl != NULL) {
1352 ctrl[i] = NULL;
1355 msg->controls = ctrl;
1357 asn1_end_tag(data);
1360 asn1_end_tag(data);
1361 return ((!data->has_error) && (data->nesting == NULL));
1366 return NT_STATUS_OK if a blob has enough bytes in it to be a full
1367 ldap packet. Set packet_size if true.
1369 NTSTATUS ldap_full_packet(void *private_data, DATA_BLOB blob, size_t *packet_size)
1371 return asn1_full_tag(blob, ASN1_SEQUENCE(0), packet_size);