Adam Ierymenko 5 лет назад
Родитель
Сommit
becc4aa8ea
7 измененных файлов с 129 добавлено и 5 удалено
  1. 1 1
      cmd/zt_service_tests/zt_service_tests.go
  2. 52 3
      core/Node.cpp
  3. 2 0
      core/Node.hpp
  4. 12 0
      core/Topology.cpp
  5. 8 0
      core/Topology.hpp
  6. 37 1
      core/zerotier.h
  7. 17 0
      pkg/zerotier/node.go

+ 1 - 1
cmd/zt_service_tests/zt_service_tests.go

@@ -8,7 +8,7 @@ import (
 
 func main() {
 	runtime.GOMAXPROCS(1)
-	debug.SetGCPercent(15)
+	debug.SetGCPercent(10)
 
 	if !TestCertificate() {
 		os.Exit(1)

+ 52 - 3
core/Node.cpp

@@ -413,6 +413,7 @@ ZT_PeerList *Node::peers() const
 	Utils::zero(buf, bufSize);
 	ZT_PeerList *pl = reinterpret_cast<ZT_PeerList *>(buf);
 	buf += sizeof(ZT_PeerList);
+	pl->freeFunction = reinterpret_cast<void (*)(const void *)>(free);
 	pl->peers = reinterpret_cast<ZT_Peer *>(buf);
 	buf += sizeof(ZT_Peer) * peers.size();
 	ZT_Path *peerPath = reinterpret_cast<ZT_Path *>(buf);
@@ -496,6 +497,7 @@ ZT_VirtualNetworkList *Node::networks() const
 	if (!buf)
 		return nullptr;
 	ZT_VirtualNetworkList *nl = (ZT_VirtualNetworkList *)buf; // NOLINT(modernize-use-auto,hicpp-use-auto)
+	nl->freeFunction = reinterpret_cast<void (*)(const void *)>(free);
 	nl->networks = (ZT_VirtualNetworkConfig *)(buf + sizeof(ZT_VirtualNetworkList));
 
 	nl->networkCount = 0;
@@ -584,6 +586,39 @@ ZT_CertificateError Node::addCertificate(
 	return RR->topology->addCertificate(tptr, c, now, localTrust, true, true, true);
 }
 
+struct p_certificateListInternal
+{
+	Vector< SharedPtr< const Certificate > > c;
+	Vector< unsigned int > t;
+};
+
+static void p_freeCertificateList(const void *cl)
+{
+	if (cl) {
+		reinterpret_cast<const p_certificateListInternal *>(reinterpret_cast<const uint8_t *>(cl) + sizeof(ZT_CertificateList))->~p_certificateListInternal();
+		free(const_cast<void *>(cl));
+	}
+}
+
+ZT_CertificateList *Node::listCertificates()
+{
+	ZT_CertificateList *const cl = (ZT_CertificateList *)malloc(sizeof(ZT_CertificateList) + sizeof(p_certificateListInternal));
+	if (!cl)
+		return nullptr;
+
+	p_certificateListInternal *const clint = reinterpret_cast<p_certificateListInternal *>(reinterpret_cast<uint8_t *>(cl) + sizeof(ZT_CertificateList));
+	new (clint) p_certificateListInternal;
+	RR->topology->allCerts(clint->c, clint->t);
+
+	cl->freeFunction = p_freeCertificateList;
+	static_assert(sizeof(SharedPtr< const Certificate >) == sizeof(void *), "SharedPtr<> is not just a wrapped pointer");
+	cl->certs = reinterpret_cast<const ZT_Certificate **>(clint->c.data());
+	cl->localTrust = clint->t.data();
+	cl->certCount = (unsigned long)clint->c.size();
+
+	return cl;
+}
+
 int Node::sendUserMessage(
 	void *tptr,
 	uint64_t dest,
@@ -840,10 +875,15 @@ void ZT_freeBuffer(void *b)
 		delete _ZT_PTRTOBUF(b);
 }
 
-void ZT_freeQueryResult(void *qr)
+struct p_queryResultBase
+{
+	void (*freeFunction)(const void *);
+};
+
+void ZT_freeQueryResult(const void *qr)
 {
-	if (qr)
-		free(qr);
+	if ((qr) && (reinterpret_cast<const p_queryResultBase *>(qr)->freeFunction))
+		reinterpret_cast<const p_queryResultBase *>(qr)->freeFunction(qr);
 }
 
 enum ZT_ResultCode ZT_Node_new(ZT_Node **node, void *uptr, void *tptr, const struct ZT_Node_Callbacks *callbacks, int64_t now)
@@ -1066,6 +1106,15 @@ enum ZT_CertificateError ZT_Node_addCertificate(
 	}
 }
 
+ZT_SDK_API ZT_CertificateList *ZT_Node_listCertificates(ZT_Node *node)
+{
+	try {
+		return reinterpret_cast<ZeroTier::Node *>(node)->listCertificates();
+	} catch (...) {
+		return nullptr;
+	}
+}
+
 void ZT_Node_setNetworkUserPtr(ZT_Node *node, uint64_t nwid, void *ptr)
 {
 	try {

+ 2 - 0
core/Node.hpp

@@ -147,6 +147,8 @@ public:
 		const void *certData,
 		unsigned int certSize);
 
+	ZT_CertificateList *listCertificates();
+
 	int sendUserMessage(
 		void *tptr,
 		uint64_t dest,

+ 12 - 0
core/Topology.cpp

@@ -242,6 +242,18 @@ ZT_CertificateError Topology::addCertificate(void *tPtr, const Certificate &cert
 	return ZT_CERTIFICATE_ERROR_NONE;
 }
 
+void Topology::allCerts(Vector< SharedPtr<const Certificate> > &c,Vector< unsigned int > &t) const noexcept
+{
+	Mutex::Lock l(m_certs_l);
+	const unsigned long cs = (unsigned long)m_certs.size();
+	c.reserve(cs);
+	t.reserve(cs);
+	for(Map< SHA384Hash, p_CertEntry >::const_iterator i(m_certs.begin());i!=m_certs.end();++i) {
+		c.push_back(i->second.certificate);
+		t.push_back(i->second.localTrust);
+	}
+}
+
 struct p_RootRankingComparisonOperator
 {
 	ZT_INLINE bool operator()(const SharedPtr< Peer > &a, const SharedPtr< Peer > &b) const noexcept

+ 8 - 0
core/Topology.hpp

@@ -142,6 +142,14 @@ public:
 	 */
 	ZT_CertificateError addCertificate(void *tPtr, const Certificate &cert, const int64_t now, unsigned int localTrust, bool writeToLocalStore, bool refreshRootSets = true, bool verify = true);
 
+	/**
+	 * Fill vectors with all certificates and their corresponding local trust flags
+	 *
+	 * @param c Certificate vector
+	 * @param t Local trust vector
+	 */
+	void allCerts(Vector< SharedPtr<const Certificate> > &c,Vector< unsigned int > &t) const noexcept;
+
 private:
 	void m_rankRoots(int64_t now);
 	void m_eraseCertificate(void *tPtr, const SharedPtr< const Certificate > &cert, const SHA384Hash *uniqueIdHash);

+ 37 - 1
core/zerotier.h

@@ -618,6 +618,32 @@ typedef struct
 	unsigned int signatureSize;
 } ZT_Certificate;
 
+/**
+ * A list of certificates
+ */
+typedef struct
+{
+	/**
+	 * Function that is called to free this list (called by ZT_freeQueryResult)
+	 */
+	void (*freeFunction)(const void *);
+
+	/**
+	 * Array of pointers to certificates
+	 */
+	const ZT_Certificate *const *certs;
+
+	/**
+	 * Array of local trust flags for each certificate
+	 */
+	const unsigned int *localTrust;
+
+	/**
+	 * Number of certificates
+	 */
+	unsigned long certCount;
+} ZT_CertificateList;
+
 /**
  * Credential type IDs
  */
@@ -1429,6 +1455,7 @@ typedef struct
  */
 typedef struct
 {
+	void (*freeFunction)(const void *);
 	ZT_VirtualNetworkConfig *networks;
 	unsigned long networkCount;
 } ZT_VirtualNetworkList;
@@ -1616,6 +1643,7 @@ typedef struct
  */
 typedef struct
 {
+	void (*freeFunction)(const void *);
 	ZT_Peer *peers;
 	unsigned long peerCount;
 } ZT_PeerList;
@@ -2003,7 +2031,7 @@ ZT_SDK_API void ZT_freeBuffer(void *b);
  *
  * @param qr Query result buffer
  */
-ZT_SDK_API void ZT_freeQueryResult(void *qr);
+ZT_SDK_API void ZT_freeQueryResult(const void *qr);
 
 /* ---------------------------------------------------------------------------------------------------------------- */
 
@@ -2392,6 +2420,14 @@ ZT_SDK_API enum ZT_CertificateError ZT_Node_addCertificate(
 	const void *certData,
 	unsigned int certSize);
 
+/**
+ * List certificates installed in this node's trust store
+ *
+ * @param node Node instance
+ * @return List of certificates or NULL on error
+ */
+ZT_SDK_API ZT_CertificateList *ZT_Node_listCertificates(ZT_Node *node);
+
 /**
  * Send a VERB_USER_MESSAGE to another ZeroTier node
  *

+ 17 - 0
pkg/zerotier/node.go

@@ -541,6 +541,23 @@ func (n *Node) TryPeer(fpOrAddress interface{}, ep *Endpoint, retries int) bool
 	return C.ZT_Node_tryPeer(n.zn, nil, fp.cFingerprint(), &ep.cep, C.int(retries)) != 0
 }
 
+// ListCertificates lists certificates and their corresponding local trust flags.
+func (n *Node) ListCertificates() (certs []*Certificate, localTrust []uint, err error) {
+	cl := C.ZT_Node_listCertificates(n.zn)
+	if cl != nil {
+		for i := uintptr(0); i < uintptr(cl.certCount); i++ {
+			c := newCertificateFromCCertificate(unsafe.Pointer(uintptr(unsafe.Pointer(cl.certs)) + (i * pointerSize)))
+			if c != nil {
+				lt := *((*C.uint)(unsafe.Pointer(uintptr(unsafe.Pointer(cl.localTrust)) + (i * C.sizeof_int))))
+				certs = append(certs, c)
+				localTrust = append(localTrust, uint(lt))
+			}
+		}
+		C.ZT_freeQueryResult(unsafe.Pointer(cl))
+	}
+	return
+}
+
 // --------------------------------------------------------------------------------------------------------------------
 
 func (n *Node) runMaintenance() {