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