2 Unix SMB/CIFS mplementation.
3 LDAP protocol helper functions for SAMBA
5 Copyright (C) Andrew Tridgell 2004
6 Copyright (C) Volker Lendecke 2004
7 Copyright (C) Stefan Metzmacher 2004
8 Copyright (C) Simo Sorce 2004
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "../lib/util/asn1.h"
27 #include "../libcli/ldap/ldap_message.h"
29 _PUBLIC_ struct ldap_message *new_ldap_message(TALLOC_CTX *mem_ctx)
31 return talloc_zero(mem_ctx, struct ldap_message);
35 static bool add_value_to_attrib(TALLOC_CTX *mem_ctx, struct ldb_val *value,
36 struct ldb_message_element *attrib)
38 attrib->values = talloc_realloc(mem_ctx,
41 attrib->num_values+1);
42 if (attrib->values == NULL)
45 attrib->values[attrib->num_values].data = talloc_steal(attrib->values,
47 attrib->values[attrib->num_values].length = value->length;
48 attrib->num_values += 1;
52 static bool add_attrib_to_array_talloc(TALLOC_CTX *mem_ctx,
53 const struct ldb_message_element *attrib,
54 struct ldb_message_element **attribs,
57 *attribs = talloc_realloc(mem_ctx,
59 struct ldb_message_element,
65 (*attribs)[*num_attribs] = *attrib;
66 talloc_steal(*attribs, attrib->values);
67 talloc_steal(*attribs, attrib->name);
72 static bool add_mod_to_array_talloc(TALLOC_CTX *mem_ctx,
74 struct ldap_mod **mods,
77 *mods = talloc_realloc(mem_ctx, *mods, struct ldap_mod, (*num_mods)+1);
82 (*mods)[*num_mods] = *mod;
87 static bool ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree)
91 switch (tree->operation) {
94 asn1_push_tag(data, ASN1_CONTEXT(tree->operation==LDB_OP_AND?0:1));
95 for (i=0; i<tree->u.list.num_elements; i++) {
96 if (!ldap_push_filter(data, tree->u.list.elements[i])) {
104 asn1_push_tag(data, ASN1_CONTEXT(2));
105 if (!ldap_push_filter(data, tree->u.isnot.child)) {
111 case LDB_OP_EQUALITY:
113 asn1_push_tag(data, ASN1_CONTEXT(3));
114 asn1_write_OctetString(data, tree->u.equality.attr,
115 strlen(tree->u.equality.attr));
116 asn1_write_OctetString(data, tree->u.equality.value.data,
117 tree->u.equality.value.length);
121 case LDB_OP_SUBSTRING:
123 SubstringFilter ::= SEQUENCE {
124 type AttributeDescription,
125 -- at least one must be present
126 substrings SEQUENCE OF CHOICE {
127 initial [0] LDAPString,
129 final [2] LDAPString } }
131 asn1_push_tag(data, ASN1_CONTEXT(4));
132 asn1_write_OctetString(data, tree->u.substring.attr, strlen(tree->u.substring.attr));
133 asn1_push_tag(data, ASN1_SEQUENCE(0));
135 if ( ! tree->u.substring.start_with_wildcard) {
136 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
137 asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i]);
141 while (tree->u.substring.chunks[i]) {
144 if (( ! tree->u.substring.chunks[i + 1]) &&
145 (tree->u.substring.end_with_wildcard == 0)) {
150 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(ctx));
151 asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i]);
160 /* greaterOrEqual test */
161 asn1_push_tag(data, ASN1_CONTEXT(5));
162 asn1_write_OctetString(data, tree->u.comparison.attr,
163 strlen(tree->u.comparison.attr));
164 asn1_write_OctetString(data, tree->u.comparison.value.data,
165 tree->u.comparison.value.length);
170 /* lessOrEqual test */
171 asn1_push_tag(data, ASN1_CONTEXT(6));
172 asn1_write_OctetString(data, tree->u.comparison.attr,
173 strlen(tree->u.comparison.attr));
174 asn1_write_OctetString(data, tree->u.comparison.value.data,
175 tree->u.comparison.value.length);
181 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(7));
182 asn1_write_LDAPString(data, tree->u.present.attr);
184 return !data->has_error;
188 asn1_push_tag(data, ASN1_CONTEXT(8));
189 asn1_write_OctetString(data, tree->u.comparison.attr,
190 strlen(tree->u.comparison.attr));
191 asn1_write_OctetString(data, tree->u.comparison.value.data,
192 tree->u.comparison.value.length);
196 case LDB_OP_EXTENDED:
198 MatchingRuleAssertion ::= SEQUENCE {
199 matchingRule [1] MatchingRuleID OPTIONAL,
200 type [2] AttributeDescription OPTIONAL,
201 matchValue [3] AssertionValue,
202 dnAttributes [4] BOOLEAN DEFAULT FALSE
205 asn1_push_tag(data, ASN1_CONTEXT(9));
206 if (tree->u.extended.rule_id) {
207 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1));
208 asn1_write_LDAPString(data, tree->u.extended.rule_id);
211 if (tree->u.extended.attr) {
212 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(2));
213 asn1_write_LDAPString(data, tree->u.extended.attr);
216 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(3));
217 asn1_write_DATA_BLOB_LDAPString(data, &tree->u.extended.value);
219 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(4));
220 asn1_write_uint8(data, tree->u.extended.dnAttributes);
228 return !data->has_error;
231 static void ldap_encode_response(struct asn1_data *data, struct ldap_Result *result)
233 asn1_write_enumerated(data, result->resultcode);
234 asn1_write_OctetString(data, result->dn,
235 (result->dn) ? strlen(result->dn) : 0);
236 asn1_write_OctetString(data, result->errormessage,
237 (result->errormessage) ?
238 strlen(result->errormessage) : 0);
239 if (result->referral) {
240 asn1_push_tag(data, ASN1_CONTEXT(3));
241 asn1_write_OctetString(data, result->referral,
242 strlen(result->referral));
247 _PUBLIC_ bool ldap_encode(struct ldap_message *msg, DATA_BLOB *result, TALLOC_CTX *mem_ctx)
249 struct asn1_data *data = asn1_init(mem_ctx);
252 if (!data) return false;
254 asn1_push_tag(data, ASN1_SEQUENCE(0));
255 asn1_write_Integer(data, msg->messageid);
258 case LDAP_TAG_BindRequest: {
259 struct ldap_BindRequest *r = &msg->r.BindRequest;
260 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
261 asn1_write_Integer(data, r->version);
262 asn1_write_OctetString(data, r->dn,
263 (r->dn != NULL) ? strlen(r->dn) : 0);
265 switch (r->mechanism) {
266 case LDAP_AUTH_MECH_SIMPLE:
267 /* context, primitive */
268 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
269 asn1_write(data, r->creds.password,
270 strlen(r->creds.password));
273 case LDAP_AUTH_MECH_SASL:
274 /* context, constructed */
275 asn1_push_tag(data, ASN1_CONTEXT(3));
276 asn1_write_OctetString(data, r->creds.SASL.mechanism,
277 strlen(r->creds.SASL.mechanism));
278 if (r->creds.SASL.secblob) {
279 asn1_write_OctetString(data, r->creds.SASL.secblob->data,
280 r->creds.SASL.secblob->length);
291 case LDAP_TAG_BindResponse: {
292 struct ldap_BindResponse *r = &msg->r.BindResponse;
293 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
294 ldap_encode_response(data, &r->response);
295 if (r->SASL.secblob) {
296 asn1_write_ContextSimple(data, 7, r->SASL.secblob);
301 case LDAP_TAG_UnbindRequest: {
302 /* struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
305 case LDAP_TAG_SearchRequest: {
306 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
307 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
308 asn1_write_OctetString(data, r->basedn, strlen(r->basedn));
309 asn1_write_enumerated(data, r->scope);
310 asn1_write_enumerated(data, r->deref);
311 asn1_write_Integer(data, r->sizelimit);
312 asn1_write_Integer(data, r->timelimit);
313 asn1_write_BOOLEAN(data, r->attributesonly);
315 if (!ldap_push_filter(data, r->tree)) {
319 asn1_push_tag(data, ASN1_SEQUENCE(0));
320 for (i=0; i<r->num_attributes; i++) {
321 asn1_write_OctetString(data, r->attributes[i],
322 strlen(r->attributes[i]));
328 case LDAP_TAG_SearchResultEntry: {
329 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
330 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
331 asn1_write_OctetString(data, r->dn, strlen(r->dn));
332 asn1_push_tag(data, ASN1_SEQUENCE(0));
333 for (i=0; i<r->num_attributes; i++) {
334 struct ldb_message_element *attr = &r->attributes[i];
335 asn1_push_tag(data, ASN1_SEQUENCE(0));
336 asn1_write_OctetString(data, attr->name,
338 asn1_push_tag(data, ASN1_SEQUENCE(1));
339 for (j=0; j<attr->num_values; j++) {
340 asn1_write_OctetString(data,
341 attr->values[j].data,
342 attr->values[j].length);
351 case LDAP_TAG_SearchResultDone: {
352 struct ldap_Result *r = &msg->r.SearchResultDone;
353 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
354 ldap_encode_response(data, r);
358 case LDAP_TAG_ModifyRequest: {
359 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
360 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
361 asn1_write_OctetString(data, r->dn, strlen(r->dn));
362 asn1_push_tag(data, ASN1_SEQUENCE(0));
364 for (i=0; i<r->num_mods; i++) {
365 struct ldb_message_element *attrib = &r->mods[i].attrib;
366 asn1_push_tag(data, ASN1_SEQUENCE(0));
367 asn1_write_enumerated(data, r->mods[i].type);
368 asn1_push_tag(data, ASN1_SEQUENCE(0));
369 asn1_write_OctetString(data, attrib->name,
370 strlen(attrib->name));
371 asn1_push_tag(data, ASN1_SET);
372 for (j=0; j<attrib->num_values; j++) {
373 asn1_write_OctetString(data,
374 attrib->values[j].data,
375 attrib->values[j].length);
387 case LDAP_TAG_ModifyResponse: {
388 struct ldap_Result *r = &msg->r.ModifyResponse;
389 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
390 ldap_encode_response(data, r);
394 case LDAP_TAG_AddRequest: {
395 struct ldap_AddRequest *r = &msg->r.AddRequest;
396 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
397 asn1_write_OctetString(data, r->dn, strlen(r->dn));
398 asn1_push_tag(data, ASN1_SEQUENCE(0));
400 for (i=0; i<r->num_attributes; i++) {
401 struct ldb_message_element *attrib = &r->attributes[i];
402 asn1_push_tag(data, ASN1_SEQUENCE(0));
403 asn1_write_OctetString(data, attrib->name,
404 strlen(attrib->name));
405 asn1_push_tag(data, ASN1_SET);
406 for (j=0; j<r->attributes[i].num_values; j++) {
407 asn1_write_OctetString(data,
408 attrib->values[j].data,
409 attrib->values[j].length);
418 case LDAP_TAG_AddResponse: {
419 struct ldap_Result *r = &msg->r.AddResponse;
420 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
421 ldap_encode_response(data, r);
425 case LDAP_TAG_DelRequest: {
426 struct ldap_DelRequest *r = &msg->r.DelRequest;
427 asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type));
428 asn1_write(data, r->dn, strlen(r->dn));
432 case LDAP_TAG_DelResponse: {
433 struct ldap_Result *r = &msg->r.DelResponse;
434 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
435 ldap_encode_response(data, r);
439 case LDAP_TAG_ModifyDNRequest: {
440 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
441 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
442 asn1_write_OctetString(data, r->dn, strlen(r->dn));
443 asn1_write_OctetString(data, r->newrdn, strlen(r->newrdn));
444 asn1_write_BOOLEAN(data, r->deleteolddn);
445 if (r->newsuperior) {
446 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
447 asn1_write(data, r->newsuperior,
448 strlen(r->newsuperior));
454 case LDAP_TAG_ModifyDNResponse: {
455 struct ldap_Result *r = &msg->r.ModifyDNResponse;
456 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
457 ldap_encode_response(data, r);
461 case LDAP_TAG_CompareRequest: {
462 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
463 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
464 asn1_write_OctetString(data, r->dn, strlen(r->dn));
465 asn1_push_tag(data, ASN1_SEQUENCE(0));
466 asn1_write_OctetString(data, r->attribute,
467 strlen(r->attribute));
468 asn1_write_OctetString(data, r->value.data,
474 case LDAP_TAG_CompareResponse: {
475 struct ldap_Result *r = &msg->r.ModifyDNResponse;
476 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
477 ldap_encode_response(data, r);
481 case LDAP_TAG_AbandonRequest: {
482 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
483 asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type));
484 asn1_write_implicit_Integer(data, r->messageid);
488 case LDAP_TAG_SearchResultReference: {
489 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
490 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
491 asn1_write_OctetString(data, r->referral, strlen(r->referral));
495 case LDAP_TAG_ExtendedRequest: {
496 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
497 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
498 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
499 asn1_write(data, r->oid, strlen(r->oid));
502 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1));
503 asn1_write(data, r->value->data, r->value->length);
509 case LDAP_TAG_ExtendedResponse: {
510 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
511 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
512 ldap_encode_response(data, &r->response);
514 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(10));
515 asn1_write(data, r->oid, strlen(r->oid));
519 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(11));
520 asn1_write(data, r->value->data, r->value->length);
530 if (msg->controls != NULL) {
531 asn1_push_tag(data, ASN1_CONTEXT(0));
533 for (i = 0; msg->controls[i] != NULL; i++) {
534 if (!ldap_encode_control(mem_ctx, data, msg->controls[i])) {
544 if (data->has_error) {
549 *result = data_blob_talloc(mem_ctx, data->data, data->length);
554 static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
557 char *result = talloc_array(mem_ctx, char, blob.length+1);
558 memcpy(result, blob.data, blob.length);
559 result[blob.length] = '\0';
563 bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
564 struct asn1_data *data,
568 if (!asn1_read_OctetString(data, mem_ctx, &string))
570 *result = blob2string_talloc(mem_ctx, string);
571 data_blob_free(&string);
575 static void ldap_decode_response(TALLOC_CTX *mem_ctx,
576 struct asn1_data *data,
577 struct ldap_Result *result)
579 asn1_read_enumerated(data, &result->resultcode);
580 asn1_read_OctetString_talloc(mem_ctx, data, &result->dn);
581 asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage);
582 if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
583 asn1_start_tag(data, ASN1_CONTEXT(3));
584 asn1_read_OctetString_talloc(mem_ctx, data, &result->referral);
587 result->referral = NULL;
591 static struct ldb_val **ldap_decode_substring(TALLOC_CTX *mem_ctx, struct ldb_val **chunks, int chunk_num, char *value)
594 chunks = talloc_realloc(mem_ctx, chunks, struct ldb_val *, chunk_num + 2);
595 if (chunks == NULL) {
599 chunks[chunk_num] = talloc(mem_ctx, struct ldb_val);
600 if (chunks[chunk_num] == NULL) {
604 chunks[chunk_num]->data = (uint8_t *)talloc_strdup(mem_ctx, value);
605 if (chunks[chunk_num]->data == NULL) {
608 chunks[chunk_num]->length = strlen(value);
610 chunks[chunk_num + 1] = '\0';
617 parse the ASN.1 formatted search string into a ldb_parse_tree
619 static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
620 struct asn1_data *data)
623 struct ldb_parse_tree *ret;
625 if (!asn1_peek_uint8(data, &filter_tag)) {
629 filter_tag &= 0x1f; /* strip off the asn1 stuff */
631 ret = talloc(mem_ctx, struct ldb_parse_tree);
632 if (ret == NULL) return NULL;
637 /* AND or OR of one or more filters */
638 ret->operation = (filter_tag == 0)?LDB_OP_AND:LDB_OP_OR;
639 ret->u.list.num_elements = 0;
640 ret->u.list.elements = NULL;
642 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
646 while (asn1_tag_remaining(data) > 0) {
647 struct ldb_parse_tree *subtree;
648 subtree = ldap_decode_filter_tree(ret, data);
649 if (subtree == NULL) {
652 ret->u.list.elements =
653 talloc_realloc(ret, ret->u.list.elements,
654 struct ldb_parse_tree *,
655 ret->u.list.num_elements+1);
656 if (ret->u.list.elements == NULL) {
659 talloc_steal(ret->u.list.elements, subtree);
660 ret->u.list.elements[ret->u.list.num_elements] = subtree;
661 ret->u.list.num_elements++;
663 if (!asn1_end_tag(data)) {
669 /* 'not' operation */
670 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
674 ret->operation = LDB_OP_NOT;
675 ret->u.isnot.child = ldap_decode_filter_tree(ret, data);
676 if (ret->u.isnot.child == NULL) {
679 if (!asn1_end_tag(data)) {
689 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
690 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
691 asn1_read_OctetString(data, mem_ctx, &value);
693 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
697 ret->operation = LDB_OP_EQUALITY;
698 ret->u.equality.attr = talloc_steal(ret, attrib);
699 ret->u.equality.value.data = talloc_steal(ret, value.data);
700 ret->u.equality.value.length = value.length;
710 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
713 if (!asn1_read_OctetString(data, mem_ctx, &attr)) {
717 ret->operation = LDB_OP_SUBSTRING;
718 ret->u.substring.attr = talloc_strndup(ret, (char *)attr.data, attr.length);
719 ret->u.substring.chunks = NULL;
720 ret->u.substring.start_with_wildcard = 1;
721 ret->u.substring.end_with_wildcard = 1;
723 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
727 while (asn1_tag_remaining(data)) {
728 asn1_peek_uint8(data, &subs_tag);
729 subs_tag &= 0x1f; /* strip off the asn1 stuff */
730 if (subs_tag > 2) goto failed;
732 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(subs_tag));
733 asn1_read_LDAPString(data, mem_ctx, &value);
738 if (ret->u.substring.chunks != NULL) {
739 /* initial value found in the middle */
743 ret->u.substring.chunks = ldap_decode_substring(ret, NULL, 0, value);
744 if (ret->u.substring.chunks == NULL) {
748 ret->u.substring.start_with_wildcard = 0;
753 if (ret->u.substring.end_with_wildcard == 0) {
754 /* "any" value found after a "final" value */
758 ret->u.substring.chunks = ldap_decode_substring(ret,
759 ret->u.substring.chunks,
762 if (ret->u.substring.chunks == NULL) {
770 ret->u.substring.chunks = ldap_decode_substring(ret,
771 ret->u.substring.chunks,
774 if (ret->u.substring.chunks == NULL) {
778 ret->u.substring.end_with_wildcard = 0;
787 if (!asn1_end_tag(data)) { /* SEQUENCE */
791 if (!asn1_end_tag(data)) {
801 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
802 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
803 asn1_read_OctetString(data, mem_ctx, &value);
805 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
809 ret->operation = LDB_OP_GREATER;
810 ret->u.comparison.attr = talloc_steal(ret, attrib);
811 ret->u.comparison.value.data = talloc_steal(ret, value.data);
812 ret->u.comparison.value.length = value.length;
820 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
821 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
822 asn1_read_OctetString(data, mem_ctx, &value);
824 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
828 ret->operation = LDB_OP_LESS;
829 ret->u.comparison.attr = talloc_steal(ret, attrib);
830 ret->u.comparison.value.data = talloc_steal(ret, value.data);
831 ret->u.comparison.value.length = value.length;
835 /* Normal presence, "attribute=*" */
838 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(filter_tag))) {
841 if (!asn1_read_LDAPString(data, ret, &attr)) {
845 ret->operation = LDB_OP_PRESENT;
846 ret->u.present.attr = talloc_steal(ret, attr);
848 if (!asn1_end_tag(data)) {
858 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
859 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
860 asn1_read_OctetString(data, mem_ctx, &value);
862 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
866 ret->operation = LDB_OP_APPROX;
867 ret->u.comparison.attr = talloc_steal(ret, attrib);
868 ret->u.comparison.value.data = talloc_steal(ret, value.data);
869 ret->u.comparison.value.length = value.length;
873 char *oid = NULL, *attr = NULL, *value;
874 uint8_t dnAttributes;
875 /* an extended search */
876 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
880 /* FIXME: read carefully rfc2251.txt there are a number of 'MUST's
881 we need to check we properly implement --SSS */
882 /* either oid or type must be defined */
883 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
884 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(1));
885 asn1_read_LDAPString(data, ret, &oid);
888 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(2))) { /* optional */
889 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(2));
890 asn1_read_LDAPString(data, ret, &attr);
893 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(3));
894 asn1_read_LDAPString(data, ret, &value);
896 /* dnAttributes is marked as BOOLEAN DEFAULT FALSE
897 it is not marked as OPTIONAL but openldap tools
898 do not set this unless it is to be set as TRUE
899 NOTE: openldap tools do not work with AD as it
900 seems that AD always requires the dnAttributes
901 boolean value to be set */
902 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(4))) {
903 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(4));
904 asn1_read_uint8(data, &dnAttributes);
909 if ((oid == NULL && attr == NULL) || (value == NULL)) {
914 ret->operation = LDB_OP_EXTENDED;
916 /* From the RFC2251: If the type field is
917 absent and matchingRule is present, the matchValue is compared
918 against all attributes in an entry which support that matchingRule
921 ret->u.extended.attr = talloc_steal(ret, attr);
923 ret->u.extended.attr = talloc_strdup(ret, "*");
925 ret->u.extended.rule_id = talloc_steal(ret, oid);
926 ret->u.extended.value.data = (uint8_t *)talloc_steal(ret, value);
927 ret->u.extended.value.length = strlen(value);
928 ret->u.extended.dnAttributes = dnAttributes;
930 ret->operation = LDB_OP_EQUALITY;
931 ret->u.equality.attr = talloc_steal(ret, attr);
932 ret->u.equality.value.data = (uint8_t *)talloc_steal(ret, value);
933 ret->u.equality.value.length = strlen(value);
935 if (!asn1_end_tag(data)) {
952 /* Decode a single LDAP attribute, possibly containing multiple values */
953 static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
954 struct ldb_message_element *attrib)
956 asn1_start_tag(data, ASN1_SEQUENCE(0));
957 asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name);
958 asn1_start_tag(data, ASN1_SET);
959 while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
961 asn1_read_OctetString(data, mem_ctx, &blob);
962 add_value_to_attrib(mem_ctx, &blob, attrib);
969 /* Decode a set of LDAP attributes, as found in the dereference control */
970 void ldap_decode_attribs_bare(TALLOC_CTX *mem_ctx, struct asn1_data *data,
971 struct ldb_message_element **attributes,
974 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
975 struct ldb_message_element attrib;
977 ldap_decode_attrib(mem_ctx, data, &attrib);
978 add_attrib_to_array_talloc(mem_ctx, &attrib,
979 attributes, num_attributes);
983 /* Decode a set of LDAP attributes, as found in a search entry */
984 static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
985 struct ldb_message_element **attributes,
988 asn1_start_tag(data, ASN1_SEQUENCE(0));
989 ldap_decode_attribs_bare(mem_ctx, data,
990 attributes, num_attributes);
994 /* This routine returns LDAP status codes */
996 _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, struct ldap_message *msg)
1000 asn1_start_tag(data, ASN1_SEQUENCE(0));
1001 asn1_read_Integer(data, &msg->messageid);
1003 if (!asn1_peek_uint8(data, &tag))
1004 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1008 case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
1009 struct ldap_BindRequest *r = &msg->r.BindRequest;
1010 msg->type = LDAP_TAG_BindRequest;
1011 asn1_start_tag(data, tag);
1012 asn1_read_Integer(data, &r->version);
1013 asn1_read_OctetString_talloc(msg, data, &r->dn);
1014 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
1016 r->creds.password = "";
1017 r->mechanism = LDAP_AUTH_MECH_SIMPLE;
1018 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1019 pwlen = asn1_tag_remaining(data);
1021 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1024 char *pw = talloc_array(msg, char, pwlen+1);
1026 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1028 asn1_read(data, pw, pwlen);
1030 r->creds.password = pw;
1033 } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
1034 asn1_start_tag(data, ASN1_CONTEXT(3));
1035 r->mechanism = LDAP_AUTH_MECH_SASL;
1036 asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism);
1037 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) { /* optional */
1038 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1039 asn1_read_OctetString(data, msg, &tmp_blob);
1040 r->creds.SASL.secblob = talloc(msg, DATA_BLOB);
1041 if (!r->creds.SASL.secblob) {
1042 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1044 *r->creds.SASL.secblob = data_blob_talloc(r->creds.SASL.secblob,
1045 tmp_blob.data, tmp_blob.length);
1046 data_blob_free(&tmp_blob);
1048 r->creds.SASL.secblob = NULL;
1052 /* Neither Simple nor SASL bind */
1053 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1059 case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
1060 struct ldap_BindResponse *r = &msg->r.BindResponse;
1061 msg->type = LDAP_TAG_BindResponse;
1062 asn1_start_tag(data, tag);
1063 ldap_decode_response(msg, data, &r->response);
1064 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
1065 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1066 asn1_read_ContextSimple(data, 7, &tmp_blob);
1067 r->SASL.secblob = talloc(msg, DATA_BLOB);
1068 if (!r->SASL.secblob) {
1069 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1071 *r->SASL.secblob = data_blob_talloc(r->SASL.secblob,
1072 tmp_blob.data, tmp_blob.length);
1073 data_blob_free(&tmp_blob);
1075 r->SASL.secblob = NULL;
1081 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
1082 msg->type = LDAP_TAG_UnbindRequest;
1083 asn1_start_tag(data, tag);
1088 case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
1089 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
1090 int sizelimit, timelimit;
1091 const char **attrs = NULL;
1092 msg->type = LDAP_TAG_SearchRequest;
1093 asn1_start_tag(data, tag);
1094 asn1_read_OctetString_talloc(msg, data, &r->basedn);
1095 asn1_read_enumerated(data, (int *)&(r->scope));
1096 asn1_read_enumerated(data, (int *)&(r->deref));
1097 asn1_read_Integer(data, &sizelimit);
1098 r->sizelimit = sizelimit;
1099 asn1_read_Integer(data, &timelimit);
1100 r->timelimit = timelimit;
1101 asn1_read_BOOLEAN(data, &r->attributesonly);
1103 r->tree = ldap_decode_filter_tree(msg, data);
1104 if (r->tree == NULL) {
1105 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1108 asn1_start_tag(data, ASN1_SEQUENCE(0));
1110 r->num_attributes = 0;
1111 r->attributes = NULL;
1113 while (asn1_tag_remaining(data) > 0) {
1116 if (!asn1_read_OctetString_talloc(msg, data,
1118 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1119 if (!add_string_to_array(msg, attr,
1121 &r->num_attributes))
1122 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1124 r->attributes = attrs;
1131 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1132 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1133 msg->type = LDAP_TAG_SearchResultEntry;
1134 r->attributes = NULL;
1135 r->num_attributes = 0;
1136 asn1_start_tag(data, tag);
1137 asn1_read_OctetString_talloc(msg, data, &r->dn);
1138 ldap_decode_attribs(msg, data, &r->attributes,
1139 &r->num_attributes);
1144 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1145 struct ldap_Result *r = &msg->r.SearchResultDone;
1146 msg->type = LDAP_TAG_SearchResultDone;
1147 asn1_start_tag(data, tag);
1148 ldap_decode_response(msg, data, r);
1153 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1154 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
1155 msg->type = LDAP_TAG_SearchResultReference;
1156 asn1_start_tag(data, tag);
1157 asn1_read_OctetString_talloc(msg, data, &r->referral);
1162 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1163 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1164 msg->type = LDAP_TAG_ModifyRequest;
1165 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
1166 asn1_read_OctetString_talloc(msg, data, &r->dn);
1167 asn1_start_tag(data, ASN1_SEQUENCE(0));
1172 while (asn1_tag_remaining(data) > 0) {
1173 struct ldap_mod mod;
1176 asn1_start_tag(data, ASN1_SEQUENCE(0));
1177 asn1_read_enumerated(data, &v);
1179 ldap_decode_attrib(msg, data, &mod.attrib);
1181 if (!add_mod_to_array_talloc(msg, &mod,
1182 &r->mods, &r->num_mods)) {
1183 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1192 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1193 struct ldap_Result *r = &msg->r.ModifyResponse;
1194 msg->type = LDAP_TAG_ModifyResponse;
1195 asn1_start_tag(data, tag);
1196 ldap_decode_response(msg, data, r);
1201 case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1202 struct ldap_AddRequest *r = &msg->r.AddRequest;
1203 msg->type = LDAP_TAG_AddRequest;
1204 asn1_start_tag(data, tag);
1205 asn1_read_OctetString_talloc(msg, data, &r->dn);
1207 r->attributes = NULL;
1208 r->num_attributes = 0;
1209 ldap_decode_attribs(msg, data, &r->attributes,
1210 &r->num_attributes);
1216 case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1217 struct ldap_Result *r = &msg->r.AddResponse;
1218 msg->type = LDAP_TAG_AddResponse;
1219 asn1_start_tag(data, tag);
1220 ldap_decode_response(msg, data, r);
1225 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1226 struct ldap_DelRequest *r = &msg->r.DelRequest;
1229 msg->type = LDAP_TAG_DelRequest;
1230 asn1_start_tag(data,
1231 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
1232 len = asn1_tag_remaining(data);
1234 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1236 dn = talloc_array(msg, char, len+1);
1239 asn1_read(data, dn, len);
1246 case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1247 struct ldap_Result *r = &msg->r.DelResponse;
1248 msg->type = LDAP_TAG_DelResponse;
1249 asn1_start_tag(data, tag);
1250 ldap_decode_response(msg, data, r);
1255 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1256 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1257 msg->type = LDAP_TAG_ModifyDNRequest;
1258 asn1_start_tag(data,
1259 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
1260 asn1_read_OctetString_talloc(msg, data, &r->dn);
1261 asn1_read_OctetString_talloc(msg, data, &r->newrdn);
1262 asn1_read_BOOLEAN(data, &r->deleteolddn);
1263 r->newsuperior = NULL;
1264 if (asn1_tag_remaining(data) > 0) {
1267 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1268 len = asn1_tag_remaining(data);
1270 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1272 newsup = talloc_array(msg, char, len+1);
1273 if (newsup == NULL) {
1274 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1276 asn1_read(data, newsup, len);
1278 r->newsuperior = newsup;
1285 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1286 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1287 msg->type = LDAP_TAG_ModifyDNResponse;
1288 asn1_start_tag(data, tag);
1289 ldap_decode_response(msg, data, r);
1294 case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1295 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1296 msg->type = LDAP_TAG_CompareRequest;
1297 asn1_start_tag(data,
1298 ASN1_APPLICATION(LDAP_TAG_CompareRequest));
1299 asn1_read_OctetString_talloc(msg, data, &r->dn);
1300 asn1_start_tag(data, ASN1_SEQUENCE(0));
1301 asn1_read_OctetString_talloc(msg, data, &r->attribute);
1302 asn1_read_OctetString(data, msg, &r->value);
1303 if (r->value.data) {
1304 talloc_steal(msg, r->value.data);
1311 case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1312 struct ldap_Result *r = &msg->r.CompareResponse;
1313 msg->type = LDAP_TAG_CompareResponse;
1314 asn1_start_tag(data, tag);
1315 ldap_decode_response(msg, data, r);
1320 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1321 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1322 msg->type = LDAP_TAG_AbandonRequest;
1323 asn1_start_tag(data, tag);
1324 asn1_read_implicit_Integer(data, &r->messageid);
1329 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1330 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1331 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1333 msg->type = LDAP_TAG_ExtendedRequest;
1334 asn1_start_tag(data,tag);
1335 if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
1336 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1338 r->oid = blob2string_talloc(msg, tmp_blob);
1339 data_blob_free(&tmp_blob);
1341 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1344 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1345 asn1_read_ContextSimple(data, 1, &tmp_blob);
1346 r->value = talloc(msg, DATA_BLOB);
1348 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1350 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1351 data_blob_free(&tmp_blob);
1360 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1361 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1362 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1364 msg->type = LDAP_TAG_ExtendedResponse;
1365 asn1_start_tag(data, tag);
1366 ldap_decode_response(msg, data, &r->response);
1368 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(10))) {
1369 asn1_read_ContextSimple(data, 1, &tmp_blob);
1370 r->oid = blob2string_talloc(msg, tmp_blob);
1371 data_blob_free(&tmp_blob);
1373 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1379 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(11))) {
1380 asn1_read_ContextSimple(data, 1, &tmp_blob);
1381 r->value = talloc(msg, DATA_BLOB);
1383 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1385 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1386 data_blob_free(&tmp_blob);
1395 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1398 msg->controls = NULL;
1399 msg->controls_decoded = NULL;
1401 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1403 struct ldb_control **ctrl = NULL;
1404 bool *decoded = NULL;
1406 asn1_start_tag(data, ASN1_CONTEXT(0));
1408 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1410 /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1412 ctrl = talloc_realloc(msg, ctrl, struct ldb_control *, i+2);
1414 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1417 decoded = talloc_realloc(msg, decoded, bool, i+1);
1419 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1422 ctrl[i] = talloc(ctrl, struct ldb_control);
1424 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1427 if (!ldap_decode_control_wrapper(ctrl, data, ctrl[i], &value)) {
1428 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1431 if (!ldap_decode_control_value(ctrl, value, ctrl[i])) {
1432 if (ctrl[i]->critical) {
1433 ctrl[i]->data = NULL;
1437 talloc_free(ctrl[i]);
1450 msg->controls = ctrl;
1451 msg->controls_decoded = decoded;
1457 if ((data->has_error) || (data->nesting != NULL)) {
1458 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1460 return NT_STATUS_OK;
1465 return NT_STATUS_OK if a blob has enough bytes in it to be a full
1466 ldap packet. Set packet_size if true.
1468 NTSTATUS ldap_full_packet(void *private_data, DATA_BLOB blob, size_t *packet_size)
1470 return asn1_full_tag(blob, ASN1_SEQUENCE(0), packet_size);