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