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/>.
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,
41 attrib->num_values+1);
42 if (attrib->values == NULL)
45 attrib->values[attrib->num_values].data = talloc_steal(attrib->values,
47 attrib->values[attrib->num_values].length = value->length;
48 attrib->num_values += 1;
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,
57 *attribs = talloc_realloc(mem_ctx,
59 struct ldb_message_element,
65 (*attribs)[*num_attribs] = *attrib;
66 talloc_steal(*attribs, attrib->values);
67 talloc_steal(*attribs, attrib->name);
72 static bool add_mod_to_array_talloc(TALLOC_CTX *mem_ctx,
74 struct ldap_mod **mods,
77 *mods = talloc_realloc(mem_ctx, *mods, struct ldap_mod, (*num_mods)+1);
82 (*mods)[*num_mods] = *mod;
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)
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)) {
105 if (handlers[i].oid == NULL) {
112 static bool ldap_decode_control_wrapper(void *mem_ctx, struct asn1_data *data,
113 struct ldb_control *ctrl, DATA_BLOB *value)
117 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
121 if (!asn1_read_OctetString(data, mem_ctx, &oid)) {
124 ctrl->oid = talloc_strndup(mem_ctx, (char *)oid.data, oid.length);
129 if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
131 if (!asn1_read_BOOLEAN(data, &critical)) {
134 ctrl->critical = critical;
136 ctrl->critical = false;
141 if (!asn1_peek_tag(data, ASN1_OCTET_STRING)) {
142 *value = data_blob(NULL, 0);
146 if (!asn1_read_OctetString(data, mem_ctx, value)) {
151 if (!asn1_end_tag(data)) {
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)
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) {
175 /* not encoding this control */
179 if (!handlers[i].encode(mem_ctx, ctrl->data, &value)) {
185 if (handlers[i].oid == NULL) {
189 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
193 if (!asn1_write_OctetString(data, ctrl->oid, strlen(ctrl->oid))) {
197 if (ctrl->critical) {
198 if (!asn1_write_BOOLEAN(data, ctrl->critical)) {
207 if (!asn1_write_OctetString(data, value.data, value.length)) {
212 if (!asn1_pop_tag(data)) {
219 static bool ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree)
223 switch (tree->operation) {
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])) {
236 asn1_push_tag(data, ASN1_CONTEXT(2));
237 if (!ldap_push_filter(data, tree->u.isnot.child)) {
243 case LDB_OP_EQUALITY:
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);
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,
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));
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]);
273 while (tree->u.substring.chunks[i]) {
276 if (( ! tree->u.substring.chunks[i + 1]) &&
277 (tree->u.substring.end_with_wildcard == 0)) {
282 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(ctx));
283 asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i]);
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);
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);
313 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(7));
314 asn1_write_LDAPString(data, tree->u.present.attr);
316 return !data->has_error;
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);
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);
343 if (tree->u.extended.attr) {
344 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(2));
345 asn1_write_LDAPString(data, tree->u.extended.attr);
348 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(3));
349 asn1_write_DATA_BLOB_LDAPString(data, &tree->u.extended.value);
351 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(4));
352 asn1_write_uint8(data, tree->u.extended.dnAttributes);
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));
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);
386 if (!data) return false;
388 asn1_push_tag(data, ASN1_SEQUENCE(0));
389 asn1_write_Integer(data, msg->messageid);
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));
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);
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);
435 case LDAP_TAG_UnbindRequest: {
436 /* struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
437 asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type));
441 case LDAP_TAG_SearchRequest: {
442 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
443 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
444 asn1_write_OctetString(data, r->basedn, strlen(r->basedn));
445 asn1_write_enumerated(data, r->scope);
446 asn1_write_enumerated(data, r->deref);
447 asn1_write_Integer(data, r->sizelimit);
448 asn1_write_Integer(data, r->timelimit);
449 asn1_write_BOOLEAN(data, r->attributesonly);
451 if (!ldap_push_filter(data, r->tree)) {
455 asn1_push_tag(data, ASN1_SEQUENCE(0));
456 for (i=0; i<r->num_attributes; i++) {
457 asn1_write_OctetString(data, r->attributes[i],
458 strlen(r->attributes[i]));
464 case LDAP_TAG_SearchResultEntry: {
465 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
466 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
467 asn1_write_OctetString(data, r->dn, strlen(r->dn));
468 asn1_push_tag(data, ASN1_SEQUENCE(0));
469 for (i=0; i<r->num_attributes; i++) {
470 struct ldb_message_element *attr = &r->attributes[i];
471 asn1_push_tag(data, ASN1_SEQUENCE(0));
472 asn1_write_OctetString(data, attr->name,
474 asn1_push_tag(data, ASN1_SEQUENCE(1));
475 for (j=0; j<attr->num_values; j++) {
476 asn1_write_OctetString(data,
477 attr->values[j].data,
478 attr->values[j].length);
487 case LDAP_TAG_SearchResultDone: {
488 struct ldap_Result *r = &msg->r.SearchResultDone;
489 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
490 ldap_encode_response(data, r);
494 case LDAP_TAG_ModifyRequest: {
495 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
496 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
497 asn1_write_OctetString(data, r->dn, strlen(r->dn));
498 asn1_push_tag(data, ASN1_SEQUENCE(0));
500 for (i=0; i<r->num_mods; i++) {
501 struct ldb_message_element *attrib = &r->mods[i].attrib;
502 asn1_push_tag(data, ASN1_SEQUENCE(0));
503 asn1_write_enumerated(data, r->mods[i].type);
504 asn1_push_tag(data, ASN1_SEQUENCE(0));
505 asn1_write_OctetString(data, attrib->name,
506 strlen(attrib->name));
507 asn1_push_tag(data, ASN1_SET);
508 for (j=0; j<attrib->num_values; j++) {
509 asn1_write_OctetString(data,
510 attrib->values[j].data,
511 attrib->values[j].length);
523 case LDAP_TAG_ModifyResponse: {
524 struct ldap_Result *r = &msg->r.ModifyResponse;
525 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
526 ldap_encode_response(data, r);
530 case LDAP_TAG_AddRequest: {
531 struct ldap_AddRequest *r = &msg->r.AddRequest;
532 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
533 asn1_write_OctetString(data, r->dn, strlen(r->dn));
534 asn1_push_tag(data, ASN1_SEQUENCE(0));
536 for (i=0; i<r->num_attributes; i++) {
537 struct ldb_message_element *attrib = &r->attributes[i];
538 asn1_push_tag(data, ASN1_SEQUENCE(0));
539 asn1_write_OctetString(data, attrib->name,
540 strlen(attrib->name));
541 asn1_push_tag(data, ASN1_SET);
542 for (j=0; j<r->attributes[i].num_values; j++) {
543 asn1_write_OctetString(data,
544 attrib->values[j].data,
545 attrib->values[j].length);
554 case LDAP_TAG_AddResponse: {
555 struct ldap_Result *r = &msg->r.AddResponse;
556 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
557 ldap_encode_response(data, r);
561 case LDAP_TAG_DelRequest: {
562 struct ldap_DelRequest *r = &msg->r.DelRequest;
563 asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type));
564 asn1_write(data, r->dn, strlen(r->dn));
568 case LDAP_TAG_DelResponse: {
569 struct ldap_Result *r = &msg->r.DelResponse;
570 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
571 ldap_encode_response(data, r);
575 case LDAP_TAG_ModifyDNRequest: {
576 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
577 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
578 asn1_write_OctetString(data, r->dn, strlen(r->dn));
579 asn1_write_OctetString(data, r->newrdn, strlen(r->newrdn));
580 asn1_write_BOOLEAN(data, r->deleteolddn);
581 if (r->newsuperior) {
582 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
583 asn1_write(data, r->newsuperior,
584 strlen(r->newsuperior));
590 case LDAP_TAG_ModifyDNResponse: {
591 struct ldap_Result *r = &msg->r.ModifyDNResponse;
592 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
593 ldap_encode_response(data, r);
597 case LDAP_TAG_CompareRequest: {
598 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
599 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
600 asn1_write_OctetString(data, r->dn, strlen(r->dn));
601 asn1_push_tag(data, ASN1_SEQUENCE(0));
602 asn1_write_OctetString(data, r->attribute,
603 strlen(r->attribute));
604 asn1_write_OctetString(data, r->value.data,
610 case LDAP_TAG_CompareResponse: {
611 struct ldap_Result *r = &msg->r.ModifyDNResponse;
612 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
613 ldap_encode_response(data, r);
617 case LDAP_TAG_AbandonRequest: {
618 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
619 asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type));
620 asn1_write_implicit_Integer(data, r->messageid);
624 case LDAP_TAG_SearchResultReference: {
625 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
626 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
627 asn1_write_OctetString(data, r->referral, strlen(r->referral));
631 case LDAP_TAG_ExtendedRequest: {
632 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
633 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
634 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
635 asn1_write(data, r->oid, strlen(r->oid));
638 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1));
639 asn1_write(data, r->value->data, r->value->length);
645 case LDAP_TAG_ExtendedResponse: {
646 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
647 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
648 ldap_encode_response(data, &r->response);
650 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(10));
651 asn1_write(data, r->oid, strlen(r->oid));
655 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(11));
656 asn1_write(data, r->value->data, r->value->length);
666 if (msg->controls != NULL) {
667 asn1_push_tag(data, ASN1_CONTEXT(0));
669 for (i = 0; msg->controls[i] != NULL; i++) {
670 if (!ldap_encode_control(mem_ctx, data,
673 DEBUG(1,("Unable to encode control %s\n",
674 msg->controls[i]->oid));
684 if (data->has_error) {
689 *result = data_blob_talloc(mem_ctx, data->data, data->length);
694 static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
697 char *result = talloc_array(mem_ctx, char, blob.length+1);
698 memcpy(result, blob.data, blob.length);
699 result[blob.length] = '\0';
703 bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
704 struct asn1_data *data,
708 if (!asn1_read_OctetString(data, mem_ctx, &string))
710 *result = blob2string_talloc(mem_ctx, string);
711 data_blob_free(&string);
715 static void ldap_decode_response(TALLOC_CTX *mem_ctx,
716 struct asn1_data *data,
717 struct ldap_Result *result)
719 asn1_read_enumerated(data, &result->resultcode);
720 asn1_read_OctetString_talloc(mem_ctx, data, &result->dn);
721 asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage);
722 if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
723 asn1_start_tag(data, ASN1_CONTEXT(3));
724 asn1_read_OctetString_talloc(mem_ctx, data, &result->referral);
727 result->referral = NULL;
731 static struct ldb_val **ldap_decode_substring(TALLOC_CTX *mem_ctx, struct ldb_val **chunks, int chunk_num, char *value)
734 chunks = talloc_realloc(mem_ctx, chunks, struct ldb_val *, chunk_num + 2);
735 if (chunks == NULL) {
739 chunks[chunk_num] = talloc(mem_ctx, struct ldb_val);
740 if (chunks[chunk_num] == NULL) {
744 chunks[chunk_num]->data = (uint8_t *)talloc_strdup(mem_ctx, value);
745 if (chunks[chunk_num]->data == NULL) {
748 chunks[chunk_num]->length = strlen(value);
750 chunks[chunk_num + 1] = '\0';
757 parse the ASN.1 formatted search string into a ldb_parse_tree
759 static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
760 struct asn1_data *data)
763 struct ldb_parse_tree *ret;
765 if (!asn1_peek_uint8(data, &filter_tag)) {
769 filter_tag &= 0x1f; /* strip off the asn1 stuff */
771 ret = talloc(mem_ctx, struct ldb_parse_tree);
772 if (ret == NULL) return NULL;
777 /* AND or OR of one or more filters */
778 ret->operation = (filter_tag == 0)?LDB_OP_AND:LDB_OP_OR;
779 ret->u.list.num_elements = 0;
780 ret->u.list.elements = NULL;
782 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
786 while (asn1_tag_remaining(data) > 0) {
787 struct ldb_parse_tree *subtree;
788 subtree = ldap_decode_filter_tree(ret, data);
789 if (subtree == NULL) {
792 ret->u.list.elements =
793 talloc_realloc(ret, ret->u.list.elements,
794 struct ldb_parse_tree *,
795 ret->u.list.num_elements+1);
796 if (ret->u.list.elements == NULL) {
799 talloc_steal(ret->u.list.elements, subtree);
800 ret->u.list.elements[ret->u.list.num_elements] = subtree;
801 ret->u.list.num_elements++;
803 if (!asn1_end_tag(data)) {
809 /* 'not' operation */
810 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
814 ret->operation = LDB_OP_NOT;
815 ret->u.isnot.child = ldap_decode_filter_tree(ret, data);
816 if (ret->u.isnot.child == NULL) {
819 if (!asn1_end_tag(data)) {
829 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
830 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
831 asn1_read_OctetString(data, mem_ctx, &value);
833 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
837 ret->operation = LDB_OP_EQUALITY;
838 ret->u.equality.attr = talloc_steal(ret, attrib);
839 ret->u.equality.value.data = talloc_steal(ret, value.data);
840 ret->u.equality.value.length = value.length;
850 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
853 if (!asn1_read_OctetString(data, mem_ctx, &attr)) {
857 ret->operation = LDB_OP_SUBSTRING;
858 ret->u.substring.attr = talloc_strndup(ret, (char *)attr.data, attr.length);
859 ret->u.substring.chunks = NULL;
860 ret->u.substring.start_with_wildcard = 1;
861 ret->u.substring.end_with_wildcard = 1;
863 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
867 while (asn1_tag_remaining(data)) {
868 asn1_peek_uint8(data, &subs_tag);
869 subs_tag &= 0x1f; /* strip off the asn1 stuff */
870 if (subs_tag > 2) goto failed;
872 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(subs_tag));
873 asn1_read_LDAPString(data, mem_ctx, &value);
878 if (ret->u.substring.chunks != NULL) {
879 /* initial value found in the middle */
883 ret->u.substring.chunks = ldap_decode_substring(ret, NULL, 0, value);
884 if (ret->u.substring.chunks == NULL) {
888 ret->u.substring.start_with_wildcard = 0;
893 if (ret->u.substring.end_with_wildcard == 0) {
894 /* "any" value found after a "final" value */
898 ret->u.substring.chunks = ldap_decode_substring(ret,
899 ret->u.substring.chunks,
902 if (ret->u.substring.chunks == NULL) {
910 ret->u.substring.chunks = ldap_decode_substring(ret,
911 ret->u.substring.chunks,
914 if (ret->u.substring.chunks == NULL) {
918 ret->u.substring.end_with_wildcard = 0;
927 if (!asn1_end_tag(data)) { /* SEQUENCE */
931 if (!asn1_end_tag(data)) {
941 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
942 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
943 asn1_read_OctetString(data, mem_ctx, &value);
945 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
949 ret->operation = LDB_OP_GREATER;
950 ret->u.comparison.attr = talloc_steal(ret, attrib);
951 ret->u.comparison.value.data = talloc_steal(ret, value.data);
952 ret->u.comparison.value.length = value.length;
960 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
961 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
962 asn1_read_OctetString(data, mem_ctx, &value);
964 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
968 ret->operation = LDB_OP_LESS;
969 ret->u.comparison.attr = talloc_steal(ret, attrib);
970 ret->u.comparison.value.data = talloc_steal(ret, value.data);
971 ret->u.comparison.value.length = value.length;
975 /* Normal presence, "attribute=*" */
978 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(filter_tag))) {
981 if (!asn1_read_LDAPString(data, ret, &attr)) {
985 ret->operation = LDB_OP_PRESENT;
986 ret->u.present.attr = talloc_steal(ret, attr);
988 if (!asn1_end_tag(data)) {
998 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
999 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
1000 asn1_read_OctetString(data, mem_ctx, &value);
1002 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
1006 ret->operation = LDB_OP_APPROX;
1007 ret->u.comparison.attr = talloc_steal(ret, attrib);
1008 ret->u.comparison.value.data = talloc_steal(ret, value.data);
1009 ret->u.comparison.value.length = value.length;
1013 char *oid = NULL, *attr = NULL, *value;
1014 uint8_t dnAttributes;
1015 /* an extended search */
1016 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
1020 /* FIXME: read carefully rfc2251.txt there are a number of 'MUST's
1021 we need to check we properly implement --SSS */
1022 /* either oid or type must be defined */
1023 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
1024 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(1));
1025 asn1_read_LDAPString(data, ret, &oid);
1028 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(2))) { /* optional */
1029 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(2));
1030 asn1_read_LDAPString(data, ret, &attr);
1033 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(3));
1034 asn1_read_LDAPString(data, ret, &value);
1036 /* dnAttributes is marked as BOOLEAN DEFAULT FALSE
1037 it is not marked as OPTIONAL but openldap tools
1038 do not set this unless it is to be set as TRUE
1039 NOTE: openldap tools do not work with AD as it
1040 seems that AD always requires the dnAttributes
1041 boolean value to be set */
1042 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(4))) {
1043 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(4));
1044 asn1_read_uint8(data, &dnAttributes);
1049 if ((oid == NULL && attr == NULL) || (value == NULL)) {
1054 ret->operation = LDB_OP_EXTENDED;
1056 /* From the RFC2251: If the type field is
1057 absent and matchingRule is present, the matchValue is compared
1058 against all attributes in an entry which support that matchingRule
1061 ret->u.extended.attr = talloc_steal(ret, attr);
1063 ret->u.extended.attr = talloc_strdup(ret, "*");
1065 ret->u.extended.rule_id = talloc_steal(ret, oid);
1066 ret->u.extended.value.data = (uint8_t *)talloc_steal(ret, value);
1067 ret->u.extended.value.length = strlen(value);
1068 ret->u.extended.dnAttributes = dnAttributes;
1070 ret->operation = LDB_OP_EQUALITY;
1071 ret->u.equality.attr = talloc_steal(ret, attr);
1072 ret->u.equality.value.data = (uint8_t *)talloc_steal(ret, value);
1073 ret->u.equality.value.length = strlen(value);
1075 if (!asn1_end_tag(data)) {
1092 /* Decode a single LDAP attribute, possibly containing multiple values */
1093 static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1094 struct ldb_message_element *attrib)
1096 asn1_start_tag(data, ASN1_SEQUENCE(0));
1097 asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name);
1098 asn1_start_tag(data, ASN1_SET);
1099 while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
1101 asn1_read_OctetString(data, mem_ctx, &blob);
1102 add_value_to_attrib(mem_ctx, &blob, attrib);
1109 /* Decode a set of LDAP attributes, as found in the dereference control */
1110 void ldap_decode_attribs_bare(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1111 struct ldb_message_element **attributes,
1112 int *num_attributes)
1114 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1115 struct ldb_message_element attrib;
1116 ZERO_STRUCT(attrib);
1117 ldap_decode_attrib(mem_ctx, data, &attrib);
1118 add_attrib_to_array_talloc(mem_ctx, &attrib,
1119 attributes, num_attributes);
1123 /* Decode a set of LDAP attributes, as found in a search entry */
1124 static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1125 struct ldb_message_element **attributes,
1126 int *num_attributes)
1128 asn1_start_tag(data, ASN1_SEQUENCE(0));
1129 ldap_decode_attribs_bare(mem_ctx, data,
1130 attributes, num_attributes);
1134 /* This routine returns LDAP status codes */
1136 _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
1137 const struct ldap_control_handler *control_handlers,
1138 struct ldap_message *msg)
1142 asn1_start_tag(data, ASN1_SEQUENCE(0));
1143 asn1_read_Integer(data, &msg->messageid);
1145 if (!asn1_peek_uint8(data, &tag))
1146 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1150 case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
1151 struct ldap_BindRequest *r = &msg->r.BindRequest;
1152 msg->type = LDAP_TAG_BindRequest;
1153 asn1_start_tag(data, tag);
1154 asn1_read_Integer(data, &r->version);
1155 asn1_read_OctetString_talloc(msg, data, &r->dn);
1156 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
1158 r->creds.password = "";
1159 r->mechanism = LDAP_AUTH_MECH_SIMPLE;
1160 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1161 pwlen = asn1_tag_remaining(data);
1163 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1166 char *pw = talloc_array(msg, char, pwlen+1);
1168 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1170 asn1_read(data, pw, pwlen);
1172 r->creds.password = pw;
1175 } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
1176 asn1_start_tag(data, ASN1_CONTEXT(3));
1177 r->mechanism = LDAP_AUTH_MECH_SASL;
1178 asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism);
1179 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) { /* optional */
1180 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1181 asn1_read_OctetString(data, msg, &tmp_blob);
1182 r->creds.SASL.secblob = talloc(msg, DATA_BLOB);
1183 if (!r->creds.SASL.secblob) {
1184 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1186 *r->creds.SASL.secblob = data_blob_talloc(r->creds.SASL.secblob,
1187 tmp_blob.data, tmp_blob.length);
1188 data_blob_free(&tmp_blob);
1190 r->creds.SASL.secblob = NULL;
1194 /* Neither Simple nor SASL bind */
1195 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1201 case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
1202 struct ldap_BindResponse *r = &msg->r.BindResponse;
1203 msg->type = LDAP_TAG_BindResponse;
1204 asn1_start_tag(data, tag);
1205 ldap_decode_response(msg, data, &r->response);
1206 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
1207 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1208 asn1_read_ContextSimple(data, 7, &tmp_blob);
1209 r->SASL.secblob = talloc(msg, DATA_BLOB);
1210 if (!r->SASL.secblob) {
1211 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1213 *r->SASL.secblob = data_blob_talloc(r->SASL.secblob,
1214 tmp_blob.data, tmp_blob.length);
1215 data_blob_free(&tmp_blob);
1217 r->SASL.secblob = NULL;
1223 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
1224 msg->type = LDAP_TAG_UnbindRequest;
1225 asn1_start_tag(data, tag);
1230 case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
1231 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
1232 int sizelimit, timelimit;
1233 const char **attrs = NULL;
1234 msg->type = LDAP_TAG_SearchRequest;
1235 asn1_start_tag(data, tag);
1236 asn1_read_OctetString_talloc(msg, data, &r->basedn);
1237 asn1_read_enumerated(data, (int *)(void *)&(r->scope));
1238 asn1_read_enumerated(data, (int *)(void *)&(r->deref));
1239 asn1_read_Integer(data, &sizelimit);
1240 r->sizelimit = sizelimit;
1241 asn1_read_Integer(data, &timelimit);
1242 r->timelimit = timelimit;
1243 asn1_read_BOOLEAN(data, &r->attributesonly);
1245 r->tree = ldap_decode_filter_tree(msg, data);
1246 if (r->tree == NULL) {
1247 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1250 asn1_start_tag(data, ASN1_SEQUENCE(0));
1252 r->num_attributes = 0;
1253 r->attributes = NULL;
1255 while (asn1_tag_remaining(data) > 0) {
1258 if (!asn1_read_OctetString_talloc(msg, data,
1260 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1261 if (!add_string_to_array(msg, attr,
1263 &r->num_attributes))
1264 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1266 r->attributes = attrs;
1273 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1274 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1275 msg->type = LDAP_TAG_SearchResultEntry;
1276 r->attributes = NULL;
1277 r->num_attributes = 0;
1278 asn1_start_tag(data, tag);
1279 asn1_read_OctetString_talloc(msg, data, &r->dn);
1280 ldap_decode_attribs(msg, data, &r->attributes,
1281 &r->num_attributes);
1286 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1287 struct ldap_Result *r = &msg->r.SearchResultDone;
1288 msg->type = LDAP_TAG_SearchResultDone;
1289 asn1_start_tag(data, tag);
1290 ldap_decode_response(msg, data, r);
1295 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1296 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
1297 msg->type = LDAP_TAG_SearchResultReference;
1298 asn1_start_tag(data, tag);
1299 asn1_read_OctetString_talloc(msg, data, &r->referral);
1304 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1305 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1306 msg->type = LDAP_TAG_ModifyRequest;
1307 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
1308 asn1_read_OctetString_talloc(msg, data, &r->dn);
1309 asn1_start_tag(data, ASN1_SEQUENCE(0));
1314 while (asn1_tag_remaining(data) > 0) {
1315 struct ldap_mod mod;
1318 asn1_start_tag(data, ASN1_SEQUENCE(0));
1319 asn1_read_enumerated(data, &v);
1321 ldap_decode_attrib(msg, data, &mod.attrib);
1323 if (!add_mod_to_array_talloc(msg, &mod,
1324 &r->mods, &r->num_mods)) {
1325 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1334 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1335 struct ldap_Result *r = &msg->r.ModifyResponse;
1336 msg->type = LDAP_TAG_ModifyResponse;
1337 asn1_start_tag(data, tag);
1338 ldap_decode_response(msg, data, r);
1343 case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1344 struct ldap_AddRequest *r = &msg->r.AddRequest;
1345 msg->type = LDAP_TAG_AddRequest;
1346 asn1_start_tag(data, tag);
1347 asn1_read_OctetString_talloc(msg, data, &r->dn);
1349 r->attributes = NULL;
1350 r->num_attributes = 0;
1351 ldap_decode_attribs(msg, data, &r->attributes,
1352 &r->num_attributes);
1358 case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1359 struct ldap_Result *r = &msg->r.AddResponse;
1360 msg->type = LDAP_TAG_AddResponse;
1361 asn1_start_tag(data, tag);
1362 ldap_decode_response(msg, data, r);
1367 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1368 struct ldap_DelRequest *r = &msg->r.DelRequest;
1371 msg->type = LDAP_TAG_DelRequest;
1372 asn1_start_tag(data,
1373 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
1374 len = asn1_tag_remaining(data);
1376 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1378 dn = talloc_array(msg, char, len+1);
1381 asn1_read(data, dn, len);
1388 case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1389 struct ldap_Result *r = &msg->r.DelResponse;
1390 msg->type = LDAP_TAG_DelResponse;
1391 asn1_start_tag(data, tag);
1392 ldap_decode_response(msg, data, r);
1397 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1398 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1399 msg->type = LDAP_TAG_ModifyDNRequest;
1400 asn1_start_tag(data,
1401 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
1402 asn1_read_OctetString_talloc(msg, data, &r->dn);
1403 asn1_read_OctetString_talloc(msg, data, &r->newrdn);
1404 asn1_read_BOOLEAN(data, &r->deleteolddn);
1405 r->newsuperior = NULL;
1406 if (asn1_tag_remaining(data) > 0) {
1409 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1410 len = asn1_tag_remaining(data);
1412 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1414 newsup = talloc_array(msg, char, len+1);
1415 if (newsup == NULL) {
1416 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1418 asn1_read(data, newsup, len);
1420 r->newsuperior = newsup;
1427 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1428 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1429 msg->type = LDAP_TAG_ModifyDNResponse;
1430 asn1_start_tag(data, tag);
1431 ldap_decode_response(msg, data, r);
1436 case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1437 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1438 msg->type = LDAP_TAG_CompareRequest;
1439 asn1_start_tag(data,
1440 ASN1_APPLICATION(LDAP_TAG_CompareRequest));
1441 asn1_read_OctetString_talloc(msg, data, &r->dn);
1442 asn1_start_tag(data, ASN1_SEQUENCE(0));
1443 asn1_read_OctetString_talloc(msg, data, &r->attribute);
1444 asn1_read_OctetString(data, msg, &r->value);
1445 if (r->value.data) {
1446 talloc_steal(msg, r->value.data);
1453 case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1454 struct ldap_Result *r = &msg->r.CompareResponse;
1455 msg->type = LDAP_TAG_CompareResponse;
1456 asn1_start_tag(data, tag);
1457 ldap_decode_response(msg, data, r);
1462 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1463 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1464 msg->type = LDAP_TAG_AbandonRequest;
1465 asn1_start_tag(data, tag);
1466 asn1_read_implicit_Integer(data, &r->messageid);
1471 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1472 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1473 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1475 msg->type = LDAP_TAG_ExtendedRequest;
1476 asn1_start_tag(data,tag);
1477 if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
1478 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1480 r->oid = blob2string_talloc(msg, tmp_blob);
1481 data_blob_free(&tmp_blob);
1483 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1486 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1487 asn1_read_ContextSimple(data, 1, &tmp_blob);
1488 r->value = talloc(msg, DATA_BLOB);
1490 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1492 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1493 data_blob_free(&tmp_blob);
1502 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1503 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1504 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1506 msg->type = LDAP_TAG_ExtendedResponse;
1507 asn1_start_tag(data, tag);
1508 ldap_decode_response(msg, data, &r->response);
1510 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(10))) {
1511 asn1_read_ContextSimple(data, 1, &tmp_blob);
1512 r->oid = blob2string_talloc(msg, tmp_blob);
1513 data_blob_free(&tmp_blob);
1515 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1521 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(11))) {
1522 asn1_read_ContextSimple(data, 1, &tmp_blob);
1523 r->value = talloc(msg, DATA_BLOB);
1525 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1527 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1528 data_blob_free(&tmp_blob);
1537 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1540 msg->controls = NULL;
1541 msg->controls_decoded = NULL;
1543 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1545 struct ldb_control **ctrl = NULL;
1546 bool *decoded = NULL;
1548 asn1_start_tag(data, ASN1_CONTEXT(0));
1550 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1552 /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1554 ctrl = talloc_realloc(msg, ctrl, struct ldb_control *, i+2);
1556 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1559 decoded = talloc_realloc(msg, decoded, bool, i+1);
1561 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1564 ctrl[i] = talloc(ctrl, struct ldb_control);
1566 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1569 if (!ldap_decode_control_wrapper(ctrl, data, ctrl[i], &value)) {
1570 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1573 if (!ldap_decode_control_value(ctrl, value,
1576 if (ctrl[i]->critical) {
1577 ctrl[i]->data = NULL;
1581 talloc_free(ctrl[i]);
1594 msg->controls = ctrl;
1595 msg->controls_decoded = decoded;
1601 if ((data->has_error) || (data->nesting != NULL)) {
1602 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1604 return NT_STATUS_OK;
1609 return NT_STATUS_OK if a blob has enough bytes in it to be a full
1610 ldap packet. Set packet_size if true.
1612 NTSTATUS ldap_full_packet(void *private_data, DATA_BLOB blob, size_t *packet_size)
1614 if (blob.length < 6) {
1616 * We need at least 6 bytes to workout the length
1619 return STATUS_MORE_ENTRIES;
1621 return asn1_peek_full_tag(blob, ASN1_SEQUENCE(0), packet_size);