Coverage Report

Created: 2026-07-25 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/lib/ldb/common/ldb_controls.c
Line
Count
Source
1
/*
2
   ldb database library
3
4
   Copyright (C) Simo Sorce  2005
5
6
     ** NOTE! The following LGPL license applies to the ldb
7
     ** library. This does NOT imply that all of Samba is released
8
     ** under the LGPL
9
10
   This library is free software; you can redistribute it and/or
11
   modify it under the terms of the GNU Lesser General Public
12
   License as published by the Free Software Foundation; either
13
   version 3 of the License, or (at your option) any later version.
14
15
   This library is distributed in the hope that it will be useful,
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18
   Lesser General Public License for more details.
19
20
   You should have received a copy of the GNU Lesser General Public
21
   License along with this library; if not, see <http://www.gnu.org/licenses/>.
22
*/
23
24
/*
25
 *  Name: ldb_controls.c
26
 *
27
 *  Component: ldb controls utility functions
28
 *
29
 *  Description: helper functions for control modules
30
 *
31
 *  Author: Simo Sorce
32
 */
33
34
#include "ldb_private.h"
35
36
/* check if a control with the specified "oid" exist and return it */
37
/* returns NULL if not found */
38
struct ldb_control *ldb_controls_get_control(struct ldb_control **controls, const char *oid)
39
0
{
40
0
  unsigned int i;
41
42
0
  if (controls != NULL) {
43
0
    for (i = 0; controls[i]; i++) {
44
0
      if (controls[i]->oid && strcmp(oid, controls[i]->oid) == 0) {
45
0
        break;
46
0
      }
47
0
    }
48
49
0
    return controls[i];
50
0
  }
51
52
0
  return NULL;
53
0
}
54
55
/* check if a control with the specified "oid" exist and return it */
56
/* returns NULL if not found */
57
struct ldb_control *ldb_request_get_control(struct ldb_request *req, const char *oid)
58
0
{
59
0
  return ldb_controls_get_control(req->controls, oid);
60
0
}
61
62
/* check if a control with the specified "oid" exist and return it */
63
/* returns NULL if not found */
64
struct ldb_control *ldb_reply_get_control(struct ldb_reply *rep, const char *oid)
65
0
{
66
0
  return ldb_controls_get_control(rep->controls, oid);
67
0
}
68
69
/*
70
 * Saves the current controls list into the "saver" (can also be NULL) and
71
 * replace the one in "req" with a new one excluding the "exclude" control
72
 * (if it is NULL then the list remains the same)
73
 *
74
 * Returns 0 on error.
75
 */
76
int ldb_save_controls(struct ldb_control *exclude, struct ldb_request *req, struct ldb_control ***saver)
77
0
{
78
0
  struct ldb_control **lcs, **lcs_old;
79
0
  unsigned int i, j;
80
81
0
  lcs_old = req->controls;
82
0
  if (saver != NULL) {
83
0
    *saver = lcs_old;
84
0
  }
85
86
0
  for (i = 0; req->controls && req->controls[i]; i++);
87
0
  if (i == 0) {
88
0
    req->controls = NULL;
89
0
    return 1;
90
0
  }
91
92
0
  lcs = talloc_array(req, struct ldb_control *, i + 1);
93
0
  if (!lcs) {
94
0
    return 0;
95
0
  }
96
97
0
  for (i = 0, j = 0; lcs_old[i]; i++) {
98
0
    if (exclude == lcs_old[i]) continue;
99
0
    lcs[j] = lcs_old[i];
100
0
    j++;
101
0
  }
102
0
  lcs[j] = NULL;
103
104
0
  req->controls = talloc_realloc(req, lcs, struct ldb_control *, j + 1);
105
0
  if (req->controls == NULL) {
106
0
    return 0;
107
0
  }
108
0
  return 1;
109
0
}
110
111
/*
112
 * Returns a list of controls, except the one specified with "exclude" (can
113
 * also be NULL).  Included controls become a child of returned list if they
114
 * were children of "controls_in".
115
 *
116
 * Returns NULL on error (OOM) or an empty control list.
117
 */
118
struct ldb_control **ldb_controls_except_specified(struct ldb_control **controls_in,
119
                 TALLOC_CTX *mem_ctx,
120
                 struct ldb_control *exclude)
121
0
{
122
0
  struct ldb_control **lcs = NULL;
123
0
  unsigned int i, j, n;
124
125
0
  for (i = 0; controls_in && controls_in[i]; i++);
126
0
  if (i == 0) {
127
0
    return NULL;
128
0
  }
129
0
  n = i;
130
131
0
  for (i = 0, j = 0; controls_in && controls_in[i]; i++) {
132
0
    if (exclude == controls_in[i]) continue;
133
134
0
    if (!lcs) {
135
      /* Allocate here so if we remove the only
136
       * control, or there were no controls, we
137
       * don't allocate at all, and just return
138
       * NULL */
139
0
      lcs = talloc_array(mem_ctx, struct ldb_control *,
140
0
             n + 1);
141
0
      if (!lcs) {
142
0
        return NULL;
143
0
      }
144
0
    }
145
146
0
    lcs[j] = controls_in[i];
147
0
    talloc_reparent(controls_in, lcs, lcs[j]);
148
0
    j++;
149
0
  }
150
0
  if (lcs) {
151
0
    lcs[j] = NULL;
152
153
0
    lcs = talloc_realloc(mem_ctx, lcs, struct ldb_control *, j + 1);
154
0
  }
155
156
0
  return lcs;
157
0
}
158
159
/* check if there's any control marked as critical in the list */
160
/* return True if any, False if none */
161
int ldb_check_critical_controls(struct ldb_control **controls)
162
0
{
163
0
  unsigned int i;
164
165
0
  if (controls == NULL) {
166
0
    return 0;
167
0
  }
168
169
0
  for (i = 0; controls[i]; i++) {
170
0
    if (controls[i]->critical) {
171
0
      return 1;
172
0
    }
173
0
  }
174
175
0
  return 0;
176
0
}
177
178
int ldb_request_add_control(struct ldb_request *req, const char *oid, bool critical, void *data)
179
0
{
180
0
  unsigned int i, n;
181
0
  struct ldb_control **ctrls;
182
0
  struct ldb_control *ctrl;
183
184
0
  for (n=0; req->controls && req->controls[n];n++) {
185
    /* having two controls of the same OID makes no sense */
186
0
    if (req->controls[n]->oid && strcmp(oid, req->controls[n]->oid) == 0) {
187
0
      return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
188
0
    }
189
0
  }
190
191
0
  ctrls = talloc_array(req,
192
0
             struct ldb_control *,
193
0
             n + 2);
194
0
  if (!ctrls) return LDB_ERR_OPERATIONS_ERROR;
195
196
0
  for (i=0; i<n; i++) {
197
0
    ctrls[i] = req->controls[i];
198
0
  }
199
200
0
  req->controls = ctrls;
201
0
  ctrls[n] = NULL;
202
0
  ctrls[n+1] = NULL;
203
204
0
  ctrl = talloc(ctrls, struct ldb_control);
205
0
  if (!ctrl) return LDB_ERR_OPERATIONS_ERROR;
206
207
0
  ctrl->oid = talloc_strdup(ctrl, oid);
208
0
  if (!ctrl->oid) return LDB_ERR_OPERATIONS_ERROR;
209
0
  ctrl->critical  = critical;
210
0
  ctrl->data  = data;
211
212
0
  ctrls[n] = ctrl;
213
0
  return LDB_SUCCESS;
214
0
}
215
216
int ldb_reply_add_control(struct ldb_reply *ares, const char *oid, bool critical, void *data)
217
0
{
218
0
  unsigned n;
219
0
  struct ldb_control **ctrls;
220
0
  struct ldb_control *ctrl;
221
222
0
  for (n=0; ares->controls && ares->controls[n];) {
223
    /* having two controls of the same OID makes no sense */
224
0
    if (ares->controls[n]->oid && strcmp(oid, ares->controls[n]->oid) == 0) {
225
0
      return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
226
0
    }
227
0
    n++;
228
0
  }
229
230
0
  ctrls = talloc_realloc(ares, ares->controls,
231
0
             struct ldb_control *,
232
0
             n + 2);
233
0
  if (!ctrls) return LDB_ERR_OPERATIONS_ERROR;
234
0
  ares->controls = ctrls;
235
0
  ctrls[n] = NULL;
236
0
  ctrls[n+1] = NULL;
237
238
0
  ctrl = talloc(ctrls, struct ldb_control);
239
0
  if (!ctrl) return LDB_ERR_OPERATIONS_ERROR;
240
241
0
  ctrl->oid = talloc_strdup(ctrl, oid);
242
0
  if (!ctrl->oid) return LDB_ERR_OPERATIONS_ERROR;
243
0
  ctrl->critical  = critical;
244
0
  ctrl->data  = data;
245
246
0
  ctrls[n] = ctrl;
247
0
  return LDB_SUCCESS;
248
0
}
249
250
/* Add a control to the request, replacing the old one if it is already in the request */
251
int ldb_request_replace_control(struct ldb_request *req, const char *oid, bool critical, void *data)
252
0
{
253
0
  unsigned int n;
254
0
  int ret;
255
256
0
  ret = ldb_request_add_control(req, oid, critical, data);
257
0
  if (ret != LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) {
258
0
    return ret;
259
0
  }
260
261
0
  for (n=0; req->controls[n];n++) {
262
0
    if (req->controls[n]->oid && strcmp(oid, req->controls[n]->oid) == 0) {
263
0
      req->controls[n]->critical = critical;
264
0
      req->controls[n]->data = data;
265
0
      return LDB_SUCCESS;
266
0
    }
267
0
  }
268
269
0
  return LDB_ERR_OPERATIONS_ERROR;
270
0
}
271
272
/*
273
 * Return a control as string
274
 * the project (ie. name:value1:value2:...:valuen
275
 * The string didn't include the criticity of the critical flag
276
 */
