From 2abf2c5695a7793be9e46a29a7549614a9417877 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 12 Aug 2020 21:28:06 -0700 Subject: [PATCH] More certificate stuff... --- core/Node.cpp | 22 ++++++++++++++++++++++ core/Node.hpp | 4 ++++ core/Topology.cpp | 29 +++++++++++++++++++++++++++-- core/Topology.hpp | 24 ++++++++++++++++++++---- core/zerotier.h | 1 + pkg/zerotier/node.go | 10 +++++++++- 6 files changed, 83 insertions(+), 7 deletions(-) diff --git a/core/Node.cpp b/core/Node.cpp index a8d258a51..24fbf0d0f 100644 --- a/core/Node.cpp +++ b/core/Node.cpp @@ -586,6 +586,16 @@ ZT_CertificateError Node::addCertificate( return RR->topology->addCertificate(tptr, c, now, localTrust, true, true, true); } +ZT_ResultCode Node::deleteCertificate( + void *tptr, + const void *serialNo) +{ + if (!serialNo) + return ZT_RESULT_ERROR_BAD_PARAMETER; + RR->topology->deleteCertificate(tptr, reinterpret_cast(serialNo)); + return ZT_RESULT_OK; +} + struct p_certificateListInternal { Vector< SharedPtr< const Certificate > > c; @@ -1106,6 +1116,18 @@ enum ZT_CertificateError ZT_Node_addCertificate( } } +ZT_SDK_API enum ZT_ResultCode ZT_Node_deleteCertificate( + ZT_Node *node, + void *tptr, + const void *serialNo) +{ + try { + return reinterpret_cast(node)->deleteCertificate(tptr, serialNo); + } catch (...) { + return ZT_RESULT_ERROR_INTERNAL; + } +} + ZT_SDK_API ZT_CertificateList *ZT_Node_listCertificates(ZT_Node *node) { try { diff --git a/core/Node.hpp b/core/Node.hpp index a5f4ec150..2fd0f344b 100644 --- a/core/Node.hpp +++ b/core/Node.hpp @@ -147,6 +147,10 @@ public: const void *certData, unsigned int certSize); + ZT_ResultCode deleteCertificate( + void *tptr, + const void *serialNo); + ZT_CertificateList *listCertificates(); int sendUserMessage( diff --git a/core/Topology.cpp b/core/Topology.cpp index c64331c7e..9515a83b9 100644 --- a/core/Topology.cpp +++ b/core/Topology.cpp @@ -242,6 +242,32 @@ ZT_CertificateError Topology::addCertificate(void *tPtr, const Certificate &cert return ZT_CERTIFICATE_ERROR_NONE; } +unsigned int Topology::deleteCertificate(void *tPtr,const uint8_t serialNo[ZT_SHA384_DIGEST_SIZE]) +{ + Mutex::Lock l(m_certs_l); + const unsigned long origCertCount = (unsigned long)m_certs.size(); + Map< SHA384Hash, p_CertEntry >::const_iterator c(m_certs.find(SHA384Hash(serialNo))); + if (c != m_certs.end()) { + if ((c->second.certificate->subject.uniqueId) && (c->second.certificate->subject.uniqueIdSize > 0)) { + SHA384Hash uniqueIdHash; + SHA384(uniqueIdHash.data, c->second.certificate->subject.uniqueId, c->second.certificate->subject.uniqueIdSize); + m_eraseCertificate(tPtr, c->second.certificate, &uniqueIdHash); + } else { + m_eraseCertificate(tPtr, c->second.certificate, nullptr); + } + + const int64_t now = RR->node->now(); + m_cleanCertificates(tPtr, now); + m_writeTrustStore(tPtr); + { + RWMutex::Lock l3(m_peers_l); + RWMutex::Lock l2(m_roots_l); + m_updateRootPeers(tPtr, now); + } + } + return (unsigned int)(origCertCount - (unsigned long)m_certs.size()); +} + void Topology::allCerts(Vector< SharedPtr > &c,Vector< unsigned int > &t) const noexcept { Mutex::Lock l(m_certs_l); @@ -296,8 +322,7 @@ void Topology::m_eraseCertificate(void *tPtr, const SharedPtr< const Certificate for (unsigned int i = 0; i < cert->subject.identityCount; ++i) { const Identity *const ii = reinterpret_cast(cert->subject.identities[i].identity); - Map< Fingerprint, Map< SharedPtr< const Certificate >, unsigned int > >::iterator - bySubjectIdentity(m_certsBySubjectIdentity.find(ii->fingerprint())); + Map< Fingerprint, Map< SharedPtr< const Certificate >, unsigned int > >::iterator bySubjectIdentity(m_certsBySubjectIdentity.find(ii->fingerprint())); if (bySubjectIdentity != m_certsBySubjectIdentity.end()) { bySubjectIdentity->second.erase(cert); if (bySubjectIdentity->second.empty()) diff --git a/core/Topology.hpp b/core/Topology.hpp index 1a0685a95..7de6e13ab 100644 --- a/core/Topology.hpp +++ b/core/Topology.hpp @@ -140,7 +140,23 @@ public: * @param verify If true, verify certificate and certificate chain (default: true) * @return Error or 0 on success */ - ZT_CertificateError addCertificate(void *tPtr, const Certificate &cert, const int64_t now, unsigned int localTrust, bool writeToLocalStore, bool refreshRootSets = true, bool verify = true); + ZT_CertificateError addCertificate( + void *tPtr, + const Certificate &cert, + int64_t now, + unsigned int localTrust, + bool writeToLocalStore, + bool refreshRootSets = true, + bool verify = true); + + /** + * Delete certificate + * + * @param tPtr Thread pointer + * @param serialNo Serial number to delete + * @return Number of deleted certificates + */ + unsigned int deleteCertificate(void *tPtr,const uint8_t serialNo[ZT_SHA384_DIGEST_SIZE]); /** * Fill vectors with all certificates and their corresponding local trust flags @@ -154,11 +170,11 @@ private: void m_rankRoots(int64_t now); void m_eraseCertificate(void *tPtr, const SharedPtr< const Certificate > &cert, const SHA384Hash *uniqueIdHash); bool m_cleanCertificates(void *tPtr, int64_t now); - bool m_verifyCertificateChain(const Certificate *current, const int64_t now) const; - ZT_CertificateError m_verifyCertificate(const Certificate &cert, const int64_t now, unsigned int localTrust, bool skipSignatureCheck) const; + bool m_verifyCertificateChain(const Certificate *current, int64_t now) const; + ZT_CertificateError m_verifyCertificate(const Certificate &cert, int64_t now, unsigned int localTrust, bool skipSignatureCheck) const; void m_loadCached(void *tPtr, const Address &zta, SharedPtr< Peer > &peer); SharedPtr< Peer > m_peerFromCached(void *tPtr, const Address &zta); - SharedPtr< Path > m_newPath(const int64_t l, const InetAddress &r, const UniqueID &k); + SharedPtr< Path > m_newPath(int64_t l, const InetAddress &r, const UniqueID &k); void m_updateRootPeers(void *tPtr, int64_t now); void m_writeTrustStore(void *tPtr); diff --git a/core/zerotier.h b/core/zerotier.h index 3b64d7ba6..a9c0e0344 100644 --- a/core/zerotier.h +++ b/core/zerotier.h @@ -2407,6 +2407,7 @@ ZT_SDK_API int ZT_Node_tryPeer( * * @param node Node instance * @param tptr Thread pointer to pass to functions/callbacks resulting from this call + * @param now Current time * @param localTrust Local trust flags (ORed together) * @param cert Certificate object, or set to NULL if certData and certSize are to be used * @param certData Certificate binary data if 'cert' is NULL, NULL otherwise diff --git a/pkg/zerotier/node.go b/pkg/zerotier/node.go index 1b4f71cff..3ddccf77c 100644 --- a/pkg/zerotier/node.go +++ b/pkg/zerotier/node.go @@ -535,11 +535,19 @@ func (n *Node) ListCertificates() (certs []LocalCertificate, err error) { } // AddCertificate adds a certificate to this node's local certificate store (after verification). -func (n *Node) AddCertificate(cert *Certificate) error { +func (n *Node) AddCertificate(cert *Certificate, localTrust uint) error { + ccert := cert.cCertificate() + defer deleteCCertificate(ccert) + return certificateErrorToError(int(C.ZT_Node_addCertificate(n.zn, nil, C.int64_t(TimeMs()), C.uint(localTrust), (*C.ZT_Certificate)(ccert), nil, 0))) } // DeleteCertificate deletes a certificate from this node's local certificate store. func (n *Node) DeleteCertificate(serialNo []byte) error { + if len(serialNo) != CertificateSerialNoSize { + return ErrInvalidParameter + } + C.ZT_Node_deleteCertificate(n.zn, nil, unsafe.Pointer(&serialNo[0])) + return nil } // -------------------------------------------------------------------------------------------------------------------