source: trunk/server/source3/passdb/lookup_sid.c

Last change on this file was 751, checked in by Silvan Scherrer, 13 years ago

Samba Server: updated trunk to 3.6.9

File size: 46.4 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#include "passdb.h"
24#include "../librpc/gen_ndr/ndr_security.h"
25#include "secrets.h"
26#include "memcache.h"
27#include "idmap_cache.h"
28#include "../libcli/security/security.h"
29#include "lib/winbind_util.h"
30
31/*****************************************************************
32 Dissect a user-provided name into domain, name, sid and type.
33
34 If an explicit domain name was given in the form domain\user, it
35 has to try that. If no explicit domain name was given, we have
36 to do guesswork.
37*****************************************************************/
38
39bool lookup_name(TALLOC_CTX *mem_ctx,
40 const char *full_name, int flags,
41 const char **ret_domain, const char **ret_name,
42 struct dom_sid *ret_sid, enum lsa_SidType *ret_type)
43{
44 char *p;
45 const char *tmp;
46 const char *domain = NULL;
47 const char *name = NULL;
48 uint32 rid;
49 struct dom_sid sid;
50 enum lsa_SidType type;
51 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
52
53 if (tmp_ctx == NULL) {
54 DEBUG(0, ("talloc_new failed\n"));
55 return false;
56 }
57
58 p = strchr_m(full_name, '\\');
59
60 if (p != NULL) {
61 domain = talloc_strndup(tmp_ctx, full_name,
62 PTR_DIFF(p, full_name));
63 name = talloc_strdup(tmp_ctx, p+1);
64 } else {
65 domain = talloc_strdup(tmp_ctx, "");
66 name = talloc_strdup(tmp_ctx, full_name);
67 }
68
69 if ((domain == NULL) || (name == NULL)) {
70 DEBUG(0, ("talloc failed\n"));
71 TALLOC_FREE(tmp_ctx);
72 return false;
73 }
74
75 DEBUG(10,("lookup_name: %s => domain=[%s], name=[%s]\n",
76 full_name, domain, name));
77 DEBUG(10, ("lookup_name: flags = 0x0%x\n", flags));
78
79 if ((flags & LOOKUP_NAME_DOMAIN) &&
80 strequal(domain, get_global_sam_name()))
81 {
82
83 /* It's our own domain, lookup the name in passdb */
84 if (lookup_global_sam_name(name, flags, &rid, &type)) {
85 sid_compose(&sid, get_global_sam_sid(), rid);
86 goto ok;
87 }
88 TALLOC_FREE(tmp_ctx);
89 return false;
90 }
91
92 if ((flags & LOOKUP_NAME_BUILTIN) &&
93 strequal(domain, builtin_domain_name()))
94 {
95 if (strlen(name) == 0) {
96 /* Swap domain and name */
97 tmp = name; name = domain; domain = tmp;
98 sid_copy(&sid, &global_sid_Builtin);
99 type = SID_NAME_DOMAIN;
100 goto ok;
101 }
102
103 /* Explicit request for a name in BUILTIN */
104 if (lookup_builtin_name(name, &rid)) {
105 sid_compose(&sid, &global_sid_Builtin, rid);
106 type = SID_NAME_ALIAS;
107 goto ok;
108 }
109 TALLOC_FREE(tmp_ctx);
110 return false;
111 }
112
113 /* Try the explicit winbind lookup first, don't let it guess the
114 * domain yet at this point yet. This comes later. */
115
116 if ((domain[0] != '\0') &&
117 (flags & ~(LOOKUP_NAME_DOMAIN|LOOKUP_NAME_ISOLATED)) &&
118 (winbind_lookup_name(domain, name, &sid, &type))) {
119 goto ok;
120 }
121
122 if (((flags & LOOKUP_NAME_NO_NSS) == 0)
123 && strequal(domain, unix_users_domain_name())) {
124 if (lookup_unix_user_name(name, &sid)) {
125 type = SID_NAME_USER;
126 goto ok;
127 }
128 TALLOC_FREE(tmp_ctx);
129 return false;
130 }
131
132 if (((flags & LOOKUP_NAME_NO_NSS) == 0)
133 && strequal(domain, unix_groups_domain_name())) {
134 if (lookup_unix_group_name(name, &sid)) {
135 type = SID_NAME_DOM_GRP;
136 goto ok;
137 }
138 TALLOC_FREE(tmp_ctx);
139 return false;
140 }
141
142 if ((domain[0] == '\0') && (!(flags & LOOKUP_NAME_ISOLATED))) {
143 TALLOC_FREE(tmp_ctx);
144 return false;
145 }
146
147 /* Now the guesswork begins, we haven't been given an explicit
148 * domain. Try the sequence as documented on
149 * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
150 * November 27, 2005 */
151
152 /* 1. well-known names */
153
154 if ((flags & LOOKUP_NAME_WKN) &&
155 lookup_wellknown_name(tmp_ctx, name, &sid, &domain))
156 {
157 type = SID_NAME_WKN_GRP;
158 goto ok;
159 }
160
161 /* 2. Builtin domain as such */
162
163 if ((flags & (LOOKUP_NAME_BUILTIN|LOOKUP_NAME_REMOTE)) &&
164 strequal(name, builtin_domain_name()))
165 {
166 /* Swap domain and name */
167 tmp = name; name = domain; domain = tmp;
168 sid_copy(&sid, &global_sid_Builtin);
169 type = SID_NAME_DOMAIN;
170 goto ok;
171 }
172
173 /* 3. Account domain */
174
175 if ((flags & LOOKUP_NAME_DOMAIN) &&
176 strequal(name, get_global_sam_name()))
177 {
178 if (!secrets_fetch_domain_sid(name, &sid)) {
179 DEBUG(3, ("Could not fetch my SID\n"));
180 TALLOC_FREE(tmp_ctx);
181 return false;
182 }
183 /* Swap domain and name */
184 tmp = name; name = domain; domain = tmp;
185 type = SID_NAME_DOMAIN;
186 goto ok;
187 }
188
189 /* 4. Primary domain */
190
191 if ((flags & LOOKUP_NAME_DOMAIN) && !IS_DC &&
192 strequal(name, lp_workgroup()))
193 {
194 if (!secrets_fetch_domain_sid(name, &sid)) {
195 DEBUG(3, ("Could not fetch the domain SID\n"));
196 TALLOC_FREE(tmp_ctx);
197 return false;
198 }
199 /* Swap domain and name */
200 tmp = name; name = domain; domain = tmp;
201 type = SID_NAME_DOMAIN;
202 goto ok;
203 }
204
205 /* 5. Trusted domains as such, to me it looks as if members don't do
206 this, tested an XP workstation in a NT domain -- vl */
207
208 if ((flags & LOOKUP_NAME_REMOTE) && IS_DC &&
209 (pdb_get_trusteddom_pw(name, NULL, &sid, NULL)))
210 {
211 /* Swap domain and name */
212 tmp = name; name = domain; domain = tmp;
213 type = SID_NAME_DOMAIN;
214 goto ok;
215 }
216
217 /* 6. Builtin aliases */
218
219 if ((flags & LOOKUP_NAME_BUILTIN) &&
220 lookup_builtin_name(name, &rid))
221 {
222 domain = talloc_strdup(tmp_ctx, builtin_domain_name());
223 sid_compose(&sid, &global_sid_Builtin, rid);
224 type = SID_NAME_ALIAS;
225 goto ok;
226 }
227
228 /* 7. Local systems' SAM (DCs don't have a local SAM) */
229 /* 8. Primary SAM (On members, this is the domain) */
230
231 /* Both cases are done by looking at our passdb */
232
233 if ((flags & LOOKUP_NAME_DOMAIN) &&
234 lookup_global_sam_name(name, flags, &rid, &type))
235 {
236 domain = talloc_strdup(tmp_ctx, get_global_sam_name());
237 sid_compose(&sid, get_global_sam_sid(), rid);
238 goto ok;
239 }
240
241 /* Now our local possibilities are exhausted. */
242
243 if (!(flags & LOOKUP_NAME_REMOTE)) {
244 TALLOC_FREE(tmp_ctx);
245 return false;
246 }
247
248 /* If we are not a DC, we have to ask in our primary domain. Let
249 * winbind do that. */
250
251 if (!IS_DC &&
252 (winbind_lookup_name(lp_workgroup(), name, &sid, &type))) {
253 domain = talloc_strdup(tmp_ctx, lp_workgroup());
254 goto ok;
255 }
256
257 /* 9. Trusted domains */
258
259 /* If we're a DC we have to ask all trusted DC's. Winbind does not do
260 * that (yet), but give it a chance. */
261
262 if (IS_DC && winbind_lookup_name("", name, &sid, &type)) {
263 struct dom_sid dom_sid;
264 enum lsa_SidType domain_type;
265
266 if (type == SID_NAME_DOMAIN) {
267 /* Swap name and type */
268 tmp = name; name = domain; domain = tmp;
269 goto ok;
270 }
271
272 /* Here we have to cope with a little deficiency in the
273 * winbind API: We have to ask it again for the name of the
274 * domain it figured out itself. Maybe fix that later... */
275
276 sid_copy(&dom_sid, &sid);
277 sid_split_rid(&dom_sid, NULL);
278
279 if (!winbind_lookup_sid(tmp_ctx, &dom_sid, &domain, NULL,
280 &domain_type) ||
281 (domain_type != SID_NAME_DOMAIN)) {
282 DEBUG(2, ("winbind could not find the domain's name "
283 "it just looked up for us\n"));
284 TALLOC_FREE(tmp_ctx);
285 return false;
286 }
287 goto ok;
288 }
289
290 /* 10. Don't translate */
291
292 /* 11. Ok, windows would end here. Samba has two more options:
293 Unmapped users and unmapped groups */
294
295 if (((flags & LOOKUP_NAME_NO_NSS) == 0)
296 && lookup_unix_user_name(name, &sid)) {
297 domain = talloc_strdup(tmp_ctx, unix_users_domain_name());
298 type = SID_NAME_USER;
299 goto ok;
300 }
301
302 if (((flags & LOOKUP_NAME_NO_NSS) == 0)
303 && lookup_unix_group_name(name, &sid)) {
304 domain = talloc_strdup(tmp_ctx, unix_groups_domain_name());
305 type = SID_NAME_DOM_GRP;
306 goto ok;
307 }
308
309 /*
310 * Ok, all possibilities tried. Fail.
311 */
312
313 TALLOC_FREE(tmp_ctx);
314 return false;
315
316 ok:
317 if ((domain == NULL) || (name == NULL)) {
318 DEBUG(0, ("talloc failed\n"));
319 TALLOC_FREE(tmp_ctx);
320 return false;
321 }
322
323 /*
324 * Hand over the results to the talloc context we've been given.
325 */
326
327 if ((ret_name != NULL) &&
328 !(*ret_name = talloc_strdup(mem_ctx, name))) {
329 DEBUG(0, ("talloc failed\n"));
330 TALLOC_FREE(tmp_ctx);
331 return false;
332 }
333
334 if (ret_domain != NULL) {
335 char *tmp_dom;
336 if (!(tmp_dom = talloc_strdup(mem_ctx, domain))) {
337 DEBUG(0, ("talloc failed\n"));
338 TALLOC_FREE(tmp_ctx);
339 return false;
340 }
341 strupper_m(tmp_dom);
342 *ret_domain = tmp_dom;
343 }
344
345 if (ret_sid != NULL) {
346 sid_copy(ret_sid, &sid);
347 }
348
349 if (ret_type != NULL) {
350 *ret_type = type;
351 }
352
353 TALLOC_FREE(tmp_ctx);
354 return true;
355}
356
357/************************************************************************
358 Names from smb.conf can be unqualified. eg. valid users = foo
359 These names should never map to a remote name. Try global_sam_name()\foo,
360 and then "Unix Users"\foo (or "Unix Groups"\foo).
361************************************************************************/
362
363bool lookup_name_smbconf(TALLOC_CTX *mem_ctx,
364 const char *full_name, int flags,
365 const char **ret_domain, const char **ret_name,
366 struct dom_sid *ret_sid, enum lsa_SidType *ret_type)
367{
368 char *qualified_name;
369 const char *p;
370
371 /* NB. No winbindd_separator here as lookup_name needs \\' */
372 if ((p = strchr_m(full_name, *lp_winbind_separator())) != NULL) {
373
374 /* The name is already qualified with a domain. */
375
376 if (*lp_winbind_separator() != '\\') {
377 char *tmp;
378
379 /* lookup_name() needs '\\' as a separator */
380
381 tmp = talloc_strdup(mem_ctx, full_name);
382 if (!tmp) {
383 return false;
384 }
385 tmp[p - full_name] = '\\';
386 full_name = tmp;
387 }
388
389 return lookup_name(mem_ctx, full_name, flags,
390 ret_domain, ret_name,
391 ret_sid, ret_type);
392 }
393
394 /* Try with our own SAM name. */
395 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
396 get_global_sam_name(),
397 full_name );
398 if (!qualified_name) {
399 return false;
400 }
401
402 if (lookup_name(mem_ctx, qualified_name, flags,
403 ret_domain, ret_name,
404 ret_sid, ret_type)) {
405 return true;
406 }
407
408 /* Finally try with "Unix Users" or "Unix Group" */
409 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
410 flags & LOOKUP_NAME_GROUP ?
411 unix_groups_domain_name() :
412 unix_users_domain_name(),
413 full_name );
414 if (!qualified_name) {
415 return false;
416 }
417
418 return lookup_name(mem_ctx, qualified_name, flags,
419 ret_domain, ret_name,
420 ret_sid, ret_type);
421}
422
423static bool wb_lookup_rids(TALLOC_CTX *mem_ctx,
424 const struct dom_sid *domain_sid,
425 int num_rids, uint32 *rids,
426 const char **domain_name,
427 const char **names, enum lsa_SidType *types)
428{
429 int i;
430 const char **my_names;
431 enum lsa_SidType *my_types;
432 TALLOC_CTX *tmp_ctx;
433
434 if (!(tmp_ctx = talloc_init("wb_lookup_rids"))) {
435 return false;
436 }
437
438 if (!winbind_lookup_rids(tmp_ctx, domain_sid, num_rids, rids,
439 domain_name, &my_names, &my_types)) {
440 *domain_name = "";
441 for (i=0; i<num_rids; i++) {
442 names[i] = "";
443 types[i] = SID_NAME_UNKNOWN;
444 }
445 TALLOC_FREE(tmp_ctx);
446 return true;
447 }
448
449 if (!(*domain_name = talloc_strdup(mem_ctx, *domain_name))) {
450 TALLOC_FREE(tmp_ctx);
451 return false;
452 }
453
454 /*
455 * winbind_lookup_rids allocates its own array. We've been given the
456 * array, so copy it over
457 */
458
459 for (i=0; i<num_rids; i++) {
460 if (my_names[i] == NULL) {
461 TALLOC_FREE(tmp_ctx);
462 return false;
463 }
464 if (!(names[i] = talloc_strdup(names, my_names[i]))) {
465 TALLOC_FREE(tmp_ctx);
466 return false;
467 }
468 types[i] = my_types[i];
469 }
470 TALLOC_FREE(tmp_ctx);
471 return true;
472}
473
474static bool lookup_rids(TALLOC_CTX *mem_ctx, const struct dom_sid *domain_sid,
475 int num_rids, uint32_t *rids,
476 const char **domain_name,
477 const char ***names, enum lsa_SidType **types)
478{
479 int i;
480
481 DEBUG(10, ("lookup_rids called for domain sid '%s'\n",
482 sid_string_dbg(domain_sid)));
483
484 if (num_rids) {
485 *names = TALLOC_ZERO_ARRAY(mem_ctx, const char *, num_rids);
486 *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
487
488 if ((*names == NULL) || (*types == NULL)) {
489 return false;
490 }
491
492 for (i = 0; i < num_rids; i++)
493 (*types)[i] = SID_NAME_UNKNOWN;
494 } else {
495 *names = NULL;
496 *types = NULL;
497 }
498
499 if (sid_check_is_domain(domain_sid)) {
500 NTSTATUS result;
501
502 if (*domain_name == NULL) {
503 *domain_name = talloc_strdup(
504 mem_ctx, get_global_sam_name());
505 }
506
507 if (*domain_name == NULL) {
508 return false;
509 }
510
511 become_root();
512 result = pdb_lookup_rids(domain_sid, num_rids, rids,
513 *names, *types);
514 unbecome_root();
515
516 return (NT_STATUS_IS_OK(result) ||
517 NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
518 NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
519 }
520
521 if (sid_check_is_builtin(domain_sid)) {
522
523 if (*domain_name == NULL) {
524 *domain_name = talloc_strdup(
525 mem_ctx, builtin_domain_name());
526 }
527
528 if (*domain_name == NULL) {
529 return false;
530 }
531
532 for (i=0; i<num_rids; i++) {
533 if (lookup_builtin_rid(*names, rids[i],
534 &(*names)[i])) {
535 if ((*names)[i] == NULL) {
536 return false;
537 }
538 (*types)[i] = SID_NAME_ALIAS;
539 } else {
540 (*types)[i] = SID_NAME_UNKNOWN;
541 }
542 }
543 return true;
544 }
545
546 if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
547 for (i=0; i<num_rids; i++) {
548 struct dom_sid sid;
549 sid_compose(&sid, domain_sid, rids[i]);
550 if (lookup_wellknown_sid(mem_ctx, &sid,
551 domain_name, &(*names)[i])) {
552 if ((*names)[i] == NULL) {
553 return false;
554 }
555 (*types)[i] = SID_NAME_WKN_GRP;
556 } else {
557 (*types)[i] = SID_NAME_UNKNOWN;
558 }
559 }
560 return true;
561 }
562
563 if (sid_check_is_unix_users(domain_sid)) {
564 if (*domain_name == NULL) {
565 *domain_name = talloc_strdup(
566 mem_ctx, unix_users_domain_name());
567 if (*domain_name == NULL) {
568 return false;
569 }
570 }
571 for (i=0; i<num_rids; i++) {
572 (*names)[i] = talloc_strdup(
573 (*names), uidtoname(rids[i]));
574 if ((*names)[i] == NULL) {
575 return false;
576 }
577 (*types)[i] = SID_NAME_USER;
578 }
579 return true;
580 }
581
582 if (sid_check_is_unix_groups(domain_sid)) {
583 if (*domain_name == NULL) {
584 *domain_name = talloc_strdup(
585 mem_ctx, unix_groups_domain_name());
586 if (*domain_name == NULL) {
587 return false;
588 }
589 }
590 for (i=0; i<num_rids; i++) {
591 (*names)[i] = talloc_strdup(
592 (*names), gidtoname(rids[i]));
593 if ((*names)[i] == NULL) {
594 return false;
595 }
596 (*types)[i] = SID_NAME_DOM_GRP;
597 }
598 return true;
599 }
600
601 return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
602 domain_name, *names, *types);
603}
604
605/*
606 * Is the SID a domain as such? If yes, lookup its name.
607 */
608
609static bool lookup_as_domain(const struct dom_sid *sid, TALLOC_CTX *mem_ctx,
610 const char **name)
611{
612 const char *tmp;
613 enum lsa_SidType type;
614
615 if (sid_check_is_domain(sid)) {
616 *name = talloc_strdup(mem_ctx, get_global_sam_name());
617 return true;
618 }
619
620 if (sid_check_is_builtin(sid)) {
621 *name = talloc_strdup(mem_ctx, builtin_domain_name());
622 return true;
623 }
624
625 if (sid_check_is_wellknown_domain(sid, &tmp)) {
626 *name = talloc_strdup(mem_ctx, tmp);
627 return true;
628 }
629
630 if (sid_check_is_unix_users(sid)) {
631 *name = talloc_strdup(mem_ctx, unix_users_domain_name());
632 return true;
633 }
634
635 if (sid_check_is_unix_groups(sid)) {
636 *name = talloc_strdup(mem_ctx, unix_groups_domain_name());
637 return true;
638 }
639
640 if (sid->num_auths != 4) {
641 /* This can't be a domain */
642 return false;
643 }
644
645 if (IS_DC) {
646 uint32 i, num_domains;
647 struct trustdom_info **domains;
648
649 /* This is relatively expensive, but it happens only on DCs
650 * and for SIDs that have 4 sub-authorities and thus look like
651 * domains */
652
653 if (!NT_STATUS_IS_OK(pdb_enum_trusteddoms(mem_ctx,
654 &num_domains,
655 &domains))) {
656 return false;
657 }
658
659 for (i=0; i<num_domains; i++) {
660 if (dom_sid_equal(sid, &domains[i]->sid)) {
661 *name = talloc_strdup(mem_ctx,
662 domains[i]->name);
663 return true;
664 }
665 }
666 return false;
667 }
668
669 if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
670 (type == SID_NAME_DOMAIN)) {
671 *name = tmp;
672 return true;
673 }
674
675 return false;
676}
677
678/*
679 * This tries to implement the rather weird rules for the lsa_lookup level
680 * parameter.
681 *
682 * This is as close as we can get to what W2k3 does. With this we survive the
683 * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
684 * different, but I assume that's just being too liberal. For example, W2k3
685 * replies to everything else but the levels 1-6 with INVALID_PARAMETER
686 * whereas NT4 does the same as level 1 (I think). I did not fully test that
687 * with NT4, this is what w2k3 does.
688 *
689 * Level 1: Ask everywhere
690 * Level 2: Ask domain and trusted domains, no builtin and wkn
691 * Level 3: Only ask domain
692 * Level 4: W2k3ad: Only ask AD trusts
693 * Level 5: Only ask transitive forest trusts
694 * Level 6: Like 4
695 */
696
697static bool check_dom_sid_to_level(const struct dom_sid *sid, int level)
698{
699 int ret = false;
700
701 switch(level) {
702 case 1:
703 ret = true;
704 break;
705 case 2:
706 ret = (!sid_check_is_builtin(sid) &&
707 !sid_check_is_wellknown_domain(sid, NULL));
708 break;
709 case 3:
710 case 4:
711 case 6:
712 ret = sid_check_is_domain(sid);
713 break;
714 case 5:
715 ret = false;
716 break;
717 }
718
719 DEBUG(10, ("%s SID %s in level %d\n",
720 ret ? "Accepting" : "Rejecting",
721 sid_string_dbg(sid), level));
722 return ret;
723}
724
725/*
726 * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
727 * references to domains, it is explicitly made for this.
728 *
729 * This attempts to be as efficient as possible: It collects all SIDs
730 * belonging to a domain and hands them in bulk to the appropriate lookup
731 * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
732 * *hugely* from this.
733 */
734
735NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
736 const struct dom_sid **sids, int level,
737 struct lsa_dom_info **ret_domains,
738 struct lsa_name_info **ret_names)
739{
740 TALLOC_CTX *tmp_ctx;
741 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
742 struct lsa_name_info *name_infos;
743 struct lsa_dom_info *dom_infos = NULL;
744
745 int i, j;
746
747 if (!(tmp_ctx = talloc_new(mem_ctx))) {
748 DEBUG(0, ("talloc_new failed\n"));
749 return NT_STATUS_NO_MEMORY;
750 }
751
752 if (num_sids) {
753 name_infos = TALLOC_ARRAY(mem_ctx, struct lsa_name_info, num_sids);
754 if (name_infos == NULL) {
755 result = NT_STATUS_NO_MEMORY;
756 goto fail;
757 }
758 } else {
759 name_infos = NULL;
760 }
761
762 dom_infos = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_dom_info,
763 LSA_REF_DOMAIN_LIST_MULTIPLIER);
764 if (dom_infos == NULL) {
765 result = NT_STATUS_NO_MEMORY;
766 goto fail;
767 }
768
769 /* First build up the data structures:
770 *
771 * dom_infos is a list of domains referenced in the list of
772 * SIDs. Later we will walk the list of domains and look up the RIDs
773 * in bulk.
774 *
775 * name_infos is a shadow-copy of the SIDs array to collect the real
776 * data.
777 *
778 * dom_info->idxs is an index into the name_infos array. The
779 * difficulty we have here is that we need to keep the SIDs the client
780 * asked for in the same order for the reply
781 */
782
783 for (i=0; i<num_sids; i++) {
784 struct dom_sid sid;
785 uint32_t rid = 0;
786 const char *domain_name = NULL;
787
788 sid_copy(&sid, sids[i]);
789 name_infos[i].type = SID_NAME_USE_NONE;
790
791 if (lookup_as_domain(&sid, name_infos, &domain_name)) {
792 /* We can't push that through the normal lookup
793 * process, as this would reference illegal
794 * domains.
795 *
796 * For example S-1-5-32 would end up referencing
797 * domain S-1-5- with RID 32 which is clearly wrong.
798 */
799 if (domain_name == NULL) {
800 result = NT_STATUS_NO_MEMORY;
801 goto fail;
802 }
803
804 name_infos[i].rid = 0;
805 name_infos[i].type = SID_NAME_DOMAIN;
806 name_infos[i].name = NULL;
807
808 if (sid_check_is_builtin(&sid)) {
809 /* Yes, W2k3 returns "BUILTIN" both as domain
810 * and name here */
811 name_infos[i].name = talloc_strdup(
812 name_infos, builtin_domain_name());
813 if (name_infos[i].name == NULL) {
814 result = NT_STATUS_NO_MEMORY;
815 goto fail;
816 }
817 }
818 } else {
819 /* This is a normal SID with rid component */
820 if (!sid_split_rid(&sid, &rid)) {
821 result = NT_STATUS_INVALID_SID;
822 goto fail;
823 }
824 }
825
826 if (!check_dom_sid_to_level(&sid, level)) {
827 name_infos[i].rid = 0;
828 name_infos[i].type = SID_NAME_UNKNOWN;
829 name_infos[i].name = NULL;
830 continue;
831 }
832
833 for (j=0; j<LSA_REF_DOMAIN_LIST_MULTIPLIER; j++) {
834 if (!dom_infos[j].valid) {
835 break;
836 }
837 if (dom_sid_equal(&sid, &dom_infos[j].sid)) {
838 break;
839 }
840 }
841
842 if (j == LSA_REF_DOMAIN_LIST_MULTIPLIER) {
843 /* TODO: What's the right error message here? */
844 result = NT_STATUS_NONE_MAPPED;
845 goto fail;
846 }
847
848 if (!dom_infos[j].valid) {
849 /* We found a domain not yet referenced, create a new
850 * ref. */
851 dom_infos[j].valid = true;
852 sid_copy(&dom_infos[j].sid, &sid);
853
854 if (domain_name != NULL) {
855 /* This name was being found above in the case
856 * when we found a domain SID */
857 dom_infos[j].name =
858 talloc_strdup(dom_infos, domain_name);
859 if (dom_infos[j].name == NULL) {
860 result = NT_STATUS_NO_MEMORY;
861 goto fail;
862 }
863 } else {
864 /* lookup_rids will take care of this */
865 dom_infos[j].name = NULL;
866 }
867 }
868
869 name_infos[i].dom_idx = j;
870
871 if (name_infos[i].type == SID_NAME_USE_NONE) {
872 name_infos[i].rid = rid;
873
874 ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
875 &dom_infos[j].num_idxs);
876
877 if (dom_infos[j].idxs == NULL) {
878 result = NT_STATUS_NO_MEMORY;
879 goto fail;
880 }
881 }
882 }
883
884 /* Iterate over the domains found */
885
886 for (i=0; i<LSA_REF_DOMAIN_LIST_MULTIPLIER; i++) {
887 uint32_t *rids;
888 const char *domain_name = NULL;
889 const char **names;
890 enum lsa_SidType *types;
891 struct lsa_dom_info *dom = &dom_infos[i];
892
893 if (!dom->valid) {
894 /* No domains left, we're done */
895 break;
896 }
897
898 if (dom->num_idxs) {
899 if (!(rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs))) {
900 result = NT_STATUS_NO_MEMORY;
901 goto fail;
902 }
903 } else {
904 rids = NULL;
905 }
906
907 for (j=0; j<dom->num_idxs; j++) {
908 rids[j] = name_infos[dom->idxs[j]].rid;
909 }
910
911 if (!lookup_rids(tmp_ctx, &dom->sid,
912 dom->num_idxs, rids, &domain_name,
913 &names, &types)) {
914 result = NT_STATUS_NO_MEMORY;
915 goto fail;
916 }
917
918 if (!(dom->name = talloc_strdup(dom_infos, domain_name))) {
919 result = NT_STATUS_NO_MEMORY;
920 goto fail;
921 }
922
923 for (j=0; j<dom->num_idxs; j++) {
924 int idx = dom->idxs[j];
925 name_infos[idx].type = types[j];
926 if (types[j] != SID_NAME_UNKNOWN) {
927 name_infos[idx].name =
928 talloc_strdup(name_infos, names[j]);
929 if (name_infos[idx].name == NULL) {
930 result = NT_STATUS_NO_MEMORY;
931 goto fail;
932 }
933 } else {
934 name_infos[idx].name = NULL;
935 }
936 }
937 }
938
939 *ret_domains = dom_infos;
940 *ret_names = name_infos;
941 TALLOC_FREE(tmp_ctx);
942 return NT_STATUS_OK;
943
944 fail:
945 TALLOC_FREE(dom_infos);
946 TALLOC_FREE(name_infos);
947 TALLOC_FREE(tmp_ctx);
948 return result;
949}
950
951/*****************************************************************
952 *THE CANONICAL* convert SID to name function.
953*****************************************************************/
954
955bool lookup_sid(TALLOC_CTX *mem_ctx, const struct dom_sid *sid,
956 const char **ret_domain, const char **ret_name,
957 enum lsa_SidType *ret_type)
958{
959 struct lsa_dom_info *domain;
960 struct lsa_name_info *name;
961 TALLOC_CTX *tmp_ctx;
962 bool ret = false;
963
964 DEBUG(10, ("lookup_sid called for SID '%s'\n", sid_string_dbg(sid)));
965
966 if (!(tmp_ctx = talloc_new(mem_ctx))) {
967 DEBUG(0, ("talloc_new failed\n"));
968 return false;
969 }
970
971 if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
972 &domain, &name))) {
973 goto done;
974 }
975
976 if (name->type == SID_NAME_UNKNOWN) {
977 goto done;
978 }
979
980 if ((ret_domain != NULL) &&
981 !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
982 goto done;
983 }
984
985 if ((ret_name != NULL) &&
986 !(*ret_name = talloc_strdup(mem_ctx, name->name))) {
987 goto done;
988 }
989
990 if (ret_type != NULL) {
991 *ret_type = name->type;
992 }
993
994 ret = true;
995
996 done:
997 if (ret) {
998 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n", sid_string_dbg(sid),
999 domain->name, name->name, name->type));
1000 } else {
1001 DEBUG(10, ("failed to lookup sid %s\n", sid_string_dbg(sid)));
1002 }
1003 TALLOC_FREE(tmp_ctx);
1004 return ret;
1005}
1006
1007/*****************************************************************
1008 Id mapping cache. This is to avoid Winbind mappings already
1009 seen by smbd to be queried too frequently, keeping winbindd
1010 busy, and blocking smbd while winbindd is busy with other
1011 stuff. Written by Michael Steffens <michael.steffens@hp.com>,
1012 modified to use linked lists by jra.
1013*****************************************************************/
1014
1015/*****************************************************************
1016 Find a SID given a uid.
1017*****************************************************************/
1018
1019static bool fetch_sid_from_uid_cache(struct dom_sid *psid, uid_t uid)
1020{
1021 DATA_BLOB cache_value;
1022
1023 if (!memcache_lookup(NULL, UID_SID_CACHE,
1024 data_blob_const(&uid, sizeof(uid)),
1025 &cache_value)) {
1026 return false;
1027 }
1028
1029 memcpy(psid, cache_value.data, MIN(sizeof(*psid), cache_value.length));
1030 SMB_ASSERT(cache_value.length >= offsetof(struct dom_sid, id_auth));
1031 SMB_ASSERT(cache_value.length == ndr_size_dom_sid(psid, 0));
1032
1033 return true;
1034}
1035
1036/*****************************************************************
1037 Find a uid given a SID.
1038*****************************************************************/
1039
1040static bool fetch_uid_from_cache( uid_t *puid, const struct dom_sid *psid )
1041{
1042 DATA_BLOB cache_value;
1043
1044 if (!memcache_lookup(NULL, SID_UID_CACHE,
1045 data_blob_const(psid, ndr_size_dom_sid(psid, 0)),
1046 &cache_value)) {
1047 return false;
1048 }
1049
1050 SMB_ASSERT(cache_value.length == sizeof(*puid));
1051 memcpy(puid, cache_value.data, sizeof(*puid));
1052
1053 return true;
1054}
1055
1056/*****************************************************************
1057 Store uid to SID mapping in cache.
1058*****************************************************************/
1059
1060void store_uid_sid_cache(const struct dom_sid *psid, uid_t uid)
1061{
1062 memcache_add(NULL, SID_UID_CACHE,
1063 data_blob_const(psid, ndr_size_dom_sid(psid, 0)),
1064 data_blob_const(&uid, sizeof(uid)));
1065 memcache_add(NULL, UID_SID_CACHE,
1066 data_blob_const(&uid, sizeof(uid)),
1067 data_blob_const(psid, ndr_size_dom_sid(psid, 0)));
1068}
1069
1070/*****************************************************************
1071 Find a SID given a gid.
1072*****************************************************************/
1073
1074static bool fetch_sid_from_gid_cache(struct dom_sid *psid, gid_t gid)
1075{
1076 DATA_BLOB cache_value;
1077
1078 if (!memcache_lookup(NULL, GID_SID_CACHE,
1079 data_blob_const(&gid, sizeof(gid)),
1080 &cache_value)) {
1081 return false;
1082 }
1083
1084 memcpy(psid, cache_value.data, MIN(sizeof(*psid), cache_value.length));
1085 SMB_ASSERT(cache_value.length >= offsetof(struct dom_sid, id_auth));
1086 SMB_ASSERT(cache_value.length == ndr_size_dom_sid(psid, 0));
1087
1088 return true;
1089}
1090
1091/*****************************************************************
1092 Find a gid given a SID.
1093*****************************************************************/
1094
1095static bool fetch_gid_from_cache(gid_t *pgid, const struct dom_sid *psid)
1096{
1097 DATA_BLOB cache_value;
1098
1099 if (!memcache_lookup(NULL, SID_GID_CACHE,
1100 data_blob_const(psid, ndr_size_dom_sid(psid, 0)),
1101 &cache_value)) {
1102 return false;
1103 }
1104
1105 SMB_ASSERT(cache_value.length == sizeof(*pgid));
1106 memcpy(pgid, cache_value.data, sizeof(*pgid));
1107
1108 return true;
1109}
1110
1111/*****************************************************************
1112 Store gid to SID mapping in cache.
1113*****************************************************************/
1114
1115void store_gid_sid_cache(const struct dom_sid *psid, gid_t gid)
1116{
1117 memcache_add(NULL, SID_GID_CACHE,
1118 data_blob_const(psid, ndr_size_dom_sid(psid, 0)),
1119 data_blob_const(&gid, sizeof(gid)));
1120 memcache_add(NULL, GID_SID_CACHE,
1121 data_blob_const(&gid, sizeof(gid)),
1122 data_blob_const(psid, ndr_size_dom_sid(psid, 0)));
1123}
1124
1125/*****************************************************************
1126 *THE LEGACY* convert uid_t to SID function.
1127*****************************************************************/
1128
1129static void legacy_uid_to_sid(struct dom_sid *psid, uid_t uid)
1130{
1131 bool ret;
1132
1133 ZERO_STRUCTP(psid);
1134
1135 become_root();
1136 ret = pdb_uid_to_sid(uid, psid);
1137 unbecome_root();
1138
1139 if (ret) {
1140 /* This is a mapped user */
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
1160static void legacy_gid_to_sid(struct dom_sid *psid, gid_t gid)
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
1191static bool legacy_sid_to_uid(const struct dom_sid *psid, uid_t *puid)
1192{
1193 enum lsa_SidType type;
1194
1195 if (sid_check_is_in_our_domain(psid)) {
1196 union unid_t id;
1197 bool ret;
1198
1199 become_root();
1200 ret = pdb_sid_to_id(psid, &id, &type);
1201 unbecome_root();
1202
1203 if (ret) {
1204 if (type != SID_NAME_USER) {
1205 DEBUG(5, ("sid %s is a %s, expected a user\n",
1206 sid_string_dbg(psid),
1207 sid_type_lookup(type)));
1208 return false;
1209 }
1210 *puid = id.uid;
1211 goto done;
1212 }
1213
1214 /* This was ours, but it was not mapped. Fail */
1215 }
1216
1217 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1218 sid_string_dbg(psid)));
1219 return false;
1220
1221done:
1222 DEBUG(10,("LEGACY: sid %s -> uid %u\n", sid_string_dbg(psid),
1223 (unsigned int)*puid ));
1224
1225 store_uid_sid_cache(psid, *puid);
1226 return true;
1227}
1228
1229/*****************************************************************
1230 *THE LEGACY* convert SID to gid function.
1231 Group mapping is used for gids that maps to Wellknown SIDs
1232*****************************************************************/
1233
1234static bool legacy_sid_to_gid(const struct dom_sid *psid, gid_t *pgid)
1235{
1236 GROUP_MAP map;
1237 union unid_t id;
1238 enum lsa_SidType type;
1239
1240 if ((sid_check_is_in_builtin(psid) ||
1241 sid_check_is_in_wellknown_domain(psid))) {
1242 bool ret;
1243
1244 become_root();
1245 ret = pdb_getgrsid(&map, *psid);
1246 unbecome_root();
1247
1248 if (ret) {
1249 *pgid = map.gid;
1250 goto done;
1251 }
1252 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1253 sid_string_dbg(psid)));
1254 return false;
1255 }
1256
1257 if (sid_check_is_in_our_domain(psid)) {
1258 bool ret;
1259
1260 become_root();
1261 ret = pdb_sid_to_id(psid, &id, &type);
1262 unbecome_root();
1263
1264 if (ret) {
1265 if ((type != SID_NAME_DOM_GRP) &&
1266 (type != SID_NAME_ALIAS)) {
1267 DEBUG(5, ("LEGACY: sid %s is a %s, expected "
1268 "a group\n", sid_string_dbg(psid),
1269 sid_type_lookup(type)));
1270 return false;
1271 }
1272 *pgid = id.gid;
1273 goto done;
1274 }
1275
1276 /* This was ours, but it was not mapped. Fail */
1277 }
1278
1279 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1280 sid_string_dbg(psid)));
1281 return false;
1282
1283 done:
1284 DEBUG(10,("LEGACY: sid %s -> gid %u\n", sid_string_dbg(psid),
1285 (unsigned int)*pgid ));
1286
1287 store_gid_sid_cache(psid, *pgid);
1288
1289 return true;
1290}
1291
1292/*****************************************************************
1293 *THE CANONICAL* convert uid_t to SID function.
1294*****************************************************************/
1295
1296void uid_to_sid(struct dom_sid *psid, uid_t uid)
1297{
1298 bool expired = true;
1299 bool ret;
1300 ZERO_STRUCTP(psid);
1301
1302 if (fetch_sid_from_uid_cache(psid, uid))
1303 return;
1304
1305 /* Check the winbindd cache directly. */
1306 ret = idmap_cache_find_uid2sid(uid, psid, &expired);
1307
1308 if (ret && !expired && is_null_sid(psid)) {
1309 /*
1310 * Negative cache entry, we already asked.
1311 * do legacy.
1312 */
1313 legacy_uid_to_sid(psid, uid);
1314 return;
1315 }
1316
1317 if (!ret || expired) {
1318 /* Not in cache. Ask winbindd. */
1319 if (!winbind_uid_to_sid(psid, uid)) {
1320 /*
1321 * We shouldn't return the NULL SID
1322 * here if winbind was running and
1323 * couldn't map, as winbind will have
1324 * added a negative entry that will
1325 * cause us to go though the
1326 * legacy_uid_to_sid()
1327 * function anyway in the case above
1328 * the next time we ask.
1329 */
1330 DEBUG(5, ("uid_to_sid: winbind failed to find a sid "
1331 "for uid %u\n", (unsigned int)uid));
1332
1333 legacy_uid_to_sid(psid, uid);
1334 return;
1335 }
1336 }
1337
1338 DEBUG(10,("uid %u -> sid %s\n", (unsigned int)uid,
1339 sid_string_dbg(psid)));
1340
1341 store_uid_sid_cache(psid, uid);
1342 return;
1343}
1344
1345/*****************************************************************
1346 *THE CANONICAL* convert gid_t to SID function.
1347*****************************************************************/
1348
1349void gid_to_sid(struct dom_sid *psid, gid_t gid)
1350{
1351 bool expired = true;
1352 bool ret;
1353 ZERO_STRUCTP(psid);
1354
1355 if (fetch_sid_from_gid_cache(psid, gid))
1356 return;
1357
1358 /* Check the winbindd cache directly. */
1359 ret = idmap_cache_find_gid2sid(gid, psid, &expired);
1360
1361 if (ret && !expired && is_null_sid(psid)) {
1362 /*
1363 * Negative cache entry, we already asked.
1364 * do legacy.
1365 */
1366 legacy_gid_to_sid(psid, gid);
1367 return;
1368 }
1369
1370 if (!ret || expired) {
1371 /* Not in cache. Ask winbindd. */
1372 if (!winbind_gid_to_sid(psid, gid)) {
1373 /*
1374 * We shouldn't return the NULL SID
1375 * here if winbind was running and
1376 * couldn't map, as winbind will have
1377 * added a negative entry that will
1378 * cause us to go though the
1379 * legacy_gid_to_sid()
1380 * function anyway in the case above
1381 * the next time we ask.
1382 */
1383 DEBUG(5, ("gid_to_sid: winbind failed to find a sid "
1384 "for gid %u\n", (unsigned int)gid));
1385
1386 legacy_gid_to_sid(psid, gid);
1387 return;
1388 }
1389 }
1390
1391 DEBUG(10,("gid %u -> sid %s\n", (unsigned int)gid,
1392 sid_string_dbg(psid)));
1393
1394 store_gid_sid_cache(psid, gid);
1395 return;
1396}
1397
1398bool sids_to_unix_ids(const struct dom_sid *sids, uint32_t num_sids,
1399 struct wbcUnixId *ids)
1400{
1401 struct wbcDomainSid *wbc_sids = NULL;
1402 struct wbcUnixId *wbc_ids = NULL;
1403 uint32_t i, num_not_cached;
1404 wbcErr err;
1405 bool ret = false;
1406
1407 wbc_sids = TALLOC_ARRAY(talloc_tos(), struct wbcDomainSid, num_sids);
1408 if (wbc_sids == NULL) {
1409 return false;
1410 }
1411
1412 num_not_cached = 0;
1413
1414 for (i=0; i<num_sids; i++) {
1415 bool expired;
1416 uint32_t rid;
1417
1418 if (fetch_uid_from_cache(&ids[i].id.uid, &sids[i])) {
1419 ids[i].type = WBC_ID_TYPE_UID;
1420 continue;
1421 }
1422 if (fetch_gid_from_cache(&ids[i].id.gid, &sids[i])) {
1423 ids[i].type = WBC_ID_TYPE_GID;
1424 continue;
1425 }
1426 if (sid_peek_check_rid(&global_sid_Unix_Users,
1427 &sids[i], &rid)) {
1428 ids[i].type = WBC_ID_TYPE_UID;
1429 ids[i].id.uid = rid;
1430 continue;
1431 }
1432 if (sid_peek_check_rid(&global_sid_Unix_Groups,
1433 &sids[i], &rid)) {
1434 ids[i].type = WBC_ID_TYPE_GID;
1435 ids[i].id.gid = rid;
1436 continue;
1437 }
1438 if (idmap_cache_find_sid2uid(&sids[i], &ids[i].id.uid,
1439 &expired)
1440 && !expired && ids[i].id.uid != (uid_t)-1) {
1441 ids[i].type = WBC_ID_TYPE_UID;
1442 continue;
1443 }
1444 if (idmap_cache_find_sid2gid(&sids[i], &ids[i].id.gid,
1445 &expired)
1446 && !expired && ids[i].id.gid != (gid_t)-1) {
1447 ids[i].type = WBC_ID_TYPE_GID;
1448 continue;
1449 }
1450 ids[i].type = WBC_ID_TYPE_NOT_SPECIFIED;
1451 memcpy(&wbc_sids[num_not_cached], &sids[i],
1452 ndr_size_dom_sid(&sids[i], 0));
1453 num_not_cached += 1;
1454 }
1455 if (num_not_cached == 0) {
1456 goto done;
1457 }
1458 wbc_ids = TALLOC_ARRAY(talloc_tos(), struct wbcUnixId, num_not_cached);
1459 if (wbc_ids == NULL) {
1460 goto fail;
1461 }
1462 for (i=0; i<num_not_cached; i++) {
1463 wbc_ids[i].type = WBC_ID_TYPE_NOT_SPECIFIED;
1464 }
1465 err = wbcSidsToUnixIds(wbc_sids, num_not_cached, wbc_ids);
1466 if (!WBC_ERROR_IS_OK(err)) {
1467 DEBUG(10, ("wbcSidsToUnixIds returned %s\n",
1468 wbcErrorString(err)));
1469 }
1470
1471 num_not_cached = 0;
1472
1473 for (i=0; i<num_sids; i++) {
1474 if (ids[i].type == WBC_ID_TYPE_NOT_SPECIFIED) {
1475 ids[i] = wbc_ids[num_not_cached];
1476 num_not_cached += 1;
1477 }
1478 }
1479
1480 for (i=0; i<num_sids; i++) {
1481 if (ids[i].type != WBC_ID_TYPE_NOT_SPECIFIED) {
1482 continue;
1483 }
1484 if (legacy_sid_to_gid(&sids[i], &ids[i].id.gid)) {
1485 ids[i].type = WBC_ID_TYPE_GID;
1486 continue;
1487 }
1488 if (legacy_sid_to_uid(&sids[i], &ids[i].id.uid)) {
1489 ids[i].type = WBC_ID_TYPE_UID;
1490 continue;
1491 }
1492 }
1493
1494done:
1495 for (i=0; i<num_sids; i++) {
1496 switch(ids[i].type) {
1497 case WBC_ID_TYPE_GID:
1498 if (ids[i].id.gid == (gid_t)-1) {
1499 ids[i].type = WBC_ID_TYPE_NOT_SPECIFIED;
1500 }
1501 break;
1502 case WBC_ID_TYPE_UID:
1503 if (ids[i].id.uid == (uid_t)-1) {
1504 ids[i].type = WBC_ID_TYPE_NOT_SPECIFIED;
1505 }
1506 break;
1507 case WBC_ID_TYPE_NOT_SPECIFIED:
1508 break;
1509 }
1510 }
1511 ret = true;
1512fail:
1513 TALLOC_FREE(wbc_ids);
1514 TALLOC_FREE(wbc_sids);
1515 return ret;
1516}
1517
1518/*****************************************************************
1519 *THE CANONICAL* convert SID to uid function.
1520*****************************************************************/
1521
1522bool sid_to_uid(const struct dom_sid *psid, uid_t *puid)
1523{
1524 bool expired = true;
1525 bool ret;
1526 uint32 rid;
1527 gid_t gid;
1528
1529 if (fetch_uid_from_cache(puid, psid))
1530 return true;
1531
1532 if (fetch_gid_from_cache(&gid, psid)) {
1533 return false;
1534 }
1535
1536 /* Optimize for the Unix Users Domain
1537 * as the conversion is straightforward */
1538 if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
1539 uid_t uid = rid;
1540 *puid = uid;
1541
1542 /* return here, don't cache */
1543 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1544 (unsigned int)*puid ));
1545 return true;
1546 }
1547
1548 /* Check the winbindd cache directly. */
1549 ret = idmap_cache_find_sid2uid(psid, puid, &expired);
1550
1551 if (ret && !expired && (*puid == (uid_t)-1)) {
1552 /*
1553 * Negative cache entry, we already asked.
1554 * do legacy.
1555 */
1556 return legacy_sid_to_uid(psid, puid);
1557 }
1558
1559 if (!ret || expired) {
1560 /* Not in cache. Ask winbindd. */
1561 if (!winbind_sid_to_uid(puid, psid)) {
1562 DEBUG(5, ("winbind failed to find a uid for sid %s\n",
1563 sid_string_dbg(psid)));
1564 /* winbind failed. do legacy */
1565 return legacy_sid_to_uid(psid, puid);
1566 }
1567 }
1568
1569 /* TODO: Here would be the place to allocate both a gid and a uid for
1570 * the SID in question */
1571
1572 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1573 (unsigned int)*puid ));
1574
1575 store_uid_sid_cache(psid, *puid);
1576 return true;
1577}
1578
1579/*****************************************************************
1580 *THE CANONICAL* convert SID to gid function.
1581 Group mapping is used for gids that maps to Wellknown SIDs
1582*****************************************************************/
1583
1584bool sid_to_gid(const struct dom_sid *psid, gid_t *pgid)
1585{
1586 bool expired = true;
1587 bool ret;
1588 uint32 rid;
1589 uid_t uid;
1590
1591 if (fetch_gid_from_cache(pgid, psid))
1592 return true;
1593
1594 if (fetch_uid_from_cache(&uid, psid))
1595 return false;
1596
1597 /* Optimize for the Unix Groups Domain
1598 * as the conversion is straightforward */
1599 if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
1600 gid_t gid = rid;
1601 *pgid = gid;
1602
1603 /* return here, don't cache */
1604 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1605 (unsigned int)*pgid ));
1606 return true;
1607 }
1608
1609 /* Check the winbindd cache directly. */
1610 ret = idmap_cache_find_sid2gid(psid, pgid, &expired);
1611
1612 if (ret && !expired && (*pgid == (gid_t)-1)) {
1613 /*
1614 * Negative cache entry, we already asked.
1615 * do legacy.
1616 */
1617 return legacy_sid_to_gid(psid, pgid);
1618 }
1619
1620 if (!ret || expired) {
1621 /* Not in cache or negative. Ask winbindd. */
1622 /* Ask winbindd if it can map this sid to a gid.
1623 * (Idmap will check it is a valid SID and of the right type) */
1624
1625 if ( !winbind_sid_to_gid(pgid, psid) ) {
1626
1627 DEBUG(10,("winbind failed to find a gid for sid %s\n",
1628 sid_string_dbg(psid)));
1629 /* winbind failed. do legacy */
1630 return legacy_sid_to_gid(psid, pgid);
1631 }
1632 }
1633
1634 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1635 (unsigned int)*pgid ));
1636
1637 store_gid_sid_cache(psid, *pgid);
1638 return true;
1639}
1640
1641/**
1642 * @brief This function gets the primary group SID mapping the primary
1643 * GID of the user as obtained by an actual getpwnam() call.
1644 * This is necessary to avoid issues with arbitrary group SIDs
1645 * stored in passdb. We try as hard as we can to get the SID
1646 * corresponding to the GID, including trying group mapping.
1647 * If nothing else works, we will force "Domain Users" as the
1648 * primary group.
1649 * This is needed because we must always be able to lookup the
1650 * primary group SID, so we cannot settle for an arbitrary SID.
1651 *
1652 * This call can be expensive. Use with moderation.
1653 * If you have a "samu" struct around use pdb_get_group_sid()
1654 * instead as it does properly cache results.
1655 *
1656 * @param mem_ctx[in] The memory context iused to allocate the result.
1657 * @param username[in] The user's name
1658 * @param _pwd[in|out] If available, pass in user's passwd struct.
1659 * It will contain a tallocated passwd if NULL was
1660 * passed in.
1661 * @param _group_sid[out] The user's Primary Group SID
1662 *
1663 * @return NTSTATUS error code.
1664 */
1665NTSTATUS get_primary_group_sid(TALLOC_CTX *mem_ctx,
1666 const char *username,
1667 struct passwd **_pwd,
1668 struct dom_sid **_group_sid)
1669{
1670 TALLOC_CTX *tmp_ctx;
1671 bool need_lookup_sid = false;
1672 struct dom_sid *group_sid;
1673 struct passwd *pwd = *_pwd;
1674
1675 tmp_ctx = talloc_new(mem_ctx);
1676 if (!tmp_ctx) {
1677 return NT_STATUS_NO_MEMORY;
1678 }
1679
1680 if (!pwd) {
1681 pwd = Get_Pwnam_alloc(mem_ctx, username);
1682 if (!pwd) {
1683 DEBUG(0, ("Failed to find a Unix account for %s",
1684 username));
1685 TALLOC_FREE(tmp_ctx);
1686 return NT_STATUS_NO_SUCH_USER;
1687 }
1688 }
1689
1690 group_sid = talloc_zero(mem_ctx, struct dom_sid);
1691 if (!group_sid) {
1692 TALLOC_FREE(tmp_ctx);
1693 return NT_STATUS_NO_MEMORY;
1694 }
1695
1696 gid_to_sid(group_sid, pwd->pw_gid);
1697 if (!is_null_sid(group_sid)) {
1698 struct dom_sid domain_sid;
1699 uint32_t rid;
1700
1701 /* We need a sid within our domain */
1702 sid_copy(&domain_sid, group_sid);
1703 sid_split_rid(&domain_sid, &rid);
1704 if (dom_sid_equal(&domain_sid, get_global_sam_sid())) {
1705 /*
1706 * As shortcut for the expensive lookup_sid call
1707 * compare the domain sid part
1708 */
1709 switch (rid) {
1710 case DOMAIN_RID_ADMINS:
1711 case DOMAIN_RID_USERS:
1712 goto done;
1713 default:
1714 need_lookup_sid = true;
1715 break;
1716 }
1717 } else {
1718 /* Try group mapping */
1719 ZERO_STRUCTP(group_sid);
1720 if (pdb_gid_to_sid(pwd->pw_gid, group_sid)) {
1721 need_lookup_sid = true;
1722 }
1723 }
1724 }
1725
1726 /* We must verify that this is a valid SID that resolves to a
1727 * group of the correct type */
1728 if (need_lookup_sid) {
1729 enum lsa_SidType type = SID_NAME_UNKNOWN;
1730 bool lookup_ret;
1731
1732 DEBUG(10, ("do lookup_sid(%s) for group of user %s\n",
1733 sid_string_dbg(group_sid), username));
1734
1735 /* Now check that it's actually a domain group and
1736 * not something else */
1737 lookup_ret = lookup_sid(tmp_ctx, group_sid,
1738 NULL, NULL, &type);
1739
1740 if (lookup_ret && (type == SID_NAME_DOM_GRP)) {
1741 goto done;
1742 }
1743
1744 DEBUG(3, ("Primary group %s for user %s is"
1745 " a %s and not a domain group\n",
1746 sid_string_dbg(group_sid), username,
1747 sid_type_lookup(type)));
1748 }
1749
1750 /* Everything else, failed.
1751 * Just set it to the 'Domain Users' RID of 513 which will
1752 always resolve to a name */
1753 DEBUG(3, ("Forcing Primary Group to 'Domain Users' for %s\n",
1754 username));
1755
1756 sid_compose(group_sid, get_global_sam_sid(), DOMAIN_RID_USERS);
1757
1758done:
1759 *_pwd = talloc_move(mem_ctx, &pwd);
1760 *_group_sid = talloc_move(mem_ctx, &group_sid);
1761 TALLOC_FREE(tmp_ctx);
1762 return NT_STATUS_OK;
1763}
1764
1765bool delete_uid_cache(uid_t puid)
1766{
1767 DATA_BLOB uid = data_blob_const(&puid, sizeof(puid));
1768 DATA_BLOB sid;
1769
1770 if (!memcache_lookup(NULL, UID_SID_CACHE, uid, &sid)) {
1771 DEBUG(3, ("UID %d is not memcached!\n", (int)puid));
1772 return false;
1773 }
1774 DEBUG(3, ("Delete mapping UID %d <-> %s from memcache\n", (int)puid,
1775 sid_string_dbg((struct dom_sid*)sid.data)));
1776 memcache_delete(NULL, SID_UID_CACHE, sid);
1777 memcache_delete(NULL, UID_SID_CACHE, uid);
1778 return true;
1779}
1780
1781bool delete_gid_cache(gid_t pgid)
1782{
1783 DATA_BLOB gid = data_blob_const(&pgid, sizeof(pgid));
1784 DATA_BLOB sid;
1785 if (!memcache_lookup(NULL, GID_SID_CACHE, gid, &sid)) {
1786 DEBUG(3, ("GID %d is not memcached!\n", (int)pgid));
1787 return false;
1788 }
1789 DEBUG(3, ("Delete mapping GID %d <-> %s from memcache\n", (int)pgid,
1790 sid_string_dbg((struct dom_sid*)sid.data)));
1791 memcache_delete(NULL, SID_GID_CACHE, sid);
1792 memcache_delete(NULL, GID_SID_CACHE, gid);
1793 return true;
1794}
1795
1796bool delete_sid_cache(const struct dom_sid* psid)
1797{
1798 DATA_BLOB sid = data_blob_const(psid, ndr_size_dom_sid(psid, 0));
1799 DATA_BLOB id;
1800 if (memcache_lookup(NULL, SID_GID_CACHE, sid, &id)) {
1801 DEBUG(3, ("Delete mapping %s <-> GID %d from memcache\n",
1802 sid_string_dbg(psid), *(int*)id.data));
1803 memcache_delete(NULL, SID_GID_CACHE, sid);
1804 memcache_delete(NULL, GID_SID_CACHE, id);
1805 } else if (memcache_lookup(NULL, SID_UID_CACHE, sid, &id)) {
1806 DEBUG(3, ("Delete mapping %s <-> UID %d from memcache\n",
1807 sid_string_dbg(psid), *(int*)id.data));
1808 memcache_delete(NULL, SID_UID_CACHE, sid);
1809 memcache_delete(NULL, UID_SID_CACHE, id);
1810 } else {
1811 DEBUG(3, ("SID %s is not memcached!\n", sid_string_dbg(psid)));
1812 return false;
1813 }
1814 return true;
1815}
1816
1817void flush_gid_cache(void)
1818{
1819 DEBUG(3, ("Flush GID <-> SID memcache\n"));
1820 memcache_flush(NULL, SID_GID_CACHE);
1821 memcache_flush(NULL, GID_SID_CACHE);
1822}
1823
1824void flush_uid_cache(void)
1825{
1826 DEBUG(3, ("Flush UID <-> SID memcache\n"));
1827 memcache_flush(NULL, SID_UID_CACHE);
1828 memcache_flush(NULL, UID_SID_CACHE);
1829}
Note: See TracBrowser for help on using the repository browser.