277
char *ldb_control_to_string(TALLOC_CTX *mem_ctx, const struct ldb_control *control)
278
0
{
279
0
  char *res = NULL;
280
281
0
  if (strcmp(control->oid, LDB_CONTROL_PAGED_RESULTS_OID) == 0) {
282
0
    struct ldb_paged_control *rep_control = talloc_get_type(control->data, struct ldb_paged_control);
283
0
    char *cookie;
284
0
    if (rep_control == NULL) {
285
0
      return NULL;
286
0
    }
287
288
0
    cookie = ldb_base64_encode(mem_ctx, rep_control->cookie, rep_control->cookie_len);
289
0
    if (cookie == NULL) {
290
0
      return NULL;
291
0
    }
292
0
    if (cookie[0] != '\0') {
293
0
      res = talloc_asprintf(mem_ctx, "%s:%d:%s",
294
0
            LDB_CONTROL_PAGED_RESULTS_NAME,
295
0
            control->critical,
296
0
            cookie);
297
298
0
      talloc_free(cookie);
299
0
    } else {
300
0
      res = talloc_asprintf(mem_ctx, "%s:%d",
301
0
            LDB_CONTROL_PAGED_RESULTS_NAME,
302
0
            control->critical);
303
0
    }
304
0
    return res;
305
0
  }
306
307
0
  if (strcmp(control->oid, LDB_CONTROL_VLV_RESP_OID) == 0) {
308
0
    struct ldb_vlv_resp_control *rep_control = talloc_get_type(control->data,
309
0
                struct ldb_vlv_resp_control);
310
311
0
    char *cookie;
312
313
0
    if (rep_control == NULL) {
314
0
      return NULL;
315
0
    }
316
317
0
    cookie = ldb_base64_encode(mem_ctx,
318
0
             (char *)rep_control->contextId,
319
0
             rep_control->ctxid_len);
320
0
    if (cookie == NULL) {
321
0
      return NULL;
322
0
    }
323
324
0
    res = talloc_asprintf(mem_ctx, "%s:%d:%d:%d:%d:%s",
325
0
            LDB_CONTROL_VLV_RESP_NAME,
326
0
            control->critical,
327
0
            rep_control->targetPosition,
328
0
            rep_control->contentCount,
329
0
            rep_control->vlv_result,
330
0
                        cookie);
331
332
0
    return res;
333
0
  }
334
335
0
  if (strcmp(control->oid, LDB_CONTROL_SORT_RESP_OID) == 0) {
336
0
    struct ldb_sort_resp_control *rep_control = talloc_get_type(control->data,
337
0
                struct ldb_sort_resp_control);
338
339
0
    if (rep_control == NULL) {
340
0
      return NULL;
341
0
    }
342
0
    res = talloc_asprintf(mem_ctx, "%s:%d:%d:%s",
343
0
          LDB_CONTROL_SORT_RESP_NAME,
344
0
          control->critical,
345
0
          rep_control->result,
346
0
          rep_control->attr_desc);
347
348
0
    return res;
349
0
  }
350
351
0
  if (strcmp(control->oid, LDB_CONTROL_ASQ_OID) == 0) {
352
0
    struct ldb_asq_control *rep_control = talloc_get_type(control->data,
353
0
                struct ldb_asq_control);
354
355
0
    if (rep_control == NULL) {
356
0
      return NULL;
357
0
    }
358
0
    res = talloc_asprintf(mem_ctx, "%s:%d:%d",
359
0
          LDB_CONTROL_ASQ_NAME,
360
0
          control->critical,
361
0
          rep_control->result);
362
363
0
    return res;
364
0
  }
365
366
0
  if (strcmp(control->oid, LDB_CONTROL_DIRSYNC_OID) == 0) {
367
0
    char *cookie;
368
0
    struct ldb_dirsync_control *rep_control = talloc_get_type(control->data,
369
0
                struct ldb_dirsync_control);
370
371
0
    if (rep_control == NULL) {
372
0
      return NULL;
373
0
    }
374
0
    cookie = ldb_base64_encode(mem_ctx, rep_control->cookie,
375
0
        rep_control->cookie_len);
376
0
    if (cookie == NULL) {
377
0
      return NULL;
378
0
    }
379
0
    res = talloc_asprintf(mem_ctx, "%s:%d:%d:%d:%s",
380
0
          LDB_CONTROL_DIRSYNC_NAME,
381
0
          control->critical,
382
0
          rep_control->flags,
383
0
          rep_control->max_attributes,
384
0
          cookie);
385
386
0
    talloc_free(cookie);
387
0
    return res;
388
0
  }
389
0
  if (strcmp(control->oid, LDB_CONTROL_DIRSYNC_EX_OID) == 0) {
390
0
    char *cookie;
391
0
    struct ldb_dirsync_control *rep_control = talloc_get_type(control->data,
392
0
                struct ldb_dirsync_control);
393
394
0
    if (rep_control == NULL) {
395
0
      return NULL;
396
0
    }
397
0
    cookie = ldb_base64_encode(mem_ctx, rep_control->cookie,
398
0
        rep_control->cookie_len);
399
0
    if (cookie == NULL) {
400
0
      return NULL;
401
0
    }
402
0
    res = talloc_asprintf(mem_ctx, "%s:%d:%d:%d:%s",
403
0
          LDB_CONTROL_DIRSYNC_EX_NAME,
404
0
          control->critical,
405
0
          rep_control->flags,
406
0
          rep_control->max_attributes,
407
0
          cookie);
408
409
0
    talloc_free(cookie);
410
0
    return res;
411
0
  }
412
413
0
  if (strcmp(control->oid, LDB_CONTROL_VERIFY_NAME_OID) == 0) {
414
0
    struct ldb_verify_name_control *rep_control = talloc_get_type(control->data, struct ldb_verify_name_control);
415
416
0
    if (rep_control == NULL) {
417
0
      return NULL;
418
0
    }
419
0
    if (rep_control->gc != NULL) {
420
0
      res = talloc_asprintf(mem_ctx, "%s:%d:%d:%s",
421
0
            LDB_CONTROL_VERIFY_NAME_NAME,
422
0
            control->critical,
423
0
            rep_control->flags,
424
0
            rep_control->gc);
425
426
0
    } else {
427
0
      res = talloc_asprintf(mem_ctx, "%s:%d:%d",
428
0
            LDB_CONTROL_VERIFY_NAME_NAME,
429
0
            control->critical,
430
0
            rep_control->flags);
431
0
    }
432
0
    return res;
433
0
  }
434
435
  /*
436
   * From here we don't know the control
437
   */
438
0
  if (control->data == NULL) {
439
    /*
440
     * We don't know the control but there is no real data attached
441
     * to it so we can represent it with local_oid:oid:criticity.
442
     */
443
0
    res = talloc_asprintf(mem_ctx, "local_oid:%s:%d",
444
0
          control->oid,
445
0
          control->critical);
446
0
  } else {
447
0
    res = talloc_asprintf(mem_ctx, "unknown oid:%s",
448
0
          control->oid);
449
0
  }
450
0
  return res;
451
0
}
452
453
454
/*
455
 * A little trick to allow one to use constants defined in headers rather than
456
 * hardwritten in the file.
457
 * "sizeof" will return the \0 char as well so it will take the place of ":"
458
 * in the length of the string.
459
 */
