Removed 'extern int DEBUGLEVEL' as it is now in the smb.h header.
[metze/samba/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 /****************************************************************************
27  Check user is in correct domain if required
28 ****************************************************************************/
29
30 static BOOL check_domain_match(char *user, char *domain) 
31 {
32   /*
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
35    * as the Samba server
36    */
37
38   if (!lp_allow_trusted_domains() &&
39       !strequal(lp_workgroup(), domain) ) {
40       DEBUG(1, ("check_domain_match: Attempt to connect as user %s from domain %s denied.\n", user, domain));
41       return False;
42   } else {
43       return True;
44   }
45 }
46
47 /****************************************************************************
48  Check a users password, as given in the user-info struct and return various
49  interesting details in the server_info struct.
50
51  This functions does NOT need to be in a become_root()/unbecome_root() pair
52  as it makes the calls itself when needed.
53 ****************************************************************************/
54
55 NTSTATUS check_password(const auth_usersupplied_info *user_info, 
56                         auth_serversupplied_info *server_info)
57 {
58         
59         NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
60         BOOL done_pam = False;
61         
62         DEBUG(3, ("check_password:  Checking password for smb user %s\\%s@%s with the new password interface\n", 
63                   user_info->smb_username.str, user_info->requested_domain.str, user_info->wksta_name.str));
64         if (!check_domain_match(user_info->smb_username.str, user_info->domain.str)) {
65                 return NT_STATUS_LOGON_FAILURE;
66         }
67
68         if (!NT_STATUS_IS_OK(nt_status)) {
69                 nt_status = check_rhosts_security(user_info, server_info);
70         }
71         
72         if ((lp_security() == SEC_DOMAIN) && !NT_STATUS_IS_OK(nt_status)) {
73                 nt_status = check_domain_security(user_info, server_info);
74         }
75         
76         if ((lp_security() == SEC_SERVER) && !NT_STATUS_IS_OK(nt_status)) {
77                 nt_status = check_server_security(user_info, server_info);
78         }
79
80         if (lp_security() >= SEC_SERVER) {
81                 smb_user_control(user_info->unix_username.str, nt_status);
82         }
83
84         if (!NT_STATUS_IS_OK(nt_status)) {
85                 if ((user_info->plaintext_password.len > 0) 
86                     && (!lp_plaintext_to_smbpasswd())) {
87                         nt_status = check_unix_security(user_info, server_info);
88                         done_pam = True;
89                 } else { 
90                         nt_status = check_smbpasswd_security(user_info, server_info);
91                 }
92         }
93
94         if (NT_STATUS_IS_OK(nt_status) && !done_pam) {
95                 /* We might not be root if we are an RPC call */
96                 become_root();
97                 nt_status = smb_pam_accountcheck(user_info->unix_username.str);
98                 unbecome_root();
99         }
100         
101         if (NT_STATUS_IS_OK(nt_status)) {
102                 DEBUG(5, ("check_password:  Password for smb user %s suceeded\n", user_info->smb_username.str));
103         } else {
104                 DEBUG(3, ("check_password:  Password for smb user %s FAILED with error %s\n", user_info->smb_username.str, get_nt_error_msg(nt_status)));
105
106         }               
107         return nt_status;
108
109 }
110
111 /****************************************************************************
112  COMPATABILITY INTERFACES:
113  ***************************************************************************/
114
115 /****************************************************************************
116 check if a username/password is OK assuming the password is a 24 byte
117 SMB hash
118 return True if the password is correct, False otherwise
119 ****************************************************************************/
120
121 NTSTATUS pass_check_smb_with_chal(char *smb_user, char *unix_user, 
122                                   char *domain, char* workstation, 
123                                   uchar chal[8], 
124                                   uchar *lm_pwd, int lm_pwd_len,
125                                   uchar *nt_pwd, int nt_pwd_len)
126 {
127
128         auth_usersupplied_info user_info;
129         auth_serversupplied_info server_info;
130         AUTH_STR ourdomain, theirdomain, unix_username, smb_username, 
131                 wksta_name;
132                 
133         ZERO_STRUCT(user_info);
134         ZERO_STRUCT(ourdomain);
135         ZERO_STRUCT(theirdomain);
136         ZERO_STRUCT(smb_username);
137         ZERO_STRUCT(wksta_name);
138         
139         ourdomain.str = lp_workgroup();
140         ourdomain.len = strlen(ourdomain.str);
141
142         theirdomain.str = domain;
143         theirdomain.len = strlen(theirdomain.str);
144
145         user_info.requested_domain = theirdomain;
146         user_info.domain = ourdomain;
147         
148         smb_username.str = smb_user;
149         smb_username.len = strlen(smb_username.str);
150
151         /* If unix user is NULL, use smb user */
152
153         unix_username.str = unix_user ? unix_user : smb_user;
154         unix_username.len = strlen(unix_username.str);
155
156         user_info.unix_username = unix_username;
157         user_info.smb_username = smb_username;
158
159         wksta_name.str = workstation;
160         wksta_name.len = strlen(workstation);
161
162         user_info.wksta_name = wksta_name;
163
164         memcpy(user_info.chal, chal, 8);
165
166         if ((lm_pwd_len >= 24 || nt_pwd_len >= 24) || 
167             (lp_encrypted_passwords() && (lm_pwd_len == 0) && lp_null_passwords())) {
168                 /* if 24 bytes long assume it is an encrypted password */
169           
170                 user_info.lm_resp.buffer = (uint8 *)lm_pwd;
171                 user_info.lm_resp.len = lm_pwd_len;
172                 user_info.nt_resp.buffer = (uint8 *)nt_pwd;
173                 user_info.nt_resp.len = nt_pwd_len;
174
175         } else {
176                 unsigned char local_lm_response[24];
177                 unsigned char local_nt_response[24];
178                 
179                 /*
180                  * Not encrypted - do so.
181                  */
182                 
183                 DEBUG(5,("pass_check_smb: User passwords not in encrypted format.\n"));
184
185                 if (lm_pwd_len > 0) {
186                         SMBencrypt( (uchar *)lm_pwd, user_info.chal, local_lm_response);
187                         user_info.lm_resp.buffer = (uint8 *)local_lm_response;
188                         user_info.lm_resp.len = 24;
189
190
191                         /* WATCH OUT. This doesn't work if the incoming password is incorrectly cased. 
192                            We might want to add a check here and only do an LM in that case */
193
194                         /* This encrypts the lm_pwd feild, which actualy contains the password
195                            rather than the nt_pwd field becouse that contains nothing */
196                         SMBNTencrypt((uchar *)lm_pwd, user_info.chal, local_nt_response);
197                         user_info.nt_resp.buffer = (uint8 *)local_nt_response;
198                         user_info.nt_resp.len = 24;
199                 }
200                 
201                 user_info.plaintext_password.str = (char *)lm_pwd;
202                 user_info.plaintext_password.len = lm_pwd_len;
203
204         }
205
206         return check_password(&user_info, &server_info);
207 }
208
209 NTSTATUS pass_check_smb(char *smb_user, char *unix_user, 
210                         char *domain, char *workstation,
211                         uchar *lm_pwd, int lm_pwd_len,
212                         uchar *nt_pwd, int nt_pwd_len)
213 {
214         uchar chal[8];
215
216         if (!last_challenge(chal)) {
217                 generate_random_buffer( chal, 8, False);
218         }
219
220         return pass_check_smb_with_chal(smb_user, unix_user, 
221                                         domain, workstation, chal, 
222                                         lm_pwd, lm_pwd_len,
223                                         nt_pwd, nt_pwd_len);
224
225 }
226
227 /****************************************************************************
228 check if a username/password pair is OK either via the system password
229 database or the encrypted SMB password database
230 return True if the password is correct, False otherwise
231 ****************************************************************************/
232 BOOL password_ok(char *user, char *password, int pwlen)
233 {
234         extern fstring remote_machine;
235
236         /* 
237          *  This hack must die!  But until I rewrite the rest of samba
238          *  it must stay - abartlet 2001-08-03
239          */
240
241         if ((pwlen == 0) && !lp_null_passwords()) {
242                 DEBUG(4,("Null passwords not allowed.\n"));
243                 return False;
244         }
245         
246         /* The password could be either NTLM or plain LM.  Try NTLM first, but fall-through as
247            required. */
248         if (NT_STATUS_IS_OK(pass_check_smb(user, NULL, remote_machine, lp_workgroup(), NULL, 0, (unsigned char *)password, pwlen))) {
249                 return True;
250         }
251
252         if (NT_STATUS_IS_OK(pass_check_smb(user, NULL, remote_machine, lp_workgroup(), (unsigned char *)password, pwlen, NULL, 0))) {
253                 return True;
254         }
255
256         return False;
257 }