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