bb54959e96b14856d478d9b1c4fedc3e263bd456
[amitay/samba.git] / source3 / passdb / lookup_sid.c
1 /* 
2    Unix SMB/CIFS implementation.
3    uid/user handling
4    Copyright (C) Andrew Tridgell         1992-1998
5    Copyright (C) Gerald (Jerry) Carter   2003
6    Copyright (C) Volker Lendecke         2005
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23
24 /*****************************************************************
25  Dissect a user-provided name into domain, name, sid and type.
26
27  If an explicit domain name was given in the form domain\user, it
28  has to try that. If no explicit domain name was given, we have
29  to do guesswork.
30 *****************************************************************/  
31
32 bool lookup_name(TALLOC_CTX *mem_ctx,
33                  const char *full_name, int flags,
34                  const char **ret_domain, const char **ret_name,
35                  DOM_SID *ret_sid, enum lsa_SidType *ret_type)
36 {
37         char *p;
38         const char *tmp;
39         const char *domain = NULL;
40         const char *name = NULL;
41         uint32 rid;
42         DOM_SID sid;
43         enum lsa_SidType type;
44         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
45
46         if (tmp_ctx == NULL) {
47                 DEBUG(0, ("talloc_new failed\n"));
48                 return false;
49         }
50
51         p = strchr_m(full_name, '\\');
52
53         if (p != NULL) {
54                 domain = talloc_strndup(tmp_ctx, full_name,
55                                         PTR_DIFF(p, full_name));
56                 name = talloc_strdup(tmp_ctx, p+1);
57         } else {
58                 domain = talloc_strdup(tmp_ctx, "");
59                 name = talloc_strdup(tmp_ctx, full_name);
60         }
61
62         DEBUG(10,("lookup_name: %s => %s (domain), %s (name)\n", 
63                 full_name, domain, name));
64
65         if ((domain == NULL) || (name == NULL)) {
66                 DEBUG(0, ("talloc failed\n"));
67                 TALLOC_FREE(tmp_ctx);
68                 return false;
69         }
70
71         if (strequal(domain, get_global_sam_name())) {
72
73                 /* It's our own domain, lookup the name in passdb */
74                 if (lookup_global_sam_name(name, flags, &rid, &type)) {
75                         sid_copy(&sid, get_global_sam_sid());
76                         sid_append_rid(&sid, rid);
77                         goto ok;
78                 }
79                 TALLOC_FREE(tmp_ctx);
80                 return false;
81         }
82
83         if (strequal(domain, builtin_domain_name())) {
84
85                 /* Explicit request for a name in BUILTIN */
86                 if (lookup_builtin_name(name, &rid)) {
87                         sid_copy(&sid, &global_sid_Builtin);
88                         sid_append_rid(&sid, rid);
89                         type = SID_NAME_ALIAS;
90                         goto ok;
91                 }
92                 TALLOC_FREE(tmp_ctx);
93                 return false;
94         }
95
96         /* Try the explicit winbind lookup first, don't let it guess the
97          * domain yet at this point yet. This comes later. */
98
99         if ((domain[0] != '\0') &&
100             (winbind_lookup_name(domain, name, &sid, &type))) {
101                         goto ok;
102         }
103
104         if (!(flags & LOOKUP_NAME_EXPLICIT) && strequal(domain, unix_users_domain_name())) {
105                 if (lookup_unix_user_name(name, &sid)) {
106                         type = SID_NAME_USER;
107                         goto ok;
108                 }
109                 TALLOC_FREE(tmp_ctx);
110                 return false;
111         }
112
113         if (!(flags & LOOKUP_NAME_EXPLICIT) && strequal(domain, unix_groups_domain_name())) {
114                 if (lookup_unix_group_name(name, &sid)) {
115                         type = SID_NAME_DOM_GRP;
116                         goto ok;
117                 }
118                 TALLOC_FREE(tmp_ctx);
119                 return false;
120         }
121
122         if ((domain[0] == '\0') && (!(flags & LOOKUP_NAME_ISOLATED))) {
123                 TALLOC_FREE(tmp_ctx);
124                 return false;
125         }
126
127         /* Now the guesswork begins, we haven't been given an explicit
128          * domain. Try the sequence as documented on
129          * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
130          * November 27, 2005 */
131
132         /* 1. well-known names */
133
134         if (lookup_wellknown_name(tmp_ctx, name, &sid, &domain)) {
135                 type = SID_NAME_WKN_GRP;
136                 goto ok;
137         }
138
139         /* 2. Builtin domain as such */
140
141         if (strequal(name, builtin_domain_name())) {
142                 /* Swap domain and name */
143                 tmp = name; name = domain; domain = tmp;
144                 sid_copy(&sid, &global_sid_Builtin);
145                 type = SID_NAME_DOMAIN;
146                 goto ok;
147         }
148
149         /* 3. Account domain */
150
151         if (strequal(name, get_global_sam_name())) {
152                 if (!secrets_fetch_domain_sid(name, &sid)) {
153                         DEBUG(3, ("Could not fetch my SID\n"));
154                         TALLOC_FREE(tmp_ctx);
155                         return false;
156                 }
157                 /* Swap domain and name */
158                 tmp = name; name = domain; domain = tmp;
159                 type = SID_NAME_DOMAIN;
160                 goto ok;
161         }
162
163         /* 4. Primary domain */
164
165         if (!IS_DC && strequal(name, lp_workgroup())) {
166                 if (!secrets_fetch_domain_sid(name, &sid)) {
167                         DEBUG(3, ("Could not fetch the domain SID\n"));
168                         TALLOC_FREE(tmp_ctx);
169                         return false;
170                 }
171                 /* Swap domain and name */
172                 tmp = name; name = domain; domain = tmp;
173                 type = SID_NAME_DOMAIN;
174                 goto ok;
175         }
176
177         /* 5. Trusted domains as such, to me it looks as if members don't do
178               this, tested an XP workstation in a NT domain -- vl */
179
180         if (IS_DC && (pdb_get_trusteddom_pw(name, NULL, &sid, NULL))) {
181                 /* Swap domain and name */
182                 tmp = name; name = domain; domain = tmp;
183                 type = SID_NAME_DOMAIN;
184                 goto ok;
185         }
186
187         /* 6. Builtin aliases */        
188
189         if (lookup_builtin_name(name, &rid)) {
190                 domain = talloc_strdup(tmp_ctx, builtin_domain_name());
191                 sid_copy(&sid, &global_sid_Builtin);
192                 sid_append_rid(&sid, rid);
193                 type = SID_NAME_ALIAS;
194                 goto ok;
195         }
196
197         /* 7. Local systems' SAM (DCs don't have a local SAM) */
198         /* 8. Primary SAM (On members, this is the domain) */
199
200         /* Both cases are done by looking at our passdb */
201
202         if (lookup_global_sam_name(name, flags, &rid, &type)) {
203                 domain = talloc_strdup(tmp_ctx, get_global_sam_name());
204                 sid_copy(&sid, get_global_sam_sid());
205                 sid_append_rid(&sid, rid);
206                 goto ok;
207         }
208
209         /* Now our local possibilities are exhausted. */
210
211         if (!(flags & LOOKUP_NAME_REMOTE)) {
212                 TALLOC_FREE(tmp_ctx);
213                 return false;
214         }
215
216         /* If we are not a DC, we have to ask in our primary domain. Let
217          * winbind do that. */
218
219         if (!IS_DC &&
220             (winbind_lookup_name(lp_workgroup(), name, &sid, &type))) {
221                 domain = talloc_strdup(tmp_ctx, lp_workgroup());
222                 goto ok;
223         }
224
225         /* 9. Trusted domains */
226
227         /* If we're a DC we have to ask all trusted DC's. Winbind does not do
228          * that (yet), but give it a chance. */
229
230         if (IS_DC && winbind_lookup_name("", name, &sid, &type)) {
231                 DOM_SID dom_sid;
232                 uint32 tmp_rid;
233                 enum lsa_SidType domain_type;
234                 
235                 if (type == SID_NAME_DOMAIN) {
236                         /* Swap name and type */
237                         tmp = name; name = domain; domain = tmp;
238                         goto ok;
239                 }
240
241                 /* Here we have to cope with a little deficiency in the
242                  * winbind API: We have to ask it again for the name of the
243                  * domain it figured out itself. Maybe fix that later... */
244
245                 sid_copy(&dom_sid, &sid);
246                 sid_split_rid(&dom_sid, &tmp_rid);
247
248                 if (!winbind_lookup_sid(tmp_ctx, &dom_sid, &domain, NULL,
249                                         &domain_type) ||
250                     (domain_type != SID_NAME_DOMAIN)) {
251                         DEBUG(2, ("winbind could not find the domain's name "
252                                   "it just looked up for us\n"));
253                         TALLOC_FREE(tmp_ctx);
254                         return false;
255                 }
256                 goto ok;
257         }
258
259         /* 10. Don't translate */
260
261         /* 11. Ok, windows would end here. Samba has two more options:
262                Unmapped users and unmapped groups */
263
264         if (!(flags & LOOKUP_NAME_EXPLICIT) && lookup_unix_user_name(name, &sid)) {
265                 domain = talloc_strdup(tmp_ctx, unix_users_domain_name());
266                 type = SID_NAME_USER;
267                 goto ok;
268         }
269
270         if (!(flags & LOOKUP_NAME_EXPLICIT) && lookup_unix_group_name(name, &sid)) {
271                 domain = talloc_strdup(tmp_ctx, unix_groups_domain_name());
272                 type = SID_NAME_DOM_GRP;
273                 goto ok;
274         }
275
276         /*
277          * Ok, all possibilities tried. Fail.
278          */
279
280         TALLOC_FREE(tmp_ctx);
281         return false;
282
283  ok:
284         if ((domain == NULL) || (name == NULL)) {
285                 DEBUG(0, ("talloc failed\n"));
286                 TALLOC_FREE(tmp_ctx);
287                 return false;
288         }
289
290         /*
291          * Hand over the results to the talloc context we've been given.
292          */
293
294         if ((ret_name != NULL) &&
295             !(*ret_name = talloc_strdup(mem_ctx, name))) {
296                 DEBUG(0, ("talloc failed\n"));
297                 TALLOC_FREE(tmp_ctx);
298                 return false;
299         }
300
301         if (ret_domain != NULL) {
302                 char *tmp_dom;
303                 if (!(tmp_dom = talloc_strdup(mem_ctx, domain))) {
304                         DEBUG(0, ("talloc failed\n"));
305                         TALLOC_FREE(tmp_ctx);
306                         return false;
307                 }
308                 strupper_m(tmp_dom);
309                 *ret_domain = tmp_dom;
310         }
311
312         if (ret_sid != NULL) {
313                 sid_copy(ret_sid, &sid);
314         }
315
316         if (ret_type != NULL) {
317                 *ret_type = type;
318         }
319
320         TALLOC_FREE(tmp_ctx);
321         return true;
322 }
323
324 /************************************************************************
325  Names from smb.conf can be unqualified. eg. valid users = foo
326  These names should never map to a remote name. Try global_sam_name()\foo,
327  and then "Unix Users"\foo (or "Unix Groups"\foo).
328 ************************************************************************/
329
330 bool lookup_name_smbconf(TALLOC_CTX *mem_ctx,
331                  const char *full_name, int flags,
332                  const char **ret_domain, const char **ret_name,
333                  DOM_SID *ret_sid, enum lsa_SidType *ret_type)
334 {
335         char *qualified_name;
336         const char *p;
337
338         /* NB. No winbindd_separator here as lookup_name needs \\' */
339         if ((p = strchr_m(full_name, *lp_winbind_separator())) != NULL) {
340
341                 /* The name is already qualified with a domain. */
342
343                 if (*lp_winbind_separator() != '\\') {
344                         char *tmp;
345
346                         /* lookup_name() needs '\\' as a separator */
347
348                         tmp = talloc_strdup(mem_ctx, full_name);
349                         if (!tmp) {
350                                 return false;
351                         }
352                         tmp[p - full_name] = '\\';
353                         full_name = tmp;
354                 }
355
356                 return lookup_name(mem_ctx, full_name, flags,
357                                 ret_domain, ret_name,
358                                 ret_sid, ret_type);
359         }
360
361         /* Try with our own SAM name. */
362         qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
363                                 get_global_sam_name(),
364                                 full_name );
365         if (!qualified_name) {
366                 return false;
367         }
368
369         if (lookup_name(mem_ctx, qualified_name, flags,
370                                 ret_domain, ret_name,
371                                 ret_sid, ret_type)) {
372                 return true;
373         }
374         
375         /* Finally try with "Unix Users" or "Unix Group" */
376         qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
377                                 flags & LOOKUP_NAME_GROUP ?
378                                         unix_groups_domain_name() :
379                                         unix_users_domain_name(),
380                                 full_name );
381         if (!qualified_name) {
382                 return false;
383         }
384
385         return lookup_name(mem_ctx, qualified_name, flags,
386                                 ret_domain, ret_name,
387                                 ret_sid, ret_type);
388 }
389
390 static bool wb_lookup_rids(TALLOC_CTX *mem_ctx,
391                            const DOM_SID *domain_sid,
392                            int num_rids, uint32 *rids,
393                            const char **domain_name,
394                            const char **names, enum lsa_SidType *types)
395 {
396         int i;
397         const char **my_names;
398         enum lsa_SidType *my_types;
399         TALLOC_CTX *tmp_ctx;
400
401         if (!(tmp_ctx = talloc_init("wb_lookup_rids"))) {
402                 return false;
403         }
404
405         if (!winbind_lookup_rids(tmp_ctx, domain_sid, num_rids, rids,
406                                  domain_name, &my_names, &my_types)) {
407                 *domain_name = "";
408                 for (i=0; i<num_rids; i++) {
409                         names[i] = "";
410                         types[i] = SID_NAME_UNKNOWN;
411                 }
412                 TALLOC_FREE(tmp_ctx);
413                 return true;
414         }
415
416         if (!(*domain_name = talloc_strdup(mem_ctx, *domain_name))) {
417                 TALLOC_FREE(tmp_ctx);
418                 return false;
419         }
420
421         /*
422          * winbind_lookup_rids allocates its own array. We've been given the
423          * array, so copy it over
424          */
425
426         for (i=0; i<num_rids; i++) {
427                 if (my_names[i] == NULL) {
428                         TALLOC_FREE(tmp_ctx);
429                         return false;
430                 }
431                 if (!(names[i] = talloc_strdup(names, my_names[i]))) {
432                         TALLOC_FREE(tmp_ctx);
433                         return false;
434                 }
435                 types[i] = my_types[i];
436         }
437         TALLOC_FREE(tmp_ctx);
438         return true;
439 }
440
441 static bool lookup_rids(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
442                         int num_rids, uint32_t *rids,
443                         const char **domain_name,
444                         const char ***names, enum lsa_SidType **types)
445 {
446         int i;
447
448         if (num_rids) {
449                 *names = TALLOC_ARRAY(mem_ctx, const char *, num_rids);
450                 *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
451
452                 if ((*names == NULL) || (*types == NULL)) {
453                         return false;
454                 }
455         } else {
456                 *names = NULL;
457                 *types = NULL;
458         }
459
460         if (sid_check_is_domain(domain_sid)) {
461                 NTSTATUS result;
462
463                 if (*domain_name == NULL) {
464                         *domain_name = talloc_strdup(
465                                 mem_ctx, get_global_sam_name());
466                 }
467
468                 if (*domain_name == NULL) {
469                         return false;
470                 }
471
472                 become_root();
473                 result = pdb_lookup_rids(domain_sid, num_rids, rids,
474                                          *names, *types);
475                 unbecome_root();
476
477                 return (NT_STATUS_IS_OK(result) ||
478                         NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
479                         NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
480         }
481
482         if (sid_check_is_builtin(domain_sid)) {
483
484                 if (*domain_name == NULL) {
485                         *domain_name = talloc_strdup(
486                                 mem_ctx, builtin_domain_name());
487                 }
488
489                 if (*domain_name == NULL) {
490                         return false;
491                 }
492
493                 for (i=0; i<num_rids; i++) {
494                         if (lookup_builtin_rid(*names, rids[i],
495                                                &(*names)[i])) {
496                                 if ((*names)[i] == NULL) {
497                                         return false;
498                                 }
499                                 (*types)[i] = SID_NAME_ALIAS;
500                         } else {
501                                 (*types)[i] = SID_NAME_UNKNOWN;
502                         }
503                 }
504                 return true;
505         }
506
507         if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
508                 for (i=0; i<num_rids; i++) {
509                         DOM_SID sid;
510                         sid_copy(&sid, domain_sid);
511                         sid_append_rid(&sid, rids[i]);
512                         if (lookup_wellknown_sid(mem_ctx, &sid,
513                                                  domain_name, &(*names)[i])) {
514                                 if ((*names)[i] == NULL) {
515                                         return false;
516                                 }
517                                 (*types)[i] = SID_NAME_WKN_GRP;
518                         } else {
519                                 (*types)[i] = SID_NAME_UNKNOWN;
520                         }
521                 }
522                 return true;
523         }
524
525         if (sid_check_is_unix_users(domain_sid)) {
526                 if (*domain_name == NULL) {
527                         *domain_name = talloc_strdup(
528                                 mem_ctx, unix_users_domain_name());
529                 }
530                 for (i=0; i<num_rids; i++) {
531                         (*names)[i] = talloc_strdup(
532                                 (*names), uidtoname(rids[i]));
533                         (*types)[i] = SID_NAME_USER;
534                 }
535                 return true;
536         }
537
538         if (sid_check_is_unix_groups(domain_sid)) {
539                 if (*domain_name == NULL) {
540                         *domain_name = talloc_strdup(
541                                 mem_ctx, unix_groups_domain_name());
542                 }
543                 for (i=0; i<num_rids; i++) {
544                         (*names)[i] = talloc_strdup(
545                                 (*names), gidtoname(rids[i]));
546                         (*types)[i] = SID_NAME_DOM_GRP;
547                 }
548                 return true;
549         }
550
551         return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
552                               domain_name, *names, *types);
553 }
554
555 /*
556  * Is the SID a domain as such? If yes, lookup its name.
557  */
558
559 static bool lookup_as_domain(const DOM_SID *sid, TALLOC_CTX *mem_ctx,
560                              const char **name)
561 {
562         const char *tmp;
563         enum lsa_SidType type;
564
565         if (sid_check_is_domain(sid)) {
566                 *name = talloc_strdup(mem_ctx, get_global_sam_name());
567                 return true;
568         }
569
570         if (sid_check_is_builtin(sid)) {
571                 *name = talloc_strdup(mem_ctx, builtin_domain_name());
572                 return true;
573         }
574
575         if (sid_check_is_wellknown_domain(sid, &tmp)) {
576                 *name = talloc_strdup(mem_ctx, tmp);
577                 return true;
578         }
579
580         if (sid->num_auths != 4) {
581                 /* This can't be a domain */
582                 return false;
583         }
584
585         if (IS_DC) {
586                 uint32 i, num_domains;
587                 struct trustdom_info **domains;
588
589                 /* This is relatively expensive, but it happens only on DCs
590                  * and for SIDs that have 4 sub-authorities and thus look like
591                  * domains */
592
593                 if (!NT_STATUS_IS_OK(pdb_enum_trusteddoms(mem_ctx,
594                                                           &num_domains,
595                                                           &domains))) {
596                         return false;
597                 }
598
599                 for (i=0; i<num_domains; i++) {
600                         if (sid_equal(sid, &domains[i]->sid)) {
601                                 *name = talloc_strdup(mem_ctx,
602                                                       domains[i]->name);
603                                 return true;
604                         }
605                 }
606                 return false;
607         }
608
609         if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
610             (type == SID_NAME_DOMAIN)) {
611                 *name = tmp;
612                 return true;
613         }
614
615         return false;
616 }
617
618 /*
619  * This tries to implement the rather weird rules for the lsa_lookup level
620  * parameter.
621  *
622  * This is as close as we can get to what W2k3 does. With this we survive the
623  * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
624  * different, but I assume that's just being too liberal. For example, W2k3
625  * replies to everything else but the levels 1-6 with INVALID_PARAMETER
626  * whereas NT4 does the same as level 1 (I think). I did not fully test that
627  * with NT4, this is what w2k3 does.
628  *
629  * Level 1: Ask everywhere
630  * Level 2: Ask domain and trusted domains, no builtin and wkn
631  * Level 3: Only ask domain
632  * Level 4: W2k3ad: Only ask AD trusts
633  * Level 5: Only ask transitive forest trusts
634  * Level 6: Like 4
635  */
636
637 static bool check_dom_sid_to_level(const DOM_SID *sid, int level)
638 {
639         int ret = false;
640
641         switch(level) {
642         case 1:
643                 ret = true;
644                 break;
645         case 2:
646                 ret = (!sid_check_is_builtin(sid) &&
647                        !sid_check_is_wellknown_domain(sid, NULL));
648                 break;
649         case 3:
650         case 4:
651         case 6:
652                 ret = sid_check_is_domain(sid);
653                 break;
654         case 5:
655                 ret = false;
656                 break;
657         }
658
659         DEBUG(10, ("%s SID %s in level %d\n",
660                    ret ? "Accepting" : "Rejecting",
661                    sid_string_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         TALLOC_FREE(tmp_ctx);
884         return NT_STATUS_OK;
885
886  fail:
887         TALLOC_FREE(dom_infos);
888         TALLOC_FREE(name_infos);
889         TALLOC_FREE(tmp_ctx);
890         return result;
891 }
892
893 /*****************************************************************
894  *THE CANONICAL* convert SID to name function.
895 *****************************************************************/  
896
897 bool lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
898                 const char **ret_domain, const char **ret_name,
899                 enum lsa_SidType *ret_type)
900 {
901         struct lsa_dom_info *domain;
902         struct lsa_name_info *name;
903         TALLOC_CTX *tmp_ctx;
904         bool ret = false;
905
906         if (!(tmp_ctx = talloc_new(mem_ctx))) {
907                 DEBUG(0, ("talloc_new failed\n"));
908                 return false;
909         }
910
911         if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
912                                          &domain, &name))) {
913                 goto done;
914         }
915
916         if (name->type == SID_NAME_UNKNOWN) {
917                 goto done;
918         }
919
920         if ((ret_domain != NULL) &&
921             !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
922                 goto done;
923         }
924
925         if ((ret_name != NULL) && 
926             !(*ret_name = talloc_strdup(mem_ctx, name->name))) {
927                 goto done;
928         }
929
930         if (ret_type != NULL) {
931                 *ret_type = name->type;
932         }
933
934         ret = true;
935
936  done:
937         if (ret) {
938                 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n",
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