~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/auth/token_util.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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, *for_cache;
 
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_null("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(talloc_autofree_context(), &u_sid, False,
 
106
                                      1, &global_sid_Builtin_Administrators);
 
107
 
 
108
        token->privileges = se_disk_operators;
 
109
 
 
110
        for_cache = token;
 
111
 
 
112
        memcache_add_talloc(
 
113
                NULL, SINGLETON_CACHE_TALLOC,
 
114
                data_blob_string_const_null("root_nt_token"), &for_cache);
 
115
 
 
116
        return token;
 
117
}
 
118
 
 
119
 
 
120
/*
 
121
 * Add alias SIDs from memberships within the partially created token SID list
 
122
 */
 
123
 
 
124
NTSTATUS add_aliases(const DOM_SID *domain_sid,
 
125
                     struct nt_user_token *token)
 
126
{
 
127
        uint32 *aliases;
 
128
        size_t i, num_aliases;
 
129
        NTSTATUS status;
 
130
        TALLOC_CTX *tmp_ctx;
 
131
 
 
132
        if (!(tmp_ctx = talloc_init("add_aliases"))) {
 
133
                return NT_STATUS_NO_MEMORY;
 
134
        }
 
135
 
 
136
        aliases = NULL;
 
137
        num_aliases = 0;
 
138
 
 
139
        status = pdb_enum_alias_memberships(tmp_ctx, domain_sid,
 
140
                                            token->user_sids,
 
141
                                            token->num_sids,
 
142
                                            &aliases, &num_aliases);
 
143
 
 
144
        if (!NT_STATUS_IS_OK(status)) {
 
145
                DEBUG(10, ("pdb_enum_alias_memberships failed: %s\n",
 
146
                           nt_errstr(status)));
 
147
                goto done;
 
148
        }
 
149
 
 
150
        for (i=0; i<num_aliases; i++) {
 
151
                DOM_SID alias_sid;
 
152
                sid_compose(&alias_sid, domain_sid, aliases[i]);
 
153
                status = add_sid_to_array_unique(token, &alias_sid,
 
154
                                                 &token->user_sids,
 
155
                                                 &token->num_sids);
 
156
                if (!NT_STATUS_IS_OK(status)) {
 
157
                        DEBUG(0, ("add_sid_to_array failed\n"));
 
158
                        goto done;
 
159
                }
 
160
        }
 
161
 
 
162
done:
 
163
        TALLOC_FREE(tmp_ctx);
 
164
        return NT_STATUS_OK;
 
165
}
 
166
 
 
167
/*******************************************************************
 
168
*******************************************************************/
 
169
 
 
170
static NTSTATUS add_builtin_administrators(struct nt_user_token *token,
 
171
                                           const DOM_SID *dom_sid)
 
172
{
 
173
        DOM_SID domadm;
 
174
        NTSTATUS status;
 
175
 
 
176
        /* nothing to do if we aren't in a domain */
 
177
 
 
178
        if ( !(IS_DC || lp_server_role()==ROLE_DOMAIN_MEMBER) ) {
 
179
                return NT_STATUS_OK;
 
180
        }
 
181
 
 
182
        /* Find the Domain Admins SID */
 
183
 
 
184
        if ( IS_DC ) {
 
185
                sid_copy( &domadm, get_global_sam_sid() );
 
186
        } else {
 
187
                sid_copy(&domadm, dom_sid);
 
188
        }
 
189
        sid_append_rid( &domadm, DOMAIN_GROUP_RID_ADMINS );
 
190
 
 
191
        /* Add Administrators if the user beloongs to Domain Admins */
 
192
 
 
193
        if ( nt_token_check_sid( &domadm, token ) ) {
 
194
                status = add_sid_to_array(token,
 
195
                                          &global_sid_Builtin_Administrators,
 
196
                                          &token->user_sids, &token->num_sids);
 
197
        if (!NT_STATUS_IS_OK(status)) {
 
198
                        return status;
 
199
                }
 
200
        }
 
201
 
 
202
        return NT_STATUS_OK;
 
203
}
 
