2
Unix SMB/CIFS mplementation.
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/>.
23
#include "../lib/util/asn1.h"
24
#include "libcli/ldap/ldap.h"
25
#include "lib/ldb/include/ldb.h"
26
#include "libcli/ldap/ldap_proto.h"
27
#include "dsdb/samdb/samdb.h"
29
static bool decode_server_sort_response(void *mem_ctx, DATA_BLOB in, void *_out)
31
void **out = (void **)_out;
33
struct asn1_data *data = asn1_init(mem_ctx);
34
struct ldb_sort_resp_control *lsrc;
36
if (!data) return false;
38
if (!asn1_load(data, in)) {
42
lsrc = talloc(mem_ctx, struct ldb_sort_resp_control);
47
if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
51
if (!asn1_read_enumerated(data, &(lsrc->result))) {
55
lsrc->attr_desc = NULL;
56
if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
57
if (!asn1_read_OctetString(data, mem_ctx, &attr)) {
60
lsrc->attr_desc = talloc_strndup(lsrc, (const char *)attr.data, attr.length);
61
if (!lsrc->attr_desc) {
66
if (!asn1_end_tag(data)) {
75
static bool decode_server_sort_request(void *mem_ctx, DATA_BLOB in, void *_out)
77
void **out = (void **)_out;
80
struct asn1_data *data = asn1_init(mem_ctx);
81
struct ldb_server_sort_control **lssc;
84
if (!data) return false;
86
if (!asn1_load(data, in)) {
90
if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
96
for (num = 0; asn1_peek_tag(data, ASN1_SEQUENCE(0)); num++) {
97
lssc = talloc_realloc(mem_ctx, lssc, struct ldb_server_sort_control *, num + 2);
101
lssc[num] = talloc_zero(lssc, struct ldb_server_sort_control);
106
if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
110
if (!asn1_read_OctetString(data, mem_ctx, &attr)) {
114
lssc[num]->attributeName = talloc_strndup(lssc[num], (const char *)attr.data, attr.length);
115
if (!lssc [num]->attributeName) {
119
if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
120
if (!asn1_read_OctetString(data, mem_ctx, &rule)) {
123
lssc[num]->orderingRule = talloc_strndup(lssc[num], (const char *)rule.data, rule.length);
124
if (!lssc[num]->orderingRule) {
129
if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
131
if (!asn1_read_BOOLEAN(data, &reverse)) {
134
lssc[num]->reverse = reverse;
137
if (!asn1_end_tag(data)) {
146
if (!asn1_end_tag(data)) {
155
static bool decode_extended_dn_request(void *mem_ctx, DATA_BLOB in, void *_out)
157
void **out = (void **)_out;
158
struct asn1_data *data;
159
struct ldb_extended_dn_control *ledc;
161
/* The content of this control is optional */
162
if (in.length == 0) {
167
data = asn1_init(mem_ctx);
168
if (!data) return false;
170
if (!asn1_load(data, in)) {
174
ledc = talloc(mem_ctx, struct ldb_extended_dn_control);
179
if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
183
if (!asn1_read_Integer(data, &(ledc->type))) {
187
if (!asn1_end_tag(data)) {
196
static bool decode_sd_flags_request(void *mem_ctx, DATA_BLOB in, void *_out)
198
void **out = (void **)_out;
199
struct asn1_data *data = asn1_init(mem_ctx);
200
struct ldb_sd_flags_control *lsdfc;
202
if (!data) return false;
204
if (!asn1_load(data, in)) {
208
lsdfc = talloc(mem_ctx, struct ldb_sd_flags_control);
213
if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
217
if (!asn1_read_Integer(data, &(lsdfc->secinfo_flags))) {
221
if (!asn1_end_tag(data)) {
230
static bool decode_search_options_request(void *mem_ctx, DATA_BLOB in, void *_out)
232
void **out = (void **)_out;
233
struct asn1_data *data = asn1_init(mem_ctx);
234
struct ldb_search_options_control *lsoc;
236
if (!data) return false;
238
if (!asn1_load(data, in)) {
242
lsoc = talloc(mem_ctx, struct ldb_search_options_control);
247
if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
251
if (!asn1_read_Integer(data, &(lsoc->search_options))) {
255
if (!asn1_end_tag(data)) {
264
static bool decode_paged_results_request(void *mem_ctx, DATA_BLOB in, void *_out)
266
void **out = (void **)_out;
268
struct asn1_data *data = asn1_init(mem_ctx);
269
struct ldb_paged_control *lprc;
271
if (!data) return false;
273
if (!asn1_load(data, in)) {
277
lprc = talloc(mem_ctx, struct ldb_paged_control);
282
if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
286
if (!asn1_read_Integer(data, &(lprc->size))) {
290
if (!asn1_read_OctetString(data, mem_ctx, &cookie)) {
293
lprc->cookie_len = cookie.length;
294
if (lprc->cookie_len) {
295
lprc->cookie = talloc_memdup(lprc, cookie.data, cookie.length);
297
if (!(lprc->cookie)) {
304
if (!asn1_end_tag(data)) {
313
static bool decode_dirsync_request(void *mem_ctx, DATA_BLOB in, void *_out)
315
void **out = (void **)_out;
317
struct asn1_data *data = asn1_init(mem_ctx);
318
struct ldb_dirsync_control *ldc;
320
if (!data) return false;
322
if (!asn1_load(data, in)) {
326
ldc = talloc(mem_ctx, struct ldb_dirsync_control);
331
if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
335
if (!asn1_read_Integer(data, &(ldc->flags))) {
339
if (!asn1_read_Integer(data, &(ldc->max_attributes))) {
343
if (!asn1_read_OctetString(data, mem_ctx, &cookie)) {
346
ldc->cookie_len = cookie.length;
347
if (ldc->cookie_len) {
348
ldc->cookie = talloc_memdup(ldc, cookie.data, cookie.length);
350
if (!(ldc->cookie)) {
357
if (!asn1_end_tag(data)) {
366
/* seem that this controls has 2 forms one in case it is used with
367
* a Search Request and another when used ina Search Response
369
static bool decode_asq_control(void *mem_ctx, DATA_BLOB in, void *_out)
371
void **out = (void **)_out;
372
DATA_BLOB source_attribute;
373
struct asn1_data *data = asn1_init(mem_ctx);
374
struct ldb_asq_control *lac;
376
if (!data) return false;
378
if (!asn1_load(data, in)) {
382
lac = talloc(mem_ctx, struct ldb_asq_control);
387
if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
391
if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
393
if (!asn1_read_OctetString(data, mem_ctx, &source_attribute)) {
396
lac->src_attr_len = source_attribute.length;
397
if (lac->src_attr_len) {
398
lac->source_attribute = talloc_strndup(lac, (const char *)source_attribute.data, source_attribute.length);
400
if (!(lac->source_attribute)) {
404
lac->source_attribute = NULL;
409
} else if (asn1_peek_tag(data, ASN1_ENUMERATED)) {
411
if (!asn1_read_enumerated(data, &(lac->result))) {
421
if (!asn1_end_tag(data)) {
430
static bool decode_domain_scope_request(void *mem_ctx, DATA_BLOB in, void *_out)
432
if (in.length != 0) {
439
static bool decode_notification_request(void *mem_ctx, DATA_BLOB in, void *_out)
441
if (in.length != 0) {
448
static bool decode_show_deleted_request(void *mem_ctx, DATA_BLOB in, void *_out)
450
if (in.length != 0) {
457
static bool decode_permissive_modify_request(void *mem_ctx, DATA_BLOB in, void *_out)
459
if (in.length != 0) {
466
static bool decode_manageDSAIT_request(void *mem_ctx, DATA_BLOB in, void *_out)
468
if (in.length != 0) {
475
static bool decode_vlv_request(void *mem_ctx, DATA_BLOB in, void *_out)
477
void **out = (void **)_out;
478
DATA_BLOB assertion_value, context_id;
479
struct asn1_data *data = asn1_init(mem_ctx);
480
struct ldb_vlv_req_control *lvrc;
482
if (!data) return false;
484
if (!asn1_load(data, in)) {
488
lvrc = talloc(mem_ctx, struct ldb_vlv_req_control);
493
if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
497
if (!asn1_read_Integer(data, &(lvrc->beforeCount))) {
501
if (!asn1_read_Integer(data, &(lvrc->afterCount))) {
505
if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
509
if (!asn1_start_tag(data, ASN1_CONTEXT(0))) {
513
if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
517
if (!asn1_read_Integer(data, &(lvrc->match.byOffset.offset))) {
521
if (!asn1_read_Integer(data, &(lvrc->match.byOffset.contentCount))) {
525
if (!asn1_end_tag(data)) { /*SEQUENCE*/
529
if (!asn1_end_tag(data)) { /*CONTEXT*/
537
if (!asn1_start_tag(data, ASN1_CONTEXT(1))) {
541
if (!asn1_read_OctetString(data, mem_ctx, &assertion_value)) {
544
lvrc->match.gtOrEq.value_len = assertion_value.length;
545
if (lvrc->match.gtOrEq.value_len) {
546
lvrc->match.gtOrEq.value = talloc_memdup(lvrc, assertion_value.data, assertion_value.length);
548
if (!(lvrc->match.gtOrEq.value)) {
552
lvrc->match.gtOrEq.value = NULL;
555
if (!asn1_end_tag(data)) { /*CONTEXT*/
560
if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
561
if (!asn1_read_OctetString(data, mem_ctx, &context_id)) {
564
lvrc->ctxid_len = context_id.length;
565
if (lvrc->ctxid_len) {
566
lvrc->contextId = talloc_memdup(lvrc, context_id.data, context_id.length);
568
if (!(lvrc->contextId)) {
572
lvrc->contextId = NULL;
575
lvrc->contextId = NULL;
579
if (!asn1_end_tag(data)) {
588
static bool decode_vlv_response(void *mem_ctx, DATA_BLOB in, void *_out)
590
void **out = (void **)_out;
591
DATA_BLOB context_id;
592
struct asn1_data *data = asn1_init(mem_ctx);
593
struct ldb_vlv_resp_control *lvrc;
595
if (!data) return false;
597
if (!asn1_load(data, in)) {
601
lvrc = talloc(mem_ctx, struct ldb_vlv_resp_control);
606
if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
610
if (!asn1_read_Integer(data, &(lvrc->targetPosition))) {
614
if (!asn1_read_Integer(data, &(lvrc->contentCount))) {
618
if (!asn1_read_enumerated(data, &(lvrc->vlv_result))) {
622
if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
623
if (!asn1_read_OctetString(data, mem_ctx, &context_id)) {
626
lvrc->contextId = talloc_strndup(lvrc, (const char *)context_id.data, context_id.length);
627
if (!lvrc->contextId) {
630
lvrc->ctxid_len = context_id.length;
632
lvrc->contextId = NULL;
636
if (!asn1_end_tag(data)) {
645
static bool encode_server_sort_response(void *mem_ctx, void *in, DATA_BLOB *out)
647
struct ldb_sort_resp_control *lsrc = talloc_get_type(in, struct ldb_sort_resp_control);
648
struct asn1_data *data = asn1_init(mem_ctx);
650
if (!data) return false;
652
if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
656
if (!asn1_write_enumerated(data, lsrc->result)) {
660
if (lsrc->attr_desc) {
661
if (!asn1_write_OctetString(data, lsrc->attr_desc, strlen(lsrc->attr_desc))) {
666
if (!asn1_pop_tag(data)) {
670
*out = data_blob_talloc(mem_ctx, data->data, data->length);
671
if (out->data == NULL) {
679
static bool encode_server_sort_request(void *mem_ctx, void *in, DATA_BLOB *out)
681
struct ldb_server_sort_control **lssc = talloc_get_type(in, struct ldb_server_sort_control *);
682
struct asn1_data *data = asn1_init(mem_ctx);
685
if (!data) return false;
687
if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
691
for (num = 0; lssc[num]; num++) {
692
if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
696
if (!asn1_write_OctetString(data, lssc[num]->attributeName, strlen(lssc[num]->attributeName))) {
700
if (lssc[num]->orderingRule) {
701
if (!asn1_write_OctetString(data, lssc[num]->orderingRule, strlen(lssc[num]->orderingRule))) {
706
if (lssc[num]->reverse) {
707
if (!asn1_write_BOOLEAN(data, lssc[num]->reverse)) {
712
if (!asn1_pop_tag(data)) {
717
if (!asn1_pop_tag(data)) {
721
*out = data_blob_talloc(mem_ctx, data->data, data->length);
722
if (out->data == NULL) {
730
static bool encode_extended_dn_request(void *mem_ctx, void *in, DATA_BLOB *out)
732
struct ldb_extended_dn_control *ledc = talloc_get_type(in, struct ldb_extended_dn_control);
733
struct asn1_data *data;
736
*out = data_blob(NULL, 0);
740
data = asn1_init(mem_ctx);
742
if (!data) return false;
744
if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
748
if (!asn1_write_Integer(data, ledc->type)) {
752
if (!asn1_pop_tag(data)) {
756
*out = data_blob_talloc(mem_ctx, data->data, data->length);
757
if (out->data == NULL) {
765
static bool encode_sd_flags_request(void *mem_ctx, void *in, DATA_BLOB *out)
767
struct ldb_sd_flags_control *lsdfc = talloc_get_type(in, struct ldb_sd_flags_control);
768
struct asn1_data *data = asn1_init(mem_ctx);
770
if (!data) return false;
772
if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
776
if (!asn1_write_Integer(data, lsdfc->secinfo_flags)) {
780
if (!asn1_pop_tag(data)) {
784
*out = data_blob_talloc(mem_ctx, data->data, data->length);
785
if (out->data == NULL) {
793
static bool encode_search_options_request(void *mem_ctx, void *in, DATA_BLOB *out)
795
struct ldb_search_options_control *lsoc = talloc_get_type(in, struct ldb_search_options_control);
796
struct asn1_data *data = asn1_init(mem_ctx);
798
if (!data) return false;
800
if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
804
if (!asn1_write_Integer(data, lsoc->search_options)) {
808
if (!asn1_pop_tag(data)) {
812
*out = data_blob_talloc(mem_ctx, data->data, data->length);
813
if (out->data == NULL) {
821
static bool encode_paged_results_request(void *mem_ctx, void *in, DATA_BLOB *out)
823
struct ldb_paged_control *lprc = talloc_get_type(in, struct ldb_paged_control);
824
struct asn1_data *data = asn1_init(mem_ctx);
826
if (!data) return false;
828
if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
832
if (!asn1_write_Integer(data, lprc->size)) {
836
if (!asn1_write_OctetString(data, lprc->cookie, lprc->cookie_len)) {
840
if (!asn1_pop_tag(data)) {
844
*out = data_blob_talloc(mem_ctx, data->data, data->length);
845
if (out->data == NULL) {
853
/* seem that this controls has 2 forms one in case it is used with
854
* a Search Request and another when used ina Search Response
856
static bool encode_asq_control(void *mem_ctx, void *in, DATA_BLOB *out)
858
struct ldb_asq_control *lac = talloc_get_type(in, struct ldb_asq_control);
859
struct asn1_data *data = asn1_init(mem_ctx);
861
if (!data) return false;
863
if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
869
if (!asn1_write_OctetString(data, lac->source_attribute, lac->src_attr_len)) {
873
if (!asn1_write_enumerated(data, lac->result)) {
878
if (!asn1_pop_tag(data)) {
882
*out = data_blob_talloc(mem_ctx, data->data, data->length);
883
if (out->data == NULL) {
891
static bool encode_dirsync_request(void *mem_ctx, void *in, DATA_BLOB *out)
893
struct ldb_dirsync_control *ldc = talloc_get_type(in, struct ldb_dirsync_control);
894
struct asn1_data *data = asn1_init(mem_ctx);
896
if (!data) return false;
898
if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
902
if (!asn1_write_Integer(data, ldc->flags)) {
906
if (!asn1_write_Integer(data, ldc->max_attributes)) {
910
if (!asn1_write_OctetString(data, ldc->cookie, ldc->cookie_len)) {
914
if (!asn1_pop_tag(data)) {
918
*out = data_blob_talloc(mem_ctx, data->data, data->length);
919
if (out->data == NULL) {
927
static bool encode_domain_scope_request(void *mem_ctx, void *in, DATA_BLOB *out)
933
*out = data_blob(NULL, 0);
937
static bool encode_notification_request(void *mem_ctx, void *in, DATA_BLOB *out)
943
*out = data_blob(NULL, 0);
947
static bool encode_show_deleted_request(void *mem_ctx, void *in, DATA_BLOB *out)
953
*out = data_blob(NULL, 0);
957
static bool encode_permissive_modify_request(void *mem_ctx, void *in, DATA_BLOB *out)
963
*out = data_blob(NULL, 0);
967
static bool encode_manageDSAIT_request(void *mem_ctx, void *in, DATA_BLOB *out)
973
*out = data_blob(NULL, 0);
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);
982
if (!data) return false;
984
if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
988
if (!asn1_write_Integer(data, lvrc->beforeCount)) {
992
if (!asn1_write_Integer(data, lvrc->afterCount)) {
996
if (lvrc->type == 0) {
997
if (!asn1_push_tag(data, ASN1_CONTEXT(0))) {
1001
if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1005
if (!asn1_write_Integer(data, lvrc->match.byOffset.offset)) {
1009
if (!asn1_write_Integer(data, lvrc->match.byOffset.contentCount)) {
1013
if (!asn1_pop_tag(data)) { /*SEQUENCE*/
1017
if (!asn1_pop_tag(data)) { /*CONTEXT*/
1021
if (!asn1_push_tag(data, ASN1_CONTEXT(1))) {
1025
if (!asn1_write_OctetString(data, lvrc->match.gtOrEq.value, lvrc->match.gtOrEq.value_len)) {
1029
if (!asn1_pop_tag(data)) { /*CONTEXT*/
1034
if (lvrc->ctxid_len) {
1035
if (!asn1_write_OctetString(data, lvrc->contextId, lvrc->ctxid_len)) {
1040
if (!asn1_pop_tag(data)) {
1044
*out = data_blob_talloc(mem_ctx, data->data, data->length);
1045
if (out->data == NULL) {
1053
static bool encode_vlv_response(void *mem_ctx, void *in, DATA_BLOB *out)
1055
struct ldb_vlv_resp_control *lvrc = talloc_get_type(in, struct ldb_vlv_resp_control);
1056
struct asn1_data *data = asn1_init(mem_ctx);
1058
if (!data) return false;
1060
if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1064
if (!asn1_write_Integer(data, lvrc->targetPosition)) {
1068
if (!asn1_write_Integer(data, lvrc->contentCount)) {
1072
if (!asn1_write_enumerated(data, lvrc->vlv_result)) {
1076
if (lvrc->ctxid_len) {
1077
if (!asn1_write_OctetString(data, lvrc->contextId, lvrc->ctxid_len)) {
1082
if (!asn1_pop_tag(data)) {
1086
*out = data_blob_talloc(mem_ctx, data->data, data->length);
1087
if (out->data == NULL) {
1095
static bool encode_openldap_dereference(void *mem_ctx, void *in, DATA_BLOB *out)
1097
struct dsdb_openldap_dereference_control *control = talloc_get_type(in, struct dsdb_openldap_dereference_control);
1099
struct asn1_data *data = asn1_init(mem_ctx);
1101
if (!data) return false;
1103
if (!control) return false;
1105
if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1109
for (i=0; control->dereference && control->dereference[i]; i++) {
1110
if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1113
if (!asn1_write_OctetString(data, control->dereference[i]->source_attribute, strlen(control->dereference[i]->source_attribute))) {
1116
if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1119
for (j=0; control->dereference && control->dereference[i]->dereference_attribute[j]; j++) {
1120
if (!asn1_write_OctetString(data, control->dereference[i]->dereference_attribute[j],
1121
strlen(control->dereference[i]->dereference_attribute[j]))) {
1131
*out = data_blob_talloc(mem_ctx, data->data, data->length);
1132
if (out->data == NULL) {
1139
static bool decode_openldap_dereference(void *mem_ctx, DATA_BLOB in, void *_out)
1141
void **out = (void **)_out;
1142
struct asn1_data *data = asn1_init(mem_ctx);
1143
struct dsdb_openldap_dereference_result_control *control;
1144
struct dsdb_openldap_dereference_result **r = NULL;
1146
if (!data) return false;
1148
control = talloc(mem_ctx, struct dsdb_openldap_dereference_result_control);
1149
if (!control) return false;
1151
if (!asn1_load(data, in)) {
1155
control = talloc(mem_ctx, struct dsdb_openldap_dereference_result_control);
1160
if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
1164
while (asn1_tag_remaining(data) > 0) {
1165
r = talloc_realloc(control, r, struct dsdb_openldap_dereference_result *, i + 2);
1169
r[i] = talloc_zero(r, struct dsdb_openldap_dereference_result);
1174
if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
1178
asn1_read_OctetString_talloc(r[i], data, &r[i]->source_attribute);
1179
asn1_read_OctetString_talloc(r[i], data, &r[i]->dereferenced_dn);
1180
if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1181
if (!asn1_start_tag(data, ASN1_CONTEXT(0))) {
1185
ldap_decode_attribs_bare(r, data, &r[i]->attributes,
1186
&r[i]->num_attributes);
1188
if (!asn1_end_tag(data)) {
1192
if (!asn1_end_tag(data)) {
1199
if (!asn1_end_tag(data)) {
1203
control->attributes = r;
1209
static const struct ldap_control_handler ldap_known_controls[] = {
1210
{ "1.2.840.113556.1.4.319", decode_paged_results_request, encode_paged_results_request },
1211
{ "1.2.840.113556.1.4.529", decode_extended_dn_request, encode_extended_dn_request },
1212
{ "1.2.840.113556.1.4.473", decode_server_sort_request, encode_server_sort_request },
1213
{ "1.2.840.113556.1.4.474", decode_server_sort_response, encode_server_sort_response },
1214
{ "1.2.840.113556.1.4.1504", decode_asq_control, encode_asq_control },
1215
{ "1.2.840.113556.1.4.841", decode_dirsync_request, encode_dirsync_request },
1216
{ "1.2.840.113556.1.4.528", decode_notification_request, encode_notification_request },
1217
{ "1.2.840.113556.1.4.417", decode_show_deleted_request, encode_show_deleted_request },
1218
{ "1.2.840.113556.1.4.1413", decode_permissive_modify_request, encode_permissive_modify_request },
1219
{ "1.2.840.113556.1.4.801", decode_sd_flags_request, encode_sd_flags_request },
1220
{ "1.2.840.113556.1.4.1339", decode_domain_scope_request, encode_domain_scope_request },
1221
{ "1.2.840.113556.1.4.1340", decode_search_options_request, encode_search_options_request },
1222
{ "2.16.840.1.113730.3.4.2", decode_manageDSAIT_request, encode_manageDSAIT_request },
1223
{ "2.16.840.1.113730.3.4.9", decode_vlv_request, encode_vlv_request },
1224
{ "2.16.840.1.113730.3.4.10", decode_vlv_response, encode_vlv_response },
1225
/* DSDB_CONTROL_CURRENT_PARTITION_OID is internal only, and has no network representation */
1226
{ "1.3.6.1.4.1.7165.4.3.2", NULL, NULL },
1227
/* DSDB_EXTENDED_REPLICATED_OBJECTS_OID is internal only, and has no network representation */
1228
{ "1.3.6.1.4.1.7165.4.4.1", NULL, NULL },
1229
{ DSDB_OPENLDAP_DEREFERENCE_CONTROL, decode_openldap_dereference, encode_openldap_dereference},
1230
{ NULL, NULL, NULL }
1233
const struct ldap_control_handler *samba_ldap_control_handlers(void)
1235
return ldap_known_controls;