r17429: implement the LDAP_SERVER_SHOW_DELETED control in the client
[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 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_show_deleted_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_manageDSAIT_request(void *mem_ctx, DATA_BLOB in, void **out)
432 {
433         if (in.length != 0) {
434                 return False;
435         }
436
437         return True;
438 }
439
440 static BOOL decode_vlv_request(void *mem_ctx, DATA_BLOB in, void **out)
441 {
442         DATA_BLOB assertion_value, context_id;
443         struct asn1_data data;
444         struct ldb_vlv_req_control *lvrc;
445
446         if (!asn1_load(&data, in)) {
447                 return False;
448         }
449
450         lvrc = talloc(mem_ctx, struct ldb_vlv_req_control);
451         if (!lvrc) {
452                 return False;
453         }
454
455         if (!asn1_start_tag(&data, ASN1_SEQUENCE(0))) {
456                 return False;
457         }
458
459         if (!asn1_read_Integer(&data, &(lvrc->beforeCount))) {
460                 return False;
461         }
462         
463         if (!asn1_read_Integer(&data, &(lvrc->afterCount))) {
464                 return False;
465         }
466
467         if (asn1_peek_tag(&data, ASN1_CONTEXT(0))) {
468
469                 lvrc->type = 0;
470                 
471                 if (!asn1_start_tag(&data, ASN1_CONTEXT(0))) {
472                         return False;
473                 }
474
475                 if (!asn1_start_tag(&data, ASN1_SEQUENCE(0))) {
476                         return False;
477                 }
478
479                 if (!asn1_read_Integer(&data, &(lvrc->match.byOffset.offset))) {
480                         return False;
481                 }
482
483                 if (!asn1_read_Integer(&data, &(lvrc->match.byOffset.contentCount))) {
484                         return False;
485                 }
486
487                 if (!asn1_end_tag(&data)) { /*SEQUENCE*/
488                         return False;
489                 }
490
491                 if (!asn1_end_tag(&data)) { /*CONTEXT*/
492                         return False;
493                 }
494
495         } else {
496
497                 lvrc->type = 1;
498
499                 if (!asn1_start_tag(&data, ASN1_CONTEXT(1))) {
500                         return False;
501                 }
502
503                 if (!asn1_read_OctetString(&data, &assertion_value)) {
504                         return False;
505                 }
506                 lvrc->match.gtOrEq.value_len = assertion_value.length;
507                 if (lvrc->match.gtOrEq.value_len) {
508                         lvrc->match.gtOrEq.value = talloc_memdup(lvrc, assertion_value.data, assertion_value.length);
509
510                         if (!(lvrc->match.gtOrEq.value)) {
511                                 return False;
512                         }
513                 } else {
514                         lvrc->match.gtOrEq.value = NULL;
515                 }
516
517                 if (!asn1_end_tag(&data)) { /*CONTEXT*/
518                         return False;
519                 }
520         }
521
522         if (asn1_peek_tag(&data, ASN1_OCTET_STRING)) {
523                 if (!asn1_read_OctetString(&data, &context_id)) {
524                         return False;
525                 }
526                 lvrc->ctxid_len = context_id.length;
527                 if (lvrc->ctxid_len) {
528                         lvrc->contextId = talloc_memdup(lvrc, context_id.data, context_id.length);
529
530                         if (!(lvrc->contextId)) {
531                                 return False;
532                         }
533                 } else {
534                         lvrc->contextId = NULL;
535                 }
536         } else {
537                 lvrc->contextId = NULL;
538                 lvrc->ctxid_len = 0;
539         }
540
541         if (!asn1_end_tag(&data)) {
542                 return False;
543         }
544
545         *out = lvrc;
546
547         return True;
548 }
549
550 static BOOL decode_vlv_response(void *mem_ctx, DATA_BLOB in, void **out)
551 {
552         DATA_BLOB context_id;
553         struct asn1_data data;
554         struct ldb_vlv_resp_control *lvrc;
555
556         if (!asn1_load(&data, in)) {
557                 return False;
558         }
559
560         lvrc = talloc(mem_ctx, struct ldb_vlv_resp_control);
561         if (!lvrc) {
562                 return False;
563         }
564
565         if (!asn1_start_tag(&data, ASN1_SEQUENCE(0))) {
566                 return False;
567         }
568
569         if (!asn1_read_Integer(&data, &(lvrc->targetPosition))) {
570                 return False;
571         }
572         
573         if (!asn1_read_Integer(&data, &(lvrc->contentCount))) {
574                 return False;
575         }
576         
577         if (!asn1_read_enumerated(&data, &(lvrc->vlv_result))) {
578                 return False;
579         }
580
581         if (asn1_peek_tag(&data, ASN1_OCTET_STRING)) {
582                 if (!asn1_read_OctetString(&data, &context_id)) {
583                         return False;
584                 }
585                 lvrc->contextId = talloc_strndup(lvrc, (const char *)context_id.data, context_id.length);
586                 if (!lvrc->contextId) {
587                         return False;
588                 }
589                 lvrc->ctxid_len = context_id.length;
590         } else {
591                 lvrc->contextId = NULL;
592                 lvrc->ctxid_len = 0;
593         }
594
595         if (!asn1_end_tag(&data)) {
596                 return False;
597         }
598
599         *out = lvrc;
600
601         return True;
602 }
603
604 static BOOL encode_server_sort_response(void *mem_ctx, void *in, DATA_BLOB *out)
605 {
606         struct ldb_sort_resp_control *lsrc = talloc_get_type(in, struct ldb_sort_resp_control);
607         struct asn1_data data;
608
609         ZERO_STRUCT(data);
610
611         if (!asn1_push_tag(&data, ASN1_SEQUENCE(0))) {
612                 return False;
613         }
614
615         if (!asn1_write_enumerated(&data, lsrc->result)) {
616                 return False;
617         }
618
619         if (lsrc->attr_desc) {
620                 if (!asn1_write_OctetString(&data, lsrc->attr_desc, strlen(lsrc->attr_desc))) {
621                         return False;
622                 }
623         }
624
625         if (!asn1_pop_tag(&data)) {
626                 return False;
627         }
628
629         *out = data_blob_talloc(mem_ctx, data.data, data.length);
630         if (out->data == NULL) {
631                 return False;
632         }
633
634         return True;
635 }
636
637 static BOOL encode_server_sort_request(void *mem_ctx, void *in, DATA_BLOB *out)
638 {
639         struct ldb_server_sort_control **lssc = talloc_get_type(in, struct ldb_server_sort_control *);
640         struct asn1_data data;
641         int num;
642
643         ZERO_STRUCT(data);
644
645         if (!asn1_push_tag(&data, ASN1_SEQUENCE(0))) {
646                 return False;
647         }
648
649         for (num = 0; lssc[num]; num++) {
650                 if (!asn1_push_tag(&data, ASN1_SEQUENCE(0))) {
651                         return False;
652                 }
653                 
654                 if (!asn1_write_OctetString(&data, lssc[num]->attributeName, strlen(lssc[num]->attributeName))) {
655                         return False;
656                 }
657
658                 if (lssc[num]->orderingRule) {
659                         if (!asn1_write_OctetString(&data, lssc[num]->orderingRule, strlen(lssc[num]->orderingRule))) {
660                                 return False;
661                         }
662                 }
663
664                 if (lssc[num]->reverse) {
665                         if (!asn1_write_BOOLEAN(&data, lssc[num]->reverse)) {
666                                 return False;
667                         }
668                 }
669
670                 if (!asn1_pop_tag(&data)) {
671                         return False;
672                 }
673         }
674
675         if (!asn1_pop_tag(&data)) {
676                 return False;
677         }
678
679         *out = data_blob_talloc(mem_ctx, data.data, data.length);
680         if (out->data == NULL) {
681                 return False;
682         }
683
684         return True;
685 }
686
687 static BOOL encode_extended_dn_request(void *mem_ctx, void *in, DATA_BLOB *out)
688 {
689         struct ldb_extended_dn_control *ledc = talloc_get_type(in, struct ldb_extended_dn_control);
690         struct asn1_data data;
691
692         ZERO_STRUCT(data);
693
694         if (!asn1_push_tag(&data, ASN1_SEQUENCE(0))) {
695                 return False;
696         }
697
698         if (!asn1_write_Integer(&data, ledc->type)) {
699                 return False;
700         }
701
702         if (!asn1_pop_tag(&data)) {
703                 return False;
704         }
705
706         *out = data_blob_talloc(mem_ctx, data.data, data.length);
707         if (out->data == NULL) {
708                 return False;
709         }
710
711         return True;
712 }
713
714 static BOOL encode_sd_flags_request(void *mem_ctx, void *in, DATA_BLOB *out)
715 {
716         struct ldb_sd_flags_control *lsdfc = talloc_get_type(in, struct ldb_sd_flags_control);
717         struct asn1_data data;
718
719         ZERO_STRUCT(data);
720
721         if (!asn1_push_tag(&data, ASN1_SEQUENCE(0))) {
722                 return False;
723         }
724
725         if (!asn1_write_Integer(&data, lsdfc->secinfo_flags)) {
726                 return False;
727         }
728
729         if (!asn1_pop_tag(&data)) {
730                 return False;
731         }
732
733         *out = data_blob_talloc(mem_ctx, data.data, data.length);
734         if (out->data == NULL) {
735                 return False;
736         }
737
738         return True;
739 }
740
741 static BOOL encode_search_options_request(void *mem_ctx, void *in, DATA_BLOB *out)
742 {
743         struct ldb_search_options_control *lsoc = talloc_get_type(in, struct ldb_search_options_control);
744         struct asn1_data data;
745
746         ZERO_STRUCT(data);
747
748         if (!asn1_push_tag(&data, ASN1_SEQUENCE(0))) {
749                 return False;
750         }
751
752         if (!asn1_write_Integer(&data, lsoc->search_options)) {
753                 return False;
754         }
755
756         if (!asn1_pop_tag(&data)) {
757                 return False;
758         }
759
760         *out = data_blob_talloc(mem_ctx, data.data, data.length);
761         if (out->data == NULL) {
762                 return False;
763         }
764
765         return True;
766 }
767
768 static BOOL encode_paged_results_request(void *mem_ctx, void *in, DATA_BLOB *out)
769 {
770         struct ldb_paged_control *lprc = talloc_get_type(in, struct ldb_paged_control);
771         struct asn1_data data;
772
773         ZERO_STRUCT(data);
774
775         if (!asn1_push_tag(&data, ASN1_SEQUENCE(0))) {
776                 return False;
777         }
778
779         if (!asn1_write_Integer(&data, lprc->size)) {
780                 return False;
781         }
782
783         if (!asn1_write_OctetString(&data, lprc->cookie, lprc->cookie_len)) {
784                 return False;
785         }       
786
787         if (!asn1_pop_tag(&data)) {
788                 return False;
789         }
790
791         *out = data_blob_talloc(mem_ctx, data.data, data.length);
792         if (out->data == NULL) {
793                 return False;
794         }
795
796         return True;
797 }
798
799 /* seem that this controls has 2 forms one in case it is used with
800  * a Search Request and another when used ina Search Response
801  */
802 static BOOL encode_asq_control(void *mem_ctx, void *in, DATA_BLOB *out)
803 {
804         struct ldb_asq_control *lac = talloc_get_type(in, struct ldb_asq_control);
805         struct asn1_data data;
806
807         ZERO_STRUCT(data);
808
809         if (!asn1_push_tag(&data, ASN1_SEQUENCE(0))) {
810                 return False;
811         }
812
813         if (lac->request) {
814
815                 if (!asn1_write_OctetString(&data, lac->source_attribute, lac->src_attr_len)) {
816                         return False;
817                 }
818         } else {
819                 if (!asn1_write_enumerated(&data, lac->result)) {
820                         return False;
821                 }
822         }
823
824         if (!asn1_pop_tag(&data)) {
825                 return False;
826         }
827
828         *out = data_blob_talloc(mem_ctx, data.data, data.length);
829         if (out->data == NULL) {
830                 return False;
831         }
832
833         return True;
834 }
835
836 static BOOL encode_dirsync_request(void *mem_ctx, void *in, DATA_BLOB *out)
837 {
838         struct ldb_dirsync_control *ldc = talloc_get_type(in, struct ldb_dirsync_control);
839         struct asn1_data data;
840
841         ZERO_STRUCT(data);
842
843         if (!asn1_push_tag(&data, ASN1_SEQUENCE(0))) {
844                 return False;
845         }
846
847         if (!asn1_write_Integer(&data, ldc->flags)) {
848                 return False;
849         }
850
851         if (!asn1_write_Integer(&data, ldc->max_attributes)) {
852                 return False;
853         }
854
855         if (!asn1_write_OctetString(&data, ldc->cookie, ldc->cookie_len)) {
856                 return False;
857         }       
858
859         if (!asn1_pop_tag(&data)) {
860                 return False;
861         }
862
863         *out = data_blob_talloc(mem_ctx, data.data, data.length);
864         if (out->data == NULL) {
865                 return False;
866         }
867
868         return True;
869 }
870
871 static BOOL encode_domain_scope_request(void *mem_ctx, void *in, DATA_BLOB *out)
872 {
873         if (in) {
874                 return False;
875         }
876
877         *out = data_blob(NULL, 0);
878         return True;
879 }
880
881 static BOOL encode_notification_request(void *mem_ctx, void *in, DATA_BLOB *out)
882 {
883         if (in) {
884                 return False;
885         }
886
887         *out = data_blob(NULL, 0);
888         return True;
889 }
890
891 static BOOL encode_show_deleted_request(void *mem_ctx, void *in, DATA_BLOB *out)
892 {
893         if (in) {
894                 return False;
895         }
896
897         *out = data_blob(NULL, 0);
898         return True;
899 }
900
901 static BOOL encode_manageDSAIT_request(void *mem_ctx, void *in, DATA_BLOB *out)
902 {
903         if (in) {
904                 return False;
905         }
906
907         *out = data_blob(NULL, 0);
908         return True;
909 }
910
911 static BOOL encode_vlv_request(void *mem_ctx, void *in, DATA_BLOB *out)
912 {
913         struct ldb_vlv_req_control *lvrc = talloc_get_type(in, struct ldb_vlv_req_control);
914         struct asn1_data data;
915
916         ZERO_STRUCT(data);
917
918         if (!asn1_push_tag(&data, ASN1_SEQUENCE(0))) {
919                 return False;
920         }
921
922         if (!asn1_write_Integer(&data, lvrc->beforeCount)) {
923                 return False;
924         }
925
926         if (!asn1_write_Integer(&data, lvrc->afterCount)) {
927                 return False;
928         }
929
930         if (lvrc->type == 0) {
931                 if (!asn1_push_tag(&data, ASN1_CONTEXT(0))) {
932                         return False;
933                 }
934                 
935                 if (!asn1_push_tag(&data, ASN1_SEQUENCE(0))) {
936                         return False;
937                 }
938                 
939                 if (!asn1_write_Integer(&data, lvrc->match.byOffset.offset)) {
940                         return False;
941                 }
942
943                 if (!asn1_write_Integer(&data, lvrc->match.byOffset.contentCount)) {
944                         return False;
945                 }
946
947                 if (!asn1_pop_tag(&data)) { /*SEQUENCE*/
948                         return False;
949                 }
950
951                 if (!asn1_pop_tag(&data)) { /*CONTEXT*/
952                         return False;
953                 }
954         } else {
955                 if (!asn1_push_tag(&data, ASN1_CONTEXT(1))) {
956                         return False;
957                 }
958                 
959                 if (!asn1_write_OctetString(&data, lvrc->match.gtOrEq.value, lvrc->match.gtOrEq.value_len)) {
960                         return False;
961                 }
962
963                 if (!asn1_pop_tag(&data)) { /*CONTEXT*/
964                         return False;
965                 }
966         }
967
968         if (lvrc->ctxid_len) {
969                 if (!asn1_write_OctetString(&data, lvrc->contextId, lvrc->ctxid_len)) {
970                         return False;
971                 }
972         }
973
974         if (!asn1_pop_tag(&data)) {
975                 return False;
976         }
977
978         *out = data_blob_talloc(mem_ctx, data.data, data.length);
979         if (out->data == NULL) {
980                 return False;
981         }
982
983         return True;
984 }
985
986 static BOOL encode_vlv_response(void *mem_ctx, void *in, DATA_BLOB *out)
987 {
988         struct ldb_vlv_resp_control *lvrc = talloc_get_type(in, struct ldb_vlv_resp_control);
989         struct asn1_data data;
990
991         ZERO_STRUCT(data);
992
993         if (!asn1_push_tag(&data, ASN1_SEQUENCE(0))) {
994                 return False;
995         }
996
997         if (!asn1_write_Integer(&data, lvrc->targetPosition)) {
998                 return False;
999         }
1000
1001         if (!asn1_write_Integer(&data, lvrc->contentCount)) {
1002                 return False;
1003         }
1004
1005         if (!asn1_write_enumerated(&data, lvrc->vlv_result)) {
1006                 return False;
1007         }
1008
1009         if (lvrc->ctxid_len) {
1010                 if (!asn1_write_OctetString(&data, lvrc->contextId, lvrc->ctxid_len)) {
1011                         return False;
1012                 }
1013         }
1014
1015         if (!asn1_pop_tag(&data)) {
1016                 return False;
1017         }
1018
1019         *out = data_blob_talloc(mem_ctx, data.data, data.length);
1020         if (out->data == NULL) {
1021                 return False;
1022         }
1023
1024         return True;
1025 }
1026
1027 struct control_handler ldap_known_controls[] = {
1028         { "1.2.840.113556.1.4.319", decode_paged_results_request, encode_paged_results_request },
1029         { "1.2.840.113556.1.4.529", decode_extended_dn_request, encode_extended_dn_request },
1030         { "1.2.840.113556.1.4.473", decode_server_sort_request, encode_server_sort_request },
1031         { "1.2.840.113556.1.4.474", decode_server_sort_response, encode_server_sort_response },
1032         { "1.2.840.113556.1.4.1504", decode_asq_control, encode_asq_control },
1033         { "1.2.840.113556.1.4.841", decode_dirsync_request, encode_dirsync_request },
1034         { "1.2.840.113556.1.4.528", decode_notification_request, encode_notification_request },
1035         { "1.2.840.113556.1.4.417", decode_show_deleted_request, encode_show_deleted_request },
1036         { "1.2.840.113556.1.4.801", decode_sd_flags_request, encode_sd_flags_request },
1037         { "1.2.840.113556.1.4.1339", decode_domain_scope_request, encode_domain_scope_request },
1038         { "1.2.840.113556.1.4.1340", decode_search_options_request, encode_search_options_request },
1039         { "2.16.840.1.113730.3.4.2", decode_manageDSAIT_request, encode_manageDSAIT_request },
1040         { "2.16.840.1.113730.3.4.9", decode_vlv_request, encode_vlv_request },
1041         { "2.16.840.1.113730.3.4.10", decode_vlv_response, encode_vlv_response },
1042         { NULL, NULL, NULL }
1043 };
1044
1045 BOOL ldap_decode_control(void *mem_ctx, struct asn1_data *data, struct ldb_control *ctrl)
1046 {
1047         int i;
1048         DATA_BLOB oid;
1049         DATA_BLOB value;
1050
1051         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
1052                 return False;
1053         }
1054
1055         if (!asn1_read_OctetString(data, &oid)) {
1056                 return False;
1057         }
1058         ctrl->oid = talloc_strndup(mem_ctx, (char *)oid.data, oid.length);
1059         if (!ctrl->oid) {
1060                 return False;
1061         }
1062
1063         if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
1064                 BOOL critical;
1065                 if (!asn1_read_BOOLEAN(data, &critical)) {
1066                         return False;
1067                 }
1068                 ctrl->critical = critical;
1069         } else {
1070                 ctrl->critical = False;
1071         }
1072
1073         ctrl->data = NULL;
1074
1075         if (!asn1_peek_tag(data, ASN1_OCTET_STRING)) {
1076                 goto end_tag;
1077         }
1078
1079         if (!asn1_read_OctetString(data, &value)) {
1080                 return False;
1081         }
1082
1083         for (i = 0; ldap_known_controls[i].oid != NULL; i++) {
1084                 if (strcmp(ldap_known_controls[i].oid, ctrl->oid) == 0) {
1085                         if (!ldap_known_controls[i].decode(mem_ctx, value, &ctrl->data)) {
1086                                 return False;
1087                         }
1088                         break;
1089                 }
1090         }
1091         if (ldap_known_controls[i].oid == NULL) {
1092                 return False;
1093         }
1094
1095 end_tag:
1096         if (!asn1_end_tag(data)) {
1097                 return False;
1098         }
1099
1100         return True;
1101 }
1102
1103 BOOL ldap_encode_control(void *mem_ctx, struct asn1_data *data, struct ldb_control *ctrl)
1104 {
1105         DATA_BLOB value;
1106         int i;
1107
1108         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1109                 return False;
1110         }
1111
1112         if (!asn1_write_OctetString(data, ctrl->oid, strlen(ctrl->oid))) {
1113                 return False;
1114         }
1115
1116         if (ctrl->critical) {
1117                 if (!asn1_write_BOOLEAN(data, ctrl->critical)) {
1118                         return False;
1119                 }
1120         }
1121
1122         if (!ctrl->data) {
1123                 goto pop_tag;
1124         }
1125
1126         for (i = 0; ldap_known_controls[i].oid != NULL; i++) {
1127                 if (strcmp(ldap_known_controls[i].oid, ctrl->oid) == 0) {
1128                         if (!ldap_known_controls[i].encode(mem_ctx, ctrl->data, &value)) {
1129                                 return False;
1130                         }
1131                         break;
1132                 }
1133         }
1134         if (ldap_known_controls[i].oid == NULL) {
1135                 return False;
1136         }
1137
1138         if (!asn1_write_OctetString(data, value.data, value.length)) {
1139                 return False;
1140         }
1141
1142 pop_tag:
1143         if (!asn1_pop_tag(data)) {
1144                 return False;
1145         }
1146
1147         return True;
1148 }