Coverage Report

Created: 2026-07-25 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source4/dsdb/common/util.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS implementation.
3
   Samba utility functions
4
5
   Copyright (C) Andrew Tridgell 2004
6
   Copyright (C) Volker Lendecke 2004
7
   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006
8
   Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
9
10
   This program is free software; you can redistribute it and/or modify
11
   it under the terms of the GNU General Public License as published by
12
   the Free Software Foundation; either version 3 of the License, or
13
   (at your option) any later version.
14
15
   This program 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
18
   GNU General Public License for more details.
19
20
   You should have received a copy of the GNU General Public License
21
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
*/
23
24
#include "includes.h"
25
#include "ldb.h"
26
#include "ldb_module.h"
27
#include "ldb_errors.h"
28
#include "../lib/util/util_ldb.h"
29
#include "lib/crypto/gmsa.h"
30
#include "dsdb/samdb/samdb.h"
31
#include "librpc/gen_ndr/ndr_security.h"
32
#include "librpc/gen_ndr/ndr_misc.h"
33
#include "../libds/common/flags.h"
34
#include "dsdb/common/proto.h"
35
#include "libcli/ldap/ldap_ndr.h"
36
#include "param/param.h"
37
#include "librpc/gen_ndr/ndr_drsblobs.h"
38
#include "dsdb/common/util.h"
39
#include "dsdb/gmsa/gkdi.h"
40
#include "dsdb/gmsa/util.h"
41
#include "lib/socket/socket.h"
42
#include "librpc/gen_ndr/irpc.h"
43
#include "libds/common/flag_mapping.h"
44
#include "lib/util/access.h"
45
#include "lib/util/data_blob.h"
46
#include "lib/util/debug.h"
47
#include "lib/util/fault.h"
48
#include "lib/util/sys_rw_data.h"
49
#include "libcli/util/ntstatus.h"
50
#include "lib/util/smb_strtox.h"
51
#include "auth/auth.h"
52
53
#undef strncasecmp
54
#undef strcasecmp
55
56
/*
57
 * This is included to allow us to handle DSDB_FLAG_REPLICATED_UPDATE in
58
 * dsdb_request_add_controls()
59
 */
60
#include "dsdb/samdb/ldb_modules/util.h"
61
62
/* default is 30 minutes: -1e7 * 30 * 60 */
63
0
#define DEFAULT_OBSERVATION_WINDOW              (-18000000000)
64
65
/*
66
  search the sam for the specified attributes in a specific domain, filter on
67
  objectSid being in domain_sid.
68
*/
69
int samdb_search_domain(struct ldb_context *sam_ldb,
70
      TALLOC_CTX *mem_ctx,
71
      struct ldb_dn *basedn,
72
      struct ldb_message ***res,
73
      const char * const *attrs,
74
      const struct dom_sid *domain_sid,
75
      const char *format, ...)  _PRINTF_ATTRIBUTE(7,8)
76
0
{
77
0
  va_list ap;
78
0
  int i, count;
79
80
0
  va_start(ap, format);
81
0
  count = gendb_search_v(sam_ldb, mem_ctx, basedn,
82
0
             res, attrs, format, ap);
83
0
  va_end(ap);
84
85
0
  i=0;
86
87
0
  while (i<count) {
88
0
    struct dom_sid *entry_sid;
89
90
0
    entry_sid = samdb_result_dom_sid(mem_ctx, (*res)[i], "objectSid");
91
92
0
    if ((entry_sid == NULL) ||
93
0
        (!dom_sid_in_domain(domain_sid, entry_sid))) {
94
      /* Delete that entry from the result set */
95
0
      (*res)[i] = (*res)[count-1];
96
0
      count -= 1;
97
0
      talloc_free(entry_sid);
98
0
      continue;
99
0
    }
100
0
    talloc_free(entry_sid);
101
0
    i += 1;
102
0
  }
103
104
0
  return count;
105
0
}
106
107
/*
108
  search the sam for a single string attribute in exactly 1 record
109
*/
110
const char *samdb_search_string_v(struct ldb_context *sam_ldb,
111
          TALLOC_CTX *mem_ctx,
112
          struct ldb_dn *basedn,
113
          const char *attr_name,
114
          const char *format, va_list ap) _PRINTF_ATTRIBUTE(5,0)
115
0
{
116
0
  int count;
117
0
  const char *attrs[2] = { NULL, NULL };
118
0
  struct ldb_message **res = NULL;
119
120
0
  attrs[0] = attr_name;
121
122
0
  count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
123
0
  if (count > 1) {
124
0
    DEBUG(1,("samdb: search for %s %s not single valued (count=%d)\n",
125
0
       attr_name, format, count));
126
0
  }
127
0
  if (count != 1) {
128
0
    talloc_free(res);
129
0
    return NULL;
130
0
  }
131
132
0
  return ldb_msg_find_attr_as_string(res[0], attr_name, NULL);
133
0
}
134
135
/*
136
  search the sam for a single string attribute in exactly 1 record
137
*/
138
const char *samdb_search_string(struct ldb_context *sam_ldb,
139
        TALLOC_CTX *mem_ctx,
140
        struct ldb_dn *basedn,
141
        const char *attr_name,
142
        const char *format, ...) _PRINTF_ATTRIBUTE(5,6)
143
0
{
144
0
  va_list ap;
145
0
  const char *str;
146
147
0
  va_start(ap, format);
148
0
  str = samdb_search_string_v(sam_ldb, mem_ctx, basedn, attr_name, format, ap);
149
0
  va_end(ap);
150
151
0
  return str;
152
0
}
153
154
struct ldb_dn *samdb_search_dn(struct ldb_context *sam_ldb,
155
             TALLOC_CTX *mem_ctx,
156
             struct ldb_dn *basedn,
157
             const char *format, ...) _PRINTF_ATTRIBUTE(4,5)
158
0
{
159
0
  va_list ap;
160
0
  struct ldb_dn *ret;
161
0
  struct ldb_message **res = NULL;
162
0
  int count;
163
164
0
  va_start(ap, format);
165
0
  count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, NULL, format, ap);
166
0
  va_end(ap);
167
168
0
  if (count != 1) return NULL;
169
170
0
  ret = talloc_steal(mem_ctx, res[0]->dn);
171
0
  talloc_free(res);
172
173
0
  return ret;
174
0
}
175
176
/*
177
  search the sam for a dom_sid attribute in exactly 1 record
178
*/
179
struct dom_sid *samdb_search_dom_sid(struct ldb_context *sam_ldb,
180
             TALLOC_CTX *mem_ctx,
181
             struct ldb_dn *basedn,
182
             const char *attr_name,
183
             const char *format, ...) _PRINTF_ATTRIBUTE(5,6)
184
0
{
185
0
  va_list ap;
186
0
  int count;
187
0
  struct ldb_message **res;
188
0
  const char *attrs[2] = { NULL, NULL };
189
0
  struct dom_sid *sid;
190
191
0
  attrs[0] = attr_name;
192
193
0
  va_start(ap, format);
194
0
  count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
195
0
  va_end(ap);
196
0
  if (count > 1) {
197
0
    DEBUG(1,("samdb: search for %s %s not single valued (count=%d)\n",
198
0
       attr_name, format, count));
199
0
  }
200
0
  if (count != 1) {
201
0
    talloc_free(res);
202
0
    return NULL;
203
0
  }
204
0
  sid = samdb_result_dom_sid(mem_ctx, res[0], attr_name);
205
0
  talloc_free(res);
206
0
  return sid;
207
0
}
208
209
/*
210
  search the sam for a single integer attribute in exactly 1 record
211
*/
212
unsigned int samdb_search_uint(struct ldb_context *sam_ldb,
213
       TALLOC_CTX *mem_ctx,
214
       unsigned int default_value,
215
       struct ldb_dn *basedn,
216
       const char *attr_name,
217
       const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
218
0
{
219
0
  va_list ap;
220
0
  int count;
221
0
  struct ldb_message **res;
222
0
  const char *attrs[2] = { NULL, NULL };
223
224
0
  attrs[0] = attr_name;
225
226
0
  va_start(ap, format);
227
0
  count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
228
0
  va_end(ap);
229
230
0
  if (count != 1) {
231
0
    return default_value;
232
0
  }
233
234
0
  return ldb_msg_find_attr_as_uint(res[0], attr_name, default_value);
235
0
}
236
237
/*
238
  search the sam for a single signed 64 bit integer attribute in exactly 1 record
239
*/
240
int64_t samdb_search_int64(struct ldb_context *sam_ldb,
241
         TALLOC_CTX *mem_ctx,
242
         int64_t default_value,
243
         struct ldb_dn *basedn,
244
         const char *attr_name,
245
         const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
246
0
{
247
0
  va_list ap;
248
0
  int count;
249
0
  struct ldb_message **res;
250
0
  const char *attrs[2] = { NULL, NULL };
251
252
0
  attrs[0] = attr_name;
253
254
0
  va_start(ap, format);
255
0
  count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
256
0
  va_end(ap);
257
258
0
  if (count != 1) {
259
0
    return default_value;
260
0
  }
261
262
0
  return ldb_msg_find_attr_as_int64(res[0], attr_name, default_value);
263
0
}
264
265
/*
266
  search the sam for multiple records each giving a single string attribute
267
  return the number of matches, or -1 on error
268
*/
269
int samdb_search_string_multiple(struct ldb_context *sam_ldb,
270
         TALLOC_CTX *mem_ctx,
271
         struct ldb_dn *basedn,
272
         const char ***strs,
273
         const char *attr_name,
274
         const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
275
0
{
276
0
  va_list ap;
277
0
  int count, i;
278
0
  const char *attrs[2] = { NULL, NULL };
279
0
  struct ldb_message **res = NULL;
280
281
0
  attrs[0] = attr_name;
282
283
0
  va_start(ap, format);
284
0
  count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
285
0
  va_end(ap);
286
287
0
  if (count <= 0) {
288
0
    return count;
289
0
  }
290
291
  /* make sure its single valued */
292
0
  for (i=0;i<count;i++) {
293
0
    if (res[i]->num_elements != 1) {
294
0
      DEBUG(1,("samdb: search for %s %s not single valued\n",
295
0
         attr_name, format));
296
0
      talloc_free(res);
297
0
      return -1;
298
0
    }
299
0
  }
300
301
0
  *strs = talloc_array(mem_ctx, const char *, count+1);
302
0
  if (! *strs) {
303
0
    talloc_free(res);
304
0
    return -1;
305
0
  }
306
307
0
  for (i=0;i<count;i++) {
308
0
    (*strs)[i] = ldb_msg_find_attr_as_string(res[i], attr_name, NULL);
309
0
  }
310
0
  (*strs)[count] = NULL;
311
312
0
  return count;
313
0
}
314
315
struct ldb_dn *samdb_result_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const struct ldb_message *msg,
316
             const char *attr, struct ldb_dn *default_value)
317
0
{
318
0
  struct ldb_dn *ret_dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, msg, attr);
319
0
  if (!ret_dn) {
320
0
    return default_value;
321
0
  }
322
0
  return ret_dn;
323
0
}
324
325
/*
326
  pull a rid from a objectSid in a result set.
327
*/
328
uint32_t samdb_result_rid_from_sid(TALLOC_CTX *mem_ctx, const struct ldb_message *msg,
329
           const char *attr, uint32_t default_value)
330
0
{
331
0
  struct dom_sid *sid;
332
0
  uint32_t rid;
333
334
0
  sid = samdb_result_dom_sid(mem_ctx, msg, attr);
335
0
  if (sid == NULL) {
336
0
    return default_value;
337
0
  }
338
0
  rid = sid->sub_auths[sid->num_auths-1];
339
0
  talloc_free(sid);
340
0
  return rid;
341
0
}
342
343
/*
344
  pull a dom_sid structure from a objectSid in a result set.
345
*/
346
struct dom_sid *samdb_result_dom_sid(TALLOC_CTX *mem_ctx, const struct ldb_message *msg,
347
             const char *attr)
348
0
{
349
0
  ssize_t ret;
350
0
  const struct ldb_val *v;
351
0
  struct dom_sid *sid;
352
0
  v = ldb_msg_find_ldb_val(msg, attr);
353
0
  if (v == NULL) {
354
0
    return NULL;
355
0
  }
356
0
  sid = talloc(mem_ctx, struct dom_sid);
357
0
  if (sid == NULL) {
358
0
    return NULL;
359
0
  }
360
0
  ret = sid_parse(v->data, v->length, sid);
361
0
  if (ret == -1) {
362
0
    talloc_free(sid);
363
0
    return NULL;
364
0
  }
365
0
  return sid;
366
0
}
367
368
369
/**
370
 * Makes an auth_SidAttr structure from a objectSid in a result set and a
371
 * supplied attribute value.
372
 *
373
 * @param [in] mem_ctx  Talloc memory context on which to allocate the auth_SidAttr.
374
 * @param [in] msg  The message from which to take the objectSid.
375
 * @param [in] attr The attribute name, usually "objectSid".
376
 * @param [in] attrs  SE_GROUP_* flags to go with the SID.
377
 * @returns A pointer to the auth_SidAttr structure, or NULL on failure.
378
 */
379
struct auth_SidAttr *samdb_result_dom_sid_attrs(TALLOC_CTX *mem_ctx, const struct ldb_message *msg,
380
            const char *attr, uint32_t attrs)
381
0
{
382
0
  ssize_t ret;
383
0
  const struct ldb_val *v;
384
0
  struct auth_SidAttr *sid;
385
0
  v = ldb_msg_find_ldb_val(msg, attr);
386
0
  if (v == NULL) {
387
0
    return NULL;
388
0
  }
389
0
  sid = talloc_zero(mem_ctx, struct auth_SidAttr);
390
0
  if (sid == NULL) {
391
0
    return NULL;
392
0
  }
393
0
  ret = sid_parse(v->data, v->length, &sid->sid);
394
0
  if (ret == -1) {
395
0
    talloc_free(sid);
396
0
    return NULL;
397
0
  }
398
0
  sid->attrs = attrs;
399
0
  return sid;
400
0
}
401
402
/*
403
  pull a dom_sid structure from a objectSid in a result set.
404
*/
405
int samdb_result_dom_sid_buf(const struct ldb_message *msg,
406
           const char *attr,
407
           struct dom_sid *sid)
408
0
{
409
0
  ssize_t ret;
410
0
  const struct ldb_val *v = NULL;
411
0
  v = ldb_msg_find_ldb_val(msg, attr);
412
0
  if (v == NULL) {
413
0
    return LDB_ERR_NO_SUCH_ATTRIBUTE;
414
0
  }
415
0
  ret = sid_parse(v->data, v->length, sid);
416
0
  if (ret == -1) {
417
0
    return LDB_ERR_OPERATIONS_ERROR;
418
0
  }
419
0
  return LDB_SUCCESS;
420
0
}
421
422
/*
423
  pull a guid structure from a objectGUID in a result set.
424
*/
425
struct GUID samdb_result_guid(const struct ldb_message *msg, const char *attr)
426
0
{
427
0
  const struct ldb_val *v;
428
0
  struct GUID guid;
429
0
  NTSTATUS status;
430
431
0
  v = ldb_msg_find_ldb_val(msg, attr);
432
0
  if (!v) return GUID_zero();
433
434
0
  status = GUID_from_ndr_blob(v, &guid);
435
0
  if (!NT_STATUS_IS_OK(status)) {
436
0
    return GUID_zero();
437
0
  }
438
439
0
  return guid;
440
0
}
441
442
/*
443
  pull a sid prefix from a objectSid in a result set.
444
  this is used to find the domain sid for a user
445
*/
446
struct dom_sid *samdb_result_sid_prefix(TALLOC_CTX *mem_ctx, const struct ldb_message *msg,
447
          const char *attr)
448
0
{
449
0
  struct dom_sid *sid = samdb_result_dom_sid(mem_ctx, msg, attr);
450
0
  if (!sid || sid->num_auths < 1) return NULL;
451
0
  sid->num_auths--;
452
0
  return sid;
453
0
}
454
455
/*
456
  pull a NTTIME in a result set.
457
*/
458
NTTIME samdb_result_nttime(const struct ldb_message *msg, const char *attr,
459
         NTTIME default_value)
460
0
{
461
0
  return ldb_msg_find_attr_as_uint64(msg, attr, default_value);
462
0
}
463
464
/*
465
 * Windows stores 0 for lastLogoff.
466
 * But when a MS DC return the lastLogoff (as Logoff Time)
467
 * it returns INT64_MAX, not returning this value in this case
468
 * cause windows 2008 and newer version to fail for SMB requests
469
 */
470
NTTIME samdb_result_last_logoff(const struct ldb_message *msg)
471
0
{
472
0
  NTTIME ret = ldb_msg_find_attr_as_uint64(msg, "lastLogoff",0);
473
474
0
  if (ret == 0)
475
0
    ret = INT64_MAX;
476
477
0
  return ret;
478
0
}
479
480
/*
481
 * Windows uses both 0 and 9223372036854775807 (INT64_MAX) to
482
 * indicate an account doesn't expire.
483
 *
484
 * When Windows initially creates an account, it sets
485
 * accountExpires = 9223372036854775807 (INT64_MAX).  However,
486
 * when changing from an account having a specific expiration date to
487
 * that account never expiring, it sets accountExpires = 0.
488
 *
489
 * Consolidate that logic here to allow clearer logic for account expiry in
490
 * the rest of the code.
491
 */
492
NTTIME samdb_result_account_expires(const struct ldb_message *msg)
493
0
{
494
0
  NTTIME ret = ldb_msg_find_attr_as_uint64(msg, "accountExpires",
495
0
             0);
496
497
0
  if (ret == 0)
498
0
    ret = INT64_MAX;
499
500
0
  return ret;
501
0
}
502
503
/*
504
  construct the allow_password_change field from the PwdLastSet attribute and the
505
  domain password settings
506
*/
507
NTTIME samdb_result_allow_password_change(struct ldb_context *sam_ldb,
508
            TALLOC_CTX *mem_ctx,
509
            struct ldb_dn *domain_dn,
510
            const struct ldb_message *msg,
511
            const char *attr)
512
0
{
513
0
  uint64_t attr_time = ldb_msg_find_attr_as_uint64(msg, attr, 0);
514
0
  int64_t minPwdAge;
515
516
0
  if (attr_time == 0) {
517
0
    return 0;
518
0
  }
519
520
0
  minPwdAge = samdb_search_int64(sam_ldb, mem_ctx, 0, domain_dn, "minPwdAge", NULL);
521
522
  /* yes, this is a -= not a += as minPwdAge is stored as the negative
523
     of the number of 100-nano-seconds */
524
0
  attr_time -= minPwdAge;
525
526
0
  return attr_time;
527
0
}
528
529
/*
530
  pull a samr_Password structure from a result set.
531
*/
532
struct samr_Password *samdb_result_hash(TALLOC_CTX *mem_ctx, const struct ldb_message *msg, const char *attr)
533
0
{
534
0
  struct samr_Password *hash = NULL;
535
0
  const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
536
0
  if (val && (val->length >= sizeof(hash->hash))) {
537
0
    hash = talloc(mem_ctx, struct samr_Password);
538
0
    if (hash == NULL) {
539
0
      return NULL;
540
0
    }
541
0
    talloc_keep_secret(hash);
542
0
    memcpy(hash->hash, val->data, sizeof(hash->hash));
543
0
  }
544
0
  return hash;
545
0
}
546
547
/*
548
  pull an array of samr_Password structures from a result set.
549
*/
550
unsigned int samdb_result_hashes(TALLOC_CTX *mem_ctx, const struct ldb_message *msg,
551
         const char *attr, struct samr_Password **hashes)
552
0
{
553
0
  unsigned int count, i;
554
0
  const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
555
556
0
  *hashes = NULL;
557
0
  if (!val) {
558
0
    return 0;
559
0
  }
560
0
  if (val->length % 16 != 0) {
561
    /*
562
     * The length is wrong. Don’t try to read beyond the end of the
563
     * buffer.
564
     */
565
0
    return 0;
566
0
  }
567
0
  count = val->length / 16;
568
0
  if (count == 0) {
569
0
    return 0;
570
0
  }
571
572
0
  *hashes = talloc_array(mem_ctx, struct samr_Password, count);
573
0
  if (! *hashes) {
574
0
    return 0;
575
0
  }
576
0
  talloc_keep_secret(*hashes);
577
578
0
  for (i=0;i<count;i++) {
579
0
    memcpy((*hashes)[i].hash, (i*16)+(char *)val->data, 16);
580
0
  }
581
582
0
  return count;
583
0
}
584
585
NTSTATUS samdb_result_passwords_from_history(TALLOC_CTX *mem_ctx,
586
               struct loadparm_context *lp_ctx,
587
               const struct ldb_message *msg,
588
               unsigned int idx,
589
               const struct samr_Password **lm_pwd,
590
               const struct samr_Password **nt_pwd)
591
0
{
592
0
  struct samr_Password *lmPwdHash, *ntPwdHash;
593
594
0
  if (nt_pwd) {
595
0
    unsigned int num_nt;
596
0
    num_nt = samdb_result_hashes(mem_ctx, msg, "ntPwdHistory", &ntPwdHash);
597
0
    if (num_nt <= idx) {
598
0
      *nt_pwd = NULL;
599
0
    } else {
600
0
      *nt_pwd = &ntPwdHash[idx];
601
0
    }
602
0
  }
603
0
  if (lm_pwd) {
604
    /* Ensure that if we have turned off LM
605
     * authentication, that we never use the LM hash, even
606
     * if we store it */
607
0
    if (lpcfg_lanman_auth(lp_ctx)) {
608
0
      unsigned int num_lm;
609
0
      num_lm = samdb_result_hashes(mem_ctx, msg, "lmPwdHistory", &lmPwdHash);
610
0
      if (num_lm <= idx) {
611
0
        *lm_pwd = NULL;
612
0
      } else {
613
0
        *lm_pwd = &lmPwdHash[idx];
614
0
      }
615
0
    } else {
616
0
      *lm_pwd = NULL;
617
0
    }
618
0
  }
619
0
  return NT_STATUS_OK;
620
0
}
621
622
NTSTATUS samdb_result_passwords_no_lockout(TALLOC_CTX *mem_ctx,
623
             struct loadparm_context *lp_ctx,
624
             const struct ldb_message *msg,
625
             struct samr_Password **nt_pwd)
626
0
{
627
0
  struct samr_Password *ntPwdHash;
628
629
0
  if (nt_pwd) {
630
0
    unsigned int num_nt;
631
0
    num_nt = samdb_result_hashes(mem_ctx, msg, "unicodePwd", &ntPwdHash);
632
0
    if (num_nt == 0) {
633
0
      *nt_pwd = NULL;
634
0
    } else if (num_nt > 1) {
635
0
      return NT_STATUS_INTERNAL_DB_CORRUPTION;
636
0
    } else {
637
0
      *nt_pwd = &ntPwdHash[0];
638
0
    }
639
0
  }
640
0
  return NT_STATUS_OK;
641
0
}
642
643
NTSTATUS samdb_result_passwords(TALLOC_CTX *mem_ctx,
644
        struct loadparm_context *lp_ctx,
645
        const struct ldb_message *msg,
646
        struct samr_Password **nt_pwd)
647
0
{
648
0
  uint32_t acct_flags;
649
650
0
  acct_flags = samdb_result_acct_flags(msg,
651
0
               "msDS-User-Account-Control-Computed");
652
  /* Quit if the account was locked out. */
653
0
  if (acct_flags & ACB_AUTOLOCK) {
654
0
    DEBUG(3,("samdb_result_passwords: Account for user %s was locked out.\n",
655
0
       ldb_dn_get_linearized(msg->dn)));
656
0
    return NT_STATUS_ACCOUNT_LOCKED_OUT;
657
0
  }
658
659
0
  return samdb_result_passwords_no_lockout(mem_ctx, lp_ctx, msg,
660
0
             nt_pwd);
661
0
}
662
663
/*
664
  pull a samr_LogonHours structure from a result set.
665
*/
666
struct samr_LogonHours samdb_result_logon_hours(TALLOC_CTX *mem_ctx, struct ldb_message *msg, const char *attr)
667
0
{
668
0
  struct samr_LogonHours hours = {};
669
0
  size_t units_per_week = 168;
670
0
  const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
671
672
0
  if (val) {
673
0
    units_per_week = val->length * 8;
674
0
  }
675
676
0
  hours.bits = talloc_array(mem_ctx, uint8_t, units_per_week/8);
677
0
  if (!hours.bits) {
678
0
    return hours;
679
0
  }
680
0
  hours.units_per_week = units_per_week;
681
0
  memset(hours.bits, 0xFF, units_per_week/8);
682
0
  if (val) {
683
0
    memcpy(hours.bits, val->data, val->length);
684
0
  }
685
686
0
  return hours;
687
0
}
688
689
/*
690
  pull a set of account_flags from a result set.
691
692
  Naturally, this requires that userAccountControl and
693
  (if not null) the attributes 'attr' be already
694
  included in msg
695
*/
696
uint32_t samdb_result_acct_flags(const struct ldb_message *msg, const char *attr)
697
0
{
698
0
  uint32_t userAccountControl = ldb_msg_find_attr_as_uint(msg, "userAccountControl", 0);
699
0
  uint32_t attr_flags = 0;
700
0
  uint32_t acct_flags = ds_uf2acb(userAccountControl);
701
0
  if (attr) {
702
0
    attr_flags = ldb_msg_find_attr_as_uint(msg, attr, UF_ACCOUNTDISABLE);
703
0
    if (attr_flags == UF_ACCOUNTDISABLE) {
704
0
      DEBUG(0, ("Attribute %s not found, disabling account %s!\n", attr,
705
0
          ldb_dn_get_linearized(msg->dn)));
706
0
    }
707
0
    acct_flags |= ds_uf2acb(attr_flags);
708
0
  }
709
710
0
  return acct_flags;
711
0
}
712
713
NTSTATUS samdb_result_parameters(TALLOC_CTX *mem_ctx,
714
         struct ldb_message *msg,
715
         const char *attr,
716
         struct lsa_BinaryString *s)
717
0
{
718
0
  int i;
719
0
  const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
720
721
0
  ZERO_STRUCTP(s);
722
723
0
  if (!val) {
724
0
    return NT_STATUS_OK;
725
0
  }
726
727
0
  if ((val->length % 2) != 0) {
728
    /*
729
     * If the on-disk data is not even in length, we know
730
     * it is corrupt, and can not be safely pushed.  We
731
     * would either truncate, send an uninitialised
732
     * byte or send a forced zero byte
733
     */
734
0
    return NT_STATUS_INTERNAL_DB_CORRUPTION;
735
0
  }
736
737
0
  s->array = talloc_array(mem_ctx, uint16_t, val->length/2);
738
0
  if (!s->array) {
739
0
    return NT_STATUS_NO_MEMORY;
740
0
  }
741
0
  s->length = s->size = val->length;
742
743
  /* The on-disk format is the 'network' format, being UTF16LE (sort of) */
744
0
  for (i = 0; i < s->length / 2; i++) {
745
0
    s->array[i] = SVAL(val->data, i * 2);
746
0
  }
747
748
0
  return NT_STATUS_OK;
749
0
}
750
751
/* Find an attribute, with a particular value */
752
753
/* The current callers of this function expect a very specific
754
 * behaviour: In particular, objectClass subclass equivalence is not
755
 * wanted.  This means that we should not lookup the schema for the
756
 * comparison function */
757
struct ldb_message_element *samdb_find_attribute(struct ldb_context *ldb,
758
             const struct ldb_message *msg,
759
             const char *name, const char *value)
760
0
{
761
0
  unsigned int i;
762
0
  struct ldb_message_element *el = ldb_msg_find_element(msg, name);
763
764
0
  if (!el) {
765
0
    return NULL;
766
0
  }
767
768
0
  for (i=0;i<el->num_values;i++) {
769
0
    if (ldb_attr_cmp(value, (char *)el->values[i].data) == 0) {
770
0
      return el;
771
0
    }
772
0
  }
773
774
0
  return NULL;
775
0
}
776
777
static int samdb_find_or_add_attribute_ex(struct ldb_context *ldb,
778
            struct ldb_message *msg,
779
            const char *name,
780
            const char *set_value,
781
            unsigned attr_flags,
782
            bool *added)
783
0
{
784
0
  int ret;
785
0
  struct ldb_message_element *el;
786
787
0
  SMB_ASSERT(attr_flags != 0);
788
789
0
        el = ldb_msg_find_element(msg, name);
790
0
  if (el) {
791
0
    if (added != NULL) {
792
0
      *added = false;
793
0
    }
794
795
0
    return LDB_SUCCESS;
796
0
  }
797
798
0
  ret = ldb_msg_add_empty(msg, name,
799
0
        attr_flags,
800
0
        &el);
801
0
  if (ret != LDB_SUCCESS) {
802
0
    return ret;
803
0
  }
804
805
0
  if (set_value != NULL) {
806
0
    ret = ldb_msg_add_string(msg, name, set_value);
807
0
    if (ret != LDB_SUCCESS) {
808
0
      return ret;
809
0
    }
810
0
  }
811
812
0
  if (added != NULL) {
813
0
    *added = true;
814
0
  }
815
0
  return LDB_SUCCESS;
816
0
}
817
818
int samdb_find_or_add_attribute(struct ldb_context *ldb, struct ldb_message *msg, const char *name, const char *set_value)
819
0
{
820
0
  return samdb_find_or_add_attribute_ex(ldb, msg, name, set_value, LDB_FLAG_MOD_ADD, NULL);
821
0
}
822
823
/*
824
  add a dom_sid element to a message
825
*/
826
int samdb_msg_add_dom_sid(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
827
        const char *attr_name, const struct dom_sid *sid)
828
0
{
829
0
  struct ldb_val v;
830
0
  enum ndr_err_code ndr_err;
831
832
0
  ndr_err = ndr_push_struct_blob(&v, mem_ctx,
833
0
               sid,
834
0
               (ndr_push_flags_fn_t)ndr_push_dom_sid);
835
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
836
0
    return ldb_operr(sam_ldb);
837
0
  }
838
0
  return ldb_msg_add_value(msg, attr_name, &v, NULL);
839
0
}
840
841
842
/*
843
  add a delete element operation to a message
844
*/
845
int samdb_msg_add_delete(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
846
       const char *attr_name)
847
0
{
848
  /* we use an empty replace rather than a delete, as it allows for
849
     dsdb_replace() to be used everywhere */
850
0
  return ldb_msg_add_empty(msg, attr_name, LDB_FLAG_MOD_REPLACE, NULL);
851
0
}
852
853
/*
854
  add an add attribute value to a message or enhance an existing attribute
855
  which has the same name and the add flag set.
856
*/
857
int samdb_msg_add_addval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx,
858
       struct ldb_message *msg, const char *attr_name,
859
       const char *value)
860
0
{
861
0
  struct ldb_message_element *el;
862
0
  struct ldb_val val;
863
0
  char *v;
864
0
  unsigned int i;
865
0
  bool found = false;
866
0
  int ret;
867
868
0
  v = talloc_strdup(mem_ctx, value);
869
0
  if (v == NULL) {
870
0
    return ldb_oom(sam_ldb);
871
0
  }
872
873
0
  val.data = (uint8_t *) v;
874
0
  val.length = strlen(v);
875
876
0
  if (val.length == 0) {
877
    /* allow empty strings as non-existent attributes */
878
0
    return LDB_SUCCESS;
879
0
  }
880
881
0
  for (i = 0; i < msg->num_elements; i++) {
882
0
    el = &msg->elements[i];
883
0
    if ((ldb_attr_cmp(el->name, attr_name) == 0) &&
884
0
        (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_ADD)) {
885
0
      found = true;
886
0
      break;
887
0
    }
888
0
  }
889
0
  if (!found) {
890
0
    ret = ldb_msg_add_empty(msg, attr_name, LDB_FLAG_MOD_ADD,
891
0
          &el);
892
0
    if (ret != LDB_SUCCESS) {
893
0
      return ret;
894
0
    }
895
0
  }
896
897
0
  ret = ldb_msg_element_add_value(msg->elements, el, &val);
898
0
  if (ret != LDB_SUCCESS) {
899
0
    return ldb_oom(sam_ldb);
900
0
  }
901
902
0
  return LDB_SUCCESS;
903
0
}
904
905
/*
906
  add a delete attribute value to a message or enhance an existing attribute
907
  which has the same name and the delete flag set.
908
*/
909
int samdb_msg_add_delval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx,
910
       struct ldb_message *msg, const char *attr_name,
911
       const char *value)
912
0
{
913
0
  struct ldb_message_element *el;
914
0
  struct ldb_val val;
915
0
  char *v;
916
0
  unsigned int i;
917
0
  bool found = false;
918
0
  int ret;
919
920
0
  v = talloc_strdup(mem_ctx, value);
921
0
  if (v == NULL) {
922
0
    return ldb_oom(sam_ldb);
923
0
  }
924
925
0
  val.data = (uint8_t *) v;
926
0
  val.length = strlen(v);
927
928
0
  if (val.length == 0) {
929
    /* allow empty strings as non-existent attributes */
930
0
    return LDB_SUCCESS;
931
0
  }
932
933
0
  for (i = 0; i < msg->num_elements; i++) {
934
0
    el = &msg->elements[i];
935
0
    if ((ldb_attr_cmp(el->name, attr_name) == 0) &&
936
0
        (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE)) {
937
0
      found = true;
938
0
      break;
939
0
    }
940
0
  }
941
0
  if (!found) {
942
0
    ret = ldb_msg_add_empty(msg, attr_name, LDB_FLAG_MOD_DELETE,
943
0
          &el);
944
0
    if (ret != LDB_SUCCESS) {
945
0
      return ret;
946
0
    }
947
0
  }
948
949
0
  ret = ldb_msg_element_add_value(msg->elements, el, &val);
950
0
  if (ret != LDB_SUCCESS) {
951
0
    return ldb_oom(sam_ldb);
952
0
  }
953
954
0
  return LDB_SUCCESS;
955
0
}
956
957
/*
958
  add a int element to a message
959
*/
960
int samdb_msg_add_int(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
961
           const char *attr_name, int v)
962
0
{
963
0
  const char *s = talloc_asprintf(mem_ctx, "%d", v);
964
0
  if (s == NULL) {
965
0
    return ldb_oom(sam_ldb);
966
0
  }
967
0
  return ldb_msg_add_string(msg, attr_name, s);
968
0
}
969
970
int samdb_msg_add_int_flags(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
971
          const char *attr_name, int v, int flags)
972
0
{
973
0
  const char *s = talloc_asprintf(mem_ctx, "%d", v);
974
0
  if (s == NULL) {
975
0
    return ldb_oom(sam_ldb);
976
0
  }
977
0
  return ldb_msg_add_string_flags(msg, attr_name, s, flags);
978
0
}
979
980
/*
981
 * Add an unsigned int element to a message
982
 *
983
 * The issue here is that we have not yet first cast to int32_t explicitly,
984
 * before we cast to an signed int to printf() into the %d or cast to a
985
 * int64_t before we then cast to a long long to printf into a %lld.
986
 *
987
 * There are *no* unsigned integers in Active Directory LDAP, even the RID
988
 * allocations and ms-DS-Secondary-KrbTgt-Number are *signed* quantities.
989
 * (See the schema, and the syntax definitions in schema_syntax.c).
990
 *
991
 */
992
int samdb_msg_add_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
993
           const char *attr_name, unsigned int v)
994
0
{
995
0
  return samdb_msg_add_int(sam_ldb, mem_ctx, msg, attr_name, (int)v);
996
0
}
997
998
int samdb_msg_add_uint_flags(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
999
           const char *attr_name, unsigned int v, int flags)
1000
0
{
1001
0
  return samdb_msg_add_int_flags(sam_ldb, mem_ctx, msg, attr_name, (int)v, flags);
1002
0
}
1003
1004
/*
1005
  add a (signed) int64_t element to a message
1006
*/
1007
int samdb_msg_add_int64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
1008
      const char *attr_name, int64_t v)
1009
0
{
1010
0
  const char *s = talloc_asprintf(mem_ctx, "%lld", (long long)v);
1011
0
  if (s == NULL) {
1012
0
    return ldb_oom(sam_ldb);
1013
0
  }
1014
0
  return ldb_msg_add_string(msg, attr_name, s);
1015
0
}
1016
1017
/*
1018
 * Add an unsigned int64_t (uint64_t) element to a message
1019
 *
1020
 * The issue here is that we have not yet first cast to int32_t explicitly,
1021
 * before we cast to an signed int to printf() into the %d or cast to a
1022
 * int64_t before we then cast to a long long to printf into a %lld.
1023
 *
1024
 * There are *no* unsigned integers in Active Directory LDAP, even the RID
1025
 * allocations and ms-DS-Secondary-KrbTgt-Number are *signed* quantities.
1026
 * (See the schema, and the syntax definitions in schema_syntax.c).
1027
 *
1028
 */
