Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d4141531 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs updates from Steve French:
 "Various CIFS/SMB2/SMB3 updates for 3.11.  Includes bug fixes - SMB3
  support should be much more stable with key DFS fix and also signing
  possible now (although is more work to do to get SMB3 signing working
  well with multiuser).

  Mounts using the new SMB 3.02 dialect can now be done (specify
  "vers=3.02" on mount) against the most current Microsoft systems.

  Also includes a big cleanup of the cifs/smb2/smb3 authentication code
  from Jeff which fixes some long standing problems with the way allowed
  authentication flavors and signing are configured.

  Some followon patches later in the cycle will clean up allocation of
  structures for the various security mechanisms depending on what
  dialect is chosen (reduces memory usage a little) and to add support
  for the secure negotiate fsctl (for smb3) which prevents downgrade
  attacks."

* 'for-next' of git://git.samba.org/sfrench/cifs-2.6: (39 commits)
  cifs: fill TRANS2_QUERY_FILE_INFO ByteCount fields
  cifs: fix SMB2 signing enablement in cifs_enable_signing
  [CIFS] Fix build warning
  [CIFS] SMB3 Signing enablement
  [CIFS] Do not set DFS flag on SMB2 open
  [CIFS] fix static checker warning
  cifs: try to handle the MUST SecurityFlags sanely
  When server doesn't provide SecurityBuffer on SMB2Negotiate pick default
  Handle big endianness in NTLM (ntlmv2) authentication
  revalidate directories instiantiated via FIND_* in order to handle DFS referrals
  SMB2 FSCTL and IOCTL worker function
  Charge at least one credit, if server says that it supports multicredit
  Remove typo
  Some missing share flags
  cifs: using strlcpy instead of strncpy
  Update headers to update various SMB3 ioctl definitions
  Update cifs version number
  Add ability to dipslay SMB3 share flags and capabilities for debugging
  Add some missing SMB3 and SMB3.02 flags
  Add SMB3.02 dialect support
  ...
parents f39d420f 7ac0febb
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ config CIFS
	select CRYPTO_ECB
	select CRYPTO_DES
	select CRYPTO_SHA256
	select CRYPTO_CMAC
	help
	  This is the client VFS module for the Common Internet File System
	  (CIFS) protocol which is the successor to the Server Message Block
+45 −7
Original line number Diff line number Diff line
@@ -213,7 +213,7 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
						   tcon->nativeFileSystem);
				}
				seq_printf(m, "DevInfo: 0x%x Attributes: 0x%x"
					"\nPathComponentMax: %d Status: 0x%d",
					"\n\tPathComponentMax: %d Status: 0x%d",
					le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
					le32_to_cpu(tcon->fsAttrInfo.Attributes),
					le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
@@ -224,6 +224,8 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
					seq_puts(m, " type: CDROM ");
				else
					seq_printf(m, " type: %d ", dev_type);
				if (server->ops->dump_share_caps)
					server->ops->dump_share_caps(m, tcon);

				if (tcon->need_reconnect)
					seq_puts(m, "\tDISCONNECTED ");
@@ -595,9 +597,36 @@ static int cifs_security_flags_proc_open(struct inode *inode, struct file *file)
	return single_open(file, cifs_security_flags_proc_show, NULL);
}

/*
 * Ensure that if someone sets a MUST flag, that we disable all other MAY
 * flags except for the ones corresponding to the given MUST flag. If there are
 * multiple MUST flags, then try to prefer more secure ones.
 */
