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