1029
int samdb_msg_add_uint64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
1030
      const char *attr_name, uint64_t v)
1031
0
{
1032
0
  return samdb_msg_add_int64(sam_ldb, mem_ctx, msg, attr_name, (int64_t)v);
1033
0
}
1034
1035
/*
1036
  append a int element to a message
1037
*/
1038
int samdb_msg_append_int(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
1039
          const char *attr_name, int v, int flags)
1040
0
{
1041
0
  const char *s = talloc_asprintf(mem_ctx, "%d", v);
1042
0
  if (s == NULL) {
1043
0
    return ldb_oom(sam_ldb);
1044
0
  }
1045
0
  return ldb_msg_append_string(msg, attr_name, s, flags);
1046
0
}
1047
1048
/*
1049
 * Append an unsigned int element to a message
1050
 *
1051
 * The issue here is that we have not yet first cast to int32_t explicitly,
1052
 * before we cast to an signed int to printf() into the %d or cast to a
1053
 * int64_t before we then cast to a long long to printf into a %lld.
1054
 *
1055
 * There are *no* unsigned integers in Active Directory LDAP, even the RID
1056
 * allocations and ms-DS-Secondary-KrbTgt-Number are *signed* quantities.
1057
 * (See the schema, and the syntax definitions in schema_syntax.c).
1058
 *
1059
 */
1060
int samdb_msg_append_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
1061
        const char *attr_name, unsigned int v, int flags)
1062
0
{
1063
0
  return samdb_msg_append_int(sam_ldb, mem_ctx, msg, attr_name, (int)v, flags);
1064
0
}
1065
1066
/*
1067
  append a (signed) int64_t element to a message
1068
*/
1069
int samdb_msg_append_int64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
1070
         const char *attr_name, int64_t v, int flags)
1071
0
{
1072
0
  const char *s = talloc_asprintf(mem_ctx, "%lld", (long long)v);
1073
0
  if (s == NULL) {
1074
0
    return ldb_oom(sam_ldb);
1075
0
  }
1076
0
  return ldb_msg_append_string(msg, attr_name, s, flags);
1077
0
}
1078
1079
/*
1080
 * Append an unsigned int64_t (uint64_t) element to a message
1081
 *
1082
 * The issue here is that we have not yet first cast to int32_t explicitly,
1083
 * before we cast to an signed int to printf() into the %d or cast to a
1084
 * int64_t before we then cast to a long long to printf into a %lld.
1085
 *
1086
 * There are *no* unsigned integers in Active Directory LDAP, even the RID
1087
 * allocations and ms-DS-Secondary-KrbTgt-Number are *signed* quantities.
1088
 * (See the schema, and the syntax definitions in schema_syntax.c).
1089
 *
1090
 */
1091
int samdb_msg_append_uint64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
1092
          const char *attr_name, uint64_t v, int flags)
1093
0
{
1094
0
  return samdb_msg_append_int64(sam_ldb, mem_ctx, msg, attr_name, (int64_t)v, flags);
1095
0
}
1096
1097
/*
1098
  add a samr_Password element to a message
1099
*/
1100
int samdb_msg_add_hash(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
1101
           const char *attr_name, const struct samr_Password *hash)
1102
0
{
1103
0
  struct ldb_val val;
1104
0
  val.data = talloc_memdup(mem_ctx, hash->hash, 16);
1105
0
  if (!val.data) {
1106
0
    return ldb_oom(sam_ldb);
1107
0
  }
1108
0
  val.length = 16;
1109
0
  return ldb_msg_add_value(msg, attr_name, &val, NULL);
1110
0
}
1111
1112
/*
1113
  add a samr_Password array to a message
1114
*/
1115
int samdb_msg_add_hashes(struct ldb_context *ldb,
1116
       TALLOC_CTX *mem_ctx, struct ldb_message *msg,
1117
       const char *attr_name, struct samr_Password *hashes,
1118
       unsigned int count)
1119
0
{
1120
0
  struct ldb_val val;
1121
0
  unsigned int i;
1122
0
  val.data = talloc_array_size(mem_ctx, 16, count);
1123
0
  val.length = count*16;
1124
0
  if (!val.data) {
1125
0
    return ldb_oom(ldb);
1126
0
  }
1127
0
  for (i=0;i<count;i++) {
1128
0
    memcpy(i*16 + (char *)val.data, hashes[i].hash, 16);
1129
0
  }
1130
0
  return ldb_msg_add_value(msg, attr_name, &val, NULL);
1131
0
}
1132
1133
/*
1134
  add a acct_flags element to a message
1135
*/
1136
int samdb_msg_add_acct_flags(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
1137
           const char *attr_name, uint32_t v)
1138
0
{
1139
0
  return samdb_msg_add_uint(sam_ldb, mem_ctx, msg, attr_name, ds_acb2uf(v));
1140
0
}
1141
1142
/*
1143
  add a logon_hours element to a message
1144
*/
1145
int samdb_msg_add_logon_hours(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
1146
            const char *attr_name, struct samr_LogonHours *hours)
1147
0
{
1148
0
  struct ldb_val val;
1149
0
  val.length = hours->units_per_week / 8;
1150
0
  val.data = hours->bits;
1151
0
  return ldb_msg_add_value(msg, attr_name, &val, NULL);
1152
0
}
1153
1154
/*
1155
  add a parameters element to a message
1156
*/
1157
int samdb_msg_add_parameters(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
1158
           const char *attr_name, struct lsa_BinaryString *parameters)
1159
0
{
1160
0
  int i;
1161
0
  struct ldb_val val;
1162
0
  if ((parameters->length % 2) != 0) {
1163
0
    return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1164
0
  }
1165
1166
0
  val.data = talloc_array(mem_ctx, uint8_t, parameters->length);
1167
0
  if (val.data == NULL) {
1168
0
    return LDB_ERR_OPERATIONS_ERROR;
1169
0
  }
1170
0
  val.length = parameters->length;
1171
0
  for (i = 0; i < parameters->length / 2; i++) {
1172
    /*
1173
     * The on-disk format needs to be in the 'network'
1174
     * format, parameters->array is a uint16_t array of
1175
     * length parameters->length / 2
1176
     */
1177
0
    SSVAL(val.data, i * 2, parameters->array[i]);
1178
0
  }
1179
0
  return ldb_msg_add_steal_value(msg, attr_name, &val);
1180
0
}
1181
1182
/*
1183
 * Sets an unsigned int element in a message
1184
 *
1185
 * The issue here is that we have not yet first cast to int32_t explicitly,
1186
 * before we cast to an signed int to printf() into the %d or cast to a
1187
 * int64_t before we then cast to a long long to printf into a %lld.
1188
 *
1189
 * There are *no* unsigned integers in Active Directory LDAP, even the RID
1190
 * allocations and ms-DS-Secondary-KrbTgt-Number are *signed* quantities.
1191
 * (See the schema, and the syntax definitions in schema_syntax.c).
1192
 *
1193
 */
1194
int samdb_msg_set_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx,
1195
           struct ldb_message *msg, const char *attr_name,
1196
           unsigned int v)
1197
0
{
1198
0
  struct ldb_message_element *el;
1199
1200
0
  el = ldb_msg_find_element(msg, attr_name);
1201
0
  if (el) {
1202
0
    el->num_values = 0;
1203
0
  }
1204
0
  return samdb_msg_add_uint(sam_ldb, mem_ctx, msg, attr_name, v);
1205
0
}
1206
1207
/*
1208
 * Handle ldb_request in transaction
1209
 */
1210
int dsdb_autotransaction_request(struct ldb_context *sam_ldb,
1211
         struct ldb_request *req)
1212
0
{
1213
0
  int ret;
1214
1215
0
  ret = ldb_transaction_start(sam_ldb);
1216
0
  if (ret != LDB_SUCCESS) {
1217
0
    return ret;
1218
0
  }
1219
1220
0
  ret = ldb_request(sam_ldb, req);
1221
0
  if (ret == LDB_SUCCESS) {
1222
0
    ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1223
0
  }
1224
1225
0
  if (ret == LDB_SUCCESS) {
1226
0
    return ldb_transaction_commit(sam_ldb);
1227
0
  }
1228
0
  ldb_transaction_cancel(sam_ldb);
1229
1230
0
  return ret;
1231
0
}
1232
1233
/*
1234
  return a default security descriptor
1235
*/
1236
struct security_descriptor *samdb_default_security_descriptor(TALLOC_CTX *mem_ctx)
1237
0
{
1238
0
  struct security_descriptor *sd;
1239
1240
0
  sd = security_descriptor_initialise(mem_ctx);
1241
1242
0
  return sd;
1243
0
}
1244
1245
struct ldb_dn *samdb_aggregate_schema_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx)
1246
0
{
1247
0
  struct ldb_dn *schema_dn = ldb_get_schema_basedn(sam_ctx);
1248
0
  struct ldb_dn *aggregate_dn;
1249
0
  if (!schema_dn) {
1250
0
    return NULL;
1251
0
  }
1252
1253
0
  aggregate_dn = ldb_dn_copy(mem_ctx, schema_dn);
1254
0
  if (!aggregate_dn) {
1255
0
    return NULL;
1256
0
  }
1257
0
  if (!ldb_dn_add_child_fmt(aggregate_dn, "CN=Aggregate")) {
1258
0
    return NULL;
1259
0
  }
1260
0
  return aggregate_dn;
1261
0
}
1262
1263
struct ldb_dn *samdb_partitions_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx)
1264
0
{
1265
0
  struct ldb_dn *new_dn;
1266
1267
0
  new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(sam_ctx));
1268
0
  if ( ! ldb_dn_add_child_fmt(new_dn, "CN=Partitions")) {
1269
0
    talloc_free(new_dn);
1270
0
    return NULL;
1271
0
  }
1272
0
  return new_dn;
1273
0
}
1274
1275
struct ldb_dn *samdb_infrastructure_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx)
1276
0
{
1277
0
       struct ldb_dn *new_dn;
1278
1279
0
       new_dn = ldb_dn_copy(mem_ctx, ldb_get_default_basedn(sam_ctx));
1280
0
       if ( ! ldb_dn_add_child_fmt(new_dn, "CN=Infrastructure")) {
1281
0
               talloc_free(new_dn);
1282
0
               return NULL;
1283
0
       }
1284
0
       return new_dn;
1285
0
}
1286
1287
struct ldb_dn *samdb_system_container_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx)
1288
0
{
1289
0
  struct ldb_dn *new_dn = NULL;
1290
0
  bool ok;
1291
1292
0
  new_dn = ldb_dn_copy(mem_ctx, ldb_get_default_basedn(sam_ctx));
1293
0
  if (new_dn == NULL) {
1294
0
    return NULL;
1295
0
  }
1296
1297
0
  ok = ldb_dn_add_child_fmt(new_dn, "CN=System");
1298
0
  if (!ok) {
1299
0
    TALLOC_FREE(new_dn);
1300
0
    return NULL;
1301
0
  }
1302
1303
0
  return new_dn;
1304
0
}
1305
1306
struct ldb_dn *samdb_sites_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx)
1307
0
{
1308
0
  struct ldb_dn *new_dn;
1309
1310
0
  new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(sam_ctx));
1311
0
  if ( ! ldb_dn_add_child_fmt(new_dn, "CN=Sites")) {
1312
0
    talloc_free(new_dn);
1313
0
    return NULL;
1314
0
  }
1315
0
  return new_dn;
1316
0
}
1317
1318
struct ldb_dn *samdb_extended_rights_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx)
1319
0
{
1320
0
  struct ldb_dn *new_dn;
1321
1322
0
  new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(sam_ctx));
1323
0
  if ( ! ldb_dn_add_child_fmt(new_dn, "CN=Extended-Rights")) {
1324
0
    talloc_free(new_dn);
1325
0
    return NULL;
1326
0
  }
1327
0
  return new_dn;
1328
0
}
1329
1330
struct ldb_dn *samdb_configuration_dn(struct ldb_context *sam_ctx,
1331
              TALLOC_CTX *mem_ctx,
1332
              const char *dn_str)
1333
0
{
1334
0
  struct ldb_dn *config_dn = NULL;
1335
0
  struct ldb_dn *child_dn = NULL;
1336
0
  bool ok;
1337
1338
0
  config_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(sam_ctx));
1339
0
  if (config_dn == NULL) {
1340
0
    return NULL;
1341
0
  }
1342
1343
0
  child_dn = ldb_dn_new(mem_ctx, sam_ctx, dn_str);
1344
0
  if (child_dn == NULL) {
1345
0
    talloc_free(config_dn);
1346
0
    return NULL;
1347
0
  }
1348
1349
0
  ok = ldb_dn_add_child(config_dn, child_dn);
1350
0
  talloc_free(child_dn);
1351
0
  if (!ok) {
1352
0
    talloc_free(config_dn);
1353
0
    return NULL;
1354
0
  }
1355
1356
0
  return config_dn;
1357
0
}
1358
1359
struct ldb_dn *samdb_gkdi_root_key_container_dn(struct ldb_context *sam_ctx,
1360
            TALLOC_CTX *mem_ctx)
1361
0
{
1362
  /*
1363
   * [MS-GKDI] says the root key container is to be found in “CN=Sid Key
1364
   * Service,CN=Services”, but that is not correct.
1365
   */
1366
0
  return samdb_configuration_dn(sam_ctx,
1367
0
              mem_ctx,
1368
0
              "CN=Master Root Keys,"
1369
0
              "CN=Group Key Distribution Service,"
1370
0
              "CN=Services");
1371
0
}
1372
1373
struct ldb_dn *samdb_gkdi_root_key_dn(struct ldb_context *sam_ctx,
1374
              TALLOC_CTX *mem_ctx,
1375
              const struct GUID *root_key_id)
1376
0
{
1377
0
  struct ldb_dn *root_key_dn = NULL;
1378
0
  struct ldb_dn *child_dn = NULL;
1379
0
  struct GUID_txt_buf guid_buf;
1380
0
  char *root_key_id_string = NULL;
1381
0
  bool ok;
1382
1383
0
  root_key_id_string = GUID_buf_string(root_key_id, &guid_buf);
1384
0
  if (root_key_id_string == NULL) {
1385
0
    return NULL;
1386
0
  }
1387
1388
0
  root_key_dn = samdb_gkdi_root_key_container_dn(sam_ctx, mem_ctx);
1389
0
  if (root_key_dn == NULL) {
1390
0
    return NULL;
1391
0
  }
1392
1393
0
  child_dn = ldb_dn_new_fmt(mem_ctx,
1394
0
          sam_ctx,
1395
0
          "CN=%s",
1396
0
          root_key_id_string);
1397
0
  if (child_dn == NULL) {
1398
0
    talloc_free(root_key_dn);
1399
0
    return NULL;
1400
0
  }
1401
1402
0
  ok = ldb_dn_add_child(root_key_dn, child_dn);
1403
0
  talloc_free(child_dn);
1404
0
  if (!ok) {
1405
0
    talloc_free(root_key_dn);
1406
0
    return NULL;
1407
0
  }
1408
1409
0
  return root_key_dn;
1410
0
}
1411
1412
/*
1413
  work out the domain sid for the current open ldb
1414
*/
1415
const struct dom_sid *samdb_domain_sid(struct ldb_context *ldb)
1416
0
{
1417
0
  TALLOC_CTX *tmp_ctx;
1418
0
  const struct dom_sid *domain_sid;
1419
0
  const char *attrs[] = {
1420
0
    "objectSid",
1421
0
    NULL
1422
0
  };
1423
0
  struct ldb_result *res;
1424
0
  int ret;
1425
1426
  /* see if we have a cached copy */
1427
0
  domain_sid = (struct dom_sid *)ldb_get_opaque(ldb, "cache.domain_sid");
1428
0
  if (domain_sid) {
1429
0
    return domain_sid;
1430
0
  }
1431
1432
0
  tmp_ctx = talloc_new(ldb);
1433
0
  if (tmp_ctx == NULL) {
1434
0
    goto failed;
1435
0
  }
1436
1437
0
  ret = ldb_search(ldb, tmp_ctx, &res, ldb_get_default_basedn(ldb), LDB_SCOPE_BASE, attrs, "objectSid=*");
1438
1439
0
  if (ret != LDB_SUCCESS) {
1440
0
    goto failed;
1441
0
  }
1442
1443
0
  if (res->count != 1) {
1444
0
    goto failed;
1445
0
  }
1446
1447
0
  domain_sid = samdb_result_dom_sid(tmp_ctx, res->msgs[0], "objectSid");
1448
0
  if (domain_sid == NULL) {
1449
0
    goto failed;
1450
0
  }
1451
1452
  /* cache the domain_sid in the ldb */
1453
0
  if (ldb_set_opaque(ldb, "cache.domain_sid", discard_const_p(struct dom_sid, domain_sid)) != LDB_SUCCESS) {
1454
0
    goto failed;
1455
0
  }
1456
1457
0
  talloc_steal(ldb, domain_sid);
1458
0
  talloc_free(tmp_ctx);
1459
1460
0
  return domain_sid;
1461
1462
0
failed:
1463
0
  talloc_free(tmp_ctx);
1464
0
  return NULL;
1465
0
}
1466
1467
/*
1468
  get domain sid from cache
1469
*/
1470
const struct dom_sid *samdb_domain_sid_cache_only(struct ldb_context *ldb)
1471
0
{
1472
0
  return (struct dom_sid *)ldb_get_opaque(ldb, "cache.domain_sid");
1473
0
}
1474
1475
bool samdb_set_domain_sid(struct ldb_context *ldb, const struct dom_sid *dom_sid_in)
1476
0
{
1477
0
  TALLOC_CTX *tmp_ctx;
1478
0
  struct dom_sid *dom_sid_new;
1479
0
  struct dom_sid *dom_sid_old;
1480
1481
  /* see if we have a cached copy */
1482
0
  dom_sid_old = talloc_get_type(ldb_get_opaque(ldb,
1483
0
                 "cache.domain_sid"), struct dom_sid);
1484
1485
0
  tmp_ctx = talloc_new(ldb);
1486
0
  if (tmp_ctx == NULL) {
1487
0
    goto failed;
1488
0
  }
1489
1490
0
  dom_sid_new = dom_sid_dup(tmp_ctx, dom_sid_in);
1491
0
  if (!dom_sid_new) {
1492
0
    goto failed;
1493
0
  }
1494
1495
  /* cache the domain_sid in the ldb */
1496
0
  if (ldb_set_opaque(ldb, "cache.domain_sid", dom_sid_new) != LDB_SUCCESS) {
1497
0
    goto failed;
1498
0
  }
1499
1500
0
  talloc_steal(ldb, dom_sid_new);
1501
0
  talloc_free(tmp_ctx);
1502
0
  talloc_free(dom_sid_old);
1503
1504
0
  return true;
1505
1506
0
failed:
1507
0
  DEBUG(1,("Failed to set our own cached domain SID in the ldb!\n"));
1508
0
  talloc_free(tmp_ctx);
1509
0
  return false;
1510
0
}
1511
1512
/*
1513
  work out the domain guid for the current open ldb
1514
*/
1515
const struct GUID *samdb_domain_guid(struct ldb_context *ldb)
1516
0
{
1517
0
  TALLOC_CTX *tmp_ctx = NULL;
1518
0
  struct GUID *domain_guid = NULL;
1519
0
  const char *attrs[] = {
1520
0
    "objectGUID",
1521
0
    NULL
1522
0
  };
1523
0
  struct ldb_result *res = NULL;
1524
0
  int ret;
1525
1526
  /* see if we have a cached copy */
1527
0
  domain_guid = (struct GUID *)ldb_get_opaque(ldb, "cache.domain_guid");
1528
0
  if (domain_guid) {
1529
0
    return domain_guid;
1530
0
  }
1531
1532
0
  tmp_ctx = talloc_new(ldb);
1533
0
  if (tmp_ctx == NULL) {
1534
0
    goto failed;
1535
0
  }
1536
1537
0
  ret = ldb_search(ldb, tmp_ctx, &res, ldb_get_default_basedn(ldb), LDB_SCOPE_BASE, attrs, "objectGUID=*");
1538
0
  if (ret != LDB_SUCCESS) {
1539
0
    goto failed;
1540
0
  }
1541
1542
0
  if (res->count != 1) {
1543
0
    goto failed;
1544
0
  }
1545
1546
0
  domain_guid = talloc(tmp_ctx, struct GUID);
1547
0
  if (domain_guid == NULL) {
1548
0
    goto failed;
1549
0
  }
1550
0
  *domain_guid = samdb_result_guid(res->msgs[0], "objectGUID");
1551
1552
  /* cache the domain_sid in the ldb */
1553
0
  if (ldb_set_opaque(ldb, "cache.domain_guid", domain_guid) != LDB_SUCCESS) {
1554
0
    goto failed;
1555
0
  }
1556
1557
0
  talloc_steal(ldb, domain_guid);
1558
0
  talloc_free(tmp_ctx);
1559
1560
0
  return domain_guid;
1561
1562
0
failed:
1563
0
  talloc_free(tmp_ctx);
1564
0
  return NULL;
1565
0
}
1566
1567
bool samdb_set_ntds_settings_dn(struct ldb_context *ldb, struct ldb_dn *ntds_settings_dn_in)
1568
0
{
1569
0
  TALLOC_CTX *tmp_ctx;
1570
0
  struct ldb_dn *ntds_settings_dn_new;
1571
0
  struct ldb_dn *ntds_settings_dn_old;
1572
1573
  /* see if we have a forced copy from provision */
1574
0
  ntds_settings_dn_old = talloc_get_type(ldb_get_opaque(ldb,
1575
0
                    "forced.ntds_settings_dn"), struct ldb_dn);
1576
1577
0
  tmp_ctx = talloc_new(ldb);
1578
0
  if (tmp_ctx == NULL) {
1579
0
    goto failed;
1580
0
  }
1581
1582
0
  ntds_settings_dn_new = ldb_dn_copy(tmp_ctx, ntds_settings_dn_in);
1583
0
  if (!ntds_settings_dn_new) {
1584
0
    goto failed;
1585
0
  }
1586
1587
  /* set the DN in the ldb to avoid lookups during provision */
1588
0
  if (ldb_set_opaque(ldb, "forced.ntds_settings_dn", ntds_settings_dn_new) != LDB_SUCCESS) {
1589
0
    goto failed;
1590
0
  }
1591
1592
0
  talloc_steal(ldb, ntds_settings_dn_new);
1593
0
  talloc_free(tmp_ctx);
1594
0
  talloc_free(ntds_settings_dn_old);
1595
1596
0
  return true;
1597
1598
0
failed:
1599
0
  DEBUG(1,("Failed to set our NTDS Settings DN in the ldb!\n"));
1600
0
  talloc_free(tmp_ctx);
1601
0
  return false;
1602
0
}
1603
1604
/*
1605
  work out the ntds settings dn for the current open ldb
1606
*/
1607
struct ldb_dn *samdb_ntds_settings_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
1608
0
{
1609
0
  TALLOC_CTX *tmp_ctx;
1610
0
  const char *root_attrs[] = { "dsServiceName", NULL };
1611
0
  int ret;
1612
0
  struct ldb_result *root_res;
1613
0
  struct ldb_dn *settings_dn;
1614
1615
  /* see if we have a cached copy */
1616
0
  settings_dn = (struct ldb_dn *)ldb_get_opaque(ldb, "forced.ntds_settings_dn");
1617
0
  if (settings_dn) {
1618
0
    return ldb_dn_copy(mem_ctx, settings_dn);
1619
0
  }
1620
1621
0
  tmp_ctx = talloc_new(mem_ctx);
1622
0
  if (tmp_ctx == NULL) {
1623
0
    goto failed;
1624
0
  }
1625
1626
0
  ret = ldb_search(ldb, tmp_ctx, &root_res, ldb_dn_new(tmp_ctx, ldb, ""), LDB_SCOPE_BASE, root_attrs, NULL);
1627
0
  if (ret != LDB_SUCCESS) {
1628
0
    DEBUG(1,("Searching for dsServiceName in rootDSE failed: %s\n",
1629
0
       ldb_errstring(ldb)));
1630
0
    goto failed;
1631
0
  }
1632
1633
0
  if (root_res->count != 1) {
1634
0
    goto failed;
1635
0
  }
1636
1637
0
  settings_dn = ldb_msg_find_attr_as_dn(ldb, tmp_ctx, root_res->msgs[0], "dsServiceName");
1638
1639
  /* note that we do not cache the DN here, as that would mean
1640
   * we could not handle server renames at runtime. Only
1641
   * provision sets up forced.ntds_settings_dn */
1642
1643
0
  talloc_steal(mem_ctx, settings_dn);
1644
0
  talloc_free(tmp_ctx);
1645
1646
0
  return settings_dn;
1647
1648
0
failed:
1649
0
  DEBUG(1,("Failed to find our own NTDS Settings DN in the ldb!\n"));
1650
0
  talloc_free(tmp_ctx);
1651
0
  return NULL;
1652
0
}
1653
1654
/*
1655
  work out the ntds settings invocationID/objectGUID for the current open ldb
1656
*/
1657
static const struct GUID *samdb_ntds_GUID(struct ldb_context *ldb,
1658
            const char *attribute,
1659
            const char *cache_name)
1660
0
{
1661
0
  TALLOC_CTX *tmp_ctx;
1662
0
  const char *attrs[] = { attribute, NULL };
1663
0
  int ret;
1664
0
  struct ldb_result *res;
1665
0
  struct GUID *ntds_guid;
1666
0
  struct ldb_dn *ntds_settings_dn = NULL;
1667
0
  const char *errstr = NULL;
1668
1669
  /* see if we have a cached copy */
1670
0
  ntds_guid = (struct GUID *)ldb_get_opaque(ldb, cache_name);
1671
0
  if (ntds_guid != NULL) {
1672
0
    return ntds_guid;
1673
0
  }
1674
1675
0
  tmp_ctx = talloc_new(ldb);
1676
0
  if (tmp_ctx == NULL) {
1677
0
    goto failed;
1678
0
  }
1679
1680
0
  ntds_settings_dn = samdb_ntds_settings_dn(ldb, tmp_ctx);
1681
0
  if (ntds_settings_dn == NULL) {
1682
0
    errstr = "samdb_ntds_settings_dn() returned NULL";
1683
0
    goto failed;
1684
0
  }
1685
1686
0
  ret = ldb_search(ldb, tmp_ctx, &res, ntds_settings_dn,
1687
0
       LDB_SCOPE_BASE, attrs, NULL);
1688
0
  if (ret) {
1689
0
    errstr = ldb_errstring(ldb);
1690
0
    goto failed;
1691
0
  }
1692
1693
0
  if (res->count != 1) {
1694
0
    errstr = "incorrect number of results from base search";
1695
0
    goto failed;
1696
0
  }
1697
1698
0
  ntds_guid = talloc(tmp_ctx, struct GUID);
1699
0
  if (ntds_guid == NULL) {
1700
0
    goto failed;
1701
0
  }
1702
1703
0
  *ntds_guid = samdb_result_guid(res->msgs[0], attribute);
1704
1705
0
  if (GUID_all_zero(ntds_guid)) {
1706
0
    if (ldb_msg_find_ldb_val(res->msgs[0], attribute)) {
1707
0
      errstr = "failed to find the GUID attribute";
1708
0
    } else {
1709
0
      errstr = "failed to parse the GUID";
1710
0
    }
1711
0
    goto failed;
1712
0
  }
1713
1714
  /* cache the domain_sid in the ldb */
1715
0
  if (ldb_set_opaque(ldb, cache_name, ntds_guid) != LDB_SUCCESS) {
1716
0
    errstr = "ldb_set_opaque() failed";
1717
0
    goto failed;
1718
0
  }
1719
1720
0
  talloc_steal(ldb, ntds_guid);
1721
0
  talloc_free(tmp_ctx);
1722
1723
0
  return ntds_guid;
1724
1725
0
failed:
1726
0
  DBG_WARNING("Failed to find our own NTDS Settings %s in the ldb: %s!\n",
1727
0
        attribute, errstr);
1728
0
  talloc_free(tmp_ctx);
1729
0
  return NULL;
1730
0
}
1731
1732
/*
1733
  work out the ntds settings objectGUID for the current open ldb
1734
*/
1735
const struct GUID *samdb_ntds_objectGUID(struct ldb_context *ldb)
1736
0
{
1737
0
  return samdb_ntds_GUID(ldb, "objectGUID", "cache.ntds_guid");
1738
0
}
1739
1740
/*
1741
  work out the ntds settings invocationId for the current open ldb
1742
*/
1743
const struct GUID *samdb_ntds_invocation_id(struct ldb_context *ldb)
1744
0
{
1745
0
  return samdb_ntds_GUID(ldb, "invocationId", "cache.invocation_id");
1746
0
}
1747
1748
static bool samdb_set_ntds_GUID(struct ldb_context *ldb,
1749
        const struct GUID *ntds_guid_in,
1750
        const char *attribute,
1751
        const char *cache_name)
1752
0
{
1753
0
  TALLOC_CTX *tmp_ctx;
1754
0
  struct GUID *ntds_guid_new;
1755
0
  struct GUID *ntds_guid_old;
1756
1757
  /* see if we have a cached copy */
1758
0
  ntds_guid_old = (struct GUID *)ldb_get_opaque(ldb, cache_name);
1759
1760
0
  tmp_ctx = talloc_new(ldb);
1761
0
  if (tmp_ctx == NULL) {
1762
0
    goto failed;
1763
0
  }
1764
1765
0
  ntds_guid_new = talloc(tmp_ctx, struct GUID);
1766
0
  if (!ntds_guid_new) {
1767
0
    goto failed;
1768
0
  }
1769
1770
0
  *ntds_guid_new = *ntds_guid_in;
1771
1772
  /* cache the domain_sid in the ldb */
1773
0
  if (ldb_set_opaque(ldb, cache_name, ntds_guid_new) != LDB_SUCCESS) {
1774
0
    goto failed;
1775
0
  }
1776
1777
0
  talloc_steal(ldb, ntds_guid_new);
1778
0
  talloc_free(tmp_ctx);
1779
0
  talloc_free(ntds_guid_old);
1780
1781
0
  return true;
1782
1783
0
failed:
1784
0
  DBG_WARNING("Failed to set our own cached %s in the ldb!\n",
1785
0
        attribute);
1786
0
  talloc_free(tmp_ctx);
1787
0
  return false;
1788
0
}
1789
1790
bool samdb_set_ntds_objectGUID(struct ldb_context *ldb, const struct GUID *ntds_guid_in)
1791
0
{
1792
0
  return samdb_set_ntds_GUID(ldb,
1793
0
           ntds_guid_in,
1794
0
           "objectGUID",
1795
0
           "cache.ntds_guid");
1796
0
}
1797
1798
bool samdb_set_ntds_invocation_id(struct ldb_context *ldb, const struct GUID *invocation_id_in)
1799
0
{
1800
0
  return samdb_set_ntds_GUID(ldb,
1801
0
           invocation_id_in,
1802
0
           "invocationId",
1803
0
           "cache.invocation_id");
1804
0
}
1805
1806
/*
1807
  work out the server dn for the current open ldb
1808
*/
1809
struct ldb_dn *samdb_server_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
1810
0
{
1811
0
  TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1812
0
  struct ldb_dn *dn;
1813
0
  if (!tmp_ctx) {
1814
0
    return NULL;
1815
0
  }
1816
0
  dn = ldb_dn_get_parent(mem_ctx, samdb_ntds_settings_dn(ldb, tmp_ctx));
1817
0
  talloc_free(tmp_ctx);
1818
0
  return dn;
1819
1820
0
}
1821
1822
/*
1823
  work out the server dn for the current open ldb
1824
*/
1825
struct ldb_dn *samdb_server_site_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
1826
0
{
1827
0
  struct ldb_dn *server_dn;
1828
0
  struct ldb_dn *servers_dn;
1829
0
  struct ldb_dn *server_site_dn;
1830
1831
  /* TODO: there must be a saner way to do this!! */
1832
0
  server_dn = samdb_server_dn(ldb, mem_ctx);
1833
0
  if (!server_dn) return NULL;
1834
1835
0
  servers_dn = ldb_dn_get_parent(mem_ctx, server_dn);
1836
0
  talloc_free(server_dn);
1837
0
  if (!servers_dn) return NULL;
1838
1839
0
  server_site_dn = ldb_dn_get_parent(mem_ctx, servers_dn);
1840
0
  talloc_free(servers_dn);
1841
1842
0
  return server_site_dn;
1843
0
}
1844
1845
/*
1846
  find the site name from a computers DN record
1847
 */
1848
int samdb_find_site_for_computer(struct ldb_context *ldb,
1849
         TALLOC_CTX *mem_ctx, struct ldb_dn *computer_dn,
1850
         const char **site_name)
1851
0
{
1852
0
  int ret;
1853
0
  struct ldb_dn *dn;
1854
0
  const struct ldb_val *rdn_val;
1855
1856
0
  *site_name = NULL;
1857
1858
0
  ret = samdb_reference_dn(ldb, mem_ctx, computer_dn, "serverReferenceBL", &dn);
1859
0
  if (ret != LDB_SUCCESS) {
1860
0
    return ret;
1861
0
  }
1862
1863
0
  if (!ldb_dn_remove_child_components(dn, 2)) {
1864
0
    talloc_free(dn);
1865
0
    return LDB_ERR_INVALID_DN_SYNTAX;
1866
0
  }
1867
1868
0
  rdn_val = ldb_dn_get_rdn_val(dn);
1869
0
  if (rdn_val == NULL) {
1870
0
    return LDB_ERR_OPERATIONS_ERROR;
1871
0
  }
1872
1873
0
  (*site_name) = talloc_strndup(mem_ctx, (const char *)rdn_val->data, rdn_val->length);
1874
0
  talloc_free(dn);
1875
0
  if (!*site_name) {
1876
0
    return LDB_ERR_OPERATIONS_ERROR;
1877
0
  }
1878
0
  return LDB_SUCCESS;
1879
0
}
1880
1881
/*
1882
  find the NTDS GUID from a computers DN record
1883
 */
1884
int samdb_find_ntdsguid_for_computer(struct ldb_context *ldb, struct ldb_dn *computer_dn,
1885
             struct GUID *ntds_guid)
1886
0
{
1887
0
  int ret;
1888
0
  struct ldb_dn *dn;
1889
1890
0
  *ntds_guid = GUID_zero();
1891
1892
0
  ret = samdb_reference_dn(ldb, ldb, computer_dn, "serverReferenceBL", &dn);
1893
0
  if (ret != LDB_SUCCESS) {
1894
0
    return ret;
1895
0
  }
1896
1897
0
  if (!ldb_dn_add_child_fmt(dn, "CN=NTDS Settings")) {
1898
0
    talloc_free(dn);
1899
0
    return LDB_ERR_OPERATIONS_ERROR;
1900
0
  }
1901
1902
0
  ret = dsdb_find_guid_by_dn(ldb, dn, ntds_guid);
1903
0
  talloc_free(dn);
1904
0
  return ret;
1905
0
}
1906
1907
/*
1908
  find a 'reference' DN that points at another object
1909
  (eg. serverReference, rIDManagerReference etc)
1910
 */
1911
int samdb_reference_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
1912
           const char *attribute, struct ldb_dn **dn)
1913
0
{
1914
0
  const char *attrs[2];
1915
0
  struct ldb_result *res;
1916
0
  int ret;
1917
1918
0
  attrs[0] = attribute;
1919
0
  attrs[1] = NULL;
1920
1921
0
  ret = dsdb_search(ldb, mem_ctx, &res, base, LDB_SCOPE_BASE, attrs, DSDB_SEARCH_ONE_ONLY|DSDB_SEARCH_SHOW_EXTENDED_DN, NULL);
1922
0
  if (ret != LDB_SUCCESS) {
1923
0
    ldb_asprintf_errstring(ldb, "Cannot find DN %s to get attribute %s for reference dn: %s",
1924
0
               ldb_dn_get_linearized(base), attribute, ldb_errstring(ldb));
1925
0
    return ret;
1926
0
  }
1927
1928
0
  *dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, res->msgs[0], attribute);
