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