Coverage Report

Created: 2025-07-23 07:04

/src/samba/source3/auth/token_util.c
Line
Count
Source (jump to first uncovered line)
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
#include "lib/util_unixsids.h"
29
#include "system/passwd.h"
30
#include "auth.h"
31
#include "secrets.h"
32
#include "../lib/util/memcache.h"
33
#include "../librpc/gen_ndr/netlogon.h"
34
#include "../libcli/security/security.h"
35
#include "../lib/util/util_pw.h"
36
#include "passdb.h"
37
#include "lib/privileges.h"
38
39
/****************************************************************************
40
 Check for a SID in an struct security_token
41
****************************************************************************/
42
43
bool nt_token_check_sid ( const struct dom_sid *sid, const struct security_token *token )
44
0
{
45
0
  if ( !sid || !token )
46
0
    return False;
47
48
0
  return security_token_has_sid(token, sid);
49
0
}
50
51
bool nt_token_check_domain_rid( struct security_token *token, uint32_t rid )
52
0
{
53
0
  struct dom_sid domain_sid;
54
55
  /* if we are a domain member, the get the domain SID, else for
56
     a DC or standalone server, use our own SID */
57
58
0
  if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
59
0
    if ( !secrets_fetch_domain_sid( lp_workgroup(),
60
0
            &domain_sid ) ) {
61
0
      DEBUG(1,("nt_token_check_domain_rid: Cannot lookup "
62
0
         "SID for domain [%s]\n", lp_workgroup()));
63
0
      return False;
64
0
    }
65
0
  }
66
0
  else
67
0
    sid_copy( &domain_sid, get_global_sam_sid() );
68
69
0
  sid_append_rid( &domain_sid, rid );
70
71
0
  return nt_token_check_sid( &domain_sid, token );\
72
0
}
73
74
/******************************************************************************
75
 Create a token for the root user to be used internally by smbd.
76
 This is similar to running under the context of the LOCAL_SYSTEM account
77
 in Windows.  This is a read-only token.  Do not modify it or free() it.
78
 Create a copy if you need to change it.
79
******************************************************************************/
80
81
NTSTATUS get_root_nt_token( struct security_token **token )
82
0
{
83
0
  struct security_token *for_cache;
84
0
  struct dom_sid u_sid, g_sid;
85
0
  struct passwd *pw;
86
0
  void *cache_data;
87
0
  NTSTATUS status = NT_STATUS_OK;
88
89
0
  cache_data = memcache_lookup_talloc(
90
0
    NULL, SINGLETON_CACHE_TALLOC,
91
0
    data_blob_string_const_null("root_nt_token"));
92
93
0
  if (cache_data != NULL) {
94
0
    *token = talloc_get_type_abort(
95
0
      cache_data, struct security_token);
96
0
    return NT_STATUS_OK;
97
0
  }
98
99
0
  if ( !(pw = getpwuid(0)) ) {
100
0
    if ( !(pw = getpwnam("root")) ) {
101
0
      DBG_ERR("get_root_nt_token: both getpwuid(0) "
102
0
        "and getpwnam(\"root\") failed!\n");
103
0
      return NT_STATUS_NO_SUCH_USER;
104
0
    }
105
0
  }
106
107
  /* get the user and primary group SIDs; although the
108
     BUILTIN\Administrators SId is really the one that matters here */
109
110
0
  uid_to_sid(&u_sid, pw->pw_uid);
111
0
  gid_to_sid(&g_sid, pw->pw_gid);
112
113
0
  status = create_local_nt_token(talloc_tos(), &u_sid, False,
114
0
              1, &global_sid_Builtin_Administrators, token);
115
0
  if (!NT_STATUS_IS_OK(status)) {
116
0
    return status;
117
0
  }
118
119
0
  security_token_set_privilege(*token, SEC_PRIV_DISK_OPERATOR);
120
121
0
  for_cache = *token;
122
123
0
  memcache_add_talloc(
124
0
    NULL, SINGLETON_CACHE_TALLOC,
125
0
    data_blob_string_const_null("root_nt_token"), &for_cache);
126
127
0
  return status;
128
0
}
129
130
131
/*
132
 * Add alias SIDs from memberships within the partially created token SID list
133
 */
134
135
NTSTATUS add_aliases(const struct dom_sid *domain_sid,
136
         struct security_token *token)
137
0
{
138
0
  uint32_t *aliases;
139
0
  size_t i, num_aliases;
140
0
  NTSTATUS status;
141
0
  TALLOC_CTX *tmp_ctx;
142
143
0
  if (!(tmp_ctx = talloc_init("add_aliases"))) {
144
0
    return NT_STATUS_NO_MEMORY;
145
0
  }
146
147
0
  aliases = NULL;
148
0
  num_aliases = 0;
149
150
0
  status = pdb_enum_alias_memberships(tmp_ctx, domain_sid,
151
0
              token->sids,
152
0
              token->num_sids,
153
0
              &aliases, &num_aliases);
154
155
0
  if (!NT_STATUS_IS_OK(status)) {
156
0
    DEBUG(10, ("pdb_enum_alias_memberships failed: %s\n",
157
0
         nt_errstr(status)));
158
0
    goto done;
159
0
  }
160
161
0
  for (i=0; i<num_aliases; i++) {
162
0
    struct dom_sid alias_sid;
163
0
    sid_compose(&alias_sid, domain_sid, aliases[i]);
164
0
    status = add_sid_to_array_unique(token, &alias_sid,
165
0
             &token->sids,
166
0
             &token->num_sids);
167
0
    if (!NT_STATUS_IS_OK(status)) {
168
0
      DEBUG(0, ("add_sid_to_array failed\n"));
169
0
      goto done;
170
0
    }
171
0
  }
172
173
0
done:
174
0
  TALLOC_FREE(tmp_ctx);
175
0
  return NT_STATUS_OK;
176
0
}
177
178
/*******************************************************************
179
*******************************************************************/
180
181
static NTSTATUS add_builtin_administrators(struct security_token *token,
182
             const struct dom_sid *dom_sid)
