2
Unix SMB/CIFS implementation.
4
Copyright (C) Andrew Tridgell 1992-1998
5
Copyright (C) Gerald (Jerry) Carter 2003
6
Copyright (C) Volker Lendecke 2005
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.
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.
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/>.
24
/*****************************************************************
25
Dissect a user-provided name into domain, name, sid and type.
27
If an explicit domain name was given in the form domain\user, it
28
has to try that. If no explicit domain name was given, we have
30
*****************************************************************/
32
bool lookup_name(TALLOC_CTX *mem_ctx,
33
const char *full_name, int flags,
34
const char **ret_domain, const char **ret_name,
35
DOM_SID *ret_sid, enum lsa_SidType *ret_type)
39
const char *domain = NULL;
40
const char *name = NULL;
43
enum lsa_SidType type;
44
TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
46
if (tmp_ctx == NULL) {
47
DEBUG(0, ("talloc_new failed\n"));
51
p = strchr_m(full_name, '\\');
54
domain = talloc_strndup(tmp_ctx, full_name,
55
PTR_DIFF(p, full_name));
56
name = talloc_strdup(tmp_ctx, p+1);
58
domain = talloc_strdup(tmp_ctx, "");
59
name = talloc_strdup(tmp_ctx, full_name);
62
if ((domain == NULL) || (name == NULL)) {
63
DEBUG(0, ("talloc failed\n"));
68
DEBUG(10,("lookup_name: %s => %s (domain), %s (name)\n",
69
full_name, domain, name));
70
DEBUG(10, ("lookup_name: flags = 0x0%x\n", flags));
72
if ((flags & LOOKUP_NAME_DOMAIN) &&
73
strequal(domain, get_global_sam_name()))
76
/* It's our own domain, lookup the name in passdb */
77
if (lookup_global_sam_name(name, flags, &rid, &type)) {
78
sid_copy(&sid, get_global_sam_sid());
79
sid_append_rid(&sid, rid);
86
if ((flags & LOOKUP_NAME_BUILTIN) &&
87
strequal(domain, builtin_domain_name()))
89
/* Explicit request for a name in BUILTIN */
90
if (lookup_builtin_name(name, &rid)) {
91
sid_copy(&sid, &global_sid_Builtin);
92
sid_append_rid(&sid, rid);
93
type = SID_NAME_ALIAS;
100
/* Try the explicit winbind lookup first, don't let it guess the
101
* domain yet at this point yet. This comes later. */
103
if ((domain[0] != '\0') &&
104
(flags & ~(LOOKUP_NAME_DOMAIN|LOOKUP_NAME_ISOLATED)) &&
105
(winbind_lookup_name(domain, name, &sid, &type))) {
109
if (!(flags & LOOKUP_NAME_EXPLICIT) && strequal(domain, unix_users_domain_name())) {
110
if (lookup_unix_user_name(name, &sid)) {
111
type = SID_NAME_USER;
114
TALLOC_FREE(tmp_ctx);
118
if (!(flags & LOOKUP_NAME_EXPLICIT) && strequal(domain, unix_groups_domain_name())) {
119
if (lookup_unix_group_name(name, &sid)) {
120
type = SID_NAME_DOM_GRP;
123
TALLOC_FREE(tmp_ctx);
127
if ((domain[0] == '\0') && (!(flags & LOOKUP_NAME_ISOLATED))) {
128
TALLOC_FREE(tmp_ctx);
132
/* Now the guesswork begins, we haven't been given an explicit
133
* domain. Try the sequence as documented on
134
* http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
135
* November 27, 2005 */
137
/* 1. well-known names */
139
if ((flags & LOOKUP_NAME_WKN) &&
140
lookup_wellknown_name(tmp_ctx, name, &sid, &domain))
142
type = SID_NAME_WKN_GRP;
146
/* 2. Builtin domain as such */
148
if ((flags & (LOOKUP_NAME_BUILTIN|LOOKUP_NAME_REMOTE)) &&
149
strequal(name, builtin_domain_name()))
151
/* Swap domain and name */
152
tmp = name; name = domain; domain = tmp;
153
sid_copy(&sid, &global_sid_Builtin);
154
type = SID_NAME_DOMAIN;
158
/* 3. Account domain */
160
if ((flags & LOOKUP_NAME_DOMAIN) &&
161
strequal(name, get_global_sam_name()))
163
if (!secrets_fetch_domain_sid(name, &sid)) {
164
DEBUG(3, ("Could not fetch my SID\n"));
165
TALLOC_FREE(tmp_ctx);
168
/* Swap domain and name */
169
tmp = name; name = domain; domain = tmp;
170
type = SID_NAME_DOMAIN;
174
/* 4. Primary domain */
176
if ((flags & LOOKUP_NAME_DOMAIN) && !IS_DC &&
177
strequal(name, lp_workgroup()))
179
if (!secrets_fetch_domain_sid(name, &sid)) {
180
DEBUG(3, ("Could not fetch the domain SID\n"));
181
TALLOC_FREE(tmp_ctx);
184
/* Swap domain and name */
185
tmp = name; name = domain; domain = tmp;
186
type = SID_NAME_DOMAIN;
190
/* 5. Trusted domains as such, to me it looks as if members don't do
191
this, tested an XP workstation in a NT domain -- vl */
193
if ((flags & LOOKUP_NAME_REMOTE) && IS_DC &&
194
(pdb_get_trusteddom_pw(name, NULL, &sid, NULL)))
196
/* Swap domain and name */
197
tmp = name; name = domain; domain = tmp;
198
type = SID_NAME_DOMAIN;
202
/* 6. Builtin aliases */
204
if ((flags & LOOKUP_NAME_BUILTIN) &&
205
lookup_builtin_name(name, &rid))
207
domain = talloc_strdup(tmp_ctx, builtin_domain_name());
208
sid_copy(&sid, &global_sid_Builtin);
209
sid_append_rid(&sid, rid);
210
type = SID_NAME_ALIAS;
214
/* 7. Local systems' SAM (DCs don't have a local SAM) */
215
/* 8. Primary SAM (On members, this is the domain) */
217
/* Both cases are done by looking at our passdb */
219
if ((flags & LOOKUP_NAME_DOMAIN) &&
220
lookup_global_sam_name(name, flags, &rid, &type))
222
domain = talloc_strdup(tmp_ctx, get_global_sam_name());
223
sid_copy(&sid, get_global_sam_sid());
224
sid_append_rid(&sid, rid);
228
/* Now our local possibilities are exhausted. */
230
if (!(flags & LOOKUP_NAME_REMOTE)) {
231
TALLOC_FREE(tmp_ctx);
235
/* If we are not a DC, we have to ask in our primary domain. Let
236
* winbind do that. */
239
(winbind_lookup_name(lp_workgroup(), name, &sid, &type))) {
240
domain = talloc_strdup(tmp_ctx, lp_workgroup());
244
/* 9. Trusted domains */
246
/* If we're a DC we have to ask all trusted DC's. Winbind does not do
247
* that (yet), but give it a chance. */
249
if (IS_DC && winbind_lookup_name("", name, &sid, &type)) {
252
enum lsa_SidType domain_type;
254
if (type == SID_NAME_DOMAIN) {
255
/* Swap name and type */
256
tmp = name; name = domain; domain = tmp;
260
/* Here we have to cope with a little deficiency in the
261
* winbind API: We have to ask it again for the name of the
262
* domain it figured out itself. Maybe fix that later... */
264
sid_copy(&dom_sid, &sid);
265
sid_split_rid(&dom_sid, &tmp_rid);
267
if (!winbind_lookup_sid(tmp_ctx, &dom_sid, &domain, NULL,
269
(domain_type != SID_NAME_DOMAIN)) {
270
DEBUG(2, ("winbind could not find the domain's name "
271
"it just looked up for us\n"));
272
TALLOC_FREE(tmp_ctx);
278
/* 10. Don't translate */
280
/* 11. Ok, windows would end here. Samba has two more options:
281
Unmapped users and unmapped groups */
283
if (!(flags & LOOKUP_NAME_EXPLICIT) && lookup_unix_user_name(name, &sid)) {
284
domain = talloc_strdup(tmp_ctx, unix_users_domain_name());
285
type = SID_NAME_USER;
289
if (!(flags & LOOKUP_NAME_EXPLICIT) && lookup_unix_group_name(name, &sid)) {
290
domain = talloc_strdup(tmp_ctx, unix_groups_domain_name());
291
type = SID_NAME_DOM_GRP;
296
* Ok, all possibilities tried. Fail.
299
TALLOC_FREE(tmp_ctx);
303
if ((domain == NULL) || (name == NULL)) {
304
DEBUG(0, ("talloc failed\n"));
305
TALLOC_FREE(tmp_ctx);
310
* Hand over the results to the talloc context we've been given.
313
if ((ret_name != NULL) &&
314
!(*ret_name = talloc_strdup(mem_ctx, name))) {
315
DEBUG(0, ("talloc failed\n"));
316
TALLOC_FREE(tmp_ctx);
320
if (ret_domain != NULL) {
322
if (!(tmp_dom = talloc_strdup(mem_ctx, domain))) {
323
DEBUG(0, ("talloc failed\n"));
324
TALLOC_FREE(tmp_ctx);
328
*ret_domain = tmp_dom;
331
if (ret_sid != NULL) {
332
sid_copy(ret_sid, &sid);
335
if (ret_type != NULL) {
339
TALLOC_FREE(tmp_ctx);
343
/************************************************************************
344
Names from smb.conf can be unqualified. eg. valid users = foo
345
These names should never map to a remote name. Try global_sam_name()\foo,
346
and then "Unix Users"\foo (or "Unix Groups"\foo).
347
************************************************************************/
349
bool lookup_name_smbconf(TALLOC_CTX *mem_ctx,
350
const char *full_name, int flags,
351
const char **ret_domain, const char **ret_name,
352
DOM_SID *ret_sid, enum lsa_SidType *ret_type)
354
char *qualified_name;
357
/* NB. No winbindd_separator here as lookup_name needs \\' */
358
if ((p = strchr_m(full_name, *lp_winbind_separator())) != NULL) {
360
/* The name is already qualified with a domain. */
362
if (*lp_winbind_separator() != '\\') {
365
/* lookup_name() needs '\\' as a separator */
367
tmp = talloc_strdup(mem_ctx, full_name);
371
tmp[p - full_name] = '\\';
375
return lookup_name(mem_ctx, full_name, flags,
376
ret_domain, ret_name,
380
/* Try with our own SAM name. */
381
qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
382
get_global_sam_name(),
384
if (!qualified_name) {
388
if (lookup_name(mem_ctx, qualified_name, flags,
389
ret_domain, ret_name,
390
ret_sid, ret_type)) {
394
/* Finally try with "Unix Users" or "Unix Group" */
395
qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
396
flags & LOOKUP_NAME_GROUP ?
397
unix_groups_domain_name() :
398
unix_users_domain_name(),
400
if (!qualified_name) {
404
return lookup_name(mem_ctx, qualified_name, flags,
405
ret_domain, ret_name,
409
static bool wb_lookup_rids(TALLOC_CTX *mem_ctx,
410
const DOM_SID *domain_sid,
411
int num_rids, uint32 *rids,
412
const char **domain_name,
413
const char **names, enum lsa_SidType *types)
416
const char **my_names;
417
enum lsa_SidType *my_types;
420
if (!(tmp_ctx = talloc_init("wb_lookup_rids"))) {
424
if (!winbind_lookup_rids(tmp_ctx, domain_sid, num_rids, rids,
425
domain_name, &my_names, &my_types)) {
427
for (i=0; i<num_rids; i++) {
429
types[i] = SID_NAME_UNKNOWN;
431
TALLOC_FREE(tmp_ctx);
435
if (!(*domain_name = talloc_strdup(mem_ctx, *domain_name))) {
436
TALLOC_FREE(tmp_ctx);
441
* winbind_lookup_rids allocates its own array. We've been given the
442
* array, so copy it over
445
for (i=0; i<num_rids; i++) {
446
if (my_names[i] == NULL) {
447
TALLOC_FREE(tmp_ctx);
450
if (!(names[i] = talloc_strdup(names, my_names[i]))) {
451
TALLOC_FREE(tmp_ctx);
454
types[i] = my_types[i];
456
TALLOC_FREE(tmp_ctx);
460
static bool lookup_rids(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
461
int num_rids, uint32_t *rids,
462
const char **domain_name,
463
const char ***names, enum lsa_SidType **types)
467
DEBUG(10, ("lookup_rids called for domain sid '%s'\n",
468
sid_string_dbg(domain_sid)));
471
*names = TALLOC_ZERO_ARRAY(mem_ctx, const char *, num_rids);
472
*types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
474
if ((*names == NULL) || (*types == NULL)) {
478
for (i = 0; i < num_rids; i++)
479
(*types)[i] = SID_NAME_UNKNOWN;
485
if (sid_check_is_domain(domain_sid)) {
488
if (*domain_name == NULL) {
489
*domain_name = talloc_strdup(
490
mem_ctx, get_global_sam_name());
493
if (*domain_name == NULL) {
498
result = pdb_lookup_rids(domain_sid, num_rids, rids,
502
return (NT_STATUS_IS_OK(result) ||
503
NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
504
NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
507
if (sid_check_is_builtin(domain_sid)) {
509
if (*domain_name == NULL) {
510
*domain_name = talloc_strdup(
511
mem_ctx, builtin_domain_name());
514
if (*domain_name == NULL) {
518
for (i=0; i<num_rids; i++) {
519
if (lookup_builtin_rid(*names, rids[i],
521
if ((*names)[i] == NULL) {
524
(*types)[i] = SID_NAME_ALIAS;
526
(*types)[i] = SID_NAME_UNKNOWN;
532
if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
533
for (i=0; i<num_rids; i++) {
535
sid_copy(&sid, domain_sid);
536
sid_append_rid(&sid, rids[i]);
537
if (lookup_wellknown_sid(mem_ctx, &sid,
538
domain_name, &(*names)[i])) {
539
if ((*names)[i] == NULL) {
542
(*types)[i] = SID_NAME_WKN_GRP;
544
(*types)[i] = SID_NAME_UNKNOWN;
550
if (sid_check_is_unix_users(domain_sid)) {
551
if (*domain_name == NULL) {
552
*domain_name = talloc_strdup(
553
mem_ctx, unix_users_domain_name());
554
if (*domain_name == NULL) {
558
for (i=0; i<num_rids; i++) {
559
(*names)[i] = talloc_strdup(
560
(*names), uidtoname(rids[i]));
561
if ((*names)[i] == NULL) {
564
(*types)[i] = SID_NAME_USER;
569
if (sid_check_is_unix_groups(domain_sid)) {
570
if (*domain_name == NULL) {
571
*domain_name = talloc_strdup(
572
mem_ctx, unix_groups_domain_name());
573
if (*domain_name == NULL) {
577
for (i=0; i<num_rids; i++) {
578
(*names)[i] = talloc_strdup(
579
(*names), gidtoname(rids[i]));
580
if ((*names)[i] == NULL) {
583
(*types)[i] = SID_NAME_DOM_GRP;
588
return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
589
domain_name, *names, *types);
593
* Is the SID a domain as such? If yes, lookup its name.
596
static bool lookup_as_domain(const DOM_SID *sid, TALLOC_CTX *mem_ctx,
600
enum lsa_SidType type;
602
if (sid_check_is_domain(sid)) {
603
*name = talloc_strdup(mem_ctx, get_global_sam_name());
607
if (sid_check_is_builtin(sid)) {
608
*name = talloc_strdup(mem_ctx, builtin_domain_name());
612
if (sid_check_is_wellknown_domain(sid, &tmp)) {
613
*name = talloc_strdup(mem_ctx, tmp);
617
if (sid_check_is_unix_users(sid)) {
618
*name = talloc_strdup(mem_ctx, unix_users_domain_name());
622
if (sid_check_is_unix_groups(sid)) {
623
*name = talloc_strdup(mem_ctx, unix_groups_domain_name());
627
if (sid->num_auths != 4) {
628
/* This can't be a domain */
633
uint32 i, num_domains;
634
struct trustdom_info **domains;
636
/* This is relatively expensive, but it happens only on DCs
637
* and for SIDs that have 4 sub-authorities and thus look like
640
if (!NT_STATUS_IS_OK(pdb_enum_trusteddoms(mem_ctx,
646
for (i=0; i<num_domains; i++) {
647
if (sid_equal(sid, &domains[i]->sid)) {
648
*name = talloc_strdup(mem_ctx,
656
if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
657
(type == SID_NAME_DOMAIN)) {
666
* This tries to implement the rather weird rules for the lsa_lookup level
669
* This is as close as we can get to what W2k3 does. With this we survive the
670
* RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
671
* different, but I assume that's just being too liberal. For example, W2k3
672
* replies to everything else but the levels 1-6 with INVALID_PARAMETER
673
* whereas NT4 does the same as level 1 (I think). I did not fully test that
674
* with NT4, this is what w2k3 does.
676
* Level 1: Ask everywhere
677
* Level 2: Ask domain and trusted domains, no builtin and wkn
678
* Level 3: Only ask domain
679
* Level 4: W2k3ad: Only ask AD trusts
680
* Level 5: Only ask transitive forest trusts
684
static bool check_dom_sid_to_level(const DOM_SID *sid, int level)
693
ret = (!sid_check_is_builtin(sid) &&
694
!sid_check_is_wellknown_domain(sid, NULL));
699
ret = sid_check_is_domain(sid);
706
DEBUG(10, ("%s SID %s in level %d\n",
707
ret ? "Accepting" : "Rejecting",
708
sid_string_dbg(sid), level));
713
* Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
714
* references to domains, it is explicitly made for this.
716
* This attempts to be as efficient as possible: It collects all SIDs
717
* belonging to a domain and hands them in bulk to the appropriate lookup
718
* function. In particular pdb_lookup_rids with ldapsam_trusted benefits
719
* *hugely* from this. Winbind is going to be extended with a lookup_rids
720
* interface as well, so on a DC we can do a bulk lsa_lookuprids to the
724
NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
725
const DOM_SID **sids, int level,
726
struct lsa_dom_info **ret_domains,
727
struct lsa_name_info **ret_names)
730
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
731
struct lsa_name_info *name_infos;
732
struct lsa_dom_info *dom_infos = NULL;
736
if (!(tmp_ctx = talloc_new(mem_ctx))) {
737
DEBUG(0, ("talloc_new failed\n"));
738
return NT_STATUS_NO_MEMORY;
742
name_infos = TALLOC_ARRAY(mem_ctx, struct lsa_name_info, num_sids);
743
if (name_infos == NULL) {
744
result = NT_STATUS_NO_MEMORY;
751
dom_infos = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_dom_info,
752
LSA_REF_DOMAIN_LIST_MULTIPLIER);
753
if (dom_infos == NULL) {
754
result = NT_STATUS_NO_MEMORY;
758
/* First build up the data structures:
760
* dom_infos is a list of domains referenced in the list of
761
* SIDs. Later we will walk the list of domains and look up the RIDs
764
* name_infos is a shadow-copy of the SIDs array to collect the real
767
* dom_info->idxs is an index into the name_infos array. The
768
* difficulty we have here is that we need to keep the SIDs the client
769
* asked for in the same order for the reply
772
for (i=0; i<num_sids; i++) {
775
const char *domain_name = NULL;
777
sid_copy(&sid, sids[i]);
778
name_infos[i].type = SID_NAME_USE_NONE;
780
if (lookup_as_domain(&sid, name_infos, &domain_name)) {
781
/* We can't push that through the normal lookup
782
* process, as this would reference illegal
785
* For example S-1-5-32 would end up referencing
786
* domain S-1-5- with RID 32 which is clearly wrong.
788
if (domain_name == NULL) {
789
result = NT_STATUS_NO_MEMORY;
793
name_infos[i].rid = 0;
794
name_infos[i].type = SID_NAME_DOMAIN;
795
name_infos[i].name = NULL;
797
if (sid_check_is_builtin(&sid)) {
798
/* Yes, W2k3 returns "BUILTIN" both as domain
800
name_infos[i].name = talloc_strdup(
801
name_infos, builtin_domain_name());
802
if (name_infos[i].name == NULL) {
803
result = NT_STATUS_NO_MEMORY;
808
/* This is a normal SID with rid component */
809
if (!sid_split_rid(&sid, &rid)) {
810
result = NT_STATUS_INVALID_SID;
815
if (!check_dom_sid_to_level(&sid, level)) {
816
name_infos[i].rid = 0;
817
name_infos[i].type = SID_NAME_UNKNOWN;
818
name_infos[i].name = NULL;
822
for (j=0; j<LSA_REF_DOMAIN_LIST_MULTIPLIER; j++) {
823
if (!dom_infos[j].valid) {
826
if (sid_equal(&sid, &dom_infos[j].sid)) {
831
if (j == LSA_REF_DOMAIN_LIST_MULTIPLIER) {
832
/* TODO: What's the right error message here? */
833
result = NT_STATUS_NONE_MAPPED;
837
if (!dom_infos[j].valid) {
838
/* We found a domain not yet referenced, create a new
840
dom_infos[j].valid = true;
841
sid_copy(&dom_infos[j].sid, &sid);
843
if (domain_name != NULL) {
844
/* This name was being found above in the case
845
* when we found a domain SID */
847
talloc_strdup(dom_infos, domain_name);
848
if (dom_infos[j].name == NULL) {
849
result = NT_STATUS_NO_MEMORY;
853
/* lookup_rids will take care of this */
854
dom_infos[j].name = NULL;
858
name_infos[i].dom_idx = j;
860
if (name_infos[i].type == SID_NAME_USE_NONE) {
861
name_infos[i].rid = rid;
863
ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
864
&dom_infos[j].num_idxs);
866
if (dom_infos[j].idxs == NULL) {
867
result = NT_STATUS_NO_MEMORY;
873
/* Iterate over the domains found */
875
for (i=0; i<LSA_REF_DOMAIN_LIST_MULTIPLIER; i++) {
877
const char *domain_name = NULL;
879
enum lsa_SidType *types;
880
struct lsa_dom_info *dom = &dom_infos[i];
883
/* No domains left, we're done */
888
if (!(rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs))) {
889
result = NT_STATUS_NO_MEMORY;
896
for (j=0; j<dom->num_idxs; j++) {
897
rids[j] = name_infos[dom->idxs[j]].rid;
900
if (!lookup_rids(tmp_ctx, &dom->sid,
901
dom->num_idxs, rids, &domain_name,
903
result = NT_STATUS_NO_MEMORY;
907
if (!(dom->name = talloc_strdup(dom_infos, domain_name))) {
908
result = NT_STATUS_NO_MEMORY;
912
for (j=0; j<dom->num_idxs; j++) {
913
int idx = dom->idxs[j];
914
name_infos[idx].type = types[j];
915
if (types[j] != SID_NAME_UNKNOWN) {
916
name_infos[idx].name =
917
talloc_strdup(name_infos, names[j]);
918
if (name_infos[idx].name == NULL) {
919
result = NT_STATUS_NO_MEMORY;
923
name_infos[idx].name = NULL;
928
*ret_domains = dom_infos;
929
*ret_names = name_infos;
930
TALLOC_FREE(tmp_ctx);
934
TALLOC_FREE(dom_infos);
935
TALLOC_FREE(name_infos);
936
TALLOC_FREE(tmp_ctx);
940
/*****************************************************************
941
*THE CANONICAL* convert SID to name function.
942
*****************************************************************/
944
bool lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
945
const char **ret_domain, const char **ret_name,
946
enum lsa_SidType *ret_type)
948
struct lsa_dom_info *domain;
949
struct lsa_name_info *name;
953
DEBUG(10, ("lookup_sid called for SID '%s'\n", sid_string_dbg(sid)));
955
if (!(tmp_ctx = talloc_new(mem_ctx))) {
956
DEBUG(0, ("talloc_new failed\n"));
960
if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
965
if (name->type == SID_NAME_UNKNOWN) {
969
if ((ret_domain != NULL) &&
970
!(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
974
if ((ret_name != NULL) &&
975
!(*ret_name = talloc_strdup(mem_ctx, name->name))) {
979
if (ret_type != NULL) {
980
*ret_type = name->type;
987
DEBUG(10, ("Sid %s -> %s\\%s(%d)\n", sid_string_dbg(sid),
988
domain->name, name->name, name->type));
990
DEBUG(10, ("failed to lookup sid %s\n", sid_string_dbg(sid)));
992
TALLOC_FREE(tmp_ctx);
996
/*****************************************************************
997
Id mapping cache. This is to avoid Winbind mappings already
998
seen by smbd to be queried too frequently, keeping winbindd
999
busy, and blocking smbd while winbindd is busy with other
1000
stuff. Written by Michael Steffens <michael.steffens@hp.com>,
1001
modified to use linked lists by jra.
1002
*****************************************************************/
1004
/*****************************************************************
1005
Find a SID given a uid.
1006
*****************************************************************/
1008
static bool fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid)
1010
DATA_BLOB cache_value;
1012
if (!memcache_lookup(NULL, UID_SID_CACHE,
1013
data_blob_const(&uid, sizeof(uid)),
1018
memcpy(psid, cache_value.data, MIN(sizeof(*psid), cache_value.length));
1019
SMB_ASSERT(cache_value.length >= offsetof(struct dom_sid, id_auth));
1020
SMB_ASSERT(cache_value.length == ndr_size_dom_sid(psid, NULL, 0));
1025
/*****************************************************************
1026
Find a uid given a SID.
1027
*****************************************************************/
1029
static bool fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid )
1031
DATA_BLOB cache_value;
1033
if (!memcache_lookup(NULL, SID_UID_CACHE,
1034
data_blob_const(psid, ndr_size_dom_sid(psid, NULL, 0)),
1039
SMB_ASSERT(cache_value.length == sizeof(*puid));
1040
memcpy(puid, cache_value.data, sizeof(*puid));
1045
/*****************************************************************
1046
Store uid to SID mapping in cache.
1047
*****************************************************************/
1049
void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
1051
memcache_add(NULL, SID_UID_CACHE,
1052
data_blob_const(psid, ndr_size_dom_sid(psid, NULL, 0)),
1053
data_blob_const(&uid, sizeof(uid)));
1054
memcache_add(NULL, UID_SID_CACHE,
1055
data_blob_const(&uid, sizeof(uid)),
1056
data_blob_const(psid, ndr_size_dom_sid(psid, NULL, 0)));
1059
/*****************************************************************
1060
Find a SID given a gid.
1061
*****************************************************************/
1063
static bool fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid)
1065
DATA_BLOB cache_value;
1067
if (!memcache_lookup(NULL, GID_SID_CACHE,
1068
data_blob_const(&gid, sizeof(gid)),
1073
memcpy(psid, cache_value.data, MIN(sizeof(*psid), cache_value.length));
1074
SMB_ASSERT(cache_value.length >= offsetof(struct dom_sid, id_auth));
1075
SMB_ASSERT(cache_value.length == ndr_size_dom_sid(psid, NULL, 0));
1080
/*****************************************************************
1081
Find a gid given a SID.
1082
*****************************************************************/
1084
static bool fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid)
1086
DATA_BLOB cache_value;
1088
if (!memcache_lookup(NULL, SID_GID_CACHE,
1089
data_blob_const(psid, ndr_size_dom_sid(psid, NULL, 0)),
1094
SMB_ASSERT(cache_value.length == sizeof(*pgid));
1095
memcpy(pgid, cache_value.data, sizeof(*pgid));
1100
/*****************************************************************
1101
Store gid to SID mapping in cache.
1102
*****************************************************************/
1104
void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
1106
memcache_add(NULL, SID_GID_CACHE,
1107
data_blob_const(psid, ndr_size_dom_sid(psid, NULL, 0)),
1108
data_blob_const(&gid, sizeof(gid)));
1109
memcache_add(NULL, GID_SID_CACHE,
1110
data_blob_const(&gid, sizeof(gid)),
1111
data_blob_const(psid, ndr_size_dom_sid(psid, NULL, 0)));
1114
/*****************************************************************
1115
*THE LEGACY* convert uid_t to SID function.
1116
*****************************************************************/
1118
static void legacy_uid_to_sid(DOM_SID *psid, uid_t uid)
1126
ret = pdb_uid_to_rid(uid, &rid);
1130
/* This is a mapped user */
1131
sid_copy(psid, get_global_sam_sid());
1132
sid_append_rid(psid, rid);
1136
/* This is an unmapped user */
1138
uid_to_unix_users_sid(uid, psid);
1141
DEBUG(10,("LEGACY: uid %u -> sid %s\n", (unsigned int)uid,
1142
sid_string_dbg(psid)));
1144
store_uid_sid_cache(psid, uid);
1148
/*****************************************************************
1149
*THE LEGACY* convert gid_t to SID function.
1150
*****************************************************************/
1152
static void legacy_gid_to_sid(DOM_SID *psid, gid_t gid)
1159
ret = pdb_gid_to_sid(gid, psid);
1163
/* This is a mapped group */
1167
/* This is an unmapped group */
1169
gid_to_unix_groups_sid(gid, psid);
1172
DEBUG(10,("LEGACY: gid %u -> sid %s\n", (unsigned int)gid,
1173
sid_string_dbg(psid)));
1175
store_gid_sid_cache(psid, gid);
1179
/*****************************************************************
1180
*THE LEGACY* convert SID to uid function.
1181
*****************************************************************/
1183
static bool legacy_sid_to_uid(const DOM_SID *psid, uid_t *puid)
1185
enum lsa_SidType type;
1188
if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1193
ret = pdb_sid_to_id(psid, &id, &type);
1197
if (type != SID_NAME_USER) {
1198
DEBUG(5, ("sid %s is a %s, expected a user\n",
1199
sid_string_dbg(psid),
1200
sid_type_lookup(type)));
1207
/* This was ours, but it was not mapped. Fail */
1210
DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1211
sid_string_dbg(psid)));
1215
DEBUG(10,("LEGACY: sid %s -> uid %u\n", sid_string_dbg(psid),
1216
(unsigned int)*puid ));
1218
store_uid_sid_cache(psid, *puid);
1222
/*****************************************************************
1223
*THE LEGACY* convert SID to gid function.
1224
Group mapping is used for gids that maps to Wellknown SIDs
1225
*****************************************************************/
1227
static bool legacy_sid_to_gid(const DOM_SID *psid, gid_t *pgid)
1232
enum lsa_SidType type;
1234
if ((sid_check_is_in_builtin(psid) ||
1235
sid_check_is_in_wellknown_domain(psid))) {
1239
ret = pdb_getgrsid(&map, *psid);
1246
DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1247
sid_string_dbg(psid)));
1251
if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1255
ret = pdb_sid_to_id(psid, &id, &type);
1259
if ((type != SID_NAME_DOM_GRP) &&
1260
(type != SID_NAME_ALIAS)) {
1261
DEBUG(5, ("LEGACY: sid %s is a %s, expected "
1262
"a group\n", sid_string_dbg(psid),
1263
sid_type_lookup(type)));
1270
/* This was ours, but it was not mapped. Fail */
1273
DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1274
sid_string_dbg(psid)));
1278
DEBUG(10,("LEGACY: sid %s -> gid %u\n", sid_string_dbg(psid),
1279
(unsigned int)*pgid ));
1281
store_gid_sid_cache(psid, *pgid);
1286
/*****************************************************************
1287
*THE CANONICAL* convert uid_t to SID function.
1288
*****************************************************************/
1290
void uid_to_sid(DOM_SID *psid, uid_t uid)
1292
bool expired = true;
1296
if (fetch_sid_from_uid_cache(psid, uid))
1299
/* Check the winbindd cache directly. */
1300
ret = idmap_cache_find_uid2sid(uid, psid, &expired);
1302
if (ret && !expired && is_null_sid(psid)) {
1304
* Negative cache entry, we already asked.
1307
legacy_uid_to_sid(psid, uid);
1311
if (!ret || expired) {
1312
/* Not in cache. Ask winbindd. */
1313
if (!winbind_uid_to_sid(psid, uid)) {
1315
* We shouldn't return the NULL SID
1316
* here if winbind was running and
1317
* couldn't map, as winbind will have
1318
* added a negative entry that will
1319
* cause us to go though the
1320
* legacy_uid_to_sid()
1321
* function anyway in the case above
1322
* the next time we ask.
1324
DEBUG(5, ("uid_to_sid: winbind failed to find a sid "
1325
"for uid %u\n", (unsigned int)uid));
1327
legacy_uid_to_sid(psid, uid);
1332
DEBUG(10,("uid %u -> sid %s\n", (unsigned int)uid,
1333
sid_string_dbg(psid)));
1335
store_uid_sid_cache(psid, uid);
1339
/*****************************************************************
1340
*THE CANONICAL* convert gid_t to SID function.
1341
*****************************************************************/
1343
void gid_to_sid(DOM_SID *psid, gid_t gid)
1345
bool expired = true;
1349
if (fetch_sid_from_gid_cache(psid, gid))
1352
/* Check the winbindd cache directly. */
1353
ret = idmap_cache_find_gid2sid(gid, psid, &expired);
1355
if (ret && !expired && is_null_sid(psid)) {
1357
* Negative cache entry, we already asked.
1360
legacy_gid_to_sid(psid, gid);
1364
if (!ret || expired) {
1365
/* Not in cache. Ask winbindd. */
1366
if (!winbind_gid_to_sid(psid, gid)) {
1368
* We shouldn't return the NULL SID
1369
* here if winbind was running and
1370
* couldn't map, as winbind will have
1371
* added a negative entry that will
1372
* cause us to go though the
1373
* legacy_gid_to_sid()
1374
* function anyway in the case above
1375
* the next time we ask.
1377
DEBUG(5, ("gid_to_sid: winbind failed to find a sid "
1378
"for gid %u\n", (unsigned int)gid));
1380
legacy_gid_to_sid(psid, gid);
1385
DEBUG(10,("gid %u -> sid %s\n", (unsigned int)gid,
1386
sid_string_dbg(psid)));
1388
store_gid_sid_cache(psid, gid);
1392
/*****************************************************************
1393
*THE CANONICAL* convert SID to uid function.
1394
*****************************************************************/
1396
bool sid_to_uid(const DOM_SID *psid, uid_t *puid)
1398
bool expired = true;
1403
if (fetch_uid_from_cache(puid, psid))
1406
if (fetch_gid_from_cache(&gid, psid)) {
1410
/* Optimize for the Unix Users Domain
1411
* as the conversion is straightforward */
1412
if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
1416
/* return here, don't cache */
1417
DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1418
(unsigned int)*puid ));
1422
/* Check the winbindd cache directly. */
1423
ret = idmap_cache_find_sid2uid(psid, puid, &expired);
1425
if (ret && !expired && (*puid == (uid_t)-1)) {
1427
* Negative cache entry, we already asked.
1430
return legacy_sid_to_uid(psid, puid);
1433
if (!ret || expired) {
1434
/* Not in cache. Ask winbindd. */
1435
if (!winbind_sid_to_uid(puid, psid)) {
1436
DEBUG(5, ("winbind failed to find a uid for sid %s\n",
1437
sid_string_dbg(psid)));
1438
/* winbind failed. do legacy */
1439
return legacy_sid_to_uid(psid, puid);
1443
/* TODO: Here would be the place to allocate both a gid and a uid for
1444
* the SID in question */
1446
DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1447
(unsigned int)*puid ));
1449
store_uid_sid_cache(psid, *puid);
1453
/*****************************************************************
1454
*THE CANONICAL* convert SID to gid function.
1455
Group mapping is used for gids that maps to Wellknown SIDs
1456
*****************************************************************/
1458
bool sid_to_gid(const DOM_SID *psid, gid_t *pgid)
1460
bool expired = true;
1465
if (fetch_gid_from_cache(pgid, psid))
1468
if (fetch_uid_from_cache(&uid, psid))
1471
/* Optimize for the Unix Groups Domain
1472
* as the conversion is straightforward */
1473
if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
1477
/* return here, don't cache */
1478
DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1479
(unsigned int)*pgid ));
1483
/* Check the winbindd cache directly. */
1484
ret = idmap_cache_find_sid2gid(psid, pgid, &expired);
1486
if (ret && !expired && (*pgid == (gid_t)-1)) {
1488
* Negative cache entry, we already asked.
1491
return legacy_sid_to_gid(psid, pgid);
1494
if (!ret || expired) {
1495
/* Not in cache or negative. Ask winbindd. */
1496
/* Ask winbindd if it can map this sid to a gid.
1497
* (Idmap will check it is a valid SID and of the right type) */
1499
if ( !winbind_sid_to_gid(pgid, psid) ) {
1501
DEBUG(10,("winbind failed to find a gid for sid %s\n",
1502
sid_string_dbg(psid)));
1503
/* winbind failed. do legacy */
1504
return legacy_sid_to_gid(psid, pgid);
1508
DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1509
(unsigned int)*pgid ));
1511
store_gid_sid_cache(psid, *pgid);