Line data Source code
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 1160 : 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 : {
43 78 : const char *name;
44 78 : struct ldb_message *msg;
45 78 : int ret;
46 1160 : const char *container, *obj_class=NULL;
47 78 : char *cn_name;
48 78 : size_t cn_name_len;
49 :
50 1160 : const char *attrs[] = {
51 : "objectSid",
52 : "userAccountControl",
53 : NULL
54 : };
55 :
56 78 : uint32_t user_account_control;
57 78 : struct ldb_dn *account_dn;
58 78 : struct dom_sid *account_sid;
59 :
60 1160 : const char *account_name_encoded = NULL;
61 :
62 1160 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
63 1160 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
64 :
65 1160 : account_name_encoded = ldb_binary_encode_string(tmp_ctx, account_name);
66 1160 : if (account_name_encoded == NULL) {
67 0 : talloc_free(tmp_ctx);
68 0 : return NT_STATUS_NO_MEMORY;
69 : }
70 :
71 : /*
72 : * Start a transaction, so we can query and do a subsequent atomic
73 : * modify
74 : */
75 :
76 1160 : ret = ldb_transaction_start(ldb);
77 1160 : if (ret != LDB_SUCCESS) {
78 0 : DEBUG(0,("Failed to start a transaction for user creation: %s\n",
79 : ldb_errstring(ldb)));
80 0 : talloc_free(tmp_ctx);
81 0 : return NT_STATUS_LOCK_NOT_GRANTED;
82 : }
83 :
84 : /* check if the user already exists */
85 1160 : name = samdb_search_string(ldb, tmp_ctx, NULL,
86 : "sAMAccountName",
87 : "(&(sAMAccountName=%s)(objectclass=user))",
88 : account_name_encoded);
89 1160 : if (name != NULL) {
90 10 : ldb_transaction_cancel(ldb);
91 10 : talloc_free(tmp_ctx);
92 10 : return NT_STATUS_USER_EXISTS;
93 : }
94 :
95 1150 : cn_name = talloc_strdup(tmp_ctx, account_name);
96 1150 : if (!cn_name) {
97 0 : ldb_transaction_cancel(ldb);
98 0 : talloc_free(tmp_ctx);
99 0 : return NT_STATUS_NO_MEMORY;
100 : }
101 :
102 1150 : cn_name_len = strlen(cn_name);
103 1150 : 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 : }
108 :
109 1150 : msg = ldb_msg_new(tmp_ctx);
110 1150 : if (msg == NULL) {
111 0 : ldb_transaction_cancel(ldb);
112 0 : talloc_free(tmp_ctx);
113 0 : return NT_STATUS_NO_MEMORY;
114 : }
115 :
116 : /* This must be one of these values *only* */
117 1150 : if (acct_flags == ACB_NORMAL) {
118 517 : container = "CN=Users";
119 517 : obj_class = "user";
120 517 : user_account_control = UF_NORMAL_ACCOUNT;
121 627 : } else if (acct_flags == ACB_WSTRUST) {
122 278 : if (cn_name[cn_name_len - 1] != '$') {
123 0 : ldb_transaction_cancel(ldb);
124 0 : return NT_STATUS_FOOBAR;
125 : }
126 278 : cn_name[cn_name_len - 1] = '\0';
127 278 : container = "CN=Computers";
128 278 : obj_class = "computer";
129 278 : user_account_control = UF_WORKSTATION_TRUST_ACCOUNT;
130 :
131 349 : } else if (acct_flags == ACB_SVRTRUST) {
132 249 : if (cn_name[cn_name_len - 1] != '$') {
133 0 : ldb_transaction_cancel(ldb);
134 0 : return NT_STATUS_FOOBAR;
135 : }
136 249 : cn_name[cn_name_len - 1] = '\0';
137 249 : container = "OU=Domain Controllers";
138 249 : obj_class = "computer";
139 249 : user_account_control = UF_SERVER_TRUST_ACCOUNT;
140 100 : } 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 : } else {
146 100 : DEBUG(3, ("Invalid account flags specified 0x%08X, must be exactly one of \n"
147 : "ACB_NORMAL (0x%08X) ACB_WSTRUST (0x%08X) or ACB_SVRTRUST (0x%08X)\n",
148 : acct_flags,
149 : ACB_NORMAL, ACB_WSTRUST, ACB_SVRTRUST));
150 100 : ldb_transaction_cancel(ldb);
151 100 : talloc_free(tmp_ctx);
152 100 : return NT_STATUS_INVALID_PARAMETER;
153 : }
154 :
155 1050 : user_account_control |= UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD;
156 :
157 : /* add core elements to the ldb_message for the user */
158 1050 : msg->dn = ldb_dn_copy(msg, ldb_get_default_basedn(ldb));
159 1050 : 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 : }
164 :
165 1050 : ret = ldb_msg_add_string(msg, "sAMAccountName", account_name);
166 1050 : if (ret != LDB_SUCCESS) {
167 0 : goto failed;
168 : }
169 1050 : ret = ldb_msg_add_string(msg, "objectClass", obj_class);
170 1050 : if (ret != LDB_SUCCESS) {
171 0 : goto failed;
172 : }
173 1050 : ret = samdb_msg_add_uint(ldb, tmp_ctx, msg,
174 : "userAccountControl",
175 : user_account_control);
176 1050 : if (ret != LDB_SUCCESS) {
177 0 : goto failed;
178 : }
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 1050 : if (forced_sid) {
184 7 : ret = samdb_msg_add_dom_sid(ldb, msg, msg, "objectSID", forced_sid);
185 7 : if (ret != LDB_SUCCESS) {
186 0 : ldb_transaction_cancel(ldb);
187 0 : talloc_free(tmp_ctx);
188 0 : return NT_STATUS_INTERNAL_ERROR;
189 : }
190 : }
191 :
192 : /* create the user */
193 1050 : ret = ldb_add(ldb, msg);
194 1050 : switch (ret) {
195 969 : case LDB_SUCCESS:
196 1047 : 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 : ldb_dn_get_linearized(msg->dn),
201 : ldb_errstring(ldb)));
202 0 : talloc_free(tmp_ctx);
203 3 : return NT_STATUS_USER_EXISTS;
204 3 : case LDB_ERR_UNWILLING_TO_PERFORM:
205 : case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
206 3 : ldb_transaction_cancel(ldb);
207 3 : DEBUG(0,("Failed to create user record %s: %s\n",
208 : ldb_dn_get_linearized(msg->dn),
209 : ldb_errstring(ldb)));
210 3 : talloc_free(tmp_ctx);
211 3 : 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 : ldb_dn_get_linearized(msg->dn),
216 : ldb_errstring(ldb)));
217 0 : talloc_free(tmp_ctx);
218 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
219 : }
220 :
221 1047 : account_dn = msg->dn;
222 :
223 : /* retrieve the sid and account control bits for the user just created */
224 1047 : ret = dsdb_search_one(ldb, tmp_ctx, &msg,
225 : account_dn, LDB_SCOPE_BASE, attrs, 0, NULL);
226 :
227 1047 : 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 : ldb_dn_get_linearized(account_dn), ldb_errstring(ldb)));
231 0 : talloc_free(tmp_ctx);
232 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
233 : }
234 1047 : account_sid = samdb_result_dom_sid(tmp_ctx, msg, "objectSid");
235 1047 : 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 : ldb_dn_get_linearized(msg->dn)));
239 0 : talloc_free(tmp_ctx);
240 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
241 : }
242 :
243 1047 : ret = ldb_transaction_commit(ldb);
244 1047 : if (ret != LDB_SUCCESS) {
245 0 : DEBUG(0,("Failed to commit transaction to add and modify account record %s: %s\n",
246 : ldb_dn_get_linearized(msg->dn),
247 : ldb_errstring(ldb)));
248 0 : talloc_free(tmp_ctx);
249 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
250 : }
251 1047 : *dn = talloc_steal(mem_ctx, account_dn);
252 1047 : if (sid) {
253 1040 : *sid = talloc_steal(mem_ctx, account_sid);
254 : }
255 1047 : talloc_free(tmp_ctx);
256 1047 : 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 : }
263 :
264 : /*
265 : called by samr_CreateDomainGroup and pdb_samba4
266 : */
267 529 : 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 : {
273 0 : const char *name;
274 0 : struct ldb_message *msg;
275 0 : struct dom_sid *group_sid;
276 529 : const char *groupname_encoded = NULL;
277 0 : int ret;
278 :
279 529 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
280 529 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
281 :
282 529 : groupname_encoded = ldb_binary_encode_string(tmp_ctx, groupname);
283 529 : if (groupname_encoded == NULL) {
284 0 : talloc_free(tmp_ctx);
285 0 : return NT_STATUS_NO_MEMORY;
286 : }
287 :
288 : /* check if the group already exists */
289 529 : name = samdb_search_string(ldb, tmp_ctx, NULL,
290 : "sAMAccountName",
291 : "(&(sAMAccountName=%s)(objectclass=group))",
292 : groupname_encoded);
293 529 : if (name != NULL) {
294 1 : talloc_free(tmp_ctx);
295 1 : return NT_STATUS_GROUP_EXISTS;
296 : }
297 :
298 528 : msg = ldb_msg_new(tmp_ctx);
299 528 : if (msg == NULL) {
300 0 : talloc_free(tmp_ctx);
301 0 : return NT_STATUS_NO_MEMORY;
302 : }
303 :
304 : /* add core elements to the ldb_message for the user */
305 528 : msg->dn = ldb_dn_copy(tmp_ctx, ldb_get_default_basedn(ldb));
306 528 : ldb_dn_add_child_fmt(msg->dn, "CN=%s,CN=Users", groupname);
307 528 : if (!msg->dn) {
308 0 : talloc_free(tmp_ctx);
309 0 : return NT_STATUS_NO_MEMORY;
310 : }
311 528 : ldb_msg_add_string(msg, "sAMAccountName", groupname);
312 528 : ldb_msg_add_string(msg, "objectClass", "group");
313 :
314 : /* create the group */
315 528 : ret = ldb_add(ldb, msg);
316 528 : switch (ret) {
317 528 : case LDB_SUCCESS:
318 528 : break;
319 0 : case LDB_ERR_ENTRY_ALREADY_EXISTS:
320 0 : DEBUG(0,("Failed to create group record %s: %s\n",
321 : ldb_dn_get_linearized(msg->dn),
322 : 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 : ldb_dn_get_linearized(msg->dn),
328 : 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 : ldb_dn_get_linearized(msg->dn),
334 : ldb_errstring(ldb)));
335 0 : talloc_free(tmp_ctx);
336 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
337 : }
338 :
339 : /* retrieve the sid for the group just created */
340 528 : group_sid = samdb_search_dom_sid(ldb, tmp_ctx,
341 : msg->dn, "objectSid", NULL);
342 528 : if (group_sid == NULL) {
343 0 : talloc_free(tmp_ctx);
344 0 : return NT_STATUS_UNSUCCESSFUL;
345 : }
346 :
347 528 : *dn = talloc_steal(mem_ctx, msg->dn);
348 528 : *sid = talloc_steal(mem_ctx, group_sid);
349 528 : talloc_free(tmp_ctx);
350 528 : return NT_STATUS_OK;
351 : }
352 :
353 453 : 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 : {
359 0 : const char *name;
360 0 : struct ldb_message *msg;
361 0 : struct dom_sid *alias_sid;
362 453 : const char *alias_name_encoded = NULL;
363 0 : int ret;
364 :
365 453 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
366 453 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
367 :
368 453 : alias_name_encoded = ldb_binary_encode_string(tmp_ctx, alias_name);
369 453 : if (alias_name_encoded == NULL) {
370 0 : return NT_STATUS_NO_MEMORY;
371 : }
372 :
373 453 : 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 : }
378 :
379 : /* Check if alias already exists */
380 453 : name = samdb_search_string(ldb, tmp_ctx, NULL,
381 : "sAMAccountName",
382 : "(sAMAccountName=%s)(objectclass=group))",
383 : alias_name_encoded);
384 :
385 453 : if (name != NULL) {
386 0 : talloc_free(tmp_ctx);
387 0 : ldb_transaction_cancel(ldb);
388 0 : return NT_STATUS_ALIAS_EXISTS;
389 : }
390 :
391 453 : msg = ldb_msg_new(tmp_ctx);
392 453 : if (msg == NULL) {
393 0 : talloc_free(tmp_ctx);
394 0 : ldb_transaction_cancel(ldb);
395 0 : return NT_STATUS_NO_MEMORY;
396 : }
397 :
398 : /* add core elements to the ldb_message for the alias */
399 453 : msg->dn = ldb_dn_copy(mem_ctx, ldb_get_default_basedn(ldb));
400 453 : ldb_dn_add_child_fmt(msg->dn, "CN=%s,CN=Users", alias_name);
401 453 : if (!msg->dn) {
402 0 : talloc_free(tmp_ctx);
403 0 : ldb_transaction_cancel(ldb);
404 0 : return NT_STATUS_NO_MEMORY;
405 : }
406 :
407 453 : ldb_msg_add_string(msg, "sAMAccountName", alias_name);
408 453 : ldb_msg_add_string(msg, "objectClass", "group");
409 453 : samdb_msg_add_int(ldb, mem_ctx, msg, "groupType", GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
410 :
411 : /* create the alias */
412 453 : ret = ldb_add(ldb, msg);
413 453 : switch (ret) {
414 453 : case LDB_SUCCESS:
415 453 : 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 : ldb_dn_get_linearized(msg->dn),
427 : ldb_errstring(ldb)));
428 0 : talloc_free(tmp_ctx);
429 0 : ldb_transaction_cancel(ldb);
430 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
431 : }
432 :
433 : /* retrieve the sid for the alias just created */
434 453 : alias_sid = samdb_search_dom_sid(ldb, tmp_ctx,
435 : msg->dn, "objectSid", NULL);
436 :
437 453 : if (ldb_transaction_commit(ldb) != LDB_SUCCESS) {
438 0 : DEBUG(0, ("Failed to commit transaction in dsdb_add_domain_alias(): %s\n",
439 : ldb_errstring(ldb)));
440 0 : talloc_free(tmp_ctx);
441 0 : return NT_STATUS_INTERNAL_ERROR;
442 : }
443 :
444 453 : *dn = talloc_steal(mem_ctx, msg->dn);
445 453 : *sid = talloc_steal(mem_ctx, alias_sid);
446 453 : talloc_free(tmp_ctx);
447 :
448 :
449 453 : return NT_STATUS_OK;
450 : }
451 :
452 : /* Return the members of this group (which may be a domain group or an alias) */
453 243 : 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 : {
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 243 : const char *attrs[] = { "member", NULL };
465 0 : NTSTATUS status;
466 243 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
467 243 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
468 :
469 243 : ret = dsdb_search_one(ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs,
470 : DSDB_SEARCH_SHOW_EXTENDED_DN, NULL);
471 243 : if (ret == LDB_ERR_NO_SUCH_OBJECT) {
472 0 : talloc_free(tmp_ctx);
473 0 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
474 : }
475 243 : if (ret != LDB_SUCCESS) {
476 0 : DEBUG(1, ("dsdb_enum_group_mem: dsdb_search for %s failed: %s\n",
477 : ldb_dn_get_linearized(dn), ldb_errstring(ldb)));
478 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
479 : }
480 :
481 243 : member_el = ldb_msg_find_element(msg, "member");
482 243 : if (!member_el) {
483 110 : *members_out = NULL;
484 110 : *pnum_members = 0;
485 110 : talloc_free(tmp_ctx);
486 110 : return NT_STATUS_OK;
487 : }
488 :
489 133 : members = talloc_array(mem_ctx, struct dom_sid, member_el->num_values);
490 133 : if (members == NULL) {
491 0 : return NT_STATUS_NO_MEMORY;
492 : }
493 :
494 133 : j = 0;
495 302 : for (i=0; i <member_el->num_values; i++) {
496 169 : struct ldb_dn *member_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb,
497 169 : &member_el->values[i]);
498 169 : if (!member_dn || !ldb_dn_validate(member_dn)) {
499 0 : DEBUG(1, ("Could not parse %*.*s as a DN\n",
500 : (int)member_el->values[i].length,
501 : (int)member_el->values[i].length,
502 : (const char *)member_el->values[i].data));
503 0 : talloc_free(tmp_ctx);
504 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
505 : }
506 :
507 169 : status = dsdb_get_extended_dn_sid(member_dn, &members[j],
508 : "SID");
509 169 : 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 169 : } 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 : ldb_dn_get_extended_linearized(tmp_ctx, member_dn, 1),
516 : nt_errstr(status)));
517 0 : talloc_free(tmp_ctx);
518 0 : return status;
519 : }
520 :
521 169 : ++j;
522 : }
523 :
524 133 : *members_out = members;
525 133 : *pnum_members = j;
526 133 : talloc_free(tmp_ctx);
527 133 : return NT_STATUS_OK;
528 : }
529 :
530 4924 : 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 : {
538 4924 : const char *attrs[] = { "sAMAccountType", "sAMAccountName", NULL };
539 270 : unsigned int i, num_mapped;
540 :
541 4924 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
542 4924 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
543 :
544 4654 : num_mapped = 0;
545 :
546 12465 : for (i=0; i<num_rids; i++) {
547 270 : struct ldb_message *msg;
548 270 : struct ldb_dn *dn;
549 270 : uint32_t attr;
550 270 : int rc;
551 :
552 7541 : lsa_attrs[i] = SID_NAME_UNKNOWN;
553 :
554 7541 : dn = ldb_dn_new_fmt(tmp_ctx, ldb, "<SID=%s>",
555 : dom_sid_string(tmp_ctx,
556 7541 : dom_sid_add_rid(tmp_ctx, domain_sid,
557 7541 : rids[i])));
558 7541 : if (dn == NULL) {
559 0 : talloc_free(tmp_ctx);
560 0 : return NT_STATUS_NO_MEMORY;
561 : }
562 7541 : rc = dsdb_search_one(ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "samAccountName=*");
563 7541 : if (rc == LDB_ERR_NO_SUCH_OBJECT) {
564 1 : continue;
565 7540 : } else if (rc != LDB_SUCCESS) {
566 0 : talloc_free(tmp_ctx);
567 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
568 : }
569 :
570 7540 : names[i] = ldb_msg_find_attr_as_string(msg, "samAccountName", NULL);
571 7540 : if (names[i] == NULL) {
572 0 : DEBUG(10, ("no samAccountName\n"));
573 0 : continue;
574 : }
575 7540 : talloc_steal(names, names[i]);
576 7540 : attr = ldb_msg_find_attr_as_uint(msg, "samAccountType", 0);
577 7540 : lsa_attrs[i] = ds_atype_map(attr);
578 7540 : if (lsa_attrs[i] == SID_NAME_UNKNOWN) {
579 0 : continue;
580 : }
581 7540 : num_mapped += 1;
582 : }
583 4924 : talloc_free(tmp_ctx);
584 :
585 4924 : if (num_mapped == 0) {
586 0 : return NT_STATUS_NONE_MAPPED;
587 : }
588 4924 : if (num_mapped < num_rids) {
589 1 : return STATUS_SOME_UNMAPPED;
590 : }
591 4923 : return NT_STATUS_OK;
592 : }
593 :
|