mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
libcli/smb: implement SMB 3.10 session setup
Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
This commit is contained in:
parent
2f732db742
commit
c290ece1f6
@ -120,6 +120,7 @@ static void smb2cli_session_setup_done(struct tevent_req *subreq)
|
||||
tevent_req_data(req,
|
||||
struct smb2cli_session_setup_state);
|
||||
NTSTATUS status;
|
||||
NTSTATUS preauth_status;
|
||||
uint64_t current_session_id;
|
||||
uint64_t session_id;
|
||||
uint16_t session_flags;
|
||||
@ -127,6 +128,7 @@ static void smb2cli_session_setup_done(struct tevent_req *subreq)
|
||||
uint16_t security_buffer_offset;
|
||||
uint16_t security_buffer_length;
|
||||
uint8_t *security_buffer_data = NULL;
|
||||
struct iovec sent_iov[3];
|
||||
const uint8_t *hdr;
|
||||
const uint8_t *body;
|
||||
static const struct smb2cli_req_expected_response expected[] = {
|
||||
@ -142,13 +144,28 @@ static void smb2cli_session_setup_done(struct tevent_req *subreq)
|
||||
|
||||
status = smb2cli_req_recv(subreq, state, &state->recv_iov,
|
||||
expected, ARRAY_SIZE(expected));
|
||||
TALLOC_FREE(subreq);
|
||||
if (!NT_STATUS_IS_OK(status) &&
|
||||
!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
|
||||
TALLOC_FREE(subreq);
|
||||
tevent_req_nterror(req, status);
|
||||
return;
|
||||
}
|
||||
|
||||
smb2cli_req_get_sent_iov(subreq, sent_iov);
|
||||
preauth_status = smb2cli_session_update_preauth(state->session, sent_iov);
|
||||
TALLOC_FREE(subreq);
|
||||
if (tevent_req_nterror(req, preauth_status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
|
||||
preauth_status = smb2cli_session_update_preauth(state->session,
|
||||
state->recv_iov);
|
||||
if (tevent_req_nterror(req, preauth_status)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
hdr = (const uint8_t *)state->recv_iov[0].iov_base;
|
||||
body = (const uint8_t *)state->recv_iov[1].iov_base;
|
||||
|
||||
|
@ -164,6 +164,7 @@ struct smbXcli_session {
|
||||
|
||||
struct {
|
||||
DATA_BLOB signing_key;
|
||||
uint8_t preauth_sha512[64];
|
||||
} smb2_channel;
|
||||
|
||||
/*
|
||||
@ -5112,6 +5113,10 @@ struct smbXcli_session *smbXcli_session_create(TALLOC_CTX *mem_ctx,
|
||||
DLIST_ADD_END(conn->sessions, session, struct smbXcli_session *);
|
||||
session->conn = conn;
|
||||
|
||||
memcpy(session->smb2_channel.preauth_sha512,
|
||||
conn->smb2.preauth_sha512,
|
||||
sizeof(session->smb2_channel.preauth_sha512));
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
@ -5334,6 +5339,35 @@ void smb2cli_session_stop_replay(struct smbXcli_session *session)
|
||||
session->smb2->replay_active = false;
|
||||
}
|
||||
|
||||
NTSTATUS smb2cli_session_update_preauth(struct smbXcli_session *session,
|
||||
const struct iovec *iov)
|
||||
{
|
||||
struct hc_sha512state sctx;
|
||||
size_t i;
|
||||
|
||||
if (session->conn == NULL) {
|
||||
return NT_STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
if (session->conn->protocol < PROTOCOL_SMB3_10) {
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
if (session->smb2_channel.signing_key.length != 0) {
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
SHA512_Init(&sctx);
|
||||
SHA512_Update(&sctx, session->smb2_channel.preauth_sha512,
|
||||
sizeof(session->smb2_channel.preauth_sha512));
|
||||
for (i = 0; i < 3; i++) {
|
||||
SHA512_Update(&sctx, iov[i].iov_base, iov[i].iov_len);
|
||||
}
|
||||
SHA512_Final(session->smb2_channel.preauth_sha512, &sctx);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
NTSTATUS smb2cli_session_set_session_key(struct smbXcli_session *session,
|
||||
const DATA_BLOB _session_key,
|
||||
const struct iovec *recv_iov)
|
||||
@ -5344,6 +5378,16 @@ NTSTATUS smb2cli_session_set_session_key(struct smbXcli_session *session,
|
||||
bool check_signature = true;
|
||||
uint32_t hdr_flags;
|
||||
NTSTATUS status;
|
||||
struct _derivation {
|
||||
DATA_BLOB label;
|
||||
DATA_BLOB context;
|
||||
};
|
||||
struct {
|
||||
struct _derivation signing;
|
||||
struct _derivation encryption;
|
||||
struct _derivation decryption;
|
||||
struct _derivation application;
|
||||
} derivation = { };
|
||||
|
||||
if (conn == NULL) {
|
||||
return NT_STATUS_INVALID_PARAMETER_MIX;
|
||||
@ -5364,6 +5408,49 @@ NTSTATUS smb2cli_session_set_session_key(struct smbXcli_session *session,
|
||||
return NT_STATUS_INVALID_PARAMETER_MIX;
|
||||
}
|
||||
|
||||
if (conn->protocol >= PROTOCOL_SMB3_10) {
|
||||
struct _derivation *d;
|
||||
DATA_BLOB p;
|
||||
|
||||
p = data_blob_const(session->smb2_channel.preauth_sha512,
|
||||
sizeof(session->smb2_channel.preauth_sha512));
|
||||
|
||||
d = &derivation.signing;
|
||||
d->label = data_blob_string_const_null("SMBSigningKey");
|
||||
d->context = p;
|
||||
|
||||
d = &derivation.encryption;
|
||||
d->label = data_blob_string_const_null("SMBC2SCipherKey");
|
||||
d->context = p;
|
||||
|
||||
d = &derivation.decryption;
|
||||
d->label = data_blob_string_const_null("SMBS2CCipherKey");
|
||||
d->context = p;
|
||||
|
||||
d = &derivation.application;
|
||||
d->label = data_blob_string_const_null("SMBAppKey");
|
||||
d->context = p;
|
||||
|
||||
} else if (conn->protocol >= PROTOCOL_SMB2_24) {
|
||||
struct _derivation *d;
|
||||
|
||||
d = &derivation.signing;
|
||||
d->label = data_blob_string_const_null("SMB2AESCMAC");
|
||||
d->context = data_blob_string_const_null("SmbSign");
|
||||
|
||||
d = &derivation.encryption;
|
||||
d->label = data_blob_string_const_null("SMB2AESCCM");
|
||||
d->context = data_blob_string_const_null("ServerIn ");
|
||||
|
||||
d = &derivation.decryption;
|
||||
d->label = data_blob_string_const_null("SMB2AESCCM");
|
||||
d->context = data_blob_string_const_null("ServerOut");
|
||||
|
||||
d = &derivation.application;
|
||||
d->label = data_blob_string_const_null("SMB2APP");
|
||||
d->context = data_blob_string_const_null("SmbRpc");
|
||||
}
|
||||
|
||||
ZERO_STRUCT(session_key);
|
||||
memcpy(session_key, _session_key.data,
|
||||
MIN(_session_key.length, sizeof(session_key)));
|
||||
@ -5377,12 +5464,11 @@ NTSTATUS smb2cli_session_set_session_key(struct smbXcli_session *session,
|
||||
}
|
||||
|
||||
if (conn->protocol >= PROTOCOL_SMB2_24) {
|
||||
const DATA_BLOB label = data_blob_string_const_null("SMB2AESCMAC");
|
||||
const DATA_BLOB context = data_blob_string_const_null("SmbSign");
|
||||
struct _derivation *d = &derivation.signing;
|
||||
|
||||
smb2_key_derivation(session_key, sizeof(session_key),
|
||||
label.data, label.length,
|
||||
context.data, context.length,
|
||||
d->label.data, d->label.length,
|
||||
d->context.data, d->context.length,
|
||||
session->smb2->signing_key.data);
|
||||
}
|
||||
|
||||
@ -5394,12 +5480,11 @@ NTSTATUS smb2cli_session_set_session_key(struct smbXcli_session *session,
|
||||
}
|
||||
|
||||
if (conn->protocol >= PROTOCOL_SMB2_24) {
|
||||
const DATA_BLOB label = data_blob_string_const_null("SMB2AESCCM");
|
||||
const DATA_BLOB context = data_blob_string_const_null("ServerIn ");
|
||||
struct _derivation *d = &derivation.encryption;
|
||||
|
||||
smb2_key_derivation(session_key, sizeof(session_key),
|
||||
label.data, label.length,
|
||||
context.data, context.length,
|
||||
d->label.data, d->label.length,
|
||||
d->context.data, d->context.length,
|
||||
session->smb2->encryption_key.data);
|
||||
}
|
||||
|
||||
@ -5411,12 +5496,11 @@ NTSTATUS smb2cli_session_set_session_key(struct smbXcli_session *session,
|
||||
}
|
||||
|
||||
if (conn->protocol >= PROTOCOL_SMB2_24) {
|
||||
const DATA_BLOB label = data_blob_string_const_null("SMB2AESCCM");
|
||||
const DATA_BLOB context = data_blob_string_const_null("ServerOut");
|
||||
struct _derivation *d = &derivation.decryption;
|
||||
|
||||
smb2_key_derivation(session_key, sizeof(session_key),
|
||||
label.data, label.length,
|
||||
context.data, context.length,
|
||||
d->label.data, d->label.length,
|
||||
d->context.data, d->context.length,
|
||||
session->smb2->decryption_key.data);
|
||||
}
|
||||
|
||||
@ -5428,12 +5512,11 @@ NTSTATUS smb2cli_session_set_session_key(struct smbXcli_session *session,
|
||||
}
|
||||
|
||||
if (conn->protocol >= PROTOCOL_SMB2_24) {
|
||||
const DATA_BLOB label = data_blob_string_const_null("SMB2APP");
|
||||
const DATA_BLOB context = data_blob_string_const_null("SmbRpc");
|
||||
struct _derivation *d = &derivation.application;
|
||||
|
||||
smb2_key_derivation(session_key, sizeof(session_key),
|
||||
label.data, label.length,
|
||||
context.data, context.length,
|
||||
d->label.data, d->label.length,
|
||||
d->context.data, d->context.length,
|
||||
session->smb2->application_key.data);
|
||||
}
|
||||
ZERO_STRUCT(session_key);
|
||||
@ -5461,6 +5544,10 @@ NTSTATUS smb2cli_session_set_session_key(struct smbXcli_session *session,
|
||||
check_signature = true;
|
||||
}
|
||||
|
||||
if (conn->protocol >= PROTOCOL_SMB3_10) {
|
||||
check_signature = true;
|
||||
}
|
||||
|
||||
if (check_signature) {
|
||||
status = smb2_signing_check_pdu(session->smb2_channel.signing_key,
|
||||
session->conn->protocol,
|
||||
@ -5529,6 +5616,10 @@ NTSTATUS smb2cli_session_create_channel(TALLOC_CTX *mem_ctx,
|
||||
DLIST_ADD_END(conn->sessions, session2, struct smbXcli_session *);
|
||||
session2->conn = conn;
|
||||
|
||||
memcpy(session2->smb2_channel.preauth_sha512,
|
||||
conn->smb2.preauth_sha512,
|
||||
sizeof(session2->smb2_channel.preauth_sha512));
|
||||
|
||||
*_session2 = session2;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
@ -5540,6 +5631,13 @@ NTSTATUS smb2cli_session_set_channel_key(struct smbXcli_session *session,
|
||||
struct smbXcli_conn *conn = session->conn;
|
||||
uint8_t channel_key[16];
|
||||
NTSTATUS status;
|
||||
struct _derivation {
|
||||
DATA_BLOB label;
|
||||
DATA_BLOB context;
|
||||
};
|
||||
struct {
|
||||
struct _derivation signing;
|
||||
} derivation = { };
|
||||
|
||||
if (conn == NULL) {
|
||||
return NT_STATUS_INVALID_PARAMETER_MIX;
|
||||
@ -5549,6 +5647,24 @@ NTSTATUS smb2cli_session_set_channel_key(struct smbXcli_session *session,
|
||||
return NT_STATUS_INVALID_PARAMETER_MIX;
|
||||
}
|
||||
|
||||
if (conn->protocol >= PROTOCOL_SMB3_10) {
|
||||
struct _derivation *d;
|
||||
DATA_BLOB p;
|
||||
|
||||
p = data_blob_const(session->smb2_channel.preauth_sha512,
|
||||
sizeof(session->smb2_channel.preauth_sha512));
|
||||
|
||||
d = &derivation.signing;
|
||||
d->label = data_blob_string_const_null("SMBSigningKey");
|
||||
d->context = p;
|
||||
} else if (conn->protocol >= PROTOCOL_SMB2_24) {
|
||||
struct _derivation *d;
|
||||
|
||||
d = &derivation.signing;
|
||||
d->label = data_blob_string_const_null("SMB2AESCMAC");
|
||||
d->context = data_blob_string_const_null("SmbSign");
|
||||
}
|
||||
|
||||
ZERO_STRUCT(channel_key);
|
||||
memcpy(channel_key, _channel_key.data,
|
||||
MIN(_channel_key.length, sizeof(channel_key)));
|
||||
@ -5562,12 +5678,11 @@ NTSTATUS smb2cli_session_set_channel_key(struct smbXcli_session *session,
|
||||
}
|
||||
|
||||
if (conn->protocol >= PROTOCOL_SMB2_24) {
|
||||
const DATA_BLOB label = data_blob_string_const_null("SMB2AESCMAC");
|
||||
const DATA_BLOB context = data_blob_string_const_null("SmbSign");
|
||||
struct _derivation *d = &derivation.signing;
|
||||
|
||||
smb2_key_derivation(channel_key, sizeof(channel_key),
|
||||
label.data, label.length,
|
||||
context.data, context.length,
|
||||
d->label.data, d->label.length,
|
||||
d->context.data, d->context.length,
|
||||
session->smb2_channel.signing_key.data);
|
||||
}
|
||||
ZERO_STRUCT(channel_key);
|
||||
|
@ -403,6 +403,8 @@ uint16_t smb2cli_session_reset_channel_sequence(struct smbXcli_session *session,
|
||||
uint16_t channel_sequence);
|
||||
void smb2cli_session_start_replay(struct smbXcli_session *session);
|
||||
void smb2cli_session_stop_replay(struct smbXcli_session *session);
|
||||
NTSTATUS smb2cli_session_update_preauth(struct smbXcli_session *session,
|
||||
const struct iovec *iov);
|
||||
NTSTATUS smb2cli_session_set_session_key(struct smbXcli_session *session,
|
||||
const DATA_BLOB session_key,
|
||||
const struct iovec *recv_iov);
|
||||
|
Loading…
Reference in New Issue
Block a user