s4-ldap: handle VERIFY_NAME control encoding/decoding
[ddiss/samba.git] / source4 / libcli / ldap / ldap_controls.c
1 /* 
2    Unix SMB/CIFS mplementation.
3    LDAP protocol helper functions for SAMBA
4    
5    Copyright (C) Simo Sorce 2005
6     
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 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, see <http://www.gnu.org/licenses/>.
19    
20 */
21
22 #include "includes.h"
23 #include "../lib/util/asn1.h"
24 #include "libcli/ldap/libcli_ldap.h"
25 #include "libcli/ldap/ldap_proto.h"
26 #include "dsdb/samdb/samdb.h"
27
28 static bool decode_server_sort_response(void *mem_ctx, DATA_BLOB in, void *_out)
29 {
30         void **out = (void **)_out;
31         DATA_BLOB attr;
32         struct asn1_data *data = asn1_init(mem_ctx);
33         struct ldb_sort_resp_control *lsrc;
34
35         if (!data) return false;
36
37         if (!asn1_load(data, in)) {
38                 return false;
39         }
40
41         lsrc = talloc(mem_ctx, struct ldb_sort_resp_control);
42         if (!lsrc) {
43                 return false;
44         }
45
46         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
47                 return false;
48         }
49
50         if (!asn1_read_enumerated(data, &(lsrc->result))) {
51                 return false;
52         }
53
54         lsrc->attr_desc = NULL;
55         if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
56                 if (!asn1_read_OctetString(data, mem_ctx, &attr)) {
57                         return false;
58                 }
59                 lsrc->attr_desc = talloc_strndup(lsrc, (const char *)attr.data, attr.length);
60                 if (!lsrc->attr_desc) {
61                         return false;
62                 }
63         }
64
65         if (!asn1_end_tag(data)) {
66                 return false;
67         }
68
69         *out = lsrc;
70
71         return true;
72 }
73
74 static bool decode_server_sort_request(void *mem_ctx, DATA_BLOB in, void *_out)
75 {
76         void **out = (void **)_out;
77         DATA_BLOB attr;
78         DATA_BLOB rule;
79         struct asn1_data *data = asn1_init(mem_ctx);
80         struct ldb_server_sort_control **lssc;
81         int num;
82
83         if (!data) return false;
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, mem_ctx, &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, mem_ctx, &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_CONTEXT_SIMPLE(1))) {
129                         bool reverse;
130                         if (!asn1_read_BOOLEAN_context(data, &reverse, 1)) {
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         void **out = (void **)_out;
157         struct asn1_data *data;
158         struct ldb_extended_dn_control *ledc;
159
160         /* The content of this control is optional */
161         if (in.length == 0) {
162                 *out = NULL;
163                 return true;
164         }
165
166         data = asn1_init(mem_ctx);
167         if (!data) return false;
168
169         if (!asn1_load(data, in)) {
170                 return false;
171         }
172
173         ledc = talloc(mem_ctx, struct ldb_extended_dn_control);
174         if (!ledc) {
175                 return false;
176         }
177
178         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
179                 return false;
180         }
181
182         if (!asn1_read_Integer(data, &(ledc->type))) {
183                 return false;
184         }
185         
186         if (!asn1_end_tag(data)) {
187                 return false;
188         }
189
190         *out = ledc;
191
192         return true;
193 }
194
195 static bool decode_sd_flags_request(void *mem_ctx, DATA_BLOB in, void *_out)
196 {
197         void **out = (void **)_out;
198         struct asn1_data *data = asn1_init(mem_ctx);
199         struct ldb_sd_flags_control *lsdfc;
200
201         if (!data) return false;
202
203         if (!asn1_load(data, in)) {
204                 return false;
205         }
206
207         lsdfc = talloc(mem_ctx, struct ldb_sd_flags_control);
208         if (!lsdfc) {
209                 return false;
210         }
211
212         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
213                 return false;
214         }
215
216         if (!asn1_read_Integer(data, (int *) &(lsdfc->secinfo_flags))) {
217                 return false;
218         }
219
220         if (!asn1_end_tag(data)) {
221                 return false;
222         }
223
224         *out = lsdfc;
225
226         return true;
227 }
228
229 static bool decode_search_options_request(void *mem_ctx, DATA_BLOB in, void *_out)
230 {
231         void **out = (void **)_out;
232         struct asn1_data *data = asn1_init(mem_ctx);
233         struct ldb_search_options_control *lsoc;
234
235         if (!data) return false;
236
237         if (!asn1_load(data, in)) {
238                 return false;
239         }
240
241         lsoc = talloc(mem_ctx, struct ldb_search_options_control);
242         if (!lsoc) {
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, (int *) &(lsoc->search_options))) {
251                 return false;
252         }
253
254         if (!asn1_end_tag(data)) {
255                 return false;
256         }
257
258         *out = lsoc;
259
260         return true;
261 }
262
263 static bool decode_paged_results_request(void *mem_ctx, DATA_BLOB in, void *_out)
264 {
265         void **out = (void **)_out;
266         DATA_BLOB cookie;
267         struct asn1_data *data = asn1_init(mem_ctx);
268         struct ldb_paged_control *lprc;
269
270         if (!data) return false;
271
272         if (!asn1_load(data, in)) {
273                 return false;
274         }
275
276         lprc = talloc(mem_ctx, struct ldb_paged_control);
277         if (!lprc) {
278                 return false;
279         }
280
281         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
282                 return false;
283         }
284
285         if (!asn1_read_Integer(data, &(lprc->size))) {
286                 return false;
287         }
288         
289         if (!asn1_read_OctetString(data, mem_ctx, &cookie)) {
290                 return false;
291         }
292         lprc->cookie_len = cookie.length;
293         if (lprc->cookie_len) {
294                 lprc->cookie = talloc_memdup(lprc, cookie.data, cookie.length);
295
296                 if (!(lprc->cookie)) {
297                         return false;
298                 }
299         } else {
300                 lprc->cookie = NULL;
301         }
302
303         if (!asn1_end_tag(data)) {
304                 return false;
305         }
306
307         *out = lprc;
308
309         return true;
310 }
311
312 static bool decode_dirsync_request(void *mem_ctx, DATA_BLOB in, void *_out)
313 {
314         void **out = (void **)_out;
315         DATA_BLOB cookie;
316         struct asn1_data *data = asn1_init(mem_ctx);
317         struct ldb_dirsync_control *ldc;
318
319         if (!data) return false;
320
321         if (!asn1_load(data, in)) {
322                 return false;
323         }
324
325         ldc = talloc(mem_ctx, struct ldb_dirsync_control);
326         if (!ldc) {
327                 return false;
328         }
329
330         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
331                 return false;
332         }
333
334         if (!asn1_read_Integer(data, &(ldc->flags))) {
335                 return false;
336         }
337         
338         if (!asn1_read_Integer(data, &(ldc->max_attributes))) {
339                 return false;
340         }
341         
342         if (!asn1_read_OctetString(data, mem_ctx, &cookie)) {
343                 return false;
344         }
345         ldc->cookie_len = cookie.length;
346         if (ldc->cookie_len) {
347                 ldc->cookie = talloc_memdup(ldc, cookie.data, cookie.length);
348
349                 if (!(ldc->cookie)) {
350                         return false;
351                 }
352         } else {
353                 ldc->cookie = NULL;
354         }
355
356         if (!asn1_end_tag(data)) {
357                 return false;
358         }
359
360         *out = ldc;
361
362         return true;
363 }
364
365 /* seem that this controls has 2 forms one in case it is used with
366  * a Search Request and another when used ina Search Response
367  */
368 static bool decode_asq_control(void *mem_ctx, DATA_BLOB in, void *_out)
369 {
370         void **out = (void **)_out;
371         DATA_BLOB source_attribute;
372         struct asn1_data *data = asn1_init(mem_ctx);
373         struct ldb_asq_control *lac;
374
375         if (!data) return false;
376
377         if (!asn1_load(data, in)) {
378                 return false;
379         }
380
381         lac = talloc(mem_ctx, struct ldb_asq_control);
382         if (!lac) {
383                 return false;
384         }
385
386         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
387                 return false;
388         }
389
390         if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
391
392                 if (!asn1_read_OctetString(data, mem_ctx, &source_attribute)) {
393                         return false;
394                 }
395                 lac->src_attr_len = source_attribute.length;
396                 if (lac->src_attr_len) {
397                         lac->source_attribute = talloc_strndup(lac, (const char *)source_attribute.data, source_attribute.length);
398
399                         if (!(lac->source_attribute)) {
400                                 return false;
401                         }
402                 } else {
403                         lac->source_attribute = NULL;
404                 }
405
406                 lac->request = 1;
407
408         } else if (asn1_peek_tag(data, ASN1_ENUMERATED)) {
409
410                 if (!asn1_read_enumerated(data, &(lac->result))) {
411                         return false;
412                 }
413
414                 lac->request = 0;
415
416         } else {
417                 return false;
418         }
419
420         if (!asn1_end_tag(data)) {
421                 return false;
422         }
423
424         *out = lac;
425
426         return true;
427 }
428
429 static bool decode_verify_name_request(void *mem_ctx, DATA_BLOB in, void *_out)
430 {
431         void **out = (void **)_out;
432         DATA_BLOB name;
433         struct asn1_data *data = asn1_init(mem_ctx);
434         struct ldb_verify_name_control *lvnc;
435         int len;
436
437         if (!data) return false;
438
439         if (!asn1_load(data, in)) {
440                 return false;
441         }
442
443         lvnc = talloc(mem_ctx, struct ldb_verify_name_control);
444         if (!lvnc) {
445                 return false;
446         }
447
448         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
449                 return false;
450         }
451
452         if (!asn1_read_Integer(data, &(lvnc->flags))) {
453                 return false;
454         }
455
456         if (!asn1_read_OctetString(data, mem_ctx, &name)) {
457                 return false;
458         }
459
460         if (name.length) {
461                 len = utf16_len_n(name.data, name.length);
462                 convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX,
463                                         name.data, len,
464                                         (void **)&lvnc->gc, &lvnc->gc_len);
465
466                 if (!(lvnc->gc)) {
467                         return false;
468                 }
469         } else {
470                 lvnc->gc_len = 0;
471                 lvnc->gc = NULL;
472         }
473
474         if (!asn1_end_tag(data)) {
475                 return false;
476         }
477
478         *out = lvnc;
479         return true;
480 }
481
482 static bool encode_verify_name_request(void *mem_ctx, void *in, DATA_BLOB *out)
483 {
484         struct ldb_verify_name_control *lvnc = talloc_get_type(in, struct ldb_verify_name_control);
485         struct asn1_data *data = asn1_init(mem_ctx);
486         DATA_BLOB gc_utf16;
487
488         if (!data) return false;
489
490         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
491                 return false;
492         }
493
494         if (!asn1_write_Integer(data, lvnc->flags)) {
495                 return false;
496         }
497
498         if (lvnc->gc_len) {
499                 convert_string_talloc(mem_ctx, CH_UNIX, CH_UTF16,
500                                                 lvnc->gc, lvnc->gc_len,
501                                                 (void **)&gc_utf16.data, &gc_utf16.length);
502                 if (!asn1_write_OctetString(data, gc_utf16.data, gc_utf16.length)) {
503                         return false;
504                 }
505         } else {
506                 if (!asn1_write_OctetString(data, NULL, 0)) {
507                         return false;
508                 }
509         }
510
511         if (!asn1_pop_tag(data)) {
512                 return false;
513         }
514
515         *out = data_blob_talloc(mem_ctx, data->data, data->length);
516         if (out->data == NULL) {
517                 return false;
518         }
519         talloc_free(data);
520
521         return true;
522 }
523
524 static bool decode_vlv_request(void *mem_ctx, DATA_BLOB in, void *_out)
525 {
526         void **out = (void **)_out;
527         DATA_BLOB assertion_value, context_id;
528         struct asn1_data *data = asn1_init(mem_ctx);
529         struct ldb_vlv_req_control *lvrc;
530
531         if (!data) return false;
532
533         if (!asn1_load(data, in)) {
534                 return false;
535         }
536
537         lvrc = talloc(mem_ctx, struct ldb_vlv_req_control);
538         if (!lvrc) {
539                 return false;
540         }
541
542         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
543                 return false;
544         }
545
546         if (!asn1_read_Integer(data, &(lvrc->beforeCount))) {
547                 return false;
548         }
549         
550         if (!asn1_read_Integer(data, &(lvrc->afterCount))) {
551                 return false;
552         }
553
554         if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
555
556                 lvrc->type = 0;
557                 
558                 if (!asn1_start_tag(data, ASN1_CONTEXT(0))) {
559                         return false;
560                 }
561
562                 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
563                         return false;
564                 }
565
566                 if (!asn1_read_Integer(data, &(lvrc->match.byOffset.offset))) {
567                         return false;
568                 }
569
570                 if (!asn1_read_Integer(data, &(lvrc->match.byOffset.contentCount))) {
571                         return false;
572                 }
573
574                 if (!asn1_end_tag(data)) { /*SEQUENCE*/
575                         return false;
576                 }
577
578                 if (!asn1_end_tag(data)) { /*CONTEXT*/
579                         return false;
580                 }
581
582         } else {
583
584                 lvrc->type = 1;
585
586                 if (!asn1_start_tag(data, ASN1_CONTEXT(1))) {
587                         return false;
588                 }
589
590                 if (!asn1_read_OctetString(data, mem_ctx, &assertion_value)) {
591                         return false;
592                 }
593                 lvrc->match.gtOrEq.value_len = assertion_value.length;
594                 if (lvrc->match.gtOrEq.value_len) {
595                         lvrc->match.gtOrEq.value = talloc_memdup(lvrc, assertion_value.data, assertion_value.length);
596
597                         if (!(lvrc->match.gtOrEq.value)) {
598                                 return false;
599                         }
600                 } else {
601                         lvrc->match.gtOrEq.value = NULL;
602                 }
603
604                 if (!asn1_end_tag(data)) { /*CONTEXT*/
605                         return false;
606                 }
607         }
608
609         if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
610                 if (!asn1_read_OctetString(data, mem_ctx, &context_id)) {
611                         return false;
612                 }
613                 lvrc->ctxid_len = context_id.length;
614                 if (lvrc->ctxid_len) {
615                         lvrc->contextId = talloc_memdup(lvrc, context_id.data, context_id.length);
616
617                         if (!(lvrc->contextId)) {
618                                 return false;
619                         }
620                 } else {
621                         lvrc->contextId = NULL;
622                 }
623         } else {
624                 lvrc->contextId = NULL;
625                 lvrc->ctxid_len = 0;
626         }
627
628         if (!asn1_end_tag(data)) {
629                 return false;
630         }
631
632         *out = lvrc;
633
634         return true;
635 }
636
637 static bool decode_vlv_response(void *mem_ctx, DATA_BLOB in, void *_out)
638 {
639         void **out = (void **)_out;
640         DATA_BLOB context_id;
641         struct asn1_data *data = asn1_init(mem_ctx);
642         struct ldb_vlv_resp_control *lvrc;
643
644         if (!data) return false;
645
646         if (!asn1_load(data, in)) {
647                 return false;
648         }
649
650         lvrc = talloc(mem_ctx, struct ldb_vlv_resp_control);
651         if (!lvrc) {
652                 return false;
653         }
654
655         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
656                 return false;
657         }
658
659         if (!asn1_read_Integer(data, &(lvrc->targetPosition))) {
660                 return false;
661         }
662         
663         if (!asn1_read_Integer(data, &(lvrc->contentCount))) {
664                 return false;
665         }
666         
667         if (!asn1_read_enumerated(data, &(lvrc->vlv_result))) {
668                 return false;
669         }
670
671         if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
672                 if (!asn1_read_OctetString(data, mem_ctx, &context_id)) {
673                         return false;
674                 }
675                 lvrc->contextId = talloc_strndup(lvrc, (const char *)context_id.data, context_id.length);
676                 if (!lvrc->contextId) {
677                         return false;
678                 }
679                 lvrc->ctxid_len = context_id.length;
680         } else {
681                 lvrc->contextId = NULL;
682                 lvrc->ctxid_len = 0;
683         }
684
685         if (!asn1_end_tag(data)) {
686                 return false;
687         }
688
689         *out = lvrc;
690
691         return true;
692 }
693
694 static bool encode_server_sort_response(void *mem_ctx, void *in, DATA_BLOB *out)
695 {
696         struct ldb_sort_resp_control *lsrc = talloc_get_type(in, struct ldb_sort_resp_control);
697         struct asn1_data *data = asn1_init(mem_ctx);
698
699         if (!data) return false;
700
701         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
702                 return false;
703         }
704
705         if (!asn1_write_enumerated(data, lsrc->result)) {
706                 return false;
707         }
708
709         if (lsrc->attr_desc) {
710                 if (!asn1_write_OctetString(data, lsrc->attr_desc, strlen(lsrc->attr_desc))) {
711                         return false;
712                 }
713         }
714
715         if (!asn1_pop_tag(data)) {
716                 return false;
717         }
718
719         *out = data_blob_talloc(mem_ctx, data->data, data->length);
720         if (out->data == NULL) {
721                 return false;
722         }
723         talloc_free(data);
724
725         return true;
726 }
727
728 static bool encode_server_sort_request(void *mem_ctx, void *in, DATA_BLOB *out)
729 {
730         struct ldb_server_sort_control **lssc = talloc_get_type(in, struct ldb_server_sort_control *);
731         struct asn1_data *data = asn1_init(mem_ctx);
732         int num;
733
734         if (!data) return false;
735
736         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
737                 return false;
738         }
739
740         /*
741           RFC2891 section 1.1:
742             SortKeyList ::= SEQUENCE OF SEQUENCE {
743               attributeType   AttributeDescription,
744               orderingRule    [0] MatchingRuleId OPTIONAL,
745               reverseOrder    [1] BOOLEAN DEFAULT FALSE }
746         */
747         for (num = 0; lssc[num]; num++) {
748                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
749                         return false;
750                 }
751                 
752                 if (!asn1_write_OctetString(data, lssc[num]->attributeName, strlen(lssc[num]->attributeName))) {
753                         return false;
754                 }
755
756                 if (lssc[num]->orderingRule) {
757                         if (!asn1_write_OctetString(data, lssc[num]->orderingRule, strlen(lssc[num]->orderingRule))) {
758                                 return false;
759                         }
760                 }
761
762                 if (lssc[num]->reverse) {
763                         if (!asn1_write_BOOLEAN_context(data, lssc[num]->reverse, 1)) {
764                                 return false;
765                         }
766                 }
767
768                 if (!asn1_pop_tag(data)) {
769                         return false;
770                 }
771         }
772
773         if (!asn1_pop_tag(data)) {
774                 return false;
775         }
776
777         *out = data_blob_talloc(mem_ctx, data->data, data->length);
778         if (out->data == NULL) {
779                 return false;
780         }
781         talloc_free(data);
782
783         return true;
784 }
785
786 static bool encode_extended_dn_request(void *mem_ctx, void *in, DATA_BLOB *out)
787 {
788         struct ldb_extended_dn_control *ledc = talloc_get_type(in, struct ldb_extended_dn_control);
789         struct asn1_data *data;
790
791         if (!in) {
792                 *out = data_blob(NULL, 0);
793                 return true;
794         }
795
796         data = asn1_init(mem_ctx);
797
798         if (!data) return false;
799
800         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
801                 return false;
802         }
803
804         if (!asn1_write_Integer(data, ledc->type)) {
805                 return false;
806         }
807
808         if (!asn1_pop_tag(data)) {
809                 return false;
810         }
811
812         *out = data_blob_talloc(mem_ctx, data->data, data->length);
813         if (out->data == NULL) {
814                 return false;
815         }
816         talloc_free(data);
817
818         return true;
819 }
820
821 static bool encode_sd_flags_request(void *mem_ctx, void *in, DATA_BLOB *out)
822 {
823         struct ldb_sd_flags_control *lsdfc = talloc_get_type(in, struct ldb_sd_flags_control);
824         struct asn1_data *data = asn1_init(mem_ctx);
825
826         if (!data) return false;
827
828         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
829                 return false;
830         }
831
832         if (!asn1_write_Integer(data, lsdfc->secinfo_flags)) {
833                 return false;
834         }
835
836         if (!asn1_pop_tag(data)) {
837                 return false;
838         }
839
840         *out = data_blob_talloc(mem_ctx, data->data, data->length);
841         if (out->data == NULL) {
842                 return false;
843         }
844         talloc_free(data);
845
846         return true;
847 }
848
849 static bool encode_search_options_request(void *mem_ctx, void *in, DATA_BLOB *out)
850 {
851         struct ldb_search_options_control *lsoc = talloc_get_type(in, struct ldb_search_options_control);
852         struct asn1_data *data = asn1_init(mem_ctx);
853
854         if (!data) return false;
855
856         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
857                 return false;
858         }
859
860         if (!asn1_write_Integer(data, lsoc->search_options)) {
861                 return false;
862         }
863
864         if (!asn1_pop_tag(data)) {
865                 return false;
866         }
867
868         *out = data_blob_talloc(mem_ctx, data->data, data->length);
869         if (out->data == NULL) {
870                 return false;
871         }
872         talloc_free(data);
873
874         return true;
875 }
876
877 static bool encode_paged_results_request(void *mem_ctx, void *in, DATA_BLOB *out)
878 {
879         struct ldb_paged_control *lprc = talloc_get_type(in, struct ldb_paged_control);
880         struct asn1_data *data = asn1_init(mem_ctx);
881
882         if (!data) return false;
883
884         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
885                 return false;
886         }
887
888         if (!asn1_write_Integer(data, lprc->size)) {
889                 return false;
890         }
891
892         if (!asn1_write_OctetString(data, lprc->cookie, lprc->cookie_len)) {
893                 return false;
894         }       
895
896         if (!asn1_pop_tag(data)) {
897                 return false;
898         }
899
900         *out = data_blob_talloc(mem_ctx, data->data, data->length);
901         if (out->data == NULL) {
902                 return false;
903         }
904         talloc_free(data);
905
906         return true;
907 }
908
909 /* seem that this controls has 2 forms one in case it is used with
910  * a Search Request and another when used ina Search Response
911  */
912 static bool encode_asq_control(void *mem_ctx, void *in, DATA_BLOB *out)
913 {
914         struct ldb_asq_control *lac = talloc_get_type(in, struct ldb_asq_control);
915         struct asn1_data *data = asn1_init(mem_ctx);
916
917         if (!data) return false;
918
919         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
920                 return false;
921         }
922
923         if (lac->request) {
924
925                 if (!asn1_write_OctetString(data, lac->source_attribute, lac->src_attr_len)) {
926                         return false;
927                 }
928         } else {
929                 if (!asn1_write_enumerated(data, lac->result)) {
930                         return false;
931                 }
932         }
933
934         if (!asn1_pop_tag(data)) {
935                 return false;
936         }
937
938         *out = data_blob_talloc(mem_ctx, data->data, data->length);
939         if (out->data == NULL) {
940                 return false;
941         }
942         talloc_free(data);
943
944         return true;
945 }
946
947 static bool encode_dirsync_request(void *mem_ctx, void *in, DATA_BLOB *out)
948 {
949         struct ldb_dirsync_control *ldc = talloc_get_type(in, struct ldb_dirsync_control);
950         struct asn1_data *data = asn1_init(mem_ctx);
951
952         if (!data) return false;
953
954         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
955                 return false;
956         }
957
958         if (!asn1_write_Integer(data, ldc->flags)) {
959                 return false;
960         }
961
962         if (!asn1_write_Integer(data, ldc->max_attributes)) {
963                 return false;
964         }
965
966         if (!asn1_write_OctetString(data, ldc->cookie, ldc->cookie_len)) {
967                 return false;
968         }       
969
970         if (!asn1_pop_tag(data)) {
971                 return false;
972         }
973
974         *out = data_blob_talloc(mem_ctx, data->data, data->length);
975         if (out->data == NULL) {
976                 return false;
977         }
978         talloc_free(data);
979
980         return true;
981 }
982
983 static bool encode_vlv_request(void *mem_ctx, void *in, DATA_BLOB *out)
984 {
985         struct ldb_vlv_req_control *lvrc = talloc_get_type(in, struct ldb_vlv_req_control);
986         struct asn1_data *data = asn1_init(mem_ctx);
987
988         if (!data) return false;
989
990         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
991                 return false;
992         }
993
994         if (!asn1_write_Integer(data, lvrc->beforeCount)) {
995                 return false;
996         }
997
998         if (!asn1_write_Integer(data, lvrc->afterCount)) {
999                 return false;
1000         }
1001
1002         if (lvrc->type == 0) {
1003                 if (!asn1_push_tag(data, ASN1_CONTEXT(0))) {
1004                         return false;
1005                 }
1006                 
1007                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1008                         return false;
1009                 }
1010                 
1011                 if (!asn1_write_Integer(data, lvrc->match.byOffset.offset)) {
1012                         return false;
1013                 }
1014
1015                 if (!asn1_write_Integer(data, lvrc->match.byOffset.contentCount)) {
1016                         return false;
1017                 }
1018
1019                 if (!asn1_pop_tag(data)) { /*SEQUENCE*/
1020                         return false;
1021                 }
1022
1023                 if (!asn1_pop_tag(data)) { /*CONTEXT*/
1024                         return false;
1025                 }
1026         } else {
1027                 if (!asn1_push_tag(data, ASN1_CONTEXT(1))) {
1028                         return false;
1029                 }
1030                 
1031                 if (!asn1_write_OctetString(data, lvrc->match.gtOrEq.value, lvrc->match.gtOrEq.value_len)) {
1032                         return false;
1033                 }
1034
1035                 if (!asn1_pop_tag(data)) { /*CONTEXT*/
1036                         return false;
1037                 }
1038         }
1039
1040         if (lvrc->ctxid_len) {
1041                 if (!asn1_write_OctetString(data, lvrc->contextId, lvrc->ctxid_len)) {
1042                         return false;
1043                 }
1044         }
1045
1046         if (!asn1_pop_tag(data)) {
1047                 return false;
1048         }
1049
1050         *out = data_blob_talloc(mem_ctx, data->data, data->length);
1051         if (out->data == NULL) {
1052                 return false;
1053         }
1054         talloc_free(data);
1055
1056         return true;
1057 }
1058
1059 static bool encode_vlv_response(void *mem_ctx, void *in, DATA_BLOB *out)
1060 {
1061         struct ldb_vlv_resp_control *lvrc = talloc_get_type(in, struct ldb_vlv_resp_control);
1062         struct asn1_data *data = asn1_init(mem_ctx);
1063
1064         if (!data) return false;
1065
1066         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1067                 return false;
1068         }
1069
1070         if (!asn1_write_Integer(data, lvrc->targetPosition)) {
1071                 return false;
1072         }
1073
1074         if (!asn1_write_Integer(data, lvrc->contentCount)) {
1075                 return false;
1076         }
1077
1078         if (!asn1_write_enumerated(data, lvrc->vlv_result)) {
1079                 return false;
1080         }
1081
1082         if (lvrc->ctxid_len) {
1083                 if (!asn1_write_OctetString(data, lvrc->contextId, lvrc->ctxid_len)) {
1084                         return false;
1085                 }
1086         }
1087
1088         if (!asn1_pop_tag(data)) {
1089                 return false;
1090         }
1091
1092         *out = data_blob_talloc(mem_ctx, data->data, data->length);
1093         if (out->data == NULL) {
1094                 return false;
1095         }
1096         talloc_free(data);
1097
1098         return true;
1099 }
1100
1101 static bool encode_openldap_dereference(void *mem_ctx, void *in, DATA_BLOB *out)
1102 {
1103         struct dsdb_openldap_dereference_control *control = talloc_get_type(in, struct dsdb_openldap_dereference_control);
1104         int i,j;
1105         struct asn1_data *data = asn1_init(mem_ctx);
1106
1107         if (!data) return false;
1108         
1109         if (!control) return false;
1110         
1111         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1112                 return false;
1113         }
1114         
1115         for (i=0; control->dereference && control->dereference[i]; i++) {
1116                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1117                         return false;
1118                 }
1119                 if (!asn1_write_OctetString(data, control->dereference[i]->source_attribute, strlen(control->dereference[i]->source_attribute))) {
1120                         return false;
1121                 }
1122                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1123                         return false;
1124                 }
1125                 for (j=0; control->dereference && control->dereference[i]->dereference_attribute[j]; j++) {
1126                         if (!asn1_write_OctetString(data, control->dereference[i]->dereference_attribute[j], 
1127                                                     strlen(control->dereference[i]->dereference_attribute[j]))) {
1128                                 return false;
1129                         }
1130                 }
1131                 
1132                 asn1_pop_tag(data);
1133                 asn1_pop_tag(data);
1134         }
1135         asn1_pop_tag(data);
1136
1137         *out = data_blob_talloc(mem_ctx, data->data, data->length);
1138         if (out->data == NULL) {
1139                 return false;
1140         }
1141         talloc_free(data);
1142         return true;
1143 }
1144
1145 static bool decode_openldap_dereference(void *mem_ctx, DATA_BLOB in, void *_out)
1146 {
1147         void **out = (void **)_out;
1148         struct asn1_data *data = asn1_init(mem_ctx);
1149         struct dsdb_openldap_dereference_result_control *control;
1150         struct dsdb_openldap_dereference_result **r = NULL;
1151         int i = 0;
1152         if (!data) return false;
1153
1154         control = talloc(mem_ctx, struct dsdb_openldap_dereference_result_control);
1155         if (!control) return false;
1156
1157         if (!asn1_load(data, in)) {
1158                 return false;
1159         }
1160
1161         control = talloc(mem_ctx, struct dsdb_openldap_dereference_result_control);
1162         if (!control) {
1163                 return false;
1164         }
1165
1166         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
1167                 return false;
1168         }
1169
1170         while (asn1_tag_remaining(data) > 0) {                                  
1171                 r = talloc_realloc(control, r, struct dsdb_openldap_dereference_result *, i + 2);
1172                 if (!r) {
1173                         return false;
1174                 }
1175                 r[i] = talloc_zero(r, struct dsdb_openldap_dereference_result);
1176                 if (!r[i]) {
1177                         return false;
1178                 }
1179
1180                 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
1181                         return false;
1182                 }
1183                 
1184                 asn1_read_OctetString_talloc(r[i], data, &r[i]->source_attribute);
1185                 asn1_read_OctetString_talloc(r[i], data, &r[i]->dereferenced_dn);
1186                 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1187                         if (!asn1_start_tag(data, ASN1_CONTEXT(0))) {
1188                                 return false;
1189                         }
1190                         
1191                         ldap_decode_attribs_bare(r, data, &r[i]->attributes,
1192                                                  &r[i]->num_attributes);
1193                         
1194                         if (!asn1_end_tag(data)) {
1195                                 return false;
1196                         }
1197                 }
1198                 if (!asn1_end_tag(data)) {
1199                         return false;
1200                 }
1201                 i++;
1202                 r[i] = NULL;
1203         }
1204
1205         if (!asn1_end_tag(data)) {
1206                 return false;
1207         }
1208
1209         control->attributes = r;
1210         *out = control;
1211
1212         return true;
1213 }
1214
1215 static bool encode_flag_request(void *mem_ctx, void *in, DATA_BLOB *out)
1216 {
1217         if (in) {
1218                 return false;
1219         }
1220
1221         *out = data_blob(NULL, 0);
1222         return true;
1223 }
1224
1225 static bool decode_flag_request(void *mem_ctx, DATA_BLOB in, void *_out)
1226 {
1227         if (in.length != 0) {
1228                 return false;
1229         }
1230
1231         return true;
1232 }
1233
1234 static const struct ldap_control_handler ldap_known_controls[] = {
1235         { LDB_CONTROL_PAGED_RESULTS_OID, decode_paged_results_request, encode_paged_results_request },
1236         { LDB_CONTROL_SD_FLAGS_OID, decode_sd_flags_request, encode_sd_flags_request },
1237         { LDB_CONTROL_DOMAIN_SCOPE_OID, decode_flag_request, encode_flag_request },
1238         { LDB_CONTROL_SEARCH_OPTIONS_OID, decode_search_options_request, encode_search_options_request },
1239         { LDB_CONTROL_NOTIFICATION_OID, decode_flag_request, encode_flag_request },
1240         { LDB_CONTROL_TREE_DELETE_OID, decode_flag_request, encode_flag_request },
1241         { LDB_CONTROL_SHOW_DELETED_OID, decode_flag_request, encode_flag_request },
1242         { LDB_CONTROL_SHOW_RECYCLED_OID, decode_flag_request, encode_flag_request },
1243         { LDB_CONTROL_SHOW_DEACTIVATED_LINK_OID, decode_flag_request, encode_flag_request },
1244         { LDB_CONTROL_EXTENDED_DN_OID, decode_extended_dn_request, encode_extended_dn_request },
1245         { LDB_CONTROL_SERVER_SORT_OID, decode_server_sort_request, encode_server_sort_request },
1246         { LDB_CONTROL_SORT_RESP_OID, decode_server_sort_response, encode_server_sort_response },
1247         { LDB_CONTROL_ASQ_OID, decode_asq_control, encode_asq_control },
1248         { LDB_CONTROL_DIRSYNC_OID, decode_dirsync_request, encode_dirsync_request },
1249         { LDB_CONTROL_VLV_REQ_OID, decode_vlv_request, encode_vlv_request },
1250         { LDB_CONTROL_VLV_RESP_OID, decode_vlv_response, encode_vlv_response },
1251         { LDB_CONTROL_PERMISSIVE_MODIFY_OID, decode_flag_request, encode_flag_request },
1252         { LDB_CONTROL_SERVER_LAZY_COMMIT, decode_flag_request, encode_flag_request },
1253         { LDB_CONTROL_RODC_DCPROMO_OID, decode_flag_request, encode_flag_request },
1254         { LDB_CONTROL_RELAX_OID, decode_flag_request, encode_flag_request },
1255         { DSDB_OPENLDAP_DEREFERENCE_CONTROL, decode_openldap_dereference, encode_openldap_dereference },
1256         { LDB_CONTROL_VERIFY_NAME_OID, decode_verify_name_request, encode_verify_name_request },
1257
1258         /* the following are internal only, with a network
1259            representation */
1260         { DSDB_CONTROL_BYPASS_PASSWORD_HASH_OID, decode_flag_request, encode_flag_request },
1261
1262         /* all the ones below are internal only, and have no network
1263          * representation */
1264         { DSDB_CONTROL_CURRENT_PARTITION_OID, NULL, NULL },
1265         { DSDB_CONTROL_REPLICATED_UPDATE_OID, NULL, NULL },
1266         { DSDB_CONTROL_DN_STORAGE_FORMAT_OID, NULL, NULL },
1267         { LDB_CONTROL_RECALCULATE_SD_OID, NULL, NULL },
1268         { LDB_CONTROL_REVEAL_INTERNALS, NULL, NULL },
1269         { LDB_CONTROL_AS_SYSTEM_OID, NULL, NULL },
1270         { DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID, NULL, NULL },
1271         { DSDB_CONTROL_PASSWORD_HASH_VALUES_OID, NULL, NULL },
1272         { DSDB_CONTROL_PASSWORD_CHANGE_OID, NULL, NULL },
1273         { DSDB_CONTROL_APPLY_LINKS, NULL, NULL },
1274         { LDB_CONTROL_BYPASS_OPERATIONAL_OID, NULL, NULL },
1275         { DSDB_CONTROL_CHANGEREPLMETADATA_OID, NULL, NULL },
1276         { LDB_CONTROL_PROVISION_OID, NULL, NULL },
1277         { DSDB_EXTENDED_REPLICATED_OBJECTS_OID, NULL, NULL },
1278         { DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID, NULL, NULL },
1279         { DSDB_EXTENDED_ALLOCATE_RID_POOL, NULL, NULL },
1280         { DSDB_CONTROL_NO_GLOBAL_CATALOG, NULL, NULL },
1281         { DSDB_EXTENDED_SCHEMA_UPGRADE_IN_PROGRESS_OID, NULL, NULL },
1282         { NULL, NULL, NULL }
1283 };
1284
1285 const struct ldap_control_handler *samba_ldap_control_handlers(void)
1286 {
1287         return ldap_known_controls;
1288 }
1289