};
struct smbXcli_tcon {
+ bool is_smb1;
+ uint32_t fs_attributes;
+
struct {
uint16_t tcon_id;
uint16_t optional_support;
return conn->smb1.max_xmit;
}
+bool smb1cli_conn_req_possible(struct smbXcli_conn *conn)
+{
+ size_t pending;
+ uint16_t possible = conn->smb1.server.max_mux;
+
+ pending = tevent_queue_length(conn->outgoing);
+ if (pending >= possible) {
+ return false;
+ }
+ pending += talloc_array_length(conn->pending);
+ if (pending >= possible) {
+ return false;
+ }
+
+ return true;
+}
+
uint32_t smb1cli_conn_server_session_key(struct smbXcli_conn *conn)
{
return conn->smb1.server.session_key;
size_t num_pending = talloc_array_length(conn->pending);
uint16_t result;
+ if (conn->protocol == PROTOCOL_NONE) {
+ /*
+ * This is what windows sends on the SMB1 Negprot request
+ * and some vendors reuse the SMB1 MID as SMB2 sequence number.
+ */
+ return 0;
+ }
+
while (true) {
size_t i;
if (tcon) {
tid = tcon->smb1.tcon_id;
+
+ if (tcon->fs_attributes & FILE_CASE_SENSITIVE_SEARCH) {
+ clear_flags |= FLAG_CASELESS_PATHNAMES;
+ } else {
+ /* Default setting, case insensitive. */
+ additional_flags |= FLAG_CASELESS_PATHNAMES;
+ }
+
+ if (smbXcli_conn_dfs_supported(conn) &&
+ smbXcli_tcon_is_dfs_share(tcon))
+ {
+ additional_flags2 |= FLAGS2_DFS_PATHNAMES;
+ }
}
state->smb1.recv_cmd = 0xFF;
|| (talloc_array_length(conn->pending) != 0));
}
+bool smbXcli_conn_dfs_supported(struct smbXcli_conn *conn)
+{
+ if (conn->protocol >= PROTOCOL_SMB2_02) {
+ return (smb2cli_conn_server_capabilities(conn) & SMB2_CAP_DFS);
+ }
+
+ return (smb1cli_conn_capabilities(conn) & CAP_DFS);
+}
+
+bool smb2cli_conn_req_possible(struct smbXcli_conn *conn, uint32_t *max_dyn_len)
+{
+ uint16_t credits = 1;
+
+ if (conn->smb2.cur_credits == 0) {
+ if (max_dyn_len != NULL) {
+ *max_dyn_len = 0;
+ }
+ return false;
+ }
+
+ if (conn->smb2.server.capabilities & SMB2_CAP_LARGE_MTU) {
+ credits = conn->smb2.cur_credits;
+ }
+
+ if (max_dyn_len != NULL) {
+ *max_dyn_len = credits * 65536;
+ }
+
+ return true;
+}
+
uint32_t smb2cli_conn_server_capabilities(struct smbXcli_conn *conn)
{
return conn->smb2.server.capabilities;
0, /* timeout */
tcon, session,
fixed, fixed_len,
- NULL, 0);
+ NULL, 0, 0);
if (subreq == NULL) {
return false;
}
const uint8_t *fixed,
uint16_t fixed_len,
const uint8_t *dyn,
- uint32_t dyn_len)
+ uint32_t dyn_len,
+ uint32_t max_dyn_len)
{
struct tevent_req *req;
struct smbXcli_req_state *state;
state->smb2.fixed_len = fixed_len;
state->smb2.dyn = dyn;
state->smb2.dyn_len = dyn_len;
+ state->smb2.max_dyn_len = max_dyn_len;
if (state->smb2.should_encrypt) {
SIVAL(state->smb2.transform, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
const uint8_t *fixed,
uint16_t fixed_len,
const uint8_t *dyn,
- uint32_t dyn_len)
+ uint32_t dyn_len,
+ uint32_t max_dyn_len)
{
struct tevent_req *req;
NTSTATUS status;
additional_flags, clear_flags,
timeout_msec,
tcon, session,
- fixed, fixed_len, dyn, dyn_len);
+ fixed, fixed_len,
+ dyn, dyn_len,
+ max_dyn_len);
if (req == NULL) {
return NULL;
}
{PROTOCOL_SMB2_22, SMB2_DIALECT_REVISION_222},
{PROTOCOL_SMB2_24, SMB2_DIALECT_REVISION_224},
{PROTOCOL_SMB3_00, SMB3_DIALECT_REVISION_300},
+ {PROTOCOL_SMB3_02, SMB3_DIALECT_REVISION_302},
};
struct smbXcli_negprot_state {
state->timeout_msec,
NULL, NULL, /* tcon, session */
state->smb2.fixed, sizeof(state->smb2.fixed),
- state->smb2.dyn, dialect_count*2);
+ state->smb2.dyn, dialect_count*2,
+ UINT16_MAX); /* max_dyn_len */
}
static void smbXcli_negprot_smb2_done(struct tevent_req *subreq)
struct smbXcli_conn *conn = session->conn;
uint16_t no_sign_flags;
uint8_t session_key[16];
+ bool check_signature = true;
+ uint32_t hdr_flags;
NTSTATUS status;
if (conn == NULL) {
return NT_STATUS_INVALID_PARAMETER_MIX;
}
+ if (recv_iov[0].iov_len != SMB2_HDR_BODY) {
+ return NT_STATUS_INVALID_PARAMETER_MIX;
+ }
+
no_sign_flags = SMB2_SESSION_FLAG_IS_GUEST | SMB2_SESSION_FLAG_IS_NULL;
if (session->smb2->session_flags & no_sign_flags) {
return NT_STATUS_NO_MEMORY;
}
- status = smb2_signing_check_pdu(session->smb2_channel.signing_key,
- session->conn->protocol,
- recv_iov, 3);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
+ check_signature = conn->mandatory_signing;
+
+ hdr_flags = IVAL(recv_iov[0].iov_base, SMB2_HDR_FLAGS);
+ if (hdr_flags & SMB2_HDR_FLAG_SIGNED) {
+ /*
+ * Sadly some vendors don't sign the
+ * final SMB2 session setup response
+ *
+ * At least Windows and Samba are always doing this
+ * if there's a session key available.
+ *
+ * We only check the signature if it's mandatory
+ * or SMB2_HDR_FLAG_SIGNED is provided.
+ */
+ check_signature = true;
+ }
+
+ if (check_signature) {
+ status = smb2_signing_check_pdu(session->smb2_channel.signing_key,
+ session->conn->protocol,
+ recv_iov, 3);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
}
session->smb2->should_sign = false;
return NT_STATUS_OK;
}
+NTSTATUS smb2cli_session_encryption_on(struct smbXcli_session *session)
+{
+ if (session->smb2->should_encrypt) {
+ return NT_STATUS_OK;
+ }
+
+ if (session->conn->protocol < PROTOCOL_SMB2_24) {
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
+ if (!(session->conn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION)) {
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
+ if (session->smb2->signing_key.data == NULL) {
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+ session->smb2->should_encrypt = true;
+ return NT_STATUS_OK;
+}
+
struct smbXcli_tcon *smbXcli_tcon_create(TALLOC_CTX *mem_ctx)
{
struct smbXcli_tcon *tcon;
return tcon;
}
+void smbXcli_tcon_set_fs_attributes(struct smbXcli_tcon *tcon,
+ uint32_t fs_attributes)
+{
+ tcon->fs_attributes = fs_attributes;
+}
+
+uint32_t smbXcli_tcon_get_fs_attributes(struct smbXcli_tcon *tcon)
+{
+ return tcon->fs_attributes;
+}
+
+bool smbXcli_tcon_is_dfs_share(struct smbXcli_tcon *tcon)
+{
+ if (tcon == NULL) {
+ return false;
+ }
+
+ if (tcon->is_smb1) {
+ if (tcon->smb1.optional_support & SMB_SHARE_IN_DFS) {
+ return true;
+ }
+
+ return false;
+ }
+
+ if (tcon->smb2.capabilities & SMB2_SHARE_CAP_DFS) {
+ return true;
+ }
+
+ return false;
+}
+
uint16_t smb1cli_tcon_current_id(struct smbXcli_tcon *tcon)
{
return tcon->smb1.tcon_id;
void smb1cli_tcon_set_id(struct smbXcli_tcon *tcon, uint16_t tcon_id)
{
+ tcon->is_smb1 = true;
tcon->smb1.tcon_id = tcon_id;
}
const char *service,
const char *fs_type)
{
+ tcon->is_smb1 = true;
+ tcon->fs_attributes = 0;
tcon->smb1.tcon_id = tcon_id;
tcon->smb1.optional_support = optional_support;
tcon->smb1.maximal_access = maximal_access;
uint32_t capabilities,
uint32_t maximal_access)
{
+ tcon->is_smb1 = false;
+ tcon->fs_attributes = 0;
tcon->smb2.tcon_id = tcon_id;
tcon->smb2.type = type;
tcon->smb2.flags = flags;
tcon->smb2.should_encrypt = true;
}
}
+
+bool smb2cli_tcon_is_encryption_on(struct smbXcli_tcon *tcon)
+{
+ return tcon->smb2.should_encrypt;
+}