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