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