204
 
 
205
/**
 
206
 * Create the requested BUILTIN if it doesn't already exist.  This requires
 
207
 * winbindd to be running.
 
208
 *
 
209
 * @param[in] rid BUILTIN rid to create
 
210
 * @return Normal NTSTATUS return.
 
211
 */
 
212
static NTSTATUS create_builtin(uint32 rid)
 
213
{
 
214
        NTSTATUS status = NT_STATUS_OK;
 
215
        DOM_SID sid;
 
216
        gid_t gid;
 
217
 
 
218
        if (!sid_compose(&sid, &global_sid_Builtin, rid)) {
 
219
                return NT_STATUS_NO_SUCH_ALIAS;
 
220
        }
 
221
 
 
222
        if (!sid_to_gid(&sid, &gid)) {
 
223
                if (!lp_winbind_nested_groups() || !winbind_ping()) {
 
224
                        return NT_STATUS_PROTOCOL_UNREACHABLE;
 
225
                }
 
226
                status = pdb_create_builtin_alias(rid);
 
227
        }
 
228
        return status;
 
229
}
 
230
 
 
231
/**
 
232
 * Add sid as a member of builtin_sid.
 
233
 *
 
234
 * @param[in] builtin_sid       An existing builtin group.
 
235
 * @param[in] dom_sid           sid to add as a member of builtin_sid.
 
236
 * @return Normal NTSTATUS return
 
237
 */
 
238
static NTSTATUS add_sid_to_builtin(const DOM_SID *builtin_sid,
 
239
                                   const DOM_SID *dom_sid)
 
240
{
 
241
        NTSTATUS status = NT_STATUS_OK;
 
242
 
 
243
        if (!dom_sid || !builtin_sid) {
 
244
                return NT_STATUS_INVALID_PARAMETER;
 
245
        }
 
246
 
 
247
        status = pdb_add_aliasmem(builtin_sid, dom_sid);
 
248
 
 
249
        if (NT_STATUS_EQUAL(status, NT_STATUS_MEMBER_IN_ALIAS)) {
 
250
                DEBUG(5, ("add_sid_to_builtin %s is already a member of %s\n",
 
251
                          sid_string_dbg(dom_sid),
 
252
                          sid_string_dbg(builtin_sid)));
 
253
                return NT_STATUS_OK;
 
254
        }
 
255
 
 
256
        if (!NT_STATUS_IS_OK(status)) {
 
257
                DEBUG(4, ("add_sid_to_builtin %s could not be added to %s: "
 
258
                          "%s\n", sid_string_dbg(dom_sid),
 
259
                          sid_string_dbg(builtin_sid), nt_errstr(status)));
 
260
        }
 
261
        return status;
 
262
}
 
263
 
 
264
/*******************************************************************
 
265
*******************************************************************/
 
266
 
 
267
NTSTATUS create_builtin_users(const DOM_SID *dom_sid)
 
268
{
 
269
        NTSTATUS status;
 
270
        DOM_SID dom_users;
 
271
 
 
272
        status = create_builtin(BUILTIN_ALIAS_RID_USERS);
 
273
        if ( !NT_STATUS_IS_OK(status) ) {
 
274
                DEBUG(5,("create_builtin_users: Failed to create Users\n"));
 
275
                return status;
 
276
        }
 
277
 
 
278
        /* add domain users */
 
279
        if ((IS_DC || (lp_server_role() == ROLE_DOMAIN_MEMBER))
 
280
                && sid_compose(&dom_users, dom_sid, DOMAIN_GROUP_RID_USERS))
 
281
        {
 
282
                status = add_sid_to_builtin(&global_sid_Builtin_Users,
 
283
                                            &dom_users);
 
284
        }
 
285
 
 
286
        return status;
 
287
}
 
288
 
 
289
/*******************************************************************
 
290
*******************************************************************/
 
