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 static BOOL add_attrib_to_array_talloc(TALLOC_CTX *mem_ctx,
1070 const struct ldap_attribute *attrib,
1071 struct ldap_attribute **attribs,
1074 *attribs = talloc_realloc(mem_ctx, *attribs,
1075 sizeof(**attribs) * (*num_attribs+1));
1077 if (*attribs == NULL)
1080 (*attribs)[*num_attribs] = *attrib;
1085 static BOOL ldap_decode_filter(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
1088 uint8 filter_tag, tag_desc;
1090 if (!asn1_peek_uint8(data, &filter_tag))
1093 tag_desc = filter_tag;
1094 filter_tag &= 0x1f; /* strip off the asn1 stuff */
1097 switch(filter_tag) {
1099 /* AND of one or more filters */
1100 if (tag_desc != 0xa0) /* context compount */
1103 asn1_start_tag(data, ASN1_CONTEXT(0));
1105 *filter = talloc_strdup(mem_ctx, "(&");
1106 if (*filter == NULL)
1109 while (asn1_tag_remaining(data) > 0) {
1111 if (!ldap_decode_filter(mem_ctx, data, &subfilter))
1113 *filter = talloc_asprintf(mem_ctx, "%s%s", *filter,
1115 if (*filter == NULL)
1120 *filter = talloc_asprintf(mem_ctx, "%s)", *filter);
1124 /* OR of one or more filters */
1125 if (tag_desc != 0xa0) /* context compount */
1128 asn1_start_tag(data, ASN1_CONTEXT(1));
1130 *filter = talloc_strdup(mem_ctx, "(|");
1131 if (*filter == NULL)
1134 while (asn1_tag_remaining(data) > 0) {
1136 if (!ldap_decode_filter(mem_ctx, data, &subfilter))
1138 *filter = talloc_asprintf(mem_ctx, "%s%s", *filter,
1140 if (*filter == NULL)
1146 *filter = talloc_asprintf(mem_ctx, "%s)", *filter);
1151 const char *attrib, *value;
1152 if (tag_desc != 0xa0) /* context compound */
1154 asn1_start_tag(data, ASN1_CONTEXT(3));
1155 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
1156 asn1_read_OctetString_talloc(mem_ctx, data, &value);
1158 if ((data->has_error) || (attrib == NULL) || (value == NULL))
1160 *filter = talloc_asprintf(mem_ctx, "(%s=%s)", attrib, value);
1164 /* Normal presence, "attribute=*" */
1167 if (tag_desc != 0x80) /* context simple */
1169 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(7)))
1171 attr_len = asn1_tag_remaining(data);
1172 attr_name = malloc(attr_len+1);
1173 if (attr_name == NULL)
1175 asn1_read(data, attr_name, attr_len);
1176 attr_name[attr_len] = '\0';
1177 *filter = talloc_asprintf(mem_ctx, "(%s=*)", attr_name);
1178 SAFE_FREE(attr_name);
1185 if (*filter == NULL)
1190 static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
1191 struct ldap_attribute *attrib)
1193 asn1_start_tag(data, ASN1_SEQUENCE(0));
1194 asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name);
1195 asn1_start_tag(data, ASN1_SET);
1196 while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
1198 struct ldap_val value;
1199 asn1_read_OctetString(data, &blob);
1200 value.data = blob.data;
1201 value.length = blob.length;
1202 add_value_to_attrib(mem_ctx, &value, attrib);
1203 data_blob_free(&blob);
1210 static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
1211 struct ldap_attribute **attributes,
1212 int *num_attributes)
1214 asn1_start_tag(data, ASN1_SEQUENCE(0));
1215 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1216 struct ldap_attribute attrib;
1217 ZERO_STRUCT(attrib);
1218 ldap_decode_attrib(mem_ctx, data, &attrib);
1219 add_attrib_to_array_talloc(mem_ctx, &attrib,
1220 attributes, num_attributes);
1225 BOOL ldap_decode(ASN1_DATA *data, struct ldap_message *msg)
1229 asn1_start_tag(data, ASN1_SEQUENCE(0));
1230 asn1_read_Integer(data, &msg->messageid);
1232 if (!asn1_peek_uint8(data, &tag))
1237 case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
1238 struct ldap_BindRequest *r = &msg->r.BindRequest;
1239 msg->type = LDAP_TAG_BindRequest;
1240 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_BindRequest));
1241 asn1_read_Integer(data, &r->version);
1242 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
1243 if (asn1_peek_tag(data, 0x80)) {
1245 r->creds.password = "";
1246 /* Mechanism 0 (SIMPLE) */
1247 asn1_start_tag(data, 0x80);
1248 pwlen = asn1_tag_remaining(data);
1250 char *pw = talloc(msg->mem_ctx, pwlen+1);
1251 asn1_read(data, pw, pwlen);
1253 r->creds.password = pw;
1261 case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
1262 struct ldap_BindResponse *r = &msg->r.BindResponse;
1263 msg->type = LDAP_TAG_BindResponse;
1264 ldap_decode_response(msg->mem_ctx,
1265 data, LDAP_TAG_BindResponse,
1270 case ASN1_APPLICATION(LDAP_TAG_UnbindRequest): {
1271 msg->type = LDAP_TAG_UnbindRequest;
1275 case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
1276 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
1277 msg->type = LDAP_TAG_SearchRequest;
1278 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_SearchRequest));
1279 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->basedn);
1280 asn1_read_enumerated(data, (int *)&(r->scope));
1281 asn1_read_enumerated(data, (int *)&(r->deref));
1282 asn1_read_Integer(data, &r->sizelimit);
1283 asn1_read_Integer(data, &r->timelimit);
1284 asn1_read_BOOLEAN2(data, &r->attributesonly);
1286 /* Maybe create a TALLOC_CTX for the filter? This can waste
1287 * quite a bit of memory recursing down. */
1288 ldap_decode_filter(msg->mem_ctx, data, &r->filter);
1290 asn1_start_tag(data, ASN1_SEQUENCE(0));
1292 r->num_attributes = 0;
1293 r->attributes = NULL;
1295 while (asn1_tag_remaining(data) > 0) {
1297 if (!asn1_read_OctetString_talloc(msg->mem_ctx, data,
1300 if (!add_string_to_array(msg->mem_ctx, attr,
1302 &r->num_attributes))
1311 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1312 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1313 msg->type = LDAP_TAG_SearchResultEntry;
1314 r->attributes = NULL;
1315 r->num_attributes = 0;
1316 asn1_start_tag(data,
1317 ASN1_APPLICATION(LDAP_TAG_SearchResultEntry));
1318 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
1319 ldap_decode_attribs(msg->mem_ctx, data, &r->attributes,
1320 &r->num_attributes);
1325 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1326 struct ldap_Result *r = &msg->r.SearchResultDone;
1327 msg->type = LDAP_TAG_SearchResultDone;
1328 ldap_decode_response(msg->mem_ctx, data,
1329 LDAP_TAG_SearchResultDone, r);
1333 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1334 /* struct ldap_SearchResRef *r = &msg->r.SearchResultReference; */
1335 msg->type = LDAP_TAG_SearchResultReference;
1339 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1340 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1341 msg->type = LDAP_TAG_ModifyRequest;
1342 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
1343 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
1344 asn1_start_tag(data, ASN1_SEQUENCE(0));
1349 while (asn1_tag_remaining(data) > 0) {
1350 struct ldap_mod mod;
1352 asn1_start_tag(data, ASN1_SEQUENCE(0));
1353 asn1_read_enumerated(data, &mod.type);
1354 ldap_decode_attrib(msg->mem_ctx, data, &mod.attrib);
1356 if (!add_mod_to_array_talloc(msg->mem_ctx, &mod,
1357 &r->mods, &r->num_mods))
1366 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1367 struct ldap_Result *r = &msg->r.ModifyResponse;
1368 msg->type = LDAP_TAG_ModifyResponse;
1369 ldap_decode_response(msg->mem_ctx, data,
1370 LDAP_TAG_ModifyResponse, r);
1374 case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1375 struct ldap_AddRequest *r = &msg->r.AddRequest;
1376 msg->type = LDAP_TAG_AddRequest;
1377 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_AddRequest));
1378 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
1380 r->attributes = NULL;
1381 r->num_attributes = 0;
1382 ldap_decode_attribs(msg->mem_ctx, data, &r->attributes,
1383 &r->num_attributes);
1389 case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1390 struct ldap_Result *r = &msg->r.AddResponse;
1391 msg->type = LDAP_TAG_AddResponse;
1392 ldap_decode_response(msg->mem_ctx, data,
1393 LDAP_TAG_AddResponse, r);
1397 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1398 struct ldap_DelRequest *r = &msg->r.DelRequest;
1401 msg->type = LDAP_TAG_DelRequest;
1402 asn1_start_tag(data,
1403 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
1404 len = asn1_tag_remaining(data);
1405 dn = talloc(msg->mem_ctx, len+1);
1408 asn1_read(data, dn, len);
1415 case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1416 struct ldap_Result *r = &msg->r.DelResponse;
1417 msg->type = LDAP_TAG_DelResponse;
1418 ldap_decode_response(msg->mem_ctx, data,
1419 LDAP_TAG_DelResponse, r);
1423 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1424 /* struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest; */
1425 msg->type = LDAP_TAG_ModifyDNRequest;
1429 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1430 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1431 msg->type = LDAP_TAG_ModifyDNResponse;
1432 ldap_decode_response(msg->mem_ctx, data,
1433 LDAP_TAG_ModifyDNResponse, r);
1437 case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1438 /* struct ldap_CompareRequest *r = &msg->r.CompareRequest; */
1439 msg->type = LDAP_TAG_CompareRequest;
1443 case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1444 struct ldap_Result *r = &msg->r.CompareResponse;
1445 msg->type = LDAP_TAG_CompareResponse;
1446 ldap_decode_response(msg->mem_ctx, data,
1447 LDAP_TAG_CompareResponse, r);
1451 case ASN1_APPLICATION(LDAP_TAG_AbandonRequest): {
1452 /* struct ldap_AbandonRequest *r = &msg->r.AbandonRequest; */
1453 msg->type = LDAP_TAG_AbandonRequest;
1457 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1458 /* struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest; */
1459 msg->type = LDAP_TAG_ExtendedRequest;
1463 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1464 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1465 msg->type = LDAP_TAG_ExtendedResponse;
1466 ldap_decode_response(msg->mem_ctx, data,
1467 LDAP_TAG_ExtendedResponse, &r->response);
1468 /* I have to come across an operation that actually sends
1469 * something back to really see what's going on. The currently
1470 * needed pwdchange does not send anything back. */
1472 r->value.data = NULL;
1473 r->value.length = 0;
1480 return ((!data->has_error) && (data->nesting == NULL));
1483 BOOL ldap_parse_basic_url(TALLOC_CTX *mem_ctx, const char *url,
1484 char **host, uint16 *port, BOOL *ldaps)
1489 const char *p = url;
1491 /* skip leading "URL:" (if any) */
1492 if ( strnequal( p, "URL:", 4 ) ) {
1496 /* Paranoia check */
1497 SMB_ASSERT(sizeof(protocol)>10 && sizeof(tmp_host)>254);
1499 sscanf(p, "%10[^:]://%254[^:/]:%d", protocol, tmp_host, &tmp_port);
1501 if (strequal(protocol, "ldap")) {
1504 } else if (strequal(protocol, "ldaps")) {
1508 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
1515 *host = talloc_strdup(mem_ctx, tmp_host);
1517 return (*host != NULL);
1520 struct ldap_connection *new_ldap_connection(void)
1522 TALLOC_CTX *mem_ctx = talloc_init("ldap_connection");
1523 struct ldap_connection *result;
1525 if (mem_ctx == NULL)
1528 result = talloc(mem_ctx, sizeof(*result));
1533 result->mem_ctx = mem_ctx;
1534 result->next_msgid = 1;
1535 result->outstanding = NULL;
1536 result->searchid = 0;
1537 result->search_entries = NULL;
1538 result->auth_dn = NULL;
1539 result->simple_pw = NULL;
1540 result->gensec = NULL;
1545 BOOL ldap_connect(struct ldap_connection *conn, const char *url)
1550 if (!ldap_parse_basic_url(conn->mem_ctx, url, &conn->host,
1551 &conn->port, &conn->ldaps))
1554 hp = sys_gethostbyname(conn->host);
1556 if ((hp == NULL) || (hp->h_addr == NULL))
1559 putip((char *)&ip, (char *)hp->h_addr);
1561 conn->sock = open_socket_out(SOCK_STREAM, &ip, conn->port, LDAP_CONNECTION_TIMEOUT);
1563 return (conn->sock >= 0);
1566 BOOL ldap_set_simple_creds(struct ldap_connection *conn,
1567 const char *dn, const char *password)
1569 conn->auth_dn = talloc_strdup(conn->mem_ctx, dn);
1570 conn->simple_pw = talloc_strdup(conn->mem_ctx, password);
1572 return ((conn->auth_dn != NULL) && (conn->simple_pw != NULL));
1575 struct ldap_message *new_ldap_message(void)
1577 TALLOC_CTX *mem_ctx = talloc_init("ldap_message");
1578 struct ldap_message *result;
1580 if (mem_ctx == NULL)
1583 result = talloc(mem_ctx, sizeof(*result));
1588 result->mem_ctx = mem_ctx;
1592 void destroy_ldap_message(struct ldap_message *msg)
1595 talloc_destroy(msg->mem_ctx);
1598 BOOL ldap_send_msg(struct ldap_connection *conn, struct ldap_message *msg,
1599 const struct timeval *endtime)
1603 struct ldap_queue_entry *entry;
1605 msg->messageid = conn->next_msgid++;
1607 if (!ldap_encode(msg, &request))
1610 result = (write_data_until(conn->sock, request.data, request.length,
1611 endtime) == request.length);
1613 data_blob_free(&request);
1618 /* abandon and unbind don't expect results */
1620 if ((msg->type == LDAP_TAG_AbandonRequest) ||
1621 (msg->type == LDAP_TAG_UnbindRequest))
1624 entry = malloc(sizeof(*entry));
1629 entry->msgid = msg->messageid;
1631 DLIST_ADD(conn->outstanding, entry);
1636 BOOL ldap_receive_msg(struct ldap_connection *conn, struct ldap_message *msg,
1637 const struct timeval *endtime)
1639 struct asn1_data data;
1642 if (!asn1_read_sequence_until(conn->sock, &data, endtime))
1645 result = ldap_decode(&data, msg);
1651 static struct ldap_message *recv_from_queue(struct ldap_connection *conn,
1654 struct ldap_queue_entry *e;
1656 for (e = conn->outstanding; e != NULL; e = e->next) {
1658 if (e->msgid == msgid) {
1659 struct ldap_message *result = e->msg;
1660 DLIST_REMOVE(conn->outstanding, e);
1669 static void add_search_entry(struct ldap_connection *conn,
1670 struct ldap_message *msg)
1672 struct ldap_queue_entry *e = malloc(sizeof *e);
1678 DLIST_ADD_END(conn->search_entries, e, struct ldap_queue_entry *);
1682 static void fill_outstanding_request(struct ldap_connection *conn,
1683 struct ldap_message *msg)
1685 struct ldap_queue_entry *e;
1687 for (e = conn->outstanding; e != NULL; e = e->next) {
1688 if (e->msgid == msg->messageid) {
1694 /* This reply has not been expected, destroy the incoming msg */
1695 destroy_ldap_message(msg);
1699 struct ldap_message *ldap_receive(struct ldap_connection *conn, int msgid,
1700 const struct timeval *endtime)
1702 struct ldap_message *result = recv_from_queue(conn, msgid);
1708 struct asn1_data data;
1711 result = new_ldap_message();
1713 if (!asn1_read_sequence_until(conn->sock, &data, endtime))
1716 res = ldap_decode(&data, result);
1722 if (result->messageid == msgid)
1725 if (result->type == LDAP_TAG_SearchResultEntry) {
1726 add_search_entry(conn, result);
1728 fill_outstanding_request(conn, result);
1735 struct ldap_message *ldap_transaction(struct ldap_connection *conn,
1736 struct ldap_message *request)
1738 if (!ldap_send_msg(conn, request, NULL))
1741 return ldap_receive(conn, request->messageid, NULL);
1744 int ldap_bind_simple(struct ldap_connection *conn, const char *userdn, const char *password)
1746 struct ldap_message *response;
1747 struct ldap_message *msg;
1748 const char *dn, *pw;
1749 int result = LDAP_OTHER;
1757 if (conn->auth_dn) {
1767 if (conn->simple_pw) {
1768 pw = conn->simple_pw;
1774 msg = new_ldap_simple_bind_msg(dn, pw);
1778 response = ldap_transaction(conn, msg);
1780 destroy_ldap_message(msg);
1784 result = response->r.BindResponse.response.resultcode;
1786 destroy_ldap_message(msg);
1787 destroy_ldap_message(response);
1792 int ldap_bind_sasl(struct ldap_connection *conn, const char *username, const char *domain, const char *password)
1795 TALLOC_CTX *mem_ctx = NULL;
1796 struct ldap_message *response;
1797 struct ldap_message *msg;
1798 DATA_BLOB input = data_blob(NULL, 0);
1799 DATA_BLOB output = data_blob(NULL, 0);
1800 int result = LDAP_OTHER;
1805 status = gensec_client_start(&conn->gensec);
1806 if (!NT_STATUS_IS_OK(status)) {
1807 DEBUG(0, ("Failed to start GENSEC engine (%s)\n", nt_errstr(status)));
1811 status = gensec_set_domain(conn->gensec, domain);
1812 if (!NT_STATUS_IS_OK(status)) {
1813 DEBUG(1, ("Failed to start set GENSEC client domain to %s: %s\n",
1814 domain, nt_errstr(status)));
1818 status = gensec_set_username(conn->gensec, username);
1819 if (!NT_STATUS_IS_OK(status)) {
1820 DEBUG(1, ("Failed to start set GENSEC client username to %s: %s\n",
1821 username, nt_errstr(status)));
1825 status = gensec_set_password(conn->gensec, password);
1826 if (!NT_STATUS_IS_OK(status)) {
1827 DEBUG(1, ("Failed to start set GENSEC client password: %s\n",
1828 nt_errstr(status)));
1832 status = gensec_set_target_hostname(conn->gensec, conn->host);
1833 if (!NT_STATUS_IS_OK(status)) {
1834 DEBUG(1, ("Failed to start set GENSEC target hostname: %s\n",
1835 nt_errstr(status)));
1839 status = gensec_start_mech_by_sasl_name(conn->gensec, "GSS-SPNEGO");
1840 if (!NT_STATUS_IS_OK(status)) {
1841 DEBUG(1, ("Failed to start set GENSEC client SPNEGO mechanism: %s\n",
1842 nt_errstr(status)));
1846 mem_ctx = talloc_init("ldap_bind_sasl");
1850 status = gensec_update(conn->gensec, mem_ctx,
1855 if (NT_STATUS_IS_OK(status) && output.length == 0) {
1858 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
1862 msg = new_ldap_sasl_bind_msg("GSS-SPNEGO", &output);
1866 response = ldap_transaction(conn, msg);
1867 destroy_ldap_message(msg);
1869 result = response->r.BindResponse.response.resultcode;
1871 if (result != LDAP_SUCCESS && result != LDAP_SASL_BIND_IN_PROGRESS) {
1875 status = gensec_update(conn->gensec, mem_ctx,
1876 response->r.BindResponse.SASL.creds,
1879 destroy_ldap_message(response);
1884 gensec_end(&conn->gensec);
1886 talloc_destroy(mem_ctx);
1891 BOOL ldap_setup_connection(struct ldap_connection *conn,
1892 const char *url, const char *userdn, const char *password)
1896 if (!ldap_connect(conn, url)) {
1900 result = ldap_bind_simple(conn, userdn, password);
1901 if (result == LDAP_SUCCESS) {
1908 BOOL ldap_setup_connection_with_sasl(struct ldap_connection *conn, const char *url, const char *username, const char *domain, const char *password)
1912 if (!ldap_connect(conn, url)) {
1916 result = ldap_bind_sasl(conn, username, domain, password);
1917 if (result == LDAP_SUCCESS) {
1924 static BOOL ldap_abandon_message(struct ldap_connection *conn, int msgid,
1925 const struct timeval *endtime)
1927 struct ldap_message *msg = new_ldap_message();
1933 msg->type = LDAP_TAG_AbandonRequest;
1934 msg->r.AbandonRequest.messageid = msgid;
1936 result = ldap_send_msg(conn, msg, endtime);
1937 destroy_ldap_message(msg);
1941 struct ldap_message *new_ldap_search_message(const char *base,
1942 enum ldap_scope scope,
1945 const char **attributes)
1947 struct ldap_message *res = new_ldap_message();
1952 res->type = LDAP_TAG_SearchRequest;
1953 res->r.SearchRequest.basedn = base;
1954 res->r.SearchRequest.scope = scope;
1955 res->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
1956 res->r.SearchRequest.timelimit = 0;
1957 res->r.SearchRequest.sizelimit = 0;
1958 res->r.SearchRequest.attributesonly = False;
1959 res->r.SearchRequest.filter = filter;
1960 res->r.SearchRequest.num_attributes = num_attributes;
1961 res->r.SearchRequest.attributes = attributes;
1965 struct ldap_message *new_ldap_simple_bind_msg(const char *dn, const char *pw)
1967 struct ldap_message *res = new_ldap_message();
1972 res->type = LDAP_TAG_BindRequest;
1973 res->r.BindRequest.version = 3;
1974 res->r.BindRequest.dn = talloc_strdup(res->mem_ctx, dn);
1975 res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SIMPLE;
1976 res->r.BindRequest.creds.password = talloc_strdup(res->mem_ctx, pw);
1980 struct ldap_message *new_ldap_sasl_bind_msg(const char *sasl_mechanism, DATA_BLOB *secblob)
1982 struct ldap_message *res = new_ldap_message();
1987 res->type = LDAP_TAG_BindRequest;
1988 res->r.BindRequest.version = 3;
1989 res->r.BindRequest.dn = "";
1990 res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SASL;
1991 res->r.BindRequest.creds.SASL.mechanism = talloc_strdup(res->mem_ctx, sasl_mechanism);
1992 res->r.BindRequest.creds.SASL.secblob = *secblob;
1996 BOOL ldap_setsearchent(struct ldap_connection *conn, struct ldap_message *msg,
1997 const struct timeval *endtime)
1999 if ((conn->searchid != 0) &&
2000 (!ldap_abandon_message(conn, conn->searchid, endtime)))
2003 conn->searchid = conn->next_msgid;
2004 return ldap_send_msg(conn, msg, endtime);
2007 struct ldap_message *ldap_getsearchent(struct ldap_connection *conn,
2008 const struct timeval *endtime)
2010 struct ldap_message *result;
2012 if (conn->search_entries != NULL) {
2013 struct ldap_queue_entry *e = conn->search_entries;
2016 DLIST_REMOVE(conn->search_entries, e);
2021 result = ldap_receive(conn, conn->searchid, endtime);
2023 if (result->type == LDAP_TAG_SearchResultEntry)
2026 if (result->type == LDAP_TAG_SearchResultDone) {
2027 /* TODO: Handle Paged Results */
2028 destroy_ldap_message(result);
2032 /* TODO: Handle Search References here */
2036 void ldap_endsearchent(struct ldap_connection *conn,
2037 const struct timeval *endtime)
2039 struct ldap_queue_entry *e;
2041 e = conn->search_entries;
2044 struct ldap_queue_entry *next = e->next;
2045 DLIST_REMOVE(conn->search_entries, e);
2051 struct ldap_message *ldap_searchone(struct ldap_connection *conn,
2052 struct ldap_message *msg,
2053 const struct timeval *endtime)
2055 struct ldap_message *res1, *res2 = NULL;
2056 if (!ldap_setsearchent(conn, msg, endtime))
2059 res1 = ldap_getsearchent(conn, endtime);
2062 res2 = ldap_getsearchent(conn, endtime);
2064 ldap_endsearchent(conn, endtime);
2070 /* More than one entry */
2071 destroy_ldap_message(res1);
2072 destroy_ldap_message(res2);
2079 BOOL ldap_find_single_value(struct ldap_message *msg, const char *attr,
2083 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
2085 if (msg->type != LDAP_TAG_SearchResultEntry)
2088 for (i=0; i<r->num_attributes; i++) {
2089 if (strequal(attr, r->attributes[i].name)) {
2090 if (r->attributes[i].num_values != 1)
2093 *value = r->attributes[i].values[0];
2100 BOOL ldap_find_single_string(struct ldap_message *msg, const char *attr,
2101 TALLOC_CTX *mem_ctx, char **value)
2105 if (!ldap_find_single_value(msg, attr, &blob))
2108 *value = talloc(mem_ctx, blob.length+1);
2113 memcpy(*value, blob.data, blob.length);
2114 (*value)[blob.length] = '\0';
2118 BOOL ldap_find_single_int(struct ldap_message *msg, const char *attr,
2126 if (!ldap_find_single_value(msg, attr, &blob))
2129 val = malloc(blob.length+1);
2133 memcpy(val, blob.data, blob.length);
2134 val[blob.length] = '\0';
2139 *value = strtol(val, NULL, 10);
2149 int ldap_error(struct ldap_connection *conn)
2154 NTSTATUS ldap2nterror(int ldaperror)
2156 return NT_STATUS_OK;