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/>.
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"
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"
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();
53 add_script = lp_add_user_script(ctx);
54 if (!add_script || !*add_script) {
57 add_script = talloc_all_string_sub(ctx,
65 add_script = talloc_all_string_sub(ctx,
74 add_script = talloc_all_string_sub(ctx,
82 ret = smbrun(add_script, NULL, NULL);
85 ("smb_create_user: Running the command `%s' gave %d\n",
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,
97 const char *client_domain,
98 const char *workstation_name,
99 const struct tsocket_address *remote_address,
100 const struct tsocket_address *local_address,
101 const char *service_description,
102 const DATA_BLOB *lm_pwd,
103 const DATA_BLOB *nt_pwd,
104 const struct samr_Password *lm_interactive_pwd,
105 const struct samr_Password *nt_interactive_pwd,
106 const char *plaintext,
107 enum auth_password_state password_state)
112 char *internal_username = NULL;
113 bool upn_form = false;
115 if (client_domain[0] == '\0' && strchr(smb_name, '@')) {
119 was_mapped = map_username(talloc_tos(), smb_name, &internal_username);
120 if (!internal_username) {
121 return NT_STATUS_NO_MEMORY;
124 DEBUG(5, ("Mapping user [%s]\\[%s] from workstation [%s]\n",
125 client_domain, smb_name, workstation_name));
127 domain = client_domain;
129 /* If you connect to a Windows domain member using a bogus domain name,
130 * the Windows box will map the BOGUS\user to SAMNAME\user. Thus, if
131 * the Windows box is a DC the name will become DOMAIN\user and be
132 * authenticated against AD, if the Windows box is a member server but
133 * not a DC the name will become WORKSTATION\user. A standalone
134 * non-domain member box will also map to WORKSTATION\user.
135 * This also deals with the client passing in a "" domain */
137 if (!upn_form && !is_trusted_domain(domain) &&
138 !strequal(domain, my_sam_name()) &&
139 !strequal(domain, get_global_sam_name())) {
140 if (lp_map_untrusted_to_domain())
141 domain = my_sam_name();
143 domain = get_global_sam_name();
144 DEBUG(5, ("Mapped domain from [%s] to [%s] for user [%s] from "
145 "workstation [%s]\n",
146 client_domain, domain, smb_name, workstation_name));
149 /* We know that the given domain is trusted (and we are allowing them),
150 * it is our global SAM name, or for legacy behavior it is our
151 * primary domain name */
153 result = make_user_info(mem_ctx, user_info, smb_name, internal_username,
154 client_domain, domain, workstation_name,
155 remote_address, local_address,
156 service_description, lm_pwd, nt_pwd,
157 lm_interactive_pwd, nt_interactive_pwd,
158 plaintext, password_state);
159 if (NT_STATUS_IS_OK(result)) {
160 /* We have tried mapping */
161 (*user_info)->mapped_state = true;
162 /* did we actually map the user to a different name? */
163 (*user_info)->was_mapped = was_mapped;
168 /****************************************************************************
169 Create an auth_usersupplied_data, making the DATA_BLOBs here.
170 Decrypt and encrypt the passwords.
171 ****************************************************************************/
173 bool make_user_info_netlogon_network(TALLOC_CTX *mem_ctx,
174 struct auth_usersupplied_info **user_info,
175 const char *smb_name,
176 const char *client_domain,
177 const char *workstation_name,
178 const struct tsocket_address *remote_address,
179 const struct tsocket_address *local_address,
180 uint32_t logon_parameters,
181 const uchar *lm_network_pwd,
183 const uchar *nt_network_pwd,
188 DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
189 DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
191 status = make_user_info_map(mem_ctx, user_info,
192 smb_name, client_domain,
197 lm_pwd_len ? &lm_blob : NULL,
198 nt_pwd_len ? &nt_blob : NULL,
200 AUTH_PASSWORD_RESPONSE);
202 if (NT_STATUS_IS_OK(status)) {
203 (*user_info)->logon_parameters = logon_parameters;
205 ret = NT_STATUS_IS_OK(status) ? true : false;
207 data_blob_free(&lm_blob);
208 data_blob_free(&nt_blob);
212 /****************************************************************************
213 Create an auth_usersupplied_data, making the DATA_BLOBs here.
214 Decrypt and encrypt the passwords.
215 ****************************************************************************/
217 bool make_user_info_netlogon_interactive(TALLOC_CTX *mem_ctx,
218 struct auth_usersupplied_info **user_info,
219 const char *smb_name,
220 const char *client_domain,
221 const char *workstation_name,
222 const struct tsocket_address *remote_address,
223 const struct tsocket_address *local_address,
224 uint32_t logon_parameters,
226 const uchar lm_interactive_pwd[16],
227 const uchar nt_interactive_pwd[16])
229 struct samr_Password lm_pwd;
230 struct samr_Password nt_pwd;
231 unsigned char local_lm_response[24];
232 unsigned char local_nt_response[24];
234 if (lm_interactive_pwd)
235 memcpy(lm_pwd.hash, lm_interactive_pwd, sizeof(lm_pwd.hash));
237 if (nt_interactive_pwd)
238 memcpy(nt_pwd.hash, nt_interactive_pwd, sizeof(nt_pwd.hash));
240 if (lm_interactive_pwd)
241 SMBOWFencrypt(lm_pwd.hash, chal,
244 if (nt_interactive_pwd)
245 SMBOWFencrypt(nt_pwd.hash, chal,
251 DATA_BLOB local_lm_blob = data_blob_null;
252 DATA_BLOB local_nt_blob = data_blob_null;
254 if (lm_interactive_pwd) {
255 local_lm_blob = data_blob(local_lm_response,
256 sizeof(local_lm_response));
259 if (nt_interactive_pwd) {
260 local_nt_blob = data_blob(local_nt_response,
261 sizeof(local_nt_response));
264 nt_status = make_user_info_map(
267 smb_name, client_domain, workstation_name,
271 lm_interactive_pwd ? &local_lm_blob : NULL,
272 nt_interactive_pwd ? &local_nt_blob : NULL,
273 lm_interactive_pwd ? &lm_pwd : NULL,
274 nt_interactive_pwd ? &nt_pwd : NULL,
275 NULL, AUTH_PASSWORD_HASH);
277 if (NT_STATUS_IS_OK(nt_status)) {
278 (*user_info)->logon_parameters = logon_parameters;
281 ret = NT_STATUS_IS_OK(nt_status) ? true : false;
282 data_blob_free(&local_lm_blob);
283 data_blob_free(&local_nt_blob);
289 /****************************************************************************
290 Create an auth_usersupplied_data structure
291 ****************************************************************************/
293 bool make_user_info_for_reply(TALLOC_CTX *mem_ctx,
294 struct auth_usersupplied_info **user_info,
295 const char *smb_name,
296 const char *client_domain,
297 const struct tsocket_address *remote_address,
298 const struct tsocket_address *local_address,
299 const char *service_description,
300 const uint8_t chal[8],
301 DATA_BLOB plaintext_password)
304 DATA_BLOB local_lm_blob;
305 DATA_BLOB local_nt_blob;
306 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
307 char *plaintext_password_string;
309 * Not encrypted - do so.
312 DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted "
314 if (plaintext_password.data && plaintext_password.length) {
315 unsigned char local_lm_response[24];
317 #ifdef DEBUG_PASSWORD
318 DEBUG(10,("Unencrypted password (len %d):\n",
319 (int)plaintext_password.length));
320 dump_data(100, plaintext_password.data,
321 plaintext_password.length);
324 SMBencrypt( (const char *)plaintext_password.data,
325 (const uchar*)chal, local_lm_response);
326 local_lm_blob = data_blob(local_lm_response, 24);
328 /* We can't do an NT hash here, as the password needs to be
330 local_nt_blob = data_blob_null;
332 local_lm_blob = data_blob_null;
333 local_nt_blob = data_blob_null;
336 plaintext_password_string = talloc_strndup(talloc_tos(),
337 (const char *)plaintext_password.data,
338 plaintext_password.length);
339 if (!plaintext_password_string) {
343 ret = make_user_info(mem_ctx,
344 user_info, smb_name, smb_name, client_domain, client_domain,
345 get_remote_machine_name(),
349 local_lm_blob.data ? &local_lm_blob : NULL,
350 local_nt_blob.data ? &local_nt_blob : NULL,
352 plaintext_password_string,
353 AUTH_PASSWORD_PLAIN);
355 if (plaintext_password_string) {
356 memset(plaintext_password_string, '\0', strlen(plaintext_password_string));
357 talloc_free(plaintext_password_string);
360 data_blob_free(&local_lm_blob);
361 return NT_STATUS_IS_OK(ret) ? true : false;
364 /****************************************************************************
365 Create an auth_usersupplied_data structure
366 ****************************************************************************/
368 NTSTATUS make_user_info_for_reply_enc(TALLOC_CTX *mem_ctx,
369 struct auth_usersupplied_info **user_info,
370 const char *smb_name,
371 const char *client_domain,
372 const struct tsocket_address *remote_address,
373 const struct tsocket_address *local_address,
374 const char *service_description,
375 DATA_BLOB lm_resp, DATA_BLOB nt_resp)
377 bool allow_raw = lp_raw_ntlmv2_auth();
379 if (!allow_raw && nt_resp.length >= 48) {
381 * NTLMv2_RESPONSE has at least 48 bytes
382 * and should only be supported via NTLMSSP.
384 DEBUG(2,("Rejecting raw NTLMv2 authentication with "
385 "user [%s\\%s] from[%s]\n",
386 client_domain, smb_name,
387 tsocket_address_string(remote_address, mem_ctx)));
388 return NT_STATUS_INVALID_PARAMETER;
391 return make_user_info(mem_ctx,
392 user_info, smb_name, smb_name,
393 client_domain, client_domain,
394 get_remote_machine_name(),
398 lm_resp.data && (lm_resp.length > 0) ? &lm_resp : NULL,
399 nt_resp.data && (nt_resp.length > 0) ? &nt_resp : NULL,
401 AUTH_PASSWORD_RESPONSE);
404 /****************************************************************************
405 Create a guest user_info blob, for anonymous authentication.
406 ****************************************************************************/
408 bool make_user_info_guest(TALLOC_CTX *mem_ctx,
409 const struct tsocket_address *remote_address,
410 const struct tsocket_address *local_address,
411 const char *service_description,
412 struct auth_usersupplied_info **user_info)
416 nt_status = make_user_info(mem_ctx,
427 AUTH_PASSWORD_RESPONSE);
429 return NT_STATUS_IS_OK(nt_status) ? true : false;
432 static NTSTATUS log_nt_token(struct security_token *token)
434 TALLOC_CTX *frame = talloc_stackframe();
439 if ((lp_log_nt_token_command(frame) == NULL) ||
440 (strlen(lp_log_nt_token_command(frame)) == 0)) {
445 group_sidstr = talloc_strdup(frame, "");
446 for (i=1; i<token->num_sids; i++) {
447 group_sidstr = talloc_asprintf(
448 frame, "%s %s", group_sidstr,
449 sid_string_talloc(frame, &token->sids[i]));
452 command = talloc_string_sub(
453 frame, lp_log_nt_token_command(frame),
454 "%s", sid_string_talloc(frame, &token->sids[0]));
455 command = talloc_string_sub(frame, command, "%t", group_sidstr);
457 if (command == NULL) {
459 return NT_STATUS_NO_MEMORY;
462 DEBUG(8, ("running command: [%s]\n", command));
463 if (smbrun(command, NULL, NULL) != 0) {
464 DEBUG(0, ("Could not log NT token\n"));
466 return NT_STATUS_ACCESS_DENIED;
474 * Create the token to use from server_info->info3 and
475 * server_info->sids (the info3/sam groups). Find the unix gids.
478 NTSTATUS create_local_token(TALLOC_CTX *mem_ctx,
479 const struct auth_serversupplied_info *server_info,
480 DATA_BLOB *session_key,
481 const char *smb_username, /* for ->sanitized_username, for %U subs */
482 struct auth_session_info **session_info_out)
484 struct security_token *t;
487 struct dom_sid tmp_sid;
488 struct auth_session_info *session_info;
492 /* Ensure we can't possible take a code path leading to a
495 return NT_STATUS_LOGON_FAILURE;
498 session_info = talloc_zero(mem_ctx, struct auth_session_info);
500 return NT_STATUS_NO_MEMORY;
503 session_info->unix_token = talloc_zero(session_info, struct security_unix_token);
504 if (!session_info->unix_token) {
505 TALLOC_FREE(session_info);
506 return NT_STATUS_NO_MEMORY;
509 session_info->unix_token->uid = server_info->utok.uid;
510 session_info->unix_token->gid = server_info->utok.gid;
512 session_info->unix_info = talloc_zero(session_info, struct auth_user_info_unix);
513 if (!session_info->unix_info) {
514 TALLOC_FREE(session_info);
515 return NT_STATUS_NO_MEMORY;
518 session_info->unix_info->unix_name = talloc_strdup(session_info, server_info->unix_name);
519 if (!session_info->unix_info->unix_name) {
520 TALLOC_FREE(session_info);
521 return NT_STATUS_NO_MEMORY;
524 /* This is a potentially untrusted username for use in %U */
525 alpha_strcpy(tmp, smb_username, ". _-$", sizeof(tmp));
526 session_info->unix_info->sanitized_username =
527 talloc_strdup(session_info->unix_info, tmp);
530 data_blob_free(&session_info->session_key);
531 session_info->session_key = data_blob_talloc(session_info,
533 session_key->length);
534 if (!session_info->session_key.data && session_key->length) {
535 return NT_STATUS_NO_MEMORY;
538 session_info->session_key = data_blob_talloc( session_info, server_info->session_key.data,
539 server_info->session_key.length);
542 /* We need to populate session_info->info with the information found in server_info->info3 */
543 status = make_user_info_SamBaseInfo(session_info, "", &server_info->info3->base,
544 server_info->guest == false,
545 &session_info->info);
546 if (!NT_STATUS_IS_OK(status)) {
547 DEBUG(0, ("conversion of info3 into auth_user_info failed!\n"));
548 TALLOC_FREE(session_info);
552 if (server_info->security_token) {
553 /* Just copy the token, it has already been finalised
554 * (nasty hack to support a cached guest/system session_info
557 session_info->security_token = dup_nt_token(session_info, server_info->security_token);
558 if (!session_info->security_token) {
559 TALLOC_FREE(session_info);
560 return NT_STATUS_NO_MEMORY;
563 session_info->unix_token->ngroups = server_info->utok.ngroups;
564 if (server_info->utok.ngroups != 0) {
565 session_info->unix_token->groups = (gid_t *)talloc_memdup(
566 session_info->unix_token, server_info->utok.groups,
567 sizeof(gid_t)*session_info->unix_token->ngroups);
569 session_info->unix_token->groups = NULL;
572 *session_info_out = session_info;
577 * If winbind is not around, we can not make much use of the SIDs the
578 * domain controller provided us with. Likewise if the user name was
579 * mapped to some local unix user.
582 if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) ||
583 (server_info->nss_token)) {
584 char *found_username = NULL;
585 status = create_token_from_username(session_info,
586 server_info->unix_name,
588 &session_info->unix_token->uid,
589 &session_info->unix_token->gid,
591 &session_info->security_token);
592 if (NT_STATUS_IS_OK(status)) {
593 session_info->unix_info->unix_name = found_username;
596 status = create_local_nt_token_from_info3(session_info,
600 &session_info->security_token);
603 if (!NT_STATUS_IS_OK(status)) {
607 /* Convert the SIDs to gids. */
609 session_info->unix_token->ngroups = 0;
610 session_info->unix_token->groups = NULL;
612 t = session_info->security_token;
614 ids = talloc_array(talloc_tos(), struct unixid,
617 return NT_STATUS_NO_MEMORY;
620 if (!sids_to_unixids(t->sids, t->num_sids, ids)) {
622 return NT_STATUS_NO_MEMORY;
625 for (i=0; i<t->num_sids; i++) {
627 if (i == 0 && ids[i].type != ID_TYPE_BOTH) {
631 if (ids[i].type != ID_TYPE_GID &&
632 ids[i].type != ID_TYPE_BOTH) {
633 DEBUG(10, ("Could not convert SID %s to gid, "
635 sid_string_dbg(&t->sids[i])));
638 if (!add_gid_to_array_unique(session_info, ids[i].id,
639 &session_info->unix_token->groups,
640 &session_info->unix_token->ngroups)) {
641 return NT_STATUS_NO_MEMORY;
646 * Add the "Unix Group" SID for each gid to catch mapped groups
647 * and their Unix equivalent. This is to solve the backwards
648 * compatibility problem of 'valid users = +ntadmin' where
649 * ntadmin has been paired with "Domain Admins" in the group
650 * mapping table. Otherwise smb.conf would need to be changed
651 * to 'valid user = "Domain Admins"'. --jerry
653 * For consistency we also add the "Unix User" SID,
654 * so that the complete unix token is represented within
658 uid_to_unix_users_sid(session_info->unix_token->uid, &tmp_sid);
660 add_sid_to_array_unique(session_info->security_token, &tmp_sid,
661 &session_info->security_token->sids,
662 &session_info->security_token->num_sids);
664 for ( i=0; i<session_info->unix_token->ngroups; i++ ) {
665 gid_to_unix_groups_sid(session_info->unix_token->groups[i], &tmp_sid);
666 add_sid_to_array_unique(session_info->security_token, &tmp_sid,
667 &session_info->security_token->sids,
668 &session_info->security_token->num_sids);
671 security_token_debug(DBGC_AUTH, 10, session_info->security_token);
672 debug_unix_user_token(DBGC_AUTH, 10,
673 session_info->unix_token->uid,
674 session_info->unix_token->gid,
675 session_info->unix_token->ngroups,
676 session_info->unix_token->groups);
678 status = log_nt_token(session_info->security_token);
679 if (!NT_STATUS_IS_OK(status)) {
683 *session_info_out = session_info;
687 /***************************************************************************
688 Make (and fill) a server_info struct from a 'struct passwd' by conversion
690 ***************************************************************************/
692 NTSTATUS make_server_info_pw(TALLOC_CTX *mem_ctx,
693 const char *unix_username,
694 const struct passwd *pwd,
695 struct auth_serversupplied_info **server_info)
698 TALLOC_CTX *tmp_ctx = NULL;
699 struct auth_serversupplied_info *result;
701 tmp_ctx = talloc_stackframe();
702 if (tmp_ctx == NULL) {
703 return NT_STATUS_NO_MEMORY;
706 result = make_server_info(tmp_ctx);
707 if (result == NULL) {
708 status = NT_STATUS_NO_MEMORY;
712 status = passwd_to_SamInfo3(result,
717 if (!NT_STATUS_IS_OK(status)) {
721 result->unix_name = talloc_strdup(result, unix_username);
722 if (result->unix_name == NULL) {
723 status = NT_STATUS_NO_MEMORY;
727 result->utok.uid = pwd->pw_uid;
728 result->utok.gid = pwd->pw_gid;
730 *server_info = talloc_steal(mem_ctx, result);
731 status = NT_STATUS_OK;
733 talloc_free(tmp_ctx);
738 static NTSTATUS get_system_info3(TALLOC_CTX *mem_ctx,
739 struct netr_SamInfo3 *info3)
743 /* Set account name */
744 init_lsa_String(&info3->base.account_name, "SYSTEM");
746 /* Set domain name */
747 init_lsa_StringLarge(&info3->base.logon_domain, "NT AUTHORITY");
750 status = dom_sid_split_rid(mem_ctx, &global_sid_System,
751 &info3->base.domain_sid,
753 if (!NT_STATUS_IS_OK(status)) {
757 /* Primary gid is the same */
758 info3->base.primary_gid = info3->base.rid;
763 static NTSTATUS get_guest_info3(TALLOC_CTX *mem_ctx,
764 struct netr_SamInfo3 *info3)
766 const char *guest_account = lp_guest_account();
767 struct dom_sid domain_sid;
771 pwd = Get_Pwnam_alloc(mem_ctx, guest_account);
773 DEBUG(0,("SamInfo3_for_guest: Unable to locate guest "
774 "account [%s]!\n", guest_account));
775 return NT_STATUS_NO_SUCH_USER;
778 /* Set account name */
779 tmp = talloc_strdup(mem_ctx, pwd->pw_name);
781 return NT_STATUS_NO_MEMORY;
783 init_lsa_String(&info3->base.account_name, tmp);
785 /* Set domain name */
786 tmp = talloc_strdup(mem_ctx, get_global_sam_name());
788 return NT_STATUS_NO_MEMORY;
790 init_lsa_StringLarge(&info3->base.logon_domain, tmp);
793 sid_copy(&domain_sid, get_global_sam_sid());
795 info3->base.domain_sid = dom_sid_dup(mem_ctx, &domain_sid);
796 if (info3->base.domain_sid == NULL) {
797 return NT_STATUS_NO_MEMORY;
801 info3->base.rid = DOMAIN_RID_GUEST;
804 info3->base.primary_gid = DOMAIN_RID_GUESTS;
807 info3->base.user_flags = NETLOGON_GUEST;
813 /***************************************************************************
814 Make (and fill) a user_info struct for a guest login.
815 This *must* succeed for smbd to start. If there is no mapping entry for
816 the guest gid, then create one.
818 The resulting structure is a 'session_info' because
819 create_local_token() has already been called on it. This is quite
820 nasty, as the auth subsystem isn't expect this, but the behavior is
822 ***************************************************************************/
824 static NTSTATUS make_new_session_info_guest(struct auth_session_info **session_info, struct auth_serversupplied_info **server_info)
826 const char *guest_account = lp_guest_account();
827 const char *domain = lp_netbios_name();
828 struct netr_SamInfo3 info3;
832 tmp_ctx = talloc_stackframe();
833 if (tmp_ctx == NULL) {
834 return NT_STATUS_NO_MEMORY;
839 status = get_guest_info3(tmp_ctx, &info3);
840 if (!NT_STATUS_IS_OK(status)) {
841 DEBUG(0, ("get_guest_info3 failed with %s\n",
846 status = make_server_info_info3(tmp_ctx,
851 if (!NT_STATUS_IS_OK(status)) {
852 DEBUG(0, ("make_server_info_info3 failed with %s\n",
857 (*server_info)->guest = true;
859 /* This should not be done here (we should produce a server
860 * info, and later construct a session info from it), but for
861 * now this does not change the previous behavior */
862 status = create_local_token(tmp_ctx, *server_info, NULL,
863 (*server_info)->info3->base.account_name.string,
865 if (!NT_STATUS_IS_OK(status)) {
866 DEBUG(0, ("create_local_token failed: %s\n",
870 talloc_steal(NULL, *session_info);
871 talloc_steal(NULL, *server_info);
873 /* annoying, but the Guest really does have a session key, and it is
875 (*session_info)->session_key = data_blob_talloc_zero(NULL, 16);
877 status = NT_STATUS_OK;
879 TALLOC_FREE(tmp_ctx);
883 /***************************************************************************
884 Make (and fill) a auth_session_info struct for a system user login.
885 This *must* succeed for smbd to start.
886 ***************************************************************************/
888 static NTSTATUS make_new_session_info_system(TALLOC_CTX *mem_ctx,
889 struct auth_session_info **session_info)
892 struct auth_serversupplied_info *server_info;
895 tmp_ctx = talloc_stackframe();
896 if (tmp_ctx == NULL) {
897 return NT_STATUS_NO_MEMORY;
900 server_info = make_server_info(tmp_ctx);
902 status = NT_STATUS_NO_MEMORY;
903 DEBUG(0, ("failed making server_info\n"));
907 server_info->info3 = talloc_zero(server_info, struct netr_SamInfo3);
908 if (!server_info->info3) {
909 status = NT_STATUS_NO_MEMORY;
910 DEBUG(0, ("talloc failed setting info3\n"));
914 status = get_system_info3(server_info, server_info->info3);
915 if (!NT_STATUS_IS_OK(status)) {
916 DEBUG(0, ("Failed creating system info3 with %s\n",
921 server_info->utok.uid = sec_initial_uid();
922 server_info->utok.gid = sec_initial_gid();
923 server_info->unix_name = talloc_asprintf(server_info,
924 "NT AUTHORITY%cSYSTEM",
925 *lp_winbind_separator());
927 if (!server_info->unix_name) {
928 status = NT_STATUS_NO_MEMORY;
929 DEBUG(0, ("talloc_asprintf failed setting unix_name\n"));
933 server_info->security_token = talloc_zero(server_info, struct security_token);
934 if (!server_info->security_token) {
935 status = NT_STATUS_NO_MEMORY;
936 DEBUG(0, ("talloc failed setting security token\n"));
940 status = add_sid_to_array_unique(server_info->security_token->sids,
942 &server_info->security_token->sids,
943 &server_info->security_token->num_sids);
944 if (!NT_STATUS_IS_OK(status)) {
948 /* SYSTEM has all privilages */
949 server_info->security_token->privilege_mask = ~0;
951 /* Now turn the server_info into a session_info with the full token etc */
952 status = create_local_token(mem_ctx, server_info, NULL, "SYSTEM", session_info);
953 talloc_free(server_info);
955 if (!NT_STATUS_IS_OK(status)) {
956 DEBUG(0, ("create_local_token failed: %s\n",
961 talloc_steal(mem_ctx, *session_info);
964 TALLOC_FREE(tmp_ctx);
968 /****************************************************************************
969 Fake a auth_session_info just from a username (as a
970 session_info structure, with create_local_token() already called on
972 ****************************************************************************/
974 NTSTATUS make_session_info_from_username(TALLOC_CTX *mem_ctx,
975 const char *username,
977 struct auth_session_info **session_info)
981 struct auth_serversupplied_info *result;
984 tmp_ctx = talloc_stackframe();
985 if (tmp_ctx == NULL) {
986 return NT_STATUS_NO_MEMORY;
989 pwd = Get_Pwnam_alloc(tmp_ctx, username);
991 status = NT_STATUS_NO_SUCH_USER;
995 status = make_server_info_pw(tmp_ctx, pwd->pw_name, pwd, &result);
996 if (!NT_STATUS_IS_OK(status)) {
1000 result->nss_token = true;
1001 result->guest = is_guest;
1003 /* Now turn the server_info into a session_info with the full token etc */
1004 status = create_local_token(mem_ctx,
1011 talloc_free(tmp_ctx);
1016 /* This function MUST only used to create the cached server_info for
1019 * This is a lossy conversion. Variables known to be lost so far
1022 * - nss_token (not needed because the only read doesn't happen
1023 * for the GUEST user, as this routine populates ->security_token
1025 * - extra (not needed because the guest account must have valid RIDs per the output of get_guest_info3())
1027 * - The 'server_info' parameter allows the missing 'info3' to be copied across.
1029 static struct auth_serversupplied_info *copy_session_info_serverinfo_guest(TALLOC_CTX *mem_ctx,
1030 const struct auth_session_info *src,
1031 struct auth_serversupplied_info *server_info)
1033 struct auth_serversupplied_info *dst;
1035 dst = make_server_info(mem_ctx);
1040 /* This element must be provided to convert back to an auth_serversupplied_info */
1041 SMB_ASSERT(src->unix_info);
1044 dst->system = false;
1046 /* This element must be provided to convert back to an
1047 * auth_serversupplied_info. This needs to be from the
1048 * auth_session_info because the group values in particular
1049 * may change during create_local_token() processing */
1050 SMB_ASSERT(src->unix_token);
1051 dst->utok.uid = src->unix_token->uid;
1052 dst->utok.gid = src->unix_token->gid;
1053 dst->utok.ngroups = src->unix_token->ngroups;
1054 if (src->unix_token->ngroups != 0) {
1055 dst->utok.groups = (gid_t *)talloc_memdup(
1056 dst, src->unix_token->groups,
1057 sizeof(gid_t)*dst->utok.ngroups);
1059 dst->utok.groups = NULL;
1062 /* We must have a security_token as otherwise the lossy
1063 * conversion without nss_token would cause create_local_token
1064 * to take the wrong path */
1065 SMB_ASSERT(src->security_token);
1067 dst->security_token = dup_nt_token(dst, src->security_token);
1068 if (!dst->security_token) {
1073 dst->session_key = data_blob_talloc( dst, src->session_key.data,
1074 src->session_key.length);
1076 /* This is OK because this functions is only used for the
1077 * GUEST account, which has all-zero keys for both values */
1078 dst->lm_session_key = data_blob_talloc(dst, src->session_key.data,
1079 src->session_key.length);
1081 dst->info3 = copy_netr_SamInfo3(dst, server_info->info3);
1087 dst->unix_name = talloc_strdup(dst, src->unix_info->unix_name);
1088 if (!dst->unix_name) {
1096 struct auth_session_info *copy_session_info(TALLOC_CTX *mem_ctx,
1097 const struct auth_session_info *src)
1099 struct auth_session_info *dst;
1101 enum ndr_err_code ndr_err;
1103 ndr_err = ndr_push_struct_blob(
1104 &blob, talloc_tos(), src,
1105 (ndr_push_flags_fn_t)ndr_push_auth_session_info);
1106 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1107 DEBUG(0, ("copy_session_info(): ndr_push_auth_session_info failed: "
1108 "%s\n", ndr_errstr(ndr_err)));
1112 dst = talloc(mem_ctx, struct auth_session_info);
1114 DEBUG(0, ("talloc failed\n"));
1115 TALLOC_FREE(blob.data);
1119 ndr_err = ndr_pull_struct_blob(
1121 (ndr_pull_flags_fn_t)ndr_pull_auth_session_info);
1122 TALLOC_FREE(blob.data);
1124 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1125 DEBUG(0, ("copy_session_info(): ndr_pull_auth_session_info failed: "
1126 "%s\n", ndr_errstr(ndr_err)));
1135 * Set a new session key. Used in the rpc server where we have to override the
1136 * SMB level session key with SystemLibraryDTC
1139 bool session_info_set_session_key(struct auth_session_info *info,
1140 DATA_BLOB session_key)
1142 TALLOC_FREE(info->session_key.data);
1144 info->session_key = data_blob_talloc(
1145 info, session_key.data, session_key.length);
1147 return (info->session_key.data != NULL);
1150 static struct auth_session_info *guest_info = NULL;
1152 static struct auth_serversupplied_info *guest_server_info = NULL;
1154 bool init_guest_info(void)
1156 if (guest_info != NULL)
1159 return NT_STATUS_IS_OK(make_new_session_info_guest(&guest_info, &guest_server_info));
1162 NTSTATUS make_server_info_guest(TALLOC_CTX *mem_ctx,
1163 struct auth_serversupplied_info **server_info)
1165 /* This is trickier than it would appear to need to be because
1166 * we are trying to avoid certain costly operations when the
1167 * structure is converted to a 'auth_session_info' again in
1168 * create_local_token() */
1169 *server_info = copy_session_info_serverinfo_guest(mem_ctx, guest_info, guest_server_info);
1170 return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1173 NTSTATUS make_session_info_guest(TALLOC_CTX *mem_ctx,
1174 struct auth_session_info **session_info)
1176 *session_info = copy_session_info(mem_ctx, guest_info);
1177 return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1180 static struct auth_session_info *system_info = NULL;
1182 NTSTATUS init_system_session_info(void)
1184 if (system_info != NULL)
1185 return NT_STATUS_OK;
1187 return make_new_session_info_system(NULL, &system_info);
1190 NTSTATUS make_session_info_system(TALLOC_CTX *mem_ctx,
1191 struct auth_session_info **session_info)
1193 if (system_info == NULL) return NT_STATUS_UNSUCCESSFUL;
1194 *session_info = copy_session_info(mem_ctx, system_info);
1195 return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1198 const struct auth_session_info *get_session_info_system(void)
1203 /***************************************************************************
1204 Purely internal function for make_server_info_info3
1205 ***************************************************************************/
1207 static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain,
1208 const char *username, char **found_username,
1209 struct passwd **pwd,
1210 bool *username_was_mapped)
1212 char *orig_dom_user = NULL;
1213 char *dom_user = NULL;
1214 char *lower_username = NULL;
1215 char *real_username = NULL;
1216 struct passwd *passwd;
1218 lower_username = talloc_strdup(mem_ctx, username);
1219 if (!lower_username) {
1220 return NT_STATUS_NO_MEMORY;
1222 if (!strlower_m( lower_username )) {
1223 return NT_STATUS_INVALID_PARAMETER;
1226 orig_dom_user = talloc_asprintf(mem_ctx,
1229 *lp_winbind_separator(),
1231 if (!orig_dom_user) {
1232 return NT_STATUS_NO_MEMORY;
1235 /* Get the passwd struct. Try to create the account if necessary. */
1237 *username_was_mapped = map_username(mem_ctx, orig_dom_user, &dom_user);
1239 return NT_STATUS_NO_MEMORY;
1242 passwd = smb_getpwnam(mem_ctx, dom_user, &real_username, true );
1244 DEBUG(3, ("Failed to find authenticated user %s via "
1245 "getpwnam(), denying access.\n", dom_user));
1246 return NT_STATUS_NO_SUCH_USER;
1249 if (!real_username) {
1250 return NT_STATUS_NO_MEMORY;
1255 /* This is pointless -- there is no support for differing
1256 unix and windows names. Make sure to always store the
1257 one we actually looked up and succeeded. Have I mentioned
1258 why I hate the 'winbind use default domain' parameter?
1261 *found_username = talloc_strdup( mem_ctx, real_username );
1263 return NT_STATUS_OK;
1266 /****************************************************************************
1267 Wrapper to allow the getpwnam() call to strip the domain name and
1268 try again in case a local UNIX user is already there. Also run through
1269 the username if we fallback to the username only.
1270 ****************************************************************************/
1272 struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, const char *domuser,
1273 char **p_save_username, bool create )
1275 struct passwd *pw = NULL;
1277 char *username = NULL;
1279 /* we only save a copy of the username it has been mangled
1280 by winbindd use default domain */
1281 *p_save_username = NULL;
1283 /* don't call map_username() here since it has to be done higher
1284 up the stack so we don't call it multiple times */
1286 username = talloc_strdup(mem_ctx, domuser);
1291 p = strchr_m( username, *lp_winbind_separator() );
1293 /* code for a DOMAIN\user string */
1296 pw = Get_Pwnam_alloc( mem_ctx, domuser );
1298 /* make sure we get the case of the username correct */
1299 /* work around 'winbind use default domain = yes' */
1301 if ( lp_winbind_use_default_domain() &&
1302 !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
1305 /* split the domain and username into 2 strings */
1309 *p_save_username = talloc_asprintf(mem_ctx,
1312 *lp_winbind_separator(),
1314 if (!*p_save_username) {
1319 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1326 /* setup for lookup of just the username */
1327 /* remember that p and username are overlapping memory */
1330 username = talloc_strdup(mem_ctx, p);
1336 /* just lookup a plain username */
1338 pw = Get_Pwnam_alloc(mem_ctx, username);
1340 /* Create local user if requested but only if winbindd
1341 is not running. We need to protect against cases
1342 where winbindd is failing and then prematurely
1343 creating users in /etc/passwd */
1345 if ( !pw && create && !winbind_ping() ) {
1346 /* Don't add a machine account. */
1347 if (username[strlen(username)-1] == '$')
1350 _smb_create_user(NULL, username, NULL);
1351 pw = Get_Pwnam_alloc(mem_ctx, username);
1354 /* one last check for a valid passwd struct */
1357 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1362 /***************************************************************************
1363 Make a server_info struct from the info3 returned by a domain logon
1364 ***************************************************************************/
1366 NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
1367 const char *sent_nt_username,
1369 struct auth_serversupplied_info **server_info,
1370 const struct netr_SamInfo3 *info3)
1372 NTSTATUS nt_status = NT_STATUS_OK;
1373 char *found_username = NULL;
1374 const char *nt_domain;
1375 const char *nt_username;
1376 struct dom_sid user_sid;
1377 struct dom_sid group_sid;
1378 bool username_was_mapped;
1380 struct auth_serversupplied_info *result;
1381 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1384 Here is where we should check the list of
1385 trusted domains, and verify that the SID
1389 if (!sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid)) {
1390 nt_status = NT_STATUS_INVALID_PARAMETER;
1394 if (!sid_compose(&group_sid, info3->base.domain_sid,
1395 info3->base.primary_gid)) {
1396 nt_status = NT_STATUS_INVALID_PARAMETER;
1400 nt_username = talloc_strdup(tmp_ctx, info3->base.account_name.string);
1402 /* If the server didn't give us one, just use the one we sent
1404 nt_username = sent_nt_username;
1407 nt_domain = talloc_strdup(mem_ctx, info3->base.logon_domain.string);
1409 /* If the server didn't give us one, just use the one we sent
1414 /* If getpwnam() fails try the add user script (2.2.x behavior).
1416 We use the _unmapped_ username here in an attempt to provide
1417 consistent username mapping behavior between kerberos and NTLM[SSP]
1418 authentication in domain mode security. I.E. Username mapping
1419 should be applied to the fully qualified username
1420 (e.g. DOMAIN\user) and not just the login name. Yes this means we
1421 called map_username() unnecessarily in make_user_info_map() but
1422 that is how the current code is designed. Making the change here
1423 is the least disruptive place. -- jerry */
1425 /* this call will try to create the user if necessary */
1427 nt_status = check_account(tmp_ctx,
1432 &username_was_mapped);
1434 if (!NT_STATUS_IS_OK(nt_status)) {
1435 /* Handle 'map to guest = Bad Uid */
1436 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) &&
1437 (lp_security() == SEC_ADS || lp_security() == SEC_DOMAIN) &&
1438 lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID) {
1439 DBG_NOTICE("Try to map %s to guest account",
1441 nt_status = make_server_info_guest(tmp_ctx, &result);
1442 if (NT_STATUS_IS_OK(nt_status)) {
1443 *server_info = talloc_move(mem_ctx, &result);
1449 result = make_server_info(tmp_ctx);
1450 if (result == NULL) {
1451 DEBUG(4, ("make_server_info failed!\n"));
1452 nt_status = NT_STATUS_NO_MEMORY;
1456 result->unix_name = talloc_strdup(result, found_username);
1458 /* copy in the info3 */
1459 result->info3 = copy_netr_SamInfo3(result, info3);
1460 if (result->info3 == NULL) {
1461 nt_status = NT_STATUS_NO_MEMORY;
1465 /* Fill in the unix info we found on the way */
1467 result->utok.uid = pwd->pw_uid;
1468 result->utok.gid = pwd->pw_gid;
1470 /* ensure we are never given NULL session keys */
1472 if (all_zero(info3->base.key.key, sizeof(info3->base.key.key))) {
1473 result->session_key = data_blob_null;
1475 result->session_key = data_blob_talloc(
1476 result, info3->base.key.key,
1477 sizeof(info3->base.key.key));
1480 if (all_zero(info3->base.LMSessKey.key,
1481 sizeof(info3->base.LMSessKey.key))) {
1482 result->lm_session_key = data_blob_null;
1484 result->lm_session_key = data_blob_talloc(
1485 result, info3->base.LMSessKey.key,
1486 sizeof(info3->base.LMSessKey.key));
1489 result->nss_token |= username_was_mapped;
1491 result->guest = (info3->base.user_flags & NETLOGON_GUEST);
1493 *server_info = talloc_move(mem_ctx, &result);
1495 nt_status = NT_STATUS_OK;
1497 talloc_free(tmp_ctx);
1502 /*****************************************************************************
1503 Make a server_info struct from the wbcAuthUserInfo returned by a domain logon
1504 ******************************************************************************/
1506 NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx,
1507 const char *sent_nt_username,
1509 const struct wbcAuthUserInfo *info,
1510 struct auth_serversupplied_info **server_info)
1512 struct netr_SamInfo3 info3;
1513 struct netr_SamInfo6 *info6;
1515 info6 = wbcAuthUserInfo_to_netr_SamInfo6(mem_ctx, info);
1517 return NT_STATUS_NO_MEMORY;
1520 info3.base = info6->base;
1521 info3.sidcount = info6->sidcount;
1522 info3.sids = info6->sids;
1524 return make_server_info_info3(mem_ctx,
1525 sent_nt_username, domain,
1526 server_info, &info3);
1530 * Verify whether or not given domain is trusted.
1532 * @param domain_name name of the domain to be verified
1533 * @return true if domain is one of the trusted ones or
1534 * false if otherwise
1537 bool is_trusted_domain(const char* dom_name)
1539 struct dom_sid trustdom_sid;
1542 /* no trusted domains for a standalone server */
1544 if ( lp_server_role() == ROLE_STANDALONE )
1547 if (dom_name == NULL || dom_name[0] == '\0') {
1551 if (strequal(dom_name, get_global_sam_name())) {
1555 /* if we are a DC, then check for a direct trust relationships */
1559 DEBUG (5,("is_trusted_domain: Checking for domain trust with "
1560 "[%s]\n", dom_name ));
1561 ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL);
1569 /* If winbind is around, ask it */
1571 result = wb_is_trusted_domain(dom_name);
1573 if (result == WBC_ERR_SUCCESS) {
1577 if (result == WBC_ERR_DOMAIN_NOT_FOUND) {
1578 /* winbind could not find the domain */
1582 DEBUG(10, ("wb_is_trusted_domain returned error: %s\n",
1583 wbcErrorString(result)));
1585 /* The only other possible result is that winbind is not up
1586 and running. We need to update the trustdom_cache
1589 update_trustdom_cache();
1592 /* now the trustdom cache should be available a DC could still
1593 * have a transitive trust so fall back to the cache of trusted
1594 * domains (like a domain member would use */
1596 if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) {
1606 on a logon error possibly map the error to success if "map to guest"
1609 NTSTATUS do_map_to_guest_server_info(TALLOC_CTX *mem_ctx,
1613 struct auth_serversupplied_info **server_info)
1615 user = user ? user : "";
1616 domain = domain ? domain : "";
1618 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
1619 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
1620 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
1621 DEBUG(3,("No such user %s [%s] - using guest account\n",
1623 return make_server_info_guest(mem_ctx, server_info);
1625 } else if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1626 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
1627 DEBUG(3,("Registered username %s for guest access\n",
1629 return make_server_info_guest(mem_ctx, server_info);
1637 Extract session key from a session info and return it in a blob
1638 if intent is KEY_USE_16BYTES, truncate it to 16 bytes
1640 See sections 3.2.4.15 and 3.3.4.2 of MS-SMB
1641 Also see https://lists.samba.org/archive/cifs-protocol/2012-January/002265.html for details
1643 Note that returned session_key is referencing the original key, it is supposed to be
1644 short-lived. If original session_info->session_key is gone, the reference will be broken.
1646 NTSTATUS session_extract_session_key(const struct auth_session_info *session_info, DATA_BLOB *session_key, enum session_key_use_intent intent)
1649 if (session_key == NULL || session_info == NULL) {
1650 return NT_STATUS_INVALID_PARAMETER;
1653 if (session_info->session_key.length == 0) {
1654 return NT_STATUS_NO_USER_SESSION_KEY;
1657 *session_key = session_info->session_key;
1658 if (intent == KEY_USE_16BYTES) {
1659 session_key->length = MIN(session_info->session_key.length, 16);
1661 return NT_STATUS_OK;