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 extern int DEBUGLEVEL
;
28 extern pstring global_myname
;
31 /****************************************************************************
32 update the encrypted smbpasswd file from the plaintext username and password
34 this ugly hack needs to die, but not quite yet...
35 *****************************************************************************/
36 static BOOL
update_smbpassword_file(char *user
, char *password
)
38 SAM_ACCOUNT
*sampass
= NULL
;
41 pdb_init_sam(&sampass
);
44 ret
= pdb_getsampwnam(sampass
, user
);
48 DEBUG(0,("pdb_getsampwnam returned NULL\n"));
49 pdb_free_sam(sampass
);
54 * Remove the account disabled flag - we are updating the
55 * users password from a login.
57 pdb_set_acct_ctrl(sampass
, pdb_get_acct_ctrl(sampass
) & ~ACB_DISABLED
);
59 /* Here, the flag is one, because we want to ignore the
60 XXXXXXX'd out password */
61 ret
= change_oem_password( sampass
, password
, True
);
63 DEBUG(3,("change_oem_password returned False\n"));
66 pdb_free_sam(sampass
);
70 /****************************************************************************
71 Check user is in correct domain if required
72 ****************************************************************************/
74 static BOOL
check_domain_match(char *user
, char *domain
)
77 * If we aren't serving to trusted domains, we must make sure that
78 * the validation request comes from an account in the same domain
82 if (!lp_allow_trusted_domains() &&
83 !strequal(lp_workgroup(), domain
) ) {
84 DEBUG(1, ("check_domain_match: Attempt to connect as user %s from domain %s denied.\n", user
, domain
));
92 uint32
check_password(const auth_usersupplied_info
*user_info
, auth_serversupplied_info
*server_info
)
95 uint32 nt_status
= NT_STATUS_LOGON_FAILURE
;
97 DEBUG(3, ("check_password: Checking password for user %s with the new password interface\n", user_info
->smb_username
.str
));
98 if (check_hosts_equiv(user_info
->smb_username
.str
)) {
99 nt_status
= NT_STATUS_NOPROBLEMO
;
102 if (!check_domain_match(user_info
->smb_username
.str
, user_info
->domain
.str
)) {
103 return NT_STATUS_LOGON_FAILURE
;
106 if ((lp_security() == SEC_DOMAIN
) && (nt_status
!= NT_STATUS_NOPROBLEMO
)) {
107 nt_status
= check_domain_security(user_info
, server_info
);
110 if ((lp_security() == SEC_SERVER
) && (nt_status
!= NT_STATUS_NOPROBLEMO
)) {
111 nt_status
= check_server_security(user_info
, server_info
);
114 if (lp_security() >= SEC_SERVER
) {
115 smb_user_control(user_info
->smb_username
.str
, nt_status
);
118 if ((nt_status
!= NT_STATUS_NOPROBLEMO
)
119 && (user_info
->plaintext_password
.len
> 0)
120 && (!lp_plaintext_to_smbpasswd())) {
121 return (pass_check(user_info
->smb_username
.str
,
122 user_info
->plaintext_password
.str
,
123 user_info
->plaintext_password
.len
,
124 lp_update_encrypted() ?
125 update_smbpassword_file
: NULL
)
126 ? NT_STATUS_NOPROBLEMO
: NT_STATUS_LOGON_FAILURE
);
129 if (nt_status
!= NT_STATUS_NOPROBLEMO
) {
130 nt_status
= check_smbpasswd_security(user_info
, server_info
);
133 if (nt_status
== NT_STATUS_NOPROBLEMO
) {
134 /* We might not be root if we are an RPC call */
136 nt_status
= smb_pam_accountcheck(user_info
->smb_username
.str
);
140 if (nt_status
== NT_STATUS_NOPROBLEMO
) {
141 DEBUG(5, ("check_password: Password for user %s suceeded\n", user_info
->smb_username
.str
));
143 DEBUG(3, ("check_password: Password for user %s FAILED with error %d\n", user_info
->smb_username
.str
, nt_status
));
149 /****************************************************************************
150 COMPATABILITY INTERFACES:
151 ***************************************************************************/
153 /****************************************************************************
154 check if a username/password is OK assuming the password is a 24 byte
156 return True if the password is correct, False otherwise
157 ****************************************************************************/
159 uint32
pass_check_smb_with_chal(char *user
, char *domain
, uchar chal
[8],
160 uchar
*lm_pwd
, int lm_pwd_len
,
161 uchar
*nt_pwd
, int nt_pwd_len
)
164 auth_usersupplied_info user_info
;
165 auth_serversupplied_info server_info
;
166 AUTH_STR ourdomain
, theirdomain
, smb_username
, wksta_name
;
168 ZERO_STRUCT(user_info
);
169 ZERO_STRUCT(ourdomain
);
170 ZERO_STRUCT(theirdomain
);
171 ZERO_STRUCT(smb_username
);
172 ZERO_STRUCT(wksta_name
);
174 ourdomain
.str
= lp_workgroup();
175 ourdomain
.len
= strlen(ourdomain
.str
);
177 theirdomain
.str
= domain
;
178 theirdomain
.len
= strlen(theirdomain
.str
);
180 user_info
.requested_domain
= theirdomain
;
181 user_info
.domain
= ourdomain
;
183 smb_username
.str
= user
;
184 smb_username
.len
= strlen(smb_username
.str
);
186 user_info
.requested_username
= smb_username
; /* For the time-being */
187 user_info
.smb_username
= smb_username
;
189 user_info
.wksta_name
.str
= client_name();
190 user_info
.wksta_name
.len
= strlen(client_name());
192 user_info
.wksta_name
= wksta_name
;
194 memcpy(user_info
.chal
, chal
, 8);
196 if (lm_pwd_len
>= 24 || (lp_encrypted_passwords() && (lm_pwd_len
== 0) && lp_null_passwords())) {
197 /* if 24 bytes long assume it is an encrypted password */
199 user_info
.lm_resp
.buffer
= (uint8
*)lm_pwd
;
200 user_info
.lm_resp
.len
= lm_pwd_len
;
201 user_info
.nt_resp
.buffer
= (uint8
*)nt_pwd
;
202 user_info
.nt_resp
.len
= nt_pwd_len
;
205 unsigned char local_lm_response
[24];
206 unsigned char local_nt_response
[24];
209 * Not encrypted - do so.
212 DEBUG(5,("pass_check_smb: User passwords not in encrypted format.\n"));
214 if (lm_pwd_len
> 0) {
215 SMBencrypt( (uchar
*)lm_pwd
, user_info
.chal
, local_lm_response
);
216 user_info
.lm_resp
.buffer
= (uint8
*)local_lm_response
;
217 user_info
.lm_resp
.len
= 24;
219 /* This encrypts the lm_pwd feild, which actualy contains the password
220 rather than the nt_pwd field becouse that contains nothing */
221 SMBNTencrypt((uchar
*)lm_pwd
, user_info
.chal
, local_nt_response
);
222 user_info
.nt_resp
.buffer
= (uint8
*)local_nt_response
;
223 user_info
.nt_resp
.len
= 24;
226 user_info
.plaintext_password
.str
= lm_pwd
;
227 user_info
.plaintext_password
.len
= lm_pwd_len
;
231 return check_password(&user_info
, &server_info
);
234 uint32
pass_check_smb(char *user
, char *domain
,
235 uchar
*lm_pwd
, int lm_pwd_len
,
236 uchar
*nt_pwd
, int nt_pwd_len
)
240 if (!last_challenge(chal
)) {
241 generate_random_buffer( chal
, 8, False
);
244 return pass_check_smb_with_chal(user
, domain
, chal
,
250 /****************************************************************************
251 check if a username/password pair is OK either via the system password
252 database or the encrypted SMB password database
253 return True if the password is correct, False otherwise
254 ****************************************************************************/
255 BOOL
password_ok(char *user
, char *password
, int pwlen
)
259 * This hack must die! But until I rewrite the rest of samba
260 * it must stay - abartlet 2001-08-03
263 if ((pwlen
== 0) && !lp_null_passwords()) {
264 DEBUG(4,("Null passwords not allowed.\n"));
268 if (pass_check_smb(user
, lp_workgroup(), NULL
, 0, password
, pwlen
) == NT_STATUS_NOPROBLEMO
) {
272 if (pass_check_smb(user
, lp_workgroup(), password
, pwlen
, NULL
, 0) == NT_STATUS_NOPROBLEMO
) {