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 /* The value of data indicates if this
223 * optional element exists at all. In SASL
224 * there is a difference between NULL and
225 * zero-legnth, but our APIs don't express it
227 if (r->creds.SASL.secblob.data) {
228 asn1_write_OctetString(&data, r->creds.SASL.secblob.data,
229 r->creds.SASL.secblob.length);
240 case LDAP_TAG_BindResponse: {
241 struct ldap_BindResponse *r = &msg->r.BindResponse;
242 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
243 ldap_encode_response(&data, &r->response);
244 /* The value of data indicates if this
245 * optional element exists at all. In SASL
246 * there is a difference between NULL and
247 * zero-legnth, but our APIs don't express it
249 if (r->SASL.secblob.data) {
250 asn1_write_ContextSimple(&data, 7, &r->SASL.secblob);
255 case LDAP_TAG_UnbindRequest: {
256 /* struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
259 case LDAP_TAG_SearchRequest: {
260 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
261 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
262 asn1_write_OctetString(&data, r->basedn, strlen(r->basedn));
263 asn1_write_enumerated(&data, r->scope);
264 asn1_write_enumerated(&data, r->deref);
265 asn1_write_Integer(&data, r->sizelimit);
266 asn1_write_Integer(&data, r->timelimit);
267 asn1_write_BOOLEAN(&data, r->attributesonly);
269 if (!ldap_push_filter(&data, r->tree)) {
273 asn1_push_tag(&data, ASN1_SEQUENCE(0));
274 for (i=0; i<r->num_attributes; i++) {
275 asn1_write_OctetString(&data, r->attributes[i],
276 strlen(r->attributes[i]));
282 case LDAP_TAG_SearchResultEntry: {
283 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
284 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
285 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
286 asn1_push_tag(&data, ASN1_SEQUENCE(0));
287 for (i=0; i<r->num_attributes; i++) {
288 struct ldb_message_element *attr = &r->attributes[i];
289 asn1_push_tag(&data, ASN1_SEQUENCE(0));
290 asn1_write_OctetString(&data, attr->name,
292 asn1_push_tag(&data, ASN1_SEQUENCE(1));
293 for (j=0; j<attr->num_values; j++) {
294 asn1_write_OctetString(&data,
295 attr->values[j].data,
296 attr->values[j].length);
305 case LDAP_TAG_SearchResultDone: {
306 struct ldap_Result *r = &msg->r.SearchResultDone;
307 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
308 ldap_encode_response(&data, r);
312 case LDAP_TAG_ModifyRequest: {
313 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
314 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
315 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
316 asn1_push_tag(&data, ASN1_SEQUENCE(0));
318 for (i=0; i<r->num_mods; i++) {
319 struct ldb_message_element *attrib = &r->mods[i].attrib;
320 asn1_push_tag(&data, ASN1_SEQUENCE(0));
321 asn1_write_enumerated(&data, r->mods[i].type);
322 asn1_push_tag(&data, ASN1_SEQUENCE(0));
323 asn1_write_OctetString(&data, attrib->name,
324 strlen(attrib->name));
325 asn1_push_tag(&data, ASN1_SET);
326 for (j=0; j<attrib->num_values; j++) {
327 asn1_write_OctetString(&data,
328 attrib->values[j].data,
329 attrib->values[j].length);
341 case LDAP_TAG_ModifyResponse: {
342 struct ldap_Result *r = &msg->r.ModifyResponse;
343 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
344 ldap_encode_response(&data, r);
348 case LDAP_TAG_AddRequest: {
349 struct ldap_AddRequest *r = &msg->r.AddRequest;
350 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
351 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
352 asn1_push_tag(&data, ASN1_SEQUENCE(0));
354 for (i=0; i<r->num_attributes; i++) {
355 struct ldb_message_element *attrib = &r->attributes[i];
356 asn1_push_tag(&data, ASN1_SEQUENCE(0));
357 asn1_write_OctetString(&data, attrib->name,
358 strlen(attrib->name));
359 asn1_push_tag(&data, ASN1_SET);
360 for (j=0; j<r->attributes[i].num_values; j++) {
361 asn1_write_OctetString(&data,
362 attrib->values[j].data,
363 attrib->values[j].length);
372 case LDAP_TAG_AddResponse: {
373 struct ldap_Result *r = &msg->r.AddResponse;
374 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
375 ldap_encode_response(&data, r);
379 case LDAP_TAG_DelRequest: {
380 struct ldap_DelRequest *r = &msg->r.DelRequest;
381 asn1_push_tag(&data, ASN1_APPLICATION_SIMPLE(msg->type));
382 asn1_write(&data, r->dn, strlen(r->dn));
386 case LDAP_TAG_DelResponse: {
387 struct ldap_Result *r = &msg->r.DelResponse;
388 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
389 ldap_encode_response(&data, r);
393 case LDAP_TAG_ModifyDNRequest: {
394 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
395 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
396 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
397 asn1_write_OctetString(&data, r->newrdn, strlen(r->newrdn));
398 asn1_write_BOOLEAN(&data, r->deleteolddn);
399 if (r->newsuperior != NULL) {
400 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
401 asn1_write(&data, r->newsuperior,
402 strlen(r->newsuperior));
408 case LDAP_TAG_ModifyDNResponse: {
409 struct ldap_Result *r = &msg->r.ModifyDNResponse;
410 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
411 ldap_encode_response(&data, r);
415 case LDAP_TAG_CompareRequest: {
416 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
417 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
418 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
419 asn1_push_tag(&data, ASN1_SEQUENCE(0));
420 asn1_write_OctetString(&data, r->attribute,
421 strlen(r->attribute));
422 asn1_write_OctetString(&data, r->value.data,
428 case LDAP_TAG_CompareResponse: {
429 struct ldap_Result *r = &msg->r.ModifyDNResponse;
430 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
431 ldap_encode_response(&data, r);
435 case LDAP_TAG_AbandonRequest: {
436 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
437 asn1_push_tag(&data, ASN1_APPLICATION_SIMPLE(msg->type));
438 asn1_write_implicit_Integer(&data, r->messageid);
442 case LDAP_TAG_SearchResultReference: {
443 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
444 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
445 asn1_write_OctetString(&data, r->referral, strlen(r->referral));
449 case LDAP_TAG_ExtendedRequest: {
450 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
451 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
452 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
453 asn1_write(&data, r->oid, strlen(r->oid));
455 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(1));
456 asn1_write(&data, r->value.data, r->value.length);
461 case LDAP_TAG_ExtendedResponse: {
462 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
463 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
464 ldap_encode_response(&data, &r->response);
472 if (msg->controls != NULL) {
473 asn1_push_tag(&data, ASN1_CONTEXT(0));
475 for (i = 0; msg->controls[i] != NULL; i++) {
476 if (!ldap_encode_control(mem_ctx, &data, msg->controls[i])) {
486 if (data.has_error) {
491 *result = data_blob_talloc(mem_ctx, data.data, data.length);
496 static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
499 char *result = talloc_size(mem_ctx, blob.length+1);
500 memcpy(result, blob.data, blob.length);
501 result[blob.length] = '\0';
505 static BOOL asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
506 struct asn1_data *data,
510 if (!asn1_read_OctetString(data, &string))
512 *result = blob2string_talloc(mem_ctx, string);
513 data_blob_free(&string);
517 static void ldap_decode_response(TALLOC_CTX *mem_ctx,
518 struct asn1_data *data,
519 struct ldap_Result *result)
521 asn1_read_enumerated(data, &result->resultcode);
522 asn1_read_OctetString_talloc(mem_ctx, data, &result->dn);
523 asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage);
524 if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
525 asn1_start_tag(data, ASN1_CONTEXT(3));
526 asn1_read_OctetString_talloc(mem_ctx, data, &result->referral);
529 result->referral = NULL;
533 static struct ldb_val **ldap_decode_substring(TALLOC_CTX *mem_ctx, struct ldb_val **chunks, int chunk_num, char *value)
536 chunks = talloc_realloc(mem_ctx, chunks, struct ldb_val *, chunk_num + 2);
537 if (chunks == NULL) {
541 chunks[chunk_num] = talloc(mem_ctx, struct ldb_val);
542 if (chunks[chunk_num] == NULL) {
546 chunks[chunk_num]->data = (uint8_t *)talloc_strdup(mem_ctx, value);
547 if (chunks[chunk_num]->data == NULL) {
550 chunks[chunk_num]->length = strlen(value) + 1;
552 chunks[chunk_num + 1] = NULL;
559 parse the ASN.1 formatted search string into a ldb_parse_tree
561 static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
562 struct asn1_data *data)
565 struct ldb_parse_tree *ret;
567 if (!asn1_peek_uint8(data, &filter_tag)) {
571 filter_tag &= 0x1f; /* strip off the asn1 stuff */
573 ret = talloc(mem_ctx, struct ldb_parse_tree);
574 if (ret == NULL) return NULL;
579 /* AND or OR of one or more filters */
580 ret->operation = (filter_tag == 0)?LDB_OP_AND:LDB_OP_OR;
581 ret->u.list.num_elements = 0;
582 ret->u.list.elements = NULL;
584 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
588 while (asn1_tag_remaining(data) > 0) {
589 struct ldb_parse_tree *subtree;
590 subtree = ldap_decode_filter_tree(ret, data);
591 if (subtree == NULL) {
594 ret->u.list.elements =
595 talloc_realloc(ret, ret->u.list.elements,
596 struct ldb_parse_tree *,
597 ret->u.list.num_elements+1);
598 if (ret->u.list.elements == NULL) {
601 talloc_steal(ret->u.list.elements, subtree);
602 ret->u.list.elements[ret->u.list.num_elements] = subtree;
603 ret->u.list.num_elements++;
605 if (!asn1_end_tag(data)) {
611 /* 'not' operation */
612 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
616 ret->operation = LDB_OP_NOT;
617 ret->u.isnot.child = ldap_decode_filter_tree(ret, data);
618 if (ret->u.isnot.child == NULL) {
621 if (!asn1_end_tag(data)) {
631 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
632 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
633 asn1_read_OctetString(data, &value);
635 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
639 ret->operation = LDB_OP_EQUALITY;
640 ret->u.equality.attr = talloc_steal(ret, attrib);
641 ret->u.equality.value.data = talloc_steal(ret, value.data);
642 ret->u.equality.value.length = value.length;
652 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
655 if (!asn1_read_OctetString(data, &attr)) {
659 ret->operation = LDB_OP_SUBSTRING;
660 ret->u.substring.attr = talloc_strndup(ret, (char *)attr.data, attr.length);
661 ret->u.substring.chunks = NULL;
662 ret->u.substring.start_with_wildcard = 1;
663 ret->u.substring.end_with_wildcard = 1;
665 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
669 while (asn1_tag_remaining(data)) {
670 asn1_peek_uint8(data, &subs_tag);
671 subs_tag &= 0x1f; /* strip off the asn1 stuff */
672 if (subs_tag > 2) goto failed;
674 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(subs_tag));
675 asn1_read_LDAPString(data, &value);
680 if (ret->u.substring.chunks != NULL) {
681 /* initial value found in the middle */
685 ret->u.substring.chunks = ldap_decode_substring(ret, NULL, 0, value);
686 if (ret->u.substring.chunks == NULL) {
690 ret->u.substring.start_with_wildcard = 0;
695 if (ret->u.substring.end_with_wildcard == 0) {
696 /* "any" value found after a "final" value */
700 ret->u.substring.chunks = ldap_decode_substring(ret,
701 ret->u.substring.chunks,
704 if (ret->u.substring.chunks == NULL) {
712 ret->u.substring.chunks = ldap_decode_substring(ret,
713 ret->u.substring.chunks,
716 if (ret->u.substring.chunks == NULL) {
720 ret->u.substring.end_with_wildcard = 0;
729 if (!asn1_end_tag(data)) { /* SEQUENCE */
733 if (!asn1_end_tag(data)) {
743 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
744 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
745 asn1_read_OctetString(data, &value);
747 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
751 ret->operation = LDB_OP_GREATER;
752 ret->u.comparison.attr = talloc_steal(ret, attrib);
753 ret->u.comparison.value.data = talloc_steal(ret, value.data);
754 ret->u.comparison.value.length = value.length;
762 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
763 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
764 asn1_read_OctetString(data, &value);
766 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
770 ret->operation = LDB_OP_LESS;
771 ret->u.comparison.attr = talloc_steal(ret, attrib);
772 ret->u.comparison.value.data = talloc_steal(ret, value.data);
773 ret->u.comparison.value.length = value.length;
777 /* Normal presence, "attribute=*" */
780 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(filter_tag))) {
783 if (!asn1_read_LDAPString(data, &attr)) {
787 ret->operation = LDB_OP_PRESENT;
788 ret->u.present.attr = talloc_steal(ret, attr);
790 if (!asn1_end_tag(data)) {
800 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
801 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
802 asn1_read_OctetString(data, &value);
804 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
808 ret->operation = LDB_OP_APPROX;
809 ret->u.comparison.attr = talloc_steal(ret, attrib);
810 ret->u.comparison.value.data = talloc_steal(ret, value.data);
811 ret->u.comparison.value.length = value.length;
815 char *oid = NULL, *attr = NULL, *value;
816 uint8_t dnAttributes;
817 /* an extended search */
818 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
822 /* FIXME: read carefully rfc2251.txt there are a number of 'MUST's
823 we need to check we properly implement --SSS */
824 /* either oid or type must be defined */
825 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
826 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(1));
827 asn1_read_LDAPString(data, &oid);
830 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(2))) { /* optional */
831 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(2));
832 asn1_read_LDAPString(data, &attr);
835 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(3));
836 asn1_read_LDAPString(data, &value);
838 /* dnAttributes is marked as BOOLEAN DEFAULT FALSE
839 it is not marked as OPTIONAL but openldap tools
840 do not set this unless it is to be set as TRUE
841 NOTE: openldap tools do not work with AD as it
842 seems that AD always requires the dnAttributes
843 boolean value to be set */
844 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(4))) {
845 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(4));
846 asn1_read_uint8(data, &dnAttributes);
851 if ((oid == NULL && attr == NULL) || (value == NULL)) {
856 ret->operation = LDB_OP_EXTENDED;
858 /* From the RFC2251: If the type field is
859 absent and matchingRule is present, the matchValue is compared
860 against all attributes in an entry which support that matchingRule
863 ret->u.extended.attr = talloc_steal(ret, attr);
865 ret->u.extended.attr = talloc_strdup(ret, "*");
867 ret->u.extended.rule_id = talloc_steal(ret, oid);
868 ret->u.extended.value.data = talloc_steal(ret, value);
869 ret->u.extended.value.length = strlen(value);
870 ret->u.extended.dnAttributes = dnAttributes;
872 ret->operation = LDB_OP_EQUALITY;
873 ret->u.equality.attr = talloc_steal(ret, attr);
874 ret->u.equality.value.data = talloc_steal(ret, value);
875 ret->u.equality.value.length = strlen(value);
877 if (!asn1_end_tag(data)) {
884 DEBUG(0,("Unsupported LDAP filter operation 0x%x\n", filter_tag));
896 static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
897 struct ldb_message_element *attrib)
899 asn1_start_tag(data, ASN1_SEQUENCE(0));
900 asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name);
901 asn1_start_tag(data, ASN1_SET);
902 while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
904 asn1_read_OctetString(data, &blob);
905 add_value_to_attrib(mem_ctx, &blob, attrib);
912 static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
913 struct ldb_message_element **attributes,
916 asn1_start_tag(data, ASN1_SEQUENCE(0));
917 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
918 struct ldb_message_element attrib;
920 ldap_decode_attrib(mem_ctx, data, &attrib);
921 add_attrib_to_array_talloc(mem_ctx, &attrib,
922 attributes, num_attributes);
927 BOOL ldap_decode(struct asn1_data *data, struct ldap_message *msg)
931 asn1_start_tag(data, ASN1_SEQUENCE(0));
932 asn1_read_Integer(data, &msg->messageid);
934 if (!asn1_peek_uint8(data, &tag))
939 case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
940 struct ldap_BindRequest *r = &msg->r.BindRequest;
941 msg->type = LDAP_TAG_BindRequest;
942 asn1_start_tag(data, tag);
943 asn1_read_Integer(data, &r->version);
944 asn1_read_OctetString_talloc(msg, data, &r->dn);
945 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
947 r->creds.password = "";
948 r->mechanism = LDAP_AUTH_MECH_SIMPLE;
949 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
950 pwlen = asn1_tag_remaining(data);
952 char *pw = talloc_size(msg, pwlen+1);
953 asn1_read(data, pw, pwlen);
955 r->creds.password = pw;
958 } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
959 asn1_start_tag(data, ASN1_CONTEXT(3));
960 r->mechanism = LDAP_AUTH_MECH_SASL;
961 asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism);
962 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) { /* optional */
963 asn1_read_OctetString(data, &r->creds.SASL.secblob);
964 if (r->creds.SASL.secblob.data) {
965 talloc_steal(msg, r->creds.SASL.secblob.data);
968 r->creds.SASL.secblob = data_blob(NULL, 0);
976 case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
977 struct ldap_BindResponse *r = &msg->r.BindResponse;
978 msg->type = LDAP_TAG_BindResponse;
979 asn1_start_tag(data, tag);
980 ldap_decode_response(msg, data, &r->response);
981 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
982 DATA_BLOB tmp_blob = data_blob(NULL, 0);
983 asn1_read_ContextSimple(data, 7, &tmp_blob);
984 r->SASL.secblob = data_blob_talloc(msg, tmp_blob.data, tmp_blob.length);
985 data_blob_free(&tmp_blob);
987 r->SASL.secblob = data_blob(NULL, 0);
993 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
994 msg->type = LDAP_TAG_UnbindRequest;
995 asn1_start_tag(data, tag);
1000 case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
1001 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
1002 msg->type = LDAP_TAG_SearchRequest;
1003 asn1_start_tag(data, tag);
1004 asn1_read_OctetString_talloc(msg, data, &r->basedn);
1005 asn1_read_enumerated(data, (int *)&(r->scope));
1006 asn1_read_enumerated(data, (int *)&(r->deref));
1007 asn1_read_Integer(data, &r->sizelimit);
1008 asn1_read_Integer(data, &r->timelimit);
1009 asn1_read_BOOLEAN(data, &r->attributesonly);
1011 r->tree = ldap_decode_filter_tree(msg, data);
1012 if (r->tree == NULL) {
1016 asn1_start_tag(data, ASN1_SEQUENCE(0));
1018 r->num_attributes = 0;
1019 r->attributes = NULL;
1021 while (asn1_tag_remaining(data) > 0) {
1023 if (!asn1_read_OctetString_talloc(msg, data,
1026 if (!add_string_to_array(msg, attr,
1028 &r->num_attributes))
1037 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1038 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1039 msg->type = LDAP_TAG_SearchResultEntry;
1040 r->attributes = NULL;
1041 r->num_attributes = 0;
1042 asn1_start_tag(data, tag);
1043 asn1_read_OctetString_talloc(msg, data, &r->dn);
1044 ldap_decode_attribs(msg, data, &r->attributes,
1045 &r->num_attributes);
1050 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1051 struct ldap_Result *r = &msg->r.SearchResultDone;
1052 msg->type = LDAP_TAG_SearchResultDone;
1053 asn1_start_tag(data, tag);
1054 ldap_decode_response(msg, data, r);
1059 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1060 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
1061 msg->type = LDAP_TAG_SearchResultReference;
1062 asn1_start_tag(data, tag);
1063 asn1_read_OctetString_talloc(msg, data, &r->referral);
1068 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1069 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1070 msg->type = LDAP_TAG_ModifyRequest;
1071 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
1072 asn1_read_OctetString_talloc(msg, data, &r->dn);
1073 asn1_start_tag(data, ASN1_SEQUENCE(0));
1078 while (asn1_tag_remaining(data) > 0) {
1079 struct ldap_mod mod;
1082 asn1_start_tag(data, ASN1_SEQUENCE(0));
1083 asn1_read_enumerated(data, &v);
1085 ldap_decode_attrib(msg, data, &mod.attrib);
1087 if (!add_mod_to_array_talloc(msg, &mod,
1088 &r->mods, &r->num_mods))
1097 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1098 struct ldap_Result *r = &msg->r.ModifyResponse;
1099 msg->type = LDAP_TAG_ModifyResponse;
1100 asn1_start_tag(data, tag);
1101 ldap_decode_response(msg, data, r);
1106 case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1107 struct ldap_AddRequest *r = &msg->r.AddRequest;
1108 msg->type = LDAP_TAG_AddRequest;
1109 asn1_start_tag(data, tag);
1110 asn1_read_OctetString_talloc(msg, data, &r->dn);
1112 r->attributes = NULL;
1113 r->num_attributes = 0;
1114 ldap_decode_attribs(msg, data, &r->attributes,
1115 &r->num_attributes);
1121 case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1122 struct ldap_Result *r = &msg->r.AddResponse;
1123 msg->type = LDAP_TAG_AddResponse;
1124 asn1_start_tag(data, tag);
1125 ldap_decode_response(msg, data, r);
1130 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1131 struct ldap_DelRequest *r = &msg->r.DelRequest;
1134 msg->type = LDAP_TAG_DelRequest;
1135 asn1_start_tag(data,
1136 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
1137 len = asn1_tag_remaining(data);
1138 dn = talloc_size(msg, len+1);
1141 asn1_read(data, dn, len);
1148 case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1149 struct ldap_Result *r = &msg->r.DelResponse;
1150 msg->type = LDAP_TAG_DelResponse;
1151 asn1_start_tag(data, tag);
1152 ldap_decode_response(msg, data, r);
1157 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1158 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1159 msg->type = LDAP_TAG_ModifyDNRequest;
1160 asn1_start_tag(data,
1161 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
1162 asn1_read_OctetString_talloc(msg, data, &r->dn);
1163 asn1_read_OctetString_talloc(msg, data, &r->newrdn);
1164 asn1_read_BOOLEAN(data, &r->deleteolddn);
1165 r->newsuperior = NULL;
1166 if (asn1_tag_remaining(data) > 0) {
1169 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1170 len = asn1_tag_remaining(data);
1171 newsup = talloc_size(msg, len+1);
1174 asn1_read(data, newsup, len);
1176 r->newsuperior = newsup;
1183 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1184 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1185 msg->type = LDAP_TAG_ModifyDNResponse;
1186 asn1_start_tag(data, tag);
1187 ldap_decode_response(msg, data, r);
1192 case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1193 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1194 msg->type = LDAP_TAG_CompareRequest;
1195 asn1_start_tag(data,
1196 ASN1_APPLICATION(LDAP_TAG_CompareRequest));
1197 asn1_read_OctetString_talloc(msg, data, &r->dn);
1198 asn1_start_tag(data, ASN1_SEQUENCE(0));
1199 asn1_read_OctetString_talloc(msg, data, &r->attribute);
1200 asn1_read_OctetString(data, &r->value);
1201 if (r->value.data) {
1202 talloc_steal(msg, r->value.data);
1209 case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1210 struct ldap_Result *r = &msg->r.CompareResponse;
1211 msg->type = LDAP_TAG_CompareResponse;
1212 asn1_start_tag(data, tag);
1213 ldap_decode_response(msg, data, r);
1218 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1219 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1220 msg->type = LDAP_TAG_AbandonRequest;
1221 asn1_start_tag(data, tag);
1222 asn1_read_implicit_Integer(data, &r->messageid);
1227 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1228 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1229 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1231 msg->type = LDAP_TAG_ExtendedRequest;
1232 asn1_start_tag(data,tag);
1233 if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
1236 r->oid = blob2string_talloc(msg, tmp_blob);
1237 data_blob_free(&tmp_blob);
1242 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1243 asn1_read_ContextSimple(data, 1, &tmp_blob);
1244 r->value = data_blob_talloc(msg, tmp_blob.data, tmp_blob.length);
1245 data_blob_free(&tmp_blob);
1247 r->value = data_blob(NULL, 0);
1254 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1255 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1256 msg->type = LDAP_TAG_ExtendedResponse;
1257 asn1_start_tag(data, tag);
1258 ldap_decode_response(msg, data, &r->response);
1259 /* I have to come across an operation that actually sends
1260 * something back to really see what's going on. The currently
1261 * needed pwdchange does not send anything back. */
1263 r->value.data = NULL;
1264 r->value.length = 0;
1272 msg->controls = NULL;
1274 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1276 struct ldap_Control **ctrl = NULL;
1278 asn1_start_tag(data, ASN1_CONTEXT(0));
1280 for (i=0; asn1_peek_tag(data, ASN1_SEQUENCE(0)); i++) {
1281 /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1283 ctrl = talloc_realloc(msg, ctrl, struct ldap_Control *, i+2);
1288 ctrl[i] = talloc(ctrl, struct ldap_Control);
1293 if (!ldap_decode_control(ctrl, data, ctrl[i])) {
1301 msg->controls = ctrl;
1307 return ((!data->has_error) && (data->nesting == NULL));
1312 return NT_STATUS_OK if a blob has enough bytes in it to be a full
1313 ldap packet. Set packet_size if true.
1315 NTSTATUS ldap_full_packet(void *private, DATA_BLOB blob, size_t *packet_size)
1317 return asn1_full_tag(blob, ASN1_SEQUENCE(0), packet_size);