Commit | Line | Data |
---|---|---|
e2f34481 NJ |
1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* | |
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" | |
e2f34481 NJ |
9 | |
10 | #include "auth.h" | |
11 | #include "connection.h" | |
12 | #include "smb_common.h" | |
13 | #include "server.h" | |
e2f34481 NJ |
14 | |
15 | static 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, | |
004443b3 | 22 | .max_credits = SMB2_MAX_CREDITS, |
e2f34481 NJ |
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) - 1, | |
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 | ||
41 | static 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, | |
004443b3 | 48 | .max_credits = SMB2_MAX_CREDITS, |
e2f34481 NJ |
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) - 1, | |
56 | .lock_cmd = SMB2_LOCK, | |
57 | .cap_unix = 0, | |
58 | .cap_nt_find = SMB2_NT_FIND, | |
59 | .cap_large_files = SMB2_LARGE_FILES, | |
ade62d8b | 60 | .create_lease_size = sizeof(struct create_lease_v2), |
e2f34481 NJ |
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 | ||
68 | static 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, | |
004443b3 | 75 | .max_credits = SMB2_MAX_CREDITS, |
e2f34481 NJ |
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) - 1, | |
83 | .lock_cmd = SMB2_LOCK, | |
84 | .cap_unix = 0, | |
85 | .cap_nt_find = SMB2_NT_FIND, | |
86 | .cap_large_files = SMB2_LARGE_FILES, | |
ade62d8b | 87 | .create_lease_size = sizeof(struct create_lease_v2), |
e2f34481 NJ |
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 | ||
95 | static 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, | |
004443b3 | 102 | .max_credits = SMB2_MAX_CREDITS, |
e2f34481 NJ |
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) - 1, | |
110 | .lock_cmd = SMB2_LOCK, | |
111 | .cap_unix = 0, | |
112 | .cap_nt_find = SMB2_NT_FIND, | |
113 | .cap_large_files = SMB2_LARGE_FILES, | |
ade62d8b | 114 | .create_lease_size = sizeof(struct create_lease_v2), |
e2f34481 NJ |
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 | ||
122 | static 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_rsp | |
133 | }; | |
134 | ||
135 | static 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_resp | |
151 | }; | |
152 | ||
153 | static 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_resp | |
169 | }; | |
170 | ||
171 | static 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 | ||
e2f34481 NJ |
193 | /** |
194 | * init_smb2_1_server() - initialize a smb server connection with smb2.1 | |
195 | * command dispatcher | |
196 | * @conn: connection instance | |
197 | */ | |
198 | void 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); | |
d6c9ad23 | 204 | conn->signing_algorithm = SIGNING_ALG_HMAC_SHA256_LE; |
e2f34481 NJ |
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.0 | |
212 | * command dispatcher | |
213 | * @conn: connection instance | |
214 | */ | |
215 | void 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); | |
d6c9ad23 | 221 | conn->signing_algorithm = SIGNING_ALG_AES_CMAC_LE; |
e2f34481 NJ |
222 | |
223 | if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES) | |
224 | conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING; | |
225 | ||
226 | if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION && | |
d7e5852b | 227 | conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION) |
e2f34481 | 228 | conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION; |
f5a544e3 NJ |
229 | |
230 | if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) | |
231 | conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL; | |
e2f34481 NJ |
232 | } |
233 | ||
234 | /** | |
235 | * init_smb3_02_server() - initialize a smb server connection with smb3.02 | |
236 | * command dispatcher | |
237 | * @conn: connection instance | |
238 | */ | |
239 | void init_smb3_02_server(struct ksmbd_conn *conn) | |
240 | { | |
241 | conn->vals = &smb302_server_values; | |
242 | conn->ops = &smb3_0_server_ops; | |
243 | conn->cmds = smb2_0_server_cmds; | |
244 | conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds); | |
d6c9ad23 | 245 | conn->signing_algorithm = SIGNING_ALG_AES_CMAC_LE; |
e2f34481 NJ |
246 | |
247 | if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES) | |
248 | conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING; | |
249 | ||
250 | if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION && | |
64b39f4a | 251 | conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION) |
e2f34481 | 252 | conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION; |
f5a544e3 NJ |
253 | |
254 | if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) | |
255 | conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL; | |
e2f34481 NJ |
256 | } |
257 | ||
258 | /** | |
259 | * init_smb3_11_server() - initialize a smb server connection with smb3.11 | |
260 | * command dispatcher | |
261 | * @conn: connection instance | |
262 | */ | |
263 | int init_smb3_11_server(struct ksmbd_conn *conn) | |
264 | { | |
265 | conn->vals = &smb311_server_values; | |
266 | conn->ops = &smb3_11_server_ops; | |
267 | conn->cmds = smb2_0_server_cmds; | |
268 | conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds); | |
d6c9ad23 | 269 | conn->signing_algorithm = SIGNING_ALG_AES_CMAC_LE; |
e2f34481 NJ |
270 | |
271 | if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES) | |
272 | conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING; | |
273 | ||
f5a544e3 NJ |
274 | if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) |
275 | conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL; | |
276 | ||
e2f34481 NJ |
277 | INIT_LIST_HEAD(&conn->preauth_sess_table); |
278 | return 0; | |
279 | } | |
280 | ||
281 | void init_smb2_max_read_size(unsigned int sz) | |
282 | { | |
4bc59477 | 283 | sz = clamp_val(sz, SMB3_MIN_IOSIZE, SMB3_MAX_IOSIZE); |
e2f34481 NJ |
284 | smb21_server_values.max_read_size = sz; |
285 | smb30_server_values.max_read_size = sz; | |
286 | smb302_server_values.max_read_size = sz; | |
287 | smb311_server_values.max_read_size = sz; | |
288 | } | |
289 | ||
290 | void init_smb2_max_write_size(unsigned int sz) | |
291 | { | |
4bc59477 | 292 | sz = clamp_val(sz, SMB3_MIN_IOSIZE, SMB3_MAX_IOSIZE); |
e2f34481 NJ |
293 | smb21_server_values.max_write_size = sz; |
294 | smb30_server_values.max_write_size = sz; | |
295 | smb302_server_values.max_write_size = sz; | |
296 | smb311_server_values.max_write_size = sz; | |
297 | } | |
298 | ||
299 | void init_smb2_max_trans_size(unsigned int sz) | |
300 | { | |
4bc59477 | 301 | sz = clamp_val(sz, SMB3_MIN_IOSIZE, SMB3_MAX_IOSIZE); |
e2f34481 NJ |
302 | smb21_server_values.max_trans_size = sz; |
303 | smb30_server_values.max_trans_size = sz; | |
304 | smb302_server_values.max_trans_size = sz; | |
305 | smb311_server_values.max_trans_size = sz; | |
306 | } | |
004443b3 NJ |
307 | |
308 | void init_smb2_max_credits(unsigned int sz) | |
309 | { | |
310 | smb21_server_values.max_credits = sz; | |
311 | smb30_server_values.max_credits = sz; | |
312 | smb302_server_values.max_credits = sz; | |
313 | smb311_server_values.max_credits = sz; | |
314 | } |