1929
0
  if (!*dn) {
1930
0
    if (!ldb_msg_find_element(res->msgs[0], attribute)) {
1931
0
      ldb_asprintf_errstring(ldb, "Cannot find attribute %s of %s to calculate reference dn", attribute,
1932
0
                 ldb_dn_get_linearized(base));
1933
0
    } else {
1934
0
      ldb_asprintf_errstring(ldb, "Cannot interpret attribute %s of %s as a dn", attribute,
1935
0
                 ldb_dn_get_linearized(base));
1936
0
    }
1937
0
    talloc_free(res);
1938
0
    return LDB_ERR_NO_SUCH_ATTRIBUTE;
1939
0
  }
1940
1941
0
  talloc_free(res);
1942
0
  return LDB_SUCCESS;
1943
0
}
1944
1945
/*
1946
  find if a DN (must have GUID component!) is our ntdsDsa
1947
 */
1948
int samdb_dn_is_our_ntdsa(struct ldb_context *ldb, struct ldb_dn *dn, bool *is_ntdsa)
1949
0
{
1950
0
  NTSTATUS status;
1951
0
  struct GUID dn_guid;
1952
0
  const struct GUID *our_ntds_guid;
1953
0
  status = dsdb_get_extended_dn_guid(dn, &dn_guid, "GUID");
1954
0
  if (!NT_STATUS_IS_OK(status)) {
1955
0
    return LDB_ERR_OPERATIONS_ERROR;
1956
0
  }
1957
1958
0
  our_ntds_guid = samdb_ntds_objectGUID(ldb);
1959
0
  if (!our_ntds_guid) {
1960
0
    DEBUG(0, ("Failed to find our NTDS Settings GUID for comparison with %s - %s\n", ldb_dn_get_linearized(dn), ldb_errstring(ldb)));
1961
0
    return LDB_ERR_OPERATIONS_ERROR;
1962
0
  }
1963
1964
0
  *is_ntdsa = GUID_equal(&dn_guid, our_ntds_guid);
1965
0
  return LDB_SUCCESS;
1966
0
}
1967
1968
/*
1969
  find a 'reference' DN that points at another object and indicate if it is our ntdsDsa
1970
 */
1971
int samdb_reference_dn_is_our_ntdsa(struct ldb_context *ldb, struct ldb_dn *base,
1972
            const char *attribute, bool *is_ntdsa)
1973
0
{
1974
0
  int ret;
1975
0
  struct ldb_dn *referenced_dn;
1976
0
  TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1977
0
  if (tmp_ctx == NULL) {
1978
0
    return LDB_ERR_OPERATIONS_ERROR;
1979
0
  }
1980
0
  ret = samdb_reference_dn(ldb, tmp_ctx, base, attribute, &referenced_dn);
1981
0
  if (ret != LDB_SUCCESS) {
1982
0
    DEBUG(0, ("Failed to find object %s for attribute %s - %s\n", ldb_dn_get_linearized(base), attribute, ldb_errstring(ldb)));
1983
0
    return ret;
1984
0
  }
1985
1986
0
  ret = samdb_dn_is_our_ntdsa(ldb, referenced_dn, is_ntdsa);
1987
1988
0
  talloc_free(tmp_ctx);
1989
0
  return ret;
1990
0
}
1991
1992
/*
1993
  find our machine account via the serverReference attribute in the
1994
  server DN
1995
 */
1996
int samdb_server_reference_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn **dn)
1997
0
{
1998
0
  struct ldb_dn *server_dn;
1999
0
  int ret;
2000
2001
0
  server_dn = samdb_server_dn(ldb, mem_ctx);
2002
0
  if (server_dn == NULL) {
2003
0
    return ldb_error(ldb, LDB_ERR_NO_SUCH_OBJECT, __func__);
2004
0
  }
2005
2006
0
  ret = samdb_reference_dn(ldb, mem_ctx, server_dn, "serverReference", dn);
2007
0
  talloc_free(server_dn);
2008
2009
0
  return ret;
2010
0
}
2011
2012
/*
2013
  find the RID Manager$ DN via the rIDManagerReference attribute in the
2014
  base DN
2015
 */
2016
int samdb_rid_manager_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn **dn)
2017
0
{
2018
0
  return samdb_reference_dn(ldb, mem_ctx, ldb_get_default_basedn(ldb),
2019
0
          "rIDManagerReference", dn);
2020
0
}
2021
2022
/*
2023
  find the RID Set DN via the rIDSetReferences attribute in our
2024
  machine account DN
2025
 */
2026
int samdb_rid_set_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn **dn)
2027
0
{
2028
0
  struct ldb_dn *server_ref_dn = NULL;
2029
0
  int ret;
2030
2031
0
  ret = samdb_server_reference_dn(ldb, mem_ctx, &server_ref_dn);
2032
0
  if (ret != LDB_SUCCESS) {
2033
0
    return ret;
2034
0
  }
2035
0
  ret = samdb_reference_dn(ldb, mem_ctx, server_ref_dn, "rIDSetReferences", dn);
2036
0
  talloc_free(server_ref_dn);
2037
0
  return ret;
2038
0
}
2039
2040
const char *samdb_server_site_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
2041
0
{
2042
0
  const struct ldb_val *val = ldb_dn_get_rdn_val(samdb_server_site_dn(ldb,
2043
0
                      mem_ctx));
2044
2045
0
  if (val == NULL) {
2046
0
    return NULL;
2047
0
  }
2048
2049
0
  return (const char *) val->data;
2050
0
}
2051
2052
/*
2053
 * Finds the client site by using the client's IP address.
2054
 * The "subnet_name" returns the name of the subnet if parameter != NULL
2055
 *
2056
 * Has a Windows-based fallback to provide the only site available, or an empty
2057
 * string if there are multiple sites.
2058
 */
2059
const char *samdb_client_site_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
2060
           const char *ip_address, char **subnet_name,
2061
           bool fallback)
2062
0
{
2063
0
  const char *attrs[] = { "cn", "siteObject", NULL };
2064
0
  struct ldb_dn *sites_container_dn = NULL;
2065
0
  struct ldb_dn *subnets_dn = NULL;
2066
0
  struct ldb_dn *sites_dn = NULL;
2067
0
  struct ldb_result *res = NULL;
2068
0
  const struct ldb_val *val = NULL;
2069
0
  const char *site_name = NULL;
2070
0
  const char *l_subnet_name = NULL;
2071
0
  const char *allow_list[2] = { NULL, NULL };
2072
0
  unsigned int i, count;
2073
0
  int ret;
2074
2075
  /*
2076
   * if we don't have a client ip e.g. ncalrpc
2077
   * the server site is the client site
2078
   */
2079
0
  if (ip_address == NULL) {
2080
0
    return samdb_server_site_name(ldb, mem_ctx);
2081
0
  }
2082
2083
0
  sites_container_dn = samdb_sites_dn(ldb, mem_ctx);
2084
0
  if (sites_container_dn == NULL) {
2085
0
    goto exit;
2086
0
  }
2087
2088
0
  subnets_dn = ldb_dn_copy(mem_ctx, sites_container_dn);
2089
0
  if ( ! ldb_dn_add_child_fmt(subnets_dn, "CN=Subnets")) {
2090
0
    goto exit;
2091
0
  }
2092
2093
0
  ret = ldb_search(ldb, mem_ctx, &res, subnets_dn, LDB_SCOPE_ONELEVEL,
2094
0
       attrs, NULL);
2095
0
  if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2096
0
    count = 0;
2097
0
  } else if (ret != LDB_SUCCESS) {
2098
0
    goto exit;
2099
0
  } else {
2100
0
    count = res->count;
2101
0
  }
2102
2103
0
  for (i = 0; i < count; i++) {
2104
0
    l_subnet_name = ldb_msg_find_attr_as_string(res->msgs[i], "cn",
2105
0
                  NULL);
2106
2107
0
    allow_list[0] = l_subnet_name;
2108
2109
0
    if (allow_access_nolog(NULL, allow_list, "", ip_address)) {
2110
0
      sites_dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx,
2111
0
                 res->msgs[i],
2112
0
                 "siteObject");
2113
0
      if (sites_dn == NULL) {
2114
        /* No reference, maybe another subnet matches */
2115
0
        continue;
2116
0
      }
2117
2118
      /* "val" cannot be NULL here since "sites_dn" != NULL */
2119
0
      val = ldb_dn_get_rdn_val(sites_dn);
2120
0
      site_name = talloc_strdup(mem_ctx,
2121
0
              (const char *) val->data);
2122
2123
0
      TALLOC_FREE(sites_dn);
2124
2125
0
      break;
2126
0
    }
2127
0
  }
2128
2129
0
  if (site_name == NULL && fallback) {
2130
    /* This is the Windows Server fallback rule: when no subnet
2131
     * exists and we have only one site available then use it (it
2132
     * is for sure the same as our server site). If more sites do
2133
     * exist then we don't know which one to use and set the site
2134
     * name to "". */
2135
0
    size_t cnt = 0;
2136
0
    ret = dsdb_domain_count(
2137
0
      ldb,
2138
0
      &cnt,
2139
0
      sites_container_dn,
2140
0
      NULL,
2141
0
      LDB_SCOPE_SUBTREE,
2142
0
      "(objectClass=site)");
2143
0
    if (ret != LDB_SUCCESS) {
2144
0
      goto exit;
2145
0
    }
2146
0
    if (cnt == 1) {
2147
0
      site_name = samdb_server_site_name(ldb, mem_ctx);
2148
0
    } else {
2149
0
      site_name = talloc_strdup(mem_ctx, "");
2150
0
    }
2151
0
    l_subnet_name = NULL;
2152
0
  }
2153
2154
0
  if (subnet_name != NULL) {
2155
0
    *subnet_name = talloc_strdup(mem_ctx, l_subnet_name);
2156
0
  }
2157
2158
0
exit:
2159
0
  TALLOC_FREE(sites_container_dn);
2160
0
  TALLOC_FREE(subnets_dn);
2161
0
  TALLOC_FREE(res);
2162
2163
0
  return site_name;
2164
0
}
2165
2166
/*
2167
  work out if we are the PDC for the domain of the current open ldb
2168
*/
2169
bool samdb_is_pdc(struct ldb_context *ldb)
2170
0
{
2171
0
  int ret;
2172
0
  bool is_pdc;
2173
2174
0
  ret = samdb_reference_dn_is_our_ntdsa(ldb, ldb_get_default_basedn(ldb), "fsmoRoleOwner",
2175
0
                &is_pdc);
2176
0
  if (ret != LDB_SUCCESS) {
2177
0
    DEBUG(1,("Failed to find if we are the PDC for this ldb: Searching for fSMORoleOwner in %s failed: %s\n",
2178
0
       ldb_dn_get_linearized(ldb_get_default_basedn(ldb)),
2179
0
       ldb_errstring(ldb)));
2180
0
    return false;
2181
0
  }
2182
2183
0
  return is_pdc;
2184
0
}
2185
2186
/*
2187
  work out if we are a Global Catalog server for the domain of the current open ldb
2188
*/
2189
bool samdb_is_gc(struct ldb_context *ldb)
2190
0
{
2191
0
  uint32_t options = 0;
2192
0
  if (samdb_ntds_options(ldb, &options) != LDB_SUCCESS) {
2193
0
    return false;
2194
0
  }
2195
0
  return (options & DS_NTDSDSA_OPT_IS_GC) != 0;
2196
0
}
2197
2198
/* Find a domain object in the parents of a particular DN.  */
2199
int samdb_search_for_parent_domain(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn *dn,
2200
           struct ldb_dn **parent_dn, const char **errstring)
2201
0
{
2202
0
  TALLOC_CTX *local_ctx;
2203
0
  struct ldb_dn *sdn = dn;
2204
0
  struct ldb_result *res = NULL;
2205
0
  int ret = LDB_SUCCESS;
2206
0
  const char *attrs[] = { NULL };
2207
2208
0
  local_ctx = talloc_new(mem_ctx);
2209
0
  if (local_ctx == NULL) return ldb_oom(ldb);
2210
2211
0
  while ((sdn = ldb_dn_get_parent(local_ctx, sdn))) {
2212
0
    ret = ldb_search(ldb, local_ctx, &res, sdn, LDB_SCOPE_BASE, attrs,
2213
0
         "(|(objectClass=domain)(objectClass=builtinDomain))");
2214
0
    if (ret == LDB_SUCCESS) {
2215
0
      if (res->count == 1) {
2216
0
        break;
2217
0
      }
2218
0
    } else {
2219
0
      break;
2220
0
    }
2221
0
  }
2222
2223
0
  if (ret != LDB_SUCCESS) {
2224
0
    *errstring = talloc_asprintf(mem_ctx, "Error searching for parent domain of %s, failed searching for %s: %s",
2225
0
               ldb_dn_get_linearized(dn),
2226
0
               ldb_dn_get_linearized(sdn),
2227
0
               ldb_errstring(ldb));
2228
0
    talloc_free(local_ctx);
2229
0
    return ret;
2230
0
  }
2231
  /* should never be true with 'ret=LDB_SUCCESS', here to satisfy clang */
2232
0
  if (res == NULL) {
2233
0
    talloc_free(local_ctx);
2234
0
    return LDB_ERR_OTHER;
2235
0
  }
2236
0
  if (res->count != 1) {
2237
0
    *errstring = talloc_asprintf(mem_ctx, "Invalid dn (%s), not child of a domain object",
2238
0
               ldb_dn_get_linearized(dn));
2239
0
    DEBUG(0,(__location__ ": %s\n", *errstring));
2240
0
    talloc_free(local_ctx);
2241
0
    return LDB_ERR_CONSTRAINT_VIOLATION;
2242
0
  }
2243
2244
0
  *parent_dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
2245
0
  talloc_free(local_ctx);
2246
0
  return ret;
2247
0
}
2248
2249
static void pwd_timeout_debug(struct tevent_context *unused1,
2250
            struct tevent_timer *unused2,
2251
            struct timeval unused3,
2252
            void *unused4)
2253
0
{
2254
0
  DEBUG(0, ("WARNING: check_password_complexity: password script "
2255
0
      "took more than 1 second to run\n"));
2256
0
}
2257
2258
2259
/*
2260
 * Performs checks on a user password (plaintext UNIX format - attribute
2261
 * "password"). The remaining parameters have to be extracted from the domain
2262
 * object in the AD.
2263
 *
2264
 * Result codes from "enum samr_ValidationStatus" (consider "samr.idl")
2265
 */
2266
enum samr_ValidationStatus samdb_check_password(TALLOC_CTX *mem_ctx,
2267
            struct loadparm_context *lp_ctx,
2268
            const char *account_name,
2269
            const char *user_principal_name,
2270
            const char *full_name,
2271
            const DATA_BLOB *utf8_blob,
2272
            const uint32_t pwdProperties,
2273
            const uint32_t minPwdLength)
2274
0
{
2275
0
  const struct loadparm_substitution *lp_sub =
2276
0
    lpcfg_noop_substitution();
2277
0
  char *password_script = NULL;
2278
0
  const char *utf8_pw = (const char *)utf8_blob->data;
2279
2280
  /*
2281
   * This looks strange because it is.
2282
   *
2283
   * The check for the number of characters in the password
2284
   * should clearly not be against the byte length, or else a
2285
   * single UTF8 character would count for more than one.
2286
   *
2287
   * We have chosen to use the number of 16-bit units that the
2288
   * password encodes to as the measure of length.  This is not
2289
   * the same as the number of codepoints, if a password
2290
   * contains a character beyond the Basic Multilingual Plane
2291
   * (above 65535) it will count for more than one "character".
2292
   */
2293
2294
0
  size_t password_characters_roughly = strlen_m(utf8_pw);
2295
2296
  /* checks if the "minPwdLength" property is satisfied */
2297
0
  if (minPwdLength > password_characters_roughly) {
2298
0
    return SAMR_VALIDATION_STATUS_PWD_TOO_SHORT;
2299
0
  }
2300
2301
  /* We might not be asked to check the password complexity */
2302
0
  if (!(pwdProperties & DOMAIN_PASSWORD_COMPLEX)) {
2303
0
    return SAMR_VALIDATION_STATUS_SUCCESS;
2304
0
  }
2305
2306
0
  if (password_characters_roughly == 0) {
2307
0
    return SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH;
2308
0
  }
2309
2310
0
  password_script = lpcfg_check_password_script(lp_ctx, lp_sub, mem_ctx);
2311
0
  if (password_script != NULL && *password_script != '\0') {
2312
0
    int check_ret = 0;
2313
0
    int error = 0;
2314
0
    ssize_t nwritten = 0;
2315
0
    struct tevent_context *event_ctx = NULL;
2316
0
    struct tevent_req *req = NULL;
2317
0
    int cps_stdin = -1;
2318
0
    const char * const cmd[4] = {
2319
0
      "/bin/sh", "-c",
2320
0
      password_script,
2321
0
      NULL
2322
0
    };
2323
2324
0
    event_ctx = tevent_context_init(mem_ctx);
2325
0
    if (event_ctx == NULL) {
2326
0
      TALLOC_FREE(password_script);
2327
0
      return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
2328
0
    }
2329
2330
    /* Gives a warning after 1 second, terminates after 10 */
2331
0
    tevent_add_timer(event_ctx, event_ctx,
2332
0
         tevent_timeval_current_ofs(1, 0),
2333
0
         pwd_timeout_debug, NULL);
2334
2335
0
    check_ret = setenv("SAMBA_CPS_ACCOUNT_NAME", account_name, 1);
2336
0
    if (check_ret != 0) {
2337
0
      TALLOC_FREE(password_script);
2338
0
      TALLOC_FREE(event_ctx);
2339
0
      return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
2340
0
    }
2341
0
    if (user_principal_name != NULL) {
2342
0
      check_ret = setenv("SAMBA_CPS_USER_PRINCIPAL_NAME",
2343
0
             user_principal_name, 1);
2344
0
    } else {
2345
0
      unsetenv("SAMBA_CPS_USER_PRINCIPAL_NAME");
2346
0
    }
2347
0
    if (check_ret != 0) {
2348
0
      TALLOC_FREE(password_script);
2349
0
      TALLOC_FREE(event_ctx);
2350
0
      return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
2351
0
    }
2352
0
    if (full_name != NULL) {
2353
0
      check_ret = setenv("SAMBA_CPS_FULL_NAME", full_name, 1);
2354
0
    } else {
2355
0
      unsetenv("SAMBA_CPS_FULL_NAME");
2356
0
    }
2357
0
    if (check_ret != 0) {
2358
0
      TALLOC_FREE(password_script);
2359
0
      TALLOC_FREE(event_ctx);
2360
0
      return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
2361
0
    }
2362
2363
0
    req = samba_runcmd_send(event_ctx, event_ctx,
2364
0
          tevent_timeval_current_ofs(10, 0),
2365
0
          100, 100, cmd, NULL);
2366
0
    unsetenv("SAMBA_CPS_ACCOUNT_NAME");
2367
0
    unsetenv("SAMBA_CPS_USER_PRINCIPAL_NAME");
2368
0
    unsetenv("SAMBA_CPS_FULL_NAME");
2369
0
    if (req == NULL) {
2370
0
      TALLOC_FREE(password_script);
2371
0
      TALLOC_FREE(event_ctx);
2372
0
      return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
2373
0
    }
2374
2375
0
    cps_stdin = samba_runcmd_export_stdin(req);
2376
2377
0
    nwritten = write_data(
2378
0
      cps_stdin, utf8_blob->data, utf8_blob->length);
2379
0
    if (nwritten == -1) {
2380
0
      close(cps_stdin);
2381
0
      TALLOC_FREE(password_script);
2382
0
      TALLOC_FREE(event_ctx);
2383
0
      return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
2384
0
    }
2385
2386
0
    close(cps_stdin);
2387
2388
0
    if (!tevent_req_poll(req, event_ctx)) {
2389
0
      TALLOC_FREE(password_script);
2390
0
      TALLOC_FREE(event_ctx);
2391
0
      return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
2392
0
    }
2393
2394
0
    check_ret = samba_runcmd_recv(req, &error);
2395
0
    TALLOC_FREE(event_ctx);
2396
2397
0
    if (error == ETIMEDOUT) {
2398
0
      DEBUG(0, ("check_password_complexity: check password script took too long!\n"));
2399
0
      TALLOC_FREE(password_script);
2400
0
      return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
2401
0
    }
2402
0
    DEBUG(5,("check_password_complexity: check password script (%s) "
2403
0
       "returned [%d]\n", password_script, check_ret));
2404
2405
0
    if (check_ret != 0) {
2406
0
      DEBUG(1,("check_password_complexity: "
2407
0
         "check password script said new password is not good "
2408
0
         "enough!\n"));
2409
0
      TALLOC_FREE(password_script);
2410
0
      return SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH;
2411
0
    }
2412
2413
0
    TALLOC_FREE(password_script);
2414
0
    return SAMR_VALIDATION_STATUS_SUCCESS;
2415
0
  }
2416
2417
0
  TALLOC_FREE(password_script);
2418
2419
  /*
2420
   * Here are the standard AD password quality rules, which we
2421
   * run after the script.
2422
   */
2423
2424
0
  if (!check_password_quality(utf8_pw)) {
2425
0
    return SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH;
2426
0
  }
2427
2428
0
  return SAMR_VALIDATION_STATUS_SUCCESS;
2429
0
}
2430
2431
/*
2432
 * Callback for "samdb_set_password" password change
2433
 */
2434
int samdb_set_password_callback(struct ldb_request *req, struct ldb_reply *ares)
2435
0
{
2436
0
  int ret;
2437
2438
0
  if (!ares) {
2439
0
    return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2440
0
  }
2441
2442
0
  if (ares->error != LDB_SUCCESS) {
2443
0
    ret = ares->error;
2444
0
    req->context = talloc_steal(req,
2445
0
              ldb_reply_get_control(ares, DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID));
2446
0
    talloc_free(ares);
2447
0
    return ldb_request_done(req, ret);
2448
0
  }
2449
2450
0
  if (ares->type != LDB_REPLY_DONE) {
2451
0
    talloc_free(ares);
2452
0
    return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2453
0
  }
2454
2455
0
  req->context = talloc_steal(req,
2456
0
            ldb_reply_get_control(ares, DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID));
2457
0
  talloc_free(ares);
2458
0
  return ldb_request_done(req, LDB_SUCCESS);
2459
0
}
2460
2461
static NTSTATUS samdb_set_password_request(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
2462
          struct ldb_dn *user_dn,
2463
          const DATA_BLOB *new_password,
2464
          const struct samr_Password *ntNewHash,
2465
          enum dsdb_password_checked old_password_checked,
2466
          bool permit_interdomain_trust,
2467
          struct ldb_request **req_out)
2468
0
{
2469
0
  struct ldb_message *msg;
2470
0
  struct ldb_message_element *el;
2471
0
  struct ldb_request *req;
2472
0
  int ret;
2473
0
  bool hash_values = false;
2474
2475
0
  *req_out = NULL;
2476
2477
0
#define CHECK_RET(x) \
2478
0
  if (x != LDB_SUCCESS) { \
2479
0
    talloc_free(msg); \
2480
0
    return NT_STATUS_NO_MEMORY; \
2481
0
  }
2482
2483
0
  msg = ldb_msg_new(mem_ctx);
2484
0
  if (msg == NULL) {
2485
0
    return NT_STATUS_NO_MEMORY;
2486
0
  }
2487
0
  msg->dn = user_dn;
2488
0
  if ((new_password != NULL)
2489
0
      && ((ntNewHash == NULL))) {
2490
    /* we have the password as plaintext UTF16 */
2491
0
    CHECK_RET(ldb_msg_add_value(msg, "clearTextPassword",
2492
0
              new_password, NULL));
2493
0
    el = ldb_msg_find_element(msg, "clearTextPassword");
2494
0
    el->flags = LDB_FLAG_MOD_REPLACE;
2495
0
  } else if ((new_password == NULL)
2496
0
      && ((ntNewHash != NULL))) {
2497
    /* we have a password as NT hash */
2498
0
    if (ntNewHash != NULL) {
2499
0
      CHECK_RET(samdb_msg_add_hash(ldb, msg, msg,
2500
0
        "unicodePwd", ntNewHash));
2501
0
      el = ldb_msg_find_element(msg, "unicodePwd");
2502
0
      el->flags = LDB_FLAG_MOD_REPLACE;
2503
0
    }
2504
0
    hash_values = true;
2505
0
  } else {
2506
    /* the password wasn't specified correctly */
2507
0
    talloc_free(msg);
2508
0
    return NT_STATUS_INVALID_PARAMETER;
2509
0
  }
2510
2511
0
#undef CHECK_RET
2512
2513
  /* build modify request */
2514
0
  ret = ldb_build_mod_req(&req, ldb, mem_ctx, msg, NULL, NULL,
2515
0
        samdb_set_password_callback, NULL);
2516
0
        if (ret != LDB_SUCCESS) {
2517
0
    talloc_free(msg);
2518
0
    return NT_STATUS_NO_MEMORY;
2519
0
        }
2520
2521
  /* Tie the lifetime of the message to that of the request. */
2522
0
  talloc_steal(req, msg);
2523
2524
  /* A password change operation */
2525
0
  if (old_password_checked == DSDB_PASSWORD_CHECKED_AND_CORRECT) {
2526
0
    struct dsdb_control_password_change *change;
2527
2528
0
    change = talloc(req, struct dsdb_control_password_change);
2529
0
    if (change == NULL) {
2530
0
      talloc_free(req);
2531
0
      return NT_STATUS_NO_MEMORY;
2532
0
    }
2533
2534
0
    change->old_password_checked = old_password_checked;
2535
2536
0
    ret = ldb_request_add_control(req,
2537
0
                DSDB_CONTROL_PASSWORD_CHANGE_OLD_PW_CHECKED_OID,
2538
0
                true, change);
2539
0
    if (ret != LDB_SUCCESS) {
2540
0
      talloc_free(req);
2541
0
      return NT_STATUS_NO_MEMORY;
2542
0
    }
2543
2544
  /* a KDC-triggered smart card password rollover (ResetSmartCardAccountPassword) */
2545
0
  } else if (old_password_checked == DSDB_PASSWORD_KDC_RESET_SMARTCARD_ACCOUNT_PASSWORD) {
2546
0
    ret = ldb_request_add_control(req,
2547
0
                DSDB_CONTROL_PASSWORD_KDC_RESET_SMARTCARD_ACCOUNT_PASSWORD,
2548
0
                true, NULL);
2549
0
    if (ret != LDB_SUCCESS) {
2550
0
      talloc_free(req);
2551
0
      return NT_STATUS_NO_MEMORY;
2552
0
    }
2553
0
  }
2554
0
  if (hash_values) {
2555
0
    ret = ldb_request_add_control(req,
2556
0
                DSDB_CONTROL_PASSWORD_HASH_VALUES_OID,
2557
0
                true, NULL);
2558
0
    if (ret != LDB_SUCCESS) {
2559
0
      talloc_free(req);
2560
0
      return NT_STATUS_NO_MEMORY;
2561
0
    }
2562
0
  }
2563
0
  if (permit_interdomain_trust) {
2564
0
    ret = ldb_request_add_control(req,
2565
0
                DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
2566
0
                false, NULL);
2567
0
    if (ret != LDB_SUCCESS) {
2568
0
      talloc_free(req);
2569
0
      return NT_STATUS_NO_MEMORY;
2570
0
    }
2571
0
  }
2572
0
  ret = ldb_request_add_control(req,
2573
0
              DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID,
2574
0
              true, NULL);
2575
0
  if (ret != LDB_SUCCESS) {
2576
0
    talloc_free(req);
2577
0
    return NT_STATUS_NO_MEMORY;
2578
0
  }
2579
2580
0
  *req_out = req;
2581
2582
0
  return NT_STATUS_OK;
2583
0
}
2584
2585
/*
2586
 * Sets the user password using plaintext UTF16 (attribute "new_password") or NT
2587
 * (attribute "ntNewHash") hash. Also pass the old LM and/or NT hash (attributes
2588
 * "lmOldHash"/"ntOldHash") if it is a user change or not. The "rejectReason"
2589
 * gives some more information if the change failed.
2590
 *
2591
 * Results: NT_STATUS_OK, NT_STATUS_INVALID_PARAMETER, NT_STATUS_UNSUCCESSFUL,
2592
 *   NT_STATUS_WRONG_PASSWORD, NT_STATUS_PASSWORD_RESTRICTION,
2593
 *   NT_STATUS_ACCESS_DENIED, NT_STATUS_ACCOUNT_LOCKED_OUT, NT_STATUS_NO_MEMORY
2594
 */
2595
static NTSTATUS samdb_set_password_internal(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
2596
          struct ldb_dn *user_dn,
2597
          const DATA_BLOB *new_password,
2598
          const struct samr_Password *ntNewHash,
2599
          enum dsdb_password_checked old_password_checked,
2600
          enum samPwdChangeReason *reject_reason,
2601
          struct samr_DomInfo1 **_dominfo,
2602
          bool permit_interdomain_trust)
2603
0
{
2604
0
  struct ldb_request *req;
2605
0
  struct dsdb_control_password_change_status *pwd_stat = NULL;
2606
0
  int ret;
2607
0
  NTSTATUS status = NT_STATUS_OK;
2608
2609
0
  status = samdb_set_password_request(ldb,
2610
0
              mem_ctx,
2611
0
              user_dn,
2612
0
              new_password,
2613
0
              ntNewHash,
2614
0
              old_password_checked,
2615
0
              permit_interdomain_trust,
2616
0
              &req);
2617
0
  if (!NT_STATUS_IS_OK(status)) {
2618
0
    return status;
2619
0
  }
2620
2621
0
  ret = ldb_request(ldb, req);
2622
0
  if (ret == LDB_SUCCESS) {
2623
0
    ret = ldb_wait(req->handle, LDB_WAIT_ALL);
2624
0
  }
2625
2626
0
  if (req->context != NULL) {
2627
0
    struct ldb_control *control = talloc_get_type_abort(req->context,
2628
0
                    struct ldb_control);
2629
0
    pwd_stat = talloc_get_type_abort(control->data,
2630
0
             struct dsdb_control_password_change_status);
2631
0
    talloc_steal(mem_ctx, pwd_stat);
2632
0
  }
2633
2634
0
  talloc_free(req);
2635
2636
  /* Sets the domain info (if requested) */
2637
0
  if (_dominfo != NULL) {
2638
0
    struct samr_DomInfo1 *dominfo;
2639
2640
0
    dominfo = talloc_zero(mem_ctx, struct samr_DomInfo1);
2641
0
    if (dominfo == NULL) {
2642
0
      return NT_STATUS_NO_MEMORY;
2643
0
    }
2644
2645
0
    if (pwd_stat != NULL) {
2646
0
      dominfo->min_password_length     = pwd_stat->domain_data.minPwdLength;
2647
0
      dominfo->password_properties     = pwd_stat->domain_data.pwdProperties;
2648
0
      dominfo->password_history_length = pwd_stat->domain_data.pwdHistoryLength;
2649
0
      dominfo->max_password_age        = pwd_stat->domain_data.maxPwdAge;
2650
0
      dominfo->min_password_age        = pwd_stat->domain_data.minPwdAge;
2651
0
    }
2652
2653
0
    *_dominfo = dominfo;
2654
0
  }
2655
2656
0
  if (reject_reason != NULL) {
2657
0
    if (pwd_stat != NULL) {
2658
0
      *reject_reason = pwd_stat->reject_reason;
2659
0
    } else {
2660
0
      *reject_reason = SAM_PWD_CHANGE_NO_ERROR;
2661
0
    }
2662
0
  }
2663
2664
0
  if (pwd_stat != NULL) {
2665
0
    talloc_free(pwd_stat);
2666
0
  }
2667
2668
0
  if (ret == LDB_ERR_CONSTRAINT_VIOLATION) {
2669
0
    const char *errmsg = ldb_errstring(ldb);
2670
0
    char *endptr = NULL;
2671
0
    WERROR werr = WERR_GEN_FAILURE;
2672
0
    status = NT_STATUS_UNSUCCESSFUL;
2673
0
    if (errmsg != NULL) {
2674
0
      werr = W_ERROR(strtol(errmsg, &endptr, 16));
2675
0
      DBG_WARNING("%s\n", errmsg);
2676
0
    }
2677
0
    if (endptr != errmsg) {
2678
0
      if (W_ERROR_EQUAL(werr, WERR_INVALID_PASSWORD)) {
2679
0
        status = NT_STATUS_WRONG_PASSWORD;
2680
0
      }
2681
0
      if (W_ERROR_EQUAL(werr, WERR_PASSWORD_RESTRICTION)) {
2682
0
        status = NT_STATUS_PASSWORD_RESTRICTION;
2683
0
      }
2684
0
      if (W_ERROR_EQUAL(werr, WERR_ACCOUNT_LOCKED_OUT)) {
2685
0
        status = NT_STATUS_ACCOUNT_LOCKED_OUT;
2686
0
      }
2687
0
    }
2688
0
  } else if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2689
    /* don't let the caller know if an account doesn't exist */
2690
0
    status = NT_STATUS_WRONG_PASSWORD;
2691
0
  } else if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
2692
0
    status = NT_STATUS_ACCESS_DENIED;
2693
0
  } else if (ret != LDB_SUCCESS) {
2694
0
    DEBUG(1, ("Failed to set password on %s: %s\n",
2695
0
        ldb_dn_get_linearized(user_dn),
2696
0
        ldb_errstring(ldb)));
2697
0
    status = NT_STATUS_UNSUCCESSFUL;
2698
0
  }
2699
2700
0
  return status;
2701
0
}
2702
2703
NTSTATUS samdb_set_password(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
2704
          struct ldb_dn *user_dn,
2705
          const DATA_BLOB *new_password,
2706
          const struct samr_Password *ntNewHash,
2707
          enum dsdb_password_checked old_password_checked,
2708
          enum samPwdChangeReason *reject_reason,
2709
          struct samr_DomInfo1 **_dominfo)
2710
0
{
2711
0
  return samdb_set_password_internal(ldb, mem_ctx,
2712
0
          user_dn,
2713
0
          new_password,
2714
0
          ntNewHash,
2715
0
          old_password_checked,
2716
0
          reject_reason, _dominfo,
2717
0
          false); /* reject trusts */
2718
0
}
2719
2720
/*
2721
 * Sets the user password using plaintext UTF16 (attribute "new_password") or NT
2722
 * (attribute "ntNewHash") hash. Also pass the old LM and/or NT hash (attributes
2723
 * "lmOldHash"/"ntOldHash") if it is a user change or not. The "rejectReason"
2724
 * gives some more information if the change failed.
2725
 *
2726
 * This wrapper function for "samdb_set_password" takes a SID as input rather
2727
 * than a user DN.
2728
 *
2729
 * This call encapsulates a new LDB transaction for changing the password;
2730
 * therefore the user hasn't to start a new one.
2731
 *
2732
 * Results: NT_STATUS_OK, NT_STATUS_INTERNAL_DB_CORRUPTION,
2733
 *   NT_STATUS_INVALID_PARAMETER, NT_STATUS_UNSUCCESSFUL,
2734
 *   NT_STATUS_WRONG_PASSWORD, NT_STATUS_PASSWORD_RESTRICTION,
2735
 *   NT_STATUS_ACCESS_DENIED, NT_STATUS_ACCOUNT_LOCKED_OUT, NT_STATUS_NO_MEMORY
2736
 *   NT_STATUS_TRANSACTION_ABORTED, NT_STATUS_NO_SUCH_USER
2737
 */
2738
NTSTATUS samdb_set_password_sid(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
2739
        const struct dom_sid *user_sid,
2740
        const uint32_t *new_version, /* optional for trusts */
2741
        const DATA_BLOB *new_password,
2742
        const struct samr_Password *ntNewHash,
2743
        enum dsdb_password_checked old_password_checked,
2744
        enum samPwdChangeReason *reject_reason,
2745
        struct samr_DomInfo1 **_dominfo)
2746
0
{
2747
0
  TALLOC_CTX *frame = talloc_stackframe();
2748
0
  NTSTATUS nt_status;
2749
0
  static const char * const attrs[] = {
2750
0
    "userAccountControl",
2751
0
    "sAMAccountName",
2752
0
    NULL
2753
0
  };
2754
0
  struct ldb_message *user_msg = NULL;
2755
0
  int ret;
2756
0
  uint32_t uac = 0;
2757
2758
0
  ret = ldb_transaction_start(ldb);
2759
0
  if (ret != LDB_SUCCESS) {
2760
0
    DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(ldb)));