460
0
#define LDB_CONTROL_CMP(control, NAME) strncmp(control, NAME ":", sizeof(NAME))
461
462
/* Parse one string and return associated control if parsing is successful*/
463
struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *control_strings)
464
0
{
465
0
  struct ldb_control *ctrl;
466
467
0
  if (!(ctrl = talloc(mem_ctx, struct ldb_control))) {
468
0
    ldb_oom(ldb);
469
0
    return NULL;
470
0
  }
471
472
0
  if (LDB_CONTROL_CMP(control_strings,
473
0
        LDB_CONTROL_VLV_REQ_NAME) == 0) {
474
0
    struct ldb_vlv_req_control *control;
475
0
    const char *p;
476
0
    char attr[1024];
477
0
    char ctxid[1024];
478
0
    int crit, bc, ac, os, cc, ret;
479
480
0
    attr[0] = '\0';
481
0
    ctxid[0] = '\0';
482
0
    p = &(control_strings[sizeof(LDB_CONTROL_VLV_REQ_NAME)]);
483
0
    ret = sscanf(p, "%d:%d:%d:%d:%d:%1023[^$]", &crit, &bc, &ac, &os, &cc, ctxid);
484
    /* We allow 2 ways to encode the GT_EQ case, because the
485
       comparison string might contain null bytes or colons, which
486
       would break sscanf (or indeed any parsing mechanism). */
487
0
    if (ret == 3) {
488
0
      ret = sscanf(p, "%d:%d:%d:>=%1023[^:]:%1023[^$]", &crit, &bc, &ac, attr, ctxid);
489
0
    }
490
0
    if (ret == 3) {
491
0
      int len;
492
0
      ret = sscanf(p, "%d:%d:%d:base64>=%1023[^:]:%1023[^$]", &crit, &bc, &ac, attr, ctxid);
493
0
      len = ldb_base64_decode(attr);
494
0
      if (len < 0) {
495
0
        ret = -1;
496
0
      }
497
0
    }
498
499
0
    if ((ret < 4) || (crit < 0) || (crit > 1)) {
500
0
      ldb_set_errstring(ldb,
501
0
            "invalid VLV control syntax\n"
502
0
            " syntax: crit(b):bc(n):ac(n):"
503
0
            "{os(n):cc(n)|>=val(s)|base64>=val(o)}[:ctxid(o)]\n"
504
0
            "   note: b = boolean, n = number, s = string, o = b64 binary blob");
505
0
      talloc_free(ctrl);
506
0
      return NULL;
507
0
    }
508
0
    ctrl->oid = LDB_CONTROL_VLV_REQ_OID;
509
0
    ctrl->critical = crit;
510
0
    if (!(control = talloc(ctrl,
511
0
          struct ldb_vlv_req_control))) {
512
0
      ldb_oom(ldb);
513
0
      talloc_free(ctrl);
514
0
      return NULL;
515
0
    }
516
0
    control->beforeCount = bc;
517
0
    control->afterCount = ac;
518
0
    if (attr[0]) {
519
0
      control->type = 1;
520
0
      control->match.gtOrEq.value = talloc_strdup(control, attr);
521
0
      control->match.gtOrEq.value_len = strlen(attr);
522
0
    } else {
523
0
      control->type = 0;
524
0
      control->match.byOffset.offset = os;
525
0
      control->match.byOffset.contentCount = cc;
526
0
    }
527
0
    if (ctxid[0]) {
528
0
      int len = ldb_base64_decode(ctxid);
529
0
      if (len < 0) {
530
0
        ldb_set_errstring(ldb,
531
0
              "invalid VLV context_id\n");
532
0
        talloc_free(ctrl);
533
0
        return NULL;
534
0
      }
535
0
      control->ctxid_len = len;
536
0
      control->contextId = talloc_memdup(control, ctxid,
537
0
                 control->ctxid_len);
538
0
      if (control->contextId == NULL) {
539
0
        ldb_oom(ldb);
540
0
        talloc_free(ctrl);
541
0
        return NULL;
542
0
      }
543
0
    } else {
544
0
      control->ctxid_len = 0;
545
0
      control->contextId = NULL;
546
0
    }
547
0
    ctrl->data = control;
548
549
0
    return ctrl;
550
0
  }
551
552
0
  if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_DIRSYNC_NAME) == 0) {
553
0
    struct ldb_dirsync_control *control;
554
0
    const char *p;
555
0
    char *cookie = NULL;
556
0
    int crit, max_attrs, ret;
557
0
    uint32_t flags;
558
559
0
    cookie = talloc_zero_array(ctrl, char,
560
0
             strlen(control_strings) + 1);
561
0
    if (cookie == NULL) {
562
0
      ldb_oom(ldb);
563
0
      talloc_free(ctrl);
564
0
      return NULL;
565
0
    }
566
567
0
    p = &(control_strings[sizeof(LDB_CONTROL_DIRSYNC_NAME)]);
568
0
    ret = sscanf(p, "%d:%u:%d:%[^$]", &crit, &flags, &max_attrs, cookie);
569
570
0
    if ((ret < 3) || (crit < 0) || (crit > 1) || (max_attrs < 0)) {
571
0
      ldb_set_errstring(ldb,
572
0
            "invalid dirsync control syntax\n"
573
0
            " syntax: crit(b):flags(n):max_attrs(n)[:cookie(o)]\n"
574
0
            "   note: b = boolean, n = number, o = b64 binary blob");
575
0
      talloc_free(ctrl);
576
0
      return NULL;
577
0
    }
578
579
    /* w2k3 seems to ignore the parameter,
580
     * but w2k sends a wrong cookie when this value is to small
581
     * this would cause looping forever, while getting
582
     * the same data and same cookie forever
583
     */
584
0
    if (max_attrs == 0) max_attrs = 0x0FFFFFFF;
585
586
0
    ctrl->oid = LDB_CONTROL_DIRSYNC_OID;
587
0
    ctrl->critical = crit;
588
0
    control = talloc(ctrl, struct ldb_dirsync_control);
589
0
    if (control == NULL) {
590
0
      ldb_oom(ldb);
591
0
      talloc_free(ctrl);
592
0
      return NULL;
593
0
    }
594
0
    control->flags = flags;
595
0
    control->max_attributes = max_attrs;
596
0
    if (*cookie) {
597
0
      int len = ldb_base64_decode(cookie);
598
0
      if (len < 0) {
599
0
        ldb_set_errstring(ldb,
600
0
              "invalid dirsync cookie\n");
601
0
        talloc_free(ctrl);
602
0
        return NULL;
603
0
      }
604
0
      control->cookie_len = len;
605
0
      control->cookie = (char *)talloc_memdup(control, cookie, control->cookie_len);
606
0
      if (control->cookie == NULL) {
607
0
        ldb_oom(ldb);
608
0
        talloc_free(ctrl);
609
0
        return NULL;
610
0
      }
611
0
    } else {
612
0
      control->cookie = NULL;
613
0
      control->cookie_len = 0;
614
0
    }
615
0
    ctrl->data = control;
616
0
    TALLOC_FREE(cookie);
617
618
0
    return ctrl;
619
0
  }
