Coverage Report

Created: 2026-01-16 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source4/dsdb/common/util_samr.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS implementation.
3
4
   Helpers to add users and groups to the DB
5
6
   Copyright (C) Andrew Tridgell 2004
7
   Copyright (C) Volker Lendecke 2004
8
   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2010
9
   Copyright (C) Matthias Dieter Wallnöfer 2009
10
11
   This program is free software; you can redistribute it and/or modify
12
   it under the terms of the GNU General Public License as published by
13
   the Free Software Foundation; either version 3 of the License, or
14
   (at your option) any later version.
15
16
   This program is distributed in the hope that it will be useful,
17
   but WITHOUT ANY WARRANTY; without even the implied warranty of
18
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
   GNU General Public License for more details.
20
21
   You should have received a copy of the GNU General Public License
22
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
23
*/
24
25
#include "includes.h"
26
#include "dsdb/samdb/samdb.h"
27
#include "dsdb/common/util.h"
28
#include "../libds/common/flags.h"
29
#include "libcli/security/security.h"
30
31
#include "libds/common/flag_mapping.h"
32
33
/* Add a user, SAMR style, including the correct transaction
34
 * semantics.  Used by the SAMR server and by pdb_samba4 */
35
NTSTATUS dsdb_add_user(struct ldb_context *ldb,
36
           TALLOC_CTX *mem_ctx,
37
           const char *account_name,
38
           uint32_t acct_flags,
39
           const struct dom_sid *forced_sid,
40
           struct dom_sid **sid,
41
           struct ldb_dn **dn)
