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