183
0
{
184
0
  struct dom_sid domadm;
185
0
  NTSTATUS status;
186
187
  /* nothing to do if we aren't in a domain */
188
189
0
  if ( !(IS_DC || lp_server_role()==ROLE_DOMAIN_MEMBER) ) {
190
0
    return NT_STATUS_OK;
191
0
  }
192
193
  /* Find the Domain Admins SID */
194
195
0
  if ( IS_DC ) {
196
0
    sid_copy( &domadm, get_global_sam_sid() );
197
0
  } else {
198
0
    if (dom_sid == NULL) {
199
0
      return NT_STATUS_INVALID_PARAMETER_MIX;
200
0
    }
201
0
    sid_copy(&domadm, dom_sid);
202
0
  }
203
0
  sid_append_rid( &domadm, DOMAIN_RID_ADMINS );
204
205
  /* Add Administrators if the user beloongs to Domain Admins */
206
207
0
  if ( nt_token_check_sid( &domadm, token ) ) {
208
0
    status = add_sid_to_array(token,
209
0
            &global_sid_Builtin_Administrators,
210
0
            &token->sids, &token->num_sids);
211
0
  if (!NT_STATUS_IS_OK(status)) {
212
0
      return status;
213
0
    }
214
0
  }
215
216
0
  return NT_STATUS_OK;
217
0
}
218
219
static NTSTATUS add_builtin_guests(struct security_token *token,
220
           const struct dom_sid *dom_sid)
221
0
{
222
0
  struct dom_sid tmp_sid;
223
0
  NTSTATUS status;
224
225
  /*
226
   * First check the local GUEST account.
227
   */
228
0
  sid_compose(&tmp_sid, get_global_sam_sid(), DOMAIN_RID_GUEST);
229
230
0
  if (nt_token_check_sid(&tmp_sid, token)) {
231
0
    status = add_sid_to_array_unique(token,
232
0
          &global_sid_Builtin_Guests,
233
0
          &token->sids, &token->num_sids);
234
0
    if (!NT_STATUS_IS_OK(status)) {
235
0
      return status;
236
0
    }
237
238
0
    return NT_STATUS_OK;
239
0
  }
240
241
  /*
242
   * First check the local GUESTS group.
243
   */
244
0
  sid_compose(&tmp_sid, get_global_sam_sid(), DOMAIN_RID_GUESTS);
245
246
0
  if (nt_token_check_sid(&tmp_sid, token)) {
247
0
    status = add_sid_to_array_unique(token,
248
0
          &global_sid_Builtin_Guests,
249
0
          &token->sids, &token->num_sids);
250
0
    if (!NT_STATUS_IS_OK(status)) {
251
0
      return status;
252
0
    }
253
254
0
    return NT_STATUS_OK;
255
0
  }
256
257
0
  if (lp_server_role() != ROLE_DOMAIN_MEMBER) {
258
0
    return NT_STATUS_OK;
259
0
  }
260
261
0
  if (dom_sid == NULL) {
262
0
    return NT_STATUS_INVALID_PARAMETER_MIX;
263
0
  }
264
265
  /*
266
   * First check the domain GUESTS group.
267
   */
268
0
  sid_copy(&tmp_sid, dom_sid);
269
0
  sid_append_rid(&tmp_sid, DOMAIN_RID_GUESTS);
270
271
0
  if (nt_token_check_sid(&tmp_sid, token)) {
272
0
    status = add_sid_to_array_unique(token,
273
0
          &global_sid_Builtin_Guests,
274
0
          &token->sids, &token->num_sids);
275
0
    if (!NT_STATUS_IS_OK(status)) {
276
0
      return status;
277
0
    }
278
279
0
    return NT_STATUS_OK;
280
0
  }
281
282
0
  return NT_STATUS_OK;
283
0
}
284
285
static NTSTATUS add_local_groups(struct security_token *result,
286
         bool is_guest);
287
288
NTSTATUS get_user_sid_info3_and_extra(const struct netr_SamInfo3 *info3,
289
              const struct extra_auth_info *extra,
290
              struct dom_sid *sid)
291
0
{
292
  /* USER SID */
293
0
  if (info3->base.rid == (uint32_t)(-1)) {
294
    /* this is a signal the user was fake and generated,
295
     * the actual SID we want to use is stored in the extra
296
     * sids */
297
0
    if (is_null_sid(&extra->user_sid)) {
298
      /* we couldn't find the user sid, bail out */
299
0
      DEBUG(3, ("Invalid user SID\n"));
300
0
      return NT_STATUS_UNSUCCESSFUL;
301
0
    }
302
0
    sid_copy(sid, &extra->user_sid);
303
0
  } else {
304
0
    sid_copy(sid, info3->base.domain_sid);
305
0
    sid_append_rid(sid, info3->base.rid);
306
0
  }
307
0
  return NT_STATUS_OK;
308
0
}
309
310
static struct security_token *init_local_nt_token(TALLOC_CTX *mem_ctx) 
311
0
{
312
  /*
313
   * We do not have a method to populate the claims into this
314
   * buffer in the source3/ stack.  When that changes, we will
315
   * instead make this optional based on lp_acl_claims_evaluation()
316
   */
317
318
0
  struct security_token *result
319
0
    = security_token_initialise(mem_ctx,
320
0
              CLAIMS_EVALUATION_NEVER);
321
322
0
  if (result == NULL) {
323
0
    DBG_ERR("talloc failed for security_token\n");
324
0
    return NULL;
325
0
  }
326
327
0
  return result;
328
0
}
329
330
NTSTATUS create_local_nt_token_from_info3(TALLOC_CTX *mem_ctx,
331
            bool is_guest,
332
            const struct netr_SamInfo3 *info3,
333
            const struct extra_auth_info *extra,
334
            struct security_token **ntok)
