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