2 Unix SMB/CIFS mplementation.
3 LDAP protocol helper functions for SAMBA
5 Copyright (C) Andrew Tridgell 2004
6 Copyright (C) Volker Lendecke 2004
7 Copyright (C) Stefan Metzmacher 2004
8 Copyright (C) Simo Sorce 2004
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #include "system/iconv.h"
29 #include "libcli/ldap/ldap.h"
31 /****************************************************************************
33 * LDAP filter parser -- main routine is ldap_parse_filter
35 * Shamelessly stolen and adapted from ldb.
37 ***************************************************************************/
40 return next token element. Caller frees
42 static char *ldap_parse_lex(TALLOC_CTX *mem_ctx, const char **s,
57 if (strchr(sep, *p)) {
59 ret = talloc_strndup(mem_ctx, p, 1);
66 while (*p && (isalnum(*p) || !strchr(sep, *p))) {
74 ret = talloc_strndup(mem_ctx, *s, p - *s);
86 find a matching close brace in a string
88 static const char *match_brace(const char *s)
90 unsigned int count = 0;
91 while (*s && (count != 0 || *s != ')')) {
106 static struct ldap_parse_tree *ldap_parse_filter(TALLOC_CTX *mem_ctx,
110 decode a RFC2254 binary string representation of a buffer.
111 Used in LDAP filters.
113 struct ldap_val ldap_binary_decode(TALLOC_CTX *mem_ctx, const char *str)
117 int slen = strlen(str);
119 ret.data = talloc_size(mem_ctx, slen);
121 if (ret.data == NULL) return ret;
123 for (i=j=0;i<slen;i++) {
124 if (str[i] == '\\') {
126 if (sscanf(&str[i+1], "%02X", &c) != 1) {
127 talloc_free(ret.data);
131 ((uint8_t *)ret.data)[j++] = c;
134 ((uint8_t *)ret.data)[j++] = str[i];
144 encode a blob as a RFC2254 binary string, escaping any
145 non-printable or '\' characters
147 const char *ldap_binary_encode(TALLOC_CTX *mem_ctx, DATA_BLOB blob)
151 int len = blob.length;
152 for (i=0;i<blob.length;i++) {
153 if (!isprint(blob.data[i]) || strchr(" *()\\&|!", blob.data[i])) {
157 ret = talloc_array(mem_ctx, char, len+1);
158 if (ret == NULL) return NULL;
161 for (i=0;i<blob.length;i++) {
162 if (!isprint(blob.data[i]) || strchr(" *()\\&|!", blob.data[i])) {
163 snprintf(ret+len, 4, "\\%02X", blob.data[i]);
166 ret[len++] = blob.data[i];
177 <simple> ::= <attributetype> <filtertype> <attributevalue>
179 static struct ldap_parse_tree *ldap_parse_simple(TALLOC_CTX *mem_ctx,
183 struct ldap_parse_tree *ret;
185 l = ldap_parse_lex(mem_ctx, &s, LDAP_ALL_SEP);
190 if (strchr("()&|=", *l))
193 eq = ldap_parse_lex(mem_ctx, &s, LDAP_ALL_SEP);
194 if (!eq || strcmp(eq, "=") != 0)
197 val = ldap_parse_lex(mem_ctx, &s, ")");
198 if (val && strchr("()&|", *val))
201 ret = talloc(mem_ctx, struct ldap_parse_tree);
207 ret->operation = LDAP_OP_SIMPLE;
208 ret->u.simple.attr = l;
209 ret->u.simple.value = ldap_binary_decode(ret, val);
217 <and> ::= '&' <filterlist>
218 <or> ::= '|' <filterlist>
219 <filterlist> ::= <filter> | <filter> <filterlist>
221 static struct ldap_parse_tree *ldap_parse_filterlist(TALLOC_CTX *mem_ctx,
222 enum ldap_parse_op op,
225 struct ldap_parse_tree *ret, *next;
227 ret = talloc(mem_ctx, struct ldap_parse_tree);
234 ret->u.list.num_elements = 1;
235 ret->u.list.elements = talloc(mem_ctx, struct ldap_parse_tree *);
236 if (!ret->u.list.elements) {
241 ret->u.list.elements[0] = ldap_parse_filter(mem_ctx, &s);
242 if (!ret->u.list.elements[0]) {
246 while (isspace(*s)) s++;
248 while (*s && (next = ldap_parse_filter(mem_ctx, &s))) {
249 struct ldap_parse_tree **e;
250 e = talloc_realloc(ret,
251 ret->u.list.elements,
252 struct ldap_parse_tree *,
253 ret->u.list.num_elements+1);
258 ret->u.list.elements = e;
259 ret->u.list.elements[ret->u.list.num_elements] = next;
260 ret->u.list.num_elements++;
261 while (isspace(*s)) s++;
269 <not> ::= '!' <filter>
271 static struct ldap_parse_tree *ldap_parse_not(TALLOC_CTX *mem_ctx, const char *s)
273 struct ldap_parse_tree *ret;
275 ret = talloc(mem_ctx, struct ldap_parse_tree);
281 ret->operation = LDAP_OP_NOT;
282 ret->u.not.child = ldap_parse_filter(mem_ctx, &s);
283 if (!ret->u.not.child)
291 <filtercomp> ::= <and> | <or> | <not> | <simple>
293 static struct ldap_parse_tree *ldap_parse_filtercomp(TALLOC_CTX *mem_ctx,
296 while (isspace(*s)) s++;
300 return ldap_parse_filterlist(mem_ctx, LDAP_OP_AND, s+1);
303 return ldap_parse_filterlist(mem_ctx, LDAP_OP_OR, s+1);
306 return ldap_parse_not(mem_ctx, s+1);
313 return ldap_parse_simple(mem_ctx, s);
318 <filter> ::= '(' <filtercomp> ')'
320 static struct ldap_parse_tree *ldap_parse_filter(TALLOC_CTX *mem_ctx,
325 struct ldap_parse_tree *ret;
327 l = ldap_parse_lex(mem_ctx, s, LDAP_ALL_SEP);
332 if (strcmp(l, "(") != 0) {
342 s2 = talloc_strndup(mem_ctx, *s, p - *s);
348 ret = ldap_parse_filtercomp(mem_ctx, s2);
356 main parser entry point. Takes a search string and returns a parse tree
358 expression ::= <simple> | <filter>
360 static struct ldap_parse_tree *ldap_parse_tree(TALLOC_CTX *mem_ctx, const char *s)
362 while (isspace(*s)) s++;
365 return ldap_parse_filter(mem_ctx, &s);
368 return ldap_parse_simple(mem_ctx, s);
371 static BOOL ldap_push_filter(struct asn1_data *data, struct ldap_parse_tree *tree)
373 switch (tree->operation) {
374 case LDAP_OP_SIMPLE: {
375 if ((tree->u.simple.value.length == 1) &&
376 (((char *)(tree->u.simple.value.data))[0] == '*')) {
377 /* Just a presence test */
378 asn1_push_tag(data, 0x87);
379 asn1_write(data, tree->u.simple.attr,
380 strlen(tree->u.simple.attr));
382 return !data->has_error;
385 /* Equality is all we currently do... */
386 asn1_push_tag(data, 0xa3);
387 asn1_write_OctetString(data, tree->u.simple.attr,
388 strlen(tree->u.simple.attr));
389 asn1_write_OctetString(data, tree->u.simple.value.data,
390 tree->u.simple.value.length);
398 asn1_push_tag(data, 0xa0);
399 for (i=0; i<tree->u.list.num_elements; i++) {
400 ldap_push_filter(data, tree->u.list.elements[i]);
409 asn1_push_tag(data, 0xa1);
410 for (i=0; i<tree->u.list.num_elements; i++) {
411 ldap_push_filter(data, tree->u.list.elements[i]);
419 return !data->has_error;
422 static void ldap_encode_response(struct asn1_data *data, struct ldap_Result *result)
424 asn1_write_enumerated(data, result->resultcode);
425 asn1_write_OctetString(data, result->dn,
426 (result->dn) ? strlen(result->dn) : 0);
427 asn1_write_OctetString(data, result->errormessage,
428 (result->errormessage) ?
429 strlen(result->errormessage) : 0);
430 if (result->referral) {
431 asn1_push_tag(data, ASN1_CONTEXT(3));
432 asn1_write_OctetString(data, result->referral,
433 strlen(result->referral));
438 BOOL ldap_encode(struct ldap_message *msg, DATA_BLOB *result)
440 struct asn1_data data;
444 asn1_push_tag(&data, ASN1_SEQUENCE(0));
445 asn1_write_Integer(&data, msg->messageid);
448 case LDAP_TAG_BindRequest: {
449 struct ldap_BindRequest *r = &msg->r.BindRequest;
450 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
451 asn1_write_Integer(&data, r->version);
452 asn1_write_OctetString(&data, r->dn,
453 (r->dn != NULL) ? strlen(r->dn) : 0);
455 switch (r->mechanism) {
456 case LDAP_AUTH_MECH_SIMPLE:
457 /* context, primitive */
458 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
459 asn1_write(&data, r->creds.password,
460 strlen(r->creds.password));
463 case LDAP_AUTH_MECH_SASL:
464 /* context, constructed */
465 asn1_push_tag(&data, ASN1_CONTEXT(3));
466 asn1_write_OctetString(&data, r->creds.SASL.mechanism,
467 strlen(r->creds.SASL.mechanism));
468 asn1_write_OctetString(&data, r->creds.SASL.secblob.data,
469 r->creds.SASL.secblob.length);
480 case LDAP_TAG_BindResponse: {
481 struct ldap_BindResponse *r = &msg->r.BindResponse;
482 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
483 ldap_encode_response(&data, &r->response);
484 if (r->SASL.secblob.length > 0) {
485 asn1_write_ContextSimple(&data, 7, &r->SASL.secblob);
490 case LDAP_TAG_UnbindRequest: {
491 /* struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
494 case LDAP_TAG_SearchRequest: {
495 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
496 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
497 asn1_write_OctetString(&data, r->basedn, strlen(r->basedn));
498 asn1_write_enumerated(&data, r->scope);
499 asn1_write_enumerated(&data, r->deref);
500 asn1_write_Integer(&data, r->sizelimit);
501 asn1_write_Integer(&data, r->timelimit);
502 asn1_write_BOOLEAN(&data, r->attributesonly);
505 TALLOC_CTX *mem_ctx = talloc_init("ldap_parse_tree");
506 struct ldap_parse_tree *tree;
511 tree = ldap_parse_tree(mem_ctx, r->filter);
516 ldap_push_filter(&data, tree);
518 talloc_free(mem_ctx);
521 asn1_push_tag(&data, ASN1_SEQUENCE(0));
522 for (i=0; i<r->num_attributes; i++) {
523 asn1_write_OctetString(&data, r->attributes[i],
524 strlen(r->attributes[i]));
531 case LDAP_TAG_SearchResultEntry: {
532 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
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));
536 for (i=0; i<r->num_attributes; i++) {
537 struct ldap_attribute *attr = &r->attributes[i];
538 asn1_push_tag(&data, ASN1_SEQUENCE(0));
539 asn1_write_OctetString(&data, attr->name,
541 asn1_push_tag(&data, ASN1_SEQUENCE(1));
542 for (j=0; j<attr->num_values; j++) {
543 asn1_write_OctetString(&data,
544 attr->values[j].data,
545 attr->values[j].length);
554 case LDAP_TAG_SearchResultDone: {
555 struct ldap_Result *r = &msg->r.SearchResultDone;
556 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
557 ldap_encode_response(&data, r);
561 case LDAP_TAG_ModifyRequest: {
562 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
563 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
564 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
565 asn1_push_tag(&data, ASN1_SEQUENCE(0));
567 for (i=0; i<r->num_mods; i++) {
568 struct ldap_attribute *attrib = &r->mods[i].attrib;
569 asn1_push_tag(&data, ASN1_SEQUENCE(0));
570 asn1_write_enumerated(&data, r->mods[i].type);
571 asn1_push_tag(&data, ASN1_SEQUENCE(0));
572 asn1_write_OctetString(&data, attrib->name,
573 strlen(attrib->name));
574 asn1_push_tag(&data, ASN1_SET);
575 for (j=0; j<attrib->num_values; j++) {
576 asn1_write_OctetString(&data,
577 attrib->values[j].data,
578 attrib->values[j].length);
590 case LDAP_TAG_ModifyResponse: {
591 struct ldap_Result *r = &msg->r.ModifyResponse;
592 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
593 ldap_encode_response(&data, r);
597 case LDAP_TAG_AddRequest: {
598 struct ldap_AddRequest *r = &msg->r.AddRequest;
599 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
600 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
601 asn1_push_tag(&data, ASN1_SEQUENCE(0));
603 for (i=0; i<r->num_attributes; i++) {
604 struct ldap_attribute *attrib = &r->attributes[i];
605 asn1_push_tag(&data, ASN1_SEQUENCE(0));
606 asn1_write_OctetString(&data, attrib->name,
607 strlen(attrib->name));
608 asn1_push_tag(&data, ASN1_SET);
609 for (j=0; j<r->attributes[i].num_values; j++) {
610 asn1_write_OctetString(&data,
611 attrib->values[j].data,
612 attrib->values[j].length);
621 case LDAP_TAG_AddResponse: {
622 struct ldap_Result *r = &msg->r.AddResponse;
623 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
624 ldap_encode_response(&data, r);
628 case LDAP_TAG_DelRequest: {
629 struct ldap_DelRequest *r = &msg->r.DelRequest;
630 asn1_push_tag(&data, ASN1_APPLICATION_SIMPLE(msg->type));
631 asn1_write(&data, r->dn, strlen(r->dn));
635 case LDAP_TAG_DelResponse: {
636 struct ldap_Result *r = &msg->r.DelResponse;
637 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
638 ldap_encode_response(&data, r);
642 case LDAP_TAG_ModifyDNRequest: {
643 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
644 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
645 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
646 asn1_write_OctetString(&data, r->newrdn, strlen(r->newrdn));
647 asn1_write_BOOLEAN(&data, r->deleteolddn);
648 if (r->newsuperior != NULL) {
649 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
650 asn1_write(&data, r->newsuperior,
651 strlen(r->newsuperior));
657 case LDAP_TAG_ModifyDNResponse: {
658 struct ldap_Result *r = &msg->r.ModifyDNResponse;
659 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
660 ldap_encode_response(&data, r);
664 case LDAP_TAG_CompareRequest: {
665 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
666 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
667 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
668 asn1_push_tag(&data, ASN1_SEQUENCE(0));
669 asn1_write_OctetString(&data, r->attribute,
670 strlen(r->attribute));
671 asn1_write_OctetString(&data, r->value.data,
677 case LDAP_TAG_CompareResponse: {
678 struct ldap_Result *r = &msg->r.ModifyDNResponse;
679 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
680 ldap_encode_response(&data, r);
684 case LDAP_TAG_AbandonRequest: {
685 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
686 asn1_push_tag(&data, ASN1_APPLICATION_SIMPLE(msg->type));
687 asn1_write_implicit_Integer(&data, r->messageid);
691 case LDAP_TAG_SearchResultReference: {
692 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
693 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
694 asn1_write_OctetString(&data, r->referral, strlen(r->referral));
698 case LDAP_TAG_ExtendedRequest: {
699 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
700 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
701 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
702 asn1_write(&data, r->oid, strlen(r->oid));
704 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(1));
705 asn1_write(&data, r->value.data, r->value.length);
710 case LDAP_TAG_ExtendedResponse: {
711 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
712 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
713 ldap_encode_response(&data, &r->response);
722 *result = data_blob(data.data, data.length);
727 static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
730 char *result = talloc_size(mem_ctx, blob.length+1);
731 memcpy(result, blob.data, blob.length);
732 result[blob.length] = '\0';
736 static BOOL asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
737 struct asn1_data *data,
741 if (!asn1_read_OctetString(data, &string))
743 *result = blob2string_talloc(mem_ctx, string);
744 data_blob_free(&string);
748 static void ldap_decode_response(TALLOC_CTX *mem_ctx,
749 struct asn1_data *data,
750 struct ldap_Result *result)
752 asn1_read_enumerated(data, &result->resultcode);
753 asn1_read_OctetString_talloc(mem_ctx, data, &result->dn);
754 asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage);
755 if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
756 asn1_start_tag(data, ASN1_CONTEXT(3));
757 asn1_read_OctetString_talloc(mem_ctx, data, &result->referral);
760 result->referral = NULL;
764 static BOOL ldap_decode_filter(TALLOC_CTX *mem_ctx, struct asn1_data *data,
765 const char **filterp)
767 uint8_t filter_tag, tag_desc;
772 if (!asn1_peek_uint8(data, &filter_tag))
775 tag_desc = filter_tag;
776 filter_tag &= 0x1f; /* strip off the asn1 stuff */
781 /* AND of one or more filters */
782 if (tag_desc != 0xa0) /* context compount */
785 asn1_start_tag(data, ASN1_CONTEXT(0));
787 filter = talloc_strdup(mem_ctx, "(&");
791 while (asn1_tag_remaining(data) > 0) {
792 const char *subfilter;
793 if (!ldap_decode_filter(mem_ctx, data, &subfilter))
795 filter = talloc_asprintf_append(filter, "%s", subfilter);
801 filter = talloc_asprintf_append(filter, ")");
805 /* OR of one or more filters */
806 if (tag_desc != 0xa0) /* context compount */
809 asn1_start_tag(data, ASN1_CONTEXT(1));
811 filter = talloc_strdup(mem_ctx, "(|");
815 while (asn1_tag_remaining(data) > 0) {
816 const char *subfilter;
817 if (!ldap_decode_filter(mem_ctx, data, &subfilter))
819 filter = talloc_asprintf_append(filter, "%s", subfilter);
826 filter = talloc_asprintf_append(filter, ")");
833 if (tag_desc != 0xa0) /* context compound */
835 asn1_start_tag(data, ASN1_CONTEXT(3));
836 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
837 asn1_read_OctetString(data, &value);
839 if ((data->has_error) || (attrib == NULL) || (value.data == NULL))
841 filter = talloc_asprintf(mem_ctx, "(%s=%s)",
842 attrib, ldap_binary_encode(mem_ctx, value));
843 data_blob_free(&value);
847 /* Normal presence, "attribute=*" */
850 if (tag_desc != 0x80) /* context simple */
852 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(7)))
854 attr_len = asn1_tag_remaining(data);
855 attr_name = malloc(attr_len+1);
856 if (attr_name == NULL)
858 asn1_read(data, attr_name, attr_len);
859 attr_name[attr_len] = '\0';
860 filter = talloc_asprintf(mem_ctx, "(%s=*)", attr_name);
861 SAFE_FREE(attr_name);
876 static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
877 struct ldap_attribute *attrib)
879 asn1_start_tag(data, ASN1_SEQUENCE(0));
880 asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name);
881 asn1_start_tag(data, ASN1_SET);
882 while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
884 struct ldap_val value;
885 asn1_read_OctetString(data, &blob);
886 value.data = blob.data;
887 value.length = blob.length;
888 add_value_to_attrib(mem_ctx, &value, attrib);
889 data_blob_free(&blob);
896 static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
897 struct ldap_attribute **attributes,
900 asn1_start_tag(data, ASN1_SEQUENCE(0));
901 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
902 struct ldap_attribute attrib;
904 ldap_decode_attrib(mem_ctx, data, &attrib);
905 add_attrib_to_array_talloc(mem_ctx, &attrib,
906 attributes, num_attributes);
911 BOOL ldap_decode(struct asn1_data *data, struct ldap_message *msg)
915 asn1_start_tag(data, ASN1_SEQUENCE(0));
916 asn1_read_Integer(data, &msg->messageid);
918 if (!asn1_peek_uint8(data, &tag))
923 case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
924 struct ldap_BindRequest *r = &msg->r.BindRequest;
925 msg->type = LDAP_TAG_BindRequest;
926 asn1_start_tag(data, tag);
927 asn1_read_Integer(data, &r->version);
928 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
929 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
931 r->creds.password = "";
932 r->mechanism = LDAP_AUTH_MECH_SIMPLE;
933 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
934 pwlen = asn1_tag_remaining(data);
936 char *pw = talloc_size(msg->mem_ctx, pwlen+1);
937 asn1_read(data, pw, pwlen);
939 r->creds.password = pw;
942 } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
943 asn1_start_tag(data, ASN1_CONTEXT(3));
944 r->mechanism = LDAP_AUTH_MECH_SASL;
945 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->creds.SASL.mechanism);
946 asn1_read_OctetString(data, &r->creds.SASL.secblob);
947 if (r->creds.SASL.secblob.data) {
948 talloc_steal(msg->mem_ctx, r->creds.SASL.secblob.data);
956 case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
957 struct ldap_BindResponse *r = &msg->r.BindResponse;
958 msg->type = LDAP_TAG_BindResponse;
959 asn1_start_tag(data, tag);
960 ldap_decode_response(msg->mem_ctx, data, &r->response);
961 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
962 DATA_BLOB tmp_blob = data_blob(NULL, 0);
963 asn1_read_ContextSimple(data, 7, &tmp_blob);
964 r->SASL.secblob = data_blob_talloc(msg->mem_ctx, tmp_blob.data, tmp_blob.length);
965 data_blob_free(&tmp_blob);
967 r->SASL.secblob = data_blob(NULL, 0);
973 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
974 msg->type = LDAP_TAG_UnbindRequest;
975 asn1_start_tag(data, tag);
980 case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
981 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
982 msg->type = LDAP_TAG_SearchRequest;
983 asn1_start_tag(data, tag);
984 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->basedn);
985 asn1_read_enumerated(data, (int *)&(r->scope));
986 asn1_read_enumerated(data, (int *)&(r->deref));
987 asn1_read_Integer(data, &r->sizelimit);
988 asn1_read_Integer(data, &r->timelimit);
989 asn1_read_BOOLEAN(data, &r->attributesonly);
991 /* Maybe create a TALLOC_CTX for the filter? This can waste
992 * quite a bit of memory recursing down. */
993 ldap_decode_filter(msg->mem_ctx, data, &r->filter);
995 asn1_start_tag(data, ASN1_SEQUENCE(0));
997 r->num_attributes = 0;
998 r->attributes = NULL;
1000 while (asn1_tag_remaining(data) > 0) {
1002 if (!asn1_read_OctetString_talloc(msg->mem_ctx, data,
1005 if (!add_string_to_array(msg->mem_ctx, attr,
1007 &r->num_attributes))
1016 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1017 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1018 msg->type = LDAP_TAG_SearchResultEntry;
1019 r->attributes = NULL;
1020 r->num_attributes = 0;
1021 asn1_start_tag(data, tag);
1022 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
1023 ldap_decode_attribs(msg->mem_ctx, data, &r->attributes,
1024 &r->num_attributes);
1029 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1030 struct ldap_Result *r = &msg->r.SearchResultDone;
1031 msg->type = LDAP_TAG_SearchResultDone;
1032 asn1_start_tag(data, tag);
1033 ldap_decode_response(msg->mem_ctx, data, r);
1038 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1039 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
1040 msg->type = LDAP_TAG_SearchResultReference;
1041 asn1_start_tag(data, tag);
1042 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->referral);
1047 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1048 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1049 msg->type = LDAP_TAG_ModifyRequest;
1050 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
1051 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
1052 asn1_start_tag(data, ASN1_SEQUENCE(0));
1057 while (asn1_tag_remaining(data) > 0) {
1058 struct ldap_mod mod;
1061 asn1_start_tag(data, ASN1_SEQUENCE(0));
1062 asn1_read_enumerated(data, &v);
1064 ldap_decode_attrib(msg->mem_ctx, data, &mod.attrib);
1066 if (!add_mod_to_array_talloc(msg->mem_ctx, &mod,
1067 &r->mods, &r->num_mods))
1076 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1077 struct ldap_Result *r = &msg->r.ModifyResponse;
1078 msg->type = LDAP_TAG_ModifyResponse;
1079 asn1_start_tag(data, tag);
1080 ldap_decode_response(msg->mem_ctx, data, r);
1085 case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1086 struct ldap_AddRequest *r = &msg->r.AddRequest;
1087 msg->type = LDAP_TAG_AddRequest;
1088 asn1_start_tag(data, tag);
1089 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
1091 r->attributes = NULL;
1092 r->num_attributes = 0;
1093 ldap_decode_attribs(msg->mem_ctx, data, &r->attributes,
1094 &r->num_attributes);
1100 case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1101 struct ldap_Result *r = &msg->r.AddResponse;
1102 msg->type = LDAP_TAG_AddResponse;
1103 asn1_start_tag(data, tag);
1104 ldap_decode_response(msg->mem_ctx, data, r);
1109 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1110 struct ldap_DelRequest *r = &msg->r.DelRequest;
1113 msg->type = LDAP_TAG_DelRequest;
1114 asn1_start_tag(data,
1115 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
1116 len = asn1_tag_remaining(data);
1117 dn = talloc_size(msg->mem_ctx, len+1);
1120 asn1_read(data, dn, len);
1127 case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1128 struct ldap_Result *r = &msg->r.DelResponse;
1129 msg->type = LDAP_TAG_DelResponse;
1130 asn1_start_tag(data, tag);
1131 ldap_decode_response(msg->mem_ctx, data, r);
1136 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1137 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1138 msg->type = LDAP_TAG_ModifyDNRequest;
1139 asn1_start_tag(data,
1140 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
1141 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
1142 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->newrdn);
1143 asn1_read_BOOLEAN(data, &r->deleteolddn);
1144 r->newsuperior = NULL;
1145 if (asn1_tag_remaining(data) > 0) {
1148 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1149 len = asn1_tag_remaining(data);
1150 newsup = talloc_size(msg->mem_ctx, len+1);
1153 asn1_read(data, newsup, len);
1155 r->newsuperior = newsup;
1162 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1163 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1164 msg->type = LDAP_TAG_ModifyDNResponse;
1165 asn1_start_tag(data, tag);
1166 ldap_decode_response(msg->mem_ctx, data, r);
1171 case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1172 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1173 msg->type = LDAP_TAG_CompareRequest;
1174 asn1_start_tag(data,
1175 ASN1_APPLICATION(LDAP_TAG_CompareRequest));
1176 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
1177 asn1_start_tag(data, ASN1_SEQUENCE(0));
1178 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->attribute);
1179 asn1_read_OctetString(data, &r->value);
1180 if (r->value.data) {
1181 talloc_steal(msg->mem_ctx, r->value.data);
1188 case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1189 struct ldap_Result *r = &msg->r.CompareResponse;
1190 msg->type = LDAP_TAG_CompareResponse;
1191 asn1_start_tag(data, tag);
1192 ldap_decode_response(msg->mem_ctx, data, r);
1197 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1198 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1199 msg->type = LDAP_TAG_AbandonRequest;
1200 asn1_start_tag(data, tag);
1201 asn1_read_implicit_Integer(data, &r->messageid);
1206 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1207 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1208 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1210 msg->type = LDAP_TAG_ExtendedRequest;
1211 asn1_start_tag(data,tag);
1212 if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
1215 r->oid = blob2string_talloc(msg->mem_ctx, tmp_blob);
1216 data_blob_free(&tmp_blob);
1221 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1222 asn1_read_ContextSimple(data, 1, &tmp_blob);
1223 r->value = data_blob_talloc(msg->mem_ctx, tmp_blob.data, tmp_blob.length);
1224 data_blob_free(&tmp_blob);
1226 r->value = data_blob(NULL, 0);
1233 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1234 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1235 msg->type = LDAP_TAG_ExtendedResponse;
1236 asn1_start_tag(data, tag);
1237 ldap_decode_response(msg->mem_ctx, data, &r->response);
1238 /* I have to come across an operation that actually sends
1239 * something back to really see what's going on. The currently
1240 * needed pwdchange does not send anything back. */
1242 r->value.data = NULL;
1243 r->value.length = 0;
1251 msg->num_controls = 0;
1252 msg->controls = NULL;
1254 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1256 struct ldap_Control *ctrl = NULL;
1258 asn1_start_tag(data, ASN1_CONTEXT(0));
1260 for (i=0; asn1_peek_tag(data, ASN1_SEQUENCE(0)); i++) {
1261 asn1_start_tag(data, ASN1_SEQUENCE(0));
1263 ctrl = talloc_realloc(msg->mem_ctx, ctrl, struct ldap_Control, i+1);
1268 ctrl[i].critical = False;
1269 ctrl[i].value = data_blob(NULL, 0);
1271 asn1_read_OctetString_talloc(ctrl, data, &ctrl[i].oid);
1273 if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
1274 asn1_read_BOOLEAN(data, &ctrl[i].critical);
1277 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
1278 asn1_read_OctetString(data, &ctrl[i].value);
1279 if (ctrl[i].value.data) {
1280 talloc_steal(msg->mem_ctx, ctrl[i].value.data);
1286 msg->num_controls = i;
1287 msg->controls = ctrl;
1293 return ((!data->has_error) && (data->nesting == NULL));
1296 BOOL ldap_parse_basic_url(TALLOC_CTX *mem_ctx, const char *url,
1297 char **host, uint16_t *port, BOOL *ldaps)
1302 const char *p = url;
1305 /* skip leading "URL:" (if any) */
1306 if (strncasecmp( p, "URL:", 4) == 0) {
1310 /* Paranoia check */
1311 SMB_ASSERT(sizeof(protocol)>10 && sizeof(tmp_host)>254);
1313 ret = sscanf(p, "%10[^:]://%254[^:/]:%d", protocol, tmp_host, &tmp_port);
1318 if (strequal(protocol, "ldap")) {
1321 } else if (strequal(protocol, "ldaps")) {
1325 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
1332 *host = talloc_strdup(mem_ctx, tmp_host);
1334 return (*host != NULL);
1340 externally callable version of filter string parsing - used in the
1343 struct ldap_parse_tree *ldap_parse_filter_string(TALLOC_CTX *mem_ctx,
1346 return ldap_parse_filter(mem_ctx, &s);