From 5d3d51e9ad1e4db8d9580ce7f2ba4e86e658bb13 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 20 May 2009 20:51:10 +0200 Subject: [PATCH] s3:smbd: check the incoming session id for SMB2 requests metze --- source3/smbd/globals.h | 6 ++++ source3/smbd/smb2_server.c | 63 +++++++++++++++++++++++++++++++++-- source3/smbd/smb2_sesssetup.c | 31 +++++++++++++++++ 3 files changed, 98 insertions(+), 2 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 5a7ad7d9e32..345f7488020 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -201,6 +201,7 @@ extern int num_children; struct tstream_context; struct smbd_smb2_request; +struct smbd_smb2_session; DATA_BLOB negprot_spnego(void); @@ -220,6 +221,8 @@ NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req, NTSTATUS smbd_smb2_request_done(struct smbd_smb2_request *req, DATA_BLOB body, DATA_BLOB *dyn); +NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req); + NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req); NTSTATUS smbd_smb2_request_process_sesssetup(struct smbd_smb2_request *req); NTSTATUS smbd_smb2_request_process_keepalive(struct smbd_smb2_request *req); @@ -229,6 +232,9 @@ struct smbd_smb2_request { struct smbd_server_connection *conn; + /* the session the request operates on, maybe NULL */ + struct smbd_smb2_session *session; + int current_idx; struct { diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index 6d8961eebb1..36f4c10b17d 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -288,6 +288,7 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req) const uint8_t *inhdr; int i = req->current_idx; uint16_t opcode; + NTSTATUS status; inhdr = (const uint8_t *)req->in.vector[i].iov_base; @@ -303,35 +304,73 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req) return smbd_smb2_request_process_sesssetup(req); case SMB2_OP_LOGOFF: + status = smbd_smb2_request_check_session(req); + if (!NT_STATUS_IS_OK(status)) { + return smbd_smb2_request_error(req, status); + } return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED); - return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED); case SMB2_OP_TCON: + status = smbd_smb2_request_check_session(req); + if (!NT_STATUS_IS_OK(status)) { + return smbd_smb2_request_error(req, status); + } return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED); - return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED); case SMB2_OP_TDIS: + status = smbd_smb2_request_check_session(req); + if (!NT_STATUS_IS_OK(status)) { + return smbd_smb2_request_error(req, status); + } return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED); case SMB2_OP_CREATE: + status = smbd_smb2_request_check_session(req); + if (!NT_STATUS_IS_OK(status)) { + return smbd_smb2_request_error(req, status); + } return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED); case SMB2_OP_CLOSE: + status = smbd_smb2_request_check_session(req); + if (!NT_STATUS_IS_OK(status)) { + return smbd_smb2_request_error(req, status); + } return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED); case SMB2_OP_FLUSH: + status = smbd_smb2_request_check_session(req); + if (!NT_STATUS_IS_OK(status)) { + return smbd_smb2_request_error(req, status); + } return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED); case SMB2_OP_READ: + status = smbd_smb2_request_check_session(req); + if (!NT_STATUS_IS_OK(status)) { + return smbd_smb2_request_error(req, status); + } return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED); case SMB2_OP_WRITE: + status = smbd_smb2_request_check_session(req); + if (!NT_STATUS_IS_OK(status)) { + return smbd_smb2_request_error(req, status); + } return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED); case SMB2_OP_LOCK: + status = smbd_smb2_request_check_session(req); + if (!NT_STATUS_IS_OK(status)) { + return smbd_smb2_request_error(req, status); + } return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED); case SMB2_OP_IOCTL: + status = smbd_smb2_request_check_session(req); + if (!NT_STATUS_IS_OK(status)) { + return smbd_smb2_request_error(req, status); + } return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED); case SMB2_OP_CANCEL: @@ -341,18 +380,38 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req) return smbd_smb2_request_process_keepalive(req); case SMB2_OP_FIND: + status = smbd_smb2_request_check_session(req); + if (!NT_STATUS_IS_OK(status)) { + return smbd_smb2_request_error(req, status); + } return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED); case SMB2_OP_NOTIFY: + status = smbd_smb2_request_check_session(req); + if (!NT_STATUS_IS_OK(status)) { + return smbd_smb2_request_error(req, status); + } return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED); case SMB2_OP_GETINFO: + status = smbd_smb2_request_check_session(req); + if (!NT_STATUS_IS_OK(status)) { + return smbd_smb2_request_error(req, status); + } return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED); case SMB2_OP_SETINFO: + status = smbd_smb2_request_check_session(req); + if (!NT_STATUS_IS_OK(status)) { + return smbd_smb2_request_error(req, status); + } return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED); case SMB2_OP_BREAK: + status = smbd_smb2_request_check_session(req); + if (!NT_STATUS_IS_OK(status)) { + return smbd_smb2_request_error(req, status); + } return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED); } diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c index 6c4da393e17..d322223ad5f 100644 --- a/source3/smbd/smb2_sesssetup.c +++ b/source3/smbd/smb2_sesssetup.c @@ -180,6 +180,11 @@ static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *req, } else if (NT_STATUS_IS_OK(status)) { /* TODO: setup session key for signing */ session->status = NT_STATUS_OK; + /* + * we attach the session to the request + * so that the response can be signed + */ + req->session = session; } else { return status; } @@ -188,3 +193,29 @@ static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *req, return status; } +NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req) +{ + const uint8_t *inhdr; + int i = req->current_idx; + uint64_t in_session_id; + void *p; + struct smbd_smb2_session *session; + + inhdr = (const uint8_t *)req->in.vector[i+0].iov_base; + + in_session_id = SVAL(inhdr, SMB2_HDR_SESSION_ID); + + /* lookup an existing session */ + p = idr_find(req->conn->smb2.sessions.idtree, in_session_id); + if (p == NULL) { + return NT_STATUS_USER_SESSION_DELETED; + } + session = talloc_get_type_abort(p, struct smbd_smb2_session); + + if (!NT_STATUS_IS_OK(session->status)) { + return NT_STATUS_ACCESS_DENIED; + } + + req->session = session; + return NT_STATUS_OK; +} -- 2.34.1