On Tue, 7 Sep 2010 07:38:45 -0500 Shirish Pargaonkar <shirishpargaonkar@xxxxxxxxx> wrote: > On Tue, Sep 7, 2010 at 7:35 AM, Jeff Layton <jlayton@xxxxxxxxx> wrote: > > On Mon, 6 Sep 2010 22:35:23 -0500 > > shirishpargaonkar@xxxxxxxxx wrote: > > > >> From: Shirish Pargaonkar <shirishpargaonkar@xxxxxxxxx> > >> > >> Signed-off-by: Shirish Pargaonkar <shirishpargaonkar@xxxxxxxxx> > >> --- > >> fs/cifs/cifsencrypt.c | 33 ++++++++++++-------- > >> fs/cifs/cifsglob.h | 2 +- > >> fs/cifs/cifsproto.h | 2 +- > >> fs/cifs/sess.c | 80 +++++++++++++++++++++++++++++++++--------------- > >> fs/cifs/transport.c | 6 ++-- > >> 5 files changed, 80 insertions(+), 43 deletions(-) > >> > >> diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c > >> index 5f0fc6b..5fbd19b 100644 > >> --- a/fs/cifs/cifsencrypt.c > >> +++ b/fs/cifs/cifsencrypt.c > >> @@ -80,7 +80,7 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, > >> server->sequence_number++; > >> spin_unlock(&GlobalMid_Lock); > >> > >> - rc = cifs_calculate_signature(cifs_pdu, &server->mac_signing_key, > >> + rc = cifs_calculate_signature(cifs_pdu, &server->session_key, > >> smb_signature); > >> if (rc) > >> memset(cifs_pdu->Signature.SecuritySignature, 0, 8); > >> @@ -147,7 +147,7 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, > >> server->sequence_number++; > >> spin_unlock(&GlobalMid_Lock); > >> > >> - rc = cifs_calc_signature2(iov, n_vec, &server->mac_signing_key, > >> + rc = cifs_calc_signature2(iov, n_vec, &server->session_key, > >> smb_signature); > >> if (rc) > >> memset(cifs_pdu->Signature.SecuritySignature, 0, 8); > >> @@ -211,7 +211,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu, > >> } > >> > >> /* We fill in key by putting in 40 byte array which was allocated by caller */ > >> -int cifs_calculate_mac_key(struct session_key *key, const char *rn, > >> +int cifs_calculate_session_key(struct session_key *key, const char *rn, > >> const char *password) > >> { > >> char temp_key[16]; > >> @@ -319,7 +319,7 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses, > >> { > >> int rc = 0; > >> int len; > >> - char nt_hash[16]; > >> + char nt_hash[CIFS_NTHASH_SIZE]; > >> struct HMACMD5Context *pctxt; > >> wchar_t *user; > >> wchar_t *domain; > >> @@ -377,7 +377,7 @@ int > >> setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf, > >> const struct nls_table *nls_cp) > >> { > >> - int rc; > >> + int rc = 0; > >> struct ntlmv2_resp *buf = (struct ntlmv2_resp *)resp_buf; > >> struct HMACMD5Context context; > >> > >> @@ -404,11 +404,11 @@ setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf, > >> /* now calculate the MAC key for NTLMv2 */ > >> hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context); > >> hmac_md5_update(resp_buf, 16, &context); > >> - hmac_md5_final(ses->server->mac_signing_key.data.ntlmv2.key, &context); > >> + hmac_md5_final(ses->server->session_key.data.ntlmv2.key, &context); > >> > >> - memcpy(&ses->server->mac_signing_key.data.ntlmv2.resp, resp_buf, > >> + memcpy(&ses->server->session_key.data.ntlmv2.resp, resp_buf, > >> sizeof(struct ntlmv2_resp)); > >> - ses->server->mac_signing_key.len = 16 + sizeof(struct ntlmv2_resp); > >> + ses->server->session_key.len = 16 + sizeof(struct ntlmv2_resp); > >> > >> return rc; > >> } > >> @@ -418,11 +418,18 @@ void CalcNTLMv2_response(const struct cifsSesInfo *ses, > >> { > >> struct HMACMD5Context context; > >> /* rest of v2 struct already generated */ > >> - memcpy(v2_session_response + 8, ses->server->cryptKey, 8); > >> - hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context); > >> - > >> - hmac_md5_update(v2_session_response+8, > >> - sizeof(struct ntlmv2_resp) - 8, &context); > >> + memcpy(v2_session_response + CIFS_SERVER_CHALLENGE_SIZE, > >> + ses->server->cryptKey, CIFS_SERVER_CHALLENGE_SIZE); > >> + hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, > >> + CIFS_HMAC_MD5_HASH_SIZE, &context); > >> + > >> + hmac_md5_update(v2_session_response + CIFS_SERVER_CHALLENGE_SIZE, > >> + sizeof(struct ntlmv2_resp) - CIFS_SERVER_CHALLENGE_SIZE, > >> + &context); > >> + > >> + if (ses->server->tilen) > >> + hmac_md5_update(ses->server->tiblob, > >> + ses->server->tilen, &context); > >> > >> hmac_md5_final(v2_session_response, &context); > >> /* cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */ > >> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h > >> index 6b7249e..f67a5d7 100644 > >> --- a/fs/cifs/cifsglob.h > >> +++ b/fs/cifs/cifsglob.h > >> @@ -201,7 +201,7 @@ struct TCP_Server_Info { > >> /* 16th byte of RFC1001 workstation name is always null */ > >> char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; > >> __u32 sequence_number; /* needed for CIFS PDU signature */ > >> - struct session_key mac_signing_key; > >> + struct session_key session_key; > >> char ntlmv2_hash[16]; > >> unsigned long lstrp; /* when we got last response from this server */ > >> u16 dialect; /* dialect index that server chose */ > >> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h > >> index ccc6d57..d1b9bc4 100644 > >> --- a/fs/cifs/cifsproto.h > >> +++ b/fs/cifs/cifsproto.h > >> @@ -363,7 +363,7 @@ extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *, > >> extern int cifs_verify_signature(struct smb_hdr *, > >> const struct session_key *session_key, > >> __u32 expected_sequence_number); > >> -extern int cifs_calculate_mac_key(struct session_key *key, const char *rn, > >> +extern int cifs_calculate_session_key(struct session_key *key, const char *rn, > >> const char *pass); > >> extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, > >> const struct nls_table *); > >> diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c > >> index 6551b17..f7fc3dc 100644 > >> --- a/fs/cifs/sess.c > >> +++ b/fs/cifs/sess.c > >> @@ -442,7 +442,7 @@ static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, > >> /* BB is NTLMV2 session security format easier to use here? */ > >> flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET | > >> NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | > >> - NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM; > >> + NTLMSSP_NEGOTIATE_NTLM; > >> if (ses->server->secMode & > >> (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) > >> flags |= NTLMSSP_NEGOTIATE_SIGN; > >> @@ -468,10 +468,12 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, > >> struct cifsSesInfo *ses, > >> const struct nls_table *nls_cp, bool first) > >> { > >> + int rc; > >> + unsigned int size; > >> AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer; > >> __u32 flags; > >> unsigned char *tmp; > >> - char ntlm_session_key[CIFS_SESS_KEY_SIZE]; > >> + struct ntlmv2_resp ntlmv2_response = {}; > >> > >> memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); > >> sec_blob->MessageType = NtLmAuthenticate; > >> @@ -479,7 +481,7 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, > >> flags = NTLMSSP_NEGOTIATE_56 | > >> NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO | > >> NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | > >> - NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM; > >> + NTLMSSP_NEGOTIATE_NTLM; > >> if (ses->server->secMode & > >> (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) > >> flags |= NTLMSSP_NEGOTIATE_SIGN; > >> @@ -494,19 +496,25 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, > >> sec_blob->LmChallengeResponse.Length = 0; > >> sec_blob->LmChallengeResponse.MaximumLength = 0; > >> > >> - /* calculate session key, BB what about adding similar ntlmv2 path? */ > >> - SMBNTencrypt(ses->password, ses->server->cryptKey, ntlm_session_key); > >> - if (first) > >> - cifs_calculate_mac_key(&ses->server->mac_signing_key, > >> - ntlm_session_key, ses->password); > >> - > >> - memcpy(tmp, ntlm_session_key, CIFS_SESS_KEY_SIZE); > >> sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer); > >> - sec_blob->NtChallengeResponse.Length = cpu_to_le16(CIFS_SESS_KEY_SIZE); > >> - sec_blob->NtChallengeResponse.MaximumLength = > >> - cpu_to_le16(CIFS_SESS_KEY_SIZE); > >> + rc = setup_ntlmv2_rsp(ses, (char *)&ntlmv2_response, nls_cp); > >> + if (rc) { > >> + cERROR(1, "error rc: %d during ntlmssp ntlmv2 setup", rc); > >> + goto setup_ntlmv2_ret; > >> + } > >> + size = sizeof(struct ntlmv2_resp); > >> + memcpy(tmp, (char *)&ntlmv2_response, size); > >> + tmp += size; > >> + if (ses->server->tilen > 0) { > >> + memcpy(tmp, ses->server->tiblob, ses->server->tilen); > >> + tmp += ses->server->tilen; > >> + } else > >> + ses->server->tilen = 0; > >> > >> - tmp += CIFS_SESS_KEY_SIZE; > >> + sec_blob->NtChallengeResponse.Length = cpu_to_le16(size + > >> + ses->server->tilen); > >> + sec_blob->NtChallengeResponse.MaximumLength = > >> + cpu_to_le16(size + ses->server->tilen); > >> > >> if (ses->domainName == NULL) { > >> sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); > >> @@ -518,7 +526,6 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, > >> len = cifs_strtoUCS((__le16 *)tmp, ses->domainName, > >> MAX_USERNAME_SIZE, nls_cp); > >> len *= 2; /* unicode is 2 bytes each */ > >> - len += 2; /* trailing null */ > >> sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); > >> sec_blob->DomainName.Length = cpu_to_le16(len); > >> sec_blob->DomainName.MaximumLength = cpu_to_le16(len); > >> @@ -535,7 +542,6 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, > >> len = cifs_strtoUCS((__le16 *)tmp, ses->userName, > >> MAX_USERNAME_SIZE, nls_cp); > >> len *= 2; /* unicode is 2 bytes each */ > >> - len += 2; /* trailing null */ > >> sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer); > >> sec_blob->UserName.Length = cpu_to_le16(len); > >> sec_blob->UserName.MaximumLength = cpu_to_le16(len); > >> @@ -551,6 +557,7 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, > >> sec_blob->SessionKey.Length = 0; > >> sec_blob->SessionKey.MaximumLength = 0; > >> > >> +setup_ntlmv2_ret: > >> if (ses->server->tilen > 0) > >> kfree(ses->server->tiblob); > >> > >> @@ -567,15 +574,14 @@ static void setup_ntlmssp_neg_req(SESSION_SETUP_ANDX *pSMB, > >> return; > >> } > >> > >> -static int setup_ntlmssp_auth_req(SESSION_SETUP_ANDX *pSMB, > >> +static int setup_ntlmssp_auth_req(char *ntlmsspblob, > >> struct cifsSesInfo *ses, > >> const struct nls_table *nls, bool first_time) > >> { > >> int bloblen; > >> > >> - bloblen = build_ntlmssp_auth_blob(&pSMB->req.SecurityBlob[0], ses, nls, > >> + bloblen = build_ntlmssp_auth_blob(ntlmsspblob, ses, nls, > >> first_time); > >> - pSMB->req.SecurityBlobLength = cpu_to_le16(bloblen); > >> > >> return bloblen; > >> } > >> @@ -711,7 +717,7 @@ ssetup_ntlmssp_authenticate: > >> > >> if (first_time) /* should this be moved into common code > >> with similar ntlmv2 path? */ > >> - cifs_calculate_mac_key(&ses->server->mac_signing_key, > >> + cifs_calculate_session_key(&ses->server->session_key, > >> ntlm_session_key, ses->password); > >> /* copy session key */ > >> > >> @@ -751,10 +757,19 @@ ssetup_ntlmssp_authenticate: > >> > >> /* calculate session key */ > >> rc = setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp); > >> + if (rc) { > >> + kfree(v2_sess_key); > >> + goto ssetup_exit; > >> + } > >> memcpy(bcc_ptr, (char *)v2_sess_key, > >> sizeof(struct ntlmv2_resp)); > >> bcc_ptr += sizeof(struct ntlmv2_resp); > >> kfree(v2_sess_key); > >> + if (ses->server->tilen > 0) { > >> + memcpy(bcc_ptr, ses->server->tiblob, > >> + ses->server->tilen); > >> + bcc_ptr += ses->server->tilen; > >> + } > >> if (ses->capabilities & CAP_UNICODE) { > >> if (iov[0].iov_len % 2) { > >> *bcc_ptr = 0; > >> @@ -785,15 +800,15 @@ ssetup_ntlmssp_authenticate: > >> } > >> /* bail out if key is too long */ > >> if (msg->sesskey_len > > >> - sizeof(ses->server->mac_signing_key.data.krb5)) { > >> + sizeof(ses->server->session_key.data.krb5)) { > >> cERROR(1, "Kerberos signing key too long (%u bytes)", > >> msg->sesskey_len); > >> rc = -EOVERFLOW; > >> goto ssetup_exit; > >> } > >> if (first_time) { > >> - ses->server->mac_signing_key.len = msg->sesskey_len; > >> - memcpy(ses->server->mac_signing_key.data.krb5, > >> + ses->server->session_key.len = msg->sesskey_len; > >> + memcpy(ses->server->session_key.data.krb5, > >> msg->data, msg->sesskey_len); > >> } > >> pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; > >> @@ -835,12 +850,28 @@ ssetup_ntlmssp_authenticate: > >> if (phase == NtLmNegotiate) { > >> setup_ntlmssp_neg_req(pSMB, ses); > >> iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE); > >> + iov[1].iov_base = &pSMB->req.SecurityBlob[0]; > >> } else if (phase == NtLmAuthenticate) { > >> int blob_len; > >> - blob_len = setup_ntlmssp_auth_req(pSMB, ses, > >> + char *ntlmsspblob; > >> + > >> + ntlmsspblob = kmalloc(5 * > > ^^^^^^^^^^ > > Why 5 here? > > > >> + sizeof(struct _AUTHENTICATE_MESSAGE), > >> + GFP_KERNEL); > >> + if (!ntlmsspblob) { > >> + cERROR(1, "Can't allocate NTLMSSP"); > >> + rc = -ENOMEM; > >> + goto ssetup_exit; > >> + } > >> + > >> + blob_len = setup_ntlmssp_auth_req(ntlmsspblob, > >> + ses, > >> nls_cp, > >> first_time); > >> iov[1].iov_len = blob_len; > >> + iov[1].iov_base = ntlmsspblob; > >> + pSMB->req.SecurityBlobLength = > >> + cpu_to_le16(blob_len); > >> /* Make sure that we tell the server that we > >> are using the uid that it just gave us back > >> on the response (challenge) */ > >> @@ -850,7 +881,6 @@ ssetup_ntlmssp_authenticate: > >> rc = -ENOSYS; > >> goto ssetup_exit; > >> } > >> - iov[1].iov_base = &pSMB->req.SecurityBlob[0]; > >> /* unicode strings must be word aligned */ > >> if ((iov[0].iov_len + iov[1].iov_len) % 2) { > >> *bcc_ptr = 0; > >> diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c > >> index 82f78c4..a66c91e 100644 > >> --- a/fs/cifs/transport.c > >> +++ b/fs/cifs/transport.c > >> @@ -543,7 +543,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, > >> (ses->server->secMode & (SECMODE_SIGN_REQUIRED | > >> SECMODE_SIGN_ENABLED))) { > >> rc = cifs_verify_signature(midQ->resp_buf, > >> - &ses->server->mac_signing_key, > >> + &ses->server->session_key, > >> midQ->sequence_number+1); > >> if (rc) { > >> cERROR(1, "Unexpected SMB signature"); > >> @@ -731,7 +731,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, > >> (ses->server->secMode & (SECMODE_SIGN_REQUIRED | > >> SECMODE_SIGN_ENABLED))) { > >> rc = cifs_verify_signature(out_buf, > >> - &ses->server->mac_signing_key, > >> + &ses->server->session_key, > >> midQ->sequence_number+1); > >> if (rc) { > >> cERROR(1, "Unexpected SMB signature"); > >> @@ -981,7 +981,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, > >> (ses->server->secMode & (SECMODE_SIGN_REQUIRED | > >> SECMODE_SIGN_ENABLED))) { > >> rc = cifs_verify_signature(out_buf, > >> - &ses->server->mac_signing_key, > >> + &ses->server->session_key, > >> midQ->sequence_number+1); > >> if (rc) { > >> cERROR(1, "Unexpected SMB signature"); > > > > > > -- > > Jeff Layton <jlayton@xxxxxxxxx> > > > > An empirical value, that is good enough to hold even if we had all 10 fields > in AV pairs/Target Info. Even if we decide to include LM2 key (for > whatever reason > like passthrough authentication, if at all), that size would be good enough. > That deserves a comment in the code. -- Jeff Layton <jlayton@xxxxxxxxx> -- To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html