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