[CIFS] NTLMv2 support part 5

NTLMv2 authentication (stronger authentication than default NTLM) which
many servers support now works.  There was a problem with the construction
of the security blob in the older code.  Currently requires
	/proc/fs/cifs/Experimental to be set to 2
and
	/proc/fs/cifs/SecurityFlags to be set to 0x4004 (to require using
	NTLMv2 instead of default of NTLM)

Next we will check signing to make sure optional NTLMv2 packet signing also
works.

Signed-off-by: Steve French <sfrench@us.ibm.com>
This commit is contained in:
Steve French 2006-06-08 05:41:32 +00:00
parent f3ffb68144
commit 1717ffc588
4 changed files with 50 additions and 24 deletions

View File

@ -5,7 +5,9 @@ session setup needed for OS/2 and older servers such as Windows 95 and 98.
Fix oops on ls to OS/2 servers. Add support for level 1 FindFirst
so we can do search (ls etc.) to OS/2. Do not send NTCreateX
or recent levels of FindFirst unless server says it supports NT SMBs
(instead use legacy equivalents from LANMAN dialect).
(instead use legacy equivalents from LANMAN dialect). Fix to allow
NTLMv2 authentication support (now can use stronger password hashing
on mount if corresponding /proc/fs/cifs/SecurityFlags is set (0x4004)
Version 1.43
------------

View File

@ -212,7 +212,8 @@ int cifs_calculate_mac_key(char * key, const char * rn, const char * password)
return 0;
}
int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_info)
int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses,
const struct nls_table * nls_info)
{
char temp_hash[16];
struct HMACMD5Context ctx;
@ -305,13 +306,15 @@ void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key)
}
#endif /* CIFS_WEAK_PW_HASH */
static int calc_ntlmv2_hash(const struct cifsSesInfo *ses,
char * ntv2_hash)
static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
const struct nls_table * nls_cp)
{
int rc = 0;
int len;
char nt_hash[16];
struct HMACMD5Context * pctxt;
wchar_t * user;
wchar_t * domain;
pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL);
@ -321,26 +324,44 @@ static int calc_ntlmv2_hash(const struct cifsSesInfo *ses,
/* calculate md4 hash of password */
E_md4hash(ses->password, nt_hash);
/* convERT Domainname to unicode and uppercase */
/* convert Domainname to unicode and uppercase */
hmac_md5_init_limK_to_64(nt_hash, 16, pctxt);
/* convert ses->userName to unicode and uppercase */
/* len = ... */ /* BB FIXME BB */
/* hmac_md5_update(user, len, pctxt); */
len = strlen(ses->userName);
user = kmalloc(2 + (len * 2), GFP_KERNEL);
if(user == NULL)
goto calc_exit_2;
len = cifs_strtoUCS(user, ses->userName, len, nls_cp);
UniStrupr(user);
hmac_md5_update((char *)user, 2*len, pctxt);
/* convert ses->domainName to unicode and uppercase */
if(ses->domainName) {
len = strlen(ses->domainName);
/* len = ... */ /* BB FIXME BB */
/* hmac_md5_update(domain, len, pctxt); */
domain = kmalloc(2 + (len * 2), GFP_KERNEL);
if(domain == NULL)
goto calc_exit_1;
len = cifs_strtoUCS(domain, ses->domainName, len, nls_cp);
UniStrupr(domain);
hmac_md5_final(ntv2_hash, pctxt);
hmac_md5_update((char *)domain, 2*len, pctxt);
kfree(domain);
}
calc_exit_1:
kfree(user);
calc_exit_2:
/* BB FIXME what about bytes 24 through 40 of the signing key?
compare with the NTLM example */
hmac_md5_final(ses->server->mac_signing_key, pctxt);
return rc;
}
void setup_ntlmv2_rsp(const struct cifsSesInfo * ses, char * resp_buf)
void setup_ntlmv2_rsp(struct cifsSesInfo * ses, char * resp_buf,
const struct nls_table * nls_cp)
{
int rc;
struct ntlmv2_resp * buf = (struct ntlmv2_resp *)resp_buf;
@ -348,27 +369,28 @@ void setup_ntlmv2_rsp(const struct cifsSesInfo * ses, char * resp_buf)
buf->blob_signature = cpu_to_le32(0x00000101);
buf->reserved = 0;
buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));
get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));
buf->reserved2 = 0;
buf->names[0].type = 0;
buf->names[0].length = 0;
/* calculate buf->ntlmv2_hash */
rc = calc_ntlmv2_hash(ses,buf->ntlmv2_hash);
rc = calc_ntlmv2_hash(ses, nls_cp);
if(rc)
cERROR(1,("could not get v2 hash rc %d",rc));
CalcNTLMv2_response(ses, resp_buf);
}
void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_response)
void CalcNTLMv2_response(const struct cifsSesInfo * ses, char * v2_session_response)
{
struct HMACMD5Context context;
/* rest of v2 struct already generated */
memcpy(v2_session_response + 8, ses->server->cryptKey,8);
/* gen_blob(v2_session_response + 16); */
hmac_md5_init_limK_to_64(ses->server->mac_signing_key, 16, &context);
hmac_md5_update(ses->server->cryptKey,8,&context);
/* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */
hmac_md5_update(v2_session_response+8,
sizeof(struct ntlmv2_resp) - 8, &context);
hmac_md5_final(v2_session_response,&context);
cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); /* BB removeme BB */
/* cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */
}

View File

@ -285,9 +285,11 @@ extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key,
__u32 expected_sequence_number);
extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *);
extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * );
extern void setup_ntlmv2_rsp(const struct cifsSesInfo *, char *);
extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *,
const struct nls_table *);
extern void CalcNTLMv2_response(const struct cifsSesInfo *, char * );
extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
const struct nls_table *);
#ifdef CONFIG_CIFS_WEAK_PW_HASH
extern void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key);
#endif /* CIFS_WEAK_PW_HASH */

View File

@ -432,7 +432,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
cpu_to_le16(sizeof(struct ntlmv2_resp));
/* calculate session key */
setup_ntlmv2_rsp(ses, v2_sess_key);
setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
if(first_time) /* should this be moved into common code
with similar ntlmv2 path? */
/* cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key,