42
0
{
43
0
  const char *name;
44
0
  struct ldb_message *msg;
45
0
  int ret;
46
0
  const char *container, *obj_class=NULL;
47
0
  char *cn_name;
48
0
  size_t cn_name_len;
49
50
0
  const char *attrs[] = {
51
0
    "objectSid",
52
0
    "userAccountControl",
53
0
    NULL
54
0
  };
55
56
0
  uint32_t user_account_control;
57
0
  struct ldb_dn *account_dn;
58
0
  struct dom_sid *account_sid;
59
60
0
  const char *account_name_encoded = NULL;
61
62
0
  TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
63
0
  NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
64
65
0
  account_name_encoded = ldb_binary_encode_string(tmp_ctx, account_name);
66
0
  if (account_name_encoded == NULL) {
67
0
    talloc_free(tmp_ctx);
68
0
    return NT_STATUS_NO_MEMORY;
69
0
  }
70
71
  /*
72
   * Start a transaction, so we can query and do a subsequent atomic
73
   * modify
74
   */
75
76
0
  ret = ldb_transaction_start(ldb);
77
0
  if (ret != LDB_SUCCESS) {
78
0
    DEBUG(0,("Failed to start a transaction for user creation: %s\n",
79
0
       ldb_errstring(ldb)));
80
0
    talloc_free(tmp_ctx);
81
0
    return NT_STATUS_LOCK_NOT_GRANTED;
82
0
  }
83
84
  /* check if the user already exists */
85
0
  name = samdb_search_string(ldb, tmp_ctx, NULL,
86
0
           "sAMAccountName",
87
0
           "(&(sAMAccountName=%s)(objectclass=user))",
88
0
           account_name_encoded);
89
0
  if (name != NULL) {
90
0
    ldb_transaction_cancel(ldb);
91
0
    talloc_free(tmp_ctx);
92
0
    return NT_STATUS_USER_EXISTS;
93
0
  }
94
95
0
  cn_name = talloc_strdup(tmp_ctx, account_name);
96
0
  if (!cn_name) {
97
0
    ldb_transaction_cancel(ldb);
98
0
    talloc_free(tmp_ctx);
99
0
    return NT_STATUS_NO_MEMORY;
100
0
  }
101
102
0
  cn_name_len = strlen(cn_name);
103
0
  if (cn_name_len < 1) {
104
0
    ldb_transaction_cancel(ldb);
105
0
    talloc_free(tmp_ctx);
106
0
    return NT_STATUS_INVALID_PARAMETER;
107
0
  }
108
109
0
  msg = ldb_msg_new(tmp_ctx);
110
0
  if (msg == NULL) {
111
0
    ldb_transaction_cancel(ldb);
112
0
    talloc_free(tmp_ctx);
113
0
    return NT_STATUS_NO_MEMORY;
114
0
  }
115
116
  /* This must be one of these values *only* */
117
0
  if (acct_flags == ACB_NORMAL) {
118
0
    container = "CN=Users";
119
0
    obj_class = "user";
120
0
    user_account_control = UF_NORMAL_ACCOUNT;
121
0
  } else if (acct_flags == ACB_WSTRUST) {
122
0
    if (cn_name[cn_name_len - 1] != '$') {
123
0
      ldb_transaction_cancel(ldb);
124
0
      return NT_STATUS_FOOBAR;
125
0
    }
126
0
    cn_name[cn_name_len - 1] = '\0';
127
0
    container = "CN=Computers";
128
0
    obj_class = "computer";
129
0
    user_account_control = UF_WORKSTATION_TRUST_ACCOUNT;
130
131
0
  } else if (acct_flags == ACB_SVRTRUST) {
132
0
    if (cn_name[cn_name_len - 1] != '$') {
133
0
      ldb_transaction_cancel(ldb);
134
0
      return NT_STATUS_FOOBAR;
135
0
    }
136
0
    cn_name[cn_name_len - 1] = '\0';
137
0
    container = "OU=Domain Controllers";
138
0
    obj_class = "computer";
139
0
    user_account_control = UF_SERVER_TRUST_ACCOUNT;
140
0
  } else if (acct_flags == ACB_DOMTRUST) {
141
0
    DEBUG(3, ("Invalid account flags specified:  cannot create domain trusts via this interface (must use LSA CreateTrustedDomain calls\n"));
142
0
    ldb_transaction_cancel(ldb);
143
0
    talloc_free(tmp_ctx);
144
0
    return NT_STATUS_INVALID_PARAMETER;
145
0
  } else {
146
0
    DEBUG(3, ("Invalid account flags specified 0x%08X, must be exactly one of \n"
147
0
        "ACB_NORMAL (0x%08X) ACB_WSTRUST (0x%08X) or ACB_SVRTRUST (0x%08X)\n",
148
0
        acct_flags,
149
0
        ACB_NORMAL, ACB_WSTRUST, ACB_SVRTRUST));
150
0
    ldb_transaction_cancel(ldb);
151
0
    talloc_free(tmp_ctx);
152
0
    return NT_STATUS_INVALID_PARAMETER;
153
0
  }
154
155
0
  user_account_control |= UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD;
156
157
  /* add core elements to the ldb_message for the user */
158
0
  msg->dn = ldb_dn_copy(msg, ldb_get_default_basedn(ldb));
159
0
  if ( ! ldb_dn_add_child_fmt(msg->dn, "CN=%s,%s", cn_name, container)) {
160
0
    ldb_transaction_cancel(ldb);
161
0
    talloc_free(tmp_ctx);
162
0
    return NT_STATUS_FOOBAR;
163
0
  }
164
165
0
  ret = ldb_msg_add_string(msg, "sAMAccountName", account_name);
166
0
  if (ret != LDB_SUCCESS) {
167
0
    goto failed;
168
0
  }
169
0
  ret = ldb_msg_add_string(msg, "objectClass", obj_class);
170
0
  if (ret != LDB_SUCCESS) {
171
0
    goto failed;
172
0
  }
173
0
  ret = samdb_msg_add_uint(ldb, tmp_ctx, msg,
174
0
         "userAccountControl",
175
0
         user_account_control);
176
0
  if (ret != LDB_SUCCESS) {
177
0
    goto failed;
178
0
  }
179
180
  /* This is only here for migrations using pdb_samba4, the
181
   * caller and the samldb are responsible for ensuring it makes
182
   * sense */
183
0
  if (forced_sid) {
184
0
    ret = samdb_msg_add_dom_sid(ldb, msg, msg, "objectSID", forced_sid);
185
0
    if (ret != LDB_SUCCESS) {
186
0
      ldb_transaction_cancel(ldb);
187
0
      talloc_free(tmp_ctx);
188
0
      return NT_STATUS_INTERNAL_ERROR;
189
0
    }
190
0
  }
191
192
  /* create the user */
193
0
  ret = ldb_add(ldb, msg);
194
0
  switch (ret) {
195
0
  case LDB_SUCCESS:
196
0
    break;
197
0
  case LDB_ERR_ENTRY_ALREADY_EXISTS:
198
0
    ldb_transaction_cancel(ldb);
199
0
    DEBUG(0,("Failed to create user record %s: %s\n",
200
0
       ldb_dn_get_linearized(msg->dn),
201
0
       ldb_errstring(ldb)));
202
0
    talloc_free(tmp_ctx);
203
0
    return NT_STATUS_USER_EXISTS;
204
0
  case LDB_ERR_UNWILLING_TO_PERFORM:
205
0
  case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
206
0
    ldb_transaction_cancel(ldb);
207
0
    DEBUG(0,("Failed to create user record %s: %s\n",
208
0
       ldb_dn_get_linearized(msg->dn),
209
0
       ldb_errstring(ldb)));
210
0
    talloc_free(tmp_ctx);
211
0
    return NT_STATUS_ACCESS_DENIED;
212
0
  default:
213
0
    ldb_transaction_cancel(ldb);
214
0
    DEBUG(0,("Failed to create user record %s: %s\n",
215
0
       ldb_dn_get_linearized(msg->dn),
216
0
       ldb_errstring(ldb)));
217
0
    talloc_free(tmp_ctx);
218
0
    return NT_STATUS_INTERNAL_DB_CORRUPTION;
219
0
  }
220
221
0
  account_dn = msg->dn;
222
223
  /* retrieve the sid and account control bits for the user just created */
224
0
  ret = dsdb_search_one(ldb, tmp_ctx, &msg,
225
0
            account_dn, LDB_SCOPE_BASE, attrs, 0, NULL);
226
227
0
  if (ret != LDB_SUCCESS) {
228
0
    ldb_transaction_cancel(ldb);
229
0
    DEBUG(0,("Can't locate the account we just created %s: %s\n",
230
0
       ldb_dn_get_linearized(account_dn), ldb_errstring(ldb)));
231
0
    talloc_free(tmp_ctx);
232
0
    return NT_STATUS_INTERNAL_DB_CORRUPTION;
233
0
  }
234
0
  account_sid = samdb_result_dom_sid(tmp_ctx, msg, "objectSid");
235
0
  if (account_sid == NULL) {
236
0
    ldb_transaction_cancel(ldb);
237
0
    DEBUG(0,("Apparently we failed to get the objectSid of the just created account record %s\n",
238
0
       ldb_dn_get_linearized(msg->dn)));
239
0
    talloc_free(tmp_ctx);
240
0
    return NT_STATUS_INTERNAL_DB_CORRUPTION;
241
0
  }
242
243
0
  ret = ldb_transaction_commit(ldb);
244
0
  if (ret != LDB_SUCCESS) {
245
0
    DEBUG(0,("Failed to commit transaction to add and modify account record %s: %s\n",
246
0
       ldb_dn_get_linearized(msg->dn),
247
0
       ldb_errstring(ldb)));
248
0
    talloc_free(tmp_ctx);
249
0
    return NT_STATUS_INTERNAL_DB_CORRUPTION;
250
0
  }
251
0
  *dn = talloc_steal(mem_ctx, account_dn);
252
0
  if (sid) {
253
0
    *sid = talloc_steal(mem_ctx, account_sid);
254
0
  }
255
0
  talloc_free(tmp_ctx);
256
0
  return NT_STATUS_OK;
257
258
0
  failed:
259
0
  ldb_transaction_cancel(ldb);
260
0
  talloc_free(tmp_ctx);
261
0
  return NT_STATUS_INTERNAL_ERROR;
262
0
}
263
264
/*
265
  called by samr_CreateDomainGroup and pdb_samba4
266
*/
267
NTSTATUS dsdb_add_domain_group(struct ldb_context *ldb,
268
             TALLOC_CTX *mem_ctx,
269
             const char *groupname,
270
             struct dom_sid **sid,
271
             struct ldb_dn **dn)
