s4:libcli/ldap: split out a ldap_decode_attribs_bare() function
[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 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 /* Decode a single LDAP attribute, possibly containing multiple values */
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 /* Decode a set of LDAP attributes, as found in the dereference control */
915 void ldap_decode_attribs_bare(TALLOC_CTX *mem_ctx, struct asn1_data *data,
916                               struct ldb_message_element **attributes,
917                               int *num_attributes)
918 {
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 }
927
928 /* Decode a set of LDAP attributes, as found in a search entry */
929 void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
930                          struct ldb_message_element **attributes,
931                          int *num_attributes)
932 {
933         asn1_start_tag(data, ASN1_SEQUENCE(0));
934         ldap_decode_attribs_bare(mem_ctx, data, 
935                                  attributes, num_attributes);
936         asn1_end_tag(data);
937 }
938
939 /* This routine returns LDAP status codes */
940
941 _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, struct ldap_message *msg)
942 {
943         uint8_t tag;
944
945         asn1_start_tag(data, ASN1_SEQUENCE(0));
946         asn1_read_Integer(data, &msg->messageid);
947
948         if (!asn1_peek_uint8(data, &tag))
949                 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
950
951         switch(tag) {
952
953         case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
954                 struct ldap_BindRequest *r = &msg->r.BindRequest;
955                 msg->type = LDAP_TAG_BindRequest;
956                 asn1_start_tag(data, tag);
957                 asn1_read_Integer(data, &r->version);
958                 asn1_read_OctetString_talloc(msg, data, &r->dn);
959                 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
960                         int pwlen;
961                         r->creds.password = "";
962                         r->mechanism = LDAP_AUTH_MECH_SIMPLE;
963                         asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
964                         pwlen = asn1_tag_remaining(data);
965                         if (pwlen == -1) {
966                                 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
967                         }
968                         if (pwlen != 0) {
969                                 char *pw = talloc_array(msg, char, pwlen+1);
970                                 if (!pw) {
971                                         return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
972                                 }
973                                 asn1_read(data, pw, pwlen);
974                                 pw[pwlen] = '\0';
975                                 r->creds.password = pw;
976                         }
977                         asn1_end_tag(data);
978                 } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
979                         asn1_start_tag(data, ASN1_CONTEXT(3));
980                         r->mechanism = LDAP_AUTH_MECH_SASL;
981                         asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism);
982                         if (asn1_peek_tag(data, ASN1_OCTET_STRING)) { /* optional */
983                                 DATA_BLOB tmp_blob = data_blob(NULL, 0);
984                                 asn1_read_OctetString(data, msg, &tmp_blob);
985                                 r->creds.SASL.secblob = talloc(msg, DATA_BLOB);
986                                 if (!r->creds.SASL.secblob) {
987                                         return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
988                                 }
989                                 *r->creds.SASL.secblob = data_blob_talloc(r->creds.SASL.secblob,
990                                                                           tmp_blob.data, tmp_blob.length);
991                                 data_blob_free(&tmp_blob);
992                         } else {
993                                 r->creds.SASL.secblob = NULL;
994                         }
995                         asn1_end_tag(data);
996                 } else {
997                         /* Neither Simple nor SASL bind */
998                         return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
999                 }
1000                 asn1_end_tag(data);
1001                 break;
1002         }
1003
1004         case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
1005                 struct ldap_BindResponse *r = &msg->r.BindResponse;
1006                 msg->type = LDAP_TAG_BindResponse;
1007                 asn1_start_tag(data, tag);
1008                 ldap_decode_response(msg, data, &r->response);
1009                 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
1010                         DATA_BLOB tmp_blob = data_blob(NULL, 0);
1011                         asn1_read_ContextSimple(data, 7, &tmp_blob);
1012                         r->SASL.secblob = talloc(msg, DATA_BLOB);
1013                         if (!r->SASL.secblob) {
1014                                 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1015                         }
1016                         *r->SASL.secblob = data_blob_talloc(r->SASL.secblob,
1017                                                             tmp_blob.data, tmp_blob.length);
1018                         data_blob_free(&tmp_blob);
1019                 } else {
1020                         r->SASL.secblob = NULL;
1021                 }
1022                 asn1_end_tag(data);
1023                 break;
1024         }
1025
1026         case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
1027                 msg->type = LDAP_TAG_UnbindRequest;
1028                 asn1_start_tag(data, tag);
1029                 asn1_end_tag(data);
1030                 break;
1031         }
1032
1033         case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
1034                 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
1035                 msg->type = LDAP_TAG_SearchRequest;
1036                 asn1_start_tag(data, tag);
1037                 asn1_read_OctetString_talloc(msg, data, &r->basedn);
1038                 asn1_read_enumerated(data, (int *)&(r->scope));
1039                 asn1_read_enumerated(data, (int *)&(r->deref));
1040                 asn1_read_Integer(data, &r->sizelimit);
1041                 asn1_read_Integer(data, &r->timelimit);
1042                 asn1_read_BOOLEAN(data, &r->attributesonly);
1043
1044                 r->tree = ldap_decode_filter_tree(msg, data);
1045                 if (r->tree == NULL) {
1046                         return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1047                 }
1048
1049                 asn1_start_tag(data, ASN1_SEQUENCE(0));
1050
1051                 r->num_attributes = 0;
1052                 r->attributes = NULL;
1053
1054                 while (asn1_tag_remaining(data) > 0) {                                  
1055
1056                         const char *attr;
1057                         if (!asn1_read_OctetString_talloc(msg, data,
1058                                                           &attr))
1059                                 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1060                         if (!add_string_to_array(msg, attr,
1061                                                  &r->attributes,
1062                                                  &r->num_attributes))
1063                                 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1064                 }
1065
1066                 asn1_end_tag(data);
1067                 asn1_end_tag(data);
1068                 break;
1069         }
1070
1071         case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1072                 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1073                 msg->type = LDAP_TAG_SearchResultEntry;
1074                 r->attributes = NULL;
1075                 r->num_attributes = 0;
1076                 asn1_start_tag(data, tag);
1077                 asn1_read_OctetString_talloc(msg, data, &r->dn);
1078                 ldap_decode_attribs(msg, data, &r->attributes,
1079                                     &r->num_attributes);
1080                 asn1_end_tag(data);
1081                 break;
1082         }
1083
1084         case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1085                 struct ldap_Result *r = &msg->r.SearchResultDone;
1086                 msg->type = LDAP_TAG_SearchResultDone;
1087                 asn1_start_tag(data, tag);
1088                 ldap_decode_response(msg, data, r);
1089                 asn1_end_tag(data);
1090                 break;
1091         }
1092
1093         case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1094                 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
1095                 msg->type = LDAP_TAG_SearchResultReference;
1096                 asn1_start_tag(data, tag);
1097                 asn1_read_OctetString_talloc(msg, data, &r->referral);
1098                 asn1_end_tag(data);
1099                 break;
1100         }
1101
1102         case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1103                 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1104                 msg->type = LDAP_TAG_ModifyRequest;
1105                 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
1106                 asn1_read_OctetString_talloc(msg, data, &r->dn);
1107                 asn1_start_tag(data, ASN1_SEQUENCE(0));
1108
1109                 r->num_mods = 0;
1110                 r->mods = NULL;
1111
1112                 while (asn1_tag_remaining(data) > 0) {
1113                         struct ldap_mod mod;
1114                         int v;
1115                         ZERO_STRUCT(mod);
1116                         asn1_start_tag(data, ASN1_SEQUENCE(0));
1117                         asn1_read_enumerated(data, &v);
1118                         mod.type = v;
1119                         ldap_decode_attrib(msg, data, &mod.attrib);
1120                         asn1_end_tag(data);
1121                         if (!add_mod_to_array_talloc(msg, &mod,
1122                                                      &r->mods, &r->num_mods)) {
1123                                 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1124                         }
1125                 }
1126
1127                 asn1_end_tag(data);
1128                 asn1_end_tag(data);
1129                 break;
1130         }
1131
1132         case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1133                 struct ldap_Result *r = &msg->r.ModifyResponse;
1134                 msg->type = LDAP_TAG_ModifyResponse;
1135                 asn1_start_tag(data, tag);
1136                 ldap_decode_response(msg, data, r);
1137                 asn1_end_tag(data);
1138                 break;
1139         }
1140
1141         case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1142                 struct ldap_AddRequest *r = &msg->r.AddRequest;
1143                 msg->type = LDAP_TAG_AddRequest;
1144                 asn1_start_tag(data, tag);
1145                 asn1_read_OctetString_talloc(msg, data, &r->dn);
1146
1147                 r->attributes = NULL;
1148                 r->num_attributes = 0;
1149                 ldap_decode_attribs(msg, data, &r->attributes,
1150                                     &r->num_attributes);
1151
1152                 asn1_end_tag(data);
1153                 break;
1154         }
1155
1156         case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1157                 struct ldap_Result *r = &msg->r.AddResponse;
1158                 msg->type = LDAP_TAG_AddResponse;
1159                 asn1_start_tag(data, tag);
1160                 ldap_decode_response(msg, data, r);
1161                 asn1_end_tag(data);
1162                 break;
1163         }
1164
1165         case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1166                 struct ldap_DelRequest *r = &msg->r.DelRequest;
1167                 int len;
1168                 char *dn;
1169                 msg->type = LDAP_TAG_DelRequest;
1170                 asn1_start_tag(data,
1171                                ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
1172                 len = asn1_tag_remaining(data);
1173                 if (len == -1) {
1174                         return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1175                 }
1176                 dn = talloc_array(msg, char, len+1);
1177                 if (dn == NULL)
1178                         break;
1179                 asn1_read(data, dn, len);
1180                 dn[len] = '\0';
1181                 r->dn = dn;
1182                 asn1_end_tag(data);
1183                 break;
1184         }
1185
1186         case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1187                 struct ldap_Result *r = &msg->r.DelResponse;
1188                 msg->type = LDAP_TAG_DelResponse;
1189                 asn1_start_tag(data, tag);
1190                 ldap_decode_response(msg, data, r);
1191                 asn1_end_tag(data);
1192                 break;
1193         }
1194
1195         case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1196                 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1197                 msg->type = LDAP_TAG_ModifyDNRequest;
1198                 asn1_start_tag(data,
1199                                ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
1200                 asn1_read_OctetString_talloc(msg, data, &r->dn);
1201                 asn1_read_OctetString_talloc(msg, data, &r->newrdn);
1202                 asn1_read_BOOLEAN(data, &r->deleteolddn);
1203                 r->newsuperior = NULL;
1204                 if (asn1_tag_remaining(data) > 0) {
1205                         int len;
1206                         char *newsup;
1207                         asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1208                         len = asn1_tag_remaining(data);
1209                         if (len == -1) {
1210                                 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1211                         }
1212                         newsup = talloc_array(msg, char, len+1);
1213                         if (newsup == NULL) {
1214                                 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1215                         }
1216                         asn1_read(data, newsup, len);
1217                         newsup[len] = '\0';
1218                         r->newsuperior = newsup;
1219                         asn1_end_tag(data);
1220                 }
1221                 asn1_end_tag(data);
1222                 break;
1223         }
1224
1225         case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1226                 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1227                 msg->type = LDAP_TAG_ModifyDNResponse;
1228                 asn1_start_tag(data, tag);
1229                 ldap_decode_response(msg, data, r);
1230                 asn1_end_tag(data);
1231                 break;
1232         }
1233
1234         case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1235                 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1236                 msg->type = LDAP_TAG_CompareRequest;
1237                 asn1_start_tag(data,
1238                                ASN1_APPLICATION(LDAP_TAG_CompareRequest));
1239                 asn1_read_OctetString_talloc(msg, data, &r->dn);
1240                 asn1_start_tag(data, ASN1_SEQUENCE(0));
1241                 asn1_read_OctetString_talloc(msg, data, &r->attribute);
1242                 asn1_read_OctetString(data, msg, &r->value);
1243                 if (r->value.data) {
1244                         talloc_steal(msg, r->value.data);
1245                 }
1246                 asn1_end_tag(data);
1247                 asn1_end_tag(data);
1248                 break;
1249         }
1250
1251         case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1252                 struct ldap_Result *r = &msg->r.CompareResponse;
1253                 msg->type = LDAP_TAG_CompareResponse;
1254                 asn1_start_tag(data, tag);
1255                 ldap_decode_response(msg, data, r);
1256                 asn1_end_tag(data);
1257                 break;
1258         }
1259
1260         case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1261                 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1262                 msg->type = LDAP_TAG_AbandonRequest;
1263                 asn1_start_tag(data, tag);
1264                 asn1_read_implicit_Integer(data, &r->messageid);
1265                 asn1_end_tag(data);
1266                 break;
1267         }
1268
1269         case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1270                 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1271                 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1272
1273                 msg->type = LDAP_TAG_ExtendedRequest;
1274                 asn1_start_tag(data,tag);
1275                 if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
1276                         return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1277                 }
1278                 r->oid = blob2string_talloc(msg, tmp_blob);
1279                 data_blob_free(&tmp_blob);
1280                 if (!r->oid) {
1281                         return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1282                 }
1283
1284                 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1285                         asn1_read_ContextSimple(data, 1, &tmp_blob);
1286                         r->value = talloc(msg, DATA_BLOB);
1287                         if (!r->value) {
1288                                 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1289                         }
1290                         *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1291                         data_blob_free(&tmp_blob);
1292                 } else {
1293                         r->value = NULL;
1294                 }
1295
1296                 asn1_end_tag(data);
1297                 break;
1298         }
1299
1300         case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1301                 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1302                 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1303
1304                 msg->type = LDAP_TAG_ExtendedResponse;
1305                 asn1_start_tag(data, tag);              
1306                 ldap_decode_response(msg, data, &r->response);
1307
1308                 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(10))) {
1309                         asn1_read_ContextSimple(data, 1, &tmp_blob);
1310                         r->oid = blob2string_talloc(msg, tmp_blob);
1311                         data_blob_free(&tmp_blob);
1312                         if (!r->oid) {
1313                                 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1314                         }
1315                 } else {
1316                         r->oid = NULL;
1317                 }
1318
1319                 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(11))) {
1320                         asn1_read_ContextSimple(data, 1, &tmp_blob);
1321                         r->value = talloc(msg, DATA_BLOB);
1322                         if (!r->value) {
1323                                 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1324                         }
1325                         *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1326                         data_blob_free(&tmp_blob);
1327                 } else {
1328                         r->value = NULL;
1329                 }
1330
1331                 asn1_end_tag(data);
1332                 break;
1333         }
1334         default: 
1335                 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1336         }
1337
1338         msg->controls = NULL;
1339         msg->controls_decoded = NULL;
1340
1341         if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1342                 int i = 0;
1343                 struct ldb_control **ctrl = NULL;
1344                 bool *decoded = NULL;
1345
1346                 asn1_start_tag(data, ASN1_CONTEXT(0));
1347
1348                 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1349                         DATA_BLOB value;
1350                         /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1351
1352                         ctrl = talloc_realloc(msg, ctrl, struct ldb_control *, i+2);
1353                         if (!ctrl) {
1354                                 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1355                         }
1356
1357                         decoded = talloc_realloc(msg, decoded, bool, i+1);
1358                         if (!decoded) {
1359                                 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1360                         }
1361
1362                         ctrl[i] = talloc(ctrl, struct ldb_control);
1363                         if (!ctrl[i]) {
1364                                 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1365                         }
1366
1367                         if (!ldap_decode_control_wrapper(ctrl, data, ctrl[i], &value)) {
1368                                 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1369                         }
1370                         
1371                         if (!ldap_decode_control_value(ctrl, value, ctrl[i])) {
1372                                 if (ctrl[i]->critical) {
1373                                         ctrl[i]->data = NULL;
1374                                         decoded[i] = false;
1375                                         i++;
1376                                 } else {
1377                                         talloc_free(ctrl[i]);
1378                                         ctrl[i] = NULL;
1379                                 }
1380                         } else {
1381                                 decoded[i] = true;
1382                                 i++;
1383                         }
1384                 }
1385
1386                 if (ctrl != NULL) {
1387                         ctrl[i] = NULL;
1388                 }
1389
1390                 msg->controls = ctrl;
1391                 msg->controls_decoded = decoded;
1392
1393                 asn1_end_tag(data);
1394         }
1395
1396         asn1_end_tag(data);
1397         if ((data->has_error) || (data->nesting != NULL)) {
1398                 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1399         }
1400         return NT_STATUS_OK;
1401 }
1402
1403
1404 /*
1405   return NT_STATUS_OK if a blob has enough bytes in it to be a full
1406   ldap packet. Set packet_size if true.
1407 */
1408 NTSTATUS ldap_full_packet(void *private_data, DATA_BLOB blob, size_t *packet_size)
1409 {
1410         return asn1_full_tag(blob, ASN1_SEQUENCE(0), packet_size);
1411 }