s3-lsa: Fix static list of luids in our privileges implementation.
[Samba/ekacnet.git] / libcli / ldap / ldap_message.c
blob1e4421442ca832324a6e2dd763294e8a97c6c9c7
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 DEBUG(1,("Unable to encode control %s\n",
672 msg->controls[i]->oid));
673 return false;
677 asn1_pop_tag(data);
680 asn1_pop_tag(data);
682 if (data->has_error) {
683 asn1_free(data);
684 return false;
687 *result = data_blob_talloc(mem_ctx, data->data, data->length);
688 asn1_free(data);
689 return true;
692 static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
693 DATA_BLOB blob)
695 char *result = talloc_array(mem_ctx, char, blob.length+1);
696 memcpy(result, blob.data, blob.length);
697 result[blob.length] = '\0';
698 return result;
701 bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
702 struct asn1_data *data,
703 const char **result)
705 DATA_BLOB string;
706 if (!asn1_read_OctetString(data, mem_ctx, &string))
707 return false;
708 *result = blob2string_talloc(mem_ctx, string);
709 data_blob_free(&string);
710 return true;
713 static void ldap_decode_response(TALLOC_CTX *mem_ctx,
714 struct asn1_data *data,
715 struct ldap_Result *result)
717 asn1_read_enumerated(data, &result->resultcode);
718 asn1_read_OctetString_talloc(mem_ctx, data, &result->dn);
719 asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage);
720 if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
721 asn1_start_tag(data, ASN1_CONTEXT(3));
722 asn1_read_OctetString_talloc(mem_ctx, data, &result->referral);
723 asn1_end_tag(data);
724 } else {
725 result->referral = NULL;
729 static struct ldb_val **ldap_decode_substring(TALLOC_CTX *mem_ctx, struct ldb_val **chunks, int chunk_num, char *value)
732 chunks = talloc_realloc(mem_ctx, chunks, struct ldb_val *, chunk_num + 2);
733 if (chunks == NULL) {
734 return NULL;
737 chunks[chunk_num] = talloc(mem_ctx, struct ldb_val);
738 if (chunks[chunk_num] == NULL) {
739 return NULL;
742 chunks[chunk_num]->data = (uint8_t *)talloc_strdup(mem_ctx, value);
743 if (chunks[chunk_num]->data == NULL) {
744 return NULL;
746 chunks[chunk_num]->length = strlen(value);
748 chunks[chunk_num + 1] = '\0';
750 return chunks;
755 parse the ASN.1 formatted search string into a ldb_parse_tree
757 static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
758 struct asn1_data *data)
760 uint8_t filter_tag;
761 struct ldb_parse_tree *ret;
763 if (!asn1_peek_uint8(data, &filter_tag)) {
764 return NULL;
767 filter_tag &= 0x1f; /* strip off the asn1 stuff */
769 ret = talloc(mem_ctx, struct ldb_parse_tree);
770 if (ret == NULL) return NULL;
772 switch(filter_tag) {
773 case 0:
774 case 1:
775 /* AND or OR of one or more filters */
776 ret->operation = (filter_tag == 0)?LDB_OP_AND:LDB_OP_OR;
777 ret->u.list.num_elements = 0;
778 ret->u.list.elements = NULL;
780 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
781 goto failed;
784 while (asn1_tag_remaining(data) > 0) {
785 struct ldb_parse_tree *subtree;
786 subtree = ldap_decode_filter_tree(ret, data);
787 if (subtree == NULL) {
788 goto failed;
790 ret->u.list.elements =
791 talloc_realloc(ret, ret->u.list.elements,
792 struct ldb_parse_tree *,
793 ret->u.list.num_elements+1);
794 if (ret->u.list.elements == NULL) {
795 goto failed;
797 talloc_steal(ret->u.list.elements, subtree);
798 ret->u.list.elements[ret->u.list.num_elements] = subtree;
799 ret->u.list.num_elements++;
801 if (!asn1_end_tag(data)) {
802 goto failed;
804 break;
806 case 2:
807 /* 'not' operation */
808 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
809 goto failed;
812 ret->operation = LDB_OP_NOT;
813 ret->u.isnot.child = ldap_decode_filter_tree(ret, data);
814 if (ret->u.isnot.child == NULL) {
815 goto failed;
817 if (!asn1_end_tag(data)) {
818 goto failed;
820 break;
822 case 3: {
823 /* equalityMatch */
824 const char *attrib;
825 DATA_BLOB value;
827 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
828 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
829 asn1_read_OctetString(data, mem_ctx, &value);
830 asn1_end_tag(data);
831 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
832 goto failed;
835 ret->operation = LDB_OP_EQUALITY;
836 ret->u.equality.attr = talloc_steal(ret, attrib);
837 ret->u.equality.value.data = talloc_steal(ret, value.data);
838 ret->u.equality.value.length = value.length;
839 break;
841 case 4: {
842 /* substrings */
843 DATA_BLOB attr;
844 uint8_t subs_tag;
845 char *value;
846 int chunk_num = 0;
848 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
849 goto failed;
851 if (!asn1_read_OctetString(data, mem_ctx, &attr)) {
852 goto failed;
855 ret->operation = LDB_OP_SUBSTRING;
856 ret->u.substring.attr = talloc_strndup(ret, (char *)attr.data, attr.length);
857 ret->u.substring.chunks = NULL;
858 ret->u.substring.start_with_wildcard = 1;
859 ret->u.substring.end_with_wildcard = 1;
861 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
862 goto failed;
865 while (asn1_tag_remaining(data)) {
866 asn1_peek_uint8(data, &subs_tag);
867 subs_tag &= 0x1f; /* strip off the asn1 stuff */
868 if (subs_tag > 2) goto failed;
870 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(subs_tag));
871 asn1_read_LDAPString(data, mem_ctx, &value);
872 asn1_end_tag(data);
874 switch (subs_tag) {
875 case 0:
876 if (ret->u.substring.chunks != NULL) {
877 /* initial value found in the middle */
878 goto failed;
881 ret->u.substring.chunks = ldap_decode_substring(ret, NULL, 0, value);
882 if (ret->u.substring.chunks == NULL) {
883 goto failed;
886 ret->u.substring.start_with_wildcard = 0;
887 chunk_num = 1;
888 break;
890 case 1:
891 if (ret->u.substring.end_with_wildcard == 0) {
892 /* "any" value found after a "final" value */
893 goto failed;
896 ret->u.substring.chunks = ldap_decode_substring(ret,
897 ret->u.substring.chunks,
898 chunk_num,
899 value);
900 if (ret->u.substring.chunks == NULL) {
901 goto failed;
904 chunk_num++;
905 break;
907 case 2:
908 ret->u.substring.chunks = ldap_decode_substring(ret,
909 ret->u.substring.chunks,
910 chunk_num,
911 value);
912 if (ret->u.substring.chunks == NULL) {
913 goto failed;
916 ret->u.substring.end_with_wildcard = 0;
917 break;
919 default:
920 goto failed;
925 if (!asn1_end_tag(data)) { /* SEQUENCE */
926 goto failed;
929 if (!asn1_end_tag(data)) {
930 goto failed;
932 break;
934 case 5: {
935 /* greaterOrEqual */
936 const char *attrib;
937 DATA_BLOB value;
939 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
940 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
941 asn1_read_OctetString(data, mem_ctx, &value);
942 asn1_end_tag(data);
943 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
944 goto failed;
947 ret->operation = LDB_OP_GREATER;
948 ret->u.comparison.attr = talloc_steal(ret, attrib);
949 ret->u.comparison.value.data = talloc_steal(ret, value.data);
950 ret->u.comparison.value.length = value.length;
951 break;
953 case 6: {
954 /* lessOrEqual */
955 const char *attrib;
956 DATA_BLOB value;
958 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
959 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
960 asn1_read_OctetString(data, mem_ctx, &value);
961 asn1_end_tag(data);
962 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
963 goto failed;
966 ret->operation = LDB_OP_LESS;
967 ret->u.comparison.attr = talloc_steal(ret, attrib);
968 ret->u.comparison.value.data = talloc_steal(ret, value.data);
969 ret->u.comparison.value.length = value.length;
970 break;
972 case 7: {
973 /* Normal presence, "attribute=*" */
974 char *attr;
976 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(filter_tag))) {
977 goto failed;
979 if (!asn1_read_LDAPString(data, ret, &attr)) {
980 goto failed;
983 ret->operation = LDB_OP_PRESENT;
984 ret->u.present.attr = talloc_steal(ret, attr);
986 if (!asn1_end_tag(data)) {
987 goto failed;
989 break;
991 case 8: {
992 /* approx */
993 const char *attrib;
994 DATA_BLOB value;
996 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
997 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
998 asn1_read_OctetString(data, mem_ctx, &value);
999 asn1_end_tag(data);
1000 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
1001 goto failed;
1004 ret->operation = LDB_OP_APPROX;
1005 ret->u.comparison.attr = talloc_steal(ret, attrib);
1006 ret->u.comparison.value.data = talloc_steal(ret, value.data);
1007 ret->u.comparison.value.length = value.length;
1008 break;
1010 case 9: {
1011 char *oid = NULL, *attr = NULL, *value;
1012 uint8_t dnAttributes;
1013 /* an extended search */
1014 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
1015 goto failed;
1018 /* FIXME: read carefully rfc2251.txt there are a number of 'MUST's
1019 we need to check we properly implement --SSS */
1020 /* either oid or type must be defined */
1021 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
1022 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(1));
1023 asn1_read_LDAPString(data, ret, &oid);
1024 asn1_end_tag(data);
1026 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(2))) { /* optional */
1027 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(2));
1028 asn1_read_LDAPString(data, ret, &attr);
1029 asn1_end_tag(data);
1031 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(3));
1032 asn1_read_LDAPString(data, ret, &value);
1033 asn1_end_tag(data);
1034 /* dnAttributes is marked as BOOLEAN DEFAULT FALSE
1035 it is not marked as OPTIONAL but openldap tools
1036 do not set this unless it is to be set as TRUE
1037 NOTE: openldap tools do not work with AD as it
1038 seems that AD always requires the dnAttributes
1039 boolean value to be set */
1040 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(4))) {
1041 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(4));
1042 asn1_read_uint8(data, &dnAttributes);
1043 asn1_end_tag(data);
1044 } else {
1045 dnAttributes = 0;
1047 if ((oid == NULL && attr == NULL) || (value == NULL)) {
1048 goto failed;
1051 if (oid) {
1052 ret->operation = LDB_OP_EXTENDED;
1054 /* From the RFC2251: If the type field is
1055 absent and matchingRule is present, the matchValue is compared
1056 against all attributes in an entry which support that matchingRule
1058 if (attr) {
1059 ret->u.extended.attr = talloc_steal(ret, attr);
1060 } else {
1061 ret->u.extended.attr = talloc_strdup(ret, "*");
1063 ret->u.extended.rule_id = talloc_steal(ret, oid);
1064 ret->u.extended.value.data = (uint8_t *)talloc_steal(ret, value);
1065 ret->u.extended.value.length = strlen(value);
1066 ret->u.extended.dnAttributes = dnAttributes;
1067 } else {
1068 ret->operation = LDB_OP_EQUALITY;
1069 ret->u.equality.attr = talloc_steal(ret, attr);
1070 ret->u.equality.value.data = (uint8_t *)talloc_steal(ret, value);
1071 ret->u.equality.value.length = strlen(value);
1073 if (!asn1_end_tag(data)) {
1074 goto failed;
1076 break;
1079 default:
1080 goto failed;
1083 return ret;
1085 failed:
1086 talloc_free(ret);
1087 return NULL;
1090 /* Decode a single LDAP attribute, possibly containing multiple values */
1091 static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1092 struct ldb_message_element *attrib)
1094 asn1_start_tag(data, ASN1_SEQUENCE(0));
1095 asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name);
1096 asn1_start_tag(data, ASN1_SET);
1097 while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
1098 DATA_BLOB blob;
1099 asn1_read_OctetString(data, mem_ctx, &blob);
1100 add_value_to_attrib(mem_ctx, &blob, attrib);
1102 asn1_end_tag(data);
1103 asn1_end_tag(data);
1107 /* Decode a set of LDAP attributes, as found in the dereference control */
1108 void ldap_decode_attribs_bare(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1109 struct ldb_message_element **attributes,
1110 int *num_attributes)
1112 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1113 struct ldb_message_element attrib;
1114 ZERO_STRUCT(attrib);
1115 ldap_decode_attrib(mem_ctx, data, &attrib);
1116 add_attrib_to_array_talloc(mem_ctx, &attrib,
1117 attributes, num_attributes);
1121 /* Decode a set of LDAP attributes, as found in a search entry */
1122 static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1123 struct ldb_message_element **attributes,
1124 int *num_attributes)
1126 asn1_start_tag(data, ASN1_SEQUENCE(0));
1127 ldap_decode_attribs_bare(mem_ctx, data,
1128 attributes, num_attributes);
1129 asn1_end_tag(data);
1132 /* This routine returns LDAP status codes */
1134 _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
1135 const struct ldap_control_handler *control_handlers,
1136 struct ldap_message *msg)
1138 uint8_t tag;
1140 asn1_start_tag(data, ASN1_SEQUENCE(0));
1141 asn1_read_Integer(data, &msg->messageid);
1143 if (!asn1_peek_uint8(data, &tag))
1144 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1146 switch(tag) {
1148 case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
1149 struct ldap_BindRequest *r = &msg->r.BindRequest;
1150 msg->type = LDAP_TAG_BindRequest;
1151 asn1_start_tag(data, tag);
1152 asn1_read_Integer(data, &r->version);
1153 asn1_read_OctetString_talloc(msg, data, &r->dn);
1154 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
1155 int pwlen;
1156 r->creds.password = "";
1157 r->mechanism = LDAP_AUTH_MECH_SIMPLE;
1158 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1159 pwlen = asn1_tag_remaining(data);
1160 if (pwlen == -1) {
1161 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1163 if (pwlen != 0) {
1164 char *pw = talloc_array(msg, char, pwlen+1);
1165 if (!pw) {
1166 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1168 asn1_read(data, pw, pwlen);
1169 pw[pwlen] = '\0';
1170 r->creds.password = pw;
1172 asn1_end_tag(data);
1173 } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
1174 asn1_start_tag(data, ASN1_CONTEXT(3));
1175 r->mechanism = LDAP_AUTH_MECH_SASL;
1176 asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism);
1177 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) { /* optional */
1178 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1179 asn1_read_OctetString(data, msg, &tmp_blob);
1180 r->creds.SASL.secblob = talloc(msg, DATA_BLOB);
1181 if (!r->creds.SASL.secblob) {
1182 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1184 *r->creds.SASL.secblob = data_blob_talloc(r->creds.SASL.secblob,
1185 tmp_blob.data, tmp_blob.length);
1186 data_blob_free(&tmp_blob);
1187 } else {
1188 r->creds.SASL.secblob = NULL;
1190 asn1_end_tag(data);
1191 } else {
1192 /* Neither Simple nor SASL bind */
1193 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1195 asn1_end_tag(data);
1196 break;
1199 case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
1200 struct ldap_BindResponse *r = &msg->r.BindResponse;
1201 msg->type = LDAP_TAG_BindResponse;
1202 asn1_start_tag(data, tag);
1203 ldap_decode_response(msg, data, &r->response);
1204 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
1205 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1206 asn1_read_ContextSimple(data, 7, &tmp_blob);
1207 r->SASL.secblob = talloc(msg, DATA_BLOB);
1208 if (!r->SASL.secblob) {
1209 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1211 *r->SASL.secblob = data_blob_talloc(r->SASL.secblob,
1212 tmp_blob.data, tmp_blob.length);
1213 data_blob_free(&tmp_blob);
1214 } else {
1215 r->SASL.secblob = NULL;
1217 asn1_end_tag(data);
1218 break;
1221 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
1222 msg->type = LDAP_TAG_UnbindRequest;
1223 asn1_start_tag(data, tag);
1224 asn1_end_tag(data);
1225 break;
1228 case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
1229 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
1230 int sizelimit, timelimit;
1231 const char **attrs = NULL;
1232 msg->type = LDAP_TAG_SearchRequest;
1233 asn1_start_tag(data, tag);
1234 asn1_read_OctetString_talloc(msg, data, &r->basedn);
1235 asn1_read_enumerated(data, (int *)(void *)&(r->scope));
1236 asn1_read_enumerated(data, (int *)(void *)&(r->deref));
1237 asn1_read_Integer(data, &sizelimit);
1238 r->sizelimit = sizelimit;
1239 asn1_read_Integer(data, &timelimit);
1240 r->timelimit = timelimit;
1241 asn1_read_BOOLEAN(data, &r->attributesonly);
1243 r->tree = ldap_decode_filter_tree(msg, data);
1244 if (r->tree == NULL) {
1245 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1248 asn1_start_tag(data, ASN1_SEQUENCE(0));
1250 r->num_attributes = 0;
1251 r->attributes = NULL;
1253 while (asn1_tag_remaining(data) > 0) {
1255 const char *attr;
1256 if (!asn1_read_OctetString_talloc(msg, data,
1257 &attr))
1258 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1259 if (!add_string_to_array(msg, attr,
1260 &attrs,
1261 &r->num_attributes))
1262 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1264 r->attributes = attrs;
1266 asn1_end_tag(data);
1267 asn1_end_tag(data);
1268 break;
1271 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1272 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1273 msg->type = LDAP_TAG_SearchResultEntry;
1274 r->attributes = NULL;
1275 r->num_attributes = 0;
1276 asn1_start_tag(data, tag);
1277 asn1_read_OctetString_talloc(msg, data, &r->dn);
1278 ldap_decode_attribs(msg, data, &r->attributes,
1279 &r->num_attributes);
1280 asn1_end_tag(data);
1281 break;
1284 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1285 struct ldap_Result *r = &msg->r.SearchResultDone;
1286 msg->type = LDAP_TAG_SearchResultDone;
1287 asn1_start_tag(data, tag);
1288 ldap_decode_response(msg, data, r);
1289 asn1_end_tag(data);
1290 break;
1293 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1294 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
1295 msg->type = LDAP_TAG_SearchResultReference;
1296 asn1_start_tag(data, tag);
1297 asn1_read_OctetString_talloc(msg, data, &r->referral);
1298 asn1_end_tag(data);
1299 break;
1302 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1303 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1304 msg->type = LDAP_TAG_ModifyRequest;
1305 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
1306 asn1_read_OctetString_talloc(msg, data, &r->dn);
1307 asn1_start_tag(data, ASN1_SEQUENCE(0));
1309 r->num_mods = 0;
1310 r->mods = NULL;
1312 while (asn1_tag_remaining(data) > 0) {
1313 struct ldap_mod mod;
1314 int v;
1315 ZERO_STRUCT(mod);
1316 asn1_start_tag(data, ASN1_SEQUENCE(0));
1317 asn1_read_enumerated(data, &v);
1318 mod.type = v;
1319 ldap_decode_attrib(msg, data, &mod.attrib);
1320 asn1_end_tag(data);
1321 if (!add_mod_to_array_talloc(msg, &mod,
1322 &r->mods, &r->num_mods)) {
1323 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1327 asn1_end_tag(data);
1328 asn1_end_tag(data);
1329 break;
1332 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1333 struct ldap_Result *r = &msg->r.ModifyResponse;
1334 msg->type = LDAP_TAG_ModifyResponse;
1335 asn1_start_tag(data, tag);
1336 ldap_decode_response(msg, data, r);
1337 asn1_end_tag(data);
1338 break;
1341 case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1342 struct ldap_AddRequest *r = &msg->r.AddRequest;
1343 msg->type = LDAP_TAG_AddRequest;
1344 asn1_start_tag(data, tag);
1345 asn1_read_OctetString_talloc(msg, data, &r->dn);
1347 r->attributes = NULL;
1348 r->num_attributes = 0;
1349 ldap_decode_attribs(msg, data, &r->attributes,
1350 &r->num_attributes);
1352 asn1_end_tag(data);
1353 break;
1356 case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1357 struct ldap_Result *r = &msg->r.AddResponse;
1358 msg->type = LDAP_TAG_AddResponse;
1359 asn1_start_tag(data, tag);
1360 ldap_decode_response(msg, data, r);
1361 asn1_end_tag(data);
1362 break;
1365 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1366 struct ldap_DelRequest *r = &msg->r.DelRequest;
1367 int len;
1368 char *dn;
1369 msg->type = LDAP_TAG_DelRequest;
1370 asn1_start_tag(data,
1371 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
1372 len = asn1_tag_remaining(data);
1373 if (len == -1) {
1374 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1376 dn = talloc_array(msg, char, len+1);
1377 if (dn == NULL)
1378 break;
1379 asn1_read(data, dn, len);
1380 dn[len] = '\0';
1381 r->dn = dn;
1382 asn1_end_tag(data);
1383 break;
1386 case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1387 struct ldap_Result *r = &msg->r.DelResponse;
1388 msg->type = LDAP_TAG_DelResponse;
1389 asn1_start_tag(data, tag);
1390 ldap_decode_response(msg, data, r);
1391 asn1_end_tag(data);
1392 break;
1395 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1396 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1397 msg->type = LDAP_TAG_ModifyDNRequest;
1398 asn1_start_tag(data,
1399 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
1400 asn1_read_OctetString_talloc(msg, data, &r->dn);
1401 asn1_read_OctetString_talloc(msg, data, &r->newrdn);
1402 asn1_read_BOOLEAN(data, &r->deleteolddn);
1403 r->newsuperior = NULL;
1404 if (asn1_tag_remaining(data) > 0) {
1405 int len;
1406 char *newsup;
1407 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1408 len = asn1_tag_remaining(data);
1409 if (len == -1) {
1410 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1412 newsup = talloc_array(msg, char, len+1);
1413 if (newsup == NULL) {
1414 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1416 asn1_read(data, newsup, len);
1417 newsup[len] = '\0';
1418 r->newsuperior = newsup;
1419 asn1_end_tag(data);
1421 asn1_end_tag(data);
1422 break;
1425 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1426 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1427 msg->type = LDAP_TAG_ModifyDNResponse;
1428 asn1_start_tag(data, tag);
1429 ldap_decode_response(msg, data, r);
1430 asn1_end_tag(data);
1431 break;
1434 case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1435 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1436 msg->type = LDAP_TAG_CompareRequest;
1437 asn1_start_tag(data,
1438 ASN1_APPLICATION(LDAP_TAG_CompareRequest));
1439 asn1_read_OctetString_talloc(msg, data, &r->dn);
1440 asn1_start_tag(data, ASN1_SEQUENCE(0));
1441 asn1_read_OctetString_talloc(msg, data, &r->attribute);
1442 asn1_read_OctetString(data, msg, &r->value);
1443 if (r->value.data) {
1444 talloc_steal(msg, r->value.data);
1446 asn1_end_tag(data);
1447 asn1_end_tag(data);
1448 break;
1451 case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1452 struct ldap_Result *r = &msg->r.CompareResponse;
1453 msg->type = LDAP_TAG_CompareResponse;
1454 asn1_start_tag(data, tag);
1455 ldap_decode_response(msg, data, r);
1456 asn1_end_tag(data);
1457 break;
1460 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1461 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1462 msg->type = LDAP_TAG_AbandonRequest;
1463 asn1_start_tag(data, tag);
1464 asn1_read_implicit_Integer(data, &r->messageid);
1465 asn1_end_tag(data);
1466 break;
1469 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1470 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1471 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1473 msg->type = LDAP_TAG_ExtendedRequest;
1474 asn1_start_tag(data,tag);
1475 if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
1476 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1478 r->oid = blob2string_talloc(msg, tmp_blob);
1479 data_blob_free(&tmp_blob);
1480 if (!r->oid) {
1481 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1484 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1485 asn1_read_ContextSimple(data, 1, &tmp_blob);
1486 r->value = talloc(msg, DATA_BLOB);
1487 if (!r->value) {
1488 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1490 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1491 data_blob_free(&tmp_blob);
1492 } else {
1493 r->value = NULL;
1496 asn1_end_tag(data);
1497 break;
1500 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1501 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1502 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1504 msg->type = LDAP_TAG_ExtendedResponse;
1505 asn1_start_tag(data, tag);
1506 ldap_decode_response(msg, data, &r->response);
1508 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(10))) {
1509 asn1_read_ContextSimple(data, 1, &tmp_blob);
1510 r->oid = blob2string_talloc(msg, tmp_blob);
1511 data_blob_free(&tmp_blob);
1512 if (!r->oid) {
1513 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1515 } else {
1516 r->oid = NULL;
1519 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(11))) {
1520 asn1_read_ContextSimple(data, 1, &tmp_blob);
1521 r->value = talloc(msg, DATA_BLOB);
1522 if (!r->value) {
1523 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1525 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1526 data_blob_free(&tmp_blob);
1527 } else {
1528 r->value = NULL;
1531 asn1_end_tag(data);
1532 break;
1534 default:
1535 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1538 msg->controls = NULL;
1539 msg->controls_decoded = NULL;
1541 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1542 int i = 0;
1543 struct ldb_control **ctrl = NULL;
1544 bool *decoded = NULL;
1546 asn1_start_tag(data, ASN1_CONTEXT(0));
1548 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1549 DATA_BLOB value;
1550 /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1552 ctrl = talloc_realloc(msg, ctrl, struct ldb_control *, i+2);
1553 if (!ctrl) {
1554 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1557 decoded = talloc_realloc(msg, decoded, bool, i+1);
1558 if (!decoded) {
1559 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1562 ctrl[i] = talloc(ctrl, struct ldb_control);
1563 if (!ctrl[i]) {
1564 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1567 if (!ldap_decode_control_wrapper(ctrl, data, ctrl[i], &value)) {
1568 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1571 if (!ldap_decode_control_value(ctrl, value,
1572 control_handlers,
1573 ctrl[i])) {
1574 if (ctrl[i]->critical) {
1575 ctrl[i]->data = NULL;
1576 decoded[i] = false;
1577 i++;
1578 } else {
1579 talloc_free(ctrl[i]);
1580 ctrl[i] = NULL;
1582 } else {
1583 decoded[i] = true;
1584 i++;
1588 if (ctrl != NULL) {
1589 ctrl[i] = NULL;
1592 msg->controls = ctrl;
1593 msg->controls_decoded = decoded;
1595 asn1_end_tag(data);
1598 asn1_end_tag(data);
1599 if ((data->has_error) || (data->nesting != NULL)) {
1600 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1602 return NT_STATUS_OK;
1607 return NT_STATUS_OK if a blob has enough bytes in it to be a full
1608 ldap packet. Set packet_size if true.
1610 NTSTATUS ldap_full_packet(void *private_data, DATA_BLOB blob, size_t *packet_size)
1612 return asn1_full_tag(blob, ASN1_SEQUENCE(0), packet_size);