863e5b66b9c1dd05f6e3262d26fa822eef010625
[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_OCTET_STRING)) {
122                         if (!asn1_read_OctetString(data, mem_ctx, &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_start_tag(data, ASN1_SEQUENCE(0))) {
566                         return false;
567                 }
568
569                 if (!asn1_read_Integer(data, &(lvrc->match.byOffset.offset))) {
570                         return false;
571                 }
572
573                 if (!asn1_read_Integer(data, &(lvrc->match.byOffset.contentCount))) {
574                         return false;
575                 }
576
577                 if (!asn1_end_tag(data)) { /*SEQUENCE*/
578                         return false;
579                 }
580
581                 if (!asn1_end_tag(data)) { /*CONTEXT*/
582                         return false;
583                 }
584
585         } else {
586
587                 lvrc->type = 1;
588
589                 if (!asn1_start_tag(data, ASN1_CONTEXT(1))) {
590                         return false;
591                 }
592
593                 if (!asn1_read_OctetString(data, mem_ctx, &assertion_value)) {
594                         return false;
595                 }
596                 lvrc->match.gtOrEq.value_len = assertion_value.length;
597                 if (lvrc->match.gtOrEq.value_len) {
598                         lvrc->match.gtOrEq.value = talloc_memdup(lvrc, assertion_value.data, assertion_value.length);
599
600                         if (!(lvrc->match.gtOrEq.value)) {
601                                 return false;
602                         }
603                 } else {
604                         lvrc->match.gtOrEq.value = NULL;
605                 }
606
607                 if (!asn1_end_tag(data)) { /*CONTEXT*/
608                         return false;
609                 }
610         }
611
612         if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
613                 if (!asn1_read_OctetString(data, mem_ctx, &context_id)) {
614                         return false;
615                 }
616                 lvrc->ctxid_len = context_id.length;
617                 if (lvrc->ctxid_len) {
618                         lvrc->contextId = talloc_memdup(lvrc, context_id.data, context_id.length);
619
620                         if (!(lvrc->contextId)) {
621                                 return false;
622                         }
623                 } else {
624                         lvrc->contextId = NULL;
625                 }
626         } else {
627                 lvrc->contextId = NULL;
628                 lvrc->ctxid_len = 0;
629         }
630
631         if (!asn1_end_tag(data)) {
632                 return false;
633         }
634
635         *out = lvrc;
636
637         return true;
638 }
639
640 static bool decode_vlv_response(void *mem_ctx, DATA_BLOB in, void *_out)
641 {
642         void **out = (void **)_out;
643         DATA_BLOB context_id;
644         struct asn1_data *data = asn1_init(mem_ctx);
645         struct ldb_vlv_resp_control *lvrc;
646
647         if (!data) return false;
648
649         if (!asn1_load(data, in)) {
650                 return false;
651         }
652
653         lvrc = talloc(mem_ctx, struct ldb_vlv_resp_control);
654         if (!lvrc) {
655                 return false;
656         }
657
658         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
659                 return false;
660         }
661
662         if (!asn1_read_Integer(data, &(lvrc->targetPosition))) {
663                 return false;
664         }
665         
666         if (!asn1_read_Integer(data, &(lvrc->contentCount))) {
667                 return false;
668         }
669         
670         if (!asn1_read_enumerated(data, &(lvrc->vlv_result))) {
671                 return false;
672         }
673
674         if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
675                 if (!asn1_read_OctetString(data, mem_ctx, &context_id)) {
676                         return false;
677                 }
678                 lvrc->contextId = talloc_strndup(lvrc, (const char *)context_id.data, context_id.length);
679                 if (!lvrc->contextId) {
680                         return false;
681                 }
682                 lvrc->ctxid_len = context_id.length;
683         } else {
684                 lvrc->contextId = NULL;
685                 lvrc->ctxid_len = 0;
686         }
687
688         if (!asn1_end_tag(data)) {
689                 return false;
690         }
691
692         *out = lvrc;
693
694         return true;
695 }
696
697 static bool encode_server_sort_response(void *mem_ctx, void *in, DATA_BLOB *out)
698 {
699         struct ldb_sort_resp_control *lsrc = talloc_get_type(in, struct ldb_sort_resp_control);
700         struct asn1_data *data = asn1_init(mem_ctx);
701
702         if (!data) return false;
703
704         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
705                 return false;
706         }
707
708         if (!asn1_write_enumerated(data, lsrc->result)) {
709                 return false;
710         }
711
712         if (lsrc->attr_desc) {
713                 if (!asn1_write_OctetString(data, lsrc->attr_desc, strlen(lsrc->attr_desc))) {
714                         return false;
715                 }
716         }
717
718         if (!asn1_pop_tag(data)) {
719                 return false;
720         }
721
722         if (!asn1_extract_blob(data, mem_ctx, out)) {
723                 return false;
724         }
725
726         talloc_free(data);
727
728         return true;
729 }
730
731 static bool encode_server_sort_request(void *mem_ctx, void *in, DATA_BLOB *out)
732 {
733         struct ldb_server_sort_control **lssc = talloc_get_type(in, struct ldb_server_sort_control *);
734         struct asn1_data *data = asn1_init(mem_ctx);
735         int num;
736
737         if (!data) return false;
738
739         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
740                 return false;
741         }
742
743         /*
744           RFC2891 section 1.1:
745             SortKeyList ::= SEQUENCE OF SEQUENCE {
746               attributeType   AttributeDescription,
747               orderingRule    [0] MatchingRuleId OPTIONAL,
748               reverseOrder    [1] BOOLEAN DEFAULT FALSE }
749         */
750         for (num = 0; lssc[num]; num++) {
751                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
752                         return false;
753                 }
754                 
755                 if (!asn1_write_OctetString(data, lssc[num]->attributeName, strlen(lssc[num]->attributeName))) {
756                         return false;
757                 }
758
759                 if (lssc[num]->orderingRule) {
760                         if (!asn1_write_OctetString(data, lssc[num]->orderingRule, strlen(lssc[num]->orderingRule))) {
761                                 return false;
762                         }
763                 }
764
765                 if (lssc[num]->reverse) {
766                         if (!asn1_write_BOOLEAN_context(data, lssc[num]->reverse, 1)) {
767                                 return false;
768                         }
769                 }
770
771                 if (!asn1_pop_tag(data)) {
772                         return false;
773                 }
774         }
775
776         if (!asn1_pop_tag(data)) {
777                 return false;
778         }
779
780         if (!asn1_extract_blob(data, mem_ctx, out)) {
781                 return false;
782         }
783
784         talloc_free(data);
785
786         return true;
787 }
788
789 static bool encode_extended_dn_request(void *mem_ctx, void *in, DATA_BLOB *out)
790 {
791         struct ldb_extended_dn_control *ledc = talloc_get_type(in, struct ldb_extended_dn_control);
792         struct asn1_data *data;
793
794         if (!in) {
795                 *out = data_blob(NULL, 0);
796                 return true;
797         }
798
799         data = asn1_init(mem_ctx);
800
801         if (!data) return false;
802
803         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
804                 return false;
805         }
806
807         if (!asn1_write_Integer(data, ledc->type)) {
808                 return false;
809         }
810
811         if (!asn1_pop_tag(data)) {
812                 return false;
813         }
814
815         if (!asn1_extract_blob(data, mem_ctx, out)) {
816                 return false;
817         }
818
819         talloc_free(data);
820
821         return true;
822 }
823
824 static bool encode_sd_flags_request(void *mem_ctx, void *in, DATA_BLOB *out)
825 {
826         struct ldb_sd_flags_control *lsdfc = talloc_get_type(in, struct ldb_sd_flags_control);
827         struct asn1_data *data = asn1_init(mem_ctx);
828
829         if (!data) return false;
830
831         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
832                 return false;
833         }
834
835         if (!asn1_write_Integer(data, lsdfc->secinfo_flags)) {
836                 return false;
837         }
838
839         if (!asn1_pop_tag(data)) {
840                 return false;
841         }
842
843         if (!asn1_extract_blob(data, mem_ctx, out)) {
844                 return false;
845         }
846
847         talloc_free(data);
848
849         return true;
850 }
851
852 static bool encode_search_options_request(void *mem_ctx, void *in, DATA_BLOB *out)
853 {
854         struct ldb_search_options_control *lsoc = talloc_get_type(in, struct ldb_search_options_control);
855         struct asn1_data *data = asn1_init(mem_ctx);
856
857         if (!data) return false;
858
859         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
860                 return false;
861         }
862
863         if (!asn1_write_Integer(data, lsoc->search_options)) {
864                 return false;
865         }
866
867         if (!asn1_pop_tag(data)) {
868                 return false;
869         }
870
871         if (!asn1_extract_blob(data, mem_ctx, out)) {
872                 return false;
873         }
874
875         talloc_free(data);
876
877         return true;
878 }
879
880 static bool encode_paged_results_request(void *mem_ctx, void *in, DATA_BLOB *out)
881 {
882         struct ldb_paged_control *lprc = talloc_get_type(in, struct ldb_paged_control);
883         struct asn1_data *data = asn1_init(mem_ctx);
884
885         if (!data) return false;
886
887         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
888                 return false;
889         }
890
891         if (!asn1_write_Integer(data, lprc->size)) {
892                 return false;
893         }
894
895         if (!asn1_write_OctetString(data, lprc->cookie, lprc->cookie_len)) {
896                 return false;
897         }       
898
899         if (!asn1_pop_tag(data)) {
900                 return false;
901         }
902
903         if (!asn1_extract_blob(data, mem_ctx, out)) {
904                 return false;
905         }
906
907         talloc_free(data);
908
909         return true;
910 }
911
912 /* seem that this controls has 2 forms one in case it is used with
913  * a Search Request and another when used ina Search Response
914  */
915 static bool encode_asq_control(void *mem_ctx, void *in, DATA_BLOB *out)
916 {
917         struct ldb_asq_control *lac = talloc_get_type(in, struct ldb_asq_control);
918         struct asn1_data *data = asn1_init(mem_ctx);
919
920         if (!data) return false;
921
922         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
923                 return false;
924         }
925
926         if (lac->request) {
927
928                 if (!asn1_write_OctetString(data, lac->source_attribute, lac->src_attr_len)) {
929                         return false;
930                 }
931         } else {
932                 if (!asn1_write_enumerated(data, lac->result)) {
933                         return false;
934                 }
935         }
936
937         if (!asn1_pop_tag(data)) {
938                 return false;
939         }
940
941         if (!asn1_extract_blob(data, mem_ctx, out)) {
942                 return false;
943         }
944
945         talloc_free(data);
946
947         return true;
948 }
949
950 static bool encode_dirsync_request(void *mem_ctx, void *in, DATA_BLOB *out)
951 {
952         struct ldb_dirsync_control *ldc = talloc_get_type(in, struct ldb_dirsync_control);
953         struct asn1_data *data = asn1_init(mem_ctx);
954
955         if (!data) return false;
956
957         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
958                 return false;
959         }
960
961         if (!asn1_write_Integer(data, ldc->flags)) {
962                 return false;
963         }
964
965         if (!asn1_write_Integer(data, ldc->max_attributes)) {
966                 return false;
967         }
968
969         if (!asn1_write_OctetString(data, ldc->cookie, ldc->cookie_len)) {
970                 return false;
971         }       
972
973         if (!asn1_pop_tag(data)) {
974                 return false;
975         }
976
977         if (!asn1_extract_blob(data, mem_ctx, out)) {
978                 return false;
979         }
980
981         talloc_free(data);
982
983         return true;
984 }
985
986 static bool encode_vlv_request(void *mem_ctx, void *in, DATA_BLOB *out)
987 {
988         struct ldb_vlv_req_control *lvrc = talloc_get_type(in, struct ldb_vlv_req_control);
989         struct asn1_data *data = asn1_init(mem_ctx);
990
991         if (!data) return false;
992
993         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
994                 return false;
995         }
996
997         if (!asn1_write_Integer(data, lvrc->beforeCount)) {
998                 return false;
999         }
1000
1001         if (!asn1_write_Integer(data, lvrc->afterCount)) {
1002                 return false;
1003         }
1004
1005         if (lvrc->type == 0) {
1006                 if (!asn1_push_tag(data, ASN1_CONTEXT(0))) {
1007                         return false;
1008                 }
1009                 
1010                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1011                         return false;
1012                 }
1013                 
1014                 if (!asn1_write_Integer(data, lvrc->match.byOffset.offset)) {
1015                         return false;
1016                 }
1017
1018                 if (!asn1_write_Integer(data, lvrc->match.byOffset.contentCount)) {
1019                         return false;
1020                 }
1021
1022                 if (!asn1_pop_tag(data)) { /*SEQUENCE*/
1023                         return false;
1024                 }
1025
1026                 if (!asn1_pop_tag(data)) { /*CONTEXT*/
1027                         return false;
1028                 }
1029         } else {
1030                 if (!asn1_push_tag(data, ASN1_CONTEXT(1))) {
1031                         return false;
1032                 }
1033                 
1034                 if (!asn1_write_OctetString(data, lvrc->match.gtOrEq.value, lvrc->match.gtOrEq.value_len)) {
1035                         return false;
1036                 }
1037
1038                 if (!asn1_pop_tag(data)) { /*CONTEXT*/
1039                         return false;
1040                 }
1041         }
1042
1043         if (lvrc->ctxid_len) {
1044                 if (!asn1_write_OctetString(data, lvrc->contextId, lvrc->ctxid_len)) {
1045                         return false;
1046                 }
1047         }
1048
1049         if (!asn1_pop_tag(data)) {
1050                 return false;
1051         }
1052
1053         if (!asn1_extract_blob(data, mem_ctx, out)) {
1054                 return false;
1055         }
1056
1057         talloc_free(data);
1058
1059         return true;
1060 }
1061
1062 static bool encode_vlv_response(void *mem_ctx, void *in, DATA_BLOB *out)
1063 {
1064         struct ldb_vlv_resp_control *lvrc = talloc_get_type(in, struct ldb_vlv_resp_control);
1065         struct asn1_data *data = asn1_init(mem_ctx);
1066
1067         if (!data) return false;
1068
1069         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1070                 return false;
1071         }
1072
1073         if (!asn1_write_Integer(data, lvrc->targetPosition)) {
1074                 return false;
1075         }
1076
1077         if (!asn1_write_Integer(data, lvrc->contentCount)) {
1078                 return false;
1079         }
1080
1081         if (!asn1_write_enumerated(data, lvrc->vlv_result)) {
1082                 return false;
1083         }
1084
1085         if (lvrc->ctxid_len) {
1086                 if (!asn1_write_OctetString(data, lvrc->contextId, lvrc->ctxid_len)) {
1087                         return false;
1088                 }
1089         }
1090
1091         if (!asn1_pop_tag(data)) {
1092                 return false;
1093         }
1094
1095         if (!asn1_extract_blob(data, mem_ctx, out)) {
1096                 return false;
1097         }
1098
1099         talloc_free(data);
1100
1101         return true;
1102 }
1103
1104 static bool encode_openldap_dereference(void *mem_ctx, void *in, DATA_BLOB *out)
1105 {
1106         struct dsdb_openldap_dereference_control *control = talloc_get_type(in, struct dsdb_openldap_dereference_control);
1107         int i,j;
1108         struct asn1_data *data = asn1_init(mem_ctx);
1109
1110         if (!data) return false;
1111         
1112         if (!control) return false;
1113         
1114         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1115                 return false;
1116         }
1117         
1118         for (i=0; control->dereference && control->dereference[i]; i++) {
1119                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1120                         return false;
1121                 }
1122                 if (!asn1_write_OctetString(data, control->dereference[i]->source_attribute, strlen(control->dereference[i]->source_attribute))) {
1123                         return false;
1124                 }
1125                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1126                         return false;
1127                 }
1128                 for (j=0; control->dereference && control->dereference[i]->dereference_attribute[j]; j++) {
1129                         if (!asn1_write_OctetString(data, control->dereference[i]->dereference_attribute[j], 
1130                                                     strlen(control->dereference[i]->dereference_attribute[j]))) {
1131                                 return false;
1132                         }
1133                 }
1134                 
1135                 if (!asn1_pop_tag(data)) {
1136                         return false;
1137                 }
1138                 if (!asn1_pop_tag(data)) {
1139                         return false;
1140                 }
1141         }
1142         if (!asn1_pop_tag(data)) {
1143                 return false;
1144         }
1145
1146         if (!asn1_extract_blob(data, mem_ctx, out)) {
1147                 return false;
1148         }
1149
1150         talloc_free(data);
1151         return true;
1152 }
1153
1154 static bool decode_openldap_dereference(void *mem_ctx, DATA_BLOB in, void *_out)
1155 {
1156         void **out = (void **)_out;
1157         struct asn1_data *data = asn1_init(mem_ctx);
1158         struct dsdb_openldap_dereference_result_control *control;
1159         struct dsdb_openldap_dereference_result **r = NULL;
1160         int i = 0;
1161         if (!data) return false;
1162
1163         control = talloc(mem_ctx, struct dsdb_openldap_dereference_result_control);
1164         if (!control) return false;
1165
1166         if (!asn1_load(data, in)) {
1167                 return false;
1168         }
1169
1170         control = talloc(mem_ctx, struct dsdb_openldap_dereference_result_control);
1171         if (!control) {
1172                 return false;
1173         }
1174
1175         if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
1176                 return false;
1177         }
1178
1179         while (asn1_tag_remaining(data) > 0) {                                  
1180                 r = talloc_realloc(control, r, struct dsdb_openldap_dereference_result *, i + 2);
1181                 if (!r) {
1182                         return false;
1183                 }
1184                 r[i] = talloc_zero(r, struct dsdb_openldap_dereference_result);
1185                 if (!r[i]) {
1186                         return false;
1187                 }
1188
1189                 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
1190                         return false;
1191                 }
1192                 
1193                 if (!asn1_read_OctetString_talloc(r[i], data, &r[i]->source_attribute)) {
1194                         return false;
1195                 }
1196                 if (!asn1_read_OctetString_talloc(r[i], data, &r[i]->dereferenced_dn)) {
1197                         return false;
1198                 }
1199                 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1200                         if (!asn1_start_tag(data, ASN1_CONTEXT(0))) {
1201                                 return false;
1202                         }
1203                         if (!ldap_decode_attribs_bare(r, data, &r[i]->attributes,
1204                                                  &r[i]->num_attributes)) {
1205                                 return false;
1206                         }
1207                         if (!asn1_end_tag(data)) {
1208                                 return false;
1209                         }
1210                 }
1211                 if (!asn1_end_tag(data)) {
1212                         return false;
1213                 }
1214                 i++;
1215                 r[i] = NULL;
1216         }
1217
1218         if (!asn1_end_tag(data)) {
1219                 return false;
1220         }
1221
1222         control->attributes = r;
1223         *out = control;
1224
1225         return true;
1226 }
1227
1228 static bool encode_flag_request(void *mem_ctx, void *in, DATA_BLOB *out)
1229 {
1230         if (in) {
1231                 return false;
1232         }
1233
1234         *out = data_blob(NULL, 0);
1235         return true;
1236 }
1237
1238 static bool decode_flag_request(void *mem_ctx, DATA_BLOB in, void *_out)
1239 {
1240         if (in.length != 0) {
1241                 return false;
1242         }
1243
1244         return true;
1245 }
1246
1247 static const struct ldap_control_handler ldap_known_controls[] = {
1248         { LDB_CONTROL_PAGED_RESULTS_OID, decode_paged_results_request, encode_paged_results_request },
1249         { LDB_CONTROL_SD_FLAGS_OID, decode_sd_flags_request, encode_sd_flags_request },
1250         { LDB_CONTROL_DOMAIN_SCOPE_OID, decode_flag_request, encode_flag_request },
1251         { LDB_CONTROL_SEARCH_OPTIONS_OID, decode_search_options_request, encode_search_options_request },
1252         { LDB_CONTROL_NOTIFICATION_OID, decode_flag_request, encode_flag_request },
1253         { LDB_CONTROL_TREE_DELETE_OID, decode_flag_request, encode_flag_request },
1254         { LDB_CONTROL_SHOW_DELETED_OID, decode_flag_request, encode_flag_request },
1255         { LDB_CONTROL_SHOW_RECYCLED_OID, decode_flag_request, encode_flag_request },
1256         { LDB_CONTROL_SHOW_DEACTIVATED_LINK_OID, decode_flag_request, encode_flag_request },
1257         { LDB_CONTROL_EXTENDED_DN_OID, decode_extended_dn_request, encode_extended_dn_request },
1258         { LDB_CONTROL_SERVER_SORT_OID, decode_server_sort_request, encode_server_sort_request },
1259         { LDB_CONTROL_SORT_RESP_OID, decode_server_sort_response, encode_server_sort_response },
1260         { LDB_CONTROL_ASQ_OID, decode_asq_control, encode_asq_control },
1261         { LDB_CONTROL_DIRSYNC_OID, decode_dirsync_request, encode_dirsync_request },
1262         { LDB_CONTROL_DIRSYNC_EX_OID, decode_dirsync_request, encode_dirsync_request },
1263         { LDB_CONTROL_VLV_REQ_OID, decode_vlv_request, encode_vlv_request },
1264         { LDB_CONTROL_VLV_RESP_OID, decode_vlv_response, encode_vlv_response },
1265         { LDB_CONTROL_PERMISSIVE_MODIFY_OID, decode_flag_request, encode_flag_request },
1266         { LDB_CONTROL_SERVER_LAZY_COMMIT, decode_flag_request, encode_flag_request },
1267         { LDB_CONTROL_RODC_DCPROMO_OID, decode_flag_request, encode_flag_request },
1268         { LDB_CONTROL_RELAX_OID, decode_flag_request, encode_flag_request },
1269         { DSDB_OPENLDAP_DEREFERENCE_CONTROL, decode_openldap_dereference, encode_openldap_dereference },
1270         { LDB_CONTROL_VERIFY_NAME_OID, decode_verify_name_request, encode_verify_name_request },
1271
1272         /* the following are internal only, with a network
1273            representation */
1274         { DSDB_CONTROL_BYPASS_PASSWORD_HASH_OID, decode_flag_request, encode_flag_request },
1275
1276         /* all the ones below are internal only, and have no network
1277          * representation */
1278         { DSDB_CONTROL_CURRENT_PARTITION_OID, NULL, NULL },
1279         { DSDB_CONTROL_REPLICATED_UPDATE_OID, NULL, NULL },
1280         { DSDB_CONTROL_DN_STORAGE_FORMAT_OID, NULL, NULL },
1281         { LDB_CONTROL_RECALCULATE_SD_OID, NULL, NULL },
1282         { LDB_CONTROL_REVEAL_INTERNALS, NULL, NULL },
1283         { LDB_CONTROL_AS_SYSTEM_OID, NULL, NULL },
1284         { DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID, NULL, NULL },
1285         { DSDB_CONTROL_PASSWORD_HASH_VALUES_OID, NULL, NULL },
1286         { DSDB_CONTROL_PASSWORD_CHANGE_OID, NULL, NULL },
1287         { DSDB_CONTROL_APPLY_LINKS, NULL, NULL },
1288         { LDB_CONTROL_BYPASS_OPERATIONAL_OID, NULL, NULL },
1289         { DSDB_CONTROL_CHANGEREPLMETADATA_OID, NULL, NULL },
1290         { LDB_CONTROL_PROVISION_OID, NULL, NULL },
1291         { DSDB_EXTENDED_REPLICATED_OBJECTS_OID, NULL, NULL },
1292         { DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID, NULL, NULL },
1293         { DSDB_EXTENDED_ALLOCATE_RID_POOL, NULL, NULL },
1294         { DSDB_CONTROL_NO_GLOBAL_CATALOG, NULL, NULL },
1295         { DSDB_EXTENDED_SCHEMA_UPGRADE_IN_PROGRESS_OID, NULL, NULL },
1296         { NULL, NULL, NULL }
1297 };
1298
1299 const struct ldap_control_handler *samba_ldap_control_handlers(void)
1300 {
1301         return ldap_known_controls;
1302 }
1303