272
0
{
273
0
  const char *name;
274
0
  struct ldb_message *msg;
275
0
  struct dom_sid *group_sid;
276
0
  const char *groupname_encoded = NULL;
277
0
  int ret;
278
279
0
  TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
280
0
  NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
281
282
0
  groupname_encoded = ldb_binary_encode_string(tmp_ctx, groupname);
283
0
  if (groupname_encoded == NULL) {
284
0
    talloc_free(tmp_ctx);
285
0
    return NT_STATUS_NO_MEMORY;
286
0
  }
287
288
  /* check if the group already exists */
289
0
  name = samdb_search_string(ldb, tmp_ctx, NULL,
290
0
           "sAMAccountName",
291
0
           "(&(sAMAccountName=%s)(objectclass=group))",
292
0
           groupname_encoded);
293
0
  if (name != NULL) {
294
0
    talloc_free(tmp_ctx);
295
0
    return NT_STATUS_GROUP_EXISTS;
296
0
  }
297
298
0
  msg = ldb_msg_new(tmp_ctx);
299
0
  if (msg == NULL) {
300
0
    talloc_free(tmp_ctx);
301
0
    return NT_STATUS_NO_MEMORY;
302
0
  }
303
304
  /* add core elements to the ldb_message for the user */
305
0
  msg->dn = ldb_dn_copy(tmp_ctx, ldb_get_default_basedn(ldb));
306
0
  ldb_dn_add_child_fmt(msg->dn, "CN=%s,CN=Users", groupname);
307
0
  if (!msg->dn) {
308
0
    talloc_free(tmp_ctx);
309
0
    return NT_STATUS_NO_MEMORY;
310
0
  }
311
0
  ldb_msg_add_string(msg, "sAMAccountName", groupname);
312
0
  ldb_msg_add_string(msg, "objectClass", "group");
313
314
  /* create the group */
315
0
  ret = ldb_add(ldb, msg);
316
0
  switch (ret) {
317
0
  case  LDB_SUCCESS:
318
0
    break;
319
0
  case  LDB_ERR_ENTRY_ALREADY_EXISTS:
320
0
    DEBUG(0,("Failed to create group record %s: %s\n",
321
0
       ldb_dn_get_linearized(msg->dn),
322
0
       ldb_errstring(ldb)));
323
0
    talloc_free(tmp_ctx);
324
0
    return NT_STATUS_GROUP_EXISTS;
325
0
  case  LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
326
0
    DEBUG(0,("Failed to create group record %s: %s\n",
327
0
       ldb_dn_get_linearized(msg->dn),
328
0
       ldb_errstring(ldb)));
329
0
    talloc_free(tmp_ctx);
330
0
    return NT_STATUS_ACCESS_DENIED;
331
0
  default:
332
0
    DEBUG(0,("Failed to create group record %s: %s\n",
333
0
       ldb_dn_get_linearized(msg->dn),
334
0
       ldb_errstring(ldb)));
335
0
    talloc_free(tmp_ctx);
336
0
    return NT_STATUS_INTERNAL_DB_CORRUPTION;
337
0
  }
338
339
  /* retrieve the sid for the group just created */
340
0
  group_sid = samdb_search_dom_sid(ldb, tmp_ctx,
341
0
           msg->dn, "objectSid", NULL);
342
0
  if (group_sid == NULL) {
343
0
    talloc_free(tmp_ctx);
344
0
    return NT_STATUS_UNSUCCESSFUL;
345
0
  }
346
347
0
  *dn = talloc_steal(mem_ctx, msg->dn);
348
0
  *sid = talloc_steal(mem_ctx, group_sid);
349
0
  talloc_free(tmp_ctx);
350
0
  return NT_STATUS_OK;
351
0
}
352
353
NTSTATUS dsdb_add_domain_alias(struct ldb_context *ldb,
354
             TALLOC_CTX *mem_ctx,
355
             const char *alias_name,
356
             struct dom_sid **sid,
357
             struct ldb_dn **dn)
