Raise HandshakeFailure
in transport
Change the exception handling flow. Raise `SecurityUpgradeFailure` in security_multistream.
This commit is contained in:
parent
80452d9589
commit
3e04480d62
|
@ -10,6 +10,7 @@ def pubkey_from_protobuf(pubkey_pb: protobuf.PublicKey) -> PublicKey:
|
||||||
# TODO: Test against secp256k1 keys
|
# TODO: Test against secp256k1 keys
|
||||||
elif pubkey_pb.key_type == protobuf.Secp256k1:
|
elif pubkey_pb.key_type == protobuf.Secp256k1:
|
||||||
return Secp256k1PublicKey.from_bytes(pubkey_pb.data)
|
return Secp256k1PublicKey.from_bytes(pubkey_pb.data)
|
||||||
|
# TODO: Support `Ed25519` and `ECDSA` in the future?
|
||||||
else:
|
else:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"unsupported key_type={pubkey_pb.key_type}, data={pubkey_pb.data!r}"
|
f"unsupported key_type={pubkey_pb.key_type}, data={pubkey_pb.data!r}"
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
class ValidationError(Exception):
|
class BaseLibp2pError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ValidationError(BaseLibp2pError):
|
||||||
"""
|
"""
|
||||||
Raised when something does not pass a validation check.
|
Raised when something does not pass a validation check.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ from libp2p.peer.id import ID
|
||||||
from libp2p.security.base_session import BaseSession
|
from libp2p.security.base_session import BaseSession
|
||||||
from libp2p.security.base_transport import BaseSecureTransport
|
from libp2p.security.base_transport import BaseSecureTransport
|
||||||
from libp2p.security.secure_conn_interface import ISecureConn
|
from libp2p.security.secure_conn_interface import ISecureConn
|
||||||
from libp2p.transport.exceptions import SecurityUpgradeFailure
|
from libp2p.transport.exceptions import HandshakeFailure
|
||||||
from libp2p.typing import TProtocol
|
from libp2p.typing import TProtocol
|
||||||
from libp2p.utils import encode_fixedint_prefixed, read_fixedint_prefixed
|
from libp2p.utils import encode_fixedint_prefixed, read_fixedint_prefixed
|
||||||
|
|
||||||
|
@ -32,14 +32,14 @@ class InsecureSession(BaseSession):
|
||||||
# Verify if the given `pubkey` matches the given `peer_id`
|
# Verify if the given `pubkey` matches the given `peer_id`
|
||||||
try:
|
try:
|
||||||
remote_pubkey = pubkey_from_protobuf(remote_msg.pubkey)
|
remote_pubkey = pubkey_from_protobuf(remote_msg.pubkey)
|
||||||
except ValueError as error:
|
except ValueError:
|
||||||
raise SecurityUpgradeFailure(
|
raise HandshakeFailure(
|
||||||
f"unknown protocol of remote_msg.pubkey={remote_msg.pubkey}"
|
f"unknown `key_type` of remote_msg.pubkey={remote_msg.pubkey}"
|
||||||
) from error
|
)
|
||||||
remote_peer_id = ID(remote_msg.id)
|
remote_peer_id = ID(remote_msg.id)
|
||||||
remote_peer_id_from_pubkey = ID.from_pubkey(remote_pubkey)
|
remote_peer_id_from_pubkey = ID.from_pubkey(remote_pubkey)
|
||||||
if remote_peer_id_from_pubkey != remote_peer_id:
|
if remote_peer_id_from_pubkey != remote_peer_id:
|
||||||
raise SecurityUpgradeFailure(
|
raise HandshakeFailure(
|
||||||
"peer id and pubkey from the remote mismatch: "
|
"peer id and pubkey from the remote mismatch: "
|
||||||
f"remote_peer_id={remote_peer_id}, remote_pubkey={remote_pubkey}, "
|
f"remote_peer_id={remote_peer_id}, remote_pubkey={remote_pubkey}, "
|
||||||
f"remote_peer_id_from_pubkey={remote_peer_id_from_pubkey}"
|
f"remote_peer_id_from_pubkey={remote_peer_id_from_pubkey}"
|
||||||
|
@ -76,10 +76,9 @@ class InsecureTransport(BaseSecureTransport):
|
||||||
"""
|
"""
|
||||||
session = InsecureSession(self, conn, peer_id)
|
session = InsecureSession(self, conn, peer_id)
|
||||||
await session.run_handshake()
|
await session.run_handshake()
|
||||||
# TODO: Check if `remote_public_key is not None`. If so, check if `session.remote_peer`
|
|
||||||
received_peer_id = session.get_remote_peer()
|
received_peer_id = session.get_remote_peer()
|
||||||
if received_peer_id != peer_id:
|
if session.remote_permanent_pubkey is not None and received_peer_id != peer_id:
|
||||||
raise SecurityUpgradeFailure(
|
raise HandshakeFailure(
|
||||||
"remote peer sent unexpected peer ID. "
|
"remote peer sent unexpected peer ID. "
|
||||||
f"expected={peer_id} received={received_peer_id}"
|
f"expected={peer_id} received={received_peer_id}"
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,11 +4,15 @@ from typing import Mapping
|
||||||
|
|
||||||
from libp2p.network.connection.raw_connection_interface import IRawConnection
|
from libp2p.network.connection.raw_connection_interface import IRawConnection
|
||||||
from libp2p.peer.id import ID
|
from libp2p.peer.id import ID
|
||||||
from libp2p.protocol_muxer.multiselect import Multiselect
|
from libp2p.protocol_muxer.multiselect import Multiselect, MultiselectError
|
||||||
from libp2p.protocol_muxer.multiselect_client import MultiselectClient
|
from libp2p.protocol_muxer.multiselect_client import (
|
||||||
|
MultiselectClient,
|
||||||
|
MultiselectClientError,
|
||||||
|
)
|
||||||
from libp2p.protocol_muxer.multiselect_communicator import RawConnectionCommunicator
|
from libp2p.protocol_muxer.multiselect_communicator import RawConnectionCommunicator
|
||||||
from libp2p.security.secure_conn_interface import ISecureConn
|
from libp2p.security.secure_conn_interface import ISecureConn
|
||||||
from libp2p.security.secure_transport_interface import ISecureTransport
|
from libp2p.security.secure_transport_interface import ISecureTransport
|
||||||
|
from libp2p.transport.exceptions import HandshakeFailure, SecurityUpgradeFailure
|
||||||
from libp2p.typing import TProtocol
|
from libp2p.typing import TProtocol
|
||||||
|
|
||||||
|
|
||||||
|
@ -63,8 +67,18 @@ class SecurityMultistream(ABC):
|
||||||
for an inbound connection (i.e. we are not the initiator)
|
for an inbound connection (i.e. we are not the initiator)
|
||||||
:return: secure connection object (that implements secure_conn_interface)
|
:return: secure connection object (that implements secure_conn_interface)
|
||||||
"""
|
"""
|
||||||
|
try:
|
||||||
transport = await self.select_transport(conn, False)
|
transport = await self.select_transport(conn, False)
|
||||||
|
except MultiselectError as error:
|
||||||
|
raise SecurityUpgradeFailure(
|
||||||
|
"failed to negotiate the secure protocol"
|
||||||
|
) from error
|
||||||
|
try:
|
||||||
secure_conn = await transport.secure_inbound(conn)
|
secure_conn = await transport.secure_inbound(conn)
|
||||||
|
except HandshakeFailure as error:
|
||||||
|
raise SecurityUpgradeFailure(
|
||||||
|
"failed to secure the inbound transport"
|
||||||
|
) from error
|
||||||
return secure_conn
|
return secure_conn
|
||||||
|
|
||||||
async def secure_outbound(self, conn: IRawConnection, peer_id: ID) -> ISecureConn:
|
async def secure_outbound(self, conn: IRawConnection, peer_id: ID) -> ISecureConn:
|
||||||
|
@ -73,8 +87,18 @@ class SecurityMultistream(ABC):
|
||||||
for an inbound connection (i.e. we are the initiator)
|
for an inbound connection (i.e. we are the initiator)
|
||||||
:return: secure connection object (that implements secure_conn_interface)
|
:return: secure connection object (that implements secure_conn_interface)
|
||||||
"""
|
"""
|
||||||
|
try:
|
||||||
transport = await self.select_transport(conn, True)
|
transport = await self.select_transport(conn, True)
|
||||||
|
except MultiselectClientError as error:
|
||||||
|
raise SecurityUpgradeFailure(
|
||||||
|
"failed to negotiate the secure protocol"
|
||||||
|
) from error
|
||||||
|
try:
|
||||||
secure_conn = await transport.secure_outbound(conn, peer_id)
|
secure_conn = await transport.secure_outbound(conn, peer_id)
|
||||||
|
except HandshakeFailure as error:
|
||||||
|
raise SecurityUpgradeFailure(
|
||||||
|
"failed to secure the outbound transport"
|
||||||
|
) from error
|
||||||
return secure_conn
|
return secure_conn
|
||||||
|
|
||||||
async def select_transport(
|
async def select_transport(
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
|
from libp2p.exceptions import BaseLibp2pError
|
||||||
|
|
||||||
|
|
||||||
# TODO: Add `BaseLibp2pError` and `UpgradeFailure` can inherit from it?
|
# TODO: Add `BaseLibp2pError` and `UpgradeFailure` can inherit from it?
|
||||||
class UpgradeFailure(Exception):
|
class UpgradeFailure(BaseLibp2pError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class SecurityUpgradeFailure(UpgradeFailure):
|
class SecurityUpgradeFailure(UpgradeFailure):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class HandshakeFailure(BaseLibp2pError):
|
||||||
|
pass
|
||||||
|
|
|
@ -4,9 +4,9 @@ import pytest
|
||||||
|
|
||||||
from libp2p import new_node
|
from libp2p import new_node
|
||||||
from libp2p.crypto.rsa import create_new_key_pair
|
from libp2p.crypto.rsa import create_new_key_pair
|
||||||
from libp2p.protocol_muxer.multiselect_client import MultiselectClientError
|
|
||||||
from libp2p.security.insecure.transport import InsecureSession, InsecureTransport
|
from libp2p.security.insecure.transport import InsecureSession, InsecureTransport
|
||||||
from libp2p.security.simple.transport import SimpleSecurityTransport
|
from libp2p.security.simple.transport import SimpleSecurityTransport
|
||||||
|
from libp2p.transport.exceptions import SecurityUpgradeFailure
|
||||||
from tests.configs import LISTEN_MADDR
|
from tests.configs import LISTEN_MADDR
|
||||||
from tests.utils import cleanup, connect
|
from tests.utils import cleanup, connect
|
||||||
|
|
||||||
|
@ -161,7 +161,7 @@ async def test_multiple_security_none_the_same_fails():
|
||||||
def assertion_func(_):
|
def assertion_func(_):
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
with pytest.raises(MultiselectClientError):
|
with pytest.raises(SecurityUpgradeFailure):
|
||||||
await perform_simple_test(
|
await perform_simple_test(
|
||||||
assertion_func, transports_for_initiator, transports_for_noninitiator
|
assertion_func, transports_for_initiator, transports_for_noninitiator
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user