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