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;
194 struct _derivation signing;
195 struct _derivation encryption;
196 struct _derivation decryption;
197 struct _derivation application;
200 if (xconn->protocol >= PROTOCOL_SMB3_10) {
201 struct smbXsrv_preauth *preauth;
202 struct _derivation *d;
204 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 = talloc_move(session->global,
412 session->global->auth_session_info_seqnum += 1;
413 for (i=0; i < session->global->num_channels; i++) {
414 struct smbXsrv_channel_global0 *_c =
415 &session->global->channels[i];
417 _c->auth_session_info_seqnum =
418 session->global->auth_session_info_seqnum;
420 session->global->auth_time = timeval_to_nttime(&smb2req->request_time);
421 session->global->expiration_time = gensec_expire_time(session->gensec);
423 if (!session_claim(session)) {
424 DEBUG(1, ("smb2: Failed to claim session "
426 (unsigned long long)session->compat->vuid));
427 return NT_STATUS_LOGON_FAILURE;
430 status = smbXsrv_session_update(session);
431 if (!NT_STATUS_IS_OK(status)) {
432 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
433 (unsigned long long)session->compat->vuid,
435 return NT_STATUS_LOGON_FAILURE;
439 * we attach the session to the request
440 * so that the response can be signed
443 smb2req->do_signing = true;
446 global_client_caps |= (CAP_LEVEL_II_OPLOCKS|CAP_STATUS32);
448 *out_session_id = session->global->session_wire_id;
453 static NTSTATUS smbd_smb2_reauth_generic_return(struct smbXsrv_session *session,
454 struct smbd_smb2_request *smb2req,
455 struct auth_session_info *session_info,
456 uint16_t *out_session_flags,
457 uint64_t *out_session_id)
460 struct smbXsrv_session *x = session;
461 struct smbXsrv_connection *xconn = smb2req->xconn;
464 data_blob_clear_free(&session_info->session_key);
465 session_info->session_key = data_blob_dup_talloc(session_info,
466 x->global->application_key);
467 if (session_info->session_key.data == NULL) {
468 return NT_STATUS_NO_MEMORY;
471 session->compat->session_info = session_info;
472 session->compat->vuid = session->global->session_wire_id;
474 session->compat->homes_snum =
475 register_homes_share(session_info->unix_info->unix_name);
477 set_current_user_info(session_info->unix_info->sanitized_username,
478 session_info->unix_info->unix_name,
479 session_info->info->domain_name);
481 reload_services(smb2req->sconn, conn_snum_used, true);
483 session->status = NT_STATUS_OK;
484 TALLOC_FREE(session->global->auth_session_info);
485 session->global->auth_session_info = talloc_move(session->global,
487 session->global->auth_session_info_seqnum += 1;
488 for (i=0; i < session->global->num_channels; i++) {
489 struct smbXsrv_channel_global0 *_c =
490 &session->global->channels[i];
492 _c->auth_session_info_seqnum =
493 session->global->auth_session_info_seqnum;
495 session->global->auth_time = timeval_to_nttime(&smb2req->request_time);
496 session->global->expiration_time = gensec_expire_time(session->gensec);
498 status = smbXsrv_session_update(session);
499 if (!NT_STATUS_IS_OK(status)) {
500 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
501 (unsigned long long)session->compat->vuid,
503 return NT_STATUS_LOGON_FAILURE;
506 conn_clear_vuid_caches(xconn->client->sconn, session->compat->vuid);
508 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
509 smb2req->do_signing = true;
512 *out_session_id = session->global->session_wire_id;
517 static NTSTATUS smbd_smb2_bind_auth_return(struct smbXsrv_session *session,
518 struct smbd_smb2_request *smb2req,
519 struct auth_session_info *session_info,
520 uint16_t *out_session_flags,
521 uint64_t *out_session_id)
524 struct smbXsrv_session *x = session;
525 struct smbXsrv_connection *xconn = smb2req->xconn;
526 struct smbXsrv_channel_global0 *c = NULL;
527 uint8_t session_key[16];
534 struct _derivation signing;
537 if (xconn->protocol >= PROTOCOL_SMB3_10) {
538 struct smbXsrv_preauth *preauth;
539 struct _derivation *d;
541 struct hc_sha512state sctx;
543 preauth = talloc_move(smb2req, &session->preauth);
545 samba_SHA512_Init(&sctx);
546 samba_SHA512_Update(&sctx, preauth->sha512_value,
547 sizeof(preauth->sha512_value));
548 for (i = 1; i < smb2req->in.vector_count; i++) {
549 samba_SHA512_Update(&sctx,
550 smb2req->in.vector[i].iov_base,
551 smb2req->in.vector[i].iov_len);
553 samba_SHA512_Final(preauth->sha512_value, &sctx);
555 p = data_blob_const(preauth->sha512_value,
556 sizeof(preauth->sha512_value));
558 d = &derivation.signing;
559 d->label = data_blob_string_const_null("SMBSigningKey");
562 } else if (xconn->protocol >= PROTOCOL_SMB2_24) {
563 struct _derivation *d;
565 d = &derivation.signing;
566 d->label = data_blob_string_const_null("SMB2AESCMAC");
567 d->context = data_blob_string_const_null("SmbSign");
570 status = smbXsrv_session_find_channel(session, xconn, &c);
571 if (!NT_STATUS_IS_OK(status)) {
575 ok = security_token_is_sid(session_info->security_token,
576 &x->global->auth_session_info->security_token->sids[0]);
578 return NT_STATUS_NOT_SUPPORTED;
581 if (session_info->session_key.length == 0) {
582 /* TODO: return code? */
583 return NT_STATUS_LOGON_FAILURE;
586 ZERO_STRUCT(session_key);
587 memcpy(session_key, session_info->session_key.data,
588 MIN(session_info->session_key.length, sizeof(session_key)));
590 c->signing_key = data_blob_talloc(x->global,
592 sizeof(session_key));
593 if (c->signing_key.data == NULL) {
594 ZERO_STRUCT(session_key);
595 return NT_STATUS_NO_MEMORY;
598 if (xconn->protocol >= PROTOCOL_SMB2_24) {
599 struct _derivation *d = &derivation.signing;
601 smb2_key_derivation(session_key, sizeof(session_key),
602 d->label.data, d->label.length,
603 d->context.data, d->context.length,
604 c->signing_key.data);
606 ZERO_STRUCT(session_key);
608 status = smbXsrv_session_update(session);
609 if (!NT_STATUS_IS_OK(status)) {
610 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
611 (unsigned long long)session->compat->vuid,
613 return NT_STATUS_LOGON_FAILURE;
616 *out_session_id = session->global->session_wire_id;
621 struct smbd_smb2_session_setup_state {
622 struct tevent_context *ev;
623 struct smbd_smb2_request *smb2req;
624 uint64_t in_session_id;
626 uint8_t in_security_mode;
627 uint64_t in_previous_session_id;
628 DATA_BLOB in_security_buffer;
629 struct smbXsrv_session *session;
630 struct auth_session_info *session_info;
631 uint16_t out_session_flags;
632 DATA_BLOB out_security_buffer;
633 uint64_t out_session_id;
636 static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq);
637 static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq);
638 static void smbd_smb2_session_setup_auth_return(struct tevent_req *req);
640 static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx,
641 struct tevent_context *ev,
642 struct smbd_smb2_request *smb2req,
643 uint64_t in_session_id,
645 uint8_t in_security_mode,
646 uint64_t in_previous_session_id,
647 DATA_BLOB in_security_buffer)
649 struct tevent_req *req;
650 struct smbd_smb2_session_setup_state *state;
652 NTTIME now = timeval_to_nttime(&smb2req->request_time);
653 struct tevent_req *subreq;
655 req = tevent_req_create(mem_ctx, &state,
656 struct smbd_smb2_session_setup_state);
661 state->smb2req = smb2req;
662 state->in_session_id = in_session_id;
663 state->in_flags = in_flags;
664 state->in_security_mode = in_security_mode;
665 state->in_previous_session_id = in_previous_session_id;
666 state->in_security_buffer = in_security_buffer;
668 if (in_flags & SMB2_SESSION_FLAG_BINDING) {
669 struct smbXsrv_channel_global0 *c = NULL;
671 if (smb2req->xconn->protocol < PROTOCOL_SMB2_22) {
672 DEBUG(0,("%s:%s: session binding requested\n", __location__, __func__));
673 tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
674 return tevent_req_post(req, ev);
677 if (smb2req->session == NULL) {
678 DEBUG(0,("%s:%s: session binding requested\n", __location__, __func__));
679 tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
680 return tevent_req_post(req, ev);
683 if (!smb2req->do_signing) {
684 tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
685 return tevent_req_post(req, ev);
688 status = smbXsrv_session_find_channel(smb2req->session,
691 if (NT_STATUS_IS_OK(status)) {
692 if (c->signing_key.length == 0) {
695 DEBUG(0,("%s:%s: session binding requested\n", __location__, __func__));
696 tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
697 return tevent_req_post(req, ev);
701 * OLD: 3.00 NEW 3.02 => INVALID_PARAMETER
702 * OLD: 3.02 NEW 3.00 => INVALID_PARAMETER
703 * OLD: 2.10 NEW 3.02 => ACCESS_DENIED
704 * OLD: 3.02 NEW 2.10 => ACCESS_DENIED
706 if (smb2req->session->global->connection_dialect < SMB2_DIALECT_REVISION_222) {
707 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
708 return tevent_req_post(req, ev);
710 if (smb2req->xconn->smb2.server.dialect < SMB2_DIALECT_REVISION_222) {
711 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
712 return tevent_req_post(req, ev);
714 if (smb2req->session->global->connection_dialect != smb2req->xconn->smb2.server.dialect) {
715 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
716 return tevent_req_post(req, ev);
719 if (security_session_user_level(smb2req->session->global->auth_session_info, NULL) < SECURITY_USER) {
720 DEBUG(0,("%s:%s: session binding requested\n", __location__, __func__));
721 tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED); //???
722 return tevent_req_post(req, ev);
725 //TODO check in_previous_session_id == 0 ???
727 status = smbXsrv_session_add_channel(smb2req->session,
730 if (!NT_STATUS_IS_OK(status)) {
731 DEBUG(0,("%s:%s: session binding requested\n", __location__, __func__));
732 tevent_req_nterror(req, status);
733 return tevent_req_post(req, ev);
736 status = smbXsrv_session_update(smb2req->session);
737 if (!NT_STATUS_IS_OK(status)) {
738 DEBUG(0,("%s:%s: session binding requested\n", __location__, __func__));
739 tevent_req_nterror(req, status);
740 return tevent_req_post(req, ev);
743 DEBUG(0,("%s:%s: session binding requested c[%p]\n", __location__, __func__, c));
745 // * We do not support multi channel.
747 //tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
748 //return tevent_req_post(req, ev);
753 if (state->in_session_id == 0) {
754 /* create a new session */
755 status = smbXsrv_session_create(state->smb2req->xconn,
756 now, &state->session);
757 if (tevent_req_nterror(req, status)) {
758 return tevent_req_post(req, ev);
760 smb2req->session = state->session;
762 if (smb2req->session == NULL) {
763 tevent_req_nterror(req, NT_STATUS_USER_SESSION_DELETED);
764 return tevent_req_post(req, ev);
767 state->session = smb2req->session;
768 status = state->session->status;
769 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
770 status = NT_STATUS_OK;
772 if (NT_STATUS_IS_OK(status)) {
773 state->session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
774 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
775 TALLOC_FREE(state->session->gensec);
777 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
778 tevent_req_nterror(req, status);
779 return tevent_req_post(req, ev);
783 if (state->session->gensec == NULL) {
784 status = auth_generic_prepare(state->session,
785 state->smb2req->xconn->remote_address,
786 &state->session->gensec);
787 if (tevent_req_nterror(req, status)) {
788 return tevent_req_post(req, ev);
791 gensec_want_feature(state->session->gensec, GENSEC_FEATURE_SESSION_KEY);
792 gensec_want_feature(state->session->gensec, GENSEC_FEATURE_UNIX_TOKEN);
794 status = gensec_start_mech_by_oid(state->session->gensec,
796 if (tevent_req_nterror(req, status)) {
797 return tevent_req_post(req, ev);
802 subreq = gensec_update_send(state, state->ev,
803 state->session->gensec,
804 state->in_security_buffer);
806 if (tevent_req_nomem(subreq, req)) {
807 return tevent_req_post(req, ev);
809 tevent_req_set_callback(subreq, smbd_smb2_session_setup_gensec_done, req);
814 static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq)
816 struct tevent_req *req =
817 tevent_req_callback_data(subreq,
819 struct smbd_smb2_session_setup_state *state =
821 struct smbd_smb2_session_setup_state);
825 status = gensec_update_recv(subreq, state,
826 &state->out_security_buffer);
829 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
830 !NT_STATUS_IS_OK(status)) {
831 tevent_req_nterror(req, status);
835 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
836 state->out_session_id = state->session->global->session_wire_id;
837 state->smb2req->preauth = state->session->preauth;
838 tevent_req_nterror(req, status);
842 status = gensec_session_info(state->session->gensec,
844 &state->session_info);
845 if (tevent_req_nterror(req, status)) {
849 if ((state->in_previous_session_id != 0) &&
850 (state->session->global->session_wire_id !=
851 state->in_previous_session_id))
853 subreq = smb2srv_session_close_previous_send(state, state->ev,
854 state->smb2req->xconn,
856 state->in_previous_session_id,
857 state->session->global->session_wire_id);
858 if (tevent_req_nomem(subreq, req)) {
861 tevent_req_set_callback(subreq,
862 smbd_smb2_session_setup_previous_done,
867 smbd_smb2_session_setup_auth_return(req);
870 static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq)
872 struct tevent_req *req =
873 tevent_req_callback_data(subreq,
877 status = smb2srv_session_close_previous_recv(subreq);
879 if (tevent_req_nterror(req, status)) {
883 smbd_smb2_session_setup_auth_return(req);
886 static void smbd_smb2_session_setup_auth_return(struct tevent_req *req)
888 struct smbd_smb2_session_setup_state *state =
890 struct smbd_smb2_session_setup_state);
893 if (state->in_flags & SMB2_SESSION_FLAG_BINDING) {
894 status = smbd_smb2_bind_auth_return(state->session,
897 &state->out_session_flags,
898 &state->out_session_id);
899 if (tevent_req_nterror(req, status)) {
902 tevent_req_done(req);
906 if (state->session->global->auth_session_info != NULL) {
907 status = smbd_smb2_reauth_generic_return(state->session,
910 &state->out_session_flags,
911 &state->out_session_id);
912 if (tevent_req_nterror(req, status)) {
915 tevent_req_done(req);
919 status = smbd_smb2_auth_generic_return(state->session,
921 state->in_security_mode,
923 &state->out_session_flags,
924 &state->out_session_id);
925 if (tevent_req_nterror(req, status)) {
929 tevent_req_done(req);
933 static NTSTATUS smbd_smb2_session_setup_recv(struct tevent_req *req,
934 uint16_t *out_session_flags,
936 DATA_BLOB *out_security_buffer,
937 uint64_t *out_session_id)
939 struct smbd_smb2_session_setup_state *state =
941 struct smbd_smb2_session_setup_state);
944 if (tevent_req_is_nterror(req, &status)) {
945 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
946 tevent_req_received(req);
947 return nt_status_squash(status);
950 status = NT_STATUS_OK;
953 *out_session_flags = state->out_session_flags;
954 *out_security_buffer = state->out_security_buffer;
955 *out_session_id = state->out_session_id;
957 talloc_steal(mem_ctx, out_security_buffer->data);
958 tevent_req_received(req);
962 struct smbd_smb2_session_setup_wrap_state {
963 struct tevent_context *ev;
964 struct smbd_smb2_request *smb2req;
965 uint64_t in_session_id;
967 uint8_t in_security_mode;
968 uint64_t in_previous_session_id;
969 DATA_BLOB in_security_buffer;
970 uint16_t out_session_flags;
971 DATA_BLOB out_security_buffer;
972 uint64_t out_session_id;
976 static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req *subreq);
977 static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req *subreq);
979 static struct tevent_req *smbd_smb2_session_setup_wrap_send(TALLOC_CTX *mem_ctx,
980 struct tevent_context *ev,
981 struct smbd_smb2_request *smb2req,
982 uint64_t in_session_id,
984 uint8_t in_security_mode,
985 uint64_t in_previous_session_id,
986 DATA_BLOB in_security_buffer)
988 struct tevent_req *req;
989 struct smbd_smb2_session_setup_wrap_state *state;
990 struct tevent_req *subreq;
992 req = tevent_req_create(mem_ctx, &state,
993 struct smbd_smb2_session_setup_wrap_state);
998 state->smb2req = smb2req;
999 state->in_session_id = in_session_id;
1000 state->in_flags = in_flags;
1001 state->in_security_mode = in_security_mode;
1002 state->in_previous_session_id = in_previous_session_id;
1003 state->in_security_buffer = in_security_buffer;
1005 subreq = smbd_smb2_session_setup_send(state, state->ev,
1007 state->in_session_id,
1009 state->in_security_mode,
1010 state->in_previous_session_id,
1011 state->in_security_buffer);
1012 if (tevent_req_nomem(subreq, req)) {
1013 return tevent_req_post(req, ev);
1015 tevent_req_set_callback(subreq,
1016 smbd_smb2_session_setup_wrap_setup_done, req);
1021 static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req *subreq)
1023 struct tevent_req *req =
1024 tevent_req_callback_data(subreq,
1026 struct smbd_smb2_session_setup_wrap_state *state =
1027 tevent_req_data(req,
1028 struct smbd_smb2_session_setup_wrap_state);
1031 status = smbd_smb2_session_setup_recv(subreq,
1032 &state->out_session_flags,
1034 &state->out_security_buffer,
1035 &state->out_session_id);
1036 TALLOC_FREE(subreq);
1037 if (NT_STATUS_IS_OK(status)) {
1038 tevent_req_done(req);
1041 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1042 tevent_req_nterror(req, status);
1046 if (state->smb2req->session == NULL) {
1047 tevent_req_nterror(req, status);
1051 state->error = status;
1053 subreq = smb2srv_session_shutdown_send(state, state->ev,
1054 state->smb2req->session,
1056 if (tevent_req_nomem(subreq, req)) {
1059 tevent_req_set_callback(subreq,
1060 smbd_smb2_session_setup_wrap_shutdown_done,
1064 static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req *subreq)
1066 struct tevent_req *req =
1067 tevent_req_callback_data(subreq,
1069 struct smbd_smb2_session_setup_wrap_state *state =
1070 tevent_req_data(req,
1071 struct smbd_smb2_session_setup_wrap_state);
1074 status = smb2srv_session_shutdown_recv(subreq);
1075 TALLOC_FREE(subreq);
1076 if (tevent_req_nterror(req, status)) {
1081 * we may need to sign the response, so we need to keep
1082 * the session until the response is sent to the wire.
1084 talloc_steal(state->smb2req, state->smb2req->session);
1086 tevent_req_nterror(req, state->error);
1089 static NTSTATUS smbd_smb2_session_setup_wrap_recv(struct tevent_req *req,
1090 uint16_t *out_session_flags,
1091 TALLOC_CTX *mem_ctx,
1092 DATA_BLOB *out_security_buffer,
1093 uint64_t *out_session_id)
1095 struct smbd_smb2_session_setup_wrap_state *state =
1096 tevent_req_data(req,
1097 struct smbd_smb2_session_setup_wrap_state);
1100 if (tevent_req_is_nterror(req, &status)) {
1101 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1102 tevent_req_received(req);
1103 return nt_status_squash(status);
1106 status = NT_STATUS_OK;
1109 *out_session_flags = state->out_session_flags;
1110 *out_security_buffer = state->out_security_buffer;
1111 *out_session_id = state->out_session_id;
1113 talloc_steal(mem_ctx, out_security_buffer->data);
1114 tevent_req_received(req);
1118 static struct tevent_req *smbd_smb2_logoff_send(TALLOC_CTX *mem_ctx,
1119 struct tevent_context *ev,
1120 struct smbd_smb2_request *smb2req);
1121 static NTSTATUS smbd_smb2_logoff_recv(struct tevent_req *req);
1122 static void smbd_smb2_request_logoff_done(struct tevent_req *subreq);
1124 NTSTATUS smbd_smb2_request_process_logoff(struct smbd_smb2_request *req)
1127 struct tevent_req *subreq = NULL;
1129 status = smbd_smb2_request_verify_sizes(req, 0x04);
1130 if (!NT_STATUS_IS_OK(status)) {
1131 return smbd_smb2_request_error(req, status);
1134 subreq = smbd_smb2_logoff_send(req, req->sconn->ev_ctx, req);
1135 if (subreq == NULL) {
1136 return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
1138 tevent_req_set_callback(subreq, smbd_smb2_request_logoff_done, req);
1141 * Wait a long time before going async on this to allow
1142 * requests we're waiting on to finish. Set timeout to 10 secs.
1144 return smbd_smb2_request_pending_queue(req, subreq, 10000000);
1147 static void smbd_smb2_request_logoff_done(struct tevent_req *subreq)
1149 struct smbd_smb2_request *smb2req =
1150 tevent_req_callback_data(subreq,
1151 struct smbd_smb2_request);
1156 status = smbd_smb2_logoff_recv(subreq);
1157 TALLOC_FREE(subreq);
1158 if (!NT_STATUS_IS_OK(status)) {
1159 error = smbd_smb2_request_error(smb2req, status);
1160 if (!NT_STATUS_IS_OK(error)) {
1161 smbd_server_connection_terminate(smb2req->xconn,
1168 outbody = smbd_smb2_generate_outbody(smb2req, 0x04);
1169 if (outbody.data == NULL) {
1170 error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
1171 if (!NT_STATUS_IS_OK(error)) {
1172 smbd_server_connection_terminate(smb2req->xconn,
1179 SSVAL(outbody.data, 0x00, 0x04); /* struct size */
1180 SSVAL(outbody.data, 0x02, 0); /* reserved */
1182 error = smbd_smb2_request_done(smb2req, outbody, NULL);
1183 if (!NT_STATUS_IS_OK(error)) {
1184 smbd_server_connection_terminate(smb2req->xconn,
1190 struct smbd_smb2_logoff_state {
1191 struct smbd_smb2_request *smb2req;
1194 static void smbd_smb2_logoff_shutdown_done(struct tevent_req *subreq);
1196 static struct tevent_req *smbd_smb2_logoff_send(TALLOC_CTX *mem_ctx,
1197 struct tevent_context *ev,
1198 struct smbd_smb2_request *smb2req)
1200 struct tevent_req *req;
1201 struct smbd_smb2_logoff_state *state;
1202 struct tevent_req *subreq;
1204 req = tevent_req_create(mem_ctx, &state,
1205 struct smbd_smb2_logoff_state);
1209 state->smb2req = smb2req;
1211 subreq = smb2srv_session_shutdown_send(state, ev,
1214 if (tevent_req_nomem(subreq, req)) {
1215 return tevent_req_post(req, ev);
1217 tevent_req_set_callback(subreq, smbd_smb2_logoff_shutdown_done, req);
1222 static void smbd_smb2_logoff_shutdown_done(struct tevent_req *subreq)
1224 struct tevent_req *req = tevent_req_callback_data(
1225 subreq, struct tevent_req);
1226 struct smbd_smb2_logoff_state *state = tevent_req_data(
1227 req, struct smbd_smb2_logoff_state);
1230 status = smb2srv_session_shutdown_recv(subreq);
1231 if (tevent_req_nterror(req, status)) {
1234 TALLOC_FREE(subreq);
1237 * As we've been awoken, we may have changed
1238 * uid in the meantime. Ensure we're still
1239 * root (SMB2_OP_LOGOFF has .as_root = true).
1241 change_to_root_user();
1243 status = smbXsrv_session_logoff(state->smb2req->session);
1244 if (tevent_req_nterror(req, status)) {
1249 * we may need to sign the response, so we need to keep
1250 * the session until the response is sent to the wire.
1252 talloc_steal(state->smb2req, state->smb2req->session);
1254 tevent_req_done(req);
1257 static NTSTATUS smbd_smb2_logoff_recv(struct tevent_req *req)
1259 return tevent_req_simple_recv_ntstatus(req);