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