cifs: Cleanup and thus reduce smb session structure and fields used during authentication
Removed following fields from smb session structure cryptkey, ntlmv2_hash, tilen, tiblob and ntlmssp_auth structure is allocated dynamically only if the auth mech in NTLMSSP. response field within a session_key structure is used to initially store the target info (either plucked from type 2 challenge packet in case of NTLMSSP or fabricated in case of NTLMv2 without extended security) and then to store Message Authentication Key (mak) (session key + client response). Server challenge or cryptkey needed during a NTLMSSP authentication is now part of ntlmssp_auth structure which gets allocated and freed once authenticaiton process is done. Signed-off-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
This commit is contained in:
parent
d3ba50b17a
commit
d3686d54c7
|
@ -328,15 +328,15 @@ build_avpair_blob(struct cifsSesInfo *ses, const struct nls_table *nls_cp)
|
|||
* two times the unicode length of a server name +
|
||||
* size of a timestamp (which is 8 bytes).
|
||||
*/
|
||||
ses->tilen = size + 2 * (2 * dlen) + 2 * (2 * wlen) + 8;
|
||||
ses->tiblob = kzalloc(ses->tilen, GFP_KERNEL);
|
||||
if (!ses->tiblob) {
|
||||
ses->tilen = 0;
|
||||
ses->auth_key.len = size + 2 * (2 * dlen) + 2 * (2 * wlen) + 8;
|
||||
ses->auth_key.response = kzalloc(ses->auth_key.len, GFP_KERNEL);
|
||||
if (!ses->auth_key.response) {
|
||||
ses->auth_key.len = 0;
|
||||
cERROR(1, "Challenge target info allocation failure");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
blobptr = ses->tiblob;
|
||||
blobptr = ses->auth_key.response;
|
||||
attrptr = (struct ntlmssp2_name *) blobptr;
|
||||
|
||||
attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_DOMAIN_NAME);
|
||||
|
@ -400,11 +400,11 @@ find_domain_name(struct cifsSesInfo *ses, const struct nls_table *nls_cp)
|
|||
unsigned char *blobend;
|
||||
struct ntlmssp2_name *attrptr;
|
||||
|
||||
if (!ses->tilen || !ses->tiblob)
|
||||
if (!ses->auth_key.len || !ses->auth_key.response)
|
||||
return 0;
|
||||
|
||||
blobptr = ses->tiblob;
|
||||
blobend = ses->tiblob + ses->tilen;
|
||||
blobptr = ses->auth_key.response;
|
||||
blobend = blobptr + ses->auth_key.len;
|
||||
|
||||
while (blobptr + onesize < blobend) {
|
||||
attrptr = (struct ntlmssp2_name *) blobptr;
|
||||
|
@ -436,7 +436,7 @@ find_domain_name(struct cifsSesInfo *ses, const struct nls_table *nls_cp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
|
||||
static int calc_ntlmv2_hash(struct cifsSesInfo *ses, char *ntlmv2_hash,
|
||||
const struct nls_table *nls_cp)
|
||||
{
|
||||
int rc = 0;
|
||||
|
@ -509,7 +509,7 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
|
|||
}
|
||||
|
||||
rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
|
||||
ses->ntlmv2_hash);
|
||||
ntlmv2_hash);
|
||||
|
||||
calc_exit_1:
|
||||
kfree(user);
|
||||
|
@ -518,7 +518,7 @@ calc_exit_2:
|
|||
}
|
||||
|
||||
static int
|
||||
CalcNTLMv2_response(const struct cifsSesInfo *ses)
|
||||
CalcNTLMv2_response(const struct cifsSesInfo *ses, char *ntlmv2_hash)
|
||||
{
|
||||
int rc;
|
||||
unsigned int offset = CIFS_SESS_KEY_SIZE + 8;
|
||||
|
@ -529,7 +529,7 @@ CalcNTLMv2_response(const struct cifsSesInfo *ses)
|
|||
}
|
||||
|
||||
crypto_shash_setkey(ses->server->secmech.hmacmd5,
|
||||
ses->ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
|
||||
ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
|
||||
|
||||
rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
|
||||
if (rc) {
|
||||
|
@ -539,7 +539,7 @@ CalcNTLMv2_response(const struct cifsSesInfo *ses)
|
|||
|
||||
if (ses->server->secType == RawNTLMSSP)
|
||||
memcpy(ses->auth_key.response + offset,
|
||||
ses->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
|
||||
ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
|
||||
else
|
||||
memcpy(ses->auth_key.response + offset,
|
||||
ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
|
||||
|
@ -558,7 +558,10 @@ setup_ntlmv2_rsp(struct cifsSesInfo *ses, const struct nls_table *nls_cp)
|
|||
{
|
||||
int rc;
|
||||
int baselen;
|
||||
unsigned int tilen;
|
||||
struct ntlmv2_resp *buf;
|
||||
char ntlmv2_hash[16];
|
||||
unsigned char *tiblob = NULL; /* target info blob */
|
||||
|
||||
if (ses->server->secType == RawNTLMSSP) {
|
||||
if (!ses->domainName) {
|
||||
|
@ -572,18 +575,22 @@ setup_ntlmv2_rsp(struct cifsSesInfo *ses, const struct nls_table *nls_cp)
|
|||
rc = build_avpair_blob(ses, nls_cp);
|
||||
if (rc) {
|
||||
cERROR(1, "error %d building av pair blob", rc);
|
||||
return rc;
|
||||
goto setup_ntlmv2_rsp_ret;
|
||||
}
|
||||
}
|
||||
|
||||
baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp);
|
||||
ses->auth_key.len = baselen + ses->tilen;
|
||||
ses->auth_key.response = kmalloc(ses->auth_key.len, GFP_KERNEL);
|
||||
tilen = ses->auth_key.len;
|
||||
tiblob = ses->auth_key.response;
|
||||
|
||||
ses->auth_key.response = kmalloc(baselen + tilen, GFP_KERNEL);
|
||||
if (!ses->auth_key.response) {
|
||||
rc = ENOMEM;
|
||||
ses->auth_key.len = 0;
|
||||
cERROR(1, "%s: Can't allocate auth blob", __func__);
|
||||
goto setup_ntlmv2_rsp_ret;
|
||||
}
|
||||
ses->auth_key.len += baselen;
|
||||
|
||||
buf = (struct ntlmv2_resp *)
|
||||
(ses->auth_key.response + CIFS_SESS_KEY_SIZE);
|
||||
|
@ -593,17 +600,17 @@ setup_ntlmv2_rsp(struct cifsSesInfo *ses, const struct nls_table *nls_cp)
|
|||
get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));
|
||||
buf->reserved2 = 0;
|
||||
|
||||
memcpy(ses->auth_key.response + baselen, ses->tiblob, ses->tilen);
|
||||
memcpy(ses->auth_key.response + baselen, tiblob, tilen);
|
||||
|
||||
/* calculate ntlmv2_hash */
|
||||
rc = calc_ntlmv2_hash(ses, nls_cp);
|
||||
rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp);
|
||||
if (rc) {
|
||||
cERROR(1, "could not get v2 hash rc %d", rc);
|
||||
goto setup_ntlmv2_rsp_ret;
|
||||
}
|
||||
|
||||
/* calculate first part of the client response (CR1) */
|
||||
rc = CalcNTLMv2_response(ses);
|
||||
rc = CalcNTLMv2_response(ses, ntlmv2_hash);
|
||||
if (rc) {
|
||||
cERROR(1, "Could not calculate CR1 rc: %d", rc);
|
||||
goto setup_ntlmv2_rsp_ret;
|
||||
|
@ -611,7 +618,7 @@ setup_ntlmv2_rsp(struct cifsSesInfo *ses, const struct nls_table *nls_cp)
|
|||
|
||||
/* now calculate the session key for NTLMv2 */
|
||||
crypto_shash_setkey(ses->server->secmech.hmacmd5,
|
||||
ses->ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
|
||||
ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
|
||||
|
||||
rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
|
||||
if (rc) {
|
||||
|
@ -627,9 +634,7 @@ setup_ntlmv2_rsp(struct cifsSesInfo *ses, const struct nls_table *nls_cp)
|
|||
ses->auth_key.response);
|
||||
|
||||
setup_ntlmv2_rsp_ret:
|
||||
kfree(ses->tiblob);
|
||||
ses->tiblob = NULL;
|
||||
ses->tilen = 0;
|
||||
kfree(tiblob);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -657,7 +662,7 @@ calc_seckey(struct cifsSesInfo *ses)
|
|||
CIFS_SESS_KEY_SIZE);
|
||||
|
||||
sg_init_one(&sgin, sec_key, CIFS_SESS_KEY_SIZE);
|
||||
sg_init_one(&sgout, ses->ntlmssp.ciphertext, CIFS_CPHTXT_SIZE);
|
||||
sg_init_one(&sgout, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE);
|
||||
|
||||
rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, CIFS_CPHTXT_SIZE);
|
||||
if (rc) {
|
||||
|
|
|
@ -119,11 +119,12 @@ struct cifs_secmech {
|
|||
struct sdesc *sdescmd5; /* ctxt to generate cifs/smb signature */
|
||||
};
|
||||
|
||||
/* per smb connection structure/fields */
|
||||
/* per smb session structure/fields */
|
||||
struct ntlmssp_auth {
|
||||
__u32 client_flags; /* sent by client in type 1 ntlmsssp exchange */
|
||||
__u32 server_flags; /* sent by server in type 2 ntlmssp exchange */
|
||||
unsigned char ciphertext[CIFS_CPHTXT_SIZE]; /* sent to server */
|
||||
char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlmssp */
|
||||
};
|
||||
|
||||
struct cifs_cred {
|
||||
|
@ -241,12 +242,8 @@ struct cifsSesInfo {
|
|||
char userName[MAX_USERNAME_SIZE + 1];
|
||||
char *domainName;
|
||||
char *password;
|
||||
char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlmssp */
|
||||
struct session_key auth_key;
|
||||
char ntlmv2_hash[16];
|
||||
unsigned int tilen; /* length of the target info blob */
|
||||
unsigned char *tiblob; /* target info blob in challenge response */
|
||||
struct ntlmssp_auth ntlmssp; /* ciphertext, flags */
|
||||
struct ntlmssp_auth *ntlmssp; /* ciphertext, flags, server challenge */
|
||||
bool need_reconnect:1; /* connection reset, uid now invalid */
|
||||
};
|
||||
/* no more than one of the following three session flags may be set */
|
||||
|
|
|
@ -1818,8 +1818,6 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
|
|||
if (ses == NULL)
|
||||
goto get_ses_fail;
|
||||
|
||||
ses->tilen = 0;
|
||||
ses->tiblob = NULL;
|
||||
/* new SMB session uses our server ref */
|
||||
ses->server = server;
|
||||
if (server->addr.sockAddr6.sin6_family == AF_INET6)
|
||||
|
@ -1840,10 +1838,9 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
|
|||
goto get_ses_fail;
|
||||
}
|
||||
if (volume_info->domainname) {
|
||||
int len = strlen(volume_info->domainname);
|
||||
ses->domainName = kmalloc(len + 1, GFP_KERNEL);
|
||||
if (ses->domainName)
|
||||
strcpy(ses->domainName, volume_info->domainname);
|
||||
ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
|
||||
if (!ses->domainName)
|
||||
goto get_ses_fail;
|
||||
}
|
||||
ses->cred_uid = volume_info->cred_uid;
|
||||
ses->linux_uid = volume_info->linux_uid;
|
||||
|
@ -3213,6 +3210,8 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *ses,
|
|||
kfree(ses->auth_key.response);
|
||||
ses->auth_key.response = NULL;
|
||||
ses->auth_key.len = 0;
|
||||
kfree(ses->ntlmssp);
|
||||
ses->ntlmssp = NULL;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -399,23 +399,22 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
memcpy(ses->cryptkey, pblob->Challenge, CIFS_CRYPTO_KEY_SIZE);
|
||||
memcpy(ses->ntlmssp->cryptkey, pblob->Challenge, CIFS_CRYPTO_KEY_SIZE);
|
||||
/* BB we could decode pblob->NegotiateFlags; some may be useful */
|
||||
/* In particular we can examine sign flags */
|
||||
/* BB spec says that if AvId field of MsvAvTimestamp is populated then
|
||||
we must set the MIC field of the AUTHENTICATE_MESSAGE */
|
||||
ses->ntlmssp.server_flags = le32_to_cpu(pblob->NegotiateFlags);
|
||||
ses->ntlmssp->server_flags = le32_to_cpu(pblob->NegotiateFlags);
|
||||
tioffset = cpu_to_le16(pblob->TargetInfoArray.BufferOffset);
|
||||
tilen = cpu_to_le16(pblob->TargetInfoArray.Length);
|
||||
ses->tilen = tilen;
|
||||
if (ses->tilen) {
|
||||
ses->tiblob = kmalloc(tilen, GFP_KERNEL);
|
||||
if (!ses->tiblob) {
|
||||
if (tilen) {
|
||||
ses->auth_key.response = kmalloc(tilen, GFP_KERNEL);
|
||||
if (!ses->auth_key.response) {
|
||||
cERROR(1, "Challenge target info allocation failure");
|
||||
ses->tilen = 0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
memcpy(ses->tiblob, bcc_ptr + tioffset, ses->tilen);
|
||||
memcpy(ses->auth_key.response, bcc_ptr + tioffset, tilen);
|
||||
ses->auth_key.len = tilen;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -545,9 +544,9 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
|
|||
sec_blob->WorkstationName.MaximumLength = 0;
|
||||
tmp += 2;
|
||||
|
||||
if ((ses->ntlmssp.server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) &&
|
||||
if ((ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) &&
|
||||
!calc_seckey(ses)) {
|
||||
memcpy(tmp, ses->ntlmssp.ciphertext, CIFS_CPHTXT_SIZE);
|
||||
memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE);
|
||||
sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer);
|
||||
sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE);
|
||||
sec_blob->SessionKey.MaximumLength =
|
||||
|
@ -601,8 +600,16 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||
return -EINVAL;
|
||||
|
||||
type = ses->server->secType;
|
||||
|
||||
cFYI(1, "sess setup type %d", type);
|
||||
if (type == RawNTLMSSP) {
|
||||
/* if memory allocation is successful, caller of this function
|
||||
* frees it.
|
||||
*/
|
||||
ses->ntlmssp = kmalloc(sizeof(struct ntlmssp_auth), GFP_KERNEL);
|
||||
if (!ses->ntlmssp)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ssetup_ntlmssp_authenticate:
|
||||
if (phase == NtLmChallenge)
|
||||
phase = NtLmAuthenticate; /* if ntlmssp, now final phase */
|
||||
|
|
Loading…
Reference in New Issue