diff options
author | Steve French <sfrench@us.ibm.com> | 2006-06-01 15:20:10 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2006-06-01 15:20:10 -0400 |
commit | 7c7b25bc8e392aea781324efa771bc191377b876 (patch) | |
tree | ddad1a91f948746dbef140994c615253a7f42e65 /fs | |
parent | 9c53588ec96d85f82e9bf3fb1af7cca31056e940 (diff) |
[CIFS] Support for setting up SMB sessions to legacy lanman servers part 2
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/cifs_debug.c | 4 | ||||
-rw-r--r-- | fs/cifs/cifsencrypt.c | 40 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 3 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 3 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 27 | ||||
-rw-r--r-- | fs/cifs/connect.c | 47 | ||||
-rw-r--r-- | fs/cifs/netmisc.c | 2 | ||||
-rw-r--r-- | fs/cifs/sess.c | 97 |
9 files changed, 150 insertions, 75 deletions
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 7f4013a8607f..4e10e21c54fd 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c | |||
@@ -508,7 +508,7 @@ cifs_proc_init(void) | |||
508 | pde->write_proc = multiuser_mount_write; | 508 | pde->write_proc = multiuser_mount_write; |
509 | 509 | ||
510 | pde = | 510 | pde = |
511 | create_proc_read_entry("ExtendedSecurity", 0, proc_fs_cifs, | 511 | create_proc_read_entry("SecurityFlags", 0, proc_fs_cifs, |
512 | extended_security_read, NULL); | 512 | extended_security_read, NULL); |
513 | if (pde) | 513 | if (pde) |
514 | pde->write_proc = extended_security_write; | 514 | pde->write_proc = extended_security_write; |
@@ -547,7 +547,7 @@ cifs_proc_clean(void) | |||
547 | remove_proc_entry("MultiuserMount", proc_fs_cifs); | 547 | remove_proc_entry("MultiuserMount", proc_fs_cifs); |
548 | remove_proc_entry("OplockEnabled", proc_fs_cifs); | 548 | remove_proc_entry("OplockEnabled", proc_fs_cifs); |
549 | /* remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); */ | 549 | /* remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); */ |
550 | remove_proc_entry("ExtendedSecurity",proc_fs_cifs); | 550 | remove_proc_entry("SecurityFlags",proc_fs_cifs); |
551 | /* remove_proc_entry("PacketSigningEnabled",proc_fs_cifs); */ | 551 | /* remove_proc_entry("PacketSigningEnabled",proc_fs_cifs); */ |
552 | remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs); | 552 | remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs); |
553 | remove_proc_entry("Experimental",proc_fs_cifs); | 553 | remove_proc_entry("Experimental",proc_fs_cifs); |
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 08781a4698b4..e11d8c6bb227 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include "md5.h" | 26 | #include "md5.h" |
27 | #include "cifs_unicode.h" | 27 | #include "cifs_unicode.h" |
28 | #include "cifsproto.h" | 28 | #include "cifsproto.h" |
29 | #include <linux/ctype.h> | ||
29 | 30 | ||
30 | /* Calculate and return the CIFS signature based on the mac key and the smb pdu */ | 31 | /* Calculate and return the CIFS signature based on the mac key and the smb pdu */ |
31 | /* the 16 byte signature must be allocated by the caller */ | 32 | /* the 16 byte signature must be allocated by the caller */ |
@@ -35,6 +36,8 @@ | |||
35 | 36 | ||
36 | extern void mdfour(unsigned char *out, unsigned char *in, int n); | 37 | extern void mdfour(unsigned char *out, unsigned char *in, int n); |
37 | extern void E_md4hash(const unsigned char *passwd, unsigned char *p16); | 38 | extern void E_md4hash(const unsigned char *passwd, unsigned char *p16); |
39 | extern void SMBencrypt(unsigned char *passwd, unsigned char *c8, | ||
40 | unsigned char *p24); | ||
38 | 41 | ||
39 | static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, | 42 | static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, |
40 | const char * key, char * signature) | 43 | const char * key, char * signature) |
@@ -45,7 +48,7 @@ static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, | |||
45 | return -EINVAL; | 48 | return -EINVAL; |
46 | 49 | ||
47 | MD5Init(&context); | 50 | MD5Init(&context); |
48 | MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16); | 51 | MD5Update(&context,key,CIFS_SESS_KEY_SIZE+16); |
49 | MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length); | 52 | MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length); |
50 | MD5Final(signature,&context); | 53 | MD5Final(signature,&context); |
51 | return 0; | 54 | return 0; |
@@ -90,7 +93,7 @@ static int cifs_calc_signature2(const struct kvec * iov, int n_vec, | |||
90 | return -EINVAL; | 93 | return -EINVAL; |
91 | 94 | ||
92 | MD5Init(&context); | 95 | MD5Init(&context); |
93 | MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16); | 96 | MD5Update(&context,key,CIFS_SESS_KEY_SIZE+16); |
94 | for(i=0;i<n_vec;i++) { | 97 | for(i=0;i<n_vec;i++) { |
95 | if(iov[i].iov_base == NULL) { | 98 | if(iov[i].iov_base == NULL) { |
96 | cERROR(1,("null iovec entry")); | 99 | cERROR(1,("null iovec entry")); |
@@ -204,7 +207,7 @@ int cifs_calculate_mac_key(char * key, const char * rn, const char * password) | |||
204 | 207 | ||
205 | E_md4hash(password, temp_key); | 208 | E_md4hash(password, temp_key); |
206 | mdfour(key,temp_key,16); | 209 | mdfour(key,temp_key,16); |
207 | memcpy(key+16,rn, CIFS_SESSION_KEY_SIZE); | 210 | memcpy(key+16,rn, CIFS_SESS_KEY_SIZE); |
208 | return 0; | 211 | return 0; |
209 | } | 212 | } |
210 | 213 | ||
@@ -261,6 +264,37 @@ int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_ | |||
261 | kfree(unicode_buf); | 264 | kfree(unicode_buf); |
262 | return 0; | 265 | return 0; |
263 | } | 266 | } |
267 | |||
268 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
269 | void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key) | ||
270 | { | ||
271 | int i; | ||
272 | char password_with_pad[CIFS_ENCPWD_SIZE]; | ||
273 | |||
274 | memset(password_with_pad, 0, CIFS_ENCPWD_SIZE); | ||
275 | strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE); | ||
276 | |||
277 | /* calculate old style session key */ | ||
278 | /* calling toupper is less broken than repeatedly | ||
279 | calling nls_toupper would be since that will never | ||
280 | work for UTF8, but neither handles multibyte code pages | ||
281 | but the only alternative would be converting to UCS-16 (Unicode) | ||
282 | (using a routine something like UniStrupr) then | ||
283 | uppercasing and then converting back from Unicode - which | ||
284 | would only worth doing it if we knew it were utf8. Basically | ||
285 | utf8 and other multibyte codepages each need their own strupper | ||
286 | function since a byte at a time will ont work. */ | ||
287 | |||
288 | for(i = 0; i < CIFS_ENCPWD_SIZE; i++) { | ||
289 | password_with_pad[i] = toupper(password_with_pad[i]); | ||
290 | } | ||
291 | |||
292 | SMBencrypt(password_with_pad, ses->server->cryptKey, lnm_session_key); | ||
293 | /* clear password before we return/free memory */ | ||
294 | memset(password_with_pad, 0, CIFS_ENCPWD_SIZE); | ||
295 | } | ||
296 | #endif /* CIFS_WEAK_PW_HASH */ | ||
297 | |||
264 | void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_response) | 298 | void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_response) |
265 | { | 299 | { |
266 | struct HMACMD5Context context; | 300 | struct HMACMD5Context context; |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 7a042041a16a..975e69a2e1c4 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -158,7 +158,7 @@ struct TCP_Server_Info { | |||
158 | /* 16th byte of RFC1001 workstation name is always null */ | 158 | /* 16th byte of RFC1001 workstation name is always null */ |
159 | char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL]; | 159 | char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL]; |
160 | __u32 sequence_number; /* needed for CIFS PDU signature */ | 160 | __u32 sequence_number; /* needed for CIFS PDU signature */ |
161 | char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16]; | 161 | char mac_signing_key[CIFS_SESS_KEY_SIZE + 16]; |
162 | }; | 162 | }; |
163 | 163 | ||
164 | /* | 164 | /* |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index e0ff9b56cc4c..135941738d9d 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -116,7 +116,8 @@ | |||
116 | /* | 116 | /* |
117 | * Size of the session key (crypto key encrypted with the password | 117 | * Size of the session key (crypto key encrypted with the password |
118 | */ | 118 | */ |
119 | #define CIFS_SESSION_KEY_SIZE (24) | 119 | #define CIFS_SESS_KEY_SIZE (24) |
120 | #define V2_SESS_KEY_SIZE (86) | ||
120 | 121 | ||
121 | /* | 122 | /* |
122 | * Maximum user name length | 123 | * Maximum user name length |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index ff78cf7b0d1b..59b037f14511 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -287,6 +287,9 @@ extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key, | |||
287 | extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass); | 287 | extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass); |
288 | extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *); | 288 | extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *); |
289 | extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * ); | 289 | extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * ); |
290 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
291 | extern void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key); | ||
292 | #endif /* CIFS_WEAK_PW_HASH */ | ||
290 | extern int CIFSSMBCopy(int xid, | 293 | extern int CIFSSMBCopy(int xid, |
291 | struct cifsTconInfo *source_tcon, | 294 | struct cifsTconInfo *source_tcon, |
292 | const char *fromName, | 295 | const char *fromName, |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index da3154fa9c8a..6b5be6d59f07 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -438,12 +438,19 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
438 | goto neg_err_exit; | 438 | goto neg_err_exit; |
439 | } else if((pSMBr->hdr.WordCount == 13) && | 439 | } else if((pSMBr->hdr.WordCount == 13) && |
440 | (pSMBr->DialectIndex == LANMAN_PROT)) { | 440 | (pSMBr->DialectIndex == LANMAN_PROT)) { |
441 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
441 | struct lanman_neg_rsp * rsp = | 442 | struct lanman_neg_rsp * rsp = |
442 | (struct lanman_neg_rsp *)pSMBr; | 443 | (struct lanman_neg_rsp *)pSMBr; |
443 | 444 | ||
444 | 445 | if((extended_security & CIFSSEC_MAY_LANMAN) || | |
445 | /* BB Mark ses struct as negotiated lanman level BB */ | 446 | (extended_security & CIFSSEC_MAY_PLNTXT)) |
446 | server->secType = LANMAN; | 447 | server->secType = LANMAN; |
448 | else { | ||
449 | cERROR(1, ("mount failed weak security disabled" | ||
450 | " in /proc/fs/cifs/SecurityFlags")); | ||
451 | rc = -EOPNOTSUPP; | ||
452 | goto neg_err_exit; | ||
453 | } | ||
447 | server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode); | 454 | server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode); |
448 | server->maxReq = le16_to_cpu(rsp->MaxMpxCount); | 455 | server->maxReq = le16_to_cpu(rsp->MaxMpxCount); |
449 | server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize), | 456 | server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize), |
@@ -469,6 +476,11 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
469 | } | 476 | } |
470 | 477 | ||
471 | cFYI(1,("LANMAN negotiated")); /* BB removeme BB */ | 478 | cFYI(1,("LANMAN negotiated")); /* BB removeme BB */ |
479 | #else /* weak security disabled */ | ||
480 | cERROR(1,("mount failed, cifs module not built with " | ||
481 | "CIFS_WEAK_PW_HASH support")); | ||
482 | rc = -EOPNOTSUPP; | ||
483 | #endif /* WEAK_PW_HASH */ | ||
472 | goto neg_err_exit; | 484 | goto neg_err_exit; |
473 | } else if(pSMBr->hdr.WordCount != 17) { | 485 | } else if(pSMBr->hdr.WordCount != 17) { |
474 | /* unknown wct */ | 486 | /* unknown wct */ |
@@ -479,8 +491,13 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
479 | server->secMode = pSMBr->SecurityMode; | 491 | server->secMode = pSMBr->SecurityMode; |
480 | if((server->secMode & SECMODE_USER) == 0) | 492 | if((server->secMode & SECMODE_USER) == 0) |
481 | cFYI(1,("share mode security")); | 493 | cFYI(1,("share mode security")); |
482 | server->secType = NTLM; /* BB override default for | 494 | |
483 | NTLMv2 or kerberos v5 */ | 495 | if(extended_security & CIFSSEC_MUST_NTLMV2) |
496 | server->secType = NTLMv2; | ||
497 | else | ||
498 | server->secType = NTLM; | ||
499 | /* else krb5 ... */ | ||
500 | |||
484 | /* one byte - no need to convert this or EncryptionKeyLen | 501 | /* one byte - no need to convert this or EncryptionKeyLen |
485 | from little endian */ | 502 | from little endian */ |
486 | server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount); | 503 | server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount); |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 7ffb8f244f6a..e6f3d2fff6c0 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -1990,7 +1990,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1990 | 1990 | ||
1991 | static int | 1991 | static int |
1992 | CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | 1992 | CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, |
1993 | char session_key[CIFS_SESSION_KEY_SIZE], | 1993 | char session_key[CIFS_SESS_KEY_SIZE], |
1994 | const struct nls_table *nls_codepage) | 1994 | const struct nls_table *nls_codepage) |
1995 | { | 1995 | { |
1996 | struct smb_hdr *smb_buffer; | 1996 | struct smb_hdr *smb_buffer; |
@@ -2048,15 +2048,15 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2048 | pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); | 2048 | pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); |
2049 | 2049 | ||
2050 | pSMB->req_no_secext.CaseInsensitivePasswordLength = | 2050 | pSMB->req_no_secext.CaseInsensitivePasswordLength = |
2051 | cpu_to_le16(CIFS_SESSION_KEY_SIZE); | 2051 | cpu_to_le16(CIFS_SESS_KEY_SIZE); |
2052 | 2052 | ||
2053 | pSMB->req_no_secext.CaseSensitivePasswordLength = | 2053 | pSMB->req_no_secext.CaseSensitivePasswordLength = |
2054 | cpu_to_le16(CIFS_SESSION_KEY_SIZE); | 2054 | cpu_to_le16(CIFS_SESS_KEY_SIZE); |
2055 | bcc_ptr = pByteArea(smb_buffer); | 2055 | bcc_ptr = pByteArea(smb_buffer); |
2056 | memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE); | 2056 | memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE); |
2057 | bcc_ptr += CIFS_SESSION_KEY_SIZE; | 2057 | bcc_ptr += CIFS_SESS_KEY_SIZE; |
2058 | memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE); | 2058 | memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE); |
2059 | bcc_ptr += CIFS_SESSION_KEY_SIZE; | 2059 | bcc_ptr += CIFS_SESS_KEY_SIZE; |
2060 | 2060 | ||
2061 | if (ses->capabilities & CAP_UNICODE) { | 2061 | if (ses->capabilities & CAP_UNICODE) { |
2062 | if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */ | 2062 | if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */ |
@@ -3004,14 +3004,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
3004 | SecurityBlob->LmChallengeResponse.Buffer = 0; | 3004 | SecurityBlob->LmChallengeResponse.Buffer = 0; |
3005 | 3005 | ||
3006 | SecurityBlob->NtChallengeResponse.Length = | 3006 | SecurityBlob->NtChallengeResponse.Length = |
3007 | cpu_to_le16(CIFS_SESSION_KEY_SIZE); | 3007 | cpu_to_le16(CIFS_SESS_KEY_SIZE); |
3008 | SecurityBlob->NtChallengeResponse.MaximumLength = | 3008 | SecurityBlob->NtChallengeResponse.MaximumLength = |
3009 | cpu_to_le16(CIFS_SESSION_KEY_SIZE); | 3009 | cpu_to_le16(CIFS_SESS_KEY_SIZE); |
3010 | memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE); | 3010 | memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE); |
3011 | SecurityBlob->NtChallengeResponse.Buffer = | 3011 | SecurityBlob->NtChallengeResponse.Buffer = |
3012 | cpu_to_le32(SecurityBlobLength); | 3012 | cpu_to_le32(SecurityBlobLength); |
3013 | SecurityBlobLength += CIFS_SESSION_KEY_SIZE; | 3013 | SecurityBlobLength += CIFS_SESS_KEY_SIZE; |
3014 | bcc_ptr += CIFS_SESSION_KEY_SIZE; | 3014 | bcc_ptr += CIFS_SESS_KEY_SIZE; |
3015 | 3015 | ||
3016 | if (ses->capabilities & CAP_UNICODE) { | 3016 | if (ses->capabilities & CAP_UNICODE) { |
3017 | if (domain == NULL) { | 3017 | if (domain == NULL) { |
@@ -3350,22 +3350,33 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3350 | bcc_ptr = &pSMB->Password[0]; | 3350 | bcc_ptr = &pSMB->Password[0]; |
3351 | if((ses->server->secMode) & SECMODE_USER) { | 3351 | if((ses->server->secMode) & SECMODE_USER) { |
3352 | pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ | 3352 | pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ |
3353 | *bcc_ptr = 0; /* password is null byte */ | ||
3353 | bcc_ptr++; /* skip password */ | 3354 | bcc_ptr++; /* skip password */ |
3355 | /* already aligned so no need to do it below */ | ||
3354 | } else { | 3356 | } else { |
3355 | pSMB->PasswordLength = cpu_to_le16(CIFS_SESSION_KEY_SIZE); | 3357 | pSMB->PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE); |
3356 | /* BB FIXME add code to fail this if NTLMv2 or Kerberos | 3358 | /* BB FIXME add code to fail this if NTLMv2 or Kerberos |
3357 | specified as required (when that support is added to | 3359 | specified as required (when that support is added to |
3358 | the vfs in the future) as only NTLM or the much | 3360 | the vfs in the future) as only NTLM or the much |
3359 | weaker LANMAN (which we do not send) is accepted | 3361 | weaker LANMAN (which we do not send by default) is accepted |
3360 | by Samba (not sure whether other servers allow | 3362 | by Samba (not sure whether other servers allow |
3361 | NTLMv2 password here) */ | 3363 | NTLMv2 password here) */ |
3364 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
3365 | if((extended_security & CIFSSEC_MAY_LANMAN) && | ||
3366 | (ses->server->secType == LANMAN)) | ||
3367 | calc_lanman_hash(ses, bcc_ptr); | ||
3368 | else | ||
3369 | #endif /* CIFS_WEAK_PW_HASH */ | ||
3362 | SMBNTencrypt(ses->password, | 3370 | SMBNTencrypt(ses->password, |
3363 | ses->server->cryptKey, | 3371 | ses->server->cryptKey, |
3364 | bcc_ptr); | 3372 | bcc_ptr); |
3365 | 3373 | ||
3366 | bcc_ptr += CIFS_SESSION_KEY_SIZE; | 3374 | bcc_ptr += CIFS_SESS_KEY_SIZE; |
3367 | *bcc_ptr = 0; | 3375 | if(ses->capabilities & CAP_UNICODE) { |
3368 | bcc_ptr++; /* align */ | 3376 | /* must align unicode strings */ |
3377 | *bcc_ptr = 0; /* null byte password */ | ||
3378 | bcc_ptr++; | ||
3379 | } | ||
3369 | } | 3380 | } |
3370 | 3381 | ||
3371 | if(ses->server->secMode & | 3382 | if(ses->server->secMode & |
@@ -3507,7 +3518,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, | |||
3507 | struct nls_table * nls_info) | 3518 | struct nls_table * nls_info) |
3508 | { | 3519 | { |
3509 | int rc = 0; | 3520 | int rc = 0; |
3510 | char ntlm_session_key[CIFS_SESSION_KEY_SIZE]; | 3521 | char ntlm_session_key[CIFS_SESS_KEY_SIZE]; |
3511 | int ntlmv2_flag = FALSE; | 3522 | int ntlmv2_flag = FALSE; |
3512 | int first_time = 0; | 3523 | int first_time = 0; |
3513 | 3524 | ||
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index 5de74d216fdd..a0bcdd6f4a67 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c | |||
@@ -84,7 +84,7 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = { | |||
84 | 84 | ||
85 | static const struct smb_to_posix_error mapping_table_ERRSRV[] = { | 85 | static const struct smb_to_posix_error mapping_table_ERRSRV[] = { |
86 | {ERRerror, -EIO}, | 86 | {ERRerror, -EIO}, |
87 | {ERRbadpw, -EPERM}, | 87 | {ERRbadpw, -EACCES}, /* was EPERM */ |
88 | {ERRbadtype, -EREMOTE}, | 88 | {ERRbadtype, -EREMOTE}, |
89 | {ERRaccess, -EACCES}, | 89 | {ERRaccess, -EACCES}, |
90 | {ERRinvtid, -ENXIO}, | 90 | {ERRinvtid, -ENXIO}, |
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index fdc248fffa0a..a52aacb3feff 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
@@ -28,12 +28,8 @@ | |||
28 | #include "cifs_debug.h" | 28 | #include "cifs_debug.h" |
29 | #include "ntlmssp.h" | 29 | #include "ntlmssp.h" |
30 | #include "nterr.h" | 30 | #include "nterr.h" |
31 | #include <linux/ctype.h> | ||
32 | #include <linux/utsname.h> | 31 | #include <linux/utsname.h> |
33 | 32 | ||
34 | extern void SMBencrypt(unsigned char *passwd, unsigned char *c8, | ||
35 | unsigned char *p24); | ||
36 | |||
37 | extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, | 33 | extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, |
38 | unsigned char *p24); | 34 | unsigned char *p24); |
39 | 35 | ||
@@ -80,7 +76,7 @@ static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB) | |||
80 | return capabilities; | 76 | return capabilities; |
81 | } | 77 | } |
82 | 78 | ||
83 | void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, | 79 | static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, |
84 | const struct nls_table * nls_cp) | 80 | const struct nls_table * nls_cp) |
85 | { | 81 | { |
86 | char * bcc_ptr = *pbcc_area; | 82 | char * bcc_ptr = *pbcc_area; |
@@ -130,7 +126,7 @@ void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, | |||
130 | *pbcc_area = bcc_ptr; | 126 | *pbcc_area = bcc_ptr; |
131 | } | 127 | } |
132 | 128 | ||
133 | void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, | 129 | static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, |
134 | const struct nls_table * nls_cp) | 130 | const struct nls_table * nls_cp) |
135 | { | 131 | { |
136 | char * bcc_ptr = *pbcc_area; | 132 | char * bcc_ptr = *pbcc_area; |
@@ -173,7 +169,7 @@ void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, | |||
173 | *pbcc_area = bcc_ptr; | 169 | *pbcc_area = bcc_ptr; |
174 | } | 170 | } |
175 | 171 | ||
176 | int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses, | 172 | static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses, |
177 | const struct nls_table * nls_cp) | 173 | const struct nls_table * nls_cp) |
178 | { | 174 | { |
179 | int rc = 0; | 175 | int rc = 0; |
@@ -255,7 +251,7 @@ int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses, | |||
255 | return rc; | 251 | return rc; |
256 | } | 252 | } |
257 | 253 | ||
258 | int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses, | 254 | static int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses, |
259 | const struct nls_table * nls_cp) | 255 | const struct nls_table * nls_cp) |
260 | { | 256 | { |
261 | int rc = 0; | 257 | int rc = 0; |
@@ -317,7 +313,6 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, | |||
317 | { | 313 | { |
318 | int rc = 0; | 314 | int rc = 0; |
319 | int wct; | 315 | int wct; |
320 | int i; | ||
321 | struct smb_hdr *smb_buf; | 316 | struct smb_hdr *smb_buf; |
322 | char *bcc_ptr; | 317 | char *bcc_ptr; |
323 | SESSION_SETUP_ANDX *pSMB; | 318 | SESSION_SETUP_ANDX *pSMB; |
@@ -343,7 +338,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, | |||
343 | return -EOPNOTSUPP; | 338 | return -EOPNOTSUPP; |
344 | #endif | 339 | #endif |
345 | wct = 10; /* lanman 2 style sessionsetup */ | 340 | wct = 10; /* lanman 2 style sessionsetup */ |
346 | } else if(type == NTLM) /* NTLMv2 may retry NTLM */ | 341 | } else if((type == NTLM) || (type == NTLMv2)) /* NTLMv2 may retry NTLM */ |
347 | wct = 13; /* old style NTLM sessionsetup */ | 342 | wct = 13; /* old style NTLM sessionsetup */ |
348 | else /* same size for negotiate or auth, NTLMSSP or extended security */ | 343 | else /* same size for negotiate or auth, NTLMSSP or extended security */ |
349 | wct = 12; | 344 | wct = 12; |
@@ -360,41 +355,22 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, | |||
360 | 355 | ||
361 | if(type == LANMAN) { | 356 | if(type == LANMAN) { |
362 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 357 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
363 | char lnm_session_key[CIFS_SESSION_KEY_SIZE]; | 358 | char lnm_session_key[CIFS_SESS_KEY_SIZE]; |
364 | char password_with_pad[CIFS_ENCPWD_SIZE]; | ||
365 | 359 | ||
366 | /* no capabilities flags in old lanman negotiation */ | 360 | /* no capabilities flags in old lanman negotiation */ |
367 | 361 | ||
368 | pSMB->old_req.PasswordLength = CIFS_SESSION_KEY_SIZE; | 362 | pSMB->old_req.PasswordLength = CIFS_SESS_KEY_SIZE; |
369 | /* BB calculate hash with password */ | 363 | /* BB calculate hash with password */ |
370 | /* and copy into bcc */ | 364 | /* and copy into bcc */ |
371 | 365 | ||
372 | memset(password_with_pad, 0, CIFS_ENCPWD_SIZE); | 366 | calc_lanman_hash(ses, lnm_session_key); |
373 | strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE); | ||
374 | |||
375 | /* calculate old style session key */ | ||
376 | /* toupper may be less broken then repeatedly calling | ||
377 | nls_toupper would be, but neither handles multibyte code pages | ||
378 | but the only alternative would be converting to UCS-16 (Unicode) | ||
379 | uppercasing and converting back which is only worth doing if | ||
380 | we knew it were utf8. utf8 code page needs its own | ||
381 | toupper and tolower and strnicmp functions */ | ||
382 | |||
383 | for(i = 0; i< CIFS_ENCPWD_SIZE; i++) { | ||
384 | password_with_pad[i] = toupper(password_with_pad[i]); | ||
385 | } | ||
386 | |||
387 | SMBencrypt(password_with_pad, ses->server->cryptKey, | ||
388 | lnm_session_key); | ||
389 | 367 | ||
390 | #ifdef CONFIG_CIFS_DEBUG2 | 368 | #ifdef CONFIG_CIFS_DEBUG2 |
391 | cifs_dump_mem("cryptkey: ",ses->server->cryptKey, | 369 | cifs_dump_mem("cryptkey: ",ses->server->cryptKey, |
392 | CIFS_SESSION_KEY_SIZE); | 370 | CIFS_SESS_KEY_SIZE); |
393 | #endif | 371 | #endif |
394 | /* clear password before we return/free memory */ | 372 | memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESS_KEY_SIZE); |
395 | memset(password_with_pad, 0, CIFS_ENCPWD_SIZE); | 373 | bcc_ptr += CIFS_SESS_KEY_SIZE; |
396 | memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESSION_KEY_SIZE); | ||
397 | bcc_ptr += CIFS_SESSION_KEY_SIZE; | ||
398 | 374 | ||
399 | /* can not sign if LANMAN negotiated so no need | 375 | /* can not sign if LANMAN negotiated so no need |
400 | to calculate signing key? but what if server | 376 | to calculate signing key? but what if server |
@@ -406,13 +382,13 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, | |||
406 | ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); | 382 | ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); |
407 | #endif | 383 | #endif |
408 | } else if (type == NTLM) { | 384 | } else if (type == NTLM) { |
409 | char ntlm_session_key[CIFS_SESSION_KEY_SIZE]; | 385 | char ntlm_session_key[CIFS_SESS_KEY_SIZE]; |
410 | 386 | ||
411 | pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); | 387 | pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); |
412 | pSMB->req_no_secext.CaseInsensitivePasswordLength = | 388 | pSMB->req_no_secext.CaseInsensitivePasswordLength = |
413 | cpu_to_le16(CIFS_SESSION_KEY_SIZE); | 389 | cpu_to_le16(CIFS_SESS_KEY_SIZE); |
414 | pSMB->req_no_secext.CaseSensitivePasswordLength = | 390 | pSMB->req_no_secext.CaseSensitivePasswordLength = |
415 | cpu_to_le16(CIFS_SESSION_KEY_SIZE); | 391 | cpu_to_le16(CIFS_SESS_KEY_SIZE); |
416 | 392 | ||
417 | /* calculate session key */ | 393 | /* calculate session key */ |
418 | SMBNTencrypt(ses->password, ses->server->cryptKey, | 394 | SMBNTencrypt(ses->password, ses->server->cryptKey, |
@@ -420,15 +396,48 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, | |||
420 | 396 | ||
421 | if(first_time) /* should this be moved into common code | 397 | if(first_time) /* should this be moved into common code |
422 | with similar ntlmv2 path? */ | 398 | with similar ntlmv2 path? */ |
423 | cifs_calculate_mac_key( | 399 | cifs_calculate_mac_key( ses->server->mac_signing_key, |
424 | ses->server->mac_signing_key, | ||
425 | ntlm_session_key, ses->password); | 400 | ntlm_session_key, ses->password); |
426 | /* copy session key */ | 401 | /* copy session key */ |
427 | 402 | ||
428 | memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESSION_KEY_SIZE); | 403 | memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE); |
429 | bcc_ptr += CIFS_SESSION_KEY_SIZE; | 404 | bcc_ptr += CIFS_SESS_KEY_SIZE; |
430 | memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESSION_KEY_SIZE); | 405 | memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE); |
431 | bcc_ptr += CIFS_SESSION_KEY_SIZE; | 406 | bcc_ptr += CIFS_SESS_KEY_SIZE; |
407 | if(ses->capabilities & CAP_UNICODE) | ||
408 | unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); | ||
409 | else | ||
410 | ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); | ||
411 | } else if (type == NTLMv2) { | ||
412 | char * v2_sess_key = kmalloc(V2_SESS_KEY_SIZE, GFP_KERNEL); | ||
413 | |||
414 | if(v2_sess_key == NULL) { | ||
415 | cifs_small_buf_release(smb_buf); | ||
416 | return -ENOMEM; | ||
417 | } | ||
418 | |||
419 | pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); | ||
420 | |||
421 | /* LM2 password would be here if we supported it */ | ||
422 | pSMB->req_no_secext.CaseInsensitivePasswordLength = 0; | ||
423 | /* cpu_to_le16(LM2_SESS_KEY_SIZE); */ | ||
424 | |||
425 | pSMB->req_no_secext.CaseSensitivePasswordLength = | ||
426 | cpu_to_le16(V2_SESS_KEY_SIZE); | ||
427 | |||
428 | /* calculate session key */ | ||
429 | CalcNTLMv2_response(ses, v2_sess_key); | ||
430 | if(first_time) /* should this be moved into common code | ||
431 | with similar ntlmv2 path? */ | ||
432 | /* cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key, | ||
433 | response BB FIXME, v2_sess_key); */ | ||
434 | |||
435 | /* copy session key */ | ||
436 | |||
437 | /* memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE); | ||
438 | bcc_ptr += LM2_SESS_KEY_SIZE; */ | ||
439 | memcpy(bcc_ptr, (char *)v2_sess_key, V2_SESS_KEY_SIZE); | ||
440 | bcc_ptr += V2_SESS_KEY_SIZE; | ||
432 | if(ses->capabilities & CAP_UNICODE) | 441 | if(ses->capabilities & CAP_UNICODE) |
433 | unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); | 442 | unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); |
434 | else | 443 | else |