diff options
author | Shirish Pargaonkar <shirishpargaonkar@gmail.com> | 2010-10-21 07:42:55 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2010-10-26 14:20:10 -0400 |
commit | 21e733930be6458e0c33482b6783e7c15ba984eb (patch) | |
tree | 1458ccf45529649267451a7e06fcd25d9c7ab0ac /fs/cifs/sess.c | |
parent | 6573e9b73e19c0f6b9dfa2b399267ea0f42d6c6b (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/sess.c')
-rw-r--r-- | fs/cifs/sess.c | 107 |
1 files changed, 39 insertions, 68 deletions
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 | ||
35 | extern 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 | ||