aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorShirish Pargaonkar <shirishpargaonkar@gmail.com>2010-10-21 07:42:55 -0400
committerSteve French <sfrench@us.ibm.com>2010-10-26 14:20:10 -0400
commit21e733930be6458e0c33482b6783e7c15ba984eb (patch)
tree1458ccf45529649267451a7e06fcd25d9c7ab0ac /fs/cifs
parent6573e9b73e19c0f6b9dfa2b399267ea0f42d6c6b (diff)
NTLM auth and sign - Allocate session key/client response dynamically
Start calculating auth response within a session. Move/Add pertinet data structures like session key, server challenge and ntlmv2_hash in a session structure. We should do the calculations within a session before copying session key and response over to server data structures because a session setup can fail. Only after a very first smb session succeeds, it copy/make its session key, session key of smb connection. This key stays with the smb connection throughout its life. sequence_number within server is set to 0x2. The authentication Message Authentication Key (mak) which consists of session key followed by client response within structure session_key is now dynamic. Every authentication type allocates the key + response sized memory within its session structure and later either assigns or frees it once the client response is sent and if session's session key becomes connetion's session key. ntlm/ntlmi authentication functions are rearranged. A function named setup_ntlm_resp(), similar to setup_ntlmv2_resp(), replaces function cifs_calculate_session_key(). size of CIFS_SESS_KEY_SIZE is changed to 16, to reflect the byte size of the key it holds. Reviewed-by: Jeff Layton <jlayton@samba.org> Signed-off-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifsencrypt.c113
-rw-r--r--fs/cifs/cifsglob.h9
-rw-r--r--fs/cifs/cifspdu.h7
-rw-r--r--fs/cifs/cifsproto.h11
-rw-r--r--fs/cifs/connect.c18
-rw-r--r--fs/cifs/sess.c107
-rw-r--r--fs/cifs/transport.c6
7 files changed, 134 insertions, 137 deletions
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 7ac0056294cf..987b479d55dd 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -43,15 +43,16 @@ extern void SMBencrypt(unsigned char *passwd, const unsigned char *c8,
43 unsigned char *p24); 43 unsigned char *p24);
44 44
45static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu, 45static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
46 const struct session_key *key, char *signature) 46 struct TCP_Server_Info *server, char *signature)
47{ 47{
48 struct MD5Context context; 48 struct MD5Context context;
49 49
50 if ((cifs_pdu == NULL) || (signature == NULL) || (key == NULL)) 50 if (cifs_pdu == NULL || signature == NULL || server == NULL)
51 return -EINVAL; 51 return -EINVAL;
52 52
53 cifs_MD5_init(&context); 53 cifs_MD5_init(&context);
54 cifs_MD5_update(&context, (char *)&key->data, key->len); 54 cifs_MD5_update(&context, server->session_key.response,
55 server->session_key.len);
55 cifs_MD5_update(&context, cifs_pdu->Protocol, cifs_pdu->smb_buf_length); 56 cifs_MD5_update(&context, cifs_pdu->Protocol, cifs_pdu->smb_buf_length);
56 57
57 cifs_MD5_final(signature, &context); 58 cifs_MD5_final(signature, &context);
@@ -79,8 +80,7 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
79 server->sequence_number++; 80 server->sequence_number++;
80 spin_unlock(&GlobalMid_Lock); 81 spin_unlock(&GlobalMid_Lock);
81 82
82 rc = cifs_calculate_signature(cifs_pdu, &server->session_key, 83 rc = cifs_calculate_signature(cifs_pdu, server, smb_signature);
83 smb_signature);
84 if (rc) 84 if (rc)
85 memset(cifs_pdu->Signature.SecuritySignature, 0, 8); 85 memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
86 else 86 else
@@ -90,16 +90,17 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
90} 90}
91 91
92static int cifs_calc_signature2(const struct kvec *iov, int n_vec, 92static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
93 const struct session_key *key, char *signature) 93 struct TCP_Server_Info *server, char *signature)
94{ 94{
95 struct MD5Context context; 95 struct MD5Context context;
96 int i; 96 int i;
97 97
98 if ((iov == NULL) || (signature == NULL) || (key == NULL)) 98 if (iov == NULL || signature == NULL || server == NULL)
99 return -EINVAL; 99 return -EINVAL;
100 100
101 cifs_MD5_init(&context); 101 cifs_MD5_init(&context);
102 cifs_MD5_update(&context, (char *)&key->data, key->len); 102 cifs_MD5_update(&context, server->session_key.response,
103 server->session_key.len);
103 for (i = 0; i < n_vec; i++) { 104 for (i = 0; i < n_vec; i++) {
104 if (iov[i].iov_len == 0) 105 if (iov[i].iov_len == 0)
105 continue; 106 continue;
@@ -146,8 +147,7 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
146 server->sequence_number++; 147 server->sequence_number++;
147 spin_unlock(&GlobalMid_Lock); 148 spin_unlock(&GlobalMid_Lock);
148 149
149 rc = cifs_calc_signature2(iov, n_vec, &server->session_key, 150 rc = cifs_calc_signature2(iov, n_vec, server, smb_signature);
150 smb_signature);
151 if (rc) 151 if (rc)
152 memset(cifs_pdu->Signature.SecuritySignature, 0, 8); 152 memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
153 else 153 else
@@ -157,14 +157,14 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
157} 157}
158 158
159int cifs_verify_signature(struct smb_hdr *cifs_pdu, 159int cifs_verify_signature(struct smb_hdr *cifs_pdu,
160 const struct session_key *session_key, 160 struct TCP_Server_Info *server,
161 __u32 expected_sequence_number) 161 __u32 expected_sequence_number)
162{ 162{
163 unsigned int rc; 163 unsigned int rc;
164 char server_response_sig[8]; 164 char server_response_sig[8];
165 char what_we_think_sig_should_be[20]; 165 char what_we_think_sig_should_be[20];
166 166
167 if (cifs_pdu == NULL || session_key == NULL) 167 if (cifs_pdu == NULL || server == NULL)
168 return -EINVAL; 168 return -EINVAL;
169 169
170 if (cifs_pdu->Command == SMB_COM_NEGOTIATE) 170 if (cifs_pdu->Command == SMB_COM_NEGOTIATE)
@@ -193,7 +193,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu,
193 cpu_to_le32(expected_sequence_number); 193 cpu_to_le32(expected_sequence_number);
194 cifs_pdu->Signature.Sequence.Reserved = 0; 194 cifs_pdu->Signature.Sequence.Reserved = 0;
195 195
196 rc = cifs_calculate_signature(cifs_pdu, session_key, 196 rc = cifs_calculate_signature(cifs_pdu, server,
197 what_we_think_sig_should_be); 197 what_we_think_sig_should_be);
198 198
199 if (rc) 199 if (rc)
@@ -209,18 +209,28 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu,
209 209
210} 210}
211 211
212/* We fill in key by putting in 40 byte array which was allocated by caller */ 212/* first calculate 24 bytes ntlm response and then 16 byte session key */
213int cifs_calculate_session_key(struct session_key *key, const char *rn, 213int setup_ntlm_response(struct cifsSesInfo *ses)
214 const char *password)
215{ 214{
216 char temp_key[16]; 215 unsigned int temp_len = CIFS_SESS_KEY_SIZE + CIFS_AUTH_RESP_SIZE;
217 if ((key == NULL) || (rn == NULL)) 216 char temp_key[CIFS_SESS_KEY_SIZE];
217
218 if (!ses)
218 return -EINVAL; 219 return -EINVAL;
219 220
220 E_md4hash(password, temp_key); 221 ses->auth_key.response = kmalloc(temp_len, GFP_KERNEL);
221 mdfour(key->data.ntlm, temp_key, 16); 222 if (!ses->auth_key.response) {
222 memcpy(key->data.ntlm+16, rn, CIFS_SESS_KEY_SIZE); 223 cERROR(1, "NTLM can't allocate (%u bytes) memory", temp_len);
223 key->len = 40; 224 return -ENOMEM;
225 }
226 ses->auth_key.len = temp_len;
227
228 SMBNTencrypt(ses->password, ses->cryptKey,
229 ses->auth_key.response + CIFS_SESS_KEY_SIZE);
230
231 E_md4hash(ses->password, temp_key);
232 mdfour(ses->auth_key.response, temp_key, CIFS_SESS_KEY_SIZE);
233
224 return 0; 234 return 0;
225} 235}
226 236
@@ -465,19 +475,13 @@ calc_exit_2:
465} 475}
466 476
467int 477int
468setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf, 478setup_ntlmv2_rsp(struct cifsSesInfo *ses, const struct nls_table *nls_cp)
469 const struct nls_table *nls_cp)
470{ 479{
471 int rc; 480 int rc;
472 struct ntlmv2_resp *buf = (struct ntlmv2_resp *)resp_buf; 481 int baselen;
482 struct ntlmv2_resp *buf;
473 struct HMACMD5Context context; 483 struct HMACMD5Context context;
474 484
475 buf->blob_signature = cpu_to_le32(0x00000101);
476 buf->reserved = 0;
477 buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
478 get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));
479 buf->reserved2 = 0;
480
481 if (ses->server->secType == RawNTLMSSP) { 485 if (ses->server->secType == RawNTLMSSP) {
482 if (!ses->domainName) { 486 if (!ses->domainName) {
483 rc = find_domain_name(ses); 487 rc = find_domain_name(ses);
@@ -494,22 +498,38 @@ setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf,
494 } 498 }
495 } 499 }
496 500
501 baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp);
502 ses->auth_key.len = baselen + ses->tilen;
503 ses->auth_key.response = kmalloc(ses->auth_key.len, GFP_KERNEL);
504 if (!ses->auth_key.response) {
505 rc = ENOMEM;
506 cERROR(1, "%s: Can't allocate auth blob", __func__);
507 goto setup_ntlmv2_rsp_ret;
508 }
509
510 buf = (struct ntlmv2_resp *)
511 (ses->auth_key.response + CIFS_SESS_KEY_SIZE);
512 buf->blob_signature = cpu_to_le32(0x00000101);
513 buf->reserved = 0;
514 buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
515 get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));
516 buf->reserved2 = 0;
517
518 memcpy(ses->auth_key.response + baselen, ses->tiblob, ses->tilen);
519
497 /* calculate buf->ntlmv2_hash */ 520 /* calculate buf->ntlmv2_hash */
498 rc = calc_ntlmv2_hash(ses, nls_cp); 521 rc = calc_ntlmv2_hash(ses, nls_cp);
499 if (rc) { 522 if (rc) {
500 cERROR(1, "could not get v2 hash rc %d", rc); 523 cERROR(1, "could not get v2 hash rc %d", rc);
501 goto setup_ntlmv2_rsp_ret; 524 goto setup_ntlmv2_rsp_ret;
502 } 525 }
503 CalcNTLMv2_response(ses, resp_buf); 526 CalcNTLMv2_response(ses);
504 527
505 /* now calculate the session key for NTLMv2 */ 528 /* now calculate the session key for NTLMv2 */
506 hmac_md5_init_limK_to_64(ses->ntlmv2_hash, 16, &context); 529 hmac_md5_init_limK_to_64(ses->ntlmv2_hash, 16, &context);
507 hmac_md5_update(resp_buf, 16, &context); 530 hmac_md5_update(ses->auth_key.response + CIFS_SESS_KEY_SIZE,
508 hmac_md5_final(ses->auth_key.data.ntlmv2.key, &context); 531 16, &context);
509 532 hmac_md5_final(ses->auth_key.response, &context);
510 memcpy(&ses->auth_key.data.ntlmv2.resp, resp_buf,
511 sizeof(struct ntlmv2_resp));
512 ses->auth_key.len = 16 + sizeof(struct ntlmv2_resp);
513 533
514 return 0; 534 return 0;
515 535
@@ -521,20 +541,17 @@ setup_ntlmv2_rsp_ret:
521 return rc; 541 return rc;
522} 542}
523 543
524void CalcNTLMv2_response(const struct cifsSesInfo *ses, 544void CalcNTLMv2_response(const struct cifsSesInfo *ses)
525 char *v2_session_response)
526{ 545{
546 unsigned int offset = CIFS_SESS_KEY_SIZE + 8;
527 struct HMACMD5Context context; 547 struct HMACMD5Context context;
548
528 /* rest of v2 struct already generated */ 549 /* rest of v2 struct already generated */
529 memcpy(v2_session_response + 8, ses->cryptKey, 8); 550 memcpy(ses->auth_key.response + offset, ses->cryptKey, 8);
530 hmac_md5_init_limK_to_64(ses->ntlmv2_hash, 16, &context); 551 hmac_md5_init_limK_to_64(ses->ntlmv2_hash, 16, &context);
531 552
532 hmac_md5_update(v2_session_response+8, 553 hmac_md5_update(ses->auth_key.response + offset,
533 sizeof(struct ntlmv2_resp) - 8, &context); 554 ses->auth_key.len - offset, &context);
534
535 if (ses->tilen)
536 hmac_md5_update(ses->tiblob, ses->tilen, &context);
537 555
538 hmac_md5_final(v2_session_response, &context); 556 hmac_md5_final(ses->auth_key.response + CIFS_SESS_KEY_SIZE, &context);
539/* cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */
540} 557}
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 539475a11c45..66f76b2d270b 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -99,14 +99,7 @@ enum protocolEnum {
99 99
100struct session_key { 100struct session_key {
101 unsigned int len; 101 unsigned int len;
102 union { 102 char *response;
103 char ntlm[CIFS_SESS_KEY_SIZE + 16];
104 char krb5[CIFS_SESS_KEY_SIZE + 16]; /* BB: length correct? */
105 struct {
106 char key[16];
107 struct ntlmv2_resp resp;
108 } ntlmv2;
109 } data;
110}; 103};
111 104
112struct cifs_cred { 105struct cifs_cred {
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index b0f4b5656d4c..a152cd6db99b 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -131,9 +131,14 @@
131#define CIFS_CRYPTO_KEY_SIZE (8) 131#define CIFS_CRYPTO_KEY_SIZE (8)
132 132
133/* 133/*
134 * Size of the ntlm client response
135 */
136#define CIFS_AUTH_RESP_SIZE (24)
137
138/*
134 * Size of the session key (crypto key encrypted with the password 139 * Size of the session key (crypto key encrypted with the password
135 */ 140 */
136#define CIFS_SESS_KEY_SIZE (24) 141#define CIFS_SESS_KEY_SIZE (16)
137 142
138/* 143/*
139 * Maximum user name length 144 * Maximum user name length
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index e593c40ba7ba..8c2d0cf1a62f 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -362,13 +362,12 @@ extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *);
362extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *, 362extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
363 __u32 *); 363 __u32 *);
364extern int cifs_verify_signature(struct smb_hdr *, 364extern int cifs_verify_signature(struct smb_hdr *,
365 const struct session_key *session_key, 365 struct TCP_Server_Info *server,
366 __u32 expected_sequence_number); 366 __u32 expected_sequence_number);
367extern int cifs_calculate_session_key(struct session_key *key, const char *rn, 367extern void SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *);
368 const char *pass); 368extern int setup_ntlm_response(struct cifsSesInfo *);
369extern void CalcNTLMv2_response(const struct cifsSesInfo *, char *); 369extern void CalcNTLMv2_response(const struct cifsSesInfo *);
370extern int setup_ntlmv2_rsp(struct cifsSesInfo *, char *, 370extern int setup_ntlmv2_rsp(struct cifsSesInfo *, const struct nls_table *);
371 const struct nls_table *);
372#ifdef CONFIG_CIFS_WEAK_PW_HASH 371#ifdef CONFIG_CIFS_WEAK_PW_HASH
373extern void calc_lanman_hash(const char *password, const char *cryptkey, 372extern void calc_lanman_hash(const char *password, const char *cryptkey,
374 bool encrypt, char *lnm_session_key); 373 bool encrypt, char *lnm_session_key);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 7e73176acb58..c5807d39dced 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -175,6 +175,9 @@ cifs_reconnect(struct TCP_Server_Info *server)
175 } 175 }
176 server->sequence_number = 0; 176 server->sequence_number = 0;
177 server->session_estab = false; 177 server->session_estab = false;
178 kfree(server->session_key.response);
179 server->session_key.response = NULL;
180 server->session_key.len = 0;
178 181
179 spin_lock(&GlobalMid_Lock); 182 spin_lock(&GlobalMid_Lock);
180 list_for_each(tmp, &server->pending_mid_q) { 183 list_for_each(tmp, &server->pending_mid_q) {
@@ -1562,6 +1565,10 @@ cifs_put_tcp_session(struct TCP_Server_Info *server)
1562 1565
1563 cifs_fscache_release_client_cookie(server); 1566 cifs_fscache_release_client_cookie(server);
1564 1567
1568 kfree(server->session_key.response);
1569 server->session_key.response = NULL;
1570 server->session_key.len = 0;
1571
1565 task = xchg(&server->tsk, NULL); 1572 task = xchg(&server->tsk, NULL);
1566 if (task) 1573 if (task)
1567 force_sig(SIGKILL, task); 1574 force_sig(SIGKILL, task);
@@ -3178,10 +3185,11 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *ses,
3178 } else { 3185 } else {
3179 mutex_lock(&ses->server->srv_mutex); 3186 mutex_lock(&ses->server->srv_mutex);
3180 if (!server->session_estab) { 3187 if (!server->session_estab) {
3181 memcpy(&server->session_key.data, 3188 server->session_key.response = ses->auth_key.response;
3182 &ses->auth_key.data, ses->auth_key.len);
3183 server->session_key.len = ses->auth_key.len; 3189 server->session_key.len = ses->auth_key.len;
3184 ses->server->session_estab = true; 3190 server->sequence_number = 0x2;
3191 server->session_estab = true;
3192 ses->auth_key.response = NULL;
3185 } 3193 }
3186 mutex_unlock(&server->srv_mutex); 3194 mutex_unlock(&server->srv_mutex);
3187 3195
@@ -3192,6 +3200,10 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *ses,
3192 spin_unlock(&GlobalMid_Lock); 3200 spin_unlock(&GlobalMid_Lock);
3193 } 3201 }
3194 3202
3203 kfree(ses->auth_key.response);
3204 ses->auth_key.response = NULL;
3205 ses->auth_key.len = 0;
3206
3195 return rc; 3207 return rc;
3196} 3208}
3197 3209
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 2a11efd96592..b2934683bd08 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -32,9 +32,6 @@
32#include <linux/slab.h> 32#include <linux/slab.h>
33#include "cifs_spnego.h" 33#include "cifs_spnego.h"
34 34
35extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
36 unsigned char *p24);
37
38/* 35/*
39 * Checks if this is the first smb session to be reconnected after 36 * Checks if this is the first smb session to be reconnected after
40 * the socket has been reestablished (so we know whether to use vc 0). 37 * the socket has been reestablished (so we know whether to use vc 0).
@@ -469,11 +466,9 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
469 const struct nls_table *nls_cp) 466 const struct nls_table *nls_cp)
470{ 467{
471 int rc; 468 int rc;
472 unsigned int size;
473 AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer; 469 AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer;
474 __u32 flags; 470 __u32 flags;
475 unsigned char *tmp; 471 unsigned char *tmp;
476 struct ntlmv2_resp ntlmv2_response = {};
477 472
478 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); 473 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
479 sec_blob->MessageType = NtLmAuthenticate; 474 sec_blob->MessageType = NtLmAuthenticate;
@@ -497,25 +492,19 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
497 sec_blob->LmChallengeResponse.MaximumLength = 0; 492 sec_blob->LmChallengeResponse.MaximumLength = 0;
498 493
499 sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer); 494 sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer);
500 rc = setup_ntlmv2_rsp(ses, (char *)&ntlmv2_response, nls_cp); 495 rc = setup_ntlmv2_rsp(ses, nls_cp);
501 if (rc) { 496 if (rc) {
502 cERROR(1, "Error %d during NTLMSSP authentication", rc); 497 cERROR(1, "Error %d during NTLMSSP authentication", rc);
503 goto setup_ntlmv2_ret; 498 goto setup_ntlmv2_ret;
504 } 499 }
505 size = sizeof(struct ntlmv2_resp); 500 memcpy(tmp, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
506 memcpy(tmp, (char *)&ntlmv2_response, size); 501 ses->auth_key.len - CIFS_SESS_KEY_SIZE);
507 tmp += size; 502 tmp += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
508 if (ses->tilen > 0) {
509 memcpy(tmp, ses->tiblob, ses->tilen);
510 tmp += ses->tilen;
511 }
512 503
513 sec_blob->NtChallengeResponse.Length = cpu_to_le16(size + ses->tilen); 504 sec_blob->NtChallengeResponse.Length =
505 cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
514 sec_blob->NtChallengeResponse.MaximumLength = 506 sec_blob->NtChallengeResponse.MaximumLength =
515 cpu_to_le16(size + ses->tilen); 507 cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
516 kfree(ses->tiblob);
517 ses->tiblob = NULL;
518 ses->tilen = 0;
519 508
520 if (ses->domainName == NULL) { 509 if (ses->domainName == NULL) {
521 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); 510 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
@@ -687,24 +676,27 @@ ssetup_ntlmssp_authenticate:
687 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); 676 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
688#endif 677#endif
689 } else if (type == NTLM) { 678 } else if (type == NTLM) {
690 char ntlm_session_key[CIFS_SESS_KEY_SIZE];
691
692 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); 679 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
693 pSMB->req_no_secext.CaseInsensitivePasswordLength = 680 pSMB->req_no_secext.CaseInsensitivePasswordLength =
694 cpu_to_le16(CIFS_SESS_KEY_SIZE); 681 cpu_to_le16(CIFS_AUTH_RESP_SIZE);
695 pSMB->req_no_secext.CaseSensitivePasswordLength = 682 pSMB->req_no_secext.CaseSensitivePasswordLength =
696 cpu_to_le16(CIFS_SESS_KEY_SIZE); 683 cpu_to_le16(CIFS_AUTH_RESP_SIZE);
684
685 /* calculate ntlm response and session key */
686 rc = setup_ntlm_response(ses);
687 if (rc) {
688 cERROR(1, "Error %d during NTLM authentication", rc);
689 goto ssetup_exit;
690 }
697 691
698 /* calculate session key */ 692 /* copy ntlm response */
699 SMBNTencrypt(ses->password, ses->cryptKey, ntlm_session_key); 693 memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
694 CIFS_AUTH_RESP_SIZE);
695 bcc_ptr += CIFS_AUTH_RESP_SIZE;
696 memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
697 CIFS_AUTH_RESP_SIZE);
698 bcc_ptr += CIFS_AUTH_RESP_SIZE;
700 699
701 cifs_calculate_session_key(&ses->auth_key,
702 ntlm_session_key, ses->password);
703 /* copy session key */
704 memcpy(bcc_ptr, (char *)ntlm_session_key, CIFS_SESS_KEY_SIZE);
705 bcc_ptr += CIFS_SESS_KEY_SIZE;
706 memcpy(bcc_ptr, (char *)ntlm_session_key, CIFS_SESS_KEY_SIZE);
707 bcc_ptr += CIFS_SESS_KEY_SIZE;
708 if (ses->capabilities & CAP_UNICODE) { 700 if (ses->capabilities & CAP_UNICODE) {
709 /* unicode strings must be word aligned */ 701 /* unicode strings must be word aligned */
710 if (iov[0].iov_len % 2) { 702 if (iov[0].iov_len % 2) {
@@ -715,47 +707,26 @@ ssetup_ntlmssp_authenticate:
715 } else 707 } else
716 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); 708 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
717 } else if (type == NTLMv2) { 709 } else if (type == NTLMv2) {
718 char *v2_sess_key =
719 kmalloc(sizeof(struct ntlmv2_resp), GFP_KERNEL);
720
721 /* BB FIXME change all users of v2_sess_key to
722 struct ntlmv2_resp */
723
724 if (v2_sess_key == NULL) {
725 rc = -ENOMEM;
726 goto ssetup_exit;
727 }
728
729 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); 710 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
730 711
731 /* LM2 password would be here if we supported it */ 712 /* LM2 password would be here if we supported it */
732 pSMB->req_no_secext.CaseInsensitivePasswordLength = 0; 713 pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
733 /* cpu_to_le16(LM2_SESS_KEY_SIZE); */
734 714
735 /* calculate session key */ 715 /* calculate nlmv2 response and session key */
736 rc = setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp); 716 rc = setup_ntlmv2_rsp(ses, nls_cp);
737 if (rc) { 717 if (rc) {
738 cERROR(1, "Error %d during NTLMv2 authentication", rc); 718 cERROR(1, "Error %d during NTLMv2 authentication", rc);
739 kfree(v2_sess_key);
740 goto ssetup_exit; 719 goto ssetup_exit;
741 } 720 }
742 memcpy(bcc_ptr, (char *)v2_sess_key, 721 memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
743 sizeof(struct ntlmv2_resp)); 722 ses->auth_key.len - CIFS_SESS_KEY_SIZE);
744 bcc_ptr += sizeof(struct ntlmv2_resp); 723 bcc_ptr += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
745 kfree(v2_sess_key); 724
746 /* set case sensitive password length after tilen may get 725 /* set case sensitive password length after tilen may get
747 * assigned, tilen is 0 otherwise. 726 * assigned, tilen is 0 otherwise.
748 */ 727 */
749 pSMB->req_no_secext.CaseSensitivePasswordLength = 728 pSMB->req_no_secext.CaseSensitivePasswordLength =
750 cpu_to_le16(sizeof(struct ntlmv2_resp) + ses->tilen); 729 cpu_to_le16(ses->auth_key.len);
751 if (ses->tilen > 0) {
752 memcpy(bcc_ptr, ses->tiblob, ses->tilen);
753 bcc_ptr += ses->tilen;
754 /* we never did allocate ses->domainName to free */
755 kfree(ses->tiblob);
756 ses->tiblob = NULL;
757 ses->tilen = 0;
758 }
759 730
760 if (ses->capabilities & CAP_UNICODE) { 731 if (ses->capabilities & CAP_UNICODE) {
761 if (iov[0].iov_len % 2) { 732 if (iov[0].iov_len % 2) {
@@ -768,6 +739,7 @@ ssetup_ntlmssp_authenticate:
768 } else if (type == Kerberos) { 739 } else if (type == Kerberos) {
769#ifdef CONFIG_CIFS_UPCALL 740#ifdef CONFIG_CIFS_UPCALL
770 struct cifs_spnego_msg *msg; 741 struct cifs_spnego_msg *msg;
742
771 spnego_key = cifs_get_spnego_key(ses); 743 spnego_key = cifs_get_spnego_key(ses);
772 if (IS_ERR(spnego_key)) { 744 if (IS_ERR(spnego_key)) {
773 rc = PTR_ERR(spnego_key); 745 rc = PTR_ERR(spnego_key);
@@ -785,16 +757,17 @@ ssetup_ntlmssp_authenticate:
785 rc = -EKEYREJECTED; 757 rc = -EKEYREJECTED;
786 goto ssetup_exit; 758 goto ssetup_exit;
787 } 759 }
788 /* bail out if key is too long */ 760
789 if (msg->sesskey_len > 761 ses->auth_key.response = kmalloc(msg->sesskey_len, GFP_KERNEL);
790 sizeof(ses->auth_key.data.krb5)) { 762 if (!ses->auth_key.response) {
791 cERROR(1, "Kerberos signing key too long (%u bytes)", 763 cERROR(1, "Kerberos can't allocate (%u bytes) memory",
792 msg->sesskey_len); 764 msg->sesskey_len);
793 rc = -EOVERFLOW; 765 rc = -ENOMEM;
794 goto ssetup_exit; 766 goto ssetup_exit;
795 } 767 }
768 memcpy(ses->auth_key.response, msg->data, msg->sesskey_len);
796 ses->auth_key.len = msg->sesskey_len; 769 ses->auth_key.len = msg->sesskey_len;
797 memcpy(ses->auth_key.data.krb5, msg->data, msg->sesskey_len); 770
798 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; 771 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
799 capabilities |= CAP_EXTENDED_SECURITY; 772 capabilities |= CAP_EXTENDED_SECURITY;
800 pSMB->req.Capabilities = cpu_to_le32(capabilities); 773 pSMB->req.Capabilities = cpu_to_le32(capabilities);
@@ -897,8 +870,6 @@ ssetup_ntlmssp_authenticate:
897 CIFS_STD_OP /* not long */ | CIFS_LOG_ERROR); 870 CIFS_STD_OP /* not long */ | CIFS_LOG_ERROR);
898 /* SMB request buf freed in SendReceive2 */ 871 /* SMB request buf freed in SendReceive2 */
899 872
900 cFYI(1, "ssetup rc from sendrecv2 is %d", rc);
901
902 pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base; 873 pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base;
903 smb_buf = (struct smb_hdr *)iov[0].iov_base; 874 smb_buf = (struct smb_hdr *)iov[0].iov_base;
904 875
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index a66c91eb6eb4..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->session_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->session_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->session_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");