source: vendor/current/source3/passdb/lookup_sid.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

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