aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/sess.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/sess.c')
-rw-r--r--fs/cifs/sess.c136
1 files changed, 91 insertions, 45 deletions
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 0a57cb7db5dd..c926e6c7c0c6 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; /* challenge message target info area */
387 unsigned int tilen; /* challenge 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,19 @@ 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->tilen = tilen;
414 if (ses->tilen) {
415 ses->tiblob = kmalloc(tilen, GFP_KERNEL);
416 if (!ses->tiblob) {
417 cERROR(1, "Challenge target info allocation failure");
418 ses->tilen = 0;
419 return -ENOMEM;
420 }
421 memcpy(ses->tiblob, bcc_ptr + tioffset, ses->tilen);
422 }
423
408 return 0; 424 return 0;
409} 425}
410 426
@@ -425,7 +441,7 @@ static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
425 /* BB is NTLMV2 session security format easier to use here? */ 441 /* BB is NTLMV2 session security format easier to use here? */
426 flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET | 442 flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET |
427 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | 443 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
428 NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM; 444 NTLMSSP_NEGOTIATE_NTLM;
429 if (ses->server->secMode & 445 if (ses->server->secMode &
430 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) 446 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
431 flags |= NTLMSSP_NEGOTIATE_SIGN; 447 flags |= NTLMSSP_NEGOTIATE_SIGN;
@@ -449,12 +465,14 @@ static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
449 This function returns the length of the data in the blob */ 465 This function returns the length of the data in the blob */
450static int build_ntlmssp_auth_blob(unsigned char *pbuffer, 466static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
451 struct cifsSesInfo *ses, 467 struct cifsSesInfo *ses,
452 const struct nls_table *nls_cp, bool first) 468 const struct nls_table *nls_cp)
453{ 469{
470 int rc;
471 unsigned int size;
454 AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer; 472 AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer;
455 __u32 flags; 473 __u32 flags;
456 unsigned char *tmp; 474 unsigned char *tmp;
457 char ntlm_session_key[CIFS_SESS_KEY_SIZE]; 475 struct ntlmv2_resp ntlmv2_response = {};
458 476
459 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); 477 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
460 sec_blob->MessageType = NtLmAuthenticate; 478 sec_blob->MessageType = NtLmAuthenticate;
@@ -462,7 +480,7 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
462 flags = NTLMSSP_NEGOTIATE_56 | 480 flags = NTLMSSP_NEGOTIATE_56 |
463 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO | 481 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO |
464 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | 482 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
465 NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM; 483 NTLMSSP_NEGOTIATE_NTLM;
466 if (ses->server->secMode & 484 if (ses->server->secMode &
467 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) 485 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
468 flags |= NTLMSSP_NEGOTIATE_SIGN; 486 flags |= NTLMSSP_NEGOTIATE_SIGN;
@@ -477,19 +495,26 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
477 sec_blob->LmChallengeResponse.Length = 0; 495 sec_blob->LmChallengeResponse.Length = 0;
478 sec_blob->LmChallengeResponse.MaximumLength = 0; 496 sec_blob->LmChallengeResponse.MaximumLength = 0;
479 497
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); 498 sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer);
488 sec_blob->NtChallengeResponse.Length = cpu_to_le16(CIFS_SESS_KEY_SIZE); 499 rc = setup_ntlmv2_rsp(ses, (char *)&ntlmv2_response, nls_cp);
489 sec_blob->NtChallengeResponse.MaximumLength = 500 if (rc) {
490 cpu_to_le16(CIFS_SESS_KEY_SIZE); 501 cERROR(1, "Error %d during NTLMSSP authentication", rc);
502 goto setup_ntlmv2_ret;
503 }
504 size = sizeof(struct ntlmv2_resp);
505 memcpy(tmp, (char *)&ntlmv2_response, size);
506 tmp += size;
507 if (ses->tilen > 0) {
508 memcpy(tmp, ses->tiblob, ses->tilen);
509 tmp += ses->tilen;
510 }
491 511
492 tmp += CIFS_SESS_KEY_SIZE; 512 sec_blob->NtChallengeResponse.Length = cpu_to_le16(size + ses->tilen);
513 sec_blob->NtChallengeResponse.MaximumLength =
514 cpu_to_le16(size + ses->tilen);
515 kfree(ses->tiblob);
516 ses->tiblob = NULL;
517 ses->tilen = 0;
493 518
494 if (ses->domainName == NULL) { 519 if (ses->domainName == NULL) {
495 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); 520 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
@@ -501,7 +526,6 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
501 len = cifs_strtoUCS((__le16 *)tmp, ses->domainName, 526 len = cifs_strtoUCS((__le16 *)tmp, ses->domainName,
502 MAX_USERNAME_SIZE, nls_cp); 527 MAX_USERNAME_SIZE, nls_cp);
503 len *= 2; /* unicode is 2 bytes each */ 528 len *= 2; /* unicode is 2 bytes each */
504 len += 2; /* trailing null */
505 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); 529 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
506 sec_blob->DomainName.Length = cpu_to_le16(len); 530 sec_blob->DomainName.Length = cpu_to_le16(len);
507 sec_blob->DomainName.MaximumLength = cpu_to_le16(len); 531 sec_blob->DomainName.MaximumLength = cpu_to_le16(len);
@@ -518,7 +542,6 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
518 len = cifs_strtoUCS((__le16 *)tmp, ses->userName, 542 len = cifs_strtoUCS((__le16 *)tmp, ses->userName,
519 MAX_USERNAME_SIZE, nls_cp); 543 MAX_USERNAME_SIZE, nls_cp);
520 len *= 2; /* unicode is 2 bytes each */ 544 len *= 2; /* unicode is 2 bytes each */
521 len += 2; /* trailing null */
522 sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer); 545 sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
523 sec_blob->UserName.Length = cpu_to_le16(len); 546 sec_blob->UserName.Length = cpu_to_le16(len);
524 sec_blob->UserName.MaximumLength = cpu_to_le16(len); 547 sec_blob->UserName.MaximumLength = cpu_to_le16(len);
@@ -533,6 +556,8 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
533 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); 556 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer);
534 sec_blob->SessionKey.Length = 0; 557 sec_blob->SessionKey.Length = 0;
535 sec_blob->SessionKey.MaximumLength = 0; 558 sec_blob->SessionKey.MaximumLength = 0;
559
560setup_ntlmv2_ret:
536 return tmp - pbuffer; 561 return tmp - pbuffer;
537} 562}
538 563
@@ -545,19 +570,6 @@ static void setup_ntlmssp_neg_req(SESSION_SETUP_ANDX *pSMB,
545 570
546 return; 571 return;
547} 572}
548
549static int setup_ntlmssp_auth_req(SESSION_SETUP_ANDX *pSMB,
550 struct cifsSesInfo *ses,
551 const struct nls_table *nls, bool first_time)
552{
553 int bloblen;
554
555 bloblen = build_ntlmssp_auth_blob(&pSMB->req.SecurityBlob[0], ses, nls,
556 first_time);
557 pSMB->req.SecurityBlobLength = cpu_to_le16(bloblen);
558
559 return bloblen;
560}
561#endif 573#endif
562 574
563int 575int
@@ -580,6 +592,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
580 struct key *spnego_key = NULL; 592 struct key *spnego_key = NULL;
581 __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */ 593 __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */
582 bool first_time; 594 bool first_time;
595 int blob_len;
596 char *ntlmsspblob = NULL;
583 597
584 if (ses == NULL) 598 if (ses == NULL)
585 return -EINVAL; 599 return -EINVAL;
@@ -690,7 +704,7 @@ ssetup_ntlmssp_authenticate:
690 704
691 if (first_time) /* should this be moved into common code 705 if (first_time) /* should this be moved into common code
692 with similar ntlmv2 path? */ 706 with similar ntlmv2 path? */
693 cifs_calculate_mac_key(&ses->server->mac_signing_key, 707 cifs_calculate_session_key(&ses->server->session_key,
694 ntlm_session_key, ses->password); 708 ntlm_session_key, ses->password);
695 /* copy session key */ 709 /* copy session key */
696 710
@@ -725,16 +739,31 @@ ssetup_ntlmssp_authenticate:
725 pSMB->req_no_secext.CaseInsensitivePasswordLength = 0; 739 pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
726 /* cpu_to_le16(LM2_SESS_KEY_SIZE); */ 740 /* cpu_to_le16(LM2_SESS_KEY_SIZE); */
727 741
728 pSMB->req_no_secext.CaseSensitivePasswordLength =
729 cpu_to_le16(sizeof(struct ntlmv2_resp));
730
731 /* calculate session key */ 742 /* calculate session key */
732 setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp); 743 rc = setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
733 /* FIXME: calculate MAC key */ 744 if (rc) {
745 cERROR(1, "Error %d during NTLMv2 authentication", rc);
746 kfree(v2_sess_key);
747 goto ssetup_exit;
748 }
734 memcpy(bcc_ptr, (char *)v2_sess_key, 749 memcpy(bcc_ptr, (char *)v2_sess_key,
735 sizeof(struct ntlmv2_resp)); 750 sizeof(struct ntlmv2_resp));
736 bcc_ptr += sizeof(struct ntlmv2_resp); 751 bcc_ptr += sizeof(struct ntlmv2_resp);
737 kfree(v2_sess_key); 752 kfree(v2_sess_key);
753 /* set case sensitive password length after tilen may get
754 * assigned, tilen is 0 otherwise.
755 */
756 pSMB->req_no_secext.CaseSensitivePasswordLength =
757 cpu_to_le16(sizeof(struct ntlmv2_resp) + ses->tilen);
758 if (ses->tilen > 0) {
759 memcpy(bcc_ptr, ses->tiblob, ses->tilen);
760 bcc_ptr += ses->tilen;
761 /* we never did allocate ses->domainName to free */
762 kfree(ses->tiblob);
763 ses->tiblob = NULL;
764 ses->tilen = 0;
765 }
766
738 if (ses->capabilities & CAP_UNICODE) { 767 if (ses->capabilities & CAP_UNICODE) {
739 if (iov[0].iov_len % 2) { 768 if (iov[0].iov_len % 2) {
740 *bcc_ptr = 0; 769 *bcc_ptr = 0;
@@ -765,15 +794,15 @@ ssetup_ntlmssp_authenticate:
765 } 794 }
766 /* bail out if key is too long */ 795 /* bail out if key is too long */
767 if (msg->sesskey_len > 796 if (msg->sesskey_len >
768 sizeof(ses->server->mac_signing_key.data.krb5)) { 797 sizeof(ses->server->session_key.data.krb5)) {
769 cERROR(1, "Kerberos signing key too long (%u bytes)", 798 cERROR(1, "Kerberos signing key too long (%u bytes)",
770 msg->sesskey_len); 799 msg->sesskey_len);
771 rc = -EOVERFLOW; 800 rc = -EOVERFLOW;
772 goto ssetup_exit; 801 goto ssetup_exit;
773 } 802 }
774 if (first_time) { 803 if (first_time) {
775 ses->server->mac_signing_key.len = msg->sesskey_len; 804 ses->server->session_key.len = msg->sesskey_len;
776 memcpy(ses->server->mac_signing_key.data.krb5, 805 memcpy(ses->server->session_key.data.krb5,
777 msg->data, msg->sesskey_len); 806 msg->data, msg->sesskey_len);
778 } 807 }
779 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; 808 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
@@ -815,12 +844,28 @@ ssetup_ntlmssp_authenticate:
815 if (phase == NtLmNegotiate) { 844 if (phase == NtLmNegotiate) {
816 setup_ntlmssp_neg_req(pSMB, ses); 845 setup_ntlmssp_neg_req(pSMB, ses);
817 iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE); 846 iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE);
847 iov[1].iov_base = &pSMB->req.SecurityBlob[0];
818 } else if (phase == NtLmAuthenticate) { 848 } else if (phase == NtLmAuthenticate) {
819 int blob_len; 849 /* 5 is an empirical value, large enought to
820 blob_len = setup_ntlmssp_auth_req(pSMB, ses, 850 * hold authenticate message, max 10 of
821 nls_cp, 851 * av paris, doamin,user,workstation mames,
822 first_time); 852 * flags etc..
853 */
854 ntlmsspblob = kmalloc(
855 5*sizeof(struct _AUTHENTICATE_MESSAGE),
856 GFP_KERNEL);
857 if (!ntlmsspblob) {
858 cERROR(1, "Can't allocate NTLMSSP");
859 rc = -ENOMEM;
860 goto ssetup_exit;
861 }
862
863 blob_len = build_ntlmssp_auth_blob(ntlmsspblob,
864 ses, nls_cp);
823 iov[1].iov_len = blob_len; 865 iov[1].iov_len = blob_len;
866 iov[1].iov_base = ntlmsspblob;
867 pSMB->req.SecurityBlobLength =
868 cpu_to_le16(blob_len);
824 /* Make sure that we tell the server that we 869 /* Make sure that we tell the server that we
825 are using the uid that it just gave us back 870 are using the uid that it just gave us back
826 on the response (challenge) */ 871 on the response (challenge) */
@@ -830,7 +875,6 @@ ssetup_ntlmssp_authenticate:
830 rc = -ENOSYS; 875 rc = -ENOSYS;
831 goto ssetup_exit; 876 goto ssetup_exit;
832 } 877 }
833 iov[1].iov_base = &pSMB->req.SecurityBlob[0];
834 /* unicode strings must be word aligned */ 878 /* unicode strings must be word aligned */
835 if ((iov[0].iov_len + iov[1].iov_len) % 2) { 879 if ((iov[0].iov_len + iov[1].iov_len) % 2) {
836 *bcc_ptr = 0; 880 *bcc_ptr = 0;
@@ -931,6 +975,8 @@ ssetup_exit:
931 key_put(spnego_key); 975 key_put(spnego_key);
932 } 976 }
933 kfree(str_area); 977 kfree(str_area);
978 kfree(ntlmsspblob);
979 ntlmsspblob = NULL;
934 if (resp_buf_type == CIFS_SMALL_BUFFER) { 980 if (resp_buf_type == CIFS_SMALL_BUFFER) {
935 cFYI(1, "ssetup freeing small buf %p", iov[0].iov_base); 981 cFYI(1, "ssetup freeing small buf %p", iov[0].iov_base);
936 cifs_small_buf_release(iov[0].iov_base); 982 cifs_small_buf_release(iov[0].iov_base);