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