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