Coverage Report

Created: 2026-04-01 06:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source4/dsdb/samdb/ldb_modules/util.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS implementation.
3
   Samba utility functions
4
5
   Copyright (C) Andrew Tridgell 2009
6
   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
7
   Copyright (C) Matthieu Patou <mat@matws.net> 2011
8
9
   This program is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 3 of the License, or
12
   (at your option) any later version.
13
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
19
   You should have received a copy of the GNU General Public License
20
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
*/
22
23
#include "includes.h"
24
#include "ldb.h"
25
#include "ldb_module.h"
26
#include "librpc/ndr/libndr.h"
27
#include "dsdb/samdb/ldb_modules/util.h"
28
#include "dsdb/samdb/samdb.h"
29
#include "dsdb/common/util.h"
30
#include "libcli/security/security.h"
31
32
#undef strcasecmp
33
34
/*
35
  search for attrs on one DN, in the modules below
36
 */
37
int dsdb_module_search_dn(struct ldb_module *module,
38
        TALLOC_CTX *mem_ctx,
39
        struct ldb_result **_res,
40
        struct ldb_dn *basedn,
41
        const char * const *attrs,
42
        uint32_t dsdb_flags,
43
        struct ldb_request *parent)
44
0
{
45
0
  int ret;
46
0
  struct ldb_request *req;
47
0
  TALLOC_CTX *tmp_ctx;
48
0
  struct ldb_result *res;
49
50
0
  tmp_ctx = talloc_new(mem_ctx);
51
0
  if (tmp_ctx == NULL) {
52
0
    return ldb_oom(ldb_module_get_ctx(module));
53
0
  }
54
55
0
  res = talloc_zero(tmp_ctx, struct ldb_result);
56
0
  if (!res) {
57
0
    talloc_free(tmp_ctx);
58
0
    return ldb_oom(ldb_module_get_ctx(module));
59
0
  }
60
61
0
  ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
62
0
           basedn,
63
0
           LDB_SCOPE_BASE,
64
0
           NULL,
65
0
           attrs,
66
0
           NULL,
67
0
           res,
68
0
           ldb_search_default_callback,
69
0
           parent);
70
0
  LDB_REQ_SET_LOCATION(req);
71
0
  if (ret != LDB_SUCCESS) {
72
0
    talloc_free(tmp_ctx);
73
0
    return ret;
74
0
  }
75
76
0
  ret = dsdb_request_add_controls(req, dsdb_flags);
77
0
  if (ret != LDB_SUCCESS) {
78
0
    talloc_free(tmp_ctx);
79
0
    return ret;
80
0
  }
81
82
0
  if (dsdb_flags & DSDB_FLAG_TRUSTED) {
83
0
    ldb_req_mark_trusted(req);
84
0
  }
85
86
  /* Run the new request */
87
0
  if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
88
0
    ret = ldb_next_request(module, req);
89
0
  } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
90
0
    ret = ldb_request(ldb_module_get_ctx(module), req);
91
0
  } else {
92
0
    const struct ldb_module_ops *ops = ldb_module_get_ops(module);
93
0
    SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
94
0
    ret = ops->search(module, req);
95
0
  }
96
0
  if (ret == LDB_SUCCESS) {
97
0
    ret = ldb_wait(req->handle, LDB_WAIT_ALL);
98
0
  }
99
100
0
  if (ret != LDB_SUCCESS) {
101
0
    talloc_free(tmp_ctx);
102
0
    return ret;
103
0
  }
104
105
0
  if (res->count != 1) {
106
    /* we may be reading a DB that does not have the 'check base on search' option... */
107
0
    ret = LDB_ERR_NO_SUCH_OBJECT;
108
0
    ldb_asprintf_errstring(ldb_module_get_ctx(module),
109
0
               "dsdb_module_search_dn: did not find base dn %s (%d results)",
110
0
               ldb_dn_get_linearized(basedn), res->count);
111
0
  } else {
112
0
    *_res = talloc_steal(mem_ctx, res);
113
0
  }
114
0
  talloc_free(tmp_ctx);
115
0
  return ret;
116
0
}
117
118
int dsdb_module_search_tree(struct ldb_module *module,
119
           TALLOC_CTX *mem_ctx,
120
           struct ldb_result **_res,
121
           struct ldb_dn *basedn,
122
           enum ldb_scope scope,
123
           struct ldb_parse_tree *tree,
124
           const char * const *attrs,
125
           int dsdb_flags,
126
           struct ldb_request *parent)
127
0
{
128
0
  int ret;
129
0
  struct ldb_request *req;
130
0
  TALLOC_CTX *tmp_ctx;
131
0
  struct ldb_result *res;
132
133
0
  tmp_ctx = talloc_new(mem_ctx);
134
0
  if (tmp_ctx == NULL) {
135
0
    return ldb_oom(ldb_module_get_ctx(module));
136
0
  }
137
138
  /* cross-partitions searches with a basedn break multi-domain support */
139
0
  SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
140
141
0
  res = talloc_zero(tmp_ctx, struct ldb_result);
142
0
  if (!res) {
143
0
    talloc_free(tmp_ctx);
144
0
    return ldb_oom(ldb_module_get_ctx(module));
145
0
  }
146
147
0
  ret = ldb_build_search_req_ex(&req, ldb_module_get_ctx(module), tmp_ctx,
148
0
           basedn,
149
0
           scope,
150
0
           tree,
151
0
           attrs,
152
0
           NULL,
153
0
           res,
154
0
           ldb_search_default_callback,
155
0
           parent);
156
0
  LDB_REQ_SET_LOCATION(req);
157
0
  if (ret != LDB_SUCCESS) {
158
0
    talloc_free(tmp_ctx);
159
0
    return ret;
160
0
  }
161
162
0
  ret = dsdb_request_add_controls(req, dsdb_flags);
163
0
  if (ret != LDB_SUCCESS) {
164
0
    talloc_free(tmp_ctx);
165
0
    return ret;
166
0
  }
167
168
0
  if (dsdb_flags & DSDB_FLAG_TRUSTED) {
169
0
    ldb_req_mark_trusted(req);
170
0
  }
171
172
0
  if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
173
0
    ret = ldb_next_request(module, req);
174
0
  } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
175
0
    ret = ldb_request(ldb_module_get_ctx(module), req);
176
0
  } else {
177
0
    const struct ldb_module_ops *ops = ldb_module_get_ops(module);
178
0
    SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
179
0
    ret = ops->search(module, req);
180
0
  }
181
0
  if (ret == LDB_SUCCESS) {
182
0
    ret = ldb_wait(req->handle, LDB_WAIT_ALL);
183
0
  }
184
185
0
  if (dsdb_flags & DSDB_SEARCH_ONE_ONLY) {
186
0
    if (res->count == 0) {
187
0
      talloc_free(tmp_ctx);
188
0
      return ldb_error(ldb_module_get_ctx(module), LDB_ERR_NO_SUCH_OBJECT, __func__);
189
0
    }
190
0
    if (res->count != 1) {
191
0
      talloc_free(tmp_ctx);
192
0
      ldb_reset_err_string(ldb_module_get_ctx(module));
193
0
      return LDB_ERR_CONSTRAINT_VIOLATION;
194
0
    }
195
0
  }
196
197
0
  talloc_free(req);
198
0
  if (ret == LDB_SUCCESS) {
199
0
    *_res = talloc_steal(mem_ctx, res);
200
0
  }
201
0
  talloc_free(tmp_ctx);
202
0
  return ret;
203
0
}
204
205
/*
206
  search for attrs in the modules below
207
 */
208
int dsdb_module_search(struct ldb_module *module,
209
           TALLOC_CTX *mem_ctx,
210
           struct ldb_result **_res,
211
           struct ldb_dn *basedn, enum ldb_scope scope,
212
           const char * const *attrs,
213
           int dsdb_flags,
214
           struct ldb_request *parent,
215
           const char *format, ...) _PRINTF_ATTRIBUTE(9, 10)
216
0
{
217
0
  int ret;
218
0
  TALLOC_CTX *tmp_ctx;
219
0
  va_list ap;
220
0
  char *expression;
221
0
  struct ldb_parse_tree *tree;
222
223
  /* cross-partitions searches with a basedn break multi-domain support */
224
0
  SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
225
226
0
  tmp_ctx = talloc_new(mem_ctx);
227
0
  if (tmp_ctx == NULL) {
228
0
    return ldb_oom(ldb_module_get_ctx(module));
229
0
  }
230
231
0
  if (format) {
232
0
    va_start(ap, format);
233
0
    expression = talloc_vasprintf(tmp_ctx, format, ap);
234
0
    va_end(ap);
235
236
0
    if (!expression) {
237
0
      talloc_free(tmp_ctx);
238
0
      return ldb_oom(ldb_module_get_ctx(module));
239
0
    }
240
0
  } else {
241
0
    expression = NULL;
242
0
  }
243
244
0
  tree = ldb_parse_tree(tmp_ctx, expression);
245
0
  if (tree == NULL) {
246
0
    talloc_free(tmp_ctx);
247
0
    ldb_set_errstring(ldb_module_get_ctx(module),
248
0
        "Unable to parse search expression");
249
0
    return LDB_ERR_OPERATIONS_ERROR;
250
0
  }
251
252
0
  ret = dsdb_module_search_tree(module,
253
0
           mem_ctx,
254
0
           _res,
255
0
           basedn,
256
0
           scope,
257
0
           tree,
258
0
           attrs,
259
0
           dsdb_flags,
260
0
           parent);
261
262
0
  talloc_free(tmp_ctx);
263
0
  return ret;
264
0
}
265
266
/*
267
  find an object given a GUID. This searches across all partitions
268
 */