static void
cifs_security_flags_handle_must_flags(unsigned int *flags)
{
	unsigned int signflags = *flags & CIFSSEC_MUST_SIGN;

	if ((*flags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
		*flags = CIFSSEC_MUST_KRB5;
	else if ((*flags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
		*flags = CIFSSEC_MUST_NTLMSSP;
	else if ((*flags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
		*flags = CIFSSEC_MUST_NTLMV2;
	else if ((*flags & CIFSSEC_MUST_NTLM) == CIFSSEC_MUST_NTLM)
		*flags = CIFSSEC_MUST_NTLM;
	else if ((*flags & CIFSSEC_MUST_LANMAN) == CIFSSEC_MUST_LANMAN)
		*flags = CIFSSEC_MUST_LANMAN;
	else if ((*flags & CIFSSEC_MUST_PLNTXT) == CIFSSEC_MUST_PLNTXT)
		*flags = CIFSSEC_MUST_PLNTXT;

	*flags |= signflags;
}

static ssize_t cifs_security_flags_proc_write(struct file *file,
		const char __user *buffer, size_t count, loff_t *ppos)
{
	int rc;
	unsigned int flags;
	char flags_string[12];
	char c;
@@ -620,26 +649,35 @@ static ssize_t cifs_security_flags_proc_write(struct file *file,
			global_secflags = CIFSSEC_MAX;
			return count;
		} else if (!isdigit(c)) {
			cifs_dbg(VFS, "invalid flag %c\n", c);
			cifs_dbg(VFS, "Invalid SecurityFlags: %s\n",
					flags_string);
			return -EINVAL;
		}
	}
	/* else we have a number */

	flags = simple_strtoul(flags_string, NULL, 0);
	/* else we have a number */
	rc = kstrtouint(flags_string, 0, &flags);
	if (rc) {
		cifs_dbg(VFS, "Invalid SecurityFlags: %s\n",
				flags_string);
		return rc;
	}

	cifs_dbg(FYI, "sec flags 0x%x\n", flags);

	if (flags <= 0)  {
		cifs_dbg(VFS, "invalid security flags %s\n", flags_string);
	if (flags == 0)  {
		cifs_dbg(VFS, "Invalid SecurityFlags: %s\n", flags_string);
		return -EINVAL;
	}

	if (flags & ~CIFSSEC_MASK) {
		cifs_dbg(VFS, "attempt to set unsupported security flags 0x%x\n",
		cifs_dbg(VFS, "Unsupported security flags: 0x%x\n",
			 flags & ~CIFSSEC_MASK);
		return -EINVAL;
	}

	cifs_security_flags_handle_must_flags(&flags);

	/* flags look ok - update the global security flags for cifs module */
	global_secflags = flags;
	if (global_secflags & CIFSSEC_MUST_SIGN) {
+4 −4
Original line number Diff line number Diff line
@@ -327,14 +327,14 @@ UniToupper(register wchar_t uc)
/*
 * UniStrupr:  Upper case a unicode string
 */
static inline wchar_t *
UniStrupr(register wchar_t *upin)
static inline __le16 *
UniStrupr(register __le16 *upin)
{
	register wchar_t *up;
	register __le16 *up;

	up = upin;
	while (*up) {		/* For all characters */
		*up = UniToupper(*up);
		*up = cpu_to_le16(UniToupper(le16_to_cpu(*up)));
		up++;
	}
	return upin;		/* Return input pointer */
+34 −6
Original line number Diff line number Diff line
@@ -276,7 +276,6 @@ int calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt,
		strncpy(password_with_pad, password, CIFS_ENCPWD_SIZE);

	if (!encrypt && global_secflags & CIFSSEC_MAY_PLNTXT) {
		memset(lnm_session_key, 0, CIFS_SESS_KEY_SIZE);
		memcpy(lnm_session_key, password_with_pad,
			CIFS_ENCPWD_SIZE);
		return 0;
@@ -414,7 +413,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
	int rc = 0;
	int len;
	char nt_hash[CIFS_NTHASH_SIZE];
	wchar_t *user;
	__le16 *user;
	wchar_t *domain;
	wchar_t *server;

@@ -439,7 +438,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
		return rc;
	}

	/* convert ses->user_name to unicode and uppercase */
	/* convert ses->user_name to unicode */
	len = ses->user_name ? strlen(ses->user_name) : 0;
	user = kmalloc(2 + (len * 2), GFP_KERNEL);
	if (user == NULL) {
@@ -448,7 +447,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
	}

	if (len) {
		len = cifs_strtoUTF16((__le16 *)user, ses->user_name, len, nls_cp);
		len = cifs_strtoUTF16(user, ses->user_name, len, nls_cp);
		UniStrupr(user);
	} else {
		memset(user, '\0', 2);
@@ -536,7 +535,7 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
		return rc;
	}

	if (ses->server->secType == RawNTLMSSP)
	if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED)
		memcpy(ses->auth_key.response + offset,
			ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
	else
@@ -568,7 +567,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
	char ntlmv2_hash[16];
	unsigned char *tiblob = NULL; /* target info blob */

	if (ses->server->secType == RawNTLMSSP) {
	if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) {
		if (!ses->domainName) {
			rc = find_domain_name(ses, nls_cp);
			if (rc) {
@@ -706,6 +705,9 @@ calc_seckey(struct cifs_ses *ses)
void
cifs_crypto_shash_release(struct TCP_Server_Info *server)
{
	if (server->secmech.cmacaes)
		crypto_free_shash(server->secmech.cmacaes);

	if (server->secmech.hmacsha256)
		crypto_free_shash(server->secmech.hmacsha256);

@@ -715,6 +717,8 @@ cifs_crypto_shash_release(struct TCP_Server_Info *server)
	if (server->secmech.hmacmd5)
		crypto_free_shash(server->secmech.hmacmd5);

	kfree(server->secmech.sdesccmacaes);

	kfree(server->secmech.sdeschmacsha256);

	kfree(server->secmech.sdeschmacmd5);
@@ -748,6 +752,13 @@ cifs_crypto_shash_allocate(struct TCP_Server_Info *server)
		goto crypto_allocate_hmacsha256_fail;
	}

	server->secmech.cmacaes = crypto_alloc_shash("cmac(aes)", 0, 0);
	if (IS_ERR(server->secmech.cmacaes)) {
		cifs_dbg(VFS, "could not allocate crypto cmac-aes");
		rc = PTR_ERR(server->secmech.cmacaes);
		goto crypto_allocate_cmacaes_fail;
	}

	size = sizeof(struct shash_desc) +
			crypto_shash_descsize(server->secmech.hmacmd5);
	server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL);
@@ -778,8 +789,22 @@ cifs_crypto_shash_allocate(struct TCP_Server_Info *server)
	server->secmech.sdeschmacsha256->shash.tfm = server->secmech.hmacsha256;
	server->secmech.sdeschmacsha256->shash.flags = 0x0;

	size = sizeof(struct shash_desc) +
			crypto_shash_descsize(server->secmech.cmacaes);
	server->secmech.sdesccmacaes = kmalloc(size, GFP_KERNEL);
	if (!server->secmech.sdesccmacaes) {
		cifs_dbg(VFS, "%s: Can't alloc cmacaes\n", __func__);
		rc = -ENOMEM;
		goto crypto_allocate_cmacaes_sdesc_fail;
	}
	server->secmech.sdesccmacaes->shash.tfm = server->secmech.cmacaes;
	server->secmech.sdesccmacaes->shash.flags = 0x0;

	return 0;

crypto_allocate_cmacaes_sdesc_fail:
	kfree(server->secmech.sdeschmacsha256);

crypto_allocate_hmacsha256_sdesc_fail:
	kfree(server->secmech.sdescmd5);

@@ -787,6 +812,9 @@ cifs_crypto_shash_allocate(struct TCP_Server_Info *server)
	kfree(server->secmech.sdeschmacmd5);

crypto_allocate_hmacmd5_sdesc_fail:
	crypto_free_shash(server->secmech.cmacaes);

crypto_allocate_cmacaes_fail:
	crypto_free_shash(server->secmech.hmacsha256);

crypto_allocate_hmacsha256_fail:
+7 −4
Original line number Diff line number Diff line
@@ -312,11 +312,14 @@ cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
}

static void
cifs_show_security(struct seq_file *s, struct TCP_Server_Info *server)
cifs_show_security(struct seq_file *s, struct cifs_ses *ses)
{
	if (ses->sectype == Unspecified)
		return;

	seq_printf(s, ",sec=");

	switch (server->secType) {
	switch (ses->sectype) {
	case LANMAN:
		seq_printf(s, "lanman");
		break;
@@ -338,7 +341,7 @@ cifs_show_security(struct seq_file *s, struct TCP_Server_Info *server)
		break;
	}

	if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
	if (ses->sign)
		seq_printf(s, "i");
}

@@ -369,7 +372,7 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
	srcaddr = (struct sockaddr *)&tcon->ses->server->srcaddr;

	seq_printf(s, ",vers=%s", tcon->ses->server->vals->version_string);
	cifs_show_security(s, tcon->ses->server);
	cifs_show_security(s, tcon->ses);
	cifs_show_cache_flavor(s, cifs_sb);

	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)
Loading