Commit 24420862 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag '4.14-smb3-multidialect-support-and-fixes-for-stable' of...

Merge tag '4.14-smb3-multidialect-support-and-fixes-for-stable' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs fixes from Steve French:
 "Convert default dialect to smb2.1 or later to allow connecting to
  Windows 7 for example, also includes some fixes for stable"

* tag '4.14-smb3-multidialect-support-and-fixes-for-stable' of git://git.samba.org/sfrench/cifs-2.6:
  Update version of cifs module
  cifs: hide unused functions
  SMB3: Add support for multidialect negotiate (SMB2.1 and later)
  CIFS/SMB3: Update documentation to reflect SMB3 and various changes
  cifs: check rsp for NULL before dereferencing in SMB2_open
parents ebb2c243 94a9daea
...@@ -41,6 +41,11 @@ Igor Mammedov (DFS support) ...@@ -41,6 +41,11 @@ Igor Mammedov (DFS support)
Jeff Layton (many, many fixes, as well as great work on the cifs Kerberos code) Jeff Layton (many, many fixes, as well as great work on the cifs Kerberos code)
Scott Lovenberg Scott Lovenberg
Pavel Shilovsky (for great work adding SMB2 support, and various SMB3 features) Pavel Shilovsky (for great work adding SMB2 support, and various SMB3 features)
Aurelien Aptel (for DFS SMB3 work and some key bug fixes)
Ronnie Sahlberg (for SMB3 xattr work and bug fixes)
Shirish Pargaonkar (for many ACL patches over the years)
Sachin Prabhu (many bug fixes, including for reconnect, copy offload and security)
Test case and Bug Report contributors Test case and Bug Report contributors
------------------------------------- -------------------------------------
......
The CIFS VFS support for Linux supports many advanced network filesystem This module supports the SMB3 family of advanced network protocols (as well
features such as hierarchical dfs like namespace, hardlinks, locking and more. as older dialects, originally called "CIFS" or SMB1).
The CIFS VFS module for Linux supports many advanced network filesystem
features such as hierarchical DFS like namespace, hardlinks, locking and more.
It was designed to comply with the SNIA CIFS Technical Reference (which It was designed to comply with the SNIA CIFS Technical Reference (which
supersedes the 1992 X/Open SMB Standard) as well as to perform best practice supersedes the 1992 X/Open SMB Standard) as well as to perform best practice
practical interoperability with Windows 2000, Windows XP, Samba and equivalent practical interoperability with Windows 2000, Windows XP, Samba and equivalent
servers. This code was developed in participation with the Protocol Freedom servers. This code was developed in participation with the Protocol Freedom
Information Foundation. Information Foundation. CIFS and now SMB3 has now become a defacto
standard for interoperating between Macs and Windows and major NAS appliances.
Please see Please see
http://protocolfreedom.org/ and http://protocolfreedom.org/ and
...@@ -15,30 +19,11 @@ for more details. ...@@ -15,30 +19,11 @@ for more details.
For questions or bug reports please contact: For questions or bug reports please contact:
sfrench@samba.org (sfrench@us.ibm.com) sfrench@samba.org (sfrench@us.ibm.com)
See the project page at: https://wiki.samba.org/index.php/LinuxCIFS_utils
Build instructions: Build instructions:
================== ==================
For Linux 2.4: For Linux:
1) Get the kernel source (e.g.from http://www.kernel.org)
and download the cifs vfs source (see the project page
at http://us1.samba.org/samba/Linux_CIFS_client.html)
and change directory into the top of the kernel directory
then patch the kernel (e.g. "patch -p1 < cifs_24.patch")
to add the cifs vfs to your kernel configure options if
it has not already been added (e.g. current SuSE and UL
users do not need to apply the cifs_24.patch since the cifs vfs is
already in the kernel configure menu) and then
mkdir linux/fs/cifs and then copy the current cifs vfs files from
the cifs download to your kernel build directory e.g.
cp <cifs_download_dir>/fs/cifs/* to <kernel_download_dir>/fs/cifs
2) make menuconfig (or make xconfig)
3) select cifs from within the network filesystem choices
4) save and exit
5) make dep
6) make modules (or "make" if CIFS VFS not to be built as a module)
For Linux 2.6:
1) Download the kernel (e.g. from http://www.kernel.org) 1) Download the kernel (e.g. from http://www.kernel.org)
and change directory into the top of the kernel directory tree and change directory into the top of the kernel directory tree
(e.g. /usr/src/linux-2.5.73) (e.g. /usr/src/linux-2.5.73)
...@@ -61,16 +46,13 @@ would simply type "make install"). ...@@ -61,16 +46,13 @@ would simply type "make install").
If you do not have the utility mount.cifs (in the Samba 3.0 source tree and on If you do not have the utility mount.cifs (in the Samba 3.0 source tree and on
the CIFS VFS web site) copy it to the same directory in which mount.smbfs and the CIFS VFS web site) copy it to the same directory in which mount.smbfs and
similar files reside (usually /sbin). Although the helper software is not similar files reside (usually /sbin). Although the helper software is not
required, mount.cifs is recommended. Eventually the Samba 3.0 utility program required, mount.cifs is recommended. Most distros include a "cifs-utils"
"net" may also be helpful since it may someday provide easier mount syntax for package that includes this utility so it is recommended to install this.
users who are used to Windows e.g.
net use <mount point> <UNC name or cifs URL>
Note that running the Winbind pam/nss module (logon service) on all of your Note that running the Winbind pam/nss module (logon service) on all of your
Linux clients is useful in mapping Uids and Gids consistently across the Linux clients is useful in mapping Uids and Gids consistently across the
domain to the proper network user. The mount.cifs mount helper can be domain to the proper network user. The mount.cifs mount helper can be
trivially built from Samba 3.0 or later source e.g. by executing: found at cifs-utils.git on git.samba.org
gcc samba/source/client/mount.cifs.c -o mount.cifs
If cifs is built as a module, then the size and number of network buffers If cifs is built as a module, then the size and number of network buffers
and maximum number of simultaneous requests to one server can be configured. and maximum number of simultaneous requests to one server can be configured.
...@@ -79,6 +61,18 @@ Changing these from their defaults is not recommended. By executing modinfo ...@@ -79,6 +61,18 @@ Changing these from their defaults is not recommended. By executing modinfo
on kernel/fs/cifs/cifs.ko the list of configuration changes that can be made on kernel/fs/cifs/cifs.ko the list of configuration changes that can be made
at module initialization time (by running insmod cifs.ko) can be seen. at module initialization time (by running insmod cifs.ko) can be seen.
Recommendations
===============
To improve security the SMB2.1 dialect or later (usually will get SMB3) is now
the new default. To use old dialects (e.g. to mount Windows XP) use "vers=1.0"
on mount (or vers=2.0 for Windows Vista). Note that the CIFS (vers=1.0) is
much older and less secure than the default dialect SMB3 which includes
many advanced security features such as downgrade attack detection
and encrypted shares and stronger signing and authentication algorithms.
There are additional mount options that may be helpful for SMB3 to get
improved POSIX behavior (NB: can use vers=3.0 to force only SMB3, never 2.1):
"mfsymlinks" and "cifsacl" and "idsfromsid"
Allowing User Mounts Allowing User Mounts
==================== ====================
To permit users to mount and unmount over directories they own is possible To permit users to mount and unmount over directories they own is possible
...@@ -98,9 +92,7 @@ and execution of suid programs on the remote target would be enabled ...@@ -98,9 +92,7 @@ and execution of suid programs on the remote target would be enabled
by default. This can be changed, as with nfs and other filesystems, by default. This can be changed, as with nfs and other filesystems,
by simply specifying "nosuid" among the mount options. For user mounts by simply specifying "nosuid" among the mount options. For user mounts
though to be able to pass the suid flag to mount requires rebuilding though to be able to pass the suid flag to mount requires rebuilding
mount.cifs with the following flag: mount.cifs with the following flag: CIFS_ALLOW_USR_SUID
gcc samba/source/client/mount.cifs.c -DCIFS_ALLOW_USR_SUID -o mount.cifs
There is a corresponding manual page for cifs mounting in the Samba 3.0 and There is a corresponding manual page for cifs mounting in the Samba 3.0 and
later source tree in docs/manpages/mount.cifs.8 later source tree in docs/manpages/mount.cifs.8
...@@ -189,18 +181,18 @@ applications running on the same server as Samba. ...@@ -189,18 +181,18 @@ applications running on the same server as Samba.
Use instructions: Use instructions:
================ ================
Once the CIFS VFS support is built into the kernel or installed as a module Once the CIFS VFS support is built into the kernel or installed as a module
(cifs.o), you can use mount syntax like the following to access Samba or Windows (cifs.ko), you can use mount syntax like the following to access Samba or
servers: Mac or Windows servers:
mount -t cifs //9.53.216.11/e$ /mnt -o user=myname,pass=mypassword mount -t cifs //9.53.216.11/e$ /mnt -o username=myname,password=mypassword
Before -o the option -v may be specified to make the mount.cifs Before -o the option -v may be specified to make the mount.cifs
mount helper display the mount steps more verbosely. mount helper display the mount steps more verbosely.
After -o the following commonly used cifs vfs specific options After -o the following commonly used cifs vfs specific options
are supported: are supported:
user=<username> username=<username>
pass=<password> password=<password>
domain=<domain name> domain=<domain name>
Other cifs mount options are described below. Use of TCP names (in addition to Other cifs mount options are described below. Use of TCP names (in addition to
...@@ -246,13 +238,16 @@ the Server's registry. Samba starting with version 3.10 will allow such ...@@ -246,13 +238,16 @@ the Server's registry. Samba starting with version 3.10 will allow such
filenames (ie those which contain valid Linux characters, which normally filenames (ie those which contain valid Linux characters, which normally
would be forbidden for Windows/CIFS semantics) as long as the server is would be forbidden for Windows/CIFS semantics) as long as the server is
configured for Unix Extensions (and the client has not disabled configured for Unix Extensions (and the client has not disabled
/proc/fs/cifs/LinuxExtensionsEnabled). /proc/fs/cifs/LinuxExtensionsEnabled). In addition the mount option
"mapposix" can be used on CIFS (vers=1.0) to force the mapping of
illegal Windows/NTFS/SMB characters to a remap range (this mount parm
is the default for SMB3). This remap ("mapposix") range is also
compatible with Mac (and "Services for Mac" on some older Windows).
CIFS VFS Mount Options CIFS VFS Mount Options
====================== ======================
A partial list of the supported mount options follows: A partial list of the supported mount options follows:
user The user name to use when trying to establish username The user name to use when trying to establish
the CIFS session. the CIFS session.
password The user password. If the mount helper is password The user password. If the mount helper is
installed, the user will be prompted for password installed, the user will be prompted for password
......
Version 2.03 August 1, 2014 Version 2.04 September 13, 2017
A Partial List of Missing Features A Partial List of Missing Features
================================== ==================================
...@@ -8,73 +8,69 @@ for visible, important contributions to this module. Here ...@@ -8,73 +8,69 @@ for visible, important contributions to this module. Here
is a partial list of the known problems and missing features: is a partial list of the known problems and missing features:
a) SMB3 (and SMB3.02) missing optional features: a) SMB3 (and SMB3.02) missing optional features:
- RDMA - RDMA (started)
- multichannel (started) - multichannel (started)
- directory leases (improved metadata caching) - directory leases (improved metadata caching)
- T10 copy offload (copy chunk is only mechanism supported) - T10 copy offload (copy chunk is only mechanism supported)
- encrypted shares
b) improved sparse file support b) improved sparse file support
c) Directory entry caching relies on a 1 second timer, rather than c) Directory entry caching relies on a 1 second timer, rather than
using FindNotify or equivalent. - (started) using Directory Leases
d) quota support (needs minor kernel change since quota calls d) quota support (needs minor kernel change since quota calls
to make it to network filesystems or deviceless filesystems) to make it to network filesystems or deviceless filesystems)
e) improve support for very old servers (OS/2 and Win9x for example) e) Better optimize open to reduce redundant opens (using reference
Including support for changing the time remotely (utimes command). counts more) and to improve use of compounding in SMB3 to reduce
number of roundtrips.
f) hook lower into the sockets api (as NFS/SunRPC does) to avoid the f) Finish inotify support so kde and gnome file list windows
extra copy in/out of the socket buffers in some cases.
g) Better optimize open (and pathbased setfilesize) to reduce the
oplock breaks coming from windows srv. Piggyback identical file
opens on top of each other by incrementing reference count rather
than resending (helps reduce server resource utilization and avoid
spurious oplock breaks).
h) Add support for storing symlink info to Windows servers
in the Extended Attribute format their SFU clients would recognize.
i) Finish inotify support so kde and gnome file list windows
will autorefresh (partially complete by Asser). Needs minor kernel will autorefresh (partially complete by Asser). Needs minor kernel
vfs change to support removing D_NOTIFY on a file. vfs change to support removing D_NOTIFY on a file.
j) Add GUI tool to configure /proc/fs/cifs settings and for display of g) Add GUI tool to configure /proc/fs/cifs settings and for display of
the CIFS statistics (started) the CIFS statistics (started)
k) implement support for security and trusted categories of xattrs h) implement support for security and trusted categories of xattrs
(requires minor protocol extension) to enable better support for SELINUX (requires minor protocol extension) to enable better support for SELINUX
l) Implement O_DIRECT flag on open (already supported on mount) i) Implement O_DIRECT flag on open (already supported on mount)
m) Create UID mapping facility so server UIDs can be mapped on a per j) Create UID mapping facility so server UIDs can be mapped on a per
mount or a per server basis to client UIDs or nobody if no mapping mount or a per server basis to client UIDs or nobody if no mapping
exists. This is helpful when Unix extensions are negotiated to exists. Also better integration with winbind for resolving SID owners
allow better permission checking when UIDs differ on the server
and client. Add new protocol request to the CIFS protocol k) Add tools to take advantage of more smb3 specific ioctls and features
standard for asking the server for the corresponding name of a
particular uid. l) encrypted file support
m) improved stats gathering, tools (perhaps integration with nfsometer?)
n) DOS attrs - returned as pseudo-xattr in Samba format (check VFAT and NTFS for this too) n) allow setting more NTFS/SMB3 file attributes remotely (currently limited to compressed
file attribute via chflags) and improve user space tools for managing and
viewing them.
o) mount check for unmatched uids o) mount helper GUI (to simplify the various configuration options on mount)
p) Add support for new vfs entry point for fallocate p) autonegotiation of dialects (offering more than one dialect ie SMB3.02,
SMB3, SMB2.1 not just SMB3).
q) Add tools to take advantage of cifs/smb3 specific ioctls and features q) Allow mount.cifs to be more verbose in reporting errors with dialect
such as "CopyChunk" (fast server side file copy) or unsupported feature errors.
r) encrypted file support r) updating cifs documentation, and user guid.
s) improved stats gathering, tools (perhaps integration with nfsometer?) s) Addressing bugs found by running a broader set of xfstests in standard
file system xfstest suite.
t) allow setting more NTFS/SMB3 file attributes remotely (currently limited to compressed t) split cifs and smb3 support into separate modules so legacy (and less
file attribute via chflags) secure) CIFS dialect can be disabled in environments that don't need it
and simplify the code.
u) mount helper GUI (to simplify the various configuration options on mount) u) Finish up SMB3.1.1 dialect support
v) POSIX Extensions for SMB3.1.1
KNOWN BUGS KNOWN BUGS
==================================== ====================================
......
This is the client VFS module for the Common Internet File System This is the client VFS module for the SMB3 NAS protocol as well
(CIFS) protocol which is the successor to the Server Message Block older dialects such as the Common Internet File System (CIFS)
protocol which was the successor to the Server Message Block
(SMB) protocol, the native file sharing mechanism for most early (SMB) protocol, the native file sharing mechanism for most early
PC operating systems. New and improved versions of CIFS are now PC operating systems. New and improved versions of CIFS are now
called SMB2 and SMB3. These dialects are also supported by the called SMB2 and SMB3. These dialects are also supported by the
CIFS VFS module. CIFS is fully supported by network CIFS VFS module. CIFS is fully supported by network
file servers such as Windows 2000, 2003, 2008 and 2012 file servers such as Windows 2000, 2003, 2008, 2012 and 2016
as well by Samba (which provides excellent CIFS as well by Samba (which provides excellent CIFS
server support for Linux and many other operating systems), so server support for Linux and many other operating systems), Apple
systems, as well as most Network Attached Storage vendors, so
this network filesystem client can mount to a wide variety of this network filesystem client can mount to a wide variety of
servers. servers.
The intent of this module is to provide the most advanced network The intent of this module is to provide the most advanced network
file system function for CIFS compliant servers, including better file system function for SMB3 compliant servers, including advanced
POSIX compliance, secure per-user session establishment, high security features, excellent parallelized high performance i/o, better
performance safe distributed caching (oplock), optional packet POSIX compliance, secure per-user session establishment, encryption,
high performance safe distributed caching (leases/oplocks), optional packet
signing, large files, Unicode support and other internationalization signing, large files, Unicode support and other internationalization
improvements. Since both Samba server and this filesystem client support improvements. Since both Samba server and this filesystem client support
the CIFS Unix extensions, the combination can provide a reasonable the CIFS Unix extensions (and in the future SMB3 POSIX extensions),
alternative to NFSv4 for fileserving in some Linux to Linux environments, the combination can provide a reasonable alternative to other network and
not just in Linux to Windows environments. cluster file systems for fileserving in some Linux to Linux environments,
not just in Linux to Windows (or Linux to Mac) environments.
This filesystem has an mount utility (mount.cifs) that can be obtained from This filesystem has an mount utility (mount.cifs) that can be obtained from
......
...@@ -149,5 +149,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); ...@@ -149,5 +149,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
extern const struct export_operations cifs_export_ops; extern const struct export_operations cifs_export_ops;
#endif /* CONFIG_CIFS_NFSD_EXPORT */ #endif /* CONFIG_CIFS_NFSD_EXPORT */
#define CIFS_VERSION "2.09" #define CIFS_VERSION "2.10"
#endif /* _CIFSFS_H */ #endif /* _CIFSFS_H */
...@@ -188,6 +188,8 @@ enum smb_version { ...@@ -188,6 +188,8 @@ enum smb_version {
#ifdef CONFIG_CIFS_SMB311 #ifdef CONFIG_CIFS_SMB311
Smb_311, Smb_311,
#endif /* SMB311 */ #endif /* SMB311 */
Smb_3any,
Smb_default,
Smb_version_err Smb_version_err
}; };
...@@ -1701,6 +1703,10 @@ extern struct smb_version_values smb20_values; ...@@ -1701,6 +1703,10 @@ extern struct smb_version_values smb20_values;
#define SMB21_VERSION_STRING "2.1" #define SMB21_VERSION_STRING "2.1"
extern struct smb_version_operations smb21_operations; extern struct smb_version_operations smb21_operations;
extern struct smb_version_values smb21_values; extern struct smb_version_values smb21_values;
#define SMBDEFAULT_VERSION_STRING "default"
extern struct smb_version_values smbdefault_values;
#define SMB3ANY_VERSION_STRING "3"
extern struct smb_version_values smb3any_values;
#define SMB30_VERSION_STRING "3.0" #define SMB30_VERSION_STRING "3.0"
extern struct smb_version_operations smb30_operations; extern struct smb_version_operations smb30_operations;
extern struct smb_version_values smb30_values; extern struct smb_version_values smb30_values;
......
...@@ -301,6 +301,8 @@ static const match_table_t cifs_smb_version_tokens = { ...@@ -301,6 +301,8 @@ static const match_table_t cifs_smb_version_tokens = {
{ Smb_311, SMB311_VERSION_STRING }, { Smb_311, SMB311_VERSION_STRING },
{ Smb_311, ALT_SMB311_VERSION_STRING }, { Smb_311, ALT_SMB311_VERSION_STRING },
#endif /* SMB311 */ #endif /* SMB311 */
{ Smb_3any, SMB3ANY_VERSION_STRING },
{ Smb_default, SMBDEFAULT_VERSION_STRING },
{ Smb_version_err, NULL } { Smb_version_err, NULL }
}; };
...@@ -1148,6 +1150,14 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol) ...@@ -1148,6 +1150,14 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol)
vol->vals = &smb311_values; vol->vals = &smb311_values;
break; break;
#endif /* SMB311 */ #endif /* SMB311 */
case Smb_3any:
vol->ops = &smb30_operations; /* currently identical with 3.0 */
vol->vals = &smb3any_values;
break;
case Smb_default:
vol->ops = &smb30_operations; /* currently identical with 3.0 */
vol->vals = &smbdefault_values;
break;
default: default:
cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value); cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
return 1; return 1;
...@@ -1274,9 +1284,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, ...@@ -1274,9 +1284,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
vol->actimeo = CIFS_DEF_ACTIMEO; vol->actimeo = CIFS_DEF_ACTIMEO;
/* FIXME: add autonegotiation for SMB3 or later rather than just SMB3 */ /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
vol->ops = &smb30_operations; /* both secure and accepted widely */ vol->ops = &smb30_operations;
vol->vals = &smb30_values; vol->vals = &smbdefault_values;
vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT; vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
...@@ -1988,11 +1998,10 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, ...@@ -1988,11 +1998,10 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
if (got_version == false) if (got_version == false)
pr_warn("No dialect specified on mount. Default has changed to " pr_warn("No dialect specified on mount. Default has changed to "
"a more secure dialect, SMB3 (vers=3.0), from CIFS " "a more secure dialect, SMB2.1 or later (e.g. SMB3), from CIFS "
"(SMB1). To use the less secure SMB1 dialect to access " "(SMB1). To use the less secure SMB1 dialect to access "
"old servers which do not support SMB3 specify vers=1.0" "old servers which do not support SMB3 (or SMB2.1) specify vers=1.0"
" on mount. For somewhat newer servers such as Windows " " on mount.\n");
"7 try vers=2.1.\n");
kfree(mountdata_copy); kfree(mountdata_copy);
return 0; return 0;
...@@ -2133,6 +2142,7 @@ static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol) ...@@ -2133,6 +2142,7 @@ static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
if (vol->nosharesock) if (vol->nosharesock)
return 0; return 0;
/* BB update this for smb3any and default case */
if ((server->vals != vol->vals) || (server->ops != vol->ops)) if ((server->vals != vol->vals) || (server->ops != vol->ops))
return 0; return 0;
......
...@@ -426,6 +426,7 @@ smb2_query_file_info(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -426,6 +426,7 @@ smb2_query_file_info(const unsigned int xid, struct cifs_tcon *tcon,
return rc; return rc;
} }
#ifdef CONFIG_CIFS_XATTR
static ssize_t static ssize_t
move_smb2_ea_to_cifs(char *dst, size_t dst_size, move_smb2_ea_to_cifs(char *dst, size_t dst_size,
struct smb2_file_full_ea_info *src, size_t src_size, struct smb2_file_full_ea_info *src, size_t src_size,
...@@ -613,6 +614,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -613,6 +614,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
return rc; return rc;
} }
#endif
static bool static bool
smb2_can_echo(struct TCP_Server_Info *server) smb2_can_echo(struct TCP_Server_Info *server)
...@@ -3110,6 +3112,46 @@ struct smb_version_values smb21_values = { ...@@ -3110,6 +3112,46 @@ struct smb_version_values smb21_values = {
.create_lease_size = sizeof(struct create_lease), .create_lease_size = sizeof(struct create_lease),
}; };
struct smb_version_values smb3any_values = {
.version_string = SMB3ANY_VERSION_STRING,
.protocol_id = SMB302_PROT_ID, /* doesn't matter, send protocol array */
.req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION,
.large_lock_type = 0,
.exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
.shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
.header_size = sizeof(struct smb2_hdr),
.max_header_size = MAX_SMB2_HDR_SIZE,
.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
.lock_cmd = SMB2_LOCK,
.cap_unix = 0,
.cap_nt_find = SMB2_NT_FIND,
.cap_large_files = SMB2_LARGE_FILES,
.signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
.signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
.create_lease_size = sizeof(struct create_lease_v2),
};
struct smb_version_values smbdefault_values = {
.version_string = SMBDEFAULT_VERSION_STRING,
.protocol_id = SMB302_PROT_ID, /* doesn't matter, send protocol array */
.req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION,
.large_lock_type = 0,
.exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
.shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
.header_size = sizeof(struct smb2_hdr),
.max_header_size = MAX_SMB2_HDR_SIZE,
.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
.lock_cmd = SMB2_LOCK,
.cap_unix = 0,
.cap_nt_find = SMB2_NT_FIND,
.cap_large_files = SMB2_LARGE_FILES,
.signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
.signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
.create_lease_size = sizeof(struct create_lease_v2),
};
struct smb_version_values smb30_values = { struct smb_version_values smb30_values = {
.version_string = SMB30_VERSION_STRING, .version_string = SMB30_VERSION_STRING,
.protocol_id = SMB30_PROT_ID, .protocol_id = SMB30_PROT_ID,
......
...@@ -491,10 +491,25 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) ...@@ -491,10 +491,25 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
req->hdr.sync_hdr.SessionId = 0; req->hdr.sync_hdr.SessionId = 0;
if (strcmp(ses->server->vals->version_string,
SMB3ANY_VERSION_STRING) == 0) {
req->Dialects[0] = cpu_to_le16(SMB30_PROT_ID);
req->Dialects[1] = cpu_to_le16(SMB302_PROT_ID);
req->DialectCount = cpu_to_le16(2);
inc_rfc1001_len(req, 4);
} else if (strcmp(ses->server->vals->version_string,
SMBDEFAULT_VERSION_STRING) == 0) {
req->Dialects[0] = cpu_to_le16(SMB21_PROT_ID);
req->Dialects[1] = cpu_to_le16(SMB30_PROT_ID);
req->Dialects[2] = cpu_to_le16(SMB302_PROT_ID);
req->DialectCount = cpu_to_le16(3);
inc_rfc1001_len(req, 6);
} else {
/* otherwise send specific dialect */
req->Dialects[0] = cpu_to_le16(ses->server->vals->protocol_id); req->Dialects[0] = cpu_to_le16(ses->server->vals->protocol_id);
req->DialectCount = cpu_to_le16(1);
req->DialectCount = cpu_to_le16(1); /* One vers= at a time for now */
inc_rfc1001_len(req, 2); inc_rfc1001_len(req, 2);
}
/* only one of SMB2 signing flags may be set in SMB2 request */ /* only one of SMB2 signing flags may be set in SMB2 request */
if (ses->sign) if (ses->sign)
...@@ -528,16 +543,42 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) ...@@ -528,16 +543,42 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
*/ */
if (rc == -EOPNOTSUPP) { if (rc == -EOPNOTSUPP) {
cifs_dbg(VFS, "Dialect not supported by server. Consider " cifs_dbg(VFS, "Dialect not supported by server. Consider "
"specifying vers=1.0 or vers=2.1 on mount for accessing" "specifying vers=1.0 or vers=2.0 on mount for accessing"
" older servers\n"); " older servers\n");
goto neg_exit; goto neg_exit;
} else if (rc != 0) } else if (rc != 0)
goto neg_exit; goto neg_exit;
if (strcmp(ses->server->vals->version_string,
SMB3ANY_VERSION_STRING) == 0) {
if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) {
cifs_dbg(VFS,
"SMB2 dialect returned but not requested\n");
return -EIO;
} else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) {
cifs_dbg(VFS,
"SMB2.1 dialect returned but not requested\n");
return -EIO;
}
} else if (strcmp(ses->server->vals->version_string,
SMBDEFAULT_VERSION_STRING) == 0) {
if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) {
cifs_dbg(VFS,
"SMB2 dialect returned but not requested\n");
return -EIO;
} else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) {
/* ops set to 3.0 by default for default so update */
ses->server->ops = &smb21_operations;
}
} else if (rsp->DialectRevision != ses->server->vals->protocol_id) {
/* if requested single dialect ensure returned dialect matched */
cifs_dbg(VFS, "Illegal 0x%x dialect returned: not requested\n",
cpu_to_le16(rsp->DialectRevision));
return -EIO;
}
cifs_dbg(FYI, "mode 0x%x\n", rsp->SecurityMode); cifs_dbg(FYI, "mode 0x%x\n", rsp->SecurityMode);
/* BB we may eventually want to match the negotiated vs. requested
dialect, even though we are only requesting one at a time */
if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID))
cifs_dbg(FYI, "negotiated smb2.0 dialect\n"); cifs_dbg(FYI, "negotiated smb2.0 dialect\n");
else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID))
...@@ -558,6 +599,8 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) ...@@ -558,6 +599,8 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
} }
server->dialect = le16_to_cpu(rsp->DialectRevision); server->dialect = le16_to_cpu(rsp->DialectRevision);
/* BB: add check that dialect was valid given dialect(s) we asked for */
/* SMB2 only has an extended negflavor */ /* SMB2 only has an extended negflavor */
server->negflavor = CIFS_NEGFLAVOR_EXTENDED; server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
/* set it to the maximum buffer size value we can send with 1 credit */ /* set it to the maximum buffer size value we can send with 1 credit */
...@@ -606,6 +649,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) ...@@ -606,6 +649,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
struct validate_negotiate_info_req vneg_inbuf; struct validate_negotiate_info_req vneg_inbuf;
struct validate_negotiate_info_rsp *pneg_rsp; struct validate_negotiate_info_rsp *pneg_rsp;
u32 rsplen; u32 rsplen;
u32 inbuflen; /* max of 4 dialects */
cifs_dbg(FYI, "validate negotiate\n"); cifs_dbg(FYI, "validate negotiate\n");
...@@ -634,9 +678,30 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) ...@@ -634,9 +678,30 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
else else
vneg_inbuf.SecurityMode = 0; vneg_inbuf.SecurityMode = 0;
vneg_inbuf.DialectCount = cpu_to_le16(1);
if (strcmp(tcon->ses->server->vals->version_string,
SMB3ANY_VERSION_STRING) == 0) {
vneg_inbuf.Dialects[0] = cpu_to_le16(SMB30_PROT_ID);
vneg_inbuf.Dialects[1] = cpu_to_le16(SMB302_PROT_ID);
vneg_inbuf.DialectCount = cpu_to_le16(2);
/* structure is big enough for 3 dialects, sending only 2 */
inbuflen = sizeof(struct validate_negotiate_info_req) - 2;
} else if (strcmp(tcon->ses->server->vals->version_string,
SMBDEFAULT_VERSION_STRING) == 0) {
vneg_inbuf.Dialects[0] = cpu_to_le16(SMB21_PROT_ID);
vneg_inbuf.Dialects[1] = cpu_to_le16(SMB30_PROT_ID);
vneg_inbuf.Dialects[2] = cpu_to_le16(SMB302_PROT_ID);
vneg_inbuf.DialectCount = cpu_to_le16(3);
/* structure is big enough for 3 dialects */
inbuflen = sizeof(struct validate_negotiate_info_req);
} else {
/* otherwise specific dialect was requested */
vneg_inbuf.Dialects[0] = vneg_inbuf.Dialects[0] =
cpu_to_le16(tcon->ses->server->vals->protocol_id); cpu_to_le16(tcon->ses->server->vals->protocol_id);
vneg_inbuf.DialectCount = cpu_to_le16(1);
/* structure is big enough for 3 dialects, sending only 1 */
inbuflen = sizeof(struct validate_negotiate_info_req) - 4;
}
rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID, rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
FSCTL_VALIDATE_NEGOTIATE_INFO, true /* is_fsctl */, FSCTL_VALIDATE_NEGOTIATE_INFO, true /* is_fsctl */,
...@@ -1634,7 +1699,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, ...@@ -1634,7 +1699,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
struct cifs_tcon *tcon = oparms->tcon; struct cifs_tcon *tcon = oparms->tcon;
struct cifs_ses *ses = tcon->ses; struct cifs_ses *ses = tcon->ses;
struct kvec iov[4]; struct kvec iov[4];
struct kvec rsp_iov; struct kvec rsp_iov = {NULL, 0};
int resp_buftype; int resp_buftype;
int uni_path_len; int uni_path_len;
__le16 *copy_path = NULL; __le16 *copy_path = NULL;
...@@ -1763,7 +1828,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, ...@@ -1763,7 +1828,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
if (rc != 0) { if (rc != 0) {
cifs_stats_fail_inc(tcon, SMB2_CREATE_HE); cifs_stats_fail_inc(tcon, SMB2_CREATE_HE);
if (err_buf) if (err_buf && rsp)
*err_buf = kmemdup(rsp, get_rfc1002_length(rsp) + 4, *err_buf = kmemdup(rsp, get_rfc1002_length(rsp) + 4,
GFP_KERNEL); GFP_KERNEL);
goto creat_exit; goto creat_exit;
......
...@@ -716,7 +716,7 @@ struct validate_negotiate_info_req { ...@@ -716,7 +716,7 @@ struct validate_negotiate_info_req {
__u8 Guid[SMB2_CLIENT_GUID_SIZE]; __u8 Guid[SMB2_CLIENT_GUID_SIZE];
__le16 SecurityMode; __le16 SecurityMode;
__le16 DialectCount; __le16 DialectCount;
__le16 Dialects[1]; /* dialect (someday maybe list) client asked for */ __le16 Dialects[3]; /* BB expand this if autonegotiate > 3 dialects */
} __packed; } __packed;
struct validate_negotiate_info_rsp { struct validate_negotiate_info_rsp {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment