s4:dsdb: add support for DSDB_OPENLDAP_DEREFERENCE_CONTROL
[kai/samba.git] / source4 / libcli / ldap / ldap_controls.c
1 /* 
2    Unix SMB/CIFS mplementation.
3    LDAP protocol helper functions for SAMBA
4    
5    Copyright (C) Simo Sorce 2005
6     
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19    
20 */
21
22 #include "includes.h"
23 #include "../lib/util/asn1.h"
24 #include "libcli/ldap/ldap.h"
25 #include "lib/ldb/include/ldb.h"
26 #include "libcli/ldap/ldap_proto.h"
27 #include "dsdb/samdb/samdb.h"
28
29 struct control_handler {
30         const char *oid;
31         bool (*decode)(void *mem_ctx, DATA_BLOB in, void **out);
32         bool (*encode)(void *mem_ctx, void *in, DATA_BLOB *out);
33 };
34
35 static bool decode_server_sort_response(void *mem_ctx, DATA_BLOB in, void **out)
36 {
37         DATA_BLOB attr;
38         struct asn1_data *data = asn1_init(mem_ctx);
39         struct ldb_sort_resp_control *lsrc;
40
41         if (!data) return false;
42
43         if (!asn1_load(data, in)) {
44                 return false;
45         }
46
47         lsrc = talloc(mem_ctx, struct ldb_sort_resp_control);
48         if (!lsrc) {
49                 return false;
50         }
51
52         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
53                 return false;
54         }
55
56         if (!asn1_read_enumerated(data, &(lsrc->result))) {
57                 return false;
58         }
59
60         lsrc->attr_desc = NULL;
61         if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
62                 if (!asn1_read_OctetString(data, mem_ctx, &attr)) {
63                         return false;
64                 }
65                 lsrc->attr_desc = talloc_strndup(lsrc, (const char *)attr.data, attr.length);
66                 if (!lsrc->attr_desc) {
67                         return false;
68                 }
69         }
70
71         if (!asn1_end_tag(data)) {
72                 return false;
73         }
74
75         *out = lsrc;
76
77         return true;
78 }
79
80 static bool decode_server_sort_request(void *mem_ctx, DATA_BLOB in, void **out)
81 {
82         DATA_BLOB attr;
83         DATA_BLOB rule;
84         struct asn1_data *data = asn1_init(mem_ctx);
85         struct ldb_server_sort_control **lssc;
86         int num;
87
88         if (!data) return false;
89
90         if (!asn1_load(data, in)) {
91                 return false;
92         }
93
94         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
95                 return false;
96         }
97
98         lssc = NULL;
99
100         for (num = 0; asn1_peek_tag(data, ASN1_SEQUENCE(0)); num++) {
101                 lssc = talloc_realloc(mem_ctx, lssc, struct ldb_server_sort_control *, num + 2);
102                 if (!lssc) {
103                         return false;
104                 }
105                 lssc[num] = talloc_zero(lssc, struct ldb_server_sort_control);
106                 if (!lssc[num]) {
107                         return false;
108                 }
109
110                 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
111                         return false;
112                 }
113
114                 if (!asn1_read_OctetString(data, mem_ctx, &attr)) {
115                         return false;
116                 }
117
118                 lssc[num]->attributeName = talloc_strndup(lssc[num], (const char *)attr.data, attr.length);
119                 if (!lssc [num]->attributeName) {
120                         return false;
121                 }
122         
123                 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
124                         if (!asn1_read_OctetString(data, mem_ctx, &rule)) {
125                                 return false;
126                         }
127                         lssc[num]->orderingRule = talloc_strndup(lssc[num], (const char *)rule.data, rule.length);
128                         if (!lssc[num]->orderingRule) {
129                                 return false;
130                         }
131                 }
132
133                 if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
134                         bool reverse;
135                         if (!asn1_read_BOOLEAN(data, &reverse)) {
136                         return false;
137                         }
138                         lssc[num]->reverse = reverse;
139                 }
140         
141                 if (!asn1_end_tag(data)) {
142                         return false;
143                 }
144         }
145
146         if (lssc != NULL) {
147                 lssc[num] = NULL;
148         }
149
150         if (!asn1_end_tag(data)) {
151                 return false;
152         }
153
154         *out = lssc;
155
156         return true;
157 }
158
159 static bool decode_extended_dn_request(void *mem_ctx, DATA_BLOB in, void **out)
160 {
161         struct asn1_data *data;
162         struct ldb_extended_dn_control *ledc;
163
164         /* The content of this control is optional */
165         if (in.length == 0) {
166                 *out = NULL;
167                 return true;
168         }
169
170         data = asn1_init(mem_ctx);
171         if (!data) return false;
172
173         if (!asn1_load(data, in)) {
174                 return false;
175         }
176
177         ledc = talloc(mem_ctx, struct ldb_extended_dn_control);
178         if (!ledc) {
179                 return false;
180         }
181
182         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
183                 return false;
184         }
185
186         if (!asn1_read_Integer(data, &(ledc->type))) {
187                 return false;
188         }
189         
190         if (!asn1_end_tag(data)) {
191                 return false;
192         }
193
194         *out = ledc;
195
196         return true;
197 }
198
199 static bool decode_sd_flags_request(void *mem_ctx, DATA_BLOB in, void **out)
200 {
201         struct asn1_data *data = asn1_init(mem_ctx);
202         struct ldb_sd_flags_control *lsdfc;
203
204         if (!data) return false;
205
206         if (!asn1_load(data, in)) {
207                 return false;
208         }
209
210         lsdfc = talloc(mem_ctx, struct ldb_sd_flags_control);
211         if (!lsdfc) {
212                 return false;
213         }
214
215         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
216                 return false;
217         }
218
219         if (!asn1_read_Integer(data, &(lsdfc->secinfo_flags))) {
220                 return false;
221         }
222
223         if (!asn1_end_tag(data)) {
224                 return false;
225         }
226
227         *out = lsdfc;
228
229         return true;
230 }
231
232 static bool decode_search_options_request(void *mem_ctx, DATA_BLOB in, void **out)
233 {
234         struct asn1_data *data = asn1_init(mem_ctx);
235         struct ldb_search_options_control *lsoc;
236
237         if (!data) return false;
238
239         if (!asn1_load(data, in)) {
240                 return false;
241         }
242
243         lsoc = talloc(mem_ctx, struct ldb_search_options_control);
244         if (!lsoc) {
245                 return false;
246         }
247
248         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
249                 return false;
250         }
251
252         if (!asn1_read_Integer(data, &(lsoc->search_options))) {
253                 return false;
254         }
255
256         if (!asn1_end_tag(data)) {
257                 return false;
258         }
259
260         *out = lsoc;
261
262         return true;
263 }
264
265 static bool decode_paged_results_request(void *mem_ctx, DATA_BLOB in, void **out)
266 {
267         DATA_BLOB cookie;
268         struct asn1_data *data = asn1_init(mem_ctx);
269         struct ldb_paged_control *lprc;
270
271         if (!data) return false;
272
273         if (!asn1_load(data, in)) {
274                 return false;
275         }
276
277         lprc = talloc(mem_ctx, struct ldb_paged_control);
278         if (!lprc) {
279                 return false;
280         }
281
282         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
283                 return false;
284         }
285
286         if (!asn1_read_Integer(data, &(lprc->size))) {
287                 return false;
288         }
289         
290         if (!asn1_read_OctetString(data, mem_ctx, &cookie)) {
291                 return false;
292         }
293         lprc->cookie_len = cookie.length;
294         if (lprc->cookie_len) {
295                 lprc->cookie = talloc_memdup(lprc, cookie.data, cookie.length);
296
297                 if (!(lprc->cookie)) {
298                         return false;
299                 }
300         } else {
301                 lprc->cookie = NULL;
302         }
303
304         if (!asn1_end_tag(data)) {
305                 return false;
306         }
307
308         *out = lprc;
309
310         return true;
311 }
312
313 static bool decode_dirsync_request(void *mem_ctx, DATA_BLOB in, void **out)
314 {
315         DATA_BLOB cookie;
316         struct asn1_data *data = asn1_init(mem_ctx);
317         struct ldb_dirsync_control *ldc;
318
319         if (!data) return false;
320
321         if (!asn1_load(data, in)) {
322                 return false;
323         }
324
325         ldc = talloc(mem_ctx, struct ldb_dirsync_control);
326         if (!ldc) {
327                 return false;
328         }
329
330         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
331                 return false;
332         }
333
334         if (!asn1_read_Integer(data, &(ldc->flags))) {
335                 return false;
336         }
337         
338         if (!asn1_read_Integer(data, &(ldc->max_attributes))) {
339                 return false;
340         }
341         
342         if (!asn1_read_OctetString(data, mem_ctx, &cookie)) {
343                 return false;
344         }
345         ldc->cookie_len = cookie.length;
346         if (ldc->cookie_len) {
347                 ldc->cookie = talloc_memdup(ldc, cookie.data, cookie.length);
348
349                 if (!(ldc->cookie)) {
350                         return false;
351                 }
352         } else {
353                 ldc->cookie = NULL;
354         }
355
356         if (!asn1_end_tag(data)) {
357                 return false;
358         }
359
360         *out = ldc;
361
362         return true;
363 }
364
365 /* seem that this controls has 2 forms one in case it is used with
366  * a Search Request and another when used ina Search Response
367  */
368 static bool decode_asq_control(void *mem_ctx, DATA_BLOB in, void **out)
369 {
370         DATA_BLOB source_attribute;
371         struct asn1_data *data = asn1_init(mem_ctx);
372         struct ldb_asq_control *lac;
373
374         if (!data) return false;
375
376         if (!asn1_load(data, in)) {
377                 return false;
378         }
379
380         lac = talloc(mem_ctx, struct ldb_asq_control);
381         if (!lac) {
382                 return false;
383         }
384
385         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
386                 return false;
387         }
388
389         if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
390
391                 if (!asn1_read_OctetString(data, mem_ctx, &source_attribute)) {
392                         return false;
393                 }
394                 lac->src_attr_len = source_attribute.length;
395                 if (lac->src_attr_len) {
396                         lac->source_attribute = talloc_strndup(lac, (const char *)source_attribute.data, source_attribute.length);
397
398                         if (!(lac->source_attribute)) {
399                                 return false;
400                         }
401                 } else {
402                         lac->source_attribute = NULL;
403                 }
404
405                 lac->request = 1;
406
407         } else if (asn1_peek_tag(data, ASN1_ENUMERATED)) {
408
409                 if (!asn1_read_enumerated(data, &(lac->result))) {
410                         return false;
411                 }
412
413                 lac->request = 0;
414
415         } else {
416                 return false;
417         }
418
419         if (!asn1_end_tag(data)) {
420                 return false;
421         }
422
423         *out = lac;
424
425         return true;
426 }
427
428 static bool decode_domain_scope_request(void *mem_ctx, DATA_BLOB in, void **out)
429 {
430         if (in.length != 0) {
431                 return false;
432         }
433
434         return true;
435 }
436
437 static bool decode_notification_request(void *mem_ctx, DATA_BLOB in, void **out)
438 {
439         if (in.length != 0) {
440                 return false;
441         }
442
443         return true;
444 }
445
446 static bool decode_show_deleted_request(void *mem_ctx, DATA_BLOB in, void **out)
447 {
448         if (in.length != 0) {
449                 return false;
450         }
451
452         return true;
453 }
454
455 static bool decode_permissive_modify_request(void *mem_ctx, DATA_BLOB in, void **out)
456 {
457         if (in.length != 0) {
458                 return false;
459         }
460
461         return true;
462 }
463
464 static bool decode_manageDSAIT_request(void *mem_ctx, DATA_BLOB in, void **out)
465 {
466         if (in.length != 0) {
467                 return false;
468         }
469
470         return true;
471 }
472
473 static bool decode_vlv_request(void *mem_ctx, DATA_BLOB in, void **out)
474 {
475         DATA_BLOB assertion_value, context_id;
476         struct asn1_data *data = asn1_init(mem_ctx);
477         struct ldb_vlv_req_control *lvrc;
478
479         if (!data) return false;
480
481         if (!asn1_load(data, in)) {
482                 return false;
483         }
484
485         lvrc = talloc(mem_ctx, struct ldb_vlv_req_control);
486         if (!lvrc) {
487                 return false;
488         }
489
490         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
491                 return false;
492         }
493
494         if (!asn1_read_Integer(data, &(lvrc->beforeCount))) {
495                 return false;
496         }
497         
498         if (!asn1_read_Integer(data, &(lvrc->afterCount))) {
499                 return false;
500         }
501
502         if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
503
504                 lvrc->type = 0;
505                 
506                 if (!asn1_start_tag(data, ASN1_CONTEXT(0))) {
507                         return false;
508                 }
509
510                 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
511                         return false;
512                 }
513
514                 if (!asn1_read_Integer(data, &(lvrc->match.byOffset.offset))) {
515                         return false;
516                 }
517
518                 if (!asn1_read_Integer(data, &(lvrc->match.byOffset.contentCount))) {
519                         return false;
520                 }
521
522                 if (!asn1_end_tag(data)) { /*SEQUENCE*/
523                         return false;
524                 }
525
526                 if (!asn1_end_tag(data)) { /*CONTEXT*/
527                         return false;
528                 }
529
530         } else {
531
532                 lvrc->type = 1;
533
534                 if (!asn1_start_tag(data, ASN1_CONTEXT(1))) {
535                         return false;
536                 }
537
538                 if (!asn1_read_OctetString(data, mem_ctx, &assertion_value)) {
539                         return false;
540                 }
541                 lvrc->match.gtOrEq.value_len = assertion_value.length;
542                 if (lvrc->match.gtOrEq.value_len) {
543                         lvrc->match.gtOrEq.value = talloc_memdup(lvrc, assertion_value.data, assertion_value.length);
544
545                         if (!(lvrc->match.gtOrEq.value)) {
546                                 return false;
547                         }
548                 } else {
549                         lvrc->match.gtOrEq.value = NULL;
550                 }
551
552                 if (!asn1_end_tag(data)) { /*CONTEXT*/
553                         return false;
554                 }
555         }
556
557         if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
558                 if (!asn1_read_OctetString(data, mem_ctx, &context_id)) {
559                         return false;
560                 }
561                 lvrc->ctxid_len = context_id.length;
562                 if (lvrc->ctxid_len) {
563                         lvrc->contextId = talloc_memdup(lvrc, context_id.data, context_id.length);
564
565                         if (!(lvrc->contextId)) {
566                                 return false;
567                         }
568                 } else {
569                         lvrc->contextId = NULL;
570                 }
571         } else {
572                 lvrc->contextId = NULL;
573                 lvrc->ctxid_len = 0;
574         }
575
576         if (!asn1_end_tag(data)) {
577                 return false;
578         }
579
580         *out = lvrc;
581
582         return true;
583 }
584
585 static bool decode_vlv_response(void *mem_ctx, DATA_BLOB in, void **out)
586 {
587         DATA_BLOB context_id;
588         struct asn1_data *data = asn1_init(mem_ctx);
589         struct ldb_vlv_resp_control *lvrc;
590
591         if (!data) return false;
592
593         if (!asn1_load(data, in)) {
594                 return false;
595         }
596
597         lvrc = talloc(mem_ctx, struct ldb_vlv_resp_control);
598         if (!lvrc) {
599                 return false;
600         }
601
602         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
603                 return false;
604         }
605
606         if (!asn1_read_Integer(data, &(lvrc->targetPosition))) {
607                 return false;
608         }
609         
610         if (!asn1_read_Integer(data, &(lvrc->contentCount))) {
611                 return false;
612         }
613         
614         if (!asn1_read_enumerated(data, &(lvrc->vlv_result))) {
615                 return false;
616         }
617
618         if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
619                 if (!asn1_read_OctetString(data, mem_ctx, &context_id)) {
620                         return false;
621                 }
622                 lvrc->contextId = talloc_strndup(lvrc, (const char *)context_id.data, context_id.length);
623                 if (!lvrc->contextId) {
624                         return false;
625                 }
626                 lvrc->ctxid_len = context_id.length;
627         } else {
628                 lvrc->contextId = NULL;
629                 lvrc->ctxid_len = 0;
630         }
631
632         if (!asn1_end_tag(data)) {
633                 return false;
634         }
635
636         *out = lvrc;
637
638         return true;
639 }
640
641 static bool encode_server_sort_response(void *mem_ctx, void *in, DATA_BLOB *out)
642 {
643         struct ldb_sort_resp_control *lsrc = talloc_get_type(in, struct ldb_sort_resp_control);
644         struct asn1_data *data = asn1_init(mem_ctx);
645
646         if (!data) return false;
647
648         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
649                 return false;
650         }
651
652         if (!asn1_write_enumerated(data, lsrc->result)) {
653                 return false;
654         }
655
656         if (lsrc->attr_desc) {
657                 if (!asn1_write_OctetString(data, lsrc->attr_desc, strlen(lsrc->attr_desc))) {
658                         return false;
659                 }
660         }
661
662         if (!asn1_pop_tag(data)) {
663                 return false;
664         }
665
666         *out = data_blob_talloc(mem_ctx, data->data, data->length);
667         if (out->data == NULL) {
668                 return false;
669         }
670         talloc_free(data);
671
672         return true;
673 }
674
675 static bool encode_server_sort_request(void *mem_ctx, void *in, DATA_BLOB *out)
676 {
677         struct ldb_server_sort_control **lssc = talloc_get_type(in, struct ldb_server_sort_control *);
678         struct asn1_data *data = asn1_init(mem_ctx);
679         int num;
680
681         if (!data) return false;
682
683         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
684                 return false;
685         }
686
687         for (num = 0; lssc[num]; num++) {
688                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
689                         return false;
690                 }
691                 
692                 if (!asn1_write_OctetString(data, lssc[num]->attributeName, strlen(lssc[num]->attributeName))) {
693                         return false;
694                 }
695
696                 if (lssc[num]->orderingRule) {
697                         if (!asn1_write_OctetString(data, lssc[num]->orderingRule, strlen(lssc[num]->orderingRule))) {
698                                 return false;
699                         }
700                 }
701
702                 if (lssc[num]->reverse) {
703                         if (!asn1_write_BOOLEAN(data, lssc[num]->reverse)) {
704                                 return false;
705                         }
706                 }
707
708                 if (!asn1_pop_tag(data)) {
709                         return false;
710                 }
711         }
712
713         if (!asn1_pop_tag(data)) {
714                 return false;
715         }
716
717         *out = data_blob_talloc(mem_ctx, data->data, data->length);
718         if (out->data == NULL) {
719                 return false;
720         }
721         talloc_free(data);
722
723         return true;
724 }
725
726 static bool encode_extended_dn_request(void *mem_ctx, void *in, DATA_BLOB *out)
727 {
728         struct ldb_extended_dn_control *ledc = talloc_get_type(in, struct ldb_extended_dn_control);
729         struct asn1_data *data;
730
731         if (!in) {
732                 *out = data_blob(NULL, 0);
733                 return true;
734         }
735
736         data = asn1_init(mem_ctx);
737
738         if (!data) return false;
739
740         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
741                 return false;
742         }
743
744         if (!asn1_write_Integer(data, ledc->type)) {
745                 return false;
746         }
747
748         if (!asn1_pop_tag(data)) {
749                 return false;
750         }
751
752         *out = data_blob_talloc(mem_ctx, data->data, data->length);
753         if (out->data == NULL) {
754                 return false;
755         }
756         talloc_free(data);
757
758         return true;
759 }
760
761 static bool encode_sd_flags_request(void *mem_ctx, void *in, DATA_BLOB *out)
762 {
763         struct ldb_sd_flags_control *lsdfc = talloc_get_type(in, struct ldb_sd_flags_control);
764         struct asn1_data *data = asn1_init(mem_ctx);
765
766         if (!data) return false;
767
768         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
769                 return false;
770         }
771
772         if (!asn1_write_Integer(data, lsdfc->secinfo_flags)) {
773                 return false;
774         }
775
776         if (!asn1_pop_tag(data)) {
777                 return false;
778         }
779
780         *out = data_blob_talloc(mem_ctx, data->data, data->length);
781         if (out->data == NULL) {
782                 return false;
783         }
784         talloc_free(data);
785
786         return true;
787 }
788
789 static bool encode_search_options_request(void *mem_ctx, void *in, DATA_BLOB *out)
790 {
791         struct ldb_search_options_control *lsoc = talloc_get_type(in, struct ldb_search_options_control);
792         struct asn1_data *data = asn1_init(mem_ctx);
793
794         if (!data) return false;
795
796         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
797                 return false;
798         }
799
800         if (!asn1_write_Integer(data, lsoc->search_options)) {
801                 return false;
802         }
803
804         if (!asn1_pop_tag(data)) {
805                 return false;
806         }
807
808         *out = data_blob_talloc(mem_ctx, data->data, data->length);
809         if (out->data == NULL) {
810                 return false;
811         }
812         talloc_free(data);
813
814         return true;
815 }
816
817 static bool encode_paged_results_request(void *mem_ctx, void *in, DATA_BLOB *out)
818 {
819         struct ldb_paged_control *lprc = talloc_get_type(in, struct ldb_paged_control);
820         struct asn1_data *data = asn1_init(mem_ctx);
821
822         if (!data) return false;
823
824         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
825                 return false;
826         }
827
828         if (!asn1_write_Integer(data, lprc->size)) {
829                 return false;
830         }
831
832         if (!asn1_write_OctetString(data, lprc->cookie, lprc->cookie_len)) {
833                 return false;
834         }       
835
836         if (!asn1_pop_tag(data)) {
837                 return false;
838         }
839
840         *out = data_blob_talloc(mem_ctx, data->data, data->length);
841         if (out->data == NULL) {
842                 return false;
843         }
844         talloc_free(data);
845
846         return true;
847 }
848
849 /* seem that this controls has 2 forms one in case it is used with
850  * a Search Request and another when used ina Search Response
851  */
852 static bool encode_asq_control(void *mem_ctx, void *in, DATA_BLOB *out)
853 {
854         struct ldb_asq_control *lac = talloc_get_type(in, struct ldb_asq_control);
855         struct asn1_data *data = asn1_init(mem_ctx);
856
857         if (!data) return false;
858
859         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
860                 return false;
861         }
862
863         if (lac->request) {
864
865                 if (!asn1_write_OctetString(data, lac->source_attribute, lac->src_attr_len)) {
866                         return false;
867                 }
868         } else {
869                 if (!asn1_write_enumerated(data, lac->result)) {
870                         return false;
871                 }
872         }
873
874         if (!asn1_pop_tag(data)) {
875                 return false;
876         }
877
878         *out = data_blob_talloc(mem_ctx, data->data, data->length);
879         if (out->data == NULL) {
880                 return false;
881         }
882         talloc_free(data);
883
884         return true;
885 }
886
887 static bool encode_dirsync_request(void *mem_ctx, void *in, DATA_BLOB *out)
888 {
889         struct ldb_dirsync_control *ldc = talloc_get_type(in, struct ldb_dirsync_control);
890         struct asn1_data *data = asn1_init(mem_ctx);
891
892         if (!data) return false;
893
894         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
895                 return false;
896         }
897
898         if (!asn1_write_Integer(data, ldc->flags)) {
899                 return false;
900         }
901
902         if (!asn1_write_Integer(data, ldc->max_attributes)) {
903                 return false;
904         }
905
906         if (!asn1_write_OctetString(data, ldc->cookie, ldc->cookie_len)) {
907                 return false;
908         }       
909
910         if (!asn1_pop_tag(data)) {
911                 return false;
912         }
913
914         *out = data_blob_talloc(mem_ctx, data->data, data->length);
915         if (out->data == NULL) {
916                 return false;
917         }
918         talloc_free(data);
919
920         return true;
921 }
922
923 static bool encode_domain_scope_request(void *mem_ctx, void *in, DATA_BLOB *out)
924 {
925         if (in) {
926                 return false;
927         }
928
929         *out = data_blob(NULL, 0);
930         return true;
931 }
932
933 static bool encode_notification_request(void *mem_ctx, void *in, DATA_BLOB *out)
934 {
935         if (in) {
936                 return false;
937         }
938
939         *out = data_blob(NULL, 0);
940         return true;
941 }
942
943 static bool encode_show_deleted_request(void *mem_ctx, void *in, DATA_BLOB *out)
944 {
945         if (in) {
946                 return false;
947         }
948
949         *out = data_blob(NULL, 0);
950         return true;
951 }
952
953 static bool encode_permissive_modify_request(void *mem_ctx, void *in, DATA_BLOB *out)
954 {
955         if (in) {
956                 return false;
957         }
958
959         *out = data_blob(NULL, 0);
960         return true;
961 }
962
963 static bool encode_manageDSAIT_request(void *mem_ctx, void *in, DATA_BLOB *out)
964 {
965         if (in) {
966                 return false;
967         }
968
969         *out = data_blob(NULL, 0);
970         return true;
971 }
972
973 static bool encode_vlv_request(void *mem_ctx, void *in, DATA_BLOB *out)
974 {
975         struct ldb_vlv_req_control *lvrc = talloc_get_type(in, struct ldb_vlv_req_control);
976         struct asn1_data *data = asn1_init(mem_ctx);
977
978         if (!data) return false;
979
980         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
981                 return false;
982         }
983
984         if (!asn1_write_Integer(data, lvrc->beforeCount)) {
985                 return false;
986         }
987
988         if (!asn1_write_Integer(data, lvrc->afterCount)) {
989                 return false;
990         }
991
992         if (lvrc->type == 0) {
993                 if (!asn1_push_tag(data, ASN1_CONTEXT(0))) {
994                         return false;
995                 }
996                 
997                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
998                         return false;
999                 }
1000                 
1001                 if (!asn1_write_Integer(data, lvrc->match.byOffset.offset)) {
1002                         return false;
1003                 }
1004
1005                 if (!asn1_write_Integer(data, lvrc->match.byOffset.contentCount)) {
1006                         return false;
1007                 }
1008
1009                 if (!asn1_pop_tag(data)) { /*SEQUENCE*/
1010                         return false;
1011                 }
1012
1013                 if (!asn1_pop_tag(data)) { /*CONTEXT*/
1014                         return false;
1015                 }
1016         } else {
1017                 if (!asn1_push_tag(data, ASN1_CONTEXT(1))) {
1018                         return false;
1019                 }
1020                 
1021                 if (!asn1_write_OctetString(data, lvrc->match.gtOrEq.value, lvrc->match.gtOrEq.value_len)) {
1022                         return false;
1023                 }
1024
1025                 if (!asn1_pop_tag(data)) { /*CONTEXT*/
1026                         return false;
1027                 }
1028         }
1029
1030         if (lvrc->ctxid_len) {
1031                 if (!asn1_write_OctetString(data, lvrc->contextId, lvrc->ctxid_len)) {
1032                         return false;
1033                 }
1034         }
1035
1036         if (!asn1_pop_tag(data)) {
1037                 return false;
1038         }
1039
1040         *out = data_blob_talloc(mem_ctx, data->data, data->length);
1041         if (out->data == NULL) {
1042                 return false;
1043         }
1044         talloc_free(data);
1045
1046         return true;
1047 }
1048
1049 static bool encode_vlv_response(void *mem_ctx, void *in, DATA_BLOB *out)
1050 {
1051         struct ldb_vlv_resp_control *lvrc = talloc_get_type(in, struct ldb_vlv_resp_control);
1052         struct asn1_data *data = asn1_init(mem_ctx);
1053
1054         if (!data) return false;
1055
1056         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1057                 return false;
1058         }
1059
1060         if (!asn1_write_Integer(data, lvrc->targetPosition)) {
1061                 return false;
1062         }
1063
1064         if (!asn1_write_Integer(data, lvrc->contentCount)) {
1065                 return false;
1066         }
1067
1068         if (!asn1_write_enumerated(data, lvrc->vlv_result)) {
1069                 return false;
1070         }
1071
1072         if (lvrc->ctxid_len) {
1073                 if (!asn1_write_OctetString(data, lvrc->contextId, lvrc->ctxid_len)) {
1074                         return false;
1075                 }
1076         }
1077
1078         if (!asn1_pop_tag(data)) {
1079                 return false;
1080         }
1081
1082         *out = data_blob_talloc(mem_ctx, data->data, data->length);
1083         if (out->data == NULL) {
1084                 return false;
1085         }
1086         talloc_free(data);
1087
1088         return true;
1089 }
1090
1091 static bool encode_openldap_dereference(void *mem_ctx, void *in, DATA_BLOB *out)
1092 {
1093         struct dsdb_openldap_dereference_control *control = talloc_get_type(in, struct dsdb_openldap_dereference_control);
1094         int i,j;
1095         struct asn1_data *data = asn1_init(mem_ctx);
1096
1097         if (!data) return false;
1098         
1099         if (!control) return false;
1100         
1101         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1102                 return false;
1103         }
1104         
1105         for (i=0; control->dereference && control->dereference[i]; i++) {
1106                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1107                         return false;
1108                 }
1109                 if (!asn1_write_OctetString(data, control->dereference[i]->source_attribute, strlen(control->dereference[i]->source_attribute))) {
1110                         return false;
1111                 }
1112                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1113                         return false;
1114                 }
1115                 for (j=0; control->dereference && control->dereference[i]->dereference_attribute[j]; j++) {
1116                         if (!asn1_write_OctetString(data, control->dereference[i]->dereference_attribute[j], 
1117                                                     strlen(control->dereference[i]->dereference_attribute[j]))) {
1118                                 return false;
1119                         }
1120                 }
1121                 
1122                 asn1_pop_tag(data);
1123                 asn1_pop_tag(data);
1124         }
1125         asn1_pop_tag(data);
1126
1127         *out = data_blob_talloc(mem_ctx, data->data, data->length);
1128         if (out->data == NULL) {
1129                 return false;
1130         }
1131         talloc_free(data);
1132         return true;
1133 }
1134
1135 static bool decode_openldap_dereference(void *mem_ctx, DATA_BLOB in, void **out)
1136 {
1137         struct asn1_data *data = asn1_init(mem_ctx);
1138         struct dsdb_openldap_dereference_result_control *control;
1139         struct dsdb_openldap_dereference_result **r = NULL;
1140         int i = 0;
1141         if (!data) return false;
1142
1143         control = talloc(mem_ctx, struct dsdb_openldap_dereference_result_control);
1144         if (!control) return false;
1145
1146         if (!asn1_load(data, in)) {
1147                 return false;
1148         }
1149
1150         control = talloc(mem_ctx, struct dsdb_openldap_dereference_result_control);
1151         if (!control) {
1152                 return false;
1153         }
1154
1155         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
1156                 return false;
1157         }
1158
1159         while (asn1_tag_remaining(data) > 0) {                                  
1160                 r = talloc_realloc(control, r, struct dsdb_openldap_dereference_result *, i + 2);
1161                 if (!r) {
1162                         return false;
1163                 }
1164                 r[i] = talloc_zero(r, struct dsdb_openldap_dereference_result);
1165                 if (!r[i]) {
1166                         return false;
1167                 }
1168
1169                 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
1170                         return false;
1171                 }
1172                 
1173                 asn1_read_OctetString_talloc(r[i], data, &r[i]->source_attribute);
1174                 asn1_read_OctetString_talloc(r[i], data, &r[i]->dereferenced_dn);
1175                 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1176                         if (!asn1_start_tag(data, ASN1_CONTEXT(0))) {
1177                                 return false;
1178                         }
1179                         
1180                         ldap_decode_attribs_bare(r, data, &r[i]->attributes,
1181                                                  &r[i]->num_attributes);
1182                         
1183                         if (!asn1_end_tag(data)) {
1184                                 return false;
1185                         }
1186                 }
1187                 if (!asn1_end_tag(data)) {
1188                         return false;
1189                 }
1190                 i++;
1191                 r[i] = NULL;
1192         }
1193
1194         if (!asn1_end_tag(data)) {
1195                 return false;
1196         }
1197
1198         control->attributes = r;
1199         *out = control;
1200
1201         return true;
1202 }
1203
1204 struct control_handler ldap_known_controls[] = {
1205         { "1.2.840.113556.1.4.319", decode_paged_results_request, encode_paged_results_request },
1206         { "1.2.840.113556.1.4.529", decode_extended_dn_request, encode_extended_dn_request },
1207         { "1.2.840.113556.1.4.473", decode_server_sort_request, encode_server_sort_request },
1208         { "1.2.840.113556.1.4.474", decode_server_sort_response, encode_server_sort_response },
1209         { "1.2.840.113556.1.4.1504", decode_asq_control, encode_asq_control },
1210         { "1.2.840.113556.1.4.841", decode_dirsync_request, encode_dirsync_request },
1211         { "1.2.840.113556.1.4.528", decode_notification_request, encode_notification_request },
1212         { "1.2.840.113556.1.4.417", decode_show_deleted_request, encode_show_deleted_request },
1213         { "1.2.840.113556.1.4.1413", decode_permissive_modify_request, encode_permissive_modify_request },
1214         { "1.2.840.113556.1.4.801", decode_sd_flags_request, encode_sd_flags_request },
1215         { "1.2.840.113556.1.4.1339", decode_domain_scope_request, encode_domain_scope_request },
1216         { "1.2.840.113556.1.4.1340", decode_search_options_request, encode_search_options_request },
1217         { "2.16.840.1.113730.3.4.2", decode_manageDSAIT_request, encode_manageDSAIT_request },
1218         { "2.16.840.1.113730.3.4.9", decode_vlv_request, encode_vlv_request },
1219         { "2.16.840.1.113730.3.4.10", decode_vlv_response, encode_vlv_response },
1220 /* DSDB_CONTROL_CURRENT_PARTITION_OID is internal only, and has no network representation */
1221         { "1.3.6.1.4.1.7165.4.3.2", NULL, NULL },
1222 /* DSDB_EXTENDED_REPLICATED_OBJECTS_OID is internal only, and has no network representation */
1223         { "1.3.6.1.4.1.7165.4.4.1", NULL, NULL },
1224         { DSDB_OPENLDAP_DEREFERENCE_CONTROL, decode_openldap_dereference, encode_openldap_dereference},
1225         { NULL, NULL, NULL }
1226 };
1227
1228 bool ldap_decode_control_value(void *mem_ctx, DATA_BLOB value, struct ldb_control *ctrl)
1229 {
1230         int i;
1231
1232         for (i = 0; ldap_known_controls[i].oid != NULL; i++) {
1233                 if (strcmp(ldap_known_controls[i].oid, ctrl->oid) == 0) {
1234                         if (!ldap_known_controls[i].decode || !ldap_known_controls[i].decode(mem_ctx, value, &ctrl->data)) {
1235                                 return false;
1236                         }
1237                         break;
1238                 }
1239         }
1240         if (ldap_known_controls[i].oid == NULL) {
1241                 return false;
1242         }
1243
1244         return true;
1245 }
1246
1247 bool ldap_decode_control_wrapper(void *mem_ctx, struct asn1_data *data, struct ldb_control *ctrl, DATA_BLOB *value)
1248 {
1249         DATA_BLOB oid;
1250
1251         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
1252                 return false;
1253         }
1254
1255         if (!asn1_read_OctetString(data, mem_ctx, &oid)) {
1256                 return false;
1257         }
1258         ctrl->oid = talloc_strndup(mem_ctx, (char *)oid.data, oid.length);
1259         if (!ctrl->oid) {
1260                 return false;
1261         }
1262
1263         if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
1264                 bool critical;
1265                 if (!asn1_read_BOOLEAN(data, &critical)) {
1266                         return false;
1267                 }
1268                 ctrl->critical = critical;
1269         } else {
1270                 ctrl->critical = false;
1271         }
1272
1273         ctrl->data = NULL;
1274
1275         if (!asn1_peek_tag(data, ASN1_OCTET_STRING)) {
1276                 *value = data_blob(NULL, 0);
1277                 goto end_tag;
1278         }
1279
1280         if (!asn1_read_OctetString(data, mem_ctx, value)) {
1281                 return false;
1282         }
1283
1284 end_tag:
1285         if (!asn1_end_tag(data)) {
1286                 return false;
1287         }
1288
1289         return true;
1290 }
1291
1292 bool ldap_encode_control(void *mem_ctx, struct asn1_data *data, struct ldb_control *ctrl)
1293 {
1294         DATA_BLOB value;
1295         int i;
1296
1297         for (i = 0; ldap_known_controls[i].oid != NULL; i++) {
1298                 if (strcmp(ldap_known_controls[i].oid, ctrl->oid) == 0) {
1299                         if (!ldap_known_controls[i].encode) {
1300                                 if (ctrl->critical) {
1301                                         return false;
1302                                 } else {
1303                                         /* not encoding this control */
1304                                         return true;
1305                                 }
1306                         }
1307                         if (!ldap_known_controls[i].encode(mem_ctx, ctrl->data, &value)) {
1308                                 return false;
1309                         }
1310                         break;
1311                 }
1312         }
1313         if (ldap_known_controls[i].oid == NULL) {
1314                 return false;
1315         }
1316
1317         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1318                 return false;
1319         }
1320
1321         if (!asn1_write_OctetString(data, ctrl->oid, strlen(ctrl->oid))) {
1322                 return false;
1323         }
1324
1325         if (ctrl->critical) {
1326                 if (!asn1_write_BOOLEAN(data, ctrl->critical)) {
1327                         return false;
1328                 }
1329         }
1330
1331         if (!ctrl->data) {
1332                 goto pop_tag;
1333         }
1334
1335         if (!asn1_write_OctetString(data, value.data, value.length)) {
1336                 return false;
1337         }
1338
1339 pop_tag:
1340         if (!asn1_pop_tag(data)) {
1341                 return false;
1342         }
1343
1344         return true;
1345 }