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