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