source: branches/samba-3.2.x/source/passdb/lookup_sid.c

Last change on this file was 335, checked in by Herwig Bauernfeind, 16 years ago

Update 3.2 to 3.2.14 (final)

File size: 35.7 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 uid/user handling
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Gerald (Jerry) Carter 2003
6 Copyright (C) Volker Lendecke 2005
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#include "includes.h"
23
24/*****************************************************************
25 Dissect a user-provided name into domain, name, sid and type.
26
27 If an explicit domain name was given in the form domain\user, it
28 has to try that. If no explicit domain name was given, we have
29 to do guesswork.
30*****************************************************************/
31
32bool lookup_name(TALLOC_CTX *mem_ctx,
33 const char *full_name, int flags,
34 const char **ret_domain, const char **ret_name,
35 DOM_SID *ret_sid, enum lsa_SidType *ret_type)
36{
37 char *p;
38 const char *tmp;
39 const char *domain = NULL;
40 const char *name = NULL;
41 uint32 rid;
42 DOM_SID sid;
43 enum lsa_SidType type;
44 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
45
46 if (tmp_ctx == NULL) {
47 DEBUG(0, ("talloc_new failed\n"));
48 return false;
49 }
50
51 p = strchr_m(full_name, '\\');
52
53 if (p != NULL) {
54 domain = talloc_strndup(tmp_ctx, full_name,
55 PTR_DIFF(p, full_name));
56 name = talloc_strdup(tmp_ctx, p+1);
57 } else {
58 domain = talloc_strdup(tmp_ctx, "");
59 name = talloc_strdup(tmp_ctx, full_name);
60 }
61
62 if ((domain == NULL) || (name == NULL)) {
63 DEBUG(0, ("talloc failed\n"));
64 TALLOC_FREE(tmp_ctx);
65 return false;
66 }
67
68 DEBUG(10,("lookup_name: %s => %s (domain), %s (name)\n",
69 full_name, domain, name));
70 DEBUG(10, ("lookup_name: flags = 0x0%x\n", flags));
71
72 if ((flags & LOOKUP_NAME_DOMAIN) &&
73 strequal(domain, get_global_sam_name()))
74 {
75
76 /* It's our own domain, lookup the name in passdb */
77 if (lookup_global_sam_name(name, flags, &rid, &type)) {
78 sid_copy(&sid, get_global_sam_sid());
79 sid_append_rid(&sid, rid);
80 goto ok;
81 }
82 TALLOC_FREE(tmp_ctx);
83 return false;
84 }
85
86 if ((flags & LOOKUP_NAME_BUILTIN) &&
87 strequal(domain, builtin_domain_name()))
88 {
89 /* Explicit request for a name in BUILTIN */
90 if (lookup_builtin_name(name, &rid)) {
91 sid_copy(&sid, &global_sid_Builtin);
92 sid_append_rid(&sid, rid);
93 type = SID_NAME_ALIAS;
94 goto ok;
95 }
96 TALLOC_FREE(tmp_ctx);
97 return false;
98 }
99
100 /* Try the explicit winbind lookup first, don't let it guess the
101 * domain yet at this point yet. This comes later. */
102
103 if ((domain[0] != '\0') &&
104 (flags & ~(LOOKUP_NAME_DOMAIN|LOOKUP_NAME_ISOLATED)) &&
105 (winbind_lookup_name(domain, name, &sid, &type))) {
106 goto ok;
107 }
108
109 if (!(flags & LOOKUP_NAME_EXPLICIT) && strequal(domain, unix_users_domain_name())) {
110 if (lookup_unix_user_name(name, &sid)) {
111 type = SID_NAME_USER;
112 goto ok;
113 }
114 TALLOC_FREE(tmp_ctx);
115 return false;
116 }
117
118 if (!(flags & LOOKUP_NAME_EXPLICIT) && strequal(domain, unix_groups_domain_name())) {
119 if (lookup_unix_group_name(name, &sid)) {
120 type = SID_NAME_DOM_GRP;
121 goto ok;
122 }
123 TALLOC_FREE(tmp_ctx);
124 return false;
125 }
126
127 if ((domain[0] == '\0') && (!(flags & LOOKUP_NAME_ISOLATED))) {
128 TALLOC_FREE(tmp_ctx);
129 return false;
130 }
131
132 /* Now the guesswork begins, we haven't been given an explicit
133 * domain. Try the sequence as documented on
134 * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
135 * November 27, 2005 */
136
137 /* 1. well-known names */
138
139 if ((flags & LOOKUP_NAME_WKN) &&
140 lookup_wellknown_name(tmp_ctx, name, &sid, &domain))
141 {
142 type = SID_NAME_WKN_GRP;
143 goto ok;
144 }
145
146 /* 2. Builtin domain as such */
147
148 if ((flags & (LOOKUP_NAME_BUILTIN|LOOKUP_NAME_REMOTE)) &&
149 strequal(name, builtin_domain_name()))
150 {
151 /* Swap domain and name */
152 tmp = name; name = domain; domain = tmp;
153 sid_copy(&sid, &global_sid_Builtin);
154 type = SID_NAME_DOMAIN;
155 goto ok;
156 }
157
158 /* 3. Account domain */
159
160 if ((flags & LOOKUP_NAME_DOMAIN) &&
161 strequal(name, get_global_sam_name()))
162 {
163 if (!secrets_fetch_domain_sid(name, &sid)) {
164 DEBUG(3, ("Could not fetch my SID\n"));
165 TALLOC_FREE(tmp_ctx);
166 return false;
167 }
168 /* Swap domain and name */
169 tmp = name; name = domain; domain = tmp;
170 type = SID_NAME_DOMAIN;
171 goto ok;
172 }
173
174 /* 4. Primary domain */
175
176 if ((flags & LOOKUP_NAME_DOMAIN) && !IS_DC &&
177 strequal(name, lp_workgroup()))
178 {
179 if (!secrets_fetch_domain_sid(name, &sid)) {
180 DEBUG(3, ("Could not fetch the domain SID\n"));
181 TALLOC_FREE(tmp_ctx);
182 return false;
183 }
184 /* Swap domain and name */
185 tmp = name; name = domain; domain = tmp;
186 type = SID_NAME_DOMAIN;
187 goto ok;
188 }
189
190 /* 5. Trusted domains as such, to me it looks as if members don't do
191 this, tested an XP workstation in a NT domain -- vl */
192
193 if ((flags & LOOKUP_NAME_REMOTE) && IS_DC &&
194 (pdb_get_trusteddom_pw(name, NULL, &sid, NULL)))
195 {
196 /* Swap domain and name */
197 tmp = name; name = domain; domain = tmp;
198 type = SID_NAME_DOMAIN;
199 goto ok;
200 }
201
202 /* 6. Builtin aliases */
203
204 if ((flags & LOOKUP_NAME_BUILTIN) &&
205 lookup_builtin_name(name, &rid))
206 {
207 domain = talloc_strdup(tmp_ctx, builtin_domain_name());
208 sid_copy(&sid, &global_sid_Builtin);
209 sid_append_rid(&sid, rid);
210 type = SID_NAME_ALIAS;
211 goto ok;
212 }
213
214 /* 7. Local systems' SAM (DCs don't have a local SAM) */
215 /* 8. Primary SAM (On members, this is the domain) */
216
217 /* Both cases are done by looking at our passdb */
218
219 if ((flags & LOOKUP_NAME_DOMAIN) &&
220 lookup_global_sam_name(name, flags, &rid, &type))
221 {
222 domain = talloc_strdup(tmp_ctx, get_global_sam_name());
223 sid_copy(&sid, get_global_sam_sid());
224 sid_append_rid(&sid, rid);
225 goto ok;
226 }
227
228 /* Now our local possibilities are exhausted. */
229
230 if (!(flags & LOOKUP_NAME_REMOTE)) {
231 TALLOC_FREE(tmp_ctx);
232 return false;
233 }
234
235 /* If we are not a DC, we have to ask in our primary domain. Let
236 * winbind do that. */
237
238 if (!IS_DC &&
239 (winbind_lookup_name(lp_workgroup(), name, &sid, &type))) {
240 domain = talloc_strdup(tmp_ctx, lp_workgroup());
241 goto ok;
242 }
243
244 /* 9. Trusted domains */
245
246 /* If we're a DC we have to ask all trusted DC's. Winbind does not do
247 * that (yet), but give it a chance. */
248
249 if (IS_DC && winbind_lookup_name("", name, &sid, &type)) {
250 DOM_SID dom_sid;
251 uint32 tmp_rid;
252 enum lsa_SidType domain_type;
253
254 if (type == SID_NAME_DOMAIN) {
255 /* Swap name and type */
256 tmp = name; name = domain; domain = tmp;
257 goto ok;
258 }
259
260 /* Here we have to cope with a little deficiency in the
261 * winbind API: We have to ask it again for the name of the
262 * domain it figured out itself. Maybe fix that later... */
263
264 sid_copy(&dom_sid, &sid);
265 sid_split_rid(&dom_sid, &tmp_rid);
266
267 if (!winbind_lookup_sid(tmp_ctx, &dom_sid, &domain, NULL,
268 &domain_type) ||
269 (domain_type != SID_NAME_DOMAIN)) {
270 DEBUG(2, ("winbind could not find the domain's name "
271 "it just looked up for us\n"));
272 TALLOC_FREE(tmp_ctx);
273 return false;
274 }
275 goto ok;
276 }
277
278 /* 10. Don't translate */
279
280 /* 11. Ok, windows would end here. Samba has two more options:
281 Unmapped users and unmapped groups */
282
283 if (!(flags & LOOKUP_NAME_EXPLICIT) && lookup_unix_user_name(name, &sid)) {
284 domain = talloc_strdup(tmp_ctx, unix_users_domain_name());
285 type = SID_NAME_USER;
286 goto ok;
287 }
288
289 if (!(flags & LOOKUP_NAME_EXPLICIT) && lookup_unix_group_name(name, &sid)) {
290 domain = talloc_strdup(tmp_ctx, unix_groups_domain_name());
291 type = SID_NAME_DOM_GRP;
292 goto ok;
293 }
294
295 /*
296 * Ok, all possibilities tried. Fail.
297 */
298
299 TALLOC_FREE(tmp_ctx);
300 return false;
301
302 ok:
303 if ((domain == NULL) || (name == NULL)) {
304 DEBUG(0, ("talloc failed\n"));
305 TALLOC_FREE(tmp_ctx);
306 return false;
307 }
308
309 /*
310 * Hand over the results to the talloc context we've been given.
311 */
312
313 if ((ret_name != NULL) &&
314 !(*ret_name = talloc_strdup(mem_ctx, name))) {
315 DEBUG(0, ("talloc failed\n"));
316 TALLOC_FREE(tmp_ctx);
317 return false;
318 }
319
320 if (ret_domain != NULL) {
321 char *tmp_dom;
322 if (!(tmp_dom = talloc_strdup(mem_ctx, domain))) {
323 DEBUG(0, ("talloc failed\n"));
324 TALLOC_FREE(tmp_ctx);
325 return false;
326 }
327 strupper_m(tmp_dom);
328 *ret_domain = tmp_dom;
329 }
330
331 if (ret_sid != NULL) {
332 sid_copy(ret_sid, &sid);
333 }
334
335 if (ret_type != NULL) {
336 *ret_type = type;
337 }
338
339 TALLOC_FREE(tmp_ctx);
340 return true;
341}
342
343/************************************************************************
344 Names from smb.conf can be unqualified. eg. valid users = foo
345 These names should never map to a remote name. Try global_sam_name()\foo,
346 and then "Unix Users"\foo (or "Unix Groups"\foo).
347************************************************************************/
348
349bool lookup_name_smbconf(TALLOC_CTX *mem_ctx,
350 const char *full_name, int flags,
351 const char **ret_domain, const char **ret_name,
352 DOM_SID *ret_sid, enum lsa_SidType *ret_type)
353{
354 char *qualified_name;
355 const char *p;
356
357 /* NB. No winbindd_separator here as lookup_name needs \\' */
358 if ((p = strchr_m(full_name, *lp_winbind_separator())) != NULL) {
359
360 /* The name is already qualified with a domain. */
361
362 if (*lp_winbind_separator() != '\\') {
363 char *tmp;
364
365 /* lookup_name() needs '\\' as a separator */
366
367 tmp = talloc_strdup(mem_ctx, full_name);
368 if (!tmp) {
369 return false;
370 }
371 tmp[p - full_name] = '\\';
372 full_name = tmp;
373 }
374
375 return lookup_name(mem_ctx, full_name, flags,
376 ret_domain, ret_name,
377 ret_sid, ret_type);
378 }
379
380 /* Try with our own SAM name. */
381 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
382 get_global_sam_name(),
383 full_name );
384 if (!qualified_name) {
385 return false;
386 }
387
388 if (lookup_name(mem_ctx, qualified_name, flags,
389 ret_domain, ret_name,
390 ret_sid, ret_type)) {
391 return true;
392 }
393
394 /* Finally try with "Unix Users" or "Unix Group" */
395 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
396 flags & LOOKUP_NAME_GROUP ?
397 unix_groups_domain_name() :
398 unix_users_domain_name(),
399 full_name );
400 if (!qualified_name) {
401 return false;
402 }
403
404 return lookup_name(mem_ctx, qualified_name, flags,
405 ret_domain, ret_name,
406 ret_sid, ret_type);
407}
408
409static bool wb_lookup_rids(TALLOC_CTX *mem_ctx,
410 const DOM_SID *domain_sid,
411 int num_rids, uint32 *rids,
412 const char **domain_name,
413 const char **names, enum lsa_SidType *types)
414{
415 int i;
416 const char **my_names;
417 enum lsa_SidType *my_types;
418 TALLOC_CTX *tmp_ctx;
419
420 if (!(tmp_ctx = talloc_init("wb_lookup_rids"))) {
421 return false;
422 }
423
424 if (!winbind_lookup_rids(tmp_ctx, domain_sid, num_rids, rids,
425 domain_name, &my_names, &my_types)) {
426 *domain_name = "";
427 for (i=0; i<num_rids; i++) {
428 names[i] = "";
429 types[i] = SID_NAME_UNKNOWN;
430 }
431 TALLOC_FREE(tmp_ctx);
432 return true;
433 }
434
435 if (!(*domain_name = talloc_strdup(mem_ctx, *domain_name))) {
436 TALLOC_FREE(tmp_ctx);
437 return false;
438 }
439
440 /*
441 * winbind_lookup_rids allocates its own array. We've been given the
442 * array, so copy it over
443 */
444
445 for (i=0; i<num_rids; i++) {
446 if (my_names[i] == NULL) {
447 TALLOC_FREE(tmp_ctx);
448 return false;
449 }
450 if (!(names[i] = talloc_strdup(names, my_names[i]))) {
451 TALLOC_FREE(tmp_ctx);
452 return false;
453 }
454 types[i] = my_types[i];
455 }
456 TALLOC_FREE(tmp_ctx);
457 return true;
458}
459
460static bool lookup_rids(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
461 int num_rids, uint32_t *rids,
462 const char **domain_name,
463 const char ***names, enum lsa_SidType **types)
464{
465 int i;
466
467 DEBUG(10, ("lookup_rids called for domain sid '%s'\n",
468 sid_string_dbg(domain_sid)));
469
470 if (num_rids) {
471 *names = TALLOC_ZERO_ARRAY(mem_ctx, const char *, num_rids);
472 *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
473
474 if ((*names == NULL) || (*types == NULL)) {
475 return false;
476 }
477
478 for (i = 0; i < num_rids; i++)
479 (*types)[i] = SID_NAME_UNKNOWN;
480 } else {
481 *names = NULL;
482 *types = NULL;
483 }
484
485 if (sid_check_is_domain(domain_sid)) {
486 NTSTATUS result;
487
488 if (*domain_name == NULL) {
489 *domain_name = talloc_strdup(
490 mem_ctx, get_global_sam_name());
491 }
492
493 if (*domain_name == NULL) {
494 return false;
495 }
496
497 become_root();
498 result = pdb_lookup_rids(domain_sid, num_rids, rids,
499 *names, *types);
500 unbecome_root();
501
502 return (NT_STATUS_IS_OK(result) ||
503 NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
504 NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
505 }
506
507 if (sid_check_is_builtin(domain_sid)) {
508
509 if (*domain_name == NULL) {
510 *domain_name = talloc_strdup(
511 mem_ctx, builtin_domain_name());
512 }
513
514 if (*domain_name == NULL) {
515 return false;
516 }
517
518 for (i=0; i<num_rids; i++) {
519 if (lookup_builtin_rid(*names, rids[i],
520 &(*names)[i])) {
521 if ((*names)[i] == NULL) {
522 return false;
523 }
524 (*types)[i] = SID_NAME_ALIAS;
525 } else {
526 (*types)[i] = SID_NAME_UNKNOWN;
527 }
528 }
529 return true;
530 }
531
532 if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
533 for (i=0; i<num_rids; i++) {
534 DOM_SID sid;
535 sid_copy(&sid, domain_sid);
536 sid_append_rid(&sid, rids[i]);
537 if (lookup_wellknown_sid(mem_ctx, &sid,
538 domain_name, &(*names)[i])) {
539 if ((*names)[i] == NULL) {
540 return false;
541 }
542 (*types)[i] = SID_NAME_WKN_GRP;
543 } else {
544 (*types)[i] = SID_NAME_UNKNOWN;
545 }
546 }
547 return true;
548 }
549
550 if (sid_check_is_unix_users(domain_sid)) {
551 if (*domain_name == NULL) {
552 *domain_name = talloc_strdup(
553 mem_ctx, unix_users_domain_name());
554 if (*domain_name == NULL) {
555 return false;
556 }
557 }
558 for (i=0; i<num_rids; i++) {
559 (*names)[i] = talloc_strdup(
560 (*names), uidtoname(rids[i]));
561 if ((*names)[i] == NULL) {
562 return false;
563 }
564 (*types)[i] = SID_NAME_USER;
565 }
566 return true;
567 }
568
569 if (sid_check_is_unix_groups(domain_sid)) {
570 if (*domain_name == NULL) {
571 *domain_name = talloc_strdup(
572 mem_ctx, unix_groups_domain_name());
573 if (*domain_name == NULL) {
574 return false;
575 }
576 }
577 for (i=0; i<num_rids; i++) {
578 (*names)[i] = talloc_strdup(
579 (*names), gidtoname(rids[i]));
580 if ((*names)[i] == NULL) {
581 return false;
582 }
583 (*types)[i] = SID_NAME_DOM_GRP;
584 }
585 return true;
586 }
587
588 return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
589 domain_name, *names, *types);
590}
591
592/*
593 * Is the SID a domain as such? If yes, lookup its name.
594 */
595
596static bool lookup_as_domain(const DOM_SID *sid, TALLOC_CTX *mem_ctx,
597 const char **name)
598{
599 const char *tmp;
600 enum lsa_SidType type;
601
602 if (sid_check_is_domain(sid)) {
603 *name = talloc_strdup(mem_ctx, get_global_sam_name());
604 return true;
605 }
606
607 if (sid_check_is_builtin(sid)) {
608 *name = talloc_strdup(mem_ctx, builtin_domain_name());
609 return true;
610 }
611
612 if (sid_check_is_wellknown_domain(sid, &tmp)) {
613 *name = talloc_strdup(mem_ctx, tmp);
614 return true;
615 }
616
617 if (sid_check_is_unix_users(sid)) {
618 *name = talloc_strdup(mem_ctx, unix_users_domain_name());
619 return true;
620 }
621
622 if (sid_check_is_unix_groups(sid)) {
623 *name = talloc_strdup(mem_ctx, unix_groups_domain_name());
624 return true;
625 }
626
627 if (sid->num_auths != 4) {
628 /* This can't be a domain */
629 return false;
630 }
631
632 if (IS_DC) {
633 uint32 i, num_domains;
634 struct trustdom_info **domains;
635
636 /* This is relatively expensive, but it happens only on DCs
637 * and for SIDs that have 4 sub-authorities and thus look like
638 * domains */
639
640 if (!NT_STATUS_IS_OK(pdb_enum_trusteddoms(mem_ctx,
641 &num_domains,
642 &domains))) {
643 return false;
644 }
645
646 for (i=0; i<num_domains; i++) {
647 if (sid_equal(sid, &domains[i]->sid)) {
648 *name = talloc_strdup(mem_ctx,
649 domains[i]->name);
650 return true;
651 }
652 }
653 return false;
654 }
655
656 if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
657 (type == SID_NAME_DOMAIN)) {
658 *name = tmp;
659 return true;
660 }
661
662 return false;
663}
664
665/*
666 * This tries to implement the rather weird rules for the lsa_lookup level
667 * parameter.
668 *
669 * This is as close as we can get to what W2k3 does. With this we survive the
670 * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
671 * different, but I assume that's just being too liberal. For example, W2k3
672 * replies to everything else but the levels 1-6 with INVALID_PARAMETER
673 * whereas NT4 does the same as level 1 (I think). I did not fully test that
674 * with NT4, this is what w2k3 does.
675 *
676 * Level 1: Ask everywhere
677 * Level 2: Ask domain and trusted domains, no builtin and wkn
678 * Level 3: Only ask domain
679 * Level 4: W2k3ad: Only ask AD trusts
680 * Level 5: Only ask transitive forest trusts
681 * Level 6: Like 4
682 */
683
684static bool check_dom_sid_to_level(const DOM_SID *sid, int level)
685{
686 int ret = false;
687
688 switch(level) {
689 case 1:
690 ret = true;
691 break;
692 case 2:
693 ret = (!sid_check_is_builtin(sid) &&
694 !sid_check_is_wellknown_domain(sid, NULL));
695 break;
696 case 3:
697 case 4:
698 case 6:
699 ret = sid_check_is_domain(sid);
700 break;
701 case 5:
702 ret = false;
703 break;
704 }
705
706 DEBUG(10, ("%s SID %s in level %d\n",
707 ret ? "Accepting" : "Rejecting",
708 sid_string_dbg(sid), level));
709 return ret;
710}
711
712/*
713 * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
714 * references to domains, it is explicitly made for this.
715 *
716 * This attempts to be as efficient as possible: It collects all SIDs
717 * belonging to a domain and hands them in bulk to the appropriate lookup
718 * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
719 * *hugely* from this. Winbind is going to be extended with a lookup_rids
720 * interface as well, so on a DC we can do a bulk lsa_lookuprids to the
721 * appropriate DC.
722 */
723
724NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
725 const DOM_SID **sids, int level,
726 struct lsa_dom_info **ret_domains,
727 struct lsa_name_info **ret_names)
728{
729 TALLOC_CTX *tmp_ctx;
730 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
731 struct lsa_name_info *name_infos;
732 struct lsa_dom_info *dom_infos = NULL;
733
734 int i, j;
735
736 if (!(tmp_ctx = talloc_new(mem_ctx))) {
737 DEBUG(0, ("talloc_new failed\n"));
738 return NT_STATUS_NO_MEMORY;
739 }
740
741 if (num_sids) {
742 name_infos = TALLOC_ARRAY(mem_ctx, struct lsa_name_info, num_sids);
743 if (name_infos == NULL) {
744 result = NT_STATUS_NO_MEMORY;
745 goto fail;
746 }
747 } else {
748 name_infos = NULL;
749 }
750
751 dom_infos = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_dom_info,
752 MAX_REF_DOMAINS);
753 if (dom_infos == NULL) {
754 result = NT_STATUS_NO_MEMORY;
755 goto fail;
756 }
757
758 /* First build up the data structures:
759 *
760 * dom_infos is a list of domains referenced in the list of
761 * SIDs. Later we will walk the list of domains and look up the RIDs
762 * in bulk.
763 *
764 * name_infos is a shadow-copy of the SIDs array to collect the real
765 * data.
766 *
767 * dom_info->idxs is an index into the name_infos array. The
768 * difficulty we have here is that we need to keep the SIDs the client
769 * asked for in the same order for the reply
770 */
771
772 for (i=0; i<num_sids; i++) {
773 DOM_SID sid;
774 uint32 rid;
775 const char *domain_name = NULL;
776
777 sid_copy(&sid, sids[i]);
778 name_infos[i].type = SID_NAME_USE_NONE;
779
780 if (lookup_as_domain(&sid, name_infos, &domain_name)) {
781 /* We can't push that through the normal lookup
782 * process, as this would reference illegal
783 * domains.
784 *
785 * For example S-1-5-32 would end up referencing
786 * domain S-1-5- with RID 32 which is clearly wrong.
787 */
788 if (domain_name == NULL) {
789 result = NT_STATUS_NO_MEMORY;
790 goto fail;
791 }
792
793 name_infos[i].rid = 0;
794 name_infos[i].type = SID_NAME_DOMAIN;
795 name_infos[i].name = NULL;
796
797 if (sid_check_is_builtin(&sid)) {
798 /* Yes, W2k3 returns "BUILTIN" both as domain
799 * and name here */
800 name_infos[i].name = talloc_strdup(
801 name_infos, builtin_domain_name());
802 if (name_infos[i].name == NULL) {
803 result = NT_STATUS_NO_MEMORY;
804 goto fail;
805 }
806 }
807 } else {
808 /* This is a normal SID with rid component */
809 if (!sid_split_rid(&sid, &rid)) {
810 result = NT_STATUS_INVALID_SID;
811 goto fail;
812 }
813 }
814
815 if (!check_dom_sid_to_level(&sid, level)) {
816 name_infos[i].rid = 0;
817 name_infos[i].type = SID_NAME_UNKNOWN;
818 name_infos[i].name = NULL;
819 continue;
820 }
821
822 for (j=0; j<MAX_REF_DOMAINS; j++) {
823 if (!dom_infos[j].valid) {
824 break;
825 }
826 if (sid_equal(&sid, &dom_infos[j].sid)) {
827 break;
828 }
829 }
830
831 if (j == MAX_REF_DOMAINS) {
832 /* TODO: What's the right error message here? */
833 result = NT_STATUS_NONE_MAPPED;
834 goto fail;
835 }
836
837 if (!dom_infos[j].valid) {
838 /* We found a domain not yet referenced, create a new
839 * ref. */
840 dom_infos[j].valid = true;
841 sid_copy(&dom_infos[j].sid, &sid);
842
843 if (domain_name != NULL) {
844 /* This name was being found above in the case
845 * when we found a domain SID */
846 dom_infos[j].name =
847 talloc_strdup(dom_infos, domain_name);
848 if (dom_infos[j].name == NULL) {
849 result = NT_STATUS_NO_MEMORY;
850 goto fail;
851 }
852 } else {
853 /* lookup_rids will take care of this */
854 dom_infos[j].name = NULL;
855 }
856 }
857
858 name_infos[i].dom_idx = j;
859
860 if (name_infos[i].type == SID_NAME_USE_NONE) {
861 name_infos[i].rid = rid;
862
863 ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
864 &dom_infos[j].num_idxs);
865
866 if (dom_infos[j].idxs == NULL) {
867 result = NT_STATUS_NO_MEMORY;
868 goto fail;
869 }
870 }
871 }
872
873 /* Iterate over the domains found */
874
875 for (i=0; i<MAX_REF_DOMAINS; i++) {
876 uint32_t *rids;
877 const char *domain_name = NULL;
878 const char **names;
879 enum lsa_SidType *types;
880 struct lsa_dom_info *dom = &dom_infos[i];
881
882 if (!dom->valid) {
883 /* No domains left, we're done */
884 break;
885 }
886
887 if (dom->num_idxs) {
888 if (!(rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs))) {
889 result = NT_STATUS_NO_MEMORY;
890 goto fail;
891 }
892 } else {
893 rids = NULL;
894 }
895
896 for (j=0; j<dom->num_idxs; j++) {
897 rids[j] = name_infos[dom->idxs[j]].rid;
898 }
899
900 if (!lookup_rids(tmp_ctx, &dom->sid,
901 dom->num_idxs, rids, &domain_name,
902 &names, &types)) {
903 result = NT_STATUS_NO_MEMORY;
904 goto fail;
905 }
906
907 if (!(dom->name = talloc_strdup(dom_infos, domain_name))) {
908 result = NT_STATUS_NO_MEMORY;
909 goto fail;
910 }
911
912 for (j=0; j<dom->num_idxs; j++) {
913 int idx = dom->idxs[j];
914 name_infos[idx].type = types[j];
915 if (types[j] != SID_NAME_UNKNOWN) {
916 name_infos[idx].name =
917 talloc_strdup(name_infos, names[j]);
918 if (name_infos[idx].name == NULL) {
919 result = NT_STATUS_NO_MEMORY;
920 goto fail;
921 }
922 } else {
923 name_infos[idx].name = NULL;
924 }
925 }
926 }
927
928 *ret_domains = dom_infos;
929 *ret_names = name_infos;
930 TALLOC_FREE(tmp_ctx);
931 return NT_STATUS_OK;
932
933 fail:
934 TALLOC_FREE(dom_infos);
935 TALLOC_FREE(name_infos);
936 TALLOC_FREE(tmp_ctx);
937 return result;
938}
939
940/*****************************************************************
941 *THE CANONICAL* convert SID to name function.
942*****************************************************************/
943
944bool lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
945 const char **ret_domain, const char **ret_name,
946 enum lsa_SidType *ret_type)
947{
948 struct lsa_dom_info *domain;
949 struct lsa_name_info *name;
950 TALLOC_CTX *tmp_ctx;
951 bool ret = false;
952
953 DEBUG(10, ("lookup_sid called for SID '%s'\n", sid_string_dbg(sid)));
954
955 if (!(tmp_ctx = talloc_new(mem_ctx))) {
956 DEBUG(0, ("talloc_new failed\n"));
957 return false;
958 }
959
960 if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
961 &domain, &name))) {
962 goto done;
963 }
964
965 if (name->type == SID_NAME_UNKNOWN) {
966 goto done;
967 }
968
969 if ((ret_domain != NULL) &&
970 !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
971 goto done;
972 }
973
974 if ((ret_name != NULL) &&
975 !(*ret_name = talloc_strdup(mem_ctx, name->name))) {
976 goto done;
977 }
978
979 if (ret_type != NULL) {
980 *ret_type = name->type;
981 }
982
983 ret = true;
984
985 done:
986 if (ret) {
987 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n", sid_string_dbg(sid),
988 domain->name, name->name, name->type));
989 } else {
990 DEBUG(10, ("failed to lookup sid %s\n", sid_string_dbg(sid)));
991 }
992 TALLOC_FREE(tmp_ctx);
993 return ret;
994}
995
996/*****************************************************************
997 Id mapping cache. This is to avoid Winbind mappings already
998 seen by smbd to be queried too frequently, keeping winbindd
999 busy, and blocking smbd while winbindd is busy with other
1000 stuff. Written by Michael Steffens <michael.steffens@hp.com>,
1001 modified to use linked lists by jra.
1002*****************************************************************/
1003
1004/*****************************************************************
1005 Find a SID given a uid.
1006*****************************************************************/
1007
1008static bool fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid)
1009{
1010 DATA_BLOB cache_value;
1011
1012 if (!memcache_lookup(NULL, UID_SID_CACHE,
1013 data_blob_const(&uid, sizeof(uid)),
1014 &cache_value)) {
1015 return false;
1016 }
1017
1018 memcpy(psid, cache_value.data, MIN(sizeof(*psid), cache_value.length));
1019 SMB_ASSERT(cache_value.length >= offsetof(struct dom_sid, id_auth));
1020 SMB_ASSERT(cache_value.length == ndr_size_dom_sid(psid, 0));
1021
1022 return true;
1023}
1024
1025/*****************************************************************
1026 Find a uid given a SID.
1027*****************************************************************/
1028
1029static bool fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid )
1030{
1031 DATA_BLOB cache_value;
1032
1033 if (!memcache_lookup(NULL, SID_UID_CACHE,
1034 data_blob_const(psid, ndr_size_dom_sid(psid, 0)),
1035 &cache_value)) {
1036 return false;
1037 }
1038
1039 SMB_ASSERT(cache_value.length == sizeof(*puid));
1040 memcpy(puid, cache_value.data, sizeof(*puid));
1041
1042 return true;
1043}
1044
1045/*****************************************************************
1046 Store uid to SID mapping in cache.
1047*****************************************************************/
1048
1049void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
1050{
1051 memcache_add(NULL, SID_UID_CACHE,
1052 data_blob_const(psid, ndr_size_dom_sid(psid, 0)),
1053 data_blob_const(&uid, sizeof(uid)));
1054 memcache_add(NULL, UID_SID_CACHE,
1055 data_blob_const(&uid, sizeof(uid)),
1056 data_blob_const(psid, ndr_size_dom_sid(psid, 0)));
1057}
1058
1059/*****************************************************************
1060 Find a SID given a gid.
1061*****************************************************************/
1062
1063static bool fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid)
1064{
1065 DATA_BLOB cache_value;
1066
1067 if (!memcache_lookup(NULL, GID_SID_CACHE,
1068 data_blob_const(&gid, sizeof(gid)),
1069 &cache_value)) {
1070 return false;
1071 }
1072
1073 memcpy(psid, cache_value.data, MIN(sizeof(*psid), cache_value.length));
1074 SMB_ASSERT(cache_value.length >= offsetof(struct dom_sid, id_auth));
1075 SMB_ASSERT(cache_value.length == ndr_size_dom_sid(psid, 0));
1076
1077 return true;
1078}
1079
1080/*****************************************************************
1081 Find a gid given a SID.
1082*****************************************************************/
1083
1084static bool fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid)
1085{
1086 DATA_BLOB cache_value;
1087
1088 if (!memcache_lookup(NULL, SID_GID_CACHE,
1089 data_blob_const(psid, ndr_size_dom_sid(psid, 0)),
1090 &cache_value)) {
1091 return false;
1092 }
1093
1094 SMB_ASSERT(cache_value.length == sizeof(*pgid));
1095 memcpy(pgid, cache_value.data, sizeof(*pgid));
1096
1097 return true;
1098}
1099
1100/*****************************************************************
1101 Store gid to SID mapping in cache.
1102*****************************************************************/
1103
1104void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
1105{
1106 memcache_add(NULL, SID_GID_CACHE,
1107 data_blob_const(psid, ndr_size_dom_sid(psid, 0)),
1108 data_blob_const(&gid, sizeof(gid)));
1109 memcache_add(NULL, GID_SID_CACHE,
1110 data_blob_const(&gid, sizeof(gid)),
1111 data_blob_const(psid, ndr_size_dom_sid(psid, 0)));
1112}
1113
1114/*****************************************************************
1115 *THE LEGACY* convert uid_t to SID function.
1116*****************************************************************/
1117
1118static void legacy_uid_to_sid(DOM_SID *psid, uid_t uid)
1119{
1120 uint32 rid;
1121 bool ret;
1122
1123 ZERO_STRUCTP(psid);
1124
1125 become_root();
1126 ret = pdb_uid_to_rid(uid, &rid);
1127 unbecome_root();
1128
1129 if (ret) {
1130 /* This is a mapped user */
1131 sid_copy(psid, get_global_sam_sid());
1132 sid_append_rid(psid, rid);
1133 goto done;
1134 }
1135
1136 /* This is an unmapped user */
1137
1138 uid_to_unix_users_sid(uid, psid);
1139
1140 done:
1141 DEBUG(10,("LEGACY: uid %u -> sid %s\n", (unsigned int)uid,
1142 sid_string_dbg(psid)));
1143
1144 store_uid_sid_cache(psid, uid);
1145 return;
1146}
1147
1148/*****************************************************************
1149 *THE LEGACY* convert gid_t to SID function.
1150*****************************************************************/
1151
1152static void legacy_gid_to_sid(DOM_SID *psid, gid_t gid)
1153{
1154 bool ret;
1155
1156 ZERO_STRUCTP(psid);
1157
1158 become_root();
1159 ret = pdb_gid_to_sid(gid, psid);
1160 unbecome_root();
1161
1162 if (ret) {
1163 /* This is a mapped group */
1164 goto done;
1165 }
1166
1167 /* This is an unmapped group */
1168
1169 gid_to_unix_groups_sid(gid, psid);
1170
1171 done:
1172 DEBUG(10,("LEGACY: gid %u -> sid %s\n", (unsigned int)gid,
1173 sid_string_dbg(psid)));
1174
1175 store_gid_sid_cache(psid, gid);
1176 return;
1177}
1178
1179/*****************************************************************
1180 *THE LEGACY* convert SID to uid function.
1181*****************************************************************/
1182
1183static bool legacy_sid_to_uid(const DOM_SID *psid, uid_t *puid)
1184{
1185 enum lsa_SidType type;
1186 uint32 rid;
1187
1188 if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1189 union unid_t id;
1190 bool ret;
1191
1192 become_root();
1193 ret = pdb_sid_to_id(psid, &id, &type);
1194 unbecome_root();
1195
1196 if (ret) {
1197 if (type != SID_NAME_USER) {
1198 DEBUG(5, ("sid %s is a %s, expected a user\n",
1199 sid_string_dbg(psid),
1200 sid_type_lookup(type)));
1201 return false;
1202 }
1203 *puid = id.uid;
1204 goto done;
1205 }
1206
1207 /* This was ours, but it was not mapped. Fail */
1208 }
1209
1210 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1211 sid_string_dbg(psid)));
1212 return false;
1213
1214done:
1215 DEBUG(10,("LEGACY: sid %s -> uid %u\n", sid_string_dbg(psid),
1216 (unsigned int)*puid ));
1217
1218 store_uid_sid_cache(psid, *puid);
1219 return true;
1220}
1221
1222/*****************************************************************
1223 *THE LEGACY* convert SID to gid function.
1224 Group mapping is used for gids that maps to Wellknown SIDs
1225*****************************************************************/
1226
1227static bool legacy_sid_to_gid(const DOM_SID *psid, gid_t *pgid)
1228{
1229 uint32 rid;
1230 GROUP_MAP map;
1231 union unid_t id;
1232 enum lsa_SidType type;
1233
1234 if ((sid_check_is_in_builtin(psid) ||
1235 sid_check_is_in_wellknown_domain(psid))) {
1236 bool ret;
1237
1238 become_root();
1239 ret = pdb_getgrsid(&map, *psid);
1240 unbecome_root();
1241
1242 if (ret) {
1243 *pgid = map.gid;
1244 goto done;
1245 }
1246 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1247 sid_string_dbg(psid)));
1248 return false;
1249 }
1250
1251 if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1252 bool ret;
1253
1254 become_root();
1255 ret = pdb_sid_to_id(psid, &id, &type);
1256 unbecome_root();
1257
1258 if (ret) {
1259 if ((type != SID_NAME_DOM_GRP) &&
1260 (type != SID_NAME_ALIAS)) {
1261 DEBUG(5, ("LEGACY: sid %s is a %s, expected "
1262 "a group\n", sid_string_dbg(psid),
1263 sid_type_lookup(type)));
1264 return false;
1265 }
1266 *pgid = id.gid;
1267 goto done;
1268 }
1269
1270 /* This was ours, but it was not mapped. Fail */
1271 }
1272
1273 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1274 sid_string_dbg(psid)));
1275 return false;
1276
1277 done:
1278 DEBUG(10,("LEGACY: sid %s -> gid %u\n", sid_string_dbg(psid),
1279 (unsigned int)*pgid ));
1280
1281 store_gid_sid_cache(psid, *pgid);
1282
1283 return true;
1284}
1285
1286/*****************************************************************
1287 *THE CANONICAL* convert uid_t to SID function.
1288*****************************************************************/
1289
1290void uid_to_sid(DOM_SID *psid, uid_t uid)
1291{
1292 ZERO_STRUCTP(psid);
1293
1294 if (fetch_sid_from_uid_cache(psid, uid))
1295 return;
1296
1297 if (!winbind_uid_to_sid(psid, uid)) {
1298 if (!winbind_ping()) {
1299 legacy_uid_to_sid(psid, uid);
1300 return;
1301 }
1302
1303 DEBUG(5, ("uid_to_sid: winbind failed to find a sid for uid %u\n",
1304 uid));
1305 return;
1306 }
1307
1308 DEBUG(10,("uid %u -> sid %s\n", (unsigned int)uid,
1309 sid_string_dbg(psid)));
1310
1311 store_uid_sid_cache(psid, uid);
1312 return;
1313}
1314
1315/*****************************************************************
1316 *THE CANONICAL* convert gid_t to SID function.
1317*****************************************************************/
1318
1319void gid_to_sid(DOM_SID *psid, gid_t gid)
1320{
1321 ZERO_STRUCTP(psid);
1322
1323 if (fetch_sid_from_gid_cache(psid, gid))
1324 return;
1325
1326 if (!winbind_gid_to_sid(psid, gid)) {
1327 if (!winbind_ping()) {
1328 legacy_gid_to_sid(psid, gid);
1329 return;
1330 }
1331
1332 DEBUG(5, ("gid_to_sid: winbind failed to find a sid for gid %u\n",
1333 gid));
1334 return;
1335 }
1336
1337 DEBUG(10,("gid %u -> sid %s\n", (unsigned int)gid,
1338 sid_string_dbg(psid)));
1339
1340 store_gid_sid_cache(psid, gid);
1341 return;
1342}
1343
1344/*****************************************************************
1345 *THE CANONICAL* convert SID to uid function.
1346*****************************************************************/
1347
1348bool sid_to_uid(const DOM_SID *psid, uid_t *puid)
1349{
1350 uint32 rid;
1351 gid_t gid;
1352
1353 if (fetch_uid_from_cache(puid, psid))
1354 return true;
1355
1356 if (fetch_gid_from_cache(&gid, psid)) {
1357 return false;
1358 }
1359
1360 /* Optimize for the Unix Users Domain
1361 * as the conversion is straightforward */
1362 if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
1363 uid_t uid = rid;
1364 *puid = uid;
1365
1366 /* return here, don't cache */
1367 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1368 (unsigned int)*puid ));
1369 return true;
1370 }
1371
1372 if (!winbind_sid_to_uid(puid, psid)) {
1373 if (!winbind_ping()) {
1374 return legacy_sid_to_uid(psid, puid);
1375 }
1376
1377 DEBUG(5, ("winbind failed to find a uid for sid %s\n",
1378 sid_string_dbg(psid)));
1379 return false;
1380 }
1381
1382 /* TODO: Here would be the place to allocate both a gid and a uid for
1383 * the SID in question */
1384
1385 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1386 (unsigned int)*puid ));
1387
1388 store_uid_sid_cache(psid, *puid);
1389 return true;
1390}
1391
1392/*****************************************************************
1393 *THE CANONICAL* convert SID to gid function.
1394 Group mapping is used for gids that maps to Wellknown SIDs
1395*****************************************************************/
1396
1397bool sid_to_gid(const DOM_SID *psid, gid_t *pgid)
1398{
1399 uint32 rid;
1400 uid_t uid;
1401
1402 if (fetch_gid_from_cache(pgid, psid))
1403 return true;
1404
1405 if (fetch_uid_from_cache(&uid, psid))
1406 return false;
1407
1408 /* Optimize for the Unix Groups Domain
1409 * as the conversion is straightforward */
1410 if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
1411 gid_t gid = rid;
1412 *pgid = gid;
1413
1414 /* return here, don't cache */
1415 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1416 (unsigned int)*pgid ));
1417 return true;
1418 }
1419
1420 /* Ask winbindd if it can map this sid to a gid.
1421 * (Idmap will check it is a valid SID and of the right type) */
1422
1423 if ( !winbind_sid_to_gid(pgid, psid) ) {
1424 if (!winbind_ping()) {
1425 return legacy_sid_to_gid(psid, pgid);
1426 }
1427
1428 DEBUG(10,("winbind failed to find a gid for sid %s\n",
1429 sid_string_dbg(psid)));
1430 return false;
1431 }
1432
1433 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1434 (unsigned int)*pgid ));
1435
1436 store_gid_sid_cache(psid, *pgid);
1437
1438 return true;
1439}
1440
Note: See TracBrowser for help on using the repository browser.