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"
36 static struct tevent_req
*smbd_smb2_session_setup_wrap_send(TALLOC_CTX
*mem_ctx
,
37 struct tevent_context
*ev
,
38 struct smbd_smb2_request
*smb2req
,
39 uint64_t in_session_id
,
41 uint8_t in_security_mode
,
42 uint64_t in_previous_session_id
,
43 DATA_BLOB in_security_buffer
);
44 static NTSTATUS
smbd_smb2_session_setup_wrap_recv(struct tevent_req
*req
,
45 uint16_t *out_session_flags
,
47 DATA_BLOB
*out_security_buffer
,
48 uint64_t *out_session_id
);
50 static void smbd_smb2_request_sesssetup_done(struct tevent_req
*subreq
);
52 NTSTATUS
smbd_smb2_request_process_sesssetup(struct smbd_smb2_request
*smb2req
)
55 const uint8_t *inbody
;
56 uint64_t in_session_id
;
58 uint8_t in_security_mode
;
59 uint64_t in_previous_session_id
;
60 uint16_t in_security_offset
;
61 uint16_t in_security_length
;
62 DATA_BLOB in_security_buffer
;
64 struct tevent_req
*subreq
;
66 status
= smbd_smb2_request_verify_sizes(smb2req
, 0x19);
67 if (!NT_STATUS_IS_OK(status
)) {
68 return smbd_smb2_request_error(smb2req
, status
);
70 inhdr
= SMBD_SMB2_IN_HDR_PTR(smb2req
);
71 inbody
= SMBD_SMB2_IN_BODY_PTR(smb2req
);
73 in_session_id
= BVAL(inhdr
, SMB2_HDR_SESSION_ID
);
75 in_flags
= CVAL(inbody
, 0x02);
76 in_security_mode
= CVAL(inbody
, 0x03);
77 /* Capabilities = IVAL(inbody, 0x04) */
78 /* Channel = IVAL(inbody, 0x08) */
79 in_security_offset
= SVAL(inbody
, 0x0C);
80 in_security_length
= SVAL(inbody
, 0x0E);
81 in_previous_session_id
= BVAL(inbody
, 0x10);
83 if (in_security_offset
!= (SMB2_HDR_BODY
+ SMBD_SMB2_IN_BODY_LEN(smb2req
))) {
84 return smbd_smb2_request_error(smb2req
, NT_STATUS_INVALID_PARAMETER
);
87 if (in_security_length
> SMBD_SMB2_IN_DYN_LEN(smb2req
)) {
88 return smbd_smb2_request_error(smb2req
, NT_STATUS_INVALID_PARAMETER
);
91 in_security_buffer
.data
= SMBD_SMB2_IN_DYN_PTR(smb2req
);
92 in_security_buffer
.length
= in_security_length
;
94 subreq
= smbd_smb2_session_setup_wrap_send(smb2req
,
95 smb2req
->sconn
->ev_ctx
,
100 in_previous_session_id
,
102 if (subreq
== NULL
) {
103 return smbd_smb2_request_error(smb2req
, NT_STATUS_NO_MEMORY
);
105 tevent_req_set_callback(subreq
, smbd_smb2_request_sesssetup_done
, smb2req
);
107 return smbd_smb2_request_pending_queue(smb2req
, subreq
, 500);
110 static void smbd_smb2_request_sesssetup_done(struct tevent_req
*subreq
)
112 struct smbd_smb2_request
*smb2req
=
113 tevent_req_callback_data(subreq
,
114 struct smbd_smb2_request
);
118 uint16_t out_session_flags
= 0;
119 uint64_t out_session_id
= 0;
120 uint16_t out_security_offset
;
121 DATA_BLOB out_security_buffer
= data_blob_null
;
123 NTSTATUS error
; /* transport error */
125 status
= smbd_smb2_session_setup_wrap_recv(subreq
,
128 &out_security_buffer
,
131 if (!NT_STATUS_IS_OK(status
) &&
132 !NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
133 status
= nt_status_squash(status
);
134 error
= smbd_smb2_request_error(smb2req
, status
);
135 if (!NT_STATUS_IS_OK(error
)) {
136 smbd_server_connection_terminate(smb2req
->xconn
,
143 out_security_offset
= SMB2_HDR_BODY
+ 0x08;
145 outhdr
= SMBD_SMB2_OUT_HDR_PTR(smb2req
);
147 outbody
= smbd_smb2_generate_outbody(smb2req
, 0x08);
148 if (outbody
.data
== NULL
) {
149 error
= smbd_smb2_request_error(smb2req
, NT_STATUS_NO_MEMORY
);
150 if (!NT_STATUS_IS_OK(error
)) {
151 smbd_server_connection_terminate(smb2req
->xconn
,
158 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
, out_session_id
);
160 SSVAL(outbody
.data
, 0x00, 0x08 + 1); /* struct size */
161 SSVAL(outbody
.data
, 0x02,
162 out_session_flags
); /* session flags */
163 SSVAL(outbody
.data
, 0x04,
164 out_security_offset
); /* security buffer offset */
165 SSVAL(outbody
.data
, 0x06,
166 out_security_buffer
.length
); /* security buffer length */
168 outdyn
= out_security_buffer
;
170 error
= smbd_smb2_request_done_ex(smb2req
, status
, outbody
, &outdyn
,
172 if (!NT_STATUS_IS_OK(error
)) {
173 smbd_server_connection_terminate(smb2req
->xconn
,
179 static NTSTATUS
smbd_smb2_auth_generic_return(struct smbXsrv_session
*session
,
180 struct smbd_smb2_request
*smb2req
,
181 uint8_t in_security_mode
,
182 struct auth_session_info
*session_info
,
183 uint16_t *out_session_flags
,
184 uint64_t *out_session_id
)
188 uint8_t session_key
[16];
189 struct smbXsrv_session
*x
= session
;
190 struct smbXsrv_connection
*xconn
= smb2req
->xconn
;
196 struct _derivation signing
;
197 struct _derivation encryption
;
198 struct _derivation decryption
;
199 struct _derivation application
;
202 if (xconn
->protocol
>= PROTOCOL_SMB3_10
) {
203 struct smbXsrv_preauth
*preauth
;
204 struct _derivation
*d
;
206 struct hc_sha512state sctx
;
209 preauth
= talloc_move(smb2req
, &session
->preauth
);
211 samba_SHA512_Init(&sctx
);
212 samba_SHA512_Update(&sctx
, preauth
->sha512_value
,
213 sizeof(preauth
->sha512_value
));
214 for (i
= 1; i
< smb2req
->in
.vector_count
; i
++) {
215 samba_SHA512_Update(&sctx
,
216 smb2req
->in
.vector
[i
].iov_base
,
217 smb2req
->in
.vector
[i
].iov_len
);
219 samba_SHA512_Final(preauth
->sha512_value
, &sctx
);
221 p
= data_blob_const(preauth
->sha512_value
,
222 sizeof(preauth
->sha512_value
));
224 d
= &derivation
.signing
;
225 d
->label
= data_blob_string_const_null("SMBSigningKey");
228 d
= &derivation
.decryption
;
229 d
->label
= data_blob_string_const_null("SMBC2SCipherKey");
232 d
= &derivation
.encryption
;
233 d
->label
= data_blob_string_const_null("SMBS2CCipherKey");
236 d
= &derivation
.application
;
237 d
->label
= data_blob_string_const_null("SMBAppKey");
240 } else if (xconn
->protocol
>= PROTOCOL_SMB2_24
) {
241 struct _derivation
*d
;
243 d
= &derivation
.signing
;
244 d
->label
= data_blob_string_const_null("SMB2AESCMAC");
245 d
->context
= data_blob_string_const_null("SmbSign");
247 d
= &derivation
.decryption
;
248 d
->label
= data_blob_string_const_null("SMB2AESCCM");
249 d
->context
= data_blob_string_const_null("ServerIn ");
251 d
= &derivation
.encryption
;
252 d
->label
= data_blob_string_const_null("SMB2AESCCM");
253 d
->context
= data_blob_string_const_null("ServerOut");
255 d
= &derivation
.application
;
256 d
->label
= data_blob_string_const_null("SMB2APP");
257 d
->context
= data_blob_string_const_null("SmbRpc");
260 if ((in_security_mode
& SMB2_NEGOTIATE_SIGNING_REQUIRED
) ||
261 lp_server_signing() == SMB_SIGNING_REQUIRED
) {
262 x
->global
->signing_required
= true;
265 if ((lp_smb_encrypt(-1) >= SMB_SIGNING_DESIRED
) &&
266 (xconn
->smb2
.client
.capabilities
& SMB2_CAP_ENCRYPTION
)) {
267 x
->encryption_desired
= true;
270 if (lp_smb_encrypt(-1) == SMB_SIGNING_REQUIRED
) {
271 x
->encryption_desired
= true;
272 x
->global
->encryption_required
= true;
275 if (security_session_user_level(session_info
, NULL
) < SECURITY_USER
) {
276 /* we map anonymous to guest internally */
277 *out_session_flags
|= SMB2_SESSION_FLAG_IS_GUEST
;
278 *out_session_flags
|= SMB2_SESSION_FLAG_IS_NULL
;
279 /* force no signing */
280 x
->global
->signing_required
= false;
284 if (guest
&& x
->global
->encryption_required
) {
285 DEBUG(1,("reject guest session as encryption is required\n"));
286 return NT_STATUS_ACCESS_DENIED
;
289 if (xconn
->smb2
.server
.cipher
== 0) {
290 if (x
->global
->encryption_required
) {
291 DEBUG(1,("reject session with dialect[0x%04X] "
292 "as encryption is required\n",
293 xconn
->smb2
.server
.dialect
));
294 return NT_STATUS_ACCESS_DENIED
;
298 if (x
->encryption_desired
) {
299 *out_session_flags
|= SMB2_SESSION_FLAG_ENCRYPT_DATA
;
302 ZERO_STRUCT(session_key
);
303 memcpy(session_key
, session_info
->session_key
.data
,
304 MIN(session_info
->session_key
.length
, sizeof(session_key
)));
306 x
->global
->signing_key
= data_blob_talloc(x
->global
,
308 sizeof(session_key
));
309 if (x
->global
->signing_key
.data
== NULL
) {
310 ZERO_STRUCT(session_key
);
311 return NT_STATUS_NO_MEMORY
;
314 if (xconn
->protocol
>= PROTOCOL_SMB2_24
) {
315 struct _derivation
*d
= &derivation
.signing
;
317 smb2_key_derivation(session_key
, sizeof(session_key
),
318 d
->label
.data
, d
->label
.length
,
319 d
->context
.data
, d
->context
.length
,
320 x
->global
->signing_key
.data
);
323 if (xconn
->protocol
>= PROTOCOL_SMB2_24
) {
324 struct _derivation
*d
= &derivation
.decryption
;
326 x
->global
->decryption_key
= data_blob_talloc(x
->global
,
328 sizeof(session_key
));
329 if (x
->global
->decryption_key
.data
== NULL
) {
330 ZERO_STRUCT(session_key
);
331 return NT_STATUS_NO_MEMORY
;
334 smb2_key_derivation(session_key
, sizeof(session_key
),
335 d
->label
.data
, d
->label
.length
,
336 d
->context
.data
, d
->context
.length
,
337 x
->global
->decryption_key
.data
);
340 if (xconn
->protocol
>= PROTOCOL_SMB2_24
) {
341 struct _derivation
*d
= &derivation
.encryption
;
344 x
->global
->encryption_key
= data_blob_talloc(x
->global
,
346 sizeof(session_key
));
347 if (x
->global
->encryption_key
.data
== NULL
) {
348 ZERO_STRUCT(session_key
);
349 return NT_STATUS_NO_MEMORY
;
352 smb2_key_derivation(session_key
, sizeof(session_key
),
353 d
->label
.data
, d
->label
.length
,
354 d
->context
.data
, d
->context
.length
,
355 x
->global
->encryption_key
.data
);
358 * CCM and GCM algorithms must never have their
359 * nonce wrap, or the security of the whole
360 * communication and the keys is destroyed.
361 * We must drop the connection once we have
362 * transfered too much data.
364 * NOTE: We assume nonces greater than 8 bytes.
366 generate_random_buffer((uint8_t *)&x
->nonce_high_random
,
367 sizeof(x
->nonce_high_random
));
368 switch (xconn
->smb2
.server
.cipher
) {
369 case SMB2_ENCRYPTION_AES128_CCM
:
370 nonce_size
= AES_CCM_128_NONCE_SIZE
;
372 case SMB2_ENCRYPTION_AES128_GCM
:
373 nonce_size
= AES_GCM_128_IV_SIZE
;
379 x
->nonce_high_max
= SMB2_NONCE_HIGH_MAX(nonce_size
);
384 x
->global
->application_key
= data_blob_dup_talloc(x
->global
,
385 x
->global
->signing_key
);
386 if (x
->global
->application_key
.data
== NULL
) {
387 ZERO_STRUCT(session_key
);
388 return NT_STATUS_NO_MEMORY
;
391 if (xconn
->protocol
>= PROTOCOL_SMB2_24
) {
392 struct _derivation
*d
= &derivation
.application
;
394 smb2_key_derivation(session_key
, sizeof(session_key
),
395 d
->label
.data
, d
->label
.length
,
396 d
->context
.data
, d
->context
.length
,
397 x
->global
->application_key
.data
);
399 ZERO_STRUCT(session_key
);
401 x
->global
->channels
[0].signing_key
= data_blob_dup_talloc(x
->global
->channels
,
402 x
->global
->signing_key
);
403 if (x
->global
->channels
[0].signing_key
.data
== NULL
) {
404 return NT_STATUS_NO_MEMORY
;
407 data_blob_clear_free(&session_info
->session_key
);
408 session_info
->session_key
= data_blob_dup_talloc(session_info
,
409 x
->global
->application_key
);
410 if (session_info
->session_key
.data
== NULL
) {
411 return NT_STATUS_NO_MEMORY
;
414 session
->compat
= talloc_zero(session
, struct user_struct
);
415 if (session
->compat
== NULL
) {
416 return NT_STATUS_NO_MEMORY
;
418 session
->compat
->session
= session
;
419 session
->compat
->homes_snum
= -1;
420 session
->compat
->session_info
= session_info
;
421 session
->compat
->session_keystr
= NULL
;
422 session
->compat
->vuid
= session
->global
->session_wire_id
;
423 DLIST_ADD(smb2req
->sconn
->users
, session
->compat
);
424 smb2req
->sconn
->num_users
++;
426 if (security_session_user_level(session_info
, NULL
) >= SECURITY_USER
) {
427 session
->compat
->homes_snum
=
428 register_homes_share(session_info
->unix_info
->unix_name
);
431 set_current_user_info(session_info
->unix_info
->sanitized_username
,
432 session_info
->unix_info
->unix_name
,
433 session_info
->info
->domain_name
);
435 reload_services(smb2req
->sconn
, conn_snum_used
, true);
437 session
->status
= NT_STATUS_OK
;
438 session
->global
->auth_session_info
= session_info
;
439 session
->global
->auth_session_info_seqnum
+= 1;
440 session
->global
->channels
[0].auth_session_info_seqnum
=
441 session
->global
->auth_session_info_seqnum
;
442 session
->global
->auth_time
= timeval_to_nttime(&smb2req
->request_time
);
443 session
->global
->expiration_time
= gensec_expire_time(session
->gensec
);
445 if (!session_claim(session
)) {
446 DEBUG(1, ("smb2: Failed to claim session "
448 (unsigned long long)session
->compat
->vuid
));
449 return NT_STATUS_LOGON_FAILURE
;
452 status
= smbXsrv_session_update(session
);
453 if (!NT_STATUS_IS_OK(status
)) {
454 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
455 (unsigned long long)session
->compat
->vuid
,
457 return NT_STATUS_LOGON_FAILURE
;
461 * we attach the session to the request
462 * so that the response can be signed
465 smb2req
->do_signing
= true;
468 global_client_caps
|= (CAP_LEVEL_II_OPLOCKS
|CAP_STATUS32
);
470 *out_session_id
= session
->global
->session_wire_id
;
475 static NTSTATUS
smbd_smb2_reauth_generic_return(struct smbXsrv_session
*session
,
476 struct smbd_smb2_request
*smb2req
,
477 struct auth_session_info
*session_info
,
478 uint16_t *out_session_flags
,
479 uint64_t *out_session_id
)
482 struct smbXsrv_session
*x
= session
;
484 data_blob_clear_free(&session_info
->session_key
);
485 session_info
->session_key
= data_blob_dup_talloc(session_info
,
486 x
->global
->application_key
);
487 if (session_info
->session_key
.data
== NULL
) {
488 return NT_STATUS_NO_MEMORY
;
491 session
->compat
->session_info
= session_info
;
492 session
->compat
->vuid
= session
->global
->session_wire_id
;
494 session
->compat
->homes_snum
=
495 register_homes_share(session_info
->unix_info
->unix_name
);
497 set_current_user_info(session_info
->unix_info
->sanitized_username
,
498 session_info
->unix_info
->unix_name
,
499 session_info
->info
->domain_name
);
501 reload_services(smb2req
->sconn
, conn_snum_used
, true);
503 session
->status
= NT_STATUS_OK
;
504 TALLOC_FREE(session
->global
->auth_session_info
);
505 session
->global
->auth_session_info
= session_info
;
506 session
->global
->auth_session_info_seqnum
+= 1;
507 session
->global
->channels
[0].auth_session_info_seqnum
=
508 session
->global
->auth_session_info_seqnum
;
509 session
->global
->auth_time
= timeval_to_nttime(&smb2req
->request_time
);
510 session
->global
->expiration_time
= gensec_expire_time(session
->gensec
);
512 status
= smbXsrv_session_update(session
);
513 if (!NT_STATUS_IS_OK(status
)) {
514 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
515 (unsigned long long)session
->compat
->vuid
,
517 return NT_STATUS_LOGON_FAILURE
;
520 conn_clear_vuid_caches(smb2req
->sconn
, session
->compat
->vuid
);
522 if (security_session_user_level(session_info
, NULL
) >= SECURITY_USER
) {
523 smb2req
->do_signing
= true;
526 *out_session_id
= session
->global
->session_wire_id
;
531 struct smbd_smb2_session_setup_state
{
532 struct tevent_context
*ev
;
533 struct smbd_smb2_request
*smb2req
;
534 uint64_t in_session_id
;
536 uint8_t in_security_mode
;
537 uint64_t in_previous_session_id
;
538 DATA_BLOB in_security_buffer
;
539 struct smbXsrv_session
*session
;
540 struct auth_session_info
*session_info
;
541 uint16_t out_session_flags
;
542 DATA_BLOB out_security_buffer
;
543 uint64_t out_session_id
;
546 static void smbd_smb2_session_setup_gensec_done(struct tevent_req
*subreq
);
547 static void smbd_smb2_session_setup_previous_done(struct tevent_req
*subreq
);
548 static void smbd_smb2_session_setup_auth_return(struct tevent_req
*req
);
550 static struct tevent_req
*smbd_smb2_session_setup_send(TALLOC_CTX
*mem_ctx
,
551 struct tevent_context
*ev
,
552 struct smbd_smb2_request
*smb2req
,
553 uint64_t in_session_id
,
555 uint8_t in_security_mode
,
556 uint64_t in_previous_session_id
,
557 DATA_BLOB in_security_buffer
)
559 struct tevent_req
*req
;
560 struct smbd_smb2_session_setup_state
*state
;
562 NTTIME now
= timeval_to_nttime(&smb2req
->request_time
);
563 struct tevent_req
*subreq
;
565 req
= tevent_req_create(mem_ctx
, &state
,
566 struct smbd_smb2_session_setup_state
);
571 state
->smb2req
= smb2req
;
572 state
->in_session_id
= in_session_id
;
573 state
->in_flags
= in_flags
;
574 state
->in_security_mode
= in_security_mode
;
575 state
->in_previous_session_id
= in_previous_session_id
;
576 state
->in_security_buffer
= in_security_buffer
;
578 if (in_flags
& SMB2_SESSION_FLAG_BINDING
) {
579 if (smb2req
->xconn
->protocol
< PROTOCOL_SMB2_22
) {
580 tevent_req_nterror(req
, NT_STATUS_REQUEST_NOT_ACCEPTED
);
581 return tevent_req_post(req
, ev
);
585 * We do not support multi channel.
587 tevent_req_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
588 return tevent_req_post(req
, ev
);
591 if (state
->in_session_id
== 0) {
592 /* create a new session */
593 status
= smbXsrv_session_create(state
->smb2req
->xconn
,
594 now
, &state
->session
);
595 if (tevent_req_nterror(req
, status
)) {
596 return tevent_req_post(req
, ev
);
598 smb2req
->session
= state
->session
;
600 if (smb2req
->session
== NULL
) {
601 tevent_req_nterror(req
, NT_STATUS_USER_SESSION_DELETED
);
602 return tevent_req_post(req
, ev
);
605 state
->session
= smb2req
->session
;
606 status
= state
->session
->status
;
607 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
608 status
= NT_STATUS_OK
;
610 if (NT_STATUS_IS_OK(status
)) {
611 state
->session
->status
= NT_STATUS_MORE_PROCESSING_REQUIRED
;
612 status
= NT_STATUS_MORE_PROCESSING_REQUIRED
;
613 TALLOC_FREE(state
->session
->gensec
);
615 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
616 tevent_req_nterror(req
, status
);
617 return tevent_req_post(req
, ev
);
621 if (state
->session
->gensec
== NULL
) {
622 status
= auth_generic_prepare(state
->session
,
623 state
->smb2req
->xconn
->remote_address
,
624 &state
->session
->gensec
);
625 if (tevent_req_nterror(req
, status
)) {
626 return tevent_req_post(req
, ev
);
629 gensec_want_feature(state
->session
->gensec
, GENSEC_FEATURE_SESSION_KEY
);
630 gensec_want_feature(state
->session
->gensec
, GENSEC_FEATURE_UNIX_TOKEN
);
632 status
= gensec_start_mech_by_oid(state
->session
->gensec
,
634 if (tevent_req_nterror(req
, status
)) {
635 return tevent_req_post(req
, ev
);
640 subreq
= gensec_update_send(state
, state
->ev
,
641 state
->session
->gensec
,
642 state
->in_security_buffer
);
644 if (tevent_req_nomem(subreq
, req
)) {
645 return tevent_req_post(req
, ev
);
647 tevent_req_set_callback(subreq
, smbd_smb2_session_setup_gensec_done
, req
);
652 static void smbd_smb2_session_setup_gensec_done(struct tevent_req
*subreq
)
654 struct tevent_req
*req
=
655 tevent_req_callback_data(subreq
,
657 struct smbd_smb2_session_setup_state
*state
=
659 struct smbd_smb2_session_setup_state
);
663 status
= gensec_update_recv(subreq
, state
,
664 &state
->out_security_buffer
);
667 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
668 !NT_STATUS_IS_OK(status
)) {
669 tevent_req_nterror(req
, status
);
673 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
674 state
->out_session_id
= state
->session
->global
->session_wire_id
;
675 state
->smb2req
->preauth
= state
->session
->preauth
;
676 tevent_req_nterror(req
, status
);
680 status
= gensec_session_info(state
->session
->gensec
,
681 state
->session
->global
,
682 &state
->session_info
);
683 if (tevent_req_nterror(req
, status
)) {
687 if ((state
->in_previous_session_id
!= 0) &&
688 (state
->session
->global
->session_wire_id
!=
689 state
->in_previous_session_id
))
691 subreq
= smb2srv_session_close_previous_send(state
, state
->ev
,
692 state
->smb2req
->xconn
,
694 state
->in_previous_session_id
,
695 state
->session
->global
->session_wire_id
);
696 if (tevent_req_nomem(subreq
, req
)) {
699 tevent_req_set_callback(subreq
,
700 smbd_smb2_session_setup_previous_done
,
705 smbd_smb2_session_setup_auth_return(req
);
708 static void smbd_smb2_session_setup_previous_done(struct tevent_req
*subreq
)
710 struct tevent_req
*req
=
711 tevent_req_callback_data(subreq
,
715 status
= smb2srv_session_close_previous_recv(subreq
);
717 if (tevent_req_nterror(req
, status
)) {
721 smbd_smb2_session_setup_auth_return(req
);
724 static void smbd_smb2_session_setup_auth_return(struct tevent_req
*req
)
726 struct smbd_smb2_session_setup_state
*state
=
728 struct smbd_smb2_session_setup_state
);
731 if (state
->session
->global
->auth_session_info
!= NULL
) {
732 status
= smbd_smb2_reauth_generic_return(state
->session
,
735 &state
->out_session_flags
,
736 &state
->out_session_id
);
737 if (tevent_req_nterror(req
, status
)) {
740 tevent_req_done(req
);
744 status
= smbd_smb2_auth_generic_return(state
->session
,
746 state
->in_security_mode
,
748 &state
->out_session_flags
,
749 &state
->out_session_id
);
750 if (tevent_req_nterror(req
, status
)) {
754 tevent_req_done(req
);
758 static NTSTATUS
smbd_smb2_session_setup_recv(struct tevent_req
*req
,
759 uint16_t *out_session_flags
,
761 DATA_BLOB
*out_security_buffer
,
762 uint64_t *out_session_id
)
764 struct smbd_smb2_session_setup_state
*state
=
766 struct smbd_smb2_session_setup_state
);
769 if (tevent_req_is_nterror(req
, &status
)) {
770 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
771 tevent_req_received(req
);
772 return nt_status_squash(status
);
775 status
= NT_STATUS_OK
;
778 *out_session_flags
= state
->out_session_flags
;
779 *out_security_buffer
= state
->out_security_buffer
;
780 *out_session_id
= state
->out_session_id
;
782 talloc_steal(mem_ctx
, out_security_buffer
->data
);
783 tevent_req_received(req
);
787 struct smbd_smb2_session_setup_wrap_state
{
788 struct tevent_context
*ev
;
789 struct smbd_smb2_request
*smb2req
;
790 uint64_t in_session_id
;
792 uint8_t in_security_mode
;
793 uint64_t in_previous_session_id
;
794 DATA_BLOB in_security_buffer
;
795 uint16_t out_session_flags
;
796 DATA_BLOB out_security_buffer
;
797 uint64_t out_session_id
;
801 static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req
*subreq
);
802 static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req
*subreq
);
804 static struct tevent_req
*smbd_smb2_session_setup_wrap_send(TALLOC_CTX
*mem_ctx
,
805 struct tevent_context
*ev
,
806 struct smbd_smb2_request
*smb2req
,
807 uint64_t in_session_id
,
809 uint8_t in_security_mode
,
810 uint64_t in_previous_session_id
,
811 DATA_BLOB in_security_buffer
)
813 struct tevent_req
*req
;
814 struct smbd_smb2_session_setup_wrap_state
*state
;
815 struct tevent_req
*subreq
;
817 req
= tevent_req_create(mem_ctx
, &state
,
818 struct smbd_smb2_session_setup_wrap_state
);
823 state
->smb2req
= smb2req
;
824 state
->in_session_id
= in_session_id
;
825 state
->in_flags
= in_flags
;
826 state
->in_security_mode
= in_security_mode
;
827 state
->in_previous_session_id
= in_previous_session_id
;
828 state
->in_security_buffer
= in_security_buffer
;
830 subreq
= smbd_smb2_session_setup_send(state
, state
->ev
,
832 state
->in_session_id
,
834 state
->in_security_mode
,
835 state
->in_previous_session_id
,
836 state
->in_security_buffer
);
837 if (tevent_req_nomem(subreq
, req
)) {
838 return tevent_req_post(req
, ev
);
840 tevent_req_set_callback(subreq
,
841 smbd_smb2_session_setup_wrap_setup_done
, req
);
846 static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req
*subreq
)
848 struct tevent_req
*req
=
849 tevent_req_callback_data(subreq
,
851 struct smbd_smb2_session_setup_wrap_state
*state
=
853 struct smbd_smb2_session_setup_wrap_state
);
856 status
= smbd_smb2_session_setup_recv(subreq
,
857 &state
->out_session_flags
,
859 &state
->out_security_buffer
,
860 &state
->out_session_id
);
862 if (NT_STATUS_IS_OK(status
)) {
863 tevent_req_done(req
);
866 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
867 tevent_req_nterror(req
, status
);
871 if (state
->smb2req
->session
== NULL
) {
872 tevent_req_nterror(req
, status
);
876 state
->error
= status
;
878 subreq
= smb2srv_session_shutdown_send(state
, state
->ev
,
879 state
->smb2req
->session
,
881 if (tevent_req_nomem(subreq
, req
)) {
884 tevent_req_set_callback(subreq
,
885 smbd_smb2_session_setup_wrap_shutdown_done
,
889 static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req
*subreq
)
891 struct tevent_req
*req
=
892 tevent_req_callback_data(subreq
,
894 struct smbd_smb2_session_setup_wrap_state
*state
=
896 struct smbd_smb2_session_setup_wrap_state
);
899 status
= smb2srv_session_shutdown_recv(subreq
);
901 if (tevent_req_nterror(req
, status
)) {
906 * we may need to sign the response, so we need to keep
907 * the session until the response is sent to the wire.
909 talloc_steal(state
->smb2req
, state
->smb2req
->session
);
911 tevent_req_nterror(req
, state
->error
);
914 static NTSTATUS
smbd_smb2_session_setup_wrap_recv(struct tevent_req
*req
,
915 uint16_t *out_session_flags
,
917 DATA_BLOB
*out_security_buffer
,
918 uint64_t *out_session_id
)
920 struct smbd_smb2_session_setup_wrap_state
*state
=
922 struct smbd_smb2_session_setup_wrap_state
);
925 if (tevent_req_is_nterror(req
, &status
)) {
926 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
927 tevent_req_received(req
);
928 return nt_status_squash(status
);
931 status
= NT_STATUS_OK
;
934 *out_session_flags
= state
->out_session_flags
;
935 *out_security_buffer
= state
->out_security_buffer
;
936 *out_session_id
= state
->out_session_id
;
938 talloc_steal(mem_ctx
, out_security_buffer
->data
);
939 tevent_req_received(req
);
943 static struct tevent_req
*smbd_smb2_logoff_send(TALLOC_CTX
*mem_ctx
,
944 struct tevent_context
*ev
,
945 struct smbd_smb2_request
*smb2req
);
946 static NTSTATUS
smbd_smb2_logoff_recv(struct tevent_req
*req
);
947 static void smbd_smb2_request_logoff_done(struct tevent_req
*subreq
);
949 NTSTATUS
smbd_smb2_request_process_logoff(struct smbd_smb2_request
*req
)
952 struct tevent_req
*subreq
= NULL
;
954 status
= smbd_smb2_request_verify_sizes(req
, 0x04);
955 if (!NT_STATUS_IS_OK(status
)) {
956 return smbd_smb2_request_error(req
, status
);
959 subreq
= smbd_smb2_logoff_send(req
, req
->sconn
->ev_ctx
, req
);
960 if (subreq
== NULL
) {
961 return smbd_smb2_request_error(req
, NT_STATUS_NO_MEMORY
);
963 tevent_req_set_callback(subreq
, smbd_smb2_request_logoff_done
, req
);
966 * Wait a long time before going async on this to allow
967 * requests we're waiting on to finish. Set timeout to 10 secs.
969 return smbd_smb2_request_pending_queue(req
, subreq
, 10000000);
972 static void smbd_smb2_request_logoff_done(struct tevent_req
*subreq
)
974 struct smbd_smb2_request
*smb2req
=
975 tevent_req_callback_data(subreq
,
976 struct smbd_smb2_request
);
981 status
= smbd_smb2_logoff_recv(subreq
);
983 if (!NT_STATUS_IS_OK(status
)) {
984 error
= smbd_smb2_request_error(smb2req
, status
);
985 if (!NT_STATUS_IS_OK(error
)) {
986 smbd_server_connection_terminate(smb2req
->xconn
,
993 outbody
= smbd_smb2_generate_outbody(smb2req
, 0x04);
994 if (outbody
.data
== NULL
) {
995 error
= smbd_smb2_request_error(smb2req
, NT_STATUS_NO_MEMORY
);
996 if (!NT_STATUS_IS_OK(error
)) {
997 smbd_server_connection_terminate(smb2req
->xconn
,
1004 SSVAL(outbody
.data
, 0x00, 0x04); /* struct size */
1005 SSVAL(outbody
.data
, 0x02, 0); /* reserved */
1007 error
= smbd_smb2_request_done(smb2req
, outbody
, NULL
);
1008 if (!NT_STATUS_IS_OK(error
)) {
1009 smbd_server_connection_terminate(smb2req
->xconn
,
1015 struct smbd_smb2_logoff_state
{
1016 struct smbd_smb2_request
*smb2req
;
1019 static void smbd_smb2_logoff_shutdown_done(struct tevent_req
*subreq
);
1021 static struct tevent_req
*smbd_smb2_logoff_send(TALLOC_CTX
*mem_ctx
,
1022 struct tevent_context
*ev
,
1023 struct smbd_smb2_request
*smb2req
)
1025 struct tevent_req
*req
;
1026 struct smbd_smb2_logoff_state
*state
;
1027 struct tevent_req
*subreq
;
1029 req
= tevent_req_create(mem_ctx
, &state
,
1030 struct smbd_smb2_logoff_state
);
1034 state
->smb2req
= smb2req
;
1036 subreq
= smb2srv_session_shutdown_send(state
, ev
,
1039 if (tevent_req_nomem(subreq
, req
)) {
1040 return tevent_req_post(req
, ev
);
1042 tevent_req_set_callback(subreq
, smbd_smb2_logoff_shutdown_done
, req
);
1047 static void smbd_smb2_logoff_shutdown_done(struct tevent_req
*subreq
)
1049 struct tevent_req
*req
= tevent_req_callback_data(
1050 subreq
, struct tevent_req
);
1051 struct smbd_smb2_logoff_state
*state
= tevent_req_data(
1052 req
, struct smbd_smb2_logoff_state
);
1055 status
= smb2srv_session_shutdown_recv(subreq
);
1056 if (tevent_req_nterror(req
, status
)) {
1059 TALLOC_FREE(subreq
);
1062 * As we've been awoken, we may have changed
1063 * uid in the meantime. Ensure we're still
1064 * root (SMB2_OP_LOGOFF has .as_root = true).
1066 change_to_root_user();
1068 status
= smbXsrv_session_logoff(state
->smb2req
->session
);
1069 if (tevent_req_nterror(req
, status
)) {
1074 * we may need to sign the response, so we need to keep
1075 * the session until the response is sent to the wire.
1077 talloc_steal(state
->smb2req
, state
->smb2req
->session
);
1079 tevent_req_done(req
);
1082 static NTSTATUS
smbd_smb2_logoff_recv(struct tevent_req
*req
)
1084 return tevent_req_simple_recv_ntstatus(req
);