Coverage Report

Created: 2025-11-16 06:57

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