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