p2p/subproto/cert.go
/**
* @file
* @copyright defined in aergo/LICENSE.txt
*/
package subproto
import (
"github.com/aergoio/aergo-lib/log"
"github.com/aergoio/aergo/v2/p2p/p2pcommon"
"github.com/aergoio/aergo/v2/p2p/p2putil"
"github.com/aergoio/aergo/v2/types"
)
type issueCertRequestHandler struct {
BaseMsgHandler
cm p2pcommon.CertificateManager
}
var _ p2pcommon.MessageHandler = (*issueCertRequestHandler)(nil)
type issueCertResponseHandler struct {
BaseMsgHandler
cm p2pcommon.CertificateManager
}
var _ p2pcommon.MessageHandler = (*issueCertResponseHandler)(nil)
// newAddressesReqHandler creates handler for PingRequest
func NewIssueCertReqHandler(pm p2pcommon.PeerManager, cm p2pcommon.CertificateManager, peer p2pcommon.RemotePeer, logger *log.Logger, actor p2pcommon.ActorService) *issueCertRequestHandler {
ph := &issueCertRequestHandler{BaseMsgHandler{protocol: p2pcommon.IssueCertificateRequest, pm: pm, peer: peer, actor: actor, logger: logger}, cm} //TODO fill CertificateManager
return ph
}
func (h *issueCertRequestHandler) ParsePayload(rawbytes []byte) (p2pcommon.MessageBody, error) {
return p2putil.UnmarshalAndReturn(rawbytes, &types.IssueCertificateRequest{})
}
func (h *issueCertRequestHandler) Handle(msg p2pcommon.Message, msgBody p2pcommon.MessageBody) {
remotePeer := h.peer
// data := msgBody.(*types.IssueCertificateRequest)
p2putil.DebugLogReceive(h.logger, h.protocol, msg.ID().String(), remotePeer, nil)
resp := &types.IssueCertificateResponse{}
cert, err := h.cm.CreateCertificate(remotePeer.Meta())
if err != nil {
if err == p2pcommon.ErrInvalidRole {
resp.Status = types.ResultStatus_PERMISSION_DENIED
} else {
resp.Status = types.ResultStatus_UNAVAILABLE
}
} else {
pcert, err := p2putil.ConvertCertToProto(cert)
if err != nil {
resp.Status = types.ResultStatus_INTERNAL
} else {
resp.Status = types.ResultStatus_OK
resp.Certificate = pcert
}
}
remotePeer.SendMessage(remotePeer.MF().NewMsgResponseOrder(msg.ID(), p2pcommon.IssueCertificateResponse, resp))
}
// newAddressesRespHandler creates handler for PingRequest
func NewIssueCertRespHandler(pm p2pcommon.PeerManager, cm p2pcommon.CertificateManager, peer p2pcommon.RemotePeer, logger *log.Logger, actor p2pcommon.ActorService) *issueCertResponseHandler {
ph := &issueCertResponseHandler{BaseMsgHandler{protocol: p2pcommon.IssueCertificateResponse, pm: pm, peer: peer, actor: actor, logger: logger}, cm}
return ph
}
func (h *issueCertResponseHandler) ParsePayload(rawbytes []byte) (p2pcommon.MessageBody, error) {
return p2putil.UnmarshalAndReturn(rawbytes, &types.IssueCertificateResponse{})
}
func (h *issueCertResponseHandler) Handle(msg p2pcommon.Message, msgBody p2pcommon.MessageBody) {
remotePeer := h.peer
data := msgBody.(*types.IssueCertificateResponse)
p2putil.DebugLogReceiveResponse(h.logger, h.protocol, msg.ID().String(), msg.OriginalID().String(), remotePeer, data)
remotePeer.ConsumeRequest(msg.OriginalID())
if data.Status == types.ResultStatus_OK {
cert, err := p2putil.CheckAndGetV1(data.Certificate)
if err == nil {
h.cm.AddCertificate(cert)
} else {
h.logger.Info().Err(err).Msg("Failed to convert certificate")
}
}
}
type certRenewedNoticeHandler struct {
BaseMsgHandler
cm p2pcommon.CertificateManager
}
// newAddressesRespHandler creates handler for PingRequest
func NewCertRenewedNoticeHandler(pm p2pcommon.PeerManager, cm p2pcommon.CertificateManager, peer p2pcommon.RemotePeer, logger *log.Logger, actor p2pcommon.ActorService) *certRenewedNoticeHandler {
ph := &certRenewedNoticeHandler{BaseMsgHandler{protocol: p2pcommon.CertificateRenewedNotice, pm: pm, peer: peer, actor: actor, logger: logger}, cm}
return ph
}
func (h *certRenewedNoticeHandler) ParsePayload(rawbytes []byte) (p2pcommon.MessageBody, error) {
return p2putil.UnmarshalAndReturn(rawbytes, &types.CertificateRenewedNotice{})
}
func (h *certRenewedNoticeHandler) Handle(msg p2pcommon.Message, msgBody p2pcommon.MessageBody) {
p := h.peer
data := msgBody.(*types.CertificateRenewedNotice)
p2putil.DebugLogReceive(h.logger, h.protocol, msg.ID().String(), p, data)
// TODO check authorization (i.e. if remotePeer is agent )
if p.Meta().Role != types.PeerRole_Agent {
h.logger.Debug().Str("role", p.AcceptedRole().String()).Str(p2putil.LogPeerName, p.Name()).Msg("invalid peer status. peer is not agent")
return
}
// verify certificate
cert, err := p2putil.CheckAndGetV1(data.Certificate)
if err != nil {
h.logger.Debug().Str(p2putil.LogPeerName, p.Name()).Err(err).Msg("cert verification failed")
return
}
// check contents of certificates
if !p2putil.ContainsID(p.Meta().ProducerIDs, cert.BPID) {
// TODO add penalty
// this agent is not in charge of that bp id.
h.logger.Info().Str(p2putil.LogPeerName, p.Name()).Stringer("bpID", types.LogPeerShort(cert.BPID)).Msg("drop renewed certificate, since issuer is not managed producer of remote peer")
return
}
if !types.IsSamePeerID(p.ID(), cert.AgentID) {
// TODO add penalty
// this certificate is not my certificate
h.logger.Info().Str(p2putil.LogPeerName, p.Name()).Stringer("bpID", types.LogPeerShort(cert.BPID)).Stringer("agentID", types.LogPeerShort(cert.AgentID)).Msg("drop renewed certificate, since agent id is not the remote peer")
return
}
p.AddCertificate(cert)
}