From 8c45fbe64c160af5304e484fa8b5b6edd951c27c Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 9 Mar 2021 18:08:31 -0500 Subject: [PATCH] C++ build fixes, fix regression in SharedPtr --- core/Peer.cpp | 4 +- core/SharedPtr.hpp | 12 +- core/Tests.cpp | 6 +- core/VL1.cpp | 2 +- rust-zerotier-core/src/certificate.rs | 128 +++++---------------- rust-zerotier-service/src/cli.rs | 15 ++- rust-zerotier-service/src/commands/cert.rs | 100 ++++++++++++++++ rust-zerotier-service/src/main.rs | 35 ++++-- 8 files changed, 176 insertions(+), 126 deletions(-) diff --git a/core/Peer.cpp b/core/Peer.cpp index 73e8a6685..0fd0735ac 100644 --- a/core/Peer.cpp +++ b/core/Peer.cpp @@ -156,7 +156,7 @@ void Peer::send(void *tPtr, int64_t now, const void *data, unsigned int len) noe if (via) { via->send(RR, tPtr, data, len, now); } else { - const SharedPtr< Peer > root(RR->topology->root(now)); + const SharedPtr< Peer > root(RR->topology->root()); if ((root) && (root.ptr() != this)) { via = root->path(now); if (via) { @@ -397,7 +397,7 @@ void Peer::pulse(void *const tPtr, const int64_t now, const bool isRoot) // Send a HELLO indirectly if we were not able to send one via any direct path. if (needHello) { - const SharedPtr< Peer > root(RR->topology->root(now)); + const SharedPtr< Peer > root(RR->topology->root()); if (root) { const SharedPtr< Path > via(root->path(now)); if (via) { diff --git a/core/SharedPtr.hpp b/core/SharedPtr.hpp index 7a5034592..2e65d5759 100644 --- a/core/SharedPtr.hpp +++ b/core/SharedPtr.hpp @@ -42,7 +42,7 @@ public: ZT_INLINE ~SharedPtr() { if (likely(m_ptr != nullptr)) { - if (unlikely(const_cast *>(&(m_ptr->__refCount))->fetch_sub(1, std::memory_order_relaxed) <= 0)) + if (unlikely(const_cast *>(&(m_ptr->__refCount))->fetch_sub(1, std::memory_order_relaxed) <= 1)) delete m_ptr; } } @@ -52,7 +52,7 @@ public: if (likely(m_ptr != sp.m_ptr)) { T *const p = sp._getAndInc(); if (likely(m_ptr != nullptr)) { - if (unlikely(const_cast *>(&(m_ptr->__refCount))->fetch_sub(1, std::memory_order_relaxed) <= 0)) + if (unlikely(const_cast *>(&(m_ptr->__refCount))->fetch_sub(1, std::memory_order_relaxed) <= 1)) delete m_ptr; } m_ptr = p; @@ -63,7 +63,7 @@ public: ZT_INLINE void set(T *ptr) noexcept { if (likely(m_ptr != nullptr)) { - if (unlikely(const_cast *>(&(m_ptr->__refCount))->fetch_sub(1, std::memory_order_relaxed) <= 0)) + if (unlikely(const_cast *>(&(m_ptr->__refCount))->fetch_sub(1, std::memory_order_relaxed) <= 1)) delete m_ptr; } const_cast *>(&(ptr->__refCount))->fetch_add(1, std::memory_order_relaxed); @@ -93,7 +93,7 @@ public: ZT_INLINE void move(SharedPtr &from) { if (m_ptr != nullptr) { - if (const_cast *>(&(m_ptr->__refCount))->fetch_sub(1, std::memory_order_relaxed) <= 0) + if (const_cast *>(&(m_ptr->__refCount))->fetch_sub(1, std::memory_order_relaxed) <= 1) delete m_ptr; } m_ptr = from.m_ptr; @@ -121,7 +121,7 @@ public: ZT_INLINE void zero() { if (likely(m_ptr != nullptr)) { - if (unlikely(const_cast *>(&(m_ptr->__refCount))->fetch_sub(1, std::memory_order_relaxed) <= 0)) + if (unlikely(const_cast *>(&(m_ptr->__refCount))->fetch_sub(1, std::memory_order_relaxed) <= 1)) delete m_ptr; m_ptr = nullptr; } @@ -188,7 +188,7 @@ public: private: ZT_INLINE T *_getAndInc() const noexcept { - if (likely(m_ptr)) + if (likely(m_ptr != nullptr)) const_cast *>(&(m_ptr->__refCount))->fetch_add(1, std::memory_order_relaxed); return m_ptr; } diff --git a/core/Tests.cpp b/core/Tests.cpp index a0fd4b250..3401be60c 100644 --- a/core/Tests.cpp +++ b/core/Tests.cpp @@ -649,18 +649,18 @@ extern "C" const char *ZTT_general() bufs.push_back(SharedPtr< Buf >(new Buf())); cnt += ZT_BUF_MAX_POOL_SIZE + 100; if (Buf::poolAllocated() != cnt) { - ZT_T_PRINTF("FAILED" ZT_EOL_S); + ZT_T_PRINTF("FAILED (1)" ZT_EOL_S); return "Buf memory pool test failed"; } bufs.clear(); if (Buf::poolAllocated() != ZT_BUF_MAX_POOL_SIZE) { - ZT_T_PRINTF("FAILED" ZT_EOL_S); + ZT_T_PRINTF("FAILED (2)" ZT_EOL_S); return "Buf memory pool test failed"; } Buf::freePool(); cnt -= ZT_BUF_MAX_POOL_SIZE + 100; if (Buf::poolAllocated() != cnt) { - ZT_T_PRINTF("FAILED" ZT_EOL_S); + ZT_T_PRINTF("FAILED (3)" ZT_EOL_S); return "Buf memory pool test failed"; } } catch (...) { diff --git a/core/VL1.cpp b/core/VL1.cpp index 9655eed41..3ca6a3647 100644 --- a/core/VL1.cpp +++ b/core/VL1.cpp @@ -437,7 +437,7 @@ void VL1::m_relay(void *tPtr, const SharedPtr< Path > &path, Address destination void VL1::m_sendPendingWhois(void *tPtr, int64_t now) { - const SharedPtr< Peer > root(RR->topology->root(now)); + const SharedPtr< Peer > root(RR->topology->root()); if (unlikely(!root)) return; const SharedPtr< Path > rootPath(root->path(now)); diff --git a/rust-zerotier-core/src/certificate.rs b/rust-zerotier-core/src/certificate.rs index 146841544..17c80c643 100644 --- a/rust-zerotier-core/src/certificate.rs +++ b/rust-zerotier-core/src/certificate.rs @@ -41,86 +41,41 @@ pub const CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE: u32 = ztcore::ZT_C ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#[derive(PartialEq, Eq)] +#[derive(PartialEq, Eq, PartialOrd, Ord)] pub struct CertificateSerialNo(pub [u8; 48]); impl CertificateSerialNo { - /// Create a new empty (all zero) serial number. #[inline(always)] - pub fn new() -> CertificateSerialNo { - CertificateSerialNo([0; 48]) - } - - pub fn new_from_string(s: &str) -> Result { - let b = hex::decode(s); - if b.is_err() { - return Err(ResultCode::ErrorBadParameter); - } - return Ok(CertificateSerialNo::from(b.unwrap().as_slice())); - } + pub fn new() -> CertificateSerialNo { CertificateSerialNo([0; 48]) } + pub fn new_from_string(s: &str) -> Result { hex::decode(s).map_or_else(|_| { Err(ResultCode::ErrorBadParameter) }, |b| { Ok(CertificateSerialNo::from(b.unwrap().as_slice())) }) } } impl From<&[u8; 48]> for CertificateSerialNo { #[inline(always)] - fn from(a: &[u8; 48]) -> CertificateSerialNo { - CertificateSerialNo(*a) - } -} - -impl From<&[u8]> for CertificateSerialNo { - fn from(v: &[u8]) -> CertificateSerialNo { - let mut l = v.len(); - if l > 48 { - l = 48; - } - let mut s = CertificateSerialNo::new(); - s.0[0..l].copy_from_slice(&v[0..l]); - s - } + fn from(a: &[u8; 48]) -> CertificateSerialNo { CertificateSerialNo(*a) } } impl Hash for CertificateSerialNo { #[inline(always)] - fn hash(&self, state: &mut H) { - self.0.hash(state); - } + fn hash(&self, state: &mut H) { self.0.hash(state); } } impl ToString for CertificateSerialNo { #[inline(always)] - fn to_string(&self) -> String { - hex::encode(self.0) - } + fn to_string(&self) -> String { hex::encode(self.0) } } impl serde::Serialize for CertificateSerialNo { - fn serialize(&self, serializer: S) -> Result where S: serde::Serializer { - serializer.serialize_str(self.to_string().as_str()) - } + fn serialize(&self, serializer: S) -> Result where S: serde::Serializer { serializer.serialize_str(self.to_string().as_str()) } } - struct CertificateSerialNoVisitor; - impl<'de> serde::de::Visitor<'de> for CertificateSerialNoVisitor { type Value = CertificateSerialNo; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("CertificateSerialNoVisitor value in string form") - } - - fn visit_str(self, s: &str) -> Result where E: serde::de::Error { - let id = CertificateSerialNo::new_from_string(s); - if id.is_err() { - return Err(serde::de::Error::invalid_value(serde::de::Unexpected::Str(s), &self)); - } - return Ok(id.ok().unwrap() as Self::Value); - } + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { formatter.write_str("object") } + fn visit_str(self, s: &str) -> Result where E: serde::de::Error { Self::Value::new_from_string(s).map_or_else(|_| { Err(serde::de::Error::invalid_value(serde::de::Unexpected::Str(s), &self)) },|id| { Ok(id as Self::Value) }) } } - impl<'de> serde::Deserialize<'de> for CertificateSerialNo { - fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de> { - deserializer.deserialize_str(CertificateSerialNoVisitor) - } + fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de> { deserializer.deserialize_str(CertificateSerialNoVisitor) } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -149,33 +104,16 @@ impl ToString for CertificateUniqueIdType { } impl serde::Serialize for CertificateUniqueIdType { - fn serialize(&self, serializer: S) -> Result where S: serde::Serializer { - serializer.serialize_str(self.to_string().as_str()) - } + fn serialize(&self, serializer: S) -> Result where S: serde::Serializer { serializer.serialize_str(self.to_string().as_str()) } } - struct CertificateUniqueIdTypeVisitor; - impl<'de> serde::de::Visitor<'de> for CertificateUniqueIdTypeVisitor { type Value = CertificateUniqueIdType; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("CertificateUniqueIdType value in string form") - } - - fn visit_str(self, s: &str) -> Result where E: serde::de::Error { - let id = CertificateUniqueIdType::new_from_string(s); - if id.is_err() { - return Err(serde::de::Error::invalid_value(serde::de::Unexpected::Str(s), &self)); - } - return Ok(id.ok().unwrap() as Self::Value); - } + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { formatter.write_str("object") } + fn visit_str(self, s: &str) -> Result where E: serde::de::Error { Self::Value::new_from_string(s).map_or_else(|_| { Err(serde::de::Error::invalid_value(serde::de::Unexpected::Str(s), &self)) },|id| { Ok(id as Self::Value) }) } } - impl<'de> serde::Deserialize<'de> for CertificateUniqueIdType { - fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de> { - deserializer.deserialize_str(CertificateUniqueIdTypeVisitor) - } + fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de> { deserializer.deserialize_str(CertificateUniqueIdTypeVisitor) } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -210,9 +148,10 @@ impl CertificateSubjectUniqueIdSecret { } } +implement_to_from_json!(CertificateSubjectUniqueIdSecret); + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/// Reasons a certificate may be rejected. #[derive(FromPrimitive, ToPrimitive, PartialEq, Eq)] pub enum CertificateError { None = ztcore::ZT_CertificateError_ZT_CERTIFICATE_ERROR_NONE as isize, @@ -246,9 +185,9 @@ impl ToString for CertificateError { } } -impl From<&str> for CertificateError { - fn from(s: &str) -> CertificateError { - match s.to_ascii_lowercase().as_str() { +impl> From for CertificateError { + fn from(s: S) -> CertificateError { + match s.as_ref().to_ascii_lowercase().as_str() { "havenewercert" => CertificateError::HaveNewerCert, "invalidformat" => CertificateError::InvalidFormat, "invalididentity" => CertificateError::InvalidIdentity, @@ -264,29 +203,16 @@ impl From<&str> for CertificateError { } impl serde::Serialize for CertificateError { - fn serialize(&self, serializer: S) -> Result where S: serde::Serializer { - serializer.serialize_str(self.to_string().as_str()) - } + fn serialize(&self, serializer: S) -> Result where S: serde::Serializer { serializer.serialize_str(self.to_string().as_str()) } } - struct CertificateErrorVisitor; - impl<'de> serde::de::Visitor<'de> for CertificateErrorVisitor { type Value = CertificateError; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("CertificateError value in string form") - } - - fn visit_str(self, s: &str) -> Result where E: serde::de::Error { - return Ok(CertificateError::from(s)); - } + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { formatter.write_str("object") } + fn visit_str(self, s: &str) -> Result where E: serde::de::Error { return Ok(CertificateError::from(s)); } } - impl<'de> serde::Deserialize<'de> for CertificateError { - fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de> { - deserializer.deserialize_str(CertificateErrorVisitor) - } + fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de> { deserializer.deserialize_str(CertificateErrorVisitor) } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -379,6 +305,8 @@ impl CertificateName { } } +implement_to_from_json!(CertificateName); + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #[derive(Serialize, Deserialize, PartialEq, Eq)] @@ -409,6 +337,8 @@ impl CertificateNetwork { } } +implement_to_from_json!(CertificateNetwork); + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #[derive(Serialize, Deserialize, PartialEq, Eq)] @@ -436,6 +366,8 @@ impl CertificateIdentity { } } +implement_to_from_json!(CertificateIdentity); + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #[derive(Serialize, Deserialize, PartialEq, Eq)] @@ -614,6 +546,8 @@ impl CertificateSubject { } } +implement_to_from_json!(CertificateSubject); + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #[derive(Serialize, Deserialize, PartialEq, Eq)] diff --git a/rust-zerotier-service/src/cli.rs b/rust-zerotier-service/src/cli.rs index 2198ee448..11b1e5e94 100644 --- a/rust-zerotier-service/src/cli.rs +++ b/rust-zerotier-service/src/cli.rs @@ -93,8 +93,8 @@ Advanced Operations: cert [args] · list List certificates at local node · show Show certificate details - newsid Create a new subject unique ID - newcsr Create a subject CSR + newsid [sid secret out] Create a new subject unique ID + newcsr Create a subject CSR sign Sign a CSR to create a certificate verify Verify certificate (not chain) dump Verify and print certificate @@ -229,15 +229,14 @@ pub(crate) fn parse_cli_args() -> ArgMatches<'static> { .subcommand(App::new("show") .arg(Arg::with_name("serial").index(1).required(true))) .subcommand(App::new("newsid") - .arg(Arg::with_name("path").index(1).required(true))) + .arg(Arg::with_name("path").index(1).required(false))) .subcommand(App::new("newcsr") - .arg(Arg::with_name("subject").index(1).required(true)) - .arg(Arg::with_name("secret").index(2).required(true)) - .arg(Arg::with_name("output").index(3).required(true))) + .arg(Arg::with_name("secret").index(1).required(true)) + .arg(Arg::with_name("output").index(2).required(false))) .subcommand(App::new("sign") .arg(Arg::with_name("csr").index(1).required(true)) .arg(Arg::with_name("identity").index(2).required(true)) - .arg(Arg::with_name("output").index(3).required(true))) + .arg(Arg::with_name("output").index(3).required(false))) .subcommand(App::new("verify") .arg(Arg::with_name("cert").index(1).required(true))) .subcommand(App::new("dump") @@ -248,7 +247,7 @@ pub(crate) fn parse_cli_args() -> ArgMatches<'static> { .subcommand(App::new("restore")) .subcommand(App::new("export") .arg(Arg::with_name("serial").index(1).required(true)) - .arg(Arg::with_name("path").index(2))) + .arg(Arg::with_name("path").index(2).required(false))) .subcommand(App::new("delete") .arg(Arg::with_name("serial").index(1).required(true)))) .help(help.as_str()) diff --git a/rust-zerotier-service/src/commands/cert.rs b/rust-zerotier-service/src/commands/cert.rs index e69de29bb..134cfc844 100644 --- a/rust-zerotier-service/src/commands/cert.rs +++ b/rust-zerotier-service/src/commands/cert.rs @@ -0,0 +1,100 @@ +/* + * Copyright (c)2013-2021 ZeroTier, Inc. + * + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. + * + * Change Date: 2026-01-01 + * + * On the date above, in accordance with the Business Source License, use + * of this software will be governed by version 2.0 of the Apache License. + */ +/****/ + +use clap::ArgMatches; +use crate::store::Store; +use zerotier_core::{CertificateSubjectUniqueIdSecret, CertificateUniqueIdType}; +use std::io::Write; + +#[inline(always)] +fn list(store: &Store, auth_token: &Option) -> i32 { + 0 +} + +#[inline(always)] +fn show<'a>(store: &Store, cli_args: &ArgMatches<'a>, auth_token: &Option) -> i32 { + 0 +} + +#[inline(always)] +fn newsid<'a>(store: &Store, cli_args: Option<&ArgMatches<'a>>, auth_token: &Option) -> i32 { + let sid = CertificateSubjectUniqueIdSecret::new(CertificateUniqueIdType::NistP384); // right now there's only one type + let sid = sid.to_json(); + let path = cli_args.map_or("", |cli_args| { cli_args.value_of("path").unwrap_or("") }); + if path.is_empty() { + let _ = std::io::stdout().write_all(sid.as_bytes()); + 0 + } else { + std::fs::write(path, sid.as_bytes()).map_or_else(|e| { + eprintln!("FATAL: error writing '{}': {}", path, e.to_string()); + e.raw_os_error().unwrap_or(1) + }, || { + 0 + }) + } +} + +#[inline(always)] +fn sign<'a>(store: &Store, cli_args: &ArgMatches<'a>, auth_token: &Option) -> i32 { + 0 +} + +#[inline(always)] +fn verify<'a>(store: &Store, cli_args: &ArgMatches<'a>, auth_token: &Option) -> i32 { + 0 +} + +#[inline(always)] +fn dump<'a>(store: &Store, cli_args: &ArgMatches<'a>, auth_token: &Option) -> i32 { + 0 +} + +#[inline(always)] +fn import<'a>(store: &Store, cli_args: &ArgMatches<'a>, auth_token: &Option) -> i32 { + 0 +} + +#[inline(always)] +fn restore(store: &Store, auth_token: &Option) -> i32 { + 0 +} + +#[inline(always)] +fn export<'a>(store: &Store, cli_args: &ArgMatches<'a>, auth_token: &Option) -> i32 { + 0 +} + +#[inline(always)] +fn delete<'a>(store: &Store, cli_args: &ArgMatches<'a>, auth_token: &Option) -> i32 { + 0 +} + +pub(crate) fn run<'a>(store: &Store, cli_args: &ArgMatches<'a>, auth_token: &Option) -> i32 { + match cli_args.subcommand() { + ("list", None) => list(store, auth_token), + ("show", Some(sub_cli_args)) => show(store, sub_cli_args, auth_token), + ("newsid", sub_cli_args) => newsid(store, sub_cli_args, auth_token), + ("newcsr", Some(sub_cli_args)) => newcsr(store, sub_cli_args, auth_token), + ("sign", Some(sub_cli_args)) => sign(store, sub_cli_args, auth_token), + ("verify", Some(sub_cli_args)) => verify(store, sub_cli_args, auth_token), + ("dump", Some(sub_cli_args)) => dump(store, sub_cli_args, auth_token), + ("import", Some(sub_cli_args)) => import(store, sub_cli_args, auth_token), + ("restore", None) => restore(store, auth_token), + ("export", Some(sub_cli_args)) => export(store, sub_cli_args, auth_token), + ("delete", Some(sub_cli_args)) => delete(store, sub_cli_args, auth_token), + _ => { + crate::cli::print_help(); + 1 + } + } +} diff --git a/rust-zerotier-service/src/main.rs b/rust-zerotier-service/src/main.rs index 28b528d28..03d5fa73d 100644 --- a/rust-zerotier-service/src/main.rs +++ b/rust-zerotier-service/src/main.rs @@ -25,13 +25,14 @@ mod service; mod utils; mod weblistener; -#[allow(non_snake_case,non_upper_case_globals,non_camel_case_types,dead_code,improper_ctypes)] +#[allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, improper_ctypes)] mod osdep; // bindgen generated use std::boxed::Box; use std::sync::Arc; use crate::store::Store; +use clap::ArgMatches; fn main() { let mut process_exit_value: i32 = 0; @@ -85,18 +86,34 @@ fn main() { drop(zerotier_path); - match cli_args.as_ref().subcommand_name().unwrap() { - "version" => { + match cli_args.subcommand() { + ("help", None) => { + cli::print_help() + } + ("version", None) => { let ver = zerotier_core::version(); println!("{}.{}.{}", ver.0, ver.1, ver.2); - }, - - "service" => { + } + ("status", None) => {} + ("set", Some(sub_cli_args)) => {} + ("peer", Some(sub_cli_args)) => {} + ("network", Some(sub_cli_args)) => {} + ("join", Some(sub_cli_args)) => {} + ("leave", Some(sub_cli_args)) => {} + ("service", None) => { drop(cli_args); // free unnecssary memory before launching service process_exit_value = service::run(&store, auth_token); - }, - - _ => cli::print_help(), // includes "help" + } + ("controller", Some(sub_cli_args)) => {} + ("identity", Some(sub_cli_args)) => {} + ("locator", Some(sub_cli_args)) => {} + ("cert", Some(sub_cli_args)) => { + process_exit_value = crate::commands::cert::run(&store, sub_cli_args, &auth_token); + } + _ => { + cli::print_help(); + process_exit_value = 1; + } } store.erase_pid();