Line data Source code
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 23593 : bool nt_token_check_sid ( const struct dom_sid *sid, const struct security_token *token )
44 : {
45 23593 : if ( !sid || !token )
46 0 : return False;
47 :
48 23593 : return security_token_has_sid(token, sid);
49 : }
50 :
51 134 : bool nt_token_check_domain_rid( struct security_token *token, uint32_t rid )
52 : {
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 134 : if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
59 0 : if ( !secrets_fetch_domain_sid( lp_workgroup(),
60 : &domain_sid ) ) {
61 0 : DEBUG(1,("nt_token_check_domain_rid: Cannot lookup "
62 : "SID for domain [%s]\n", lp_workgroup()));
63 0 : return False;
64 : }
65 : }
66 : else
67 134 : sid_copy( &domain_sid, get_global_sam_sid() );
68 :
69 134 : sid_append_rid( &domain_sid, rid );
70 :
71 134 : return nt_token_check_sid( &domain_sid, token );\
72 : }
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 104 : NTSTATUS get_root_nt_token( struct security_token **token )
82 : {
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 104 : NTSTATUS status = NT_STATUS_OK;
88 :
89 104 : cache_data = memcache_lookup_talloc(
90 : NULL, SINGLETON_CACHE_TALLOC,
91 : data_blob_string_const_null("root_nt_token"));
92 :
93 104 : if (cache_data != NULL) {
94 0 : *token = talloc_get_type_abort(
95 : cache_data, struct security_token);
96 0 : return NT_STATUS_OK;
97 : }
98 :
99 104 : if ( !(pw = getpwuid(0)) ) {
100 52 : if ( !(pw = getpwnam("root")) ) {
101 0 : DBG_ERR("get_root_nt_token: both getpwuid(0) "
102 : "and getpwnam(\"root\") failed!\n");
103 0 : return NT_STATUS_NO_SUCH_USER;
104 : }
105 : }
106 :
107 : /* get the user and primary group SIDs; although the
108 : BUILTIN\Administrators SId is really the one that matters here */
109 :
110 104 : uid_to_sid(&u_sid, pw->pw_uid);
111 104 : gid_to_sid(&g_sid, pw->pw_gid);
112 :
113 104 : status = create_local_nt_token(talloc_tos(), &u_sid, False,
114 : 1, &global_sid_Builtin_Administrators, token);
115 104 : if (!NT_STATUS_IS_OK(status)) {
116 0 : return status;
117 : }
118 :
119 104 : security_token_set_privilege(*token, SEC_PRIV_DISK_OPERATOR);
120 :
121 104 : for_cache = *token;
122 :
123 104 : memcache_add_talloc(
124 : NULL, SINGLETON_CACHE_TALLOC,
125 : data_blob_string_const_null("root_nt_token"), &for_cache);
126 :
127 104 : return status;
128 : }
129 :
130 :
131 : /*
132 : * Add alias SIDs from memberships within the partially created token SID list
133 : */
134 :
135 46638 : NTSTATUS add_aliases(const struct dom_sid *domain_sid,
136 : struct security_token *token)
137 : {
138 0 : uint32_t *aliases;
139 0 : size_t i, num_aliases;
140 0 : NTSTATUS status;
141 0 : TALLOC_CTX *tmp_ctx;
142 :
143 46638 : if (!(tmp_ctx = talloc_init("add_aliases"))) {
144 0 : return NT_STATUS_NO_MEMORY;
145 : }
146 :
147 46638 : aliases = NULL;
148 46638 : num_aliases = 0;
149 :
150 46638 : status = pdb_enum_alias_memberships(tmp_ctx, domain_sid,
151 46638 : token->sids,
152 46638 : token->num_sids,
153 : &aliases, &num_aliases);
154 :
155 46638 : if (!NT_STATUS_IS_OK(status)) {
156 0 : DEBUG(10, ("pdb_enum_alias_memberships failed: %s\n",
157 : nt_errstr(status)));
158 0 : goto done;
159 : }
160 :
161 56266 : for (i=0; i<num_aliases; i++) {
162 0 : struct dom_sid alias_sid;
163 9628 : sid_compose(&alias_sid, domain_sid, aliases[i]);
164 9628 : status = add_sid_to_array_unique(token, &alias_sid,
165 : &token->sids,
166 : &token->num_sids);
167 9628 : if (!NT_STATUS_IS_OK(status)) {
168 0 : DEBUG(0, ("add_sid_to_array failed\n"));
169 0 : goto done;
170 : }
171 : }
172 :
173 46638 : done:
174 46638 : TALLOC_FREE(tmp_ctx);
175 46638 : return NT_STATUS_OK;
176 : }
177 :
178 : /*******************************************************************
179 : *******************************************************************/
180 :
181 11484 : static NTSTATUS add_builtin_administrators(struct security_token *token,
182 : const struct dom_sid *dom_sid)
183 : {
184 0 : struct dom_sid domadm;
185 0 : NTSTATUS status;
186 :
187 : /* nothing to do if we aren't in a domain */
188 :
189 11484 : if ( !(IS_DC || lp_server_role()==ROLE_DOMAIN_MEMBER) ) {
190 11414 : return NT_STATUS_OK;
191 : }
192 :
193 : /* Find the Domain Admins SID */
194 :
195 70 : if ( IS_DC ) {
196 22 : sid_copy( &domadm, get_global_sam_sid() );
197 : } else {
198 48 : if (dom_sid == NULL) {
199 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
200 : }
201 48 : sid_copy(&domadm, dom_sid);
202 : }
203 70 : sid_append_rid( &domadm, DOMAIN_RID_ADMINS );
204 :
205 : /* Add Administrators if the user beloongs to Domain Admins */
206 :
207 70 : if ( nt_token_check_sid( &domadm, token ) ) {
208 0 : status = add_sid_to_array(token,
209 : &global_sid_Builtin_Administrators,
210 : &token->sids, &token->num_sids);
211 0 : if (!NT_STATUS_IS_OK(status)) {
212 0 : return status;
213 : }
214 : }
215 :
216 70 : return NT_STATUS_OK;
217 : }
218 :
219 11492 : static NTSTATUS add_builtin_guests(struct security_token *token,
220 : const struct dom_sid *dom_sid)
221 : {
222 0 : struct dom_sid tmp_sid;
223 0 : NTSTATUS status;
224 :
225 : /*
226 : * First check the local GUEST account.
227 : */
228 11492 : sid_compose(&tmp_sid, get_global_sam_sid(), DOMAIN_RID_GUEST);
229 :
230 11492 : if (nt_token_check_sid(&tmp_sid, token)) {
231 162 : status = add_sid_to_array_unique(token,
232 : &global_sid_Builtin_Guests,
233 : &token->sids, &token->num_sids);
234 162 : if (!NT_STATUS_IS_OK(status)) {
235 0 : return status;
236 : }
237 :
238 162 : return NT_STATUS_OK;
239 : }
240 :
241 : /*
242 : * First check the local GUESTS group.
243 : */
244 11330 : sid_compose(&tmp_sid, get_global_sam_sid(), DOMAIN_RID_GUESTS);
245 :
246 11330 : if (nt_token_check_sid(&tmp_sid, token)) {
247 0 : status = add_sid_to_array_unique(token,
248 : &global_sid_Builtin_Guests,
249 : &token->sids, &token->num_sids);
250 0 : if (!NT_STATUS_IS_OK(status)) {
251 0 : return status;
252 : }
253 :
254 0 : return NT_STATUS_OK;
255 : }
256 :
257 11330 : if (lp_server_role() != ROLE_DOMAIN_MEMBER) {
258 11330 : return NT_STATUS_OK;
259 : }
260 :
261 0 : if (dom_sid == NULL) {
262 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
263 : }
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 : &global_sid_Builtin_Guests,
274 : &token->sids, &token->num_sids);
275 0 : if (!NT_STATUS_IS_OK(status)) {
276 0 : return status;
277 : }
278 :
279 0 : return NT_STATUS_OK;
280 : }
281 :
282 0 : return NT_STATUS_OK;
283 : }
284 :
285 : static NTSTATUS add_local_groups(struct security_token *result,
286 : bool is_guest);
287 :
288 42995 : 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 : {
292 : /* USER SID */
293 42995 : 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 : }
302 0 : sid_copy(sid, &extra->user_sid);
303 : } else {
304 42995 : sid_copy(sid, info3->base.domain_sid);
305 42995 : sid_append_rid(sid, info3->base.rid);
306 : }
307 42995 : return NT_STATUS_OK;
308 : }
309 :
310 24287 : static struct security_token *init_local_nt_token(TALLOC_CTX *mem_ctx)
311 : {
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 24287 : = security_token_initialise(mem_ctx,
320 : CLAIMS_EVALUATION_NEVER);
321 :
322 24287 : if (result == NULL) {
323 0 : DBG_ERR("talloc failed for security_token\n");
324 0 : return NULL;
325 : }
326 :
327 24287 : return result;
328 : }
329 :
330 21677 : 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 : {
336 21677 : struct security_token *usrtok = NULL;
337 21677 : uint32_t session_info_flags = 0;
338 0 : NTSTATUS status;
339 0 : uint32_t i;
340 :
341 21677 : DEBUG(10, ("Create local NT token for %s\n",
342 : info3->base.account_name.string));
343 :
344 21677 : usrtok = init_local_nt_token(mem_ctx);
345 21677 : if (!usrtok) {
346 0 : return NT_STATUS_NO_MEMORY;
347 : }
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 21677 : usrtok->sids = talloc_array(usrtok, struct dom_sid, 2);
354 21677 : if (!usrtok->sids) {
355 0 : TALLOC_FREE(usrtok);
356 0 : return NT_STATUS_NO_MEMORY;
357 : }
358 21677 : usrtok->num_sids = 2;
359 :
360 21677 : status = get_user_sid_info3_and_extra(info3, extra, &usrtok->sids[0]);
361 21677 : if (!NT_STATUS_IS_OK(status)) {
362 0 : TALLOC_FREE(usrtok);
363 0 : return status;
364 : }
365 :
366 : /* GROUP SID */
367 21677 : 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 : }
377 0 : sid_copy(&usrtok->sids[1], &extra->pgid_sid);
378 : } else {
379 21677 : sid_copy(&usrtok->sids[1], info3->base.domain_sid);
380 21677 : sid_append_rid(&usrtok->sids[1],
381 21677 : info3->base.primary_gid);
382 : }
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 28386 : for (i = 0; i < info3->base.groups.count; i++) {
391 0 : struct dom_sid tmp_sid;
392 :
393 6709 : sid_copy(&tmp_sid, info3->base.domain_sid);
394 6709 : sid_append_rid(&tmp_sid, info3->base.groups.rids[i].rid);
395 :
396 6709 : status = add_sid_to_array_unique(usrtok, &tmp_sid,
397 : &usrtok->sids,
398 : &usrtok->num_sids);
399 6709 : 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 : }
404 : }
405 :
406 : /* now also add extra sids if they are not the special user/group
407 : * sids */
408 62482 : for (i = 0; i < info3->sidcount; i++) {
409 40805 : status = add_sid_to_array_unique(usrtok,
410 40805 : info3->sids[i].sid,
411 : &usrtok->sids,
412 : &usrtok->num_sids);
413 40805 : 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 : }
418 : }
419 :
420 21677 : status = add_local_groups(usrtok, is_guest);
421 21677 : 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 : }
426 :
427 21677 : session_info_flags |= AUTH_SESSION_INFO_DEFAULT_GROUPS;
428 21677 : if (!is_guest) {
429 20901 : session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
430 : }
431 :
432 21677 : status = finalize_local_nt_token(usrtok, session_info_flags);
433 21677 : 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 : }
438 :
439 21677 : *ntok = usrtok;
440 21677 : return NT_STATUS_OK;
441 : }
442 :
443 : /*******************************************************************
444 : Create a NT token for the user, expanding local aliases
445 : *******************************************************************/
446 :
447 2610 : 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 : {
454 2610 : struct security_token *result = NULL;
455 0 : int i;
456 0 : NTSTATUS status;
457 2610 : uint32_t session_info_flags = 0;
458 0 : struct dom_sid_buf buf;
459 :
460 2610 : DEBUG(10, ("Create local NT token for %s\n",
461 : dom_sid_str_buf(user_sid, &buf)));
462 :
463 2610 : result = init_local_nt_token(mem_ctx);
464 2610 : if (result == NULL) {
465 0 : status = NT_STATUS_NO_MEMORY;
466 0 : goto err;
467 : }
468 :
469 : /* Add the user and primary group sid */
470 :
471 2610 : status = add_sid_to_array(result, user_sid,
472 : &result->sids, &result->num_sids);
473 2610 : if (!NT_STATUS_IS_OK(status)) {
474 0 : goto err;
475 : }
476 :
477 : /* For guest, num_groupsids may be zero. */
478 2610 : if (num_groupsids) {
479 2610 : status = add_sid_to_array(result, &groupsids[0],
480 : &result->sids,
481 : &result->num_sids);
482 2610 : if (!NT_STATUS_IS_OK(status)) {
483 0 : goto err;
484 : }
485 : }
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 35818 : for (i=1; i<num_groupsids; i++) {
494 33208 : status = add_sid_to_array_unique(result, &groupsids[i],
495 : &result->sids,
496 : &result->num_sids);
497 33208 : if (!NT_STATUS_IS_OK(status)) {
498 0 : goto err;
499 : }
500 : }
501 :
502 2610 : status = add_local_groups(result, is_guest);
503 2610 : if (!NT_STATUS_IS_OK(status)) {
504 968 : goto err;
505 : }
506 :
507 1642 : session_info_flags |= AUTH_SESSION_INFO_DEFAULT_GROUPS;
508 1642 : if (!is_guest) {
509 1567 : session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
510 : }
511 :
512 1642 : status = finalize_local_nt_token(result, session_info_flags);
513 1642 : if (!NT_STATUS_IS_OK(status)) {
514 0 : goto err;
515 : }
516 :
517 1642 : 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 75 : status = add_sid_to_array_unique(result,
530 : &global_sid_Builtin_Guests,
531 : &result->sids,
532 : &result->num_sids);
533 75 : if (!NT_STATUS_IS_OK(status)) {
534 0 : DEBUG(3, ("Failed to add SID to nt token\n"));
535 0 : goto err;
536 : }
537 : }
538 :
539 1642 : *token = result;
540 1642 : return NT_STATUS_SUCCESS;
541 :
542 968 : err:
543 968 : TALLOC_FREE(result);
544 968 : return status;
545 : }
546 :
547 : /***************************************************
548 : Merge in any groups from /etc/group.
549 : ***************************************************/
550 :
551 24287 : static NTSTATUS add_local_groups(struct security_token *result,
552 : bool is_guest)
553 : {
554 24287 : gid_t *gids = NULL;
555 24287 : uint32_t getgroups_num_group_sids = 0;
556 24287 : struct passwd *pass = NULL;
557 24287 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
558 0 : uint32_t i;
559 :
560 24287 : 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 851 : pass = Get_Pwnam_alloc(tmp_ctx, lp_guest_account());
568 : } else {
569 0 : uid_t uid;
570 :
571 : /* For non-guest result->sids[0] is always the user sid. */
572 23436 : 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 : }
580 :
581 23436 : pass = getpwuid_alloc(tmp_ctx, uid);
582 23436 : if (pass == NULL) {
583 0 : struct dom_sid_buf buf;
584 968 : DBG_ERR("SID %s -> getpwuid(%u) failed, is nsswitch configured?\n",
585 : dom_sid_str_buf(&result->sids[0], &buf),
586 : (unsigned int)uid);
587 968 : TALLOC_FREE(tmp_ctx);
588 968 : return NT_STATUS_NO_SUCH_USER;
589 : }
590 : }
591 :
592 23319 : if (!pass) {
593 0 : TALLOC_FREE(tmp_ctx);
594 0 : return NT_STATUS_UNSUCCESSFUL;
595 : }
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 23319 : if (!getgroups_unix_user(tmp_ctx, pass->pw_name, pass->pw_gid,
618 : &gids, &getgroups_num_group_sids)) {
619 0 : DEBUG(1, ("getgroups_unix_user for user %s failed\n",
620 : pass->pw_name));
621 0 : TALLOC_FREE(tmp_ctx);
622 0 : return NT_STATUS_UNSUCCESSFUL;
623 : }
624 :
625 67143 : for (i=0; i<getgroups_num_group_sids; i++) {
626 0 : NTSTATUS status;
627 0 : struct dom_sid grp_sid;
628 43824 : gid_to_sid(&grp_sid, gids[i]);
629 :
630 43824 : status = add_sid_to_array_unique(result,
631 : &grp_sid,
632 : &result->sids,
633 : &result->num_sids);
634 43824 : 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 : }
639 : }
640 23319 : TALLOC_FREE(tmp_ctx);
641 23319 : return NT_STATUS_OK;
642 : }
643 :
644 24704 : NTSTATUS finalize_local_nt_token(struct security_token *result,
645 : uint32_t session_info_flags)
646 : {
647 24704 : struct dom_sid _dom_sid = { 0, };
648 24704 : struct dom_sid *domain_sid = NULL;
649 0 : NTSTATUS status;
650 0 : struct acct_info *info;
651 0 : bool ok;
652 :
653 24704 : result->privilege_mask = 0;
654 24704 : result->rights_mask = 0;
655 :
656 24704 : if (result->num_sids == 0) {
657 0 : return NT_STATUS_INVALID_TOKEN;
658 : }
659 :
660 24704 : if (session_info_flags & AUTH_SESSION_INFO_DEFAULT_GROUPS) {
661 24095 : status = add_sid_to_array(result, &global_sid_World,
662 : &result->sids, &result->num_sids);
663 24095 : if (!NT_STATUS_IS_OK(status)) {
664 0 : return status;
665 : }
666 24095 : status = add_sid_to_array(result, &global_sid_Network,
667 : &result->sids, &result->num_sids);
668 24095 : if (!NT_STATUS_IS_OK(status)) {
669 0 : return status;
670 : }
671 : }
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 24704 : if (security_token_is_anonymous(result)) {
683 776 : return NT_STATUS_OK;
684 : }
685 23928 : if (security_token_is_system(result)) {
686 609 : result->privilege_mask = ~0;
687 609 : return NT_STATUS_OK;
688 : }
689 :
690 23319 : if (session_info_flags & AUTH_SESSION_INFO_AUTHENTICATED) {
691 22468 : status = add_sid_to_array(result,
692 : &global_sid_Authenticated_Users,
693 : &result->sids,
694 : &result->num_sids);
695 22468 : if (!NT_STATUS_IS_OK(status)) {
696 0 : return status;
697 : }
698 : }
699 :
700 : /* Add in BUILTIN sids */
701 :
702 23319 : become_root();
703 23319 : ok = secrets_fetch_domain_sid(lp_workgroup(), &_dom_sid);
704 23319 : if (ok) {
705 11897 : domain_sid = &_dom_sid;
706 : } else {
707 11422 : DEBUG(3, ("Failed to fetch domain sid for %s\n",
708 : lp_workgroup()));
709 : }
710 23319 : unbecome_root();
711 :
712 23319 : info = talloc_zero(talloc_tos(), struct acct_info);
713 23319 : if (info == NULL) {
714 0 : DEBUG(0, ("talloc failed!\n"));
715 0 : return NT_STATUS_NO_MEMORY;
716 : }
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 23319 : status = pdb_get_aliasinfo(&global_sid_Builtin_Administrators, info);
723 23319 : if (!NT_STATUS_IS_OK(status)) {
724 :
725 11489 : become_root();
726 11489 : status = create_builtin_administrators(domain_sid);
727 11489 : unbecome_root();
728 :
729 11489 : if (NT_STATUS_EQUAL(status, NT_STATUS_PROTOCOL_UNREACHABLE)) {
730 : /* Add BUILTIN\Administrators directly to token. */
731 11484 : status = add_builtin_administrators(result, domain_sid);
732 11484 : if ( !NT_STATUS_IS_OK(status) ) {
733 0 : DEBUG(3, ("Failed to check for local "
734 : "Administrators membership (%s)\n",
735 : nt_errstr(status)));
736 : }
737 5 : } else if (!NT_STATUS_IS_OK(status)) {
738 0 : DEBUG(2, ("WARNING: Failed to create "
739 : "BUILTIN\\Administrators group! Can "
740 : "Winbind allocate gids?\n"));
741 : }
742 : }
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 23319 : status = pdb_get_aliasinfo(&global_sid_Builtin_Users, info);
749 23319 : if (!NT_STATUS_IS_OK(status)) {
750 :
751 11492 : become_root();
752 11492 : status = create_builtin_users(domain_sid);
753 11492 : unbecome_root();
754 :
755 11492 : if (!NT_STATUS_EQUAL(status, NT_STATUS_PROTOCOL_UNREACHABLE) &&
756 1 : !NT_STATUS_IS_OK(status))
757 : {
758 0 : DEBUG(2, ("WARNING: Failed to create BUILTIN\\Users group! "
759 : "Can Winbind allocate gids?\n"));
760 : }
761 : }
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 23319 : status = pdb_get_aliasinfo(&global_sid_Builtin_Guests, info);
769 23319 : if (!NT_STATUS_IS_OK(status)) {
770 :
771 11497 : become_root();
772 11497 : status = create_builtin_guests(domain_sid);
773 11497 : 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 11497 : if (NT_STATUS_EQUAL(status, NT_STATUS_PROTOCOL_UNREACHABLE) ||
790 5 : NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
791 5 : 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 11492 : status = add_builtin_guests(result, domain_sid);
804 11492 : if (!NT_STATUS_IS_OK(status)) {
805 0 : DEBUG(3, ("Failed to check for local "
806 : "Guests membership (%s)\n",
807 : nt_errstr(status)));
808 : /*
809 : * This is a hard error.
810 : */
811 0 : return status;
812 : }
813 5 : } else if (!NT_STATUS_IS_OK(status)) {
814 0 : DEBUG(2, ("Failed to create "
815 : "BUILTIN\\Guests group %s! Can "
816 : "Winbind allocate gids?\n",
817 : nt_errstr(status)));
818 : /*
819 : * This is a hard error.
820 : */
821 0 : return status;
822 : }
823 : }
824 :
825 23319 : TALLOC_FREE(info);
826 :
827 : /* Deal with local groups */
828 :
829 23319 : if (lp_winbind_nested_groups()) {
830 :
831 23319 : become_root();
832 :
833 : /* Now add the aliases. First the one from our local SAM */
834 :
835 23319 : status = add_aliases(get_global_sam_sid(), result);
836 :
837 23319 : if (!NT_STATUS_IS_OK(status)) {
838 0 : unbecome_root();
839 0 : return status;
840 : }
841 :
842 : /* Finally the builtin ones */
843 :
844 23319 : status = add_aliases(&global_sid_Builtin, result);
845 :
846 23319 : if (!NT_STATUS_IS_OK(status)) {
847 0 : unbecome_root();
848 0 : return status;
849 : }
850 :
851 23319 : unbecome_root();
852 : }
853 :
854 23319 : 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 : }
861 :
862 0 : status = add_sid_to_array(result,
863 : &tmp_sid,
864 : &result->sids,
865 : &result->num_sids);
866 0 : if (!NT_STATUS_IS_OK(status)) {
867 0 : return status;
868 : }
869 : }
870 :
871 23319 : 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 : }
875 : } else {
876 : /* Add privileges based on current user sids */
877 23319 : get_privileges_for_sids(&result->privilege_mask, result->sids,
878 23319 : result->num_sids);
879 : }
880 :
881 23319 : return NT_STATUS_OK;
882 : }
883 :
884 : /****************************************************************************
885 : prints a UNIX 'token' to debug output.
886 : ****************************************************************************/
887 :
888 5428283 : 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 : {
891 5428283 : TALLOC_CTX *frame = talloc_stackframe();
892 5428283 : char *s = NULL;
893 19214 : int i;
894 :
895 5428283 : s = talloc_asprintf(frame,
896 : "UNIX token of user %ld\n",
897 : (long int)uid);
898 :
899 5428283 : talloc_asprintf_addbuf(
900 : &s,
901 : "Primary group is %ld and contains %i supplementary "
902 : "groups\n",
903 : (long int)gid,
904 : n_groups);
905 8052903 : for (i = 0; i < n_groups; i++) {
906 2605406 : talloc_asprintf_addbuf(&s,
907 : "Group[%3i]: %ld\n",
908 : i,
909 2605406 : (long int)groups[i]);
910 : }
911 :
912 5428283 : DEBUGC(dbg_class, dbg_lev, ("%s", s ? s : "(NULL)"));
913 5428283 : TALLOC_FREE(frame);
914 5428283 : }
915 :
916 : /*
917 : * Create an artificial NT token given just a domain SID.
918 : *
919 : * We have 3 cases:
920 : *
921 : * unmapped unix users: Go directly to nss to find the user's group.
922 : *
923 : * A passdb user: The list of groups is provided by pdb_enum_group_memberships.
924 : *
925 : * If the user is provided by winbind, the primary gid is set to "domain
926 : * users" of the user's domain. For an explanation why this is necessary, see
927 : * the thread starting at
928 : * http://lists.samba.org/archive/samba-technical/2006-January/044803.html.
929 : */
930 :
931 5132 : static NTSTATUS create_token_from_sid(TALLOC_CTX *mem_ctx,
932 : const struct dom_sid *user_sid,
933 : bool is_guest,
934 : uid_t *uid, gid_t *gid,
935 : char **found_username,
936 : struct security_token **token)
937 : {
938 5132 : NTSTATUS result = NT_STATUS_NO_SUCH_USER;
939 5132 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
940 270 : gid_t *gids;
941 270 : struct dom_sid *group_sids;
942 270 : struct dom_sid tmp_sid;
943 270 : uint32_t num_group_sids;
944 270 : uint32_t num_gids;
945 270 : uint32_t i;
946 270 : uint32_t high, low;
947 270 : bool range_ok;
948 270 : struct dom_sid_buf buf;
949 :
950 5132 : if (sid_check_is_in_our_sam(user_sid)) {
951 270 : bool ret;
952 270 : uint32_t pdb_num_group_sids;
953 : /* This is a passdb user, so ask passdb */
954 :
955 4844 : struct samu *sam_acct = NULL;
956 :
957 4844 : if ( !(sam_acct = samu_new( tmp_ctx )) ) {
958 0 : result = NT_STATUS_NO_MEMORY;
959 0 : goto done;
960 : }
961 :
962 4844 : become_root();
963 4844 : ret = pdb_getsampwsid(sam_acct, user_sid);
964 4844 : unbecome_root();
965 :
966 4844 : if (!ret) {
967 0 : DEBUG(1, ("pdb_getsampwsid(%s) failed\n",
968 : dom_sid_str_buf(user_sid, &buf)));
969 0 : DEBUGADD(1, ("Fall back to unix user\n"));
970 0 : goto unix_user;
971 : }
972 :
973 4844 : result = pdb_enum_group_memberships(tmp_ctx, sam_acct,
974 : &group_sids, &gids,
975 : &pdb_num_group_sids);
976 4844 : if (!NT_STATUS_IS_OK(result)) {
977 0 : DEBUG(1, ("enum_group_memberships failed for %s: "
978 : "%s\n",
979 : dom_sid_str_buf(user_sid, &buf),
980 : nt_errstr(result)));
981 0 : DEBUGADD(1, ("Fall back to unix uid lookup\n"));
982 0 : goto unix_user;
983 : }
984 4844 : num_group_sids = pdb_num_group_sids;
985 :
986 : /* see the smb_panic() in pdb_default_enum_group_memberships */
987 4844 : SMB_ASSERT(num_group_sids > 0);
988 :
989 : /* Ensure we're returning the found_username on the right context. */
990 4844 : *found_username = talloc_strdup(mem_ctx,
991 : pdb_get_username(sam_acct));
992 :
993 4844 : if (*found_username == NULL) {
994 0 : result = NT_STATUS_NO_MEMORY;
995 0 : goto done;
996 : }
997 :
998 : /*
999 : * If the SID from lookup_name() was the guest sid, passdb knows
1000 : * about the mapping of guest sid to lp_guest_account()
1001 : * username and will return the unix_pw info for a guest
1002 : * user. Use it if it's there, else lookup the *uid details
1003 : * using Get_Pwnam_alloc(). See bug #6291 for details. JRA.
1004 : */
1005 :
1006 : /* We must always assign the *uid. */
1007 4844 : if (sam_acct->unix_pw == NULL) {
1008 4698 : struct passwd *pwd = Get_Pwnam_alloc(sam_acct, *found_username );
1009 4698 : if (!pwd) {
1010 2474 : DEBUG(10, ("Get_Pwnam_alloc failed for %s\n",
1011 : *found_username));
1012 2474 : result = NT_STATUS_NO_SUCH_USER;
1013 2474 : goto done;
1014 : }
1015 2224 : result = samu_set_unix(sam_acct, pwd );
1016 2224 : if (!NT_STATUS_IS_OK(result)) {
1017 0 : DEBUG(10, ("samu_set_unix failed for %s\n",
1018 : *found_username));
1019 0 : result = NT_STATUS_NO_SUCH_USER;
1020 0 : goto done;
1021 : }
1022 : }
1023 2370 : *uid = sam_acct->unix_pw->pw_uid;
1024 :
1025 288 : } else if (sid_check_is_in_unix_users(user_sid)) {
1026 0 : uint32_t getgroups_num_group_sids;
1027 : /* This is a unix user not in passdb. We need to ask nss
1028 : * directly, without consulting passdb */
1029 :
1030 0 : struct passwd *pass;
1031 :
1032 : /*
1033 : * This goto target is used as a fallback for the passdb
1034 : * case. The concrete bug report is when passdb gave us an
1035 : * unmapped gid.
1036 : */
1037 :
1038 264 : unix_user:
1039 :
1040 264 : if (!sid_to_uid(user_sid, uid)) {
1041 0 : DEBUG(1, ("unix_user case, sid_to_uid for %s failed\n",
1042 : dom_sid_str_buf(user_sid, &buf)));
1043 0 : result = NT_STATUS_NO_SUCH_USER;
1044 0 : goto done;
1045 : }
1046 :
1047 264 : uid_to_unix_users_sid(*uid, &tmp_sid);
1048 264 : user_sid = &tmp_sid;
1049 :
1050 264 : pass = getpwuid_alloc(tmp_ctx, *uid);
1051 264 : if (pass == NULL) {
1052 130 : DEBUG(1, ("getpwuid(%u) failed\n",
1053 : (unsigned int)*uid));
1054 130 : goto done;
1055 : }
1056 :
1057 134 : if (!getgroups_unix_user(tmp_ctx, pass->pw_name, pass->pw_gid,
1058 : &gids, &getgroups_num_group_sids)) {
1059 0 : DEBUG(1, ("getgroups_unix_user for user %s failed\n",
1060 : pass->pw_name));
1061 0 : goto done;
1062 : }
1063 134 : num_group_sids = getgroups_num_group_sids;
1064 :
1065 134 : group_sids = talloc_array(tmp_ctx, struct dom_sid, num_group_sids);
1066 134 : if (group_sids == NULL) {
1067 0 : DEBUG(1, ("talloc_array failed\n"));
1068 0 : result = NT_STATUS_NO_MEMORY;
1069 0 : goto done;
1070 : }
1071 :
1072 268 : for (i=0; i<num_group_sids; i++) {
1073 134 : gid_to_sid(&group_sids[i], gids[i]);
1074 : }
1075 :
1076 : /* In getgroups_unix_user we always set the primary gid */
1077 134 : SMB_ASSERT(num_group_sids > 0);
1078 :
1079 : /* Ensure we're returning the found_username on the right context. */
1080 134 : *found_username = talloc_strdup(mem_ctx, pass->pw_name);
1081 134 : if (*found_username == NULL) {
1082 0 : result = NT_STATUS_NO_MEMORY;
1083 0 : goto done;
1084 : }
1085 : } else {
1086 :
1087 : /* This user is from winbind, force the primary gid to the
1088 : * user's "domain users" group. Under certain circumstances
1089 : * (user comes from NT4), this might be a loss of
1090 : * information. But we can not rely on winbind getting the
1091 : * correct info. AD might prohibit winbind looking up that
1092 : * information. */
1093 :
1094 : /* We must always assign the *uid. */
1095 24 : if (!sid_to_uid(user_sid, uid)) {
1096 16 : DEBUG(1, ("winbindd case, sid_to_uid for %s failed\n",
1097 : dom_sid_str_buf(user_sid, &buf)));
1098 16 : result = NT_STATUS_NO_SUCH_USER;
1099 16 : goto done;
1100 : }
1101 :
1102 8 : num_group_sids = 1;
1103 8 : group_sids = talloc_array(tmp_ctx, struct dom_sid, num_group_sids);
1104 8 : if (group_sids == NULL) {
1105 0 : DEBUG(1, ("talloc_array failed\n"));
1106 0 : result = NT_STATUS_NO_MEMORY;
1107 0 : goto done;
1108 : }
1109 :
1110 8 : gids = talloc_array(tmp_ctx, gid_t, num_group_sids);
1111 8 : if (gids == NULL) {
1112 0 : result = NT_STATUS_NO_MEMORY;
1113 0 : goto done;
1114 : }
1115 :
1116 8 : sid_copy(&group_sids[0], user_sid);
1117 8 : sid_split_rid(&group_sids[0], NULL);
1118 8 : sid_append_rid(&group_sids[0], DOMAIN_RID_USERS);
1119 :
1120 8 : if (!sid_to_gid(&group_sids[0], &gids[0])) {
1121 8 : DEBUG(1, ("sid_to_gid(%s) failed\n",
1122 : dom_sid_str_buf(&group_sids[0], &buf)));
1123 8 : goto done;
1124 : }
1125 :
1126 0 : *found_username = NULL;
1127 : }
1128 :
1129 2504 : *gid = gids[0];
1130 :
1131 : /* Add the "Unix Group" SID for each gid to catch mapped groups
1132 : and their Unix equivalent. This is to solve the backwards
1133 : compatibility problem of 'valid users = +ntadmin' where
1134 : ntadmin has been paired with "Domain Admins" in the group
1135 : mapping table. Otherwise smb.conf would need to be changed
1136 : to 'valid user = "Domain Admins"'. --jerry */
1137 :
1138 2504 : num_gids = num_group_sids;
1139 2504 : range_ok = lp_idmap_default_range(&low, &high);
1140 20560 : for ( i=0; i<num_gids; i++ ) {
1141 0 : struct dom_sid unix_group_sid;
1142 :
1143 : /* don't pickup anything managed by Winbind */
1144 18056 : if (range_ok && (gids[i] >= low) && (gids[i] <= high)) {
1145 0 : continue;
1146 : }
1147 :
1148 18056 : gid_to_unix_groups_sid(gids[i], &unix_group_sid);
1149 :
1150 18056 : result = add_sid_to_array_unique(tmp_ctx, &unix_group_sid,
1151 : &group_sids, &num_group_sids);
1152 18056 : if (!NT_STATUS_IS_OK(result)) {
1153 0 : goto done;
1154 : }
1155 : }
1156 :
1157 : /* Ensure we're creating the nt_token on the right context. */
1158 2504 : result = create_local_nt_token(mem_ctx, user_sid,
1159 : is_guest, num_group_sids, group_sids, token);
1160 :
1161 2504 : if (!NT_STATUS_IS_OK(result)) {
1162 968 : goto done;
1163 : }
1164 :
1165 1536 : result = NT_STATUS_OK;
1166 5132 : done:
1167 5132 : TALLOC_FREE(tmp_ctx);
1168 5132 : return result;
1169 : }
1170 :
1171 : /*
1172 : * Create an artificial NT token given just a username. (Initially intended
1173 : * for force user)
1174 : *
1175 : * We go through lookup_name() to avoid problems we had with 'winbind use
1176 : * default domain'.
1177 : *
1178 : * We have 3 cases:
1179 : *
1180 : * unmapped unix users: Go directly to nss to find the user's group.
1181 : *
1182 : * A passdb user: The list of groups is provided by pdb_enum_group_memberships.
1183 : *
1184 : * If the user is provided by winbind, the primary gid is set to "domain
1185 : * users" of the user's domain. For an explanation why this is necessary, see
1186 : * the thread starting at
1187 : * http://lists.samba.org/archive/samba-technical/2006-January/044803.html.
1188 : */
1189 :
1190 310 : NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username,
1191 : bool is_guest,
1192 : uid_t *uid, gid_t *gid,
1193 : char **found_username,
1194 : struct security_token **token)
1195 : {
1196 310 : NTSTATUS result = NT_STATUS_NO_SUCH_USER;
1197 310 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1198 0 : struct dom_sid user_sid;
1199 0 : enum lsa_SidType type;
1200 :
1201 310 : if (!lookup_name_smbconf(tmp_ctx, username, LOOKUP_NAME_ALL,
1202 : NULL, NULL, &user_sid, &type)) {
1203 2 : DEBUG(1, ("lookup_name_smbconf for %s failed\n", username));
1204 2 : goto done;
1205 : }
1206 :
1207 308 : if (type != SID_NAME_USER) {
1208 0 : DEBUG(1, ("%s is a %s, not a user\n", username,
1209 : sid_type_lookup(type)));
1210 0 : goto done;
1211 : }
1212 :
1213 308 : result = create_token_from_sid(mem_ctx, &user_sid, is_guest, uid, gid, found_username, token);
1214 :
1215 308 : if (!NT_STATUS_IS_OK(result)) {
1216 24 : goto done;
1217 : }
1218 :
1219 : /*
1220 : * If result == NT_STATUS_OK then
1221 : * we know we have a valid token. Ensure
1222 : * we also have a valid username to match.
1223 : */
1224 :
1225 284 : if (*found_username == NULL) {
1226 0 : *found_username = talloc_strdup(mem_ctx, username);
1227 0 : if (*found_username == NULL) {
1228 0 : result = NT_STATUS_NO_MEMORY;
1229 : }
1230 : }
1231 :
1232 284 : done:
1233 310 : TALLOC_FREE(tmp_ctx);
1234 310 : return result;
1235 : }
1236 :
1237 : /***************************************************************************
1238 : Build upon create_token_from_sid:
1239 :
1240 : Expensive helper function to figure out whether a user given its sid is
1241 : member of a particular group.
1242 : ***************************************************************************/
1243 :
1244 5709 : bool user_sid_in_group_sid(const struct dom_sid *sid, const struct dom_sid *group_sid)
1245 : {
1246 270 : NTSTATUS status;
1247 270 : uid_t uid;
1248 270 : gid_t gid;
1249 270 : char *found_username;
1250 270 : struct security_token *token;
1251 5709 : bool result = false;
1252 270 : enum lsa_SidType type;
1253 5709 : TALLOC_CTX *mem_ctx = talloc_stackframe();
1254 270 : struct dom_sid_buf buf;
1255 :
1256 5709 : if (!lookup_sid(mem_ctx, sid,
1257 : NULL, NULL, &type)) {
1258 0 : DEBUG(1, ("lookup_sid for %s failed\n",
1259 : dom_sid_str_buf(sid, &buf)));
1260 0 : goto done;
1261 : }
1262 :
1263 5709 : if (type != SID_NAME_USER) {
1264 885 : DEBUG(5, ("%s is a %s, not a user\n",
1265 : dom_sid_str_buf(sid, &buf),
1266 : sid_type_lookup(type)));
1267 885 : goto done;
1268 : }
1269 :
1270 4824 : status = create_token_from_sid(mem_ctx, sid, False,
1271 : &uid, &gid, &found_username,
1272 : &token);
1273 :
1274 4824 : if (!NT_STATUS_IS_OK(status)) {
1275 3572 : DEBUG(10, ("could not create token for %s\n",
1276 : dom_sid_str_buf(sid, &buf)));
1277 3572 : goto done;
1278 : }
1279 :
1280 1252 : result = security_token_has_sid(token, group_sid);
1281 :
1282 5709 : done:
1283 5709 : TALLOC_FREE(mem_ctx);
1284 5709 : return result;
1285 : }
1286 :
1287 : /***************************************************************************
1288 : Build upon create_token_from_username:
1289 :
1290 : Expensive helper function to figure out whether a user given its name is
1291 : member of a particular group.
1292 : ***************************************************************************/
1293 :
1294 40 : bool user_in_group_sid(const char *username, const struct dom_sid *group_sid)
1295 : {
1296 0 : NTSTATUS status;
1297 0 : uid_t uid;
1298 0 : gid_t gid;
1299 0 : char *found_username;
1300 0 : struct security_token *token;
1301 0 : bool result;
1302 40 : TALLOC_CTX *mem_ctx = talloc_stackframe();
1303 :
1304 40 : status = create_token_from_username(mem_ctx, username, False,
1305 : &uid, &gid, &found_username,
1306 : &token);
1307 :
1308 40 : if (!NT_STATUS_IS_OK(status)) {
1309 26 : DEBUG(10, ("could not create token for %s\n", username));
1310 26 : TALLOC_FREE(mem_ctx);
1311 26 : return False;
1312 : }
1313 :
1314 14 : result = security_token_has_sid(token, group_sid);
1315 :
1316 14 : TALLOC_FREE(mem_ctx);
1317 14 : return result;
1318 : }
1319 :
1320 40 : bool user_in_group(const char *username, const char *groupname)
1321 : {
1322 40 : TALLOC_CTX *mem_ctx = talloc_stackframe();
1323 0 : struct dom_sid group_sid;
1324 0 : bool ret;
1325 :
1326 40 : ret = lookup_name(mem_ctx, groupname, LOOKUP_NAME_ALL,
1327 : NULL, NULL, &group_sid, NULL);
1328 40 : TALLOC_FREE(mem_ctx);
1329 :
1330 40 : if (!ret) {
1331 0 : DEBUG(10, ("lookup_name for (%s) failed.\n", groupname));
1332 0 : return False;
1333 : }
1334 :
1335 40 : return user_in_group_sid(username, &group_sid);
1336 : }
1337 :
1338 : /* END */
|