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