r21511: this seems to be the nicer fix for the problem with
[abartlet/samba.git/.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 == -1) {
953                                 return False;
954                         }
955                         if (pwlen != 0) {
956                                 char *pw = talloc_size(msg, pwlen+1);
957                                 if (!pw) {
958                                         return False;
959                                 }
960                                 asn1_read(data, pw, pwlen);
961                                 pw[pwlen] = '\0';
962                                 r->creds.password = pw;
963                         }
964                         asn1_end_tag(data);
965                 } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
966                         asn1_start_tag(data, ASN1_CONTEXT(3));
967                         r->mechanism = LDAP_AUTH_MECH_SASL;
968                         asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism);
969                         if (asn1_peek_tag(data, ASN1_OCTET_STRING)) { /* optional */
970                                 DATA_BLOB tmp_blob = data_blob(NULL, 0);
971                                 asn1_read_OctetString(data, &tmp_blob);
972                                 r->creds.SASL.secblob = talloc(msg, DATA_BLOB);
973                                 if (!r->creds.SASL.secblob) {
974                                         return False;
975                                 }
976                                 *r->creds.SASL.secblob = data_blob_talloc(r->creds.SASL.secblob,
977                                                                           tmp_blob.data, tmp_blob.length);
978                                 data_blob_free(&tmp_blob);
979                         } else {
980                                 r->creds.SASL.secblob = NULL;
981                         }
982                         asn1_end_tag(data);
983                 } else {
984                         /* Neither Simple nor SASL bind */
985                         return False;
986                 }
987                 asn1_end_tag(data);
988                 break;
989         }
990
991         case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
992                 struct ldap_BindResponse *r = &msg->r.BindResponse;
993                 msg->type = LDAP_TAG_BindResponse;
994                 asn1_start_tag(data, tag);
995                 ldap_decode_response(msg, data, &r->response);
996                 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
997                         DATA_BLOB tmp_blob = data_blob(NULL, 0);
998                         asn1_read_ContextSimple(data, 7, &tmp_blob);
999                         r->SASL.secblob = talloc(msg, DATA_BLOB);
1000                         if (!r->SASL.secblob) {
1001                                 return False;
1002                         }
1003                         *r->SASL.secblob = data_blob_talloc(r->SASL.secblob,
1004                                                             tmp_blob.data, tmp_blob.length);
1005                         data_blob_free(&tmp_blob);
1006                 } else {
1007                         r->SASL.secblob = NULL;
1008                 }
1009                 asn1_end_tag(data);
1010                 break;
1011         }
1012
1013         case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
1014                 msg->type = LDAP_TAG_UnbindRequest;
1015                 asn1_start_tag(data, tag);
1016                 asn1_end_tag(data);
1017                 break;
1018         }
1019
1020         case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
1021                 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
1022                 msg->type = LDAP_TAG_SearchRequest;
1023                 asn1_start_tag(data, tag);
1024                 asn1_read_OctetString_talloc(msg, data, &r->basedn);
1025                 asn1_read_enumerated(data, (int *)&(r->scope));
1026                 asn1_read_enumerated(data, (int *)&(r->deref));
1027                 asn1_read_Integer(data, &r->sizelimit);
1028                 asn1_read_Integer(data, &r->timelimit);
1029                 asn1_read_BOOLEAN(data, &r->attributesonly);
1030
1031                 r->tree = ldap_decode_filter_tree(msg, data);
1032                 if (r->tree == NULL) {
1033                         return False;
1034                 }
1035
1036                 asn1_start_tag(data, ASN1_SEQUENCE(0));
1037
1038                 r->num_attributes = 0;
1039                 r->attributes = NULL;
1040
1041                 while (asn1_tag_remaining(data) > 0) {
1042                         const char *attr;
1043                         if (!asn1_read_OctetString_talloc(msg, data,
1044                                                           &attr))
1045                                 return False;
1046                         if (!add_string_to_array(msg, attr,
1047                                                  &r->attributes,
1048                                                  &r->num_attributes))
1049                                 return False;
1050                 }
1051
1052                 asn1_end_tag(data);
1053                 asn1_end_tag(data);
1054                 break;
1055         }
1056
1057         case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1058                 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1059                 msg->type = LDAP_TAG_SearchResultEntry;
1060                 r->attributes = NULL;
1061                 r->num_attributes = 0;
1062                 asn1_start_tag(data, tag);
1063                 asn1_read_OctetString_talloc(msg, data, &r->dn);
1064                 ldap_decode_attribs(msg, data, &r->attributes,
1065                                     &r->num_attributes);
1066                 asn1_end_tag(data);
1067                 break;
1068         }
1069
1070         case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1071                 struct ldap_Result *r = &msg->r.SearchResultDone;
1072                 msg->type = LDAP_TAG_SearchResultDone;
1073                 asn1_start_tag(data, tag);
1074                 ldap_decode_response(msg, data, r);
1075                 asn1_end_tag(data);
1076                 break;
1077         }
1078
1079         case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1080                 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
1081                 msg->type = LDAP_TAG_SearchResultReference;
1082                 asn1_start_tag(data, tag);
1083                 asn1_read_OctetString_talloc(msg, data, &r->referral);
1084                 asn1_end_tag(data);
1085                 break;
1086         }
1087
1088         case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1089                 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1090                 msg->type = LDAP_TAG_ModifyRequest;
1091                 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
1092                 asn1_read_OctetString_talloc(msg, data, &r->dn);
1093                 asn1_start_tag(data, ASN1_SEQUENCE(0));
1094
1095                 r->num_mods = 0;
1096                 r->mods = NULL;
1097
1098                 while (asn1_tag_remaining(data) > 0) {
1099                         struct ldap_mod mod;
1100                         int v;
1101                         ZERO_STRUCT(mod);
1102                         asn1_start_tag(data, ASN1_SEQUENCE(0));
1103                         asn1_read_enumerated(data, &v);
1104                         mod.type = v;
1105                         ldap_decode_attrib(msg, data, &mod.attrib);
1106                         asn1_end_tag(data);
1107                         if (!add_mod_to_array_talloc(msg, &mod,
1108                                                      &r->mods, &r->num_mods)) {
1109                                 return False;
1110                         }
1111                 }
1112
1113                 asn1_end_tag(data);
1114                 asn1_end_tag(data);
1115                 break;
1116         }
1117
1118         case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1119                 struct ldap_Result *r = &msg->r.ModifyResponse;
1120                 msg->type = LDAP_TAG_ModifyResponse;
1121                 asn1_start_tag(data, tag);
1122                 ldap_decode_response(msg, data, r);
1123                 asn1_end_tag(data);
1124                 break;
1125         }
1126
1127         case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1128                 struct ldap_AddRequest *r = &msg->r.AddRequest;
1129                 msg->type = LDAP_TAG_AddRequest;
1130                 asn1_start_tag(data, tag);
1131                 asn1_read_OctetString_talloc(msg, data, &r->dn);
1132
1133                 r->attributes = NULL;
1134                 r->num_attributes = 0;
1135                 ldap_decode_attribs(msg, data, &r->attributes,
1136                                     &r->num_attributes);
1137
1138                 asn1_end_tag(data);
1139                 break;
1140         }
1141
1142         case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1143                 struct ldap_Result *r = &msg->r.AddResponse;
1144                 msg->type = LDAP_TAG_AddResponse;
1145                 asn1_start_tag(data, tag);
1146                 ldap_decode_response(msg, data, r);
1147                 asn1_end_tag(data);
1148                 break;
1149         }
1150
1151         case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1152                 struct ldap_DelRequest *r = &msg->r.DelRequest;
1153                 int len;
1154                 char *dn;
1155                 msg->type = LDAP_TAG_DelRequest;
1156                 asn1_start_tag(data,
1157                                ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
1158                 len = asn1_tag_remaining(data);
1159                 if (len == -1) {
1160                         return False;
1161                 }
1162                 dn = talloc_size(msg, len+1);
1163                 if (dn == NULL)
1164                         break;
1165                 asn1_read(data, dn, len);
1166                 dn[len] = '\0';
1167                 r->dn = dn;
1168                 asn1_end_tag(data);
1169                 break;
1170         }
1171
1172         case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1173                 struct ldap_Result *r = &msg->r.DelResponse;
1174                 msg->type = LDAP_TAG_DelResponse;
1175                 asn1_start_tag(data, tag);
1176                 ldap_decode_response(msg, data, r);
1177                 asn1_end_tag(data);
1178                 break;
1179         }
1180
1181         case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1182                 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1183                 msg->type = LDAP_TAG_ModifyDNRequest;
1184                 asn1_start_tag(data,
1185                                ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
1186                 asn1_read_OctetString_talloc(msg, data, &r->dn);
1187                 asn1_read_OctetString_talloc(msg, data, &r->newrdn);
1188                 asn1_read_BOOLEAN(data, &r->deleteolddn);
1189                 r->newsuperior = NULL;
1190                 if (asn1_tag_remaining(data) > 0) {
1191                         int len;
1192                         char *newsup;
1193                         asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1194                         len = asn1_tag_remaining(data);
1195                         if (len == -1) {
1196                                 return False;
1197                         }
1198                         newsup = talloc_size(msg, len+1);
1199                         if (newsup == NULL) {
1200                                 return False;
1201                         }
1202                         asn1_read(data, newsup, len);
1203                         newsup[len] = '\0';
1204                         r->newsuperior = newsup;
1205                         asn1_end_tag(data);
1206                 }
1207                 asn1_end_tag(data);
1208                 break;
1209         }
1210
1211         case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1212                 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1213                 msg->type = LDAP_TAG_ModifyDNResponse;
1214                 asn1_start_tag(data, tag);
1215                 ldap_decode_response(msg, data, r);
1216                 asn1_end_tag(data);
1217                 break;
1218         }
1219
1220         case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1221                 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1222                 msg->type = LDAP_TAG_CompareRequest;
1223                 asn1_start_tag(data,
1224                                ASN1_APPLICATION(LDAP_TAG_CompareRequest));
1225                 asn1_read_OctetString_talloc(msg, data, &r->dn);
1226                 asn1_start_tag(data, ASN1_SEQUENCE(0));
1227                 asn1_read_OctetString_talloc(msg, data, &r->attribute);
1228                 asn1_read_OctetString(data, &r->value);
1229                 if (r->value.data) {
1230                         talloc_steal(msg, r->value.data);
1231                 }
1232                 asn1_end_tag(data);
1233                 asn1_end_tag(data);
1234                 break;
1235         }
1236
1237         case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1238                 struct ldap_Result *r = &msg->r.CompareResponse;
1239                 msg->type = LDAP_TAG_CompareResponse;
1240                 asn1_start_tag(data, tag);
1241                 ldap_decode_response(msg, data, r);
1242                 asn1_end_tag(data);
1243                 break;
1244         }
1245
1246         case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1247                 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1248                 msg->type = LDAP_TAG_AbandonRequest;
1249                 asn1_start_tag(data, tag);
1250                 asn1_read_implicit_Integer(data, &r->messageid);
1251                 asn1_end_tag(data);
1252                 break;
1253         }
1254
1255         case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1256                 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1257                 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1258
1259                 msg->type = LDAP_TAG_ExtendedRequest;
1260                 asn1_start_tag(data,tag);
1261                 if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
1262                         return False;
1263                 }
1264                 r->oid = blob2string_talloc(msg, tmp_blob);
1265                 data_blob_free(&tmp_blob);
1266                 if (!r->oid) {
1267                         return False;
1268                 }
1269
1270                 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1271                         asn1_read_ContextSimple(data, 1, &tmp_blob);
1272                         r->value = talloc(msg, DATA_BLOB);
1273                         if (!r->value) {
1274                                 return False;
1275                         }
1276                         *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1277                         data_blob_free(&tmp_blob);
1278                 } else {
1279                         r->value = NULL;
1280                 }
1281
1282                 asn1_end_tag(data);
1283                 break;
1284         }
1285
1286         case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1287                 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1288                 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1289
1290                 msg->type = LDAP_TAG_ExtendedResponse;
1291                 asn1_start_tag(data, tag);              
1292                 ldap_decode_response(msg, data, &r->response);
1293
1294                 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(10))) {
1295                         asn1_read_ContextSimple(data, 1, &tmp_blob);
1296                         r->oid = blob2string_talloc(msg, tmp_blob);
1297                         data_blob_free(&tmp_blob);
1298                         if (!r->oid) {
1299                                 return False;
1300                         }
1301                 } else {
1302                         r->oid = NULL;
1303                 }
1304
1305                 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(11))) {
1306                         asn1_read_ContextSimple(data, 1, &tmp_blob);
1307                         r->value = talloc(msg, DATA_BLOB);
1308                         if (!r->value) {
1309                                 return False;
1310                         }
1311                         *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1312                         data_blob_free(&tmp_blob);
1313                 } else {
1314                         r->value = NULL;
1315                 }
1316
1317                 asn1_end_tag(data);
1318                 break;
1319         }
1320         default: 
1321                 return False;
1322         }
1323
1324         msg->controls = NULL;
1325
1326         if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1327                 int i;
1328                 struct ldb_control **ctrl = NULL;
1329
1330                 asn1_start_tag(data, ASN1_CONTEXT(0));
1331
1332                 for (i=0; asn1_peek_tag(data, ASN1_SEQUENCE(0)); i++) {
1333                         /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1334
1335                         ctrl = talloc_realloc(msg, ctrl, struct ldb_control *, i+2);
1336                         if (!ctrl) {
1337                                 return False;
1338                         }
1339
1340                         ctrl[i] = talloc(ctrl, struct ldb_control);
1341                         if (!ctrl[i]) {
1342                                 return False;
1343                         }
1344
1345                         if (!ldap_decode_control(ctrl, data, ctrl[i])) {
1346                                 return False;
1347                         }
1348
1349                 }
1350
1351                 if (ctrl != NULL) {
1352                         ctrl[i] = NULL;
1353                 }
1354
1355                 msg->controls = ctrl;
1356
1357                 asn1_end_tag(data);
1358         }
1359
1360         asn1_end_tag(data);
1361         return ((!data->has_error) && (data->nesting == NULL));
1362 }
1363
1364
1365 /*
1366   return NT_STATUS_OK if a blob has enough bytes in it to be a full
1367   ldap packet. Set packet_size if true.
1368 */
1369 NTSTATUS ldap_full_packet(void *private_data, DATA_BLOB blob, size_t *packet_size)
1370 {
1371         return asn1_full_tag(blob, ASN1_SEQUENCE(0), packet_size);
1372 }