aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/cifs_unicode.c33
-rw-r--r--fs/cifs/cifs_unicode.h2
-rw-r--r--fs/cifs/cifsfs.c3
-rw-r--r--fs/cifs/cifsglob.h1
-rw-r--r--fs/cifs/connect.c4
-rw-r--r--fs/cifs/file.c14
-rw-r--r--fs/cifs/ntlmssp.h2
-rw-r--r--fs/cifs/sess.c80
-rw-r--r--fs/cifs/smb2pdu.c37
9 files changed, 124 insertions, 52 deletions
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index 5a53ac6b1e02..02b071bf3732 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -101,6 +101,12 @@ convert_sfm_char(const __u16 src_char, char *target)
101 case SFM_SLASH: 101 case SFM_SLASH:
102 *target = '\\'; 102 *target = '\\';
103 break; 103 break;
104 case SFM_SPACE:
105 *target = ' ';
106 break;
107 case SFM_PERIOD:
108 *target = '.';
109 break;
104 default: 110 default:
105 return false; 111 return false;
106 } 112 }
@@ -404,7 +410,7 @@ static __le16 convert_to_sfu_char(char src_char)
404 return dest_char; 410 return dest_char;
405} 411}
406 412
407static __le16 convert_to_sfm_char(char src_char) 413static __le16 convert_to_sfm_char(char src_char, bool end_of_string)
408{ 414{
409 __le16 dest_char; 415 __le16 dest_char;
410 416
@@ -427,6 +433,18 @@ static __le16 convert_to_sfm_char(char src_char)
427 case '|': 433 case '|':
428 dest_char = cpu_to_le16(SFM_PIPE); 434 dest_char = cpu_to_le16(SFM_PIPE);
429 break; 435 break;
436 case '.':
437 if (end_of_string)
438 dest_char = cpu_to_le16(SFM_PERIOD);
439 else
440 dest_char = 0;
441 break;
442 case ' ':
443 if (end_of_string)
444 dest_char = cpu_to_le16(SFM_SPACE);
445 else
446 dest_char = 0;
447 break;
430 default: 448 default:
431 dest_char = 0; 449 dest_char = 0;
432 } 450 }
@@ -469,9 +487,16 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen,
469 /* see if we must remap this char */ 487 /* see if we must remap this char */
470 if (map_chars == SFU_MAP_UNI_RSVD) 488 if (map_chars == SFU_MAP_UNI_RSVD)
471 dst_char = convert_to_sfu_char(src_char); 489 dst_char = convert_to_sfu_char(src_char);
472 else if (map_chars == SFM_MAP_UNI_RSVD) 490 else if (map_chars == SFM_MAP_UNI_RSVD) {
473 dst_char = convert_to_sfm_char(src_char); 491 bool end_of_string;
474 else 492
493 if (i == srclen - 1)
494 end_of_string = true;
495 else
496 end_of_string = false;
497
498 dst_char = convert_to_sfm_char(src_char, end_of_string);
499 } else
475 dst_char = 0; 500 dst_char = 0;
476 /* 501 /*
477 * FIXME: We can not handle remapping backslash (UNI_SLASH) 502 * FIXME: We can not handle remapping backslash (UNI_SLASH)
diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h
index bdc52cb9a676..479bc0a941f3 100644
--- a/fs/cifs/cifs_unicode.h
+++ b/fs/cifs/cifs_unicode.h
@@ -64,6 +64,8 @@
64#define SFM_LESSTHAN ((__u16) 0xF023) 64#define SFM_LESSTHAN ((__u16) 0xF023)
65#define SFM_PIPE ((__u16) 0xF027) 65#define SFM_PIPE ((__u16) 0xF027)
66#define SFM_SLASH ((__u16) 0xF026) 66#define SFM_SLASH ((__u16) 0xF026)
67#define SFM_PERIOD ((__u16) 0xF028)
68#define SFM_SPACE ((__u16) 0xF029)
67 69
68/* 70/*
69 * Mapping mechanism to use when one of the seven reserved characters is 71 * Mapping mechanism to use when one of the seven reserved characters is
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 5d8b7edf8a8f..5d841f39c4b7 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -87,6 +87,7 @@ extern mempool_t *cifs_req_poolp;
87extern mempool_t *cifs_mid_poolp; 87extern mempool_t *cifs_mid_poolp;
88 88
89struct workqueue_struct *cifsiod_wq; 89struct workqueue_struct *cifsiod_wq;
90__u32 cifs_lock_secret;
90 91
91/* 92/*
92 * Bumps refcount for cifs super block. 93 * Bumps refcount for cifs super block.
@@ -1266,6 +1267,8 @@ init_cifs(void)
1266 spin_lock_init(&cifs_file_list_lock); 1267 spin_lock_init(&cifs_file_list_lock);
1267 spin_lock_init(&GlobalMid_Lock); 1268 spin_lock_init(&GlobalMid_Lock);
1268 1269
1270 get_random_bytes(&cifs_lock_secret, sizeof(cifs_lock_secret));
1271
1269 if (cifs_max_pending < 2) { 1272 if (cifs_max_pending < 2) {
1270 cifs_max_pending = 2; 1273 cifs_max_pending = 2;
1271 cifs_dbg(FYI, "cifs_max_pending set to min of 2\n"); 1274 cifs_dbg(FYI, "cifs_max_pending set to min of 2\n");
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index bba106cdc43c..8f1d8c1e72be 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -1619,6 +1619,7 @@ void cifs_oplock_break(struct work_struct *work);
1619 1619
1620extern const struct slow_work_ops cifs_oplock_break_ops; 1620extern const struct slow_work_ops cifs_oplock_break_ops;
1621extern struct workqueue_struct *cifsiod_wq; 1621extern struct workqueue_struct *cifsiod_wq;
1622extern __u32 cifs_lock_secret;
1622 1623
1623extern mempool_t *cifs_mid_poolp; 1624extern mempool_t *cifs_mid_poolp;
1624 1625
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 66736f57b5ab..7d2b15c06090 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -428,7 +428,9 @@ cifs_echo_request(struct work_struct *work)
428 * server->ops->need_neg() == true. Also, no need to ping if 428 * server->ops->need_neg() == true. Also, no need to ping if
429 * we got a response recently. 429 * we got a response recently.
430 */ 430 */
431 if (!server->ops->need_neg || server->ops->need_neg(server) || 431
432 if (server->tcpStatus == CifsNeedReconnect ||
433 server->tcpStatus == CifsExiting || server->tcpStatus == CifsNew ||
432 (server->ops->can_echo && !server->ops->can_echo(server)) || 434 (server->ops->can_echo && !server->ops->can_echo(server)) ||
433 time_before(jiffies, server->lstrp + echo_interval - HZ)) 435 time_before(jiffies, server->lstrp + echo_interval - HZ))
434 goto requeue_echo; 436 goto requeue_echo;
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 9793ae0bcaa2..d4890b6dc22d 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1112,6 +1112,12 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
1112 return rc; 1112 return rc;
1113} 1113}
1114 1114
1115static __u32
1116hash_lockowner(fl_owner_t owner)
1117{
1118 return cifs_lock_secret ^ hash32_ptr((const void *)owner);
1119}
1120
1115struct lock_to_push { 1121struct lock_to_push {
1116 struct list_head llist; 1122 struct list_head llist;
1117 __u64 offset; 1123 __u64 offset;
@@ -1178,7 +1184,7 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile)
1178 else 1184 else
1179 type = CIFS_WRLCK; 1185 type = CIFS_WRLCK;
1180 lck = list_entry(el, struct lock_to_push, llist); 1186 lck = list_entry(el, struct lock_to_push, llist);
1181 lck->pid = flock->fl_pid; 1187 lck->pid = hash_lockowner(flock->fl_owner);
1182 lck->netfid = cfile->fid.netfid; 1188 lck->netfid = cfile->fid.netfid;
1183 lck->length = length; 1189 lck->length = length;
1184 lck->type = type; 1190 lck->type = type;
@@ -1305,7 +1311,8 @@ cifs_getlk(struct file *file, struct file_lock *flock, __u32 type,
1305 posix_lock_type = CIFS_RDLCK; 1311 posix_lock_type = CIFS_RDLCK;
1306 else 1312 else
1307 posix_lock_type = CIFS_WRLCK; 1313 posix_lock_type = CIFS_WRLCK;
1308 rc = CIFSSMBPosixLock(xid, tcon, netfid, current->tgid, 1314 rc = CIFSSMBPosixLock(xid, tcon, netfid,
1315 hash_lockowner(flock->fl_owner),
1309 flock->fl_start, length, flock, 1316 flock->fl_start, length, flock,
1310 posix_lock_type, wait_flag); 1317 posix_lock_type, wait_flag);
1311 return rc; 1318 return rc;
@@ -1505,7 +1512,8 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
1505 posix_lock_type = CIFS_UNLCK; 1512 posix_lock_type = CIFS_UNLCK;
1506 1513
1507 rc = CIFSSMBPosixLock(xid, tcon, cfile->fid.netfid, 1514 rc = CIFSSMBPosixLock(xid, tcon, cfile->fid.netfid,
1508 current->tgid, flock->fl_start, length, 1515 hash_lockowner(flock->fl_owner),
1516 flock->fl_start, length,
1509 NULL, posix_lock_type, wait_flag); 1517 NULL, posix_lock_type, wait_flag);
1510 goto out; 1518 goto out;
1511 } 1519 }
diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h
index 848249fa120f..3079b38f0afb 100644
--- a/fs/cifs/ntlmssp.h
+++ b/fs/cifs/ntlmssp.h
@@ -133,6 +133,6 @@ typedef struct _AUTHENTICATE_MESSAGE {
133 133
134int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, struct cifs_ses *ses); 134int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, struct cifs_ses *ses);
135void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, struct cifs_ses *ses); 135void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, struct cifs_ses *ses);
136int build_ntlmssp_auth_blob(unsigned char *pbuffer, u16 *buflen, 136int build_ntlmssp_auth_blob(unsigned char **pbuffer, u16 *buflen,
137 struct cifs_ses *ses, 137 struct cifs_ses *ses,
138 const struct nls_table *nls_cp); 138 const struct nls_table *nls_cp);
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index af0ec2d5ad0e..538d9b55699a 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -364,19 +364,43 @@ void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
364 sec_blob->DomainName.MaximumLength = 0; 364 sec_blob->DomainName.MaximumLength = 0;
365} 365}
366 366
367/* We do not malloc the blob, it is passed in pbuffer, because its 367static int size_of_ntlmssp_blob(struct cifs_ses *ses)
368 maximum possible size is fixed and small, making this approach cleaner. 368{
369 This function returns the length of the data in the blob */ 369 int sz = sizeof(AUTHENTICATE_MESSAGE) + ses->auth_key.len
370int build_ntlmssp_auth_blob(unsigned char *pbuffer, 370 - CIFS_SESS_KEY_SIZE + CIFS_CPHTXT_SIZE + 2;
371
372 if (ses->domainName)
373 sz += 2 * strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
374 else
375 sz += 2;
376
377 if (ses->user_name)
378 sz += 2 * strnlen(ses->user_name, CIFS_MAX_USERNAME_LEN);
379 else
380 sz += 2;
381
382 return sz;
383}
384
385int build_ntlmssp_auth_blob(unsigned char **pbuffer,
371 u16 *buflen, 386 u16 *buflen,
372 struct cifs_ses *ses, 387 struct cifs_ses *ses,
373 const struct nls_table *nls_cp) 388 const struct nls_table *nls_cp)
374{ 389{
375 int rc; 390 int rc;
376 AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer; 391 AUTHENTICATE_MESSAGE *sec_blob;
377 __u32 flags; 392 __u32 flags;
378 unsigned char *tmp; 393 unsigned char *tmp;
379 394
395 rc = setup_ntlmv2_rsp(ses, nls_cp);
396 if (rc) {
397 cifs_dbg(VFS, "Error %d during NTLMSSP authentication\n", rc);
398 *buflen = 0;
399 goto setup_ntlmv2_ret;
400 }
401 *pbuffer = kmalloc(size_of_ntlmssp_blob(ses), GFP_KERNEL);
402 sec_blob = (AUTHENTICATE_MESSAGE *)*pbuffer;
403
380 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); 404 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
381 sec_blob->MessageType = NtLmAuthenticate; 405 sec_blob->MessageType = NtLmAuthenticate;
382 406
@@ -391,7 +415,7 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
391 flags |= NTLMSSP_NEGOTIATE_KEY_XCH; 415 flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
392 } 416 }
393 417
394 tmp = pbuffer + sizeof(AUTHENTICATE_MESSAGE); 418 tmp = *pbuffer + sizeof(AUTHENTICATE_MESSAGE);
395 sec_blob->NegotiateFlags = cpu_to_le32(flags); 419 sec_blob->NegotiateFlags = cpu_to_le32(flags);
396 420
397 sec_blob->LmChallengeResponse.BufferOffset = 421 sec_blob->LmChallengeResponse.BufferOffset =
@@ -399,13 +423,9 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
399 sec_blob->LmChallengeResponse.Length = 0; 423 sec_blob->LmChallengeResponse.Length = 0;
400 sec_blob->LmChallengeResponse.MaximumLength = 0; 424 sec_blob->LmChallengeResponse.MaximumLength = 0;
401 425
402 sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer); 426 sec_blob->NtChallengeResponse.BufferOffset =
427 cpu_to_le32(tmp - *pbuffer);
403 if (ses->user_name != NULL) { 428 if (ses->user_name != NULL) {
404 rc = setup_ntlmv2_rsp(ses, nls_cp);
405 if (rc) {
406 cifs_dbg(VFS, "Error %d during NTLMSSP authentication\n", rc);
407 goto setup_ntlmv2_ret;
408 }
409 memcpy(tmp, ses->auth_key.response + CIFS_SESS_KEY_SIZE, 429 memcpy(tmp, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
410 ses->auth_key.len - CIFS_SESS_KEY_SIZE); 430 ses->auth_key.len - CIFS_SESS_KEY_SIZE);
411 tmp += ses->auth_key.len - CIFS_SESS_KEY_SIZE; 431 tmp += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
@@ -423,23 +443,23 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
423 } 443 }
424 444
425 if (ses->domainName == NULL) { 445 if (ses->domainName == NULL) {
426 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); 446 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
427 sec_blob->DomainName.Length = 0; 447 sec_blob->DomainName.Length = 0;
428 sec_blob->DomainName.MaximumLength = 0; 448 sec_blob->DomainName.MaximumLength = 0;
429 tmp += 2; 449 tmp += 2;
430 } else { 450 } else {
431 int len; 451 int len;
432 len = cifs_strtoUTF16((__le16 *)tmp, ses->domainName, 452 len = cifs_strtoUTF16((__le16 *)tmp, ses->domainName,
433 CIFS_MAX_USERNAME_LEN, nls_cp); 453 CIFS_MAX_DOMAINNAME_LEN, nls_cp);
434 len *= 2; /* unicode is 2 bytes each */ 454 len *= 2; /* unicode is 2 bytes each */
435 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); 455 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
436 sec_blob->DomainName.Length = cpu_to_le16(len); 456 sec_blob->DomainName.Length = cpu_to_le16(len);
437 sec_blob->DomainName.MaximumLength = cpu_to_le16(len); 457 sec_blob->DomainName.MaximumLength = cpu_to_le16(len);
438 tmp += len; 458 tmp += len;
439 } 459 }
440 460
441 if (ses->user_name == NULL) { 461 if (ses->user_name == NULL) {
442 sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer); 462 sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
443 sec_blob->UserName.Length = 0; 463 sec_blob->UserName.Length = 0;
444 sec_blob->UserName.MaximumLength = 0; 464 sec_blob->UserName.MaximumLength = 0;
445 tmp += 2; 465 tmp += 2;
@@ -448,13 +468,13 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
448 len = cifs_strtoUTF16((__le16 *)tmp, ses->user_name, 468 len = cifs_strtoUTF16((__le16 *)tmp, ses->user_name,
449 CIFS_MAX_USERNAME_LEN, nls_cp); 469 CIFS_MAX_USERNAME_LEN, nls_cp);
450 len *= 2; /* unicode is 2 bytes each */ 470 len *= 2; /* unicode is 2 bytes each */
451 sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer); 471 sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
452 sec_blob->UserName.Length = cpu_to_le16(len); 472 sec_blob->UserName.Length = cpu_to_le16(len);
453 sec_blob->UserName.MaximumLength = cpu_to_le16(len); 473 sec_blob->UserName.MaximumLength = cpu_to_le16(len);
454 tmp += len; 474 tmp += len;
455 } 475 }
456 476
457 sec_blob->WorkstationName.BufferOffset = cpu_to_le32(tmp - pbuffer); 477 sec_blob->WorkstationName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
458 sec_blob->WorkstationName.Length = 0; 478 sec_blob->WorkstationName.Length = 0;
459 sec_blob->WorkstationName.MaximumLength = 0; 479 sec_blob->WorkstationName.MaximumLength = 0;
460 tmp += 2; 480 tmp += 2;
@@ -463,19 +483,19 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
463 (ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_EXTENDED_SEC)) 483 (ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_EXTENDED_SEC))
464 && !calc_seckey(ses)) { 484 && !calc_seckey(ses)) {
465 memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE); 485 memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE);
466 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); 486 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - *pbuffer);
467 sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE); 487 sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE);
468 sec_blob->SessionKey.MaximumLength = 488 sec_blob->SessionKey.MaximumLength =
469 cpu_to_le16(CIFS_CPHTXT_SIZE); 489 cpu_to_le16(CIFS_CPHTXT_SIZE);
470 tmp += CIFS_CPHTXT_SIZE; 490 tmp += CIFS_CPHTXT_SIZE;
471 } else { 491 } else {
472 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); 492 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - *pbuffer);
473 sec_blob->SessionKey.Length = 0; 493 sec_blob->SessionKey.Length = 0;
474 sec_blob->SessionKey.MaximumLength = 0; 494 sec_blob->SessionKey.MaximumLength = 0;
475 } 495 }
476 496
497 *buflen = tmp - *pbuffer;
477setup_ntlmv2_ret: 498setup_ntlmv2_ret:
478 *buflen = tmp - pbuffer;
479 return rc; 499 return rc;
480} 500}
481 501
@@ -690,6 +710,8 @@ sess_auth_lanman(struct sess_data *sess_data)
690 rc = calc_lanman_hash(ses->password, ses->server->cryptkey, 710 rc = calc_lanman_hash(ses->password, ses->server->cryptkey,
691 ses->server->sec_mode & SECMODE_PW_ENCRYPT ? 711 ses->server->sec_mode & SECMODE_PW_ENCRYPT ?
692 true : false, lnm_session_key); 712 true : false, lnm_session_key);
713 if (rc)
714 goto out;
693 715
694 memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_AUTH_RESP_SIZE); 716 memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_AUTH_RESP_SIZE);
695 bcc_ptr += CIFS_AUTH_RESP_SIZE; 717 bcc_ptr += CIFS_AUTH_RESP_SIZE;
@@ -1266,7 +1288,7 @@ sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data)
1266 struct cifs_ses *ses = sess_data->ses; 1288 struct cifs_ses *ses = sess_data->ses;
1267 __u16 bytes_remaining; 1289 __u16 bytes_remaining;
1268 char *bcc_ptr; 1290 char *bcc_ptr;
1269 char *ntlmsspblob = NULL; 1291 unsigned char *ntlmsspblob = NULL;
1270 u16 blob_len; 1292 u16 blob_len;
1271 1293
1272 cifs_dbg(FYI, "rawntlmssp session setup authenticate phase\n"); 1294 cifs_dbg(FYI, "rawntlmssp session setup authenticate phase\n");
@@ -1279,19 +1301,7 @@ sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data)
1279 /* Build security blob before we assemble the request */ 1301 /* Build security blob before we assemble the request */
1280 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base; 1302 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1281 smb_buf = (struct smb_hdr *)pSMB; 1303 smb_buf = (struct smb_hdr *)pSMB;
1282 /* 1304 rc = build_ntlmssp_auth_blob(&ntlmsspblob,
1283 * 5 is an empirical value, large enough to hold
1284 * authenticate message plus max 10 of av paris,
1285 * domain, user, workstation names, flags, etc.
1286 */
1287 ntlmsspblob = kzalloc(5*sizeof(struct _AUTHENTICATE_MESSAGE),
1288 GFP_KERNEL);
1289 if (!ntlmsspblob) {
1290 rc = -ENOMEM;
1291 goto out;
1292 }
1293
1294 rc = build_ntlmssp_auth_blob(ntlmsspblob,
1295 &blob_len, ses, sess_data->nls_cp); 1305 &blob_len, ses, sess_data->nls_cp);
1296 if (rc) 1306 if (rc)
1297 goto out_free_ntlmsspblob; 1307 goto out_free_ntlmsspblob;
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 8f38e33d365b..29e06db5f187 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -588,7 +588,7 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
588 u16 blob_length = 0; 588 u16 blob_length = 0;
589 struct key *spnego_key = NULL; 589 struct key *spnego_key = NULL;
590 char *security_blob = NULL; 590 char *security_blob = NULL;
591 char *ntlmssp_blob = NULL; 591 unsigned char *ntlmssp_blob = NULL;
592 bool use_spnego = false; /* else use raw ntlmssp */ 592 bool use_spnego = false; /* else use raw ntlmssp */
593 593
594 cifs_dbg(FYI, "Session Setup\n"); 594 cifs_dbg(FYI, "Session Setup\n");
@@ -713,13 +713,7 @@ ssetup_ntlmssp_authenticate:
713 iov[1].iov_len = blob_length; 713 iov[1].iov_len = blob_length;
714 } else if (phase == NtLmAuthenticate) { 714 } else if (phase == NtLmAuthenticate) {
715 req->hdr.SessionId = ses->Suid; 715 req->hdr.SessionId = ses->Suid;
716 ntlmssp_blob = kzalloc(sizeof(struct _NEGOTIATE_MESSAGE) + 500, 716 rc = build_ntlmssp_auth_blob(&ntlmssp_blob, &blob_length, ses,
717 GFP_KERNEL);
718 if (ntlmssp_blob == NULL) {
719 rc = -ENOMEM;
720 goto ssetup_exit;
721 }
722 rc = build_ntlmssp_auth_blob(ntlmssp_blob, &blob_length, ses,
723 nls_cp); 717 nls_cp);
724 if (rc) { 718 if (rc) {
725 cifs_dbg(FYI, "build_ntlmssp_auth_blob failed %d\n", 719 cifs_dbg(FYI, "build_ntlmssp_auth_blob failed %d\n",
@@ -1818,6 +1812,33 @@ SMB2_echo(struct TCP_Server_Info *server)
1818 1812
1819 cifs_dbg(FYI, "In echo request\n"); 1813 cifs_dbg(FYI, "In echo request\n");
1820 1814
1815 if (server->tcpStatus == CifsNeedNegotiate) {
1816 struct list_head *tmp, *tmp2;
1817 struct cifs_ses *ses;
1818 struct cifs_tcon *tcon;
1819
1820 cifs_dbg(FYI, "Need negotiate, reconnecting tcons\n");
1821 spin_lock(&cifs_tcp_ses_lock);
1822 list_for_each(tmp, &server->smb_ses_list) {
1823 ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
1824 list_for_each(tmp2, &ses->tcon_list) {
1825 tcon = list_entry(tmp2, struct cifs_tcon,
1826 tcon_list);
1827 /* add check for persistent handle reconnect */
1828 if (tcon && tcon->need_reconnect) {
1829 spin_unlock(&cifs_tcp_ses_lock);
1830 rc = smb2_reconnect(SMB2_ECHO, tcon);
1831 spin_lock(&cifs_tcp_ses_lock);
1832 }
1833 }
1834 }
1835 spin_unlock(&cifs_tcp_ses_lock);
1836 }
1837
1838 /* if no session, renegotiate failed above */
1839 if (server->tcpStatus == CifsNeedNegotiate)
1840 return -EIO;
1841
1821 rc = small_smb2_init(SMB2_ECHO, NULL, (void **)&req); 1842 rc = small_smb2_init(SMB2_ECHO, NULL, (void **)&req);
1822 if (rc) 1843 if (rc)
1823 return rc; 1844 return rc;