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