Blame view
fs/cifs/cifsencrypt.c
20.7 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 |
/* * fs/cifs/cifsencrypt.c * |
12b3b8ffb [CIFS] Cleanup NT... |
4 |
* Copyright (C) International Business Machines Corp., 2005,2006 |
1da177e4c Linux-2.6.12-rc2 |
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
* Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <linux/fs.h> |
5a0e3ad6a include cleanup: ... |
23 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
24 |
#include "cifspdu.h" |
ffdd6e4d1 [CIFS] fix whites... |
25 |
#include "cifsglob.h" |
1da177e4c Linux-2.6.12-rc2 |
26 |
#include "cifs_debug.h" |
1da177e4c Linux-2.6.12-rc2 |
27 28 |
#include "cifs_unicode.h" #include "cifsproto.h" |
2b149f119 cifs NTLMv2/NTLMS... |
29 |
#include "ntlmssp.h" |
7c7b25bc8 [CIFS] Support fo... |
30 |
#include <linux/ctype.h> |
6d027cfdb [CIFS] NTLMv2 sup... |
31 |
#include <linux/random.h> |
1da177e4c Linux-2.6.12-rc2 |
32 |
|
157c24911 cifs: wrap receiv... |
33 34 35 36 37 38 39 |
/* * Calculate and return the CIFS signature based on the mac key and SMB PDU. * The 16 byte signature must be allocated by the caller. Note we only use the * 1st eight bytes and that the smb header signature field on input contains * the sequence number before this function is called. Also, this function * should be called with the server->srv_mutex held. */ |
826a95e4a cifs: consolidate... |
40 41 |
static int cifs_calc_signature(const struct kvec *iov, int n_vec, struct TCP_Server_Info *server, char *signature) |
84afc29b1 [CIFS] Readpages ... |
42 |
{ |
e9917a000 [CIFS] Incorrect ... |
43 |
int i; |
307fbd31b NTLM auth and sig... |
44 |
int rc; |
84afc29b1 [CIFS] Readpages ... |
45 |
|
21e733930 NTLM auth and sig... |
46 |
if (iov == NULL || signature == NULL || server == NULL) |
e9917a000 [CIFS] Incorrect ... |
47 |
return -EINVAL; |
84afc29b1 [CIFS] Readpages ... |
48 |
|
307fbd31b NTLM auth and sig... |
49 50 51 52 53 54 55 56 |
if (!server->secmech.sdescmd5) { cERROR(1, "%s: Can't generate signature ", __func__); return -1; } rc = crypto_shash_init(&server->secmech.sdescmd5->shash); if (rc) { |
14cae3243 cifs: Cleanup: ch... |
57 58 |
cERROR(1, "%s: Could not init md5 ", __func__); |
307fbd31b NTLM auth and sig... |
59 60 |
return rc; } |
14cae3243 cifs: Cleanup: ch... |
61 |
rc = crypto_shash_update(&server->secmech.sdescmd5->shash, |
307fbd31b NTLM auth and sig... |
62 |
server->session_key.response, server->session_key.len); |
14cae3243 cifs: Cleanup: ch... |
63 64 65 66 67 |
if (rc) { cERROR(1, "%s: Could not update with response ", __func__); return rc; } |
307fbd31b NTLM auth and sig... |
68 |
|
50c2f7538 [CIFS] whitespace... |
69 |
for (i = 0; i < n_vec; i++) { |
745542e21 [CIFS] allow cifs... |
70 71 |
if (iov[i].iov_len == 0) continue; |
ffdd6e4d1 [CIFS] fix whites... |
72 |
if (iov[i].iov_base == NULL) { |
56234e276 Revert "Eliminate... |
73 |
cERROR(1, "null iovec entry"); |
e9917a000 [CIFS] Incorrect ... |
74 |
return -EIO; |
745542e21 [CIFS] allow cifs... |
75 |
} |
ffdd6e4d1 [CIFS] fix whites... |
76 |
/* The first entry includes a length field (which does not get |
e9917a000 [CIFS] Incorrect ... |
77 |
signed that occupies the first 4 bytes before the header */ |
ffdd6e4d1 [CIFS] fix whites... |
78 |
if (i == 0) { |
63d2583f5 [CIFS] Fix walkin... |
79 |
if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ |
e9917a000 [CIFS] Incorrect ... |
80 |
break; /* nothing to sign or corrupt header */ |
14cae3243 cifs: Cleanup: ch... |
81 |
rc = |
307fbd31b NTLM auth and sig... |
82 83 |
crypto_shash_update(&server->secmech.sdescmd5->shash, iov[i].iov_base + 4, iov[i].iov_len - 4); |
14cae3243 cifs: Cleanup: ch... |
84 85 |
} else { rc = |
307fbd31b NTLM auth and sig... |
86 87 |
crypto_shash_update(&server->secmech.sdescmd5->shash, iov[i].iov_base, iov[i].iov_len); |
14cae3243 cifs: Cleanup: ch... |
88 89 90 91 92 93 94 |
} if (rc) { cERROR(1, "%s: Could not update with payload ", __func__); return rc; } |
e9917a000 [CIFS] Incorrect ... |
95 |
} |
84afc29b1 [CIFS] Readpages ... |
96 |
|
307fbd31b NTLM auth and sig... |
97 |
rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature); |
14cae3243 cifs: Cleanup: ch... |
98 99 100 |
if (rc) cERROR(1, "%s: Could not generate md5 hash ", __func__); |
84afc29b1 [CIFS] Readpages ... |
101 |
|
307fbd31b NTLM auth and sig... |
102 |
return rc; |
84afc29b1 [CIFS] Readpages ... |
103 |
} |
a0f8b4fb4 cifs: remove unne... |
104 |
/* must be called with server->srv_mutex held */ |
ffdd6e4d1 [CIFS] fix whites... |
105 |
int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, |
63d2583f5 [CIFS] Fix walkin... |
106 |
__u32 *pexpected_response_sequence_number) |
84afc29b1 [CIFS] Readpages ... |
107 108 109 |
{ int rc = 0; char smb_signature[20]; |
826a95e4a cifs: consolidate... |
110 |
struct smb_hdr *cifs_pdu = (struct smb_hdr *)iov[0].iov_base; |
84afc29b1 [CIFS] Readpages ... |
111 |
|
ffdd6e4d1 [CIFS] fix whites... |
112 |
if ((cifs_pdu == NULL) || (server == NULL)) |
84afc29b1 [CIFS] Readpages ... |
113 |
return -EINVAL; |
998d6fcb2 cifs: don't start... |
114 115 |
if (!(cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) || server->tcpStatus == CifsNeedNegotiate) |
84afc29b1 [CIFS] Readpages ... |
116 |
return rc; |
998d6fcb2 cifs: don't start... |
117 |
if (!server->session_estab) { |
b4dacbc28 cifs: use memcpy ... |
118 |
memcpy(cifs_pdu->Signature.SecuritySignature, "BSRSPYL", 8); |
998d6fcb2 cifs: don't start... |
119 120 |
return rc; } |
ffdd6e4d1 [CIFS] fix whites... |
121 |
cifs_pdu->Signature.Sequence.SequenceNumber = |
84afc29b1 [CIFS] Readpages ... |
122 |
cpu_to_le32(server->sequence_number); |
ffdd6e4d1 [CIFS] fix whites... |
123 |
cifs_pdu->Signature.Sequence.Reserved = 0; |
84afc29b1 [CIFS] Readpages ... |
124 |
|
ffdd6e4d1 [CIFS] fix whites... |
125 126 |
*pexpected_response_sequence_number = server->sequence_number++; server->sequence_number++; |
84afc29b1 [CIFS] Readpages ... |
127 |
|
826a95e4a cifs: consolidate... |
128 |
rc = cifs_calc_signature(iov, n_vec, server, smb_signature); |
ffdd6e4d1 [CIFS] fix whites... |
129 130 131 132 |
if (rc) memset(cifs_pdu->Signature.SecuritySignature, 0, 8); else memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8); |
84afc29b1 [CIFS] Readpages ... |
133 |
|
ffdd6e4d1 [CIFS] fix whites... |
134 |
return rc; |
84afc29b1 [CIFS] Readpages ... |
135 |
} |
826a95e4a cifs: consolidate... |
136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
/* must be called with server->srv_mutex held */ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, __u32 *pexpected_response_sequence_number) { struct kvec iov; iov.iov_base = cifs_pdu; iov.iov_len = be32_to_cpu(cifs_pdu->smb_buf_length) + 4; return cifs_sign_smb2(&iov, 1, server, pexpected_response_sequence_number); } int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov, |
21e733930 NTLM auth and sig... |
150 |
struct TCP_Server_Info *server, |
ffdd6e4d1 [CIFS] fix whites... |
151 |
__u32 expected_sequence_number) |
1da177e4c Linux-2.6.12-rc2 |
152 |
{ |
c8e56f1f4 Revert "[CIFS] Fi... |
153 |
unsigned int rc; |
1da177e4c Linux-2.6.12-rc2 |
154 155 |
char server_response_sig[8]; char what_we_think_sig_should_be[20]; |
826a95e4a cifs: consolidate... |
156 |
struct smb_hdr *cifs_pdu = (struct smb_hdr *)iov[0].iov_base; |
1da177e4c Linux-2.6.12-rc2 |
157 |
|
21e733930 NTLM auth and sig... |
158 |
if (cifs_pdu == NULL || server == NULL) |
1da177e4c Linux-2.6.12-rc2 |
159 |
return -EINVAL; |
9c4843ea5 cifs: silence pri... |
160 |
if (!server->session_estab) |
1da177e4c Linux-2.6.12-rc2 |
161 162 163 |
return 0; if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) { |
50c2f7538 [CIFS] whitespace... |
164 |
struct smb_com_lock_req *pSMB = |
ffdd6e4d1 [CIFS] fix whites... |
165 166 |
(struct smb_com_lock_req *)cifs_pdu; if (pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE) |
1da177e4c Linux-2.6.12-rc2 |
167 168 |
return 0; } |
50c2f7538 [CIFS] whitespace... |
169 170 |
/* BB what if signatures are supposed to be on for session but server does not send one? BB */ |
1da177e4c Linux-2.6.12-rc2 |
171 |
/* Do not need to verify session setups with signature "BSRSPYL " */ |
50c2f7538 [CIFS] whitespace... |
172 |
if (memcmp(cifs_pdu->Signature.SecuritySignature, "BSRSPYL ", 8) == 0) |
b6b38f704 [CIFS] Neaten cER... |
173 174 |
cFYI(1, "dummy signature received for smb command 0x%x", cifs_pdu->Command); |
1da177e4c Linux-2.6.12-rc2 |
175 176 177 |
/* save off the origiginal signature so we can modify the smb and check its signature against what the server sent */ |
50c2f7538 [CIFS] whitespace... |
178 |
memcpy(server_response_sig, cifs_pdu->Signature.SecuritySignature, 8); |
1da177e4c Linux-2.6.12-rc2 |
179 |
|
50c2f7538 [CIFS] whitespace... |
180 181 |
cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(expected_sequence_number); |
1da177e4c Linux-2.6.12-rc2 |
182 |
cifs_pdu->Signature.Sequence.Reserved = 0; |
157c24911 cifs: wrap receiv... |
183 |
mutex_lock(&server->srv_mutex); |
826a95e4a cifs: consolidate... |
184 185 |
rc = cifs_calc_signature(iov, nr_iov, server, what_we_think_sig_should_be); |
157c24911 cifs: wrap receiv... |
186 |
mutex_unlock(&server->srv_mutex); |
1da177e4c Linux-2.6.12-rc2 |
187 |
|
50c2f7538 [CIFS] whitespace... |
188 |
if (rc) |
1da177e4c Linux-2.6.12-rc2 |
189 |
return rc; |
50c2f7538 [CIFS] whitespace... |
190 191 |
/* cifs_dump_mem("what we think it should be: ", what_we_think_sig_should_be, 16); */ |
1da177e4c Linux-2.6.12-rc2 |
192 |
|
50c2f7538 [CIFS] whitespace... |
193 |
if (memcmp(server_response_sig, what_we_think_sig_should_be, 8)) |
1da177e4c Linux-2.6.12-rc2 |
194 195 196 197 198 |
return -EACCES; else return 0; } |
21e733930 NTLM auth and sig... |
199 |
/* first calculate 24 bytes ntlm response and then 16 byte session key */ |
9ef5992e4 cifs: Assume pass... |
200 |
int setup_ntlm_response(struct cifs_ses *ses, const struct nls_table *nls_cp) |
1da177e4c Linux-2.6.12-rc2 |
201 |
{ |
ee2c92585 cifs: More crypto... |
202 |
int rc = 0; |
21e733930 NTLM auth and sig... |
203 204 205 206 |
unsigned int temp_len = CIFS_SESS_KEY_SIZE + CIFS_AUTH_RESP_SIZE; char temp_key[CIFS_SESS_KEY_SIZE]; if (!ses) |
1da177e4c Linux-2.6.12-rc2 |
207 |
return -EINVAL; |
21e733930 NTLM auth and sig... |
208 209 210 211 212 213 |
ses->auth_key.response = kmalloc(temp_len, GFP_KERNEL); if (!ses->auth_key.response) { cERROR(1, "NTLM can't allocate (%u bytes) memory", temp_len); return -ENOMEM; } ses->auth_key.len = temp_len; |
ee2c92585 cifs: More crypto... |
214 |
rc = SMBNTencrypt(ses->password, ses->server->cryptkey, |
9ef5992e4 cifs: Assume pass... |
215 |
ses->auth_key.response + CIFS_SESS_KEY_SIZE, nls_cp); |
ee2c92585 cifs: More crypto... |
216 217 218 219 220 |
if (rc) { cFYI(1, "%s Can't generate NTLM response, error: %d", __func__, rc); return rc; } |
9ef5992e4 cifs: Assume pass... |
221 |
rc = E_md4hash(ses->password, temp_key, nls_cp); |
ee2c92585 cifs: More crypto... |
222 223 224 225 |
if (rc) { cFYI(1, "%s Can't generate NT hash, error: %d", __func__, rc); return rc; } |
21e733930 NTLM auth and sig... |
226 |
|
ee2c92585 cifs: More crypto... |
227 228 229 230 |
rc = mdfour(ses->auth_key.response, temp_key, CIFS_SESS_KEY_SIZE); if (rc) cFYI(1, "%s Can't generate NTLM session key, error: %d", __func__, rc); |
21e733930 NTLM auth and sig... |
231 |
|
ee2c92585 cifs: More crypto... |
232 |
return rc; |
1da177e4c Linux-2.6.12-rc2 |
233 |
} |
7c7b25bc8 [CIFS] Support fo... |
234 |
#ifdef CONFIG_CIFS_WEAK_PW_HASH |
43988d768 [CIFS] Use ecb de... |
235 |
int calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt, |
4e53a3fb9 cifs: have calc_l... |
236 |
char *lnm_session_key) |
7c7b25bc8 [CIFS] Support fo... |
237 238 |
{ int i; |
43988d768 [CIFS] Use ecb de... |
239 |
int rc; |
7c7b25bc8 [CIFS] Support fo... |
240 241 242 |
char password_with_pad[CIFS_ENCPWD_SIZE]; memset(password_with_pad, 0, CIFS_ENCPWD_SIZE); |
4e53a3fb9 cifs: have calc_l... |
243 244 |
if (password) strncpy(password_with_pad, password, CIFS_ENCPWD_SIZE); |
04912d6a2 cifs: rename "ext... |
245 |
if (!encrypt && global_secflags & CIFSSEC_MAY_PLNTXT) { |
4e53a3fb9 cifs: have calc_l... |
246 247 248 |
memset(lnm_session_key, 0, CIFS_SESS_KEY_SIZE); memcpy(lnm_session_key, password_with_pad, CIFS_ENCPWD_SIZE); |
43988d768 [CIFS] Use ecb de... |
249 |
return 0; |
4e53a3fb9 cifs: have calc_l... |
250 |
} |
bdc4bf6e8 [CIFS] Support fo... |
251 |
|
7c7b25bc8 [CIFS] Support fo... |
252 253 254 255 256 257 258 259 260 261 |
/* calculate old style session key */ /* calling toupper is less broken than repeatedly calling nls_toupper would be since that will never work for UTF8, but neither handles multibyte code pages but the only alternative would be converting to UCS-16 (Unicode) (using a routine something like UniStrupr) then uppercasing and then converting back from Unicode - which would only worth doing it if we knew it were utf8. Basically utf8 and other multibyte codepages each need their own strupper function since a byte at a time will ont work. */ |
ef571cadd [CIFS] Fix warnin... |
262 |
for (i = 0; i < CIFS_ENCPWD_SIZE; i++) |
7c7b25bc8 [CIFS] Support fo... |
263 |
password_with_pad[i] = toupper(password_with_pad[i]); |
7c7b25bc8 [CIFS] Support fo... |
264 |
|
43988d768 [CIFS] Use ecb de... |
265 |
rc = SMBencrypt(password_with_pad, cryptkey, lnm_session_key); |
4e53a3fb9 cifs: have calc_l... |
266 |
|
43988d768 [CIFS] Use ecb de... |
267 |
return rc; |
7c7b25bc8 [CIFS] Support fo... |
268 269 |
} #endif /* CIFS_WEAK_PW_HASH */ |
9daa42e22 CIFS ntlm authent... |
270 271 272 273 |
/* Build a proper attribute value/target info pairs blob. * Fill in netbios and dns domain name and workstation name * and client time (total five av pairs and + one end of fields indicator. * Allocate domain name which gets freed when session struct is deallocated. |
2b149f119 cifs NTLMv2/NTLMS... |
274 275 |
*/ static int |
96daf2b09 [CIFS] Rename thr... |
276 |
build_avpair_blob(struct cifs_ses *ses, const struct nls_table *nls_cp) |
2b149f119 cifs NTLMv2/NTLMS... |
277 |
{ |
9daa42e22 CIFS ntlm authent... |
278 |
unsigned int dlen; |
cfbd6f84c cifs: Fix broken ... |
279 |
unsigned int size = 2 * sizeof(struct ntlmssp2_name); |
9daa42e22 CIFS ntlm authent... |
280 281 |
char *defdmname = "WORKGROUP"; unsigned char *blobptr; |
2b149f119 cifs NTLMv2/NTLMS... |
282 |
struct ntlmssp2_name *attrptr; |
9daa42e22 CIFS ntlm authent... |
283 284 285 286 287 288 289 |
if (!ses->domainName) { ses->domainName = kstrdup(defdmname, GFP_KERNEL); if (!ses->domainName) return -ENOMEM; } dlen = strlen(ses->domainName); |
9daa42e22 CIFS ntlm authent... |
290 |
|
cfbd6f84c cifs: Fix broken ... |
291 292 293 294 295 |
/* * The length of this blob is two times the size of a * structure (av pair) which holds name/size * ( for NTLMSSP_AV_NB_DOMAIN_NAME followed by NTLMSSP_AV_EOL ) + * unicode length of a netbios domain name |
9daa42e22 CIFS ntlm authent... |
296 |
*/ |
cfbd6f84c cifs: Fix broken ... |
297 |
ses->auth_key.len = size + 2 * dlen; |
d3686d54c cifs: Cleanup and... |
298 299 300 |
ses->auth_key.response = kzalloc(ses->auth_key.len, GFP_KERNEL); if (!ses->auth_key.response) { ses->auth_key.len = 0; |
2b149f119 cifs NTLMv2/NTLMS... |
301 302 303 |
cERROR(1, "Challenge target info allocation failure"); return -ENOMEM; } |
9daa42e22 CIFS ntlm authent... |
304 |
|
d3686d54c cifs: Cleanup and... |
305 |
blobptr = ses->auth_key.response; |
9daa42e22 CIFS ntlm authent... |
306 |
attrptr = (struct ntlmssp2_name *) blobptr; |
cfbd6f84c cifs: Fix broken ... |
307 308 309 310 |
/* * As defined in MS-NTLM 3.3.2, just this av pair field * is sufficient as part of the temp */ |
9daa42e22 CIFS ntlm authent... |
311 312 313 314 |
attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_DOMAIN_NAME); attrptr->length = cpu_to_le16(2 * dlen); blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name); cifs_strtoUCS((__le16 *)blobptr, ses->domainName, dlen, nls_cp); |
2b149f119 cifs NTLMv2/NTLMS... |
315 316 317 318 319 320 321 322 323 324 325 326 327 328 |
return 0; } /* Server has provided av pairs/target info in the type 2 challenge * packet and we have plucked it and stored within smb session. * We parse that blob here to find netbios domain name to be used * as part of ntlmv2 authentication (in Target String), if not already * specified on the command line. * If this function returns without any error but without fetching * domain name, authentication may fail against some server but * may not fail against other (those who are not very particular * about target string i.e. for some, just user name might suffice. */ static int |
96daf2b09 [CIFS] Rename thr... |
329 |
find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp) |
2b149f119 cifs NTLMv2/NTLMS... |
330 331 332 333 334 335 336 |
{ unsigned int attrsize; unsigned int type; unsigned int onesize = sizeof(struct ntlmssp2_name); unsigned char *blobptr; unsigned char *blobend; struct ntlmssp2_name *attrptr; |
d3686d54c cifs: Cleanup and... |
337 |
if (!ses->auth_key.len || !ses->auth_key.response) |
2b149f119 cifs NTLMv2/NTLMS... |
338 |
return 0; |
d3686d54c cifs: Cleanup and... |
339 340 |
blobptr = ses->auth_key.response; blobend = blobptr + ses->auth_key.len; |
2b149f119 cifs NTLMv2/NTLMS... |
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 |
while (blobptr + onesize < blobend) { attrptr = (struct ntlmssp2_name *) blobptr; type = le16_to_cpu(attrptr->type); if (type == NTLMSSP_AV_EOL) break; blobptr += 2; /* advance attr type */ attrsize = le16_to_cpu(attrptr->length); blobptr += 2; /* advance attr size */ if (blobptr + attrsize > blobend) break; if (type == NTLMSSP_AV_NB_DOMAIN_NAME) { if (!attrsize) break; if (!ses->domainName) { ses->domainName = kmalloc(attrsize + 1, GFP_KERNEL); if (!ses->domainName) return -ENOMEM; cifs_from_ucs2(ses->domainName, (__le16 *)blobptr, attrsize, attrsize, |
f7c5445a9 NTLM auth and sig... |
362 |
nls_cp, false); |
2b149f119 cifs NTLMv2/NTLMS... |
363 364 365 366 367 368 369 370 |
break; } } blobptr += attrsize; /* advance attr value */ } return 0; } |
96daf2b09 [CIFS] Rename thr... |
371 |
static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash, |
50c2f7538 [CIFS] whitespace... |
372 |
const struct nls_table *nls_cp) |
a8ee03441 [CIFS] NTLMv2 sup... |
373 374 375 |
{ int rc = 0; int len; |
307fbd31b NTLM auth and sig... |
376 |
char nt_hash[CIFS_NTHASH_SIZE]; |
50c2f7538 [CIFS] whitespace... |
377 378 |
wchar_t *user; wchar_t *domain; |
307fbd31b NTLM auth and sig... |
379 |
wchar_t *server; |
a8ee03441 [CIFS] NTLMv2 sup... |
380 |
|
307fbd31b NTLM auth and sig... |
381 382 383 384 385 |
if (!ses->server->secmech.sdeschmacmd5) { cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash "); return -1; } |
56234e276 Revert "Eliminate... |
386 |
|
c8e56f1f4 Revert "[CIFS] Fi... |
387 |
/* calculate md4 hash of password */ |
9ef5992e4 cifs: Assume pass... |
388 |
E_md4hash(ses->password, nt_hash, nls_cp); |
9fbc59086 [CIFS] Fix ntlmv2... |
389 |
|
14cae3243 cifs: Cleanup: ch... |
390 |
rc = crypto_shash_setkey(ses->server->secmech.hmacmd5, nt_hash, |
307fbd31b NTLM auth and sig... |
391 |
CIFS_NTHASH_SIZE); |
14cae3243 cifs: Cleanup: ch... |
392 393 394 395 |
if (rc) { cERROR(1, "%s: Could not set NT Hash as a key", __func__); return rc; } |
307fbd31b NTLM auth and sig... |
396 397 398 399 400 401 402 |
rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash); if (rc) { cERROR(1, "calc_ntlmv2_hash: could not init hmacmd5 "); return rc; } |
a8ee03441 [CIFS] NTLMv2 sup... |
403 |
|
8727c8a85 Allow user names ... |
404 405 |
/* convert ses->user_name to unicode and uppercase */ len = strlen(ses->user_name); |
1717ffc58 [CIFS] NTLMv2 sup... |
406 |
user = kmalloc(2 + (len * 2), GFP_KERNEL); |
307fbd31b NTLM auth and sig... |
407 408 409 410 |
if (user == NULL) { cERROR(1, "calc_ntlmv2_hash: user mem alloc failure "); rc = -ENOMEM; |
14cae3243 cifs: Cleanup: ch... |
411 |
return rc; |
307fbd31b NTLM auth and sig... |
412 |
} |
8727c8a85 Allow user names ... |
413 |
len = cifs_strtoUCS((__le16 *)user, ses->user_name, len, nls_cp); |
1717ffc58 [CIFS] NTLMv2 sup... |
414 |
UniStrupr(user); |
307fbd31b NTLM auth and sig... |
415 |
|
14cae3243 cifs: Cleanup: ch... |
416 |
rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash, |
307fbd31b NTLM auth and sig... |
417 |
(char *)user, 2 * len); |
14cae3243 cifs: Cleanup: ch... |
418 419 420 421 422 423 |
kfree(user); if (rc) { cERROR(1, "%s: Could not update with user ", __func__); return rc; } |
a8ee03441 [CIFS] NTLMv2 sup... |
424 425 |
/* convert ses->domainName to unicode and uppercase */ |
50c2f7538 [CIFS] whitespace... |
426 |
if (ses->domainName) { |
1717ffc58 [CIFS] NTLMv2 sup... |
427 |
len = strlen(ses->domainName); |
a8ee03441 [CIFS] NTLMv2 sup... |
428 |
|
50c2f7538 [CIFS] whitespace... |
429 |
domain = kmalloc(2 + (len * 2), GFP_KERNEL); |
307fbd31b NTLM auth and sig... |
430 431 432 |
if (domain == NULL) { cERROR(1, "calc_ntlmv2_hash: domain mem alloc failure"); rc = -ENOMEM; |
14cae3243 cifs: Cleanup: ch... |
433 |
return rc; |
307fbd31b NTLM auth and sig... |
434 |
} |
8f2376adf [CIFS] Fix endian... |
435 436 |
len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len, nls_cp); |
14cae3243 cifs: Cleanup: ch... |
437 |
rc = |
307fbd31b NTLM auth and sig... |
438 439 |
crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash, (char *)domain, 2 * len); |
1717ffc58 [CIFS] NTLMv2 sup... |
440 |
kfree(domain); |
14cae3243 cifs: Cleanup: ch... |
441 442 443 444 445 446 |
if (rc) { cERROR(1, "%s: Could not update with domain ", __func__); return rc; } |
307fbd31b NTLM auth and sig... |
447 448 449 450 451 452 453 |
} else if (ses->serverName) { len = strlen(ses->serverName); server = kmalloc(2 + (len * 2), GFP_KERNEL); if (server == NULL) { cERROR(1, "calc_ntlmv2_hash: server mem alloc failure"); rc = -ENOMEM; |
14cae3243 cifs: Cleanup: ch... |
454 |
return rc; |
307fbd31b NTLM auth and sig... |
455 456 457 |
} len = cifs_strtoUCS((__le16 *)server, ses->serverName, len, nls_cp); |
14cae3243 cifs: Cleanup: ch... |
458 |
rc = |
307fbd31b NTLM auth and sig... |
459 460 461 |
crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash, (char *)server, 2 * len); kfree(server); |
14cae3243 cifs: Cleanup: ch... |
462 463 464 465 466 467 |
if (rc) { cERROR(1, "%s: Could not update with server ", __func__); return rc; } |
1717ffc58 [CIFS] NTLMv2 sup... |
468 |
} |
307fbd31b NTLM auth and sig... |
469 470 |
rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash, |
d3686d54c cifs: Cleanup and... |
471 |
ntlmv2_hash); |
14cae3243 cifs: Cleanup: ch... |
472 473 474 |
if (rc) cERROR(1, "%s: Could not generate md5 hash ", __func__); |
307fbd31b NTLM auth and sig... |
475 |
|
307fbd31b NTLM auth and sig... |
476 477 478 479 |
return rc; } static int |
96daf2b09 [CIFS] Rename thr... |
480 |
CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash) |
307fbd31b NTLM auth and sig... |
481 482 483 484 485 486 487 488 489 |
{ int rc; unsigned int offset = CIFS_SESS_KEY_SIZE + 8; if (!ses->server->secmech.sdeschmacmd5) { cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash "); return -1; } |
14cae3243 cifs: Cleanup: ch... |
490 |
rc = crypto_shash_setkey(ses->server->secmech.hmacmd5, |
d3686d54c cifs: Cleanup and... |
491 |
ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE); |
14cae3243 cifs: Cleanup: ch... |
492 493 494 495 |
if (rc) { cERROR(1, "%s: Could not set NTLMV2 Hash as a key", __func__); return rc; } |
307fbd31b NTLM auth and sig... |
496 497 498 499 500 501 |
rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash); if (rc) { cERROR(1, "CalcNTLMv2_response: could not init hmacmd5"); return rc; } |
d3ba50b17 NTLM auth and sig... |
502 503 |
if (ses->server->secType == RawNTLMSSP) memcpy(ses->auth_key.response + offset, |
d3686d54c cifs: Cleanup and... |
504 |
ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE); |
d3ba50b17 NTLM auth and sig... |
505 506 507 |
else memcpy(ses->auth_key.response + offset, ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE); |
14cae3243 cifs: Cleanup: ch... |
508 |
rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash, |
307fbd31b NTLM auth and sig... |
509 |
ses->auth_key.response + offset, ses->auth_key.len - offset); |
14cae3243 cifs: Cleanup: ch... |
510 511 512 513 514 |
if (rc) { cERROR(1, "%s: Could not update with response ", __func__); return rc; } |
307fbd31b NTLM auth and sig... |
515 516 517 |
rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash, ses->auth_key.response + CIFS_SESS_KEY_SIZE); |
14cae3243 cifs: Cleanup: ch... |
518 519 520 |
if (rc) cERROR(1, "%s: Could not generate md5 hash ", __func__); |
9fbc59086 [CIFS] Fix ntlmv2... |
521 522 523 |
return rc; } |
307fbd31b NTLM auth and sig... |
524 |
|
2b149f119 cifs NTLMv2/NTLMS... |
525 |
int |
96daf2b09 [CIFS] Rename thr... |
526 |
setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) |
9fbc59086 [CIFS] Fix ntlmv2... |
527 |
{ |
c8e56f1f4 Revert "[CIFS] Fi... |
528 |
int rc; |
21e733930 NTLM auth and sig... |
529 |
int baselen; |
d3686d54c cifs: Cleanup and... |
530 |
unsigned int tilen; |
21e733930 NTLM auth and sig... |
531 |
struct ntlmv2_resp *buf; |
d3686d54c cifs: Cleanup and... |
532 533 |
char ntlmv2_hash[16]; unsigned char *tiblob = NULL; /* target info blob */ |
6d027cfdb [CIFS] NTLMv2 sup... |
534 |
|
2b149f119 cifs NTLMv2/NTLMS... |
535 536 |
if (ses->server->secType == RawNTLMSSP) { if (!ses->domainName) { |
f7c5445a9 NTLM auth and sig... |
537 |
rc = find_domain_name(ses, nls_cp); |
2b149f119 cifs NTLMv2/NTLMS... |
538 539 540 541 542 543 |
if (rc) { cERROR(1, "error %d finding domain name", rc); goto setup_ntlmv2_rsp_ret; } } } else { |
9daa42e22 CIFS ntlm authent... |
544 |
rc = build_avpair_blob(ses, nls_cp); |
2b149f119 cifs NTLMv2/NTLMS... |
545 546 |
if (rc) { cERROR(1, "error %d building av pair blob", rc); |
d3686d54c cifs: Cleanup and... |
547 |
goto setup_ntlmv2_rsp_ret; |
2b149f119 cifs NTLMv2/NTLMS... |
548 549 |
} } |
a8ee03441 [CIFS] NTLMv2 sup... |
550 |
|
21e733930 NTLM auth and sig... |
551 |
baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp); |
d3686d54c cifs: Cleanup and... |
552 553 554 555 |
tilen = ses->auth_key.len; tiblob = ses->auth_key.response; ses->auth_key.response = kmalloc(baselen + tilen, GFP_KERNEL); |
21e733930 NTLM auth and sig... |
556 557 |
if (!ses->auth_key.response) { rc = ENOMEM; |
d3686d54c cifs: Cleanup and... |
558 |
ses->auth_key.len = 0; |
21e733930 NTLM auth and sig... |
559 560 561 |
cERROR(1, "%s: Can't allocate auth blob", __func__); goto setup_ntlmv2_rsp_ret; } |
d3686d54c cifs: Cleanup and... |
562 |
ses->auth_key.len += baselen; |
21e733930 NTLM auth and sig... |
563 564 565 566 567 568 569 570 |
buf = (struct ntlmv2_resp *) (ses->auth_key.response + CIFS_SESS_KEY_SIZE); buf->blob_signature = cpu_to_le32(0x00000101); buf->reserved = 0; buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); get_random_bytes(&buf->client_chal, sizeof(buf->client_chal)); buf->reserved2 = 0; |
d3686d54c cifs: Cleanup and... |
571 |
memcpy(ses->auth_key.response + baselen, tiblob, tilen); |
21e733930 NTLM auth and sig... |
572 |
|
f7c5445a9 NTLM auth and sig... |
573 |
/* calculate ntlmv2_hash */ |
d3686d54c cifs: Cleanup and... |
574 |
rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp); |
2b149f119 cifs NTLMv2/NTLMS... |
575 |
if (rc) { |
b6b38f704 [CIFS] Neaten cER... |
576 |
cERROR(1, "could not get v2 hash rc %d", rc); |
2b149f119 cifs NTLMv2/NTLMS... |
577 578 |
goto setup_ntlmv2_rsp_ret; } |
f7c5445a9 NTLM auth and sig... |
579 580 |
/* calculate first part of the client response (CR1) */ |
d3686d54c cifs: Cleanup and... |
581 |
rc = CalcNTLMv2_response(ses, ntlmv2_hash); |
307fbd31b NTLM auth and sig... |
582 583 584 585 |
if (rc) { cERROR(1, "Could not calculate CR1 rc: %d", rc); goto setup_ntlmv2_rsp_ret; } |
b609f06ac [CIFS] Fix packet... |
586 |
|
5d0d28824 NTLM authenticati... |
587 |
/* now calculate the session key for NTLMv2 */ |
14cae3243 cifs: Cleanup: ch... |
588 |
rc = crypto_shash_setkey(ses->server->secmech.hmacmd5, |
d3686d54c cifs: Cleanup and... |
589 |
ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE); |
14cae3243 cifs: Cleanup: ch... |
590 591 592 593 |
if (rc) { cERROR(1, "%s: Could not set NTLMV2 Hash as a key", __func__); goto setup_ntlmv2_rsp_ret; } |
307fbd31b NTLM auth and sig... |
594 595 596 597 598 599 600 |
rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash); if (rc) { cERROR(1, "%s: Could not init hmacmd5 ", __func__); goto setup_ntlmv2_rsp_ret; } |
14cae3243 cifs: Cleanup: ch... |
601 |
rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash, |
307fbd31b NTLM auth and sig... |
602 603 |
ses->auth_key.response + CIFS_SESS_KEY_SIZE, CIFS_HMAC_MD5_HASH_SIZE); |
14cae3243 cifs: Cleanup: ch... |
604 605 606 607 608 |
if (rc) { cERROR(1, "%s: Could not update with response ", __func__); goto setup_ntlmv2_rsp_ret; } |
307fbd31b NTLM auth and sig... |
609 610 611 |
rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash, ses->auth_key.response); |
14cae3243 cifs: Cleanup: ch... |
612 613 614 |
if (rc) cERROR(1, "%s: Could not generate md5 hash ", __func__); |
2b149f119 cifs NTLMv2/NTLMS... |
615 |
|
2b149f119 cifs NTLMv2/NTLMS... |
616 |
setup_ntlmv2_rsp_ret: |
d3686d54c cifs: Cleanup and... |
617 |
kfree(tiblob); |
2b149f119 cifs NTLMv2/NTLMS... |
618 619 |
return rc; |
6d027cfdb [CIFS] NTLMv2 sup... |
620 |
} |
d2b915210 NTLM auth and sig... |
621 |
int |
96daf2b09 [CIFS] Rename thr... |
622 |
calc_seckey(struct cifs_ses *ses) |
d2b915210 NTLM auth and sig... |
623 624 625 626 627 628 629 630 631 632 |
{ int rc; struct crypto_blkcipher *tfm_arc4; struct scatterlist sgin, sgout; struct blkcipher_desc desc; unsigned char sec_key[CIFS_SESS_KEY_SIZE]; /* a nonce */ get_random_bytes(sec_key, CIFS_SESS_KEY_SIZE); tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); |
7a8587e7c cifs: No need to ... |
633 634 |
if (IS_ERR(tfm_arc4)) { rc = PTR_ERR(tfm_arc4); |
d2b915210 NTLM auth and sig... |
635 636 |
cERROR(1, "could not allocate crypto API arc4 "); |
7a8587e7c cifs: No need to ... |
637 |
return rc; |
d2b915210 NTLM auth and sig... |
638 639 640 |
} desc.tfm = tfm_arc4; |
14cae3243 cifs: Cleanup: ch... |
641 |
rc = crypto_blkcipher_setkey(tfm_arc4, ses->auth_key.response, |
d2b915210 NTLM auth and sig... |
642 |
CIFS_SESS_KEY_SIZE); |
14cae3243 cifs: Cleanup: ch... |
643 644 645 646 |
if (rc) { cERROR(1, "%s: Could not set response as a key", __func__); return rc; } |
d2b915210 NTLM auth and sig... |
647 648 |
sg_init_one(&sgin, sec_key, CIFS_SESS_KEY_SIZE); |
d3686d54c cifs: Cleanup and... |
649 |
sg_init_one(&sgout, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE); |
d2b915210 NTLM auth and sig... |
650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 |
rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, CIFS_CPHTXT_SIZE); if (rc) { cERROR(1, "could not encrypt session key rc: %d ", rc); crypto_free_blkcipher(tfm_arc4); return rc; } /* make secondary_key/nonce as session key */ memcpy(ses->auth_key.response, sec_key, CIFS_SESS_KEY_SIZE); /* and make len as that of session key only */ ses->auth_key.len = CIFS_SESS_KEY_SIZE; crypto_free_blkcipher(tfm_arc4); |
14cae3243 cifs: Cleanup: ch... |
665 |
return rc; |
d2b915210 NTLM auth and sig... |
666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 |
} void cifs_crypto_shash_release(struct TCP_Server_Info *server) { if (server->secmech.md5) crypto_free_shash(server->secmech.md5); if (server->secmech.hmacmd5) crypto_free_shash(server->secmech.hmacmd5); kfree(server->secmech.sdeschmacmd5); kfree(server->secmech.sdescmd5); } int cifs_crypto_shash_allocate(struct TCP_Server_Info *server) { int rc; unsigned int size; server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0); |
ee2c92585 cifs: More crypto... |
689 |
if (IS_ERR(server->secmech.hmacmd5)) { |
d2b915210 NTLM auth and sig... |
690 691 692 693 694 695 |
cERROR(1, "could not allocate crypto hmacmd5 "); return PTR_ERR(server->secmech.hmacmd5); } server->secmech.md5 = crypto_alloc_shash("md5", 0, 0); |
ee2c92585 cifs: More crypto... |
696 |
if (IS_ERR(server->secmech.md5)) { |
d2b915210 NTLM auth and sig... |
697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 |
cERROR(1, "could not allocate crypto md5 "); rc = PTR_ERR(server->secmech.md5); goto crypto_allocate_md5_fail; } size = sizeof(struct shash_desc) + crypto_shash_descsize(server->secmech.hmacmd5); server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL); if (!server->secmech.sdeschmacmd5) { cERROR(1, "cifs_crypto_shash_allocate: can't alloc hmacmd5 "); rc = -ENOMEM; goto crypto_allocate_hmacmd5_sdesc_fail; } server->secmech.sdeschmacmd5->shash.tfm = server->secmech.hmacmd5; server->secmech.sdeschmacmd5->shash.flags = 0x0; size = sizeof(struct shash_desc) + crypto_shash_descsize(server->secmech.md5); server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL); if (!server->secmech.sdescmd5) { cERROR(1, "cifs_crypto_shash_allocate: can't alloc md5 "); rc = -ENOMEM; goto crypto_allocate_md5_sdesc_fail; } server->secmech.sdescmd5->shash.tfm = server->secmech.md5; server->secmech.sdescmd5->shash.flags = 0x0; return 0; crypto_allocate_md5_sdesc_fail: kfree(server->secmech.sdeschmacmd5); crypto_allocate_hmacmd5_sdesc_fail: crypto_free_shash(server->secmech.md5); crypto_allocate_md5_fail: crypto_free_shash(server->secmech.hmacmd5); return rc; } |