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