269
int dsdb_module_obj_by_guid(struct ldb_module *module,
270
          TALLOC_CTX *mem_ctx,
271
          struct ldb_message **_msg,
272
          const struct GUID *guid,
273
          const char * const *attrs,
274
          struct ldb_request *parent)
275
0
{
276
0
  struct ldb_result *res;
277
0
  TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
278
0
  int ret;
279
280
0
  ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
281
0
         attrs,
282
0
         DSDB_FLAG_NEXT_MODULE |
283
0
         DSDB_SEARCH_SHOW_RECYCLED |
284
0
         DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
285
0
         DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
286
0
         parent,
287
0
         "objectGUID=%s", GUID_string(tmp_ctx, guid));
288
0
  if (ret != LDB_SUCCESS) {
289
0
    talloc_free(tmp_ctx);
290
0
    return ret;
291
0
  }
292
0
  if (res->count == 0) {
293
0
    talloc_free(tmp_ctx);
294
0
    return ldb_error(ldb_module_get_ctx(module), LDB_ERR_NO_SUCH_OBJECT, __func__);
295
0
  }
296
0
  if (res->count != 1) {
297
0
    ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching objectGUID %s\n",
298
0
               GUID_string(tmp_ctx, guid));
299
0
    talloc_free(tmp_ctx);
300
0
    return LDB_ERR_OPERATIONS_ERROR;
301
0
  }
302
303
0
  *_msg = talloc_steal(mem_ctx, res->msgs[0]);
304
305
0
  talloc_free(tmp_ctx);
306
0
  return LDB_SUCCESS;
307
0
}
308
309
/*
310
  find a DN given a GUID. This searches across all partitions
311
 */
312
int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
313
         const struct GUID *guid, struct ldb_dn **dn,
314
         struct ldb_request *parent)
315
0
{
316
0
  struct ldb_message *msg = NULL;
317
0
  static const char * const attrs[] = { NULL };
318
0
  TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
319
0
  int ret;
320
321
0
  ret = dsdb_module_obj_by_guid(module,
322
0
              tmp_ctx,
323
0
              &msg,
324
0
              guid,
325
0
              attrs,
326
0
              parent);
327
0
  if (ret != LDB_SUCCESS) {
328
0
    talloc_free(tmp_ctx);
329
0
    return ret;
330
0
  }
331
332
0
  *dn = talloc_steal(mem_ctx, msg->dn);
333
334
0
  talloc_free(tmp_ctx);
335
0
  return LDB_SUCCESS;
336
0
}
337
338
/*
339
  find a GUID given a DN.
340
 */
341
int dsdb_module_guid_by_dn(struct ldb_module *module, struct ldb_dn *dn, struct GUID *guid,
342
         struct ldb_request *parent)
343
0
{
344
0
  static const char * const attrs[] = { NULL };
345
0
  struct ldb_result *res;
346
0
  TALLOC_CTX *tmp_ctx = talloc_new(module);
347
0
  int ret;
348
0
  NTSTATUS status;
349
350
0
  ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, attrs,
351
0
                              DSDB_FLAG_NEXT_MODULE |
352
0
                              DSDB_SEARCH_SHOW_RECYCLED |
353
0
            DSDB_SEARCH_SHOW_EXTENDED_DN,
354
0
            parent);
355
0
  if (ret != LDB_SUCCESS) {
356
0
    ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to find GUID for %s",
357
0
               ldb_dn_get_linearized(dn));
358
0
    talloc_free(tmp_ctx);
359
0
    return ret;
360
0
  }
361
362
0
  status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
363
0
  if (!NT_STATUS_IS_OK(status)) {
364
0
    talloc_free(tmp_ctx);
365
0
    return ldb_operr(ldb_module_get_ctx(module));
366
0
  }
367
368
0
  talloc_free(tmp_ctx);
369
0
  return LDB_SUCCESS;
370
0
}
371
372
373
/*
374
  a ldb_extended request operating on modules below the
375
  current module
376
377
  Note that this does not automatically start a transaction. If you
378
  need a transaction the caller needs to start it as needed.
379
 */
380
int dsdb_module_extended(struct ldb_module *module,
381
       TALLOC_CTX *mem_ctx,
382
       struct ldb_result **_res,
383
       const char* oid, void* data,
384
       uint32_t dsdb_flags,
385
       struct ldb_request *parent)
386
0
{
387
0
  struct ldb_request *req;
388
0
  int ret;
389
0
  struct ldb_context *ldb = ldb_module_get_ctx(module);
390
0
  TALLOC_CTX *tmp_ctx = talloc_new(module);
391
0
  struct ldb_result *res;
392
393
0
  if (_res != NULL) {
394
0
    (*_res) = NULL;
395
0
  }
396
397
0
  res = talloc_zero(tmp_ctx, struct ldb_result);
398
0
  if (!res) {
399
0
    talloc_free(tmp_ctx);
400
0
    return ldb_oom(ldb_module_get_ctx(module));
401
0
  }
402
403
0
  ret = ldb_build_extended_req(&req, ldb,
404
0
      tmp_ctx,
405
0
      oid,
406
0
      data,
407
0
      NULL,
408
0
      res, ldb_extended_default_callback,
409
0
      parent);
410
411
0
  LDB_REQ_SET_LOCATION(req);
412
0
  if (ret != LDB_SUCCESS) {
413
0
    talloc_free(tmp_ctx);
414
0
    return ret;
415
0
  }
416
417
0
  ret = dsdb_request_add_controls(req, dsdb_flags);
418
0
  if (ret != LDB_SUCCESS) {
419
0
    talloc_free(tmp_ctx);
420
0
    return ret;
421
0
  }
422
423
0
  if (dsdb_flags & DSDB_FLAG_TRUSTED) {
424
0
    ldb_req_mark_trusted(req);
425
0
  }
426
427
  /* Run the new request */
428
0
  if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
429
0
    ret = ldb_next_request(module, req);
430
0
  } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
431
0
    ret = ldb_request(ldb_module_get_ctx(module), req);
432
0
  } else {
433
0
    const struct ldb_module_ops *ops = ldb_module_get_ops(module);
434
0
    SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
435
0
    ret = ops->extended(module, req);
436
0
  }
437
0
  if (ret == LDB_SUCCESS) {
438
0
    ret = ldb_wait(req->handle, LDB_WAIT_ALL);
439
0
  }
440
441
0
  if (_res != NULL && ret == LDB_SUCCESS) {
442
0
    (*_res) = talloc_steal(mem_ctx, res);
443
0
  }
444
445
0
  talloc_free(tmp_ctx);
446
0
  return ret;
447
0
}
448
449
450
/*
451
  a ldb_modify request operating on modules below the
452
  current module
453
 */
454
int dsdb_module_modify(struct ldb_module *module,
455
           const struct ldb_message *message,
456
           uint32_t dsdb_flags,
457
           struct ldb_request *parent)
458
0
{
459
0
  struct ldb_request *mod_req;
460
0
  int ret;
461
0
  struct ldb_context *ldb = ldb_module_get_ctx(module);
462
0
  TALLOC_CTX *tmp_ctx = talloc_new(module);
463
0
  struct ldb_result *res;
464
465
0
  res = talloc_zero(tmp_ctx, struct ldb_result);
466
0
  if (!res) {
467
0
    talloc_free(tmp_ctx);
468
0
    return ldb_oom(ldb_module_get_ctx(module));
469
0
  }
470
471
0
  ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
472
0
        message,
473
0
        NULL,
474
0
        res,
475
0
        ldb_modify_default_callback,
476
0
        parent);
477
0
  LDB_REQ_SET_LOCATION(mod_req);
478
0
  if (ret != LDB_SUCCESS) {
479
0
    talloc_free(tmp_ctx);
480
0
    return ret;
481
0
  }
482
483
0
  ret = dsdb_request_add_controls(mod_req, dsdb_flags);
484
0
  if (ret != LDB_SUCCESS) {
485
0
    talloc_free(tmp_ctx);
486
0
    return ret;
487
0
  }
488
489
0
  if (dsdb_flags & DSDB_FLAG_TRUSTED) {
490
0
    ldb_req_mark_trusted(mod_req);
491
0
  }
492
493
  /* Run the new request */
494
0
  if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
495
0
    ret = ldb_next_request(module, mod_req);
496
0
  } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
497
0
    ret = ldb_request(ldb_module_get_ctx(module), mod_req);
498
0
  } else {
499
0
    const struct ldb_module_ops *ops = ldb_module_get_ops(module);
500
0
    SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
501
0
    ret = ops->modify(module, mod_req);
502
0
  }
503
0
  if (ret == LDB_SUCCESS) {
504
0
    ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
505
0
  }
506
507
0
  talloc_free(tmp_ctx);
508
0
  return ret;
509
0
}
510
511
512
513
/*
514
  a ldb_rename request operating on modules below the
515
  current module
516
 */
