uint8_t io_priority;
+ bool force_channel_sequence;
+
uint8_t preauth_sha512[64];
} smb2;
uint64_t nonce_low;
uint16_t channel_sequence;
bool replay_active;
+ bool require_signed_response;
};
struct smbXcli_session {
struct tevent_req *write_req;
+ struct timeval endtime;
+
struct {
/* Space for the header including the wct */
uint8_t hdr[HDR_VWV];
uint64_t encryption_session_id;
bool signing_skipped;
+ bool require_signed_response;
bool notify_async;
bool got_async;
uint16_t cancel_flags;
return &conn->smb1.server.guid;
}
+bool smbXcli_conn_get_force_channel_sequence(struct smbXcli_conn *conn)
+{
+ return conn->smb2.force_channel_sequence;
+}
+
+void smbXcli_conn_set_force_channel_sequence(struct smbXcli_conn *conn,
+ bool v)
+{
+ conn->smb2.force_channel_sequence = v;
+}
+
struct smbXcli_conn_samba_suicide_state {
struct smbXcli_conn *conn;
struct iovec iov;
state->smb1.iov_count = iov_count + 4;
if (timeout_msec > 0) {
- struct timeval endtime;
-
- endtime = timeval_current_ofs_msec(timeout_msec);
- if (!tevent_req_set_endtime(req, ev, endtime)) {
+ state->endtime = timeval_current_ofs_msec(timeout_msec);
+ if (!tevent_req_set_endtime(req, ev, state->endtime)) {
return req;
}
}
struct iovec **piov, int *pnum_iov)
{
struct iovec *iov;
- int num_iov;
+ size_t num_iov;
size_t buflen;
size_t taken;
size_t remaining;
wct_ofs = SVAL(cur[0].iov_base, 2);
if (wct_ofs < taken) {
- return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ goto inval;
}
if (wct_ofs > buflen) {
- return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ goto inval;
}
/*
TALLOC_FREE(subreq);
}
+struct timeval smbXcli_req_endtime(struct tevent_req *req)
+{
+ struct smbXcli_req_state *state = tevent_req_data(
+ req, struct smbXcli_req_state);
+
+ return state->endtime;
+}
+
struct tevent_req *smb2cli_req_create(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct smbXcli_conn *conn,
uint32_t flags = 0;
uint32_t tid = 0;
uint64_t uid = 0;
- bool use_channel_sequence = false;
+ bool use_channel_sequence = conn->smb2.force_channel_sequence;
uint16_t channel_sequence = 0;
bool use_replay_flag = false;
state->smb2.should_sign = session->smb2->should_sign;
state->smb2.should_encrypt = session->smb2->should_encrypt;
+ state->smb2.require_signed_response =
+ session->smb2->require_signed_response;
if (cmd == SMB2_OP_SESSSETUP &&
session->smb2_channel.signing_key.length == 0 &&
}
if (timeout_msec > 0) {
- struct timeval endtime;
-
- endtime = timeval_current_ofs_msec(timeout_msec);
- if (!tevent_req_set_endtime(req, ev, endtime)) {
+ state->endtime = timeval_current_ofs_msec(timeout_msec);
+ if (!tevent_req_set_endtime(req, ev, state->endtime)) {
return req;
}
}
uint8_t *buf,
size_t buflen,
TALLOC_CTX *mem_ctx,
- struct iovec **piov, int *pnum_iov)
+ struct iovec **piov,
+ size_t *pnum_iov)
{
struct iovec *iov;
int num_iov = 0;
struct tevent_req *req;
struct smbXcli_req_state *state = NULL;
struct iovec *iov = NULL;
- int i, num_iov = 0;
+ size_t i, num_iov = 0;
NTSTATUS status;
bool defer = true;
struct smbXcli_session *last_session = NULL;
}
last_session = session;
- if (state->smb2.should_sign) {
- if (!(flags & SMB2_HDR_FLAG_SIGNED)) {
- return NT_STATUS_ACCESS_DENIED;
- }
- }
-
if (flags & SMB2_HDR_FLAG_SIGNED) {
uint64_t uid = BVAL(inhdr, SMB2_HDR_SESSION_ID);
*/
signing_key = NULL;
}
+
+ if (!NT_STATUS_IS_OK(status)) {
+ /*
+ * Only check the signature of the last response
+ * of a successfull session auth. This matches
+ * Windows behaviour for NTLM auth and reauth.
+ */
+ state->smb2.require_signed_response = false;
+ }
+ }
+
+ if (state->smb2.should_sign ||
+ state->smb2.require_signed_response)
+ {
+ if (!(flags & SMB2_HDR_FLAG_SIGNED)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ }
+
+ if (signing_key == NULL && state->smb2.require_signed_response) {
+ signing_key = &session->smb2_channel.signing_key;
}
if (cur[0].iov_len == SMB2_TF_HDR_SIZE) {
}
if (signing_key) {
- status = smb2_signing_check_pdu(*signing_key,
- state->conn->protocol,
- &cur[1], 3);
- if (!NT_STATUS_IS_OK(status)) {
+ NTSTATUS signing_status;
+
+ signing_status = smb2_signing_check_pdu(*signing_key,
+ state->conn->protocol,
+ &cur[1], 3);
+ if (!NT_STATUS_IS_OK(signing_status)) {
/*
* If the signing check fails, we disconnect
* the connection.
*/
- return status;
+ return signing_status;
}
}
}
if (conn->protocol == PROTOCOL_NONE) {
+ DBG_ERR("No compatible protocol selected by server.\n");
tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
return;
}
session->smb2->replay_active = false;
}
+void smb2cli_session_require_signed_response(struct smbXcli_session *session,
+ bool require_signed_response)
+{
+ session->smb2->require_signed_response = require_signed_response;
+}
+
NTSTATUS smb2cli_session_update_preauth(struct smbXcli_session *session,
const struct iovec *iov)
{