r1756: merge volkers ldap client lib to samba4 for simo to start with the
[samba.git] / source4 / 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 #include "smb_ldap.h"
26
27 /****************************************************************************
28  *
29  * LDAP filter parser -- main routine is ldb_parse_filter
30  *
31  * Shamelessly stolen and adapted from Samba 4.
32  *
33  ***************************************************************************/
34
35 /* Hmm. A blob might be more appropriate here :-) */
36
37 struct ldb_val {
38         unsigned int length;
39         void *data;
40 };
41
42 enum ldb_parse_op {LDB_OP_SIMPLE, LDB_OP_AND, LDB_OP_OR, LDB_OP_NOT};
43
44 struct ldb_parse_tree {
45         enum ldb_parse_op operation;
46         union {
47                 struct {
48                         char *attr;
49                         struct ldb_val value;
50                 } simple;
51                 struct {
52                         unsigned int num_elements;
53                         struct ldb_parse_tree **elements;
54                 } list;
55                 struct {
56                         struct ldb_parse_tree *child;
57                 } not;
58         } u;
59 };
60
61 #define LDB_ALL_SEP "()&|=!"
62
63 /*
64   return next token element. Caller frees
65 */
66 static char *ldb_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 ldb_parse_tree *ldb_parse_filter(TALLOC_CTX *mem_ctx,
131                                                const char **s);
132
133 /*
134   <simple> ::= <attributetype> <filtertype> <attributevalue>
135 */
136 static struct ldb_parse_tree *ldb_parse_simple(TALLOC_CTX *mem_ctx,
137                                                const char *s)
138 {
139         char *eq, *val, *l;
140         struct ldb_parse_tree *ret;
141
142         l = ldb_parse_lex(mem_ctx, &s, LDB_ALL_SEP);
143         if (!l) {
144                 return NULL;
145         }
146
147         if (strchr("()&|=", *l))
148                 return NULL;
149
150         eq = ldb_parse_lex(mem_ctx, &s, LDB_ALL_SEP);
151         if (!eq || strcmp(eq, "=") != 0)
152                 return NULL;
153
154         val = ldb_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 = LDB_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 ldb_parse_tree *ldb_parse_filterlist(TALLOC_CTX *mem_ctx,
180                                                    enum ldb_parse_op op,
181                                                    const char *s)
182 {
183         struct ldb_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] = ldb_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 = ldb_parse_filter(mem_ctx, &s))) {
208                 struct ldb_parse_tree **e;
209                 e = talloc_realloc(mem_ctx, ret->u.list.elements,
210                                    sizeof(struct ldb_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 ldb_parse_tree *ldb_parse_not(TALLOC_CTX *mem_ctx, const char *s)
230 {
231         struct ldb_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 = LDB_OP_NOT;
240         ret->u.not.child = ldb_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 ldb_parse_tree *ldb_parse_filtercomp(TALLOC_CTX *mem_ctx,
252                                                    const char *s)
253 {
254         while (isspace(*s)) s++;
255
256         switch (*s) {
257         case '&':
258                 return ldb_parse_filterlist(mem_ctx, LDB_OP_AND, s+1);
259
260         case '|':
261                 return ldb_parse_filterlist(mem_ctx, LDB_OP_OR, s+1);
262
263         case '!':
264                 return ldb_parse_not(mem_ctx, s+1);
265
266         case '(':
267         case ')':
268                 return NULL;
269         }
270
271         return ldb_parse_simple(mem_ctx, s);
272 }
273
274
275 /*
276   <filter> ::= '(' <filtercomp> ')'
277 */
278 static struct ldb_parse_tree *ldb_parse_filter(TALLOC_CTX *mem_ctx,
279                                                const char **s)
280 {
281         char *l, *s2;
282         const char *p, *p2;
283         struct ldb_parse_tree *ret;
284
285         l = ldb_parse_lex(mem_ctx, s, LDB_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 = ldb_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 ldb_parse_tree *ldb_parse_tree(TALLOC_CTX *mem_ctx, const char *s)
319 {
320         while (isspace(*s)) s++;
321
322         if (*s == '(') {
323                 return ldb_parse_filter(mem_ctx, &s);
324         }
325
326         return ldb_parse_simple(mem_ctx, s);
327 }
328
329 static BOOL ldap_push_filter(ASN1_DATA *data, struct ldb_parse_tree *tree)
330 {
331         switch (tree->operation) {
332         case LDB_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 LDB_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 LDB_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 ldb_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 ldb_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 ldb_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 ldb_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_MOD_ADD;
600
601                 if (strequal(attr_name, "delete"))
602                         mod.type = LDAP_MOD_DELETE;
603
604                 if (strequal(attr_name, "replace"))
605                         mod.type = LDAP_MOD_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 ldb_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.creds.data,
794                                                r->creds.SASL.creds.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("ldb_parse_tree");
826                         struct ldb_parse_tree *tree;
827
828                         if (mem_ctx == NULL)
829                                 return False;
830
831                         tree = ldb_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_SearchResultDone *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 static BOOL add_attrib_to_array_talloc(TALLOC_CTX *mem_ctx,
1070                                        const struct ldap_attribute *attrib,
1071                                        struct ldap_attribute **attribs,
1072                                        int *num_attribs)
1073 {
1074         *attribs = talloc_realloc(mem_ctx, *attribs,
1075                                   sizeof(**attribs) * (*num_attribs+1));
1076
1077         if (*attribs == NULL)
1078                 return False;
1079
1080         (*attribs)[*num_attribs] = *attrib;
1081         *num_attribs += 1;
1082         return True;
1083 }
1084                                        
1085 static BOOL ldap_decode_filter(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
1086                                char **filter)
1087 {
1088         uint8 filter_tag, tag_desc;
1089
1090         if (!asn1_peek_uint8(data, &filter_tag))
1091                 return False;
1092
1093         tag_desc = filter_tag;
1094         filter_tag &= 0x1f;     /* strip off the asn1 stuff */
1095         tag_desc &= 0xe0;
1096
1097         switch(filter_tag) {
1098         case 0: {
1099                 /* AND of one or more filters */
1100                 if (tag_desc != 0xa0) /* context compount */
1101                         return False;
1102
1103                 asn1_start_tag(data, ASN1_CONTEXT(0));
1104
1105                 *filter = talloc_strdup(mem_ctx, "(&");
1106                 if (*filter == NULL)
1107                         return False;
1108
1109                 while (asn1_tag_remaining(data) > 0) {
1110                         char *subfilter;
1111                         if (!ldap_decode_filter(mem_ctx, data, &subfilter))
1112                                 return False;
1113                         *filter = talloc_asprintf(mem_ctx, "%s%s", *filter,
1114                                                   subfilter);
1115                         if (*filter == NULL)
1116                                 return False;
1117                 }
1118                 asn1_end_tag(data);
1119
1120                 *filter = talloc_asprintf(mem_ctx, "%s)", *filter);
1121                 break;
1122         }
1123         case 1: {
1124                 /* OR of one or more filters */
1125                 if (tag_desc != 0xa0) /* context compount */
1126                         return False;
1127
1128                 asn1_start_tag(data, ASN1_CONTEXT(1));
1129
1130                 *filter = talloc_strdup(mem_ctx, "(|");
1131                 if (*filter == NULL)
1132                         return False;
1133
1134                 while (asn1_tag_remaining(data) > 0) {
1135                         char *subfilter;
1136                         if (!ldap_decode_filter(mem_ctx, data, &subfilter))
1137                                 return False;
1138                         *filter = talloc_asprintf(mem_ctx, "%s%s", *filter,
1139                                                   subfilter);
1140                         if (*filter == NULL)
1141                                 return False;
1142                 }
1143
1144                 asn1_end_tag(data);
1145
1146                 *filter = talloc_asprintf(mem_ctx, "%s)", *filter);
1147                 break;
1148         }
1149         case 3: {
1150                 /* equalityMatch */
1151                 const char *attrib, *value;
1152                 if (tag_desc != 0xa0) /* context compound */
1153                         return False;
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);
1157                 asn1_end_tag(data);
1158                 if ((data->has_error) || (attrib == NULL) || (value == NULL))
1159                         return False;
1160                 *filter = talloc_asprintf(mem_ctx, "(%s=%s)", attrib, value);
1161                 break;
1162         }
1163         case 7: {
1164                 /* Normal presence, "attribute=*" */
1165                 int attr_len;
1166                 char *attr_name;
1167                 if (tag_desc != 0x80) /* context simple */
1168                         return False;
1169                 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(7)))
1170                         return False;
1171                 attr_len = asn1_tag_remaining(data);
1172                 attr_name = malloc(attr_len+1);
1173                 if (attr_name == NULL)
1174                         return False;
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);
1179                 asn1_end_tag(data);
1180                 break;
1181         }
1182         default:
1183                 return False;
1184         }
1185         if (*filter == NULL)
1186                 return False;
1187         return True;
1188 }
1189
1190 static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
1191                                struct ldap_attribute *attrib)
1192 {
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)) {
1197                 DATA_BLOB blob;
1198                 struct ldb_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);
1204         }
1205         asn1_end_tag(data);
1206         asn1_end_tag(data);
1207         
1208 }
1209
1210 static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
1211                                 struct ldap_attribute **attributes,
1212                                 int *num_attributes)
1213 {
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);
1221         }
1222         asn1_end_tag(data);
1223 }
1224
1225 BOOL ldap_decode(ASN1_DATA *data, struct ldap_message *msg)
1226 {
1227         uint8 tag;
1228
1229         asn1_start_tag(data, ASN1_SEQUENCE(0));
1230         asn1_read_Integer(data, &msg->messageid);
1231
1232         if (!asn1_peek_uint8(data, &tag))
1233                 return False;
1234
1235         switch(tag) {
1236
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)) {
1244                         int pwlen;
1245                         r->creds.password = "";
1246                         /* Mechanism 0 (SIMPLE) */
1247                         asn1_start_tag(data, 0x80);
1248                         pwlen = asn1_tag_remaining(data);
1249                         if (pwlen != 0) {
1250                                 char *pw = talloc(msg->mem_ctx, pwlen+1);
1251                                 asn1_read(data, pw, pwlen);
1252                                 pw[pwlen] = '\0';
1253                                 r->creds.password = pw;
1254                         }
1255                         asn1_end_tag(data);
1256                 }
1257                 asn1_end_tag(data);
1258                 break;
1259         }
1260
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,
1266                                      &r->response);
1267                 break;
1268         }
1269
1270         case ASN1_APPLICATION(LDAP_TAG_UnbindRequest): {
1271                 msg->type = LDAP_TAG_UnbindRequest;
1272                 break;
1273         }
1274
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);
1285
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);
1289
1290                 asn1_start_tag(data, ASN1_SEQUENCE(0));
1291
1292                 r->num_attributes = 0;
1293                 r->attributes = NULL;
1294
1295                 while (asn1_tag_remaining(data) > 0) {
1296                         const char *attr;
1297                         if (!asn1_read_OctetString_talloc(msg->mem_ctx, data,
1298                                                           &attr))
1299                                 return False;
1300                         if (!add_string_to_array(msg->mem_ctx, attr,
1301                                                  &r->attributes,
1302                                                  &r->num_attributes))
1303                                 return False;
1304                 }
1305
1306                 asn1_end_tag(data);
1307                 asn1_end_tag(data);
1308                 break;
1309         }
1310
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);
1321                 asn1_end_tag(data);
1322                 break;
1323         }
1324
1325         case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1326                 struct ldap_SearchResultDone *r = &msg->r.SearchResultDone;
1327                 msg->type = LDAP_TAG_SearchResultDone;
1328                 ldap_decode_response(msg->mem_ctx, data,
1329                                      LDAP_TAG_SearchResultDone, r);
1330                 break;
1331         }
1332
1333         case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1334 /*              struct ldap_SearchResRef *r = &msg->r.SearchResultReference; */
1335                 msg->type = LDAP_TAG_SearchResultReference;
1336                 break;
1337         }
1338
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));
1345
1346                 r->num_mods = 0;
1347                 r->mods = NULL;
1348
1349                 while (asn1_tag_remaining(data) > 0) {
1350                         struct ldap_mod mod;
1351                         ZERO_STRUCT(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);
1355                         asn1_end_tag(data);
1356                         if (!add_mod_to_array_talloc(msg->mem_ctx, &mod,
1357                                                      &r->mods, &r->num_mods))
1358                                 break;
1359                 }
1360
1361                 asn1_end_tag(data);
1362                 asn1_end_tag(data);
1363                 break;
1364         }
1365
1366         case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1367                 struct ldap_ModifyResponse *r = &msg->r.ModifyResponse;
1368                 msg->type = LDAP_TAG_ModifyResponse;
1369                 ldap_decode_response(msg->mem_ctx, data,
1370                                      LDAP_TAG_ModifyResponse, r);
1371                 break;
1372         }
1373
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);
1379
1380                 r->attributes = NULL;
1381                 r->num_attributes = 0;
1382                 ldap_decode_attribs(msg->mem_ctx, data, &r->attributes,
1383                                     &r->num_attributes);
1384
1385                 asn1_end_tag(data);
1386                 break;
1387         }
1388
1389         case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1390                 struct ldap_AddResponse *r = &msg->r.AddResponse;
1391                 msg->type = LDAP_TAG_AddResponse;
1392                 ldap_decode_response(msg->mem_ctx, data,
1393                                      LDAP_TAG_AddResponse, r);
1394                 break;
1395         }
1396
1397         case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1398                 struct ldap_DelRequest *r = &msg->r.DelRequest;
1399                 int len;
1400                 char *dn;
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);
1406                 if (dn == NULL)
1407                         break;
1408                 asn1_read(data, dn, len);
1409                 dn[len] = '\0';
1410                 r->dn = dn;
1411                 asn1_end_tag(data);
1412                 break;
1413         }
1414
1415         case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1416                 struct ldap_DelResponse *r = &msg->r.DelResponse;
1417                 msg->type = LDAP_TAG_DelResponse;
1418                 ldap_decode_response(msg->mem_ctx, data,
1419                                      LDAP_TAG_DelResponse, r);
1420                 break;
1421         }
1422
1423         case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1424 /*              struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest; */
1425                 msg->type = LDAP_TAG_ModifyDNRequest;
1426                 break;
1427         }
1428
1429         case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1430                 struct ldap_ModifyDNResponse *r = &msg->r.ModifyDNResponse;
1431                 msg->type = LDAP_TAG_ModifyDNResponse;
1432                 ldap_decode_response(msg->mem_ctx, data,
1433                                      LDAP_TAG_ModifyDNResponse, r);
1434                 break;
1435         }
1436
1437         case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1438 /*              struct ldap_CompareRequest *r = &msg->r.CompareRequest; */
1439                 msg->type = LDAP_TAG_CompareRequest;
1440                 break;
1441         }
1442
1443         case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1444                 struct ldap_CompareResponse *r = &msg->r.CompareResponse;
1445                 msg->type = LDAP_TAG_CompareResponse;
1446                 ldap_decode_response(msg->mem_ctx, data,
1447                                      LDAP_TAG_CompareResponse, r);
1448                 break;
1449         }
1450
1451         case ASN1_APPLICATION(LDAP_TAG_AbandonRequest): {
1452 /*              struct ldap_AbandonRequest *r = &msg->r.AbandonRequest; */
1453                 msg->type = LDAP_TAG_AbandonRequest;
1454                 break;
1455         }
1456
1457         case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1458 /*              struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest; */
1459                 msg->type = LDAP_TAG_ExtendedRequest;
1460                 break;
1461         }
1462
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. */
1471                 r->name = NULL;
1472                 r->value.data = NULL;
1473                 r->value.length = 0;
1474                 break;
1475         }
1476
1477         }
1478
1479         asn1_end_tag(data);
1480         return ((!data->has_error) && (data->nesting == NULL));
1481 }
1482
1483 BOOL ldap_parse_basic_url(TALLOC_CTX *mem_ctx, const char *url,
1484                           char **host, uint16 *port, BOOL *ldaps)
1485 {
1486         int tmp_port = 0;
1487         fstring protocol;
1488         fstring tmp_host;
1489         const char *p = url;
1490
1491         /* skip leading "URL:" (if any) */
1492         if ( strnequal( p, "URL:", 4 ) ) {
1493                 p += 4;
1494         }
1495
1496         /* Paranoia check */
1497         SMB_ASSERT(sizeof(protocol)>10 && sizeof(tmp_host)>254);
1498                 
1499         sscanf(p, "%10[^:]://%254[^:/]:%d", protocol, tmp_host, &tmp_port);
1500
1501         if (strequal(protocol, "ldap")) {
1502                 *port = 389;
1503                 *ldaps = False;
1504         } else if (strequal(protocol, "ldaps")) {
1505                 *port = 636;
1506                 *ldaps = True;
1507         } else {
1508                 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
1509                 return False;
1510         }
1511
1512         if (tmp_port != 0)
1513                 *port = tmp_port;
1514         
1515         *host = talloc_strdup(mem_ctx, tmp_host);
1516
1517         return (*host != NULL);
1518 }
1519
1520 struct ldap_connection *new_ldap_connection(void)
1521 {
1522         TALLOC_CTX *mem_ctx = talloc_init("ldap_connection");
1523         struct ldap_connection *result;
1524
1525         if (mem_ctx == NULL)
1526                 return NULL;
1527
1528         result = talloc(mem_ctx, sizeof(*result));
1529
1530         if (result == NULL)
1531                 return NULL;
1532
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         return result;
1539 }
1540
1541 BOOL ldap_connect(struct ldap_connection *conn, const char *url)
1542 {
1543         struct hostent *hp;
1544         struct in_addr ip;
1545
1546         if (!ldap_parse_basic_url(conn->mem_ctx, url, &conn->host,
1547                                   &conn->port, &conn->ldaps))
1548                 return False;
1549
1550         hp = sys_gethostbyname(conn->host);
1551
1552         if ((hp == NULL) || (hp->h_addr == NULL))
1553                 return False;
1554
1555         putip((char *)&ip, (char *)hp->h_addr);
1556
1557         conn->sock = open_socket_out(SOCK_STREAM, &ip, conn->port, 10000);
1558
1559         return (conn->sock >= 0);
1560 }
1561
1562 BOOL ldap_set_simple_creds(struct ldap_connection *conn,
1563                            const char *dn, const char *password)
1564 {
1565         conn->auth_dn = talloc_strdup(conn->mem_ctx, dn);
1566         conn->simple_pw = talloc_strdup(conn->mem_ctx, password);
1567
1568         return ((conn->auth_dn != NULL) && (conn->simple_pw != NULL));
1569 }
1570
1571 struct ldap_message *new_ldap_message(void)
1572 {
1573         TALLOC_CTX *mem_ctx = talloc_init("ldap_message");
1574         struct ldap_message *result;
1575
1576         if (mem_ctx == NULL)
1577                 return NULL;
1578
1579         result = talloc(mem_ctx, sizeof(*result));
1580
1581         if (result == NULL)
1582                 return NULL;
1583
1584         result->mem_ctx = mem_ctx;
1585         return result;
1586 }
1587
1588 void destroy_ldap_message(struct ldap_message *msg)
1589 {
1590         if (msg != NULL)
1591                 talloc_destroy(msg->mem_ctx);
1592 }
1593
1594 BOOL ldap_send_msg(struct ldap_connection *conn, struct ldap_message *msg,
1595                    const struct timeval *endtime)
1596 {
1597         DATA_BLOB request;
1598         BOOL result;
1599         struct ldap_queue_entry *entry;
1600
1601         msg->messageid = conn->next_msgid++;
1602
1603         if (!ldap_encode(msg, &request))
1604                 return False;
1605
1606         result = (write_data_until(conn->sock, request.data, request.length,
1607                                    endtime) == request.length);
1608
1609         data_blob_free(&request);
1610
1611         if (!result)
1612                 return result;
1613
1614         /* abandon and unbind don't expect results */
1615
1616         if ((msg->type == LDAP_TAG_AbandonRequest) ||
1617             (msg->type == LDAP_TAG_UnbindRequest))
1618                 return True;
1619
1620         entry = malloc(sizeof(*entry)); 
1621
1622         if (entry == NULL)
1623                 return False;
1624
1625         entry->msgid = msg->messageid;
1626         entry->msg = NULL;
1627         DLIST_ADD(conn->outstanding, entry);
1628
1629         return True;
1630 }
1631
1632 BOOL ldap_receive_msg(struct ldap_connection *conn, struct ldap_message *msg,
1633                       const struct timeval *endtime)
1634 {
1635         struct asn1_data data;
1636         BOOL result;
1637
1638         if (!asn1_read_sequence_until(conn->sock, &data, endtime))
1639                 return False;
1640
1641         result = ldap_decode(&data, msg);
1642
1643         asn1_free(&data);
1644         return result;
1645 }
1646
1647 static struct ldap_message *recv_from_queue(struct ldap_connection *conn,
1648                                             int msgid)
1649 {
1650         struct ldap_queue_entry *e;
1651
1652         for (e = conn->outstanding; e != NULL; e = e->next) {
1653
1654                 if (e->msgid == msgid) {
1655                         struct ldap_message *result = e->msg;
1656                         DLIST_REMOVE(conn->outstanding, e);
1657                         SAFE_FREE(e);
1658                         return result;
1659                 }
1660         }
1661
1662         return NULL;
1663 }
1664
1665 static void add_search_entry(struct ldap_connection *conn,
1666                              struct ldap_message *msg)
1667 {
1668         struct ldap_queue_entry *e = malloc(sizeof *e);
1669         struct ldap_queue_entry *tmp;
1670
1671         if (e == NULL)
1672                 return;
1673
1674         e->msg = msg;
1675         DLIST_ADD_END(conn->search_entries, e, tmp);
1676         return;
1677 }
1678
1679 static void fill_outstanding_request(struct ldap_connection *conn,
1680                                      struct ldap_message *msg)
1681 {
1682         struct ldap_queue_entry *e;
1683
1684         for (e = conn->outstanding; e != NULL; e = e->next) {
1685                 if (e->msgid == msg->messageid) {
1686                         e->msg = msg;
1687                         return;
1688                 }
1689         }
1690
1691         /* This reply has not been expected, destroy the incoming msg */
1692         destroy_ldap_message(msg);
1693         return;
1694 }
1695
1696 struct ldap_message *ldap_receive(struct ldap_connection *conn, int msgid,
1697                                   const struct timeval *endtime)
1698 {
1699         struct ldap_message *result = recv_from_queue(conn, msgid);
1700
1701         if (result != NULL)
1702                 return result;
1703
1704         while (True) {
1705                 struct asn1_data data;
1706                 result = new_ldap_message();
1707                 BOOL res;
1708
1709                 if (!asn1_read_sequence_until(conn->sock, &data, endtime))
1710                         return NULL;
1711
1712                 res = ldap_decode(&data, result);
1713                 asn1_free(&data);
1714
1715                 if (!res)
1716                         return NULL;
1717
1718                 if (result->messageid == msgid)
1719                         return result;
1720
1721                 if (result->type == LDAP_TAG_SearchResultEntry) {
1722                         add_search_entry(conn, result);
1723                 } else {
1724                         fill_outstanding_request(conn, result);
1725                 }
1726         }
1727
1728         return NULL;
1729 }
1730
1731 struct ldap_message *ldap_transaction(struct ldap_connection *conn,
1732                                       struct ldap_message *request)
1733 {
1734         if (!ldap_send_msg(conn, request, NULL))
1735                 return False;
1736
1737         return ldap_receive(conn, request->messageid, NULL);
1738 }
1739
1740 BOOL ldap_setup_connection(struct ldap_connection *conn,
1741                            const char *url)
1742 {
1743         struct ldap_message *msg = new_ldap_message();
1744         struct ldap_message *response;
1745         BOOL result;
1746
1747         if (msg == NULL)
1748                 return False;
1749
1750         if (!ldap_connect(conn, url)) {
1751                 destroy_ldap_message(msg);
1752                 return False;
1753         }
1754
1755         msg->messageid = conn->next_msgid++;
1756         msg->type = LDAP_TAG_BindRequest;
1757         msg->r.BindRequest.version = 3;
1758         msg->r.BindRequest.dn = conn->auth_dn;
1759         msg->r.BindRequest.mechanism = LDAP_AUTH_MECH_SIMPLE;
1760         msg->r.BindRequest.creds.password = conn->simple_pw;
1761
1762         if ((response = ldap_transaction(conn, msg)) == NULL)
1763                 return False;
1764
1765         result = (response->r.BindResponse.response.resultcode == 0);
1766
1767         destroy_ldap_message(msg);
1768         destroy_ldap_message(response);
1769         return result;
1770 }
1771
1772 static BOOL ldap_abandon_message(struct ldap_connection *conn, int msgid,
1773                                  const struct timeval *endtime)
1774 {
1775         struct ldap_message *msg = new_ldap_message();
1776         BOOL result;
1777
1778         if (msg == NULL)
1779                 return False;
1780
1781         msg->type = LDAP_TAG_AbandonRequest;
1782         msg->r.AbandonRequest.messageid = msgid;
1783
1784         result = ldap_send_msg(conn, msg, endtime);
1785         destroy_ldap_message(msg);
1786         return result;
1787 }
1788
1789 struct ldap_message *new_ldap_search_message(const char *base,
1790                                              enum ldap_scope scope,
1791                                              char *filter,
1792                                              int num_attributes,
1793                                              const char **attributes)
1794 {
1795         struct ldap_message *res = new_ldap_message();
1796
1797         if (res == NULL)
1798                 return NULL;
1799
1800         res->type = LDAP_TAG_SearchRequest;
1801         res->r.SearchRequest.basedn = base;
1802         res->r.SearchRequest.scope = scope;
1803         res->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
1804         res->r.SearchRequest.timelimit = 0;
1805         res->r.SearchRequest.sizelimit = 0;
1806         res->r.SearchRequest.attributesonly = False;
1807         res->r.SearchRequest.filter = filter;
1808         res->r.SearchRequest.num_attributes = num_attributes;
1809         res->r.SearchRequest.attributes = attributes;
1810         return res;
1811 }
1812
1813 struct ldap_message *new_ldap_simple_bind_msg(const char *dn, const char *pw)
1814 {
1815         struct ldap_message *res = new_ldap_message();
1816
1817         if (res == NULL)
1818                 return NULL;
1819
1820         res->type = LDAP_TAG_BindRequest;
1821         res->r.BindRequest.version = 3;
1822         res->r.BindRequest.dn = talloc_strdup(res->mem_ctx, dn);
1823         res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SIMPLE;
1824         res->r.BindRequest.creds.password = talloc_strdup(res->mem_ctx, pw);
1825         return res;
1826 }
1827
1828 BOOL ldap_setsearchent(struct ldap_connection *conn, struct ldap_message *msg,
1829                        const struct timeval *endtime)
1830 {
1831         if ((conn->searchid != 0) &&
1832             (!ldap_abandon_message(conn, conn->searchid, endtime)))
1833                 return False;
1834
1835         conn->searchid = conn->next_msgid;
1836         return ldap_send_msg(conn, msg, endtime);
1837 }
1838
1839 struct ldap_message *ldap_getsearchent(struct ldap_connection *conn,
1840                                        const struct timeval *endtime)
1841 {
1842         struct ldap_message *result;
1843
1844         if (conn->search_entries != NULL) {
1845                 struct ldap_queue_entry *e = conn->search_entries;
1846
1847                 result = e->msg;
1848                 DLIST_REMOVE(conn->search_entries, e);
1849                 SAFE_FREE(e);
1850                 return result;
1851         }
1852
1853         result = ldap_receive(conn, conn->searchid, endtime);
1854
1855         if (result->type == LDAP_TAG_SearchResultEntry)
1856                 return result;
1857
1858         if (result->type == LDAP_TAG_SearchResultDone) {
1859                 /* TODO: Handle Paged Results */
1860                 destroy_ldap_message(result);
1861                 return NULL;
1862         }
1863
1864         /* TODO: Handle Search References here */
1865         return NULL;
1866 }
1867
1868 void ldap_endsearchent(struct ldap_connection *conn,
1869                        const struct timeval *endtime)
1870 {
1871         struct ldap_queue_entry *e;
1872
1873         e = conn->search_entries;
1874
1875         while (e != NULL) {
1876                 struct ldap_queue_entry *next = e->next;
1877                 DLIST_REMOVE(conn->search_entries, e);
1878                 SAFE_FREE(e);
1879                 e = next;
1880         }
1881 }
1882
1883 struct ldap_message *ldap_searchone(struct ldap_connection *conn,
1884                                     struct ldap_message *msg,
1885                                     const struct timeval *endtime)
1886 {
1887         struct ldap_message *res1, *res2 = NULL;
1888         if (!ldap_setsearchent(conn, msg, endtime))
1889                 return NULL;
1890
1891         res1 = ldap_getsearchent(conn, endtime);
1892
1893         if (res1 != NULL)
1894                 res2 = ldap_getsearchent(conn, endtime);
1895
1896         ldap_endsearchent(conn, endtime);
1897
1898         if (res1 == NULL)
1899                 return NULL;
1900
1901         if (res2 != NULL) {
1902                 /* More than one entry */
1903                 destroy_ldap_message(res1);
1904                 destroy_ldap_message(res2);
1905                 return NULL;
1906         }
1907
1908         return res1;
1909 }
1910
1911 BOOL ldap_find_single_value(struct ldap_message *msg, const char *attr,
1912                             DATA_BLOB *value)
1913 {
1914         int i;
1915         struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1916
1917         if (msg->type != LDAP_TAG_SearchResultEntry)
1918                 return False;
1919
1920         for (i=0; i<r->num_attributes; i++) {
1921                 if (strequal(attr, r->attributes[i].name)) {
1922                         if (r->attributes[i].num_values != 1)
1923                                 return False;
1924
1925                         *value = r->attributes[i].values[0];
1926                         return True;
1927                 }
1928         }
1929         return False;
1930 }
1931
1932 BOOL ldap_find_single_string(struct ldap_message *msg, const char *attr,
1933                              TALLOC_CTX *mem_ctx, char **value)
1934 {
1935         DATA_BLOB blob;
1936
1937         if (!ldap_find_single_value(msg, attr, &blob))
1938                 return False;
1939
1940         *value = talloc(mem_ctx, blob.length+1);
1941
1942         if (*value == NULL)
1943                 return False;
1944
1945         memcpy(*value, blob.data, blob.length);
1946         (*value)[blob.length] = '\0';
1947         return True;
1948 }
1949
1950 BOOL ldap_find_single_int(struct ldap_message *msg, const char *attr,
1951                           int *value)
1952 {
1953         DATA_BLOB blob;
1954         char *val;
1955         int errno_save;
1956         BOOL res;
1957
1958         if (!ldap_find_single_value(msg, attr, &blob))
1959                 return False;
1960
1961         val = malloc(blob.length+1);
1962         if (val == NULL)
1963                 return False;
1964
1965         memcpy(val, blob.data, blob.length);
1966         val[blob.length] = '\0';
1967
1968         errno_save = errno;
1969         errno = 0;
1970
1971         *value = strtol(val, NULL, 10);
1972
1973         res = (errno == 0);
1974
1975         free(val);
1976         errno = errno_save;
1977
1978         return res;
1979 }
1980
1981 int ldap_error(struct ldap_connection *conn)
1982 {
1983         return 0;
1984 }
1985
1986 NTSTATUS ldap2nterror(int ldaperror)
1987 {
1988         return NT_STATUS_OK;
1989 }