x->global->signing_required = true;
}
+ if (lp_smb_encrypt(-1) == SMB_SIGNING_REQUIRED) {
+ x->global->encryption_required = true;
+ }
+
if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
/* we map anonymous to guest internally */
*out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
guest = true;
}
+ if (guest && x->global->encryption_required) {
+ DEBUG(1,("reject guest session as encryption is required\n"));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ if (!(conn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION)) {
+ if (x->global->encryption_required) {
+ DEBUG(1,("reject session with dialect[0x%04X] "
+ "as encryption is required\n",
+ conn->smb2.server.dialect));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ }
+
+ if (x->global->encryption_required) {
+ *out_session_flags |= SMB2_SESSION_FLAG_ENCRYPT_DATA;
+ }
+
ZERO_STRUCT(session_key);
memcpy(session_key, session_info->session_key.data,
MIN(session_info->session_key.length, sizeof(session_key)));
sizeof(session_key));
if (x->global->signing_key.data == NULL) {
ZERO_STRUCT(session_key);
- TALLOC_FREE(session);
return NT_STATUS_NO_MEMORY;
}
x->global->signing_key.data);
}
+ if (conn->protocol >= PROTOCOL_SMB2_24) {
+ const DATA_BLOB label = data_blob_string_const_null("SMB2AESCCM");
+ const DATA_BLOB context = data_blob_string_const_null("ServerIn ");
+
+ x->global->decryption_key = data_blob_talloc(x->global,
+ session_key,
+ sizeof(session_key));
+ if (x->global->decryption_key.data == NULL) {
+ ZERO_STRUCT(session_key);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ smb2_key_derivation(session_key, sizeof(session_key),
+ label.data, label.length,
+ context.data, context.length,
+ x->global->decryption_key.data);
+ }
+
+ if (conn->protocol >= PROTOCOL_SMB2_24) {
+ const DATA_BLOB label = data_blob_string_const_null("SMB2AESCCM");
+ const DATA_BLOB context = data_blob_string_const_null("ServerOut");
+
+ x->global->encryption_key = data_blob_talloc(x->global,
+ session_key,
+ sizeof(session_key));
+ if (x->global->encryption_key.data == NULL) {
+ ZERO_STRUCT(session_key);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ smb2_key_derivation(session_key, sizeof(session_key),
+ label.data, label.length,
+ context.data, context.length,
+ x->global->encryption_key.data);
+
+ generate_random_buffer((uint8_t *)&x->nonce_high, sizeof(x->nonce_high));
+ x->nonce_low = 1;
+ }
+
x->global->application_key = data_blob_dup_talloc(x->global,
x->global->signing_key);
if (x->global->application_key.data == NULL) {
ZERO_STRUCT(session_key);
- TALLOC_FREE(session);
return NT_STATUS_NO_MEMORY;
}
x->global->channels[0].signing_key = data_blob_dup_talloc(x->global->channels,
x->global->signing_key);
if (x->global->channels[0].signing_key.data == NULL) {
- TALLOC_FREE(session);
return NT_STATUS_NO_MEMORY;
}
session_info->session_key = data_blob_dup_talloc(session_info,
x->global->application_key);
if (session_info->session_key.data == NULL) {
- TALLOC_FREE(session);
return NT_STATUS_NO_MEMORY;
}
session->compat = talloc_zero(session, struct user_struct);
if (session->compat == NULL) {
- TALLOC_FREE(session);
return NT_STATUS_NO_MEMORY;
}
session->compat->session = session;
register_homes_share(session_info->unix_info->unix_name);
}
- if (!session_claim(smb2req->sconn, session->compat)) {
+ if (!session_claim(smb2req->sconn, session)) {
DEBUG(1, ("smb2: Failed to claim session "
"for vuid=%llu\n",
(unsigned long long)session->compat->vuid));
- TALLOC_FREE(session);
return NT_STATUS_LOGON_FAILURE;
}
DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
(unsigned long long)session->compat->vuid,
nt_errstr(status)));
- TALLOC_FREE(session);
return NT_STATUS_LOGON_FAILURE;
}
session_info->session_key = data_blob_dup_talloc(session_info,
x->global->application_key);
if (session_info->session_key.data == NULL) {
- TALLOC_FREE(session);
return NT_STATUS_NO_MEMORY;
}
DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
(unsigned long long)session->compat->vuid,
nt_errstr(status)));
- TALLOC_FREE(session);
return NT_STATUS_LOGON_FAILURE;
}
conn_clear_vuid_caches(conn->sconn, session->compat->vuid);
- /*
- * we attach the session to the request
- * so that the response can be signed
- */
- smb2req->session = session;
- smb2req->do_signing = true;
-
- global_client_caps |= (CAP_LEVEL_II_OPLOCKS|CAP_STATUS32);
-
*out_session_id = session->global->session_wire_id;
return NT_STATUS_OK;
uint16_t out_session_flags;
DATA_BLOB out_security_buffer;
uint64_t out_session_id;
+ /* The following pointer is owned by state->session. */
+ struct smbd_smb2_session_setup_state **pp_self_ref;
};
+static int pp_self_ref_destructor(struct smbd_smb2_session_setup_state **pp_state)
+{
+ (*pp_state)->session = NULL;
+ /*
+ * To make things clearer, ensure the pp_self_ref
+ * pointer is nulled out. We're never going to
+ * access this again.
+ */
+ (*pp_state)->pp_self_ref = NULL;
+ return 0;
+}
+
static int smbd_smb2_session_setup_state_destructor(struct smbd_smb2_session_setup_state *state)
{
/*
static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq);
static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq);
+/************************************************************************
+ We have to tag the state->session pointer with memory talloc'ed
+ on it to ensure it gets NULL'ed out if the underlying struct smbXsrv_session
+ is deleted by shutdown whilst this request is in flight.
+************************************************************************/
+
+static NTSTATUS tag_state_session_ptr(struct smbd_smb2_session_setup_state *state)
+{
+ state->pp_self_ref = talloc_zero(state->session,
+ struct smbd_smb2_session_setup_state *);
+ if (state->pp_self_ref == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ *state->pp_self_ref = state;
+ talloc_set_destructor(state->pp_self_ref, pp_self_ref_destructor);
+ return NT_STATUS_OK;
+}
+
static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct smbd_smb2_request *smb2req,
}
}
+ status = tag_state_session_ptr(state);
+ if (tevent_req_nterror(req, status)) {
+ return tevent_req_post(req, ev);
+ }
+
if (state->session->gensec == NULL) {
status = auth_generic_prepare(state->session,
state->session->connection->remote_address,
if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
state->out_session_id = state->session->global->session_wire_id;
/* we want to keep the session */
- state->session = NULL;
+ TALLOC_FREE(state->pp_self_ref);
tevent_req_nterror(req, status);
return;
}
return;
}
/* we want to keep the session */
- state->session = NULL;
+ TALLOC_FREE(state->pp_self_ref);
tevent_req_done(req);
return;
}
}
/* we want to keep the session */
- state->session = NULL;
+ TALLOC_FREE(state->pp_self_ref);
tevent_req_done(req);
return;
}
return;
}
/* we want to keep the session */
- state->session = NULL;
+ TALLOC_FREE(state->pp_self_ref);
tevent_req_done(req);
return;
}
}
/* we want to keep the session */
- state->session = NULL;
+ TALLOC_FREE(state->pp_self_ref);
tevent_req_done(req);
return;
}