aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2006-06-08 01:41:32 -0400
committerSteve French <sfrench@us.ibm.com>2006-06-08 01:41:32 -0400
commit1717ffc58850dfa9e08b4977f8d0323cb3336863 (patch)
tree6528d6d355b1288fe4831cdff59671f6536b4b2b
parentf3ffb6814408f29817fc84d40ecc9c796acaa3ab (diff)
[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>
-rw-r--r--fs/cifs/CHANGES4
-rw-r--r--fs/cifs/cifsencrypt.c60
-rw-r--r--fs/cifs/cifsproto.h8
-rw-r--r--fs/cifs/sess.c2
4 files changed, 50 insertions, 24 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 7e0058bc3dd9..79a202b8f66a 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -5,7 +5,9 @@ session setup needed for OS/2 and older servers such as Windows 95 and 98.
5Fix oops on ls to OS/2 servers. Add support for level 1 FindFirst 5Fix oops on ls to OS/2 servers. Add support for level 1 FindFirst
6so we can do search (ls etc.) to OS/2. Do not send NTCreateX 6so we can do search (ls etc.) to OS/2. Do not send NTCreateX
7or recent levels of FindFirst unless server says it supports NT SMBs 7or recent levels of FindFirst unless server says it supports NT SMBs
8(instead use legacy equivalents from LANMAN dialect). 8(instead use legacy equivalents from LANMAN dialect). Fix to allow
9NTLMv2 authentication support (now can use stronger password hashing
10on mount if corresponding /proc/fs/cifs/SecurityFlags is set (0x4004)
9 11
10Version 1.43 12Version 1.43
11------------ 13------------
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 8bcb1da3270e..a89efaf78a26 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -212,7 +212,8 @@ int cifs_calculate_mac_key(char * key, const char * rn, const char * password)
212 return 0; 212 return 0;
213} 213}
214 214
215int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_info) 215int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses,
216 const struct nls_table * nls_info)
216{ 217{
217 char temp_hash[16]; 218 char temp_hash[16];
218 struct HMACMD5Context ctx; 219 struct HMACMD5Context ctx;
@@ -305,13 +306,15 @@ void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key)
305} 306}
306#endif /* CIFS_WEAK_PW_HASH */ 307#endif /* CIFS_WEAK_PW_HASH */
307 308
308static int calc_ntlmv2_hash(const struct cifsSesInfo *ses, 309static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
309 char * ntv2_hash) 310 const struct nls_table * nls_cp)
310{ 311{
311 int rc = 0; 312 int rc = 0;
312 int len; 313 int len;
313 char nt_hash[16]; 314 char nt_hash[16];
314 struct HMACMD5Context * pctxt; 315 struct HMACMD5Context * pctxt;
316 wchar_t * user;
317 wchar_t * domain;
315 318
316 pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL); 319 pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL);
317 320
@@ -321,26 +324,44 @@ static int calc_ntlmv2_hash(const struct cifsSesInfo *ses,
321 /* calculate md4 hash of password */ 324 /* calculate md4 hash of password */
322 E_md4hash(ses->password, nt_hash); 325 E_md4hash(ses->password, nt_hash);
323 326
324 /* convERT Domainname to unicode and uppercase */ 327 /* convert Domainname to unicode and uppercase */
325 hmac_md5_init_limK_to_64(nt_hash, 16, pctxt); 328 hmac_md5_init_limK_to_64(nt_hash, 16, pctxt);
326 329
327 /* convert ses->userName to unicode and uppercase */ 330 /* convert ses->userName to unicode and uppercase */
328 331 len = strlen(ses->userName);
329 /* len = ... */ /* BB FIXME BB */ 332 user = kmalloc(2 + (len * 2), GFP_KERNEL);
330 333 if(user == NULL)
331 /* hmac_md5_update(user, len, pctxt); */ 334 goto calc_exit_2;
335 len = cifs_strtoUCS(user, ses->userName, len, nls_cp);
336 UniStrupr(user);
337 hmac_md5_update((char *)user, 2*len, pctxt);
332 338
333 /* convert ses->domainName to unicode and uppercase */ 339 /* convert ses->domainName to unicode and uppercase */
340 if(ses->domainName) {
341 len = strlen(ses->domainName);
334 342
335 /* len = ... */ /* BB FIXME BB */ 343 domain = kmalloc(2 + (len * 2), GFP_KERNEL);
336 /* hmac_md5_update(domain, len, pctxt); */ 344 if(domain == NULL)
345 goto calc_exit_1;
346 len = cifs_strtoUCS(domain, ses->domainName, len, nls_cp);
347 UniStrupr(domain);
337 348
338 hmac_md5_final(ntv2_hash, pctxt); 349 hmac_md5_update((char *)domain, 2*len, pctxt);
350
351 kfree(domain);
352 }
353calc_exit_1:
354 kfree(user);
355calc_exit_2:
356 /* BB FIXME what about bytes 24 through 40 of the signing key?
357 compare with the NTLM example */
358 hmac_md5_final(ses->server->mac_signing_key, pctxt);
339 359
340 return rc; 360 return rc;
341} 361}
342 362
343void setup_ntlmv2_rsp(const struct cifsSesInfo * ses, char * resp_buf) 363void setup_ntlmv2_rsp(struct cifsSesInfo * ses, char * resp_buf,
364 const struct nls_table * nls_cp)
344{ 365{
345 int rc; 366 int rc;
346 struct ntlmv2_resp * buf = (struct ntlmv2_resp *)resp_buf; 367 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 buf->blob_signature = cpu_to_le32(0x00000101); 369 buf->blob_signature = cpu_to_le32(0x00000101);
349 buf->reserved = 0; 370 buf->reserved = 0;
350 buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); 371 buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
351 get_random_bytes(&buf->client_chal, sizeof(buf->client_chal)); 372 get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));
352 buf->reserved2 = 0; 373 buf->reserved2 = 0;
353 buf->names[0].type = 0; 374 buf->names[0].type = 0;
354 buf->names[0].length = 0; 375 buf->names[0].length = 0;
355 376
356 /* calculate buf->ntlmv2_hash */ 377 /* calculate buf->ntlmv2_hash */
357 rc = calc_ntlmv2_hash(ses,buf->ntlmv2_hash); 378 rc = calc_ntlmv2_hash(ses, nls_cp);
358 if(rc) 379 if(rc)
359 cERROR(1,("could not get v2 hash rc %d",rc)); 380 cERROR(1,("could not get v2 hash rc %d",rc));
381 CalcNTLMv2_response(ses, resp_buf);
360} 382}
361 383
362void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_response) 384void CalcNTLMv2_response(const struct cifsSesInfo * ses, char * v2_session_response)
363{ 385{
364 struct HMACMD5Context context; 386 struct HMACMD5Context context;
387 /* rest of v2 struct already generated */
365 memcpy(v2_session_response + 8, ses->server->cryptKey,8); 388 memcpy(v2_session_response + 8, ses->server->cryptKey,8);
366 /* gen_blob(v2_session_response + 16); */
367 hmac_md5_init_limK_to_64(ses->server->mac_signing_key, 16, &context); 389 hmac_md5_init_limK_to_64(ses->server->mac_signing_key, 16, &context);
368 390
369 hmac_md5_update(ses->server->cryptKey,8,&context); 391 hmac_md5_update(v2_session_response+8,
370/* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */ 392 sizeof(struct ntlmv2_resp) - 8, &context);
371 393
372 hmac_md5_final(v2_session_response,&context); 394 hmac_md5_final(v2_session_response,&context);
373 cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); /* BB removeme BB */ 395/* cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */
374} 396}
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 824afb937a6f..7ffd5b0d63cf 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -285,9 +285,11 @@ extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
285extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key, 285extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key,
286 __u32 expected_sequence_number); 286 __u32 expected_sequence_number);
287extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass); 287extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
288extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *); 288extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *,
289extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * ); 289 const struct nls_table *);
290extern void setup_ntlmv2_rsp(const struct cifsSesInfo *, char *); 290extern void CalcNTLMv2_response(const struct cifsSesInfo *, char * );
291extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
292 const struct nls_table *);
291#ifdef CONFIG_CIFS_WEAK_PW_HASH 293#ifdef CONFIG_CIFS_WEAK_PW_HASH
292extern void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key); 294extern void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key);
293#endif /* CIFS_WEAK_PW_HASH */ 295#endif /* CIFS_WEAK_PW_HASH */
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index c6fd01f55e90..c039b54206aa 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -432,7 +432,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
432 cpu_to_le16(sizeof(struct ntlmv2_resp)); 432 cpu_to_le16(sizeof(struct ntlmv2_resp));
433 433
434 /* calculate session key */ 434 /* calculate session key */
435 setup_ntlmv2_rsp(ses, v2_sess_key); 435 setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
436 if(first_time) /* should this be moved into common code 436 if(first_time) /* should this be moved into common code
437 with similar ntlmv2 path? */ 437 with similar ntlmv2 path? */
438 /* cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key, 438 /* cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key,