358
0
{
359
0
  const char *name;
360
0
  struct ldb_message *msg;
361
0
  struct dom_sid *alias_sid;
362
0
  const char *alias_name_encoded = NULL;
363
0
  int ret;
364
365
0
  TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
366
0
  NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
367
368
0
  alias_name_encoded = ldb_binary_encode_string(tmp_ctx, alias_name);
369
0
  if (alias_name_encoded == NULL) {
370
0
    return NT_STATUS_NO_MEMORY;
371
0
  }
372
373
0
  if (ldb_transaction_start(ldb) != LDB_SUCCESS) {
374
0
    DEBUG(0, ("Failed to start transaction in dsdb_add_domain_alias(): %s\n", ldb_errstring(ldb)));
375
0
    talloc_free(tmp_ctx);
376
0
    return NT_STATUS_INTERNAL_ERROR;
377
0
  }
378
379
  /* Check if alias already exists */
380
0
  name = samdb_search_string(ldb, tmp_ctx, NULL,
381
0
           "sAMAccountName",
382
0
           "(sAMAccountName=%s)(objectclass=group))",
383
0
           alias_name_encoded);
384
385
0
  if (name != NULL) {
386
0
    talloc_free(tmp_ctx);
387
0
    ldb_transaction_cancel(ldb);
388
0
    return NT_STATUS_ALIAS_EXISTS;
389
0
  }
390
391
0
  msg = ldb_msg_new(tmp_ctx);
392
0
  if (msg == NULL) {
393
0
    talloc_free(tmp_ctx);
394
0
    ldb_transaction_cancel(ldb);
395
0
    return NT_STATUS_NO_MEMORY;
396
0
  }
397
398
  /* add core elements to the ldb_message for the alias */
399
0
  msg->dn = ldb_dn_copy(mem_ctx, ldb_get_default_basedn(ldb));
400
0
  ldb_dn_add_child_fmt(msg->dn, "CN=%s,CN=Users", alias_name);
401
0
  if (!msg->dn) {
402
0
    talloc_free(tmp_ctx);
403
0
    ldb_transaction_cancel(ldb);
404
0
    return NT_STATUS_NO_MEMORY;
405
0
  }
406
407
0
  ldb_msg_add_string(msg, "sAMAccountName", alias_name);
408
0
  ldb_msg_add_string(msg, "objectClass", "group");
409
0
  samdb_msg_add_int(ldb, mem_ctx, msg, "groupType", GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
410
411
  /* create the alias */
412
0
  ret = ldb_add(ldb, msg);
413
0
  switch (ret) {
414
0
  case LDB_SUCCESS:
415
0
    break;
416
0
  case LDB_ERR_ENTRY_ALREADY_EXISTS:
417
0
    talloc_free(tmp_ctx);
418
0
    ldb_transaction_cancel(ldb);
419
0
    return NT_STATUS_ALIAS_EXISTS;
420
0
  case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
421
0
    talloc_free(tmp_ctx);
422
0
    ldb_transaction_cancel(ldb);
423
0
    return NT_STATUS_ACCESS_DENIED;
424
0
  default:
425
0
    DEBUG(0,("Failed to create alias record %s: %s\n",
426
0
       ldb_dn_get_linearized(msg->dn),
427
0
       ldb_errstring(ldb)));
428
0
    talloc_free(tmp_ctx);
429
0
    ldb_transaction_cancel(ldb);
430
0
    return NT_STATUS_INTERNAL_DB_CORRUPTION;
431
0
  }
432
433
  /* retrieve the sid for the alias just created */
434
0
  alias_sid = samdb_search_dom_sid(ldb, tmp_ctx,
435
0
           msg->dn, "objectSid", NULL);
436
437
0
  if (ldb_transaction_commit(ldb) != LDB_SUCCESS) {
438
0
    DEBUG(0, ("Failed to commit transaction in dsdb_add_domain_alias(): %s\n",
439
0
        ldb_errstring(ldb)));
440
0
    talloc_free(tmp_ctx);
441
0
    return NT_STATUS_INTERNAL_ERROR;
442
0
  }
443
444
0
  *dn = talloc_steal(mem_ctx, msg->dn);
445
0
  *sid = talloc_steal(mem_ctx, alias_sid);
446
0
  talloc_free(tmp_ctx);
447
448
449
0
  return NT_STATUS_OK;
450
0
}
451
452
/* Return the members of this group (which may be a domain group or an alias) */
453
NTSTATUS dsdb_enum_group_mem(struct ldb_context *ldb,
454
           TALLOC_CTX *mem_ctx,
455
           struct ldb_dn *dn,
456
           struct dom_sid **members_out,
457
           unsigned int *pnum_members)
458
0
{
459
0
  struct ldb_message *msg;
460
0
  unsigned int i, j;
461
0
  int ret;
462
0
  struct dom_sid *members;
463
0
  struct ldb_message_element *member_el;
464
0
  const char *attrs[] = { "member", NULL };
465
0
  NTSTATUS status;
466
0
  TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
467
0
  NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
468
469
0
  ret = dsdb_search_one(ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs,
470
0
            DSDB_SEARCH_SHOW_EXTENDED_DN, NULL);
471
0
  if (ret == LDB_ERR_NO_SUCH_OBJECT) {
472
0
    talloc_free(tmp_ctx);
473
0
    return NT_STATUS_OBJECT_NAME_NOT_FOUND;
474
0
  }
475
0
  if (ret != LDB_SUCCESS) {
476
0
    DEBUG(1, ("dsdb_enum_group_mem: dsdb_search for %s failed: %s\n",
477
0
        ldb_dn_get_linearized(dn), ldb_errstring(ldb)));
478
0
    return NT_STATUS_INTERNAL_DB_CORRUPTION;
479
0
  }
480
481
0
  member_el = ldb_msg_find_element(msg, "member");
482
0
  if (!member_el) {
483
0
    *members_out = NULL;
484
0
    *pnum_members = 0;
485
0
    talloc_free(tmp_ctx);
486
0
    return NT_STATUS_OK;
487
0
  }
488
489
0
  members = talloc_array(mem_ctx, struct dom_sid, member_el->num_values);
490
0
  if (members == NULL) {
491
0
    return NT_STATUS_NO_MEMORY;
492
0
  }
493
494
0
  j = 0;
495
0
  for (i=0; i <member_el->num_values; i++) {
496
0
    struct ldb_dn *member_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb,
497
0
                     &member_el->values[i]);
498
0
    if (!member_dn || !ldb_dn_validate(member_dn)) {
499
0
      DEBUG(1, ("Could not parse %*.*s as a DN\n",
500
0
          (int)member_el->values[i].length,
501
0
          (int)member_el->values[i].length,
502
0
          (const char *)member_el->values[i].data));
503
0
      talloc_free(tmp_ctx);
504
0
      return NT_STATUS_INTERNAL_DB_CORRUPTION;
505
0
    }
506
507
0
    status = dsdb_get_extended_dn_sid(member_dn, &members[j],
508
0
              "SID");
509
0
    if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
510
      /* If we fail finding a SID then this is no error since
511
       * it could be a non SAM object - e.g. a contact */
512
0
      continue;
513
0
    } else if (!NT_STATUS_IS_OK(status)) {
514
0
      DEBUG(1, ("When parsing DN '%s' we failed to parse it's SID component, so we cannot fetch the membership: %s\n",
515
0
          ldb_dn_get_extended_linearized(tmp_ctx, member_dn, 1),
516
0
          nt_errstr(status)));
517
0
      talloc_free(tmp_ctx);
518
0
      return status;
519
0
    }
520
521
0
    ++j;
522
0
  }
