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