r6817: - fixed empty ldap search elements in filters
[jelmer/samba4-debian.git] / source / libcli / ldap / ldap.c
1 /* 
2    Unix SMB/CIFS mplementation.
3    LDAP protocol helper functions for SAMBA
4    
5    Copyright (C) Andrew Tridgell  2004
6    Copyright (C) Volker Lendecke 2004
7    Copyright (C) Stefan Metzmacher 2004
8    Copyright (C) Simo Sorce 2004
9     
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23    
24 */
25
26 #include "includes.h"
27 #include "system/iconv.h"
28 #include "asn_1.h"
29 #include "libcli/ldap/ldap.h"
30
31 /****************************************************************************
32  *
33  * LDAP filter parser -- main routine is ldap_parse_filter
34  *
35  * Shamelessly stolen and adapted from ldb.
36  *
37  ***************************************************************************/
38
39 /*
40   return next token element. Caller frees
41 */
42 static char *ldap_parse_lex(TALLOC_CTX *mem_ctx, const char **s,
43                            const char *sep)
44 {
45         const char *p = *s;
46         char *ret;
47
48         while (isspace(*p)) {
49                 p++;
50         }
51         *s = p;
52
53         if (*p == 0) {
54                 return NULL;
55         }
56
57         if (strchr(sep, *p)) {
58                 (*s) = p+1;
59                 ret = talloc_strndup(mem_ctx, p, 1);
60                 if (!ret) {
61                         errno = ENOMEM;
62                 }
63                 return ret;
64         }
65
66         while (*p && (isalnum(*p) || !strchr(sep, *p))) {
67                 p++;
68         }
69
70         if (p == *s) {
71                 return NULL;
72         }
73
74         ret = talloc_strndup(mem_ctx, *s, p - *s);
75         if (!ret) {
76                 errno = ENOMEM;
77         }
78
79         *s = p;
80
81         return ret;
82 }
83
84
85 /*
86   find a matching close brace in a string
87 */
88 static const char *match_brace(const char *s)
89 {
90         unsigned int count = 0;
91         while (*s && (count != 0 || *s != ')')) {
92                 if (*s == '(') {
93                         count++;
94                 }
95                 if (*s == ')') {
96                         count--;
97                 }
98                 s++;
99         }
100         if (! *s) {
101                 return NULL;
102         }
103         return s;
104 }
105
106 static struct ldap_parse_tree *ldap_parse_filter(TALLOC_CTX *mem_ctx,
107                                                const char **s);
108
109 /*
110    decode a RFC2254 binary string representation of a buffer.
111    Used in LDAP filters.
112 */
113 struct ldap_val ldap_binary_decode(TALLOC_CTX *mem_ctx, const char *str)
114 {
115         int i, j;
116         struct ldap_val ret;
117         int slen = strlen(str);
118
119         ret.data = talloc_size(mem_ctx, slen);
120         ret.length = 0;
121         if (ret.data == NULL) return ret;
122
123         for (i=j=0;i<slen;i++) {
124                 if (str[i] == '\\') {
125                         unsigned c;
126                         if (sscanf(&str[i+1], "%02X", &c) != 1) {
127                                 talloc_free(ret.data);
128                                 ZERO_STRUCT(ret);
129                                 return ret;
130                         }
131                         ((uint8_t *)ret.data)[j++] = c;
132                         i += 2;
133                 } else {
134                         ((uint8_t *)ret.data)[j++] = str[i];
135                 }
136         }
137         ret.length = j;
138
139         return ret;
140 }
141
142
143 /*
144    encode a blob as a RFC2254 binary string, escaping any
145    non-printable or '\' characters
146 */
147 const char *ldap_binary_encode(TALLOC_CTX *mem_ctx, DATA_BLOB blob)
148 {
149         int i;
150         char *ret;
151         int len = blob.length;
152         for (i=0;i<blob.length;i++) {
153                 if (!isprint(blob.data[i]) || strchr(" *()\\&|!", blob.data[i])) {
154                         len += 2;
155                 }
156         }
157         ret = talloc_array(mem_ctx, char, len+1);
158         if (ret == NULL) return NULL;
159
160         len = 0;
161         for (i=0;i<blob.length;i++) {
162                 if (!isprint(blob.data[i]) || strchr(" *()\\&|!", blob.data[i])) {
163                         snprintf(ret+len, 4, "\\%02X", blob.data[i]);
164                         len += 3;
165                 } else {
166                         ret[len++] = blob.data[i];
167                 }
168         }
169
170         ret[len] = 0;
171
172         return ret;     
173 }
174
175
176 /*
177   <simple> ::= <attributetype> <filtertype> <attributevalue>
178 */
179 static struct ldap_parse_tree *ldap_parse_simple(TALLOC_CTX *mem_ctx,
180                                                const char *s)
181 {
182         char *eq, *val, *l;
183         struct ldap_parse_tree *ret;
184
185         l = ldap_parse_lex(mem_ctx, &s, LDAP_ALL_SEP);
186         if (!l) {
187                 return NULL;
188         }
189
190         if (strchr("()&|=", *l))
191                 return NULL;
192
193         eq = ldap_parse_lex(mem_ctx, &s, LDAP_ALL_SEP);
194         if (!eq || strcmp(eq, "=") != 0)
195                 return NULL;
196
197         val = ldap_parse_lex(mem_ctx, &s, ")");
198         if (val && strchr("()&|", *val))
199                 return NULL;
200         
201         ret = talloc(mem_ctx, struct ldap_parse_tree);
202         if (!ret) {
203                 errno = ENOMEM;
204                 return NULL;
205         }
206
207         ret->operation = LDAP_OP_SIMPLE;
208         ret->u.simple.attr = l;
209         ret->u.simple.value = ldap_binary_decode(ret, val);
210
211         return ret;
212 }
213
214
215 /*
216   parse a filterlist
217   <and> ::= '&' <filterlist>
218   <or> ::= '|' <filterlist>
219   <filterlist> ::= <filter> | <filter> <filterlist>
220 */
221 static struct ldap_parse_tree *ldap_parse_filterlist(TALLOC_CTX *mem_ctx,
222                                                    enum ldap_parse_op op,
223                                                    const char *s)
224 {
225         struct ldap_parse_tree *ret, *next;
226
227         ret = talloc(mem_ctx, struct ldap_parse_tree);
228         if (!ret) {
229                 errno = ENOMEM;
230                 return NULL;
231         }
232
233         ret->operation = op;
234         ret->u.list.num_elements = 1;
235         ret->u.list.elements = talloc(mem_ctx, struct ldap_parse_tree *);
236         if (!ret->u.list.elements) {
237                 errno = ENOMEM;
238                 return NULL;
239         }
240
241         ret->u.list.elements[0] = ldap_parse_filter(mem_ctx, &s);
242         if (!ret->u.list.elements[0]) {
243                 return NULL;
244         }
245
246         while (isspace(*s)) s++;
247
248         while (*s && (next = ldap_parse_filter(mem_ctx, &s))) {
249                 struct ldap_parse_tree **e;
250                 e = talloc_realloc(ret,
251                                      ret->u.list.elements,
252                                      struct ldap_parse_tree *,
253                                      ret->u.list.num_elements+1);
254                 if (!e) {
255                         errno = ENOMEM;
256                         return NULL;
257                 }
258                 ret->u.list.elements = e;
259                 ret->u.list.elements[ret->u.list.num_elements] = next;
260                 ret->u.list.num_elements++;
261                 while (isspace(*s)) s++;
262         }
263
264         return ret;
265 }
266
267
268 /*
269   <not> ::= '!' <filter>
270 */
271 static struct ldap_parse_tree *ldap_parse_not(TALLOC_CTX *mem_ctx, const char *s)
272 {
273         struct ldap_parse_tree *ret;
274
275         ret = talloc(mem_ctx, struct ldap_parse_tree);
276         if (!ret) {
277                 errno = ENOMEM;
278                 return NULL;
279         }
280
281         ret->operation = LDAP_OP_NOT;
282         ret->u.not.child = ldap_parse_filter(mem_ctx, &s);
283         if (!ret->u.not.child)
284                 return NULL;
285
286         return ret;
287 }
288
289 /*
290   parse a filtercomp
291   <filtercomp> ::= <and> | <or> | <not> | <simple>
292 */
293 static struct ldap_parse_tree *ldap_parse_filtercomp(TALLOC_CTX *mem_ctx,
294                                                    const char *s)
295 {
296         while (isspace(*s)) s++;
297
298         switch (*s) {
299         case '&':
300                 return ldap_parse_filterlist(mem_ctx, LDAP_OP_AND, s+1);
301
302         case '|':
303                 return ldap_parse_filterlist(mem_ctx, LDAP_OP_OR, s+1);
304
305         case '!':
306                 return ldap_parse_not(mem_ctx, s+1);
307
308         case '(':
309         case ')':
310                 return NULL;
311         }
312
313         return ldap_parse_simple(mem_ctx, s);
314 }
315
316
317 /*
318   <filter> ::= '(' <filtercomp> ')'
319 */
320 static struct ldap_parse_tree *ldap_parse_filter(TALLOC_CTX *mem_ctx,
321                                                  const char **s)
322 {
323         char *l, *s2;
324         const char *p, *p2;
325         struct ldap_parse_tree *ret;
326
327         l = ldap_parse_lex(mem_ctx, s, LDAP_ALL_SEP);
328         if (!l) {
329                 return NULL;
330         }
331
332         if (strcmp(l, "(") != 0) {
333                 return NULL;
334         }
335
336         p = match_brace(*s);
337         if (!p) {
338                 return NULL;
339         }
340         p2 = p + 1;
341
342         s2 = talloc_strndup(mem_ctx, *s, p - *s);
343         if (!s2) {
344                 errno = ENOMEM;
345                 return NULL;
346         }
347
348         ret = ldap_parse_filtercomp(mem_ctx, s2);
349
350         *s = p2;
351
352         return ret;
353 }
354
355 /*
356   main parser entry point. Takes a search string and returns a parse tree
357
358   expression ::= <simple> | <filter>
359 */
360 static struct ldap_parse_tree *ldap_parse_tree(TALLOC_CTX *mem_ctx, const char *s)
361 {
362         while (isspace(*s)) s++;
363
364         if (*s == '(') {
365                 return ldap_parse_filter(mem_ctx, &s);
366         }
367
368         return ldap_parse_simple(mem_ctx, s);
369 }
370
371 static BOOL ldap_push_filter(struct asn1_data *data, struct ldap_parse_tree *tree)
372 {
373         switch (tree->operation) {
374         case LDAP_OP_SIMPLE: {
375                 if ((tree->u.simple.value.length == 1) &&
376                     (((char *)(tree->u.simple.value.data))[0] == '*')) {
377                         /* Just a presence test */
378                         asn1_push_tag(data, 0x87);
379                         asn1_write(data, tree->u.simple.attr,
380                                    strlen(tree->u.simple.attr));
381                         asn1_pop_tag(data);
382                         return !data->has_error;
383                 }
384
385                 /* Equality is all we currently do... */
386                 asn1_push_tag(data, 0xa3);
387                 asn1_write_OctetString(data, tree->u.simple.attr,
388                                       strlen(tree->u.simple.attr));
389                 asn1_write_OctetString(data, tree->u.simple.value.data,
390                                       tree->u.simple.value.length);
391                 asn1_pop_tag(data);
392                 break;
393         }
394
395         case LDAP_OP_AND: {
396                 int i;
397
398                 asn1_push_tag(data, 0xa0);
399                 for (i=0; i<tree->u.list.num_elements; i++) {
400                         ldap_push_filter(data, tree->u.list.elements[i]);
401                 }
402                 asn1_pop_tag(data);
403                 break;
404         }
405
406         case LDAP_OP_OR: {
407                 int i;
408
409                 asn1_push_tag(data, 0xa1);
410                 for (i=0; i<tree->u.list.num_elements; i++) {
411                         ldap_push_filter(data, tree->u.list.elements[i]);
412                 }
413                 asn1_pop_tag(data);
414                 break;
415         }
416         default:
417                 return False;
418         }
419         return !data->has_error;
420 }
421
422 static void ldap_encode_response(struct asn1_data *data, struct ldap_Result *result)
423 {
424         asn1_write_enumerated(data, result->resultcode);
425         asn1_write_OctetString(data, result->dn,
426                                (result->dn) ? strlen(result->dn) : 0);
427         asn1_write_OctetString(data, result->errormessage,
428                                (result->errormessage) ?
429                                strlen(result->errormessage) : 0);
430         if (result->referral) {
431                 asn1_push_tag(data, ASN1_CONTEXT(3));
432                 asn1_write_OctetString(data, result->referral,
433                                        strlen(result->referral));
434                 asn1_pop_tag(data);
435         }
436 }
437
438 BOOL ldap_encode(struct ldap_message *msg, DATA_BLOB *result)
439 {
440         struct asn1_data data;
441         int i, j;
442
443         ZERO_STRUCT(data);
444         asn1_push_tag(&data, ASN1_SEQUENCE(0));
445         asn1_write_Integer(&data, msg->messageid);
446
447         switch (msg->type) {
448         case LDAP_TAG_BindRequest: {
449                 struct ldap_BindRequest *r = &msg->r.BindRequest;
450                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
451                 asn1_write_Integer(&data, r->version);
452                 asn1_write_OctetString(&data, r->dn,
453                                        (r->dn != NULL) ? strlen(r->dn) : 0);
454
455                 switch (r->mechanism) {
456                 case LDAP_AUTH_MECH_SIMPLE:
457                         /* context, primitive */
458                         asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
459                         asn1_write(&data, r->creds.password,
460                                    strlen(r->creds.password));
461                         asn1_pop_tag(&data);
462                         break;
463                 case LDAP_AUTH_MECH_SASL:
464                         /* context, constructed */
465                         asn1_push_tag(&data, ASN1_CONTEXT(3));
466                         asn1_write_OctetString(&data, r->creds.SASL.mechanism,
467                                                strlen(r->creds.SASL.mechanism));
468                         asn1_write_OctetString(&data, r->creds.SASL.secblob.data,
469                                                r->creds.SASL.secblob.length);
470                         asn1_pop_tag(&data);
471                         break;
472                 default:
473                         return False;
474                 }
475
476                 asn1_pop_tag(&data);
477                 asn1_pop_tag(&data);
478                 break;
479         }
480         case LDAP_TAG_BindResponse: {
481                 struct ldap_BindResponse *r = &msg->r.BindResponse;
482                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
483                 ldap_encode_response(&data, &r->response);
484                 if (r->SASL.secblob.length > 0) {
485                         asn1_write_ContextSimple(&data, 7, &r->SASL.secblob);
486                 }
487                 asn1_pop_tag(&data);
488                 break;
489         }
490         case LDAP_TAG_UnbindRequest: {
491 /*              struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
492                 break;
493         }
494         case LDAP_TAG_SearchRequest: {
495                 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
496                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
497                 asn1_write_OctetString(&data, r->basedn, strlen(r->basedn));
498                 asn1_write_enumerated(&data, r->scope);
499                 asn1_write_enumerated(&data, r->deref);
500                 asn1_write_Integer(&data, r->sizelimit);
501                 asn1_write_Integer(&data, r->timelimit);
502                 asn1_write_BOOLEAN(&data, r->attributesonly);
503
504                 {
505                         TALLOC_CTX *mem_ctx = talloc_init("ldap_parse_tree");
506                         struct ldap_parse_tree *tree;
507
508                         if (mem_ctx == NULL)
509                                 return False;
510
511                         tree = ldap_parse_tree(mem_ctx, r->filter);
512
513                         if (tree == NULL)
514                                 return False;
515
516                         ldap_push_filter(&data, tree);
517
518                         talloc_free(mem_ctx);
519                 }
520
521                 asn1_push_tag(&data, ASN1_SEQUENCE(0));
522                 for (i=0; i<r->num_attributes; i++) {
523                         asn1_write_OctetString(&data, r->attributes[i],
524                                                strlen(r->attributes[i]));
525                 }
526                 asn1_pop_tag(&data);
527
528                 asn1_pop_tag(&data);
529                 break;
530         }
531         case LDAP_TAG_SearchResultEntry: {
532                 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
533                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
534                 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
535                 asn1_push_tag(&data, ASN1_SEQUENCE(0));
536                 for (i=0; i<r->num_attributes; i++) {
537                         struct ldap_attribute *attr = &r->attributes[i];
538                         asn1_push_tag(&data, ASN1_SEQUENCE(0));
539                         asn1_write_OctetString(&data, attr->name,
540                                                strlen(attr->name));
541                         asn1_push_tag(&data, ASN1_SEQUENCE(1));
542                         for (j=0; j<attr->num_values; j++) {
543                                 asn1_write_OctetString(&data,
544                                                        attr->values[j].data,
545                                                        attr->values[j].length);
546                         }
547                         asn1_pop_tag(&data);
548                         asn1_pop_tag(&data);
549                 }
550                 asn1_pop_tag(&data);
551                 asn1_pop_tag(&data);
552                 break;
553         }
554         case LDAP_TAG_SearchResultDone: {
555                 struct ldap_Result *r = &msg->r.SearchResultDone;
556                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
557                 ldap_encode_response(&data, r);
558                 asn1_pop_tag(&data);
559                 break;
560         }
561         case LDAP_TAG_ModifyRequest: {
562                 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
563                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
564                 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
565                 asn1_push_tag(&data, ASN1_SEQUENCE(0));
566
567                 for (i=0; i<r->num_mods; i++) {
568                         struct ldap_attribute *attrib = &r->mods[i].attrib;
569                         asn1_push_tag(&data, ASN1_SEQUENCE(0));
570                         asn1_write_enumerated(&data, r->mods[i].type);
571                         asn1_push_tag(&data, ASN1_SEQUENCE(0));
572                         asn1_write_OctetString(&data, attrib->name,
573                                                strlen(attrib->name));
574                         asn1_push_tag(&data, ASN1_SET);
575                         for (j=0; j<attrib->num_values; j++) {
576                                 asn1_write_OctetString(&data,
577                                                        attrib->values[j].data,
578                                                        attrib->values[j].length);
579         
580                         }
581                         asn1_pop_tag(&data);
582                         asn1_pop_tag(&data);
583                         asn1_pop_tag(&data);
584                 }
585                 
586                 asn1_pop_tag(&data);
587                 asn1_pop_tag(&data);
588                 break;
589         }
590         case LDAP_TAG_ModifyResponse: {
591                 struct ldap_Result *r = &msg->r.ModifyResponse;
592                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
593                 ldap_encode_response(&data, r);
594                 asn1_pop_tag(&data);
595                 break;
596         }
597         case LDAP_TAG_AddRequest: {
598                 struct ldap_AddRequest *r = &msg->r.AddRequest;
599                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
600                 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
601                 asn1_push_tag(&data, ASN1_SEQUENCE(0));
602
603                 for (i=0; i<r->num_attributes; i++) {
604                         struct ldap_attribute *attrib = &r->attributes[i];
605                         asn1_push_tag(&data, ASN1_SEQUENCE(0));
606                         asn1_write_OctetString(&data, attrib->name,
607                                                strlen(attrib->name));
608                         asn1_push_tag(&data, ASN1_SET);
609                         for (j=0; j<r->attributes[i].num_values; j++) {
610                                 asn1_write_OctetString(&data,
611                                                        attrib->values[j].data,
612                                                        attrib->values[j].length);
613                         }
614                         asn1_pop_tag(&data);
615                         asn1_pop_tag(&data);
616                 }
617                 asn1_pop_tag(&data);
618                 asn1_pop_tag(&data);
619                 break;
620         }
621         case LDAP_TAG_AddResponse: {
622                 struct ldap_Result *r = &msg->r.AddResponse;
623                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
624                 ldap_encode_response(&data, r);
625                 asn1_pop_tag(&data);
626                 break;
627         }
628         case LDAP_TAG_DelRequest: {
629                 struct ldap_DelRequest *r = &msg->r.DelRequest;
630                 asn1_push_tag(&data, ASN1_APPLICATION_SIMPLE(msg->type));
631                 asn1_write(&data, r->dn, strlen(r->dn));
632                 asn1_pop_tag(&data);
633                 break;
634         }
635         case LDAP_TAG_DelResponse: {
636                 struct ldap_Result *r = &msg->r.DelResponse;
637                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
638                 ldap_encode_response(&data, r);
639                 asn1_pop_tag(&data);
640                 break;
641         }
642         case LDAP_TAG_ModifyDNRequest: {
643                 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
644                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
645                 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
646                 asn1_write_OctetString(&data, r->newrdn, strlen(r->newrdn));
647                 asn1_write_BOOLEAN(&data, r->deleteolddn);
648                 if (r->newsuperior != NULL) {
649                         asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
650                         asn1_write(&data, r->newsuperior,
651                                    strlen(r->newsuperior));
652                         asn1_pop_tag(&data);
653                 }
654                 asn1_pop_tag(&data);
655                 break;
656         }
657         case LDAP_TAG_ModifyDNResponse: {
658                 struct ldap_Result *r = &msg->r.ModifyDNResponse;
659                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
660                 ldap_encode_response(&data, r);
661                 asn1_pop_tag(&data);
662                 break;
663         }
664         case LDAP_TAG_CompareRequest: {
665                 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
666                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
667                 asn1_write_OctetString(&data, r->dn, strlen(r->dn));
668                 asn1_push_tag(&data, ASN1_SEQUENCE(0));
669                 asn1_write_OctetString(&data, r->attribute,
670                                        strlen(r->attribute));
671                 asn1_write_OctetString(&data, r->value.data,
672                                        r->value.length);
673                 asn1_pop_tag(&data);
674                 asn1_pop_tag(&data);
675                 break;
676         }
677         case LDAP_TAG_CompareResponse: {
678                 struct ldap_Result *r = &msg->r.ModifyDNResponse;
679                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
680                 ldap_encode_response(&data, r);
681                 asn1_pop_tag(&data);
682                 break;
683         }
684         case LDAP_TAG_AbandonRequest: {
685                 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
686                 asn1_push_tag(&data, ASN1_APPLICATION_SIMPLE(msg->type));
687                 asn1_write_implicit_Integer(&data, r->messageid);
688                 asn1_pop_tag(&data);
689                 break;
690         }
691         case LDAP_TAG_SearchResultReference: {
692                 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
693                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
694                 asn1_write_OctetString(&data, r->referral, strlen(r->referral));
695                 asn1_pop_tag(&data);
696                 break;
697         }
698         case LDAP_TAG_ExtendedRequest: {
699                 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
700                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
701                 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
702                 asn1_write(&data, r->oid, strlen(r->oid));
703                 asn1_pop_tag(&data);
704                 asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(1));
705                 asn1_write(&data, r->value.data, r->value.length);
706                 asn1_pop_tag(&data);
707                 asn1_pop_tag(&data);
708                 break;
709         }
710         case LDAP_TAG_ExtendedResponse: {
711                 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
712                 asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
713                 ldap_encode_response(&data, &r->response);
714                 asn1_pop_tag(&data);
715                 break;
716         }
717         default:
718                 return False;
719         }
720
721         asn1_pop_tag(&data);
722         *result = data_blob(data.data, data.length);
723         asn1_free(&data);
724         return True;
725 }
726
727 static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
728                                       DATA_BLOB blob)
729 {
730         char *result = talloc_size(mem_ctx, blob.length+1);
731         memcpy(result, blob.data, blob.length);
732         result[blob.length] = '\0';
733         return result;
734 }
735
736 static BOOL asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
737                                          struct asn1_data *data,
738                                          const char **result)
739 {
740         DATA_BLOB string;
741         if (!asn1_read_OctetString(data, &string))
742                 return False;
743         *result = blob2string_talloc(mem_ctx, string);
744         data_blob_free(&string);
745         return True;
746 }
747
748 static void ldap_decode_response(TALLOC_CTX *mem_ctx,
749                                  struct asn1_data *data,
750                                  struct ldap_Result *result)
751 {
752         asn1_read_enumerated(data, &result->resultcode);
753         asn1_read_OctetString_talloc(mem_ctx, data, &result->dn);
754         asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage);
755         if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
756                 asn1_start_tag(data, ASN1_CONTEXT(3));
757                 asn1_read_OctetString_talloc(mem_ctx, data, &result->referral);
758                 asn1_end_tag(data);
759         } else {
760                 result->referral = NULL;
761         }
762 }
763
764 static BOOL ldap_decode_filter(TALLOC_CTX *mem_ctx, struct asn1_data *data,
765                                const char **filterp)
766 {
767         uint8_t filter_tag, tag_desc;
768         char *filter = NULL;
769
770         *filterp = NULL;
771
772         if (!asn1_peek_uint8(data, &filter_tag))
773                 return False;
774
775         tag_desc = filter_tag;
776         filter_tag &= 0x1f;     /* strip off the asn1 stuff */
777         tag_desc &= 0xe0;
778
779         switch(filter_tag) {
780         case 0: {
781                 /* AND of one or more filters */
782                 if (tag_desc != 0xa0) /* context compount */
783                         return False;
784
785                 asn1_start_tag(data, ASN1_CONTEXT(0));
786
787                 filter = talloc_strdup(mem_ctx, "(&");
788                 if (filter == NULL)
789                         return False;
790
791                 while (asn1_tag_remaining(data) > 0) {
792                         const char *subfilter;
793                         if (!ldap_decode_filter(mem_ctx, data, &subfilter))
794                                 return False;
795                         filter = talloc_asprintf_append(filter, "%s", subfilter);
796                         if (filter == NULL)
797                                 return False;
798                 }
799                 asn1_end_tag(data);
800
801                 filter = talloc_asprintf_append(filter, ")");
802                 break;
803         }
804         case 1: {
805                 /* OR of one or more filters */
806                 if (tag_desc != 0xa0) /* context compount */
807                         return False;
808
809                 asn1_start_tag(data, ASN1_CONTEXT(1));
810
811                 filter = talloc_strdup(mem_ctx, "(|");
812                 if (filter == NULL)
813                         return False;
814
815                 while (asn1_tag_remaining(data) > 0) {
816                         const char *subfilter;
817                         if (!ldap_decode_filter(mem_ctx, data, &subfilter))
818                                 return False;
819                         filter = talloc_asprintf_append(filter, "%s", subfilter);
820                         if (filter == NULL)
821                                 return False;
822                 }
823
824                 asn1_end_tag(data);
825
826                 filter = talloc_asprintf_append(filter, ")");
827                 break;
828         }
829         case 3: {
830                 /* equalityMatch */
831                 const char *attrib;
832                 DATA_BLOB value;
833                 if (tag_desc != 0xa0) /* context compound */
834                         return False;
835                 asn1_start_tag(data, ASN1_CONTEXT(3));
836                 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
837                 asn1_read_OctetString(data, &value);
838                 asn1_end_tag(data);
839                 if ((data->has_error) || (attrib == NULL) || (value.data == NULL))
840                         return False;
841                 filter = talloc_asprintf(mem_ctx, "(%s=%s)", 
842                                          attrib, ldap_binary_encode(mem_ctx, value));
843                 data_blob_free(&value);
844                 break;
845         }
846         case 7: {
847                 /* Normal presence, "attribute=*" */
848                 int attr_len;
849                 char *attr_name;
850                 if (tag_desc != 0x80) /* context simple */
851                         return False;
852                 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(7)))
853                         return False;
854                 attr_len = asn1_tag_remaining(data);
855                 attr_name = malloc(attr_len+1);
856                 if (attr_name == NULL)
857                         return False;
858                 asn1_read(data, attr_name, attr_len);
859                 attr_name[attr_len] = '\0';
860                 filter = talloc_asprintf(mem_ctx, "(%s=*)", attr_name);
861                 SAFE_FREE(attr_name);
862                 asn1_end_tag(data);
863                 break;
864         }
865         default:
866                 return False;
867         }
868         if (filter == NULL)
869                 return False;
870
871         *filterp = filter;
872
873         return True;
874 }
875
876 static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
877                                struct ldap_attribute *attrib)
878 {
879         asn1_start_tag(data, ASN1_SEQUENCE(0));
880         asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name);
881         asn1_start_tag(data, ASN1_SET);
882         while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
883                 DATA_BLOB blob;
884                 struct ldap_val value;
885                 asn1_read_OctetString(data, &blob);
886                 value.data = blob.data;
887                 value.length = blob.length;
888                 add_value_to_attrib(mem_ctx, &value, attrib);
889                 data_blob_free(&blob);
890         }
891         asn1_end_tag(data);
892         asn1_end_tag(data);
893         
894 }
895
896 static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
897                                 struct ldap_attribute **attributes,
898                                 int *num_attributes)
899 {
900         asn1_start_tag(data, ASN1_SEQUENCE(0));
901         while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
902                 struct ldap_attribute attrib;
903                 ZERO_STRUCT(attrib);
904                 ldap_decode_attrib(mem_ctx, data, &attrib);
905                 add_attrib_to_array_talloc(mem_ctx, &attrib,
906                                            attributes, num_attributes);
907         }
908         asn1_end_tag(data);
909 }
910
911 BOOL ldap_decode(struct asn1_data *data, struct ldap_message *msg)
912 {
913         uint8_t tag;
914
915         asn1_start_tag(data, ASN1_SEQUENCE(0));
916         asn1_read_Integer(data, &msg->messageid);
917
918         if (!asn1_peek_uint8(data, &tag))
919                 return False;
920
921         switch(tag) {
922
923         case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
924                 struct ldap_BindRequest *r = &msg->r.BindRequest;
925                 msg->type = LDAP_TAG_BindRequest;
926                 asn1_start_tag(data, tag);
927                 asn1_read_Integer(data, &r->version);
928                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
929                 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
930                         int pwlen;
931                         r->creds.password = "";
932                         r->mechanism = LDAP_AUTH_MECH_SIMPLE;
933                         asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
934                         pwlen = asn1_tag_remaining(data);
935                         if (pwlen != 0) {
936                                 char *pw = talloc_size(msg->mem_ctx, pwlen+1);
937                                 asn1_read(data, pw, pwlen);
938                                 pw[pwlen] = '\0';
939                                 r->creds.password = pw;
940                         }
941                         asn1_end_tag(data);
942                 } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
943                         asn1_start_tag(data, ASN1_CONTEXT(3));
944                         r->mechanism = LDAP_AUTH_MECH_SASL;
945                         asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->creds.SASL.mechanism);
946                         asn1_read_OctetString(data, &r->creds.SASL.secblob);
947                         if (r->creds.SASL.secblob.data) {
948                                 talloc_steal(msg->mem_ctx, r->creds.SASL.secblob.data);
949                         }
950                         asn1_end_tag(data);
951                 }
952                 asn1_end_tag(data);
953                 break;
954         }
955
956         case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
957                 struct ldap_BindResponse *r = &msg->r.BindResponse;
958                 msg->type = LDAP_TAG_BindResponse;
959                 asn1_start_tag(data, tag);
960                 ldap_decode_response(msg->mem_ctx, data, &r->response);
961                 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
962                         DATA_BLOB tmp_blob = data_blob(NULL, 0);
963                         asn1_read_ContextSimple(data, 7, &tmp_blob);
964                         r->SASL.secblob = data_blob_talloc(msg->mem_ctx, tmp_blob.data, tmp_blob.length);
965                         data_blob_free(&tmp_blob);
966                 } else {
967                         r->SASL.secblob = data_blob(NULL, 0);
968                 }
969                 asn1_end_tag(data);
970                 break;
971         }
972
973         case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
974                 msg->type = LDAP_TAG_UnbindRequest;
975                 asn1_start_tag(data, tag);
976                 asn1_end_tag(data);
977                 break;
978         }
979
980         case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
981                 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
982                 msg->type = LDAP_TAG_SearchRequest;
983                 asn1_start_tag(data, tag);
984                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->basedn);
985                 asn1_read_enumerated(data, (int *)&(r->scope));
986                 asn1_read_enumerated(data, (int *)&(r->deref));
987                 asn1_read_Integer(data, &r->sizelimit);
988                 asn1_read_Integer(data, &r->timelimit);
989                 asn1_read_BOOLEAN(data, &r->attributesonly);
990
991                 /* Maybe create a TALLOC_CTX for the filter? This can waste
992                  * quite a bit of memory recursing down. */
993                 ldap_decode_filter(msg->mem_ctx, data, &r->filter);
994
995                 asn1_start_tag(data, ASN1_SEQUENCE(0));
996
997                 r->num_attributes = 0;
998                 r->attributes = NULL;
999
1000                 while (asn1_tag_remaining(data) > 0) {
1001                         const char *attr;
1002                         if (!asn1_read_OctetString_talloc(msg->mem_ctx, data,
1003                                                           &attr))
1004                                 return False;
1005                         if (!add_string_to_array(msg->mem_ctx, attr,
1006                                                  &r->attributes,
1007                                                  &r->num_attributes))
1008                                 return False;
1009                 }
1010
1011                 asn1_end_tag(data);
1012                 asn1_end_tag(data);
1013                 break;
1014         }
1015
1016         case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1017                 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1018                 msg->type = LDAP_TAG_SearchResultEntry;
1019                 r->attributes = NULL;
1020                 r->num_attributes = 0;
1021                 asn1_start_tag(data, tag);
1022                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
1023                 ldap_decode_attribs(msg->mem_ctx, data, &r->attributes,
1024                                     &r->num_attributes);
1025                 asn1_end_tag(data);
1026                 break;
1027         }
1028
1029         case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1030                 struct ldap_Result *r = &msg->r.SearchResultDone;
1031                 msg->type = LDAP_TAG_SearchResultDone;
1032                 asn1_start_tag(data, tag);
1033                 ldap_decode_response(msg->mem_ctx, data, r);
1034                 asn1_end_tag(data);
1035                 break;
1036         }
1037
1038         case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1039                 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
1040                 msg->type = LDAP_TAG_SearchResultReference;
1041                 asn1_start_tag(data, tag);
1042                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->referral);
1043                 asn1_end_tag(data);
1044                 break;
1045         }
1046
1047         case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1048                 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1049                 msg->type = LDAP_TAG_ModifyRequest;
1050                 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
1051                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
1052                 asn1_start_tag(data, ASN1_SEQUENCE(0));
1053
1054                 r->num_mods = 0;
1055                 r->mods = NULL;
1056
1057                 while (asn1_tag_remaining(data) > 0) {
1058                         struct ldap_mod mod;
1059                         int v;
1060                         ZERO_STRUCT(mod);
1061                         asn1_start_tag(data, ASN1_SEQUENCE(0));
1062                         asn1_read_enumerated(data, &v);
1063                         mod.type = v;
1064                         ldap_decode_attrib(msg->mem_ctx, data, &mod.attrib);
1065                         asn1_end_tag(data);
1066                         if (!add_mod_to_array_talloc(msg->mem_ctx, &mod,
1067                                                      &r->mods, &r->num_mods))
1068                                 break;
1069                 }
1070
1071                 asn1_end_tag(data);
1072                 asn1_end_tag(data);
1073                 break;
1074         }
1075
1076         case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1077                 struct ldap_Result *r = &msg->r.ModifyResponse;
1078                 msg->type = LDAP_TAG_ModifyResponse;
1079                 asn1_start_tag(data, tag);
1080                 ldap_decode_response(msg->mem_ctx, data, r);
1081                 asn1_end_tag(data);
1082                 break;
1083         }
1084
1085         case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1086                 struct ldap_AddRequest *r = &msg->r.AddRequest;
1087                 msg->type = LDAP_TAG_AddRequest;
1088                 asn1_start_tag(data, tag);
1089                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
1090
1091                 r->attributes = NULL;
1092                 r->num_attributes = 0;
1093                 ldap_decode_attribs(msg->mem_ctx, data, &r->attributes,
1094                                     &r->num_attributes);
1095
1096                 asn1_end_tag(data);
1097                 break;
1098         }
1099
1100         case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1101                 struct ldap_Result *r = &msg->r.AddResponse;
1102                 msg->type = LDAP_TAG_AddResponse;
1103                 asn1_start_tag(data, tag);
1104                 ldap_decode_response(msg->mem_ctx, data, r);
1105                 asn1_end_tag(data);
1106                 break;
1107         }
1108
1109         case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1110                 struct ldap_DelRequest *r = &msg->r.DelRequest;
1111                 int len;
1112                 char *dn;
1113                 msg->type = LDAP_TAG_DelRequest;
1114                 asn1_start_tag(data,
1115                                ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
1116                 len = asn1_tag_remaining(data);
1117                 dn = talloc_size(msg->mem_ctx, len+1);
1118                 if (dn == NULL)
1119                         break;
1120                 asn1_read(data, dn, len);
1121                 dn[len] = '\0';
1122                 r->dn = dn;
1123                 asn1_end_tag(data);
1124                 break;
1125         }
1126
1127         case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1128                 struct ldap_Result *r = &msg->r.DelResponse;
1129                 msg->type = LDAP_TAG_DelResponse;
1130                 asn1_start_tag(data, tag);
1131                 ldap_decode_response(msg->mem_ctx, data, r);
1132                 asn1_end_tag(data);
1133                 break;
1134         }
1135
1136         case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1137                 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1138                 msg->type = LDAP_TAG_ModifyDNRequest;
1139                 asn1_start_tag(data,
1140                                ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
1141                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
1142                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->newrdn);
1143                 asn1_read_BOOLEAN(data, &r->deleteolddn);
1144                 r->newsuperior = NULL;
1145                 if (asn1_tag_remaining(data) > 0) {
1146                         int len;
1147                         char *newsup;
1148                         asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1149                         len = asn1_tag_remaining(data);
1150                         newsup = talloc_size(msg->mem_ctx, len+1);
1151                         if (newsup == NULL)
1152                                 break;
1153                         asn1_read(data, newsup, len);
1154                         newsup[len] = '\0';
1155                         r->newsuperior = newsup;
1156                         asn1_end_tag(data);
1157                 }
1158                 asn1_end_tag(data);
1159                 break;
1160         }
1161
1162         case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1163                 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1164                 msg->type = LDAP_TAG_ModifyDNResponse;
1165                 asn1_start_tag(data, tag);
1166                 ldap_decode_response(msg->mem_ctx, data, r);
1167                 asn1_end_tag(data);
1168                 break;
1169         }
1170
1171         case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1172                 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1173                 msg->type = LDAP_TAG_CompareRequest;
1174                 asn1_start_tag(data,
1175                                ASN1_APPLICATION(LDAP_TAG_CompareRequest));
1176                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
1177                 asn1_start_tag(data, ASN1_SEQUENCE(0));
1178                 asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->attribute);
1179                 asn1_read_OctetString(data, &r->value);
1180                 if (r->value.data) {
1181                         talloc_steal(msg->mem_ctx, r->value.data);
1182                 }
1183                 asn1_end_tag(data);
1184                 asn1_end_tag(data);
1185                 break;
1186         }
1187
1188         case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1189                 struct ldap_Result *r = &msg->r.CompareResponse;
1190                 msg->type = LDAP_TAG_CompareResponse;
1191                 asn1_start_tag(data, tag);
1192                 ldap_decode_response(msg->mem_ctx, data, r);
1193                 asn1_end_tag(data);
1194                 break;
1195         }
1196
1197         case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1198                 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1199                 msg->type = LDAP_TAG_AbandonRequest;
1200                 asn1_start_tag(data, tag);
1201                 asn1_read_implicit_Integer(data, &r->messageid);
1202                 asn1_end_tag(data);
1203                 break;
1204         }
1205
1206         case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1207                 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1208                 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1209
1210                 msg->type = LDAP_TAG_ExtendedRequest;
1211                 asn1_start_tag(data,tag);
1212                 if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
1213                         return False;
1214                 }
1215                 r->oid = blob2string_talloc(msg->mem_ctx, tmp_blob);
1216                 data_blob_free(&tmp_blob);
1217                 if (!r->oid) {
1218                         return False;
1219                 }
1220
1221                 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1222                         asn1_read_ContextSimple(data, 1, &tmp_blob);
1223                         r->value = data_blob_talloc(msg->mem_ctx, tmp_blob.data, tmp_blob.length);
1224                         data_blob_free(&tmp_blob);
1225                 } else {
1226                         r->value = data_blob(NULL, 0);
1227                 }
1228
1229                 asn1_end_tag(data);
1230                 break;
1231         }
1232
1233         case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1234                 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1235                 msg->type = LDAP_TAG_ExtendedResponse;
1236                 asn1_start_tag(data, tag);              
1237                 ldap_decode_response(msg->mem_ctx, data, &r->response);
1238                 /* I have to come across an operation that actually sends
1239                  * something back to really see what's going on. The currently
1240                  * needed pwdchange does not send anything back. */
1241                 r->name = NULL;
1242                 r->value.data = NULL;
1243                 r->value.length = 0;
1244                 asn1_end_tag(data);
1245                 break;
1246         }
1247         default: 
1248                 return False;
1249         }
1250
1251         msg->num_controls = 0;
1252         msg->controls = NULL;
1253
1254         if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1255                 int i;
1256                 struct ldap_Control *ctrl = NULL;
1257
1258                 asn1_start_tag(data, ASN1_CONTEXT(0));
1259
1260                 for (i=0; asn1_peek_tag(data, ASN1_SEQUENCE(0)); i++) {
1261                         asn1_start_tag(data, ASN1_SEQUENCE(0));
1262
1263                         ctrl = talloc_realloc(msg->mem_ctx, ctrl, struct ldap_Control, i+1);
1264                         if (!ctrl) {
1265                                 return False;
1266                         }
1267                         ctrl[i].oid = NULL;
1268                         ctrl[i].critical = False;
1269                         ctrl[i].value = data_blob(NULL, 0);
1270
1271                         asn1_read_OctetString_talloc(ctrl, data, &ctrl[i].oid);
1272
1273                         if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
1274                                 asn1_read_BOOLEAN(data, &ctrl[i].critical);
1275                         }
1276
1277                         if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
1278                                 asn1_read_OctetString(data, &ctrl[i].value);
1279                                 if (ctrl[i].value.data) {
1280                                         talloc_steal(msg->mem_ctx, ctrl[i].value.data);
1281                                 }
1282                         }
1283
1284                         asn1_end_tag(data);
1285                 }
1286                 msg->num_controls = i;
1287                 msg->controls = ctrl;
1288
1289                 asn1_end_tag(data);
1290         }
1291
1292         asn1_end_tag(data);
1293         return ((!data->has_error) && (data->nesting == NULL));
1294 }
1295
1296 BOOL ldap_parse_basic_url(TALLOC_CTX *mem_ctx, const char *url,
1297                           char **host, uint16_t *port, BOOL *ldaps)
1298 {
1299         int tmp_port = 0;
1300         char protocol[11];
1301         char tmp_host[255];
1302         const char *p = url;
1303         int ret;
1304
1305         /* skip leading "URL:" (if any) */
1306         if (strncasecmp( p, "URL:", 4) == 0) {
1307                 p += 4;
1308         }
1309
1310         /* Paranoia check */
1311         SMB_ASSERT(sizeof(protocol)>10 && sizeof(tmp_host)>254);
1312                 
1313         ret = sscanf(p, "%10[^:]://%254[^:/]:%d", protocol, tmp_host, &tmp_port);
1314         if (ret < 2) {
1315                 return False;
1316         }
1317
1318         if (strequal(protocol, "ldap")) {
1319                 *port = 389;
1320                 *ldaps = False;
1321         } else if (strequal(protocol, "ldaps")) {
1322                 *port = 636;
1323                 *ldaps = True;
1324         } else {
1325                 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
1326                 return False;
1327         }
1328
1329         if (tmp_port != 0)
1330                 *port = tmp_port;
1331
1332         *host = talloc_strdup(mem_ctx, tmp_host);
1333
1334         return (*host != NULL);
1335 }
1336
1337
1338
1339 /* 
1340    externally callable version of filter string parsing - used in the
1341    cldap server
1342 */
1343 struct ldap_parse_tree *ldap_parse_filter_string(TALLOC_CTX *mem_ctx,
1344                                                  const char *s)
1345 {
1346         return ldap_parse_filter(mem_ctx, &s);
1347 }
1348
1349
1350