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.h"
28 #include "libcli/ldap/ldap_proto.h"
31 static bool ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree)
35 switch (tree->operation) {
38 asn1_push_tag(data, ASN1_CONTEXT(tree->operation==LDB_OP_AND?0:1));
39 for (i=0; i<tree->u.list.num_elements; i++) {
40 if (!ldap_push_filter(data, tree->u.list.elements[i])) {
48 asn1_push_tag(data, ASN1_CONTEXT(2));
49 if (!ldap_push_filter(data, tree->u.isnot.child)) {
57 asn1_push_tag(data, ASN1_CONTEXT(3));
58 asn1_write_OctetString(data, tree->u.equality.attr,
59 strlen(tree->u.equality.attr));
60 asn1_write_OctetString(data, tree->u.equality.value.data,
61 tree->u.equality.value.length);
65 case LDB_OP_SUBSTRING:
67 SubstringFilter ::= SEQUENCE {
68 type AttributeDescription,
69 -- at least one must be present
70 substrings SEQUENCE OF CHOICE {
71 initial [0] LDAPString,
73 final [2] LDAPString } }
75 asn1_push_tag(data, ASN1_CONTEXT(4));
76 asn1_write_OctetString(data, tree->u.substring.attr, strlen(tree->u.substring.attr));
77 asn1_push_tag(data, ASN1_SEQUENCE(0));
79 if ( ! tree->u.substring.start_with_wildcard) {
80 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
81 asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i]);
85 while (tree->u.substring.chunks[i]) {
88 if (( ! tree->u.substring.chunks[i + 1]) &&
89 (tree->u.substring.end_with_wildcard == 0)) {
94 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(ctx));
95 asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i]);
104 /* greaterOrEqual test */
105 asn1_push_tag(data, ASN1_CONTEXT(5));
106 asn1_write_OctetString(data, tree->u.comparison.attr,
107 strlen(tree->u.comparison.attr));
108 asn1_write_OctetString(data, tree->u.comparison.value.data,
109 tree->u.comparison.value.length);
114 /* lessOrEqual test */
115 asn1_push_tag(data, ASN1_CONTEXT(6));
116 asn1_write_OctetString(data, tree->u.comparison.attr,
117 strlen(tree->u.comparison.attr));
118 asn1_write_OctetString(data, tree->u.comparison.value.data,
119 tree->u.comparison.value.length);
125 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(7));
126 asn1_write_LDAPString(data, tree->u.present.attr);
128 return !data->has_error;
132 asn1_push_tag(data, ASN1_CONTEXT(8));
133 asn1_write_OctetString(data, tree->u.comparison.attr,
134 strlen(tree->u.comparison.attr));
135 asn1_write_OctetString(data, tree->u.comparison.value.data,
136 tree->u.comparison.value.length);
140 case LDB_OP_EXTENDED:
142 MatchingRuleAssertion ::= SEQUENCE {
143 matchingRule [1] MatchingRuleID OPTIONAL,
144 type [2] AttributeDescription OPTIONAL,
145 matchValue [3] AssertionValue,
146 dnAttributes [4] BOOLEAN DEFAULT FALSE
149 asn1_push_tag(data, ASN1_CONTEXT(9));
150 if (tree->u.extended.rule_id) {
151 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1));
152 asn1_write_LDAPString(data, tree->u.extended.rule_id);
155 if (tree->u.extended.attr) {
156 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(2));
157 asn1_write_LDAPString(data, tree->u.extended.attr);
160 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(3));
161 asn1_write_DATA_BLOB_LDAPString(data, &tree->u.extended.value);
163 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(4));
164 asn1_write_uint8(data, tree->u.extended.dnAttributes);
172 return !data->has_error;
175 static void ldap_encode_response(struct asn1_data *data, struct ldap_Result *result)
177 asn1_write_enumerated(data, result->resultcode);
178 asn1_write_OctetString(data, result->dn,
179 (result->dn) ? strlen(result->dn) : 0);
180 asn1_write_OctetString(data, result->errormessage,
181 (result->errormessage) ?
182 strlen(result->errormessage) : 0);
183 if (result->referral) {
184 asn1_push_tag(data, ASN1_CONTEXT(3));
185 asn1_write_OctetString(data, result->referral,
186 strlen(result->referral));
191 _PUBLIC_ bool ldap_encode(struct ldap_message *msg, DATA_BLOB *result, TALLOC_CTX *mem_ctx)
193 struct asn1_data *data = asn1_init(mem_ctx);
196 if (!data) return false;
198 asn1_push_tag(data, ASN1_SEQUENCE(0));
199 asn1_write_Integer(data, msg->messageid);
202 case LDAP_TAG_BindRequest: {
203 struct ldap_BindRequest *r = &msg->r.BindRequest;
204 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
205 asn1_write_Integer(data, r->version);
206 asn1_write_OctetString(data, r->dn,
207 (r->dn != NULL) ? strlen(r->dn) : 0);
209 switch (r->mechanism) {
210 case LDAP_AUTH_MECH_SIMPLE:
211 /* context, primitive */
212 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
213 asn1_write(data, r->creds.password,
214 strlen(r->creds.password));
217 case LDAP_AUTH_MECH_SASL:
218 /* context, constructed */
219 asn1_push_tag(data, ASN1_CONTEXT(3));
220 asn1_write_OctetString(data, r->creds.SASL.mechanism,
221 strlen(r->creds.SASL.mechanism));
222 if (r->creds.SASL.secblob) {
223 asn1_write_OctetString(data, r->creds.SASL.secblob->data,
224 r->creds.SASL.secblob->length);
235 case LDAP_TAG_BindResponse: {
236 struct ldap_BindResponse *r = &msg->r.BindResponse;
237 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
238 ldap_encode_response(data, &r->response);
239 if (r->SASL.secblob) {
240 asn1_write_ContextSimple(data, 7, r->SASL.secblob);
245 case LDAP_TAG_UnbindRequest: {
246 /* struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
249 case LDAP_TAG_SearchRequest: {
250 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
251 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
252 asn1_write_OctetString(data, r->basedn, strlen(r->basedn));
253 asn1_write_enumerated(data, r->scope);
254 asn1_write_enumerated(data, r->deref);
255 asn1_write_Integer(data, r->sizelimit);
256 asn1_write_Integer(data, r->timelimit);
257 asn1_write_BOOLEAN(data, r->attributesonly);
259 if (!ldap_push_filter(data, r->tree)) {
263 asn1_push_tag(data, ASN1_SEQUENCE(0));
264 for (i=0; i<r->num_attributes; i++) {
265 asn1_write_OctetString(data, r->attributes[i],
266 strlen(r->attributes[i]));
272 case LDAP_TAG_SearchResultEntry: {
273 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
274 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
275 asn1_write_OctetString(data, r->dn, strlen(r->dn));
276 asn1_push_tag(data, ASN1_SEQUENCE(0));
277 for (i=0; i<r->num_attributes; i++) {
278 struct ldb_message_element *attr = &r->attributes[i];
279 asn1_push_tag(data, ASN1_SEQUENCE(0));
280 asn1_write_OctetString(data, attr->name,
282 asn1_push_tag(data, ASN1_SEQUENCE(1));
283 for (j=0; j<attr->num_values; j++) {
284 asn1_write_OctetString(data,
285 attr->values[j].data,
286 attr->values[j].length);
295 case LDAP_TAG_SearchResultDone: {
296 struct ldap_Result *r = &msg->r.SearchResultDone;
297 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
298 ldap_encode_response(data, r);
302 case LDAP_TAG_ModifyRequest: {
303 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
304 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
305 asn1_write_OctetString(data, r->dn, strlen(r->dn));
306 asn1_push_tag(data, ASN1_SEQUENCE(0));
308 for (i=0; i<r->num_mods; i++) {
309 struct ldb_message_element *attrib = &r->mods[i].attrib;
310 asn1_push_tag(data, ASN1_SEQUENCE(0));
311 asn1_write_enumerated(data, r->mods[i].type);
312 asn1_push_tag(data, ASN1_SEQUENCE(0));
313 asn1_write_OctetString(data, attrib->name,
314 strlen(attrib->name));
315 asn1_push_tag(data, ASN1_SET);
316 for (j=0; j<attrib->num_values; j++) {
317 asn1_write_OctetString(data,
318 attrib->values[j].data,
319 attrib->values[j].length);
331 case LDAP_TAG_ModifyResponse: {
332 struct ldap_Result *r = &msg->r.ModifyResponse;
333 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
334 ldap_encode_response(data, r);
338 case LDAP_TAG_AddRequest: {
339 struct ldap_AddRequest *r = &msg->r.AddRequest;
340 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
341 asn1_write_OctetString(data, r->dn, strlen(r->dn));
342 asn1_push_tag(data, ASN1_SEQUENCE(0));
344 for (i=0; i<r->num_attributes; i++) {
345 struct ldb_message_element *attrib = &r->attributes[i];
346 asn1_push_tag(data, ASN1_SEQUENCE(0));
347 asn1_write_OctetString(data, attrib->name,
348 strlen(attrib->name));
349 asn1_push_tag(data, ASN1_SET);
350 for (j=0; j<r->attributes[i].num_values; j++) {
351 asn1_write_OctetString(data,
352 attrib->values[j].data,
353 attrib->values[j].length);
362 case LDAP_TAG_AddResponse: {
363 struct ldap_Result *r = &msg->r.AddResponse;
364 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
365 ldap_encode_response(data, r);
369 case LDAP_TAG_DelRequest: {
370 struct ldap_DelRequest *r = &msg->r.DelRequest;
371 asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type));
372 asn1_write(data, r->dn, strlen(r->dn));
376 case LDAP_TAG_DelResponse: {
377 struct ldap_Result *r = &msg->r.DelResponse;
378 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
379 ldap_encode_response(data, r);
383 case LDAP_TAG_ModifyDNRequest: {
384 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
385 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
386 asn1_write_OctetString(data, r->dn, strlen(r->dn));
387 asn1_write_OctetString(data, r->newrdn, strlen(r->newrdn));
388 asn1_write_BOOLEAN(data, r->deleteolddn);
389 if (r->newsuperior) {
390 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
391 asn1_write(data, r->newsuperior,
392 strlen(r->newsuperior));
398 case LDAP_TAG_ModifyDNResponse: {
399 struct ldap_Result *r = &msg->r.ModifyDNResponse;
400 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
401 ldap_encode_response(data, r);
405 case LDAP_TAG_CompareRequest: {
406 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
407 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
408 asn1_write_OctetString(data, r->dn, strlen(r->dn));
409 asn1_push_tag(data, ASN1_SEQUENCE(0));
410 asn1_write_OctetString(data, r->attribute,
411 strlen(r->attribute));
412 asn1_write_OctetString(data, r->value.data,
418 case LDAP_TAG_CompareResponse: {
419 struct ldap_Result *r = &msg->r.ModifyDNResponse;
420 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
421 ldap_encode_response(data, r);
425 case LDAP_TAG_AbandonRequest: {
426 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
427 asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type));
428 asn1_write_implicit_Integer(data, r->messageid);
432 case LDAP_TAG_SearchResultReference: {
433 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
434 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
435 asn1_write_OctetString(data, r->referral, strlen(r->referral));
439 case LDAP_TAG_ExtendedRequest: {
440 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
441 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
442 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
443 asn1_write(data, r->oid, strlen(r->oid));
446 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1));
447 asn1_write(data, r->value->data, r->value->length);
453 case LDAP_TAG_ExtendedResponse: {
454 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
455 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
456 ldap_encode_response(data, &r->response);
458 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(10));
459 asn1_write(data, r->oid, strlen(r->oid));
463 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(11));
464 asn1_write(data, r->value->data, r->value->length);
474 if (msg->controls != NULL) {
475 asn1_push_tag(data, ASN1_CONTEXT(0));
477 for (i = 0; msg->controls[i] != NULL; i++) {
478 if (!ldap_encode_control(mem_ctx, data, msg->controls[i])) {
488 if (data->has_error) {
493 *result = data_blob_talloc(mem_ctx, data->data, data->length);
498 static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
501 char *result = talloc_array(mem_ctx, char, blob.length+1);
502 memcpy(result, blob.data, blob.length);
503 result[blob.length] = '\0';
507 static bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
508 struct asn1_data *data,
512 if (!asn1_read_OctetString(data, mem_ctx, &string))
514 *result = blob2string_talloc(mem_ctx, string);
515 data_blob_free(&string);
519 static void ldap_decode_response(TALLOC_CTX *mem_ctx,
520 struct asn1_data *data,
521 struct ldap_Result *result)
523 asn1_read_enumerated(data, &result->resultcode);
524 asn1_read_OctetString_talloc(mem_ctx, data, &result->dn);
525 asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage);
526 if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
527 asn1_start_tag(data, ASN1_CONTEXT(3));
528 asn1_read_OctetString_talloc(mem_ctx, data, &result->referral);
531 result->referral = NULL;
535 static struct ldb_val **ldap_decode_substring(TALLOC_CTX *mem_ctx, struct ldb_val **chunks, int chunk_num, char *value)
538 chunks = talloc_realloc(mem_ctx, chunks, struct ldb_val *, chunk_num + 2);
539 if (chunks == NULL) {
543 chunks[chunk_num] = talloc(mem_ctx, struct ldb_val);
544 if (chunks[chunk_num] == NULL) {
548 chunks[chunk_num]->data = (uint8_t *)talloc_strdup(mem_ctx, value);
549 if (chunks[chunk_num]->data == NULL) {
552 chunks[chunk_num]->length = strlen(value);
554 chunks[chunk_num + 1] = '\0';
561 parse the ASN.1 formatted search string into a ldb_parse_tree
563 static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
564 struct asn1_data *data)
567 struct ldb_parse_tree *ret;
569 if (!asn1_peek_uint8(data, &filter_tag)) {
573 filter_tag &= 0x1f; /* strip off the asn1 stuff */
575 ret = talloc(mem_ctx, struct ldb_parse_tree);
576 if (ret == NULL) return NULL;
581 /* AND or OR of one or more filters */
582 ret->operation = (filter_tag == 0)?LDB_OP_AND:LDB_OP_OR;
583 ret->u.list.num_elements = 0;
584 ret->u.list.elements = NULL;
586 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
590 while (asn1_tag_remaining(data) > 0) {
591 struct ldb_parse_tree *subtree;
592 subtree = ldap_decode_filter_tree(ret, data);
593 if (subtree == NULL) {
596 ret->u.list.elements =
597 talloc_realloc(ret, ret->u.list.elements,
598 struct ldb_parse_tree *,
599 ret->u.list.num_elements+1);
600 if (ret->u.list.elements == NULL) {
603 talloc_steal(ret->u.list.elements, subtree);
604 ret->u.list.elements[ret->u.list.num_elements] = subtree;
605 ret->u.list.num_elements++;
607 if (!asn1_end_tag(data)) {
613 /* 'not' operation */
614 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
618 ret->operation = LDB_OP_NOT;
619 ret->u.isnot.child = ldap_decode_filter_tree(ret, data);
620 if (ret->u.isnot.child == NULL) {
623 if (!asn1_end_tag(data)) {
633 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
634 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
635 asn1_read_OctetString(data, mem_ctx, &value);
637 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
641 ret->operation = LDB_OP_EQUALITY;
642 ret->u.equality.attr = talloc_steal(ret, attrib);
643 ret->u.equality.value.data = talloc_steal(ret, value.data);
644 ret->u.equality.value.length = value.length;
654 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
657 if (!asn1_read_OctetString(data, mem_ctx, &attr)) {
661 ret->operation = LDB_OP_SUBSTRING;
662 ret->u.substring.attr = talloc_strndup(ret, (char *)attr.data, attr.length);
663 ret->u.substring.chunks = NULL;
664 ret->u.substring.start_with_wildcard = 1;
665 ret->u.substring.end_with_wildcard = 1;
667 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
671 while (asn1_tag_remaining(data)) {
672 asn1_peek_uint8(data, &subs_tag);
673 subs_tag &= 0x1f; /* strip off the asn1 stuff */
674 if (subs_tag > 2) goto failed;
676 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(subs_tag));
677 asn1_read_LDAPString(data, mem_ctx, &value);
682 if (ret->u.substring.chunks != NULL) {
683 /* initial value found in the middle */
687 ret->u.substring.chunks = ldap_decode_substring(ret, NULL, 0, value);
688 if (ret->u.substring.chunks == NULL) {
692 ret->u.substring.start_with_wildcard = 0;
697 if (ret->u.substring.end_with_wildcard == 0) {
698 /* "any" value found after a "final" value */
702 ret->u.substring.chunks = ldap_decode_substring(ret,
703 ret->u.substring.chunks,
706 if (ret->u.substring.chunks == NULL) {
714 ret->u.substring.chunks = ldap_decode_substring(ret,
715 ret->u.substring.chunks,
718 if (ret->u.substring.chunks == NULL) {
722 ret->u.substring.end_with_wildcard = 0;
731 if (!asn1_end_tag(data)) { /* SEQUENCE */
735 if (!asn1_end_tag(data)) {
745 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
746 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
747 asn1_read_OctetString(data, mem_ctx, &value);
749 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
753 ret->operation = LDB_OP_GREATER;
754 ret->u.comparison.attr = talloc_steal(ret, attrib);
755 ret->u.comparison.value.data = talloc_steal(ret, value.data);
756 ret->u.comparison.value.length = value.length;
764 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
765 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
766 asn1_read_OctetString(data, mem_ctx, &value);
768 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
772 ret->operation = LDB_OP_LESS;
773 ret->u.comparison.attr = talloc_steal(ret, attrib);
774 ret->u.comparison.value.data = talloc_steal(ret, value.data);
775 ret->u.comparison.value.length = value.length;
779 /* Normal presence, "attribute=*" */
782 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(filter_tag))) {
785 if (!asn1_read_LDAPString(data, ret, &attr)) {
789 ret->operation = LDB_OP_PRESENT;
790 ret->u.present.attr = talloc_steal(ret, attr);
792 if (!asn1_end_tag(data)) {
802 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
803 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
804 asn1_read_OctetString(data, mem_ctx, &value);
806 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
810 ret->operation = LDB_OP_APPROX;
811 ret->u.comparison.attr = talloc_steal(ret, attrib);
812 ret->u.comparison.value.data = talloc_steal(ret, value.data);
813 ret->u.comparison.value.length = value.length;
817 char *oid = NULL, *attr = NULL, *value;
818 uint8_t dnAttributes;
819 /* an extended search */
820 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
824 /* FIXME: read carefully rfc2251.txt there are a number of 'MUST's
825 we need to check we properly implement --SSS */
826 /* either oid or type must be defined */
827 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
828 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(1));
829 asn1_read_LDAPString(data, ret, &oid);
832 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(2))) { /* optional */
833 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(2));
834 asn1_read_LDAPString(data, ret, &attr);
837 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(3));
838 asn1_read_LDAPString(data, ret, &value);
840 /* dnAttributes is marked as BOOLEAN DEFAULT FALSE
841 it is not marked as OPTIONAL but openldap tools
842 do not set this unless it is to be set as TRUE
843 NOTE: openldap tools do not work with AD as it
844 seems that AD always requires the dnAttributes
845 boolean value to be set */
846 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(4))) {
847 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(4));
848 asn1_read_uint8(data, &dnAttributes);
853 if ((oid == NULL && attr == NULL) || (value == NULL)) {
858 ret->operation = LDB_OP_EXTENDED;
860 /* From the RFC2251: If the type field is
861 absent and matchingRule is present, the matchValue is compared
862 against all attributes in an entry which support that matchingRule
865 ret->u.extended.attr = talloc_steal(ret, attr);
867 ret->u.extended.attr = talloc_strdup(ret, "*");
869 ret->u.extended.rule_id = talloc_steal(ret, oid);
870 ret->u.extended.value.data = talloc_steal(ret, value);
871 ret->u.extended.value.length = strlen(value);
872 ret->u.extended.dnAttributes = dnAttributes;
874 ret->operation = LDB_OP_EQUALITY;
875 ret->u.equality.attr = talloc_steal(ret, attr);
876 ret->u.equality.value.data = talloc_steal(ret, value);
877 ret->u.equality.value.length = strlen(value);
879 if (!asn1_end_tag(data)) {
886 DEBUG(0,("Unsupported LDAP filter operation 0x%x\n", filter_tag));
898 static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
899 struct ldb_message_element *attrib)
901 asn1_start_tag(data, ASN1_SEQUENCE(0));
902 asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name);
903 asn1_start_tag(data, ASN1_SET);
904 while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
906 asn1_read_OctetString(data, mem_ctx, &blob);
907 add_value_to_attrib(mem_ctx, &blob, attrib);
914 static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
915 struct ldb_message_element **attributes,
918 asn1_start_tag(data, ASN1_SEQUENCE(0));
919 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
920 struct ldb_message_element attrib;
922 ldap_decode_attrib(mem_ctx, data, &attrib);
923 add_attrib_to_array_talloc(mem_ctx, &attrib,
924 attributes, num_attributes);
929 /* This routine returns LDAP status codes */
931 _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, struct ldap_message *msg)
935 asn1_start_tag(data, ASN1_SEQUENCE(0));
936 asn1_read_Integer(data, &msg->messageid);
938 if (!asn1_peek_uint8(data, &tag))
939 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
943 case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
944 struct ldap_BindRequest *r = &msg->r.BindRequest;
945 msg->type = LDAP_TAG_BindRequest;
946 asn1_start_tag(data, tag);
947 asn1_read_Integer(data, &r->version);
948 asn1_read_OctetString_talloc(msg, data, &r->dn);
949 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
951 r->creds.password = "";
952 r->mechanism = LDAP_AUTH_MECH_SIMPLE;
953 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
954 pwlen = asn1_tag_remaining(data);
956 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
959 char *pw = talloc_array(msg, char, pwlen+1);
961 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
963 asn1_read(data, pw, pwlen);
965 r->creds.password = pw;
968 } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
969 asn1_start_tag(data, ASN1_CONTEXT(3));
970 r->mechanism = LDAP_AUTH_MECH_SASL;
971 asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism);
972 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) { /* optional */
973 DATA_BLOB tmp_blob = data_blob(NULL, 0);
974 asn1_read_OctetString(data, msg, &tmp_blob);
975 r->creds.SASL.secblob = talloc(msg, DATA_BLOB);
976 if (!r->creds.SASL.secblob) {
977 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
979 *r->creds.SASL.secblob = data_blob_talloc(r->creds.SASL.secblob,
980 tmp_blob.data, tmp_blob.length);
981 data_blob_free(&tmp_blob);
983 r->creds.SASL.secblob = NULL;
987 /* Neither Simple nor SASL bind */
988 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
994 case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
995 struct ldap_BindResponse *r = &msg->r.BindResponse;
996 msg->type = LDAP_TAG_BindResponse;
997 asn1_start_tag(data, tag);
998 ldap_decode_response(msg, data, &r->response);
999 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
1000 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1001 asn1_read_ContextSimple(data, 7, &tmp_blob);
1002 r->SASL.secblob = talloc(msg, DATA_BLOB);
1003 if (!r->SASL.secblob) {
1004 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1006 *r->SASL.secblob = data_blob_talloc(r->SASL.secblob,
1007 tmp_blob.data, tmp_blob.length);
1008 data_blob_free(&tmp_blob);
1010 r->SASL.secblob = NULL;
1016 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
1017 msg->type = LDAP_TAG_UnbindRequest;
1018 asn1_start_tag(data, tag);
1023 case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
1024 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
1025 msg->type = LDAP_TAG_SearchRequest;
1026 asn1_start_tag(data, tag);
1027 asn1_read_OctetString_talloc(msg, data, &r->basedn);
1028 asn1_read_enumerated(data, (int *)&(r->scope));
1029 asn1_read_enumerated(data, (int *)&(r->deref));
1030 asn1_read_Integer(data, &r->sizelimit);
1031 asn1_read_Integer(data, &r->timelimit);
1032 asn1_read_BOOLEAN(data, &r->attributesonly);
1034 r->tree = ldap_decode_filter_tree(msg, data);
1035 if (r->tree == NULL) {
1036 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1039 asn1_start_tag(data, ASN1_SEQUENCE(0));
1041 r->num_attributes = 0;
1042 r->attributes = NULL;
1044 while (asn1_tag_remaining(data) > 0) {
1047 if (!asn1_read_OctetString_talloc(msg, data,
1049 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1050 if (!add_string_to_array(msg, attr,
1052 &r->num_attributes))
1053 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1061 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1062 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1063 msg->type = LDAP_TAG_SearchResultEntry;
1064 r->attributes = NULL;
1065 r->num_attributes = 0;
1066 asn1_start_tag(data, tag);
1067 asn1_read_OctetString_talloc(msg, data, &r->dn);
1068 ldap_decode_attribs(msg, data, &r->attributes,
1069 &r->num_attributes);
1074 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1075 struct ldap_Result *r = &msg->r.SearchResultDone;
1076 msg->type = LDAP_TAG_SearchResultDone;
1077 asn1_start_tag(data, tag);
1078 ldap_decode_response(msg, data, r);
1083 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1084 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
1085 msg->type = LDAP_TAG_SearchResultReference;
1086 asn1_start_tag(data, tag);
1087 asn1_read_OctetString_talloc(msg, data, &r->referral);
1092 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1093 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1094 msg->type = LDAP_TAG_ModifyRequest;
1095 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
1096 asn1_read_OctetString_talloc(msg, data, &r->dn);
1097 asn1_start_tag(data, ASN1_SEQUENCE(0));
1102 while (asn1_tag_remaining(data) > 0) {
1103 struct ldap_mod mod;
1106 asn1_start_tag(data, ASN1_SEQUENCE(0));
1107 asn1_read_enumerated(data, &v);
1109 ldap_decode_attrib(msg, data, &mod.attrib);
1111 if (!add_mod_to_array_talloc(msg, &mod,
1112 &r->mods, &r->num_mods)) {
1113 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1122 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1123 struct ldap_Result *r = &msg->r.ModifyResponse;
1124 msg->type = LDAP_TAG_ModifyResponse;
1125 asn1_start_tag(data, tag);
1126 ldap_decode_response(msg, data, r);
1131 case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1132 struct ldap_AddRequest *r = &msg->r.AddRequest;
1133 msg->type = LDAP_TAG_AddRequest;
1134 asn1_start_tag(data, tag);
1135 asn1_read_OctetString_talloc(msg, data, &r->dn);
1137 r->attributes = NULL;
1138 r->num_attributes = 0;
1139 ldap_decode_attribs(msg, data, &r->attributes,
1140 &r->num_attributes);
1146 case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1147 struct ldap_Result *r = &msg->r.AddResponse;
1148 msg->type = LDAP_TAG_AddResponse;
1149 asn1_start_tag(data, tag);
1150 ldap_decode_response(msg, data, r);
1155 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1156 struct ldap_DelRequest *r = &msg->r.DelRequest;
1159 msg->type = LDAP_TAG_DelRequest;
1160 asn1_start_tag(data,
1161 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
1162 len = asn1_tag_remaining(data);
1164 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1166 dn = talloc_array(msg, char, len+1);
1169 asn1_read(data, dn, len);
1176 case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1177 struct ldap_Result *r = &msg->r.DelResponse;
1178 msg->type = LDAP_TAG_DelResponse;
1179 asn1_start_tag(data, tag);
1180 ldap_decode_response(msg, data, r);
1185 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1186 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1187 msg->type = LDAP_TAG_ModifyDNRequest;
1188 asn1_start_tag(data,
1189 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
1190 asn1_read_OctetString_talloc(msg, data, &r->dn);
1191 asn1_read_OctetString_talloc(msg, data, &r->newrdn);
1192 asn1_read_BOOLEAN(data, &r->deleteolddn);
1193 r->newsuperior = NULL;
1194 if (asn1_tag_remaining(data) > 0) {
1197 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1198 len = asn1_tag_remaining(data);
1200 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1202 newsup = talloc_array(msg, char, len+1);
1203 if (newsup == NULL) {
1204 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1206 asn1_read(data, newsup, len);
1208 r->newsuperior = newsup;
1215 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1216 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1217 msg->type = LDAP_TAG_ModifyDNResponse;
1218 asn1_start_tag(data, tag);
1219 ldap_decode_response(msg, data, r);
1224 case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1225 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1226 msg->type = LDAP_TAG_CompareRequest;
1227 asn1_start_tag(data,
1228 ASN1_APPLICATION(LDAP_TAG_CompareRequest));
1229 asn1_read_OctetString_talloc(msg, data, &r->dn);
1230 asn1_start_tag(data, ASN1_SEQUENCE(0));
1231 asn1_read_OctetString_talloc(msg, data, &r->attribute);
1232 asn1_read_OctetString(data, msg, &r->value);
1233 if (r->value.data) {
1234 talloc_steal(msg, r->value.data);
1241 case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1242 struct ldap_Result *r = &msg->r.CompareResponse;
1243 msg->type = LDAP_TAG_CompareResponse;
1244 asn1_start_tag(data, tag);
1245 ldap_decode_response(msg, data, r);
1250 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1251 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1252 msg->type = LDAP_TAG_AbandonRequest;
1253 asn1_start_tag(data, tag);
1254 asn1_read_implicit_Integer(data, &r->messageid);
1259 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1260 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1261 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1263 msg->type = LDAP_TAG_ExtendedRequest;
1264 asn1_start_tag(data,tag);
1265 if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
1266 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1268 r->oid = blob2string_talloc(msg, tmp_blob);
1269 data_blob_free(&tmp_blob);
1271 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1274 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1275 asn1_read_ContextSimple(data, 1, &tmp_blob);
1276 r->value = talloc(msg, DATA_BLOB);
1278 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1280 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1281 data_blob_free(&tmp_blob);
1290 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1291 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1292 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1294 msg->type = LDAP_TAG_ExtendedResponse;
1295 asn1_start_tag(data, tag);
1296 ldap_decode_response(msg, data, &r->response);
1298 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(10))) {
1299 asn1_read_ContextSimple(data, 1, &tmp_blob);
1300 r->oid = blob2string_talloc(msg, tmp_blob);
1301 data_blob_free(&tmp_blob);
1303 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1309 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(11))) {
1310 asn1_read_ContextSimple(data, 1, &tmp_blob);
1311 r->value = talloc(msg, DATA_BLOB);
1313 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1315 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1316 data_blob_free(&tmp_blob);
1325 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1328 msg->controls = NULL;
1329 msg->controls_decoded = NULL;
1331 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1333 struct ldb_control **ctrl = NULL;
1334 bool *decoded = NULL;
1336 asn1_start_tag(data, ASN1_CONTEXT(0));
1338 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1340 /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1342 ctrl = talloc_realloc(msg, ctrl, struct ldb_control *, i+2);
1344 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1347 decoded = talloc_realloc(msg, decoded, bool, i+1);
1349 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1352 ctrl[i] = talloc(ctrl, struct ldb_control);
1354 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1357 if (!ldap_decode_control_wrapper(ctrl, data, ctrl[i], &value)) {
1358 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1361 if (!ldap_decode_control_value(ctrl, value, ctrl[i])) {
1362 if (ctrl[i]->critical) {
1363 ctrl[i]->data = NULL;
1367 talloc_free(ctrl[i]);
1380 msg->controls = ctrl;
1381 msg->controls_decoded = decoded;
1387 if ((data->has_error) || (data->nesting != NULL)) {
1388 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1390 return NT_STATUS_OK;
1395 return NT_STATUS_OK if a blob has enough bytes in it to be a full
1396 ldap packet. Set packet_size if true.
1398 NTSTATUS ldap_full_packet(void *private_data, DATA_BLOB blob, size_t *packet_size)
1400 return asn1_full_tag(blob, ASN1_SEQUENCE(0), packet_size);