291
 
 
292
NTSTATUS create_builtin_administrators(const DOM_SID *dom_sid)
 
293
{
 
294
        NTSTATUS status;
 
295
        DOM_SID dom_admins, root_sid;
 
296
        fstring root_name;
 
297
        enum lsa_SidType type;
 
298
        TALLOC_CTX *ctx;
 
299
        bool ret;
 
300
 
 
301
        status = create_builtin(BUILTIN_ALIAS_RID_ADMINS);
 
302
        if ( !NT_STATUS_IS_OK(status) ) {
 
303
                DEBUG(5,("create_builtin_administrators: Failed to create Administrators\n"));
 
304
                return status;
 
305
        }
 
306
 
 
307
        /* add domain admins */
 
308
        if ((IS_DC || (lp_server_role() == ROLE_DOMAIN_MEMBER))
 
309
                && sid_compose(&dom_admins, dom_sid, DOMAIN_GROUP_RID_ADMINS))
 
310
        {
 
311
                status = add_sid_to_builtin(&global_sid_Builtin_Administrators,
 
312
                                            &dom_admins);
 
313
                if (!NT_STATUS_IS_OK(status)) {
 
314
                        return status;
 
315
                }
 
316
        }
 
317
 
 
318
        /* add root */
 
319
        if ( (ctx = talloc_init("create_builtin_administrators")) == NULL ) {
 
320
                return NT_STATUS_NO_MEMORY;
 
321
        }
 
322
        fstr_sprintf( root_name, "%s\\root", get_global_sam_name() );
 
323
        ret = lookup_name(ctx, root_name, LOOKUP_NAME_DOMAIN, NULL, NULL,
 
324
                          &root_sid, &type);
 
325
        TALLOC_FREE( ctx );
 
326
 
 
327
        if ( ret ) {
 
328
                status = add_sid_to_builtin(&global_sid_Builtin_Administrators,
 
329
                                            &root_sid);
 
330
        }
 
331
 
 
332
        return status;
 
333
}
 
334
 
 
335
 
 
336
/*******************************************************************
 
337
 Create a NT token for the user, expanding local aliases
 
338
*******************************************************************/
 
339
 
 
340
struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
 
341
                                            const DOM_SID *user_sid,
 
342
                                            bool is_guest,
 
343
                                            int num_groupsids,
 
344
                                            const DOM_SID *groupsids)
 