620
0
  if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_DIRSYNC_EX_NAME) == 0) {
621
0
    struct ldb_dirsync_control *control;
622
0
    const char *p;
623
0
    char *cookie = NULL;
624
0
    int crit, max_attrs, ret;
625
0
    uint32_t flags;
626
627
0
    cookie = talloc_zero_array(ctrl, char,
628
0
             strlen(control_strings) + 1);
629
0
    if (cookie == NULL) {
630
0
      ldb_oom(ldb);
631
0
      talloc_free(ctrl);
632
0
      return NULL;
633
0
    }
634
635
0
    p = &(control_strings[sizeof(LDB_CONTROL_DIRSYNC_EX_NAME)]);
636
0
    ret = sscanf(p, "%d:%u:%d:%1023[^$]", &crit, &flags, &max_attrs, cookie);
637
638
0
    if ((ret < 3) || (crit < 0) || (crit > 1) || (max_attrs < 0)) {
639
0
      ldb_set_errstring(ldb,
640
0
            "invalid dirsync_ex control syntax\n"
641
0
            " syntax: crit(b):flags(n):max_attrs(n)[:cookie(o)]\n"
642
0
            "   note: b = boolean, n = number, o = b64 binary blob");
643
0
      talloc_free(ctrl);
644
0
      return NULL;
645
0
    }
646
647
    /* w2k3 seems to ignore the parameter,
648
     * but w2k sends a wrong cookie when this value is to small
649
     * this would cause looping forever, while getting
650
     * the same data and same cookie forever
651
     */
652
0
    if (max_attrs == 0) max_attrs = 0x0FFFFFFF;
653
654
0
    ctrl->oid = LDB_CONTROL_DIRSYNC_EX_OID;
655
0
    ctrl->critical = crit;
656
0
    control = talloc(ctrl, struct ldb_dirsync_control);
657
0
    if (control == NULL) {
658
0
      ldb_oom(ldb);
659
0
      talloc_free(ctrl);
660
0
      return NULL;
661
0
    }
662
0
    control->flags = flags;
663
0
    control->max_attributes = max_attrs;
664
0
    if (*cookie) {
665
0
      int len = ldb_base64_decode(cookie);
666
0
      if (len < 0) {
667
0
        ldb_set_errstring(ldb,
668
0
              "invalid dirsync_ex cookie"
669
0
              " (probably too long)\n");
670
0
        talloc_free(ctrl);
671
0
        return NULL;
672
0
      }
673
0
      control->cookie_len = len;
674
0
      control->cookie = (char *)talloc_memdup(control, cookie, control->cookie_len);
675
0
      if (control->cookie == NULL) {
676
0
        ldb_oom(ldb);
677
0
        talloc_free(ctrl);
678
0
        return NULL;
679
0
      }
680
0
    } else {
681
0
      control->cookie = NULL;
682
0
      control->cookie_len = 0;
683
0
    }
684
0
    ctrl->data = control;
685
0
    TALLOC_FREE(cookie);
686
687
0
    return ctrl;
688
0
  }
689
690
0
  if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_ASQ_NAME) == 0) {
691
0
    struct ldb_asq_control *control;
692
0
    const char *p;
693
0
    char attr[256];
694
0
    int crit, ret;
695
696
0
    attr[0] = '\0';
697
0
    p = &(control_strings[sizeof(LDB_CONTROL_ASQ_NAME)]);
698
0
    ret = sscanf(p, "%d:%255[^$]", &crit, attr);
699
0
    if ((ret != 2) || (crit < 0) || (crit > 1) || (attr[0] == '\0')) {
700
0
      ldb_set_errstring(ldb,
701
0
            "invalid asq control syntax\n"
702
0
            " syntax: crit(b):attr(s)\n"
703
0
            "   note: b = boolean, s = string");
704
0
      talloc_free(ctrl);
705
0
      return NULL;
706
0
    }
707
708
0
    ctrl->oid = LDB_CONTROL_ASQ_OID;
709
0
    ctrl->critical = crit;
710
0
    control = talloc(ctrl, struct ldb_asq_control);
711
0
    if (control == NULL) {
712
0
      ldb_oom(ldb);
713
0
      talloc_free(ctrl);
714
0
      return NULL;
715
0
    }
716
0
    control->request = 1;
717
0
    control->source_attribute = talloc_strdup(control, attr);
718
0
    control->src_attr_len = strlen(attr);
719
0
    ctrl->data = control;
720
721
0
    return ctrl;
722
0
  }
