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