Merge branch 'master' of git://git.samba.org/samba into teventfix
[samba.git] / source4 / libcli / ldap / ldap_controls.c
1 /* 
2    Unix SMB/CIFS mplementation.
3    LDAP protocol helper functions for SAMBA
4    
5    Copyright (C) Simo Sorce 2005
6     
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19    
20 */
21
22 #include "includes.h"
23 #include "../lib/util/asn1.h"
24 #include "libcli/ldap/ldap.h"
25 #include "lib/ldb/include/ldb.h"
26 #include "libcli/ldap/ldap_proto.h"
27 #include "dsdb/samdb/samdb.h"
28
29 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_BOOLEAN)) {
130                         bool reverse;
131                         if (!asn1_read_BOOLEAN(data, &reverse)) {
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, &(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, &(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_domain_scope_request(void *mem_ctx, DATA_BLOB in, void *_out)
431 {
432         if (in.length != 0) {
433                 return false;
434         }
435
436         return true;
437 }
438
439 static bool decode_notification_request(void *mem_ctx, DATA_BLOB in, void *_out)
440 {
441         if (in.length != 0) {
442                 return false;
443         }
444
445         return true;
446 }
447
448 static bool decode_show_deleted_request(void *mem_ctx, DATA_BLOB in, void *_out)
449 {
450         if (in.length != 0) {
451                 return false;
452         }
453
454         return true;
455 }
456
457 static bool decode_permissive_modify_request(void *mem_ctx, DATA_BLOB in, void *_out)
458 {
459         if (in.length != 0) {
460                 return false;
461         }
462
463         return true;
464 }
465
466 static bool decode_manageDSAIT_request(void *mem_ctx, DATA_BLOB in, void *_out)
467 {
468         if (in.length != 0) {
469                 return false;
470         }
471
472         return true;
473 }
474
475 static bool decode_vlv_request(void *mem_ctx, DATA_BLOB in, void *_out)
476 {
477         void **out = (void **)_out;
478         DATA_BLOB assertion_value, context_id;
479         struct asn1_data *data = asn1_init(mem_ctx);
480         struct ldb_vlv_req_control *lvrc;
481
482         if (!data) return false;
483
484         if (!asn1_load(data, in)) {
485                 return false;
486         }
487
488         lvrc = talloc(mem_ctx, struct ldb_vlv_req_control);
489         if (!lvrc) {
490                 return false;
491         }
492
493         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
494                 return false;
495         }
496
497         if (!asn1_read_Integer(data, &(lvrc->beforeCount))) {
498                 return false;
499         }
500         
501         if (!asn1_read_Integer(data, &(lvrc->afterCount))) {
502                 return false;
503         }
504
505         if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
506
507                 lvrc->type = 0;
508                 
509                 if (!asn1_start_tag(data, ASN1_CONTEXT(0))) {
510                         return false;
511                 }
512
513                 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
514                         return false;
515                 }
516
517                 if (!asn1_read_Integer(data, &(lvrc->match.byOffset.offset))) {
518                         return false;
519                 }
520
521                 if (!asn1_read_Integer(data, &(lvrc->match.byOffset.contentCount))) {
522                         return false;
523                 }
524
525                 if (!asn1_end_tag(data)) { /*SEQUENCE*/
526                         return false;
527                 }
528
529                 if (!asn1_end_tag(data)) { /*CONTEXT*/
530                         return false;
531                 }
532
533         } else {
534
535                 lvrc->type = 1;
536
537                 if (!asn1_start_tag(data, ASN1_CONTEXT(1))) {
538                         return false;
539                 }
540
541                 if (!asn1_read_OctetString(data, mem_ctx, &assertion_value)) {
542                         return false;
543                 }
544                 lvrc->match.gtOrEq.value_len = assertion_value.length;
545                 if (lvrc->match.gtOrEq.value_len) {
546                         lvrc->match.gtOrEq.value = talloc_memdup(lvrc, assertion_value.data, assertion_value.length);
547
548                         if (!(lvrc->match.gtOrEq.value)) {
549                                 return false;
550                         }
551                 } else {
552                         lvrc->match.gtOrEq.value = NULL;
553                 }
554
555                 if (!asn1_end_tag(data)) { /*CONTEXT*/
556                         return false;
557                 }
558         }
559
560         if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
561                 if (!asn1_read_OctetString(data, mem_ctx, &context_id)) {
562                         return false;
563                 }
564                 lvrc->ctxid_len = context_id.length;
565                 if (lvrc->ctxid_len) {
566                         lvrc->contextId = talloc_memdup(lvrc, context_id.data, context_id.length);
567
568                         if (!(lvrc->contextId)) {
569                                 return false;
570                         }
571                 } else {
572                         lvrc->contextId = NULL;
573                 }
574         } else {
575                 lvrc->contextId = NULL;
576                 lvrc->ctxid_len = 0;
577         }
578
579         if (!asn1_end_tag(data)) {
580                 return false;
581         }
582
583         *out = lvrc;
584
585         return true;
586 }
587
588 static bool decode_vlv_response(void *mem_ctx, DATA_BLOB in, void *_out)
589 {
590         void **out = (void **)_out;
591         DATA_BLOB context_id;
592         struct asn1_data *data = asn1_init(mem_ctx);
593         struct ldb_vlv_resp_control *lvrc;
594
595         if (!data) return false;
596
597         if (!asn1_load(data, in)) {
598                 return false;
599         }
600
601         lvrc = talloc(mem_ctx, struct ldb_vlv_resp_control);
602         if (!lvrc) {
603                 return false;
604         }
605
606         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
607                 return false;
608         }
609
610         if (!asn1_read_Integer(data, &(lvrc->targetPosition))) {
611                 return false;
612         }
613         
614         if (!asn1_read_Integer(data, &(lvrc->contentCount))) {
615                 return false;
616         }
617         
618         if (!asn1_read_enumerated(data, &(lvrc->vlv_result))) {
619                 return false;
620         }
621
622         if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
623                 if (!asn1_read_OctetString(data, mem_ctx, &context_id)) {
624                         return false;
625                 }
626                 lvrc->contextId = talloc_strndup(lvrc, (const char *)context_id.data, context_id.length);
627                 if (!lvrc->contextId) {
628                         return false;
629                 }
630                 lvrc->ctxid_len = context_id.length;
631         } else {
632                 lvrc->contextId = NULL;
633                 lvrc->ctxid_len = 0;
634         }
635
636         if (!asn1_end_tag(data)) {
637                 return false;
638         }
639
640         *out = lvrc;
641
642         return true;
643 }
644
645 static bool encode_server_sort_response(void *mem_ctx, void *in, DATA_BLOB *out)
646 {
647         struct ldb_sort_resp_control *lsrc = talloc_get_type(in, struct ldb_sort_resp_control);
648         struct asn1_data *data = asn1_init(mem_ctx);
649
650         if (!data) return false;
651
652         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
653                 return false;
654         }
655
656         if (!asn1_write_enumerated(data, lsrc->result)) {
657                 return false;
658         }
659
660         if (lsrc->attr_desc) {
661                 if (!asn1_write_OctetString(data, lsrc->attr_desc, strlen(lsrc->attr_desc))) {
662                         return false;
663                 }
664         }
665
666         if (!asn1_pop_tag(data)) {
667                 return false;
668         }
669
670         *out = data_blob_talloc(mem_ctx, data->data, data->length);
671         if (out->data == NULL) {
672                 return false;
673         }
674         talloc_free(data);
675
676         return true;
677 }
678
679 static bool encode_server_sort_request(void *mem_ctx, void *in, DATA_BLOB *out)
680 {
681         struct ldb_server_sort_control **lssc = talloc_get_type(in, struct ldb_server_sort_control *);
682         struct asn1_data *data = asn1_init(mem_ctx);
683         int num;
684
685         if (!data) return false;
686
687         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
688                 return false;
689         }
690
691         for (num = 0; lssc[num]; num++) {
692                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
693                         return false;
694                 }
695                 
696                 if (!asn1_write_OctetString(data, lssc[num]->attributeName, strlen(lssc[num]->attributeName))) {
697                         return false;
698                 }
699
700                 if (lssc[num]->orderingRule) {
701                         if (!asn1_write_OctetString(data, lssc[num]->orderingRule, strlen(lssc[num]->orderingRule))) {
702                                 return false;
703                         }
704                 }
705
706                 if (lssc[num]->reverse) {
707                         if (!asn1_write_BOOLEAN(data, lssc[num]->reverse)) {
708                                 return false;
709                         }
710                 }
711
712                 if (!asn1_pop_tag(data)) {
713                         return false;
714                 }
715         }
716
717         if (!asn1_pop_tag(data)) {
718                 return false;
719         }
720
721         *out = data_blob_talloc(mem_ctx, data->data, data->length);
722         if (out->data == NULL) {
723                 return false;
724         }
725         talloc_free(data);
726
727         return true;
728 }
729
730 static bool encode_extended_dn_request(void *mem_ctx, void *in, DATA_BLOB *out)
731 {
732         struct ldb_extended_dn_control *ledc = talloc_get_type(in, struct ldb_extended_dn_control);
733         struct asn1_data *data;
734
735         if (!in) {
736                 *out = data_blob(NULL, 0);
737                 return true;
738         }
739
740         data = asn1_init(mem_ctx);
741
742         if (!data) return false;
743
744         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
745                 return false;
746         }
747
748         if (!asn1_write_Integer(data, ledc->type)) {
749                 return false;
750         }
751
752         if (!asn1_pop_tag(data)) {
753                 return false;
754         }
755
756         *out = data_blob_talloc(mem_ctx, data->data, data->length);
757         if (out->data == NULL) {
758                 return false;
759         }
760         talloc_free(data);
761
762         return true;
763 }
764
765 static bool encode_sd_flags_request(void *mem_ctx, void *in, DATA_BLOB *out)
766 {
767         struct ldb_sd_flags_control *lsdfc = talloc_get_type(in, struct ldb_sd_flags_control);
768         struct asn1_data *data = asn1_init(mem_ctx);
769
770         if (!data) return false;
771
772         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
773                 return false;
774         }
775
776         if (!asn1_write_Integer(data, lsdfc->secinfo_flags)) {
777                 return false;
778         }
779
780         if (!asn1_pop_tag(data)) {
781                 return false;
782         }
783
784         *out = data_blob_talloc(mem_ctx, data->data, data->length);
785         if (out->data == NULL) {
786                 return false;
787         }
788         talloc_free(data);
789
790         return true;
791 }
792
793 static bool encode_search_options_request(void *mem_ctx, void *in, DATA_BLOB *out)
794 {
795         struct ldb_search_options_control *lsoc = talloc_get_type(in, struct ldb_search_options_control);
796         struct asn1_data *data = asn1_init(mem_ctx);
797
798         if (!data) return false;
799
800         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
801                 return false;
802         }
803
804         if (!asn1_write_Integer(data, lsoc->search_options)) {
805                 return false;
806         }
807
808         if (!asn1_pop_tag(data)) {
809                 return false;
810         }
811
812         *out = data_blob_talloc(mem_ctx, data->data, data->length);
813         if (out->data == NULL) {
814                 return false;
815         }
816         talloc_free(data);
817
818         return true;
819 }
820
821 static bool encode_paged_results_request(void *mem_ctx, void *in, DATA_BLOB *out)
822 {
823         struct ldb_paged_control *lprc = talloc_get_type(in, struct ldb_paged_control);
824         struct asn1_data *data = asn1_init(mem_ctx);
825
826         if (!data) return false;
827
828         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
829                 return false;
830         }
831
832         if (!asn1_write_Integer(data, lprc->size)) {
833                 return false;
834         }
835
836         if (!asn1_write_OctetString(data, lprc->cookie, lprc->cookie_len)) {
837                 return false;
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 /* seem that this controls has 2 forms one in case it is used with
854  * a Search Request and another when used ina Search Response
855  */
856 static bool encode_asq_control(void *mem_ctx, void *in, DATA_BLOB *out)
857 {
858         struct ldb_asq_control *lac = talloc_get_type(in, struct ldb_asq_control);
859         struct asn1_data *data = asn1_init(mem_ctx);
860
861         if (!data) return false;
862
863         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
864                 return false;
865         }
866
867         if (lac->request) {
868
869                 if (!asn1_write_OctetString(data, lac->source_attribute, lac->src_attr_len)) {
870                         return false;
871                 }
872         } else {
873                 if (!asn1_write_enumerated(data, lac->result)) {
874                         return false;
875                 }
876         }
877
878         if (!asn1_pop_tag(data)) {
879                 return false;
880         }
881
882         *out = data_blob_talloc(mem_ctx, data->data, data->length);
883         if (out->data == NULL) {
884                 return false;
885         }
886         talloc_free(data);
887
888         return true;
889 }
890
891 static bool encode_dirsync_request(void *mem_ctx, void *in, DATA_BLOB *out)
892 {
893         struct ldb_dirsync_control *ldc = talloc_get_type(in, struct ldb_dirsync_control);
894         struct asn1_data *data = asn1_init(mem_ctx);
895
896         if (!data) return false;
897
898         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
899                 return false;
900         }
901
902         if (!asn1_write_Integer(data, ldc->flags)) {
903                 return false;
904         }
905
906         if (!asn1_write_Integer(data, ldc->max_attributes)) {
907                 return false;
908         }
909
910         if (!asn1_write_OctetString(data, ldc->cookie, ldc->cookie_len)) {
911                 return false;
912         }       
913
914         if (!asn1_pop_tag(data)) {
915                 return false;
916         }
917
918         *out = data_blob_talloc(mem_ctx, data->data, data->length);
919         if (out->data == NULL) {
920                 return false;
921         }
922         talloc_free(data);
923
924         return true;
925 }
926
927 static bool encode_domain_scope_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_notification_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_show_deleted_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_permissive_modify_request(void *mem_ctx, void *in, DATA_BLOB *out)
958 {
959         if (in) {
960                 return false;
961         }
962
963         *out = data_blob(NULL, 0);
964         return true;
965 }
966
967 static bool encode_manageDSAIT_request(void *mem_ctx, void *in, DATA_BLOB *out)
968 {
969         if (in) {
970                 return false;
971         }
972
973         *out = data_blob(NULL, 0);
974         return true;
975 }
976
977 static bool encode_vlv_request(void *mem_ctx, void *in, DATA_BLOB *out)
978 {
979         struct ldb_vlv_req_control *lvrc = talloc_get_type(in, struct ldb_vlv_req_control);
980         struct asn1_data *data = asn1_init(mem_ctx);
981
982         if (!data) return false;
983
984         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
985                 return false;
986         }
987
988         if (!asn1_write_Integer(data, lvrc->beforeCount)) {
989                 return false;
990         }
991
992         if (!asn1_write_Integer(data, lvrc->afterCount)) {
993                 return false;
994         }
995
996         if (lvrc->type == 0) {
997                 if (!asn1_push_tag(data, ASN1_CONTEXT(0))) {
998                         return false;
999                 }
1000                 
1001                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1002                         return false;
1003                 }
1004                 
1005                 if (!asn1_write_Integer(data, lvrc->match.byOffset.offset)) {
1006                         return false;
1007                 }
1008
1009                 if (!asn1_write_Integer(data, lvrc->match.byOffset.contentCount)) {
1010                         return false;
1011                 }
1012
1013                 if (!asn1_pop_tag(data)) { /*SEQUENCE*/
1014                         return false;
1015                 }
1016
1017                 if (!asn1_pop_tag(data)) { /*CONTEXT*/
1018                         return false;
1019                 }
1020         } else {
1021                 if (!asn1_push_tag(data, ASN1_CONTEXT(1))) {
1022                         return false;
1023                 }
1024                 
1025                 if (!asn1_write_OctetString(data, lvrc->match.gtOrEq.value, lvrc->match.gtOrEq.value_len)) {
1026                         return false;
1027                 }
1028
1029                 if (!asn1_pop_tag(data)) { /*CONTEXT*/
1030                         return false;
1031                 }
1032         }
1033
1034         if (lvrc->ctxid_len) {
1035                 if (!asn1_write_OctetString(data, lvrc->contextId, lvrc->ctxid_len)) {
1036                         return false;
1037                 }
1038         }
1039
1040         if (!asn1_pop_tag(data)) {
1041                 return false;
1042         }
1043
1044         *out = data_blob_talloc(mem_ctx, data->data, data->length);
1045         if (out->data == NULL) {
1046                 return false;
1047         }
1048         talloc_free(data);
1049
1050         return true;
1051 }
1052
1053 static bool encode_vlv_response(void *mem_ctx, void *in, DATA_BLOB *out)
1054 {
1055         struct ldb_vlv_resp_control *lvrc = talloc_get_type(in, struct ldb_vlv_resp_control);
1056         struct asn1_data *data = asn1_init(mem_ctx);
1057
1058         if (!data) return false;
1059
1060         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1061                 return false;
1062         }
1063
1064         if (!asn1_write_Integer(data, lvrc->targetPosition)) {
1065                 return false;
1066         }
1067
1068         if (!asn1_write_Integer(data, lvrc->contentCount)) {
1069                 return false;
1070         }
1071
1072         if (!asn1_write_enumerated(data, lvrc->vlv_result)) {
1073                 return false;
1074         }
1075
1076         if (lvrc->ctxid_len) {
1077                 if (!asn1_write_OctetString(data, lvrc->contextId, lvrc->ctxid_len)) {
1078                         return false;
1079                 }
1080         }
1081
1082         if (!asn1_pop_tag(data)) {
1083                 return false;
1084         }
1085
1086         *out = data_blob_talloc(mem_ctx, data->data, data->length);
1087         if (out->data == NULL) {
1088                 return false;
1089         }
1090         talloc_free(data);
1091
1092         return true;
1093 }
1094
1095 static bool encode_openldap_dereference(void *mem_ctx, void *in, DATA_BLOB *out)
1096 {
1097         struct dsdb_openldap_dereference_control *control = talloc_get_type(in, struct dsdb_openldap_dereference_control);
1098         int i,j;
1099         struct asn1_data *data = asn1_init(mem_ctx);
1100
1101         if (!data) return false;
1102         
1103         if (!control) return false;
1104         
1105         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1106                 return false;
1107         }
1108         
1109         for (i=0; control->dereference && control->dereference[i]; i++) {
1110                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1111                         return false;
1112                 }
1113                 if (!asn1_write_OctetString(data, control->dereference[i]->source_attribute, strlen(control->dereference[i]->source_attribute))) {
1114                         return false;
1115                 }
1116                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1117                         return false;
1118                 }
1119                 for (j=0; control->dereference && control->dereference[i]->dereference_attribute[j]; j++) {
1120                         if (!asn1_write_OctetString(data, control->dereference[i]->dereference_attribute[j], 
1121                                                     strlen(control->dereference[i]->dereference_attribute[j]))) {
1122                                 return false;
1123                         }
1124                 }
1125                 
1126                 asn1_pop_tag(data);
1127                 asn1_pop_tag(data);
1128         }
1129         asn1_pop_tag(data);
1130
1131         *out = data_blob_talloc(mem_ctx, data->data, data->length);
1132         if (out->data == NULL) {
1133                 return false;
1134         }
1135         talloc_free(data);
1136         return true;
1137 }
1138
1139 static bool decode_openldap_dereference(void *mem_ctx, DATA_BLOB in, void *_out)
1140 {
1141         void **out = (void **)_out;
1142         struct asn1_data *data = asn1_init(mem_ctx);
1143         struct dsdb_openldap_dereference_result_control *control;
1144         struct dsdb_openldap_dereference_result **r = NULL;
1145         int i = 0;
1146         if (!data) return false;
1147
1148         control = talloc(mem_ctx, struct dsdb_openldap_dereference_result_control);
1149         if (!control) return false;
1150
1151         if (!asn1_load(data, in)) {
1152                 return false;
1153         }
1154
1155         control = talloc(mem_ctx, struct dsdb_openldap_dereference_result_control);
1156         if (!control) {
1157                 return false;
1158         }
1159
1160         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
1161                 return false;
1162         }
1163
1164         while (asn1_tag_remaining(data) > 0) {                                  
1165                 r = talloc_realloc(control, r, struct dsdb_openldap_dereference_result *, i + 2);
1166                 if (!r) {
1167                         return false;
1168                 }
1169                 r[i] = talloc_zero(r, struct dsdb_openldap_dereference_result);
1170                 if (!r[i]) {
1171                         return false;
1172                 }
1173
1174                 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
1175                         return false;
1176                 }
1177                 
1178                 asn1_read_OctetString_talloc(r[i], data, &r[i]->source_attribute);
1179                 asn1_read_OctetString_talloc(r[i], data, &r[i]->dereferenced_dn);
1180                 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1181                         if (!asn1_start_tag(data, ASN1_CONTEXT(0))) {
1182                                 return false;
1183                         }
1184                         
1185                         ldap_decode_attribs_bare(r, data, &r[i]->attributes,
1186                                                  &r[i]->num_attributes);
1187                         
1188                         if (!asn1_end_tag(data)) {
1189                                 return false;
1190                         }
1191                 }
1192                 if (!asn1_end_tag(data)) {
1193                         return false;
1194                 }
1195                 i++;
1196                 r[i] = NULL;
1197         }
1198
1199         if (!asn1_end_tag(data)) {
1200                 return false;
1201         }
1202
1203         control->attributes = r;
1204         *out = control;
1205
1206         return true;
1207 }
1208
1209 static const struct ldap_control_handler ldap_known_controls[] = {
1210         { "1.2.840.113556.1.4.319", decode_paged_results_request, encode_paged_results_request },
1211         { "1.2.840.113556.1.4.529", decode_extended_dn_request, encode_extended_dn_request },
1212         { "1.2.840.113556.1.4.473", decode_server_sort_request, encode_server_sort_request },
1213         { "1.2.840.113556.1.4.474", decode_server_sort_response, encode_server_sort_response },
1214         { "1.2.840.113556.1.4.1504", decode_asq_control, encode_asq_control },
1215         { "1.2.840.113556.1.4.841", decode_dirsync_request, encode_dirsync_request },
1216         { "1.2.840.113556.1.4.528", decode_notification_request, encode_notification_request },
1217         { "1.2.840.113556.1.4.417", decode_show_deleted_request, encode_show_deleted_request },
1218         { "1.2.840.113556.1.4.1413", decode_permissive_modify_request, encode_permissive_modify_request },
1219         { "1.2.840.113556.1.4.801", decode_sd_flags_request, encode_sd_flags_request },
1220         { "1.2.840.113556.1.4.1339", decode_domain_scope_request, encode_domain_scope_request },
1221         { "1.2.840.113556.1.4.1340", decode_search_options_request, encode_search_options_request },
1222         { "2.16.840.1.113730.3.4.2", decode_manageDSAIT_request, encode_manageDSAIT_request },
1223         { "2.16.840.1.113730.3.4.9", decode_vlv_request, encode_vlv_request },
1224         { "2.16.840.1.113730.3.4.10", decode_vlv_response, encode_vlv_response },
1225 /* DSDB_CONTROL_CURRENT_PARTITION_OID is internal only, and has no network representation */
1226         { "1.3.6.1.4.1.7165.4.3.2", NULL, NULL },
1227 /* DSDB_EXTENDED_REPLICATED_OBJECTS_OID is internal only, and has no network representation */
1228         { "1.3.6.1.4.1.7165.4.4.1", NULL, NULL },
1229         { DSDB_OPENLDAP_DEREFERENCE_CONTROL, decode_openldap_dereference, encode_openldap_dereference},
1230         { NULL, NULL, NULL }
1231 };
1232
1233 const struct ldap_control_handler *samba_ldap_control_handlers(void)
1234 {
1235         return ldap_known_controls;
1236 }
1237