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