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