335
0
{
336
0
  struct security_token *usrtok = NULL;
337
0
  uint32_t session_info_flags = 0;
338
0
  NTSTATUS status;
339
0
  uint32_t i;
340
341
0
  DEBUG(10, ("Create local NT token for %s\n",
342
0
       info3->base.account_name.string));
343
344
0
  usrtok = init_local_nt_token(mem_ctx);
345
0
  if (!usrtok) {
346
0
    return NT_STATUS_NO_MEMORY;
347
0
  }
348
349
  /* Add the user and primary group sid FIRST */
350
  /* check if the user rid is the special "Domain Guests" rid.
351
   * If so pick the first sid for the extra sids instead as it
352
   * is a local fake account */
353
0
  usrtok->sids = talloc_array(usrtok, struct dom_sid, 2);
354
0
  if (!usrtok->sids) {
355
0
    TALLOC_FREE(usrtok);
356
0
    return NT_STATUS_NO_MEMORY;
357
0
  }
358
0
  usrtok->num_sids = 2;
359
360
0
  status = get_user_sid_info3_and_extra(info3, extra, &usrtok->sids[0]);
361
0
  if (!NT_STATUS_IS_OK(status)) {
362
0
    TALLOC_FREE(usrtok);
363
0
    return status;
364
0
  }
365
366
  /* GROUP SID */
367
0
  if (info3->base.primary_gid == (uint32_t)(-1)) {
368
    /* this is a signal the user was fake and generated,
369
     * the actual SID we want to use is stored in the extra
370
     * sids */
371
0
    if (is_null_sid(&extra->pgid_sid)) {
372
      /* we couldn't find the user sid, bail out */
373
0
      DEBUG(3, ("Invalid group SID\n"));
374
0
      TALLOC_FREE(usrtok);
375
0
      return NT_STATUS_UNSUCCESSFUL;
376
0
    }
377
0
    sid_copy(&usrtok->sids[1], &extra->pgid_sid);
378
0
  } else {
379
0
    sid_copy(&usrtok->sids[1], info3->base.domain_sid);
380
0
    sid_append_rid(&usrtok->sids[1],
381
0
        info3->base.primary_gid);
382
0
  }
383
384
  /* Now the SIDs we got from authentication. These are the ones from
385
   * the info3 struct or from the pdb_enum_group_memberships, depending
386
   * on who authenticated the user.
387
   * Note that we start the for loop at "1" here, we already added the
388
   * first group sid as primary above. */
389
390
0
  for (i = 0; i < info3->base.groups.count; i++) {
391
0
    struct dom_sid tmp_sid;
392
393
0
    sid_copy(&tmp_sid, info3->base.domain_sid);
394
0
    sid_append_rid(&tmp_sid, info3->base.groups.rids[i].rid);
395
396
0
    status = add_sid_to_array_unique(usrtok, &tmp_sid,
397
0
             &usrtok->sids,
398
0
             &usrtok->num_sids);
399
0
    if (!NT_STATUS_IS_OK(status)) {
400
0
      DEBUG(3, ("Failed to add SID to nt token\n"));
401
0
      TALLOC_FREE(usrtok);
402
0
      return status;
403
0
    }
404
0
  }
405
406
  /* now also add extra sids if they are not the special user/group
407
   * sids */
408
0
  for (i = 0; i < info3->sidcount; i++) {
409
0
    status = add_sid_to_array_unique(usrtok,
410
0
             info3->sids[i].sid,
411
0
             &usrtok->sids,
412
0
             &usrtok->num_sids);
413
0
    if (!NT_STATUS_IS_OK(status)) {
414
0
      DEBUG(3, ("Failed to add SID to nt token\n"));
415
0
      TALLOC_FREE(usrtok);
416
0
      return status;
417
0
    }
418
0
  }
419
420
0
  status = add_local_groups(usrtok, is_guest);
421
0
  if (!NT_STATUS_IS_OK(status)) {
422
0
    DEBUG(3, ("Failed to add local groups\n"));
423
0
    TALLOC_FREE(usrtok);
424
0
    return status;
425
0
  }
426
427
0
  session_info_flags |= AUTH_SESSION_INFO_DEFAULT_GROUPS;
428
0
  if (!is_guest) {
429
0
    session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
430
0
  }
431
432
0
  status = finalize_local_nt_token(usrtok, session_info_flags);
433
0
  if (!NT_STATUS_IS_OK(status)) {
434
0
    DEBUG(3, ("Failed to finalize nt token\n"));
435
0
    TALLOC_FREE(usrtok);
436
0
    return status;
437
0
  }
438
439
0
  *ntok = usrtok;
440
0
  return NT_STATUS_OK;
441
0
}
442
443
/*******************************************************************
444
 Create a NT token for the user, expanding local aliases
445
*******************************************************************/
446
447
NTSTATUS create_local_nt_token(TALLOC_CTX *mem_ctx,
448
              const struct dom_sid *user_sid,
449
              bool is_guest,
450
              int num_groupsids,
451
              const struct dom_sid *groupsids,
452
              struct security_token **token)
453
0
{
454
0
  struct security_token *result = NULL;
455
0
  int i;
456
0
  NTSTATUS status;
457
0
  uint32_t session_info_flags = 0;
458
0
  struct dom_sid_buf buf;
459
460
0
  DEBUG(10, ("Create local NT token for %s\n",
461
0
       dom_sid_str_buf(user_sid, &buf)));
462
463
0
  result = init_local_nt_token(mem_ctx);
464
0
  if (result == NULL) {
465
0
    status = NT_STATUS_NO_MEMORY;
466
0
    goto err;
467
0
  }
468
469
  /* Add the user and primary group sid */
470
471
0
  status = add_sid_to_array(result, user_sid,
472
0
          &result->sids, &result->num_sids);
473
0
  if (!NT_STATUS_IS_OK(status)) {
474
0
    goto err;
475
0
  }
476
477
  /* For guest, num_groupsids may be zero. */
478
0
  if (num_groupsids) {
479
0
    status = add_sid_to_array(result, &groupsids[0],
480
0
            &result->sids,
481
0
            &result->num_sids);
482
0
    if (!NT_STATUS_IS_OK(status)) {
483
0
      goto err;
484
0
    }
485
0
  }
486
487
  /* Now the SIDs we got from authentication. These are the ones from
488
   * the info3 struct or from the pdb_enum_group_memberships, depending
489
   * on who authenticated the user.
490
   * Note that we start the for loop at "1" here, we already added the
491
   * first group sid as primary above. */
492
493
0
  for (i=1; i<num_groupsids; i++) {
494
0
    status = add_sid_to_array_unique(result, &groupsids[i],
495
0
             &result->sids,
496
0
             &result->num_sids);
497
0
    if (!NT_STATUS_IS_OK(status)) {
498
0
      goto err;
499
0
    }
500
0
  }
501
502
0
  status = add_local_groups(result, is_guest);
503
0
  if (!NT_STATUS_IS_OK(status)) {
504
0
    goto err;
505
0
  }
506
507
0
  session_info_flags |= AUTH_SESSION_INFO_DEFAULT_GROUPS;
508
0
  if (!is_guest) {
509
0
    session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
510
0
  }
511
512
0
  status = finalize_local_nt_token(result, session_info_flags);
513
0
  if (!NT_STATUS_IS_OK(status)) {
514
0
    goto err;
515
0
  }
516
517
0
  if (is_guest) {
518
    /*
519
     * It's ugly, but for now it's
520
     * needed to add Builtin_Guests
521
     * here, the "local" token only
522
     * consist of S-1-22-* SIDs
523
     * and finalize_local_nt_token()
524
     * doesn't have the chance to
525
     * to detect it need to
526
     * add Builtin_Guests via
527
     * add_builtin_guests().
528
     */
529
0
    status = add_sid_to_array_unique(result,
530
0
             &global_sid_Builtin_Guests,
531
0
             &result->sids,
532
0
             &result->num_sids);
533
0
    if (!NT_STATUS_IS_OK(status)) {
534
0
      DEBUG(3, ("Failed to add SID to nt token\n"));
535
0
      goto err;
536
0
    }
537
0
  }
538
539
0
  *token = result;
540
0
  return NT_STATUS_SUCCESS;
541
542
0
err:
543
0
  TALLOC_FREE(result);
544
0
  return status;
545
0
}
546
547
/***************************************************
548
 Merge in any groups from /etc/group.
549
***************************************************/
550
551
static NTSTATUS add_local_groups(struct security_token *result,
552
         bool is_guest)
