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