723
724
0
  if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_EXTENDED_DN_NAME) == 0) {
725
0
    struct ldb_extended_dn_control *control;
726
0
    const char *p;
727
0
    int crit, type, ret;
728
729
0
    p = &(control_strings[sizeof(LDB_CONTROL_EXTENDED_DN_NAME)]);
730
0
    ret = sscanf(p, "%d:%d", &crit, &type);
731
0
    if ((ret != 2) || (crit < 0) || (crit > 1) || (type < 0) || (type > 1)) {
732
0
      ret = sscanf(p, "%d", &crit);
733
0
      if ((ret != 1) || (crit < 0) || (crit > 1)) {
734
0
        ldb_set_errstring(ldb,
735
0
              "invalid extended_dn control syntax\n"
736
0
              " syntax: crit(b)[:type(i)]\n"
737
0
              "   note: b = boolean\n"
738
0
              "         i = integer\n"
739
0
              "   valid values are: 0 - hexadecimal representation\n"
740
0
              "                     1 - normal string representation");
741
0
        talloc_free(ctrl);
742
0
        return NULL;
743
0
      }
744
0
      control = NULL;
745
0
    } else {
746
0
      control = talloc(ctrl, struct ldb_extended_dn_control);
747
0
      if (control == NULL) {
748
0
        ldb_oom(ldb);
749
0
        talloc_free(ctrl);
750
0
        return NULL;
751
0
      }
752
0
      control->type = type;
753
0
    }
754
755
0
    ctrl->oid = LDB_CONTROL_EXTENDED_DN_OID;
756
0
    ctrl->critical = crit;
757
0
    ctrl->data = control;
758
759
0
    return ctrl;
760
0
  }
761
762
0
  if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SD_FLAGS_NAME) == 0) {
763
0
    struct ldb_sd_flags_control *control;
764
0
    const char *p;
765
0
    int crit, ret;
766
0
    unsigned secinfo_flags;
767
768
0
    p = &(control_strings[sizeof(LDB_CONTROL_SD_FLAGS_NAME)]);
769
0
    ret = sscanf(p, "%d:%u", &crit, &secinfo_flags);
770
0
    if ((ret != 2) || (crit < 0) || (crit > 1) || (secinfo_flags > 0xF)) {
771
0
      ldb_set_errstring(ldb,
772
0
            "invalid sd_flags control syntax\n"
773
0
            " syntax: crit(b):secinfo_flags(n)\n"
774
0
            "   note: b = boolean, n = number");
775
0
      talloc_free(ctrl);
776
0
      return NULL;
777
0
    }
778
779
0
    ctrl->oid = LDB_CONTROL_SD_FLAGS_OID;
780
0
    ctrl->critical = crit;
781
0
    control = talloc(ctrl, struct ldb_sd_flags_control);
782
0
    if (control == NULL) {
783
0
      ldb_oom(ldb);
784
0
      talloc_free(ctrl);
785
0
      return NULL;
786
0
    }
787
788
0
    control->secinfo_flags = secinfo_flags;
789
0
    ctrl->data = control;
790
791
0
    return ctrl;
792
0
  }
793
794
0
  if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SEARCH_OPTIONS_NAME) == 0) {
795
0
    struct ldb_search_options_control *control;
796
0
    const char *p;
797
0
    int crit, ret;
798
0
    unsigned search_options;
799
800
0
    p = &(control_strings[sizeof(LDB_CONTROL_SEARCH_OPTIONS_NAME)]);
801
0
    ret = sscanf(p, "%d:%u", &crit, &search_options);
802
0
    if ((ret != 2) || (crit < 0) || (crit > 1) || (search_options > 0xF)) {
803
0
      ldb_set_errstring(ldb,
804
0
            "invalid search_options control syntax\n"
805
0
            " syntax: crit(b):search_options(n)\n"
806
0
            "   note: b = boolean, n = number");
807
0
      talloc_free(ctrl);
808
0
      return NULL;
809
0
    }
810
811
0
    ctrl->oid = LDB_CONTROL_SEARCH_OPTIONS_OID;
812
0
    ctrl->critical = crit;
813
0
    control = talloc(ctrl, struct ldb_search_options_control);
814
0
    if (control == NULL) {
815
0
      ldb_oom(ldb);
816
0
      talloc_free(ctrl);
817
0
      return NULL;
818
0
    }
819
820
0
    control->search_options = search_options;
821
0
    ctrl->data = control;
822
823
0
    return ctrl;
824
0
  }
825
826
0
  if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_BYPASS_OPERATIONAL_NAME) == 0) {
827
0
    const char *p;
828
0
    int crit, ret;
829
830
0
    p = &(control_strings[sizeof(LDB_CONTROL_BYPASS_OPERATIONAL_NAME)]);
831
0
    ret = sscanf(p, "%d", &crit);
832
0
    if ((ret != 1) || (crit < 0) || (crit > 1)) {
833
0
      ldb_set_errstring(ldb,
834
0
            "invalid bypassoperational control syntax\n"
835
0
            " syntax: crit(b)\n"
836
0
            "   note: b = boolean");
837
0
      talloc_free(ctrl);
838
0
      return NULL;
839
0
    }
840
841
0
    ctrl->oid = LDB_CONTROL_BYPASS_OPERATIONAL_OID;
842
0
    ctrl->critical = crit;
843
0
    ctrl->data = NULL;
844
845
0
    return ctrl;
846
0
  }
847
848
0
  if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_RELAX_NAME) == 0) {
849
0
    const char *p;
850
0
    int crit, ret;
851
852
0
    p = &(control_strings[sizeof(LDB_CONTROL_RELAX_NAME)]);
853
0
    ret = sscanf(p, "%d", &crit);
854
0
    if ((ret != 1) || (crit < 0) || (crit > 1)) {
855
0
      ldb_set_errstring(ldb,
856
0
            "invalid relax control syntax\n"
857
0
            " syntax: crit(b)\n"
858
0
            "   note: b = boolean");
859
0
      talloc_free(ctrl);
860
0
      return NULL;
861
0
    }
862
863
0
    ctrl->oid = LDB_CONTROL_RELAX_OID;
864
0
    ctrl->critical = crit;
865
0
    ctrl->data = NULL;
866
867
0
    return ctrl;
868
0
  }
869
870
0
  if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_RECALCULATE_SD_NAME) == 0) {
871
0
    const char *p;
872
0
    int crit, ret;
873
874
0
    p = &(control_strings[sizeof(LDB_CONTROL_RECALCULATE_SD_NAME)]);
875
0
    ret = sscanf(p, "%d", &crit);
876
0
    if ((ret != 1) || (crit < 0) || (crit > 1)) {
877
0
      ldb_set_errstring(ldb,
878
0
            "invalid recalculate_sd control syntax\n"
879
0
            " syntax: crit(b)\n"
880
0
            "   note: b = boolean");
881
0
      talloc_free(ctrl);
882
0
      return NULL;
883
0
    }
884
885
0
    ctrl->oid = LDB_CONTROL_RECALCULATE_SD_OID;
886
0
    ctrl->critical = crit;
887
0
    ctrl->data = NULL;
888
889
0
    return ctrl;
890
0
  }