517
int dsdb_module_rename(struct ldb_module *module,
518
           struct ldb_dn *olddn, struct ldb_dn *newdn,
519
           uint32_t dsdb_flags,
520
           struct ldb_request *parent)
521
0
{
522
0
  struct ldb_request *req;
523
0
  int ret;
524
0
  struct ldb_context *ldb = ldb_module_get_ctx(module);
525
0
  TALLOC_CTX *tmp_ctx = talloc_new(module);
526
0
  struct ldb_result *res;
527
528
0
  res = talloc_zero(tmp_ctx, struct ldb_result);
529
0
  if (!res) {
530
0
    talloc_free(tmp_ctx);
531
0
    return ldb_oom(ldb_module_get_ctx(module));
532
0
  }
533
534
0
  ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
535
0
           olddn,
536
0
           newdn,
537
0
           NULL,
538
0
           res,
539
0
           ldb_modify_default_callback,
540
0
           parent);
541
0
  LDB_REQ_SET_LOCATION(req);
542
0
  if (ret != LDB_SUCCESS) {
543
0
    talloc_free(tmp_ctx);
544
0
    return ret;
545
0
  }
546
547
0
  ret = dsdb_request_add_controls(req, dsdb_flags);
548
0
  if (ret != LDB_SUCCESS) {
549
0
    talloc_free(tmp_ctx);
550
0
    return ret;
551
0
  }
552
553
0
  if (dsdb_flags & DSDB_FLAG_TRUSTED) {
554
0
    ldb_req_mark_trusted(req);
555
0
  }
556
557
  /* Run the new request */
558
0
  if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
559
0
    ret = ldb_next_request(module, req);
560
0
  } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
561
0
    ret = ldb_request(ldb_module_get_ctx(module), req);
562
0
  } else {
563
0
    const struct ldb_module_ops *ops = ldb_module_get_ops(module);
564
0
    SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
565
0
    ret = ops->rename(module, req);
566
0
  }
567
0
  if (ret == LDB_SUCCESS) {
568
0
    ret = ldb_wait(req->handle, LDB_WAIT_ALL);
569
0
  }
570
571
0
  talloc_free(tmp_ctx);
572
0
  return ret;
573
0
}
574
575
/*
576
  a ldb_add request operating on modules below the
577
  current module
578
 */
579
int dsdb_module_add(struct ldb_module *module,
580
        const struct ldb_message *message,
581
        uint32_t dsdb_flags,
582
        struct ldb_request *parent)
583
0
{
584
0
  struct ldb_request *req;
585
0
  int ret;
586
0
  struct ldb_context *ldb = ldb_module_get_ctx(module);
587
0
  TALLOC_CTX *tmp_ctx = talloc_new(module);
588
0
  struct ldb_result *res;
589
590
0
  res = talloc_zero(tmp_ctx, struct ldb_result);
591
0
  if (!res) {
592
0
    talloc_free(tmp_ctx);
593
0
    return ldb_oom(ldb_module_get_ctx(module));
594
0
  }
595
596
0
  ret = ldb_build_add_req(&req, ldb, tmp_ctx,
597
0
        message,
598
0
        NULL,
599
0
        res,
600
0
        ldb_modify_default_callback,
601
0
        parent);
602
0
  LDB_REQ_SET_LOCATION(req);
603
0
  if (ret != LDB_SUCCESS) {
604
0
    talloc_free(tmp_ctx);
605
0
    return ret;
606
0
  }
607
608
0
  ret = dsdb_request_add_controls(req, dsdb_flags);
609
0
  if (ret != LDB_SUCCESS) {
610
0
    talloc_free(tmp_ctx);
611
0
    return ret;
612
0
  }
613
614
0
  if (dsdb_flags & DSDB_FLAG_TRUSTED) {
615
0
    ldb_req_mark_trusted(req);
616
0
  }
617
618
  /* Run the new request */
619
0
  if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
620
0
    ret = ldb_next_request(module, req);
621
0
  } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
622
0
    ret = ldb_request(ldb_module_get_ctx(module), req);
623
0
  } else {
624
0
    const struct ldb_module_ops *ops = ldb_module_get_ops(module);
625
0
    SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
626
0
    ret = ops->add(module, req);
627
0
  }
628
0
  if (ret == LDB_SUCCESS) {
629
0
    ret = ldb_wait(req->handle, LDB_WAIT_ALL);
630
0
  }
631
632
0
  talloc_free(tmp_ctx);
633
0
  return ret;
634
0
}
635
636
/*
637
  a ldb_delete request operating on modules below the
638
  current module
639
 */
640
int dsdb_module_del(struct ldb_module *module,
641
        struct ldb_dn *dn,
642
        uint32_t dsdb_flags,
643
        struct ldb_request *parent)
644
0
{
645
0
  struct ldb_request *req;
646
0
  int ret;
647
0
  struct ldb_context *ldb = ldb_module_get_ctx(module);
648
0
  TALLOC_CTX *tmp_ctx = talloc_new(module);
649
0
  struct ldb_result *res;
650
651
0
  res = talloc_zero(tmp_ctx, struct ldb_result);
652
0
  if (!res) {
653
0
    talloc_free(tmp_ctx);
654
0
    return ldb_oom(ldb);
655
0
  }
656
657
0
  ret = ldb_build_del_req(&req, ldb, tmp_ctx,
658
0
        dn,
659
0
        NULL,
660
0
        res,
661
0
        ldb_modify_default_callback,
662
0
        parent);
663
0
  LDB_REQ_SET_LOCATION(req);
664
0
  if (ret != LDB_SUCCESS) {
665
0
    talloc_free(tmp_ctx);
666
0
    return ret;
667
0
  }
668
669
0
  ret = dsdb_request_add_controls(req, dsdb_flags);
670
0
  if (ret != LDB_SUCCESS) {
671
0
    talloc_free(tmp_ctx);
672
0
    return ret;
673
0
  }
674
675
0
  if (dsdb_flags & DSDB_FLAG_TRUSTED) {
676
0
    ldb_req_mark_trusted(req);
677
0
  }
678
679
  /* Run the new request */
680
0
  if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
681
0
    ret = ldb_next_request(module, req);
682
0
  } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
683
0
    ret = ldb_request(ldb_module_get_ctx(module), req);
684
0
  } else {
685
0
    const struct ldb_module_ops *ops = ldb_module_get_ops(module);
686
0
    SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
687
0
    ret = ops->del(module, req);
688
0
  }
689
0
  if (ret == LDB_SUCCESS) {
690
0
    ret = ldb_wait(req->handle, LDB_WAIT_ALL);
691
0
  }
692
693
0
  talloc_free(tmp_ctx);
694
0
  return ret;
695
0
}
696
697
/*
698
  check if a single valued link has multiple non-deleted values
699
700
  This is needed when we will be using the RELAX control to stop
701
  ldb_tdb from checking single valued links
702
 */
703
int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
704
          const struct ldb_message_element *el)
705
0
{
706
0
  bool found_active = false;
707
0
  unsigned int i;
708
709
0
  if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
710
0
      el->num_values < 2) {
711
0
    return LDB_SUCCESS;
712
0
  }
713
714
0
  for (i=0; i<el->num_values; i++) {
715
0
    if (!dsdb_dn_is_deleted_val(&el->values[i])) {
716
0
      if (found_active) {
717
0
        return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
718
0
      }
719
0
      found_active = true;
720
0
    }
721
0
  }
722
723
0
  return LDB_SUCCESS;
724
0
}
725
726
727
int dsdb_check_samba_compatible_feature(struct ldb_module *module,
728
          const char *feature,
729
          bool *found)
730
0
{
731
0
  struct ldb_context *ldb = ldb_module_get_ctx(module);
732
0
  struct ldb_result *res;
733
0
  static const char * const samba_dsdb_attrs[] = {
734
0
    SAMBA_COMPATIBLE_FEATURES_ATTR,
735
0
    NULL
736
0
  };
737
0
  int ret;
738
0
  struct ldb_dn *samba_dsdb_dn = NULL;
739
0
  TALLOC_CTX *tmp_ctx = talloc_new(ldb);
740
0
  if (tmp_ctx == NULL) {
741
0
    *found = false;
742
0
    return ldb_oom(ldb);
743
0
  }
744
0
  *found = false;
745
746
0
  samba_dsdb_dn = ldb_dn_new(tmp_ctx, ldb, "@SAMBA_DSDB");
747
0
  if (samba_dsdb_dn == NULL) {
748
0
    TALLOC_FREE(tmp_ctx);
749
0
    return ldb_oom(ldb);
750
0
  }
751
752
0
  ret = dsdb_module_search_dn(module,
753
0
            tmp_ctx,
754
0
            &res,
755
0
            samba_dsdb_dn,
756
0
            samba_dsdb_attrs,
757
0
            DSDB_FLAG_NEXT_MODULE,
758
0
            NULL);
759
0
  if (ret == LDB_SUCCESS) {
760
0
    *found = ldb_msg_check_string_attribute(
761
0
      res->msgs[0],
762
0
      SAMBA_COMPATIBLE_FEATURES_ATTR,
763
0
      feature);
764
0
  } else if (ret == LDB_ERR_NO_SUCH_OBJECT) {
765
    /* it is not an error not to find it */
766
0
    ret = LDB_SUCCESS;
767
0
  }
768
0
  TALLOC_FREE(tmp_ctx);
769
0
  return ret;
770
0
}
771
772
773
/*
774
  check if an optional feature is enabled on our own NTDS DN
775
776
  Note that features can be marked as enabled in more than one
777
  place. For example, the recyclebin feature is marked as enabled both
778
  on the CN=Partitions,CN=Configuration object and on the NTDS DN of
779
  each DC in the forest. It seems likely that it is the job of the KCC
780
  to propagate between the two
781
 */
