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 "libcli/util/asn_1.h"
27 #include "libcli/ldap/ldap.h"
30 static bool ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree)
34 switch (tree->operation) {
37 asn1_push_tag(data, ASN1_CONTEXT(tree->operation==LDB_OP_AND?0:1));
38 for (i=0; i<tree->u.list.num_elements; i++) {
39 if (!ldap_push_filter(data, tree->u.list.elements[i])) {
47 asn1_push_tag(data, ASN1_CONTEXT(2));
48 if (!ldap_push_filter(data, tree->u.isnot.child)) {
56 asn1_push_tag(data, ASN1_CONTEXT(3));
57 asn1_write_OctetString(data, tree->u.equality.attr,
58 strlen(tree->u.equality.attr));
59 asn1_write_OctetString(data, tree->u.equality.value.data,
60 tree->u.equality.value.length);
64 case LDB_OP_SUBSTRING:
66 SubstringFilter ::= SEQUENCE {
67 type AttributeDescription,
68 -- at least one must be present
69 substrings SEQUENCE OF CHOICE {
70 initial [0] LDAPString,
72 final [2] LDAPString } }
74 asn1_push_tag(data, ASN1_CONTEXT(4));
75 asn1_write_OctetString(data, tree->u.substring.attr, strlen(tree->u.substring.attr));
76 asn1_push_tag(data, ASN1_SEQUENCE(0));
78 if ( ! tree->u.substring.start_with_wildcard) {
79 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
80 asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i]);
84 while (tree->u.substring.chunks[i]) {
87 if (( ! tree->u.substring.chunks[i + 1]) &&
88 (tree->u.substring.end_with_wildcard == 0)) {
93 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(ctx));
94 asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i]);
103 /* greaterOrEqual test */
104 asn1_push_tag(data, ASN1_CONTEXT(5));
105 asn1_write_OctetString(data, tree->u.comparison.attr,
106 strlen(tree->u.comparison.attr));
107 asn1_write_OctetString(data, tree->u.comparison.value.data,
108 tree->u.comparison.value.length);
113 /* lessOrEqual test */
114 asn1_push_tag(data, ASN1_CONTEXT(6));
115 asn1_write_OctetString(data, tree->u.comparison.attr,
116 strlen(tree->u.comparison.attr));
117 asn1_write_OctetString(data, tree->u.comparison.value.data,
118 tree->u.comparison.value.length);
124 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(7));
125 asn1_write_LDAPString(data, tree->u.present.attr);
127 return !data->has_error;
131 asn1_push_tag(data, ASN1_CONTEXT(8));
132 asn1_write_OctetString(data, tree->u.comparison.attr,
133 strlen(tree->u.comparison.attr));
134 asn1_write_OctetString(data, tree->u.comparison.value.data,
135 tree->u.comparison.value.length);
139 case LDB_OP_EXTENDED:
141 MatchingRuleAssertion ::= SEQUENCE {
142 matchingRule [1] MatchingRuleID OPTIONAL,
143 type [2] AttributeDescription OPTIONAL,
144 matchValue [3] AssertionValue,
145 dnAttributes [4] BOOLEAN DEFAULT FALSE
148 asn1_push_tag(data, ASN1_CONTEXT(9));
149 if (tree->u.extended.rule_id) {
150 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1));
151 asn1_write_LDAPString(data, tree->u.extended.rule_id);
154 if (tree->u.extended.attr) {
155 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(2));
156 asn1_write_LDAPString(data, tree->u.extended.attr);
159 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(3));
160 asn1_write_DATA_BLOB_LDAPString(data, &tree->u.extended.value);
162 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(4));
163 asn1_write_uint8(data, tree->u.extended.dnAttributes);
171 return !data->has_error;
174 static void ldap_encode_response(struct asn1_data *data, struct ldap_Result *result)
176 asn1_write_enumerated(data, result->resultcode);
177 asn1_write_OctetString(data, result->dn,
178 (result->dn) ? strlen(result->dn) : 0);
179 asn1_write_OctetString(data, result->errormessage,
180 (result->errormessage) ?
181 strlen(result->errormessage) : 0);
182 if (result->referral) {
183 asn1_push_tag(data, ASN1_CONTEXT(3));
184 asn1_write_OctetString(data, result->referral,
185 strlen(result->referral));
190 bool ldap_encode(struct ldap_message *msg, DATA_BLOB *result, TALLOC_CTX *mem_ctx)
192 struct asn1_data *data = asn1_init(mem_ctx);
195 if (!data) return false;
197 asn1_push_tag(data, ASN1_SEQUENCE(0));
198 asn1_write_Integer(data, msg->messageid);
201 case LDAP_TAG_BindRequest: {
202 struct ldap_BindRequest *r = &msg->r.BindRequest;
203 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
204 asn1_write_Integer(data, r->version);
205 asn1_write_OctetString(data, r->dn,
206 (r->dn != NULL) ? strlen(r->dn) : 0);
208 switch (r->mechanism) {
209 case LDAP_AUTH_MECH_SIMPLE:
210 /* context, primitive */
211 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
212 asn1_write(data, r->creds.password,
213 strlen(r->creds.password));
216 case LDAP_AUTH_MECH_SASL:
217 /* context, constructed */
218 asn1_push_tag(data, ASN1_CONTEXT(3));
219 asn1_write_OctetString(data, r->creds.SASL.mechanism,
220 strlen(r->creds.SASL.mechanism));
221 if (r->creds.SASL.secblob) {
222 asn1_write_OctetString(data, r->creds.SASL.secblob->data,
223 r->creds.SASL.secblob->length);
234 case LDAP_TAG_BindResponse: {
235 struct ldap_BindResponse *r = &msg->r.BindResponse;
236 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
237 ldap_encode_response(data, &r->response);
238 if (r->SASL.secblob) {
239 asn1_write_ContextSimple(data, 7, r->SASL.secblob);
244 case LDAP_TAG_UnbindRequest: {
245 /* struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
248 case LDAP_TAG_SearchRequest: {
249 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
250 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
251 asn1_write_OctetString(data, r->basedn, strlen(r->basedn));
252 asn1_write_enumerated(data, r->scope);
253 asn1_write_enumerated(data, r->deref);
254 asn1_write_Integer(data, r->sizelimit);
255 asn1_write_Integer(data, r->timelimit);
256 asn1_write_BOOLEAN(data, r->attributesonly);
258 if (!ldap_push_filter(data, r->tree)) {
262 asn1_push_tag(data, ASN1_SEQUENCE(0));
263 for (i=0; i<r->num_attributes; i++) {
264 asn1_write_OctetString(data, r->attributes[i],
265 strlen(r->attributes[i]));
271 case LDAP_TAG_SearchResultEntry: {
272 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
273 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
274 asn1_write_OctetString(data, r->dn, strlen(r->dn));
275 asn1_push_tag(data, ASN1_SEQUENCE(0));
276 for (i=0; i<r->num_attributes; i++) {
277 struct ldb_message_element *attr = &r->attributes[i];
278 asn1_push_tag(data, ASN1_SEQUENCE(0));
279 asn1_write_OctetString(data, attr->name,
281 asn1_push_tag(data, ASN1_SEQUENCE(1));
282 for (j=0; j<attr->num_values; j++) {
283 asn1_write_OctetString(data,
284 attr->values[j].data,
285 attr->values[j].length);
294 case LDAP_TAG_SearchResultDone: {
295 struct ldap_Result *r = &msg->r.SearchResultDone;
296 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
297 ldap_encode_response(data, r);
301 case LDAP_TAG_ModifyRequest: {
302 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
303 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
304 asn1_write_OctetString(data, r->dn, strlen(r->dn));
305 asn1_push_tag(data, ASN1_SEQUENCE(0));
307 for (i=0; i<r->num_mods; i++) {
308 struct ldb_message_element *attrib = &r->mods[i].attrib;
309 asn1_push_tag(data, ASN1_SEQUENCE(0));
310 asn1_write_enumerated(data, r->mods[i].type);
311 asn1_push_tag(data, ASN1_SEQUENCE(0));
312 asn1_write_OctetString(data, attrib->name,
313 strlen(attrib->name));
314 asn1_push_tag(data, ASN1_SET);
315 for (j=0; j<attrib->num_values; j++) {
316 asn1_write_OctetString(data,
317 attrib->values[j].data,
318 attrib->values[j].length);
330 case LDAP_TAG_ModifyResponse: {
331 struct ldap_Result *r = &msg->r.ModifyResponse;
332 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
333 ldap_encode_response(data, r);
337 case LDAP_TAG_AddRequest: {
338 struct ldap_AddRequest *r = &msg->r.AddRequest;
339 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
340 asn1_write_OctetString(data, r->dn, strlen(r->dn));
341 asn1_push_tag(data, ASN1_SEQUENCE(0));
343 for (i=0; i<r->num_attributes; i++) {
344 struct ldb_message_element *attrib = &r->attributes[i];
345 asn1_push_tag(data, ASN1_SEQUENCE(0));
346 asn1_write_OctetString(data, attrib->name,
347 strlen(attrib->name));
348 asn1_push_tag(data, ASN1_SET);
349 for (j=0; j<r->attributes[i].num_values; j++) {
350 asn1_write_OctetString(data,
351 attrib->values[j].data,
352 attrib->values[j].length);
361 case LDAP_TAG_AddResponse: {
362 struct ldap_Result *r = &msg->r.AddResponse;
363 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
364 ldap_encode_response(data, r);
368 case LDAP_TAG_DelRequest: {
369 struct ldap_DelRequest *r = &msg->r.DelRequest;
370 asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type));
371 asn1_write(data, r->dn, strlen(r->dn));
375 case LDAP_TAG_DelResponse: {
376 struct ldap_Result *r = &msg->r.DelResponse;
377 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
378 ldap_encode_response(data, r);
382 case LDAP_TAG_ModifyDNRequest: {
383 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
384 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
385 asn1_write_OctetString(data, r->dn, strlen(r->dn));
386 asn1_write_OctetString(data, r->newrdn, strlen(r->newrdn));
387 asn1_write_BOOLEAN(data, r->deleteolddn);
388 if (r->newsuperior) {
389 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
390 asn1_write(data, r->newsuperior,
391 strlen(r->newsuperior));
397 case LDAP_TAG_ModifyDNResponse: {
398 struct ldap_Result *r = &msg->r.ModifyDNResponse;
399 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
400 ldap_encode_response(data, r);
404 case LDAP_TAG_CompareRequest: {
405 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
406 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
407 asn1_write_OctetString(data, r->dn, strlen(r->dn));
408 asn1_push_tag(data, ASN1_SEQUENCE(0));
409 asn1_write_OctetString(data, r->attribute,
410 strlen(r->attribute));
411 asn1_write_OctetString(data, r->value.data,
417 case LDAP_TAG_CompareResponse: {
418 struct ldap_Result *r = &msg->r.ModifyDNResponse;
419 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
420 ldap_encode_response(data, r);
424 case LDAP_TAG_AbandonRequest: {
425 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
426 asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type));
427 asn1_write_implicit_Integer(data, r->messageid);
431 case LDAP_TAG_SearchResultReference: {
432 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
433 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
434 asn1_write_OctetString(data, r->referral, strlen(r->referral));
438 case LDAP_TAG_ExtendedRequest: {
439 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
440 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
441 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
442 asn1_write(data, r->oid, strlen(r->oid));
445 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1));
446 asn1_write(data, r->value->data, r->value->length);
452 case LDAP_TAG_ExtendedResponse: {
453 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
454 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
455 ldap_encode_response(data, &r->response);
457 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(10));
458 asn1_write(data, r->oid, strlen(r->oid));
462 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(11));
463 asn1_write(data, r->value->data, r->value->length);
473 if (msg->controls != NULL) {
474 asn1_push_tag(data, ASN1_CONTEXT(0));
476 for (i = 0; msg->controls[i] != NULL; i++) {
477 if (!ldap_encode_control(mem_ctx, data, msg->controls[i])) {
487 if (data->has_error) {
492 *result = data_blob_talloc(mem_ctx, data->data, data->length);
497 static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
500 char *result = talloc_array(mem_ctx, char, blob.length+1);
501 memcpy(result, blob.data, blob.length);
502 result[blob.length] = '\0';
506 static bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
507 struct asn1_data *data,
511 if (!asn1_read_OctetString(data, mem_ctx, &string))
513 *result = blob2string_talloc(mem_ctx, string);
514 data_blob_free(&string);
518 static void ldap_decode_response(TALLOC_CTX *mem_ctx,
519 struct asn1_data *data,
520 struct ldap_Result *result)
522 asn1_read_enumerated(data, &result->resultcode);
523 asn1_read_OctetString_talloc(mem_ctx, data, &result->dn);
524 asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage);
525 if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
526 asn1_start_tag(data, ASN1_CONTEXT(3));
527 asn1_read_OctetString_talloc(mem_ctx, data, &result->referral);
530 result->referral = NULL;
534 static struct ldb_val **ldap_decode_substring(TALLOC_CTX *mem_ctx, struct ldb_val **chunks, int chunk_num, char *value)
537 chunks = talloc_realloc(mem_ctx, chunks, struct ldb_val *, chunk_num + 2);
538 if (chunks == NULL) {
542 chunks[chunk_num] = talloc(mem_ctx, struct ldb_val);
543 if (chunks[chunk_num] == NULL) {
547 chunks[chunk_num]->data = (uint8_t *)talloc_strdup(mem_ctx, value);
548 if (chunks[chunk_num]->data == NULL) {
551 chunks[chunk_num]->length = strlen(value);
553 chunks[chunk_num + 1] = '\0';
560 parse the ASN.1 formatted search string into a ldb_parse_tree
562 static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
563 struct asn1_data *data)
566 struct ldb_parse_tree *ret;
568 if (!asn1_peek_uint8(data, &filter_tag)) {
572 filter_tag &= 0x1f; /* strip off the asn1 stuff */
574 ret = talloc(mem_ctx, struct ldb_parse_tree);
575 if (ret == NULL) return NULL;
580 /* AND or OR of one or more filters */
581 ret->operation = (filter_tag == 0)?LDB_OP_AND:LDB_OP_OR;
582 ret->u.list.num_elements = 0;
583 ret->u.list.elements = NULL;
585 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
589 while (asn1_tag_remaining(data) > 0) {
590 struct ldb_parse_tree *subtree;
591 subtree = ldap_decode_filter_tree(ret, data);
592 if (subtree == NULL) {
595 ret->u.list.elements =
596 talloc_realloc(ret, ret->u.list.elements,
597 struct ldb_parse_tree *,
598 ret->u.list.num_elements+1);
599 if (ret->u.list.elements == NULL) {
602 talloc_steal(ret->u.list.elements, subtree);
603 ret->u.list.elements[ret->u.list.num_elements] = subtree;
604 ret->u.list.num_elements++;
606 if (!asn1_end_tag(data)) {
612 /* 'not' operation */
613 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
617 ret->operation = LDB_OP_NOT;
618 ret->u.isnot.child = ldap_decode_filter_tree(ret, data);
619 if (ret->u.isnot.child == NULL) {
622 if (!asn1_end_tag(data)) {
632 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
633 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
634 asn1_read_OctetString(data, mem_ctx, &value);
636 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
640 ret->operation = LDB_OP_EQUALITY;
641 ret->u.equality.attr = talloc_steal(ret, attrib);
642 ret->u.equality.value.data = talloc_steal(ret, value.data);
643 ret->u.equality.value.length = value.length;
653 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
656 if (!asn1_read_OctetString(data, mem_ctx, &attr)) {
660 ret->operation = LDB_OP_SUBSTRING;
661 ret->u.substring.attr = talloc_strndup(ret, (char *)attr.data, attr.length);
662 ret->u.substring.chunks = NULL;
663 ret->u.substring.start_with_wildcard = 1;
664 ret->u.substring.end_with_wildcard = 1;
666 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
670 while (asn1_tag_remaining(data)) {
671 asn1_peek_uint8(data, &subs_tag);
672 subs_tag &= 0x1f; /* strip off the asn1 stuff */
673 if (subs_tag > 2) goto failed;
675 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(subs_tag));
676 asn1_read_LDAPString(data, mem_ctx, &value);
681 if (ret->u.substring.chunks != NULL) {
682 /* initial value found in the middle */
686 ret->u.substring.chunks = ldap_decode_substring(ret, NULL, 0, value);
687 if (ret->u.substring.chunks == NULL) {
691 ret->u.substring.start_with_wildcard = 0;
696 if (ret->u.substring.end_with_wildcard == 0) {
697 /* "any" value found after a "final" value */
701 ret->u.substring.chunks = ldap_decode_substring(ret,
702 ret->u.substring.chunks,
705 if (ret->u.substring.chunks == NULL) {
713 ret->u.substring.chunks = ldap_decode_substring(ret,
714 ret->u.substring.chunks,
717 if (ret->u.substring.chunks == NULL) {
721 ret->u.substring.end_with_wildcard = 0;
730 if (!asn1_end_tag(data)) { /* SEQUENCE */
734 if (!asn1_end_tag(data)) {
744 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
745 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
746 asn1_read_OctetString(data, mem_ctx, &value);
748 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
752 ret->operation = LDB_OP_GREATER;
753 ret->u.comparison.attr = talloc_steal(ret, attrib);
754 ret->u.comparison.value.data = talloc_steal(ret, value.data);
755 ret->u.comparison.value.length = value.length;
763 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
764 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
765 asn1_read_OctetString(data, mem_ctx, &value);
767 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
771 ret->operation = LDB_OP_LESS;
772 ret->u.comparison.attr = talloc_steal(ret, attrib);
773 ret->u.comparison.value.data = talloc_steal(ret, value.data);
774 ret->u.comparison.value.length = value.length;
778 /* Normal presence, "attribute=*" */
781 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(filter_tag))) {
784 if (!asn1_read_LDAPString(data, ret, &attr)) {
788 ret->operation = LDB_OP_PRESENT;
789 ret->u.present.attr = talloc_steal(ret, attr);
791 if (!asn1_end_tag(data)) {
801 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
802 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
803 asn1_read_OctetString(data, mem_ctx, &value);
805 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
809 ret->operation = LDB_OP_APPROX;
810 ret->u.comparison.attr = talloc_steal(ret, attrib);
811 ret->u.comparison.value.data = talloc_steal(ret, value.data);
812 ret->u.comparison.value.length = value.length;
816 char *oid = NULL, *attr = NULL, *value;
817 uint8_t dnAttributes;
818 /* an extended search */
819 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
823 /* FIXME: read carefully rfc2251.txt there are a number of 'MUST's
824 we need to check we properly implement --SSS */
825 /* either oid or type must be defined */
826 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
827 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(1));
828 asn1_read_LDAPString(data, ret, &oid);
831 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(2))) { /* optional */
832 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(2));
833 asn1_read_LDAPString(data, ret, &attr);
836 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(3));
837 asn1_read_LDAPString(data, ret, &value);
839 /* dnAttributes is marked as BOOLEAN DEFAULT FALSE
840 it is not marked as OPTIONAL but openldap tools
841 do not set this unless it is to be set as TRUE
842 NOTE: openldap tools do not work with AD as it
843 seems that AD always requires the dnAttributes
844 boolean value to be set */
845 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(4))) {
846 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(4));
847 asn1_read_uint8(data, &dnAttributes);
852 if ((oid == NULL && attr == NULL) || (value == NULL)) {
857 ret->operation = LDB_OP_EXTENDED;
859 /* From the RFC2251: If the type field is
860 absent and matchingRule is present, the matchValue is compared
861 against all attributes in an entry which support that matchingRule
864 ret->u.extended.attr = talloc_steal(ret, attr);
866 ret->u.extended.attr = talloc_strdup(ret, "*");
868 ret->u.extended.rule_id = talloc_steal(ret, oid);
869 ret->u.extended.value.data = talloc_steal(ret, value);
870 ret->u.extended.value.length = strlen(value);
871 ret->u.extended.dnAttributes = dnAttributes;
873 ret->operation = LDB_OP_EQUALITY;
874 ret->u.equality.attr = talloc_steal(ret, attr);
875 ret->u.equality.value.data = talloc_steal(ret, value);
876 ret->u.equality.value.length = strlen(value);
878 if (!asn1_end_tag(data)) {
885 DEBUG(0,("Unsupported LDAP filter operation 0x%x\n", filter_tag));
897 static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
898 struct ldb_message_element *attrib)
900 asn1_start_tag(data, ASN1_SEQUENCE(0));
901 asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name);
902 asn1_start_tag(data, ASN1_SET);
903 while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
905 asn1_read_OctetString(data, mem_ctx, &blob);
906 add_value_to_attrib(mem_ctx, &blob, attrib);
913 static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
914 struct ldb_message_element **attributes,
917 asn1_start_tag(data, ASN1_SEQUENCE(0));
918 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
919 struct ldb_message_element attrib;
921 ldap_decode_attrib(mem_ctx, data, &attrib);
922 add_attrib_to_array_talloc(mem_ctx, &attrib,
923 attributes, num_attributes);
928 /* This routine returns LDAP status codes */
930 NTSTATUS ldap_decode(struct asn1_data *data, struct ldap_message *msg)
934 asn1_start_tag(data, ASN1_SEQUENCE(0));
935 asn1_read_Integer(data, &msg->messageid);
937 if (!asn1_peek_uint8(data, &tag))
938 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
942 case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
943 struct ldap_BindRequest *r = &msg->r.BindRequest;
944 msg->type = LDAP_TAG_BindRequest;
945 asn1_start_tag(data, tag);
946 asn1_read_Integer(data, &r->version);
947 asn1_read_OctetString_talloc(msg, data, &r->dn);
948 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
950 r->creds.password = "";
951 r->mechanism = LDAP_AUTH_MECH_SIMPLE;
952 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
953 pwlen = asn1_tag_remaining(data);
955 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
958 char *pw = talloc_array(msg, char, pwlen+1);
960 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
962 asn1_read(data, pw, pwlen);
964 r->creds.password = pw;
967 } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
968 asn1_start_tag(data, ASN1_CONTEXT(3));
969 r->mechanism = LDAP_AUTH_MECH_SASL;
970 asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism);
971 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) { /* optional */
972 DATA_BLOB tmp_blob = data_blob(NULL, 0);
973 asn1_read_OctetString(data, msg, &tmp_blob);
974 r->creds.SASL.secblob = talloc(msg, DATA_BLOB);
975 if (!r->creds.SASL.secblob) {
976 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
978 *r->creds.SASL.secblob = data_blob_talloc(r->creds.SASL.secblob,
979 tmp_blob.data, tmp_blob.length);
980 data_blob_free(&tmp_blob);
982 r->creds.SASL.secblob = NULL;
986 /* Neither Simple nor SASL bind */
987 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
993 case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
994 struct ldap_BindResponse *r = &msg->r.BindResponse;
995 msg->type = LDAP_TAG_BindResponse;
996 asn1_start_tag(data, tag);
997 ldap_decode_response(msg, data, &r->response);
998 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
999 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1000 asn1_read_ContextSimple(data, 7, &tmp_blob);
1001 r->SASL.secblob = talloc(msg, DATA_BLOB);
1002 if (!r->SASL.secblob) {
1003 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1005 *r->SASL.secblob = data_blob_talloc(r->SASL.secblob,
1006 tmp_blob.data, tmp_blob.length);
1007 data_blob_free(&tmp_blob);
1009 r->SASL.secblob = NULL;
1015 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
1016 msg->type = LDAP_TAG_UnbindRequest;
1017 asn1_start_tag(data, tag);
1022 case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
1023 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
1024 msg->type = LDAP_TAG_SearchRequest;
1025 asn1_start_tag(data, tag);
1026 asn1_read_OctetString_talloc(msg, data, &r->basedn);
1027 asn1_read_enumerated(data, (int *)&(r->scope));
1028 asn1_read_enumerated(data, (int *)&(r->deref));
1029 asn1_read_Integer(data, &r->sizelimit);
1030 asn1_read_Integer(data, &r->timelimit);
1031 asn1_read_BOOLEAN(data, &r->attributesonly);
1033 r->tree = ldap_decode_filter_tree(msg, data);
1034 if (r->tree == NULL) {
1035 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1038 asn1_start_tag(data, ASN1_SEQUENCE(0));
1040 r->num_attributes = 0;
1041 r->attributes = NULL;
1043 while (asn1_tag_remaining(data) > 0) {
1046 if (!asn1_read_OctetString_talloc(msg, data,
1048 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1049 if (!add_string_to_array(msg, attr,
1051 &r->num_attributes))
1052 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1060 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1061 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1062 msg->type = LDAP_TAG_SearchResultEntry;
1063 r->attributes = NULL;
1064 r->num_attributes = 0;
1065 asn1_start_tag(data, tag);
1066 asn1_read_OctetString_talloc(msg, data, &r->dn);
1067 ldap_decode_attribs(msg, data, &r->attributes,
1068 &r->num_attributes);
1073 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1074 struct ldap_Result *r = &msg->r.SearchResultDone;
1075 msg->type = LDAP_TAG_SearchResultDone;
1076 asn1_start_tag(data, tag);
1077 ldap_decode_response(msg, data, r);
1082 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1083 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
1084 msg->type = LDAP_TAG_SearchResultReference;
1085 asn1_start_tag(data, tag);
1086 asn1_read_OctetString_talloc(msg, data, &r->referral);
1091 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1092 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1093 msg->type = LDAP_TAG_ModifyRequest;
1094 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
1095 asn1_read_OctetString_talloc(msg, data, &r->dn);
1096 asn1_start_tag(data, ASN1_SEQUENCE(0));
1101 while (asn1_tag_remaining(data) > 0) {
1102 struct ldap_mod mod;
1105 asn1_start_tag(data, ASN1_SEQUENCE(0));
1106 asn1_read_enumerated(data, &v);
1108 ldap_decode_attrib(msg, data, &mod.attrib);
1110 if (!add_mod_to_array_talloc(msg, &mod,
1111 &r->mods, &r->num_mods)) {
1112 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1121 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1122 struct ldap_Result *r = &msg->r.ModifyResponse;
1123 msg->type = LDAP_TAG_ModifyResponse;
1124 asn1_start_tag(data, tag);
1125 ldap_decode_response(msg, data, r);
1130 case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1131 struct ldap_AddRequest *r = &msg->r.AddRequest;
1132 msg->type = LDAP_TAG_AddRequest;
1133 asn1_start_tag(data, tag);
1134 asn1_read_OctetString_talloc(msg, data, &r->dn);
1136 r->attributes = NULL;
1137 r->num_attributes = 0;
1138 ldap_decode_attribs(msg, data, &r->attributes,
1139 &r->num_attributes);
1145 case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1146 struct ldap_Result *r = &msg->r.AddResponse;
1147 msg->type = LDAP_TAG_AddResponse;
1148 asn1_start_tag(data, tag);
1149 ldap_decode_response(msg, data, r);
1154 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1155 struct ldap_DelRequest *r = &msg->r.DelRequest;
1158 msg->type = LDAP_TAG_DelRequest;
1159 asn1_start_tag(data,
1160 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
1161 len = asn1_tag_remaining(data);
1163 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1165 dn = talloc_array(msg, char, len+1);
1168 asn1_read(data, dn, len);
1175 case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1176 struct ldap_Result *r = &msg->r.DelResponse;
1177 msg->type = LDAP_TAG_DelResponse;
1178 asn1_start_tag(data, tag);
1179 ldap_decode_response(msg, data, r);
1184 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1185 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1186 msg->type = LDAP_TAG_ModifyDNRequest;
1187 asn1_start_tag(data,
1188 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
1189 asn1_read_OctetString_talloc(msg, data, &r->dn);
1190 asn1_read_OctetString_talloc(msg, data, &r->newrdn);
1191 asn1_read_BOOLEAN(data, &r->deleteolddn);
1192 r->newsuperior = NULL;
1193 if (asn1_tag_remaining(data) > 0) {
1196 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1197 len = asn1_tag_remaining(data);
1199 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1201 newsup = talloc_array(msg, char, len+1);
1202 if (newsup == NULL) {
1203 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1205 asn1_read(data, newsup, len);
1207 r->newsuperior = newsup;
1214 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1215 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1216 msg->type = LDAP_TAG_ModifyDNResponse;
1217 asn1_start_tag(data, tag);
1218 ldap_decode_response(msg, data, r);
1223 case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1224 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1225 msg->type = LDAP_TAG_CompareRequest;
1226 asn1_start_tag(data,
1227 ASN1_APPLICATION(LDAP_TAG_CompareRequest));
1228 asn1_read_OctetString_talloc(msg, data, &r->dn);
1229 asn1_start_tag(data, ASN1_SEQUENCE(0));
1230 asn1_read_OctetString_talloc(msg, data, &r->attribute);
1231 asn1_read_OctetString(data, msg, &r->value);
1232 if (r->value.data) {
1233 talloc_steal(msg, r->value.data);
1240 case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1241 struct ldap_Result *r = &msg->r.CompareResponse;
1242 msg->type = LDAP_TAG_CompareResponse;
1243 asn1_start_tag(data, tag);
1244 ldap_decode_response(msg, data, r);
1249 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1250 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1251 msg->type = LDAP_TAG_AbandonRequest;
1252 asn1_start_tag(data, tag);
1253 asn1_read_implicit_Integer(data, &r->messageid);
1258 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1259 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1260 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1262 msg->type = LDAP_TAG_ExtendedRequest;
1263 asn1_start_tag(data,tag);
1264 if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
1265 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1267 r->oid = blob2string_talloc(msg, tmp_blob);
1268 data_blob_free(&tmp_blob);
1270 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1273 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1274 asn1_read_ContextSimple(data, 1, &tmp_blob);
1275 r->value = talloc(msg, DATA_BLOB);
1277 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1279 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1280 data_blob_free(&tmp_blob);
1289 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1290 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1291 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1293 msg->type = LDAP_TAG_ExtendedResponse;
1294 asn1_start_tag(data, tag);
1295 ldap_decode_response(msg, data, &r->response);
1297 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(10))) {
1298 asn1_read_ContextSimple(data, 1, &tmp_blob);
1299 r->oid = blob2string_talloc(msg, tmp_blob);
1300 data_blob_free(&tmp_blob);
1302 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1308 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(11))) {
1309 asn1_read_ContextSimple(data, 1, &tmp_blob);
1310 r->value = talloc(msg, DATA_BLOB);
1312 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1314 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1315 data_blob_free(&tmp_blob);
1324 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1327 msg->controls = NULL;
1328 msg->controls_decoded = NULL;
1330 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1332 struct ldb_control **ctrl = NULL;
1333 bool *decoded = NULL;
1335 asn1_start_tag(data, ASN1_CONTEXT(0));
1337 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1339 /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1341 ctrl = talloc_realloc(msg, ctrl, struct ldb_control *, i+2);
1343 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1346 decoded = talloc_realloc(msg, decoded, bool, i+1);
1348 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1351 ctrl[i] = talloc(ctrl, struct ldb_control);
1353 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1356 if (!ldap_decode_control_wrapper(ctrl, data, ctrl[i], &value)) {
1357 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1360 if (!ldap_decode_control_value(ctrl, value, ctrl[i])) {
1361 if (ctrl[i]->critical) {
1362 ctrl[i]->data = NULL;
1366 talloc_free(ctrl[i]);
1379 msg->controls = ctrl;
1380 msg->controls_decoded = decoded;
1386 if ((data->has_error) || (data->nesting != NULL)) {
1387 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1389 return NT_STATUS_OK;
1394 return NT_STATUS_OK if a blob has enough bytes in it to be a full
1395 ldap packet. Set packet_size if true.
1397 NTSTATUS ldap_full_packet(void *private_data, DATA_BLOB blob, size_t *packet_size)
1399 return asn1_full_tag(blob, ASN1_SEQUENCE(0), packet_size);