2 Unix SMB/CIFS implementation.
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/>.
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../libcli/smb/smb_common.h"
26 #include "../auth/gensec/gensec.h"
28 #include "../lib/tsocket/tsocket.h"
29 #include "../libcli/security/security.h"
30 #include "../lib/util/tevent_ntstatus.h"
31 #include "lib/crypto/sha512.h"
32 #include "lib/crypto/aes.h"
33 #include "lib/crypto/aes_ccm_128.h"
34 #include "lib/crypto/aes_gcm_128.h"
37 #define DBGC_CLASS DBGC_SMB2
39 static struct tevent_req *smbd_smb2_session_setup_wrap_send(TALLOC_CTX *mem_ctx,
40 struct tevent_context *ev,
41 struct smbd_smb2_request *smb2req,
42 uint64_t in_session_id,
44 uint8_t in_security_mode,
45 uint64_t in_previous_session_id,
46 DATA_BLOB in_security_buffer);
47 static NTSTATUS smbd_smb2_session_setup_wrap_recv(struct tevent_req *req,
48 uint16_t *out_session_flags,
50 DATA_BLOB *out_security_buffer,
51 uint64_t *out_session_id);
53 static void smbd_smb2_request_sesssetup_done(struct tevent_req *subreq);
55 NTSTATUS smbd_smb2_request_process_sesssetup(struct smbd_smb2_request *smb2req)
58 const uint8_t *inbody;
59 uint64_t in_session_id;
61 uint8_t in_security_mode;
62 uint64_t in_previous_session_id;
63 uint16_t in_security_offset;
64 uint16_t in_security_length;
65 DATA_BLOB in_security_buffer;
67 struct tevent_req *subreq;
69 status = smbd_smb2_request_verify_sizes(smb2req, 0x19);
70 if (!NT_STATUS_IS_OK(status)) {
71 return smbd_smb2_request_error(smb2req, status);
73 inhdr = SMBD_SMB2_IN_HDR_PTR(smb2req);
74 inbody = SMBD_SMB2_IN_BODY_PTR(smb2req);
76 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
78 in_flags = CVAL(inbody, 0x02);
79 in_security_mode = CVAL(inbody, 0x03);
80 /* Capabilities = IVAL(inbody, 0x04) */
81 /* Channel = IVAL(inbody, 0x08) */
82 in_security_offset = SVAL(inbody, 0x0C);
83 in_security_length = SVAL(inbody, 0x0E);
84 in_previous_session_id = BVAL(inbody, 0x10);
86 if (in_security_offset != (SMB2_HDR_BODY + SMBD_SMB2_IN_BODY_LEN(smb2req))) {
87 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
90 if (in_security_length > SMBD_SMB2_IN_DYN_LEN(smb2req)) {
91 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
94 in_security_buffer.data = SMBD_SMB2_IN_DYN_PTR(smb2req);
95 in_security_buffer.length = in_security_length;
97 subreq = smbd_smb2_session_setup_wrap_send(smb2req,
98 smb2req->sconn->ev_ctx,
103 in_previous_session_id,
105 if (subreq == NULL) {
106 return smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
108 tevent_req_set_callback(subreq, smbd_smb2_request_sesssetup_done, smb2req);
111 * Avoid sending a STATUS_PENDING message, which
112 * matches a Windows Server and avoids problems with
115 * Even after 90 seconds a Windows Server doesn't return
116 * STATUS_PENDING if using NTLMSSP against a non reachable
119 return smbd_smb2_request_pending_queue(smb2req, subreq, 0);
122 static void smbd_smb2_request_sesssetup_done(struct tevent_req *subreq)
124 struct smbd_smb2_request *smb2req =
125 tevent_req_callback_data(subreq,
126 struct smbd_smb2_request);
130 uint16_t out_session_flags = 0;
131 uint64_t out_session_id = 0;
132 uint16_t out_security_offset;
133 DATA_BLOB out_security_buffer = data_blob_null;
135 NTSTATUS error; /* transport error */
137 status = smbd_smb2_session_setup_wrap_recv(subreq,
140 &out_security_buffer,
143 if (!NT_STATUS_IS_OK(status) &&
144 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
145 status = nt_status_squash(status);
146 error = smbd_smb2_request_error(smb2req, status);
147 if (!NT_STATUS_IS_OK(error)) {
148 smbd_server_connection_terminate(smb2req->xconn,
155 out_security_offset = SMB2_HDR_BODY + 0x08;
157 outhdr = SMBD_SMB2_OUT_HDR_PTR(smb2req);
159 outbody = smbd_smb2_generate_outbody(smb2req, 0x08);
160 if (outbody.data == NULL) {
161 error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
162 if (!NT_STATUS_IS_OK(error)) {
163 smbd_server_connection_terminate(smb2req->xconn,
170 SBVAL(outhdr, SMB2_HDR_SESSION_ID, out_session_id);
172 SSVAL(outbody.data, 0x00, 0x08 + 1); /* struct size */
173 SSVAL(outbody.data, 0x02,
174 out_session_flags); /* session flags */
175 SSVAL(outbody.data, 0x04,
176 out_security_offset); /* security buffer offset */
177 SSVAL(outbody.data, 0x06,
178 out_security_buffer.length); /* security buffer length */
180 outdyn = out_security_buffer;
182 error = smbd_smb2_request_done_ex(smb2req, status, outbody, &outdyn,
184 if (!NT_STATUS_IS_OK(error)) {
185 smbd_server_connection_terminate(smb2req->xconn,
191 static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
192 struct smbXsrv_session_auth0 **_auth,
193 struct smbd_smb2_request *smb2req,
194 uint8_t in_security_mode,
195 struct auth_session_info *session_info,
196 uint16_t *out_session_flags,
197 uint64_t *out_session_id)
201 uint8_t session_key[16];
202 struct smbXsrv_session *x = session;
203 struct smbXsrv_session_auth0 *auth = *_auth;
204 struct smbXsrv_connection *xconn = smb2req->xconn;
211 struct _derivation signing;
212 struct _derivation encryption;
213 struct _derivation decryption;
214 struct _derivation application;
219 if (xconn->protocol >= PROTOCOL_SMB3_10) {
220 struct smbXsrv_preauth *preauth;
221 struct _derivation *d;
223 struct hc_sha512state sctx;
225 preauth = talloc_move(smb2req, &auth->preauth);
227 samba_SHA512_Init(&sctx);
228 samba_SHA512_Update(&sctx, preauth->sha512_value,
229 sizeof(preauth->sha512_value));
230 for (i = 1; i < smb2req->in.vector_count; i++) {
231 samba_SHA512_Update(&sctx,
232 smb2req->in.vector[i].iov_base,
233 smb2req->in.vector[i].iov_len);
235 samba_SHA512_Final(preauth->sha512_value, &sctx);
237 p = data_blob_const(preauth->sha512_value,
238 sizeof(preauth->sha512_value));
240 d = &derivation.signing;
241 d->label = data_blob_string_const_null("SMBSigningKey");
244 d = &derivation.decryption;
245 d->label = data_blob_string_const_null("SMBC2SCipherKey");
248 d = &derivation.encryption;
249 d->label = data_blob_string_const_null("SMBS2CCipherKey");
252 d = &derivation.application;
253 d->label = data_blob_string_const_null("SMBAppKey");
256 } else if (xconn->protocol >= PROTOCOL_SMB2_24) {
257 struct _derivation *d;
259 d = &derivation.signing;
260 d->label = data_blob_string_const_null("SMB2AESCMAC");
261 d->context = data_blob_string_const_null("SmbSign");
263 d = &derivation.decryption;
264 d->label = data_blob_string_const_null("SMB2AESCCM");
265 d->context = data_blob_string_const_null("ServerIn ");
267 d = &derivation.encryption;
268 d->label = data_blob_string_const_null("SMB2AESCCM");
269 d->context = data_blob_string_const_null("ServerOut");
271 d = &derivation.application;
272 d->label = data_blob_string_const_null("SMB2APP");
273 d->context = data_blob_string_const_null("SmbRpc");
276 if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
277 (xconn->smb2.server.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED))
279 x->global->signing_flags = SMBXSRV_SIGNING_REQUIRED;
282 if ((lp_smb_encrypt(-1) >= SMB_SIGNING_DESIRED) &&
283 (xconn->smb2.client.capabilities & SMB2_CAP_ENCRYPTION)) {
284 x->global->encryption_flags = SMBXSRV_ENCRYPTION_DESIRED;
287 if (lp_smb_encrypt(-1) == SMB_SIGNING_REQUIRED) {
288 x->global->encryption_flags = SMBXSRV_ENCRYPTION_REQUIRED |
289 SMBXSRV_ENCRYPTION_DESIRED;
292 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
293 if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
294 *out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
296 /* force no signing */
297 x->global->signing_flags &= ~SMBXSRV_SIGNING_REQUIRED;
298 /* we map anonymous to guest internally */
302 if (guest && (x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED)) {
303 DEBUG(1,("reject guest session as encryption is required\n"));
304 return NT_STATUS_ACCESS_DENIED;
307 if (xconn->smb2.server.cipher == 0) {
308 if (x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
309 DEBUG(1,("reject session with dialect[0x%04X] "
310 "as encryption is required\n",
311 xconn->smb2.server.dialect));
312 return NT_STATUS_ACCESS_DENIED;
315 x->global->channels[0].encryption_cipher = xconn->smb2.server.cipher;
318 if (x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
319 *out_session_flags |= SMB2_SESSION_FLAG_ENCRYPT_DATA;
322 ZERO_STRUCT(session_key);
323 memcpy(session_key, session_info->session_key.data,
324 MIN(session_info->session_key.length, sizeof(session_key)));
326 x->global->signing_key = data_blob_talloc(x->global,
328 sizeof(session_key));
329 if (x->global->signing_key.data == NULL) {
330 ZERO_STRUCT(session_key);
331 return NT_STATUS_NO_MEMORY;
334 if (xconn->protocol >= PROTOCOL_SMB2_24) {
335 struct _derivation *d = &derivation.signing;
337 smb2_key_derivation(session_key, sizeof(session_key),
338 d->label.data, d->label.length,
339 d->context.data, d->context.length,
340 x->global->signing_key.data);
343 if (xconn->protocol >= PROTOCOL_SMB2_24) {
344 struct _derivation *d = &derivation.decryption;
346 x->global->decryption_key = data_blob_talloc(x->global,
348 sizeof(session_key));
349 if (x->global->decryption_key.data == NULL) {
350 ZERO_STRUCT(session_key);
351 return NT_STATUS_NO_MEMORY;
354 smb2_key_derivation(session_key, sizeof(session_key),
355 d->label.data, d->label.length,
356 d->context.data, d->context.length,
357 x->global->decryption_key.data);
360 if (xconn->protocol >= PROTOCOL_SMB2_24) {
361 struct _derivation *d = &derivation.encryption;
364 x->global->encryption_key = data_blob_talloc(x->global,
366 sizeof(session_key));
367 if (x->global->encryption_key.data == NULL) {
368 ZERO_STRUCT(session_key);
369 return NT_STATUS_NO_MEMORY;
372 smb2_key_derivation(session_key, sizeof(session_key),
373 d->label.data, d->label.length,
374 d->context.data, d->context.length,
375 x->global->encryption_key.data);
378 * CCM and GCM algorithms must never have their
379 * nonce wrap, or the security of the whole
380 * communication and the keys is destroyed.
381 * We must drop the connection once we have
382 * transfered too much data.
384 * NOTE: We assume nonces greater than 8 bytes.
386 generate_random_buffer((uint8_t *)&x->nonce_high_random,
387 sizeof(x->nonce_high_random));
388 switch (xconn->smb2.server.cipher) {
389 case SMB2_ENCRYPTION_AES128_CCM:
390 nonce_size = AES_CCM_128_NONCE_SIZE;
392 case SMB2_ENCRYPTION_AES128_GCM:
393 nonce_size = AES_GCM_128_IV_SIZE;
399 x->nonce_high_max = SMB2_NONCE_HIGH_MAX(nonce_size);
404 x->global->application_key = data_blob_dup_talloc(x->global,
405 x->global->signing_key);
406 if (x->global->application_key.data == NULL) {
407 ZERO_STRUCT(session_key);
408 return NT_STATUS_NO_MEMORY;
411 if (xconn->protocol >= PROTOCOL_SMB2_24) {
412 struct _derivation *d = &derivation.application;
414 smb2_key_derivation(session_key, sizeof(session_key),
415 d->label.data, d->label.length,
416 d->context.data, d->context.length,
417 x->global->application_key.data);
420 if (xconn->protocol >= PROTOCOL_SMB3_00 && lp_debug_encryption()) {
421 DEBUG(0, ("debug encryption: dumping generated session keys\n"));
422 DEBUGADD(0, ("Session Id "));
423 dump_data(0, (uint8_t*)&session->global->session_wire_id,
424 sizeof(session->global->session_wire_id));
425 DEBUGADD(0, ("Session Key "));
426 dump_data(0, session_key, sizeof(session_key));
427 DEBUGADD(0, ("Signing Key "));
428 dump_data(0, x->global->signing_key.data,
429 x->global->signing_key.length);
430 DEBUGADD(0, ("App Key "));
431 dump_data(0, x->global->application_key.data,
432 x->global->application_key.length);
434 /* In server code, ServerIn is the decryption key */
436 DEBUGADD(0, ("ServerIn Key "));
437 dump_data(0, x->global->decryption_key.data,
438 x->global->decryption_key.length);
439 DEBUGADD(0, ("ServerOut Key "));
440 dump_data(0, x->global->encryption_key.data,
441 x->global->encryption_key.length);
444 ZERO_STRUCT(session_key);
446 x->global->channels[0].signing_key = data_blob_dup_talloc(x->global->channels,
447 x->global->signing_key);
448 if (x->global->channels[0].signing_key.data == NULL) {
449 return NT_STATUS_NO_MEMORY;
452 data_blob_clear_free(&session_info->session_key);
453 session_info->session_key = data_blob_dup_talloc(session_info,
454 x->global->application_key);
455 if (session_info->session_key.data == NULL) {
456 return NT_STATUS_NO_MEMORY;
459 session->compat = talloc_zero(session, struct user_struct);
460 if (session->compat == NULL) {
461 return NT_STATUS_NO_MEMORY;
463 session->compat->session = session;
464 session->compat->homes_snum = -1;
465 session->compat->session_info = session_info;
466 session->compat->session_keystr = NULL;
467 session->compat->vuid = session->global->session_wire_id;
468 DLIST_ADD(smb2req->sconn->users, session->compat);
469 smb2req->sconn->num_users++;
471 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
472 session->compat->homes_snum =
473 register_homes_share(session_info->unix_info->unix_name);
476 set_current_user_info(session_info->unix_info->sanitized_username,
477 session_info->unix_info->unix_name,
478 session_info->info->domain_name);
480 reload_services(smb2req->sconn, conn_snum_used, true);
482 session->status = NT_STATUS_OK;
483 session->global->auth_session_info = talloc_move(session->global,
485 session->global->auth_session_info_seqnum += 1;
486 for (i=0; i < session->global->num_channels; i++) {
487 struct smbXsrv_channel_global0 *_c =
488 &session->global->channels[i];
490 _c->auth_session_info_seqnum =
491 session->global->auth_session_info_seqnum;
493 session->global->auth_time = timeval_to_nttime(&smb2req->request_time);
494 session->global->expiration_time = gensec_expire_time(auth->gensec);
496 if (!session_claim(session)) {
497 DEBUG(1, ("smb2: Failed to claim session "
499 (unsigned long long)session->compat->vuid));
500 return NT_STATUS_LOGON_FAILURE;
504 status = smbXsrv_session_update(session);
505 if (!NT_STATUS_IS_OK(status)) {
506 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
507 (unsigned long long)session->compat->vuid,
509 return NT_STATUS_LOGON_FAILURE;
513 * we attach the session to the request
514 * so that the response can be signed
517 smb2req->do_signing = true;
520 global_client_caps |= (CAP_LEVEL_II_OPLOCKS|CAP_STATUS32);
522 *out_session_id = session->global->session_wire_id;
523 smb2req->last_session_id = session->global->session_wire_id;
528 static NTSTATUS smbd_smb2_reauth_generic_return(struct smbXsrv_session *session,
529 struct smbXsrv_session_auth0 **_auth,
530 struct smbd_smb2_request *smb2req,
531 struct auth_session_info *session_info,
532 uint16_t *out_session_flags,
533 uint64_t *out_session_id)
536 struct smbXsrv_session *x = session;
537 struct smbXsrv_session_auth0 *auth = *_auth;
538 struct smbXsrv_connection *xconn = smb2req->xconn;
543 data_blob_clear_free(&session_info->session_key);
544 session_info->session_key = data_blob_dup_talloc(session_info,
545 x->global->application_key);
546 if (session_info->session_key.data == NULL) {
547 return NT_STATUS_NO_MEMORY;
550 session->compat->session_info = session_info;
551 session->compat->vuid = session->global->session_wire_id;
553 session->compat->homes_snum =
554 register_homes_share(session_info->unix_info->unix_name);
556 set_current_user_info(session_info->unix_info->sanitized_username,
557 session_info->unix_info->unix_name,
558 session_info->info->domain_name);
560 reload_services(smb2req->sconn, conn_snum_used, true);
562 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
563 smb2req->do_signing = true;
566 session->status = NT_STATUS_OK;
567 TALLOC_FREE(session->global->auth_session_info);
568 session->global->auth_session_info = talloc_move(session->global,
570 session->global->auth_session_info_seqnum += 1;
571 for (i=0; i < session->global->num_channels; i++) {
572 struct smbXsrv_channel_global0 *_c =
573 &session->global->channels[i];
575 _c->auth_session_info_seqnum =
576 session->global->auth_session_info_seqnum;
578 session->global->auth_time = timeval_to_nttime(&smb2req->request_time);
579 session->global->expiration_time = gensec_expire_time(auth->gensec);
582 status = smbXsrv_session_update(session);
583 if (!NT_STATUS_IS_OK(status)) {
584 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
585 (unsigned long long)session->compat->vuid,
587 return NT_STATUS_LOGON_FAILURE;
590 conn_clear_vuid_caches(xconn->client->sconn, session->compat->vuid);
592 *out_session_id = session->global->session_wire_id;
597 static NTSTATUS smbd_smb2_bind_auth_return(struct smbXsrv_session *session,
598 struct smbXsrv_session_auth0 **_auth,
599 struct smbd_smb2_request *smb2req,
600 struct auth_session_info *session_info,
601 uint16_t *out_session_flags,
602 uint64_t *out_session_id)
605 struct smbXsrv_session *x = session;
606 struct smbXsrv_session_auth0 *auth = *_auth;
607 struct smbXsrv_connection *xconn = smb2req->xconn;
608 struct smbXsrv_channel_global0 *c = NULL;
609 uint8_t session_key[16];
616 struct _derivation signing;
622 if (xconn->protocol >= PROTOCOL_SMB3_10) {
623 struct smbXsrv_preauth *preauth;
624 struct _derivation *d;
626 struct hc_sha512state sctx;
628 preauth = talloc_move(smb2req, &auth->preauth);
630 samba_SHA512_Init(&sctx);
631 samba_SHA512_Update(&sctx, preauth->sha512_value,
632 sizeof(preauth->sha512_value));
633 for (i = 1; i < smb2req->in.vector_count; i++) {
634 samba_SHA512_Update(&sctx,
635 smb2req->in.vector[i].iov_base,
636 smb2req->in.vector[i].iov_len);
638 samba_SHA512_Final(preauth->sha512_value, &sctx);
640 p = data_blob_const(preauth->sha512_value,
641 sizeof(preauth->sha512_value));
643 d = &derivation.signing;
644 d->label = data_blob_string_const_null("SMBSigningKey");
647 } else if (xconn->protocol >= PROTOCOL_SMB2_24) {
648 struct _derivation *d;
650 d = &derivation.signing;
651 d->label = data_blob_string_const_null("SMB2AESCMAC");
652 d->context = data_blob_string_const_null("SmbSign");
655 status = smbXsrv_session_find_channel(session, xconn, &c);
656 if (!NT_STATUS_IS_OK(status)) {
660 ok = security_token_is_sid(session_info->security_token,
661 &x->global->auth_session_info->security_token->sids[0]);
663 return NT_STATUS_NOT_SUPPORTED;
666 if (session_info->session_key.length == 0) {
667 /* See [MS-SMB2] 3.3.5.2.4 for the return code. */
668 return NT_STATUS_NOT_SUPPORTED;
671 ZERO_STRUCT(session_key);
672 memcpy(session_key, session_info->session_key.data,
673 MIN(session_info->session_key.length, sizeof(session_key)));
675 c->signing_key = data_blob_talloc(x->global,
677 sizeof(session_key));
678 if (c->signing_key.data == NULL) {
679 ZERO_STRUCT(session_key);
680 return NT_STATUS_NO_MEMORY;
683 if (xconn->protocol >= PROTOCOL_SMB2_24) {
684 struct _derivation *d = &derivation.signing;
686 smb2_key_derivation(session_key, sizeof(session_key),
687 d->label.data, d->label.length,
688 d->context.data, d->context.length,
689 c->signing_key.data);
691 ZERO_STRUCT(session_key);
694 status = smbXsrv_session_update(session);
695 if (!NT_STATUS_IS_OK(status)) {
696 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
697 (unsigned long long)session->compat->vuid,
699 return NT_STATUS_LOGON_FAILURE;
702 *out_session_id = session->global->session_wire_id;
707 struct smbd_smb2_session_setup_state {
708 struct tevent_context *ev;
709 struct smbd_smb2_request *smb2req;
710 uint64_t in_session_id;
712 uint8_t in_security_mode;
713 uint64_t in_previous_session_id;
714 DATA_BLOB in_security_buffer;
715 struct smbXsrv_session *session;
716 struct smbXsrv_session_auth0 *auth;
717 struct auth_session_info *session_info;
718 uint16_t out_session_flags;
719 DATA_BLOB out_security_buffer;
720 uint64_t out_session_id;
723 static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq);
724 static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq);
725 static void smbd_smb2_session_setup_auth_return(struct tevent_req *req);
727 static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx,
728 struct tevent_context *ev,
729 struct smbd_smb2_request *smb2req,
730 uint64_t in_session_id,
732 uint8_t in_security_mode,
733 uint64_t in_previous_session_id,
734 DATA_BLOB in_security_buffer)
736 struct tevent_req *req;
737 struct smbd_smb2_session_setup_state *state;
739 NTTIME now = timeval_to_nttime(&smb2req->request_time);
740 struct tevent_req *subreq;
741 struct smbXsrv_channel_global0 *c = NULL;
742 enum security_user_level seclvl;
744 req = tevent_req_create(mem_ctx, &state,
745 struct smbd_smb2_session_setup_state);
750 state->smb2req = smb2req;
751 state->in_session_id = in_session_id;
752 state->in_flags = in_flags;
753 state->in_security_mode = in_security_mode;
754 state->in_previous_session_id = in_previous_session_id;
755 state->in_security_buffer = in_security_buffer;
757 if (in_flags & SMB2_SESSION_FLAG_BINDING) {
758 if (smb2req->xconn->protocol < PROTOCOL_SMB2_22) {
759 tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
760 return tevent_req_post(req, ev);
763 if (!smb2req->xconn->client->server_multi_channel_enabled) {
764 tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
765 return tevent_req_post(req, ev);
768 if (in_session_id == 0) {
769 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
770 return tevent_req_post(req, ev);
773 if (smb2req->session == NULL) {
774 tevent_req_nterror(req, NT_STATUS_USER_SESSION_DELETED);
775 return tevent_req_post(req, ev);
778 if (!smb2req->do_signing) {
779 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
780 return tevent_req_post(req, ev);
783 status = smbXsrv_session_find_channel(smb2req->session,
786 if (NT_STATUS_IS_OK(status)) {
787 if (c->signing_key.length == 0) {
790 tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
791 return tevent_req_post(req, ev);
795 * OLD: 3.00 NEW 3.02 => INVALID_PARAMETER
796 * OLD: 3.02 NEW 3.00 => INVALID_PARAMETER
797 * OLD: 2.10 NEW 3.02 => ACCESS_DENIED
798 * OLD: 3.02 NEW 2.10 => ACCESS_DENIED
800 if (smb2req->session->global->connection_dialect
801 < SMB2_DIALECT_REVISION_222)
803 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
804 return tevent_req_post(req, ev);
806 if (smb2req->xconn->smb2.server.dialect
807 < SMB2_DIALECT_REVISION_222)
809 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
810 return tevent_req_post(req, ev);
812 if (smb2req->session->global->connection_dialect
813 != smb2req->xconn->smb2.server.dialect)
815 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
816 return tevent_req_post(req, ev);
819 seclvl = security_session_user_level(
820 smb2req->session->global->auth_session_info,
822 if (seclvl < SECURITY_USER) {
823 tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
824 return tevent_req_post(req, ev);
827 status = smbXsrv_session_add_channel(smb2req->session,
830 if (!NT_STATUS_IS_OK(status)) {
831 tevent_req_nterror(req, status);
832 return tevent_req_post(req, ev);
835 status = smbXsrv_session_update(smb2req->session);
836 if (!NT_STATUS_IS_OK(status)) {
837 tevent_req_nterror(req, status);
838 return tevent_req_post(req, ev);
844 if (state->in_session_id == 0) {
845 /* create a new session */
846 status = smbXsrv_session_create(state->smb2req->xconn,
847 now, &state->session);
848 if (tevent_req_nterror(req, status)) {
849 return tevent_req_post(req, ev);
851 smb2req->session = state->session;
853 if (smb2req->session == NULL) {
854 tevent_req_nterror(req, NT_STATUS_USER_SESSION_DELETED);
855 return tevent_req_post(req, ev);
858 state->session = smb2req->session;
859 status = state->session->status;
860 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
861 status = NT_STATUS_OK;
863 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
864 status = NT_STATUS_OK;
866 if (tevent_req_nterror(req, status)) {
867 return tevent_req_post(req, ev);
869 if (!(in_flags & SMB2_SESSION_FLAG_BINDING)) {
870 state->session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
874 status = smbXsrv_session_find_channel(smb2req->session,
876 if (!NT_STATUS_IS_OK(status)) {
877 tevent_req_nterror(req, status);
878 return tevent_req_post(req, ev);
881 status = smbXsrv_session_find_auth(state->session, smb2req->xconn,
883 if (!NT_STATUS_IS_OK(status)) {
884 status = smbXsrv_session_create_auth(state->session,
886 in_flags, in_security_mode,
888 if (tevent_req_nterror(req, status)) {
889 return tevent_req_post(req, ev);
893 if (state->auth->gensec == NULL) {
894 status = auth_generic_prepare(state->auth,
895 state->smb2req->xconn->remote_address,
896 state->smb2req->xconn->local_address,
898 &state->auth->gensec);
899 if (tevent_req_nterror(req, status)) {
900 return tevent_req_post(req, ev);
903 gensec_want_feature(state->auth->gensec, GENSEC_FEATURE_SESSION_KEY);
904 gensec_want_feature(state->auth->gensec, GENSEC_FEATURE_UNIX_TOKEN);
905 gensec_want_feature(state->auth->gensec, GENSEC_FEATURE_SMB_TRANSPORT);
907 status = gensec_start_mech_by_oid(state->auth->gensec,
909 if (tevent_req_nterror(req, status)) {
910 return tevent_req_post(req, ev);
914 status = smbXsrv_session_update(state->session);
915 if (tevent_req_nterror(req, status)) {
916 return tevent_req_post(req, ev);
920 subreq = gensec_update_send(state, state->ev,
922 state->in_security_buffer);
924 if (tevent_req_nomem(subreq, req)) {
925 return tevent_req_post(req, ev);
927 tevent_req_set_callback(subreq, smbd_smb2_session_setup_gensec_done, req);
932 static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq)
934 struct tevent_req *req =
935 tevent_req_callback_data(subreq,
937 struct smbd_smb2_session_setup_state *state =
939 struct smbd_smb2_session_setup_state);
943 status = gensec_update_recv(subreq, state,
944 &state->out_security_buffer);
947 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
948 !NT_STATUS_IS_OK(status)) {
949 tevent_req_nterror(req, status);
953 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
954 state->out_session_id = state->session->global->session_wire_id;
955 state->smb2req->preauth = state->auth->preauth;
956 tevent_req_nterror(req, status);
960 status = gensec_session_info(state->auth->gensec,
962 &state->session_info);
963 if (tevent_req_nterror(req, status)) {
967 if ((state->in_previous_session_id != 0) &&
968 (state->session->global->session_wire_id !=
969 state->in_previous_session_id))
971 subreq = smb2srv_session_close_previous_send(state, state->ev,
972 state->smb2req->xconn,
974 state->in_previous_session_id,
975 state->session->global->session_wire_id);
976 if (tevent_req_nomem(subreq, req)) {
979 tevent_req_set_callback(subreq,
980 smbd_smb2_session_setup_previous_done,
985 smbd_smb2_session_setup_auth_return(req);
988 static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq)
990 struct tevent_req *req =
991 tevent_req_callback_data(subreq,
995 status = smb2srv_session_close_previous_recv(subreq);
997 if (tevent_req_nterror(req, status)) {
1001 smbd_smb2_session_setup_auth_return(req);
1004 static void smbd_smb2_session_setup_auth_return(struct tevent_req *req)
1006 struct smbd_smb2_session_setup_state *state =
1007 tevent_req_data(req,
1008 struct smbd_smb2_session_setup_state);
1011 if (state->in_flags & SMB2_SESSION_FLAG_BINDING) {
1012 status = smbd_smb2_bind_auth_return(state->session,
1015 state->session_info,
1016 &state->out_session_flags,
1017 &state->out_session_id);
1018 if (tevent_req_nterror(req, status)) {
1021 tevent_req_done(req);
1025 if (state->session->global->auth_session_info != NULL) {
1026 status = smbd_smb2_reauth_generic_return(state->session,
1029 state->session_info,
1030 &state->out_session_flags,
1031 &state->out_session_id);
1032 if (tevent_req_nterror(req, status)) {
1035 tevent_req_done(req);
1039 status = smbd_smb2_auth_generic_return(state->session,
1042 state->in_security_mode,
1043 state->session_info,
1044 &state->out_session_flags,
1045 &state->out_session_id);
1046 if (tevent_req_nterror(req, status)) {
1050 tevent_req_done(req);
1054 static NTSTATUS smbd_smb2_session_setup_recv(struct tevent_req *req,
1055 uint16_t *out_session_flags,
1056 TALLOC_CTX *mem_ctx,
1057 DATA_BLOB *out_security_buffer,
1058 uint64_t *out_session_id)
1060 struct smbd_smb2_session_setup_state *state =
1061 tevent_req_data(req,
1062 struct smbd_smb2_session_setup_state);
1065 if (tevent_req_is_nterror(req, &status)) {
1066 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1067 tevent_req_received(req);
1068 return nt_status_squash(status);
1071 status = NT_STATUS_OK;
1074 *out_session_flags = state->out_session_flags;
1075 *out_security_buffer = state->out_security_buffer;
1076 *out_session_id = state->out_session_id;
1078 talloc_steal(mem_ctx, out_security_buffer->data);
1079 tevent_req_received(req);
1083 struct smbd_smb2_session_setup_wrap_state {
1084 struct tevent_context *ev;
1085 struct smbd_smb2_request *smb2req;
1086 uint64_t in_session_id;
1088 uint8_t in_security_mode;
1089 uint64_t in_previous_session_id;
1090 DATA_BLOB in_security_buffer;
1091 uint16_t out_session_flags;
1092 DATA_BLOB out_security_buffer;
1093 uint64_t out_session_id;
1097 static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req *subreq);
1098 static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req *subreq);
1100 static struct tevent_req *smbd_smb2_session_setup_wrap_send(TALLOC_CTX *mem_ctx,
1101 struct tevent_context *ev,
1102 struct smbd_smb2_request *smb2req,
1103 uint64_t in_session_id,
1105 uint8_t in_security_mode,
1106 uint64_t in_previous_session_id,
1107 DATA_BLOB in_security_buffer)
1109 struct tevent_req *req;
1110 struct smbd_smb2_session_setup_wrap_state *state;
1111 struct tevent_req *subreq;
1113 req = tevent_req_create(mem_ctx, &state,
1114 struct smbd_smb2_session_setup_wrap_state);
1119 state->smb2req = smb2req;
1120 state->in_session_id = in_session_id;
1121 state->in_flags = in_flags;
1122 state->in_security_mode = in_security_mode;
1123 state->in_previous_session_id = in_previous_session_id;
1124 state->in_security_buffer = in_security_buffer;
1126 subreq = smbd_smb2_session_setup_send(state, state->ev,
1128 state->in_session_id,
1130 state->in_security_mode,
1131 state->in_previous_session_id,
1132 state->in_security_buffer);
1133 if (tevent_req_nomem(subreq, req)) {
1134 return tevent_req_post(req, ev);
1136 tevent_req_set_callback(subreq,
1137 smbd_smb2_session_setup_wrap_setup_done, req);
1142 static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req *subreq)
1144 struct tevent_req *req =
1145 tevent_req_callback_data(subreq,
1147 struct smbd_smb2_session_setup_wrap_state *state =
1148 tevent_req_data(req,
1149 struct smbd_smb2_session_setup_wrap_state);
1152 status = smbd_smb2_session_setup_recv(subreq,
1153 &state->out_session_flags,
1155 &state->out_security_buffer,
1156 &state->out_session_id);
1157 TALLOC_FREE(subreq);
1158 if (NT_STATUS_IS_OK(status)) {
1159 tevent_req_done(req);
1162 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1163 tevent_req_nterror(req, status);
1167 if (state->smb2req->session == NULL) {
1168 tevent_req_nterror(req, status);
1172 state->error = status;
1174 subreq = smb2srv_session_shutdown_send(state, state->ev,
1175 state->smb2req->session,
1177 if (tevent_req_nomem(subreq, req)) {
1180 tevent_req_set_callback(subreq,
1181 smbd_smb2_session_setup_wrap_shutdown_done,
1185 static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req *subreq)
1187 struct tevent_req *req =
1188 tevent_req_callback_data(subreq,
1190 struct smbd_smb2_session_setup_wrap_state *state =
1191 tevent_req_data(req,
1192 struct smbd_smb2_session_setup_wrap_state);
1195 status = smb2srv_session_shutdown_recv(subreq);
1196 TALLOC_FREE(subreq);
1197 if (tevent_req_nterror(req, status)) {
1202 * we may need to sign the response, so we need to keep
1203 * the session until the response is sent to the wire.
1205 talloc_steal(state->smb2req, state->smb2req->session);
1207 tevent_req_nterror(req, state->error);
1210 static NTSTATUS smbd_smb2_session_setup_wrap_recv(struct tevent_req *req,
1211 uint16_t *out_session_flags,
1212 TALLOC_CTX *mem_ctx,
1213 DATA_BLOB *out_security_buffer,
1214 uint64_t *out_session_id)
1216 struct smbd_smb2_session_setup_wrap_state *state =
1217 tevent_req_data(req,
1218 struct smbd_smb2_session_setup_wrap_state);
1221 if (tevent_req_is_nterror(req, &status)) {
1222 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1223 tevent_req_received(req);
1224 return nt_status_squash(status);
1227 status = NT_STATUS_OK;
1230 *out_session_flags = state->out_session_flags;
1231 *out_security_buffer = state->out_security_buffer;
1232 *out_session_id = state->out_session_id;
1234 talloc_steal(mem_ctx, out_security_buffer->data);
1235 tevent_req_received(req);
1239 static struct tevent_req *smbd_smb2_logoff_send(TALLOC_CTX *mem_ctx,
1240 struct tevent_context *ev,
1241 struct smbd_smb2_request *smb2req);
1242 static NTSTATUS smbd_smb2_logoff_recv(struct tevent_req *req);
1243 static void smbd_smb2_request_logoff_done(struct tevent_req *subreq);
1245 NTSTATUS smbd_smb2_request_process_logoff(struct smbd_smb2_request *req)
1248 struct tevent_req *subreq = NULL;
1250 status = smbd_smb2_request_verify_sizes(req, 0x04);
1251 if (!NT_STATUS_IS_OK(status)) {
1252 return smbd_smb2_request_error(req, status);
1255 subreq = smbd_smb2_logoff_send(req, req->sconn->ev_ctx, req);
1256 if (subreq == NULL) {
1257 return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
1259 tevent_req_set_callback(subreq, smbd_smb2_request_logoff_done, req);
1262 * Avoid sending a STATUS_PENDING message, it's very likely
1263 * the client won't expect that.
1265 return smbd_smb2_request_pending_queue(req, subreq, 0);
1268 static void smbd_smb2_request_logoff_done(struct tevent_req *subreq)
1270 struct smbd_smb2_request *smb2req =
1271 tevent_req_callback_data(subreq,
1272 struct smbd_smb2_request);
1277 status = smbd_smb2_logoff_recv(subreq);
1278 TALLOC_FREE(subreq);
1279 if (!NT_STATUS_IS_OK(status)) {
1280 error = smbd_smb2_request_error(smb2req, status);
1281 if (!NT_STATUS_IS_OK(error)) {
1282 smbd_server_connection_terminate(smb2req->xconn,
1289 outbody = smbd_smb2_generate_outbody(smb2req, 0x04);
1290 if (outbody.data == NULL) {
1291 error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
1292 if (!NT_STATUS_IS_OK(error)) {
1293 smbd_server_connection_terminate(smb2req->xconn,
1300 SSVAL(outbody.data, 0x00, 0x04); /* struct size */
1301 SSVAL(outbody.data, 0x02, 0); /* reserved */
1303 error = smbd_smb2_request_done(smb2req, outbody, NULL);
1304 if (!NT_STATUS_IS_OK(error)) {
1305 smbd_server_connection_terminate(smb2req->xconn,
1311 struct smbd_smb2_logoff_state {
1312 struct smbd_smb2_request *smb2req;
1315 static void smbd_smb2_logoff_shutdown_done(struct tevent_req *subreq);
1317 static struct tevent_req *smbd_smb2_logoff_send(TALLOC_CTX *mem_ctx,
1318 struct tevent_context *ev,
1319 struct smbd_smb2_request *smb2req)
1321 struct tevent_req *req;
1322 struct smbd_smb2_logoff_state *state;
1323 struct tevent_req *subreq;
1325 req = tevent_req_create(mem_ctx, &state,
1326 struct smbd_smb2_logoff_state);
1330 state->smb2req = smb2req;
1332 subreq = smb2srv_session_shutdown_send(state, ev,
1335 if (tevent_req_nomem(subreq, req)) {
1336 return tevent_req_post(req, ev);
1338 tevent_req_set_callback(subreq, smbd_smb2_logoff_shutdown_done, req);
1343 static void smbd_smb2_logoff_shutdown_done(struct tevent_req *subreq)
1345 struct tevent_req *req = tevent_req_callback_data(
1346 subreq, struct tevent_req);
1347 struct smbd_smb2_logoff_state *state = tevent_req_data(
1348 req, struct smbd_smb2_logoff_state);
1351 const struct GUID *client_guid =
1352 &state->smb2req->session->client->connections->smb2.client.guid;
1354 status = smb2srv_session_shutdown_recv(subreq);
1355 if (tevent_req_nterror(req, status)) {
1358 TALLOC_FREE(subreq);
1360 if (!GUID_all_zero(client_guid)) {
1361 ok = remote_arch_cache_delete(client_guid);
1363 /* Most likely not an error, but not in cache */
1364 DBG_DEBUG("Deletion from remote arch cache failed\n");
1369 * As we've been awoken, we may have changed
1370 * uid in the meantime. Ensure we're still
1371 * root (SMB2_OP_LOGOFF has .as_root = true).
1373 change_to_root_user();
1375 status = smbXsrv_session_logoff(state->smb2req->session);
1376 if (tevent_req_nterror(req, status)) {
1381 * we may need to sign the response, so we need to keep
1382 * the session until the response is sent to the wire.
1384 talloc_steal(state->smb2req, state->smb2req->session);
1386 tevent_req_done(req);
1389 static NTSTATUS smbd_smb2_logoff_recv(struct tevent_req *req)
1391 return tevent_req_simple_recv_ntstatus(req);