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