2 Unix SMB/CIFS implementation.
5 Copyright (C) Stefan Metzmacher 2009
6 Copyright (C) Jeremy Allison 2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../libcli/smb/smb_common.h"
26 #include "../auth/gensec/gensec.h"
28 #include "../lib/tsocket/tsocket.h"
29 #include "../libcli/security/security.h"
30 #include "../lib/util/tevent_ntstatus.h"
31 #include "lib/crypto/sha512.h"
32 #include "lib/crypto/aes.h"
33 #include "lib/crypto/aes_ccm_128.h"
34 #include "lib/crypto/aes_gcm_128.h"
37 #define DBGC_CLASS DBGC_SMB2
39 static struct tevent_req
*smbd_smb2_session_setup_wrap_send(TALLOC_CTX
*mem_ctx
,
40 struct tevent_context
*ev
,
41 struct smbd_smb2_request
*smb2req
,
42 uint64_t in_session_id
,
44 uint8_t in_security_mode
,
45 uint64_t in_previous_session_id
,
46 DATA_BLOB in_security_buffer
);
47 static NTSTATUS
smbd_smb2_session_setup_wrap_recv(struct tevent_req
*req
,
48 uint16_t *out_session_flags
,
50 DATA_BLOB
*out_security_buffer
,
51 uint64_t *out_session_id
);
53 static void smbd_smb2_request_sesssetup_done(struct tevent_req
*subreq
);
55 NTSTATUS
smbd_smb2_request_process_sesssetup(struct smbd_smb2_request
*smb2req
)
58 const uint8_t *inbody
;
59 uint64_t in_session_id
;
61 uint8_t in_security_mode
;
62 uint64_t in_previous_session_id
;
63 uint16_t in_security_offset
;
64 uint16_t in_security_length
;
65 DATA_BLOB in_security_buffer
;
67 struct tevent_req
*subreq
;
69 status
= smbd_smb2_request_verify_sizes(smb2req
, 0x19);
70 if (!NT_STATUS_IS_OK(status
)) {
71 return smbd_smb2_request_error(smb2req
, status
);
73 inhdr
= SMBD_SMB2_IN_HDR_PTR(smb2req
);
74 inbody
= SMBD_SMB2_IN_BODY_PTR(smb2req
);
76 in_session_id
= BVAL(inhdr
, SMB2_HDR_SESSION_ID
);
78 in_flags
= CVAL(inbody
, 0x02);
79 in_security_mode
= CVAL(inbody
, 0x03);
80 /* Capabilities = IVAL(inbody, 0x04) */
81 /* Channel = IVAL(inbody, 0x08) */
82 in_security_offset
= SVAL(inbody
, 0x0C);
83 in_security_length
= SVAL(inbody
, 0x0E);
84 in_previous_session_id
= BVAL(inbody
, 0x10);
86 if (in_security_offset
!= (SMB2_HDR_BODY
+ SMBD_SMB2_IN_BODY_LEN(smb2req
))) {
87 return smbd_smb2_request_error(smb2req
, NT_STATUS_INVALID_PARAMETER
);
90 if (in_security_length
> SMBD_SMB2_IN_DYN_LEN(smb2req
)) {
91 return smbd_smb2_request_error(smb2req
, NT_STATUS_INVALID_PARAMETER
);
94 in_security_buffer
.data
= SMBD_SMB2_IN_DYN_PTR(smb2req
);
95 in_security_buffer
.length
= in_security_length
;
97 subreq
= smbd_smb2_session_setup_wrap_send(smb2req
,
103 in_previous_session_id
,
105 if (subreq
== NULL
) {
106 return smbd_smb2_request_error(smb2req
, NT_STATUS_NO_MEMORY
);
108 tevent_req_set_callback(subreq
, smbd_smb2_request_sesssetup_done
, smb2req
);
110 return smbd_smb2_request_pending_queue(smb2req
, subreq
, 500);
113 static void smbd_smb2_request_sesssetup_done(struct tevent_req
*subreq
)
115 struct smbd_smb2_request
*smb2req
=
116 tevent_req_callback_data(subreq
,
117 struct smbd_smb2_request
);
121 uint16_t out_session_flags
= 0;
122 uint64_t out_session_id
= 0;
123 uint16_t out_security_offset
;
124 DATA_BLOB out_security_buffer
= data_blob_null
;
126 NTSTATUS error
; /* transport error */
128 status
= smbd_smb2_session_setup_wrap_recv(subreq
,
131 &out_security_buffer
,
134 if (!NT_STATUS_IS_OK(status
) &&
135 !NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
136 status
= nt_status_squash(status
);
137 error
= smbd_smb2_request_error(smb2req
, status
);
138 if (!NT_STATUS_IS_OK(error
)) {
139 smbd_server_connection_terminate(smb2req
->xconn
,
146 out_security_offset
= SMB2_HDR_BODY
+ 0x08;
148 outhdr
= SMBD_SMB2_OUT_HDR_PTR(smb2req
);
150 outbody
= smbd_smb2_generate_outbody(smb2req
, 0x08);
151 if (outbody
.data
== NULL
) {
152 error
= smbd_smb2_request_error(smb2req
, NT_STATUS_NO_MEMORY
);
153 if (!NT_STATUS_IS_OK(error
)) {
154 smbd_server_connection_terminate(smb2req
->xconn
,
161 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
, out_session_id
);
163 SSVAL(outbody
.data
, 0x00, 0x08 + 1); /* struct size */
164 SSVAL(outbody
.data
, 0x02,
165 out_session_flags
); /* session flags */
166 SSVAL(outbody
.data
, 0x04,
167 out_security_offset
); /* security buffer offset */
168 SSVAL(outbody
.data
, 0x06,
169 out_security_buffer
.length
); /* security buffer length */
171 outdyn
= out_security_buffer
;
173 error
= smbd_smb2_request_done_ex(smb2req
, status
, outbody
, &outdyn
,
175 if (!NT_STATUS_IS_OK(error
)) {
176 smbd_server_connection_terminate(smb2req
->xconn
,
182 static NTSTATUS
smbd_smb2_auth_generic_return(struct smbXsrv_session
*session
,
183 struct smbXsrv_session_auth0
**_auth
,
184 struct smbd_smb2_request
*smb2req
,
185 uint8_t in_security_mode
,
186 struct auth_session_info
*session_info
,
187 uint16_t *out_session_flags
,
188 uint64_t *out_session_id
)
192 uint8_t session_key
[16];
193 struct smbXsrv_session
*x
= session
;
194 struct smbXsrv_session_auth0
*auth
= *_auth
;
195 struct smbXsrv_connection
*xconn
= smb2req
->xconn
;
202 struct _derivation signing
;
203 struct _derivation encryption
;
204 struct _derivation decryption
;
205 struct _derivation application
;
210 if (xconn
->protocol
>= PROTOCOL_SMB3_10
) {
211 struct smbXsrv_preauth
*preauth
;
212 struct _derivation
*d
;
214 struct hc_sha512state sctx
;
216 preauth
= talloc_move(smb2req
, &auth
->preauth
);
218 samba_SHA512_Init(&sctx
);
219 samba_SHA512_Update(&sctx
, preauth
->sha512_value
,
220 sizeof(preauth
->sha512_value
));
221 for (i
= 1; i
< smb2req
->in
.vector_count
; i
++) {
222 samba_SHA512_Update(&sctx
,
223 smb2req
->in
.vector
[i
].iov_base
,
224 smb2req
->in
.vector
[i
].iov_len
);
226 samba_SHA512_Final(preauth
->sha512_value
, &sctx
);
228 p
= data_blob_const(preauth
->sha512_value
,
229 sizeof(preauth
->sha512_value
));
231 d
= &derivation
.signing
;
232 d
->label
= data_blob_string_const_null("SMBSigningKey");
235 d
= &derivation
.decryption
;
236 d
->label
= data_blob_string_const_null("SMBC2SCipherKey");
239 d
= &derivation
.encryption
;
240 d
->label
= data_blob_string_const_null("SMBS2CCipherKey");
243 d
= &derivation
.application
;
244 d
->label
= data_blob_string_const_null("SMBAppKey");
247 } else if (xconn
->protocol
>= PROTOCOL_SMB2_24
) {
248 struct _derivation
*d
;
250 d
= &derivation
.signing
;
251 d
->label
= data_blob_string_const_null("SMB2AESCMAC");
252 d
->context
= data_blob_string_const_null("SmbSign");
254 d
= &derivation
.decryption
;
255 d
->label
= data_blob_string_const_null("SMB2AESCCM");
256 d
->context
= data_blob_string_const_null("ServerIn ");
258 d
= &derivation
.encryption
;
259 d
->label
= data_blob_string_const_null("SMB2AESCCM");
260 d
->context
= data_blob_string_const_null("ServerOut");
262 d
= &derivation
.application
;
263 d
->label
= data_blob_string_const_null("SMB2APP");
264 d
->context
= data_blob_string_const_null("SmbRpc");
267 if ((in_security_mode
& SMB2_NEGOTIATE_SIGNING_REQUIRED
) ||
268 (xconn
->smb2
.server
.security_mode
& SMB2_NEGOTIATE_SIGNING_REQUIRED
))
270 x
->global
->signing_flags
= SMBXSRV_SIGNING_REQUIRED
;
273 if ((lp_smb_encrypt(-1) >= SMB_SIGNING_DESIRED
) &&
274 (xconn
->smb2
.client
.capabilities
& SMB2_CAP_ENCRYPTION
)) {
275 x
->global
->encryption_flags
= SMBXSRV_ENCRYPTION_DESIRED
;
278 if (lp_smb_encrypt(-1) == SMB_SIGNING_REQUIRED
) {
279 x
->global
->encryption_flags
= SMBXSRV_ENCRYPTION_REQUIRED
|
280 SMBXSRV_ENCRYPTION_DESIRED
;
283 if (security_session_user_level(session_info
, NULL
) < SECURITY_USER
) {
284 if (security_session_user_level(session_info
, NULL
) == SECURITY_GUEST
) {
285 *out_session_flags
|= SMB2_SESSION_FLAG_IS_GUEST
;
287 /* force no signing */
288 x
->global
->signing_flags
&= ~SMBXSRV_SIGNING_REQUIRED
;
289 /* we map anonymous to guest internally */
293 if (guest
&& (x
->global
->encryption_flags
& SMBXSRV_ENCRYPTION_REQUIRED
)) {
294 DEBUG(1,("reject guest session as encryption is required\n"));
295 return NT_STATUS_ACCESS_DENIED
;
298 if (xconn
->smb2
.server
.cipher
== 0) {
299 if (x
->global
->encryption_flags
& SMBXSRV_ENCRYPTION_REQUIRED
) {
300 DEBUG(1,("reject session with dialect[0x%04X] "
301 "as encryption is required\n",
302 xconn
->smb2
.server
.dialect
));
303 return NT_STATUS_ACCESS_DENIED
;
306 x
->global
->channels
[0].encryption_cipher
= xconn
->smb2
.server
.cipher
;
309 if (x
->global
->encryption_flags
& SMBXSRV_ENCRYPTION_DESIRED
) {
310 *out_session_flags
|= SMB2_SESSION_FLAG_ENCRYPT_DATA
;
313 ZERO_STRUCT(session_key
);
314 memcpy(session_key
, session_info
->session_key
.data
,
315 MIN(session_info
->session_key
.length
, sizeof(session_key
)));
317 x
->global
->signing_key
= data_blob_talloc(x
->global
,
319 sizeof(session_key
));
320 if (x
->global
->signing_key
.data
== NULL
) {
321 ZERO_STRUCT(session_key
);
322 return NT_STATUS_NO_MEMORY
;
325 if (xconn
->protocol
>= PROTOCOL_SMB2_24
) {
326 struct _derivation
*d
= &derivation
.signing
;
328 smb2_key_derivation(session_key
, sizeof(session_key
),
329 d
->label
.data
, d
->label
.length
,
330 d
->context
.data
, d
->context
.length
,
331 x
->global
->signing_key
.data
);
334 if (xconn
->protocol
>= PROTOCOL_SMB2_24
) {
335 struct _derivation
*d
= &derivation
.decryption
;
337 x
->global
->decryption_key
= data_blob_talloc(x
->global
,
339 sizeof(session_key
));
340 if (x
->global
->decryption_key
.data
== NULL
) {
341 ZERO_STRUCT(session_key
);
342 return NT_STATUS_NO_MEMORY
;
345 smb2_key_derivation(session_key
, sizeof(session_key
),
346 d
->label
.data
, d
->label
.length
,
347 d
->context
.data
, d
->context
.length
,
348 x
->global
->decryption_key
.data
);
351 if (xconn
->protocol
>= PROTOCOL_SMB2_24
) {
352 struct _derivation
*d
= &derivation
.encryption
;
355 x
->global
->encryption_key
= data_blob_talloc(x
->global
,
357 sizeof(session_key
));
358 if (x
->global
->encryption_key
.data
== NULL
) {
359 ZERO_STRUCT(session_key
);
360 return NT_STATUS_NO_MEMORY
;
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
->encryption_key
.data
);
369 * CCM and GCM algorithms must never have their
370 * nonce wrap, or the security of the whole
371 * communication and the keys is destroyed.
372 * We must drop the connection once we have
373 * transfered too much data.
375 * NOTE: We assume nonces greater than 8 bytes.
377 generate_random_buffer((uint8_t *)&x
->nonce_high_random
,
378 sizeof(x
->nonce_high_random
));
379 switch (xconn
->smb2
.server
.cipher
) {
380 case SMB2_ENCRYPTION_AES128_CCM
:
381 nonce_size
= AES_CCM_128_NONCE_SIZE
;
383 case SMB2_ENCRYPTION_AES128_GCM
:
384 nonce_size
= AES_GCM_128_IV_SIZE
;
390 x
->nonce_high_max
= SMB2_NONCE_HIGH_MAX(nonce_size
);
395 x
->global
->application_key
= data_blob_dup_talloc(x
->global
,
396 x
->global
->signing_key
);
397 if (x
->global
->application_key
.data
== NULL
) {
398 ZERO_STRUCT(session_key
);
399 return NT_STATUS_NO_MEMORY
;
402 if (xconn
->protocol
>= PROTOCOL_SMB2_24
) {
403 struct _derivation
*d
= &derivation
.application
;
405 smb2_key_derivation(session_key
, sizeof(session_key
),
406 d
->label
.data
, d
->label
.length
,
407 d
->context
.data
, d
->context
.length
,
408 x
->global
->application_key
.data
);
410 ZERO_STRUCT(session_key
);
412 x
->global
->channels
[0].signing_key
= data_blob_dup_talloc(x
->global
->channels
,
413 x
->global
->signing_key
);
414 if (x
->global
->channels
[0].signing_key
.data
== NULL
) {
415 return NT_STATUS_NO_MEMORY
;
418 data_blob_clear_free(&session_info
->session_key
);
419 session_info
->session_key
= data_blob_dup_talloc(session_info
,
420 x
->global
->application_key
);
421 if (session_info
->session_key
.data
== NULL
) {
422 return NT_STATUS_NO_MEMORY
;
425 session
->compat
= talloc_zero(session
, struct user_struct
);
426 if (session
->compat
== NULL
) {
427 return NT_STATUS_NO_MEMORY
;
429 session
->compat
->session
= session
;
430 session
->compat
->homes_snum
= -1;
431 session
->compat
->session_info
= session_info
;
432 session
->compat
->session_keystr
= NULL
;
433 session
->compat
->vuid
= session
->global
->session_wire_id
;
434 DLIST_ADD(smb2req
->sconn
->users
, session
->compat
);
435 smb2req
->sconn
->num_users
++;
437 if (security_session_user_level(session_info
, NULL
) >= SECURITY_USER
) {
438 session
->compat
->homes_snum
=
439 register_homes_share(session_info
->unix_info
->unix_name
);
442 set_current_user_info(session_info
->unix_info
->sanitized_username
,
443 session_info
->unix_info
->unix_name
,
444 session_info
->info
->domain_name
);
446 reload_services(smb2req
->sconn
, conn_snum_used
, true);
448 session
->status
= NT_STATUS_OK
;
449 session
->global
->auth_session_info
= talloc_move(session
->global
,
451 session
->global
->auth_session_info_seqnum
+= 1;
452 for (i
=0; i
< session
->global
->num_channels
; i
++) {
453 struct smbXsrv_channel_global0
*_c
=
454 &session
->global
->channels
[i
];
456 _c
->auth_session_info_seqnum
=
457 session
->global
->auth_session_info_seqnum
;
459 session
->global
->auth_time
= timeval_to_nttime(&smb2req
->request_time
);
460 session
->global
->expiration_time
= gensec_expire_time(auth
->gensec
);
462 if (!session_claim(session
)) {
463 DEBUG(1, ("smb2: Failed to claim session "
465 (unsigned long long)session
->compat
->vuid
));
466 return NT_STATUS_LOGON_FAILURE
;
470 status
= smbXsrv_session_update(session
);
471 if (!NT_STATUS_IS_OK(status
)) {
472 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
473 (unsigned long long)session
->compat
->vuid
,
475 return NT_STATUS_LOGON_FAILURE
;
479 * we attach the session to the request
480 * so that the response can be signed
483 smb2req
->do_signing
= true;
486 global_client_caps
|= (CAP_LEVEL_II_OPLOCKS
|CAP_STATUS32
);
488 *out_session_id
= session
->global
->session_wire_id
;
489 smb2req
->last_session_id
= session
->global
->session_wire_id
;
494 static NTSTATUS
smbd_smb2_reauth_generic_return(struct smbXsrv_session
*session
,
495 struct smbXsrv_session_auth0
**_auth
,
496 struct smbd_smb2_request
*smb2req
,
497 struct auth_session_info
*session_info
,
498 uint16_t *out_session_flags
,
499 uint64_t *out_session_id
)
502 struct smbXsrv_session
*x
= session
;
503 struct smbXsrv_session_auth0
*auth
= *_auth
;
504 struct smbXsrv_connection
*xconn
= smb2req
->xconn
;
509 data_blob_clear_free(&session_info
->session_key
);
510 session_info
->session_key
= data_blob_dup_talloc(session_info
,
511 x
->global
->application_key
);
512 if (session_info
->session_key
.data
== NULL
) {
513 return NT_STATUS_NO_MEMORY
;
516 session
->compat
->session_info
= session_info
;
517 session
->compat
->vuid
= session
->global
->session_wire_id
;
519 session
->compat
->homes_snum
=
520 register_homes_share(session_info
->unix_info
->unix_name
);
522 set_current_user_info(session_info
->unix_info
->sanitized_username
,
523 session_info
->unix_info
->unix_name
,
524 session_info
->info
->domain_name
);
526 reload_services(smb2req
->sconn
, conn_snum_used
, true);
528 session
->status
= NT_STATUS_OK
;
529 TALLOC_FREE(session
->global
->auth_session_info
);
530 session
->global
->auth_session_info
= talloc_move(session
->global
,
532 session
->global
->auth_session_info_seqnum
+= 1;
533 for (i
=0; i
< session
->global
->num_channels
; i
++) {
534 struct smbXsrv_channel_global0
*_c
=
535 &session
->global
->channels
[i
];
537 _c
->auth_session_info_seqnum
=
538 session
->global
->auth_session_info_seqnum
;
540 session
->global
->auth_time
= timeval_to_nttime(&smb2req
->request_time
);
541 session
->global
->expiration_time
= gensec_expire_time(auth
->gensec
);
544 status
= smbXsrv_session_update(session
);
545 if (!NT_STATUS_IS_OK(status
)) {
546 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
547 (unsigned long long)session
->compat
->vuid
,
549 return NT_STATUS_LOGON_FAILURE
;
552 conn_clear_vuid_caches(xconn
->client
->sconn
, session
->compat
->vuid
);
554 if (security_session_user_level(session_info
, NULL
) >= SECURITY_USER
) {
555 smb2req
->do_signing
= true;
558 *out_session_id
= session
->global
->session_wire_id
;
563 static NTSTATUS
smbd_smb2_bind_auth_return(struct smbXsrv_session
*session
,
564 struct smbXsrv_session_auth0
**_auth
,
565 struct smbd_smb2_request
*smb2req
,
566 struct auth_session_info
*session_info
,
567 uint16_t *out_session_flags
,
568 uint64_t *out_session_id
)
571 struct smbXsrv_session
*x
= session
;
572 struct smbXsrv_session_auth0
*auth
= *_auth
;
573 struct smbXsrv_connection
*xconn
= smb2req
->xconn
;
574 struct smbXsrv_channel_global0
*c
= NULL
;
575 uint8_t session_key
[16];
582 struct _derivation signing
;
588 if (xconn
->protocol
>= PROTOCOL_SMB3_10
) {
589 struct smbXsrv_preauth
*preauth
;
590 struct _derivation
*d
;
592 struct hc_sha512state sctx
;
594 preauth
= talloc_move(smb2req
, &auth
->preauth
);
596 samba_SHA512_Init(&sctx
);
597 samba_SHA512_Update(&sctx
, preauth
->sha512_value
,
598 sizeof(preauth
->sha512_value
));
599 for (i
= 1; i
< smb2req
->in
.vector_count
; i
++) {
600 samba_SHA512_Update(&sctx
,
601 smb2req
->in
.vector
[i
].iov_base
,
602 smb2req
->in
.vector
[i
].iov_len
);
604 samba_SHA512_Final(preauth
->sha512_value
, &sctx
);
606 p
= data_blob_const(preauth
->sha512_value
,
607 sizeof(preauth
->sha512_value
));
609 d
= &derivation
.signing
;
610 d
->label
= data_blob_string_const_null("SMBSigningKey");
613 } else if (xconn
->protocol
>= PROTOCOL_SMB2_24
) {
614 struct _derivation
*d
;
616 d
= &derivation
.signing
;
617 d
->label
= data_blob_string_const_null("SMB2AESCMAC");
618 d
->context
= data_blob_string_const_null("SmbSign");
621 status
= smbXsrv_session_find_channel(session
, xconn
, &c
);
622 if (!NT_STATUS_IS_OK(status
)) {
626 ok
= security_token_is_sid(session_info
->security_token
,
627 &x
->global
->auth_session_info
->security_token
->sids
[0]);
629 return NT_STATUS_NOT_SUPPORTED
;
632 if (session_info
->session_key
.length
== 0) {
633 /* See [MS-SMB2] 3.3.5.2.4 for the return code. */
634 return NT_STATUS_NOT_SUPPORTED
;
637 ZERO_STRUCT(session_key
);
638 memcpy(session_key
, session_info
->session_key
.data
,
639 MIN(session_info
->session_key
.length
, sizeof(session_key
)));
641 c
->signing_key
= data_blob_talloc(x
->global
,
643 sizeof(session_key
));
644 if (c
->signing_key
.data
== NULL
) {
645 ZERO_STRUCT(session_key
);
646 return NT_STATUS_NO_MEMORY
;
649 if (xconn
->protocol
>= PROTOCOL_SMB2_24
) {
650 struct _derivation
*d
= &derivation
.signing
;
652 smb2_key_derivation(session_key
, sizeof(session_key
),
653 d
->label
.data
, d
->label
.length
,
654 d
->context
.data
, d
->context
.length
,
655 c
->signing_key
.data
);
657 ZERO_STRUCT(session_key
);
660 status
= smbXsrv_session_update(session
);
661 if (!NT_STATUS_IS_OK(status
)) {
662 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
663 (unsigned long long)session
->compat
->vuid
,
665 return NT_STATUS_LOGON_FAILURE
;
668 *out_session_id
= session
->global
->session_wire_id
;
673 struct smbd_smb2_session_setup_state
{
674 struct tevent_context
*ev
;
675 struct smbd_smb2_request
*smb2req
;
676 uint64_t in_session_id
;
678 uint8_t in_security_mode
;
679 uint64_t in_previous_session_id
;
680 DATA_BLOB in_security_buffer
;
681 struct smbXsrv_session
*session
;
682 struct smbXsrv_session_auth0
*auth
;
683 struct auth_session_info
*session_info
;
684 uint16_t out_session_flags
;
685 DATA_BLOB out_security_buffer
;
686 uint64_t out_session_id
;
689 static void smbd_smb2_session_setup_gensec_done(struct tevent_req
*subreq
);
690 static void smbd_smb2_session_setup_previous_done(struct tevent_req
*subreq
);
691 static void smbd_smb2_session_setup_auth_return(struct tevent_req
*req
);
693 static struct tevent_req
*smbd_smb2_session_setup_send(TALLOC_CTX
*mem_ctx
,
694 struct tevent_context
*ev
,
695 struct smbd_smb2_request
*smb2req
,
696 uint64_t in_session_id
,
698 uint8_t in_security_mode
,
699 uint64_t in_previous_session_id
,
700 DATA_BLOB in_security_buffer
)
702 struct tevent_req
*req
;
703 struct smbd_smb2_session_setup_state
*state
;
705 NTTIME now
= timeval_to_nttime(&smb2req
->request_time
);
706 struct tevent_req
*subreq
;
707 struct smbXsrv_channel_global0
*c
= NULL
;
708 enum security_user_level seclvl
;
710 req
= tevent_req_create(mem_ctx
, &state
,
711 struct smbd_smb2_session_setup_state
);
716 state
->smb2req
= smb2req
;
717 state
->in_session_id
= in_session_id
;
718 state
->in_flags
= in_flags
;
719 state
->in_security_mode
= in_security_mode
;
720 state
->in_previous_session_id
= in_previous_session_id
;
721 state
->in_security_buffer
= in_security_buffer
;
723 if (in_flags
& SMB2_SESSION_FLAG_BINDING
) {
724 if (smb2req
->xconn
->protocol
< PROTOCOL_SMB2_22
) {
725 tevent_req_nterror(req
, NT_STATUS_REQUEST_NOT_ACCEPTED
);
726 return tevent_req_post(req
, ev
);
729 if (!smb2req
->xconn
->client
->server_multi_channel_enabled
) {
730 tevent_req_nterror(req
, NT_STATUS_REQUEST_NOT_ACCEPTED
);
731 return tevent_req_post(req
, ev
);
734 if (in_session_id
== 0) {
735 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
736 return tevent_req_post(req
, ev
);
739 if (smb2req
->session
== NULL
) {
740 tevent_req_nterror(req
, NT_STATUS_USER_SESSION_DELETED
);
741 return tevent_req_post(req
, ev
);
744 if (!smb2req
->do_signing
) {
745 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
746 return tevent_req_post(req
, ev
);
749 status
= smbXsrv_session_find_channel(smb2req
->session
,
752 if (NT_STATUS_IS_OK(status
)) {
753 if (c
->signing_key
.length
== 0) {
756 tevent_req_nterror(req
, NT_STATUS_REQUEST_NOT_ACCEPTED
);
757 return tevent_req_post(req
, ev
);
761 * OLD: 3.00 NEW 3.02 => INVALID_PARAMETER
762 * OLD: 3.02 NEW 3.00 => INVALID_PARAMETER
763 * OLD: 2.10 NEW 3.02 => ACCESS_DENIED
764 * OLD: 3.02 NEW 2.10 => ACCESS_DENIED
766 if (smb2req
->session
->global
->connection_dialect
767 < SMB2_DIALECT_REVISION_222
)
769 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
770 return tevent_req_post(req
, ev
);
772 if (smb2req
->xconn
->smb2
.server
.dialect
773 < SMB2_DIALECT_REVISION_222
)
775 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
776 return tevent_req_post(req
, ev
);
778 if (smb2req
->session
->global
->connection_dialect
779 != smb2req
->xconn
->smb2
.server
.dialect
)
781 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
782 return tevent_req_post(req
, ev
);
785 seclvl
= security_session_user_level(
786 smb2req
->session
->global
->auth_session_info
,
788 if (seclvl
< SECURITY_USER
) {
789 tevent_req_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
790 return tevent_req_post(req
, ev
);
793 status
= smbXsrv_session_add_channel(smb2req
->session
,
796 if (!NT_STATUS_IS_OK(status
)) {
797 tevent_req_nterror(req
, status
);
798 return tevent_req_post(req
, ev
);
801 status
= smbXsrv_session_update(smb2req
->session
);
802 if (!NT_STATUS_IS_OK(status
)) {
803 tevent_req_nterror(req
, status
);
804 return tevent_req_post(req
, ev
);
810 if (state
->in_session_id
== 0) {
811 /* create a new session */
812 status
= smbXsrv_session_create(state
->smb2req
->xconn
,
813 now
, &state
->session
);
814 if (tevent_req_nterror(req
, status
)) {
815 return tevent_req_post(req
, ev
);
817 smb2req
->session
= state
->session
;
819 if (smb2req
->session
== NULL
) {
820 tevent_req_nterror(req
, NT_STATUS_USER_SESSION_DELETED
);
821 return tevent_req_post(req
, ev
);
824 state
->session
= smb2req
->session
;
825 status
= state
->session
->status
;
826 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
827 status
= NT_STATUS_OK
;
829 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
830 status
= NT_STATUS_OK
;
832 if (tevent_req_nterror(req
, status
)) {
833 return tevent_req_post(req
, ev
);
835 if (!(in_flags
& SMB2_SESSION_FLAG_BINDING
)) {
836 state
->session
->status
= NT_STATUS_MORE_PROCESSING_REQUIRED
;
840 status
= smbXsrv_session_find_channel(smb2req
->session
,
842 if (!NT_STATUS_IS_OK(status
)) {
843 tevent_req_nterror(req
, status
);
844 return tevent_req_post(req
, ev
);
847 status
= smbXsrv_session_find_auth(state
->session
, smb2req
->xconn
,
849 if (!NT_STATUS_IS_OK(status
)) {
850 status
= smbXsrv_session_create_auth(state
->session
,
852 in_flags
, in_security_mode
,
854 if (tevent_req_nterror(req
, status
)) {
855 return tevent_req_post(req
, ev
);
859 if (state
->auth
->gensec
== NULL
) {
860 status
= auth_generic_prepare(state
->auth
,
861 state
->smb2req
->xconn
->remote_address
,
862 state
->smb2req
->xconn
->local_address
,
864 &state
->auth
->gensec
);
865 if (tevent_req_nterror(req
, status
)) {
866 return tevent_req_post(req
, ev
);
869 gensec_want_feature(state
->auth
->gensec
, GENSEC_FEATURE_SESSION_KEY
);
870 gensec_want_feature(state
->auth
->gensec
, GENSEC_FEATURE_UNIX_TOKEN
);
871 gensec_want_feature(state
->auth
->gensec
, GENSEC_FEATURE_SMB_TRANSPORT
);
873 status
= gensec_start_mech_by_oid(state
->auth
->gensec
,
875 if (tevent_req_nterror(req
, status
)) {
876 return tevent_req_post(req
, ev
);
880 status
= smbXsrv_session_update(state
->session
);
881 if (tevent_req_nterror(req
, status
)) {
882 return tevent_req_post(req
, ev
);
886 subreq
= gensec_update_send(state
, state
->ev
,
888 state
->in_security_buffer
);
890 if (tevent_req_nomem(subreq
, req
)) {
891 return tevent_req_post(req
, ev
);
893 tevent_req_set_callback(subreq
, smbd_smb2_session_setup_gensec_done
, req
);
898 static void smbd_smb2_session_setup_gensec_done(struct tevent_req
*subreq
)
900 struct tevent_req
*req
=
901 tevent_req_callback_data(subreq
,
903 struct smbd_smb2_session_setup_state
*state
=
905 struct smbd_smb2_session_setup_state
);
909 status
= gensec_update_recv(subreq
, state
,
910 &state
->out_security_buffer
);
913 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
914 !NT_STATUS_IS_OK(status
)) {
915 tevent_req_nterror(req
, status
);
919 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
920 state
->out_session_id
= state
->session
->global
->session_wire_id
;
921 state
->smb2req
->preauth
= state
->auth
->preauth
;
922 tevent_req_nterror(req
, status
);
926 status
= gensec_session_info(state
->auth
->gensec
,
928 &state
->session_info
);
929 if (tevent_req_nterror(req
, status
)) {
933 if ((state
->in_previous_session_id
!= 0) &&
934 (state
->session
->global
->session_wire_id
!=
935 state
->in_previous_session_id
))
937 subreq
= smb2srv_session_close_previous_send(state
, state
->ev
,
938 state
->smb2req
->xconn
,
940 state
->in_previous_session_id
,
941 state
->session
->global
->session_wire_id
);
942 if (tevent_req_nomem(subreq
, req
)) {
945 tevent_req_set_callback(subreq
,
946 smbd_smb2_session_setup_previous_done
,
951 smbd_smb2_session_setup_auth_return(req
);
954 static void smbd_smb2_session_setup_previous_done(struct tevent_req
*subreq
)
956 struct tevent_req
*req
=
957 tevent_req_callback_data(subreq
,
961 status
= smb2srv_session_close_previous_recv(subreq
);
963 if (tevent_req_nterror(req
, status
)) {
967 smbd_smb2_session_setup_auth_return(req
);
970 static void smbd_smb2_session_setup_auth_return(struct tevent_req
*req
)
972 struct smbd_smb2_session_setup_state
*state
=
974 struct smbd_smb2_session_setup_state
);
977 if (state
->in_flags
& SMB2_SESSION_FLAG_BINDING
) {
978 status
= smbd_smb2_bind_auth_return(state
->session
,
982 &state
->out_session_flags
,
983 &state
->out_session_id
);
984 if (tevent_req_nterror(req
, status
)) {
987 tevent_req_done(req
);
991 if (state
->session
->global
->auth_session_info
!= NULL
) {
992 status
= smbd_smb2_reauth_generic_return(state
->session
,
996 &state
->out_session_flags
,
997 &state
->out_session_id
);
998 if (tevent_req_nterror(req
, status
)) {
1001 tevent_req_done(req
);
1005 status
= smbd_smb2_auth_generic_return(state
->session
,
1008 state
->in_security_mode
,
1009 state
->session_info
,
1010 &state
->out_session_flags
,
1011 &state
->out_session_id
);
1012 if (tevent_req_nterror(req
, status
)) {
1016 tevent_req_done(req
);
1020 static NTSTATUS
smbd_smb2_session_setup_recv(struct tevent_req
*req
,
1021 uint16_t *out_session_flags
,
1022 TALLOC_CTX
*mem_ctx
,
1023 DATA_BLOB
*out_security_buffer
,
1024 uint64_t *out_session_id
)
1026 struct smbd_smb2_session_setup_state
*state
=
1027 tevent_req_data(req
,
1028 struct smbd_smb2_session_setup_state
);
1031 if (tevent_req_is_nterror(req
, &status
)) {
1032 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1033 tevent_req_received(req
);
1034 return nt_status_squash(status
);
1037 status
= NT_STATUS_OK
;
1040 *out_session_flags
= state
->out_session_flags
;
1041 *out_security_buffer
= state
->out_security_buffer
;
1042 *out_session_id
= state
->out_session_id
;
1044 talloc_steal(mem_ctx
, out_security_buffer
->data
);
1045 tevent_req_received(req
);
1049 struct smbd_smb2_session_setup_wrap_state
{
1050 struct tevent_context
*ev
;
1051 struct smbd_smb2_request
*smb2req
;
1052 uint64_t in_session_id
;
1054 uint8_t in_security_mode
;
1055 uint64_t in_previous_session_id
;
1056 DATA_BLOB in_security_buffer
;
1057 uint16_t out_session_flags
;
1058 DATA_BLOB out_security_buffer
;
1059 uint64_t out_session_id
;
1063 static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req
*subreq
);
1064 static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req
*subreq
);
1066 static struct tevent_req
*smbd_smb2_session_setup_wrap_send(TALLOC_CTX
*mem_ctx
,
1067 struct tevent_context
*ev
,
1068 struct smbd_smb2_request
*smb2req
,
1069 uint64_t in_session_id
,
1071 uint8_t in_security_mode
,
1072 uint64_t in_previous_session_id
,
1073 DATA_BLOB in_security_buffer
)
1075 struct tevent_req
*req
;
1076 struct smbd_smb2_session_setup_wrap_state
*state
;
1077 struct tevent_req
*subreq
;
1079 req
= tevent_req_create(mem_ctx
, &state
,
1080 struct smbd_smb2_session_setup_wrap_state
);
1085 state
->smb2req
= smb2req
;
1086 state
->in_session_id
= in_session_id
;
1087 state
->in_flags
= in_flags
;
1088 state
->in_security_mode
= in_security_mode
;
1089 state
->in_previous_session_id
= in_previous_session_id
;
1090 state
->in_security_buffer
= in_security_buffer
;
1092 subreq
= smbd_smb2_session_setup_send(state
, state
->ev
,
1094 state
->in_session_id
,
1096 state
->in_security_mode
,
1097 state
->in_previous_session_id
,
1098 state
->in_security_buffer
);
1099 if (tevent_req_nomem(subreq
, req
)) {
1100 return tevent_req_post(req
, ev
);
1102 tevent_req_set_callback(subreq
,
1103 smbd_smb2_session_setup_wrap_setup_done
, req
);
1108 static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req
*subreq
)
1110 struct tevent_req
*req
=
1111 tevent_req_callback_data(subreq
,
1113 struct smbd_smb2_session_setup_wrap_state
*state
=
1114 tevent_req_data(req
,
1115 struct smbd_smb2_session_setup_wrap_state
);
1118 status
= smbd_smb2_session_setup_recv(subreq
,
1119 &state
->out_session_flags
,
1121 &state
->out_security_buffer
,
1122 &state
->out_session_id
);
1123 TALLOC_FREE(subreq
);
1124 if (NT_STATUS_IS_OK(status
)) {
1125 tevent_req_done(req
);
1128 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1129 tevent_req_nterror(req
, status
);
1133 if (state
->smb2req
->session
== NULL
) {
1134 tevent_req_nterror(req
, status
);
1138 state
->error
= status
;
1140 subreq
= smb2srv_session_shutdown_send(state
, state
->ev
,
1141 state
->smb2req
->session
,
1143 if (tevent_req_nomem(subreq
, req
)) {
1146 tevent_req_set_callback(subreq
,
1147 smbd_smb2_session_setup_wrap_shutdown_done
,
1151 static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req
*subreq
)
1153 struct tevent_req
*req
=
1154 tevent_req_callback_data(subreq
,
1156 struct smbd_smb2_session_setup_wrap_state
*state
=
1157 tevent_req_data(req
,
1158 struct smbd_smb2_session_setup_wrap_state
);
1161 status
= smb2srv_session_shutdown_recv(subreq
);
1162 TALLOC_FREE(subreq
);
1163 if (tevent_req_nterror(req
, status
)) {
1168 * we may need to sign the response, so we need to keep
1169 * the session until the response is sent to the wire.
1171 talloc_steal(state
->smb2req
, state
->smb2req
->session
);
1173 tevent_req_nterror(req
, state
->error
);
1176 static NTSTATUS
smbd_smb2_session_setup_wrap_recv(struct tevent_req
*req
,
1177 uint16_t *out_session_flags
,
1178 TALLOC_CTX
*mem_ctx
,
1179 DATA_BLOB
*out_security_buffer
,
1180 uint64_t *out_session_id
)
1182 struct smbd_smb2_session_setup_wrap_state
*state
=
1183 tevent_req_data(req
,
1184 struct smbd_smb2_session_setup_wrap_state
);
1187 if (tevent_req_is_nterror(req
, &status
)) {
1188 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1189 tevent_req_received(req
);
1190 return nt_status_squash(status
);
1193 status
= NT_STATUS_OK
;
1196 *out_session_flags
= state
->out_session_flags
;
1197 *out_security_buffer
= state
->out_security_buffer
;
1198 *out_session_id
= state
->out_session_id
;
1200 talloc_steal(mem_ctx
, out_security_buffer
->data
);
1201 tevent_req_received(req
);
1205 static struct tevent_req
*smbd_smb2_logoff_send(TALLOC_CTX
*mem_ctx
,
1206 struct tevent_context
*ev
,
1207 struct smbd_smb2_request
*smb2req
);
1208 static NTSTATUS
smbd_smb2_logoff_recv(struct tevent_req
*req
);
1209 static void smbd_smb2_request_logoff_done(struct tevent_req
*subreq
);
1211 NTSTATUS
smbd_smb2_request_process_logoff(struct smbd_smb2_request
*req
)
1214 struct tevent_req
*subreq
= NULL
;
1216 status
= smbd_smb2_request_verify_sizes(req
, 0x04);
1217 if (!NT_STATUS_IS_OK(status
)) {
1218 return smbd_smb2_request_error(req
, status
);
1221 subreq
= smbd_smb2_logoff_send(req
, req
->ev_ctx
, req
);
1222 if (subreq
== NULL
) {
1223 return smbd_smb2_request_error(req
, NT_STATUS_NO_MEMORY
);
1225 tevent_req_set_callback(subreq
, smbd_smb2_request_logoff_done
, req
);
1228 * Wait a long time before going async on this to allow
1229 * requests we're waiting on to finish. Set timeout to 10 secs.
1231 return smbd_smb2_request_pending_queue(req
, subreq
, 10000000);
1234 static void smbd_smb2_request_logoff_done(struct tevent_req
*subreq
)
1236 struct smbd_smb2_request
*smb2req
=
1237 tevent_req_callback_data(subreq
,
1238 struct smbd_smb2_request
);
1243 status
= smbd_smb2_logoff_recv(subreq
);
1244 TALLOC_FREE(subreq
);
1245 if (!NT_STATUS_IS_OK(status
)) {
1246 error
= smbd_smb2_request_error(smb2req
, status
);
1247 if (!NT_STATUS_IS_OK(error
)) {
1248 smbd_server_connection_terminate(smb2req
->xconn
,
1255 outbody
= smbd_smb2_generate_outbody(smb2req
, 0x04);
1256 if (outbody
.data
== NULL
) {
1257 error
= smbd_smb2_request_error(smb2req
, NT_STATUS_NO_MEMORY
);
1258 if (!NT_STATUS_IS_OK(error
)) {
1259 smbd_server_connection_terminate(smb2req
->xconn
,
1266 SSVAL(outbody
.data
, 0x00, 0x04); /* struct size */
1267 SSVAL(outbody
.data
, 0x02, 0); /* reserved */
1269 error
= smbd_smb2_request_done(smb2req
, outbody
, NULL
);
1270 if (!NT_STATUS_IS_OK(error
)) {
1271 smbd_server_connection_terminate(smb2req
->xconn
,
1277 struct smbd_smb2_logoff_state
{
1278 struct smbd_smb2_request
*smb2req
;
1281 static void smbd_smb2_logoff_shutdown_done(struct tevent_req
*subreq
);
1283 static struct tevent_req
*smbd_smb2_logoff_send(TALLOC_CTX
*mem_ctx
,
1284 struct tevent_context
*ev
,
1285 struct smbd_smb2_request
*smb2req
)
1287 struct tevent_req
*req
;
1288 struct smbd_smb2_logoff_state
*state
;
1289 struct tevent_req
*subreq
;
1291 req
= tevent_req_create(mem_ctx
, &state
,
1292 struct smbd_smb2_logoff_state
);
1296 state
->smb2req
= smb2req
;
1298 subreq
= smb2srv_session_shutdown_send(state
, ev
,
1301 if (tevent_req_nomem(subreq
, req
)) {
1302 return tevent_req_post(req
, ev
);
1304 tevent_req_set_callback(subreq
, smbd_smb2_logoff_shutdown_done
, req
);
1309 static void smbd_smb2_logoff_shutdown_done(struct tevent_req
*subreq
)
1311 struct tevent_req
*req
= tevent_req_callback_data(
1312 subreq
, struct tevent_req
);
1313 struct smbd_smb2_logoff_state
*state
= tevent_req_data(
1314 req
, struct smbd_smb2_logoff_state
);
1317 const struct GUID
*client_guid
=
1318 &state
->smb2req
->session
->client
->connections
->smb2
.client
.guid
;
1320 status
= smb2srv_session_shutdown_recv(subreq
);
1321 if (tevent_req_nterror(req
, status
)) {
1324 TALLOC_FREE(subreq
);
1326 if (!GUID_all_zero(client_guid
)) {
1327 ok
= remote_arch_cache_delete(client_guid
);
1329 /* Most likely not an error, but not in cache */
1330 DBG_DEBUG("Deletion from remote arch cache failed\n");
1335 * As we've been awoken, we may have changed
1336 * uid in the meantime. Ensure we're still
1337 * root (SMB2_OP_LOGOFF has .as_root = true).
1339 change_to_root_user();
1341 status
= smbXsrv_session_logoff(state
->smb2req
->session
);
1342 if (tevent_req_nterror(req
, status
)) {
1347 * we may need to sign the response, so we need to keep
1348 * the session until the response is sent to the wire.
1350 talloc_steal(state
->smb2req
, state
->smb2req
->session
);
1352 tevent_req_done(req
);
1355 static NTSTATUS
smbd_smb2_logoff_recv(struct tevent_req
*req
)
1357 return tevent_req_simple_recv_ntstatus(req
);