linux/fs/ksmbd/smb2ops.c
Namjae Jeon 8b758859df ksmbd: reorder and document on-disk and netlink structures in headers
Reorder and document on-disk and netlink structures in headers.

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.

Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
2021-06-30 14:47:24 +09:00

309 lines
11 KiB
C

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
* Copyright (C) 2018 Samsung Electronics Co., Ltd.
*/
#include <linux/slab.h>
#include "glob.h"
#include "smb2pdu.h"
#include "auth.h"
#include "connection.h"
#include "smb_common.h"
#include "server.h"
static struct smb_version_values smb21_server_values = {
.version_string = SMB21_VERSION_STRING,
.protocol_id = SMB21_PROT_ID,
.capabilities = SMB2_GLOBAL_CAP_LARGE_MTU,
.max_read_size = SMB21_DEFAULT_IOSIZE,
.max_write_size = SMB21_DEFAULT_IOSIZE,
.max_trans_size = SMB21_DEFAULT_IOSIZE,
.large_lock_type = 0,
.exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
.shared_lock_type = SMB2_LOCKFLAG_SHARED,
.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,
.create_lease_size = sizeof(struct create_lease),
.create_durable_size = sizeof(struct create_durable_rsp),
.create_mxac_size = sizeof(struct create_mxac_rsp),
.create_disk_id_size = sizeof(struct create_disk_id_rsp),
.create_posix_size = sizeof(struct create_posix_rsp),
};
static struct smb_version_values smb30_server_values = {
.version_string = SMB30_VERSION_STRING,
.protocol_id = SMB30_PROT_ID,
.capabilities = SMB2_GLOBAL_CAP_LARGE_MTU,
.max_read_size = SMB3_DEFAULT_IOSIZE,
.max_write_size = SMB3_DEFAULT_IOSIZE,
.max_trans_size = SMB3_DEFAULT_TRANS_SIZE,
.large_lock_type = 0,
.exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
.shared_lock_type = SMB2_LOCKFLAG_SHARED,
.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,
.create_lease_size = sizeof(struct create_lease_v2),
.create_durable_size = sizeof(struct create_durable_rsp),
.create_durable_v2_size = sizeof(struct create_durable_v2_rsp),
.create_mxac_size = sizeof(struct create_mxac_rsp),
.create_disk_id_size = sizeof(struct create_disk_id_rsp),
.create_posix_size = sizeof(struct create_posix_rsp),
};
static struct smb_version_values smb302_server_values = {
.version_string = SMB302_VERSION_STRING,
.protocol_id = SMB302_PROT_ID,
.capabilities = SMB2_GLOBAL_CAP_LARGE_MTU,
.max_read_size = SMB3_DEFAULT_IOSIZE,
.max_write_size = SMB3_DEFAULT_IOSIZE,
.max_trans_size = SMB3_DEFAULT_TRANS_SIZE,
.large_lock_type = 0,
.exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
.shared_lock_type = SMB2_LOCKFLAG_SHARED,
.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,
.create_lease_size = sizeof(struct create_lease_v2),
.create_durable_size = sizeof(struct create_durable_rsp),
.create_durable_v2_size = sizeof(struct create_durable_v2_rsp),
.create_mxac_size = sizeof(struct create_mxac_rsp),
.create_disk_id_size = sizeof(struct create_disk_id_rsp),
.create_posix_size = sizeof(struct create_posix_rsp),
};
static struct smb_version_values smb311_server_values = {
.version_string = SMB311_VERSION_STRING,
.protocol_id = SMB311_PROT_ID,
.capabilities = SMB2_GLOBAL_CAP_LARGE_MTU,
.max_read_size = SMB3_DEFAULT_IOSIZE,
.max_write_size = SMB3_DEFAULT_IOSIZE,
.max_trans_size = SMB3_DEFAULT_TRANS_SIZE,
.large_lock_type = 0,
.exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
.shared_lock_type = SMB2_LOCKFLAG_SHARED,
.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,
.create_lease_size = sizeof(struct create_lease_v2),
.create_durable_size = sizeof(struct create_durable_rsp),
.create_durable_v2_size = sizeof(struct create_durable_v2_rsp),
.create_mxac_size = sizeof(struct create_mxac_rsp),
.create_disk_id_size = sizeof(struct create_disk_id_rsp),
.create_posix_size = sizeof(struct create_posix_rsp),
};
static struct smb_version_ops smb2_0_server_ops = {
.get_cmd_val = get_smb2_cmd_val,
.init_rsp_hdr = init_smb2_rsp_hdr,
.set_rsp_status = set_smb2_rsp_status,
.allocate_rsp_buf = smb2_allocate_rsp_buf,
.set_rsp_credits = smb2_set_rsp_credits,
.check_user_session = smb2_check_user_session,
.get_ksmbd_tcon = smb2_get_ksmbd_tcon,
.is_sign_req = smb2_is_sign_req,
.check_sign_req = smb2_check_sign_req,
.set_sign_rsp = smb2_set_sign_rsp
};
static struct smb_version_ops smb3_0_server_ops = {
.get_cmd_val = get_smb2_cmd_val,
.init_rsp_hdr = init_smb2_rsp_hdr,
.set_rsp_status = set_smb2_rsp_status,
.allocate_rsp_buf = smb2_allocate_rsp_buf,
.set_rsp_credits = smb2_set_rsp_credits,
.check_user_session = smb2_check_user_session,
.get_ksmbd_tcon = smb2_get_ksmbd_tcon,
.is_sign_req = smb2_is_sign_req,
.check_sign_req = smb3_check_sign_req,
.set_sign_rsp = smb3_set_sign_rsp,
.generate_signingkey = ksmbd_gen_smb30_signingkey,
.generate_encryptionkey = ksmbd_gen_smb30_encryptionkey,
.is_transform_hdr = smb3_is_transform_hdr,
.decrypt_req = smb3_decrypt_req,
.encrypt_resp = smb3_encrypt_resp
};
static struct smb_version_ops smb3_11_server_ops = {
.get_cmd_val = get_smb2_cmd_val,
.init_rsp_hdr = init_smb2_rsp_hdr,
.set_rsp_status = set_smb2_rsp_status,
.allocate_rsp_buf = smb2_allocate_rsp_buf,
.set_rsp_credits = smb2_set_rsp_credits,
.check_user_session = smb2_check_user_session,
.get_ksmbd_tcon = smb2_get_ksmbd_tcon,
.is_sign_req = smb2_is_sign_req,
.check_sign_req = smb3_check_sign_req,
.set_sign_rsp = smb3_set_sign_rsp,
.generate_signingkey = ksmbd_gen_smb311_signingkey,
.generate_encryptionkey = ksmbd_gen_smb311_encryptionkey,
.is_transform_hdr = smb3_is_transform_hdr,
.decrypt_req = smb3_decrypt_req,
.encrypt_resp = smb3_encrypt_resp
};
static struct smb_version_cmds smb2_0_server_cmds[NUMBER_OF_SMB2_COMMANDS] = {
[SMB2_NEGOTIATE_HE] = { .proc = smb2_negotiate_request, },
[SMB2_SESSION_SETUP_HE] = { .proc = smb2_sess_setup, },
[SMB2_TREE_CONNECT_HE] = { .proc = smb2_tree_connect,},
[SMB2_TREE_DISCONNECT_HE] = { .proc = smb2_tree_disconnect,},
[SMB2_LOGOFF_HE] = { .proc = smb2_session_logoff,},
[SMB2_CREATE_HE] = { .proc = smb2_open},
[SMB2_QUERY_INFO_HE] = { .proc = smb2_query_info},
[SMB2_QUERY_DIRECTORY_HE] = { .proc = smb2_query_dir},
[SMB2_CLOSE_HE] = { .proc = smb2_close},
[SMB2_ECHO_HE] = { .proc = smb2_echo},
[SMB2_SET_INFO_HE] = { .proc = smb2_set_info},
[SMB2_READ_HE] = { .proc = smb2_read},
[SMB2_WRITE_HE] = { .proc = smb2_write},
[SMB2_FLUSH_HE] = { .proc = smb2_flush},
[SMB2_CANCEL_HE] = { .proc = smb2_cancel},
[SMB2_LOCK_HE] = { .proc = smb2_lock},
[SMB2_IOCTL_HE] = { .proc = smb2_ioctl},
[SMB2_OPLOCK_BREAK_HE] = { .proc = smb2_oplock_break},
[SMB2_CHANGE_NOTIFY_HE] = { .proc = smb2_notify},
};
int init_smb2_0_server(struct ksmbd_conn *conn)
{
return -EOPNOTSUPP;
}
/**
* init_smb2_1_server() - initialize a smb server connection with smb2.1
* command dispatcher
* @conn: connection instance
*/
void init_smb2_1_server(struct ksmbd_conn *conn)
{
conn->vals = &smb21_server_values;
conn->ops = &smb2_0_server_ops;
conn->cmds = smb2_0_server_cmds;
conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);
conn->max_credits = SMB2_MAX_CREDITS;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
}
/**
* init_smb3_0_server() - initialize a smb server connection with smb3.0
* command dispatcher
* @conn: connection instance
*/
void init_smb3_0_server(struct ksmbd_conn *conn)
{
conn->vals = &smb30_server_values;
conn->ops = &smb3_0_server_ops;
conn->cmds = smb2_0_server_cmds;
conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);
conn->max_credits = SMB2_MAX_CREDITS;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION &&
conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL;
}
/**
* init_smb3_02_server() - initialize a smb server connection with smb3.02
* command dispatcher
* @conn: connection instance
*/
void init_smb3_02_server(struct ksmbd_conn *conn)
{
conn->vals = &smb302_server_values;
conn->ops = &smb3_0_server_ops;
conn->cmds = smb2_0_server_cmds;
conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);
conn->max_credits = SMB2_MAX_CREDITS;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION &&
conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL;
}
/**
* init_smb3_11_server() - initialize a smb server connection with smb3.11
* command dispatcher
* @conn: connection instance
*/
int init_smb3_11_server(struct ksmbd_conn *conn)
{
conn->vals = &smb311_server_values;
conn->ops = &smb3_11_server_ops;
conn->cmds = smb2_0_server_cmds;
conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);
conn->max_credits = SMB2_MAX_CREDITS;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
if (conn->cipher_type)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL;
INIT_LIST_HEAD(&conn->preauth_sess_table);
return 0;
}
void init_smb2_max_read_size(unsigned int sz)
{
smb21_server_values.max_read_size = sz;
smb30_server_values.max_read_size = sz;
smb302_server_values.max_read_size = sz;
smb311_server_values.max_read_size = sz;
}
void init_smb2_max_write_size(unsigned int sz)
{
smb21_server_values.max_write_size = sz;
smb30_server_values.max_write_size = sz;
smb302_server_values.max_write_size = sz;
smb311_server_values.max_write_size = sz;
}
void init_smb2_max_trans_size(unsigned int sz)
{
smb21_server_values.max_trans_size = sz;
smb30_server_values.max_trans_size = sz;
smb302_server_values.max_trans_size = sz;
smb311_server_values.max_trans_size = sz;
}