mirror of
https://github.com/samba-team/samba.git
synced 2025-01-26 10:04:02 +03:00
s3:smb2_sesssetup: make use of the smbXsrv_session infrastructure
We still have smbd_smb2_session as primary structure, but that will went away once we got rid of smbd_smb2_tcon. metze
This commit is contained in:
parent
1fffd35692
commit
02d206ee64
@ -494,8 +494,8 @@ struct smbd_smb2_session {
|
||||
uint64_t vuid;
|
||||
struct gensec_security *gensec_security;
|
||||
struct auth_session_info *session_info;
|
||||
DATA_BLOB session_key;
|
||||
bool do_signing;
|
||||
|
||||
struct smbXsrv_session *smbXsrv;
|
||||
|
||||
struct user_struct *compat_vuser;
|
||||
|
||||
@ -532,6 +532,8 @@ struct user_struct {
|
||||
struct auth_session_info *session_info;
|
||||
|
||||
struct gensec_security *gensec_security;
|
||||
|
||||
struct smbXsrv_session0 *session;
|
||||
};
|
||||
|
||||
struct smbd_server_connection {
|
||||
@ -672,14 +674,6 @@ struct smbd_server_connection {
|
||||
struct tstream_context *stream;
|
||||
bool negprot_2ff;
|
||||
struct {
|
||||
/* an id tree used to allocate vuids */
|
||||
/* this holds info on session vuids that are already
|
||||
* validated for this VC */
|
||||
struct idr_context *idtree;
|
||||
|
||||
/* this is the limit of vuid values for this connection */
|
||||
uint64_t limit;
|
||||
|
||||
struct smbd_smb2_session *list;
|
||||
} sessions;
|
||||
struct {
|
||||
|
@ -3157,9 +3157,18 @@ static void smbd_id_cache_kill(struct messaging_context *msg_ctx,
|
||||
NTSTATUS smbXsrv_connection_init_tables(struct smbXsrv_connection *conn,
|
||||
enum protocol_types protocol)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
set_Protocol(protocol);
|
||||
conn->protocol = protocol;
|
||||
|
||||
if (protocol >= PROTOCOL_SMB2_02) {
|
||||
status = smb2srv_session_table_init(conn);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
|
@ -108,11 +108,6 @@ static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
sconn->smb2.sessions.idtree = idr_init(sconn);
|
||||
if (sconn->smb2.sessions.idtree == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
sconn->smb2.sessions.limit = 0x0000FFFE;
|
||||
sconn->smb2.sessions.list = NULL;
|
||||
sconn->smb2.seqnum_low = 0;
|
||||
sconn->smb2.credits_granted = 0;
|
||||
@ -816,9 +811,13 @@ static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request
|
||||
/* Re-sign if needed. */
|
||||
if (nreq->do_signing) {
|
||||
NTSTATUS status;
|
||||
status = smb2_signing_sign_pdu(nreq->session->session_key,
|
||||
get_Protocol(),
|
||||
&nreq->out.vector[i], 3);
|
||||
struct smbXsrv_session *x = nreq->session->smbXsrv;
|
||||
struct smbXsrv_connection *conn = x->connection;
|
||||
DATA_BLOB signing_key = x->global->channels[0].signing_key;
|
||||
|
||||
status = smb2_signing_sign_pdu(signing_key,
|
||||
conn->protocol,
|
||||
&nreq->out.vector[i], 3);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
@ -1101,10 +1100,13 @@ static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
|
||||
|
||||
if (req->do_signing) {
|
||||
NTSTATUS status;
|
||||
struct smbXsrv_session *x = req->session->smbXsrv;
|
||||
struct smbXsrv_connection *conn = x->connection;
|
||||
DATA_BLOB signing_key = x->global->channels[0].signing_key;
|
||||
|
||||
status = smb2_signing_sign_pdu(req->session->session_key,
|
||||
get_Protocol(),
|
||||
&state->vector[1], 2);
|
||||
status = smb2_signing_sign_pdu(signing_key,
|
||||
conn->protocol,
|
||||
&state->vector[1], 2);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
smbd_server_connection_terminate(req->sconn,
|
||||
nt_errstr(status));
|
||||
@ -1247,8 +1249,10 @@ static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
|
||||
int i = req->current_idx;
|
||||
uint32_t in_flags;
|
||||
uint64_t in_session_id;
|
||||
void *p;
|
||||
struct smbd_smb2_session *session;
|
||||
struct smbXsrv_session *smbXsrv;
|
||||
NTSTATUS status;
|
||||
NTTIME now = timeval_to_nttime(&req->request_time);
|
||||
|
||||
req->session = NULL;
|
||||
req->tcon = NULL;
|
||||
@ -1263,12 +1267,13 @@ static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
|
||||
}
|
||||
|
||||
/* lookup an existing session */
|
||||
p = idr_find(req->sconn->smb2.sessions.idtree, in_session_id);
|
||||
if (p == NULL) {
|
||||
return NT_STATUS_USER_SESSION_DELETED;
|
||||
status = smb2srv_session_lookup(req->sconn->conn,
|
||||
in_session_id, now,
|
||||
&smbXsrv);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
session = talloc_get_type_abort(p, struct smbd_smb2_session);
|
||||
|
||||
session = smbXsrv->smb2sess;
|
||||
if (!NT_STATUS_IS_OK(session->status)) {
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
@ -1388,6 +1393,7 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
|
||||
NTSTATUS session_status;
|
||||
uint32_t allowed_flags;
|
||||
NTSTATUS return_value;
|
||||
struct smbXsrv_session *x = NULL;
|
||||
|
||||
inhdr = (const uint8_t *)req->in.vector[i].iov_base;
|
||||
|
||||
@ -1439,23 +1445,29 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
|
||||
* we defer the check of the session_status
|
||||
*/
|
||||
session_status = smbd_smb2_request_check_session(req);
|
||||
if (req->session) {
|
||||
x = req->session->smbXsrv;
|
||||
}
|
||||
|
||||
req->do_signing = false;
|
||||
if (flags & SMB2_HDR_FLAG_SIGNED) {
|
||||
struct smbXsrv_connection *conn = x->connection;
|
||||
DATA_BLOB signing_key = x->global->channels[0].signing_key;
|
||||
|
||||
if (!NT_STATUS_IS_OK(session_status)) {
|
||||
return smbd_smb2_request_error(req, session_status);
|
||||
}
|
||||
|
||||
req->do_signing = true;
|
||||
status = smb2_signing_check_pdu(req->session->session_key,
|
||||
get_Protocol(),
|
||||
status = smb2_signing_check_pdu(signing_key,
|
||||
conn->protocol,
|
||||
&req->in.vector[i], 3);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return smbd_smb2_request_error(req, status);
|
||||
}
|
||||
} else if (opcode == SMB2_OP_CANCEL) {
|
||||
/* Cancel requests are allowed to skip the signing */
|
||||
} else if (req->session && req->session->do_signing) {
|
||||
} else if (x && x->global->signing_required) {
|
||||
return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
|
||||
}
|
||||
|
||||
@ -1937,8 +1949,12 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
|
||||
|
||||
if (req->do_signing) {
|
||||
NTSTATUS status;
|
||||
status = smb2_signing_sign_pdu(req->session->session_key,
|
||||
get_Protocol(),
|
||||
struct smbXsrv_session *x = req->session->smbXsrv;
|
||||
struct smbXsrv_connection *conn = x->connection;
|
||||
DATA_BLOB signing_key = x->global->channels[0].signing_key;
|
||||
|
||||
status = smb2_signing_sign_pdu(signing_key,
|
||||
conn->protocol,
|
||||
&req->out.vector[i], 3);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
|
@ -187,7 +187,6 @@ static int smbd_smb2_session_destructor(struct smbd_smb2_session *session)
|
||||
talloc_free(session->tcons.list);
|
||||
}
|
||||
|
||||
idr_remove(session->sconn->smb2.sessions.idtree, session->vuid);
|
||||
DLIST_REMOVE(session->sconn->smb2.sessions.list, session);
|
||||
invalidate_vuid(session->sconn, session->vuid);
|
||||
|
||||
@ -195,6 +194,9 @@ static int smbd_smb2_session_destructor(struct smbd_smb2_session *session)
|
||||
session->status = NT_STATUS_USER_SESSION_DELETED;
|
||||
session->sconn = NULL;
|
||||
|
||||
session->smbXsrv->compat = NULL;
|
||||
TALLOC_FREE(session->smbXsrv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -206,11 +208,14 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbd_smb2_session *session,
|
||||
uint16_t *out_session_flags,
|
||||
uint64_t *out_session_id)
|
||||
{
|
||||
NTSTATUS status;
|
||||
bool guest = false;
|
||||
uint8_t session_key[16];
|
||||
struct smbXsrv_session *x = session->smbXsrv;
|
||||
|
||||
if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
|
||||
lp_server_signing() == SMB_SIGNING_REQUIRED) {
|
||||
session->do_signing = true;
|
||||
x->global->signing_required = true;
|
||||
}
|
||||
|
||||
if (security_session_user_level(session->session_info, NULL) < SECURITY_USER) {
|
||||
@ -218,11 +223,39 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbd_smb2_session *session,
|
||||
*out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
|
||||
*out_session_flags |= SMB2_SESSION_FLAG_IS_NULL;
|
||||
/* force no signing */
|
||||
session->do_signing = false;
|
||||
x->global->signing_required = false;
|
||||
guest = true;
|
||||
}
|
||||
|
||||
session->session_key = session->session_info->session_key;
|
||||
ZERO_STRUCT(session_key);
|
||||
memcpy(session_key, session->session_info->session_key.data,
|
||||
MIN(session->session_info->session_key.length, sizeof(session_key)));
|
||||
|
||||
x->global->signing_key = data_blob_talloc(x->global,
|
||||
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->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;
|
||||
}
|
||||
|
||||
ZERO_STRUCT(session_key);
|
||||
|
||||
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->compat_vuser = talloc_zero(session, struct user_struct);
|
||||
if (session->compat_vuser == NULL) {
|
||||
@ -256,6 +289,21 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbd_smb2_session *session,
|
||||
|
||||
reload_services(smb2req->sconn, conn_snum_used, true);
|
||||
|
||||
session->smbXsrv->status = NT_STATUS_OK;
|
||||
session->smbXsrv->global->auth_session_info = session->session_info;
|
||||
session->smbXsrv->global->auth_session_info_seqnum += 1;
|
||||
session->smbXsrv->global->channels[0].auth_session_info_seqnum =
|
||||
session->smbXsrv->global->auth_session_info_seqnum;
|
||||
|
||||
status = smbXsrv_session_update(session->smbXsrv);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
|
||||
(unsigned long long)session->compat_vuser->vuid,
|
||||
nt_errstr(status)));
|
||||
TALLOC_FREE(session);
|
||||
return NT_STATUS_LOGON_FAILURE;
|
||||
}
|
||||
|
||||
session->status = NT_STATUS_OK;
|
||||
|
||||
/*
|
||||
@ -351,55 +399,63 @@ static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *smb2req,
|
||||
DATA_BLOB *out_security_buffer,
|
||||
uint64_t *out_session_id)
|
||||
{
|
||||
struct smbd_smb2_session *session;
|
||||
struct smbd_smb2_session *smb2sess;
|
||||
struct smbXsrv_session *session;
|
||||
NTSTATUS status;
|
||||
NTTIME now = timeval_to_nttime(&smb2req->request_time);
|
||||
|
||||
*out_session_flags = 0;
|
||||
*out_session_id = 0;
|
||||
|
||||
if (in_session_id == 0) {
|
||||
int id;
|
||||
|
||||
/* create a new session */
|
||||
session = talloc_zero(smb2req->sconn, struct smbd_smb2_session);
|
||||
if (session == NULL) {
|
||||
smb2sess = talloc_zero(smb2req->sconn, struct smbd_smb2_session);
|
||||
if (smb2sess == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
|
||||
id = idr_get_new_random(smb2req->sconn->smb2.sessions.idtree,
|
||||
session,
|
||||
smb2req->sconn->smb2.sessions.limit);
|
||||
if (id == -1) {
|
||||
return NT_STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
session->vuid = id;
|
||||
|
||||
session->tcons.idtree = idr_init(session);
|
||||
if (session->tcons.idtree == NULL) {
|
||||
status = smbXsrv_session_create(smb2req->sconn->conn,
|
||||
now, &session);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
smb2sess->smbXsrv = session;
|
||||
session->smb2sess = smb2sess;
|
||||
talloc_set_destructor(smb2sess, smbd_smb2_session_destructor);
|
||||
|
||||
smb2sess->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
|
||||
smb2sess->vuid = session->global->session_wire_id;
|
||||
|
||||
smb2sess->tcons.idtree = idr_init(smb2sess);
|
||||
if (smb2sess->tcons.idtree == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
session->tcons.limit = 0x0000FFFE;
|
||||
session->tcons.list = NULL;
|
||||
smb2sess->tcons.limit = 0x0000FFFE;
|
||||
smb2sess->tcons.list = NULL;
|
||||
|
||||
DLIST_ADD_END(smb2req->sconn->smb2.sessions.list, session,
|
||||
DLIST_ADD_END(smb2req->sconn->smb2.sessions.list, smb2sess,
|
||||
struct smbd_smb2_session *);
|
||||
session->sconn = smb2req->sconn;
|
||||
talloc_set_destructor(session, smbd_smb2_session_destructor);
|
||||
smb2sess->sconn = smb2req->sconn;
|
||||
} else {
|
||||
void *p;
|
||||
|
||||
/* lookup an existing session */
|
||||
p = idr_find(smb2req->sconn->smb2.sessions.idtree, in_session_id);
|
||||
if (p == NULL) {
|
||||
return NT_STATUS_USER_SESSION_DELETED;
|
||||
status = smb2srv_session_lookup(smb2req->sconn->conn,
|
||||
in_session_id, now,
|
||||
&session);
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
return NT_STATUS_REQUEST_NOT_ACCEPTED;
|
||||
}
|
||||
session = talloc_get_type_abort(p, struct smbd_smb2_session);
|
||||
if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
smb2sess = session->smb2sess;
|
||||
}
|
||||
|
||||
if (NT_STATUS_IS_OK(session->status)) {
|
||||
if (NT_STATUS_IS_OK(smb2sess->status)) {
|
||||
return NT_STATUS_REQUEST_NOT_ACCEPTED;
|
||||
}
|
||||
|
||||
return smbd_smb2_auth_generic(session,
|
||||
return smbd_smb2_auth_generic(smb2sess,
|
||||
smb2req,
|
||||
in_security_mode,
|
||||
in_previous_session_id,
|
||||
|
Loading…
x
Reference in New Issue
Block a user