Merge branch 'v3-2-test' of ssh://git.samba.org/data/git/samba into v3-2-test
[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
29 /****************************************************************************
30  Check for a SID in an NT_USER_TOKEN
31 ****************************************************************************/
32
33 bool nt_token_check_sid ( const DOM_SID *sid, const NT_USER_TOKEN *token )
34 {
35         int i;
36
37         if ( !sid || !token )
38                 return False;
39
40         for ( i=0; i<token->num_sids; i++ ) {
41                 if ( sid_equal( sid, &token->user_sids[i] ) )
42                         return True;
43         }
44
45         return False;
46 }
47
48 bool nt_token_check_domain_rid( NT_USER_TOKEN *token, uint32 rid )
49 {
50         DOM_SID domain_sid;
51
52         /* if we are a domain member, the get the domain SID, else for
53            a DC or standalone server, use our own SID */
54
55         if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
56                 if ( !secrets_fetch_domain_sid( lp_workgroup(),
57                                                 &domain_sid ) ) {
58                         DEBUG(1,("nt_token_check_domain_rid: Cannot lookup "
59                                  "SID for domain [%s]\n", lp_workgroup()));
60                         return False;
61                 }
62         }
63         else
64                 sid_copy( &domain_sid, get_global_sam_sid() );
65
66         sid_append_rid( &domain_sid, rid );
67
68         return nt_token_check_sid( &domain_sid, token );\
69 }
70
71 /******************************************************************************
72  Create a token for the root user to be used internally by smbd.
73  This is similar to running under the context of the LOCAL_SYSTEM account
74  in Windows.  This is a read-only token.  Do not modify it or free() it.
75  Create a copy if your need to change it.
76 ******************************************************************************/
77
78 NT_USER_TOKEN *get_root_nt_token( void )
79 {
80         struct nt_user_token *token = NULL;
81         DOM_SID u_sid, g_sid;
82         struct passwd *pw;
83         void *cache_data;
84
85         cache_data = memcache_lookup_talloc(
86                 NULL, SINGLETON_CACHE_TALLOC,
87                 data_blob_string_const("root_nt_token"));
88
89         if (cache_data != NULL) {
90                 return talloc_get_type_abort(
91                         cache_data, struct nt_user_token);
92         }
93
94         if ( !(pw = sys_getpwnam( "root" )) ) {
95                 DEBUG(0,("get_root_nt_token: getpwnam(\"root\") failed!\n"));
96                 return NULL;
97         }
98
99         /* get the user and primary group SIDs; although the
100            BUILTIN\Administrators SId is really the one that matters here */
101
102         uid_to_sid(&u_sid, pw->pw_uid);
103         gid_to_sid(&g_sid, pw->pw_gid);
104
105         token = create_local_nt_token(NULL, &u_sid, False,
106                                       1, &global_sid_Builtin_Administrators);
107
108         memcache_add_talloc(
109                 NULL, SINGLETON_CACHE_TALLOC,
110                 data_blob_string_const("root_nt_token"), token);
111
112         return token;
113 }
114
115
116 /*
117  * Add alias SIDs from memberships within the partially created token SID list
118  */
119
120 NTSTATUS add_aliases(const DOM_SID *domain_sid,
121                      struct nt_user_token *token)
122 {
123         uint32 *aliases;
124         size_t i, num_aliases;
125         NTSTATUS status;
126         TALLOC_CTX *tmp_ctx;
127
128         if (!(tmp_ctx = talloc_init("add_aliases"))) {
129                 return NT_STATUS_NO_MEMORY;
130         }
131
132         aliases = NULL;
133         num_aliases = 0;
134
135         status = pdb_enum_alias_memberships(tmp_ctx, domain_sid,
136                                             token->user_sids,
137                                             token->num_sids,
138                                             &aliases, &num_aliases);
139
140         if (!NT_STATUS_IS_OK(status)) {
141                 DEBUG(10, ("pdb_enum_alias_memberships failed: %s\n",
142                            nt_errstr(status)));
143                 goto done;
144         }
145
146         for (i=0; i<num_aliases; i++) {
147                 DOM_SID alias_sid;
148                 sid_compose(&alias_sid, domain_sid, aliases[i]);
149                 status = add_sid_to_array_unique(token, &alias_sid,
150                                                  &token->user_sids,
151                                                  &token->num_sids);
152                 if (!NT_STATUS_IS_OK(status)) {
153                         DEBUG(0, ("add_sid_to_array failed\n"));
154                         goto done;
155                 }
156         }
157
158 done:
159         TALLOC_FREE(tmp_ctx);
160         return NT_STATUS_OK;
161 }
162
163 /*******************************************************************
164 *******************************************************************/
165
166 static NTSTATUS add_builtin_administrators( struct nt_user_token *token )
167 {
168         DOM_SID domadm;
169         NTSTATUS status;
170
171         /* nothing to do if we aren't in a domain */
172
173         if ( !(IS_DC || lp_server_role()==ROLE_DOMAIN_MEMBER) ) {
174                 return NT_STATUS_OK;
175         }
176
177         /* Find the Domain Admins SID */
178
179         if ( IS_DC ) {
180                 sid_copy( &domadm, get_global_sam_sid() );
181         } else {
182                 if ( !secrets_fetch_domain_sid( lp_workgroup(), &domadm ) )
183                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
184         }
185         sid_append_rid( &domadm, DOMAIN_GROUP_RID_ADMINS );
186
187         /* Add Administrators if the user beloongs to Domain Admins */
188
189         if ( nt_token_check_sid( &domadm, token ) ) {
190                 status = add_sid_to_array(token,
191                                           &global_sid_Builtin_Administrators,
192                                           &token->user_sids, &token->num_sids);
193         if (!NT_STATUS_IS_OK(status)) {
194                         return status;
195                 }
196         }
197
198         return NT_STATUS_OK;
199 }
200
201 /*******************************************************************
202 *******************************************************************/
203
204 static NTSTATUS create_builtin_users( void )
205 {
206         NTSTATUS status;
207         DOM_SID dom_users;
208
209         status = pdb_create_builtin_alias( BUILTIN_ALIAS_RID_USERS );
210         if ( !NT_STATUS_IS_OK(status) ) {
211                 DEBUG(0,("create_builtin_users: Failed to create Users\n"));
212                 return status;
213         }
214
215         /* add domain users */
216         if ((IS_DC || (lp_server_role() == ROLE_DOMAIN_MEMBER))
217                 && secrets_fetch_domain_sid(lp_workgroup(), &dom_users))
218         {
219                 sid_append_rid(&dom_users, DOMAIN_GROUP_RID_USERS );
220                 status = pdb_add_aliasmem( &global_sid_Builtin_Users, &dom_users);
221                 if ( !NT_STATUS_IS_OK(status) ) {
222                         DEBUG(0,("create_builtin_administrators: Failed to add Domain Users to"
223                                 " Users\n"));
224                         return status;
225                 }
226         }
227
228         return NT_STATUS_OK;
229 }
230
231 /*******************************************************************
232 *******************************************************************/
233
234 static NTSTATUS create_builtin_administrators( void )
235 {
236         NTSTATUS status;
237         DOM_SID dom_admins, root_sid;
238         fstring root_name;
239         enum lsa_SidType type;
240         TALLOC_CTX *ctx;
241         bool ret;
242
243         status = pdb_create_builtin_alias( BUILTIN_ALIAS_RID_ADMINS );
244         if ( !NT_STATUS_IS_OK(status) ) {
245                 DEBUG(0,("create_builtin_administrators: Failed to create Administrators\n"));
246                 return status;
247         }
248
249         /* add domain admins */
250         if ((IS_DC || (lp_server_role() == ROLE_DOMAIN_MEMBER))
251                 && secrets_fetch_domain_sid(lp_workgroup(), &dom_admins))
252         {
253                 sid_append_rid(&dom_admins, DOMAIN_GROUP_RID_ADMINS);
254                 status = pdb_add_aliasmem( &global_sid_Builtin_Administrators, &dom_admins );
255                 if ( !NT_STATUS_IS_OK(status) ) {
256                         DEBUG(0,("create_builtin_administrators: Failed to add Domain Admins"
257                                 " Administrators\n"));
258                         return status;
259                 }
260         }
261
262         /* add root */
263         if ( (ctx = talloc_init("create_builtin_administrators")) == NULL ) {
264                 return NT_STATUS_NO_MEMORY;
265         }
266         fstr_sprintf( root_name, "%s\\root", get_global_sam_name() );
267         ret = lookup_name(ctx, root_name, LOOKUP_NAME_DOMAIN, NULL, NULL,
268                           &root_sid, &type);
269         TALLOC_FREE( ctx );
270
271         if ( ret ) {
272                 status = pdb_add_aliasmem( &global_sid_Builtin_Administrators, &root_sid );
273                 if ( !NT_STATUS_IS_OK(status) ) {
274                         DEBUG(0,("create_builtin_administrators: Failed to add root"
275                                 " Administrators\n"));
276                         return status;
277                 }
278         }
279
280         return NT_STATUS_OK;
281 }
282
283
284 /*******************************************************************
285  Create a NT token for the user, expanding local aliases
286 *******************************************************************/
287
288 struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
289                                             const DOM_SID *user_sid,
290                                             bool is_guest,
291                                             int num_groupsids,
292                                             const DOM_SID *groupsids)
293 {
294         struct nt_user_token *result = NULL;
295         int i;
296         NTSTATUS status;
297         gid_t gid;
298
299         DEBUG(10, ("Create local NT token for %s\n",
300                    sid_string_dbg(user_sid)));
301
302         if (!(result = TALLOC_ZERO_P(mem_ctx, struct nt_user_token))) {
303                 DEBUG(0, ("talloc failed\n"));
304                 return NULL;
305         }
306
307         /* Add the user and primary group sid */
308
309         status = add_sid_to_array(result, user_sid,
310                                   &result->user_sids, &result->num_sids);
311         if (!NT_STATUS_IS_OK(status)) {
312                 return NULL;
313         }
314
315         /* For guest, num_groupsids may be zero. */
316         if (num_groupsids) {
317                 status = add_sid_to_array(result, &groupsids[0],
318                                           &result->user_sids,
319                                           &result->num_sids);
320                 if (!NT_STATUS_IS_OK(status)) {
321                         return NULL;
322                 }
323         }
324
325         /* Add in BUILTIN sids */
326
327         status = add_sid_to_array(result, &global_sid_World,
328                                   &result->user_sids, &result->num_sids);
329         if (!NT_STATUS_IS_OK(status)) {
330                 return NULL;
331         }
332         status = add_sid_to_array(result, &global_sid_Network,
333                                   &result->user_sids, &result->num_sids);
334         if (!NT_STATUS_IS_OK(status)) {
335                 return NULL;
336         }
337
338         if (is_guest) {
339                 status = add_sid_to_array(result, &global_sid_Builtin_Guests,
340                                           &result->user_sids,
341                                           &result->num_sids);
342                 if (!NT_STATUS_IS_OK(status)) {
343                         return NULL;
344                 }
345         } else {
346                 status = add_sid_to_array(result,
347                                           &global_sid_Authenticated_Users,
348                                           &result->user_sids,
349                                           &result->num_sids);
350                 if (!NT_STATUS_IS_OK(status)) {
351                         return NULL;
352                 }
353         }
354
355         /* Now the SIDs we got from authentication. These are the ones from
356          * the info3 struct or from the pdb_enum_group_memberships, depending
357          * on who authenticated the user.
358          * Note that we start the for loop at "1" here, we already added the
359          * first group sid as primary above. */
360
361         for (i=1; i<num_groupsids; i++) {
362                 status = add_sid_to_array_unique(result, &groupsids[i],
363                                                  &result->user_sids,
364                                                  &result->num_sids);
365                 if (!NT_STATUS_IS_OK(status)) {
366                         return NULL;
367                 }
368         }
369
370         /* Deal with the BUILTIN\Administrators group.  If the SID can
371            be resolved then assume that the add_aliasmem( S-1-5-32 )
372            handled it. */
373
374         if ( !sid_to_gid( &global_sid_Builtin_Administrators, &gid ) ) {
375                 /* We can only create a mapping if winbind is running
376                    and the nested group functionality has been enabled */
377
378                 if ( lp_winbind_nested_groups() && winbind_ping() ) {
379                         become_root();
380                         status = create_builtin_administrators( );
381                         if ( !NT_STATUS_IS_OK(status) ) {
382                                 DEBUG(2,("create_local_nt_token: Failed to create BUILTIN\\Administrators group!\n"));
383                                 /* don't fail, just log the message */
384                         }
385                         unbecome_root();
386                 }
387                 else {
388                         status = add_builtin_administrators( result );
389                         if ( !NT_STATUS_IS_OK(status) ) {
390                                 /* just log a complaint but do not fail */
391                                 DEBUG(3,("create_local_nt_token: failed to check for local Administrators"
392                                         " membership (%s)\n", nt_errstr(status)));
393                         }
394                 }
395         }
396
397         /* Deal with the BUILTIN\Users group.  If the SID can
398            be resolved then assume that the add_aliasmem( S-1-5-32 )
399            handled it. */
400
401         if ( !sid_to_gid( &global_sid_Builtin_Users, &gid ) ) {
402                 /* We can only create a mapping if winbind is running
403                    and the nested group functionality has been enabled */
404
405                 if ( lp_winbind_nested_groups() && winbind_ping() ) {
406                         become_root();
407                         status = create_builtin_users( );
408                         if ( !NT_STATUS_IS_OK(status) ) {
409                                 DEBUG(2,("create_local_nt_token: Failed to create BUILTIN\\Users group!\n"));
410                                 /* don't fail, just log the message */
411                         }
412                         unbecome_root();
413                 }
414         }
415
416         /* Deal with local groups */
417
418         if (lp_winbind_nested_groups()) {
419
420                 become_root();
421
422                 /* Now add the aliases. First the one from our local SAM */
423
424                 status = add_aliases(get_global_sam_sid(), result);
425
426                 if (!NT_STATUS_IS_OK(status)) {
427                         unbecome_root();
428                         TALLOC_FREE(result);
429                         return NULL;
430                 }
431
432                 /* Finally the builtin ones */
433
434                 status = add_aliases(&global_sid_Builtin, result);
435
436                 if (!NT_STATUS_IS_OK(status)) {
437                         unbecome_root();
438                         TALLOC_FREE(result);
439                         return NULL;
440                 }
441
442                 unbecome_root();
443         }
444
445
446         get_privileges_for_sids(&result->privileges, result->user_sids,
447                                 result->num_sids);
448         return result;
449 }
450
451 /****************************************************************************
452  prints a NT_USER_TOKEN to debug output.
453 ****************************************************************************/
454
455 void debug_nt_user_token(int dbg_class, int dbg_lev, NT_USER_TOKEN *token)
456 {
457         size_t     i;
458
459         if (!token) {
460                 DEBUGC(dbg_class, dbg_lev, ("NT user token: (NULL)\n"));
461                 return;
462         }
463
464         DEBUGC(dbg_class, dbg_lev,
465                ("NT user token of user %s\n",
466                 sid_string_dbg(&token->user_sids[0]) ));
467         DEBUGADDC(dbg_class, dbg_lev,
468                   ("contains %lu SIDs\n", (unsigned long)token->num_sids));
469         for (i = 0; i < token->num_sids; i++)
470                 DEBUGADDC(dbg_class, dbg_lev,
471                           ("SID[%3lu]: %s\n", (unsigned long)i,
472                            sid_string_dbg(&token->user_sids[i])));
473
474         dump_se_priv( dbg_class, dbg_lev, &token->privileges );
475 }
476
477 /****************************************************************************
478  prints a UNIX 'token' to debug output.
479 ****************************************************************************/
480
481 void debug_unix_user_token(int dbg_class, int dbg_lev, uid_t uid, gid_t gid,
482                            int n_groups, gid_t *groups)
483 {
484         int     i;
485         DEBUGC(dbg_class, dbg_lev,
486                ("UNIX token of user %ld\n", (long int)uid));
487
488         DEBUGADDC(dbg_class, dbg_lev,
489                   ("Primary group is %ld and contains %i supplementary "
490                    "groups\n", (long int)gid, n_groups));
491         for (i = 0; i < n_groups; i++)
492                 DEBUGADDC(dbg_class, dbg_lev, ("Group[%3i]: %ld\n", i,
493                         (long int)groups[i]));
494 }
495
496 /* END */