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