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