2761
0
    TALLOC_FREE(frame);
2762
0
    return NT_STATUS_TRANSACTION_ABORTED;
2763
0
  }
2764
2765
0
  ret = dsdb_search_one(ldb, frame, &user_msg, ldb_get_default_basedn(ldb),
2766
0
            LDB_SCOPE_SUBTREE, attrs, 0,
2767
0
            "(&(objectSid=%s)(objectClass=user))",
2768
0
            ldap_encode_ndr_dom_sid(frame, user_sid));
2769
0
  if (ret != LDB_SUCCESS) {
2770
0
    ldb_transaction_cancel(ldb);
2771
0
    DEBUG(3, ("samdb_set_password_sid: SID[%s] not found in samdb %s - %s, "
2772
0
        "returning NO_SUCH_USER\n",
2773
0
        dom_sid_string(frame, user_sid),
2774
0
        ldb_strerror(ret), ldb_errstring(ldb)));
2775
0
    TALLOC_FREE(frame);
2776
0
    return NT_STATUS_NO_SUCH_USER;
2777
0
  }
2778
2779
0
  uac = ldb_msg_find_attr_as_uint(user_msg, "userAccountControl", 0);
2780
0
  if (!(uac & UF_ACCOUNT_TYPE_MASK)) {
2781
0
    ldb_transaction_cancel(ldb);
2782
0
    DEBUG(1, ("samdb_set_password_sid: invalid "
2783
0
        "userAccountControl[0x%08X] for SID[%s] DN[%s], "
2784
0
        "returning NO_SUCH_USER\n",
2785
0
        (unsigned)uac, dom_sid_string(frame, user_sid),
2786
0
        ldb_dn_get_linearized(user_msg->dn)));
2787
0
    TALLOC_FREE(frame);
2788
0
    return NT_STATUS_NO_SUCH_USER;
2789
0
  }
2790
2791
0
  if (uac & UF_INTERDOMAIN_TRUST_ACCOUNT) {
2792
0
    static const char * const tdo_attrs[] = {
2793
0
      "trustAuthIncoming",
2794
0
      "trustDirection",
2795
0
      NULL
2796
0
    };
2797
0
    struct ldb_message *tdo_msg = NULL;
2798
0
    const char *account_name = NULL;
2799
0
    uint32_t trust_direction;
2800
0
    uint32_t i;
2801
0
    const struct ldb_val *old_val = NULL;
2802
0
    struct trustAuthInOutBlob old_blob = {
2803
0
      .count = 0,
2804
0
    };
2805
0
    uint32_t old_version = 0;
2806
0
    struct AuthenticationInformation *old_version_a = NULL;
2807
0
    uint32_t _new_version = 0;
2808
0
    struct trustAuthInOutBlob new_blob = {
2809
0
      .count = 0,
2810
0
    };
2811
0
    struct ldb_val new_val = {
2812
0
      .length = 0,
2813
0
    };
2814
0
    struct timeval tv = timeval_current();
2815
0
    NTTIME now = timeval_to_nttime(&tv);
2816
0
    enum ndr_err_code ndr_err;
2817
2818
0
    if (new_password == NULL && ntNewHash == NULL) {
2819
0
      ldb_transaction_cancel(ldb);
2820
0
      DEBUG(1, ("samdb_set_password_sid: "
2821
0
          "no new password provided "
2822
0
          "sAMAccountName for SID[%s] DN[%s], "
2823
0
          "returning INVALID_PARAMETER\n",
2824
0
          dom_sid_string(frame, user_sid),
2825
0
          ldb_dn_get_linearized(user_msg->dn)));
2826
0
      TALLOC_FREE(frame);
2827
0
      return NT_STATUS_INVALID_PARAMETER;
2828
0
    }
2829
2830
0
    if (new_password != NULL && ntNewHash != NULL) {
2831
0
      ldb_transaction_cancel(ldb);
2832
0
      DEBUG(1, ("samdb_set_password_sid: "
2833
0
          "two new passwords provided "
2834
0
          "sAMAccountName for SID[%s] DN[%s], "
2835
0
          "returning INVALID_PARAMETER\n",
2836
0
          dom_sid_string(frame, user_sid),
2837
0
          ldb_dn_get_linearized(user_msg->dn)));
2838
0
      TALLOC_FREE(frame);
2839
0
      return NT_STATUS_INVALID_PARAMETER;
2840
0
    }
2841
2842
0
    if (new_password != NULL && (new_password->length % 2)) {
2843
0
      ldb_transaction_cancel(ldb);
2844
0
      DEBUG(2, ("samdb_set_password_sid: "
2845
0
          "invalid utf16 length (%zu) "
2846
0
          "sAMAccountName for SID[%s] DN[%s], "
2847
0
          "returning WRONG_PASSWORD\n",
2848
0
          new_password->length,
2849
0
          dom_sid_string(frame, user_sid),
2850
0
          ldb_dn_get_linearized(user_msg->dn)));
2851
0
      TALLOC_FREE(frame);
2852
0
      return NT_STATUS_WRONG_PASSWORD;
2853
0
    }
2854
2855
0
    if (new_password != NULL && new_password->length >= 500) {
2856
0
      ldb_transaction_cancel(ldb);
2857
0
      DEBUG(2, ("samdb_set_password_sid: "
2858
0
          "utf16 password too long (%zu) "
2859
0
          "sAMAccountName for SID[%s] DN[%s], "
2860
0
          "returning WRONG_PASSWORD\n",
2861
0
          new_password->length,
2862
0
          dom_sid_string(frame, user_sid),
2863
0
          ldb_dn_get_linearized(user_msg->dn)));
2864
0
      TALLOC_FREE(frame);
2865
0
      return NT_STATUS_WRONG_PASSWORD;
2866
0
    }
2867
2868
0
    account_name = ldb_msg_find_attr_as_string(user_msg,
2869
0
              "sAMAccountName", NULL);
2870
0
    if (account_name == NULL) {
2871
0
      ldb_transaction_cancel(ldb);
2872
0
      DEBUG(1, ("samdb_set_password_sid: missing "
2873
0
          "sAMAccountName for SID[%s] DN[%s], "
2874
0
          "returning NO_SUCH_USER\n",
2875
0
          dom_sid_string(frame, user_sid),
2876
0
          ldb_dn_get_linearized(user_msg->dn)));
2877
0
      TALLOC_FREE(frame);
2878
0
      return NT_STATUS_NO_SUCH_USER;
2879
0
    }
2880
2881
0
    nt_status = dsdb_trust_search_tdo_by_type(ldb,
2882
0
                SEC_CHAN_DOMAIN,
2883
0
                account_name,
2884
0
                tdo_attrs,
2885
0
                frame, &tdo_msg);
2886
0
    if (!NT_STATUS_IS_OK(nt_status)) {
2887
0
      ldb_transaction_cancel(ldb);
2888
0
      DEBUG(1, ("samdb_set_password_sid: dsdb_trust_search_tdo "
2889
0
          "failed(%s) for sAMAccountName[%s] SID[%s] DN[%s], "
2890
0
          "returning INTERNAL_DB_CORRUPTION\n",
2891
0
          nt_errstr(nt_status), account_name,
2892
0
          dom_sid_string(frame, user_sid),
2893
0
          ldb_dn_get_linearized(user_msg->dn)));
2894
0
      TALLOC_FREE(frame);
2895
0
      return NT_STATUS_INTERNAL_DB_CORRUPTION;
2896
0
    }
2897
2898
0
    trust_direction = ldb_msg_find_attr_as_int(tdo_msg,
2899
0
                 "trustDirection", 0);
2900
0
    if (!(trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
2901
0
      ldb_transaction_cancel(ldb);
2902
0
      DEBUG(1, ("samdb_set_password_sid: direction[0x%08X] is "
2903
0
          "not inbound for sAMAccountName[%s] "
2904
0
          "DN[%s] TDO[%s], "
2905
0
          "returning INTERNAL_DB_CORRUPTION\n",
2906
0
          (unsigned)trust_direction,
2907
0
          account_name,
2908
0
          ldb_dn_get_linearized(user_msg->dn),
2909
0
          ldb_dn_get_linearized(tdo_msg->dn)));
2910
0
      TALLOC_FREE(frame);
2911
0
      return NT_STATUS_INTERNAL_DB_CORRUPTION;
2912
0
    }
2913
2914
0
    old_val = ldb_msg_find_ldb_val(tdo_msg, "trustAuthIncoming");
2915
0
    if (old_val != NULL) {
2916
0
      ndr_err = ndr_pull_struct_blob(old_val, frame, &old_blob,
2917
0
          (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2918
0
      if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2919
0
        ldb_transaction_cancel(ldb);
2920
0
        DEBUG(1, ("samdb_set_password_sid: "
2921
0
            "failed(%s) to parse "
2922
0
            "trustAuthOutgoing sAMAccountName[%s] "
2923
0
            "DN[%s] TDO[%s], "
2924
0
            "returning INTERNAL_DB_CORRUPTION\n",
2925
0
            ndr_map_error2string(ndr_err),
2926
0
            account_name,
2927
0
            ldb_dn_get_linearized(user_msg->dn),
2928
0
            ldb_dn_get_linearized(tdo_msg->dn)));
2929
2930
0
        TALLOC_FREE(frame);
2931
0
        return NT_STATUS_INTERNAL_DB_CORRUPTION;
2932
0
      }
2933
0
    }
2934
2935
0
    for (i = old_blob.current.count; i > 0; i--) {
2936
0
      struct AuthenticationInformation *a =
2937
0
        &old_blob.current.array[i - 1];
2938
2939
0
      switch (a->AuthType) {
2940
0
      case TRUST_AUTH_TYPE_NONE:
2941
0
        if (i == old_blob.current.count) {
2942
          /*
2943
           * remove TRUST_AUTH_TYPE_NONE at the
2944
           * end
2945
           */
2946
0
          old_blob.current.count--;
2947
0
        }
2948
0
        break;
2949
2950
0
      case TRUST_AUTH_TYPE_VERSION:
2951
0
        old_version_a = a;
2952
0
        old_version = a->AuthInfo.version.version;
2953
0
        break;
2954
2955
0
      case TRUST_AUTH_TYPE_CLEAR:
2956
0
        break;
2957
2958
0
      case TRUST_AUTH_TYPE_NT4OWF:
2959
0
        break;
2960
0
      }
2961
0
    }
2962
2963
0
    if (new_version == NULL) {
2964
0
      _new_version = 0;
2965
0
      new_version = &_new_version;
2966
0
    }
2967
2968
0
    if (old_version_a != NULL && *new_version != (old_version + 1)) {
2969
0
      old_version_a->LastUpdateTime = now;
2970
0
      old_version_a->AuthType = TRUST_AUTH_TYPE_NONE;
2971
0
    }
2972
2973
0
    new_blob.count = MAX(old_blob.current.count, 2);
2974
0
    new_blob.current.array = talloc_zero_array(frame,
2975
0
            struct AuthenticationInformation,
2976
0
            new_blob.count);
2977
0
    if (new_blob.current.array == NULL) {
2978
0
      ldb_transaction_cancel(ldb);
2979
0
      TALLOC_FREE(frame);
2980
0
      return NT_STATUS_NO_MEMORY;
2981
0
    }
2982
0
    new_blob.previous.array = talloc_zero_array(frame,
2983
0
            struct AuthenticationInformation,
2984
0
            new_blob.count);
2985
0
    if (new_blob.current.array == NULL) {
2986
0
      ldb_transaction_cancel(ldb);
2987
0
      TALLOC_FREE(frame);
2988
0
      return NT_STATUS_NO_MEMORY;
2989
0
    }
2990
2991
0
    for (i = 0; i < old_blob.current.count; i++) {
2992
0
      struct AuthenticationInformation *o =
2993
0
        &old_blob.current.array[i];
2994
0
      struct AuthenticationInformation *p =
2995
0
        &new_blob.previous.array[i];
2996
2997
0
      *p = *o;
2998
0
      new_blob.previous.count++;
2999
0
    }
3000
0
    for (; i < new_blob.count; i++) {
3001
0
      struct AuthenticationInformation *pi =
3002
0
        &new_blob.previous.array[i];
3003
3004
0
      if (i == 0) {
3005
        /*
3006
         * new_blob.previous is still empty so
3007
         * we'll do new_blob.previous = new_blob.current
3008
         * below.
3009
         */
3010
0
        break;
3011
0
      }
3012
3013
0
      pi->LastUpdateTime = now;
3014
0
      pi->AuthType = TRUST_AUTH_TYPE_NONE;
3015
0
      new_blob.previous.count++;
3016
0
    }
3017
3018
0
    for (i = 0; i < new_blob.count; i++) {
3019
0
      struct AuthenticationInformation *ci =
3020
0
        &new_blob.current.array[i];
3021
3022
0
      ci->LastUpdateTime = now;
3023
0
      switch (i) {
3024
0
      case 0:
3025
0
        if (ntNewHash != NULL) {
3026
0
          ci->AuthType = TRUST_AUTH_TYPE_NT4OWF;
3027
0
          ci->AuthInfo.nt4owf.password = *ntNewHash;
3028
0
          break;
3029
0
        }
3030
3031
0
        ci->AuthType = TRUST_AUTH_TYPE_CLEAR;
3032
0
        ci->AuthInfo.clear.size = new_password->length;
3033
0
        ci->AuthInfo.clear.password = new_password->data;
3034
0
        break;
3035
0
      case 1:
3036
0
        ci->AuthType = TRUST_AUTH_TYPE_VERSION;
3037
0
        ci->AuthInfo.version.version = *new_version;
3038
0
        break;
3039
0
      default:
3040
0
        ci->AuthType = TRUST_AUTH_TYPE_NONE;
3041
0
        break;
3042
0
      }
3043
3044
0
      new_blob.current.count++;
3045
0
    }
3046
3047
0
    if (new_blob.previous.count == 0) {
3048
0
      TALLOC_FREE(new_blob.previous.array);
3049
0
      new_blob.previous = new_blob.current;
3050
0
    }
3051
3052
0
    ndr_err = ndr_push_struct_blob(&new_val, frame, &new_blob,
3053
0
        (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
3054
0
    if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3055
0
      ldb_transaction_cancel(ldb);
3056
0
      DEBUG(1, ("samdb_set_password_sid: "
3057
0
          "failed(%s) to generate "
3058
0
          "trustAuthOutgoing sAMAccountName[%s] "
3059
0
          "DN[%s] TDO[%s], "
3060
0
          "returning UNSUCCESSFUL\n",
3061
0
          ndr_map_error2string(ndr_err),
3062
0
          account_name,
3063
0
          ldb_dn_get_linearized(user_msg->dn),
3064
0
          ldb_dn_get_linearized(tdo_msg->dn)));
3065
0
      TALLOC_FREE(frame);
3066
0
      return NT_STATUS_UNSUCCESSFUL;
3067
0
    }
3068
3069
0
    tdo_msg->num_elements = 0;
3070
0
    TALLOC_FREE(tdo_msg->elements);
3071
3072
0
    ret = ldb_msg_append_value(tdo_msg, "trustAuthIncoming",
3073
0
             &new_val, LDB_FLAG_MOD_REPLACE);
3074
0
    if (ret != LDB_SUCCESS) {
3075
0
      ldb_transaction_cancel(ldb);
3076
0
      TALLOC_FREE(frame);
3077
0
      return NT_STATUS_NO_MEMORY;
3078
0
    }
3079
3080
0
    ret = ldb_modify(ldb, tdo_msg);
3081
0
    if (ret != LDB_SUCCESS) {
3082
0
      nt_status = dsdb_ldb_err_to_ntstatus(ret);
3083
0
      ldb_transaction_cancel(ldb);
3084
0
      DEBUG(1, ("samdb_set_password_sid: "
3085
0
          "failed to replace "
3086
0
          "trustAuthOutgoing sAMAccountName[%s] "
3087
0
          "DN[%s] TDO[%s], "
3088
0
          "%s - %s\n",
3089
0
          account_name,
3090
0
          ldb_dn_get_linearized(user_msg->dn),
3091
0
          ldb_dn_get_linearized(tdo_msg->dn),
3092
0
          nt_errstr(nt_status), ldb_errstring(ldb)));
3093
0
      TALLOC_FREE(frame);
3094
0
      return nt_status;
3095
0
    }
3096
0
  }
3097
3098
0
  nt_status = samdb_set_password_internal(ldb, mem_ctx,
3099
0
            user_msg->dn,
3100
0
            new_password,
3101
0
            ntNewHash,
3102
0
            old_password_checked,
3103
0
            reject_reason, _dominfo,
3104
0
            true); /* permit trusts */
3105
0
  if (!NT_STATUS_IS_OK(nt_status)) {
3106
0
    ldb_transaction_cancel(ldb);
3107
0
    TALLOC_FREE(frame);
3108
0
    return nt_status;
3109
0
  }
3110
3111
0
  ret = ldb_transaction_commit(ldb);
3112
0
  if (ret != LDB_SUCCESS) {
3113
0
    DEBUG(0,("Failed to commit transaction to change password on %s: %s\n",
3114
0
       ldb_dn_get_linearized(user_msg->dn),
3115
0
       ldb_errstring(ldb)));
3116
0
    TALLOC_FREE(frame);
3117
0
    return NT_STATUS_TRANSACTION_ABORTED;
3118
0
  }
3119
3120
0
  TALLOC_FREE(frame);
3121
0
  return NT_STATUS_OK;
3122
0
}
3123
3124
3125
NTSTATUS samdb_create_foreign_security_principal(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
3126
             struct dom_sid *sid, struct ldb_dn **ret_dn)
3127
0
{
3128
0
  struct ldb_message *msg;
3129
0
  struct ldb_dn *basedn = NULL;
3130
0
  char *sidstr;
3131
0
  int ret;
3132
3133
0
  sidstr = dom_sid_string(mem_ctx, sid);
3134
0
  NT_STATUS_HAVE_NO_MEMORY(sidstr);
3135
3136
  /* We might have to create a ForeignSecurityPrincipal, even if this user
3137
   * is in our own domain */
3138
3139
0
  msg = ldb_msg_new(sidstr);
3140
0
  if (msg == NULL) {
3141
0
    talloc_free(sidstr);
3142
0
    return NT_STATUS_NO_MEMORY;
3143
0
  }
3144
3145
0
  ret = dsdb_wellknown_dn(sam_ctx, sidstr,
3146
0
        ldb_get_default_basedn(sam_ctx),
3147
0
        DS_GUID_FOREIGNSECURITYPRINCIPALS_CONTAINER,
3148
0
        &basedn);
3149
0
  if (ret != LDB_SUCCESS) {
3150
0
    DEBUG(0, ("Failed to find DN for "
3151
0
        "ForeignSecurityPrincipal container - %s\n", ldb_errstring(sam_ctx)));
3152
0
    talloc_free(sidstr);
3153
0
    return NT_STATUS_INTERNAL_DB_CORRUPTION;
3154
0
  }
3155
3156
  /* add core elements to the ldb_message for the alias */
3157
0
  msg->dn = basedn;
3158
0
  if ( ! ldb_dn_add_child_fmt(msg->dn, "CN=%s", sidstr)) {
3159
0
    talloc_free(sidstr);
3160
0
    return NT_STATUS_NO_MEMORY;
3161
0
  }
3162
3163
0
  ret = ldb_msg_add_string(msg, "objectClass",
3164
0
         "foreignSecurityPrincipal");
3165
0
  if (ret != LDB_SUCCESS) {
3166
0
    talloc_free(sidstr);
3167
0
    return NT_STATUS_NO_MEMORY;
3168
0
  }
3169
3170
  /* create the alias */
3171
0
  ret = ldb_add(sam_ctx, msg);
3172
0
  if (ret != LDB_SUCCESS) {
3173
0
    DEBUG(0,("Failed to create foreignSecurityPrincipal "
3174
0
       "record %s: %s\n",
3175
0
       ldb_dn_get_linearized(msg->dn),
3176
0
       ldb_errstring(sam_ctx)));
3177
0
    talloc_free(sidstr);
3178
0
    return NT_STATUS_INTERNAL_DB_CORRUPTION;
3179
0
  }
3180
3181
0
  *ret_dn = talloc_steal(mem_ctx, msg->dn);
3182
0
  talloc_free(sidstr);
3183
3184
0
  return NT_STATUS_OK;
3185
0
}
3186
3187
3188
/*
3189
  Find the DN of a domain, assuming it to be a dotted.dns name
3190
*/
3191
3192
struct ldb_dn *samdb_dns_domain_to_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *dns_domain)
3193
0
{
3194
0
  unsigned int i;
3195
0
  TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
3196
0
  const char *binary_encoded;
3197
0
  const char * const *split_realm;
3198
0
  struct ldb_dn *dn;
3199
3200
0
  if (!tmp_ctx) {
3201
0
    return NULL;
3202
0
  }
3203
3204
0
  split_realm = (const char * const *)str_list_make(tmp_ctx, dns_domain, ".");
3205
0
  if (!split_realm) {
3206
0
    talloc_free(tmp_ctx);
3207
0
    return NULL;
3208
0
  }
3209
0
  dn = ldb_dn_new(mem_ctx, ldb, NULL);
3210
0
  for (i=0; split_realm[i]; i++) {
3211
0
    binary_encoded = ldb_binary_encode_string(tmp_ctx, split_realm[i]);
3212
0
    if (binary_encoded == NULL) {
3213
0
      DEBUG(2, ("Failed to add dc= element to DN %s\n",
3214
0
          ldb_dn_get_linearized(dn)));
3215
0
      talloc_free(tmp_ctx);
3216
0
      return NULL;
3217
0
    }
3218
0
    if (!ldb_dn_add_base_fmt(dn, "dc=%s", binary_encoded)) {
3219
0
      DEBUG(2, ("Failed to add dc=%s element to DN %s\n",
3220
0
          binary_encoded, ldb_dn_get_linearized(dn)));
3221
0
      talloc_free(tmp_ctx);
3222
0
      return NULL;
3223
0
    }
3224
0
  }
3225
0
  if (!ldb_dn_validate(dn)) {
3226
0
    DEBUG(2, ("Failed to validated DN %s\n",
3227
0
        ldb_dn_get_linearized(dn)));
3228
0
    talloc_free(tmp_ctx);
3229
0
    return NULL;
3230
0
  }
3231
0
  talloc_free(tmp_ctx);
3232
0
  return dn;
3233
0
}
3234
3235
3236
/*
3237
  Find the DNS equivalent of a DN, in dotted DNS form
3238
*/
3239
char *samdb_dn_to_dns_domain(TALLOC_CTX *mem_ctx, struct ldb_dn *dn)
3240
0
{
3241
0
  int i, num_components = ldb_dn_get_comp_num(dn);
3242
0
  char *dns_name = talloc_strdup(mem_ctx, "");
3243
3244
0
  for (i=0; i<num_components; i++) {
3245
0
    const struct ldb_val *v = ldb_dn_get_component_val(dn, i);
3246
0
    if (v == NULL) {
3247
0
      talloc_free(dns_name);
3248
0
      return NULL;
3249
0
    }
3250
0
    talloc_asprintf_addbuf(&dns_name,
3251
0
               "%*.*s.",
3252
0
               (int)v->length,
3253
0
               (int)v->length,
3254
0
               (char *)v->data);
3255
0
  }
3256
3257
0
  if (dns_name == NULL) {
3258
0
    return NULL;
3259
0
  }
3260
3261
  /* remove the last '.' */
3262
0
  if (dns_name[0] != 0) {
3263
0
    dns_name[strlen(dns_name)-1] = 0;
3264
0
  }
3265
3266
0
  return dns_name;
3267
0
}
3268
3269
/*
3270
  Find the DNS _msdcs name for a given NTDS GUID. The resulting DNS
3271
  name is based on the forest DNS name
3272
*/
3273
char *samdb_ntds_msdcs_dns_name(struct ldb_context *samdb,
3274
        TALLOC_CTX *mem_ctx,
3275
        const struct GUID *ntds_guid)
3276
0
{
3277
0
  TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
3278
0
  const char *guid_str;
3279
0
  struct ldb_dn *forest_dn;
3280
0
  const char *dnsforest;
3281
0
  char *ret;
3282
3283
0
  guid_str = GUID_string(tmp_ctx, ntds_guid);
3284
0
  if (guid_str == NULL) {
3285
0
    talloc_free(tmp_ctx);
3286
0
    return NULL;
3287
0
  }
3288
0
  forest_dn = ldb_get_root_basedn(samdb);
3289
0
  if (forest_dn == NULL) {
3290
0
    talloc_free(tmp_ctx);
3291
0
    return NULL;
3292
0
  }
3293
0
  dnsforest = samdb_dn_to_dns_domain(tmp_ctx, forest_dn);
3294
0
  if (dnsforest == NULL) {
3295
0
    talloc_free(tmp_ctx);
3296
0
    return NULL;
3297
0
  }
3298
0
  ret = talloc_asprintf(mem_ctx, "%s._msdcs.%s", guid_str, dnsforest);
3299
0
  talloc_free(tmp_ctx);
3300
0
  return ret;
3301
0
}
3302
3303
3304
/*
3305
  Find the DN of a domain, be it the netbios or DNS name
3306
*/
3307
struct ldb_dn *samdb_domain_to_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
3308
          const char *domain_name)
3309
0
{
3310
0
  const char * const domain_ref_attrs[] = {
3311
0
    "ncName", NULL
3312
0
  };
3313
0
  const char * const domain_ref2_attrs[] = {
3314
0
    NULL
3315
0
  };
3316
0
  struct ldb_result *res_domain_ref;
3317
0
  char *escaped_domain = ldb_binary_encode_string(mem_ctx, domain_name);
3318
0
  int ret_domain;
3319
3320
0
  if (escaped_domain == NULL) {
3321
0
    return NULL;
3322
0
  }
3323
3324
  /* find the domain's DN */
3325
0
  ret_domain = ldb_search(ldb, mem_ctx,
3326
0
        &res_domain_ref,
3327
0
        samdb_partitions_dn(ldb, mem_ctx),
3328
0
        LDB_SCOPE_ONELEVEL,
3329
0
        domain_ref_attrs,
3330
0
        "(&(nETBIOSName=%s)(objectclass=crossRef))",
3331
0
        escaped_domain);
3332
0
  if (ret_domain != LDB_SUCCESS) {
3333
0
    return NULL;
3334
0
  }
3335
3336
0
  if (res_domain_ref->count == 0) {
3337
0
    ret_domain = ldb_search(ldb, mem_ctx,
3338
0
            &res_domain_ref,
3339
0
            samdb_dns_domain_to_dn(ldb, mem_ctx, domain_name),
3340
0
            LDB_SCOPE_BASE,
3341
0
            domain_ref2_attrs,
3342
0
            "(objectclass=domain)");
3343
0
    if (ret_domain != LDB_SUCCESS) {
3344
0
      return NULL;
3345
0
    }
3346
3347
0
    if (res_domain_ref->count == 1) {
3348
0
      return res_domain_ref->msgs[0]->dn;
3349
0
    }
3350
0
    return NULL;
3351
0
  }
3352
3353
0
  if (res_domain_ref->count > 1) {
3354
0
    DEBUG(0,("Found %d records matching domain [%s]\n",
3355
0
       ret_domain, domain_name));
3356
0
    return NULL;
3357
0
  }
3358
3359
0
  return samdb_result_dn(ldb, mem_ctx, res_domain_ref->msgs[0], "nCName", NULL);
3360
3361
0
}
3362
3363
3364
/*
3365
  use a GUID to find a DN
3366
 */
3367
int dsdb_find_dn_by_guid(struct ldb_context *ldb,
3368
       TALLOC_CTX *mem_ctx,
3369
       const struct GUID *guid,
3370
       uint32_t dsdb_flags,
3371
       struct ldb_dn **dn)
3372
0
{
3373
0
  int ret;
3374
0
  struct ldb_result *res;
3375
0
  const char *attrs[] = { NULL };
3376
0
  struct GUID_txt_buf buf;
3377
0
  char *guid_str = GUID_buf_string(guid, &buf);
3378
3379
0
  ret = dsdb_search(ldb, mem_ctx, &res, NULL, LDB_SCOPE_SUBTREE, attrs,
3380
0
        DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
3381
0
        DSDB_SEARCH_SHOW_EXTENDED_DN |
3382
0
        DSDB_SEARCH_ONE_ONLY | dsdb_flags,
3383
0
        "objectGUID=%s", guid_str);
3384
0
  if (ret != LDB_SUCCESS) {
3385
0
    return ret;
3386
0
  }
3387
3388
0
  *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
3389
0
  talloc_free(res);
3390
3391
0
  return LDB_SUCCESS;
3392
0
}
3393
3394
/*
3395
  use a DN to find a GUID with a given attribute name
3396
 */
3397
int dsdb_find_guid_attr_by_dn(struct ldb_context *ldb,
3398
            struct ldb_dn *dn, const char *attribute,
3399
            struct GUID *guid)
3400
0
{
3401
0
  int ret;
3402
0
  struct ldb_result *res = NULL;
3403
0
  const char *attrs[2];
3404
0
  TALLOC_CTX *tmp_ctx = talloc_new(ldb);
3405
3406
0
  attrs[0] = attribute;
3407
0
  attrs[1] = NULL;
3408
3409
0
  ret = dsdb_search_dn(ldb, tmp_ctx, &res, dn, attrs,
3410
0
           DSDB_SEARCH_SHOW_DELETED |
3411
0
           DSDB_SEARCH_SHOW_RECYCLED);
3412
0
  if (ret != LDB_SUCCESS) {
3413
0
    talloc_free(tmp_ctx);
3414
0
    return ret;
3415
0
  }
3416
  /* satisfy clang */
3417
0
  if (res == NULL) {
3418
0
    talloc_free(tmp_ctx);
3419
0
    return LDB_ERR_OTHER;
3420
0
  }
3421
0
  if (res->count < 1) {
3422
0
    talloc_free(tmp_ctx);
3423
0
    return ldb_error(ldb, LDB_ERR_NO_SUCH_OBJECT, __func__);
3424
0
  }
3425
0
  *guid = samdb_result_guid(res->msgs[0], attribute);
3426
0
  talloc_free(tmp_ctx);
3427
0
  return LDB_SUCCESS;
3428
0
}
3429
3430
/*
3431
  use a DN to find a GUID
3432
 */
3433
int dsdb_find_guid_by_dn(struct ldb_context *ldb,
3434
       struct ldb_dn *dn, struct GUID *guid)
3435
0
{
3436
0
  return dsdb_find_guid_attr_by_dn(ldb, dn, "objectGUID", guid);
3437
0
}
3438
3439
3440
3441
/*
3442
 adds the given GUID to the given ldb_message. This value is added
3443
 for the given attr_name (may be either "objectGUID" or "parentGUID").
3444
 This function is used in processing 'add' requests.
3445
 */
3446
int dsdb_msg_add_guid(struct ldb_message *msg,
3447
    struct GUID *guid,
3448
    const char *attr_name)
3449
0
{
3450
0
  int ret;
3451
0
  struct ldb_val v;
3452
0
  NTSTATUS status;
3453
0
  TALLOC_CTX *tmp_ctx =  talloc_init("dsdb_msg_add_guid");
3454
3455
0
  status = GUID_to_ndr_blob(guid, tmp_ctx, &v);
3456
0
  if (!NT_STATUS_IS_OK(status)) {
3457
0
    ret = LDB_ERR_OPERATIONS_ERROR;
3458
0
    goto done;
3459
0
  }
3460
3461
0
  ret = ldb_msg_add_steal_value(msg, attr_name, &v);
3462
0
  if (ret != LDB_SUCCESS) {
3463
0
    DEBUG(4,(__location__ ": Failed to add %s to the message\n",
3464
0
           attr_name));
3465
0
    goto done;
3466
0
  }
3467
3468
0
  ret = LDB_SUCCESS;
3469
3470
0
done:
3471
0
  talloc_free(tmp_ctx);
3472
0
  return ret;
3473
3474
0
}
3475
3476
3477
/*
3478
  use a DN to find a SID
3479
 */
3480
int dsdb_find_sid_by_dn(struct ldb_context *ldb,
3481
      struct ldb_dn *dn, struct dom_sid *sid)
3482
0
{
3483
0
  int ret;
3484
0
  struct ldb_result *res = NULL;
3485
0
  const char *attrs[] = { "objectSid", NULL };
3486
0
  TALLOC_CTX *tmp_ctx = talloc_new(ldb);
3487
0
  struct dom_sid *s;
3488
3489
0
  ZERO_STRUCTP(sid);
3490
3491
0
  ret = dsdb_search_dn(ldb, tmp_ctx, &res, dn, attrs,
3492
0
           DSDB_SEARCH_SHOW_DELETED |
3493
0
           DSDB_SEARCH_SHOW_RECYCLED);
3494
0
  if (ret != LDB_SUCCESS) {
3495
0
    talloc_free(tmp_ctx);
3496
0
    return ret;
3497
0
  }
3498
0
  if (res == NULL) {
3499
0
    talloc_free(tmp_ctx);
3500
0
    return LDB_ERR_OTHER;
3501
0
  }
3502
0
  if (res->count < 1) {
3503
0
    talloc_free(tmp_ctx);
3504
0
    return ldb_error(ldb, LDB_ERR_NO_SUCH_OBJECT, __func__);
3505
0
  }
3506
0
  s = samdb_result_dom_sid(tmp_ctx, res->msgs[0], "objectSid");
3507
0
  if (s == NULL) {
3508
0
    talloc_free(tmp_ctx);
3509
0
    return ldb_error(ldb, LDB_ERR_NO_SUCH_OBJECT, __func__);
3510
0
  }
3511
0
  *sid = *s;
3512
0
  talloc_free(tmp_ctx);
3513
0
  return LDB_SUCCESS;
3514
0
}
3515
3516
/*
3517
  use a SID to find a DN
3518
 */
3519
int dsdb_find_dn_by_sid(struct ldb_context *ldb,
3520
      TALLOC_CTX *mem_ctx,
3521
      struct dom_sid *sid, struct ldb_dn **dn)
3522
0
{
3523
0
  int ret;
3524
0
  struct ldb_result *res;
3525
0
  const char *attrs[] = { NULL };
3526
0
  char *sid_str = ldap_encode_ndr_dom_sid(mem_ctx, sid);
3527
3528
0
  if (!sid_str) {
3529
0
    return ldb_operr(ldb);
3530
0
  }
3531
3532
0
  ret = dsdb_search(ldb, mem_ctx, &res, NULL, LDB_SCOPE_SUBTREE, attrs,
3533
0
        DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
3534
0
        DSDB_SEARCH_SHOW_EXTENDED_DN |
3535
0
        DSDB_SEARCH_ONE_ONLY,
3536
0
        "objectSid=%s", sid_str);
3537
0
  talloc_free(sid_str);
3538
0
  if (ret != LDB_SUCCESS) {
3539
0
    return ret;
3540
0
  }
3541
3542
0
  *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
3543
0
  talloc_free(res);
3544
3545
0
  return LDB_SUCCESS;
3546
0
}
3547
3548
/*
3549
  load a repsFromTo blob list for a given partition GUID
3550
  attr must be "repsFrom" or "repsTo"
3551
 */
3552
WERROR dsdb_loadreps(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, struct ldb_dn *dn,
3553
         const char *attr, struct repsFromToBlob **r, uint32_t *count)
