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"
30 /****************************************************************************
32 * LDAP filter parser -- main routine is ldap_parse_filter
34 * Shamelessly stolen and adapted from ldb.
36 ***************************************************************************/
39 return next token element. Caller frees
41 static char *ldap_parse_lex(TALLOC_CTX *mem_ctx, const char **s,
56 if (strchr(sep, *p)) {
58 ret = talloc_strndup(mem_ctx, p, 1);
65 while (*p && (isalnum(*p) || !strchr(sep, *p))) {
73 ret = talloc_strndup(mem_ctx, *s, p - *s);
85 find a matching close brace in a string
87 static const char *match_brace(const char *s)
89 unsigned int count = 0;
90 while (*s && (count != 0 || *s != ')')) {
105 static struct ldap_parse_tree *ldap_parse_filter(TALLOC_CTX *mem_ctx,
109 <simple> ::= <attributetype> <filtertype> <attributevalue>
111 static struct ldap_parse_tree *ldap_parse_simple(TALLOC_CTX *mem_ctx,
115 struct ldap_parse_tree *ret;
117 l = ldap_parse_lex(mem_ctx, &s, LDAP_ALL_SEP);
122 if (strchr("()&|=", *l))
125 eq = ldap_parse_lex(mem_ctx, &s, LDAP_ALL_SEP);
126 if (!eq || strcmp(eq, "=") != 0)
129 val = ldap_parse_lex(mem_ctx, &s, ")");
130 if (val && strchr("()&|", *val))
133 ret = talloc(mem_ctx, sizeof(*ret));
139 ret->operation = LDAP_OP_SIMPLE;
140 ret->u.simple.attr = l;
141 ret->u.simple.value.data = val;
142 ret->u.simple.value.length = val?strlen(val):0;
150 <and> ::= '&' <filterlist>
151 <or> ::= '|' <filterlist>
152 <filterlist> ::= <filter> | <filter> <filterlist>
154 static struct ldap_parse_tree *ldap_parse_filterlist(TALLOC_CTX *mem_ctx,
155 enum ldap_parse_op op,
158 struct ldap_parse_tree *ret, *next;
160 ret = talloc(mem_ctx, sizeof(*ret));
168 ret->u.list.num_elements = 1;
169 ret->u.list.elements = talloc(mem_ctx, sizeof(*ret->u.list.elements));
170 if (!ret->u.list.elements) {
175 ret->u.list.elements[0] = ldap_parse_filter(mem_ctx, &s);
176 if (!ret->u.list.elements[0]) {
180 while (isspace(*s)) s++;
182 while (*s && (next = ldap_parse_filter(mem_ctx, &s))) {
183 struct ldap_parse_tree **e;
184 e = talloc_realloc_p(ret,
185 ret->u.list.elements,
186 struct ldap_parse_tree *,
187 ret->u.list.num_elements+1);
192 ret->u.list.elements = e;
193 ret->u.list.elements[ret->u.list.num_elements] = next;
194 ret->u.list.num_elements++;
195 while (isspace(*s)) s++;
203 <not> ::= '!' <filter>
205 static struct ldap_parse_tree *ldap_parse_not(TALLOC_CTX *mem_ctx, const char *s)
207 struct ldap_parse_tree *ret;
209 ret = talloc(mem_ctx, sizeof(*ret));
215 ret->operation = LDAP_OP_NOT;
216 ret->u.not.child = ldap_parse_filter(mem_ctx, &s);
217 if (!ret->u.not.child)
225 <filtercomp> ::= <and> | <or> | <not> | <simple>
227 static struct ldap_parse_tree *ldap_parse_filtercomp(TALLOC_CTX *mem_ctx,
230 while (isspace(*s)) s++;
234 return ldap_parse_filterlist(mem_ctx, LDAP_OP_AND, s+1);
237 return ldap_parse_filterlist(mem_ctx, LDAP_OP_OR, s+1);
240 return ldap_parse_not(mem_ctx, s+1);
247 return ldap_parse_simple(mem_ctx, s);
252 <filter> ::= '(' <filtercomp> ')'
254 static struct ldap_parse_tree *ldap_parse_filter(TALLOC_CTX *mem_ctx,
259 struct ldap_parse_tree *ret;
261 l = ldap_parse_lex(mem_ctx, s, LDAP_ALL_SEP);
266 if (strcmp(l, "(") != 0) {
276 s2 = talloc_strndup(mem_ctx, *s, p - *s);
282 ret = ldap_parse_filtercomp(mem_ctx, s2);
290 main parser entry point. Takes a search string and returns a parse tree
292 expression ::= <simple> | <filter>
294 static struct ldap_parse_tree *ldap_parse_tree(TALLOC_CTX *mem_ctx, const char *s)
296 while (isspace(*s)) s++;
299 return ldap_parse_filter(mem_ctx, &s);
302 return ldap_parse_simple(mem_ctx, s);
305 static BOOL ldap_push_filter(struct asn1_data *data, struct ldap_parse_tree *tree)
307 switch (tree->operation) {
308 case LDAP_OP_SIMPLE: {
309 if ((tree->u.simple.value.length == 1) &&
310 (((char *)(tree->u.simple.value.data))[0] == '*')) {
311 /* Just a presence test */
312 asn1_push_tag(data, 0x87);
313 asn1_write(data, tree->u.simple.attr,
314 strlen(tree->u.simple.attr));
316 return !data->has_error;
319 /* Equality is all we currently do... */
320 asn1_push_tag(data, 0xa3);
321 asn1_write_OctetString(data, tree->u.simple.attr,
322 strlen(tree->u.simple.attr));
323 asn1_write_OctetString(data, tree->u.simple.value.data,
324 tree->u.simple.value.length);
332 asn1_push_tag(data, 0xa0);
333 for (i=0; i<tree->u.list.num_elements; i++) {
334 ldap_push_filter(data, tree->u.list.elements[i]);
343 asn1_push_tag(data, 0xa1);
344 for (i=0; i<tree->u.list.num_elements; i++) {
345 ldap_push_filter(data, tree->u.list.elements[i]);
353 return !data->has_error;
356 static void ldap_encode_response(struct asn1_data *data, struct ldap_Result *result)
358 asn1_write_enumerated(data, result->resultcode);
359 asn1_write_OctetString(data, result->dn,
360 (result->dn) ? strlen(result->dn) : 0);
361 asn1_write_OctetString(data, result->errormessage,
362 (result->errormessage) ?
363 strlen(result->errormessage) : 0);
364 if (result->referral) {
365 asn1_push_tag(data, ASN1_CONTEXT(3));
366 asn1_write_OctetString(data, result->referral,
367 strlen(result->referral));
372 BOOL ldap_encode(struct ldap_message *msg, DATA_BLOB *result)
374 struct asn1_data data;
378 asn1_push_tag(&data, ASN1_SEQUENCE(0));
379 asn1_write_Integer(&data, msg->messageid);
382 case LDAP_TAG_BindRequest: {
383 struct ldap_BindRequest *r = &msg->r.BindRequest;
384 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
385 asn1_write_Integer(&data, r->version);
386 asn1_write_OctetString(&data, r->dn,
387 (r->dn != NULL) ? strlen(r->dn) : 0);
389 switch (r->mechanism) {
390 case LDAP_AUTH_MECH_SIMPLE:
391 /* context, primitive */
392 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
393 asn1_write(&data, r->creds.password,
394 strlen(r->creds.password));
397 case LDAP_AUTH_MECH_SASL:
398 /* context, constructed */
399 asn1_push_tag(&data, ASN1_CONTEXT(3));
400 asn1_write_OctetString(&data, r->creds.SASL.mechanism,
401 strlen(r->creds.SASL.mechanism));
402 asn1_write_OctetString(&data, r->creds.SASL.secblob.data,
403 r->creds.SASL.secblob.length);
414 case LDAP_TAG_BindResponse: {
415 struct ldap_BindResponse *r = &msg->r.BindResponse;
416 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
417 ldap_encode_response(&data, &r->response);
418 if (r->SASL.secblob.length > 0) {
419 asn1_write_ContextSimple(&data, 7, &r->SASL.secblob);
424 case LDAP_TAG_UnbindRequest: {
425 /* struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
428 case LDAP_TAG_SearchRequest: {
429 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
430 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
431 asn1_write_OctetString(&data, r->basedn, strlen(r->basedn));
432 asn1_write_enumerated(&data, r->scope);
433 asn1_write_enumerated(&data, r->deref);
434 asn1_write_Integer(&data, r->sizelimit);
435 asn1_write_Integer(&data, r->timelimit);
436 asn1_write_BOOLEAN(&data, r->attributesonly);
439 TALLOC_CTX *mem_ctx = talloc_init("ldap_parse_tree");
440 struct ldap_parse_tree *tree;
445 tree = ldap_parse_tree(mem_ctx, r->filter);
450 ldap_push_filter(&data, tree);
452 talloc_destroy(mem_ctx);
455 asn1_push_tag(&data, ASN1_SEQUENCE(0));
456 for (i=0; i<r->num_attributes; i++) {
457 asn1_write_OctetString(&data, r->attributes[i],
458 strlen(r->attributes[i]));
465 case LDAP_TAG_SearchResultEntry: {
466 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
467 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
468 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
469 asn1_push_tag(&data, ASN1_SEQUENCE(0));
470 for (i=0; i<r->num_attributes; i++) {
471 struct ldap_attribute *attr = &r->attributes[i];
472 asn1_push_tag(&data, ASN1_SEQUENCE(0));
473 asn1_write_OctetString(&data, attr->name,
475 asn1_push_tag(&data, ASN1_SEQUENCE(1));
476 for (j=0; j<attr->num_values; j++) {
477 asn1_write_OctetString(&data,
478 attr->values[j].data,
479 attr->values[j].length);
488 case LDAP_TAG_SearchResultDone: {
489 struct ldap_Result *r = &msg->r.SearchResultDone;
490 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
491 ldap_encode_response(&data, r);
495 case LDAP_TAG_ModifyRequest: {
496 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
497 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
498 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
499 asn1_push_tag(&data, ASN1_SEQUENCE(0));
501 for (i=0; i<r->num_mods; i++) {
502 struct ldap_attribute *attrib = &r->mods[i].attrib;
503 asn1_push_tag(&data, ASN1_SEQUENCE(0));
504 asn1_write_enumerated(&data, r->mods[i].type);
505 asn1_push_tag(&data, ASN1_SEQUENCE(0));
506 asn1_write_OctetString(&data, attrib->name,
507 strlen(attrib->name));
508 asn1_push_tag(&data, ASN1_SET);
509 for (j=0; j<attrib->num_values; j++) {
510 asn1_write_OctetString(&data,
511 attrib->values[j].data,
512 attrib->values[j].length);
524 case LDAP_TAG_ModifyResponse: {
525 struct ldap_Result *r = &msg->r.ModifyResponse;
526 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
527 ldap_encode_response(&data, r);
531 case LDAP_TAG_AddRequest: {
532 struct ldap_AddRequest *r = &msg->r.AddRequest;
533 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
534 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
535 asn1_push_tag(&data, ASN1_SEQUENCE(0));
537 for (i=0; i<r->num_attributes; i++) {
538 struct ldap_attribute *attrib = &r->attributes[i];
539 asn1_push_tag(&data, ASN1_SEQUENCE(0));
540 asn1_write_OctetString(&data, attrib->name,
541 strlen(attrib->name));
542 asn1_push_tag(&data, ASN1_SET);
543 for (j=0; j<r->attributes[i].num_values; j++) {
544 asn1_write_OctetString(&data,
545 attrib->values[j].data,
546 attrib->values[j].length);
555 case LDAP_TAG_AddResponse: {
556 struct ldap_Result *r = &msg->r.AddResponse;
557 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
558 ldap_encode_response(&data, r);
562 case LDAP_TAG_DelRequest: {
563 struct ldap_DelRequest *r = &msg->r.DelRequest;
564 asn1_push_tag(&data, ASN1_APPLICATION_SIMPLE(msg->type));
565 asn1_write(&data, r->dn, strlen(r->dn));
569 case LDAP_TAG_DelResponse: {
570 struct ldap_Result *r = &msg->r.DelResponse;
571 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
572 ldap_encode_response(&data, r);
576 case LDAP_TAG_ModifyDNRequest: {
577 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
578 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
579 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
580 asn1_write_OctetString(&data, r->newrdn, strlen(r->newrdn));
581 asn1_write_BOOLEAN(&data, r->deleteolddn);
582 if (r->newsuperior != NULL) {
583 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
584 asn1_write(&data, r->newsuperior,
585 strlen(r->newsuperior));
591 case LDAP_TAG_ModifyDNResponse: {
592 struct ldap_Result *r = &msg->r.ModifyDNResponse;
593 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
594 ldap_encode_response(&data, r);
598 case LDAP_TAG_CompareRequest: {
599 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
600 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
601 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
602 asn1_push_tag(&data, ASN1_SEQUENCE(0));
603 asn1_write_OctetString(&data, r->attribute,
604 strlen(r->attribute));
605 asn1_write_OctetString(&data, r->value.data,
611 case LDAP_TAG_CompareResponse: {
612 struct ldap_Result *r = &msg->r.ModifyDNResponse;
613 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
614 ldap_encode_response(&data, r);
618 case LDAP_TAG_AbandonRequest: {
619 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
620 asn1_push_tag(&data, ASN1_APPLICATION_SIMPLE(msg->type));
621 asn1_write_implicit_Integer(&data, r->messageid);
625 case LDAP_TAG_SearchResultReference: {
626 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
627 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
628 asn1_write_OctetString(&data, r->referral, strlen(r->referral));
632 case LDAP_TAG_ExtendedRequest: {
633 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
634 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
635 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
636 asn1_write(&data, r->oid, strlen(r->oid));
638 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(1));
639 asn1_write(&data, r->value.data, r->value.length);
644 case LDAP_TAG_ExtendedResponse: {
645 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
646 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
647 ldap_encode_response(&data, &r->response);
656 *result = data_blob(data.data, data.length);
661 static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
664 char *result = talloc(mem_ctx, blob.length+1);
665 memcpy(result, blob.data, blob.length);
666 result[blob.length] = '\0';
670 static BOOL asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
671 struct asn1_data *data,
675 if (!asn1_read_OctetString(data, &string))
677 *result = blob2string_talloc(mem_ctx, string);
678 data_blob_free(&string);
682 static void ldap_decode_response(TALLOC_CTX *mem_ctx,
683 struct asn1_data *data,
684 struct ldap_Result *result)
686 asn1_read_enumerated(data, &result->resultcode);
687 asn1_read_OctetString_talloc(mem_ctx, data, &result->dn);
688 asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage);
689 if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
690 asn1_start_tag(data, ASN1_CONTEXT(3));
691 asn1_read_OctetString_talloc(mem_ctx, data, &result->referral);
694 result->referral = NULL;
698 static BOOL ldap_decode_filter(TALLOC_CTX *mem_ctx, struct asn1_data *data,
701 uint8 filter_tag, tag_desc;
703 if (!asn1_peek_uint8(data, &filter_tag))
706 tag_desc = filter_tag;
707 filter_tag &= 0x1f; /* strip off the asn1 stuff */
712 /* AND of one or more filters */
713 if (tag_desc != 0xa0) /* context compount */
716 asn1_start_tag(data, ASN1_CONTEXT(0));
718 *filter = talloc_strdup(mem_ctx, "(&");
722 while (asn1_tag_remaining(data) > 0) {
724 if (!ldap_decode_filter(mem_ctx, data, &subfilter))
726 *filter = talloc_asprintf(mem_ctx, "%s%s", *filter,
733 *filter = talloc_asprintf(mem_ctx, "%s)", *filter);
737 /* OR of one or more filters */
738 if (tag_desc != 0xa0) /* context compount */
741 asn1_start_tag(data, ASN1_CONTEXT(1));
743 *filter = talloc_strdup(mem_ctx, "(|");
747 while (asn1_tag_remaining(data) > 0) {
749 if (!ldap_decode_filter(mem_ctx, data, &subfilter))
751 *filter = talloc_asprintf(mem_ctx, "%s%s", *filter,
759 *filter = talloc_asprintf(mem_ctx, "%s)", *filter);
764 const char *attrib, *value;
765 if (tag_desc != 0xa0) /* context compound */
767 asn1_start_tag(data, ASN1_CONTEXT(3));
768 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
769 asn1_read_OctetString_talloc(mem_ctx, data, &value);
771 if ((data->has_error) || (attrib == NULL) || (value == NULL))
773 *filter = talloc_asprintf(mem_ctx, "(%s=%s)", attrib, value);
777 /* Normal presence, "attribute=*" */
780 if (tag_desc != 0x80) /* context simple */
782 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(7)))
784 attr_len = asn1_tag_remaining(data);
785 attr_name = malloc(attr_len+1);
786 if (attr_name == NULL)
788 asn1_read(data, attr_name, attr_len);
789 attr_name[attr_len] = '\0';
790 *filter = talloc_asprintf(mem_ctx, "(%s=*)", attr_name);
791 SAFE_FREE(attr_name);
803 static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
804 struct ldap_attribute *attrib)
806 asn1_start_tag(data, ASN1_SEQUENCE(0));
807 asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name);
808 asn1_start_tag(data, ASN1_SET);
809 while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
811 struct ldap_val value;
812 asn1_read_OctetString(data, &blob);
813 value.data = blob.data;
814 value.length = blob.length;
815 add_value_to_attrib(mem_ctx, &value, attrib);
816 data_blob_free(&blob);
823 static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
824 struct ldap_attribute **attributes,
827 asn1_start_tag(data, ASN1_SEQUENCE(0));
828 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
829 struct ldap_attribute attrib;
831 ldap_decode_attrib(mem_ctx, data, &attrib);
832 add_attrib_to_array_talloc(mem_ctx, &attrib,
833 attributes, num_attributes);
838 BOOL ldap_decode(struct asn1_data *data, struct ldap_message *msg)
842 asn1_start_tag(data, ASN1_SEQUENCE(0));
843 asn1_read_Integer(data, &msg->messageid);
845 if (!asn1_peek_uint8(data, &tag))
850 case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
851 struct ldap_BindRequest *r = &msg->r.BindRequest;
852 msg->type = LDAP_TAG_BindRequest;
853 asn1_start_tag(data, tag);
854 asn1_read_Integer(data, &r->version);
855 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
856 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
858 r->creds.password = "";
859 r->mechanism = LDAP_AUTH_MECH_SIMPLE;
860 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
861 pwlen = asn1_tag_remaining(data);
863 char *pw = talloc(msg->mem_ctx, pwlen+1);
864 asn1_read(data, pw, pwlen);
866 r->creds.password = pw;
869 } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
870 asn1_start_tag(data, ASN1_CONTEXT(3));
871 r->mechanism = LDAP_AUTH_MECH_SASL;
872 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->creds.SASL.mechanism);
873 asn1_read_OctetString(data, &r->creds.SASL.secblob);
874 if (r->creds.SASL.secblob.data) {
875 talloc_steal(msg->mem_ctx, r->creds.SASL.secblob.data);
883 case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
884 struct ldap_BindResponse *r = &msg->r.BindResponse;
885 msg->type = LDAP_TAG_BindResponse;
886 asn1_start_tag(data, tag);
887 ldap_decode_response(msg->mem_ctx, data, &r->response);
888 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
889 DATA_BLOB tmp_blob = data_blob(NULL, 0);
890 asn1_read_ContextSimple(data, 7, &tmp_blob);
891 r->SASL.secblob = data_blob_talloc(msg->mem_ctx, tmp_blob.data, tmp_blob.length);
892 data_blob_free(&tmp_blob);
894 r->SASL.secblob = data_blob(NULL, 0);
900 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
901 msg->type = LDAP_TAG_UnbindRequest;
902 asn1_start_tag(data, tag);
907 case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
908 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
909 msg->type = LDAP_TAG_SearchRequest;
910 asn1_start_tag(data, tag);
911 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->basedn);
912 asn1_read_enumerated(data, (int *)&(r->scope));
913 asn1_read_enumerated(data, (int *)&(r->deref));
914 asn1_read_Integer(data, &r->sizelimit);
915 asn1_read_Integer(data, &r->timelimit);
916 asn1_read_BOOLEAN(data, &r->attributesonly);
918 /* Maybe create a TALLOC_CTX for the filter? This can waste
919 * quite a bit of memory recursing down. */
920 ldap_decode_filter(msg->mem_ctx, data, &r->filter);
922 asn1_start_tag(data, ASN1_SEQUENCE(0));
924 r->num_attributes = 0;
925 r->attributes = NULL;
927 while (asn1_tag_remaining(data) > 0) {
929 if (!asn1_read_OctetString_talloc(msg->mem_ctx, data,
932 if (!add_string_to_array(msg->mem_ctx, attr,
943 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
944 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
945 msg->type = LDAP_TAG_SearchResultEntry;
946 r->attributes = NULL;
947 r->num_attributes = 0;
948 asn1_start_tag(data, tag);
949 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
950 ldap_decode_attribs(msg->mem_ctx, data, &r->attributes,
956 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
957 struct ldap_Result *r = &msg->r.SearchResultDone;
958 msg->type = LDAP_TAG_SearchResultDone;
959 asn1_start_tag(data, tag);
960 ldap_decode_response(msg->mem_ctx, data, r);
965 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
966 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
967 msg->type = LDAP_TAG_SearchResultReference;
968 asn1_start_tag(data, tag);
969 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->referral);
974 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
975 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
976 msg->type = LDAP_TAG_ModifyRequest;
977 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
978 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
979 asn1_start_tag(data, ASN1_SEQUENCE(0));
984 while (asn1_tag_remaining(data) > 0) {
988 asn1_start_tag(data, ASN1_SEQUENCE(0));
989 asn1_read_enumerated(data, &v);
991 ldap_decode_attrib(msg->mem_ctx, data, &mod.attrib);
993 if (!add_mod_to_array_talloc(msg->mem_ctx, &mod,
994 &r->mods, &r->num_mods))
1003 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1004 struct ldap_Result *r = &msg->r.ModifyResponse;
1005 msg->type = LDAP_TAG_ModifyResponse;
1006 asn1_start_tag(data, tag);
1007 ldap_decode_response(msg->mem_ctx, data, r);
1012 case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1013 struct ldap_AddRequest *r = &msg->r.AddRequest;
1014 msg->type = LDAP_TAG_AddRequest;
1015 asn1_start_tag(data, tag);
1016 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
1018 r->attributes = NULL;
1019 r->num_attributes = 0;
1020 ldap_decode_attribs(msg->mem_ctx, data, &r->attributes,
1021 &r->num_attributes);
1027 case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1028 struct ldap_Result *r = &msg->r.AddResponse;
1029 msg->type = LDAP_TAG_AddResponse;
1030 asn1_start_tag(data, tag);
1031 ldap_decode_response(msg->mem_ctx, data, r);
1036 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1037 struct ldap_DelRequest *r = &msg->r.DelRequest;
1040 msg->type = LDAP_TAG_DelRequest;
1041 asn1_start_tag(data,
1042 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
1043 len = asn1_tag_remaining(data);
1044 dn = talloc(msg->mem_ctx, len+1);
1047 asn1_read(data, dn, len);
1054 case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1055 struct ldap_Result *r = &msg->r.DelResponse;
1056 msg->type = LDAP_TAG_DelResponse;
1057 asn1_start_tag(data, tag);
1058 ldap_decode_response(msg->mem_ctx, data, r);
1063 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1064 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1065 msg->type = LDAP_TAG_ModifyDNRequest;
1066 asn1_start_tag(data,
1067 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
1068 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
1069 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->newrdn);
1070 asn1_read_BOOLEAN(data, &r->deleteolddn);
1071 r->newsuperior = NULL;
1072 if (asn1_tag_remaining(data) > 0) {
1075 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1076 len = asn1_tag_remaining(data);
1077 newsup = talloc(msg->mem_ctx, len+1);
1080 asn1_read(data, newsup, len);
1082 r->newsuperior = newsup;
1089 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1090 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1091 msg->type = LDAP_TAG_ModifyDNResponse;
1092 asn1_start_tag(data, tag);
1093 ldap_decode_response(msg->mem_ctx, data, r);
1098 case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1099 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1100 msg->type = LDAP_TAG_CompareRequest;
1101 asn1_start_tag(data,
1102 ASN1_APPLICATION(LDAP_TAG_CompareRequest));
1103 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
1104 asn1_start_tag(data, ASN1_SEQUENCE(0));
1105 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->attribute);
1106 asn1_read_OctetString(data, &r->value);
1107 if (r->value.data) {
1108 talloc_steal(msg->mem_ctx, r->value.data);
1115 case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1116 struct ldap_Result *r = &msg->r.CompareResponse;
1117 msg->type = LDAP_TAG_CompareResponse;
1118 asn1_start_tag(data, tag);
1119 ldap_decode_response(msg->mem_ctx, data, r);
1124 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1125 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1126 msg->type = LDAP_TAG_AbandonRequest;
1127 asn1_start_tag(data, tag);
1128 asn1_read_implicit_Integer(data, &r->messageid);
1133 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1134 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1135 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1137 msg->type = LDAP_TAG_ExtendedRequest;
1138 asn1_start_tag(data,tag);
1139 if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
1142 r->oid = blob2string_talloc(msg->mem_ctx, tmp_blob);
1143 data_blob_free(&tmp_blob);
1148 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1149 asn1_read_ContextSimple(data, 1, &tmp_blob);
1150 r->value = data_blob_talloc(msg->mem_ctx, tmp_blob.data, tmp_blob.length);
1151 data_blob_free(&tmp_blob);
1153 r->value = data_blob(NULL, 0);
1160 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1161 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1162 msg->type = LDAP_TAG_ExtendedResponse;
1163 asn1_start_tag(data, tag);
1164 ldap_decode_response(msg->mem_ctx, data, &r->response);
1165 /* I have to come across an operation that actually sends
1166 * something back to really see what's going on. The currently
1167 * needed pwdchange does not send anything back. */
1169 r->value.data = NULL;
1170 r->value.length = 0;
1178 msg->num_controls = 0;
1179 msg->controls = NULL;
1181 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1183 struct ldap_Control *ctrl = NULL;
1185 asn1_start_tag(data, ASN1_CONTEXT(0));
1187 for (i=0; asn1_peek_tag(data, ASN1_SEQUENCE(0)); i++) {
1188 asn1_start_tag(data, ASN1_SEQUENCE(0));
1190 ctrl = talloc_realloc_p(msg->mem_ctx, ctrl, struct ldap_Control, i+1);
1195 ctrl[i].critical = False;
1196 ctrl[i].value = data_blob(NULL, 0);
1198 asn1_read_OctetString_talloc(ctrl, data, &ctrl[i].oid);
1200 if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
1201 asn1_read_BOOLEAN(data, &ctrl[i].critical);
1204 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
1205 asn1_read_OctetString(data, &ctrl[i].value);
1206 if (ctrl[i].value.data) {
1207 talloc_steal(msg->mem_ctx, ctrl[i].value.data);
1213 msg->num_controls = i;
1214 msg->controls = ctrl;
1220 return ((!data->has_error) && (data->nesting == NULL));
1223 BOOL ldap_parse_basic_url(TALLOC_CTX *mem_ctx, const char *url,
1224 char **host, uint16 *port, BOOL *ldaps)
1229 const char *p = url;
1232 /* skip leading "URL:" (if any) */
1233 if (strncasecmp( p, "URL:", 4) == 0) {
1237 /* Paranoia check */
1238 SMB_ASSERT(sizeof(protocol)>10 && sizeof(tmp_host)>254);
1240 ret = sscanf(p, "%10[^:]://%254[^:/]:%d", protocol, tmp_host, &tmp_port);
1245 if (strequal(protocol, "ldap")) {
1248 } else if (strequal(protocol, "ldaps")) {
1252 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
1259 *host = talloc_strdup(mem_ctx, tmp_host);
1261 return (*host != NULL);