553
0
{
554
0
  gid_t *gids = NULL;
555
0
  uint32_t getgroups_num_group_sids = 0;
556
0
  struct passwd *pass = NULL;
557
0
  TALLOC_CTX *tmp_ctx = talloc_stackframe();
558
0
  uint32_t i;
559
560
0
  if (is_guest) {
561
    /*
562
     * Guest is a special case. It's always
563
     * a user that can be looked up, but
564
     * result->sids[0] is set to DOMAIN\Guest.
565
     * Lookup by account name instead.
566
     */
567
0
    pass = Get_Pwnam_alloc(tmp_ctx, lp_guest_account());
568
0
  } else {
569
0
    uid_t uid;
570
571
    /* For non-guest result->sids[0] is always the user sid. */
572
0
    if (!sid_to_uid(&result->sids[0], &uid)) {
573
      /*
574
       * Non-mappable SID like SYSTEM.
575
       * Can't be in any /etc/group groups.
576
       */
577
0
      TALLOC_FREE(tmp_ctx);
578
0
      return NT_STATUS_OK;
579
0
    }
580
581
0
    pass = getpwuid_alloc(tmp_ctx, uid);
582
0
    if (pass == NULL) {
583
0
      struct dom_sid_buf buf;
584
0
      DBG_ERR("SID %s -> getpwuid(%u) failed, is nsswitch configured?\n",
585
0
        dom_sid_str_buf(&result->sids[0], &buf),
586
0
        (unsigned int)uid);
587
0
      TALLOC_FREE(tmp_ctx);
588
0
      return NT_STATUS_NO_SUCH_USER;
589
0
    }
590
0
  }
591
592
0
  if (!pass) {
593
0
    TALLOC_FREE(tmp_ctx);
594
0
    return NT_STATUS_UNSUCCESSFUL;
595
0
  }
596
597
  /*
598
   * Now we must get any groups this user has been
599
   * added to in /etc/group and merge them in.
600
   * This has to be done in every code path
601
   * that creates an NT token, as remote users
602
   * may have been added to the local /etc/group
603
   * database. Tokens created merely from the
604
   * info3 structs (via the DC or via the krb5 PAC)
605
   * won't have these local groups. Note the
606
   * groups added here will only be UNIX groups
607
   * (S-1-22-2-XXXX groups) as getgroups_unix_user()
608
   * turns off winbindd before calling getgroups().
609
   *
610
   * NB. This is duplicating work already
611
   * done in the 'unix_user:' case of
612
   * create_token_from_sid() but won't
613
   * do anything other than be inefficient
614
   * in that case.
615
   */
616
617
0
  if (!getgroups_unix_user(tmp_ctx, pass->pw_name, pass->pw_gid,
618
0
      &gids, &getgroups_num_group_sids)) {
619
0
    DEBUG(1, ("getgroups_unix_user for user %s failed\n",
620
0
      pass->pw_name));
621
0
    TALLOC_FREE(tmp_ctx);
622
0
    return NT_STATUS_UNSUCCESSFUL;
623
0
  }
624
625
0
  for (i=0; i<getgroups_num_group_sids; i++) {
626
0
    NTSTATUS status;
627
0
    struct dom_sid grp_sid;
628
0
    gid_to_sid(&grp_sid, gids[i]);
629
630
0
    status = add_sid_to_array_unique(result,
631
0
           &grp_sid,
632
0
           &result->sids,
633
0
           &result->num_sids);
634
0
    if (!NT_STATUS_IS_OK(status)) {
635
0
      DEBUG(3, ("Failed to add UNIX SID to nt token\n"));
636
0
      TALLOC_FREE(tmp_ctx);
637
0
      return status;
638
0
    }
639
0
  }
640
0
  TALLOC_FREE(tmp_ctx);
641
0
  return NT_STATUS_OK;
642
0
}
643
644
NTSTATUS finalize_local_nt_token(struct security_token *result,
645
         uint32_t session_info_flags)