3554
0
{
3555
0
  const char *attrs[] = { attr, NULL };
3556
0
  struct ldb_result *res = NULL;
3557
0
  TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
3558
0
  unsigned int i;
3559
0
  struct ldb_message_element *el;
3560
0
  int ret;
3561
3562
0
  *r = NULL;
3563
0
  *count = 0;
3564
3565
0
  if (tmp_ctx == NULL) {
3566
0
    return WERR_NOT_ENOUGH_MEMORY;
3567
0
  }
3568
3569
0
  ret = dsdb_search_dn(sam_ctx, tmp_ctx, &res, dn, attrs, 0);
3570
0
  if (ret == LDB_ERR_NO_SUCH_OBJECT) {
3571
    /* partition hasn't been replicated yet */
3572
0
    talloc_free(tmp_ctx);
3573
0
    return WERR_OK;
3574
0
  }
3575
0
  if (ret != LDB_SUCCESS) {
3576
0
    DEBUG(0,("dsdb_loadreps: failed to read partition object: %s\n", ldb_errstring(sam_ctx)));
3577
0
    talloc_free(tmp_ctx);
3578
0
    return WERR_DS_DRA_INTERNAL_ERROR;
3579
0
  }
3580
3581
  /* satisfy clang */
3582
0
  if (res == NULL) {
3583
0
    talloc_free(tmp_ctx);
3584
0
    return WERR_DS_DRA_INTERNAL_ERROR;
3585
0
  }
3586
0
  el = ldb_msg_find_element(res->msgs[0], attr);
3587
0
  if (el == NULL) {
3588
    /* it's OK to be empty */
3589
0
    talloc_free(tmp_ctx);
3590
0
    return WERR_OK;
3591
0
  }
3592
3593
0
  *count = el->num_values;
3594
0
  *r = talloc_array(mem_ctx, struct repsFromToBlob, *count);
3595
0
  if (*r == NULL) {
3596
0
    talloc_free(tmp_ctx);
3597
0
    return WERR_DS_DRA_INTERNAL_ERROR;
3598
0
  }
3599
3600
0
  for (i=0; i<(*count); i++) {
3601
0
    enum ndr_err_code ndr_err;
3602
0
    ndr_err = ndr_pull_struct_blob(&el->values[i],
3603
0
                 mem_ctx,
3604
0
                 &(*r)[i],
3605
0
                 (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob);
3606
0
    if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3607
0
      talloc_free(tmp_ctx);
3608
0
      return WERR_DS_DRA_INTERNAL_ERROR;
3609
0
    }
3610
0
  }
3611
3612
0
  talloc_free(tmp_ctx);
3613
3614
0
  return WERR_OK;
3615
0
}
3616
3617
/*
3618
  save the repsFromTo blob list for a given partition GUID
3619
  attr must be "repsFrom" or "repsTo"
3620
 */
3621
WERROR dsdb_savereps(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, struct ldb_dn *dn,
3622
         const char *attr, struct repsFromToBlob *r, uint32_t count)
3623
0
{
3624
0
  TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
3625
0
  struct ldb_message *msg;
3626
0
  struct ldb_message_element *el;
3627
0
  unsigned int i;
3628
3629
0
  if (tmp_ctx == NULL) {
3630
0
    goto failed;
3631
0
  }
3632
3633
0
  msg = ldb_msg_new(tmp_ctx);
3634
0
  if (msg == NULL) {
3635
0
    goto failed;
3636
0
  }
3637
0
  msg->dn = dn;
3638
0
  if (ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_REPLACE, &el) != LDB_SUCCESS) {
3639
0
    goto failed;
3640
0
  }
3641
3642
0
  el->values = talloc_array(msg, struct ldb_val, count);
3643
0
  if (!el->values) {
3644
0
    goto failed;
3645
0
  }
3646
3647
0
  for (i=0; i<count; i++) {
3648
0
    struct ldb_val v;
3649
0
    enum ndr_err_code ndr_err;
3650
3651
0
    ndr_err = ndr_push_struct_blob(&v, tmp_ctx,
3652
0
                 &r[i],
3653
0
                 (ndr_push_flags_fn_t)ndr_push_repsFromToBlob);
3654
0
    if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3655
0
      goto failed;
3656
0
    }
3657
3658
0
    el->num_values++;
3659
0
    el->values[i] = v;
3660
0
  }
3661
3662
0
  if (dsdb_modify(sam_ctx, msg, 0) != LDB_SUCCESS) {
3663
0
    DEBUG(0,("Failed to store %s - %s\n", attr, ldb_errstring(sam_ctx)));
3664
0
    goto failed;
3665
0
  }
3666
3667
0
  talloc_free(tmp_ctx);
3668
3669
0
  return WERR_OK;
3670
3671
0
failed:
3672
0
  talloc_free(tmp_ctx);
3673
0
  return WERR_DS_DRA_INTERNAL_ERROR;
3674
0
}
3675
3676
3677
/*
3678
  load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
3679
  object for a partition
3680
 */
3681
int dsdb_load_partition_usn(struct ldb_context *ldb, struct ldb_dn *dn,
3682
        uint64_t *uSN, uint64_t *urgent_uSN)
3683
0
{
3684
0
  struct ldb_request *req;
3685
0
  int ret;
3686
0
  TALLOC_CTX *tmp_ctx = talloc_new(ldb);
3687
0
  struct dsdb_control_current_partition *p_ctrl;
3688
0
  struct ldb_result *res;
3689
3690
0
  if (tmp_ctx == NULL) {
3691
0
    return ldb_oom(ldb);
3692
0
  }
3693
3694
0
  res = talloc_zero(tmp_ctx, struct ldb_result);
3695
0
  if (!res) {
3696
0
    talloc_free(tmp_ctx);
3697
0
    return ldb_oom(ldb);
3698
0
  }
3699
3700
0
  ret = ldb_build_search_req(&req, ldb, tmp_ctx,
3701
0
           ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
3702
0
           LDB_SCOPE_BASE,
3703
0
           NULL, NULL,
3704
0
           NULL,
3705
0
           res, ldb_search_default_callback,
3706
0
           NULL);
3707
0
  if (ret != LDB_SUCCESS) {
3708
0
    talloc_free(tmp_ctx);
3709
0
    return ret;
3710
0
  }
3711
3712
0
  p_ctrl = talloc(req, struct dsdb_control_current_partition);
3713
0
  if (p_ctrl == NULL) {
3714
0
    talloc_free(tmp_ctx);
3715
0
    return ldb_oom(ldb);
3716
0
  }
3717
0
  p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
3718
0
  p_ctrl->dn = dn;
3719
3720
0
  ret = ldb_request_add_control(req,
3721
0
              DSDB_CONTROL_CURRENT_PARTITION_OID,
3722
0
              false, p_ctrl);
3723
0
  if (ret != LDB_SUCCESS) {
3724
0
    talloc_free(tmp_ctx);
3725
0
    return ret;
3726
0
  }
3727
3728
  /* Run the new request */
3729
0
  ret = ldb_request(ldb, req);
3730
3731
0
  if (ret == LDB_SUCCESS) {
3732
0
    ret = ldb_wait(req->handle, LDB_WAIT_ALL);
3733
0
  }
3734
3735
0
  if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
3736
    /* it hasn't been created yet, which means
3737
       an implicit value of zero */
3738
0
    *uSN = 0;
3739
0
    talloc_free(tmp_ctx);
3740
0
    return LDB_SUCCESS;
3741
0
  }
3742
3743
0
  if (ret != LDB_SUCCESS) {
3744
0
    talloc_free(tmp_ctx);
3745
0
    return ret;
3746
0
  }
3747
3748
0
  if (res->count < 1) {
3749
0
    *uSN = 0;
3750
0
    if (urgent_uSN) {
3751
0
      *urgent_uSN = 0;
3752
0
    }
3753
0
  } else {
3754
0
    *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
3755
0
    if (urgent_uSN) {
3756
0
      *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
3757
0
    }
3758
0
  }
3759
3760
0
  talloc_free(tmp_ctx);
3761
3762
0
  return LDB_SUCCESS;
3763
0
}
3764
3765
int drsuapi_DsReplicaCursor2_compare(const struct drsuapi_DsReplicaCursor2 *c1,
3766
               const struct drsuapi_DsReplicaCursor2 *c2)
3767
0
{
3768
0
  return GUID_compare(&c1->source_dsa_invocation_id, &c2->source_dsa_invocation_id);
3769
0
}
3770
3771
int drsuapi_DsReplicaCursor_compare(const struct drsuapi_DsReplicaCursor *c1,
3772
            const struct drsuapi_DsReplicaCursor *c2)
3773
0
{
3774
0
  return GUID_compare(&c1->source_dsa_invocation_id, &c2->source_dsa_invocation_id);
3775
0
}
3776
3777
/*
3778
 * Return the NTDS object for a GUID, confirming it is in the
3779
 * configuration partition and a nTDSDSA object
3780
 */
3781
int samdb_get_ntds_obj_by_guid(TALLOC_CTX *mem_ctx,
3782
             struct ldb_context *sam_ctx,
3783
             const struct GUID *objectGUID,
3784
             const char **attrs,
3785
             struct ldb_message **msg)
3786
0
{
3787
0
  int ret;
3788
0
  struct ldb_result *res;
3789
0
  struct GUID_txt_buf guid_buf;
3790
0
  char *guid_str = GUID_buf_string(objectGUID, &guid_buf);
3791
0
  struct ldb_dn *config_dn = NULL;
3792
3793
0
  config_dn = ldb_get_config_basedn(sam_ctx);
3794
0
  if (config_dn == NULL) {
3795
0
    return ldb_operr(sam_ctx);
3796
0
  }
3797
3798
0
  ret = dsdb_search(sam_ctx,
3799
0
        mem_ctx,
3800
0
        &res,
3801
0
        config_dn,
3802
0
        LDB_SCOPE_SUBTREE,
3803
0
        attrs,
3804
0
        DSDB_SEARCH_ONE_ONLY,
3805
0
        "(&(objectGUID=%s)(objectClass=nTDSDSA))",
3806
0
        guid_str);
3807
0
  if (ret != LDB_SUCCESS) {
3808
0
    return ret;
3809
0
  }
3810
0
  if (msg) {
3811
0
    *msg = talloc_steal(mem_ctx, res->msgs[0]);
3812
0
  }
3813
0
  TALLOC_FREE(res);
3814
0
  return ret;
3815
0
}
3816
3817
3818
/*
3819
  see if a computer identified by its objectGUID is a RODC
3820
*/
3821
int samdb_is_rodc(struct ldb_context *sam_ctx, const struct GUID *objectGUID, bool *is_rodc)
3822
0
{
3823
  /* 1) find the DN for this servers NTDSDSA object
3824
     2) search for the msDS-isRODC attribute
3825
     3) if not present then not a RODC
3826
     4) if present and TRUE then is a RODC
3827
  */
3828
0
  const char *attrs[] = { "msDS-isRODC", NULL };
3829
0
  int ret;
3830
0
  struct ldb_message *msg;
3831
0
  TALLOC_CTX *tmp_ctx = talloc_new(sam_ctx);
3832
3833
0
  if (tmp_ctx == NULL) {
3834
0
    return ldb_oom(sam_ctx);
3835
0
  }
3836
3837
0
  ret = samdb_get_ntds_obj_by_guid(tmp_ctx,
3838
0
           sam_ctx,
3839
0
           objectGUID,
3840
0
           attrs, &msg);
3841
3842
0
  if (ret == LDB_ERR_NO_SUCH_OBJECT) {
3843
0
    *is_rodc = false;
3844
0
    talloc_free(tmp_ctx);
3845
0
    return LDB_SUCCESS;
3846
0
  }
3847
3848
0
  if (ret != LDB_SUCCESS) {
3849
0
    DEBUG(1,("Failed to find our own NTDS Settings object by objectGUID=%s!\n",
3850
0
       GUID_string(tmp_ctx, objectGUID)));
3851
0
    *is_rodc = false;
3852
0
    talloc_free(tmp_ctx);
3853
0
    return ret;
3854
0
  }
3855
3856
0
  ret = ldb_msg_find_attr_as_bool(msg, "msDS-isRODC", 0);
3857
0
  *is_rodc = (ret == 1);
3858
3859
0
  talloc_free(tmp_ctx);
3860
0
  return LDB_SUCCESS;
3861
0
}
3862
3863
3864
/*
3865
  see if we are a RODC
3866
*/
3867
int samdb_rodc(struct ldb_context *sam_ctx, bool *am_rodc)
3868
0
{
3869
0
  const struct GUID *objectGUID;
3870
0
  int ret;
3871
0
  bool *cached;
3872
3873
  /* see if we have a cached copy */
3874
0
  cached = (bool *)ldb_get_opaque(sam_ctx, "cache.am_rodc");
3875
0
  if (cached) {
3876
0
    *am_rodc = *cached;
3877
0
    return LDB_SUCCESS;
3878
0
  }
3879
3880
0
  objectGUID = samdb_ntds_objectGUID(sam_ctx);
3881
0
  if (!objectGUID) {
3882
0
    return ldb_operr(sam_ctx);
3883
0
  }
3884
3885
0
  ret = samdb_is_rodc(sam_ctx, objectGUID, am_rodc);
3886
0
  if (ret != LDB_SUCCESS) {
3887
0
    return ret;
3888
0
  }
3889
3890
0
  cached = talloc(sam_ctx, bool);
3891
0
  if (cached == NULL) {
3892
0
    return ldb_oom(sam_ctx);
3893
0
  }
3894
0
  *cached = *am_rodc;
3895
3896
0
  ret = ldb_set_opaque(sam_ctx, "cache.am_rodc", cached);
3897
0
  if (ret != LDB_SUCCESS) {
3898
0
    talloc_free(cached);
3899
0
    return ldb_operr(sam_ctx);
3900
0
  }
3901
3902
0
  return LDB_SUCCESS;
3903
0
}
3904
3905
int samdb_dns_host_name(struct ldb_context *sam_ctx, const char **host_name)
3906
0
{
3907
0
  const char *_host_name = NULL;
3908
0
  const char *attrs[] = { "dnsHostName", NULL };
3909
0
  TALLOC_CTX *tmp_ctx = NULL;
3910
0
  int ret;
3911
0
  struct ldb_result *res = NULL;
3912
3913
0
  _host_name = (const char *)ldb_get_opaque(sam_ctx, "cache.dns_host_name");
3914
0
  if (_host_name != NULL) {
3915
0
    *host_name = _host_name;
3916
0
    return LDB_SUCCESS;
3917
0
  }
3918
3919
0
  tmp_ctx = talloc_new(sam_ctx);
3920
0
  if (tmp_ctx == NULL) {
3921
0
    return ldb_oom(sam_ctx);
3922
0
  }
3923
3924
0
  ret = dsdb_search_dn(sam_ctx, tmp_ctx, &res, NULL, attrs, 0);
3925
3926
0
  if (res == NULL || res->count != 1 || ret != LDB_SUCCESS) {
3927
0
    DEBUG(0, ("Failed to get rootDSE for dnsHostName: %s\n",
3928
0
        ldb_errstring(sam_ctx)));
3929
0
    TALLOC_FREE(tmp_ctx);
3930
0
    return ret;
3931
0
  }
3932
3933
0
  _host_name = ldb_msg_find_attr_as_string(res->msgs[0],
3934
0
             "dnsHostName",
3935
0
             NULL);
3936
0
  if (_host_name == NULL) {
3937
0
    DEBUG(0, ("Failed to get dnsHostName from rootDSE\n"));
3938
0
    TALLOC_FREE(tmp_ctx);
3939
0
    return LDB_ERR_OPERATIONS_ERROR;
3940
0
  }
3941
0
  ret = ldb_set_opaque(sam_ctx, "cache.dns_host_name",
3942
0
           discard_const_p(char *, _host_name));
3943
0
  if (ret != LDB_SUCCESS) {
3944
0
    TALLOC_FREE(tmp_ctx);
3945
0
    return ldb_operr(sam_ctx);
3946
0
  }
3947
3948
0
  *host_name = talloc_steal(sam_ctx, _host_name);
3949
3950
0
  TALLOC_FREE(tmp_ctx);
3951
0
  return LDB_SUCCESS;
3952
0
}
3953
3954
bool samdb_set_am_rodc(struct ldb_context *ldb, bool am_rodc)
3955
0
{
3956
0
  TALLOC_CTX *tmp_ctx;
3957
0
  bool *cached;
3958
3959
0
  tmp_ctx = talloc_new(ldb);
3960
0
  if (tmp_ctx == NULL) {
3961
0
    goto failed;
3962
0
  }
3963
3964
0
  cached = talloc(tmp_ctx, bool);
3965
0
  if (!cached) {
3966
0
    goto failed;
3967
0
  }
3968
3969
0
  *cached = am_rodc;
3970
0
  if (ldb_set_opaque(ldb, "cache.am_rodc", cached) != LDB_SUCCESS) {
3971
0
    goto failed;
3972
0
  }
3973
3974
0
  talloc_steal(ldb, cached);
3975
0
  talloc_free(tmp_ctx);
3976
0
  return true;
3977
3978
0
failed:
3979
0
  DEBUG(1,("Failed to set our own cached am_rodc in the ldb!\n"));
3980
0
  talloc_free(tmp_ctx);
3981
0
  return false;
3982
0
}
3983
3984
3985
/*
3986
 * return NTDSSiteSettings options. See MS-ADTS 7.1.1.2.2.1.1
3987
 * flags are DS_NTDSSETTINGS_OPT_*
3988
 */
3989
int samdb_ntds_site_settings_options(struct ldb_context *ldb_ctx,
3990
          uint32_t *options)
3991
0
{
3992
0
  int rc;
3993
0
  TALLOC_CTX *tmp_ctx;
3994
0
  struct ldb_result *res;
3995
0
  struct ldb_dn *site_dn;
3996
0
  const char *attrs[] = { "options", NULL };
3997
3998
0
  tmp_ctx = talloc_new(ldb_ctx);
3999
0
  if (tmp_ctx == NULL)
4000
0
    goto failed;
4001
4002
        /* Retrieve the site dn for the ldb that we
4003
   * have open.  This is our local site.
4004
         */
4005
0
        site_dn = samdb_server_site_dn(ldb_ctx, tmp_ctx);
4006
0
  if (site_dn == NULL)
4007
0
    goto failed;
4008
4009
  /* Perform a one level (child) search from the local
4010
         * site distinguished name.   We're looking for the
4011
         * "options" attribute within the nTDSSiteSettings
4012
         * object
4013
   */
4014
0
  rc = ldb_search(ldb_ctx, tmp_ctx, &res, site_dn,
4015
0
      LDB_SCOPE_ONELEVEL, attrs,
4016
0
                        "objectClass=nTDSSiteSettings");
4017
4018
0
        if (rc != LDB_SUCCESS || res->count != 1)
4019
0
    goto failed;
4020
4021
0
  *options = ldb_msg_find_attr_as_uint(res->msgs[0], "options", 0);
4022
4023
0
  talloc_free(tmp_ctx);
4024
4025
0
  return LDB_SUCCESS;
4026
4027
0
failed:
4028
0
  DEBUG(1,("Failed to find our NTDS Site Settings options in ldb!\n"));
4029
0
  talloc_free(tmp_ctx);
4030
0
  return ldb_error(ldb_ctx, LDB_ERR_NO_SUCH_OBJECT, __func__);
4031
0
}
4032
4033
/*
4034
  return NTDS options flags. See MS-ADTS 7.1.1.2.2.1.2.1.1
4035
4036
  flags are DS_NTDS_OPTION_*
4037
*/
4038
int samdb_ntds_options(struct ldb_context *ldb, uint32_t *options)
4039
0
{
4040
0
  TALLOC_CTX *tmp_ctx;
4041
0
  const char *attrs[] = { "options", NULL };
4042
0
  int ret;
4043
0
  struct ldb_result *res;
4044
4045
0
  tmp_ctx = talloc_new(ldb);
4046
0
  if (tmp_ctx == NULL) {
4047
0
    goto failed;
4048
0
  }
4049
4050
0
  ret = ldb_search(ldb, tmp_ctx, &res, samdb_ntds_settings_dn(ldb, tmp_ctx), LDB_SCOPE_BASE, attrs, NULL);
4051
0
  if (ret != LDB_SUCCESS) {
4052
0
    goto failed;
4053
0
  }
4054
4055
0
  if (res->count != 1) {
4056
0
    goto failed;
4057
0
  }
4058
4059
0
  *options = ldb_msg_find_attr_as_uint(res->msgs[0], "options", 0);
4060
4061
0
  talloc_free(tmp_ctx);
4062
4063
0
  return LDB_SUCCESS;
4064
4065
0
failed:
4066
0
  DEBUG(1,("Failed to find our own NTDS Settings options in the ldb!\n"));
4067
0
  talloc_free(tmp_ctx);
4068
0
  return ldb_error(ldb, LDB_ERR_NO_SUCH_OBJECT, __func__);
4069
0
}
4070
4071
const char* samdb_ntds_object_category(TALLOC_CTX *tmp_ctx, struct ldb_context *ldb)
4072
0
{
4073
0
  const char *attrs[] = { "objectCategory", NULL };
4074
0
  int ret;
4075
0
  struct ldb_result *res;
4076
4077
0
  ret = ldb_search(ldb, tmp_ctx, &res, samdb_ntds_settings_dn(ldb, tmp_ctx), LDB_SCOPE_BASE, attrs, NULL);
4078
0
  if (ret != LDB_SUCCESS) {
4079
0
    goto failed;
4080
0
  }
4081
4082
0
  if (res->count != 1) {
4083
0
    goto failed;
4084
0
  }
4085
4086
0
  return ldb_msg_find_attr_as_string(res->msgs[0], "objectCategory", NULL);
4087
4088
0
failed:
4089
0
  DEBUG(1,("Failed to find our own NTDS Settings objectCategory in the ldb!\n"));
4090
0
  return NULL;
4091
0
}
4092
4093
/*
4094
 * Function which generates a "lDAPDisplayName" attribute from a "CN" one.
4095
 * Algorithm implemented according to MS-ADTS 3.1.1.2.3.4
4096
 */
4097
const char *samdb_cn_to_lDAPDisplayName(TALLOC_CTX *mem_ctx, const char *cn)
4098
0
{
4099
0
  char **tokens, *ret;
4100
0
  size_t i;
4101
4102
0
  tokens = str_list_make(mem_ctx, cn, " -_");
4103
0
  if (tokens == NULL || tokens[0] == NULL) {
4104
0
    return NULL;
4105
0
  }
4106
4107
  /* "tolower()" and "toupper()" should also work properly on 0x00 */
4108
0
  tokens[0][0] = tolower(tokens[0][0]);
4109
0
  for (i = 1; tokens[i] != NULL; i++)
4110
0
    tokens[i][0] = toupper(tokens[i][0]);
4111
4112
0
  ret = talloc_strdup(mem_ctx, tokens[0]);
4113
0
  for (i = 1; tokens[i] != NULL; i++) {
4114
0
    talloc_asprintf_addbuf(&ret, "%s", tokens[i]);
4115
0
  }
4116
4117
0
  talloc_free(tokens);
4118
4119
0
  return ret;
4120
0
}
4121
4122
/*
4123
 * This detects and returns the domain functional level (DS_DOMAIN_FUNCTION_*)
4124
 */
4125
int dsdb_functional_level(struct ldb_context *ldb)
4126
0
{
4127
0
  unsigned long long *domainFunctionality =
4128
0
    talloc_get_type(ldb_get_opaque(ldb, "domainFunctionality"), unsigned long long);
4129
0
  if (!domainFunctionality) {
4130
    /* this is expected during initial provision */
4131
0
    DEBUG(4,(__location__ ": WARNING: domainFunctionality not setup\n"));
4132
0
    return DS_DOMAIN_FUNCTION_2000;
4133
0
  }
4134
0
  return *domainFunctionality;
4135
0
}
4136
4137
/*
4138
 * This detects and returns the forest functional level (DS_DOMAIN_FUNCTION_*)
4139
 */
4140
int dsdb_forest_functional_level(struct ldb_context *ldb)
4141
0
{
4142
0
  unsigned long long *forestFunctionality =
4143
0
    talloc_get_type(ldb_get_opaque(ldb, "forestFunctionality"), unsigned long long);
4144
0
  if (!forestFunctionality) {
4145
0
    DEBUG(0,(__location__ ": WARNING: forestFunctionality not setup\n"));
4146
0
    return DS_DOMAIN_FUNCTION_2000;
4147
0
  }
4148
0
  return *forestFunctionality;
4149
0
}
4150
4151
/*
4152
 * This detects and returns the DC functional level (DS_DOMAIN_FUNCTION_*)
4153
 */
4154
int dsdb_dc_functional_level(struct ldb_context *ldb)
4155
0
{
4156
0
  unsigned long long *dcFunctionality =
4157
0
    talloc_get_type(ldb_get_opaque(ldb, "domainControllerFunctionality"), unsigned long long);
4158
0
  if (!dcFunctionality) {
4159
    /* this is expected during initial provision */
4160
0
    DEBUG(4,(__location__ ": WARNING: domainControllerFunctionality not setup\n"));
4161
0
    return DS_DOMAIN_FUNCTION_2008_R2;
4162
0
  }
4163
0
  return *dcFunctionality;
4164
0
}
4165
4166
const char *dsdb_dc_operatingSystemVersion(int dc_functional_level)
4167
0
{
4168
0
  const char *operatingSystemVersion = NULL;
4169
4170
  /*
4171
   * While we are there also update
4172
   * operatingSystem and operatingSystemVersion
4173
   * as at least operatingSystemVersion is really
4174
   * important for some clients/applications (like exchange).
4175
   */
4176
4177
0
  if (dc_functional_level >= DS_DOMAIN_FUNCTION_2016) {
4178
    /* Pretend Windows 2016 */
4179
0
    operatingSystemVersion = "10.0 (14393)";
4180
0
  } else if (dc_functional_level >= DS_DOMAIN_FUNCTION_2012_R2) {
4181
    /* Pretend Windows 2012 R2 */
4182
0
    operatingSystemVersion = "6.3 (9600)";
4183
0
  } else if (dc_functional_level >= DS_DOMAIN_FUNCTION_2012) {
4184
    /* Pretend Windows 2012 */
4185
0
    operatingSystemVersion = "6.2 (9200)";
4186
0
  } else {
4187
    /* Pretend Windows 2008 R2 */
4188
0
    operatingSystemVersion = "6.1 (7600)";
4189
0
  }
4190
4191
0
  return operatingSystemVersion;
4192
0
}
4193
4194
int dsdb_check_and_update_fl(struct ldb_context *ldb_ctx, struct loadparm_context *lp_ctx)
4195
0
{
4196
0
  TALLOC_CTX *frame = talloc_stackframe();
4197
0
  int ret;
4198
4199
0
  int db_dc_functional_level;
4200
0
  int db_domain_functional_level;
4201
0
  int db_forest_functional_level;
4202
0
  int lp_dc_functional_level = lpcfg_ad_dc_functional_level(lp_ctx);
4203
0
  bool am_rodc;
4204
0
  struct ldb_message *msg = NULL;
4205
0
  struct ldb_dn *dc_ntds_settings_dn = NULL;
4206
0
  struct ldb_dn *dc_computer_dn = NULL;
4207
0
  const char *operatingSystem = NULL;
4208
0
  const char *operatingSystemVersion = NULL;
4209
4210
0
  db_dc_functional_level = dsdb_dc_functional_level(ldb_ctx);
4211
0
  db_domain_functional_level = dsdb_functional_level(ldb_ctx);
4212
0
  db_forest_functional_level = dsdb_forest_functional_level(ldb_ctx);
4213
4214
0
  if (lp_dc_functional_level < db_domain_functional_level) {
4215
0
    DBG_ERR("Refusing to start as smb.conf 'ad dc functional level' maps to %d, "
4216
0
      "which is less than the domain functional level of %d\n",
4217
0
      lp_dc_functional_level, db_domain_functional_level);
4218
0
    TALLOC_FREE(frame);
4219
0
    return LDB_ERR_CONSTRAINT_VIOLATION;
4220
0
  }
4221
4222
0
  if (lp_dc_functional_level < db_forest_functional_level) {
4223
0
    DBG_ERR("Refusing to start as smb.conf 'ad dc functional level' maps to %d, "
4224
0
      "which is less than the forest functional level of %d\n",
4225
0
      lp_dc_functional_level, db_forest_functional_level);
4226
0
    TALLOC_FREE(frame);
4227
0
    return LDB_ERR_CONSTRAINT_VIOLATION;
4228
0
  }
4229
4230
  /* Check if we need to update the DB */
4231
0
  if (db_dc_functional_level == lp_dc_functional_level) {
4232
    /*
4233
     * Note that this early return means
4234
     * we're not updating operatingSystem and
4235
     * operatingSystemVersion.
4236
     *
4237
     * But at least for now that's
4238
     * exactly what we want.
4239
     */
4240
0
    TALLOC_FREE(frame);
4241
0
    return LDB_SUCCESS;
4242
0
  }
4243
4244
  /* Confirm we are not an RODC before we try a modify */
4245
0
  ret = samdb_rodc(ldb_ctx, &am_rodc);
4246
0
  if (ret != LDB_SUCCESS) {
4247
0
    DBG_ERR("Failed to determine if this server is an RODC\n");
4248
0
    TALLOC_FREE(frame);
4249
0
    return ret;
4250
0
  }
4251
4252
0
  if (am_rodc) {
4253
0
    DBG_WARNING("Unable to update DC's msDS-Behavior-Version "
4254
0
          "(from %d to %d) and operatingSystem[Version] "
4255
0
          "as we are an RODC\n",
4256
0
          db_dc_functional_level, lp_dc_functional_level);
4257
0
    TALLOC_FREE(frame);
4258
0
    return LDB_SUCCESS;
4259
0
  }
4260
4261
0
  dc_ntds_settings_dn = samdb_ntds_settings_dn(ldb_ctx, frame);
4262
4263
0
  if (dc_ntds_settings_dn == NULL) {
4264
0
    DBG_ERR("Failed to find own NTDS Settings DN\n");
4265
0
    TALLOC_FREE(frame);
4266
0
    return LDB_ERR_NO_SUCH_OBJECT;
4267
0
  }
4268
4269
  /* Now update our msDS-Behavior-Version */
4270
4271
0
  msg = ldb_msg_new(frame);
4272
0
  if (msg == NULL) {
4273
0
    DBG_ERR("Failed to allocate message to update msDS-Behavior-Version\n");
4274
0
    TALLOC_FREE(frame);
4275
0
    return LDB_ERR_OPERATIONS_ERROR;
4276
0
  }
4277
4278
0
  msg->dn = dc_ntds_settings_dn;
4279
4280
0
  ret = samdb_msg_add_int(ldb_ctx, frame, msg, "msDS-Behavior-Version", lp_dc_functional_level);
4281
0
  if (ret != LDB_SUCCESS) {
4282
0
    DBG_ERR("Failed to set new msDS-Behavior-Version on message\n");
4283
0
    TALLOC_FREE(frame);
4284
0
    return LDB_ERR_OPERATIONS_ERROR;
4285
0
  }
4286
4287
0
  ret = dsdb_replace(ldb_ctx, msg, 0);
4288
0
  if (ret != LDB_SUCCESS) {
4289
0
    DBG_ERR("Failed to update DB with new msDS-Behavior-Version on %s: %s\n",
4290
0
      ldb_dn_get_linearized(dc_ntds_settings_dn),
4291
0
      ldb_errstring(ldb_ctx));
4292
0
    TALLOC_FREE(frame);
4293
0
    return ret;
4294
0
  }
4295
4296
  /*
4297
   * We have to update the opaque because this particular ldb_context
4298
   * will not re-read the DB
4299
   */
4300
0
  {
4301
0
    unsigned long long *val = talloc(ldb_ctx, unsigned long long);
4302
0
    if (!val) {
4303
0
      TALLOC_FREE(frame);
4304
0
      return LDB_ERR_OPERATIONS_ERROR;
4305
0
    }
4306
0
    *val = lp_dc_functional_level;
4307
0
    ret = ldb_set_opaque(ldb_ctx,
4308
0
             "domainControllerFunctionality", val);
4309
0
    if (ret != LDB_SUCCESS) {
4310
0
      DBG_ERR("Failed to re-set domainControllerFunctionality opaque\n");
4311
0
      TALLOC_FREE(val);
4312
0
      TALLOC_FREE(frame);
4313
0
      return ret;
4314
0
    }
4315
0
  }
4316
4317
  /*
4318
   * While we are there also update
4319
   * operatingSystem and operatingSystemVersion
4320
   * as at least operatingSystemVersion is really
4321
   * important for some clients/applications (like exchange).
4322
   */
4323
4324
0
  operatingSystem = talloc_asprintf(frame, "Samba-%s",
4325
0
            samba_version_string());
4326
0
  if (operatingSystem == NULL) {
4327
0
    TALLOC_FREE(frame);
4328
0
    return ldb_oom(ldb_ctx);
4329
0
  }
4330
4331
0
  operatingSystemVersion = dsdb_dc_operatingSystemVersion(db_dc_functional_level);
4332
4333
0
  ret = samdb_server_reference_dn(ldb_ctx, frame, &dc_computer_dn);
4334
0
  if (ret != LDB_SUCCESS) {
4335
0
    DBG_ERR("Failed to get the dc_computer_dn: %s\n",
4336
0
      ldb_errstring(ldb_ctx));
4337
0
    TALLOC_FREE(frame);
4338
0
    return ret;
4339
0
  }
4340
4341
0
  msg = ldb_msg_new(frame);
4342
0
  if (msg == NULL) {
4343
0
    DBG_ERR("Failed to allocate message to update msDS-Behavior-Version\n");
4344
0
    TALLOC_FREE(frame);
4345
0
    return LDB_ERR_OPERATIONS_ERROR;
4346
0
  }
4347
4348
0
  msg->dn = dc_computer_dn;
4349
4350
0
  ret = samdb_msg_add_addval(ldb_ctx, frame, msg,
4351
0
           "operatingSystem",
4352
0
           operatingSystem);
4353
0
  if (ret != LDB_SUCCESS) {
4354
0
    DBG_ERR("Failed to set new operatingSystem on message\n");
4355
0
    TALLOC_FREE(frame);
4356
0
    return ldb_operr(ldb_ctx);
4357
0
  }
4358
4359
0
  ret = samdb_msg_add_addval(ldb_ctx, frame, msg,
4360
0
           "operatingSystemVersion",
4361
0
           operatingSystemVersion);
4362
0
  if (ret != LDB_SUCCESS) {
4363
0
    DBG_ERR("Failed to set new operatingSystemVersion on message\n");
4364
0
    TALLOC_FREE(frame);
4365
0
    return ldb_operr(ldb_ctx);
4366
0
  }
4367
4368
0
  ret = dsdb_replace(ldb_ctx, msg, 0);
4369
0
  if (ret != LDB_SUCCESS) {
4370
0
    DBG_ERR("Failed to update DB with new operatingSystem[Version] on %s: %s\n",
4371
0
      ldb_dn_get_linearized(dc_computer_dn),
4372
0
      ldb_errstring(ldb_ctx));
4373
0
    TALLOC_FREE(frame);
4374
0
    return ret;
4375
0
  }
4376
4377
0
  TALLOC_FREE(frame);
4378
0
  return LDB_SUCCESS;
4379
0
}
4380
4381
4382
/*
4383
  set a GUID in an extended DN structure
4384
 */
4385
int dsdb_set_extended_dn_guid(struct ldb_dn *dn, const struct GUID *guid, const char *component_name)
4386
0
{
4387
0
  struct ldb_val v;
4388
0
  NTSTATUS status;
4389
0
  int ret;
4390
4391
0
  status = GUID_to_ndr_blob(guid, dn, &v);
4392
0
  if (!NT_STATUS_IS_OK(status)) {
4393
0
    return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
4394
0
  }
4395
4396
0
  ret = ldb_dn_set_extended_component(dn, component_name, &v);
4397
0
  data_blob_free(&v);
4398
0
  return ret;
4399
0
}
4400
4401
/*
4402
  return a GUID from a extended DN structure
4403
 */
4404
NTSTATUS dsdb_get_extended_dn_guid(struct ldb_dn *dn, struct GUID *guid, const char *component_name)
4405
0
{
4406
0
  const struct ldb_val *v;
4407
4408
0
  v = ldb_dn_get_extended_component(dn, component_name);
4409
0
  if (v == NULL) {
4410
0
    return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4411
0
  }
4412
4413
0
  return GUID_from_ndr_blob(v, guid);
4414
0
}
4415
4416
/*
4417
  return a uint64_t from a extended DN structure
4418
 */
4419
NTSTATUS dsdb_get_extended_dn_uint64(struct ldb_dn *dn, uint64_t *val, const char *component_name)
4420
0
{
4421
0
  const struct ldb_val *v;
4422
0
  int error = 0;
4423
4424
0
  v = ldb_dn_get_extended_component(dn, component_name);
4425
0
  if (v == NULL) {
4426
0
    return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4427
0
  }
4428
4429
  /* Just check we don't allow the caller to fill our stack */
4430
0
  if (v->length >= 64) {
4431
0
    return NT_STATUS_INVALID_PARAMETER;
4432
0
  } else {
4433
0
    char s[v->length+1];
4434
0
    memcpy(s, v->data, v->length);
4435
0
    s[v->length] = 0;
4436
4437
0
    *val = smb_strtoull(s, NULL, 0, &error, SMB_STR_STANDARD);
4438
0
    if (error != 0) {
4439
0
      return NT_STATUS_INVALID_PARAMETER;
4440
0
    }
4441
0
  }
4442
0
  return NT_STATUS_OK;
4443
0
}
4444
4445
/*
4446
  return a NTTIME from a extended DN structure
4447
 */