891
892
0
  if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_DOMAIN_SCOPE_NAME) == 0) {
893
0
    const char *p;
894
0
    int crit, ret;
895
896
0
    p = &(control_strings[sizeof(LDB_CONTROL_DOMAIN_SCOPE_NAME)]);
897
0
    ret = sscanf(p, "%d", &crit);
898
0
    if ((ret != 1) || (crit < 0) || (crit > 1)) {
899
0
      ldb_set_errstring(ldb,
900
0
            "invalid domain_scope control syntax\n"
901
0
            " syntax: crit(b)\n"
902
0
            "   note: b = boolean");
903
0
      talloc_free(ctrl);
904
0
      return NULL;
905
0
    }
906
907
0
    ctrl->oid = LDB_CONTROL_DOMAIN_SCOPE_OID;
908
0
    ctrl->critical = crit;
909
0
    ctrl->data = NULL;
910
911
0
    return ctrl;
912
0
  }
913
914
0
  if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_PAGED_RESULTS_NAME) == 0) {
915
0
    struct ldb_paged_control *control;
916
0
    const char *p;
917
0
    char cookie[1024];
918
0
    int crit, size, ret;
919
920
0
    cookie[0] = '\0';
921
0
    p = &(control_strings[sizeof(LDB_CONTROL_PAGED_RESULTS_NAME)]);
922
0
    ret = sscanf(p, "%d:%d:%1023[^$]", &crit, &size, cookie);
923
0
    if ((ret < 2) || (ret > 3) || (crit < 0) || (crit > 1) ||
924
0
        (size < 0)) {
925
0
      ldb_set_errstring(ldb,
926
0
        "invalid paged_results control syntax\n"
927
0
        " syntax: crit(b):size(n)[:cookie(base64)]\n"
928
0
        "   note: b = boolean, n = number");
929
0
      talloc_free(ctrl);
930
0
      return NULL;
931
0
    }
932
933
0
    ctrl->oid = LDB_CONTROL_PAGED_RESULTS_OID;
934
0
    ctrl->critical = crit;
935
0
    control = talloc(ctrl, struct ldb_paged_control);
936
0
    if (control == NULL) {
937
0
      ldb_oom(ldb);
938
0
      talloc_free(ctrl);
939
0
      return NULL;
940
0
    }
941
942
0
    control->size = size;
943
0
    if (cookie[0] != '\0') {
944
0
      int len = ldb_base64_decode(cookie);
945
0
      if (len < 0) {
946
0
        ldb_set_errstring(ldb,
947
0
              "invalid paged_results cookie"
948
0
              " (probably too long)\n");
949
0
        talloc_free(ctrl);
950
0
        return NULL;
951
0
      }
952
0
      control->cookie_len = len;
953
0
      control->cookie = talloc_memdup(control, cookie, control->cookie_len);
954
0
      if (control->cookie == NULL) {
955
0
        ldb_oom(ldb);
956
0
        talloc_free(ctrl);
957
0
        return NULL;
958
0
      }
959
0
    } else {
960
0
      control->cookie = NULL;
961
0
      control->cookie_len = 0;
962
0
    }
963
0
    ctrl->data = control;
964
965
0
    return ctrl;
966
0
  }
967
968
0
  if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SERVER_SORT_NAME) == 0) {
969
0
    struct ldb_server_sort_control **control;
970
0
    const char *p;
971
0
    char attr[256];
972
0
    char rule[128];
973
0
    int crit, rev, ret;
974
975
0
    attr[0] = '\0';
976
0
    rule[0] = '\0';
977
0
    p = &(control_strings[sizeof(LDB_CONTROL_SERVER_SORT_NAME)]);
978
0
    ret = sscanf(p, "%d:%d:%255[^:]:%127[^:]", &crit, &rev, attr, rule);
979
0
    if ((ret < 3) || (crit < 0) || (crit > 1) || (rev < 0 ) || (rev > 1) ||attr[0] == '\0') {
980
0
      ldb_set_errstring(ldb,
981
0
            "invalid server_sort control syntax\n"
982
0
            " syntax: crit(b):rev(b):attr(s)[:rule(s)]\n"
983
0
            "   note: b = boolean, s = string");
984
0
      talloc_free(ctrl);
985
0
      return NULL;
986
0
    }
987
0
    ctrl->oid = LDB_CONTROL_SERVER_SORT_OID;
988
0
    ctrl->critical = crit;
989
0
    control = talloc_array(ctrl, struct ldb_server_sort_control *, 2);
990
0
    if (control == NULL) {
991
0
      ldb_oom(ldb);
992
0
      talloc_free(ctrl);
993
0
      return NULL;
994
0
    }
995
996
0
    control[0] = talloc(control, struct ldb_server_sort_control);
997
0
    if (control[0] == NULL) {
998
0
      ldb_oom(ldb);
999
0
      talloc_free(ctrl);
1000
0
      return NULL;
1001
0
    }
1002
1003
0
    control[0]->attributeName = talloc_strdup(control, attr);
1004
0
    if (control[0]->attributeName == NULL) {
1005
0
      ldb_oom(ldb);
1006
0
      talloc_free(ctrl);
1007
0
      return NULL;
1008
0
    }
1009
1010
0
    if (rule[0]) {
1011
0
      control[0]->orderingRule = talloc_strdup(control, rule);
1012
0
      if (control[0]->orderingRule == NULL) {
1013
0
        ldb_oom(ldb);
1014
0
        talloc_free(ctrl);
1015
0
        return NULL;
1016
0
      }
1017
0
    } else {
1018
0
      control[0]->orderingRule = NULL;
1019
0
    }
1020
0
    control[0]->reverse = rev;
1021
0
    control[1] = NULL;
1022
0
    ctrl->data = control;
1023
1024
0
    return ctrl;
1025
0
  }
1026
1027
0
  if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_NOTIFICATION_NAME) == 0) {
1028
0
    const char *p;
1029
0
    int crit, ret;
1030
1031
0
    p = &(control_strings[sizeof(LDB_CONTROL_NOTIFICATION_NAME)]);
1032
0
    ret = sscanf(p, "%d", &crit);
1033
0
    if ((ret != 1) || (crit < 0) || (crit > 1)) {
1034
0
      ldb_set_errstring(ldb,
1035
0
            "invalid notification control syntax\n"
1036
0
            " syntax: crit(b)\n"
1037
0
            "   note: b = boolean");
1038
0
      talloc_free(ctrl);
1039
0
      return NULL;
1040
0
    }
1041
1042
0
    ctrl->oid = LDB_CONTROL_NOTIFICATION_OID;
1043
0
    ctrl->critical = crit;
1044
0
    ctrl->data = NULL;
1045
1046
0
    return ctrl;
1047
0
  }
