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