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