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 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));
897 /* Decode a single LDAP attribute, possibly containing multiple values */
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 /* Decode a set of LDAP attributes, as found in the dereference control */
915 void ldap_decode_attribs_bare(TALLOC_CTX *mem_ctx, struct asn1_data *data,
916 struct ldb_message_element **attributes,
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);
928 /* Decode a set of LDAP attributes, as found in a search entry */
929 void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
930 struct ldb_message_element **attributes,
933 asn1_start_tag(data, ASN1_SEQUENCE(0));
934 ldap_decode_attribs_bare(mem_ctx, data,
935 attributes, num_attributes);
939 /* This routine returns LDAP status codes */
941 _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, struct ldap_message *msg)
945 asn1_start_tag(data, ASN1_SEQUENCE(0));
946 asn1_read_Integer(data, &msg->messageid);
948 if (!asn1_peek_uint8(data, &tag))
949 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
953 case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
954 struct ldap_BindRequest *r = &msg->r.BindRequest;
955 msg->type = LDAP_TAG_BindRequest;
956 asn1_start_tag(data, tag);
957 asn1_read_Integer(data, &r->version);
958 asn1_read_OctetString_talloc(msg, data, &r->dn);
959 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
961 r->creds.password = "";
962 r->mechanism = LDAP_AUTH_MECH_SIMPLE;
963 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
964 pwlen = asn1_tag_remaining(data);
966 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
969 char *pw = talloc_array(msg, char, pwlen+1);
971 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
973 asn1_read(data, pw, pwlen);
975 r->creds.password = pw;
978 } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
979 asn1_start_tag(data, ASN1_CONTEXT(3));
980 r->mechanism = LDAP_AUTH_MECH_SASL;
981 asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism);
982 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) { /* optional */
983 DATA_BLOB tmp_blob = data_blob(NULL, 0);
984 asn1_read_OctetString(data, msg, &tmp_blob);
985 r->creds.SASL.secblob = talloc(msg, DATA_BLOB);
986 if (!r->creds.SASL.secblob) {
987 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
989 *r->creds.SASL.secblob = data_blob_talloc(r->creds.SASL.secblob,
990 tmp_blob.data, tmp_blob.length);
991 data_blob_free(&tmp_blob);
993 r->creds.SASL.secblob = NULL;
997 /* Neither Simple nor SASL bind */
998 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1004 case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
1005 struct ldap_BindResponse *r = &msg->r.BindResponse;
1006 msg->type = LDAP_TAG_BindResponse;
1007 asn1_start_tag(data, tag);
1008 ldap_decode_response(msg, data, &r->response);
1009 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
1010 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1011 asn1_read_ContextSimple(data, 7, &tmp_blob);
1012 r->SASL.secblob = talloc(msg, DATA_BLOB);
1013 if (!r->SASL.secblob) {
1014 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1016 *r->SASL.secblob = data_blob_talloc(r->SASL.secblob,
1017 tmp_blob.data, tmp_blob.length);
1018 data_blob_free(&tmp_blob);
1020 r->SASL.secblob = NULL;
1026 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
1027 msg->type = LDAP_TAG_UnbindRequest;
1028 asn1_start_tag(data, tag);
1033 case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
1034 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
1035 msg->type = LDAP_TAG_SearchRequest;
1036 asn1_start_tag(data, tag);
1037 asn1_read_OctetString_talloc(msg, data, &r->basedn);
1038 asn1_read_enumerated(data, (int *)&(r->scope));
1039 asn1_read_enumerated(data, (int *)&(r->deref));
1040 asn1_read_Integer(data, &r->sizelimit);
1041 asn1_read_Integer(data, &r->timelimit);
1042 asn1_read_BOOLEAN(data, &r->attributesonly);
1044 r->tree = ldap_decode_filter_tree(msg, data);
1045 if (r->tree == NULL) {
1046 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1049 asn1_start_tag(data, ASN1_SEQUENCE(0));
1051 r->num_attributes = 0;
1052 r->attributes = NULL;
1054 while (asn1_tag_remaining(data) > 0) {
1057 if (!asn1_read_OctetString_talloc(msg, data,
1059 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1060 if (!add_string_to_array(msg, attr,
1062 &r->num_attributes))
1063 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1071 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1072 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1073 msg->type = LDAP_TAG_SearchResultEntry;
1074 r->attributes = NULL;
1075 r->num_attributes = 0;
1076 asn1_start_tag(data, tag);
1077 asn1_read_OctetString_talloc(msg, data, &r->dn);
1078 ldap_decode_attribs(msg, data, &r->attributes,
1079 &r->num_attributes);
1084 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1085 struct ldap_Result *r = &msg->r.SearchResultDone;
1086 msg->type = LDAP_TAG_SearchResultDone;
1087 asn1_start_tag(data, tag);
1088 ldap_decode_response(msg, data, r);
1093 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1094 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
1095 msg->type = LDAP_TAG_SearchResultReference;
1096 asn1_start_tag(data, tag);
1097 asn1_read_OctetString_talloc(msg, data, &r->referral);
1102 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1103 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1104 msg->type = LDAP_TAG_ModifyRequest;
1105 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
1106 asn1_read_OctetString_talloc(msg, data, &r->dn);
1107 asn1_start_tag(data, ASN1_SEQUENCE(0));
1112 while (asn1_tag_remaining(data) > 0) {
1113 struct ldap_mod mod;
1116 asn1_start_tag(data, ASN1_SEQUENCE(0));
1117 asn1_read_enumerated(data, &v);
1119 ldap_decode_attrib(msg, data, &mod.attrib);
1121 if (!add_mod_to_array_talloc(msg, &mod,
1122 &r->mods, &r->num_mods)) {
1123 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1132 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1133 struct ldap_Result *r = &msg->r.ModifyResponse;
1134 msg->type = LDAP_TAG_ModifyResponse;
1135 asn1_start_tag(data, tag);
1136 ldap_decode_response(msg, data, r);
1141 case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1142 struct ldap_AddRequest *r = &msg->r.AddRequest;
1143 msg->type = LDAP_TAG_AddRequest;
1144 asn1_start_tag(data, tag);
1145 asn1_read_OctetString_talloc(msg, data, &r->dn);
1147 r->attributes = NULL;
1148 r->num_attributes = 0;
1149 ldap_decode_attribs(msg, data, &r->attributes,
1150 &r->num_attributes);
1156 case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1157 struct ldap_Result *r = &msg->r.AddResponse;
1158 msg->type = LDAP_TAG_AddResponse;
1159 asn1_start_tag(data, tag);
1160 ldap_decode_response(msg, data, r);
1165 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1166 struct ldap_DelRequest *r = &msg->r.DelRequest;
1169 msg->type = LDAP_TAG_DelRequest;
1170 asn1_start_tag(data,
1171 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
1172 len = asn1_tag_remaining(data);
1174 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1176 dn = talloc_array(msg, char, len+1);
1179 asn1_read(data, dn, len);
1186 case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1187 struct ldap_Result *r = &msg->r.DelResponse;
1188 msg->type = LDAP_TAG_DelResponse;
1189 asn1_start_tag(data, tag);
1190 ldap_decode_response(msg, data, r);
1195 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1196 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1197 msg->type = LDAP_TAG_ModifyDNRequest;
1198 asn1_start_tag(data,
1199 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
1200 asn1_read_OctetString_talloc(msg, data, &r->dn);
1201 asn1_read_OctetString_talloc(msg, data, &r->newrdn);
1202 asn1_read_BOOLEAN(data, &r->deleteolddn);
1203 r->newsuperior = NULL;
1204 if (asn1_tag_remaining(data) > 0) {
1207 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1208 len = asn1_tag_remaining(data);
1210 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1212 newsup = talloc_array(msg, char, len+1);
1213 if (newsup == NULL) {
1214 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1216 asn1_read(data, newsup, len);
1218 r->newsuperior = newsup;
1225 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1226 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1227 msg->type = LDAP_TAG_ModifyDNResponse;
1228 asn1_start_tag(data, tag);
1229 ldap_decode_response(msg, data, r);
1234 case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1235 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1236 msg->type = LDAP_TAG_CompareRequest;
1237 asn1_start_tag(data,
1238 ASN1_APPLICATION(LDAP_TAG_CompareRequest));
1239 asn1_read_OctetString_talloc(msg, data, &r->dn);
1240 asn1_start_tag(data, ASN1_SEQUENCE(0));
1241 asn1_read_OctetString_talloc(msg, data, &r->attribute);
1242 asn1_read_OctetString(data, msg, &r->value);
1243 if (r->value.data) {
1244 talloc_steal(msg, r->value.data);
1251 case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1252 struct ldap_Result *r = &msg->r.CompareResponse;
1253 msg->type = LDAP_TAG_CompareResponse;
1254 asn1_start_tag(data, tag);
1255 ldap_decode_response(msg, data, r);
1260 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1261 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1262 msg->type = LDAP_TAG_AbandonRequest;
1263 asn1_start_tag(data, tag);
1264 asn1_read_implicit_Integer(data, &r->messageid);
1269 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1270 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1271 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1273 msg->type = LDAP_TAG_ExtendedRequest;
1274 asn1_start_tag(data,tag);
1275 if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
1276 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1278 r->oid = blob2string_talloc(msg, tmp_blob);
1279 data_blob_free(&tmp_blob);
1281 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1284 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1285 asn1_read_ContextSimple(data, 1, &tmp_blob);
1286 r->value = talloc(msg, DATA_BLOB);
1288 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1290 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1291 data_blob_free(&tmp_blob);
1300 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1301 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1302 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1304 msg->type = LDAP_TAG_ExtendedResponse;
1305 asn1_start_tag(data, tag);
1306 ldap_decode_response(msg, data, &r->response);
1308 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(10))) {
1309 asn1_read_ContextSimple(data, 1, &tmp_blob);
1310 r->oid = blob2string_talloc(msg, tmp_blob);
1311 data_blob_free(&tmp_blob);
1313 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1319 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(11))) {
1320 asn1_read_ContextSimple(data, 1, &tmp_blob);
1321 r->value = talloc(msg, DATA_BLOB);
1323 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1325 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1326 data_blob_free(&tmp_blob);
1335 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1338 msg->controls = NULL;
1339 msg->controls_decoded = NULL;
1341 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1343 struct ldb_control **ctrl = NULL;
1344 bool *decoded = NULL;
1346 asn1_start_tag(data, ASN1_CONTEXT(0));
1348 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1350 /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1352 ctrl = talloc_realloc(msg, ctrl, struct ldb_control *, i+2);
1354 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1357 decoded = talloc_realloc(msg, decoded, bool, i+1);
1359 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1362 ctrl[i] = talloc(ctrl, struct ldb_control);
1364 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1367 if (!ldap_decode_control_wrapper(ctrl, data, ctrl[i], &value)) {
1368 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1371 if (!ldap_decode_control_value(ctrl, value, ctrl[i])) {
1372 if (ctrl[i]->critical) {
1373 ctrl[i]->data = NULL;
1377 talloc_free(ctrl[i]);
1390 msg->controls = ctrl;
1391 msg->controls_decoded = decoded;
1397 if ((data->has_error) || (data->nesting != NULL)) {
1398 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1400 return NT_STATUS_OK;
1405 return NT_STATUS_OK if a blob has enough bytes in it to be a full
1406 ldap packet. Set packet_size if true.
1408 NTSTATUS ldap_full_packet(void *private_data, DATA_BLOB blob, size_t *packet_size)
1410 return asn1_full_tag(blob, ASN1_SEQUENCE(0), packet_size);