s3: add prototype to fix the build
[Samba/ekacnet.git] / libcli / ldap / ldap_message.c
blob8b0f8a2ea1560f36f6f9e96dfd57fc31f9528f0b
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_message.h"
29 _PUBLIC_ struct ldap_message *new_ldap_message(TALLOC_CTX *mem_ctx)
31 return talloc_zero(mem_ctx, struct ldap_message);
35 static bool add_value_to_attrib(TALLOC_CTX *mem_ctx, struct ldb_val *value,
36 struct ldb_message_element *attrib)
38 attrib->values = talloc_realloc(mem_ctx,
39 attrib->values,
40 DATA_BLOB,
41 attrib->num_values+1);
42 if (attrib->values == NULL)
43 return false;
45 attrib->values[attrib->num_values].data = talloc_steal(attrib->values,
46 value->data);
47 attrib->values[attrib->num_values].length = value->length;
48 attrib->num_values += 1;
49 return true;
52 static bool add_attrib_to_array_talloc(TALLOC_CTX *mem_ctx,
53 const struct ldb_message_element *attrib,
54 struct ldb_message_element **attribs,
55 int *num_attribs)
57 *attribs = talloc_realloc(mem_ctx,
58 *attribs,
59 struct ldb_message_element,
60 *num_attribs+1);
62 if (*attribs == NULL)
63 return false;
65 (*attribs)[*num_attribs] = *attrib;
66 talloc_steal(*attribs, attrib->values);
67 talloc_steal(*attribs, attrib->name);
68 *num_attribs += 1;
69 return true;
72 static bool add_mod_to_array_talloc(TALLOC_CTX *mem_ctx,
73 struct ldap_mod *mod,
74 struct ldap_mod **mods,
75 int *num_mods)
77 *mods = talloc_realloc(mem_ctx, *mods, struct ldap_mod, (*num_mods)+1);
79 if (*mods == NULL)
80 return false;
82 (*mods)[*num_mods] = *mod;
83 *num_mods += 1;
84 return true;
87 static bool ldap_decode_control_value(void *mem_ctx, DATA_BLOB value,
88 const struct ldap_control_handler *handlers,
89 struct ldb_control *ctrl)
91 int i;
93 if (!handlers) {
94 return true;
97 for (i = 0; handlers[i].oid != NULL; i++) {
98 if (strcmp(handlers[i].oid, ctrl->oid) == 0) {
99 if (!handlers[i].decode || !handlers[i].decode(mem_ctx, value, &ctrl->data)) {
100 return false;
102 break;
105 if (handlers[i].oid == NULL) {
106 return false;
109 return true;
112 static bool ldap_decode_control_wrapper(void *mem_ctx, struct asn1_data *data,
113 struct ldb_control *ctrl, DATA_BLOB *value)
115 DATA_BLOB oid;
117 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
118 return false;
121 if (!asn1_read_OctetString(data, mem_ctx, &oid)) {
122 return false;
124 ctrl->oid = talloc_strndup(mem_ctx, (char *)oid.data, oid.length);
125 if (!ctrl->oid) {
126 return false;
129 if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
130 bool critical;
131 if (!asn1_read_BOOLEAN(data, &critical)) {
132 return false;
134 ctrl->critical = critical;
135 } else {
136 ctrl->critical = false;
139 ctrl->data = NULL;
141 if (!asn1_peek_tag(data, ASN1_OCTET_STRING)) {
142 *value = data_blob(NULL, 0);
143 goto end_tag;
146 if (!asn1_read_OctetString(data, mem_ctx, value)) {
147 return false;
150 end_tag:
151 if (!asn1_end_tag(data)) {
152 return false;
155 return true;
158 static bool ldap_encode_control(void *mem_ctx, struct asn1_data *data,
159 const struct ldap_control_handler *handlers,
160 struct ldb_control *ctrl)
162 DATA_BLOB value;
163 int i;
165 if (!handlers) {
166 return false;
169 for (i = 0; handlers[i].oid != NULL; i++) {
170 if (strcmp(handlers[i].oid, ctrl->oid) == 0) {
171 if (!handlers[i].encode) {
172 if (ctrl->critical) {
173 return false;
174 } else {
175 /* not encoding this control */
176 return true;
179 if (!handlers[i].encode(mem_ctx, ctrl->data, &value)) {
180 return false;
182 break;
185 if (handlers[i].oid == NULL) {
186 return false;
189 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
190 return false;
193 if (!asn1_write_OctetString(data, ctrl->oid, strlen(ctrl->oid))) {
194 return false;
197 if (ctrl->critical) {
198 if (!asn1_write_BOOLEAN(data, ctrl->critical)) {
199 return false;
203 if (!ctrl->data) {
204 goto pop_tag;
207 if (!asn1_write_OctetString(data, value.data, value.length)) {
208 return false;
211 pop_tag:
212 if (!asn1_pop_tag(data)) {
213 return false;
216 return true;
219 static bool ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree)
221 int i;
223 switch (tree->operation) {
224 case LDB_OP_AND:
225 case LDB_OP_OR:
226 asn1_push_tag(data, ASN1_CONTEXT(tree->operation==LDB_OP_AND?0:1));
227 for (i=0; i<tree->u.list.num_elements; i++) {
228 if (!ldap_push_filter(data, tree->u.list.elements[i])) {
229 return false;
232 asn1_pop_tag(data);
233 break;
235 case LDB_OP_NOT:
236 asn1_push_tag(data, ASN1_CONTEXT(2));
237 if (!ldap_push_filter(data, tree->u.isnot.child)) {
238 return false;
240 asn1_pop_tag(data);
241 break;
243 case LDB_OP_EQUALITY:
244 /* equality test */
245 asn1_push_tag(data, ASN1_CONTEXT(3));
246 asn1_write_OctetString(data, tree->u.equality.attr,
247 strlen(tree->u.equality.attr));
248 asn1_write_OctetString(data, tree->u.equality.value.data,
249 tree->u.equality.value.length);
250 asn1_pop_tag(data);
251 break;
253 case LDB_OP_SUBSTRING:
255 SubstringFilter ::= SEQUENCE {
256 type AttributeDescription,
257 -- at least one must be present
258 substrings SEQUENCE OF CHOICE {
259 initial [0] LDAPString,
260 any [1] LDAPString,
261 final [2] LDAPString } }
263 asn1_push_tag(data, ASN1_CONTEXT(4));
264 asn1_write_OctetString(data, tree->u.substring.attr, strlen(tree->u.substring.attr));
265 asn1_push_tag(data, ASN1_SEQUENCE(0));
266 i = 0;
267 if ( ! tree->u.substring.start_with_wildcard) {
268 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
269 asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i]);
270 asn1_pop_tag(data);
271 i++;
273 while (tree->u.substring.chunks[i]) {
274 int ctx;
276 if (( ! tree->u.substring.chunks[i + 1]) &&
277 (tree->u.substring.end_with_wildcard == 0)) {
278 ctx = 2;
279 } else {
280 ctx = 1;
282 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(ctx));
283 asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i]);
284 asn1_pop_tag(data);
285 i++;
287 asn1_pop_tag(data);
288 asn1_pop_tag(data);
289 break;
291 case LDB_OP_GREATER:
292 /* greaterOrEqual test */
293 asn1_push_tag(data, ASN1_CONTEXT(5));
294 asn1_write_OctetString(data, tree->u.comparison.attr,
295 strlen(tree->u.comparison.attr));
296 asn1_write_OctetString(data, tree->u.comparison.value.data,
297 tree->u.comparison.value.length);
298 asn1_pop_tag(data);
299 break;
301 case LDB_OP_LESS:
302 /* lessOrEqual test */
303 asn1_push_tag(data, ASN1_CONTEXT(6));
304 asn1_write_OctetString(data, tree->u.comparison.attr,
305 strlen(tree->u.comparison.attr));
306 asn1_write_OctetString(data, tree->u.comparison.value.data,
307 tree->u.comparison.value.length);
308 asn1_pop_tag(data);
309 break;
311 case LDB_OP_PRESENT:
312 /* present test */
313 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(7));
314 asn1_write_LDAPString(data, tree->u.present.attr);
315 asn1_pop_tag(data);
316 return !data->has_error;
318 case LDB_OP_APPROX:
319 /* approx test */
320 asn1_push_tag(data, ASN1_CONTEXT(8));
321 asn1_write_OctetString(data, tree->u.comparison.attr,
322 strlen(tree->u.comparison.attr));
323 asn1_write_OctetString(data, tree->u.comparison.value.data,
324 tree->u.comparison.value.length);
325 asn1_pop_tag(data);
326 break;
328 case LDB_OP_EXTENDED:
330 MatchingRuleAssertion ::= SEQUENCE {
331 matchingRule [1] MatchingRuleID OPTIONAL,
332 type [2] AttributeDescription OPTIONAL,
333 matchValue [3] AssertionValue,
334 dnAttributes [4] BOOLEAN DEFAULT FALSE
337 asn1_push_tag(data, ASN1_CONTEXT(9));
338 if (tree->u.extended.rule_id) {
339 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1));
340 asn1_write_LDAPString(data, tree->u.extended.rule_id);
341 asn1_pop_tag(data);
343 if (tree->u.extended.attr) {
344 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(2));
345 asn1_write_LDAPString(data, tree->u.extended.attr);
346 asn1_pop_tag(data);
348 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(3));
349 asn1_write_DATA_BLOB_LDAPString(data, &tree->u.extended.value);
350 asn1_pop_tag(data);
351 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(4));
352 asn1_write_uint8(data, tree->u.extended.dnAttributes);
353 asn1_pop_tag(data);
354 asn1_pop_tag(data);
355 break;
357 default:
358 return false;
360 return !data->has_error;
363 static void ldap_encode_response(struct asn1_data *data, struct ldap_Result *result)
365 asn1_write_enumerated(data, result->resultcode);
366 asn1_write_OctetString(data, result->dn,
367 (result->dn) ? strlen(result->dn) : 0);
368 asn1_write_OctetString(data, result->errormessage,
369 (result->errormessage) ?
370 strlen(result->errormessage) : 0);
371 if (result->referral) {
372 asn1_push_tag(data, ASN1_CONTEXT(3));
373 asn1_write_OctetString(data, result->referral,
374 strlen(result->referral));
375 asn1_pop_tag(data);
379 _PUBLIC_ bool ldap_encode(struct ldap_message *msg,
380 const struct ldap_control_handler *control_handlers,
381 DATA_BLOB *result, TALLOC_CTX *mem_ctx)
383 struct asn1_data *data = asn1_init(mem_ctx);
384 int i, j;
386 if (!data) return false;
388 asn1_push_tag(data, ASN1_SEQUENCE(0));
389 asn1_write_Integer(data, msg->messageid);
391 switch (msg->type) {
392 case LDAP_TAG_BindRequest: {
393 struct ldap_BindRequest *r = &msg->r.BindRequest;
394 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
395 asn1_write_Integer(data, r->version);
396 asn1_write_OctetString(data, r->dn,
397 (r->dn != NULL) ? strlen(r->dn) : 0);
399 switch (r->mechanism) {
400 case LDAP_AUTH_MECH_SIMPLE:
401 /* context, primitive */
402 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
403 asn1_write(data, r->creds.password,
404 strlen(r->creds.password));
405 asn1_pop_tag(data);
406 break;
407 case LDAP_AUTH_MECH_SASL:
408 /* context, constructed */
409 asn1_push_tag(data, ASN1_CONTEXT(3));
410 asn1_write_OctetString(data, r->creds.SASL.mechanism,
411 strlen(r->creds.SASL.mechanism));
412 if (r->creds.SASL.secblob) {
413 asn1_write_OctetString(data, r->creds.SASL.secblob->data,
414 r->creds.SASL.secblob->length);
416 asn1_pop_tag(data);
417 break;
418 default:
419 return false;
422 asn1_pop_tag(data);
423 break;
425 case LDAP_TAG_BindResponse: {
426 struct ldap_BindResponse *r = &msg->r.BindResponse;
427 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
428 ldap_encode_response(data, &r->response);
429 if (r->SASL.secblob) {
430 asn1_write_ContextSimple(data, 7, r->SASL.secblob);
432 asn1_pop_tag(data);
433 break;
435 case LDAP_TAG_UnbindRequest: {
436 /* struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
437 break;
439 case LDAP_TAG_SearchRequest: {
440 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
441 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
442 asn1_write_OctetString(data, r->basedn, strlen(r->basedn));
443 asn1_write_enumerated(data, r->scope);
444 asn1_write_enumerated(data, r->deref);
445 asn1_write_Integer(data, r->sizelimit);
446 asn1_write_Integer(data, r->timelimit);
447 asn1_write_BOOLEAN(data, r->attributesonly);
449 if (!ldap_push_filter(data, r->tree)) {
450 return false;
453 asn1_push_tag(data, ASN1_SEQUENCE(0));
454 for (i=0; i<r->num_attributes; i++) {
455 asn1_write_OctetString(data, r->attributes[i],
456 strlen(r->attributes[i]));
458 asn1_pop_tag(data);
459 asn1_pop_tag(data);
460 break;
462 case LDAP_TAG_SearchResultEntry: {
463 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
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 for (i=0; i<r->num_attributes; i++) {
468 struct ldb_message_element *attr = &r->attributes[i];
469 asn1_push_tag(data, ASN1_SEQUENCE(0));
470 asn1_write_OctetString(data, attr->name,
471 strlen(attr->name));
472 asn1_push_tag(data, ASN1_SEQUENCE(1));
473 for (j=0; j<attr->num_values; j++) {
474 asn1_write_OctetString(data,
475 attr->values[j].data,
476 attr->values[j].length);
478 asn1_pop_tag(data);
479 asn1_pop_tag(data);
481 asn1_pop_tag(data);
482 asn1_pop_tag(data);
483 break;
485 case LDAP_TAG_SearchResultDone: {
486 struct ldap_Result *r = &msg->r.SearchResultDone;
487 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
488 ldap_encode_response(data, r);
489 asn1_pop_tag(data);
490 break;
492 case LDAP_TAG_ModifyRequest: {
493 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
494 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
495 asn1_write_OctetString(data, r->dn, strlen(r->dn));
496 asn1_push_tag(data, ASN1_SEQUENCE(0));
498 for (i=0; i<r->num_mods; i++) {
499 struct ldb_message_element *attrib = &r->mods[i].attrib;
500 asn1_push_tag(data, ASN1_SEQUENCE(0));
501 asn1_write_enumerated(data, r->mods[i].type);
502 asn1_push_tag(data, ASN1_SEQUENCE(0));
503 asn1_write_OctetString(data, attrib->name,
504 strlen(attrib->name));
505 asn1_push_tag(data, ASN1_SET);
506 for (j=0; j<attrib->num_values; j++) {
507 asn1_write_OctetString(data,
508 attrib->values[j].data,
509 attrib->values[j].length);
512 asn1_pop_tag(data);
513 asn1_pop_tag(data);
514 asn1_pop_tag(data);
517 asn1_pop_tag(data);
518 asn1_pop_tag(data);
519 break;
521 case LDAP_TAG_ModifyResponse: {
522 struct ldap_Result *r = &msg->r.ModifyResponse;
523 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
524 ldap_encode_response(data, r);
525 asn1_pop_tag(data);
526 break;
528 case LDAP_TAG_AddRequest: {
529 struct ldap_AddRequest *r = &msg->r.AddRequest;
530 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
531 asn1_write_OctetString(data, r->dn, strlen(r->dn));
532 asn1_push_tag(data, ASN1_SEQUENCE(0));
534 for (i=0; i<r->num_attributes; i++) {
535 struct ldb_message_element *attrib = &r->attributes[i];
536 asn1_push_tag(data, ASN1_SEQUENCE(0));
537 asn1_write_OctetString(data, attrib->name,
538 strlen(attrib->name));
539 asn1_push_tag(data, ASN1_SET);
540 for (j=0; j<r->attributes[i].num_values; j++) {
541 asn1_write_OctetString(data,
542 attrib->values[j].data,
543 attrib->values[j].length);
545 asn1_pop_tag(data);
546 asn1_pop_tag(data);
548 asn1_pop_tag(data);
549 asn1_pop_tag(data);
550 break;
552 case LDAP_TAG_AddResponse: {
553 struct ldap_Result *r = &msg->r.AddResponse;
554 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
555 ldap_encode_response(data, r);
556 asn1_pop_tag(data);
557 break;
559 case LDAP_TAG_DelRequest: {
560 struct ldap_DelRequest *r = &msg->r.DelRequest;
561 asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type));
562 asn1_write(data, r->dn, strlen(r->dn));
563 asn1_pop_tag(data);
564 break;
566 case LDAP_TAG_DelResponse: {
567 struct ldap_Result *r = &msg->r.DelResponse;
568 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
569 ldap_encode_response(data, r);
570 asn1_pop_tag(data);
571 break;
573 case LDAP_TAG_ModifyDNRequest: {
574 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
575 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
576 asn1_write_OctetString(data, r->dn, strlen(r->dn));
577 asn1_write_OctetString(data, r->newrdn, strlen(r->newrdn));
578 asn1_write_BOOLEAN(data, r->deleteolddn);
579 if (r->newsuperior) {
580 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
581 asn1_write(data, r->newsuperior,
582 strlen(r->newsuperior));
583 asn1_pop_tag(data);
585 asn1_pop_tag(data);
586 break;
588 case LDAP_TAG_ModifyDNResponse: {
589 struct ldap_Result *r = &msg->r.ModifyDNResponse;
590 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
591 ldap_encode_response(data, r);
592 asn1_pop_tag(data);
593 break;
595 case LDAP_TAG_CompareRequest: {
596 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
597 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
598 asn1_write_OctetString(data, r->dn, strlen(r->dn));
599 asn1_push_tag(data, ASN1_SEQUENCE(0));
600 asn1_write_OctetString(data, r->attribute,
601 strlen(r->attribute));
602 asn1_write_OctetString(data, r->value.data,
603 r->value.length);
604 asn1_pop_tag(data);
605 asn1_pop_tag(data);
606 break;
608 case LDAP_TAG_CompareResponse: {
609 struct ldap_Result *r = &msg->r.ModifyDNResponse;
610 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
611 ldap_encode_response(data, r);
612 asn1_pop_tag(data);
613 break;
615 case LDAP_TAG_AbandonRequest: {
616 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
617 asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type));
618 asn1_write_implicit_Integer(data, r->messageid);
619 asn1_pop_tag(data);
620 break;
622 case LDAP_TAG_SearchResultReference: {
623 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
624 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
625 asn1_write_OctetString(data, r->referral, strlen(r->referral));
626 asn1_pop_tag(data);
627 break;
629 case LDAP_TAG_ExtendedRequest: {
630 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
631 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
632 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
633 asn1_write(data, r->oid, strlen(r->oid));
634 asn1_pop_tag(data);
635 if (r->value) {
636 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1));
637 asn1_write(data, r->value->data, r->value->length);
638 asn1_pop_tag(data);
640 asn1_pop_tag(data);
641 break;
643 case LDAP_TAG_ExtendedResponse: {
644 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
645 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
646 ldap_encode_response(data, &r->response);
647 if (r->oid) {
648 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(10));
649 asn1_write(data, r->oid, strlen(r->oid));
650 asn1_pop_tag(data);
652 if (r->value) {
653 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(11));
654 asn1_write(data, r->value->data, r->value->length);
655 asn1_pop_tag(data);
657 asn1_pop_tag(data);
658 break;
660 default:
661 return false;
664 if (msg->controls != NULL) {
665 asn1_push_tag(data, ASN1_CONTEXT(0));
667 for (i = 0; msg->controls[i] != NULL; i++) {
668 if (!ldap_encode_control(mem_ctx, data,
669 control_handlers,
670 msg->controls[i])) {
671 return false;
675 asn1_pop_tag(data);
678 asn1_pop_tag(data);
680 if (data->has_error) {
681 asn1_free(data);
682 return false;
685 *result = data_blob_talloc(mem_ctx, data->data, data->length);
686 asn1_free(data);
687 return true;
690 static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
691 DATA_BLOB blob)
693 char *result = talloc_array(mem_ctx, char, blob.length+1);
694 memcpy(result, blob.data, blob.length);
695 result[blob.length] = '\0';
696 return result;
699 bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
700 struct asn1_data *data,
701 const char **result)
703 DATA_BLOB string;
704 if (!asn1_read_OctetString(data, mem_ctx, &string))
705 return false;
706 *result = blob2string_talloc(mem_ctx, string);
707 data_blob_free(&string);
708 return true;
711 static void ldap_decode_response(TALLOC_CTX *mem_ctx,
712 struct asn1_data *data,
713 struct ldap_Result *result)
715 asn1_read_enumerated(data, &result->resultcode);
716 asn1_read_OctetString_talloc(mem_ctx, data, &result->dn);
717 asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage);
718 if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
719 asn1_start_tag(data, ASN1_CONTEXT(3));
720 asn1_read_OctetString_talloc(mem_ctx, data, &result->referral);
721 asn1_end_tag(data);
722 } else {
723 result->referral = NULL;
727 static struct ldb_val **ldap_decode_substring(TALLOC_CTX *mem_ctx, struct ldb_val **chunks, int chunk_num, char *value)
730 chunks = talloc_realloc(mem_ctx, chunks, struct ldb_val *, chunk_num + 2);
731 if (chunks == NULL) {
732 return NULL;
735 chunks[chunk_num] = talloc(mem_ctx, struct ldb_val);
736 if (chunks[chunk_num] == NULL) {
737 return NULL;
740 chunks[chunk_num]->data = (uint8_t *)talloc_strdup(mem_ctx, value);
741 if (chunks[chunk_num]->data == NULL) {
742 return NULL;
744 chunks[chunk_num]->length = strlen(value);
746 chunks[chunk_num + 1] = '\0';
748 return chunks;
753 parse the ASN.1 formatted search string into a ldb_parse_tree
755 static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
756 struct asn1_data *data)
758 uint8_t filter_tag;
759 struct ldb_parse_tree *ret;
761 if (!asn1_peek_uint8(data, &filter_tag)) {
762 return NULL;
765 filter_tag &= 0x1f; /* strip off the asn1 stuff */
767 ret = talloc(mem_ctx, struct ldb_parse_tree);
768 if (ret == NULL) return NULL;
770 switch(filter_tag) {
771 case 0:
772 case 1:
773 /* AND or OR of one or more filters */
774 ret->operation = (filter_tag == 0)?LDB_OP_AND:LDB_OP_OR;
775 ret->u.list.num_elements = 0;
776 ret->u.list.elements = NULL;
778 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
779 goto failed;
782 while (asn1_tag_remaining(data) > 0) {
783 struct ldb_parse_tree *subtree;
784 subtree = ldap_decode_filter_tree(ret, data);
785 if (subtree == NULL) {
786 goto failed;
788 ret->u.list.elements =
789 talloc_realloc(ret, ret->u.list.elements,
790 struct ldb_parse_tree *,
791 ret->u.list.num_elements+1);
792 if (ret->u.list.elements == NULL) {
793 goto failed;
795 talloc_steal(ret->u.list.elements, subtree);
796 ret->u.list.elements[ret->u.list.num_elements] = subtree;
797 ret->u.list.num_elements++;
799 if (!asn1_end_tag(data)) {
800 goto failed;
802 break;
804 case 2:
805 /* 'not' operation */
806 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
807 goto failed;
810 ret->operation = LDB_OP_NOT;
811 ret->u.isnot.child = ldap_decode_filter_tree(ret, data);
812 if (ret->u.isnot.child == NULL) {
813 goto failed;
815 if (!asn1_end_tag(data)) {
816 goto failed;
818 break;
820 case 3: {
821 /* equalityMatch */
822 const char *attrib;
823 DATA_BLOB value;
825 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
826 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
827 asn1_read_OctetString(data, mem_ctx, &value);
828 asn1_end_tag(data);
829 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
830 goto failed;
833 ret->operation = LDB_OP_EQUALITY;
834 ret->u.equality.attr = talloc_steal(ret, attrib);
835 ret->u.equality.value.data = talloc_steal(ret, value.data);
836 ret->u.equality.value.length = value.length;
837 break;
839 case 4: {
840 /* substrings */
841 DATA_BLOB attr;
842 uint8_t subs_tag;
843 char *value;
844 int chunk_num = 0;
846 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
847 goto failed;
849 if (!asn1_read_OctetString(data, mem_ctx, &attr)) {
850 goto failed;
853 ret->operation = LDB_OP_SUBSTRING;
854 ret->u.substring.attr = talloc_strndup(ret, (char *)attr.data, attr.length);
855 ret->u.substring.chunks = NULL;
856 ret->u.substring.start_with_wildcard = 1;
857 ret->u.substring.end_with_wildcard = 1;
859 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
860 goto failed;
863 while (asn1_tag_remaining(data)) {
864 asn1_peek_uint8(data, &subs_tag);
865 subs_tag &= 0x1f; /* strip off the asn1 stuff */
866 if (subs_tag > 2) goto failed;
868 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(subs_tag));
869 asn1_read_LDAPString(data, mem_ctx, &value);
870 asn1_end_tag(data);
872 switch (subs_tag) {
873 case 0:
874 if (ret->u.substring.chunks != NULL) {
875 /* initial value found in the middle */
876 goto failed;
879 ret->u.substring.chunks = ldap_decode_substring(ret, NULL, 0, value);
880 if (ret->u.substring.chunks == NULL) {
881 goto failed;
884 ret->u.substring.start_with_wildcard = 0;
885 chunk_num = 1;
886 break;
888 case 1:
889 if (ret->u.substring.end_with_wildcard == 0) {
890 /* "any" value found after a "final" value */
891 goto failed;
894 ret->u.substring.chunks = ldap_decode_substring(ret,
895 ret->u.substring.chunks,
896 chunk_num,
897 value);
898 if (ret->u.substring.chunks == NULL) {
899 goto failed;
902 chunk_num++;
903 break;
905 case 2:
906 ret->u.substring.chunks = ldap_decode_substring(ret,
907 ret->u.substring.chunks,
908 chunk_num,
909 value);
910 if (ret->u.substring.chunks == NULL) {
911 goto failed;
914 ret->u.substring.end_with_wildcard = 0;
915 break;
917 default:
918 goto failed;
923 if (!asn1_end_tag(data)) { /* SEQUENCE */
924 goto failed;
927 if (!asn1_end_tag(data)) {
928 goto failed;
930 break;
932 case 5: {
933 /* greaterOrEqual */
934 const char *attrib;
935 DATA_BLOB value;
937 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
938 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
939 asn1_read_OctetString(data, mem_ctx, &value);
940 asn1_end_tag(data);
941 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
942 goto failed;
945 ret->operation = LDB_OP_GREATER;
946 ret->u.comparison.attr = talloc_steal(ret, attrib);
947 ret->u.comparison.value.data = talloc_steal(ret, value.data);
948 ret->u.comparison.value.length = value.length;
949 break;
951 case 6: {
952 /* lessOrEqual */
953 const char *attrib;
954 DATA_BLOB value;
956 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
957 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
958 asn1_read_OctetString(data, mem_ctx, &value);
959 asn1_end_tag(data);
960 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
961 goto failed;
964 ret->operation = LDB_OP_LESS;
965 ret->u.comparison.attr = talloc_steal(ret, attrib);
966 ret->u.comparison.value.data = talloc_steal(ret, value.data);
967 ret->u.comparison.value.length = value.length;
968 break;
970 case 7: {
971 /* Normal presence, "attribute=*" */
972 char *attr;
974 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(filter_tag))) {
975 goto failed;
977 if (!asn1_read_LDAPString(data, ret, &attr)) {
978 goto failed;
981 ret->operation = LDB_OP_PRESENT;
982 ret->u.present.attr = talloc_steal(ret, attr);
984 if (!asn1_end_tag(data)) {
985 goto failed;
987 break;
989 case 8: {
990 /* approx */
991 const char *attrib;
992 DATA_BLOB value;
994 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
995 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
996 asn1_read_OctetString(data, mem_ctx, &value);
997 asn1_end_tag(data);
998 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
999 goto failed;
1002 ret->operation = LDB_OP_APPROX;
1003 ret->u.comparison.attr = talloc_steal(ret, attrib);
1004 ret->u.comparison.value.data = talloc_steal(ret, value.data);
1005 ret->u.comparison.value.length = value.length;
1006 break;
1008 case 9: {
1009 char *oid = NULL, *attr = NULL, *value;
1010 uint8_t dnAttributes;
1011 /* an extended search */
1012 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
1013 goto failed;
1016 /* FIXME: read carefully rfc2251.txt there are a number of 'MUST's
1017 we need to check we properly implement --SSS */
1018 /* either oid or type must be defined */
1019 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
1020 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(1));
1021 asn1_read_LDAPString(data, ret, &oid);
1022 asn1_end_tag(data);
1024 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(2))) { /* optional */
1025 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(2));
1026 asn1_read_LDAPString(data, ret, &attr);
1027 asn1_end_tag(data);
1029 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(3));
1030 asn1_read_LDAPString(data, ret, &value);
1031 asn1_end_tag(data);
1032 /* dnAttributes is marked as BOOLEAN DEFAULT FALSE
1033 it is not marked as OPTIONAL but openldap tools
1034 do not set this unless it is to be set as TRUE
1035 NOTE: openldap tools do not work with AD as it
1036 seems that AD always requires the dnAttributes
1037 boolean value to be set */
1038 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(4))) {
1039 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(4));
1040 asn1_read_uint8(data, &dnAttributes);
1041 asn1_end_tag(data);
1042 } else {
1043 dnAttributes = 0;
1045 if ((oid == NULL && attr == NULL) || (value == NULL)) {
1046 goto failed;
1049 if (oid) {
1050 ret->operation = LDB_OP_EXTENDED;
1052 /* From the RFC2251: If the type field is
1053 absent and matchingRule is present, the matchValue is compared
1054 against all attributes in an entry which support that matchingRule
1056 if (attr) {
1057 ret->u.extended.attr = talloc_steal(ret, attr);
1058 } else {
1059 ret->u.extended.attr = talloc_strdup(ret, "*");
1061 ret->u.extended.rule_id = talloc_steal(ret, oid);
1062 ret->u.extended.value.data = (uint8_t *)talloc_steal(ret, value);
1063 ret->u.extended.value.length = strlen(value);
1064 ret->u.extended.dnAttributes = dnAttributes;
1065 } else {
1066 ret->operation = LDB_OP_EQUALITY;
1067 ret->u.equality.attr = talloc_steal(ret, attr);
1068 ret->u.equality.value.data = (uint8_t *)talloc_steal(ret, value);
1069 ret->u.equality.value.length = strlen(value);
1071 if (!asn1_end_tag(data)) {
1072 goto failed;
1074 break;
1077 default:
1078 goto failed;
1081 return ret;
1083 failed:
1084 talloc_free(ret);
1085 return NULL;
1088 /* Decode a single LDAP attribute, possibly containing multiple values */
1089 static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1090 struct ldb_message_element *attrib)
1092 asn1_start_tag(data, ASN1_SEQUENCE(0));
1093 asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name);
1094 asn1_start_tag(data, ASN1_SET);
1095 while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
1096 DATA_BLOB blob;
1097 asn1_read_OctetString(data, mem_ctx, &blob);
1098 add_value_to_attrib(mem_ctx, &blob, attrib);
1100 asn1_end_tag(data);
1101 asn1_end_tag(data);
1105 /* Decode a set of LDAP attributes, as found in the dereference control */
1106 void ldap_decode_attribs_bare(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1107 struct ldb_message_element **attributes,
1108 int *num_attributes)
1110 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1111 struct ldb_message_element attrib;
1112 ZERO_STRUCT(attrib);
1113 ldap_decode_attrib(mem_ctx, data, &attrib);
1114 add_attrib_to_array_talloc(mem_ctx, &attrib,
1115 attributes, num_attributes);
1119 /* Decode a set of LDAP attributes, as found in a search entry */
1120 static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1121 struct ldb_message_element **attributes,
1122 int *num_attributes)
1124 asn1_start_tag(data, ASN1_SEQUENCE(0));
1125 ldap_decode_attribs_bare(mem_ctx, data,
1126 attributes, num_attributes);
1127 asn1_end_tag(data);
1130 /* This routine returns LDAP status codes */
1132 _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
1133 const struct ldap_control_handler *control_handlers,
1134 struct ldap_message *msg)
1136 uint8_t tag;
1138 asn1_start_tag(data, ASN1_SEQUENCE(0));
1139 asn1_read_Integer(data, &msg->messageid);
1141 if (!asn1_peek_uint8(data, &tag))
1142 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1144 switch(tag) {
1146 case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
1147 struct ldap_BindRequest *r = &msg->r.BindRequest;
1148 msg->type = LDAP_TAG_BindRequest;
1149 asn1_start_tag(data, tag);
1150 asn1_read_Integer(data, &r->version);
1151 asn1_read_OctetString_talloc(msg, data, &r->dn);
1152 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
1153 int pwlen;
1154 r->creds.password = "";
1155 r->mechanism = LDAP_AUTH_MECH_SIMPLE;
1156 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1157 pwlen = asn1_tag_remaining(data);
1158 if (pwlen == -1) {
1159 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1161 if (pwlen != 0) {
1162 char *pw = talloc_array(msg, char, pwlen+1);
1163 if (!pw) {
1164 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1166 asn1_read(data, pw, pwlen);
1167 pw[pwlen] = '\0';
1168 r->creds.password = pw;
1170 asn1_end_tag(data);
1171 } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
1172 asn1_start_tag(data, ASN1_CONTEXT(3));
1173 r->mechanism = LDAP_AUTH_MECH_SASL;
1174 asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism);
1175 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) { /* optional */
1176 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1177 asn1_read_OctetString(data, msg, &tmp_blob);
1178 r->creds.SASL.secblob = talloc(msg, DATA_BLOB);
1179 if (!r->creds.SASL.secblob) {
1180 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1182 *r->creds.SASL.secblob = data_blob_talloc(r->creds.SASL.secblob,
1183 tmp_blob.data, tmp_blob.length);
1184 data_blob_free(&tmp_blob);
1185 } else {
1186 r->creds.SASL.secblob = NULL;
1188 asn1_end_tag(data);
1189 } else {
1190 /* Neither Simple nor SASL bind */
1191 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1193 asn1_end_tag(data);
1194 break;
1197 case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
1198 struct ldap_BindResponse *r = &msg->r.BindResponse;
1199 msg->type = LDAP_TAG_BindResponse;
1200 asn1_start_tag(data, tag);
1201 ldap_decode_response(msg, data, &r->response);
1202 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
1203 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1204 asn1_read_ContextSimple(data, 7, &tmp_blob);
1205 r->SASL.secblob = talloc(msg, DATA_BLOB);
1206 if (!r->SASL.secblob) {
1207 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1209 *r->SASL.secblob = data_blob_talloc(r->SASL.secblob,
1210 tmp_blob.data, tmp_blob.length);
1211 data_blob_free(&tmp_blob);
1212 } else {
1213 r->SASL.secblob = NULL;
1215 asn1_end_tag(data);
1216 break;
1219 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
1220 msg->type = LDAP_TAG_UnbindRequest;
1221 asn1_start_tag(data, tag);
1222 asn1_end_tag(data);
1223 break;
1226 case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
1227 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
1228 int sizelimit, timelimit;
1229 const char **attrs = NULL;
1230 msg->type = LDAP_TAG_SearchRequest;
1231 asn1_start_tag(data, tag);
1232 asn1_read_OctetString_talloc(msg, data, &r->basedn);
1233 asn1_read_enumerated(data, (int *)(void *)&(r->scope));
1234 asn1_read_enumerated(data, (int *)(void *)&(r->deref));
1235 asn1_read_Integer(data, &sizelimit);
1236 r->sizelimit = sizelimit;
1237 asn1_read_Integer(data, &timelimit);
1238 r->timelimit = timelimit;
1239 asn1_read_BOOLEAN(data, &r->attributesonly);
1241 r->tree = ldap_decode_filter_tree(msg, data);
1242 if (r->tree == NULL) {
1243 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1246 asn1_start_tag(data, ASN1_SEQUENCE(0));
1248 r->num_attributes = 0;
1249 r->attributes = NULL;
1251 while (asn1_tag_remaining(data) > 0) {
1253 const char *attr;
1254 if (!asn1_read_OctetString_talloc(msg, data,
1255 &attr))
1256 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1257 if (!add_string_to_array(msg, attr,
1258 &attrs,
1259 &r->num_attributes))
1260 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1262 r->attributes = attrs;
1264 asn1_end_tag(data);
1265 asn1_end_tag(data);
1266 break;
1269 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1270 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1271 msg->type = LDAP_TAG_SearchResultEntry;
1272 r->attributes = NULL;
1273 r->num_attributes = 0;
1274 asn1_start_tag(data, tag);
1275 asn1_read_OctetString_talloc(msg, data, &r->dn);
1276 ldap_decode_attribs(msg, data, &r->attributes,
1277 &r->num_attributes);
1278 asn1_end_tag(data);
1279 break;
1282 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1283 struct ldap_Result *r = &msg->r.SearchResultDone;
1284 msg->type = LDAP_TAG_SearchResultDone;
1285 asn1_start_tag(data, tag);
1286 ldap_decode_response(msg, data, r);
1287 asn1_end_tag(data);
1288 break;
1291 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1292 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
1293 msg->type = LDAP_TAG_SearchResultReference;
1294 asn1_start_tag(data, tag);
1295 asn1_read_OctetString_talloc(msg, data, &r->referral);
1296 asn1_end_tag(data);
1297 break;
1300 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1301 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1302 msg->type = LDAP_TAG_ModifyRequest;
1303 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
1304 asn1_read_OctetString_talloc(msg, data, &r->dn);
1305 asn1_start_tag(data, ASN1_SEQUENCE(0));
1307 r->num_mods = 0;
1308 r->mods = NULL;
1310 while (asn1_tag_remaining(data) > 0) {
1311 struct ldap_mod mod;
1312 int v;
1313 ZERO_STRUCT(mod);
1314 asn1_start_tag(data, ASN1_SEQUENCE(0));
1315 asn1_read_enumerated(data, &v);
1316 mod.type = v;
1317 ldap_decode_attrib(msg, data, &mod.attrib);
1318 asn1_end_tag(data);
1319 if (!add_mod_to_array_talloc(msg, &mod,
1320 &r->mods, &r->num_mods)) {
1321 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1325 asn1_end_tag(data);
1326 asn1_end_tag(data);
1327 break;
1330 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1331 struct ldap_Result *r = &msg->r.ModifyResponse;
1332 msg->type = LDAP_TAG_ModifyResponse;
1333 asn1_start_tag(data, tag);
1334 ldap_decode_response(msg, data, r);
1335 asn1_end_tag(data);
1336 break;
1339 case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1340 struct ldap_AddRequest *r = &msg->r.AddRequest;
1341 msg->type = LDAP_TAG_AddRequest;
1342 asn1_start_tag(data, tag);
1343 asn1_read_OctetString_talloc(msg, data, &r->dn);
1345 r->attributes = NULL;
1346 r->num_attributes = 0;
1347 ldap_decode_attribs(msg, data, &r->attributes,
1348 &r->num_attributes);
1350 asn1_end_tag(data);
1351 break;
1354 case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1355 struct ldap_Result *r = &msg->r.AddResponse;
1356 msg->type = LDAP_TAG_AddResponse;
1357 asn1_start_tag(data, tag);
1358 ldap_decode_response(msg, data, r);
1359 asn1_end_tag(data);
1360 break;
1363 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1364 struct ldap_DelRequest *r = &msg->r.DelRequest;
1365 int len;
1366 char *dn;
1367 msg->type = LDAP_TAG_DelRequest;
1368 asn1_start_tag(data,
1369 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
1370 len = asn1_tag_remaining(data);
1371 if (len == -1) {
1372 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1374 dn = talloc_array(msg, char, len+1);
1375 if (dn == NULL)
1376 break;
1377 asn1_read(data, dn, len);
1378 dn[len] = '\0';
1379 r->dn = dn;
1380 asn1_end_tag(data);
1381 break;
1384 case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1385 struct ldap_Result *r = &msg->r.DelResponse;
1386 msg->type = LDAP_TAG_DelResponse;
1387 asn1_start_tag(data, tag);
1388 ldap_decode_response(msg, data, r);
1389 asn1_end_tag(data);
1390 break;
1393 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1394 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1395 msg->type = LDAP_TAG_ModifyDNRequest;
1396 asn1_start_tag(data,
1397 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
1398 asn1_read_OctetString_talloc(msg, data, &r->dn);
1399 asn1_read_OctetString_talloc(msg, data, &r->newrdn);
1400 asn1_read_BOOLEAN(data, &r->deleteolddn);
1401 r->newsuperior = NULL;
1402 if (asn1_tag_remaining(data) > 0) {
1403 int len;
1404 char *newsup;
1405 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1406 len = asn1_tag_remaining(data);
1407 if (len == -1) {
1408 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1410 newsup = talloc_array(msg, char, len+1);
1411 if (newsup == NULL) {
1412 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1414 asn1_read(data, newsup, len);
1415 newsup[len] = '\0';
1416 r->newsuperior = newsup;
1417 asn1_end_tag(data);
1419 asn1_end_tag(data);
1420 break;
1423 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1424 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1425 msg->type = LDAP_TAG_ModifyDNResponse;
1426 asn1_start_tag(data, tag);
1427 ldap_decode_response(msg, data, r);
1428 asn1_end_tag(data);
1429 break;
1432 case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1433 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1434 msg->type = LDAP_TAG_CompareRequest;
1435 asn1_start_tag(data,
1436 ASN1_APPLICATION(LDAP_TAG_CompareRequest));
1437 asn1_read_OctetString_talloc(msg, data, &r->dn);
1438 asn1_start_tag(data, ASN1_SEQUENCE(0));
1439 asn1_read_OctetString_talloc(msg, data, &r->attribute);
1440 asn1_read_OctetString(data, msg, &r->value);
1441 if (r->value.data) {
1442 talloc_steal(msg, r->value.data);
1444 asn1_end_tag(data);
1445 asn1_end_tag(data);
1446 break;
1449 case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1450 struct ldap_Result *r = &msg->r.CompareResponse;
1451 msg->type = LDAP_TAG_CompareResponse;
1452 asn1_start_tag(data, tag);
1453 ldap_decode_response(msg, data, r);
1454 asn1_end_tag(data);
1455 break;
1458 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1459 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1460 msg->type = LDAP_TAG_AbandonRequest;
1461 asn1_start_tag(data, tag);
1462 asn1_read_implicit_Integer(data, &r->messageid);
1463 asn1_end_tag(data);
1464 break;
1467 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1468 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1469 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1471 msg->type = LDAP_TAG_ExtendedRequest;
1472 asn1_start_tag(data,tag);
1473 if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
1474 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1476 r->oid = blob2string_talloc(msg, tmp_blob);
1477 data_blob_free(&tmp_blob);
1478 if (!r->oid) {
1479 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1482 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1483 asn1_read_ContextSimple(data, 1, &tmp_blob);
1484 r->value = talloc(msg, DATA_BLOB);
1485 if (!r->value) {
1486 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1488 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1489 data_blob_free(&tmp_blob);
1490 } else {
1491 r->value = NULL;
1494 asn1_end_tag(data);
1495 break;
1498 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1499 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1500 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1502 msg->type = LDAP_TAG_ExtendedResponse;
1503 asn1_start_tag(data, tag);
1504 ldap_decode_response(msg, data, &r->response);
1506 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(10))) {
1507 asn1_read_ContextSimple(data, 1, &tmp_blob);
1508 r->oid = blob2string_talloc(msg, tmp_blob);
1509 data_blob_free(&tmp_blob);
1510 if (!r->oid) {
1511 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1513 } else {
1514 r->oid = NULL;
1517 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(11))) {
1518 asn1_read_ContextSimple(data, 1, &tmp_blob);
1519 r->value = talloc(msg, DATA_BLOB);
1520 if (!r->value) {
1521 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1523 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1524 data_blob_free(&tmp_blob);
1525 } else {
1526 r->value = NULL;
1529 asn1_end_tag(data);
1530 break;
1532 default:
1533 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1536 msg->controls = NULL;
1537 msg->controls_decoded = NULL;
1539 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1540 int i = 0;
1541 struct ldb_control **ctrl = NULL;
1542 bool *decoded = NULL;
1544 asn1_start_tag(data, ASN1_CONTEXT(0));
1546 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1547 DATA_BLOB value;
1548 /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1550 ctrl = talloc_realloc(msg, ctrl, struct ldb_control *, i+2);
1551 if (!ctrl) {
1552 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1555 decoded = talloc_realloc(msg, decoded, bool, i+1);
1556 if (!decoded) {
1557 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1560 ctrl[i] = talloc(ctrl, struct ldb_control);
1561 if (!ctrl[i]) {
1562 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1565 if (!ldap_decode_control_wrapper(ctrl, data, ctrl[i], &value)) {
1566 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1569 if (!ldap_decode_control_value(ctrl, value,
1570 control_handlers,
1571 ctrl[i])) {
1572 if (ctrl[i]->critical) {
1573 ctrl[i]->data = NULL;
1574 decoded[i] = false;
1575 i++;
1576 } else {
1577 talloc_free(ctrl[i]);
1578 ctrl[i] = NULL;
1580 } else {
1581 decoded[i] = true;
1582 i++;
1586 if (ctrl != NULL) {
1587 ctrl[i] = NULL;
1590 msg->controls = ctrl;
1591 msg->controls_decoded = decoded;
1593 asn1_end_tag(data);
1596 asn1_end_tag(data);
1597 if ((data->has_error) || (data->nesting != NULL)) {
1598 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1600 return NT_STATUS_OK;
1605 return NT_STATUS_OK if a blob has enough bytes in it to be a full
1606 ldap packet. Set packet_size if true.
1608 NTSTATUS ldap_full_packet(void *private_data, DATA_BLOB blob, size_t *packet_size)
1610 return asn1_full_tag(blob, ASN1_SEQUENCE(0), packet_size);