2 Unix SMB/CIFS mplementation.
3 LDAP protocol helper functions for SAMBA
5 Copyright (C) Andrew Tridgell 2004
6 Copyright (C) Volker Lendecke 2004
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /****************************************************************************
28 * LDAP filter parser -- main routine is ldap_parse_filter
30 * Shamelessly stolen and adapted from ldb.
32 ***************************************************************************/
34 /* Hmm. A blob might be more appropriate here :-) */
41 enum ldap_parse_op {LDAP_OP_SIMPLE, LDAP_OP_AND, LDAP_OP_OR, LDAP_OP_NOT};
43 struct ldap_parse_tree {
44 enum ldap_parse_op operation;
48 struct ldap_val value;
51 unsigned int num_elements;
52 struct ldap_parse_tree **elements;
55 struct ldap_parse_tree *child;
60 #define LDAP_ALL_SEP "()&|=!"
61 #define LDAP_CONNECTION_TIMEOUT 10000
64 return next token element. Caller frees
66 static char *ldap_parse_lex(TALLOC_CTX *mem_ctx, const char **s,
81 if (strchr(sep, *p)) {
83 ret = talloc_strndup(mem_ctx, p, 1);
90 while (*p && (isalnum(*p) || !strchr(sep, *p))) {
98 ret = talloc_strndup(mem_ctx, *s, p - *s);
110 find a matching close brace in a string
112 static const char *match_brace(const char *s)
114 unsigned int count = 0;
115 while (*s && (count != 0 || *s != ')')) {
130 static struct ldap_parse_tree *ldap_parse_filter(TALLOC_CTX *mem_ctx,
134 <simple> ::= <attributetype> <filtertype> <attributevalue>
136 static struct ldap_parse_tree *ldap_parse_simple(TALLOC_CTX *mem_ctx,
140 struct ldap_parse_tree *ret;
142 l = ldap_parse_lex(mem_ctx, &s, LDAP_ALL_SEP);
147 if (strchr("()&|=", *l))
150 eq = ldap_parse_lex(mem_ctx, &s, LDAP_ALL_SEP);
151 if (!eq || strcmp(eq, "=") != 0)
154 val = ldap_parse_lex(mem_ctx, &s, ")");
155 if (val && strchr("()&|", *val))
158 ret = talloc(mem_ctx, sizeof(*ret));
164 ret->operation = LDAP_OP_SIMPLE;
165 ret->u.simple.attr = l;
166 ret->u.simple.value.data = val;
167 ret->u.simple.value.length = val?strlen(val):0;
175 <and> ::= '&' <filterlist>
176 <or> ::= '|' <filterlist>
177 <filterlist> ::= <filter> | <filter> <filterlist>
179 static struct ldap_parse_tree *ldap_parse_filterlist(TALLOC_CTX *mem_ctx,
180 enum ldap_parse_op op,
183 struct ldap_parse_tree *ret, *next;
185 ret = talloc(mem_ctx, sizeof(*ret));
193 ret->u.list.num_elements = 1;
194 ret->u.list.elements = talloc(mem_ctx, sizeof(*ret->u.list.elements));
195 if (!ret->u.list.elements) {
200 ret->u.list.elements[0] = ldap_parse_filter(mem_ctx, &s);
201 if (!ret->u.list.elements[0]) {
205 while (isspace(*s)) s++;
207 while (*s && (next = ldap_parse_filter(mem_ctx, &s))) {
208 struct ldap_parse_tree **e;
209 e = talloc_realloc(mem_ctx, ret->u.list.elements,
210 sizeof(struct ldap_parse_tree) *
211 (ret->u.list.num_elements+1));
216 ret->u.list.elements = e;
217 ret->u.list.elements[ret->u.list.num_elements] = next;
218 ret->u.list.num_elements++;
219 while (isspace(*s)) s++;
227 <not> ::= '!' <filter>
229 static struct ldap_parse_tree *ldap_parse_not(TALLOC_CTX *mem_ctx, const char *s)
231 struct ldap_parse_tree *ret;
233 ret = talloc(mem_ctx, sizeof(*ret));
239 ret->operation = LDAP_OP_NOT;
240 ret->u.not.child = ldap_parse_filter(mem_ctx, &s);
241 if (!ret->u.not.child)
249 <filtercomp> ::= <and> | <or> | <not> | <simple>
251 static struct ldap_parse_tree *ldap_parse_filtercomp(TALLOC_CTX *mem_ctx,
254 while (isspace(*s)) s++;
258 return ldap_parse_filterlist(mem_ctx, LDAP_OP_AND, s+1);
261 return ldap_parse_filterlist(mem_ctx, LDAP_OP_OR, s+1);
264 return ldap_parse_not(mem_ctx, s+1);
271 return ldap_parse_simple(mem_ctx, s);
276 <filter> ::= '(' <filtercomp> ')'
278 static struct ldap_parse_tree *ldap_parse_filter(TALLOC_CTX *mem_ctx,
283 struct ldap_parse_tree *ret;
285 l = ldap_parse_lex(mem_ctx, s, LDAP_ALL_SEP);
290 if (strcmp(l, "(") != 0) {
300 s2 = talloc_strndup(mem_ctx, *s, p - *s);
306 ret = ldap_parse_filtercomp(mem_ctx, s2);
314 main parser entry point. Takes a search string and returns a parse tree
316 expression ::= <simple> | <filter>
318 static struct ldap_parse_tree *ldap_parse_tree(TALLOC_CTX *mem_ctx, const char *s)
320 while (isspace(*s)) s++;
323 return ldap_parse_filter(mem_ctx, &s);
326 return ldap_parse_simple(mem_ctx, s);
329 static BOOL ldap_push_filter(ASN1_DATA *data, struct ldap_parse_tree *tree)
331 switch (tree->operation) {
332 case LDAP_OP_SIMPLE: {
333 if ((tree->u.simple.value.length == 1) &&
334 (((char *)(tree->u.simple.value.data))[0] == '*')) {
335 /* Just a presence test */
336 asn1_push_tag(data, 0x87);
337 asn1_write(data, tree->u.simple.attr,
338 strlen(tree->u.simple.attr));
340 return !data->has_error;
343 /* Equality is all we currently do... */
344 asn1_push_tag(data, 0xa3);
345 asn1_write_OctetString(data, tree->u.simple.attr,
346 strlen(tree->u.simple.attr));
347 asn1_write_OctetString(data, tree->u.simple.value.data,
348 tree->u.simple.value.length);
356 asn1_push_tag(data, 0xa0);
357 for (i=0; i<tree->u.list.num_elements; i++) {
358 ldap_push_filter(data, tree->u.list.elements[i]);
367 asn1_push_tag(data, 0xa1);
368 for (i=0; i<tree->u.list.num_elements; i++) {
369 ldap_push_filter(data, tree->u.list.elements[i]);
377 return !data->has_error;
380 /****************************************************************************
384 * Shamelessly stolen and adapted from Samba 4.
386 ***************************************************************************/
389 pull a ldif chunk, which is defined as a piece of data ending in \n\n or EOF
390 this routine removes any RFC2849 continuations and comments
394 static char *next_chunk(TALLOC_CTX *mem_ctx,
395 int (*fgetc_fn)(void *), void *private_data)
397 size_t alloc_size=0, chunk_size = 0;
402 while ((c = fgetc_fn(private_data)) != EOF) {
403 if (chunk_size+1 >= alloc_size) {
406 c2 = talloc_realloc(mem_ctx, chunk, alloc_size);
421 /* handle continuation lines - see RFC2849 */
422 if (c == ' ' && chunk_size > 1 &&
423 chunk[chunk_size-1] == '\n') {
428 /* chunks are terminated by a double line-feed */
429 if (c == '\n' && chunk_size > 0 &&
430 chunk[chunk_size-1] == '\n') {
431 chunk[chunk_size-1] = 0;
436 (chunk_size == 0 || chunk[chunk_size-1] == '\n')) {
441 /* ignore leading blank lines */
442 if (chunk_size == 0 && c == '\n') {
446 chunk[chunk_size++] = c;
450 chunk[chunk_size] = 0;
456 /* simple ldif attribute parser */
457 static int next_attr(char **s, const char **attr, struct ldap_val *value)
460 int base64_encoded = 0;
462 if (strncmp(*s, "-\n", 2) == 0) {
483 while (isspace(*p)) {
492 value->length = strlen((char *)value->data);
493 *s = ((char *)value->data) + value->length;
495 value->length = p - (char *)value->data;
500 if (base64_encoded) {
501 DATA_BLOB blob = base64_decode_data_blob(value->data);
502 memcpy(value->data, blob.data, blob.length);
503 value->length = blob.length;
504 ((char *)value->data)[value->length] = '\0';
510 static BOOL add_value_to_attrib(TALLOC_CTX *mem_ctx, struct ldap_val *value,
511 struct ldap_attribute *attrib)
513 attrib->values = talloc_realloc(mem_ctx, attrib->values,
514 sizeof(*attrib->values) *
515 (attrib->num_values+1));
516 if (attrib->values == NULL)
519 attrib->values[attrib->num_values] =
520 data_blob_talloc(mem_ctx, value->data, value->length);
521 attrib->num_values += 1;
525 static BOOL fill_add_attributes(struct ldap_message *msg, char **chunk)
527 struct ldap_AddRequest *r = &msg->r.AddRequest;
528 const char *attr_name;
529 struct ldap_val value;
531 r->num_attributes = 0;
532 r->attributes = NULL;
534 while (next_attr(chunk, &attr_name, &value) == 0) {
536 struct ldap_attribute *attrib = NULL;
538 for (i=0; i<r->num_attributes; i++) {
539 if (strequal(r->attributes[i].name, attr_name)) {
540 attrib = &r->attributes[i];
545 if (attrib == NULL) {
546 r->attributes = talloc_realloc(msg->mem_ctx,
548 sizeof(*r->attributes) *
549 (r->num_attributes+1));
550 if (r->attributes == NULL)
553 attrib = &(r->attributes[r->num_attributes]);
554 r->num_attributes += 1;
555 ZERO_STRUCTP(attrib);
556 attrib->name = talloc_strdup(msg->mem_ctx,
560 if (!add_value_to_attrib(msg->mem_ctx, &value, attrib))
566 static BOOL add_mod_to_array_talloc(TALLOC_CTX *mem_ctx,
567 struct ldap_mod *mod,
568 struct ldap_mod **mods,
571 *mods = talloc_realloc(mem_ctx, *mods,
572 sizeof(**mods) * ((*num_mods)+1));
577 (*mods)[*num_mods] = *mod;
582 static BOOL fill_mods(struct ldap_message *msg, char **chunk)
584 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
585 const char *attr_name;
586 struct ldap_val value;
591 while (next_attr(chunk, &attr_name, &value) == 0) {
594 mod.type = LDAP_MODIFY_NONE;
596 mod.attrib.name = talloc_strdup(msg->mem_ctx, value.data);
598 if (strequal(attr_name, "add"))
599 mod.type = LDAP_MODIFY_ADD;
601 if (strequal(attr_name, "delete"))
602 mod.type = LDAP_MODIFY_DELETE;
604 if (strequal(attr_name, "replace"))
605 mod.type = LDAP_MODIFY_REPLACE;
607 if (mod.type == LDAP_MODIFY_NONE) {
608 DEBUG(2, ("ldif modification type %s unsupported\n",
613 mod.attrib.num_values = 0;
614 mod.attrib.values = NULL;
616 while (next_attr(chunk, &attr_name, &value) == 0) {
617 if (strequal(attr_name, "-"))
619 if (!strequal(attr_name, mod.attrib.name)) {
620 DEBUG(3, ("attrib name %s does not "
621 "match %s\n", attr_name,
625 if (!add_value_to_attrib(msg->mem_ctx, &value,
627 DEBUG(3, ("Could not add value\n"));
632 if (!add_mod_to_array_talloc(msg->mem_ctx, &mod, &r->mods,
641 read from a LDIF source, creating a ldap_message
643 static struct ldap_message *ldif_read(int (*fgetc_fn)(void *),
646 struct ldap_message *msg;
647 const char *attr=NULL;
649 char *chunk=NULL, *s;
650 struct ldap_val value;
654 msg = new_ldap_message();
658 chunk = next_chunk(msg->mem_ctx, fgetc_fn, private_data);
665 if (next_attr(&s, &attr, &value) != 0) {
669 /* first line must be a dn */
670 if (!strequal(attr, "dn")) {
671 DEBUG(5, ("Error: First line of ldif must be a dn not '%s'\n",
676 dn = talloc_strdup(msg->mem_ctx, value.data);
678 if (next_attr(&s, &attr, &value) != 0) {
682 if (!strequal(attr, "changetype")) {
683 DEBUG(5, ("Error: Second line of ldif must be a changetype "
684 "not '%s'\n", attr));
688 if (strequal(value.data, "delete")) {
689 msg->type = LDAP_TAG_DelRequest;
690 msg->r.DelRequest.dn = dn;
694 if (strequal(value.data, "add")) {
695 msg->type = LDAP_TAG_AddRequest;
697 msg->r.AddRequest.dn = dn;
699 if (!fill_add_attributes(msg, &s))
705 if (strequal(value.data, "modify")) {
706 msg->type = LDAP_TAG_ModifyRequest;
708 msg->r.ModifyRequest.dn = dn;
710 if (!fill_mods(msg, &s))
716 DEBUG(3, ("changetype %s not supported\n", (char *)value.data));
719 destroy_ldap_message(msg);
724 a wrapper around ldif_read() for reading from const char*
726 struct ldif_read_string_state {
730 static int fgetc_string(void *private_data)
732 struct ldif_read_string_state *state = private_data;
733 if (state->s[0] != 0) {
739 struct ldap_message *ldap_ldif2msg(const char *s)
741 struct ldif_read_string_state state;
743 return ldif_read(fgetc_string, &state);
746 static void ldap_encode_response(enum ldap_request_tag tag,
747 struct ldap_Result *result,
750 asn1_push_tag(data, ASN1_APPLICATION(tag));
751 asn1_write_enumerated(data, result->resultcode);
752 asn1_write_OctetString(data, result->dn,
753 (result->dn) ? strlen(result->dn) : 0);
754 asn1_write_OctetString(data, result->errormessage,
755 (result->errormessage) ?
756 strlen(result->errormessage) : 0);
757 if (result->referral != NULL)
758 asn1_write_OctetString(data, result->referral,
759 strlen(result->referral));
763 BOOL ldap_encode(struct ldap_message *msg, DATA_BLOB *result)
769 asn1_push_tag(&data, ASN1_SEQUENCE(0));
770 asn1_write_Integer(&data, msg->messageid);
773 case LDAP_TAG_BindRequest: {
774 struct ldap_BindRequest *r = &msg->r.BindRequest;
775 asn1_push_tag(&data, ASN1_APPLICATION(LDAP_TAG_BindRequest));
776 asn1_write_Integer(&data, r->version);
777 asn1_write_OctetString(&data, r->dn,
778 (r->dn != NULL) ? strlen(r->dn) : 0);
780 switch (r->mechanism) {
781 case LDAP_AUTH_MECH_SIMPLE:
782 /* context, primitive */
783 asn1_push_tag(&data, r->mechanism | 0x80);
784 asn1_write(&data, r->creds.password,
785 strlen(r->creds.password));
788 case LDAP_AUTH_MECH_SASL:
789 /* context, constructed */
790 asn1_push_tag(&data, r->mechanism | 0xa0);
791 asn1_write_OctetString(&data, r->creds.SASL.mechanism,
792 strlen(r->creds.SASL.mechanism));
793 asn1_write_OctetString(&data, r->creds.SASL.secblob.data,
794 r->creds.SASL.secblob.length);
805 case LDAP_TAG_BindResponse: {
806 struct ldap_BindResponse *r = &msg->r.BindResponse;
807 ldap_encode_response(msg->type, &r->response, &data);
810 case LDAP_TAG_UnbindRequest: {
811 /* struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
814 case LDAP_TAG_SearchRequest: {
815 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
816 asn1_push_tag(&data, ASN1_APPLICATION(LDAP_TAG_SearchRequest));
817 asn1_write_OctetString(&data, r->basedn, strlen(r->basedn));
818 asn1_write_enumerated(&data, r->scope);
819 asn1_write_enumerated(&data, r->deref);
820 asn1_write_Integer(&data, r->sizelimit);
821 asn1_write_Integer(&data, r->timelimit);
822 asn1_write_BOOLEAN2(&data, r->attributesonly);
825 TALLOC_CTX *mem_ctx = talloc_init("ldap_parse_tree");
826 struct ldap_parse_tree *tree;
831 tree = ldap_parse_tree(mem_ctx, r->filter);
836 ldap_push_filter(&data, tree);
838 talloc_destroy(mem_ctx);
841 asn1_push_tag(&data, ASN1_SEQUENCE(0));
842 for (i=0; i<r->num_attributes; i++) {
843 asn1_write_OctetString(&data, r->attributes[i],
844 strlen(r->attributes[i]));
851 case LDAP_TAG_SearchResultEntry: {
852 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
853 asn1_push_tag(&data, ASN1_APPLICATION(LDAP_TAG_SearchResultEntry));
854 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
855 asn1_push_tag(&data, ASN1_SEQUENCE(0));
856 for (i=0; i<r->num_attributes; i++) {
857 struct ldap_attribute *attr = &r->attributes[i];
858 asn1_push_tag(&data, ASN1_SEQUENCE(0));
859 asn1_write_OctetString(&data, attr->name,
861 asn1_push_tag(&data, ASN1_SEQUENCE(1));
862 for (j=0; j<attr->num_values; j++) {
863 asn1_write_OctetString(&data,
864 attr->values[j].data,
865 attr->values[j].length);
874 case LDAP_TAG_SearchResultDone: {
875 struct ldap_Result *r = &msg->r.SearchResultDone;
876 ldap_encode_response(msg->type, r, &data);
879 case LDAP_TAG_ModifyRequest: {
880 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
881 asn1_push_tag(&data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
882 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
883 asn1_push_tag(&data, ASN1_SEQUENCE(0));
885 for (i=0; i<r->num_mods; i++) {
886 struct ldap_attribute *attrib = &r->mods[i].attrib;
887 asn1_push_tag(&data, ASN1_SEQUENCE(0));
888 asn1_write_enumerated(&data, r->mods[i].type);
889 asn1_push_tag(&data, ASN1_SEQUENCE(0));
890 asn1_write_OctetString(&data, attrib->name,
891 strlen(attrib->name));
892 asn1_push_tag(&data, ASN1_SET);
893 for (j=0; j<attrib->num_values; j++) {
894 asn1_write_OctetString(&data,
895 attrib->values[j].data,
896 attrib->values[j].length);
908 case LDAP_TAG_ModifyResponse: {
909 struct ldap_Result *r = &msg->r.ModifyResponse;
910 ldap_encode_response(msg->type, r, &data);
913 case LDAP_TAG_AddRequest: {
914 struct ldap_AddRequest *r = &msg->r.AddRequest;
915 asn1_push_tag(&data, ASN1_APPLICATION(LDAP_TAG_AddRequest));
916 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
917 asn1_push_tag(&data, ASN1_SEQUENCE(0));
919 for (i=0; i<r->num_attributes; i++) {
920 struct ldap_attribute *attrib = &r->attributes[i];
921 asn1_push_tag(&data, ASN1_SEQUENCE(0));
922 asn1_write_OctetString(&data, attrib->name,
923 strlen(attrib->name));
924 asn1_push_tag(&data, ASN1_SET);
925 for (j=0; j<r->attributes[i].num_values; j++) {
926 asn1_write_OctetString(&data,
927 attrib->values[j].data,
928 attrib->values[j].length);
937 case LDAP_TAG_AddResponse: {
938 struct ldap_Result *r = &msg->r.AddResponse;
939 ldap_encode_response(msg->type, r, &data);
942 case LDAP_TAG_DelRequest: {
943 struct ldap_DelRequest *r = &msg->r.DelRequest;
945 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
946 asn1_write(&data, r->dn, strlen(r->dn));
950 case LDAP_TAG_DelResponse: {
951 struct ldap_Result *r = &msg->r.DelResponse;
952 ldap_encode_response(msg->type, r, &data);
955 case LDAP_TAG_ModifyDNRequest: {
956 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
958 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
959 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
960 asn1_write_OctetString(&data, r->newrdn, strlen(r->newrdn));
961 asn1_write_BOOLEAN2(&data, r->deleteolddn);
962 if (r->newsuperior != NULL) {
963 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
964 asn1_write(&data, r->newsuperior,
965 strlen(r->newsuperior));
971 case LDAP_TAG_ModifyDNResponse: {
972 /* struct ldap_Result *r = &msg->r.ModifyDNResponse; */
975 case LDAP_TAG_CompareRequest: {
976 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
978 ASN1_APPLICATION(LDAP_TAG_CompareRequest));
979 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
980 asn1_push_tag(&data, ASN1_SEQUENCE(0));
981 asn1_write_OctetString(&data, r->attribute,
982 strlen(r->attribute));
983 asn1_write_OctetString(&data, r->value,
989 case LDAP_TAG_CompareResponse: {
990 /* struct ldap_Result *r = &msg->r.CompareResponse; */
993 case LDAP_TAG_AbandonRequest: {
994 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
996 ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest));
997 asn1_write_Integer(&data, r->messageid);
1001 case LDAP_TAG_SearchResultReference: {
1002 /* struct ldap_SearchResRef *r = &msg->r.SearchResultReference; */
1005 case LDAP_TAG_ExtendedRequest: {
1006 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1007 asn1_push_tag(&data, ASN1_APPLICATION(LDAP_TAG_ExtendedRequest));
1008 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
1009 asn1_write(&data, r->oid, strlen(r->oid));
1010 asn1_pop_tag(&data);
1011 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(1));
1012 asn1_write(&data, r->value.data, r->value.length);
1013 asn1_pop_tag(&data);
1014 asn1_pop_tag(&data);
1017 case LDAP_TAG_ExtendedResponse: {
1018 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1019 ldap_encode_response(msg->type, &r->response, &data);
1026 asn1_pop_tag(&data);
1027 *result = data_blob(data.data, data.length);
1032 static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
1035 char *result = talloc(mem_ctx, blob.length+1);
1036 memcpy(result, blob.data, blob.length);
1037 result[blob.length] = '\0';
1041 static BOOL asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
1043 const char **result)
1046 if (!asn1_read_OctetString(data, &string))
1048 *result = blob2string_talloc(mem_ctx, string);
1049 data_blob_free(&string);
1053 static void ldap_decode_response(TALLOC_CTX *mem_ctx,
1055 enum ldap_request_tag tag,
1056 struct ldap_Result *result)
1058 asn1_start_tag(data, ASN1_APPLICATION(tag));
1059 asn1_read_enumerated(data, &result->resultcode);
1060 asn1_read_OctetString_talloc(mem_ctx, data, &result->dn);
1061 asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage);
1062 if (asn1_peek_tag(data, ASN1_OCTET_STRING))
1063 asn1_read_OctetString_talloc(mem_ctx, data, &result->referral);
1065 result->referral = NULL;
1069 /* read a octet string blob */
1070 static BOOL asn1_read_ContextSimple(ASN1_DATA *data, uint8_t num, DATA_BLOB *blob)
1074 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(num))) return False;
1075 len = asn1_tag_remaining(data);
1077 data->has_error = True;
1080 *blob = data_blob(NULL, len);
1081 asn1_read(data, blob->data, len);
1083 return !data->has_error;
1086 static void ldap_decode_BindResponse(TALLOC_CTX *mem_ctx,
1088 enum ldap_request_tag tag,
1089 struct ldap_BindResponse *BindResp)
1091 asn1_start_tag(data, ASN1_APPLICATION(tag));
1092 asn1_read_enumerated(data, &BindResp->response.resultcode);
1093 asn1_read_OctetString_talloc(mem_ctx, data, &BindResp->response.dn);
1094 asn1_read_OctetString_talloc(mem_ctx, data, &BindResp->response.errormessage);
1095 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
1096 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1097 asn1_read_ContextSimple(data, 7, &tmp_blob);
1098 BindResp->SASL.secblob = data_blob_talloc(mem_ctx, tmp_blob.data, tmp_blob.length);
1099 data_blob_free(&tmp_blob);
1101 BindResp->SASL.secblob = data_blob(NULL, 0);
1106 static BOOL add_attrib_to_array_talloc(TALLOC_CTX *mem_ctx,
1107 const struct ldap_attribute *attrib,
1108 struct ldap_attribute **attribs,
1111 *attribs = talloc_realloc(mem_ctx, *attribs,
1112 sizeof(**attribs) * (*num_attribs+1));
1114 if (*attribs == NULL)
1117 (*attribs)[*num_attribs] = *attrib;
1122 static BOOL ldap_decode_filter(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
1125 uint8 filter_tag, tag_desc;
1127 if (!asn1_peek_uint8(data, &filter_tag))
1130 tag_desc = filter_tag;
1131 filter_tag &= 0x1f; /* strip off the asn1 stuff */
1134 switch(filter_tag) {
1136 /* AND of one or more filters */
1137 if (tag_desc != 0xa0) /* context compount */
1140 asn1_start_tag(data, ASN1_CONTEXT(0));
1142 *filter = talloc_strdup(mem_ctx, "(&");
1143 if (*filter == NULL)
1146 while (asn1_tag_remaining(data) > 0) {
1148 if (!ldap_decode_filter(mem_ctx, data, &subfilter))
1150 *filter = talloc_asprintf(mem_ctx, "%s%s", *filter,
1152 if (*filter == NULL)
1157 *filter = talloc_asprintf(mem_ctx, "%s)", *filter);
1161 /* OR of one or more filters */
1162 if (tag_desc != 0xa0) /* context compount */
1165 asn1_start_tag(data, ASN1_CONTEXT(1));
1167 *filter = talloc_strdup(mem_ctx, "(|");
1168 if (*filter == NULL)
1171 while (asn1_tag_remaining(data) > 0) {
1173 if (!ldap_decode_filter(mem_ctx, data, &subfilter))
1175 *filter = talloc_asprintf(mem_ctx, "%s%s", *filter,
1177 if (*filter == NULL)
1183 *filter = talloc_asprintf(mem_ctx, "%s)", *filter);
1188 const char *attrib, *value;
1189 if (tag_desc != 0xa0) /* context compound */
1191 asn1_start_tag(data, ASN1_CONTEXT(3));
1192 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
1193 asn1_read_OctetString_talloc(mem_ctx, data, &value);
1195 if ((data->has_error) || (attrib == NULL) || (value == NULL))
1197 *filter = talloc_asprintf(mem_ctx, "(%s=%s)", attrib, value);
1201 /* Normal presence, "attribute=*" */
1204 if (tag_desc != 0x80) /* context simple */
1206 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(7)))
1208 attr_len = asn1_tag_remaining(data);
1209 attr_name = malloc(attr_len+1);
1210 if (attr_name == NULL)
1212 asn1_read(data, attr_name, attr_len);
1213 attr_name[attr_len] = '\0';
1214 *filter = talloc_asprintf(mem_ctx, "(%s=*)", attr_name);
1215 SAFE_FREE(attr_name);
1222 if (*filter == NULL)
1227 static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
1228 struct ldap_attribute *attrib)
1230 asn1_start_tag(data, ASN1_SEQUENCE(0));
1231 asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name);
1232 asn1_start_tag(data, ASN1_SET);
1233 while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
1235 struct ldap_val value;
1236 asn1_read_OctetString(data, &blob);
1237 value.data = blob.data;
1238 value.length = blob.length;
1239 add_value_to_attrib(mem_ctx, &value, attrib);
1240 data_blob_free(&blob);
1247 static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
1248 struct ldap_attribute **attributes,
1249 int *num_attributes)
1251 asn1_start_tag(data, ASN1_SEQUENCE(0));
1252 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1253 struct ldap_attribute attrib;
1254 ZERO_STRUCT(attrib);
1255 ldap_decode_attrib(mem_ctx, data, &attrib);
1256 add_attrib_to_array_talloc(mem_ctx, &attrib,
1257 attributes, num_attributes);
1262 BOOL ldap_decode(ASN1_DATA *data, struct ldap_message *msg)
1266 asn1_start_tag(data, ASN1_SEQUENCE(0));
1267 asn1_read_Integer(data, &msg->messageid);
1269 if (!asn1_peek_uint8(data, &tag))
1274 case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
1275 struct ldap_BindRequest *r = &msg->r.BindRequest;
1276 msg->type = LDAP_TAG_BindRequest;
1277 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_BindRequest));
1278 asn1_read_Integer(data, &r->version);
1279 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
1280 if (asn1_peek_tag(data, 0x80)) {
1282 r->creds.password = "";
1283 /* Mechanism 0 (SIMPLE) */
1284 asn1_start_tag(data, 0x80);
1285 pwlen = asn1_tag_remaining(data);
1287 char *pw = talloc(msg->mem_ctx, pwlen+1);
1288 asn1_read(data, pw, pwlen);
1290 r->creds.password = pw;
1298 case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
1299 struct ldap_BindResponse *r = &msg->r.BindResponse;
1300 msg->type = LDAP_TAG_BindResponse;
1301 ldap_decode_BindResponse(msg->mem_ctx,
1302 data, LDAP_TAG_BindResponse,
1307 case ASN1_APPLICATION(LDAP_TAG_UnbindRequest): {
1308 msg->type = LDAP_TAG_UnbindRequest;
1312 case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
1313 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
1314 msg->type = LDAP_TAG_SearchRequest;
1315 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_SearchRequest));
1316 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->basedn);
1317 asn1_read_enumerated(data, (int *)&(r->scope));
1318 asn1_read_enumerated(data, (int *)&(r->deref));
1319 asn1_read_Integer(data, &r->sizelimit);
1320 asn1_read_Integer(data, &r->timelimit);
1321 asn1_read_BOOLEAN2(data, &r->attributesonly);
1323 /* Maybe create a TALLOC_CTX for the filter? This can waste
1324 * quite a bit of memory recursing down. */
1325 ldap_decode_filter(msg->mem_ctx, data, &r->filter);
1327 asn1_start_tag(data, ASN1_SEQUENCE(0));
1329 r->num_attributes = 0;
1330 r->attributes = NULL;
1332 while (asn1_tag_remaining(data) > 0) {
1334 if (!asn1_read_OctetString_talloc(msg->mem_ctx, data,
1337 if (!add_string_to_array(msg->mem_ctx, attr,
1339 &r->num_attributes))
1348 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1349 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1350 msg->type = LDAP_TAG_SearchResultEntry;
1351 r->attributes = NULL;
1352 r->num_attributes = 0;
1353 asn1_start_tag(data,
1354 ASN1_APPLICATION(LDAP_TAG_SearchResultEntry));
1355 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
1356 ldap_decode_attribs(msg->mem_ctx, data, &r->attributes,
1357 &r->num_attributes);
1362 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1363 struct ldap_Result *r = &msg->r.SearchResultDone;
1364 msg->type = LDAP_TAG_SearchResultDone;
1365 ldap_decode_response(msg->mem_ctx, data,
1366 LDAP_TAG_SearchResultDone, r);
1370 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1371 /* struct ldap_SearchResRef *r = &msg->r.SearchResultReference; */
1372 msg->type = LDAP_TAG_SearchResultReference;
1376 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1377 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1378 msg->type = LDAP_TAG_ModifyRequest;
1379 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
1380 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
1381 asn1_start_tag(data, ASN1_SEQUENCE(0));
1386 while (asn1_tag_remaining(data) > 0) {
1387 struct ldap_mod mod;
1389 asn1_start_tag(data, ASN1_SEQUENCE(0));
1390 asn1_read_enumerated(data, &mod.type);
1391 ldap_decode_attrib(msg->mem_ctx, data, &mod.attrib);
1393 if (!add_mod_to_array_talloc(msg->mem_ctx, &mod,
1394 &r->mods, &r->num_mods))
1403 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1404 struct ldap_Result *r = &msg->r.ModifyResponse;
1405 msg->type = LDAP_TAG_ModifyResponse;
1406 ldap_decode_response(msg->mem_ctx, data,
1407 LDAP_TAG_ModifyResponse, r);
1411 case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1412 struct ldap_AddRequest *r = &msg->r.AddRequest;
1413 msg->type = LDAP_TAG_AddRequest;
1414 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_AddRequest));
1415 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
1417 r->attributes = NULL;
1418 r->num_attributes = 0;
1419 ldap_decode_attribs(msg->mem_ctx, data, &r->attributes,
1420 &r->num_attributes);
1426 case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1427 struct ldap_Result *r = &msg->r.AddResponse;
1428 msg->type = LDAP_TAG_AddResponse;
1429 ldap_decode_response(msg->mem_ctx, data,
1430 LDAP_TAG_AddResponse, r);
1434 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1435 struct ldap_DelRequest *r = &msg->r.DelRequest;
1438 msg->type = LDAP_TAG_DelRequest;
1439 asn1_start_tag(data,
1440 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
1441 len = asn1_tag_remaining(data);
1442 dn = talloc(msg->mem_ctx, len+1);
1445 asn1_read(data, dn, len);
1452 case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1453 struct ldap_Result *r = &msg->r.DelResponse;
1454 msg->type = LDAP_TAG_DelResponse;
1455 ldap_decode_response(msg->mem_ctx, data,
1456 LDAP_TAG_DelResponse, r);
1460 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1461 /* struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest; */
1462 msg->type = LDAP_TAG_ModifyDNRequest;
1466 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1467 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1468 msg->type = LDAP_TAG_ModifyDNResponse;
1469 ldap_decode_response(msg->mem_ctx, data,
1470 LDAP_TAG_ModifyDNResponse, r);
1474 case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1475 /* struct ldap_CompareRequest *r = &msg->r.CompareRequest; */
1476 msg->type = LDAP_TAG_CompareRequest;
1480 case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1481 struct ldap_Result *r = &msg->r.CompareResponse;
1482 msg->type = LDAP_TAG_CompareResponse;
1483 ldap_decode_response(msg->mem_ctx, data,
1484 LDAP_TAG_CompareResponse, r);
1488 case ASN1_APPLICATION(LDAP_TAG_AbandonRequest): {
1489 /* struct ldap_AbandonRequest *r = &msg->r.AbandonRequest; */
1490 msg->type = LDAP_TAG_AbandonRequest;
1494 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1495 /* struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest; */
1496 msg->type = LDAP_TAG_ExtendedRequest;
1500 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1501 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1502 msg->type = LDAP_TAG_ExtendedResponse;
1503 ldap_decode_response(msg->mem_ctx, data,
1504 LDAP_TAG_ExtendedResponse, &r->response);
1505 /* I have to come across an operation that actually sends
1506 * something back to really see what's going on. The currently
1507 * needed pwdchange does not send anything back. */
1509 r->value.data = NULL;
1510 r->value.length = 0;
1517 return ((!data->has_error) && (data->nesting == NULL));
1520 BOOL ldap_parse_basic_url(TALLOC_CTX *mem_ctx, const char *url,
1521 char **host, uint16 *port, BOOL *ldaps)
1526 const char *p = url;
1528 /* skip leading "URL:" (if any) */
1529 if ( strnequal( p, "URL:", 4 ) ) {
1533 /* Paranoia check */
1534 SMB_ASSERT(sizeof(protocol)>10 && sizeof(tmp_host)>254);
1536 sscanf(p, "%10[^:]://%254[^:/]:%d", protocol, tmp_host, &tmp_port);
1538 if (strequal(protocol, "ldap")) {
1541 } else if (strequal(protocol, "ldaps")) {
1545 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
1552 *host = talloc_strdup(mem_ctx, tmp_host);
1554 return (*host != NULL);
1557 struct ldap_connection *new_ldap_connection(void)
1559 TALLOC_CTX *mem_ctx = talloc_init("ldap_connection");
1560 struct ldap_connection *result;
1562 if (mem_ctx == NULL)
1565 result = talloc(mem_ctx, sizeof(*result));
1570 result->mem_ctx = mem_ctx;
1571 result->next_msgid = 1;
1572 result->outstanding = NULL;
1573 result->searchid = 0;
1574 result->search_entries = NULL;
1575 result->auth_dn = NULL;
1576 result->simple_pw = NULL;
1577 result->gensec = NULL;
1582 BOOL ldap_connect(struct ldap_connection *conn, const char *url)
1587 if (!ldap_parse_basic_url(conn->mem_ctx, url, &conn->host,
1588 &conn->port, &conn->ldaps))
1591 hp = sys_gethostbyname(conn->host);
1593 if ((hp == NULL) || (hp->h_addr == NULL))
1596 putip((char *)&ip, (char *)hp->h_addr);
1598 conn->sock = open_socket_out(SOCK_STREAM, &ip, conn->port, LDAP_CONNECTION_TIMEOUT);
1600 return (conn->sock >= 0);
1603 BOOL ldap_set_simple_creds(struct ldap_connection *conn,
1604 const char *dn, const char *password)
1606 conn->auth_dn = talloc_strdup(conn->mem_ctx, dn);
1607 conn->simple_pw = talloc_strdup(conn->mem_ctx, password);
1609 return ((conn->auth_dn != NULL) && (conn->simple_pw != NULL));
1612 struct ldap_message *new_ldap_message(void)
1614 TALLOC_CTX *mem_ctx = talloc_init("ldap_message");
1615 struct ldap_message *result;
1617 if (mem_ctx == NULL)
1620 result = talloc(mem_ctx, sizeof(*result));
1625 result->mem_ctx = mem_ctx;
1629 void destroy_ldap_message(struct ldap_message *msg)
1632 talloc_destroy(msg->mem_ctx);
1635 BOOL ldap_send_msg(struct ldap_connection *conn, struct ldap_message *msg,
1636 const struct timeval *endtime)
1640 struct ldap_queue_entry *entry;
1642 msg->messageid = conn->next_msgid++;
1644 if (!ldap_encode(msg, &request))
1647 result = (write_data_until(conn->sock, request.data, request.length,
1648 endtime) == request.length);
1650 data_blob_free(&request);
1655 /* abandon and unbind don't expect results */
1657 if ((msg->type == LDAP_TAG_AbandonRequest) ||
1658 (msg->type == LDAP_TAG_UnbindRequest))
1661 entry = malloc(sizeof(*entry));
1666 entry->msgid = msg->messageid;
1668 DLIST_ADD(conn->outstanding, entry);
1673 BOOL ldap_receive_msg(struct ldap_connection *conn, struct ldap_message *msg,
1674 const struct timeval *endtime)
1676 struct asn1_data data;
1679 if (!asn1_read_sequence_until(conn->sock, &data, endtime))
1682 result = ldap_decode(&data, msg);
1688 static struct ldap_message *recv_from_queue(struct ldap_connection *conn,
1691 struct ldap_queue_entry *e;
1693 for (e = conn->outstanding; e != NULL; e = e->next) {
1695 if (e->msgid == msgid) {
1696 struct ldap_message *result = e->msg;
1697 DLIST_REMOVE(conn->outstanding, e);
1706 static void add_search_entry(struct ldap_connection *conn,
1707 struct ldap_message *msg)
1709 struct ldap_queue_entry *e = malloc(sizeof *e);
1715 DLIST_ADD_END(conn->search_entries, e, struct ldap_queue_entry *);
1719 static void fill_outstanding_request(struct ldap_connection *conn,
1720 struct ldap_message *msg)
1722 struct ldap_queue_entry *e;
1724 for (e = conn->outstanding; e != NULL; e = e->next) {
1725 if (e->msgid == msg->messageid) {
1731 /* This reply has not been expected, destroy the incoming msg */
1732 destroy_ldap_message(msg);
1736 struct ldap_message *ldap_receive(struct ldap_connection *conn, int msgid,
1737 const struct timeval *endtime)
1739 struct ldap_message *result = recv_from_queue(conn, msgid);
1745 struct asn1_data data;
1748 result = new_ldap_message();
1750 if (!asn1_read_sequence_until(conn->sock, &data, endtime))
1753 res = ldap_decode(&data, result);
1759 if (result->messageid == msgid)
1762 if (result->type == LDAP_TAG_SearchResultEntry) {
1763 add_search_entry(conn, result);
1765 fill_outstanding_request(conn, result);
1772 struct ldap_message *ldap_transaction(struct ldap_connection *conn,
1773 struct ldap_message *request)
1775 if (!ldap_send_msg(conn, request, NULL))
1778 return ldap_receive(conn, request->messageid, NULL);
1781 int ldap_bind_simple(struct ldap_connection *conn, const char *userdn, const char *password)
1783 struct ldap_message *response;
1784 struct ldap_message *msg;
1785 const char *dn, *pw;
1786 int result = LDAP_OTHER;
1794 if (conn->auth_dn) {
1804 if (conn->simple_pw) {
1805 pw = conn->simple_pw;
1811 msg = new_ldap_simple_bind_msg(dn, pw);
1815 response = ldap_transaction(conn, msg);
1817 destroy_ldap_message(msg);
1821 result = response->r.BindResponse.response.resultcode;
1823 destroy_ldap_message(msg);
1824 destroy_ldap_message(response);
1829 int ldap_bind_sasl(struct ldap_connection *conn, const char *username, const char *domain, const char *password)
1832 TALLOC_CTX *mem_ctx = NULL;
1833 struct ldap_message *response;
1834 struct ldap_message *msg;
1835 DATA_BLOB input = data_blob(NULL, 0);
1836 DATA_BLOB output = data_blob(NULL, 0);
1837 int result = LDAP_OTHER;
1842 status = gensec_client_start(&conn->gensec);
1843 if (!NT_STATUS_IS_OK(status)) {
1844 DEBUG(0, ("Failed to start GENSEC engine (%s)\n", nt_errstr(status)));
1848 status = gensec_set_domain(conn->gensec, domain);
1849 if (!NT_STATUS_IS_OK(status)) {
1850 DEBUG(1, ("Failed to start set GENSEC client domain to %s: %s\n",
1851 domain, nt_errstr(status)));
1855 status = gensec_set_username(conn->gensec, username);
1856 if (!NT_STATUS_IS_OK(status)) {
1857 DEBUG(1, ("Failed to start set GENSEC client username to %s: %s\n",
1858 username, nt_errstr(status)));
1862 status = gensec_set_password(conn->gensec, password);
1863 if (!NT_STATUS_IS_OK(status)) {
1864 DEBUG(1, ("Failed to start set GENSEC client password: %s\n",
1865 nt_errstr(status)));
1869 status = gensec_set_target_hostname(conn->gensec, conn->host);
1870 if (!NT_STATUS_IS_OK(status)) {
1871 DEBUG(1, ("Failed to start set GENSEC target hostname: %s\n",
1872 nt_errstr(status)));
1876 status = gensec_start_mech_by_sasl_name(conn->gensec, "GSS-SPNEGO");
1877 if (!NT_STATUS_IS_OK(status)) {
1878 DEBUG(1, ("Failed to start set GENSEC client SPNEGO mechanism: %s\n",
1879 nt_errstr(status)));
1883 mem_ctx = talloc_init("ldap_bind_sasl");
1887 status = gensec_update(conn->gensec, mem_ctx,
1892 if (NT_STATUS_IS_OK(status) && output.length == 0) {
1895 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
1899 msg = new_ldap_sasl_bind_msg("GSS-SPNEGO", &output);
1903 response = ldap_transaction(conn, msg);
1904 destroy_ldap_message(msg);
1910 result = response->r.BindResponse.response.resultcode;
1912 if (result != LDAP_SUCCESS && result != LDAP_SASL_BIND_IN_PROGRESS) {
1916 status = gensec_update(conn->gensec, mem_ctx,
1917 response->r.BindResponse.SASL.secblob,
1920 destroy_ldap_message(response);
1925 gensec_end(&conn->gensec);
1927 talloc_destroy(mem_ctx);
1932 BOOL ldap_setup_connection(struct ldap_connection *conn,
1933 const char *url, const char *userdn, const char *password)
1937 if (!ldap_connect(conn, url)) {
1941 result = ldap_bind_simple(conn, userdn, password);
1942 if (result == LDAP_SUCCESS) {
1949 BOOL ldap_setup_connection_with_sasl(struct ldap_connection *conn, const char *url, const char *username, const char *domain, const char *password)
1953 if (!ldap_connect(conn, url)) {
1957 result = ldap_bind_sasl(conn, username, domain, password);
1958 if (result == LDAP_SUCCESS) {
1965 static BOOL ldap_abandon_message(struct ldap_connection *conn, int msgid,
1966 const struct timeval *endtime)
1968 struct ldap_message *msg = new_ldap_message();
1974 msg->type = LDAP_TAG_AbandonRequest;
1975 msg->r.AbandonRequest.messageid = msgid;
1977 result = ldap_send_msg(conn, msg, endtime);
1978 destroy_ldap_message(msg);
1982 struct ldap_message *new_ldap_search_message(const char *base,
1983 enum ldap_scope scope,
1986 const char **attributes)
1988 struct ldap_message *res = new_ldap_message();
1993 res->type = LDAP_TAG_SearchRequest;
1994 res->r.SearchRequest.basedn = base;
1995 res->r.SearchRequest.scope = scope;
1996 res->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
1997 res->r.SearchRequest.timelimit = 0;
1998 res->r.SearchRequest.sizelimit = 0;
1999 res->r.SearchRequest.attributesonly = False;
2000 res->r.SearchRequest.filter = filter;
2001 res->r.SearchRequest.num_attributes = num_attributes;
2002 res->r.SearchRequest.attributes = attributes;
2006 struct ldap_message *new_ldap_simple_bind_msg(const char *dn, const char *pw)
2008 struct ldap_message *res = new_ldap_message();
2013 res->type = LDAP_TAG_BindRequest;
2014 res->r.BindRequest.version = 3;
2015 res->r.BindRequest.dn = talloc_strdup(res->mem_ctx, dn);
2016 res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SIMPLE;
2017 res->r.BindRequest.creds.password = talloc_strdup(res->mem_ctx, pw);
2021 struct ldap_message *new_ldap_sasl_bind_msg(const char *sasl_mechanism, DATA_BLOB *secblob)
2023 struct ldap_message *res = new_ldap_message();
2028 res->type = LDAP_TAG_BindRequest;
2029 res->r.BindRequest.version = 3;
2030 res->r.BindRequest.dn = "";
2031 res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SASL;
2032 res->r.BindRequest.creds.SASL.mechanism = talloc_strdup(res->mem_ctx, sasl_mechanism);
2033 res->r.BindRequest.creds.SASL.secblob = *secblob;
2037 BOOL ldap_setsearchent(struct ldap_connection *conn, struct ldap_message *msg,
2038 const struct timeval *endtime)
2040 if ((conn->searchid != 0) &&
2041 (!ldap_abandon_message(conn, conn->searchid, endtime)))
2044 conn->searchid = conn->next_msgid;
2045 return ldap_send_msg(conn, msg, endtime);
2048 struct ldap_message *ldap_getsearchent(struct ldap_connection *conn,
2049 const struct timeval *endtime)
2051 struct ldap_message *result;
2053 if (conn->search_entries != NULL) {
2054 struct ldap_queue_entry *e = conn->search_entries;
2057 DLIST_REMOVE(conn->search_entries, e);
2062 result = ldap_receive(conn, conn->searchid, endtime);
2064 if (result->type == LDAP_TAG_SearchResultEntry)
2067 if (result->type == LDAP_TAG_SearchResultDone) {
2068 /* TODO: Handle Paged Results */
2069 destroy_ldap_message(result);
2073 /* TODO: Handle Search References here */
2077 void ldap_endsearchent(struct ldap_connection *conn,
2078 const struct timeval *endtime)
2080 struct ldap_queue_entry *e;
2082 e = conn->search_entries;
2085 struct ldap_queue_entry *next = e->next;
2086 DLIST_REMOVE(conn->search_entries, e);
2092 struct ldap_message *ldap_searchone(struct ldap_connection *conn,
2093 struct ldap_message *msg,
2094 const struct timeval *endtime)
2096 struct ldap_message *res1, *res2 = NULL;
2097 if (!ldap_setsearchent(conn, msg, endtime))
2100 res1 = ldap_getsearchent(conn, endtime);
2103 res2 = ldap_getsearchent(conn, endtime);
2105 ldap_endsearchent(conn, endtime);
2111 /* More than one entry */
2112 destroy_ldap_message(res1);
2113 destroy_ldap_message(res2);
2120 BOOL ldap_find_single_value(struct ldap_message *msg, const char *attr,
2124 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
2126 if (msg->type != LDAP_TAG_SearchResultEntry)
2129 for (i=0; i<r->num_attributes; i++) {
2130 if (strequal(attr, r->attributes[i].name)) {
2131 if (r->attributes[i].num_values != 1)
2134 *value = r->attributes[i].values[0];
2141 BOOL ldap_find_single_string(struct ldap_message *msg, const char *attr,
2142 TALLOC_CTX *mem_ctx, char **value)
2146 if (!ldap_find_single_value(msg, attr, &blob))
2149 *value = talloc(mem_ctx, blob.length+1);
2154 memcpy(*value, blob.data, blob.length);
2155 (*value)[blob.length] = '\0';
2159 BOOL ldap_find_single_int(struct ldap_message *msg, const char *attr,
2167 if (!ldap_find_single_value(msg, attr, &blob))
2170 val = malloc(blob.length+1);
2174 memcpy(val, blob.data, blob.length);
2175 val[blob.length] = '\0';
2180 *value = strtol(val, NULL, 10);
2190 int ldap_error(struct ldap_connection *conn)
2195 NTSTATUS ldap2nterror(int ldaperror)
2197 return NT_STATUS_OK;