782
int dsdb_check_optional_feature(struct ldb_module *module, struct GUID op_feature_guid, bool *feature_enabled)
783
0
{
784
0
  TALLOC_CTX *tmp_ctx;
785
0
  struct ldb_context *ldb = ldb_module_get_ctx(module);
786
0
  struct ldb_result *res;
787
0
  struct ldb_dn *search_dn;
788
0
  struct GUID search_guid;
789
0
  static const char * const attrs[] = {"msDS-EnabledFeature", NULL};
790
0
  int ret;
791
0
  unsigned int i;
792
0
  struct ldb_message_element *el;
793
0
  struct ldb_dn *feature_dn;
794
795
0
  tmp_ctx = talloc_new(ldb);
796
797
0
  feature_dn = samdb_ntds_settings_dn(ldb_module_get_ctx(module), tmp_ctx);
798
0
  if (feature_dn == NULL) {
799
0
    talloc_free(tmp_ctx);
800
0
    return ldb_operr(ldb_module_get_ctx(module));
801
0
  }
802
803
0
  *feature_enabled = false;
804
805
0
  ret = dsdb_module_search_dn(module, tmp_ctx, &res, feature_dn, attrs, DSDB_FLAG_NEXT_MODULE, NULL);
806
0
  if (ret != LDB_SUCCESS) {
807
0
    ldb_asprintf_errstring(ldb,
808
0
        "Could not find the feature object - dn: %s\n",
809
0
        ldb_dn_get_linearized(feature_dn));
810
0
    talloc_free(tmp_ctx);
811
0
    return LDB_ERR_NO_SUCH_OBJECT;
812
0
  }
813
0
  if (res->msgs[0]->num_elements > 0) {
814
0
    static const char * const attrs2[] = {"msDS-OptionalFeatureGUID", NULL};
815
816
0
    el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature");
817
818
0
    for (i=0; i<el->num_values; i++) {
819
0
      search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]);
820
821
0
      ret = dsdb_module_search_dn(module, tmp_ctx, &res,
822
0
                search_dn, attrs2, DSDB_FLAG_NEXT_MODULE, NULL);
823
0
      if (ret != LDB_SUCCESS) {
824
0
        ldb_asprintf_errstring(ldb,
825
0
            "Could no find object dn: %s\n",
826
0
            ldb_dn_get_linearized(search_dn));
827
0
        talloc_free(tmp_ctx);
828
0
        return LDB_ERR_OPERATIONS_ERROR;
829
0
      }
830
831
0
      search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID");
832
833
0
      if (GUID_equal(&search_guid, &op_feature_guid)) {
834
0
        *feature_enabled = true;
835
0
        break;
836
0
      }
837
0
    }
838
0
  }
839
0
  talloc_free(tmp_ctx);
840
0
  return LDB_SUCCESS;
841
0
}
842
843
/*
844
  find the NTDS GUID from a computers DN record
845
 */
846
int dsdb_module_find_ntdsguid_for_computer(struct ldb_module *module,
847
             TALLOC_CTX *mem_ctx,
848
             struct ldb_dn *computer_dn,
849
             struct GUID *ntds_guid,
850
             struct ldb_request *parent)
851
0
{
852
0
  int ret;
853
0
  struct ldb_dn *dn;
854
855
0
  *ntds_guid = GUID_zero();
856
857
0
  ret = dsdb_module_reference_dn(module, mem_ctx, computer_dn,
858
0
               "serverReferenceBL", &dn, parent);
859
0
  if (ret != LDB_SUCCESS) {
860
0
    return ret;
861
0
  }
862
863
0
  if (!ldb_dn_add_child_fmt(dn, "CN=NTDS Settings")) {
864
0
    talloc_free(dn);
865
0
    return LDB_ERR_OPERATIONS_ERROR;
866
0
  }
867
868
0
  ret = dsdb_module_guid_by_dn(module, dn, ntds_guid, parent);
869
0
  talloc_free(dn);
870
0
  return ret;
871
0
}
872
873
/*
874
  find a 'reference' DN that points at another object
875
  (eg. serverReference, rIDManagerReference etc)
876
 */
877
int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
878
           const char *attribute, struct ldb_dn **dn, struct ldb_request *parent)
879
0
{
880
0
  const char *attrs[2];
881
0
  struct ldb_result *res;
882
0
  int ret;
883
884
0
  attrs[0] = attribute;
885
0
  attrs[1] = NULL;
886
887
0
  ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs,
888
0
                              DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_EXTENDED_DN, parent);
889
0
  if (ret != LDB_SUCCESS) {
890
0
    *dn = NULL;
891
0
    return ret;
892
0
  }
893
894
0
  *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
895
0
              mem_ctx, res->msgs[0], attribute);
896
0
  if (!*dn) {
897
0
    ldb_reset_err_string(ldb_module_get_ctx(module));
898
0
    talloc_free(res);
899
0
    return LDB_ERR_NO_SUCH_ATTRIBUTE;
900
0
  }
901
902
0
  talloc_free(res);
903
0
  return LDB_SUCCESS;
904
0
}
905
906
/*
907
  find the RID Manager$ DN via the rIDManagerReference attribute in the
908
  base DN
909
 */
910
int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn,
911
             struct ldb_request *parent)
912
0
{
913
0
  return dsdb_module_reference_dn(module, mem_ctx,
914
0
          ldb_get_default_basedn(ldb_module_get_ctx(module)),
915
0
          "rIDManagerReference", dn, parent);
916
0
}
917
918
/*
919
  used to chain to the callers callback
920
 */
921
int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
922
0
{
923
0
  struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
924
925
0
  if (!ares) {
926
0
    return ldb_module_done(up_req, NULL, NULL,
927
0
               LDB_ERR_OPERATIONS_ERROR);
928
0
  }
929
930
0
  if (ares->error != LDB_SUCCESS || ares->type == LDB_REPLY_DONE) {
931
0
    return ldb_module_done(up_req, ares->controls,
932
0
               ares->response, ares->error);
933
0
  }
934
935
  /* Otherwise pass on the callback */
936
0
  switch (ares->type) {
937
0
  case LDB_REPLY_ENTRY:
938
0
    return ldb_module_send_entry(up_req, ares->message,
939
0
               ares->controls);
940
941
0
  case LDB_REPLY_REFERRAL:
942
0
    return ldb_module_send_referral(up_req,
943
0
            ares->referral);
944
0
  default:
945
    /* Can't happen */
946
0
    return LDB_ERR_OPERATIONS_ERROR;
947
0
  }
948
0
}
949
950
/*
951
  load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
952
  object for a partition
953
 */
954
int dsdb_module_load_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
955
           uint64_t *uSN, uint64_t *urgent_uSN, struct ldb_request *parent)
956
0
{
957
0
  struct ldb_context *ldb = ldb_module_get_ctx(module);
958
0
  struct ldb_request *req;
959
0
  int ret;
960
0
  TALLOC_CTX *tmp_ctx = talloc_new(module);
961
0
  struct dsdb_control_current_partition *p_ctrl;
962
0
  struct ldb_result *res;
963
964
0
  res = talloc_zero(tmp_ctx, struct ldb_result);
965
0
  if (!res) {
966
0
    talloc_free(tmp_ctx);
967
0
    return ldb_module_oom(module);
968
0
  }
969
970
0
  ret = ldb_build_search_req(&req, ldb, tmp_ctx,
971
0
           ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
972
0
           LDB_SCOPE_BASE,
973
0
           NULL, NULL,
974
0
           NULL,
975
0
           res, ldb_search_default_callback,
976
0
           parent);
977
0
  LDB_REQ_SET_LOCATION(req);
978
0
  if (ret != LDB_SUCCESS) {
979
0
    talloc_free(tmp_ctx);
980
0
    return ret;
981
0
  }
982
983
0
  p_ctrl = talloc(req, struct dsdb_control_current_partition);
984
0
  if (p_ctrl == NULL) {
985
0
    talloc_free(tmp_ctx);
986
0
    return ldb_module_oom(module);
987
0
  }
988
0
  p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
989
0
  p_ctrl->dn = dn;
990
991
992
0
  ret = ldb_request_add_control(req,
993
0
              DSDB_CONTROL_CURRENT_PARTITION_OID,
994
0
              false, p_ctrl);
995
0
  if (ret != LDB_SUCCESS) {
996
0
    talloc_free(tmp_ctx);
997
0
    return ret;
998
0
  }
999
1000
  /* Run the new request */
1001
0
  ret = ldb_next_request(module, req);
1002
1003
0
  if (ret == LDB_SUCCESS) {
1004
0
    ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1005
0
  }
1006
1007
0
  if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
1008
    /* it hasn't been created yet, which means
1009
       an implicit value of zero */
1010
0
    *uSN = 0;
1011
0
    talloc_free(tmp_ctx);
1012
0
    ldb_reset_err_string(ldb);
1013
0
    return LDB_SUCCESS;
1014
0
  }
