s3-passdb: Respect LOOKUP_NAME_GROUP flag in sid lookup.
[obnox/samba/samba-obnox.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_t 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|LOOKUP_NAME_GROUP)) == 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|LOOKUP_NAME_GROUP)) == 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 winbind default domain name. */
399         if (lp_winbind_use_default_domain()) {
400                 bool ok;
401
402                 qualified_name = talloc_asprintf(mem_ctx,
403                                                  "%s\\%s",
404                                                  lp_workgroup(),
405                                                  full_name);
406                 if (qualified_name == NULL) {
407                         return false;
408                 }
409
410                 ok = lookup_name(mem_ctx,
411                                  qualified_name,
412                                  flags,
413                                  ret_domain,
414                                  ret_name,
415                                  ret_sid,
416                                  ret_type);
417                 if (ok) {
418                         return true;
419                 }
420         }
421
422         /* Try with our own SAM name. */
423         qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
424                                 get_global_sam_name(),
425                                 full_name );
426         if (!qualified_name) {
427                 return false;
428         }
429
430         if (lookup_name(mem_ctx, qualified_name, flags,
431                                 ret_domain, ret_name,
432                                 ret_sid, ret_type)) {
433                 return true;
434         }
435
436         /* Finally try with "Unix Users" or "Unix Group" */
437         qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
438                                 flags & LOOKUP_NAME_GROUP ?
439                                         unix_groups_domain_name() :
440                                         unix_users_domain_name(),
441                                 full_name );
442         if (!qualified_name) {
443                 return false;
444         }
445
446         return lookup_name(mem_ctx, qualified_name, flags,
447                                 ret_domain, ret_name,
448                                 ret_sid, ret_type);
449 }
450
451 static bool wb_lookup_rids(TALLOC_CTX *mem_ctx,
452                            const struct dom_sid *domain_sid,
453                            int num_rids, uint32_t *rids,
454                            const char **domain_name,
455                            const char **names, enum lsa_SidType *types)
456 {
457         int i;
458         const char **my_names;
459         enum lsa_SidType *my_types;
460         TALLOC_CTX *tmp_ctx;
461
462         if (!(tmp_ctx = talloc_init("wb_lookup_rids"))) {
463                 return false;
464         }
465
466         if (!winbind_lookup_rids(tmp_ctx, domain_sid, num_rids, rids,
467                                  domain_name, &my_names, &my_types)) {
468                 *domain_name = "";
469                 for (i=0; i<num_rids; i++) {
470                         names[i] = "";
471                         types[i] = SID_NAME_UNKNOWN;
472                 }
473                 TALLOC_FREE(tmp_ctx);
474                 return true;
475         }
476
477         if (!(*domain_name = talloc_strdup(mem_ctx, *domain_name))) {
478                 TALLOC_FREE(tmp_ctx);
479                 return false;
480         }
481
482         /*
483          * winbind_lookup_rids allocates its own array. We've been given the
484          * array, so copy it over
485          */
486
487         for (i=0; i<num_rids; i++) {
488                 if (my_names[i] == NULL) {
489                         TALLOC_FREE(tmp_ctx);
490                         return false;
491                 }
492                 if (!(names[i] = talloc_strdup(names, my_names[i]))) {
493                         TALLOC_FREE(tmp_ctx);
494                         return false;
495                 }
496                 types[i] = my_types[i];
497         }
498         TALLOC_FREE(tmp_ctx);
499         return true;
500 }
501
502 static bool lookup_rids(TALLOC_CTX *mem_ctx, const struct dom_sid *domain_sid,
503                         int num_rids, uint32_t *rids,
504                         const char **domain_name,
505                         const char ***names, enum lsa_SidType **types)
506 {
507         int i;
508
509         DEBUG(10, ("lookup_rids called for domain sid '%s'\n",
510                    sid_string_dbg(domain_sid)));
511
512         if (num_rids) {
513                 *names = talloc_zero_array(mem_ctx, const char *, num_rids);
514                 *types = talloc_array(mem_ctx, enum lsa_SidType, num_rids);
515
516                 if ((*names == NULL) || (*types == NULL)) {
517                         return false;
518                 }
519
520                 for (i = 0; i < num_rids; i++)
521                         (*types)[i] = SID_NAME_UNKNOWN;
522         } else {
523                 *names = NULL;
524                 *types = NULL;
525         }
526
527         if (sid_check_is_our_sam(domain_sid)) {
528                 NTSTATUS result;
529
530                 if (*domain_name == NULL) {
531                         *domain_name = talloc_strdup(
532                                 mem_ctx, get_global_sam_name());
533                 }
534
535                 if (*domain_name == NULL) {
536                         return false;
537                 }
538
539                 become_root();
540                 result = pdb_lookup_rids(domain_sid, num_rids, rids,
541                                          *names, *types);
542                 unbecome_root();
543
544                 return (NT_STATUS_IS_OK(result) ||
545                         NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
546                         NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
547         }
548
549         if (sid_check_is_builtin(domain_sid)) {
550
551                 if (*domain_name == NULL) {
552                         *domain_name = talloc_strdup(
553                                 mem_ctx, builtin_domain_name());
554                 }
555
556                 if (*domain_name == NULL) {
557                         return false;
558                 }
559
560                 for (i=0; i<num_rids; i++) {
561                         if (lookup_builtin_rid(*names, rids[i],
562                                                &(*names)[i])) {
563                                 if ((*names)[i] == NULL) {
564                                         return false;
565                                 }
566                                 (*types)[i] = SID_NAME_ALIAS;
567                         } else {
568                                 (*types)[i] = SID_NAME_UNKNOWN;
569                         }
570                 }
571                 return true;
572         }
573
574         if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
575                 for (i=0; i<num_rids; i++) {
576                         struct dom_sid sid;
577                         sid_compose(&sid, domain_sid, rids[i]);
578                         if (lookup_wellknown_sid(mem_ctx, &sid,
579                                                  domain_name, &(*names)[i])) {
580                                 if ((*names)[i] == NULL) {
581                                         return false;
582                                 }
583                                 (*types)[i] = SID_NAME_WKN_GRP;
584                         } else {
585                                 (*types)[i] = SID_NAME_UNKNOWN;
586                         }
587                 }
588                 return true;
589         }
590
591         if (sid_check_is_unix_users(domain_sid)) {
592                 if (*domain_name == NULL) {
593                         *domain_name = talloc_strdup(
594                                 mem_ctx, unix_users_domain_name());
595                         if (*domain_name == NULL) {
596                                 return false;
597                         }
598                 }
599                 for (i=0; i<num_rids; i++) {
600                         (*names)[i] = talloc_strdup(
601                                 (*names), uidtoname(rids[i]));
602                         if ((*names)[i] == NULL) {
603                                 return false;
604                         }
605                         (*types)[i] = SID_NAME_USER;
606                 }
607                 return true;
608         }
609
610         if (sid_check_is_unix_groups(domain_sid)) {
611                 if (*domain_name == NULL) {
612                         *domain_name = talloc_strdup(
613                                 mem_ctx, unix_groups_domain_name());
614                         if (*domain_name == NULL) {
615                                 return false;
616                         }
617                 }
618                 for (i=0; i<num_rids; i++) {
619                         (*names)[i] = talloc_strdup(
620                                 (*names), gidtoname(rids[i]));
621                         if ((*names)[i] == NULL) {
622                                 return false;
623                         }
624                         (*types)[i] = SID_NAME_DOM_GRP;
625                 }
626                 return true;
627         }
628
629         return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
630                               domain_name, *names, *types);
631 }
632
633 /*
634  * Is the SID a domain as such? If yes, lookup its name.
635  */
636
637 static bool lookup_as_domain(const struct dom_sid *sid, TALLOC_CTX *mem_ctx,
638                              const char **name)
639 {
640         const char *tmp;
641         enum lsa_SidType type;
642
643         if (sid_check_is_our_sam(sid)) {
644                 *name = talloc_strdup(mem_ctx, get_global_sam_name());
645                 return true;
646         }
647
648         if (sid_check_is_builtin(sid)) {
649                 *name = talloc_strdup(mem_ctx, builtin_domain_name());
650                 return true;
651         }
652
653         if (sid_check_is_wellknown_domain(sid, &tmp)) {
654                 *name = talloc_strdup(mem_ctx, tmp);
655                 return true;
656         }
657
658         if (sid_check_is_unix_users(sid)) {
659                 *name = talloc_strdup(mem_ctx, unix_users_domain_name());
660                 return true;
661         }
662
663         if (sid_check_is_unix_groups(sid)) {
664                 *name = talloc_strdup(mem_ctx, unix_groups_domain_name());
665                 return true;
666         }
667
668         if (sid->num_auths != 4) {
669                 /* This can't be a domain */
670                 return false;
671         }
672
673         if (IS_DC) {
674                 uint32_t i, num_domains;
675                 struct trustdom_info **domains;
676
677                 /* This is relatively expensive, but it happens only on DCs
678                  * and for SIDs that have 4 sub-authorities and thus look like
679                  * domains */
680
681                 if (!NT_STATUS_IS_OK(pdb_enum_trusteddoms(mem_ctx,
682                                                           &num_domains,
683                                                           &domains))) {
684                         return false;
685                 }
686
687                 for (i=0; i<num_domains; i++) {
688                         if (dom_sid_equal(sid, &domains[i]->sid)) {
689                                 *name = talloc_strdup(mem_ctx,
690                                                       domains[i]->name);
691                                 return true;
692                         }
693                 }
694                 return false;
695         }
696
697         if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
698             (type == SID_NAME_DOMAIN)) {
699                 *name = tmp;
700                 return true;
701         }
702
703         return false;
704 }
705
706 /*
707  * This tries to implement the rather weird rules for the lsa_lookup level
708  * parameter.
709  *
710  * This is as close as we can get to what W2k3 does. With this we survive the
711  * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
712  * different, but I assume that's just being too liberal. For example, W2k3
713  * replies to everything else but the levels 1-6 with INVALID_PARAMETER
714  * whereas NT4 does the same as level 1 (I think). I did not fully test that
715  * with NT4, this is what w2k3 does.
716  *
717  * Level 1: Ask everywhere
718  * Level 2: Ask domain and trusted domains, no builtin and wkn
719  * Level 3: Only ask domain
720  * Level 4: W2k3ad: Only ask AD trusts
721  * Level 5: Only ask transitive forest trusts
722  * Level 6: Like 4
723  */
724
725 static bool check_dom_sid_to_level(const struct dom_sid *sid, int level)
726 {
727         int ret = false;
728
729         switch(level) {
730         case 1:
731                 ret = true;
732                 break;
733         case 2:
734                 ret = (!sid_check_is_builtin(sid) &&
735                        !sid_check_is_wellknown_domain(sid, NULL));
736                 break;
737         case 3:
738         case 4:
739         case 6:
740                 ret = sid_check_is_our_sam(sid);
741                 break;
742         case 5:
743                 ret = false;
744                 break;
745         }
746
747         DEBUG(10, ("%s SID %s in level %d\n",
748                    ret ? "Accepting" : "Rejecting",
749                    sid_string_dbg(sid), level));
750         return ret;
751 }
752
753 /*
754  * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
755  * references to domains, it is explicitly made for this.
756  *
757  * This attempts to be as efficient as possible: It collects all SIDs
758  * belonging to a domain and hands them in bulk to the appropriate lookup
759  * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
760  * *hugely* from this.
761  */
762
763 NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
764                      const struct dom_sid **sids, int level,
765                      struct lsa_dom_info **ret_domains,
766                      struct lsa_name_info **ret_names)
767 {
768         TALLOC_CTX *tmp_ctx;
769         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
770         struct lsa_name_info *name_infos;
771         struct lsa_dom_info *dom_infos = NULL;
772
773         int i, j;
774
775         if (!(tmp_ctx = talloc_new(mem_ctx))) {
776                 DEBUG(0, ("talloc_new failed\n"));
777                 return NT_STATUS_NO_MEMORY;
778         }
779
780         if (num_sids) {
781                 name_infos = talloc_array(mem_ctx, struct lsa_name_info, num_sids);
782                 if (name_infos == NULL) {
783                         result = NT_STATUS_NO_MEMORY;
784                         goto fail;
785                 }
786         } else {
787                 name_infos = NULL;
788         }
789
790         dom_infos = talloc_zero_array(mem_ctx, struct lsa_dom_info,
791                                       LSA_REF_DOMAIN_LIST_MULTIPLIER);
792         if (dom_infos == NULL) {
793                 result = NT_STATUS_NO_MEMORY;
794                 goto fail;
795         }
796
797         /* First build up the data structures:
798          * 
799          * dom_infos is a list of domains referenced in the list of
800          * SIDs. Later we will walk the list of domains and look up the RIDs
801          * in bulk.
802          *
803          * name_infos is a shadow-copy of the SIDs array to collect the real
804          * data.
805          *
806          * dom_info->idxs is an index into the name_infos array. The
807          * difficulty we have here is that we need to keep the SIDs the client
808          * asked for in the same order for the reply
809          */
810
811         for (i=0; i<num_sids; i++) {
812                 struct dom_sid sid;
813                 uint32_t rid = 0;
814                 const char *domain_name = NULL;
815
816                 sid_copy(&sid, sids[i]);
817                 name_infos[i].type = SID_NAME_USE_NONE;
818
819                 if (lookup_as_domain(&sid, name_infos, &domain_name)) {
820                         /* We can't push that through the normal lookup
821                          * process, as this would reference illegal
822                          * domains.
823                          *
824                          * For example S-1-5-32 would end up referencing
825                          * domain S-1-5- with RID 32 which is clearly wrong.
826                          */
827                         if (domain_name == NULL) {
828                                 result = NT_STATUS_NO_MEMORY;
829                                 goto fail;
830                         }
831
832                         name_infos[i].rid = 0;
833                         name_infos[i].type = SID_NAME_DOMAIN;
834                         name_infos[i].name = NULL;
835
836                         if (sid_check_is_builtin(&sid)) {
837                                 /* Yes, W2k3 returns "BUILTIN" both as domain
838                                  * and name here */
839                                 name_infos[i].name = talloc_strdup(
840                                         name_infos, builtin_domain_name());
841                                 if (name_infos[i].name == NULL) {
842                                         result = NT_STATUS_NO_MEMORY;
843                                         goto fail;
844                                 }
845                         }
846                 } else {
847                         /* This is a normal SID with rid component */
848                         if (!sid_split_rid(&sid, &rid)) {
849                                 result = NT_STATUS_INVALID_SID;
850                                 goto fail;
851                         }
852                 }
853
854                 if (!check_dom_sid_to_level(&sid, level)) {
855                         name_infos[i].rid = 0;
856                         name_infos[i].type = SID_NAME_UNKNOWN;
857                         name_infos[i].name = NULL;
858                         continue;
859                 }
860
861                 for (j=0; j<LSA_REF_DOMAIN_LIST_MULTIPLIER; j++) {
862                         if (!dom_infos[j].valid) {
863                                 break;
864                         }
865                         if (dom_sid_equal(&sid, &dom_infos[j].sid)) {
866                                 break;
867                         }
868                 }
869
870                 if (j == LSA_REF_DOMAIN_LIST_MULTIPLIER) {
871                         /* TODO: What's the right error message here? */
872                         result = NT_STATUS_NONE_MAPPED;
873                         goto fail;
874                 }
875
876                 if (!dom_infos[j].valid) {
877                         /* We found a domain not yet referenced, create a new
878                          * ref. */
879                         dom_infos[j].valid = true;
880                         sid_copy(&dom_infos[j].sid, &sid);
881
882                         if (domain_name != NULL) {
883                                 /* This name was being found above in the case
884                                  * when we found a domain SID */
885                                 dom_infos[j].name =
886                                         talloc_strdup(dom_infos, domain_name);
887                                 if (dom_infos[j].name == NULL) {
888                                         result = NT_STATUS_NO_MEMORY;
889                                         goto fail;
890                                 }
891                         } else {
892                                 /* lookup_rids will take care of this */
893                                 dom_infos[j].name = NULL;
894                         }
895                 }
896
897                 name_infos[i].dom_idx = j;
898
899                 if (name_infos[i].type == SID_NAME_USE_NONE) {
900                         name_infos[i].rid = rid;
901
902                         ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
903                                      &dom_infos[j].num_idxs);
904
905                         if (dom_infos[j].idxs == NULL) {
906                                 result = NT_STATUS_NO_MEMORY;
907                                 goto fail;
908                         }
909                 }
910         }
911
912         /* Iterate over the domains found */
913
914         for (i=0; i<LSA_REF_DOMAIN_LIST_MULTIPLIER; i++) {
915                 uint32_t *rids;
916                 const char *domain_name = NULL;
917                 const char **names;
918                 enum lsa_SidType *types;
919                 struct lsa_dom_info *dom = &dom_infos[i];
920
921                 if (!dom->valid) {
922                         /* No domains left, we're done */
923                         break;
924                 }
925
926                 if (dom->num_idxs == 0) {
927                         /*
928                          * This happens only if the only sid related to
929                          * this domain is the domain sid itself, which
930                          * is mapped to SID_NAME_DOMAIN above.
931                          */
932                         continue;
933                 }
934
935                 if (!(rids = talloc_array(tmp_ctx, uint32_t, dom->num_idxs))) {
936                         result = NT_STATUS_NO_MEMORY;
937                         goto fail;
938                 }
939
940                 for (j=0; j<dom->num_idxs; j++) {
941                         rids[j] = name_infos[dom->idxs[j]].rid;
942                 }
943
944                 if (!lookup_rids(tmp_ctx, &dom->sid,
945                                  dom->num_idxs, rids, &domain_name,
946                                  &names, &types)) {
947                         result = NT_STATUS_NO_MEMORY;
948                         goto fail;
949                 }
950
951                 if (!(dom->name = talloc_strdup(dom_infos, domain_name))) {
952                         result = NT_STATUS_NO_MEMORY;
953                         goto fail;
954                 }
955
956                 for (j=0; j<dom->num_idxs; j++) {
957                         int idx = dom->idxs[j];
958                         name_infos[idx].type = types[j];
959                         if (types[j] != SID_NAME_UNKNOWN) {
960                                 name_infos[idx].name =
961                                         talloc_strdup(name_infos, names[j]);
962                                 if (name_infos[idx].name == NULL) {
963                                         result = NT_STATUS_NO_MEMORY;
964                                         goto fail;
965                                 }
966                         } else {
967                                 name_infos[idx].name = NULL;
968                         }
969                 }
970         }
971
972         *ret_domains = dom_infos;
973         *ret_names = name_infos;
974         TALLOC_FREE(tmp_ctx);
975         return NT_STATUS_OK;
976
977  fail:
978         TALLOC_FREE(dom_infos);
979         TALLOC_FREE(name_infos);
980         TALLOC_FREE(tmp_ctx);
981         return result;
982 }
983
984 /*****************************************************************
985  *THE CANONICAL* convert SID to name function.
986 *****************************************************************/  
987
988 bool lookup_sid(TALLOC_CTX *mem_ctx, const struct dom_sid *sid,
989                 const char **ret_domain, const char **ret_name,
990                 enum lsa_SidType *ret_type)
991 {
992         struct lsa_dom_info *domain;
993         struct lsa_name_info *name;
994         TALLOC_CTX *tmp_ctx;
995         bool ret = false;
996
997         DEBUG(10, ("lookup_sid called for SID '%s'\n", sid_string_dbg(sid)));
998
999         if (!(tmp_ctx = talloc_new(mem_ctx))) {
1000                 DEBUG(0, ("talloc_new failed\n"));
1001                 return false;
1002         }
1003
1004         if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
1005                                          &domain, &name))) {
1006                 goto done;
1007         }
1008
1009         if (name->type == SID_NAME_UNKNOWN) {
1010                 goto done;
1011         }
1012
1013         if ((ret_domain != NULL) &&
1014             !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
1015                 goto done;
1016         }
1017
1018         if ((ret_name != NULL) && 
1019             !(*ret_name = talloc_strdup(mem_ctx, name->name))) {
1020                 goto done;
1021         }
1022
1023         if (ret_type != NULL) {
1024                 *ret_type = name->type;
1025         }
1026
1027         ret = true;
1028
1029  done:
1030         if (ret) {
1031                 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n", sid_string_dbg(sid),
1032                            domain->name, name->name, name->type));
1033         } else {
1034                 DEBUG(10, ("failed to lookup sid %s\n", sid_string_dbg(sid)));
1035         }
1036         TALLOC_FREE(tmp_ctx);
1037         return ret;
1038 }
1039
1040 /*****************************************************************
1041  Id mapping cache.  This is to avoid Winbind mappings already
1042  seen by smbd to be queried too frequently, keeping winbindd
1043  busy, and blocking smbd while winbindd is busy with other
1044  stuff. Written by Michael Steffens <michael.steffens@hp.com>,
1045  modified to use linked lists by jra.
1046 *****************************************************************/  
1047
1048
1049 /*****************************************************************
1050  *THE LEGACY* convert uid_t to SID function.
1051 *****************************************************************/  
1052
1053 static void legacy_uid_to_sid(struct dom_sid *psid, uid_t uid)
1054 {
1055         bool ret;
1056         struct unixid id;
1057
1058         ZERO_STRUCTP(psid);
1059
1060         id.id = uid;
1061         id.type = ID_TYPE_UID;
1062
1063         become_root();
1064         ret = pdb_id_to_sid(&id, psid);
1065         unbecome_root();
1066
1067         if (ret) {
1068                 /* This is a mapped user */
1069                 goto done;
1070         }
1071
1072         /* This is an unmapped user */
1073
1074         uid_to_unix_users_sid(uid, psid);
1075
1076         {
1077                 struct unixid xid = {
1078                         .id = uid, .type = ID_TYPE_UID
1079                 };
1080                 idmap_cache_set_sid2unixid(psid, &xid);
1081         }
1082
1083  done:
1084         DEBUG(10,("LEGACY: uid %u -> sid %s\n", (unsigned int)uid,
1085                   sid_string_dbg(psid)));
1086
1087         return;
1088 }
1089
1090 /*****************************************************************
1091  *THE LEGACY* convert gid_t to SID function.
1092 *****************************************************************/  
1093
1094 static void legacy_gid_to_sid(struct dom_sid *psid, gid_t gid)
1095 {
1096         bool ret;
1097         struct unixid id;
1098
1099         ZERO_STRUCTP(psid);
1100
1101         id.id = gid;
1102         id.type = ID_TYPE_GID;
1103
1104         become_root();
1105         ret = pdb_id_to_sid(&id, psid);
1106         unbecome_root();
1107
1108         if (ret) {
1109                 /* This is a mapped group */
1110                 goto done;
1111         }
1112
1113         /* This is an unmapped group */
1114
1115         gid_to_unix_groups_sid(gid, psid);
1116
1117         {
1118                 struct unixid xid = {
1119                         .id = gid, .type = ID_TYPE_GID
1120                 };
1121                 idmap_cache_set_sid2unixid(psid, &xid);
1122         }
1123
1124  done:
1125         DEBUG(10,("LEGACY: gid %u -> sid %s\n", (unsigned int)gid,
1126                   sid_string_dbg(psid)));
1127
1128         return;
1129 }
1130
1131 /*****************************************************************
1132  *THE LEGACY* convert SID to id function.
1133 *****************************************************************/  
1134
1135 static bool legacy_sid_to_unixid(const struct dom_sid *psid, struct unixid *id)
1136 {
1137         bool ret;
1138
1139         become_root();
1140         ret = pdb_sid_to_id(psid, id);
1141         unbecome_root();
1142
1143         if (!ret) {
1144                 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1145                           sid_string_dbg(psid)));
1146                 return false;
1147         }
1148
1149         return true;
1150 }
1151
1152 static bool legacy_sid_to_gid(const struct dom_sid *psid, gid_t *pgid)
1153 {
1154         struct unixid id;
1155         if (!legacy_sid_to_unixid(psid, &id)) {
1156                 return false;
1157         }
1158         if (id.type == ID_TYPE_GID || id.type == ID_TYPE_BOTH) {
1159                 *pgid = id.id;
1160                 return true;
1161         }
1162         return false;
1163 }
1164
1165 static bool legacy_sid_to_uid(const struct dom_sid *psid, uid_t *puid)
1166 {
1167         struct unixid id;
1168         if (!legacy_sid_to_unixid(psid, &id)) {
1169                 return false;
1170         }
1171         if (id.type == ID_TYPE_UID || id.type == ID_TYPE_BOTH) {
1172                 *puid = id.id;
1173                 return true;
1174         }
1175         return false;
1176 }
1177
1178 /*****************************************************************
1179  *THE CANONICAL* convert uid_t to SID function.
1180 *****************************************************************/  
1181
1182 void uid_to_sid(struct dom_sid *psid, uid_t uid)
1183 {
1184         bool expired = true;
1185         bool ret;
1186         ZERO_STRUCTP(psid);
1187
1188         /* Check the winbindd cache directly. */
1189         ret = idmap_cache_find_uid2sid(uid, psid, &expired);
1190
1191         if (ret && !expired && is_null_sid(psid)) {
1192                 /*
1193                  * Negative cache entry, we already asked.
1194                  * do legacy.
1195                  */
1196                 legacy_uid_to_sid(psid, uid);
1197                 return;
1198         }
1199
1200         if (!ret || expired) {
1201                 /* Not in cache. Ask winbindd. */
1202                 if (!winbind_uid_to_sid(psid, uid)) {
1203                         /*
1204                          * We shouldn't return the NULL SID
1205                          * here if winbind was running and
1206                          * couldn't map, as winbind will have
1207                          * added a negative entry that will
1208                          * cause us to go though the
1209                          * legacy_uid_to_sid()
1210                          * function anyway in the case above
1211                          * the next time we ask.
1212                          */
1213                         DEBUG(5, ("uid_to_sid: winbind failed to find a sid "
1214                                   "for uid %u\n", (unsigned int)uid));
1215
1216                         legacy_uid_to_sid(psid, uid);
1217                         return;
1218                 }
1219         }
1220
1221         DEBUG(10,("uid %u -> sid %s\n", (unsigned int)uid,
1222                   sid_string_dbg(psid)));
1223
1224         return;
1225 }
1226
1227 /*****************************************************************
1228  *THE CANONICAL* convert gid_t to SID function.
1229 *****************************************************************/  
1230
1231 void gid_to_sid(struct dom_sid *psid, gid_t gid)
1232 {
1233         bool expired = true;
1234         bool ret;
1235         ZERO_STRUCTP(psid);
1236
1237         /* Check the winbindd cache directly. */
1238         ret = idmap_cache_find_gid2sid(gid, psid, &expired);
1239
1240         if (ret && !expired && is_null_sid(psid)) {
1241                 /*
1242                  * Negative cache entry, we already asked.
1243                  * do legacy.
1244                  */
1245                 legacy_gid_to_sid(psid, gid);
1246                 return;
1247         }
1248
1249         if (!ret || expired) {
1250                 /* Not in cache. Ask winbindd. */
1251                 if (!winbind_gid_to_sid(psid, gid)) {
1252                         /*
1253                          * We shouldn't return the NULL SID
1254                          * here if winbind was running and
1255                          * couldn't map, as winbind will have
1256                          * added a negative entry that will
1257                          * cause us to go though the
1258                          * legacy_gid_to_sid()
1259                          * function anyway in the case above
1260                          * the next time we ask.
1261                          */
1262                         DEBUG(5, ("gid_to_sid: winbind failed to find a sid "
1263                                   "for gid %u\n", (unsigned int)gid));
1264
1265                         legacy_gid_to_sid(psid, gid);
1266                         return;
1267                 }
1268         }
1269
1270         DEBUG(10,("gid %u -> sid %s\n", (unsigned int)gid,
1271                   sid_string_dbg(psid)));
1272
1273         return;
1274 }
1275
1276 bool sids_to_unixids(const struct dom_sid *sids, uint32_t num_sids,
1277                      struct unixid *ids)
1278 {
1279         struct wbcDomainSid *wbc_sids = NULL;
1280         struct wbcUnixId *wbc_ids = NULL;
1281         uint32_t i, num_not_cached;
1282         wbcErr err;
1283         bool ret = false;
1284
1285         wbc_sids = talloc_array(talloc_tos(), struct wbcDomainSid, num_sids);
1286         if (wbc_sids == NULL) {
1287                 return false;
1288         }
1289
1290         num_not_cached = 0;
1291
1292         for (i=0; i<num_sids; i++) {
1293                 bool expired;
1294                 uint32_t rid;
1295
1296                 if (sid_peek_check_rid(&global_sid_Unix_Users,
1297                                        &sids[i], &rid)) {
1298                         ids[i].type = ID_TYPE_UID;
1299                         ids[i].id = rid;
1300                         continue;
1301                 }
1302                 if (sid_peek_check_rid(&global_sid_Unix_Groups,
1303                                        &sids[i], &rid)) {
1304                         ids[i].type = ID_TYPE_GID;
1305                         ids[i].id = rid;
1306                         continue;
1307                 }
1308                 if (idmap_cache_find_sid2unixid(&sids[i], &ids[i], &expired)
1309                     && !expired)
1310                 {
1311                         continue;
1312                 }
1313                 ids[i].type = ID_TYPE_NOT_SPECIFIED;
1314                 memcpy(&wbc_sids[num_not_cached], &sids[i],
1315                        ndr_size_dom_sid(&sids[i], 0));
1316                 num_not_cached += 1;
1317         }
1318         if (num_not_cached == 0) {
1319                 goto done;
1320         }
1321         wbc_ids = talloc_array(talloc_tos(), struct wbcUnixId, num_not_cached);
1322         if (wbc_ids == NULL) {
1323                 goto fail;
1324         }
1325         for (i=0; i<num_not_cached; i++) {
1326                 wbc_ids[i].type = WBC_ID_TYPE_NOT_SPECIFIED;
1327         }
1328         err = wbcSidsToUnixIds(wbc_sids, num_not_cached, wbc_ids);
1329         if (!WBC_ERROR_IS_OK(err)) {
1330                 DEBUG(10, ("wbcSidsToUnixIds returned %s\n",
1331                            wbcErrorString(err)));
1332         }
1333
1334         num_not_cached = 0;
1335
1336         for (i=0; i<num_sids; i++) {
1337                 if (ids[i].type == ID_TYPE_NOT_SPECIFIED) {
1338                         switch (wbc_ids[num_not_cached].type) {
1339                         case WBC_ID_TYPE_UID:
1340                                 ids[i].type = ID_TYPE_UID;
1341                                 ids[i].id = wbc_ids[num_not_cached].id.uid;
1342                                 break;
1343                         case WBC_ID_TYPE_GID:
1344                                 ids[i].type = ID_TYPE_GID;
1345                                 ids[i].id = wbc_ids[num_not_cached].id.gid;
1346                                 break;
1347                         default:
1348                                 /* The types match, and wbcUnixId -> id is a union anyway */
1349                                 ids[i].type = (enum id_type)wbc_ids[num_not_cached].type;
1350                                 ids[i].id = wbc_ids[num_not_cached].id.gid;
1351                                 break;
1352                         }
1353                         num_not_cached += 1;
1354                 }
1355         }
1356
1357         for (i=0; i<num_sids; i++) {
1358                 if (ids[i].type != ID_TYPE_NOT_SPECIFIED) {
1359                         continue;
1360                 }
1361                 if (legacy_sid_to_gid(&sids[i], &ids[i].id)) {
1362                         ids[i].type = ID_TYPE_GID;
1363                         continue;
1364                 }
1365                 if (legacy_sid_to_uid(&sids[i], &ids[i].id)) {
1366                         ids[i].type = ID_TYPE_UID;
1367                         continue;
1368                 }
1369         }
1370 done:
1371         for (i=0; i<num_sids; i++) {
1372                 switch(ids[i].type) {
1373                 case WBC_ID_TYPE_GID:
1374                 case WBC_ID_TYPE_UID:
1375                 case WBC_ID_TYPE_BOTH:
1376                         if (ids[i].id == -1) {
1377                                 ids[i].type = ID_TYPE_NOT_SPECIFIED;
1378                         }
1379                         break;
1380                 case WBC_ID_TYPE_NOT_SPECIFIED:
1381                         break;
1382                 }
1383         }
1384
1385         ret = true;
1386 fail:
1387         TALLOC_FREE(wbc_ids);
1388         TALLOC_FREE(wbc_sids);
1389         return ret;
1390 }
1391
1392 /*****************************************************************
1393  *THE CANONICAL* convert SID to uid function.
1394 *****************************************************************/  
1395
1396 bool sid_to_uid(const struct dom_sid *psid, uid_t *puid)
1397 {
1398         bool expired = true;
1399         bool ret;
1400         uint32_t rid;
1401
1402         /* Optimize for the Unix Users Domain
1403          * as the conversion is straightforward */
1404         if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
1405                 uid_t uid = rid;
1406                 *puid = uid;
1407
1408                 /* return here, don't cache */
1409                 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1410                         (unsigned int)*puid ));
1411                 return true;
1412         }
1413
1414         /* Check the winbindd cache directly. */
1415         ret = idmap_cache_find_sid2uid(psid, puid, &expired);
1416
1417         if (ret && !expired && (*puid == (uid_t)-1)) {
1418                 /*
1419                  * Negative cache entry, we already asked.
1420                  * do legacy.
1421                  */
1422                 return legacy_sid_to_uid(psid, puid);
1423         }
1424
1425         if (!ret || expired) {
1426                 /* Not in cache. Ask winbindd. */
1427                 if (!winbind_sid_to_uid(puid, psid)) {
1428                         DEBUG(5, ("winbind failed to find a uid for sid %s\n",
1429                                   sid_string_dbg(psid)));
1430                         /* winbind failed. do legacy */
1431                         return legacy_sid_to_uid(psid, puid);
1432                 }
1433         }
1434
1435         /* TODO: Here would be the place to allocate both a gid and a uid for
1436          * the SID in question */
1437
1438         DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1439                 (unsigned int)*puid ));
1440
1441         return true;
1442 }
1443
1444 /*****************************************************************
1445  *THE CANONICAL* convert SID to gid function.
1446  Group mapping is used for gids that maps to Wellknown SIDs
1447 *****************************************************************/  
1448
1449 bool sid_to_gid(const struct dom_sid *psid, gid_t *pgid)
1450 {
1451         bool expired = true;
1452         bool ret;
1453         uint32_t rid;
1454
1455         /* Optimize for the Unix Groups Domain
1456          * as the conversion is straightforward */
1457         if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
1458                 gid_t gid = rid;
1459                 *pgid = gid;
1460
1461                 /* return here, don't cache */
1462                 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1463                         (unsigned int)*pgid ));
1464                 return true;
1465         }
1466
1467         /* Check the winbindd cache directly. */
1468         ret = idmap_cache_find_sid2gid(psid, pgid, &expired);
1469
1470         if (ret && !expired && (*pgid == (gid_t)-1)) {
1471                 /*
1472                  * Negative cache entry, we already asked.
1473                  * do legacy.
1474                  */
1475                 return legacy_sid_to_gid(psid, pgid);
1476         }
1477
1478         if (!ret || expired) {
1479                 /* Not in cache or negative. Ask winbindd. */
1480                 /* Ask winbindd if it can map this sid to a gid.
1481                  * (Idmap will check it is a valid SID and of the right type) */
1482
1483                 if ( !winbind_sid_to_gid(pgid, psid) ) {
1484
1485                         DEBUG(10,("winbind failed to find a gid for sid %s\n",
1486                                   sid_string_dbg(psid)));
1487                         /* winbind failed. do legacy */
1488                         return legacy_sid_to_gid(psid, pgid);
1489                 }
1490         }
1491
1492         DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1493                   (unsigned int)*pgid ));
1494
1495         return true;
1496 }
1497
1498 /**
1499  * @brief This function gets the primary group SID mapping the primary
1500  *        GID of the user as obtained by an actual getpwnam() call.
1501  *        This is necessary to avoid issues with arbitrary group SIDs
1502  *        stored in passdb. We try as hard as we can to get the SID
1503  *        corresponding to the GID, including trying group mapping.
1504  *        If nothing else works, we will force "Domain Users" as the
1505  *        primary group.
1506  *        This is needed because we must always be able to lookup the
1507  *        primary group SID, so we cannot settle for an arbitrary SID.
1508  *
1509  *        This call can be expensive. Use with moderation.
1510  *        If you have a "samu" struct around use pdb_get_group_sid()
1511  *        instead as it does properly cache results.
1512  *
1513  * @param mem_ctx[in]     The memory context iused to allocate the result.
1514  * @param username[in]    The user's name
1515  * @param _pwd[in|out]    If available, pass in user's passwd struct.
1516  *                        It will contain a tallocated passwd if NULL was
1517  *                        passed in.
1518  * @param _group_sid[out] The user's Primary Group SID
1519  *
1520  * @return NTSTATUS error code.
1521  */
1522 NTSTATUS get_primary_group_sid(TALLOC_CTX *mem_ctx,
1523                                 const char *username,
1524                                 struct passwd **_pwd,
1525                                 struct dom_sid **_group_sid)
1526 {
1527         TALLOC_CTX *tmp_ctx;
1528         bool need_lookup_sid = false;
1529         struct dom_sid *group_sid;
1530         struct passwd *pwd = *_pwd;
1531
1532         tmp_ctx = talloc_new(mem_ctx);
1533         if (!tmp_ctx) {
1534                 return NT_STATUS_NO_MEMORY;
1535         }
1536
1537         if (!pwd) {
1538                 pwd = Get_Pwnam_alloc(mem_ctx, username);
1539                 if (!pwd) {
1540                         DEBUG(0, ("Failed to find a Unix account for %s\n",
1541                                   username));
1542                         TALLOC_FREE(tmp_ctx);
1543                         return NT_STATUS_NO_SUCH_USER;
1544                 }
1545         }
1546
1547         group_sid = talloc_zero(mem_ctx, struct dom_sid);
1548         if (!group_sid) {
1549                 TALLOC_FREE(tmp_ctx);
1550                 return NT_STATUS_NO_MEMORY;
1551         }
1552
1553         gid_to_sid(group_sid, pwd->pw_gid);
1554         if (!is_null_sid(group_sid)) {
1555                 struct dom_sid domain_sid;
1556                 uint32_t rid;
1557
1558                 /* We need a sid within our domain */
1559                 sid_copy(&domain_sid, group_sid);
1560                 sid_split_rid(&domain_sid, &rid);
1561                 if (dom_sid_equal(&domain_sid, get_global_sam_sid())) {
1562                         /*
1563                          * As shortcut for the expensive lookup_sid call
1564                          * compare the domain sid part
1565                          */
1566                         switch (rid) {
1567                         case DOMAIN_RID_ADMINS:
1568                         case DOMAIN_RID_USERS:
1569                                 goto done;
1570                         default:
1571                                 need_lookup_sid = true;
1572                                 break;
1573                         }
1574                 } else {
1575                         /* Try group mapping */
1576                         struct unixid id;
1577
1578                         id.id = pwd->pw_gid;
1579                         id.type = ID_TYPE_GID;
1580
1581                         ZERO_STRUCTP(group_sid);
1582                         if (pdb_id_to_sid(&id, group_sid)) {
1583                                 need_lookup_sid = true;
1584                         }
1585                 }
1586         }
1587
1588         /* We must verify that this is a valid SID that resolves to a
1589          * group of the correct type */
1590         if (need_lookup_sid) {
1591                 enum lsa_SidType type = SID_NAME_UNKNOWN;
1592                 bool lookup_ret;
1593
1594                 DEBUG(10, ("do lookup_sid(%s) for group of user %s\n",
1595                            sid_string_dbg(group_sid), username));
1596
1597                 /* Now check that it's actually a domain group and
1598                  * not something else */
1599                 lookup_ret = lookup_sid(tmp_ctx, group_sid,
1600                                         NULL, NULL, &type);
1601
1602                 if (lookup_ret && (type == SID_NAME_DOM_GRP)) {
1603                         goto done;
1604                 }
1605
1606                 DEBUG(3, ("Primary group %s for user %s is"
1607                           " a %s and not a domain group\n",
1608                           sid_string_dbg(group_sid), username,
1609                           sid_type_lookup(type)));
1610         }
1611
1612         /* Everything else, failed.
1613          * Just set it to the 'Domain Users' RID of 513 which will
1614            always resolve to a name */
1615         DEBUG(3, ("Forcing Primary Group to 'Domain Users' for %s\n",
1616                   username));
1617
1618         sid_compose(group_sid, get_global_sam_sid(), DOMAIN_RID_USERS);
1619
1620 done:
1621         *_pwd = talloc_move(mem_ctx, &pwd);
1622         *_group_sid = talloc_move(mem_ctx, &group_sid);
1623         TALLOC_FREE(tmp_ctx);
1624         return NT_STATUS_OK;
1625 }
1626