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.
28 /****************************************************************************
30 * LDAP filter parser -- main routine is ldap_parse_filter
32 * Shamelessly stolen and adapted from ldb.
34 ***************************************************************************/
37 return next token element. Caller frees
39 static char *ldap_parse_lex(TALLOC_CTX *mem_ctx, const char **s,
54 if (strchr(sep, *p)) {
56 ret = talloc_strndup(mem_ctx, p, 1);
63 while (*p && (isalnum(*p) || !strchr(sep, *p))) {
71 ret = talloc_strndup(mem_ctx, *s, p - *s);
83 find a matching close brace in a string
85 static const char *match_brace(const char *s)
87 unsigned int count = 0;
88 while (*s && (count != 0 || *s != ')')) {
103 static struct ldap_parse_tree *ldap_parse_filter(TALLOC_CTX *mem_ctx,
107 <simple> ::= <attributetype> <filtertype> <attributevalue>
109 static struct ldap_parse_tree *ldap_parse_simple(TALLOC_CTX *mem_ctx,
113 struct ldap_parse_tree *ret;
115 l = ldap_parse_lex(mem_ctx, &s, LDAP_ALL_SEP);
120 if (strchr("()&|=", *l))
123 eq = ldap_parse_lex(mem_ctx, &s, LDAP_ALL_SEP);
124 if (!eq || strcmp(eq, "=") != 0)
127 val = ldap_parse_lex(mem_ctx, &s, ")");
128 if (val && strchr("()&|", *val))
131 ret = talloc(mem_ctx, sizeof(*ret));
137 ret->operation = LDAP_OP_SIMPLE;
138 ret->u.simple.attr = l;
139 ret->u.simple.value.data = val;
140 ret->u.simple.value.length = val?strlen(val):0;
148 <and> ::= '&' <filterlist>
149 <or> ::= '|' <filterlist>
150 <filterlist> ::= <filter> | <filter> <filterlist>
152 static struct ldap_parse_tree *ldap_parse_filterlist(TALLOC_CTX *mem_ctx,
153 enum ldap_parse_op op,
156 struct ldap_parse_tree *ret, *next;
158 ret = talloc(mem_ctx, sizeof(*ret));
166 ret->u.list.num_elements = 1;
167 ret->u.list.elements = talloc(mem_ctx, sizeof(*ret->u.list.elements));
168 if (!ret->u.list.elements) {
173 ret->u.list.elements[0] = ldap_parse_filter(mem_ctx, &s);
174 if (!ret->u.list.elements[0]) {
178 while (isspace(*s)) s++;
180 while (*s && (next = ldap_parse_filter(mem_ctx, &s))) {
181 struct ldap_parse_tree **e;
182 e = talloc_realloc_p(ret,
183 ret->u.list.elements,
184 struct ldap_parse_tree *,
185 ret->u.list.num_elements+1);
190 ret->u.list.elements = e;
191 ret->u.list.elements[ret->u.list.num_elements] = next;
192 ret->u.list.num_elements++;
193 while (isspace(*s)) s++;
201 <not> ::= '!' <filter>
203 static struct ldap_parse_tree *ldap_parse_not(TALLOC_CTX *mem_ctx, const char *s)
205 struct ldap_parse_tree *ret;
207 ret = talloc(mem_ctx, sizeof(*ret));
213 ret->operation = LDAP_OP_NOT;
214 ret->u.not.child = ldap_parse_filter(mem_ctx, &s);
215 if (!ret->u.not.child)
223 <filtercomp> ::= <and> | <or> | <not> | <simple>
225 static struct ldap_parse_tree *ldap_parse_filtercomp(TALLOC_CTX *mem_ctx,
228 while (isspace(*s)) s++;
232 return ldap_parse_filterlist(mem_ctx, LDAP_OP_AND, s+1);
235 return ldap_parse_filterlist(mem_ctx, LDAP_OP_OR, s+1);
238 return ldap_parse_not(mem_ctx, s+1);
245 return ldap_parse_simple(mem_ctx, s);
250 <filter> ::= '(' <filtercomp> ')'
252 static struct ldap_parse_tree *ldap_parse_filter(TALLOC_CTX *mem_ctx,
257 struct ldap_parse_tree *ret;
259 l = ldap_parse_lex(mem_ctx, s, LDAP_ALL_SEP);
264 if (strcmp(l, "(") != 0) {
274 s2 = talloc_strndup(mem_ctx, *s, p - *s);
280 ret = ldap_parse_filtercomp(mem_ctx, s2);
288 main parser entry point. Takes a search string and returns a parse tree
290 expression ::= <simple> | <filter>
292 static struct ldap_parse_tree *ldap_parse_tree(TALLOC_CTX *mem_ctx, const char *s)
294 while (isspace(*s)) s++;
297 return ldap_parse_filter(mem_ctx, &s);
300 return ldap_parse_simple(mem_ctx, s);
303 static BOOL ldap_push_filter(ASN1_DATA *data, struct ldap_parse_tree *tree)
305 switch (tree->operation) {
306 case LDAP_OP_SIMPLE: {
307 if ((tree->u.simple.value.length == 1) &&
308 (((char *)(tree->u.simple.value.data))[0] == '*')) {
309 /* Just a presence test */
310 asn1_push_tag(data, 0x87);
311 asn1_write(data, tree->u.simple.attr,
312 strlen(tree->u.simple.attr));
314 return !data->has_error;
317 /* Equality is all we currently do... */
318 asn1_push_tag(data, 0xa3);
319 asn1_write_OctetString(data, tree->u.simple.attr,
320 strlen(tree->u.simple.attr));
321 asn1_write_OctetString(data, tree->u.simple.value.data,
322 tree->u.simple.value.length);
330 asn1_push_tag(data, 0xa0);
331 for (i=0; i<tree->u.list.num_elements; i++) {
332 ldap_push_filter(data, tree->u.list.elements[i]);
341 asn1_push_tag(data, 0xa1);
342 for (i=0; i<tree->u.list.num_elements; i++) {
343 ldap_push_filter(data, tree->u.list.elements[i]);
351 return !data->has_error;
354 static void ldap_encode_response(enum ldap_request_tag tag,
355 struct ldap_Result *result,
358 asn1_push_tag(data, ASN1_APPLICATION(tag));
359 asn1_write_enumerated(data, result->resultcode);
360 asn1_write_OctetString(data, result->dn,
361 (result->dn) ? strlen(result->dn) : 0);
362 asn1_write_OctetString(data, result->errormessage,
363 (result->errormessage) ?
364 strlen(result->errormessage) : 0);
365 if (result->referral != NULL)
366 asn1_write_OctetString(data, result->referral,
367 strlen(result->referral));
371 BOOL ldap_encode(struct ldap_message *msg, DATA_BLOB *result)
377 asn1_push_tag(&data, ASN1_SEQUENCE(0));
378 asn1_write_Integer(&data, msg->messageid);
381 case LDAP_TAG_BindRequest: {
382 struct ldap_BindRequest *r = &msg->r.BindRequest;
383 asn1_push_tag(&data, ASN1_APPLICATION(LDAP_TAG_BindRequest));
384 asn1_write_Integer(&data, r->version);
385 asn1_write_OctetString(&data, r->dn,
386 (r->dn != NULL) ? strlen(r->dn) : 0);
388 switch (r->mechanism) {
389 case LDAP_AUTH_MECH_SIMPLE:
390 /* context, primitive */
391 asn1_push_tag(&data, r->mechanism | 0x80);
392 asn1_write(&data, r->creds.password,
393 strlen(r->creds.password));
396 case LDAP_AUTH_MECH_SASL:
397 /* context, constructed */
398 asn1_push_tag(&data, r->mechanism | 0xa0);
399 asn1_write_OctetString(&data, r->creds.SASL.mechanism,
400 strlen(r->creds.SASL.mechanism));
401 asn1_write_OctetString(&data, r->creds.SASL.secblob.data,
402 r->creds.SASL.secblob.length);
413 case LDAP_TAG_BindResponse: {
414 struct ldap_BindResponse *r = &msg->r.BindResponse;
415 ldap_encode_response(msg->type, &r->response, &data);
418 case LDAP_TAG_UnbindRequest: {
419 /* struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
422 case LDAP_TAG_SearchRequest: {
423 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
424 asn1_push_tag(&data, ASN1_APPLICATION(LDAP_TAG_SearchRequest));
425 asn1_write_OctetString(&data, r->basedn, strlen(r->basedn));
426 asn1_write_enumerated(&data, r->scope);
427 asn1_write_enumerated(&data, r->deref);
428 asn1_write_Integer(&data, r->sizelimit);
429 asn1_write_Integer(&data, r->timelimit);
430 asn1_write_BOOLEAN(&data, r->attributesonly);
433 TALLOC_CTX *mem_ctx = talloc_init("ldap_parse_tree");
434 struct ldap_parse_tree *tree;
439 tree = ldap_parse_tree(mem_ctx, r->filter);
444 ldap_push_filter(&data, tree);
446 talloc_destroy(mem_ctx);
449 asn1_push_tag(&data, ASN1_SEQUENCE(0));
450 for (i=0; i<r->num_attributes; i++) {
451 asn1_write_OctetString(&data, r->attributes[i],
452 strlen(r->attributes[i]));
459 case LDAP_TAG_SearchResultEntry: {
460 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
461 asn1_push_tag(&data, ASN1_APPLICATION(LDAP_TAG_SearchResultEntry));
462 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
463 asn1_push_tag(&data, ASN1_SEQUENCE(0));
464 for (i=0; i<r->num_attributes; i++) {
465 struct ldap_attribute *attr = &r->attributes[i];
466 asn1_push_tag(&data, ASN1_SEQUENCE(0));
467 asn1_write_OctetString(&data, attr->name,
469 asn1_push_tag(&data, ASN1_SEQUENCE(1));
470 for (j=0; j<attr->num_values; j++) {
471 asn1_write_OctetString(&data,
472 attr->values[j].data,
473 attr->values[j].length);
482 case LDAP_TAG_SearchResultDone: {
483 struct ldap_Result *r = &msg->r.SearchResultDone;
484 ldap_encode_response(msg->type, r, &data);
487 case LDAP_TAG_ModifyRequest: {
488 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
489 asn1_push_tag(&data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
490 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
491 asn1_push_tag(&data, ASN1_SEQUENCE(0));
493 for (i=0; i<r->num_mods; i++) {
494 struct ldap_attribute *attrib = &r->mods[i].attrib;
495 asn1_push_tag(&data, ASN1_SEQUENCE(0));
496 asn1_write_enumerated(&data, r->mods[i].type);
497 asn1_push_tag(&data, ASN1_SEQUENCE(0));
498 asn1_write_OctetString(&data, attrib->name,
499 strlen(attrib->name));
500 asn1_push_tag(&data, ASN1_SET);
501 for (j=0; j<attrib->num_values; j++) {
502 asn1_write_OctetString(&data,
503 attrib->values[j].data,
504 attrib->values[j].length);
516 case LDAP_TAG_ModifyResponse: {
517 struct ldap_Result *r = &msg->r.ModifyResponse;
518 ldap_encode_response(msg->type, r, &data);
521 case LDAP_TAG_AddRequest: {
522 struct ldap_AddRequest *r = &msg->r.AddRequest;
523 asn1_push_tag(&data, ASN1_APPLICATION(LDAP_TAG_AddRequest));
524 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
525 asn1_push_tag(&data, ASN1_SEQUENCE(0));
527 for (i=0; i<r->num_attributes; i++) {
528 struct ldap_attribute *attrib = &r->attributes[i];
529 asn1_push_tag(&data, ASN1_SEQUENCE(0));
530 asn1_write_OctetString(&data, attrib->name,
531 strlen(attrib->name));
532 asn1_push_tag(&data, ASN1_SET);
533 for (j=0; j<r->attributes[i].num_values; j++) {
534 asn1_write_OctetString(&data,
535 attrib->values[j].data,
536 attrib->values[j].length);
545 case LDAP_TAG_AddResponse: {
546 struct ldap_Result *r = &msg->r.AddResponse;
547 ldap_encode_response(msg->type, r, &data);
550 case LDAP_TAG_DelRequest: {
551 struct ldap_DelRequest *r = &msg->r.DelRequest;
553 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
554 asn1_write(&data, r->dn, strlen(r->dn));
558 case LDAP_TAG_DelResponse: {
559 struct ldap_Result *r = &msg->r.DelResponse;
560 ldap_encode_response(msg->type, r, &data);
563 case LDAP_TAG_ModifyDNRequest: {
564 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
566 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
567 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
568 asn1_write_OctetString(&data, r->newrdn, strlen(r->newrdn));
569 asn1_write_BOOLEAN(&data, r->deleteolddn);
570 if (r->newsuperior != NULL) {
571 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
572 asn1_write(&data, r->newsuperior,
573 strlen(r->newsuperior));
579 case LDAP_TAG_ModifyDNResponse: {
580 struct ldap_Result *r = &msg->r.ModifyDNResponse;
581 ldap_encode_response(msg->type, r, &data);
584 case LDAP_TAG_CompareRequest: {
585 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
587 ASN1_APPLICATION(LDAP_TAG_CompareRequest));
588 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
589 asn1_push_tag(&data, ASN1_SEQUENCE(0));
590 asn1_write_OctetString(&data, r->attribute,
591 strlen(r->attribute));
592 asn1_write_OctetString(&data, r->value.data,
598 case LDAP_TAG_CompareResponse: {
599 struct ldap_Result *r = &msg->r.ModifyDNResponse;
600 ldap_encode_response(msg->type, r, &data);
603 case LDAP_TAG_AbandonRequest: {
604 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
606 ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest));
607 asn1_write_implicit_Integer(&data, r->messageid);
611 case LDAP_TAG_SearchResultReference: {
612 /* struct ldap_SearchResRef *r = &msg->r.SearchResultReference; */
615 case LDAP_TAG_ExtendedRequest: {
616 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
617 asn1_push_tag(&data, ASN1_APPLICATION(LDAP_TAG_ExtendedRequest));
618 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
619 asn1_write(&data, r->oid, strlen(r->oid));
621 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(1));
622 asn1_write(&data, r->value.data, r->value.length);
627 case LDAP_TAG_ExtendedResponse: {
628 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
629 ldap_encode_response(msg->type, &r->response, &data);
637 *result = data_blob(data.data, data.length);
642 static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
645 char *result = talloc(mem_ctx, blob.length+1);
646 memcpy(result, blob.data, blob.length);
647 result[blob.length] = '\0';
651 static BOOL asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
656 if (!asn1_read_OctetString(data, &string))
658 *result = blob2string_talloc(mem_ctx, string);
659 data_blob_free(&string);
663 static void ldap_decode_response(TALLOC_CTX *mem_ctx,
665 enum ldap_request_tag tag,
666 struct ldap_Result *result)
668 asn1_start_tag(data, ASN1_APPLICATION(tag));
669 asn1_read_enumerated(data, &result->resultcode);
670 asn1_read_OctetString_talloc(mem_ctx, data, &result->dn);
671 asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage);
672 if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
673 asn1_start_tag(data, ASN1_CONTEXT(3));
674 asn1_read_OctetString_talloc(mem_ctx, data, &result->referral);
677 result->referral = NULL;
682 static BOOL ldap_decode_filter(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
685 uint8 filter_tag, tag_desc;
687 if (!asn1_peek_uint8(data, &filter_tag))
690 tag_desc = filter_tag;
691 filter_tag &= 0x1f; /* strip off the asn1 stuff */
696 /* AND of one or more filters */
697 if (tag_desc != 0xa0) /* context compount */
700 asn1_start_tag(data, ASN1_CONTEXT(0));
702 *filter = talloc_strdup(mem_ctx, "(&");
706 while (asn1_tag_remaining(data) > 0) {
708 if (!ldap_decode_filter(mem_ctx, data, &subfilter))
710 *filter = talloc_asprintf(mem_ctx, "%s%s", *filter,
717 *filter = talloc_asprintf(mem_ctx, "%s)", *filter);
721 /* OR of one or more filters */
722 if (tag_desc != 0xa0) /* context compount */
725 asn1_start_tag(data, ASN1_CONTEXT(1));
727 *filter = talloc_strdup(mem_ctx, "(|");
731 while (asn1_tag_remaining(data) > 0) {
733 if (!ldap_decode_filter(mem_ctx, data, &subfilter))
735 *filter = talloc_asprintf(mem_ctx, "%s%s", *filter,
743 *filter = talloc_asprintf(mem_ctx, "%s)", *filter);
748 const char *attrib, *value;
749 if (tag_desc != 0xa0) /* context compound */
751 asn1_start_tag(data, ASN1_CONTEXT(3));
752 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
753 asn1_read_OctetString_talloc(mem_ctx, data, &value);
755 if ((data->has_error) || (attrib == NULL) || (value == NULL))
757 *filter = talloc_asprintf(mem_ctx, "(%s=%s)", attrib, value);
761 /* Normal presence, "attribute=*" */
764 if (tag_desc != 0x80) /* context simple */
766 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(7)))
768 attr_len = asn1_tag_remaining(data);
769 attr_name = malloc(attr_len+1);
770 if (attr_name == NULL)
772 asn1_read(data, attr_name, attr_len);
773 attr_name[attr_len] = '\0';
774 *filter = talloc_asprintf(mem_ctx, "(%s=*)", attr_name);
775 SAFE_FREE(attr_name);
787 static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
788 struct ldap_attribute *attrib)
790 asn1_start_tag(data, ASN1_SEQUENCE(0));
791 asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name);
792 asn1_start_tag(data, ASN1_SET);
793 while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
795 struct ldap_val value;
796 asn1_read_OctetString(data, &blob);
797 value.data = blob.data;
798 value.length = blob.length;
799 add_value_to_attrib(mem_ctx, &value, attrib);
800 data_blob_free(&blob);
807 static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
808 struct ldap_attribute **attributes,
811 asn1_start_tag(data, ASN1_SEQUENCE(0));
812 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
813 struct ldap_attribute attrib;
815 ldap_decode_attrib(mem_ctx, data, &attrib);
816 add_attrib_to_array_talloc(mem_ctx, &attrib,
817 attributes, num_attributes);
822 BOOL ldap_decode(ASN1_DATA *data, struct ldap_message *msg)
826 asn1_start_tag(data, ASN1_SEQUENCE(0));
827 asn1_read_Integer(data, &msg->messageid);
829 if (!asn1_peek_uint8(data, &tag))
834 case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
835 struct ldap_BindRequest *r = &msg->r.BindRequest;
836 msg->type = LDAP_TAG_BindRequest;
837 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_BindRequest));
838 asn1_read_Integer(data, &r->version);
839 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
840 if (asn1_peek_tag(data, 0x80)) {
842 r->creds.password = "";
843 /* Mechanism 0 (SIMPLE) */
844 asn1_start_tag(data, 0x80);
845 pwlen = asn1_tag_remaining(data);
847 char *pw = talloc(msg->mem_ctx, pwlen+1);
848 asn1_read(data, pw, pwlen);
850 r->creds.password = pw;
858 case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
859 struct ldap_BindResponse *r = &msg->r.BindResponse;
860 msg->type = LDAP_TAG_BindResponse;
861 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_BindResponse));
862 asn1_read_enumerated(data, &r->response.resultcode);
863 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->response.dn);
864 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->response.errormessage);
865 if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
866 asn1_start_tag(data, ASN1_CONTEXT(3));
867 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->response.referral);
870 r->response.referral = NULL;
872 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
873 DATA_BLOB tmp_blob = data_blob(NULL, 0);
874 asn1_read_ContextSimple(data, 7, &tmp_blob);
875 r->SASL.secblob = data_blob_talloc(msg->mem_ctx, tmp_blob.data, tmp_blob.length);
876 data_blob_free(&tmp_blob);
878 r->SASL.secblob = data_blob(NULL, 0);
884 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
885 msg->type = LDAP_TAG_UnbindRequest;
886 asn1_start_tag(data, ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest));
891 case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
892 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
893 msg->type = LDAP_TAG_SearchRequest;
894 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_SearchRequest));
895 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->basedn);
896 asn1_read_enumerated(data, (int *)&(r->scope));
897 asn1_read_enumerated(data, (int *)&(r->deref));
898 asn1_read_Integer(data, &r->sizelimit);
899 asn1_read_Integer(data, &r->timelimit);
900 asn1_read_BOOLEAN(data, &r->attributesonly);
902 /* Maybe create a TALLOC_CTX for the filter? This can waste
903 * quite a bit of memory recursing down. */
904 ldap_decode_filter(msg->mem_ctx, data, &r->filter);
906 asn1_start_tag(data, ASN1_SEQUENCE(0));
908 r->num_attributes = 0;
909 r->attributes = NULL;
911 while (asn1_tag_remaining(data) > 0) {
913 if (!asn1_read_OctetString_talloc(msg->mem_ctx, data,
916 if (!add_string_to_array(msg->mem_ctx, attr,
927 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
928 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
929 msg->type = LDAP_TAG_SearchResultEntry;
930 r->attributes = NULL;
931 r->num_attributes = 0;
933 ASN1_APPLICATION(LDAP_TAG_SearchResultEntry));
934 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
935 ldap_decode_attribs(msg->mem_ctx, data, &r->attributes,
941 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
942 struct ldap_Result *r = &msg->r.SearchResultDone;
943 msg->type = LDAP_TAG_SearchResultDone;
944 ldap_decode_response(msg->mem_ctx, data,
945 LDAP_TAG_SearchResultDone, r);
949 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
950 /* struct ldap_SearchResRef *r = &msg->r.SearchResultReference; */
951 msg->type = LDAP_TAG_SearchResultReference;
955 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
956 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
957 msg->type = LDAP_TAG_ModifyRequest;
958 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
959 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
960 asn1_start_tag(data, ASN1_SEQUENCE(0));
965 while (asn1_tag_remaining(data) > 0) {
968 asn1_start_tag(data, ASN1_SEQUENCE(0));
969 asn1_read_enumerated(data, &mod.type);
970 ldap_decode_attrib(msg->mem_ctx, data, &mod.attrib);
972 if (!add_mod_to_array_talloc(msg->mem_ctx, &mod,
973 &r->mods, &r->num_mods))
982 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
983 struct ldap_Result *r = &msg->r.ModifyResponse;
984 msg->type = LDAP_TAG_ModifyResponse;
985 ldap_decode_response(msg->mem_ctx, data,
986 LDAP_TAG_ModifyResponse, r);
990 case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
991 struct ldap_AddRequest *r = &msg->r.AddRequest;
992 msg->type = LDAP_TAG_AddRequest;
993 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_AddRequest));
994 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
996 r->attributes = NULL;
997 r->num_attributes = 0;
998 ldap_decode_attribs(msg->mem_ctx, data, &r->attributes,
1005 case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1006 struct ldap_Result *r = &msg->r.AddResponse;
1007 msg->type = LDAP_TAG_AddResponse;
1008 ldap_decode_response(msg->mem_ctx, data,
1009 LDAP_TAG_AddResponse, r);
1013 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1014 struct ldap_DelRequest *r = &msg->r.DelRequest;
1017 msg->type = LDAP_TAG_DelRequest;
1018 asn1_start_tag(data,
1019 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
1020 len = asn1_tag_remaining(data);
1021 dn = talloc(msg->mem_ctx, len+1);
1024 asn1_read(data, dn, len);
1031 case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1032 struct ldap_Result *r = &msg->r.DelResponse;
1033 msg->type = LDAP_TAG_DelResponse;
1034 ldap_decode_response(msg->mem_ctx, data,
1035 LDAP_TAG_DelResponse, r);
1039 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1040 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1041 msg->type = LDAP_TAG_ModifyDNRequest;
1042 asn1_start_tag(data,
1043 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
1044 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
1045 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->newrdn);
1046 asn1_read_BOOLEAN(data, &r->deleteolddn);
1047 r->newsuperior = NULL;
1048 if (asn1_tag_remaining(data) > 0) {
1051 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1052 len = asn1_tag_remaining(data);
1053 newsup = talloc(msg->mem_ctx, len+1);
1056 asn1_read(data, newsup, len);
1058 r->newsuperior = newsup;
1065 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1066 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1067 msg->type = LDAP_TAG_ModifyDNResponse;
1068 ldap_decode_response(msg->mem_ctx, data,
1069 LDAP_TAG_ModifyDNResponse, r);
1073 case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1074 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1075 msg->type = LDAP_TAG_CompareRequest;
1076 asn1_start_tag(data,
1077 ASN1_APPLICATION(LDAP_TAG_CompareRequest));
1078 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
1079 asn1_start_tag(data, ASN1_SEQUENCE(0));
1080 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->attribute);
1081 asn1_read_OctetString(data, &r->value);
1082 if (r->value.data) {
1083 talloc_steal(msg->mem_ctx, r->value.data);
1090 case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1091 struct ldap_Result *r = &msg->r.CompareResponse;
1092 msg->type = LDAP_TAG_CompareResponse;
1093 ldap_decode_response(msg->mem_ctx, data,
1094 LDAP_TAG_CompareResponse, r);
1098 case ASN1_APPLICATION(LDAP_TAG_AbandonRequest): {
1099 /* struct ldap_AbandonRequest *r = &msg->r.AbandonRequest; */
1100 msg->type = LDAP_TAG_AbandonRequest;
1104 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1105 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1106 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1108 msg->type = LDAP_TAG_ExtendedRequest;
1109 asn1_start_tag(data,ASN1_APPLICATION(LDAP_TAG_ExtendedRequest));
1110 if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
1113 r->oid = blob2string_talloc(msg->mem_ctx, tmp_blob);
1114 data_blob_free(&tmp_blob);
1119 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1120 asn1_read_ContextSimple(data, 1, &tmp_blob);
1121 r->value = data_blob_talloc(msg->mem_ctx, tmp_blob.data, tmp_blob.length);
1122 data_blob_free(&tmp_blob);
1124 r->value = data_blob(NULL, 0);
1131 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1132 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1133 msg->type = LDAP_TAG_ExtendedResponse;
1134 ldap_decode_response(msg->mem_ctx, data,
1135 LDAP_TAG_ExtendedResponse, &r->response);
1136 /* I have to come across an operation that actually sends
1137 * something back to really see what's going on. The currently
1138 * needed pwdchange does not send anything back. */
1140 r->value.data = NULL;
1141 r->value.length = 0;
1149 return ((!data->has_error) && (data->nesting == NULL));
1152 BOOL ldap_parse_basic_url(TALLOC_CTX *mem_ctx, const char *url,
1153 char **host, uint16 *port, BOOL *ldaps)
1158 const char *p = url;
1160 /* skip leading "URL:" (if any) */
1161 if (strncasecmp( p, "URL:", 4) == 0) {
1165 /* Paranoia check */
1166 SMB_ASSERT(sizeof(protocol)>10 && sizeof(tmp_host)>254);
1168 sscanf(p, "%10[^:]://%254[^:/]:%d", protocol, tmp_host, &tmp_port);
1170 if (strequal(protocol, "ldap")) {
1173 } else if (strequal(protocol, "ldaps")) {
1177 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
1184 *host = talloc_strdup(mem_ctx, tmp_host);
1186 return (*host != NULL);
1189 struct ldap_connection *new_ldap_connection(void)
1191 TALLOC_CTX *mem_ctx = talloc_init("ldap_connection");
1192 struct ldap_connection *result;
1194 if (mem_ctx == NULL)
1197 result = talloc(mem_ctx, sizeof(*result));
1202 result->mem_ctx = mem_ctx;
1203 result->next_msgid = 1;
1204 result->outstanding = NULL;
1205 result->searchid = 0;
1206 result->search_entries = NULL;
1207 result->auth_dn = NULL;
1208 result->simple_pw = NULL;
1209 result->gensec = NULL;
1214 BOOL ldap_connect(struct ldap_connection *conn, const char *url)
1219 if (!ldap_parse_basic_url(conn->mem_ctx, url, &conn->host,
1220 &conn->port, &conn->ldaps))
1223 hp = sys_gethostbyname(conn->host);
1225 if ((hp == NULL) || (hp->h_addr == NULL))
1228 putip((char *)&ip, (char *)hp->h_addr);
1230 conn->sock = open_socket_out(SOCK_STREAM, &ip, conn->port, LDAP_CONNECTION_TIMEOUT);
1232 return (conn->sock >= 0);
1235 BOOL ldap_set_simple_creds(struct ldap_connection *conn,
1236 const char *dn, const char *password)
1238 conn->auth_dn = talloc_strdup(conn->mem_ctx, dn);
1239 conn->simple_pw = talloc_strdup(conn->mem_ctx, password);
1241 return ((conn->auth_dn != NULL) && (conn->simple_pw != NULL));
1244 struct ldap_message *new_ldap_message(void)
1246 TALLOC_CTX *mem_ctx = talloc_init("ldap_message");
1247 struct ldap_message *result;
1249 if (mem_ctx == NULL)
1252 result = talloc(mem_ctx, sizeof(*result));
1257 result->mem_ctx = mem_ctx;
1261 void destroy_ldap_message(struct ldap_message *msg)
1264 talloc_destroy(msg->mem_ctx);
1267 BOOL ldap_send_msg(struct ldap_connection *conn, struct ldap_message *msg,
1268 const struct timeval *endtime)
1272 struct ldap_queue_entry *entry;
1274 msg->messageid = conn->next_msgid++;
1276 if (!ldap_encode(msg, &request))
1279 result = (write_data_until(conn->sock, request.data, request.length,
1280 endtime) == request.length);
1282 data_blob_free(&request);
1287 /* abandon and unbind don't expect results */
1289 if ((msg->type == LDAP_TAG_AbandonRequest) ||
1290 (msg->type == LDAP_TAG_UnbindRequest))
1293 entry = malloc(sizeof(*entry));
1298 entry->msgid = msg->messageid;
1300 DLIST_ADD(conn->outstanding, entry);
1305 BOOL ldap_receive_msg(struct ldap_connection *conn, struct ldap_message *msg,
1306 const struct timeval *endtime)
1308 struct asn1_data data;
1311 if (!asn1_read_sequence_until(conn->sock, &data, endtime))
1314 result = ldap_decode(&data, msg);
1320 static struct ldap_message *recv_from_queue(struct ldap_connection *conn,
1323 struct ldap_queue_entry *e;
1325 for (e = conn->outstanding; e != NULL; e = e->next) {
1327 if (e->msgid == msgid) {
1328 struct ldap_message *result = e->msg;
1329 DLIST_REMOVE(conn->outstanding, e);
1338 static void add_search_entry(struct ldap_connection *conn,
1339 struct ldap_message *msg)
1341 struct ldap_queue_entry *e = malloc(sizeof *e);
1347 DLIST_ADD_END(conn->search_entries, e, struct ldap_queue_entry *);
1351 static void fill_outstanding_request(struct ldap_connection *conn,
1352 struct ldap_message *msg)
1354 struct ldap_queue_entry *e;
1356 for (e = conn->outstanding; e != NULL; e = e->next) {
1357 if (e->msgid == msg->messageid) {
1363 /* This reply has not been expected, destroy the incoming msg */
1364 destroy_ldap_message(msg);
1368 struct ldap_message *ldap_receive(struct ldap_connection *conn, int msgid,
1369 const struct timeval *endtime)
1371 struct ldap_message *result = recv_from_queue(conn, msgid);
1377 struct asn1_data data;
1380 result = new_ldap_message();
1382 if (!asn1_read_sequence_until(conn->sock, &data, endtime))
1385 res = ldap_decode(&data, result);
1391 if (result->messageid == msgid)
1394 if (result->type == LDAP_TAG_SearchResultEntry) {
1395 add_search_entry(conn, result);
1397 fill_outstanding_request(conn, result);
1404 struct ldap_message *ldap_transaction(struct ldap_connection *conn,
1405 struct ldap_message *request)
1407 if (!ldap_send_msg(conn, request, NULL))
1410 return ldap_receive(conn, request->messageid, NULL);
1413 int ldap_bind_simple(struct ldap_connection *conn, const char *userdn, const char *password)
1415 struct ldap_message *response;
1416 struct ldap_message *msg;
1417 const char *dn, *pw;
1418 int result = LDAP_OTHER;
1426 if (conn->auth_dn) {
1436 if (conn->simple_pw) {
1437 pw = conn->simple_pw;
1443 msg = new_ldap_simple_bind_msg(dn, pw);
1447 response = ldap_transaction(conn, msg);
1449 destroy_ldap_message(msg);
1453 result = response->r.BindResponse.response.resultcode;
1455 destroy_ldap_message(msg);
1456 destroy_ldap_message(response);
1461 int ldap_bind_sasl(struct ldap_connection *conn, const char *username, const char *domain, const char *password)
1464 TALLOC_CTX *mem_ctx = NULL;
1465 struct ldap_message *response;
1466 struct ldap_message *msg;
1467 DATA_BLOB input = data_blob(NULL, 0);
1468 DATA_BLOB output = data_blob(NULL, 0);
1469 int result = LDAP_OTHER;
1474 status = gensec_client_start(conn, &conn->gensec);
1475 if (!NT_STATUS_IS_OK(status)) {
1476 DEBUG(0, ("Failed to start GENSEC engine (%s)\n", nt_errstr(status)));
1480 status = gensec_set_domain(conn->gensec, domain);
1481 if (!NT_STATUS_IS_OK(status)) {
1482 DEBUG(1, ("Failed to start set GENSEC client domain to %s: %s\n",
1483 domain, nt_errstr(status)));
1487 status = gensec_set_username(conn->gensec, username);
1488 if (!NT_STATUS_IS_OK(status)) {
1489 DEBUG(1, ("Failed to start set GENSEC client username to %s: %s\n",
1490 username, nt_errstr(status)));
1494 status = gensec_set_password(conn->gensec, password);
1495 if (!NT_STATUS_IS_OK(status)) {
1496 DEBUG(1, ("Failed to start set GENSEC client password: %s\n",
1497 nt_errstr(status)));
1501 status = gensec_set_target_hostname(conn->gensec, conn->host);
1502 if (!NT_STATUS_IS_OK(status)) {
1503 DEBUG(1, ("Failed to start set GENSEC target hostname: %s\n",
1504 nt_errstr(status)));
1508 status = gensec_start_mech_by_sasl_name(conn->gensec, "GSS-SPNEGO");
1509 if (!NT_STATUS_IS_OK(status)) {
1510 DEBUG(1, ("Failed to start set GENSEC client SPNEGO mechanism: %s\n",
1511 nt_errstr(status)));
1515 mem_ctx = talloc_init("ldap_bind_sasl");
1519 status = gensec_update(conn->gensec, mem_ctx,
1524 if (NT_STATUS_IS_OK(status) && output.length == 0) {
1527 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
1531 msg = new_ldap_sasl_bind_msg("GSS-SPNEGO", &output);
1535 response = ldap_transaction(conn, msg);
1536 destroy_ldap_message(msg);
1542 result = response->r.BindResponse.response.resultcode;
1544 if (result != LDAP_SUCCESS && result != LDAP_SASL_BIND_IN_PROGRESS) {
1548 status = gensec_update(conn->gensec, mem_ctx,
1549 response->r.BindResponse.SASL.secblob,
1552 destroy_ldap_message(response);
1557 gensec_end(&conn->gensec);
1559 talloc_destroy(mem_ctx);
1564 BOOL ldap_setup_connection(struct ldap_connection *conn,
1565 const char *url, const char *userdn, const char *password)
1569 if (!ldap_connect(conn, url)) {
1573 result = ldap_bind_simple(conn, userdn, password);
1574 if (result == LDAP_SUCCESS) {
1581 BOOL ldap_setup_connection_with_sasl(struct ldap_connection *conn, const char *url, const char *username, const char *domain, const char *password)
1585 if (!ldap_connect(conn, url)) {
1589 result = ldap_bind_sasl(conn, username, domain, password);
1590 if (result == LDAP_SUCCESS) {
1597 static BOOL ldap_abandon_message(struct ldap_connection *conn, int msgid,
1598 const struct timeval *endtime)
1600 struct ldap_message *msg = new_ldap_message();
1606 msg->type = LDAP_TAG_AbandonRequest;
1607 msg->r.AbandonRequest.messageid = msgid;
1609 result = ldap_send_msg(conn, msg, endtime);
1610 destroy_ldap_message(msg);
1614 struct ldap_message *new_ldap_search_message(const char *base,
1615 enum ldap_scope scope,
1618 const char **attributes)
1620 struct ldap_message *res = new_ldap_message();
1625 res->type = LDAP_TAG_SearchRequest;
1626 res->r.SearchRequest.basedn = base;
1627 res->r.SearchRequest.scope = scope;
1628 res->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
1629 res->r.SearchRequest.timelimit = 0;
1630 res->r.SearchRequest.sizelimit = 0;
1631 res->r.SearchRequest.attributesonly = False;
1632 res->r.SearchRequest.filter = filter;
1633 res->r.SearchRequest.num_attributes = num_attributes;
1634 res->r.SearchRequest.attributes = attributes;
1638 struct ldap_message *new_ldap_simple_bind_msg(const char *dn, const char *pw)
1640 struct ldap_message *res = new_ldap_message();
1645 res->type = LDAP_TAG_BindRequest;
1646 res->r.BindRequest.version = 3;
1647 res->r.BindRequest.dn = talloc_strdup(res->mem_ctx, dn);
1648 res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SIMPLE;
1649 res->r.BindRequest.creds.password = talloc_strdup(res->mem_ctx, pw);
1653 struct ldap_message *new_ldap_sasl_bind_msg(const char *sasl_mechanism, DATA_BLOB *secblob)
1655 struct ldap_message *res = new_ldap_message();
1660 res->type = LDAP_TAG_BindRequest;
1661 res->r.BindRequest.version = 3;
1662 res->r.BindRequest.dn = "";
1663 res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SASL;
1664 res->r.BindRequest.creds.SASL.mechanism = talloc_strdup(res->mem_ctx, sasl_mechanism);
1665 res->r.BindRequest.creds.SASL.secblob = *secblob;
1669 BOOL ldap_setsearchent(struct ldap_connection *conn, struct ldap_message *msg,
1670 const struct timeval *endtime)
1672 if ((conn->searchid != 0) &&
1673 (!ldap_abandon_message(conn, conn->searchid, endtime)))
1676 conn->searchid = conn->next_msgid;
1677 return ldap_send_msg(conn, msg, endtime);
1680 struct ldap_message *ldap_getsearchent(struct ldap_connection *conn,
1681 const struct timeval *endtime)
1683 struct ldap_message *result;
1685 if (conn->search_entries != NULL) {
1686 struct ldap_queue_entry *e = conn->search_entries;
1689 DLIST_REMOVE(conn->search_entries, e);
1694 result = ldap_receive(conn, conn->searchid, endtime);
1696 if (result->type == LDAP_TAG_SearchResultEntry)
1699 if (result->type == LDAP_TAG_SearchResultDone) {
1700 /* TODO: Handle Paged Results */
1701 destroy_ldap_message(result);
1705 /* TODO: Handle Search References here */
1709 void ldap_endsearchent(struct ldap_connection *conn,
1710 const struct timeval *endtime)
1712 struct ldap_queue_entry *e;
1714 e = conn->search_entries;
1717 struct ldap_queue_entry *next = e->next;
1718 DLIST_REMOVE(conn->search_entries, e);
1724 struct ldap_message *ldap_searchone(struct ldap_connection *conn,
1725 struct ldap_message *msg,
1726 const struct timeval *endtime)
1728 struct ldap_message *res1, *res2 = NULL;
1729 if (!ldap_setsearchent(conn, msg, endtime))
1732 res1 = ldap_getsearchent(conn, endtime);
1735 res2 = ldap_getsearchent(conn, endtime);
1737 ldap_endsearchent(conn, endtime);
1743 /* More than one entry */
1744 destroy_ldap_message(res1);
1745 destroy_ldap_message(res2);
1752 BOOL ldap_find_single_value(struct ldap_message *msg, const char *attr,
1756 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1758 if (msg->type != LDAP_TAG_SearchResultEntry)
1761 for (i=0; i<r->num_attributes; i++) {
1762 if (strequal(attr, r->attributes[i].name)) {
1763 if (r->attributes[i].num_values != 1)
1766 *value = r->attributes[i].values[0];
1773 BOOL ldap_find_single_string(struct ldap_message *msg, const char *attr,
1774 TALLOC_CTX *mem_ctx, char **value)
1778 if (!ldap_find_single_value(msg, attr, &blob))
1781 *value = talloc(mem_ctx, blob.length+1);
1786 memcpy(*value, blob.data, blob.length);
1787 (*value)[blob.length] = '\0';
1791 BOOL ldap_find_single_int(struct ldap_message *msg, const char *attr,
1799 if (!ldap_find_single_value(msg, attr, &blob))
1802 val = malloc(blob.length+1);
1806 memcpy(val, blob.data, blob.length);
1807 val[blob.length] = '\0';
1812 *value = strtol(val, NULL, 10);
1822 int ldap_error(struct ldap_connection *conn)
1827 NTSTATUS ldap2nterror(int ldaperror)
1829 return NT_STATUS_OK;