345
{
 
346
        struct nt_user_token *result = NULL;
 
347
        int i;
 
348
        NTSTATUS status;
 
349
        gid_t gid;
 
350
        DOM_SID dom_sid;
 
351
 
 
352
        DEBUG(10, ("Create local NT token for %s\n",
 
353
                   sid_string_dbg(user_sid)));
 
354
 
 
355
        if (!(result = TALLOC_ZERO_P(mem_ctx, struct nt_user_token))) {
 
356
                DEBUG(0, ("talloc failed\n"));
 
357
                return NULL;
 
358
        }
 
359
 
 
360
        /* Add the user and primary group sid */
 
361
 
 
362
        status = add_sid_to_array(result, user_sid,
 
363
                                  &result->user_sids, &result->num_sids);
 
364
        if (!NT_STATUS_IS_OK(status)) {
 
365
                return NULL;
 
366
        }
 
367
 
 
368
        /* For guest, num_groupsids may be zero. */
 
369
        if (num_groupsids) {
 
370
                status = add_sid_to_array(result, &groupsids[0],
 
371
                                          &result->user_sids,
 
372
                                          &result->num_sids);
 
373
                if (!NT_STATUS_IS_OK(status)) {
 
374
                        return NULL;
 
375
                }
 
376
        }
 
377
 
 
378
        /* Add in BUILTIN sids */
 
379
 
 
380
        status = add_sid_to_array(result, &global_sid_World,
 
381
                                  &result->user_sids, &result->num_sids);
 
382
        if (!NT_STATUS_IS_OK(status)) {
 
383
                return NULL;
 
384
        }
 
385
        status = add_sid_to_array(result, &global_sid_Network,
 
386
                                  &result->user_sids, &result->num_sids);
 
387
        if (!NT_STATUS_IS_OK(status)) {
 
388
                return NULL;
 
389
        }
 
390
 
 
391
        if (is_guest) {
 
392
                status = add_sid_to_array(result, &global_sid_Builtin_Guests,
 
393
                                          &result->user_sids,
 
394
                                          &result->num_sids);
 
395
                if (!NT_STATUS_IS_OK(status)) {
 
396
                        return NULL;
 
397
                }
 
398
        } else {
 
399
                status = add_sid_to_array(result,
 
400
                                          &global_sid_Authenticated_Users,
 
401
                                          &result->user_sids,
 
402
                                          &result->num_sids);
 
403
                if (!NT_STATUS_IS_OK(status)) {
 
404
                        return NULL;
 
405
                }
 
406
        }
 
407
 
 
408
        /* Now the SIDs we got from authentication. These are the ones from
 
409
         * the info3 struct or from the pdb_enum_group_memberships, depending
 
410
         * on who authenticated the user.
 
411
         * Note that we start the for loop at "1" here, we already added the
 
412
         * first group sid as primary above. */
 
413
 
 
414
        for (i=1; i<num_groupsids; i++) {
 
415
                status = add_sid_to_array_unique(result, &groupsids[i],
 
416
                                                 &result->user_sids,
 
417
                                                 &result->num_sids);
 
418
                if (!NT_STATUS_IS_OK(status)) {
 
419
                        return NULL;
 
420
                }
 
421
        }
 
422
 
 
423
        /* Deal with the BUILTIN\Administrators group.  If the SID can
 
424
           be resolved then assume that the add_aliasmem( S-1-5-32 )
 
425
           handled it. */
 
426
 
 
427
        if (!sid_to_gid(&global_sid_Builtin_Administrators, &gid)) {
 
428
 
 
429
                become_root();
 
430
                if (!secrets_fetch_domain_sid(lp_workgroup(), &dom_sid)) {
 
431
                        status = NT_STATUS_OK;
 
432
                        DEBUG(3, ("Failed to fetch domain sid for %s\n",
 
433
                                  lp_workgroup()));
 
434
                } else {
 
435
                        status = create_builtin_administrators(&dom_sid);
 
436
                }
 
437
                unbecome_root();
 
438
 
 
439
                if (NT_STATUS_EQUAL(status, NT_STATUS_PROTOCOL_UNREACHABLE)) {
 
440
                        /* Add BUILTIN\Administrators directly to token. */
 
441
                        status = add_builtin_administrators(result, &dom_sid);
 
442
                        if ( !NT_STATUS_IS_OK(status) ) {
 
443
                                DEBUG(3, ("Failed to check for local "
 
444
                                          "Administrators membership (%s)\n",
 
445
                                          nt_errstr(status)));
 
446
                        }
 
447
                } else if (!NT_STATUS_IS_OK(status)) {
 
448
                        DEBUG(2, ("WARNING: Failed to create "
 
449
                                  "BUILTIN\\Administrators group!  Can "
 
450
                                  "Winbind allocate gids?\n"));
 
451
                }
 
452
        }
 
453
 
 
454
        /* Deal with the BUILTIN\Users group.  If the SID can
 
455
           be resolved then assume that the add_aliasmem( S-1-5-32 )
 
456
           handled it. */
 
457
 
 
458
        if (!sid_to_gid(&global_sid_Builtin_Users, &gid)) {
 
459
 
 
460
                become_root();
 
461
                if (!secrets_fetch_domain_sid(lp_workgroup(), &dom_sid)) {
 
462
                        status = NT_STATUS_OK;
 
463
                        DEBUG(3, ("Failed to fetch domain sid for %s\n",
 
464
                                  lp_workgroup()));
 
465
                } else {
 
466
                        status = create_builtin_users(&dom_sid);
 
467
                }
 
468
                unbecome_root();
 
469
 
 
470
                if (!NT_STATUS_EQUAL(status, NT_STATUS_PROTOCOL_UNREACHABLE) &&
 
471
                    !NT_STATUS_IS_OK(status))
 
472
                {
 
473
                        DEBUG(2, ("WARNING: Failed to create BUILTIN\\Users group! "
 
474
                                  "Can Winbind allocate gids?\n"));
 
475
                }
 
476
        }
 
477
 
 
478
        /* Deal with local groups */
 
479
 
 
480
        if (lp_winbind_nested_groups()) {
 
481
 
 
482
                become_root();
 
483
 
 
484
                /* Now add the aliases. First the one from our local SAM */
 
485
 
 
486
                status = add_aliases(get_global_sam_sid(), result);
 
487
 
 
488
                if (!NT_STATUS_IS_OK(status)) {
 
489
                        unbecome_root();
 
490
                        TALLOC_FREE(result);
 
491
                        return NULL;
 
492
                }
 
493
 
 
494
                /* Finally the builtin ones */
 
495
 
 
496
                status = add_aliases(&global_sid_Builtin, result);
 
497
 
 
498
                if (!NT_STATUS_IS_OK(status)) {
 
499
                        unbecome_root();
 
500
                        TALLOC_FREE(result);
 
501
                        return NULL;
 
502
                }
 
503
 
 
504
                unbecome_root();
 
505
        }
 
506
 
 
507
 
 
508
        get_privileges_for_sids(&result->privileges, result->user_sids,
 
509
                                result->num_sids);
 
510
        return result;
 
511
}
 
