1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
14 */
15
16 /*
17 * Dispatch function for SMB2_SESSION_SETUP
18 *
19 * Note that the Capabilities supplied in this request are an inferior
20 * subset of those given to us previously in the SMB2 Negotiate request.
21 * We need to remember the full set of capabilities from SMB2 Negotiate,
22 * and therefore ignore the subset of capabilities supplied here.
23 */
24
25 #include <smbsrv/smb2_kproto.h>
26
27 static void smb2_ss_adjust_credits(smb_request_t *);
28
29 smb_sdrc_t
30 smb2_session_setup(smb_request_t *sr)
31 {
32 smb_arg_sessionsetup_t *sinfo;
33 uint16_t StructureSize;
34 uint8_t Flags;
35 uint8_t SecurityMode;
36 uint32_t Capabilities; /* ignored - see above */
37 uint32_t Channel;
38 uint16_t SecBufOffset;
39 uint16_t SecBufLength;
40 uint64_t PrevSessionId;
41 uint16_t SessionFlags;
42 uint32_t status;
43 int skip;
44 int rc = 0;
45
46 sinfo = smb_srm_zalloc(sr, sizeof (smb_arg_sessionsetup_t));
47 sr->sr_ssetup = sinfo;
48
49 rc = smb_mbc_decodef(
50 &sr->smb_data, "wbbllwwq",
51 &StructureSize, /* w */
52 &Flags, /* b */
53 &SecurityMode, /* b */
54 &Capabilities, /* l */
55 &Channel, /* l */
56 &SecBufOffset, /* w */
57 &SecBufLength, /* w */
58 &PrevSessionId); /* q */
59 if (rc)
60 return (SDRC_ERROR);
61
62 /*
63 * We're normally positioned at the security buffer now,
64 * but there could be some padding before it.
65 */
66 skip = (SecBufOffset + sr->smb2_cmd_hdr) -
67 sr->smb_data.chain_offset;
68 if (skip < 0)
69 return (SDRC_ERROR);
70 if (skip > 0)
71 (void) smb_mbc_decodef(&sr->smb_data, "#.", skip);
72
73 /*
74 * Get the security buffer
75 */
76 sinfo->ssi_iseclen = SecBufLength;
77 sinfo->ssi_isecblob = smb_srm_zalloc(sr, sinfo->ssi_iseclen);
78 rc = smb_mbc_decodef(&sr->smb_data, "#c",
79 sinfo->ssi_iseclen, sinfo->ssi_isecblob);
80 if (rc)
81 return (SDRC_ERROR);
82
83 /*
84 * The real auth. work happens in here.
85 */
86 status = smb_authenticate_ext(sr);
87
88 SecBufOffset = SMB2_HDR_SIZE + 8;
89 SecBufLength = sinfo->ssi_oseclen;
90 SessionFlags = 0;
91
92 switch (status) {
93
94 case NT_STATUS_SUCCESS: /* Authenticated */
95 if (sr->uid_user->u_flags & SMB_USER_FLAG_GUEST)
96 SessionFlags |= SMB2_SESSION_FLAG_IS_GUEST;
97 if (sr->uid_user->u_flags & SMB_USER_FLAG_ANON)
98 SessionFlags |= SMB2_SESSION_FLAG_IS_NULL;
99 smb2_ss_adjust_credits(sr);
100 break;
101
102 /*
103 * This is not really an error, but tells the client
104 * it should send another session setup request.
105 * Not smb2_put_error because we send a payload.
106 */
107 case NT_STATUS_MORE_PROCESSING_REQUIRED:
108 sr->smb2_status = status;
109 break;
110
111 default:
112 SecBufLength = 0;
113 sr->smb2_status = status;
114 break;
115 }
116
117 /*
118 * SMB2 Session Setup reply
119 */
120
121 rc = smb_mbc_encodef(
122 &sr->reply,
123 "wwww#c",
124 9, /* StructSize */ /* w */
125 SessionFlags, /* w */
126 SecBufOffset, /* w */
127 SecBufLength, /* w */
128 SecBufLength, /* # */
129 sinfo->ssi_osecblob); /* c */
130 if (rc)
131 return (SDRC_ERROR);
132
133 return (SDRC_SUCCESS);
134 }
135
136 /*
137 * After a successful authentication, raise s_max_credits up to the
138 * normal maximum that clients are allowed to request. Also, if we
139 * haven't yet given them their initial credits, do that now.
140 *
141 * Normally, clients will request some credits with session setup,
142 * but in case they don't request enough to raise s_cur_credits
143 * up to the configured initial_credits, increase the requested
144 * credits of this SR sufficiently to make that happen. The actual
145 * increase happens in the dispatch code after we return.
146 */
147 static void
148 smb2_ss_adjust_credits(smb_request_t *sr)
149 {
150 smb_session_t *s = sr->session;
151
|
1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
14 */
15
16 /*
17 * Dispatch function for SMB2_SESSION_SETUP
18 *
19 * Note that the Capabilities supplied in this request are an inferior
20 * subset of those given to us previously in the SMB2 Negotiate request.
21 * We need to remember the full set of capabilities from SMB2 Negotiate,
22 * and therefore ignore the subset of capabilities supplied here.
23 */
24
25 #include <smbsrv/smb2_kproto.h>
26
27 static void smb2_ss_adjust_credits(smb_request_t *);
28
29 smb_sdrc_t
30 smb2_session_setup(smb_request_t *sr)
31 {
32 smb_arg_sessionsetup_t *sinfo;
33 smb_user_t *prev_user;
34 uint16_t StructureSize;
35 uint8_t Flags;
36 uint8_t SecurityMode;
37 uint32_t Capabilities; /* ignored - see above */
38 uint32_t Channel;
39 uint16_t SecBufOffset;
40 uint16_t SecBufLength;
41 uint64_t PrevSsnId;
42 uint16_t SessionFlags;
43 uint32_t status;
44 int skip;
45 int rc = 0;
46
47 sinfo = smb_srm_zalloc(sr, sizeof (smb_arg_sessionsetup_t));
48 sr->sr_ssetup = sinfo;
49
50 rc = smb_mbc_decodef(
51 &sr->smb_data, "wbbllwwq",
52 &StructureSize, /* w */
53 &Flags, /* b */
54 &SecurityMode, /* b */
55 &Capabilities, /* l */
56 &Channel, /* l */
57 &SecBufOffset, /* w */
58 &SecBufLength, /* w */
59 &PrevSsnId); /* q */
60 if (rc)
61 return (SDRC_ERROR);
62
63 /*
64 * We're normally positioned at the security buffer now,
65 * but there could be some padding before it.
66 */
67 skip = (SecBufOffset + sr->smb2_cmd_hdr) -
68 sr->smb_data.chain_offset;
69 if (skip < 0)
70 return (SDRC_ERROR);
71 if (skip > 0)
72 (void) smb_mbc_decodef(&sr->smb_data, "#.", skip);
73
74 /*
75 * Get the security buffer
76 */
77 sinfo->ssi_iseclen = SecBufLength;
78 sinfo->ssi_isecblob = smb_srm_zalloc(sr, sinfo->ssi_iseclen);
79 rc = smb_mbc_decodef(&sr->smb_data, "#c",
80 sinfo->ssi_iseclen, sinfo->ssi_isecblob);
81 if (rc)
82 return (SDRC_ERROR);
83
84 /*
85 * Decoded everything. Dtrace probe,
86 * then no more early returns.
87 */
88 DTRACE_SMB2_START(op__SessionSetup, smb_request_t *, sr);
89
90 /*
91 * [MS-SMB2] 3.3.5.5 Receiving an SMB2 SESSION_SETUP Request
92 *
93 * If we support 3.x, RejectUnencryptedAccess is TRUE,
94 * global EncryptData is TRUE, but we're not talking
95 * 3.x or the client doesn't support encryption,
96 * return ACCESS_DENIED.
97 *
98 * If RejectUnencryptedAccess is TRUE, we force max_protocol
99 * to at least 3.0.
100 */
101 if (sr->sr_server->sv_cfg.skc_encrypt == SMB_CONFIG_REQUIRED &&
102 (sr->session->dialect < SMB_VERS_3_0 ||
103 !SMB3_CLIENT_ENCRYPTS(sr))) {
104 status = NT_STATUS_ACCESS_DENIED;
105 goto errout;
106 }
107
108 /*
109 * SMB3 multi-channel features are not supported.
110 * Once they are, this will check the dialect and
111 * whether multi-channel was negotiated, i.e.
112 * if (sr->session->dialect < SMB_VERS_3_0 ||
113 * s->IsMultiChannelCapable == False)
114 * return (error...)
115 */
116 if (Flags & SMB2_SESSION_FLAG_BINDING) {
117 status = NT_STATUS_REQUEST_NOT_ACCEPTED;
118 goto errout;
119 }
120
121 /*
122 * The real auth. work happens in here.
123 */
124 status = smb_authenticate_ext(sr);
125
126 SecBufOffset = SMB2_HDR_SIZE + 8;
127 SecBufLength = sinfo->ssi_oseclen;
128 SessionFlags = 0;
129
130 switch (status) {
131
132 case NT_STATUS_SUCCESS: /* Authenticated */
133 if ((sr->uid_user->u_flags & SMB_USER_FLAG_GUEST) != 0)
134 SessionFlags |= SMB2_SESSION_FLAG_IS_GUEST;
135 if ((sr->uid_user->u_flags & SMB_USER_FLAG_ANON) != 0)
136 SessionFlags |= SMB2_SESSION_FLAG_IS_NULL;
137 if (sr->uid_user->u_encrypt != SMB_CONFIG_DISABLED)
138 SessionFlags |= SMB2_SESSION_FLAG_ENCRYPT_DATA;
139 smb2_ss_adjust_credits(sr);
140
141 /*
142 * PrevSsnId is a session that the client is reporting as
143 * having gone away, and for which we might not yet have seen
144 * a disconnect. Find the session and log it off as if we had
145 * received a disconnect. Note that the client is allowed to
146 * set PrevSsnID to the _current_ SessionID, so skip the lookup
147 * in that case. Only allow this session logoff if we owned it.
148 */
149 if (PrevSsnId == 0 ||
150 PrevSsnId == sr->smb2_ssnid)
151 break;
152 prev_user = smb_server_lookup_ssnid(sr->sr_server, PrevSsnId);
153 if (prev_user != NULL) {
154 if (smb_is_same_user(prev_user->u_cred, sr->user_cr)) {
155 /* Treat this as if we lost the connection */
156 prev_user->preserve_opens =
157 SMB2_DH_PRESERVE_SOME;
158 smb_user_logoff(prev_user);
159 }
160 smb_user_release(prev_user); /* from lookup */
161 }
162 break;
163
164 /*
165 * This is not really an error, but tells the client
166 * it should send another session setup request.
167 * Not smb2_put_error because we send a payload.
168 */
169 case NT_STATUS_MORE_PROCESSING_REQUIRED:
170 sr->smb2_status = status;
171 break;
172
173 default:
174 errout:
175 SecBufLength = 0;
176 sr->smb2_status = status;
177 break;
178 }
179
180 /* sr->smb2_status set above */
181 DTRACE_SMB2_DONE(op__SessionSetup, smb_request_t *, sr);
182
183 /*
184 * SMB2 Session Setup reply
185 */
186
187 rc = smb_mbc_encodef(
188 &sr->reply,
189 "wwww#c",
190 9, /* StructSize */ /* w */
191 SessionFlags, /* w */
192 SecBufOffset, /* w */
193 SecBufLength, /* w */
194 SecBufLength, /* # */
195 sinfo->ssi_osecblob); /* c */
196 if (rc)
197 sr->smb2_status = NT_STATUS_INTERNAL_ERROR;
198
199 return (SDRC_SUCCESS);
200 }
201
202 /*
203 * After a successful authentication, raise s_max_credits up to the
204 * normal maximum that clients are allowed to request. Also, if we
205 * haven't yet given them their initial credits, do that now.
206 *
207 * Normally, clients will request some credits with session setup,
208 * but in case they don't request enough to raise s_cur_credits
209 * up to the configured initial_credits, increase the requested
210 * credits of this SR sufficiently to make that happen. The actual
211 * increase happens in the dispatch code after we return.
212 */
213 static void
214 smb2_ss_adjust_credits(smb_request_t *sr)
215 {
216 smb_session_t *s = sr->session;
217
|