4448
NTSTATUS dsdb_get_extended_dn_nttime(struct ldb_dn *dn, NTTIME *nttime, const char *component_name)
4449
0
{
4450
0
  return dsdb_get_extended_dn_uint64(dn, nttime, component_name);
4451
0
}
4452
4453
/*
4454
  return a uint32_t from a extended DN structure
4455
 */
4456
NTSTATUS dsdb_get_extended_dn_uint32(struct ldb_dn *dn, uint32_t *val, const char *component_name)
4457
0
{
4458
0
  const struct ldb_val *v;
4459
0
  int error = 0;
4460
4461
0
  v = ldb_dn_get_extended_component(dn, component_name);
4462
0
  if (v == NULL) {
4463
0
    return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4464
0
  }
4465
4466
  /* Just check we don't allow the caller to fill our stack */
4467
0
  if (v->length >= 32) {
4468
0
    return NT_STATUS_INVALID_PARAMETER;
4469
0
  } else {
4470
0
    char s[v->length + 1];
4471
0
    memcpy(s, v->data, v->length);
4472
0
    s[v->length] = 0;
4473
0
    *val = smb_strtoul(s, NULL, 0, &error, SMB_STR_STANDARD);
4474
0
    if (error != 0) {
4475
0
      return NT_STATUS_INVALID_PARAMETER;
4476
0
    }
4477
0
  }
4478
4479
0
  return NT_STATUS_OK;
4480
0
}
4481
4482
/*
4483
  return a dom_sid from a extended DN structure
4484
 */
4485
NTSTATUS dsdb_get_extended_dn_sid(struct ldb_dn *dn, struct dom_sid *sid, const char *component_name)
4486
0
{
4487
0
  const struct ldb_val *sid_blob;
4488
0
  enum ndr_err_code ndr_err;
4489
4490
0
  sid_blob = ldb_dn_get_extended_component(dn, component_name);
4491
0
  if (!sid_blob) {
4492
0
    return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4493
0
  }
4494
4495
0
  ndr_err = ndr_pull_struct_blob_all_noalloc(sid_blob, sid,
4496
0
               (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
4497
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4498
0
    NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
4499
0
    return status;
4500
0
  }
4501
4502
0
  return NT_STATUS_OK;
4503
0
}
4504
4505
4506
/*
4507
  return RMD_FLAGS directly from a ldb_dn
4508
  returns 0 if not found
4509
 */
4510
uint32_t dsdb_dn_rmd_flags(struct ldb_dn *dn)
4511
0
{
4512
0
  uint32_t rmd_flags = 0;
4513
0
  NTSTATUS status = dsdb_get_extended_dn_uint32(dn, &rmd_flags,
4514
0
                  "RMD_FLAGS");
4515
0
  if (NT_STATUS_IS_OK(status)) {
4516
0
    return rmd_flags;
4517
0
  }
4518
0
  return 0;
4519
0
}
4520
4521
/*
4522
  return RMD_FLAGS directly from a ldb_val for a DN
4523
  returns 0 if RMD_FLAGS is not found
4524
 */
4525
uint32_t dsdb_dn_val_rmd_flags(const struct ldb_val *val)
4526
0
{
4527
0
  const char *p;
4528
0
  uint32_t flags;
4529
0
  char *end;
4530
0
  int error = 0;
4531
4532
0
  if (val->length < 13) {
4533
0
    return 0;
4534
0
  }
4535
0
  p = memmem(val->data, val->length, "<RMD_FLAGS=", 11);
4536
0
  if (!p) {
4537
0
    return 0;
4538
0
  }
4539
0
  flags = smb_strtoul(p+11, &end, 10, &error, SMB_STR_STANDARD);
4540
0
  if (!end || *end != '>' || error != 0) {
4541
    /* it must end in a > */
4542
0
    return 0;
4543
0
  }
4544
0
  return flags;
4545
0
}
4546
4547
/*
4548
  return true if a ldb_val containing a DN in storage form is deleted
4549
 */
4550
bool dsdb_dn_is_deleted_val(const struct ldb_val *val)
4551
0
{
4552
0
  return (dsdb_dn_val_rmd_flags(val) & DSDB_RMD_FLAG_DELETED) != 0;
4553
0
}
4554
4555
/*
4556
  return true if a ldb_val containing a DN in storage form is
4557
  in the upgraded w2k3 linked attribute format
4558
 */
4559
bool dsdb_dn_is_upgraded_link_val(const struct ldb_val *val)
4560
0
{
4561
0
  return memmem(val->data, val->length, "<RMD_VERSION=", 13) != NULL;
4562
0
}
4563
4564
/*
4565
  return a DN for a wellknown GUID
4566
 */
4567
int dsdb_wellknown_dn(struct ldb_context *samdb, TALLOC_CTX *mem_ctx,
4568
          struct ldb_dn *nc_root, const char *wk_guid,
4569
          struct ldb_dn **wkguid_dn)
4570
0
{
4571
0
  TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4572
0
  const char *attrs[] = { NULL };
4573
0
  int ret;
4574
0
  struct ldb_dn *dn;
4575
0
  struct ldb_result *res = NULL;
4576
4577
0
  if (tmp_ctx == NULL) {
4578
0
    return ldb_oom(samdb);
4579
0
  }
4580
4581
  /* construct the magic WKGUID DN */
4582
0
  dn = ldb_dn_new_fmt(tmp_ctx, samdb, "<WKGUID=%s,%s>",
4583
0
          wk_guid, ldb_dn_get_linearized(nc_root));
4584
0
  if (!wkguid_dn) {
4585
0
    talloc_free(tmp_ctx);
4586
0
    return ldb_operr(samdb);
4587
0
  }
4588
4589
0
  ret = dsdb_search_dn(samdb, tmp_ctx, &res, dn, attrs,
4590
0
           DSDB_SEARCH_SHOW_DELETED |
4591
0
           DSDB_SEARCH_SHOW_RECYCLED);
4592
0
  if (ret != LDB_SUCCESS) {
4593
0
    talloc_free(tmp_ctx);
4594
0
    return ret;
4595
0
  }
4596
  /* fix clang warning */
4597
0
  if (res == NULL){
4598
0
    talloc_free(tmp_ctx);
4599
0
    return LDB_ERR_OTHER;
4600
0
  }
4601
4602
0
  (*wkguid_dn) = talloc_steal(mem_ctx, res->msgs[0]->dn);
4603
0
  talloc_free(tmp_ctx);
4604
0
  return LDB_SUCCESS;
4605
0
}
4606
4607
4608
static int dsdb_dn_compare_ptrs(struct ldb_dn **dn1, struct ldb_dn **dn2)
4609
0
{
4610
0
  return ldb_dn_compare(*dn1, *dn2);
4611
0
}
4612
4613
/*
4614
  find a NC root given a DN within the NC by reading the rootDSE namingContexts
4615
 */
4616
static int dsdb_find_nc_root_string_based(struct ldb_context *samdb,
4617
            TALLOC_CTX *mem_ctx,
4618
            struct ldb_dn *dn,
4619
            struct ldb_dn **nc_root)
4620
0
{
4621
0
  const char *root_attrs[] = { "namingContexts", NULL };
4622
0
  TALLOC_CTX *tmp_ctx;
4623
0
  int ret;
4624
0
  struct ldb_message_element *el;
4625
0
  struct ldb_result *root_res;
4626
0
  unsigned int i;
4627
0
  struct ldb_dn **nc_dns;
4628
4629
0
  tmp_ctx = talloc_new(samdb);
4630
0
  if (tmp_ctx == NULL) {
4631
0
    return ldb_oom(samdb);
4632
0
  }
4633
4634
0
  ret = ldb_search(samdb, tmp_ctx, &root_res,
4635
0
       ldb_dn_new(tmp_ctx, samdb, ""), LDB_SCOPE_BASE, root_attrs, NULL);
4636
0
  if (ret != LDB_SUCCESS || root_res->count == 0) {
4637
0
    DEBUG(1,("Searching for namingContexts in rootDSE failed: %s\n", ldb_errstring(samdb)));
4638
0
    talloc_free(tmp_ctx);
4639
0
    return ret;
4640
0
  }
4641
4642
0
  el = ldb_msg_find_element(root_res->msgs[0], "namingContexts");
4643
0
  if ((el == NULL) || (el->num_values < 3)) {
4644
0
    struct ldb_message *tmp_msg;
4645
4646
0
    DEBUG(5,("dsdb_find_nc_root: Finding a valid 'namingContexts' element in the RootDSE failed. Using a temporary list.\n"));
4647
4648
    /* This generates a temporary list of NCs in order to let the
4649
     * provisioning work. */
4650
0
    tmp_msg = ldb_msg_new(tmp_ctx);
4651
0
    if (tmp_msg == NULL) {
4652
0
      talloc_free(tmp_ctx);
4653
0
      return ldb_oom(samdb);
4654
0
    }
4655
0
    ret = ldb_msg_add_steal_string(tmp_msg, "namingContexts",
4656
0
                 ldb_dn_alloc_linearized(tmp_msg, ldb_get_schema_basedn(samdb)));
4657
0
    if (ret != LDB_SUCCESS) {
4658
0
      talloc_free(tmp_ctx);
4659
0
      return ret;
4660
0
    }
4661
0
    ret = ldb_msg_add_steal_string(tmp_msg, "namingContexts",
4662
0
                 ldb_dn_alloc_linearized(tmp_msg, ldb_get_config_basedn(samdb)));
4663
0
    if (ret != LDB_SUCCESS) {
4664
0
      talloc_free(tmp_ctx);
4665
0
      return ret;
4666
0
    }
4667
0
    ret = ldb_msg_add_steal_string(tmp_msg, "namingContexts",
4668
0
                 ldb_dn_alloc_linearized(tmp_msg, ldb_get_default_basedn(samdb)));
4669
0
    if (ret != LDB_SUCCESS) {
4670
0
      talloc_free(tmp_ctx);
4671
0
      return ret;
4672
0
    }
4673
0
    el = &tmp_msg->elements[0];
4674
0
  }
4675
4676
0
       nc_dns = talloc_array(tmp_ctx, struct ldb_dn *, el->num_values);
4677
0
       if (!nc_dns) {
4678
0
         talloc_free(tmp_ctx);
4679
0
         return ldb_oom(samdb);
4680
0
       }
4681
4682
0
       for (i=0; i<el->num_values; i++) {
4683
0
         nc_dns[i] = ldb_dn_from_ldb_val(nc_dns, samdb, &el->values[i]);
4684
0
         if (nc_dns[i] == NULL) {
4685
0
           talloc_free(tmp_ctx);
4686
0
           return ldb_operr(samdb);
4687
0
         }
4688
0
       }
4689
4690
0
       TYPESAFE_QSORT(nc_dns, el->num_values, dsdb_dn_compare_ptrs);
4691
4692
0
       for (i=0; i<el->num_values; i++) {
4693
0
               if (ldb_dn_compare_base(nc_dns[i], dn) == 0) {
4694
0
           (*nc_root) = talloc_steal(mem_ctx, nc_dns[i]);
4695
0
                       talloc_free(tmp_ctx);
4696
0
                       return LDB_SUCCESS;
4697
0
               }
4698
0
       }
4699
4700
0
       talloc_free(tmp_ctx);
4701
0
       return ldb_error(samdb, LDB_ERR_NO_SUCH_OBJECT, __func__);
4702
0
}
4703
4704
struct dsdb_get_partition_and_dn {
4705
  TALLOC_CTX *mem_ctx;
4706
  unsigned int count;
4707
  struct ldb_dn *dn;
4708
  struct ldb_dn *partition_dn;
4709
  bool want_partition_dn;
4710
};
4711
4712
static int dsdb_get_partition_and_dn(struct ldb_request *req,
4713
             struct ldb_reply *ares)
4714
0
{
4715
0
  int ret;
4716
0
  struct dsdb_get_partition_and_dn *context = req->context;
4717
0
  struct ldb_control *partition_ctrl = NULL;
4718
0
  struct dsdb_control_current_partition *partition = NULL;
4719
4720
0
  if (!ares) {
4721
0
    return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
4722
0
  }
4723
0
  if (ares->error != LDB_SUCCESS
4724
0
      && ares->error != LDB_ERR_NO_SUCH_OBJECT) {
4725
0
    return ldb_request_done(req, ares->error);
4726
0
  }
4727
4728
0
  switch (ares->type) {
4729
0
  case LDB_REPLY_ENTRY:
4730
0
    if (context->count != 0) {
4731
0
      return ldb_request_done(req,
4732
0
            LDB_ERR_CONSTRAINT_VIOLATION);
4733
0
    }
4734
0
    context->count++;
4735
4736
0
    context->dn = talloc_steal(context->mem_ctx,
4737
0
             ares->message->dn);
4738
0
    break;
4739
4740
0
  case LDB_REPLY_REFERRAL:
4741
0
    talloc_free(ares);
4742
0
    return ldb_request_done(req, LDB_SUCCESS);
4743
4744
0
  case LDB_REPLY_DONE:
4745
0
    partition_ctrl
4746
0
      = ldb_reply_get_control(ares,
4747
0
            DSDB_CONTROL_CURRENT_PARTITION_OID);
4748
0
    if (!context->want_partition_dn ||
4749
0
      partition_ctrl == NULL) {
4750
0
      ret = ares->error;
4751
0
      talloc_free(ares);
4752
4753
0
      return ldb_request_done(req, ret);
4754
0
    }
4755
4756
0
    partition
4757
0
      = talloc_get_type_abort(partition_ctrl->data,
4758
0
            struct dsdb_control_current_partition);
4759
0
    context->partition_dn
4760
0
      = ldb_dn_copy(context->mem_ctx, partition->dn);
4761
0
    if (context->partition_dn == NULL) {
4762
0
      return ldb_request_done(req,
4763
0
            LDB_ERR_OPERATIONS_ERROR);
4764
0
    }
4765
4766
0
    ret = ares->error;
4767
0
    talloc_free(ares);
4768
4769
0
    return ldb_request_done(req, ret);
4770
0
  }
4771
4772
0
  talloc_free(ares);
4773
0
  return LDB_SUCCESS;
4774
0
}
4775
4776
/*
4777
  find a NC root given a DN within the NC
4778
 */
4779
int dsdb_normalise_dn_and_find_nc_root(struct ldb_context *samdb,
4780
               TALLOC_CTX *mem_ctx,
4781
               struct ldb_dn *dn,
4782
               struct ldb_dn **normalised_dn,
4783
               struct ldb_dn **nc_root)
4784
0
{
4785
0
  TALLOC_CTX *tmp_ctx;
4786
0
  int ret;
4787
0
  struct ldb_request *req;
4788
0
  struct ldb_result *res;
4789
0
  struct ldb_dn *search_dn = dn;
4790
0
  static const char * attrs[] = { NULL };
4791
0
  bool has_extended = ldb_dn_has_extended(dn);
4792
0
  bool has_normal_components = ldb_dn_get_comp_num(dn) >= 1;
4793
0
  struct dsdb_get_partition_and_dn context = {
4794
0
    .mem_ctx = mem_ctx,
4795
0
    .want_partition_dn = nc_root != NULL
4796
0
  };
4797
4798
0
  if (!has_extended && !has_normal_components) {
4799
0
    return ldb_error(samdb, LDB_ERR_NO_SUCH_OBJECT,
4800
0
         "Request for NC root for rootDSE (\"\") denied.");
4801
0
  }
4802
4803
0
  tmp_ctx = talloc_new(samdb);
4804
0
  if (tmp_ctx == NULL) {
4805
0
    return ldb_oom(samdb);
4806
0
  }
4807
4808
0
  res = talloc_zero(tmp_ctx, struct ldb_result);
4809
0
  if (res == NULL) {
4810
0
    talloc_free(tmp_ctx);
4811
0
    return ldb_oom(samdb);
4812
0
  }
4813
4814
0
  if (has_extended && has_normal_components) {
4815
0
    bool minimise_ok;
4816
0
    search_dn = ldb_dn_copy(tmp_ctx, dn);
4817
0
    if (search_dn == NULL) {
4818
0
      talloc_free(tmp_ctx);
4819
0
      return ldb_oom(samdb);
4820
0
    }
4821
0
    minimise_ok = ldb_dn_minimise(search_dn);
4822
0
    if (!minimise_ok) {
4823
0
      talloc_free(tmp_ctx);
4824
0
      return ldb_operr(samdb);
4825
0
    }
4826
0
  }
4827
4828
0
  ret = ldb_build_search_req(&req, samdb, tmp_ctx,
4829
0
           search_dn,
4830
0
           LDB_SCOPE_BASE,
4831
0
           NULL,
4832
0
           attrs,
4833
0
           NULL,
4834
0
           &context,
4835
0
           dsdb_get_partition_and_dn,
4836
0
           NULL);
4837
0
  if (ret != LDB_SUCCESS) {
4838
0
    talloc_free(tmp_ctx);
4839
0
    return ret;
4840
0
  }
4841
4842
0
  ret = ldb_request_add_control(req,
4843
0
              DSDB_CONTROL_CURRENT_PARTITION_OID,
4844
0
              false, NULL);
4845
0
  if (ret != LDB_SUCCESS) {
4846
0
    talloc_free(tmp_ctx);
4847
0
    return ret;
4848
0
  }
4849
4850
0
  ret = dsdb_request_add_controls(req,
4851
0
          DSDB_SEARCH_SHOW_RECYCLED|
4852
0
          DSDB_SEARCH_SHOW_DELETED|
4853
0
          DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT);
4854
0
  if (ret != LDB_SUCCESS) {
4855
0
    talloc_free(tmp_ctx);
4856
0
    return ret;
4857
0
  }
4858
4859
0
  ret = ldb_request(samdb, req);
4860
0
  if (ret == LDB_SUCCESS) {
4861
0
    ret = ldb_wait(req->handle, LDB_WAIT_ALL);
4862
0
  }
4863
4864
  /*
4865
   * This could be a new DN, not in the DB, which is OK.  If we
4866
   * don't need the normalised DN, we can continue.
4867
   *
4868
   * We may be told the partition it would be in in the search
4869
   * reply control, or if not we can do a string-based match.
4870
   */
4871
4872
0
  if (ret == LDB_ERR_NO_SUCH_OBJECT) {
4873
0
    if (normalised_dn != NULL) {
4874
0
      talloc_free(tmp_ctx);
4875
0
      return ret;
4876
0
    }
4877
0
    ret = LDB_SUCCESS;
4878
0
    ldb_reset_err_string(samdb);
4879
0
  } else if (ret != LDB_SUCCESS) {
4880
0
    talloc_free(tmp_ctx);
4881
0
    return ret;
4882
0
  }
4883
4884
0
  if (normalised_dn != NULL) {
4885
0
    if (context.count != 1) {
4886
      /* No results */
4887
0
      ldb_asprintf_errstring(samdb,
4888
0
                 "Request for NC root for %s failed to return any results.",
4889
0
                 ldb_dn_get_linearized(dn));
4890
0
      talloc_free(tmp_ctx);
4891
0
      return LDB_ERR_NO_SUCH_OBJECT;
4892
0
    }
4893
0
    *normalised_dn = context.dn;
4894
0
  }
4895
4896
  /*
4897
   * If the user did not need to find the nc_root,
4898
   * we are done
4899
   */
4900
0
  if (nc_root == NULL) {
4901
0
    talloc_free(tmp_ctx);
4902
0
    return ret;
4903
0
  }
4904
4905
  /*
4906
   * When we are working locally, both for the case were
4907
   * we find the DN, and the case where we fail, we get
4908
   * back via controls the partition it was in or should
4909
   * have been in, to return to the client
4910
   */
4911
0
  if (context.partition_dn != NULL) {
4912
0
    (*nc_root) = context.partition_dn;
4913
4914
0
    talloc_free(tmp_ctx);
4915
0
    return ret;
4916
0
  }
4917
4918
  /*
4919
   * This is a remote operation, which is a little harder as we
4920
   * have a work out the nc_root from the list of NCs. If we did
4921
   * at least resolve the DN to a string, get that now, it makes
4922
   * the string-based match below possible for a GUID-based
4923
   * input over remote LDAP.
4924
   */
4925
0
  if (context.dn) {
4926
0
    dn = context.dn;
4927
0
  } else if (has_extended && !has_normal_components) {
4928
0
    ldb_asprintf_errstring(samdb,
4929
0
               "Cannot determine NC root "
4930
0
               "for a not-found bare extended DN %s.",
4931
0
               ldb_dn_get_extended_linearized(tmp_ctx, dn, 1));
4932
0
    talloc_free(tmp_ctx);
4933
0
    return LDB_ERR_NO_SUCH_OBJECT;
4934
0
  }
4935
4936
  /*
4937
   * Either we are working against a remote LDAP
4938
   * server or the object doesn't exist locally.
4939
   *
4940
   * This means any GUID that was present in the DN
4941
   * therefore could not be evaluated, so do a
4942
   * string-based match instead.
4943
   */
4944
0
  talloc_free(tmp_ctx);
4945
0
  return dsdb_find_nc_root_string_based(samdb,
4946
0
                mem_ctx,
4947
0
                dn,
4948
0
                nc_root);
4949
0
}
4950
4951
/*
4952
  find a NC root given a DN within the NC
4953
 */
4954
int dsdb_find_nc_root(struct ldb_context *samdb,
4955
          TALLOC_CTX *mem_ctx,
4956
          struct ldb_dn *dn,
4957
          struct ldb_dn **nc_root)
4958
0
{
4959
0
  return dsdb_normalise_dn_and_find_nc_root(samdb,
4960
0
              mem_ctx,
4961
0
              dn,
4962
0
              NULL,
4963
0
              nc_root);
4964
0
}
4965
4966
/*
4967
  find the deleted objects DN for any object, by looking for the NC
4968
  root, then looking up the wellknown GUID
4969
 */
4970
int dsdb_get_deleted_objects_dn(struct ldb_context *ldb,
4971
        TALLOC_CTX *mem_ctx, struct ldb_dn *obj_dn,
4972
        struct ldb_dn **do_dn)
4973
0
{
4974
0
  struct ldb_dn *nc_root;
4975
0
  int ret;
4976
4977
0
  ret = dsdb_find_nc_root(ldb, mem_ctx, obj_dn, &nc_root);
4978
0
  if (ret != LDB_SUCCESS) {
4979
0
    return ret;
4980
0
  }
4981
4982
0
  ret = dsdb_wellknown_dn(ldb, mem_ctx, nc_root, DS_GUID_DELETED_OBJECTS_CONTAINER, do_dn);
4983
0
  talloc_free(nc_root);
4984
0
  return ret;
4985
0
}
4986
4987
/*
4988
  return the tombstoneLifetime, in days
4989
 */
4990
int dsdb_tombstone_lifetime(struct ldb_context *ldb, uint32_t *lifetime)
4991
0
{
4992
0
  struct ldb_dn *dn;
4993
0
  dn = ldb_get_config_basedn(ldb);
4994
0
  if (!dn) {
4995
0
    return ldb_error(ldb, LDB_ERR_NO_SUCH_OBJECT, __func__);
4996
0
  }
4997
0
  dn = ldb_dn_copy(ldb, dn);
4998
0
  if (!dn) {
4999
0
    return ldb_operr(ldb);
5000
0
  }
5001
  /* see MS-ADTS section 7.1.1.2.4.1.1. There doesn't appear to
5002
   be a wellknown GUID for this */
5003
0
  if (!ldb_dn_add_child_fmt(dn, "CN=Directory Service,CN=Windows NT,CN=Services")) {
5004
0
    talloc_free(dn);
5005
0
    return ldb_operr(ldb);
5006
0
  }
5007
5008
0
  *lifetime = samdb_search_uint(ldb, dn, 180, dn, "tombstoneLifetime", "objectClass=nTDSService");
5009
0
  talloc_free(dn);
5010
0
  return LDB_SUCCESS;
5011
0
}
5012
5013
/*
5014
  compare a ldb_val to a string case insensitively
5015
 */
5016
int samdb_ldb_val_case_cmp(const char *s, struct ldb_val *v)
5017
0
{
5018
0
  size_t len = strlen(s);
5019
0
  int ret;
5020
0
  if (len > v->length) return 1;
5021
0
  ret = strncasecmp(s, (const char *)v->data, v->length);
5022
0
  if (ret != 0) return ret;
5023
0
  if (v->length > len && v->data[len] != 0) {
5024
0
    return -1;
5025
0
  }
5026
0
  return 0;
5027
0
}
5028
5029
5030
/*
5031
  load the UDV for a partition in v2 format
5032
  The list is returned sorted, and with our local cursor added
5033
 */
5034
int dsdb_load_udv_v2(struct ldb_context *samdb, struct ldb_dn *dn, TALLOC_CTX *mem_ctx,
5035
         struct drsuapi_DsReplicaCursor2 **cursors, uint32_t *count)
5036
0
{
5037
0
  static const char *attrs[] = { "replUpToDateVector", NULL };
5038
0
  struct ldb_result *r = NULL;
5039
0
  const struct ldb_val *ouv_value;
5040
0
  unsigned int i;
5041
0
  int ret;
5042
0
  uint64_t highest_usn = 0;
5043
0
  const struct GUID *our_invocation_id;
5044
0
  static const struct timeval tv1970;
5045
0
  NTTIME nt1970 = timeval_to_nttime(&tv1970);
5046
5047
0
  ret = dsdb_search_dn(samdb, mem_ctx, &r, dn, attrs, DSDB_SEARCH_SHOW_RECYCLED|DSDB_SEARCH_SHOW_DELETED);
5048
0
  if (ret != LDB_SUCCESS) {
5049
0
    return ret;
5050
0
  }
5051
  /* fix clang warning */
5052
0
  if (r == NULL) {
5053
0
    return LDB_ERR_OTHER;
5054
0
  }
5055
0
  ouv_value = ldb_msg_find_ldb_val(r->msgs[0], "replUpToDateVector");
5056
0
  if (ouv_value) {
5057
0
    enum ndr_err_code ndr_err;
5058
0
    struct replUpToDateVectorBlob ouv;
5059
5060
0
    ndr_err = ndr_pull_struct_blob(ouv_value, r, &ouv,
5061
0
                 (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob);
5062
0
    if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
5063
0
      talloc_free(r);
5064
0
      return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
5065
0
    }
5066
0
    if (ouv.version != 2) {
5067
      /* we always store as version 2, and
5068
       * replUpToDateVector is not replicated
5069
       */
5070
0
      talloc_free(r);
5071
0
      return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
5072
0
    }
5073
5074
0
    *count = ouv.ctr.ctr2.count;
5075
0
    *cursors = talloc_steal(mem_ctx, ouv.ctr.ctr2.cursors);
5076
0
  } else {
5077
0
    *count = 0;
5078
0
    *cursors = NULL;
5079
0
  }
5080
5081
0
  talloc_free(r);
5082
5083
0
  our_invocation_id = samdb_ntds_invocation_id(samdb);
5084
0
  if (!our_invocation_id) {
5085
0
    DEBUG(0,(__location__ ": No invocationID on samdb - %s\n", ldb_errstring(samdb)));
5086
0
    talloc_free(*cursors);
5087
0
    return ldb_operr(samdb);
5088
0
  }
5089
5090
0
  ret = ldb_sequence_number(samdb, LDB_SEQ_HIGHEST_SEQ, &highest_usn);
5091
0
  if (ret != LDB_SUCCESS) {
5092
    /* nothing to add - this can happen after a vampire */
5093
0
    TYPESAFE_QSORT(*cursors, *count, drsuapi_DsReplicaCursor2_compare);
5094
0
    return LDB_SUCCESS;
5095
0
  }
5096
5097
0
  for (i=0; i<*count; i++) {
5098
0
    if (GUID_equal(our_invocation_id, &(*cursors)[i].source_dsa_invocation_id)) {
5099
0
      (*cursors)[i].highest_usn = highest_usn;
5100
0
      (*cursors)[i].last_sync_success = nt1970;
5101
0
      TYPESAFE_QSORT(*cursors, *count, drsuapi_DsReplicaCursor2_compare);
5102
0
      return LDB_SUCCESS;
5103
0
    }
5104
0
  }
5105
5106
0
  (*cursors) = talloc_realloc(mem_ctx, *cursors, struct drsuapi_DsReplicaCursor2, (*count)+1);
5107
0
  if (! *cursors) {
5108
0
    return ldb_oom(samdb);
5109
0
  }
5110
5111
0
  (*cursors)[*count].source_dsa_invocation_id = *our_invocation_id;
5112
0
  (*cursors)[*count].highest_usn = highest_usn;
5113
0
  (*cursors)[*count].last_sync_success = nt1970;
5114
0
  (*count)++;
5115
5116
0
  TYPESAFE_QSORT(*cursors, *count, drsuapi_DsReplicaCursor2_compare);
5117
5118
0
  return LDB_SUCCESS;
5119
0
}
5120
5121
/*
5122
  load the UDV for a partition in version 1 format
5123
  The list is returned sorted, and with our local cursor added
5124
 */
5125
int dsdb_load_udv_v1(struct ldb_context *samdb, struct ldb_dn *dn, TALLOC_CTX *mem_ctx,
5126
         struct drsuapi_DsReplicaCursor **cursors, uint32_t *count)
5127
0
{
5128
0
  struct drsuapi_DsReplicaCursor2 *v2 = NULL;
5129
0
  uint32_t i;
5130
0
  int ret;
5131
5132
0
  ret = dsdb_load_udv_v2(samdb, dn, mem_ctx, &v2, count);
5133
0
  if (ret != LDB_SUCCESS) {
5134
0
    return ret;
5135
0
  }
5136
5137
0
  if (*count == 0) {
5138
0
    talloc_free(v2);
5139
0
    *cursors = NULL;
5140
0
    return LDB_SUCCESS;
5141
0
  }
5142
5143
0
  *cursors = talloc_array(mem_ctx, struct drsuapi_DsReplicaCursor, *count);
5144
0
  if (*cursors == NULL) {
5145
0
    talloc_free(v2);
5146
0
    return ldb_oom(samdb);
5147
0
  }
5148
5149
0
  for (i=0; i<*count; i++) {
5150
0
    (*cursors)[i].source_dsa_invocation_id = v2[i].source_dsa_invocation_id;
5151
0
    (*cursors)[i].highest_usn = v2[i].highest_usn;
5152
0
  }
5153
0
  talloc_free(v2);
5154
0
  return LDB_SUCCESS;
5155
0
}
5156
5157
/*
5158
  add a set of controls to a ldb_request structure based on a set of
5159
  flags. See util.h for a list of available flags
5160
 */
5161
int dsdb_request_add_controls(struct ldb_request *req, uint32_t dsdb_flags)
5162
0
{
5163
0
  int ret;
5164
0
  if (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) {
5165
0
    struct ldb_search_options_control *options;
5166
    /* Using the phantom root control allows us to search all partitions */
5167
0
    options = talloc(req, struct ldb_search_options_control);
5168
0
    if (options == NULL) {
5169
0
      return LDB_ERR_OPERATIONS_ERROR;
5170
0
    }
5171
0
    options->search_options = LDB_SEARCH_OPTION_PHANTOM_ROOT;
5172
5173
0
    ret = ldb_request_add_control(req,
5174
0
                LDB_CONTROL_SEARCH_OPTIONS_OID,
5175
0
                true, options);
5176
0
    if (ret != LDB_SUCCESS) {
5177
0
      return ret;
5178
0
    }
5179
0
  }
5180
5181
0
  if (dsdb_flags & DSDB_SEARCH_NO_GLOBAL_CATALOG) {
5182
0
    ret = ldb_request_add_control(req,
5183
0
                DSDB_CONTROL_NO_GLOBAL_CATALOG,
5184
0
                false, NULL);
5185
0
    if (ret != LDB_SUCCESS) {
5186
0
      return ret;
5187
0
    }
5188
0
  }
5189
5190
0
  if (dsdb_flags & DSDB_SEARCH_SHOW_DELETED) {
5191
0
    ret = ldb_request_add_control(req, LDB_CONTROL_SHOW_DELETED_OID, true, NULL);
5192
0
    if (ret != LDB_SUCCESS) {
5193
0
      return ret;
5194
0
    }
5195
0
  }
5196
5197
0
  if (dsdb_flags & DSDB_SEARCH_SHOW_RECYCLED) {
5198
0
    ret = ldb_request_add_control(req, LDB_CONTROL_SHOW_RECYCLED_OID, false, NULL);
5199
0
    if (ret != LDB_SUCCESS) {
5200
0
      return ret;
5201
0
    }
5202
0
  }
5203
5204
0
  if (dsdb_flags & DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT) {
5205
0
    ret = ldb_request_add_control(req, DSDB_CONTROL_DN_STORAGE_FORMAT_OID, false, NULL);
5206
0
    if (ret != LDB_SUCCESS) {
5207
0
      return ret;
5208
0
    }
5209
0
  }
5210
5211
0
  if (dsdb_flags & DSDB_SEARCH_SHOW_EXTENDED_DN) {
5212
0
    struct ldb_extended_dn_control *extended_ctrl = talloc(req, struct ldb_extended_dn_control);
5213
0
    if (!extended_ctrl) {
5214
0
      return LDB_ERR_OPERATIONS_ERROR;
5215
0
    }
5216
0
    extended_ctrl->type = 1;
5217
5218
0
    ret = ldb_request_add_control(req, LDB_CONTROL_EXTENDED_DN_OID, true, extended_ctrl);
5219
0
    if (ret != LDB_SUCCESS) {
5220
0
      return ret;
5221
0
    }
5222
0
  }
5223
5224
0
  if (dsdb_flags & DSDB_SEARCH_REVEAL_INTERNALS) {
5225
0
    ret = ldb_request_add_control(req, LDB_CONTROL_REVEAL_INTERNALS, false, NULL);
5226
0
    if (ret != LDB_SUCCESS) {
5227
0
      return ret;
5228
0
    }
5229
0
  }
5230
5231
0
  if (dsdb_flags & DSDB_MODIFY_RELAX) {
5232
0
    ret = ldb_request_add_control(req, LDB_CONTROL_RELAX_OID, false, NULL);
5233
0
    if (ret != LDB_SUCCESS) {
5234
0
      return ret;
5235
0
    }
5236
0
  }
5237
5238
0
  if (dsdb_flags & DSDB_MODIFY_PERMISSIVE) {
5239
0
    ret = ldb_request_add_control(req, LDB_CONTROL_PERMISSIVE_MODIFY_OID, false, NULL);
5240
0
    if (ret != LDB_SUCCESS) {
5241
0
      return ret;
5242
0
    }
5243
0
  }
5244
5245
0
  if (dsdb_flags & DSDB_FLAG_AS_SYSTEM) {
5246
0
    ret = ldb_request_add_control(req, LDB_CONTROL_AS_SYSTEM_OID, false, NULL);
5247
0
    if (ret != LDB_SUCCESS) {
5248
0
      return ret;
5249
0
    }
5250
0
  }
5251
5252
0
  if (dsdb_flags & DSDB_TREE_DELETE) {
5253
0
    ret = ldb_request_add_control(req, LDB_CONTROL_TREE_DELETE_OID, false, NULL);
5254
0
    if (ret != LDB_SUCCESS) {
5255
0
      return ret;
5256
0
    }
5257
0
  }
5258
5259
0
  if (dsdb_flags & DSDB_PROVISION) {
5260
0
    ret = ldb_request_add_control(req, LDB_CONTROL_PROVISION_OID, false, NULL);
5261
0
    if (ret != LDB_SUCCESS) {
5262
0
      return ret;
5263
0
    }
5264
0
  }
5265
5266
  /* This is a special control to bypass the password_hash module for use in pdb_samba4 for Samba3 upgrades */
5267
0
  if (dsdb_flags & DSDB_BYPASS_PASSWORD_HASH) {
5268
0
    ret = ldb_request_add_control(req, DSDB_CONTROL_BYPASS_PASSWORD_HASH_OID, true, NULL);
5269
0
    if (ret != LDB_SUCCESS) {
5270
0
      return ret;
5271
0
    }
5272
0
  }
5273
5274
0
  if (dsdb_flags & DSDB_PASSWORD_BYPASS_LAST_SET) {
5275
    /*
5276
     * This must not be critical, as it will only be
5277
     * handled (and need to be handled) if the other
5278
     * attributes in the request bring password_hash into
5279
     * action
5280
     */
5281
0
    ret = ldb_request_add_control(req, DSDB_CONTROL_PASSWORD_BYPASS_LAST_SET_OID, false, NULL);
5282
0
    if (ret != LDB_SUCCESS) {
5283
0
      return ret;
5284
0
    }
5285
0
  }
5286
5287
0
  if (dsdb_flags & DSDB_REPLMD_VANISH_LINKS) {
5288
0
    ret = ldb_request_add_control(req, DSDB_CONTROL_REPLMD_VANISH_LINKS, true, NULL);
5289
0
    if (ret != LDB_SUCCESS) {
5290
0
      return ret;
5291
0
    }
5292
0
  }
5293
5294
0
  if (dsdb_flags & DSDB_MODIFY_PARTIAL_REPLICA) {
5295
0
    ret = ldb_request_add_control(req, DSDB_CONTROL_PARTIAL_REPLICA, false, NULL);
5296
0
    if (ret != LDB_SUCCESS) {
5297
0
      return ret;
5298
0
    }
5299
0
  }
5300
5301
0
  if (dsdb_flags & DSDB_FLAG_REPLICATED_UPDATE) {
5302
0
    ret = ldb_request_add_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID, false, NULL);
5303
0
    if (ret != LDB_SUCCESS) {
5304
0
      return ret;
5305
0
    }
5306
0
  }
5307
5308
0
  if (dsdb_flags & DSDB_FLAG_FORCE_ALLOW_VALIDATED_DNS_HOSTNAME_SPN_WRITE) {
5309
0
    ret = ldb_request_add_control(req, DSDB_CONTROL_FORCE_ALLOW_VALIDATED_DNS_HOSTNAME_SPN_WRITE_OID, true, NULL);
5310
0
    if (ret != LDB_SUCCESS) {
5311
0
      return ret;
5312
0
    }
5313
0
  }
5314
5315
0
  if (dsdb_flags & DSDB_MARK_REQ_UNTRUSTED) {
5316
0
    ldb_req_mark_untrusted(req);
5317
0
  }
5318
5319
0
  return LDB_SUCCESS;
5320
0
}
5321
5322
/*
5323
   returns true if a control with the specified "oid" exists
5324
*/
5325
bool dsdb_request_has_control(struct ldb_request *req, const char *oid)
5326
0
{
5327
0
  return (ldb_request_get_control(req, oid) != NULL);
5328
0
}
5329
5330
/*
5331
  an add with a set of controls
5332
*/
5333
int dsdb_add(struct ldb_context *ldb, const struct ldb_message *message,
5334
       uint32_t dsdb_flags)
