提交 1717ffc5 编写于 作者: S Steve French

[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: NSteve French <sfrench@us.ibm.com>
上级 f3ffb681
...@@ -5,7 +5,9 @@ session setup needed for OS/2 and older servers such as Windows 95 and 98. ...@@ -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 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 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 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 Version 1.43
------------ ------------
......
...@@ -212,7 +212,8 @@ int cifs_calculate_mac_key(char * key, const char * rn, const char * password) ...@@ -212,7 +212,8 @@ int cifs_calculate_mac_key(char * key, const char * rn, const char * password)
return 0; 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]; char temp_hash[16];
struct HMACMD5Context ctx; struct HMACMD5Context ctx;
...@@ -305,13 +306,15 @@ void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key) ...@@ -305,13 +306,15 @@ void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key)
} }
#endif /* CIFS_WEAK_PW_HASH */ #endif /* CIFS_WEAK_PW_HASH */
static int calc_ntlmv2_hash(const struct cifsSesInfo *ses, static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
char * ntv2_hash) const struct nls_table * nls_cp)
{ {
int rc = 0; int rc = 0;
int len; int len;
char nt_hash[16]; char nt_hash[16];
struct HMACMD5Context * pctxt; struct HMACMD5Context * pctxt;
wchar_t * user;
wchar_t * domain;
pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL); pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL);
...@@ -321,26 +324,44 @@ static int calc_ntlmv2_hash(const struct cifsSesInfo *ses, ...@@ -321,26 +324,44 @@ static int calc_ntlmv2_hash(const struct cifsSesInfo *ses,
/* calculate md4 hash of password */ /* calculate md4 hash of password */
E_md4hash(ses->password, nt_hash); 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); hmac_md5_init_limK_to_64(nt_hash, 16, pctxt);
/* convert ses->userName to unicode and uppercase */ /* convert ses->userName to unicode and uppercase */
len = strlen(ses->userName);
/* len = ... */ /* BB FIXME BB */ user = kmalloc(2 + (len * 2), GFP_KERNEL);
if(user == NULL)
/* hmac_md5_update(user, len, pctxt); */ 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 */ /* convert ses->domainName to unicode and uppercase */
if(ses->domainName) {
len = strlen(ses->domainName);
/* len = ... */ /* BB FIXME BB */ domain = kmalloc(2 + (len * 2), GFP_KERNEL);
/* hmac_md5_update(domain, len, pctxt); */ 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; 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; int rc;
struct ntlmv2_resp * buf = (struct ntlmv2_resp *)resp_buf; struct ntlmv2_resp * buf = (struct ntlmv2_resp *)resp_buf;
...@@ -348,27 +369,28 @@ void setup_ntlmv2_rsp(const struct cifsSesInfo * ses, char * 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->blob_signature = cpu_to_le32(0x00000101);
buf->reserved = 0; buf->reserved = 0;
buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); 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->reserved2 = 0;
buf->names[0].type = 0; buf->names[0].type = 0;
buf->names[0].length = 0; buf->names[0].length = 0;
/* calculate buf->ntlmv2_hash */ /* calculate buf->ntlmv2_hash */
rc = calc_ntlmv2_hash(ses,buf->ntlmv2_hash); rc = calc_ntlmv2_hash(ses, nls_cp);
if(rc) if(rc)
cERROR(1,("could not get v2 hash rc %d",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; struct HMACMD5Context context;
/* rest of v2 struct already generated */
memcpy(v2_session_response + 8, ses->server->cryptKey,8); 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_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+8,
/* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */ sizeof(struct ntlmv2_resp) - 8, &context);
hmac_md5_final(v2_session_response,&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); */
} }
...@@ -285,9 +285,11 @@ extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *, ...@@ -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, extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key,
__u32 expected_sequence_number); __u32 expected_sequence_number);
extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass); 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 int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *,
extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * ); const struct nls_table *);
extern void setup_ntlmv2_rsp(const struct cifsSesInfo *, char *); 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 #ifdef CONFIG_CIFS_WEAK_PW_HASH
extern void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key); extern void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key);
#endif /* CIFS_WEAK_PW_HASH */ #endif /* CIFS_WEAK_PW_HASH */
......
...@@ -432,7 +432,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, ...@@ -432,7 +432,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
cpu_to_le16(sizeof(struct ntlmv2_resp)); cpu_to_le16(sizeof(struct ntlmv2_resp));
/* calculate session key */ /* 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 if(first_time) /* should this be moved into common code
with similar ntlmv2 path? */ with similar ntlmv2 path? */
/* cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key, /* cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册