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