11 cifs/smb3 client fixes, including some restructuring to allow disabling less secure algorithms, and 2 for stable
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmEsHj4ACgkQiiy9cAdy T1EIaAwAojBPoKmXwYGWRWtged9Z2U0gKa2yud+e02dqXemR0g7dqtyQThYru9VV v/lbQUi+WZT+uWpYPyXqcFjOXj2gZkSAcXxpXgDQfDecl3rXo+pUTzPXCqcbRxmu mpNrU5XrFtuX44dltPhg/BQvdnIyzmeeJ34BbdljQ+Ph9jy89hr7plXMmloyClCY f/BS1jalE9QMBgGDjmqaJ0eaz7oyhCjXF399NXE245OQsT6N+92D/mH7CYFMjKNp FQZ6rK1qeZaPuG5zFTYiS9ajzAdYxxGDa7gjo7+Totdr+IJJHW6aODjklngjZKHl ihTXLKpX/PxNZ45ILDLYcmzfDsj9hB63V9B0ARfDTI4VMc3f5yltxu0DxSTOn78v zRtfvyyw3scVnk9j2PhaJk/fofrv/RwdNPjlMX5QvuSG4u0E2DlKNX/YUpPgAZmH PU7XS/OPYcpo5Q4aPJ5cYgulsvnNiTlY0QYkM1eB0zv8koLPRFkvpMnShVEcahOq 0Tw5Ekhp =d9f7 -----END PGP SIGNATURE----- Merge tag '5.15-rc-smb3-fixes-part1' of git://git.samba.org/sfrench/cifs-2.6 Pull cifs client updates from Steve French: "Eleven cifs/smb3 client fixes: - mostly restructuring to allow disabling less secure algorithms (this will allow eventual removing rc4 and md4 from general use in the kernel) - four fixes, including two for stable - enable r/w support with fscache and cifs.ko I am working on a larger set of changes (the usual ... multichannel, auth and signing improvements), but wanted to get these in earlier to reduce chance of merge conflicts later in the merge window" * tag '5.15-rc-smb3-fixes-part1' of git://git.samba.org/sfrench/cifs-2.6: cifs: Do not leak EDEADLK to dgetents64 for STATUS_USER_SESSION_DELETED cifs: add cifs_common directory to MAINTAINERS file cifs: cifs_md4 convert to SPDX identifier cifs: create a MD4 module and switch cifs.ko to use it cifs: fork arc4 and create a separate module for it for cifs and other users cifs: remove support for NTLM and weaker authentication algorithms cifs: enable fscache usage even for files opened as rw oid_registry: Add OIDs for missing Spnego auth mechanisms to Macs smb3: fix posix extensions mount option cifs: fix wrong release in sess_alloc_buffer() failed path CIFS: Fix a potencially linear read overflow
This commit is contained in:
Коммит
9c849ce86e
|
@ -4629,6 +4629,7 @@ W: http://linux-cifs.samba.org/
|
||||||
T: git git://git.samba.org/sfrench/cifs-2.6.git
|
T: git git://git.samba.org/sfrench/cifs-2.6.git
|
||||||
F: Documentation/admin-guide/cifs/
|
F: Documentation/admin-guide/cifs/
|
||||||
F: fs/cifs/
|
F: fs/cifs/
|
||||||
|
F: fs/cifs_common/
|
||||||
|
|
||||||
COMPACTPCI HOTPLUG CORE
|
COMPACTPCI HOTPLUG CORE
|
||||||
M: Scott Murray <scott@spiteful.org>
|
M: Scott Murray <scott@spiteful.org>
|
||||||
|
|
|
@ -348,8 +348,15 @@ config NFS_V4_2_SSC_HELPER
|
||||||
|
|
||||||
source "net/sunrpc/Kconfig"
|
source "net/sunrpc/Kconfig"
|
||||||
source "fs/ceph/Kconfig"
|
source "fs/ceph/Kconfig"
|
||||||
|
|
||||||
source "fs/cifs/Kconfig"
|
source "fs/cifs/Kconfig"
|
||||||
source "fs/ksmbd/Kconfig"
|
source "fs/ksmbd/Kconfig"
|
||||||
|
|
||||||
|
config CIFS_COMMON
|
||||||
|
tristate
|
||||||
|
default y if CIFS=y
|
||||||
|
default m if CIFS=m
|
||||||
|
|
||||||
source "fs/coda/Kconfig"
|
source "fs/coda/Kconfig"
|
||||||
source "fs/afs/Kconfig"
|
source "fs/afs/Kconfig"
|
||||||
source "fs/9p/Kconfig"
|
source "fs/9p/Kconfig"
|
||||||
|
|
|
@ -96,6 +96,7 @@ obj-$(CONFIG_LOCKD) += lockd/
|
||||||
obj-$(CONFIG_NLS) += nls/
|
obj-$(CONFIG_NLS) += nls/
|
||||||
obj-$(CONFIG_UNICODE) += unicode/
|
obj-$(CONFIG_UNICODE) += unicode/
|
||||||
obj-$(CONFIG_SYSV_FS) += sysv/
|
obj-$(CONFIG_SYSV_FS) += sysv/
|
||||||
|
obj-$(CONFIG_CIFS_COMMON) += cifs_common/
|
||||||
obj-$(CONFIG_CIFS) += cifs/
|
obj-$(CONFIG_CIFS) += cifs/
|
||||||
obj-$(CONFIG_SMB_SERVER) += ksmbd/
|
obj-$(CONFIG_SMB_SERVER) += ksmbd/
|
||||||
obj-$(CONFIG_HPFS_FS) += hpfs/
|
obj-$(CONFIG_HPFS_FS) += hpfs/
|
||||||
|
|
|
@ -4,19 +4,16 @@ config CIFS
|
||||||
depends on INET
|
depends on INET
|
||||||
select NLS
|
select NLS
|
||||||
select CRYPTO
|
select CRYPTO
|
||||||
select CRYPTO_MD4
|
|
||||||
select CRYPTO_MD5
|
select CRYPTO_MD5
|
||||||
select CRYPTO_SHA256
|
select CRYPTO_SHA256
|
||||||
select CRYPTO_SHA512
|
select CRYPTO_SHA512
|
||||||
select CRYPTO_CMAC
|
select CRYPTO_CMAC
|
||||||
select CRYPTO_HMAC
|
select CRYPTO_HMAC
|
||||||
select CRYPTO_LIB_ARC4
|
|
||||||
select CRYPTO_AEAD2
|
select CRYPTO_AEAD2
|
||||||
select CRYPTO_CCM
|
select CRYPTO_CCM
|
||||||
select CRYPTO_GCM
|
select CRYPTO_GCM
|
||||||
select CRYPTO_ECB
|
select CRYPTO_ECB
|
||||||
select CRYPTO_AES
|
select CRYPTO_AES
|
||||||
select CRYPTO_LIB_DES
|
|
||||||
select KEYS
|
select KEYS
|
||||||
select DNS_RESOLVER
|
select DNS_RESOLVER
|
||||||
select ASN1
|
select ASN1
|
||||||
|
@ -85,33 +82,6 @@ config CIFS_ALLOW_INSECURE_LEGACY
|
||||||
|
|
||||||
If unsure, say Y.
|
If unsure, say Y.
|
||||||
|
|
||||||
config CIFS_WEAK_PW_HASH
|
|
||||||
bool "Support legacy servers which use weaker LANMAN security"
|
|
||||||
depends on CIFS && CIFS_ALLOW_INSECURE_LEGACY
|
|
||||||
help
|
|
||||||
Modern CIFS servers including Samba and most Windows versions
|
|
||||||
(since 1997) support stronger NTLM (and even NTLMv2 and Kerberos)
|
|
||||||
security mechanisms. These hash the password more securely
|
|
||||||
than the mechanisms used in the older LANMAN version of the
|
|
||||||
SMB protocol but LANMAN based authentication is needed to
|
|
||||||
establish sessions with some old SMB servers.
|
|
||||||
|
|
||||||
Enabling this option allows the cifs module to mount to older
|
|
||||||
LANMAN based servers such as OS/2 and Windows 95, but such
|
|
||||||
mounts may be less secure than mounts using NTLM or more recent
|
|
||||||
security mechanisms if you are on a public network. Unless you
|
|
||||||
have a need to access old SMB servers (and are on a private
|
|
||||||
network) you probably want to say N. Even if this support
|
|
||||||
is enabled in the kernel build, LANMAN authentication will not be
|
|
||||||
used automatically. At runtime LANMAN mounts are disabled but
|
|
||||||
can be set to required (or optional) either in
|
|
||||||
/proc/fs/cifs (see Documentation/admin-guide/cifs/usage.rst for
|
|
||||||
more detail) or via an option on the mount command. This support
|
|
||||||
is disabled by default in order to reduce the possibility of a
|
|
||||||
downgrade attack.
|
|
||||||
|
|
||||||
If unsure, say N.
|
|
||||||
|
|
||||||
config CIFS_UPCALL
|
config CIFS_UPCALL
|
||||||
bool "Kerberos/SPNEGO advanced session setup"
|
bool "Kerberos/SPNEGO advanced session setup"
|
||||||
depends on CIFS
|
depends on CIFS
|
||||||
|
|
|
@ -250,9 +250,6 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
|
||||||
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
|
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
|
||||||
seq_printf(m, ",ALLOW_INSECURE_LEGACY");
|
seq_printf(m, ",ALLOW_INSECURE_LEGACY");
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
|
||||||
seq_printf(m, ",WEAK_PW_HASH");
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_CIFS_POSIX
|
#ifdef CONFIG_CIFS_POSIX
|
||||||
seq_printf(m, ",CIFS_POSIX");
|
seq_printf(m, ",CIFS_POSIX");
|
||||||
#endif
|
#endif
|
||||||
|
@ -929,14 +926,6 @@ cifs_security_flags_handle_must_flags(unsigned int *flags)
|
||||||
*flags = CIFSSEC_MUST_NTLMSSP;
|
*flags = CIFSSEC_MUST_NTLMSSP;
|
||||||
else if ((*flags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
|
else if ((*flags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
|
||||||
*flags = CIFSSEC_MUST_NTLMV2;
|
*flags = CIFSSEC_MUST_NTLMV2;
|
||||||
else if ((*flags & CIFSSEC_MUST_NTLM) == CIFSSEC_MUST_NTLM)
|
|
||||||
*flags = CIFSSEC_MUST_NTLM;
|
|
||||||
else if (CIFSSEC_MUST_LANMAN &&
|
|
||||||
(*flags & CIFSSEC_MUST_LANMAN) == CIFSSEC_MUST_LANMAN)
|
|
||||||
*flags = CIFSSEC_MUST_LANMAN;
|
|
||||||
else if (CIFSSEC_MUST_PLNTXT &&
|
|
||||||
(*flags & CIFSSEC_MUST_PLNTXT) == CIFSSEC_MUST_PLNTXT)
|
|
||||||
*flags = CIFSSEC_MUST_PLNTXT;
|
|
||||||
|
|
||||||
*flags |= signflags;
|
*flags |= signflags;
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,8 +147,6 @@ static int cifs_swn_send_register_message(struct cifs_swn_reg *swnreg)
|
||||||
goto nlmsg_fail;
|
goto nlmsg_fail;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LANMAN:
|
|
||||||
case NTLM:
|
|
||||||
case NTLMv2:
|
case NTLMv2:
|
||||||
case RawNTLMSSP:
|
case RawNTLMSSP:
|
||||||
ret = cifs_swn_auth_info_ntlm(swnreg->tcon, skb);
|
ret = cifs_swn_auth_info_ntlm(swnreg->tcon, skb);
|
||||||
|
|
|
@ -358,14 +358,9 @@ cifs_strndup_from_utf16(const char *src, const int maxlen,
|
||||||
if (!dst)
|
if (!dst)
|
||||||
return NULL;
|
return NULL;
|
||||||
cifs_from_utf16(dst, (__le16 *) src, len, maxlen, codepage,
|
cifs_from_utf16(dst, (__le16 *) src, len, maxlen, codepage,
|
||||||
NO_MAP_UNI_RSVD);
|
NO_MAP_UNI_RSVD);
|
||||||
} else {
|
} else {
|
||||||
len = strnlen(src, maxlen);
|
dst = kstrndup(src, maxlen, GFP_KERNEL);
|
||||||
len++;
|
|
||||||
dst = kmalloc(len, GFP_KERNEL);
|
|
||||||
if (!dst)
|
|
||||||
return NULL;
|
|
||||||
strlcpy(dst, src, len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return dst;
|
return dst;
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include <linux/random.h>
|
#include <linux/random.h>
|
||||||
#include <linux/highmem.h>
|
#include <linux/highmem.h>
|
||||||
#include <linux/fips.h>
|
#include <linux/fips.h>
|
||||||
#include <crypto/arc4.h>
|
#include "../cifs_common/arc4.h"
|
||||||
#include <crypto/aead.h>
|
#include <crypto/aead.h>
|
||||||
|
|
||||||
int __cifs_calc_signature(struct smb_rqst *rqst,
|
int __cifs_calc_signature(struct smb_rqst *rqst,
|
||||||
|
@ -250,87 +250,6 @@ int cifs_verify_signature(struct smb_rqst *rqst,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* first calculate 24 bytes ntlm response and then 16 byte session key */
|
|
||||||
int setup_ntlm_response(struct cifs_ses *ses, const struct nls_table *nls_cp)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
unsigned int temp_len = CIFS_SESS_KEY_SIZE + CIFS_AUTH_RESP_SIZE;
|
|
||||||
char temp_key[CIFS_SESS_KEY_SIZE];
|
|
||||||
|
|
||||||
if (!ses)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
ses->auth_key.response = kmalloc(temp_len, GFP_KERNEL);
|
|
||||||
if (!ses->auth_key.response)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
ses->auth_key.len = temp_len;
|
|
||||||
|
|
||||||
rc = SMBNTencrypt(ses->password, ses->server->cryptkey,
|
|
||||||
ses->auth_key.response + CIFS_SESS_KEY_SIZE, nls_cp);
|
|
||||||
if (rc) {
|
|
||||||
cifs_dbg(FYI, "%s Can't generate NTLM response, error: %d\n",
|
|
||||||
__func__, rc);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = E_md4hash(ses->password, temp_key, nls_cp);
|
|
||||||
if (rc) {
|
|
||||||
cifs_dbg(FYI, "%s Can't generate NT hash, error: %d\n",
|
|
||||||
__func__, rc);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = mdfour(ses->auth_key.response, temp_key, CIFS_SESS_KEY_SIZE);
|
|
||||||
if (rc)
|
|
||||||
cifs_dbg(FYI, "%s Can't generate NTLM session key, error: %d\n",
|
|
||||||
__func__, rc);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
|
||||||
int calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt,
|
|
||||||
char *lnm_session_key)
|
|
||||||
{
|
|
||||||
int i, len;
|
|
||||||
int rc;
|
|
||||||
char password_with_pad[CIFS_ENCPWD_SIZE] = {0};
|
|
||||||
|
|
||||||
if (password) {
|
|
||||||
for (len = 0; len < CIFS_ENCPWD_SIZE; len++)
|
|
||||||
if (!password[len])
|
|
||||||
break;
|
|
||||||
|
|
||||||
memcpy(password_with_pad, password, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!encrypt && global_secflags & CIFSSEC_MAY_PLNTXT) {
|
|
||||||
memcpy(lnm_session_key, password_with_pad,
|
|
||||||
CIFS_ENCPWD_SIZE);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* calculate old style session key */
|
|
||||||
/* calling toupper is less broken than repeatedly
|
|
||||||
calling nls_toupper would be since that will never
|
|
||||||
work for UTF8, but neither handles multibyte code pages
|
|
||||||
but the only alternative would be converting to UCS-16 (Unicode)
|
|
||||||
(using a routine something like UniStrupr) then
|
|
||||||
uppercasing and then converting back from Unicode - which
|
|
||||||
would only worth doing it if we knew it were utf8. Basically
|
|
||||||
utf8 and other multibyte codepages each need their own strupper
|
|
||||||
function since a byte at a time will ont work. */
|
|
||||||
|
|
||||||
for (i = 0; i < CIFS_ENCPWD_SIZE; i++)
|
|
||||||
password_with_pad[i] = toupper(password_with_pad[i]);
|
|
||||||
|
|
||||||
rc = SMBencrypt(password_with_pad, cryptkey, lnm_session_key);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
#endif /* CIFS_WEAK_PW_HASH */
|
|
||||||
|
|
||||||
/* Build a proper attribute value/target info pairs blob.
|
/* Build a proper attribute value/target info pairs blob.
|
||||||
* Fill in netbios and dns domain name and workstation name
|
* Fill in netbios and dns domain name and workstation name
|
||||||
* and client time (total five av pairs and + one end of fields indicator.
|
* and client time (total five av pairs and + one end of fields indicator.
|
||||||
|
@ -780,9 +699,9 @@ calc_seckey(struct cifs_ses *ses)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
arc4_setkey(ctx_arc4, ses->auth_key.response, CIFS_SESS_KEY_SIZE);
|
cifs_arc4_setkey(ctx_arc4, ses->auth_key.response, CIFS_SESS_KEY_SIZE);
|
||||||
arc4_crypt(ctx_arc4, ses->ntlmssp->ciphertext, sec_key,
|
cifs_arc4_crypt(ctx_arc4, ses->ntlmssp->ciphertext, sec_key,
|
||||||
CIFS_CPHTXT_SIZE);
|
CIFS_CPHTXT_SIZE);
|
||||||
|
|
||||||
/* make secondary_key/nonce as session key */
|
/* make secondary_key/nonce as session key */
|
||||||
memcpy(ses->auth_key.response, sec_key, CIFS_SESS_KEY_SIZE);
|
memcpy(ses->auth_key.response, sec_key, CIFS_SESS_KEY_SIZE);
|
||||||
|
|
|
@ -399,7 +399,6 @@ cifs_evict_inode(struct inode *inode)
|
||||||
{
|
{
|
||||||
truncate_inode_pages_final(&inode->i_data);
|
truncate_inode_pages_final(&inode->i_data);
|
||||||
clear_inode(inode);
|
clear_inode(inode);
|
||||||
cifs_fscache_release_inode_cookie(inode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -438,15 +437,9 @@ cifs_show_security(struct seq_file *s, struct cifs_ses *ses)
|
||||||
seq_puts(s, ",sec=");
|
seq_puts(s, ",sec=");
|
||||||
|
|
||||||
switch (ses->sectype) {
|
switch (ses->sectype) {
|
||||||
case LANMAN:
|
|
||||||
seq_puts(s, "lanman");
|
|
||||||
break;
|
|
||||||
case NTLMv2:
|
case NTLMv2:
|
||||||
seq_puts(s, "ntlmv2");
|
seq_puts(s, "ntlmv2");
|
||||||
break;
|
break;
|
||||||
case NTLM:
|
|
||||||
seq_puts(s, "ntlm");
|
|
||||||
break;
|
|
||||||
case Kerberos:
|
case Kerberos:
|
||||||
seq_puts(s, "krb5");
|
seq_puts(s, "krb5");
|
||||||
break;
|
break;
|
||||||
|
@ -1755,7 +1748,6 @@ MODULE_DESCRIPTION
|
||||||
MODULE_VERSION(CIFS_VERSION);
|
MODULE_VERSION(CIFS_VERSION);
|
||||||
MODULE_SOFTDEP("ecb");
|
MODULE_SOFTDEP("ecb");
|
||||||
MODULE_SOFTDEP("hmac");
|
MODULE_SOFTDEP("hmac");
|
||||||
MODULE_SOFTDEP("md4");
|
|
||||||
MODULE_SOFTDEP("md5");
|
MODULE_SOFTDEP("md5");
|
||||||
MODULE_SOFTDEP("nls");
|
MODULE_SOFTDEP("nls");
|
||||||
MODULE_SOFTDEP("aes");
|
MODULE_SOFTDEP("aes");
|
||||||
|
|
|
@ -114,8 +114,6 @@ enum statusEnum {
|
||||||
|
|
||||||
enum securityEnum {
|
enum securityEnum {
|
||||||
Unspecified = 0, /* not specified */
|
Unspecified = 0, /* not specified */
|
||||||
LANMAN, /* Legacy LANMAN auth */
|
|
||||||
NTLM, /* Legacy NTLM012 auth with NTLM hash */
|
|
||||||
NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
|
NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
|
||||||
RawNTLMSSP, /* NTLMSSP without SPNEGO, NTLMv2 hash */
|
RawNTLMSSP, /* NTLMSSP without SPNEGO, NTLMv2 hash */
|
||||||
Kerberos, /* Kerberos via SPNEGO */
|
Kerberos, /* Kerberos via SPNEGO */
|
||||||
|
@ -634,7 +632,6 @@ struct TCP_Server_Info {
|
||||||
struct session_key session_key;
|
struct session_key session_key;
|
||||||
unsigned long lstrp; /* when we got last response from this server */
|
unsigned long lstrp; /* when we got last response from this server */
|
||||||
struct cifs_secmech secmech; /* crypto sec mech functs, descriptors */
|
struct cifs_secmech secmech; /* crypto sec mech functs, descriptors */
|
||||||
#define CIFS_NEGFLAVOR_LANMAN 0 /* wct == 13, LANMAN */
|
|
||||||
#define CIFS_NEGFLAVOR_UNENCAP 1 /* wct == 17, but no ext_sec */
|
#define CIFS_NEGFLAVOR_UNENCAP 1 /* wct == 17, but no ext_sec */
|
||||||
#define CIFS_NEGFLAVOR_EXTENDED 2 /* wct == 17, ext_sec bit set */
|
#define CIFS_NEGFLAVOR_EXTENDED 2 /* wct == 17, ext_sec bit set */
|
||||||
char negflavor; /* NEGOTIATE response flavor */
|
char negflavor; /* NEGOTIATE response flavor */
|
||||||
|
@ -1734,16 +1731,8 @@ static inline bool is_retryable_error(int error)
|
||||||
|
|
||||||
/* Security Flags: indicate type of session setup needed */
|
/* Security Flags: indicate type of session setup needed */
|
||||||
#define CIFSSEC_MAY_SIGN 0x00001
|
#define CIFSSEC_MAY_SIGN 0x00001
|
||||||
#define CIFSSEC_MAY_NTLM 0x00002
|
|
||||||
#define CIFSSEC_MAY_NTLMV2 0x00004
|
#define CIFSSEC_MAY_NTLMV2 0x00004
|
||||||
#define CIFSSEC_MAY_KRB5 0x00008
|
#define CIFSSEC_MAY_KRB5 0x00008
|
||||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
|
||||||
#define CIFSSEC_MAY_LANMAN 0x00010
|
|
||||||
#define CIFSSEC_MAY_PLNTXT 0x00020
|
|
||||||
#else
|
|
||||||
#define CIFSSEC_MAY_LANMAN 0
|
|
||||||
#define CIFSSEC_MAY_PLNTXT 0
|
|
||||||
#endif /* weak passwords */
|
|
||||||
#define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */
|
#define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */
|
||||||
#define CIFSSEC_MAY_NTLMSSP 0x00080 /* raw ntlmssp with ntlmv2 */
|
#define CIFSSEC_MAY_NTLMSSP 0x00080 /* raw ntlmssp with ntlmv2 */
|
||||||
|
|
||||||
|
@ -1751,32 +1740,19 @@ static inline bool is_retryable_error(int error)
|
||||||
/* note that only one of the following can be set so the
|
/* note that only one of the following can be set so the
|
||||||
result of setting MUST flags more than once will be to
|
result of setting MUST flags more than once will be to
|
||||||
require use of the stronger protocol */
|
require use of the stronger protocol */
|
||||||
#define CIFSSEC_MUST_NTLM 0x02002
|
|
||||||
#define CIFSSEC_MUST_NTLMV2 0x04004
|
#define CIFSSEC_MUST_NTLMV2 0x04004
|
||||||
#define CIFSSEC_MUST_KRB5 0x08008
|
#define CIFSSEC_MUST_KRB5 0x08008
|
||||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
|
||||||
#define CIFSSEC_MUST_LANMAN 0x10010
|
|
||||||
#define CIFSSEC_MUST_PLNTXT 0x20020
|
|
||||||
#ifdef CONFIG_CIFS_UPCALL
|
|
||||||
#define CIFSSEC_MASK 0xBF0BF /* allows weak security but also krb5 */
|
|
||||||
#else
|
|
||||||
#define CIFSSEC_MASK 0xB70B7 /* current flags supported if weak */
|
|
||||||
#endif /* UPCALL */
|
|
||||||
#else /* do not allow weak pw hash */
|
|
||||||
#define CIFSSEC_MUST_LANMAN 0
|
|
||||||
#define CIFSSEC_MUST_PLNTXT 0
|
|
||||||
#ifdef CONFIG_CIFS_UPCALL
|
#ifdef CONFIG_CIFS_UPCALL
|
||||||
#define CIFSSEC_MASK 0x8F08F /* flags supported if no weak allowed */
|
#define CIFSSEC_MASK 0x8F08F /* flags supported if no weak allowed */
|
||||||
#else
|
#else
|
||||||
#define CIFSSEC_MASK 0x87087 /* flags supported if no weak allowed */
|
#define CIFSSEC_MASK 0x87087 /* flags supported if no weak allowed */
|
||||||
#endif /* UPCALL */
|
#endif /* UPCALL */
|
||||||
#endif /* WEAK_PW_HASH */
|
|
||||||
#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */
|
#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */
|
||||||
#define CIFSSEC_MUST_NTLMSSP 0x80080 /* raw ntlmssp with ntlmv2 */
|
#define CIFSSEC_MUST_NTLMSSP 0x80080 /* raw ntlmssp with ntlmv2 */
|
||||||
|
|
||||||
#define CIFSSEC_DEF (CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_NTLMSSP)
|
#define CIFSSEC_DEF (CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_NTLMSSP)
|
||||||
#define CIFSSEC_MAX (CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2)
|
#define CIFSSEC_MAX (CIFSSEC_MUST_NTLMV2)
|
||||||
#define CIFSSEC_AUTH_MASK (CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_LANMAN | CIFSSEC_MAY_PLNTXT | CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP)
|
#define CIFSSEC_AUTH_MASK (CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP)
|
||||||
/*
|
/*
|
||||||
*****************************************************************
|
*****************************************************************
|
||||||
* All constants go here
|
* All constants go here
|
||||||
|
@ -1940,10 +1916,6 @@ static inline char *get_security_type_str(enum securityEnum sectype)
|
||||||
return "Kerberos";
|
return "Kerberos";
|
||||||
case NTLMv2:
|
case NTLMv2:
|
||||||
return "NTLMv2";
|
return "NTLMv2";
|
||||||
case NTLM:
|
|
||||||
return "NTLM";
|
|
||||||
case LANMAN:
|
|
||||||
return "LANMAN";
|
|
||||||
default:
|
default:
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,13 +14,7 @@
|
||||||
#include <asm/unaligned.h>
|
#include <asm/unaligned.h>
|
||||||
#include "smbfsctl.h"
|
#include "smbfsctl.h"
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
|
||||||
#define LANMAN_PROT 0
|
|
||||||
#define LANMAN2_PROT 1
|
|
||||||
#define CIFS_PROT 2
|
|
||||||
#else
|
|
||||||
#define CIFS_PROT 0
|
#define CIFS_PROT 0
|
||||||
#endif
|
|
||||||
#define POSIX_PROT (CIFS_PROT+1)
|
#define POSIX_PROT (CIFS_PROT+1)
|
||||||
#define BAD_PROT 0xFFFF
|
#define BAD_PROT 0xFFFF
|
||||||
|
|
||||||
|
@ -505,30 +499,8 @@ typedef struct negotiate_req {
|
||||||
unsigned char DialectsArray[1];
|
unsigned char DialectsArray[1];
|
||||||
} __attribute__((packed)) NEGOTIATE_REQ;
|
} __attribute__((packed)) NEGOTIATE_REQ;
|
||||||
|
|
||||||
/* Dialect index is 13 for LANMAN */
|
|
||||||
|
|
||||||
#define MIN_TZ_ADJ (15 * 60) /* minimum grid for timezones in seconds */
|
#define MIN_TZ_ADJ (15 * 60) /* minimum grid for timezones in seconds */
|
||||||
|
|
||||||
typedef struct lanman_neg_rsp {
|
|
||||||
struct smb_hdr hdr; /* wct = 13 */
|
|
||||||
__le16 DialectIndex;
|
|
||||||
__le16 SecurityMode;
|
|
||||||
__le16 MaxBufSize;
|
|
||||||
__le16 MaxMpxCount;
|
|
||||||
__le16 MaxNumberVcs;
|
|
||||||
__le16 RawMode;
|
|
||||||
__le32 SessionKey;
|
|
||||||
struct {
|
|
||||||
__le16 Time;
|
|
||||||
__le16 Date;
|
|
||||||
} __attribute__((packed)) SrvTime;
|
|
||||||
__le16 ServerTimeZone;
|
|
||||||
__le16 EncryptionKeyLength;
|
|
||||||
__le16 Reserved;
|
|
||||||
__u16 ByteCount;
|
|
||||||
unsigned char EncryptionKey[1];
|
|
||||||
} __attribute__((packed)) LANMAN_NEG_RSP;
|
|
||||||
|
|
||||||
#define READ_RAW_ENABLE 1
|
#define READ_RAW_ENABLE 1
|
||||||
#define WRITE_RAW_ENABLE 2
|
#define WRITE_RAW_ENABLE 2
|
||||||
#define RAW_ENABLE (READ_RAW_ENABLE | WRITE_RAW_ENABLE)
|
#define RAW_ENABLE (READ_RAW_ENABLE | WRITE_RAW_ENABLE)
|
||||||
|
|
|
@ -498,19 +498,12 @@ extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *);
|
||||||
extern int cifs_verify_signature(struct smb_rqst *rqst,
|
extern int cifs_verify_signature(struct smb_rqst *rqst,
|
||||||
struct TCP_Server_Info *server,
|
struct TCP_Server_Info *server,
|
||||||
__u32 expected_sequence_number);
|
__u32 expected_sequence_number);
|
||||||
extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *,
|
|
||||||
const struct nls_table *);
|
|
||||||
extern int setup_ntlm_response(struct cifs_ses *, const struct nls_table *);
|
|
||||||
extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *);
|
extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *);
|
||||||
extern void cifs_crypto_secmech_release(struct TCP_Server_Info *server);
|
extern void cifs_crypto_secmech_release(struct TCP_Server_Info *server);
|
||||||
extern int calc_seckey(struct cifs_ses *);
|
extern int calc_seckey(struct cifs_ses *);
|
||||||
extern int generate_smb30signingkey(struct cifs_ses *);
|
extern int generate_smb30signingkey(struct cifs_ses *);
|
||||||
extern int generate_smb311signingkey(struct cifs_ses *);
|
extern int generate_smb311signingkey(struct cifs_ses *);
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
|
||||||
extern int calc_lanman_hash(const char *password, const char *cryptkey,
|
|
||||||
bool encrypt, char *lnm_session_key);
|
|
||||||
#endif /* CIFS_WEAK_PW_HASH */
|
|
||||||
extern int CIFSSMBCopy(unsigned int xid,
|
extern int CIFSSMBCopy(unsigned int xid,
|
||||||
struct cifs_tcon *source_tcon,
|
struct cifs_tcon *source_tcon,
|
||||||
const char *fromName,
|
const char *fromName,
|
||||||
|
@ -547,11 +540,8 @@ extern int check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
|
||||||
struct cifs_sb_info *cifs_sb,
|
struct cifs_sb_info *cifs_sb,
|
||||||
struct cifs_fattr *fattr,
|
struct cifs_fattr *fattr,
|
||||||
const unsigned char *path);
|
const unsigned char *path);
|
||||||
extern int mdfour(unsigned char *, unsigned char *, int);
|
|
||||||
extern int E_md4hash(const unsigned char *passwd, unsigned char *p16,
|
extern int E_md4hash(const unsigned char *passwd, unsigned char *p16,
|
||||||
const struct nls_table *codepage);
|
const struct nls_table *codepage);
|
||||||
extern int SMBencrypt(unsigned char *passwd, const unsigned char *c8,
|
|
||||||
unsigned char *p24);
|
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
cifs_setup_volume_info(struct smb3_fs_context *ctx, const char *mntopts, const char *devname);
|
cifs_setup_volume_info(struct smb3_fs_context *ctx, const char *mntopts, const char *devname);
|
||||||
|
|
|
@ -42,10 +42,6 @@ static struct {
|
||||||
int index;
|
int index;
|
||||||
char *name;
|
char *name;
|
||||||
} protocols[] = {
|
} protocols[] = {
|
||||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
|
||||||
{LANMAN_PROT, "\2LM1.2X002"},
|
|
||||||
{LANMAN2_PROT, "\2LANMAN2.1"},
|
|
||||||
#endif /* weak password hashing for legacy clients */
|
|
||||||
{CIFS_PROT, "\2NT LM 0.12"},
|
{CIFS_PROT, "\2NT LM 0.12"},
|
||||||
{POSIX_PROT, "\2POSIX 2"},
|
{POSIX_PROT, "\2POSIX 2"},
|
||||||
{BAD_PROT, "\2"}
|
{BAD_PROT, "\2"}
|
||||||
|
@ -55,10 +51,6 @@ static struct {
|
||||||
int index;
|
int index;
|
||||||
char *name;
|
char *name;
|
||||||
} protocols[] = {
|
} protocols[] = {
|
||||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
|
||||||
{LANMAN_PROT, "\2LM1.2X002"},
|
|
||||||
{LANMAN2_PROT, "\2LANMAN2.1"},
|
|
||||||
#endif /* weak password hashing for legacy clients */
|
|
||||||
{CIFS_PROT, "\2NT LM 0.12"},
|
{CIFS_PROT, "\2NT LM 0.12"},
|
||||||
{BAD_PROT, "\2"}
|
{BAD_PROT, "\2"}
|
||||||
};
|
};
|
||||||
|
@ -66,17 +58,9 @@ static struct {
|
||||||
|
|
||||||
/* define the number of elements in the cifs dialect array */
|
/* define the number of elements in the cifs dialect array */
|
||||||
#ifdef CONFIG_CIFS_POSIX
|
#ifdef CONFIG_CIFS_POSIX
|
||||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
|
||||||
#define CIFS_NUM_PROT 4
|
|
||||||
#else
|
|
||||||
#define CIFS_NUM_PROT 2
|
#define CIFS_NUM_PROT 2
|
||||||
#endif /* CIFS_WEAK_PW_HASH */
|
|
||||||
#else /* not posix */
|
#else /* not posix */
|
||||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
|
||||||
#define CIFS_NUM_PROT 3
|
|
||||||
#else
|
|
||||||
#define CIFS_NUM_PROT 1
|
#define CIFS_NUM_PROT 1
|
||||||
#endif /* CONFIG_CIFS_WEAK_PW_HASH */
|
|
||||||
#endif /* CIFS_POSIX */
|
#endif /* CIFS_POSIX */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -475,89 +459,6 @@ cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
|
||||||
static int
|
|
||||||
decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
|
|
||||||
{
|
|
||||||
__s16 tmp;
|
|
||||||
struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
|
|
||||||
|
|
||||||
if (server->dialect != LANMAN_PROT && server->dialect != LANMAN2_PROT)
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
|
|
||||||
server->sec_mode = le16_to_cpu(rsp->SecurityMode);
|
|
||||||
server->maxReq = min_t(unsigned int,
|
|
||||||
le16_to_cpu(rsp->MaxMpxCount),
|
|
||||||
cifs_max_pending);
|
|
||||||
set_credits(server, server->maxReq);
|
|
||||||
server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
|
|
||||||
/* set up max_read for readpages check */
|
|
||||||
server->max_read = server->maxBuf;
|
|
||||||
/* even though we do not use raw we might as well set this
|
|
||||||
accurately, in case we ever find a need for it */
|
|
||||||
if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
|
|
||||||
server->max_rw = 0xFF00;
|
|
||||||
server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
|
|
||||||
} else {
|
|
||||||
server->max_rw = 0;/* do not need to use raw anyway */
|
|
||||||
server->capabilities = CAP_MPX_MODE;
|
|
||||||
}
|
|
||||||
tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
|
|
||||||
if (tmp == -1) {
|
|
||||||
/* OS/2 often does not set timezone therefore
|
|
||||||
* we must use server time to calc time zone.
|
|
||||||
* Could deviate slightly from the right zone.
|
|
||||||
* Smallest defined timezone difference is 15 minutes
|
|
||||||
* (i.e. Nepal). Rounding up/down is done to match
|
|
||||||
* this requirement.
|
|
||||||
*/
|
|
||||||
int val, seconds, remain, result;
|
|
||||||
struct timespec64 ts;
|
|
||||||
time64_t utc = ktime_get_real_seconds();
|
|
||||||
ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
|
|
||||||
rsp->SrvTime.Time, 0);
|
|
||||||
cifs_dbg(FYI, "SrvTime %lld sec since 1970 (utc: %lld) diff: %lld\n",
|
|
||||||
ts.tv_sec, utc,
|
|
||||||
utc - ts.tv_sec);
|
|
||||||
val = (int)(utc - ts.tv_sec);
|
|
||||||
seconds = abs(val);
|
|
||||||
result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
|
|
||||||
remain = seconds % MIN_TZ_ADJ;
|
|
||||||
if (remain >= (MIN_TZ_ADJ / 2))
|
|
||||||
result += MIN_TZ_ADJ;
|
|
||||||
if (val < 0)
|
|
||||||
result = -result;
|
|
||||||
server->timeAdj = result;
|
|
||||||
} else {
|
|
||||||
server->timeAdj = (int)tmp;
|
|
||||||
server->timeAdj *= 60; /* also in seconds */
|
|
||||||
}
|
|
||||||
cifs_dbg(FYI, "server->timeAdj: %d seconds\n", server->timeAdj);
|
|
||||||
|
|
||||||
|
|
||||||
/* BB get server time for time conversions and add
|
|
||||||
code to use it and timezone since this is not UTC */
|
|
||||||
|
|
||||||
if (rsp->EncryptionKeyLength ==
|
|
||||||
cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
|
|
||||||
memcpy(server->cryptkey, rsp->EncryptionKey,
|
|
||||||
CIFS_CRYPTO_KEY_SIZE);
|
|
||||||
} else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
|
|
||||||
return -EIO; /* need cryptkey unless plain text */
|
|
||||||
}
|
|
||||||
|
|
||||||
cifs_dbg(FYI, "LANMAN negotiated\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
static inline int
|
|
||||||
decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
|
|
||||||
{
|
|
||||||
cifs_dbg(VFS, "mount failed, cifs module not built with CIFS_WEAK_PW_HASH support\n");
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
should_set_ext_sec_flag(enum securityEnum sectype)
|
should_set_ext_sec_flag(enum securityEnum sectype)
|
||||||
{
|
{
|
||||||
|
@ -626,16 +527,12 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
|
||||||
server->dialect = le16_to_cpu(pSMBr->DialectIndex);
|
server->dialect = le16_to_cpu(pSMBr->DialectIndex);
|
||||||
cifs_dbg(FYI, "Dialect: %d\n", server->dialect);
|
cifs_dbg(FYI, "Dialect: %d\n", server->dialect);
|
||||||
/* Check wct = 1 error case */
|
/* Check wct = 1 error case */
|
||||||
if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
|
if ((pSMBr->hdr.WordCount <= 13) || (server->dialect == BAD_PROT)) {
|
||||||
/* core returns wct = 1, but we do not ask for core - otherwise
|
/* core returns wct = 1, but we do not ask for core - otherwise
|
||||||
small wct just comes when dialect index is -1 indicating we
|
small wct just comes when dialect index is -1 indicating we
|
||||||
could not negotiate a common dialect */
|
could not negotiate a common dialect */
|
||||||
rc = -EOPNOTSUPP;
|
rc = -EOPNOTSUPP;
|
||||||
goto neg_err_exit;
|
goto neg_err_exit;
|
||||||
} else if (pSMBr->hdr.WordCount == 13) {
|
|
||||||
server->negflavor = CIFS_NEGFLAVOR_LANMAN;
|
|
||||||
rc = decode_lanman_negprot_rsp(server, pSMBr);
|
|
||||||
goto signing_check;
|
|
||||||
} else if (pSMBr->hdr.WordCount != 17) {
|
} else if (pSMBr->hdr.WordCount != 17) {
|
||||||
/* unknown wct */
|
/* unknown wct */
|
||||||
rc = -EOPNOTSUPP;
|
rc = -EOPNOTSUPP;
|
||||||
|
@ -677,7 +574,6 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
|
||||||
server->capabilities &= ~CAP_EXTENDED_SECURITY;
|
server->capabilities &= ~CAP_EXTENDED_SECURITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
signing_check:
|
|
||||||
if (!rc)
|
if (!rc)
|
||||||
rc = cifs_enable_signing(server, ses->sign);
|
rc = cifs_enable_signing(server, ses->sign);
|
||||||
neg_err_exit:
|
neg_err_exit:
|
||||||
|
@ -2101,6 +1997,7 @@ cifs_writev_complete(struct work_struct *work)
|
||||||
else if (wdata->result < 0)
|
else if (wdata->result < 0)
|
||||||
SetPageError(page);
|
SetPageError(page);
|
||||||
end_page_writeback(page);
|
end_page_writeback(page);
|
||||||
|
cifs_readpage_to_fscache(inode, page);
|
||||||
put_page(page);
|
put_page(page);
|
||||||
}
|
}
|
||||||
if (wdata->result != -EAGAIN)
|
if (wdata->result != -EAGAIN)
|
||||||
|
|
|
@ -3684,38 +3684,6 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
|
||||||
*bcc_ptr = 0; /* password is null byte */
|
*bcc_ptr = 0; /* password is null byte */
|
||||||
bcc_ptr++; /* skip password */
|
bcc_ptr++; /* skip password */
|
||||||
/* already aligned so no need to do it below */
|
/* already aligned so no need to do it below */
|
||||||
} else {
|
|
||||||
pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
|
|
||||||
/* BB FIXME add code to fail this if NTLMv2 or Kerberos
|
|
||||||
specified as required (when that support is added to
|
|
||||||
the vfs in the future) as only NTLM or the much
|
|
||||||
weaker LANMAN (which we do not send by default) is accepted
|
|
||||||
by Samba (not sure whether other servers allow
|
|
||||||
NTLMv2 password here) */
|
|
||||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
|
||||||
if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
|
|
||||||
(ses->sectype == LANMAN))
|
|
||||||
calc_lanman_hash(tcon->password, ses->server->cryptkey,
|
|
||||||
ses->server->sec_mode &
|
|
||||||
SECMODE_PW_ENCRYPT ? true : false,
|
|
||||||
bcc_ptr);
|
|
||||||
else
|
|
||||||
#endif /* CIFS_WEAK_PW_HASH */
|
|
||||||
rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
|
|
||||||
bcc_ptr, nls_codepage);
|
|
||||||
if (rc) {
|
|
||||||
cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
|
|
||||||
__func__, rc);
|
|
||||||
cifs_buf_release(smb_buffer);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
bcc_ptr += CIFS_AUTH_RESP_SIZE;
|
|
||||||
if (ses->capabilities & CAP_UNICODE) {
|
|
||||||
/* must align unicode strings */
|
|
||||||
*bcc_ptr = 0; /* null byte password */
|
|
||||||
bcc_ptr++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ses->server->sign)
|
if (ses->server->sign)
|
||||||
|
|
|
@ -377,6 +377,8 @@ static void cifsFileInfo_put_final(struct cifsFileInfo *cifs_file)
|
||||||
struct cifsLockInfo *li, *tmp;
|
struct cifsLockInfo *li, *tmp;
|
||||||
struct super_block *sb = inode->i_sb;
|
struct super_block *sb = inode->i_sb;
|
||||||
|
|
||||||
|
cifs_fscache_release_inode_cookie(inode);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Delete any outstanding lock records. We'll lose them when the file
|
* Delete any outstanding lock records. We'll lose them when the file
|
||||||
* is closed anyway.
|
* is closed anyway.
|
||||||
|
@ -882,8 +884,10 @@ int cifs_close(struct inode *inode, struct file *file)
|
||||||
if ((cinode->oplock == CIFS_CACHE_RHW_FLG) &&
|
if ((cinode->oplock == CIFS_CACHE_RHW_FLG) &&
|
||||||
cinode->lease_granted &&
|
cinode->lease_granted &&
|
||||||
dclose) {
|
dclose) {
|
||||||
if (test_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags))
|
if (test_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags)) {
|
||||||
inode->i_ctime = inode->i_mtime = current_time(inode);
|
inode->i_ctime = inode->i_mtime = current_time(inode);
|
||||||
|
cifs_fscache_update_inode_cookie(inode);
|
||||||
|
}
|
||||||
spin_lock(&cinode->deferred_lock);
|
spin_lock(&cinode->deferred_lock);
|
||||||
cifs_add_deferred_close(cfile, dclose);
|
cifs_add_deferred_close(cfile, dclose);
|
||||||
if (cfile->deferred_close_scheduled &&
|
if (cfile->deferred_close_scheduled &&
|
||||||
|
@ -4170,6 +4174,10 @@ static vm_fault_t
|
||||||
cifs_page_mkwrite(struct vm_fault *vmf)
|
cifs_page_mkwrite(struct vm_fault *vmf)
|
||||||
{
|
{
|
||||||
struct page *page = vmf->page;
|
struct page *page = vmf->page;
|
||||||
|
struct file *file = vmf->vma->vm_file;
|
||||||
|
struct inode *inode = file_inode(file);
|
||||||
|
|
||||||
|
cifs_fscache_wait_on_page_write(inode, page);
|
||||||
|
|
||||||
lock_page(page);
|
lock_page(page);
|
||||||
return VM_FAULT_LOCKED;
|
return VM_FAULT_LOCKED;
|
||||||
|
@ -4235,13 +4243,16 @@ cifs_readv_complete(struct work_struct *work)
|
||||||
(rdata->result == -EAGAIN && got_bytes)) {
|
(rdata->result == -EAGAIN && got_bytes)) {
|
||||||
flush_dcache_page(page);
|
flush_dcache_page(page);
|
||||||
SetPageUptodate(page);
|
SetPageUptodate(page);
|
||||||
}
|
} else
|
||||||
|
SetPageError(page);
|
||||||
|
|
||||||
unlock_page(page);
|
unlock_page(page);
|
||||||
|
|
||||||
if (rdata->result == 0 ||
|
if (rdata->result == 0 ||
|
||||||
(rdata->result == -EAGAIN && got_bytes))
|
(rdata->result == -EAGAIN && got_bytes))
|
||||||
cifs_readpage_to_fscache(rdata->mapping->host, page);
|
cifs_readpage_to_fscache(rdata->mapping->host, page);
|
||||||
|
else
|
||||||
|
cifs_fscache_uncache_page(rdata->mapping->host, page);
|
||||||
|
|
||||||
got_bytes -= min_t(unsigned int, PAGE_SIZE, got_bytes);
|
got_bytes -= min_t(unsigned int, PAGE_SIZE, got_bytes);
|
||||||
|
|
||||||
|
|
|
@ -57,12 +57,9 @@ static const match_table_t cifs_secflavor_tokens = {
|
||||||
{ Opt_sec_krb5p, "krb5p" },
|
{ Opt_sec_krb5p, "krb5p" },
|
||||||
{ Opt_sec_ntlmsspi, "ntlmsspi" },
|
{ Opt_sec_ntlmsspi, "ntlmsspi" },
|
||||||
{ Opt_sec_ntlmssp, "ntlmssp" },
|
{ Opt_sec_ntlmssp, "ntlmssp" },
|
||||||
{ Opt_ntlm, "ntlm" },
|
|
||||||
{ Opt_sec_ntlmi, "ntlmi" },
|
|
||||||
{ Opt_sec_ntlmv2, "nontlm" },
|
{ Opt_sec_ntlmv2, "nontlm" },
|
||||||
{ Opt_sec_ntlmv2, "ntlmv2" },
|
{ Opt_sec_ntlmv2, "ntlmv2" },
|
||||||
{ Opt_sec_ntlmv2i, "ntlmv2i" },
|
{ Opt_sec_ntlmv2i, "ntlmv2i" },
|
||||||
{ Opt_sec_lanman, "lanman" },
|
|
||||||
{ Opt_sec_none, "none" },
|
{ Opt_sec_none, "none" },
|
||||||
|
|
||||||
{ Opt_sec_err, NULL }
|
{ Opt_sec_err, NULL }
|
||||||
|
@ -221,23 +218,12 @@ cifs_parse_security_flavors(struct fs_context *fc, char *value, struct smb3_fs_c
|
||||||
case Opt_sec_ntlmssp:
|
case Opt_sec_ntlmssp:
|
||||||
ctx->sectype = RawNTLMSSP;
|
ctx->sectype = RawNTLMSSP;
|
||||||
break;
|
break;
|
||||||
case Opt_sec_ntlmi:
|
|
||||||
ctx->sign = true;
|
|
||||||
fallthrough;
|
|
||||||
case Opt_ntlm:
|
|
||||||
ctx->sectype = NTLM;
|
|
||||||
break;
|
|
||||||
case Opt_sec_ntlmv2i:
|
case Opt_sec_ntlmv2i:
|
||||||
ctx->sign = true;
|
ctx->sign = true;
|
||||||
fallthrough;
|
fallthrough;
|
||||||
case Opt_sec_ntlmv2:
|
case Opt_sec_ntlmv2:
|
||||||
ctx->sectype = NTLMv2;
|
ctx->sectype = NTLMv2;
|
||||||
break;
|
break;
|
||||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
|
||||||
case Opt_sec_lanman:
|
|
||||||
ctx->sectype = LANMAN;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case Opt_sec_none:
|
case Opt_sec_none:
|
||||||
ctx->nullauth = 1;
|
ctx->nullauth = 1;
|
||||||
break;
|
break;
|
||||||
|
@ -1266,10 +1252,17 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
|
||||||
ctx->posix_paths = 1;
|
ctx->posix_paths = 1;
|
||||||
break;
|
break;
|
||||||
case Opt_unix:
|
case Opt_unix:
|
||||||
if (result.negated)
|
if (result.negated) {
|
||||||
|
if (ctx->linux_ext == 1)
|
||||||
|
pr_warn_once("conflicting posix mount options specified\n");
|
||||||
ctx->linux_ext = 0;
|
ctx->linux_ext = 0;
|
||||||
else
|
|
||||||
ctx->no_linux_ext = 1;
|
ctx->no_linux_ext = 1;
|
||||||
|
} else {
|
||||||
|
if (ctx->no_linux_ext == 1)
|
||||||
|
pr_warn_once("conflicting posix mount options specified\n");
|
||||||
|
ctx->linux_ext = 1;
|
||||||
|
ctx->no_linux_ext = 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case Opt_nocase:
|
case Opt_nocase:
|
||||||
ctx->nocase = 1;
|
ctx->nocase = 1;
|
||||||
|
|
|
@ -47,11 +47,8 @@ enum cifs_sec_param {
|
||||||
Opt_sec_krb5p,
|
Opt_sec_krb5p,
|
||||||
Opt_sec_ntlmsspi,
|
Opt_sec_ntlmsspi,
|
||||||
Opt_sec_ntlmssp,
|
Opt_sec_ntlmssp,
|
||||||
Opt_ntlm,
|
|
||||||
Opt_sec_ntlmi,
|
|
||||||
Opt_sec_ntlmv2,
|
Opt_sec_ntlmv2,
|
||||||
Opt_sec_ntlmv2i,
|
Opt_sec_ntlmv2i,
|
||||||
Opt_sec_lanman,
|
|
||||||
Opt_sec_none,
|
Opt_sec_none,
|
||||||
|
|
||||||
Opt_sec_err
|
Opt_sec_err
|
||||||
|
|
|
@ -176,29 +176,34 @@ void cifs_fscache_release_inode_cookie(struct inode *inode)
|
||||||
auxdata.last_change_time_nsec = cifsi->vfs_inode.i_ctime.tv_nsec;
|
auxdata.last_change_time_nsec = cifsi->vfs_inode.i_ctime.tv_nsec;
|
||||||
|
|
||||||
cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cifsi->fscache);
|
cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cifsi->fscache);
|
||||||
|
/* fscache_relinquish_cookie does not seem to update auxdata */
|
||||||
|
fscache_update_cookie(cifsi->fscache, &auxdata);
|
||||||
fscache_relinquish_cookie(cifsi->fscache, &auxdata, false);
|
fscache_relinquish_cookie(cifsi->fscache, &auxdata, false);
|
||||||
cifsi->fscache = NULL;
|
cifsi->fscache = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cifs_fscache_disable_inode_cookie(struct inode *inode)
|
void cifs_fscache_update_inode_cookie(struct inode *inode)
|
||||||
{
|
{
|
||||||
|
struct cifs_fscache_inode_auxdata auxdata;
|
||||||
struct cifsInodeInfo *cifsi = CIFS_I(inode);
|
struct cifsInodeInfo *cifsi = CIFS_I(inode);
|
||||||
|
|
||||||
if (cifsi->fscache) {
|
if (cifsi->fscache) {
|
||||||
|
memset(&auxdata, 0, sizeof(auxdata));
|
||||||
|
auxdata.eof = cifsi->server_eof;
|
||||||
|
auxdata.last_write_time_sec = cifsi->vfs_inode.i_mtime.tv_sec;
|
||||||
|
auxdata.last_change_time_sec = cifsi->vfs_inode.i_ctime.tv_sec;
|
||||||
|
auxdata.last_write_time_nsec = cifsi->vfs_inode.i_mtime.tv_nsec;
|
||||||
|
auxdata.last_change_time_nsec = cifsi->vfs_inode.i_ctime.tv_nsec;
|
||||||
|
|
||||||
cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cifsi->fscache);
|
cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cifsi->fscache);
|
||||||
fscache_uncache_all_inode_pages(cifsi->fscache, inode);
|
fscache_update_cookie(cifsi->fscache, &auxdata);
|
||||||
fscache_relinquish_cookie(cifsi->fscache, NULL, true);
|
|
||||||
cifsi->fscache = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cifs_fscache_set_inode_cookie(struct inode *inode, struct file *filp)
|
void cifs_fscache_set_inode_cookie(struct inode *inode, struct file *filp)
|
||||||
{
|
{
|
||||||
if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
|
cifs_fscache_enable_inode_cookie(inode);
|
||||||
cifs_fscache_disable_inode_cookie(inode);
|
|
||||||
else
|
|
||||||
cifs_fscache_enable_inode_cookie(inode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cifs_fscache_reset_inode_cookie(struct inode *inode)
|
void cifs_fscache_reset_inode_cookie(struct inode *inode)
|
||||||
|
@ -310,6 +315,8 @@ void __cifs_readpage_to_fscache(struct inode *inode, struct page *page)
|
||||||
struct cifsInodeInfo *cifsi = CIFS_I(inode);
|
struct cifsInodeInfo *cifsi = CIFS_I(inode);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
WARN_ON(!cifsi->fscache);
|
||||||
|
|
||||||
cifs_dbg(FYI, "%s: (fsc: %p, p: %p, i: %p)\n",
|
cifs_dbg(FYI, "%s: (fsc: %p, p: %p, i: %p)\n",
|
||||||
__func__, cifsi->fscache, page, inode);
|
__func__, cifsi->fscache, page, inode);
|
||||||
ret = fscache_write_page(cifsi->fscache, page,
|
ret = fscache_write_page(cifsi->fscache, page,
|
||||||
|
@ -334,3 +341,21 @@ void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode)
|
||||||
fscache_wait_on_page_write(cookie, page);
|
fscache_wait_on_page_write(cookie, page);
|
||||||
fscache_uncache_page(cookie, page);
|
fscache_uncache_page(cookie, page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __cifs_fscache_wait_on_page_write(struct inode *inode, struct page *page)
|
||||||
|
{
|
||||||
|
struct cifsInodeInfo *cifsi = CIFS_I(inode);
|
||||||
|
struct fscache_cookie *cookie = cifsi->fscache;
|
||||||
|
|
||||||
|
cifs_dbg(FYI, "%s: (0x%p/0x%p)\n", __func__, page, cookie);
|
||||||
|
fscache_wait_on_page_write(cookie, page);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __cifs_fscache_uncache_page(struct inode *inode, struct page *page)
|
||||||
|
{
|
||||||
|
struct cifsInodeInfo *cifsi = CIFS_I(inode);
|
||||||
|
struct fscache_cookie *cookie = cifsi->fscache;
|
||||||
|
|
||||||
|
cifs_dbg(FYI, "%s: (0x%p/0x%p)\n", __func__, page, cookie);
|
||||||
|
fscache_uncache_page(cookie, page);
|
||||||
|
}
|
||||||
|
|
|
@ -55,10 +55,13 @@ extern void cifs_fscache_get_super_cookie(struct cifs_tcon *);
|
||||||
extern void cifs_fscache_release_super_cookie(struct cifs_tcon *);
|
extern void cifs_fscache_release_super_cookie(struct cifs_tcon *);
|
||||||
|
|
||||||
extern void cifs_fscache_release_inode_cookie(struct inode *);
|
extern void cifs_fscache_release_inode_cookie(struct inode *);
|
||||||
|
extern void cifs_fscache_update_inode_cookie(struct inode *inode);
|
||||||
extern void cifs_fscache_set_inode_cookie(struct inode *, struct file *);
|
extern void cifs_fscache_set_inode_cookie(struct inode *, struct file *);
|
||||||
extern void cifs_fscache_reset_inode_cookie(struct inode *);
|
extern void cifs_fscache_reset_inode_cookie(struct inode *);
|
||||||
|
|
||||||
extern void __cifs_fscache_invalidate_page(struct page *, struct inode *);
|
extern void __cifs_fscache_invalidate_page(struct page *, struct inode *);
|
||||||
|
extern void __cifs_fscache_wait_on_page_write(struct inode *inode, struct page *page);
|
||||||
|
extern void __cifs_fscache_uncache_page(struct inode *inode, struct page *page);
|
||||||
extern int cifs_fscache_release_page(struct page *page, gfp_t gfp);
|
extern int cifs_fscache_release_page(struct page *page, gfp_t gfp);
|
||||||
extern int __cifs_readpage_from_fscache(struct inode *, struct page *);
|
extern int __cifs_readpage_from_fscache(struct inode *, struct page *);
|
||||||
extern int __cifs_readpages_from_fscache(struct inode *,
|
extern int __cifs_readpages_from_fscache(struct inode *,
|
||||||
|
@ -76,6 +79,20 @@ static inline void cifs_fscache_invalidate_page(struct page *page,
|
||||||
__cifs_fscache_invalidate_page(page, inode);
|
__cifs_fscache_invalidate_page(page, inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void cifs_fscache_wait_on_page_write(struct inode *inode,
|
||||||
|
struct page *page)
|
||||||
|
{
|
||||||
|
if (PageFsCache(page))
|
||||||
|
__cifs_fscache_wait_on_page_write(inode, page);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void cifs_fscache_uncache_page(struct inode *inode,
|
||||||
|
struct page *page)
|
||||||
|
{
|
||||||
|
if (PageFsCache(page))
|
||||||
|
__cifs_fscache_uncache_page(inode, page);
|
||||||
|
}
|
||||||
|
|
||||||
static inline int cifs_readpage_from_fscache(struct inode *inode,
|
static inline int cifs_readpage_from_fscache(struct inode *inode,
|
||||||
struct page *page)
|
struct page *page)
|
||||||
{
|
{
|
||||||
|
@ -123,6 +140,7 @@ static inline void
|
||||||
cifs_fscache_release_super_cookie(struct cifs_tcon *tcon) {}
|
cifs_fscache_release_super_cookie(struct cifs_tcon *tcon) {}
|
||||||
|
|
||||||
static inline void cifs_fscache_release_inode_cookie(struct inode *inode) {}
|
static inline void cifs_fscache_release_inode_cookie(struct inode *inode) {}
|
||||||
|
static inline void cifs_fscache_update_inode_cookie(struct inode *inode) {}
|
||||||
static inline void cifs_fscache_set_inode_cookie(struct inode *inode,
|
static inline void cifs_fscache_set_inode_cookie(struct inode *inode,
|
||||||
struct file *filp) {}
|
struct file *filp) {}
|
||||||
static inline void cifs_fscache_reset_inode_cookie(struct inode *inode) {}
|
static inline void cifs_fscache_reset_inode_cookie(struct inode *inode) {}
|
||||||
|
@ -133,6 +151,11 @@ static inline int cifs_fscache_release_page(struct page *page, gfp_t gfp)
|
||||||
|
|
||||||
static inline void cifs_fscache_invalidate_page(struct page *page,
|
static inline void cifs_fscache_invalidate_page(struct page *page,
|
||||||
struct inode *inode) {}
|
struct inode *inode) {}
|
||||||
|
static inline void cifs_fscache_wait_on_page_write(struct inode *inode,
|
||||||
|
struct page *page) {}
|
||||||
|
static inline void cifs_fscache_uncache_page(struct inode *inode,
|
||||||
|
struct page *page) {}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
cifs_readpage_from_fscache(struct inode *inode, struct page *page)
|
cifs_readpage_from_fscache(struct inode *inode, struct page *page)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2297,6 +2297,7 @@ cifs_revalidate_mapping(struct inode *inode)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
unsigned long *flags = &CIFS_I(inode)->flags;
|
unsigned long *flags = &CIFS_I(inode)->flags;
|
||||||
|
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||||
|
|
||||||
/* swapfiles are not supposed to be shared */
|
/* swapfiles are not supposed to be shared */
|
||||||
if (IS_SWAPFILE(inode))
|
if (IS_SWAPFILE(inode))
|
||||||
|
@ -2308,11 +2309,16 @@ cifs_revalidate_mapping(struct inode *inode)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) {
|
if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) {
|
||||||
|
/* for cache=singleclient, do not invalidate */
|
||||||
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RW_CACHE)
|
||||||
|
goto skip_invalidate;
|
||||||
|
|
||||||
rc = cifs_invalidate_mapping(inode);
|
rc = cifs_invalidate_mapping(inode);
|
||||||
if (rc)
|
if (rc)
|
||||||
set_bit(CIFS_INO_INVALID_MAPPING, flags);
|
set_bit(CIFS_INO_INVALID_MAPPING, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skip_invalidate:
|
||||||
clear_bit_unlock(CIFS_INO_LOCK, flags);
|
clear_bit_unlock(CIFS_INO_LOCK, flags);
|
||||||
smp_mb__after_atomic();
|
smp_mb__after_atomic();
|
||||||
wake_up_bit(flags, CIFS_INO_LOCK);
|
wake_up_bit(flags, CIFS_INO_LOCK);
|
||||||
|
|
|
@ -369,7 +369,7 @@ int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
initiate_cifs_search(const unsigned int xid, struct file *file,
|
_initiate_cifs_search(const unsigned int xid, struct file *file,
|
||||||
const char *full_path)
|
const char *full_path)
|
||||||
{
|
{
|
||||||
__u16 search_flags;
|
__u16 search_flags;
|
||||||
|
@ -451,6 +451,27 @@ error_exit:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
initiate_cifs_search(const unsigned int xid, struct file *file,
|
||||||
|
const char *full_path)
|
||||||
|
{
|
||||||
|
int rc, retry_count = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
rc = _initiate_cifs_search(xid, file, full_path);
|
||||||
|
/*
|
||||||
|
* If we don't have enough credits to start reading the
|
||||||
|
* directory just try again after short wait.
|
||||||
|
*/
|
||||||
|
if (rc != -EDEADLK)
|
||||||
|
break;
|
||||||
|
|
||||||
|
usleep_range(512, 2048);
|
||||||
|
} while (retry_count++ < 5);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/* return length of unicode string in bytes */
|
/* return length of unicode string in bytes */
|
||||||
static int cifs_unicode_bytelen(const char *str)
|
static int cifs_unicode_bytelen(const char *str)
|
||||||
{
|
{
|
||||||
|
|
257
fs/cifs/sess.c
257
fs/cifs/sess.c
|
@ -799,30 +799,16 @@ cifs_select_sectype(struct TCP_Server_Info *server, enum securityEnum requested)
|
||||||
}
|
}
|
||||||
case CIFS_NEGFLAVOR_UNENCAP:
|
case CIFS_NEGFLAVOR_UNENCAP:
|
||||||
switch (requested) {
|
switch (requested) {
|
||||||
case NTLM:
|
|
||||||
case NTLMv2:
|
case NTLMv2:
|
||||||
return requested;
|
return requested;
|
||||||
case Unspecified:
|
case Unspecified:
|
||||||
if (global_secflags & CIFSSEC_MAY_NTLMV2)
|
if (global_secflags & CIFSSEC_MAY_NTLMV2)
|
||||||
return NTLMv2;
|
return NTLMv2;
|
||||||
if (global_secflags & CIFSSEC_MAY_NTLM)
|
|
||||||
return NTLM;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fallthrough; /* to attempt LANMAN authentication next */
|
fallthrough;
|
||||||
case CIFS_NEGFLAVOR_LANMAN:
|
|
||||||
switch (requested) {
|
|
||||||
case LANMAN:
|
|
||||||
return requested;
|
|
||||||
case Unspecified:
|
|
||||||
if (global_secflags & CIFSSEC_MAY_LANMAN)
|
|
||||||
return LANMAN;
|
|
||||||
fallthrough;
|
|
||||||
default:
|
|
||||||
return Unspecified;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
return Unspecified;
|
return Unspecified;
|
||||||
}
|
}
|
||||||
|
@ -877,7 +863,7 @@ sess_alloc_buffer(struct sess_data *sess_data, int wct)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_free_smb_buf:
|
out_free_smb_buf:
|
||||||
kfree(smb_buf);
|
cifs_small_buf_release(smb_buf);
|
||||||
sess_data->iov[0].iov_base = NULL;
|
sess_data->iov[0].iov_base = NULL;
|
||||||
sess_data->iov[0].iov_len = 0;
|
sess_data->iov[0].iov_len = 0;
|
||||||
sess_data->buf0_type = CIFS_NO_BUFFER;
|
sess_data->buf0_type = CIFS_NO_BUFFER;
|
||||||
|
@ -947,230 +933,6 @@ sess_sendreceive(struct sess_data *sess_data)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* LANMAN and plaintext are less secure and off by default.
|
|
||||||
* So we make this explicitly be turned on in kconfig (in the
|
|
||||||
* build) and turned on at runtime (changed from the default)
|
|
||||||
* in proc/fs/cifs or via mount parm. Unfortunately this is
|
|
||||||
* needed for old Win (e.g. Win95), some obscure NAS and OS/2
|
|
||||||
*/
|
|
||||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
|
||||||
static void
|
|
||||||
sess_auth_lanman(struct sess_data *sess_data)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
struct smb_hdr *smb_buf;
|
|
||||||
SESSION_SETUP_ANDX *pSMB;
|
|
||||||
char *bcc_ptr;
|
|
||||||
struct cifs_ses *ses = sess_data->ses;
|
|
||||||
char lnm_session_key[CIFS_AUTH_RESP_SIZE];
|
|
||||||
__u16 bytes_remaining;
|
|
||||||
|
|
||||||
/* lanman 2 style sessionsetup */
|
|
||||||
/* wct = 10 */
|
|
||||||
rc = sess_alloc_buffer(sess_data, 10);
|
|
||||||
if (rc)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
|
|
||||||
bcc_ptr = sess_data->iov[2].iov_base;
|
|
||||||
(void)cifs_ssetup_hdr(ses, pSMB);
|
|
||||||
|
|
||||||
pSMB->req.hdr.Flags2 &= ~SMBFLG2_UNICODE;
|
|
||||||
|
|
||||||
if (ses->user_name != NULL) {
|
|
||||||
/* no capabilities flags in old lanman negotiation */
|
|
||||||
pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
|
|
||||||
|
|
||||||
/* Calculate hash with password and copy into bcc_ptr.
|
|
||||||
* Encryption Key (stored as in cryptkey) gets used if the
|
|
||||||
* security mode bit in Negotiate Protocol response states
|
|
||||||
* to use challenge/response method (i.e. Password bit is 1).
|
|
||||||
*/
|
|
||||||
rc = calc_lanman_hash(ses->password, ses->server->cryptkey,
|
|
||||||
ses->server->sec_mode & SECMODE_PW_ENCRYPT ?
|
|
||||||
true : false, lnm_session_key);
|
|
||||||
if (rc)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_AUTH_RESP_SIZE);
|
|
||||||
bcc_ptr += CIFS_AUTH_RESP_SIZE;
|
|
||||||
} else {
|
|
||||||
pSMB->old_req.PasswordLength = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* can not sign if LANMAN negotiated so no need
|
|
||||||
* to calculate signing key? but what if server
|
|
||||||
* changed to do higher than lanman dialect and
|
|
||||||
* we reconnected would we ever calc signing_key?
|
|
||||||
*/
|
|
||||||
|
|
||||||
cifs_dbg(FYI, "Negotiating LANMAN setting up strings\n");
|
|
||||||
/* Unicode not allowed for LANMAN dialects */
|
|
||||||
ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
|
|
||||||
|
|
||||||
sess_data->iov[2].iov_len = (long) bcc_ptr -
|
|
||||||
(long) sess_data->iov[2].iov_base;
|
|
||||||
|
|
||||||
rc = sess_sendreceive(sess_data);
|
|
||||||
if (rc)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
|
|
||||||
smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
|
|
||||||
|
|
||||||
/* lanman response has a word count of 3 */
|
|
||||||
if (smb_buf->WordCount != 3) {
|
|
||||||
rc = -EIO;
|
|
||||||
cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
|
|
||||||
cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
|
|
||||||
|
|
||||||
ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
|
|
||||||
cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
|
|
||||||
|
|
||||||
bytes_remaining = get_bcc(smb_buf);
|
|
||||||
bcc_ptr = pByteArea(smb_buf);
|
|
||||||
|
|
||||||
/* BB check if Unicode and decode strings */
|
|
||||||
if (bytes_remaining == 0) {
|
|
||||||
/* no string area to decode, do nothing */
|
|
||||||
} else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
|
|
||||||
/* unicode string area must be word-aligned */
|
|
||||||
if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
|
|
||||||
++bcc_ptr;
|
|
||||||
--bytes_remaining;
|
|
||||||
}
|
|
||||||
decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
|
|
||||||
sess_data->nls_cp);
|
|
||||||
} else {
|
|
||||||
decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
|
|
||||||
sess_data->nls_cp);
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = sess_establish_session(sess_data);
|
|
||||||
out:
|
|
||||||
sess_data->result = rc;
|
|
||||||
sess_data->func = NULL;
|
|
||||||
sess_free_buffer(sess_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
|
||||||
sess_auth_ntlm(struct sess_data *sess_data)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
struct smb_hdr *smb_buf;
|
|
||||||
SESSION_SETUP_ANDX *pSMB;
|
|
||||||
char *bcc_ptr;
|
|
||||||
struct cifs_ses *ses = sess_data->ses;
|
|
||||||
__u32 capabilities;
|
|
||||||
__u16 bytes_remaining;
|
|
||||||
|
|
||||||
/* old style NTLM sessionsetup */
|
|
||||||
/* wct = 13 */
|
|
||||||
rc = sess_alloc_buffer(sess_data, 13);
|
|
||||||
if (rc)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
|
|
||||||
bcc_ptr = sess_data->iov[2].iov_base;
|
|
||||||
capabilities = cifs_ssetup_hdr(ses, pSMB);
|
|
||||||
|
|
||||||
pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
|
|
||||||
if (ses->user_name != NULL) {
|
|
||||||
pSMB->req_no_secext.CaseInsensitivePasswordLength =
|
|
||||||
cpu_to_le16(CIFS_AUTH_RESP_SIZE);
|
|
||||||
pSMB->req_no_secext.CaseSensitivePasswordLength =
|
|
||||||
cpu_to_le16(CIFS_AUTH_RESP_SIZE);
|
|
||||||
|
|
||||||
/* calculate ntlm response and session key */
|
|
||||||
rc = setup_ntlm_response(ses, sess_data->nls_cp);
|
|
||||||
if (rc) {
|
|
||||||
cifs_dbg(VFS, "Error %d during NTLM authentication\n",
|
|
||||||
rc);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* copy ntlm response */
|
|
||||||
memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
|
|
||||||
CIFS_AUTH_RESP_SIZE);
|
|
||||||
bcc_ptr += CIFS_AUTH_RESP_SIZE;
|
|
||||||
memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
|
|
||||||
CIFS_AUTH_RESP_SIZE);
|
|
||||||
bcc_ptr += CIFS_AUTH_RESP_SIZE;
|
|
||||||
} else {
|
|
||||||
pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
|
|
||||||
pSMB->req_no_secext.CaseSensitivePasswordLength = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ses->capabilities & CAP_UNICODE) {
|
|
||||||
/* unicode strings must be word aligned */
|
|
||||||
if (sess_data->iov[0].iov_len % 2) {
|
|
||||||
*bcc_ptr = 0;
|
|
||||||
bcc_ptr++;
|
|
||||||
}
|
|
||||||
unicode_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
|
|
||||||
} else {
|
|
||||||
ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
sess_data->iov[2].iov_len = (long) bcc_ptr -
|
|
||||||
(long) sess_data->iov[2].iov_base;
|
|
||||||
|
|
||||||
rc = sess_sendreceive(sess_data);
|
|
||||||
if (rc)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
|
|
||||||
smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
|
|
||||||
|
|
||||||
if (smb_buf->WordCount != 3) {
|
|
||||||
rc = -EIO;
|
|
||||||
cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
|
|
||||||
cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
|
|
||||||
|
|
||||||
ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
|
|
||||||
cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
|
|
||||||
|
|
||||||
bytes_remaining = get_bcc(smb_buf);
|
|
||||||
bcc_ptr = pByteArea(smb_buf);
|
|
||||||
|
|
||||||
/* BB check if Unicode and decode strings */
|
|
||||||
if (bytes_remaining == 0) {
|
|
||||||
/* no string area to decode, do nothing */
|
|
||||||
} else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
|
|
||||||
/* unicode string area must be word-aligned */
|
|
||||||
if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
|
|
||||||
++bcc_ptr;
|
|
||||||
--bytes_remaining;
|
|
||||||
}
|
|
||||||
decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
|
|
||||||
sess_data->nls_cp);
|
|
||||||
} else {
|
|
||||||
decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
|
|
||||||
sess_data->nls_cp);
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = sess_establish_session(sess_data);
|
|
||||||
out:
|
|
||||||
sess_data->result = rc;
|
|
||||||
sess_data->func = NULL;
|
|
||||||
sess_free_buffer(sess_data);
|
|
||||||
kfree(ses->auth_key.response);
|
|
||||||
ses->auth_key.response = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sess_auth_ntlmv2(struct sess_data *sess_data)
|
sess_auth_ntlmv2(struct sess_data *sess_data)
|
||||||
{
|
{
|
||||||
|
@ -1675,21 +1437,6 @@ static int select_sec(struct cifs_ses *ses, struct sess_data *sess_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case LANMAN:
|
|
||||||
/* LANMAN and plaintext are less secure and off by default.
|
|
||||||
* So we make this explicitly be turned on in kconfig (in the
|
|
||||||
* build) and turned on at runtime (changed from the default)
|
|
||||||
* in proc/fs/cifs or via mount parm. Unfortunately this is
|
|
||||||
* needed for old Win (e.g. Win95), some obscure NAS and OS/2 */
|
|
||||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
|
||||||
sess_data->func = sess_auth_lanman;
|
|
||||||
break;
|
|
||||||
#else
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
#endif
|
|
||||||
case NTLM:
|
|
||||||
sess_data->func = sess_auth_ntlm;
|
|
||||||
break;
|
|
||||||
case NTLMv2:
|
case NTLMv2:
|
||||||
sess_data->func = sess_auth_ntlmv2;
|
sess_data->func = sess_auth_ntlmv2;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// SPDX-License-Identifier: LGPL-2.1
|
// SPDX-License-Identifier: LGPL-2.1
|
||||||
/*
|
/*
|
||||||
* fs/smb2/smb2maperror.c
|
|
||||||
*
|
*
|
||||||
* Functions which do error mapping of SMB2 status codes to POSIX errors
|
* Functions which do error mapping of SMB2 status codes to POSIX errors
|
||||||
*
|
*
|
||||||
|
|
|
@ -18,13 +18,13 @@
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/random.h>
|
#include <linux/random.h>
|
||||||
#include <crypto/des.h>
|
|
||||||
#include "cifs_fs_sb.h"
|
#include "cifs_fs_sb.h"
|
||||||
#include "cifs_unicode.h"
|
#include "cifs_unicode.h"
|
||||||
#include "cifspdu.h"
|
#include "cifspdu.h"
|
||||||
#include "cifsglob.h"
|
#include "cifsglob.h"
|
||||||
#include "cifs_debug.h"
|
#include "cifs_debug.h"
|
||||||
#include "cifsproto.h"
|
#include "cifsproto.h"
|
||||||
|
#include "../cifs_common/md4.h"
|
||||||
|
|
||||||
#ifndef false
|
#ifndef false
|
||||||
#define false 0
|
#define false 0
|
||||||
|
@ -38,126 +38,29 @@
|
||||||
#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
|
#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
|
||||||
#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((__u16)(val)))
|
#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((__u16)(val)))
|
||||||
|
|
||||||
static void
|
|
||||||
str_to_key(unsigned char *str, unsigned char *key)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
key[0] = str[0] >> 1;
|
|
||||||
key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
|
|
||||||
key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
|
|
||||||
key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
|
|
||||||
key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
|
|
||||||
key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
|
|
||||||
key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
|
|
||||||
key[7] = str[6] & 0x7F;
|
|
||||||
for (i = 0; i < 8; i++)
|
|
||||||
key[i] = (key[i] << 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
smbhash(unsigned char *out, const unsigned char *in, unsigned char *key)
|
|
||||||
{
|
|
||||||
unsigned char key2[8];
|
|
||||||
struct des_ctx ctx;
|
|
||||||
|
|
||||||
str_to_key(key, key2);
|
|
||||||
|
|
||||||
if (fips_enabled) {
|
|
||||||
cifs_dbg(VFS, "FIPS compliance enabled: DES not permitted\n");
|
|
||||||
return -ENOENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
des_expand_key(&ctx, key2, DES_KEY_SIZE);
|
|
||||||
des_encrypt(&ctx, out, in);
|
|
||||||
memzero_explicit(&ctx, sizeof(ctx));
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
E_P16(unsigned char *p14, unsigned char *p16)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
unsigned char sp8[8] =
|
|
||||||
{ 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
|
|
||||||
|
|
||||||
rc = smbhash(p16, sp8, p14);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
rc = smbhash(p16 + 8, sp8, p14 + 7);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
E_P24(unsigned char *p21, const unsigned char *c8, unsigned char *p24)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = smbhash(p24, c8, p21);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
rc = smbhash(p24 + 8, c8, p21 + 7);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
rc = smbhash(p24 + 16, c8, p21 + 14);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* produce a md4 message digest from data of length n bytes */
|
/* produce a md4 message digest from data of length n bytes */
|
||||||
int
|
static int
|
||||||
mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len)
|
mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct crypto_shash *md4 = NULL;
|
struct md4_ctx mctx;
|
||||||
struct sdesc *sdescmd4 = NULL;
|
|
||||||
|
|
||||||
rc = cifs_alloc_hash("md4", &md4, &sdescmd4);
|
rc = cifs_md4_init(&mctx);
|
||||||
if (rc)
|
|
||||||
goto mdfour_err;
|
|
||||||
|
|
||||||
rc = crypto_shash_init(&sdescmd4->shash);
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
cifs_dbg(VFS, "%s: Could not init md4 shash\n", __func__);
|
cifs_dbg(VFS, "%s: Could not init MD4\n", __func__);
|
||||||
goto mdfour_err;
|
goto mdfour_err;
|
||||||
}
|
}
|
||||||
rc = crypto_shash_update(&sdescmd4->shash, link_str, link_len);
|
rc = cifs_md4_update(&mctx, link_str, link_len);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
cifs_dbg(VFS, "%s: Could not update with link_str\n", __func__);
|
cifs_dbg(VFS, "%s: Could not update MD4\n", __func__);
|
||||||
goto mdfour_err;
|
goto mdfour_err;
|
||||||
}
|
}
|
||||||
rc = crypto_shash_final(&sdescmd4->shash, md4_hash);
|
rc = cifs_md4_final(&mctx, md4_hash);
|
||||||
if (rc)
|
if (rc)
|
||||||
cifs_dbg(VFS, "%s: Could not generate md4 hash\n", __func__);
|
cifs_dbg(VFS, "%s: Could not finalize MD4\n", __func__);
|
||||||
|
|
||||||
|
|
||||||
mdfour_err:
|
mdfour_err:
|
||||||
cifs_free_hash(&md4, &sdescmd4);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
This implements the X/Open SMB password encryption
|
|
||||||
It takes a password, a 8 byte "crypt key" and puts 24 bytes of
|
|
||||||
encrypted password into p24 */
|
|
||||||
/* Note that password must be uppercased and null terminated */
|
|
||||||
int
|
|
||||||
SMBencrypt(unsigned char *passwd, const unsigned char *c8, unsigned char *p24)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
unsigned char p14[14], p16[16], p21[21];
|
|
||||||
|
|
||||||
memset(p14, '\0', 14);
|
|
||||||
memset(p16, '\0', 16);
|
|
||||||
memset(p21, '\0', 21);
|
|
||||||
|
|
||||||
memcpy(p14, passwd, 14);
|
|
||||||
rc = E_P16(p14, p16);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
memcpy(p21, p16, 16);
|
|
||||||
rc = E_P24(p21, c8, p24);
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,25 +89,3 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16,
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Does the NT MD4 hash then des encryption. */
|
|
||||||
int
|
|
||||||
SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24,
|
|
||||||
const struct nls_table *codepage)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
unsigned char p16[16], p21[21];
|
|
||||||
|
|
||||||
memset(p16, '\0', 16);
|
|
||||||
memset(p21, '\0', 21);
|
|
||||||
|
|
||||||
rc = E_md4hash(passwd, p16, codepage);
|
|
||||||
if (rc) {
|
|
||||||
cifs_dbg(FYI, "%s Can't generate NT hash, error: %d\n",
|
|
||||||
__func__, rc);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
memcpy(p21, p16, 16);
|
|
||||||
rc = E_P24(p21, c8, p24);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
#
|
||||||
|
# Makefile for Linux filesystem routines that are shared by client and server.
|
||||||
|
#
|
||||||
|
|
||||||
|
obj-$(CONFIG_CIFS_COMMON) += cifs_arc4.o
|
||||||
|
obj-$(CONFIG_CIFS_COMMON) += cifs_md4.o
|
|
@ -0,0 +1,23 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||||
|
/*
|
||||||
|
* Common values for ARC4 Cipher Algorithm
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CRYPTO_ARC4_H
|
||||||
|
#define _CRYPTO_ARC4_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
#define ARC4_MIN_KEY_SIZE 1
|
||||||
|
#define ARC4_MAX_KEY_SIZE 256
|
||||||
|
#define ARC4_BLOCK_SIZE 1
|
||||||
|
|
||||||
|
struct arc4_ctx {
|
||||||
|
u32 S[256];
|
||||||
|
u32 x, y;
|
||||||
|
};
|
||||||
|
|
||||||
|
int cifs_arc4_setkey(struct arc4_ctx *ctx, const u8 *in_key, unsigned int key_len);
|
||||||
|
void cifs_arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in, unsigned int len);
|
||||||
|
|
||||||
|
#endif /* _CRYPTO_ARC4_H */
|
|
@ -0,0 +1,87 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
/*
|
||||||
|
* Cryptographic API
|
||||||
|
*
|
||||||
|
* ARC4 Cipher Algorithm
|
||||||
|
*
|
||||||
|
* Jon Oberheide <jon@oberheide.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include "arc4.h"
|
||||||
|
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
|
int cifs_arc4_setkey(struct arc4_ctx *ctx, const u8 *in_key, unsigned int key_len)
|
||||||
|
{
|
||||||
|
int i, j = 0, k = 0;
|
||||||
|
|
||||||
|
ctx->x = 1;
|
||||||
|
ctx->y = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < 256; i++)
|
||||||
|
ctx->S[i] = i;
|
||||||
|
|
||||||
|
for (i = 0; i < 256; i++) {
|
||||||
|
u32 a = ctx->S[i];
|
||||||
|
|
||||||
|
j = (j + in_key[k] + a) & 0xff;
|
||||||
|
ctx->S[i] = ctx->S[j];
|
||||||
|
ctx->S[j] = a;
|
||||||
|
if (++k >= key_len)
|
||||||
|
k = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(cifs_arc4_setkey);
|
||||||
|
|
||||||
|
void cifs_arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in, unsigned int len)
|
||||||
|
{
|
||||||
|
u32 *const S = ctx->S;
|
||||||
|
u32 x, y, a, b;
|
||||||
|
u32 ty, ta, tb;
|
||||||
|
|
||||||
|
if (len == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
x = ctx->x;
|
||||||
|
y = ctx->y;
|
||||||
|
|
||||||
|
a = S[x];
|
||||||
|
y = (y + a) & 0xff;
|
||||||
|
b = S[y];
|
||||||
|
|
||||||
|
do {
|
||||||
|
S[y] = a;
|
||||||
|
a = (a + b) & 0xff;
|
||||||
|
S[x] = b;
|
||||||
|
x = (x + 1) & 0xff;
|
||||||
|
ta = S[x];
|
||||||
|
ty = (y + ta) & 0xff;
|
||||||
|
tb = S[ty];
|
||||||
|
*out++ = *in++ ^ S[a];
|
||||||
|
if (--len == 0)
|
||||||
|
break;
|
||||||
|
y = ty;
|
||||||
|
a = ta;
|
||||||
|
b = tb;
|
||||||
|
} while (true);
|
||||||
|
|
||||||
|
ctx->x = x;
|
||||||
|
ctx->y = y;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(cifs_arc4_crypt);
|
||||||
|
|
||||||
|
static int __init
|
||||||
|
init_cifs_common(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static void __init
|
||||||
|
exit_cifs_common(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(init_cifs_common)
|
||||||
|
module_exit(exit_cifs_common)
|
|
@ -0,0 +1,197 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/*
|
||||||
|
* Cryptographic API.
|
||||||
|
*
|
||||||
|
* MD4 Message Digest Algorithm (RFC1320).
|
||||||
|
*
|
||||||
|
* Implementation derived from Andrew Tridgell and Steve French's
|
||||||
|
* CIFS MD4 implementation, and the cryptoapi implementation
|
||||||
|
* originally based on the public domain implementation written
|
||||||
|
* by Colin Plumb in 1993.
|
||||||
|
*
|
||||||
|
* Copyright (c) Andrew Tridgell 1997-1998.
|
||||||
|
* Modified by Steve French (sfrench@us.ibm.com) 2002
|
||||||
|
* Copyright (c) Cryptoapi developers.
|
||||||
|
* Copyright (c) 2002 David S. Miller (davem@redhat.com)
|
||||||
|
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <asm/byteorder.h>
|
||||||
|
#include "md4.h"
|
||||||
|
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
|
static inline u32 lshift(u32 x, unsigned int s)
|
||||||
|
{
|
||||||
|
x &= 0xFFFFFFFF;
|
||||||
|
return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 F(u32 x, u32 y, u32 z)
|
||||||
|
{
|
||||||
|
return (x & y) | ((~x) & z);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 G(u32 x, u32 y, u32 z)
|
||||||
|
{
|
||||||
|
return (x & y) | (x & z) | (y & z);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 H(u32 x, u32 y, u32 z)
|
||||||
|
{
|
||||||
|
return x ^ y ^ z;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ROUND1(a,b,c,d,k,s) (a = lshift(a + F(b,c,d) + k, s))
|
||||||
|
#define ROUND2(a,b,c,d,k,s) (a = lshift(a + G(b,c,d) + k + (u32)0x5A827999,s))
|
||||||
|
#define ROUND3(a,b,c,d,k,s) (a = lshift(a + H(b,c,d) + k + (u32)0x6ED9EBA1,s))
|
||||||
|
|
||||||
|
static void md4_transform(u32 *hash, u32 const *in)
|
||||||
|
{
|
||||||
|
u32 a, b, c, d;
|
||||||
|
|
||||||
|
a = hash[0];
|
||||||
|
b = hash[1];
|
||||||
|
c = hash[2];
|
||||||
|
d = hash[3];
|
||||||
|
|
||||||
|
ROUND1(a, b, c, d, in[0], 3);
|
||||||
|
ROUND1(d, a, b, c, in[1], 7);
|
||||||
|
ROUND1(c, d, a, b, in[2], 11);
|
||||||
|
ROUND1(b, c, d, a, in[3], 19);
|
||||||
|
ROUND1(a, b, c, d, in[4], 3);
|
||||||
|
ROUND1(d, a, b, c, in[5], 7);
|
||||||
|
ROUND1(c, d, a, b, in[6], 11);
|
||||||
|
ROUND1(b, c, d, a, in[7], 19);
|
||||||
|
ROUND1(a, b, c, d, in[8], 3);
|
||||||
|
ROUND1(d, a, b, c, in[9], 7);
|
||||||
|
ROUND1(c, d, a, b, in[10], 11);
|
||||||
|
ROUND1(b, c, d, a, in[11], 19);
|
||||||
|
ROUND1(a, b, c, d, in[12], 3);
|
||||||
|
ROUND1(d, a, b, c, in[13], 7);
|
||||||
|
ROUND1(c, d, a, b, in[14], 11);
|
||||||
|
ROUND1(b, c, d, a, in[15], 19);
|
||||||
|
|
||||||
|
ROUND2(a, b, c, d, in[0], 3);
|
||||||
|
ROUND2(d, a, b, c, in[4], 5);
|
||||||
|
ROUND2(c, d, a, b, in[8], 9);
|
||||||
|
ROUND2(b, c, d, a, in[12], 13);
|
||||||
|
ROUND2(a, b, c, d, in[1], 3);
|
||||||
|
ROUND2(d, a, b, c, in[5], 5);
|
||||||
|
ROUND2(c, d, a, b, in[9], 9);
|
||||||
|
ROUND2(b, c, d, a, in[13], 13);
|
||||||
|
ROUND2(a, b, c, d, in[2], 3);
|
||||||
|
ROUND2(d, a, b, c, in[6], 5);
|
||||||
|
ROUND2(c, d, a, b, in[10], 9);
|
||||||
|
ROUND2(b, c, d, a, in[14], 13);
|
||||||
|
ROUND2(a, b, c, d, in[3], 3);
|
||||||
|
ROUND2(d, a, b, c, in[7], 5);
|
||||||
|
ROUND2(c, d, a, b, in[11], 9);
|
||||||
|
ROUND2(b, c, d, a, in[15], 13);
|
||||||
|
|
||||||
|
ROUND3(a, b, c, d, in[0], 3);
|
||||||
|
ROUND3(d, a, b, c, in[8], 9);
|
||||||
|
ROUND3(c, d, a, b, in[4], 11);
|
||||||
|
ROUND3(b, c, d, a, in[12], 15);
|
||||||
|
ROUND3(a, b, c, d, in[2], 3);
|
||||||
|
ROUND3(d, a, b, c, in[10], 9);
|
||||||
|
ROUND3(c, d, a, b, in[6], 11);
|
||||||
|
ROUND3(b, c, d, a, in[14], 15);
|
||||||
|
ROUND3(a, b, c, d, in[1], 3);
|
||||||
|
ROUND3(d, a, b, c, in[9], 9);
|
||||||
|
ROUND3(c, d, a, b, in[5], 11);
|
||||||
|
ROUND3(b, c, d, a, in[13], 15);
|
||||||
|
ROUND3(a, b, c, d, in[3], 3);
|
||||||
|
ROUND3(d, a, b, c, in[11], 9);
|
||||||
|
ROUND3(c, d, a, b, in[7], 11);
|
||||||
|
ROUND3(b, c, d, a, in[15], 15);
|
||||||
|
|
||||||
|
hash[0] += a;
|
||||||
|
hash[1] += b;
|
||||||
|
hash[2] += c;
|
||||||
|
hash[3] += d;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void md4_transform_helper(struct md4_ctx *ctx)
|
||||||
|
{
|
||||||
|
le32_to_cpu_array(ctx->block, ARRAY_SIZE(ctx->block));
|
||||||
|
md4_transform(ctx->hash, ctx->block);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cifs_md4_init(struct md4_ctx *mctx)
|
||||||
|
{
|
||||||
|
memset(mctx, 0, sizeof(struct md4_ctx));
|
||||||
|
mctx->hash[0] = 0x67452301;
|
||||||
|
mctx->hash[1] = 0xefcdab89;
|
||||||
|
mctx->hash[2] = 0x98badcfe;
|
||||||
|
mctx->hash[3] = 0x10325476;
|
||||||
|
mctx->byte_count = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(cifs_md4_init);
|
||||||
|
|
||||||
|
int cifs_md4_update(struct md4_ctx *mctx, const u8 *data, unsigned int len)
|
||||||
|
{
|
||||||
|
const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
|
||||||
|
|
||||||
|
mctx->byte_count += len;
|
||||||
|
|
||||||
|
if (avail > len) {
|
||||||
|
memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
|
||||||
|
data, len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
|
||||||
|
data, avail);
|
||||||
|
|
||||||
|
md4_transform_helper(mctx);
|
||||||
|
data += avail;
|
||||||
|
len -= avail;
|
||||||
|
|
||||||
|
while (len >= sizeof(mctx->block)) {
|
||||||
|
memcpy(mctx->block, data, sizeof(mctx->block));
|
||||||
|
md4_transform_helper(mctx);
|
||||||
|
data += sizeof(mctx->block);
|
||||||
|
len -= sizeof(mctx->block);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(mctx->block, data, len);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(cifs_md4_update);
|
||||||
|
|
||||||
|
int cifs_md4_final(struct md4_ctx *mctx, u8 *out)
|
||||||
|
{
|
||||||
|
const unsigned int offset = mctx->byte_count & 0x3f;
|
||||||
|
char *p = (char *)mctx->block + offset;
|
||||||
|
int padding = 56 - (offset + 1);
|
||||||
|
|
||||||
|
*p++ = 0x80;
|
||||||
|
if (padding < 0) {
|
||||||
|
memset(p, 0x00, padding + sizeof(u64));
|
||||||
|
md4_transform_helper(mctx);
|
||||||
|
p = (char *)mctx->block;
|
||||||
|
padding = 56;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(p, 0, padding);
|
||||||
|
mctx->block[14] = mctx->byte_count << 3;
|
||||||
|
mctx->block[15] = mctx->byte_count >> 29;
|
||||||
|
le32_to_cpu_array(mctx->block, (sizeof(mctx->block) -
|
||||||
|
sizeof(u64)) / sizeof(u32));
|
||||||
|
md4_transform(mctx->hash, mctx->block);
|
||||||
|
cpu_to_le32_array(mctx->hash, ARRAY_SIZE(mctx->hash));
|
||||||
|
memcpy(out, mctx->hash, sizeof(mctx->hash));
|
||||||
|
memset(mctx, 0, sizeof(*mctx));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(cifs_md4_final);
|
|
@ -0,0 +1,27 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||||
|
/*
|
||||||
|
* Common values for ARC4 Cipher Algorithm
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CIFS_MD4_H
|
||||||
|
#define _CIFS_MD4_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
#define MD4_DIGEST_SIZE 16
|
||||||
|
#define MD4_HMAC_BLOCK_SIZE 64
|
||||||
|
#define MD4_BLOCK_WORDS 16
|
||||||
|
#define MD4_HASH_WORDS 4
|
||||||
|
|
||||||
|
struct md4_ctx {
|
||||||
|
u32 hash[MD4_HASH_WORDS];
|
||||||
|
u32 block[MD4_BLOCK_WORDS];
|
||||||
|
u64 byte_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int cifs_md4_init(struct md4_ctx *mctx);
|
||||||
|
int cifs_md4_update(struct md4_ctx *mctx, const u8 *data, unsigned int len);
|
||||||
|
int cifs_md4_final(struct md4_ctx *mctx, u8 *out);
|
||||||
|
|
||||||
|
#endif /* _CIFS_MD4_H */
|
|
@ -70,6 +70,9 @@ enum OID {
|
||||||
|
|
||||||
OID_spnego, /* 1.3.6.1.5.5.2 */
|
OID_spnego, /* 1.3.6.1.5.5.2 */
|
||||||
|
|
||||||
|
OID_IAKerb, /* 1.3.6.1.5.2.5 */
|
||||||
|
OID_PKU2U, /* 1.3.5.1.5.2.7 */
|
||||||
|
OID_Scram, /* 1.3.6.1.5.5.14 */
|
||||||
OID_certAuthInfoAccess, /* 1.3.6.1.5.5.7.1.1 */
|
OID_certAuthInfoAccess, /* 1.3.6.1.5.5.7.1.1 */
|
||||||
OID_sha1, /* 1.3.14.3.2.26 */
|
OID_sha1, /* 1.3.14.3.2.26 */
|
||||||
OID_id_ansip384r1, /* 1.3.132.0.34 */
|
OID_id_ansip384r1, /* 1.3.132.0.34 */
|
||||||
|
@ -104,6 +107,10 @@ enum OID {
|
||||||
OID_authorityKeyIdentifier, /* 2.5.29.35 */
|
OID_authorityKeyIdentifier, /* 2.5.29.35 */
|
||||||
OID_extKeyUsage, /* 2.5.29.37 */
|
OID_extKeyUsage, /* 2.5.29.37 */
|
||||||
|
|
||||||
|
/* Heimdal mechanisms */
|
||||||
|
OID_NetlogonMechanism, /* 1.2.752.43.14.2 */
|
||||||
|
OID_appleLocalKdcSupported, /* 1.2.752.43.14.3 */
|
||||||
|
|
||||||
/* EC-RDSA */
|
/* EC-RDSA */
|
||||||
OID_gostCPSignA, /* 1.2.643.2.2.35.1 */
|
OID_gostCPSignA, /* 1.2.643.2.2.35.1 */
|
||||||
OID_gostCPSignB, /* 1.2.643.2.2.35.2 */
|
OID_gostCPSignB, /* 1.2.643.2.2.35.2 */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче