source: trunk/server/source3/auth/auth_util.c@ 953

Last change on this file since 953 was 920, checked in by Silvan Scherrer, 10 years ago

Samba Server: apply latest security patches to trunk

File size: 39.4 KB
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
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
22*/
23
24#include "includes.h"
25#include "auth.h"
26#include "../libcli/auth/libcli_auth.h"
27#include "../lib/crypto/arcfour.h"
28#include "rpc_client/init_lsa.h"
29#include "../libcli/security/security.h"
30#include "../lib/util/util_pw.h"
31#include "lib/winbind_util.h"
32#include "passdb.h"
33#include "../lib/tsocket/tsocket.h"
34
35#undef DBGC_CLASS
36#define DBGC_CLASS DBGC_AUTH
37
38/****************************************************************************
39 Create a UNIX user on demand.
40****************************************************************************/
41
42static int _smb_create_user(const char *domain, const char *unix_username, const char *homedir)
43{
44 TALLOC_CTX *ctx = talloc_tos();
45 char *add_script;
46 int ret;
47
48 add_script = talloc_strdup(ctx, lp_adduser_script());
49 if (!add_script || !*add_script) {
50 return -1;
51 }
52 add_script = talloc_all_string_sub(ctx,
53 add_script,
54 "%u",
55 unix_username);
56 if (!add_script) {
57 return -1;
58 }
59 if (domain) {
60 add_script = talloc_all_string_sub(ctx,
61 add_script,
62 "%D",
63 domain);
64 if (!add_script) {
65 return -1;
66 }
67 }
68 if (homedir) {
69 add_script = talloc_all_string_sub(ctx,
70 add_script,
71 "%H",
72 homedir);
73 if (!add_script) {
74 return -1;
75 }
76 }
77 ret = smbrun(add_script,NULL);
78 flush_pwnam_cache();
79 DEBUG(ret ? 0 : 3,
80 ("smb_create_user: Running the command `%s' gave %d\n",
81 add_script,ret));
82 return ret;
83}
84
85/****************************************************************************
86 Create an auth_usersupplied_data structure after appropriate mapping.
87****************************************************************************/
88
89NTSTATUS make_user_info_map(struct auth_usersupplied_info **user_info,
90 const char *smb_name,
91 const char *client_domain,
92 const char *workstation_name,
93 DATA_BLOB *lm_pwd,
94 DATA_BLOB *nt_pwd,
95 const struct samr_Password *lm_interactive_pwd,
96 const struct samr_Password *nt_interactive_pwd,
97 const char *plaintext,
98 enum auth_password_state password_state)
99{
100 const char *domain;
101 NTSTATUS result;
102 bool was_mapped;
103 char *internal_username = NULL;
104
105 was_mapped = map_username(talloc_tos(), smb_name, &internal_username);
106 if (!internal_username) {
107 return NT_STATUS_NO_MEMORY;
108 }
109
110 DEBUG(5, ("Mapping user [%s]\\[%s] from workstation [%s]\n",
111 client_domain, smb_name, workstation_name));
112
113 domain = client_domain;
114
115 /* If you connect to a Windows domain member using a bogus domain name,
116 * the Windows box will map the BOGUS\user to SAMNAME\user. Thus, if
117 * the Windows box is a DC the name will become DOMAIN\user and be
118 * authenticated against AD, if the Windows box is a member server but
119 * not a DC the name will become WORKSTATION\user. A standalone
120 * non-domain member box will also map to WORKSTATION\user.
121 * This also deals with the client passing in a "" domain */
122
123 if (!is_trusted_domain(domain) &&
124 !strequal(domain, my_sam_name()) &&
125 !strequal(domain, get_global_sam_name()))
126 {
127 if (lp_map_untrusted_to_domain())
128 domain = my_sam_name();
129 else
130 domain = get_global_sam_name();
131 DEBUG(5, ("Mapped domain from [%s] to [%s] for user [%s] from "
132 "workstation [%s]\n",
133 client_domain, domain, smb_name, workstation_name));
134 }
135
136 /* We know that the given domain is trusted (and we are allowing them),
137 * it is our global SAM name, or for legacy behavior it is our
138 * primary domain name */
139
140 result = make_user_info(user_info, smb_name, internal_username,
141 client_domain, domain, workstation_name,
142 lm_pwd, nt_pwd,
143 lm_interactive_pwd, nt_interactive_pwd,
144 plaintext, password_state);
145 if (NT_STATUS_IS_OK(result)) {
146 /* We have tried mapping */
147 (*user_info)->mapped_state = True;
148 /* did we actually map the user to a different name? */
149 (*user_info)->was_mapped = was_mapped;
150 }
151 return result;
152}
153
154/****************************************************************************
155 Create an auth_usersupplied_data, making the DATA_BLOBs here.
156 Decrypt and encrypt the passwords.
157****************************************************************************/
158
159bool make_user_info_netlogon_network(struct auth_usersupplied_info **user_info,
160 const char *smb_name,
161 const char *client_domain,
162 const char *workstation_name,
163 uint32 logon_parameters,
164 const uchar *lm_network_pwd,
165 int lm_pwd_len,
166 const uchar *nt_network_pwd,
167 int nt_pwd_len)
168{
169 bool ret;
170 NTSTATUS status;
171 DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
172 DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
173
174 status = make_user_info_map(user_info,
175 smb_name, client_domain,
176 workstation_name,
177 lm_pwd_len ? &lm_blob : NULL,
178 nt_pwd_len ? &nt_blob : NULL,
179 NULL, NULL, NULL,
180 AUTH_PASSWORD_RESPONSE);
181
182 if (NT_STATUS_IS_OK(status)) {
183 (*user_info)->logon_parameters = logon_parameters;
184 }
185 ret = NT_STATUS_IS_OK(status) ? True : False;
186
187 data_blob_free(&lm_blob);
188 data_blob_free(&nt_blob);
189 return ret;
190}
191
192/****************************************************************************
193 Create an auth_usersupplied_data, making the DATA_BLOBs here.
194 Decrypt and encrypt the passwords.
195****************************************************************************/
196
197bool make_user_info_netlogon_interactive(struct auth_usersupplied_info **user_info,
198 const char *smb_name,
199 const char *client_domain,
200 const char *workstation_name,
201 uint32 logon_parameters,
202 const uchar chal[8],
203 const uchar lm_interactive_pwd[16],
204 const uchar nt_interactive_pwd[16],
205 const uchar *dc_sess_key)
206{
207 struct samr_Password lm_pwd;
208 struct samr_Password nt_pwd;
209 unsigned char local_lm_response[24];
210 unsigned char local_nt_response[24];
211 unsigned char key[16];
212
213 memcpy(key, dc_sess_key, 16);
214
215 if (lm_interactive_pwd)
216 memcpy(lm_pwd.hash, lm_interactive_pwd, sizeof(lm_pwd.hash));
217
218 if (nt_interactive_pwd)
219 memcpy(nt_pwd.hash, nt_interactive_pwd, sizeof(nt_pwd.hash));
220
221#ifdef DEBUG_PASSWORD
222 DEBUG(100,("key:"));
223 dump_data(100, key, sizeof(key));
224
225 DEBUG(100,("lm owf password:"));
226 dump_data(100, lm_pwd.hash, sizeof(lm_pwd.hash));
227
228 DEBUG(100,("nt owf password:"));
229 dump_data(100, nt_pwd.hash, sizeof(nt_pwd.hash));
230#endif
231
232 if (lm_interactive_pwd)
233 arcfour_crypt(lm_pwd.hash, key, sizeof(lm_pwd.hash));
234
235 if (nt_interactive_pwd)
236 arcfour_crypt(nt_pwd.hash, key, sizeof(nt_pwd.hash));
237
238#ifdef DEBUG_PASSWORD
239 DEBUG(100,("decrypt of lm owf password:"));
240 dump_data(100, lm_pwd.hash, sizeof(lm_pwd));
241
242 DEBUG(100,("decrypt of nt owf password:"));
243 dump_data(100, nt_pwd.hash, sizeof(nt_pwd));
244#endif
245
246 if (lm_interactive_pwd)
247 SMBOWFencrypt(lm_pwd.hash, chal,
248 local_lm_response);
249
250 if (nt_interactive_pwd)
251 SMBOWFencrypt(nt_pwd.hash, chal,
252 local_nt_response);
253
254 /* Password info paranoia */
255 ZERO_STRUCT(key);
256
257 {
258 bool ret;
259 NTSTATUS nt_status;
260 DATA_BLOB local_lm_blob;
261 DATA_BLOB local_nt_blob;
262
263 if (lm_interactive_pwd) {
264 local_lm_blob = data_blob(local_lm_response,
265 sizeof(local_lm_response));
266 }
267
268 if (nt_interactive_pwd) {
269 local_nt_blob = data_blob(local_nt_response,
270 sizeof(local_nt_response));
271 }
272
273 nt_status = make_user_info_map(
274 user_info,
275 smb_name, client_domain, workstation_name,
276 lm_interactive_pwd ? &local_lm_blob : NULL,
277 nt_interactive_pwd ? &local_nt_blob : NULL,
278 lm_interactive_pwd ? &lm_pwd : NULL,
279 nt_interactive_pwd ? &nt_pwd : NULL,
280 NULL, AUTH_PASSWORD_HASH);
281
282 if (NT_STATUS_IS_OK(nt_status)) {
283 (*user_info)->logon_parameters = logon_parameters;
284 }
285
286 ret = NT_STATUS_IS_OK(nt_status) ? True : False;
287 data_blob_free(&local_lm_blob);
288 data_blob_free(&local_nt_blob);
289 return ret;
290 }
291}
292
293
294/****************************************************************************
295 Create an auth_usersupplied_data structure
296****************************************************************************/
297
298bool make_user_info_for_reply(struct auth_usersupplied_info **user_info,
299 const char *smb_name,
300 const char *client_domain,
301 const uint8 chal[8],
302 DATA_BLOB plaintext_password)
303{
304
305 DATA_BLOB local_lm_blob;
306 DATA_BLOB local_nt_blob;
307 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
308 char *plaintext_password_string;
309 /*
310 * Not encrypted - do so.
311 */
312
313 DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted "
314 "format.\n"));
315 if (plaintext_password.data && plaintext_password.length) {
316 unsigned char local_lm_response[24];
317
318#ifdef DEBUG_PASSWORD
319 DEBUG(10,("Unencrypted password (len %d):\n",
320 (int)plaintext_password.length));
321 dump_data(100, plaintext_password.data,
322 plaintext_password.length);
323#endif
324
325 SMBencrypt( (const char *)plaintext_password.data,
326 (const uchar*)chal, local_lm_response);
327 local_lm_blob = data_blob(local_lm_response, 24);
328
329 /* We can't do an NT hash here, as the password needs to be
330 case insensitive */
331 local_nt_blob = data_blob_null;
332 } else {
333 local_lm_blob = data_blob_null;
334 local_nt_blob = data_blob_null;
335 }
336
337 plaintext_password_string = talloc_strndup(talloc_tos(),
338 (const char *)plaintext_password.data,
339 plaintext_password.length);
340 if (!plaintext_password_string) {
341 return False;
342 }
343
344 ret = make_user_info_map(
345 user_info, smb_name, client_domain,
346 get_remote_machine_name(),
347 local_lm_blob.data ? &local_lm_blob : NULL,
348 local_nt_blob.data ? &local_nt_blob : NULL,
349 NULL, NULL,
350 plaintext_password_string,
351 AUTH_PASSWORD_PLAIN);
352
353 if (plaintext_password_string) {
354 memset(plaintext_password_string, '\0', strlen(plaintext_password_string));
355 talloc_free(plaintext_password_string);
356 }
357
358 data_blob_free(&local_lm_blob);
359 return NT_STATUS_IS_OK(ret) ? True : False;
360}
361
362/****************************************************************************
363 Create an auth_usersupplied_data structure
364****************************************************************************/
365
366NTSTATUS make_user_info_for_reply_enc(struct auth_usersupplied_info **user_info,
367 const char *smb_name,
368 const char *client_domain,
369 DATA_BLOB lm_resp, DATA_BLOB nt_resp)
370{
371 bool allow_raw = lp_raw_ntlmv2_auth();
372
373 if (!allow_raw && nt_resp.length >= 48) {
374 /*
375 * NTLMv2_RESPONSE has at least 48 bytes
376 * and should only be supported via NTLMSSP.
377 */
378 DEBUG(2,("Rejecting raw NTLMv2 authentication with "
379 "user [%s\\%s]\n",
380 client_domain, smb_name));
381 return NT_STATUS_INVALID_PARAMETER;
382 }
383
384 return make_user_info_map(user_info, smb_name,
385 client_domain,
386 get_remote_machine_name(),
387 lm_resp.data && (lm_resp.length > 0) ? &lm_resp : NULL,
388 nt_resp.data && (nt_resp.length > 0) ? &nt_resp : NULL,
389 NULL, NULL, NULL,
390 AUTH_PASSWORD_RESPONSE);
391}
392
393/****************************************************************************
394 Create a guest user_info blob, for anonymous authenticaion.
395****************************************************************************/
396
397bool make_user_info_guest(struct auth_usersupplied_info **user_info)
398{
399 NTSTATUS nt_status;
400
401 nt_status = make_user_info(user_info,
402 "","",
403 "","",
404 "",
405 NULL, NULL,
406 NULL, NULL,
407 NULL,
408 AUTH_PASSWORD_RESPONSE);
409
410 return NT_STATUS_IS_OK(nt_status) ? True : False;
411}
412
413static NTSTATUS log_nt_token(struct security_token *token)
414{
415 TALLOC_CTX *frame = talloc_stackframe();
416 char *command;
417 char *group_sidstr;
418 size_t i;
419
420 if ((lp_log_nt_token_command() == NULL) ||
421 (strlen(lp_log_nt_token_command()) == 0)) {
422 TALLOC_FREE(frame);
423 return NT_STATUS_OK;
424 }
425
426 group_sidstr = talloc_strdup(frame, "");
427 for (i=1; i<token->num_sids; i++) {
428 group_sidstr = talloc_asprintf(
429 frame, "%s %s", group_sidstr,
430 sid_string_talloc(frame, &token->sids[i]));
431 }
432
433 command = talloc_string_sub(
434 frame, lp_log_nt_token_command(),
435 "%s", sid_string_talloc(frame, &token->sids[0]));
436 command = talloc_string_sub(frame, command, "%t", group_sidstr);
437
438 if (command == NULL) {
439 TALLOC_FREE(frame);
440 return NT_STATUS_NO_MEMORY;
441 }
442
443 DEBUG(8, ("running command: [%s]\n", command));
444 if (smbrun(command, NULL) != 0) {
445 DEBUG(0, ("Could not log NT token\n"));
446 TALLOC_FREE(frame);
447 return NT_STATUS_ACCESS_DENIED;
448 }
449
450 TALLOC_FREE(frame);
451 return NT_STATUS_OK;
452}
453
454/*
455 * Create the token to use from server_info->info3 and
456 * server_info->sids (the info3/sam groups). Find the unix gids.
457 */
458
459NTSTATUS create_local_token(struct auth_serversupplied_info *server_info)
460{
461 struct security_token *t;
462 NTSTATUS status;
463 size_t i;
464 struct dom_sid tmp_sid;
465 struct wbcUnixId *ids;
466
467 /*
468 * If winbind is not around, we can not make much use of the SIDs the
469 * domain controller provided us with. Likewise if the user name was
470 * mapped to some local unix user.
471 */
472
473 if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) ||
474 (server_info->nss_token)) {
475 status = create_token_from_username(server_info,
476 server_info->unix_name,
477 server_info->guest,
478 &server_info->utok.uid,
479 &server_info->utok.gid,
480 &server_info->unix_name,
481 &server_info->security_token);
482
483 } else {
484 status = create_local_nt_token_from_info3(server_info,
485 server_info->guest,
486 server_info->info3,
487 &server_info->extra,
488 &server_info->security_token);
489 }
490
491 if (!NT_STATUS_IS_OK(status)) {
492 return status;
493 }
494
495 /* Convert the SIDs to gids. */
496
497 server_info->utok.ngroups = 0;
498 server_info->utok.groups = NULL;
499
500 t = server_info->security_token;
501
502 ids = TALLOC_ARRAY(talloc_tos(), struct wbcUnixId,
503 t->num_sids);
504 if (ids == NULL) {
505 return NT_STATUS_NO_MEMORY;
506 }
507
508 if (!sids_to_unix_ids(t->sids, t->num_sids, ids)) {
509 TALLOC_FREE(ids);
510 return NT_STATUS_NO_MEMORY;
511 }
512
513 /* Start at index 1, where the groups start. */
514
515 for (i=1; i<t->num_sids; i++) {
516
517 if (ids[i].type != WBC_ID_TYPE_GID) {
518 DEBUG(10, ("Could not convert SID %s to gid, "
519 "ignoring it\n",
520 sid_string_dbg(&t->sids[i])));
521 continue;
522 }
523 if (!add_gid_to_array_unique(server_info, ids[i].id.gid,
524 &server_info->utok.groups,
525 &server_info->utok.ngroups)) {
526 return NT_STATUS_NO_MEMORY;
527 }
528 }
529
530 /*
531 * Add the "Unix Group" SID for each gid to catch mapped groups
532 * and their Unix equivalent. This is to solve the backwards
533 * compatibility problem of 'valid users = +ntadmin' where
534 * ntadmin has been paired with "Domain Admins" in the group
535 * mapping table. Otherwise smb.conf would need to be changed
536 * to 'valid user = "Domain Admins"'. --jerry
537 *
538 * For consistency we also add the "Unix User" SID,
539 * so that the complete unix token is represented within
540 * the nt token.
541 */
542
543 uid_to_unix_users_sid(server_info->utok.uid, &tmp_sid);
544
545 add_sid_to_array_unique(server_info->security_token, &tmp_sid,
546 &server_info->security_token->sids,
547 &server_info->security_token->num_sids);
548
549 for ( i=0; i<server_info->utok.ngroups; i++ ) {
550 gid_to_unix_groups_sid(server_info->utok.groups[i], &tmp_sid);
551 add_sid_to_array_unique(server_info->security_token, &tmp_sid,
552 &server_info->security_token->sids,
553 &server_info->security_token->num_sids);
554 }
555
556 security_token_debug(DBGC_AUTH, 10, server_info->security_token);
557 debug_unix_user_token(DBGC_AUTH, 10,
558 server_info->utok.uid,
559 server_info->utok.gid,
560 server_info->utok.ngroups,
561 server_info->utok.groups);
562
563 status = log_nt_token(server_info->security_token);
564 return status;
565}
566
567/***************************************************************************
568 Make (and fill) a server_info struct from a 'struct passwd' by conversion
569 to a struct samu
570***************************************************************************/
571
572NTSTATUS make_server_info_pw(struct auth_serversupplied_info **server_info,
573 char *unix_username,
574 struct passwd *pwd)
575{
576 NTSTATUS status;
577 struct samu *sampass = NULL;
578 char *qualified_name = NULL;
579 TALLOC_CTX *mem_ctx = NULL;
580 struct dom_sid u_sid;
581 enum lsa_SidType type;
582 struct auth_serversupplied_info *result;
583
584 /*
585 * The SID returned in server_info->sam_account is based
586 * on our SAM sid even though for a pure UNIX account this should
587 * not be the case as it doesn't really exist in the SAM db.
588 * This causes lookups on "[in]valid users" to fail as they
589 * will lookup this name as a "Unix User" SID to check against
590 * the user token. Fix this by adding the "Unix User"\unix_username
591 * SID to the sid array. The correct fix should probably be
592 * changing the server_info->sam_account user SID to be a
593 * S-1-22 Unix SID, but this might break old configs where
594 * plaintext passwords were used with no SAM backend.
595 */
596
597 mem_ctx = talloc_init("make_server_info_pw_tmp");
598 if (!mem_ctx) {
599 return NT_STATUS_NO_MEMORY;
600 }
601
602 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
603 unix_users_domain_name(),
604 unix_username );
605 if (!qualified_name) {
606 TALLOC_FREE(mem_ctx);
607 return NT_STATUS_NO_MEMORY;
608 }
609
610 if (!lookup_name(mem_ctx, qualified_name, LOOKUP_NAME_ALL,
611 NULL, NULL,
612 &u_sid, &type)) {
613 TALLOC_FREE(mem_ctx);
614 return NT_STATUS_NO_SUCH_USER;
615 }
616
617 TALLOC_FREE(mem_ctx);
618
619 if (type != SID_NAME_USER) {
620 return NT_STATUS_NO_SUCH_USER;
621 }
622
623 if ( !(sampass = samu_new( NULL )) ) {
624 return NT_STATUS_NO_MEMORY;
625 }
626
627 status = samu_set_unix( sampass, pwd );
628 if (!NT_STATUS_IS_OK(status)) {
629 return status;
630 }
631
632 /* In pathological cases the above call can set the account
633 * name to the DOMAIN\username form. Reset the account name
634 * using unix_username */
635 pdb_set_username(sampass, unix_username, PDB_SET);
636
637 /* set the user sid to be the calculated u_sid */
638 pdb_set_user_sid(sampass, &u_sid, PDB_SET);
639
640 result = make_server_info(NULL);
641 if (result == NULL) {
642 TALLOC_FREE(sampass);
643 return NT_STATUS_NO_MEMORY;
644 }
645
646 status = samu_to_SamInfo3(result, sampass, global_myname(),
647 &result->info3, &result->extra);
648 TALLOC_FREE(sampass);
649 if (!NT_STATUS_IS_OK(status)) {
650 DEBUG(10, ("Failed to convert samu to info3: %s\n",
651 nt_errstr(status)));
652 TALLOC_FREE(result);
653 return status;
654 }
655
656 result->unix_name = talloc_strdup(result, unix_username);
657 result->sanitized_username = sanitize_username(result, unix_username);
658
659 if ((result->unix_name == NULL)
660 || (result->sanitized_username == NULL)) {
661 TALLOC_FREE(result);
662 return NT_STATUS_NO_MEMORY;
663 }
664
665 result->utok.uid = pwd->pw_uid;
666 result->utok.gid = pwd->pw_gid;
667
668 *server_info = result;
669
670 return NT_STATUS_OK;
671}
672
673static NTSTATUS get_system_info3(TALLOC_CTX *mem_ctx,
674 struct passwd *pwd,
675 struct netr_SamInfo3 *info3)
676{
677 struct dom_sid domain_sid;
678 const char *tmp;
679
680 /* Set account name */
681 tmp = talloc_strdup(mem_ctx, pwd->pw_name);
682 if (tmp == NULL) {
683 return NT_STATUS_NO_MEMORY;
684 }
685 init_lsa_String(&info3->base.account_name, tmp);
686
687 /* Set domain name */
688 tmp = talloc_strdup(mem_ctx, get_global_sam_name());
689 if (tmp == NULL) {
690 return NT_STATUS_NO_MEMORY;
691 }
692 init_lsa_StringLarge(&info3->base.domain, tmp);
693
694 /* Domain sid */
695 sid_copy(&domain_sid, get_global_sam_sid());
696
697 info3->base.domain_sid = dom_sid_dup(mem_ctx, &domain_sid);
698 if (info3->base.domain_sid == NULL) {
699 return NT_STATUS_NO_MEMORY;
700 }
701
702 /* Admin rid */
703 info3->base.rid = DOMAIN_RID_ADMINISTRATOR;
704
705 /* Primary gid */
706 info3->base.primary_gid = BUILTIN_RID_ADMINISTRATORS;
707
708 return NT_STATUS_OK;
709}
710
711static NTSTATUS get_guest_info3(TALLOC_CTX *mem_ctx,
712 struct netr_SamInfo3 *info3)
713{
714 const char *guest_account = lp_guestaccount();
715 struct dom_sid domain_sid;
716 struct passwd *pwd;
717 const char *tmp;
718
719 pwd = Get_Pwnam_alloc(mem_ctx, guest_account);
720 if (pwd == NULL) {
721 DEBUG(0,("SamInfo3_for_guest: Unable to locate guest "
722 "account [%s]!\n", guest_account));
723 return NT_STATUS_NO_SUCH_USER;
724 }
725
726 /* Set acount name */
727 tmp = talloc_strdup(mem_ctx, pwd->pw_name);
728 if (tmp == NULL) {
729 return NT_STATUS_NO_MEMORY;
730 }
731 init_lsa_String(&info3->base.account_name, tmp);
732
733 /* Set domain name */
734 tmp = talloc_strdup(mem_ctx, get_global_sam_name());
735 if (tmp == NULL) {
736 return NT_STATUS_NO_MEMORY;
737 }
738 init_lsa_StringLarge(&info3->base.domain, tmp);
739
740 /* Domain sid */
741 sid_copy(&domain_sid, get_global_sam_sid());
742
743 info3->base.domain_sid = dom_sid_dup(mem_ctx, &domain_sid);
744 if (info3->base.domain_sid == NULL) {
745 return NT_STATUS_NO_MEMORY;
746 }
747
748 /* Guest rid */
749 info3->base.rid = DOMAIN_RID_GUEST;
750
751 /* Primary gid */
752 info3->base.primary_gid = DOMAIN_RID_GUESTS;
753
754 TALLOC_FREE(pwd);
755 return NT_STATUS_OK;
756}
757
758/***************************************************************************
759 Make (and fill) a user_info struct for a guest login.
760 This *must* succeed for smbd to start. If there is no mapping entry for
761 the guest gid, then create one.
762***************************************************************************/
763
764static NTSTATUS make_new_server_info_guest(struct auth_serversupplied_info **server_info)
765{
766 static const char zeros[16] = {0};
767 const char *guest_account = lp_guestaccount();
768 const char *domain = global_myname();
769 struct netr_SamInfo3 info3;
770 TALLOC_CTX *tmp_ctx;
771 NTSTATUS status;
772 fstring tmp;
773
774 tmp_ctx = talloc_stackframe();
775 if (tmp_ctx == NULL) {
776 return NT_STATUS_NO_MEMORY;
777 }
778
779 ZERO_STRUCT(info3);
780
781 status = get_guest_info3(tmp_ctx, &info3);
782 if (!NT_STATUS_IS_OK(status)) {
783 goto done;
784 }
785
786 status = make_server_info_info3(tmp_ctx,
787 guest_account,
788 domain,
789 server_info,
790 &info3);
791 if (!NT_STATUS_IS_OK(status)) {
792 goto done;
793 }
794
795 (*server_info)->guest = True;
796
797 status = create_local_token(*server_info);
798 if (!NT_STATUS_IS_OK(status)) {
799 DEBUG(10, ("create_local_token failed: %s\n",
800 nt_errstr(status)));
801 goto done;
802 }
803
804 /* annoying, but the Guest really does have a session key, and it is
805 all zeros! */
806 (*server_info)->user_session_key = data_blob(zeros, sizeof(zeros));
807 (*server_info)->lm_session_key = data_blob(zeros, sizeof(zeros));
808
809 alpha_strcpy(tmp, (*server_info)->info3->base.account_name.string,
810 ". _-$", sizeof(tmp));
811 (*server_info)->sanitized_username = talloc_strdup(*server_info, tmp);
812
813 status = NT_STATUS_OK;
814done:
815 TALLOC_FREE(tmp_ctx);
816 return status;
817}
818
819/****************************************************************************
820 Fake a auth_session_info just from a username (as a
821 session_info structure, with create_local_token() already called on
822 it.
823****************************************************************************/
824
825static NTSTATUS make_system_session_info_from_pw(TALLOC_CTX *mem_ctx,
826 struct passwd *pwd,
827 struct auth_serversupplied_info **server_info)
828{
829 const char *domain = global_myname();
830 struct netr_SamInfo3 info3;
831 TALLOC_CTX *tmp_ctx;
832 NTSTATUS status;
833
834 tmp_ctx = talloc_stackframe();
835 if (tmp_ctx == NULL) {
836 return NT_STATUS_NO_MEMORY;
837 }
838
839 ZERO_STRUCT(info3);
840
841 status = get_system_info3(tmp_ctx, pwd, &info3);
842 if (!NT_STATUS_IS_OK(status)) {
843 DEBUG(0, ("Failed creating system info3 with %s\n",
844 nt_errstr(status)));
845 goto done;
846 }
847
848 status = make_server_info_info3(mem_ctx,
849 pwd->pw_name,
850 domain,
851 server_info,
852 &info3);
853 if (!NT_STATUS_IS_OK(status)) {
854 DEBUG(0, ("make_server_info_info3 failed with %s\n",
855 nt_errstr(status)));
856 goto done;
857 }
858
859 (*server_info)->nss_token = true;
860
861 /* Now turn the server_info into a session_info with the full token etc */
862 status = create_local_token(*server_info);
863 if (!NT_STATUS_IS_OK(status)) {
864 DEBUG(0, ("create_local_token failed: %s\n",
865 nt_errstr(status)));
866 goto done;
867 }
868
869 status = NT_STATUS_OK;
870done:
871 TALLOC_FREE(tmp_ctx);
872 return status;
873}
874
875/***************************************************************************
876 Make (and fill) a auth_session_info struct for a system user login.
877 This *must* succeed for smbd to start.
878***************************************************************************/
879
880static NTSTATUS make_new_session_info_system(TALLOC_CTX *mem_ctx,
881 struct auth_serversupplied_info **session_info)
882{
883 struct passwd *pwd;
884 NTSTATUS status;
885
886 pwd = getpwuid_alloc(mem_ctx, sec_initial_uid());
887 if (pwd == NULL) {
888 return NT_STATUS_NO_SUCH_USER;
889 }
890
891 status = make_system_session_info_from_pw(mem_ctx,
892 pwd,
893 session_info);
894 TALLOC_FREE(pwd);
895 if (!NT_STATUS_IS_OK(status)) {
896 return status;
897 }
898
899 (*session_info)->system = true;
900
901 status = add_sid_to_array_unique((*session_info)->security_token->sids,
902 &global_sid_System,
903 &(*session_info)->security_token->sids,
904 &(*session_info)->security_token->num_sids);
905 if (!NT_STATUS_IS_OK(status)) {
906 TALLOC_FREE((*session_info));
907 return status;
908 }
909
910 return NT_STATUS_OK;
911}
912
913/****************************************************************************
914 Fake a auth_serversupplied_info just from a username
915****************************************************************************/
916
917NTSTATUS make_serverinfo_from_username(TALLOC_CTX *mem_ctx,
918 const char *username,
919 bool use_guest_token,
920 bool is_guest,
921 struct auth_serversupplied_info **presult)
922{
923 struct auth_serversupplied_info *result;
924 struct passwd *pwd;
925 NTSTATUS status;
926
927 pwd = Get_Pwnam_alloc(talloc_tos(), username);
928 if (pwd == NULL) {
929 return NT_STATUS_NO_SUCH_USER;
930 }
931
932 status = make_server_info_pw(&result, pwd->pw_name, pwd);
933
934 TALLOC_FREE(pwd);
935
936 if (!NT_STATUS_IS_OK(status)) {
937 return status;
938 }
939
940 result->nss_token = true;
941 result->guest = is_guest;
942
943 if (use_guest_token) {
944 status = make_server_info_guest(mem_ctx, &result);
945 } else {
946 status = create_local_token(result);
947 }
948
949 if (!NT_STATUS_IS_OK(status)) {
950 TALLOC_FREE(result);
951 return status;
952 }
953
954 *presult = talloc_steal(mem_ctx, result);
955 return NT_STATUS_OK;
956}
957
958
959struct auth_serversupplied_info *copy_serverinfo(TALLOC_CTX *mem_ctx,
960 const struct auth_serversupplied_info *src)
961{
962 struct auth_serversupplied_info *dst;
963
964 dst = make_server_info(mem_ctx);
965 if (dst == NULL) {
966 return NULL;
967 }
968
969 dst->guest = src->guest;
970 dst->system = src->system;
971 dst->utok.uid = src->utok.uid;
972 dst->utok.gid = src->utok.gid;
973 dst->utok.ngroups = src->utok.ngroups;
974 if (src->utok.ngroups != 0) {
975 dst->utok.groups = (gid_t *)TALLOC_MEMDUP(
976 dst, src->utok.groups,
977 sizeof(gid_t)*dst->utok.ngroups);
978 } else {
979 dst->utok.groups = NULL;
980 }
981
982 if (src->security_token) {
983 dst->security_token = dup_nt_token(dst, src->security_token);
984 if (!dst->security_token) {
985 TALLOC_FREE(dst);
986 return NULL;
987 }
988 }
989
990 dst->user_session_key = data_blob_talloc( dst, src->user_session_key.data,
991 src->user_session_key.length);
992
993 dst->lm_session_key = data_blob_talloc(dst, src->lm_session_key.data,
994 src->lm_session_key.length);
995
996 dst->info3 = copy_netr_SamInfo3(dst, src->info3);
997 if (!dst->info3) {
998 TALLOC_FREE(dst);
999 return NULL;
1000 }
1001 dst->extra = src->extra;
1002
1003 dst->unix_name = talloc_strdup(dst, src->unix_name);
1004 if (!dst->unix_name) {
1005 TALLOC_FREE(dst);
1006 return NULL;
1007 }
1008
1009 dst->sanitized_username = talloc_strdup(dst, src->sanitized_username);
1010 if (!dst->sanitized_username) {
1011 TALLOC_FREE(dst);
1012 return NULL;
1013 }
1014
1015 return dst;
1016}
1017
1018/*
1019 * Set a new session key. Used in the rpc server where we have to override the
1020 * SMB level session key with SystemLibraryDTC
1021 */
1022
1023bool session_info_set_session_key(struct auth_serversupplied_info *info,
1024 DATA_BLOB session_key)
1025{
1026 TALLOC_FREE(info->user_session_key.data);
1027
1028 info->user_session_key = data_blob_talloc(
1029 info, session_key.data, session_key.length);
1030
1031 return (info->user_session_key.data != NULL);
1032}
1033
1034static struct auth_serversupplied_info *guest_info = NULL;
1035
1036bool init_guest_info(void)
1037{
1038 if (guest_info != NULL)
1039 return True;
1040
1041 return NT_STATUS_IS_OK(make_new_server_info_guest(&guest_info));
1042}
1043
1044NTSTATUS make_server_info_guest(TALLOC_CTX *mem_ctx,
1045 struct auth_serversupplied_info **server_info)
1046{
1047 *server_info = copy_serverinfo(mem_ctx, guest_info);
1048 return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1049}
1050
1051static struct auth_serversupplied_info *system_info = NULL;
1052
1053NTSTATUS init_system_info(void)
1054{
1055 if (system_info != NULL)
1056 return NT_STATUS_OK;
1057
1058 return make_new_session_info_system(NULL, &system_info);
1059}
1060
1061NTSTATUS make_session_info_system(TALLOC_CTX *mem_ctx,
1062 struct auth_serversupplied_info **session_info)
1063{
1064 if (system_info == NULL) return NT_STATUS_UNSUCCESSFUL;
1065 *session_info = copy_serverinfo(mem_ctx, system_info);
1066 return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1067}
1068
1069const struct auth_serversupplied_info *get_session_info_system(void)
1070{
1071 return system_info;
1072}
1073
1074bool copy_current_user(struct current_user *dst, struct current_user *src)
1075{
1076 gid_t *groups;
1077 struct security_token *nt_token;
1078
1079 groups = (gid_t *)memdup(src->ut.groups,
1080 sizeof(gid_t) * src->ut.ngroups);
1081 if ((src->ut.ngroups != 0) && (groups == NULL)) {
1082 return False;
1083 }
1084
1085 nt_token = dup_nt_token(NULL, src->nt_user_token);
1086 if (nt_token == NULL) {
1087 SAFE_FREE(groups);
1088 return False;
1089 }
1090
1091 dst->conn = src->conn;
1092 dst->vuid = src->vuid;
1093 dst->ut.uid = src->ut.uid;
1094 dst->ut.gid = src->ut.gid;
1095 dst->ut.ngroups = src->ut.ngroups;
1096 dst->ut.groups = groups;
1097 dst->nt_user_token = nt_token;
1098 return True;
1099}
1100
1101/***************************************************************************
1102 Purely internal function for make_server_info_info3
1103***************************************************************************/
1104
1105static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain,
1106 const char *username, char **found_username,
1107 struct passwd **pwd,
1108 bool *username_was_mapped)
1109{
1110 char *orig_dom_user = NULL;
1111 char *dom_user = NULL;
1112 char *lower_username = NULL;
1113 char *real_username = NULL;
1114 struct passwd *passwd;
1115
1116 lower_username = talloc_strdup(mem_ctx, username);
1117 if (!lower_username) {
1118 return NT_STATUS_NO_MEMORY;
1119 }
1120 strlower_m( lower_username );
1121
1122 orig_dom_user = talloc_asprintf(mem_ctx,
1123 "%s%c%s",
1124 domain,
1125 *lp_winbind_separator(),
1126 lower_username);
1127 if (!orig_dom_user) {
1128 return NT_STATUS_NO_MEMORY;
1129 }
1130
1131 /* Get the passwd struct. Try to create the account if necessary. */
1132
1133 *username_was_mapped = map_username(mem_ctx, orig_dom_user, &dom_user);
1134 if (!dom_user) {
1135 return NT_STATUS_NO_MEMORY;
1136 }
1137
1138 passwd = smb_getpwnam(mem_ctx, dom_user, &real_username, True );
1139 if (!passwd) {
1140 DEBUG(3, ("Failed to find authenticated user %s via "
1141 "getpwnam(), denying access.\n", dom_user));
1142 return NT_STATUS_NO_SUCH_USER;
1143 }
1144
1145 if (!real_username) {
1146 return NT_STATUS_NO_MEMORY;
1147 }
1148
1149 *pwd = passwd;
1150
1151 /* This is pointless -- there is no suport for differing
1152 unix and windows names. Make sure to always store the
1153 one we actually looked up and succeeded. Have I mentioned
1154 why I hate the 'winbind use default domain' parameter?
1155 --jerry */
1156
1157 *found_username = talloc_strdup( mem_ctx, real_username );
1158
1159 return NT_STATUS_OK;
1160}
1161
1162/****************************************************************************
1163 Wrapper to allow the getpwnam() call to strip the domain name and
1164 try again in case a local UNIX user is already there. Also run through
1165 the username if we fallback to the username only.
1166 ****************************************************************************/
1167
1168struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, const char *domuser,
1169 char **p_save_username, bool create )
1170{
1171 struct passwd *pw = NULL;
1172 char *p = NULL;
1173 char *username = NULL;
1174
1175 /* we only save a copy of the username it has been mangled
1176 by winbindd use default domain */
1177 *p_save_username = NULL;
1178
1179 /* don't call map_username() here since it has to be done higher
1180 up the stack so we don't call it multiple times */
1181
1182 username = talloc_strdup(mem_ctx, domuser);
1183 if (!username) {
1184 return NULL;
1185 }
1186
1187 p = strchr_m( username, *lp_winbind_separator() );
1188
1189 /* code for a DOMAIN\user string */
1190
1191 if ( p ) {
1192 pw = Get_Pwnam_alloc( mem_ctx, domuser );
1193 if ( pw ) {
1194 /* make sure we get the case of the username correct */
1195 /* work around 'winbind use default domain = yes' */
1196
1197 if ( lp_winbind_use_default_domain() &&
1198 !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
1199 char *domain;
1200
1201 /* split the domain and username into 2 strings */
1202 *p = '\0';
1203 domain = username;
1204
1205 *p_save_username = talloc_asprintf(mem_ctx,
1206 "%s%c%s",
1207 domain,
1208 *lp_winbind_separator(),
1209 pw->pw_name);
1210 if (!*p_save_username) {
1211 TALLOC_FREE(pw);
1212 return NULL;
1213 }
1214 } else {
1215 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1216 }
1217
1218 /* whew -- done! */
1219 return pw;
1220 }
1221
1222 /* setup for lookup of just the username */
1223 /* remember that p and username are overlapping memory */
1224
1225 p++;
1226 username = talloc_strdup(mem_ctx, p);
1227 if (!username) {
1228 return NULL;
1229 }
1230 }
1231
1232 /* just lookup a plain username */
1233
1234 pw = Get_Pwnam_alloc(mem_ctx, username);
1235
1236 /* Create local user if requested but only if winbindd
1237 is not running. We need to protect against cases
1238 where winbindd is failing and then prematurely
1239 creating users in /etc/passwd */
1240
1241 if ( !pw && create && !winbind_ping() ) {
1242 /* Don't add a machine account. */
1243 if (username[strlen(username)-1] == '$')
1244 return NULL;
1245
1246 _smb_create_user(NULL, username, NULL);
1247 pw = Get_Pwnam_alloc(mem_ctx, username);
1248 }
1249
1250 /* one last check for a valid passwd struct */
1251
1252 if (pw) {
1253 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1254 }
1255 return pw;
1256}
1257
1258/***************************************************************************
1259 Make a server_info struct from the info3 returned by a domain logon
1260***************************************************************************/
1261
1262NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
1263 const char *sent_nt_username,
1264 const char *domain,
1265 struct auth_serversupplied_info **server_info,
1266 struct netr_SamInfo3 *info3)
1267{
1268 static const char zeros[16] = {0, };
1269
1270 NTSTATUS nt_status = NT_STATUS_OK;
1271 char *found_username = NULL;
1272 const char *nt_domain;
1273 const char *nt_username;
1274 struct dom_sid user_sid;
1275 struct dom_sid group_sid;
1276 bool username_was_mapped;
1277 struct passwd *pwd;
1278 struct auth_serversupplied_info *result;
1279
1280 /*
1281 Here is where we should check the list of
1282 trusted domains, and verify that the SID
1283 matches.
1284 */
1285
1286 if (!sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid)) {
1287 return NT_STATUS_INVALID_PARAMETER;
1288 }
1289
1290 if (!sid_compose(&group_sid, info3->base.domain_sid,
1291 info3->base.primary_gid)) {
1292 return NT_STATUS_INVALID_PARAMETER;
1293 }
1294
1295 nt_username = talloc_strdup(mem_ctx, info3->base.account_name.string);
1296 if (!nt_username) {
1297 /* If the server didn't give us one, just use the one we sent
1298 * them */
1299 nt_username = sent_nt_username;
1300 }
1301
1302 nt_domain = talloc_strdup(mem_ctx, info3->base.domain.string);
1303 if (!nt_domain) {
1304 /* If the server didn't give us one, just use the one we sent
1305 * them */
1306 nt_domain = domain;
1307 }
1308
1309 /* If getpwnam() fails try the add user script (2.2.x behavior).
1310
1311 We use the _unmapped_ username here in an attempt to provide
1312 consistent username mapping behavior between kerberos and NTLM[SSP]
1313 authentication in domain mode security. I.E. Username mapping
1314 should be applied to the fully qualified username
1315 (e.g. DOMAIN\user) and not just the login name. Yes this means we
1316 called map_username() unnecessarily in make_user_info_map() but
1317 that is how the current code is designed. Making the change here
1318 is the least disruptive place. -- jerry */
1319
1320 /* this call will try to create the user if necessary */
1321
1322 nt_status = check_account(mem_ctx, nt_domain, sent_nt_username,
1323 &found_username, &pwd,
1324 &username_was_mapped);
1325
1326 if (!NT_STATUS_IS_OK(nt_status)) {
1327 return nt_status;
1328 }
1329
1330 result = make_server_info(NULL);
1331 if (result == NULL) {
1332 DEBUG(4, ("make_server_info failed!\n"));
1333 return NT_STATUS_NO_MEMORY;
1334 }
1335
1336 result->unix_name = talloc_strdup(result, found_username);
1337
1338 result->sanitized_username = sanitize_username(result,
1339 result->unix_name);
1340 if (result->sanitized_username == NULL) {
1341 TALLOC_FREE(result);
1342 return NT_STATUS_NO_MEMORY;
1343 }
1344
1345 /* copy in the info3 */
1346 result->info3 = copy_netr_SamInfo3(result, info3);
1347 if (result->info3 == NULL) {
1348 TALLOC_FREE(result);
1349 return NT_STATUS_NO_MEMORY;
1350 }
1351
1352 /* Fill in the unix info we found on the way */
1353
1354 result->utok.uid = pwd->pw_uid;
1355 result->utok.gid = pwd->pw_gid;
1356
1357 /* ensure we are never given NULL session keys */
1358
1359 if (memcmp(info3->base.key.key, zeros, sizeof(zeros)) == 0) {
1360 result->user_session_key = data_blob_null;
1361 } else {
1362 result->user_session_key = data_blob_talloc(
1363 result, info3->base.key.key,
1364 sizeof(info3->base.key.key));
1365 }
1366
1367 if (memcmp(info3->base.LMSessKey.key, zeros, 8) == 0) {
1368 result->lm_session_key = data_blob_null;
1369 } else {
1370 result->lm_session_key = data_blob_talloc(
1371 result, info3->base.LMSessKey.key,
1372 sizeof(info3->base.LMSessKey.key));
1373 }
1374
1375 result->nss_token |= username_was_mapped;
1376
1377 *server_info = result;
1378
1379 return NT_STATUS_OK;
1380}
1381
1382/*****************************************************************************
1383 Make a server_info struct from the wbcAuthUserInfo returned by a domain logon
1384******************************************************************************/
1385
1386NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx,
1387 const char *sent_nt_username,
1388 const char *domain,
1389 const struct wbcAuthUserInfo *info,
1390 struct auth_serversupplied_info **server_info)
1391{
1392 struct netr_SamInfo3 *info3;
1393
1394 info3 = wbcAuthUserInfo_to_netr_SamInfo3(mem_ctx, info);
1395 if (!info3) {
1396 return NT_STATUS_NO_MEMORY;
1397 }
1398
1399 return make_server_info_info3(mem_ctx,
1400 sent_nt_username, domain,
1401 server_info, info3);
1402}
1403
1404/**
1405 * Verify whether or not given domain is trusted.
1406 *
1407 * @param domain_name name of the domain to be verified
1408 * @return true if domain is one of the trusted ones or
1409 * false if otherwise
1410 **/
1411
1412bool is_trusted_domain(const char* dom_name)
1413{
1414 struct dom_sid trustdom_sid;
1415 bool ret;
1416
1417 /* no trusted domains for a standalone server */
1418
1419 if ( lp_server_role() == ROLE_STANDALONE )
1420 return False;
1421
1422 if (dom_name == NULL || dom_name[0] == '\0') {
1423 return false;
1424 }
1425
1426 if (strequal(dom_name, get_global_sam_name())) {
1427 return false;
1428 }
1429
1430 /* if we are a DC, then check for a direct trust relationships */
1431
1432 if ( IS_DC ) {
1433 become_root();
1434 DEBUG (5,("is_trusted_domain: Checking for domain trust with "
1435 "[%s]\n", dom_name ));
1436 ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL);
1437 unbecome_root();
1438 if (ret)
1439 return True;
1440 }
1441 else {
1442 wbcErr result;
1443
1444 /* If winbind is around, ask it */
1445
1446 result = wb_is_trusted_domain(dom_name);
1447
1448 if (result == WBC_ERR_SUCCESS) {
1449 return True;
1450 }
1451
1452 if (result == WBC_ERR_DOMAIN_NOT_FOUND) {
1453 /* winbind could not find the domain */
1454 return False;
1455 }
1456
1457 /* The only other possible result is that winbind is not up
1458 and running. We need to update the trustdom_cache
1459 ourselves */
1460
1461 update_trustdom_cache();
1462 }
1463
1464 /* now the trustdom cache should be available a DC could still
1465 * have a transitive trust so fall back to the cache of trusted
1466 * domains (like a domain member would use */
1467
1468 if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) {
1469 return True;
1470 }
1471
1472 return False;
1473}
1474
Note: See TracBrowser for help on using the repository browser.