646
0
{
647
0
  struct dom_sid _dom_sid = { 0, };
648
0
  struct dom_sid *domain_sid = NULL;
649
0
  NTSTATUS status;
650
0
  struct acct_info *info;
651
0
  bool ok;
652
653
0
  result->privilege_mask = 0;
654
0
  result->rights_mask = 0;
655
656
0
  if (result->num_sids == 0) {
657
0
    return NT_STATUS_INVALID_TOKEN;
658
0
  }
659
660
0
  if (session_info_flags & AUTH_SESSION_INFO_DEFAULT_GROUPS) {
661
0
    status = add_sid_to_array(result, &global_sid_World,
662
0
            &result->sids, &result->num_sids);
663
0
    if (!NT_STATUS_IS_OK(status)) {
664
0
      return status;
665
0
    }
666
0
    status = add_sid_to_array(result, &global_sid_Network,
667
0
            &result->sids, &result->num_sids);
668
0
    if (!NT_STATUS_IS_OK(status)) {
669
0
      return status;
670
0
    }
671
0
  }
672
673
  /*
674
   * Don't expand nested groups of system, anonymous etc
675
   *
676
   * Note that they still get SID_WORLD and SID_NETWORK
677
   * for now in order let existing tests pass.
678
   *
679
   * But SYSTEM doesn't get AUTHENTICATED_USERS
680
   * and ANONYMOUS doesn't get BUILTIN GUESTS anymore.
681
   */
682
0
  if (security_token_is_anonymous(result)) {
683
0
    return NT_STATUS_OK;
684
0
  }
685
0
  if (security_token_is_system(result)) {
686
0
    result->privilege_mask = ~0;
687
0
    return NT_STATUS_OK;
688
0
  }
689
690
0
  if (session_info_flags & AUTH_SESSION_INFO_AUTHENTICATED) {
691
0
    status = add_sid_to_array(result,
692
0
            &global_sid_Authenticated_Users,
693
0
            &result->sids,
694
0
            &result->num_sids);
695
0
    if (!NT_STATUS_IS_OK(status)) {
696
0
      return status;
697
0
    }
698
0
  }
699
700
  /* Add in BUILTIN sids */
701
702
0
  become_root();
703
0
  ok = secrets_fetch_domain_sid(lp_workgroup(), &_dom_sid);
704
0
  if (ok) {
705
0
    domain_sid = &_dom_sid;
706
0
  } else {
707
0
    DEBUG(3, ("Failed to fetch domain sid for %s\n",
708
0
        lp_workgroup()));
709
0
  }
710
0
  unbecome_root();
711
712
0
  info = talloc_zero(talloc_tos(), struct acct_info);
713
0
  if (info == NULL) {
714
0
    DEBUG(0, ("talloc failed!\n"));
715
0
    return NT_STATUS_NO_MEMORY;
716
0
  }
717
718
  /* Deal with the BUILTIN\Administrators group.  If the SID can
719
     be resolved then assume that the add_aliasmem( S-1-5-32 )
720
     handled it. */
721
722
0
  status = pdb_get_aliasinfo(&global_sid_Builtin_Administrators, info);
723
0
  if (!NT_STATUS_IS_OK(status)) {
724
725
0
    become_root();
726
0
    status = create_builtin_administrators(domain_sid);
727
0
    unbecome_root();
728
729
0
    if (NT_STATUS_EQUAL(status, NT_STATUS_PROTOCOL_UNREACHABLE)) {
730
      /* Add BUILTIN\Administrators directly to token. */
731
0
      status = add_builtin_administrators(result, domain_sid);
732
0
      if ( !NT_STATUS_IS_OK(status) ) {
733
0
        DEBUG(3, ("Failed to check for local "
734
0
            "Administrators membership (%s)\n",
735
0
            nt_errstr(status)));
736
0
      }
737
0
    } else if (!NT_STATUS_IS_OK(status)) {
738
0
      DEBUG(2, ("WARNING: Failed to create "
739
0
          "BUILTIN\\Administrators group!  Can "
740
0
          "Winbind allocate gids?\n"));
741
0
    }
742
0
  }
743
744
  /* Deal with the BUILTIN\Users group.  If the SID can
745
     be resolved then assume that the add_aliasmem( S-1-5-32 )
746
     handled it. */
747
748
0
  status = pdb_get_aliasinfo(&global_sid_Builtin_Users, info);
749
0
  if (!NT_STATUS_IS_OK(status)) {
750
751
0
    become_root();
752
0
    status = create_builtin_users(domain_sid);
753
0
    unbecome_root();
754
755
0
    if (!NT_STATUS_EQUAL(status, NT_STATUS_PROTOCOL_UNREACHABLE) &&
756
0
        !NT_STATUS_IS_OK(status))
757
0
    {
758
0
      DEBUG(2, ("WARNING: Failed to create BUILTIN\\Users group! "
759
0
          "Can Winbind allocate gids?\n"));
760
0
    }
761
0
  }
762
763
  /*
764
   * Deal with the BUILTIN\Guests group.  If the SID can
765
   * be resolved then assume that the add_aliasmem( S-1-5-32 )
766
   * handled it.
767
   */
768
0
  status = pdb_get_aliasinfo(&global_sid_Builtin_Guests, info);
769
0
  if (!NT_STATUS_IS_OK(status)) {
770
771
0
    become_root();
772
0
    status = create_builtin_guests(domain_sid);
773
0
    unbecome_root();
774
775
    /*
776
     * NT_STATUS_PROTOCOL_UNREACHABLE:
777
     * => winbindd is not running.
778
     *
779
     * NT_STATUS_ACCESS_DENIED:
780
     * => no idmap config at all
781
     * and wbint_AllocateGid()/winbind_allocate_gid()
782
     * failed.
783
     *
784
     * NT_STATUS_NO_SUCH_GROUP:
785
     * => no idmap config at all and
786
     * "tdbsam:map builtin = no" means
787
     * wbint_Sids2UnixIDs() fails.
788
     */
789
0
    if (NT_STATUS_EQUAL(status, NT_STATUS_PROTOCOL_UNREACHABLE) ||
790
0
        NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
791
0
        NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_GROUP)) {
792
      /*
793
       * Add BUILTIN\Guests directly to token.
794
       * But only if the token already indicates
795
       * real guest access by:
796
       * - local GUEST account
797
       * - local GUESTS group
798
       * - domain GUESTS group
799
       *
800
       * Even if a user was authenticated, it
801
       * can be member of a guest related group.
802
       */
803
0
      status = add_builtin_guests(result, domain_sid);
804
0
      if (!NT_STATUS_IS_OK(status)) {
805
0
        DEBUG(3, ("Failed to check for local "
806
0
            "Guests membership (%s)\n",
807
0
            nt_errstr(status)));
808
        /*
809
         * This is a hard error.
810
         */
811
0
        return status;
812
0
      }
813
0
    } else if (!NT_STATUS_IS_OK(status)) {
814
0
      DEBUG(2, ("Failed to create "
815
0
          "BUILTIN\\Guests group %s!  Can "
816
0
          "Winbind allocate gids?\n",
817
0
          nt_errstr(status)));
818
      /*
819
       * This is a hard error.
820
       */
821
0
      return status;
822
0
    }
823
0
  }
824
825
0
  TALLOC_FREE(info);
826
827
  /* Deal with local groups */
828
829
0
  if (lp_winbind_nested_groups()) {
830
831
0
    become_root();
832
833
    /* Now add the aliases. First the one from our local SAM */
834
835
0
    status = add_aliases(get_global_sam_sid(), result);
836
837
0
    if (!NT_STATUS_IS_OK(status)) {
838
0
      unbecome_root();
839
0
      return status;
840
0
    }
841
842
    /* Finally the builtin ones */
843
844
0
    status = add_aliases(&global_sid_Builtin, result);
845
846
0
    if (!NT_STATUS_IS_OK(status)) {
847
0
      unbecome_root();
848
0
      return status;
849
0
    }
850
851
0
    unbecome_root();
852
0
  }
853
854
0
  if (session_info_flags & AUTH_SESSION_INFO_NTLM) {
855
0
    struct dom_sid tmp_sid = { 0, };
856
857
0
    ok = dom_sid_parse(SID_NT_NTLM_AUTHENTICATION, &tmp_sid);
858
0
    if (!ok) {
859
0
      return NT_STATUS_NO_MEMORY;
860
0
    }
861
862
0
    status = add_sid_to_array(result,
863
0
            &tmp_sid,
864
0
            &result->sids,
865
0
            &result->num_sids);
866
0
    if (!NT_STATUS_IS_OK(status)) {
867
0
      return status;
868
0
    }
869
0
  }
