ctdb-scripts: Move connection tracking to 10.interface
[samba4-gss.git] / source4 / libcli / ldap / ldap_controls.c
blob8d3a40f602e31b3f0bd0ebebaf6dcc152b29dd53
1 /*
2 Unix SMB/CIFS implementation.
3 LDAP protocol helper functions for SAMBA
5 Copyright (C) Simo Sorce 2005
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.
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.
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/>.
22 #include "includes.h"
24 #include <ldb.h>
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"
31 static bool decode_server_sort_response(void *mem_ctx, DATA_BLOB in, void *_out)
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;
38 if (!data) return false;
40 if (!asn1_load(data, in)) {
41 return false;
44 lsrc = talloc(mem_ctx, struct ldb_sort_resp_control);
45 if (!lsrc) {
46 return false;
49 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
50 return false;
53 if (!asn1_read_enumerated(data, &(lsrc->result))) {
54 return false;
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;
62 lsrc->attr_desc = talloc_strndup(lsrc, (const char *)attr.data, attr.length);
63 if (!lsrc->attr_desc) {
64 return false;
68 if (!asn1_end_tag(data)) {
69 return false;
72 *out = lsrc;
74 return true;
77 static bool decode_server_sort_request(void *mem_ctx, DATA_BLOB in, void *_out)
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;
86 if (!data) return false;
88 if (!asn1_load(data, in)) {
89 return false;
92 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
93 return false;
96 lssc = NULL;
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;
103 lssc[num] = talloc_zero(lssc, struct ldb_server_sort_control);
104 if (!lssc[num]) {
105 return false;
108 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
109 return false;
112 if (!asn1_read_OctetString(data, mem_ctx, &attr)) {
113 return false;
116 lssc[num]->attributeName = talloc_strndup(lssc[num], (const char *)attr.data, attr.length);
117 if (!lssc [num]->attributeName) {
118 return false;
121 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
122 if (!asn1_read_ContextSimple(data, mem_ctx, 0, &rule)) {
123 return false;
125 lssc[num]->orderingRule = talloc_strndup(lssc[num], (const char *)rule.data, rule.length);
126 if (!lssc[num]->orderingRule) {
127 return false;
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;
136 lssc[num]->reverse = reverse;
139 if (!asn1_end_tag(data)) {
140 return false;
144 if (lssc != NULL) {
145 lssc[num] = NULL;
148 if (!asn1_end_tag(data)) {
149 return false;
152 *out = lssc;
154 return true;
157 static bool decode_extended_dn_request(void *mem_ctx, DATA_BLOB in, void *_out)
159 void **out = _out;
160 struct asn1_data *data;
161 struct ldb_extended_dn_control *ledc;
163 /* The content of this control is optional */
164 if (in.length == 0) {
165 *out = NULL;
166 return true;
169 data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
170 if (!data) return false;
172 if (!asn1_load(data, in)) {
173 return false;
176 ledc = talloc(mem_ctx, struct ldb_extended_dn_control);
177 if (!ledc) {
178 return false;
181 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
182 return false;
185 if (!asn1_read_Integer(data, &(ledc->type))) {
186 return false;
189 if (!asn1_end_tag(data)) {
190 return false;
193 *out = ledc;
195 return true;
198 static bool decode_sd_flags_request(void *mem_ctx, DATA_BLOB in, void *_out)
200 void **out = _out;
201 struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
202 struct ldb_sd_flags_control *lsdfc;
204 if (!data) return false;
206 if (!asn1_load(data, in)) {
207 return false;
210 lsdfc = talloc(mem_ctx, struct ldb_sd_flags_control);
211 if (!lsdfc) {
212 return false;
215 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
216 return false;
219 if (!asn1_read_Integer(data, (int *) &(lsdfc->secinfo_flags))) {
220 return false;
223 if (!asn1_end_tag(data)) {
224 return false;
227 *out = lsdfc;
229 return true;
232 static bool decode_search_options_request(void *mem_ctx, DATA_BLOB in, void *_out)
234 void **out = _out;
235 struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
236 struct ldb_search_options_control *lsoc;
238 if (!data) return false;
240 if (!asn1_load(data, in)) {
241 return false;
244 lsoc = talloc(mem_ctx, struct ldb_search_options_control);
245 if (!lsoc) {
246 return false;
249 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
250 return false;
253 if (!asn1_read_Integer(data, (int *) &(lsoc->search_options))) {
254 return false;
257 if (!asn1_end_tag(data)) {
258 return false;
261 *out = lsoc;
263 return true;
266 static bool decode_paged_results_request(void *mem_ctx, DATA_BLOB in, void *_out)
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;
273 if (!data) return false;
275 if (!asn1_load(data, in)) {
276 return false;
279 lprc = talloc(mem_ctx, struct ldb_paged_control);
280 if (!lprc) {
281 return false;
284 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
285 return false;
288 if (!asn1_read_Integer(data, &(lprc->size))) {
289 return false;
292 if (!asn1_read_OctetString(data, mem_ctx, &cookie)) {
293 return false;
295 lprc->cookie_len = cookie.length;
296 if (lprc->cookie_len) {
297 lprc->cookie = talloc_memdup(lprc, cookie.data, cookie.length);
299 if (!(lprc->cookie)) {
300 return false;
302 } else {
303 lprc->cookie = NULL;
306 if (!asn1_end_tag(data)) {
307 return false;
310 *out = lprc;
312 return true;
315 static bool decode_dirsync_request(void *mem_ctx, DATA_BLOB in, void *_out)
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;
322 if (!data) return false;
324 if (!asn1_load(data, in)) {
325 return false;
328 ldc = talloc(mem_ctx, struct ldb_dirsync_control);
329 if (!ldc) {
330 return false;
333 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
334 return false;
337 if (!asn1_read_Integer(data, &(ldc->flags))) {
338 return false;
341 if (!asn1_read_Integer(data, &(ldc->max_attributes))) {
342 return false;
345 if (!asn1_read_OctetString(data, mem_ctx, &cookie)) {
346 return false;
348 ldc->cookie_len = cookie.length;
349 if (ldc->cookie_len) {
350 ldc->cookie = talloc_memdup(ldc, cookie.data, cookie.length);
352 if (!(ldc->cookie)) {
353 return false;
355 } else {
356 ldc->cookie = NULL;
359 if (!asn1_end_tag(data)) {
360 return false;
363 *out = ldc;
365 return true;
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
371 static bool decode_asq_control(void *mem_ctx, DATA_BLOB in, void *_out)
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;
378 if (!data) return false;
380 if (!asn1_load(data, in)) {
381 return false;
384 lac = talloc(mem_ctx, struct ldb_asq_control);
385 if (!lac) {
386 return false;
389 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
390 return false;
393 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
395 if (!asn1_read_OctetString(data, mem_ctx, &source_attribute)) {
396 return false;
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);
402 if (!(lac->source_attribute)) {
403 return false;
405 } else {
406 lac->source_attribute = NULL;
409 lac->request = 1;
411 } else if (asn1_peek_tag(data, ASN1_ENUMERATED)) {
413 if (!asn1_read_enumerated(data, &(lac->result))) {
414 return false;
417 lac->request = 0;
419 } else {
420 return false;
423 if (!asn1_end_tag(data)) {
424 return false;
427 *out = lac;
429 return true;
432 static bool decode_verify_name_request(void *mem_ctx, DATA_BLOB in, void *_out)
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;
440 if (!data) return false;
442 if (!asn1_load(data, in)) {
443 return false;
446 lvnc = talloc(mem_ctx, struct ldb_verify_name_control);
447 if (!lvnc) {
448 return false;
451 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
452 return false;
455 if (!asn1_read_Integer(data, &(lvnc->flags))) {
456 return false;
459 if (!asn1_read_OctetString(data, mem_ctx, &name)) {
460 return false;
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);
469 if (!(lvnc->gc)) {
470 return false;
472 } else {
473 lvnc->gc_len = 0;
474 lvnc->gc = NULL;
477 if (!asn1_end_tag(data)) {
478 return false;
481 *out = lvnc;
482 return true;
485 static bool encode_verify_name_request(void *mem_ctx, void *in, DATA_BLOB *out)
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;
491 if (!data) return false;
493 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
494 return false;
497 if (!asn1_write_Integer(data, lvnc->flags)) {
498 return false;
501 if (lvnc->gc_len) {
502 bool ok;
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;
510 if (!asn1_write_OctetString(data, gc_utf16.data, gc_utf16.length)) {
511 return false;
513 } else {
514 if (!asn1_write_OctetString(data, NULL, 0)) {
515 return false;
519 if (!asn1_pop_tag(data)) {
520 return false;
523 if (!asn1_extract_blob(data, mem_ctx, out)) {
524 return false;
527 talloc_free(data);
529 return true;
532 static bool decode_vlv_request(void *mem_ctx, DATA_BLOB in, void *_out)
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;
539 if (!data) return false;
541 if (!asn1_load(data, in)) {
542 return false;
545 lvrc = talloc(mem_ctx, struct ldb_vlv_req_control);
546 if (!lvrc) {
547 return false;
550 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
551 return false;
554 if (!asn1_read_Integer(data, &(lvrc->beforeCount))) {
555 return false;
558 if (!asn1_read_Integer(data, &(lvrc->afterCount))) {
559 return false;
562 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
564 lvrc->type = 0;
566 if (!asn1_start_tag(data, ASN1_CONTEXT(0))) {
567 return false;
570 if (!asn1_read_Integer(data, &(lvrc->match.byOffset.offset))) {
571 return false;
574 if (!asn1_read_Integer(data, &(lvrc->match.byOffset.contentCount))) {
575 return false;
578 if (!asn1_end_tag(data)) { /*CONTEXT*/
579 return false;
582 } else {
584 lvrc->type = 1;
586 if (!asn1_read_ContextSimple(data, mem_ctx, 1, &assertion_value)){
587 return false;
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);
594 if (!(lvrc->match.gtOrEq.value)) {
595 return false;
597 } else {
598 lvrc->match.gtOrEq.value = NULL;
602 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
603 if (!asn1_read_OctetString(data, mem_ctx, &context_id)) {
604 return false;
606 lvrc->ctxid_len = context_id.length;
607 if (lvrc->ctxid_len) {
608 lvrc->contextId = talloc_memdup(lvrc, context_id.data, context_id.length);
610 if (!(lvrc->contextId)) {
611 return false;
613 } else {
614 lvrc->contextId = NULL;
616 } else {
617 lvrc->contextId = NULL;
618 lvrc->ctxid_len = 0;
621 if (!asn1_end_tag(data)) {
622 return false;
625 *out = lvrc;
627 return true;
630 static bool decode_vlv_response(void *mem_ctx, DATA_BLOB in, void *_out)
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;
637 if (!data) return false;
639 if (!asn1_load(data, in)) {
640 return false;
643 lvrc = talloc(mem_ctx, struct ldb_vlv_resp_control);
644 if (!lvrc) {
645 return false;
648 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
649 return false;
652 if (!asn1_read_Integer(data, &(lvrc->targetPosition))) {
653 return false;
656 if (!asn1_read_Integer(data, &(lvrc->contentCount))) {
657 return false;
660 if (!asn1_read_enumerated(data, &(lvrc->vlv_result))) {
661 return false;
664 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
665 if (!asn1_read_OctetString(data, mem_ctx, &context_id)) {
666 return false;
668 lvrc->contextId = talloc_memdup(lvrc, (const char *)context_id.data, context_id.length);
669 if (!lvrc->contextId) {
670 return false;
672 lvrc->ctxid_len = context_id.length;
673 } else {
674 lvrc->contextId = NULL;
675 lvrc->ctxid_len = 0;
678 if (!asn1_end_tag(data)) {
679 return false;
682 *out = lvrc;
684 return true;
687 static bool encode_server_sort_response(void *mem_ctx, void *in, DATA_BLOB *out)
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);
692 if (!data) return false;
694 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
695 return false;
698 if (!asn1_write_enumerated(data, lsrc->result)) {
699 return false;
702 if (lsrc->attr_desc) {
703 if (!asn1_write_OctetString(data, lsrc->attr_desc, strlen(lsrc->attr_desc))) {
704 return false;
708 if (!asn1_pop_tag(data)) {
709 return false;
712 if (!asn1_extract_blob(data, mem_ctx, out)) {
713 return false;
716 talloc_free(data);
718 return true;
721 static bool encode_server_sort_request(void *mem_ctx, void *in, DATA_BLOB *out)
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;
727 if (!data) return false;
729 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
730 return false;
734 RFC2891 section 1.1:
735 SortKeyList ::= SEQUENCE OF SEQUENCE {
736 attributeType AttributeDescription,
737 orderingRule [0] MatchingRuleId OPTIONAL,
738 reverseOrder [1] BOOLEAN DEFAULT FALSE }
740 for (num = 0; lssc[num]; num++) {
741 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
742 return false;
745 if (!asn1_write_OctetString(data, lssc[num]->attributeName, strlen(lssc[num]->attributeName))) {
746 return false;
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;
756 if (lssc[num]->reverse) {
757 if (!asn1_write_BOOLEAN_context(data, lssc[num]->reverse, 1)) {
758 return false;
762 if (!asn1_pop_tag(data)) {
763 return false;
767 if (!asn1_pop_tag(data)) {
768 return false;
771 if (!asn1_extract_blob(data, mem_ctx, out)) {
772 return false;
775 talloc_free(data);
777 return true;
780 static bool encode_extended_dn_request(void *mem_ctx, void *in, DATA_BLOB *out)
782 struct ldb_extended_dn_control *ledc = talloc_get_type(in, struct ldb_extended_dn_control);
783 struct asn1_data *data;
785 if (!in) {
786 *out = data_blob(NULL, 0);
787 return true;
790 data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
792 if (!data) return false;
794 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
795 return false;
798 if (!asn1_write_Integer(data, ledc->type)) {
799 return false;
802 if (!asn1_pop_tag(data)) {
803 return false;
806 if (!asn1_extract_blob(data, mem_ctx, out)) {
807 return false;
810 talloc_free(data);
812 return true;
815 static bool encode_sd_flags_request(void *mem_ctx, void *in, DATA_BLOB *out)
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);
820 if (!data) return false;
822 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
823 return false;
826 if (!asn1_write_Integer(data, lsdfc->secinfo_flags)) {
827 return false;
830 if (!asn1_pop_tag(data)) {
831 return false;
834 if (!asn1_extract_blob(data, mem_ctx, out)) {
835 return false;
838 talloc_free(data);
840 return true;
843 static bool encode_search_options_request(void *mem_ctx, void *in, DATA_BLOB *out)
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);
848 if (!data) return false;
850 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
851 return false;
854 if (!asn1_write_Integer(data, lsoc->search_options)) {
855 return false;
858 if (!asn1_pop_tag(data)) {
859 return false;
862 if (!asn1_extract_blob(data, mem_ctx, out)) {
863 return false;
866 talloc_free(data);
868 return true;
871 static bool encode_paged_results_request(void *mem_ctx, void *in, DATA_BLOB *out)
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);
876 if (!data) return false;
878 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
879 return false;
882 if (!asn1_write_Integer(data, lprc->size)) {
883 return false;
886 if (!asn1_write_OctetString(data, lprc->cookie, lprc->cookie_len)) {
887 return false;
890 if (!asn1_pop_tag(data)) {
891 return false;
894 if (!asn1_extract_blob(data, mem_ctx, out)) {
895 return false;
898 talloc_free(data);
900 return true;
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
906 static bool encode_asq_control(void *mem_ctx, void *in, DATA_BLOB *out)
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);
911 if (!data) return false;
913 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
914 return false;
917 if (lac->request) {
919 if (!asn1_write_OctetString(data, lac->source_attribute, lac->src_attr_len)) {
920 return false;
922 } else {
923 if (!asn1_write_enumerated(data, lac->result)) {
924 return false;
928 if (!asn1_pop_tag(data)) {
929 return false;
932 if (!asn1_extract_blob(data, mem_ctx, out)) {
933 return false;
936 talloc_free(data);
938 return true;
941 static bool encode_dirsync_request(void *mem_ctx, void *in, DATA_BLOB *out)
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);
946 if (!data) return false;
948 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
949 return false;
952 if (!asn1_write_Integer(data, ldc->flags)) {
953 return false;
956 if (!asn1_write_Integer(data, ldc->max_attributes)) {
957 return false;
960 if (!asn1_write_OctetString(data, ldc->cookie, ldc->cookie_len)) {
961 return false;
964 if (!asn1_pop_tag(data)) {
965 return false;
968 if (!asn1_extract_blob(data, mem_ctx, out)) {
969 return false;
972 talloc_free(data);
974 return true;
977 static bool encode_vlv_request(void *mem_ctx, void *in, DATA_BLOB *out)
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);
982 if (!data) return false;
984 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
985 return false;
988 if (!asn1_write_Integer(data, lvrc->beforeCount)) {
989 return false;
992 if (!asn1_write_Integer(data, lvrc->afterCount)) {
993 return false;
996 if (lvrc->type == 0) {
997 if (!asn1_push_tag(data, ASN1_CONTEXT(0))) {
998 return false;
1001 if (!asn1_write_Integer(data, lvrc->match.byOffset.offset)) {
1002 return false;
1005 if (!asn1_write_Integer(data, lvrc->match.byOffset.contentCount)) {
1006 return false;
1009 if (!asn1_pop_tag(data)) { /*CONTEXT*/
1010 return false;
1012 } else {
1013 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1014 return false;
1017 if (!asn1_write(data, lvrc->match.gtOrEq.value, lvrc->match.gtOrEq.value_len)) {
1018 return false;
1021 if (!asn1_pop_tag(data)) { /*CONTEXT*/
1022 return false;
1026 if (lvrc->ctxid_len) {
1027 if (!asn1_write_OctetString(data, lvrc->contextId, lvrc->ctxid_len)) {
1028 return false;
1032 if (!asn1_pop_tag(data)) {
1033 return false;
1036 if (!asn1_extract_blob(data, mem_ctx, out)) {
1037 return false;
1040 talloc_free(data);
1042 return true;
1045 static bool encode_vlv_response(void *mem_ctx, void *in, DATA_BLOB *out)
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);
1050 if (!data) return false;
1052 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1053 return false;
1056 if (!asn1_write_Integer(data, lvrc->targetPosition)) {
1057 return false;
1060 if (!asn1_write_Integer(data, lvrc->contentCount)) {
1061 return false;
1064 if (!asn1_write_enumerated(data, lvrc->vlv_result)) {
1065 return false;
1068 if (lvrc->ctxid_len) {
1069 if (!asn1_write_OctetString(data, lvrc->contextId, lvrc->ctxid_len)) {
1070 return false;
1074 if (!asn1_pop_tag(data)) {
1075 return false;
1078 if (!asn1_extract_blob(data, mem_ctx, out)) {
1079 return false;
1082 talloc_free(data);
1084 return true;
1087 static bool encode_openldap_dereference(void *mem_ctx, void *in, DATA_BLOB *out)
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);
1093 if (!data) return false;
1095 if (!control) return false;
1097 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1098 return false;
1101 for (i=0; control->dereference && control->dereference[i]; i++) {
1102 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1103 return false;
1105 if (!asn1_write_OctetString(data, control->dereference[i]->source_attribute, strlen(control->dereference[i]->source_attribute))) {
1106 return false;
1108 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1109 return false;
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;
1118 if (!asn1_pop_tag(data)) {
1119 return false;
1121 if (!asn1_pop_tag(data)) {
1122 return false;
1125 if (!asn1_pop_tag(data)) {
1126 return false;
1129 if (!asn1_extract_blob(data, mem_ctx, out)) {
1130 return false;
1133 talloc_free(data);
1134 return true;
1137 static bool decode_openldap_dereference(void *mem_ctx, DATA_BLOB in, void *_out)
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;
1146 control = talloc(mem_ctx, struct dsdb_openldap_dereference_result_control);
1147 if (!control) return false;
1149 if (!asn1_load(data, in)) {
1150 return false;
1153 control = talloc(mem_ctx, struct dsdb_openldap_dereference_result_control);
1154 if (!control) {
1155 return false;
1158 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
1159 return false;
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;
1167 r[i] = talloc_zero(r, struct dsdb_openldap_dereference_result);
1168 if (!r[i]) {
1169 return false;
1172 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
1173 return false;
1176 if (!asn1_read_OctetString_talloc(r[i], data, &r[i]->source_attribute)) {
1177 return false;
1179 if (!asn1_read_OctetString_talloc(r[i], data, &r[i]->dereferenced_dn)) {
1180 return false;
1182 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1183 if (!asn1_start_tag(data, ASN1_CONTEXT(0))) {
1184 return false;
1186 if (!ldap_decode_attribs_bare(r, data, &r[i]->attributes,
1187 &r[i]->num_attributes)) {
1188 return false;
1190 if (!asn1_end_tag(data)) {
1191 return false;
1194 if (!asn1_end_tag(data)) {
1195 return false;
1197 i++;
1198 r[i] = NULL;
1201 if (!asn1_end_tag(data)) {
1202 return false;
1205 control->attributes = r;
1206 *out = control;
1208 return true;
1211 static bool encode_flag_request(void *mem_ctx, void *in, DATA_BLOB *out)
1213 if (in) {
1214 return false;
1217 *out = data_blob(NULL, 0);
1218 return true;
1221 static bool decode_flag_request(void *mem_ctx, DATA_BLOB in, void *_out)
1223 if (in.length != 0) {
1224 return false;
1227 return true;
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 },
1255 /* the following are internal only, with a network
1256 representation */
1257 { DSDB_CONTROL_BYPASS_PASSWORD_HASH_OID, decode_flag_request, encode_flag_request },
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 }
1306 const struct ldap_control_handler *samba_ldap_control_handlers(void)
1308 return ldap_known_controls;