uint32_t *out_share_flags,
uint32_t *out_capabilities,
uint32_t *out_maximal_access,
- uint32_t *out_tree_id);
+ uint32_t *out_tree_id,
+ bool *disconnect);
static void smbd_smb2_request_tcon_done(struct tevent_req *subreq);
uint32_t out_capabilities = 0;
uint32_t out_maximal_access = 0;
uint32_t out_tree_id = 0;
+ bool disconnect = false;
NTSTATUS status;
NTSTATUS error;
&out_share_flags,
&out_capabilities,
&out_maximal_access,
- &out_tree_id);
+ &out_tree_id,
+ &disconnect);
TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)) {
+ if (disconnect) {
+ smbd_server_connection_terminate(req->xconn,
+ nt_errstr(status));
+ return;
+ }
error = smbd_smb2_request_error(req, status);
if (!NT_STATUS_IS_OK(error)) {
smbd_server_connection_terminate(req->xconn,
uint32_t *out_share_flags,
uint32_t *out_capabilities,
uint32_t *out_maximal_access,
- uint32_t *out_tree_id)
+ uint32_t *out_tree_id,
+ bool *disconnect)
{
struct smbXsrv_connection *conn = req->xconn;
const char *share = in_path;
connection_struct *compat_conn = NULL;
struct user_struct *compat_vuser = req->session->compat;
NTSTATUS status;
- bool encryption_required = req->session->global->encryption_required;
+ bool encryption_desired = req->session->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
+ bool encryption_required = req->session->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
bool guest_session = false;
+ bool require_signed_tcon = false;
+
+ *disconnect = false;
if (strncmp(share, "\\\\", 2) == 0) {
const char *p = strchr(share+2, '\\');
DEBUG(10,("smbd_smb2_tree_connect: path[%s] share[%s]\n",
in_path, share));
+ if (security_session_user_level(compat_vuser->session_info, NULL) < SECURITY_USER) {
+ guest_session = true;
+ }
+
+ if (conn->protocol >= PROTOCOL_SMB3_11 && !guest_session) {
+ require_signed_tcon = true;
+ }
+
+ if (require_signed_tcon && !req->do_encryption && !req->do_signing) {
+ DEBUG(1, ("smbd_smb2_tree_connect: reject request to share "
+ "[%s] as '%s\\%s' without encryption or signing. "
+ "Disconnecting.\n",
+ share,
+ req->session->global->auth_session_info->info->domain_name,
+ req->session->global->auth_session_info->info->account_name));
+ *disconnect = true;
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
service = talloc_strdup(talloc_tos(), share);
if(!service) {
return NT_STATUS_NO_MEMORY;
return NT_STATUS_BAD_NETWORK_NAME;
}
- if ((lp_smb_encrypt(snum) > SMB_SIGNING_OFF) &&
- (conn->smb2.client.capabilities & SMB2_CAP_ENCRYPTION)) {
- encryption_required = true;
+ if ((lp_smb_encrypt(snum) >= SMB_SIGNING_DESIRED) &&
+ (conn->smb2.server.cipher != 0))
+ {
+ encryption_desired = true;
}
if (lp_smb_encrypt(snum) == SMB_SIGNING_REQUIRED) {
+ encryption_desired = true;
encryption_required = true;
}
- if (security_session_user_level(compat_vuser->session_info, NULL) < SECURITY_USER) {
- guest_session = true;
- }
-
if (guest_session && encryption_required) {
DEBUG(1,("reject guest as encryption is required for service %s\n",
service));
return status;
}
- tcon->global->encryption_required = encryption_required;
+ if (encryption_desired) {
+ tcon->global->encryption_flags |= SMBXSRV_ENCRYPTION_DESIRED;
+ }
+ if (encryption_required) {
+ tcon->global->encryption_flags |= SMBXSRV_ENCRYPTION_REQUIRED;
+ }
compat_conn = make_connection_smb2(req,
tcon, snum,
*out_share_flags |= SMB2_SHAREFLAG_ACCESS_BASED_DIRECTORY_ENUM;
}
- if (encryption_required) {
+ if (encryption_desired) {
*out_share_flags |= SMB2_SHAREFLAG_ENCRYPT_DATA;
}
uint32_t out_capabilities;
uint32_t out_maximal_access;
uint32_t out_tree_id;
+ bool disconnect;
};
static struct tevent_req *smbd_smb2_tree_connect_send(TALLOC_CTX *mem_ctx,
&state->out_share_flags,
&state->out_capabilities,
&state->out_maximal_access,
- &state->out_tree_id);
+ &state->out_tree_id,
+ &state->disconnect);
if (tevent_req_nterror(req, status)) {
return tevent_req_post(req, ev);
}
uint32_t *out_share_flags,
uint32_t *out_capabilities,
uint32_t *out_maximal_access,
- uint32_t *out_tree_id)
+ uint32_t *out_tree_id,
+ bool *disconnect)
{
struct smbd_smb2_tree_connect_state *state =
tevent_req_data(req,
*out_capabilities = state->out_capabilities;
*out_maximal_access = state->out_maximal_access;
*out_tree_id = state->out_tree_id;
+ *disconnect = state->disconnect;
tevent_req_received(req);
return NT_STATUS_OK;