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