lib: replace: Add strsep function (missing on Solaris).
[Samba.git] / source3 / auth / auth_util.c
blob69e150fc972be54fc7b01d089f4fb07344771b78
1 /*
2 Unix SMB/CIFS implementation.
3 Authentication utility functions
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001-2011
6 Copyright (C) Jeremy Allison 2000-2001
7 Copyright (C) Rafal Szczesniak 2002
8 Copyright (C) Volker Lendecke 2006-2008
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.
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.
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/>.
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 "../librpc/gen_ndr/ndr_auth.h"
34 #include "../auth/auth_sam_reply.h"
35 #include "../librpc/gen_ndr/idmap.h"
36 #include "lib/param/loadparm.h"
38 #undef DBGC_CLASS
39 #define DBGC_CLASS DBGC_AUTH
41 /****************************************************************************
42 Create a UNIX user on demand.
43 ****************************************************************************/
45 static int _smb_create_user(const char *domain, const char *unix_username, const char *homedir)
47 TALLOC_CTX *ctx = talloc_tos();
48 char *add_script;
49 int ret;
51 add_script = lp_add_user_script(ctx);
52 if (!add_script || !*add_script) {
53 return -1;
55 add_script = talloc_all_string_sub(ctx,
56 add_script,
57 "%u",
58 unix_username);
59 if (!add_script) {
60 return -1;
62 if (domain) {
63 add_script = talloc_all_string_sub(ctx,
64 add_script,
65 "%D",
66 domain);
67 if (!add_script) {
68 return -1;
71 if (homedir) {
72 add_script = talloc_all_string_sub(ctx,
73 add_script,
74 "%H",
75 homedir);
76 if (!add_script) {
77 return -1;
80 ret = smbrun(add_script,NULL);
81 flush_pwnam_cache();
82 DEBUG(ret ? 0 : 3,
83 ("smb_create_user: Running the command `%s' gave %d\n",
84 add_script,ret));
85 return ret;
88 /****************************************************************************
89 Create an auth_usersupplied_data structure after appropriate mapping.
90 ****************************************************************************/
92 NTSTATUS make_user_info_map(TALLOC_CTX *mem_ctx,
93 struct auth_usersupplied_info **user_info,
94 const char *smb_name,
95 const char *client_domain,
96 const char *workstation_name,
97 const struct tsocket_address *remote_address,
98 const DATA_BLOB *lm_pwd,
99 const DATA_BLOB *nt_pwd,
100 const struct samr_Password *lm_interactive_pwd,
101 const struct samr_Password *nt_interactive_pwd,
102 const char *plaintext,
103 enum auth_password_state password_state)
105 const char *domain;
106 NTSTATUS result;
107 bool was_mapped;
108 char *internal_username = NULL;
110 was_mapped = map_username(talloc_tos(), smb_name, &internal_username);
111 if (!internal_username) {
112 return NT_STATUS_NO_MEMORY;
115 DEBUG(5, ("Mapping user [%s]\\[%s] from workstation [%s]\n",
116 client_domain, smb_name, workstation_name));
118 domain = client_domain;
120 /* If you connect to a Windows domain member using a bogus domain name,
121 * the Windows box will map the BOGUS\user to SAMNAME\user. Thus, if
122 * the Windows box is a DC the name will become DOMAIN\user and be
123 * authenticated against AD, if the Windows box is a member server but
124 * not a DC the name will become WORKSTATION\user. A standalone
125 * non-domain member box will also map to WORKSTATION\user.
126 * This also deals with the client passing in a "" domain */
128 if (!is_trusted_domain(domain) &&
129 !strequal(domain, my_sam_name()) &&
130 !strequal(domain, get_global_sam_name()))
132 if (lp_map_untrusted_to_domain())
133 domain = my_sam_name();
134 else
135 domain = get_global_sam_name();
136 DEBUG(5, ("Mapped domain from [%s] to [%s] for user [%s] from "
137 "workstation [%s]\n",
138 client_domain, domain, smb_name, workstation_name));
141 /* We know that the given domain is trusted (and we are allowing them),
142 * it is our global SAM name, or for legacy behavior it is our
143 * primary domain name */
145 result = make_user_info(mem_ctx, user_info, smb_name, internal_username,
146 client_domain, domain, workstation_name,
147 remote_address, lm_pwd, nt_pwd,
148 lm_interactive_pwd, nt_interactive_pwd,
149 plaintext, password_state);
150 if (NT_STATUS_IS_OK(result)) {
151 /* We have tried mapping */
152 (*user_info)->mapped_state = true;
153 /* did we actually map the user to a different name? */
154 (*user_info)->was_mapped = was_mapped;
156 return result;
159 /****************************************************************************
160 Create an auth_usersupplied_data, making the DATA_BLOBs here.
161 Decrypt and encrypt the passwords.
162 ****************************************************************************/
164 bool make_user_info_netlogon_network(TALLOC_CTX *mem_ctx,
165 struct auth_usersupplied_info **user_info,
166 const char *smb_name,
167 const char *client_domain,
168 const char *workstation_name,
169 const struct tsocket_address *remote_address,
170 uint32_t logon_parameters,
171 const uchar *lm_network_pwd,
172 int lm_pwd_len,
173 const uchar *nt_network_pwd,
174 int nt_pwd_len)
176 bool ret;
177 NTSTATUS status;
178 DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
179 DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
181 status = make_user_info_map(mem_ctx, user_info,
182 smb_name, client_domain,
183 workstation_name,
184 remote_address,
185 lm_pwd_len ? &lm_blob : NULL,
186 nt_pwd_len ? &nt_blob : NULL,
187 NULL, NULL, NULL,
188 AUTH_PASSWORD_RESPONSE);
190 if (NT_STATUS_IS_OK(status)) {
191 (*user_info)->logon_parameters = logon_parameters;
193 ret = NT_STATUS_IS_OK(status) ? true : false;
195 data_blob_free(&lm_blob);
196 data_blob_free(&nt_blob);
197 return ret;
200 /****************************************************************************
201 Create an auth_usersupplied_data, making the DATA_BLOBs here.
202 Decrypt and encrypt the passwords.
203 ****************************************************************************/
205 bool make_user_info_netlogon_interactive(TALLOC_CTX *mem_ctx,
206 struct auth_usersupplied_info **user_info,
207 const char *smb_name,
208 const char *client_domain,
209 const char *workstation_name,
210 const struct tsocket_address *remote_address,
211 uint32_t logon_parameters,
212 const uchar chal[8],
213 const uchar lm_interactive_pwd[16],
214 const uchar nt_interactive_pwd[16])
216 struct samr_Password lm_pwd;
217 struct samr_Password nt_pwd;
218 unsigned char local_lm_response[24];
219 unsigned char local_nt_response[24];
221 if (lm_interactive_pwd)
222 memcpy(lm_pwd.hash, lm_interactive_pwd, sizeof(lm_pwd.hash));
224 if (nt_interactive_pwd)
225 memcpy(nt_pwd.hash, nt_interactive_pwd, sizeof(nt_pwd.hash));
227 if (lm_interactive_pwd)
228 SMBOWFencrypt(lm_pwd.hash, chal,
229 local_lm_response);
231 if (nt_interactive_pwd)
232 SMBOWFencrypt(nt_pwd.hash, chal,
233 local_nt_response);
236 bool ret;
237 NTSTATUS nt_status;
238 DATA_BLOB local_lm_blob = data_blob_null;
239 DATA_BLOB local_nt_blob = data_blob_null;
241 if (lm_interactive_pwd) {
242 local_lm_blob = data_blob(local_lm_response,
243 sizeof(local_lm_response));
246 if (nt_interactive_pwd) {
247 local_nt_blob = data_blob(local_nt_response,
248 sizeof(local_nt_response));
251 nt_status = make_user_info_map(
252 mem_ctx,
253 user_info,
254 smb_name, client_domain, workstation_name,
255 remote_address,
256 lm_interactive_pwd ? &local_lm_blob : NULL,
257 nt_interactive_pwd ? &local_nt_blob : NULL,
258 lm_interactive_pwd ? &lm_pwd : NULL,
259 nt_interactive_pwd ? &nt_pwd : NULL,
260 NULL, AUTH_PASSWORD_HASH);
262 if (NT_STATUS_IS_OK(nt_status)) {
263 (*user_info)->logon_parameters = logon_parameters;
266 ret = NT_STATUS_IS_OK(nt_status) ? true : false;
267 data_blob_free(&local_lm_blob);
268 data_blob_free(&local_nt_blob);
269 return ret;
274 /****************************************************************************
275 Create an auth_usersupplied_data structure
276 ****************************************************************************/
278 bool make_user_info_for_reply(TALLOC_CTX *mem_ctx,
279 struct auth_usersupplied_info **user_info,
280 const char *smb_name,
281 const char *client_domain,
282 const struct tsocket_address *remote_address,
283 const uint8_t chal[8],
284 DATA_BLOB plaintext_password)
287 DATA_BLOB local_lm_blob;
288 DATA_BLOB local_nt_blob;
289 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
290 char *plaintext_password_string;
292 * Not encrypted - do so.
295 DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted "
296 "format.\n"));
297 if (plaintext_password.data && plaintext_password.length) {
298 unsigned char local_lm_response[24];
300 #ifdef DEBUG_PASSWORD
301 DEBUG(10,("Unencrypted password (len %d):\n",
302 (int)plaintext_password.length));
303 dump_data(100, plaintext_password.data,
304 plaintext_password.length);
305 #endif
307 SMBencrypt( (const char *)plaintext_password.data,
308 (const uchar*)chal, local_lm_response);
309 local_lm_blob = data_blob(local_lm_response, 24);
311 /* We can't do an NT hash here, as the password needs to be
312 case insensitive */
313 local_nt_blob = data_blob_null;
314 } else {
315 local_lm_blob = data_blob_null;
316 local_nt_blob = data_blob_null;
319 plaintext_password_string = talloc_strndup(talloc_tos(),
320 (const char *)plaintext_password.data,
321 plaintext_password.length);
322 if (!plaintext_password_string) {
323 return false;
326 ret = make_user_info(mem_ctx,
327 user_info, smb_name, smb_name, client_domain, client_domain,
328 get_remote_machine_name(),
329 remote_address,
330 local_lm_blob.data ? &local_lm_blob : NULL,
331 local_nt_blob.data ? &local_nt_blob : NULL,
332 NULL, NULL,
333 plaintext_password_string,
334 AUTH_PASSWORD_PLAIN);
336 if (plaintext_password_string) {
337 memset(plaintext_password_string, '\0', strlen(plaintext_password_string));
338 talloc_free(plaintext_password_string);
341 data_blob_free(&local_lm_blob);
342 return NT_STATUS_IS_OK(ret) ? true : false;
345 /****************************************************************************
346 Create an auth_usersupplied_data structure
347 ****************************************************************************/
349 NTSTATUS make_user_info_for_reply_enc(TALLOC_CTX *mem_ctx,
350 struct auth_usersupplied_info **user_info,
351 const char *smb_name,
352 const char *client_domain,
353 const struct tsocket_address *remote_address,
354 DATA_BLOB lm_resp, DATA_BLOB nt_resp)
356 return make_user_info(mem_ctx,
357 user_info, smb_name, smb_name,
358 client_domain, client_domain,
359 get_remote_machine_name(),
360 remote_address,
361 lm_resp.data && (lm_resp.length > 0) ? &lm_resp : NULL,
362 nt_resp.data && (nt_resp.length > 0) ? &nt_resp : NULL,
363 NULL, NULL, NULL,
364 AUTH_PASSWORD_RESPONSE);
367 /****************************************************************************
368 Create a guest user_info blob, for anonymous authentication.
369 ****************************************************************************/
371 bool make_user_info_guest(TALLOC_CTX *mem_ctx,
372 const struct tsocket_address *remote_address,
373 struct auth_usersupplied_info **user_info)
375 NTSTATUS nt_status;
377 nt_status = make_user_info(mem_ctx,
378 user_info,
379 "","",
380 "","",
381 "",
382 remote_address,
383 NULL, NULL,
384 NULL, NULL,
385 NULL,
386 AUTH_PASSWORD_RESPONSE);
388 return NT_STATUS_IS_OK(nt_status) ? true : false;
391 static NTSTATUS log_nt_token(struct security_token *token)
393 TALLOC_CTX *frame = talloc_stackframe();
394 char *command;
395 char *group_sidstr;
396 size_t i;
398 if ((lp_log_nt_token_command(frame) == NULL) ||
399 (strlen(lp_log_nt_token_command(frame)) == 0)) {
400 TALLOC_FREE(frame);
401 return NT_STATUS_OK;
404 group_sidstr = talloc_strdup(frame, "");
405 for (i=1; i<token->num_sids; i++) {
406 group_sidstr = talloc_asprintf(
407 frame, "%s %s", group_sidstr,
408 sid_string_talloc(frame, &token->sids[i]));
411 command = talloc_string_sub(
412 frame, lp_log_nt_token_command(frame),
413 "%s", sid_string_talloc(frame, &token->sids[0]));
414 command = talloc_string_sub(frame, command, "%t", group_sidstr);
416 if (command == NULL) {
417 TALLOC_FREE(frame);
418 return NT_STATUS_NO_MEMORY;
421 DEBUG(8, ("running command: [%s]\n", command));
422 if (smbrun(command, NULL) != 0) {
423 DEBUG(0, ("Could not log NT token\n"));
424 TALLOC_FREE(frame);
425 return NT_STATUS_ACCESS_DENIED;
428 TALLOC_FREE(frame);
429 return NT_STATUS_OK;
433 * Create the token to use from server_info->info3 and
434 * server_info->sids (the info3/sam groups). Find the unix gids.
437 NTSTATUS create_local_token(TALLOC_CTX *mem_ctx,
438 const struct auth_serversupplied_info *server_info,
439 DATA_BLOB *session_key,
440 const char *smb_username, /* for ->sanitized_username, for %U subs */
441 struct auth_session_info **session_info_out)
443 struct security_token *t;
444 NTSTATUS status;
445 size_t i;
446 struct dom_sid tmp_sid;
447 struct auth_session_info *session_info;
448 struct unixid *ids;
449 fstring tmp;
451 /* Ensure we can't possible take a code path leading to a
452 * null defref. */
453 if (!server_info) {
454 return NT_STATUS_LOGON_FAILURE;
457 session_info = talloc_zero(mem_ctx, struct auth_session_info);
458 if (!session_info) {
459 return NT_STATUS_NO_MEMORY;
462 session_info->unix_token = talloc_zero(session_info, struct security_unix_token);
463 if (!session_info->unix_token) {
464 TALLOC_FREE(session_info);
465 return NT_STATUS_NO_MEMORY;
468 session_info->unix_token->uid = server_info->utok.uid;
469 session_info->unix_token->gid = server_info->utok.gid;
471 session_info->unix_info = talloc_zero(session_info, struct auth_user_info_unix);
472 if (!session_info->unix_info) {
473 TALLOC_FREE(session_info);
474 return NT_STATUS_NO_MEMORY;
477 session_info->unix_info->unix_name = talloc_strdup(session_info, server_info->unix_name);
478 if (!session_info->unix_info->unix_name) {
479 TALLOC_FREE(session_info);
480 return NT_STATUS_NO_MEMORY;
483 /* This is a potentially untrusted username for use in %U */
484 alpha_strcpy(tmp, smb_username, ". _-$", sizeof(tmp));
485 session_info->unix_info->sanitized_username =
486 talloc_strdup(session_info->unix_info, tmp);
488 if (session_key) {
489 data_blob_free(&session_info->session_key);
490 session_info->session_key = data_blob_talloc(session_info,
491 session_key->data,
492 session_key->length);
493 if (!session_info->session_key.data && session_key->length) {
494 return NT_STATUS_NO_MEMORY;
496 } else {
497 session_info->session_key = data_blob_talloc( session_info, server_info->session_key.data,
498 server_info->session_key.length);
501 /* We need to populate session_info->info with the information found in server_info->info3 */
502 status = make_user_info_SamBaseInfo(session_info, "", &server_info->info3->base,
503 server_info->guest == false,
504 &session_info->info);
505 if (!NT_STATUS_IS_OK(status)) {
506 DEBUG(0, ("conversion of info3 into auth_user_info failed!\n"));
507 TALLOC_FREE(session_info);
508 return status;
511 if (server_info->security_token) {
512 /* Just copy the token, it has already been finalised
513 * (nasty hack to support a cached guest/system session_info
516 session_info->security_token = dup_nt_token(session_info, server_info->security_token);
517 if (!session_info->security_token) {
518 TALLOC_FREE(session_info);
519 return NT_STATUS_NO_MEMORY;
522 session_info->unix_token->ngroups = server_info->utok.ngroups;
523 if (server_info->utok.ngroups != 0) {
524 session_info->unix_token->groups = (gid_t *)talloc_memdup(
525 session_info->unix_token, server_info->utok.groups,
526 sizeof(gid_t)*session_info->unix_token->ngroups);
527 } else {
528 session_info->unix_token->groups = NULL;
531 *session_info_out = session_info;
532 return NT_STATUS_OK;
536 * If winbind is not around, we can not make much use of the SIDs the
537 * domain controller provided us with. Likewise if the user name was
538 * mapped to some local unix user.
541 if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) ||
542 (server_info->nss_token)) {
543 char *found_username = NULL;
544 status = create_token_from_username(session_info,
545 server_info->unix_name,
546 server_info->guest,
547 &session_info->unix_token->uid,
548 &session_info->unix_token->gid,
549 &found_username,
550 &session_info->security_token);
551 if (NT_STATUS_IS_OK(status)) {
552 session_info->unix_info->unix_name = found_username;
554 } else {
555 status = create_local_nt_token_from_info3(session_info,
556 server_info->guest,
557 server_info->info3,
558 &server_info->extra,
559 &session_info->security_token);
562 if (!NT_STATUS_IS_OK(status)) {
563 return status;
566 /* Convert the SIDs to gids. */
568 session_info->unix_token->ngroups = 0;
569 session_info->unix_token->groups = NULL;
571 t = session_info->security_token;
573 ids = talloc_array(talloc_tos(), struct unixid,
574 t->num_sids);
575 if (ids == NULL) {
576 return NT_STATUS_NO_MEMORY;
579 if (!sids_to_unixids(t->sids, t->num_sids, ids)) {
580 TALLOC_FREE(ids);
581 return NT_STATUS_NO_MEMORY;
584 for (i=0; i<t->num_sids; i++) {
586 if (i == 0 && ids[i].type != ID_TYPE_BOTH) {
587 continue;
590 if (ids[i].type != ID_TYPE_GID &&
591 ids[i].type != ID_TYPE_BOTH) {
592 DEBUG(10, ("Could not convert SID %s to gid, "
593 "ignoring it\n",
594 sid_string_dbg(&t->sids[i])));
595 continue;
597 if (!add_gid_to_array_unique(session_info, ids[i].id,
598 &session_info->unix_token->groups,
599 &session_info->unix_token->ngroups)) {
600 return NT_STATUS_NO_MEMORY;
605 * Add the "Unix Group" SID for each gid to catch mapped groups
606 * and their Unix equivalent. This is to solve the backwards
607 * compatibility problem of 'valid users = +ntadmin' where
608 * ntadmin has been paired with "Domain Admins" in the group
609 * mapping table. Otherwise smb.conf would need to be changed
610 * to 'valid user = "Domain Admins"'. --jerry
612 * For consistency we also add the "Unix User" SID,
613 * so that the complete unix token is represented within
614 * the nt token.
617 uid_to_unix_users_sid(session_info->unix_token->uid, &tmp_sid);
619 add_sid_to_array_unique(session_info->security_token, &tmp_sid,
620 &session_info->security_token->sids,
621 &session_info->security_token->num_sids);
623 for ( i=0; i<session_info->unix_token->ngroups; i++ ) {
624 gid_to_unix_groups_sid(session_info->unix_token->groups[i], &tmp_sid);
625 add_sid_to_array_unique(session_info->security_token, &tmp_sid,
626 &session_info->security_token->sids,
627 &session_info->security_token->num_sids);
630 security_token_debug(DBGC_AUTH, 10, session_info->security_token);
631 debug_unix_user_token(DBGC_AUTH, 10,
632 session_info->unix_token->uid,
633 session_info->unix_token->gid,
634 session_info->unix_token->ngroups,
635 session_info->unix_token->groups);
637 status = log_nt_token(session_info->security_token);
638 if (!NT_STATUS_IS_OK(status)) {
639 return status;
642 *session_info_out = session_info;
643 return NT_STATUS_OK;
646 /***************************************************************************
647 Make (and fill) a server_info struct from a 'struct passwd' by conversion
648 to a struct samu
649 ***************************************************************************/
651 NTSTATUS make_server_info_pw(TALLOC_CTX *mem_ctx,
652 const char *unix_username,
653 const struct passwd *pwd,
654 struct auth_serversupplied_info **server_info)
656 NTSTATUS status;
657 TALLOC_CTX *tmp_ctx = NULL;
658 struct auth_serversupplied_info *result;
660 tmp_ctx = talloc_stackframe();
661 if (tmp_ctx == NULL) {
662 return NT_STATUS_NO_MEMORY;
665 result = make_server_info(tmp_ctx);
666 if (result == NULL) {
667 status = NT_STATUS_NO_MEMORY;
668 goto done;
671 status = passwd_to_SamInfo3(result,
672 unix_username,
673 pwd,
674 &result->info3,
675 &result->extra);
676 if (!NT_STATUS_IS_OK(status)) {
677 goto done;
680 result->unix_name = talloc_strdup(result, unix_username);
681 if (result->unix_name == NULL) {
682 status = NT_STATUS_NO_MEMORY;
683 goto done;
686 result->utok.uid = pwd->pw_uid;
687 result->utok.gid = pwd->pw_gid;
689 *server_info = talloc_steal(mem_ctx, result);
690 status = NT_STATUS_OK;
691 done:
692 talloc_free(tmp_ctx);
694 return status;
697 static NTSTATUS get_system_info3(TALLOC_CTX *mem_ctx,
698 struct netr_SamInfo3 *info3)
700 NTSTATUS status;
701 struct dom_sid *system_sid;
703 /* Set account name */
704 init_lsa_String(&info3->base.account_name, "SYSTEM");
706 /* Set domain name */
707 init_lsa_StringLarge(&info3->base.logon_domain, "NT AUTHORITY");
710 /* The SID set here will be overwirtten anyway, but try and make it SID_NT_SYSTEM anyway */
711 /* Domain sid is NT_AUTHORITY */
713 system_sid = dom_sid_parse_talloc(mem_ctx, SID_NT_SYSTEM);
714 if (system_sid == NULL) {
715 return NT_STATUS_NO_MEMORY;
718 status = dom_sid_split_rid(mem_ctx, system_sid, &info3->base.domain_sid,
719 &info3->base.rid);
720 TALLOC_FREE(system_sid);
721 if (!NT_STATUS_IS_OK(status)) {
722 return status;
725 /* Primary gid is the same */
726 info3->base.primary_gid = info3->base.rid;
728 return NT_STATUS_OK;
731 static NTSTATUS get_guest_info3(TALLOC_CTX *mem_ctx,
732 struct netr_SamInfo3 *info3)
734 const char *guest_account = lp_guest_account();
735 struct dom_sid domain_sid;
736 struct passwd *pwd;
737 const char *tmp;
739 pwd = Get_Pwnam_alloc(mem_ctx, guest_account);
740 if (pwd == NULL) {
741 DEBUG(0,("SamInfo3_for_guest: Unable to locate guest "
742 "account [%s]!\n", guest_account));
743 return NT_STATUS_NO_SUCH_USER;
746 /* Set account name */
747 tmp = talloc_strdup(mem_ctx, pwd->pw_name);
748 if (tmp == NULL) {
749 return NT_STATUS_NO_MEMORY;
751 init_lsa_String(&info3->base.account_name, tmp);
753 /* Set domain name */
754 tmp = talloc_strdup(mem_ctx, get_global_sam_name());
755 if (tmp == NULL) {
756 return NT_STATUS_NO_MEMORY;
758 init_lsa_StringLarge(&info3->base.logon_domain, tmp);
760 /* Domain sid */
761 sid_copy(&domain_sid, get_global_sam_sid());
763 info3->base.domain_sid = dom_sid_dup(mem_ctx, &domain_sid);
764 if (info3->base.domain_sid == NULL) {
765 return NT_STATUS_NO_MEMORY;
768 /* Guest rid */
769 info3->base.rid = DOMAIN_RID_GUEST;
771 /* Primary gid */
772 info3->base.primary_gid = DOMAIN_RID_GUESTS;
774 /* Set as guest */
775 info3->base.user_flags = NETLOGON_GUEST;
777 TALLOC_FREE(pwd);
778 return NT_STATUS_OK;
781 /***************************************************************************
782 Make (and fill) a user_info struct for a guest login.
783 This *must* succeed for smbd to start. If there is no mapping entry for
784 the guest gid, then create one.
786 The resulting structure is a 'session_info' because
787 create_local_token() has already been called on it. This is quite
788 nasty, as the auth subsystem isn't expect this, but the behavior is
789 left as-is for now.
790 ***************************************************************************/
792 static NTSTATUS make_new_session_info_guest(struct auth_session_info **session_info, struct auth_serversupplied_info **server_info)
794 static const char zeros[16] = {0};
795 const char *guest_account = lp_guest_account();
796 const char *domain = lp_netbios_name();
797 struct netr_SamInfo3 info3;
798 TALLOC_CTX *tmp_ctx;
799 NTSTATUS status;
801 tmp_ctx = talloc_stackframe();
802 if (tmp_ctx == NULL) {
803 return NT_STATUS_NO_MEMORY;
806 ZERO_STRUCT(info3);
808 status = get_guest_info3(tmp_ctx, &info3);
809 if (!NT_STATUS_IS_OK(status)) {
810 DEBUG(0, ("get_guest_info3 failed with %s\n",
811 nt_errstr(status)));
812 goto done;
815 status = make_server_info_info3(tmp_ctx,
816 guest_account,
817 domain,
818 server_info,
819 &info3);
820 if (!NT_STATUS_IS_OK(status)) {
821 DEBUG(0, ("make_server_info_info3 failed with %s\n",
822 nt_errstr(status)));
823 goto done;
826 (*server_info)->guest = true;
828 /* This should not be done here (we should produce a server
829 * info, and later construct a session info from it), but for
830 * now this does not change the previous behavior */
831 status = create_local_token(tmp_ctx, *server_info, NULL,
832 (*server_info)->info3->base.account_name.string,
833 session_info);
834 if (!NT_STATUS_IS_OK(status)) {
835 DEBUG(0, ("create_local_token failed: %s\n",
836 nt_errstr(status)));
837 goto done;
839 talloc_steal(NULL, *session_info);
840 talloc_steal(NULL, *server_info);
842 /* annoying, but the Guest really does have a session key, and it is
843 all zeros! */
844 (*session_info)->session_key = data_blob(zeros, sizeof(zeros));
846 status = NT_STATUS_OK;
847 done:
848 TALLOC_FREE(tmp_ctx);
849 return status;
852 /***************************************************************************
853 Make (and fill) a auth_session_info struct for a system user login.
854 This *must* succeed for smbd to start.
855 ***************************************************************************/
857 static NTSTATUS make_new_session_info_system(TALLOC_CTX *mem_ctx,
858 struct auth_session_info **session_info)
860 NTSTATUS status;
861 struct auth_serversupplied_info *server_info;
862 TALLOC_CTX *tmp_ctx;
864 tmp_ctx = talloc_stackframe();
865 if (tmp_ctx == NULL) {
866 return NT_STATUS_NO_MEMORY;
869 server_info = make_server_info(tmp_ctx);
870 if (!server_info) {
871 status = NT_STATUS_NO_MEMORY;
872 DEBUG(0, ("failed making server_info\n"));
873 goto done;
876 server_info->info3 = talloc_zero(server_info, struct netr_SamInfo3);
877 if (!server_info->info3) {
878 status = NT_STATUS_NO_MEMORY;
879 DEBUG(0, ("talloc failed setting info3\n"));
880 goto done;
883 status = get_system_info3(server_info, server_info->info3);
884 if (!NT_STATUS_IS_OK(status)) {
885 DEBUG(0, ("Failed creating system info3 with %s\n",
886 nt_errstr(status)));
887 goto done;
890 server_info->utok.uid = sec_initial_uid();
891 server_info->utok.gid = sec_initial_gid();
892 server_info->unix_name = talloc_asprintf(server_info,
893 "NT AUTHORITY%cSYSTEM",
894 *lp_winbind_separator());
896 if (!server_info->unix_name) {
897 status = NT_STATUS_NO_MEMORY;
898 DEBUG(0, ("talloc_asprintf failed setting unix_name\n"));
899 goto done;
902 server_info->security_token = talloc_zero(server_info, struct security_token);
903 if (!server_info->security_token) {
904 status = NT_STATUS_NO_MEMORY;
905 DEBUG(0, ("talloc failed setting security token\n"));
906 goto done;
909 status = add_sid_to_array_unique(server_info->security_token->sids,
910 &global_sid_System,
911 &server_info->security_token->sids,
912 &server_info->security_token->num_sids);
913 if (!NT_STATUS_IS_OK(status)) {
914 goto done;
917 /* SYSTEM has all privilages */
918 server_info->security_token->privilege_mask = ~0;
920 /* Now turn the server_info into a session_info with the full token etc */
921 status = create_local_token(mem_ctx, server_info, NULL, "SYSTEM", session_info);
922 talloc_free(server_info);
924 if (!NT_STATUS_IS_OK(status)) {
925 DEBUG(0, ("create_local_token failed: %s\n",
926 nt_errstr(status)));
927 goto done;
930 talloc_steal(mem_ctx, *session_info);
932 done:
933 TALLOC_FREE(tmp_ctx);
934 return status;
937 /****************************************************************************
938 Fake a auth_session_info just from a username (as a
939 session_info structure, with create_local_token() already called on
941 ****************************************************************************/
943 NTSTATUS make_session_info_from_username(TALLOC_CTX *mem_ctx,
944 const char *username,
945 bool is_guest,
946 struct auth_session_info **session_info)
948 struct passwd *pwd;
949 NTSTATUS status;
950 struct auth_serversupplied_info *result;
951 TALLOC_CTX *tmp_ctx;
953 tmp_ctx = talloc_stackframe();
954 if (tmp_ctx == NULL) {
955 return NT_STATUS_NO_MEMORY;
958 pwd = Get_Pwnam_alloc(tmp_ctx, username);
959 if (pwd == NULL) {
960 status = NT_STATUS_NO_SUCH_USER;
961 goto done;
964 status = make_server_info_pw(tmp_ctx, pwd->pw_name, pwd, &result);
965 if (!NT_STATUS_IS_OK(status)) {
966 goto done;
969 result->nss_token = true;
970 result->guest = is_guest;
972 /* Now turn the server_info into a session_info with the full token etc */
973 status = create_local_token(mem_ctx,
974 result,
975 NULL,
976 pwd->pw_name,
977 session_info);
979 done:
980 talloc_free(tmp_ctx);
982 return status;
985 /* This function MUST only used to create the cached server_info for
986 * guest.
988 * This is a lossy conversion. Variables known to be lost so far
989 * include:
991 * - nss_token (not needed because the only read doesn't happen
992 * for the GUEST user, as this routine populates ->security_token
994 * - extra (not needed because the guest account must have valid RIDs per the output of get_guest_info3())
996 * - The 'server_info' parameter allows the missing 'info3' to be copied across.
998 static struct auth_serversupplied_info *copy_session_info_serverinfo_guest(TALLOC_CTX *mem_ctx,
999 const struct auth_session_info *src,
1000 struct auth_serversupplied_info *server_info)
1002 struct auth_serversupplied_info *dst;
1004 dst = make_server_info(mem_ctx);
1005 if (dst == NULL) {
1006 return NULL;
1009 /* This element must be provided to convert back to an auth_serversupplied_info */
1010 SMB_ASSERT(src->unix_info);
1012 dst->guest = true;
1013 dst->system = false;
1015 /* This element must be provided to convert back to an
1016 * auth_serversupplied_info. This needs to be from the
1017 * auth_session_info because the group values in particular
1018 * may change during create_local_token() processing */
1019 SMB_ASSERT(src->unix_token);
1020 dst->utok.uid = src->unix_token->uid;
1021 dst->utok.gid = src->unix_token->gid;
1022 dst->utok.ngroups = src->unix_token->ngroups;
1023 if (src->unix_token->ngroups != 0) {
1024 dst->utok.groups = (gid_t *)talloc_memdup(
1025 dst, src->unix_token->groups,
1026 sizeof(gid_t)*dst->utok.ngroups);
1027 } else {
1028 dst->utok.groups = NULL;
1031 /* We must have a security_token as otherwise the lossy
1032 * conversion without nss_token would cause create_local_token
1033 * to take the wrong path */
1034 SMB_ASSERT(src->security_token);
1036 dst->security_token = dup_nt_token(dst, src->security_token);
1037 if (!dst->security_token) {
1038 TALLOC_FREE(dst);
1039 return NULL;
1042 dst->session_key = data_blob_talloc( dst, src->session_key.data,
1043 src->session_key.length);
1045 /* This is OK because this functions is only used for the
1046 * GUEST account, which has all-zero keys for both values */
1047 dst->lm_session_key = data_blob_talloc(dst, src->session_key.data,
1048 src->session_key.length);
1050 dst->info3 = copy_netr_SamInfo3(dst, server_info->info3);
1051 if (!dst->info3) {
1052 TALLOC_FREE(dst);
1053 return NULL;
1056 dst->unix_name = talloc_strdup(dst, src->unix_info->unix_name);
1057 if (!dst->unix_name) {
1058 TALLOC_FREE(dst);
1059 return NULL;
1062 return dst;
1065 struct auth_session_info *copy_session_info(TALLOC_CTX *mem_ctx,
1066 const struct auth_session_info *src)
1068 struct auth_session_info *dst;
1069 DATA_BLOB blob;
1070 enum ndr_err_code ndr_err;
1072 ndr_err = ndr_push_struct_blob(
1073 &blob, talloc_tos(), src,
1074 (ndr_push_flags_fn_t)ndr_push_auth_session_info);
1075 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1076 DEBUG(0, ("copy_session_info(): ndr_push_auth_session_info failed: "
1077 "%s\n", ndr_errstr(ndr_err)));
1078 return NULL;
1081 dst = talloc(mem_ctx, struct auth_session_info);
1082 if (dst == NULL) {
1083 DEBUG(0, ("talloc failed\n"));
1084 TALLOC_FREE(blob.data);
1085 return NULL;
1088 ndr_err = ndr_pull_struct_blob(
1089 &blob, dst, dst,
1090 (ndr_pull_flags_fn_t)ndr_pull_auth_session_info);
1091 TALLOC_FREE(blob.data);
1093 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1094 DEBUG(0, ("copy_session_info(): ndr_pull_auth_session_info failed: "
1095 "%s\n", ndr_errstr(ndr_err)));
1096 TALLOC_FREE(dst);
1097 return NULL;
1100 return dst;
1104 * Set a new session key. Used in the rpc server where we have to override the
1105 * SMB level session key with SystemLibraryDTC
1108 bool session_info_set_session_key(struct auth_session_info *info,
1109 DATA_BLOB session_key)
1111 TALLOC_FREE(info->session_key.data);
1113 info->session_key = data_blob_talloc(
1114 info, session_key.data, session_key.length);
1116 return (info->session_key.data != NULL);
1119 static struct auth_session_info *guest_info = NULL;
1121 static struct auth_serversupplied_info *guest_server_info = NULL;
1123 bool init_guest_info(void)
1125 if (guest_info != NULL)
1126 return true;
1128 return NT_STATUS_IS_OK(make_new_session_info_guest(&guest_info, &guest_server_info));
1131 NTSTATUS make_server_info_guest(TALLOC_CTX *mem_ctx,
1132 struct auth_serversupplied_info **server_info)
1134 /* This is trickier than it would appear to need to be because
1135 * we are trying to avoid certain costly operations when the
1136 * structure is converted to a 'auth_session_info' again in
1137 * create_local_token() */
1138 *server_info = copy_session_info_serverinfo_guest(mem_ctx, guest_info, guest_server_info);
1139 return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1142 NTSTATUS make_session_info_guest(TALLOC_CTX *mem_ctx,
1143 struct auth_session_info **session_info)
1145 *session_info = copy_session_info(mem_ctx, guest_info);
1146 return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1149 static struct auth_session_info *system_info = NULL;
1151 NTSTATUS init_system_session_info(void)
1153 if (system_info != NULL)
1154 return NT_STATUS_OK;
1156 return make_new_session_info_system(NULL, &system_info);
1159 NTSTATUS make_session_info_system(TALLOC_CTX *mem_ctx,
1160 struct auth_session_info **session_info)
1162 if (system_info == NULL) return NT_STATUS_UNSUCCESSFUL;
1163 *session_info = copy_session_info(mem_ctx, system_info);
1164 return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1167 const struct auth_session_info *get_session_info_system(void)
1169 return system_info;
1172 /***************************************************************************
1173 Purely internal function for make_server_info_info3
1174 ***************************************************************************/
1176 static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain,
1177 const char *username, char **found_username,
1178 struct passwd **pwd,
1179 bool *username_was_mapped)
1181 char *orig_dom_user = NULL;
1182 char *dom_user = NULL;
1183 char *lower_username = NULL;
1184 char *real_username = NULL;
1185 struct passwd *passwd;
1187 lower_username = talloc_strdup(mem_ctx, username);
1188 if (!lower_username) {
1189 return NT_STATUS_NO_MEMORY;
1191 if (!strlower_m( lower_username )) {
1192 return NT_STATUS_INVALID_PARAMETER;
1195 orig_dom_user = talloc_asprintf(mem_ctx,
1196 "%s%c%s",
1197 domain,
1198 *lp_winbind_separator(),
1199 lower_username);
1200 if (!orig_dom_user) {
1201 return NT_STATUS_NO_MEMORY;
1204 /* Get the passwd struct. Try to create the account if necessary. */
1206 *username_was_mapped = map_username(mem_ctx, orig_dom_user, &dom_user);
1207 if (!dom_user) {
1208 return NT_STATUS_NO_MEMORY;
1211 passwd = smb_getpwnam(mem_ctx, dom_user, &real_username, true );
1212 if (!passwd) {
1213 DEBUG(3, ("Failed to find authenticated user %s via "
1214 "getpwnam(), denying access.\n", dom_user));
1215 return NT_STATUS_NO_SUCH_USER;
1218 if (!real_username) {
1219 return NT_STATUS_NO_MEMORY;
1222 *pwd = passwd;
1224 /* This is pointless -- there is no support for differing
1225 unix and windows names. Make sure to always store the
1226 one we actually looked up and succeeded. Have I mentioned
1227 why I hate the 'winbind use default domain' parameter?
1228 --jerry */
1230 *found_username = talloc_strdup( mem_ctx, real_username );
1232 return NT_STATUS_OK;
1235 /****************************************************************************
1236 Wrapper to allow the getpwnam() call to strip the domain name and
1237 try again in case a local UNIX user is already there. Also run through
1238 the username if we fallback to the username only.
1239 ****************************************************************************/
1241 struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, const char *domuser,
1242 char **p_save_username, bool create )
1244 struct passwd *pw = NULL;
1245 char *p = NULL;
1246 char *username = NULL;
1248 /* we only save a copy of the username it has been mangled
1249 by winbindd use default domain */
1250 *p_save_username = NULL;
1252 /* don't call map_username() here since it has to be done higher
1253 up the stack so we don't call it multiple times */
1255 username = talloc_strdup(mem_ctx, domuser);
1256 if (!username) {
1257 return NULL;
1260 p = strchr_m( username, *lp_winbind_separator() );
1262 /* code for a DOMAIN\user string */
1264 if ( p ) {
1265 pw = Get_Pwnam_alloc( mem_ctx, domuser );
1266 if ( pw ) {
1267 /* make sure we get the case of the username correct */
1268 /* work around 'winbind use default domain = yes' */
1270 if ( lp_winbind_use_default_domain() &&
1271 !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
1272 char *domain;
1274 /* split the domain and username into 2 strings */
1275 *p = '\0';
1276 domain = username;
1278 *p_save_username = talloc_asprintf(mem_ctx,
1279 "%s%c%s",
1280 domain,
1281 *lp_winbind_separator(),
1282 pw->pw_name);
1283 if (!*p_save_username) {
1284 TALLOC_FREE(pw);
1285 return NULL;
1287 } else {
1288 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1291 /* whew -- done! */
1292 return pw;
1295 /* setup for lookup of just the username */
1296 /* remember that p and username are overlapping memory */
1298 p++;
1299 username = talloc_strdup(mem_ctx, p);
1300 if (!username) {
1301 return NULL;
1305 /* just lookup a plain username */
1307 pw = Get_Pwnam_alloc(mem_ctx, username);
1309 /* Create local user if requested but only if winbindd
1310 is not running. We need to protect against cases
1311 where winbindd is failing and then prematurely
1312 creating users in /etc/passwd */
1314 if ( !pw && create && !winbind_ping() ) {
1315 /* Don't add a machine account. */
1316 if (username[strlen(username)-1] == '$')
1317 return NULL;
1319 _smb_create_user(NULL, username, NULL);
1320 pw = Get_Pwnam_alloc(mem_ctx, username);
1323 /* one last check for a valid passwd struct */
1325 if (pw) {
1326 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1328 return pw;
1331 /***************************************************************************
1332 Make a server_info struct from the info3 returned by a domain logon
1333 ***************************************************************************/
1335 NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
1336 const char *sent_nt_username,
1337 const char *domain,
1338 struct auth_serversupplied_info **server_info,
1339 const struct netr_SamInfo3 *info3)
1341 static const char zeros[16] = {0, };
1343 NTSTATUS nt_status = NT_STATUS_OK;
1344 char *found_username = NULL;
1345 const char *nt_domain;
1346 const char *nt_username;
1347 struct dom_sid user_sid;
1348 struct dom_sid group_sid;
1349 bool username_was_mapped;
1350 struct passwd *pwd;
1351 struct auth_serversupplied_info *result;
1354 Here is where we should check the list of
1355 trusted domains, and verify that the SID
1356 matches.
1359 if (!sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid)) {
1360 return NT_STATUS_INVALID_PARAMETER;
1363 if (!sid_compose(&group_sid, info3->base.domain_sid,
1364 info3->base.primary_gid)) {
1365 return NT_STATUS_INVALID_PARAMETER;
1368 nt_username = talloc_strdup(mem_ctx, info3->base.account_name.string);
1369 if (!nt_username) {
1370 /* If the server didn't give us one, just use the one we sent
1371 * them */
1372 nt_username = sent_nt_username;
1375 nt_domain = talloc_strdup(mem_ctx, info3->base.logon_domain.string);
1376 if (!nt_domain) {
1377 /* If the server didn't give us one, just use the one we sent
1378 * them */
1379 nt_domain = domain;
1382 /* If getpwnam() fails try the add user script (2.2.x behavior).
1384 We use the _unmapped_ username here in an attempt to provide
1385 consistent username mapping behavior between kerberos and NTLM[SSP]
1386 authentication in domain mode security. I.E. Username mapping
1387 should be applied to the fully qualified username
1388 (e.g. DOMAIN\user) and not just the login name. Yes this means we
1389 called map_username() unnecessarily in make_user_info_map() but
1390 that is how the current code is designed. Making the change here
1391 is the least disruptive place. -- jerry */
1393 /* this call will try to create the user if necessary */
1395 nt_status = check_account(mem_ctx, nt_domain, sent_nt_username,
1396 &found_username, &pwd,
1397 &username_was_mapped);
1399 if (!NT_STATUS_IS_OK(nt_status)) {
1400 return nt_status;
1403 result = make_server_info(NULL);
1404 if (result == NULL) {
1405 DEBUG(4, ("make_server_info failed!\n"));
1406 return NT_STATUS_NO_MEMORY;
1409 result->unix_name = talloc_strdup(result, found_username);
1411 /* copy in the info3 */
1412 result->info3 = copy_netr_SamInfo3(result, info3);
1413 if (result->info3 == NULL) {
1414 TALLOC_FREE(result);
1415 return NT_STATUS_NO_MEMORY;
1418 /* Fill in the unix info we found on the way */
1420 result->utok.uid = pwd->pw_uid;
1421 result->utok.gid = pwd->pw_gid;
1423 /* ensure we are never given NULL session keys */
1425 if (memcmp(info3->base.key.key, zeros, sizeof(zeros)) == 0) {
1426 result->session_key = data_blob_null;
1427 } else {
1428 result->session_key = data_blob_talloc(
1429 result, info3->base.key.key,
1430 sizeof(info3->base.key.key));
1433 if (memcmp(info3->base.LMSessKey.key, zeros, 8) == 0) {
1434 result->lm_session_key = data_blob_null;
1435 } else {
1436 result->lm_session_key = data_blob_talloc(
1437 result, info3->base.LMSessKey.key,
1438 sizeof(info3->base.LMSessKey.key));
1441 result->nss_token |= username_was_mapped;
1443 result->guest = (info3->base.user_flags & NETLOGON_GUEST);
1445 *server_info = result;
1447 return NT_STATUS_OK;
1450 /*****************************************************************************
1451 Make a server_info struct from the wbcAuthUserInfo returned by a domain logon
1452 ******************************************************************************/
1454 NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx,
1455 const char *sent_nt_username,
1456 const char *domain,
1457 const struct wbcAuthUserInfo *info,
1458 struct auth_serversupplied_info **server_info)
1460 struct netr_SamInfo3 *info3;
1462 info3 = wbcAuthUserInfo_to_netr_SamInfo3(mem_ctx, info);
1463 if (!info3) {
1464 return NT_STATUS_NO_MEMORY;
1467 return make_server_info_info3(mem_ctx,
1468 sent_nt_username, domain,
1469 server_info, info3);
1473 * Verify whether or not given domain is trusted.
1475 * @param domain_name name of the domain to be verified
1476 * @return true if domain is one of the trusted ones or
1477 * false if otherwise
1480 bool is_trusted_domain(const char* dom_name)
1482 struct dom_sid trustdom_sid;
1483 bool ret;
1485 /* no trusted domains for a standalone server */
1487 if ( lp_server_role() == ROLE_STANDALONE )
1488 return false;
1490 if (dom_name == NULL || dom_name[0] == '\0') {
1491 return false;
1494 if (strequal(dom_name, get_global_sam_name())) {
1495 return false;
1498 /* if we are a DC, then check for a direct trust relationships */
1500 if ( IS_DC ) {
1501 become_root();
1502 DEBUG (5,("is_trusted_domain: Checking for domain trust with "
1503 "[%s]\n", dom_name ));
1504 ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL);
1505 unbecome_root();
1506 if (ret)
1507 return true;
1509 else {
1510 wbcErr result;
1512 /* If winbind is around, ask it */
1514 result = wb_is_trusted_domain(dom_name);
1516 if (result == WBC_ERR_SUCCESS) {
1517 return true;
1520 if (result == WBC_ERR_DOMAIN_NOT_FOUND) {
1521 /* winbind could not find the domain */
1522 return false;
1525 DEBUG(10, ("wb_is_trusted_domain returned error: %s\n",
1526 wbcErrorString(result)));
1528 /* The only other possible result is that winbind is not up
1529 and running. We need to update the trustdom_cache
1530 ourselves */
1532 update_trustdom_cache();
1535 /* now the trustdom cache should be available a DC could still
1536 * have a transitive trust so fall back to the cache of trusted
1537 * domains (like a domain member would use */
1539 if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) {
1540 return true;
1543 return false;
1549 on a logon error possibly map the error to success if "map to guest"
1550 is set approriately
1552 NTSTATUS do_map_to_guest_server_info(TALLOC_CTX *mem_ctx,
1553 NTSTATUS status,
1554 const char *user,
1555 const char *domain,
1556 struct auth_serversupplied_info **server_info)
1558 user = user ? user : "";
1559 domain = domain ? domain : "";
1561 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
1562 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
1563 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
1564 DEBUG(3,("No such user %s [%s] - using guest account\n",
1565 user, domain));
1566 return make_server_info_guest(mem_ctx, server_info);
1568 } else if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1569 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
1570 DEBUG(3,("Registered username %s for guest access\n",
1571 user));
1572 return make_server_info_guest(mem_ctx, server_info);
1576 return status;
1580 Extract session key from a session info and return it in a blob
1581 if intent is KEY_USE_16BYTES, truncate it to 16 bytes
1583 See sections 3.2.4.15 and 3.3.4.2 of MS-SMB
1584 Also see https://lists.samba.org/archive/cifs-protocol/2012-January/002265.html for details
1586 Note that returned session_key is referencing the original key, it is supposed to be
1587 short-lived. If original session_info->session_key is gone, the reference will be broken.
1589 NTSTATUS session_extract_session_key(const struct auth_session_info *session_info, DATA_BLOB *session_key, enum session_key_use_intent intent)
1592 if (session_key == NULL || session_info == NULL) {
1593 return NT_STATUS_INVALID_PARAMETER;
1596 if (session_info->session_key.length == 0) {
1597 return NT_STATUS_NO_USER_SESSION_KEY;
1600 *session_key = session_info->session_key;
1601 if (intent == KEY_USE_16BYTES) {
1602 session_key->length = MIN(session_info->session_key.length, 16);
1604 return NT_STATUS_OK;