1015
1016
0
  if (ret != LDB_SUCCESS) {
1017
0
    talloc_free(tmp_ctx);
1018
0
    return ret;
1019
0
  }
1020
1021
0
  if (res->count != 1) {
1022
0
    *uSN = 0;
1023
0
    if (urgent_uSN) {
1024
0
      *urgent_uSN = 0;
1025
0
    }
1026
0
  } else {
1027
0
    *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
1028
0
    if (urgent_uSN) {
1029
0
      *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
1030
0
    }
1031
0
  }
1032
1033
0
  talloc_free(tmp_ctx);
1034
1035
0
  return LDB_SUCCESS;
1036
0
}
1037
1038
/*
1039
  save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
1040
  partition
1041
 */
1042
int dsdb_module_save_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
1043
           uint64_t uSN, uint64_t urgent_uSN,
1044
           struct ldb_request *parent)
1045
0
{
1046
0
  struct ldb_context *ldb = ldb_module_get_ctx(module);
1047
0
  struct ldb_request *req;
1048
0
  struct ldb_message *msg;
1049
0
  struct dsdb_control_current_partition *p_ctrl;
1050
0
  int ret;
1051
0
  struct ldb_result *res;
1052
1053
0
  msg = ldb_msg_new(module);
1054
0
  if (msg == NULL) {
1055
0
    return ldb_module_oom(module);
1056
0
  }
1057
1058
0
  msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
1059
0
  if (msg->dn == NULL) {
1060
0
    talloc_free(msg);
1061
0
    return ldb_operr(ldb_module_get_ctx(module));
1062
0
  }
1063
1064
0
  res = talloc_zero(msg, struct ldb_result);
1065
0
  if (!res) {
1066
0
    talloc_free(msg);
1067
0
    return ldb_module_oom(module);
1068
0
  }
1069
1070
0
  ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNHighest", uSN);
1071
0
  if (ret != LDB_SUCCESS) {
1072
0
    talloc_free(msg);
1073
0
    return ret;
1074
0
  }
1075
0
  msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
1076
1077
  /* urgent_uSN is optional so may not be stored */
1078
0
  if (urgent_uSN) {
1079
0
    ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNUrgent",
1080
0
             urgent_uSN);
1081
0
    if (ret != LDB_SUCCESS) {
1082
0
      talloc_free(msg);
1083
0
      return ret;
1084
0
    }
1085
0
    msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
1086
0
  }
1087
1088
1089
0
  p_ctrl = talloc(msg, struct dsdb_control_current_partition);
1090
0
  if (p_ctrl == NULL) {
1091
0
    talloc_free(msg);
1092
0
    return ldb_oom(ldb);
1093
0
  }
1094
0
  p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
1095
0
  p_ctrl->dn = dn;
1096
0
  ret = ldb_build_mod_req(&req, ldb, msg,
1097
0
        msg,
1098
0
        NULL,
1099
0
        res,
1100
0
        ldb_modify_default_callback,
1101
0
        parent);
1102
0
  LDB_REQ_SET_LOCATION(req);
1103
0
again:
1104
0
  if (ret != LDB_SUCCESS) {
1105
0
    talloc_free(msg);
1106
0
    return ret;
1107
0
  }
1108
1109
0
  ret = ldb_request_add_control(req,
1110
0
              DSDB_CONTROL_CURRENT_PARTITION_OID,
1111
0
              false, p_ctrl);
1112
0
  if (ret != LDB_SUCCESS) {
1113
0
    talloc_free(msg);
1114
0
    return ret;
1115
0
  }
1116
1117
  /* Run the new request */
1118
0
  ret = ldb_next_request(module, req);
1119
1120
0
  if (ret == LDB_SUCCESS) {
1121
0
    ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1122
0
  }
1123
0
  if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1124
0
    ret = ldb_build_add_req(&req, ldb, msg,
1125
0
          msg,
1126
0
          NULL,
1127
0
          res,
1128
0
          ldb_modify_default_callback,
1129
0
          parent);
1130
0
    LDB_REQ_SET_LOCATION(req);
1131
0
    goto again;
1132
0
  }
1133
1134
0
  talloc_free(msg);
1135
1136
0
  return ret;
1137
0
}
1138
1139
bool dsdb_module_am_system(struct ldb_module *module)
1140
0
{
1141
0
  struct ldb_context *ldb = ldb_module_get_ctx(module);
1142
0
  struct auth_session_info *session_info
1143
0
    = talloc_get_type(
1144
0
      ldb_get_opaque(ldb, DSDB_SESSION_INFO),
1145
0
      struct auth_session_info);
1146
0
  return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
1147
0
}
1148
1149
bool dsdb_module_am_administrator(struct ldb_module *module)
1150
0
{
1151
0
  struct ldb_context *ldb = ldb_module_get_ctx(module);
1152
0
  struct auth_session_info *session_info
1153
0
    = talloc_get_type(
1154
0
      ldb_get_opaque(ldb, DSDB_SESSION_INFO),
1155
0
      struct auth_session_info);
1156
0
  return security_session_user_level(session_info, NULL) == SECURITY_ADMINISTRATOR;
1157
0
}
1158
1159
/*
1160
 * Return ‘true’ if the caller has system access. The ‘acl’ module passes
1161
 * SYSTEM_CONTROL_STRIP_CRITICAL when it wants to strip the critical flag.
1162
 */
1163
bool dsdb_have_system_access(
1164
  struct ldb_module *module,
1165
  struct ldb_request *req,
1166
  const enum system_control_strip_critical strip_critical)
1167
0
{
1168
0
  struct ldb_control *as_system = NULL;
1169
1170
0
  as_system = ldb_request_get_control(req, LDB_CONTROL_AS_SYSTEM_OID);
1171
0
  if (as_system != NULL) {
1172
0
    switch (strip_critical) {
1173
0
    case SYSTEM_CONTROL_KEEP_CRITICAL:
1174
0
      break;
1175
0
    case SYSTEM_CONTROL_STRIP_CRITICAL:
1176
0
      as_system->critical = 0;
1177
0
      break;
1178
0
    }
1179
1180
0
    return true;
1181
0
  }
1182
1183
0
  return dsdb_module_am_system(module);
1184
0
}
1185
1186
/*
1187
  check if the recyclebin is enabled
1188
 */
1189
int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
1190
0
{
1191
0
  struct ldb_context *ldb = ldb_module_get_ctx(module);
1192
0
  struct GUID recyclebin_guid;
1193
0
  int ret;
1194
1195
0
  GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
1196
1197
0
  ret = dsdb_check_optional_feature(module, recyclebin_guid, enabled);
1198
0
  if (ret != LDB_SUCCESS) {
1199
0
    ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
1200
0
    return ret;
1201
0
  }
1202
1203
0
  return LDB_SUCCESS;
1204
0
}
1205
1206
int dsdb_msg_constrainted_update_int32(struct ldb_module *module,
1207
               struct ldb_message *msg,
1208
               const char *attr,
1209
               const int32_t *old_val,
1210
               const int32_t *new_val)
1211
0
{
1212
0
  struct ldb_message_element *el;
1213
0
  int ret;
1214
0
  char *vstring;
1215
1216
0
  if (old_val) {
1217
0
    ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1218
0
    if (ret != LDB_SUCCESS) {
1219
0
      return ret;
1220
0
    }
1221
0
    el->num_values = 1;
1222
0
    el->values = talloc_array(msg, struct ldb_val, el->num_values);
1223
0
    if (!el->values) {
1224
0
      return ldb_module_oom(module);
1225
0
    }
1226
0
    vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
1227
0
    if (!vstring) {
1228
0
      return ldb_module_oom(module);
1229
0
    }
1230
0
    *el->values = data_blob_string_const(vstring);
1231
0
  }
1232
1233
0
  if (new_val) {
1234
0
    ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1235
0
    if (ret != LDB_SUCCESS) {
1236
0
      return ret;
1237
0
    }
1238
0
    el->num_values = 1;
1239
0
    el->values = talloc_array(msg, struct ldb_val, el->num_values);
1240
0
    if (!el->values) {
1241
0
      return ldb_module_oom(module);
1242
0
    }
1243
0
    vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
1244
0
    if (!vstring) {
1245
0
      return ldb_module_oom(module);
1246
0
    }
1247
0
    *el->values = data_blob_string_const(vstring);
1248
0
  }
1249
1250
0
  return LDB_SUCCESS;
1251
0
}
1252
1253
int dsdb_msg_constrainted_update_uint32(struct ldb_module *module,
1254
          struct ldb_message *msg,
1255
          const char *attr,
1256
          const uint32_t *old_val,
1257
          const uint32_t *new_val)
1258
0
{
1259
0
  return dsdb_msg_constrainted_update_int32(module, msg, attr,
1260
0
              (const int32_t *)old_val,
1261
0
              (const int32_t *)new_val);
1262
0
}
1263
1264
int dsdb_msg_constrainted_update_int64(struct ldb_module *module,
1265
               struct ldb_message *msg,
1266
               const char *attr,
1267
               const int64_t *old_val,
1268
               const int64_t *new_val)
