pysmb: Check for credentials using same method as pyrpc
[Samba.git] / source3 / auth / auth_util.c
blob5d9f0e0270fefa51ece72b9d3a41ed350fd2ff56
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 "lib/util_unixsids.h"
27 #include "../libcli/auth/libcli_auth.h"
28 #include "../lib/crypto/arcfour.h"
29 #include "rpc_client/init_lsa.h"
30 #include "../libcli/security/security.h"
31 #include "../lib/util/util_pw.h"
32 #include "lib/winbind_util.h"
33 #include "passdb.h"
34 #include "../librpc/gen_ndr/ndr_auth.h"
35 #include "../auth/auth_sam_reply.h"
36 #include "../librpc/gen_ndr/idmap.h"
37 #include "lib/param/loadparm.h"
38 #include "../lib/tsocket/tsocket.h"
40 #undef DBGC_CLASS
41 #define DBGC_CLASS DBGC_AUTH
43 /****************************************************************************
44 Create a UNIX user on demand.
45 ****************************************************************************/
47 static int _smb_create_user(const char *domain, const char *unix_username, const char *homedir)
49 TALLOC_CTX *ctx = talloc_tos();
50 char *add_script;
51 int ret;
53 add_script = lp_add_user_script(ctx);
54 if (!add_script || !*add_script) {
55 return -1;
57 add_script = talloc_all_string_sub(ctx,
58 add_script,
59 "%u",
60 unix_username);
61 if (!add_script) {
62 return -1;
64 if (domain) {
65 add_script = talloc_all_string_sub(ctx,
66 add_script,
67 "%D",
68 domain);
69 if (!add_script) {
70 return -1;
73 if (homedir) {
74 add_script = talloc_all_string_sub(ctx,
75 add_script,
76 "%H",
77 homedir);
78 if (!add_script) {
79 return -1;
82 ret = smbrun(add_script, NULL, NULL);
83 flush_pwnam_cache();
84 DEBUG(ret ? 0 : 3,
85 ("smb_create_user: Running the command `%s' gave %d\n",
86 add_script,ret));
87 return ret;
90 /****************************************************************************
91 Create an auth_usersupplied_data structure after appropriate mapping.
92 ****************************************************************************/
94 NTSTATUS make_user_info_map(TALLOC_CTX *mem_ctx,
95 struct auth_usersupplied_info **user_info,
96 const char *smb_name,
97 const char *client_domain,
98 const char *workstation_name,
99 const struct tsocket_address *remote_address,
100 const DATA_BLOB *lm_pwd,
101 const DATA_BLOB *nt_pwd,
102 const struct samr_Password *lm_interactive_pwd,
103 const struct samr_Password *nt_interactive_pwd,
104 const char *plaintext,
105 enum auth_password_state password_state)
107 const char *domain;
108 NTSTATUS result;
109 bool was_mapped;
110 char *internal_username = NULL;
111 bool upn_form = false;
113 if (client_domain[0] == '\0' && strchr(smb_name, '@')) {
114 upn_form = true;
117 was_mapped = map_username(talloc_tos(), smb_name, &internal_username);
118 if (!internal_username) {
119 return NT_STATUS_NO_MEMORY;
122 DEBUG(5, ("Mapping user [%s]\\[%s] from workstation [%s]\n",
123 client_domain, smb_name, workstation_name));
125 domain = client_domain;
127 /* If you connect to a Windows domain member using a bogus domain name,
128 * the Windows box will map the BOGUS\user to SAMNAME\user. Thus, if
129 * the Windows box is a DC the name will become DOMAIN\user and be
130 * authenticated against AD, if the Windows box is a member server but
131 * not a DC the name will become WORKSTATION\user. A standalone
132 * non-domain member box will also map to WORKSTATION\user.
133 * This also deals with the client passing in a "" domain */
135 if (!upn_form && !is_trusted_domain(domain) &&
136 !strequal(domain, my_sam_name()) &&
137 !strequal(domain, get_global_sam_name())) {
138 if (lp_map_untrusted_to_domain())
139 domain = my_sam_name();
140 else
141 domain = get_global_sam_name();
142 DEBUG(5, ("Mapped domain from [%s] to [%s] for user [%s] from "
143 "workstation [%s]\n",
144 client_domain, domain, smb_name, workstation_name));
147 /* We know that the given domain is trusted (and we are allowing them),
148 * it is our global SAM name, or for legacy behavior it is our
149 * primary domain name */
151 result = make_user_info(mem_ctx, user_info, smb_name, internal_username,
152 client_domain, domain, workstation_name,
153 remote_address, lm_pwd, nt_pwd,
154 lm_interactive_pwd, nt_interactive_pwd,
155 plaintext, password_state);
156 if (NT_STATUS_IS_OK(result)) {
157 /* We have tried mapping */
158 (*user_info)->mapped_state = true;
159 /* did we actually map the user to a different name? */
160 (*user_info)->was_mapped = was_mapped;
162 return result;
165 /****************************************************************************
166 Create an auth_usersupplied_data, making the DATA_BLOBs here.
167 Decrypt and encrypt the passwords.
168 ****************************************************************************/
170 bool make_user_info_netlogon_network(TALLOC_CTX *mem_ctx,
171 struct auth_usersupplied_info **user_info,
172 const char *smb_name,
173 const char *client_domain,
174 const char *workstation_name,
175 const struct tsocket_address *remote_address,
176 uint32_t logon_parameters,
177 const uchar *lm_network_pwd,
178 int lm_pwd_len,
179 const uchar *nt_network_pwd,
180 int nt_pwd_len)
182 bool ret;
183 NTSTATUS status;
184 DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
185 DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
187 status = make_user_info_map(mem_ctx, user_info,
188 smb_name, client_domain,
189 workstation_name,
190 remote_address,
191 lm_pwd_len ? &lm_blob : NULL,
192 nt_pwd_len ? &nt_blob : NULL,
193 NULL, NULL, NULL,
194 AUTH_PASSWORD_RESPONSE);
196 if (NT_STATUS_IS_OK(status)) {
197 (*user_info)->logon_parameters = logon_parameters;
199 ret = NT_STATUS_IS_OK(status) ? true : false;
201 data_blob_free(&lm_blob);
202 data_blob_free(&nt_blob);
203 return ret;
206 /****************************************************************************
207 Create an auth_usersupplied_data, making the DATA_BLOBs here.
208 Decrypt and encrypt the passwords.
209 ****************************************************************************/
211 bool make_user_info_netlogon_interactive(TALLOC_CTX *mem_ctx,
212 struct auth_usersupplied_info **user_info,
213 const char *smb_name,
214 const char *client_domain,
215 const char *workstation_name,
216 const struct tsocket_address *remote_address,
217 uint32_t logon_parameters,
218 const uchar chal[8],
219 const uchar lm_interactive_pwd[16],
220 const uchar nt_interactive_pwd[16])
222 struct samr_Password lm_pwd;
223 struct samr_Password nt_pwd;
224 unsigned char local_lm_response[24];
225 unsigned char local_nt_response[24];
227 if (lm_interactive_pwd)
228 memcpy(lm_pwd.hash, lm_interactive_pwd, sizeof(lm_pwd.hash));
230 if (nt_interactive_pwd)
231 memcpy(nt_pwd.hash, nt_interactive_pwd, sizeof(nt_pwd.hash));
233 if (lm_interactive_pwd)
234 SMBOWFencrypt(lm_pwd.hash, chal,
235 local_lm_response);
237 if (nt_interactive_pwd)
238 SMBOWFencrypt(nt_pwd.hash, chal,
239 local_nt_response);
242 bool ret;
243 NTSTATUS nt_status;
244 DATA_BLOB local_lm_blob = data_blob_null;
245 DATA_BLOB local_nt_blob = data_blob_null;
247 if (lm_interactive_pwd) {
248 local_lm_blob = data_blob(local_lm_response,
249 sizeof(local_lm_response));
252 if (nt_interactive_pwd) {
253 local_nt_blob = data_blob(local_nt_response,
254 sizeof(local_nt_response));
257 nt_status = make_user_info_map(
258 mem_ctx,
259 user_info,
260 smb_name, client_domain, workstation_name,
261 remote_address,
262 lm_interactive_pwd ? &local_lm_blob : NULL,
263 nt_interactive_pwd ? &local_nt_blob : NULL,
264 lm_interactive_pwd ? &lm_pwd : NULL,
265 nt_interactive_pwd ? &nt_pwd : NULL,
266 NULL, AUTH_PASSWORD_HASH);
268 if (NT_STATUS_IS_OK(nt_status)) {
269 (*user_info)->logon_parameters = logon_parameters;
272 ret = NT_STATUS_IS_OK(nt_status) ? true : false;
273 data_blob_free(&local_lm_blob);
274 data_blob_free(&local_nt_blob);
275 return ret;
280 /****************************************************************************
281 Create an auth_usersupplied_data structure
282 ****************************************************************************/
284 bool make_user_info_for_reply(TALLOC_CTX *mem_ctx,
285 struct auth_usersupplied_info **user_info,
286 const char *smb_name,
287 const char *client_domain,
288 const struct tsocket_address *remote_address,
289 const uint8_t chal[8],
290 DATA_BLOB plaintext_password)
293 DATA_BLOB local_lm_blob;
294 DATA_BLOB local_nt_blob;
295 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
296 char *plaintext_password_string;
298 * Not encrypted - do so.
301 DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted "
302 "format.\n"));
303 if (plaintext_password.data && plaintext_password.length) {
304 unsigned char local_lm_response[24];
306 #ifdef DEBUG_PASSWORD
307 DEBUG(10,("Unencrypted password (len %d):\n",
308 (int)plaintext_password.length));
309 dump_data(100, plaintext_password.data,
310 plaintext_password.length);
311 #endif
313 SMBencrypt( (const char *)plaintext_password.data,
314 (const uchar*)chal, local_lm_response);
315 local_lm_blob = data_blob(local_lm_response, 24);
317 /* We can't do an NT hash here, as the password needs to be
318 case insensitive */
319 local_nt_blob = data_blob_null;
320 } else {
321 local_lm_blob = data_blob_null;
322 local_nt_blob = data_blob_null;
325 plaintext_password_string = talloc_strndup(talloc_tos(),
326 (const char *)plaintext_password.data,
327 plaintext_password.length);
328 if (!plaintext_password_string) {
329 return false;
332 ret = make_user_info(mem_ctx,
333 user_info, smb_name, smb_name, client_domain, client_domain,
334 get_remote_machine_name(),
335 remote_address,
336 local_lm_blob.data ? &local_lm_blob : NULL,
337 local_nt_blob.data ? &local_nt_blob : NULL,
338 NULL, NULL,
339 plaintext_password_string,
340 AUTH_PASSWORD_PLAIN);
342 if (plaintext_password_string) {
343 memset(plaintext_password_string, '\0', strlen(plaintext_password_string));
344 talloc_free(plaintext_password_string);
347 data_blob_free(&local_lm_blob);
348 return NT_STATUS_IS_OK(ret) ? true : false;
351 /****************************************************************************
352 Create an auth_usersupplied_data structure
353 ****************************************************************************/
355 NTSTATUS make_user_info_for_reply_enc(TALLOC_CTX *mem_ctx,
356 struct auth_usersupplied_info **user_info,
357 const char *smb_name,
358 const char *client_domain,
359 const struct tsocket_address *remote_address,
360 DATA_BLOB lm_resp, DATA_BLOB nt_resp)
362 bool allow_raw = lp_raw_ntlmv2_auth();
364 if (!allow_raw && nt_resp.length >= 48) {
366 * NTLMv2_RESPONSE has at least 48 bytes
367 * and should only be supported via NTLMSSP.
369 DEBUG(2,("Rejecting raw NTLMv2 authentication with "
370 "user [%s\\%s] from[%s]\n",
371 client_domain, smb_name,
372 tsocket_address_string(remote_address, mem_ctx)));
373 return NT_STATUS_INVALID_PARAMETER;
376 return make_user_info(mem_ctx,
377 user_info, smb_name, smb_name,
378 client_domain, client_domain,
379 get_remote_machine_name(),
380 remote_address,
381 lm_resp.data && (lm_resp.length > 0) ? &lm_resp : NULL,
382 nt_resp.data && (nt_resp.length > 0) ? &nt_resp : NULL,
383 NULL, NULL, NULL,
384 AUTH_PASSWORD_RESPONSE);
387 /****************************************************************************
388 Create a guest user_info blob, for anonymous authentication.
389 ****************************************************************************/
391 bool make_user_info_guest(TALLOC_CTX *mem_ctx,
392 const struct tsocket_address *remote_address,
393 struct auth_usersupplied_info **user_info)
395 NTSTATUS nt_status;
397 nt_status = make_user_info(mem_ctx,
398 user_info,
399 "","",
400 "","",
401 "",
402 remote_address,
403 NULL, NULL,
404 NULL, NULL,
405 NULL,
406 AUTH_PASSWORD_RESPONSE);
408 return NT_STATUS_IS_OK(nt_status) ? true : false;
411 static NTSTATUS log_nt_token(struct security_token *token)
413 TALLOC_CTX *frame = talloc_stackframe();
414 char *command;
415 char *group_sidstr;
416 size_t i;
418 if ((lp_log_nt_token_command(frame) == NULL) ||
419 (strlen(lp_log_nt_token_command(frame)) == 0)) {
420 TALLOC_FREE(frame);
421 return NT_STATUS_OK;
424 group_sidstr = talloc_strdup(frame, "");
425 for (i=1; i<token->num_sids; i++) {
426 group_sidstr = talloc_asprintf(
427 frame, "%s %s", group_sidstr,
428 sid_string_talloc(frame, &token->sids[i]));
431 command = talloc_string_sub(
432 frame, lp_log_nt_token_command(frame),
433 "%s", sid_string_talloc(frame, &token->sids[0]));
434 command = talloc_string_sub(frame, command, "%t", group_sidstr);
436 if (command == NULL) {
437 TALLOC_FREE(frame);
438 return NT_STATUS_NO_MEMORY;
441 DEBUG(8, ("running command: [%s]\n", command));
442 if (smbrun(command, NULL, NULL) != 0) {
443 DEBUG(0, ("Could not log NT token\n"));
444 TALLOC_FREE(frame);
445 return NT_STATUS_ACCESS_DENIED;
448 TALLOC_FREE(frame);
449 return NT_STATUS_OK;
453 * Create the token to use from server_info->info3 and
454 * server_info->sids (the info3/sam groups). Find the unix gids.
457 NTSTATUS create_local_token(TALLOC_CTX *mem_ctx,
458 const struct auth_serversupplied_info *server_info,
459 DATA_BLOB *session_key,
460 const char *smb_username, /* for ->sanitized_username, for %U subs */
461 struct auth_session_info **session_info_out)
463 struct security_token *t;
464 NTSTATUS status;
465 size_t i;
466 struct dom_sid tmp_sid;
467 struct auth_session_info *session_info;
468 struct unixid *ids;
469 fstring tmp;
471 /* Ensure we can't possible take a code path leading to a
472 * null defref. */
473 if (!server_info) {
474 return NT_STATUS_LOGON_FAILURE;
477 session_info = talloc_zero(mem_ctx, struct auth_session_info);
478 if (!session_info) {
479 return NT_STATUS_NO_MEMORY;
482 session_info->unix_token = talloc_zero(session_info, struct security_unix_token);
483 if (!session_info->unix_token) {
484 TALLOC_FREE(session_info);
485 return NT_STATUS_NO_MEMORY;
488 session_info->unix_token->uid = server_info->utok.uid;
489 session_info->unix_token->gid = server_info->utok.gid;
491 session_info->unix_info = talloc_zero(session_info, struct auth_user_info_unix);
492 if (!session_info->unix_info) {
493 TALLOC_FREE(session_info);
494 return NT_STATUS_NO_MEMORY;
497 session_info->unix_info->unix_name = talloc_strdup(session_info, server_info->unix_name);
498 if (!session_info->unix_info->unix_name) {
499 TALLOC_FREE(session_info);
500 return NT_STATUS_NO_MEMORY;
503 /* This is a potentially untrusted username for use in %U */
504 alpha_strcpy(tmp, smb_username, ". _-$", sizeof(tmp));
505 session_info->unix_info->sanitized_username =
506 talloc_strdup(session_info->unix_info, tmp);
508 if (session_key) {
509 data_blob_free(&session_info->session_key);
510 session_info->session_key = data_blob_talloc(session_info,
511 session_key->data,
512 session_key->length);
513 if (!session_info->session_key.data && session_key->length) {
514 return NT_STATUS_NO_MEMORY;
516 } else {
517 session_info->session_key = data_blob_talloc( session_info, server_info->session_key.data,
518 server_info->session_key.length);
521 /* We need to populate session_info->info with the information found in server_info->info3 */
522 status = make_user_info_SamBaseInfo(session_info, "", &server_info->info3->base,
523 server_info->guest == false,
524 &session_info->info);
525 if (!NT_STATUS_IS_OK(status)) {
526 DEBUG(0, ("conversion of info3 into auth_user_info failed!\n"));
527 TALLOC_FREE(session_info);
528 return status;
531 if (server_info->security_token) {
532 /* Just copy the token, it has already been finalised
533 * (nasty hack to support a cached guest/system session_info
536 session_info->security_token = dup_nt_token(session_info, server_info->security_token);
537 if (!session_info->security_token) {
538 TALLOC_FREE(session_info);
539 return NT_STATUS_NO_MEMORY;
542 session_info->unix_token->ngroups = server_info->utok.ngroups;
543 if (server_info->utok.ngroups != 0) {
544 session_info->unix_token->groups = (gid_t *)talloc_memdup(
545 session_info->unix_token, server_info->utok.groups,
546 sizeof(gid_t)*session_info->unix_token->ngroups);
547 } else {
548 session_info->unix_token->groups = NULL;
551 *session_info_out = session_info;
552 return NT_STATUS_OK;
556 * If winbind is not around, we can not make much use of the SIDs the
557 * domain controller provided us with. Likewise if the user name was
558 * mapped to some local unix user.
561 if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) ||
562 (server_info->nss_token)) {
563 char *found_username = NULL;
564 status = create_token_from_username(session_info,
565 server_info->unix_name,
566 server_info->guest,
567 &session_info->unix_token->uid,
568 &session_info->unix_token->gid,
569 &found_username,
570 &session_info->security_token);
571 if (NT_STATUS_IS_OK(status)) {
572 session_info->unix_info->unix_name = found_username;
574 } else {
575 status = create_local_nt_token_from_info3(session_info,
576 server_info->guest,
577 server_info->info3,
578 &server_info->extra,
579 &session_info->security_token);
582 if (!NT_STATUS_IS_OK(status)) {
583 return status;
586 /* Convert the SIDs to gids. */
588 session_info->unix_token->ngroups = 0;
589 session_info->unix_token->groups = NULL;
591 t = session_info->security_token;
593 ids = talloc_array(talloc_tos(), struct unixid,
594 t->num_sids);
595 if (ids == NULL) {
596 return NT_STATUS_NO_MEMORY;
599 if (!sids_to_unixids(t->sids, t->num_sids, ids)) {
600 TALLOC_FREE(ids);
601 return NT_STATUS_NO_MEMORY;
604 for (i=0; i<t->num_sids; i++) {
606 if (i == 0 && ids[i].type != ID_TYPE_BOTH) {
607 continue;
610 if (ids[i].type != ID_TYPE_GID &&
611 ids[i].type != ID_TYPE_BOTH) {
612 DEBUG(10, ("Could not convert SID %s to gid, "
613 "ignoring it\n",
614 sid_string_dbg(&t->sids[i])));
615 continue;
617 if (!add_gid_to_array_unique(session_info, ids[i].id,
618 &session_info->unix_token->groups,
619 &session_info->unix_token->ngroups)) {
620 return NT_STATUS_NO_MEMORY;
625 * Add the "Unix Group" SID for each gid to catch mapped groups
626 * and their Unix equivalent. This is to solve the backwards
627 * compatibility problem of 'valid users = +ntadmin' where
628 * ntadmin has been paired with "Domain Admins" in the group
629 * mapping table. Otherwise smb.conf would need to be changed
630 * to 'valid user = "Domain Admins"'. --jerry
632 * For consistency we also add the "Unix User" SID,
633 * so that the complete unix token is represented within
634 * the nt token.
637 uid_to_unix_users_sid(session_info->unix_token->uid, &tmp_sid);
639 add_sid_to_array_unique(session_info->security_token, &tmp_sid,
640 &session_info->security_token->sids,
641 &session_info->security_token->num_sids);
643 for ( i=0; i<session_info->unix_token->ngroups; i++ ) {
644 gid_to_unix_groups_sid(session_info->unix_token->groups[i], &tmp_sid);
645 add_sid_to_array_unique(session_info->security_token, &tmp_sid,
646 &session_info->security_token->sids,
647 &session_info->security_token->num_sids);
650 security_token_debug(DBGC_AUTH, 10, session_info->security_token);
651 debug_unix_user_token(DBGC_AUTH, 10,
652 session_info->unix_token->uid,
653 session_info->unix_token->gid,
654 session_info->unix_token->ngroups,
655 session_info->unix_token->groups);
657 status = log_nt_token(session_info->security_token);
658 if (!NT_STATUS_IS_OK(status)) {
659 return status;
662 *session_info_out = session_info;
663 return NT_STATUS_OK;
666 /***************************************************************************
667 Make (and fill) a server_info struct from a 'struct passwd' by conversion
668 to a struct samu
669 ***************************************************************************/
671 NTSTATUS make_server_info_pw(TALLOC_CTX *mem_ctx,
672 const char *unix_username,
673 const struct passwd *pwd,
674 struct auth_serversupplied_info **server_info)
676 NTSTATUS status;
677 TALLOC_CTX *tmp_ctx = NULL;
678 struct auth_serversupplied_info *result;
680 tmp_ctx = talloc_stackframe();
681 if (tmp_ctx == NULL) {
682 return NT_STATUS_NO_MEMORY;
685 result = make_server_info(tmp_ctx);
686 if (result == NULL) {
687 status = NT_STATUS_NO_MEMORY;
688 goto done;
691 status = passwd_to_SamInfo3(result,
692 unix_username,
693 pwd,
694 &result->info3,
695 &result->extra);
696 if (!NT_STATUS_IS_OK(status)) {
697 goto done;
700 result->unix_name = talloc_strdup(result, unix_username);
701 if (result->unix_name == NULL) {
702 status = NT_STATUS_NO_MEMORY;
703 goto done;
706 result->utok.uid = pwd->pw_uid;
707 result->utok.gid = pwd->pw_gid;
709 *server_info = talloc_steal(mem_ctx, result);
710 status = NT_STATUS_OK;
711 done:
712 talloc_free(tmp_ctx);
714 return status;
717 static NTSTATUS get_system_info3(TALLOC_CTX *mem_ctx,
718 struct netr_SamInfo3 *info3)
720 NTSTATUS status;
722 /* Set account name */
723 init_lsa_String(&info3->base.account_name, "SYSTEM");
725 /* Set domain name */
726 init_lsa_StringLarge(&info3->base.logon_domain, "NT AUTHORITY");
729 status = dom_sid_split_rid(mem_ctx, &global_sid_System,
730 &info3->base.domain_sid,
731 &info3->base.rid);
732 if (!NT_STATUS_IS_OK(status)) {
733 return status;
736 /* Primary gid is the same */
737 info3->base.primary_gid = info3->base.rid;
739 return NT_STATUS_OK;
742 static NTSTATUS get_guest_info3(TALLOC_CTX *mem_ctx,
743 struct netr_SamInfo3 *info3)
745 const char *guest_account = lp_guest_account();
746 struct dom_sid domain_sid;
747 struct passwd *pwd;
748 const char *tmp;
750 pwd = Get_Pwnam_alloc(mem_ctx, guest_account);
751 if (pwd == NULL) {
752 DEBUG(0,("SamInfo3_for_guest: Unable to locate guest "
753 "account [%s]!\n", guest_account));
754 return NT_STATUS_NO_SUCH_USER;
757 /* Set account name */
758 tmp = talloc_strdup(mem_ctx, pwd->pw_name);
759 if (tmp == NULL) {
760 return NT_STATUS_NO_MEMORY;
762 init_lsa_String(&info3->base.account_name, tmp);
764 /* Set domain name */
765 tmp = talloc_strdup(mem_ctx, get_global_sam_name());
766 if (tmp == NULL) {
767 return NT_STATUS_NO_MEMORY;
769 init_lsa_StringLarge(&info3->base.logon_domain, tmp);
771 /* Domain sid */
772 sid_copy(&domain_sid, get_global_sam_sid());
774 info3->base.domain_sid = dom_sid_dup(mem_ctx, &domain_sid);
775 if (info3->base.domain_sid == NULL) {
776 return NT_STATUS_NO_MEMORY;
779 /* Guest rid */
780 info3->base.rid = DOMAIN_RID_GUEST;
782 /* Primary gid */
783 info3->base.primary_gid = DOMAIN_RID_GUESTS;
785 /* Set as guest */
786 info3->base.user_flags = NETLOGON_GUEST;
788 TALLOC_FREE(pwd);
789 return NT_STATUS_OK;
792 /***************************************************************************
793 Make (and fill) a user_info struct for a guest login.
794 This *must* succeed for smbd to start. If there is no mapping entry for
795 the guest gid, then create one.
797 The resulting structure is a 'session_info' because
798 create_local_token() has already been called on it. This is quite
799 nasty, as the auth subsystem isn't expect this, but the behavior is
800 left as-is for now.
801 ***************************************************************************/
803 static NTSTATUS make_new_session_info_guest(struct auth_session_info **session_info, struct auth_serversupplied_info **server_info)
805 const char *guest_account = lp_guest_account();
806 const char *domain = lp_netbios_name();
807 struct netr_SamInfo3 info3;
808 TALLOC_CTX *tmp_ctx;
809 NTSTATUS status;
811 tmp_ctx = talloc_stackframe();
812 if (tmp_ctx == NULL) {
813 return NT_STATUS_NO_MEMORY;
816 ZERO_STRUCT(info3);
818 status = get_guest_info3(tmp_ctx, &info3);
819 if (!NT_STATUS_IS_OK(status)) {
820 DEBUG(0, ("get_guest_info3 failed with %s\n",
821 nt_errstr(status)));
822 goto done;
825 status = make_server_info_info3(tmp_ctx,
826 guest_account,
827 domain,
828 server_info,
829 &info3);
830 if (!NT_STATUS_IS_OK(status)) {
831 DEBUG(0, ("make_server_info_info3 failed with %s\n",
832 nt_errstr(status)));
833 goto done;
836 (*server_info)->guest = true;
838 /* This should not be done here (we should produce a server
839 * info, and later construct a session info from it), but for
840 * now this does not change the previous behavior */
841 status = create_local_token(tmp_ctx, *server_info, NULL,
842 (*server_info)->info3->base.account_name.string,
843 session_info);
844 if (!NT_STATUS_IS_OK(status)) {
845 DEBUG(0, ("create_local_token failed: %s\n",
846 nt_errstr(status)));
847 goto done;
849 talloc_steal(NULL, *session_info);
850 talloc_steal(NULL, *server_info);
852 /* annoying, but the Guest really does have a session key, and it is
853 all zeros! */
854 (*session_info)->session_key = data_blob_talloc_zero(NULL, 16);
856 status = NT_STATUS_OK;
857 done:
858 TALLOC_FREE(tmp_ctx);
859 return status;
862 /***************************************************************************
863 Make (and fill) a auth_session_info struct for a system user login.
864 This *must* succeed for smbd to start.
865 ***************************************************************************/
867 static NTSTATUS make_new_session_info_system(TALLOC_CTX *mem_ctx,
868 struct auth_session_info **session_info)
870 NTSTATUS status;
871 struct auth_serversupplied_info *server_info;
872 TALLOC_CTX *tmp_ctx;
874 tmp_ctx = talloc_stackframe();
875 if (tmp_ctx == NULL) {
876 return NT_STATUS_NO_MEMORY;
879 server_info = make_server_info(tmp_ctx);
880 if (!server_info) {
881 status = NT_STATUS_NO_MEMORY;
882 DEBUG(0, ("failed making server_info\n"));
883 goto done;
886 server_info->info3 = talloc_zero(server_info, struct netr_SamInfo3);
887 if (!server_info->info3) {
888 status = NT_STATUS_NO_MEMORY;
889 DEBUG(0, ("talloc failed setting info3\n"));
890 goto done;
893 status = get_system_info3(server_info, server_info->info3);
894 if (!NT_STATUS_IS_OK(status)) {
895 DEBUG(0, ("Failed creating system info3 with %s\n",
896 nt_errstr(status)));
897 goto done;
900 server_info->utok.uid = sec_initial_uid();
901 server_info->utok.gid = sec_initial_gid();
902 server_info->unix_name = talloc_asprintf(server_info,
903 "NT AUTHORITY%cSYSTEM",
904 *lp_winbind_separator());
906 if (!server_info->unix_name) {
907 status = NT_STATUS_NO_MEMORY;
908 DEBUG(0, ("talloc_asprintf failed setting unix_name\n"));
909 goto done;
912 server_info->security_token = talloc_zero(server_info, struct security_token);
913 if (!server_info->security_token) {
914 status = NT_STATUS_NO_MEMORY;
915 DEBUG(0, ("talloc failed setting security token\n"));
916 goto done;
919 status = add_sid_to_array_unique(server_info->security_token->sids,
920 &global_sid_System,
921 &server_info->security_token->sids,
922 &server_info->security_token->num_sids);
923 if (!NT_STATUS_IS_OK(status)) {
924 goto done;
927 /* SYSTEM has all privilages */
928 server_info->security_token->privilege_mask = ~0;
930 /* Now turn the server_info into a session_info with the full token etc */
931 status = create_local_token(mem_ctx, server_info, NULL, "SYSTEM", session_info);
932 talloc_free(server_info);
934 if (!NT_STATUS_IS_OK(status)) {
935 DEBUG(0, ("create_local_token failed: %s\n",
936 nt_errstr(status)));
937 goto done;
940 talloc_steal(mem_ctx, *session_info);
942 done:
943 TALLOC_FREE(tmp_ctx);
944 return status;
947 /****************************************************************************
948 Fake a auth_session_info just from a username (as a
949 session_info structure, with create_local_token() already called on
951 ****************************************************************************/
953 NTSTATUS make_session_info_from_username(TALLOC_CTX *mem_ctx,
954 const char *username,
955 bool is_guest,
956 struct auth_session_info **session_info)
958 struct passwd *pwd;
959 NTSTATUS status;
960 struct auth_serversupplied_info *result;
961 TALLOC_CTX *tmp_ctx;
963 tmp_ctx = talloc_stackframe();
964 if (tmp_ctx == NULL) {
965 return NT_STATUS_NO_MEMORY;
968 pwd = Get_Pwnam_alloc(tmp_ctx, username);
969 if (pwd == NULL) {
970 status = NT_STATUS_NO_SUCH_USER;
971 goto done;
974 status = make_server_info_pw(tmp_ctx, pwd->pw_name, pwd, &result);
975 if (!NT_STATUS_IS_OK(status)) {
976 goto done;
979 result->nss_token = true;
980 result->guest = is_guest;
982 /* Now turn the server_info into a session_info with the full token etc */
983 status = create_local_token(mem_ctx,
984 result,
985 NULL,
986 pwd->pw_name,
987 session_info);
989 done:
990 talloc_free(tmp_ctx);
992 return status;
995 /* This function MUST only used to create the cached server_info for
996 * guest.
998 * This is a lossy conversion. Variables known to be lost so far
999 * include:
1001 * - nss_token (not needed because the only read doesn't happen
1002 * for the GUEST user, as this routine populates ->security_token
1004 * - extra (not needed because the guest account must have valid RIDs per the output of get_guest_info3())
1006 * - The 'server_info' parameter allows the missing 'info3' to be copied across.
1008 static struct auth_serversupplied_info *copy_session_info_serverinfo_guest(TALLOC_CTX *mem_ctx,
1009 const struct auth_session_info *src,
1010 struct auth_serversupplied_info *server_info)
1012 struct auth_serversupplied_info *dst;
1014 dst = make_server_info(mem_ctx);
1015 if (dst == NULL) {
1016 return NULL;
1019 /* This element must be provided to convert back to an auth_serversupplied_info */
1020 SMB_ASSERT(src->unix_info);
1022 dst->guest = true;
1023 dst->system = false;
1025 /* This element must be provided to convert back to an
1026 * auth_serversupplied_info. This needs to be from the
1027 * auth_session_info because the group values in particular
1028 * may change during create_local_token() processing */
1029 SMB_ASSERT(src->unix_token);
1030 dst->utok.uid = src->unix_token->uid;
1031 dst->utok.gid = src->unix_token->gid;
1032 dst->utok.ngroups = src->unix_token->ngroups;
1033 if (src->unix_token->ngroups != 0) {
1034 dst->utok.groups = (gid_t *)talloc_memdup(
1035 dst, src->unix_token->groups,
1036 sizeof(gid_t)*dst->utok.ngroups);
1037 } else {
1038 dst->utok.groups = NULL;
1041 /* We must have a security_token as otherwise the lossy
1042 * conversion without nss_token would cause create_local_token
1043 * to take the wrong path */
1044 SMB_ASSERT(src->security_token);
1046 dst->security_token = dup_nt_token(dst, src->security_token);
1047 if (!dst->security_token) {
1048 TALLOC_FREE(dst);
1049 return NULL;
1052 dst->session_key = data_blob_talloc( dst, src->session_key.data,
1053 src->session_key.length);
1055 /* This is OK because this functions is only used for the
1056 * GUEST account, which has all-zero keys for both values */
1057 dst->lm_session_key = data_blob_talloc(dst, src->session_key.data,
1058 src->session_key.length);
1060 dst->info3 = copy_netr_SamInfo3(dst, server_info->info3);
1061 if (!dst->info3) {
1062 TALLOC_FREE(dst);
1063 return NULL;
1066 dst->unix_name = talloc_strdup(dst, src->unix_info->unix_name);
1067 if (!dst->unix_name) {
1068 TALLOC_FREE(dst);
1069 return NULL;
1072 return dst;
1075 struct auth_session_info *copy_session_info(TALLOC_CTX *mem_ctx,
1076 const struct auth_session_info *src)
1078 struct auth_session_info *dst;
1079 DATA_BLOB blob;
1080 enum ndr_err_code ndr_err;
1082 ndr_err = ndr_push_struct_blob(
1083 &blob, talloc_tos(), src,
1084 (ndr_push_flags_fn_t)ndr_push_auth_session_info);
1085 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1086 DEBUG(0, ("copy_session_info(): ndr_push_auth_session_info failed: "
1087 "%s\n", ndr_errstr(ndr_err)));
1088 return NULL;
1091 dst = talloc(mem_ctx, struct auth_session_info);
1092 if (dst == NULL) {
1093 DEBUG(0, ("talloc failed\n"));
1094 TALLOC_FREE(blob.data);
1095 return NULL;
1098 ndr_err = ndr_pull_struct_blob(
1099 &blob, dst, dst,
1100 (ndr_pull_flags_fn_t)ndr_pull_auth_session_info);
1101 TALLOC_FREE(blob.data);
1103 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1104 DEBUG(0, ("copy_session_info(): ndr_pull_auth_session_info failed: "
1105 "%s\n", ndr_errstr(ndr_err)));
1106 TALLOC_FREE(dst);
1107 return NULL;
1110 return dst;
1114 * Set a new session key. Used in the rpc server where we have to override the
1115 * SMB level session key with SystemLibraryDTC
1118 bool session_info_set_session_key(struct auth_session_info *info,
1119 DATA_BLOB session_key)
1121 TALLOC_FREE(info->session_key.data);
1123 info->session_key = data_blob_talloc(
1124 info, session_key.data, session_key.length);
1126 return (info->session_key.data != NULL);
1129 static struct auth_session_info *guest_info = NULL;
1131 static struct auth_serversupplied_info *guest_server_info = NULL;
1133 bool init_guest_info(void)
1135 if (guest_info != NULL)
1136 return true;
1138 return NT_STATUS_IS_OK(make_new_session_info_guest(&guest_info, &guest_server_info));
1141 NTSTATUS make_server_info_guest(TALLOC_CTX *mem_ctx,
1142 struct auth_serversupplied_info **server_info)
1144 /* This is trickier than it would appear to need to be because
1145 * we are trying to avoid certain costly operations when the
1146 * structure is converted to a 'auth_session_info' again in
1147 * create_local_token() */
1148 *server_info = copy_session_info_serverinfo_guest(mem_ctx, guest_info, guest_server_info);
1149 return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1152 NTSTATUS make_session_info_guest(TALLOC_CTX *mem_ctx,
1153 struct auth_session_info **session_info)
1155 *session_info = copy_session_info(mem_ctx, guest_info);
1156 return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1159 static struct auth_session_info *system_info = NULL;
1161 NTSTATUS init_system_session_info(void)
1163 if (system_info != NULL)
1164 return NT_STATUS_OK;
1166 return make_new_session_info_system(NULL, &system_info);
1169 NTSTATUS make_session_info_system(TALLOC_CTX *mem_ctx,
1170 struct auth_session_info **session_info)
1172 if (system_info == NULL) return NT_STATUS_UNSUCCESSFUL;
1173 *session_info = copy_session_info(mem_ctx, system_info);
1174 return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1177 const struct auth_session_info *get_session_info_system(void)
1179 return system_info;
1182 /***************************************************************************
1183 Purely internal function for make_server_info_info3
1184 ***************************************************************************/
1186 static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain,
1187 const char *username, char **found_username,
1188 struct passwd **pwd,
1189 bool *username_was_mapped)
1191 char *orig_dom_user = NULL;
1192 char *dom_user = NULL;
1193 char *lower_username = NULL;
1194 char *real_username = NULL;
1195 struct passwd *passwd;
1197 lower_username = talloc_strdup(mem_ctx, username);
1198 if (!lower_username) {
1199 return NT_STATUS_NO_MEMORY;
1201 if (!strlower_m( lower_username )) {
1202 return NT_STATUS_INVALID_PARAMETER;
1205 orig_dom_user = talloc_asprintf(mem_ctx,
1206 "%s%c%s",
1207 domain,
1208 *lp_winbind_separator(),
1209 lower_username);
1210 if (!orig_dom_user) {
1211 return NT_STATUS_NO_MEMORY;
1214 /* Get the passwd struct. Try to create the account if necessary. */
1216 *username_was_mapped = map_username(mem_ctx, orig_dom_user, &dom_user);
1217 if (!dom_user) {
1218 return NT_STATUS_NO_MEMORY;
1221 passwd = smb_getpwnam(mem_ctx, dom_user, &real_username, true );
1222 if (!passwd) {
1223 DEBUG(3, ("Failed to find authenticated user %s via "
1224 "getpwnam(), denying access.\n", dom_user));
1225 return NT_STATUS_NO_SUCH_USER;
1228 if (!real_username) {
1229 return NT_STATUS_NO_MEMORY;
1232 *pwd = passwd;
1234 /* This is pointless -- there is no support for differing
1235 unix and windows names. Make sure to always store the
1236 one we actually looked up and succeeded. Have I mentioned
1237 why I hate the 'winbind use default domain' parameter?
1238 --jerry */
1240 *found_username = talloc_strdup( mem_ctx, real_username );
1242 return NT_STATUS_OK;
1245 /****************************************************************************
1246 Wrapper to allow the getpwnam() call to strip the domain name and
1247 try again in case a local UNIX user is already there. Also run through
1248 the username if we fallback to the username only.
1249 ****************************************************************************/
1251 struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, const char *domuser,
1252 char **p_save_username, bool create )
1254 struct passwd *pw = NULL;
1255 char *p = NULL;
1256 char *username = NULL;
1258 /* we only save a copy of the username it has been mangled
1259 by winbindd use default domain */
1260 *p_save_username = NULL;
1262 /* don't call map_username() here since it has to be done higher
1263 up the stack so we don't call it multiple times */
1265 username = talloc_strdup(mem_ctx, domuser);
1266 if (!username) {
1267 return NULL;
1270 p = strchr_m( username, *lp_winbind_separator() );
1272 /* code for a DOMAIN\user string */
1274 if ( p ) {
1275 pw = Get_Pwnam_alloc( mem_ctx, domuser );
1276 if ( pw ) {
1277 /* make sure we get the case of the username correct */
1278 /* work around 'winbind use default domain = yes' */
1280 if ( lp_winbind_use_default_domain() &&
1281 !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
1282 char *domain;
1284 /* split the domain and username into 2 strings */
1285 *p = '\0';
1286 domain = username;
1288 *p_save_username = talloc_asprintf(mem_ctx,
1289 "%s%c%s",
1290 domain,
1291 *lp_winbind_separator(),
1292 pw->pw_name);
1293 if (!*p_save_username) {
1294 TALLOC_FREE(pw);
1295 return NULL;
1297 } else {
1298 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1301 /* whew -- done! */
1302 return pw;
1305 /* setup for lookup of just the username */
1306 /* remember that p and username are overlapping memory */
1308 p++;
1309 username = talloc_strdup(mem_ctx, p);
1310 if (!username) {
1311 return NULL;
1315 /* just lookup a plain username */
1317 pw = Get_Pwnam_alloc(mem_ctx, username);
1319 /* Create local user if requested but only if winbindd
1320 is not running. We need to protect against cases
1321 where winbindd is failing and then prematurely
1322 creating users in /etc/passwd */
1324 if ( !pw && create && !winbind_ping() ) {
1325 /* Don't add a machine account. */
1326 if (username[strlen(username)-1] == '$')
1327 return NULL;
1329 _smb_create_user(NULL, username, NULL);
1330 pw = Get_Pwnam_alloc(mem_ctx, username);
1333 /* one last check for a valid passwd struct */
1335 if (pw) {
1336 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1338 return pw;
1341 /***************************************************************************
1342 Make a server_info struct from the info3 returned by a domain logon
1343 ***************************************************************************/
1345 NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
1346 const char *sent_nt_username,
1347 const char *domain,
1348 struct auth_serversupplied_info **server_info,
1349 const struct netr_SamInfo3 *info3)
1351 NTSTATUS nt_status = NT_STATUS_OK;
1352 char *found_username = NULL;
1353 const char *nt_domain;
1354 const char *nt_username;
1355 struct dom_sid user_sid;
1356 struct dom_sid group_sid;
1357 bool username_was_mapped;
1358 struct passwd *pwd;
1359 struct auth_serversupplied_info *result;
1360 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1363 Here is where we should check the list of
1364 trusted domains, and verify that the SID
1365 matches.
1368 if (!sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid)) {
1369 nt_status = NT_STATUS_INVALID_PARAMETER;
1370 goto out;
1373 if (!sid_compose(&group_sid, info3->base.domain_sid,
1374 info3->base.primary_gid)) {
1375 nt_status = NT_STATUS_INVALID_PARAMETER;
1376 goto out;
1379 nt_username = talloc_strdup(tmp_ctx, info3->base.account_name.string);
1380 if (!nt_username) {
1381 /* If the server didn't give us one, just use the one we sent
1382 * them */
1383 nt_username = sent_nt_username;
1386 nt_domain = talloc_strdup(mem_ctx, info3->base.logon_domain.string);
1387 if (!nt_domain) {
1388 /* If the server didn't give us one, just use the one we sent
1389 * them */
1390 nt_domain = domain;
1393 /* If getpwnam() fails try the add user script (2.2.x behavior).
1395 We use the _unmapped_ username here in an attempt to provide
1396 consistent username mapping behavior between kerberos and NTLM[SSP]
1397 authentication in domain mode security. I.E. Username mapping
1398 should be applied to the fully qualified username
1399 (e.g. DOMAIN\user) and not just the login name. Yes this means we
1400 called map_username() unnecessarily in make_user_info_map() but
1401 that is how the current code is designed. Making the change here
1402 is the least disruptive place. -- jerry */
1404 /* this call will try to create the user if necessary */
1406 nt_status = check_account(tmp_ctx,
1407 nt_domain,
1408 nt_username,
1409 &found_username,
1410 &pwd,
1411 &username_was_mapped);
1413 if (!NT_STATUS_IS_OK(nt_status)) {
1414 /* Handle 'map to guest = Bad Uid */
1415 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) &&
1416 (lp_security() == SEC_ADS || lp_security() == SEC_DOMAIN) &&
1417 lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID) {
1418 DBG_NOTICE("Try to map %s to guest account",
1419 nt_username);
1420 nt_status = make_server_info_guest(tmp_ctx, &result);
1421 if (NT_STATUS_IS_OK(nt_status)) {
1422 *server_info = talloc_move(mem_ctx, &result);
1425 goto out;
1428 result = make_server_info(tmp_ctx);
1429 if (result == NULL) {
1430 DEBUG(4, ("make_server_info failed!\n"));
1431 nt_status = NT_STATUS_NO_MEMORY;
1432 goto out;
1435 result->unix_name = talloc_strdup(result, found_username);
1437 /* copy in the info3 */
1438 result->info3 = copy_netr_SamInfo3(result, info3);
1439 if (result->info3 == NULL) {
1440 nt_status = NT_STATUS_NO_MEMORY;
1441 goto out;
1444 /* Fill in the unix info we found on the way */
1446 result->utok.uid = pwd->pw_uid;
1447 result->utok.gid = pwd->pw_gid;
1449 /* ensure we are never given NULL session keys */
1451 if (all_zero(info3->base.key.key, sizeof(info3->base.key.key))) {
1452 result->session_key = data_blob_null;
1453 } else {
1454 result->session_key = data_blob_talloc(
1455 result, info3->base.key.key,
1456 sizeof(info3->base.key.key));
1459 if (all_zero(info3->base.LMSessKey.key,
1460 sizeof(info3->base.LMSessKey.key))) {
1461 result->lm_session_key = data_blob_null;
1462 } else {
1463 result->lm_session_key = data_blob_talloc(
1464 result, info3->base.LMSessKey.key,
1465 sizeof(info3->base.LMSessKey.key));
1468 result->nss_token |= username_was_mapped;
1470 result->guest = (info3->base.user_flags & NETLOGON_GUEST);
1472 *server_info = talloc_move(mem_ctx, &result);
1474 nt_status = NT_STATUS_OK;
1475 out:
1476 talloc_free(tmp_ctx);
1478 return nt_status;
1481 /*****************************************************************************
1482 Make a server_info struct from the wbcAuthUserInfo returned by a domain logon
1483 ******************************************************************************/
1485 NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx,
1486 const char *sent_nt_username,
1487 const char *domain,
1488 const struct wbcAuthUserInfo *info,
1489 struct auth_serversupplied_info **server_info)
1491 struct netr_SamInfo3 info3;
1492 struct netr_SamInfo6 *info6;
1494 info6 = wbcAuthUserInfo_to_netr_SamInfo6(mem_ctx, info);
1495 if (!info6) {
1496 return NT_STATUS_NO_MEMORY;
1499 info3.base = info6->base;
1500 info3.sidcount = info6->sidcount;
1501 info3.sids = info6->sids;
1503 return make_server_info_info3(mem_ctx,
1504 sent_nt_username, domain,
1505 server_info, &info3);
1509 * Verify whether or not given domain is trusted.
1511 * @param domain_name name of the domain to be verified
1512 * @return true if domain is one of the trusted ones or
1513 * false if otherwise
1516 bool is_trusted_domain(const char* dom_name)
1518 struct dom_sid trustdom_sid;
1519 bool ret;
1521 /* no trusted domains for a standalone server */
1523 if ( lp_server_role() == ROLE_STANDALONE )
1524 return false;
1526 if (dom_name == NULL || dom_name[0] == '\0') {
1527 return false;
1530 if (strequal(dom_name, get_global_sam_name())) {
1531 return false;
1534 /* if we are a DC, then check for a direct trust relationships */
1536 if ( IS_DC ) {
1537 become_root();
1538 DEBUG (5,("is_trusted_domain: Checking for domain trust with "
1539 "[%s]\n", dom_name ));
1540 ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL);
1541 unbecome_root();
1542 if (ret)
1543 return true;
1545 else {
1546 wbcErr result;
1548 /* If winbind is around, ask it */
1550 result = wb_is_trusted_domain(dom_name);
1552 if (result == WBC_ERR_SUCCESS) {
1553 return true;
1556 if (result == WBC_ERR_DOMAIN_NOT_FOUND) {
1557 /* winbind could not find the domain */
1558 return false;
1561 DEBUG(10, ("wb_is_trusted_domain returned error: %s\n",
1562 wbcErrorString(result)));
1564 /* The only other possible result is that winbind is not up
1565 and running. We need to update the trustdom_cache
1566 ourselves */
1568 update_trustdom_cache();
1571 /* now the trustdom cache should be available a DC could still
1572 * have a transitive trust so fall back to the cache of trusted
1573 * domains (like a domain member would use */
1575 if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) {
1576 return true;
1579 return false;
1585 on a logon error possibly map the error to success if "map to guest"
1586 is set approriately
1588 NTSTATUS do_map_to_guest_server_info(TALLOC_CTX *mem_ctx,
1589 NTSTATUS status,
1590 const char *user,
1591 const char *domain,
1592 struct auth_serversupplied_info **server_info)
1594 user = user ? user : "";
1595 domain = domain ? domain : "";
1597 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
1598 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
1599 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
1600 DEBUG(3,("No such user %s [%s] - using guest account\n",
1601 user, domain));
1602 return make_server_info_guest(mem_ctx, server_info);
1604 } else if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1605 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
1606 DEBUG(3,("Registered username %s for guest access\n",
1607 user));
1608 return make_server_info_guest(mem_ctx, server_info);
1612 return status;
1616 Extract session key from a session info and return it in a blob
1617 if intent is KEY_USE_16BYTES, truncate it to 16 bytes
1619 See sections 3.2.4.15 and 3.3.4.2 of MS-SMB
1620 Also see https://lists.samba.org/archive/cifs-protocol/2012-January/002265.html for details
1622 Note that returned session_key is referencing the original key, it is supposed to be
1623 short-lived. If original session_info->session_key is gone, the reference will be broken.
1625 NTSTATUS session_extract_session_key(const struct auth_session_info *session_info, DATA_BLOB *session_key, enum session_key_use_intent intent)
1628 if (session_key == NULL || session_info == NULL) {
1629 return NT_STATUS_INVALID_PARAMETER;
1632 if (session_info->session_key.length == 0) {
1633 return NT_STATUS_NO_USER_SESSION_KEY;
1636 *session_key = session_info->session_key;
1637 if (intent == KEY_USE_16BYTES) {
1638 session_key->length = MIN(session_info->session_key.length, 16);
1640 return NT_STATUS_OK;