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