r20824: Send access to the trusted domain passwords through the pdb backend, so that
[sfrench/samba-autobuild/.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                 return True;
414         }
415
416         /*
417          * winbind_lookup_rids allocates its own array. We've been given the
418          * array, so copy it over
419          */
420
421         for (i=0; i<num_rids; i++) {
422                 if (my_names[i] == NULL) {
423                         TALLOC_FREE(tmp_ctx);
424                         return False;
425                 }
426                 if (!(names[i] = talloc_strdup(names, my_names[i]))) {
427                         TALLOC_FREE(tmp_ctx);
428                         return False;
429                 }
430                 types[i] = my_types[i];
431         }
432         TALLOC_FREE(tmp_ctx);
433         return True;
434 }
435
436 static BOOL lookup_rids(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
437                         int num_rids, uint32_t *rids,
438                         const char **domain_name,
439                         const char ***names, enum lsa_SidType **types)
440 {
441         int i;
442
443         *names = TALLOC_ARRAY(mem_ctx, const char *, num_rids);
444         *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
445
446         if ((*names == NULL) || (*types == NULL)) {
447                 return False;
448         }
449
450         if (sid_check_is_domain(domain_sid)) {
451                 NTSTATUS result;
452
453                 if (*domain_name == NULL) {
454                         *domain_name = talloc_strdup(
455                                 mem_ctx, get_global_sam_name());
456                 }
457
458                 if (*domain_name == NULL) {
459                         return False;
460                 }
461
462                 become_root_uid_only();
463                 result = pdb_lookup_rids(domain_sid, num_rids, rids,
464                                          *names, *types);
465                 unbecome_root_uid_only();
466
467                 return (NT_STATUS_IS_OK(result) ||
468                         NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
469                         NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
470         }
471
472         if (sid_check_is_builtin(domain_sid)) {
473
474                 if (*domain_name == NULL) {
475                         *domain_name = talloc_strdup(
476                                 mem_ctx, builtin_domain_name());
477                 }
478
479                 if (*domain_name == NULL) {
480                         return False;
481                 }
482
483                 for (i=0; i<num_rids; i++) {
484                         if (lookup_builtin_rid(*names, rids[i],
485                                                &(*names)[i])) {
486                                 if ((*names)[i] == NULL) {
487                                         return False;
488                                 }
489                                 (*types)[i] = SID_NAME_ALIAS;
490                         } else {
491                                 (*types)[i] = SID_NAME_UNKNOWN;
492                         }
493                 }
494                 return True;
495         }
496
497         if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
498                 for (i=0; i<num_rids; i++) {
499                         DOM_SID sid;
500                         sid_copy(&sid, domain_sid);
501                         sid_append_rid(&sid, rids[i]);
502                         if (lookup_wellknown_sid(mem_ctx, &sid,
503                                                  domain_name, &(*names)[i])) {
504                                 if ((*names)[i] == NULL) {
505                                         return False;
506                                 }
507                                 (*types)[i] = SID_NAME_WKN_GRP;
508                         } else {
509                                 (*types)[i] = SID_NAME_UNKNOWN;
510                         }
511                 }
512                 return True;
513         }
514
515         if (sid_check_is_unix_users(domain_sid)) {
516                 if (*domain_name == NULL) {
517                         *domain_name = talloc_strdup(
518                                 mem_ctx, unix_users_domain_name());
519                 }
520                 for (i=0; i<num_rids; i++) {
521                         (*names)[i] = talloc_strdup(
522                                 (*names), uidtoname(rids[i]));
523                         (*types)[i] = SID_NAME_USER;
524                 }
525                 return True;
526         }
527
528         if (sid_check_is_unix_groups(domain_sid)) {
529                 if (*domain_name == NULL) {
530                         *domain_name = talloc_strdup(
531                                 mem_ctx, unix_groups_domain_name());
532                 }
533                 for (i=0; i<num_rids; i++) {
534                         (*names)[i] = talloc_strdup(
535                                 (*names), gidtoname(rids[i]));
536                         (*types)[i] = SID_NAME_DOM_GRP;
537                 }
538                 return True;
539         }
540
541         return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
542                               domain_name, *names, *types);
543 }
544
545 /*
546  * Is the SID a domain as such? If yes, lookup its name.
547  */
548
549 static BOOL lookup_as_domain(const DOM_SID *sid, TALLOC_CTX *mem_ctx,
550                              const char **name)
551 {
552         const char *tmp;
553         enum lsa_SidType type;
554
555         if (sid_check_is_domain(sid)) {
556                 *name = talloc_strdup(mem_ctx, get_global_sam_name());
557                 return True;
558         }
559
560         if (sid_check_is_builtin(sid)) {
561                 *name = talloc_strdup(mem_ctx, builtin_domain_name());
562                 return True;
563         }
564
565         if (sid_check_is_wellknown_domain(sid, &tmp)) {
566                 *name = talloc_strdup(mem_ctx, tmp);
567                 return True;
568         }
569
570         if (sid->num_auths != 4) {
571                 /* This can't be a domain */
572                 return False;
573         }
574
575         if (IS_DC) {
576                 uint32 i, num_domains;
577                 struct trustdom_info **domains;
578
579                 /* This is relatively expensive, but it happens only on DCs
580                  * and for SIDs that have 4 sub-authorities and thus look like
581                  * domains */
582
583                 if (!NT_STATUS_IS_OK(pdb_enum_trusteddoms(mem_ctx,
584                                                           &num_domains,
585                                                           &domains))) {
586                         return False;
587                 }
588
589                 for (i=0; i<num_domains; i++) {
590                         if (sid_equal(sid, &domains[i]->sid)) {
591                                 *name = talloc_strdup(mem_ctx,
592                                                       domains[i]->name);
593                                 return True;
594                         }
595                 }
596                 return False;
597         }
598
599         if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
600             (type == SID_NAME_DOMAIN)) {
601                 *name = tmp;
602                 return True;
603         }
604
605         return False;
606 }
607
608 /*
609  * This tries to implement the rather weird rules for the lsa_lookup level
610  * parameter.
611  *
612  * This is as close as we can get to what W2k3 does. With this we survive the
613  * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
614  * different, but I assume that's just being too liberal. For example, W2k3
615  * replies to everything else but the levels 1-6 with INVALID_PARAMETER
616  * whereas NT4 does the same as level 1 (I think). I did not fully test that
617  * with NT4, this is what w2k3 does.
618  *
619  * Level 1: Ask everywhere
620  * Level 2: Ask domain and trusted domains, no builtin and wkn
621  * Level 3: Only ask domain
622  * Level 4: W2k3ad: Only ask AD trusts
623  * Level 5: Don't lookup anything
624  * Level 6: Like 4
625  */
626
627 static BOOL check_dom_sid_to_level(const DOM_SID *sid, int level)
628 {
629         int ret = False;
630
631         switch(level) {
632         case 1:
633                 ret = True;
634                 break;
635         case 2:
636                 ret = (!sid_check_is_builtin(sid) &&
637                        !sid_check_is_wellknown_domain(sid, NULL));
638                 break;
639         case 3:
640         case 4:
641         case 6:
642                 ret = sid_check_is_domain(sid);
643                 break;
644         case 5:
645                 ret = False;
646                 break;
647         }
648
649         DEBUG(10, ("%s SID %s in level %d\n",
650                    ret ? "Accepting" : "Rejecting",
651                    sid_string_static(sid), level));
652         return ret;
653 }
654
655 /*
656  * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
657  * references to domains, it is explicitly made for this.
658  *
659  * This attempts to be as efficient as possible: It collects all SIDs
660  * belonging to a domain and hands them in bulk to the appropriate lookup
661  * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
662  * *hugely* from this. Winbind is going to be extended with a lookup_rids
663  * interface as well, so on a DC we can do a bulk lsa_lookuprids to the
664  * appropriate DC.
665  */
666
667 NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
668                      const DOM_SID **sids, int level,
669                      struct lsa_dom_info **ret_domains,
670                      struct lsa_name_info **ret_names)
671 {
672         TALLOC_CTX *tmp_ctx;
673         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
674         struct lsa_name_info *name_infos;
675         struct lsa_dom_info *dom_infos;
676
677         int i, j;
678
679         if (!(tmp_ctx = talloc_new(mem_ctx))) {
680                 DEBUG(0, ("talloc_new failed\n"));
681                 return NT_STATUS_NO_MEMORY;
682         }
683
684         name_infos = TALLOC_ARRAY(mem_ctx, struct lsa_name_info, num_sids);
685         dom_infos = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_dom_info,
686                                       MAX_REF_DOMAINS);
687         if ((name_infos == NULL) || (dom_infos == NULL)) {
688                 result = NT_STATUS_NO_MEMORY;
689                 goto fail;
690         }
691
692         /* First build up the data structures:
693          * 
694          * dom_infos is a list of domains referenced in the list of
695          * SIDs. Later we will walk the list of domains and look up the RIDs
696          * in bulk.
697          *
698          * name_infos is a shadow-copy of the SIDs array to collect the real
699          * data.
700          *
701          * dom_info->idxs is an index into the name_infos array. The
702          * difficulty we have here is that we need to keep the SIDs the client
703          * asked for in the same order for the reply
704          */
705
706         for (i=0; i<num_sids; i++) {
707                 DOM_SID sid;
708                 uint32 rid;
709                 const char *domain_name = NULL;
710
711                 sid_copy(&sid, sids[i]);
712                 name_infos[i].type = SID_NAME_USE_NONE;
713
714                 if (lookup_as_domain(&sid, name_infos, &domain_name)) {
715                         /* We can't push that through the normal lookup
716                          * process, as this would reference illegal
717                          * domains.
718                          *
719                          * For example S-1-5-32 would end up referencing
720                          * domain S-1-5- with RID 32 which is clearly wrong.
721                          */
722                         if (domain_name == NULL) {
723                                 result = NT_STATUS_NO_MEMORY;
724                                 goto fail;
725                         }
726                                 
727                         name_infos[i].rid = 0;
728                         name_infos[i].type = SID_NAME_DOMAIN;
729                         name_infos[i].name = NULL;
730
731                         if (sid_check_is_builtin(&sid)) {
732                                 /* Yes, W2k3 returns "BUILTIN" both as domain
733                                  * and name here */
734                                 name_infos[i].name = talloc_strdup(
735                                         name_infos, builtin_domain_name());
736                                 if (name_infos[i].name == NULL) {
737                                         result = NT_STATUS_NO_MEMORY;
738                                         goto fail;
739                                 }
740                         }
741                 } else {
742                         /* This is a normal SID with rid component */
743                         if (!sid_split_rid(&sid, &rid)) {
744                                 result = NT_STATUS_INVALID_PARAMETER;
745                                 goto fail;
746                         }
747                 }
748
749                 if (!check_dom_sid_to_level(&sid, level)) {
750                         name_infos[i].rid = 0;
751                         name_infos[i].type = SID_NAME_UNKNOWN;
752                         name_infos[i].name = NULL;
753                         continue;
754                 }
755
756                 for (j=0; j<MAX_REF_DOMAINS; j++) {
757                         if (!dom_infos[j].valid) {
758                                 break;
759                         }
760                         if (sid_equal(&sid, &dom_infos[j].sid)) {
761                                 break;
762                         }
763                 }
764
765                 if (j == MAX_REF_DOMAINS) {
766                         /* TODO: What's the right error message here? */
767                         result = NT_STATUS_NONE_MAPPED;
768                         goto fail;
769                 }
770
771                 if (!dom_infos[j].valid) {
772                         /* We found a domain not yet referenced, create a new
773                          * ref. */
774                         dom_infos[j].valid = True;
775                         sid_copy(&dom_infos[j].sid, &sid);
776
777                         if (domain_name != NULL) {
778                                 /* This name was being found above in the case
779                                  * when we found a domain SID */
780                                 dom_infos[j].name =
781                                         talloc_strdup(dom_infos, domain_name);
782                                 if (dom_infos[j].name == NULL) {
783                                         result = NT_STATUS_NO_MEMORY;
784                                         goto fail;
785                                 }
786                         } else {
787                                 /* lookup_rids will take care of this */
788                                 dom_infos[j].name = NULL;
789                         }
790                 }
791
792                 name_infos[i].dom_idx = j;
793
794                 if (name_infos[i].type == SID_NAME_USE_NONE) {
795                         name_infos[i].rid = rid;
796
797                         ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
798                                      &dom_infos[j].num_idxs);
799
800                         if (dom_infos[j].idxs == NULL) {
801                                 result = NT_STATUS_NO_MEMORY;
802                                 goto fail;
803                         }
804                 }
805         }
806
807         /* Iterate over the domains found */
808
809         for (i=0; i<MAX_REF_DOMAINS; i++) {
810                 uint32_t *rids;
811                 const char *domain_name = NULL;
812                 const char **names;
813                 enum lsa_SidType *types;
814                 struct lsa_dom_info *dom = &dom_infos[i];
815
816                 if (!dom->valid) {
817                         /* No domains left, we're done */
818                         break;
819                 }
820
821                 if (!(rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs))) {
822                         result = NT_STATUS_NO_MEMORY;
823                         goto fail;
824                 }
825
826                 for (j=0; j<dom->num_idxs; j++) {
827                         rids[j] = name_infos[dom->idxs[j]].rid;
828                 }
829
830                 if (!lookup_rids(tmp_ctx, &dom->sid,
831                                  dom->num_idxs, rids, &domain_name,
832                                  &names, &types)) {
833                         result = NT_STATUS_NO_MEMORY;
834                         goto fail;
835                 }
836
837                 if (!(dom->name = talloc_strdup(dom_infos, domain_name))) {
838                         result = NT_STATUS_NO_MEMORY;
839                         goto fail;
840                 }
841                         
842                 for (j=0; j<dom->num_idxs; j++) {
843                         int idx = dom->idxs[j];
844                         name_infos[idx].type = types[j];
845                         if (types[j] != SID_NAME_UNKNOWN) {
846                                 name_infos[idx].name =
847                                         talloc_strdup(name_infos, names[j]);
848                                 if (name_infos[idx].name == NULL) {
849                                         result = NT_STATUS_NO_MEMORY;
850                                         goto fail;
851                                 }
852                         } else {
853                                 name_infos[idx].name = NULL;
854                         }
855                 }
856         }
857
858         *ret_domains = dom_infos;
859         *ret_names = name_infos;
860         return NT_STATUS_OK;
861
862  fail:
863         TALLOC_FREE(dom_infos);
864         TALLOC_FREE(name_infos);
865         TALLOC_FREE(tmp_ctx);
866         return result;
867 }
868
869 /*****************************************************************
870  *THE CANONICAL* convert SID to name function.
871 *****************************************************************/  
872
873 BOOL lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
874                 const char **ret_domain, const char **ret_name,
875                 enum lsa_SidType *ret_type)
876 {
877         struct lsa_dom_info *domain;
878         struct lsa_name_info *name;
879         TALLOC_CTX *tmp_ctx;
880         BOOL ret = False;
881
882         if (!(tmp_ctx = talloc_new(mem_ctx))) {
883                 DEBUG(0, ("talloc_new failed\n"));
884                 return False;
885         }
886
887         if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
888                                          &domain, &name))) {
889                 goto done;
890         }
891
892         if (name->type == SID_NAME_UNKNOWN) {
893                 goto done;
894         }
895
896         if ((ret_domain != NULL) &&
897             !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
898                 goto done;
899         }
900
901         if ((ret_name != NULL) && 
902             !(*ret_name = talloc_strdup(mem_ctx, name->name))) {
903                 goto done;
904         }
905
906         if (ret_type != NULL) {
907                 *ret_type = name->type;
908         }
909
910         ret = True;
911
912  done:
913         if (ret) {
914                 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n",
915                            sid_string_static(sid), domain->name,
916                            name->name, name->type));
917         } else {
918                 DEBUG(10, ("failed to lookup sid %s\n",
919                            sid_string_static(sid)));
920         }
921         TALLOC_FREE(tmp_ctx);
922         return ret;
923 }
924
925 /*****************************************************************
926  Id mapping cache.  This is to avoid Winbind mappings already
927  seen by smbd to be queried too frequently, keeping winbindd
928  busy, and blocking smbd while winbindd is busy with other
929  stuff. Written by Michael Steffens <michael.steffens@hp.com>,
930  modified to use linked lists by jra.
931 *****************************************************************/  
932
933 #define MAX_UID_SID_CACHE_SIZE 100
934 #define TURNOVER_UID_SID_CACHE_SIZE 10
935 #define MAX_GID_SID_CACHE_SIZE 100
936 #define TURNOVER_GID_SID_CACHE_SIZE 10
937
938 static size_t n_uid_sid_cache = 0;
939 static size_t n_gid_sid_cache = 0;
940
941 static struct uid_sid_cache {
942         struct uid_sid_cache *next, *prev;
943         uid_t uid;
944         DOM_SID sid;
945         enum lsa_SidType sidtype;
946 } *uid_sid_cache_head;
947
948 static struct gid_sid_cache {
949         struct gid_sid_cache *next, *prev;
950         gid_t gid;
951         DOM_SID sid;
952         enum lsa_SidType sidtype;
953 } *gid_sid_cache_head;
954
955 /*****************************************************************
956   Find a SID given a uid.
957 *****************************************************************/  
958
959 static BOOL fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid)
960 {
961         struct uid_sid_cache *pc;
962
963         for (pc = uid_sid_cache_head; pc; pc = pc->next) {
964                 if (pc->uid == uid) {
965                         *psid = pc->sid;
966                         DEBUG(3,("fetch sid from uid cache %u -> %s\n",
967                                  (unsigned int)uid, sid_string_static(psid)));
968                         DLIST_PROMOTE(uid_sid_cache_head, pc);
969                         return True;
970                 }
971         }
972         return False;
973 }
974
975 /*****************************************************************
976   Find a uid given a SID.
977 *****************************************************************/  
978
979 static BOOL fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid )
980 {
981         struct uid_sid_cache *pc;
982
983         for (pc = uid_sid_cache_head; pc; pc = pc->next) {
984                 if (sid_compare(&pc->sid, psid) == 0) {
985                         *puid = pc->uid;
986                         DEBUG(3,("fetch uid from cache %u -> %s\n",
987                                  (unsigned int)*puid, sid_string_static(psid)));
988                         DLIST_PROMOTE(uid_sid_cache_head, pc);
989                         return True;
990                 }
991         }
992         return False;
993 }
994
995 /*****************************************************************
996  Store uid to SID mapping in cache.
997 *****************************************************************/  
998
999 void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
1000 {
1001         struct uid_sid_cache *pc;
1002
1003         /* do not store SIDs in the "Unix Group" domain */
1004         
1005         if ( sid_check_is_in_unix_users( psid ) )
1006                 return;
1007
1008         if (n_uid_sid_cache >= MAX_UID_SID_CACHE_SIZE && n_uid_sid_cache > TURNOVER_UID_SID_CACHE_SIZE) {
1009                 /* Delete the last TURNOVER_UID_SID_CACHE_SIZE entries. */
1010                 struct uid_sid_cache *pc_next;
1011                 size_t i;
1012
1013                 for (i = 0, pc = uid_sid_cache_head; i < (n_uid_sid_cache - TURNOVER_UID_SID_CACHE_SIZE); i++, pc = pc->next)
1014                         ;
1015                 for(; pc; pc = pc_next) {
1016                         pc_next = pc->next;
1017                         DLIST_REMOVE(uid_sid_cache_head,pc);
1018                         SAFE_FREE(pc);
1019                         n_uid_sid_cache--;
1020                 }
1021         }
1022
1023         pc = SMB_MALLOC_P(struct uid_sid_cache);
1024         if (!pc)
1025                 return;
1026         pc->uid = uid;
1027         sid_copy(&pc->sid, psid);
1028         DLIST_ADD(uid_sid_cache_head, pc);
1029         n_uid_sid_cache++;
1030 }
1031
1032 /*****************************************************************
1033   Find a SID given a gid.
1034 *****************************************************************/  
1035
1036 static BOOL fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid)
1037 {
1038         struct gid_sid_cache *pc;
1039
1040         for (pc = gid_sid_cache_head; pc; pc = pc->next) {
1041                 if (pc->gid == gid) {
1042                         *psid = pc->sid;
1043                         DEBUG(3,("fetch sid from gid cache %u -> %s\n",
1044                                  (unsigned int)gid, sid_string_static(psid)));
1045                         DLIST_PROMOTE(gid_sid_cache_head, pc);
1046                         return True;
1047                 }
1048         }
1049         return False;
1050 }
1051
1052 /*****************************************************************
1053   Find a gid given a SID.
1054 *****************************************************************/  
1055
1056 static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid)
1057 {
1058         struct gid_sid_cache *pc;
1059
1060         for (pc = gid_sid_cache_head; pc; pc = pc->next) {
1061                 if (sid_compare(&pc->sid, psid) == 0) {
1062                         *pgid = pc->gid;
1063                         DEBUG(3,("fetch gid from cache %u -> %s\n",
1064                                  (unsigned int)*pgid, sid_string_static(psid)));
1065                         DLIST_PROMOTE(gid_sid_cache_head, pc);
1066                         return True;
1067                 }
1068         }
1069         return False;
1070 }
1071
1072 /*****************************************************************
1073  Store gid to SID mapping in cache.
1074 *****************************************************************/  
1075
1076 void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
1077 {
1078         struct gid_sid_cache *pc;
1079         
1080         /* do not store SIDs in the "Unix Group" domain */
1081         
1082         if ( sid_check_is_in_unix_groups( psid ) )
1083                 return;
1084
1085         if (n_gid_sid_cache >= MAX_GID_SID_CACHE_SIZE && n_gid_sid_cache > TURNOVER_GID_SID_CACHE_SIZE) {
1086                 /* Delete the last TURNOVER_GID_SID_CACHE_SIZE entries. */
1087                 struct gid_sid_cache *pc_next;
1088                 size_t i;
1089
1090                 for (i = 0, pc = gid_sid_cache_head; i < (n_gid_sid_cache - TURNOVER_GID_SID_CACHE_SIZE); i++, pc = pc->next)
1091                         ;
1092                 for(; pc; pc = pc_next) {
1093                         pc_next = pc->next;
1094                         DLIST_REMOVE(gid_sid_cache_head,pc);
1095                         SAFE_FREE(pc);
1096                         n_gid_sid_cache--;
1097                 }
1098         }
1099
1100         pc = SMB_MALLOC_P(struct gid_sid_cache);
1101         if (!pc)
1102                 return;
1103         pc->gid = gid;
1104         sid_copy(&pc->sid, psid);
1105         DLIST_ADD(gid_sid_cache_head, pc);
1106
1107         DEBUG(3,("store_gid_sid_cache: gid %u in cache -> %s\n", (unsigned int)gid,
1108                 sid_string_static(psid)));
1109
1110         n_gid_sid_cache++;
1111 }
1112
1113 /*****************************************************************
1114  *THE LEGACY* convert uid_t to SID function.
1115 *****************************************************************/  
1116
1117 void legacy_uid_to_sid(DOM_SID *psid, uid_t uid)
1118 {
1119         uint32 rid;
1120         BOOL ret;
1121
1122         ZERO_STRUCTP(psid);
1123
1124         become_root_uid_only();
1125         ret = pdb_uid_to_rid(uid, &rid);
1126         unbecome_root_uid_only();
1127
1128         if (ret) {
1129                 /* This is a mapped user */
1130                 sid_copy(psid, get_global_sam_sid());
1131                 sid_append_rid(psid, rid);
1132                 goto done;
1133         }
1134
1135         /* This is an unmapped user */
1136
1137         uid_to_unix_users_sid(uid, psid);
1138
1139  done:
1140         DEBUG(10,("LEGACY: uid %u -> sid %s\n", (unsigned int)uid,
1141                   sid_string_static(psid)));
1142
1143         store_uid_sid_cache(psid, uid);
1144         return;
1145 }
1146
1147 /*****************************************************************
1148  *THE LEGACY* convert gid_t to SID function.
1149 *****************************************************************/  
1150
1151 void legacy_gid_to_sid(DOM_SID *psid, gid_t gid)
1152 {
1153         BOOL ret;
1154
1155         ZERO_STRUCTP(psid);
1156
1157         become_root_uid_only();
1158         ret = pdb_gid_to_sid(gid, psid);
1159         unbecome_root_uid_only();
1160
1161         if (ret) {
1162                 /* This is a mapped group */
1163                 goto done;
1164         }
1165         
1166         /* This is an unmapped group */
1167
1168         gid_to_unix_groups_sid(gid, psid);
1169
1170  done:
1171         DEBUG(10,("LEGACY: gid %u -> sid %s\n", (unsigned int)gid,
1172                   sid_string_static(psid)));
1173
1174         store_gid_sid_cache(psid, gid);
1175         return;
1176 }
1177
1178 /*****************************************************************
1179  *THE LEGACY* convert SID to uid function.
1180 *****************************************************************/  
1181
1182 BOOL legacy_sid_to_uid(const DOM_SID *psid, uid_t *puid)
1183 {
1184         enum lsa_SidType type;
1185         uint32 rid;
1186
1187         if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
1188                 uid_t uid = rid;
1189                 *puid = uid;
1190                 goto done;
1191         }
1192
1193         if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1194                 union unid_t id;
1195                 BOOL ret;
1196
1197                 become_root_uid_only();
1198                 ret = pdb_sid_to_id(psid, &id, &type);
1199                 unbecome_root_uid_only();
1200
1201                 if (ret) {
1202                         if (type != SID_NAME_USER) {
1203                                 DEBUG(5, ("sid %s is a %s, expected a user\n",
1204                                           sid_string_static(psid),
1205                                           sid_type_lookup(type)));
1206                                 return False;
1207                         }
1208                         *puid = id.uid;
1209                         goto done;
1210                 }
1211
1212                 /* This was ours, but it was not mapped.  Fail */
1213         }
1214
1215         DEBUG(10,("LEGACY: mapping failed for sid %s\n", sid_string_static(psid)));
1216         return False;
1217
1218 done:
1219         DEBUG(10,("LEGACY: sid %s -> uid %u\n", sid_string_static(psid),
1220                 (unsigned int)*puid ));
1221
1222         store_uid_sid_cache(psid, *puid);
1223         return True;
1224 }
1225
1226 /*****************************************************************
1227  *THE LEGACY* convert SID to gid function.
1228  Group mapping is used for gids that maps to Wellknown SIDs
1229 *****************************************************************/  
1230
1231 BOOL legacy_sid_to_gid(const DOM_SID *psid, gid_t *pgid)
1232 {
1233         uint32 rid;
1234         GROUP_MAP map;
1235         union unid_t id;
1236         enum lsa_SidType type;
1237
1238         if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
1239                 gid_t gid = rid;
1240                 *pgid = gid;
1241                 goto done;
1242         }
1243
1244         if ((sid_check_is_in_builtin(psid) ||
1245              sid_check_is_in_wellknown_domain(psid))) {
1246                 BOOL ret;
1247
1248                 become_root_uid_only();
1249                 ret = pdb_getgrsid(&map, *psid);
1250                 unbecome_root_uid_only();
1251
1252                 if (ret) {
1253                         *pgid = map.gid;
1254                         goto done;
1255                 }
1256                 DEBUG(10,("LEGACY: mapping failed for sid %s\n", sid_string_static(psid)));
1257                 return False;
1258         }
1259
1260         if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1261                 BOOL ret;
1262
1263                 become_root_uid_only();
1264                 ret = pdb_sid_to_id(psid, &id, &type);
1265                 unbecome_root_uid_only();
1266
1267                 if (ret) {
1268                         if ((type != SID_NAME_DOM_GRP) &&
1269                             (type != SID_NAME_ALIAS)) {
1270                                 DEBUG(5, ("LEGACY: sid %s is a %s, expected a group\n",
1271                                           sid_string_static(psid),
1272                                           sid_type_lookup(type)));
1273                                 return False;
1274                         }
1275                         *pgid = id.gid;
1276                         goto done;
1277                 }
1278         
1279                 /* This was ours, but it was not mapped.  Fail */
1280         }
1281
1282         DEBUG(10,("LEGACY: mapping failed for sid %s\n", sid_string_static(psid)));
1283         return False;
1284         
1285  done:
1286         DEBUG(10,("LEGACY: sid %s -> gid %u\n", sid_string_static(psid),
1287                   (unsigned int)*pgid ));
1288
1289         store_gid_sid_cache(psid, *pgid);
1290
1291         return True;
1292 }
1293
1294 /*****************************************************************
1295  *THE CANONICAL* convert uid_t to SID function.
1296 *****************************************************************/  
1297
1298 void uid_to_sid(DOM_SID *psid, uid_t uid)
1299 {
1300         ZERO_STRUCTP(psid);
1301
1302         if (fetch_sid_from_uid_cache(psid, uid))
1303                 return;
1304
1305         if (!winbind_uid_to_sid(psid, uid)) {
1306                 if (!winbind_ping()) {
1307                         DEBUG(2, ("WARNING: Winbindd not running, mapping ids with legacy code\n"));
1308                         legacy_uid_to_sid(psid, uid);
1309                         return;
1310                 }
1311
1312                 DEBUG(5, ("uid_to_sid: winbind failed to find a sid for uid %u\n",
1313                         uid));
1314                 return;
1315         }
1316
1317         DEBUG(10,("uid %u -> sid %s\n",
1318                   (unsigned int)uid, sid_string_static(psid)));
1319
1320         store_uid_sid_cache(psid, uid);
1321         return;
1322 }
1323
1324 /*****************************************************************
1325  *THE CANONICAL* convert gid_t to SID function.
1326 *****************************************************************/  
1327
1328 void gid_to_sid(DOM_SID *psid, gid_t gid)
1329 {
1330         ZERO_STRUCTP(psid);
1331
1332         if (fetch_sid_from_gid_cache(psid, gid))
1333                 return;
1334
1335         if (!winbind_gid_to_sid(psid, gid)) {
1336                 if (!winbind_ping()) {
1337                         DEBUG(2, ("WARNING: Winbindd not running, mapping ids with legacy code\n"));
1338                         legacy_gid_to_sid(psid, gid);
1339                         return;
1340                 }
1341
1342                 DEBUG(5, ("gid_to_sid: winbind failed to find a sid for gid %u\n",
1343                         gid));
1344                 return;
1345         }
1346
1347         DEBUG(10,("gid %u -> sid %s\n",
1348                   (unsigned int)gid, sid_string_static(psid)));
1349         
1350         store_gid_sid_cache(psid, gid);
1351         return;
1352 }
1353
1354 /*****************************************************************
1355  *THE CANONICAL* convert SID to uid function.
1356 *****************************************************************/  
1357
1358 BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid)
1359 {
1360         gid_t gid;
1361
1362         if (fetch_uid_from_cache(puid, psid))
1363                 return True;
1364
1365         if (fetch_gid_from_cache(&gid, psid)) {
1366                 return False;
1367         }
1368
1369         if (!winbind_sid_to_uid(puid, psid)) {
1370                 if (!winbind_ping()) {
1371                         DEBUG(2, ("WARNING: Winbindd not running, mapping ids with legacy code\n"));
1372                         return legacy_sid_to_uid(psid, puid);
1373                 }
1374
1375                 DEBUG(5, ("winbind failed to find a uid for sid %s\n",
1376                           sid_string_static(psid)));
1377                 return False;
1378         }
1379
1380         /* TODO: Here would be the place to allocate both a gid and a uid for
1381          * the SID in question */
1382
1383         DEBUG(10,("sid %s -> uid %u\n", sid_string_static(psid),
1384                 (unsigned int)*puid ));
1385
1386         store_uid_sid_cache(psid, *puid);
1387         return True;
1388 }
1389
1390 /*****************************************************************
1391  *THE CANONICAL* convert SID to gid function.
1392  Group mapping is used for gids that maps to Wellknown SIDs
1393 *****************************************************************/  
1394
1395 BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid)
1396 {
1397         uid_t uid;
1398
1399         if (fetch_gid_from_cache(pgid, psid))
1400                 return True;
1401
1402         if (fetch_uid_from_cache(&uid, psid))
1403                 return False;
1404
1405         /* Ask winbindd if it can map this sid to a gid.
1406          * (Idmap will check it is a valid SID and of the right type) */
1407
1408         if ( !winbind_sid_to_gid(pgid, psid) ) {
1409                 if (!winbind_ping()) {
1410                         DEBUG(2, ("WARNING: Winbindd not running, mapping ids with legacy code\n"));
1411                         return legacy_sid_to_gid(psid, pgid);
1412                 }
1413
1414                 DEBUG(10,("winbind failed to find a gid for sid %s\n",
1415                                         sid_string_static(psid)));
1416                 return False;
1417         }
1418
1419         DEBUG(10,("sid %s -> gid %u\n", sid_string_static(psid),
1420                   (unsigned int)*pgid ));
1421
1422         store_gid_sid_cache(psid, *pgid);
1423         
1424         return True;
1425 }
1426