RIP BOOL. Convert BOOL -> bool. I found a few interesting
[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_static(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         return NT_STATUS_OK;
884
885  fail:
886         TALLOC_FREE(dom_infos);
887         TALLOC_FREE(name_infos);
888         TALLOC_FREE(tmp_ctx);
889         return result;
890 }
891
892 /*****************************************************************
893  *THE CANONICAL* convert SID to name function.
894 *****************************************************************/  
895
896 bool lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
897                 const char **ret_domain, const char **ret_name,
898                 enum lsa_SidType *ret_type)
899 {
900         struct lsa_dom_info *domain;
901         struct lsa_name_info *name;
902         TALLOC_CTX *tmp_ctx;
903         bool ret = False;
904
905         if (!(tmp_ctx = talloc_new(mem_ctx))) {
906                 DEBUG(0, ("talloc_new failed\n"));
907                 return False;
908         }
909
910         if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
911                                          &domain, &name))) {
912                 goto done;
913         }
914
915         if (name->type == SID_NAME_UNKNOWN) {
916                 goto done;
917         }
918
919         if ((ret_domain != NULL) &&
920             !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
921                 goto done;
922         }
923
924         if ((ret_name != NULL) && 
925             !(*ret_name = talloc_strdup(mem_ctx, name->name))) {
926                 goto done;
927         }
928
929         if (ret_type != NULL) {
930                 *ret_type = name->type;
931         }
932
933         ret = True;
934
935  done:
936         if (ret) {
937                 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n",
938                            sid_string_static(sid), domain->name,
939                            name->name, name->type));
940         } else {
941                 DEBUG(10, ("failed to lookup sid %s\n",
942                            sid_string_static(sid)));
943         }
944         TALLOC_FREE(tmp_ctx);
945         return ret;
946 }
947
948 /*****************************************************************
949  Id mapping cache.  This is to avoid Winbind mappings already
950  seen by smbd to be queried too frequently, keeping winbindd
951  busy, and blocking smbd while winbindd is busy with other
952  stuff. Written by Michael Steffens <michael.steffens@hp.com>,
953  modified to use linked lists by jra.
954 *****************************************************************/  
955
956 #define MAX_UID_SID_CACHE_SIZE 100
957 #define TURNOVER_UID_SID_CACHE_SIZE 10
958 #define MAX_GID_SID_CACHE_SIZE 100
959 #define TURNOVER_GID_SID_CACHE_SIZE 10
960
961 static size_t n_uid_sid_cache = 0;
962 static size_t n_gid_sid_cache = 0;
963
964 static struct uid_sid_cache {
965         struct uid_sid_cache *next, *prev;
966         uid_t uid;
967         DOM_SID sid;
968         enum lsa_SidType sidtype;
969 } *uid_sid_cache_head;
970
971 static struct gid_sid_cache {
972         struct gid_sid_cache *next, *prev;
973         gid_t gid;
974         DOM_SID sid;
975         enum lsa_SidType sidtype;
976 } *gid_sid_cache_head;
977
978 /*****************************************************************
979   Find a SID given a uid.
980 *****************************************************************/  
981
982 static bool fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid)
983 {
984         struct uid_sid_cache *pc;
985
986         for (pc = uid_sid_cache_head; pc; pc = pc->next) {
987                 if (pc->uid == uid) {
988                         *psid = pc->sid;
989                         DEBUG(3,("fetch sid from uid cache %u -> %s\n",
990                                  (unsigned int)uid, sid_string_static(psid)));
991                         DLIST_PROMOTE(uid_sid_cache_head, pc);
992                         return True;
993                 }
994         }
995         return False;
996 }
997
998 /*****************************************************************
999   Find a uid given a SID.
1000 *****************************************************************/  
1001
1002 static bool fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid )
1003 {
1004         struct uid_sid_cache *pc;
1005
1006         for (pc = uid_sid_cache_head; pc; pc = pc->next) {
1007                 if (sid_compare(&pc->sid, psid) == 0) {
1008                         *puid = pc->uid;
1009                         DEBUG(3,("fetch uid from cache %u -> %s\n",
1010                                  (unsigned int)*puid, sid_string_static(psid)));
1011                         DLIST_PROMOTE(uid_sid_cache_head, pc);
1012                         return True;
1013                 }
1014         }
1015         return False;
1016 }
1017
1018 /*****************************************************************
1019  Store uid to SID mapping in cache.
1020 *****************************************************************/  
1021
1022 void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
1023 {
1024         struct uid_sid_cache *pc;
1025
1026         /* do not store SIDs in the "Unix Group" domain */
1027         
1028         if ( sid_check_is_in_unix_users( psid ) )
1029                 return;
1030
1031         if (n_uid_sid_cache >= MAX_UID_SID_CACHE_SIZE && n_uid_sid_cache > TURNOVER_UID_SID_CACHE_SIZE) {
1032                 /* Delete the last TURNOVER_UID_SID_CACHE_SIZE entries. */
1033                 struct uid_sid_cache *pc_next;
1034                 size_t i;
1035
1036                 for (i = 0, pc = uid_sid_cache_head; i < (n_uid_sid_cache - TURNOVER_UID_SID_CACHE_SIZE); i++, pc = pc->next)
1037                         ;
1038                 for(; pc; pc = pc_next) {
1039                         pc_next = pc->next;
1040                         DLIST_REMOVE(uid_sid_cache_head,pc);
1041                         SAFE_FREE(pc);
1042                         n_uid_sid_cache--;
1043                 }
1044         }
1045
1046         pc = SMB_MALLOC_P(struct uid_sid_cache);
1047         if (!pc)
1048                 return;
1049         pc->uid = uid;
1050         sid_copy(&pc->sid, psid);
1051         DLIST_ADD(uid_sid_cache_head, pc);
1052         n_uid_sid_cache++;
1053 }
1054
1055 /*****************************************************************
1056   Find a SID given a gid.
1057 *****************************************************************/  
1058
1059 static bool fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid)
1060 {
1061         struct gid_sid_cache *pc;
1062
1063         for (pc = gid_sid_cache_head; pc; pc = pc->next) {
1064                 if (pc->gid == gid) {
1065                         *psid = pc->sid;
1066                         DEBUG(3,("fetch sid from gid cache %u -> %s\n",
1067                                  (unsigned int)gid, sid_string_static(psid)));
1068                         DLIST_PROMOTE(gid_sid_cache_head, pc);
1069                         return True;
1070                 }
1071         }
1072         return False;
1073 }
1074
1075 /*****************************************************************
1076   Find a gid given a SID.
1077 *****************************************************************/  
1078
1079 static bool fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid)
1080 {
1081         struct gid_sid_cache *pc;
1082
1083         for (pc = gid_sid_cache_head; pc; pc = pc->next) {
1084                 if (sid_compare(&pc->sid, psid) == 0) {
1085                         *pgid = pc->gid;
1086                         DEBUG(3,("fetch gid from cache %u -> %s\n",
1087                                  (unsigned int)*pgid, sid_string_static(psid)));
1088                         DLIST_PROMOTE(gid_sid_cache_head, pc);
1089                         return True;
1090                 }
1091         }
1092         return False;
1093 }
1094
1095 /*****************************************************************
1096  Store gid to SID mapping in cache.
1097 *****************************************************************/  
1098
1099 void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
1100 {
1101         struct gid_sid_cache *pc;
1102         
1103         /* do not store SIDs in the "Unix Group" domain */
1104         
1105         if ( sid_check_is_in_unix_groups( psid ) )
1106                 return;
1107
1108         if (n_gid_sid_cache >= MAX_GID_SID_CACHE_SIZE && n_gid_sid_cache > TURNOVER_GID_SID_CACHE_SIZE) {
1109                 /* Delete the last TURNOVER_GID_SID_CACHE_SIZE entries. */
1110                 struct gid_sid_cache *pc_next;
1111                 size_t i;
1112
1113                 for (i = 0, pc = gid_sid_cache_head; i < (n_gid_sid_cache - TURNOVER_GID_SID_CACHE_SIZE); i++, pc = pc->next)
1114                         ;
1115                 for(; pc; pc = pc_next) {
1116                         pc_next = pc->next;
1117                         DLIST_REMOVE(gid_sid_cache_head,pc);
1118                         SAFE_FREE(pc);
1119                         n_gid_sid_cache--;
1120                 }
1121         }
1122
1123         pc = SMB_MALLOC_P(struct gid_sid_cache);
1124         if (!pc)
1125                 return;
1126         pc->gid = gid;
1127         sid_copy(&pc->sid, psid);
1128         DLIST_ADD(gid_sid_cache_head, pc);
1129
1130         DEBUG(3,("store_gid_sid_cache: gid %u in cache -> %s\n", (unsigned int)gid,
1131                 sid_string_static(psid)));
1132
1133         n_gid_sid_cache++;
1134 }
1135
1136 /*****************************************************************
1137  *THE LEGACY* convert uid_t to SID function.
1138 *****************************************************************/  
1139
1140 static void legacy_uid_to_sid(DOM_SID *psid, uid_t uid)
1141 {
1142         uint32 rid;
1143         bool ret;
1144
1145         ZERO_STRUCTP(psid);
1146
1147         become_root();
1148         ret = pdb_uid_to_rid(uid, &rid);
1149         unbecome_root();
1150
1151         if (ret) {
1152                 /* This is a mapped user */
1153                 sid_copy(psid, get_global_sam_sid());
1154                 sid_append_rid(psid, rid);
1155                 goto done;
1156         }
1157
1158         /* This is an unmapped user */
1159
1160         uid_to_unix_users_sid(uid, psid);
1161
1162  done:
1163         DEBUG(10,("LEGACY: uid %u -> sid %s\n", (unsigned int)uid,
1164                   sid_string_static(psid)));
1165
1166         store_uid_sid_cache(psid, uid);
1167         return;
1168 }
1169
1170 /*****************************************************************
1171  *THE LEGACY* convert gid_t to SID function.
1172 *****************************************************************/  
1173
1174 static void legacy_gid_to_sid(DOM_SID *psid, gid_t gid)
1175 {
1176         bool ret;
1177
1178         ZERO_STRUCTP(psid);
1179
1180         become_root();
1181         ret = pdb_gid_to_sid(gid, psid);
1182         unbecome_root();
1183
1184         if (ret) {
1185                 /* This is a mapped group */
1186                 goto done;
1187         }
1188         
1189         /* This is an unmapped group */
1190
1191         gid_to_unix_groups_sid(gid, psid);
1192
1193  done:
1194         DEBUG(10,("LEGACY: gid %u -> sid %s\n", (unsigned int)gid,
1195                   sid_string_static(psid)));
1196
1197         store_gid_sid_cache(psid, gid);
1198         return;
1199 }
1200
1201 /*****************************************************************
1202  *THE LEGACY* convert SID to uid function.
1203 *****************************************************************/  
1204
1205 static bool legacy_sid_to_uid(const DOM_SID *psid, uid_t *puid)
1206 {
1207         enum lsa_SidType type;
1208         uint32 rid;
1209
1210         if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1211                 union unid_t id;
1212                 bool ret;
1213
1214                 become_root();
1215                 ret = pdb_sid_to_id(psid, &id, &type);
1216                 unbecome_root();
1217
1218                 if (ret) {
1219                         if (type != SID_NAME_USER) {
1220                                 DEBUG(5, ("sid %s is a %s, expected a user\n",
1221                                           sid_string_static(psid),
1222                                           sid_type_lookup(type)));
1223                                 return False;
1224                         }
1225                         *puid = id.uid;
1226                         goto done;
1227                 }
1228
1229                 /* This was ours, but it was not mapped.  Fail */
1230         }
1231
1232         DEBUG(10,("LEGACY: mapping failed for sid %s\n", sid_string_static(psid)));
1233         return False;
1234
1235 done:
1236         DEBUG(10,("LEGACY: sid %s -> uid %u\n", sid_string_static(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", sid_string_static(psid)));
1268                 return False;
1269         }
1270
1271         if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1272                 bool ret;
1273
1274                 become_root();
1275                 ret = pdb_sid_to_id(psid, &id, &type);
1276                 unbecome_root();
1277
1278                 if (ret) {
1279                         if ((type != SID_NAME_DOM_GRP) &&
1280                             (type != SID_NAME_ALIAS)) {
1281                                 DEBUG(5, ("LEGACY: sid %s is a %s, expected a group\n",
1282                                           sid_string_static(psid),
1283                                           sid_type_lookup(type)));
1284                                 return False;
1285                         }
1286                         *pgid = id.gid;
1287                         goto done;
1288                 }
1289         
1290                 /* This was ours, but it was not mapped.  Fail */
1291         }
1292
1293         DEBUG(10,("LEGACY: mapping failed for sid %s\n", sid_string_static(psid)));
1294         return False;
1295         
1296  done:
1297         DEBUG(10,("LEGACY: sid %s -> gid %u\n", sid_string_static(psid),
1298                   (unsigned int)*pgid ));
1299
1300         store_gid_sid_cache(psid, *pgid);
1301
1302         return True;
1303 }
1304
1305 /*****************************************************************
1306  *THE CANONICAL* convert uid_t to SID function.
1307 *****************************************************************/  
1308
1309 void uid_to_sid(DOM_SID *psid, uid_t uid)
1310 {
1311         ZERO_STRUCTP(psid);
1312
1313         if (fetch_sid_from_uid_cache(psid, uid))
1314                 return;
1315
1316         if (!winbind_uid_to_sid(psid, uid)) {
1317                 if (!winbind_ping()) {
1318                         legacy_uid_to_sid(psid, uid);
1319                         return;
1320                 }
1321
1322                 DEBUG(5, ("uid_to_sid: winbind failed to find a sid for uid %u\n",
1323                         uid));
1324                 return;
1325         }
1326
1327         DEBUG(10,("uid %u -> sid %s\n",
1328                   (unsigned int)uid, sid_string_static(psid)));
1329
1330         store_uid_sid_cache(psid, uid);
1331         return;
1332 }
1333
1334 /*****************************************************************
1335  *THE CANONICAL* convert gid_t to SID function.
1336 *****************************************************************/  
1337
1338 void gid_to_sid(DOM_SID *psid, gid_t gid)
1339 {
1340         ZERO_STRUCTP(psid);
1341
1342         if (fetch_sid_from_gid_cache(psid, gid))
1343                 return;
1344
1345         if (!winbind_gid_to_sid(psid, gid)) {
1346                 if (!winbind_ping()) {
1347                         legacy_gid_to_sid(psid, gid);
1348                         return;
1349                 }
1350
1351                 DEBUG(5, ("gid_to_sid: winbind failed to find a sid for gid %u\n",
1352                         gid));
1353                 return;
1354         }
1355
1356         DEBUG(10,("gid %u -> sid %s\n",
1357                   (unsigned int)gid, sid_string_static(psid)));
1358         
1359         store_gid_sid_cache(psid, gid);
1360         return;
1361 }
1362
1363 /*****************************************************************
1364  *THE CANONICAL* convert SID to uid function.
1365 *****************************************************************/  
1366
1367 bool sid_to_uid(const DOM_SID *psid, uid_t *puid)
1368 {
1369         uint32 rid;
1370         gid_t gid;
1371
1372         if (fetch_uid_from_cache(puid, psid))
1373                 return True;
1374
1375         if (fetch_gid_from_cache(&gid, psid)) {
1376                 return False;
1377         }
1378
1379         /* Optimize for the Unix Users Domain
1380          * as the conversion is straightforward */
1381         if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
1382                 uid_t uid = rid;
1383                 *puid = uid;
1384
1385                 /* return here, don't cache */
1386                 DEBUG(10,("sid %s -> uid %u\n", sid_string_static(psid),
1387                         (unsigned int)*puid ));
1388                 return True;
1389         }
1390
1391         if (!winbind_sid_to_uid(puid, psid)) {
1392                 if (!winbind_ping()) {
1393                         return legacy_sid_to_uid(psid, puid);
1394                 }
1395
1396                 DEBUG(5, ("winbind failed to find a uid for sid %s\n",
1397                           sid_string_static(psid)));
1398                 return False;
1399         }
1400
1401         /* TODO: Here would be the place to allocate both a gid and a uid for
1402          * the SID in question */
1403
1404         DEBUG(10,("sid %s -> uid %u\n", sid_string_static(psid),
1405                 (unsigned int)*puid ));
1406
1407         store_uid_sid_cache(psid, *puid);
1408         return True;
1409 }
1410
1411 /*****************************************************************
1412  *THE CANONICAL* convert SID to gid function.
1413  Group mapping is used for gids that maps to Wellknown SIDs
1414 *****************************************************************/  
1415
1416 bool sid_to_gid(const DOM_SID *psid, gid_t *pgid)
1417 {
1418         uint32 rid;
1419         uid_t uid;
1420
1421         if (fetch_gid_from_cache(pgid, psid))
1422                 return True;
1423
1424         if (fetch_uid_from_cache(&uid, psid))
1425                 return False;
1426
1427         /* Optimize for the Unix Groups Domain
1428          * as the conversion is straightforward */
1429         if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
1430                 gid_t gid = rid;
1431                 *pgid = gid;
1432
1433                 /* return here, don't cache */
1434                 DEBUG(10,("sid %s -> gid %u\n", sid_string_static(psid),
1435                         (unsigned int)*pgid ));
1436                 return True;
1437         }
1438
1439         /* Ask winbindd if it can map this sid to a gid.
1440          * (Idmap will check it is a valid SID and of the right type) */
1441
1442         if ( !winbind_sid_to_gid(pgid, psid) ) {
1443                 if (!winbind_ping()) {
1444                         return legacy_sid_to_gid(psid, pgid);
1445                 }
1446
1447                 DEBUG(10,("winbind failed to find a gid for sid %s\n",
1448                                         sid_string_static(psid)));
1449                 return False;
1450         }
1451
1452         DEBUG(10,("sid %s -> gid %u\n", sid_string_static(psid),
1453                   (unsigned int)*pgid ));
1454
1455         store_gid_sid_cache(psid, *pgid);
1456         
1457         return True;
1458 }
1459