870
871
0
  if (session_info_flags & AUTH_SESSION_INFO_SIMPLE_PRIVILEGES) {
872
0
    if (security_token_has_builtin_administrators(result)) {
873
0
      result->privilege_mask = ~0;
874
0
    }
875
0
  } else {
876
    /* Add privileges based on current user sids */
877
0
    get_privileges_for_sids(&result->privilege_mask, result->sids,
878
0
          result->num_sids);
879
0
  }
880
881
0
  return NT_STATUS_OK;
882
0
}
883
884
/****************************************************************************
885
 prints a UNIX 'token' to debug output.
886
****************************************************************************/
887
888
void debug_unix_user_token(int dbg_class, int dbg_lev, uid_t uid, gid_t gid,
889
         int n_groups, gid_t *groups)
890
0
{
891
0
  TALLOC_CTX *frame = NULL;
892
0
  char *s = NULL;
893
0
  int     i;
894
895
0
  if (!CHECK_DEBUGLVLC(dbg_class, dbg_lev)) {
896
0
    return;
897
0
  }
898
899
0
  frame = talloc_stackframe();
900
901
0
  s = talloc_asprintf(frame,
902
0
          "UNIX token of user %ld\n",
903
0
          (long int)uid);
904
905
0
  talloc_asprintf_addbuf(
906
0
    &s,
907
0
    "Primary group is %ld and contains %i supplementary "
908
0
    "groups\n",
909
0
    (long int)gid,
910
0
    n_groups);
911
0
  for (i = 0; i < n_groups; i++) {
912
0
    talloc_asprintf_addbuf(&s,
913
0
               "Group[%3i]: %ld\n",
914
0
               i,
915
0
               (long int)groups[i]);
916
0
  }
917
918
0
  DEBUGC(dbg_class, dbg_lev, ("%s", s ? s : "(NULL)"));
919
0
  TALLOC_FREE(frame);
920
0
}
921
922
/*
923
 * Create an artificial NT token given just a domain SID.
924
 *
925
 * We have 3 cases:
926
 *
927
 * unmapped unix users: Go directly to nss to find the user's group.
928
 *
929
 * A passdb user: The list of groups is provided by pdb_enum_group_memberships.
930
 *
931
 * If the user is provided by winbind, the primary gid is set to "domain
932
 * users" of the user's domain. For an explanation why this is necessary, see
933
 * the thread starting at
934
 * http://lists.samba.org/archive/samba-technical/2006-January/044803.html.
935
 */
936
937
static NTSTATUS create_token_from_sid(TALLOC_CTX *mem_ctx,
938
              const struct dom_sid *user_sid,
939
              bool is_guest,
940
              uid_t *uid, gid_t *gid,
941
              char **found_username,
942
              struct security_token **token)
