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