1048
1049
0
  if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_TREE_DELETE_NAME) == 0) {
1050
0
    const char *p;
1051
0
    int crit, ret;
1052
1053
0
    p = &(control_strings[sizeof(LDB_CONTROL_TREE_DELETE_NAME)]);
1054
0
    ret = sscanf(p, "%d", &crit);
1055
0
    if ((ret != 1) || (crit < 0) || (crit > 1)) {
1056
0
      ldb_set_errstring(ldb,
1057
0
            "invalid tree_delete control syntax\n"
1058
0
            " syntax: crit(b)\n"
1059
0
            "   note: b = boolean");
1060
0
      talloc_free(ctrl);
1061
0
      return NULL;
1062
0
    }
1063
1064
0
    ctrl->oid = LDB_CONTROL_TREE_DELETE_OID;
1065
0
    ctrl->critical = crit;
1066
0
    ctrl->data = NULL;
1067
1068
0
    return ctrl;
1069
0
  }
1070
1071
0
  if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SHOW_DELETED_NAME) == 0) {
1072
0
    const char *p;
1073
0
    int crit, ret;
1074
1075
0
    p = &(control_strings[sizeof(LDB_CONTROL_SHOW_DELETED_NAME)]);
1076
0
    ret = sscanf(p, "%d", &crit);
1077
0
    if ((ret != 1) || (crit < 0) || (crit > 1)) {
1078
0
      ldb_set_errstring(ldb,
1079
0
            "invalid show_deleted control syntax\n"
1080
0
            " syntax: crit(b)\n"
1081
0
            "   note: b = boolean");
1082
0
      talloc_free(ctrl);
1083
0
      return NULL;
1084
0
    }
1085
1086
0
    ctrl->oid = LDB_CONTROL_SHOW_DELETED_OID;
1087
0
    ctrl->critical = crit;
1088
0
    ctrl->data = NULL;
1089
1090
0
    return ctrl;
1091
0
  }
1092
1093
0
  if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SHOW_DEACTIVATED_LINK_NAME) == 0) {
1094
0
    const char *p;
1095
0
    int crit, ret;
1096
1097
0
    p = &(control_strings[sizeof(LDB_CONTROL_SHOW_DEACTIVATED_LINK_NAME)]);
1098
0
    ret = sscanf(p, "%d", &crit);
1099
0
    if ((ret != 1) || (crit < 0) || (crit > 1)) {
1100
0
      ldb_set_errstring(ldb,
1101
0
            "invalid show_deactivated_link control syntax\n"
1102
0
            " syntax: crit(b)\n"
1103
0
            "   note: b = boolean");
1104
0
      talloc_free(ctrl);
1105
0
      return NULL;
1106
0
    }
1107
1108
0
    ctrl->oid = LDB_CONTROL_SHOW_DEACTIVATED_LINK_OID;
1109
0
    ctrl->critical = crit;
1110
0
    ctrl->data = NULL;
1111
1112
0
    return ctrl;
1113
0
  }
1114
1115
0
  if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SHOW_RECYCLED_NAME) == 0) {
1116
0
    const char *p;
1117
0
    int crit, ret;
1118
1119
0
    p = &(control_strings[sizeof(LDB_CONTROL_SHOW_RECYCLED_NAME)]);
1120
0
    ret = sscanf(p, "%d", &crit);
1121
0
    if ((ret != 1) || (crit < 0) || (crit > 1)) {
1122
0
      ldb_set_errstring(ldb,
1123
0
            "invalid show_recycled control syntax\n"
1124
0
            " syntax: crit(b)\n"
1125
0
            "   note: b = boolean");
1126
0
      talloc_free(ctrl);
1127
0
      return NULL;
1128
0
    }
1129
1130
0
    ctrl->oid = LDB_CONTROL_SHOW_RECYCLED_OID;
1131
0
    ctrl->critical = crit;
1132
0
    ctrl->data = NULL;
1133
1134
0
    return ctrl;
1135
0
  }
1136
1137
0
  if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_PERMISSIVE_MODIFY_NAME) == 0) {
1138
0
    const char *p;
1139
0
    int crit, ret;
1140
1141
0
    p = &(control_strings[sizeof(LDB_CONTROL_PERMISSIVE_MODIFY_NAME)]);
1142
0
    ret = sscanf(p, "%d", &crit);
1143
0
    if ((ret != 1) || (crit < 0) || (crit > 1)) {
1144
0
      ldb_set_errstring(ldb,
1145
0
            "invalid permissive_modify control syntax\n"
1146
0
            " syntax: crit(b)\n"
1147
0
            "   note: b = boolean");
1148
0
      talloc_free(ctrl);
1149
0
      return NULL;
1150
0
    }
1151
1152
0
    ctrl->oid = LDB_CONTROL_PERMISSIVE_MODIFY_OID;
1153
0
    ctrl->critical = crit;
1154
0
    ctrl->data = NULL;
1155
1156
0
    return ctrl;
1157
0
  }
1158
1159
0
  if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_REVEAL_INTERNALS_NAME) == 0) {
1160
0
    const char *p;
1161
0
    int crit, ret;
1162
1163
0
    p = &(control_strings[sizeof(LDB_CONTROL_REVEAL_INTERNALS_NAME)]);
1164
0
    ret = sscanf(p, "%d", &crit);
1165
0
    if ((ret != 1) || (crit < 0) || (crit > 1)) {
1166
0
      ldb_set_errstring(ldb,
1167
0
            "invalid reveal_internals control syntax\n"
1168
0
            " syntax: crit(b)\n"
1169
0
            "   note: b = boolean");
1170
0
      talloc_free(ctrl);
1171
0
      return NULL;
1172
0
    }
1173
1174
0
    ctrl->oid = LDB_CONTROL_REVEAL_INTERNALS;
1175
0
    ctrl->critical = crit;
1176
0
    ctrl->data = NULL;
1177
1178
0
    return ctrl;
1179
0
  }
1180
1181
0
  if (strncmp(control_strings, "local_oid:", 10) == 0) {
1182
0
    const char *p;
1183
0
    int crit = 0, ret = 0;
1184
0
    char oid[256];
1185
1186
0
    oid[0] = '\0';
1187
0
    p = &(control_strings[10]);
1188
0
    ret = sscanf(p, "%255[^:]:%d", oid, &crit);
1189
1190
0
    if ((ret != 2) || strlen(oid) == 0 || (crit < 0) || (crit > 1)) {
1191
0
      ldb_set_errstring(ldb,
1192
0
            "invalid local_oid control syntax\n"
1193
0
            " syntax: oid(s):crit(b)\n"
1194
0
            "   note: b = boolean, s = string");
1195
0
      talloc_free(ctrl);
1196
0
      return NULL;
1197
0
    }
1198
1199
0
    ctrl->oid = talloc_strdup(ctrl, oid);
1200
0
    if (!ctrl->oid) {
1201
0
      ldb_oom(ldb);
1202
0
      talloc_free(ctrl);
1203
0
      return NULL;
1204
0
    }
1205
0
    ctrl->critical = crit;
1206
0
    ctrl->data = NULL;
1207
1208
0
    return ctrl;
1209
0
  }
