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"
33 static struct tevent_req *smbd_smb2_session_setup_wrap_send(TALLOC_CTX *mem_ctx,
34 struct tevent_context *ev,
35 struct smbd_smb2_request *smb2req,
36 uint64_t in_session_id,
38 uint8_t in_security_mode,
39 uint64_t in_previous_session_id,
40 DATA_BLOB in_security_buffer);
41 static NTSTATUS smbd_smb2_session_setup_wrap_recv(struct tevent_req *req,
42 uint16_t *out_session_flags,
44 DATA_BLOB *out_security_buffer,
45 uint64_t *out_session_id);
47 static void smbd_smb2_request_sesssetup_done(struct tevent_req *subreq);
49 NTSTATUS smbd_smb2_request_process_sesssetup(struct smbd_smb2_request *smb2req)
52 const uint8_t *inbody;
53 uint64_t in_session_id;
55 uint8_t in_security_mode;
56 uint64_t in_previous_session_id;
57 uint16_t in_security_offset;
58 uint16_t in_security_length;
59 DATA_BLOB in_security_buffer;
61 struct tevent_req *subreq;
63 status = smbd_smb2_request_verify_sizes(smb2req, 0x19);
64 if (!NT_STATUS_IS_OK(status)) {
65 return smbd_smb2_request_error(smb2req, status);
67 inhdr = SMBD_SMB2_IN_HDR_PTR(smb2req);
68 inbody = SMBD_SMB2_IN_BODY_PTR(smb2req);
70 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
72 in_flags = CVAL(inbody, 0x02);
73 in_security_mode = CVAL(inbody, 0x03);
74 /* Capabilities = IVAL(inbody, 0x04) */
75 /* Channel = IVAL(inbody, 0x08) */
76 in_security_offset = SVAL(inbody, 0x0C);
77 in_security_length = SVAL(inbody, 0x0E);
78 in_previous_session_id = BVAL(inbody, 0x10);
80 if (in_security_offset != (SMB2_HDR_BODY + SMBD_SMB2_IN_BODY_LEN(smb2req))) {
81 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
84 if (in_security_length > SMBD_SMB2_IN_DYN_LEN(smb2req)) {
85 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
88 in_security_buffer.data = SMBD_SMB2_IN_DYN_PTR(smb2req);
89 in_security_buffer.length = in_security_length;
91 subreq = smbd_smb2_session_setup_wrap_send(smb2req,
92 smb2req->sconn->ev_ctx,
97 in_previous_session_id,
100 return smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
102 tevent_req_set_callback(subreq, smbd_smb2_request_sesssetup_done, smb2req);
104 return smbd_smb2_request_pending_queue(smb2req, subreq, 500);
107 static void smbd_smb2_request_sesssetup_done(struct tevent_req *subreq)
109 struct smbd_smb2_request *smb2req =
110 tevent_req_callback_data(subreq,
111 struct smbd_smb2_request);
115 uint16_t out_session_flags = 0;
116 uint64_t out_session_id = 0;
117 uint16_t out_security_offset;
118 DATA_BLOB out_security_buffer = data_blob_null;
120 NTSTATUS error; /* transport error */
122 status = smbd_smb2_session_setup_wrap_recv(subreq,
125 &out_security_buffer,
128 if (!NT_STATUS_IS_OK(status) &&
129 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
130 status = nt_status_squash(status);
131 error = smbd_smb2_request_error(smb2req, status);
132 if (!NT_STATUS_IS_OK(error)) {
133 smbd_server_connection_terminate(smb2req->xconn,
140 out_security_offset = SMB2_HDR_BODY + 0x08;
142 outhdr = SMBD_SMB2_OUT_HDR_PTR(smb2req);
144 outbody = smbd_smb2_generate_outbody(smb2req, 0x08);
145 if (outbody.data == NULL) {
146 error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
147 if (!NT_STATUS_IS_OK(error)) {
148 smbd_server_connection_terminate(smb2req->xconn,
155 SBVAL(outhdr, SMB2_HDR_SESSION_ID, out_session_id);
157 SSVAL(outbody.data, 0x00, 0x08 + 1); /* struct size */
158 SSVAL(outbody.data, 0x02,
159 out_session_flags); /* session flags */
160 SSVAL(outbody.data, 0x04,
161 out_security_offset); /* security buffer offset */
162 SSVAL(outbody.data, 0x06,
163 out_security_buffer.length); /* security buffer length */
165 outdyn = out_security_buffer;
167 error = smbd_smb2_request_done_ex(smb2req, status, outbody, &outdyn,
169 if (!NT_STATUS_IS_OK(error)) {
170 smbd_server_connection_terminate(smb2req->xconn,
176 static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
177 struct smbd_smb2_request *smb2req,
178 uint8_t in_security_mode,
179 struct auth_session_info *session_info,
180 uint16_t *out_session_flags,
181 uint64_t *out_session_id)
185 uint8_t session_key[16];
186 struct smbXsrv_session *x = session;
187 struct smbXsrv_connection *xconn = smb2req->xconn;
193 struct _derivation signing;
194 struct _derivation encryption;
195 struct _derivation decryption;
196 struct _derivation application;
199 if (xconn->protocol >= PROTOCOL_SMB3_10) {
200 struct smbXsrv_preauth *preauth;
201 struct _derivation *d;
203 struct hc_sha512state sctx;
206 preauth = talloc_move(smb2req, &session->preauth);
208 samba_SHA512_Init(&sctx);
209 samba_SHA512_Update(&sctx, preauth->sha512_value,
210 sizeof(preauth->sha512_value));
211 for (i = 1; i < smb2req->in.vector_count; i++) {
212 samba_SHA512_Update(&sctx,
213 smb2req->in.vector[i].iov_base,
214 smb2req->in.vector[i].iov_len);
216 samba_SHA512_Final(preauth->sha512_value, &sctx);
218 p = data_blob_const(preauth->sha512_value,
219 sizeof(preauth->sha512_value));
221 d = &derivation.signing;
222 d->label = data_blob_string_const_null("SMBSigningKey");
225 d = &derivation.decryption;
226 d->label = data_blob_string_const_null("SMBC2SCipherKey");
229 d = &derivation.encryption;
230 d->label = data_blob_string_const_null("SMBS2CCipherKey");
233 d = &derivation.application;
234 d->label = data_blob_string_const_null("SMBAppKey");
237 } else if (xconn->protocol >= PROTOCOL_SMB2_24) {
238 struct _derivation *d;
240 d = &derivation.signing;
241 d->label = data_blob_string_const_null("SMB2AESCMAC");
242 d->context = data_blob_string_const_null("SmbSign");
244 d = &derivation.decryption;
245 d->label = data_blob_string_const_null("SMB2AESCCM");
246 d->context = data_blob_string_const_null("ServerIn ");
248 d = &derivation.encryption;
249 d->label = data_blob_string_const_null("SMB2AESCCM");
250 d->context = data_blob_string_const_null("ServerOut");
252 d = &derivation.application;
253 d->label = data_blob_string_const_null("SMB2APP");
254 d->context = data_blob_string_const_null("SmbRpc");
257 if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
258 lp_server_signing() == SMB_SIGNING_REQUIRED) {
259 x->global->signing_required = true;
262 if ((lp_smb_encrypt(-1) > SMB_SIGNING_OFF) &&
263 (xconn->smb2.client.capabilities & SMB2_CAP_ENCRYPTION)) {
264 x->global->encryption_required = true;
267 if (lp_smb_encrypt(-1) == SMB_SIGNING_REQUIRED) {
268 x->global->encryption_required = true;
271 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
272 /* we map anonymous to guest internally */
273 *out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
274 *out_session_flags |= SMB2_SESSION_FLAG_IS_NULL;
275 /* force no signing */
276 x->global->signing_required = false;
280 if (guest && x->global->encryption_required) {
281 DEBUG(1,("reject guest session as encryption is required\n"));
282 return NT_STATUS_ACCESS_DENIED;
285 if (xconn->smb2.server.cipher == 0) {
286 if (x->global->encryption_required) {
287 DEBUG(1,("reject session with dialect[0x%04X] "
288 "as encryption is required\n",
289 xconn->smb2.server.dialect));
290 return NT_STATUS_ACCESS_DENIED;
294 if (x->global->encryption_required) {
295 *out_session_flags |= SMB2_SESSION_FLAG_ENCRYPT_DATA;
298 ZERO_STRUCT(session_key);
299 memcpy(session_key, session_info->session_key.data,
300 MIN(session_info->session_key.length, sizeof(session_key)));
302 x->global->signing_key = data_blob_talloc(x->global,
304 sizeof(session_key));
305 if (x->global->signing_key.data == NULL) {
306 ZERO_STRUCT(session_key);
307 return NT_STATUS_NO_MEMORY;
310 if (xconn->protocol >= PROTOCOL_SMB2_24) {
311 struct _derivation *d = &derivation.signing;
313 smb2_key_derivation(session_key, sizeof(session_key),
314 d->label.data, d->label.length,
315 d->context.data, d->context.length,
316 x->global->signing_key.data);
319 if (xconn->protocol >= PROTOCOL_SMB2_24) {
320 struct _derivation *d = &derivation.decryption;
322 x->global->decryption_key = data_blob_talloc(x->global,
324 sizeof(session_key));
325 if (x->global->decryption_key.data == NULL) {
326 ZERO_STRUCT(session_key);
327 return NT_STATUS_NO_MEMORY;
330 smb2_key_derivation(session_key, sizeof(session_key),
331 d->label.data, d->label.length,
332 d->context.data, d->context.length,
333 x->global->decryption_key.data);
336 if (xconn->protocol >= PROTOCOL_SMB2_24) {
337 struct _derivation *d = &derivation.encryption;
339 x->global->encryption_key = data_blob_talloc(x->global,
341 sizeof(session_key));
342 if (x->global->encryption_key.data == NULL) {
343 ZERO_STRUCT(session_key);
344 return NT_STATUS_NO_MEMORY;
347 smb2_key_derivation(session_key, sizeof(session_key),
348 d->label.data, d->label.length,
349 d->context.data, d->context.length,
350 x->global->encryption_key.data);
352 generate_random_buffer((uint8_t *)&x->nonce_high, sizeof(x->nonce_high));
356 x->global->application_key = data_blob_dup_talloc(x->global,
357 x->global->signing_key);
358 if (x->global->application_key.data == NULL) {
359 ZERO_STRUCT(session_key);
360 return NT_STATUS_NO_MEMORY;
363 if (xconn->protocol >= PROTOCOL_SMB2_24) {
364 struct _derivation *d = &derivation.application;
366 smb2_key_derivation(session_key, sizeof(session_key),
367 d->label.data, d->label.length,
368 d->context.data, d->context.length,
369 x->global->application_key.data);
371 ZERO_STRUCT(session_key);
373 x->global->channels[0].signing_key = data_blob_dup_talloc(x->global->channels,
374 x->global->signing_key);
375 if (x->global->channels[0].signing_key.data == NULL) {
376 return NT_STATUS_NO_MEMORY;
379 data_blob_clear_free(&session_info->session_key);
380 session_info->session_key = data_blob_dup_talloc(session_info,
381 x->global->application_key);
382 if (session_info->session_key.data == NULL) {
383 return NT_STATUS_NO_MEMORY;
386 session->compat = talloc_zero(session, struct user_struct);
387 if (session->compat == NULL) {
388 return NT_STATUS_NO_MEMORY;
390 session->compat->session = session;
391 session->compat->homes_snum = -1;
392 session->compat->session_info = session_info;
393 session->compat->session_keystr = NULL;
394 session->compat->vuid = session->global->session_wire_id;
395 DLIST_ADD(smb2req->sconn->users, session->compat);
396 smb2req->sconn->num_users++;
398 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
399 session->compat->homes_snum =
400 register_homes_share(session_info->unix_info->unix_name);
403 set_current_user_info(session_info->unix_info->sanitized_username,
404 session_info->unix_info->unix_name,
405 session_info->info->domain_name);
407 reload_services(smb2req->sconn, conn_snum_used, true);
409 session->status = NT_STATUS_OK;
410 session->global->auth_session_info = session_info;
411 session->global->auth_session_info_seqnum += 1;
412 session->global->channels[0].auth_session_info_seqnum =
413 session->global->auth_session_info_seqnum;
414 session->global->auth_time = timeval_to_nttime(&smb2req->request_time);
415 session->global->expiration_time = gensec_expire_time(session->gensec);
417 if (!session_claim(session)) {
418 DEBUG(1, ("smb2: Failed to claim session "
420 (unsigned long long)session->compat->vuid));
421 return NT_STATUS_LOGON_FAILURE;
424 status = smbXsrv_session_update(session);
425 if (!NT_STATUS_IS_OK(status)) {
426 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
427 (unsigned long long)session->compat->vuid,
429 return NT_STATUS_LOGON_FAILURE;
433 * we attach the session to the request
434 * so that the response can be signed
437 smb2req->do_signing = true;
440 global_client_caps |= (CAP_LEVEL_II_OPLOCKS|CAP_STATUS32);
442 *out_session_id = session->global->session_wire_id;
447 static NTSTATUS smbd_smb2_reauth_generic_return(struct smbXsrv_session *session,
448 struct smbd_smb2_request *smb2req,
449 struct auth_session_info *session_info,
450 uint16_t *out_session_flags,
451 uint64_t *out_session_id)
454 struct smbXsrv_session *x = session;
456 data_blob_clear_free(&session_info->session_key);
457 session_info->session_key = data_blob_dup_talloc(session_info,
458 x->global->application_key);
459 if (session_info->session_key.data == NULL) {
460 return NT_STATUS_NO_MEMORY;
463 session->compat->session_info = session_info;
464 session->compat->vuid = session->global->session_wire_id;
466 session->compat->homes_snum =
467 register_homes_share(session_info->unix_info->unix_name);
469 set_current_user_info(session_info->unix_info->sanitized_username,
470 session_info->unix_info->unix_name,
471 session_info->info->domain_name);
473 reload_services(smb2req->sconn, conn_snum_used, true);
475 session->status = NT_STATUS_OK;
476 TALLOC_FREE(session->global->auth_session_info);
477 session->global->auth_session_info = session_info;
478 session->global->auth_session_info_seqnum += 1;
479 session->global->channels[0].auth_session_info_seqnum =
480 session->global->auth_session_info_seqnum;
481 session->global->auth_time = timeval_to_nttime(&smb2req->request_time);
482 session->global->expiration_time = gensec_expire_time(session->gensec);
484 status = smbXsrv_session_update(session);
485 if (!NT_STATUS_IS_OK(status)) {
486 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
487 (unsigned long long)session->compat->vuid,
489 return NT_STATUS_LOGON_FAILURE;
492 conn_clear_vuid_caches(smb2req->sconn, session->compat->vuid);
494 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
495 smb2req->do_signing = true;
498 *out_session_id = session->global->session_wire_id;
503 struct smbd_smb2_session_setup_state {
504 struct tevent_context *ev;
505 struct smbd_smb2_request *smb2req;
506 uint64_t in_session_id;
508 uint8_t in_security_mode;
509 uint64_t in_previous_session_id;
510 DATA_BLOB in_security_buffer;
511 struct smbXsrv_session *session;
512 struct auth_session_info *session_info;
513 uint16_t out_session_flags;
514 DATA_BLOB out_security_buffer;
515 uint64_t out_session_id;
518 static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq);
519 static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq);
520 static void smbd_smb2_session_setup_auth_return(struct tevent_req *req);
522 static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx,
523 struct tevent_context *ev,
524 struct smbd_smb2_request *smb2req,
525 uint64_t in_session_id,
527 uint8_t in_security_mode,
528 uint64_t in_previous_session_id,
529 DATA_BLOB in_security_buffer)
531 struct tevent_req *req;
532 struct smbd_smb2_session_setup_state *state;
534 NTTIME now = timeval_to_nttime(&smb2req->request_time);
535 struct tevent_req *subreq;
537 req = tevent_req_create(mem_ctx, &state,
538 struct smbd_smb2_session_setup_state);
543 state->smb2req = smb2req;
544 state->in_session_id = in_session_id;
545 state->in_flags = in_flags;
546 state->in_security_mode = in_security_mode;
547 state->in_previous_session_id = in_previous_session_id;
548 state->in_security_buffer = in_security_buffer;
550 if (in_flags & SMB2_SESSION_FLAG_BINDING) {
551 if (smb2req->xconn->protocol < PROTOCOL_SMB2_22) {
552 tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
553 return tevent_req_post(req, ev);
557 * We do not support multi channel.
559 tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
560 return tevent_req_post(req, ev);
563 if (state->in_session_id == 0) {
564 /* create a new session */
565 status = smbXsrv_session_create(state->smb2req->xconn,
566 now, &state->session);
567 if (tevent_req_nterror(req, status)) {
568 return tevent_req_post(req, ev);
570 smb2req->session = state->session;
572 if (smb2req->session == NULL) {
573 tevent_req_nterror(req, NT_STATUS_USER_SESSION_DELETED);
574 return tevent_req_post(req, ev);
577 state->session = smb2req->session;
578 status = state->session->status;
579 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
580 status = NT_STATUS_OK;
582 if (NT_STATUS_IS_OK(status)) {
583 state->session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
584 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
585 TALLOC_FREE(state->session->gensec);
587 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
588 tevent_req_nterror(req, status);
589 return tevent_req_post(req, ev);
593 if (state->session->gensec == NULL) {
594 status = auth_generic_prepare(state->session,
595 state->smb2req->xconn->remote_address,
596 &state->session->gensec);
597 if (tevent_req_nterror(req, status)) {
598 return tevent_req_post(req, ev);
601 gensec_want_feature(state->session->gensec, GENSEC_FEATURE_SESSION_KEY);
602 gensec_want_feature(state->session->gensec, GENSEC_FEATURE_UNIX_TOKEN);
604 status = gensec_start_mech_by_oid(state->session->gensec,
606 if (tevent_req_nterror(req, status)) {
607 return tevent_req_post(req, ev);
612 subreq = gensec_update_send(state, state->ev,
613 state->session->gensec,
614 state->in_security_buffer);
616 if (tevent_req_nomem(subreq, req)) {
617 return tevent_req_post(req, ev);
619 tevent_req_set_callback(subreq, smbd_smb2_session_setup_gensec_done, req);
624 static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq)
626 struct tevent_req *req =
627 tevent_req_callback_data(subreq,
629 struct smbd_smb2_session_setup_state *state =
631 struct smbd_smb2_session_setup_state);
635 status = gensec_update_recv(subreq, state,
636 &state->out_security_buffer);
639 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
640 !NT_STATUS_IS_OK(status)) {
641 tevent_req_nterror(req, status);
645 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
646 state->out_session_id = state->session->global->session_wire_id;
647 state->smb2req->preauth = state->session->preauth;
648 tevent_req_nterror(req, status);
652 status = gensec_session_info(state->session->gensec,
653 state->session->global,
654 &state->session_info);
655 if (tevent_req_nterror(req, status)) {
659 if ((state->in_previous_session_id != 0) &&
660 (state->session->global->session_wire_id !=
661 state->in_previous_session_id))
663 subreq = smb2srv_session_close_previous_send(state, state->ev,
664 state->smb2req->xconn,
666 state->in_previous_session_id,
667 state->session->global->session_wire_id);
668 if (tevent_req_nomem(subreq, req)) {
671 tevent_req_set_callback(subreq,
672 smbd_smb2_session_setup_previous_done,
677 smbd_smb2_session_setup_auth_return(req);
680 static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq)
682 struct tevent_req *req =
683 tevent_req_callback_data(subreq,
687 status = smb2srv_session_close_previous_recv(subreq);
689 if (tevent_req_nterror(req, status)) {
693 smbd_smb2_session_setup_auth_return(req);
696 static void smbd_smb2_session_setup_auth_return(struct tevent_req *req)
698 struct smbd_smb2_session_setup_state *state =
700 struct smbd_smb2_session_setup_state);
703 if (state->session->global->auth_session_info != NULL) {
704 status = smbd_smb2_reauth_generic_return(state->session,
707 &state->out_session_flags,
708 &state->out_session_id);
709 if (tevent_req_nterror(req, status)) {
712 tevent_req_done(req);
716 status = smbd_smb2_auth_generic_return(state->session,
718 state->in_security_mode,
720 &state->out_session_flags,
721 &state->out_session_id);
722 if (tevent_req_nterror(req, status)) {
726 tevent_req_done(req);
730 static NTSTATUS smbd_smb2_session_setup_recv(struct tevent_req *req,
731 uint16_t *out_session_flags,
733 DATA_BLOB *out_security_buffer,
734 uint64_t *out_session_id)
736 struct smbd_smb2_session_setup_state *state =
738 struct smbd_smb2_session_setup_state);
741 if (tevent_req_is_nterror(req, &status)) {
742 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
743 tevent_req_received(req);
744 return nt_status_squash(status);
747 status = NT_STATUS_OK;
750 *out_session_flags = state->out_session_flags;
751 *out_security_buffer = state->out_security_buffer;
752 *out_session_id = state->out_session_id;
754 talloc_steal(mem_ctx, out_security_buffer->data);
755 tevent_req_received(req);
759 struct smbd_smb2_session_setup_wrap_state {
760 struct tevent_context *ev;
761 struct smbd_smb2_request *smb2req;
762 uint64_t in_session_id;
764 uint8_t in_security_mode;
765 uint64_t in_previous_session_id;
766 DATA_BLOB in_security_buffer;
767 uint16_t out_session_flags;
768 DATA_BLOB out_security_buffer;
769 uint64_t out_session_id;
773 static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req *subreq);
774 static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req *subreq);
776 static struct tevent_req *smbd_smb2_session_setup_wrap_send(TALLOC_CTX *mem_ctx,
777 struct tevent_context *ev,
778 struct smbd_smb2_request *smb2req,
779 uint64_t in_session_id,
781 uint8_t in_security_mode,
782 uint64_t in_previous_session_id,
783 DATA_BLOB in_security_buffer)
785 struct tevent_req *req;
786 struct smbd_smb2_session_setup_wrap_state *state;
787 struct tevent_req *subreq;
789 req = tevent_req_create(mem_ctx, &state,
790 struct smbd_smb2_session_setup_wrap_state);
795 state->smb2req = smb2req;
796 state->in_session_id = in_session_id;
797 state->in_flags = in_flags;
798 state->in_security_mode = in_security_mode;
799 state->in_previous_session_id = in_previous_session_id;
800 state->in_security_buffer = in_security_buffer;
802 subreq = smbd_smb2_session_setup_send(state, state->ev,
804 state->in_session_id,
806 state->in_security_mode,
807 state->in_previous_session_id,
808 state->in_security_buffer);
809 if (tevent_req_nomem(subreq, req)) {
810 return tevent_req_post(req, ev);
812 tevent_req_set_callback(subreq,
813 smbd_smb2_session_setup_wrap_setup_done, req);
818 static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req *subreq)
820 struct tevent_req *req =
821 tevent_req_callback_data(subreq,
823 struct smbd_smb2_session_setup_wrap_state *state =
825 struct smbd_smb2_session_setup_wrap_state);
828 status = smbd_smb2_session_setup_recv(subreq,
829 &state->out_session_flags,
831 &state->out_security_buffer,
832 &state->out_session_id);
834 if (NT_STATUS_IS_OK(status)) {
835 tevent_req_done(req);
838 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
839 tevent_req_nterror(req, status);
843 if (state->smb2req->session == NULL) {
844 tevent_req_nterror(req, status);
848 state->error = status;
850 subreq = smb2srv_session_shutdown_send(state, state->ev,
851 state->smb2req->session,
853 if (tevent_req_nomem(subreq, req)) {
856 tevent_req_set_callback(subreq,
857 smbd_smb2_session_setup_wrap_shutdown_done,
861 static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req *subreq)
863 struct tevent_req *req =
864 tevent_req_callback_data(subreq,
866 struct smbd_smb2_session_setup_wrap_state *state =
868 struct smbd_smb2_session_setup_wrap_state);
871 status = smb2srv_session_shutdown_recv(subreq);
873 if (tevent_req_nterror(req, status)) {
878 * we may need to sign the response, so we need to keep
879 * the session until the response is sent to the wire.
881 talloc_steal(state->smb2req, state->smb2req->session);
883 tevent_req_nterror(req, state->error);
886 static NTSTATUS smbd_smb2_session_setup_wrap_recv(struct tevent_req *req,
887 uint16_t *out_session_flags,
889 DATA_BLOB *out_security_buffer,
890 uint64_t *out_session_id)
892 struct smbd_smb2_session_setup_wrap_state *state =
894 struct smbd_smb2_session_setup_wrap_state);
897 if (tevent_req_is_nterror(req, &status)) {
898 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
899 tevent_req_received(req);
900 return nt_status_squash(status);
903 status = NT_STATUS_OK;
906 *out_session_flags = state->out_session_flags;
907 *out_security_buffer = state->out_security_buffer;
908 *out_session_id = state->out_session_id;
910 talloc_steal(mem_ctx, out_security_buffer->data);
911 tevent_req_received(req);
915 static struct tevent_req *smbd_smb2_logoff_send(TALLOC_CTX *mem_ctx,
916 struct tevent_context *ev,
917 struct smbd_smb2_request *smb2req);
918 static NTSTATUS smbd_smb2_logoff_recv(struct tevent_req *req);
919 static void smbd_smb2_request_logoff_done(struct tevent_req *subreq);
921 NTSTATUS smbd_smb2_request_process_logoff(struct smbd_smb2_request *req)
924 struct tevent_req *subreq = NULL;
926 status = smbd_smb2_request_verify_sizes(req, 0x04);
927 if (!NT_STATUS_IS_OK(status)) {
928 return smbd_smb2_request_error(req, status);
931 subreq = smbd_smb2_logoff_send(req, req->sconn->ev_ctx, req);
932 if (subreq == NULL) {
933 return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
935 tevent_req_set_callback(subreq, smbd_smb2_request_logoff_done, req);
938 * Wait a long time before going async on this to allow
939 * requests we're waiting on to finish. Set timeout to 10 secs.
941 return smbd_smb2_request_pending_queue(req, subreq, 10000000);
944 static void smbd_smb2_request_logoff_done(struct tevent_req *subreq)
946 struct smbd_smb2_request *smb2req =
947 tevent_req_callback_data(subreq,
948 struct smbd_smb2_request);
953 status = smbd_smb2_logoff_recv(subreq);
955 if (!NT_STATUS_IS_OK(status)) {
956 error = smbd_smb2_request_error(smb2req, status);
957 if (!NT_STATUS_IS_OK(error)) {
958 smbd_server_connection_terminate(smb2req->xconn,
965 outbody = smbd_smb2_generate_outbody(smb2req, 0x04);
966 if (outbody.data == NULL) {
967 error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
968 if (!NT_STATUS_IS_OK(error)) {
969 smbd_server_connection_terminate(smb2req->xconn,
976 SSVAL(outbody.data, 0x00, 0x04); /* struct size */
977 SSVAL(outbody.data, 0x02, 0); /* reserved */
979 error = smbd_smb2_request_done(smb2req, outbody, NULL);
980 if (!NT_STATUS_IS_OK(error)) {
981 smbd_server_connection_terminate(smb2req->xconn,
987 struct smbd_smb2_logoff_state {
988 struct smbd_smb2_request *smb2req;
991 static void smbd_smb2_logoff_shutdown_done(struct tevent_req *subreq);
993 static struct tevent_req *smbd_smb2_logoff_send(TALLOC_CTX *mem_ctx,
994 struct tevent_context *ev,
995 struct smbd_smb2_request *smb2req)
997 struct tevent_req *req;
998 struct smbd_smb2_logoff_state *state;
999 struct tevent_req *subreq;
1001 req = tevent_req_create(mem_ctx, &state,
1002 struct smbd_smb2_logoff_state);
1006 state->smb2req = smb2req;
1008 subreq = smb2srv_session_shutdown_send(state, ev,
1011 if (tevent_req_nomem(subreq, req)) {
1012 return tevent_req_post(req, ev);
1014 tevent_req_set_callback(subreq, smbd_smb2_logoff_shutdown_done, req);
1019 static void smbd_smb2_logoff_shutdown_done(struct tevent_req *subreq)
1021 struct tevent_req *req = tevent_req_callback_data(
1022 subreq, struct tevent_req);
1023 struct smbd_smb2_logoff_state *state = tevent_req_data(
1024 req, struct smbd_smb2_logoff_state);
1027 status = smb2srv_session_shutdown_recv(subreq);
1028 if (tevent_req_nterror(req, status)) {
1031 TALLOC_FREE(subreq);
1034 * As we've been awoken, we may have changed
1035 * uid in the meantime. Ensure we're still
1036 * root (SMB2_OP_LOGOFF has .as_root = true).
1038 change_to_root_user();
1040 status = smbXsrv_session_logoff(state->smb2req->session);
1041 if (tevent_req_nterror(req, status)) {
1046 * we may need to sign the response, so we need to keep
1047 * the session until the response is sent to the wire.
1049 talloc_steal(state->smb2req, state->smb2req->session);
1051 tevent_req_done(req);
1054 static NTSTATUS smbd_smb2_logoff_recv(struct tevent_req *req)
1056 return tevent_req_simple_recv_ntstatus(req);