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