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. -- 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