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 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_talloc(mem_ctx, 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 = (uint8_t *)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_strndup(ret, (char *)attr.data, attr.length);
635 ret->u.substring.chunks = NULL;
636 ret->u.substring.start_with_wildcard = 1;
637 ret->u.substring.end_with_wildcard = 1;
639 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
643 while (asn1_tag_remaining(data)) {
644 asn1_peek_uint8(data, &subs_tag);
645 subs_tag &= 0x1f; /* strip off the asn1 stuff */
646 if (subs_tag > 2) goto failed;
648 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(subs_tag));
649 asn1_read_LDAPString(data, &value);
654 if (ret->u.substring.chunks != NULL) {
655 /* initial value found in the middle */
659 ret->u.substring.chunks = ldap_decode_substring(ret, NULL, 0, value);
660 if (ret->u.substring.chunks == NULL) {
664 ret->u.substring.start_with_wildcard = 0;
669 if (ret->u.substring.end_with_wildcard == 0) {
670 /* "any" value found after a "final" value */
674 ret->u.substring.chunks = ldap_decode_substring(ret,
675 ret->u.substring.chunks,
678 if (ret->u.substring.chunks == NULL) {
686 ret->u.substring.chunks = ldap_decode_substring(ret,
687 ret->u.substring.chunks,
690 if (ret->u.substring.chunks == NULL) {
694 ret->u.substring.end_with_wildcard = 0;
703 if (!asn1_end_tag(data)) { /* SEQUENCE */
707 if (!asn1_end_tag(data)) {
717 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
718 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
719 asn1_read_OctetString(data, &value);
721 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
725 ret->operation = LDB_OP_GREATER;
726 ret->u.comparison.attr = talloc_steal(ret, attrib);
727 ret->u.comparison.value.data = talloc_steal(ret, value.data);
728 ret->u.comparison.value.length = value.length;
736 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
737 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
738 asn1_read_OctetString(data, &value);
740 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
744 ret->operation = LDB_OP_LESS;
745 ret->u.comparison.attr = talloc_steal(ret, attrib);
746 ret->u.comparison.value.data = talloc_steal(ret, value.data);
747 ret->u.comparison.value.length = value.length;
751 /* Normal presence, "attribute=*" */
754 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(filter_tag))) {
757 if (!asn1_read_LDAPString(data, &attr)) {
761 ret->operation = LDB_OP_PRESENT;
762 ret->u.present.attr = talloc_steal(ret, attr);
764 if (!asn1_end_tag(data)) {
774 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
775 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
776 asn1_read_OctetString(data, &value);
778 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
782 ret->operation = LDB_OP_APPROX;
783 ret->u.comparison.attr = talloc_steal(ret, attrib);
784 ret->u.comparison.value.data = talloc_steal(ret, value.data);
785 ret->u.comparison.value.length = value.length;
789 char *oid = NULL, *attr = NULL, *value;
790 uint8_t dnAttributes;
791 /* an extended search */
792 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
796 /* FIXME: read carefully rfc2251.txt there are a number of 'MUST's
797 we need to check we properly implement --SSS */
798 /* either oid or type must be defined */
799 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
800 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(1));
801 asn1_read_LDAPString(data, &oid);
804 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(2))) { /* optional */
805 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(2));
806 asn1_read_LDAPString(data, &attr);
809 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(3));
810 asn1_read_LDAPString(data, &value);
812 /* dnAttributes is marked as BOOLEAN DEFAULT FALSE
813 it is not marked as OPTIONAL but openldap tools
814 do not set this unless it is to be set as TRUE
815 NOTE: openldap tools do not work with AD as it
816 seems that AD always requires the dnAttributes
817 boolean value to be set */
818 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(4))) {
819 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(4));
820 asn1_read_uint8(data, &dnAttributes);
825 if ((oid == NULL && attr == NULL) || (value == NULL)) {
830 ret->operation = LDB_OP_EXTENDED;
832 /* From the RFC2251: If the type field is
833 absent and matchingRule is present, the matchValue is compared
834 against all attributes in an entry which support that matchingRule
837 ret->u.extended.attr = talloc_steal(ret, attr);
839 ret->u.extended.attr = talloc_strdup(ret, "*");
841 ret->u.extended.rule_id = talloc_steal(ret, oid);
842 ret->u.extended.value.data = talloc_steal(ret, value);
843 ret->u.extended.value.length = strlen(value);
844 ret->u.extended.dnAttributes = dnAttributes;
846 ret->operation = LDB_OP_EQUALITY;
847 ret->u.equality.attr = talloc_steal(ret, attr);
848 ret->u.equality.value.data = talloc_steal(ret, value);
849 ret->u.equality.value.length = strlen(value);
851 if (!asn1_end_tag(data)) {
858 DEBUG(0,("Unsupported LDAP filter operation 0x%x\n", filter_tag));
870 static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
871 struct ldb_message_element *attrib)
873 asn1_start_tag(data, ASN1_SEQUENCE(0));
874 asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name);
875 asn1_start_tag(data, ASN1_SET);
876 while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
878 asn1_read_OctetString(data, &blob);
879 add_value_to_attrib(mem_ctx, &blob, attrib);
886 static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
887 struct ldb_message_element **attributes,
890 asn1_start_tag(data, ASN1_SEQUENCE(0));
891 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
892 struct ldb_message_element attrib;
894 ldap_decode_attrib(mem_ctx, data, &attrib);
895 add_attrib_to_array_talloc(mem_ctx, &attrib,
896 attributes, num_attributes);
901 BOOL ldap_decode(struct asn1_data *data, struct ldap_message *msg)
905 asn1_start_tag(data, ASN1_SEQUENCE(0));
906 asn1_read_Integer(data, &msg->messageid);
908 if (!asn1_peek_uint8(data, &tag))
913 case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
914 struct ldap_BindRequest *r = &msg->r.BindRequest;
915 msg->type = LDAP_TAG_BindRequest;
916 asn1_start_tag(data, tag);
917 asn1_read_Integer(data, &r->version);
918 asn1_read_OctetString_talloc(msg, data, &r->dn);
919 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
921 r->creds.password = "";
922 r->mechanism = LDAP_AUTH_MECH_SIMPLE;
923 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
924 pwlen = asn1_tag_remaining(data);
926 char *pw = talloc_size(msg, pwlen+1);
927 asn1_read(data, pw, pwlen);
929 r->creds.password = pw;
932 } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
933 asn1_start_tag(data, ASN1_CONTEXT(3));
934 r->mechanism = LDAP_AUTH_MECH_SASL;
935 asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism);
936 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) { /* optional */
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);
942 r->creds.SASL.secblob = data_blob(NULL, 0);
950 case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
951 struct ldap_BindResponse *r = &msg->r.BindResponse;
952 msg->type = LDAP_TAG_BindResponse;
953 asn1_start_tag(data, tag);
954 ldap_decode_response(msg, data, &r->response);
955 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
956 DATA_BLOB tmp_blob = data_blob(NULL, 0);
957 asn1_read_ContextSimple(data, 7, &tmp_blob);
958 r->SASL.secblob = data_blob_talloc(msg, tmp_blob.data, tmp_blob.length);
959 data_blob_free(&tmp_blob);
961 r->SASL.secblob = data_blob(NULL, 0);
967 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
968 msg->type = LDAP_TAG_UnbindRequest;
969 asn1_start_tag(data, tag);
974 case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
975 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
976 msg->type = LDAP_TAG_SearchRequest;
977 asn1_start_tag(data, tag);
978 asn1_read_OctetString_talloc(msg, data, &r->basedn);
979 asn1_read_enumerated(data, (int *)&(r->scope));
980 asn1_read_enumerated(data, (int *)&(r->deref));
981 asn1_read_Integer(data, &r->sizelimit);
982 asn1_read_Integer(data, &r->timelimit);
983 asn1_read_BOOLEAN(data, &r->attributesonly);
985 r->tree = ldap_decode_filter_tree(msg, data);
986 if (r->tree == NULL) {
990 asn1_start_tag(data, ASN1_SEQUENCE(0));
992 r->num_attributes = 0;
993 r->attributes = NULL;
995 while (asn1_tag_remaining(data) > 0) {
997 if (!asn1_read_OctetString_talloc(msg, data,
1000 if (!add_string_to_array(msg, attr,
1002 &r->num_attributes))
1011 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1012 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1013 msg->type = LDAP_TAG_SearchResultEntry;
1014 r->attributes = NULL;
1015 r->num_attributes = 0;
1016 asn1_start_tag(data, tag);
1017 asn1_read_OctetString_talloc(msg, data, &r->dn);
1018 ldap_decode_attribs(msg, data, &r->attributes,
1019 &r->num_attributes);
1024 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1025 struct ldap_Result *r = &msg->r.SearchResultDone;
1026 msg->type = LDAP_TAG_SearchResultDone;
1027 asn1_start_tag(data, tag);
1028 ldap_decode_response(msg, data, r);
1033 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1034 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
1035 msg->type = LDAP_TAG_SearchResultReference;
1036 asn1_start_tag(data, tag);
1037 asn1_read_OctetString_talloc(msg, data, &r->referral);
1042 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1043 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1044 msg->type = LDAP_TAG_ModifyRequest;
1045 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
1046 asn1_read_OctetString_talloc(msg, data, &r->dn);
1047 asn1_start_tag(data, ASN1_SEQUENCE(0));
1052 while (asn1_tag_remaining(data) > 0) {
1053 struct ldap_mod mod;
1056 asn1_start_tag(data, ASN1_SEQUENCE(0));
1057 asn1_read_enumerated(data, &v);
1059 ldap_decode_attrib(msg, data, &mod.attrib);
1061 if (!add_mod_to_array_talloc(msg, &mod,
1062 &r->mods, &r->num_mods))
1071 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1072 struct ldap_Result *r = &msg->r.ModifyResponse;
1073 msg->type = LDAP_TAG_ModifyResponse;
1074 asn1_start_tag(data, tag);
1075 ldap_decode_response(msg, data, r);
1080 case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1081 struct ldap_AddRequest *r = &msg->r.AddRequest;
1082 msg->type = LDAP_TAG_AddRequest;
1083 asn1_start_tag(data, tag);
1084 asn1_read_OctetString_talloc(msg, data, &r->dn);
1086 r->attributes = NULL;
1087 r->num_attributes = 0;
1088 ldap_decode_attribs(msg, data, &r->attributes,
1089 &r->num_attributes);
1095 case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1096 struct ldap_Result *r = &msg->r.AddResponse;
1097 msg->type = LDAP_TAG_AddResponse;
1098 asn1_start_tag(data, tag);
1099 ldap_decode_response(msg, data, r);
1104 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1105 struct ldap_DelRequest *r = &msg->r.DelRequest;
1108 msg->type = LDAP_TAG_DelRequest;
1109 asn1_start_tag(data,
1110 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
1111 len = asn1_tag_remaining(data);
1112 dn = talloc_size(msg, len+1);
1115 asn1_read(data, dn, len);
1122 case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1123 struct ldap_Result *r = &msg->r.DelResponse;
1124 msg->type = LDAP_TAG_DelResponse;
1125 asn1_start_tag(data, tag);
1126 ldap_decode_response(msg, data, r);
1131 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1132 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1133 msg->type = LDAP_TAG_ModifyDNRequest;
1134 asn1_start_tag(data,
1135 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
1136 asn1_read_OctetString_talloc(msg, data, &r->dn);
1137 asn1_read_OctetString_talloc(msg, data, &r->newrdn);
1138 asn1_read_BOOLEAN(data, &r->deleteolddn);
1139 r->newsuperior = NULL;
1140 if (asn1_tag_remaining(data) > 0) {
1143 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1144 len = asn1_tag_remaining(data);
1145 newsup = talloc_size(msg, len+1);
1148 asn1_read(data, newsup, len);
1150 r->newsuperior = newsup;
1157 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1158 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1159 msg->type = LDAP_TAG_ModifyDNResponse;
1160 asn1_start_tag(data, tag);
1161 ldap_decode_response(msg, data, r);
1166 case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1167 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1168 msg->type = LDAP_TAG_CompareRequest;
1169 asn1_start_tag(data,
1170 ASN1_APPLICATION(LDAP_TAG_CompareRequest));
1171 asn1_read_OctetString_talloc(msg, data, &r->dn);
1172 asn1_start_tag(data, ASN1_SEQUENCE(0));
1173 asn1_read_OctetString_talloc(msg, data, &r->attribute);
1174 asn1_read_OctetString(data, &r->value);
1175 if (r->value.data) {
1176 talloc_steal(msg, r->value.data);
1183 case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1184 struct ldap_Result *r = &msg->r.CompareResponse;
1185 msg->type = LDAP_TAG_CompareResponse;
1186 asn1_start_tag(data, tag);
1187 ldap_decode_response(msg, data, r);
1192 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1193 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1194 msg->type = LDAP_TAG_AbandonRequest;
1195 asn1_start_tag(data, tag);
1196 asn1_read_implicit_Integer(data, &r->messageid);
1201 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1202 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1203 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1205 msg->type = LDAP_TAG_ExtendedRequest;
1206 asn1_start_tag(data,tag);
1207 if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
1210 r->oid = blob2string_talloc(msg, tmp_blob);
1211 data_blob_free(&tmp_blob);
1216 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1217 asn1_read_ContextSimple(data, 1, &tmp_blob);
1218 r->value = data_blob_talloc(msg, tmp_blob.data, tmp_blob.length);
1219 data_blob_free(&tmp_blob);
1221 r->value = data_blob(NULL, 0);
1228 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1229 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1230 msg->type = LDAP_TAG_ExtendedResponse;
1231 asn1_start_tag(data, tag);
1232 ldap_decode_response(msg, data, &r->response);
1233 /* I have to come across an operation that actually sends
1234 * something back to really see what's going on. The currently
1235 * needed pwdchange does not send anything back. */
1237 r->value.data = NULL;
1238 r->value.length = 0;
1246 msg->num_controls = 0;
1247 msg->controls = NULL;
1249 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1251 struct ldap_Control *ctrl = NULL;
1253 asn1_start_tag(data, ASN1_CONTEXT(0));
1255 for (i=0; asn1_peek_tag(data, ASN1_SEQUENCE(0)); i++) {
1256 asn1_start_tag(data, ASN1_SEQUENCE(0));
1258 ctrl = talloc_realloc(msg, ctrl, struct ldap_Control, i+1);
1263 ctrl[i].critical = False;
1264 ctrl[i].value = data_blob(NULL, 0);
1266 asn1_read_OctetString_talloc(ctrl, data, &ctrl[i].oid);
1268 if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
1269 asn1_read_BOOLEAN(data, &ctrl[i].critical);
1272 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
1273 asn1_read_OctetString(data, &ctrl[i].value);
1274 if (ctrl[i].value.data) {
1275 talloc_steal(msg, ctrl[i].value.data);
1281 msg->num_controls = i;
1282 msg->controls = ctrl;
1288 return ((!data->has_error) && (data->nesting == NULL));
1293 return NT_STATUS_OK if a blob has enough bytes in it to be a full
1294 ldap packet. Set packet_size if true.
1296 NTSTATUS ldap_full_packet(void *private, DATA_BLOB blob, size_t *packet_size)
1298 return asn1_full_tag(blob, ASN1_SEQUENCE(0), packet_size);