5b22825da4b331f2482c378a60c8895560877260
[kai/samba.git] / source / libcli / ldap / ldap.c
1 /* 
2    Unix SMB/CIFS mplementation.
3    LDAP protocol helper functions for SAMBA
4    
5    Copyright (C) Andrew Tridgell  2004
6    Copyright (C) Volker Lendecke 2004
7     
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.
12    
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.
17    
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.
21    
22 */
23
24 #include "includes.h"
25
26 /****************************************************************************
27  *
28  * LDAP filter parser -- main routine is ldap_parse_filter
29  *
30  * Shamelessly stolen and adapted from ldb.
31  *
32  ***************************************************************************/
33
34 /* Hmm. A blob might be more appropriate here :-) */
35
36 struct ldap_val {
37         unsigned int length;
38         void *data;
39 };
40
41 enum ldap_parse_op {LDAP_OP_SIMPLE, LDAP_OP_AND, LDAP_OP_OR, LDAP_OP_NOT};
42
43 struct ldap_parse_tree {
44         enum ldap_parse_op operation;
45         union {
46                 struct {
47                         char *attr;
48                         struct ldap_val value;
49                 } simple;
50                 struct {
51                         unsigned int num_elements;
52                         struct ldap_parse_tree **elements;
53                 } list;
54                 struct {
55                         struct ldap_parse_tree *child;
56                 } not;
57         } u;
58 };
59
60 #define LDAP_ALL_SEP "()&|=!"
61 #define LDAP_CONNECTION_TIMEOUT 10000
62
63 /*
64   return next token element. Caller frees
65 */
66 static char *ldap_parse_lex(TALLOC_CTX *mem_ctx, const char **s,
67                            const char *sep)
68 {
69         const char *p = *s;
70         char *ret;
71
72         while (isspace(*p)) {
73                 p++;
74         }
75         *s = p;
76
77         if (*p == 0) {
78                 return NULL;
79         }
80
81         if (strchr(sep, *p)) {
82                 (*s) = p+1;
83                 ret = talloc_strndup(mem_ctx, p, 1);
84                 if (!ret) {
85                         errno = ENOMEM;
86                 }
87                 return ret;
88         }
89
90         while (*p && (isalnum(*p) || !strchr(sep, *p))) {
91                 p++;
92         }
93
94         if (p == *s) {
95                 return NULL;
96         }
97
98         ret = talloc_strndup(mem_ctx, *s, p - *s);
99         if (!ret) {
100                 errno = ENOMEM;
101         }
102
103         *s = p;
104
105         return ret;
106 }
107
108
109 /*
110   find a matching close brace in a string
111 */
112 static const char *match_brace(const char *s)
113 {
114         unsigned int count = 0;
115         while (*s && (count != 0 || *s != ')')) {
116                 if (*s == '(') {
117                         count++;
118                 }
119                 if (*s == ')') {
120                         count--;
121                 }
122                 s++;
123         }
124         if (! *s) {
125                 return NULL;
126         }
127         return s;
128 }
129
130 static struct ldap_parse_tree *ldap_parse_filter(TALLOC_CTX *mem_ctx,
131                                                const char **s);
132
133 /*
134   <simple> ::= <attributetype> <filtertype> <attributevalue>
135 */
136 static struct ldap_parse_tree *ldap_parse_simple(TALLOC_CTX *mem_ctx,
137                                                const char *s)
138 {
139         char *eq, *val, *l;
140         struct ldap_parse_tree *ret;
141
142         l = ldap_parse_lex(mem_ctx, &s, LDAP_ALL_SEP);
143         if (!l) {
144                 return NULL;
145         }
146
147         if (strchr("()&|=", *l))
148                 return NULL;
149
150         eq = ldap_parse_lex(mem_ctx, &s, LDAP_ALL_SEP);
151         if (!eq || strcmp(eq, "=") != 0)
152                 return NULL;
153
154         val = ldap_parse_lex(mem_ctx, &s, ")");
155         if (val && strchr("()&|", *val))
156                 return NULL;
157         
158         ret = talloc(mem_ctx, sizeof(*ret));
159         if (!ret) {
160                 errno = ENOMEM;
161                 return NULL;
162         }
163
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;
168
169         return ret;
170 }
171
172
173 /*
174   parse a filterlist
175   <and> ::= '&' <filterlist>
176   <or> ::= '|' <filterlist>
177   <filterlist> ::= <filter> | <filter> <filterlist>
178 */
179 static struct ldap_parse_tree *ldap_parse_filterlist(TALLOC_CTX *mem_ctx,
180                                                    enum ldap_parse_op op,
181                                                    const char *s)
182 {
183         struct ldap_parse_tree *ret, *next;
184
185         ret = talloc(mem_ctx, sizeof(*ret));
186
187         if (!ret) {
188                 errno = ENOMEM;
189                 return NULL;
190         }
191
192         ret->operation = op;
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) {
196                 errno = ENOMEM;
197                 return NULL;
198         }
199
200         ret->u.list.elements[0] = ldap_parse_filter(mem_ctx, &s);
201         if (!ret->u.list.elements[0]) {
202                 return NULL;
203         }
204
205         while (isspace(*s)) s++;
206
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));
212                 if (!e) {
213                         errno = ENOMEM;
214                         return NULL;
215                 }
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++;
220         }
221
222         return ret;
223 }
224
225
226 /*
227   <not> ::= '!' <filter>
228 */
229 static struct ldap_parse_tree *ldap_parse_not(TALLOC_CTX *mem_ctx, const char *s)
230 {
231         struct ldap_parse_tree *ret;
232
233         ret = talloc(mem_ctx, sizeof(*ret));
234         if (!ret) {
235                 errno = ENOMEM;
236                 return NULL;
237         }
238
239         ret->operation = LDAP_OP_NOT;
240         ret->u.not.child = ldap_parse_filter(mem_ctx, &s);
241         if (!ret->u.not.child)
242                 return NULL;
243
244         return ret;
245 }
246
247 /*
248   parse a filtercomp
249   <filtercomp> ::= <and> | <or> | <not> | <simple>
250 */
251 static struct ldap_parse_tree *ldap_parse_filtercomp(TALLOC_CTX *mem_ctx,
252                                                    const char *s)
253 {
254         while (isspace(*s)) s++;
255
256         switch (*s) {
257         case '&':
258                 return ldap_parse_filterlist(mem_ctx, LDAP_OP_AND, s+1);
259
260         case '|':
261                 return ldap_parse_filterlist(mem_ctx, LDAP_OP_OR, s+1);
262
263         case '!':
264                 return ldap_parse_not(mem_ctx, s+1);
265
266         case '(':
267         case ')':
268                 return NULL;
269         }
270
271         return ldap_parse_simple(mem_ctx, s);
272 }
273
274
275 /*
276   <filter> ::= '(' <filtercomp> ')'
277 */
278 static struct ldap_parse_tree *ldap_parse_filter(TALLOC_CTX *mem_ctx,
279                                                const char **s)
280 {
281         char *l, *s2;
282         const char *p, *p2;
283         struct ldap_parse_tree *ret;
284
285         l = ldap_parse_lex(mem_ctx, s, LDAP_ALL_SEP);
286         if (!l) {
287                 return NULL;
288         }
289
290         if (strcmp(l, "(") != 0) {
291                 return NULL;
292         }
293
294         p = match_brace(*s);
295         if (!p) {
296                 return NULL;
297         }
298         p2 = p + 1;
299
300         s2 = talloc_strndup(mem_ctx, *s, p - *s);
301         if (!s2) {
302                 errno = ENOMEM;
303                 return NULL;
304         }
305
306         ret = ldap_parse_filtercomp(mem_ctx, s2);
307
308         *s = p2;
309
310         return ret;
311 }
312
313 /*
314   main parser entry point. Takes a search string and returns a parse tree
315
316   expression ::= <simple> | <filter>
317 */
318 static struct ldap_parse_tree *ldap_parse_tree(TALLOC_CTX *mem_ctx, const char *s)
319 {
320         while (isspace(*s)) s++;
321
322         if (*s == '(') {
323                 return ldap_parse_filter(mem_ctx, &s);
324         }
325
326         return ldap_parse_simple(mem_ctx, s);
327 }
328
329 static BOOL ldap_push_filter(ASN1_DATA *data, struct ldap_parse_tree *tree)
330 {
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));
339                         asn1_pop_tag(data);
340                         return !data->has_error;
341                 }
342
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);
349                 asn1_pop_tag(data);
350                 break;
351         }
352
353         case LDAP_OP_AND: {
354                 int i;
355
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]);
359                 }
360                 asn1_pop_tag(data);
361                 break;
362         }
363
364         case LDAP_OP_OR: {
365                 int i;
366
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]);
370                 }
371                 asn1_pop_tag(data);
372                 break;
373         }
374         default:
375                 return False;
376         }
377         return !data->has_error;
378 }
379
380 /****************************************************************************
381  *
382  * LDIF parser
383  *
384  * Shamelessly stolen and adapted from Samba 4.
385  *
386  ***************************************************************************/
387
388 /*
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
391
392   caller frees
393 */
394 static char *next_chunk(TALLOC_CTX *mem_ctx,
395                         int (*fgetc_fn)(void *), void *private_data)
396 {
397         size_t alloc_size=0, chunk_size = 0;
398         char *chunk = NULL;
399         int c;
400         int in_comment = 0;
401
402         while ((c = fgetc_fn(private_data)) != EOF) {
403                 if (chunk_size+1 >= alloc_size) {
404                         char *c2;
405                         alloc_size += 1024;
406                         c2 = talloc_realloc(mem_ctx, chunk, alloc_size);
407                         if (!c2) {
408                                 errno = ENOMEM;
409                                 return NULL;
410                         }
411                         chunk = c2;
412                 }
413
414                 if (in_comment) {
415                         if (c == '\n') {
416                                 in_comment = 0;
417                         }
418                         continue;                       
419                 }
420                 
421                 /* handle continuation lines - see RFC2849 */
422                 if (c == ' ' && chunk_size > 1 &&
423                     chunk[chunk_size-1] == '\n') {
424                         chunk_size--;
425                         continue;
426                 }
427                 
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;
432                         return chunk;
433                 }
434
435                 if (c == '#' &&
436                     (chunk_size == 0 || chunk[chunk_size-1] == '\n')) {
437                         in_comment = 1;
438                         continue;
439                 }
440
441                 /* ignore leading blank lines */
442                 if (chunk_size == 0 && c == '\n') {
443                         continue;
444                 }
445
446                 chunk[chunk_size++] = c;
447         }
448
449         if (chunk) {
450                 chunk[chunk_size] = 0;
451         }
452
453         return chunk;
454 }
455
456 /* simple ldif attribute parser */
457 static int next_attr(char **s, const char **attr, struct ldap_val *value)
458 {
459         char *p;
460         int base64_encoded = 0;
461
462         if (strncmp(*s, "-\n", 2) == 0) {
463                 value->length = 0;
464                 *attr = "-";
465                 *s += 2;
466                 return 0;
467         }
468
469         p = strchr(*s, ':');
470         if (!p) {
471                 return -1;
472         }
473
474         *p++ = 0;
475
476         if (*p == ':') {
477                 base64_encoded = 1;
478                 p++;
479         }
480
481         *attr = *s;
482
483         while (isspace(*p)) {
484                 p++;
485         }
486
487         value->data = p;
488
489         p = strchr(p, '\n');
490
491         if (!p) {
492                 value->length = strlen((char *)value->data);
493                 *s = ((char *)value->data) + value->length;
494         } else {
495                 value->length = p - (char *)value->data;
496                 *s = p+1;
497                 *p = 0;
498         }
499
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';
505         }
506
507         return 0;
508 }
509
510 static BOOL add_value_to_attrib(TALLOC_CTX *mem_ctx, struct ldap_val *value,
511                                 struct ldap_attribute *attrib)
512 {
513         attrib->values = talloc_realloc(mem_ctx, attrib->values,
514                                         sizeof(*attrib->values) *
515                                         (attrib->num_values+1));
516         if (attrib->values == NULL)
517                 return False;
518
519         attrib->values[attrib->num_values] =
520                 data_blob_talloc(mem_ctx, value->data, value->length);
521         attrib->num_values += 1;
522         return True;
523 }
524
525 static BOOL fill_add_attributes(struct ldap_message *msg, char **chunk)
526 {
527         struct ldap_AddRequest *r = &msg->r.AddRequest;
528         const char *attr_name;
529         struct ldap_val value;
530
531         r->num_attributes = 0;
532         r->attributes = NULL;
533
534         while (next_attr(chunk, &attr_name, &value) == 0) {
535                 int i;
536                 struct ldap_attribute *attrib = NULL;
537                 
538                 for (i=0; i<r->num_attributes; i++) {
539                         if (strequal(r->attributes[i].name, attr_name)) {
540                                 attrib = &r->attributes[i];
541                                 break;
542                         }
543                 }
544
545                 if (attrib == NULL) {
546                         r->attributes = talloc_realloc(msg->mem_ctx,
547                                                        r->attributes,
548                                                        sizeof(*r->attributes) *
549                                                        (r->num_attributes+1));
550                         if (r->attributes == NULL)
551                                 return False;
552
553                         attrib = &(r->attributes[r->num_attributes]);
554                         r->num_attributes += 1;
555                         ZERO_STRUCTP(attrib);
556                         attrib->name = talloc_strdup(msg->mem_ctx,
557                                                      attr_name);
558                 }
559
560                 if (!add_value_to_attrib(msg->mem_ctx, &value, attrib))
561                         return False;
562         }
563         return True;
564 }
565
566 static BOOL add_mod_to_array_talloc(TALLOC_CTX *mem_ctx,
567                                     struct ldap_mod *mod,
568                                     struct ldap_mod **mods,
569                                     int *num_mods)
570 {
571         *mods = talloc_realloc(mem_ctx, *mods,
572                                sizeof(**mods) * ((*num_mods)+1));
573
574         if (*mods == NULL)
575                 return False;
576
577         (*mods)[*num_mods] = *mod;
578         *num_mods += 1;
579         return True;
580 }
581
582 static BOOL fill_mods(struct ldap_message *msg, char **chunk)
583 {
584         struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
585         const char *attr_name;
586         struct ldap_val value;
587
588         r->num_mods = 0;
589         r->mods = NULL;
590
591         while (next_attr(chunk, &attr_name, &value) == 0) {
592
593                 struct ldap_mod mod;
594                 mod.type = LDAP_MODIFY_NONE;
595
596                 mod.attrib.name = talloc_strdup(msg->mem_ctx, value.data);
597
598                 if (strequal(attr_name, "add"))
599                         mod.type = LDAP_MODIFY_ADD;
600
601                 if (strequal(attr_name, "delete"))
602                         mod.type = LDAP_MODIFY_DELETE;
603
604                 if (strequal(attr_name, "replace"))
605                         mod.type = LDAP_MODIFY_REPLACE;
606
607                 if (mod.type == LDAP_MODIFY_NONE) {
608                         DEBUG(2, ("ldif modification type %s unsupported\n",
609                                   attr_name));
610                         return False;
611                 }
612
613                 mod.attrib.num_values = 0;
614                 mod.attrib.values = NULL;
615
616                 while (next_attr(chunk, &attr_name, &value) == 0) {
617                         if (strequal(attr_name, "-"))
618                                 break;
619                         if (!strequal(attr_name, mod.attrib.name)) {
620                                 DEBUG(3, ("attrib name %s does not "
621                                           "match %s\n", attr_name,
622                                           mod.attrib.name));
623                                 return False;
624                         }
625                         if (!add_value_to_attrib(msg->mem_ctx, &value,
626                                                  &mod.attrib)) {
627                                 DEBUG(3, ("Could not add value\n"));
628                                 return False;
629                         }
630                 }
631
632                 if (!add_mod_to_array_talloc(msg->mem_ctx, &mod, &r->mods,
633                                              &r->num_mods))
634                         return False;
635         }
636
637         return True;
638 }
639
640 /*
641  read from a LDIF source, creating a ldap_message
642 */
643 static struct ldap_message *ldif_read(int (*fgetc_fn)(void *),
644                                       void *private_data)
645 {
646         struct ldap_message *msg;
647         const char *attr=NULL;
648         const char *dn;
649         char *chunk=NULL, *s;
650         struct ldap_val value;
651
652         value.data = NULL;
653
654         msg = new_ldap_message();
655         if (msg == NULL)
656                 return NULL;
657
658         chunk = next_chunk(msg->mem_ctx, fgetc_fn, private_data);
659         if (!chunk) {
660                 goto failed;
661         }
662
663         s = chunk;
664
665         if (next_attr(&s, &attr, &value) != 0) {
666                 goto failed;
667         }
668         
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",
672                           attr));
673                 goto failed;
674         }
675
676         dn = talloc_strdup(msg->mem_ctx, value.data);
677
678         if (next_attr(&s, &attr, &value) != 0) {
679                 goto failed;
680         }
681
682         if (!strequal(attr, "changetype")) {
683                 DEBUG(5, ("Error: Second line of ldif must be a changetype "
684                           "not '%s'\n",  attr));
685                 goto failed;
686         }
687
688         if (strequal(value.data, "delete")) {
689                 msg->type = LDAP_TAG_DelRequest;
690                 msg->r.DelRequest.dn = dn;
691                 return msg;
692         }
693
694         if (strequal(value.data, "add")) {
695                 msg->type = LDAP_TAG_AddRequest;
696
697                 msg->r.AddRequest.dn = dn;
698
699                 if (!fill_add_attributes(msg, &s))
700                         goto failed;
701
702                 return msg;
703         }
704
705         if (strequal(value.data, "modify")) {
706                 msg->type = LDAP_TAG_ModifyRequest;
707
708                 msg->r.ModifyRequest.dn = dn;
709
710                 if (!fill_mods(msg, &s))
711                         goto failed;
712
713                 return msg;
714         }
715
716         DEBUG(3, ("changetype %s not supported\n", (char *)value.data));
717
718 failed:
719         destroy_ldap_message(msg);
720         return NULL;
721 }
722
723 /*
724   a wrapper around ldif_read() for reading from const char*
725 */
726 struct ldif_read_string_state {
727         const char *s;
728 };
729
730 static int fgetc_string(void *private_data)
731 {
732         struct ldif_read_string_state *state = private_data;
733         if (state->s[0] != 0) {
734                 return *state->s++;
735         }
736         return EOF;
737 }
738
739 struct ldap_message *ldap_ldif2msg(const char *s)
740 {
741         struct ldif_read_string_state state;
742         state.s = s;
743         return ldif_read(fgetc_string, &state);
744 }
745
746 static void ldap_encode_response(enum ldap_request_tag tag,
747                                  struct ldap_Result *result,
748                                  ASN1_DATA *data)
749 {
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));
760         asn1_pop_tag(data);
761 }
762
763 BOOL ldap_encode(struct ldap_message *msg, DATA_BLOB *result)
764 {
765         ASN1_DATA data;
766         int i, j;
767
768         ZERO_STRUCT(data);
769         asn1_push_tag(&data, ASN1_SEQUENCE(0));
770         asn1_write_Integer(&data, msg->messageid);
771
772         switch (msg->type) {
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);
779
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));
786                         asn1_pop_tag(&data);
787                         break;
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);
795                         asn1_pop_tag(&data);
796                         break;
797                 default:
798                         return False;
799                 }
800
801                 asn1_pop_tag(&data);
802                 asn1_pop_tag(&data);
803                 break;
804         }
805         case LDAP_TAG_BindResponse: {
806                 struct ldap_BindResponse *r = &msg->r.BindResponse;
807                 ldap_encode_response(msg->type, &r->response, &data);
808                 break;
809         }
810         case LDAP_TAG_UnbindRequest: {
811 /*              struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
812                 break;
813         }
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);
823
824                 {
825                         TALLOC_CTX *mem_ctx = talloc_init("ldap_parse_tree");
826                         struct ldap_parse_tree *tree;
827
828                         if (mem_ctx == NULL)
829                                 return False;
830
831                         tree = ldap_parse_tree(mem_ctx, r->filter);
832
833                         if (tree == NULL)
834                                 return False;
835
836                         ldap_push_filter(&data, tree);
837
838                         talloc_destroy(mem_ctx);
839                 }
840
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]));
845                 }
846                 asn1_pop_tag(&data);
847
848                 asn1_pop_tag(&data);
849                 break;
850         }
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,
860                                                strlen(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);
866                         }
867                         asn1_pop_tag(&data);
868                         asn1_pop_tag(&data);
869                 }
870                 asn1_pop_tag(&data);
871                 asn1_pop_tag(&data);
872                 break;
873         }
874         case LDAP_TAG_SearchResultDone: {
875                 struct ldap_Result *r = &msg->r.SearchResultDone;
876                 ldap_encode_response(msg->type, r, &data);
877                 break;
878         }
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));
884
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);
897         
898                         }
899                         asn1_pop_tag(&data);
900                         asn1_pop_tag(&data);
901                         asn1_pop_tag(&data);
902                 }
903                 
904                 asn1_pop_tag(&data);
905                 asn1_pop_tag(&data);
906                 break;
907         }
908         case LDAP_TAG_ModifyResponse: {
909                 struct ldap_Result *r = &msg->r.ModifyResponse;
910                 ldap_encode_response(msg->type, r, &data);
911                 break;
912         }
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));
918
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);
929                         }
930                         asn1_pop_tag(&data);
931                         asn1_pop_tag(&data);
932                 }
933                 asn1_pop_tag(&data);
934                 asn1_pop_tag(&data);
935                 break;
936         }
937         case LDAP_TAG_AddResponse: {
938                 struct ldap_Result *r = &msg->r.AddResponse;
939                 ldap_encode_response(msg->type, r, &data);
940                 break;
941         }
942         case LDAP_TAG_DelRequest: {
943                 struct ldap_DelRequest *r = &msg->r.DelRequest;
944                 asn1_push_tag(&data,
945                               ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
946                 asn1_write(&data, r->dn, strlen(r->dn));
947                 asn1_pop_tag(&data);
948                 break;
949         }
950         case LDAP_TAG_DelResponse: {
951                 struct ldap_Result *r = &msg->r.DelResponse;
952                 ldap_encode_response(msg->type, r, &data);
953                 break;
954         }
955         case LDAP_TAG_ModifyDNRequest: {
956                 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
957                 asn1_push_tag(&data,
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));
966                         asn1_pop_tag(&data);
967                 }
968                 asn1_pop_tag(&data);
969                 break;
970         }
971         case LDAP_TAG_ModifyDNResponse: {
972 /*              struct ldap_Result *r = &msg->r.ModifyDNResponse; */
973                 break;
974         }
975         case LDAP_TAG_CompareRequest: {
976                 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
977                 asn1_push_tag(&data,
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,
984                                        strlen(r->value));
985                 asn1_pop_tag(&data);
986                 asn1_pop_tag(&data);
987                 break;
988         }
989         case LDAP_TAG_CompareResponse: {
990 /*              struct ldap_Result *r = &msg->r.CompareResponse; */
991                 break;
992         }
993         case LDAP_TAG_AbandonRequest: {
994                 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
995                 asn1_push_tag(&data,
996                               ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest));
997                 asn1_write_Integer(&data, r->messageid);
998                 asn1_pop_tag(&data);
999                 break;
1000         }
1001         case LDAP_TAG_SearchResultReference: {
1002 /*              struct ldap_SearchResRef *r = &msg->r.SearchResultReference; */
1003                 break;
1004         }
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);
1015                 break;
1016         }
1017         case LDAP_TAG_ExtendedResponse: {
1018                 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1019                 ldap_encode_response(msg->type, &r->response, &data);
1020                 break;
1021         }
1022         default:
1023                 return False;
1024         }
1025
1026         asn1_pop_tag(&data);
1027         *result = data_blob(data.data, data.length);
1028         asn1_free(&data);
1029         return True;
1030 }
1031
1032 static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
1033                                       DATA_BLOB blob)
1034 {
1035         char *result = talloc(mem_ctx, blob.length+1);
1036         memcpy(result, blob.data, blob.length);
1037         result[blob.length] = '\0';
1038         return result;
1039 }
1040
1041 static BOOL asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
1042                                          ASN1_DATA *data,
1043                                          const char **result)
1044 {
1045         DATA_BLOB string;
1046         if (!asn1_read_OctetString(data, &string))
1047                 return False;
1048         *result = blob2string_talloc(mem_ctx, string);
1049         data_blob_free(&string);
1050         return True;
1051 }
1052
1053 static void ldap_decode_response(TALLOC_CTX *mem_ctx,
1054                                  ASN1_DATA *data,
1055                                  enum ldap_request_tag tag,
1056                                  struct ldap_Result *result)
1057 {
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);
1064         else
1065                 result->referral = NULL;
1066         asn1_end_tag(data);
1067 }
1068
1069 /* read a octet string blob */
1070 static BOOL asn1_read_ContextSimple(ASN1_DATA *data, uint8_t num, DATA_BLOB *blob)
1071 {
1072         int len;
1073         ZERO_STRUCTP(blob);
1074         if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(num))) return False;
1075         len = asn1_tag_remaining(data);
1076         if (len < 0) {
1077                 data->has_error = True;
1078                 return False;
1079         }
1080         *blob = data_blob(NULL, len);
1081         asn1_read(data, blob->data, len);
1082         asn1_end_tag(data);
1083         return !data->has_error;
1084 }
1085
1086 static void ldap_decode_BindResponse(TALLOC_CTX *mem_ctx,
1087                                  ASN1_DATA *data,
1088                                  enum ldap_request_tag tag,
1089                                  struct ldap_BindResponse *BindResp)
1090 {
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);
1100         } else {
1101                 BindResp->SASL.secblob = data_blob(NULL, 0);
1102         }
1103         asn1_end_tag(data);
1104 }
1105
1106 static BOOL add_attrib_to_array_talloc(TALLOC_CTX *mem_ctx,
1107                                        const struct ldap_attribute *attrib,
1108                                        struct ldap_attribute **attribs,
1109                                        int *num_attribs)
1110 {
1111         *attribs = talloc_realloc(mem_ctx, *attribs,
1112                                   sizeof(**attribs) * (*num_attribs+1));
1113
1114         if (*attribs == NULL)
1115                 return False;
1116
1117         (*attribs)[*num_attribs] = *attrib;
1118         *num_attribs += 1;
1119         return True;
1120 }
1121                                        
1122 static BOOL ldap_decode_filter(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
1123                                char **filter)
1124 {
1125         uint8 filter_tag, tag_desc;
1126
1127         if (!asn1_peek_uint8(data, &filter_tag))
1128                 return False;
1129
1130         tag_desc = filter_tag;
1131         filter_tag &= 0x1f;     /* strip off the asn1 stuff */
1132         tag_desc &= 0xe0;
1133
1134         switch(filter_tag) {
1135         case 0: {
1136                 /* AND of one or more filters */
1137                 if (tag_desc != 0xa0) /* context compount */
1138                         return False;
1139
1140                 asn1_start_tag(data, ASN1_CONTEXT(0));
1141
1142                 *filter = talloc_strdup(mem_ctx, "(&");
1143                 if (*filter == NULL)
1144                         return False;
1145
1146                 while (asn1_tag_remaining(data) > 0) {
1147                         char *subfilter;
1148                         if (!ldap_decode_filter(mem_ctx, data, &subfilter))
1149                                 return False;
1150                         *filter = talloc_asprintf(mem_ctx, "%s%s", *filter,
1151                                                   subfilter);
1152                         if (*filter == NULL)
1153                                 return False;
1154                 }
1155                 asn1_end_tag(data);
1156
1157                 *filter = talloc_asprintf(mem_ctx, "%s)", *filter);
1158                 break;
1159         }
1160         case 1: {
1161                 /* OR of one or more filters */
1162                 if (tag_desc != 0xa0) /* context compount */
1163                         return False;
1164
1165                 asn1_start_tag(data, ASN1_CONTEXT(1));
1166
1167                 *filter = talloc_strdup(mem_ctx, "(|");
1168                 if (*filter == NULL)
1169                         return False;
1170
1171                 while (asn1_tag_remaining(data) > 0) {
1172                         char *subfilter;
1173                         if (!ldap_decode_filter(mem_ctx, data, &subfilter))
1174                                 return False;
1175                         *filter = talloc_asprintf(mem_ctx, "%s%s", *filter,
1176                                                   subfilter);
1177                         if (*filter == NULL)
1178                                 return False;
1179                 }
1180
1181                 asn1_end_tag(data);
1182
1183                 *filter = talloc_asprintf(mem_ctx, "%s)", *filter);
1184                 break;
1185         }
1186         case 3: {
1187                 /* equalityMatch */
1188                 const char *attrib, *value;
1189                 if (tag_desc != 0xa0) /* context compound */
1190                         return False;
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);
1194                 asn1_end_tag(data);
1195                 if ((data->has_error) || (attrib == NULL) || (value == NULL))
1196                         return False;
1197                 *filter = talloc_asprintf(mem_ctx, "(%s=%s)", attrib, value);
1198                 break;
1199         }
1200         case 7: {
1201                 /* Normal presence, "attribute=*" */
1202                 int attr_len;
1203                 char *attr_name;
1204                 if (tag_desc != 0x80) /* context simple */
1205                         return False;
1206                 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(7)))
1207                         return False;
1208                 attr_len = asn1_tag_remaining(data);
1209                 attr_name = malloc(attr_len+1);
1210                 if (attr_name == NULL)
1211                         return False;
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);
1216                 asn1_end_tag(data);
1217                 break;
1218         }
1219         default:
1220                 return False;
1221         }
1222         if (*filter == NULL)
1223                 return False;
1224         return True;
1225 }
1226
1227 static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
1228                                struct ldap_attribute *attrib)
1229 {
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)) {
1234                 DATA_BLOB blob;
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);
1241         }
1242         asn1_end_tag(data);
1243         asn1_end_tag(data);
1244         
1245 }
1246
1247 static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
1248                                 struct ldap_attribute **attributes,
1249                                 int *num_attributes)
1250 {
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);
1258         }
1259         asn1_end_tag(data);
1260 }
1261
1262 BOOL ldap_decode(ASN1_DATA *data, struct ldap_message *msg)
1263 {
1264         uint8 tag;
1265
1266         asn1_start_tag(data, ASN1_SEQUENCE(0));
1267         asn1_read_Integer(data, &msg->messageid);
1268
1269         if (!asn1_peek_uint8(data, &tag))
1270                 return False;
1271
1272         switch(tag) {
1273
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)) {
1281                         int pwlen;
1282                         r->creds.password = "";
1283                         /* Mechanism 0 (SIMPLE) */
1284                         asn1_start_tag(data, 0x80);
1285                         pwlen = asn1_tag_remaining(data);
1286                         if (pwlen != 0) {
1287                                 char *pw = talloc(msg->mem_ctx, pwlen+1);
1288                                 asn1_read(data, pw, pwlen);
1289                                 pw[pwlen] = '\0';
1290                                 r->creds.password = pw;
1291                         }
1292                         asn1_end_tag(data);
1293                 }
1294                 asn1_end_tag(data);
1295                 break;
1296         }
1297
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,
1303                                      r);
1304                 break;
1305         }
1306
1307         case ASN1_APPLICATION(LDAP_TAG_UnbindRequest): {
1308                 msg->type = LDAP_TAG_UnbindRequest;
1309                 break;
1310         }
1311
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);
1322
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);
1326
1327                 asn1_start_tag(data, ASN1_SEQUENCE(0));
1328
1329                 r->num_attributes = 0;
1330                 r->attributes = NULL;
1331
1332                 while (asn1_tag_remaining(data) > 0) {
1333                         const char *attr;
1334                         if (!asn1_read_OctetString_talloc(msg->mem_ctx, data,
1335                                                           &attr))
1336                                 return False;
1337                         if (!add_string_to_array(msg->mem_ctx, attr,
1338                                                  &r->attributes,
1339                                                  &r->num_attributes))
1340                                 return False;
1341                 }
1342
1343                 asn1_end_tag(data);
1344                 asn1_end_tag(data);
1345                 break;
1346         }
1347
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);
1358                 asn1_end_tag(data);
1359                 break;
1360         }
1361
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);
1367                 break;
1368         }
1369
1370         case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1371 /*              struct ldap_SearchResRef *r = &msg->r.SearchResultReference; */
1372                 msg->type = LDAP_TAG_SearchResultReference;
1373                 break;
1374         }
1375
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));
1382
1383                 r->num_mods = 0;
1384                 r->mods = NULL;
1385
1386                 while (asn1_tag_remaining(data) > 0) {
1387                         struct ldap_mod mod;
1388                         ZERO_STRUCT(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);
1392                         asn1_end_tag(data);
1393                         if (!add_mod_to_array_talloc(msg->mem_ctx, &mod,
1394                                                      &r->mods, &r->num_mods))
1395                                 break;
1396                 }
1397
1398                 asn1_end_tag(data);
1399                 asn1_end_tag(data);
1400                 break;
1401         }
1402
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);
1408                 break;
1409         }
1410
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);
1416
1417                 r->attributes = NULL;
1418                 r->num_attributes = 0;
1419                 ldap_decode_attribs(msg->mem_ctx, data, &r->attributes,
1420                                     &r->num_attributes);
1421
1422                 asn1_end_tag(data);
1423                 break;
1424         }
1425
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);
1431                 break;
1432         }
1433
1434         case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1435                 struct ldap_DelRequest *r = &msg->r.DelRequest;
1436                 int len;
1437                 char *dn;
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);
1443                 if (dn == NULL)
1444                         break;
1445                 asn1_read(data, dn, len);
1446                 dn[len] = '\0';
1447                 r->dn = dn;
1448                 asn1_end_tag(data);
1449                 break;
1450         }
1451
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);
1457                 break;
1458         }
1459
1460         case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1461 /*              struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest; */
1462                 msg->type = LDAP_TAG_ModifyDNRequest;
1463                 break;
1464         }
1465
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);
1471                 break;
1472         }
1473
1474         case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1475 /*              struct ldap_CompareRequest *r = &msg->r.CompareRequest; */
1476                 msg->type = LDAP_TAG_CompareRequest;
1477                 break;
1478         }
1479
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);
1485                 break;
1486         }
1487
1488         case ASN1_APPLICATION(LDAP_TAG_AbandonRequest): {
1489 /*              struct ldap_AbandonRequest *r = &msg->r.AbandonRequest; */
1490                 msg->type = LDAP_TAG_AbandonRequest;
1491                 break;
1492         }
1493
1494         case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1495 /*              struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest; */
1496                 msg->type = LDAP_TAG_ExtendedRequest;
1497                 break;
1498         }
1499
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. */
1508                 r->name = NULL;
1509                 r->value.data = NULL;
1510                 r->value.length = 0;
1511                 break;
1512         }
1513
1514         }
1515
1516         asn1_end_tag(data);
1517         return ((!data->has_error) && (data->nesting == NULL));
1518 }
1519
1520 BOOL ldap_parse_basic_url(TALLOC_CTX *mem_ctx, const char *url,
1521                           char **host, uint16 *port, BOOL *ldaps)
1522 {
1523         int tmp_port = 0;
1524         fstring protocol;
1525         fstring tmp_host;
1526         const char *p = url;
1527
1528         /* skip leading "URL:" (if any) */
1529         if ( strnequal( p, "URL:", 4 ) ) {
1530                 p += 4;
1531         }
1532
1533         /* Paranoia check */
1534         SMB_ASSERT(sizeof(protocol)>10 && sizeof(tmp_host)>254);
1535                 
1536         sscanf(p, "%10[^:]://%254[^:/]:%d", protocol, tmp_host, &tmp_port);
1537
1538         if (strequal(protocol, "ldap")) {
1539                 *port = 389;
1540                 *ldaps = False;
1541         } else if (strequal(protocol, "ldaps")) {
1542                 *port = 636;
1543                 *ldaps = True;
1544         } else {
1545                 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
1546                 return False;
1547         }
1548
1549         if (tmp_port != 0)
1550                 *port = tmp_port;
1551         
1552         *host = talloc_strdup(mem_ctx, tmp_host);
1553
1554         return (*host != NULL);
1555 }
1556
1557 struct ldap_connection *new_ldap_connection(void)
1558 {
1559         TALLOC_CTX *mem_ctx = talloc_init("ldap_connection");
1560         struct ldap_connection *result;
1561
1562         if (mem_ctx == NULL)
1563                 return NULL;
1564
1565         result = talloc(mem_ctx, sizeof(*result));
1566
1567         if (result == NULL)
1568                 return NULL;
1569
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;
1578
1579         return result;
1580 }
1581
1582 BOOL ldap_connect(struct ldap_connection *conn, const char *url)
1583 {
1584         struct hostent *hp;
1585         struct in_addr ip;
1586
1587         if (!ldap_parse_basic_url(conn->mem_ctx, url, &conn->host,
1588                                   &conn->port, &conn->ldaps))
1589                 return False;
1590
1591         hp = sys_gethostbyname(conn->host);
1592
1593         if ((hp == NULL) || (hp->h_addr == NULL))
1594                 return False;
1595
1596         putip((char *)&ip, (char *)hp->h_addr);
1597
1598         conn->sock = open_socket_out(SOCK_STREAM, &ip, conn->port, LDAP_CONNECTION_TIMEOUT);
1599
1600         return (conn->sock >= 0);
1601 }
1602
1603 BOOL ldap_set_simple_creds(struct ldap_connection *conn,
1604                            const char *dn, const char *password)
1605 {
1606         conn->auth_dn = talloc_strdup(conn->mem_ctx, dn);
1607         conn->simple_pw = talloc_strdup(conn->mem_ctx, password);
1608
1609         return ((conn->auth_dn != NULL) && (conn->simple_pw != NULL));
1610 }
1611
1612 struct ldap_message *new_ldap_message(void)
1613 {
1614         TALLOC_CTX *mem_ctx = talloc_init("ldap_message");
1615         struct ldap_message *result;
1616
1617         if (mem_ctx == NULL)
1618                 return NULL;
1619
1620         result = talloc(mem_ctx, sizeof(*result));
1621
1622         if (result == NULL)
1623                 return NULL;
1624
1625         result->mem_ctx = mem_ctx;
1626         return result;
1627 }
1628
1629 void destroy_ldap_message(struct ldap_message *msg)
1630 {
1631         if (msg != NULL)
1632                 talloc_destroy(msg->mem_ctx);
1633 }
1634
1635 BOOL ldap_send_msg(struct ldap_connection *conn, struct ldap_message *msg,
1636                    const struct timeval *endtime)
1637 {
1638         DATA_BLOB request;
1639         BOOL result;
1640         struct ldap_queue_entry *entry;
1641
1642         msg->messageid = conn->next_msgid++;
1643
1644         if (!ldap_encode(msg, &request))
1645                 return False;
1646
1647         result = (write_data_until(conn->sock, request.data, request.length,
1648                                    endtime) == request.length);
1649
1650         data_blob_free(&request);
1651
1652         if (!result)
1653                 return result;
1654
1655         /* abandon and unbind don't expect results */
1656
1657         if ((msg->type == LDAP_TAG_AbandonRequest) ||
1658             (msg->type == LDAP_TAG_UnbindRequest))
1659                 return True;
1660
1661         entry = malloc(sizeof(*entry)); 
1662
1663         if (entry == NULL)
1664                 return False;
1665
1666         entry->msgid = msg->messageid;
1667         entry->msg = NULL;
1668         DLIST_ADD(conn->outstanding, entry);
1669
1670         return True;
1671 }
1672
1673 BOOL ldap_receive_msg(struct ldap_connection *conn, struct ldap_message *msg,
1674                       const struct timeval *endtime)
1675 {
1676         struct asn1_data data;
1677         BOOL result;
1678
1679         if (!asn1_read_sequence_until(conn->sock, &data, endtime))
1680                 return False;
1681
1682         result = ldap_decode(&data, msg);
1683
1684         asn1_free(&data);
1685         return result;
1686 }
1687
1688 static struct ldap_message *recv_from_queue(struct ldap_connection *conn,
1689                                             int msgid)
1690 {
1691         struct ldap_queue_entry *e;
1692
1693         for (e = conn->outstanding; e != NULL; e = e->next) {
1694
1695                 if (e->msgid == msgid) {
1696                         struct ldap_message *result = e->msg;
1697                         DLIST_REMOVE(conn->outstanding, e);
1698                         SAFE_FREE(e);
1699                         return result;
1700                 }
1701         }
1702
1703         return NULL;
1704 }
1705
1706 static void add_search_entry(struct ldap_connection *conn,
1707                              struct ldap_message *msg)
1708 {
1709         struct ldap_queue_entry *e = malloc(sizeof *e);
1710
1711         if (e == NULL)
1712                 return;
1713
1714         e->msg = msg;
1715         DLIST_ADD_END(conn->search_entries, e, struct ldap_queue_entry *);
1716         return;
1717 }
1718
1719 static void fill_outstanding_request(struct ldap_connection *conn,
1720                                      struct ldap_message *msg)
1721 {
1722         struct ldap_queue_entry *e;
1723
1724         for (e = conn->outstanding; e != NULL; e = e->next) {
1725                 if (e->msgid == msg->messageid) {
1726                         e->msg = msg;
1727                         return;
1728                 }
1729         }
1730
1731         /* This reply has not been expected, destroy the incoming msg */
1732         destroy_ldap_message(msg);
1733         return;
1734 }
1735
1736 struct ldap_message *ldap_receive(struct ldap_connection *conn, int msgid,
1737                                   const struct timeval *endtime)
1738 {
1739         struct ldap_message *result = recv_from_queue(conn, msgid);
1740
1741         if (result != NULL)
1742                 return result;
1743
1744         while (True) {
1745                 struct asn1_data data;
1746                 BOOL res;
1747
1748                 result = new_ldap_message();
1749
1750                 if (!asn1_read_sequence_until(conn->sock, &data, endtime))
1751                         return NULL;
1752
1753                 res = ldap_decode(&data, result);
1754                 asn1_free(&data);
1755
1756                 if (!res)
1757                         return NULL;
1758
1759                 if (result->messageid == msgid)
1760                         return result;
1761
1762                 if (result->type == LDAP_TAG_SearchResultEntry) {
1763                         add_search_entry(conn, result);
1764                 } else {
1765                         fill_outstanding_request(conn, result);
1766                 }
1767         }
1768
1769         return NULL;
1770 }
1771
1772 struct ldap_message *ldap_transaction(struct ldap_connection *conn,
1773                                       struct ldap_message *request)
1774 {
1775         if (!ldap_send_msg(conn, request, NULL))
1776                 return False;
1777
1778         return ldap_receive(conn, request->messageid, NULL);
1779 }
1780
1781 int ldap_bind_simple(struct ldap_connection *conn, const char *userdn, const char *password)
1782 {
1783         struct ldap_message *response;
1784         struct ldap_message *msg;
1785         const char *dn, *pw;
1786         int result = LDAP_OTHER;
1787
1788         if (conn == NULL)
1789                 return result;
1790
1791         if (userdn) {
1792                 dn = userdn;
1793         } else {
1794                 if (conn->auth_dn) {
1795                         dn = conn->auth_dn;
1796                 } else {
1797                         dn = "";
1798                 }
1799         }
1800
1801         if (password) {
1802                 pw = password;
1803         } else {
1804                 if (conn->simple_pw) {
1805                         pw = conn->simple_pw;
1806                 } else {
1807                         pw = "";
1808                 }
1809         }
1810
1811         msg =  new_ldap_simple_bind_msg(dn, pw);
1812         if (!msg)
1813                 return result;
1814
1815         response = ldap_transaction(conn, msg);
1816         if (!response) {
1817                 destroy_ldap_message(msg);
1818                 return result;
1819         }
1820                 
1821         result = response->r.BindResponse.response.resultcode;
1822
1823         destroy_ldap_message(msg);
1824         destroy_ldap_message(response);
1825
1826         return result;
1827 }
1828
1829 int ldap_bind_sasl(struct ldap_connection *conn, const char *username, const char *domain, const char *password)
1830 {
1831         NTSTATUS status;
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;
1838
1839         if (conn == NULL)
1840                 return result;
1841
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)));
1845                 return result;
1846         }
1847
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)));
1852                 goto done;
1853         }
1854
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)));
1859                 goto done;
1860         }
1861
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)));
1866                 goto done;
1867         }
1868
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)));
1873                 goto done;
1874         }
1875
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)));
1880                 goto done;
1881         }
1882
1883         mem_ctx = talloc_init("ldap_bind_sasl");
1884         if (!mem_ctx)
1885                 goto done;
1886
1887         status = gensec_update(conn->gensec, mem_ctx,
1888                                input,
1889                                &output);
1890
1891         while(1) {
1892                 if (NT_STATUS_IS_OK(status) && output.length == 0) {
1893                         break;
1894                 }
1895                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
1896                         break;
1897                 }
1898
1899                 msg =  new_ldap_sasl_bind_msg("GSS-SPNEGO", &output);
1900                 if (!msg)
1901                         goto done;
1902
1903                 response = ldap_transaction(conn, msg);
1904                 destroy_ldap_message(msg);
1905
1906                 if (!response) {
1907                         goto done;
1908                 }
1909
1910                 result = response->r.BindResponse.response.resultcode;
1911
1912                 if (result != LDAP_SUCCESS && result != LDAP_SASL_BIND_IN_PROGRESS) {
1913                         break;
1914                 }
1915
1916                 status = gensec_update(conn->gensec, mem_ctx,
1917                                        response->r.BindResponse.SASL.secblob,
1918                                        &output);
1919
1920                 destroy_ldap_message(response);
1921         }
1922
1923 done:
1924         if (conn->gensec)
1925                 gensec_end(&conn->gensec);
1926         if (mem_ctx)
1927                 talloc_destroy(mem_ctx);
1928
1929         return result;
1930 }
1931
1932 BOOL ldap_setup_connection(struct ldap_connection *conn,
1933                            const char *url, const char *userdn, const char *password)
1934 {
1935         int result;
1936
1937         if (!ldap_connect(conn, url)) {
1938                 return False;
1939         }
1940
1941         result = ldap_bind_simple(conn, userdn, password);
1942         if (result == LDAP_SUCCESS) {
1943                 return True;
1944         }
1945
1946         return False;
1947 }
1948
1949 BOOL ldap_setup_connection_with_sasl(struct ldap_connection *conn, const char *url, const char *username, const char *domain, const char *password)
1950 {
1951         int result;
1952
1953         if (!ldap_connect(conn, url)) {
1954                 return False;
1955         }
1956
1957         result = ldap_bind_sasl(conn, username, domain, password);
1958         if (result == LDAP_SUCCESS) {
1959                 return True;
1960         }
1961
1962         return False;
1963 }
1964
1965 static BOOL ldap_abandon_message(struct ldap_connection *conn, int msgid,
1966                                  const struct timeval *endtime)
1967 {
1968         struct ldap_message *msg = new_ldap_message();
1969         BOOL result;
1970
1971         if (msg == NULL)
1972                 return False;
1973
1974         msg->type = LDAP_TAG_AbandonRequest;
1975         msg->r.AbandonRequest.messageid = msgid;
1976
1977         result = ldap_send_msg(conn, msg, endtime);
1978         destroy_ldap_message(msg);
1979         return result;
1980 }
1981
1982 struct ldap_message *new_ldap_search_message(const char *base,
1983                                              enum ldap_scope scope,
1984                                              char *filter,
1985                                              int num_attributes,
1986                                              const char **attributes)
1987 {
1988         struct ldap_message *res = new_ldap_message();
1989
1990         if (res == NULL)
1991                 return NULL;
1992
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;
2003         return res;
2004 }
2005
2006 struct ldap_message *new_ldap_simple_bind_msg(const char *dn, const char *pw)
2007 {
2008         struct ldap_message *res = new_ldap_message();
2009
2010         if (res == NULL)
2011                 return NULL;
2012
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);
2018         return res;
2019 }
2020
2021 struct ldap_message *new_ldap_sasl_bind_msg(const char *sasl_mechanism, DATA_BLOB *secblob)
2022 {
2023         struct ldap_message *res = new_ldap_message();
2024
2025         if (res == NULL)
2026                 return NULL;
2027
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;
2034         return res;
2035 }
2036
2037 BOOL ldap_setsearchent(struct ldap_connection *conn, struct ldap_message *msg,
2038                        const struct timeval *endtime)
2039 {
2040         if ((conn->searchid != 0) &&
2041             (!ldap_abandon_message(conn, conn->searchid, endtime)))
2042                 return False;
2043
2044         conn->searchid = conn->next_msgid;
2045         return ldap_send_msg(conn, msg, endtime);
2046 }
2047
2048 struct ldap_message *ldap_getsearchent(struct ldap_connection *conn,
2049                                        const struct timeval *endtime)
2050 {
2051         struct ldap_message *result;
2052
2053         if (conn->search_entries != NULL) {
2054                 struct ldap_queue_entry *e = conn->search_entries;
2055
2056                 result = e->msg;
2057                 DLIST_REMOVE(conn->search_entries, e);
2058                 SAFE_FREE(e);
2059                 return result;
2060         }
2061
2062         result = ldap_receive(conn, conn->searchid, endtime);
2063
2064         if (result->type == LDAP_TAG_SearchResultEntry)
2065                 return result;
2066
2067         if (result->type == LDAP_TAG_SearchResultDone) {
2068                 /* TODO: Handle Paged Results */
2069                 destroy_ldap_message(result);
2070                 return NULL;
2071         }
2072
2073         /* TODO: Handle Search References here */
2074         return NULL;
2075 }
2076
2077 void ldap_endsearchent(struct ldap_connection *conn,
2078                        const struct timeval *endtime)
2079 {
2080         struct ldap_queue_entry *e;
2081
2082         e = conn->search_entries;
2083
2084         while (e != NULL) {
2085                 struct ldap_queue_entry *next = e->next;
2086                 DLIST_REMOVE(conn->search_entries, e);
2087                 SAFE_FREE(e);
2088                 e = next;
2089         }
2090 }
2091
2092 struct ldap_message *ldap_searchone(struct ldap_connection *conn,
2093                                     struct ldap_message *msg,
2094                                     const struct timeval *endtime)
2095 {
2096         struct ldap_message *res1, *res2 = NULL;
2097         if (!ldap_setsearchent(conn, msg, endtime))
2098                 return NULL;
2099
2100         res1 = ldap_getsearchent(conn, endtime);
2101
2102         if (res1 != NULL)
2103                 res2 = ldap_getsearchent(conn, endtime);
2104
2105         ldap_endsearchent(conn, endtime);
2106
2107         if (res1 == NULL)
2108                 return NULL;
2109
2110         if (res2 != NULL) {
2111                 /* More than one entry */
2112                 destroy_ldap_message(res1);
2113                 destroy_ldap_message(res2);
2114                 return NULL;
2115         }
2116
2117         return res1;
2118 }
2119
2120 BOOL ldap_find_single_value(struct ldap_message *msg, const char *attr,
2121                             DATA_BLOB *value)
2122 {
2123         int i;
2124         struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
2125
2126         if (msg->type != LDAP_TAG_SearchResultEntry)
2127                 return False;
2128
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)
2132                                 return False;
2133
2134                         *value = r->attributes[i].values[0];
2135                         return True;
2136                 }
2137         }
2138         return False;
2139 }
2140
2141 BOOL ldap_find_single_string(struct ldap_message *msg, const char *attr,
2142                              TALLOC_CTX *mem_ctx, char **value)
2143 {
2144         DATA_BLOB blob;
2145
2146         if (!ldap_find_single_value(msg, attr, &blob))
2147                 return False;
2148
2149         *value = talloc(mem_ctx, blob.length+1);
2150
2151         if (*value == NULL)
2152                 return False;
2153
2154         memcpy(*value, blob.data, blob.length);
2155         (*value)[blob.length] = '\0';
2156         return True;
2157 }
2158
2159 BOOL ldap_find_single_int(struct ldap_message *msg, const char *attr,
2160                           int *value)
2161 {
2162         DATA_BLOB blob;
2163         char *val;
2164         int errno_save;
2165         BOOL res;
2166
2167         if (!ldap_find_single_value(msg, attr, &blob))
2168                 return False;
2169
2170         val = malloc(blob.length+1);
2171         if (val == NULL)
2172                 return False;
2173
2174         memcpy(val, blob.data, blob.length);
2175         val[blob.length] = '\0';
2176
2177         errno_save = errno;
2178         errno = 0;
2179
2180         *value = strtol(val, NULL, 10);
2181
2182         res = (errno == 0);
2183
2184         free(val);
2185         errno = errno_save;
2186
2187         return res;
2188 }
2189
2190 int ldap_error(struct ldap_connection *conn)
2191 {
2192         return 0;
2193 }
2194
2195 NTSTATUS ldap2nterror(int ldaperror)
2196 {
2197         return NT_STATUS_OK;
2198 }