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