943
0
{
944
0
  NTSTATUS result = NT_STATUS_NO_SUCH_USER;
945
0
  TALLOC_CTX *tmp_ctx = talloc_stackframe();
946
0
  gid_t *gids;
947
0
  struct dom_sid *group_sids;
948
0
  struct dom_sid tmp_sid;
949
0
  uint32_t num_group_sids;
950
0
  uint32_t num_gids;
951
0
  uint32_t i;
952
0
  uint32_t high, low;
953
0
  bool range_ok;
954
0
  struct dom_sid_buf buf;
955
956
0
  if (sid_check_is_in_our_sam(user_sid)) {
957
0
    bool ret;
958
0
    uint32_t pdb_num_group_sids;
959
    /* This is a passdb user, so ask passdb */
960
961
0
    struct samu *sam_acct = NULL;
962
963
0
    if ( !(sam_acct = samu_new( tmp_ctx )) ) {
964
0
      result = NT_STATUS_NO_MEMORY;
965
0
      goto done;
966
0
    }
967
968
0
    become_root();
969
0
    ret = pdb_getsampwsid(sam_acct, user_sid);
970
0
    unbecome_root();
971
972
0
    if (!ret) {
973
0
      DEBUG(1, ("pdb_getsampwsid(%s) failed\n",
974
0
          dom_sid_str_buf(user_sid, &buf)));
975
0
      DEBUGADD(1, ("Fall back to unix user\n"));
976
0
      goto unix_user;
977
0
    }
978
979
0
    result = pdb_enum_group_memberships(tmp_ctx, sam_acct,
980
0
                &group_sids, &gids,
981
0
                &pdb_num_group_sids);
982
0
    if (!NT_STATUS_IS_OK(result)) {
983
0
      DEBUG(1, ("enum_group_memberships failed for %s: "
984
0
          "%s\n",
985
0
          dom_sid_str_buf(user_sid, &buf),
986
0
          nt_errstr(result)));
987
0
      DEBUGADD(1, ("Fall back to unix uid lookup\n"));
988
0
      goto unix_user;
989
0
    }
990
0
    num_group_sids = pdb_num_group_sids;
991
992
    /* see the smb_panic() in pdb_default_enum_group_memberships */
993
0
    SMB_ASSERT(num_group_sids > 0);
994
995
    /* Ensure we're returning the found_username on the right context. */
996
0
    *found_username = talloc_strdup(mem_ctx,
997
0
            pdb_get_username(sam_acct));
998
999
0
    if (*found_username == NULL) {
1000
0
      result = NT_STATUS_NO_MEMORY;
1001
0
      goto done;
1002
0
    }
1003
1004
    /*
1005
     * If the SID from lookup_name() was the guest sid, passdb knows
1006
     * about the mapping of guest sid to lp_guest_account()
1007
     * username and will return the unix_pw info for a guest
1008
     * user. Use it if it's there, else lookup the *uid details
1009
     * using Get_Pwnam_alloc(). See bug #6291 for details. JRA.
1010
     */
1011
1012
    /* We must always assign the *uid. */
1013
0
    if (sam_acct->unix_pw == NULL) {
1014
0
      struct passwd *pwd = Get_Pwnam_alloc(sam_acct, *found_username );
1015
0
      if (!pwd) {
1016
0
        DEBUG(10, ("Get_Pwnam_alloc failed for %s\n",
1017
0
          *found_username));
1018
0
        result = NT_STATUS_NO_SUCH_USER;
1019
0
        goto done;
1020
0
      }
1021
0
      result = samu_set_unix(sam_acct, pwd );
1022
0
      if (!NT_STATUS_IS_OK(result)) {
1023
0
        DEBUG(10, ("samu_set_unix failed for %s\n",
1024
0
          *found_username));
1025
0
        result = NT_STATUS_NO_SUCH_USER;
1026
0
        goto done;
1027
0
      }
1028
0
    }
1029
0
    *uid = sam_acct->unix_pw->pw_uid;
1030
1031
0
  } else  if (sid_check_is_in_unix_users(user_sid)) {
1032
0
    uint32_t getgroups_num_group_sids;
1033
    /* This is a unix user not in passdb. We need to ask nss
1034
     * directly, without consulting passdb */
1035
1036
0
    struct passwd *pass;
1037
1038
    /*
1039
     * This goto target is used as a fallback for the passdb
1040
     * case. The concrete bug report is when passdb gave us an
1041
     * unmapped gid.
1042
     */
1043
1044
0
  unix_user:
1045
1046
0
    if (!sid_to_uid(user_sid, uid)) {
1047
0
      DEBUG(1, ("unix_user case, sid_to_uid for %s failed\n",
1048
0
          dom_sid_str_buf(user_sid, &buf)));
1049
0
      result = NT_STATUS_NO_SUCH_USER;
1050
0
      goto done;
1051
0
    }
1052
1053
0
    uid_to_unix_users_sid(*uid, &tmp_sid);
1054
0
    user_sid = &tmp_sid;
1055
1056
0
    pass = getpwuid_alloc(tmp_ctx, *uid);
1057
0
    if (pass == NULL) {
1058
0
      DEBUG(1, ("getpwuid(%u) failed\n",
1059
0
          (unsigned int)*uid));
1060
0
      goto done;
1061
0
    }
1062
1063
0
    if (!getgroups_unix_user(tmp_ctx, pass->pw_name, pass->pw_gid,
1064
0
           &gids, &getgroups_num_group_sids)) {
1065
0
      DEBUG(1, ("getgroups_unix_user for user %s failed\n",
1066
0
          pass->pw_name));
1067
0
      goto done;
1068
0
    }
1069
0
    num_group_sids = getgroups_num_group_sids;
1070
1071
0
    group_sids = talloc_array(tmp_ctx, struct dom_sid, num_group_sids);
1072
0
    if (group_sids == NULL) {
1073
0
      DEBUG(1, ("talloc_array failed\n"));
1074
0
      result = NT_STATUS_NO_MEMORY;
1075
0
      goto done;
1076
0
    }
1077
1078
0
    for (i=0; i<num_group_sids; i++) {
1079
0
      gid_to_sid(&group_sids[i], gids[i]);
1080
0
    }
1081
1082
    /* In getgroups_unix_user we always set the primary gid */
1083
0
    SMB_ASSERT(num_group_sids > 0);
1084
1085
    /* Ensure we're returning the found_username on the right context. */
1086
0
    *found_username = talloc_strdup(mem_ctx, pass->pw_name);
1087
0
    if (*found_username == NULL) {
1088
0
      result = NT_STATUS_NO_MEMORY;
1089
0
      goto done;
1090
0
    }
1091
0
  } else {
1092
1093
    /* This user is from winbind, force the primary gid to the
1094
     * user's "domain users" group. Under certain circumstances
1095
     * (user comes from NT4), this might be a loss of
1096
     * information. But we can not rely on winbind getting the
1097
     * correct info. AD might prohibit winbind looking up that
1098
     * information. */
1099
1100
    /* We must always assign the *uid. */
1101
0
    if (!sid_to_uid(user_sid, uid)) {
1102
0
      DEBUG(1, ("winbindd case, sid_to_uid for %s failed\n",
1103
0
          dom_sid_str_buf(user_sid, &buf)));
1104
0
      result = NT_STATUS_NO_SUCH_USER;
1105
0
      goto done;
1106
0
    }
1107
1108
0
    num_group_sids = 1;
1109
0
    group_sids = talloc_array(tmp_ctx, struct dom_sid, num_group_sids);
1110
0
    if (group_sids == NULL) {
1111
0
      DEBUG(1, ("talloc_array failed\n"));
1112
0
      result = NT_STATUS_NO_MEMORY;
1113
0
      goto done;
1114
0
    }
1115
1116
0
    gids = talloc_array(tmp_ctx, gid_t, num_group_sids);
1117
0
    if (gids == NULL) {
1118
0
      result = NT_STATUS_NO_MEMORY;
1119
0
      goto done;
1120
0
    }
1121
1122
0
    sid_copy(&group_sids[0], user_sid);
1123
0
    sid_split_rid(&group_sids[0], NULL);
1124
0
    sid_append_rid(&group_sids[0], DOMAIN_RID_USERS);
1125
1126
0
    if (!sid_to_gid(&group_sids[0], &gids[0])) {
1127
0
      DEBUG(1, ("sid_to_gid(%s) failed\n",
1128
0
          dom_sid_str_buf(&group_sids[0], &buf)));
1129
0
      goto done;
1130
0
    }
1131
1132
0
    *found_username = NULL;
1133
0
  }
1134
1135
0
  *gid = gids[0];
1136
1137
  /* Add the "Unix Group" SID for each gid to catch mapped groups
1138
     and their Unix equivalent.  This is to solve the backwards
1139
     compatibility problem of 'valid users = +ntadmin' where
1140
     ntadmin has been paired with "Domain Admins" in the group
1141
     mapping table.  Otherwise smb.conf would need to be changed
1142
     to 'valid user = "Domain Admins"'.  --jerry */
1143
1144
0
  num_gids = num_group_sids;
1145
0
  range_ok = lp_idmap_default_range(&low, &high);
1146
0
  for ( i=0; i<num_gids; i++ ) {
1147
0
    struct dom_sid unix_group_sid;
1148
1149
    /* don't pickup anything managed by Winbind */
1150
0
    if (range_ok && (gids[i] >= low) && (gids[i] <= high)) {
1151
0
      continue;
1152
0
    }
1153
1154
0
    gid_to_unix_groups_sid(gids[i], &unix_group_sid);
1155
1156
0
    result = add_sid_to_array_unique(tmp_ctx, &unix_group_sid,
1157
0
             &group_sids, &num_group_sids);
1158
0
    if (!NT_STATUS_IS_OK(result)) {
1159
0
      goto done;
1160
0
    }
1161
0
  }
1162
1163
  /* Ensure we're creating the nt_token on the right context. */
1164
0
  result = create_local_nt_token(mem_ctx, user_sid,
1165
0
               is_guest, num_group_sids, group_sids, token);
1166
1167
0
  if (!NT_STATUS_IS_OK(result)) {
1168
0
    goto done;
1169
0
  }
1170
1171
0
  result = NT_STATUS_OK;
1172
0
 done:
1173
0
  TALLOC_FREE(tmp_ctx);
1174
0
  return result;
1175
0
}
1176
1177
/*
1178
 * Create an artificial NT token given just a username. (Initially intended
1179
 * for force user)
1180
 *
1181
 * We go through lookup_name() to avoid problems we had with 'winbind use
1182
 * default domain'.
1183
 *
1184
 * We have 3 cases:
1185
 *
1186
 * unmapped unix users: Go directly to nss to find the user's group.
1187
 *
1188
 * A passdb user: The list of groups is provided by pdb_enum_group_memberships.
1189
 *
1190
 * If the user is provided by winbind, the primary gid is set to "domain
1191
 * users" of the user's domain. For an explanation why this is necessary, see
1192
 * the thread starting at
1193
 * http://lists.samba.org/archive/samba-technical/2006-January/044803.html.
1194
 */
