r3443: the next stage in the include files re-organisation.
[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    Copyright (C) Stefan Metzmacher 2004
8    Copyright (C) Simo Sorce 2004
9     
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23    
24 */
25
26 #include "includes.h"
27 #include "system/network.h"
28
29 /****************************************************************************
30  *
31  * LDAP filter parser -- main routine is ldap_parse_filter
32  *
33  * Shamelessly stolen and adapted from ldb.
34  *
35  ***************************************************************************/
36
37 /*
38   return next token element. Caller frees
39 */
40 static char *ldap_parse_lex(TALLOC_CTX *mem_ctx, const char **s,
41                            const char *sep)
42 {
43         const char *p = *s;
44         char *ret;
45
46         while (isspace(*p)) {
47                 p++;
48         }
49         *s = p;
50
51         if (*p == 0) {
52                 return NULL;
53         }
54
55         if (strchr(sep, *p)) {
56                 (*s) = p+1;
57                 ret = talloc_strndup(mem_ctx, p, 1);
58                 if (!ret) {
59                         errno = ENOMEM;
60                 }
61                 return ret;
62         }
63
64         while (*p && (isalnum(*p) || !strchr(sep, *p))) {
65                 p++;
66         }
67
68         if (p == *s) {
69                 return NULL;
70         }
71
72         ret = talloc_strndup(mem_ctx, *s, p - *s);
73         if (!ret) {
74                 errno = ENOMEM;
75         }
76
77         *s = p;
78
79         return ret;
80 }
81
82
83 /*
84   find a matching close brace in a string
85 */
86 static const char *match_brace(const char *s)
87 {
88         unsigned int count = 0;
89         while (*s && (count != 0 || *s != ')')) {
90                 if (*s == '(') {
91                         count++;
92                 }
93                 if (*s == ')') {
94                         count--;
95                 }
96                 s++;
97         }
98         if (! *s) {
99                 return NULL;
100         }
101         return s;
102 }
103
104 static struct ldap_parse_tree *ldap_parse_filter(TALLOC_CTX *mem_ctx,
105                                                const char **s);
106
107 /*
108   <simple> ::= <attributetype> <filtertype> <attributevalue>
109 */
110 static struct ldap_parse_tree *ldap_parse_simple(TALLOC_CTX *mem_ctx,
111                                                const char *s)
112 {
113         char *eq, *val, *l;
114         struct ldap_parse_tree *ret;
115
116         l = ldap_parse_lex(mem_ctx, &s, LDAP_ALL_SEP);
117         if (!l) {
118                 return NULL;
119         }
120
121         if (strchr("()&|=", *l))
122                 return NULL;
123
124         eq = ldap_parse_lex(mem_ctx, &s, LDAP_ALL_SEP);
125         if (!eq || strcmp(eq, "=") != 0)
126                 return NULL;
127
128         val = ldap_parse_lex(mem_ctx, &s, ")");
129         if (val && strchr("()&|", *val))
130                 return NULL;
131         
132         ret = talloc(mem_ctx, sizeof(*ret));
133         if (!ret) {
134                 errno = ENOMEM;
135                 return NULL;
136         }
137
138         ret->operation = LDAP_OP_SIMPLE;
139         ret->u.simple.attr = l;
140         ret->u.simple.value.data = val;
141         ret->u.simple.value.length = val?strlen(val):0;
142
143         return ret;
144 }
145
146
147 /*
148   parse a filterlist
149   <and> ::= '&' <filterlist>
150   <or> ::= '|' <filterlist>
151   <filterlist> ::= <filter> | <filter> <filterlist>
152 */
153 static struct ldap_parse_tree *ldap_parse_filterlist(TALLOC_CTX *mem_ctx,
154                                                    enum ldap_parse_op op,
155                                                    const char *s)
156 {
157         struct ldap_parse_tree *ret, *next;
158
159         ret = talloc(mem_ctx, sizeof(*ret));
160
161         if (!ret) {
162                 errno = ENOMEM;
163                 return NULL;
164         }
165
166         ret->operation = op;
167         ret->u.list.num_elements = 1;
168         ret->u.list.elements = talloc(mem_ctx, sizeof(*ret->u.list.elements));
169         if (!ret->u.list.elements) {
170                 errno = ENOMEM;
171                 return NULL;
172         }
173
174         ret->u.list.elements[0] = ldap_parse_filter(mem_ctx, &s);
175         if (!ret->u.list.elements[0]) {
176                 return NULL;
177         }
178
179         while (isspace(*s)) s++;
180
181         while (*s && (next = ldap_parse_filter(mem_ctx, &s))) {
182                 struct ldap_parse_tree **e;
183                 e = talloc_realloc_p(ret,
184                                      ret->u.list.elements,
185                                      struct ldap_parse_tree *,
186                                      ret->u.list.num_elements+1);
187                 if (!e) {
188                         errno = ENOMEM;
189                         return NULL;
190                 }
191                 ret->u.list.elements = e;
192                 ret->u.list.elements[ret->u.list.num_elements] = next;
193                 ret->u.list.num_elements++;
194                 while (isspace(*s)) s++;
195         }
196
197         return ret;
198 }
199
200
201 /*
202   <not> ::= '!' <filter>
203 */
204 static struct ldap_parse_tree *ldap_parse_not(TALLOC_CTX *mem_ctx, const char *s)
205 {
206         struct ldap_parse_tree *ret;
207
208         ret = talloc(mem_ctx, sizeof(*ret));
209         if (!ret) {
210                 errno = ENOMEM;
211                 return NULL;
212         }
213
214         ret->operation = LDAP_OP_NOT;
215         ret->u.not.child = ldap_parse_filter(mem_ctx, &s);
216         if (!ret->u.not.child)
217                 return NULL;
218
219         return ret;
220 }
221
222 /*
223   parse a filtercomp
224   <filtercomp> ::= <and> | <or> | <not> | <simple>
225 */
226 static struct ldap_parse_tree *ldap_parse_filtercomp(TALLOC_CTX *mem_ctx,
227                                                    const char *s)
228 {
229         while (isspace(*s)) s++;
230
231         switch (*s) {
232         case '&':
233                 return ldap_parse_filterlist(mem_ctx, LDAP_OP_AND, s+1);
234
235         case '|':
236                 return ldap_parse_filterlist(mem_ctx, LDAP_OP_OR, s+1);
237
238         case '!':
239                 return ldap_parse_not(mem_ctx, s+1);
240
241         case '(':
242         case ')':
243                 return NULL;
244         }
245
246         return ldap_parse_simple(mem_ctx, s);
247 }
248
249
250 /*
251   <filter> ::= '(' <filtercomp> ')'
252 */
253 static struct ldap_parse_tree *ldap_parse_filter(TALLOC_CTX *mem_ctx,
254                                                const char **s)
255 {
256         char *l, *s2;
257         const char *p, *p2;
258         struct ldap_parse_tree *ret;
259
260         l = ldap_parse_lex(mem_ctx, s, LDAP_ALL_SEP);
261         if (!l) {
262                 return NULL;
263         }
264
265         if (strcmp(l, "(") != 0) {
266                 return NULL;
267         }
268
269         p = match_brace(*s);
270         if (!p) {
271                 return NULL;
272         }
273         p2 = p + 1;
274
275         s2 = talloc_strndup(mem_ctx, *s, p - *s);
276         if (!s2) {
277                 errno = ENOMEM;
278                 return NULL;
279         }
280
281         ret = ldap_parse_filtercomp(mem_ctx, s2);
282
283         *s = p2;
284
285         return ret;
286 }
287
288 /*
289   main parser entry point. Takes a search string and returns a parse tree
290
291   expression ::= <simple> | <filter>
292 */
293 static struct ldap_parse_tree *ldap_parse_tree(TALLOC_CTX *mem_ctx, const char *s)
294 {
295         while (isspace(*s)) s++;
296
297         if (*s == '(') {
298                 return ldap_parse_filter(mem_ctx, &s);
299         }
300
301         return ldap_parse_simple(mem_ctx, s);
302 }
303
304 static BOOL ldap_push_filter(ASN1_DATA *data, struct ldap_parse_tree *tree)
305 {
306         switch (tree->operation) {
307         case LDAP_OP_SIMPLE: {
308                 if ((tree->u.simple.value.length == 1) &&
309                     (((char *)(tree->u.simple.value.data))[0] == '*')) {
310                         /* Just a presence test */
311                         asn1_push_tag(data, 0x87);
312                         asn1_write(data, tree->u.simple.attr,
313                                    strlen(tree->u.simple.attr));
314                         asn1_pop_tag(data);
315                         return !data->has_error;
316                 }
317
318                 /* Equality is all we currently do... */
319                 asn1_push_tag(data, 0xa3);
320                 asn1_write_OctetString(data, tree->u.simple.attr,
321                                       strlen(tree->u.simple.attr));
322                 asn1_write_OctetString(data, tree->u.simple.value.data,
323                                       tree->u.simple.value.length);
324                 asn1_pop_tag(data);
325                 break;
326         }
327
328         case LDAP_OP_AND: {
329                 int i;
330
331                 asn1_push_tag(data, 0xa0);
332                 for (i=0; i<tree->u.list.num_elements; i++) {
333                         ldap_push_filter(data, tree->u.list.elements[i]);
334                 }
335                 asn1_pop_tag(data);
336                 break;
337         }
338
339         case LDAP_OP_OR: {
340                 int i;
341
342                 asn1_push_tag(data, 0xa1);
343                 for (i=0; i<tree->u.list.num_elements; i++) {
344                         ldap_push_filter(data, tree->u.list.elements[i]);
345                 }
346                 asn1_pop_tag(data);
347                 break;
348         }
349         default:
350                 return False;
351         }
352         return !data->has_error;
353 }
354
355 static void ldap_encode_response(ASN1_DATA *data, struct ldap_Result *result)
356 {
357         asn1_write_enumerated(data, result->resultcode);
358         asn1_write_OctetString(data, result->dn,
359                                (result->dn) ? strlen(result->dn) : 0);
360         asn1_write_OctetString(data, result->errormessage,
361                                (result->errormessage) ?
362                                strlen(result->errormessage) : 0);
363         if (result->referral != NULL)
364                 asn1_write_OctetString(data, result->referral,
365                                        strlen(result->referral));
366 }
367
368 BOOL ldap_encode(struct ldap_message *msg, DATA_BLOB *result)
369 {
370         ASN1_DATA data;
371         int i, j;
372
373         ZERO_STRUCT(data);
374         asn1_push_tag(&data, ASN1_SEQUENCE(0));
375         asn1_write_Integer(&data, msg->messageid);
376
377         switch (msg->type) {
378         case LDAP_TAG_BindRequest: {
379                 struct ldap_BindRequest *r = &msg->r.BindRequest;
380                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
381                 asn1_write_Integer(&data, r->version);
382                 asn1_write_OctetString(&data, r->dn,
383                                        (r->dn != NULL) ? strlen(r->dn) : 0);
384
385                 switch (r->mechanism) {
386                 case LDAP_AUTH_MECH_SIMPLE:
387                         /* context, primitive */
388                         asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
389                         asn1_write(&data, r->creds.password,
390                                    strlen(r->creds.password));
391                         asn1_pop_tag(&data);
392                         break;
393                 case LDAP_AUTH_MECH_SASL:
394                         /* context, constructed */
395                         asn1_push_tag(&data, ASN1_CONTEXT(3));
396                         asn1_write_OctetString(&data, r->creds.SASL.mechanism,
397                                                strlen(r->creds.SASL.mechanism));
398                         asn1_write_OctetString(&data, r->creds.SASL.secblob.data,
399                                                r->creds.SASL.secblob.length);
400                         asn1_pop_tag(&data);
401                         break;
402                 default:
403                         return False;
404                 }
405
406                 asn1_pop_tag(&data);
407                 asn1_pop_tag(&data);
408                 break;
409         }
410         case LDAP_TAG_BindResponse: {
411                 struct ldap_BindResponse *r = &msg->r.BindResponse;
412                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
413                 ldap_encode_response(&data, &r->response);
414                 if (r->SASL.secblob.length > 0) {
415                         asn1_write_ContextSimple(&data, 7, &r->SASL.secblob);
416                 }
417                 asn1_pop_tag(&data);
418                 break;
419         }
420         case LDAP_TAG_UnbindRequest: {
421 /*              struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
422                 break;
423         }
424         case LDAP_TAG_SearchRequest: {
425                 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
426                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
427                 asn1_write_OctetString(&data, r->basedn, strlen(r->basedn));
428                 asn1_write_enumerated(&data, r->scope);
429                 asn1_write_enumerated(&data, r->deref);
430                 asn1_write_Integer(&data, r->sizelimit);
431                 asn1_write_Integer(&data, r->timelimit);
432                 asn1_write_BOOLEAN(&data, r->attributesonly);
433
434                 {
435                         TALLOC_CTX *mem_ctx = talloc_init("ldap_parse_tree");
436                         struct ldap_parse_tree *tree;
437
438                         if (mem_ctx == NULL)
439                                 return False;
440
441                         tree = ldap_parse_tree(mem_ctx, r->filter);
442
443                         if (tree == NULL)
444                                 return False;
445
446                         ldap_push_filter(&data, tree);
447
448                         talloc_destroy(mem_ctx);
449                 }
450
451                 asn1_push_tag(&data, ASN1_SEQUENCE(0));
452                 for (i=0; i<r->num_attributes; i++) {
453                         asn1_write_OctetString(&data, r->attributes[i],
454                                                strlen(r->attributes[i]));
455                 }
456                 asn1_pop_tag(&data);
457
458                 asn1_pop_tag(&data);
459                 break;
460         }
461         case LDAP_TAG_SearchResultEntry: {
462                 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
463                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
464                 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
465                 asn1_push_tag(&data, ASN1_SEQUENCE(0));
466                 for (i=0; i<r->num_attributes; i++) {
467                         struct ldap_attribute *attr = &r->attributes[i];
468                         asn1_push_tag(&data, ASN1_SEQUENCE(0));
469                         asn1_write_OctetString(&data, attr->name,
470                                                strlen(attr->name));
471                         asn1_push_tag(&data, ASN1_SEQUENCE(1));
472                         for (j=0; j<attr->num_values; j++) {
473                                 asn1_write_OctetString(&data,
474                                                        attr->values[j].data,
475                                                        attr->values[j].length);
476                         }
477                         asn1_pop_tag(&data);
478                         asn1_pop_tag(&data);
479                 }
480                 asn1_pop_tag(&data);
481                 asn1_pop_tag(&data);
482                 break;
483         }
484         case LDAP_TAG_SearchResultDone: {
485                 struct ldap_Result *r = &msg->r.SearchResultDone;
486                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
487                 ldap_encode_response(&data, r);
488                 asn1_pop_tag(&data);
489                 break;
490         }
491         case LDAP_TAG_ModifyRequest: {
492                 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
493                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
494                 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
495                 asn1_push_tag(&data, ASN1_SEQUENCE(0));
496
497                 for (i=0; i<r->num_mods; i++) {
498                         struct ldap_attribute *attrib = &r->mods[i].attrib;
499                         asn1_push_tag(&data, ASN1_SEQUENCE(0));
500                         asn1_write_enumerated(&data, r->mods[i].type);
501                         asn1_push_tag(&data, ASN1_SEQUENCE(0));
502                         asn1_write_OctetString(&data, attrib->name,
503                                                strlen(attrib->name));
504                         asn1_push_tag(&data, ASN1_SET);
505                         for (j=0; j<attrib->num_values; j++) {
506                                 asn1_write_OctetString(&data,
507                                                        attrib->values[j].data,
508                                                        attrib->values[j].length);
509         
510                         }
511                         asn1_pop_tag(&data);
512                         asn1_pop_tag(&data);
513                         asn1_pop_tag(&data);
514                 }
515                 
516                 asn1_pop_tag(&data);
517                 asn1_pop_tag(&data);
518                 break;
519         }
520         case LDAP_TAG_ModifyResponse: {
521                 struct ldap_Result *r = &msg->r.ModifyResponse;
522                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
523                 ldap_encode_response(&data, r);
524                 asn1_pop_tag(&data);
525                 break;
526         }
527         case LDAP_TAG_AddRequest: {
528                 struct ldap_AddRequest *r = &msg->r.AddRequest;
529                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
530                 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
531                 asn1_push_tag(&data, ASN1_SEQUENCE(0));
532
533                 for (i=0; i<r->num_attributes; i++) {
534                         struct ldap_attribute *attrib = &r->attributes[i];
535                         asn1_push_tag(&data, ASN1_SEQUENCE(0));
536                         asn1_write_OctetString(&data, attrib->name,
537                                                strlen(attrib->name));
538                         asn1_push_tag(&data, ASN1_SET);
539                         for (j=0; j<r->attributes[i].num_values; j++) {
540                                 asn1_write_OctetString(&data,
541                                                        attrib->values[j].data,
542                                                        attrib->values[j].length);
543                         }
544                         asn1_pop_tag(&data);
545                         asn1_pop_tag(&data);
546                 }
547                 asn1_pop_tag(&data);
548                 asn1_pop_tag(&data);
549                 break;
550         }
551         case LDAP_TAG_AddResponse: {
552                 struct ldap_Result *r = &msg->r.AddResponse;
553                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
554                 ldap_encode_response(&data, r);
555                 asn1_pop_tag(&data);
556                 break;
557         }
558         case LDAP_TAG_DelRequest: {
559                 struct ldap_DelRequest *r = &msg->r.DelRequest;
560                 asn1_push_tag(&data, ASN1_APPLICATION_SIMPLE(msg->type));
561                 asn1_write(&data, r->dn, strlen(r->dn));
562                 asn1_pop_tag(&data);
563                 break;
564         }
565         case LDAP_TAG_DelResponse: {
566                 struct ldap_Result *r = &msg->r.DelResponse;
567                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
568                 ldap_encode_response(&data, r);
569                 asn1_pop_tag(&data);
570                 break;
571         }
572         case LDAP_TAG_ModifyDNRequest: {
573                 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
574                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
575                 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
576                 asn1_write_OctetString(&data, r->newrdn, strlen(r->newrdn));
577                 asn1_write_BOOLEAN(&data, r->deleteolddn);
578                 if (r->newsuperior != NULL) {
579                         asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
580                         asn1_write(&data, r->newsuperior,
581                                    strlen(r->newsuperior));
582                         asn1_pop_tag(&data);
583                 }
584                 asn1_pop_tag(&data);
585                 break;
586         }
587         case LDAP_TAG_ModifyDNResponse: {
588                 struct ldap_Result *r = &msg->r.ModifyDNResponse;
589                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
590                 ldap_encode_response(&data, r);
591                 asn1_pop_tag(&data);
592                 break;
593         }
594         case LDAP_TAG_CompareRequest: {
595                 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
596                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
597                 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
598                 asn1_push_tag(&data, ASN1_SEQUENCE(0));
599                 asn1_write_OctetString(&data, r->attribute,
600                                        strlen(r->attribute));
601                 asn1_write_OctetString(&data, r->value.data,
602                                        r->value.length);
603                 asn1_pop_tag(&data);
604                 asn1_pop_tag(&data);
605                 break;
606         }
607         case LDAP_TAG_CompareResponse: {
608                 struct ldap_Result *r = &msg->r.ModifyDNResponse;
609                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
610                 ldap_encode_response(&data, r);
611                 asn1_pop_tag(&data);
612                 break;
613         }
614         case LDAP_TAG_AbandonRequest: {
615                 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
616                 asn1_push_tag(&data, ASN1_APPLICATION_SIMPLE(msg->type));
617                 asn1_write_implicit_Integer(&data, r->messageid);
618                 asn1_pop_tag(&data);
619                 break;
620         }
621         case LDAP_TAG_SearchResultReference: {
622 /*              struct ldap_SearchResRef *r = &msg->r.SearchResultReference; */
623                 break;
624         }
625         case LDAP_TAG_ExtendedRequest: {
626                 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
627                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
628                 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
629                 asn1_write(&data, r->oid, strlen(r->oid));
630                 asn1_pop_tag(&data);
631                 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(1));
632                 asn1_write(&data, r->value.data, r->value.length);
633                 asn1_pop_tag(&data);
634                 asn1_pop_tag(&data);
635                 break;
636         }
637         case LDAP_TAG_ExtendedResponse: {
638                 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
639                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
640                 ldap_encode_response(&data, &r->response);
641                 asn1_pop_tag(&data);
642                 break;
643         }
644         default:
645                 return False;
646         }
647
648         asn1_pop_tag(&data);
649         *result = data_blob(data.data, data.length);
650         asn1_free(&data);
651         return True;
652 }
653
654 static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
655                                       DATA_BLOB blob)
656 {
657         char *result = talloc(mem_ctx, blob.length+1);
658         memcpy(result, blob.data, blob.length);
659         result[blob.length] = '\0';
660         return result;
661 }
662
663 static BOOL asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
664                                          ASN1_DATA *data,
665                                          const char **result)
666 {
667         DATA_BLOB string;
668         if (!asn1_read_OctetString(data, &string))
669                 return False;
670         *result = blob2string_talloc(mem_ctx, string);
671         data_blob_free(&string);
672         return True;
673 }
674
675 static void ldap_decode_response(TALLOC_CTX *mem_ctx,
676                                  ASN1_DATA *data,
677                                  struct ldap_Result *result)
678 {
679         asn1_read_enumerated(data, &result->resultcode);
680         asn1_read_OctetString_talloc(mem_ctx, data, &result->dn);
681         asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage);
682         if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
683                 asn1_start_tag(data, ASN1_CONTEXT(3));
684                 asn1_read_OctetString_talloc(mem_ctx, data, &result->referral);
685                 asn1_end_tag(data);
686         } else {
687                 result->referral = NULL;
688         }
689 }
690
691 static BOOL ldap_decode_filter(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
692                                char **filter)
693 {
694         uint8 filter_tag, tag_desc;
695
696         if (!asn1_peek_uint8(data, &filter_tag))
697                 return False;
698
699         tag_desc = filter_tag;
700         filter_tag &= 0x1f;     /* strip off the asn1 stuff */
701         tag_desc &= 0xe0;
702
703         switch(filter_tag) {
704         case 0: {
705                 /* AND of one or more filters */
706                 if (tag_desc != 0xa0) /* context compount */
707                         return False;
708
709                 asn1_start_tag(data, ASN1_CONTEXT(0));
710
711                 *filter = talloc_strdup(mem_ctx, "(&");
712                 if (*filter == NULL)
713                         return False;
714
715                 while (asn1_tag_remaining(data) > 0) {
716                         char *subfilter;
717                         if (!ldap_decode_filter(mem_ctx, data, &subfilter))
718                                 return False;
719                         *filter = talloc_asprintf(mem_ctx, "%s%s", *filter,
720                                                   subfilter);
721                         if (*filter == NULL)
722                                 return False;
723                 }
724                 asn1_end_tag(data);
725
726                 *filter = talloc_asprintf(mem_ctx, "%s)", *filter);
727                 break;
728         }
729         case 1: {
730                 /* OR of one or more filters */
731                 if (tag_desc != 0xa0) /* context compount */
732                         return False;
733
734                 asn1_start_tag(data, ASN1_CONTEXT(1));
735
736                 *filter = talloc_strdup(mem_ctx, "(|");
737                 if (*filter == NULL)
738                         return False;
739
740                 while (asn1_tag_remaining(data) > 0) {
741                         char *subfilter;
742                         if (!ldap_decode_filter(mem_ctx, data, &subfilter))
743                                 return False;
744                         *filter = talloc_asprintf(mem_ctx, "%s%s", *filter,
745                                                   subfilter);
746                         if (*filter == NULL)
747                                 return False;
748                 }
749
750                 asn1_end_tag(data);
751
752                 *filter = talloc_asprintf(mem_ctx, "%s)", *filter);
753                 break;
754         }
755         case 3: {
756                 /* equalityMatch */
757                 const char *attrib, *value;
758                 if (tag_desc != 0xa0) /* context compound */
759                         return False;
760                 asn1_start_tag(data, ASN1_CONTEXT(3));
761                 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
762                 asn1_read_OctetString_talloc(mem_ctx, data, &value);
763                 asn1_end_tag(data);
764                 if ((data->has_error) || (attrib == NULL) || (value == NULL))
765                         return False;
766                 *filter = talloc_asprintf(mem_ctx, "(%s=%s)", attrib, value);
767                 break;
768         }
769         case 7: {
770                 /* Normal presence, "attribute=*" */
771                 int attr_len;
772                 char *attr_name;
773                 if (tag_desc != 0x80) /* context simple */
774                         return False;
775                 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(7)))
776                         return False;
777                 attr_len = asn1_tag_remaining(data);
778                 attr_name = malloc(attr_len+1);
779                 if (attr_name == NULL)
780                         return False;
781                 asn1_read(data, attr_name, attr_len);
782                 attr_name[attr_len] = '\0';
783                 *filter = talloc_asprintf(mem_ctx, "(%s=*)", attr_name);
784                 SAFE_FREE(attr_name);
785                 asn1_end_tag(data);
786                 break;
787         }
788         default:
789                 return False;
790         }
791         if (*filter == NULL)
792                 return False;
793         return True;
794 }
795
796 static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
797                                struct ldap_attribute *attrib)
798 {
799         asn1_start_tag(data, ASN1_SEQUENCE(0));
800         asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name);
801         asn1_start_tag(data, ASN1_SET);
802         while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
803                 DATA_BLOB blob;
804                 struct ldap_val value;
805                 asn1_read_OctetString(data, &blob);
806                 value.data = blob.data;
807                 value.length = blob.length;
808                 add_value_to_attrib(mem_ctx, &value, attrib);
809                 data_blob_free(&blob);
810         }
811         asn1_end_tag(data);
812         asn1_end_tag(data);
813         
814 }
815
816 static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
817                                 struct ldap_attribute **attributes,
818                                 int *num_attributes)
819 {
820         asn1_start_tag(data, ASN1_SEQUENCE(0));
821         while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
822                 struct ldap_attribute attrib;
823                 ZERO_STRUCT(attrib);
824                 ldap_decode_attrib(mem_ctx, data, &attrib);
825                 add_attrib_to_array_talloc(mem_ctx, &attrib,
826                                            attributes, num_attributes);
827         }
828         asn1_end_tag(data);
829 }
830
831 BOOL ldap_decode(ASN1_DATA *data, struct ldap_message *msg)
832 {
833         uint8 tag;
834
835         asn1_start_tag(data, ASN1_SEQUENCE(0));
836         asn1_read_Integer(data, &msg->messageid);
837
838         if (!asn1_peek_uint8(data, &tag))
839                 return False;
840
841         switch(tag) {
842
843         case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
844                 struct ldap_BindRequest *r = &msg->r.BindRequest;
845                 msg->type = LDAP_TAG_BindRequest;
846                 asn1_start_tag(data, tag);
847                 asn1_read_Integer(data, &r->version);
848                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
849                 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
850                         int pwlen;
851                         r->creds.password = "";
852                         r->mechanism = LDAP_AUTH_MECH_SIMPLE;
853                         asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
854                         pwlen = asn1_tag_remaining(data);
855                         if (pwlen != 0) {
856                                 char *pw = talloc(msg->mem_ctx, pwlen+1);
857                                 asn1_read(data, pw, pwlen);
858                                 pw[pwlen] = '\0';
859                                 r->creds.password = pw;
860                         }
861                         asn1_end_tag(data);
862                 } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
863                         asn1_start_tag(data, ASN1_CONTEXT(3));
864                         r->mechanism = LDAP_AUTH_MECH_SASL;
865                         asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->creds.SASL.mechanism);
866                         asn1_read_OctetString(data, &r->creds.SASL.secblob);
867                         if (r->creds.SASL.secblob.data) {
868                                 talloc_steal(msg->mem_ctx, r->creds.SASL.secblob.data);
869                         }
870                         asn1_end_tag(data);
871                 }
872                 asn1_end_tag(data);
873                 break;
874         }
875
876         case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
877                 struct ldap_BindResponse *r = &msg->r.BindResponse;
878                 msg->type = LDAP_TAG_BindResponse;
879                 asn1_start_tag(data, tag);
880                 ldap_decode_response(msg->mem_ctx, data, &r->response);
881                 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
882                         DATA_BLOB tmp_blob = data_blob(NULL, 0);
883                         asn1_read_ContextSimple(data, 7, &tmp_blob);
884                         r->SASL.secblob = data_blob_talloc(msg->mem_ctx, tmp_blob.data, tmp_blob.length);
885                         data_blob_free(&tmp_blob);
886                 } else {
887                         r->SASL.secblob = data_blob(NULL, 0);
888                 }
889                 asn1_end_tag(data);
890                 break;
891         }
892
893         case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
894                 msg->type = LDAP_TAG_UnbindRequest;
895                 asn1_start_tag(data, tag);
896                 asn1_end_tag(data);
897                 break;
898         }
899
900         case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
901                 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
902                 msg->type = LDAP_TAG_SearchRequest;
903                 asn1_start_tag(data, tag);
904                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->basedn);
905                 asn1_read_enumerated(data, (int *)&(r->scope));
906                 asn1_read_enumerated(data, (int *)&(r->deref));
907                 asn1_read_Integer(data, &r->sizelimit);
908                 asn1_read_Integer(data, &r->timelimit);
909                 asn1_read_BOOLEAN(data, &r->attributesonly);
910
911                 /* Maybe create a TALLOC_CTX for the filter? This can waste
912                  * quite a bit of memory recursing down. */
913                 ldap_decode_filter(msg->mem_ctx, data, &r->filter);
914
915                 asn1_start_tag(data, ASN1_SEQUENCE(0));
916
917                 r->num_attributes = 0;
918                 r->attributes = NULL;
919
920                 while (asn1_tag_remaining(data) > 0) {
921                         const char *attr;
922                         if (!asn1_read_OctetString_talloc(msg->mem_ctx, data,
923                                                           &attr))
924                                 return False;
925                         if (!add_string_to_array(msg->mem_ctx, attr,
926                                                  &r->attributes,
927                                                  &r->num_attributes))
928                                 return False;
929                 }
930
931                 asn1_end_tag(data);
932                 asn1_end_tag(data);
933                 break;
934         }
935
936         case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
937                 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
938                 msg->type = LDAP_TAG_SearchResultEntry;
939                 r->attributes = NULL;
940                 r->num_attributes = 0;
941                 asn1_start_tag(data, tag);
942                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
943                 ldap_decode_attribs(msg->mem_ctx, data, &r->attributes,
944                                     &r->num_attributes);
945                 asn1_end_tag(data);
946                 break;
947         }
948
949         case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
950                 struct ldap_Result *r = &msg->r.SearchResultDone;
951                 msg->type = LDAP_TAG_SearchResultDone;
952                 asn1_start_tag(data, tag);
953                 ldap_decode_response(msg->mem_ctx, data, r);
954                 asn1_end_tag(data);
955                 break;
956         }
957
958         case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
959 /*              struct ldap_SearchResRef *r = &msg->r.SearchResultReference; */
960                 msg->type = LDAP_TAG_SearchResultReference;
961                 break;
962         }
963
964         case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
965                 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
966                 msg->type = LDAP_TAG_ModifyRequest;
967                 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
968                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
969                 asn1_start_tag(data, ASN1_SEQUENCE(0));
970
971                 r->num_mods = 0;
972                 r->mods = NULL;
973
974                 while (asn1_tag_remaining(data) > 0) {
975                         struct ldap_mod mod;
976                         ZERO_STRUCT(mod);
977                         asn1_start_tag(data, ASN1_SEQUENCE(0));
978                         asn1_read_enumerated(data, &mod.type);
979                         ldap_decode_attrib(msg->mem_ctx, data, &mod.attrib);
980                         asn1_end_tag(data);
981                         if (!add_mod_to_array_talloc(msg->mem_ctx, &mod,
982                                                      &r->mods, &r->num_mods))
983                                 break;
984                 }
985
986                 asn1_end_tag(data);
987                 asn1_end_tag(data);
988                 break;
989         }
990
991         case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
992                 struct ldap_Result *r = &msg->r.ModifyResponse;
993                 msg->type = LDAP_TAG_ModifyResponse;
994                 asn1_start_tag(data, tag);
995                 ldap_decode_response(msg->mem_ctx, data, r);
996                 asn1_end_tag(data);
997                 break;
998         }
999
1000         case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1001                 struct ldap_AddRequest *r = &msg->r.AddRequest;
1002                 msg->type = LDAP_TAG_AddRequest;
1003                 asn1_start_tag(data, tag);
1004                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
1005
1006                 r->attributes = NULL;
1007                 r->num_attributes = 0;
1008                 ldap_decode_attribs(msg->mem_ctx, data, &r->attributes,
1009                                     &r->num_attributes);
1010
1011                 asn1_end_tag(data);
1012                 break;
1013         }
1014
1015         case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1016                 struct ldap_Result *r = &msg->r.AddResponse;
1017                 msg->type = LDAP_TAG_AddResponse;
1018                 asn1_start_tag(data, tag);
1019                 ldap_decode_response(msg->mem_ctx, data, r);
1020                 asn1_end_tag(data);
1021                 break;
1022         }
1023
1024         case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1025                 struct ldap_DelRequest *r = &msg->r.DelRequest;
1026                 int len;
1027                 char *dn;
1028                 msg->type = LDAP_TAG_DelRequest;
1029                 asn1_start_tag(data,
1030                                ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
1031                 len = asn1_tag_remaining(data);
1032                 dn = talloc(msg->mem_ctx, len+1);
1033                 if (dn == NULL)
1034                         break;
1035                 asn1_read(data, dn, len);
1036                 dn[len] = '\0';
1037                 r->dn = dn;
1038                 asn1_end_tag(data);
1039                 break;
1040         }
1041
1042         case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1043                 struct ldap_Result *r = &msg->r.DelResponse;
1044                 msg->type = LDAP_TAG_DelResponse;
1045                 asn1_start_tag(data, tag);
1046                 ldap_decode_response(msg->mem_ctx, data, r);
1047                 asn1_end_tag(data);
1048                 break;
1049         }
1050
1051         case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1052                 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1053                 msg->type = LDAP_TAG_ModifyDNRequest;
1054                 asn1_start_tag(data,
1055                                ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
1056                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
1057                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->newrdn);
1058                 asn1_read_BOOLEAN(data, &r->deleteolddn);
1059                 r->newsuperior = NULL;
1060                 if (asn1_tag_remaining(data) > 0) {
1061                         int len;
1062                         char *newsup;
1063                         asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1064                         len = asn1_tag_remaining(data);
1065                         newsup = talloc(msg->mem_ctx, len+1);
1066                         if (newsup == NULL)
1067                                 break;
1068                         asn1_read(data, newsup, len);
1069                         newsup[len] = '\0';
1070                         r->newsuperior = newsup;
1071                         asn1_end_tag(data);
1072                 }
1073                 asn1_end_tag(data);
1074                 break;
1075         }
1076
1077         case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1078                 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1079                 msg->type = LDAP_TAG_ModifyDNResponse;
1080                 asn1_start_tag(data, tag);
1081                 ldap_decode_response(msg->mem_ctx, data, r);
1082                 asn1_end_tag(data);
1083                 break;
1084         }
1085
1086         case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1087                 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1088                 msg->type = LDAP_TAG_CompareRequest;
1089                 asn1_start_tag(data,
1090                                ASN1_APPLICATION(LDAP_TAG_CompareRequest));
1091                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
1092                 asn1_start_tag(data, ASN1_SEQUENCE(0));
1093                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->attribute);
1094                 asn1_read_OctetString(data, &r->value);
1095                 if (r->value.data) {
1096                         talloc_steal(msg->mem_ctx, r->value.data);
1097                 }
1098                 asn1_end_tag(data);
1099                 asn1_end_tag(data);
1100                 break;
1101         }
1102
1103         case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1104                 struct ldap_Result *r = &msg->r.CompareResponse;
1105                 msg->type = LDAP_TAG_CompareResponse;
1106                 asn1_start_tag(data, tag);
1107                 ldap_decode_response(msg->mem_ctx, data, r);
1108                 asn1_end_tag(data);
1109                 break;
1110         }
1111
1112         case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1113                 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1114                 msg->type = LDAP_TAG_AbandonRequest;
1115                 asn1_start_tag(data, tag);
1116                 asn1_read_implicit_Integer(data, &r->messageid);
1117                 asn1_end_tag(data);
1118                 break;
1119         }
1120
1121         case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1122                 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1123                 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1124
1125                 msg->type = LDAP_TAG_ExtendedRequest;
1126                 asn1_start_tag(data,tag);
1127                 if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
1128                         return False;
1129                 }
1130                 r->oid = blob2string_talloc(msg->mem_ctx, tmp_blob);
1131                 data_blob_free(&tmp_blob);
1132                 if (!r->oid) {
1133                         return False;
1134                 }
1135
1136                 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1137                         asn1_read_ContextSimple(data, 1, &tmp_blob);
1138                         r->value = data_blob_talloc(msg->mem_ctx, tmp_blob.data, tmp_blob.length);
1139                         data_blob_free(&tmp_blob);
1140                 } else {
1141                         r->value = data_blob(NULL, 0);
1142                 }
1143
1144                 asn1_end_tag(data);
1145                 break;
1146         }
1147
1148         case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1149                 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1150                 msg->type = LDAP_TAG_ExtendedResponse;
1151                 asn1_start_tag(data, tag);              
1152                 ldap_decode_response(msg->mem_ctx, data, &r->response);
1153                 /* I have to come across an operation that actually sends
1154                  * something back to really see what's going on. The currently
1155                  * needed pwdchange does not send anything back. */
1156                 r->name = NULL;
1157                 r->value.data = NULL;
1158                 r->value.length = 0;
1159                 asn1_end_tag(data);
1160                 break;
1161         }
1162         default: 
1163                 return False;
1164         }
1165
1166         msg->num_controls = 0;
1167         msg->controls = NULL;
1168
1169         if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1170                 int i;
1171                 struct ldap_Control *ctrl = NULL;
1172
1173                 asn1_start_tag(data, ASN1_CONTEXT(0));
1174
1175                 for (i=0; asn1_peek_tag(data, ASN1_SEQUENCE(0)); i++) {
1176                         asn1_start_tag(data, ASN1_SEQUENCE(0));
1177
1178                         ctrl = talloc_realloc_p(msg->mem_ctx, ctrl, struct ldap_Control, i+1);
1179                         if (!ctrl) {
1180                                 return False;
1181                         }
1182                         ctrl[i].oid = NULL;
1183                         ctrl[i].critical = False;
1184                         ctrl[i].value = data_blob(NULL, 0);
1185
1186                         asn1_read_OctetString_talloc(ctrl, data, &ctrl[i].oid);
1187
1188                         if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
1189                                 asn1_read_BOOLEAN(data, &ctrl[i].critical);
1190                         }
1191
1192                         if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
1193                                 asn1_read_OctetString(data, &ctrl[i].value);
1194                                 if (ctrl[i].value.data) {
1195                                         talloc_steal(msg->mem_ctx, ctrl[i].value.data);
1196                                 }
1197                         }
1198
1199                         asn1_end_tag(data);
1200                 }
1201                 msg->num_controls = i;
1202                 msg->controls = ctrl;
1203
1204                 asn1_end_tag(data);
1205         }
1206
1207         asn1_end_tag(data);
1208         return ((!data->has_error) && (data->nesting == NULL));
1209 }
1210
1211 BOOL ldap_parse_basic_url(TALLOC_CTX *mem_ctx, const char *url,
1212                           char **host, uint16 *port, BOOL *ldaps)
1213 {
1214         int tmp_port = 0;
1215         fstring protocol;
1216         fstring tmp_host;
1217         const char *p = url;
1218
1219         /* skip leading "URL:" (if any) */
1220         if (strncasecmp( p, "URL:", 4) == 0) {
1221                 p += 4;
1222         }
1223
1224         /* Paranoia check */
1225         SMB_ASSERT(sizeof(protocol)>10 && sizeof(tmp_host)>254);
1226                 
1227         sscanf(p, "%10[^:]://%254[^:/]:%d", protocol, tmp_host, &tmp_port);
1228
1229         if (strequal(protocol, "ldap")) {
1230                 *port = 389;
1231                 *ldaps = False;
1232         } else if (strequal(protocol, "ldaps")) {
1233                 *port = 636;
1234                 *ldaps = True;
1235         } else {
1236                 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
1237                 return False;
1238         }
1239
1240         if (tmp_port != 0)
1241                 *port = tmp_port;
1242         
1243         *host = talloc_strdup(mem_ctx, tmp_host);
1244
1245         return (*host != NULL);
1246 }
1247
1248 struct ldap_connection *new_ldap_connection(void)
1249 {
1250         TALLOC_CTX *mem_ctx = talloc_init("ldap_connection");
1251         struct ldap_connection *result;
1252
1253         if (mem_ctx == NULL)
1254                 return NULL;
1255
1256         result = talloc(mem_ctx, sizeof(*result));
1257
1258         if (result == NULL)
1259                 return NULL;
1260
1261         result->mem_ctx = mem_ctx;
1262         result->next_msgid = 1;
1263         result->outstanding = NULL;
1264         result->searchid = 0;
1265         result->search_entries = NULL;
1266         result->auth_dn = NULL;
1267         result->simple_pw = NULL;
1268         result->gensec = NULL;
1269
1270         return result;
1271 }
1272
1273 BOOL ldap_connect(struct ldap_connection *conn, const char *url)
1274 {
1275         struct hostent *hp;
1276         struct ipv4_addr ip;
1277
1278         if (!ldap_parse_basic_url(conn->mem_ctx, url, &conn->host,
1279                                   &conn->port, &conn->ldaps))
1280                 return False;
1281
1282         hp = sys_gethostbyname(conn->host);
1283
1284         if ((hp == NULL) || (hp->h_addr == NULL))
1285                 return False;
1286
1287         putip((char *)&ip, (char *)hp->h_addr);
1288
1289         conn->sock = open_socket_out(SOCK_STREAM, &ip, conn->port, LDAP_CONNECTION_TIMEOUT);
1290
1291         return (conn->sock >= 0);
1292 }
1293
1294 BOOL ldap_set_simple_creds(struct ldap_connection *conn,
1295                            const char *dn, const char *password)
1296 {
1297         conn->auth_dn = talloc_strdup(conn->mem_ctx, dn);
1298         conn->simple_pw = talloc_strdup(conn->mem_ctx, password);
1299
1300         return ((conn->auth_dn != NULL) && (conn->simple_pw != NULL));
1301 }
1302
1303 struct ldap_message *new_ldap_message(void)
1304 {
1305         TALLOC_CTX *mem_ctx = talloc_init("ldap_message");
1306         struct ldap_message *result;
1307
1308         if (mem_ctx == NULL)
1309                 return NULL;
1310
1311         result = talloc(mem_ctx, sizeof(*result));
1312
1313         if (result == NULL)
1314                 return NULL;
1315
1316         result->mem_ctx = mem_ctx;
1317         return result;
1318 }
1319
1320 void destroy_ldap_message(struct ldap_message *msg)
1321 {
1322         if (msg != NULL)
1323                 talloc_destroy(msg->mem_ctx);
1324 }
1325
1326 BOOL ldap_send_msg(struct ldap_connection *conn, struct ldap_message *msg,
1327                    const struct timeval *endtime)
1328 {
1329         DATA_BLOB request;
1330         BOOL result;
1331         struct ldap_queue_entry *entry;
1332
1333         msg->messageid = conn->next_msgid++;
1334
1335         if (!ldap_encode(msg, &request))
1336                 return False;
1337
1338         result = (write_data_until(conn->sock, request.data, request.length,
1339                                    endtime) == request.length);
1340
1341         data_blob_free(&request);
1342
1343         if (!result)
1344                 return result;
1345
1346         /* abandon and unbind don't expect results */
1347
1348         if ((msg->type == LDAP_TAG_AbandonRequest) ||
1349             (msg->type == LDAP_TAG_UnbindRequest))
1350                 return True;
1351
1352         entry = malloc(sizeof(*entry)); 
1353
1354         if (entry == NULL)
1355                 return False;
1356
1357         entry->msgid = msg->messageid;
1358         entry->msg = NULL;
1359         DLIST_ADD(conn->outstanding, entry);
1360
1361         return True;
1362 }
1363
1364 BOOL ldap_receive_msg(struct ldap_connection *conn, struct ldap_message *msg,
1365                       const struct timeval *endtime)
1366 {
1367         struct asn1_data data;
1368         BOOL result;
1369
1370         if (!asn1_read_sequence_until(conn->sock, &data, endtime))
1371                 return False;
1372
1373         result = ldap_decode(&data, msg);
1374
1375         asn1_free(&data);
1376         return result;
1377 }
1378
1379 static struct ldap_message *recv_from_queue(struct ldap_connection *conn,
1380                                             int msgid)
1381 {
1382         struct ldap_queue_entry *e;
1383
1384         for (e = conn->outstanding; e != NULL; e = e->next) {
1385
1386                 if (e->msgid == msgid) {
1387                         struct ldap_message *result = e->msg;
1388                         DLIST_REMOVE(conn->outstanding, e);
1389                         SAFE_FREE(e);
1390                         return result;
1391                 }
1392         }
1393
1394         return NULL;
1395 }
1396
1397 static void add_search_entry(struct ldap_connection *conn,
1398                              struct ldap_message *msg)
1399 {
1400         struct ldap_queue_entry *e = malloc(sizeof *e);
1401
1402         if (e == NULL)
1403                 return;
1404
1405         e->msg = msg;
1406         DLIST_ADD_END(conn->search_entries, e, struct ldap_queue_entry *);
1407         return;
1408 }
1409
1410 static void fill_outstanding_request(struct ldap_connection *conn,
1411                                      struct ldap_message *msg)
1412 {
1413         struct ldap_queue_entry *e;
1414
1415         for (e = conn->outstanding; e != NULL; e = e->next) {
1416                 if (e->msgid == msg->messageid) {
1417                         e->msg = msg;
1418                         return;
1419                 }
1420         }
1421
1422         /* This reply has not been expected, destroy the incoming msg */
1423         destroy_ldap_message(msg);
1424         return;
1425 }
1426
1427 struct ldap_message *ldap_receive(struct ldap_connection *conn, int msgid,
1428                                   const struct timeval *endtime)
1429 {
1430         struct ldap_message *result = recv_from_queue(conn, msgid);
1431
1432         if (result != NULL)
1433                 return result;
1434
1435         while (True) {
1436                 struct asn1_data data;
1437                 BOOL res;
1438
1439                 result = new_ldap_message();
1440
1441                 if (!asn1_read_sequence_until(conn->sock, &data, endtime))
1442                         return NULL;
1443
1444                 res = ldap_decode(&data, result);
1445                 asn1_free(&data);
1446
1447                 if (!res)
1448                         return NULL;
1449
1450                 if (result->messageid == msgid)
1451                         return result;
1452
1453                 if (result->type == LDAP_TAG_SearchResultEntry) {
1454                         add_search_entry(conn, result);
1455                 } else {
1456                         fill_outstanding_request(conn, result);
1457                 }
1458         }
1459
1460         return NULL;
1461 }
1462
1463 struct ldap_message *ldap_transaction(struct ldap_connection *conn,
1464                                       struct ldap_message *request)
1465 {
1466         if (!ldap_send_msg(conn, request, NULL))
1467                 return False;
1468
1469         return ldap_receive(conn, request->messageid, NULL);
1470 }
1471
1472 int ldap_bind_simple(struct ldap_connection *conn, const char *userdn, const char *password)
1473 {
1474         struct ldap_message *response;
1475         struct ldap_message *msg;
1476         const char *dn, *pw;
1477         int result = LDAP_OTHER;
1478
1479         if (conn == NULL)
1480                 return result;
1481
1482         if (userdn) {
1483                 dn = userdn;
1484         } else {
1485                 if (conn->auth_dn) {
1486                         dn = conn->auth_dn;
1487                 } else {
1488                         dn = "";
1489                 }
1490         }
1491
1492         if (password) {
1493                 pw = password;
1494         } else {
1495                 if (conn->simple_pw) {
1496                         pw = conn->simple_pw;
1497                 } else {
1498                         pw = "";
1499                 }
1500         }
1501
1502         msg =  new_ldap_simple_bind_msg(dn, pw);
1503         if (!msg)
1504                 return result;
1505
1506         response = ldap_transaction(conn, msg);
1507         if (!response) {
1508                 destroy_ldap_message(msg);
1509                 return result;
1510         }
1511                 
1512         result = response->r.BindResponse.response.resultcode;
1513
1514         destroy_ldap_message(msg);
1515         destroy_ldap_message(response);
1516
1517         return result;
1518 }
1519
1520 int ldap_bind_sasl(struct ldap_connection *conn, const char *username, const char *domain, const char *password)
1521 {
1522         NTSTATUS status;
1523         TALLOC_CTX *mem_ctx = NULL;
1524         struct ldap_message *response;
1525         struct ldap_message *msg;
1526         DATA_BLOB input = data_blob(NULL, 0);
1527         DATA_BLOB output = data_blob(NULL, 0);
1528         int result = LDAP_OTHER;
1529
1530         if (conn == NULL)
1531                 return result;
1532
1533         status = gensec_client_start(conn, &conn->gensec);
1534         if (!NT_STATUS_IS_OK(status)) {
1535                 DEBUG(0, ("Failed to start GENSEC engine (%s)\n", nt_errstr(status)));
1536                 return result;
1537         }
1538
1539         gensec_want_feature(conn->gensec, GENSEC_WANT_SIGN | GENSEC_WANT_SEAL);
1540
1541         status = gensec_set_domain(conn->gensec, domain);
1542         if (!NT_STATUS_IS_OK(status)) {
1543                 DEBUG(1, ("Failed to start set GENSEC client domain to %s: %s\n", 
1544                           domain, nt_errstr(status)));
1545                 goto done;
1546         }
1547
1548         status = gensec_set_username(conn->gensec, username);
1549         if (!NT_STATUS_IS_OK(status)) {
1550                 DEBUG(1, ("Failed to start set GENSEC client username to %s: %s\n", 
1551                           username, nt_errstr(status)));
1552                 goto done;
1553         }
1554
1555         status = gensec_set_password(conn->gensec, password);
1556         if (!NT_STATUS_IS_OK(status)) {
1557                 DEBUG(1, ("Failed to start set GENSEC client password: %s\n", 
1558                           nt_errstr(status)));
1559                 goto done;
1560         }
1561
1562         status = gensec_set_target_hostname(conn->gensec, conn->host);
1563         if (!NT_STATUS_IS_OK(status)) {
1564                 DEBUG(1, ("Failed to start set GENSEC target hostname: %s\n", 
1565                           nt_errstr(status)));
1566                 goto done;
1567         }
1568
1569         status = gensec_start_mech_by_sasl_name(conn->gensec, "GSS-SPNEGO");
1570         if (!NT_STATUS_IS_OK(status)) {
1571                 DEBUG(1, ("Failed to start set GENSEC client SPNEGO mechanism: %s\n",
1572                           nt_errstr(status)));
1573                 goto done;
1574         }
1575
1576         mem_ctx = talloc_init("ldap_bind_sasl");
1577         if (!mem_ctx)
1578                 goto done;
1579
1580         status = gensec_update(conn->gensec, mem_ctx,
1581                                input,
1582                                &output);
1583
1584         while(1) {
1585                 if (NT_STATUS_IS_OK(status) && output.length == 0) {
1586                         break;
1587                 }
1588                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
1589                         break;
1590                 }
1591
1592                 msg =  new_ldap_sasl_bind_msg("GSS-SPNEGO", &output);
1593                 if (!msg)
1594                         goto done;
1595
1596                 response = ldap_transaction(conn, msg);
1597                 destroy_ldap_message(msg);
1598
1599                 if (!response) {
1600                         goto done;
1601                 }
1602
1603                 result = response->r.BindResponse.response.resultcode;
1604
1605                 if (result != LDAP_SUCCESS && result != LDAP_SASL_BIND_IN_PROGRESS) {
1606                         break;
1607                 }
1608
1609                 status = gensec_update(conn->gensec, mem_ctx,
1610                                        response->r.BindResponse.SASL.secblob,
1611                                        &output);
1612
1613                 destroy_ldap_message(response);
1614         }
1615
1616 done:
1617         if (mem_ctx)
1618                 talloc_destroy(mem_ctx);
1619
1620         return result;
1621 }
1622
1623 BOOL ldap_setup_connection(struct ldap_connection *conn,
1624                            const char *url, const char *userdn, const char *password)
1625 {
1626         int result;
1627
1628         if (!ldap_connect(conn, url)) {
1629                 return False;
1630         }
1631
1632         result = ldap_bind_simple(conn, userdn, password);
1633         if (result == LDAP_SUCCESS) {
1634                 return True;
1635         }
1636
1637         return False;
1638 }
1639
1640 BOOL ldap_setup_connection_with_sasl(struct ldap_connection *conn, const char *url, const char *username, const char *domain, const char *password)
1641 {
1642         int result;
1643
1644         if (!ldap_connect(conn, url)) {
1645                 return False;
1646         }
1647
1648         result = ldap_bind_sasl(conn, username, domain, password);
1649         if (result == LDAP_SUCCESS) {
1650                 return True;
1651         }
1652
1653         return False;
1654 }
1655
1656 static BOOL ldap_abandon_message(struct ldap_connection *conn, int msgid,
1657                                  const struct timeval *endtime)
1658 {
1659         struct ldap_message *msg = new_ldap_message();
1660         BOOL result;
1661
1662         if (msg == NULL)
1663                 return False;
1664
1665         msg->type = LDAP_TAG_AbandonRequest;
1666         msg->r.AbandonRequest.messageid = msgid;
1667
1668         result = ldap_send_msg(conn, msg, endtime);
1669         destroy_ldap_message(msg);
1670         return result;
1671 }
1672
1673 struct ldap_message *new_ldap_search_message(const char *base,
1674                                              enum ldap_scope scope,
1675                                              char *filter,
1676                                              int num_attributes,
1677                                              const char **attributes)
1678 {
1679         struct ldap_message *res = new_ldap_message();
1680
1681         if (res == NULL)
1682                 return NULL;
1683
1684         res->type = LDAP_TAG_SearchRequest;
1685         res->r.SearchRequest.basedn = base;
1686         res->r.SearchRequest.scope = scope;
1687         res->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
1688         res->r.SearchRequest.timelimit = 0;
1689         res->r.SearchRequest.sizelimit = 0;
1690         res->r.SearchRequest.attributesonly = False;
1691         res->r.SearchRequest.filter = filter;
1692         res->r.SearchRequest.num_attributes = num_attributes;
1693         res->r.SearchRequest.attributes = attributes;
1694         return res;
1695 }
1696
1697 struct ldap_message *new_ldap_simple_bind_msg(const char *dn, const char *pw)
1698 {
1699         struct ldap_message *res = new_ldap_message();
1700
1701         if (res == NULL)
1702                 return NULL;
1703
1704         res->type = LDAP_TAG_BindRequest;
1705         res->r.BindRequest.version = 3;
1706         res->r.BindRequest.dn = talloc_strdup(res->mem_ctx, dn);
1707         res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SIMPLE;
1708         res->r.BindRequest.creds.password = talloc_strdup(res->mem_ctx, pw);
1709         return res;
1710 }
1711
1712 struct ldap_message *new_ldap_sasl_bind_msg(const char *sasl_mechanism, DATA_BLOB *secblob)
1713 {
1714         struct ldap_message *res = new_ldap_message();
1715
1716         if (res == NULL)
1717                 return NULL;
1718
1719         res->type = LDAP_TAG_BindRequest;
1720         res->r.BindRequest.version = 3;
1721         res->r.BindRequest.dn = "";
1722         res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SASL;
1723         res->r.BindRequest.creds.SASL.mechanism = talloc_strdup(res->mem_ctx, sasl_mechanism);
1724         res->r.BindRequest.creds.SASL.secblob = *secblob;
1725         return res;
1726 }
1727
1728 BOOL ldap_setsearchent(struct ldap_connection *conn, struct ldap_message *msg,
1729                        const struct timeval *endtime)
1730 {
1731         if ((conn->searchid != 0) &&
1732             (!ldap_abandon_message(conn, conn->searchid, endtime)))
1733                 return False;
1734
1735         conn->searchid = conn->next_msgid;
1736         return ldap_send_msg(conn, msg, endtime);
1737 }
1738
1739 struct ldap_message *ldap_getsearchent(struct ldap_connection *conn,
1740                                        const struct timeval *endtime)
1741 {
1742         struct ldap_message *result;
1743
1744         if (conn->search_entries != NULL) {
1745                 struct ldap_queue_entry *e = conn->search_entries;
1746
1747                 result = e->msg;
1748                 DLIST_REMOVE(conn->search_entries, e);
1749                 SAFE_FREE(e);
1750                 return result;
1751         }
1752
1753         result = ldap_receive(conn, conn->searchid, endtime);
1754         if (!result) {
1755                 return NULL;
1756         }
1757
1758         if (result->type == LDAP_TAG_SearchResultEntry)
1759                 return result;
1760
1761         if (result->type == LDAP_TAG_SearchResultDone) {
1762                 /* TODO: Handle Paged Results */
1763                 destroy_ldap_message(result);
1764                 return NULL;
1765         }
1766
1767         /* TODO: Handle Search References here */
1768         return NULL;
1769 }
1770
1771 void ldap_endsearchent(struct ldap_connection *conn,
1772                        const struct timeval *endtime)
1773 {
1774         struct ldap_queue_entry *e;
1775
1776         e = conn->search_entries;
1777
1778         while (e != NULL) {
1779                 struct ldap_queue_entry *next = e->next;
1780                 DLIST_REMOVE(conn->search_entries, e);
1781                 SAFE_FREE(e);
1782                 e = next;
1783         }
1784 }
1785
1786 struct ldap_message *ldap_searchone(struct ldap_connection *conn,
1787                                     struct ldap_message *msg,
1788                                     const struct timeval *endtime)
1789 {
1790         struct ldap_message *res1, *res2 = NULL;
1791         if (!ldap_setsearchent(conn, msg, endtime))
1792                 return NULL;
1793
1794         res1 = ldap_getsearchent(conn, endtime);
1795
1796         if (res1 != NULL)
1797                 res2 = ldap_getsearchent(conn, endtime);
1798
1799         ldap_endsearchent(conn, endtime);
1800
1801         if (res1 == NULL)
1802                 return NULL;
1803
1804         if (res2 != NULL) {
1805                 /* More than one entry */
1806                 destroy_ldap_message(res1);
1807                 destroy_ldap_message(res2);
1808                 return NULL;
1809         }
1810
1811         return res1;
1812 }
1813
1814 BOOL ldap_find_single_value(struct ldap_message *msg, const char *attr,
1815                             DATA_BLOB *value)
1816 {
1817         int i;
1818         struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1819
1820         if (msg->type != LDAP_TAG_SearchResultEntry)
1821                 return False;
1822
1823         for (i=0; i<r->num_attributes; i++) {
1824                 if (strequal(attr, r->attributes[i].name)) {
1825                         if (r->attributes[i].num_values != 1)
1826                                 return False;
1827
1828                         *value = r->attributes[i].values[0];
1829                         return True;
1830                 }
1831         }
1832         return False;
1833 }
1834
1835 BOOL ldap_find_single_string(struct ldap_message *msg, const char *attr,
1836                              TALLOC_CTX *mem_ctx, char **value)
1837 {
1838         DATA_BLOB blob;
1839
1840         if (!ldap_find_single_value(msg, attr, &blob))
1841                 return False;
1842
1843         *value = talloc(mem_ctx, blob.length+1);
1844
1845         if (*value == NULL)
1846                 return False;
1847
1848         memcpy(*value, blob.data, blob.length);
1849         (*value)[blob.length] = '\0';
1850         return True;
1851 }
1852
1853 BOOL ldap_find_single_int(struct ldap_message *msg, const char *attr,
1854                           int *value)
1855 {
1856         DATA_BLOB blob;
1857         char *val;
1858         int errno_save;
1859         BOOL res;
1860
1861         if (!ldap_find_single_value(msg, attr, &blob))
1862                 return False;
1863
1864         val = malloc(blob.length+1);
1865         if (val == NULL)
1866                 return False;
1867
1868         memcpy(val, blob.data, blob.length);
1869         val[blob.length] = '\0';
1870
1871         errno_save = errno;
1872         errno = 0;
1873
1874         *value = strtol(val, NULL, 10);
1875
1876         res = (errno == 0);
1877
1878         free(val);
1879         errno = errno_save;
1880
1881         return res;
1882 }
1883
1884 int ldap_error(struct ldap_connection *conn)
1885 {
1886         return 0;
1887 }
1888
1889 NTSTATUS ldap2nterror(int ldaperror)
1890 {
1891         return NT_STATUS_OK;
1892 }