Commit ed8f425f 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:
  cifs: prevent possible memory corruption in cifs_demultiplex_thread
  cifs: eliminate some more premature cifsd exits
  cifs: prevent cifsd from exiting prematurely
  [CIFS] ntlmv2/ntlmssp remove-unused-function CalcNTLMv2_partial_mac_key
  cifs: eliminate redundant xdev check in cifs_rename
  Revert "[CIFS] Fix ntlmv2 auth with ntlmssp"
  Revert "missing changes during ntlmv2/ntlmssp auth and sign"
  Revert "Eliminate sparse warning - bad constant expression"
  Revert "[CIFS] Eliminate unused variable warning"
parents 1421e986 32670396
...@@ -2,8 +2,6 @@ config CIFS ...@@ -2,8 +2,6 @@ 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;
if (compare_oid(oid, oidlen, KRB5U2U_OID, else if (compare_oid(oid, oidlen, KRB5U2U_OID,
KRB5U2U_OID_LEN)) KRB5U2U_OID_LEN))
server->sec_kerberosu2u = true; server->sec_kerberosu2u = true;
if (compare_oid(oid, oidlen, KRB5_OID, else if (compare_oid(oid, oidlen, KRB5_OID,
KRB5_OID_LEN)) KRB5_OID_LEN))
server->sec_kerberos = true; server->sec_kerberos = true;
if (compare_oid(oid, oidlen, NTLMSSP_OID, else if (compare_oid(oid, oidlen, NTLMSSP_OID,
NTLMSSP_OID_LEN)) NTLMSSP_OID_LEN))
server->sec_ntlmssp = true; server->sec_ntlmssp = true;
......
This diff is collapsed.
...@@ -25,9 +25,6 @@ ...@@ -25,9 +25,6 @@
#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
*/ */
...@@ -100,7 +97,7 @@ enum protocolEnum { ...@@ -100,7 +97,7 @@ enum protocolEnum {
/* Netbios frames protocol not supported at this time */ /* Netbios frames protocol not supported at this time */
}; };
struct session_key { struct mac_key {
unsigned int len; unsigned int len;
union { union {
char ntlm[CIFS_SESS_KEY_SIZE + 16]; char ntlm[CIFS_SESS_KEY_SIZE + 16];
...@@ -123,21 +120,6 @@ struct cifs_cred { ...@@ -123,21 +120,6 @@ 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
...@@ -200,14 +182,11 @@ struct TCP_Server_Info { ...@@ -200,14 +182,11 @@ 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 session_key session_key; struct mac_key mac_signing_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,12 +134,6 @@ ...@@ -134,12 +134,6 @@
* 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
...@@ -669,6 +663,7 @@ struct ntlmv2_resp { ...@@ -669,6 +663,7 @@ 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));
......
...@@ -87,8 +87,9 @@ extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); ...@@ -87,8 +87,9 @@ extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
extern int decode_negTokenInit(unsigned char *security_blob, int length, extern int decode_negTokenInit(unsigned char *security_blob, int length,
struct TCP_Server_Info *server); struct TCP_Server_Info *server);
extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len); extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len);
extern int cifs_set_port(struct sockaddr *addr, const unsigned short int port);
extern int cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, extern int cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len,
unsigned short int port); const unsigned short int port);
extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr); extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr);
extern void header_assemble(struct smb_hdr *, char /* command */ , extern void header_assemble(struct smb_hdr *, char /* command */ ,
const struct cifsTconInfo *, int /* length of const struct cifsTconInfo *, int /* length of
...@@ -361,15 +362,13 @@ extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *); ...@@ -361,15 +362,13 @@ 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 *,
struct TCP_Server_Info *server, const struct mac_key *mac_key,
__u32 expected_sequence_number); __u32 expected_sequence_number);
extern int cifs_calculate_session_key(struct session_key *key, const char *rn, extern int cifs_calculate_mac_key(struct mac_key *key, const char *rn,
const char *pass); const char *pass);
extern int setup_ntlmv2_rsp(struct cifsSesInfo *, char *, 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,14 +604,11 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) ...@@ -604,14 +604,11 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
else else
rc = -EINVAL; rc = -EINVAL;
if (server->secType == Kerberos) { if (server->sec_kerberos || server->sec_mskerberos)
if (!server->sec_kerberos && server->secType = Kerberos;
!server->sec_mskerberos) else if (server->sec_ntlmssp)
rc = -EOPNOTSUPP; server->secType = RawNTLMSSP;
} else if (server->secType == RawNTLMSSP) { else
if (!server->sec_ntlmssp)
rc = -EOPNOTSUPP;
} else
rc = -EOPNOTSUPP; rc = -EOPNOTSUPP;
} }
} else } else
......
...@@ -400,7 +400,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -400,7 +400,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
cFYI(1, "call to reconnect done"); cFYI(1, "call to reconnect done");
csocket = server->ssocket; csocket = server->ssocket;
continue; continue;
} else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) { } else if (length == -ERESTARTSYS ||
length == -EAGAIN ||
length == -EINTR) {
msleep(1); /* minimum sleep to prevent looping msleep(1); /* minimum sleep to prevent looping
allowing socket to clear and app threads to set allowing socket to clear and app threads to set
tcpStatus CifsNeedReconnect if server hung */ tcpStatus CifsNeedReconnect if server hung */
...@@ -414,18 +416,6 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -414,18 +416,6 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
} else } else
continue; continue;
} else if (length <= 0) { } else if (length <= 0) {
if (server->tcpStatus == CifsNew) {
cFYI(1, "tcp session abend after SMBnegprot");
/* some servers kill the TCP session rather than
returning an SMB negprot error, in which
case reconnecting here is not going to help,
and so simply return error to mount */
break;
}
if (!try_to_freeze() && (length == -EINTR)) {
cFYI(1, "cifsd thread killed");
break;
}
cFYI(1, "Reconnect after unexpected peek error %d", cFYI(1, "Reconnect after unexpected peek error %d",
length); length);
cifs_reconnect(server); cifs_reconnect(server);
...@@ -466,27 +456,19 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -466,27 +456,19 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
an error on SMB negprot response */ an error on SMB negprot response */
cFYI(1, "Negative RFC1002 Session Response Error 0x%x)", cFYI(1, "Negative RFC1002 Session Response Error 0x%x)",
pdu_length); pdu_length);
if (server->tcpStatus == CifsNew) { /* give server a second to clean up */
/* if nack on negprot (rather than
ret of smb negprot error) reconnecting
not going to help, ret error to mount */
break;
} else {
/* give server a second to
clean up before reconnect attempt */
msleep(1000); msleep(1000);
/* always try 445 first on reconnect /* always try 445 first on reconnect since we get NACK
since we get NACK on some if we ever * on some if we ever connected to port 139 (the NACK
connected to port 139 (the NACK is * is since we do not begin with RFC1001 session
since we do not begin with RFC1001 * initialize frame)
session initialize frame) */ */
server->addr.sockAddr.sin_port = cifs_set_port((struct sockaddr *)
htons(CIFS_PORT); &server->addr.sockAddr, CIFS_PORT);
cifs_reconnect(server); cifs_reconnect(server);
csocket = server->ssocket; csocket = server->ssocket;
wake_up(&server->response_q); wake_up(&server->response_q);
continue; continue;
}
} else if (temp != (char) 0) { } else if (temp != (char) 0) {
cERROR(1, "Unknown RFC 1002 frame"); cERROR(1, "Unknown RFC 1002 frame");
cifs_dump_mem(" Received Data: ", (char *)smb_buffer, cifs_dump_mem(" Received Data: ", (char *)smb_buffer,
...@@ -522,8 +504,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -522,8 +504,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
total_read += length) { total_read += length) {
length = kernel_recvmsg(csocket, &smb_msg, &iov, 1, length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
pdu_length - total_read, 0); pdu_length - total_read, 0);
if ((server->tcpStatus == CifsExiting) || if (server->tcpStatus == CifsExiting) {
(length == -EINTR)) {
/* then will exit */ /* then will exit */
reconnect = 2; reconnect = 2;
break; break;
...@@ -534,8 +515,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -534,8 +515,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
/* Now we will reread sock */ /* Now we will reread sock */
reconnect = 1; reconnect = 1;
break; break;
} else if ((length == -ERESTARTSYS) || } else if (length == -ERESTARTSYS ||
(length == -EAGAIN)) { length == -EAGAIN ||
length == -EINTR) {
msleep(1); /* minimum sleep to prevent looping, msleep(1); /* minimum sleep to prevent looping,
allowing socket to clear and app allowing socket to clear and app
threads to set tcpStatus threads to set tcpStatus
...@@ -1708,7 +1690,6 @@ cifs_put_smb_ses(struct cifsSesInfo *ses) ...@@ -1708,7 +1690,6 @@ 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);
} }
...@@ -1788,23 +1769,13 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) ...@@ -1788,23 +1769,13 @@ 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);
......
...@@ -1462,28 +1462,17 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, ...@@ -1462,28 +1462,17 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
{ {
char *fromName = NULL; char *fromName = NULL;
char *toName = NULL; char *toName = NULL;
struct cifs_sb_info *cifs_sb_source; struct cifs_sb_info *cifs_sb;
struct cifs_sb_info *cifs_sb_target;
struct cifsTconInfo *tcon; struct cifsTconInfo *tcon;
FILE_UNIX_BASIC_INFO *info_buf_source = NULL; FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
FILE_UNIX_BASIC_INFO *info_buf_target; FILE_UNIX_BASIC_INFO *info_buf_target;
int xid, rc, tmprc; int xid, rc, tmprc;
cifs_sb_target = CIFS_SB(target_dir->i_sb); cifs_sb = CIFS_SB(source_dir->i_sb);
cifs_sb_source = CIFS_SB(source_dir->i_sb); tcon = cifs_sb->tcon;
tcon = cifs_sb_source->tcon;
xid = GetXid(); xid = GetXid();
/*
* BB: this might be allowed if same server, but different share.
* Consider adding support for this
*/
if (tcon != cifs_sb_target->tcon) {
rc = -EXDEV;
goto cifs_rename_exit;
}
/* /*
* we already have the rename sem so we do not need to * we already have the rename sem so we do not need to
* grab it again here to protect the path integrity * grab it again here to protect the path integrity
...@@ -1519,17 +1508,16 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, ...@@ -1519,17 +1508,16 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
info_buf_target = info_buf_source + 1; info_buf_target = info_buf_source + 1;
tmprc = CIFSSMBUnixQPathInfo(xid, tcon, fromName, tmprc = CIFSSMBUnixQPathInfo(xid, tcon, fromName,
info_buf_source, info_buf_source,
cifs_sb_source->local_nls, cifs_sb->local_nls,
cifs_sb_source->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
if (tmprc != 0) if (tmprc != 0)
goto unlink_target; goto unlink_target;
tmprc = CIFSSMBUnixQPathInfo(xid, tcon, tmprc = CIFSSMBUnixQPathInfo(xid, tcon, toName,
toName, info_buf_target, info_buf_target,
cifs_sb_target->local_nls, cifs_sb->local_nls,
/* remap based on source sb */ cifs_sb->mnt_cifs_flags &
cifs_sb_source->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
if (tmprc == 0 && (info_buf_source->UniqueId == if (tmprc == 0 && (info_buf_source->UniqueId ==
......
...@@ -206,26 +206,30 @@ cifs_convert_address(struct sockaddr *dst, const char *src, int len) ...@@ -206,26 +206,30 @@ cifs_convert_address(struct sockaddr *dst, const char *src, int len)
} }
int int
cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, cifs_set_port(struct sockaddr *addr, const unsigned short int port)
const unsigned short int port)
{ {
if (!cifs_convert_address(dst, src, len)) switch (addr->sa_family) {
return 0;
switch (dst->sa_family) {
case AF_INET: case AF_INET:
((struct sockaddr_in *)dst)->sin_port = htons(port); ((struct sockaddr_in *)addr)->sin_port = htons(port);
break; break;
case AF_INET6: case AF_INET6:
((struct sockaddr_in6 *)dst)->sin6_port = htons(port); ((struct sockaddr_in6 *)addr)->sin6_port = htons(port);
break; break;
default: default:
return 0; return 0;
} }
return 1; return 1;
} }
int
cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len,
const unsigned short int port)
{
if (!cifs_convert_address(dst, src, len))
return 0;
return cifs_set_port(dst, port);
}
/***************************************************************************** /*****************************************************************************
convert a NT status code to a dos class/code convert a NT status code to a dos class/code
*****************************************************************************/ *****************************************************************************/
......
...@@ -61,19 +61,6 @@ ...@@ -61,19 +61,6 @@
#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,9 +383,6 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft, ...@@ -383,9 +383,6 @@ 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)) {
...@@ -408,20 +405,6 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, ...@@ -408,20 +405,6 @@ 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;
} }
...@@ -442,13 +425,12 @@ static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, ...@@ -442,13 +425,12 @@ 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_NTLM; NTLMSSP_NEGOTIATE_NT_ONLY | 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;
NTLMSSP_NEGOTIATE_KEY_XCH | if (ses->server->secMode & SECMODE_SIGN_REQUIRED)
NTLMSSP_NEGOTIATE_EXTENDED_SEC; flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
}
sec_blob->NegotiateFlags |= cpu_to_le32(flags); sec_blob->NegotiateFlags |= cpu_to_le32(flags);
...@@ -469,12 +451,10 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, ...@@ -469,12 +451,10 @@ 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;
struct ntlmv2_resp ntlmv2_response = {}; char ntlm_session_key[CIFS_SESS_KEY_SIZE];
memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
sec_blob->MessageType = NtLmAuthenticate; sec_blob->MessageType = NtLmAuthenticate;
...@@ -497,25 +477,19 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, ...@@ -497,25 +477,19 @@ 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;
sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer); /* calculate session key, BB what about adding similar ntlmv2 path? */
rc = setup_ntlmv2_rsp(ses, (char *)&ntlmv2_response, nls_cp); SMBNTencrypt(ses->password, ses->server->cryptKey, ntlm_session_key);
if (rc) { if (first)
cERROR(1, "error rc: %d during ntlmssp ntlmv2 setup", rc); cifs_calculate_mac_key(&ses->server->mac_signing_key,
goto setup_ntlmv2_ret; ntlm_session_key, ses->password);
}
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;
sec_blob->NtChallengeResponse.Length = cpu_to_le16(size + memcpy(tmp, ntlm_session_key, CIFS_SESS_KEY_SIZE);
ses->server->tilen); sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer);
sec_blob->NtChallengeResponse.Length = cpu_to_le16(CIFS_SESS_KEY_SIZE);
sec_blob->NtChallengeResponse.MaximumLength = sec_blob->NtChallengeResponse.MaximumLength =
cpu_to_le16(size + ses->server->tilen); cpu_to_le16(CIFS_SESS_KEY_SIZE);
tmp += CIFS_SESS_KEY_SIZE;
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);
...@@ -527,6 +501,7 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, ...@@ -527,6 +501,7 @@ 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);
...@@ -543,6 +518,7 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, ...@@ -543,6 +518,7 @@ 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);
...@@ -554,26 +530,9 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, ...@@ -554,26 +530,9 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
sec_blob->WorkstationName.MaximumLength = 0; sec_blob->WorkstationName.MaximumLength = 0;
tmp += 2; tmp += 2;
if ((ses->server->ntlmssp.server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) &&
!calc_seckey(ses->server)) {
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.BufferOffset = cpu_to_le32(tmp - pbuffer);
sec_blob->SessionKey.Length = 0; sec_blob->SessionKey.Length = 0;
sec_blob->SessionKey.MaximumLength = 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;
} }
...@@ -587,14 +546,15 @@ static void setup_ntlmssp_neg_req(SESSION_SETUP_ANDX *pSMB, ...@@ -587,14 +546,15 @@ static void setup_ntlmssp_neg_req(SESSION_SETUP_ANDX *pSMB,
return; return;
} }
static int setup_ntlmssp_auth_req(char *ntlmsspblob, static int setup_ntlmssp_auth_req(SESSION_SETUP_ANDX *pSMB,
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(ntlmsspblob, ses, nls, bloblen = build_ntlmssp_auth_blob(&pSMB->req.SecurityBlob[0], ses, nls,
first_time); first_time);
pSMB->req.SecurityBlobLength = cpu_to_le16(bloblen);
return bloblen; return bloblen;
} }
...@@ -730,7 +690,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -730,7 +690,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_session_key(&ses->server->session_key, cifs_calculate_mac_key(&ses->server->mac_signing_key,
ntlm_session_key, ses->password); ntlm_session_key, ses->password);
/* copy session key */ /* copy session key */
...@@ -769,21 +729,12 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -769,21 +729,12 @@ 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 */
rc = setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp); 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;
...@@ -814,15 +765,15 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -814,15 +765,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->session_key.data.krb5)) { sizeof(ses->server->mac_signing_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->session_key.len = msg->sesskey_len; ses->server->mac_signing_key.len = msg->sesskey_len;
memcpy(ses->server->session_key.data.krb5, memcpy(ses->server->mac_signing_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;
...@@ -864,28 +815,12 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -864,28 +815,12 @@ 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;
char *ntlmsspblob; blob_len = setup_ntlmssp_auth_req(pSMB, ses,
ntlmsspblob = kmalloc(5 *
sizeof(struct _AUTHENTICATE_MESSAGE),
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, nls_cp,
first_time); 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) */
...@@ -895,6 +830,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -895,6 +830,7 @@ 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, &ses->server->mac_signing_key,
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, &ses->server->mac_signing_key,
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, &ses->server->mac_signing_key,
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