lib: Add lib/util_unixsids.h
[samba.git] / source3 / auth / token_util.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  Authentication utility functions
4  *  Copyright (C) Andrew Tridgell 1992-1998
5  *  Copyright (C) Andrew Bartlett 2001
6  *  Copyright (C) Jeremy Allison 2000-2001
7  *  Copyright (C) Rafal Szczesniak 2002
8  *  Copyright (C) Volker Lendecke 2006
9  *  Copyright (C) Michael Adam 2007
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 3 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
23  */
24
25 /* functions moved from auth/auth_util.c to minimize linker deps */
26
27 #include "includes.h"
28 #include "lib/util_unixsids.h"
29 #include "system/passwd.h"
30 #include "auth.h"
31 #include "secrets.h"
32 #include "../lib/util/memcache.h"
33 #include "../librpc/gen_ndr/netlogon.h"
34 #include "../libcli/security/security.h"
35 #include "../lib/util/util_pw.h"
36 #include "passdb.h"
37 #include "lib/privileges.h"
38
39 /****************************************************************************
40  Check for a SID in an struct security_token
41 ****************************************************************************/
42
43 bool nt_token_check_sid ( const struct dom_sid *sid, const struct security_token *token )
44 {
45         if ( !sid || !token )
46                 return False;
47
48         return security_token_has_sid(token, sid);
49 }
50
51 bool nt_token_check_domain_rid( struct security_token *token, uint32_t rid )
52 {
53         struct dom_sid domain_sid;
54
55         /* if we are a domain member, the get the domain SID, else for
56            a DC or standalone server, use our own SID */
57
58         if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
59                 if ( !secrets_fetch_domain_sid( lp_workgroup(),
60                                                 &domain_sid ) ) {
61                         DEBUG(1,("nt_token_check_domain_rid: Cannot lookup "
62                                  "SID for domain [%s]\n", lp_workgroup()));
63                         return False;
64                 }
65         }
66         else
67                 sid_copy( &domain_sid, get_global_sam_sid() );
68
69         sid_append_rid( &domain_sid, rid );
70
71         return nt_token_check_sid( &domain_sid, token );\
72 }
73
74 /******************************************************************************
75  Create a token for the root user to be used internally by smbd.
76  This is similar to running under the context of the LOCAL_SYSTEM account
77  in Windows.  This is a read-only token.  Do not modify it or free() it.
78  Create a copy if you need to change it.
79 ******************************************************************************/
80
81 struct security_token *get_root_nt_token( void )
82 {
83         struct security_token *token, *for_cache;
84         struct dom_sid u_sid, g_sid;
85         struct passwd *pw;
86         void *cache_data;
87
88         cache_data = memcache_lookup_talloc(
89                 NULL, SINGLETON_CACHE_TALLOC,
90                 data_blob_string_const_null("root_nt_token"));
91
92         if (cache_data != NULL) {
93                 return talloc_get_type_abort(
94                         cache_data, struct security_token);
95         }
96
97         if ( !(pw = getpwuid(0)) ) {
98                 if ( !(pw = getpwnam("root")) ) {
99                         DEBUG(0,("get_root_nt_token: both getpwuid(0) "
100                                 "and getpwnam(\"root\") failed!\n"));
101                         return NULL;
102                 }
103         }
104
105         /* get the user and primary group SIDs; although the
106            BUILTIN\Administrators SId is really the one that matters here */
107
108         uid_to_sid(&u_sid, pw->pw_uid);
109         gid_to_sid(&g_sid, pw->pw_gid);
110
111         token = create_local_nt_token(talloc_tos(), &u_sid, False,
112                                       1, &global_sid_Builtin_Administrators);
113
114         security_token_set_privilege(token, SEC_PRIV_DISK_OPERATOR);
115
116         for_cache = token;
117
118         memcache_add_talloc(
119                 NULL, SINGLETON_CACHE_TALLOC,
120                 data_blob_string_const_null("root_nt_token"), &for_cache);
121
122         return token;
123 }
124
125
126 /*
127  * Add alias SIDs from memberships within the partially created token SID list
128  */
129
130 NTSTATUS add_aliases(const struct dom_sid *domain_sid,
131                      struct security_token *token)
132 {
133         uint32_t *aliases;
134         size_t i, num_aliases;
135         NTSTATUS status;
136         TALLOC_CTX *tmp_ctx;
137
138         if (!(tmp_ctx = talloc_init("add_aliases"))) {
139                 return NT_STATUS_NO_MEMORY;
140         }
141
142         aliases = NULL;
143         num_aliases = 0;
144
145         status = pdb_enum_alias_memberships(tmp_ctx, domain_sid,
146                                             token->sids,
147                                             token->num_sids,
148                                             &aliases, &num_aliases);
149
150         if (!NT_STATUS_IS_OK(status)) {
151                 DEBUG(10, ("pdb_enum_alias_memberships failed: %s\n",
152                            nt_errstr(status)));
153                 goto done;
154         }
155
156         for (i=0; i<num_aliases; i++) {
157                 struct dom_sid alias_sid;
158                 sid_compose(&alias_sid, domain_sid, aliases[i]);
159                 status = add_sid_to_array_unique(token, &alias_sid,
160                                                  &token->sids,
161                                                  &token->num_sids);
162                 if (!NT_STATUS_IS_OK(status)) {
163                         DEBUG(0, ("add_sid_to_array failed\n"));
164                         goto done;
165                 }
166         }
167
168 done:
169         TALLOC_FREE(tmp_ctx);
170         return NT_STATUS_OK;
171 }
172
173 /*******************************************************************
174 *******************************************************************/
175
176 static NTSTATUS add_builtin_administrators(struct security_token *token,
177                                            const struct dom_sid *dom_sid)
178 {
179         struct dom_sid domadm;
180         NTSTATUS status;
181
182         /* nothing to do if we aren't in a domain */
183
184         if ( !(IS_DC || lp_server_role()==ROLE_DOMAIN_MEMBER) ) {
185                 return NT_STATUS_OK;
186         }
187
188         /* Find the Domain Admins SID */
189
190         if ( IS_DC ) {
191                 sid_copy( &domadm, get_global_sam_sid() );
192         } else {
193                 sid_copy(&domadm, dom_sid);
194         }
195         sid_append_rid( &domadm, DOMAIN_RID_ADMINS );
196
197         /* Add Administrators if the user beloongs to Domain Admins */
198
199         if ( nt_token_check_sid( &domadm, token ) ) {
200                 status = add_sid_to_array(token,
201                                           &global_sid_Builtin_Administrators,
202                                           &token->sids, &token->num_sids);
203         if (!NT_STATUS_IS_OK(status)) {
204                         return status;
205                 }
206         }
207
208         return NT_STATUS_OK;
209 }
210
211 static NTSTATUS finalize_local_nt_token(struct security_token *result,
212                                         bool is_guest);
213
214 NTSTATUS create_local_nt_token_from_info3(TALLOC_CTX *mem_ctx,
215                                           bool is_guest,
216                                           const struct netr_SamInfo3 *info3,
217                                           const struct extra_auth_info *extra,
218                                           struct security_token **ntok)
219 {
220         struct security_token *usrtok = NULL;
221         NTSTATUS status;
222         int i;
223
224         DEBUG(10, ("Create local NT token for %s\n",
225                    info3->base.account_name.string));
226
227         usrtok = talloc_zero(mem_ctx, struct security_token);
228         if (!usrtok) {
229                 DEBUG(0, ("talloc failed\n"));
230                 return NT_STATUS_NO_MEMORY;
231         }
232
233         /* Add the user and primary group sid FIRST */
234         /* check if the user rid is the special "Domain Guests" rid.
235          * If so pick the first sid for the extra sids instead as it
236          * is a local fake account */
237         usrtok->sids = talloc_array(usrtok, struct dom_sid, 2);
238         if (!usrtok->sids) {
239                 TALLOC_FREE(usrtok);
240                 return NT_STATUS_NO_MEMORY;
241         }
242         usrtok->num_sids = 2;
243
244         /* USER SID */
245         if (info3->base.rid == (uint32_t)(-1)) {
246                 /* this is a signal the user was fake and generated,
247                  * the actual SID we want to use is stored in the extra
248                  * sids */
249                 if (is_null_sid(&extra->user_sid)) {
250                         /* we couldn't find the user sid, bail out */
251                         DEBUG(3, ("Invalid user SID\n"));
252                         TALLOC_FREE(usrtok);
253                         return NT_STATUS_UNSUCCESSFUL;
254                 }
255                 sid_copy(&usrtok->sids[0], &extra->user_sid);
256         } else {
257                 sid_copy(&usrtok->sids[0], info3->base.domain_sid);
258                 sid_append_rid(&usrtok->sids[0], info3->base.rid);
259         }
260
261         /* GROUP SID */
262         if (info3->base.primary_gid == (uint32_t)(-1)) {
263                 /* this is a signal the user was fake and generated,
264                  * the actual SID we want to use is stored in the extra
265                  * sids */
266                 if (is_null_sid(&extra->pgid_sid)) {
267                         /* we couldn't find the user sid, bail out */
268                         DEBUG(3, ("Invalid group SID\n"));
269                         TALLOC_FREE(usrtok);
270                         return NT_STATUS_UNSUCCESSFUL;
271                 }
272                 sid_copy(&usrtok->sids[1], &extra->pgid_sid);
273         } else {
274                 sid_copy(&usrtok->sids[1], info3->base.domain_sid);
275                 sid_append_rid(&usrtok->sids[1],
276                                 info3->base.primary_gid);
277         }
278
279         /* Now the SIDs we got from authentication. These are the ones from
280          * the info3 struct or from the pdb_enum_group_memberships, depending
281          * on who authenticated the user.
282          * Note that we start the for loop at "1" here, we already added the
283          * first group sid as primary above. */
284
285         for (i = 0; i < info3->base.groups.count; i++) {
286                 struct dom_sid tmp_sid;
287
288                 sid_copy(&tmp_sid, info3->base.domain_sid);
289                 sid_append_rid(&tmp_sid, info3->base.groups.rids[i].rid);
290
291                 status = add_sid_to_array_unique(usrtok, &tmp_sid,
292                                                  &usrtok->sids,
293                                                  &usrtok->num_sids);
294                 if (!NT_STATUS_IS_OK(status)) {
295                         DEBUG(3, ("Failed to add SID to nt token\n"));
296                         TALLOC_FREE(usrtok);
297                         return status;
298                 }
299         }
300
301         /* now also add extra sids if they are not the special user/group
302          * sids */
303         for (i = 0; i < info3->sidcount; i++) {
304                 status = add_sid_to_array_unique(usrtok,
305                                                  info3->sids[i].sid,
306                                                  &usrtok->sids,
307                                                  &usrtok->num_sids);
308                 if (!NT_STATUS_IS_OK(status)) {
309                         DEBUG(3, ("Failed to add SID to nt token\n"));
310                         TALLOC_FREE(usrtok);
311                         return status;
312                 }
313         }
314
315         status = finalize_local_nt_token(usrtok, is_guest);
316         if (!NT_STATUS_IS_OK(status)) {
317                 DEBUG(3, ("Failed to finalize nt token\n"));
318                 TALLOC_FREE(usrtok);
319                 return status;
320         }
321
322         *ntok = usrtok;
323         return NT_STATUS_OK;
324 }
325
326 /*******************************************************************
327  Create a NT token for the user, expanding local aliases
328 *******************************************************************/
329
330 struct security_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
331                                             const struct dom_sid *user_sid,
332                                             bool is_guest,
333                                             int num_groupsids,
334                                             const struct dom_sid *groupsids)
335 {
336         struct security_token *result = NULL;
337         int i;
338         NTSTATUS status;
339
340         DEBUG(10, ("Create local NT token for %s\n",
341                    sid_string_dbg(user_sid)));
342
343         if (!(result = talloc_zero(mem_ctx, struct security_token))) {
344                 DEBUG(0, ("talloc failed\n"));
345                 return NULL;
346         }
347
348         /* Add the user and primary group sid */
349
350         status = add_sid_to_array(result, user_sid,
351                                   &result->sids, &result->num_sids);
352         if (!NT_STATUS_IS_OK(status)) {
353                 TALLOC_FREE(result);
354                 return NULL;
355         }
356
357         /* For guest, num_groupsids may be zero. */
358         if (num_groupsids) {
359                 status = add_sid_to_array(result, &groupsids[0],
360                                           &result->sids,
361                                           &result->num_sids);
362                 if (!NT_STATUS_IS_OK(status)) {
363                         TALLOC_FREE(result);
364                         return NULL;
365                 }
366         }
367
368         /* Now the SIDs we got from authentication. These are the ones from
369          * the info3 struct or from the pdb_enum_group_memberships, depending
370          * on who authenticated the user.
371          * Note that we start the for loop at "1" here, we already added the
372          * first group sid as primary above. */
373
374         for (i=1; i<num_groupsids; i++) {
375                 status = add_sid_to_array_unique(result, &groupsids[i],
376                                                  &result->sids,
377                                                  &result->num_sids);
378                 if (!NT_STATUS_IS_OK(status)) {
379                         TALLOC_FREE(result);
380                         return NULL;
381                 }
382         }
383
384         status = finalize_local_nt_token(result, is_guest);
385         if (!NT_STATUS_IS_OK(status)) {
386                 TALLOC_FREE(result);
387                 return NULL;
388         }
389
390         return result;
391 }
392
393 /***************************************************
394  Merge in any groups from /etc/group.
395 ***************************************************/
396
397 static NTSTATUS add_local_groups(struct security_token *result,
398                                  bool is_guest)
399 {
400         gid_t *gids = NULL;
401         uint32_t getgroups_num_group_sids = 0;
402         struct passwd *pass = NULL;
403         TALLOC_CTX *tmp_ctx = talloc_stackframe();
404         int i;
405
406         if (is_guest) {
407                 /*
408                  * Guest is a special case. It's always
409                  * a user that can be looked up, but
410                  * result->sids[0] is set to DOMAIN\Guest.
411                  * Lookup by account name instead.
412                  */
413                 pass = Get_Pwnam_alloc(tmp_ctx, lp_guest_account());
414         } else {
415                 uid_t uid;
416
417                 /* For non-guest result->sids[0] is always the user sid. */
418                 if (!sid_to_uid(&result->sids[0], &uid)) {
419                         /*
420                          * Non-mappable SID like SYSTEM.
421                          * Can't be in any /etc/group groups.
422                          */
423                         TALLOC_FREE(tmp_ctx);
424                         return NT_STATUS_OK;
425                 }
426
427                 pass = getpwuid_alloc(tmp_ctx, uid);
428                 if (pass == NULL) {
429                         DEBUG(1, ("SID %s -> getpwuid(%u) failed\n",
430                                 sid_string_dbg(&result->sids[0]),
431                                 (unsigned int)uid));
432                 }
433         }
434
435         if (!pass) {
436                 TALLOC_FREE(tmp_ctx);
437                 return NT_STATUS_UNSUCCESSFUL;
438         }
439
440         /*
441          * Now we must get any groups this user has been
442          * added to in /etc/group and merge them in.
443          * This has to be done in every code path
444          * that creates an NT token, as remote users
445          * may have been added to the local /etc/group
446          * database. Tokens created merely from the
447          * info3 structs (via the DC or via the krb5 PAC)
448          * won't have these local groups. Note the
449          * groups added here will only be UNIX groups
450          * (S-1-22-2-XXXX groups) as getgroups_unix_user()
451          * turns off winbindd before calling getgroups().
452          *
453          * NB. This is duplicating work already
454          * done in the 'unix_user:' case of
455          * create_token_from_sid() but won't
456          * do anything other than be inefficient
457          * in that case.
458          */
459
460         if (!getgroups_unix_user(tmp_ctx, pass->pw_name, pass->pw_gid,
461                         &gids, &getgroups_num_group_sids)) {
462                 DEBUG(1, ("getgroups_unix_user for user %s failed\n",
463                         pass->pw_name));
464                 TALLOC_FREE(tmp_ctx);
465                 return NT_STATUS_UNSUCCESSFUL;
466         }
467
468         for (i=0; i<getgroups_num_group_sids; i++) {
469                 NTSTATUS status;
470                 struct dom_sid grp_sid;
471                 gid_to_sid(&grp_sid, gids[i]);
472
473                 status = add_sid_to_array_unique(result,
474                                          &grp_sid,
475                                          &result->sids,
476                                          &result->num_sids);
477                 if (!NT_STATUS_IS_OK(status)) {
478                         DEBUG(3, ("Failed to add UNIX SID to nt token\n"));
479                         TALLOC_FREE(tmp_ctx);
480                         return status;
481                 }
482         }
483         TALLOC_FREE(tmp_ctx);
484         return NT_STATUS_OK;
485 }
486
487 static NTSTATUS finalize_local_nt_token(struct security_token *result,
488                                         bool is_guest)
489 {
490         struct dom_sid dom_sid;
491         NTSTATUS status;
492         struct acct_info *info;
493
494         /* Add any local groups. */
495
496         status = add_local_groups(result, is_guest);
497         if (!NT_STATUS_IS_OK(status)) {
498                 return status;
499         }
500
501         /* Add in BUILTIN sids */
502
503         status = add_sid_to_array(result, &global_sid_World,
504                                   &result->sids, &result->num_sids);
505         if (!NT_STATUS_IS_OK(status)) {
506                 return status;
507         }
508         status = add_sid_to_array(result, &global_sid_Network,
509                                   &result->sids, &result->num_sids);
510         if (!NT_STATUS_IS_OK(status)) {
511                 return status;
512         }
513
514         if (is_guest) {
515                 status = add_sid_to_array(result, &global_sid_Builtin_Guests,
516                                           &result->sids,
517                                           &result->num_sids);
518                 if (!NT_STATUS_IS_OK(status)) {
519                         return status;
520                 }
521         } else {
522                 status = add_sid_to_array(result,
523                                           &global_sid_Authenticated_Users,
524                                           &result->sids,
525                                           &result->num_sids);
526                 if (!NT_STATUS_IS_OK(status)) {
527                         return status;
528                 }
529         }
530
531         info = talloc_zero(talloc_tos(), struct acct_info);
532         if (info == NULL) {
533                 DEBUG(0, ("talloc failed!\n"));
534                 return NT_STATUS_NO_MEMORY;
535         }
536
537         /* Deal with the BUILTIN\Administrators group.  If the SID can
538            be resolved then assume that the add_aliasmem( S-1-5-32 )
539            handled it. */
540
541         status = pdb_get_aliasinfo(&global_sid_Builtin_Administrators, info);
542         if (!NT_STATUS_IS_OK(status)) {
543
544                 become_root();
545                 if (!secrets_fetch_domain_sid(lp_workgroup(), &dom_sid)) {
546                         status = NT_STATUS_OK;
547                         DEBUG(3, ("Failed to fetch domain sid for %s\n",
548                                   lp_workgroup()));
549                 } else {
550                         status = create_builtin_administrators(&dom_sid);
551                 }
552                 unbecome_root();
553
554                 if (NT_STATUS_EQUAL(status, NT_STATUS_PROTOCOL_UNREACHABLE)) {
555                         /* Add BUILTIN\Administrators directly to token. */
556                         status = add_builtin_administrators(result, &dom_sid);
557                         if ( !NT_STATUS_IS_OK(status) ) {
558                                 DEBUG(3, ("Failed to check for local "
559                                           "Administrators membership (%s)\n",
560                                           nt_errstr(status)));
561                         }
562                 } else if (!NT_STATUS_IS_OK(status)) {
563                         DEBUG(2, ("WARNING: Failed to create "
564                                   "BUILTIN\\Administrators group!  Can "
565                                   "Winbind allocate gids?\n"));
566                 }
567         }
568
569         /* Deal with the BUILTIN\Users group.  If the SID can
570            be resolved then assume that the add_aliasmem( S-1-5-32 )
571            handled it. */
572
573         status = pdb_get_aliasinfo(&global_sid_Builtin_Users, info);
574         if (!NT_STATUS_IS_OK(status)) {
575
576                 become_root();
577                 if (!secrets_fetch_domain_sid(lp_workgroup(), &dom_sid)) {
578                         status = NT_STATUS_OK;
579                         DEBUG(3, ("Failed to fetch domain sid for %s\n",
580                                   lp_workgroup()));
581                 } else {
582                         status = create_builtin_users(&dom_sid);
583                 }
584                 unbecome_root();
585
586                 if (!NT_STATUS_EQUAL(status, NT_STATUS_PROTOCOL_UNREACHABLE) &&
587                     !NT_STATUS_IS_OK(status))
588                 {
589                         DEBUG(2, ("WARNING: Failed to create BUILTIN\\Users group! "
590                                   "Can Winbind allocate gids?\n"));
591                 }
592         }
593
594         TALLOC_FREE(info);
595
596         /* Deal with local groups */
597
598         if (lp_winbind_nested_groups()) {
599
600                 become_root();
601
602                 /* Now add the aliases. First the one from our local SAM */
603
604                 status = add_aliases(get_global_sam_sid(), result);
605
606                 if (!NT_STATUS_IS_OK(status)) {
607                         unbecome_root();
608                         return status;
609                 }
610
611                 /* Finally the builtin ones */
612
613                 status = add_aliases(&global_sid_Builtin, result);
614
615                 if (!NT_STATUS_IS_OK(status)) {
616                         unbecome_root();
617                         return status;
618                 }
619
620                 unbecome_root();
621         }
622
623         /* Add privileges based on current user sids */
624
625         get_privileges_for_sids(&result->privilege_mask, result->sids,
626                                 result->num_sids);
627
628         return NT_STATUS_OK;
629 }
630
631 /****************************************************************************
632  prints a UNIX 'token' to debug output.
633 ****************************************************************************/
634
635 void debug_unix_user_token(int dbg_class, int dbg_lev, uid_t uid, gid_t gid,
636                            int n_groups, gid_t *groups)
637 {
638         int     i;
639         DEBUGC(dbg_class, dbg_lev,
640                ("UNIX token of user %ld\n", (long int)uid));
641
642         DEBUGADDC(dbg_class, dbg_lev,
643                   ("Primary group is %ld and contains %i supplementary "
644                    "groups\n", (long int)gid, n_groups));
645         for (i = 0; i < n_groups; i++)
646                 DEBUGADDC(dbg_class, dbg_lev, ("Group[%3i]: %ld\n", i,
647                         (long int)groups[i]));
648 }
649
650 /*
651  * Create an artificial NT token given just a domain SID.
652  *
653  * We have 3 cases:
654  *
655  * unmapped unix users: Go directly to nss to find the user's group.
656  *
657  * A passdb user: The list of groups is provided by pdb_enum_group_memberships.
658  *
659  * If the user is provided by winbind, the primary gid is set to "domain
660  * users" of the user's domain. For an explanation why this is necessary, see
661  * the thread starting at
662  * http://lists.samba.org/archive/samba-technical/2006-January/044803.html.
663  */
664
665 static NTSTATUS create_token_from_sid(TALLOC_CTX *mem_ctx,
666                                       const struct dom_sid *user_sid,
667                                       bool is_guest,
668                                       uid_t *uid, gid_t *gid,
669                                       char **found_username,
670                                       struct security_token **token)
671 {
672         NTSTATUS result = NT_STATUS_NO_SUCH_USER;
673         TALLOC_CTX *tmp_ctx = talloc_stackframe();
674         gid_t *gids;
675         struct dom_sid *group_sids;
676         struct dom_sid tmp_sid;
677         uint32_t num_group_sids;
678         uint32_t num_gids;
679         uint32_t i;
680         uint32_t high, low;
681         bool range_ok;
682
683         if (sid_check_is_in_our_sam(user_sid)) {
684                 bool ret;
685                 uint32_t pdb_num_group_sids;
686                 /* This is a passdb user, so ask passdb */
687
688                 struct samu *sam_acct = NULL;
689
690                 if ( !(sam_acct = samu_new( tmp_ctx )) ) {
691                         result = NT_STATUS_NO_MEMORY;
692                         goto done;
693                 }
694
695                 become_root();
696                 ret = pdb_getsampwsid(sam_acct, user_sid);
697                 unbecome_root();
698
699                 if (!ret) {
700                         DEBUG(1, ("pdb_getsampwsid(%s) failed\n",
701                                   sid_string_dbg(user_sid)));
702                         DEBUGADD(1, ("Fall back to unix user\n"));
703                         goto unix_user;
704                 }
705
706                 result = pdb_enum_group_memberships(tmp_ctx, sam_acct,
707                                                     &group_sids, &gids,
708                                                     &pdb_num_group_sids);
709                 if (!NT_STATUS_IS_OK(result)) {
710                         DEBUG(1, ("enum_group_memberships failed for %s: "
711                                   "%s\n", sid_string_dbg(user_sid),
712                                   nt_errstr(result)));
713                         DEBUGADD(1, ("Fall back to unix uid lookup\n"));
714                         goto unix_user;
715                 }
716                 num_group_sids = pdb_num_group_sids;
717
718                 /* see the smb_panic() in pdb_default_enum_group_memberships */
719                 SMB_ASSERT(num_group_sids > 0);
720
721                 /* Ensure we're returning the found_username on the right context. */
722                 *found_username = talloc_strdup(mem_ctx,
723                                                 pdb_get_username(sam_acct));
724
725                 if (*found_username == NULL) {
726                         result = NT_STATUS_NO_MEMORY;
727                         goto done;
728                 }
729
730                 /*
731                  * If the SID from lookup_name() was the guest sid, passdb knows
732                  * about the mapping of guest sid to lp_guest_account()
733                  * username and will return the unix_pw info for a guest
734                  * user. Use it if it's there, else lookup the *uid details
735                  * using Get_Pwnam_alloc(). See bug #6291 for details. JRA.
736                  */
737
738                 /* We must always assign the *uid. */
739                 if (sam_acct->unix_pw == NULL) {
740                         struct passwd *pwd = Get_Pwnam_alloc(sam_acct, *found_username );
741                         if (!pwd) {
742                                 DEBUG(10, ("Get_Pwnam_alloc failed for %s\n",
743                                         *found_username));
744                                 result = NT_STATUS_NO_SUCH_USER;
745                                 goto done;
746                         }
747                         result = samu_set_unix(sam_acct, pwd );
748                         if (!NT_STATUS_IS_OK(result)) {
749                                 DEBUG(10, ("samu_set_unix failed for %s\n",
750                                         *found_username));
751                                 result = NT_STATUS_NO_SUCH_USER;
752                                 goto done;
753                         }
754                 }
755                 *uid = sam_acct->unix_pw->pw_uid;
756
757         } else  if (sid_check_is_in_unix_users(user_sid)) {
758                 uint32_t getgroups_num_group_sids;
759                 /* This is a unix user not in passdb. We need to ask nss
760                  * directly, without consulting passdb */
761
762                 struct passwd *pass;
763
764                 /*
765                  * This goto target is used as a fallback for the passdb
766                  * case. The concrete bug report is when passdb gave us an
767                  * unmapped gid.
768                  */
769
770         unix_user:
771
772                 if (!sid_to_uid(user_sid, uid)) {
773                         DEBUG(1, ("unix_user case, sid_to_uid for %s failed\n",
774                                   sid_string_dbg(user_sid)));
775                         result = NT_STATUS_NO_SUCH_USER;
776                         goto done;
777                 }
778
779                 uid_to_unix_users_sid(*uid, &tmp_sid);
780                 user_sid = &tmp_sid;
781
782                 pass = getpwuid_alloc(tmp_ctx, *uid);
783                 if (pass == NULL) {
784                         DEBUG(1, ("getpwuid(%u) failed\n",
785                                   (unsigned int)*uid));
786                         goto done;
787                 }
788
789                 if (!getgroups_unix_user(tmp_ctx, pass->pw_name, pass->pw_gid,
790                                          &gids, &getgroups_num_group_sids)) {
791                         DEBUG(1, ("getgroups_unix_user for user %s failed\n",
792                                   pass->pw_name));
793                         goto done;
794                 }
795                 num_group_sids = getgroups_num_group_sids;
796
797                 group_sids = talloc_array(tmp_ctx, struct dom_sid, num_group_sids);
798                 if (group_sids == NULL) {
799                         DEBUG(1, ("talloc_array failed\n"));
800                         result = NT_STATUS_NO_MEMORY;
801                         goto done;
802                 }
803
804                 for (i=0; i<num_group_sids; i++) {
805                         gid_to_sid(&group_sids[i], gids[i]);
806                 }
807
808                 /* In getgroups_unix_user we always set the primary gid */
809                 SMB_ASSERT(num_group_sids > 0);
810
811                 /* Ensure we're returning the found_username on the right context. */
812                 *found_username = talloc_strdup(mem_ctx, pass->pw_name);
813                 if (*found_username == NULL) {
814                         result = NT_STATUS_NO_MEMORY;
815                         goto done;
816                 }
817         } else {
818
819                 /* This user is from winbind, force the primary gid to the
820                  * user's "domain users" group. Under certain circumstances
821                  * (user comes from NT4), this might be a loss of
822                  * information. But we can not rely on winbind getting the
823                  * correct info. AD might prohibit winbind looking up that
824                  * information. */
825
826                 /* We must always assign the *uid. */
827                 if (!sid_to_uid(user_sid, uid)) {
828                         DEBUG(1, ("winbindd case, sid_to_uid for %s failed\n",
829                                   sid_string_dbg(user_sid)));
830                         result = NT_STATUS_NO_SUCH_USER;
831                         goto done;
832                 }
833
834                 num_group_sids = 1;
835                 group_sids = talloc_array(tmp_ctx, struct dom_sid, num_group_sids);
836                 if (group_sids == NULL) {
837                         DEBUG(1, ("talloc_array failed\n"));
838                         result = NT_STATUS_NO_MEMORY;
839                         goto done;
840                 }
841
842                 gids = talloc_array(tmp_ctx, gid_t, num_group_sids);
843                 if (gids == NULL) {
844                         result = NT_STATUS_NO_MEMORY;
845                         goto done;
846                 }
847
848                 sid_copy(&group_sids[0], user_sid);
849                 sid_split_rid(&group_sids[0], NULL);
850                 sid_append_rid(&group_sids[0], DOMAIN_RID_USERS);
851
852                 if (!sid_to_gid(&group_sids[0], &gids[0])) {
853                         DEBUG(1, ("sid_to_gid(%s) failed\n",
854                                   sid_string_dbg(&group_sids[0])));
855                         goto done;
856                 }
857
858                 *found_username = NULL;
859         }
860
861         *gid = gids[0];
862
863         /* Add the "Unix Group" SID for each gid to catch mapped groups
864            and their Unix equivalent.  This is to solve the backwards
865            compatibility problem of 'valid users = +ntadmin' where
866            ntadmin has been paired with "Domain Admins" in the group
867            mapping table.  Otherwise smb.conf would need to be changed
868            to 'valid user = "Domain Admins"'.  --jerry */
869
870         num_gids = num_group_sids;
871         range_ok = lp_idmap_default_range(&low, &high);
872         for ( i=0; i<num_gids; i++ ) {
873                 struct dom_sid unix_group_sid;
874
875                 /* don't pickup anything managed by Winbind */
876                 if (range_ok && (gids[i] >= low) && (gids[i] <= high)) {
877                         continue;
878                 }
879
880                 gid_to_unix_groups_sid(gids[i], &unix_group_sid);
881
882                 result = add_sid_to_array_unique(tmp_ctx, &unix_group_sid,
883                                                  &group_sids, &num_group_sids);
884                 if (!NT_STATUS_IS_OK(result)) {
885                         goto done;
886                 }
887         }
888
889         /* Ensure we're creating the nt_token on the right context. */
890         *token = create_local_nt_token(mem_ctx, user_sid,
891                                        is_guest, num_group_sids, group_sids);
892
893         if (*token == NULL) {
894                 result = NT_STATUS_NO_MEMORY;
895                 goto done;
896         }
897
898         result = NT_STATUS_OK;
899  done:
900         TALLOC_FREE(tmp_ctx);
901         return result;
902 }
903
904 /*
905  * Create an artificial NT token given just a username. (Initially intended
906  * for force user)
907  *
908  * We go through lookup_name() to avoid problems we had with 'winbind use
909  * default domain'.
910  *
911  * We have 3 cases:
912  *
913  * unmapped unix users: Go directly to nss to find the user's group.
914  *
915  * A passdb user: The list of groups is provided by pdb_enum_group_memberships.
916  *
917  * If the user is provided by winbind, the primary gid is set to "domain
918  * users" of the user's domain. For an explanation why this is necessary, see
919  * the thread starting at
920  * http://lists.samba.org/archive/samba-technical/2006-January/044803.html.
921  */
922
923 NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username,
924                                     bool is_guest,
925                                     uid_t *uid, gid_t *gid,
926                                     char **found_username,
927                                     struct security_token **token)
928 {
929         NTSTATUS result = NT_STATUS_NO_SUCH_USER;
930         TALLOC_CTX *tmp_ctx = talloc_stackframe();
931         struct dom_sid user_sid;
932         enum lsa_SidType type;
933
934         if (!lookup_name_smbconf(tmp_ctx, username, LOOKUP_NAME_ALL,
935                          NULL, NULL, &user_sid, &type)) {
936                 DEBUG(1, ("lookup_name_smbconf for %s failed\n", username));
937                 goto done;
938         }
939
940         if (type != SID_NAME_USER) {
941                 DEBUG(1, ("%s is a %s, not a user\n", username,
942                           sid_type_lookup(type)));
943                 goto done;
944         }
945
946         result = create_token_from_sid(mem_ctx, &user_sid, is_guest, uid, gid, found_username, token);
947
948         if (!NT_STATUS_IS_OK(result)) {
949                 goto done;
950         }
951
952         /*
953          * If result == NT_STATUS_OK then
954          * we know we have a valid token. Ensure
955          * we also have a valid username to match.
956          */
957
958         if (*found_username == NULL) {
959                 *found_username = talloc_strdup(mem_ctx, username);
960                 if (*found_username == NULL) {
961                         result = NT_STATUS_NO_MEMORY;
962                 }
963         }
964
965 done:
966         TALLOC_FREE(tmp_ctx);
967         return result;
968 }
969
970 /***************************************************************************
971  Build upon create_token_from_sid:
972
973  Expensive helper function to figure out whether a user given its sid is
974  member of a particular group.
975 ***************************************************************************/
976
977 bool user_sid_in_group_sid(const struct dom_sid *sid, const struct dom_sid *group_sid)
978 {
979         NTSTATUS status;
980         uid_t uid;
981         gid_t gid;
982         char *found_username;
983         struct security_token *token;
984         bool result = false;
985         enum lsa_SidType type;
986         TALLOC_CTX *mem_ctx = talloc_stackframe();
987
988         if (!lookup_sid(mem_ctx, sid,
989                          NULL, NULL, &type)) {
990                 DEBUG(1, ("lookup_sid for %s failed\n", dom_sid_string(mem_ctx, sid)));
991                 goto done;
992         }
993
994         if (type != SID_NAME_USER) {
995                 DEBUG(5, ("%s is a %s, not a user\n", dom_sid_string(mem_ctx, sid),
996                           sid_type_lookup(type)));
997                 goto done;
998         }
999
1000         status = create_token_from_sid(mem_ctx, sid, False,
1001                                        &uid, &gid, &found_username,
1002                                        &token);
1003
1004         if (!NT_STATUS_IS_OK(status)) {
1005                 DEBUG(10, ("could not create token for %s\n", dom_sid_string(mem_ctx, sid)));
1006                 goto done;
1007         }
1008
1009         result = security_token_has_sid(token, group_sid);
1010
1011 done:
1012         TALLOC_FREE(mem_ctx);
1013         return result;
1014 }
1015
1016 /***************************************************************************
1017  Build upon create_token_from_username:
1018
1019  Expensive helper function to figure out whether a user given its name is
1020  member of a particular group.
1021 ***************************************************************************/
1022
1023 bool user_in_group_sid(const char *username, const struct dom_sid *group_sid)
1024 {
1025         NTSTATUS status;
1026         uid_t uid;
1027         gid_t gid;
1028         char *found_username;
1029         struct security_token *token;
1030         bool result;
1031         TALLOC_CTX *mem_ctx = talloc_stackframe();
1032
1033         status = create_token_from_username(mem_ctx, username, False,
1034                                             &uid, &gid, &found_username,
1035                                             &token);
1036
1037         if (!NT_STATUS_IS_OK(status)) {
1038                 DEBUG(10, ("could not create token for %s\n", username));
1039                 TALLOC_FREE(mem_ctx);
1040                 return False;
1041         }
1042
1043         result = security_token_has_sid(token, group_sid);
1044
1045         TALLOC_FREE(mem_ctx);
1046         return result;
1047 }
1048
1049 bool user_in_group(const char *username, const char *groupname)
1050 {
1051         TALLOC_CTX *mem_ctx = talloc_stackframe();
1052         struct dom_sid group_sid;
1053         bool ret;
1054
1055         ret = lookup_name(mem_ctx, groupname, LOOKUP_NAME_ALL,
1056                           NULL, NULL, &group_sid, NULL);
1057         TALLOC_FREE(mem_ctx);
1058
1059         if (!ret) {
1060                 DEBUG(10, ("lookup_name for (%s) failed.\n", groupname));
1061                 return False;
1062         }
1063
1064         return user_in_group_sid(username, &group_sid);
1065 }
1066
1067 /* END */