aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2010-08-20 16:42:26 -0400
committerSteve French <sfrench@us.ibm.com>2010-08-20 16:42:26 -0400
commit9fbc590860e75785bdaf8b83e48fabfe4d4f7d58 (patch)
treedccc154927cf1e12c702537b5bc028158b938e21 /fs/cifs
parentbf4f12113812ac5be76c5590c6f50c8346f784a4 (diff)
[CIFS] Fix ntlmv2 auth with ntlmssp
Make ntlmv2 as an authentication mechanism within ntlmssp instead of ntlmv1. Parse type 2 response in ntlmssp negotiation to pluck AV pairs and use them to calculate ntlmv2 response token. Also, assign domain name from the sever response in type 2 packet of ntlmssp and use that (netbios) domain name in calculation of response. Enable cifs/smb signing using rc4 and md5. Changed name of the structure mac_key to session_key to reflect the type of key it holds. Use kernel crypto_shash_* APIs instead of the equivalent cifs functions. Signed-off-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com> Acked-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/Kconfig2
-rw-r--r--fs/cifs/asn1.c6
-rw-r--r--fs/cifs/cifsencrypt.c416
-rw-r--r--fs/cifs/cifsglob.h18
-rw-r--r--fs/cifs/cifspdu.h7
-rw-r--r--fs/cifs/cifsproto.h12
-rw-r--r--fs/cifs/cifssmb.c13
-rw-r--r--fs/cifs/connect.c13
-rw-r--r--fs/cifs/ntlmssp.h13
-rw-r--r--fs/cifs/sess.c118
-rw-r--r--fs/cifs/transport.c6
11 files changed, 452 insertions, 172 deletions
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig
index 917b7d449bb2..0da1debd499d 100644
--- a/fs/cifs/Kconfig
+++ b/fs/cifs/Kconfig
@@ -2,6 +2,8 @@ config CIFS
2 tristate "CIFS support (advanced network filesystem, SMBFS successor)" 2 tristate "CIFS support (advanced network filesystem, SMBFS successor)"
3 depends on INET 3 depends on INET
4 select NLS 4 select NLS
5 select CRYPTO_MD5
6 select CRYPTO_ARC4
5 help 7 help
6 This is the client VFS module for the Common Internet File System 8 This is the client VFS module for the Common Internet File System
7 (CIFS) protocol which is the successor to the Server Message Block 9 (CIFS) protocol which is the successor to the Server Message Block
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
index cfd1ce34e0bc..21f0fbd86989 100644
--- a/fs/cifs/asn1.c
+++ b/fs/cifs/asn1.c
@@ -597,13 +597,13 @@ decode_negTokenInit(unsigned char *security_blob, int length,
597 if (compare_oid(oid, oidlen, MSKRB5_OID, 597 if (compare_oid(oid, oidlen, MSKRB5_OID,
598 MSKRB5_OID_LEN)) 598 MSKRB5_OID_LEN))
599 server->sec_mskerberos = true; 599 server->sec_mskerberos = true;
600 else if (compare_oid(oid, oidlen, KRB5U2U_OID, 600 if (compare_oid(oid, oidlen, KRB5U2U_OID,
601 KRB5U2U_OID_LEN)) 601 KRB5U2U_OID_LEN))
602 server->sec_kerberosu2u = true; 602 server->sec_kerberosu2u = true;
603 else if (compare_oid(oid, oidlen, KRB5_OID, 603 if (compare_oid(oid, oidlen, KRB5_OID,
604 KRB5_OID_LEN)) 604 KRB5_OID_LEN))
605 server->sec_kerberos = true; 605 server->sec_kerberos = true;
606 else if (compare_oid(oid, oidlen, NTLMSSP_OID, 606 if (compare_oid(oid, oidlen, NTLMSSP_OID,
607 NTLMSSP_OID_LEN)) 607 NTLMSSP_OID_LEN))
608 server->sec_ntlmssp = true; 608 server->sec_ntlmssp = true;
609 609
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 847628dfdc44..051d00011ca3 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -27,6 +27,7 @@
27#include "md5.h" 27#include "md5.h"
28#include "cifs_unicode.h" 28#include "cifs_unicode.h"
29#include "cifsproto.h" 29#include "cifsproto.h"
30#include "ntlmssp.h"
30#include <linux/ctype.h> 31#include <linux/ctype.h>
31#include <linux/random.h> 32#include <linux/random.h>
32 33
@@ -42,21 +43,44 @@ extern void SMBencrypt(unsigned char *passwd, const unsigned char *c8,
42 unsigned char *p24); 43 unsigned char *p24);
43 44
44static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu, 45static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
45 const struct mac_key *key, char *signature) 46 struct TCP_Server_Info *server, char *signature)
46{ 47{
47 struct MD5Context context; 48 int rc = 0;
49 struct {
50 struct shash_desc shash;
51 char ctx[crypto_shash_descsize(server->ntlmssp.md5)];
52 } sdesc;
48 53
49 if ((cifs_pdu == NULL) || (signature == NULL) || (key == NULL)) 54 if (cifs_pdu == NULL || server == NULL || signature == NULL)
50 return -EINVAL; 55 return -EINVAL;
51 56
52 cifs_MD5_init(&context); 57 sdesc.shash.tfm = server->ntlmssp.md5;
53 cifs_MD5_update(&context, (char *)&key->data, key->len); 58 sdesc.shash.flags = 0x0;
54 cifs_MD5_update(&context, cifs_pdu->Protocol, cifs_pdu->smb_buf_length); 59
60 rc = crypto_shash_init(&sdesc.shash);
61 if (rc) {
62 cERROR(1, "could not initialize master crypto API hmacmd5\n");
63 return rc;
64 }
65
66 if (server->secType == RawNTLMSSP)
67 crypto_shash_update(&sdesc.shash,
68 server->session_key.data.ntlmv2.key,
69 CIFS_NTLMV2_SESSKEY_SIZE);
70 else
71 crypto_shash_update(&sdesc.shash,
72 (char *)&server->session_key.data,
73 server->session_key.len);
74
75 crypto_shash_update(&sdesc.shash,
76 cifs_pdu->Protocol, cifs_pdu->smb_buf_length);
77
78 rc = crypto_shash_final(&sdesc.shash, signature);
55 79
56 cifs_MD5_final(signature, &context);
57 return 0; 80 return 0;
58} 81}
59 82
83
60int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, 84int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
61 __u32 *pexpected_response_sequence_number) 85 __u32 *pexpected_response_sequence_number)
62{ 86{
@@ -78,8 +102,7 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
78 server->sequence_number++; 102 server->sequence_number++;
79 spin_unlock(&GlobalMid_Lock); 103 spin_unlock(&GlobalMid_Lock);
80 104
81 rc = cifs_calculate_signature(cifs_pdu, &server->mac_signing_key, 105 rc = cifs_calculate_signature(cifs_pdu, server, smb_signature);
82 smb_signature);
83 if (rc) 106 if (rc)
84 memset(cifs_pdu->Signature.SecuritySignature, 0, 8); 107 memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
85 else 108 else
@@ -89,16 +112,36 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
89} 112}
90 113
91static int cifs_calc_signature2(const struct kvec *iov, int n_vec, 114static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
92 const struct mac_key *key, char *signature) 115 struct TCP_Server_Info *server, char *signature)
93{ 116{
94 struct MD5Context context;
95 int i; 117 int i;
118 int rc = 0;
119 struct {
120 struct shash_desc shash;
121 char ctx[crypto_shash_descsize(server->ntlmssp.md5)];
122 } sdesc;
96 123
97 if ((iov == NULL) || (signature == NULL) || (key == NULL)) 124 if (iov == NULL || server == NULL || signature == NULL)
98 return -EINVAL; 125 return -EINVAL;
99 126
100 cifs_MD5_init(&context); 127 sdesc.shash.tfm = server->ntlmssp.md5;
101 cifs_MD5_update(&context, (char *)&key->data, key->len); 128 sdesc.shash.flags = 0x0;
129
130 rc = crypto_shash_init(&sdesc.shash);
131 if (rc) {
132 cERROR(1, "could not initialize master crypto API hmacmd5\n");
133 return rc;
134 }
135
136 if (server->secType == RawNTLMSSP)
137 crypto_shash_update(&sdesc.shash,
138 server->session_key.data.ntlmv2.key,
139 CIFS_NTLMV2_SESSKEY_SIZE);
140 else
141 crypto_shash_update(&sdesc.shash,
142 (char *)&server->session_key.data,
143 server->session_key.len);
144
102 for (i = 0; i < n_vec; i++) { 145 for (i = 0; i < n_vec; i++) {
103 if (iov[i].iov_len == 0) 146 if (iov[i].iov_len == 0)
104 continue; 147 continue;
@@ -111,18 +154,18 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
111 if (i == 0) { 154 if (i == 0) {
112 if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ 155 if (iov[0].iov_len <= 8) /* cmd field at offset 9 */
113 break; /* nothing to sign or corrupt header */ 156 break; /* nothing to sign or corrupt header */
114 cifs_MD5_update(&context, iov[0].iov_base+4, 157 crypto_shash_update(&sdesc.shash,
115 iov[0].iov_len-4); 158 iov[i].iov_base + 4, iov[i].iov_len - 4);
116 } else 159 } else
117 cifs_MD5_update(&context, iov[i].iov_base, iov[i].iov_len); 160 crypto_shash_update(&sdesc.shash,
161 iov[i].iov_base, iov[i].iov_len);
118 } 162 }
119 163
120 cifs_MD5_final(signature, &context); 164 rc = crypto_shash_final(&sdesc.shash, signature);
121 165
122 return 0; 166 return 0;
123} 167}
124 168
125
126int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, 169int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
127 __u32 *pexpected_response_sequence_number) 170 __u32 *pexpected_response_sequence_number)
128{ 171{
@@ -145,8 +188,7 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
145 server->sequence_number++; 188 server->sequence_number++;
146 spin_unlock(&GlobalMid_Lock); 189 spin_unlock(&GlobalMid_Lock);
147 190
148 rc = cifs_calc_signature2(iov, n_vec, &server->mac_signing_key, 191 rc = cifs_calc_signature2(iov, n_vec, server, smb_signature);
149 smb_signature);
150 if (rc) 192 if (rc)
151 memset(cifs_pdu->Signature.SecuritySignature, 0, 8); 193 memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
152 else 194 else
@@ -156,14 +198,14 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
156} 198}
157 199
158int cifs_verify_signature(struct smb_hdr *cifs_pdu, 200int cifs_verify_signature(struct smb_hdr *cifs_pdu,
159 const struct mac_key *mac_key, 201 struct TCP_Server_Info *server,
160 __u32 expected_sequence_number) 202 __u32 expected_sequence_number)
161{ 203{
162 unsigned int rc; 204 int rc;
163 char server_response_sig[8]; 205 char server_response_sig[8];
164 char what_we_think_sig_should_be[20]; 206 char what_we_think_sig_should_be[20];
165 207
166 if ((cifs_pdu == NULL) || (mac_key == NULL)) 208 if (cifs_pdu == NULL || server == NULL)
167 return -EINVAL; 209 return -EINVAL;
168 210
169 if (cifs_pdu->Command == SMB_COM_NEGOTIATE) 211 if (cifs_pdu->Command == SMB_COM_NEGOTIATE)
@@ -192,7 +234,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu,
192 cpu_to_le32(expected_sequence_number); 234 cpu_to_le32(expected_sequence_number);
193 cifs_pdu->Signature.Sequence.Reserved = 0; 235 cifs_pdu->Signature.Sequence.Reserved = 0;
194 236
195 rc = cifs_calculate_signature(cifs_pdu, mac_key, 237 rc = cifs_calculate_signature(cifs_pdu, server,
196 what_we_think_sig_should_be); 238 what_we_think_sig_should_be);
197 239
198 if (rc) 240 if (rc)
@@ -209,7 +251,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu,
209} 251}
210 252
211/* We fill in key by putting in 40 byte array which was allocated by caller */ 253/* We fill in key by putting in 40 byte array which was allocated by caller */
212int cifs_calculate_mac_key(struct mac_key *key, const char *rn, 254int cifs_calculate_session_key(struct session_key *key, const char *rn,
213 const char *password) 255 const char *password)
214{ 256{
215 char temp_key[16]; 257 char temp_key[16];
@@ -223,63 +265,6 @@ int cifs_calculate_mac_key(struct mac_key *key, const char *rn,
223 return 0; 265 return 0;
224} 266}
225 267
226int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *ses,
227 const struct nls_table *nls_info)
228{
229 char temp_hash[16];
230 struct HMACMD5Context ctx;
231 char *ucase_buf;
232 __le16 *unicode_buf;
233 unsigned int i, user_name_len, dom_name_len;
234
235 if (ses == NULL)
236 return -EINVAL;
237
238 E_md4hash(ses->password, temp_hash);
239
240 hmac_md5_init_limK_to_64(temp_hash, 16, &ctx);
241 user_name_len = strlen(ses->userName);
242 if (user_name_len > MAX_USERNAME_SIZE)
243 return -EINVAL;
244 if (ses->domainName == NULL)
245 return -EINVAL; /* BB should we use CIFS_LINUX_DOM */
246 dom_name_len = strlen(ses->domainName);
247 if (dom_name_len > MAX_USERNAME_SIZE)
248 return -EINVAL;
249
250 ucase_buf = kmalloc((MAX_USERNAME_SIZE+1), GFP_KERNEL);
251 if (ucase_buf == NULL)
252 return -ENOMEM;
253 unicode_buf = kmalloc((MAX_USERNAME_SIZE+1)*4, GFP_KERNEL);
254 if (unicode_buf == NULL) {
255 kfree(ucase_buf);
256 return -ENOMEM;
257 }
258
259 for (i = 0; i < user_name_len; i++)
260 ucase_buf[i] = nls_info->charset2upper[(int)ses->userName[i]];
261 ucase_buf[i] = 0;
262 user_name_len = cifs_strtoUCS(unicode_buf, ucase_buf,
263 MAX_USERNAME_SIZE*2, nls_info);
264 unicode_buf[user_name_len] = 0;
265 user_name_len++;
266
267 for (i = 0; i < dom_name_len; i++)
268 ucase_buf[i] = nls_info->charset2upper[(int)ses->domainName[i]];
269 ucase_buf[i] = 0;
270 dom_name_len = cifs_strtoUCS(unicode_buf+user_name_len, ucase_buf,
271 MAX_USERNAME_SIZE*2, nls_info);
272
273 unicode_buf[user_name_len + dom_name_len] = 0;
274 hmac_md5_update((const unsigned char *) unicode_buf,
275 (user_name_len+dom_name_len)*2, &ctx);
276
277 hmac_md5_final(ses->server->ntlmv2_hash, &ctx);
278 kfree(ucase_buf);
279 kfree(unicode_buf);
280 return 0;
281}
282
283#ifdef CONFIG_CIFS_WEAK_PW_HASH 268#ifdef CONFIG_CIFS_WEAK_PW_HASH
284void calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt, 269void calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt,
285 char *lnm_session_key) 270 char *lnm_session_key)
@@ -324,21 +309,29 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
324{ 309{
325 int rc = 0; 310 int rc = 0;
326 int len; 311 int len;
327 char nt_hash[16]; 312 char nt_hash[CIFS_NTHASH_SIZE];
328 struct HMACMD5Context *pctxt;
329 wchar_t *user; 313 wchar_t *user;
330 wchar_t *domain; 314 wchar_t *domain;
331 315 wchar_t *server;
332 pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL); 316 struct {
333 317 struct shash_desc shash;
334 if (pctxt == NULL) 318 char ctx[crypto_shash_descsize(ses->server->ntlmssp.hmacmd5)];
335 return -ENOMEM; 319 } sdesc;
336 320
337 /* calculate md4 hash of password */ 321 /* calculate md4 hash of password */
338 E_md4hash(ses->password, nt_hash); 322 E_md4hash(ses->password, nt_hash);
339 323
340 /* convert Domainname to unicode and uppercase */ 324 sdesc.shash.tfm = ses->server->ntlmssp.hmacmd5;
341 hmac_md5_init_limK_to_64(nt_hash, 16, pctxt); 325 sdesc.shash.flags = 0x0;
326
327 crypto_shash_setkey(ses->server->ntlmssp.hmacmd5, nt_hash,
328 CIFS_NTHASH_SIZE);
329
330 rc = crypto_shash_init(&sdesc.shash);
331 if (rc) {
332 cERROR(1, "could not initialize master crypto API hmacmd5\n");
333 return rc;
334 }
342 335
343 /* convert ses->userName to unicode and uppercase */ 336 /* convert ses->userName to unicode and uppercase */
344 len = strlen(ses->userName); 337 len = strlen(ses->userName);
@@ -347,7 +340,8 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
347 goto calc_exit_2; 340 goto calc_exit_2;
348 len = cifs_strtoUCS((__le16 *)user, ses->userName, len, nls_cp); 341 len = cifs_strtoUCS((__le16 *)user, ses->userName, len, nls_cp);
349 UniStrupr(user); 342 UniStrupr(user);
350 hmac_md5_update((char *)user, 2*len, pctxt); 343
344 crypto_shash_update(&sdesc.shash, (char *)user, 2 * len);
351 345
352 /* convert ses->domainName to unicode and uppercase */ 346 /* convert ses->domainName to unicode and uppercase */
353 if (ses->domainName) { 347 if (ses->domainName) {
@@ -363,65 +357,243 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
363 Maybe converting the domain name earlier makes sense */ 357 Maybe converting the domain name earlier makes sense */
364 /* UniStrupr(domain); */ 358 /* UniStrupr(domain); */
365 359
366 hmac_md5_update((char *)domain, 2*len, pctxt); 360 crypto_shash_update(&sdesc.shash, (char *)domain, 2 * len);
367 361
368 kfree(domain); 362 kfree(domain);
363 } else if (ses->serverName) {
364 len = strlen(ses->serverName);
365
366 server = kmalloc(2 + (len * 2), GFP_KERNEL);
367 if (server == NULL)
368 goto calc_exit_1;
369 len = cifs_strtoUCS((__le16 *)server, ses->serverName, len,
370 nls_cp);
371 /* the following line was removed since it didn't work well
372 with lower cased domain name that passed as an option.
373 Maybe converting the domain name earlier makes sense */
374 /* UniStrupr(domain); */
375
376 crypto_shash_update(&sdesc.shash, (char *)server, 2 * len);
377
378 kfree(server);
369 } 379 }
370calc_exit_1: 380calc_exit_1:
371 kfree(user); 381 kfree(user);
372calc_exit_2: 382calc_exit_2:
373 /* BB FIXME what about bytes 24 through 40 of the signing key? 383 /* BB FIXME what about bytes 24 through 40 of the signing key?
374 compare with the NTLM example */ 384 compare with the NTLM example */
375 hmac_md5_final(ses->server->ntlmv2_hash, pctxt); 385 rc = crypto_shash_final(&sdesc.shash, ses->server->ntlmv2_hash);
376 386
377 kfree(pctxt);
378 return rc; 387 return rc;
379} 388}
380 389
381void setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf, 390static int
382 const struct nls_table *nls_cp) 391find_domain_name(struct cifsSesInfo *ses)
392{
393 int rc = 0;
394 unsigned int attrsize;
395 unsigned int type;
396 unsigned char *blobptr;
397 struct ntlmssp2_name *attrptr;
398
399 if (ses->server->tiblob) {
400 blobptr = ses->server->tiblob;
401 attrptr = (struct ntlmssp2_name *) blobptr;
402
403 while ((type = attrptr->type) != 0) {
404 blobptr += 2; /* advance attr type */
405 attrsize = attrptr->length;
406 blobptr += 2; /* advance attr size */
407 if (type == NTLMSSP_AV_NB_DOMAIN_NAME) {
408 if (!ses->domainName) {
409 ses->domainName =
410 kmalloc(attrptr->length + 1,
411 GFP_KERNEL);
412 if (!ses->domainName)
413 return -ENOMEM;
414 cifs_from_ucs2(ses->domainName,
415 (__le16 *)blobptr,
416 attrptr->length,
417 attrptr->length,
418 load_nls_default(), false);
419 }
420 }
421 blobptr += attrsize; /* advance attr value */
422 attrptr = (struct ntlmssp2_name *) blobptr;
423 }
424 } else {
425 ses->server->tilen = 2 * sizeof(struct ntlmssp2_name);
426 ses->server->tiblob = kmalloc(ses->server->tilen, GFP_KERNEL);
427 if (!ses->server->tiblob) {
428 ses->server->tilen = 0;
429 cERROR(1, "Challenge target info allocation failure");
430 return -ENOMEM;
431 }
432 memset(ses->server->tiblob, 0x0, ses->server->tilen);
433 attrptr = (struct ntlmssp2_name *) ses->server->tiblob;
434 attrptr->type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE);
435 }
436
437 return rc;
438}
439
440static int
441CalcNTLMv2_response(const struct TCP_Server_Info *server,
442 char *v2_session_response)
383{ 443{
384 int rc; 444 int rc;
445 struct {
446 struct shash_desc shash;
447 char ctx[crypto_shash_descsize(server->ntlmssp.hmacmd5)];
448 } sdesc;
449
450 sdesc.shash.tfm = server->ntlmssp.hmacmd5;
451 sdesc.shash.flags = 0x0;
452
453 crypto_shash_setkey(server->ntlmssp.hmacmd5, server->ntlmv2_hash,
454 CIFS_HMAC_MD5_HASH_SIZE);
455
456 rc = crypto_shash_init(&sdesc.shash);
457 if (rc) {
458 cERROR(1, "could not initialize master crypto API hmacmd5\n");
459 return rc;
460 }
461
462 memcpy(v2_session_response + CIFS_SERVER_CHALLENGE_SIZE,
463 server->cryptKey, CIFS_SERVER_CHALLENGE_SIZE);
464 crypto_shash_update(&sdesc.shash,
465 v2_session_response + CIFS_SERVER_CHALLENGE_SIZE,
466 sizeof(struct ntlmv2_resp) - CIFS_SERVER_CHALLENGE_SIZE);
467
468 if (server->tilen)
469 crypto_shash_update(&sdesc.shash,
470 server->tiblob, server->tilen);
471
472 rc = crypto_shash_final(&sdesc.shash, v2_session_response);
473
474 return rc;
475}
476
477int
478setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf,
479 const struct nls_table *nls_cp)
480{
481 int rc = 0;
385 struct ntlmv2_resp *buf = (struct ntlmv2_resp *)resp_buf; 482 struct ntlmv2_resp *buf = (struct ntlmv2_resp *)resp_buf;
386 struct HMACMD5Context context; 483 struct {
484 struct shash_desc shash;
485 char ctx[crypto_shash_descsize(ses->server->ntlmssp.hmacmd5)];
486 } sdesc;
387 487
388 buf->blob_signature = cpu_to_le32(0x00000101); 488 buf->blob_signature = cpu_to_le32(0x00000101);
389 buf->reserved = 0; 489 buf->reserved = 0;
390 buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); 490 buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
391 get_random_bytes(&buf->client_chal, sizeof(buf->client_chal)); 491 get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));
392 buf->reserved2 = 0; 492 buf->reserved2 = 0;
393 buf->names[0].type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE); 493
394 buf->names[0].length = 0; 494 if (!ses->domainName) {
395 buf->names[1].type = 0; 495 rc = find_domain_name(ses);
396 buf->names[1].length = 0; 496 if (rc) {
497 cERROR(1, "could not get domain/server name rc %d", rc);
498 return rc;
499 }
500 }
397 501
398 /* calculate buf->ntlmv2_hash */ 502 /* calculate buf->ntlmv2_hash */
399 rc = calc_ntlmv2_hash(ses, nls_cp); 503 rc = calc_ntlmv2_hash(ses, nls_cp);
400 if (rc) 504 if (rc) {
505 cERROR(1, "could not get v2 hash rc %d", rc);
506 return rc;
507 }
508 rc = CalcNTLMv2_response(ses->server, resp_buf);
509 if (rc) {
401 cERROR(1, "could not get v2 hash rc %d", rc); 510 cERROR(1, "could not get v2 hash rc %d", rc);
402 CalcNTLMv2_response(ses, resp_buf); 511 return rc;
512 }
513
514 crypto_shash_setkey(ses->server->ntlmssp.hmacmd5,
515 ses->server->ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
516
517 sdesc.shash.tfm = ses->server->ntlmssp.hmacmd5;
518 sdesc.shash.flags = 0x0;
519
520 rc = crypto_shash_init(&sdesc.shash);
521 if (rc) {
522 cERROR(1, "could not initialize master crypto API hmacmd5\n");
523 return rc;
524 }
525
526 crypto_shash_update(&sdesc.shash, resp_buf, CIFS_HMAC_MD5_HASH_SIZE);
403 527
404 /* now calculate the MAC key for NTLMv2 */ 528 rc = crypto_shash_final(&sdesc.shash,
405 hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context); 529 ses->server->session_key.data.ntlmv2.key);
406 hmac_md5_update(resp_buf, 16, &context);
407 hmac_md5_final(ses->server->mac_signing_key.data.ntlmv2.key, &context);
408 530
409 memcpy(&ses->server->mac_signing_key.data.ntlmv2.resp, resp_buf, 531 memcpy(&ses->server->session_key.data.ntlmv2.resp, resp_buf,
410 sizeof(struct ntlmv2_resp)); 532 sizeof(struct ntlmv2_resp));
411 ses->server->mac_signing_key.len = 16 + sizeof(struct ntlmv2_resp); 533 ses->server->session_key.len = 16 + sizeof(struct ntlmv2_resp);
534
535 return rc;
412} 536}
413 537
414void CalcNTLMv2_response(const struct cifsSesInfo *ses, 538int
415 char *v2_session_response) 539calc_seckey(struct TCP_Server_Info *server)
416{ 540{
417 struct HMACMD5Context context; 541 int rc;
418 /* rest of v2 struct already generated */ 542 unsigned char sec_key[CIFS_NTLMV2_SESSKEY_SIZE];
419 memcpy(v2_session_response + 8, ses->server->cryptKey, 8); 543 struct crypto_blkcipher *tfm_arc4;
420 hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context); 544 struct scatterlist sgin, sgout;
545 struct blkcipher_desc desc;
546
547 get_random_bytes(sec_key, CIFS_NTLMV2_SESSKEY_SIZE);
548
549 tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)",
550 0, CRYPTO_ALG_ASYNC);
551 if (!tfm_arc4 || IS_ERR(tfm_arc4)) {
552 cERROR(1, "could not allocate " "master crypto API arc4\n");
553 return 1;
554 }
555
556 crypto_blkcipher_setkey(tfm_arc4,
557 server->session_key.data.ntlmv2.key, CIFS_CPHTXT_SIZE);
558 sg_init_one(&sgin, sec_key, CIFS_CPHTXT_SIZE);
559 sg_init_one(&sgout, server->ntlmssp.ciphertext, CIFS_CPHTXT_SIZE);
560 rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, CIFS_CPHTXT_SIZE);
561
562 if (!rc)
563 memcpy(server->session_key.data.ntlmv2.key,
564 sec_key, CIFS_NTLMV2_SESSKEY_SIZE);
421 565
422 hmac_md5_update(v2_session_response+8, 566 crypto_free_blkcipher(tfm_arc4);
423 sizeof(struct ntlmv2_resp) - 8, &context);
424 567
425 hmac_md5_final(v2_session_response, &context); 568 return 0;
426/* cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */ 569}
570
571void
572cifs_crypto_shash_release(struct TCP_Server_Info *server)
573{
574 if (server->ntlmssp.md5)
575 crypto_free_shash(server->ntlmssp.md5);
576
577 if (server->ntlmssp.hmacmd5)
578 crypto_free_shash(server->ntlmssp.hmacmd5);
579}
580
581int
582cifs_crypto_shash_allocate(struct TCP_Server_Info *server)
583{
584 server->ntlmssp.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0);
585 if (!server->ntlmssp.hmacmd5 ||
586 IS_ERR(server->ntlmssp.hmacmd5)) {
587 cERROR(1, "could not allocate master crypto API hmacmd5\n");
588 return 1;
589 }
590
591 server->ntlmssp.md5 = crypto_alloc_shash("md5", 0, 0);
592 if (!server->ntlmssp.md5 || IS_ERR(server->ntlmssp.md5)) {
593 crypto_free_shash(server->ntlmssp.hmacmd5);
594 cERROR(1, "could not allocate master crypto API md5\n");
595 return 1;
596 }
597
598 return 0;
427} 599}
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 0cdfb8c32ac6..49563e0c1725 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -25,6 +25,9 @@
25#include <linux/workqueue.h> 25#include <linux/workqueue.h>
26#include "cifs_fs_sb.h" 26#include "cifs_fs_sb.h"
27#include "cifsacl.h" 27#include "cifsacl.h"
28#include <crypto/internal/hash.h>
29#include <linux/scatterlist.h>
30
28/* 31/*
29 * The sizes of various internal tables and strings 32 * The sizes of various internal tables and strings
30 */ 33 */
@@ -97,7 +100,7 @@ enum protocolEnum {
97 /* Netbios frames protocol not supported at this time */ 100 /* Netbios frames protocol not supported at this time */
98}; 101};
99 102
100struct mac_key { 103struct session_key {
101 unsigned int len; 104 unsigned int len;
102 union { 105 union {
103 char ntlm[CIFS_SESS_KEY_SIZE + 16]; 106 char ntlm[CIFS_SESS_KEY_SIZE + 16];
@@ -120,6 +123,14 @@ struct cifs_cred {
120 struct cifs_ace *aces; 123 struct cifs_ace *aces;
121}; 124};
122 125
126struct ntlmssp_auth {
127 __u32 client_flags;
128 __u32 server_flags;
129 unsigned char ciphertext[CIFS_CPHTXT_SIZE];
130 struct crypto_shash *hmacmd5;
131 struct crypto_shash *md5;
132};
133
123/* 134/*
124 ***************************************************************** 135 *****************************************************************
125 * Except the CIFS PDUs themselves all the 136 * Except the CIFS PDUs themselves all the
@@ -182,11 +193,14 @@ struct TCP_Server_Info {
182 /* 16th byte of RFC1001 workstation name is always null */ 193 /* 16th byte of RFC1001 workstation name is always null */
183 char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; 194 char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
184 __u32 sequence_number; /* needed for CIFS PDU signature */ 195 __u32 sequence_number; /* needed for CIFS PDU signature */
185 struct mac_key mac_signing_key; 196 struct session_key session_key;
186 char ntlmv2_hash[16]; 197 char ntlmv2_hash[16];
187 unsigned long lstrp; /* when we got last response from this server */ 198 unsigned long lstrp; /* when we got last response from this server */
188 u16 dialect; /* dialect index that server chose */ 199 u16 dialect; /* dialect index that server chose */
189 /* extended security flavors that server supports */ 200 /* extended security flavors that server supports */
201 unsigned int tilen; /* length of the target info blob */
202 unsigned char *tiblob; /* target info blob in challenge response */
203 struct ntlmssp_auth ntlmssp; /* various keys, ciphers, flags */
190 bool sec_kerberos; /* supports plain Kerberos */ 204 bool sec_kerberos; /* supports plain Kerberos */
191 bool sec_mskerberos; /* supports legacy MS Kerberos */ 205 bool sec_mskerberos; /* supports legacy MS Kerberos */
192 bool sec_kerberosu2u; /* supports U2U Kerberos */ 206 bool sec_kerberosu2u; /* supports U2U Kerberos */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 14d036d8db11..320e0fd0ba7b 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -134,6 +134,12 @@
134 * Size of the session key (crypto key encrypted with the password 134 * Size of the session key (crypto key encrypted with the password
135 */ 135 */
136#define CIFS_SESS_KEY_SIZE (24) 136#define CIFS_SESS_KEY_SIZE (24)
137#define CIFS_CLIENT_CHALLENGE_SIZE (8)
138#define CIFS_SERVER_CHALLENGE_SIZE (8)
139#define CIFS_HMAC_MD5_HASH_SIZE (16)
140#define CIFS_CPHTXT_SIZE (16)
141#define CIFS_NTLMV2_SESSKEY_SIZE (16)
142#define CIFS_NTHASH_SIZE (16)
137 143
138/* 144/*
139 * Maximum user name length 145 * Maximum user name length
@@ -663,7 +669,6 @@ struct ntlmv2_resp {
663 __le64 time; 669 __le64 time;
664 __u64 client_chal; /* random */ 670 __u64 client_chal; /* random */
665 __u32 reserved2; 671 __u32 reserved2;
666 struct ntlmssp2_name names[2];
667 /* array of name entries could follow ending in minimum 4 byte struct */ 672 /* array of name entries could follow ending in minimum 4 byte struct */
668} __attribute__((packed)); 673} __attribute__((packed));
669 674
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 1f5450814087..1378d9133844 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -361,15 +361,15 @@ extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *);
361extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *, 361extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
362 __u32 *); 362 __u32 *);
363extern int cifs_verify_signature(struct smb_hdr *, 363extern int cifs_verify_signature(struct smb_hdr *,
364 const struct mac_key *mac_key, 364 struct TCP_Server_Info *server,
365 __u32 expected_sequence_number); 365 __u32 expected_sequence_number);
366extern int cifs_calculate_mac_key(struct mac_key *key, const char *rn, 366extern int cifs_calculate_session_key(struct session_key *key, const char *rn,
367 const char *pass); 367 const char *pass);
368extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, 368extern int setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
369 const struct nls_table *);
370extern void CalcNTLMv2_response(const struct cifsSesInfo *, char *);
371extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
372 const struct nls_table *); 369 const struct nls_table *);
370extern int cifs_crypto_shash_allocate(struct TCP_Server_Info *);
371extern void cifs_crypto_shash_release(struct TCP_Server_Info *);
372extern int calc_seckey(struct TCP_Server_Info *);
373#ifdef CONFIG_CIFS_WEAK_PW_HASH 373#ifdef CONFIG_CIFS_WEAK_PW_HASH
374extern void calc_lanman_hash(const char *password, const char *cryptkey, 374extern void calc_lanman_hash(const char *password, const char *cryptkey,
375 bool encrypt, char *lnm_session_key); 375 bool encrypt, char *lnm_session_key);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index c65c3419dd37..4bda920d1f75 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -604,11 +604,14 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
604 else 604 else
605 rc = -EINVAL; 605 rc = -EINVAL;
606 606
607 if (server->sec_kerberos || server->sec_mskerberos) 607 if (server->secType == Kerberos) {
608 server->secType = Kerberos; 608 if (!server->sec_kerberos &&
609 else if (server->sec_ntlmssp) 609 !server->sec_mskerberos)
610 server->secType = RawNTLMSSP; 610 rc = -EOPNOTSUPP;
611 else 611 } else if (server->secType == RawNTLMSSP) {
612 if (!server->sec_ntlmssp)
613 rc = -EOPNOTSUPP;
614 } else
612 rc = -EOPNOTSUPP; 615 rc = -EOPNOTSUPP;
613 } 616 }
614 } else 617 } else
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 446e2486d5f0..18af707f00f1 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1707,6 +1707,7 @@ cifs_put_smb_ses(struct cifsSesInfo *ses)
1707 CIFSSMBLogoff(xid, ses); 1707 CIFSSMBLogoff(xid, ses);
1708 _FreeXid(xid); 1708 _FreeXid(xid);
1709 } 1709 }
1710 cifs_crypto_shash_release(server);
1710 sesInfoFree(ses); 1711 sesInfoFree(ses);
1711 cifs_put_tcp_session(server); 1712 cifs_put_tcp_session(server);
1712} 1713}
@@ -1786,13 +1787,23 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
1786 ses->linux_uid = volume_info->linux_uid; 1787 ses->linux_uid = volume_info->linux_uid;
1787 ses->overrideSecFlg = volume_info->secFlg; 1788 ses->overrideSecFlg = volume_info->secFlg;
1788 1789
1790 rc = cifs_crypto_shash_allocate(server);
1791 if (rc) {
1792 cERROR(1, "could not setup hash structures rc %d", rc);
1793 goto get_ses_fail;
1794 }
1795 server->tilen = 0;
1796 server->tiblob = NULL;
1797
1789 mutex_lock(&ses->session_mutex); 1798 mutex_lock(&ses->session_mutex);
1790 rc = cifs_negotiate_protocol(xid, ses); 1799 rc = cifs_negotiate_protocol(xid, ses);
1791 if (!rc) 1800 if (!rc)
1792 rc = cifs_setup_session(xid, ses, volume_info->local_nls); 1801 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
1793 mutex_unlock(&ses->session_mutex); 1802 mutex_unlock(&ses->session_mutex);
1794 if (rc) 1803 if (rc) {
1804 cifs_crypto_shash_release(ses->server);
1795 goto get_ses_fail; 1805 goto get_ses_fail;
1806 }
1796 1807
1797 /* success, put it on the list */ 1808 /* success, put it on the list */
1798 write_lock(&cifs_tcp_ses_lock); 1809 write_lock(&cifs_tcp_ses_lock);
diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h
index 49c9a4e75319..1db0f0746a5b 100644
--- a/fs/cifs/ntlmssp.h
+++ b/fs/cifs/ntlmssp.h
@@ -61,6 +61,19 @@
61#define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000 61#define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000
62#define NTLMSSP_NEGOTIATE_56 0x80000000 62#define NTLMSSP_NEGOTIATE_56 0x80000000
63 63
64/* Define AV Pair Field IDs */
65#define NTLMSSP_AV_EOL 0
66#define NTLMSSP_AV_NB_COMPUTER_NAME 1
67#define NTLMSSP_AV_NB_DOMAIN_NAME 2
68#define NTLMSSP_AV_DNS_COMPUTER_NAME 3
69#define NTLMSSP_AV_DNS_DOMAIN_NAME 4
70#define NTLMSSP_AV_DNS_TREE_NAME 5
71#define NTLMSSP_AV_FLAGS 6
72#define NTLMSSP_AV_TIMESTAMP 7
73#define NTLMSSP_AV_RESTRICTION 8
74#define NTLMSSP_AV_TARGET_NAME 9
75#define NTLMSSP_AV_CHANNEL_BINDINGS 10
76
64/* Although typedefs are not commonly used for structure definitions */ 77/* Although typedefs are not commonly used for structure definitions */
65/* in the Linux kernel, in this particular case they are useful */ 78/* in the Linux kernel, in this particular case they are useful */
66/* to more closely match the standards document for NTLMSSP from */ 79/* to more closely match the standards document for NTLMSSP from */
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 0a57cb7db5dd..41fc5328120d 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -383,6 +383,9 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft,
383static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, 383static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
384 struct cifsSesInfo *ses) 384 struct cifsSesInfo *ses)
385{ 385{
386 unsigned int tioffset; /* challeng message target info area */
387 unsigned int tilen; /* challeng message target info area length */
388
386 CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr; 389 CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr;
387 390
388 if (blob_len < sizeof(CHALLENGE_MESSAGE)) { 391 if (blob_len < sizeof(CHALLENGE_MESSAGE)) {
@@ -405,6 +408,18 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
405 /* BB spec says that if AvId field of MsvAvTimestamp is populated then 408 /* BB spec says that if AvId field of MsvAvTimestamp is populated then
406 we must set the MIC field of the AUTHENTICATE_MESSAGE */ 409 we must set the MIC field of the AUTHENTICATE_MESSAGE */
407 410
411 tioffset = cpu_to_le16(pblob->TargetInfoArray.BufferOffset);
412 tilen = cpu_to_le16(pblob->TargetInfoArray.Length);
413 ses->server->tilen = tilen;
414 if (tilen) {
415 ses->server->tiblob = kmalloc(tilen, GFP_KERNEL);
416 if (!ses->server->tiblob) {
417 cERROR(1, "Challenge target info allocation failure");
418 return -ENOMEM;
419 }
420 memcpy(ses->server->tiblob, bcc_ptr + tioffset, tilen);
421 }
422
408 return 0; 423 return 0;
409} 424}
410 425
@@ -451,10 +466,12 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
451 struct cifsSesInfo *ses, 466 struct cifsSesInfo *ses,
452 const struct nls_table *nls_cp, bool first) 467 const struct nls_table *nls_cp, bool first)
453{ 468{
469 int rc;
470 unsigned int size;
454 AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer; 471 AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer;
455 __u32 flags; 472 __u32 flags;
456 unsigned char *tmp; 473 unsigned char *tmp;
457 char ntlm_session_key[CIFS_SESS_KEY_SIZE]; 474 struct ntlmv2_resp ntlmv2_response = {};
458 475
459 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); 476 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
460 sec_blob->MessageType = NtLmAuthenticate; 477 sec_blob->MessageType = NtLmAuthenticate;
@@ -477,19 +494,25 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
477 sec_blob->LmChallengeResponse.Length = 0; 494 sec_blob->LmChallengeResponse.Length = 0;
478 sec_blob->LmChallengeResponse.MaximumLength = 0; 495 sec_blob->LmChallengeResponse.MaximumLength = 0;
479 496
480 /* calculate session key, BB what about adding similar ntlmv2 path? */
481 SMBNTencrypt(ses->password, ses->server->cryptKey, ntlm_session_key);
482 if (first)
483 cifs_calculate_mac_key(&ses->server->mac_signing_key,
484 ntlm_session_key, ses->password);
485
486 memcpy(tmp, ntlm_session_key, CIFS_SESS_KEY_SIZE);
487 sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer); 497 sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer);
488 sec_blob->NtChallengeResponse.Length = cpu_to_le16(CIFS_SESS_KEY_SIZE); 498 rc = setup_ntlmv2_rsp(ses, (char *)&ntlmv2_response, nls_cp);
489 sec_blob->NtChallengeResponse.MaximumLength = 499 if (rc) {
490 cpu_to_le16(CIFS_SESS_KEY_SIZE); 500 cERROR(1, "error rc: %d during ntlmssp ntlmv2 setup", rc);
501 goto setup_ntlmv2_ret;
502 }
503 size = sizeof(struct ntlmv2_resp);
504 memcpy(tmp, (char *)&ntlmv2_response, size);
505 tmp += size;
506 if (ses->server->tilen > 0) {
507 memcpy(tmp, ses->server->tiblob, ses->server->tilen);
508 tmp += ses->server->tilen;
509 } else
510 ses->server->tilen = 0;
491 511
492 tmp += CIFS_SESS_KEY_SIZE; 512 sec_blob->NtChallengeResponse.Length = cpu_to_le16(size +
513 ses->server->tilen);
514 sec_blob->NtChallengeResponse.MaximumLength =
515 cpu_to_le16(size + ses->server->tilen);
493 516
494 if (ses->domainName == NULL) { 517 if (ses->domainName == NULL) {
495 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); 518 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
@@ -501,7 +524,6 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
501 len = cifs_strtoUCS((__le16 *)tmp, ses->domainName, 524 len = cifs_strtoUCS((__le16 *)tmp, ses->domainName,
502 MAX_USERNAME_SIZE, nls_cp); 525 MAX_USERNAME_SIZE, nls_cp);
503 len *= 2; /* unicode is 2 bytes each */ 526 len *= 2; /* unicode is 2 bytes each */
504 len += 2; /* trailing null */
505 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); 527 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
506 sec_blob->DomainName.Length = cpu_to_le16(len); 528 sec_blob->DomainName.Length = cpu_to_le16(len);
507 sec_blob->DomainName.MaximumLength = cpu_to_le16(len); 529 sec_blob->DomainName.MaximumLength = cpu_to_le16(len);
@@ -518,7 +540,6 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
518 len = cifs_strtoUCS((__le16 *)tmp, ses->userName, 540 len = cifs_strtoUCS((__le16 *)tmp, ses->userName,
519 MAX_USERNAME_SIZE, nls_cp); 541 MAX_USERNAME_SIZE, nls_cp);
520 len *= 2; /* unicode is 2 bytes each */ 542 len *= 2; /* unicode is 2 bytes each */
521 len += 2; /* trailing null */
522 sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer); 543 sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
523 sec_blob->UserName.Length = cpu_to_le16(len); 544 sec_blob->UserName.Length = cpu_to_le16(len);
524 sec_blob->UserName.MaximumLength = cpu_to_le16(len); 545 sec_blob->UserName.MaximumLength = cpu_to_le16(len);
@@ -530,9 +551,26 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
530 sec_blob->WorkstationName.MaximumLength = 0; 551 sec_blob->WorkstationName.MaximumLength = 0;
531 tmp += 2; 552 tmp += 2;
532 553
533 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); 554 if ((ses->server->ntlmssp.server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) &&
534 sec_blob->SessionKey.Length = 0; 555 !calc_seckey(ses->server)) {
535 sec_blob->SessionKey.MaximumLength = 0; 556 memcpy(tmp, ses->server->ntlmssp.ciphertext, CIFS_CPHTXT_SIZE);
557 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer);
558 sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE);
559 sec_blob->SessionKey.MaximumLength =
560 cpu_to_le16(CIFS_CPHTXT_SIZE);
561 tmp += CIFS_CPHTXT_SIZE;
562 } else {
563 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer);
564 sec_blob->SessionKey.Length = 0;
565 sec_blob->SessionKey.MaximumLength = 0;
566 }
567
568 ses->server->sequence_number = 0;
569
570setup_ntlmv2_ret:
571 if (ses->server->tilen > 0)
572 kfree(ses->server->tiblob);
573
536 return tmp - pbuffer; 574 return tmp - pbuffer;
537} 575}
538 576
@@ -546,15 +584,14 @@ static void setup_ntlmssp_neg_req(SESSION_SETUP_ANDX *pSMB,
546 return; 584 return;
547} 585}
548 586
549static int setup_ntlmssp_auth_req(SESSION_SETUP_ANDX *pSMB, 587static int setup_ntlmssp_auth_req(char *ntlmsspblob,
550 struct cifsSesInfo *ses, 588 struct cifsSesInfo *ses,
551 const struct nls_table *nls, bool first_time) 589 const struct nls_table *nls, bool first_time)
552{ 590{
553 int bloblen; 591 int bloblen;
554 592
555 bloblen = build_ntlmssp_auth_blob(&pSMB->req.SecurityBlob[0], ses, nls, 593 bloblen = build_ntlmssp_auth_blob(ntlmsspblob, ses, nls,
556 first_time); 594 first_time);
557 pSMB->req.SecurityBlobLength = cpu_to_le16(bloblen);
558 595
559 return bloblen; 596 return bloblen;
560} 597}
@@ -580,6 +617,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
580 struct key *spnego_key = NULL; 617 struct key *spnego_key = NULL;
581 __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */ 618 __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */
582 bool first_time; 619 bool first_time;
620 char *ntlmsspblob;
583 621
584 if (ses == NULL) 622 if (ses == NULL)
585 return -EINVAL; 623 return -EINVAL;
@@ -690,7 +728,7 @@ ssetup_ntlmssp_authenticate:
690 728
691 if (first_time) /* should this be moved into common code 729 if (first_time) /* should this be moved into common code
692 with similar ntlmv2 path? */ 730 with similar ntlmv2 path? */
693 cifs_calculate_mac_key(&ses->server->mac_signing_key, 731 cifs_calculate_session_key(&ses->server->session_key,
694 ntlm_session_key, ses->password); 732 ntlm_session_key, ses->password);
695 /* copy session key */ 733 /* copy session key */
696 734
@@ -729,12 +767,21 @@ ssetup_ntlmssp_authenticate:
729 cpu_to_le16(sizeof(struct ntlmv2_resp)); 767 cpu_to_le16(sizeof(struct ntlmv2_resp));
730 768
731 /* calculate session key */ 769 /* calculate session key */
732 setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp); 770 rc = setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
771 if (rc) {
772 kfree(v2_sess_key);
773 goto ssetup_exit;
774 }
733 /* FIXME: calculate MAC key */ 775 /* FIXME: calculate MAC key */
734 memcpy(bcc_ptr, (char *)v2_sess_key, 776 memcpy(bcc_ptr, (char *)v2_sess_key,
735 sizeof(struct ntlmv2_resp)); 777 sizeof(struct ntlmv2_resp));
736 bcc_ptr += sizeof(struct ntlmv2_resp); 778 bcc_ptr += sizeof(struct ntlmv2_resp);
737 kfree(v2_sess_key); 779 kfree(v2_sess_key);
780 if (ses->server->tilen > 0) {
781 memcpy(bcc_ptr, ses->server->tiblob,
782 ses->server->tilen);
783 bcc_ptr += ses->server->tilen;
784 }
738 if (ses->capabilities & CAP_UNICODE) { 785 if (ses->capabilities & CAP_UNICODE) {
739 if (iov[0].iov_len % 2) { 786 if (iov[0].iov_len % 2) {
740 *bcc_ptr = 0; 787 *bcc_ptr = 0;
@@ -765,15 +812,15 @@ ssetup_ntlmssp_authenticate:
765 } 812 }
766 /* bail out if key is too long */ 813 /* bail out if key is too long */
767 if (msg->sesskey_len > 814 if (msg->sesskey_len >
768 sizeof(ses->server->mac_signing_key.data.krb5)) { 815 sizeof(ses->server->session_key.data.krb5)) {
769 cERROR(1, "Kerberos signing key too long (%u bytes)", 816 cERROR(1, "Kerberos signing key too long (%u bytes)",
770 msg->sesskey_len); 817 msg->sesskey_len);
771 rc = -EOVERFLOW; 818 rc = -EOVERFLOW;
772 goto ssetup_exit; 819 goto ssetup_exit;
773 } 820 }
774 if (first_time) { 821 if (first_time) {
775 ses->server->mac_signing_key.len = msg->sesskey_len; 822 ses->server->session_key.len = msg->sesskey_len;
776 memcpy(ses->server->mac_signing_key.data.krb5, 823 memcpy(ses->server->session_key.data.krb5,
777 msg->data, msg->sesskey_len); 824 msg->data, msg->sesskey_len);
778 } 825 }
779 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; 826 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
@@ -815,12 +862,26 @@ ssetup_ntlmssp_authenticate:
815 if (phase == NtLmNegotiate) { 862 if (phase == NtLmNegotiate) {
816 setup_ntlmssp_neg_req(pSMB, ses); 863 setup_ntlmssp_neg_req(pSMB, ses);
817 iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE); 864 iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE);
865 iov[1].iov_base = &pSMB->req.SecurityBlob[0];
818 } else if (phase == NtLmAuthenticate) { 866 } else if (phase == NtLmAuthenticate) {
819 int blob_len; 867 int blob_len;
820 blob_len = setup_ntlmssp_auth_req(pSMB, ses, 868 ntlmsspblob = kmalloc(5 *
821 nls_cp, 869 sizeof(struct _AUTHENTICATE_MESSAGE),
822 first_time); 870 GFP_KERNEL);
871 if (!ntlmsspblob) {
872 cERROR(1, "Can't allocate NTLMSSP");
873 rc = -ENOMEM;
874 goto ssetup_exit;
875 }
876
877 blob_len = setup_ntlmssp_auth_req(ntlmsspblob,
878 ses,
879 nls_cp,
880 first_time);
823 iov[1].iov_len = blob_len; 881 iov[1].iov_len = blob_len;
882 iov[1].iov_base = ntlmsspblob;
883 pSMB->req.SecurityBlobLength =
884 cpu_to_le16(blob_len);
824 /* Make sure that we tell the server that we 885 /* Make sure that we tell the server that we
825 are using the uid that it just gave us back 886 are using the uid that it just gave us back
826 on the response (challenge) */ 887 on the response (challenge) */
@@ -830,7 +891,6 @@ ssetup_ntlmssp_authenticate:
830 rc = -ENOSYS; 891 rc = -ENOSYS;
831 goto ssetup_exit; 892 goto ssetup_exit;
832 } 893 }
833 iov[1].iov_base = &pSMB->req.SecurityBlob[0];
834 /* unicode strings must be word aligned */ 894 /* unicode strings must be word aligned */
835 if ((iov[0].iov_len + iov[1].iov_len) % 2) { 895 if ((iov[0].iov_len + iov[1].iov_len) % 2) {
836 *bcc_ptr = 0; 896 *bcc_ptr = 0;
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 82f78c4d6978..e0588cdf4cc5 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -543,7 +543,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
543 (ses->server->secMode & (SECMODE_SIGN_REQUIRED | 543 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
544 SECMODE_SIGN_ENABLED))) { 544 SECMODE_SIGN_ENABLED))) {
545 rc = cifs_verify_signature(midQ->resp_buf, 545 rc = cifs_verify_signature(midQ->resp_buf,
546 &ses->server->mac_signing_key, 546 ses->server,
547 midQ->sequence_number+1); 547 midQ->sequence_number+1);
548 if (rc) { 548 if (rc) {
549 cERROR(1, "Unexpected SMB signature"); 549 cERROR(1, "Unexpected SMB signature");
@@ -731,7 +731,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
731 (ses->server->secMode & (SECMODE_SIGN_REQUIRED | 731 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
732 SECMODE_SIGN_ENABLED))) { 732 SECMODE_SIGN_ENABLED))) {
733 rc = cifs_verify_signature(out_buf, 733 rc = cifs_verify_signature(out_buf,
734 &ses->server->mac_signing_key, 734 ses->server,
735 midQ->sequence_number+1); 735 midQ->sequence_number+1);
736 if (rc) { 736 if (rc) {
737 cERROR(1, "Unexpected SMB signature"); 737 cERROR(1, "Unexpected SMB signature");
@@ -981,7 +981,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
981 (ses->server->secMode & (SECMODE_SIGN_REQUIRED | 981 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
982 SECMODE_SIGN_ENABLED))) { 982 SECMODE_SIGN_ENABLED))) {
983 rc = cifs_verify_signature(out_buf, 983 rc = cifs_verify_signature(out_buf,
984 &ses->server->mac_signing_key, 984 ses->server,
985 midQ->sequence_number+1); 985 midQ->sequence_number+1);
986 if (rc) { 986 if (rc) {
987 cERROR(1, "Unexpected SMB signature"); 987 cERROR(1, "Unexpected SMB signature");