Commit 37822188 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
  Eliminate sparse warning - bad constant expression
  cifs: check for NULL session password
  missing changes during ntlmv2/ntlmssp auth and sign
  [CIFS] Fix ntlmv2 auth with ntlmssp
  cifs: correction of unicode header files
  cifs: fix NULL pointer dereference in cifs_find_smb_ses
  cifs: consolidate error handling in several functions
  cifs: clean up error handling in cifs_mknod
parents 5a559057 2d20ca83
...@@ -2,6 +2,8 @@ config CIFS ...@@ -2,6 +2,8 @@ config CIFS
tristate "CIFS support (advanced network filesystem, SMBFS successor)" tristate "CIFS support (advanced network filesystem, SMBFS successor)"
depends on INET depends on INET
select NLS select NLS
select CRYPTO_MD5
select CRYPTO_ARC4
help help
This is the client VFS module for the Common Internet File System This is the client VFS module for the Common Internet File System
(CIFS) protocol which is the successor to the Server Message Block (CIFS) protocol which is the successor to the Server Message Block
......
...@@ -597,13 +597,13 @@ decode_negTokenInit(unsigned char *security_blob, int length, ...@@ -597,13 +597,13 @@ decode_negTokenInit(unsigned char *security_blob, int length,
if (compare_oid(oid, oidlen, MSKRB5_OID, if (compare_oid(oid, oidlen, MSKRB5_OID,
MSKRB5_OID_LEN)) MSKRB5_OID_LEN))
server->sec_mskerberos = true; server->sec_mskerberos = true;
else if (compare_oid(oid, oidlen, KRB5U2U_OID, if (compare_oid(oid, oidlen, KRB5U2U_OID,
KRB5U2U_OID_LEN)) KRB5U2U_OID_LEN))
server->sec_kerberosu2u = true; server->sec_kerberosu2u = true;
else if (compare_oid(oid, oidlen, KRB5_OID, if (compare_oid(oid, oidlen, KRB5_OID,
KRB5_OID_LEN)) KRB5_OID_LEN))
server->sec_kerberos = true; server->sec_kerberos = true;
else if (compare_oid(oid, oidlen, NTLMSSP_OID, if (compare_oid(oid, oidlen, NTLMSSP_OID,
NTLMSSP_OID_LEN)) NTLMSSP_OID_LEN))
server->sec_ntlmssp = true; server->sec_ntlmssp = true;
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
* This is a compressed table of upper and lower case conversion. * This is a compressed table of upper and lower case conversion.
* *
*/ */
#ifndef _CIFS_UNICODE_H
#define _CIFS_UNICODE_H
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <linux/types.h> #include <linux/types.h>
...@@ -67,8 +69,8 @@ extern const struct UniCaseRange CifsUniUpperRange[]; ...@@ -67,8 +69,8 @@ extern const struct UniCaseRange CifsUniUpperRange[];
#endif /* UNIUPR_NOUPPER */ #endif /* UNIUPR_NOUPPER */
#ifndef UNIUPR_NOLOWER #ifndef UNIUPR_NOLOWER
extern signed char UniLowerTable[512]; extern signed char CifsUniLowerTable[512];
extern struct UniCaseRange UniLowerRange[]; extern const struct UniCaseRange CifsUniLowerRange[];
#endif /* UNIUPR_NOLOWER */ #endif /* UNIUPR_NOLOWER */
#ifdef __KERNEL__ #ifdef __KERNEL__
...@@ -337,15 +339,15 @@ UniStrupr(register wchar_t *upin) ...@@ -337,15 +339,15 @@ UniStrupr(register wchar_t *upin)
* UniTolower: Convert a unicode character to lower case * UniTolower: Convert a unicode character to lower case
*/ */
static inline wchar_t static inline wchar_t
UniTolower(wchar_t uc) UniTolower(register wchar_t uc)
{ {
register struct UniCaseRange *rp; register const struct UniCaseRange *rp;
if (uc < sizeof(UniLowerTable)) { if (uc < sizeof(CifsUniLowerTable)) {
/* Latin characters */ /* Latin characters */
return uc + UniLowerTable[uc]; /* Use base tables */ return uc + CifsUniLowerTable[uc]; /* Use base tables */
} else { } else {
rp = UniLowerRange; /* Use range tables */ rp = CifsUniLowerRange; /* Use range tables */
while (rp->start) { while (rp->start) {
if (uc < rp->start) /* Before start of range */ if (uc < rp->start) /* Before start of range */
return uc; /* Uppercase = input */ return uc; /* Uppercase = input */
...@@ -374,3 +376,5 @@ UniStrlwr(register wchar_t *upin) ...@@ -374,3 +376,5 @@ UniStrlwr(register wchar_t *upin)
} }
#endif #endif
#endif /* _CIFS_UNICODE_H */
...@@ -140,7 +140,7 @@ const struct UniCaseRange CifsUniUpperRange[] = { ...@@ -140,7 +140,7 @@ const struct UniCaseRange CifsUniUpperRange[] = {
/* /*
* Latin lower case * Latin lower case
*/ */
static signed char CifsUniLowerTable[512] = { signed char CifsUniLowerTable[512] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
...@@ -242,12 +242,12 @@ static signed char UniCaseRangeLff20[27] = { ...@@ -242,12 +242,12 @@ static signed char UniCaseRangeLff20[27] = {
/* /*
* Lower Case Range * Lower Case Range
*/ */
static const struct UniCaseRange CifsUniLowerRange[] = { const struct UniCaseRange CifsUniLowerRange[] = {
0x0380, 0x03ab, UniCaseRangeL0380, {0x0380, 0x03ab, UniCaseRangeL0380},
0x0400, 0x042f, UniCaseRangeL0400, {0x0400, 0x042f, UniCaseRangeL0400},
0x0490, 0x04cb, UniCaseRangeL0490, {0x0490, 0x04cb, UniCaseRangeL0490},
0x1e00, 0x1ff7, UniCaseRangeL1e00, {0x1e00, 0x1ff7, UniCaseRangeL1e00},
0xff20, 0xff3a, UniCaseRangeLff20, {0xff20, 0xff3a, UniCaseRangeLff20},
0, 0, 0 {0}
}; };
#endif #endif
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "md5.h" #include "md5.h"
#include "cifs_unicode.h" #include "cifs_unicode.h"
#include "cifsproto.h" #include "cifsproto.h"
#include "ntlmssp.h"
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/random.h> #include <linux/random.h>
...@@ -42,21 +43,43 @@ extern void SMBencrypt(unsigned char *passwd, const unsigned char *c8, ...@@ -42,21 +43,43 @@ extern void SMBencrypt(unsigned char *passwd, const unsigned char *c8,
unsigned char *p24); unsigned char *p24);
static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu, static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
const struct mac_key *key, char *signature) struct TCP_Server_Info *server, char *signature)
{ {
struct MD5Context context; int rc;
if ((cifs_pdu == NULL) || (signature == NULL) || (key == NULL)) if (cifs_pdu == NULL || server == NULL || signature == NULL)
return -EINVAL; return -EINVAL;
cifs_MD5_init(&context); if (!server->ntlmssp.sdescmd5) {
cifs_MD5_update(&context, (char *)&key->data, key->len); cERROR(1,
cifs_MD5_update(&context, cifs_pdu->Protocol, cifs_pdu->smb_buf_length); "cifs_calculate_signature: can't generate signature\n");
return -1;
}
cifs_MD5_final(signature, &context); rc = crypto_shash_init(&server->ntlmssp.sdescmd5->shash);
return 0; if (rc) {
cERROR(1, "cifs_calculate_signature: oould not init md5\n");
return rc;
}
if (server->secType == RawNTLMSSP)
crypto_shash_update(&server->ntlmssp.sdescmd5->shash,
server->session_key.data.ntlmv2.key,
CIFS_NTLMV2_SESSKEY_SIZE);
else
crypto_shash_update(&server->ntlmssp.sdescmd5->shash,
(char *)&server->session_key.data,
server->session_key.len);
crypto_shash_update(&server->ntlmssp.sdescmd5->shash,
cifs_pdu->Protocol, cifs_pdu->smb_buf_length);
rc = crypto_shash_final(&server->ntlmssp.sdescmd5->shash, signature);
return rc;
} }
int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
__u32 *pexpected_response_sequence_number) __u32 *pexpected_response_sequence_number)
{ {
...@@ -78,8 +101,7 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, ...@@ -78,8 +101,7 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
server->sequence_number++; server->sequence_number++;
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
rc = cifs_calculate_signature(cifs_pdu, &server->mac_signing_key, rc = cifs_calculate_signature(cifs_pdu, server, smb_signature);
smb_signature);
if (rc) if (rc)
memset(cifs_pdu->Signature.SecuritySignature, 0, 8); memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
else else
...@@ -89,21 +111,39 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, ...@@ -89,21 +111,39 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
} }
static int cifs_calc_signature2(const struct kvec *iov, int n_vec, static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
const struct mac_key *key, char *signature) struct TCP_Server_Info *server, char *signature)
{ {
struct MD5Context context;
int i; int i;
int rc;
if ((iov == NULL) || (signature == NULL) || (key == NULL)) if (iov == NULL || server == NULL || signature == NULL)
return -EINVAL; return -EINVAL;
cifs_MD5_init(&context); if (!server->ntlmssp.sdescmd5) {
cifs_MD5_update(&context, (char *)&key->data, key->len); cERROR(1, "cifs_calc_signature2: can't generate signature\n");
return -1;
}
rc = crypto_shash_init(&server->ntlmssp.sdescmd5->shash);
if (rc) {
cERROR(1, "cifs_calc_signature2: oould not init md5\n");
return rc;
}
if (server->secType == RawNTLMSSP)
crypto_shash_update(&server->ntlmssp.sdescmd5->shash,
server->session_key.data.ntlmv2.key,
CIFS_NTLMV2_SESSKEY_SIZE);
else
crypto_shash_update(&server->ntlmssp.sdescmd5->shash,
(char *)&server->session_key.data,
server->session_key.len);
for (i = 0; i < n_vec; i++) { for (i = 0; i < n_vec; i++) {
if (iov[i].iov_len == 0) if (iov[i].iov_len == 0)
continue; continue;
if (iov[i].iov_base == NULL) { if (iov[i].iov_base == NULL) {
cERROR(1, "null iovec entry"); cERROR(1, "cifs_calc_signature2: null iovec entry");
return -EIO; return -EIO;
} }
/* The first entry includes a length field (which does not get /* The first entry includes a length field (which does not get
...@@ -111,18 +151,18 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec, ...@@ -111,18 +151,18 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
if (i == 0) { if (i == 0) {
if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ if (iov[0].iov_len <= 8) /* cmd field at offset 9 */
break; /* nothing to sign or corrupt header */ break; /* nothing to sign or corrupt header */
cifs_MD5_update(&context, iov[0].iov_base+4, crypto_shash_update(&server->ntlmssp.sdescmd5->shash,
iov[0].iov_len-4); iov[i].iov_base + 4, iov[i].iov_len - 4);
} else } else
cifs_MD5_update(&context, iov[i].iov_base, iov[i].iov_len); crypto_shash_update(&server->ntlmssp.sdescmd5->shash,
iov[i].iov_base, iov[i].iov_len);
} }
cifs_MD5_final(signature, &context); rc = crypto_shash_final(&server->ntlmssp.sdescmd5->shash, signature);
return 0; return rc;
} }
int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
__u32 *pexpected_response_sequence_number) __u32 *pexpected_response_sequence_number)
{ {
...@@ -145,8 +185,7 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, ...@@ -145,8 +185,7 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
server->sequence_number++; server->sequence_number++;
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
rc = cifs_calc_signature2(iov, n_vec, &server->mac_signing_key, rc = cifs_calc_signature2(iov, n_vec, server, smb_signature);
smb_signature);
if (rc) if (rc)
memset(cifs_pdu->Signature.SecuritySignature, 0, 8); memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
else else
...@@ -156,14 +195,14 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, ...@@ -156,14 +195,14 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
} }
int cifs_verify_signature(struct smb_hdr *cifs_pdu, int cifs_verify_signature(struct smb_hdr *cifs_pdu,
const struct mac_key *mac_key, struct TCP_Server_Info *server,
__u32 expected_sequence_number) __u32 expected_sequence_number)
{ {
unsigned int rc; int rc;
char server_response_sig[8]; char server_response_sig[8];
char what_we_think_sig_should_be[20]; char what_we_think_sig_should_be[20];
if ((cifs_pdu == NULL) || (mac_key == NULL)) if (cifs_pdu == NULL || server == NULL)
return -EINVAL; return -EINVAL;
if (cifs_pdu->Command == SMB_COM_NEGOTIATE) if (cifs_pdu->Command == SMB_COM_NEGOTIATE)
...@@ -192,7 +231,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu, ...@@ -192,7 +231,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu,
cpu_to_le32(expected_sequence_number); cpu_to_le32(expected_sequence_number);
cifs_pdu->Signature.Sequence.Reserved = 0; cifs_pdu->Signature.Sequence.Reserved = 0;
rc = cifs_calculate_signature(cifs_pdu, mac_key, rc = cifs_calculate_signature(cifs_pdu, server,
what_we_think_sig_should_be); what_we_think_sig_should_be);
if (rc) if (rc)
...@@ -209,7 +248,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu, ...@@ -209,7 +248,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu,
} }
/* We fill in key by putting in 40 byte array which was allocated by caller */ /* We fill in key by putting in 40 byte array which was allocated by caller */
int cifs_calculate_mac_key(struct mac_key *key, const char *rn, int cifs_calculate_session_key(struct session_key *key, const char *rn,
const char *password) const char *password)
{ {
char temp_key[16]; char temp_key[16];
...@@ -223,63 +262,6 @@ int cifs_calculate_mac_key(struct mac_key *key, const char *rn, ...@@ -223,63 +262,6 @@ int cifs_calculate_mac_key(struct mac_key *key, const char *rn,
return 0; return 0;
} }
int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *ses,
const struct nls_table *nls_info)
{
char temp_hash[16];
struct HMACMD5Context ctx;
char *ucase_buf;
__le16 *unicode_buf;
unsigned int i, user_name_len, dom_name_len;
if (ses == NULL)
return -EINVAL;
E_md4hash(ses->password, temp_hash);
hmac_md5_init_limK_to_64(temp_hash, 16, &ctx);
user_name_len = strlen(ses->userName);
if (user_name_len > MAX_USERNAME_SIZE)
return -EINVAL;
if (ses->domainName == NULL)
return -EINVAL; /* BB should we use CIFS_LINUX_DOM */
dom_name_len = strlen(ses->domainName);
if (dom_name_len > MAX_USERNAME_SIZE)
return -EINVAL;
ucase_buf = kmalloc((MAX_USERNAME_SIZE+1), GFP_KERNEL);
if (ucase_buf == NULL)
return -ENOMEM;
unicode_buf = kmalloc((MAX_USERNAME_SIZE+1)*4, GFP_KERNEL);
if (unicode_buf == NULL) {
kfree(ucase_buf);
return -ENOMEM;
}
for (i = 0; i < user_name_len; i++)
ucase_buf[i] = nls_info->charset2upper[(int)ses->userName[i]];
ucase_buf[i] = 0;
user_name_len = cifs_strtoUCS(unicode_buf, ucase_buf,
MAX_USERNAME_SIZE*2, nls_info);
unicode_buf[user_name_len] = 0;
user_name_len++;
for (i = 0; i < dom_name_len; i++)
ucase_buf[i] = nls_info->charset2upper[(int)ses->domainName[i]];
ucase_buf[i] = 0;
dom_name_len = cifs_strtoUCS(unicode_buf+user_name_len, ucase_buf,
MAX_USERNAME_SIZE*2, nls_info);
unicode_buf[user_name_len + dom_name_len] = 0;
hmac_md5_update((const unsigned char *) unicode_buf,
(user_name_len+dom_name_len)*2, &ctx);
hmac_md5_final(ses->server->ntlmv2_hash, &ctx);
kfree(ucase_buf);
kfree(unicode_buf);
return 0;
}
#ifdef CONFIG_CIFS_WEAK_PW_HASH #ifdef CONFIG_CIFS_WEAK_PW_HASH
void calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt, void calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt,
char *lnm_session_key) char *lnm_session_key)
...@@ -324,38 +306,52 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses, ...@@ -324,38 +306,52 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
{ {
int rc = 0; int rc = 0;
int len; int len;
char nt_hash[16]; char nt_hash[CIFS_NTHASH_SIZE];
struct HMACMD5Context *pctxt;
wchar_t *user; wchar_t *user;
wchar_t *domain; wchar_t *domain;
wchar_t *server;
pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL); if (!ses->server->ntlmssp.sdeschmacmd5) {
cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n");
if (pctxt == NULL) return -1;
return -ENOMEM; }
/* 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 */ crypto_shash_setkey(ses->server->ntlmssp.hmacmd5, nt_hash,
hmac_md5_init_limK_to_64(nt_hash, 16, pctxt); CIFS_NTHASH_SIZE);
rc = crypto_shash_init(&ses->server->ntlmssp.sdeschmacmd5->shash);
if (rc) {
cERROR(1, "calc_ntlmv2_hash: could not init hmacmd5\n");
return rc;
}
/* convert ses->userName to unicode and uppercase */ /* convert ses->userName to unicode and uppercase */
len = strlen(ses->userName); len = strlen(ses->userName);
user = kmalloc(2 + (len * 2), GFP_KERNEL); user = kmalloc(2 + (len * 2), GFP_KERNEL);
if (user == NULL) if (user == NULL) {
cERROR(1, "calc_ntlmv2_hash: user mem alloc failure\n");
rc = -ENOMEM;
goto calc_exit_2; goto calc_exit_2;
}
len = cifs_strtoUCS((__le16 *)user, ses->userName, len, nls_cp); len = cifs_strtoUCS((__le16 *)user, ses->userName, len, nls_cp);
UniStrupr(user); UniStrupr(user);
hmac_md5_update((char *)user, 2*len, pctxt);
crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash,
(char *)user, 2 * len);
/* convert ses->domainName to unicode and uppercase */ /* convert ses->domainName to unicode and uppercase */
if (ses->domainName) { if (ses->domainName) {
len = strlen(ses->domainName); len = strlen(ses->domainName);
domain = kmalloc(2 + (len * 2), GFP_KERNEL); domain = kmalloc(2 + (len * 2), GFP_KERNEL);
if (domain == NULL) if (domain == NULL) {
cERROR(1, "calc_ntlmv2_hash: domain mem alloc failure");
rc = -ENOMEM;
goto calc_exit_1; goto calc_exit_1;
}
len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len, len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len,
nls_cp); nls_cp);
/* the following line was removed since it didn't work well /* the following line was removed since it didn't work well
...@@ -363,65 +359,292 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses, ...@@ -363,65 +359,292 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
Maybe converting the domain name earlier makes sense */ Maybe converting the domain name earlier makes sense */
/* UniStrupr(domain); */ /* UniStrupr(domain); */
hmac_md5_update((char *)domain, 2*len, pctxt); crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash,
(char *)domain, 2 * len);
kfree(domain); kfree(domain);
} else if (ses->serverName) {
len = strlen(ses->serverName);
server = kmalloc(2 + (len * 2), GFP_KERNEL);
if (server == NULL) {
cERROR(1, "calc_ntlmv2_hash: server mem alloc failure");
rc = -ENOMEM;
goto calc_exit_1;
}
len = cifs_strtoUCS((__le16 *)server, ses->serverName, len,
nls_cp);
/* the following line was removed since it didn't work well
with lower cased domain name that passed as an option.
Maybe converting the domain name earlier makes sense */
/* UniStrupr(domain); */
crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash,
(char *)server, 2 * len);
kfree(server);
} }
rc = crypto_shash_final(&ses->server->ntlmssp.sdeschmacmd5->shash,
ses->server->ntlmv2_hash);
calc_exit_1: calc_exit_1:
kfree(user); kfree(user);
calc_exit_2: calc_exit_2:
/* BB FIXME what about bytes 24 through 40 of the signing key? /* BB FIXME what about bytes 24 through 40 of the signing key?
compare with the NTLM example */ compare with the NTLM example */
hmac_md5_final(ses->server->ntlmv2_hash, pctxt);
kfree(pctxt);
return rc; return rc;
} }
void setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf, static int
const struct nls_table *nls_cp) find_domain_name(struct cifsSesInfo *ses)
{
int rc = 0;
unsigned int attrsize;
unsigned int type;
unsigned char *blobptr;
struct ntlmssp2_name *attrptr;
if (ses->server->tiblob) {
blobptr = ses->server->tiblob;
attrptr = (struct ntlmssp2_name *) blobptr;
while ((type = attrptr->type) != 0) {
blobptr += 2; /* advance attr type */
attrsize = attrptr->length;
blobptr += 2; /* advance attr size */
if (type == NTLMSSP_AV_NB_DOMAIN_NAME) {
if (!ses->domainName) {
ses->domainName =
kmalloc(attrptr->length + 1,
GFP_KERNEL);
if (!ses->domainName)
return -ENOMEM;
cifs_from_ucs2(ses->domainName,
(__le16 *)blobptr,
attrptr->length,
attrptr->length,
load_nls_default(), false);
}
}
blobptr += attrsize; /* advance attr value */
attrptr = (struct ntlmssp2_name *) blobptr;
}
} else {
ses->server->tilen = 2 * sizeof(struct ntlmssp2_name);
ses->server->tiblob = kmalloc(ses->server->tilen, GFP_KERNEL);
if (!ses->server->tiblob) {
ses->server->tilen = 0;
cERROR(1, "Challenge target info allocation failure");
return -ENOMEM;
}
memset(ses->server->tiblob, 0x0, ses->server->tilen);
attrptr = (struct ntlmssp2_name *) ses->server->tiblob;
attrptr->type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE);
}
return rc;
}
static int
CalcNTLMv2_response(const struct TCP_Server_Info *server,
char *v2_session_response)
{ {
int rc; int rc;
if (!server->ntlmssp.sdeschmacmd5) {
cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n");
return -1;
}
crypto_shash_setkey(server->ntlmssp.hmacmd5, server->ntlmv2_hash,
CIFS_HMAC_MD5_HASH_SIZE);
rc = crypto_shash_init(&server->ntlmssp.sdeschmacmd5->shash);
if (rc) {
cERROR(1, "CalcNTLMv2_response: could not init hmacmd5");
return rc;
}
memcpy(v2_session_response + CIFS_SERVER_CHALLENGE_SIZE,
server->cryptKey, CIFS_SERVER_CHALLENGE_SIZE);
crypto_shash_update(&server->ntlmssp.sdeschmacmd5->shash,
v2_session_response + CIFS_SERVER_CHALLENGE_SIZE,
sizeof(struct ntlmv2_resp) - CIFS_SERVER_CHALLENGE_SIZE);
if (server->tilen)
crypto_shash_update(&server->ntlmssp.sdeschmacmd5->shash,
server->tiblob, server->tilen);
rc = crypto_shash_final(&server->ntlmssp.sdeschmacmd5->shash,
v2_session_response);
return rc;
}
int
setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf,
const struct nls_table *nls_cp)
{
int rc = 0;
struct ntlmv2_resp *buf = (struct ntlmv2_resp *)resp_buf; struct ntlmv2_resp *buf = (struct ntlmv2_resp *)resp_buf;
struct HMACMD5Context context;
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 = cpu_to_le16(NTLMSSP_DOMAIN_TYPE);
buf->names[0].length = 0; if (!ses->domainName) {
buf->names[1].type = 0; rc = find_domain_name(ses);
buf->names[1].length = 0; if (rc) {
cERROR(1, "could not get domain/server name rc %d", rc);
return rc;
}
}
/* calculate buf->ntlmv2_hash */ /* calculate buf->ntlmv2_hash */
rc = calc_ntlmv2_hash(ses, nls_cp); 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); return rc;
}
rc = CalcNTLMv2_response(ses->server, resp_buf);
if (rc) {
cERROR(1, "could not get v2 hash rc %d", rc);
return rc;
}
/* now calculate the MAC key for NTLMv2 */ if (!ses->server->ntlmssp.sdeschmacmd5) {
hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context); cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n");
hmac_md5_update(resp_buf, 16, &context); return -1;
hmac_md5_final(ses->server->mac_signing_key.data.ntlmv2.key, &context); }
memcpy(&ses->server->mac_signing_key.data.ntlmv2.resp, resp_buf, crypto_shash_setkey(ses->server->ntlmssp.hmacmd5,
sizeof(struct ntlmv2_resp)); ses->server->ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
ses->server->mac_signing_key.len = 16 + sizeof(struct ntlmv2_resp);
rc = crypto_shash_init(&ses->server->ntlmssp.sdeschmacmd5->shash);
if (rc) {
cERROR(1, "setup_ntlmv2_rsp: could not init hmacmd5\n");
return rc;
}
crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash,
resp_buf, CIFS_HMAC_MD5_HASH_SIZE);
rc = crypto_shash_final(&ses->server->ntlmssp.sdeschmacmd5->shash,
ses->server->session_key.data.ntlmv2.key);
memcpy(&ses->server->session_key.data.ntlmv2.resp, resp_buf,
sizeof(struct ntlmv2_resp));
ses->server->session_key.len = 16 + sizeof(struct ntlmv2_resp);
return rc;
} }
void CalcNTLMv2_response(const struct cifsSesInfo *ses, int
char *v2_session_response) calc_seckey(struct TCP_Server_Info *server)
{ {
struct HMACMD5Context context; int rc;
/* rest of v2 struct already generated */ unsigned char sec_key[CIFS_NTLMV2_SESSKEY_SIZE];
memcpy(v2_session_response + 8, ses->server->cryptKey, 8); struct crypto_blkcipher *tfm_arc4;
hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context); struct scatterlist sgin, sgout;
struct blkcipher_desc desc;
get_random_bytes(sec_key, CIFS_NTLMV2_SESSKEY_SIZE);
tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)",
0, CRYPTO_ALG_ASYNC);
if (!tfm_arc4 || IS_ERR(tfm_arc4)) {
cERROR(1, "could not allocate " "master crypto API arc4\n");
return 1;
}
desc.tfm = tfm_arc4;
crypto_blkcipher_setkey(tfm_arc4,
server->session_key.data.ntlmv2.key, CIFS_CPHTXT_SIZE);
sg_init_one(&sgin, sec_key, CIFS_CPHTXT_SIZE);
sg_init_one(&sgout, server->ntlmssp.ciphertext, CIFS_CPHTXT_SIZE);
rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, CIFS_CPHTXT_SIZE);
hmac_md5_update(v2_session_response+8, if (!rc)
sizeof(struct ntlmv2_resp) - 8, &context); memcpy(server->session_key.data.ntlmv2.key,
sec_key, CIFS_NTLMV2_SESSKEY_SIZE);
crypto_free_blkcipher(tfm_arc4);
return 0;
}
hmac_md5_final(v2_session_response, &context); void
/* cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */ cifs_crypto_shash_release(struct TCP_Server_Info *server)
{
if (server->ntlmssp.md5)
crypto_free_shash(server->ntlmssp.md5);
if (server->ntlmssp.hmacmd5)
crypto_free_shash(server->ntlmssp.hmacmd5);
kfree(server->ntlmssp.sdeschmacmd5);
kfree(server->ntlmssp.sdescmd5);
}
int
cifs_crypto_shash_allocate(struct TCP_Server_Info *server)
{
int rc;
unsigned int size;
server->ntlmssp.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0);
if (!server->ntlmssp.hmacmd5 ||
IS_ERR(server->ntlmssp.hmacmd5)) {
cERROR(1, "could not allocate crypto hmacmd5\n");
return 1;
}
server->ntlmssp.md5 = crypto_alloc_shash("md5", 0, 0);
if (!server->ntlmssp.md5 || IS_ERR(server->ntlmssp.md5)) {
cERROR(1, "could not allocate crypto md5\n");
rc = 1;
goto cifs_crypto_shash_allocate_ret1;
}
size = sizeof(struct shash_desc) +
crypto_shash_descsize(server->ntlmssp.hmacmd5);
server->ntlmssp.sdeschmacmd5 = kmalloc(size, GFP_KERNEL);
if (!server->ntlmssp.sdeschmacmd5) {
cERROR(1, "cifs_crypto_shash_allocate: can't alloc hmacmd5\n");
rc = -ENOMEM;
goto cifs_crypto_shash_allocate_ret2;
}
server->ntlmssp.sdeschmacmd5->shash.tfm = server->ntlmssp.hmacmd5;
server->ntlmssp.sdeschmacmd5->shash.flags = 0x0;
size = sizeof(struct shash_desc) +
crypto_shash_descsize(server->ntlmssp.md5);
server->ntlmssp.sdescmd5 = kmalloc(size, GFP_KERNEL);
if (!server->ntlmssp.sdescmd5) {
cERROR(1, "cifs_crypto_shash_allocate: can't alloc md5\n");
rc = -ENOMEM;
goto cifs_crypto_shash_allocate_ret3;
}
server->ntlmssp.sdescmd5->shash.tfm = server->ntlmssp.md5;
server->ntlmssp.sdescmd5->shash.flags = 0x0;
return 0;
cifs_crypto_shash_allocate_ret3:
kfree(server->ntlmssp.sdeschmacmd5);
cifs_crypto_shash_allocate_ret2:
crypto_free_shash(server->ntlmssp.md5);
cifs_crypto_shash_allocate_ret1:
crypto_free_shash(server->ntlmssp.hmacmd5);
return rc;
} }
...@@ -25,6 +25,9 @@ ...@@ -25,6 +25,9 @@
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include "cifs_fs_sb.h" #include "cifs_fs_sb.h"
#include "cifsacl.h" #include "cifsacl.h"
#include <crypto/internal/hash.h>
#include <linux/scatterlist.h>
/* /*
* The sizes of various internal tables and strings * The sizes of various internal tables and strings
*/ */
...@@ -97,7 +100,7 @@ enum protocolEnum { ...@@ -97,7 +100,7 @@ enum protocolEnum {
/* Netbios frames protocol not supported at this time */ /* Netbios frames protocol not supported at this time */
}; };
struct mac_key { struct session_key {
unsigned int len; unsigned int len;
union { union {
char ntlm[CIFS_SESS_KEY_SIZE + 16]; char ntlm[CIFS_SESS_KEY_SIZE + 16];
...@@ -120,6 +123,21 @@ struct cifs_cred { ...@@ -120,6 +123,21 @@ struct cifs_cred {
struct cifs_ace *aces; struct cifs_ace *aces;
}; };
struct sdesc {
struct shash_desc shash;
char ctx[];
};
struct ntlmssp_auth {
__u32 client_flags;
__u32 server_flags;
unsigned char ciphertext[CIFS_CPHTXT_SIZE];
struct crypto_shash *hmacmd5;
struct crypto_shash *md5;
struct sdesc *sdeschmacmd5;
struct sdesc *sdescmd5;
};
/* /*
***************************************************************** *****************************************************************
* Except the CIFS PDUs themselves all the * Except the CIFS PDUs themselves all the
...@@ -182,11 +200,14 @@ struct TCP_Server_Info { ...@@ -182,11 +200,14 @@ struct TCP_Server_Info {
/* 16th byte of RFC1001 workstation name is always null */ /* 16th byte of RFC1001 workstation name is always null */
char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
__u32 sequence_number; /* needed for CIFS PDU signature */ __u32 sequence_number; /* needed for CIFS PDU signature */
struct mac_key mac_signing_key; struct session_key session_key;
char ntlmv2_hash[16]; char ntlmv2_hash[16];
unsigned long lstrp; /* when we got last response from this server */ unsigned long lstrp; /* when we got last response from this server */
u16 dialect; /* dialect index that server chose */ u16 dialect; /* dialect index that server chose */
/* extended security flavors that server supports */ /* extended security flavors that server supports */
unsigned int tilen; /* length of the target info blob */
unsigned char *tiblob; /* target info blob in challenge response */
struct ntlmssp_auth ntlmssp; /* various keys, ciphers, flags */
bool sec_kerberos; /* supports plain Kerberos */ bool sec_kerberos; /* supports plain Kerberos */
bool sec_mskerberos; /* supports legacy MS Kerberos */ bool sec_mskerberos; /* supports legacy MS Kerberos */
bool sec_kerberosu2u; /* supports U2U Kerberos */ bool sec_kerberosu2u; /* supports U2U Kerberos */
......
...@@ -134,6 +134,12 @@ ...@@ -134,6 +134,12 @@
* Size of the session key (crypto key encrypted with the password * Size of the session key (crypto key encrypted with the password
*/ */
#define CIFS_SESS_KEY_SIZE (24) #define CIFS_SESS_KEY_SIZE (24)
#define CIFS_CLIENT_CHALLENGE_SIZE (8)
#define CIFS_SERVER_CHALLENGE_SIZE (8)
#define CIFS_HMAC_MD5_HASH_SIZE (16)
#define CIFS_CPHTXT_SIZE (16)
#define CIFS_NTLMV2_SESSKEY_SIZE (16)
#define CIFS_NTHASH_SIZE (16)
/* /*
* Maximum user name length * Maximum user name length
...@@ -663,7 +669,6 @@ struct ntlmv2_resp { ...@@ -663,7 +669,6 @@ struct ntlmv2_resp {
__le64 time; __le64 time;
__u64 client_chal; /* random */ __u64 client_chal; /* random */
__u32 reserved2; __u32 reserved2;
struct ntlmssp2_name names[2];
/* array of name entries could follow ending in minimum 4 byte struct */ /* array of name entries could follow ending in minimum 4 byte struct */
} __attribute__((packed)); } __attribute__((packed));
......
...@@ -361,15 +361,15 @@ extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *); ...@@ -361,15 +361,15 @@ extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *);
extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *, extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
__u32 *); __u32 *);
extern int cifs_verify_signature(struct smb_hdr *, extern int cifs_verify_signature(struct smb_hdr *,
const struct mac_key *mac_key, struct TCP_Server_Info *server,
__u32 expected_sequence_number); __u32 expected_sequence_number);
extern int cifs_calculate_mac_key(struct mac_key *key, const char *rn, extern int cifs_calculate_session_key(struct session_key *key, const char *rn,
const char *pass); const char *pass);
extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, extern int setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
const struct nls_table *);
extern void CalcNTLMv2_response(const struct cifsSesInfo *, char *);
extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
const struct nls_table *); const struct nls_table *);
extern int cifs_crypto_shash_allocate(struct TCP_Server_Info *);
extern void cifs_crypto_shash_release(struct TCP_Server_Info *);
extern int calc_seckey(struct TCP_Server_Info *);
#ifdef CONFIG_CIFS_WEAK_PW_HASH #ifdef CONFIG_CIFS_WEAK_PW_HASH
extern void calc_lanman_hash(const char *password, const char *cryptkey, extern void calc_lanman_hash(const char *password, const char *cryptkey,
bool encrypt, char *lnm_session_key); bool encrypt, char *lnm_session_key);
......
...@@ -604,11 +604,14 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) ...@@ -604,11 +604,14 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
else else
rc = -EINVAL; rc = -EINVAL;
if (server->sec_kerberos || server->sec_mskerberos) if (server->secType == Kerberos) {
server->secType = Kerberos; if (!server->sec_kerberos &&
else if (server->sec_ntlmssp) !server->sec_mskerberos)
server->secType = RawNTLMSSP; rc = -EOPNOTSUPP;
else } else if (server->secType == RawNTLMSSP) {
if (!server->sec_ntlmssp)
rc = -EOPNOTSUPP;
} else
rc = -EOPNOTSUPP; rc = -EOPNOTSUPP;
} }
} else } else
......
...@@ -1673,7 +1673,9 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol) ...@@ -1673,7 +1673,9 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
MAX_USERNAME_SIZE)) MAX_USERNAME_SIZE))
continue; continue;
if (strlen(vol->username) != 0 && if (strlen(vol->username) != 0 &&
strncmp(ses->password, vol->password, ses->password != NULL &&
strncmp(ses->password,
vol->password ? vol->password : "",
MAX_PASSWORD_SIZE)) MAX_PASSWORD_SIZE))
continue; continue;
} }
...@@ -1706,6 +1708,7 @@ cifs_put_smb_ses(struct cifsSesInfo *ses) ...@@ -1706,6 +1708,7 @@ cifs_put_smb_ses(struct cifsSesInfo *ses)
CIFSSMBLogoff(xid, ses); CIFSSMBLogoff(xid, ses);
_FreeXid(xid); _FreeXid(xid);
} }
cifs_crypto_shash_release(server);
sesInfoFree(ses); sesInfoFree(ses);
cifs_put_tcp_session(server); cifs_put_tcp_session(server);
} }
...@@ -1785,13 +1788,23 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) ...@@ -1785,13 +1788,23 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
ses->linux_uid = volume_info->linux_uid; ses->linux_uid = volume_info->linux_uid;
ses->overrideSecFlg = volume_info->secFlg; ses->overrideSecFlg = volume_info->secFlg;
rc = cifs_crypto_shash_allocate(server);
if (rc) {
cERROR(1, "could not setup hash structures rc %d", rc);
goto get_ses_fail;
}
server->tilen = 0;
server->tiblob = NULL;
mutex_lock(&ses->session_mutex); mutex_lock(&ses->session_mutex);
rc = cifs_negotiate_protocol(xid, ses); rc = cifs_negotiate_protocol(xid, ses);
if (!rc) if (!rc)
rc = cifs_setup_session(xid, ses, volume_info->local_nls); rc = cifs_setup_session(xid, ses, volume_info->local_nls);
mutex_unlock(&ses->session_mutex); mutex_unlock(&ses->session_mutex);
if (rc) if (rc) {
cifs_crypto_shash_release(ses->server);
goto get_ses_fail; goto get_ses_fail;
}
/* success, put it on the list */ /* success, put it on the list */
write_lock(&cifs_tcp_ses_lock); write_lock(&cifs_tcp_ses_lock);
......
...@@ -305,8 +305,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -305,8 +305,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if (full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
FreeXid(xid); goto cifs_create_out;
return rc;
} }
if (oplockEnabled) if (oplockEnabled)
...@@ -365,9 +364,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -365,9 +364,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
if (buf == NULL) { if (buf == NULL) {
kfree(full_path); rc = -ENOMEM;
FreeXid(xid); goto cifs_create_out;
return -ENOMEM;
} }
/* /*
...@@ -496,6 +494,11 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, ...@@ -496,6 +494,11 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
char *full_path = NULL; char *full_path = NULL;
struct inode *newinode = NULL; struct inode *newinode = NULL;
int oplock = 0;
u16 fileHandle;
FILE_ALL_INFO *buf = NULL;
unsigned int bytes_written;
struct win_dev *pdev;
if (!old_valid_dev(device_number)) if (!old_valid_dev(device_number))
return -EINVAL; return -EINVAL;
...@@ -506,9 +509,12 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, ...@@ -506,9 +509,12 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if (full_path == NULL) if (full_path == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
else if (pTcon->unix_ext) { goto mknod_out;
}
if (pTcon->unix_ext) {
struct cifs_unix_set_info_args args = { struct cifs_unix_set_info_args args = {
.mode = mode & ~current_umask(), .mode = mode & ~current_umask(),
.ctime = NO_CHANGE_64, .ctime = NO_CHANGE_64,
...@@ -527,87 +533,78 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, ...@@ -527,87 +533,78 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
cifs_sb->local_nls, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc)
goto mknod_out;
if (!rc) { rc = cifs_get_inode_info_unix(&newinode, full_path,
rc = cifs_get_inode_info_unix(&newinode, full_path,
inode->i_sb, xid); inode->i_sb, xid);
if (pTcon->nocase) if (pTcon->nocase)
direntry->d_op = &cifs_ci_dentry_ops; direntry->d_op = &cifs_ci_dentry_ops;
else else
direntry->d_op = &cifs_dentry_ops; direntry->d_op = &cifs_dentry_ops;
if (rc == 0)
d_instantiate(direntry, newinode);
}
} else {
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
int oplock = 0;
u16 fileHandle;
FILE_ALL_INFO *buf;
cFYI(1, "sfu compat create special file"); if (rc == 0)
d_instantiate(direntry, newinode);
goto mknod_out;
}
buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
if (buf == NULL) { goto mknod_out;
kfree(full_path);
rc = -ENOMEM;
FreeXid(xid);
return rc;
}
rc = CIFSSMBOpen(xid, pTcon, full_path,
FILE_CREATE, /* fail if exists */ cFYI(1, "sfu compat create special file");
GENERIC_WRITE /* BB would
WRITE_OWNER | WRITE_DAC be better? */, buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
/* Create a file and set the if (buf == NULL) {
file attribute to SYSTEM */ kfree(full_path);
CREATE_NOT_DIR | CREATE_OPTION_SPECIAL, rc = -ENOMEM;
&fileHandle, &oplock, buf, FreeXid(xid);
cifs_sb->local_nls, return rc;
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
/* BB FIXME - add handling for backlevel servers
which need legacy open and check for all
calls to SMBOpen for fallback to SMBLeagcyOpen */
if (!rc) {
/* BB Do not bother to decode buf since no
local inode yet to put timestamps in,
but we can reuse it safely */
unsigned int bytes_written;
struct win_dev *pdev;
pdev = (struct win_dev *)buf;
if (S_ISCHR(mode)) {
memcpy(pdev->type, "IntxCHR", 8);
pdev->major =
cpu_to_le64(MAJOR(device_number));
pdev->minor =
cpu_to_le64(MINOR(device_number));
rc = CIFSSMBWrite(xid, pTcon,
fileHandle,
sizeof(struct win_dev),
0, &bytes_written, (char *)pdev,
NULL, 0);
} else if (S_ISBLK(mode)) {
memcpy(pdev->type, "IntxBLK", 8);
pdev->major =
cpu_to_le64(MAJOR(device_number));
pdev->minor =
cpu_to_le64(MINOR(device_number));
rc = CIFSSMBWrite(xid, pTcon,
fileHandle,
sizeof(struct win_dev),
0, &bytes_written, (char *)pdev,
NULL, 0);
} /* else if(S_ISFIFO */
CIFSSMBClose(xid, pTcon, fileHandle);
d_drop(direntry);
}
kfree(buf);
/* add code here to set EAs */
}
} }
/* FIXME: would WRITE_OWNER | WRITE_DAC be better? */
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_CREATE,
GENERIC_WRITE, CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
&fileHandle, &oplock, buf, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc)
goto mknod_out;
/* BB Do not bother to decode buf since no local inode yet to put
* timestamps in, but we can reuse it safely */
pdev = (struct win_dev *)buf;
if (S_ISCHR(mode)) {
memcpy(pdev->type, "IntxCHR", 8);
pdev->major =
cpu_to_le64(MAJOR(device_number));
pdev->minor =
cpu_to_le64(MINOR(device_number));
rc = CIFSSMBWrite(xid, pTcon,
fileHandle,
sizeof(struct win_dev),
0, &bytes_written, (char *)pdev,
NULL, 0);
} else if (S_ISBLK(mode)) {
memcpy(pdev->type, "IntxBLK", 8);
pdev->major =
cpu_to_le64(MAJOR(device_number));
pdev->minor =
cpu_to_le64(MINOR(device_number));
rc = CIFSSMBWrite(xid, pTcon,
fileHandle,
sizeof(struct win_dev),
0, &bytes_written, (char *)pdev,
NULL, 0);
} /* else if (S_ISFIFO) */
CIFSSMBClose(xid, pTcon, fileHandle);
d_drop(direntry);
/* FIXME: add code here to set EAs */
mknod_out:
kfree(full_path); kfree(full_path);
kfree(buf);
FreeXid(xid); FreeXid(xid);
return rc; return rc;
} }
......
...@@ -242,8 +242,7 @@ int cifs_open(struct inode *inode, struct file *file) ...@@ -242,8 +242,7 @@ int cifs_open(struct inode *inode, struct file *file)
full_path = build_path_from_dentry(file->f_path.dentry); full_path = build_path_from_dentry(file->f_path.dentry);
if (full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
FreeXid(xid); goto out;
return rc;
} }
cFYI(1, "inode = 0x%p file flags are 0x%x for %s", cFYI(1, "inode = 0x%p file flags are 0x%x for %s",
......
...@@ -61,6 +61,19 @@ ...@@ -61,6 +61,19 @@
#define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000 #define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000
#define NTLMSSP_NEGOTIATE_56 0x80000000 #define NTLMSSP_NEGOTIATE_56 0x80000000
/* Define AV Pair Field IDs */
#define NTLMSSP_AV_EOL 0
#define NTLMSSP_AV_NB_COMPUTER_NAME 1
#define NTLMSSP_AV_NB_DOMAIN_NAME 2
#define NTLMSSP_AV_DNS_COMPUTER_NAME 3
#define NTLMSSP_AV_DNS_DOMAIN_NAME 4
#define NTLMSSP_AV_DNS_TREE_NAME 5
#define NTLMSSP_AV_FLAGS 6
#define NTLMSSP_AV_TIMESTAMP 7
#define NTLMSSP_AV_RESTRICTION 8
#define NTLMSSP_AV_TARGET_NAME 9
#define NTLMSSP_AV_CHANNEL_BINDINGS 10
/* Although typedefs are not commonly used for structure definitions */ /* Although typedefs are not commonly used for structure definitions */
/* in the Linux kernel, in this particular case they are useful */ /* in the Linux kernel, in this particular case they are useful */
/* to more closely match the standards document for NTLMSSP from */ /* to more closely match the standards document for NTLMSSP from */
......
...@@ -383,6 +383,9 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft, ...@@ -383,6 +383,9 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft,
static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
struct cifsSesInfo *ses) struct cifsSesInfo *ses)
{ {
unsigned int tioffset; /* challeng message target info area */
unsigned int tilen; /* challeng message target info area length */
CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr; CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr;
if (blob_len < sizeof(CHALLENGE_MESSAGE)) { if (blob_len < sizeof(CHALLENGE_MESSAGE)) {
...@@ -405,6 +408,20 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, ...@@ -405,6 +408,20 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
/* BB spec says that if AvId field of MsvAvTimestamp is populated then /* BB spec says that if AvId field of MsvAvTimestamp is populated then
we must set the MIC field of the AUTHENTICATE_MESSAGE */ we must set the MIC field of the AUTHENTICATE_MESSAGE */
ses->server->ntlmssp.server_flags = le32_to_cpu(pblob->NegotiateFlags);
tioffset = cpu_to_le16(pblob->TargetInfoArray.BufferOffset);
tilen = cpu_to_le16(pblob->TargetInfoArray.Length);
ses->server->tilen = tilen;
if (tilen) {
ses->server->tiblob = kmalloc(tilen, GFP_KERNEL);
if (!ses->server->tiblob) {
cERROR(1, "Challenge target info allocation failure");
return -ENOMEM;
}
memcpy(ses->server->tiblob, bcc_ptr + tioffset, tilen);
}
return 0; return 0;
} }
...@@ -425,12 +442,13 @@ static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, ...@@ -425,12 +442,13 @@ static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
/* BB is NTLMV2 session security format easier to use here? */ /* BB is NTLMV2 session security format easier to use here? */
flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET | flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET |
NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM; NTLMSSP_NEGOTIATE_NTLM;
if (ses->server->secMode & if (ses->server->secMode &
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
flags |= NTLMSSP_NEGOTIATE_SIGN; flags |= NTLMSSP_NEGOTIATE_SIGN |
if (ses->server->secMode & SECMODE_SIGN_REQUIRED) NTLMSSP_NEGOTIATE_KEY_XCH |
flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; NTLMSSP_NEGOTIATE_EXTENDED_SEC;
}
sec_blob->NegotiateFlags |= cpu_to_le32(flags); sec_blob->NegotiateFlags |= cpu_to_le32(flags);
...@@ -451,10 +469,12 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, ...@@ -451,10 +469,12 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
struct cifsSesInfo *ses, struct cifsSesInfo *ses,
const struct nls_table *nls_cp, bool first) const struct nls_table *nls_cp, bool first)
{ {
int rc;
unsigned int size;
AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer; AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer;
__u32 flags; __u32 flags;
unsigned char *tmp; unsigned char *tmp;
char ntlm_session_key[CIFS_SESS_KEY_SIZE]; struct ntlmv2_resp ntlmv2_response = {};
memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
sec_blob->MessageType = NtLmAuthenticate; sec_blob->MessageType = NtLmAuthenticate;
...@@ -477,19 +497,25 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, ...@@ -477,19 +497,25 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
sec_blob->LmChallengeResponse.Length = 0; sec_blob->LmChallengeResponse.Length = 0;
sec_blob->LmChallengeResponse.MaximumLength = 0; sec_blob->LmChallengeResponse.MaximumLength = 0;
/* calculate session key, BB what about adding similar ntlmv2 path? */
SMBNTencrypt(ses->password, ses->server->cryptKey, ntlm_session_key);
if (first)
cifs_calculate_mac_key(&ses->server->mac_signing_key,
ntlm_session_key, ses->password);
memcpy(tmp, ntlm_session_key, CIFS_SESS_KEY_SIZE);
sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer); sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer);
sec_blob->NtChallengeResponse.Length = cpu_to_le16(CIFS_SESS_KEY_SIZE); rc = setup_ntlmv2_rsp(ses, (char *)&ntlmv2_response, nls_cp);
sec_blob->NtChallengeResponse.MaximumLength = if (rc) {
cpu_to_le16(CIFS_SESS_KEY_SIZE); cERROR(1, "error rc: %d during ntlmssp ntlmv2 setup", rc);
goto setup_ntlmv2_ret;
}
size = sizeof(struct ntlmv2_resp);
memcpy(tmp, (char *)&ntlmv2_response, size);
tmp += size;
if (ses->server->tilen > 0) {
memcpy(tmp, ses->server->tiblob, ses->server->tilen);
tmp += ses->server->tilen;
} else
ses->server->tilen = 0;
tmp += CIFS_SESS_KEY_SIZE; sec_blob->NtChallengeResponse.Length = cpu_to_le16(size +
ses->server->tilen);
sec_blob->NtChallengeResponse.MaximumLength =
cpu_to_le16(size + ses->server->tilen);
if (ses->domainName == NULL) { if (ses->domainName == NULL) {
sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
...@@ -501,7 +527,6 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, ...@@ -501,7 +527,6 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
len = cifs_strtoUCS((__le16 *)tmp, ses->domainName, len = cifs_strtoUCS((__le16 *)tmp, ses->domainName,
MAX_USERNAME_SIZE, nls_cp); MAX_USERNAME_SIZE, nls_cp);
len *= 2; /* unicode is 2 bytes each */ len *= 2; /* unicode is 2 bytes each */
len += 2; /* trailing null */
sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
sec_blob->DomainName.Length = cpu_to_le16(len); sec_blob->DomainName.Length = cpu_to_le16(len);
sec_blob->DomainName.MaximumLength = cpu_to_le16(len); sec_blob->DomainName.MaximumLength = cpu_to_le16(len);
...@@ -518,7 +543,6 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, ...@@ -518,7 +543,6 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
len = cifs_strtoUCS((__le16 *)tmp, ses->userName, len = cifs_strtoUCS((__le16 *)tmp, ses->userName,
MAX_USERNAME_SIZE, nls_cp); MAX_USERNAME_SIZE, nls_cp);
len *= 2; /* unicode is 2 bytes each */ len *= 2; /* unicode is 2 bytes each */
len += 2; /* trailing null */
sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer); sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
sec_blob->UserName.Length = cpu_to_le16(len); sec_blob->UserName.Length = cpu_to_le16(len);
sec_blob->UserName.MaximumLength = cpu_to_le16(len); sec_blob->UserName.MaximumLength = cpu_to_le16(len);
...@@ -530,9 +554,26 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, ...@@ -530,9 +554,26 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
sec_blob->WorkstationName.MaximumLength = 0; sec_blob->WorkstationName.MaximumLength = 0;
tmp += 2; tmp += 2;
sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); if ((ses->server->ntlmssp.server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) &&
sec_blob->SessionKey.Length = 0; !calc_seckey(ses->server)) {
sec_blob->SessionKey.MaximumLength = 0; memcpy(tmp, ses->server->ntlmssp.ciphertext, CIFS_CPHTXT_SIZE);
sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer);
sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE);
sec_blob->SessionKey.MaximumLength =
cpu_to_le16(CIFS_CPHTXT_SIZE);
tmp += CIFS_CPHTXT_SIZE;
} else {
sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer);
sec_blob->SessionKey.Length = 0;
sec_blob->SessionKey.MaximumLength = 0;
}
ses->server->sequence_number = 0;
setup_ntlmv2_ret:
if (ses->server->tilen > 0)
kfree(ses->server->tiblob);
return tmp - pbuffer; return tmp - pbuffer;
} }
...@@ -546,15 +587,14 @@ static void setup_ntlmssp_neg_req(SESSION_SETUP_ANDX *pSMB, ...@@ -546,15 +587,14 @@ static void setup_ntlmssp_neg_req(SESSION_SETUP_ANDX *pSMB,
return; return;
} }
static int setup_ntlmssp_auth_req(SESSION_SETUP_ANDX *pSMB, static int setup_ntlmssp_auth_req(char *ntlmsspblob,
struct cifsSesInfo *ses, struct cifsSesInfo *ses,
const struct nls_table *nls, bool first_time) const struct nls_table *nls, bool first_time)
{ {
int bloblen; int bloblen;
bloblen = build_ntlmssp_auth_blob(&pSMB->req.SecurityBlob[0], ses, nls, bloblen = build_ntlmssp_auth_blob(ntlmsspblob, ses, nls,
first_time); first_time);
pSMB->req.SecurityBlobLength = cpu_to_le16(bloblen);
return bloblen; return bloblen;
} }
...@@ -580,6 +620,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -580,6 +620,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
struct key *spnego_key = NULL; struct key *spnego_key = NULL;
__le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */ __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */
bool first_time; bool first_time;
char *ntlmsspblob;
if (ses == NULL) if (ses == NULL)
return -EINVAL; return -EINVAL;
...@@ -690,7 +731,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -690,7 +731,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
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_mac_key(&ses->server->mac_signing_key, cifs_calculate_session_key(&ses->server->session_key,
ntlm_session_key, ses->password); ntlm_session_key, ses->password);
/* copy session key */ /* copy session key */
...@@ -729,12 +770,21 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -729,12 +770,21 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
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, nls_cp); rc = setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
if (rc) {
kfree(v2_sess_key);
goto ssetup_exit;
}
/* FIXME: calculate MAC key */ /* FIXME: calculate MAC key */
memcpy(bcc_ptr, (char *)v2_sess_key, memcpy(bcc_ptr, (char *)v2_sess_key,
sizeof(struct ntlmv2_resp)); sizeof(struct ntlmv2_resp));
bcc_ptr += sizeof(struct ntlmv2_resp); bcc_ptr += sizeof(struct ntlmv2_resp);
kfree(v2_sess_key); kfree(v2_sess_key);
if (ses->server->tilen > 0) {
memcpy(bcc_ptr, ses->server->tiblob,
ses->server->tilen);
bcc_ptr += ses->server->tilen;
}
if (ses->capabilities & CAP_UNICODE) { if (ses->capabilities & CAP_UNICODE) {
if (iov[0].iov_len % 2) { if (iov[0].iov_len % 2) {
*bcc_ptr = 0; *bcc_ptr = 0;
...@@ -765,15 +815,15 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -765,15 +815,15 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
} }
/* bail out if key is too long */ /* bail out if key is too long */
if (msg->sesskey_len > if (msg->sesskey_len >
sizeof(ses->server->mac_signing_key.data.krb5)) { sizeof(ses->server->session_key.data.krb5)) {
cERROR(1, "Kerberos signing key too long (%u bytes)", cERROR(1, "Kerberos signing key too long (%u bytes)",
msg->sesskey_len); msg->sesskey_len);
rc = -EOVERFLOW; rc = -EOVERFLOW;
goto ssetup_exit; goto ssetup_exit;
} }
if (first_time) { if (first_time) {
ses->server->mac_signing_key.len = msg->sesskey_len; ses->server->session_key.len = msg->sesskey_len;
memcpy(ses->server->mac_signing_key.data.krb5, memcpy(ses->server->session_key.data.krb5,
msg->data, msg->sesskey_len); msg->data, msg->sesskey_len);
} }
pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
...@@ -815,12 +865,26 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -815,12 +865,26 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
if (phase == NtLmNegotiate) { if (phase == NtLmNegotiate) {
setup_ntlmssp_neg_req(pSMB, ses); setup_ntlmssp_neg_req(pSMB, ses);
iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE); iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE);
iov[1].iov_base = &pSMB->req.SecurityBlob[0];
} else if (phase == NtLmAuthenticate) { } else if (phase == NtLmAuthenticate) {
int blob_len; int blob_len;
blob_len = setup_ntlmssp_auth_req(pSMB, ses, ntlmsspblob = kmalloc(5 *
nls_cp, sizeof(struct _AUTHENTICATE_MESSAGE),
first_time); GFP_KERNEL);
if (!ntlmsspblob) {
cERROR(1, "Can't allocate NTLMSSP");
rc = -ENOMEM;
goto ssetup_exit;
}
blob_len = setup_ntlmssp_auth_req(ntlmsspblob,
ses,
nls_cp,
first_time);
iov[1].iov_len = blob_len; iov[1].iov_len = blob_len;
iov[1].iov_base = ntlmsspblob;
pSMB->req.SecurityBlobLength =
cpu_to_le16(blob_len);
/* Make sure that we tell the server that we /* Make sure that we tell the server that we
are using the uid that it just gave us back are using the uid that it just gave us back
on the response (challenge) */ on the response (challenge) */
...@@ -830,7 +894,6 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -830,7 +894,6 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
rc = -ENOSYS; rc = -ENOSYS;
goto ssetup_exit; goto ssetup_exit;
} }
iov[1].iov_base = &pSMB->req.SecurityBlob[0];
/* unicode strings must be word aligned */ /* unicode strings must be word aligned */
if ((iov[0].iov_len + iov[1].iov_len) % 2) { if ((iov[0].iov_len + iov[1].iov_len) % 2) {
*bcc_ptr = 0; *bcc_ptr = 0;
......
...@@ -543,7 +543,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -543,7 +543,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
(ses->server->secMode & (SECMODE_SIGN_REQUIRED | (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
SECMODE_SIGN_ENABLED))) { SECMODE_SIGN_ENABLED))) {
rc = cifs_verify_signature(midQ->resp_buf, rc = cifs_verify_signature(midQ->resp_buf,
&ses->server->mac_signing_key, ses->server,
midQ->sequence_number+1); midQ->sequence_number+1);
if (rc) { if (rc) {
cERROR(1, "Unexpected SMB signature"); cERROR(1, "Unexpected SMB signature");
...@@ -731,7 +731,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -731,7 +731,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
(ses->server->secMode & (SECMODE_SIGN_REQUIRED | (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
SECMODE_SIGN_ENABLED))) { SECMODE_SIGN_ENABLED))) {
rc = cifs_verify_signature(out_buf, rc = cifs_verify_signature(out_buf,
&ses->server->mac_signing_key, ses->server,
midQ->sequence_number+1); midQ->sequence_number+1);
if (rc) { if (rc) {
cERROR(1, "Unexpected SMB signature"); cERROR(1, "Unexpected SMB signature");
...@@ -981,7 +981,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, ...@@ -981,7 +981,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
(ses->server->secMode & (SECMODE_SIGN_REQUIRED | (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
SECMODE_SIGN_ENABLED))) { SECMODE_SIGN_ENABLED))) {
rc = cifs_verify_signature(out_buf, rc = cifs_verify_signature(out_buf,
&ses->server->mac_signing_key, ses->server,
midQ->sequence_number+1); midQ->sequence_number+1);
if (rc) { if (rc) {
cERROR(1, "Unexpected SMB signature"); cERROR(1, "Unexpected SMB signature");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment