Beispiel #1
0
struct ntvfs_handle *smb2srv_pull_handle(struct smb2srv_request *req, const uint8_t *base, uint_t offset)
{
	struct smbsrv_tcon *tcon;
	struct smbsrv_handle *handle;
	uint64_t hid;
	uint32_t tid;
	uint32_t pad;

	hid = BVAL(base, offset);
	tid = IVAL(base, offset + 8);
	pad = IVAL(base, offset + 12);

	if (pad != UINT32_MAX) {
		return NULL;
	}

	/* if it's the wildcard handle, don't waste time to search it... */
	if (hid == UINT64_MAX && tid == UINT32_MAX) {
		return NULL;
	}

	/*
	 * the handle can belong to a different tcon
	 * as that TID in the SMB2 header says, but
	 * the request should succeed nevertheless!
	 *
	 * because if this we put the 32 bit TID into the
	 * 128 bit handle, so that we can extract the tcon from the
	 * handle
	 */
	tcon = req->tcon;
	if (tid != req->tcon->tid) {
		tcon = smbsrv_smb2_tcon_find(req->session, tid, req->request_time);
		if (!tcon) {
			return NULL;
		}
	}

	handle = smbsrv_smb2_handle_find(tcon, hid, req->request_time);
	if (!handle) {
		return NULL;
	}

	/*
	 * as the smb2srv_tcon is a child object of the smb2srv_session
	 * the handle belongs to the correct session!
	 *
	 * Note: no check is needed here for SMB2
	 */

	/*
	 * as the handle may have overwritten the tcon
	 * we need to set it on the request so that the
	 * correct ntvfs context will be used for the ntvfs_*() request
	 */
	req->tcon = tcon;
	return handle->ntvfs;
}
Beispiel #2
0
static NTSTATUS smb2srv_reply(struct smb2srv_request *req)
{
	uint16_t opcode;
	uint32_t tid;
	uint64_t uid;
	uint32_t flags;

	if (SVAL(req->in.hdr, SMB2_HDR_LENGTH) != SMB2_HDR_BODY) {
		smbsrv_terminate_connection(req->smb_conn, "Invalid SMB2 header length");
		return NT_STATUS_INVALID_PARAMETER;
	}
	opcode			= SVAL(req->in.hdr, SMB2_HDR_OPCODE);
	req->chain_offset	= IVAL(req->in.hdr, SMB2_HDR_NEXT_COMMAND);
	req->seqnum		= BVAL(req->in.hdr, SMB2_HDR_MESSAGE_ID);
	tid			= IVAL(req->in.hdr, SMB2_HDR_TID);
	uid			= BVAL(req->in.hdr, SMB2_HDR_SESSION_ID);
	flags			= IVAL(req->in.hdr, SMB2_HDR_FLAGS);

	if (opcode != SMB2_OP_CANCEL &&
	    req->smb_conn->highest_smb2_seqnum != 0 &&
	    req->seqnum <= req->smb_conn->highest_smb2_seqnum) {
		smbsrv_terminate_connection(req->smb_conn, "Invalid SMB2 sequence number");
		return NT_STATUS_INVALID_PARAMETER;
	}
	if (opcode != SMB2_OP_CANCEL) {
		req->smb_conn->highest_smb2_seqnum = req->seqnum;
	}

	if (flags & SMB2_HDR_FLAG_CHAINED) {
		uid = req->chained_session_id;
		tid = req->chained_tree_id;
	}

	req->session	= smbsrv_session_find(req->smb_conn, uid, req->request_time);
	req->tcon	= smbsrv_smb2_tcon_find(req->session, tid, req->request_time);

	req->chained_session_id = uid;
	req->chained_tree_id = tid;

	errno = 0;

	/* supporting signing is mandatory in SMB2, and is per-packet. So we 
	   should check the signature on any incoming packet that is signed, and 
	   should give a signed reply to any signed request */
	if (flags & SMB2_HDR_FLAG_SIGNED) {
		NTSTATUS status;

		if (!req->session) goto nosession;

		req->is_signed = true;
		status = smb2_check_signature(&req->in, 
					      req->session->session_info->session_key);
		if (!NT_STATUS_IS_OK(status)) {
			smb2srv_send_error(req, status);
			return NT_STATUS_OK;			
		}
	} else if (req->session && req->session->smb2_signing.active) {
		/* we require signing and this request was not signed */
		smb2srv_send_error(req, NT_STATUS_ACCESS_DENIED);
		return NT_STATUS_OK;					
	}

	if (!NT_STATUS_IS_OK(req->chain_status)) {
		smb2srv_send_error(req, req->chain_status);
		return NT_STATUS_OK;
	}

	switch (opcode) {
	case SMB2_OP_NEGPROT:
		smb2srv_negprot_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_SESSSETUP:
		smb2srv_sesssetup_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_LOGOFF:
		if (!req->session) goto nosession;
		smb2srv_logoff_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_TCON:
		if (!req->session) goto nosession;
		smb2srv_tcon_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_TDIS:
		if (!req->session) goto nosession;
		if (!req->tcon)	goto notcon;
		smb2srv_tdis_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_CREATE:
		if (!req->session) goto nosession;
		if (!req->tcon)	goto notcon;
		smb2srv_create_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_CLOSE:
		if (!req->session) goto nosession;
		if (!req->tcon)	goto notcon;
		smb2srv_close_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_FLUSH:
		if (!req->session) goto nosession;
		if (!req->tcon)	goto notcon;
		smb2srv_flush_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_READ:
		if (!req->session) goto nosession;
		if (!req->tcon)	goto notcon;
		smb2srv_read_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_WRITE:
		if (!req->session) goto nosession;
		if (!req->tcon)	goto notcon;
		smb2srv_write_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_LOCK:
		if (!req->session) goto nosession;
		if (!req->tcon)	goto notcon;
		smb2srv_lock_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_IOCTL:
		if (!req->session) goto nosession;
		if (!req->tcon)	goto notcon;
		smb2srv_ioctl_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_CANCEL:
		smb2srv_cancel_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_KEEPALIVE:
		smb2srv_keepalive_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_FIND:
		if (!req->session) goto nosession;
		if (!req->tcon)	goto notcon;
		smb2srv_find_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_NOTIFY:
		if (!req->session) goto nosession;
		if (!req->tcon)	goto notcon;
		smb2srv_notify_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_GETINFO:
		if (!req->session) goto nosession;
		if (!req->tcon)	goto notcon;
		smb2srv_getinfo_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_SETINFO:
		if (!req->session) goto nosession;
		if (!req->tcon)	goto notcon;
		smb2srv_setinfo_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_BREAK:
		if (!req->session) goto nosession;
		if (!req->tcon)	goto notcon;
		smb2srv_break_recv(req);
		return NT_STATUS_OK;
	}

	DEBUG(1,("Invalid SMB2 opcode: 0x%04X\n", opcode));
	smbsrv_terminate_connection(req->smb_conn, "Invalid SMB2 opcode");
	return NT_STATUS_OK;

nosession:
	smb2srv_send_error(req, NT_STATUS_USER_SESSION_DELETED);
	return NT_STATUS_OK;
notcon:
	smb2srv_send_error(req, NT_STATUS_NETWORK_NAME_DELETED);
	return NT_STATUS_OK;
}