/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- lookup_name
- lookup_name_smbconf
- wb_lookup_rids
- lookup_rids
- lookup_as_domain
- check_dom_sid_to_level
- lookup_sids
- lookup_sid
- fetch_sid_from_uid_cache
- fetch_uid_from_cache
- store_uid_sid_cache
- fetch_sid_from_gid_cache
- fetch_gid_from_cache
- store_gid_sid_cache
- legacy_uid_to_sid
- legacy_gid_to_sid
- legacy_sid_to_uid
- legacy_sid_to_gid
- uid_to_sid
- gid_to_sid
- sid_to_uid
- sid_to_gid
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
32 bool lookup_name(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
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
349 bool lookup_name_smbconf(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
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
409 static bool wb_lookup_rids(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
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 = talloc_strdup(mem_ctx, "");
427 if (!(*domain_name)) {
428 TALLOC_FREE(tmp_ctx);
429 return False;
430 }
431 for (i=0; i<num_rids; i++) {
432 names[i] = talloc_strdup(names, "");
433 if (!names[i]) {
434 TALLOC_FREE(tmp_ctx);
435 return False;
436 }
437 types[i] = SID_NAME_UNKNOWN;
438 }
439 TALLOC_FREE(tmp_ctx);
440 return true;
441 }
442
443 if (!(*domain_name = talloc_strdup(mem_ctx, *domain_name))) {
444 TALLOC_FREE(tmp_ctx);
445 return false;
446 }
447
448 /*
449 * winbind_lookup_rids allocates its own array. We've been given the
450 * array, so copy it over
451 */
452
453 for (i=0; i<num_rids; i++) {
454 if (my_names[i] == NULL) {
455 TALLOC_FREE(tmp_ctx);
456 return false;
457 }
458 if (!(names[i] = talloc_strdup(names, my_names[i]))) {
459 TALLOC_FREE(tmp_ctx);
460 return false;
461 }
462 types[i] = my_types[i];
463 }
464 TALLOC_FREE(tmp_ctx);
465 return true;
466 }
467
468 static bool lookup_rids(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
/* [<][>][^][v][top][bottom][index][help] */
469 int num_rids, uint32_t *rids,
470 const char **domain_name,
471 const char ***names, enum lsa_SidType **types)
472 {
473 int i;
474
475 DEBUG(10, ("lookup_rids called for domain sid '%s'\n",
476 sid_string_dbg(domain_sid)));
477
478 if (num_rids) {
479 *names = TALLOC_ZERO_ARRAY(mem_ctx, const char *, num_rids);
480 *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
481
482 if ((*names == NULL) || (*types == NULL)) {
483 return false;
484 }
485
486 for (i = 0; i < num_rids; i++)
487 (*types)[i] = SID_NAME_UNKNOWN;
488 } else {
489 *names = NULL;
490 *types = NULL;
491 }
492
493 if (sid_check_is_domain(domain_sid)) {
494 NTSTATUS result;
495
496 if (*domain_name == NULL) {
497 *domain_name = talloc_strdup(
498 mem_ctx, get_global_sam_name());
499 }
500
501 if (*domain_name == NULL) {
502 return false;
503 }
504
505 become_root();
506 result = pdb_lookup_rids(domain_sid, num_rids, rids,
507 *names, *types);
508 unbecome_root();
509
510 return (NT_STATUS_IS_OK(result) ||
511 NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
512 NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
513 }
514
515 if (sid_check_is_builtin(domain_sid)) {
516
517 if (*domain_name == NULL) {
518 *domain_name = talloc_strdup(
519 mem_ctx, builtin_domain_name());
520 }
521
522 if (*domain_name == NULL) {
523 return false;
524 }
525
526 for (i=0; i<num_rids; i++) {
527 if (lookup_builtin_rid(*names, rids[i],
528 &(*names)[i])) {
529 if ((*names)[i] == NULL) {
530 return false;
531 }
532 (*types)[i] = SID_NAME_ALIAS;
533 } else {
534 (*types)[i] = SID_NAME_UNKNOWN;
535 }
536 }
537 return true;
538 }
539
540 if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
541 for (i=0; i<num_rids; i++) {
542 DOM_SID sid;
543 sid_copy(&sid, domain_sid);
544 sid_append_rid(&sid, rids[i]);
545 if (lookup_wellknown_sid(mem_ctx, &sid,
546 domain_name, &(*names)[i])) {
547 if ((*names)[i] == NULL) {
548 return false;
549 }
550 (*types)[i] = SID_NAME_WKN_GRP;
551 } else {
552 (*types)[i] = SID_NAME_UNKNOWN;
553 }
554 }
555 return true;
556 }
557
558 if (sid_check_is_unix_users(domain_sid)) {
559 if (*domain_name == NULL) {
560 *domain_name = talloc_strdup(
561 mem_ctx, unix_users_domain_name());
562 if (*domain_name == NULL) {
563 return false;
564 }
565 }
566 for (i=0; i<num_rids; i++) {
567 (*names)[i] = talloc_strdup(
568 (*names), uidtoname(rids[i]));
569 if ((*names)[i] == NULL) {
570 return false;
571 }
572 (*types)[i] = SID_NAME_USER;
573 }
574 return true;
575 }
576
577 if (sid_check_is_unix_groups(domain_sid)) {
578 if (*domain_name == NULL) {
579 *domain_name = talloc_strdup(
580 mem_ctx, unix_groups_domain_name());
581 if (*domain_name == NULL) {
582 return false;
583 }
584 }
585 for (i=0; i<num_rids; i++) {
586 (*names)[i] = talloc_strdup(
587 (*names), gidtoname(rids[i]));
588 if ((*names)[i] == NULL) {
589 return false;
590 }
591 (*types)[i] = SID_NAME_DOM_GRP;
592 }
593 return true;
594 }
595
596 return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
597 domain_name, *names, *types);
598 }
599
600 /*
601 * Is the SID a domain as such? If yes, lookup its name.
602 */
603
604 static bool lookup_as_domain(const DOM_SID *sid, TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
605 const char **name)
606 {
607 const char *tmp;
608 enum lsa_SidType type;
609
610 if (sid_check_is_domain(sid)) {
611 *name = talloc_strdup(mem_ctx, get_global_sam_name());
612 return true;
613 }
614
615 if (sid_check_is_builtin(sid)) {
616 *name = talloc_strdup(mem_ctx, builtin_domain_name());
617 return true;
618 }
619
620 if (sid_check_is_wellknown_domain(sid, &tmp)) {
621 *name = talloc_strdup(mem_ctx, tmp);
622 return true;
623 }
624
625 if (sid_check_is_unix_users(sid)) {
626 *name = talloc_strdup(mem_ctx, unix_users_domain_name());
627 return true;
628 }
629
630 if (sid_check_is_unix_groups(sid)) {
631 *name = talloc_strdup(mem_ctx, unix_groups_domain_name());
632 return true;
633 }
634
635 if (sid->num_auths != 4) {
636 /* This can't be a domain */
637 return false;
638 }
639
640 if (IS_DC) {
641 uint32 i, num_domains;
642 struct trustdom_info **domains;
643
644 /* This is relatively expensive, but it happens only on DCs
645 * and for SIDs that have 4 sub-authorities and thus look like
646 * domains */
647
648 if (!NT_STATUS_IS_OK(pdb_enum_trusteddoms(mem_ctx,
649 &num_domains,
650 &domains))) {
651 return false;
652 }
653
654 for (i=0; i<num_domains; i++) {
655 if (sid_equal(sid, &domains[i]->sid)) {
656 *name = talloc_strdup(mem_ctx,
657 domains[i]->name);
658 return true;
659 }
660 }
661 return false;
662 }
663
664 if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
665 (type == SID_NAME_DOMAIN)) {
666 *name = tmp;
667 return true;
668 }
669
670 return false;
671 }
672
673 /*
674 * This tries to implement the rather weird rules for the lsa_lookup level
675 * parameter.
676 *
677 * This is as close as we can get to what W2k3 does. With this we survive the
678 * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
679 * different, but I assume that's just being too liberal. For example, W2k3
680 * replies to everything else but the levels 1-6 with INVALID_PARAMETER
681 * whereas NT4 does the same as level 1 (I think). I did not fully test that
682 * with NT4, this is what w2k3 does.
683 *
684 * Level 1: Ask everywhere
685 * Level 2: Ask domain and trusted domains, no builtin and wkn
686 * Level 3: Only ask domain
687 * Level 4: W2k3ad: Only ask AD trusts
688 * Level 5: Only ask transitive forest trusts
689 * Level 6: Like 4
690 */
691
692 static bool check_dom_sid_to_level(const DOM_SID *sid, int level)
/* [<][>][^][v][top][bottom][index][help] */
693 {
694 int ret = false;
695
696 switch(level) {
697 case 1:
698 ret = true;
699 break;
700 case 2:
701 ret = (!sid_check_is_builtin(sid) &&
702 !sid_check_is_wellknown_domain(sid, NULL));
703 break;
704 case 3:
705 case 4:
706 case 6:
707 ret = sid_check_is_domain(sid);
708 break;
709 case 5:
710 ret = false;
711 break;
712 }
713
714 DEBUG(10, ("%s SID %s in level %d\n",
715 ret ? "Accepting" : "Rejecting",
716 sid_string_dbg(sid), level));
717 return ret;
718 }
719
720 /*
721 * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
722 * references to domains, it is explicitly made for this.
723 *
724 * This attempts to be as efficient as possible: It collects all SIDs
725 * belonging to a domain and hands them in bulk to the appropriate lookup
726 * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
727 * *hugely* from this. Winbind is going to be extended with a lookup_rids
728 * interface as well, so on a DC we can do a bulk lsa_lookuprids to the
729 * appropriate DC.
730 */
731
732 NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
/* [<][>][^][v][top][bottom][index][help] */
733 const DOM_SID **sids, int level,
734 struct lsa_dom_info **ret_domains,
735 struct lsa_name_info **ret_names)
736 {
737 TALLOC_CTX *tmp_ctx;
738 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
739 struct lsa_name_info *name_infos;
740 struct lsa_dom_info *dom_infos = NULL;
741
742 int i, j;
743
744 if (!(tmp_ctx = talloc_new(mem_ctx))) {
745 DEBUG(0, ("talloc_new failed\n"));
746 return NT_STATUS_NO_MEMORY;
747 }
748
749 if (num_sids) {
750 name_infos = TALLOC_ARRAY(mem_ctx, struct lsa_name_info, num_sids);
751 if (name_infos == NULL) {
752 result = NT_STATUS_NO_MEMORY;
753 goto fail;
754 }
755 } else {
756 name_infos = NULL;
757 }
758
759 dom_infos = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_dom_info,
760 LSA_REF_DOMAIN_LIST_MULTIPLIER);
761 if (dom_infos == NULL) {
762 result = NT_STATUS_NO_MEMORY;
763 goto fail;
764 }
765
766 /* First build up the data structures:
767 *
768 * dom_infos is a list of domains referenced in the list of
769 * SIDs. Later we will walk the list of domains and look up the RIDs
770 * in bulk.
771 *
772 * name_infos is a shadow-copy of the SIDs array to collect the real
773 * data.
774 *
775 * dom_info->idxs is an index into the name_infos array. The
776 * difficulty we have here is that we need to keep the SIDs the client
777 * asked for in the same order for the reply
778 */
779
780 for (i=0; i<num_sids; i++) {
781 DOM_SID sid;
782 uint32 rid;
783 const char *domain_name = NULL;
784
785 sid_copy(&sid, sids[i]);
786 name_infos[i].type = SID_NAME_USE_NONE;
787
788 if (lookup_as_domain(&sid, name_infos, &domain_name)) {
789 /* We can't push that through the normal lookup
790 * process, as this would reference illegal
791 * domains.
792 *
793 * For example S-1-5-32 would end up referencing
794 * domain S-1-5- with RID 32 which is clearly wrong.
795 */
796 if (domain_name == NULL) {
797 result = NT_STATUS_NO_MEMORY;
798 goto fail;
799 }
800
801 name_infos[i].rid = 0;
802 name_infos[i].type = SID_NAME_DOMAIN;
803 name_infos[i].name = NULL;
804
805 if (sid_check_is_builtin(&sid)) {
806 /* Yes, W2k3 returns "BUILTIN" both as domain
807 * and name here */
808 name_infos[i].name = talloc_strdup(
809 name_infos, builtin_domain_name());
810 if (name_infos[i].name == NULL) {
811 result = NT_STATUS_NO_MEMORY;
812 goto fail;
813 }
814 }
815 } else {
816 /* This is a normal SID with rid component */
817 if (!sid_split_rid(&sid, &rid)) {
818 result = NT_STATUS_INVALID_SID;
819 goto fail;
820 }
821 }
822
823 if (!check_dom_sid_to_level(&sid, level)) {
824 name_infos[i].rid = 0;
825 name_infos[i].type = SID_NAME_UNKNOWN;
826 name_infos[i].name = NULL;
827 continue;
828 }
829
830 for (j=0; j<LSA_REF_DOMAIN_LIST_MULTIPLIER; j++) {
831 if (!dom_infos[j].valid) {
832 break;
833 }
834 if (sid_equal(&sid, &dom_infos[j].sid)) {
835 break;
836 }
837 }
838
839 if (j == LSA_REF_DOMAIN_LIST_MULTIPLIER) {
840 /* TODO: What's the right error message here? */
841 result = NT_STATUS_NONE_MAPPED;
842 goto fail;
843 }
844
845 if (!dom_infos[j].valid) {
846 /* We found a domain not yet referenced, create a new
847 * ref. */
848 dom_infos[j].valid = true;
849 sid_copy(&dom_infos[j].sid, &sid);
850
851 if (domain_name != NULL) {
852 /* This name was being found above in the case
853 * when we found a domain SID */
854 dom_infos[j].name =
855 talloc_strdup(dom_infos, domain_name);
856 if (dom_infos[j].name == NULL) {
857 result = NT_STATUS_NO_MEMORY;
858 goto fail;
859 }
860 } else {
861 /* lookup_rids will take care of this */
862 dom_infos[j].name = NULL;
863 }
864 }
865
866 name_infos[i].dom_idx = j;
867
868 if (name_infos[i].type == SID_NAME_USE_NONE) {
869 name_infos[i].rid = rid;
870
871 ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
872 &dom_infos[j].num_idxs);
873
874 if (dom_infos[j].idxs == NULL) {
875 result = NT_STATUS_NO_MEMORY;
876 goto fail;
877 }
878 }
879 }
880
881 /* Iterate over the domains found */
882
883 for (i=0; i<LSA_REF_DOMAIN_LIST_MULTIPLIER; i++) {
884 uint32_t *rids;
885 const char *domain_name = NULL;
886 const char **names;
887 enum lsa_SidType *types;
888 struct lsa_dom_info *dom = &dom_infos[i];
889
890 if (!dom->valid) {
891 /* No domains left, we're done */
892 break;
893 }
894
895 if (dom->num_idxs) {
896 if (!(rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs))) {
897 result = NT_STATUS_NO_MEMORY;
898 goto fail;
899 }
900 } else {
901 rids = NULL;
902 }
903
904 for (j=0; j<dom->num_idxs; j++) {
905 rids[j] = name_infos[dom->idxs[j]].rid;
906 }
907
908 if (!lookup_rids(tmp_ctx, &dom->sid,
909 dom->num_idxs, rids, &domain_name,
910 &names, &types)) {
911 result = NT_STATUS_NO_MEMORY;
912 goto fail;
913 }
914
915 if (!(dom->name = talloc_strdup(dom_infos, domain_name))) {
916 result = NT_STATUS_NO_MEMORY;
917 goto fail;
918 }
919
920 for (j=0; j<dom->num_idxs; j++) {
921 int idx = dom->idxs[j];
922 name_infos[idx].type = types[j];
923 if (types[j] != SID_NAME_UNKNOWN) {
924 name_infos[idx].name =
925 talloc_strdup(name_infos, names[j]);
926 if (name_infos[idx].name == NULL) {
927 result = NT_STATUS_NO_MEMORY;
928 goto fail;
929 }
930 } else {
931 name_infos[idx].name = NULL;
932 }
933 }
934 }
935
936 *ret_domains = dom_infos;
937 *ret_names = name_infos;
938 TALLOC_FREE(tmp_ctx);
939 return NT_STATUS_OK;
940
941 fail:
942 TALLOC_FREE(dom_infos);
943 TALLOC_FREE(name_infos);
944 TALLOC_FREE(tmp_ctx);
945 return result;
946 }
947
948 /*****************************************************************
949 *THE CANONICAL* convert SID to name function.
950 *****************************************************************/
951
952 bool lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
/* [<][>][^][v][top][bottom][index][help] */
953 const char **ret_domain, const char **ret_name,
954 enum lsa_SidType *ret_type)
955 {
956 struct lsa_dom_info *domain;
957 struct lsa_name_info *name;
958 TALLOC_CTX *tmp_ctx;
959 bool ret = false;
960
961 DEBUG(10, ("lookup_sid called for SID '%s'\n", sid_string_dbg(sid)));
962
963 if (!(tmp_ctx = talloc_new(mem_ctx))) {
964 DEBUG(0, ("talloc_new failed\n"));
965 return false;
966 }
967
968 if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
969 &domain, &name))) {
970 goto done;
971 }
972
973 if (name->type == SID_NAME_UNKNOWN) {
974 goto done;
975 }
976
977 if ((ret_domain != NULL) &&
978 !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
979 goto done;
980 }
981
982 if ((ret_name != NULL) &&
983 !(*ret_name = talloc_strdup(mem_ctx, name->name))) {
984 goto done;
985 }
986
987 if (ret_type != NULL) {
988 *ret_type = name->type;
989 }
990
991 ret = true;
992
993 done:
994 if (ret) {
995 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n", sid_string_dbg(sid),
996 domain->name, name->name, name->type));
997 } else {
998 DEBUG(10, ("failed to lookup sid %s\n", sid_string_dbg(sid)));
999 }
1000 TALLOC_FREE(tmp_ctx);
1001 return ret;
1002 }
1003
1004 /*****************************************************************
1005 Id mapping cache. This is to avoid Winbind mappings already
1006 seen by smbd to be queried too frequently, keeping winbindd
1007 busy, and blocking smbd while winbindd is busy with other
1008 stuff. Written by Michael Steffens <michael.steffens@hp.com>,
1009 modified to use linked lists by jra.
1010 *****************************************************************/
1011
1012 /*****************************************************************
1013 Find a SID given a uid.
1014 *****************************************************************/
1015
1016 static bool fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid)
/* [<][>][^][v][top][bottom][index][help] */
1017 {
1018 DATA_BLOB cache_value;
1019
1020 if (!memcache_lookup(NULL, UID_SID_CACHE,
1021 data_blob_const(&uid, sizeof(uid)),
1022 &cache_value)) {
1023 return false;
1024 }
1025
1026 memcpy(psid, cache_value.data, MIN(sizeof(*psid), cache_value.length));
1027 SMB_ASSERT(cache_value.length >= offsetof(struct dom_sid, id_auth));
1028 SMB_ASSERT(cache_value.length == ndr_size_dom_sid(psid, NULL, 0));
1029
1030 return true;
1031 }
1032
1033 /*****************************************************************
1034 Find a uid given a SID.
1035 *****************************************************************/
1036
1037 static bool fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid )
/* [<][>][^][v][top][bottom][index][help] */
1038 {
1039 DATA_BLOB cache_value;
1040
1041 if (!memcache_lookup(NULL, SID_UID_CACHE,
1042 data_blob_const(psid, ndr_size_dom_sid(psid, NULL, 0)),
1043 &cache_value)) {
1044 return false;
1045 }
1046
1047 SMB_ASSERT(cache_value.length == sizeof(*puid));
1048 memcpy(puid, cache_value.data, sizeof(*puid));
1049
1050 return true;
1051 }
1052
1053 /*****************************************************************
1054 Store uid to SID mapping in cache.
1055 *****************************************************************/
1056
1057 void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
/* [<][>][^][v][top][bottom][index][help] */
1058 {
1059 memcache_add(NULL, SID_UID_CACHE,
1060 data_blob_const(psid, ndr_size_dom_sid(psid, NULL, 0)),
1061 data_blob_const(&uid, sizeof(uid)));
1062 memcache_add(NULL, UID_SID_CACHE,
1063 data_blob_const(&uid, sizeof(uid)),
1064 data_blob_const(psid, ndr_size_dom_sid(psid, NULL, 0)));
1065 }
1066
1067 /*****************************************************************
1068 Find a SID given a gid.
1069 *****************************************************************/
1070
1071 static bool fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid)
/* [<][>][^][v][top][bottom][index][help] */
1072 {
1073 DATA_BLOB cache_value;
1074
1075 if (!memcache_lookup(NULL, GID_SID_CACHE,
1076 data_blob_const(&gid, sizeof(gid)),
1077 &cache_value)) {
1078 return false;
1079 }
1080
1081 memcpy(psid, cache_value.data, MIN(sizeof(*psid), cache_value.length));
1082 SMB_ASSERT(cache_value.length >= offsetof(struct dom_sid, id_auth));
1083 SMB_ASSERT(cache_value.length == ndr_size_dom_sid(psid, NULL, 0));
1084
1085 return true;
1086 }
1087
1088 /*****************************************************************
1089 Find a gid given a SID.
1090 *****************************************************************/
1091
1092 static bool fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid)
/* [<][>][^][v][top][bottom][index][help] */
1093 {
1094 DATA_BLOB cache_value;
1095
1096 if (!memcache_lookup(NULL, SID_GID_CACHE,
1097 data_blob_const(psid, ndr_size_dom_sid(psid, NULL, 0)),
1098 &cache_value)) {
1099 return false;
1100 }
1101
1102 SMB_ASSERT(cache_value.length == sizeof(*pgid));
1103 memcpy(pgid, cache_value.data, sizeof(*pgid));
1104
1105 return true;
1106 }
1107
1108 /*****************************************************************
1109 Store gid to SID mapping in cache.
1110 *****************************************************************/
1111
1112 void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
/* [<][>][^][v][top][bottom][index][help] */
1113 {
1114 memcache_add(NULL, SID_GID_CACHE,
1115 data_blob_const(psid, ndr_size_dom_sid(psid, NULL, 0)),
1116 data_blob_const(&gid, sizeof(gid)));
1117 memcache_add(NULL, GID_SID_CACHE,
1118 data_blob_const(&gid, sizeof(gid)),
1119 data_blob_const(psid, ndr_size_dom_sid(psid, NULL, 0)));
1120 }
1121
1122 /*****************************************************************
1123 *THE LEGACY* convert uid_t to SID function.
1124 *****************************************************************/
1125
1126 static void legacy_uid_to_sid(DOM_SID *psid, uid_t uid)
/* [<][>][^][v][top][bottom][index][help] */
1127 {
1128 uint32 rid;
1129 bool ret;
1130
1131 ZERO_STRUCTP(psid);
1132
1133 become_root();
1134 ret = pdb_uid_to_rid(uid, &rid);
1135 unbecome_root();
1136
1137 if (ret) {
1138 /* This is a mapped user */
1139 sid_copy(psid, get_global_sam_sid());
1140 sid_append_rid(psid, rid);
1141 goto done;
1142 }
1143
1144 /* This is an unmapped user */
1145
1146 uid_to_unix_users_sid(uid, psid);
1147
1148 done:
1149 DEBUG(10,("LEGACY: uid %u -> sid %s\n", (unsigned int)uid,
1150 sid_string_dbg(psid)));
1151
1152 store_uid_sid_cache(psid, uid);
1153 return;
1154 }
1155
1156 /*****************************************************************
1157 *THE LEGACY* convert gid_t to SID function.
1158 *****************************************************************/
1159
1160 static void legacy_gid_to_sid(DOM_SID *psid, gid_t gid)
/* [<][>][^][v][top][bottom][index][help] */
1161 {
1162 bool ret;
1163
1164 ZERO_STRUCTP(psid);
1165
1166 become_root();
1167 ret = pdb_gid_to_sid(gid, psid);
1168 unbecome_root();
1169
1170 if (ret) {
1171 /* This is a mapped group */
1172 goto done;
1173 }
1174
1175 /* This is an unmapped group */
1176
1177 gid_to_unix_groups_sid(gid, psid);
1178
1179 done:
1180 DEBUG(10,("LEGACY: gid %u -> sid %s\n", (unsigned int)gid,
1181 sid_string_dbg(psid)));
1182
1183 store_gid_sid_cache(psid, gid);
1184 return;
1185 }
1186
1187 /*****************************************************************
1188 *THE LEGACY* convert SID to uid function.
1189 *****************************************************************/
1190
1191 static bool legacy_sid_to_uid(const DOM_SID *psid, uid_t *puid)
/* [<][>][^][v][top][bottom][index][help] */
1192 {
1193 enum lsa_SidType type;
1194 uint32 rid;
1195
1196 if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1197 union unid_t id;
1198 bool ret;
1199
1200 become_root();
1201 ret = pdb_sid_to_id(psid, &id, &type);
1202 unbecome_root();
1203
1204 if (ret) {
1205 if (type != SID_NAME_USER) {
1206 DEBUG(5, ("sid %s is a %s, expected a user\n",
1207 sid_string_dbg(psid),
1208 sid_type_lookup(type)));
1209 return false;
1210 }
1211 *puid = id.uid;
1212 goto done;
1213 }
1214
1215 /* This was ours, but it was not mapped. Fail */
1216 }
1217
1218 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1219 sid_string_dbg(psid)));
1220 return false;
1221
1222 done:
1223 DEBUG(10,("LEGACY: sid %s -> uid %u\n", sid_string_dbg(psid),
1224 (unsigned int)*puid ));
1225
1226 store_uid_sid_cache(psid, *puid);
1227 return true;
1228 }
1229
1230 /*****************************************************************
1231 *THE LEGACY* convert SID to gid function.
1232 Group mapping is used for gids that maps to Wellknown SIDs
1233 *****************************************************************/
1234
1235 static bool legacy_sid_to_gid(const DOM_SID *psid, gid_t *pgid)
/* [<][>][^][v][top][bottom][index][help] */
1236 {
1237 uint32 rid;
1238 GROUP_MAP map;
1239 union unid_t id;
1240 enum lsa_SidType type;
1241
1242 if ((sid_check_is_in_builtin(psid) ||
1243 sid_check_is_in_wellknown_domain(psid))) {
1244 bool ret;
1245
1246 become_root();
1247 ret = pdb_getgrsid(&map, *psid);
1248 unbecome_root();
1249
1250 if (ret) {
1251 *pgid = map.gid;
1252 goto done;
1253 }
1254 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1255 sid_string_dbg(psid)));
1256 return false;
1257 }
1258
1259 if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1260 bool ret;
1261
1262 become_root();
1263 ret = pdb_sid_to_id(psid, &id, &type);
1264 unbecome_root();
1265
1266 if (ret) {
1267 if ((type != SID_NAME_DOM_GRP) &&
1268 (type != SID_NAME_ALIAS)) {
1269 DEBUG(5, ("LEGACY: sid %s is a %s, expected "
1270 "a group\n", sid_string_dbg(psid),
1271 sid_type_lookup(type)));
1272 return false;
1273 }
1274 *pgid = id.gid;
1275 goto done;
1276 }
1277
1278 /* This was ours, but it was not mapped. Fail */
1279 }
1280
1281 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1282 sid_string_dbg(psid)));
1283 return false;
1284
1285 done:
1286 DEBUG(10,("LEGACY: sid %s -> gid %u\n", sid_string_dbg(psid),
1287 (unsigned int)*pgid ));
1288
1289 store_gid_sid_cache(psid, *pgid);
1290
1291 return true;
1292 }
1293
1294 /*****************************************************************
1295 *THE CANONICAL* convert uid_t to SID function.
1296 *****************************************************************/
1297
1298 void uid_to_sid(DOM_SID *psid, uid_t uid)
/* [<][>][^][v][top][bottom][index][help] */
1299 {
1300 bool expired = true;
1301 bool ret;
1302 ZERO_STRUCTP(psid);
1303
1304 if (fetch_sid_from_uid_cache(psid, uid))
1305 return;
1306
1307 /* Check the winbindd cache directly. */
1308 ret = idmap_cache_find_uid2sid(uid, psid, &expired);
1309
1310 if (ret && !expired && is_null_sid(psid)) {
1311 /*
1312 * Negative cache entry, we already asked.
1313 * do legacy.
1314 */
1315 legacy_uid_to_sid(psid, uid);
1316 return;
1317 }
1318
1319 if (!ret || expired) {
1320 /* Not in cache. Ask winbindd. */
1321 if (!winbind_uid_to_sid(psid, uid)) {
1322 /*
1323 * We shouldn't return the NULL SID
1324 * here if winbind was running and
1325 * couldn't map, as winbind will have
1326 * added a negative entry that will
1327 * cause us to go though the
1328 * legacy_uid_to_sid()
1329 * function anyway in the case above
1330 * the next time we ask.
1331 */
1332 DEBUG(5, ("uid_to_sid: winbind failed to find a sid "
1333 "for uid %u\n", (unsigned int)uid));
1334
1335 legacy_uid_to_sid(psid, uid);
1336 return;
1337 }
1338 }
1339
1340 DEBUG(10,("uid %u -> sid %s\n", (unsigned int)uid,
1341 sid_string_dbg(psid)));
1342
1343 store_uid_sid_cache(psid, uid);
1344 return;
1345 }
1346
1347 /*****************************************************************
1348 *THE CANONICAL* convert gid_t to SID function.
1349 *****************************************************************/
1350
1351 void gid_to_sid(DOM_SID *psid, gid_t gid)
/* [<][>][^][v][top][bottom][index][help] */
1352 {
1353 bool expired = true;
1354 bool ret;
1355 ZERO_STRUCTP(psid);
1356
1357 if (fetch_sid_from_gid_cache(psid, gid))
1358 return;
1359
1360 /* Check the winbindd cache directly. */
1361 ret = idmap_cache_find_gid2sid(gid, psid, &expired);
1362
1363 if (ret && !expired && is_null_sid(psid)) {
1364 /*
1365 * Negative cache entry, we already asked.
1366 * do legacy.
1367 */
1368 legacy_gid_to_sid(psid, gid);
1369 return;
1370 }
1371
1372 if (!ret || expired) {
1373 /* Not in cache. Ask winbindd. */
1374 if (!winbind_gid_to_sid(psid, gid)) {
1375 /*
1376 * We shouldn't return the NULL SID
1377 * here if winbind was running and
1378 * couldn't map, as winbind will have
1379 * added a negative entry that will
1380 * cause us to go though the
1381 * legacy_gid_to_sid()
1382 * function anyway in the case above
1383 * the next time we ask.
1384 */
1385 DEBUG(5, ("gid_to_sid: winbind failed to find a sid "
1386 "for gid %u\n", (unsigned int)gid));
1387
1388 legacy_gid_to_sid(psid, gid);
1389 return;
1390 }
1391 }
1392
1393 DEBUG(10,("gid %u -> sid %s\n", (unsigned int)gid,
1394 sid_string_dbg(psid)));
1395
1396 store_gid_sid_cache(psid, gid);
1397 return;
1398 }
1399
1400 /*****************************************************************
1401 *THE CANONICAL* convert SID to uid function.
1402 *****************************************************************/
1403
1404 bool sid_to_uid(const DOM_SID *psid, uid_t *puid)
/* [<][>][^][v][top][bottom][index][help] */
1405 {
1406 bool expired = true;
1407 bool ret;
1408 uint32 rid;
1409 gid_t gid;
1410
1411 if (fetch_uid_from_cache(puid, psid))
1412 return true;
1413
1414 if (fetch_gid_from_cache(&gid, psid)) {
1415 return false;
1416 }
1417
1418 /* Optimize for the Unix Users Domain
1419 * as the conversion is straightforward */
1420 if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
1421 uid_t uid = rid;
1422 *puid = uid;
1423
1424 /* return here, don't cache */
1425 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1426 (unsigned int)*puid ));
1427 return true;
1428 }
1429
1430 /* Check the winbindd cache directly. */
1431 ret = idmap_cache_find_sid2uid(psid, puid, &expired);
1432
1433 if (ret && !expired && (*puid == (uid_t)-1)) {
1434 /*
1435 * Negative cache entry, we already asked.
1436 * do legacy.
1437 */
1438 return legacy_sid_to_uid(psid, puid);
1439 }
1440
1441 if (!ret || expired) {
1442 /* Not in cache. Ask winbindd. */
1443 if (!winbind_sid_to_uid(puid, psid)) {
1444 DEBUG(5, ("winbind failed to find a uid for sid %s\n",
1445 sid_string_dbg(psid)));
1446 /* winbind failed. do legacy */
1447 return legacy_sid_to_uid(psid, puid);
1448 }
1449 }
1450
1451 /* TODO: Here would be the place to allocate both a gid and a uid for
1452 * the SID in question */
1453
1454 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1455 (unsigned int)*puid ));
1456
1457 store_uid_sid_cache(psid, *puid);
1458 return true;
1459 }
1460
1461 /*****************************************************************
1462 *THE CANONICAL* convert SID to gid function.
1463 Group mapping is used for gids that maps to Wellknown SIDs
1464 *****************************************************************/
1465
1466 bool sid_to_gid(const DOM_SID *psid, gid_t *pgid)
/* [<][>][^][v][top][bottom][index][help] */
1467 {
1468 bool expired = true;
1469 bool ret;
1470 uint32 rid;
1471 uid_t uid;
1472
1473 if (fetch_gid_from_cache(pgid, psid))
1474 return true;
1475
1476 if (fetch_uid_from_cache(&uid, psid))
1477 return false;
1478
1479 /* Optimize for the Unix Groups Domain
1480 * as the conversion is straightforward */
1481 if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
1482 gid_t gid = rid;
1483 *pgid = gid;
1484
1485 /* return here, don't cache */
1486 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1487 (unsigned int)*pgid ));
1488 return true;
1489 }
1490
1491 /* Check the winbindd cache directly. */
1492 ret = idmap_cache_find_sid2gid(psid, pgid, &expired);
1493
1494 if (ret && !expired && (*pgid == (gid_t)-1)) {
1495 /*
1496 * Negative cache entry, we already asked.
1497 * do legacy.
1498 */
1499 return legacy_sid_to_gid(psid, pgid);
1500 }
1501
1502 if (!ret || expired) {
1503 /* Not in cache or negative. Ask winbindd. */
1504 /* Ask winbindd if it can map this sid to a gid.
1505 * (Idmap will check it is a valid SID and of the right type) */
1506
1507 if ( !winbind_sid_to_gid(pgid, psid) ) {
1508
1509 DEBUG(10,("winbind failed to find a gid for sid %s\n",
1510 sid_string_dbg(psid)));
1511 /* winbind failed. do legacy */
1512 return legacy_sid_to_gid(psid, pgid);
1513 }
1514 }
1515
1516 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1517 (unsigned int)*pgid ));
1518
1519 store_gid_sid_cache(psid, *pgid);
1520 return true;
1521 }