195a404ff36c7137dfa4249c7ca8ca24486e1200
[tprouty/samba.git] / source / lib / passcheck.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Password and authentication handling
5    Copyright (C) Andrew Tridgell 1992-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 extern int DEBUGLEVEL;
25 extern int Protocol;
26
27 extern pstring scope;
28 extern pstring global_myname;
29 extern fstring global_myworkgroup;
30
31
32
33 /****************************************************************************
34 core of smb password checking routine.
35 ****************************************************************************/
36 static BOOL smb_pwd_check_ntlmv1(char *password, unsigned char *part_passwd,
37                                 unsigned char *c8,
38                                 uchar sess_key[16])
39 {
40   /* Finish the encryption of part_passwd. */
41   unsigned char p24[24];
42
43   if (part_passwd == NULL)
44     DEBUG(10,("No password set - allowing access\n"));
45   /* No password set - always true ! */
46   if (part_passwd == NULL)
47     return True;
48
49   SMBOWFencrypt(part_passwd, c8, p24);
50         if (sess_key != NULL)
51         {
52                 SMBsesskeygen_ntv1(part_passwd, NULL, sess_key);
53         }
54
55 #if DEBUG_PASSWORD
56         DEBUG(100,("Part password (P16) was |"));
57         dump_data(100, part_passwd, 16);
58         DEBUG(100,("Password from client was |"));
59         dump_data(100, password, 24);
60         DEBUG(100,("Given challenge was |"));
61         dump_data(100, c8, 8);
62         DEBUG(100,("Value from encryption was |"));
63         dump_data(100, p24, 24);
64 #endif
65   return (memcmp(p24, password, 24) == 0);
66 }
67
68 /****************************************************************************
69 core of smb password checking routine.
70 ****************************************************************************/
71 static BOOL smb_pwd_check_ntlmv2(char *password, size_t pwd_len,
72                                 unsigned char *part_passwd,
73                                 unsigned char const *c8,
74                                 const char *user, const char *domain,
75                                 char *sess_key)
76 {
77         /* Finish the encryption of part_passwd. */
78         unsigned char kr[16];
79         unsigned char resp[16];
80
81         if (part_passwd == NULL)
82         {
83                 DEBUG(10,("No password set - allowing access\n"));
84         }
85         /* No password set - always true ! */
86         if (part_passwd == NULL)
87         {
88                 return True;
89         }
90
91         ntv2_owf_gen(part_passwd, user, domain, kr);
92         SMBOWFencrypt_ntv2(kr, c8, 8, password+16, pwd_len-16, resp);
93         if (sess_key != NULL)
94         {
95                 SMBsesskeygen_ntv2(kr, resp, sess_key);
96         }
97
98 #if DEBUG_PASSWORD
99         DEBUG(100,("Part password (P16) was |"));
100         dump_data(100, part_passwd, 16);
101         DEBUG(100,("Password from client was |"));
102         dump_data(100, password, pwd_len);
103         DEBUG(100,("Given challenge was |"));
104         dump_data(100, c8, 8);
105         DEBUG(100,("Value from encryption was |"));
106         dump_data(100, resp, 16);
107 #endif
108
109         return (memcmp(resp, password, 16) == 0);
110 }
111
112 /****************************************************************************
113  Do a specific test for an smb password being correct, given a smb_password and
114  the lanman and NT responses.
115 ****************************************************************************/
116 BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar challenge[8],
117                                 const char *user, const char *domain,
118                                 uchar *lm_pass, size_t lm_pwd_len,
119                                 uchar *nt_pass, size_t nt_pwd_len,
120                                 uchar sess_key[16])
121 {
122         if (smb_pass == NULL)
123         {
124                 return False;
125         }
126
127         DEBUG(4,("Checking SMB password for user %s\n", 
128                  smb_pass->unix_name));
129
130         if (smb_pass->acct_ctrl & ACB_DISABLED)
131         {
132                 DEBUG(3,("account for user %s was disabled.\n", 
133                          smb_pass->unix_name));
134                 return False;
135         }
136
137         if (challenge == NULL)
138         {
139                 DEBUG(1,("no challenge available - password failed\n"));
140                 return False;
141         }
142
143         if ((Protocol >= PROTOCOL_NT1) && (smb_pass->smb_nt_passwd != NULL))
144         {
145                 /* We have the NT MD4 hash challenge available - see if we can
146                    use it (ie. does it exist in the smbpasswd file).
147                 */
148                 if (lp_server_ntlmv2() != False && nt_pwd_len > 24)
149                 {
150                         DEBUG(4,("smb_password_ok: Check NTLMv2 password\n"));
151                         if (smb_pwd_check_ntlmv2(nt_pass, nt_pwd_len,
152                                        (uchar *)smb_pass->smb_nt_passwd, 
153                                         challenge, user, domain,
154                                         sess_key))
155                         {
156                                 return True;
157                         }
158                 }
159                 if (lp_server_ntlmv2() != True && nt_pwd_len == 24)
160                 {
161                         DEBUG(4,("smb_password_ok: Check NT MD4 password\n"));
162                         if (smb_pwd_check_ntlmv1((char *)nt_pass, 
163                                        (uchar *)smb_pass->smb_nt_passwd, 
164                                        challenge,
165                                        sess_key))
166                         {
167                                 DEBUG(4,("NT MD4 password check succeeded\n"));
168                                 return True;
169                         }
170                 }
171                 DEBUG(4,("NT MD4 password check failed\n"));
172         }
173
174         if (lp_server_ntlmv2() == True)
175         {
176                 DEBUG(4,("Not checking LM MD4 password\n"));
177                 return False;
178         }
179
180         /* Try against the lanman password. smb_pass->smb_passwd == NULL means
181            no password, allow access. */
182
183         DEBUG(4,("Checking LM MD4 password\n"));
184
185         if ((smb_pass->smb_passwd == NULL) && 
186            (smb_pass->acct_ctrl & ACB_PWNOTREQ))
187         {
188                 DEBUG(4,("no password required for user %s\n",
189                          smb_pass->unix_name));
190                 return True;
191         }
192
193         if ((smb_pass->smb_passwd != NULL) && 
194            smb_pwd_check_ntlmv1((char *)lm_pass, 
195                               (uchar *)smb_pass->smb_passwd,
196                                 challenge, NULL))
197         {
198                 DEBUG(4,("LM MD4 password check succeeded\n"));
199                 return(True);
200         }
201
202         DEBUG(4,("LM MD4 password check failed\n"));
203
204         return False;
205 }
206
207
208 /****************************************************************************
209 check if a username/password is OK assuming the password is a 24 byte
210 SMB hash
211 return True if the password is correct, False otherwise
212 ****************************************************************************/
213 BOOL pass_check_smb(struct smb_passwd *smb_pass, char *domain, uchar *chal,
214                 uchar *lm_pwd, size_t lm_pwd_len,
215                 uchar *nt_pwd, size_t nt_pwd_len,
216                 struct passwd *pwd, uchar user_sess_key[16])
217 {
218         const struct passwd *pass;
219         struct passwd pw;
220         char *user = NULL;
221
222         if (smb_pass == NULL)
223         {
224                 DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user));
225                 return False;
226         }
227
228         user = smb_pass->unix_name;
229
230         if (lm_pwd == NULL || nt_pwd == NULL)
231         {
232                 return False;
233         }
234
235         if (pwd != NULL && user == NULL)
236         {
237                 pass = (struct passwd *) pwd;
238                 user = pass->pw_name;
239         }
240         else
241         {
242                 pass = Get_Pwnam(user,True);
243                 if (pass == NULL)
244                 {
245                         DEBUG(3,("Couldn't find user %s\n",user));
246                         return False;
247                 }
248                 memcpy(&pw, pass, sizeof(struct passwd));
249                 pass = &pw;
250         }
251
252         /* Quit if the account was disabled. */
253         if (smb_pass->acct_ctrl & ACB_DISABLED) {
254                 DEBUG(3,("account for user %s was disabled.\n", user));
255                 return False;
256         }
257
258         /* Ensure the uid's match */
259         if (smb_pass->unix_uid != pass->pw_uid)
260         {
261                 DEBUG(3,("Error : UNIX (%d) and SMB (%d) uids in password files do not match !\n", pass->pw_uid, smb_pass->unix_uid));
262                 return False;
263         }
264
265         if (lm_pwd[0] == '\0' && IS_BITS_SET_ALL(smb_pass->acct_ctrl, ACB_PWNOTREQ) && lp_null_passwords())
266         {
267                 DEBUG(3,("account for user %s has no password and null passwords are allowed.\n", smb_pass->unix_name));
268                 return(True);
269         }
270
271         if (smb_password_ok(smb_pass, chal, user, domain,
272                                             lm_pwd, lm_pwd_len,
273                                             nt_pwd, nt_pwd_len,
274                                             user_sess_key))
275         {
276                 if (user_sess_key != NULL)
277                 {
278 #ifdef DEBUG_PASSWORD
279                 DEBUG(100,("user session key: "));
280                 dump_data(100, user_sess_key, 16);
281 #endif
282                 }
283                 return(True);
284         }
285         
286         DEBUG(3,("Error pass_check_smb failed\n"));
287         return False;
288 }
289