2 Unix SMB/Netbios implementation.
4 Password and authentication handling
5 Copyright (C) Andrew Tridgell 1992-2000
6 Copyright (C) Luke Kenneth Casson Leighton 1996-2000
7 Copyright (C) Andrew Bartlett 2001
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /****************************************************************************
27 Check user is in correct domain if required
28 ****************************************************************************/
30 static BOOL check_domain_match(char *user, char *domain)
33 * If we aren't serving to trusted domains, we must make sure that
34 * the validation request comes from an account in the same domain
38 if (!lp_allow_trusted_domains() &&
39 (!strequal(lp_workgroup(), domain) || strequal("", domain))) {
40 DEBUG(1, ("check_domain_match: Attempt to connect as user %s from domain %s denied.\n", user, domain));
47 /****************************************************************************
48 Check a users password, as given in the user-info struct and return various
49 interesting details in the server_info struct.
51 This functions does NOT need to be in a become_root()/unbecome_root() pair
52 as it makes the calls itself when needed.
54 The return value takes precedence over the contents of the server_info
55 struct. When the return is other than NT_STATUS_NOPROBLEMO the contents
56 of that structure is undefined.
58 ****************************************************************************/
60 NTSTATUS check_password(const auth_usersupplied_info *user_info,
61 const auth_authsupplied_info *auth_info,
62 auth_serversupplied_info **server_info)
65 NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
66 const char *pdb_username;
67 auth_methods *auth_method;
69 if (!user_info || !auth_info || !server_info) {
70 return NT_STATUS_LOGON_FAILURE;
73 DEBUG(3, ("check_password: Checking password for unmapped user [%s]\\[%s]@[%s] with the new password interface\n",
74 user_info->client_domain.str, user_info->smb_name.str, user_info->wksta_name.str));
76 DEBUG(3, ("check_password: mapped user is: [%s]\\[%s]@[%s]\n",
77 user_info->domain.str, user_info->internal_username.str, user_info->wksta_name.str));
78 DEBUG(10, ("auth_info challange created by %s\n", auth_info->challange_set_by));
79 DEBUG(10, ("challange is: \n"));
80 dump_data(5, (auth_info)->challange.data, (auth_info)->challange.length);
83 DEBUG(100, ("user_info has passwords of length %d and %d\n",
84 user_info->lm_resp.length, user_info->nt_resp.length));
85 DEBUG(100, ("lm:\n"));
86 dump_data(100, user_info->lm_resp.data, user_info->lm_resp.length);
87 DEBUG(100, ("nt:\n"));
88 dump_data(100, user_info->nt_resp.data, user_info->nt_resp.length);
91 for (auth_method = auth_info->auth_method_list;auth_method; auth_method = auth_method->next)
93 nt_status = auth_method->auth(auth_method->private_data, user_info, auth_info, server_info);
94 if (NT_STATUS_IS_OK(nt_status)) {
95 DEBUG(3, ("check_password: %s authentication for user [%s] suceeded\n",
96 auth_method->name, user_info->smb_name.str));
98 DEBUG(5, ("check_password: %s authentication for user [%s] FAILED with error %s\n",
99 auth_method->name, user_info->smb_name.str, get_nt_error_msg(nt_status)));
102 if (NT_STATUS_IS_OK(nt_status)) {
107 /* This needs to be sorted: If it doesn't match, what should we do? */
108 if (!check_domain_match(user_info->smb_name.str, user_info->domain.str)) {
109 return NT_STATUS_LOGON_FAILURE;
113 /* This is one of the few places the *relies* (rather than just sets defaults
114 on the value of lp_security(). This needs to change. A new paramater
116 if (lp_security() >= SEC_SERVER) {
117 smb_user_control(user_info, *server_info, nt_status);
120 if (NT_STATUS_IS_OK(nt_status)) {
121 pdb_username = pdb_get_username((*server_info)->sam_account);
122 if (!(*server_info)->guest) {
123 /* We might not be root if we are an RPC call */
125 nt_status = smb_pam_accountcheck(pdb_username);
128 if (NT_STATUS_IS_OK(nt_status)) {
129 DEBUG(5, ("check_password: PAM Account for user [%s] suceeded\n",
132 DEBUG(3, ("check_password: PAM Account for user [%s] FAILED with error %s\n",
133 pdb_username, get_nt_error_msg(nt_status)));
137 if (NT_STATUS_IS_OK(nt_status)) {
138 DEBUG((*server_info)->guest ? 5 : 2,
139 ("check_password: %sauthenticaion for user [%s] -> [%s] -> [%s] suceeded\n",
140 (*server_info)->guest ? "guest " : "",
141 user_info->smb_name.str,
142 user_info->internal_username.str,
147 if (!NT_STATUS_IS_OK(nt_status)) {
148 DEBUG(2, ("check_password: Authenticaion for user [%s] -> [%s] FAILED with error %s\n",
149 user_info->smb_name.str, user_info->internal_username.str,
150 get_nt_error_msg(nt_status)));
151 ZERO_STRUCTP(server_info);
157 /****************************************************************************
158 Squash an NT_STATUS return in line with requirements for unauthenticated
159 connections. (session setups in particular)
160 ****************************************************************************/
162 NTSTATUS nt_status_squash(NTSTATUS nt_status)
164 if NT_STATUS_IS_OK(nt_status) {
166 } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) {
167 /* Match WinXP and don't give the game away */
168 return NT_STATUS_LOGON_FAILURE;
170 } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) {
171 /* Match WinXP and don't give the game away */
172 return NT_STATUS_LOGON_FAILURE;
180 /****************************************************************************
181 COMPATABILITY INTERFACES:
182 ***************************************************************************/
184 /****************************************************************************
185 check if a username/password is OK assuming the password is a 24 byte
187 return True if the password is correct, False otherwise
188 ****************************************************************************/
190 static NTSTATUS pass_check_smb(char *smb_name,
194 DATA_BLOB plaintext_password,
199 auth_usersupplied_info *user_info = NULL;
200 extern auth_authsupplied_info *negprot_global_auth_info;
201 auth_serversupplied_info *server_info = NULL;
203 make_user_info_for_reply_enc(&user_info, smb_name,
208 nt_status = check_password(user_info, negprot_global_auth_info, &server_info);
210 auth_authsupplied_info *plaintext_auth_info = NULL;
212 if (!make_auth_info_subsystem(&plaintext_auth_info)) {
213 return NT_STATUS_NO_MEMORY;
216 chal = auth_get_challange(plaintext_auth_info);
218 if (!make_user_info_for_reply(&user_info,
219 smb_name, domain, chal.data,
220 plaintext_password)) {
221 return NT_STATUS_NO_MEMORY;
224 nt_status = check_password(user_info, plaintext_auth_info, &server_info);
226 data_blob_free(&chal);
227 free_auth_info(&plaintext_auth_info);
229 free_user_info(&user_info);
230 free_server_info(&server_info);
234 /****************************************************************************
235 check if a username/password pair is OK either via the system password
236 database or the encrypted SMB password database
237 return True if the password is correct, False otherwise
238 ****************************************************************************/
239 BOOL password_ok(char *smb_name, DATA_BLOB password_blob)
242 DATA_BLOB null_password = data_blob(NULL, 0);
243 extern BOOL global_encrypted_passwords_negotiated;
244 BOOL encrypted = (global_encrypted_passwords_negotiated && password_blob.length == 24);
248 * The password could be either NTLM or plain LM. Try NTLM first,
249 * but fall-through as required.
250 * NTLMv2 makes no sense here.
252 if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), null_password, password_blob, null_password, encrypted))) {
256 if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), password_blob, null_password, null_password, encrypted))) {
260 if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), null_password, null_password, password_blob, encrypted))) {