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"
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, 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, 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, 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)
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 asn1_write_OctetString(&data, r->creds.SASL.secblob.data,
223 r->creds.SASL.secblob.length);
233 case LDAP_TAG_BindResponse: {
234 struct ldap_BindResponse *r = &msg->r.BindResponse;
235 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
236 ldap_encode_response(&data, &r->response);
237 asn1_write_ContextSimple(&data, 7, &r->SASL.secblob);
241 case LDAP_TAG_UnbindRequest: {
242 /* struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
245 case LDAP_TAG_SearchRequest: {
246 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
247 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
248 asn1_write_OctetString(&data, r->basedn, strlen(r->basedn));
249 asn1_write_enumerated(&data, r->scope);
250 asn1_write_enumerated(&data, r->deref);
251 asn1_write_Integer(&data, r->sizelimit);
252 asn1_write_Integer(&data, r->timelimit);
253 asn1_write_BOOLEAN(&data, r->attributesonly);
255 if (!ldap_push_filter(&data, r->tree)) {
259 asn1_push_tag(&data, ASN1_SEQUENCE(0));
260 for (i=0; i<r->num_attributes; i++) {
261 asn1_write_OctetString(&data, r->attributes[i],
262 strlen(r->attributes[i]));
268 case LDAP_TAG_SearchResultEntry: {
269 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
270 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
271 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
272 asn1_push_tag(&data, ASN1_SEQUENCE(0));
273 for (i=0; i<r->num_attributes; i++) {
274 struct ldb_message_element *attr = &r->attributes[i];
275 asn1_push_tag(&data, ASN1_SEQUENCE(0));
276 asn1_write_OctetString(&data, attr->name,
278 asn1_push_tag(&data, ASN1_SEQUENCE(1));
279 for (j=0; j<attr->num_values; j++) {
280 asn1_write_OctetString(&data,
281 attr->values[j].data,
282 attr->values[j].length);
291 case LDAP_TAG_SearchResultDone: {
292 struct ldap_Result *r = &msg->r.SearchResultDone;
293 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
294 ldap_encode_response(&data, r);
298 case LDAP_TAG_ModifyRequest: {
299 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
300 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
301 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
302 asn1_push_tag(&data, ASN1_SEQUENCE(0));
304 for (i=0; i<r->num_mods; i++) {
305 struct ldb_message_element *attrib = &r->mods[i].attrib;
306 asn1_push_tag(&data, ASN1_SEQUENCE(0));
307 asn1_write_enumerated(&data, r->mods[i].type);
308 asn1_push_tag(&data, ASN1_SEQUENCE(0));
309 asn1_write_OctetString(&data, attrib->name,
310 strlen(attrib->name));
311 asn1_push_tag(&data, ASN1_SET);
312 for (j=0; j<attrib->num_values; j++) {
313 asn1_write_OctetString(&data,
314 attrib->values[j].data,
315 attrib->values[j].length);
327 case LDAP_TAG_ModifyResponse: {
328 struct ldap_Result *r = &msg->r.ModifyResponse;
329 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
330 ldap_encode_response(&data, r);
334 case LDAP_TAG_AddRequest: {
335 struct ldap_AddRequest *r = &msg->r.AddRequest;
336 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
337 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
338 asn1_push_tag(&data, ASN1_SEQUENCE(0));
340 for (i=0; i<r->num_attributes; i++) {
341 struct ldb_message_element *attrib = &r->attributes[i];
342 asn1_push_tag(&data, ASN1_SEQUENCE(0));
343 asn1_write_OctetString(&data, attrib->name,
344 strlen(attrib->name));
345 asn1_push_tag(&data, ASN1_SET);
346 for (j=0; j<r->attributes[i].num_values; j++) {
347 asn1_write_OctetString(&data,
348 attrib->values[j].data,
349 attrib->values[j].length);
358 case LDAP_TAG_AddResponse: {
359 struct ldap_Result *r = &msg->r.AddResponse;
360 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
361 ldap_encode_response(&data, r);
365 case LDAP_TAG_DelRequest: {
366 struct ldap_DelRequest *r = &msg->r.DelRequest;
367 asn1_push_tag(&data, ASN1_APPLICATION_SIMPLE(msg->type));
368 asn1_write(&data, r->dn, strlen(r->dn));
372 case LDAP_TAG_DelResponse: {
373 struct ldap_Result *r = &msg->r.DelResponse;
374 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
375 ldap_encode_response(&data, r);
379 case LDAP_TAG_ModifyDNRequest: {
380 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
381 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
382 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
383 asn1_write_OctetString(&data, r->newrdn, strlen(r->newrdn));
384 asn1_write_BOOLEAN(&data, r->deleteolddn);
385 if (r->newsuperior != NULL) {
386 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
387 asn1_write(&data, r->newsuperior,
388 strlen(r->newsuperior));
394 case LDAP_TAG_ModifyDNResponse: {
395 struct ldap_Result *r = &msg->r.ModifyDNResponse;
396 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
397 ldap_encode_response(&data, r);
401 case LDAP_TAG_CompareRequest: {
402 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
403 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
404 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
405 asn1_push_tag(&data, ASN1_SEQUENCE(0));
406 asn1_write_OctetString(&data, r->attribute,
407 strlen(r->attribute));
408 asn1_write_OctetString(&data, r->value.data,
414 case LDAP_TAG_CompareResponse: {
415 struct ldap_Result *r = &msg->r.ModifyDNResponse;
416 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
417 ldap_encode_response(&data, r);
421 case LDAP_TAG_AbandonRequest: {
422 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
423 asn1_push_tag(&data, ASN1_APPLICATION_SIMPLE(msg->type));
424 asn1_write_implicit_Integer(&data, r->messageid);
428 case LDAP_TAG_SearchResultReference: {
429 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
430 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
431 asn1_write_OctetString(&data, r->referral, strlen(r->referral));
435 case LDAP_TAG_ExtendedRequest: {
436 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
437 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
438 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
439 asn1_write(&data, r->oid, strlen(r->oid));
441 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(1));
442 asn1_write(&data, r->value.data, r->value.length);
447 case LDAP_TAG_ExtendedResponse: {
448 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
449 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
450 ldap_encode_response(&data, &r->response);
460 if (data.has_error) {
465 *result = data_blob(data.data, data.length);
470 static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
473 char *result = talloc_size(mem_ctx, blob.length+1);
474 memcpy(result, blob.data, blob.length);
475 result[blob.length] = '\0';
479 static BOOL asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
480 struct asn1_data *data,
484 if (!asn1_read_OctetString(data, &string))
486 *result = blob2string_talloc(mem_ctx, string);
487 data_blob_free(&string);
491 static void ldap_decode_response(TALLOC_CTX *mem_ctx,
492 struct asn1_data *data,
493 struct ldap_Result *result)
495 asn1_read_enumerated(data, &result->resultcode);
496 asn1_read_OctetString_talloc(mem_ctx, data, &result->dn);
497 asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage);
498 if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
499 asn1_start_tag(data, ASN1_CONTEXT(3));
500 asn1_read_OctetString_talloc(mem_ctx, data, &result->referral);
503 result->referral = NULL;
507 static struct ldb_val **ldap_decode_substring(TALLOC_CTX *mem_ctx, struct ldb_val **chunks, int chunk_num, char *value)
510 chunks = talloc_realloc(mem_ctx, chunks, struct ldb_val *, chunk_num + 2);
511 if (chunks == NULL) {
515 chunks[chunk_num] = talloc(mem_ctx, struct ldb_val);
516 if (chunks[chunk_num] == NULL) {
520 chunks[chunk_num]->data = talloc_strdup(mem_ctx, value);
521 if (chunks[chunk_num]->data == NULL) {
524 chunks[chunk_num]->length = strlen(value) + 1;
526 chunks[chunk_num + 1] = NULL;
533 parse the ASN.1 formatted search string into a ldb_parse_tree
535 static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
536 struct asn1_data *data)
539 struct ldb_parse_tree *ret;
541 if (!asn1_peek_uint8(data, &filter_tag)) {
545 filter_tag &= 0x1f; /* strip off the asn1 stuff */
547 ret = talloc(mem_ctx, struct ldb_parse_tree);
548 if (ret == NULL) return NULL;
553 /* AND or OR of one or more filters */
554 ret->operation = (filter_tag == 0)?LDB_OP_AND:LDB_OP_OR;
555 ret->u.list.num_elements = 0;
556 ret->u.list.elements = NULL;
558 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
562 while (asn1_tag_remaining(data) > 0) {
563 struct ldb_parse_tree *subtree;
564 subtree = ldap_decode_filter_tree(ret, data);
565 if (subtree == NULL) {
568 ret->u.list.elements =
569 talloc_realloc(ret, ret->u.list.elements,
570 struct ldb_parse_tree *,
571 ret->u.list.num_elements+1);
572 if (ret->u.list.elements == NULL) {
575 talloc_steal(ret->u.list.elements, subtree);
576 ret->u.list.elements[ret->u.list.num_elements] = subtree;
577 ret->u.list.num_elements++;
579 if (!asn1_end_tag(data)) {
585 /* 'not' operation */
586 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
590 ret->operation = LDB_OP_NOT;
591 ret->u.isnot.child = ldap_decode_filter_tree(ret, data);
592 if (ret->u.isnot.child == NULL) {
595 if (!asn1_end_tag(data)) {
605 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
606 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
607 asn1_read_OctetString(data, &value);
609 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
613 ret->operation = LDB_OP_EQUALITY;
614 ret->u.equality.attr = talloc_steal(ret, attrib);
615 ret->u.equality.value.data = talloc_steal(ret, value.data);
616 ret->u.equality.value.length = value.length;
626 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
629 if (!asn1_read_OctetString(data, &attr)) {
633 ret->operation = LDB_OP_SUBSTRING;
634 ret->u.substring.attr = talloc_memdup(ret, attr.data, attr.length + 1);
635 ret->u.substring.attr[attr.length] = '\0';
636 ret->u.substring.chunks = NULL;
637 ret->u.substring.start_with_wildcard = 1;
638 ret->u.substring.end_with_wildcard = 1;
640 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
644 while (asn1_tag_remaining(data)) {
645 asn1_peek_uint8(data, &subs_tag);
646 subs_tag &= 0x1f; /* strip off the asn1 stuff */
647 if (subs_tag > 2) goto failed;
649 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(subs_tag));
650 asn1_read_LDAPString(data, &value);
655 if (ret->u.substring.chunks != NULL) {
656 /* initial value found in the middle */
660 ret->u.substring.chunks = ldap_decode_substring(ret, NULL, 0, value);
661 if (ret->u.substring.chunks == NULL) {
665 ret->u.substring.start_with_wildcard = 0;
670 if (ret->u.substring.end_with_wildcard == 0) {
671 /* "any" value found after a "final" value */
675 ret->u.substring.chunks = ldap_decode_substring(ret,
676 ret->u.substring.chunks,
679 if (ret->u.substring.chunks == NULL) {
687 ret->u.substring.chunks = ldap_decode_substring(ret,
688 ret->u.substring.chunks,
691 if (ret->u.substring.chunks == NULL) {
695 ret->u.substring.end_with_wildcard = 0;
704 if (!asn1_end_tag(data)) { /* SEQUENCE */
708 if (!asn1_end_tag(data)) {
718 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
719 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
720 asn1_read_OctetString(data, &value);
722 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
726 ret->operation = LDB_OP_GREATER;
727 ret->u.comparison.attr = talloc_steal(ret, attrib);
728 ret->u.comparison.value.data = talloc_steal(ret, value.data);
729 ret->u.comparison.value.length = value.length;
737 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
738 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
739 asn1_read_OctetString(data, &value);
741 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
745 ret->operation = LDB_OP_LESS;
746 ret->u.comparison.attr = talloc_steal(ret, attrib);
747 ret->u.comparison.value.data = talloc_steal(ret, value.data);
748 ret->u.comparison.value.length = value.length;
752 /* Normal presence, "attribute=*" */
755 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(filter_tag))) {
758 if (!asn1_read_LDAPString(data, &attr)) {
762 ret->operation = LDB_OP_PRESENT;
763 ret->u.present.attr = talloc_steal(ret, attr);
765 if (!asn1_end_tag(data)) {
775 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
776 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
777 asn1_read_OctetString(data, &value);
779 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
783 ret->operation = LDB_OP_APPROX;
784 ret->u.comparison.attr = talloc_steal(ret, attrib);
785 ret->u.comparison.value.data = talloc_steal(ret, value.data);
786 ret->u.comparison.value.length = value.length;
790 char *oid = NULL, *attr = NULL, *value;
791 uint8_t dnAttributes;
792 /* an extended search */
793 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
797 /* FIXME: read carefully rfc2251.txt there are a number of 'MUST's
798 we need to check we properly implement --SSS */
799 /* either oid or type must be defined */
800 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
801 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(1));
802 asn1_read_LDAPString(data, &oid);
805 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(2))) { /* optional */
806 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(2));
807 asn1_read_LDAPString(data, &attr);
810 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(3));
811 asn1_read_LDAPString(data, &value);
813 /* dnAttributes is marked as BOOLEAN DEFAULT FALSE
814 it is not marked as OPTIONAL but openldap tools
815 do not set this unless it is to be set as TRUE
816 NOTE: openldap tools do not work with AD as it
817 seems that AD always requires the dnAttributes
818 boolean value to be set */
819 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(4))) {
820 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(4));
821 asn1_read_uint8(data, &dnAttributes);
826 if ((oid == NULL && attr == NULL) || (value == NULL)) {
831 ret->operation = LDB_OP_EXTENDED;
833 /* From the RFC2251: If the type field is
834 absent and matchingRule is present, the matchValue is compared
835 against all attributes in an entry which support that matchingRule
838 ret->u.extended.attr = talloc_steal(ret, attr);
840 ret->u.extended.attr = talloc_strdup(ret, "*");
842 ret->u.extended.rule_id = talloc_steal(ret, oid);
843 ret->u.extended.value.data = talloc_steal(ret, value);
844 ret->u.extended.value.length = strlen(value);
845 ret->u.extended.dnAttributes = dnAttributes;
847 ret->operation = LDB_OP_EQUALITY;
848 ret->u.equality.attr = talloc_steal(ret, attr);
849 ret->u.equality.value.data = talloc_steal(ret, value);
850 ret->u.equality.value.length = strlen(value);
852 if (!asn1_end_tag(data)) {
859 DEBUG(0,("Unsupported LDAP filter operation 0x%x\n", filter_tag));
871 static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
872 struct ldb_message_element *attrib)
874 asn1_start_tag(data, ASN1_SEQUENCE(0));
875 asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name);
876 asn1_start_tag(data, ASN1_SET);
877 while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
879 asn1_read_OctetString(data, &blob);
880 add_value_to_attrib(mem_ctx, &blob, attrib);
887 static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
888 struct ldb_message_element **attributes,
891 asn1_start_tag(data, ASN1_SEQUENCE(0));
892 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
893 struct ldb_message_element attrib;
895 ldap_decode_attrib(mem_ctx, data, &attrib);
896 add_attrib_to_array_talloc(mem_ctx, &attrib,
897 attributes, num_attributes);
902 BOOL ldap_decode(struct asn1_data *data, struct ldap_message *msg)
906 asn1_start_tag(data, ASN1_SEQUENCE(0));
907 asn1_read_Integer(data, &msg->messageid);
909 if (!asn1_peek_uint8(data, &tag))
914 case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
915 struct ldap_BindRequest *r = &msg->r.BindRequest;
916 msg->type = LDAP_TAG_BindRequest;
917 asn1_start_tag(data, tag);
918 asn1_read_Integer(data, &r->version);
919 asn1_read_OctetString_talloc(msg, data, &r->dn);
920 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
922 r->creds.password = "";
923 r->mechanism = LDAP_AUTH_MECH_SIMPLE;
924 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
925 pwlen = asn1_tag_remaining(data);
927 char *pw = talloc_size(msg, pwlen+1);
928 asn1_read(data, pw, pwlen);
930 r->creds.password = pw;
933 } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
934 asn1_start_tag(data, ASN1_CONTEXT(3));
935 r->mechanism = LDAP_AUTH_MECH_SASL;
936 asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism);
937 asn1_read_OctetString(data, &r->creds.SASL.secblob);
938 if (r->creds.SASL.secblob.data) {
939 talloc_steal(msg, r->creds.SASL.secblob.data);
947 case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
948 struct ldap_BindResponse *r = &msg->r.BindResponse;
949 msg->type = LDAP_TAG_BindResponse;
950 asn1_start_tag(data, tag);
951 ldap_decode_response(msg, data, &r->response);
952 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
953 DATA_BLOB tmp_blob = data_blob(NULL, 0);
954 asn1_read_ContextSimple(data, 7, &tmp_blob);
955 r->SASL.secblob = data_blob_talloc(msg, tmp_blob.data, tmp_blob.length);
956 data_blob_free(&tmp_blob);
958 r->SASL.secblob = data_blob(NULL, 0);
964 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
965 msg->type = LDAP_TAG_UnbindRequest;
966 asn1_start_tag(data, tag);
971 case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
972 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
973 msg->type = LDAP_TAG_SearchRequest;
974 asn1_start_tag(data, tag);
975 asn1_read_OctetString_talloc(msg, data, &r->basedn);
976 asn1_read_enumerated(data, (int *)&(r->scope));
977 asn1_read_enumerated(data, (int *)&(r->deref));
978 asn1_read_Integer(data, &r->sizelimit);
979 asn1_read_Integer(data, &r->timelimit);
980 asn1_read_BOOLEAN(data, &r->attributesonly);
982 r->tree = ldap_decode_filter_tree(msg, data);
983 if (r->tree == NULL) {
987 asn1_start_tag(data, ASN1_SEQUENCE(0));
989 r->num_attributes = 0;
990 r->attributes = NULL;
992 while (asn1_tag_remaining(data) > 0) {
994 if (!asn1_read_OctetString_talloc(msg, data,
997 if (!add_string_to_array(msg, attr,
1008 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1009 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1010 msg->type = LDAP_TAG_SearchResultEntry;
1011 r->attributes = NULL;
1012 r->num_attributes = 0;
1013 asn1_start_tag(data, tag);
1014 asn1_read_OctetString_talloc(msg, data, &r->dn);
1015 ldap_decode_attribs(msg, data, &r->attributes,
1016 &r->num_attributes);
1021 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1022 struct ldap_Result *r = &msg->r.SearchResultDone;
1023 msg->type = LDAP_TAG_SearchResultDone;
1024 asn1_start_tag(data, tag);
1025 ldap_decode_response(msg, data, r);
1030 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1031 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
1032 msg->type = LDAP_TAG_SearchResultReference;
1033 asn1_start_tag(data, tag);
1034 asn1_read_OctetString_talloc(msg, data, &r->referral);
1039 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1040 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1041 msg->type = LDAP_TAG_ModifyRequest;
1042 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
1043 asn1_read_OctetString_talloc(msg, data, &r->dn);
1044 asn1_start_tag(data, ASN1_SEQUENCE(0));
1049 while (asn1_tag_remaining(data) > 0) {
1050 struct ldap_mod mod;
1053 asn1_start_tag(data, ASN1_SEQUENCE(0));
1054 asn1_read_enumerated(data, &v);
1056 ldap_decode_attrib(msg, data, &mod.attrib);
1058 if (!add_mod_to_array_talloc(msg, &mod,
1059 &r->mods, &r->num_mods))
1068 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1069 struct ldap_Result *r = &msg->r.ModifyResponse;
1070 msg->type = LDAP_TAG_ModifyResponse;
1071 asn1_start_tag(data, tag);
1072 ldap_decode_response(msg, data, r);
1077 case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1078 struct ldap_AddRequest *r = &msg->r.AddRequest;
1079 msg->type = LDAP_TAG_AddRequest;
1080 asn1_start_tag(data, tag);
1081 asn1_read_OctetString_talloc(msg, data, &r->dn);
1083 r->attributes = NULL;
1084 r->num_attributes = 0;
1085 ldap_decode_attribs(msg, data, &r->attributes,
1086 &r->num_attributes);
1092 case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1093 struct ldap_Result *r = &msg->r.AddResponse;
1094 msg->type = LDAP_TAG_AddResponse;
1095 asn1_start_tag(data, tag);
1096 ldap_decode_response(msg, data, r);
1101 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1102 struct ldap_DelRequest *r = &msg->r.DelRequest;
1105 msg->type = LDAP_TAG_DelRequest;
1106 asn1_start_tag(data,
1107 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
1108 len = asn1_tag_remaining(data);
1109 dn = talloc_size(msg, len+1);
1112 asn1_read(data, dn, len);
1119 case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1120 struct ldap_Result *r = &msg->r.DelResponse;
1121 msg->type = LDAP_TAG_DelResponse;
1122 asn1_start_tag(data, tag);
1123 ldap_decode_response(msg, data, r);
1128 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1129 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1130 msg->type = LDAP_TAG_ModifyDNRequest;
1131 asn1_start_tag(data,
1132 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
1133 asn1_read_OctetString_talloc(msg, data, &r->dn);
1134 asn1_read_OctetString_talloc(msg, data, &r->newrdn);
1135 asn1_read_BOOLEAN(data, &r->deleteolddn);
1136 r->newsuperior = NULL;
1137 if (asn1_tag_remaining(data) > 0) {
1140 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1141 len = asn1_tag_remaining(data);
1142 newsup = talloc_size(msg, len+1);
1145 asn1_read(data, newsup, len);
1147 r->newsuperior = newsup;
1154 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1155 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1156 msg->type = LDAP_TAG_ModifyDNResponse;
1157 asn1_start_tag(data, tag);
1158 ldap_decode_response(msg, data, r);
1163 case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1164 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1165 msg->type = LDAP_TAG_CompareRequest;
1166 asn1_start_tag(data,
1167 ASN1_APPLICATION(LDAP_TAG_CompareRequest));
1168 asn1_read_OctetString_talloc(msg, data, &r->dn);
1169 asn1_start_tag(data, ASN1_SEQUENCE(0));
1170 asn1_read_OctetString_talloc(msg, data, &r->attribute);
1171 asn1_read_OctetString(data, &r->value);
1172 if (r->value.data) {
1173 talloc_steal(msg, r->value.data);
1180 case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1181 struct ldap_Result *r = &msg->r.CompareResponse;
1182 msg->type = LDAP_TAG_CompareResponse;
1183 asn1_start_tag(data, tag);
1184 ldap_decode_response(msg, data, r);
1189 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1190 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1191 msg->type = LDAP_TAG_AbandonRequest;
1192 asn1_start_tag(data, tag);
1193 asn1_read_implicit_Integer(data, &r->messageid);
1198 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1199 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1200 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1202 msg->type = LDAP_TAG_ExtendedRequest;
1203 asn1_start_tag(data,tag);
1204 if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
1207 r->oid = blob2string_talloc(msg, tmp_blob);
1208 data_blob_free(&tmp_blob);
1213 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1214 asn1_read_ContextSimple(data, 1, &tmp_blob);
1215 r->value = data_blob_talloc(msg, tmp_blob.data, tmp_blob.length);
1216 data_blob_free(&tmp_blob);
1218 r->value = data_blob(NULL, 0);
1225 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1226 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1227 msg->type = LDAP_TAG_ExtendedResponse;
1228 asn1_start_tag(data, tag);
1229 ldap_decode_response(msg, data, &r->response);
1230 /* I have to come across an operation that actually sends
1231 * something back to really see what's going on. The currently
1232 * needed pwdchange does not send anything back. */
1234 r->value.data = NULL;
1235 r->value.length = 0;
1243 msg->num_controls = 0;
1244 msg->controls = NULL;
1246 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1248 struct ldap_Control *ctrl = NULL;
1250 asn1_start_tag(data, ASN1_CONTEXT(0));
1252 for (i=0; asn1_peek_tag(data, ASN1_SEQUENCE(0)); i++) {
1253 asn1_start_tag(data, ASN1_SEQUENCE(0));
1255 ctrl = talloc_realloc(msg, ctrl, struct ldap_Control, i+1);
1260 ctrl[i].critical = False;
1261 ctrl[i].value = data_blob(NULL, 0);
1263 asn1_read_OctetString_talloc(ctrl, data, &ctrl[i].oid);
1265 if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
1266 asn1_read_BOOLEAN(data, &ctrl[i].critical);
1269 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
1270 asn1_read_OctetString(data, &ctrl[i].value);
1271 if (ctrl[i].value.data) {
1272 talloc_steal(msg, ctrl[i].value.data);
1278 msg->num_controls = i;
1279 msg->controls = ctrl;
1285 return ((!data->has_error) && (data->nesting == NULL));