330 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>4 * Copyright (C) 2018 Samsung Electronics Co., Ltd.5 */6 7#include <linux/slab.h>8#include "glob.h"9 10#include "auth.h"11#include "connection.h"12#include "smb_common.h"13#include "server.h"14 15static struct smb_version_values smb21_server_values = {16 .version_string = SMB21_VERSION_STRING,17 .protocol_id = SMB21_PROT_ID,18 .capabilities = SMB2_GLOBAL_CAP_LARGE_MTU,19 .max_read_size = SMB21_DEFAULT_IOSIZE,20 .max_write_size = SMB21_DEFAULT_IOSIZE,21 .max_trans_size = SMB21_DEFAULT_IOSIZE,22 .max_credits = SMB2_MAX_CREDITS,23 .large_lock_type = 0,24 .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,25 .shared_lock_type = SMB2_LOCKFLAG_SHARED,26 .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,27 .header_size = sizeof(struct smb2_hdr),28 .max_header_size = MAX_SMB2_HDR_SIZE,29 .read_rsp_size = sizeof(struct smb2_read_rsp),30 .lock_cmd = SMB2_LOCK,31 .cap_unix = 0,32 .cap_nt_find = SMB2_NT_FIND,33 .cap_large_files = SMB2_LARGE_FILES,34 .create_lease_size = sizeof(struct create_lease),35 .create_durable_size = sizeof(struct create_durable_rsp),36 .create_mxac_size = sizeof(struct create_mxac_rsp),37 .create_disk_id_size = sizeof(struct create_disk_id_rsp),38 .create_posix_size = sizeof(struct create_posix_rsp),39};40 41static struct smb_version_values smb30_server_values = {42 .version_string = SMB30_VERSION_STRING,43 .protocol_id = SMB30_PROT_ID,44 .capabilities = SMB2_GLOBAL_CAP_LARGE_MTU,45 .max_read_size = SMB3_DEFAULT_IOSIZE,46 .max_write_size = SMB3_DEFAULT_IOSIZE,47 .max_trans_size = SMB3_DEFAULT_TRANS_SIZE,48 .max_credits = SMB2_MAX_CREDITS,49 .large_lock_type = 0,50 .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,51 .shared_lock_type = SMB2_LOCKFLAG_SHARED,52 .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,53 .header_size = sizeof(struct smb2_hdr),54 .max_header_size = MAX_SMB2_HDR_SIZE,55 .read_rsp_size = sizeof(struct smb2_read_rsp),56 .lock_cmd = SMB2_LOCK,57 .cap_unix = 0,58 .cap_nt_find = SMB2_NT_FIND,59 .cap_large_files = SMB2_LARGE_FILES,60 .create_lease_size = sizeof(struct create_lease_v2),61 .create_durable_size = sizeof(struct create_durable_rsp),62 .create_durable_v2_size = sizeof(struct create_durable_v2_rsp),63 .create_mxac_size = sizeof(struct create_mxac_rsp),64 .create_disk_id_size = sizeof(struct create_disk_id_rsp),65 .create_posix_size = sizeof(struct create_posix_rsp),66};67 68static struct smb_version_values smb302_server_values = {69 .version_string = SMB302_VERSION_STRING,70 .protocol_id = SMB302_PROT_ID,71 .capabilities = SMB2_GLOBAL_CAP_LARGE_MTU,72 .max_read_size = SMB3_DEFAULT_IOSIZE,73 .max_write_size = SMB3_DEFAULT_IOSIZE,74 .max_trans_size = SMB3_DEFAULT_TRANS_SIZE,75 .max_credits = SMB2_MAX_CREDITS,76 .large_lock_type = 0,77 .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,78 .shared_lock_type = SMB2_LOCKFLAG_SHARED,79 .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,80 .header_size = sizeof(struct smb2_hdr),81 .max_header_size = MAX_SMB2_HDR_SIZE,82 .read_rsp_size = sizeof(struct smb2_read_rsp),83 .lock_cmd = SMB2_LOCK,84 .cap_unix = 0,85 .cap_nt_find = SMB2_NT_FIND,86 .cap_large_files = SMB2_LARGE_FILES,87 .create_lease_size = sizeof(struct create_lease_v2),88 .create_durable_size = sizeof(struct create_durable_rsp),89 .create_durable_v2_size = sizeof(struct create_durable_v2_rsp),90 .create_mxac_size = sizeof(struct create_mxac_rsp),91 .create_disk_id_size = sizeof(struct create_disk_id_rsp),92 .create_posix_size = sizeof(struct create_posix_rsp),93};94 95static struct smb_version_values smb311_server_values = {96 .version_string = SMB311_VERSION_STRING,97 .protocol_id = SMB311_PROT_ID,98 .capabilities = SMB2_GLOBAL_CAP_LARGE_MTU,99 .max_read_size = SMB3_DEFAULT_IOSIZE,100 .max_write_size = SMB3_DEFAULT_IOSIZE,101 .max_trans_size = SMB3_DEFAULT_TRANS_SIZE,102 .max_credits = SMB2_MAX_CREDITS,103 .large_lock_type = 0,104 .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,105 .shared_lock_type = SMB2_LOCKFLAG_SHARED,106 .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,107 .header_size = sizeof(struct smb2_hdr),108 .max_header_size = MAX_SMB2_HDR_SIZE,109 .read_rsp_size = sizeof(struct smb2_read_rsp),110 .lock_cmd = SMB2_LOCK,111 .cap_unix = 0,112 .cap_nt_find = SMB2_NT_FIND,113 .cap_large_files = SMB2_LARGE_FILES,114 .create_lease_size = sizeof(struct create_lease_v2),115 .create_durable_size = sizeof(struct create_durable_rsp),116 .create_durable_v2_size = sizeof(struct create_durable_v2_rsp),117 .create_mxac_size = sizeof(struct create_mxac_rsp),118 .create_disk_id_size = sizeof(struct create_disk_id_rsp),119 .create_posix_size = sizeof(struct create_posix_rsp),120};121 122static struct smb_version_ops smb2_0_server_ops = {123 .get_cmd_val = get_smb2_cmd_val,124 .init_rsp_hdr = init_smb2_rsp_hdr,125 .set_rsp_status = set_smb2_rsp_status,126 .allocate_rsp_buf = smb2_allocate_rsp_buf,127 .set_rsp_credits = smb2_set_rsp_credits,128 .check_user_session = smb2_check_user_session,129 .get_ksmbd_tcon = smb2_get_ksmbd_tcon,130 .is_sign_req = smb2_is_sign_req,131 .check_sign_req = smb2_check_sign_req,132 .set_sign_rsp = smb2_set_sign_rsp133};134 135static struct smb_version_ops smb3_0_server_ops = {136 .get_cmd_val = get_smb2_cmd_val,137 .init_rsp_hdr = init_smb2_rsp_hdr,138 .set_rsp_status = set_smb2_rsp_status,139 .allocate_rsp_buf = smb2_allocate_rsp_buf,140 .set_rsp_credits = smb2_set_rsp_credits,141 .check_user_session = smb2_check_user_session,142 .get_ksmbd_tcon = smb2_get_ksmbd_tcon,143 .is_sign_req = smb2_is_sign_req,144 .check_sign_req = smb3_check_sign_req,145 .set_sign_rsp = smb3_set_sign_rsp,146 .generate_signingkey = ksmbd_gen_smb30_signingkey,147 .generate_encryptionkey = ksmbd_gen_smb30_encryptionkey,148 .is_transform_hdr = smb3_is_transform_hdr,149 .decrypt_req = smb3_decrypt_req,150 .encrypt_resp = smb3_encrypt_resp151};152 153static struct smb_version_ops smb3_11_server_ops = {154 .get_cmd_val = get_smb2_cmd_val,155 .init_rsp_hdr = init_smb2_rsp_hdr,156 .set_rsp_status = set_smb2_rsp_status,157 .allocate_rsp_buf = smb2_allocate_rsp_buf,158 .set_rsp_credits = smb2_set_rsp_credits,159 .check_user_session = smb2_check_user_session,160 .get_ksmbd_tcon = smb2_get_ksmbd_tcon,161 .is_sign_req = smb2_is_sign_req,162 .check_sign_req = smb3_check_sign_req,163 .set_sign_rsp = smb3_set_sign_rsp,164 .generate_signingkey = ksmbd_gen_smb311_signingkey,165 .generate_encryptionkey = ksmbd_gen_smb311_encryptionkey,166 .is_transform_hdr = smb3_is_transform_hdr,167 .decrypt_req = smb3_decrypt_req,168 .encrypt_resp = smb3_encrypt_resp169};170 171static struct smb_version_cmds smb2_0_server_cmds[NUMBER_OF_SMB2_COMMANDS] = {172 [SMB2_NEGOTIATE_HE] = { .proc = smb2_negotiate_request, },173 [SMB2_SESSION_SETUP_HE] = { .proc = smb2_sess_setup, },174 [SMB2_TREE_CONNECT_HE] = { .proc = smb2_tree_connect,},175 [SMB2_TREE_DISCONNECT_HE] = { .proc = smb2_tree_disconnect,},176 [SMB2_LOGOFF_HE] = { .proc = smb2_session_logoff,},177 [SMB2_CREATE_HE] = { .proc = smb2_open},178 [SMB2_QUERY_INFO_HE] = { .proc = smb2_query_info},179 [SMB2_QUERY_DIRECTORY_HE] = { .proc = smb2_query_dir},180 [SMB2_CLOSE_HE] = { .proc = smb2_close},181 [SMB2_ECHO_HE] = { .proc = smb2_echo},182 [SMB2_SET_INFO_HE] = { .proc = smb2_set_info},183 [SMB2_READ_HE] = { .proc = smb2_read},184 [SMB2_WRITE_HE] = { .proc = smb2_write},185 [SMB2_FLUSH_HE] = { .proc = smb2_flush},186 [SMB2_CANCEL_HE] = { .proc = smb2_cancel},187 [SMB2_LOCK_HE] = { .proc = smb2_lock},188 [SMB2_IOCTL_HE] = { .proc = smb2_ioctl},189 [SMB2_OPLOCK_BREAK_HE] = { .proc = smb2_oplock_break},190 [SMB2_CHANGE_NOTIFY_HE] = { .proc = smb2_notify},191};192 193/**194 * init_smb2_1_server() - initialize a smb server connection with smb2.1195 * command dispatcher196 * @conn: connection instance197 */198void init_smb2_1_server(struct ksmbd_conn *conn)199{200 conn->vals = &smb21_server_values;201 conn->ops = &smb2_0_server_ops;202 conn->cmds = smb2_0_server_cmds;203 conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);204 conn->signing_algorithm = SIGNING_ALG_HMAC_SHA256_LE;205 206 if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)207 conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;208}209 210/**211 * init_smb3_0_server() - initialize a smb server connection with smb3.0212 * command dispatcher213 * @conn: connection instance214 */215void init_smb3_0_server(struct ksmbd_conn *conn)216{217 conn->vals = &smb30_server_values;218 conn->ops = &smb3_0_server_ops;219 conn->cmds = smb2_0_server_cmds;220 conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);221 conn->signing_algorithm = SIGNING_ALG_AES_CMAC_LE;222 223 if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)224 conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING |225 SMB2_GLOBAL_CAP_DIRECTORY_LEASING;226 227 if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION &&228 conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION)229 conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;230 231 if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION ||232 (!(server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION_OFF) &&233 conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION))234 conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;235 236 if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL)237 conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL;238}239 240/**241 * init_smb3_02_server() - initialize a smb server connection with smb3.02242 * command dispatcher243 * @conn: connection instance244 */245void init_smb3_02_server(struct ksmbd_conn *conn)246{247 conn->vals = &smb302_server_values;248 conn->ops = &smb3_0_server_ops;249 conn->cmds = smb2_0_server_cmds;250 conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);251 conn->signing_algorithm = SIGNING_ALG_AES_CMAC_LE;252 253 if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)254 conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING |255 SMB2_GLOBAL_CAP_DIRECTORY_LEASING;256 257 if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION ||258 (!(server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION_OFF) &&259 conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION))260 conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;261 262 if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL)263 conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL;264 265 if (server_conf.flags & KSMBD_GLOBAL_FLAG_DURABLE_HANDLE)266 conn->vals->capabilities |= SMB2_GLOBAL_CAP_PERSISTENT_HANDLES;267}268 269/**270 * init_smb3_11_server() - initialize a smb server connection with smb3.11271 * command dispatcher272 * @conn: connection instance273 */274int init_smb3_11_server(struct ksmbd_conn *conn)275{276 conn->vals = &smb311_server_values;277 conn->ops = &smb3_11_server_ops;278 conn->cmds = smb2_0_server_cmds;279 conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);280 conn->signing_algorithm = SIGNING_ALG_AES_CMAC_LE;281 282 if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)283 conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING |284 SMB2_GLOBAL_CAP_DIRECTORY_LEASING;285 286 if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL)287 conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL;288 289 if (server_conf.flags & KSMBD_GLOBAL_FLAG_DURABLE_HANDLE)290 conn->vals->capabilities |= SMB2_GLOBAL_CAP_PERSISTENT_HANDLES;291 292 INIT_LIST_HEAD(&conn->preauth_sess_table);293 return 0;294}295 296void init_smb2_max_read_size(unsigned int sz)297{298 sz = clamp_val(sz, SMB3_MIN_IOSIZE, SMB3_MAX_IOSIZE);299 smb21_server_values.max_read_size = sz;300 smb30_server_values.max_read_size = sz;301 smb302_server_values.max_read_size = sz;302 smb311_server_values.max_read_size = sz;303}304 305void init_smb2_max_write_size(unsigned int sz)306{307 sz = clamp_val(sz, SMB3_MIN_IOSIZE, SMB3_MAX_IOSIZE);308 smb21_server_values.max_write_size = sz;309 smb30_server_values.max_write_size = sz;310 smb302_server_values.max_write_size = sz;311 smb311_server_values.max_write_size = sz;312}313 314void init_smb2_max_trans_size(unsigned int sz)315{316 sz = clamp_val(sz, SMB3_MIN_IOSIZE, SMB3_MAX_IOSIZE);317 smb21_server_values.max_trans_size = sz;318 smb30_server_values.max_trans_size = sz;319 smb302_server_values.max_trans_size = sz;320 smb311_server_values.max_trans_size = sz;321}322 323void init_smb2_max_credits(unsigned int sz)324{325 smb21_server_values.max_credits = sz;326 smb30_server_values.max_credits = sz;327 smb302_server_values.max_credits = sz;328 smb311_server_values.max_credits = sz;329}330