Remove CRL from Certificate as it really does not belong there, and Rust cleanup.

This commit is contained in:
Adam Ierymenko 2021-01-01 17:09:30 -05:00
parent 890e7f5442
commit ce40a1df8a
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
11 changed files with 205 additions and 182 deletions

View file

@ -108,12 +108,6 @@ Certificate &Certificate::operator=(const ZT_Certificate &cert)
this->maxPathLength = cert.maxPathLength; this->maxPathLength = cert.maxPathLength;
if ((cert.crl) && (cert.crlCount > 0)) {
for (unsigned int i = 0; i < cert.crlCount; ++i) {
if (cert.crl[i])
addCRLCertificate(cert.crl[i]);
}
}
if ((cert.signature) && (cert.signatureSize > 0)) { if ((cert.signature) && (cert.signatureSize > 0)) {
m_signature.assign(cert.signature, cert.signature + cert.signatureSize); m_signature.assign(cert.signature, cert.signature + cert.signatureSize);
this->signature = m_signature.data(); this->signature = m_signature.data();
@ -223,14 +217,6 @@ bool Certificate::setSubjectUniqueId(const uint8_t uniqueId[ZT_CERTIFICATE_UNIQU
return true; return true;
} }
void Certificate::addCRLCertificate(const uint8_t serialNo[ZT_SHA384_DIGEST_SIZE])
{
m_serials.push_front(SHA384Hash(serialNo));
m_crl.push_back(m_serials.front().bytes());
this->crl = m_crl.data();
this->crlCount = (unsigned int)m_crl.size();
}
Vector< uint8_t > Certificate::encode(const bool omitSignature) const Vector< uint8_t > Certificate::encode(const bool omitSignature) const
{ {
char tmp[32]; char tmp[32];
@ -285,14 +271,6 @@ Vector< uint8_t > Certificate::encode(const bool omitSignature) const
if ((this->extendedAttributes) && (this->extendedAttributesSize > 0)) if ((this->extendedAttributes) && (this->extendedAttributesSize > 0))
d["x"].assign(this->extendedAttributes, this->extendedAttributes + this->extendedAttributesSize); d["x"].assign(this->extendedAttributes, this->extendedAttributes + this->extendedAttributesSize);
if ((this->crl) && (this->crlCount > 0)) {
d.add("r$", (uint64_t)this->crlCount);
for (unsigned int i = 0; i < this->crlCount; ++i) {
if (this->crl[i])
d[Dictionary::arraySubscript(tmp, sizeof(tmp), "r$", i)].assign(this->crl[i], this->crl[i] + ZT_SHA384_DIGEST_SIZE);
}
}
if ((!omitSignature) && (this->signature) && (this->signatureSize > 0)) if ((!omitSignature) && (this->signature) && (this->signatureSize > 0))
d["S"].assign(this->signature, this->signature + this->signatureSize); d["S"].assign(this->signature, this->signature + this->signatureSize);
@ -423,14 +401,6 @@ bool Certificate::decode(const void *const data, const unsigned int len)
this->extendedAttributesSize = (unsigned int)m_extendedAttributes.size(); this->extendedAttributesSize = (unsigned int)m_extendedAttributes.size();
} }
cnt = (unsigned int)d.getUI("r$");
for (unsigned int i = 0; i < cnt; ++i) {
const Vector< uint8_t > &cr = d[Dictionary::arraySubscript(tmp, sizeof(tmp), "r$", i)];
if (cr.size() != ZT_SHA384_DIGEST_SIZE)
return false;
this->addCRLCertificate(cr.data());
}
m_signature = d["S"]; m_signature = d["S"];
if (!m_signature.empty()) { if (!m_signature.empty()) {
this->signature = m_signature.data(); this->signature = m_signature.data();
@ -588,7 +558,6 @@ void Certificate::m_clear()
m_extendedAttributes.clear(); m_extendedAttributes.clear();
m_subjectUniqueId.clear(); m_subjectUniqueId.clear();
m_subjectUniqueIdProofSignature.clear(); m_subjectUniqueIdProofSignature.clear();
m_crl.clear();
m_signature.clear(); m_signature.clear();
} }

View file

@ -125,13 +125,6 @@ public:
*/ */
bool setSubjectUniqueId(const uint8_t uniqueId[ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE], const uint8_t uniqueIdPrivate[ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE]); bool setSubjectUniqueId(const uint8_t uniqueId[ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE], const uint8_t uniqueIdPrivate[ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE]);
/**
* Add a serial number to the CRL list
*
* @param serialNo Serial number of certificate to revoke
*/
void addCRLCertificate(const uint8_t serialNo[ZT_SHA384_DIGEST_SIZE]);
/** /**
* Marshal this certificate in binary form * Marshal this certificate in binary form
* *
@ -236,7 +229,6 @@ private:
Vector< uint8_t > m_extendedAttributes; Vector< uint8_t > m_extendedAttributes;
Vector< uint8_t > m_subjectUniqueId; Vector< uint8_t > m_subjectUniqueId;
Vector< uint8_t > m_subjectUniqueIdProofSignature; Vector< uint8_t > m_subjectUniqueIdProofSignature;
Vector< const uint8_t * > m_crl;
Vector< uint8_t > m_signature; Vector< uint8_t > m_signature;
std::atomic< int > __refCount; std::atomic< int > __refCount;

View file

@ -601,16 +601,6 @@ typedef struct
*/ */
unsigned int maxPathLength; unsigned int maxPathLength;
/**
* List of certificate serial numbers being revoked.
*/
const uint8_t *const *crl;
/**
* Number of 48-byte serial numbers in crl list.
*/
unsigned int crlCount;
/** /**
* Signature by issuer (algorithm determined by identity type). * Signature by issuer (algorithm determined by identity type).
*/ */

View file

@ -1,5 +1,6 @@
use std::cell::Cell; use std::cell::Cell;
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use std::hash::{Hash, Hasher};
use std::mem::{MaybeUninit, zeroed}; use std::mem::{MaybeUninit, zeroed};
use std::os::raw::{c_char, c_uint, c_void}; use std::os::raw::{c_char, c_uint, c_void};
use std::ptr::{copy_nonoverlapping, null, null_mut}; use std::ptr::{copy_nonoverlapping, null, null_mut};
@ -48,6 +49,7 @@ impl CertificateSerialNo {
} }
impl From<&[u8; 48]> for CertificateSerialNo { impl From<&[u8; 48]> for CertificateSerialNo {
#[inline(always)]
fn from(a: &[u8; 48]) -> CertificateSerialNo { fn from(a: &[u8; 48]) -> CertificateSerialNo {
CertificateSerialNo(*a) CertificateSerialNo(*a)
} }
@ -65,7 +67,15 @@ impl From<&[u8]> for CertificateSerialNo {
} }
} }
impl Hash for CertificateSerialNo {
#[inline(always)]
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}
impl ToString for CertificateSerialNo { impl ToString for CertificateSerialNo {
#[inline(always)]
fn to_string(&self) -> String { fn to_string(&self) -> String {
hex::encode(self.0) hex::encode(self.0)
} }
@ -162,7 +172,8 @@ impl<'de> serde::Deserialize<'de> for CertificateUniqueIdType {
pub struct CertificateSubjectUniqueIdSecret { pub struct CertificateSubjectUniqueIdSecret {
pub public: Vec<u8>, pub public: Vec<u8>,
pub private: Vec<u8>, pub private: Vec<u8>,
pub type_: CertificateUniqueIdType, #[serde(rename = "type")]
pub type_: CertificateUniqueIdType
} }
const CERTIFICATE_UNIQUE_ID_CREATE_BUF_SIZE: usize = 128; const CERTIFICATE_UNIQUE_ID_CREATE_BUF_SIZE: usize = 128;
@ -227,36 +238,56 @@ impl ToString for CertificateError {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#[allow(non_snake_case)]
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct CertificateName { pub struct CertificateName {
pub serialNo: String, #[serde(rename = "serialNo")]
pub commonName: String, pub serial_no: String,
#[serde(rename = "commonName")]
pub common_name: String,
pub country: String, pub country: String,
pub organization: String, pub organization: String,
pub unit: String, pub unit: String,
pub locality: String, pub locality: String,
pub province: String, pub province: String,
pub streetAddress: String, #[serde(rename = "streetAddress")]
pub postalCode: String, pub street_address: String,
#[serde(rename = "postalCode")]
pub postal_code: String,
pub email: String, pub email: String,
pub url: String, pub url: String,
pub host: String, pub host: String,
} }
impl CertificateName { impl CertificateName {
pub fn new() -> CertificateName {
CertificateName {
serial_no: String::new(),
common_name: String::new(),
country: String::new(),
organization: String::new(),
unit: String::new(),
locality: String::new(),
province: String::new(),
street_address: String::new(),
postal_code: String::new(),
email: String::new(),
url: String::new(),
host: String::new()
}
}
pub(crate) unsafe fn new_from_capi(cn: &ztcore::ZT_Certificate_Name) -> CertificateName { pub(crate) unsafe fn new_from_capi(cn: &ztcore::ZT_Certificate_Name) -> CertificateName {
unsafe { unsafe {
return CertificateName { return CertificateName {
serialNo: cstr_to_string(cn.serialNo.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1), serial_no: cstr_to_string(cn.serialNo.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1),
commonName: cstr_to_string(cn.commonName.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1), common_name: cstr_to_string(cn.commonName.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1),
country: cstr_to_string(cn.country.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1), country: cstr_to_string(cn.country.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1),
organization: cstr_to_string(cn.organization.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1), organization: cstr_to_string(cn.organization.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1),
unit: cstr_to_string(cn.unit.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1), unit: cstr_to_string(cn.unit.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1),
locality: cstr_to_string(cn.locality.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1), locality: cstr_to_string(cn.locality.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1),
province: cstr_to_string(cn.province.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1), province: cstr_to_string(cn.province.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1),
streetAddress: cstr_to_string(cn.streetAddress.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1), street_address: cstr_to_string(cn.streetAddress.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1),
postalCode: cstr_to_string(cn.postalCode.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1), postal_code: cstr_to_string(cn.postalCode.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1),
email: cstr_to_string(cn.email.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1), email: cstr_to_string(cn.email.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1),
url: cstr_to_string(cn.url.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1), url: cstr_to_string(cn.url.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1),
host: cstr_to_string(cn.host.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1) host: cstr_to_string(cn.host.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1)
@ -282,15 +313,15 @@ impl CertificateName {
pub(crate) unsafe fn to_capi(&self) -> ztcore::ZT_Certificate_Name { pub(crate) unsafe fn to_capi(&self) -> ztcore::ZT_Certificate_Name {
unsafe { unsafe {
let mut cn: ztcore::ZT_Certificate_Name = zeroed(); let mut cn: ztcore::ZT_Certificate_Name = zeroed();
Self::str_to_cert_cstr(&self.serialNo, &mut cn.serialNo); Self::str_to_cert_cstr(&self.serial_no, &mut cn.serialNo);
Self::str_to_cert_cstr(&self.commonName, &mut cn.commonName); Self::str_to_cert_cstr(&self.common_name, &mut cn.commonName);
Self::str_to_cert_cstr(&self.country, &mut cn.country); Self::str_to_cert_cstr(&self.country, &mut cn.country);
Self::str_to_cert_cstr(&self.organization, &mut cn.organization); Self::str_to_cert_cstr(&self.organization, &mut cn.organization);
Self::str_to_cert_cstr(&self.unit, &mut cn.unit); Self::str_to_cert_cstr(&self.unit, &mut cn.unit);
Self::str_to_cert_cstr(&self.locality, &mut cn.locality); Self::str_to_cert_cstr(&self.locality, &mut cn.locality);
Self::str_to_cert_cstr(&self.province, &mut cn.province); Self::str_to_cert_cstr(&self.province, &mut cn.province);
Self::str_to_cert_cstr(&self.streetAddress, &mut cn.streetAddress); Self::str_to_cert_cstr(&self.street_address, &mut cn.streetAddress);
Self::str_to_cert_cstr(&self.postalCode, &mut cn.postalCode); Self::str_to_cert_cstr(&self.postal_code, &mut cn.postalCode);
Self::str_to_cert_cstr(&self.email, &mut cn.email); Self::str_to_cert_cstr(&self.email, &mut cn.email);
Self::str_to_cert_cstr(&self.url, &mut cn.url); Self::str_to_cert_cstr(&self.url, &mut cn.url);
Self::str_to_cert_cstr(&self.host, &mut cn.host); Self::str_to_cert_cstr(&self.host, &mut cn.host);
@ -364,17 +395,19 @@ implement_to_from_json!(CertificateIdentity);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#[allow(non_snake_case)]
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct CertificateSubject { pub struct CertificateSubject {
pub timestamp: i64, pub timestamp: i64,
pub identities: Vec<CertificateIdentity>, pub identities: Vec<CertificateIdentity>,
pub networks: Vec<CertificateNetwork>, pub networks: Vec<CertificateNetwork>,
pub certificates: Vec<CertificateSerialNo>, pub certificates: Vec<CertificateSerialNo>,
pub updateURLs: Vec<String>, #[serde(rename = "updateURLs")]
pub update_urls: Vec<String>,
pub name: CertificateName, pub name: CertificateName,
pub uniqueId: Vec<u8>, #[serde(rename = "uniqueId")]
pub uniqueIdProofSignature: Vec<u8>, pub unique_id: Vec<u8>,
#[serde(rename = "uniqueIdProofSignature")]
pub unique_id_proof_signature: Vec<u8>,
} }
pub(crate) struct CertificateSubjectCAPIContainer { pub(crate) struct CertificateSubjectCAPIContainer {
@ -387,6 +420,19 @@ pub(crate) struct CertificateSubjectCAPIContainer {
} }
impl CertificateSubject { impl CertificateSubject {
pub fn new() -> CertificateSubject {
CertificateSubject {
timestamp: 0,
identities: Vec::new(),
networks: Vec::new(),
certificates: Vec::new(),
update_urls: Vec::new(),
name: CertificateName::new(),
unique_id: Vec::new(),
unique_id_proof_signature: Vec::new()
}
}
pub(crate) unsafe fn new_from_capi(cs: &ztcore::ZT_Certificate_Subject) -> CertificateSubject { pub(crate) unsafe fn new_from_capi(cs: &ztcore::ZT_Certificate_Subject) -> CertificateSubject {
unsafe { unsafe {
let mut identities: Vec<CertificateIdentity> = Vec::new(); let mut identities: Vec<CertificateIdentity> = Vec::new();
@ -431,10 +477,10 @@ impl CertificateSubject {
identities: identities, identities: identities,
networks: networks, networks: networks,
certificates: certificates, certificates: certificates,
updateURLs: update_urls, update_urls: update_urls,
name: CertificateName::new_from_capi(&cs.name), name: CertificateName::new_from_capi(&cs.name),
uniqueId: Vec::from(std::slice::from_raw_parts(cs.uniqueId, cs.uniqueIdSize as usize)), unique_id: Vec::from(std::slice::from_raw_parts(cs.uniqueId, cs.uniqueIdSize as usize)),
uniqueIdProofSignature: Vec::from(std::slice::from_raw_parts(cs.uniqueIdProofSignature, cs.uniqueIdProofSignatureSize as usize)), unique_id_proof_signature: Vec::from(std::slice::from_raw_parts(cs.uniqueIdProofSignature, cs.uniqueIdProofSignatureSize as usize)),
}; };
} }
} }
@ -464,9 +510,9 @@ impl CertificateSubject {
capi_certificates.push((*i).0.as_ptr()); capi_certificates.push((*i).0.as_ptr());
} }
} }
if !self.updateURLs.is_empty() { if !self.update_urls.is_empty() {
capi_urls.reserve(self.updateURLs.len()); capi_urls.reserve(self.update_urls.len());
for i in self.updateURLs.iter() { for i in self.update_urls.iter() {
let cs = CString::new((*i).as_str()); let cs = CString::new((*i).as_str());
if cs.is_ok() { if cs.is_ok() {
capi_urls_strs.push(cs.unwrap()); capi_urls_strs.push(cs.unwrap());
@ -487,10 +533,10 @@ impl CertificateSubject {
certificateCount: capi_certificates.len() as c_uint, certificateCount: capi_certificates.len() as c_uint,
updateURLCount: capi_urls.len() as c_uint, updateURLCount: capi_urls.len() as c_uint,
name: unsafe { self.name.to_capi() }, name: unsafe { self.name.to_capi() },
uniqueId: self.uniqueId.as_ptr(), uniqueId: self.unique_id.as_ptr(),
uniqueIdProofSignature: self.uniqueIdProofSignature.as_ptr(), uniqueIdProofSignature: self.unique_id_proof_signature.as_ptr(),
uniqueIdSize: self.uniqueId.len() as c_uint, uniqueIdSize: self.unique_id.len() as c_uint,
uniqueIdProofSignatureSize: self.uniqueIdProofSignature.len() as c_uint, uniqueIdProofSignatureSize: self.unique_id_proof_signature.len() as c_uint,
}, },
subject_identities: capi_identities, subject_identities: capi_identities,
subject_networks: capi_networks, subject_networks: capi_networks,
@ -527,85 +573,79 @@ implement_to_from_json!(CertificateSubject);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#[allow(non_snake_case)]
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct Certificate { pub struct Certificate {
pub serialNo: CertificateSerialNo, #[serde(rename = "serialNo")]
pub serial_no: CertificateSerialNo,
pub flags: u64, pub flags: u64,
pub timestamp: i64, pub timestamp: i64,
pub validity: [i64; 2], pub validity: [i64; 2],
pub subject: CertificateSubject, pub subject: CertificateSubject,
pub issuer: Identity, pub issuer: Option<Identity>,
pub issuerName: CertificateName, #[serde(rename = "issuerName")]
pub extendedAttributes: Vec<u8>, pub issuer_name: CertificateName,
pub maxPathLength: u32, #[serde(rename = "extendedAttributes")]
pub crl: Vec<CertificateSerialNo>, pub extended_attributes: Vec<u8>,
pub signature: Vec<u8>, #[serde(rename = "maxPathLength")]
pub max_path_length: u32,
pub signature: Vec<u8>
} }
pub(crate) struct CertificateCAPIContainer { pub(crate) struct CertificateCAPIContainer {
pub(crate) certificate: ztcore::ZT_Certificate, pub(crate) certificate: ztcore::ZT_Certificate,
certificate_crls: Vec<*const u8>,
subject_container: CertificateSubjectCAPIContainer, subject_container: CertificateSubjectCAPIContainer,
} }
impl Certificate { impl Certificate {
pub(crate) unsafe fn new_from_capi(c: &ztcore::ZT_Certificate) -> Certificate { pub fn new() -> Certificate {
unsafe { Certificate {
let mut crl: Vec<CertificateSerialNo> = Vec::new(); serial_no: CertificateSerialNo::new(),
if !c.crl.is_null() && c.crlCount > 0 { flags: 0,
let ccrl: &[*const u8] = std::slice::from_raw_parts(c.crl, c.crlCount as usize); timestamp: 0,
let mut ctmp: [u8; 48] = [0; 48]; validity: [0, i64::max_value()],
for i in ccrl.iter() { subject: CertificateSubject::new(),
if !(*i).is_null() { issuer: None,
copy_nonoverlapping(*i, ctmp.as_mut_ptr(), 48); issuer_name: CertificateName::new(),
crl.push(CertificateSerialNo(ctmp)); extended_attributes: Vec::new(),
} max_path_length: 0,
signature: Vec::new()
} }
} }
pub(crate) unsafe fn new_from_capi(c: &ztcore::ZT_Certificate) -> Certificate {
unsafe {
return Certificate { return Certificate {
serialNo: CertificateSerialNo(c.serialNo), serial_no: CertificateSerialNo(c.serialNo),
flags: c.flags, flags: c.flags,
timestamp: c.timestamp, timestamp: c.timestamp,
validity: c.validity, validity: c.validity,
subject: CertificateSubject::new_from_capi(&c.subject), subject: CertificateSubject::new_from_capi(&c.subject),
issuer: Identity::new_from_capi(c.issuer, false), issuer: if c.issuer.is_null() { None } else { Some(Identity::new_from_capi(c.issuer, false)) },
issuerName: CertificateName::new_from_capi(&c.issuerName), issuer_name: CertificateName::new_from_capi(&c.issuerName),
extendedAttributes: Vec::from(std::slice::from_raw_parts(c.extendedAttributes, c.extendedAttributesSize as usize)), extended_attributes: Vec::from(std::slice::from_raw_parts(c.extendedAttributes, c.extendedAttributesSize as usize)),
maxPathLength: c.maxPathLength as u32, max_path_length: c.maxPathLength as u32,
crl: crl,
signature: Vec::from(std::slice::from_raw_parts(c.signature, c.signatureSize as usize)), signature: Vec::from(std::slice::from_raw_parts(c.signature, c.signatureSize as usize)),
}; };
} }
} }
pub(crate) unsafe fn to_capi(&self) -> CertificateCAPIContainer { pub(crate) unsafe fn to_capi(&self) -> CertificateCAPIContainer {
let mut capi_crls: Vec<*const u8> = Vec::new();
capi_crls.reserve(self.crl.len());
for i in self.crl.iter() {
capi_crls.push((*i).0.as_ptr());
}
let subject = unsafe { self.subject.to_capi() }; let subject = unsafe { self.subject.to_capi() };
CertificateCAPIContainer { CertificateCAPIContainer {
certificate: ztcore::ZT_Certificate { certificate: ztcore::ZT_Certificate {
serialNo: self.serialNo.0, serialNo: self.serial_no.0,
flags: self.flags, flags: self.flags,
timestamp: self.timestamp, timestamp: self.timestamp,
validity: self.validity, validity: self.validity,
subject: subject.subject, subject: subject.subject,
issuer: self.issuer.capi, issuer: if self.issuer.is_some() { self.issuer.as_ref().unwrap().capi } else { null() },
issuerName: unsafe { self.issuerName.to_capi() }, issuerName: unsafe { self.issuer_name.to_capi() },
extendedAttributes: self.extendedAttributes.as_ptr(), extendedAttributes: self.extended_attributes.as_ptr(),
extendedAttributesSize: self.extendedAttributes.len() as c_uint, extendedAttributesSize: self.extended_attributes.len() as c_uint,
maxPathLength: self.maxPathLength as c_uint, maxPathLength: self.max_path_length as c_uint,
crl: capi_crls.as_ptr(),
crlCount: capi_crls.len() as c_uint,
signature: self.signature.as_ptr(), signature: self.signature.as_ptr(),
signatureSize: self.signature.len() as c_uint, signatureSize: self.signature.len() as c_uint,
}, },
certificate_crls: capi_crls,
subject_container: subject, subject_container: subject,
} }
} }
@ -669,3 +709,15 @@ impl Certificate {
implement_to_from_json!(Certificate); implement_to_from_json!(Certificate);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#[cfg(test)]
mod tests {
use crate::*;
#[test]
fn certificate_serial_no() {
let test: [u8; 48] = [1; 48];
let sn = CertificateSerialNo::from(&test[0..48]);
assert!(test.eq(&sn.0));
}
}

View file

@ -1,9 +1,25 @@
use crate::*;
use crate::bindings::capi as ztcore;
use num_traits::FromPrimitive;
use std::os::raw::{c_char, c_int};
use std::ffi::CStr; use std::ffi::CStr;
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use std::os::raw::{c_char, c_int};
use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::FromPrimitive;
use crate::*;
use crate::bindings::capi as ztcore;
#[derive(FromPrimitive,ToPrimitive)]
pub enum EndpointType {
Nil = ztcore::ZT_EndpointType_ZT_ENDPOINT_TYPE_NIL as isize,
ZeroTier = ztcore::ZT_EndpointType_ZT_ENDPOINT_TYPE_ZEROTIER as isize,
Ethernet = ztcore::ZT_EndpointType_ZT_ENDPOINT_TYPE_ETHERNET as isize,
WifiDirect = ztcore::ZT_EndpointType_ZT_ENDPOINT_TYPE_WIFI_DIRECT as isize,
Bluetooth = ztcore::ZT_EndpointType_ZT_ENDPOINT_TYPE_BLUETOOTH as isize,
Ip = ztcore::ZT_EndpointType_ZT_ENDPOINT_TYPE_IP as isize,
IpUdp = ztcore::ZT_EndpointType_ZT_ENDPOINT_TYPE_IP_UDP as isize,
IpTcp = ztcore::ZT_EndpointType_ZT_ENDPOINT_TYPE_IP_TCP as isize,
IpHttp = ztcore::ZT_EndpointType_ZT_ENDPOINT_TYPE_IP_HTTP as isize,
}
pub struct Endpoint { pub struct Endpoint {
pub type_: EndpointType, pub type_: EndpointType,
@ -11,7 +27,6 @@ pub struct Endpoint {
} }
impl Endpoint { impl Endpoint {
#[inline]
pub(crate) fn new_from_capi(ep: &ztcore::ZT_Endpoint) -> Endpoint { pub(crate) fn new_from_capi(ep: &ztcore::ZT_Endpoint) -> Endpoint {
return Endpoint{ return Endpoint{
type_: EndpointType::from_u32(ep.type_ as u32).unwrap(), type_: EndpointType::from_u32(ep.type_ as u32).unwrap(),
@ -37,12 +52,12 @@ impl Endpoint {
impl ToString for Endpoint { impl ToString for Endpoint {
fn to_string(&self) -> String { fn to_string(&self) -> String {
let mut buf: [u8; 1024] = [0; 1024];
unsafe { unsafe {
if ztcore::ZT_Endpoint_toString(&(self.capi) as *const ztcore::ZT_Endpoint, buf.as_mut_ptr() as *mut c_char, buf.len() as c_int).is_null() { let mut buf: MaybeUninit<[c_char; 1024]> = MaybeUninit::uninit();
if ztcore::ZT_Endpoint_toString(&(self.capi) as *const ztcore::ZT_Endpoint, (*buf.as_mut_ptr()).as_mut_ptr(), 1024).is_null() {
return String::from("(invalid)"); return String::from("(invalid)");
} }
return String::from(CStr::from_bytes_with_nul(buf.as_ref()).unwrap().to_str().unwrap()); return cstr_to_string((*buf.as_ptr()).as_ptr(), 1024);
} }
} }
} }

View file

@ -1,8 +1,11 @@
use std::ffi::CStr;
use std::mem::MaybeUninit;
use std::os::raw::*;
use num_traits::{FromPrimitive, ToPrimitive};
use crate::*; use crate::*;
use crate::bindings::capi as ztcore; use crate::bindings::capi as ztcore;
use std::os::raw::*;
use std::ffi::CStr;
use num_traits::{ToPrimitive, FromPrimitive};
#[derive(FromPrimitive,ToPrimitive)] #[derive(FromPrimitive,ToPrimitive)]
pub enum IdentityType { pub enum IdentityType {
@ -55,12 +58,12 @@ impl Identity {
} }
fn intl_to_string(&self, include_private: bool) -> String { fn intl_to_string(&self, include_private: bool) -> String {
let mut buf: [u8; 2048] = [0; 2048];
unsafe { unsafe {
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() { 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)"); return String::from("(invalid)");
} }
return String::from(CStr::from_bytes_with_nul(buf.as_ref()).unwrap().to_str().unwrap()); return cstr_to_string((*buf.as_ptr()).as_ptr(), 4096);
} }
} }

View file

@ -23,13 +23,13 @@ use bindings::capi as ztcore;
pub use identity::*; pub use identity::*;
pub use address::Address; pub use address::Address;
pub use fingerprint::Fingerprint; pub use fingerprint::Fingerprint;
pub use endpoint::Endpoint; pub use endpoint::*;
pub use certificate::*; pub use certificate::*;
pub use networkid::NetworkId; pub use networkid::NetworkId;
pub use locator::Locator; pub use locator::*;
pub use path::Path; pub use path::Path;
pub use peer::Peer; pub use peer::Peer;
pub use node::Node; pub use node::*;
pub use mac::MAC; pub use mac::MAC;
pub use buffer::Buffer; pub use buffer::Buffer;
pub use portableatomici64::PortableAtomicI64; pub use portableatomici64::PortableAtomicI64;
@ -72,19 +72,6 @@ pub enum CredentialType {
Revocation = ztcore::ZT_CredentialType_ZT_CREDENTIAL_TYPE_REVOCATION as isize, Revocation = ztcore::ZT_CredentialType_ZT_CREDENTIAL_TYPE_REVOCATION as isize,
} }
#[derive(FromPrimitive,ToPrimitive)]
pub enum EndpointType {
Nil = ztcore::ZT_EndpointType_ZT_ENDPOINT_TYPE_NIL as isize,
ZeroTier = ztcore::ZT_EndpointType_ZT_ENDPOINT_TYPE_ZEROTIER as isize,
Ethernet = ztcore::ZT_EndpointType_ZT_ENDPOINT_TYPE_ETHERNET as isize,
WifiDirect = ztcore::ZT_EndpointType_ZT_ENDPOINT_TYPE_WIFI_DIRECT as isize,
Bluetooth = ztcore::ZT_EndpointType_ZT_ENDPOINT_TYPE_BLUETOOTH as isize,
Ip = ztcore::ZT_EndpointType_ZT_ENDPOINT_TYPE_IP as isize,
IpUdp = ztcore::ZT_EndpointType_ZT_ENDPOINT_TYPE_IP_UDP as isize,
IpTcp = ztcore::ZT_EndpointType_ZT_ENDPOINT_TYPE_IP_TCP as isize,
IpHttp = ztcore::ZT_EndpointType_ZT_ENDPOINT_TYPE_IP_HTTP as isize,
}
#[derive(FromPrimitive,ToPrimitive)] #[derive(FromPrimitive,ToPrimitive)]
pub enum TraceEventType { pub enum TraceEventType {
UnexpectedError = ztcore::ZT_TraceEventType_ZT_TRACE_UNEXPECTED_ERROR as isize, UnexpectedError = ztcore::ZT_TraceEventType_ZT_TRACE_UNEXPECTED_ERROR as isize,

View file

@ -20,8 +20,10 @@ const NODE_BACKGROUND_MIN_DELAY: i64 = 250;
pub struct NodeStatus { pub struct NodeStatus {
pub address: Address, pub address: Address,
pub identity: Identity, pub identity: Identity,
pub publicIdentity: String, #[serde(rename = "publicIdentity")]
pub secretIdentity: String, pub public_identity: String,
#[serde(rename = "secretIdentity")]
pub secret_identity: String,
pub online: bool pub online: bool
} }
@ -293,8 +295,8 @@ impl Node {
return NodeStatus { return NodeStatus {
address: Address(ns.address), address: Address(ns.address),
identity: Identity::new_from_capi(&*ns.identity, false).clone(), identity: Identity::new_from_capi(&*ns.identity, false).clone(),
publicIdentity: String::from(CStr::from_ptr(ns.publicIdentity).to_str().unwrap()), public_identity: String::from(CStr::from_ptr(ns.publicIdentity).to_str().unwrap()),
secretIdentity: String::from(CStr::from_ptr(ns.secretIdentity).to_str().unwrap()), secret_identity: String::from(CStr::from_ptr(ns.secretIdentity).to_str().unwrap()),
online: ns.online != 0 online: ns.online != 0
} }
} }

View file

@ -2,12 +2,13 @@ use crate::*;
use crate::bindings::capi as ztcore; use crate::bindings::capi as ztcore;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[allow(non_snake_case)]
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct Path { pub struct Path {
pub endpoint: Endpoint, pub endpoint: Endpoint,
pub lastSend: i64, #[serde(rename = "lastSend")]
pub lastReceive: i64, pub last_send: i64,
#[serde(rename = "lastReceive")]
pub last_receive: i64,
pub alive: bool, pub alive: bool,
pub preferred: bool pub preferred: bool
} }
@ -17,8 +18,8 @@ impl Path {
pub(crate) fn new_from_capi(p: &ztcore::ZT_Path) -> Path { pub(crate) fn new_from_capi(p: &ztcore::ZT_Path) -> Path {
Path{ Path{
endpoint: Endpoint::new_from_capi(&p.endpoint), endpoint: Endpoint::new_from_capi(&p.endpoint),
lastSend: p.lastSend, last_send: p.lastSend,
lastReceive: p.lastReceive, last_receive: p.lastReceive,
alive: p.alive != 0, alive: p.alive != 0,
preferred: p.preferred != 0 preferred: p.preferred != 0
} }

View file

@ -2,21 +2,24 @@ use crate::*;
use crate::bindings::capi as ztcore; use crate::bindings::capi as ztcore;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[allow(non_snake_case)]
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct Peer { pub struct Peer {
address: Address, pub address: Address,
identity: Identity, pub identity: Identity,
fingerprint: Fingerprint, pub fingerprint: Fingerprint,
versionMajor: i32, #[serde(rename = "versionMajor")]
versionMinor: i32, pub version_major: i32,
versionRev: i32, #[serde(rename = "versionMinor")]
versionProto: i32, pub version_minor: i32,
latency: i32, #[serde(rename = "versionRev")]
root: bool, pub version_rev: i32,
networks: Vec<NetworkId>, #[serde(rename = "versionProto")]
paths: Vec<Path>, pub version_proto: i32,
// locator: Locator pub latency: i32,
pub root: bool,
pub networks: Vec<NetworkId>,
pub paths: Vec<Path>,
pub locator: Option<Locator>
} }
impl Peer { impl Peer {
@ -35,14 +38,15 @@ impl Peer {
address: Address(p.address), address: Address(p.address),
identity: Identity::new_from_capi(p.identity, false).clone(), // clone to get a copy independent of 'p' identity: Identity::new_from_capi(p.identity, false).clone(), // clone to get a copy independent of 'p'
fingerprint: Fingerprint::new_from_capi(&(*p.fingerprint)), fingerprint: Fingerprint::new_from_capi(&(*p.fingerprint)),
versionMajor: p.versionMajor as i32, version_major: p.versionMajor as i32,
versionMinor: p.versionMinor as i32, version_minor: p.versionMinor as i32,
versionRev: p.versionRev as i32, version_rev: p.versionRev as i32,
versionProto: p.versionProto as i32, version_proto: p.versionProto as i32,
latency: p.latency as i32, latency: p.latency as i32,
root: p.root != 0, root: p.root != 0,
networks: networks, networks: networks,
paths: paths paths: paths,
locator: if p.locator.is_null() { None } else { Some(Locator::new_from_capi(p.locator, false).clone() )}
} }
} }
} }

View file

@ -83,12 +83,16 @@ pub struct VirtualNetworkConfig {
pub mac: MAC, pub mac: MAC,
pub name: String, pub name: String,
pub status: VirtualNetworkStatus, pub status: VirtualNetworkStatus,
#[serde(rename = "type")]
pub type_: VirtualNetworkType, pub type_: VirtualNetworkType,
pub mtu: u32, pub mtu: u32,
pub bridge: bool, pub bridge: bool,
pub broadcastEnabled: bool, #[serde(rename = "broadcastEnabled")]
pub netconfRevision: u64, pub broadcast_enabled: bool,
pub assignedAddresses: Vec<SockAddr>, #[serde(rename = "netconfRevision")]
pub netconf_revision: u64,
#[serde(rename = "assignedAddresses")]
pub assigned_addresses: Vec<SockAddr>,
pub routes: Vec<VirtualNetworkRoute> pub routes: Vec<VirtualNetworkRoute>
} }
@ -97,6 +101,10 @@ const SIZEOF_SOCKADDR_IN6: ztcore::socklen_t = size_of::<ztcore::sockaddr_in6>()
/// Obtain a socket2::SockAddr from a C struct sockaddr_storage as used in the ZeroTier core. /// Obtain a socket2::SockAddr from a C struct sockaddr_storage as used in the ZeroTier core.
pub(crate) fn sockaddr_from_capi(ss: &ztcore::sockaddr_storage) -> Option<SockAddr> { pub(crate) fn sockaddr_from_capi(ss: &ztcore::sockaddr_storage) -> Option<SockAddr> {
// The transmute() calls in here are to work around the fact that socket2
// uses sockaddr_storage from the libc crate, while ztcore uses it as
// generated from bindgen from the system headers. It's the same thing but
// Rust's type system doesn't know that.
match ss.ss_family as u32 { match ss.ss_family as u32 {
ztcore::AF_INET => { unsafe { Some(SockAddr::from_raw_parts(transmute(ss as *const ztcore::sockaddr_storage), transmute(SIZEOF_SOCKADDR_IN))) } }, ztcore::AF_INET => { unsafe { Some(SockAddr::from_raw_parts(transmute(ss as *const ztcore::sockaddr_storage), transmute(SIZEOF_SOCKADDR_IN))) } },
ztcore::AF_INET6 => { unsafe { Some(SockAddr::from_raw_parts(transmute(ss as *const ztcore::sockaddr_storage), transmute(SIZEOF_SOCKADDR_IN6))) } }, ztcore::AF_INET6 => { unsafe { Some(SockAddr::from_raw_parts(transmute(ss as *const ztcore::sockaddr_storage), transmute(SIZEOF_SOCKADDR_IN6))) } },
@ -136,9 +144,9 @@ impl VirtualNetworkConfig {
type_: FromPrimitive::from_u32(vnc.type_ as u32).unwrap(), type_: FromPrimitive::from_u32(vnc.type_ as u32).unwrap(),
mtu: vnc.mtu as u32, mtu: vnc.mtu as u32,
bridge: vnc.bridge != 0, bridge: vnc.bridge != 0,
broadcastEnabled: vnc.broadcastEnabled != 0, broadcast_enabled: vnc.broadcastEnabled != 0,
netconfRevision: vnc.netconfRevision as u64, netconf_revision: vnc.netconfRevision as u64,
assignedAddresses: aa, assigned_addresses: aa,
routes: rts routes: rts
} }
} }