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