1269
0
{
1270
0
  struct ldb_message_element *el;
1271
0
  int ret;
1272
0
  char *vstring;
1273
1274
0
  if (old_val) {
1275
0
    ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1276
0
    if (ret != LDB_SUCCESS) {
1277
0
      return ret;
1278
0
    }
1279
0
    el->num_values = 1;
1280
0
    el->values = talloc_array(msg, struct ldb_val, el->num_values);
1281
0
    if (!el->values) {
1282
0
      return ldb_module_oom(module);
1283
0
    }
1284
0
    vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
1285
0
    if (!vstring) {
1286
0
      return ldb_module_oom(module);
1287
0
    }
1288
0
    *el->values = data_blob_string_const(vstring);
1289
0
  }
1290
1291
0
  if (new_val) {
1292
0
    ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1293
0
    if (ret != LDB_SUCCESS) {
1294
0
      return ret;
1295
0
    }
1296
0
    el->num_values = 1;
1297
0
    el->values = talloc_array(msg, struct ldb_val, el->num_values);
1298
0
    if (!el->values) {
1299
0
      return ldb_module_oom(module);
1300
0
    }
1301
0
    vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
1302
0
    if (!vstring) {
1303
0
      return ldb_module_oom(module);
1304
0
    }
1305
0
    *el->values = data_blob_string_const(vstring);
1306
0
  }
1307
1308
0
  return LDB_SUCCESS;
1309
0
}
1310
1311
int dsdb_msg_constrainted_update_uint64(struct ldb_module *module,
1312
          struct ldb_message *msg,
1313
          const char *attr,
1314
          const uint64_t *old_val,
1315
          const uint64_t *new_val)
1316
0
{
1317
0
  return dsdb_msg_constrainted_update_int64(module, msg, attr,
1318
0
              (const int64_t *)old_val,
1319
0
              (const int64_t *)new_val);
1320
0
}
1321
1322
/*
1323
  update an int32 attribute safely via a constrained delete/add
1324
 */
1325
int dsdb_module_constrainted_update_int32(struct ldb_module *module,
1326
            struct ldb_dn *dn,
1327
            const char *attr,
1328
            const int32_t *old_val,
1329
            const int32_t *new_val,
1330
            struct ldb_request *parent)
1331
0
{
1332
0
  struct ldb_message *msg;
1333
0
  int ret;
1334
1335
0
  msg = ldb_msg_new(module);
1336
0
  if (msg == NULL) {
1337
0
    return ldb_module_oom(module);
1338
0
  }
1339
0
  msg->dn = dn;
1340
1341
0
  ret = dsdb_msg_constrainted_update_int32(module,
1342
0
             msg, attr,
1343
0
             old_val,
1344
0
             new_val);
1345
0
  if (ret != LDB_SUCCESS) {
1346
0
    talloc_free(msg);
1347
0
    return ret;
1348
0
  }
1349
1350
0
  ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1351
0
  talloc_free(msg);
1352
0
  return ret;
1353
0
}
1354
1355
int dsdb_module_constrainted_update_uint32(struct ldb_module *module,
1356
             struct ldb_dn *dn,
1357
             const char *attr,
1358
             const uint32_t *old_val,
1359
             const uint32_t *new_val,
1360
             struct ldb_request *parent)
1361
0
{
1362
0
  return dsdb_module_constrainted_update_int32(module, dn, attr,
1363
0
                 (const int32_t *)old_val,
1364
0
                 (const int32_t *)new_val, parent);
1365
0
}
1366
1367
/*
1368
  update an int64 attribute safely via a constrained delete/add
1369
 */
1370
int dsdb_module_constrainted_update_int64(struct ldb_module *module,
1371
            struct ldb_dn *dn,
1372
            const char *attr,
1373
            const int64_t *old_val,
1374
            const int64_t *new_val,
1375
            struct ldb_request *parent)
1376
0
{
1377
0
  struct ldb_message *msg;
1378
0
  int ret;
1379
1380
0
  msg = ldb_msg_new(module);
1381
0
  if (msg == NULL) {
1382
0
    return ldb_module_oom(module);
1383
0
  }
1384
0
  msg->dn = dn;
1385
1386
0
  ret = dsdb_msg_constrainted_update_int64(module,
1387
0
             msg, attr,
1388
0
             old_val,
1389
0
             new_val);
1390
0
  if (ret != LDB_SUCCESS) {
1391
0
    talloc_free(msg);
1392
0
    return ret;
1393
0
  }
1394
1395
0
  ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1396
0
  talloc_free(msg);
1397
0
  return ret;
1398
0
}
1399
1400
int dsdb_module_constrainted_update_uint64(struct ldb_module *module,
1401
             struct ldb_dn *dn,
1402
             const char *attr,
1403
             const uint64_t *old_val,
1404
             const uint64_t *new_val,
1405
             struct ldb_request *parent)
1406
0
{
1407
0
  return dsdb_module_constrainted_update_int64(module, dn, attr,
1408
0
                 (const int64_t *)old_val,
1409
0
                 (const int64_t *)new_val,
1410
0
                 parent);
1411
0
}
1412
1413
1414
const struct ldb_val *dsdb_module_find_dsheuristics(struct ldb_module *module,
1415
                TALLOC_CTX *mem_ctx, struct ldb_request *parent)
1416
0
{
1417
0
  int ret;
1418
0
  struct ldb_dn *new_dn;
1419
0
  struct ldb_context *ldb = ldb_module_get_ctx(module);
1420
0
  static const char * const attrs[] = { "dSHeuristics", NULL };
1421
0
  struct ldb_result *res;
1422
1423
0
  new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
1424
0
  if (!ldb_dn_add_child_fmt(new_dn,
1425
0
           "CN=Directory Service,CN=Windows NT,CN=Services")) {
1426
0
    talloc_free(new_dn);
1427
0
    return NULL;
1428
0
  }
1429
0
  ret = dsdb_module_search_dn(module, mem_ctx, &res,
1430
0
            new_dn,
1431
0
            attrs,
1432
0
            DSDB_FLAG_NEXT_MODULE,
1433
0
            parent);
1434
0
  if (ret == LDB_SUCCESS && res->count == 1) {
1435
0
    talloc_free(new_dn);
1436
0
    return ldb_msg_find_ldb_val(res->msgs[0],
1437
0
              "dSHeuristics");
1438
0
  }
1439
0
  talloc_free(new_dn);
1440
0
  return NULL;
1441
0
}
1442
1443
bool dsdb_block_anonymous_ops(struct ldb_module *module, struct ldb_request *parent)
1444
0
{
1445
0
  TALLOC_CTX *tmp_ctx = talloc_new(module);
1446
0
  bool result;
1447
0
  const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1448
0
                     tmp_ctx, parent);
1449
0
  if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
1450
0
    result = true;
1451
0
  } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
1452
0
    result = false;
1453
0
  } else {
1454
0
    result = true;
1455
0
  }
1456
1457
0
  talloc_free(tmp_ctx);
1458
0
  return result;
1459
0
}
1460
1461
bool dsdb_user_password_support(struct ldb_module *module,
1462
        TALLOC_CTX *mem_ctx,
1463
        struct ldb_request *parent)
1464
0
{
1465
0
  TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1466
0
  bool result;
1467
0
  const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1468
0
                     tmp_ctx,
1469
0
                     parent);
1470
0
  if (hr_val == NULL || hr_val->length < DS_HR_USER_PASSWORD_SUPPORT) {
1471
0
    result = false;
1472
0
  } else if ((hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '2') ||
1473
0
       (hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '0')) {
1474
0
    result = false;
1475
0
  } else {
1476
0
    result = true;
1477
0
  }
1478
1479
0
  talloc_free(tmp_ctx);
1480
0
  return result;
1481
0
}
1482
1483
bool dsdb_do_list_object(struct ldb_module *module,
1484
       TALLOC_CTX *mem_ctx,
1485
       struct ldb_request *parent)
1486
0
{
1487
0
  TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1488
0
  bool result;
1489
0
  const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1490
0
                     tmp_ctx,
1491
0
                     parent);
1492
0
  if (hr_val == NULL || hr_val->length < DS_HR_DOLISTOBJECT) {
1493
0
    result = false;
1494
0
  } else if (hr_val->data[DS_HR_DOLISTOBJECT -1] == '1') {
1495
0
    result = true;
1496
0
  } else {
1497
0
    result = false;
1498
0
  }
1499
1500
0
  talloc_free(tmp_ctx);
1501
0
  return result;
1502
0
}
1503
1504
bool dsdb_attribute_authz_on_ldap_add(struct ldb_module *module,
1505
              TALLOC_CTX *mem_ctx,
1506
              struct ldb_request *parent)
1507
0
{
1508
0
  TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1509
0
  bool result = false;
1510
0
  const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1511
0
                     tmp_ctx,
1512
0
                     parent);
1513
0
  if (hr_val != NULL && hr_val->length >= DS_HR_ATTR_AUTHZ_ON_LDAP_ADD) {
1514
0
    uint8_t val = hr_val->data[DS_HR_ATTR_AUTHZ_ON_LDAP_ADD - 1];
1515
0
    if (val != '0' && val != '2') {
1516
0
      result = true;
1517
0
    }
1518
0
  }
1519
1520
0
  talloc_free(tmp_ctx);
1521
0
  return result;
