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