512
 
 
513
/****************************************************************************
 
514
 prints a NT_USER_TOKEN to debug output.
 
515
****************************************************************************/
 
516
 
 
517
void debug_nt_user_token(int dbg_class, int dbg_lev, NT_USER_TOKEN *token)
 
518
{
 
519
        size_t     i;
 
520
 
 
521
        if (!token) {
 
522
                DEBUGC(dbg_class, dbg_lev, ("NT user token: (NULL)\n"));
 
523
                return;
 
524
        }
 
525
 
 
526
        DEBUGC(dbg_class, dbg_lev,
 
527
               ("NT user token of user %s\n",
 
528
                sid_string_dbg(&token->user_sids[0]) ));
 
529
        DEBUGADDC(dbg_class, dbg_lev,
 
530
                  ("contains %lu SIDs\n", (unsigned long)token->num_sids));
 
531
        for (i = 0; i < token->num_sids; i++)
 
532
                DEBUGADDC(dbg_class, dbg_lev,
 
533
                          ("SID[%3lu]: %s\n", (unsigned long)i,
 
534
                           sid_string_dbg(&token->user_sids[i])));
 
535
 
 
536
        dump_se_priv( dbg_class, dbg_lev, &token->privileges );
 
537
}
 
538
 
 
539
/****************************************************************************
 
540
 prints a UNIX 'token' to debug output.
 
541
****************************************************************************/
 
542
 
 
543
void debug_unix_user_token(int dbg_class, int dbg_lev, uid_t uid, gid_t gid,
 
544
                           int n_groups, gid_t *groups)
 
545
{
 
546
        int     i;
 
547
        DEBUGC(dbg_class, dbg_lev,
 
548
               ("UNIX token of user %ld\n", (long int)uid));
 
549
 
 
550
        DEBUGADDC(dbg_class, dbg_lev,
 
551
                  ("Primary group is %ld and contains %i supplementary "
 
552
                   "groups\n", (long int)gid, n_groups));
 
553
        for (i = 0; i < n_groups; i++)
 
554
                DEBUGADDC(dbg_class, dbg_lev, ("Group[%3i]: %ld\n", i,
 
555
                        (long int)groups[i]));
 
556
}
 
557
 
 
558
/* END */