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