1a90cf9f2SGordon Ross /*
2a90cf9f2SGordon Ross * This file and its contents are supplied under the terms of the
3a90cf9f2SGordon Ross * Common Development and Distribution License ("CDDL"), version 1.0.
4a90cf9f2SGordon Ross * You may only use this file in accordance with the terms of version
5a90cf9f2SGordon Ross * 1.0 of the CDDL.
6a90cf9f2SGordon Ross *
7a90cf9f2SGordon Ross * A full copy of the text of the CDDL should have accompanied this
8a90cf9f2SGordon Ross * source. A copy of the CDDL is also available via the Internet at
9a90cf9f2SGordon Ross * http://www.illumos.org/license/CDDL.
10a90cf9f2SGordon Ross */
11a90cf9f2SGordon Ross
12a90cf9f2SGordon Ross /*
1393bc28dbSGordon Ross * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
14*4e065a9fSAlexander Stetsenko * Copyright 2020 RackTop Systems, Inc.
15a90cf9f2SGordon Ross */
16a90cf9f2SGordon Ross
17a90cf9f2SGordon Ross /*
18a90cf9f2SGordon Ross * Dispatch function for SMB2_SESSION_SETUP
19a90cf9f2SGordon Ross *
20a90cf9f2SGordon Ross * Note that the Capabilities supplied in this request are an inferior
21a90cf9f2SGordon Ross * subset of those given to us previously in the SMB2 Negotiate request.
22a90cf9f2SGordon Ross * We need to remember the full set of capabilities from SMB2 Negotiate,
23a90cf9f2SGordon Ross * and therefore ignore the subset of capabilities supplied here.
24a90cf9f2SGordon Ross */
25a90cf9f2SGordon Ross
26a90cf9f2SGordon Ross #include <smbsrv/smb2_kproto.h>
27a90cf9f2SGordon Ross
28a90cf9f2SGordon Ross static void smb2_ss_adjust_credits(smb_request_t *);
29a90cf9f2SGordon Ross
30a90cf9f2SGordon Ross smb_sdrc_t
smb2_session_setup(smb_request_t * sr)31a90cf9f2SGordon Ross smb2_session_setup(smb_request_t *sr)
32a90cf9f2SGordon Ross {
33a90cf9f2SGordon Ross smb_arg_sessionsetup_t *sinfo;
34a90cf9f2SGordon Ross uint16_t StructureSize;
35a90cf9f2SGordon Ross uint8_t Flags;
36a90cf9f2SGordon Ross uint8_t SecurityMode;
37a90cf9f2SGordon Ross uint32_t Capabilities; /* ignored - see above */
38a90cf9f2SGordon Ross uint32_t Channel;
39a90cf9f2SGordon Ross uint16_t SecBufOffset;
40a90cf9f2SGordon Ross uint16_t SecBufLength;
41811599a4SMatt Barden uint64_t PrevSsnId;
42a90cf9f2SGordon Ross uint16_t SessionFlags;
43a90cf9f2SGordon Ross uint32_t status;
44a90cf9f2SGordon Ross int skip;
45a90cf9f2SGordon Ross int rc = 0;
46a90cf9f2SGordon Ross
47a90cf9f2SGordon Ross sinfo = smb_srm_zalloc(sr, sizeof (smb_arg_sessionsetup_t));
48a90cf9f2SGordon Ross sr->sr_ssetup = sinfo;
49a90cf9f2SGordon Ross
50a90cf9f2SGordon Ross rc = smb_mbc_decodef(
51a90cf9f2SGordon Ross &sr->smb_data, "wbbllwwq",
52a90cf9f2SGordon Ross &StructureSize, /* w */
53a90cf9f2SGordon Ross &Flags, /* b */
54a90cf9f2SGordon Ross &SecurityMode, /* b */
55a90cf9f2SGordon Ross &Capabilities, /* l */
56a90cf9f2SGordon Ross &Channel, /* l */
57a90cf9f2SGordon Ross &SecBufOffset, /* w */
58a90cf9f2SGordon Ross &SecBufLength, /* w */
59811599a4SMatt Barden &PrevSsnId); /* q */
60a90cf9f2SGordon Ross if (rc)
61a90cf9f2SGordon Ross return (SDRC_ERROR);
62a90cf9f2SGordon Ross
63a90cf9f2SGordon Ross /*
64a90cf9f2SGordon Ross * We're normally positioned at the security buffer now,
65a90cf9f2SGordon Ross * but there could be some padding before it.
66a90cf9f2SGordon Ross */
67a90cf9f2SGordon Ross skip = (SecBufOffset + sr->smb2_cmd_hdr) -
68a90cf9f2SGordon Ross sr->smb_data.chain_offset;
69a90cf9f2SGordon Ross if (skip < 0)
70a90cf9f2SGordon Ross return (SDRC_ERROR);
71a90cf9f2SGordon Ross if (skip > 0)
72a90cf9f2SGordon Ross (void) smb_mbc_decodef(&sr->smb_data, "#.", skip);
73a90cf9f2SGordon Ross
74a90cf9f2SGordon Ross /*
75a90cf9f2SGordon Ross * Get the security buffer
76a90cf9f2SGordon Ross */
77a90cf9f2SGordon Ross sinfo->ssi_iseclen = SecBufLength;
78a90cf9f2SGordon Ross sinfo->ssi_isecblob = smb_srm_zalloc(sr, sinfo->ssi_iseclen);
79a90cf9f2SGordon Ross rc = smb_mbc_decodef(&sr->smb_data, "#c",
80a90cf9f2SGordon Ross sinfo->ssi_iseclen, sinfo->ssi_isecblob);
81a90cf9f2SGordon Ross if (rc)
82a90cf9f2SGordon Ross return (SDRC_ERROR);
83a90cf9f2SGordon Ross
84a90cf9f2SGordon Ross /*
8593bc28dbSGordon Ross * Decoded everything. Dtrace probe,
8693bc28dbSGordon Ross * then no more early returns.
8793bc28dbSGordon Ross */
8893bc28dbSGordon Ross DTRACE_SMB2_START(op__SessionSetup, smb_request_t *, sr);
8993bc28dbSGordon Ross
9093bc28dbSGordon Ross /*
911160dcf7SMatt Barden * [MS-SMB2] 3.3.5.5 Receiving an SMB2 SESSION_SETUP Request
921160dcf7SMatt Barden *
931160dcf7SMatt Barden * If we support 3.x, RejectUnencryptedAccess is TRUE,
941160dcf7SMatt Barden * global EncryptData is TRUE, but we're not talking
951160dcf7SMatt Barden * 3.x or the client doesn't support encryption,
961160dcf7SMatt Barden * return ACCESS_DENIED.
971160dcf7SMatt Barden *
981160dcf7SMatt Barden * If RejectUnencryptedAccess is TRUE, we force max_protocol
991160dcf7SMatt Barden * to at least 3.0.
1001160dcf7SMatt Barden */
1011160dcf7SMatt Barden if (sr->sr_server->sv_cfg.skc_encrypt == SMB_CONFIG_REQUIRED &&
1021160dcf7SMatt Barden (sr->session->dialect < SMB_VERS_3_0 ||
1031160dcf7SMatt Barden !SMB3_CLIENT_ENCRYPTS(sr))) {
1041160dcf7SMatt Barden status = NT_STATUS_ACCESS_DENIED;
1051160dcf7SMatt Barden goto errout;
1061160dcf7SMatt Barden }
1071160dcf7SMatt Barden
1081160dcf7SMatt Barden /*
1091160dcf7SMatt Barden * SMB3 multi-channel features are not supported.
1101160dcf7SMatt Barden * Once they are, this will check the dialect and
1111160dcf7SMatt Barden * whether multi-channel was negotiated, i.e.
1121160dcf7SMatt Barden * if (sr->session->dialect < SMB_VERS_3_0 ||
1131160dcf7SMatt Barden * s->IsMultiChannelCapable == False)
1141160dcf7SMatt Barden * return (error...)
1151160dcf7SMatt Barden */
1161160dcf7SMatt Barden if (Flags & SMB2_SESSION_FLAG_BINDING) {
1171160dcf7SMatt Barden status = NT_STATUS_REQUEST_NOT_ACCEPTED;
1181160dcf7SMatt Barden goto errout;
1191160dcf7SMatt Barden }
1201160dcf7SMatt Barden
1211160dcf7SMatt Barden /*
122a90cf9f2SGordon Ross * The real auth. work happens in here.
123a90cf9f2SGordon Ross */
124a90cf9f2SGordon Ross status = smb_authenticate_ext(sr);
125a90cf9f2SGordon Ross
126a90cf9f2SGordon Ross SecBufOffset = SMB2_HDR_SIZE + 8;
127a90cf9f2SGordon Ross SecBufLength = sinfo->ssi_oseclen;
128a90cf9f2SGordon Ross SessionFlags = 0;
129a90cf9f2SGordon Ross
130a90cf9f2SGordon Ross switch (status) {
131a90cf9f2SGordon Ross
132a90cf9f2SGordon Ross case NT_STATUS_SUCCESS: /* Authenticated */
1331160dcf7SMatt Barden if ((sr->uid_user->u_flags & SMB_USER_FLAG_GUEST) != 0)
134a90cf9f2SGordon Ross SessionFlags |= SMB2_SESSION_FLAG_IS_GUEST;
1351160dcf7SMatt Barden if ((sr->uid_user->u_flags & SMB_USER_FLAG_ANON) != 0)
136a90cf9f2SGordon Ross SessionFlags |= SMB2_SESSION_FLAG_IS_NULL;
1371160dcf7SMatt Barden if (sr->uid_user->u_encrypt != SMB_CONFIG_DISABLED)
1381160dcf7SMatt Barden SessionFlags |= SMB2_SESSION_FLAG_ENCRYPT_DATA;
139a90cf9f2SGordon Ross smb2_ss_adjust_credits(sr);
140811599a4SMatt Barden
141811599a4SMatt Barden /*
142811599a4SMatt Barden * PrevSsnId is a session that the client is reporting as
143811599a4SMatt Barden * having gone away, and for which we might not yet have seen
144811599a4SMatt Barden * a disconnect. We need to log off the previous session so
145811599a4SMatt Barden * any durable handles in that session will become orphans
146811599a4SMatt Barden * that can be reclaimed in this new session. Note that
147811599a4SMatt Barden * either zero or the _current_ session ID means there is
148811599a4SMatt Barden * no previous session to logoff.
149811599a4SMatt Barden */
150811599a4SMatt Barden if (PrevSsnId != 0 &&
151811599a4SMatt Barden PrevSsnId != sr->smb2_ssnid)
152811599a4SMatt Barden smb_server_logoff_ssnid(sr, PrevSsnId);
153a90cf9f2SGordon Ross break;
154a90cf9f2SGordon Ross
155a90cf9f2SGordon Ross /*
156a90cf9f2SGordon Ross * This is not really an error, but tells the client
157a90cf9f2SGordon Ross * it should send another session setup request.
158a90cf9f2SGordon Ross * Not smb2_put_error because we send a payload.
159a90cf9f2SGordon Ross */
160a90cf9f2SGordon Ross case NT_STATUS_MORE_PROCESSING_REQUIRED:
161a90cf9f2SGordon Ross sr->smb2_status = status;
162a90cf9f2SGordon Ross break;
163a90cf9f2SGordon Ross
164a90cf9f2SGordon Ross default:
165c51c88bdSMatt Barden errout:
166a90cf9f2SGordon Ross SecBufLength = 0;
167a90cf9f2SGordon Ross sr->smb2_status = status;
168a90cf9f2SGordon Ross break;
169a90cf9f2SGordon Ross }
170a90cf9f2SGordon Ross
17193bc28dbSGordon Ross /* sr->smb2_status set above */
17293bc28dbSGordon Ross DTRACE_SMB2_DONE(op__SessionSetup, smb_request_t *, sr);
17393bc28dbSGordon Ross
174a90cf9f2SGordon Ross /*
175a90cf9f2SGordon Ross * SMB2 Session Setup reply
176a90cf9f2SGordon Ross */
177a90cf9f2SGordon Ross
178a90cf9f2SGordon Ross rc = smb_mbc_encodef(
179a90cf9f2SGordon Ross &sr->reply,
180a90cf9f2SGordon Ross "wwww#c",
181a90cf9f2SGordon Ross 9, /* StructSize */ /* w */
182a90cf9f2SGordon Ross SessionFlags, /* w */
183a90cf9f2SGordon Ross SecBufOffset, /* w */
184a90cf9f2SGordon Ross SecBufLength, /* w */
185a90cf9f2SGordon Ross SecBufLength, /* # */
186a90cf9f2SGordon Ross sinfo->ssi_osecblob); /* c */
187a90cf9f2SGordon Ross if (rc)
18893bc28dbSGordon Ross sr->smb2_status = NT_STATUS_INTERNAL_ERROR;
189a90cf9f2SGordon Ross
190a90cf9f2SGordon Ross return (SDRC_SUCCESS);
191a90cf9f2SGordon Ross }
192a90cf9f2SGordon Ross
193a90cf9f2SGordon Ross /*
194a90cf9f2SGordon Ross * After a successful authentication, raise s_max_credits up to the
195a90cf9f2SGordon Ross * normal maximum that clients are allowed to request. Also, if we
196a90cf9f2SGordon Ross * haven't yet given them their initial credits, do that now.
197a90cf9f2SGordon Ross *
198a90cf9f2SGordon Ross * Normally, clients will request some credits with session setup,
199a90cf9f2SGordon Ross * but in case they don't request enough to raise s_cur_credits
200a90cf9f2SGordon Ross * up to the configured initial_credits, increase the requested
201a90cf9f2SGordon Ross * credits of this SR sufficiently to make that happen. The actual
202a90cf9f2SGordon Ross * increase happens in the dispatch code after we return.
203a90cf9f2SGordon Ross */
204a90cf9f2SGordon Ross static void
smb2_ss_adjust_credits(smb_request_t * sr)205a90cf9f2SGordon Ross smb2_ss_adjust_credits(smb_request_t *sr)
206a90cf9f2SGordon Ross {
207a90cf9f2SGordon Ross smb_session_t *s = sr->session;
208a90cf9f2SGordon Ross
209a90cf9f2SGordon Ross mutex_enter(&s->s_credits_mutex);
210a90cf9f2SGordon Ross s->s_max_credits = s->s_cfg.skc_maximum_credits;
211a90cf9f2SGordon Ross
212a90cf9f2SGordon Ross if (s->s_cur_credits < s->s_cfg.skc_initial_credits) {
213a90cf9f2SGordon Ross uint16_t grant;
214a90cf9f2SGordon Ross
215a90cf9f2SGordon Ross /* How many credits we want to grant with this SR. */
216a90cf9f2SGordon Ross grant = s->s_cfg.skc_initial_credits - s->s_cur_credits;
217a90cf9f2SGordon Ross
218a90cf9f2SGordon Ross /*
219a90cf9f2SGordon Ross * Do we need to increase the smb2_credit_request?
220a90cf9f2SGordon Ross * One might prefer to read this expression as:
221a90cf9f2SGordon Ross * ((credit_request - credit_charge) < grant)
222a90cf9f2SGordon Ross * but we know credit_charge == 1 and would rather not
223a90cf9f2SGordon Ross * deal with a possibly negative value on the left,
224a90cf9f2SGordon Ross * so adding credit_charge to both sides...
225a90cf9f2SGordon Ross */
226a90cf9f2SGordon Ross if (sr->smb2_credit_request < (grant + 1)) {
227a90cf9f2SGordon Ross sr->smb2_credit_request = (grant + 1);
228a90cf9f2SGordon Ross }
229a90cf9f2SGordon Ross }
230a90cf9f2SGordon Ross
231a90cf9f2SGordon Ross mutex_exit(&s->s_credits_mutex);
232a90cf9f2SGordon Ross }
233