1522
0
}
1523
1524
bool dsdb_block_owner_implicit_rights(struct ldb_module *module,
1525
              TALLOC_CTX *mem_ctx,
1526
              struct ldb_request *parent)
1527
0
{
1528
0
  TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1529
0
  bool result = false;
1530
0
  const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1531
0
                     tmp_ctx,
1532
0
                     parent);
1533
0
  if (hr_val != NULL && hr_val->length >= DS_HR_BLOCK_OWNER_IMPLICIT_RIGHTS) {
1534
0
    uint8_t val = hr_val->data[DS_HR_BLOCK_OWNER_IMPLICIT_RIGHTS - 1];
1535
0
    if (val != '0' && val != '2') {
1536
0
      result = true;
1537
0
    }
1538
0
  }
1539
1540
0
  talloc_free(tmp_ctx);
1541
0
  return result;
1542
0
}
1543
1544
/*
1545
  show the chain of requests, useful for debugging async requests
1546
 */
1547
void dsdb_req_chain_debug(struct ldb_request *req, int level)
1548
0
{
1549
0
  char *s = ldb_module_call_chain(req, req);
1550
0
  DEBUG(level, ("%s\n", s));
1551
0
  talloc_free(s);
1552
0
}
1553
1554
/*
1555
 * Get all the values that *might* be added by an ldb message, as a composite
1556
 * ldb element.
1557
 *
1558
 * This is useful when we need to check all the possible values against some
1559
 * criteria.
1560
 *
1561
 * In cases where a modify message mixes multiple ADDs, DELETEs, and REPLACES,
1562
 * the returned element might contain more values than would actually end up
1563
 * in the database if the message was run to its conclusion.
1564
 *
1565
 * If the operation is not LDB_ADD or LDB_MODIFY, an operations error is
1566
 * returned.
1567
 *
1568
 * The returned element might not be new, and should not be modified or freed
1569
 * before the message is finished.
1570
 */
1571
1572
int dsdb_get_expected_new_values(TALLOC_CTX *mem_ctx,
1573
         const struct ldb_message *msg,
1574
         const char *attr_name,
1575
         struct ldb_message_element **el,
1576
         enum ldb_request_type operation)
1577
0
{
1578
0
  unsigned int i;
1579
0
  unsigned int el_count = 0;
1580
0
  unsigned int val_count = 0;
1581
0
  struct ldb_val *v = NULL;
1582
0
  struct ldb_message_element *_el = NULL;
1583
0
  *el = NULL;
1584
1585
0
  if (operation != LDB_ADD && operation != LDB_MODIFY) {
1586
0
    DBG_ERR("inapplicable operation type: %d\n", operation);
1587
0
    return LDB_ERR_OPERATIONS_ERROR;
1588
0
  }
1589
1590
  /* count the adding or replacing elements */
1591
0
  for (i = 0; i < msg->num_elements; i++) {
1592
0
    if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1593
0
      unsigned int tmp;
1594
0
      if ((operation == LDB_MODIFY) &&
1595
0
          (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1596
0
            == LDB_FLAG_MOD_DELETE)) {
1597
0
        continue;
1598
0
      }
1599
0
      el_count++;
1600
0
      tmp = val_count + msg->elements[i].num_values;
1601
0
      if (unlikely(tmp < val_count)) {
1602
0
        DBG_ERR("too many values for one element!\n");
1603
0
        return LDB_ERR_OPERATIONS_ERROR;
1604
0
      }
1605
0
      val_count = tmp;
1606
0
    }
1607
0
  }
1608
0
  if (el_count == 0) {
1609
    /* nothing to see here */
1610
0
    return LDB_SUCCESS;
1611
0
  }
1612
1613
0
  if (el_count == 1 || val_count == 0) {
1614
    /*
1615
     * There is one effective element, which we can return as-is,
1616
     * OR there are only elements with zero values -- any of which
1617
     * will do.
1618
     */
1619
0
    for (i = 0; i < msg->num_elements; i++) {
1620
0
      if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1621
0
        if ((operation == LDB_MODIFY) &&
1622
0
            (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1623
0
             == LDB_FLAG_MOD_DELETE)) {
1624
0
          continue;
1625
0
        }
1626
0
        *el = &msg->elements[i];
1627
0
        return LDB_SUCCESS;
1628
0
      }
1629
0
    }
1630
0
  }
1631
1632
0
  _el = talloc_zero(mem_ctx, struct ldb_message_element);
1633
0
  if (_el == NULL) {
1634
0
    return LDB_ERR_OPERATIONS_ERROR;
1635
0
  }
1636
0
  _el->name = attr_name;
1637
1638
0
  if (val_count == 0) {
1639
    /*
1640
     * Seems unlikely, but sometimes we might be adding zero
1641
     * values in multiple separate elements. The talloc zero has
1642
     * already set the expected values = NULL, num_values = 0.
1643
     */
1644
0
    *el = _el;
1645
0
    return LDB_SUCCESS;
1646
0
  }
1647
1648
0
  _el->values = talloc_array(_el, struct ldb_val, val_count);
1649
0
  if (_el->values == NULL) {
1650
0
    talloc_free(_el);
1651
0
    return LDB_ERR_OPERATIONS_ERROR;
1652
0
  }
1653
0
  _el->num_values = val_count;
1654
1655
0
  v = _el->values;
1656
1657
0
  for (i = 0; i < msg->num_elements; i++) {
1658
0
    if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1659
0
      const struct ldb_message_element *tmp_el = &msg->elements[i];
1660
0
      if ((operation == LDB_MODIFY) &&
1661
0
          (LDB_FLAG_MOD_TYPE(tmp_el->flags)
1662
0
            == LDB_FLAG_MOD_DELETE)) {
1663
0
        continue;
1664
0
      }
1665
0
      if (tmp_el->values == NULL || tmp_el->num_values == 0) {
1666
0
        continue;
1667
0
      }
1668
0
      memcpy(v,
1669
0
             tmp_el->values,
1670
0
             tmp_el->num_values * sizeof(*v));
1671
0
      v += tmp_el->num_values;
1672
0
    }
1673
0
  }
1674
1675
0
  *el = _el;
1676
0
  return LDB_SUCCESS;
1677
0
}
1678
1679
1680
/*
1681
 * Get the value of a single-valued attribute from an ADDed message. 'val' will only live as
1682
 * long as 'msg' and 'original_val' do, and must not be freed.
1683
 */
1684
int dsdb_msg_add_get_single_value(const struct ldb_message *msg,
1685
                                  const char *attr_name,
1686
                                  const struct ldb_val **val)
1687
0
{
1688
0
  const struct ldb_message_element *el = NULL;
1689
1690
  /*
1691
   * The ldb_msg_normalize() call in ldb_request() ensures that
1692
   * there is at most one message element for each
1693
   * attribute. Thus, we don't need a loop to deal with an
1694
   * LDB_ADD.
1695
   */
1696
0
  el = ldb_msg_find_element(msg, attr_name);
1697
0
  if (el == NULL) {
1698
0
    *val = NULL;
1699
0
    return LDB_SUCCESS;
1700
0
  }
1701
0
  if (el->num_values != 1) {
1702
0
    return LDB_ERR_CONSTRAINT_VIOLATION;
1703
0
  }
1704
1705
0
  *val = &el->values[0];
1706
0
  return LDB_SUCCESS;
1707
0
}
1708
1709
/*
1710
 * Get the value of a single-valued attribute after processing a
1711
 * message. 'operation' is either LDB_ADD or LDB_MODIFY. 'val' will only live as
1712
 * long as 'msg' and 'original_val' do, and must not be freed.
1713
 */
1714
int dsdb_msg_get_single_value(const struct ldb_message *msg,
1715
            const char *attr_name,
1716
            const struct ldb_val *original_val,
1717
            const struct ldb_val **val,
1718
            enum ldb_request_type operation)
1719
0
{
1720
0
  unsigned idx;
1721
1722
0
  *val = NULL;
1723
1724
0
  if (operation == LDB_ADD) {
1725
0
    if (original_val != NULL) {
1726
      /* This is an error on the caller's part. */
1727
0
      return LDB_ERR_CONSTRAINT_VIOLATION;
1728
0
    }
1729
0
    return dsdb_msg_add_get_single_value(msg, attr_name, val);
1730
0
  }
1731
1732
0
  SMB_ASSERT(operation == LDB_MODIFY);
1733
1734
0
  *val = original_val;
1735
1736
0
  for (idx = 0; idx < msg->num_elements; ++idx) {
1737
0
    const struct ldb_message_element *el = &msg->elements[idx];
1738
1739
0
    if (ldb_attr_cmp(el->name, attr_name) != 0) {
1740
0
      continue;
1741
0
    }
1742
1743
0
    switch (el->flags & LDB_FLAG_MOD_MASK) {
1744
0
    case LDB_FLAG_MOD_ADD:
1745
0
      if (el->num_values != 1) {
1746
0
        return LDB_ERR_CONSTRAINT_VIOLATION;
1747
0
      }
1748
0
      if (*val != NULL) {
1749
0
        return LDB_ERR_CONSTRAINT_VIOLATION;
1750
0
      }
1751
1752
0
      *val = &el->values[0];
1753
1754
0
      break;
1755
1756
0
    case LDB_FLAG_MOD_REPLACE:
1757
0
      if (el->num_values > 1) {
1758
0
        return LDB_ERR_CONSTRAINT_VIOLATION;
1759
0
      }
1760
1761
0
      *val = el->num_values ? &el->values[0] : NULL;
1762
1763
0
      break;
1764
1765
0
    case LDB_FLAG_MOD_DELETE:
1766
0
      if (el->num_values > 1) {
1767
0
        return LDB_ERR_CONSTRAINT_VIOLATION;
1768
0
      }
1769
1770
      /*
1771
       * If a value was specified for the delete, we don't
1772
       * bother checking it matches the value we currently
1773
       * have. Any mismatch will be caught later (e.g. in
1774
       * ldb_kv_modify_internal).
1775
       */
1776
1777
0
      *val = NULL;
1778
1779
0
      break;
1780
0
    }
1781
0
  }
1782
1783
0
  return LDB_SUCCESS;
1784
0
}
1785
1786
/*
1787
 * This function determines the (last) structural or 88 object class of a passed
1788
 * "objectClass" attribute - per MS-ADTS 3.1.1.1.4 this is the last value.
1789
 * Without schema this does not work and hence NULL is returned.
1790
 */
