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 2 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, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #include "system/iconv.h"
28 #include "libcli/util/asn_1.h"
29 #include "libcli/ldap/ldap.h"
32 static BOOL ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree)
36 switch (tree->operation) {
39 asn1_push_tag(data, ASN1_CONTEXT(tree->operation==LDB_OP_AND?0:1));
40 for (i=0; i<tree->u.list.num_elements; i++) {
41 if (!ldap_push_filter(data, tree->u.list.elements[i])) {
49 asn1_push_tag(data, ASN1_CONTEXT(2));
50 if (!ldap_push_filter(data, tree->u.isnot.child)) {
58 asn1_push_tag(data, ASN1_CONTEXT(3));
59 asn1_write_OctetString(data, tree->u.equality.attr,
60 strlen(tree->u.equality.attr));
61 asn1_write_OctetString(data, tree->u.equality.value.data,
62 tree->u.equality.value.length);
66 case LDB_OP_SUBSTRING:
68 SubstringFilter ::= SEQUENCE {
69 type AttributeDescription,
70 -- at least one must be present
71 substrings SEQUENCE OF CHOICE {
72 initial [0] LDAPString,
74 final [2] LDAPString } }
76 asn1_push_tag(data, ASN1_CONTEXT(4));
77 asn1_write_OctetString(data, tree->u.substring.attr, strlen(tree->u.substring.attr));
78 asn1_push_tag(data, ASN1_SEQUENCE(0));
80 if ( ! tree->u.substring.start_with_wildcard) {
81 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
82 asn1_write_LDAPString(data, (char *)tree->u.substring.chunks[i]->data);
86 while (tree->u.substring.chunks[i]) {
89 if (( ! tree->u.substring.chunks[i + 1]) &&
90 (tree->u.substring.end_with_wildcard == 0)) {
95 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(ctx));
96 asn1_write_LDAPString(data, (char *)tree->u.substring.chunks[i]->data);
105 /* greaterOrEqual test */
106 asn1_push_tag(data, ASN1_CONTEXT(5));
107 asn1_write_OctetString(data, tree->u.comparison.attr,
108 strlen(tree->u.comparison.attr));
109 asn1_write_OctetString(data, tree->u.comparison.value.data,
110 tree->u.comparison.value.length);
115 /* lessOrEqual test */
116 asn1_push_tag(data, ASN1_CONTEXT(6));
117 asn1_write_OctetString(data, tree->u.comparison.attr,
118 strlen(tree->u.comparison.attr));
119 asn1_write_OctetString(data, tree->u.comparison.value.data,
120 tree->u.comparison.value.length);
126 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(7));
127 asn1_write_LDAPString(data, tree->u.present.attr);
129 return !data->has_error;
133 asn1_push_tag(data, ASN1_CONTEXT(8));
134 asn1_write_OctetString(data, tree->u.comparison.attr,
135 strlen(tree->u.comparison.attr));
136 asn1_write_OctetString(data, tree->u.comparison.value.data,
137 tree->u.comparison.value.length);
141 case LDB_OP_EXTENDED:
143 MatchingRuleAssertion ::= SEQUENCE {
144 matchingRule [1] MatchingRuleID OPTIONAL,
145 type [2] AttributeDescription OPTIONAL,
146 matchValue [3] AssertionValue,
147 dnAttributes [4] BOOLEAN DEFAULT FALSE
150 asn1_push_tag(data, ASN1_CONTEXT(9));
151 if (tree->u.extended.rule_id) {
152 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1));
153 asn1_write_LDAPString(data, tree->u.extended.rule_id);
156 if (tree->u.extended.attr) {
157 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(2));
158 asn1_write_LDAPString(data, tree->u.extended.attr);
161 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(3));
162 asn1_write_LDAPString(data, (char *)tree->u.extended.value.data);
164 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(4));
165 asn1_write_uint8(data, tree->u.extended.dnAttributes);
173 return !data->has_error;
176 static void ldap_encode_response(struct asn1_data *data, struct ldap_Result *result)
178 asn1_write_enumerated(data, result->resultcode);
179 asn1_write_OctetString(data, result->dn,
180 (result->dn) ? strlen(result->dn) : 0);
181 asn1_write_OctetString(data, result->errormessage,
182 (result->errormessage) ?
183 strlen(result->errormessage) : 0);
184 if (result->referral) {
185 asn1_push_tag(data, ASN1_CONTEXT(3));
186 asn1_write_OctetString(data, result->referral,
187 strlen(result->referral));
192 BOOL ldap_encode(struct ldap_message *msg, DATA_BLOB *result, TALLOC_CTX *mem_ctx)
194 struct asn1_data data;
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_size(mem_ctx, 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, &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) + 1;
554 chunks[chunk_num + 1] = NULL;
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, &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, &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, &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, &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, &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, &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, &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, &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, &attr);
837 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(3));
838 asn1_read_LDAPString(data, &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, &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 BOOL ldap_decode(struct asn1_data *data, struct ldap_message *msg)
933 asn1_start_tag(data, ASN1_SEQUENCE(0));
934 asn1_read_Integer(data, &msg->messageid);
936 if (!asn1_peek_uint8(data, &tag))
941 case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
942 struct ldap_BindRequest *r = &msg->r.BindRequest;
943 msg->type = LDAP_TAG_BindRequest;
944 asn1_start_tag(data, tag);
945 asn1_read_Integer(data, &r->version);
946 asn1_read_OctetString_talloc(msg, data, &r->dn);
947 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
949 r->creds.password = "";
950 r->mechanism = LDAP_AUTH_MECH_SIMPLE;
951 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
952 pwlen = asn1_tag_remaining(data);
954 char *pw = talloc_size(msg, pwlen+1);
955 asn1_read(data, pw, pwlen);
957 r->creds.password = pw;
960 } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
961 asn1_start_tag(data, ASN1_CONTEXT(3));
962 r->mechanism = LDAP_AUTH_MECH_SASL;
963 asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism);
964 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) { /* optional */
965 DATA_BLOB tmp_blob = data_blob(NULL, 0);
966 asn1_read_OctetString(data, &tmp_blob);
967 r->creds.SASL.secblob = talloc(msg, DATA_BLOB);
968 if (!r->creds.SASL.secblob) {
971 *r->creds.SASL.secblob = data_blob_talloc(r->creds.SASL.secblob,
972 tmp_blob.data, tmp_blob.length);
973 data_blob_free(&tmp_blob);
975 r->creds.SASL.secblob = NULL;
983 case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
984 struct ldap_BindResponse *r = &msg->r.BindResponse;
985 msg->type = LDAP_TAG_BindResponse;
986 asn1_start_tag(data, tag);
987 ldap_decode_response(msg, data, &r->response);
988 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
989 DATA_BLOB tmp_blob = data_blob(NULL, 0);
990 asn1_read_ContextSimple(data, 7, &tmp_blob);
991 r->SASL.secblob = talloc(msg, DATA_BLOB);
992 if (!r->SASL.secblob) {
995 *r->SASL.secblob = data_blob_talloc(r->SASL.secblob,
996 tmp_blob.data, tmp_blob.length);
997 data_blob_free(&tmp_blob);
999 r->SASL.secblob = NULL;
1005 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
1006 msg->type = LDAP_TAG_UnbindRequest;
1007 asn1_start_tag(data, tag);
1012 case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
1013 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
1014 msg->type = LDAP_TAG_SearchRequest;
1015 asn1_start_tag(data, tag);
1016 asn1_read_OctetString_talloc(msg, data, &r->basedn);
1017 asn1_read_enumerated(data, (int *)&(r->scope));
1018 asn1_read_enumerated(data, (int *)&(r->deref));
1019 asn1_read_Integer(data, &r->sizelimit);
1020 asn1_read_Integer(data, &r->timelimit);
1021 asn1_read_BOOLEAN(data, &r->attributesonly);
1023 r->tree = ldap_decode_filter_tree(msg, data);
1024 if (r->tree == NULL) {
1028 asn1_start_tag(data, ASN1_SEQUENCE(0));
1030 r->num_attributes = 0;
1031 r->attributes = NULL;
1033 while (asn1_tag_remaining(data) > 0) {
1035 if (!asn1_read_OctetString_talloc(msg, data,
1038 if (!add_string_to_array(msg, attr,
1040 &r->num_attributes))
1049 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1050 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1051 msg->type = LDAP_TAG_SearchResultEntry;
1052 r->attributes = NULL;
1053 r->num_attributes = 0;
1054 asn1_start_tag(data, tag);
1055 asn1_read_OctetString_talloc(msg, data, &r->dn);
1056 ldap_decode_attribs(msg, data, &r->attributes,
1057 &r->num_attributes);
1062 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1063 struct ldap_Result *r = &msg->r.SearchResultDone;
1064 msg->type = LDAP_TAG_SearchResultDone;
1065 asn1_start_tag(data, tag);
1066 ldap_decode_response(msg, data, r);
1071 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1072 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
1073 msg->type = LDAP_TAG_SearchResultReference;
1074 asn1_start_tag(data, tag);
1075 asn1_read_OctetString_talloc(msg, data, &r->referral);
1080 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1081 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1082 msg->type = LDAP_TAG_ModifyRequest;
1083 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
1084 asn1_read_OctetString_talloc(msg, data, &r->dn);
1085 asn1_start_tag(data, ASN1_SEQUENCE(0));
1090 while (asn1_tag_remaining(data) > 0) {
1091 struct ldap_mod mod;
1094 asn1_start_tag(data, ASN1_SEQUENCE(0));
1095 asn1_read_enumerated(data, &v);
1097 ldap_decode_attrib(msg, data, &mod.attrib);
1099 if (!add_mod_to_array_talloc(msg, &mod,
1100 &r->mods, &r->num_mods))
1109 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1110 struct ldap_Result *r = &msg->r.ModifyResponse;
1111 msg->type = LDAP_TAG_ModifyResponse;
1112 asn1_start_tag(data, tag);
1113 ldap_decode_response(msg, data, r);
1118 case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1119 struct ldap_AddRequest *r = &msg->r.AddRequest;
1120 msg->type = LDAP_TAG_AddRequest;
1121 asn1_start_tag(data, tag);
1122 asn1_read_OctetString_talloc(msg, data, &r->dn);
1124 r->attributes = NULL;
1125 r->num_attributes = 0;
1126 ldap_decode_attribs(msg, data, &r->attributes,
1127 &r->num_attributes);
1133 case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1134 struct ldap_Result *r = &msg->r.AddResponse;
1135 msg->type = LDAP_TAG_AddResponse;
1136 asn1_start_tag(data, tag);
1137 ldap_decode_response(msg, data, r);
1142 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1143 struct ldap_DelRequest *r = &msg->r.DelRequest;
1146 msg->type = LDAP_TAG_DelRequest;
1147 asn1_start_tag(data,
1148 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
1149 len = asn1_tag_remaining(data);
1150 dn = talloc_size(msg, len+1);
1153 asn1_read(data, dn, len);
1160 case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1161 struct ldap_Result *r = &msg->r.DelResponse;
1162 msg->type = LDAP_TAG_DelResponse;
1163 asn1_start_tag(data, tag);
1164 ldap_decode_response(msg, data, r);
1169 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1170 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1171 msg->type = LDAP_TAG_ModifyDNRequest;
1172 asn1_start_tag(data,
1173 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
1174 asn1_read_OctetString_talloc(msg, data, &r->dn);
1175 asn1_read_OctetString_talloc(msg, data, &r->newrdn);
1176 asn1_read_BOOLEAN(data, &r->deleteolddn);
1177 r->newsuperior = NULL;
1178 if (asn1_tag_remaining(data) > 0) {
1181 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1182 len = asn1_tag_remaining(data);
1183 newsup = talloc_size(msg, len+1);
1186 asn1_read(data, newsup, len);
1188 r->newsuperior = newsup;
1195 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1196 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1197 msg->type = LDAP_TAG_ModifyDNResponse;
1198 asn1_start_tag(data, tag);
1199 ldap_decode_response(msg, data, r);
1204 case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1205 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1206 msg->type = LDAP_TAG_CompareRequest;
1207 asn1_start_tag(data,
1208 ASN1_APPLICATION(LDAP_TAG_CompareRequest));
1209 asn1_read_OctetString_talloc(msg, data, &r->dn);
1210 asn1_start_tag(data, ASN1_SEQUENCE(0));
1211 asn1_read_OctetString_talloc(msg, data, &r->attribute);
1212 asn1_read_OctetString(data, &r->value);
1213 if (r->value.data) {
1214 talloc_steal(msg, r->value.data);
1221 case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1222 struct ldap_Result *r = &msg->r.CompareResponse;
1223 msg->type = LDAP_TAG_CompareResponse;
1224 asn1_start_tag(data, tag);
1225 ldap_decode_response(msg, data, r);
1230 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1231 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1232 msg->type = LDAP_TAG_AbandonRequest;
1233 asn1_start_tag(data, tag);
1234 asn1_read_implicit_Integer(data, &r->messageid);
1239 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1240 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1241 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1243 msg->type = LDAP_TAG_ExtendedRequest;
1244 asn1_start_tag(data,tag);
1245 if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
1248 r->oid = blob2string_talloc(msg, tmp_blob);
1249 data_blob_free(&tmp_blob);
1254 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1255 asn1_read_ContextSimple(data, 1, &tmp_blob);
1256 r->value = talloc(msg, DATA_BLOB);
1260 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1261 data_blob_free(&tmp_blob);
1270 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1271 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1272 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1274 msg->type = LDAP_TAG_ExtendedResponse;
1275 asn1_start_tag(data, tag);
1276 ldap_decode_response(msg, data, &r->response);
1278 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(10))) {
1279 asn1_read_ContextSimple(data, 1, &tmp_blob);
1280 r->oid = blob2string_talloc(msg, tmp_blob);
1281 data_blob_free(&tmp_blob);
1289 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(11))) {
1290 asn1_read_ContextSimple(data, 1, &tmp_blob);
1291 r->value = talloc(msg, DATA_BLOB);
1295 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1296 data_blob_free(&tmp_blob);
1308 msg->controls = NULL;
1310 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1312 struct ldb_control **ctrl = NULL;
1314 asn1_start_tag(data, ASN1_CONTEXT(0));
1316 for (i=0; asn1_peek_tag(data, ASN1_SEQUENCE(0)); i++) {
1317 /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1319 ctrl = talloc_realloc(msg, ctrl, struct ldb_control *, i+2);
1324 ctrl[i] = talloc(ctrl, struct ldb_control);
1329 if (!ldap_decode_control(ctrl, data, ctrl[i])) {
1337 msg->controls = ctrl;
1343 return ((!data->has_error) && (data->nesting == NULL));
1348 return NT_STATUS_OK if a blob has enough bytes in it to be a full
1349 ldap packet. Set packet_size if true.
1351 NTSTATUS ldap_full_packet(void *private_data, DATA_BLOB blob, size_t *packet_size)
1353 return asn1_full_tag(blob, ASN1_SEQUENCE(0), packet_size);