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