From 7fa7f6f07ac6db5baea639165c9a56d9883c7365 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 14 Dec 2020 16:54:43 -0500 Subject: [PATCH] Getting more rustic... --- core/CAPI.cpp | 21 ++++++++++ core/zerotier.h | 21 ++++++++++ rust-zerotier-core/src/bindings/mod.rs | 2 +- rust-zerotier-core/src/endpoint.rs | 40 +++++++++++++++++++ rust-zerotier-core/src/fingerprint.rs | 32 +++++++++++---- rust-zerotier-core/src/identity.rs | 54 +++++++++++++++++++++++--- rust-zerotier-core/src/inetaddress.rs | 0 rust-zerotier-core/src/lib.rs | 5 ++- 8 files changed, 159 insertions(+), 16 deletions(-) create mode 100644 rust-zerotier-core/src/endpoint.rs create mode 100644 rust-zerotier-core/src/inetaddress.rs diff --git a/core/CAPI.cpp b/core/CAPI.cpp index dd3a16d0f..de5e8b492 100644 --- a/core/CAPI.cpp +++ b/core/CAPI.cpp @@ -722,4 +722,25 @@ int ZT_Endpoint_fromString( /********************************************************************************************************************/ +char *ZT_Fingerprint_toString(const ZT_Fingerprint *fp, char *buf, int capacity) +{ + if (capacity < ZT_FINGERPRINT_STRING_SIZE_MAX) + return nullptr; + return reinterpret_cast(fp)->toString(buf); +} + +int ZT_Fingerprint_fromString(ZT_Fingerprint *fp, const char *s) +{ + if ((!fp)||(!s)) + return 0; + ZeroTier::Fingerprint f; + if (f.fromString(s)) { + *fp = f; + return 1; + } + return 0; +} + +/********************************************************************************************************************/ + } // extern "C" diff --git a/core/zerotier.h b/core/zerotier.h index 9030f2906..5a9b9175d 100644 --- a/core/zerotier.h +++ b/core/zerotier.h @@ -2856,6 +2856,27 @@ ZT_SDK_API void ZT_Certificate_delete(const ZT_Certificate *cert); /* ---------------------------------------------------------------------------------------------------------------- */ +/** + * Convert a Fingerprint to canonical string form + * + * @param fp Fingerprint to convert + * @param buf Buffer to contain string + * @param capacity Capacity, must be at least 128 bytes + * @return Pointer to 'buf' now filled with a string + */ +ZT_SDK_API char *ZT_Fingerprint_toString(const ZT_Fingerprint *fp, char *buf, int capacity); + +/** + * Decode a fingerprint from a string + * + * @param fp Buffer to fill with decoded fingerprint + * @param s String representation of fingerprint + * @return Non-zero on success + */ +ZT_SDK_API int ZT_Fingerprint_fromString(ZT_Fingerprint *fp, const char *s); + +/* ---------------------------------------------------------------------------------------------------------------- */ + #ifdef __cplusplus } #endif diff --git a/rust-zerotier-core/src/bindings/mod.rs b/rust-zerotier-core/src/bindings/mod.rs index 9f3c93bbc..0d3b33419 100644 --- a/rust-zerotier-core/src/bindings/mod.rs +++ b/rust-zerotier-core/src/bindings/mod.rs @@ -1,2 +1,2 @@ -#[allow(non_snake_case,non_upper_case_globals,non_camel_case_types,dead_code)] +#[allow(non_snake_case,non_upper_case_globals,non_camel_case_types,dead_code,improper_ctypes)] pub mod capi; diff --git a/rust-zerotier-core/src/endpoint.rs b/rust-zerotier-core/src/endpoint.rs new file mode 100644 index 000000000..1d8f62f3f --- /dev/null +++ b/rust-zerotier-core/src/endpoint.rs @@ -0,0 +1,40 @@ +use crate::*; +use crate::bindings::capi as ztcore; +use num_traits::FromPrimitive; +use std::os::raw::c_char; +use std::ffi::CStr; +use std::mem::MaybeUninit; + +pub struct Endpoint { + pub ep_type: EndpointType, + intl: ztcore::ZT_Endpoint +} + +impl Endpoint { + pub fn new_from_string(s: &str) -> Result { + unsafe { + let mut cep: MaybeUninit = MaybeUninit::uninit(); + let ec = ztcore::ZT_Endpoint_fromString(cep.as_mut_ptr(), s.as_ptr() as *const c_char) as i32; + if ec == 0 { + let epi = cep.assume_init(); + return Ok(Endpoint{ + ep_type: EndpointType::from_u32(epi.type_ as u32).unwrap(), + intl: epi + }); + } + return Err(ResultCode::from_i32(ec).unwrap()); + } + } +} + +impl ToString for Endpoint { + fn to_string(&self) -> String { + let mut buf: [u8; 256] = [0; 256]; + unsafe { + if ztcore::ZT_Endpoint_toString(&(self.intl) as *const ztcore::ZT_Endpoint,buf.as_mut_ptr() as *mut c_char, 1024).is_null() { + return String::from("(invalid)"); + } + return String::from(CStr::from_bytes_with_nul(&buf).unwrap().to_str().unwrap()); + } + } +} diff --git a/rust-zerotier-core/src/fingerprint.rs b/rust-zerotier-core/src/fingerprint.rs index 92de18986..7f5a82905 100644 --- a/rust-zerotier-core/src/fingerprint.rs +++ b/rust-zerotier-core/src/fingerprint.rs @@ -1,5 +1,8 @@ use crate::*; use crate::bindings::capi as ztcore; +use std::os::raw::{c_char, c_int}; +use std::ffi::CStr; +use std::mem::MaybeUninit; pub struct Fingerprint { pub address: Address, @@ -7,19 +10,32 @@ pub struct Fingerprint { } impl Fingerprint { - fn new_from_capi_fingerprint(cfp: *const ztcore::ZT_Fingerprint) -> Fingerprint { + pub fn new_from_string(s: &str) -> Result { unsafe { - return Fingerprint { - address: Address((*cfp).address), - hash: (*cfp).hash + let mut cfp: MaybeUninit = MaybeUninit::uninit(); + if ztcore::ZT_Fingerprint_fromString(cfp.as_mut_ptr(), s.as_ptr() as *const c_char) != 0 { + let fp = cfp.assume_init(); + return Ok(Fingerprint{ + address: Address(fp.address), + hash: fp.hash + }); } } + return Err(ResultCode::ErrorBadParameter); } +} - fn to_capi_fingerprint(&self) -> ztcore::ZT_Fingerprint { - ztcore::ZT_Fingerprint { - address: self.address.to_u64(), - hash: self.hash +impl ToString for Fingerprint { + fn to_string(&self) -> String { + let mut buf: [u8; 256] = [0; 256]; + unsafe { + if ztcore::ZT_Fingerprint_toString(&ztcore::ZT_Fingerprint { + address: self.address.to_u64(), + hash: self.hash + }, buf.as_mut_ptr() as *mut c_char, buf.len() as c_int).is_null() { + return String::from("(invalid)"); + } + return String::from(CStr::from_bytes_with_nul(&buf).unwrap().to_str().unwrap()); } } } diff --git a/rust-zerotier-core/src/identity.rs b/rust-zerotier-core/src/identity.rs index 51efa98be..252a281df 100644 --- a/rust-zerotier-core/src/identity.rs +++ b/rust-zerotier-core/src/identity.rs @@ -1,11 +1,11 @@ use crate::*; use crate::bindings::capi as ztcore; use std::os::raw::*; -use num_traits::ToPrimitive; use std::ffi::CStr; +use num_traits::ToPrimitive; pub struct Identity { - pub identity_type: IdentityType, + pub id_type: IdentityType, pub address: Address, capi: *mut ztcore::ZT_Identity, } @@ -19,7 +19,7 @@ impl Identity { } let a = ztcore::ZT_Identity_address(id); return Ok(Identity { - identity_type: id_type, + id_type: id_type, address: Address(a as u64), capi: id, }); @@ -35,7 +35,7 @@ impl Identity { let idt = ztcore::ZT_Identity_type(id); let a = ztcore::ZT_Identity_address(id); return Ok(Identity { - identity_type: num_traits::FromPrimitive::from_u32(idt).unwrap(), + id_type: num_traits::FromPrimitive::from_u32(idt).unwrap(), address: Address(a as u64), capi: id }); @@ -43,9 +43,9 @@ impl Identity { } pub fn to_string(&self, include_private: bool) -> String { - let mut buf: [u8; 1024] = [0; 1024]; + let mut buf: [u8; 2048] = [0; 2048]; unsafe { - if ztcore::ZT_Identity_toString(self.capi, buf.as_mut_ptr() as *mut c_char, 1024, if include_private { 1 } else { 0 }).is_null() { + if ztcore::ZT_Identity_toString(self.capi, buf.as_mut_ptr() as *mut c_char, buf.len() as c_int, if include_private { 1 } else { 0 }).is_null() { return String::from("(invalid)"); } return String::from(CStr::from_bytes_with_nul(&buf).unwrap().to_str().unwrap()); @@ -69,6 +69,48 @@ impl Identity { } false } + + pub fn fingerprint(&self) -> Fingerprint { + unsafe { + let cfp = ztcore::ZT_Identity_fingerprint(self.capi); + return Fingerprint { + address: Address((*cfp).address), + hash: (*cfp).hash + } + } + } + + pub fn sign(&self, data: &[u8]) -> Result, ResultCode> { + unsafe { + let mut sig: Vec = vec!(0; 128); + let siglen = ztcore::ZT_Identity_sign(self.capi, data.as_ptr() as *const c_void, data.len() as c_uint, sig.as_mut_ptr() as *mut c_void, sig.len() as u32); + if siglen > 0 { + sig.resize(siglen as usize, 0); + return Ok(sig.into_boxed_slice()); + } + return Err(ResultCode::ErrorBadParameter); + } + } + + pub fn verify(&self, data: &[u8], signature: &[u8]) -> bool { + if signature.len() == 0 { + return false; + } + unsafe { + if ztcore::ZT_Identity_verify(self.capi, data.as_ptr() as *const c_void, data.len() as c_uint, signature.as_ptr() as *const c_void, signature.len() as c_uint) != 0 { + return true; + } + } + false + } +} + +impl Drop for Identity { + fn drop(&mut self) { + unsafe { + ztcore::ZT_Identity_delete(self.capi); + } + } } impl ToString for Identity { diff --git a/rust-zerotier-core/src/inetaddress.rs b/rust-zerotier-core/src/inetaddress.rs new file mode 100644 index 000000000..e69de29bb diff --git a/rust-zerotier-core/src/lib.rs b/rust-zerotier-core/src/lib.rs index 044f330cf..7751a5555 100644 --- a/rust-zerotier-core/src/lib.rs +++ b/rust-zerotier-core/src/lib.rs @@ -2,10 +2,13 @@ mod bindings; mod identity; mod address; mod fingerprint; +mod endpoint; +mod inetaddress; pub use identity::Identity; pub use address::Address; pub use fingerprint::Fingerprint; +pub use endpoint::Endpoint; use bindings::capi as ztcore; use num_derive::FromPrimitive; @@ -199,7 +202,7 @@ pub enum VirtualNetworkRuleType { MatchIpv6Destination = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_IPV6_DEST as isize, MatchIpTos = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_IP_TOS as isize, MatchIpProtocol = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_IP_PROTOCOL as isize, - MatchEthertype = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_ETHERTYPE as isize, + MatchEtherType = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_ETHERTYPE as isize, MatchIcmp = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_ICMP as isize, MatchIpSourcePortRange = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE as isize, MatchIpDestinationSourceRange = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE as isize,