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