s4-dsdb: added support for LDB_CONTROL_RODC_DCPROMO_OID
[metze/samba/wip.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/libcli_ldap.h"
25 #include "lib/ldb/include/ldb.h"
26 #include "libcli/ldap/ldap_proto.h"
27 #include "dsdb/samdb/samdb.h"
28
29 static bool decode_server_sort_response(void *mem_ctx, DATA_BLOB in, void *_out)
30 {
31         void **out = (void **)_out;
32         DATA_BLOB attr;
33         struct asn1_data *data = asn1_init(mem_ctx);
34         struct ldb_sort_resp_control *lsrc;
35
36         if (!data) return false;
37
38         if (!asn1_load(data, in)) {
39                 return false;
40         }
41
42         lsrc = talloc(mem_ctx, struct ldb_sort_resp_control);
43         if (!lsrc) {
44                 return false;
45         }
46
47         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
48                 return false;
49         }
50
51         if (!asn1_read_enumerated(data, &(lsrc->result))) {
52                 return false;
53         }
54
55         lsrc->attr_desc = NULL;
56         if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
57                 if (!asn1_read_OctetString(data, mem_ctx, &attr)) {
58                         return false;
59                 }
60                 lsrc->attr_desc = talloc_strndup(lsrc, (const char *)attr.data, attr.length);
61                 if (!lsrc->attr_desc) {
62                         return false;
63                 }
64         }
65
66         if (!asn1_end_tag(data)) {
67                 return false;
68         }
69
70         *out = lsrc;
71
72         return true;
73 }
74
75 static bool decode_server_sort_request(void *mem_ctx, DATA_BLOB in, void *_out)
76 {
77         void **out = (void **)_out;
78         DATA_BLOB attr;
79         DATA_BLOB rule;
80         struct asn1_data *data = asn1_init(mem_ctx);
81         struct ldb_server_sort_control **lssc;
82         int num;
83
84         if (!data) return false;
85
86         if (!asn1_load(data, in)) {
87                 return false;
88         }
89
90         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
91                 return false;
92         }
93
94         lssc = NULL;
95
96         for (num = 0; asn1_peek_tag(data, ASN1_SEQUENCE(0)); num++) {
97                 lssc = talloc_realloc(mem_ctx, lssc, struct ldb_server_sort_control *, num + 2);
98                 if (!lssc) {
99                         return false;
100                 }
101                 lssc[num] = talloc_zero(lssc, struct ldb_server_sort_control);
102                 if (!lssc[num]) {
103                         return false;
104                 }
105
106                 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
107                         return false;
108                 }
109
110                 if (!asn1_read_OctetString(data, mem_ctx, &attr)) {
111                         return false;
112                 }
113
114                 lssc[num]->attributeName = talloc_strndup(lssc[num], (const char *)attr.data, attr.length);
115                 if (!lssc [num]->attributeName) {
116                         return false;
117                 }
118         
119                 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
120                         if (!asn1_read_OctetString(data, mem_ctx, &rule)) {
121                                 return false;
122                         }
123                         lssc[num]->orderingRule = talloc_strndup(lssc[num], (const char *)rule.data, rule.length);
124                         if (!lssc[num]->orderingRule) {
125                                 return false;
126                         }
127                 }
128
129                 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
130                         bool reverse;
131                         if (!asn1_read_BOOLEAN_context(data, &reverse, 1)) {
132                         return false;
133                         }
134                         lssc[num]->reverse = reverse;
135                 }
136         
137                 if (!asn1_end_tag(data)) {
138                         return false;
139                 }
140         }
141
142         if (lssc != NULL) {
143                 lssc[num] = NULL;
144         }
145
146         if (!asn1_end_tag(data)) {
147                 return false;
148         }
149
150         *out = lssc;
151
152         return true;
153 }
154
155 static bool decode_extended_dn_request(void *mem_ctx, DATA_BLOB in, void *_out)
156 {
157         void **out = (void **)_out;
158         struct asn1_data *data;
159         struct ldb_extended_dn_control *ledc;
160
161         /* The content of this control is optional */
162         if (in.length == 0) {
163                 *out = NULL;
164                 return true;
165         }
166
167         data = asn1_init(mem_ctx);
168         if (!data) return false;
169
170         if (!asn1_load(data, in)) {
171                 return false;
172         }
173
174         ledc = talloc(mem_ctx, struct ldb_extended_dn_control);
175         if (!ledc) {
176                 return false;
177         }
178
179         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
180                 return false;
181         }
182
183         if (!asn1_read_Integer(data, &(ledc->type))) {
184                 return false;
185         }
186         
187         if (!asn1_end_tag(data)) {
188                 return false;
189         }
190
191         *out = ledc;
192
193         return true;
194 }
195
196 static bool decode_sd_flags_request(void *mem_ctx, DATA_BLOB in, void *_out)
197 {
198         void **out = (void **)_out;
199         struct asn1_data *data = asn1_init(mem_ctx);
200         struct ldb_sd_flags_control *lsdfc;
201
202         if (!data) return false;
203
204         if (!asn1_load(data, in)) {
205                 return false;
206         }
207
208         lsdfc = talloc(mem_ctx, struct ldb_sd_flags_control);
209         if (!lsdfc) {
210                 return false;
211         }
212
213         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
214                 return false;
215         }
216
217         if (!asn1_read_Integer(data, (int *) &(lsdfc->secinfo_flags))) {
218                 return false;
219         }
220
221         if (!asn1_end_tag(data)) {
222                 return false;
223         }
224
225         *out = lsdfc;
226
227         return true;
228 }
229
230 static bool decode_search_options_request(void *mem_ctx, DATA_BLOB in, void *_out)
231 {
232         void **out = (void **)_out;
233         struct asn1_data *data = asn1_init(mem_ctx);
234         struct ldb_search_options_control *lsoc;
235
236         if (!data) return false;
237
238         if (!asn1_load(data, in)) {
239                 return false;
240         }
241
242         lsoc = talloc(mem_ctx, struct ldb_search_options_control);
243         if (!lsoc) {
244                 return false;
245         }
246
247         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
248                 return false;
249         }
250
251         if (!asn1_read_Integer(data, (int *) &(lsoc->search_options))) {
252                 return false;
253         }
254
255         if (!asn1_end_tag(data)) {
256                 return false;
257         }
258
259         *out = lsoc;
260
261         return true;
262 }
263
264 static bool decode_paged_results_request(void *mem_ctx, DATA_BLOB in, void *_out)
265 {
266         void **out = (void **)_out;
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         void **out = (void **)_out;
316         DATA_BLOB cookie;
317         struct asn1_data *data = asn1_init(mem_ctx);
318         struct ldb_dirsync_control *ldc;
319
320         if (!data) return false;
321
322         if (!asn1_load(data, in)) {
323                 return false;
324         }
325
326         ldc = talloc(mem_ctx, struct ldb_dirsync_control);
327         if (!ldc) {
328                 return false;
329         }
330
331         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
332                 return false;
333         }
334
335         if (!asn1_read_Integer(data, &(ldc->flags))) {
336                 return false;
337         }
338         
339         if (!asn1_read_Integer(data, &(ldc->max_attributes))) {
340                 return false;
341         }
342         
343         if (!asn1_read_OctetString(data, mem_ctx, &cookie)) {
344                 return false;
345         }
346         ldc->cookie_len = cookie.length;
347         if (ldc->cookie_len) {
348                 ldc->cookie = talloc_memdup(ldc, cookie.data, cookie.length);
349
350                 if (!(ldc->cookie)) {
351                         return false;
352                 }
353         } else {
354                 ldc->cookie = NULL;
355         }
356
357         if (!asn1_end_tag(data)) {
358                 return false;
359         }
360
361         *out = ldc;
362
363         return true;
364 }
365
366 /* seem that this controls has 2 forms one in case it is used with
367  * a Search Request and another when used ina Search Response
368  */
369 static bool decode_asq_control(void *mem_ctx, DATA_BLOB in, void *_out)
370 {
371         void **out = (void **)_out;
372         DATA_BLOB source_attribute;
373         struct asn1_data *data = asn1_init(mem_ctx);
374         struct ldb_asq_control *lac;
375
376         if (!data) return false;
377
378         if (!asn1_load(data, in)) {
379                 return false;
380         }
381
382         lac = talloc(mem_ctx, struct ldb_asq_control);
383         if (!lac) {
384                 return false;
385         }
386
387         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
388                 return false;
389         }
390
391         if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
392
393                 if (!asn1_read_OctetString(data, mem_ctx, &source_attribute)) {
394                         return false;
395                 }
396                 lac->src_attr_len = source_attribute.length;
397                 if (lac->src_attr_len) {
398                         lac->source_attribute = talloc_strndup(lac, (const char *)source_attribute.data, source_attribute.length);
399
400                         if (!(lac->source_attribute)) {
401                                 return false;
402                         }
403                 } else {
404                         lac->source_attribute = NULL;
405                 }
406
407                 lac->request = 1;
408
409         } else if (asn1_peek_tag(data, ASN1_ENUMERATED)) {
410
411                 if (!asn1_read_enumerated(data, &(lac->result))) {
412                         return false;
413                 }
414
415                 lac->request = 0;
416
417         } else {
418                 return false;
419         }
420
421         if (!asn1_end_tag(data)) {
422                 return false;
423         }
424
425         *out = lac;
426
427         return true;
428 }
429
430 static bool decode_vlv_request(void *mem_ctx, DATA_BLOB in, void *_out)
431 {
432         void **out = (void **)_out;
433         DATA_BLOB assertion_value, context_id;
434         struct asn1_data *data = asn1_init(mem_ctx);
435         struct ldb_vlv_req_control *lvrc;
436
437         if (!data) return false;
438
439         if (!asn1_load(data, in)) {
440                 return false;
441         }
442
443         lvrc = talloc(mem_ctx, struct ldb_vlv_req_control);
444         if (!lvrc) {
445                 return false;
446         }
447
448         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
449                 return false;
450         }
451
452         if (!asn1_read_Integer(data, &(lvrc->beforeCount))) {
453                 return false;
454         }
455         
456         if (!asn1_read_Integer(data, &(lvrc->afterCount))) {
457                 return false;
458         }
459
460         if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
461
462                 lvrc->type = 0;
463                 
464                 if (!asn1_start_tag(data, ASN1_CONTEXT(0))) {
465                         return false;
466                 }
467
468                 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
469                         return false;
470                 }
471
472                 if (!asn1_read_Integer(data, &(lvrc->match.byOffset.offset))) {
473                         return false;
474                 }
475
476                 if (!asn1_read_Integer(data, &(lvrc->match.byOffset.contentCount))) {
477                         return false;
478                 }
479
480                 if (!asn1_end_tag(data)) { /*SEQUENCE*/
481                         return false;
482                 }
483
484                 if (!asn1_end_tag(data)) { /*CONTEXT*/
485                         return false;
486                 }
487
488         } else {
489
490                 lvrc->type = 1;
491
492                 if (!asn1_start_tag(data, ASN1_CONTEXT(1))) {
493                         return false;
494                 }
495
496                 if (!asn1_read_OctetString(data, mem_ctx, &assertion_value)) {
497                         return false;
498                 }
499                 lvrc->match.gtOrEq.value_len = assertion_value.length;
500                 if (lvrc->match.gtOrEq.value_len) {
501                         lvrc->match.gtOrEq.value = talloc_memdup(lvrc, assertion_value.data, assertion_value.length);
502
503                         if (!(lvrc->match.gtOrEq.value)) {
504                                 return false;
505                         }
506                 } else {
507                         lvrc->match.gtOrEq.value = NULL;
508                 }
509
510                 if (!asn1_end_tag(data)) { /*CONTEXT*/
511                         return false;
512                 }
513         }
514
515         if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
516                 if (!asn1_read_OctetString(data, mem_ctx, &context_id)) {
517                         return false;
518                 }
519                 lvrc->ctxid_len = context_id.length;
520                 if (lvrc->ctxid_len) {
521                         lvrc->contextId = talloc_memdup(lvrc, context_id.data, context_id.length);
522
523                         if (!(lvrc->contextId)) {
524                                 return false;
525                         }
526                 } else {
527                         lvrc->contextId = NULL;
528                 }
529         } else {
530                 lvrc->contextId = NULL;
531                 lvrc->ctxid_len = 0;
532         }
533
534         if (!asn1_end_tag(data)) {
535                 return false;
536         }
537
538         *out = lvrc;
539
540         return true;
541 }
542
543 static bool decode_vlv_response(void *mem_ctx, DATA_BLOB in, void *_out)
544 {
545         void **out = (void **)_out;
546         DATA_BLOB context_id;
547         struct asn1_data *data = asn1_init(mem_ctx);
548         struct ldb_vlv_resp_control *lvrc;
549
550         if (!data) return false;
551
552         if (!asn1_load(data, in)) {
553                 return false;
554         }
555
556         lvrc = talloc(mem_ctx, struct ldb_vlv_resp_control);
557         if (!lvrc) {
558                 return false;
559         }
560
561         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
562                 return false;
563         }
564
565         if (!asn1_read_Integer(data, &(lvrc->targetPosition))) {
566                 return false;
567         }
568         
569         if (!asn1_read_Integer(data, &(lvrc->contentCount))) {
570                 return false;
571         }
572         
573         if (!asn1_read_enumerated(data, &(lvrc->vlv_result))) {
574                 return false;
575         }
576
577         if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
578                 if (!asn1_read_OctetString(data, mem_ctx, &context_id)) {
579                         return false;
580                 }
581                 lvrc->contextId = talloc_strndup(lvrc, (const char *)context_id.data, context_id.length);
582                 if (!lvrc->contextId) {
583                         return false;
584                 }
585                 lvrc->ctxid_len = context_id.length;
586         } else {
587                 lvrc->contextId = NULL;
588                 lvrc->ctxid_len = 0;
589         }
590
591         if (!asn1_end_tag(data)) {
592                 return false;
593         }
594
595         *out = lvrc;
596
597         return true;
598 }
599
600 static bool encode_server_sort_response(void *mem_ctx, void *in, DATA_BLOB *out)
601 {
602         struct ldb_sort_resp_control *lsrc = talloc_get_type(in, struct ldb_sort_resp_control);
603         struct asn1_data *data = asn1_init(mem_ctx);
604
605         if (!data) return false;
606
607         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
608                 return false;
609         }
610
611         if (!asn1_write_enumerated(data, lsrc->result)) {
612                 return false;
613         }
614
615         if (lsrc->attr_desc) {
616                 if (!asn1_write_OctetString(data, lsrc->attr_desc, strlen(lsrc->attr_desc))) {
617                         return false;
618                 }
619         }
620
621         if (!asn1_pop_tag(data)) {
622                 return false;
623         }
624
625         *out = data_blob_talloc(mem_ctx, data->data, data->length);
626         if (out->data == NULL) {
627                 return false;
628         }
629         talloc_free(data);
630
631         return true;
632 }
633
634 static bool encode_server_sort_request(void *mem_ctx, void *in, DATA_BLOB *out)
635 {
636         struct ldb_server_sort_control **lssc = talloc_get_type(in, struct ldb_server_sort_control *);
637         struct asn1_data *data = asn1_init(mem_ctx);
638         int num;
639
640         if (!data) return false;
641
642         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
643                 return false;
644         }
645
646         /*
647           RFC2891 section 1.1:
648             SortKeyList ::= SEQUENCE OF SEQUENCE {
649               attributeType   AttributeDescription,
650               orderingRule    [0] MatchingRuleId OPTIONAL,
651               reverseOrder    [1] BOOLEAN DEFAULT FALSE }
652         */
653         for (num = 0; lssc[num]; num++) {
654                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
655                         return false;
656                 }
657                 
658                 if (!asn1_write_OctetString(data, lssc[num]->attributeName, strlen(lssc[num]->attributeName))) {
659                         return false;
660                 }
661
662                 if (lssc[num]->orderingRule) {
663                         if (!asn1_write_OctetString(data, lssc[num]->orderingRule, strlen(lssc[num]->orderingRule))) {
664                                 return false;
665                         }
666                 }
667
668                 if (lssc[num]->reverse) {
669                         if (!asn1_write_BOOLEAN_context(data, lssc[num]->reverse, 1)) {
670                                 return false;
671                         }
672                 }
673
674                 if (!asn1_pop_tag(data)) {
675                         return false;
676                 }
677         }
678
679         if (!asn1_pop_tag(data)) {
680                 return false;
681         }
682
683         *out = data_blob_talloc(mem_ctx, data->data, data->length);
684         if (out->data == NULL) {
685                 return false;
686         }
687         talloc_free(data);
688
689         return true;
690 }
691
692 static bool encode_extended_dn_request(void *mem_ctx, void *in, DATA_BLOB *out)
693 {
694         struct ldb_extended_dn_control *ledc = talloc_get_type(in, struct ldb_extended_dn_control);
695         struct asn1_data *data;
696
697         if (!in) {
698                 *out = data_blob(NULL, 0);
699                 return true;
700         }
701
702         data = asn1_init(mem_ctx);
703
704         if (!data) return false;
705
706         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
707                 return false;
708         }
709
710         if (!asn1_write_Integer(data, ledc->type)) {
711                 return false;
712         }
713
714         if (!asn1_pop_tag(data)) {
715                 return false;
716         }
717
718         *out = data_blob_talloc(mem_ctx, data->data, data->length);
719         if (out->data == NULL) {
720                 return false;
721         }
722         talloc_free(data);
723
724         return true;
725 }
726
727 static bool encode_sd_flags_request(void *mem_ctx, void *in, DATA_BLOB *out)
728 {
729         struct ldb_sd_flags_control *lsdfc = talloc_get_type(in, struct ldb_sd_flags_control);
730         struct asn1_data *data = asn1_init(mem_ctx);
731
732         if (!data) return false;
733
734         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
735                 return false;
736         }
737
738         if (!asn1_write_Integer(data, lsdfc->secinfo_flags)) {
739                 return false;
740         }
741
742         if (!asn1_pop_tag(data)) {
743                 return false;
744         }
745
746         *out = data_blob_talloc(mem_ctx, data->data, data->length);
747         if (out->data == NULL) {
748                 return false;
749         }
750         talloc_free(data);
751
752         return true;
753 }
754
755 static bool encode_search_options_request(void *mem_ctx, void *in, DATA_BLOB *out)
756 {
757         struct ldb_search_options_control *lsoc = talloc_get_type(in, struct ldb_search_options_control);
758         struct asn1_data *data = asn1_init(mem_ctx);
759
760         if (!data) return false;
761
762         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
763                 return false;
764         }
765
766         if (!asn1_write_Integer(data, lsoc->search_options)) {
767                 return false;
768         }
769
770         if (!asn1_pop_tag(data)) {
771                 return false;
772         }
773
774         *out = data_blob_talloc(mem_ctx, data->data, data->length);
775         if (out->data == NULL) {
776                 return false;
777         }
778         talloc_free(data);
779
780         return true;
781 }
782
783 static bool encode_paged_results_request(void *mem_ctx, void *in, DATA_BLOB *out)
784 {
785         struct ldb_paged_control *lprc = talloc_get_type(in, struct ldb_paged_control);
786         struct asn1_data *data = asn1_init(mem_ctx);
787
788         if (!data) return false;
789
790         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
791                 return false;
792         }
793
794         if (!asn1_write_Integer(data, lprc->size)) {
795                 return false;
796         }
797
798         if (!asn1_write_OctetString(data, lprc->cookie, lprc->cookie_len)) {
799                 return false;
800         }       
801
802         if (!asn1_pop_tag(data)) {
803                 return false;
804         }
805
806         *out = data_blob_talloc(mem_ctx, data->data, data->length);
807         if (out->data == NULL) {
808                 return false;
809         }
810         talloc_free(data);
811
812         return true;
813 }
814
815 /* seem that this controls has 2 forms one in case it is used with
816  * a Search Request and another when used ina Search Response
817  */
818 static bool encode_asq_control(void *mem_ctx, void *in, DATA_BLOB *out)
819 {
820         struct ldb_asq_control *lac = talloc_get_type(in, struct ldb_asq_control);
821         struct asn1_data *data = asn1_init(mem_ctx);
822
823         if (!data) return false;
824
825         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
826                 return false;
827         }
828
829         if (lac->request) {
830
831                 if (!asn1_write_OctetString(data, lac->source_attribute, lac->src_attr_len)) {
832                         return false;
833                 }
834         } else {
835                 if (!asn1_write_enumerated(data, lac->result)) {
836                         return false;
837                 }
838         }
839
840         if (!asn1_pop_tag(data)) {
841                 return false;
842         }
843
844         *out = data_blob_talloc(mem_ctx, data->data, data->length);
845         if (out->data == NULL) {
846                 return false;
847         }
848         talloc_free(data);
849
850         return true;
851 }
852
853 static bool encode_dirsync_request(void *mem_ctx, void *in, DATA_BLOB *out)
854 {
855         struct ldb_dirsync_control *ldc = talloc_get_type(in, struct ldb_dirsync_control);
856         struct asn1_data *data = asn1_init(mem_ctx);
857
858         if (!data) return false;
859
860         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
861                 return false;
862         }
863
864         if (!asn1_write_Integer(data, ldc->flags)) {
865                 return false;
866         }
867
868         if (!asn1_write_Integer(data, ldc->max_attributes)) {
869                 return false;
870         }
871
872         if (!asn1_write_OctetString(data, ldc->cookie, ldc->cookie_len)) {
873                 return false;
874         }       
875
876         if (!asn1_pop_tag(data)) {
877                 return false;
878         }
879
880         *out = data_blob_talloc(mem_ctx, data->data, data->length);
881         if (out->data == NULL) {
882                 return false;
883         }
884         talloc_free(data);
885
886         return true;
887 }
888
889 static bool encode_vlv_request(void *mem_ctx, void *in, DATA_BLOB *out)
890 {
891         struct ldb_vlv_req_control *lvrc = talloc_get_type(in, struct ldb_vlv_req_control);
892         struct asn1_data *data = asn1_init(mem_ctx);
893
894         if (!data) return false;
895
896         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
897                 return false;
898         }
899
900         if (!asn1_write_Integer(data, lvrc->beforeCount)) {
901                 return false;
902         }
903
904         if (!asn1_write_Integer(data, lvrc->afterCount)) {
905                 return false;
906         }
907
908         if (lvrc->type == 0) {
909                 if (!asn1_push_tag(data, ASN1_CONTEXT(0))) {
910                         return false;
911                 }
912                 
913                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
914                         return false;
915                 }
916                 
917                 if (!asn1_write_Integer(data, lvrc->match.byOffset.offset)) {
918                         return false;
919                 }
920
921                 if (!asn1_write_Integer(data, lvrc->match.byOffset.contentCount)) {
922                         return false;
923                 }
924
925                 if (!asn1_pop_tag(data)) { /*SEQUENCE*/
926                         return false;
927                 }
928
929                 if (!asn1_pop_tag(data)) { /*CONTEXT*/
930                         return false;
931                 }
932         } else {
933                 if (!asn1_push_tag(data, ASN1_CONTEXT(1))) {
934                         return false;
935                 }
936                 
937                 if (!asn1_write_OctetString(data, lvrc->match.gtOrEq.value, lvrc->match.gtOrEq.value_len)) {
938                         return false;
939                 }
940
941                 if (!asn1_pop_tag(data)) { /*CONTEXT*/
942                         return false;
943                 }
944         }
945
946         if (lvrc->ctxid_len) {
947                 if (!asn1_write_OctetString(data, lvrc->contextId, lvrc->ctxid_len)) {
948                         return false;
949                 }
950         }
951
952         if (!asn1_pop_tag(data)) {
953                 return false;
954         }
955
956         *out = data_blob_talloc(mem_ctx, data->data, data->length);
957         if (out->data == NULL) {
958                 return false;
959         }
960         talloc_free(data);
961
962         return true;
963 }
964
965 static bool encode_vlv_response(void *mem_ctx, void *in, DATA_BLOB *out)
966 {
967         struct ldb_vlv_resp_control *lvrc = talloc_get_type(in, struct ldb_vlv_resp_control);
968         struct asn1_data *data = asn1_init(mem_ctx);
969
970         if (!data) return false;
971
972         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
973                 return false;
974         }
975
976         if (!asn1_write_Integer(data, lvrc->targetPosition)) {
977                 return false;
978         }
979
980         if (!asn1_write_Integer(data, lvrc->contentCount)) {
981                 return false;
982         }
983
984         if (!asn1_write_enumerated(data, lvrc->vlv_result)) {
985                 return false;
986         }
987
988         if (lvrc->ctxid_len) {
989                 if (!asn1_write_OctetString(data, lvrc->contextId, lvrc->ctxid_len)) {
990                         return false;
991                 }
992         }
993
994         if (!asn1_pop_tag(data)) {
995                 return false;
996         }
997
998         *out = data_blob_talloc(mem_ctx, data->data, data->length);
999         if (out->data == NULL) {
1000                 return false;
1001         }
1002         talloc_free(data);
1003
1004         return true;
1005 }
1006
1007 static bool encode_openldap_dereference(void *mem_ctx, void *in, DATA_BLOB *out)
1008 {
1009         struct dsdb_openldap_dereference_control *control = talloc_get_type(in, struct dsdb_openldap_dereference_control);
1010         int i,j;
1011         struct asn1_data *data = asn1_init(mem_ctx);
1012
1013         if (!data) return false;
1014         
1015         if (!control) return false;
1016         
1017         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1018                 return false;
1019         }
1020         
1021         for (i=0; control->dereference && control->dereference[i]; i++) {
1022                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1023                         return false;
1024                 }
1025                 if (!asn1_write_OctetString(data, control->dereference[i]->source_attribute, strlen(control->dereference[i]->source_attribute))) {
1026                         return false;
1027                 }
1028                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1029                         return false;
1030                 }
1031                 for (j=0; control->dereference && control->dereference[i]->dereference_attribute[j]; j++) {
1032                         if (!asn1_write_OctetString(data, control->dereference[i]->dereference_attribute[j], 
1033                                                     strlen(control->dereference[i]->dereference_attribute[j]))) {
1034                                 return false;
1035                         }
1036                 }
1037                 
1038                 asn1_pop_tag(data);
1039                 asn1_pop_tag(data);
1040         }
1041         asn1_pop_tag(data);
1042
1043         *out = data_blob_talloc(mem_ctx, data->data, data->length);
1044         if (out->data == NULL) {
1045                 return false;
1046         }
1047         talloc_free(data);
1048         return true;
1049 }
1050
1051 static bool decode_openldap_dereference(void *mem_ctx, DATA_BLOB in, void *_out)
1052 {
1053         void **out = (void **)_out;
1054         struct asn1_data *data = asn1_init(mem_ctx);
1055         struct dsdb_openldap_dereference_result_control *control;
1056         struct dsdb_openldap_dereference_result **r = NULL;
1057         int i = 0;
1058         if (!data) return false;
1059
1060         control = talloc(mem_ctx, struct dsdb_openldap_dereference_result_control);
1061         if (!control) return false;
1062
1063         if (!asn1_load(data, in)) {
1064                 return false;
1065         }
1066
1067         control = talloc(mem_ctx, struct dsdb_openldap_dereference_result_control);
1068         if (!control) {
1069                 return false;
1070         }
1071
1072         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
1073                 return false;
1074         }
1075
1076         while (asn1_tag_remaining(data) > 0) {                                  
1077                 r = talloc_realloc(control, r, struct dsdb_openldap_dereference_result *, i + 2);
1078                 if (!r) {
1079                         return false;
1080                 }
1081                 r[i] = talloc_zero(r, struct dsdb_openldap_dereference_result);
1082                 if (!r[i]) {
1083                         return false;
1084                 }
1085
1086                 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
1087                         return false;
1088                 }
1089                 
1090                 asn1_read_OctetString_talloc(r[i], data, &r[i]->source_attribute);
1091                 asn1_read_OctetString_talloc(r[i], data, &r[i]->dereferenced_dn);
1092                 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1093                         if (!asn1_start_tag(data, ASN1_CONTEXT(0))) {
1094                                 return false;
1095                         }
1096                         
1097                         ldap_decode_attribs_bare(r, data, &r[i]->attributes,
1098                                                  &r[i]->num_attributes);
1099                         
1100                         if (!asn1_end_tag(data)) {
1101                                 return false;
1102                         }
1103                 }
1104                 if (!asn1_end_tag(data)) {
1105                         return false;
1106                 }
1107                 i++;
1108                 r[i] = NULL;
1109         }
1110
1111         if (!asn1_end_tag(data)) {
1112                 return false;
1113         }
1114
1115         control->attributes = r;
1116         *out = control;
1117
1118         return true;
1119 }
1120
1121 static bool encode_flag_request(void *mem_ctx, void *in, DATA_BLOB *out)
1122 {
1123         if (in) {
1124                 return false;
1125         }
1126
1127         *out = data_blob(NULL, 0);
1128         return true;
1129 }
1130
1131 static bool decode_flag_request(void *mem_ctx, DATA_BLOB in, void *_out)
1132 {
1133         if (in.length != 0) {
1134                 return false;
1135         }
1136
1137         return true;
1138 }
1139
1140 static const struct ldap_control_handler ldap_known_controls[] = {
1141         { "1.2.840.113556.1.4.319", decode_paged_results_request, encode_paged_results_request },
1142         { "1.2.840.113556.1.4.529", decode_extended_dn_request, encode_extended_dn_request },
1143         { "1.2.840.113556.1.4.473", decode_server_sort_request, encode_server_sort_request },
1144         { "1.2.840.113556.1.4.474", decode_server_sort_response, encode_server_sort_response },
1145         { "1.2.840.113556.1.4.1504", decode_asq_control, encode_asq_control },
1146         { "1.2.840.113556.1.4.841", decode_dirsync_request, encode_dirsync_request },
1147         { "1.2.840.113556.1.4.528", decode_flag_request, encode_flag_request },
1148         { "1.2.840.113556.1.4.805", decode_flag_request, encode_flag_request },
1149         { "1.2.840.113556.1.4.417", decode_flag_request, encode_flag_request },
1150         { "1.2.840.113556.1.4.2064", decode_flag_request, encode_flag_request },
1151         { "1.2.840.113556.1.4.2065", decode_flag_request, encode_flag_request },
1152         { "1.2.840.113556.1.4.1413", decode_flag_request, encode_flag_request },
1153         { "1.2.840.113556.1.4.801", decode_sd_flags_request, encode_sd_flags_request },
1154         { "1.2.840.113556.1.4.1339", decode_flag_request, encode_flag_request },
1155         { "1.2.840.113556.1.4.1340", decode_search_options_request, encode_search_options_request },
1156         { "2.16.840.1.113730.3.4.2", decode_flag_request, encode_flag_request },
1157         { "2.16.840.1.113730.3.4.9", decode_vlv_request, encode_vlv_request },
1158         { "2.16.840.1.113730.3.4.10", decode_vlv_response, encode_vlv_response },
1159 /* DSDB_CONTROL_CURRENT_PARTITION_OID is internal only, and has no network representation */
1160         { "1.3.6.1.4.1.7165.4.3.2", NULL, NULL },
1161 /* DSDB_CONTROL_DN_STORAGE_FORMAT_OID is internal only, and has no network representation */
1162         { "1.3.6.1.4.1.7165.4.3.4", NULL, NULL },
1163 /* LDB_CONTROL_REVEAL_INTERNALS is internal only, and has no network representation */
1164         { "1.3.6.1.4.1.7165.4.3.6", NULL, NULL },
1165 /* LDB_CONTROL_AS_SYSTEM_OID is internal only, and has no network representation */
1166         { "1.3.6.1.4.1.7165.4.3.7", NULL, NULL },
1167 /* DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID is internal only, and has no network representation */
1168         { "1.3.6.1.4.1.7165.4.3.8", NULL, NULL },
1169 /* DSDB_EXTENDED_REPLICATED_OBJECTS_OID is internal only, and has no network representation */
1170         { "1.3.6.1.4.1.7165.4.4.1", NULL, NULL },
1171         { DSDB_OPENLDAP_DEREFERENCE_CONTROL, decode_openldap_dereference, encode_openldap_dereference},
1172         { LDB_CONTROL_RELAX_OID, decode_flag_request, encode_flag_request },
1173         { LDB_CONTROL_RODC_DCPROMO_OID, decode_flag_request, encode_flag_request },
1174         { NULL, NULL, NULL }
1175 };
1176
1177 const struct ldap_control_handler *samba_ldap_control_handlers(void)
1178 {
1179         return ldap_known_controls;
1180 }
1181