smbd: Return "blocker_pid" from do_lock()
[Samba.git] / source3 / smbd / smb2_sesssetup.c
blob692f22cadbed78b80d641e7f0f40c11c28eaa4c5
1 /*
2 Unix SMB/CIFS implementation.
3 Core SMB2 server
5 Copyright (C) Stefan Metzmacher 2009
6 Copyright (C) Jeremy Allison 2010
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.
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.
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/>.
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 "lib/crypto/aes.h"
32 #include "lib/crypto/aes_ccm_128.h"
33 #include "lib/crypto/aes_gcm_128.h"
35 #include <gnutls/gnutls.h>
36 #include <gnutls/crypto.h>
38 #undef DBGC_CLASS
39 #define DBGC_CLASS DBGC_SMB2
41 static struct tevent_req *smbd_smb2_session_setup_wrap_send(TALLOC_CTX *mem_ctx,
42 struct tevent_context *ev,
43 struct smbd_smb2_request *smb2req,
44 uint64_t in_session_id,
45 uint8_t in_flags,
46 uint8_t in_security_mode,
47 uint64_t in_previous_session_id,
48 DATA_BLOB in_security_buffer);
49 static NTSTATUS smbd_smb2_session_setup_wrap_recv(struct tevent_req *req,
50 uint16_t *out_session_flags,
51 TALLOC_CTX *mem_ctx,
52 DATA_BLOB *out_security_buffer,
53 uint64_t *out_session_id);
55 static void smbd_smb2_request_sesssetup_done(struct tevent_req *subreq);
57 NTSTATUS smbd_smb2_request_process_sesssetup(struct smbd_smb2_request *smb2req)
59 const uint8_t *inhdr;
60 const uint8_t *inbody;
61 uint64_t in_session_id;
62 uint8_t in_flags;
63 uint8_t in_security_mode;
64 uint64_t in_previous_session_id;
65 uint16_t in_security_offset;
66 uint16_t in_security_length;
67 DATA_BLOB in_security_buffer;
68 NTSTATUS status;
69 struct tevent_req *subreq;
71 status = smbd_smb2_request_verify_sizes(smb2req, 0x19);
72 if (!NT_STATUS_IS_OK(status)) {
73 return smbd_smb2_request_error(smb2req, status);
75 inhdr = SMBD_SMB2_IN_HDR_PTR(smb2req);
76 inbody = SMBD_SMB2_IN_BODY_PTR(smb2req);
78 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
80 in_flags = CVAL(inbody, 0x02);
81 in_security_mode = CVAL(inbody, 0x03);
82 /* Capabilities = IVAL(inbody, 0x04) */
83 /* Channel = IVAL(inbody, 0x08) */
84 in_security_offset = SVAL(inbody, 0x0C);
85 in_security_length = SVAL(inbody, 0x0E);
86 in_previous_session_id = BVAL(inbody, 0x10);
88 if (in_security_offset != (SMB2_HDR_BODY + SMBD_SMB2_IN_BODY_LEN(smb2req))) {
89 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
92 if (in_security_length > SMBD_SMB2_IN_DYN_LEN(smb2req)) {
93 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
96 in_security_buffer.data = SMBD_SMB2_IN_DYN_PTR(smb2req);
97 in_security_buffer.length = in_security_length;
99 subreq = smbd_smb2_session_setup_wrap_send(smb2req,
100 smb2req->sconn->ev_ctx,
101 smb2req,
102 in_session_id,
103 in_flags,
104 in_security_mode,
105 in_previous_session_id,
106 in_security_buffer);
107 if (subreq == NULL) {
108 return smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
110 tevent_req_set_callback(subreq, smbd_smb2_request_sesssetup_done, smb2req);
113 * Avoid sending a STATUS_PENDING message, which
114 * matches a Windows Server and avoids problems with
115 * MacOS clients.
117 * Even after 90 seconds a Windows Server doesn't return
118 * STATUS_PENDING if using NTLMSSP against a non reachable
119 * trusted domain.
121 return smbd_smb2_request_pending_queue(smb2req, subreq, 0);
124 static void smbd_smb2_request_sesssetup_done(struct tevent_req *subreq)
126 struct smbd_smb2_request *smb2req =
127 tevent_req_callback_data(subreq,
128 struct smbd_smb2_request);
129 uint8_t *outhdr;
130 DATA_BLOB outbody;
131 DATA_BLOB outdyn;
132 uint16_t out_session_flags = 0;
133 uint64_t out_session_id = 0;
134 uint16_t out_security_offset;
135 DATA_BLOB out_security_buffer = data_blob_null;
136 NTSTATUS status;
137 NTSTATUS error; /* transport error */
139 status = smbd_smb2_session_setup_wrap_recv(subreq,
140 &out_session_flags,
141 smb2req,
142 &out_security_buffer,
143 &out_session_id);
144 TALLOC_FREE(subreq);
145 if (!NT_STATUS_IS_OK(status) &&
146 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
147 status = nt_status_squash(status);
148 error = smbd_smb2_request_error(smb2req, status);
149 if (!NT_STATUS_IS_OK(error)) {
150 smbd_server_connection_terminate(smb2req->xconn,
151 nt_errstr(error));
152 return;
154 return;
157 out_security_offset = SMB2_HDR_BODY + 0x08;
159 outhdr = SMBD_SMB2_OUT_HDR_PTR(smb2req);
161 outbody = smbd_smb2_generate_outbody(smb2req, 0x08);
162 if (outbody.data == NULL) {
163 error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
164 if (!NT_STATUS_IS_OK(error)) {
165 smbd_server_connection_terminate(smb2req->xconn,
166 nt_errstr(error));
167 return;
169 return;
172 SBVAL(outhdr, SMB2_HDR_SESSION_ID, out_session_id);
174 SSVAL(outbody.data, 0x00, 0x08 + 1); /* struct size */
175 SSVAL(outbody.data, 0x02,
176 out_session_flags); /* session flags */
177 SSVAL(outbody.data, 0x04,
178 out_security_offset); /* security buffer offset */
179 SSVAL(outbody.data, 0x06,
180 out_security_buffer.length); /* security buffer length */
182 outdyn = out_security_buffer;
184 error = smbd_smb2_request_done_ex(smb2req, status, outbody, &outdyn,
185 __location__);
186 if (!NT_STATUS_IS_OK(error)) {
187 smbd_server_connection_terminate(smb2req->xconn,
188 nt_errstr(error));
189 return;
193 static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
194 struct smbXsrv_session_auth0 **_auth,
195 struct smbd_smb2_request *smb2req,
196 uint8_t in_security_mode,
197 struct auth_session_info *session_info,
198 uint16_t *out_session_flags,
199 uint64_t *out_session_id)
201 NTSTATUS status;
202 bool guest = false;
203 uint8_t session_key[16];
204 struct smbXsrv_session *x = session;
205 struct smbXsrv_session_auth0 *auth = *_auth;
206 struct smbXsrv_connection *xconn = smb2req->xconn;
207 size_t i;
208 struct _derivation {
209 DATA_BLOB label;
210 DATA_BLOB context;
212 struct {
213 struct _derivation signing;
214 struct _derivation encryption;
215 struct _derivation decryption;
216 struct _derivation application;
217 } derivation = { };
219 *_auth = NULL;
221 if (xconn->protocol >= PROTOCOL_SMB3_10) {
222 struct smbXsrv_preauth *preauth;
223 struct _derivation *d;
224 DATA_BLOB p;
225 gnutls_hash_hd_t hash_hnd;
226 int rc;
228 preauth = talloc_move(smb2req, &auth->preauth);
230 rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_SHA512);
231 if (rc < 0) {
232 return NT_STATUS_NO_MEMORY;
234 rc = gnutls_hash(hash_hnd,
235 preauth->sha512_value,
236 sizeof(preauth->sha512_value));
237 if (rc < 0) {
238 gnutls_hash_deinit(hash_hnd, NULL);
239 return NT_STATUS_ACCESS_DENIED;
241 for (i = 1; i < smb2req->in.vector_count; i++) {
242 rc = gnutls_hash(hash_hnd,
243 smb2req->in.vector[i].iov_base,
244 smb2req->in.vector[i].iov_len);
245 if (rc < 0) {
246 gnutls_hash_deinit(hash_hnd, NULL);
247 return NT_STATUS_ACCESS_DENIED;
250 gnutls_hash_deinit(hash_hnd, preauth->sha512_value);
252 p = data_blob_const(preauth->sha512_value,
253 sizeof(preauth->sha512_value));
255 d = &derivation.signing;
256 d->label = data_blob_string_const_null("SMBSigningKey");
257 d->context = p;
259 d = &derivation.decryption;
260 d->label = data_blob_string_const_null("SMBC2SCipherKey");
261 d->context = p;
263 d = &derivation.encryption;
264 d->label = data_blob_string_const_null("SMBS2CCipherKey");
265 d->context = p;
267 d = &derivation.application;
268 d->label = data_blob_string_const_null("SMBAppKey");
269 d->context = p;
271 } else if (xconn->protocol >= PROTOCOL_SMB2_24) {
272 struct _derivation *d;
274 d = &derivation.signing;
275 d->label = data_blob_string_const_null("SMB2AESCMAC");
276 d->context = data_blob_string_const_null("SmbSign");
278 d = &derivation.decryption;
279 d->label = data_blob_string_const_null("SMB2AESCCM");
280 d->context = data_blob_string_const_null("ServerIn ");
282 d = &derivation.encryption;
283 d->label = data_blob_string_const_null("SMB2AESCCM");
284 d->context = data_blob_string_const_null("ServerOut");
286 d = &derivation.application;
287 d->label = data_blob_string_const_null("SMB2APP");
288 d->context = data_blob_string_const_null("SmbRpc");
291 if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
292 (xconn->smb2.server.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED))
294 x->global->signing_flags = SMBXSRV_SIGNING_REQUIRED;
297 if ((lp_smb_encrypt(-1) >= SMB_SIGNING_DESIRED) &&
298 (xconn->smb2.client.capabilities & SMB2_CAP_ENCRYPTION)) {
299 x->global->encryption_flags = SMBXSRV_ENCRYPTION_DESIRED;
302 if (lp_smb_encrypt(-1) == SMB_SIGNING_REQUIRED) {
303 x->global->encryption_flags = SMBXSRV_ENCRYPTION_REQUIRED |
304 SMBXSRV_ENCRYPTION_DESIRED;
307 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
308 if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
309 *out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
311 /* force no signing */
312 x->global->signing_flags &= ~SMBXSRV_SIGNING_REQUIRED;
313 /* we map anonymous to guest internally */
314 guest = true;
317 if (guest && (x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED)) {
318 DEBUG(1,("reject guest session as encryption is required\n"));
319 return NT_STATUS_ACCESS_DENIED;
322 if (xconn->smb2.server.cipher == 0) {
323 if (x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
324 DEBUG(1,("reject session with dialect[0x%04X] "
325 "as encryption is required\n",
326 xconn->smb2.server.dialect));
327 return NT_STATUS_ACCESS_DENIED;
329 } else {
330 x->global->channels[0].encryption_cipher = xconn->smb2.server.cipher;
333 if (x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
334 *out_session_flags |= SMB2_SESSION_FLAG_ENCRYPT_DATA;
337 ZERO_STRUCT(session_key);
338 memcpy(session_key, session_info->session_key.data,
339 MIN(session_info->session_key.length, sizeof(session_key)));
341 x->global->signing_key = talloc_zero(x->global,
342 struct smb2_signing_key);
343 if (x->global->signing_key == NULL) {
344 ZERO_STRUCT(session_key);
345 return NT_STATUS_NO_MEMORY;
347 talloc_set_destructor(x->global->signing_key,
348 smb2_signing_key_destructor);
350 x->global->signing_key->blob =
351 x->global->signing_key_blob =
352 data_blob_talloc(x->global,
353 session_key,
354 sizeof(session_key));
355 if (!smb2_signing_key_valid(x->global->signing_key)) {
356 ZERO_STRUCT(session_key);
357 return NT_STATUS_NO_MEMORY;
360 if (xconn->protocol >= PROTOCOL_SMB2_24) {
361 struct _derivation *d = &derivation.signing;
363 smb2_key_derivation(session_key, sizeof(session_key),
364 d->label.data, d->label.length,
365 d->context.data, d->context.length,
366 x->global->signing_key->blob.data);
369 if (xconn->protocol >= PROTOCOL_SMB2_24) {
370 struct _derivation *d = &derivation.decryption;
372 x->global->decryption_key_blob = data_blob_talloc(x->global,
373 session_key,
374 sizeof(session_key));
375 if (x->global->decryption_key_blob.data == NULL) {
376 ZERO_STRUCT(session_key);
377 return NT_STATUS_NO_MEMORY;
380 smb2_key_derivation(session_key, sizeof(session_key),
381 d->label.data, d->label.length,
382 d->context.data, d->context.length,
383 x->global->decryption_key_blob.data);
386 if (xconn->protocol >= PROTOCOL_SMB2_24) {
387 struct _derivation *d = &derivation.encryption;
388 size_t nonce_size;
390 x->global->encryption_key_blob = data_blob_talloc(x->global,
391 session_key,
392 sizeof(session_key));
393 if (x->global->encryption_key_blob.data == NULL) {
394 ZERO_STRUCT(session_key);
395 return NT_STATUS_NO_MEMORY;
398 smb2_key_derivation(session_key, sizeof(session_key),
399 d->label.data, d->label.length,
400 d->context.data, d->context.length,
401 x->global->encryption_key_blob.data);
404 * CCM and GCM algorithms must never have their
405 * nonce wrap, or the security of the whole
406 * communication and the keys is destroyed.
407 * We must drop the connection once we have
408 * transfered too much data.
410 * NOTE: We assume nonces greater than 8 bytes.
412 generate_random_buffer((uint8_t *)&x->nonce_high_random,
413 sizeof(x->nonce_high_random));
414 switch (xconn->smb2.server.cipher) {
415 case SMB2_ENCRYPTION_AES128_CCM:
416 nonce_size = AES_CCM_128_NONCE_SIZE;
417 break;
418 case SMB2_ENCRYPTION_AES128_GCM:
419 nonce_size = AES_GCM_128_IV_SIZE;
420 break;
421 default:
422 nonce_size = 0;
423 break;
425 x->nonce_high_max = SMB2_NONCE_HIGH_MAX(nonce_size);
426 x->nonce_high = 0;
427 x->nonce_low = 0;
430 x->global->application_key =
431 data_blob_dup_talloc(x->global, x->global->signing_key->blob);
432 if (x->global->application_key.data == NULL) {
433 ZERO_STRUCT(session_key);
434 return NT_STATUS_NO_MEMORY;
436 talloc_keep_secret(x->global->application_key.data);
438 if (xconn->protocol >= PROTOCOL_SMB2_24) {
439 struct _derivation *d = &derivation.application;
441 smb2_key_derivation(session_key, sizeof(session_key),
442 d->label.data, d->label.length,
443 d->context.data, d->context.length,
444 x->global->application_key.data);
447 if (xconn->protocol >= PROTOCOL_SMB3_00 && lp_debug_encryption()) {
448 DEBUG(0, ("debug encryption: dumping generated session keys\n"));
449 DEBUGADD(0, ("Session Id "));
450 dump_data(0, (uint8_t*)&session->global->session_wire_id,
451 sizeof(session->global->session_wire_id));
452 DEBUGADD(0, ("Session Key "));
453 dump_data(0, session_key, sizeof(session_key));
454 DEBUGADD(0, ("Signing Key "));
455 dump_data(0, x->global->signing_key->blob.data,
456 x->global->signing_key->blob.length);
457 DEBUGADD(0, ("App Key "));
458 dump_data(0, x->global->application_key.data,
459 x->global->application_key.length);
461 /* In server code, ServerIn is the decryption key */
463 DEBUGADD(0, ("ServerIn Key "));
464 dump_data(0, x->global->decryption_key_blob.data,
465 x->global->decryption_key_blob.length);
466 DEBUGADD(0, ("ServerOut Key "));
467 dump_data(0, x->global->encryption_key_blob.data,
468 x->global->encryption_key_blob.length);
471 ZERO_STRUCT(session_key);
473 x->global->channels[0].signing_key =
474 talloc_zero(x->global->channels, struct smb2_signing_key);
475 if (x->global->channels[0].signing_key == NULL) {
476 return NT_STATUS_NO_MEMORY;
478 talloc_set_destructor(x->global->channels[0].signing_key,
479 smb2_signing_key_destructor);
481 x->global->channels[0].signing_key->blob =
482 x->global->channels[0].signing_key_blob =
483 data_blob_dup_talloc(x->global->channels[0].signing_key,
484 x->global->signing_key->blob);
485 if (!smb2_signing_key_valid(x->global->channels[0].signing_key)) {
486 return NT_STATUS_NO_MEMORY;
488 talloc_keep_secret(x->global->channels[0].signing_key->blob.data);
490 data_blob_clear_free(&session_info->session_key);
491 session_info->session_key = data_blob_dup_talloc(session_info,
492 x->global->application_key);
493 if (session_info->session_key.data == NULL) {
494 return NT_STATUS_NO_MEMORY;
496 talloc_keep_secret(session_info->session_key.data);
498 session->compat = talloc_zero(session, struct user_struct);
499 if (session->compat == NULL) {
500 return NT_STATUS_NO_MEMORY;
502 session->compat->session = session;
503 session->compat->homes_snum = -1;
504 session->compat->session_info = session_info;
505 session->compat->session_keystr = NULL;
506 session->compat->vuid = session->global->session_wire_id;
507 DLIST_ADD(smb2req->sconn->users, session->compat);
508 smb2req->sconn->num_users++;
510 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
511 session->compat->homes_snum =
512 register_homes_share(session_info->unix_info->unix_name);
515 set_current_user_info(session_info->unix_info->sanitized_username,
516 session_info->unix_info->unix_name,
517 session_info->info->domain_name);
519 reload_services(smb2req->sconn, conn_snum_used, true);
521 session->status = NT_STATUS_OK;
522 session->global->auth_session_info = talloc_move(session->global,
523 &session_info);
524 session->global->auth_session_info_seqnum += 1;
525 for (i=0; i < session->global->num_channels; i++) {
526 struct smbXsrv_channel_global0 *_c =
527 &session->global->channels[i];
529 _c->auth_session_info_seqnum =
530 session->global->auth_session_info_seqnum;
532 session->global->auth_time = timeval_to_nttime(&smb2req->request_time);
533 session->global->expiration_time = gensec_expire_time(auth->gensec);
535 if (!session_claim(session)) {
536 DEBUG(1, ("smb2: Failed to claim session "
537 "for vuid=%llu\n",
538 (unsigned long long)session->compat->vuid));
539 return NT_STATUS_LOGON_FAILURE;
542 TALLOC_FREE(auth);
543 status = smbXsrv_session_update(session);
544 if (!NT_STATUS_IS_OK(status)) {
545 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
546 (unsigned long long)session->compat->vuid,
547 nt_errstr(status)));
548 return NT_STATUS_LOGON_FAILURE;
552 * we attach the session to the request
553 * so that the response can be signed
555 if (!guest) {
556 smb2req->do_signing = true;
559 global_client_caps |= (CAP_LEVEL_II_OPLOCKS|CAP_STATUS32);
561 *out_session_id = session->global->session_wire_id;
562 smb2req->last_session_id = session->global->session_wire_id;
564 return NT_STATUS_OK;
567 static NTSTATUS smbd_smb2_reauth_generic_return(struct smbXsrv_session *session,
568 struct smbXsrv_session_auth0 **_auth,
569 struct smbd_smb2_request *smb2req,
570 struct auth_session_info *session_info,
571 uint16_t *out_session_flags,
572 uint64_t *out_session_id)
574 NTSTATUS status;
575 struct smbXsrv_session *x = session;
576 struct smbXsrv_session_auth0 *auth = *_auth;
577 struct smbXsrv_connection *xconn = smb2req->xconn;
578 size_t i;
580 *_auth = NULL;
582 data_blob_clear_free(&session_info->session_key);
583 session_info->session_key = data_blob_dup_talloc(session_info,
584 x->global->application_key);
585 if (session_info->session_key.data == NULL) {
586 return NT_STATUS_NO_MEMORY;
588 talloc_keep_secret(session_info->session_key.data);
590 session->compat->session_info = session_info;
591 session->compat->vuid = session->global->session_wire_id;
593 session->compat->homes_snum =
594 register_homes_share(session_info->unix_info->unix_name);
596 set_current_user_info(session_info->unix_info->sanitized_username,
597 session_info->unix_info->unix_name,
598 session_info->info->domain_name);
600 reload_services(smb2req->sconn, conn_snum_used, true);
602 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
603 smb2req->do_signing = true;
606 session->status = NT_STATUS_OK;
607 TALLOC_FREE(session->global->auth_session_info);
608 session->global->auth_session_info = talloc_move(session->global,
609 &session_info);
610 session->global->auth_session_info_seqnum += 1;
611 for (i=0; i < session->global->num_channels; i++) {
612 struct smbXsrv_channel_global0 *_c =
613 &session->global->channels[i];
615 _c->auth_session_info_seqnum =
616 session->global->auth_session_info_seqnum;
618 session->global->auth_time = timeval_to_nttime(&smb2req->request_time);
619 session->global->expiration_time = gensec_expire_time(auth->gensec);
621 TALLOC_FREE(auth);
622 status = smbXsrv_session_update(session);
623 if (!NT_STATUS_IS_OK(status)) {
624 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
625 (unsigned long long)session->compat->vuid,
626 nt_errstr(status)));
627 return NT_STATUS_LOGON_FAILURE;
630 conn_clear_vuid_caches(xconn->client->sconn, session->compat->vuid);
632 *out_session_id = session->global->session_wire_id;
634 return NT_STATUS_OK;
637 static NTSTATUS smbd_smb2_bind_auth_return(struct smbXsrv_session *session,
638 struct smbXsrv_session_auth0 **_auth,
639 struct smbd_smb2_request *smb2req,
640 struct auth_session_info *session_info,
641 uint16_t *out_session_flags,
642 uint64_t *out_session_id)
644 NTSTATUS status;
645 struct smbXsrv_session *x = session;
646 struct smbXsrv_session_auth0 *auth = *_auth;
647 struct smbXsrv_connection *xconn = smb2req->xconn;
648 struct smbXsrv_channel_global0 *c = NULL;
649 uint8_t session_key[16];
650 size_t i;
651 struct _derivation {
652 DATA_BLOB label;
653 DATA_BLOB context;
655 struct {
656 struct _derivation signing;
657 } derivation = { };
658 bool ok;
660 *_auth = NULL;
662 if (xconn->protocol >= PROTOCOL_SMB3_10) {
663 struct smbXsrv_preauth *preauth;
664 struct _derivation *d;
665 DATA_BLOB p;
666 gnutls_hash_hd_t hash_hnd = NULL;
667 int rc;
669 preauth = talloc_move(smb2req, &auth->preauth);
671 rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_SHA512);
672 if (rc < 0) {
673 return NT_STATUS_NO_MEMORY;
676 rc = gnutls_hash(hash_hnd,
677 preauth->sha512_value,
678 sizeof(preauth->sha512_value));
679 if (rc < 0) {
680 gnutls_hash_deinit(hash_hnd, NULL);
681 return NT_STATUS_INTERNAL_ERROR;
683 for (i = 1; i < smb2req->in.vector_count; i++) {
684 rc = gnutls_hash(hash_hnd,
685 smb2req->in.vector[i].iov_base,
686 smb2req->in.vector[i].iov_len);
687 if (rc < 0) {
688 gnutls_hash_deinit(hash_hnd, NULL);
689 return NT_STATUS_INTERNAL_ERROR;
692 gnutls_hash_deinit(hash_hnd, preauth->sha512_value);
694 p = data_blob_const(preauth->sha512_value,
695 sizeof(preauth->sha512_value));
697 d = &derivation.signing;
698 d->label = data_blob_string_const_null("SMBSigningKey");
699 d->context = p;
701 } else if (xconn->protocol >= PROTOCOL_SMB2_24) {
702 struct _derivation *d;
704 d = &derivation.signing;
705 d->label = data_blob_string_const_null("SMB2AESCMAC");
706 d->context = data_blob_string_const_null("SmbSign");
709 status = smbXsrv_session_find_channel(session, xconn, &c);
710 if (!NT_STATUS_IS_OK(status)) {
711 return status;
714 ok = security_token_is_sid(session_info->security_token,
715 &x->global->auth_session_info->security_token->sids[0]);
716 if (!ok) {
717 return NT_STATUS_NOT_SUPPORTED;
720 if (session_info->session_key.length == 0) {
721 /* See [MS-SMB2] 3.3.5.2.4 for the return code. */
722 return NT_STATUS_NOT_SUPPORTED;
725 ZERO_STRUCT(session_key);
726 memcpy(session_key, session_info->session_key.data,
727 MIN(session_info->session_key.length, sizeof(session_key)));
729 c->signing_key = talloc_zero(x->global, struct smb2_signing_key);
730 if (c->signing_key == NULL) {
731 ZERO_STRUCT(session_key);
732 return NT_STATUS_NO_MEMORY;
734 talloc_set_destructor(c->signing_key,
735 smb2_signing_key_destructor);
737 c->signing_key->blob =
738 c->signing_key_blob =
739 data_blob_talloc(c->signing_key,
740 session_key,
741 sizeof(session_key));
742 if (!smb2_signing_key_valid(c->signing_key)) {
743 ZERO_STRUCT(session_key);
744 return NT_STATUS_NO_MEMORY;
746 talloc_keep_secret(c->signing_key->blob.data);
748 if (xconn->protocol >= PROTOCOL_SMB2_24) {
749 struct _derivation *d = &derivation.signing;
751 smb2_key_derivation(session_key, sizeof(session_key),
752 d->label.data, d->label.length,
753 d->context.data, d->context.length,
754 c->signing_key->blob.data);
756 ZERO_STRUCT(session_key);
758 TALLOC_FREE(auth);
759 status = smbXsrv_session_update(session);
760 if (!NT_STATUS_IS_OK(status)) {
761 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
762 (unsigned long long)session->compat->vuid,
763 nt_errstr(status)));
764 return NT_STATUS_LOGON_FAILURE;
767 *out_session_id = session->global->session_wire_id;
769 return NT_STATUS_OK;
772 struct smbd_smb2_session_setup_state {
773 struct tevent_context *ev;
774 struct smbd_smb2_request *smb2req;
775 uint64_t in_session_id;
776 uint8_t in_flags;
777 uint8_t in_security_mode;
778 uint64_t in_previous_session_id;
779 DATA_BLOB in_security_buffer;
780 struct smbXsrv_session *session;
781 struct smbXsrv_session_auth0 *auth;
782 struct auth_session_info *session_info;
783 uint16_t out_session_flags;
784 DATA_BLOB out_security_buffer;
785 uint64_t out_session_id;
788 static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq);
789 static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq);
790 static void smbd_smb2_session_setup_auth_return(struct tevent_req *req);
792 static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx,
793 struct tevent_context *ev,
794 struct smbd_smb2_request *smb2req,
795 uint64_t in_session_id,
796 uint8_t in_flags,
797 uint8_t in_security_mode,
798 uint64_t in_previous_session_id,
799 DATA_BLOB in_security_buffer)
801 struct tevent_req *req;
802 struct smbd_smb2_session_setup_state *state;
803 NTSTATUS status;
804 NTTIME now = timeval_to_nttime(&smb2req->request_time);
805 struct tevent_req *subreq;
806 struct smbXsrv_channel_global0 *c = NULL;
807 enum security_user_level seclvl;
809 req = tevent_req_create(mem_ctx, &state,
810 struct smbd_smb2_session_setup_state);
811 if (req == NULL) {
812 return NULL;
814 state->ev = ev;
815 state->smb2req = smb2req;
816 state->in_session_id = in_session_id;
817 state->in_flags = in_flags;
818 state->in_security_mode = in_security_mode;
819 state->in_previous_session_id = in_previous_session_id;
820 state->in_security_buffer = in_security_buffer;
822 if (in_flags & SMB2_SESSION_FLAG_BINDING) {
823 if (smb2req->xconn->protocol < PROTOCOL_SMB2_22) {
824 tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
825 return tevent_req_post(req, ev);
828 if (!smb2req->xconn->client->server_multi_channel_enabled) {
829 tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
830 return tevent_req_post(req, ev);
833 if (in_session_id == 0) {
834 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
835 return tevent_req_post(req, ev);
838 if (smb2req->session == NULL) {
839 tevent_req_nterror(req, NT_STATUS_USER_SESSION_DELETED);
840 return tevent_req_post(req, ev);
843 if (!smb2req->do_signing) {
844 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
845 return tevent_req_post(req, ev);
848 status = smbXsrv_session_find_channel(smb2req->session,
849 smb2req->xconn,
850 &c);
851 if (NT_STATUS_IS_OK(status)) {
852 if (!smb2_signing_key_valid(c->signing_key)) {
853 goto auth;
855 tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
856 return tevent_req_post(req, ev);
860 * OLD: 3.00 NEW 3.02 => INVALID_PARAMETER
861 * OLD: 3.02 NEW 3.00 => INVALID_PARAMETER
862 * OLD: 2.10 NEW 3.02 => ACCESS_DENIED
863 * OLD: 3.02 NEW 2.10 => ACCESS_DENIED
865 if (smb2req->session->global->connection_dialect
866 < SMB2_DIALECT_REVISION_222)
868 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
869 return tevent_req_post(req, ev);
871 if (smb2req->xconn->smb2.server.dialect
872 < SMB2_DIALECT_REVISION_222)
874 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
875 return tevent_req_post(req, ev);
877 if (smb2req->session->global->connection_dialect
878 != smb2req->xconn->smb2.server.dialect)
880 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
881 return tevent_req_post(req, ev);
884 seclvl = security_session_user_level(
885 smb2req->session->global->auth_session_info,
886 NULL);
887 if (seclvl < SECURITY_USER) {
888 tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
889 return tevent_req_post(req, ev);
892 status = smbXsrv_session_add_channel(smb2req->session,
893 smb2req->xconn,
894 &c);
895 if (!NT_STATUS_IS_OK(status)) {
896 tevent_req_nterror(req, status);
897 return tevent_req_post(req, ev);
900 status = smbXsrv_session_update(smb2req->session);
901 if (!NT_STATUS_IS_OK(status)) {
902 tevent_req_nterror(req, status);
903 return tevent_req_post(req, ev);
907 auth:
909 if (state->in_session_id == 0) {
910 /* create a new session */
911 status = smbXsrv_session_create(state->smb2req->xconn,
912 now, &state->session);
913 if (tevent_req_nterror(req, status)) {
914 return tevent_req_post(req, ev);
916 smb2req->session = state->session;
917 } else {
918 if (smb2req->session == NULL) {
919 tevent_req_nterror(req, NT_STATUS_USER_SESSION_DELETED);
920 return tevent_req_post(req, ev);
923 state->session = smb2req->session;
924 status = state->session->status;
925 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
926 status = NT_STATUS_OK;
928 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
929 status = NT_STATUS_OK;
931 if (tevent_req_nterror(req, status)) {
932 return tevent_req_post(req, ev);
934 if (!(in_flags & SMB2_SESSION_FLAG_BINDING)) {
935 state->session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
939 status = smbXsrv_session_find_channel(smb2req->session,
940 smb2req->xconn, &c);
941 if (!NT_STATUS_IS_OK(status)) {
942 tevent_req_nterror(req, status);
943 return tevent_req_post(req, ev);
946 status = smbXsrv_session_find_auth(state->session, smb2req->xconn,
947 now, &state->auth);
948 if (!NT_STATUS_IS_OK(status)) {
949 status = smbXsrv_session_create_auth(state->session,
950 smb2req->xconn, now,
951 in_flags, in_security_mode,
952 &state->auth);
953 if (tevent_req_nterror(req, status)) {
954 return tevent_req_post(req, ev);
958 if (state->auth->gensec == NULL) {
959 status = auth_generic_prepare(state->auth,
960 state->smb2req->xconn->remote_address,
961 state->smb2req->xconn->local_address,
962 "SMB2",
963 &state->auth->gensec);
964 if (tevent_req_nterror(req, status)) {
965 return tevent_req_post(req, ev);
968 gensec_want_feature(state->auth->gensec, GENSEC_FEATURE_SESSION_KEY);
969 gensec_want_feature(state->auth->gensec, GENSEC_FEATURE_UNIX_TOKEN);
970 gensec_want_feature(state->auth->gensec, GENSEC_FEATURE_SMB_TRANSPORT);
972 status = gensec_start_mech_by_oid(state->auth->gensec,
973 GENSEC_OID_SPNEGO);
974 if (tevent_req_nterror(req, status)) {
975 return tevent_req_post(req, ev);
979 status = smbXsrv_session_update(state->session);
980 if (tevent_req_nterror(req, status)) {
981 return tevent_req_post(req, ev);
984 become_root();
985 subreq = gensec_update_send(state, state->ev,
986 state->auth->gensec,
987 state->in_security_buffer);
988 unbecome_root();
989 if (tevent_req_nomem(subreq, req)) {
990 return tevent_req_post(req, ev);
992 tevent_req_set_callback(subreq, smbd_smb2_session_setup_gensec_done, req);
994 return req;
997 static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq)
999 struct tevent_req *req =
1000 tevent_req_callback_data(subreq,
1001 struct tevent_req);
1002 struct smbd_smb2_session_setup_state *state =
1003 tevent_req_data(req,
1004 struct smbd_smb2_session_setup_state);
1005 NTSTATUS status;
1007 become_root();
1008 status = gensec_update_recv(subreq, state,
1009 &state->out_security_buffer);
1010 unbecome_root();
1011 TALLOC_FREE(subreq);
1012 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
1013 !NT_STATUS_IS_OK(status)) {
1014 tevent_req_nterror(req, status);
1015 return;
1018 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1019 state->out_session_id = state->session->global->session_wire_id;
1020 state->smb2req->preauth = state->auth->preauth;
1021 tevent_req_nterror(req, status);
1022 return;
1025 status = gensec_session_info(state->auth->gensec,
1026 state,
1027 &state->session_info);
1028 if (tevent_req_nterror(req, status)) {
1029 return;
1032 if ((state->in_previous_session_id != 0) &&
1033 (state->session->global->session_wire_id !=
1034 state->in_previous_session_id))
1036 subreq = smb2srv_session_close_previous_send(state, state->ev,
1037 state->smb2req->xconn,
1038 state->session_info,
1039 state->in_previous_session_id,
1040 state->session->global->session_wire_id);
1041 if (tevent_req_nomem(subreq, req)) {
1042 return;
1044 tevent_req_set_callback(subreq,
1045 smbd_smb2_session_setup_previous_done,
1046 req);
1047 return;
1050 smbd_smb2_session_setup_auth_return(req);
1053 static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq)
1055 struct tevent_req *req =
1056 tevent_req_callback_data(subreq,
1057 struct tevent_req);
1058 NTSTATUS status;
1060 status = smb2srv_session_close_previous_recv(subreq);
1061 TALLOC_FREE(subreq);
1062 if (tevent_req_nterror(req, status)) {
1063 return;
1066 smbd_smb2_session_setup_auth_return(req);
1069 static void smbd_smb2_session_setup_auth_return(struct tevent_req *req)
1071 struct smbd_smb2_session_setup_state *state =
1072 tevent_req_data(req,
1073 struct smbd_smb2_session_setup_state);
1074 NTSTATUS status;
1076 if (state->in_flags & SMB2_SESSION_FLAG_BINDING) {
1077 status = smbd_smb2_bind_auth_return(state->session,
1078 &state->auth,
1079 state->smb2req,
1080 state->session_info,
1081 &state->out_session_flags,
1082 &state->out_session_id);
1083 if (tevent_req_nterror(req, status)) {
1084 return;
1086 tevent_req_done(req);
1087 return;
1090 if (state->session->global->auth_session_info != NULL) {
1091 status = smbd_smb2_reauth_generic_return(state->session,
1092 &state->auth,
1093 state->smb2req,
1094 state->session_info,
1095 &state->out_session_flags,
1096 &state->out_session_id);
1097 if (tevent_req_nterror(req, status)) {
1098 return;
1100 tevent_req_done(req);
1101 return;
1104 status = smbd_smb2_auth_generic_return(state->session,
1105 &state->auth,
1106 state->smb2req,
1107 state->in_security_mode,
1108 state->session_info,
1109 &state->out_session_flags,
1110 &state->out_session_id);
1111 if (tevent_req_nterror(req, status)) {
1112 return;
1115 tevent_req_done(req);
1116 return;
1119 static NTSTATUS smbd_smb2_session_setup_recv(struct tevent_req *req,
1120 uint16_t *out_session_flags,
1121 TALLOC_CTX *mem_ctx,
1122 DATA_BLOB *out_security_buffer,
1123 uint64_t *out_session_id)
1125 struct smbd_smb2_session_setup_state *state =
1126 tevent_req_data(req,
1127 struct smbd_smb2_session_setup_state);
1128 NTSTATUS status;
1130 if (tevent_req_is_nterror(req, &status)) {
1131 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1132 tevent_req_received(req);
1133 return nt_status_squash(status);
1135 } else {
1136 status = NT_STATUS_OK;
1139 *out_session_flags = state->out_session_flags;
1140 *out_security_buffer = state->out_security_buffer;
1141 *out_session_id = state->out_session_id;
1143 talloc_steal(mem_ctx, out_security_buffer->data);
1144 tevent_req_received(req);
1145 return status;
1148 struct smbd_smb2_session_setup_wrap_state {
1149 struct tevent_context *ev;
1150 struct smbd_smb2_request *smb2req;
1151 uint64_t in_session_id;
1152 uint8_t in_flags;
1153 uint8_t in_security_mode;
1154 uint64_t in_previous_session_id;
1155 DATA_BLOB in_security_buffer;
1156 uint16_t out_session_flags;
1157 DATA_BLOB out_security_buffer;
1158 uint64_t out_session_id;
1159 NTSTATUS error;
1162 static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req *subreq);
1163 static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req *subreq);
1165 static struct tevent_req *smbd_smb2_session_setup_wrap_send(TALLOC_CTX *mem_ctx,
1166 struct tevent_context *ev,
1167 struct smbd_smb2_request *smb2req,
1168 uint64_t in_session_id,
1169 uint8_t in_flags,
1170 uint8_t in_security_mode,
1171 uint64_t in_previous_session_id,
1172 DATA_BLOB in_security_buffer)
1174 struct tevent_req *req;
1175 struct smbd_smb2_session_setup_wrap_state *state;
1176 struct tevent_req *subreq;
1178 req = tevent_req_create(mem_ctx, &state,
1179 struct smbd_smb2_session_setup_wrap_state);
1180 if (req == NULL) {
1181 return NULL;
1183 state->ev = ev;
1184 state->smb2req = smb2req;
1185 state->in_session_id = in_session_id;
1186 state->in_flags = in_flags;
1187 state->in_security_mode = in_security_mode;
1188 state->in_previous_session_id = in_previous_session_id;
1189 state->in_security_buffer = in_security_buffer;
1191 subreq = smbd_smb2_session_setup_send(state, state->ev,
1192 state->smb2req,
1193 state->in_session_id,
1194 state->in_flags,
1195 state->in_security_mode,
1196 state->in_previous_session_id,
1197 state->in_security_buffer);
1198 if (tevent_req_nomem(subreq, req)) {
1199 return tevent_req_post(req, ev);
1201 tevent_req_set_callback(subreq,
1202 smbd_smb2_session_setup_wrap_setup_done, req);
1204 return req;
1207 static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req *subreq)
1209 struct tevent_req *req =
1210 tevent_req_callback_data(subreq,
1211 struct tevent_req);
1212 struct smbd_smb2_session_setup_wrap_state *state =
1213 tevent_req_data(req,
1214 struct smbd_smb2_session_setup_wrap_state);
1215 NTSTATUS status;
1217 status = smbd_smb2_session_setup_recv(subreq,
1218 &state->out_session_flags,
1219 state,
1220 &state->out_security_buffer,
1221 &state->out_session_id);
1222 TALLOC_FREE(subreq);
1223 if (NT_STATUS_IS_OK(status)) {
1224 tevent_req_done(req);
1225 return;
1227 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1228 tevent_req_nterror(req, status);
1229 return;
1232 if (state->smb2req->session == NULL) {
1233 tevent_req_nterror(req, status);
1234 return;
1237 state->error = status;
1239 subreq = smb2srv_session_shutdown_send(state, state->ev,
1240 state->smb2req->session,
1241 state->smb2req);
1242 if (tevent_req_nomem(subreq, req)) {
1243 return;
1245 tevent_req_set_callback(subreq,
1246 smbd_smb2_session_setup_wrap_shutdown_done,
1247 req);
1250 static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req *subreq)
1252 struct tevent_req *req =
1253 tevent_req_callback_data(subreq,
1254 struct tevent_req);
1255 struct smbd_smb2_session_setup_wrap_state *state =
1256 tevent_req_data(req,
1257 struct smbd_smb2_session_setup_wrap_state);
1258 NTSTATUS status;
1260 status = smb2srv_session_shutdown_recv(subreq);
1261 TALLOC_FREE(subreq);
1262 if (tevent_req_nterror(req, status)) {
1263 return;
1267 * we may need to sign the response, so we need to keep
1268 * the session until the response is sent to the wire.
1270 talloc_steal(state->smb2req, state->smb2req->session);
1272 tevent_req_nterror(req, state->error);
1275 static NTSTATUS smbd_smb2_session_setup_wrap_recv(struct tevent_req *req,
1276 uint16_t *out_session_flags,
1277 TALLOC_CTX *mem_ctx,
1278 DATA_BLOB *out_security_buffer,
1279 uint64_t *out_session_id)
1281 struct smbd_smb2_session_setup_wrap_state *state =
1282 tevent_req_data(req,
1283 struct smbd_smb2_session_setup_wrap_state);
1284 NTSTATUS status;
1286 if (tevent_req_is_nterror(req, &status)) {
1287 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1288 tevent_req_received(req);
1289 return nt_status_squash(status);
1291 } else {
1292 status = NT_STATUS_OK;
1295 *out_session_flags = state->out_session_flags;
1296 *out_security_buffer = state->out_security_buffer;
1297 *out_session_id = state->out_session_id;
1299 talloc_steal(mem_ctx, out_security_buffer->data);
1300 tevent_req_received(req);
1301 return status;
1304 static struct tevent_req *smbd_smb2_logoff_send(TALLOC_CTX *mem_ctx,
1305 struct tevent_context *ev,
1306 struct smbd_smb2_request *smb2req);
1307 static NTSTATUS smbd_smb2_logoff_recv(struct tevent_req *req);
1308 static void smbd_smb2_request_logoff_done(struct tevent_req *subreq);
1310 NTSTATUS smbd_smb2_request_process_logoff(struct smbd_smb2_request *req)
1312 NTSTATUS status;
1313 struct tevent_req *subreq = NULL;
1315 status = smbd_smb2_request_verify_sizes(req, 0x04);
1316 if (!NT_STATUS_IS_OK(status)) {
1317 return smbd_smb2_request_error(req, status);
1320 subreq = smbd_smb2_logoff_send(req, req->sconn->ev_ctx, req);
1321 if (subreq == NULL) {
1322 return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
1324 tevent_req_set_callback(subreq, smbd_smb2_request_logoff_done, req);
1327 * Avoid sending a STATUS_PENDING message, it's very likely
1328 * the client won't expect that.
1330 return smbd_smb2_request_pending_queue(req, subreq, 0);
1333 static void smbd_smb2_request_logoff_done(struct tevent_req *subreq)
1335 struct smbd_smb2_request *smb2req =
1336 tevent_req_callback_data(subreq,
1337 struct smbd_smb2_request);
1338 DATA_BLOB outbody;
1339 NTSTATUS status;
1340 NTSTATUS error;
1342 status = smbd_smb2_logoff_recv(subreq);
1343 TALLOC_FREE(subreq);
1344 if (!NT_STATUS_IS_OK(status)) {
1345 error = smbd_smb2_request_error(smb2req, status);
1346 if (!NT_STATUS_IS_OK(error)) {
1347 smbd_server_connection_terminate(smb2req->xconn,
1348 nt_errstr(error));
1349 return;
1351 return;
1354 outbody = smbd_smb2_generate_outbody(smb2req, 0x04);
1355 if (outbody.data == NULL) {
1356 error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
1357 if (!NT_STATUS_IS_OK(error)) {
1358 smbd_server_connection_terminate(smb2req->xconn,
1359 nt_errstr(error));
1360 return;
1362 return;
1365 SSVAL(outbody.data, 0x00, 0x04); /* struct size */
1366 SSVAL(outbody.data, 0x02, 0); /* reserved */
1368 error = smbd_smb2_request_done(smb2req, outbody, NULL);
1369 if (!NT_STATUS_IS_OK(error)) {
1370 smbd_server_connection_terminate(smb2req->xconn,
1371 nt_errstr(error));
1372 return;
1376 struct smbd_smb2_logoff_state {
1377 struct smbd_smb2_request *smb2req;
1380 static void smbd_smb2_logoff_shutdown_done(struct tevent_req *subreq);
1382 static struct tevent_req *smbd_smb2_logoff_send(TALLOC_CTX *mem_ctx,
1383 struct tevent_context *ev,
1384 struct smbd_smb2_request *smb2req)
1386 struct tevent_req *req;
1387 struct smbd_smb2_logoff_state *state;
1388 struct tevent_req *subreq;
1390 req = tevent_req_create(mem_ctx, &state,
1391 struct smbd_smb2_logoff_state);
1392 if (req == NULL) {
1393 return NULL;
1395 state->smb2req = smb2req;
1397 subreq = smb2srv_session_shutdown_send(state, ev,
1398 smb2req->session,
1399 smb2req);
1400 if (tevent_req_nomem(subreq, req)) {
1401 return tevent_req_post(req, ev);
1403 tevent_req_set_callback(subreq, smbd_smb2_logoff_shutdown_done, req);
1405 return req;
1408 static void smbd_smb2_logoff_shutdown_done(struct tevent_req *subreq)
1410 struct tevent_req *req = tevent_req_callback_data(
1411 subreq, struct tevent_req);
1412 struct smbd_smb2_logoff_state *state = tevent_req_data(
1413 req, struct smbd_smb2_logoff_state);
1414 NTSTATUS status;
1415 bool ok;
1416 const struct GUID *client_guid =
1417 &state->smb2req->session->client->connections->smb2.client.guid;
1419 status = smb2srv_session_shutdown_recv(subreq);
1420 if (tevent_req_nterror(req, status)) {
1421 return;
1423 TALLOC_FREE(subreq);
1425 if (!GUID_all_zero(client_guid)) {
1426 ok = remote_arch_cache_delete(client_guid);
1427 if (!ok) {
1428 /* Most likely not an error, but not in cache */
1429 DBG_DEBUG("Deletion from remote arch cache failed\n");
1434 * As we've been awoken, we may have changed
1435 * uid in the meantime. Ensure we're still
1436 * root (SMB2_OP_LOGOFF has .as_root = true).
1438 change_to_root_user();
1440 status = smbXsrv_session_logoff(state->smb2req->session);
1441 if (tevent_req_nterror(req, status)) {
1442 return;
1446 * we may need to sign the response, so we need to keep
1447 * the session until the response is sent to the wire.
1449 talloc_steal(state->smb2req, state->smb2req->session);
1451 tevent_req_done(req);
1454 static NTSTATUS smbd_smb2_logoff_recv(struct tevent_req *req)
1456 return tevent_req_simple_recv_ntstatus(req);