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