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