aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2006-06-01 15:20:10 -0400
committerSteve French <sfrench@us.ibm.com>2006-06-01 15:20:10 -0400
commit7c7b25bc8e392aea781324efa771bc191377b876 (patch)
treeddad1a91f948746dbef140994c615253a7f42e65 /fs
parent9c53588ec96d85f82e9bf3fb1af7cca31056e940 (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.c4
-rw-r--r--fs/cifs/cifsencrypt.c40
-rw-r--r--fs/cifs/cifsglob.h2
-rw-r--r--fs/cifs/cifspdu.h3
-rw-r--r--fs/cifs/cifsproto.h3
-rw-r--r--fs/cifs/cifssmb.c27
-rw-r--r--fs/cifs/connect.c47
-rw-r--r--fs/cifs/netmisc.c2
-rw-r--r--fs/cifs/sess.c97
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
36extern void mdfour(unsigned char *out, unsigned char *in, int n); 37extern void mdfour(unsigned char *out, unsigned char *in, int n);
37extern void E_md4hash(const unsigned char *passwd, unsigned char *p16); 38extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
39extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
40 unsigned char *p24);
38 41
39static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, 42static 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
269void 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
264void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_response) 298void 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,
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 *, struct nls_table *);
289extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * ); 289extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * );
290#ifdef CONFIG_CIFS_WEAK_PW_HASH
291extern void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key);
292#endif /* CIFS_WEAK_PW_HASH */
290extern int CIFSSMBCopy(int xid, 293extern 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
1991static int 1991static int
1992CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, 1992CIFSSessSetup(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
85static const struct smb_to_posix_error mapping_table_ERRSRV[] = { 85static 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
34extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
35 unsigned char *p24);
36
37extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, 33extern 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
83void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, 79static 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
133void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, 129static 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
176int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses, 172static 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
258int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses, 254static 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