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_REQUIRED) {
- encryption_required = true;
+ if ((lp_smb_encrypt(snum) >= SMB_SIGNING_DESIRED) &&
+ (conn->smb2.server.cipher != 0))
+ {
+ encryption_desired = true;
}
- if (security_session_user_level(compat_vuser->session_info, NULL) < SECURITY_USER) {
- guest_session = true;
+ if (lp_smb_encrypt(snum) == SMB_SIGNING_REQUIRED) {
+ encryption_desired = true;
+ encryption_required = true;
}
if (guest_session && encryption_required) {
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;
struct tevent_req *req;
struct smbd_smb2_tdis_state *state;
struct tevent_req *subreq;
- struct smbd_smb2_request *preq;
- struct smbXsrv_connection *xconn = smb2req->xconn;
+ struct smbXsrv_connection *xconn = NULL;
req = tevent_req_create(mem_ctx, &state,
struct smbd_smb2_tdis_state);
*/
smb2req->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
- for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
- if (preq == smb2req) {
- /* Can't cancel current request. */
- continue;
- }
- if (preq->tcon != smb2req->tcon) {
- /* Request on different tcon. */
- continue;
- }
-
- /*
- * Never cancel anything in a compound
- * request. Way too hard to deal with
- * the result.
- */
- if (!preq->compound_related && preq->subreq != NULL) {
- tevent_req_cancel(preq->subreq);
- }
-
- /*
- * Now wait until the request is finished.
- *
- * We don't set a callback, as we just want to block the
- * wait queue and the talloc_free() of the request will
- * remove the item from the wait queue.
- */
- subreq = tevent_queue_wait_send(preq, ev, state->wait_queue);
- if (tevent_req_nomem(subreq, req)) {
- return tevent_req_post(req, ev);
+ xconn = smb2req->xconn->client->connections;
+ for (; xconn != NULL; xconn = xconn->next) {
+ struct smbd_smb2_request *preq;
+
+ for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
+ if (preq == smb2req) {
+ /* Can't cancel current request. */
+ continue;
+ }
+ if (preq->tcon != smb2req->tcon) {
+ /* Request on different tcon. */
+ continue;
+ }
+
+ /*
+ * Never cancel anything in a compound
+ * request. Way too hard to deal with
+ * the result.
+ */
+ if (!preq->compound_related && preq->subreq != NULL) {
+ tevent_req_cancel(preq->subreq);
+ }
+
+ /*
+ * Now wait until the request is finished.
+ *
+ * We don't set a callback, as we just want to block the
+ * wait queue and the talloc_free() of the request will
+ * remove the item from the wait queue.
+ */
+ subreq = tevent_queue_wait_send(preq, ev, state->wait_queue);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
}
}