diff --git a/p2p/protocol/circuitv2/client/reservation.go b/p2p/protocol/circuitv2/client/reservation.go index dbb9241937..462c01d236 100644 --- a/p2p/protocol/circuitv2/client/reservation.go +++ b/p2p/protocol/circuitv2/client/reservation.go @@ -93,10 +93,7 @@ func Reserve(ctx context.Context, h host.Host, ai peer.AddrInfo) (*Reservation, } if msg.GetType() != pbv2.HopMessage_STATUS { - return nil, ReservationError{ - Status: pbv2.Status_MALFORMED_MESSAGE, - Reason: fmt.Sprintf("unexpected relay response: not a status message (%d)", msg.GetType()), - err: err} + return nil, ReservationError{Status: pbv2.Status_MALFORMED_MESSAGE, Reason: fmt.Sprintf("unexpected relay response: not a status message (%d)", msg.GetType())} } if status := msg.GetStatus(); status != pbv2.Status_OK { @@ -130,7 +127,7 @@ func Reserve(ctx context.Context, h host.Host, ai peer.AddrInfo) (*Reservation, voucherBytes := rsvp.GetVoucher() if voucherBytes != nil { - _, rec, err := record.ConsumeEnvelope(voucherBytes, proto.RecordDomain) + env, rec, err := record.ConsumeEnvelope(voucherBytes, proto.RecordDomain) if err != nil { return nil, ReservationError{ Status: pbv2.Status_MALFORMED_MESSAGE, @@ -146,6 +143,27 @@ func Reserve(ctx context.Context, h host.Host, ai peer.AddrInfo) (*Reservation, Reason: fmt.Sprintf("unexpected voucher record type: %+T", rec), } } + signerPeerID, err := peer.IDFromPublicKey(env.PublicKey) + if err != nil { + return nil, ReservationError{ + Status: pbv2.Status_MALFORMED_MESSAGE, + Reason: fmt.Sprintf("invalid voucher signing public key: %s", err), + err: err, + } + } + if signerPeerID != voucher.Relay { + return nil, ReservationError{ + Status: pbv2.Status_MALFORMED_MESSAGE, + Reason: fmt.Sprintf("invalid voucher relay id: expected %s, got %s", signerPeerID, voucher.Relay), + } + } + if h.ID() != voucher.Peer { + return nil, ReservationError{ + Status: pbv2.Status_MALFORMED_MESSAGE, + Reason: fmt.Sprintf("invalid voucher peer id: expected %s, got %s", h.ID(), voucher.Peer), + } + + } result.Voucher = voucher } diff --git a/p2p/protocol/circuitv2/client/reservation_test.go b/p2p/protocol/circuitv2/client/reservation_test.go index decb3e71de..d1ab6dc683 100644 --- a/p2p/protocol/circuitv2/client/reservation_test.go +++ b/p2p/protocol/circuitv2/client/reservation_test.go @@ -8,8 +8,11 @@ import ( "time" "github.com/libp2p/go-libp2p" + "github.com/libp2p/go-libp2p/core/crypto" "github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/core/peer" + "github.com/libp2p/go-libp2p/core/record" + "github.com/libp2p/go-libp2p/core/test" "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/client" pbv2 "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/pb" "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/proto" @@ -84,6 +87,45 @@ func TestReservationFailures(t *testing.T) { err: "error consuming voucher envelope: failed when unmarshalling the envelope", status: pbv2.Status_MALFORMED_MESSAGE, }, + { + name: "invalid voucher 2", + streamHandler: func(s network.Stream) { + status := pbv2.Status_OK + expire := uint64(time.Now().Add(time.Hour).UnixNano()) + priv, _, err := test.RandTestKeyPair(crypto.Ed25519, 256) + if err != nil { + s.Reset() + return + } + relay, _ := test.RandPeerID() + peer, _ := test.RandPeerID() + voucher := &proto.ReservationVoucher{ + Relay: relay, + Peer: peer, + Expiration: time.Now().Add(time.Hour), + } + signedVoucher, err := record.Seal(voucher, priv) + if err != nil { + s.Reset() + return + } + env, err := signedVoucher.Marshal() + if err != nil { + s.Reset() + return + } + util.NewDelimitedWriter(s).WriteMsg(&pbv2.HopMessage{ + Type: pbv2.HopMessage_STATUS.Enum(), + Status: &status, + Reservation: &pbv2.Reservation{ + Expire: &expire, + Voucher: env, + }, + }) + }, + err: "invalid voucher relay id", + status: pbv2.Status_MALFORMED_MESSAGE, + }, } for _, tc := range testcases {