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