passdb: remove a misleading comment from lookup_name_smbconf()
[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 #include "passdb.h"
24 #include "../librpc/gen_ndr/ndr_security.h"
25 #include "secrets.h"
26 #include "../lib/util/memcache.h"
27 #include "idmap_cache.h"
28 #include "../libcli/security/security.h"
29 #include "lib/winbind_util.h"
30 #include "../librpc/gen_ndr/idmap.h"
31
32 /*****************************************************************
33  Dissect a user-provided name into domain, name, sid and type.
34
35  If an explicit domain name was given in the form domain\user, it
36  has to try that. If no explicit domain name was given, we have
37  to do guesswork.
38 *****************************************************************/  
39
40 bool lookup_name(TALLOC_CTX *mem_ctx,
41                  const char *full_name, int flags,
42                  const char **ret_domain, const char **ret_name,
43                  struct dom_sid *ret_sid, enum lsa_SidType *ret_type)
44 {
45         char *p;
46         const char *tmp;
47         const char *domain = NULL;
48         const char *name = NULL;
49         uint32_t rid;
50         struct dom_sid sid;
51         enum lsa_SidType type;
52         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
53
54         if (tmp_ctx == NULL) {
55                 DEBUG(0, ("talloc_new failed\n"));
56                 return false;
57         }
58
59         p = strchr_m(full_name, '\\');
60
61         if (p != NULL) {
62                 domain = talloc_strndup(tmp_ctx, full_name,
63                                         PTR_DIFF(p, full_name));
64                 name = talloc_strdup(tmp_ctx, p+1);
65         } else {
66                 domain = talloc_strdup(tmp_ctx, "");
67                 name = talloc_strdup(tmp_ctx, full_name);
68         }
69
70         if ((domain == NULL) || (name == NULL)) {
71                 DEBUG(0, ("talloc failed\n"));
72                 TALLOC_FREE(tmp_ctx);
73                 return false;
74         }
75
76         DEBUG(10,("lookup_name: %s => domain=[%s], name=[%s]\n",
77                 full_name, domain, name));
78         DEBUG(10, ("lookup_name: flags = 0x0%x\n", flags));
79
80         if ((flags & LOOKUP_NAME_DOMAIN) &&
81             strequal(domain, get_global_sam_name()))
82         {
83
84                 /* It's our own domain, lookup the name in passdb */
85                 if (lookup_global_sam_name(name, flags, &rid, &type)) {
86                         sid_compose(&sid, get_global_sam_sid(), rid);
87                         goto ok;
88                 }
89                 TALLOC_FREE(tmp_ctx);
90                 return false;
91         }
92
93         if ((flags & LOOKUP_NAME_BUILTIN) &&
94             strequal(domain, builtin_domain_name()))
95         {
96                 if (strlen(name) == 0) {
97                         /* Swap domain and name */
98                         tmp = name; name = domain; domain = tmp;
99                         sid_copy(&sid, &global_sid_Builtin);
100                         type = SID_NAME_DOMAIN;
101                         goto ok;
102                 }
103
104                 /* Explicit request for a name in BUILTIN */
105                 if (lookup_builtin_name(name, &rid)) {
106                         sid_compose(&sid, &global_sid_Builtin, rid);
107                         type = SID_NAME_ALIAS;
108                         goto ok;
109                 }
110                 TALLOC_FREE(tmp_ctx);
111                 return false;
112         }
113
114         /* Try the explicit winbind lookup first, don't let it guess the
115          * domain yet at this point yet. This comes later. */
116
117         if ((domain[0] != '\0') &&
118             (flags & ~(LOOKUP_NAME_DOMAIN|LOOKUP_NAME_ISOLATED)) &&
119             (winbind_lookup_name(domain, name, &sid, &type))) {
120                         goto ok;
121         }
122
123         if (((flags & (LOOKUP_NAME_NO_NSS|LOOKUP_NAME_GROUP)) == 0)
124             && strequal(domain, unix_users_domain_name())) {
125                 if (lookup_unix_user_name(name, &sid)) {
126                         type = SID_NAME_USER;
127                         goto ok;
128                 }
129                 TALLOC_FREE(tmp_ctx);
130                 return false;
131         }
132
133         if (((flags & LOOKUP_NAME_NO_NSS) == 0)
134             && strequal(domain, unix_groups_domain_name())) {
135                 if (lookup_unix_group_name(name, &sid)) {
136                         type = SID_NAME_DOM_GRP;
137                         goto ok;
138                 }
139                 TALLOC_FREE(tmp_ctx);
140                 return false;
141         }
142
143         /*
144          * Finally check for a well known domain name ("NT Authority"),
145          * this is taken care if in lookup_wellknown_name().
146          */
147         if ((domain[0] != '\0') &&
148             (flags & LOOKUP_NAME_WKN) &&
149             lookup_wellknown_name(tmp_ctx, name, &sid, &domain))
150         {
151                 type = SID_NAME_WKN_GRP;
152                 goto ok;
153         }
154
155         /*
156          * If we're told not to look up 'isolated' names then we're
157          * done.
158          */
159         if (!(flags & LOOKUP_NAME_ISOLATED)) {
160                 TALLOC_FREE(tmp_ctx);
161                 return false;
162         }
163
164         /*
165          * No domain names beyond this point
166          */
167         if (domain[0] != '\0') {
168                 TALLOC_FREE(tmp_ctx);
169                 return false;
170         }
171
172         /* Now the guesswork begins, we haven't been given an explicit
173          * domain. Try the sequence as documented on
174          * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
175          * November 27, 2005 */
176
177         /* 1. well-known names */
178
179         /*
180          * Check for well known names without a domain name.
181          * e.g. \Creator Owner.
182          */
183
184         if ((flags & LOOKUP_NAME_WKN) &&
185             lookup_wellknown_name(tmp_ctx, name, &sid, &domain))
186         {
187                 type = SID_NAME_WKN_GRP;
188                 goto ok;
189         }
190
191         /* 2. Builtin domain as such */
192
193         if ((flags & (LOOKUP_NAME_BUILTIN|LOOKUP_NAME_REMOTE)) &&
194             strequal(name, builtin_domain_name()))
195         {
196                 /* Swap domain and name */
197                 tmp = name; name = domain; domain = tmp;
198                 sid_copy(&sid, &global_sid_Builtin);
199                 type = SID_NAME_DOMAIN;
200                 goto ok;
201         }
202
203         /* 3. Account domain */
204
205         if ((flags & LOOKUP_NAME_DOMAIN) &&
206             strequal(name, get_global_sam_name()))
207         {
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 ((flags & LOOKUP_NAME_DOMAIN) && !IS_DC &&
222             strequal(name, lp_workgroup()))
223         {
224                 if (!secrets_fetch_domain_sid(name, &sid)) {
225                         DEBUG(3, ("Could not fetch the domain SID\n"));
226                         TALLOC_FREE(tmp_ctx);
227                         return false;
228                 }
229                 /* Swap domain and name */
230                 tmp = name; name = domain; domain = tmp;
231                 type = SID_NAME_DOMAIN;
232                 goto ok;
233         }
234
235         /* 5. Trusted domains as such, to me it looks as if members don't do
236               this, tested an XP workstation in a NT domain -- vl */
237
238         if ((flags & LOOKUP_NAME_REMOTE) && IS_DC &&
239             (pdb_get_trusteddom_pw(name, NULL, &sid, NULL)))
240         {
241                 /* Swap domain and name */
242                 tmp = name; name = domain; domain = tmp;
243                 type = SID_NAME_DOMAIN;
244                 goto ok;
245         }
246
247         /* 6. Builtin aliases */        
248
249         if ((flags & LOOKUP_NAME_BUILTIN) &&
250             lookup_builtin_name(name, &rid))
251         {
252                 domain = talloc_strdup(tmp_ctx, builtin_domain_name());
253                 sid_compose(&sid, &global_sid_Builtin, rid);
254                 type = SID_NAME_ALIAS;
255                 goto ok;
256         }
257
258         /* 7. Local systems' SAM (DCs don't have a local SAM) */
259         /* 8. Primary SAM (On members, this is the domain) */
260
261         /* Both cases are done by looking at our passdb */
262
263         if ((flags & LOOKUP_NAME_DOMAIN) &&
264             lookup_global_sam_name(name, flags, &rid, &type))
265         {
266                 domain = talloc_strdup(tmp_ctx, get_global_sam_name());
267                 sid_compose(&sid, get_global_sam_sid(), rid);
268                 goto ok;
269         }
270
271         /* Now our local possibilities are exhausted. */
272
273         if (!(flags & LOOKUP_NAME_REMOTE)) {
274                 TALLOC_FREE(tmp_ctx);
275                 return false;
276         }
277
278         /* If we are not a DC, we have to ask in our primary domain. Let
279          * winbind do that. */
280
281         if (!IS_DC &&
282             (winbind_lookup_name(lp_workgroup(), name, &sid, &type))) {
283                 domain = talloc_strdup(tmp_ctx, lp_workgroup());
284                 goto ok;
285         }
286
287         /* 9. Trusted domains */
288
289         /* If we're a DC we have to ask all trusted DC's. Winbind does not do
290          * that (yet), but give it a chance. */
291
292         if (IS_DC && winbind_lookup_name("", name, &sid, &type)) {
293                 struct dom_sid dom_sid;
294                 enum lsa_SidType domain_type;
295
296                 if (type == SID_NAME_DOMAIN) {
297                         /* Swap name and type */
298                         tmp = name; name = domain; domain = tmp;
299                         goto ok;
300                 }
301
302                 /* Here we have to cope with a little deficiency in the
303                  * winbind API: We have to ask it again for the name of the
304                  * domain it figured out itself. Maybe fix that later... */
305
306                 sid_copy(&dom_sid, &sid);
307                 sid_split_rid(&dom_sid, NULL);
308
309                 if (!winbind_lookup_sid(tmp_ctx, &dom_sid, &domain, NULL,
310                                         &domain_type) ||
311                     (domain_type != SID_NAME_DOMAIN)) {
312                         DEBUG(2, ("winbind could not find the domain's name "
313                                   "it just looked up for us\n"));
314                         TALLOC_FREE(tmp_ctx);
315                         return false;
316                 }
317                 goto ok;
318         }
319
320         /* 10. Don't translate */
321
322         /* 11. Ok, windows would end here. Samba has two more options:
323                Unmapped users and unmapped groups */
324
325         if (((flags & (LOOKUP_NAME_NO_NSS|LOOKUP_NAME_GROUP)) == 0)
326             && lookup_unix_user_name(name, &sid)) {
327                 domain = talloc_strdup(tmp_ctx, unix_users_domain_name());
328                 type = SID_NAME_USER;
329                 goto ok;
330         }
331
332         if (((flags & LOOKUP_NAME_NO_NSS) == 0)
333             && lookup_unix_group_name(name, &sid)) {
334                 domain = talloc_strdup(tmp_ctx, unix_groups_domain_name());
335                 type = SID_NAME_DOM_GRP;
336                 goto ok;
337         }
338
339         /*
340          * Ok, all possibilities tried. Fail.
341          */
342
343         TALLOC_FREE(tmp_ctx);
344         return false;
345
346  ok:
347         if ((domain == NULL) || (name == NULL)) {
348                 DEBUG(0, ("talloc failed\n"));
349                 TALLOC_FREE(tmp_ctx);
350                 return false;
351         }
352
353         /*
354          * Hand over the results to the talloc context we've been given.
355          */
356
357         if ((ret_name != NULL) &&
358             !(*ret_name = talloc_strdup(mem_ctx, name))) {
359                 DEBUG(0, ("talloc failed\n"));
360                 TALLOC_FREE(tmp_ctx);
361                 return false;
362         }
363
364         if (ret_domain != NULL) {
365                 char *tmp_dom;
366                 if (!(tmp_dom = talloc_strdup(mem_ctx, domain))) {
367                         DEBUG(0, ("talloc failed\n"));
368                         TALLOC_FREE(tmp_ctx);
369                         return false;
370                 }
371                 if (!strupper_m(tmp_dom)) {
372                         TALLOC_FREE(tmp_ctx);
373                         return false;
374                 }
375                 *ret_domain = tmp_dom;
376         }
377
378         if (ret_sid != NULL) {
379                 sid_copy(ret_sid, &sid);
380         }
381
382         if (ret_type != NULL) {
383                 *ret_type = type;
384         }
385
386         TALLOC_FREE(tmp_ctx);
387         return true;
388 }
389
390 /************************************************************************
391  Names from smb.conf can be unqualified. eg. valid users = foo
392  These names should never map to a remote name. Try global_sam_name()\foo,
393  and then "Unix Users"\foo (or "Unix Groups"\foo).
394 ************************************************************************/
395
396 bool lookup_name_smbconf(TALLOC_CTX *mem_ctx,
397                  const char *full_name, int flags,
398                  const char **ret_domain, const char **ret_name,
399                  struct dom_sid *ret_sid, enum lsa_SidType *ret_type)
400 {
401         char *qualified_name;
402         const char *p;
403
404         if ((p = strchr_m(full_name, *lp_winbind_separator())) != NULL) {
405
406                 /* The name is already qualified with a domain. */
407
408                 if (*lp_winbind_separator() != '\\') {
409                         char *tmp;
410
411                         /* lookup_name() needs '\\' as a separator */
412
413                         tmp = talloc_strdup(mem_ctx, full_name);
414                         if (!tmp) {
415                                 return false;
416                         }
417                         tmp[p - full_name] = '\\';
418                         full_name = tmp;
419                 }
420
421                 return lookup_name(mem_ctx, full_name, flags,
422                                 ret_domain, ret_name,
423                                 ret_sid, ret_type);
424         }
425
426         /* Try with winbind default domain name. */
427         if (lp_winbind_use_default_domain()) {
428                 bool ok;
429
430                 qualified_name = talloc_asprintf(mem_ctx,
431                                                  "%s\\%s",
432                                                  lp_workgroup(),
433                                                  full_name);
434                 if (qualified_name == NULL) {
435                         return false;
436                 }
437
438                 ok = lookup_name(mem_ctx,
439                                  qualified_name,
440                                  flags,
441                                  ret_domain,
442                                  ret_name,
443                                  ret_sid,
444                                  ret_type);
445                 if (ok) {
446                         return true;
447                 }
448         }
449
450         /* Try with our own SAM name. */
451         qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
452                                 get_global_sam_name(),
453                                 full_name );
454         if (!qualified_name) {
455                 return false;
456         }
457
458         if (lookup_name(mem_ctx, qualified_name, flags,
459                                 ret_domain, ret_name,
460                                 ret_sid, ret_type)) {
461                 return true;
462         }
463
464         /* Finally try with "Unix Users" or "Unix Group" */
465         qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
466                                 flags & LOOKUP_NAME_GROUP ?
467                                         unix_groups_domain_name() :
468                                         unix_users_domain_name(),
469                                 full_name );
470         if (!qualified_name) {
471                 return false;
472         }
473
474         return lookup_name(mem_ctx, qualified_name, flags,
475                                 ret_domain, ret_name,
476                                 ret_sid, ret_type);
477 }
478
479 static bool wb_lookup_rids(TALLOC_CTX *mem_ctx,
480                            const struct dom_sid *domain_sid,
481                            int num_rids, uint32_t *rids,
482                            const char **domain_name,
483                            const char **names, enum lsa_SidType *types)
484 {
485         int i;
486         const char **my_names;
487         enum lsa_SidType *my_types;
488         TALLOC_CTX *tmp_ctx;
489
490         if (!(tmp_ctx = talloc_init("wb_lookup_rids"))) {
491                 return false;
492         }
493
494         if (!winbind_lookup_rids(tmp_ctx, domain_sid, num_rids, rids,
495                                  domain_name, &my_names, &my_types)) {
496                 *domain_name = "";
497                 for (i=0; i<num_rids; i++) {
498                         names[i] = "";
499                         types[i] = SID_NAME_UNKNOWN;
500                 }
501                 TALLOC_FREE(tmp_ctx);
502                 return true;
503         }
504
505         if (!(*domain_name = talloc_strdup(mem_ctx, *domain_name))) {
506                 TALLOC_FREE(tmp_ctx);
507                 return false;
508         }
509
510         /*
511          * winbind_lookup_rids allocates its own array. We've been given the
512          * array, so copy it over
513          */
514
515         for (i=0; i<num_rids; i++) {
516                 if (my_names[i] == NULL) {
517                         TALLOC_FREE(tmp_ctx);
518                         return false;
519                 }
520                 if (!(names[i] = talloc_strdup(names, my_names[i]))) {
521                         TALLOC_FREE(tmp_ctx);
522                         return false;
523                 }
524                 types[i] = my_types[i];
525         }
526         TALLOC_FREE(tmp_ctx);
527         return true;
528 }
529
530 static bool lookup_rids(TALLOC_CTX *mem_ctx, const struct dom_sid *domain_sid,
531                         int num_rids, uint32_t *rids,
532                         const char **domain_name,
533                         const char ***names, enum lsa_SidType **types)
534 {
535         int i;
536
537         DEBUG(10, ("lookup_rids called for domain sid '%s'\n",
538                    sid_string_dbg(domain_sid)));
539
540         if (num_rids) {
541                 *names = talloc_zero_array(mem_ctx, const char *, num_rids);
542                 *types = talloc_array(mem_ctx, enum lsa_SidType, num_rids);
543
544                 if ((*names == NULL) || (*types == NULL)) {
545                         return false;
546                 }
547
548                 for (i = 0; i < num_rids; i++)
549                         (*types)[i] = SID_NAME_UNKNOWN;
550         } else {
551                 *names = NULL;
552                 *types = NULL;
553         }
554
555         if (sid_check_is_our_sam(domain_sid)) {
556                 NTSTATUS result;
557
558                 if (*domain_name == NULL) {
559                         *domain_name = talloc_strdup(
560                                 mem_ctx, get_global_sam_name());
561                 }
562
563                 if (*domain_name == NULL) {
564                         return false;
565                 }
566
567                 become_root();
568                 result = pdb_lookup_rids(domain_sid, num_rids, rids,
569                                          *names, *types);
570                 unbecome_root();
571
572                 return (NT_STATUS_IS_OK(result) ||
573                         NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
574                         NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
575         }
576
577         if (sid_check_is_builtin(domain_sid)) {
578
579                 if (*domain_name == NULL) {
580                         *domain_name = talloc_strdup(
581                                 mem_ctx, builtin_domain_name());
582                 }
583
584                 if (*domain_name == NULL) {
585                         return false;
586                 }
587
588                 for (i=0; i<num_rids; i++) {
589                         if (lookup_builtin_rid(*names, rids[i],
590                                                &(*names)[i])) {
591                                 if ((*names)[i] == NULL) {
592                                         return false;
593                                 }
594                                 (*types)[i] = SID_NAME_ALIAS;
595                         } else {
596                                 (*types)[i] = SID_NAME_UNKNOWN;
597                         }
598                 }
599                 return true;
600         }
601
602         if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
603                 for (i=0; i<num_rids; i++) {
604                         struct dom_sid sid;
605                         sid_compose(&sid, domain_sid, rids[i]);
606                         if (lookup_wellknown_sid(mem_ctx, &sid,
607                                                  domain_name, &(*names)[i])) {
608                                 if ((*names)[i] == NULL) {
609                                         return false;
610                                 }
611                                 (*types)[i] = SID_NAME_WKN_GRP;
612                         } else {
613                                 (*types)[i] = SID_NAME_UNKNOWN;
614                         }
615                 }
616                 return true;
617         }
618
619         if (sid_check_is_unix_users(domain_sid)) {
620                 if (*domain_name == NULL) {
621                         *domain_name = talloc_strdup(
622                                 mem_ctx, unix_users_domain_name());
623                         if (*domain_name == NULL) {
624                                 return false;
625                         }
626                 }
627                 for (i=0; i<num_rids; i++) {
628                         (*names)[i] = talloc_strdup(
629                                 (*names), uidtoname(rids[i]));
630                         if ((*names)[i] == NULL) {
631                                 return false;
632                         }
633                         (*types)[i] = SID_NAME_USER;
634                 }
635                 return true;
636         }
637
638         if (sid_check_is_unix_groups(domain_sid)) {
639                 if (*domain_name == NULL) {
640                         *domain_name = talloc_strdup(
641                                 mem_ctx, unix_groups_domain_name());
642                         if (*domain_name == NULL) {
643                                 return false;
644                         }
645                 }
646                 for (i=0; i<num_rids; i++) {
647                         (*names)[i] = talloc_strdup(
648                                 (*names), gidtoname(rids[i]));
649                         if ((*names)[i] == NULL) {
650                                 return false;
651                         }
652                         (*types)[i] = SID_NAME_DOM_GRP;
653                 }
654                 return true;
655         }
656
657         return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
658                               domain_name, *names, *types);
659 }
660
661 /*
662  * Is the SID a domain as such? If yes, lookup its name.
663  */
664
665 static bool lookup_as_domain(const struct dom_sid *sid, TALLOC_CTX *mem_ctx,
666                              const char **name)
667 {
668         const char *tmp;
669         enum lsa_SidType type;
670
671         if (sid_check_is_our_sam(sid)) {
672                 *name = talloc_strdup(mem_ctx, get_global_sam_name());
673                 return true;
674         }
675
676         if (sid_check_is_builtin(sid)) {
677                 *name = talloc_strdup(mem_ctx, builtin_domain_name());
678                 return true;
679         }
680
681         if (sid_check_is_wellknown_domain(sid, &tmp)) {
682                 *name = talloc_strdup(mem_ctx, tmp);
683                 return true;
684         }
685
686         if (sid_check_is_unix_users(sid)) {
687                 *name = talloc_strdup(mem_ctx, unix_users_domain_name());
688                 return true;
689         }
690
691         if (sid_check_is_unix_groups(sid)) {
692                 *name = talloc_strdup(mem_ctx, unix_groups_domain_name());
693                 return true;
694         }
695
696         if (sid->num_auths != 4) {
697                 /* This can't be a domain */
698                 return false;
699         }
700
701         if (IS_DC) {
702                 uint32_t i, num_domains;
703                 struct trustdom_info **domains;
704
705                 /* This is relatively expensive, but it happens only on DCs
706                  * and for SIDs that have 4 sub-authorities and thus look like
707                  * domains */
708
709                 if (!NT_STATUS_IS_OK(pdb_enum_trusteddoms(mem_ctx,
710                                                           &num_domains,
711                                                           &domains))) {
712                         return false;
713                 }
714
715                 for (i=0; i<num_domains; i++) {
716                         if (dom_sid_equal(sid, &domains[i]->sid)) {
717                                 *name = talloc_strdup(mem_ctx,
718                                                       domains[i]->name);
719                                 return true;
720                         }
721                 }
722                 return false;
723         }
724
725         if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
726             (type == SID_NAME_DOMAIN)) {
727                 *name = tmp;
728                 return true;
729         }
730
731         return false;
732 }
733
734 /*
735  * This tries to implement the rather weird rules for the lsa_lookup level
736  * parameter.
737  *
738  * This is as close as we can get to what W2k3 does. With this we survive the
739  * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
740  * different, but I assume that's just being too liberal. For example, W2k3
741  * replies to everything else but the levels 1-6 with INVALID_PARAMETER
742  * whereas NT4 does the same as level 1 (I think). I did not fully test that
743  * with NT4, this is what w2k3 does.
744  *
745  * Level 1: Ask everywhere
746  * Level 2: Ask domain and trusted domains, no builtin and wkn
747  * Level 3: Only ask domain
748  * Level 4: W2k3ad: Only ask AD trusts
749  * Level 5: Only ask transitive forest trusts
750  * Level 6: Like 4
751  */
752
753 static bool check_dom_sid_to_level(const struct dom_sid *sid, int level)
754 {
755         int ret = false;
756
757         switch(level) {
758         case 1:
759                 ret = true;
760                 break;
761         case 2:
762                 ret = (!sid_check_is_builtin(sid) &&
763                        !sid_check_is_wellknown_domain(sid, NULL));
764                 break;
765         case 3:
766         case 4:
767         case 6:
768                 ret = sid_check_is_our_sam(sid);
769                 break;
770         case 5:
771                 ret = false;
772                 break;
773         }
774
775         DEBUG(10, ("%s SID %s in level %d\n",
776                    ret ? "Accepting" : "Rejecting",
777                    sid_string_dbg(sid), level));
778         return ret;
779 }
780
781 /*
782  * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
783  * references to domains, it is explicitly made for this.
784  *
785  * This attempts to be as efficient as possible: It collects all SIDs
786  * belonging to a domain and hands them in bulk to the appropriate lookup
787  * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
788  * *hugely* from this.
789  */
790
791 NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
792                      const struct dom_sid **sids, int level,
793                      struct lsa_dom_info **ret_domains,
794                      struct lsa_name_info **ret_names)
795 {
796         TALLOC_CTX *tmp_ctx;
797         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
798         struct lsa_name_info *name_infos;
799         struct lsa_dom_info *dom_infos = NULL;
800
801         int i, j;
802
803         if (!(tmp_ctx = talloc_new(mem_ctx))) {
804                 DEBUG(0, ("talloc_new failed\n"));
805                 return NT_STATUS_NO_MEMORY;
806         }
807
808         if (num_sids) {
809                 name_infos = talloc_array(mem_ctx, struct lsa_name_info, num_sids);
810                 if (name_infos == NULL) {
811                         result = NT_STATUS_NO_MEMORY;
812                         goto fail;
813                 }
814         } else {
815                 name_infos = NULL;
816         }
817
818         dom_infos = talloc_zero_array(mem_ctx, struct lsa_dom_info,
819                                       LSA_REF_DOMAIN_LIST_MULTIPLIER);
820         if (dom_infos == NULL) {
821                 result = NT_STATUS_NO_MEMORY;
822                 goto fail;
823         }
824
825         /* First build up the data structures:
826          * 
827          * dom_infos is a list of domains referenced in the list of
828          * SIDs. Later we will walk the list of domains and look up the RIDs
829          * in bulk.
830          *
831          * name_infos is a shadow-copy of the SIDs array to collect the real
832          * data.
833          *
834          * dom_info->idxs is an index into the name_infos array. The
835          * difficulty we have here is that we need to keep the SIDs the client
836          * asked for in the same order for the reply
837          */
838
839         for (i=0; i<num_sids; i++) {
840                 struct dom_sid sid;
841                 uint32_t rid = 0;
842                 const char *domain_name = NULL;
843
844                 sid_copy(&sid, sids[i]);
845                 name_infos[i].type = SID_NAME_USE_NONE;
846
847                 if (lookup_as_domain(&sid, name_infos, &domain_name)) {
848                         /* We can't push that through the normal lookup
849                          * process, as this would reference illegal
850                          * domains.
851                          *
852                          * For example S-1-5-32 would end up referencing
853                          * domain S-1-5- with RID 32 which is clearly wrong.
854                          */
855                         if (domain_name == NULL) {
856                                 result = NT_STATUS_NO_MEMORY;
857                                 goto fail;
858                         }
859
860                         name_infos[i].rid = 0;
861                         name_infos[i].type = SID_NAME_DOMAIN;
862                         name_infos[i].name = NULL;
863
864                         if (sid_check_is_builtin(&sid)) {
865                                 /* Yes, W2k3 returns "BUILTIN" both as domain
866                                  * and name here */
867                                 name_infos[i].name = talloc_strdup(
868                                         name_infos, builtin_domain_name());
869                                 if (name_infos[i].name == NULL) {
870                                         result = NT_STATUS_NO_MEMORY;
871                                         goto fail;
872                                 }
873                         }
874                 } else {
875                         /* This is a normal SID with rid component */
876                         if (!sid_split_rid(&sid, &rid)) {
877                                 result = NT_STATUS_INVALID_SID;
878                                 goto fail;
879                         }
880                 }
881
882                 if (!check_dom_sid_to_level(&sid, level)) {
883                         name_infos[i].rid = 0;
884                         name_infos[i].type = SID_NAME_UNKNOWN;
885                         name_infos[i].name = NULL;
886                         continue;
887                 }
888
889                 for (j=0; j<LSA_REF_DOMAIN_LIST_MULTIPLIER; j++) {
890                         if (!dom_infos[j].valid) {
891                                 break;
892                         }
893                         if (dom_sid_equal(&sid, &dom_infos[j].sid)) {
894                                 break;
895                         }
896                 }
897
898                 if (j == LSA_REF_DOMAIN_LIST_MULTIPLIER) {
899                         /* TODO: What's the right error message here? */
900                         result = NT_STATUS_NONE_MAPPED;
901                         goto fail;
902                 }
903
904                 if (!dom_infos[j].valid) {
905                         /* We found a domain not yet referenced, create a new
906                          * ref. */
907                         dom_infos[j].valid = true;
908                         sid_copy(&dom_infos[j].sid, &sid);
909
910                         if (domain_name != NULL) {
911                                 /* This name was being found above in the case
912                                  * when we found a domain SID */
913                                 dom_infos[j].name =
914                                         talloc_strdup(dom_infos, domain_name);
915                                 if (dom_infos[j].name == NULL) {
916                                         result = NT_STATUS_NO_MEMORY;
917                                         goto fail;
918                                 }
919                         } else {
920                                 /* lookup_rids will take care of this */
921                                 dom_infos[j].name = NULL;
922                         }
923                 }
924
925                 name_infos[i].dom_idx = j;
926
927                 if (name_infos[i].type == SID_NAME_USE_NONE) {
928                         name_infos[i].rid = rid;
929
930                         ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
931                                      &dom_infos[j].num_idxs);
932
933                         if (dom_infos[j].idxs == NULL) {
934                                 result = NT_STATUS_NO_MEMORY;
935                                 goto fail;
936                         }
937                 }
938         }
939
940         /* Iterate over the domains found */
941
942         for (i=0; i<LSA_REF_DOMAIN_LIST_MULTIPLIER; i++) {
943                 uint32_t *rids;
944                 const char *domain_name = NULL;
945                 const char **names;
946                 enum lsa_SidType *types;
947                 struct lsa_dom_info *dom = &dom_infos[i];
948
949                 if (!dom->valid) {
950                         /* No domains left, we're done */
951                         break;
952                 }
953
954                 if (dom->num_idxs == 0) {
955                         /*
956                          * This happens only if the only sid related to
957                          * this domain is the domain sid itself, which
958                          * is mapped to SID_NAME_DOMAIN above.
959                          */
960                         continue;
961                 }
962
963                 if (!(rids = talloc_array(tmp_ctx, uint32_t, dom->num_idxs))) {
964                         result = NT_STATUS_NO_MEMORY;
965                         goto fail;
966                 }
967
968                 for (j=0; j<dom->num_idxs; j++) {
969                         rids[j] = name_infos[dom->idxs[j]].rid;
970                 }
971
972                 if (!lookup_rids(tmp_ctx, &dom->sid,
973                                  dom->num_idxs, rids, &domain_name,
974                                  &names, &types)) {
975                         result = NT_STATUS_NO_MEMORY;
976                         goto fail;
977                 }
978
979                 if (!(dom->name = talloc_strdup(dom_infos, domain_name))) {
980                         result = NT_STATUS_NO_MEMORY;
981                         goto fail;
982                 }
983
984                 for (j=0; j<dom->num_idxs; j++) {
985                         int idx = dom->idxs[j];
986                         name_infos[idx].type = types[j];
987                         if (types[j] != SID_NAME_UNKNOWN) {
988                                 name_infos[idx].name =
989                                         talloc_strdup(name_infos, names[j]);
990                                 if (name_infos[idx].name == NULL) {
991                                         result = NT_STATUS_NO_MEMORY;
992                                         goto fail;
993                                 }
994                         } else {
995                                 name_infos[idx].name = NULL;
996                         }
997                 }
998         }
999
1000         *ret_domains = dom_infos;
1001         *ret_names = name_infos;
1002         TALLOC_FREE(tmp_ctx);
1003         return NT_STATUS_OK;
1004
1005  fail:
1006         TALLOC_FREE(dom_infos);
1007         TALLOC_FREE(name_infos);
1008         TALLOC_FREE(tmp_ctx);
1009         return result;
1010 }
1011
1012 /*****************************************************************
1013  *THE CANONICAL* convert SID to name function.
1014 *****************************************************************/  
1015
1016 bool lookup_sid(TALLOC_CTX *mem_ctx, const struct dom_sid *sid,
1017                 const char **ret_domain, const char **ret_name,
1018                 enum lsa_SidType *ret_type)
1019 {
1020         struct lsa_dom_info *domain;
1021         struct lsa_name_info *name;
1022         TALLOC_CTX *tmp_ctx;
1023         bool ret = false;
1024
1025         DEBUG(10, ("lookup_sid called for SID '%s'\n", sid_string_dbg(sid)));
1026
1027         if (!(tmp_ctx = talloc_new(mem_ctx))) {
1028                 DEBUG(0, ("talloc_new failed\n"));
1029                 return false;
1030         }
1031
1032         if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
1033                                          &domain, &name))) {
1034                 goto done;
1035         }
1036
1037         if (name->type == SID_NAME_UNKNOWN) {
1038                 goto done;
1039         }
1040
1041         if ((ret_domain != NULL) &&
1042             !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
1043                 goto done;
1044         }
1045
1046         if ((ret_name != NULL) && 
1047             !(*ret_name = talloc_strdup(mem_ctx, name->name))) {
1048                 goto done;
1049         }
1050
1051         if (ret_type != NULL) {
1052                 *ret_type = name->type;
1053         }
1054
1055         ret = true;
1056
1057  done:
1058         if (ret) {
1059                 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n", sid_string_dbg(sid),
1060                            domain->name, name->name, name->type));
1061         } else {
1062                 DEBUG(10, ("failed to lookup sid %s\n", sid_string_dbg(sid)));
1063         }
1064         TALLOC_FREE(tmp_ctx);
1065         return ret;
1066 }
1067
1068 /*****************************************************************
1069  Id mapping cache.  This is to avoid Winbind mappings already
1070  seen by smbd to be queried too frequently, keeping winbindd
1071  busy, and blocking smbd while winbindd is busy with other
1072  stuff. Written by Michael Steffens <michael.steffens@hp.com>,
1073  modified to use linked lists by jra.
1074 *****************************************************************/  
1075
1076
1077 /*****************************************************************
1078  *THE LEGACY* convert uid_t to SID function.
1079 *****************************************************************/  
1080
1081 static void legacy_uid_to_sid(struct dom_sid *psid, uid_t uid)
1082 {
1083         bool ret;
1084         struct unixid id;
1085
1086         ZERO_STRUCTP(psid);
1087
1088         id.id = uid;
1089         id.type = ID_TYPE_UID;
1090
1091         become_root();
1092         ret = pdb_id_to_sid(&id, psid);
1093         unbecome_root();
1094
1095         if (ret) {
1096                 /* This is a mapped user */
1097                 goto done;
1098         }
1099
1100         /* This is an unmapped user */
1101
1102         uid_to_unix_users_sid(uid, psid);
1103
1104         {
1105                 struct unixid xid = {
1106                         .id = uid, .type = ID_TYPE_UID
1107                 };
1108                 idmap_cache_set_sid2unixid(psid, &xid);
1109         }
1110
1111  done:
1112         DEBUG(10,("LEGACY: uid %u -> sid %s\n", (unsigned int)uid,
1113                   sid_string_dbg(psid)));
1114
1115         return;
1116 }
1117
1118 /*****************************************************************
1119  *THE LEGACY* convert gid_t to SID function.
1120 *****************************************************************/  
1121
1122 static void legacy_gid_to_sid(struct dom_sid *psid, gid_t gid)
1123 {
1124         bool ret;
1125         struct unixid id;
1126
1127         ZERO_STRUCTP(psid);
1128
1129         id.id = gid;
1130         id.type = ID_TYPE_GID;
1131
1132         become_root();
1133         ret = pdb_id_to_sid(&id, psid);
1134         unbecome_root();
1135
1136         if (ret) {
1137                 /* This is a mapped group */
1138                 goto done;
1139         }
1140
1141         /* This is an unmapped group */
1142
1143         gid_to_unix_groups_sid(gid, psid);
1144
1145         {
1146                 struct unixid xid = {
1147                         .id = gid, .type = ID_TYPE_GID
1148                 };
1149                 idmap_cache_set_sid2unixid(psid, &xid);
1150         }
1151
1152  done:
1153         DEBUG(10,("LEGACY: gid %u -> sid %s\n", (unsigned int)gid,
1154                   sid_string_dbg(psid)));
1155
1156         return;
1157 }
1158
1159 /*****************************************************************
1160  *THE LEGACY* convert SID to id function.
1161 *****************************************************************/  
1162
1163 static bool legacy_sid_to_unixid(const struct dom_sid *psid, struct unixid *id)
1164 {
1165         bool ret;
1166
1167         become_root();
1168         ret = pdb_sid_to_id(psid, id);
1169         unbecome_root();
1170
1171         if (!ret) {
1172                 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1173                           sid_string_dbg(psid)));
1174                 return false;
1175         }
1176
1177         return true;
1178 }
1179
1180 static bool legacy_sid_to_gid(const struct dom_sid *psid, gid_t *pgid)
1181 {
1182         struct unixid id;
1183         if (!legacy_sid_to_unixid(psid, &id)) {
1184                 return false;
1185         }
1186         if (id.type == ID_TYPE_GID || id.type == ID_TYPE_BOTH) {
1187                 *pgid = id.id;
1188                 return true;
1189         }
1190         return false;
1191 }
1192
1193 static bool legacy_sid_to_uid(const struct dom_sid *psid, uid_t *puid)
1194 {
1195         struct unixid id;
1196         if (!legacy_sid_to_unixid(psid, &id)) {
1197                 return false;
1198         }
1199         if (id.type == ID_TYPE_UID || id.type == ID_TYPE_BOTH) {
1200                 *puid = id.id;
1201                 return true;
1202         }
1203         return false;
1204 }
1205
1206 /*****************************************************************
1207  *THE CANONICAL* convert uid_t to SID function.
1208 *****************************************************************/  
1209
1210 void uid_to_sid(struct dom_sid *psid, uid_t uid)
1211 {
1212         bool expired = true;
1213         bool ret;
1214         ZERO_STRUCTP(psid);
1215
1216         /* Check the winbindd cache directly. */
1217         ret = idmap_cache_find_uid2sid(uid, psid, &expired);
1218
1219         if (ret && !expired && is_null_sid(psid)) {
1220                 /*
1221                  * Negative cache entry, we already asked.
1222                  * do legacy.
1223                  */
1224                 legacy_uid_to_sid(psid, uid);
1225                 return;
1226         }
1227
1228         if (!ret || expired) {
1229                 /* Not in cache. Ask winbindd. */
1230                 if (!winbind_uid_to_sid(psid, uid)) {
1231                         /*
1232                          * We shouldn't return the NULL SID
1233                          * here if winbind was running and
1234                          * couldn't map, as winbind will have
1235                          * added a negative entry that will
1236                          * cause us to go though the
1237                          * legacy_uid_to_sid()
1238                          * function anyway in the case above
1239                          * the next time we ask.
1240                          */
1241                         DEBUG(5, ("uid_to_sid: winbind failed to find a sid "
1242                                   "for uid %u\n", (unsigned int)uid));
1243
1244                         legacy_uid_to_sid(psid, uid);
1245                         return;
1246                 }
1247         }
1248
1249         DEBUG(10,("uid %u -> sid %s\n", (unsigned int)uid,
1250                   sid_string_dbg(psid)));
1251
1252         return;
1253 }
1254
1255 /*****************************************************************
1256  *THE CANONICAL* convert gid_t to SID function.
1257 *****************************************************************/  
1258
1259 void gid_to_sid(struct dom_sid *psid, gid_t gid)
1260 {
1261         bool expired = true;
1262         bool ret;
1263         ZERO_STRUCTP(psid);
1264
1265         /* Check the winbindd cache directly. */
1266         ret = idmap_cache_find_gid2sid(gid, psid, &expired);
1267
1268         if (ret && !expired && is_null_sid(psid)) {
1269                 /*
1270                  * Negative cache entry, we already asked.
1271                  * do legacy.
1272                  */
1273                 legacy_gid_to_sid(psid, gid);
1274                 return;
1275         }
1276
1277         if (!ret || expired) {
1278                 /* Not in cache. Ask winbindd. */
1279                 if (!winbind_gid_to_sid(psid, gid)) {
1280                         /*
1281                          * We shouldn't return the NULL SID
1282                          * here if winbind was running and
1283                          * couldn't map, as winbind will have
1284                          * added a negative entry that will
1285                          * cause us to go though the
1286                          * legacy_gid_to_sid()
1287                          * function anyway in the case above
1288                          * the next time we ask.
1289                          */
1290                         DEBUG(5, ("gid_to_sid: winbind failed to find a sid "
1291                                   "for gid %u\n", (unsigned int)gid));
1292
1293                         legacy_gid_to_sid(psid, gid);
1294                         return;
1295                 }
1296         }
1297
1298         DEBUG(10,("gid %u -> sid %s\n", (unsigned int)gid,
1299                   sid_string_dbg(psid)));
1300
1301         return;
1302 }
1303
1304 bool sids_to_unixids(const struct dom_sid *sids, uint32_t num_sids,
1305                      struct unixid *ids)
1306 {
1307         struct wbcDomainSid *wbc_sids = NULL;
1308         struct wbcUnixId *wbc_ids = NULL;
1309         uint32_t i, num_not_cached;
1310         wbcErr err;
1311         bool ret = false;
1312
1313         wbc_sids = talloc_array(talloc_tos(), struct wbcDomainSid, num_sids);
1314         if (wbc_sids == NULL) {
1315                 return false;
1316         }
1317
1318         num_not_cached = 0;
1319
1320         for (i=0; i<num_sids; i++) {
1321                 bool expired;
1322                 uint32_t rid;
1323
1324                 if (sid_peek_check_rid(&global_sid_Unix_Users,
1325                                        &sids[i], &rid)) {
1326                         ids[i].type = ID_TYPE_UID;
1327                         ids[i].id = rid;
1328                         continue;
1329                 }
1330                 if (sid_peek_check_rid(&global_sid_Unix_Groups,
1331                                        &sids[i], &rid)) {
1332                         ids[i].type = ID_TYPE_GID;
1333                         ids[i].id = rid;
1334                         continue;
1335                 }
1336                 if (idmap_cache_find_sid2unixid(&sids[i], &ids[i], &expired)
1337                     && !expired)
1338                 {
1339                         continue;
1340                 }
1341                 ids[i].type = ID_TYPE_NOT_SPECIFIED;
1342                 memcpy(&wbc_sids[num_not_cached], &sids[i],
1343                        ndr_size_dom_sid(&sids[i], 0));
1344                 num_not_cached += 1;
1345         }
1346         if (num_not_cached == 0) {
1347                 goto done;
1348         }
1349         wbc_ids = talloc_array(talloc_tos(), struct wbcUnixId, num_not_cached);
1350         if (wbc_ids == NULL) {
1351                 goto fail;
1352         }
1353         for (i=0; i<num_not_cached; i++) {
1354                 wbc_ids[i].type = WBC_ID_TYPE_NOT_SPECIFIED;
1355         }
1356         err = wbcSidsToUnixIds(wbc_sids, num_not_cached, wbc_ids);
1357         if (!WBC_ERROR_IS_OK(err)) {
1358                 DEBUG(10, ("wbcSidsToUnixIds returned %s\n",
1359                            wbcErrorString(err)));
1360         }
1361
1362         num_not_cached = 0;
1363
1364         for (i=0; i<num_sids; i++) {
1365                 if (ids[i].type == ID_TYPE_NOT_SPECIFIED) {
1366                         switch (wbc_ids[num_not_cached].type) {
1367                         case WBC_ID_TYPE_UID:
1368                                 ids[i].type = ID_TYPE_UID;
1369                                 ids[i].id = wbc_ids[num_not_cached].id.uid;
1370                                 break;
1371                         case WBC_ID_TYPE_GID:
1372                                 ids[i].type = ID_TYPE_GID;
1373                                 ids[i].id = wbc_ids[num_not_cached].id.gid;
1374                                 break;
1375                         default:
1376                                 /* The types match, and wbcUnixId -> id is a union anyway */
1377                                 ids[i].type = (enum id_type)wbc_ids[num_not_cached].type;
1378                                 ids[i].id = wbc_ids[num_not_cached].id.gid;
1379                                 break;
1380                         }
1381                         num_not_cached += 1;
1382                 }
1383         }
1384
1385         for (i=0; i<num_sids; i++) {
1386                 if (ids[i].type != ID_TYPE_NOT_SPECIFIED) {
1387                         continue;
1388                 }
1389                 if (legacy_sid_to_gid(&sids[i], &ids[i].id)) {
1390                         ids[i].type = ID_TYPE_GID;
1391                         continue;
1392                 }
1393                 if (legacy_sid_to_uid(&sids[i], &ids[i].id)) {
1394                         ids[i].type = ID_TYPE_UID;
1395                         continue;
1396                 }
1397         }
1398 done:
1399         for (i=0; i<num_sids; i++) {
1400                 switch(ids[i].type) {
1401                 case WBC_ID_TYPE_GID:
1402                 case WBC_ID_TYPE_UID:
1403                 case WBC_ID_TYPE_BOTH:
1404                         if (ids[i].id == -1) {
1405                                 ids[i].type = ID_TYPE_NOT_SPECIFIED;
1406                         }
1407                         break;
1408                 case WBC_ID_TYPE_NOT_SPECIFIED:
1409                         break;
1410                 }
1411         }
1412
1413         ret = true;
1414 fail:
1415         TALLOC_FREE(wbc_ids);
1416         TALLOC_FREE(wbc_sids);
1417         return ret;
1418 }
1419
1420 /*****************************************************************
1421  *THE CANONICAL* convert SID to uid function.
1422 *****************************************************************/  
1423
1424 bool sid_to_uid(const struct dom_sid *psid, uid_t *puid)
1425 {
1426         bool expired = true;
1427         bool ret;
1428         uint32_t rid;
1429
1430         /* Optimize for the Unix Users Domain
1431          * as the conversion is straightforward */
1432         if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
1433                 uid_t uid = rid;
1434                 *puid = uid;
1435
1436                 /* return here, don't cache */
1437                 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1438                         (unsigned int)*puid ));
1439                 return true;
1440         }
1441
1442         /* Check the winbindd cache directly. */
1443         ret = idmap_cache_find_sid2uid(psid, puid, &expired);
1444
1445         if (ret && !expired && (*puid == (uid_t)-1)) {
1446                 /*
1447                  * Negative cache entry, we already asked.
1448                  * do legacy.
1449                  */
1450                 return legacy_sid_to_uid(psid, puid);
1451         }
1452
1453         if (!ret || expired) {
1454                 /* Not in cache. Ask winbindd. */
1455                 if (!winbind_sid_to_uid(puid, psid)) {
1456                         DEBUG(5, ("winbind failed to find a uid for sid %s\n",
1457                                   sid_string_dbg(psid)));
1458                         /* winbind failed. do legacy */
1459                         return legacy_sid_to_uid(psid, puid);
1460                 }
1461         }
1462
1463         /* TODO: Here would be the place to allocate both a gid and a uid for
1464          * the SID in question */
1465
1466         DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1467                 (unsigned int)*puid ));
1468
1469         return true;
1470 }
1471
1472 /*****************************************************************
1473  *THE CANONICAL* convert SID to gid function.
1474  Group mapping is used for gids that maps to Wellknown SIDs
1475 *****************************************************************/  
1476
1477 bool sid_to_gid(const struct dom_sid *psid, gid_t *pgid)
1478 {
1479         bool expired = true;
1480         bool ret;
1481         uint32_t rid;
1482
1483         /* Optimize for the Unix Groups Domain
1484          * as the conversion is straightforward */
1485         if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
1486                 gid_t gid = rid;
1487                 *pgid = gid;
1488
1489                 /* return here, don't cache */
1490                 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1491                         (unsigned int)*pgid ));
1492                 return true;
1493         }
1494
1495         /* Check the winbindd cache directly. */
1496         ret = idmap_cache_find_sid2gid(psid, pgid, &expired);
1497
1498         if (ret && !expired && (*pgid == (gid_t)-1)) {
1499                 /*
1500                  * Negative cache entry, we already asked.
1501                  * do legacy.
1502                  */
1503                 return legacy_sid_to_gid(psid, pgid);
1504         }
1505
1506         if (!ret || expired) {
1507                 /* Not in cache or negative. Ask winbindd. */
1508                 /* Ask winbindd if it can map this sid to a gid.
1509                  * (Idmap will check it is a valid SID and of the right type) */
1510
1511                 if ( !winbind_sid_to_gid(pgid, psid) ) {
1512
1513                         DEBUG(10,("winbind failed to find a gid for sid %s\n",
1514                                   sid_string_dbg(psid)));
1515                         /* winbind failed. do legacy */
1516                         return legacy_sid_to_gid(psid, pgid);
1517                 }
1518         }
1519
1520         DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1521                   (unsigned int)*pgid ));
1522
1523         return true;
1524 }
1525
1526 /**
1527  * @brief This function gets the primary group SID mapping the primary
1528  *        GID of the user as obtained by an actual getpwnam() call.
1529  *        This is necessary to avoid issues with arbitrary group SIDs
1530  *        stored in passdb. We try as hard as we can to get the SID
1531  *        corresponding to the GID, including trying group mapping.
1532  *        If nothing else works, we will force "Domain Users" as the
1533  *        primary group.
1534  *        This is needed because we must always be able to lookup the
1535  *        primary group SID, so we cannot settle for an arbitrary SID.
1536  *
1537  *        This call can be expensive. Use with moderation.
1538  *        If you have a "samu" struct around use pdb_get_group_sid()
1539  *        instead as it does properly cache results.
1540  *
1541  * @param mem_ctx[in]     The memory context iused to allocate the result.
1542  * @param username[in]    The user's name
1543  * @param _pwd[in|out]    If available, pass in user's passwd struct.
1544  *                        It will contain a tallocated passwd if NULL was
1545  *                        passed in.
1546  * @param _group_sid[out] The user's Primary Group SID
1547  *
1548  * @return NTSTATUS error code.
1549  */
1550 NTSTATUS get_primary_group_sid(TALLOC_CTX *mem_ctx,
1551                                 const char *username,
1552                                 struct passwd **_pwd,
1553                                 struct dom_sid **_group_sid)
1554 {
1555         TALLOC_CTX *tmp_ctx;
1556         bool need_lookup_sid = false;
1557         struct dom_sid *group_sid;
1558         struct passwd *pwd = *_pwd;
1559
1560         tmp_ctx = talloc_new(mem_ctx);
1561         if (!tmp_ctx) {
1562                 return NT_STATUS_NO_MEMORY;
1563         }
1564
1565         if (!pwd) {
1566                 pwd = Get_Pwnam_alloc(mem_ctx, username);
1567                 if (!pwd) {
1568                         DEBUG(0, ("Failed to find a Unix account for %s\n",
1569                                   username));
1570                         TALLOC_FREE(tmp_ctx);
1571                         return NT_STATUS_NO_SUCH_USER;
1572                 }
1573         }
1574
1575         group_sid = talloc_zero(mem_ctx, struct dom_sid);
1576         if (!group_sid) {
1577                 TALLOC_FREE(tmp_ctx);
1578                 return NT_STATUS_NO_MEMORY;
1579         }
1580
1581         gid_to_sid(group_sid, pwd->pw_gid);
1582         if (!is_null_sid(group_sid)) {
1583                 struct dom_sid domain_sid;
1584                 uint32_t rid;
1585
1586                 /* We need a sid within our domain */
1587                 sid_copy(&domain_sid, group_sid);
1588                 sid_split_rid(&domain_sid, &rid);
1589                 if (dom_sid_equal(&domain_sid, get_global_sam_sid())) {
1590                         /*
1591                          * As shortcut for the expensive lookup_sid call
1592                          * compare the domain sid part
1593                          */
1594                         switch (rid) {
1595                         case DOMAIN_RID_ADMINS:
1596                         case DOMAIN_RID_USERS:
1597                                 goto done;
1598                         default:
1599                                 need_lookup_sid = true;
1600                                 break;
1601                         }
1602                 } else {
1603                         /* Try group mapping */
1604                         struct unixid id;
1605
1606                         id.id = pwd->pw_gid;
1607                         id.type = ID_TYPE_GID;
1608
1609                         ZERO_STRUCTP(group_sid);
1610                         if (pdb_id_to_sid(&id, group_sid)) {
1611                                 need_lookup_sid = true;
1612                         }
1613                 }
1614         }
1615
1616         /* We must verify that this is a valid SID that resolves to a
1617          * group of the correct type */
1618         if (need_lookup_sid) {
1619                 enum lsa_SidType type = SID_NAME_UNKNOWN;
1620                 bool lookup_ret;
1621
1622                 DEBUG(10, ("do lookup_sid(%s) for group of user %s\n",
1623                            sid_string_dbg(group_sid), username));
1624
1625                 /* Now check that it's actually a domain group and
1626                  * not something else */
1627                 lookup_ret = lookup_sid(tmp_ctx, group_sid,
1628                                         NULL, NULL, &type);
1629
1630                 if (lookup_ret && (type == SID_NAME_DOM_GRP)) {
1631                         goto done;
1632                 }
1633
1634                 DEBUG(3, ("Primary group %s for user %s is"
1635                           " a %s and not a domain group\n",
1636                           sid_string_dbg(group_sid), username,
1637                           sid_type_lookup(type)));
1638         }
1639
1640         /* Everything else, failed.
1641          * Just set it to the 'Domain Users' RID of 513 which will
1642            always resolve to a name */
1643         DEBUG(3, ("Forcing Primary Group to 'Domain Users' for %s\n",
1644                   username));
1645
1646         sid_compose(group_sid, get_global_sam_sid(), DOMAIN_RID_USERS);
1647
1648 done:
1649         *_pwd = talloc_move(mem_ctx, &pwd);
1650         *_group_sid = talloc_move(mem_ctx, &group_sid);
1651         TALLOC_FREE(tmp_ctx);
1652         return NT_STATUS_OK;
1653 }
1654