5335
0
{
5336
0
  struct ldb_request *req;
5337
0
  int ret;
5338
5339
0
  ret = ldb_build_add_req(&req, ldb, ldb,
5340
0
        message,
5341
0
        NULL,
5342
0
        NULL,
5343
0
        ldb_op_default_callback,
5344
0
        NULL);
5345
5346
0
  if (ret != LDB_SUCCESS) return ret;
5347
5348
0
  ret = dsdb_request_add_controls(req, dsdb_flags);
5349
0
  if (ret != LDB_SUCCESS) {
5350
0
    talloc_free(req);
5351
0
    return ret;
5352
0
  }
5353
5354
0
  ret = dsdb_autotransaction_request(ldb, req);
5355
5356
0
  talloc_free(req);
5357
0
  return ret;
5358
0
}
5359
5360
/*
5361
  a modify with a set of controls
5362
*/
5363
int dsdb_modify(struct ldb_context *ldb, const struct ldb_message *message,
5364
    uint32_t dsdb_flags)
5365
0
{
5366
0
  struct ldb_request *req;
5367
0
  int ret;
5368
5369
0
  ret = ldb_build_mod_req(&req, ldb, ldb,
5370
0
        message,
5371
0
        NULL,
5372
0
        NULL,
5373
0
        ldb_op_default_callback,
5374
0
        NULL);
5375
5376
0
  if (ret != LDB_SUCCESS) return ret;
5377
5378
0
  ret = dsdb_request_add_controls(req, dsdb_flags);
5379
0
  if (ret != LDB_SUCCESS) {
5380
0
    talloc_free(req);
5381
0
    return ret;
5382
0
  }
5383
5384
0
  ret = dsdb_autotransaction_request(ldb, req);
5385
5386
0
  talloc_free(req);
5387
0
  return ret;
5388
0
}
5389
5390
/*
5391
  a delete with a set of flags
5392
*/
5393
int dsdb_delete(struct ldb_context *ldb, struct ldb_dn *dn,
5394
    uint32_t dsdb_flags)
5395
0
{
5396
0
  struct ldb_request *req;
5397
0
  int ret;
5398
5399
0
  ret = ldb_build_del_req(&req, ldb, ldb,
5400
0
        dn,
5401
0
        NULL,
5402
0
        NULL,
5403
0
        ldb_op_default_callback,
5404
0
        NULL);
5405
5406
0
  if (ret != LDB_SUCCESS) return ret;
5407
5408
0
  ret = dsdb_request_add_controls(req, dsdb_flags);
5409
0
  if (ret != LDB_SUCCESS) {
5410
0
    talloc_free(req);
5411
0
    return ret;
5412
0
  }
5413
5414
0
  ret = dsdb_autotransaction_request(ldb, req);
5415
5416
0
  talloc_free(req);
5417
0
  return ret;
5418
0
}
5419
5420
/*
5421
  like dsdb_modify() but set all the element flags to
5422
  LDB_FLAG_MOD_REPLACE
5423
 */
5424
int dsdb_replace(struct ldb_context *ldb, struct ldb_message *msg, uint32_t dsdb_flags)
5425
0
{
5426
0
  unsigned int i;
5427
5428
  /* mark all the message elements as LDB_FLAG_MOD_REPLACE */
5429
0
  for (i=0;i<msg->num_elements;i++) {
5430
0
    msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
5431
0
  }
5432
5433
0
  return dsdb_modify(ldb, msg, dsdb_flags);
5434
0
}
5435
5436
const char *dsdb_search_scope_as_string(enum ldb_scope scope)
5437
0
{
5438
0
  const char *scope_str;
5439
5440
0
  switch (scope) {
5441
0
  case LDB_SCOPE_BASE:
5442
0
    scope_str = "BASE";
5443
0
    break;
5444
0
  case LDB_SCOPE_ONELEVEL:
5445
0
    scope_str = "ONE";
5446
0
    break;
5447
0
  case LDB_SCOPE_SUBTREE:
5448
0
    scope_str = "SUB";
5449
0
    break;
5450
0
  default:
5451
0
    scope_str = "<Invalid scope>";
5452
0
    break;
5453
0
  }
5454
0
  return scope_str;
5455
0
}
5456
5457
5458
/*
5459
  search for attrs on one DN, allowing for dsdb_flags controls
5460
 */
5461
int dsdb_search_dn(struct ldb_context *ldb,
5462
       TALLOC_CTX *mem_ctx,
5463
       struct ldb_result **_result,
5464
       struct ldb_dn *basedn,
5465
       const char * const *attrs,
5466
       uint32_t dsdb_flags)
5467
0
{
5468
0
  int ret;
5469
0
  struct ldb_request *req;
5470
0
  struct ldb_result *res;
5471
0
  TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
5472
5473
0
  if (tmp_ctx == NULL) {
5474
0
    return ldb_oom(ldb);
5475
0
  }
5476
5477
0
  res = talloc_zero(tmp_ctx, struct ldb_result);
5478
0
  if (!res) {
5479
0
    talloc_free(tmp_ctx);
5480
0
    return ldb_oom(ldb);
5481
0
  }
5482
5483
0
  ret = ldb_build_search_req(&req, ldb, res,
5484
0
           basedn,
5485
0
           LDB_SCOPE_BASE,
5486
0
           NULL,
5487
0
           attrs,
5488
0
           NULL,
5489
0
           res,
5490
0
           ldb_search_default_callback,
5491
0
           NULL);
5492
0
  if (ret != LDB_SUCCESS) {
5493
0
    talloc_free(tmp_ctx);
5494
0
    return ret;
5495
0
  }
5496
5497
0
  ret = dsdb_request_add_controls(req, dsdb_flags);
5498
0
  if (ret != LDB_SUCCESS) {
5499
0
    talloc_free(tmp_ctx);
5500
0
    return ret;
5501
0
  }
5502
5503
0
  ret = ldb_request(ldb, req);
5504
0
  if (ret == LDB_SUCCESS) {
5505
0
    ret = ldb_wait(req->handle, LDB_WAIT_ALL);
5506
0
  }
5507
5508
0
  talloc_free(req);
5509
0
  if (ret != LDB_SUCCESS) {
5510
0
    DBG_INFO("flags=0x%08x %s -> %s (%s)\n",
5511
0
       dsdb_flags,
5512
0
       basedn?ldb_dn_get_extended_linearized(tmp_ctx,
5513
0
                     basedn,
5514
0
                     1):"NULL",
5515
0
       ldb_errstring(ldb), ldb_strerror(ret));
5516
0
    talloc_free(tmp_ctx);
5517
0
    return ret;
5518
0
  }
5519
5520
0
  DBG_DEBUG("flags=0x%08x %s -> %d\n",
5521
0
      dsdb_flags,
5522
0
      basedn?ldb_dn_get_extended_linearized(tmp_ctx,
5523
0
              basedn,
5524
0
              1):"NULL",
5525
0
      res->count);
5526
5527
0
  *_result = talloc_steal(mem_ctx, res);
5528
5529
0
  talloc_free(tmp_ctx);
5530
0
  return LDB_SUCCESS;
5531
0
}
5532
5533
/*
5534
  search for attrs on one DN, by the GUID of the DN, allowing for
5535
  dsdb_flags controls
5536
 */
5537
int dsdb_search_by_dn_guid(struct ldb_context *ldb,
5538
         TALLOC_CTX *mem_ctx,
5539
         struct ldb_result **_result,
5540
         const struct GUID *guid,
5541
         const char * const *attrs,
5542
         uint32_t dsdb_flags)
5543
0
{
5544
0
  TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
5545
0
  struct ldb_dn *dn;
5546
0
  int ret;
5547
5548
0
  if (tmp_ctx == NULL) {
5549
0
    return ldb_oom(ldb);
5550
0
  }
5551
5552
0
  dn = ldb_dn_new_fmt(tmp_ctx, ldb, "<GUID=%s>", GUID_string(tmp_ctx, guid));
5553
0
  if (dn == NULL) {
5554
0
    talloc_free(tmp_ctx);
5555
0
    return ldb_oom(ldb);
5556
0
  }
5557
5558
0
  ret = dsdb_search_dn(ldb, mem_ctx, _result, dn, attrs, dsdb_flags);
5559
0
  talloc_free(tmp_ctx);
5560
0
  return ret;
5561
0
}
5562
5563
NTSTATUS gmsa_system_password_update_request(
5564
  struct ldb_context *ldb,
5565
  TALLOC_CTX *mem_ctx,
5566
  struct ldb_dn *dn,
5567
  const uint8_t
5568
    password_buf[static const GMSA_PASSWORD_NULL_TERMINATED_LEN],
5569
  struct ldb_request **request_out)
5570
0
{
5571
0
  DATA_BLOB password_blob = {};
5572
0
  struct ldb_request *request = NULL;
5573
0
  NTSTATUS status;
5574
0
  int ret;
5575
5576
0
  dn = ldb_dn_copy(mem_ctx, dn);
5577
0
  if (dn == NULL) {
5578
0
    return NT_STATUS_INTERNAL_ERROR;
5579
0
  }
5580
5581
  /* Make a copy of the password. */
5582
0
  password_blob = data_blob_talloc(mem_ctx,
5583
0
           password_buf,
5584
0
           GMSA_PASSWORD_LEN);
5585
0
  if (password_blob.data == NULL) {
5586
0
    talloc_free(dn);
5587
0
    return NT_STATUS_NO_MEMORY;
5588
0
  }
5589
5590
0
  status = samdb_set_password_request(ldb,
5591
0
              mem_ctx,
5592
0
              dn,
5593
0
              &password_blob,
5594
0
              NULL,
5595
0
              DSDB_PASSWORD_RESET,
5596
0
              false /* reject trusts */,
5597
0
              &request);
5598
0
  if (!NT_STATUS_IS_OK(status)) {
5599
0
    data_blob_free(&password_blob);
5600
0
    talloc_free(dn);
5601
0
    return status;
5602
0
  }
5603
5604
  /* Tie the lifetime of the password to that of the request. */
5605
0
  talloc_steal(request, password_blob.data);
5606
5607
  /* Tie the lifetime of the DN to that of the request. */
5608
0
  talloc_steal(request, dn);
5609
5610
  /* Make sure the password update happens as System. */
5611
0
  ret = dsdb_request_add_controls(request, DSDB_FLAG_AS_SYSTEM);
5612
0
  if (ret) {
5613
0
    talloc_free(request);
5614
0
    return NT_STATUS_NO_MEMORY;
5615
0
  }
5616
5617
0
  *request_out = request;
5618
0
  return NT_STATUS_OK;
5619
0
}
5620
5621
/*
5622
  general search with dsdb_flags for controls
5623
 */
5624
int dsdb_search(struct ldb_context *ldb,
5625
    TALLOC_CTX *mem_ctx,
5626
    struct ldb_result **_result,
5627
    struct ldb_dn *basedn,
5628
    enum ldb_scope scope,
5629
    const char * const *attrs,
5630
    uint32_t dsdb_flags,
5631
    const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(8, 9)
5632
0
{
5633
0
  int ret;
5634
0
  struct ldb_request *req;
5635
0
  struct ldb_result *res;
5636
0
  va_list ap;
5637
0
  char *expression = NULL;
5638
0
  TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
5639
0
  int tries;
5640
0
  const int max_tries = 5;
5641
5642
  /* cross-partitions searches with a basedn break multi-domain support */
5643
0
  SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
5644
5645
0
  if (tmp_ctx == NULL) {
5646
0
    return ldb_oom(ldb);
5647
0
  }
5648
5649
0
  res = talloc(tmp_ctx, struct ldb_result);
5650
0
  if (!res) {
5651
0
    talloc_free(tmp_ctx);
5652
0
    return ldb_oom(ldb);
5653
0
  }
5654
5655
0
  if (exp_fmt) {
5656
0
    va_start(ap, exp_fmt);
5657
0
    expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
5658
0
    va_end(ap);
5659
5660
0
    if (!expression) {
5661
0
      talloc_free(tmp_ctx);
5662
0
      return ldb_oom(ldb);
5663
0
    }
5664
0
  }
5665
5666
0
  for (tries = 0; tries < max_tries; ++tries) {
5667
0
    bool retry = true;
5668
5669
0
    *res = (struct ldb_result){};
5670
5671
0
    ret = ldb_build_search_req(&req, ldb, tmp_ctx,
5672
0
             basedn,
5673
0
             scope,
5674
0
             expression,
5675
0
             attrs,
5676
0
             NULL,
5677
0
             res,
5678
0
             ldb_search_default_callback,
5679
0
             NULL);
5680
0
    if (ret != LDB_SUCCESS) {
5681
0
      talloc_free(tmp_ctx);
5682
0
      return ret;
5683
0
    }
5684
5685
0
    ret = dsdb_request_add_controls(req, dsdb_flags);
5686
0
    if (ret != LDB_SUCCESS) {
5687
0
      talloc_free(tmp_ctx);
5688
0
      ldb_reset_err_string(ldb);
5689
0
      return ret;
5690
0
    }
5691
5692
0
    ret = ldb_request(ldb, req);
5693
0
    if (ret == LDB_SUCCESS) {
5694
0
      ret = ldb_wait(req->handle, LDB_WAIT_ALL);
5695
0
    }
5696
5697
0
    if (ret != LDB_SUCCESS) {
5698
0
      DBG_INFO("%s flags=0x%08x %s %s -> %s (%s)\n",
5699
0
         dsdb_search_scope_as_string(scope),
5700
0
         dsdb_flags,
5701
0
         basedn?ldb_dn_get_extended_linearized(tmp_ctx,
5702
0
                       basedn,
5703
0
                       1):"NULL",
5704
0
         expression?expression:"NULL",
5705
0
         ldb_errstring(ldb), ldb_strerror(ret));
5706
0
      talloc_free(tmp_ctx);
5707
0
      return ret;
5708
0
    }
5709
5710
0
    if (dsdb_flags & DSDB_SEARCH_ONE_ONLY) {
5711
0
      if (res->count == 0) {
5712
0
        DBG_INFO("%s SEARCH_ONE_ONLY flags=0x%08x %s %s -> %u results\n",
5713
0
           dsdb_search_scope_as_string(scope),
5714
0
           dsdb_flags,
5715
0
           basedn?ldb_dn_get_extended_linearized(tmp_ctx,
5716
0
                         basedn,
5717
0
                         1):"NULL",
5718
0
           expression?expression:"NULL", res->count);
5719
0
        talloc_free(tmp_ctx);
5720
0
        ldb_reset_err_string(ldb);
5721
0
        return ldb_error(ldb, LDB_ERR_NO_SUCH_OBJECT, __func__);
5722
0
      }
5723
0
      if (res->count != 1) {
5724
0
        DBG_INFO("%s SEARCH_ONE_ONLY flags=0x%08x %s %s -> %u (expected 1) results\n",
5725
0
           dsdb_search_scope_as_string(scope),
5726
0
           dsdb_flags,
5727
0
           basedn?ldb_dn_get_extended_linearized(tmp_ctx,
5728
0
                         basedn,
5729
0
                         1):"NULL",
5730
0
           expression?expression:"NULL", res->count);
5731
0
        talloc_free(tmp_ctx);
5732
0
        ldb_reset_err_string(ldb);
5733
0
        return LDB_ERR_CONSTRAINT_VIOLATION;
5734
0
      }
5735
0
    }
5736
5737
0
    if (!(dsdb_flags & DSDB_SEARCH_UPDATE_MANAGED_PASSWORDS)) {
5738
0
      break;
5739
0
    }
5740
5741
    /*
5742
     * If we’re searching for passwords, we must account for the
5743
     * possibility that one or more of the accounts are Group
5744
     * Managed Service Accounts with out‐of‐date keys. In such a
5745
     * case, we must derive the new password(s), update the keys,
5746
     * and perform the search again to get the updated results.
5747
     *
5748
     * The following attributes are necessary in order for this to
5749
     * work properly:
5750
     *
5751
     * • msDS-ManagedPasswordId
5752
     * • msDS-ManagedPasswordInterval
5753
     * • objectClass
5754
     * • objectSid
5755
     * • whenCreated
5756
     */
5757
5758
0
    ret = dsdb_update_gmsa_keys(tmp_ctx, ldb, res, &retry);
5759
0
    if (ret) {
5760
0
      talloc_free(tmp_ctx);
5761
0
      return ret;
5762
0
    }
5763
0
    if (!retry) {
5764
0
      break;
5765
0
    }
5766
0
  }
5767
0
  if (tries == max_tries) {
5768
0
    talloc_free(tmp_ctx);
5769
0
    ldb_reset_err_string(ldb);
5770
0
    return ldb_operr(ldb);
5771
0
  }
5772
5773
0
  *_result = talloc_steal(mem_ctx, res);
5774
5775
0
  DBG_DEBUG("%s flags=0x%08x %s %s -> %d\n",
5776
0
      dsdb_search_scope_as_string(scope),
5777
0
      dsdb_flags,
5778
0
      basedn?ldb_dn_get_extended_linearized(tmp_ctx,
5779
0
              basedn,
5780
0
              1):"NULL",
5781
0
      expression?expression:"NULL",
5782
0
      res->count);
5783
0
  talloc_free(tmp_ctx);
5784
0
  return LDB_SUCCESS;
5785
0
}
5786
5787
5788
/*
5789
  general search with dsdb_flags for controls
5790
  returns exactly 1 record or an error
5791
 */
5792
int dsdb_search_one(struct ldb_context *ldb,
5793
        TALLOC_CTX *mem_ctx,
5794
        struct ldb_message **msg,
5795
        struct ldb_dn *basedn,
5796
        enum ldb_scope scope,
5797
        const char * const *attrs,
5798
        uint32_t dsdb_flags,
5799
        const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(8, 9)
5800
0
{
5801
0
  int ret;
5802
0
  struct ldb_result *res;
5803
0
  va_list ap;
5804
0
  char *expression = NULL;
5805
0
  TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
5806
5807
0
  if (tmp_ctx == NULL) {
5808
0
    return ldb_oom(ldb);
5809
0
  }
5810
5811
0
  dsdb_flags |= DSDB_SEARCH_ONE_ONLY;
5812
5813
0
  res = talloc_zero(tmp_ctx, struct ldb_result);
5814
0
  if (!res) {
5815
0
    talloc_free(tmp_ctx);
5816
0
    return ldb_oom(ldb);
5817
0
  }
5818
5819
0
  if (exp_fmt) {
5820
0
    va_start(ap, exp_fmt);
5821
0
    expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
5822
0
    va_end(ap);
5823
5824
0
    if (!expression) {
5825
0
      talloc_free(tmp_ctx);
5826
0
      return ldb_oom(ldb);
5827
0
    }
5828
0
    ret = dsdb_search(ldb, tmp_ctx, &res, basedn, scope, attrs,
5829
0
          dsdb_flags, "%s", expression);
5830
0
  } else {
5831
0
    ret = dsdb_search(ldb, tmp_ctx, &res, basedn, scope, attrs,
5832
0
          dsdb_flags, NULL);
5833
0
  }
5834
5835
0
  if (ret != LDB_SUCCESS) {
5836
0
    talloc_free(tmp_ctx);
5837
0
    return ret;
5838
0
  }
5839
5840
0
  *msg = talloc_steal(mem_ctx, res->msgs[0]);
5841
0
  talloc_free(tmp_ctx);
5842
5843
0
  return LDB_SUCCESS;
5844
0
}
5845
5846
/* returns back the forest DNS name */
5847
const char *samdb_forest_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
5848
0
{
5849
0
  char *forest_name = NULL;
5850
0
  char *p = NULL;
5851
5852
0
  forest_name = ldb_dn_canonical_string(mem_ctx,
5853
0
                ldb_get_root_basedn(ldb));
5854
0
  if (forest_name == NULL) {
5855
0
    return NULL;
5856
0
  }
5857
5858
0
  p = strchr(forest_name, '/');
5859
0
  if (p) {
5860
0
    *p = '\0';
5861
0
  }
5862
5863
0
  return forest_name;
5864
0
}
5865
5866
/* returns back the default domain DNS name */
5867
const char *samdb_default_domain_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
5868
0
{
5869
0
  char *domain_name = NULL;
5870
0
  char *p;
5871
5872
0
  domain_name = ldb_dn_canonical_string(mem_ctx,
5873
0
                ldb_get_default_basedn(ldb));
5874
0
  if (domain_name == NULL) {
5875
0
    return NULL;
5876
0
  }
5877
5878
0
  p = strchr(domain_name, '/');
5879
0
  if (p) {
5880
0
    *p = '\0';
5881
0
  }
5882
5883
0
  return domain_name;
5884
0
}
5885
5886
/*
5887
   validate that an DSA GUID belongs to the specified user sid.
5888
   The user SID must be a domain controller account (either RODC or
5889
   RWDC)
5890
 */
5891
int dsdb_validate_dsa_guid(struct ldb_context *ldb,
5892
         const struct GUID *dsa_guid,
5893
         const struct dom_sid *sid)
5894
0
{
5895
  /* strategy:
5896
      - find DN of record with the DSA GUID in the
5897
        configuration partition (objectGUID)
5898
            - remove "NTDS Settings" component from DN
5899
      - do a base search on that DN for serverReference with
5900
        extended-dn enabled
5901
            - extract objectSid from resulting serverReference
5902
              attribute
5903
      - check this sid matches the sid argument
5904
  */
5905
0
  struct ldb_dn *config_dn;
5906
0
  TALLOC_CTX *tmp_ctx = talloc_new(ldb);
5907
0
  struct ldb_message *msg;
5908
0
  const char *attrs1[] = { NULL };
5909
0
  const char *attrs2[] = { "serverReference", NULL };
5910
0
  int ret;
5911
0
  struct ldb_dn *dn, *account_dn;
5912
0
  struct dom_sid sid2;
5913
0
  NTSTATUS status;
5914
5915
0
  if (tmp_ctx == NULL) {
5916
0
    return ldb_oom(ldb);
5917
0
  }
5918
5919
0
  config_dn = ldb_get_config_basedn(ldb);
5920
5921
0
  ret = dsdb_search_one(ldb, tmp_ctx, &msg, config_dn, LDB_SCOPE_SUBTREE,
5922
0
            attrs1, 0, "(&(objectGUID=%s)(objectClass=nTDSDSA))", GUID_string(tmp_ctx, dsa_guid));
5923
0
  if (ret != LDB_SUCCESS) {
5924
0
    DEBUG(1,(__location__ ": Failed to find DSA objectGUID %s for sid %s\n",
5925
0
       GUID_string(tmp_ctx, dsa_guid), dom_sid_string(tmp_ctx, sid)));
5926
0
    talloc_free(tmp_ctx);
5927
0
    return ldb_operr(ldb);
5928
0
  }
5929
0
  dn = msg->dn;
5930
5931
0
  if (!ldb_dn_remove_child_components(dn, 1)) {
5932
0
    talloc_free(tmp_ctx);
5933
0
    return ldb_operr(ldb);
5934
0
  }
5935
5936
0
  ret = dsdb_search_one(ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE,
5937
0
            attrs2, DSDB_SEARCH_SHOW_EXTENDED_DN,
5938
0
            "(objectClass=server)");
5939
0
  if (ret != LDB_SUCCESS) {
5940
0
    DEBUG(1,(__location__ ": Failed to find server record for DSA with objectGUID %s, sid %s\n",
5941
0
       GUID_string(tmp_ctx, dsa_guid), dom_sid_string(tmp_ctx, sid)));
5942
0
    talloc_free(tmp_ctx);
5943
0
    return ldb_operr(ldb);
5944
0
  }
5945
5946
0
  account_dn = ldb_msg_find_attr_as_dn(ldb, tmp_ctx, msg, "serverReference");
5947
0
  if (account_dn == NULL) {
5948
0
    DEBUG(1,(__location__ ": Failed to find account dn "
5949
0
       "(serverReference) for %s, parent of DSA with "
5950
0
       "objectGUID %s, sid %s\n",
5951
0
       ldb_dn_get_linearized(msg->dn),
5952
0
       GUID_string(tmp_ctx, dsa_guid),
5953
0
       dom_sid_string(tmp_ctx, sid)));
5954
0
    talloc_free(tmp_ctx);
5955
0
    return ldb_operr(ldb);
5956
0
  }
5957
5958
0
  status = dsdb_get_extended_dn_sid(account_dn, &sid2, "SID");
5959
0
  if (!NT_STATUS_IS_OK(status)) {
5960
0
    DEBUG(1,(__location__ ": Failed to find SID for DSA with objectGUID %s, sid %s\n",
5961
0
       GUID_string(tmp_ctx, dsa_guid), dom_sid_string(tmp_ctx, sid)));
5962
0
    talloc_free(tmp_ctx);
5963
0
    return ldb_operr(ldb);
5964
0
  }
5965
5966
0
  if (!dom_sid_equal(sid, &sid2)) {
5967
    /* someone is trying to spoof another account */
5968
0
    DEBUG(0,(__location__ ": Bad DSA objectGUID %s for sid %s - expected sid %s\n",
5969
0
       GUID_string(tmp_ctx, dsa_guid),
5970
0
       dom_sid_string(tmp_ctx, sid),
5971
0
       dom_sid_string(tmp_ctx, &sid2)));
5972
0
    talloc_free(tmp_ctx);
5973
0
    return ldb_operr(ldb);
5974
0
  }
5975
5976
0
  talloc_free(tmp_ctx);
5977
0
  return LDB_SUCCESS;
5978
0
}
5979
5980
static const char * const secret_attributes[] = {
5981
  DSDB_SECRET_ATTRIBUTES,
5982
  NULL
5983
};
5984
5985
/*
5986
  check if the attribute belongs to the RODC filtered attribute set
5987
  Note that attributes that are in the filtered attribute set are the
5988
  ones that _are_ always sent to a RODC
5989
*/
5990
bool dsdb_attr_in_rodc_fas(const struct dsdb_attribute *sa)
5991
0
{
5992
  /* they never get secret attributes */
5993
0
  if (ldb_attr_in_list(secret_attributes, sa->lDAPDisplayName)) {
5994
0
    return false;
5995
0
  }
5996
5997
  /* they do get non-secret critical attributes */
5998
0
  if (sa->schemaFlagsEx & SCHEMA_FLAG_ATTR_IS_CRITICAL) {
5999
0
    return true;
6000
0
  }
6001
6002
  /* they do get non-secret attributes marked as being in the FAS  */
6003
0
  if (sa->searchFlags & SEARCH_FLAG_RODC_ATTRIBUTE) {
6004
0
    return true;
6005
0
  }
6006
6007
  /* other attributes are denied */
6008
0
  return false;
6009
0
}
6010
6011
/* return fsmo role dn and role owner dn for a particular role*/
6012
WERROR dsdb_get_fsmo_role_info(TALLOC_CTX *tmp_ctx,
6013
             struct ldb_context *ldb,
6014
             uint32_t role,
6015
             struct ldb_dn **fsmo_role_dn,
6016
             struct ldb_dn **role_owner_dn)
6017
0
{
6018
0
  int ret;
6019
0
  switch (role) {
6020
0
  case DREPL_NAMING_MASTER:
6021
0
    *fsmo_role_dn = samdb_partitions_dn(ldb, tmp_ctx);
6022
0
    ret = samdb_reference_dn(ldb, tmp_ctx, *fsmo_role_dn, "fSMORoleOwner", role_owner_dn);
6023
0
    if (ret != LDB_SUCCESS) {
6024
0
      DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Naming Master object - %s\n",
6025
0
         ldb_errstring(ldb)));
6026
0
      talloc_free(tmp_ctx);
6027
0
      return WERR_DS_DRA_INTERNAL_ERROR;
6028
0
    }
6029
0
    break;
6030
0
  case DREPL_INFRASTRUCTURE_MASTER:
6031
0
    *fsmo_role_dn = samdb_infrastructure_dn(ldb, tmp_ctx);
6032
0
    ret = samdb_reference_dn(ldb, tmp_ctx, *fsmo_role_dn, "fSMORoleOwner", role_owner_dn);
6033
0
    if (ret != LDB_SUCCESS) {
6034
0
      DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Schema Master object - %s\n",
6035
0
         ldb_errstring(ldb)));
6036
0
      talloc_free(tmp_ctx);
6037
0
      return WERR_DS_DRA_INTERNAL_ERROR;
6038
0
    }
6039
0
    break;
6040
0
  case DREPL_RID_MASTER:
6041
0
    ret = samdb_rid_manager_dn(ldb, tmp_ctx, fsmo_role_dn);
6042
0
    if (ret != LDB_SUCCESS) {
6043
0
      DEBUG(0, (__location__ ": Failed to find RID Manager object - %s\n", ldb_errstring(ldb)));
6044
0
      talloc_free(tmp_ctx);
6045
0
      return WERR_DS_DRA_INTERNAL_ERROR;
6046
0
    }
6047
6048
0
    ret = samdb_reference_dn(ldb, tmp_ctx, *fsmo_role_dn, "fSMORoleOwner", role_owner_dn);
6049
0
    if (ret != LDB_SUCCESS) {
6050
0
      DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in RID Manager object - %s\n",
6051
0
         ldb_errstring(ldb)));
6052
0
      talloc_free(tmp_ctx);
6053
0
      return WERR_DS_DRA_INTERNAL_ERROR;
6054
0
    }
6055
0
    break;
6056
0
  case DREPL_SCHEMA_MASTER:
6057
0
    *fsmo_role_dn = ldb_get_schema_basedn(ldb);
6058
0
    ret = samdb_reference_dn(ldb, tmp_ctx, *fsmo_role_dn, "fSMORoleOwner", role_owner_dn);
6059
0
    if (ret != LDB_SUCCESS) {
6060
0
      DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Schema Master object - %s\n",
6061
0
         ldb_errstring(ldb)));
6062
0
      talloc_free(tmp_ctx);
6063
0
      return WERR_DS_DRA_INTERNAL_ERROR;
6064
0
    }
6065
0
    break;
6066
0
  case DREPL_PDC_MASTER:
6067
0
    *fsmo_role_dn = ldb_get_default_basedn(ldb);
6068
0
    ret = samdb_reference_dn(ldb, tmp_ctx, *fsmo_role_dn, "fSMORoleOwner", role_owner_dn);
6069
0
    if (ret != LDB_SUCCESS) {
6070
0
      DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Pd Master object - %s\n",
6071
0
         ldb_errstring(ldb)));
6072
0
      talloc_free(tmp_ctx);
6073
0
      return WERR_DS_DRA_INTERNAL_ERROR;
6074
0
    }
6075
0
    break;
6076
0
  default:
6077
0
    return WERR_DS_DRA_INTERNAL_ERROR;
6078
0
  }
6079
0
  return WERR_OK;
6080
0
}
6081
6082
const char *samdb_dn_to_dnshostname(struct ldb_context *ldb,
6083
            TALLOC_CTX *mem_ctx,
6084
            struct ldb_dn *server_dn)
6085
0
{
6086
0
  int ldb_ret;
6087
0
  struct ldb_result *res = NULL;
6088
0
  const char * const attrs[] = { "dNSHostName", NULL};
6089
6090
0
  ldb_ret = ldb_search(ldb, mem_ctx, &res,
6091
0
           server_dn,
6092
0
           LDB_SCOPE_BASE,
6093
0
           attrs, NULL);
6094
0
  if (ldb_ret != LDB_SUCCESS) {
6095
0
    DEBUG(4, ("Failed to find dNSHostName for dn %s, ldb error: %s\n",
6096
0
        ldb_dn_get_linearized(server_dn), ldb_errstring(ldb)));
6097
0
    return NULL;
6098
0
  }
6099
6100
0
  return ldb_msg_find_attr_as_string(res->msgs[0], "dNSHostName", NULL);
6101
0
}
6102
6103
/*
6104
  returns true if an attribute is in the filter,
6105
  false otherwise, provided that attribute value is provided with the expression
6106
*/
6107
bool dsdb_attr_in_parse_tree(struct ldb_parse_tree *tree,
6108
           const char *attr)
6109
0
{
6110
0
       unsigned int i;
6111
0
       switch (tree->operation) {
6112
0
       case LDB_OP_AND:
6113
0
       case LDB_OP_OR:
6114
0
               for (i=0;i<tree->u.list.num_elements;i++) {
6115
0
                       if (dsdb_attr_in_parse_tree(tree->u.list.elements[i],
6116
0
                                                       attr))
6117
0
                               return true;
6118
0
               }
6119
0
               return false;
6120
0
       case LDB_OP_NOT:
6121
0
               return dsdb_attr_in_parse_tree(tree->u.isnot.child, attr);
6122
0
       case LDB_OP_EQUALITY:
6123
0
               if (ldb_attr_cmp(tree->u.equality.attr, attr) == 0) {
6124
0
                       return true;
6125
0
               }
6126
0
               return false;
6127
0
       case LDB_OP_GREATER:
6128
0
       case LDB_OP_LESS:
6129
0
       case LDB_OP_APPROX:
6130
0
               if (ldb_attr_cmp(tree->u.comparison.attr, attr) == 0) {
6131
0
                       return true;
6132
0
               }
6133
0
               return false;
6134
0
       case LDB_OP_SUBSTRING:
6135
0
               if (ldb_attr_cmp(tree->u.substring.attr, attr) == 0) {
6136
0
                       return true;
6137
0
               }
6138
0
               return false;
6139
0
       case LDB_OP_PRESENT:
6140
         /* (attrname=*) is not filtered out */
6141
0
               return false;
6142
0
       case LDB_OP_EXTENDED:
6143
0
               if (tree->u.extended.attr &&
6144
0
                   ldb_attr_cmp(tree->u.extended.attr, attr) == 0) {
6145
0
           return true;
6146
0
               }
6147
0
               return false;
6148
0
       }
6149
0
       return false;
6150
0
}
6151
6152
int dsdb_werror_at(struct ldb_context *ldb, int ldb_ecode, WERROR werr,
6153
       const char *location, const char *func,
6154
       const char *reason)
