diff options
| -rw-r--r-- | fs/cifs/cifs_unicode.c | 33 | ||||
| -rw-r--r-- | fs/cifs/cifs_unicode.h | 2 | ||||
| -rw-r--r-- | fs/cifs/cifsfs.c | 3 | ||||
| -rw-r--r-- | fs/cifs/cifsglob.h | 1 | ||||
| -rw-r--r-- | fs/cifs/connect.c | 4 | ||||
| -rw-r--r-- | fs/cifs/file.c | 14 | ||||
| -rw-r--r-- | fs/cifs/ntlmssp.h | 2 | ||||
| -rw-r--r-- | fs/cifs/sess.c | 80 | ||||
| -rw-r--r-- | fs/cifs/smb2pdu.c | 37 |
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 | ||
| 407 | static __le16 convert_to_sfm_char(char src_char) | 413 | static __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; | |||
| 87 | extern mempool_t *cifs_mid_poolp; | 87 | extern mempool_t *cifs_mid_poolp; |
| 88 | 88 | ||
| 89 | struct workqueue_struct *cifsiod_wq; | 89 | struct 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 | ||
| 1620 | extern const struct slow_work_ops cifs_oplock_break_ops; | 1620 | extern const struct slow_work_ops cifs_oplock_break_ops; |
| 1621 | extern struct workqueue_struct *cifsiod_wq; | 1621 | extern struct workqueue_struct *cifsiod_wq; |
| 1622 | extern __u32 cifs_lock_secret; | ||
| 1622 | 1623 | ||
| 1623 | extern mempool_t *cifs_mid_poolp; | 1624 | extern 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 | ||
| 1115 | static __u32 | ||
| 1116 | hash_lockowner(fl_owner_t owner) | ||
| 1117 | { | ||
| 1118 | return cifs_lock_secret ^ hash32_ptr((const void *)owner); | ||
| 1119 | } | ||
| 1120 | |||
| 1115 | struct lock_to_push { | 1121 | struct 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 | ||
| 134 | int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, struct cifs_ses *ses); | 134 | int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, struct cifs_ses *ses); |
| 135 | void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, struct cifs_ses *ses); | 135 | void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, struct cifs_ses *ses); |
| 136 | int build_ntlmssp_auth_blob(unsigned char *pbuffer, u16 *buflen, | 136 | int 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 | 367 | static 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 |
| 370 | int 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 | |||
| 385 | int 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; | ||
| 477 | setup_ntlmv2_ret: | 498 | setup_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; |