1791
const struct dsdb_class *dsdb_get_last_structural_class(const struct dsdb_schema *schema,
1792
              const struct ldb_message_element *element)
1793
0
{
1794
0
  const struct dsdb_class *last_class;
1795
1796
0
  if (schema == NULL) {
1797
0
    return NULL;
1798
0
  }
1799
1800
0
  if (element->num_values == 0) {
1801
0
    return NULL;
1802
0
  }
1803
1804
0
  last_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema,
1805
0
                 &element->values[element->num_values-1]);
1806
0
  if (last_class == NULL) {
1807
0
    return NULL;
1808
0
  }
1809
0
  if (last_class->objectClassCategory > 1) {
1810
0
    return NULL;
1811
0
  }
1812
1813
0
  return last_class;
1814
0
}
1815
1816
const struct dsdb_class *dsdb_get_structural_oc_from_msg(const struct dsdb_schema *schema,
1817
               const struct ldb_message *msg)
1818
0
{
1819
0
  struct ldb_message_element *oc_el;
1820
1821
0
  oc_el = ldb_msg_find_element(msg, "objectClass");
1822
0
  if (!oc_el) {
1823
0
    return NULL;
1824
0
  }
1825
1826
0
  return dsdb_get_last_structural_class(schema, oc_el);
1827
0
}
1828
1829
/*
1830
  Get the parent class of an objectclass, or NULL if none exists.
1831
 */
1832
const struct dsdb_class *dsdb_get_parent_class(const struct dsdb_schema *schema,
1833
                 const struct dsdb_class *objectclass)
1834
0
{
1835
0
  if (ldb_attr_cmp(objectclass->lDAPDisplayName, "top") == 0) {
1836
0
    return NULL;
1837
0
  }
1838
1839
0
  if (objectclass->subClassOf == NULL) {
1840
0
    return NULL;
1841
0
  }
1842
1843
0
  return dsdb_class_by_lDAPDisplayName(schema, objectclass->subClassOf);
1844
0
}
1845
1846
/*
1847
  Return true if 'struct_objectclass' is a subclass of 'other_objectclass'. The
1848
  two objectclasses must originate from the same schema, to allow for
1849
  pointer-based identity comparison.
1850
 */
1851
bool dsdb_is_subclass_of(const struct dsdb_schema *schema,
1852
       const struct dsdb_class *struct_objectclass,
1853
       const struct dsdb_class *other_objectclass)
1854
0
{
1855
0
  while (struct_objectclass != NULL) {
1856
    /* Pointer comparison can be used due to the same schema str. */
1857
0
    if (struct_objectclass == other_objectclass) {
1858
0
      return true;
1859
0
    }
1860
1861
0
    struct_objectclass = dsdb_get_parent_class(schema, struct_objectclass);
1862
0
  }
1863
1864
0
  return false;
1865
0
}
1866
1867
/* Fix the DN so that the relative attribute names are in upper case so that the DN:
1868
   cn=Administrator,cn=users,dc=samba,dc=example,dc=com becomes
1869
   CN=Administrator,CN=users,DC=samba,DC=example,DC=com
1870
*/
1871
int dsdb_fix_dn_rdncase(struct ldb_context *ldb, struct ldb_dn *dn)
1872
0
{
1873
0
  int i, ret;
1874
0
  char *upper_rdn_attr;
1875
1876
0
  for (i=0; i < ldb_dn_get_comp_num(dn); i++) {
1877
    /* We need the attribute name in upper case */
1878
0
    upper_rdn_attr = strupper_talloc(dn,
1879
0
             ldb_dn_get_component_name(dn, i));
1880
0
    if (!upper_rdn_attr) {
1881
0
      return ldb_oom(ldb);
1882
0
    }
1883
0
    ret = ldb_dn_set_component(dn, i, upper_rdn_attr,
1884
0
             *ldb_dn_get_component_val(dn, i));
1885
0
    talloc_free(upper_rdn_attr);
1886
0
    if (ret != LDB_SUCCESS) {
1887
0
      return ret;
1888
0
    }
1889
0
  }
1890
0
  return LDB_SUCCESS;
1891
0
}
1892
1893
/**
1894
 * Make most specific objectCategory for the objectClass of passed object
1895
 * NOTE: In this implementation we count that it is called on already
1896
 * verified objectClass attribute value. See objectclass.c thorough
1897
 * implementation for all the magic that involves
1898
 *
1899
 * @param ldb ldb context
1900
 * @param schema cached schema for ldb. We may get it, but it is very time consuming.
1901
 *      Hence leave the responsibility to the caller.
1902
 * @param obj AD object to determine objectCategory for
1903
 * @param mem_ctx Memory context - usually it is obj actually
1904
 * @param pobjectcategory location to store found objectCategory
1905
 *
1906
 * @return LDB_SUCCESS or error including out of memory error
1907
 */
1908
int dsdb_make_object_category(struct ldb_context *ldb, const struct dsdb_schema *schema,
1909
            const struct ldb_message *obj,
1910
            TALLOC_CTX *mem_ctx, const char **pobjectcategory)
1911
0
{
1912
0
  const struct dsdb_class     *objectclass;
1913
0
  struct ldb_message_element    *objectclass_element;
1914
0
  struct dsdb_extended_dn_store_format  *dn_format;
1915
1916
0
  objectclass_element = ldb_msg_find_element(obj, "objectClass");
1917
0
  if (!objectclass_element) {
1918
0
    ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, no objectclass specified!",
1919
0
               ldb_dn_get_linearized(obj->dn));
1920
0
    return LDB_ERR_OBJECT_CLASS_VIOLATION;
1921
0
  }
1922
0
  if (objectclass_element->num_values == 0) {
1923
0
    ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, at least one (structural) objectclass has to be specified!",
1924
0
               ldb_dn_get_linearized(obj->dn));
1925
0
    return LDB_ERR_CONSTRAINT_VIOLATION;
1926
0
  }
1927
1928
  /*
1929
   * Get the new top-most structural object class and check for
1930
   * unrelated structural classes
1931
   */
1932
0
  objectclass = dsdb_get_last_structural_class(schema,
1933
0
                 objectclass_element);
1934
0
  if (objectclass == NULL) {
1935
0
    ldb_asprintf_errstring(ldb,
1936
0
               "Failed to find a structural class for %s",
1937
0
               ldb_dn_get_linearized(obj->dn));
1938
0
    return LDB_ERR_UNWILLING_TO_PERFORM;
1939
0
  }
1940
1941
0
  dn_format = talloc_get_type(ldb_get_opaque(ldb, DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME),
1942
0
            struct dsdb_extended_dn_store_format);
1943
0
  if (dn_format && dn_format->store_extended_dn_in_ldb == false) {
1944
    /* Strip off extended components */
1945
0
    struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb,
1946
0
                 objectclass->defaultObjectCategory);
1947
0
    *pobjectcategory = ldb_dn_alloc_linearized(mem_ctx, dn);
1948
0
    talloc_free(dn);
1949
0
  } else {
1950
0
    *pobjectcategory = talloc_strdup(mem_ctx, objectclass->defaultObjectCategory);
1951
0
  }
1952
1953
0
  if (*pobjectcategory == NULL) {
1954
0
    return ldb_oom(ldb);
1955
0
  }
1956
1957
0
  return LDB_SUCCESS;
1958
0
}
1959
1960
/*
1961
 * Remove all password related attributes.
1962
 */
1963
void dsdb_remove_password_related_attrs(struct ldb_message *msg,
1964
          bool userPassword)
1965
0
{
1966
0
  if (userPassword) {
1967
0
    ldb_msg_remove_attr(msg, "userPassword");
1968
0
  }
1969
0
  ldb_msg_remove_attr(msg, "clearTextPassword");
1970
0
  ldb_msg_remove_attr(msg, "unicodePwd");
1971
0
  ldb_msg_remove_attr(msg, "ntPwdHistory");
1972
0
  ldb_msg_remove_attr(msg, "dBCSPwd");
1973
0
  ldb_msg_remove_attr(msg, "lmPwdHistory");
1974
0
  ldb_msg_remove_attr(msg, "supplementalCredentials");
1975
0
  ldb_msg_remove_attr(msg, "pwdLastSet");
1976
0
}