~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/passdb/lookup_sid.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

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