diff --git a/core/Certificate.cpp b/core/Certificate.cpp index 3e244ba24..c5a4727c7 100644 --- a/core/Certificate.cpp +++ b/core/Certificate.cpp @@ -219,7 +219,6 @@ bool Certificate::setSubjectUniqueId(const uint8_t uniqueId[ZT_CERTIFICATE_UNIQU Vector< uint8_t > Certificate::encode(const bool omitSignature) const { - char tmp[32]; Vector< uint8_t > enc; Dictionary d; @@ -488,13 +487,11 @@ ZT_CertificateError Certificate::verify() const if (this->subject.updateURLCount > 0) { if (!this->subject.updateURLs) - return ZT_CERTIFICATE_ERROR_INVALID_FORMAT; + return ZT_CERTIFICATE_ERROR_MISSING_REQUIRED_FIELDS; for (unsigned int i = 0; i < this->subject.updateURLCount; ++i) { if (!this->subject.updateURLs[i]) return ZT_CERTIFICATE_ERROR_MISSING_REQUIRED_FIELDS; } - } else if (this->subject.updateURLs) { - return ZT_CERTIFICATE_ERROR_INVALID_FORMAT; } } catch (...) {} diff --git a/rust-zerotier-core/src/certificate.rs b/rust-zerotier-core/src/certificate.rs index 2b3265134..a87853d9d 100644 --- a/rust-zerotier-core/src/certificate.rs +++ b/rust-zerotier-core/src/certificate.rs @@ -207,7 +207,7 @@ impl CertificateSubjectUniqueIdSecret { CertificateSubjectUniqueIdSecret { public: Vec::from(&unique_id[0..unique_id_size as usize]), private: Vec::from(&unique_id_private[0..unique_id_private_size as usize]), - type_: num_traits::FromPrimitive::from_u32(ct as u32).unwrap(), + type_: num_traits::FromPrimitive::from_i32(ct as i32).unwrap(), } } } @@ -215,7 +215,7 @@ impl CertificateSubjectUniqueIdSecret { ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// Reasons a certificate may be rejected. -#[derive(FromPrimitive, ToPrimitive)] +#[derive(FromPrimitive, ToPrimitive, PartialEq, Eq)] pub enum CertificateError { None = ztcore::ZT_CertificateError_ZT_CERTIFICATE_ERROR_NONE as isize, HaveNewerCert = ztcore::ZT_CertificateError_ZT_CERTIFICATE_ERROR_HAVE_NEWER_CERT as isize, @@ -555,13 +555,16 @@ impl CertificateSubject { } if !self.update_urls.is_empty() { capi_urls.reserve(self.update_urls.len()); + capi_urls_strs.reserve(self.update_urls.len()); for i in self.update_urls.iter() { let cs = CString::new((*i).as_str()); if cs.is_ok() { capi_urls_strs.push(cs.unwrap()); - capi_urls.push(capi_urls_strs.last().unwrap().as_ptr()); } } + for i in capi_urls_strs.iter() { + capi_urls.push((*i).as_ptr()); + } } CertificateSubjectCAPIContainer { @@ -694,7 +697,7 @@ impl Certificate { let capi_verify: c_int = if verify { 1 } else { 0 }; let result = unsafe { ztcore::ZT_Certificate_decode(&mut capi_cert as *mut *const ztcore::ZT_Certificate, b.as_ptr() as *const c_void, b.len() as c_int, capi_verify) }; if result != ztcore::ZT_CertificateError_ZT_CERTIFICATE_ERROR_NONE { - return Err(CertificateError::from_u32(result as u32).unwrap_or(CertificateError::InvalidFormat)); + return Err(CertificateError::from_i32(result as i32).unwrap_or(CertificateError::InvalidFormat)); } if capi_cert.is_null() { return Err(CertificateError::InvalidFormat); @@ -740,7 +743,7 @@ impl Certificate { pub fn verify(&self) -> CertificateError { unsafe { let capi = self.to_capi(); - return CertificateError::from_u32(ztcore::ZT_Certificate_verify(&capi.certificate as *const ztcore::ZT_Certificate) as u32).unwrap_or(CertificateError::InvalidFormat); + return CertificateError::from_i32(ztcore::ZT_Certificate_verify(&capi.certificate as *const ztcore::ZT_Certificate) as i32).unwrap_or(CertificateError::InvalidFormat); } } } @@ -752,6 +755,7 @@ implement_to_from_json!(Certificate); #[cfg(test)] mod tests { use crate::*; + use num_traits::FromPrimitive; #[test] fn certificate_serial_no() { @@ -767,9 +771,16 @@ mod tests { println!("certificate unique ID private: {}", hex::encode(uid.private).as_str()); } + #[test] + fn enum_from_primitive() { + let ce = CertificateError::from_i32(-2 as i32); + assert!(ce.is_some()); + let ce = ce.unwrap(); + assert!(ce == CertificateError::InvalidIdentity); + } + #[test] fn cert_encode_decode() { - let uid = CertificateSubjectUniqueIdSecret::new(CertificateUniqueIdType::NistP384); let id0 = Identity::new_generate(IdentityType::NistP384).ok().unwrap(); let mut cert = Certificate{ @@ -825,5 +836,28 @@ mod tests { assert!(cert2.is_ok()); assert!(cert2.ok().unwrap() == cert); } + + let uid = CertificateSubjectUniqueIdSecret::new(CertificateUniqueIdType::NistP384); + let csr = cert.subject.new_csr(Some(&uid)); + assert!(csr.is_ok()); + let csr = csr.ok().unwrap(); + + let mut csr_decoded = Certificate::new_from_bytes(csr.as_ref(), false); + assert!(csr_decoded.is_ok()); + let mut csr_decoded = csr_decoded.ok().unwrap(); + + let cert_signed = csr_decoded.sign(&id0); + assert!(cert_signed.is_ok()); + let cert_signed = cert_signed.ok().unwrap(); + + let cert_signed_decoded = Certificate::new_from_bytes(cert_signed.as_slice(), false); + assert!(cert_signed_decoded.is_ok()); + let cert_signed_decoded = cert_signed_decoded.ok().unwrap(); + assert!(cert_signed_decoded.signature.len() > 0); + + let cert_signed_verified = cert_signed_decoded.verify(); + println!("{}", cert_signed_decoded.to_json().as_str()); + println!("{}", cert_signed_verified.to_string()); + assert!(cert_signed_verified == CertificateError::None); } } diff --git a/rust-zerotier-core/src/endpoint.rs b/rust-zerotier-core/src/endpoint.rs index 2fafbe141..05073fa80 100644 --- a/rust-zerotier-core/src/endpoint.rs +++ b/rust-zerotier-core/src/endpoint.rs @@ -42,7 +42,7 @@ pub struct Endpoint { impl Endpoint { pub(crate) fn new_from_capi(ep: &ztcore::ZT_Endpoint) -> Endpoint { return Endpoint{ - type_: EndpointType::from_u32(ep.type_ as u32).unwrap(), + type_: EndpointType::from_i32(ep.type_ as i32).unwrap(), capi: *ep }; } @@ -59,7 +59,7 @@ impl Endpoint { if ec == 0 { let epi = cep.assume_init(); return Ok(Endpoint{ - type_: EndpointType::from_u32(epi.type_ as u32).unwrap(), + type_: EndpointType::from_i32(epi.type_ as i32).unwrap(), capi: epi }); } diff --git a/rust-zerotier-core/src/identity.rs b/rust-zerotier-core/src/identity.rs index f246cf871..7c63e927c 100644 --- a/rust-zerotier-core/src/identity.rs +++ b/rust-zerotier-core/src/identity.rs @@ -39,7 +39,7 @@ impl Identity { let idt = ztcore::ZT_Identity_type(id); let a = ztcore::ZT_Identity_address(id); return Identity { - type_: FromPrimitive::from_u32(idt as u32).unwrap(), + type_: FromPrimitive::from_i32(idt as i32).unwrap(), address: Address(a), capi: id, requires_delete: requires_delete, @@ -76,8 +76,8 @@ impl Identity { } fn intl_to_string(&self, include_private: bool) -> String { + let mut buf: MaybeUninit<[c_char; 4096]> = MaybeUninit::uninit(); unsafe { - let mut buf: MaybeUninit<[c_char; 4096]> = MaybeUninit::uninit(); if ztcore::ZT_Identity_toString(self.capi, (*buf.as_mut_ptr()).as_mut_ptr(), 4096, if include_private { 1 } else { 0 }).is_null() { return String::from("(invalid)"); } diff --git a/rust-zerotier-core/src/inetaddress.rs b/rust-zerotier-core/src/inetaddress.rs index bff38b95c..aa70a769a 100644 --- a/rust-zerotier-core/src/inetaddress.rs +++ b/rust-zerotier-core/src/inetaddress.rs @@ -138,7 +138,7 @@ impl InetAddress { /// Get the network scope of the IP in this object. pub fn ip_scope(&self) -> IpScope { unsafe { - IpScope::from_u32(ztcore::ZT_InetAddress_ipScope(self.as_capi_ptr()) as u32).unwrap_or(IpScope::None) + IpScope::from_i32(ztcore::ZT_InetAddress_ipScope(self.as_capi_ptr()) as i32).unwrap_or(IpScope::None) } } @@ -177,6 +177,15 @@ impl From<&str> for InetAddress { } } +impl PartialEq for InetAddress { + #[inline(always)] + fn eq(&self, other: &Self) -> bool { + self.to_string() == other.to_string() + } +} + +impl Eq for InetAddress {} + impl serde::Serialize for InetAddress { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer { serializer.serialize_str(self.to_string().as_str()) diff --git a/rust-zerotier-core/src/node.rs b/rust-zerotier-core/src/node.rs index dbbbc5155..c433750f0 100644 --- a/rust-zerotier-core/src/node.rs +++ b/rust-zerotier-core/src/node.rs @@ -142,7 +142,7 @@ extern "C" fn zt_virtual_network_config_function( op: ztcore::ZT_VirtualNetworkConfigOperation, conf: *const ztcore::ZT_VirtualNetworkConfig, ) { - let op2 = VirtualNetworkConfigOperation::from_u32(op as u32); + let op2 = VirtualNetworkConfigOperation::from_i32(op as i32); if op2.is_some() { let op2 = op2.unwrap(); let n = node_from_raw_ptr!(uptr); @@ -185,7 +185,7 @@ extern "C" fn zt_event_callback( data: *const c_void, data_size: c_uint ) { - let ev2 = Event::from_u32(ev as u32); + let ev2 = Event::from_i32(ev as i32); if ev2.is_some() { let ev2 = ev2.unwrap(); let n = node_from_raw_ptr!(uptr); @@ -208,7 +208,7 @@ extern "C" fn zt_state_put_function( obj_data: *const c_void, obj_data_len: c_int, ) { - let obj_type2 = StateObjectType::from_u32(obj_type as u32); + let obj_type2 = StateObjectType::from_i32(obj_type as i32); if obj_type2.is_some() { let obj_type2 = obj_type2.unwrap(); let n = node_from_raw_ptr!(uptr); @@ -236,7 +236,7 @@ extern "C" fn zt_state_get_function( *obj_data_free_function = transmute(ztcore::free as *const ()); } - let obj_type2 = StateObjectType::from_u32(obj_type as u32); + let obj_type2 = StateObjectType::from_i32(obj_type as i32); if obj_type2.is_some() { let obj_type2 = obj_type2.unwrap(); let n = node_from_raw_ptr!(uptr); @@ -356,7 +356,7 @@ impl Node { let rc = ztcore::ZT_Node_new(&mut capi as *mut *mut ztcore::ZT_Node, transmute(Arc::as_ptr(&n)), null_mut(), &callbacks as *const ztcore::ZT_Node_Callbacks, now); if rc != 0 { - return Err(ResultCode::from_u32(rc as u32).unwrap_or(ResultCode::FatalErrorInternal)); + return Err(ResultCode::from_i32(rc as i32).unwrap_or(ResultCode::FatalErrorInternal)); } else if capi.is_null() { return Err(ResultCode::FatalErrorInternal); } @@ -423,7 +423,7 @@ impl Node { if rc != ztcore::ZT_ResultCode_ZT_RESULT_OK { self.delete_network_uptr(nwid.0); } - return ResultCode::from_u32(rc as u32).unwrap_or(ResultCode::ErrorInternalNonFatal); + return ResultCode::from_i32(rc as i32).unwrap_or(ResultCode::ErrorInternalNonFatal); } fn delete_network_uptr(&self, nwid: u64) { @@ -438,7 +438,7 @@ impl Node { pub fn leave(&self, nwid: NetworkId) -> ResultCode { self.delete_network_uptr(nwid.0); unsafe { - return ResultCode::from_u32(ztcore::ZT_Node_leave(self.capi.get(), nwid.0, null_mut(), null_mut()) as u32).unwrap(); + return ResultCode::from_i32(ztcore::ZT_Node_leave(self.capi.get(), nwid.0, null_mut(), null_mut()) as i32).unwrap_or(ResultCode::ErrorInternalNonFatal); } } @@ -453,7 +453,7 @@ impl Node { pub fn process_wire_packet(&self, local_socket: i64, remote_address: &InetAddress, data: Buffer) -> ResultCode { let current_time = self.now.get(); let mut next_task_deadline: i64 = current_time; - let rc = unsafe { ResultCode::from_u32(ztcore::ZT_Node_processWirePacket(self.capi.get(), null_mut(), current_time, local_socket, remote_address.as_capi_ptr(), data.zt_core_buf as *const c_void, data.data_size as u32, 1, &mut next_task_deadline as *mut i64) as u32).unwrap_or(ResultCode::ErrorInternalNonFatal) }; + let rc = unsafe { ResultCode::from_i32(ztcore::ZT_Node_processWirePacket(self.capi.get(), null_mut(), current_time, local_socket, remote_address.as_capi_ptr(), data.zt_core_buf as *const c_void, data.data_size as u32, 1, &mut next_task_deadline as *mut i64) as i32).unwrap_or(ResultCode::ErrorInternalNonFatal) }; std::mem::forget(data); // prevent Buffer from being returned to ZT core twice, see comment in drop() in buffer.rs rc } @@ -462,20 +462,20 @@ impl Node { pub fn process_virtual_network_frame(&self, nwid: &NetworkId, source_mac: &MAC, dest_mac: &MAC, ethertype: u16, vlan_id: u16, data: Buffer) -> ResultCode { let current_time = self.now.get(); let mut next_tick_deadline: i64 = current_time; - let rc = unsafe { ResultCode::from_u32(ztcore::ZT_Node_processVirtualNetworkFrame(self.capi.get(), null_mut(), current_time, nwid.0, source_mac.0, dest_mac.0, ethertype as c_uint, vlan_id as c_uint, data.zt_core_buf as *const c_void, data.data_size as u32, 1, &mut next_tick_deadline as *mut i64) as u32).unwrap_or(ResultCode::ErrorInternalNonFatal) }; + let rc = unsafe { ResultCode::from_i32(ztcore::ZT_Node_processVirtualNetworkFrame(self.capi.get(), null_mut(), current_time, nwid.0, source_mac.0, dest_mac.0, ethertype as c_uint, vlan_id as c_uint, data.zt_core_buf as *const c_void, data.data_size as u32, 1, &mut next_tick_deadline as *mut i64) as i32).unwrap_or(ResultCode::ErrorInternalNonFatal) }; std::mem::forget(data); // prevent Buffer from being returned to ZT core twice, see comment in drop() in buffer.rs rc } pub fn multicast_subscribe(&self, nwid: &NetworkId, multicast_group: &MAC, multicast_adi: u32) -> ResultCode { unsafe { - return ResultCode::from_u32(ztcore::ZT_Node_multicastSubscribe(self.capi.get(), null_mut(), nwid.0, multicast_group.0, multicast_adi as c_ulong) as u32).unwrap_or(ResultCode::ErrorInternalNonFatal); + return ResultCode::from_i32(ztcore::ZT_Node_multicastSubscribe(self.capi.get(), null_mut(), nwid.0, multicast_group.0, multicast_adi as c_ulong) as i32).unwrap_or(ResultCode::ErrorInternalNonFatal); } } pub fn multicast_unsubscribe(&self, nwid: &NetworkId, multicast_group: &MAC, multicast_adi: u32) -> ResultCode { unsafe { - return ResultCode::from_u32(ztcore::ZT_Node_multicastUnsubscribe(self.capi.get(), nwid.0, multicast_group.0, multicast_adi as c_ulong) as u32).unwrap_or(ResultCode::ErrorInternalNonFatal); + return ResultCode::from_i32(ztcore::ZT_Node_multicastUnsubscribe(self.capi.get(), nwid.0, multicast_group.0, multicast_adi as c_ulong) as i32).unwrap_or(ResultCode::ErrorInternalNonFatal); } } diff --git a/rust-zerotier-core/src/virtualnetworkconfig.rs b/rust-zerotier-core/src/virtualnetworkconfig.rs index 3df1f423b..0a9839d15 100644 --- a/rust-zerotier-core/src/virtualnetworkconfig.rs +++ b/rust-zerotier-core/src/virtualnetworkconfig.rs @@ -22,7 +22,7 @@ use crate::bindings::capi as ztcore; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#[derive(FromPrimitive,ToPrimitive)] +#[derive(FromPrimitive,ToPrimitive, PartialEq, Eq)] pub enum VirtualNetworkType { Private = ztcore::ZT_VirtualNetworkType_ZT_NETWORK_TYPE_PRIVATE as isize, Public = ztcore::ZT_VirtualNetworkType_ZT_NETWORK_TYPE_PUBLIC as isize @@ -83,7 +83,7 @@ impl<'de> serde::Deserialize<'de> for VirtualNetworkType { ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#[derive(FromPrimitive,ToPrimitive)] +#[derive(FromPrimitive,ToPrimitive, PartialEq, Eq)] pub enum VirtualNetworkRuleType { ActionDrop = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_ACTION_DROP as isize, ActionAccept = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_ACTION_ACCEPT as isize, @@ -124,7 +124,7 @@ pub enum VirtualNetworkRuleType { ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#[derive(FromPrimitive,ToPrimitive)] +#[derive(FromPrimitive,ToPrimitive, PartialEq, Eq)] pub enum VirtualNetworkConfigOperation { Up = ztcore::ZT_VirtualNetworkConfigOperation_ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP as isize, ConfigUpdate = ztcore::ZT_VirtualNetworkConfigOperation_ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE as isize, @@ -134,7 +134,7 @@ pub enum VirtualNetworkConfigOperation { ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#[derive(FromPrimitive,ToPrimitive)] +#[derive(FromPrimitive,ToPrimitive, PartialEq, Eq)] pub enum VirtualNetworkStatus { RequestingConfiguration = ztcore::ZT_VirtualNetworkStatus_ZT_NETWORK_STATUS_REQUESTING_CONFIGURATION as isize, Ok = ztcore::ZT_VirtualNetworkStatus_ZT_NETWORK_STATUS_OK as isize, @@ -200,7 +200,7 @@ impl<'de> serde::Deserialize<'de> for VirtualNetworkStatus { ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, PartialEq, Eq)] pub struct VirtualNetworkRoute { pub target: Option, pub via: Option, @@ -208,7 +208,7 @@ pub struct VirtualNetworkRoute { pub metric: u16 } -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, PartialEq, Eq)] pub struct VirtualNetworkConfig { pub nwid: NetworkId, pub mac: MAC, @@ -254,8 +254,8 @@ impl VirtualNetworkConfig { nwid: NetworkId(vnc.nwid), mac: MAC(vnc.mac), name: unsafe { cstr_to_string(vnc.name.as_ptr(), vnc.name.len() as isize) }, - status: FromPrimitive::from_u32(vnc.status as u32).unwrap(), - type_: FromPrimitive::from_u32(vnc.type_ as u32).unwrap(), + status: FromPrimitive::from_i32(vnc.status as i32).unwrap_or(VirtualNetworkStatus::RequestingConfiguration), + type_: FromPrimitive::from_i32(vnc.type_ as i32).unwrap_or(VirtualNetworkType::Private), mtu: vnc.mtu as u32, bridge: vnc.bridge != 0, broadcast_enabled: vnc.broadcastEnabled != 0,