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