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