mirror of
https://github.com/armbian/linux-cix.git
synced 2026-01-06 12:30:45 -08:00
Merge tag '5.15-rc-first-ksmbd-merge' of git://git.samba.org/ksmbd
Pull initial ksmbd implementation from Steve French:
"Initial merge of kernel smb3 file server, ksmbd.
The SMB family of protocols is the most widely deployed network
filesystem protocol, the default on Windows and Macs (and even on many
phones and tablets), with clients and servers on all major operating
systems, but lacked a kernel server for Linux. For many cases the
current userspace server choices were suboptimal either due to memory
footprint, performance or difficulty integrating well with advanced
Linux features.
ksmbd is a new kernel module which implements the server-side of the
SMB3 protocol. The target is to provide optimized performance, GPLv2
SMB server, and better lease handling (distributed caching). The
bigger goal is to add new features more rapidly (e.g. RDMA aka
"smbdirect", and recent encryption and signing improvements to the
protocol) which are easier to develop on a smaller, more tightly
optimized kernel server than for example in Samba.
The Samba project is much broader in scope (tools, security services,
LDAP, Active Directory Domain Controller, and a cross platform file
server for a wider variety of purposes) but the user space file server
portion of Samba has proved hard to optimize for some Linux workloads,
including for smaller devices.
This is not meant to replace Samba, but rather be an extension to
allow better optimizing for Linux, and will continue to integrate well
with Samba user space tools and libraries where appropriate. Working
with the Samba team we have already made sure that the configuration
files and xattrs are in a compatible format between the kernel and
user space server.
Various types of functional and regression tests are regularly run
against it. One example is the automated 'buildbot' regression tests
which use the Linux client to test against ksmbd, e.g.
http://smb3-test-rhel-75.southcentralus.cloudapp.azure.com/#/builders/8/builds/56
but other test suites, including Samba's smbtorture functional test
suite are also used regularly"
* tag '5.15-rc-first-ksmbd-merge' of git://git.samba.org/ksmbd: (219 commits)
ksmbd: fix __write_overflow warning in ndr_read_string
MAINTAINERS: ksmbd: add cifs_common directory to ksmbd entry
MAINTAINERS: ksmbd: update my email address
ksmbd: fix permission check issue on chown and chmod
ksmbd: don't set FILE DELETE and FILE_DELETE_CHILD in access mask by default
MAINTAINERS: add git adddress of ksmbd
ksmbd: update SMB3 multi-channel support in ksmbd.rst
ksmbd: smbd: fix kernel oops during server shutdown
ksmbd: remove select FS_POSIX_ACL in Kconfig
ksmbd: use proper errno instead of -1 in smb2_get_ksmbd_tcon()
ksmbd: update the comment for smb2_get_ksmbd_tcon()
ksmbd: change int data type to boolean
ksmbd: Fix multi-protocol negotiation
ksmbd: fix an oops in error handling in smb2_open()
ksmbd: add ipv6_addr_v4mapped check to know if connection from client is ipv4
ksmbd: fix missing error code in smb2_lock
ksmbd: use channel signingkey for binding SMB2 session setup
ksmbd: don't set RSS capable in FSCTL_QUERY_NETWORK_INTERFACE_INFO
ksmbd: Return STATUS_OBJECT_PATH_NOT_FOUND if smb2_creat() returns ENOENT
ksmbd: fix -Wstringop-truncation warnings
...
This commit is contained in:
10
Documentation/filesystems/cifs/index.rst
Normal file
10
Documentation/filesystems/cifs/index.rst
Normal file
@@ -0,0 +1,10 @@
|
||||
===============================
|
||||
CIFS
|
||||
===============================
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
ksmbd
|
||||
cifsroot
|
||||
165
Documentation/filesystems/cifs/ksmbd.rst
Normal file
165
Documentation/filesystems/cifs/ksmbd.rst
Normal file
@@ -0,0 +1,165 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
==========================
|
||||
KSMBD - SMB3 Kernel Server
|
||||
==========================
|
||||
|
||||
KSMBD is a linux kernel server which implements SMB3 protocol in kernel space
|
||||
for sharing files over network.
|
||||
|
||||
KSMBD architecture
|
||||
==================
|
||||
|
||||
The subset of performance related operations belong in kernelspace and
|
||||
the other subset which belong to operations which are not really related with
|
||||
performance in userspace. So, DCE/RPC management that has historically resulted
|
||||
into number of buffer overflow issues and dangerous security bugs and user
|
||||
account management are implemented in user space as ksmbd.mountd.
|
||||
File operations that are related with performance (open/read/write/close etc.)
|
||||
in kernel space (ksmbd). This also allows for easier integration with VFS
|
||||
interface for all file operations.
|
||||
|
||||
ksmbd (kernel daemon)
|
||||
---------------------
|
||||
|
||||
When the server daemon is started, It starts up a forker thread
|
||||
(ksmbd/interface name) at initialization time and open a dedicated port 445
|
||||
for listening to SMB requests. Whenever new clients make request, Forker
|
||||
thread will accept the client connection and fork a new thread for dedicated
|
||||
communication channel between the client and the server. It allows for parallel
|
||||
processing of SMB requests(commands) from clients as well as allowing for new
|
||||
clients to make new connections. Each instance is named ksmbd/1~n(port number)
|
||||
to indicate connected clients. Depending on the SMB request types, each new
|
||||
thread can decide to pass through the commands to the user space (ksmbd.mountd),
|
||||
currently DCE/RPC commands are identified to be handled through the user space.
|
||||
To further utilize the linux kernel, it has been chosen to process the commands
|
||||
as workitems and to be executed in the handlers of the ksmbd-io kworker threads.
|
||||
It allows for multiplexing of the handlers as the kernel take care of initiating
|
||||
extra worker threads if the load is increased and vice versa, if the load is
|
||||
decreased it destroys the extra worker threads. So, after connection is
|
||||
established with client. Dedicated ksmbd/1..n(port number) takes complete
|
||||
ownership of receiving/parsing of SMB commands. Each received command is worked
|
||||
in parallel i.e., There can be multiple clients commands which are worked in
|
||||
parallel. After receiving each command a separated kernel workitem is prepared
|
||||
for each command which is further queued to be handled by ksmbd-io kworkers.
|
||||
So, each SMB workitem is queued to the kworkers. This allows the benefit of load
|
||||
sharing to be managed optimally by the default kernel and optimizing client
|
||||
performance by handling client commands in parallel.
|
||||
|
||||
ksmbd.mountd (user space daemon)
|
||||
--------------------------------
|
||||
|
||||
ksmbd.mountd is userspace process to, transfer user account and password that
|
||||
are registered using ksmbd.adduser(part of utils for user space). Further it
|
||||
allows sharing information parameters that parsed from smb.conf to ksmbd in
|
||||
kernel. For the execution part it has a daemon which is continuously running
|
||||
and connected to the kernel interface using netlink socket, it waits for the
|
||||
requests(dcerpc and share/user info). It handles RPC calls (at a minimum few
|
||||
dozen) that are most important for file server from NetShareEnum and
|
||||
NetServerGetInfo. Complete DCE/RPC response is prepared from the user space
|
||||
and passed over to the associated kernel thread for the client.
|
||||
|
||||
|
||||
KSMBD Feature Status
|
||||
====================
|
||||
|
||||
============================== =================================================
|
||||
Feature name Status
|
||||
============================== =================================================
|
||||
Dialects Supported. SMB2.1 SMB3.0, SMB3.1.1 dialects
|
||||
(intentionally excludes security vulnerable SMB1
|
||||
dialect).
|
||||
Auto Negotiation Supported.
|
||||
Compound Request Supported.
|
||||
Oplock Cache Mechanism Supported.
|
||||
SMB2 leases(v1 lease) Supported.
|
||||
Directory leases(v2 lease) Planned for future.
|
||||
Multi-credits Supported.
|
||||
NTLM/NTLMv2 Supported.
|
||||
HMAC-SHA256 Signing Supported.
|
||||
Secure negotiate Supported.
|
||||
Signing Update Supported.
|
||||
Pre-authentication integrity Supported.
|
||||
SMB3 encryption(CCM, GCM) Supported. (CCM and GCM128 supported, GCM256 in
|
||||
progress)
|
||||
SMB direct(RDMA) Partially Supported. SMB3 Multi-channel is
|
||||
required to connect to Windows client.
|
||||
SMB3 Multi-channel Partially Supported. Planned to implement
|
||||
replay/retry mechanisms for future.
|
||||
SMB3.1.1 POSIX extension Supported.
|
||||
ACLs Partially Supported. only DACLs available, SACLs
|
||||
(auditing) is planned for the future. For
|
||||
ownership (SIDs) ksmbd generates random subauth
|
||||
values(then store it to disk) and use uid/gid
|
||||
get from inode as RID for local domain SID.
|
||||
The current acl implementation is limited to
|
||||
standalone server, not a domain member.
|
||||
Integration with Samba tools is being worked on
|
||||
to allow future support for running as a domain
|
||||
member.
|
||||
Kerberos Supported.
|
||||
Durable handle v1,v2 Planned for future.
|
||||
Persistent handle Planned for future.
|
||||
SMB2 notify Planned for future.
|
||||
Sparse file support Supported.
|
||||
DCE/RPC support Partially Supported. a few calls(NetShareEnumAll,
|
||||
NetServerGetInfo, SAMR, LSARPC) that are needed
|
||||
for file server handled via netlink interface
|
||||
from ksmbd.mountd. Additional integration with
|
||||
Samba tools and libraries via upcall is being
|
||||
investigated to allow support for additional
|
||||
DCE/RPC management calls (and future support
|
||||
for Witness protocol e.g.)
|
||||
ksmbd/nfsd interoperability Planned for future. The features that ksmbd
|
||||
support are Leases, Notify, ACLs and Share modes.
|
||||
============================== =================================================
|
||||
|
||||
|
||||
How to run
|
||||
==========
|
||||
|
||||
1. Download ksmbd-tools and compile them.
|
||||
- https://github.com/cifsd-team/ksmbd-tools
|
||||
|
||||
2. Create user/password for SMB share.
|
||||
|
||||
# mkdir /etc/ksmbd/
|
||||
# ksmbd.adduser -a <Enter USERNAME for SMB share access>
|
||||
|
||||
3. Create /etc/ksmbd/smb.conf file, add SMB share in smb.conf file
|
||||
- Refer smb.conf.example and
|
||||
https://github.com/cifsd-team/ksmbd-tools/blob/master/Documentation/configuration.txt
|
||||
|
||||
4. Insert ksmbd.ko module
|
||||
|
||||
# insmod ksmbd.ko
|
||||
|
||||
5. Start ksmbd user space daemon
|
||||
# ksmbd.mountd
|
||||
|
||||
6. Access share from Windows or Linux using CIFS
|
||||
|
||||
Shutdown KSMBD
|
||||
==============
|
||||
|
||||
1. kill user and kernel space daemon
|
||||
# sudo ksmbd.control -s
|
||||
|
||||
How to turn debug print on
|
||||
==========================
|
||||
|
||||
Each layer
|
||||
/sys/class/ksmbd-control/debug
|
||||
|
||||
1. Enable all component prints
|
||||
# sudo ksmbd.control -d "all"
|
||||
|
||||
2. Enable one of components(smb, auth, vfs, oplock, ipc, conn, rdma)
|
||||
# sudo ksmbd.control -d "smb"
|
||||
|
||||
3. Show what prints are enable.
|
||||
# cat/sys/class/ksmbd-control/debug
|
||||
[smb] auth vfs oplock ipc conn [rdma]
|
||||
|
||||
4. Disable prints:
|
||||
If you try the selected component once more, It is disabled without brackets.
|
||||
@@ -72,7 +72,7 @@ Documentation for filesystem implementations.
|
||||
befs
|
||||
bfs
|
||||
btrfs
|
||||
cifs/cifsroot
|
||||
cifs/index
|
||||
ceph
|
||||
coda
|
||||
configfs
|
||||
|
||||
13
MAINTAINERS
13
MAINTAINERS
@@ -4620,7 +4620,7 @@ F: include/linux/clk/
|
||||
F: include/linux/of_clk.h
|
||||
X: drivers/clk/clkdev.c
|
||||
|
||||
COMMON INTERNET FILE SYSTEM (CIFS)
|
||||
COMMON INTERNET FILE SYSTEM CLIENT (CIFS)
|
||||
M: Steve French <sfrench@samba.org>
|
||||
L: linux-cifs@vger.kernel.org
|
||||
L: samba-technical@lists.samba.org (moderated for non-subscribers)
|
||||
@@ -10113,6 +10113,17 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest.git
|
||||
F: Documentation/dev-tools/kselftest*
|
||||
F: tools/testing/selftests/
|
||||
|
||||
KERNEL SMB3 SERVER (KSMBD)
|
||||
M: Namjae Jeon <linkinjeon@kernel.org>
|
||||
M: Sergey Senozhatsky <senozhatsky@chromium.org>
|
||||
M: Steve French <sfrench@samba.org>
|
||||
M: Hyunchul Lee <hyc.lee@gmail.com>
|
||||
L: linux-cifs@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://git.samba.org/ksmbd.git
|
||||
F: fs/cifs_common/
|
||||
F: fs/ksmbd/
|
||||
|
||||
KERNEL UNIT TESTING FRAMEWORK (KUnit)
|
||||
M: Brendan Higgins <brendanhiggins@google.com>
|
||||
L: linux-kselftest@vger.kernel.org
|
||||
|
||||
@@ -349,6 +349,7 @@ config NFS_V4_2_SSC_HELPER
|
||||
source "net/sunrpc/Kconfig"
|
||||
source "fs/ceph/Kconfig"
|
||||
source "fs/cifs/Kconfig"
|
||||
source "fs/ksmbd/Kconfig"
|
||||
source "fs/coda/Kconfig"
|
||||
source "fs/afs/Kconfig"
|
||||
source "fs/9p/Kconfig"
|
||||
|
||||
@@ -97,6 +97,7 @@ obj-$(CONFIG_NLS) += nls/
|
||||
obj-$(CONFIG_UNICODE) += unicode/
|
||||
obj-$(CONFIG_SYSV_FS) += sysv/
|
||||
obj-$(CONFIG_CIFS) += cifs/
|
||||
obj-$(CONFIG_SMB_SERVER) += ksmbd/
|
||||
obj-$(CONFIG_HPFS_FS) += hpfs/
|
||||
obj-$(CONFIG_NTFS_FS) += ntfs/
|
||||
obj-$(CONFIG_UFS_FS) += ufs/
|
||||
|
||||
68
fs/ksmbd/Kconfig
Normal file
68
fs/ksmbd/Kconfig
Normal file
@@ -0,0 +1,68 @@
|
||||
config SMB_SERVER
|
||||
tristate "SMB3 server support (EXPERIMENTAL)"
|
||||
depends on INET
|
||||
depends on MULTIUSER
|
||||
depends on FILE_LOCKING
|
||||
select NLS
|
||||
select NLS_UTF8
|
||||
select CRYPTO
|
||||
select CRYPTO_MD4
|
||||
select CRYPTO_MD5
|
||||
select CRYPTO_HMAC
|
||||
select CRYPTO_ECB
|
||||
select CRYPTO_LIB_DES
|
||||
select CRYPTO_SHA256
|
||||
select CRYPTO_CMAC
|
||||
select CRYPTO_SHA512
|
||||
select CRYPTO_AEAD2
|
||||
select CRYPTO_CCM
|
||||
select CRYPTO_GCM
|
||||
select ASN1
|
||||
select OID_REGISTRY
|
||||
default n
|
||||
help
|
||||
Choose Y here if you want to allow SMB3 compliant clients
|
||||
to access files residing on this system using SMB3 protocol.
|
||||
To compile the SMB3 server support as a module,
|
||||
choose M here: the module will be called ksmbd.
|
||||
|
||||
You may choose to use a samba server instead, in which
|
||||
case you can choose N here.
|
||||
|
||||
You also need to install user space programs which can be found
|
||||
in ksmbd-tools, available from
|
||||
https://github.com/cifsd-team/ksmbd-tools.
|
||||
More detail about how to run the ksmbd kernel server is
|
||||
available via README file
|
||||
(https://github.com/cifsd-team/ksmbd-tools/blob/master/README).
|
||||
|
||||
ksmbd kernel server includes support for auto-negotiation,
|
||||
Secure negotiate, Pre-authentication integrity, oplock/lease,
|
||||
compound requests, multi-credit, packet signing, RDMA(smbdirect),
|
||||
smb3 encryption, copy-offload, secure per-user session
|
||||
establishment via NTLM or NTLMv2.
|
||||
|
||||
config SMB_SERVER_SMBDIRECT
|
||||
bool "Support for SMB Direct protocol"
|
||||
depends on SMB_SERVER=m && INFINIBAND && INFINIBAND_ADDR_TRANS || SMB_SERVER=y && INFINIBAND=y && INFINIBAND_ADDR_TRANS=y
|
||||
select SG_POOL
|
||||
default n
|
||||
|
||||
help
|
||||
Enables SMB Direct support for SMB 3.0, 3.02 and 3.1.1.
|
||||
|
||||
SMB Direct allows transferring SMB packets over RDMA. If unsure,
|
||||
say N.
|
||||
|
||||
config SMB_SERVER_CHECK_CAP_NET_ADMIN
|
||||
bool "Enable check network administration capability"
|
||||
depends on SMB_SERVER
|
||||
default y
|
||||
|
||||
help
|
||||
Prevent unprivileged processes to start the ksmbd kernel server.
|
||||
|
||||
config SMB_SERVER_KERBEROS5
|
||||
bool "Support for Kerberos 5"
|
||||
depends on SMB_SERVER
|
||||
default n
|
||||
20
fs/ksmbd/Makefile
Normal file
20
fs/ksmbd/Makefile
Normal file
@@ -0,0 +1,20 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#
|
||||
# Makefile for Linux SMB3 kernel server
|
||||
#
|
||||
obj-$(CONFIG_SMB_SERVER) += ksmbd.o
|
||||
|
||||
ksmbd-y := unicode.o auth.o vfs.o vfs_cache.o server.o ndr.o \
|
||||
misc.o oplock.o connection.o ksmbd_work.o crypto_ctx.o \
|
||||
mgmt/ksmbd_ida.o mgmt/user_config.o mgmt/share_config.o \
|
||||
mgmt/tree_connect.o mgmt/user_session.o smb_common.o \
|
||||
transport_tcp.o transport_ipc.o smbacl.o smb2pdu.o \
|
||||
smb2ops.o smb2misc.o ksmbd_spnego_negtokeninit.asn1.o \
|
||||
ksmbd_spnego_negtokentarg.asn1.o asn1.o
|
||||
|
||||
$(obj)/asn1.o: $(obj)/ksmbd_spnego_negtokeninit.asn1.h $(obj)/ksmbd_spnego_negtokentarg.asn1.h
|
||||
|
||||
$(obj)/ksmbd_spnego_negtokeninit.asn1.o: $(obj)/ksmbd_spnego_negtokeninit.asn1.c $(obj)/ksmbd_spnego_negtokeninit.asn1.h
|
||||
$(obj)/ksmbd_spnego_negtokentarg.asn1.o: $(obj)/ksmbd_spnego_negtokentarg.asn1.c $(obj)/ksmbd_spnego_negtokentarg.asn1.h
|
||||
|
||||
ksmbd-$(CONFIG_SMB_SERVER_SMBDIRECT) += transport_rdma.o
|
||||
343
fs/ksmbd/asn1.c
Normal file
343
fs/ksmbd/asn1.c
Normal file
@@ -0,0 +1,343 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* The ASB.1/BER parsing code is derived from ip_nat_snmp_basic.c which was in
|
||||
* turn derived from the gxsnmp package by Gregory McLean & Jochen Friedrich
|
||||
*
|
||||
* Copyright (c) 2000 RP Internet (www.rpi.net.au).
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/oid_registry.h>
|
||||
|
||||
#include "glob.h"
|
||||
|
||||
#include "asn1.h"
|
||||
#include "connection.h"
|
||||
#include "auth.h"
|
||||
#include "ksmbd_spnego_negtokeninit.asn1.h"
|
||||
#include "ksmbd_spnego_negtokentarg.asn1.h"
|
||||
|
||||
#define SPNEGO_OID_LEN 7
|
||||
#define NTLMSSP_OID_LEN 10
|
||||
#define KRB5_OID_LEN 7
|
||||
#define KRB5U2U_OID_LEN 8
|
||||
#define MSKRB5_OID_LEN 7
|
||||
static unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 };
|
||||
static unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 };
|
||||
static unsigned long KRB5_OID[7] = { 1, 2, 840, 113554, 1, 2, 2 };
|
||||
static unsigned long KRB5U2U_OID[8] = { 1, 2, 840, 113554, 1, 2, 2, 3 };
|
||||
static unsigned long MSKRB5_OID[7] = { 1, 2, 840, 48018, 1, 2, 2 };
|
||||
|
||||
static char NTLMSSP_OID_STR[NTLMSSP_OID_LEN] = { 0x2b, 0x06, 0x01, 0x04, 0x01,
|
||||
0x82, 0x37, 0x02, 0x02, 0x0a };
|
||||
|
||||
static bool
|
||||
asn1_subid_decode(const unsigned char **begin, const unsigned char *end,
|
||||
unsigned long *subid)
|
||||
{
|
||||
const unsigned char *ptr = *begin;
|
||||
unsigned char ch;
|
||||
|
||||
*subid = 0;
|
||||
|
||||
do {
|
||||
if (ptr >= end)
|
||||
return false;
|
||||
|
||||
ch = *ptr++;
|
||||
*subid <<= 7;
|
||||
*subid |= ch & 0x7F;
|
||||
} while ((ch & 0x80) == 0x80);
|
||||
|
||||
*begin = ptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool asn1_oid_decode(const unsigned char *value, size_t vlen,
|
||||
unsigned long **oid, size_t *oidlen)
|
||||
{
|
||||
const unsigned char *iptr = value, *end = value + vlen;
|
||||
unsigned long *optr;
|
||||
unsigned long subid;
|
||||
|
||||
vlen += 1;
|
||||
if (vlen < 2 || vlen > UINT_MAX / sizeof(unsigned long))
|
||||
goto fail_nullify;
|
||||
|
||||
*oid = kmalloc(vlen * sizeof(unsigned long), GFP_KERNEL);
|
||||
if (!*oid)
|
||||
return false;
|
||||
|
||||
optr = *oid;
|
||||
|
||||
if (!asn1_subid_decode(&iptr, end, &subid))
|
||||
goto fail;
|
||||
|
||||
if (subid < 40) {
|
||||
optr[0] = 0;
|
||||
optr[1] = subid;
|
||||
} else if (subid < 80) {
|
||||
optr[0] = 1;
|
||||
optr[1] = subid - 40;
|
||||
} else {
|
||||
optr[0] = 2;
|
||||
optr[1] = subid - 80;
|
||||
}
|
||||
|
||||
*oidlen = 2;
|
||||
optr += 2;
|
||||
|
||||
while (iptr < end) {
|
||||
if (++(*oidlen) > vlen)
|
||||
goto fail;
|
||||
|
||||
if (!asn1_subid_decode(&iptr, end, optr++))
|
||||
goto fail;
|
||||
}
|
||||
return true;
|
||||
|
||||
fail:
|
||||
kfree(*oid);
|
||||
fail_nullify:
|
||||
*oid = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool oid_eq(unsigned long *oid1, unsigned int oid1len,
|
||||
unsigned long *oid2, unsigned int oid2len)
|
||||
{
|
||||
if (oid1len != oid2len)
|
||||
return false;
|
||||
|
||||
return memcmp(oid1, oid2, oid1len) == 0;
|
||||
}
|
||||
|
||||
int
|
||||
ksmbd_decode_negTokenInit(unsigned char *security_blob, int length,
|
||||
struct ksmbd_conn *conn)
|
||||
{
|
||||
return asn1_ber_decoder(&ksmbd_spnego_negtokeninit_decoder, conn,
|
||||
security_blob, length);
|
||||
}
|
||||
|
||||
int
|
||||
ksmbd_decode_negTokenTarg(unsigned char *security_blob, int length,
|
||||
struct ksmbd_conn *conn)
|
||||
{
|
||||
return asn1_ber_decoder(&ksmbd_spnego_negtokentarg_decoder, conn,
|
||||
security_blob, length);
|
||||
}
|
||||
|
||||
static int compute_asn_hdr_len_bytes(int len)
|
||||
{
|
||||
if (len > 0xFFFFFF)
|
||||
return 4;
|
||||
else if (len > 0xFFFF)
|
||||
return 3;
|
||||
else if (len > 0xFF)
|
||||
return 2;
|
||||
else if (len > 0x7F)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void encode_asn_tag(char *buf, unsigned int *ofs, char tag, char seq,
|
||||
int length)
|
||||
{
|
||||
int i;
|
||||
int index = *ofs;
|
||||
char hdr_len = compute_asn_hdr_len_bytes(length);
|
||||
int len = length + 2 + hdr_len;
|
||||
|
||||
/* insert tag */
|
||||
buf[index++] = tag;
|
||||
|
||||
if (!hdr_len) {
|
||||
buf[index++] = len;
|
||||
} else {
|
||||
buf[index++] = 0x80 | hdr_len;
|
||||
for (i = hdr_len - 1; i >= 0; i--)
|
||||
buf[index++] = (len >> (i * 8)) & 0xFF;
|
||||
}
|
||||
|
||||
/* insert seq */
|
||||
len = len - (index - *ofs);
|
||||
buf[index++] = seq;
|
||||
|
||||
if (!hdr_len) {
|
||||
buf[index++] = len;
|
||||
} else {
|
||||
buf[index++] = 0x80 | hdr_len;
|
||||
for (i = hdr_len - 1; i >= 0; i--)
|
||||
buf[index++] = (len >> (i * 8)) & 0xFF;
|
||||
}
|
||||
|
||||
*ofs += (index - *ofs);
|
||||
}
|
||||
|
||||
int build_spnego_ntlmssp_neg_blob(unsigned char **pbuffer, u16 *buflen,
|
||||
char *ntlm_blob, int ntlm_blob_len)
|
||||
{
|
||||
char *buf;
|
||||
unsigned int ofs = 0;
|
||||
int neg_result_len = 4 + compute_asn_hdr_len_bytes(1) * 2 + 1;
|
||||
int oid_len = 4 + compute_asn_hdr_len_bytes(NTLMSSP_OID_LEN) * 2 +
|
||||
NTLMSSP_OID_LEN;
|
||||
int ntlmssp_len = 4 + compute_asn_hdr_len_bytes(ntlm_blob_len) * 2 +
|
||||
ntlm_blob_len;
|
||||
int total_len = 4 + compute_asn_hdr_len_bytes(neg_result_len +
|
||||
oid_len + ntlmssp_len) * 2 +
|
||||
neg_result_len + oid_len + ntlmssp_len;
|
||||
|
||||
buf = kmalloc(total_len, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
/* insert main gss header */
|
||||
encode_asn_tag(buf, &ofs, 0xa1, 0x30, neg_result_len + oid_len +
|
||||
ntlmssp_len);
|
||||
|
||||
/* insert neg result */
|
||||
encode_asn_tag(buf, &ofs, 0xa0, 0x0a, 1);
|
||||
buf[ofs++] = 1;
|
||||
|
||||
/* insert oid */
|
||||
encode_asn_tag(buf, &ofs, 0xa1, 0x06, NTLMSSP_OID_LEN);
|
||||
memcpy(buf + ofs, NTLMSSP_OID_STR, NTLMSSP_OID_LEN);
|
||||
ofs += NTLMSSP_OID_LEN;
|
||||
|
||||
/* insert response token - ntlmssp blob */
|
||||
encode_asn_tag(buf, &ofs, 0xa2, 0x04, ntlm_blob_len);
|
||||
memcpy(buf + ofs, ntlm_blob, ntlm_blob_len);
|
||||
ofs += ntlm_blob_len;
|
||||
|
||||
*pbuffer = buf;
|
||||
*buflen = total_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int build_spnego_ntlmssp_auth_blob(unsigned char **pbuffer, u16 *buflen,
|
||||
int neg_result)
|
||||
{
|
||||
char *buf;
|
||||
unsigned int ofs = 0;
|
||||
int neg_result_len = 4 + compute_asn_hdr_len_bytes(1) * 2 + 1;
|
||||
int total_len = 4 + compute_asn_hdr_len_bytes(neg_result_len) * 2 +
|
||||
neg_result_len;
|
||||
|
||||
buf = kmalloc(total_len, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
/* insert main gss header */
|
||||
encode_asn_tag(buf, &ofs, 0xa1, 0x30, neg_result_len);
|
||||
|
||||
/* insert neg result */
|
||||
encode_asn_tag(buf, &ofs, 0xa0, 0x0a, 1);
|
||||
if (neg_result)
|
||||
buf[ofs++] = 2;
|
||||
else
|
||||
buf[ofs++] = 0;
|
||||
|
||||
*pbuffer = buf;
|
||||
*buflen = total_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ksmbd_gssapi_this_mech(void *context, size_t hdrlen, unsigned char tag,
|
||||
const void *value, size_t vlen)
|
||||
{
|
||||
unsigned long *oid;
|
||||
size_t oidlen;
|
||||
int err = 0;
|
||||
|
||||
if (!asn1_oid_decode(value, vlen, &oid, &oidlen)) {
|
||||
err = -EBADMSG;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!oid_eq(oid, oidlen, SPNEGO_OID, SPNEGO_OID_LEN))
|
||||
err = -EBADMSG;
|
||||
kfree(oid);
|
||||
out:
|
||||
if (err) {
|
||||
char buf[50];
|
||||
|
||||
sprint_oid(value, vlen, buf, sizeof(buf));
|
||||
ksmbd_debug(AUTH, "Unexpected OID: %s\n", buf);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int ksmbd_neg_token_init_mech_type(void *context, size_t hdrlen,
|
||||
unsigned char tag, const void *value,
|
||||
size_t vlen)
|
||||
{
|
||||
struct ksmbd_conn *conn = context;
|
||||
unsigned long *oid;
|
||||
size_t oidlen;
|
||||
int mech_type;
|
||||
char buf[50];
|
||||
|
||||
if (!asn1_oid_decode(value, vlen, &oid, &oidlen))
|
||||
goto fail;
|
||||
|
||||
if (oid_eq(oid, oidlen, NTLMSSP_OID, NTLMSSP_OID_LEN))
|
||||
mech_type = KSMBD_AUTH_NTLMSSP;
|
||||
else if (oid_eq(oid, oidlen, MSKRB5_OID, MSKRB5_OID_LEN))
|
||||
mech_type = KSMBD_AUTH_MSKRB5;
|
||||
else if (oid_eq(oid, oidlen, KRB5_OID, KRB5_OID_LEN))
|
||||
mech_type = KSMBD_AUTH_KRB5;
|
||||
else if (oid_eq(oid, oidlen, KRB5U2U_OID, KRB5U2U_OID_LEN))
|
||||
mech_type = KSMBD_AUTH_KRB5U2U;
|
||||
else
|
||||
goto fail;
|
||||
|
||||
conn->auth_mechs |= mech_type;
|
||||
if (conn->preferred_auth_mech == 0)
|
||||
conn->preferred_auth_mech = mech_type;
|
||||
|
||||
kfree(oid);
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
kfree(oid);
|
||||
sprint_oid(value, vlen, buf, sizeof(buf));
|
||||
ksmbd_debug(AUTH, "Unexpected OID: %s\n", buf);
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
int ksmbd_neg_token_init_mech_token(void *context, size_t hdrlen,
|
||||
unsigned char tag, const void *value,
|
||||
size_t vlen)
|
||||
{
|
||||
struct ksmbd_conn *conn = context;
|
||||
|
||||
conn->mechToken = kmalloc(vlen + 1, GFP_KERNEL);
|
||||
if (!conn->mechToken)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(conn->mechToken, value, vlen);
|
||||
conn->mechToken[vlen] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ksmbd_neg_token_targ_resp_token(void *context, size_t hdrlen,
|
||||
unsigned char tag, const void *value,
|
||||
size_t vlen)
|
||||
{
|
||||
struct ksmbd_conn *conn = context;
|
||||
|
||||
conn->mechToken = kmalloc(vlen + 1, GFP_KERNEL);
|
||||
if (!conn->mechToken)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(conn->mechToken, value, vlen);
|
||||
conn->mechToken[vlen] = '\0';
|
||||
return 0;
|
||||
}
|
||||
21
fs/ksmbd/asn1.h
Normal file
21
fs/ksmbd/asn1.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* The ASB.1/BER parsing code is derived from ip_nat_snmp_basic.c which was in
|
||||
* turn derived from the gxsnmp package by Gregory McLean & Jochen Friedrich
|
||||
*
|
||||
* Copyright (c) 2000 RP Internet (www.rpi.net.au).
|
||||
* Copyright (C) 2018 Samsung Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#ifndef __ASN1_H__
|
||||
#define __ASN1_H__
|
||||
|
||||
int ksmbd_decode_negTokenInit(unsigned char *security_blob, int length,
|
||||
struct ksmbd_conn *conn);
|
||||
int ksmbd_decode_negTokenTarg(unsigned char *security_blob, int length,
|
||||
struct ksmbd_conn *conn);
|
||||
int build_spnego_ntlmssp_neg_blob(unsigned char **pbuffer, u16 *buflen,
|
||||
char *ntlm_blob, int ntlm_blob_len);
|
||||
int build_spnego_ntlmssp_auth_blob(unsigned char **pbuffer, u16 *buflen,
|
||||
int neg_result);
|
||||
#endif /* __ASN1_H__ */
|
||||
1364
fs/ksmbd/auth.c
Normal file
1364
fs/ksmbd/auth.c
Normal file
File diff suppressed because it is too large
Load Diff
67
fs/ksmbd/auth.h
Normal file
67
fs/ksmbd/auth.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2018 Samsung Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#ifndef __AUTH_H__
|
||||
#define __AUTH_H__
|
||||
|
||||
#include "ntlmssp.h"
|
||||
|
||||
#ifdef CONFIG_SMB_SERVER_KERBEROS5
|
||||
#define AUTH_GSS_LENGTH 96
|
||||
#define AUTH_GSS_PADDING 0
|
||||
#else
|
||||
#define AUTH_GSS_LENGTH 74
|
||||
#define AUTH_GSS_PADDING 6
|
||||
#endif
|
||||
|
||||
#define CIFS_HMAC_MD5_HASH_SIZE (16)
|
||||
#define CIFS_NTHASH_SIZE (16)
|
||||
|
||||
/*
|
||||
* Size of the ntlm client response
|
||||
*/
|
||||
#define CIFS_AUTH_RESP_SIZE 24
|
||||
#define CIFS_SMB1_SIGNATURE_SIZE 8
|
||||
#define CIFS_SMB1_SESSKEY_SIZE 16
|
||||
|
||||
#define KSMBD_AUTH_NTLMSSP 0x0001
|
||||
#define KSMBD_AUTH_KRB5 0x0002
|
||||
#define KSMBD_AUTH_MSKRB5 0x0004
|
||||
#define KSMBD_AUTH_KRB5U2U 0x0008
|
||||
|
||||
struct ksmbd_session;
|
||||
struct ksmbd_conn;
|
||||
struct kvec;
|
||||
|
||||
int ksmbd_crypt_message(struct ksmbd_conn *conn, struct kvec *iov,
|
||||
unsigned int nvec, int enc);
|
||||
void ksmbd_copy_gss_neg_header(void *buf);
|
||||
int ksmbd_auth_ntlm(struct ksmbd_session *sess, char *pw_buf);
|
||||
int ksmbd_auth_ntlmv2(struct ksmbd_session *sess, struct ntlmv2_resp *ntlmv2,
|
||||
int blen, char *domain_name);
|
||||
int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob,
|
||||
int blob_len, struct ksmbd_session *sess);
|
||||
int ksmbd_decode_ntlmssp_neg_blob(struct negotiate_message *negblob,
|
||||
int blob_len, struct ksmbd_session *sess);
|
||||
unsigned int
|
||||
ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob,
|
||||
struct ksmbd_session *sess);
|
||||
int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
|
||||
int in_len, char *out_blob, int *out_len);
|
||||
int ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
|
||||
int n_vec, char *sig);
|
||||
int ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
|
||||
int n_vec, char *sig);
|
||||
int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess,
|
||||
struct ksmbd_conn *conn);
|
||||
int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess,
|
||||
struct ksmbd_conn *conn);
|
||||
int ksmbd_gen_smb30_encryptionkey(struct ksmbd_session *sess);
|
||||
int ksmbd_gen_smb311_encryptionkey(struct ksmbd_session *sess);
|
||||
int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf,
|
||||
__u8 *pi_hash);
|
||||
int ksmbd_gen_sd_hash(struct ksmbd_conn *conn, char *sd_buf, int len,
|
||||
__u8 *pi_hash);
|
||||
#endif
|
||||
413
fs/ksmbd/connection.c
Normal file
413
fs/ksmbd/connection.c
Normal file
@@ -0,0 +1,413 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2016 Namjae Jeon <namjae.jeon@protocolfreedom.org>
|
||||
* Copyright (C) 2018 Samsung Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "server.h"
|
||||
#include "smb_common.h"
|
||||
#include "mgmt/ksmbd_ida.h"
|
||||
#include "connection.h"
|
||||
#include "transport_tcp.h"
|
||||
#include "transport_rdma.h"
|
||||
|
||||
static DEFINE_MUTEX(init_lock);
|
||||
|
||||
static struct ksmbd_conn_ops default_conn_ops;
|
||||
|
||||
LIST_HEAD(conn_list);
|
||||
DEFINE_RWLOCK(conn_list_lock);
|
||||
|
||||
/**
|
||||
* ksmbd_conn_free() - free resources of the connection instance
|
||||
*
|
||||
* @conn: connection instance to be cleand up
|
||||
*
|
||||
* During the thread termination, the corresponding conn instance
|
||||
* resources(sock/memory) are released and finally the conn object is freed.
|
||||
*/
|
||||
void ksmbd_conn_free(struct ksmbd_conn *conn)
|
||||
{
|
||||
write_lock(&conn_list_lock);
|
||||
list_del(&conn->conns_list);
|
||||
write_unlock(&conn_list_lock);
|
||||
|
||||
kvfree(conn->request_buf);
|
||||
kfree(conn->preauth_info);
|
||||
kfree(conn);
|
||||
}
|
||||
|
||||
/**
|
||||
* ksmbd_conn_alloc() - initialize a new connection instance
|
||||
*
|
||||
* Return: ksmbd_conn struct on success, otherwise NULL
|
||||
*/
|
||||
struct ksmbd_conn *ksmbd_conn_alloc(void)
|
||||
{
|
||||
struct ksmbd_conn *conn;
|
||||
|
||||
conn = kzalloc(sizeof(struct ksmbd_conn), GFP_KERNEL);
|
||||
if (!conn)
|
||||
return NULL;
|
||||
|
||||
conn->need_neg = true;
|
||||
conn->status = KSMBD_SESS_NEW;
|
||||
conn->local_nls = load_nls("utf8");
|
||||
if (!conn->local_nls)
|
||||
conn->local_nls = load_nls_default();
|
||||
atomic_set(&conn->req_running, 0);
|
||||
atomic_set(&conn->r_count, 0);
|
||||
init_waitqueue_head(&conn->req_running_q);
|
||||
INIT_LIST_HEAD(&conn->conns_list);
|
||||
INIT_LIST_HEAD(&conn->sessions);
|
||||
INIT_LIST_HEAD(&conn->requests);
|
||||
INIT_LIST_HEAD(&conn->async_requests);
|
||||
spin_lock_init(&conn->request_lock);
|
||||
spin_lock_init(&conn->credits_lock);
|
||||
ida_init(&conn->async_ida);
|
||||
|
||||
spin_lock_init(&conn->llist_lock);
|
||||
INIT_LIST_HEAD(&conn->lock_list);
|
||||
|
||||
write_lock(&conn_list_lock);
|
||||
list_add(&conn->conns_list, &conn_list);
|
||||
write_unlock(&conn_list_lock);
|
||||
return conn;
|
||||
}
|
||||
|
||||
bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c)
|
||||
{
|
||||
struct ksmbd_conn *t;
|
||||
bool ret = false;
|
||||
|
||||
read_lock(&conn_list_lock);
|
||||
list_for_each_entry(t, &conn_list, conns_list) {
|
||||
if (memcmp(t->ClientGUID, c->ClientGUID, SMB2_CLIENT_GUID_SIZE))
|
||||
continue;
|
||||
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
read_unlock(&conn_list_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ksmbd_conn_enqueue_request(struct ksmbd_work *work)
|
||||
{
|
||||
struct ksmbd_conn *conn = work->conn;
|
||||
struct list_head *requests_queue = NULL;
|
||||
|
||||
if (conn->ops->get_cmd_val(work) != SMB2_CANCEL_HE) {
|
||||
requests_queue = &conn->requests;
|
||||
work->syncronous = true;
|
||||
}
|
||||
|
||||
if (requests_queue) {
|
||||
atomic_inc(&conn->req_running);
|
||||
spin_lock(&conn->request_lock);
|
||||
list_add_tail(&work->request_entry, requests_queue);
|
||||
spin_unlock(&conn->request_lock);
|
||||
}
|
||||
}
|
||||
|
||||
int ksmbd_conn_try_dequeue_request(struct ksmbd_work *work)
|
||||
{
|
||||
struct ksmbd_conn *conn = work->conn;
|
||||
int ret = 1;
|
||||
|
||||
if (list_empty(&work->request_entry) &&
|
||||
list_empty(&work->async_request_entry))
|
||||
return 0;
|
||||
|
||||
if (!work->multiRsp)
|
||||
atomic_dec(&conn->req_running);
|
||||
spin_lock(&conn->request_lock);
|
||||
if (!work->multiRsp) {
|
||||
list_del_init(&work->request_entry);
|
||||
if (work->syncronous == false)
|
||||
list_del_init(&work->async_request_entry);
|
||||
ret = 0;
|
||||
}
|
||||
spin_unlock(&conn->request_lock);
|
||||
|
||||
wake_up_all(&conn->req_running_q);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ksmbd_conn_lock(struct ksmbd_conn *conn)
|
||||
{
|
||||
mutex_lock(&conn->srv_mutex);
|
||||
}
|
||||
|
||||
static void ksmbd_conn_unlock(struct ksmbd_conn *conn)
|
||||
{
|
||||
mutex_unlock(&conn->srv_mutex);
|
||||
}
|
||||
|
||||
void ksmbd_conn_wait_idle(struct ksmbd_conn *conn)
|
||||
{
|
||||
wait_event(conn->req_running_q, atomic_read(&conn->req_running) < 2);
|
||||
}
|
||||
|
||||
int ksmbd_conn_write(struct ksmbd_work *work)
|
||||
{
|
||||
struct ksmbd_conn *conn = work->conn;
|
||||
struct smb_hdr *rsp_hdr = work->response_buf;
|
||||
size_t len = 0;
|
||||
int sent;
|
||||
struct kvec iov[3];
|
||||
int iov_idx = 0;
|
||||
|
||||
ksmbd_conn_try_dequeue_request(work);
|
||||
if (!rsp_hdr) {
|
||||
pr_err("NULL response header\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (work->tr_buf) {
|
||||
iov[iov_idx] = (struct kvec) { work->tr_buf,
|
||||
sizeof(struct smb2_transform_hdr) };
|
||||
len += iov[iov_idx++].iov_len;
|
||||
}
|
||||
|
||||
if (work->aux_payload_sz) {
|
||||
iov[iov_idx] = (struct kvec) { rsp_hdr, work->resp_hdr_sz };
|
||||
len += iov[iov_idx++].iov_len;
|
||||
iov[iov_idx] = (struct kvec) { work->aux_payload_buf, work->aux_payload_sz };
|
||||
len += iov[iov_idx++].iov_len;
|
||||
} else {
|
||||
if (work->tr_buf)
|
||||
iov[iov_idx].iov_len = work->resp_hdr_sz;
|
||||
else
|
||||
iov[iov_idx].iov_len = get_rfc1002_len(rsp_hdr) + 4;
|
||||
iov[iov_idx].iov_base = rsp_hdr;
|
||||
len += iov[iov_idx++].iov_len;
|
||||
}
|
||||
|
||||
ksmbd_conn_lock(conn);
|
||||
sent = conn->transport->ops->writev(conn->transport, &iov[0],
|
||||
iov_idx, len,
|
||||
work->need_invalidate_rkey,
|
||||
work->remote_key);
|
||||
ksmbd_conn_unlock(conn);
|
||||
|
||||
if (sent < 0) {
|
||||
pr_err("Failed to send message: %d\n", sent);
|
||||
return sent;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ksmbd_conn_rdma_read(struct ksmbd_conn *conn, void *buf,
|
||||
unsigned int buflen, u32 remote_key, u64 remote_offset,
|
||||
u32 remote_len)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (conn->transport->ops->rdma_read)
|
||||
ret = conn->transport->ops->rdma_read(conn->transport,
|
||||
buf, buflen,
|
||||
remote_key, remote_offset,
|
||||
remote_len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ksmbd_conn_rdma_write(struct ksmbd_conn *conn, void *buf,
|
||||
unsigned int buflen, u32 remote_key,
|
||||
u64 remote_offset, u32 remote_len)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (conn->transport->ops->rdma_write)
|
||||
ret = conn->transport->ops->rdma_write(conn->transport,
|
||||
buf, buflen,
|
||||
remote_key, remote_offset,
|
||||
remote_len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ksmbd_conn_alive(struct ksmbd_conn *conn)
|
||||
{
|
||||
if (!ksmbd_server_running())
|
||||
return false;
|
||||
|
||||
if (conn->status == KSMBD_SESS_EXITING)
|
||||
return false;
|
||||
|
||||
if (kthread_should_stop())
|
||||
return false;
|
||||
|
||||
if (atomic_read(&conn->stats.open_files_count) > 0)
|
||||
return true;
|
||||
|
||||
/*
|
||||
* Stop current session if the time that get last request from client
|
||||
* is bigger than deadtime user configured and opening file count is
|
||||
* zero.
|
||||
*/
|
||||
if (server_conf.deadtime > 0 &&
|
||||
time_after(jiffies, conn->last_active + server_conf.deadtime)) {
|
||||
ksmbd_debug(CONN, "No response from client in %lu minutes\n",
|
||||
server_conf.deadtime / SMB_ECHO_INTERVAL);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* ksmbd_conn_handler_loop() - session thread to listen on new smb requests
|
||||
* @p: connection instance
|
||||
*
|
||||
* One thread each per connection
|
||||
*
|
||||
* Return: 0 on success
|
||||
*/
|
||||
int ksmbd_conn_handler_loop(void *p)
|
||||
{
|
||||
struct ksmbd_conn *conn = (struct ksmbd_conn *)p;
|
||||
struct ksmbd_transport *t = conn->transport;
|
||||
unsigned int pdu_size;
|
||||
char hdr_buf[4] = {0,};
|
||||
int size;
|
||||
|
||||
mutex_init(&conn->srv_mutex);
|
||||
__module_get(THIS_MODULE);
|
||||
|
||||
if (t->ops->prepare && t->ops->prepare(t))
|
||||
goto out;
|
||||
|
||||
conn->last_active = jiffies;
|
||||
while (ksmbd_conn_alive(conn)) {
|
||||
if (try_to_freeze())
|
||||
continue;
|
||||
|
||||
kvfree(conn->request_buf);
|
||||
conn->request_buf = NULL;
|
||||
|
||||
size = t->ops->read(t, hdr_buf, sizeof(hdr_buf));
|
||||
if (size != sizeof(hdr_buf))
|
||||
break;
|
||||
|
||||
pdu_size = get_rfc1002_len(hdr_buf);
|
||||
ksmbd_debug(CONN, "RFC1002 header %u bytes\n", pdu_size);
|
||||
|
||||
/* make sure we have enough to get to SMB header end */
|
||||
if (!ksmbd_pdu_size_has_room(pdu_size)) {
|
||||
ksmbd_debug(CONN, "SMB request too short (%u bytes)\n",
|
||||
pdu_size);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* 4 for rfc1002 length field */
|
||||
size = pdu_size + 4;
|
||||
conn->request_buf = kvmalloc(size, GFP_KERNEL);
|
||||
if (!conn->request_buf)
|
||||
continue;
|
||||
|
||||
memcpy(conn->request_buf, hdr_buf, sizeof(hdr_buf));
|
||||
if (!ksmbd_smb_request(conn))
|
||||
break;
|
||||
|
||||
/*
|
||||
* We already read 4 bytes to find out PDU size, now
|
||||
* read in PDU
|
||||
*/
|
||||
size = t->ops->read(t, conn->request_buf + 4, pdu_size);
|
||||
if (size < 0) {
|
||||
pr_err("sock_read failed: %d\n", size);
|
||||
break;
|
||||
}
|
||||
|
||||
if (size != pdu_size) {
|
||||
pr_err("PDU error. Read: %d, Expected: %d\n",
|
||||
size, pdu_size);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!default_conn_ops.process_fn) {
|
||||
pr_err("No connection request callback\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (default_conn_ops.process_fn(conn)) {
|
||||
pr_err("Cannot handle request\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
/* Wait till all reference dropped to the Server object*/
|
||||
while (atomic_read(&conn->r_count) > 0)
|
||||
schedule_timeout(HZ);
|
||||
|
||||
unload_nls(conn->local_nls);
|
||||
if (default_conn_ops.terminate_fn)
|
||||
default_conn_ops.terminate_fn(conn);
|
||||
t->ops->disconnect(t);
|
||||
module_put(THIS_MODULE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ksmbd_conn_init_server_callbacks(struct ksmbd_conn_ops *ops)
|
||||
{
|
||||
default_conn_ops.process_fn = ops->process_fn;
|
||||
default_conn_ops.terminate_fn = ops->terminate_fn;
|
||||
}
|
||||
|
||||
int ksmbd_conn_transport_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&init_lock);
|
||||
ret = ksmbd_tcp_init();
|
||||
if (ret) {
|
||||
pr_err("Failed to init TCP subsystem: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = ksmbd_rdma_init();
|
||||
if (ret) {
|
||||
pr_err("Failed to init RDMA subsystem: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&init_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void stop_sessions(void)
|
||||
{
|
||||
struct ksmbd_conn *conn;
|
||||
|
||||
again:
|
||||
read_lock(&conn_list_lock);
|
||||
list_for_each_entry(conn, &conn_list, conns_list) {
|
||||
struct task_struct *task;
|
||||
|
||||
task = conn->transport->handler;
|
||||
if (task)
|
||||
ksmbd_debug(CONN, "Stop session handler %s/%d\n",
|
||||
task->comm, task_pid_nr(task));
|
||||
conn->status = KSMBD_SESS_EXITING;
|
||||
}
|
||||
read_unlock(&conn_list_lock);
|
||||
|
||||
if (!list_empty(&conn_list)) {
|
||||
schedule_timeout_interruptible(HZ / 10); /* 100ms */
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
|
||||
void ksmbd_conn_transport_destroy(void)
|
||||
{
|
||||
mutex_lock(&init_lock);
|
||||
ksmbd_tcp_destroy();
|
||||
ksmbd_rdma_destroy();
|
||||
stop_sessions();
|
||||
mutex_unlock(&init_lock);
|
||||
}
|
||||
213
fs/ksmbd/connection.h
Normal file
213
fs/ksmbd/connection.h
Normal file
@@ -0,0 +1,213 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2018 Samsung Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#ifndef __KSMBD_CONNECTION_H__
|
||||
#define __KSMBD_CONNECTION_H__
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/ip.h>
|
||||
#include <net/sock.h>
|
||||
#include <net/tcp.h>
|
||||
#include <net/inet_connection_sock.h>
|
||||
#include <net/request_sock.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/nls.h>
|
||||
|
||||
#include "smb_common.h"
|
||||
#include "ksmbd_work.h"
|
||||
|
||||
#define KSMBD_SOCKET_BACKLOG 16
|
||||
|
||||
/*
|
||||
* WARNING
|
||||
*
|
||||
* This is nothing but a HACK. Session status should move to channel
|
||||
* or to session. As of now we have 1 tcp_conn : 1 ksmbd_session, but
|
||||
* we need to change it to 1 tcp_conn : N ksmbd_sessions.
|
||||
*/
|
||||
enum {
|
||||
KSMBD_SESS_NEW = 0,
|
||||
KSMBD_SESS_GOOD,
|
||||
KSMBD_SESS_EXITING,
|
||||
KSMBD_SESS_NEED_RECONNECT,
|
||||
KSMBD_SESS_NEED_NEGOTIATE
|
||||
};
|
||||
|
||||
struct ksmbd_stats {
|
||||
atomic_t open_files_count;
|
||||
atomic64_t request_served;
|
||||
};
|
||||
|
||||
struct ksmbd_transport;
|
||||
|
||||
struct ksmbd_conn {
|
||||
struct smb_version_values *vals;
|
||||
struct smb_version_ops *ops;
|
||||
struct smb_version_cmds *cmds;
|
||||
unsigned int max_cmds;
|
||||
struct mutex srv_mutex;
|
||||
int status;
|
||||
unsigned int cli_cap;
|
||||
char *request_buf;
|
||||
struct ksmbd_transport *transport;
|
||||
struct nls_table *local_nls;
|
||||
struct list_head conns_list;
|
||||
/* smb session 1 per user */
|
||||
struct list_head sessions;
|
||||
unsigned long last_active;
|
||||
/* How many request are running currently */
|
||||
atomic_t req_running;
|
||||
/* References which are made for this Server object*/
|
||||
atomic_t r_count;
|
||||
unsigned short total_credits;
|
||||
unsigned short max_credits;
|
||||
spinlock_t credits_lock;
|
||||
wait_queue_head_t req_running_q;
|
||||
/* Lock to protect requests list*/
|
||||
spinlock_t request_lock;
|
||||
struct list_head requests;
|
||||
struct list_head async_requests;
|
||||
int connection_type;
|
||||
struct ksmbd_stats stats;
|
||||
char ClientGUID[SMB2_CLIENT_GUID_SIZE];
|
||||
union {
|
||||
/* pending trans request table */
|
||||
struct trans_state *recent_trans;
|
||||
/* Used by ntlmssp */
|
||||
char *ntlmssp_cryptkey;
|
||||
};
|
||||
|
||||
spinlock_t llist_lock;
|
||||
struct list_head lock_list;
|
||||
|
||||
struct preauth_integrity_info *preauth_info;
|
||||
|
||||
bool need_neg;
|
||||
unsigned int auth_mechs;
|
||||
unsigned int preferred_auth_mech;
|
||||
bool sign;
|
||||
bool use_spnego:1;
|
||||
__u16 cli_sec_mode;
|
||||
__u16 srv_sec_mode;
|
||||
/* dialect index that server chose */
|
||||
__u16 dialect;
|
||||
|
||||
char *mechToken;
|
||||
|
||||
struct ksmbd_conn_ops *conn_ops;
|
||||
|
||||
/* Preauth Session Table */
|
||||
struct list_head preauth_sess_table;
|
||||
|
||||
struct sockaddr_storage peer_addr;
|
||||
|
||||
/* Identifier for async message */
|
||||
struct ida async_ida;
|
||||
|
||||
__le16 cipher_type;
|
||||
__le16 compress_algorithm;
|
||||
bool posix_ext_supported;
|
||||
bool signing_negotiated;
|
||||
__le16 signing_algorithm;
|
||||
bool binding;
|
||||
};
|
||||
|
||||
struct ksmbd_conn_ops {
|
||||
int (*process_fn)(struct ksmbd_conn *conn);
|
||||
int (*terminate_fn)(struct ksmbd_conn *conn);
|
||||
};
|
||||
|
||||
struct ksmbd_transport_ops {
|
||||
int (*prepare)(struct ksmbd_transport *t);
|
||||
void (*disconnect)(struct ksmbd_transport *t);
|
||||
int (*read)(struct ksmbd_transport *t, char *buf, unsigned int size);
|
||||
int (*writev)(struct ksmbd_transport *t, struct kvec *iovs, int niov,
|
||||
int size, bool need_invalidate_rkey,
|
||||
unsigned int remote_key);
|
||||
int (*rdma_read)(struct ksmbd_transport *t, void *buf, unsigned int len,
|
||||
u32 remote_key, u64 remote_offset, u32 remote_len);
|
||||
int (*rdma_write)(struct ksmbd_transport *t, void *buf,
|
||||
unsigned int len, u32 remote_key, u64 remote_offset,
|
||||
u32 remote_len);
|
||||
};
|
||||
|
||||
struct ksmbd_transport {
|
||||
struct ksmbd_conn *conn;
|
||||
struct ksmbd_transport_ops *ops;
|
||||
struct task_struct *handler;
|
||||
};
|
||||
|
||||
#define KSMBD_TCP_RECV_TIMEOUT (7 * HZ)
|
||||
#define KSMBD_TCP_SEND_TIMEOUT (5 * HZ)
|
||||
#define KSMBD_TCP_PEER_SOCKADDR(c) ((struct sockaddr *)&((c)->peer_addr))
|
||||
|
||||
extern struct list_head conn_list;
|
||||
extern rwlock_t conn_list_lock;
|
||||
|
||||
bool ksmbd_conn_alive(struct ksmbd_conn *conn);
|
||||
void ksmbd_conn_wait_idle(struct ksmbd_conn *conn);
|
||||
struct ksmbd_conn *ksmbd_conn_alloc(void);
|
||||
void ksmbd_conn_free(struct ksmbd_conn *conn);
|
||||
bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c);
|
||||
int ksmbd_conn_write(struct ksmbd_work *work);
|
||||
int ksmbd_conn_rdma_read(struct ksmbd_conn *conn, void *buf,
|
||||
unsigned int buflen, u32 remote_key, u64 remote_offset,
|
||||
u32 remote_len);
|
||||
int ksmbd_conn_rdma_write(struct ksmbd_conn *conn, void *buf,
|
||||
unsigned int buflen, u32 remote_key, u64 remote_offset,
|
||||
u32 remote_len);
|
||||
void ksmbd_conn_enqueue_request(struct ksmbd_work *work);
|
||||
int ksmbd_conn_try_dequeue_request(struct ksmbd_work *work);
|
||||
void ksmbd_conn_init_server_callbacks(struct ksmbd_conn_ops *ops);
|
||||
int ksmbd_conn_handler_loop(void *p);
|
||||
int ksmbd_conn_transport_init(void);
|
||||
void ksmbd_conn_transport_destroy(void);
|
||||
|
||||
/*
|
||||
* WARNING
|
||||
*
|
||||
* This is a hack. We will move status to a proper place once we land
|
||||
* a multi-sessions support.
|
||||
*/
|
||||
static inline bool ksmbd_conn_good(struct ksmbd_work *work)
|
||||
{
|
||||
return work->conn->status == KSMBD_SESS_GOOD;
|
||||
}
|
||||
|
||||
static inline bool ksmbd_conn_need_negotiate(struct ksmbd_work *work)
|
||||
{
|
||||
return work->conn->status == KSMBD_SESS_NEED_NEGOTIATE;
|
||||
}
|
||||
|
||||
static inline bool ksmbd_conn_need_reconnect(struct ksmbd_work *work)
|
||||
{
|
||||
return work->conn->status == KSMBD_SESS_NEED_RECONNECT;
|
||||
}
|
||||
|
||||
static inline bool ksmbd_conn_exiting(struct ksmbd_work *work)
|
||||
{
|
||||
return work->conn->status == KSMBD_SESS_EXITING;
|
||||
}
|
||||
|
||||
static inline void ksmbd_conn_set_good(struct ksmbd_work *work)
|
||||
{
|
||||
work->conn->status = KSMBD_SESS_GOOD;
|
||||
}
|
||||
|
||||
static inline void ksmbd_conn_set_need_negotiate(struct ksmbd_work *work)
|
||||
{
|
||||
work->conn->status = KSMBD_SESS_NEED_NEGOTIATE;
|
||||
}
|
||||
|
||||
static inline void ksmbd_conn_set_need_reconnect(struct ksmbd_work *work)
|
||||
{
|
||||
work->conn->status = KSMBD_SESS_NEED_RECONNECT;
|
||||
}
|
||||
|
||||
static inline void ksmbd_conn_set_exiting(struct ksmbd_work *work)
|
||||
{
|
||||
work->conn->status = KSMBD_SESS_EXITING;
|
||||
}
|
||||
#endif /* __CONNECTION_H__ */
|
||||
282
fs/ksmbd/crypto_ctx.c
Normal file
282
fs/ksmbd/crypto_ctx.c
Normal file
@@ -0,0 +1,282 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2019 Samsung Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include "glob.h"
|
||||
#include "crypto_ctx.h"
|
||||
|
||||
struct crypto_ctx_list {
|
||||
spinlock_t ctx_lock;
|
||||
int avail_ctx;
|
||||
struct list_head idle_ctx;
|
||||
wait_queue_head_t ctx_wait;
|
||||
};
|
||||
|
||||
static struct crypto_ctx_list ctx_list;
|
||||
|
||||
static inline void free_aead(struct crypto_aead *aead)
|
||||
{
|
||||
if (aead)
|
||||
crypto_free_aead(aead);
|
||||
}
|
||||
|
||||
static void free_shash(struct shash_desc *shash)
|
||||
{
|
||||
if (shash) {
|
||||
crypto_free_shash(shash->tfm);
|
||||
kfree(shash);
|
||||
}
|
||||
}
|
||||
|
||||
static struct crypto_aead *alloc_aead(int id)
|
||||
{
|
||||
struct crypto_aead *tfm = NULL;
|
||||
|
||||
switch (id) {
|
||||
case CRYPTO_AEAD_AES_GCM:
|
||||
tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
|
||||
break;
|
||||
case CRYPTO_AEAD_AES_CCM:
|
||||
tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
|
||||
break;
|
||||
default:
|
||||
pr_err("Does not support encrypt ahead(id : %d)\n", id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (IS_ERR(tfm)) {
|
||||
pr_err("Failed to alloc encrypt aead : %ld\n", PTR_ERR(tfm));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return tfm;
|
||||
}
|
||||
|
||||
static struct shash_desc *alloc_shash_desc(int id)
|
||||
{
|
||||
struct crypto_shash *tfm = NULL;
|
||||
struct shash_desc *shash;
|
||||
|
||||
switch (id) {
|
||||
case CRYPTO_SHASH_HMACMD5:
|
||||
tfm = crypto_alloc_shash("hmac(md5)", 0, 0);
|
||||
break;
|
||||
case CRYPTO_SHASH_HMACSHA256:
|
||||
tfm = crypto_alloc_shash("hmac(sha256)", 0, 0);
|
||||
break;
|
||||
case CRYPTO_SHASH_CMACAES:
|
||||
tfm = crypto_alloc_shash("cmac(aes)", 0, 0);
|
||||
break;
|
||||
case CRYPTO_SHASH_SHA256:
|
||||
tfm = crypto_alloc_shash("sha256", 0, 0);
|
||||
break;
|
||||
case CRYPTO_SHASH_SHA512:
|
||||
tfm = crypto_alloc_shash("sha512", 0, 0);
|
||||
break;
|
||||
case CRYPTO_SHASH_MD4:
|
||||
tfm = crypto_alloc_shash("md4", 0, 0);
|
||||
break;
|
||||
case CRYPTO_SHASH_MD5:
|
||||
tfm = crypto_alloc_shash("md5", 0, 0);
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (IS_ERR(tfm))
|
||||
return NULL;
|
||||
|
||||
shash = kzalloc(sizeof(*shash) + crypto_shash_descsize(tfm),
|
||||
GFP_KERNEL);
|
||||
if (!shash)
|
||||
crypto_free_shash(tfm);
|
||||
else
|
||||
shash->tfm = tfm;
|
||||
return shash;
|
||||
}
|
||||
|
||||
static void ctx_free(struct ksmbd_crypto_ctx *ctx)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CRYPTO_SHASH_MAX; i++)
|
||||
free_shash(ctx->desc[i]);
|
||||
for (i = 0; i < CRYPTO_AEAD_MAX; i++)
|
||||
free_aead(ctx->ccmaes[i]);
|
||||
kfree(ctx);
|
||||
}
|
||||
|
||||
static struct ksmbd_crypto_ctx *ksmbd_find_crypto_ctx(void)
|
||||
{
|
||||
struct ksmbd_crypto_ctx *ctx;
|
||||
|
||||
while (1) {
|
||||
spin_lock(&ctx_list.ctx_lock);
|
||||
if (!list_empty(&ctx_list.idle_ctx)) {
|
||||
ctx = list_entry(ctx_list.idle_ctx.next,
|
||||
struct ksmbd_crypto_ctx,
|
||||
list);
|
||||
list_del(&ctx->list);
|
||||
spin_unlock(&ctx_list.ctx_lock);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
if (ctx_list.avail_ctx > num_online_cpus()) {
|
||||
spin_unlock(&ctx_list.ctx_lock);
|
||||
wait_event(ctx_list.ctx_wait,
|
||||
!list_empty(&ctx_list.idle_ctx));
|
||||
continue;
|
||||
}
|
||||
|
||||
ctx_list.avail_ctx++;
|
||||
spin_unlock(&ctx_list.ctx_lock);
|
||||
|
||||
ctx = kzalloc(sizeof(struct ksmbd_crypto_ctx), GFP_KERNEL);
|
||||
if (!ctx) {
|
||||
spin_lock(&ctx_list.ctx_lock);
|
||||
ctx_list.avail_ctx--;
|
||||
spin_unlock(&ctx_list.ctx_lock);
|
||||
wait_event(ctx_list.ctx_wait,
|
||||
!list_empty(&ctx_list.idle_ctx));
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void ksmbd_release_crypto_ctx(struct ksmbd_crypto_ctx *ctx)
|
||||
{
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
spin_lock(&ctx_list.ctx_lock);
|
||||
if (ctx_list.avail_ctx <= num_online_cpus()) {
|
||||
list_add(&ctx->list, &ctx_list.idle_ctx);
|
||||
spin_unlock(&ctx_list.ctx_lock);
|
||||
wake_up(&ctx_list.ctx_wait);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx_list.avail_ctx--;
|
||||
spin_unlock(&ctx_list.ctx_lock);
|
||||
ctx_free(ctx);
|
||||
}
|
||||
|
||||
static struct ksmbd_crypto_ctx *____crypto_shash_ctx_find(int id)
|
||||
{
|
||||
struct ksmbd_crypto_ctx *ctx;
|
||||
|
||||
if (id >= CRYPTO_SHASH_MAX)
|
||||
return NULL;
|
||||
|
||||
ctx = ksmbd_find_crypto_ctx();
|
||||
if (ctx->desc[id])
|
||||
return ctx;
|
||||
|
||||
ctx->desc[id] = alloc_shash_desc(id);
|
||||
if (ctx->desc[id])
|
||||
return ctx;
|
||||
ksmbd_release_crypto_ctx(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacmd5(void)
|
||||
{
|
||||
return ____crypto_shash_ctx_find(CRYPTO_SHASH_HMACMD5);
|
||||
}
|
||||
|
||||
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacsha256(void)
|
||||
{
|
||||
return ____crypto_shash_ctx_find(CRYPTO_SHASH_HMACSHA256);
|
||||
}
|
||||
|
||||
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_cmacaes(void)
|
||||
{
|
||||
return ____crypto_shash_ctx_find(CRYPTO_SHASH_CMACAES);
|
||||
}
|
||||
|
||||
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha256(void)
|
||||
{
|
||||
return ____crypto_shash_ctx_find(CRYPTO_SHASH_SHA256);
|
||||
}
|
||||
|
||||
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha512(void)
|
||||
{
|
||||
return ____crypto_shash_ctx_find(CRYPTO_SHASH_SHA512);
|
||||
}
|
||||
|
||||
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_md4(void)
|
||||
{
|
||||
return ____crypto_shash_ctx_find(CRYPTO_SHASH_MD4);
|
||||
}
|
||||
|
||||
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_md5(void)
|
||||
{
|
||||
return ____crypto_shash_ctx_find(CRYPTO_SHASH_MD5);
|
||||
}
|
||||
|
||||
static struct ksmbd_crypto_ctx *____crypto_aead_ctx_find(int id)
|
||||
{
|
||||
struct ksmbd_crypto_ctx *ctx;
|
||||
|
||||
if (id >= CRYPTO_AEAD_MAX)
|
||||
return NULL;
|
||||
|
||||
ctx = ksmbd_find_crypto_ctx();
|
||||
if (ctx->ccmaes[id])
|
||||
return ctx;
|
||||
|
||||
ctx->ccmaes[id] = alloc_aead(id);
|
||||
if (ctx->ccmaes[id])
|
||||
return ctx;
|
||||
ksmbd_release_crypto_ctx(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_gcm(void)
|
||||
{
|
||||
return ____crypto_aead_ctx_find(CRYPTO_AEAD_AES_GCM);
|
||||
}
|
||||
|
||||
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_ccm(void)
|
||||
{
|
||||
return ____crypto_aead_ctx_find(CRYPTO_AEAD_AES_CCM);
|
||||
}
|
||||
|
||||
void ksmbd_crypto_destroy(void)
|
||||
{
|
||||
struct ksmbd_crypto_ctx *ctx;
|
||||
|
||||
while (!list_empty(&ctx_list.idle_ctx)) {
|
||||
ctx = list_entry(ctx_list.idle_ctx.next,
|
||||
struct ksmbd_crypto_ctx,
|
||||
list);
|
||||
list_del(&ctx->list);
|
||||
ctx_free(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
int ksmbd_crypto_create(void)
|
||||
{
|
||||
struct ksmbd_crypto_ctx *ctx;
|
||||
|
||||
spin_lock_init(&ctx_list.ctx_lock);
|
||||
INIT_LIST_HEAD(&ctx_list.idle_ctx);
|
||||
init_waitqueue_head(&ctx_list.ctx_wait);
|
||||
ctx_list.avail_ctx = 1;
|
||||
|
||||
ctx = kzalloc(sizeof(struct ksmbd_crypto_ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
list_add(&ctx->list, &ctx_list.idle_ctx);
|
||||
return 0;
|
||||
}
|
||||
74
fs/ksmbd/crypto_ctx.h
Normal file
74
fs/ksmbd/crypto_ctx.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2019 Samsung Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#ifndef __CRYPTO_CTX_H__
|
||||
#define __CRYPTO_CTX_H__
|
||||
|
||||
#include <crypto/hash.h>
|
||||
#include <crypto/aead.h>
|
||||
|
||||
enum {
|
||||
CRYPTO_SHASH_HMACMD5 = 0,
|
||||
CRYPTO_SHASH_HMACSHA256,
|
||||
CRYPTO_SHASH_CMACAES,
|
||||
CRYPTO_SHASH_SHA256,
|
||||
CRYPTO_SHASH_SHA512,
|
||||
CRYPTO_SHASH_MD4,
|
||||
CRYPTO_SHASH_MD5,
|
||||
CRYPTO_SHASH_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
CRYPTO_AEAD_AES_GCM = 16,
|
||||
CRYPTO_AEAD_AES_CCM,
|
||||
CRYPTO_AEAD_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
CRYPTO_BLK_ECBDES = 32,
|
||||
CRYPTO_BLK_MAX,
|
||||
};
|
||||
|
||||
struct ksmbd_crypto_ctx {
|
||||
struct list_head list;
|
||||
|
||||
struct shash_desc *desc[CRYPTO_SHASH_MAX];
|
||||
struct crypto_aead *ccmaes[CRYPTO_AEAD_MAX];
|
||||
};
|
||||
|
||||
#define CRYPTO_HMACMD5(c) ((c)->desc[CRYPTO_SHASH_HMACMD5])
|
||||
#define CRYPTO_HMACSHA256(c) ((c)->desc[CRYPTO_SHASH_HMACSHA256])
|
||||
#define CRYPTO_CMACAES(c) ((c)->desc[CRYPTO_SHASH_CMACAES])
|
||||
#define CRYPTO_SHA256(c) ((c)->desc[CRYPTO_SHASH_SHA256])
|
||||
#define CRYPTO_SHA512(c) ((c)->desc[CRYPTO_SHASH_SHA512])
|
||||
#define CRYPTO_MD4(c) ((c)->desc[CRYPTO_SHASH_MD4])
|
||||
#define CRYPTO_MD5(c) ((c)->desc[CRYPTO_SHASH_MD5])
|
||||
|
||||
#define CRYPTO_HMACMD5_TFM(c) ((c)->desc[CRYPTO_SHASH_HMACMD5]->tfm)
|
||||
#define CRYPTO_HMACSHA256_TFM(c)\
|
||||
((c)->desc[CRYPTO_SHASH_HMACSHA256]->tfm)
|
||||
#define CRYPTO_CMACAES_TFM(c) ((c)->desc[CRYPTO_SHASH_CMACAES]->tfm)
|
||||
#define CRYPTO_SHA256_TFM(c) ((c)->desc[CRYPTO_SHASH_SHA256]->tfm)
|
||||
#define CRYPTO_SHA512_TFM(c) ((c)->desc[CRYPTO_SHASH_SHA512]->tfm)
|
||||
#define CRYPTO_MD4_TFM(c) ((c)->desc[CRYPTO_SHASH_MD4]->tfm)
|
||||
#define CRYPTO_MD5_TFM(c) ((c)->desc[CRYPTO_SHASH_MD5]->tfm)
|
||||
|
||||
#define CRYPTO_GCM(c) ((c)->ccmaes[CRYPTO_AEAD_AES_GCM])
|
||||
#define CRYPTO_CCM(c) ((c)->ccmaes[CRYPTO_AEAD_AES_CCM])
|
||||
|
||||
void ksmbd_release_crypto_ctx(struct ksmbd_crypto_ctx *ctx);
|
||||
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacmd5(void);
|
||||
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacsha256(void);
|
||||
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_cmacaes(void);
|
||||
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha512(void);
|
||||
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha256(void);
|
||||
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_md4(void);
|
||||
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_md5(void);
|
||||
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_gcm(void);
|
||||
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_ccm(void);
|
||||
void ksmbd_crypto_destroy(void);
|
||||
int ksmbd_crypto_create(void);
|
||||
|
||||
#endif /* __CRYPTO_CTX_H__ */
|
||||
49
fs/ksmbd/glob.h
Normal file
49
fs/ksmbd/glob.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
|
||||
* Copyright (C) 2018 Samsung Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#ifndef __KSMBD_GLOB_H
|
||||
#define __KSMBD_GLOB_H
|
||||
|
||||
#include <linux/ctype.h>
|
||||
|
||||
#include "unicode.h"
|
||||
#include "vfs_cache.h"
|
||||
|
||||
#define KSMBD_VERSION "3.1.9"
|
||||
|
||||
extern int ksmbd_debug_types;
|
||||
|
||||
#define KSMBD_DEBUG_SMB BIT(0)
|
||||
#define KSMBD_DEBUG_AUTH BIT(1)
|
||||
#define KSMBD_DEBUG_VFS BIT(2)
|
||||
#define KSMBD_DEBUG_OPLOCK BIT(3)
|
||||
#define KSMBD_DEBUG_IPC BIT(4)
|
||||
#define KSMBD_DEBUG_CONN BIT(5)
|
||||
#define KSMBD_DEBUG_RDMA BIT(6)
|
||||
#define KSMBD_DEBUG_ALL (KSMBD_DEBUG_SMB | KSMBD_DEBUG_AUTH | \
|
||||
KSMBD_DEBUG_VFS | KSMBD_DEBUG_OPLOCK | \
|
||||
KSMBD_DEBUG_IPC | KSMBD_DEBUG_CONN | \
|
||||
KSMBD_DEBUG_RDMA)
|
||||
|
||||
#ifdef pr_fmt
|
||||
#undef pr_fmt
|
||||
#endif
|
||||
|
||||
#ifdef SUBMOD_NAME
|
||||
#define pr_fmt(fmt) "ksmbd: " SUBMOD_NAME ": " fmt
|
||||
#else
|
||||
#define pr_fmt(fmt) "ksmbd: " fmt
|
||||
#endif
|
||||
|
||||
#define ksmbd_debug(type, fmt, ...) \
|
||||
do { \
|
||||
if (ksmbd_debug_types & KSMBD_DEBUG_##type) \
|
||||
pr_info(fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define UNICODE_LEN(x) ((x) * 2)
|
||||
|
||||
#endif /* __KSMBD_GLOB_H */
|
||||
395
fs/ksmbd/ksmbd_netlink.h
Normal file
395
fs/ksmbd/ksmbd_netlink.h
Normal file
@@ -0,0 +1,395 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2018 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* linux-ksmbd-devel@lists.sourceforge.net
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_KSMBD_SERVER_H
|
||||
#define _LINUX_KSMBD_SERVER_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/*
|
||||
* This is a userspace ABI to communicate data between ksmbd and user IPC
|
||||
* daemon using netlink. This is added to track and cache user account DB
|
||||
* and share configuration info from userspace.
|
||||
*
|
||||
* - KSMBD_EVENT_HEARTBEAT_REQUEST(ksmbd_heartbeat)
|
||||
* This event is to check whether user IPC daemon is alive. If user IPC
|
||||
* daemon is dead, ksmbd keep existing connection till disconnecting and
|
||||
* new connection will be denied.
|
||||
*
|
||||
* - KSMBD_EVENT_STARTING_UP(ksmbd_startup_request)
|
||||
* This event is to receive the information that initializes the ksmbd
|
||||
* server from the user IPC daemon and to start the server. The global
|
||||
* section parameters are given from smb.conf as initialization
|
||||
* information.
|
||||
*
|
||||
* - KSMBD_EVENT_SHUTTING_DOWN(ksmbd_shutdown_request)
|
||||
* This event is to shutdown ksmbd server.
|
||||
*
|
||||
* - KSMBD_EVENT_LOGIN_REQUEST/RESPONSE(ksmbd_login_request/response)
|
||||
* This event is to get user account info to user IPC daemon.
|
||||
*
|
||||
* - KSMBD_EVENT_SHARE_CONFIG_REQUEST/RESPONSE(ksmbd_share_config_request/response)
|
||||
* This event is to get net share configuration info.
|
||||
*
|
||||
* - KSMBD_EVENT_TREE_CONNECT_REQUEST/RESPONSE(ksmbd_tree_connect_request/response)
|
||||
* This event is to get session and tree connect info.
|
||||
*
|
||||
* - KSMBD_EVENT_TREE_DISCONNECT_REQUEST(ksmbd_tree_disconnect_request)
|
||||
* This event is to send tree disconnect info to user IPC daemon.
|
||||
*
|
||||
* - KSMBD_EVENT_LOGOUT_REQUEST(ksmbd_logout_request)
|
||||
* This event is to send logout request to user IPC daemon.
|
||||
*
|
||||
* - KSMBD_EVENT_RPC_REQUEST/RESPONSE(ksmbd_rpc_command)
|
||||
* This event is to make DCE/RPC request like srvsvc, wkssvc, lsarpc,
|
||||
* samr to be processed in userspace.
|
||||
*
|
||||
* - KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST/RESPONSE(ksmbd_spnego_authen_request/response)
|
||||
* This event is to make kerberos authentication to be processed in
|
||||
* userspace.
|
||||
*/
|
||||
|
||||
#define KSMBD_GENL_NAME "SMBD_GENL"
|
||||
#define KSMBD_GENL_VERSION 0x01
|
||||
|
||||
#define KSMBD_REQ_MAX_ACCOUNT_NAME_SZ 48
|
||||
#define KSMBD_REQ_MAX_HASH_SZ 18
|
||||
#define KSMBD_REQ_MAX_SHARE_NAME 64
|
||||
|
||||
/*
|
||||
* IPC heartbeat frame to check whether user IPC daemon is alive.
|
||||
*/
|
||||
struct ksmbd_heartbeat {
|
||||
__u32 handle;
|
||||
};
|
||||
|
||||
/*
|
||||
* Global config flags.
|
||||
*/
|
||||
#define KSMBD_GLOBAL_FLAG_INVALID (0)
|
||||
#define KSMBD_GLOBAL_FLAG_SMB2_LEASES BIT(0)
|
||||
#define KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION BIT(1)
|
||||
#define KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL BIT(2)
|
||||
|
||||
/*
|
||||
* IPC request for ksmbd server startup
|
||||
*/
|
||||
struct ksmbd_startup_request {
|
||||
__u32 flags; /* Flags for global config */
|
||||
__s32 signing; /* Signing enabled */
|
||||
__s8 min_prot[16]; /* The minimum SMB protocol version */
|
||||
__s8 max_prot[16]; /* The maximum SMB protocol version */
|
||||
__s8 netbios_name[16];
|
||||
__s8 work_group[64]; /* Workgroup */
|
||||
__s8 server_string[64]; /* Server string */
|
||||
__u16 tcp_port; /* tcp port */
|
||||
__u16 ipc_timeout; /*
|
||||
* specifies the number of seconds
|
||||
* server will wait for the userspace to
|
||||
* reply to heartbeat frames.
|
||||
*/
|
||||
__u32 deadtime; /* Number of minutes of inactivity */
|
||||
__u32 file_max; /* Limits the maximum number of open files */
|
||||
__u32 smb2_max_write; /* MAX write size */
|
||||
__u32 smb2_max_read; /* MAX read size */
|
||||
__u32 smb2_max_trans; /* MAX trans size */
|
||||
__u32 share_fake_fscaps; /*
|
||||
* Support some special application that
|
||||
* makes QFSINFO calls to check whether
|
||||
* we set the SPARSE_FILES bit (0x40).
|
||||
*/
|
||||
__u32 sub_auth[3]; /* Subauth value for Security ID */
|
||||
__u32 ifc_list_sz; /* interfaces list size */
|
||||
__s8 ____payload[];
|
||||
};
|
||||
|
||||
#define KSMBD_STARTUP_CONFIG_INTERFACES(s) ((s)->____payload)
|
||||
|
||||
/*
|
||||
* IPC request to shutdown ksmbd server.
|
||||
*/
|
||||
struct ksmbd_shutdown_request {
|
||||
__s32 reserved;
|
||||
};
|
||||
|
||||
/*
|
||||
* IPC user login request.
|
||||
*/
|
||||
struct ksmbd_login_request {
|
||||
__u32 handle;
|
||||
__s8 account[KSMBD_REQ_MAX_ACCOUNT_NAME_SZ]; /* user account name */
|
||||
};
|
||||
|
||||
/*
|
||||
* IPC user login response.
|
||||
*/
|
||||
struct ksmbd_login_response {
|
||||
__u32 handle;
|
||||
__u32 gid; /* group id */
|
||||
__u32 uid; /* user id */
|
||||
__s8 account[KSMBD_REQ_MAX_ACCOUNT_NAME_SZ]; /* user account name */
|
||||
__u16 status;
|
||||
__u16 hash_sz; /* hash size */
|
||||
__s8 hash[KSMBD_REQ_MAX_HASH_SZ]; /* password hash */
|
||||
};
|
||||
|
||||
/*
|
||||
* IPC request to fetch net share config.
|
||||
*/
|
||||
struct ksmbd_share_config_request {
|
||||
__u32 handle;
|
||||
__s8 share_name[KSMBD_REQ_MAX_SHARE_NAME]; /* share name */
|
||||
};
|
||||
|
||||
/*
|
||||
* IPC response to the net share config request.
|
||||
*/
|
||||
struct ksmbd_share_config_response {
|
||||
__u32 handle;
|
||||
__u32 flags;
|
||||
__u16 create_mask;
|
||||
__u16 directory_mask;
|
||||
__u16 force_create_mode;
|
||||
__u16 force_directory_mode;
|
||||
__u16 force_uid;
|
||||
__u16 force_gid;
|
||||
__u32 veto_list_sz;
|
||||
__s8 ____payload[];
|
||||
};
|
||||
|
||||
#define KSMBD_SHARE_CONFIG_VETO_LIST(s) ((s)->____payload)
|
||||
|
||||
static inline char *
|
||||
ksmbd_share_config_path(struct ksmbd_share_config_response *sc)
|
||||
{
|
||||
char *p = sc->____payload;
|
||||
|
||||
if (sc->veto_list_sz)
|
||||
p += sc->veto_list_sz + 1;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
* IPC request for tree connection. This request include session and tree
|
||||
* connect info from client.
|
||||
*/
|
||||
struct ksmbd_tree_connect_request {
|
||||
__u32 handle;
|
||||
__u16 account_flags;
|
||||
__u16 flags;
|
||||
__u64 session_id;
|
||||
__u64 connect_id;
|
||||
__s8 account[KSMBD_REQ_MAX_ACCOUNT_NAME_SZ];
|
||||
__s8 share[KSMBD_REQ_MAX_SHARE_NAME];
|
||||
__s8 peer_addr[64];
|
||||
};
|
||||
|
||||
/*
|
||||
* IPC Response structure for tree connection.
|
||||
*/
|
||||
struct ksmbd_tree_connect_response {
|
||||
__u32 handle;
|
||||
__u16 status;
|
||||
__u16 connection_flags;
|
||||
};
|
||||
|
||||
/*
|
||||
* IPC Request struture to disconnect tree connection.
|
||||
*/
|
||||
struct ksmbd_tree_disconnect_request {
|
||||
__u64 session_id; /* session id */
|
||||
__u64 connect_id; /* tree connection id */
|
||||
};
|
||||
|
||||
/*
|
||||
* IPC Response structure to logout user account.
|
||||
*/
|
||||
struct ksmbd_logout_request {
|
||||
__s8 account[KSMBD_REQ_MAX_ACCOUNT_NAME_SZ]; /* user account name */
|
||||
};
|
||||
|
||||
/*
|
||||
* RPC command structure to send rpc request like srvsvc or wkssvc to
|
||||
* IPC user daemon.
|
||||
*/
|
||||
struct ksmbd_rpc_command {
|
||||
__u32 handle;
|
||||
__u32 flags;
|
||||
__u32 payload_sz;
|
||||
__u8 payload[];
|
||||
};
|
||||
|
||||
/*
|
||||
* IPC Request Kerberos authentication
|
||||
*/
|
||||
struct ksmbd_spnego_authen_request {
|
||||
__u32 handle;
|
||||
__u16 spnego_blob_len; /* the length of spnego_blob */
|
||||
__u8 spnego_blob[0]; /*
|
||||
* the GSS token from SecurityBuffer of
|
||||
* SMB2 SESSION SETUP request
|
||||
*/
|
||||
};
|
||||
|
||||
/*
|
||||
* Response data which includes the GSS token and the session key generated by
|
||||
* user daemon.
|
||||
*/
|
||||
struct ksmbd_spnego_authen_response {
|
||||
__u32 handle;
|
||||
struct ksmbd_login_response login_response; /*
|
||||
* the login response with
|
||||
* a user identified by the
|
||||
* GSS token from a client
|
||||
*/
|
||||
__u16 session_key_len; /* the length of the session key */
|
||||
__u16 spnego_blob_len; /*
|
||||
* the length of the GSS token which will be
|
||||
* stored in SecurityBuffer of SMB2 SESSION
|
||||
* SETUP response
|
||||
*/
|
||||
__u8 payload[]; /* session key + AP_REP */
|
||||
};
|
||||
|
||||
/*
|
||||
* This also used as NETLINK attribute type value.
|
||||
*
|
||||
* NOTE:
|
||||
* Response message type value should be equal to
|
||||
* request message type value + 1.
|
||||
*/
|
||||
enum ksmbd_event {
|
||||
KSMBD_EVENT_UNSPEC = 0,
|
||||
KSMBD_EVENT_HEARTBEAT_REQUEST,
|
||||
|
||||
KSMBD_EVENT_STARTING_UP,
|
||||
KSMBD_EVENT_SHUTTING_DOWN,
|
||||
|
||||
KSMBD_EVENT_LOGIN_REQUEST,
|
||||
KSMBD_EVENT_LOGIN_RESPONSE = 5,
|
||||
|
||||
KSMBD_EVENT_SHARE_CONFIG_REQUEST,
|
||||
KSMBD_EVENT_SHARE_CONFIG_RESPONSE,
|
||||
|
||||
KSMBD_EVENT_TREE_CONNECT_REQUEST,
|
||||
KSMBD_EVENT_TREE_CONNECT_RESPONSE,
|
||||
|
||||
KSMBD_EVENT_TREE_DISCONNECT_REQUEST = 10,
|
||||
|
||||
KSMBD_EVENT_LOGOUT_REQUEST,
|
||||
|
||||
KSMBD_EVENT_RPC_REQUEST,
|
||||
KSMBD_EVENT_RPC_RESPONSE,
|
||||
|
||||
KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST,
|
||||
KSMBD_EVENT_SPNEGO_AUTHEN_RESPONSE = 15,
|
||||
|
||||
KSMBD_EVENT_MAX
|
||||
};
|
||||
|
||||
/*
|
||||
* Enumeration for IPC tree connect status.
|
||||
*/
|
||||
enum KSMBD_TREE_CONN_STATUS {
|
||||
KSMBD_TREE_CONN_STATUS_OK = 0,
|
||||
KSMBD_TREE_CONN_STATUS_NOMEM,
|
||||
KSMBD_TREE_CONN_STATUS_NO_SHARE,
|
||||
KSMBD_TREE_CONN_STATUS_NO_USER,
|
||||
KSMBD_TREE_CONN_STATUS_INVALID_USER,
|
||||
KSMBD_TREE_CONN_STATUS_HOST_DENIED = 5,
|
||||
KSMBD_TREE_CONN_STATUS_CONN_EXIST,
|
||||
KSMBD_TREE_CONN_STATUS_TOO_MANY_CONNS,
|
||||
KSMBD_TREE_CONN_STATUS_TOO_MANY_SESSIONS,
|
||||
KSMBD_TREE_CONN_STATUS_ERROR,
|
||||
};
|
||||
|
||||
/*
|
||||
* User config flags.
|
||||
*/
|
||||
#define KSMBD_USER_FLAG_INVALID (0)
|
||||
#define KSMBD_USER_FLAG_OK BIT(0)
|
||||
#define KSMBD_USER_FLAG_BAD_PASSWORD BIT(1)
|
||||
#define KSMBD_USER_FLAG_BAD_UID BIT(2)
|
||||
#define KSMBD_USER_FLAG_BAD_USER BIT(3)
|
||||
#define KSMBD_USER_FLAG_GUEST_ACCOUNT BIT(4)
|
||||
|
||||
/*
|
||||
* Share config flags.
|
||||
*/
|
||||
#define KSMBD_SHARE_FLAG_INVALID (0)
|
||||
#define KSMBD_SHARE_FLAG_AVAILABLE BIT(0)
|
||||
#define KSMBD_SHARE_FLAG_BROWSEABLE BIT(1)
|
||||
#define KSMBD_SHARE_FLAG_WRITEABLE BIT(2)
|
||||
#define KSMBD_SHARE_FLAG_READONLY BIT(3)
|
||||
#define KSMBD_SHARE_FLAG_GUEST_OK BIT(4)
|
||||
#define KSMBD_SHARE_FLAG_GUEST_ONLY BIT(5)
|
||||
#define KSMBD_SHARE_FLAG_STORE_DOS_ATTRS BIT(6)
|
||||
#define KSMBD_SHARE_FLAG_OPLOCKS BIT(7)
|
||||
#define KSMBD_SHARE_FLAG_PIPE BIT(8)
|
||||
#define KSMBD_SHARE_FLAG_HIDE_DOT_FILES BIT(9)
|
||||
#define KSMBD_SHARE_FLAG_INHERIT_OWNER BIT(10)
|
||||
#define KSMBD_SHARE_FLAG_STREAMS BIT(11)
|
||||
#define KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS BIT(12)
|
||||
#define KSMBD_SHARE_FLAG_ACL_XATTR BIT(13)
|
||||
|
||||
/*
|
||||
* Tree connect request flags.
|
||||
*/
|
||||
#define KSMBD_TREE_CONN_FLAG_REQUEST_SMB1 (0)
|
||||
#define KSMBD_TREE_CONN_FLAG_REQUEST_IPV6 BIT(0)
|
||||
#define KSMBD_TREE_CONN_FLAG_REQUEST_SMB2 BIT(1)
|
||||
|
||||
/*
|
||||
* Tree connect flags.
|
||||
*/
|
||||
#define KSMBD_TREE_CONN_FLAG_GUEST_ACCOUNT BIT(0)
|
||||
#define KSMBD_TREE_CONN_FLAG_READ_ONLY BIT(1)
|
||||
#define KSMBD_TREE_CONN_FLAG_WRITABLE BIT(2)
|
||||
#define KSMBD_TREE_CONN_FLAG_ADMIN_ACCOUNT BIT(3)
|
||||
|
||||
/*
|
||||
* RPC over IPC.
|
||||
*/
|
||||
#define KSMBD_RPC_METHOD_RETURN BIT(0)
|
||||
#define KSMBD_RPC_SRVSVC_METHOD_INVOKE BIT(1)
|
||||
#define KSMBD_RPC_SRVSVC_METHOD_RETURN (KSMBD_RPC_SRVSVC_METHOD_INVOKE | KSMBD_RPC_METHOD_RETURN)
|
||||
#define KSMBD_RPC_WKSSVC_METHOD_INVOKE BIT(2)
|
||||
#define KSMBD_RPC_WKSSVC_METHOD_RETURN (KSMBD_RPC_WKSSVC_METHOD_INVOKE | KSMBD_RPC_METHOD_RETURN)
|
||||
#define KSMBD_RPC_IOCTL_METHOD (BIT(3) | KSMBD_RPC_METHOD_RETURN)
|
||||
#define KSMBD_RPC_OPEN_METHOD BIT(4)
|
||||
#define KSMBD_RPC_WRITE_METHOD BIT(5)
|
||||
#define KSMBD_RPC_READ_METHOD (BIT(6) | KSMBD_RPC_METHOD_RETURN)
|
||||
#define KSMBD_RPC_CLOSE_METHOD BIT(7)
|
||||
#define KSMBD_RPC_RAP_METHOD (BIT(8) | KSMBD_RPC_METHOD_RETURN)
|
||||
#define KSMBD_RPC_RESTRICTED_CONTEXT BIT(9)
|
||||
#define KSMBD_RPC_SAMR_METHOD_INVOKE BIT(10)
|
||||
#define KSMBD_RPC_SAMR_METHOD_RETURN (KSMBD_RPC_SAMR_METHOD_INVOKE | KSMBD_RPC_METHOD_RETURN)
|
||||
#define KSMBD_RPC_LSARPC_METHOD_INVOKE BIT(11)
|
||||
#define KSMBD_RPC_LSARPC_METHOD_RETURN (KSMBD_RPC_LSARPC_METHOD_INVOKE | KSMBD_RPC_METHOD_RETURN)
|
||||
|
||||
/*
|
||||
* RPC status definitions.
|
||||
*/
|
||||
#define KSMBD_RPC_OK 0
|
||||
#define KSMBD_RPC_EBAD_FUNC 0x00000001
|
||||
#define KSMBD_RPC_EACCESS_DENIED 0x00000005
|
||||
#define KSMBD_RPC_EBAD_FID 0x00000006
|
||||
#define KSMBD_RPC_ENOMEM 0x00000008
|
||||
#define KSMBD_RPC_EBAD_DATA 0x0000000D
|
||||
#define KSMBD_RPC_ENOTIMPLEMENTED 0x00000040
|
||||
#define KSMBD_RPC_EINVALID_PARAMETER 0x00000057
|
||||
#define KSMBD_RPC_EMORE_DATA 0x000000EA
|
||||
#define KSMBD_RPC_EINVALID_LEVEL 0x0000007C
|
||||
#define KSMBD_RPC_SOME_NOT_MAPPED 0x00000107
|
||||
|
||||
#define KSMBD_CONFIG_OPT_DISABLED 0
|
||||
#define KSMBD_CONFIG_OPT_ENABLED 1
|
||||
#define KSMBD_CONFIG_OPT_AUTO 2
|
||||
#define KSMBD_CONFIG_OPT_MANDATORY 3
|
||||
|
||||
#endif /* _LINUX_KSMBD_SERVER_H */
|
||||
31
fs/ksmbd/ksmbd_spnego_negtokeninit.asn1
Normal file
31
fs/ksmbd/ksmbd_spnego_negtokeninit.asn1
Normal file
@@ -0,0 +1,31 @@
|
||||
GSSAPI ::=
|
||||
[APPLICATION 0] IMPLICIT SEQUENCE {
|
||||
thisMech
|
||||
OBJECT IDENTIFIER ({ksmbd_gssapi_this_mech}),
|
||||
negotiationToken
|
||||
NegotiationToken
|
||||
}
|
||||
|
||||
MechType ::= OBJECT IDENTIFIER ({ksmbd_neg_token_init_mech_type})
|
||||
|
||||
MechTypeList ::= SEQUENCE OF MechType
|
||||
|
||||
NegTokenInit ::=
|
||||
SEQUENCE {
|
||||
mechTypes
|
||||
[0] MechTypeList,
|
||||
reqFlags
|
||||
[1] BIT STRING OPTIONAL,
|
||||
mechToken
|
||||
[2] OCTET STRING OPTIONAL ({ksmbd_neg_token_init_mech_token}),
|
||||
mechListMIC
|
||||
[3] OCTET STRING OPTIONAL
|
||||
}
|
||||
|
||||
NegotiationToken ::=
|
||||
CHOICE {
|
||||
negTokenInit
|
||||
[0] NegTokenInit,
|
||||
negTokenTarg
|
||||
[1] ANY
|
||||
}
|
||||
19
fs/ksmbd/ksmbd_spnego_negtokentarg.asn1
Normal file
19
fs/ksmbd/ksmbd_spnego_negtokentarg.asn1
Normal file
@@ -0,0 +1,19 @@
|
||||
GSSAPI ::=
|
||||
CHOICE {
|
||||
negTokenInit
|
||||
[0] ANY,
|
||||
negTokenTarg
|
||||
[1] NegTokenTarg
|
||||
}
|
||||
|
||||
NegTokenTarg ::=
|
||||
SEQUENCE {
|
||||
negResult
|
||||
[0] ENUMERATED OPTIONAL,
|
||||
supportedMech
|
||||
[1] OBJECT IDENTIFIER OPTIONAL,
|
||||
responseToken
|
||||
[2] OCTET STRING OPTIONAL ({ksmbd_neg_token_targ_resp_token}),
|
||||
mechListMIC
|
||||
[3] OCTET STRING OPTIONAL
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user