523
524
0
  *members_out = members;
525
0
  *pnum_members = j;
526
0
  talloc_free(tmp_ctx);
527
0
  return NT_STATUS_OK;
528
0
}
529
530
NTSTATUS dsdb_lookup_rids(struct ldb_context *ldb,
531
        TALLOC_CTX *mem_ctx,
532
        const struct dom_sid *domain_sid,
533
        unsigned int num_rids,
534
        uint32_t *rids,
535
        const char **names,
536
        enum lsa_SidType *lsa_attrs)
537
0
{
538
0
  const char *attrs[] = { "sAMAccountType", "sAMAccountName", NULL };
539
0
  unsigned int i, num_mapped;
540
541
0
  TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
542
0
  NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
543
544
0
  num_mapped = 0;
545
546
0
  for (i=0; i<num_rids; i++) {
547
0
    struct ldb_message *msg;
548
0
    struct ldb_dn *dn;
549
0
    uint32_t attr;
550
0
    int rc;
551
552
0
    lsa_attrs[i] = SID_NAME_UNKNOWN;
553
554
0
    dn = ldb_dn_new_fmt(tmp_ctx, ldb, "<SID=%s>",
555
0
            dom_sid_string(tmp_ctx,
556
0
               dom_sid_add_rid(tmp_ctx, domain_sid,
557
0
                   rids[i])));
558
0
    if (dn == NULL) {
559
0
      talloc_free(tmp_ctx);
560
0
      return NT_STATUS_NO_MEMORY;
561
0
    }
562
0
    rc = dsdb_search_one(ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "sAMAccountName=*");
563
0
    if (rc == LDB_ERR_NO_SUCH_OBJECT) {
564
0
      continue;
565
0
    } else if (rc != LDB_SUCCESS) {
566
0
      talloc_free(tmp_ctx);
567
0
      return NT_STATUS_INTERNAL_DB_CORRUPTION;
568
0
    }
569
570
0
    names[i] = ldb_msg_find_attr_as_string(msg, "sAMAccountName", NULL);
571
0
    if (names[i] == NULL) {
572
0
      DEBUG(10, ("no samAccountName\n"));
573
0
      continue;
574
0
    }
575
0
    talloc_steal(names, names[i]);
576
0
    attr = ldb_msg_find_attr_as_uint(msg, "samAccountType", 0);
577
0
    lsa_attrs[i] = ds_atype_map(attr);
578
0
    if (lsa_attrs[i] == SID_NAME_UNKNOWN) {
579
0
      continue;
580
0
    }
581
0
    num_mapped += 1;
582
0
  }
583
0
  talloc_free(tmp_ctx);
584
585
0
  if (num_mapped == 0) {
586
0
    return NT_STATUS_NONE_MAPPED;
587
0
  }
588
0
  if (num_mapped < num_rids) {
589
0
    return STATUS_SOME_UNMAPPED;
590
0
  }
591
0
  return NT_STATUS_OK;
592
0
}
593