ee8f9d4bb131c30f35bae761d0d76ea55879f020
[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 "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_paged_results_request(void *mem_ctx, DATA_BLOB in, void **out)
186 {
187         DATA_BLOB cookie;
188         struct asn1_data data;
189         struct ldb_paged_control *lprc;
190
191         if (!asn1_load(&data, in)) {
192                 return False;
193         }
194
195         lprc = talloc(mem_ctx, struct ldb_paged_control);
196         if (!lprc) {
197                 return False;
198         }
199
200         if (!asn1_start_tag(&data, ASN1_SEQUENCE(0))) {
201                 return False;
202         }
203
204         if (!asn1_read_Integer(&data, &(lprc->size))) {
205                 return False;
206         }
207         
208         if (!asn1_read_OctetString(&data, &cookie)) {
209                 return False;
210         }
211         lprc->cookie_len = cookie.length;
212         if (lprc->cookie_len) {
213                 lprc->cookie = talloc_memdup(lprc, cookie.data, cookie.length);
214
215                 if (!(lprc->cookie)) {
216                         return False;
217                 }
218         } else {
219                 lprc->cookie = NULL;
220         }
221
222         if (!asn1_end_tag(&data)) {
223                 return False;
224         }
225
226         *out = lprc;
227
228         return True;
229 }
230
231 static BOOL decode_dirsync_request(void *mem_ctx, DATA_BLOB in, void **out)
232 {
233         DATA_BLOB cookie;
234         struct asn1_data data;
235         struct ldb_dirsync_control *ldc;
236
237         if (!asn1_load(&data, in)) {
238                 return False;
239         }
240
241         ldc = talloc(mem_ctx, struct ldb_dirsync_control);
242         if (!ldc) {
243                 return False;
244         }
245
246         if (!asn1_start_tag(&data, ASN1_SEQUENCE(0))) {
247                 return False;
248         }
249
250         if (!asn1_read_Integer(&data, &(ldc->flags))) {
251                 return False;
252         }
253         
254         if (!asn1_read_Integer(&data, &(ldc->max_attributes))) {
255                 return False;
256         }
257         
258         if (!asn1_read_OctetString(&data, &cookie)) {
259                 return False;
260         }
261         ldc->cookie_len = cookie.length;
262         if (ldc->cookie_len) {
263                 ldc->cookie = talloc_memdup(ldc, cookie.data, cookie.length);
264
265                 if (!(ldc->cookie)) {
266                         return False;
267                 }
268         } else {
269                 ldc->cookie = NULL;
270         }
271
272         if (!asn1_end_tag(&data)) {
273                 return False;
274         }
275
276         *out = ldc;
277
278         return True;
279 }
280
281 /* seem that this controls has 2 forms one in case it is used with
282  * a Search Request and another when used ina Search Response
283  */
284 static BOOL decode_asq_control(void *mem_ctx, DATA_BLOB in, void **out)
285 {
286         DATA_BLOB source_attribute;
287         struct asn1_data data;
288         struct ldb_asq_control *lac;
289
290         if (!asn1_load(&data, in)) {
291                 return False;
292         }
293
294         lac = talloc(mem_ctx, struct ldb_asq_control);
295         if (!lac) {
296                 return False;
297         }
298
299         if (!asn1_start_tag(&data, ASN1_SEQUENCE(0))) {
300                 return False;
301         }
302
303         if (asn1_peek_tag(&data, ASN1_OCTET_STRING)) {
304
305                 if (!asn1_read_OctetString(&data, &source_attribute)) {
306                         return False;
307                 }
308                 lac->src_attr_len = source_attribute.length;
309                 if (lac->src_attr_len) {
310                         lac->source_attribute = talloc_strndup(lac, (const char *)source_attribute.data, source_attribute.length);
311
312                         if (!(lac->source_attribute)) {
313                                 return False;
314                         }
315                 } else {
316                         lac->source_attribute = NULL;
317                 }
318
319                 lac->request = 1;
320
321         } else if (asn1_peek_tag(&data, ASN1_ENUMERATED)) {
322
323                 if (!asn1_read_enumerated(&data, &(lac->result))) {
324                         return False;
325                 }
326
327                 lac->request = 0;
328
329         } else {
330                 return False;
331         }
332
333         if (!asn1_end_tag(&data)) {
334                 return False;
335         }
336
337         *out = lac;
338
339         return True;
340 }
341
342 static BOOL decode_notification_request(void *mem_ctx, DATA_BLOB in, void **out)
343 {
344         if (in.length != 0) {
345                 return False;
346         }
347
348         return True;
349 }
350
351 static BOOL decode_manageDSAIT_request(void *mem_ctx, DATA_BLOB in, void **out)
352 {
353         if (in.length != 0) {
354                 return False;
355         }
356
357         return True;
358 }
359
360 static BOOL decode_vlv_request(void *mem_ctx, DATA_BLOB in, void **out)
361 {
362         DATA_BLOB assertion_value, context_id;
363         struct asn1_data data;
364         struct ldb_vlv_req_control *lvrc;
365
366         if (!asn1_load(&data, in)) {
367                 return False;
368         }
369
370         lvrc = talloc(mem_ctx, struct ldb_vlv_req_control);
371         if (!lvrc) {
372                 return False;
373         }
374
375         if (!asn1_start_tag(&data, ASN1_SEQUENCE(0))) {
376                 return False;
377         }
378
379         if (!asn1_read_Integer(&data, &(lvrc->beforeCount))) {
380                 return False;
381         }
382         
383         if (!asn1_read_Integer(&data, &(lvrc->afterCount))) {
384                 return False;
385         }
386
387         if (asn1_peek_tag(&data, ASN1_CONTEXT(0))) {
388
389                 lvrc->type = 0;
390                 
391                 if (!asn1_start_tag(&data, ASN1_CONTEXT(0))) {
392                         return False;
393                 }
394
395                 if (!asn1_start_tag(&data, ASN1_SEQUENCE(0))) {
396                         return False;
397                 }
398
399                 if (!asn1_read_Integer(&data, &(lvrc->match.byOffset.offset))) {
400                         return False;
401                 }
402
403                 if (!asn1_read_Integer(&data, &(lvrc->match.byOffset.contentCount))) {
404                         return False;
405                 }
406
407                 if (!asn1_end_tag(&data)) { /*SEQUENCE*/
408                         return False;
409                 }
410
411                 if (!asn1_end_tag(&data)) { /*CONTEXT*/
412                         return False;
413                 }
414
415         } else {
416
417                 lvrc->type = 1;
418
419                 if (!asn1_start_tag(&data, ASN1_CONTEXT(1))) {
420                         return False;
421                 }
422
423                 if (!asn1_read_OctetString(&data, &assertion_value)) {
424                         return False;
425                 }
426                 lvrc->match.gtOrEq.value_len = assertion_value.length;
427                 if (lvrc->match.gtOrEq.value_len) {
428                         lvrc->match.gtOrEq.value = talloc_memdup(lvrc, assertion_value.data, assertion_value.length);
429
430                         if (!(lvrc->match.gtOrEq.value)) {
431                                 return False;
432                         }
433                 } else {
434                         lvrc->match.gtOrEq.value = NULL;
435                 }
436
437                 if (!asn1_end_tag(&data)) { /*CONTEXT*/
438                         return False;
439                 }
440         }
441
442         if (asn1_peek_tag(&data, ASN1_OCTET_STRING)) {
443                 if (!asn1_read_OctetString(&data, &context_id)) {
444                         return False;
445                 }
446                 lvrc->ctxid_len = context_id.length;
447                 if (lvrc->ctxid_len) {
448                         lvrc->contextId = talloc_memdup(lvrc, context_id.data, context_id.length);
449
450                         if (!(lvrc->contextId)) {
451                                 return False;
452                         }
453                 } else {
454                         lvrc->contextId = NULL;
455                 }
456         } else {
457                 lvrc->contextId = NULL;
458                 lvrc->ctxid_len = 0;
459         }
460
461         if (!asn1_end_tag(&data)) {
462                 return False;
463         }
464
465         *out = lvrc;
466
467         return True;
468 }
469
470 static BOOL decode_vlv_response(void *mem_ctx, DATA_BLOB in, void **out)
471 {
472         DATA_BLOB context_id;
473         struct asn1_data data;
474         struct ldb_vlv_resp_control *lvrc;
475
476         if (!asn1_load(&data, in)) {
477                 return False;
478         }
479
480         lvrc = talloc(mem_ctx, struct ldb_vlv_resp_control);
481         if (!lvrc) {
482                 return False;
483         }
484
485         if (!asn1_start_tag(&data, ASN1_SEQUENCE(0))) {
486                 return False;
487         }
488
489         if (!asn1_read_Integer(&data, &(lvrc->targetPosition))) {
490                 return False;
491         }
492         
493         if (!asn1_read_Integer(&data, &(lvrc->contentCount))) {
494                 return False;
495         }
496         
497         if (!asn1_read_enumerated(&data, &(lvrc->vlv_result))) {
498                 return False;
499         }
500
501         if (asn1_peek_tag(&data, ASN1_OCTET_STRING)) {
502                 if (!asn1_read_OctetString(&data, &context_id)) {
503                         return False;
504                 }
505                 lvrc->contextId = talloc_strndup(lvrc, (const char *)context_id.data, context_id.length);
506                 if (!lvrc->contextId) {
507                         return False;
508                 }
509                 lvrc->ctxid_len = context_id.length;
510         } else {
511                 lvrc->contextId = NULL;
512                 lvrc->ctxid_len = 0;
513         }
514
515         if (!asn1_end_tag(&data)) {
516                 return False;
517         }
518
519         *out = lvrc;
520
521         return True;
522 }
523
524 static BOOL encode_server_sort_response(void *mem_ctx, void *in, DATA_BLOB *out)
525 {
526         struct ldb_sort_resp_control *lsrc = talloc_get_type(in, struct ldb_sort_resp_control);
527         struct asn1_data data;
528
529         ZERO_STRUCT(data);
530
531         if (!asn1_push_tag(&data, ASN1_SEQUENCE(0))) {
532                 return False;
533         }
534
535         if (!asn1_write_enumerated(&data, lsrc->result)) {
536                 return False;
537         }
538
539         if (lsrc->attr_desc) {
540                 if (!asn1_write_OctetString(&data, lsrc->attr_desc, strlen(lsrc->attr_desc))) {
541                         return False;
542                 }
543         }
544
545         if (!asn1_pop_tag(&data)) {
546                 return False;
547         }
548
549         *out = data_blob_talloc(mem_ctx, data.data, data.length);
550         if (out->data == NULL) {
551                 return False;
552         }
553
554         return True;
555 }
556
557 static BOOL encode_server_sort_request(void *mem_ctx, void *in, DATA_BLOB *out)
558 {
559         struct ldb_server_sort_control **lssc = talloc_get_type(in, struct ldb_server_sort_control *);
560         struct asn1_data data;
561         int num;
562
563         ZERO_STRUCT(data);
564
565         if (!asn1_push_tag(&data, ASN1_SEQUENCE(0))) {
566                 return False;
567         }
568
569         for (num = 0; lssc[num]; num++) {
570                 if (!asn1_push_tag(&data, ASN1_SEQUENCE(0))) {
571                         return False;
572                 }
573                 
574                 if (!asn1_write_OctetString(&data, lssc[num]->attributeName, strlen(lssc[num]->attributeName))) {
575                         return False;
576                 }
577
578                 if (lssc[num]->orderingRule) {
579                         if (!asn1_write_OctetString(&data, lssc[num]->orderingRule, strlen(lssc[num]->orderingRule))) {
580                                 return False;
581                         }
582                 }
583
584                 if (lssc[num]->reverse) {
585                         if (!asn1_write_BOOLEAN(&data, lssc[num]->reverse)) {
586                                 return False;
587                         }
588                 }
589
590                 if (!asn1_pop_tag(&data)) {
591                         return False;
592                 }
593         }
594
595         if (!asn1_pop_tag(&data)) {
596                 return False;
597         }
598
599         *out = data_blob_talloc(mem_ctx, data.data, data.length);
600         if (out->data == NULL) {
601                 return False;
602         }
603
604         return True;
605 }
606
607 static BOOL encode_extended_dn_request(void *mem_ctx, void *in, DATA_BLOB *out)
608 {
609         struct ldb_extended_dn_control *ledc = talloc_get_type(in, struct ldb_extended_dn_control);
610         struct asn1_data data;
611
612         ZERO_STRUCT(data);
613
614         if (!asn1_push_tag(&data, ASN1_SEQUENCE(0))) {
615                 return False;
616         }
617
618         if (!asn1_write_Integer(&data, ledc->type)) {
619                 return False;
620         }
621
622         if (!asn1_pop_tag(&data)) {
623                 return False;
624         }
625
626         *out = data_blob_talloc(mem_ctx, data.data, data.length);
627         if (out->data == NULL) {
628                 return False;
629         }
630
631         return True;
632 }
633
634 static BOOL encode_paged_results_request(void *mem_ctx, void *in, DATA_BLOB *out)
635 {
636         struct ldb_paged_control *lprc = talloc_get_type(in, struct ldb_paged_control);
637         struct asn1_data data;
638
639         ZERO_STRUCT(data);
640
641         if (!asn1_push_tag(&data, ASN1_SEQUENCE(0))) {
642                 return False;
643         }
644
645         if (!asn1_write_Integer(&data, lprc->size)) {
646                 return False;
647         }
648
649         if (!asn1_write_OctetString(&data, lprc->cookie, lprc->cookie_len)) {
650                 return False;
651         }       
652
653         if (!asn1_pop_tag(&data)) {
654                 return False;
655         }
656
657         *out = data_blob_talloc(mem_ctx, data.data, data.length);
658         if (out->data == NULL) {
659                 return False;
660         }
661
662         return True;
663 }
664
665 /* seem that this controls has 2 forms one in case it is used with
666  * a Search Request and another when used ina Search Response
667  */
668 static BOOL encode_asq_control(void *mem_ctx, void *in, DATA_BLOB *out)
669 {
670         struct ldb_asq_control *lac = talloc_get_type(in, struct ldb_asq_control);
671         struct asn1_data data;
672
673         ZERO_STRUCT(data);
674
675         if (!asn1_push_tag(&data, ASN1_SEQUENCE(0))) {
676                 return False;
677         }
678
679         if (lac->request) {
680
681                 if (!asn1_write_OctetString(&data, lac->source_attribute, lac->src_attr_len)) {
682                         return False;
683                 }
684         } else {
685                 if (!asn1_write_enumerated(&data, lac->result)) {
686                         return False;
687                 }
688         }
689
690         if (!asn1_pop_tag(&data)) {
691                 return False;
692         }
693
694         *out = data_blob_talloc(mem_ctx, data.data, data.length);
695         if (out->data == NULL) {
696                 return False;
697         }
698
699         return True;
700 }
701
702 static BOOL encode_dirsync_request(void *mem_ctx, void *in, DATA_BLOB *out)
703 {
704         struct ldb_dirsync_control *ldc = talloc_get_type(in, struct ldb_dirsync_control);
705         struct asn1_data data;
706
707         ZERO_STRUCT(data);
708
709         if (!asn1_push_tag(&data, ASN1_SEQUENCE(0))) {
710                 return False;
711         }
712
713         if (!asn1_write_Integer(&data, ldc->flags)) {
714                 return False;
715         }
716
717         if (!asn1_write_Integer(&data, ldc->max_attributes)) {
718                 return False;
719         }
720
721         if (!asn1_write_OctetString(&data, ldc->cookie, ldc->cookie_len)) {
722                 return False;
723         }       
724
725         if (!asn1_pop_tag(&data)) {
726                 return False;
727         }
728
729         *out = data_blob_talloc(mem_ctx, data.data, data.length);
730         if (out->data == NULL) {
731                 return False;
732         }
733
734         return True;
735 }
736
737 static BOOL encode_notification_request(void *mem_ctx, void *in, DATA_BLOB *out)
738 {
739         if (in) {
740                 return False;
741         }
742
743         *out = data_blob(NULL, 0);
744         return True;
745 }
746
747 static BOOL encode_manageDSAIT_request(void *mem_ctx, void *in, DATA_BLOB *out)
748 {
749         if (in) {
750                 return False;
751         }
752
753         *out = data_blob(NULL, 0);
754         return True;
755 }
756
757 static BOOL encode_vlv_request(void *mem_ctx, void *in, DATA_BLOB *out)
758 {
759         struct ldb_vlv_req_control *lvrc = talloc_get_type(in, struct ldb_vlv_req_control);
760         struct asn1_data data;
761
762         ZERO_STRUCT(data);
763
764         if (!asn1_push_tag(&data, ASN1_SEQUENCE(0))) {
765                 return False;
766         }
767
768         if (!asn1_write_Integer(&data, lvrc->beforeCount)) {
769                 return False;
770         }
771
772         if (!asn1_write_Integer(&data, lvrc->afterCount)) {
773                 return False;
774         }
775
776         if (lvrc->type == 0) {
777                 if (!asn1_push_tag(&data, ASN1_CONTEXT(0))) {
778                         return False;
779                 }
780                 
781                 if (!asn1_push_tag(&data, ASN1_SEQUENCE(0))) {
782                         return False;
783                 }
784                 
785                 if (!asn1_write_Integer(&data, lvrc->match.byOffset.offset)) {
786                         return False;
787                 }
788
789                 if (!asn1_write_Integer(&data, lvrc->match.byOffset.contentCount)) {
790                         return False;
791                 }
792
793                 if (!asn1_pop_tag(&data)) { /*SEQUENCE*/
794                         return False;
795                 }
796
797                 if (!asn1_pop_tag(&data)) { /*CONTEXT*/
798                         return False;
799                 }
800         } else {
801                 if (!asn1_push_tag(&data, ASN1_CONTEXT(1))) {
802                         return False;
803                 }
804                 
805                 if (!asn1_write_OctetString(&data, lvrc->match.gtOrEq.value, lvrc->match.gtOrEq.value_len)) {
806                         return False;
807                 }
808
809                 if (!asn1_pop_tag(&data)) { /*CONTEXT*/
810                         return False;
811                 }
812         }
813
814         if (lvrc->ctxid_len) {
815                 if (!asn1_write_OctetString(&data, lvrc->contextId, lvrc->ctxid_len)) {
816                         return False;
817                 }
818         }
819
820         if (!asn1_pop_tag(&data)) {
821                 return False;
822         }
823
824         *out = data_blob_talloc(mem_ctx, data.data, data.length);
825         if (out->data == NULL) {
826                 return False;
827         }
828
829         return True;
830 }
831
832 static BOOL encode_vlv_response(void *mem_ctx, void *in, DATA_BLOB *out)
833 {
834         struct ldb_vlv_resp_control *lvrc = talloc_get_type(in, struct ldb_vlv_resp_control);
835         struct asn1_data data;
836
837         ZERO_STRUCT(data);
838
839         if (!asn1_push_tag(&data, ASN1_SEQUENCE(0))) {
840                 return False;
841         }
842
843         if (!asn1_write_Integer(&data, lvrc->targetPosition)) {
844                 return False;
845         }
846
847         if (!asn1_write_Integer(&data, lvrc->contentCount)) {
848                 return False;
849         }
850
851         if (!asn1_write_enumerated(&data, lvrc->vlv_result)) {
852                 return False;
853         }
854
855         if (lvrc->ctxid_len) {
856                 if (!asn1_write_OctetString(&data, lvrc->contextId, lvrc->ctxid_len)) {
857                         return False;
858                 }
859         }
860
861         if (!asn1_pop_tag(&data)) {
862                 return False;
863         }
864
865         *out = data_blob_talloc(mem_ctx, data.data, data.length);
866         if (out->data == NULL) {
867                 return False;
868         }
869
870         return True;
871 }
872
873 struct control_handler ldap_known_controls[] = {
874         { "1.2.840.113556.1.4.319", decode_paged_results_request, encode_paged_results_request },
875         { "1.2.840.113556.1.4.529", decode_extended_dn_request, encode_extended_dn_request },
876         { "1.2.840.113556.1.4.473", decode_server_sort_request, encode_server_sort_request },
877         { "1.2.840.113556.1.4.474", decode_server_sort_response, encode_server_sort_response },
878         { "1.2.840.113556.1.4.1504", decode_asq_control, encode_asq_control },
879         { "1.2.840.113556.1.4.841", decode_dirsync_request, encode_dirsync_request },
880         { "1.2.840.113556.1.4.528", decode_notification_request, encode_notification_request },
881         { "2.16.840.1.113730.3.4.2", decode_manageDSAIT_request, encode_manageDSAIT_request },
882         { "2.16.840.1.113730.3.4.9", decode_vlv_request, encode_vlv_request },
883         { "2.16.840.1.113730.3.4.10", decode_vlv_response, encode_vlv_response },
884         { NULL, NULL, NULL }
885 };
886
887 BOOL ldap_decode_control(void *mem_ctx, struct asn1_data *data, struct ldb_control *ctrl)
888 {
889         int i;
890         DATA_BLOB oid;
891         DATA_BLOB value;
892
893         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
894                 return False;
895         }
896
897         if (!asn1_read_OctetString(data, &oid)) {
898                 return False;
899         }
900         ctrl->oid = talloc_strndup(mem_ctx, (char *)oid.data, oid.length);
901         if (!ctrl->oid) {
902                 return False;
903         }
904
905         if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
906                 BOOL critical;
907                 if (!asn1_read_BOOLEAN(data, &critical)) {
908                         return False;
909                 }
910                 ctrl->critical = critical;
911         } else {
912                 ctrl->critical = False;
913         }
914
915         ctrl->data = NULL;
916
917         if (!asn1_peek_tag(data, ASN1_OCTET_STRING)) {
918                 goto end_tag;
919         }
920
921         if (!asn1_read_OctetString(data, &value)) {
922                 return False;
923         }
924
925         for (i = 0; ldap_known_controls[i].oid != NULL; i++) {
926                 if (strcmp(ldap_known_controls[i].oid, ctrl->oid) == 0) {
927                         if (!ldap_known_controls[i].decode(mem_ctx, value, &ctrl->data)) {
928                                 return False;
929                         }
930                         break;
931                 }
932         }
933         if (ldap_known_controls[i].oid == NULL) {
934                 return False;
935         }
936
937 end_tag:
938         if (!asn1_end_tag(data)) {
939                 return False;
940         }
941
942         return True;
943 }
944
945 BOOL ldap_encode_control(void *mem_ctx, struct asn1_data *data, struct ldb_control *ctrl)
946 {
947         DATA_BLOB value;
948         int i;
949
950         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
951                 return False;
952         }
953
954         if (!asn1_write_OctetString(data, ctrl->oid, strlen(ctrl->oid))) {
955                 return False;
956         }
957
958         if (ctrl->critical) {
959                 if (!asn1_write_BOOLEAN(data, ctrl->critical)) {
960                         return False;
961                 }
962         }
963
964         if (!ctrl->data) {
965                 goto pop_tag;
966         }
967
968         for (i = 0; ldap_known_controls[i].oid != NULL; i++) {
969                 if (strcmp(ldap_known_controls[i].oid, ctrl->oid) == 0) {
970                         if (!ldap_known_controls[i].encode(mem_ctx, ctrl->data, &value)) {
971                                 return False;
972                         }
973                         break;
974                 }
975         }
976         if (ldap_known_controls[i].oid == NULL) {
977                 return False;
978         }
979
980         if (!asn1_write_OctetString(data, value.data, value.length)) {
981                 return False;
982         }
983
984 pop_tag:
985         if (!asn1_pop_tag(data)) {
986                 return False;
987         }
988
989         return True;
990 }