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