r23030: finally fixed up our asn1 code to use better memory allocation. This
[Samba.git] / source / libcli / ldap / ldap.c
blob70ba9335dbfb3a78aae72268aa3519d66f0106d3
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 = asn1_init(mem_ctx);
194 int i, j;
196 asn1_push_tag(data, ASN1_SEQUENCE(0));
197 asn1_write_Integer(data, msg->messageid);
199 switch (msg->type) {
200 case LDAP_TAG_BindRequest: {
201 struct ldap_BindRequest *r = &msg->r.BindRequest;
202 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
203 asn1_write_Integer(data, r->version);
204 asn1_write_OctetString(data, r->dn,
205 (r->dn != NULL) ? strlen(r->dn) : 0);
207 switch (r->mechanism) {
208 case LDAP_AUTH_MECH_SIMPLE:
209 /* context, primitive */
210 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
211 asn1_write(data, r->creds.password,
212 strlen(r->creds.password));
213 asn1_pop_tag(data);
214 break;
215 case LDAP_AUTH_MECH_SASL:
216 /* context, constructed */
217 asn1_push_tag(data, ASN1_CONTEXT(3));
218 asn1_write_OctetString(data, r->creds.SASL.mechanism,
219 strlen(r->creds.SASL.mechanism));
220 if (r->creds.SASL.secblob) {
221 asn1_write_OctetString(data, r->creds.SASL.secblob->data,
222 r->creds.SASL.secblob->length);
224 asn1_pop_tag(data);
225 break;
226 default:
227 return False;
230 asn1_pop_tag(data);
231 break;
233 case LDAP_TAG_BindResponse: {
234 struct ldap_BindResponse *r = &msg->r.BindResponse;
235 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
236 ldap_encode_response(data, &r->response);
237 if (r->SASL.secblob) {
238 asn1_write_ContextSimple(data, 7, r->SASL.secblob);
240 asn1_pop_tag(data);
241 break;
243 case LDAP_TAG_UnbindRequest: {
244 /* struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
245 break;
247 case LDAP_TAG_SearchRequest: {
248 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
249 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
250 asn1_write_OctetString(data, r->basedn, strlen(r->basedn));
251 asn1_write_enumerated(data, r->scope);
252 asn1_write_enumerated(data, r->deref);
253 asn1_write_Integer(data, r->sizelimit);
254 asn1_write_Integer(data, r->timelimit);
255 asn1_write_BOOLEAN(data, r->attributesonly);
257 if (!ldap_push_filter(data, r->tree)) {
258 return False;
261 asn1_push_tag(data, ASN1_SEQUENCE(0));
262 for (i=0; i<r->num_attributes; i++) {
263 asn1_write_OctetString(data, r->attributes[i],
264 strlen(r->attributes[i]));
266 asn1_pop_tag(data);
267 asn1_pop_tag(data);
268 break;
270 case LDAP_TAG_SearchResultEntry: {
271 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
272 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
273 asn1_write_OctetString(data, r->dn, strlen(r->dn));
274 asn1_push_tag(data, ASN1_SEQUENCE(0));
275 for (i=0; i<r->num_attributes; i++) {
276 struct ldb_message_element *attr = &r->attributes[i];
277 asn1_push_tag(data, ASN1_SEQUENCE(0));
278 asn1_write_OctetString(data, attr->name,
279 strlen(attr->name));
280 asn1_push_tag(data, ASN1_SEQUENCE(1));
281 for (j=0; j<attr->num_values; j++) {
282 asn1_write_OctetString(data,
283 attr->values[j].data,
284 attr->values[j].length);
286 asn1_pop_tag(data);
287 asn1_pop_tag(data);
289 asn1_pop_tag(data);
290 asn1_pop_tag(data);
291 break;
293 case LDAP_TAG_SearchResultDone: {
294 struct ldap_Result *r = &msg->r.SearchResultDone;
295 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
296 ldap_encode_response(data, r);
297 asn1_pop_tag(data);
298 break;
300 case LDAP_TAG_ModifyRequest: {
301 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
302 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
303 asn1_write_OctetString(data, r->dn, strlen(r->dn));
304 asn1_push_tag(data, ASN1_SEQUENCE(0));
306 for (i=0; i<r->num_mods; i++) {
307 struct ldb_message_element *attrib = &r->mods[i].attrib;
308 asn1_push_tag(data, ASN1_SEQUENCE(0));
309 asn1_write_enumerated(data, r->mods[i].type);
310 asn1_push_tag(data, ASN1_SEQUENCE(0));
311 asn1_write_OctetString(data, attrib->name,
312 strlen(attrib->name));
313 asn1_push_tag(data, ASN1_SET);
314 for (j=0; j<attrib->num_values; j++) {
315 asn1_write_OctetString(data,
316 attrib->values[j].data,
317 attrib->values[j].length);
320 asn1_pop_tag(data);
321 asn1_pop_tag(data);
322 asn1_pop_tag(data);
325 asn1_pop_tag(data);
326 asn1_pop_tag(data);
327 break;
329 case LDAP_TAG_ModifyResponse: {
330 struct ldap_Result *r = &msg->r.ModifyResponse;
331 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
332 ldap_encode_response(data, r);
333 asn1_pop_tag(data);
334 break;
336 case LDAP_TAG_AddRequest: {
337 struct ldap_AddRequest *r = &msg->r.AddRequest;
338 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
339 asn1_write_OctetString(data, r->dn, strlen(r->dn));
340 asn1_push_tag(data, ASN1_SEQUENCE(0));
342 for (i=0; i<r->num_attributes; i++) {
343 struct ldb_message_element *attrib = &r->attributes[i];
344 asn1_push_tag(data, ASN1_SEQUENCE(0));
345 asn1_write_OctetString(data, attrib->name,
346 strlen(attrib->name));
347 asn1_push_tag(data, ASN1_SET);
348 for (j=0; j<r->attributes[i].num_values; j++) {
349 asn1_write_OctetString(data,
350 attrib->values[j].data,
351 attrib->values[j].length);
353 asn1_pop_tag(data);
354 asn1_pop_tag(data);
356 asn1_pop_tag(data);
357 asn1_pop_tag(data);
358 break;
360 case LDAP_TAG_AddResponse: {
361 struct ldap_Result *r = &msg->r.AddResponse;
362 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
363 ldap_encode_response(data, r);
364 asn1_pop_tag(data);
365 break;
367 case LDAP_TAG_DelRequest: {
368 struct ldap_DelRequest *r = &msg->r.DelRequest;
369 asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type));
370 asn1_write(data, r->dn, strlen(r->dn));
371 asn1_pop_tag(data);
372 break;
374 case LDAP_TAG_DelResponse: {
375 struct ldap_Result *r = &msg->r.DelResponse;
376 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
377 ldap_encode_response(data, r);
378 asn1_pop_tag(data);
379 break;
381 case LDAP_TAG_ModifyDNRequest: {
382 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
383 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
384 asn1_write_OctetString(data, r->dn, strlen(r->dn));
385 asn1_write_OctetString(data, r->newrdn, strlen(r->newrdn));
386 asn1_write_BOOLEAN(data, r->deleteolddn);
387 if (r->newsuperior) {
388 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
389 asn1_write(data, r->newsuperior,
390 strlen(r->newsuperior));
391 asn1_pop_tag(data);
393 asn1_pop_tag(data);
394 break;
396 case LDAP_TAG_ModifyDNResponse: {
397 struct ldap_Result *r = &msg->r.ModifyDNResponse;
398 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
399 ldap_encode_response(data, r);
400 asn1_pop_tag(data);
401 break;
403 case LDAP_TAG_CompareRequest: {
404 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
405 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
406 asn1_write_OctetString(data, r->dn, strlen(r->dn));
407 asn1_push_tag(data, ASN1_SEQUENCE(0));
408 asn1_write_OctetString(data, r->attribute,
409 strlen(r->attribute));
410 asn1_write_OctetString(data, r->value.data,
411 r->value.length);
412 asn1_pop_tag(data);
413 asn1_pop_tag(data);
414 break;
416 case LDAP_TAG_CompareResponse: {
417 struct ldap_Result *r = &msg->r.ModifyDNResponse;
418 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
419 ldap_encode_response(data, r);
420 asn1_pop_tag(data);
421 break;
423 case LDAP_TAG_AbandonRequest: {
424 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
425 asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type));
426 asn1_write_implicit_Integer(data, r->messageid);
427 asn1_pop_tag(data);
428 break;
430 case LDAP_TAG_SearchResultReference: {
431 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
432 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
433 asn1_write_OctetString(data, r->referral, strlen(r->referral));
434 asn1_pop_tag(data);
435 break;
437 case LDAP_TAG_ExtendedRequest: {
438 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
439 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
440 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
441 asn1_write(data, r->oid, strlen(r->oid));
442 asn1_pop_tag(data);
443 if (r->value) {
444 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1));
445 asn1_write(data, r->value->data, r->value->length);
446 asn1_pop_tag(data);
448 asn1_pop_tag(data);
449 break;
451 case LDAP_TAG_ExtendedResponse: {
452 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
453 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
454 ldap_encode_response(data, &r->response);
455 if (r->oid) {
456 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(10));
457 asn1_write(data, r->oid, strlen(r->oid));
458 asn1_pop_tag(data);
460 if (r->value) {
461 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(11));
462 asn1_write(data, r->value->data, r->value->length);
463 asn1_pop_tag(data);
465 asn1_pop_tag(data);
466 break;
468 default:
469 return False;
472 if (msg->controls != NULL) {
473 asn1_push_tag(data, ASN1_CONTEXT(0));
475 for (i = 0; msg->controls[i] != NULL; i++) {
476 if (!ldap_encode_control(mem_ctx, data, msg->controls[i])) {
477 return False;
481 asn1_pop_tag(data);
484 asn1_pop_tag(data);
486 if (data->has_error) {
487 asn1_free(data);
488 return False;
491 *result = data_blob_talloc(mem_ctx, data->data, data->length);
492 asn1_free(data);
493 return True;
496 static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
497 DATA_BLOB blob)
499 char *result = talloc_size(mem_ctx, blob.length+1);
500 memcpy(result, blob.data, blob.length);
501 result[blob.length] = '\0';
502 return result;
505 static BOOL asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
506 struct asn1_data *data,
507 const char **result)
509 DATA_BLOB string;
510 if (!asn1_read_OctetString(data, mem_ctx, &string))
511 return False;
512 *result = blob2string_talloc(mem_ctx, string);
513 data_blob_free(&string);
514 return True;
517 static void ldap_decode_response(TALLOC_CTX *mem_ctx,
518 struct asn1_data *data,
519 struct ldap_Result *result)
521 asn1_read_enumerated(data, &result->resultcode);
522 asn1_read_OctetString_talloc(mem_ctx, data, &result->dn);
523 asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage);
524 if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
525 asn1_start_tag(data, ASN1_CONTEXT(3));
526 asn1_read_OctetString_talloc(mem_ctx, data, &result->referral);
527 asn1_end_tag(data);
528 } else {
529 result->referral = NULL;
533 static struct ldb_val **ldap_decode_substring(TALLOC_CTX *mem_ctx, struct ldb_val **chunks, int chunk_num, char *value)
536 chunks = talloc_realloc(mem_ctx, chunks, struct ldb_val *, chunk_num + 2);
537 if (chunks == NULL) {
538 return NULL;
541 chunks[chunk_num] = talloc(mem_ctx, struct ldb_val);
542 if (chunks[chunk_num] == NULL) {
543 return NULL;
546 chunks[chunk_num]->data = (uint8_t *)talloc_strdup(mem_ctx, value);
547 if (chunks[chunk_num]->data == NULL) {
548 return NULL;
550 chunks[chunk_num]->length = strlen(value);
552 chunks[chunk_num + 1] = '\0';
554 return chunks;
559 parse the ASN.1 formatted search string into a ldb_parse_tree
561 static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
562 struct asn1_data *data)
564 uint8_t filter_tag;
565 struct ldb_parse_tree *ret;
567 if (!asn1_peek_uint8(data, &filter_tag)) {
568 return NULL;
571 filter_tag &= 0x1f; /* strip off the asn1 stuff */
573 ret = talloc(mem_ctx, struct ldb_parse_tree);
574 if (ret == NULL) return NULL;
576 switch(filter_tag) {
577 case 0:
578 case 1:
579 /* AND or OR of one or more filters */
580 ret->operation = (filter_tag == 0)?LDB_OP_AND:LDB_OP_OR;
581 ret->u.list.num_elements = 0;
582 ret->u.list.elements = NULL;
584 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
585 goto failed;
588 while (asn1_tag_remaining(data) > 0) {
589 struct ldb_parse_tree *subtree;
590 subtree = ldap_decode_filter_tree(ret, data);
591 if (subtree == NULL) {
592 goto failed;
594 ret->u.list.elements =
595 talloc_realloc(ret, ret->u.list.elements,
596 struct ldb_parse_tree *,
597 ret->u.list.num_elements+1);
598 if (ret->u.list.elements == NULL) {
599 goto failed;
601 talloc_steal(ret->u.list.elements, subtree);
602 ret->u.list.elements[ret->u.list.num_elements] = subtree;
603 ret->u.list.num_elements++;
605 if (!asn1_end_tag(data)) {
606 goto failed;
608 break;
610 case 2:
611 /* 'not' operation */
612 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
613 goto failed;
616 ret->operation = LDB_OP_NOT;
617 ret->u.isnot.child = ldap_decode_filter_tree(ret, data);
618 if (ret->u.isnot.child == NULL) {
619 goto failed;
621 if (!asn1_end_tag(data)) {
622 goto failed;
624 break;
626 case 3: {
627 /* equalityMatch */
628 const char *attrib;
629 DATA_BLOB value;
631 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
632 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
633 asn1_read_OctetString(data, mem_ctx, &value);
634 asn1_end_tag(data);
635 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
636 goto failed;
639 ret->operation = LDB_OP_EQUALITY;
640 ret->u.equality.attr = talloc_steal(ret, attrib);
641 ret->u.equality.value.data = talloc_steal(ret, value.data);
642 ret->u.equality.value.length = value.length;
643 break;
645 case 4: {
646 /* substrings */
647 DATA_BLOB attr;
648 uint8_t subs_tag;
649 char *value;
650 int chunk_num = 0;
652 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
653 goto failed;
655 if (!asn1_read_OctetString(data, mem_ctx, &attr)) {
656 goto failed;
659 ret->operation = LDB_OP_SUBSTRING;
660 ret->u.substring.attr = talloc_strndup(ret, (char *)attr.data, attr.length);
661 ret->u.substring.chunks = NULL;
662 ret->u.substring.start_with_wildcard = 1;
663 ret->u.substring.end_with_wildcard = 1;
665 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
666 goto failed;
669 while (asn1_tag_remaining(data)) {
670 asn1_peek_uint8(data, &subs_tag);
671 subs_tag &= 0x1f; /* strip off the asn1 stuff */
672 if (subs_tag > 2) goto failed;
674 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(subs_tag));
675 asn1_read_LDAPString(data, mem_ctx, &value);
676 asn1_end_tag(data);
678 switch (subs_tag) {
679 case 0:
680 if (ret->u.substring.chunks != NULL) {
681 /* initial value found in the middle */
682 goto failed;
685 ret->u.substring.chunks = ldap_decode_substring(ret, NULL, 0, value);
686 if (ret->u.substring.chunks == NULL) {
687 goto failed;
690 ret->u.substring.start_with_wildcard = 0;
691 chunk_num = 1;
692 break;
694 case 1:
695 if (ret->u.substring.end_with_wildcard == 0) {
696 /* "any" value found after a "final" value */
697 goto failed;
700 ret->u.substring.chunks = ldap_decode_substring(ret,
701 ret->u.substring.chunks,
702 chunk_num,
703 value);
704 if (ret->u.substring.chunks == NULL) {
705 goto failed;
708 chunk_num++;
709 break;
711 case 2:
712 ret->u.substring.chunks = ldap_decode_substring(ret,
713 ret->u.substring.chunks,
714 chunk_num,
715 value);
716 if (ret->u.substring.chunks == NULL) {
717 goto failed;
720 ret->u.substring.end_with_wildcard = 0;
721 break;
723 default:
724 goto failed;
729 if (!asn1_end_tag(data)) { /* SEQUENCE */
730 goto failed;
733 if (!asn1_end_tag(data)) {
734 goto failed;
736 break;
738 case 5: {
739 /* greaterOrEqual */
740 const char *attrib;
741 DATA_BLOB value;
743 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
744 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
745 asn1_read_OctetString(data, mem_ctx, &value);
746 asn1_end_tag(data);
747 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
748 goto failed;
751 ret->operation = LDB_OP_GREATER;
752 ret->u.comparison.attr = talloc_steal(ret, attrib);
753 ret->u.comparison.value.data = talloc_steal(ret, value.data);
754 ret->u.comparison.value.length = value.length;
755 break;
757 case 6: {
758 /* lessOrEqual */
759 const char *attrib;
760 DATA_BLOB value;
762 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
763 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
764 asn1_read_OctetString(data, mem_ctx, &value);
765 asn1_end_tag(data);
766 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
767 goto failed;
770 ret->operation = LDB_OP_LESS;
771 ret->u.comparison.attr = talloc_steal(ret, attrib);
772 ret->u.comparison.value.data = talloc_steal(ret, value.data);
773 ret->u.comparison.value.length = value.length;
774 break;
776 case 7: {
777 /* Normal presence, "attribute=*" */
778 char *attr;
780 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(filter_tag))) {
781 goto failed;
783 if (!asn1_read_LDAPString(data, ret, &attr)) {
784 goto failed;
787 ret->operation = LDB_OP_PRESENT;
788 ret->u.present.attr = talloc_steal(ret, attr);
790 if (!asn1_end_tag(data)) {
791 goto failed;
793 break;
795 case 8: {
796 /* approx */
797 const char *attrib;
798 DATA_BLOB value;
800 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
801 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
802 asn1_read_OctetString(data, mem_ctx, &value);
803 asn1_end_tag(data);
804 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
805 goto failed;
808 ret->operation = LDB_OP_APPROX;
809 ret->u.comparison.attr = talloc_steal(ret, attrib);
810 ret->u.comparison.value.data = talloc_steal(ret, value.data);
811 ret->u.comparison.value.length = value.length;
812 break;
814 case 9: {
815 char *oid = NULL, *attr = NULL, *value;
816 uint8_t dnAttributes;
817 /* an extended search */
818 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
819 goto failed;
822 /* FIXME: read carefully rfc2251.txt there are a number of 'MUST's
823 we need to check we properly implement --SSS */
824 /* either oid or type must be defined */
825 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
826 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(1));
827 asn1_read_LDAPString(data, ret, &oid);
828 asn1_end_tag(data);
830 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(2))) { /* optional */
831 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(2));
832 asn1_read_LDAPString(data, ret, &attr);
833 asn1_end_tag(data);
835 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(3));
836 asn1_read_LDAPString(data, ret, &value);
837 asn1_end_tag(data);
838 /* dnAttributes is marked as BOOLEAN DEFAULT FALSE
839 it is not marked as OPTIONAL but openldap tools
840 do not set this unless it is to be set as TRUE
841 NOTE: openldap tools do not work with AD as it
842 seems that AD always requires the dnAttributes
843 boolean value to be set */
844 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(4))) {
845 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(4));
846 asn1_read_uint8(data, &dnAttributes);
847 asn1_end_tag(data);
848 } else {
849 dnAttributes = 0;
851 if ((oid == NULL && attr == NULL) || (value == NULL)) {
852 goto failed;
855 if (oid) {
856 ret->operation = LDB_OP_EXTENDED;
858 /* From the RFC2251: If the type field is
859 absent and matchingRule is present, the matchValue is compared
860 against all attributes in an entry which support that matchingRule
862 if (attr) {
863 ret->u.extended.attr = talloc_steal(ret, attr);
864 } else {
865 ret->u.extended.attr = talloc_strdup(ret, "*");
867 ret->u.extended.rule_id = talloc_steal(ret, oid);
868 ret->u.extended.value.data = talloc_steal(ret, value);
869 ret->u.extended.value.length = strlen(value);
870 ret->u.extended.dnAttributes = dnAttributes;
871 } else {
872 ret->operation = LDB_OP_EQUALITY;
873 ret->u.equality.attr = talloc_steal(ret, attr);
874 ret->u.equality.value.data = talloc_steal(ret, value);
875 ret->u.equality.value.length = strlen(value);
877 if (!asn1_end_tag(data)) {
878 goto failed;
880 break;
883 default:
884 DEBUG(0,("Unsupported LDAP filter operation 0x%x\n", filter_tag));
885 goto failed;
888 return ret;
890 failed:
891 talloc_free(ret);
892 return NULL;
896 static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
897 struct ldb_message_element *attrib)
899 asn1_start_tag(data, ASN1_SEQUENCE(0));
900 asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name);
901 asn1_start_tag(data, ASN1_SET);
902 while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
903 DATA_BLOB blob;
904 asn1_read_OctetString(data, mem_ctx, &blob);
905 add_value_to_attrib(mem_ctx, &blob, attrib);
907 asn1_end_tag(data);
908 asn1_end_tag(data);
912 static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
913 struct ldb_message_element **attributes,
914 int *num_attributes)
916 asn1_start_tag(data, ASN1_SEQUENCE(0));
917 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
918 struct ldb_message_element attrib;
919 ZERO_STRUCT(attrib);
920 ldap_decode_attrib(mem_ctx, data, &attrib);
921 add_attrib_to_array_talloc(mem_ctx, &attrib,
922 attributes, num_attributes);
924 asn1_end_tag(data);
927 /* This routine returns LDAP status codes */
929 NTSTATUS ldap_decode(struct asn1_data *data, struct ldap_message *msg)
931 uint8_t tag;
933 asn1_start_tag(data, ASN1_SEQUENCE(0));
934 asn1_read_Integer(data, &msg->messageid);
936 if (!asn1_peek_uint8(data, &tag))
937 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
939 switch(tag) {
941 case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
942 struct ldap_BindRequest *r = &msg->r.BindRequest;
943 msg->type = LDAP_TAG_BindRequest;
944 asn1_start_tag(data, tag);
945 asn1_read_Integer(data, &r->version);
946 asn1_read_OctetString_talloc(msg, data, &r->dn);
947 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
948 int pwlen;
949 r->creds.password = "";
950 r->mechanism = LDAP_AUTH_MECH_SIMPLE;
951 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
952 pwlen = asn1_tag_remaining(data);
953 if (pwlen == -1) {
954 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
956 if (pwlen != 0) {
957 char *pw = talloc_size(msg, pwlen+1);
958 if (!pw) {
959 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
961 asn1_read(data, pw, pwlen);
962 pw[pwlen] = '\0';
963 r->creds.password = pw;
965 asn1_end_tag(data);
966 } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
967 asn1_start_tag(data, ASN1_CONTEXT(3));
968 r->mechanism = LDAP_AUTH_MECH_SASL;
969 asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism);
970 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) { /* optional */
971 DATA_BLOB tmp_blob = data_blob(NULL, 0);
972 asn1_read_OctetString(data, msg, &tmp_blob);
973 r->creds.SASL.secblob = talloc(msg, DATA_BLOB);
974 if (!r->creds.SASL.secblob) {
975 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
977 *r->creds.SASL.secblob = data_blob_talloc(r->creds.SASL.secblob,
978 tmp_blob.data, tmp_blob.length);
979 data_blob_free(&tmp_blob);
980 } else {
981 r->creds.SASL.secblob = NULL;
983 asn1_end_tag(data);
984 } else {
985 /* Neither Simple nor SASL bind */
986 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
988 asn1_end_tag(data);
989 break;
992 case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
993 struct ldap_BindResponse *r = &msg->r.BindResponse;
994 msg->type = LDAP_TAG_BindResponse;
995 asn1_start_tag(data, tag);
996 ldap_decode_response(msg, data, &r->response);
997 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
998 DATA_BLOB tmp_blob = data_blob(NULL, 0);
999 asn1_read_ContextSimple(data, 7, &tmp_blob);
1000 r->SASL.secblob = talloc(msg, DATA_BLOB);
1001 if (!r->SASL.secblob) {
1002 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1004 *r->SASL.secblob = data_blob_talloc(r->SASL.secblob,
1005 tmp_blob.data, tmp_blob.length);
1006 data_blob_free(&tmp_blob);
1007 } else {
1008 r->SASL.secblob = NULL;
1010 asn1_end_tag(data);
1011 break;
1014 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
1015 msg->type = LDAP_TAG_UnbindRequest;
1016 asn1_start_tag(data, tag);
1017 asn1_end_tag(data);
1018 break;
1021 case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
1022 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
1023 msg->type = LDAP_TAG_SearchRequest;
1024 asn1_start_tag(data, tag);
1025 asn1_read_OctetString_talloc(msg, data, &r->basedn);
1026 asn1_read_enumerated(data, (int *)&(r->scope));
1027 asn1_read_enumerated(data, (int *)&(r->deref));
1028 asn1_read_Integer(data, &r->sizelimit);
1029 asn1_read_Integer(data, &r->timelimit);
1030 asn1_read_BOOLEAN(data, &r->attributesonly);
1032 r->tree = ldap_decode_filter_tree(msg, data);
1033 if (r->tree == NULL) {
1034 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1037 asn1_start_tag(data, ASN1_SEQUENCE(0));
1039 r->num_attributes = 0;
1040 r->attributes = NULL;
1042 while (asn1_tag_remaining(data) > 0) {
1044 const char *attr;
1045 if (!asn1_read_OctetString_talloc(msg, data,
1046 &attr))
1047 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1048 if (!add_string_to_array(msg, attr,
1049 &r->attributes,
1050 &r->num_attributes))
1051 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1054 asn1_end_tag(data);
1055 asn1_end_tag(data);
1056 break;
1059 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1060 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1061 msg->type = LDAP_TAG_SearchResultEntry;
1062 r->attributes = NULL;
1063 r->num_attributes = 0;
1064 asn1_start_tag(data, tag);
1065 asn1_read_OctetString_talloc(msg, data, &r->dn);
1066 ldap_decode_attribs(msg, data, &r->attributes,
1067 &r->num_attributes);
1068 asn1_end_tag(data);
1069 break;
1072 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1073 struct ldap_Result *r = &msg->r.SearchResultDone;
1074 msg->type = LDAP_TAG_SearchResultDone;
1075 asn1_start_tag(data, tag);
1076 ldap_decode_response(msg, data, r);
1077 asn1_end_tag(data);
1078 break;
1081 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1082 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
1083 msg->type = LDAP_TAG_SearchResultReference;
1084 asn1_start_tag(data, tag);
1085 asn1_read_OctetString_talloc(msg, data, &r->referral);
1086 asn1_end_tag(data);
1087 break;
1090 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1091 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1092 msg->type = LDAP_TAG_ModifyRequest;
1093 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
1094 asn1_read_OctetString_talloc(msg, data, &r->dn);
1095 asn1_start_tag(data, ASN1_SEQUENCE(0));
1097 r->num_mods = 0;
1098 r->mods = NULL;
1100 while (asn1_tag_remaining(data) > 0) {
1101 struct ldap_mod mod;
1102 int v;
1103 ZERO_STRUCT(mod);
1104 asn1_start_tag(data, ASN1_SEQUENCE(0));
1105 asn1_read_enumerated(data, &v);
1106 mod.type = v;
1107 ldap_decode_attrib(msg, data, &mod.attrib);
1108 asn1_end_tag(data);
1109 if (!add_mod_to_array_talloc(msg, &mod,
1110 &r->mods, &r->num_mods)) {
1111 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1115 asn1_end_tag(data);
1116 asn1_end_tag(data);
1117 break;
1120 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1121 struct ldap_Result *r = &msg->r.ModifyResponse;
1122 msg->type = LDAP_TAG_ModifyResponse;
1123 asn1_start_tag(data, tag);
1124 ldap_decode_response(msg, data, r);
1125 asn1_end_tag(data);
1126 break;
1129 case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1130 struct ldap_AddRequest *r = &msg->r.AddRequest;
1131 msg->type = LDAP_TAG_AddRequest;
1132 asn1_start_tag(data, tag);
1133 asn1_read_OctetString_talloc(msg, data, &r->dn);
1135 r->attributes = NULL;
1136 r->num_attributes = 0;
1137 ldap_decode_attribs(msg, data, &r->attributes,
1138 &r->num_attributes);
1140 asn1_end_tag(data);
1141 break;
1144 case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1145 struct ldap_Result *r = &msg->r.AddResponse;
1146 msg->type = LDAP_TAG_AddResponse;
1147 asn1_start_tag(data, tag);
1148 ldap_decode_response(msg, data, r);
1149 asn1_end_tag(data);
1150 break;
1153 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1154 struct ldap_DelRequest *r = &msg->r.DelRequest;
1155 int len;
1156 char *dn;
1157 msg->type = LDAP_TAG_DelRequest;
1158 asn1_start_tag(data,
1159 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
1160 len = asn1_tag_remaining(data);
1161 if (len == -1) {
1162 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1164 dn = talloc_size(msg, len+1);
1165 if (dn == NULL)
1166 break;
1167 asn1_read(data, dn, len);
1168 dn[len] = '\0';
1169 r->dn = dn;
1170 asn1_end_tag(data);
1171 break;
1174 case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1175 struct ldap_Result *r = &msg->r.DelResponse;
1176 msg->type = LDAP_TAG_DelResponse;
1177 asn1_start_tag(data, tag);
1178 ldap_decode_response(msg, data, r);
1179 asn1_end_tag(data);
1180 break;
1183 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1184 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1185 msg->type = LDAP_TAG_ModifyDNRequest;
1186 asn1_start_tag(data,
1187 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
1188 asn1_read_OctetString_talloc(msg, data, &r->dn);
1189 asn1_read_OctetString_talloc(msg, data, &r->newrdn);
1190 asn1_read_BOOLEAN(data, &r->deleteolddn);
1191 r->newsuperior = NULL;
1192 if (asn1_tag_remaining(data) > 0) {
1193 int len;
1194 char *newsup;
1195 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1196 len = asn1_tag_remaining(data);
1197 if (len == -1) {
1198 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1200 newsup = talloc_size(msg, len+1);
1201 if (newsup == NULL) {
1202 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1204 asn1_read(data, newsup, len);
1205 newsup[len] = '\0';
1206 r->newsuperior = newsup;
1207 asn1_end_tag(data);
1209 asn1_end_tag(data);
1210 break;
1213 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1214 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1215 msg->type = LDAP_TAG_ModifyDNResponse;
1216 asn1_start_tag(data, tag);
1217 ldap_decode_response(msg, data, r);
1218 asn1_end_tag(data);
1219 break;
1222 case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1223 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1224 msg->type = LDAP_TAG_CompareRequest;
1225 asn1_start_tag(data,
1226 ASN1_APPLICATION(LDAP_TAG_CompareRequest));
1227 asn1_read_OctetString_talloc(msg, data, &r->dn);
1228 asn1_start_tag(data, ASN1_SEQUENCE(0));
1229 asn1_read_OctetString_talloc(msg, data, &r->attribute);
1230 asn1_read_OctetString(data, msg, &r->value);
1231 if (r->value.data) {
1232 talloc_steal(msg, r->value.data);
1234 asn1_end_tag(data);
1235 asn1_end_tag(data);
1236 break;
1239 case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1240 struct ldap_Result *r = &msg->r.CompareResponse;
1241 msg->type = LDAP_TAG_CompareResponse;
1242 asn1_start_tag(data, tag);
1243 ldap_decode_response(msg, data, r);
1244 asn1_end_tag(data);
1245 break;
1248 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1249 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1250 msg->type = LDAP_TAG_AbandonRequest;
1251 asn1_start_tag(data, tag);
1252 asn1_read_implicit_Integer(data, &r->messageid);
1253 asn1_end_tag(data);
1254 break;
1257 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1258 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1259 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1261 msg->type = LDAP_TAG_ExtendedRequest;
1262 asn1_start_tag(data,tag);
1263 if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
1264 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1266 r->oid = blob2string_talloc(msg, tmp_blob);
1267 data_blob_free(&tmp_blob);
1268 if (!r->oid) {
1269 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1272 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1273 asn1_read_ContextSimple(data, 1, &tmp_blob);
1274 r->value = talloc(msg, DATA_BLOB);
1275 if (!r->value) {
1276 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1278 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1279 data_blob_free(&tmp_blob);
1280 } else {
1281 r->value = NULL;
1284 asn1_end_tag(data);
1285 break;
1288 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1289 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1290 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1292 msg->type = LDAP_TAG_ExtendedResponse;
1293 asn1_start_tag(data, tag);
1294 ldap_decode_response(msg, data, &r->response);
1296 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(10))) {
1297 asn1_read_ContextSimple(data, 1, &tmp_blob);
1298 r->oid = blob2string_talloc(msg, tmp_blob);
1299 data_blob_free(&tmp_blob);
1300 if (!r->oid) {
1301 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1303 } else {
1304 r->oid = NULL;
1307 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(11))) {
1308 asn1_read_ContextSimple(data, 1, &tmp_blob);
1309 r->value = talloc(msg, DATA_BLOB);
1310 if (!r->value) {
1311 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1313 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1314 data_blob_free(&tmp_blob);
1315 } else {
1316 r->value = NULL;
1319 asn1_end_tag(data);
1320 break;
1322 default:
1323 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1326 msg->controls = NULL;
1328 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1329 int i = 0;
1330 struct ldb_control **ctrl = NULL;
1332 asn1_start_tag(data, ASN1_CONTEXT(0));
1334 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1335 DATA_BLOB value;
1336 /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1338 ctrl = talloc_realloc(msg, ctrl, struct ldb_control *, i+2);
1339 if (!ctrl) {
1340 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1343 ctrl[i] = talloc(ctrl, struct ldb_control);
1344 if (!ctrl[i]) {
1345 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1348 if (!ldap_decode_control_wrapper(ctrl, data, ctrl[i], &value)) {
1349 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1352 if (!ldap_decode_control_value(ctrl, value, ctrl[i])) {
1353 if (ctrl[i]->critical) {
1354 return NT_STATUS_LDAP(LDAP_UNAVAILABLE_CRITICAL_EXTENSION);
1355 } else {
1356 talloc_free(ctrl[i]);
1357 ctrl[i] = NULL;
1359 } else {
1360 i++;
1364 if (ctrl != NULL) {
1365 ctrl[i] = NULL;
1368 msg->controls = ctrl;
1370 asn1_end_tag(data);
1373 asn1_end_tag(data);
1374 if ((data->has_error) || (data->nesting != NULL)) {
1375 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1377 return NT_STATUS_OK;
1382 return NT_STATUS_OK if a blob has enough bytes in it to be a full
1383 ldap packet. Set packet_size if true.
1385 NTSTATUS ldap_full_packet(void *private_data, DATA_BLOB blob, size_t *packet_size)
1387 return asn1_full_tag(blob, ASN1_SEQUENCE(0), packet_size);