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