6155
0
{
6156
0
  if (reason == NULL) {
6157
0
    reason = win_errstr(werr);
6158
0
  }
6159
0
  ldb_asprintf_errstring(ldb, "%08X: %s at %s:%s",
6160
0
             W_ERROR_V(werr), reason, location, func);
6161
0
  return ldb_ecode;
6162
0
}
6163
6164
/*
6165
  map an ldb error code to an approximate NTSTATUS code
6166
 */
6167
NTSTATUS dsdb_ldb_err_to_ntstatus(int err)
6168
0
{
6169
0
  switch (err) {
6170
0
  case LDB_SUCCESS:
6171
0
    return NT_STATUS_OK;
6172
6173
0
  case LDB_ERR_PROTOCOL_ERROR:
6174
0
    return NT_STATUS_DEVICE_PROTOCOL_ERROR;
6175
6176
0
  case LDB_ERR_TIME_LIMIT_EXCEEDED:
6177
0
    return NT_STATUS_IO_TIMEOUT;
6178
6179
0
  case LDB_ERR_SIZE_LIMIT_EXCEEDED:
6180
0
    return NT_STATUS_BUFFER_TOO_SMALL;
6181
6182
0
  case LDB_ERR_COMPARE_FALSE:
6183
0
  case LDB_ERR_COMPARE_TRUE:
6184
0
    return NT_STATUS_REVISION_MISMATCH;
6185
6186
0
  case LDB_ERR_AUTH_METHOD_NOT_SUPPORTED:
6187
0
    return NT_STATUS_NOT_SUPPORTED;
6188
6189
0
  case LDB_ERR_STRONG_AUTH_REQUIRED:
6190
0
  case LDB_ERR_CONFIDENTIALITY_REQUIRED:
6191
0
  case LDB_ERR_SASL_BIND_IN_PROGRESS:
6192
0
  case LDB_ERR_INAPPROPRIATE_AUTHENTICATION:
6193
0
  case LDB_ERR_INVALID_CREDENTIALS:
6194
0
  case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
6195
0
  case LDB_ERR_UNWILLING_TO_PERFORM:
6196
0
    return NT_STATUS_ACCESS_DENIED;
6197
6198
0
  case LDB_ERR_NO_SUCH_OBJECT:
6199
0
    return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6200
6201
0
  case LDB_ERR_REFERRAL:
6202
0
  case LDB_ERR_NO_SUCH_ATTRIBUTE:
6203
0
    return NT_STATUS_NOT_FOUND;
6204
6205
0
  case LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION:
6206
0
    return NT_STATUS_NOT_SUPPORTED;
6207
6208
0
  case LDB_ERR_ADMIN_LIMIT_EXCEEDED:
6209
0
    return NT_STATUS_BUFFER_TOO_SMALL;
6210
6211
0
  case LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE:
6212
0
  case LDB_ERR_INAPPROPRIATE_MATCHING:
6213
0
  case LDB_ERR_CONSTRAINT_VIOLATION:
6214
0
  case LDB_ERR_INVALID_ATTRIBUTE_SYNTAX:
6215
0
  case LDB_ERR_INVALID_DN_SYNTAX:
6216
0
  case LDB_ERR_NAMING_VIOLATION:
6217
0
  case LDB_ERR_OBJECT_CLASS_VIOLATION:
6218
0
  case LDB_ERR_NOT_ALLOWED_ON_NON_LEAF:
6219
0
  case LDB_ERR_NOT_ALLOWED_ON_RDN:
6220
0
    return NT_STATUS_INVALID_PARAMETER;
6221
6222
0
  case LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS:
6223
0
  case LDB_ERR_ENTRY_ALREADY_EXISTS:
6224
0
    return NT_STATUS_ERROR_DS_OBJ_STRING_NAME_EXISTS;
6225
6226
0
  case LDB_ERR_BUSY:
6227
0
    return NT_STATUS_NETWORK_BUSY;
6228
6229
0
  case LDB_ERR_ALIAS_PROBLEM:
6230
0
  case LDB_ERR_ALIAS_DEREFERENCING_PROBLEM:
6231
0
  case LDB_ERR_UNAVAILABLE:
6232
0
  case LDB_ERR_LOOP_DETECT:
6233
0
  case LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED:
6234
0
  case LDB_ERR_AFFECTS_MULTIPLE_DSAS:
6235
0
  case LDB_ERR_OTHER:
6236
0
  case LDB_ERR_OPERATIONS_ERROR:
6237
0
    break;
6238
0
  }
6239
0
  return NT_STATUS_UNSUCCESSFUL;
6240
0
}
6241
6242
6243
/*
6244
  create a new naming context that will hold a partial replica
6245
 */
6246
int dsdb_create_partial_replica_NC(struct ldb_context *ldb,  struct ldb_dn *dn)
6247
0
{
6248
0
  TALLOC_CTX *tmp_ctx = talloc_new(ldb);
6249
0
  struct ldb_message *msg;
6250
0
  int ret;
6251
6252
0
  if (tmp_ctx == NULL) {
6253
0
    return ldb_oom(ldb);
6254
0
  }
6255
6256
0
  msg = ldb_msg_new(tmp_ctx);
6257
0
  if (msg == NULL) {
6258
0
    talloc_free(tmp_ctx);
6259
0
    return ldb_oom(ldb);
6260
0
  }
6261
6262
0
  msg->dn = dn;
6263
0
  ret = ldb_msg_add_string(msg, "objectClass", "top");
6264
0
  if (ret != LDB_SUCCESS) {
6265
0
    talloc_free(tmp_ctx);
6266
0
    return ldb_oom(ldb);
6267
0
  }
6268
6269
  /* [MS-DRSR] implies that we should only add the 'top'
6270
   * objectclass, but that would cause lots of problems with our
6271
   * objectclass code as top is not structural, so we add
6272
   * 'domainDNS' as well to keep things sane. We're expecting
6273
   * this new NC to be of objectclass domainDNS after
6274
   * replication anyway
6275
   */
6276
0
  ret = ldb_msg_add_string(msg, "objectClass", "domainDNS");
6277
0
  if (ret != LDB_SUCCESS) {
6278
0
    talloc_free(tmp_ctx);
6279
0
    return ldb_oom(ldb);
6280
0
  }
6281
6282
0
  ret = ldb_msg_add_fmt(msg, "instanceType", "%u",
6283
0
            INSTANCE_TYPE_IS_NC_HEAD|
6284
0
            INSTANCE_TYPE_NC_ABOVE|
6285
0
            INSTANCE_TYPE_UNINSTANT);
6286
0
  if (ret != LDB_SUCCESS) {
6287
0
    talloc_free(tmp_ctx);
6288
0
    return ldb_oom(ldb);
6289
0
  }
6290
6291
0
  ret = dsdb_add(ldb, msg, DSDB_MODIFY_PARTIAL_REPLICA);
6292
0
  if (ret != LDB_SUCCESS && ret != LDB_ERR_ENTRY_ALREADY_EXISTS) {
6293
0
    DEBUG(0,("Failed to create new NC for %s - %s (%s)\n",
6294
0
       ldb_dn_get_linearized(dn),
6295
0
       ldb_errstring(ldb), ldb_strerror(ret)));
6296
0
    talloc_free(tmp_ctx);
6297
0
    return ret;
6298
0
  }
6299
6300
0
  DEBUG(1,("Created new NC for %s\n", ldb_dn_get_linearized(dn)));
6301
6302
0
  talloc_free(tmp_ctx);
6303
0
  return LDB_SUCCESS;
6304
0
}
6305
6306
/*
6307
 * Return the effective badPwdCount
6308
 *
6309
 * This requires that the user_msg have (if present):
6310
 *  - badPasswordTime
6311
 *  - badPwdCount
6312
 *
6313
 * This also requires that the domain_msg have (if present):
6314
 *  - lockOutObservationWindow
6315
 */
6316
int dsdb_effective_badPwdCount(const struct ldb_message *user_msg,
6317
             int64_t lockOutObservationWindow,
6318
             NTTIME now)
6319
0
{
6320
0
  int64_t badPasswordTime;
6321
0
  badPasswordTime = ldb_msg_find_attr_as_int64(user_msg, "badPasswordTime", 0);
6322
6323
0
  if (badPasswordTime - lockOutObservationWindow >= now) {
6324
0
    return ldb_msg_find_attr_as_int(user_msg, "badPwdCount", 0);
6325
0
  } else {
6326
0
    return 0;
6327
0
  }
6328
0
}
6329
6330
/*
6331
 * Returns a user's PSO, or NULL if none was found
6332
 */
6333
static struct ldb_result *lookup_user_pso(struct ldb_context *sam_ldb,
6334
            TALLOC_CTX *mem_ctx,
6335
            const struct ldb_message *user_msg,
6336
            const char * const *attrs)
6337
0
{
6338
0
  struct ldb_result *res = NULL;
6339
0
  struct ldb_dn *pso_dn = NULL;
6340
0
  int ret;
6341
6342
  /* if the user has a PSO that applies, then use the PSO's setting */
6343
0
  pso_dn = ldb_msg_find_attr_as_dn(sam_ldb, mem_ctx, user_msg,
6344
0
           "msDS-ResultantPSO");
6345
6346
0
  if (pso_dn != NULL) {
6347
6348
0
    ret = dsdb_search_dn(sam_ldb, mem_ctx, &res, pso_dn, attrs, 0);
6349
0
    if (ret != LDB_SUCCESS) {
6350
6351
      /*
6352
       * log the error. The caller should fallback to using
6353
       * the default domain password settings
6354
       */
6355
0
      DBG_ERR("Error retrieving msDS-ResultantPSO %s for %s\n",
6356
0
        ldb_dn_get_linearized(pso_dn),
6357
0
        ldb_dn_get_linearized(user_msg->dn));
6358
0
    }
6359
0
    talloc_free(pso_dn);
6360
0
  }
6361
0
  return res;
6362
0
}
6363
6364
/*
6365
 * Return the msDS-LockoutObservationWindow for a user message
6366
 *
6367
 * This requires that the user_msg have (if present):
6368
 *  - msDS-ResultantPSO
6369
 */
6370
int64_t samdb_result_msds_LockoutObservationWindow(
6371
  struct ldb_context *sam_ldb,
6372
  TALLOC_CTX *mem_ctx,
6373
  struct ldb_dn *domain_dn,
6374
  const struct ldb_message *user_msg)
6375
0
{
6376
0
  int64_t lockOutObservationWindow;
6377
0
  struct ldb_result *res = NULL;
6378
0
  const char *attrs[] = { "msDS-LockoutObservationWindow",
6379
0
        NULL };
6380
0
  if (domain_dn == NULL) {
6381
0
    smb_panic("domain dn is NULL");
6382
0
  }
6383
0
  res = lookup_user_pso(sam_ldb, mem_ctx, user_msg, attrs);
6384
6385
0
  if (res != NULL) {
6386
0
    lockOutObservationWindow =
6387
0
      ldb_msg_find_attr_as_int64(res->msgs[0],
6388
0
               "msDS-LockoutObservationWindow",
6389
0
                DEFAULT_OBSERVATION_WINDOW);
6390
0
    talloc_free(res);
6391
0
  } else {
6392
6393
    /* no PSO was found, lookup the default domain setting */
6394
0
    lockOutObservationWindow =
6395
0
       samdb_search_int64(sam_ldb, mem_ctx, 0, domain_dn,
6396
0
              "lockOutObservationWindow", NULL);
6397
0
  }
6398
0
  return lockOutObservationWindow;
6399
0
}
6400
6401
/*
6402
 * Return the effective badPwdCount
6403
 *
6404
 * This requires that the user_msg have (if present):
6405
 *  - badPasswordTime
6406
 *  - badPwdCount
6407
 *  - msDS-ResultantPSO
6408
 */
6409
int samdb_result_effective_badPwdCount(struct ldb_context *sam_ldb,
6410
               TALLOC_CTX *mem_ctx,
6411
               struct ldb_dn *domain_dn,
6412
               const struct ldb_message *user_msg)
6413
0
{
6414
0
  struct timeval tv_now = timeval_current();
6415
0
  NTTIME now = timeval_to_nttime(&tv_now);
6416
0
  int64_t lockOutObservationWindow =
6417
0
    samdb_result_msds_LockoutObservationWindow(
6418
0
      sam_ldb, mem_ctx, domain_dn, user_msg);
6419
0
  return dsdb_effective_badPwdCount(user_msg, lockOutObservationWindow, now);
6420
0
}
6421
6422
/*
6423
 * Returns the lockoutThreshold that applies. If a PSO is specified, then that
6424
 * setting is used over the domain defaults
6425
 */
6426
static int64_t get_lockout_threshold(struct ldb_message *domain_msg,
6427
             struct ldb_message *pso_msg)
6428
0
{
6429
0
  if (pso_msg != NULL) {
6430
0
    return ldb_msg_find_attr_as_int(pso_msg,
6431
0
            "msDS-LockoutThreshold", 0);
6432
0
  } else {
6433
0
    return ldb_msg_find_attr_as_int(domain_msg,
6434
0
            "lockoutThreshold", 0);
6435
0
  }
6436
0
}
6437
6438
/*
6439
 * Returns the lockOutObservationWindow that applies. If a PSO is specified,
6440
 * then that setting is used over the domain defaults
6441
 */
6442
static int64_t get_lockout_observation_window(struct ldb_message *domain_msg,
6443
                struct ldb_message *pso_msg)
6444
0
{
6445
0
  if (pso_msg != NULL) {
6446
0
    return ldb_msg_find_attr_as_int64(pso_msg,
6447
0
              "msDS-LockoutObservationWindow",
6448
0
               DEFAULT_OBSERVATION_WINDOW);
6449
0
  } else {
6450
0
    return ldb_msg_find_attr_as_int64(domain_msg,
6451
0
              "lockOutObservationWindow",
6452
0
               DEFAULT_OBSERVATION_WINDOW);
6453
0
  }
6454
0
}
6455
6456
/*
6457
 * Prepare an update to the badPwdCount and associated attributes.
6458
 *
6459
 * This requires that the user_msg have (if present):
6460
 *  - objectSid
6461
 *  - badPasswordTime
6462
 *  - badPwdCount
6463
 *
6464
 * This also requires that the domain_msg have (if present):
6465
 *  - pwdProperties
6466
 *  - lockoutThreshold
6467
 *  - lockOutObservationWindow
6468
 *
6469
 * This also requires that the pso_msg have (if present):
6470
 *  - msDS-LockoutThreshold
6471
 *  - msDS-LockoutObservationWindow
6472
 */
6473
NTSTATUS dsdb_update_bad_pwd_count(TALLOC_CTX *mem_ctx,
6474
           struct ldb_context *sam_ctx,
6475
           struct ldb_message *user_msg,
6476
           struct ldb_message *domain_msg,
6477
           struct ldb_message *pso_msg,
6478
           struct ldb_message **_mod_msg)
6479
0
{
6480
0
  int ret, badPwdCount;
6481
0
  unsigned int i;
6482
0
  int64_t lockoutThreshold, lockOutObservationWindow;
6483
0
  struct dom_sid *sid;
6484
0
  struct timeval tv_now = timeval_current();
6485
0
  NTTIME now = timeval_to_nttime(&tv_now);
6486
0
  NTSTATUS status;
6487
0
  uint32_t pwdProperties, rid = 0;
6488
0
  struct ldb_message *mod_msg;
6489
6490
0
  sid = samdb_result_dom_sid(mem_ctx, user_msg, "objectSid");
6491
6492
0
  pwdProperties = ldb_msg_find_attr_as_uint(domain_msg,
6493
0
              "pwdProperties", -1);
6494
0
  if (sid && !(pwdProperties & DOMAIN_PASSWORD_LOCKOUT_ADMINS)) {
6495
0
    status = dom_sid_split_rid(NULL, sid, NULL, &rid);
6496
0
    if (!NT_STATUS_IS_OK(status)) {
6497
      /*
6498
       * This can't happen anyway, but always try
6499
       * and update the badPwdCount on failure
6500
       */
6501
0
      rid = 0;
6502
0
    }
6503
0
  }
6504
0
  TALLOC_FREE(sid);
6505
6506
  /*
6507
   * Work out if we are doing password lockout on the domain.
6508
   * Also, the built in administrator account is exempt:
6509
   * http://msdn.microsoft.com/en-us/library/windows/desktop/aa375371%28v=vs.85%29.aspx
6510
   */
6511
0
  lockoutThreshold = get_lockout_threshold(domain_msg, pso_msg);
6512
0
  if (lockoutThreshold == 0 || (rid == DOMAIN_RID_ADMINISTRATOR)) {
6513
0
    DEBUG(5, ("Not updating badPwdCount on %s after wrong password\n",
6514
0
        ldb_dn_get_linearized(user_msg->dn)));
6515
0
    return NT_STATUS_OK;
6516
0
  }
6517
6518
0
  mod_msg = ldb_msg_new(mem_ctx);
6519
0
  if (mod_msg == NULL) {
6520
0
    return NT_STATUS_NO_MEMORY;
6521
0
  }
6522
0
  mod_msg->dn = ldb_dn_copy(mod_msg, user_msg->dn);
6523
0
  if (mod_msg->dn == NULL) {
6524
0
    TALLOC_FREE(mod_msg);
6525
0
    return NT_STATUS_NO_MEMORY;
6526
0
  }
6527
6528
0
  lockOutObservationWindow = get_lockout_observation_window(domain_msg,
6529
0
                  pso_msg);
6530
6531
0
  badPwdCount = dsdb_effective_badPwdCount(user_msg, lockOutObservationWindow, now);
6532
6533
0
  badPwdCount++;
6534
6535
0
  ret = samdb_msg_add_int(sam_ctx, mod_msg, mod_msg, "badPwdCount", badPwdCount);
6536
0
  if (ret != LDB_SUCCESS) {
6537
0
    TALLOC_FREE(mod_msg);
6538
0
    return NT_STATUS_NO_MEMORY;
6539
0
  }
6540
0
  ret = samdb_msg_add_int64(sam_ctx, mod_msg, mod_msg, "badPasswordTime", now);
6541
0
  if (ret != LDB_SUCCESS) {
6542
0
    TALLOC_FREE(mod_msg);
6543
0
    return NT_STATUS_NO_MEMORY;
6544
0
  }
6545
6546
0
  if (dsdb_account_is_trust(user_msg)) {
6547
    /* Trust accounts cannot be locked out. */
6548
0
  } else if (badPwdCount >= lockoutThreshold) {
6549
0
    ret = samdb_msg_add_int64(sam_ctx, mod_msg, mod_msg, "lockoutTime", now);
6550
0
    if (ret != LDB_SUCCESS) {
6551
0
      TALLOC_FREE(mod_msg);
6552
0
      return NT_STATUS_NO_MEMORY;
6553
0
    }
6554
0
    DEBUGC( DBGC_AUTH, 1, ("Locked out user %s after %d wrong passwords\n",
6555
0
        ldb_dn_get_linearized(user_msg->dn), badPwdCount));
6556
0
  } else {
6557
0
    DEBUGC( DBGC_AUTH, 5, ("Updated badPwdCount on %s after %d wrong passwords\n",
6558
0
        ldb_dn_get_linearized(user_msg->dn), badPwdCount));
6559
0
  }
6560
6561
  /* mark all the message elements as LDB_FLAG_MOD_REPLACE */
6562
0
  for (i=0; i< mod_msg->num_elements; i++) {
6563
0
    mod_msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
6564
0
  }
6565
6566
0
  *_mod_msg = mod_msg;
6567
0
  return NT_STATUS_OK;
6568
0
}
6569
6570
/**
6571
 * Sets defaults for a User object
6572
 * List of default attributes set:
6573
 *  accountExpires, badPasswordTime, badPwdCount,
6574
 *  codePage, countryCode, lastLogoff, lastLogon
6575
 *  logonCount, pwdLastSet
6576
 */
6577
int dsdb_user_obj_set_defaults(struct ldb_context *ldb,
6578
             struct ldb_message *usr_obj,
6579
             struct ldb_request *req)
6580
0
{
6581
0
  size_t i;
6582
0
  int ret;
6583
0
  static const struct attribute_values {
6584
0
    const char *name;
6585
0
    const char *value;
6586
0
    const char *add_value;
6587
0
    const char *mod_value;
6588
0
    const char *control;
6589
0
    unsigned add_flags;
6590
0
    unsigned mod_flags;
6591
0
  } map[] = {
6592
0
    {
6593
0
      .name = "accountExpires",
6594
0
      .add_value = "9223372036854775807",
6595
0
      .mod_value = "0",
6596
0
    },
6597
0
    {
6598
0
      .name = "badPasswordTime",
6599
0
      .value = "0"
6600
0
    },
6601
0
    {
6602
0
      .name = "badPwdCount",
6603
0
      .value = "0"
6604
0
    },
6605
0
    {
6606
0
      .name = "codePage",
6607
0
      .value = "0"
6608
0
    },
6609
0
    {
6610
0
      .name = "countryCode",
6611
0
      .value = "0"
6612
0
    },
6613
0
    {
6614
0
      .name = "lastLogoff",
6615
0
      .value = "0"
6616
0
    },
6617
0
    {
6618
0
      .name = "lastLogon",
6619
0
      .value = "0"
6620
0
    },
6621
0
    {
6622
0
      .name = "logonCount",
6623
0
      .value = "0"
6624
0
    },
6625
0
    {
6626
0
      .name = "logonHours",
6627
0
      .add_flags = DSDB_FLAG_INTERNAL_FORCE_META_DATA,
6628
0
    },
6629
0
    {
6630
0
      .name = "pwdLastSet",
6631
0
      .value = "0",
6632
0
      .control = DSDB_CONTROL_PASSWORD_DEFAULT_LAST_SET_OID,
6633
0
    },
6634
0
    {
6635
0
      .name = "adminCount",
6636
0
      .mod_value = "0",
6637
0
    },
6638
0
    {
6639
0
      .name = "operatorCount",
6640
0
      .mod_value = "0",
6641
0
    },
6642
0
  };
6643
6644
0
  for (i = 0; i < ARRAY_SIZE(map); i++) {
6645
0
    bool added = false;
6646
0
    const char *value = NULL;
6647
0
    unsigned flags = 0;
6648
6649
0
    if (req != NULL && req->operation == LDB_ADD) {
6650
0
      value = map[i].add_value;
6651
0
      flags = map[i].add_flags;
6652
0
    } else {
6653
0
      value = map[i].mod_value;
6654
0
      flags = map[i].mod_flags;
6655
0
    }
6656
6657
0
    if (value == NULL) {
6658
0
      value = map[i].value;
6659
0
    }
6660
6661
0
    if (value != NULL) {
6662
0
      flags |= LDB_FLAG_MOD_ADD;
6663
0
    }
6664
6665
0
    if (flags == 0) {
6666
0
      continue;
6667
0
    }
6668
6669
0
    ret = samdb_find_or_add_attribute_ex(ldb, usr_obj,
6670
0
                 map[i].name,
6671
0
                 value, flags,
6672
0
                 &added);
6673
0
    if (ret != LDB_SUCCESS) {
6674
0
      return ret;
6675
0
    }
6676
6677
0
    if (req != NULL && added && map[i].control != NULL) {
6678
0
      ret = ldb_request_add_control(req,
6679
0
                  map[i].control,
6680
0
                  false, NULL);
6681
0
      if (ret != LDB_SUCCESS) {
6682
0
        return ret;
6683
0
      }
6684
0
    }
6685
0
  }
6686
6687
0
  return LDB_SUCCESS;
6688
0
}
6689
6690
/**
6691
 * Sets 'sAMAccountType on user object based on userAccountControl.
6692
 * This function is used in processing both 'add' and 'modify' requests.
6693
 * @param ldb Current ldb_context
6694
 * @param usr_obj ldb_message representing User object
6695
 * @param user_account_control Value for userAccountControl flags
6696
 * @param account_type_p Optional pointer to account_type to return
6697
 * @return LDB_SUCCESS or LDB_ERR* code on failure
6698
 */
6699
int dsdb_user_obj_set_account_type(struct ldb_context *ldb, struct ldb_message *usr_obj,
6700
           uint32_t user_account_control, uint32_t *account_type_p)
6701
0
{
6702
0
  int ret;
6703
0
  uint32_t account_type;
6704
6705
0
  account_type = ds_uf2atype(user_account_control);
6706
0
  if (account_type == 0) {
6707
0
    ldb_set_errstring(ldb, "dsdb: Unrecognized account type!");
6708
0
    return LDB_ERR_UNWILLING_TO_PERFORM;
6709
0
  }
6710
0
  ret = samdb_msg_add_uint_flags(ldb, usr_obj, usr_obj,
6711
0
               "sAMAccountType",
6712
0
               account_type,
6713
0
               LDB_FLAG_MOD_REPLACE);
6714
0
  if (ret != LDB_SUCCESS) {
6715
0
    return ret;
6716
0
  }
6717
6718
0
  if (account_type_p) {
6719
0
    *account_type_p = account_type;
6720
0
  }
6721
6722
0
  return LDB_SUCCESS;
6723
0
}
6724
6725
/**
6726
 * Determine and set primaryGroupID based on userAccountControl value.
6727
 * This function is used in processing both 'add' and 'modify' requests.
6728
 * @param ldb Current ldb_context
6729
 * @param usr_obj ldb_message representing User object
6730
 * @param user_account_control Value for userAccountControl flags
6731
 * @param group_rid_p Optional pointer to group RID to return
6732
 * @return LDB_SUCCESS or LDB_ERR* code on failure
6733
 */
6734
int dsdb_user_obj_set_primary_group_id(struct ldb_context *ldb, struct ldb_message *usr_obj,
6735
               uint32_t user_account_control, uint32_t *group_rid_p)
6736
0
{
6737
0
  int ret;
6738
0
  uint32_t rid;
6739
6740
0
  rid = ds_uf2prim_group_rid(user_account_control);
6741
6742
0
  ret = samdb_msg_add_uint_flags(ldb, usr_obj, usr_obj,
6743
0
               "primaryGroupID", rid,
6744
0
               LDB_FLAG_MOD_REPLACE);
6745
0
  if (ret != LDB_SUCCESS) {
6746
0
    return ret;
6747
0
  }
6748
6749
0
  if (group_rid_p) {
6750
0
    *group_rid_p = rid;
6751
0
  }
6752
6753
0
  return LDB_SUCCESS;
6754
0
}
6755
6756
/**
6757
 * Returns True if the source and target DNs both have the same naming context,
6758
 * i.e. they're both in the same partition.
6759
 */
6760
bool dsdb_objects_have_same_nc(struct ldb_context *ldb,
6761
             TALLOC_CTX *mem_ctx,
6762
             struct ldb_dn *source_dn,
6763
             struct ldb_dn *target_dn)
6764
0
{
6765
0
  TALLOC_CTX *tmp_ctx;
6766
0
  struct ldb_dn *source_nc = NULL;
6767
0
  struct ldb_dn *target_nc = NULL;
6768
0
  int ret;
6769
0
  bool same_nc = true;
6770
6771
0
  tmp_ctx = talloc_new(mem_ctx);
6772
0
  if (tmp_ctx == NULL) {
6773
0
    return ldb_oom(ldb);
6774
0
  }
6775
6776
0
  ret = dsdb_find_nc_root(ldb, tmp_ctx, source_dn, &source_nc);
6777
  /* fix clang warning */
6778
0
  if (source_nc == NULL) {
6779
0
    ret = LDB_ERR_OTHER;
6780
0
  }
6781
0
  if (ret != LDB_SUCCESS) {
6782
0
    DBG_ERR("Failed to find base DN for source %s: %s\n",
6783
0
      ldb_dn_get_linearized(source_dn), ldb_errstring(ldb));
6784
0
    talloc_free(tmp_ctx);
6785
0
    return true;
6786
0
  }
6787
6788
0
  ret = dsdb_find_nc_root(ldb, tmp_ctx, target_dn, &target_nc);
6789
  /* fix clang warning */
6790
0
  if (target_nc == NULL) {
6791
0
    ret = LDB_ERR_OTHER;
6792
0
  }
6793
0
  if (ret != LDB_SUCCESS) {
6794
0
    DBG_ERR("Failed to find base DN for target %s: %s\n",
6795
0
      ldb_dn_get_linearized(target_dn), ldb_errstring(ldb));
6796
0
    talloc_free(tmp_ctx);
6797
0
    return true;
6798
0
  }
6799
6800
0
  same_nc = (ldb_dn_compare(source_nc, target_nc) == 0);
6801
6802
0
  talloc_free(tmp_ctx);
6803
6804
0
  return same_nc;
6805
0
}
6806
/*
6807
 * Context for dsdb_count_domain_callback
6808
 */
6809
struct dsdb_count_domain_context {
6810
  /*
6811
   * Number of matching records
6812
   */
6813
  size_t count;
6814
  /*
6815
   * sid of the domain that the records must belong to.
6816
   * if NULL records can belong to any domain.
6817
   */
6818
  struct dom_sid *dom_sid;
6819
};
6820
6821
/*
6822
 * @brief ldb async callback for dsdb_domain_count.
6823
 *
6824
 * count the number of records in the database matching an LDAP query,
6825
 * optionally filtering for domain membership.
6826
 *
6827
 * @param [in,out] req the ldb request being processed
6828
 *                    req->context contains:
6829
 *                        count   The number of matching records
6830
 *                        dom_sid The domain sid, if present records must belong
6831
 *                                to the domain to be counted.
6832
 *@param [in,out] ares The query result.
6833
 *
6834
 * @return an LDB error code
6835
 *
6836
 */
6837
static int dsdb_count_domain_callback(
6838
  struct ldb_request *req,
6839
  struct ldb_reply *ares)
6840
0
{
6841
6842
0
  if (ares == NULL) {
6843
0
    return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
6844
0
  }
6845
0
  if (ares->error != LDB_SUCCESS) {
6846
0
    int error = ares->error;
6847
0
    TALLOC_FREE(ares);
6848
0
    return ldb_request_done(req, error);
6849
0
  }
6850
6851
0
  switch (ares->type) {
6852
0
  case LDB_REPLY_ENTRY:
6853
0
  {
6854
0
    struct dsdb_count_domain_context *context = NULL;
6855
0
    ssize_t ret;
6856
0
    bool in_domain;
6857
0
    struct dom_sid sid;
6858
0
    const struct ldb_val *v;
6859
6860
0
    context = req->context;
6861
0
    if (context->dom_sid == NULL) {
6862
0
      context->count++;
6863
0
      break;
6864
0
    }
6865
6866
0
    v = ldb_msg_find_ldb_val(ares->message, "objectSid");
6867
0
    if (v == NULL) {
6868
0
      break;
6869
0
    }
6870
6871
0
    ret = sid_parse(v->data, v->length, &sid);
6872
0
    if (ret == -1) {
6873
0
      break;
6874
0
    }
6875
6876
0
    in_domain = dom_sid_in_domain(context->dom_sid, &sid);
6877
0
    if (!in_domain) {
6878
0
      break;
6879
0
    }
6880
6881
0
    context->count++;
6882
0
    break;
6883
0
  }
6884
0
  case LDB_REPLY_REFERRAL:
6885
0
    break;
6886
6887
0
  case LDB_REPLY_DONE:
6888
0
    TALLOC_FREE(ares);
6889
0
    return ldb_request_done(req, LDB_SUCCESS);
6890
0
  }
6891
6892
0
  TALLOC_FREE(ares);
6893
6894
0
  return LDB_SUCCESS;
6895
0
}
6896
6897
/*
6898
 * @brief Count the number of records matching a query.
6899
 *
6900
 * Count the number of entries in the database matching the supplied query,
6901
 * optionally filtering only those entries belonging to the supplied domain.
6902
 *
6903
 * @param ldb [in] Current ldb context
6904
 * @param count [out] Pointer to the count
6905
 * @param base [in] The base dn for the query
6906
 * @param dom_sid [in] The domain sid, if non NULL records that are not a member
6907
 *                     of the domain are ignored.
6908
 * @param scope [in] Search scope.
6909
 * @param exp_fmt [in] format string for the query.
6910
 *
6911
 * @return LDB_STATUS code.
6912
 */
6913
int PRINTF_ATTRIBUTE(6, 7) dsdb_domain_count(
6914
  struct ldb_context *ldb,
6915
  size_t *count,
6916
  struct ldb_dn *base,
6917
  struct dom_sid *dom_sid,
6918
  enum ldb_scope scope,
6919
  const char *exp_fmt, ...)
6920
0
{
6921
0
  TALLOC_CTX *tmp_ctx = NULL;
6922
0
  struct ldb_request *req = NULL;
6923
0
  struct dsdb_count_domain_context *context = NULL;
6924
0
  char *expression = NULL;
6925
0
  const char *object_sid[] = {"objectSid", NULL};
6926
0
  const char *none[] = {NULL};
6927
0
  va_list ap;
6928
0
  int ret;
6929
6930
0
  *count = 0;
6931
0
  tmp_ctx = talloc_new(ldb);
6932
0
  if (tmp_ctx == NULL) {
6933
0
    return ldb_oom(ldb);
6934
0
  }
6935
6936
0
  context = talloc_zero(tmp_ctx, struct dsdb_count_domain_context);
6937
0
  if (context == NULL) {
6938
0
    return LDB_ERR_OPERATIONS_ERROR;
6939
0
  }
6940
0
  context->dom_sid = dom_sid;
6941
6942
0
  if (exp_fmt) {
6943
0
    va_start(ap, exp_fmt);
6944
0
    expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
6945
0
    va_end(ap);
6946
6947
0
    if (expression == NULL) {
6948
0
      TALLOC_FREE(context);
6949
0
      TALLOC_FREE(tmp_ctx);
6950
0
      return LDB_ERR_OPERATIONS_ERROR;
6951
0
    }
6952
0
  }
6953
6954
0
  ret = ldb_build_search_req(
6955
0
    &req,
6956
0
    ldb,
6957
0
    tmp_ctx,
6958
0
    base,
6959
0
    scope,
6960
0
    expression,
6961
0
    (dom_sid == NULL) ? none : object_sid,
6962
0
    NULL,
6963
0
    context,
6964
0
    dsdb_count_domain_callback,
6965
0
    NULL);
6966
0
  ldb_req_set_location(req, "dsdb_domain_count");
6967
6968
0
  if (ret != LDB_SUCCESS) goto done;
6969
6970
0
  ret = ldb_request(ldb, req);
6971
6972
0
  if (ret == LDB_SUCCESS) {
6973
0
    ret = ldb_wait(req->handle, LDB_WAIT_ALL);
6974
0
    if (ret == LDB_SUCCESS) {
6975
0
      *count = context->count;
6976
0
    }
6977
0
  }
6978
6979
6980
0
done:
6981
0
  TALLOC_FREE(expression);
6982
0
  TALLOC_FREE(req);
6983
0
  TALLOC_FREE(context);
6984
0
  TALLOC_FREE(tmp_ctx);
6985
6986
0
  return ret;
6987
0
}
6988
6989
/*
6990
 * Returns 1 if 'sids' contains the Protected Users group SID for the domain, 0
6991
 * if not. Returns a negative value on error.
6992
 */
6993
int dsdb_is_protected_user(struct ldb_context *ldb,
6994
         const struct auth_SidAttr *sids,
6995
         uint32_t num_sids)
6996
0
{
6997
0
  const struct dom_sid *domain_sid = NULL;
6998
0
  struct dom_sid protected_users_sid;
6999
0
  uint32_t i;
7000
7001
0
  domain_sid = samdb_domain_sid(ldb);
7002
0
  if (domain_sid == NULL) {
7003
0
    return -1;
7004
0
  }
7005
7006
0
  protected_users_sid = *domain_sid;
7007
0
  if (!sid_append_rid(&protected_users_sid, DOMAIN_RID_PROTECTED_USERS)) {
7008
0
    return -1;
7009
0
  }
7010
7011
0
  for (i = 0; i < num_sids; ++i) {
7012
0
    if (dom_sid_equal(&protected_users_sid, &sids[i].sid)) {
7013
0
      return 1;
7014
0
    }
7015
0
  }
7016
7017
0
  return 0;
7018
0
}
7019
7020
bool dsdb_account_is_trust(const struct ldb_message *msg)
7021
0
{
7022
0
  uint32_t userAccountControl;
7023
7024
0
  userAccountControl = ldb_msg_find_attr_as_uint(msg,
7025
0
                   "userAccountControl",
7026
0
                   0);
7027
0
  return userAccountControl & UF_TRUST_ACCOUNT_MASK;
7028
0
}