diff options
| -rw-r--r-- | source3/smbd/globals.h | 6 | ||||
| -rw-r--r-- | source3/smbd/smb2_server.c | 63 | ||||
| -rw-r--r-- | 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 5a7ad7d9e3..345f748802 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 6d8961eebb..36f4c10b17 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 6c4da393e1..d322223ad5 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; +}  | 
