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