1195
1196
NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username,
1197
            bool is_guest,
1198
            uid_t *uid, gid_t *gid,
1199
            char **found_username,
1200
            struct security_token **token)
1201
0
{
1202
0
  NTSTATUS result = NT_STATUS_NO_SUCH_USER;
1203
0
  TALLOC_CTX *tmp_ctx = talloc_stackframe();
1204
0
  struct dom_sid user_sid;
1205
0
  enum lsa_SidType type;
1206
1207
0
  if (!lookup_name_smbconf(tmp_ctx, username, LOOKUP_NAME_ALL,
1208
0
       NULL, NULL, &user_sid, &type)) {
1209
0
    DEBUG(1, ("lookup_name_smbconf for %s failed\n", username));
1210
0
    goto done;
1211
0
  }
1212
1213
0
  if (type != SID_NAME_USER) {
1214
0
    DEBUG(1, ("%s is a %s, not a user\n", username,
1215
0
        sid_type_lookup(type)));
1216
0
    goto done;
1217
0
  }
1218
1219
0
  result = create_token_from_sid(mem_ctx, &user_sid, is_guest, uid, gid, found_username, token);
1220
1221
0
  if (!NT_STATUS_IS_OK(result)) {
1222
0
    goto done;
1223
0
  }
1224
1225
  /*
1226
   * If result == NT_STATUS_OK then
1227
   * we know we have a valid token. Ensure
1228
   * we also have a valid username to match.
1229
   */
1230
1231
0
  if (*found_username == NULL) {
1232
0
    *found_username = talloc_strdup(mem_ctx, username);
1233
0
    if (*found_username == NULL) {
1234
0
      result = NT_STATUS_NO_MEMORY;
1235
0
    }
1236
0
  }
1237
1238
0
done:
1239
0
  TALLOC_FREE(tmp_ctx);
1240
0
  return result;
1241
0
}
1242
1243
/***************************************************************************
1244
 Build upon create_token_from_sid:
1245
1246
 Expensive helper function to figure out whether a user given its sid is
1247
 member of a particular group.
1248
***************************************************************************/
1249
1250
bool user_sid_in_group_sid(const struct dom_sid *sid, const struct dom_sid *group_sid)
1251
0
{
1252
0
  NTSTATUS status;
1253
0
  uid_t uid;
1254
0
  gid_t gid;
1255
0
  char *found_username;
1256
0
  struct security_token *token;
1257
0
  bool result = false;
1258
0
  enum lsa_SidType type;
1259
0
  TALLOC_CTX *mem_ctx = talloc_stackframe();
1260
0
  struct dom_sid_buf buf;
1261
1262
0
  if (!lookup_sid(mem_ctx, sid,
1263
0
       NULL, NULL, &type)) {
1264
0
    DEBUG(1, ("lookup_sid for %s failed\n",
1265
0
        dom_sid_str_buf(sid, &buf)));
1266
0
    goto done;
1267
0
  }
1268
1269
0
  if (type != SID_NAME_USER) {
1270
0
    DEBUG(5, ("%s is a %s, not a user\n",
1271
0
        dom_sid_str_buf(sid, &buf),
1272
0
        sid_type_lookup(type)));
1273
0
    goto done;
1274
0
  }
1275
1276
0
  status = create_token_from_sid(mem_ctx, sid, False,
1277
0
               &uid, &gid, &found_username,
1278
0
               &token);
1279
1280
0
  if (!NT_STATUS_IS_OK(status)) {
1281
0
    DEBUG(10, ("could not create token for %s\n",
1282
0
         dom_sid_str_buf(sid, &buf)));
1283
0
    goto done;
1284
0
  }
1285
1286
0
  result = security_token_has_sid(token, group_sid);
1287
1288
0
done:
1289
0
  TALLOC_FREE(mem_ctx);
1290
0
  return result;
1291
0
}
1292
1293
/***************************************************************************
1294
 Build upon create_token_from_username:
1295
1296
 Expensive helper function to figure out whether a user given its name is
1297
 member of a particular group.
1298
***************************************************************************/
1299
1300
bool user_in_group_sid(const char *username, const struct dom_sid *group_sid)
1301
0
{
1302
0
  NTSTATUS status;
1303
0
  uid_t uid;
1304
0
  gid_t gid;
1305
0
  char *found_username;
1306
0
  struct security_token *token;
1307
0
  bool result;
1308
0
  TALLOC_CTX *mem_ctx = talloc_stackframe();
1309
1310
0
  status = create_token_from_username(mem_ctx, username, False,
1311
0
              &uid, &gid, &found_username,
1312
0
              &token);
1313
1314
0
  if (!NT_STATUS_IS_OK(status)) {
1315
0
    DEBUG(10, ("could not create token for %s\n", username));
1316
0
    TALLOC_FREE(mem_ctx);
1317
0
    return False;
1318
0
  }
1319
1320
0
  result = security_token_has_sid(token, group_sid);
1321
1322
0
  TALLOC_FREE(mem_ctx);
1323
0
  return result;
1324
0
}
1325
1326
bool user_in_group(const char *username, const char *groupname)
1327
0
{
1328
0
  TALLOC_CTX *mem_ctx = talloc_stackframe();
1329
0
  struct dom_sid group_sid;
1330
0
  bool ret;
1331
1332
0
  ret = lookup_name(mem_ctx, groupname, LOOKUP_NAME_ALL,
1333
0
        NULL, NULL, &group_sid, NULL);
1334
0
  TALLOC_FREE(mem_ctx);
1335
1336
0
  if (!ret) {
1337
0
    DEBUG(10, ("lookup_name for (%s) failed.\n", groupname));
1338
0
    return False;
1339
0
  }
1340
1341
0
  return user_in_group_sid(username, &group_sid);
1342
0
}
1343
1344
/* END */