source: branches/samba-3.5.x/source3/passdb/lookup_sid.c

Last change on this file was 414, checked in by Herwig Bauernfeind, 15 years ago

Samba 3.5.0: Initial import

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