aergoio/aergo

View on GitHub
p2p/subproto/cert.go

Summary

Maintainability
A
2 hrs
Test Coverage
F
34%
/**
 *  @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)
}