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