Record the NT_STATUS constant rather than its number in the logfiles
[ira/wip.git] / source3 / auth / auth.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
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
8    
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.
13    
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.
18    
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.
22 */
23
24 #include "includes.h"
25
26 extern int DEBUGLEVEL;
27
28 extern pstring global_myname;
29
30
31 /****************************************************************************
32 update the encrypted smbpasswd file from the plaintext username and password
33
34 this ugly hack needs to die, but not quite yet...
35 *****************************************************************************/
36 static BOOL update_smbpassword_file(char *user, char *password)
37 {
38         SAM_ACCOUNT     *sampass = NULL;
39         BOOL            ret;
40         
41         pdb_init_sam(&sampass);
42         
43         become_root();
44         ret = pdb_getsampwnam(sampass, user);
45         unbecome_root();
46
47         if(ret == False) {
48                 DEBUG(0,("pdb_getsampwnam returned NULL\n"));
49                 pdb_free_sam(sampass);
50                 return False;
51         }
52
53         /*
54          * Remove the account disabled flag - we are updating the
55          * users password from a login.
56          */
57         pdb_set_acct_ctrl(sampass, pdb_get_acct_ctrl(sampass) & ~ACB_DISABLED);
58
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);
62         if (ret == False) {
63                 DEBUG(3,("change_oem_password returned False\n"));
64         }
65
66         pdb_free_sam(sampass);
67         return ret;
68 }
69
70 /****************************************************************************
71  Check user is in correct domain if required
72 ****************************************************************************/
73
74 static BOOL check_domain_match(char *user, char *domain) 
75 {
76   /*
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
79    * as the Samba server
80    */
81
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));
85       return False;
86   } else {
87       return True;
88   }
89 }
90
91
92 uint32 check_password(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info)
93 {
94         
95         uint32 nt_status = NT_STATUS_LOGON_FAILURE;
96
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;
100         }
101                 
102         if (!check_domain_match(user_info->smb_username.str, user_info->domain.str)) {
103                 return NT_STATUS_LOGON_FAILURE;
104         }
105
106         if ((lp_security() == SEC_DOMAIN) && (nt_status != NT_STATUS_NOPROBLEMO)) {
107                 nt_status = check_domain_security(user_info, server_info);
108         }
109         
110         if ((lp_security() == SEC_SERVER) && (nt_status != NT_STATUS_NOPROBLEMO)) {
111                 nt_status = check_server_security(user_info, server_info);
112         }
113
114         if (lp_security() >= SEC_SERVER) {
115                 smb_user_control(user_info->smb_username.str, nt_status);
116         }
117
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);
127         }
128
129         if (nt_status != NT_STATUS_NOPROBLEMO) {
130                 nt_status = check_smbpasswd_security(user_info, server_info);
131         }
132         
133         if (nt_status == NT_STATUS_NOPROBLEMO) {
134                 /* We might not be root if we are an RPC call */
135                 become_root();
136                 nt_status = smb_pam_accountcheck(user_info->smb_username.str);
137                 unbecome_root();
138         }
139
140         if (nt_status == NT_STATUS_NOPROBLEMO) {
141                 DEBUG(5, ("check_password:  Password for user %s suceeded\n", user_info->smb_username.str));
142         } else {
143                 DEBUG(3, ("check_password:  Password for user %s FAILED with error %s\n", user_info->smb_username.str, get_nt_error_msg(nt_status)));
144
145         }               
146         return nt_status;
147
148 }
149
150 /****************************************************************************
151  COMPATABILITY INTERFACES:
152  ***************************************************************************/
153
154 /****************************************************************************
155 check if a username/password is OK assuming the password is a 24 byte
156 SMB hash
157 return True if the password is correct, False otherwise
158 ****************************************************************************/
159
160 uint32 pass_check_smb_with_chal(char *user, char *domain, uchar chal[8], 
161                     uchar *lm_pwd, int lm_pwd_len,
162                     uchar *nt_pwd, int nt_pwd_len)
163 {
164
165         auth_usersupplied_info user_info;
166         auth_serversupplied_info server_info;
167         AUTH_STR ourdomain, theirdomain, smb_username, wksta_name;
168                 
169         ZERO_STRUCT(user_info);
170         ZERO_STRUCT(ourdomain);
171         ZERO_STRUCT(theirdomain);
172         ZERO_STRUCT(smb_username);
173         ZERO_STRUCT(wksta_name);
174         
175         ourdomain.str = lp_workgroup();
176         ourdomain.len = strlen(ourdomain.str);
177
178         theirdomain.str = domain;
179         theirdomain.len = strlen(theirdomain.str);
180
181         user_info.requested_domain = theirdomain;
182         user_info.domain = ourdomain;
183         
184         smb_username.str = user;
185         smb_username.len = strlen(smb_username.str);
186
187         user_info.requested_username = smb_username;  /* For the time-being */
188         user_info.smb_username = smb_username;
189
190         user_info.wksta_name.str = client_name();
191         user_info.wksta_name.len = strlen(client_name());
192
193         user_info.wksta_name = wksta_name;
194
195         memcpy(user_info.chal, chal, 8);
196
197         if (lm_pwd_len >= 24 || (lp_encrypted_passwords() && (lm_pwd_len == 0) && lp_null_passwords())) {
198                 /* if 24 bytes long assume it is an encrypted password */
199           
200                 user_info.lm_resp.buffer = (uint8 *)lm_pwd;
201                 user_info.lm_resp.len = lm_pwd_len;
202                 user_info.nt_resp.buffer = (uint8 *)nt_pwd;
203                 user_info.nt_resp.len = nt_pwd_len;
204
205         } else {
206                 unsigned char local_lm_response[24];
207                 unsigned char local_nt_response[24];
208                 
209                 /*
210                  * Not encrypted - do so.
211                  */
212                 
213                 DEBUG(5,("pass_check_smb: User passwords not in encrypted format.\n"));
214
215                 if (lm_pwd_len > 0) {
216                         SMBencrypt( (uchar *)lm_pwd, user_info.chal, local_lm_response);
217                         user_info.lm_resp.buffer = (uint8 *)local_lm_response;
218                         user_info.lm_resp.len = 24;
219
220                         /* This encrypts the lm_pwd feild, which actualy contains the password
221                            rather than the nt_pwd field becouse that contains nothing */
222                         SMBNTencrypt((uchar *)lm_pwd, user_info.chal, local_nt_response);
223                         user_info.nt_resp.buffer = (uint8 *)local_nt_response;
224                         user_info.nt_resp.len = 24;
225                 }
226                 
227                 user_info.plaintext_password.str = lm_pwd;
228                 user_info.plaintext_password.len = lm_pwd_len;
229
230         }
231
232         return check_password(&user_info, &server_info);
233 }
234
235 uint32 pass_check_smb(char *user, char *domain,
236                     uchar *lm_pwd, int lm_pwd_len,
237                     uchar *nt_pwd, int nt_pwd_len)
238 {
239         uchar chal[8];
240
241         if (!last_challenge(chal)) {
242                 generate_random_buffer( chal, 8, False);
243         }
244
245         return pass_check_smb_with_chal(user, domain, chal, 
246                                         lm_pwd, lm_pwd_len,
247                                         nt_pwd, nt_pwd_len);
248
249 }
250
251 /****************************************************************************
252 check if a username/password pair is OK either via the system password
253 database or the encrypted SMB password database
254 return True if the password is correct, False otherwise
255 ****************************************************************************/
256 BOOL password_ok(char *user, char *password, int pwlen)
257 {
258
259         /* 
260          *  This hack must die!  But until I rewrite the rest of samba
261          *  it must stay - abartlet 2001-08-03
262          */
263
264         if ((pwlen == 0) && !lp_null_passwords()) {
265                 DEBUG(4,("Null passwords not allowed.\n"));
266                 return False;
267         }
268         
269         if (pass_check_smb(user, lp_workgroup(), NULL, 0, password, pwlen) == NT_STATUS_NOPROBLEMO) {
270                 return True;
271         }
272
273         if (pass_check_smb(user, lp_workgroup(), password, pwlen, NULL, 0) == NT_STATUS_NOPROBLEMO) {
274                 return True;
275         }
276
277         return False;
278 }
279