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