Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Core SMB2 server
4 :
5 : Copyright (C) Stefan Metzmacher 2009
6 : Copyright (C) Jeremy Allison 2010
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "includes.h"
23 : #include "smbd/smbd.h"
24 : #include "smbd/globals.h"
25 : #include "../libcli/smb/smb_common.h"
26 : #include "../auth/gensec/gensec.h"
27 : #include "auth.h"
28 : #include "../lib/tsocket/tsocket.h"
29 : #include "../libcli/security/security.h"
30 : #include "../lib/util/tevent_ntstatus.h"
31 : #include "source3/lib/substitute.h"
32 :
33 : #include "lib/crypto/gnutls_helpers.h"
34 : #include <gnutls/gnutls.h>
35 : #include <gnutls/crypto.h>
36 :
37 : #undef DBGC_CLASS
38 : #define DBGC_CLASS DBGC_SMB2
39 :
40 : static struct tevent_req *smbd_smb2_session_setup_wrap_send(TALLOC_CTX *mem_ctx,
41 : struct tevent_context *ev,
42 : struct smbd_smb2_request *smb2req,
43 : uint64_t in_session_id,
44 : uint8_t in_flags,
45 : uint8_t in_security_mode,
46 : uint64_t in_previous_session_id,
47 : DATA_BLOB in_security_buffer);
48 : static NTSTATUS smbd_smb2_session_setup_wrap_recv(struct tevent_req *req,
49 : uint16_t *out_session_flags,
50 : TALLOC_CTX *mem_ctx,
51 : DATA_BLOB *out_security_buffer,
52 : uint64_t *out_session_id);
53 :
54 : static void smbd_smb2_request_sesssetup_done(struct tevent_req *subreq);
55 :
56 47286 : NTSTATUS smbd_smb2_request_process_sesssetup(struct smbd_smb2_request *smb2req)
57 : {
58 1110 : const uint8_t *inhdr;
59 1110 : const uint8_t *inbody;
60 1110 : uint64_t in_session_id;
61 1110 : uint8_t in_flags;
62 1110 : uint8_t in_security_mode;
63 1110 : uint64_t in_previous_session_id;
64 1110 : uint16_t in_security_offset;
65 1110 : uint16_t in_security_length;
66 1110 : DATA_BLOB in_security_buffer;
67 1110 : NTSTATUS status;
68 1110 : struct tevent_req *subreq;
69 :
70 47286 : status = smbd_smb2_request_verify_sizes(smb2req, 0x19);
71 47286 : if (!NT_STATUS_IS_OK(status)) {
72 0 : return smbd_smb2_request_error(smb2req, status);
73 : }
74 47286 : inhdr = SMBD_SMB2_IN_HDR_PTR(smb2req);
75 47286 : inbody = SMBD_SMB2_IN_BODY_PTR(smb2req);
76 :
77 47286 : in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
78 :
79 47286 : in_flags = CVAL(inbody, 0x02);
80 47286 : in_security_mode = CVAL(inbody, 0x03);
81 : /* Capabilities = IVAL(inbody, 0x04) */
82 : /* Channel = IVAL(inbody, 0x08) */
83 47286 : in_security_offset = SVAL(inbody, 0x0C);
84 47286 : in_security_length = SVAL(inbody, 0x0E);
85 47286 : in_previous_session_id = BVAL(inbody, 0x10);
86 :
87 47286 : if (in_security_offset != (SMB2_HDR_BODY + SMBD_SMB2_IN_BODY_LEN(smb2req))) {
88 0 : return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
89 : }
90 :
91 47286 : if (in_security_length > SMBD_SMB2_IN_DYN_LEN(smb2req)) {
92 0 : return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
93 : }
94 :
95 47286 : in_security_buffer.data = SMBD_SMB2_IN_DYN_PTR(smb2req);
96 47286 : in_security_buffer.length = in_security_length;
97 :
98 48396 : subreq = smbd_smb2_session_setup_wrap_send(smb2req,
99 47286 : smb2req->sconn->ev_ctx,
100 : smb2req,
101 : in_session_id,
102 : in_flags,
103 : in_security_mode,
104 : in_previous_session_id,
105 : in_security_buffer);
106 47286 : if (subreq == NULL) {
107 0 : return smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
108 : }
109 47286 : tevent_req_set_callback(subreq, smbd_smb2_request_sesssetup_done, smb2req);
110 :
111 : /*
112 : * Avoid sending a STATUS_PENDING message, which
113 : * matches a Windows Server and avoids problems with
114 : * MacOS clients.
115 : *
116 : * Even after 90 seconds a Windows Server doesn't return
117 : * STATUS_PENDING if using NTLMSSP against a non reachable
118 : * trusted domain.
119 : */
120 47286 : return smbd_smb2_request_pending_queue(smb2req, subreq, 0);
121 : }
122 :
123 47286 : static void smbd_smb2_request_sesssetup_done(struct tevent_req *subreq)
124 : {
125 1110 : struct smbd_smb2_request *smb2req =
126 47286 : tevent_req_callback_data(subreq,
127 : struct smbd_smb2_request);
128 1110 : uint8_t *outhdr;
129 1110 : DATA_BLOB outbody;
130 1110 : DATA_BLOB outdyn;
131 47286 : uint16_t out_session_flags = 0;
132 47286 : uint64_t out_session_id = 0;
133 1110 : uint16_t out_security_offset;
134 47286 : DATA_BLOB out_security_buffer = data_blob_null;
135 1110 : NTSTATUS status;
136 1110 : NTSTATUS error; /* transport error */
137 :
138 47286 : status = smbd_smb2_session_setup_wrap_recv(subreq,
139 : &out_session_flags,
140 : smb2req,
141 : &out_security_buffer,
142 : &out_session_id);
143 47286 : TALLOC_FREE(subreq);
144 47286 : if (!NT_STATUS_IS_OK(status) &&
145 22550 : !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
146 3912 : status = nt_status_squash(status);
147 3912 : error = smbd_smb2_request_error(smb2req, status);
148 3912 : if (!NT_STATUS_IS_OK(error)) {
149 0 : smbd_server_connection_terminate(smb2req->xconn,
150 : nt_errstr(error));
151 3617 : return;
152 : }
153 3617 : return;
154 : }
155 :
156 43374 : out_security_offset = SMB2_HDR_BODY + 0x08;
157 :
158 43374 : outhdr = SMBD_SMB2_OUT_HDR_PTR(smb2req);
159 :
160 43374 : outbody = smbd_smb2_generate_outbody(smb2req, 0x08);
161 43374 : if (outbody.data == NULL) {
162 0 : error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
163 0 : if (!NT_STATUS_IS_OK(error)) {
164 0 : smbd_server_connection_terminate(smb2req->xconn,
165 : nt_errstr(error));
166 0 : return;
167 : }
168 0 : return;
169 : }
170 :
171 43374 : SBVAL(outhdr, SMB2_HDR_SESSION_ID, out_session_id);
172 :
173 43374 : SSVAL(outbody.data, 0x00, 0x08 + 1); /* struct size */
174 43374 : SSVAL(outbody.data, 0x02,
175 : out_session_flags); /* session flags */
176 43374 : SSVAL(outbody.data, 0x04,
177 : out_security_offset); /* security buffer offset */
178 43374 : SSVAL(outbody.data, 0x06,
179 : out_security_buffer.length); /* security buffer length */
180 :
181 43374 : outdyn = out_security_buffer;
182 :
183 43374 : error = smbd_smb2_request_done_ex(smb2req, status, outbody, &outdyn,
184 : __location__);
185 43374 : if (!NT_STATUS_IS_OK(error)) {
186 0 : smbd_server_connection_terminate(smb2req->xconn,
187 : nt_errstr(error));
188 0 : return;
189 : }
190 : }
191 :
192 23263 : static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
193 : struct smbXsrv_session_auth0 **_auth,
194 : struct smbd_smb2_request *smb2req,
195 : uint8_t in_security_mode,
196 : struct auth_session_info *session_info,
197 : uint16_t *out_session_flags,
198 : uint64_t *out_session_id)
199 : {
200 625 : NTSTATUS status;
201 23263 : bool guest = false;
202 23263 : struct smbXsrv_session *x = session;
203 23263 : struct smbXsrv_session_auth0 *auth = *_auth;
204 23263 : struct smbXsrv_connection *xconn = smb2req->xconn;
205 625 : size_t i;
206 23263 : struct smb2_signing_derivations derivations = {
207 : .signing = NULL,
208 : };
209 23263 : DATA_BLOB preauth_hash = data_blob_null;
210 :
211 23263 : *_auth = NULL;
212 :
213 23263 : if (xconn->protocol >= PROTOCOL_SMB3_11) {
214 603 : struct smbXsrv_preauth *preauth;
215 603 : gnutls_hash_hd_t hash_hnd;
216 603 : int rc;
217 :
218 20730 : preauth = talloc_move(smb2req, &auth->preauth);
219 :
220 20730 : rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_SHA512);
221 20730 : if (rc < 0) {
222 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
223 : }
224 21333 : rc = gnutls_hash(hash_hnd,
225 20730 : preauth->sha512_value,
226 : sizeof(preauth->sha512_value));
227 20730 : if (rc < 0) {
228 0 : gnutls_hash_deinit(hash_hnd, NULL);
229 0 : return NT_STATUS_ACCESS_DENIED;
230 : }
231 103650 : for (i = 1; i < smb2req->in.vector_count; i++) {
232 85332 : rc = gnutls_hash(hash_hnd,
233 82920 : smb2req->in.vector[i].iov_base,
234 82920 : smb2req->in.vector[i].iov_len);
235 82920 : if (rc < 0) {
236 0 : gnutls_hash_deinit(hash_hnd, NULL);
237 0 : return NT_STATUS_ACCESS_DENIED;
238 : }
239 : }
240 20730 : gnutls_hash_deinit(hash_hnd, preauth->sha512_value);
241 :
242 20730 : preauth_hash = data_blob_const(preauth->sha512_value,
243 : sizeof(preauth->sha512_value));
244 : }
245 :
246 23263 : smb2_signing_derivations_fill_const_stack(&derivations,
247 : xconn->protocol,
248 : preauth_hash);
249 :
250 23263 : if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
251 13894 : (xconn->smb2.server.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED))
252 : {
253 11407 : x->global->signing_flags = SMBXSRV_SIGNING_REQUIRED;
254 : }
255 :
256 23263 : if ((lp_server_smb_encrypt(-1) >= SMB_ENCRYPTION_DESIRED) &&
257 0 : (xconn->smb2.client.capabilities & SMB2_CAP_ENCRYPTION)) {
258 0 : x->global->encryption_flags = SMBXSRV_ENCRYPTION_DESIRED;
259 : }
260 :
261 23263 : if (lp_server_smb_encrypt(-1) == SMB_ENCRYPTION_REQUIRED) {
262 0 : x->global->encryption_flags = SMBXSRV_ENCRYPTION_REQUIRED |
263 : SMBXSRV_ENCRYPTION_DESIRED;
264 : }
265 :
266 23263 : if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
267 764 : if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
268 22 : *out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
269 : }
270 : /* force no signing */
271 764 : x->global->signing_flags &= ~SMBXSRV_SIGNING_REQUIRED;
272 : /* we map anonymous to guest internally */
273 764 : guest = true;
274 : }
275 :
276 22640 : if (guest && (x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED)) {
277 0 : DEBUG(1,("reject guest session as encryption is required\n"));
278 0 : return NT_STATUS_ACCESS_DENIED;
279 : }
280 :
281 23263 : if (xconn->smb2.server.cipher == 0) {
282 2679 : if (x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
283 0 : DEBUG(1,("reject session with dialect[0x%04X] "
284 : "as encryption is required\n",
285 : xconn->smb2.server.dialect));
286 0 : return NT_STATUS_ACCESS_DENIED;
287 : }
288 : }
289 23263 : x->global->signing_algo = xconn->smb2.server.sign_algo;
290 23263 : x->global->encryption_cipher = xconn->smb2.server.cipher;
291 23263 : if (guest) {
292 764 : x->global->encryption_cipher = SMB2_ENCRYPTION_NONE;
293 : }
294 :
295 23263 : if (x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
296 0 : *out_session_flags |= SMB2_SESSION_FLAG_ENCRYPT_DATA;
297 : }
298 :
299 23888 : status = smb2_signing_key_sign_create(x->global,
300 23263 : x->global->signing_algo,
301 23263 : &session_info->session_key,
302 : derivations.signing,
303 22638 : &x->global->signing_key);
304 23263 : if (!NT_STATUS_IS_OK(status)) {
305 0 : return status;
306 : }
307 23263 : x->global->signing_key_blob = x->global->signing_key->blob;
308 :
309 23263 : if (x->global->encryption_cipher != SMB2_ENCRYPTION_NONE) {
310 609 : size_t nonce_size;
311 :
312 20501 : status = smb2_signing_key_cipher_create(x->global,
313 19283 : x->global->encryption_cipher,
314 19892 : &session_info->session_key,
315 : derivations.cipher_s2c,
316 19283 : &x->global->encryption_key);
317 19892 : if (!NT_STATUS_IS_OK(status)) {
318 0 : return status;
319 : }
320 19892 : x->global->encryption_key_blob = x->global->encryption_key->blob;
321 :
322 20501 : status = smb2_signing_key_cipher_create(x->global,
323 19892 : x->global->encryption_cipher,
324 19892 : &session_info->session_key,
325 : derivations.cipher_c2s,
326 19283 : &x->global->decryption_key);
327 19892 : if (!NT_STATUS_IS_OK(status)) {
328 0 : return status;
329 : }
330 19892 : x->global->decryption_key_blob = x->global->decryption_key->blob;
331 :
332 : /*
333 : * CCM and GCM algorithms must never have their
334 : * nonce wrap, or the security of the whole
335 : * communication and the keys is destroyed.
336 : * We must drop the connection once we have
337 : * transferred too much data.
338 : *
339 : * NOTE: We assume nonces greater than 8 bytes.
340 : */
341 19892 : generate_nonce_buffer((uint8_t *)&x->nonce_high_random,
342 : sizeof(x->nonce_high_random));
343 19892 : switch (xconn->smb2.server.cipher) {
344 110 : case SMB2_ENCRYPTION_AES128_CCM:
345 110 : nonce_size = SMB2_AES_128_CCM_NONCE_SIZE;
346 110 : break;
347 19740 : case SMB2_ENCRYPTION_AES128_GCM:
348 19740 : nonce_size = gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_GCM);
349 19740 : break;
350 10 : case SMB2_ENCRYPTION_AES256_CCM:
351 10 : nonce_size = SMB2_AES_128_CCM_NONCE_SIZE;
352 10 : break;
353 12 : case SMB2_ENCRYPTION_AES256_GCM:
354 12 : nonce_size = gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_256_GCM);
355 12 : break;
356 0 : default:
357 0 : nonce_size = 0;
358 0 : break;
359 : }
360 19892 : x->nonce_high_max = SMB2_NONCE_HIGH_MAX(nonce_size);
361 19892 : x->nonce_high = 0;
362 19892 : x->nonce_low = 0;
363 : }
364 :
365 23888 : status = smb2_signing_key_sign_create(x->global,
366 23263 : x->global->signing_algo,
367 23263 : &session_info->session_key,
368 : derivations.application,
369 23263 : &x->global->application_key);
370 23263 : if (!NT_STATUS_IS_OK(status)) {
371 0 : return status;
372 : }
373 23263 : x->global->application_key_blob = x->global->application_key->blob;
374 :
375 23263 : if (xconn->protocol >= PROTOCOL_SMB3_00 && lp_debug_encryption()) {
376 0 : DEBUG(0, ("debug encryption: dumping generated session keys\n"));
377 0 : DEBUGADD(0, ("Session Id "));
378 0 : dump_data(0, (uint8_t*)&session->global->session_wire_id,
379 : sizeof(session->global->session_wire_id));
380 0 : DEBUGADD(0, ("Session Key "));
381 0 : dump_data(0, session_info->session_key.data,
382 0 : session_info->session_key.length);
383 0 : DEBUGADD(0, ("Signing Algo: %u\n", x->global->signing_algo));
384 0 : DEBUGADD(0, ("Signing Key "));
385 0 : dump_data(0, x->global->signing_key_blob.data,
386 0 : x->global->signing_key_blob.length);
387 0 : DEBUGADD(0, ("App Key "));
388 0 : dump_data(0, x->global->application_key_blob.data,
389 0 : x->global->application_key_blob.length);
390 :
391 : /* In server code, ServerIn is the decryption key */
392 :
393 0 : DEBUGADD(0, ("Cipher Algo: %u\n", x->global->encryption_cipher));
394 0 : DEBUGADD(0, ("ServerIn Key "));
395 0 : dump_data(0, x->global->decryption_key_blob.data,
396 0 : x->global->decryption_key_blob.length);
397 0 : DEBUGADD(0, ("ServerOut Key "));
398 0 : dump_data(0, x->global->encryption_key_blob.data,
399 0 : x->global->encryption_key_blob.length);
400 : }
401 :
402 23888 : status = smb2_signing_key_copy(x->global->channels,
403 23263 : x->global->signing_key,
404 23263 : &x->global->channels[0].signing_key);
405 23263 : if (!NT_STATUS_IS_OK(status)) {
406 0 : return status;
407 : }
408 23263 : x->global->channels[0].signing_key_blob =
409 23263 : x->global->channels[0].signing_key->blob;
410 23263 : x->global->channels[0].signing_algo = x->global->signing_algo;
411 23263 : x->global->channels[0].encryption_cipher = x->global->encryption_cipher;
412 :
413 23263 : data_blob_clear_free(&session_info->session_key);
414 23263 : session_info->session_key = data_blob_dup_talloc(session_info,
415 : x->global->application_key_blob);
416 23263 : if (session_info->session_key.data == NULL) {
417 0 : return NT_STATUS_NO_MEMORY;
418 : }
419 23263 : talloc_keep_secret(session_info->session_key.data);
420 :
421 23263 : smb2req->sconn->num_users++;
422 :
423 23263 : if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
424 23122 : session->homes_snum =
425 22499 : register_homes_share(session_info->unix_info->unix_name);
426 : }
427 :
428 23263 : set_current_user_info(session_info->unix_info->sanitized_username,
429 23263 : session_info->unix_info->unix_name,
430 23263 : session_info->info->domain_name);
431 :
432 23263 : reload_services(smb2req->sconn, conn_snum_used, true);
433 :
434 23263 : session->status = NT_STATUS_OK;
435 23263 : session->global->auth_session_info = talloc_move(session->global,
436 : &session_info);
437 23263 : session->global->auth_session_info_seqnum += 1;
438 46526 : for (i=0; i < session->global->num_channels; i++) {
439 23263 : struct smbXsrv_channel_global0 *_c =
440 23263 : &session->global->channels[i];
441 :
442 23263 : _c->auth_session_info_seqnum =
443 22638 : session->global->auth_session_info_seqnum;
444 : }
445 23263 : session->global->auth_time = timeval_to_nttime(&smb2req->request_time);
446 23263 : session->global->expiration_time = gensec_expire_time(auth->gensec);
447 :
448 23263 : if (!session_claim(session)) {
449 0 : DEBUG(1, ("smb2: Failed to claim session "
450 : "for vuid=%llu\n",
451 : (unsigned long long)session->global->session_wire_id));
452 0 : return NT_STATUS_LOGON_FAILURE;
453 : }
454 :
455 23263 : TALLOC_FREE(auth);
456 23263 : status = smbXsrv_session_update(session);
457 23263 : if (!NT_STATUS_IS_OK(status)) {
458 0 : DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
459 : (unsigned long long)session->global->session_wire_id,
460 : nt_errstr(status)));
461 0 : return NT_STATUS_LOGON_FAILURE;
462 : }
463 :
464 : /*
465 : * we attach the session to the request
466 : * so that the response can be signed
467 : */
468 23263 : if (!guest) {
469 22499 : smb2req->do_signing = true;
470 : }
471 :
472 23263 : global_client_caps |= (CAP_LEVEL_II_OPLOCKS|CAP_STATUS32);
473 :
474 23263 : *out_session_id = session->global->session_wire_id;
475 23263 : smb2req->last_session_id = session->global->session_wire_id;
476 :
477 23263 : return NT_STATUS_OK;
478 : }
479 :
480 142 : static NTSTATUS smbd_smb2_reauth_generic_return(struct smbXsrv_session *session,
481 : struct smbXsrv_session_auth0 **_auth,
482 : struct smbd_smb2_request *smb2req,
483 : struct auth_session_info *session_info,
484 : uint16_t *out_session_flags,
485 : uint64_t *out_session_id)
486 : {
487 24 : NTSTATUS status;
488 142 : struct smbXsrv_session *x = session;
489 142 : struct smbXsrv_session_auth0 *auth = *_auth;
490 142 : struct smbXsrv_connection *xconn = smb2req->xconn;
491 24 : size_t i;
492 :
493 142 : *_auth = NULL;
494 :
495 142 : data_blob_clear_free(&session_info->session_key);
496 142 : session_info->session_key = data_blob_dup_talloc(session_info,
497 : x->global->application_key_blob);
498 142 : if (session_info->session_key.data == NULL) {
499 0 : return NT_STATUS_NO_MEMORY;
500 : }
501 142 : talloc_keep_secret(session_info->session_key.data);
502 :
503 166 : session->homes_snum =
504 142 : register_homes_share(session_info->unix_info->unix_name);
505 :
506 142 : set_current_user_info(session_info->unix_info->sanitized_username,
507 142 : session_info->unix_info->unix_name,
508 142 : session_info->info->domain_name);
509 :
510 142 : reload_services(smb2req->sconn, conn_snum_used, true);
511 :
512 142 : if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
513 94 : smb2req->do_signing = true;
514 : }
515 :
516 142 : session->status = NT_STATUS_OK;
517 142 : TALLOC_FREE(session->global->auth_session_info);
518 142 : session->global->auth_session_info = talloc_move(session->global,
519 : &session_info);
520 142 : session->global->auth_session_info_seqnum += 1;
521 284 : for (i=0; i < session->global->num_channels; i++) {
522 142 : struct smbXsrv_channel_global0 *_c =
523 142 : &session->global->channels[i];
524 :
525 142 : _c->auth_session_info_seqnum =
526 118 : session->global->auth_session_info_seqnum;
527 : }
528 142 : session->global->auth_time = timeval_to_nttime(&smb2req->request_time);
529 142 : session->global->expiration_time = gensec_expire_time(auth->gensec);
530 :
531 142 : TALLOC_FREE(auth);
532 142 : status = smbXsrv_session_update(session);
533 142 : if (!NT_STATUS_IS_OK(status)) {
534 0 : DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
535 : (unsigned long long)session->global->session_wire_id,
536 : nt_errstr(status)));
537 0 : return NT_STATUS_LOGON_FAILURE;
538 : }
539 :
540 142 : conn_clear_vuid_caches(xconn->client->sconn,
541 142 : session->global->session_wire_id);
542 :
543 142 : *out_session_id = session->global->session_wire_id;
544 :
545 142 : return NT_STATUS_OK;
546 : }
547 :
548 896 : static NTSTATUS smbd_smb2_bind_auth_return(struct smbXsrv_session *session,
549 : struct smbXsrv_session_auth0 **_auth,
550 : struct smbd_smb2_request *smb2req,
551 : struct auth_session_info *session_info,
552 : uint16_t *out_session_flags,
553 : uint64_t *out_session_id)
554 : {
555 20 : NTSTATUS status;
556 896 : struct smbXsrv_session *x = session;
557 896 : struct smbXsrv_session_auth0 *auth = *_auth;
558 896 : struct smbXsrv_connection *xconn = smb2req->xconn;
559 896 : struct smbXsrv_channel_global0 *c = NULL;
560 20 : size_t i;
561 896 : struct smb2_signing_derivations derivations = {
562 : .signing = NULL,
563 : };
564 896 : DATA_BLOB preauth_hash = data_blob_null;
565 20 : bool ok;
566 :
567 896 : *_auth = NULL;
568 :
569 896 : if (xconn->protocol >= PROTOCOL_SMB3_11) {
570 20 : struct smbXsrv_preauth *preauth;
571 896 : gnutls_hash_hd_t hash_hnd = NULL;
572 20 : int rc;
573 :
574 896 : preauth = talloc_move(smb2req, &auth->preauth);
575 :
576 896 : rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_SHA512);
577 896 : if (rc < 0) {
578 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
579 : }
580 :
581 916 : rc = gnutls_hash(hash_hnd,
582 896 : preauth->sha512_value,
583 : sizeof(preauth->sha512_value));
584 896 : if (rc < 0) {
585 0 : gnutls_hash_deinit(hash_hnd, NULL);
586 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
587 : }
588 4480 : for (i = 1; i < smb2req->in.vector_count; i++) {
589 3664 : rc = gnutls_hash(hash_hnd,
590 3584 : smb2req->in.vector[i].iov_base,
591 3584 : smb2req->in.vector[i].iov_len);
592 3584 : if (rc < 0) {
593 0 : gnutls_hash_deinit(hash_hnd, NULL);
594 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
595 : }
596 : }
597 896 : gnutls_hash_deinit(hash_hnd, preauth->sha512_value);
598 :
599 896 : preauth_hash = data_blob_const(preauth->sha512_value,
600 : sizeof(preauth->sha512_value));
601 : }
602 :
603 896 : smb2_signing_derivations_fill_const_stack(&derivations,
604 : xconn->protocol,
605 : preauth_hash);
606 :
607 896 : status = smbXsrv_session_find_channel(session, xconn, &c);
608 896 : if (!NT_STATUS_IS_OK(status)) {
609 0 : return status;
610 : }
611 :
612 916 : ok = security_token_is_sid(session_info->security_token,
613 896 : &x->global->auth_session_info->security_token->sids[0]);
614 896 : if (!ok) {
615 8 : return NT_STATUS_ACCESS_DENIED;
616 : }
617 :
618 888 : if (session_info->session_key.length == 0) {
619 : /* See [MS-SMB2] 3.3.5.2.4 for the return code. */
620 0 : return NT_STATUS_NOT_SUPPORTED;
621 : }
622 :
623 888 : c->signing_algo = xconn->smb2.server.sign_algo;
624 888 : c->encryption_cipher = xconn->smb2.server.cipher;
625 :
626 906 : status = smb2_signing_key_sign_create(x->global->channels,
627 870 : c->signing_algo,
628 888 : &session_info->session_key,
629 : derivations.signing,
630 870 : &c->signing_key);
631 888 : if (!NT_STATUS_IS_OK(status)) {
632 0 : return status;
633 : }
634 888 : c->signing_key_blob = c->signing_key->blob;
635 :
636 888 : TALLOC_FREE(auth);
637 888 : status = smbXsrv_session_update(session);
638 888 : if (!NT_STATUS_IS_OK(status)) {
639 0 : DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
640 : (unsigned long long)session->global->session_wire_id,
641 : nt_errstr(status)));
642 0 : return NT_STATUS_LOGON_FAILURE;
643 : }
644 :
645 888 : *out_session_id = session->global->session_wire_id;
646 :
647 888 : return NT_STATUS_OK;
648 : }
649 :
650 : struct smbd_smb2_session_setup_state {
651 : struct tevent_context *ev;
652 : struct smbd_smb2_request *smb2req;
653 : uint64_t in_session_id;
654 : uint8_t in_flags;
655 : uint8_t in_security_mode;
656 : uint64_t in_previous_session_id;
657 : DATA_BLOB in_security_buffer;
658 : struct smbXsrv_session *session;
659 : struct smbXsrv_session_auth0 *auth;
660 : struct auth_session_info *session_info;
661 : uint16_t out_session_flags;
662 : DATA_BLOB out_security_buffer;
663 : uint64_t out_session_id;
664 : };
665 :
666 : static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq);
667 : static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq);
668 : static void smbd_smb2_session_setup_auth_return(struct tevent_req *req);
669 :
670 47286 : static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx,
671 : struct tevent_context *ev,
672 : struct smbd_smb2_request *smb2req,
673 : uint64_t in_session_id,
674 : uint8_t in_flags,
675 : uint8_t in_security_mode,
676 : uint64_t in_previous_session_id,
677 : DATA_BLOB in_security_buffer)
678 : {
679 1110 : struct tevent_req *req;
680 1110 : struct smbd_smb2_session_setup_state *state;
681 1110 : NTSTATUS status;
682 47286 : NTTIME now = timeval_to_nttime(&smb2req->request_time);
683 1110 : struct tevent_req *subreq;
684 47286 : struct smbXsrv_channel_global0 *c = NULL;
685 1110 : enum security_user_level seclvl;
686 :
687 47286 : req = tevent_req_create(mem_ctx, &state,
688 : struct smbd_smb2_session_setup_state);
689 47286 : if (req == NULL) {
690 0 : return NULL;
691 : }
692 47286 : state->ev = ev;
693 47286 : state->smb2req = smb2req;
694 47286 : state->in_session_id = in_session_id;
695 47286 : state->in_flags = in_flags;
696 47286 : state->in_security_mode = in_security_mode;
697 47286 : state->in_previous_session_id = in_previous_session_id;
698 47286 : state->in_security_buffer = in_security_buffer;
699 :
700 47286 : if (in_flags & SMB2_SESSION_FLAG_BINDING) {
701 2264 : if (in_session_id == 0) {
702 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
703 0 : return tevent_req_post(req, ev);
704 : }
705 :
706 2264 : if (smb2req->session == NULL) {
707 0 : tevent_req_nterror(req, NT_STATUS_USER_SESSION_DELETED);
708 0 : return tevent_req_post(req, ev);
709 : }
710 :
711 2264 : if ((smb2req->session->global->signing_algo >= SMB2_SIGNING_AES128_GMAC) &&
712 1734 : (smb2req->xconn->smb2.server.sign_algo != smb2req->session->global->signing_algo))
713 : {
714 280 : tevent_req_nterror(req, NT_STATUS_REQUEST_OUT_OF_SEQUENCE);
715 280 : return tevent_req_post(req, ev);
716 : }
717 1984 : if ((smb2req->xconn->smb2.server.sign_algo >= SMB2_SIGNING_AES128_GMAC) &&
718 1650 : (smb2req->session->global->signing_algo != smb2req->xconn->smb2.server.sign_algo))
719 : {
720 280 : tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
721 280 : return tevent_req_post(req, ev);
722 : }
723 :
724 1704 : if (smb2req->xconn->protocol < PROTOCOL_SMB3_00) {
725 100 : tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
726 100 : return tevent_req_post(req, ev);
727 : }
728 :
729 1604 : if (!smb2req->xconn->client->server_multi_channel_enabled) {
730 0 : tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
731 0 : return tevent_req_post(req, ev);
732 : }
733 :
734 1604 : if (!smb2req->do_signing) {
735 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
736 0 : return tevent_req_post(req, ev);
737 : }
738 :
739 1604 : if (smb2req->session->global->connection_dialect
740 1604 : != smb2req->xconn->smb2.server.dialect)
741 : {
742 88 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
743 88 : return tevent_req_post(req, ev);
744 : }
745 :
746 1516 : if (smb2req->session->global->encryption_cipher
747 1516 : != smb2req->xconn->smb2.server.cipher)
748 : {
749 48 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
750 48 : return tevent_req_post(req, ev);
751 : }
752 :
753 1468 : status = smb2req->session->status;
754 1468 : if (NT_STATUS_EQUAL(status, NT_STATUS_BAD_LOGON_SESSION_STATE)) {
755 : /*
756 : * This comes from smb2srv_session_lookup_global().
757 : */
758 24 : tevent_req_nterror(req, NT_STATUS_USER_SESSION_DELETED);
759 24 : return tevent_req_post(req, ev);
760 : }
761 :
762 1444 : status = smbXsrv_session_find_channel(smb2req->session,
763 1410 : smb2req->xconn,
764 : &c);
765 1444 : if (NT_STATUS_IS_OK(status)) {
766 534 : if (!smb2_signing_key_valid(c->signing_key)) {
767 534 : goto auth;
768 : }
769 0 : tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
770 0 : return tevent_req_post(req, ev);
771 : }
772 :
773 932 : seclvl = security_session_user_level(
774 910 : smb2req->session->global->auth_session_info,
775 : NULL);
776 910 : if (seclvl < SECURITY_USER) {
777 0 : tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
778 0 : return tevent_req_post(req, ev);
779 : }
780 :
781 910 : status = smbXsrv_session_add_channel(smb2req->session,
782 : smb2req->xconn,
783 : now,
784 : &c);
785 910 : if (tevent_req_nterror(req, status)) {
786 4 : return tevent_req_post(req, ev);
787 : }
788 :
789 906 : status = smbXsrv_session_update(smb2req->session);
790 906 : if (tevent_req_nterror(req, status)) {
791 0 : return tevent_req_post(req, ev);
792 : }
793 : }
794 :
795 45928 : auth:
796 :
797 46462 : if (state->in_session_id == 0) {
798 : /* create a new session */
799 25506 : status = smbXsrv_session_create(state->smb2req->xconn,
800 24879 : now, &state->session);
801 25506 : if (tevent_req_nterror(req, status)) {
802 0 : return tevent_req_post(req, ev);
803 : }
804 25506 : smb2req->session = state->session;
805 : } else {
806 20956 : if (smb2req->session == NULL) {
807 0 : tevent_req_nterror(req, NT_STATUS_USER_SESSION_DELETED);
808 0 : return tevent_req_post(req, ev);
809 : }
810 :
811 20956 : state->session = smb2req->session;
812 20956 : status = state->session->status;
813 20956 : if (NT_STATUS_EQUAL(status, NT_STATUS_BAD_LOGON_SESSION_STATE)) {
814 : /*
815 : * This comes from smb2srv_session_lookup_global().
816 : */
817 592 : tevent_req_nterror(req, NT_STATUS_USER_SESSION_DELETED);
818 592 : return tevent_req_post(req, ev);
819 : }
820 20364 : if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
821 30 : status = NT_STATUS_OK;
822 : }
823 20364 : if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
824 18547 : status = NT_STATUS_OK;
825 : }
826 20364 : if (tevent_req_nterror(req, status)) {
827 0 : return tevent_req_post(req, ev);
828 : }
829 : }
830 :
831 46730 : status = smbXsrv_session_find_channel(smb2req->session,
832 45870 : smb2req->xconn, &c);
833 45870 : if (tevent_req_nterror(req, status)) {
834 204 : return tevent_req_post(req, ev);
835 : }
836 :
837 45666 : if (!(in_flags & SMB2_SESSION_FLAG_BINDING)) {
838 44226 : state->session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
839 : }
840 :
841 46492 : status = smbXsrv_session_find_auth(state->session, smb2req->xconn,
842 45666 : now, &state->auth);
843 45666 : if (!NT_STATUS_IS_OK(status)) {
844 27263 : status = smbXsrv_session_create_auth(state->session,
845 : smb2req->xconn, now,
846 : in_flags, in_security_mode,
847 26585 : &state->auth);
848 26585 : if (tevent_req_nterror(req, status)) {
849 0 : return tevent_req_post(req, ev);
850 : }
851 : }
852 :
853 45666 : if (state->auth->gensec == NULL) {
854 27263 : status = auth_generic_prepare(state->auth,
855 25907 : state->smb2req->xconn->remote_address,
856 26585 : state->smb2req->xconn->local_address,
857 : "SMB2",
858 25907 : &state->auth->gensec);
859 26585 : if (tevent_req_nterror(req, status)) {
860 0 : return tevent_req_post(req, ev);
861 : }
862 :
863 26585 : gensec_want_feature(state->auth->gensec, GENSEC_FEATURE_SESSION_KEY);
864 26585 : gensec_want_feature(state->auth->gensec, GENSEC_FEATURE_UNIX_TOKEN);
865 26585 : gensec_want_feature(state->auth->gensec, GENSEC_FEATURE_SMB_TRANSPORT);
866 :
867 26585 : status = gensec_start_mech_by_oid(state->auth->gensec,
868 : GENSEC_OID_SPNEGO);
869 26585 : if (tevent_req_nterror(req, status)) {
870 0 : return tevent_req_post(req, ev);
871 : }
872 : }
873 :
874 45666 : status = smbXsrv_session_update(state->session);
875 45666 : if (tevent_req_nterror(req, status)) {
876 0 : return tevent_req_post(req, ev);
877 : }
878 :
879 45666 : become_root();
880 46492 : subreq = gensec_update_send(state, state->ev,
881 45666 : state->auth->gensec,
882 45666 : state->in_security_buffer);
883 45666 : unbecome_root();
884 45666 : if (tevent_req_nomem(subreq, req)) {
885 0 : return tevent_req_post(req, ev);
886 : }
887 45666 : tevent_req_set_callback(subreq, smbd_smb2_session_setup_gensec_done, req);
888 :
889 45666 : return req;
890 : }
891 :
892 45666 : static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq)
893 : {
894 826 : struct tevent_req *req =
895 45666 : tevent_req_callback_data(subreq,
896 : struct tevent_req);
897 826 : struct smbd_smb2_session_setup_state *state =
898 45666 : tevent_req_data(req,
899 : struct smbd_smb2_session_setup_state);
900 826 : NTSTATUS status;
901 :
902 45666 : become_root();
903 45666 : status = gensec_update_recv(subreq, state,
904 : &state->out_security_buffer);
905 45666 : unbecome_root();
906 45666 : TALLOC_FREE(subreq);
907 45666 : if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
908 26585 : !NT_STATUS_IS_OK(status)) {
909 2277 : tevent_req_nterror(req, status);
910 2277 : return;
911 : }
912 :
913 43389 : if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
914 19081 : state->out_session_id = state->session->global->session_wire_id;
915 19081 : state->smb2req->preauth = state->auth->preauth;
916 19081 : tevent_req_nterror(req, status);
917 19081 : return;
918 : }
919 :
920 24308 : status = gensec_session_info(state->auth->gensec,
921 : state,
922 : &state->session_info);
923 24308 : if (tevent_req_nterror(req, status)) {
924 7 : return;
925 : }
926 :
927 24301 : if ((state->in_previous_session_id != 0) &&
928 102 : (state->session->global->session_wire_id !=
929 98 : state->in_previous_session_id))
930 : {
931 106 : subreq = smb2srv_session_close_previous_send(state, state->ev,
932 102 : state->smb2req->xconn,
933 : state->session_info,
934 : state->in_previous_session_id,
935 98 : state->session->global->session_wire_id);
936 102 : if (tevent_req_nomem(subreq, req)) {
937 0 : return;
938 : }
939 102 : tevent_req_set_callback(subreq,
940 : smbd_smb2_session_setup_previous_done,
941 : req);
942 102 : return;
943 : }
944 :
945 24199 : smbd_smb2_session_setup_auth_return(req);
946 : }
947 :
948 102 : static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq)
949 : {
950 4 : struct tevent_req *req =
951 102 : tevent_req_callback_data(subreq,
952 : struct tevent_req);
953 4 : NTSTATUS status;
954 :
955 102 : status = smb2srv_session_close_previous_recv(subreq);
956 102 : TALLOC_FREE(subreq);
957 102 : if (tevent_req_nterror(req, status)) {
958 0 : return;
959 : }
960 :
961 102 : smbd_smb2_session_setup_auth_return(req);
962 : }
963 :
964 24301 : static void smbd_smb2_session_setup_auth_return(struct tevent_req *req)
965 : {
966 669 : struct smbd_smb2_session_setup_state *state =
967 24301 : tevent_req_data(req,
968 : struct smbd_smb2_session_setup_state);
969 669 : NTSTATUS status;
970 :
971 24301 : if (state->in_flags & SMB2_SESSION_FLAG_BINDING) {
972 896 : status = smbd_smb2_bind_auth_return(state->session,
973 : &state->auth,
974 : state->smb2req,
975 : state->session_info,
976 : &state->out_session_flags,
977 : &state->out_session_id);
978 896 : if (tevent_req_nterror(req, status)) {
979 6 : return;
980 : }
981 888 : tevent_req_done(req);
982 888 : return;
983 : }
984 :
985 23405 : if (state->session->global->auth_session_info != NULL) {
986 142 : status = smbd_smb2_reauth_generic_return(state->session,
987 : &state->auth,
988 : state->smb2req,
989 : state->session_info,
990 : &state->out_session_flags,
991 : &state->out_session_id);
992 142 : if (tevent_req_nterror(req, status)) {
993 0 : return;
994 : }
995 142 : tevent_req_done(req);
996 142 : return;
997 : }
998 :
999 23263 : status = smbd_smb2_auth_generic_return(state->session,
1000 : &state->auth,
1001 : state->smb2req,
1002 23263 : state->in_security_mode,
1003 : state->session_info,
1004 : &state->out_session_flags,
1005 : &state->out_session_id);
1006 23263 : if (tevent_req_nterror(req, status)) {
1007 0 : return;
1008 : }
1009 :
1010 23263 : tevent_req_done(req);
1011 23263 : return;
1012 : }
1013 :
1014 47286 : static NTSTATUS smbd_smb2_session_setup_recv(struct tevent_req *req,
1015 : uint16_t *out_session_flags,
1016 : TALLOC_CTX *mem_ctx,
1017 : DATA_BLOB *out_security_buffer,
1018 : uint64_t *out_session_id)
1019 : {
1020 1110 : struct smbd_smb2_session_setup_state *state =
1021 47286 : tevent_req_data(req,
1022 : struct smbd_smb2_session_setup_state);
1023 1110 : NTSTATUS status;
1024 :
1025 47286 : if (tevent_req_is_nterror(req, &status)) {
1026 22993 : if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1027 3912 : tevent_req_received(req);
1028 3912 : return nt_status_squash(status);
1029 : }
1030 : } else {
1031 24293 : status = NT_STATUS_OK;
1032 : }
1033 :
1034 43374 : *out_session_flags = state->out_session_flags;
1035 43374 : *out_security_buffer = state->out_security_buffer;
1036 43374 : *out_session_id = state->out_session_id;
1037 :
1038 43374 : talloc_steal(mem_ctx, out_security_buffer->data);
1039 43374 : tevent_req_received(req);
1040 43374 : return status;
1041 : }
1042 :
1043 : struct smbd_smb2_session_setup_wrap_state {
1044 : struct tevent_context *ev;
1045 : struct smbd_smb2_request *smb2req;
1046 : uint64_t in_session_id;
1047 : uint8_t in_flags;
1048 : uint8_t in_security_mode;
1049 : uint64_t in_previous_session_id;
1050 : DATA_BLOB in_security_buffer;
1051 : uint16_t out_session_flags;
1052 : DATA_BLOB out_security_buffer;
1053 : uint64_t out_session_id;
1054 : NTSTATUS error;
1055 : };
1056 :
1057 : static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req *subreq);
1058 : static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req *subreq);
1059 :
1060 47286 : static struct tevent_req *smbd_smb2_session_setup_wrap_send(TALLOC_CTX *mem_ctx,
1061 : struct tevent_context *ev,
1062 : struct smbd_smb2_request *smb2req,
1063 : uint64_t in_session_id,
1064 : uint8_t in_flags,
1065 : uint8_t in_security_mode,
1066 : uint64_t in_previous_session_id,
1067 : DATA_BLOB in_security_buffer)
1068 : {
1069 1110 : struct tevent_req *req;
1070 1110 : struct smbd_smb2_session_setup_wrap_state *state;
1071 1110 : struct tevent_req *subreq;
1072 :
1073 47286 : req = tevent_req_create(mem_ctx, &state,
1074 : struct smbd_smb2_session_setup_wrap_state);
1075 47286 : if (req == NULL) {
1076 0 : return NULL;
1077 : }
1078 47286 : state->ev = ev;
1079 47286 : state->smb2req = smb2req;
1080 47286 : state->in_session_id = in_session_id;
1081 47286 : state->in_flags = in_flags;
1082 47286 : state->in_security_mode = in_security_mode;
1083 47286 : state->in_previous_session_id = in_previous_session_id;
1084 47286 : state->in_security_buffer = in_security_buffer;
1085 :
1086 47286 : subreq = smbd_smb2_session_setup_send(state, state->ev,
1087 46176 : state->smb2req,
1088 46176 : state->in_session_id,
1089 46176 : state->in_flags,
1090 46176 : state->in_security_mode,
1091 46176 : state->in_previous_session_id,
1092 46176 : state->in_security_buffer);
1093 47286 : if (tevent_req_nomem(subreq, req)) {
1094 0 : return tevent_req_post(req, ev);
1095 : }
1096 47286 : tevent_req_set_callback(subreq,
1097 : smbd_smb2_session_setup_wrap_setup_done, req);
1098 :
1099 47286 : return req;
1100 : }
1101 :
1102 47286 : static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req *subreq)
1103 : {
1104 1110 : struct tevent_req *req =
1105 47286 : tevent_req_callback_data(subreq,
1106 : struct tevent_req);
1107 1110 : struct smbd_smb2_session_setup_wrap_state *state =
1108 47286 : tevent_req_data(req,
1109 : struct smbd_smb2_session_setup_wrap_state);
1110 1110 : NTSTATUS status;
1111 :
1112 47286 : status = smbd_smb2_session_setup_recv(subreq,
1113 : &state->out_session_flags,
1114 : state,
1115 : &state->out_security_buffer,
1116 : &state->out_session_id);
1117 47286 : TALLOC_FREE(subreq);
1118 47286 : if (NT_STATUS_IS_OK(status)) {
1119 24293 : tevent_req_done(req);
1120 44576 : return;
1121 : }
1122 22993 : if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1123 19081 : tevent_req_nterror(req, status);
1124 19081 : return;
1125 : }
1126 :
1127 3912 : if (state->smb2req->session == NULL) {
1128 0 : tevent_req_nterror(req, status);
1129 0 : return;
1130 : }
1131 :
1132 3912 : state->error = status;
1133 :
1134 3912 : if (state->in_flags & SMB2_SESSION_FLAG_BINDING) {
1135 842 : status = smbXsrv_session_remove_channel(state->smb2req->session,
1136 694 : state->smb2req->xconn);
1137 842 : if (tevent_req_nterror(req, status)) {
1138 0 : return;
1139 : }
1140 842 : tevent_req_nterror(req, state->error);
1141 842 : return;
1142 : }
1143 :
1144 3070 : if (NT_STATUS_EQUAL(state->error, NT_STATUS_USER_SESSION_DELETED)) {
1145 796 : tevent_req_nterror(req, state->error);
1146 796 : return;
1147 : }
1148 :
1149 2274 : subreq = smb2srv_session_shutdown_send(state, state->ev,
1150 2267 : state->smb2req->session,
1151 : state->smb2req);
1152 2274 : if (tevent_req_nomem(subreq, req)) {
1153 0 : return;
1154 : }
1155 2274 : tevent_req_set_callback(subreq,
1156 : smbd_smb2_session_setup_wrap_shutdown_done,
1157 : req);
1158 : }
1159 :
1160 2274 : static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req *subreq)
1161 : {
1162 7 : struct tevent_req *req =
1163 2274 : tevent_req_callback_data(subreq,
1164 : struct tevent_req);
1165 7 : struct smbd_smb2_session_setup_wrap_state *state =
1166 2274 : tevent_req_data(req,
1167 : struct smbd_smb2_session_setup_wrap_state);
1168 7 : NTSTATUS status;
1169 :
1170 2274 : status = smb2srv_session_shutdown_recv(subreq);
1171 2274 : TALLOC_FREE(subreq);
1172 2274 : if (tevent_req_nterror(req, status)) {
1173 0 : return;
1174 : }
1175 :
1176 : /*
1177 : * we may need to sign the response, so we need to keep
1178 : * the session until the response is sent to the wire.
1179 : */
1180 2274 : talloc_steal(state->smb2req, state->smb2req->session);
1181 :
1182 2274 : tevent_req_nterror(req, state->error);
1183 : }
1184 :
1185 47286 : static NTSTATUS smbd_smb2_session_setup_wrap_recv(struct tevent_req *req,
1186 : uint16_t *out_session_flags,
1187 : TALLOC_CTX *mem_ctx,
1188 : DATA_BLOB *out_security_buffer,
1189 : uint64_t *out_session_id)
1190 : {
1191 1110 : struct smbd_smb2_session_setup_wrap_state *state =
1192 47286 : tevent_req_data(req,
1193 : struct smbd_smb2_session_setup_wrap_state);
1194 1110 : NTSTATUS status;
1195 :
1196 47286 : if (tevent_req_is_nterror(req, &status)) {
1197 22993 : if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1198 3912 : tevent_req_received(req);
1199 3912 : return nt_status_squash(status);
1200 : }
1201 : } else {
1202 24293 : status = NT_STATUS_OK;
1203 : }
1204 :
1205 43374 : *out_session_flags = state->out_session_flags;
1206 43374 : *out_security_buffer = state->out_security_buffer;
1207 43374 : *out_session_id = state->out_session_id;
1208 :
1209 43374 : talloc_steal(mem_ctx, out_security_buffer->data);
1210 43374 : tevent_req_received(req);
1211 43374 : return status;
1212 : }
1213 :
1214 : static struct tevent_req *smbd_smb2_logoff_send(TALLOC_CTX *mem_ctx,
1215 : struct tevent_context *ev,
1216 : struct smbd_smb2_request *smb2req);
1217 : static NTSTATUS smbd_smb2_logoff_recv(struct tevent_req *req);
1218 : static void smbd_smb2_request_logoff_done(struct tevent_req *subreq);
1219 :
1220 159 : NTSTATUS smbd_smb2_request_process_logoff(struct smbd_smb2_request *req)
1221 : {
1222 6 : NTSTATUS status;
1223 159 : struct tevent_req *subreq = NULL;
1224 :
1225 159 : status = smbd_smb2_request_verify_sizes(req, 0x04);
1226 159 : if (!NT_STATUS_IS_OK(status)) {
1227 0 : return smbd_smb2_request_error(req, status);
1228 : }
1229 :
1230 159 : subreq = smbd_smb2_logoff_send(req, req->sconn->ev_ctx, req);
1231 159 : if (subreq == NULL) {
1232 0 : return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
1233 : }
1234 159 : tevent_req_set_callback(subreq, smbd_smb2_request_logoff_done, req);
1235 :
1236 : /*
1237 : * Avoid sending a STATUS_PENDING message, it's very likely
1238 : * the client won't expect that.
1239 : */
1240 159 : return smbd_smb2_request_pending_queue(req, subreq, 0);
1241 : }
1242 :
1243 159 : static void smbd_smb2_request_logoff_done(struct tevent_req *subreq)
1244 : {
1245 6 : struct smbd_smb2_request *smb2req =
1246 159 : tevent_req_callback_data(subreq,
1247 : struct smbd_smb2_request);
1248 6 : DATA_BLOB outbody;
1249 6 : NTSTATUS status;
1250 6 : NTSTATUS error;
1251 :
1252 165 : status = smbd_smb2_logoff_recv(subreq);
1253 159 : TALLOC_FREE(subreq);
1254 159 : if (!NT_STATUS_IS_OK(status)) {
1255 0 : error = smbd_smb2_request_error(smb2req, status);
1256 0 : if (!NT_STATUS_IS_OK(error)) {
1257 0 : smbd_server_connection_terminate(smb2req->xconn,
1258 : nt_errstr(error));
1259 0 : return;
1260 : }
1261 0 : return;
1262 : }
1263 :
1264 159 : outbody = smbd_smb2_generate_outbody(smb2req, 0x04);
1265 159 : if (outbody.data == NULL) {
1266 0 : error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
1267 0 : if (!NT_STATUS_IS_OK(error)) {
1268 0 : smbd_server_connection_terminate(smb2req->xconn,
1269 : nt_errstr(error));
1270 0 : return;
1271 : }
1272 0 : return;
1273 : }
1274 :
1275 159 : SSVAL(outbody.data, 0x00, 0x04); /* struct size */
1276 159 : SSVAL(outbody.data, 0x02, 0); /* reserved */
1277 :
1278 159 : error = smbd_smb2_request_done(smb2req, outbody, NULL);
1279 159 : if (!NT_STATUS_IS_OK(error)) {
1280 0 : smbd_server_connection_terminate(smb2req->xconn,
1281 : nt_errstr(error));
1282 0 : return;
1283 : }
1284 : }
1285 :
1286 : struct smbd_smb2_logoff_state {
1287 : struct smbd_smb2_request *smb2req;
1288 : };
1289 :
1290 : static void smbd_smb2_logoff_shutdown_done(struct tevent_req *subreq);
1291 :
1292 159 : static struct tevent_req *smbd_smb2_logoff_send(TALLOC_CTX *mem_ctx,
1293 : struct tevent_context *ev,
1294 : struct smbd_smb2_request *smb2req)
1295 : {
1296 6 : struct tevent_req *req;
1297 6 : struct smbd_smb2_logoff_state *state;
1298 6 : struct tevent_req *subreq;
1299 :
1300 159 : req = tevent_req_create(mem_ctx, &state,
1301 : struct smbd_smb2_logoff_state);
1302 159 : if (req == NULL) {
1303 0 : return NULL;
1304 : }
1305 159 : state->smb2req = smb2req;
1306 :
1307 159 : subreq = smb2srv_session_shutdown_send(state, ev,
1308 : smb2req->session,
1309 : smb2req);
1310 159 : if (tevent_req_nomem(subreq, req)) {
1311 0 : return tevent_req_post(req, ev);
1312 : }
1313 159 : tevent_req_set_callback(subreq, smbd_smb2_logoff_shutdown_done, req);
1314 :
1315 159 : return req;
1316 : }
1317 :
1318 159 : static void smbd_smb2_logoff_shutdown_done(struct tevent_req *subreq)
1319 : {
1320 159 : struct tevent_req *req = tevent_req_callback_data(
1321 : subreq, struct tevent_req);
1322 159 : struct smbd_smb2_logoff_state *state = tevent_req_data(
1323 : req, struct smbd_smb2_logoff_state);
1324 6 : NTSTATUS status;
1325 6 : bool ok;
1326 159 : const struct GUID *client_guid =
1327 159 : &state->smb2req->session->client->global->client_guid;
1328 :
1329 159 : status = smb2srv_session_shutdown_recv(subreq);
1330 159 : if (tevent_req_nterror(req, status)) {
1331 0 : return;
1332 : }
1333 159 : TALLOC_FREE(subreq);
1334 :
1335 159 : if (!GUID_all_zero(client_guid)) {
1336 147 : ok = remote_arch_cache_delete(client_guid);
1337 147 : if (!ok) {
1338 : /* Most likely not an error, but not in cache */
1339 135 : DBG_DEBUG("Deletion from remote arch cache failed\n");
1340 : }
1341 : }
1342 :
1343 : /*
1344 : * As we've been awoken, we may have changed
1345 : * uid in the meantime. Ensure we're still
1346 : * root (SMB2_OP_LOGOFF has .as_root = true).
1347 : */
1348 159 : change_to_root_user();
1349 :
1350 159 : status = smbXsrv_session_logoff(state->smb2req->session);
1351 159 : if (tevent_req_nterror(req, status)) {
1352 0 : return;
1353 : }
1354 :
1355 : /*
1356 : * we may need to sign the response, so we need to keep
1357 : * the session until the response is sent to the wire.
1358 : */
1359 159 : talloc_steal(state->smb2req, state->smb2req->session);
1360 :
1361 159 : tevent_req_done(req);
1362 : }
1363 :
1364 159 : static NTSTATUS smbd_smb2_logoff_recv(struct tevent_req *req)
1365 : {
1366 159 : return tevent_req_simple_recv_ntstatus(req);
1367 : }
|