1210
1211
0
  if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_RODC_DCPROMO_NAME) == 0) {
1212
0
    const char *p;
1213
0
    int crit, ret;
1214
1215
0
    p = &(control_strings[sizeof(LDB_CONTROL_RODC_DCPROMO_NAME)]);
1216
0
    ret = sscanf(p, "%d", &crit);
1217
0
    if ((ret != 1) || (crit < 0) || (crit > 1)) {
1218
0
      ldb_set_errstring(ldb,
1219
0
            "invalid rodc_join control syntax\n"
1220
0
            " syntax: crit(b)\n"
1221
0
            "   note: b = boolean");
1222
0
      talloc_free(ctrl);
1223
0
      return NULL;
1224
0
    }
1225
1226
0
    ctrl->oid = LDB_CONTROL_RODC_DCPROMO_OID;
1227
0
    ctrl->critical = crit;
1228
0
    ctrl->data = NULL;
1229
1230
0
    return ctrl;
1231
0
  }
1232
1233
0
  if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_PROVISION_NAME) == 0) {
1234
0
    const char *p;
1235
0
    int crit, ret;
1236
1237
0
    p = &(control_strings[sizeof(LDB_CONTROL_PROVISION_NAME)]);
1238
0
    ret = sscanf(p, "%d", &crit);
1239
0
    if ((ret != 1) || (crit < 0) || (crit > 1)) {
1240
0
      ldb_set_errstring(ldb,
1241
0
            "invalid provision control syntax\n"
1242
0
            " syntax: crit(b)\n"
1243
0
            "   note: b = boolean");
1244
0
      talloc_free(ctrl);
1245
0
      return NULL;
1246
0
    }
1247
1248
0
    ctrl->oid = LDB_CONTROL_PROVISION_OID;
1249
0
    ctrl->critical = crit;
1250
0
    ctrl->data = NULL;
1251
1252
0
    return ctrl;
1253
0
  }
1254
0
  if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_VERIFY_NAME_NAME) == 0) {
1255
0
    const char *p;
1256
0
    char gc[1024];
1257
0
    int crit, flags, ret;
1258
0
    struct ldb_verify_name_control *control;
1259
1260
0
    gc[0] = '\0';
1261
1262
0
    p = &(control_strings[sizeof(LDB_CONTROL_VERIFY_NAME_NAME)]);
1263
0
    ret = sscanf(p, "%d:%d:%1023[^$]", &crit, &flags, gc);
1264
0
    if ((ret != 3) || (crit < 0) || (crit > 1)) {
1265
0
      ret = sscanf(p, "%d:%d", &crit, &flags);
1266
0
      if ((ret != 2) || (crit < 0) || (crit > 1)) {
1267
0
        ldb_set_errstring(ldb,
1268
0
              "invalid verify_name control syntax\n"
1269
0
              " syntax: crit(b):flags(i)[:gc(s)]\n"
1270
0
              "   note: b = boolean"
1271
0
              "   note: i = integer"
1272
0
              "   note: s = string");
1273
0
        talloc_free(ctrl);
1274
0
        return NULL;
1275
0
      }
1276
0
    }
1277
1278
0
    ctrl->oid = LDB_CONTROL_VERIFY_NAME_OID;
1279
0
    ctrl->critical = crit;
1280
0
    control = talloc(ctrl, struct ldb_verify_name_control);
1281
0
    if (control == NULL) {
1282
0
      ldb_oom(ldb);
1283
0
      talloc_free(ctrl);
1284
0
      return NULL;
1285
0
    }
1286
1287
0
    control->gc = talloc_strdup(control, gc);
1288
0
    if (control->gc == NULL) {
1289
0
      ldb_oom(ldb);
1290
0
      talloc_free(ctrl);
1291
0
      return NULL;
1292
0
    }
1293
1294
0
    control->gc_len = strlen(gc);
1295
0
    control->flags = flags;
1296
0
    ctrl->data = control;
1297
0
    return ctrl;
1298
0
  }
1299
1300
0
  if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_POLICY_HINTS_NAME) == 0) {
1301
0
    const char *p = NULL;
1302
0
    int crit, val, ret;
1303
1304
0
    p = &(control_strings[sizeof(LDB_CONTROL_POLICY_HINTS_NAME)]);
1305
0
    ret = sscanf(p, "%d:%d", &crit, &val);
1306
0
    if ((ret != 2) || (crit < 0) || (crit > 1)) {
1307
0
      ldb_set_errstring(ldb,
1308
0
            "invalid pwd_policy_hints control syntax\n"
1309
0
            " syntax: crit(b):flags(n)\n"
1310
0
            "   note: b = boolean, n = number");
1311
0
      talloc_free(ctrl);
1312
0
      return NULL;
1313
0
    }
1314
1315
0
    ctrl->oid = LDB_CONTROL_POLICY_HINTS_OID;
1316
0
    ctrl->critical = crit;
1317
0
    ctrl->data = talloc(ctrl, int);
1318
0
    *((int*)ctrl->data) = val;
1319
0
    return ctrl;
1320
0
  }
1321
1322
0
  if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_POLICY_HINTS_DEPRECATED_NAME) == 0) {
1323
0
    const char *p = NULL;
1324
0
    int crit, val, ret;
1325
1326
0
    p = &(control_strings[sizeof(LDB_CONTROL_POLICY_HINTS_DEPRECATED_NAME)]);
1327
0
    ret = sscanf(p, "%d:%d", &crit, &val);
1328
0
    if ((ret != 2) || (crit < 0) || (crit > 1)) {
1329
0
      ldb_set_errstring(ldb,
1330
0
            "invalid pwd_policy_hints control syntax\n"
1331
0
            " syntax: crit(b):flags(n)\n"
1332
0
            "   note: b = boolean, n = number");
1333
0
      talloc_free(ctrl);
1334
0
      return NULL;
1335
0
    }
1336
1337
0
    ctrl->oid = LDB_CONTROL_POLICY_HINTS_DEPRECATED_OID;
1338
0
    ctrl->critical = crit;
1339
0
    ctrl->data = talloc(ctrl, int);
1340
0
    *((int*)ctrl->data) = val;
1341
0
    return ctrl;
1342
0
  }
1343
1344
1345
  /*
1346
   * When no matching control has been found.
1347
   */
1348
0
  TALLOC_FREE(ctrl);
1349
0
  return NULL;
1350
0
}
1351
1352
/* Parse controls from the format used on the command line and in ejs */
1353
struct ldb_control **ldb_parse_control_strings(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char **control_strings)
1354
0
{
1355
0
  unsigned int i;
1356
0
  struct ldb_control **ctrl;
1357
1358
0
  if (control_strings == NULL || control_strings[0] == NULL)
1359
0
    return NULL;
1360
1361
0
  for (i = 0; control_strings[i]; i++);
1362
1363
0
  ctrl = talloc_array(mem_ctx, struct ldb_control *, i + 1);
1364
1365
0
  ldb_reset_err_string(ldb);
1366
0
  for (i = 0; control_strings[i]; i++) {
1367
0
    ctrl[i] = ldb_parse_control_from_string(ldb, ctrl, control_strings[i]);
1368
0
    if (ctrl[i] == NULL) {
1369
0
      if (ldb_errstring(ldb) == NULL) {
1370
        /* no controls matched, throw an error */
1371
0
        ldb_asprintf_errstring(ldb, "Invalid control name: '%s'", control_strings[i]);
1372
0
      }
1373
0
      talloc_free(ctrl);
1374
0
      return NULL;
1375
0
    }
1376
0
  }
1377
1378
0
  ctrl[i] = NULL;
1379
1380
0
  return ctrl;
1381
0
}