r2671: we're getting too many errors caused by the talloc_realloc() API not
[samba.git] / source4 / libcli / ldap / ldap.c
1 /* 
2    Unix SMB/CIFS mplementation.
3    LDAP protocol helper functions for SAMBA
4    
5    Copyright (C) Andrew Tridgell  2004
6    Copyright (C) Volker Lendecke 2004
7    Copyright (C) Stefan Metzmacher 2004
8    Copyright (C) Simo Sorce 2004
9     
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23    
24 */
25
26 #include "includes.h"
27
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,
593                                        strlen(r->value));
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.CompareResponse; */
600                 break;
601         }
602         case LDAP_TAG_AbandonRequest: {
603                 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
604                 asn1_push_tag(&data,
605                               ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest));
606                 asn1_write_implicit_Integer(&data, r->messageid);
607                 asn1_pop_tag(&data);
608                 break;
609         }
610         case LDAP_TAG_SearchResultReference: {
611 /*              struct ldap_SearchResRef *r = &msg->r.SearchResultReference; */
612                 break;
613         }
614         case LDAP_TAG_ExtendedRequest: {
615                 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
616                 asn1_push_tag(&data, ASN1_APPLICATION(LDAP_TAG_ExtendedRequest));
617                 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
618                 asn1_write(&data, r->oid, strlen(r->oid));
619                 asn1_pop_tag(&data);
620                 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(1));
621                 asn1_write(&data, r->value.data, r->value.length);
622                 asn1_pop_tag(&data);
623                 asn1_pop_tag(&data);
624                 break;
625         }
626         case LDAP_TAG_ExtendedResponse: {
627                 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
628                 ldap_encode_response(msg->type, &r->response, &data);
629                 break;
630         }
631         default:
632                 return False;
633         }
634
635         asn1_pop_tag(&data);
636         *result = data_blob(data.data, data.length);
637         asn1_free(&data);
638         return True;
639 }
640
641 static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
642                                       DATA_BLOB blob)
643 {
644         char *result = talloc(mem_ctx, blob.length+1);
645         memcpy(result, blob.data, blob.length);
646         result[blob.length] = '\0';
647         return result;
648 }
649
650 static BOOL asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
651                                          ASN1_DATA *data,
652                                          const char **result)
653 {
654         DATA_BLOB string;
655         if (!asn1_read_OctetString(data, &string))
656                 return False;
657         *result = blob2string_talloc(mem_ctx, string);
658         data_blob_free(&string);
659         return True;
660 }
661
662 static void ldap_decode_response(TALLOC_CTX *mem_ctx,
663                                  ASN1_DATA *data,
664                                  enum ldap_request_tag tag,
665                                  struct ldap_Result *result)
666 {
667         asn1_start_tag(data, ASN1_APPLICATION(tag));
668         asn1_read_enumerated(data, &result->resultcode);
669         asn1_read_OctetString_talloc(mem_ctx, data, &result->dn);
670         asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage);
671         if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
672                 asn1_start_tag(data, ASN1_CONTEXT(3));
673                 asn1_read_OctetString_talloc(mem_ctx, data, &result->referral);
674                 asn1_end_tag(data);
675         } else {
676                 result->referral = NULL;
677         }
678         asn1_end_tag(data);
679 }
680
681 static BOOL ldap_decode_filter(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
682                                char **filter)
683 {
684         uint8 filter_tag, tag_desc;
685
686         if (!asn1_peek_uint8(data, &filter_tag))
687                 return False;
688
689         tag_desc = filter_tag;
690         filter_tag &= 0x1f;     /* strip off the asn1 stuff */
691         tag_desc &= 0xe0;
692
693         switch(filter_tag) {
694         case 0: {
695                 /* AND of one or more filters */
696                 if (tag_desc != 0xa0) /* context compount */
697                         return False;
698
699                 asn1_start_tag(data, ASN1_CONTEXT(0));
700
701                 *filter = talloc_strdup(mem_ctx, "(&");
702                 if (*filter == NULL)
703                         return False;
704
705                 while (asn1_tag_remaining(data) > 0) {
706                         char *subfilter;
707                         if (!ldap_decode_filter(mem_ctx, data, &subfilter))
708                                 return False;
709                         *filter = talloc_asprintf(mem_ctx, "%s%s", *filter,
710                                                   subfilter);
711                         if (*filter == NULL)
712                                 return False;
713                 }
714                 asn1_end_tag(data);
715
716                 *filter = talloc_asprintf(mem_ctx, "%s)", *filter);
717                 break;
718         }
719         case 1: {
720                 /* OR of one or more filters */
721                 if (tag_desc != 0xa0) /* context compount */
722                         return False;
723
724                 asn1_start_tag(data, ASN1_CONTEXT(1));
725
726                 *filter = talloc_strdup(mem_ctx, "(|");
727                 if (*filter == NULL)
728                         return False;
729
730                 while (asn1_tag_remaining(data) > 0) {
731                         char *subfilter;
732                         if (!ldap_decode_filter(mem_ctx, data, &subfilter))
733                                 return False;
734                         *filter = talloc_asprintf(mem_ctx, "%s%s", *filter,
735                                                   subfilter);
736                         if (*filter == NULL)
737                                 return False;
738                 }
739
740                 asn1_end_tag(data);
741
742                 *filter = talloc_asprintf(mem_ctx, "%s)", *filter);
743                 break;
744         }
745         case 3: {
746                 /* equalityMatch */
747                 const char *attrib, *value;
748                 if (tag_desc != 0xa0) /* context compound */
749                         return False;
750                 asn1_start_tag(data, ASN1_CONTEXT(3));
751                 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
752                 asn1_read_OctetString_talloc(mem_ctx, data, &value);
753                 asn1_end_tag(data);
754                 if ((data->has_error) || (attrib == NULL) || (value == NULL))
755                         return False;
756                 *filter = talloc_asprintf(mem_ctx, "(%s=%s)", attrib, value);
757                 break;
758         }
759         case 7: {
760                 /* Normal presence, "attribute=*" */
761                 int attr_len;
762                 char *attr_name;
763                 if (tag_desc != 0x80) /* context simple */
764                         return False;
765                 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(7)))
766                         return False;
767                 attr_len = asn1_tag_remaining(data);
768                 attr_name = malloc(attr_len+1);
769                 if (attr_name == NULL)
770                         return False;
771                 asn1_read(data, attr_name, attr_len);
772                 attr_name[attr_len] = '\0';
773                 *filter = talloc_asprintf(mem_ctx, "(%s=*)", attr_name);
774                 SAFE_FREE(attr_name);
775                 asn1_end_tag(data);
776                 break;
777         }
778         default:
779                 return False;
780         }
781         if (*filter == NULL)
782                 return False;
783         return True;
784 }
785
786 static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
787                                struct ldap_attribute *attrib)
788 {
789         asn1_start_tag(data, ASN1_SEQUENCE(0));
790         asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name);
791         asn1_start_tag(data, ASN1_SET);
792         while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
793                 DATA_BLOB blob;
794                 struct ldap_val value;
795                 asn1_read_OctetString(data, &blob);
796                 value.data = blob.data;
797                 value.length = blob.length;
798                 add_value_to_attrib(mem_ctx, &value, attrib);
799                 data_blob_free(&blob);
800         }
801         asn1_end_tag(data);
802         asn1_end_tag(data);
803         
804 }
805
806 static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
807                                 struct ldap_attribute **attributes,
808                                 int *num_attributes)
809 {
810         asn1_start_tag(data, ASN1_SEQUENCE(0));
811         while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
812                 struct ldap_attribute attrib;
813                 ZERO_STRUCT(attrib);
814                 ldap_decode_attrib(mem_ctx, data, &attrib);
815                 add_attrib_to_array_talloc(mem_ctx, &attrib,
816                                            attributes, num_attributes);
817         }
818         asn1_end_tag(data);
819 }
820
821 BOOL ldap_decode(ASN1_DATA *data, struct ldap_message *msg)
822 {
823         uint8 tag;
824
825         asn1_start_tag(data, ASN1_SEQUENCE(0));
826         asn1_read_Integer(data, &msg->messageid);
827
828         if (!asn1_peek_uint8(data, &tag))
829                 return False;
830
831         switch(tag) {
832
833         case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
834                 struct ldap_BindRequest *r = &msg->r.BindRequest;
835                 msg->type = LDAP_TAG_BindRequest;
836                 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_BindRequest));
837                 asn1_read_Integer(data, &r->version);
838                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
839                 if (asn1_peek_tag(data, 0x80)) {
840                         int pwlen;
841                         r->creds.password = "";
842                         /* Mechanism 0 (SIMPLE) */
843                         asn1_start_tag(data, 0x80);
844                         pwlen = asn1_tag_remaining(data);
845                         if (pwlen != 0) {
846                                 char *pw = talloc(msg->mem_ctx, pwlen+1);
847                                 asn1_read(data, pw, pwlen);
848                                 pw[pwlen] = '\0';
849                                 r->creds.password = pw;
850                         }
851                         asn1_end_tag(data);
852                 }
853                 asn1_end_tag(data);
854                 break;
855         }
856
857         case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
858                 struct ldap_BindResponse *r = &msg->r.BindResponse;
859                 msg->type = LDAP_TAG_BindResponse;
860                 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_BindResponse));
861                 asn1_read_enumerated(data, &r->response.resultcode);
862                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->response.dn);
863                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->response.errormessage);
864                 if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
865                         asn1_start_tag(data, ASN1_CONTEXT(3));
866                         asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->response.referral);
867                         asn1_end_tag(data);
868                 } else {
869                         r->response.referral = NULL;
870                 }
871                 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
872                         DATA_BLOB tmp_blob = data_blob(NULL, 0);
873                         asn1_read_ContextSimple(data, 7, &tmp_blob);
874                         r->SASL.secblob = data_blob_talloc(msg->mem_ctx, tmp_blob.data, tmp_blob.length);
875                         data_blob_free(&tmp_blob);
876                 } else {
877                         r->SASL.secblob = data_blob(NULL, 0);
878                 }
879                 asn1_end_tag(data);
880                 break;
881         }
882
883         case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
884                 msg->type = LDAP_TAG_UnbindRequest;
885                 asn1_start_tag(data, ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest));
886                 asn1_end_tag(data);
887                 break;
888         }
889
890         case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
891                 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
892                 msg->type = LDAP_TAG_SearchRequest;
893                 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_SearchRequest));
894                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->basedn);
895                 asn1_read_enumerated(data, (int *)&(r->scope));
896                 asn1_read_enumerated(data, (int *)&(r->deref));
897                 asn1_read_Integer(data, &r->sizelimit);
898                 asn1_read_Integer(data, &r->timelimit);
899                 asn1_read_BOOLEAN(data, &r->attributesonly);
900
901                 /* Maybe create a TALLOC_CTX for the filter? This can waste
902                  * quite a bit of memory recursing down. */
903                 ldap_decode_filter(msg->mem_ctx, data, &r->filter);
904
905                 asn1_start_tag(data, ASN1_SEQUENCE(0));
906
907                 r->num_attributes = 0;
908                 r->attributes = NULL;
909
910                 while (asn1_tag_remaining(data) > 0) {
911                         const char *attr;
912                         if (!asn1_read_OctetString_talloc(msg->mem_ctx, data,
913                                                           &attr))
914                                 return False;
915                         if (!add_string_to_array(msg->mem_ctx, attr,
916                                                  &r->attributes,
917                                                  &r->num_attributes))
918                                 return False;
919                 }
920
921                 asn1_end_tag(data);
922                 asn1_end_tag(data);
923                 break;
924         }
925
926         case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
927                 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
928                 msg->type = LDAP_TAG_SearchResultEntry;
929                 r->attributes = NULL;
930                 r->num_attributes = 0;
931                 asn1_start_tag(data,
932                                ASN1_APPLICATION(LDAP_TAG_SearchResultEntry));
933                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
934                 ldap_decode_attribs(msg->mem_ctx, data, &r->attributes,
935                                     &r->num_attributes);
936                 asn1_end_tag(data);
937                 break;
938         }
939
940         case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
941                 struct ldap_Result *r = &msg->r.SearchResultDone;
942                 msg->type = LDAP_TAG_SearchResultDone;
943                 ldap_decode_response(msg->mem_ctx, data,
944                                      LDAP_TAG_SearchResultDone, r);
945                 break;
946         }
947
948         case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
949 /*              struct ldap_SearchResRef *r = &msg->r.SearchResultReference; */
950                 msg->type = LDAP_TAG_SearchResultReference;
951                 break;
952         }
953
954         case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
955                 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
956                 msg->type = LDAP_TAG_ModifyRequest;
957                 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
958                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
959                 asn1_start_tag(data, ASN1_SEQUENCE(0));
960
961                 r->num_mods = 0;
962                 r->mods = NULL;
963
964                 while (asn1_tag_remaining(data) > 0) {
965                         struct ldap_mod mod;
966                         ZERO_STRUCT(mod);
967                         asn1_start_tag(data, ASN1_SEQUENCE(0));
968                         asn1_read_enumerated(data, &mod.type);
969                         ldap_decode_attrib(msg->mem_ctx, data, &mod.attrib);
970                         asn1_end_tag(data);
971                         if (!add_mod_to_array_talloc(msg->mem_ctx, &mod,
972                                                      &r->mods, &r->num_mods))
973                                 break;
974                 }
975
976                 asn1_end_tag(data);
977                 asn1_end_tag(data);
978                 break;
979         }
980
981         case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
982                 struct ldap_Result *r = &msg->r.ModifyResponse;
983                 msg->type = LDAP_TAG_ModifyResponse;
984                 ldap_decode_response(msg->mem_ctx, data,
985                                      LDAP_TAG_ModifyResponse, r);
986                 break;
987         }
988
989         case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
990                 struct ldap_AddRequest *r = &msg->r.AddRequest;
991                 msg->type = LDAP_TAG_AddRequest;
992                 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_AddRequest));
993                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
994
995                 r->attributes = NULL;
996                 r->num_attributes = 0;
997                 ldap_decode_attribs(msg->mem_ctx, data, &r->attributes,
998                                     &r->num_attributes);
999
1000                 asn1_end_tag(data);
1001                 break;
1002         }
1003
1004         case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1005                 struct ldap_Result *r = &msg->r.AddResponse;
1006                 msg->type = LDAP_TAG_AddResponse;
1007                 ldap_decode_response(msg->mem_ctx, data,
1008                                      LDAP_TAG_AddResponse, r);
1009                 break;
1010         }
1011
1012         case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1013                 struct ldap_DelRequest *r = &msg->r.DelRequest;
1014                 int len;
1015                 char *dn;
1016                 msg->type = LDAP_TAG_DelRequest;
1017                 asn1_start_tag(data,
1018                                ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
1019                 len = asn1_tag_remaining(data);
1020                 dn = talloc(msg->mem_ctx, len+1);
1021                 if (dn == NULL)
1022                         break;
1023                 asn1_read(data, dn, len);
1024                 dn[len] = '\0';
1025                 r->dn = dn;
1026                 asn1_end_tag(data);
1027                 break;
1028         }
1029
1030         case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1031                 struct ldap_Result *r = &msg->r.DelResponse;
1032                 msg->type = LDAP_TAG_DelResponse;
1033                 ldap_decode_response(msg->mem_ctx, data,
1034                                      LDAP_TAG_DelResponse, r);
1035                 break;
1036         }
1037
1038         case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1039                 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1040                 msg->type = LDAP_TAG_ModifyDNRequest;
1041                 asn1_start_tag(data,
1042                                ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
1043                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
1044                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->newrdn);
1045                 asn1_read_BOOLEAN(data, &r->deleteolddn);
1046                 r->newsuperior = NULL;
1047                 if (asn1_tag_remaining(data) > 0) {
1048                         int len;
1049                         char *newsup;
1050                         asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1051                         len = asn1_tag_remaining(data);
1052                         newsup = talloc(msg->mem_ctx, len+1);
1053                         if (newsup == NULL)
1054                                 break;
1055                         asn1_read(data, newsup, len);
1056                         newsup[len] = '\0';
1057                         r->newsuperior = newsup;
1058                         asn1_end_tag(data);
1059                 }
1060                 asn1_end_tag(data);
1061                 break;
1062         }
1063
1064         case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1065                 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1066                 msg->type = LDAP_TAG_ModifyDNResponse;
1067                 ldap_decode_response(msg->mem_ctx, data,
1068                                      LDAP_TAG_ModifyDNResponse, r);
1069                 break;
1070         }
1071
1072         case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1073 /*              struct ldap_CompareRequest *r = &msg->r.CompareRequest; */
1074                 msg->type = LDAP_TAG_CompareRequest;
1075                 break;
1076         }
1077
1078         case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1079                 struct ldap_Result *r = &msg->r.CompareResponse;
1080                 msg->type = LDAP_TAG_CompareResponse;
1081                 ldap_decode_response(msg->mem_ctx, data,
1082                                      LDAP_TAG_CompareResponse, r);
1083                 break;
1084         }
1085
1086         case ASN1_APPLICATION(LDAP_TAG_AbandonRequest): {
1087 /*              struct ldap_AbandonRequest *r = &msg->r.AbandonRequest; */
1088                 msg->type = LDAP_TAG_AbandonRequest;
1089                 break;
1090         }
1091
1092         case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1093                 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1094                 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1095
1096                 msg->type = LDAP_TAG_ExtendedRequest;
1097                 asn1_start_tag(data,ASN1_APPLICATION(LDAP_TAG_ExtendedRequest));
1098                 if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
1099                         return False;
1100                 }
1101                 r->oid = blob2string_talloc(msg->mem_ctx, tmp_blob);
1102                 data_blob_free(&tmp_blob);
1103                 if (!r->oid) {
1104                         return False;
1105                 }
1106
1107                 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1108                         asn1_read_ContextSimple(data, 1, &tmp_blob);
1109                         r->value = data_blob_talloc(msg->mem_ctx, tmp_blob.data, tmp_blob.length);
1110                         data_blob_free(&tmp_blob);
1111                 } else {
1112                         r->value = data_blob(NULL, 0);
1113                 }
1114
1115                 asn1_end_tag(data);
1116                 break;
1117         }
1118
1119         case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1120                 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1121                 msg->type = LDAP_TAG_ExtendedResponse;
1122                 ldap_decode_response(msg->mem_ctx, data,
1123                                      LDAP_TAG_ExtendedResponse, &r->response);
1124                 /* I have to come across an operation that actually sends
1125                  * something back to really see what's going on. The currently
1126                  * needed pwdchange does not send anything back. */
1127                 r->name = NULL;
1128                 r->value.data = NULL;
1129                 r->value.length = 0;
1130                 break;
1131         }
1132         default: 
1133                 return False;
1134         }
1135
1136         asn1_end_tag(data);
1137         return ((!data->has_error) && (data->nesting == NULL));
1138 }
1139
1140 BOOL ldap_parse_basic_url(TALLOC_CTX *mem_ctx, const char *url,
1141                           char **host, uint16 *port, BOOL *ldaps)
1142 {
1143         int tmp_port = 0;
1144         fstring protocol;
1145         fstring tmp_host;
1146         const char *p = url;
1147
1148         /* skip leading "URL:" (if any) */
1149         if (strncasecmp( p, "URL:", 4) == 0) {
1150                 p += 4;
1151         }
1152
1153         /* Paranoia check */
1154         SMB_ASSERT(sizeof(protocol)>10 && sizeof(tmp_host)>254);
1155                 
1156         sscanf(p, "%10[^:]://%254[^:/]:%d", protocol, tmp_host, &tmp_port);
1157
1158         if (strequal(protocol, "ldap")) {
1159                 *port = 389;
1160                 *ldaps = False;
1161         } else if (strequal(protocol, "ldaps")) {
1162                 *port = 636;
1163                 *ldaps = True;
1164         } else {
1165                 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
1166                 return False;
1167         }
1168
1169         if (tmp_port != 0)
1170                 *port = tmp_port;
1171         
1172         *host = talloc_strdup(mem_ctx, tmp_host);
1173
1174         return (*host != NULL);
1175 }
1176
1177 struct ldap_connection *new_ldap_connection(void)
1178 {
1179         TALLOC_CTX *mem_ctx = talloc_init("ldap_connection");
1180         struct ldap_connection *result;
1181
1182         if (mem_ctx == NULL)
1183                 return NULL;
1184
1185         result = talloc(mem_ctx, sizeof(*result));
1186
1187         if (result == NULL)
1188                 return NULL;
1189
1190         result->mem_ctx = mem_ctx;
1191         result->next_msgid = 1;
1192         result->outstanding = NULL;
1193         result->searchid = 0;
1194         result->search_entries = NULL;
1195         result->auth_dn = NULL;
1196         result->simple_pw = NULL;
1197         result->gensec = NULL;
1198
1199         return result;
1200 }
1201
1202 BOOL ldap_connect(struct ldap_connection *conn, const char *url)
1203 {
1204         struct hostent *hp;
1205         struct in_addr ip;
1206
1207         if (!ldap_parse_basic_url(conn->mem_ctx, url, &conn->host,
1208                                   &conn->port, &conn->ldaps))
1209                 return False;
1210
1211         hp = sys_gethostbyname(conn->host);
1212
1213         if ((hp == NULL) || (hp->h_addr == NULL))
1214                 return False;
1215
1216         putip((char *)&ip, (char *)hp->h_addr);
1217
1218         conn->sock = open_socket_out(SOCK_STREAM, &ip, conn->port, LDAP_CONNECTION_TIMEOUT);
1219
1220         return (conn->sock >= 0);
1221 }
1222
1223 BOOL ldap_set_simple_creds(struct ldap_connection *conn,
1224                            const char *dn, const char *password)
1225 {
1226         conn->auth_dn = talloc_strdup(conn->mem_ctx, dn);
1227         conn->simple_pw = talloc_strdup(conn->mem_ctx, password);
1228
1229         return ((conn->auth_dn != NULL) && (conn->simple_pw != NULL));
1230 }
1231
1232 struct ldap_message *new_ldap_message(void)
1233 {
1234         TALLOC_CTX *mem_ctx = talloc_init("ldap_message");
1235         struct ldap_message *result;
1236
1237         if (mem_ctx == NULL)
1238                 return NULL;
1239
1240         result = talloc(mem_ctx, sizeof(*result));
1241
1242         if (result == NULL)
1243                 return NULL;
1244
1245         result->mem_ctx = mem_ctx;
1246         return result;
1247 }
1248
1249 void destroy_ldap_message(struct ldap_message *msg)
1250 {
1251         if (msg != NULL)
1252                 talloc_destroy(msg->mem_ctx);
1253 }
1254
1255 BOOL ldap_send_msg(struct ldap_connection *conn, struct ldap_message *msg,
1256                    const struct timeval *endtime)
1257 {
1258         DATA_BLOB request;
1259         BOOL result;
1260         struct ldap_queue_entry *entry;
1261
1262         msg->messageid = conn->next_msgid++;
1263
1264         if (!ldap_encode(msg, &request))
1265                 return False;
1266
1267         result = (write_data_until(conn->sock, request.data, request.length,
1268                                    endtime) == request.length);
1269
1270         data_blob_free(&request);
1271
1272         if (!result)
1273                 return result;
1274
1275         /* abandon and unbind don't expect results */
1276
1277         if ((msg->type == LDAP_TAG_AbandonRequest) ||
1278             (msg->type == LDAP_TAG_UnbindRequest))
1279                 return True;
1280
1281         entry = malloc(sizeof(*entry)); 
1282
1283         if (entry == NULL)
1284                 return False;
1285
1286         entry->msgid = msg->messageid;
1287         entry->msg = NULL;
1288         DLIST_ADD(conn->outstanding, entry);
1289
1290         return True;
1291 }
1292
1293 BOOL ldap_receive_msg(struct ldap_connection *conn, struct ldap_message *msg,
1294                       const struct timeval *endtime)
1295 {
1296         struct asn1_data data;
1297         BOOL result;
1298
1299         if (!asn1_read_sequence_until(conn->sock, &data, endtime))
1300                 return False;
1301
1302         result = ldap_decode(&data, msg);
1303
1304         asn1_free(&data);
1305         return result;
1306 }
1307
1308 static struct ldap_message *recv_from_queue(struct ldap_connection *conn,
1309                                             int msgid)
1310 {
1311         struct ldap_queue_entry *e;
1312
1313         for (e = conn->outstanding; e != NULL; e = e->next) {
1314
1315                 if (e->msgid == msgid) {
1316                         struct ldap_message *result = e->msg;
1317                         DLIST_REMOVE(conn->outstanding, e);
1318                         SAFE_FREE(e);
1319                         return result;
1320                 }
1321         }
1322
1323         return NULL;
1324 }
1325
1326 static void add_search_entry(struct ldap_connection *conn,
1327                              struct ldap_message *msg)
1328 {
1329         struct ldap_queue_entry *e = malloc(sizeof *e);
1330
1331         if (e == NULL)
1332                 return;
1333
1334         e->msg = msg;
1335         DLIST_ADD_END(conn->search_entries, e, struct ldap_queue_entry *);
1336         return;
1337 }
1338
1339 static void fill_outstanding_request(struct ldap_connection *conn,
1340                                      struct ldap_message *msg)
1341 {
1342         struct ldap_queue_entry *e;
1343
1344         for (e = conn->outstanding; e != NULL; e = e->next) {
1345                 if (e->msgid == msg->messageid) {
1346                         e->msg = msg;
1347                         return;
1348                 }
1349         }
1350
1351         /* This reply has not been expected, destroy the incoming msg */
1352         destroy_ldap_message(msg);
1353         return;
1354 }
1355
1356 struct ldap_message *ldap_receive(struct ldap_connection *conn, int msgid,
1357                                   const struct timeval *endtime)
1358 {
1359         struct ldap_message *result = recv_from_queue(conn, msgid);
1360
1361         if (result != NULL)
1362                 return result;
1363
1364         while (True) {
1365                 struct asn1_data data;
1366                 BOOL res;
1367
1368                 result = new_ldap_message();
1369
1370                 if (!asn1_read_sequence_until(conn->sock, &data, endtime))
1371                         return NULL;
1372
1373                 res = ldap_decode(&data, result);
1374                 asn1_free(&data);
1375
1376                 if (!res)
1377                         return NULL;
1378
1379                 if (result->messageid == msgid)
1380                         return result;
1381
1382                 if (result->type == LDAP_TAG_SearchResultEntry) {
1383                         add_search_entry(conn, result);
1384                 } else {
1385                         fill_outstanding_request(conn, result);
1386                 }
1387         }
1388
1389         return NULL;
1390 }
1391
1392 struct ldap_message *ldap_transaction(struct ldap_connection *conn,
1393                                       struct ldap_message *request)
1394 {
1395         if (!ldap_send_msg(conn, request, NULL))
1396                 return False;
1397
1398         return ldap_receive(conn, request->messageid, NULL);
1399 }
1400
1401 int ldap_bind_simple(struct ldap_connection *conn, const char *userdn, const char *password)
1402 {
1403         struct ldap_message *response;
1404         struct ldap_message *msg;
1405         const char *dn, *pw;
1406         int result = LDAP_OTHER;
1407
1408         if (conn == NULL)
1409                 return result;
1410
1411         if (userdn) {
1412                 dn = userdn;
1413         } else {
1414                 if (conn->auth_dn) {
1415                         dn = conn->auth_dn;
1416                 } else {
1417                         dn = "";
1418                 }
1419         }
1420
1421         if (password) {
1422                 pw = password;
1423         } else {
1424                 if (conn->simple_pw) {
1425                         pw = conn->simple_pw;
1426                 } else {
1427                         pw = "";
1428                 }
1429         }
1430
1431         msg =  new_ldap_simple_bind_msg(dn, pw);
1432         if (!msg)
1433                 return result;
1434
1435         response = ldap_transaction(conn, msg);
1436         if (!response) {
1437                 destroy_ldap_message(msg);
1438                 return result;
1439         }
1440                 
1441         result = response->r.BindResponse.response.resultcode;
1442
1443         destroy_ldap_message(msg);
1444         destroy_ldap_message(response);
1445
1446         return result;
1447 }
1448
1449 int ldap_bind_sasl(struct ldap_connection *conn, const char *username, const char *domain, const char *password)
1450 {
1451         NTSTATUS status;
1452         TALLOC_CTX *mem_ctx = NULL;
1453         struct ldap_message *response;
1454         struct ldap_message *msg;
1455         DATA_BLOB input = data_blob(NULL, 0);
1456         DATA_BLOB output = data_blob(NULL, 0);
1457         int result = LDAP_OTHER;
1458
1459         if (conn == NULL)
1460                 return result;
1461
1462         status = gensec_client_start(conn, &conn->gensec);
1463         if (!NT_STATUS_IS_OK(status)) {
1464                 DEBUG(0, ("Failed to start GENSEC engine (%s)\n", nt_errstr(status)));
1465                 return result;
1466         }
1467
1468         status = gensec_set_domain(conn->gensec, domain);
1469         if (!NT_STATUS_IS_OK(status)) {
1470                 DEBUG(1, ("Failed to start set GENSEC client domain to %s: %s\n", 
1471                           domain, nt_errstr(status)));
1472                 goto done;
1473         }
1474
1475         status = gensec_set_username(conn->gensec, username);
1476         if (!NT_STATUS_IS_OK(status)) {
1477                 DEBUG(1, ("Failed to start set GENSEC client username to %s: %s\n", 
1478                           username, nt_errstr(status)));
1479                 goto done;
1480         }
1481
1482         status = gensec_set_password(conn->gensec, password);
1483         if (!NT_STATUS_IS_OK(status)) {
1484                 DEBUG(1, ("Failed to start set GENSEC client password: %s\n", 
1485                           nt_errstr(status)));
1486                 goto done;
1487         }
1488
1489         status = gensec_set_target_hostname(conn->gensec, conn->host);
1490         if (!NT_STATUS_IS_OK(status)) {
1491                 DEBUG(1, ("Failed to start set GENSEC target hostname: %s\n", 
1492                           nt_errstr(status)));
1493                 goto done;
1494         }
1495
1496         status = gensec_start_mech_by_sasl_name(conn->gensec, "GSS-SPNEGO");
1497         if (!NT_STATUS_IS_OK(status)) {
1498                 DEBUG(1, ("Failed to start set GENSEC client SPNEGO mechanism: %s\n",
1499                           nt_errstr(status)));
1500                 goto done;
1501         }
1502
1503         mem_ctx = talloc_init("ldap_bind_sasl");
1504         if (!mem_ctx)
1505                 goto done;
1506
1507         status = gensec_update(conn->gensec, mem_ctx,
1508                                input,
1509                                &output);
1510
1511         while(1) {
1512                 if (NT_STATUS_IS_OK(status) && output.length == 0) {
1513                         break;
1514                 }
1515                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
1516                         break;
1517                 }
1518
1519                 msg =  new_ldap_sasl_bind_msg("GSS-SPNEGO", &output);
1520                 if (!msg)
1521                         goto done;
1522
1523                 response = ldap_transaction(conn, msg);
1524                 destroy_ldap_message(msg);
1525
1526                 if (!response) {
1527                         goto done;
1528                 }
1529
1530                 result = response->r.BindResponse.response.resultcode;
1531
1532                 if (result != LDAP_SUCCESS && result != LDAP_SASL_BIND_IN_PROGRESS) {
1533                         break;
1534                 }
1535
1536                 status = gensec_update(conn->gensec, mem_ctx,
1537                                        response->r.BindResponse.SASL.secblob,
1538                                        &output);
1539
1540                 destroy_ldap_message(response);
1541         }
1542
1543 done:
1544         if (conn->gensec)
1545                 gensec_end(&conn->gensec);
1546         if (mem_ctx)
1547                 talloc_destroy(mem_ctx);
1548
1549         return result;
1550 }
1551
1552 BOOL ldap_setup_connection(struct ldap_connection *conn,
1553                            const char *url, const char *userdn, const char *password)
1554 {
1555         int result;
1556
1557         if (!ldap_connect(conn, url)) {
1558                 return False;
1559         }
1560
1561         result = ldap_bind_simple(conn, userdn, password);
1562         if (result == LDAP_SUCCESS) {
1563                 return True;
1564         }
1565
1566         return False;
1567 }
1568
1569 BOOL ldap_setup_connection_with_sasl(struct ldap_connection *conn, const char *url, const char *username, const char *domain, const char *password)
1570 {
1571         int result;
1572
1573         if (!ldap_connect(conn, url)) {
1574                 return False;
1575         }
1576
1577         result = ldap_bind_sasl(conn, username, domain, password);
1578         if (result == LDAP_SUCCESS) {
1579                 return True;
1580         }
1581
1582         return False;
1583 }
1584
1585 static BOOL ldap_abandon_message(struct ldap_connection *conn, int msgid,
1586                                  const struct timeval *endtime)
1587 {
1588         struct ldap_message *msg = new_ldap_message();
1589         BOOL result;
1590
1591         if (msg == NULL)
1592                 return False;
1593
1594         msg->type = LDAP_TAG_AbandonRequest;
1595         msg->r.AbandonRequest.messageid = msgid;
1596
1597         result = ldap_send_msg(conn, msg, endtime);
1598         destroy_ldap_message(msg);
1599         return result;
1600 }
1601
1602 struct ldap_message *new_ldap_search_message(const char *base,
1603                                              enum ldap_scope scope,
1604                                              char *filter,
1605                                              int num_attributes,
1606                                              const char **attributes)
1607 {
1608         struct ldap_message *res = new_ldap_message();
1609
1610         if (res == NULL)
1611                 return NULL;
1612
1613         res->type = LDAP_TAG_SearchRequest;
1614         res->r.SearchRequest.basedn = base;
1615         res->r.SearchRequest.scope = scope;
1616         res->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
1617         res->r.SearchRequest.timelimit = 0;
1618         res->r.SearchRequest.sizelimit = 0;
1619         res->r.SearchRequest.attributesonly = False;
1620         res->r.SearchRequest.filter = filter;
1621         res->r.SearchRequest.num_attributes = num_attributes;
1622         res->r.SearchRequest.attributes = attributes;
1623         return res;
1624 }
1625
1626 struct ldap_message *new_ldap_simple_bind_msg(const char *dn, const char *pw)
1627 {
1628         struct ldap_message *res = new_ldap_message();
1629
1630         if (res == NULL)
1631                 return NULL;
1632
1633         res->type = LDAP_TAG_BindRequest;
1634         res->r.BindRequest.version = 3;
1635         res->r.BindRequest.dn = talloc_strdup(res->mem_ctx, dn);
1636         res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SIMPLE;
1637         res->r.BindRequest.creds.password = talloc_strdup(res->mem_ctx, pw);
1638         return res;
1639 }
1640
1641 struct ldap_message *new_ldap_sasl_bind_msg(const char *sasl_mechanism, DATA_BLOB *secblob)
1642 {
1643         struct ldap_message *res = new_ldap_message();
1644
1645         if (res == NULL)
1646                 return NULL;
1647
1648         res->type = LDAP_TAG_BindRequest;
1649         res->r.BindRequest.version = 3;
1650         res->r.BindRequest.dn = "";
1651         res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SASL;
1652         res->r.BindRequest.creds.SASL.mechanism = talloc_strdup(res->mem_ctx, sasl_mechanism);
1653         res->r.BindRequest.creds.SASL.secblob = *secblob;
1654         return res;
1655 }
1656
1657 BOOL ldap_setsearchent(struct ldap_connection *conn, struct ldap_message *msg,
1658                        const struct timeval *endtime)
1659 {
1660         if ((conn->searchid != 0) &&
1661             (!ldap_abandon_message(conn, conn->searchid, endtime)))
1662                 return False;
1663
1664         conn->searchid = conn->next_msgid;
1665         return ldap_send_msg(conn, msg, endtime);
1666 }
1667
1668 struct ldap_message *ldap_getsearchent(struct ldap_connection *conn,
1669                                        const struct timeval *endtime)
1670 {
1671         struct ldap_message *result;
1672
1673         if (conn->search_entries != NULL) {
1674                 struct ldap_queue_entry *e = conn->search_entries;
1675
1676                 result = e->msg;
1677                 DLIST_REMOVE(conn->search_entries, e);
1678                 SAFE_FREE(e);
1679                 return result;
1680         }
1681
1682         result = ldap_receive(conn, conn->searchid, endtime);
1683
1684         if (result->type == LDAP_TAG_SearchResultEntry)
1685                 return result;
1686
1687         if (result->type == LDAP_TAG_SearchResultDone) {
1688                 /* TODO: Handle Paged Results */
1689                 destroy_ldap_message(result);
1690                 return NULL;
1691         }
1692
1693         /* TODO: Handle Search References here */
1694         return NULL;
1695 }
1696
1697 void ldap_endsearchent(struct ldap_connection *conn,
1698                        const struct timeval *endtime)
1699 {
1700         struct ldap_queue_entry *e;
1701
1702         e = conn->search_entries;
1703
1704         while (e != NULL) {
1705                 struct ldap_queue_entry *next = e->next;
1706                 DLIST_REMOVE(conn->search_entries, e);
1707                 SAFE_FREE(e);
1708                 e = next;
1709         }
1710 }
1711
1712 struct ldap_message *ldap_searchone(struct ldap_connection *conn,
1713                                     struct ldap_message *msg,
1714                                     const struct timeval *endtime)
1715 {
1716         struct ldap_message *res1, *res2 = NULL;
1717         if (!ldap_setsearchent(conn, msg, endtime))
1718                 return NULL;
1719
1720         res1 = ldap_getsearchent(conn, endtime);
1721
1722         if (res1 != NULL)
1723                 res2 = ldap_getsearchent(conn, endtime);
1724
1725         ldap_endsearchent(conn, endtime);
1726
1727         if (res1 == NULL)
1728                 return NULL;
1729
1730         if (res2 != NULL) {
1731                 /* More than one entry */
1732                 destroy_ldap_message(res1);
1733                 destroy_ldap_message(res2);
1734                 return NULL;
1735         }
1736
1737         return res1;
1738 }
1739
1740 BOOL ldap_find_single_value(struct ldap_message *msg, const char *attr,
1741                             DATA_BLOB *value)
1742 {
1743         int i;
1744         struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1745
1746         if (msg->type != LDAP_TAG_SearchResultEntry)
1747                 return False;
1748
1749         for (i=0; i<r->num_attributes; i++) {
1750                 if (strequal(attr, r->attributes[i].name)) {
1751                         if (r->attributes[i].num_values != 1)
1752                                 return False;
1753
1754                         *value = r->attributes[i].values[0];
1755                         return True;
1756                 }
1757         }
1758         return False;
1759 }
1760
1761 BOOL ldap_find_single_string(struct ldap_message *msg, const char *attr,
1762                              TALLOC_CTX *mem_ctx, char **value)
1763 {
1764         DATA_BLOB blob;
1765
1766         if (!ldap_find_single_value(msg, attr, &blob))
1767                 return False;
1768
1769         *value = talloc(mem_ctx, blob.length+1);
1770
1771         if (*value == NULL)
1772                 return False;
1773
1774         memcpy(*value, blob.data, blob.length);
1775         (*value)[blob.length] = '\0';
1776         return True;
1777 }
1778
1779 BOOL ldap_find_single_int(struct ldap_message *msg, const char *attr,
1780                           int *value)
1781 {
1782         DATA_BLOB blob;
1783         char *val;
1784         int errno_save;
1785         BOOL res;
1786
1787         if (!ldap_find_single_value(msg, attr, &blob))
1788                 return False;
1789
1790         val = malloc(blob.length+1);
1791         if (val == NULL)
1792                 return False;
1793
1794         memcpy(val, blob.data, blob.length);
1795         val[blob.length] = '\0';
1796
1797         errno_save = errno;
1798         errno = 0;
1799
1800         *value = strtol(val, NULL, 10);
1801
1802         res = (errno == 0);
1803
1804         free(val);
1805         errno = errno_save;
1806
1807         return res;
1808 }
1809
1810 int ldap_error(struct ldap_connection *conn)
1811 {
1812         return 0;
1813 }
1814
1815 NTSTATUS ldap2nterror(int ldaperror)
1816 {
1817         return NT_STATUS_OK;
1818 }