summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2012-08-14 09:35:59 +0200
committerStefan Metzmacher <metze@samba.org>2012-08-15 16:26:26 +0200
commitd2d5fb1abfcb9d21fe2742d53de00c7638fad14d (patch)
treec5c65429625374f50fd21fbaf3115d4216ade0b8
parent7a7e9b1c76f3967cc8cdae34e5d64759305e592a (diff)
downloadsamba-d2d5fb1abfcb9d21fe2742d53de00c7638fad14d.tar.gz
samba-d2d5fb1abfcb9d21fe2742d53de00c7638fad14d.tar.bz2
samba-d2d5fb1abfcb9d21fe2742d53de00c7638fad14d.zip
libcli/smb: verify decrypted SMB2 pdus correctly
We need to make sure we got a encrypted response if we asked for it. If we don't get a encrypted response, we use a similar logic as with signing to propagated wellknown errors to the higher layer and set state->smb2.signing_skipped = true. metze Autobuild-User(master): Stefan Metzmacher <metze@samba.org> Autobuild-Date(master): Wed Aug 15 16:26:26 CEST 2012 on sn-devel-104
-rw-r--r--libcli/smb/smbXcli_base.c40
1 files changed, 38 insertions, 2 deletions
diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c
index 05a97268a4..45da5fd90f 100644
--- a/libcli/smb/smbXcli_base.c
+++ b/libcli/smb/smbXcli_base.c
@@ -3159,6 +3159,7 @@ static NTSTATUS smb2cli_conn_dispatch_incoming(struct smbXcli_conn *conn,
uint32_t new_credits;
struct smbXcli_session *session = NULL;
const DATA_BLOB *signing_key = NULL;
+ bool was_encrypted = false;
new_credits = conn->smb2.cur_credits;
new_credits += credits;
@@ -3276,6 +3277,26 @@ static NTSTATUS smb2cli_conn_dispatch_incoming(struct smbXcli_conn *conn,
}
}
+ if (cur[0].iov_len == SMB2_TF_HDR_SIZE) {
+ const uint8_t *tf = (const uint8_t *)cur[0].iov_base;
+ uint64_t uid = BVAL(tf, SMB2_TF_SESSION_ID);
+
+ /*
+ * If the response was encrypted in a SMB2_TRANSFORM
+ * pdu, which belongs to the correct session,
+ * we do not need to do signing checks
+ *
+ * It could be the session the response belongs to
+ * or the session that was used to encrypt the
+ * SMB2_TRANSFORM request.
+ */
+ if ((session && session->smb2->session_id == uid) ||
+ (state->smb2.encryption_session_id == uid)) {
+ signing_key = NULL;
+ was_encrypted = true;
+ }
+ }
+
if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
/*
* if the server returns NT_STATUS_USER_SESSION_DELETED
@@ -3283,9 +3304,24 @@ static NTSTATUS smb2cli_conn_dispatch_incoming(struct smbXcli_conn *conn,
* propagate the NT_STATUS_USER_SESSION_DELETED
* status to the caller.
*/
+ state->smb2.signing_skipped = true;
signing_key = NULL;
- } else if (state->smb2.should_encrypt) {
- if (cur[0].iov_len != SMB2_TF_HDR_SIZE) {
+ }
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
+ /*
+ * if the server returns
+ * NT_STATUS_INVALID_PARAMETER
+ * the response might not be encrypted.
+ */
+ if (state->smb2.should_encrypt && !was_encrypted) {
+ state->smb2.signing_skipped = true;
+ signing_key = NULL;
+ }
+ }
+
+ if (state->smb2.should_encrypt && !was_encrypted) {
+ if (!state->smb2.signing_skipped) {
return NT_STATUS_ACCESS_DENIED;
}
}