mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-26 17:03:43 +02:00
Clean up some n00b Rust code and reduce the use of unsafe.
This commit is contained in:
parent
83d74d8b67
commit
890e7f5442
2 changed files with 255 additions and 223 deletions
|
@ -10,9 +10,10 @@ use serde::{Deserialize, Serialize};
|
|||
|
||||
use crate::*;
|
||||
use crate::bindings::capi as ztcore;
|
||||
use crate::bindings::capi::ZT_CertificateError;
|
||||
|
||||
/// Maximum length of a string in a certificate (mostly for the certificate name fields).
|
||||
pub const CERTIFICATE_MAX_STRING_LENGTH: u32 = ztcore::ZT_CERTIFICATE_MAX_STRING_LENGTH;
|
||||
pub const CERTIFICATE_MAX_STRING_LENGTH: isize = ztcore::ZT_CERTIFICATE_MAX_STRING_LENGTH as isize;
|
||||
|
||||
/// Certificate local trust bit field flag: this certificate self-signs a root CA.
|
||||
pub const CERTIFICATE_LOCAL_TRUST_FLAG_ROOT_CA: u32 = ztcore::ZT_CERTIFICATE_LOCAL_TRUST_FLAG_ROOT_CA;
|
||||
|
@ -31,30 +32,36 @@ pub const CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE: u32 = ztcore::ZT_C
|
|||
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<CertificateSerialNo, ResultCode> {
|
||||
let b = hex::decode(s);
|
||||
if b.is_err() {
|
||||
return Err(ResultCode::ErrorBadParameter);
|
||||
}
|
||||
return Ok(CertificateSerialNo::from(b.unwrap()));
|
||||
return Ok(CertificateSerialNo::from(b.unwrap().as_slice()));
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<u8>> for CertificateSerialNo {
|
||||
fn from(v: Vec<u8>) -> CertificateSerialNo {
|
||||
impl From<&[u8; 48]> for CertificateSerialNo {
|
||||
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;
|
||||
}
|
||||
unsafe {
|
||||
let mut r: [u8; 48] = MaybeUninit::uninit().assume_init();
|
||||
copy_nonoverlapping(v.as_ptr(), r.as_mut_ptr(), l);
|
||||
while l < 48 {
|
||||
r[l] = 0;
|
||||
l += 1;
|
||||
}
|
||||
return CertificateSerialNo(r);
|
||||
}
|
||||
let mut s = CertificateSerialNo::new();
|
||||
s.0[0..l].copy_from_slice(&v[0..l]);
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,22 +165,24 @@ pub struct CertificateSubjectUniqueIdSecret {
|
|||
pub type_: CertificateUniqueIdType,
|
||||
}
|
||||
|
||||
const CERTIFICATE_UNIQUE_ID_CREATE_BUF_SIZE: usize = 128;
|
||||
|
||||
impl CertificateSubjectUniqueIdSecret {
|
||||
pub fn new(t: CertificateUniqueIdType) -> Self {
|
||||
let mut unique_id: [u8; CERTIFICATE_UNIQUE_ID_CREATE_BUF_SIZE] = [0; CERTIFICATE_UNIQUE_ID_CREATE_BUF_SIZE];
|
||||
let mut unique_id_private: [u8; CERTIFICATE_UNIQUE_ID_CREATE_BUF_SIZE] = [0; CERTIFICATE_UNIQUE_ID_CREATE_BUF_SIZE];
|
||||
let mut unique_id_size = CERTIFICATE_UNIQUE_ID_CREATE_BUF_SIZE as c_int;
|
||||
let mut unique_id_private_size = CERTIFICATE_UNIQUE_ID_CREATE_BUF_SIZE as c_int;
|
||||
let ct: ztcore::ZT_CertificateUniqueIdType = num_traits::ToPrimitive::to_u32(&t).unwrap();
|
||||
unsafe {
|
||||
let mut unique_id: [u8; 128] = zeroed();
|
||||
let mut unique_id_private: [u8; 128] = zeroed();
|
||||
let mut unique_id_size: c_int = unique_id.len() as c_int;
|
||||
let mut unique_id_private_size: c_int = unique_id_private.len() as c_int;
|
||||
let ct: ztcore::ZT_CertificateUniqueIdType = num_traits::ToPrimitive::to_u32(&t).unwrap();
|
||||
if ztcore::ZT_Certificate_newSubjectUniqueId(ct, unique_id.as_mut_ptr() as *mut c_void, &mut unique_id_size as *mut c_int, unique_id_private.as_mut_ptr() as *mut c_void, &mut unique_id_private_size as *mut c_int) != 0 {
|
||||
if ztcore::ZT_Certificate_newSubjectUniqueId(ct, unique_id.as_mut_ptr() as *mut c_void, &mut unique_id_size, unique_id_private.as_mut_ptr() as *mut c_void, &mut unique_id_private_size) != 0 {
|
||||
panic!("fatal internal error: ZT_Certificate_newSubjectUniqueId failed.");
|
||||
}
|
||||
return 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(),
|
||||
};
|
||||
}
|
||||
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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -235,56 +244,56 @@ pub struct CertificateName {
|
|||
pub host: String,
|
||||
}
|
||||
|
||||
unsafe fn str_to_cert_cstr(s: &String, cs: &mut [c_char; 128]) {
|
||||
let mut l = s.len();
|
||||
if l == 0 {
|
||||
cs[0] = 0;
|
||||
return;
|
||||
}
|
||||
if l > 126 {
|
||||
l = 126;
|
||||
}
|
||||
unsafe {
|
||||
copy_nonoverlapping(s.as_ptr(), cs.as_mut_ptr() as *mut u8, l);
|
||||
}
|
||||
cs[l + 1] = 0;
|
||||
}
|
||||
|
||||
impl CertificateName {
|
||||
pub(crate) fn new_from_capi(cn: &ztcore::ZT_Certificate_Name) -> CertificateName {
|
||||
pub(crate) unsafe fn new_from_capi(cn: &ztcore::ZT_Certificate_Name) -> CertificateName {
|
||||
unsafe {
|
||||
return CertificateName {
|
||||
serialNo: String::from(CStr::from_ptr(cn.serialNo.as_ptr()).to_str().unwrap()),
|
||||
commonName: String::from(CStr::from_ptr(cn.commonName.as_ptr()).to_str().unwrap()),
|
||||
country: String::from(CStr::from_ptr(cn.country.as_ptr()).to_str().unwrap()),
|
||||
organization: String::from(CStr::from_ptr(cn.organization.as_ptr()).to_str().unwrap()),
|
||||
unit: String::from(CStr::from_ptr(cn.unit.as_ptr()).to_str().unwrap()),
|
||||
locality: String::from(CStr::from_ptr(cn.locality.as_ptr()).to_str().unwrap()),
|
||||
province: String::from(CStr::from_ptr(cn.province.as_ptr()).to_str().unwrap()),
|
||||
streetAddress: String::from(CStr::from_ptr(cn.streetAddress.as_ptr()).to_str().unwrap()),
|
||||
postalCode: String::from(CStr::from_ptr(cn.postalCode.as_ptr()).to_str().unwrap()),
|
||||
email: String::from(CStr::from_ptr(cn.email.as_ptr()).to_str().unwrap()),
|
||||
url: String::from(CStr::from_ptr(cn.url.as_ptr()).to_str().unwrap()),
|
||||
host: String::from(CStr::from_ptr(cn.host.as_ptr()).to_str().unwrap()),
|
||||
serialNo: 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),
|
||||
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),
|
||||
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),
|
||||
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),
|
||||
postalCode: 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),
|
||||
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)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn str_to_cert_cstr(s: &String, cs: &mut [c_char; 128]) {
|
||||
let mut l = s.len();
|
||||
if l == 0 {
|
||||
cs[0] = 0;
|
||||
return;
|
||||
}
|
||||
if l > 126 {
|
||||
l = 126;
|
||||
}
|
||||
unsafe {
|
||||
copy_nonoverlapping(s.as_ptr(), cs.as_mut_ptr() as *mut u8, l);
|
||||
}
|
||||
cs[l + 1] = 0;
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn to_capi(&self) -> ztcore::ZT_Certificate_Name {
|
||||
unsafe {
|
||||
let mut cn: ztcore::ZT_Certificate_Name = zeroed();
|
||||
str_to_cert_cstr(&self.serialNo, &mut cn.serialNo);
|
||||
str_to_cert_cstr(&self.commonName, &mut cn.commonName);
|
||||
str_to_cert_cstr(&self.country, &mut cn.country);
|
||||
str_to_cert_cstr(&self.organization, &mut cn.organization);
|
||||
str_to_cert_cstr(&self.unit, &mut cn.unit);
|
||||
str_to_cert_cstr(&self.locality, &mut cn.locality);
|
||||
str_to_cert_cstr(&self.province, &mut cn.province);
|
||||
str_to_cert_cstr(&self.streetAddress, &mut cn.streetAddress);
|
||||
str_to_cert_cstr(&self.postalCode, &mut cn.postalCode);
|
||||
str_to_cert_cstr(&self.email, &mut cn.email);
|
||||
str_to_cert_cstr(&self.url, &mut cn.url);
|
||||
str_to_cert_cstr(&self.host, &mut cn.host);
|
||||
Self::str_to_cert_cstr(&self.serialNo, &mut cn.serialNo);
|
||||
Self::str_to_cert_cstr(&self.commonName, &mut cn.commonName);
|
||||
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.unit, &mut cn.unit);
|
||||
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.streetAddress, &mut cn.streetAddress);
|
||||
Self::str_to_cert_cstr(&self.postalCode, &mut cn.postalCode);
|
||||
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.host, &mut cn.host);
|
||||
return cn;
|
||||
}
|
||||
}
|
||||
|
@ -329,21 +338,24 @@ implement_to_from_json!(CertificateNetwork);
|
|||
#[derive(Serialize, Deserialize)]
|
||||
pub struct CertificateIdentity {
|
||||
pub identity: Identity,
|
||||
pub locator: Locator,
|
||||
pub locator: Option<Locator>,
|
||||
}
|
||||
|
||||
impl CertificateIdentity {
|
||||
pub(crate) fn new_from_capi(ci: &ztcore::ZT_Certificate_Identity) -> CertificateIdentity {
|
||||
CertificateIdentity {
|
||||
identity: Identity::new_from_capi(ci.identity, false).clone(),
|
||||
locator: Locator::new_from_capi(ci.locator, false).clone(),
|
||||
pub(crate) unsafe fn new_from_capi(ci: &ztcore::ZT_Certificate_Identity) -> Option<CertificateIdentity> {
|
||||
if ci.identity.is_null() {
|
||||
return None;
|
||||
}
|
||||
Some(CertificateIdentity {
|
||||
identity: Identity::new_from_capi(ci.identity, false).clone(),
|
||||
locator: if ci.locator.is_null() { None } else { Some(Locator::new_from_capi(ci.locator, false).clone()) },
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn to_capi(&self) -> ztcore::ZT_Certificate_Identity {
|
||||
ztcore::ZT_Certificate_Identity {
|
||||
identity: self.identity.capi,
|
||||
locator: self.locator.capi,
|
||||
locator: if self.locator.is_some() { self.locator.as_ref().unwrap().capi } else { null() },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -375,32 +387,43 @@ pub(crate) struct CertificateSubjectCAPIContainer {
|
|||
}
|
||||
|
||||
impl CertificateSubject {
|
||||
pub(crate) fn new_from_capi(cs: &ztcore::ZT_Certificate_Subject) -> CertificateSubject {
|
||||
pub(crate) unsafe fn new_from_capi(cs: &ztcore::ZT_Certificate_Subject) -> CertificateSubject {
|
||||
unsafe {
|
||||
let cidentities: &[ztcore::ZT_Certificate_Identity] = std::slice::from_raw_parts(cs.identities, cs.identityCount as usize);
|
||||
let mut identities: Vec<CertificateIdentity> = Vec::new();
|
||||
for i in cidentities.iter() {
|
||||
identities.push(CertificateIdentity::new_from_capi(i));
|
||||
if !cs.identities.is_null() && cs.identityCount > 0 {
|
||||
let cidentities: &[ztcore::ZT_Certificate_Identity] = std::slice::from_raw_parts(cs.identities, cs.identityCount as usize);
|
||||
for i in cidentities.iter() {
|
||||
let ci = CertificateIdentity::new_from_capi(i);
|
||||
if ci.is_some() {
|
||||
identities.push(ci.unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let cnetworks: &[ztcore::ZT_Certificate_Network] = std::slice::from_raw_parts(cs.networks, cs.networkCount as usize);
|
||||
let mut networks: Vec<CertificateNetwork> = Vec::new();
|
||||
for i in cnetworks.iter() {
|
||||
networks.push(CertificateNetwork::new_from_capi(i));
|
||||
if !cs.networks.is_null() && cs.networkCount > 0 {
|
||||
let cnetworks: &[ztcore::ZT_Certificate_Network] = std::slice::from_raw_parts(cs.networks, cs.networkCount as usize);
|
||||
for i in cnetworks.iter() {
|
||||
networks.push(CertificateNetwork::new_from_capi(i));
|
||||
}
|
||||
}
|
||||
|
||||
let ccertificates: &[*const u8] = std::slice::from_raw_parts(cs.certificates, cs.certificateCount as usize);
|
||||
let mut certificates: Vec<CertificateSerialNo> = Vec::new();
|
||||
let mut ctmp: [u8; 48] = [0; 48];
|
||||
for i in ccertificates.iter() {
|
||||
copy_nonoverlapping(*i, ctmp.as_mut_ptr(), 48);
|
||||
certificates.push(CertificateSerialNo(ctmp));
|
||||
if !cs.certificates.is_null() && cs.certificateCount > 0 {
|
||||
let ccertificates: &[*const u8] = std::slice::from_raw_parts(cs.certificates, cs.certificateCount as usize);
|
||||
let mut ctmp: [u8; 48] = [0; 48];
|
||||
for i in ccertificates.iter() {
|
||||
copy_nonoverlapping(*i, ctmp.as_mut_ptr(), 48);
|
||||
certificates.push(CertificateSerialNo(ctmp));
|
||||
}
|
||||
}
|
||||
|
||||
let cupdate_urls: &[*const c_char] = std::slice::from_raw_parts(cs.updateURLs, cs.updateURLCount as usize);
|
||||
let mut update_urls: Vec<String> = Vec::new();
|
||||
for i in cupdate_urls.iter() {
|
||||
update_urls.push(CStr::from_ptr(*i).to_str().unwrap().to_string());
|
||||
if !cs.updateURLs.is_null() && cs.updateURLCount > 0 {
|
||||
let cupdate_urls: &[*const c_char] = std::slice::from_raw_parts(cs.updateURLs, cs.updateURLCount as usize);
|
||||
for i in cupdate_urls.iter() {
|
||||
update_urls.push(cstr_to_string(*i, CERTIFICATE_MAX_STRING_LENGTH - 1));
|
||||
}
|
||||
}
|
||||
|
||||
return CertificateSubject {
|
||||
|
@ -417,90 +440,86 @@ impl CertificateSubject {
|
|||
}
|
||||
|
||||
pub(crate) unsafe fn to_capi(&self) -> CertificateSubjectCAPIContainer {
|
||||
unsafe {
|
||||
let mut capi_identities: Vec<ztcore::ZT_Certificate_Identity> = Vec::new();
|
||||
let mut capi_networks: Vec<ztcore::ZT_Certificate_Network> = Vec::new();
|
||||
let mut capi_certificates: Vec<*const u8> = Vec::new();
|
||||
let mut capi_urls: Vec<*const c_char> = Vec::new();
|
||||
let mut capi_urls_strs: Vec<CString> = Vec::new();
|
||||
let mut capi_identities: Vec<ztcore::ZT_Certificate_Identity> = Vec::new();
|
||||
let mut capi_networks: Vec<ztcore::ZT_Certificate_Network> = Vec::new();
|
||||
let mut capi_certificates: Vec<*const u8> = Vec::new();
|
||||
let mut capi_urls: Vec<*const c_char> = Vec::new();
|
||||
let mut capi_urls_strs: Vec<CString> = Vec::new();
|
||||
|
||||
if !self.identities.is_empty() {
|
||||
capi_identities.reserve(self.identities.len());
|
||||
for i in self.identities.iter() {
|
||||
capi_identities.push((*i).to_capi());
|
||||
}
|
||||
}
|
||||
if !self.networks.is_empty() {
|
||||
capi_networks.reserve(self.networks.len());
|
||||
for i in self.networks.iter() {
|
||||
capi_networks.push((*i).to_capi());
|
||||
}
|
||||
}
|
||||
if !self.certificates.is_empty() {
|
||||
capi_certificates.reserve(self.certificates.len());
|
||||
for i in self.certificates.iter() {
|
||||
capi_certificates.push((*i).0.as_ptr());
|
||||
}
|
||||
}
|
||||
if !self.updateURLs.is_empty() {
|
||||
capi_urls.reserve(self.updateURLs.len());
|
||||
for i in self.updateURLs.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());
|
||||
}
|
||||
if !self.identities.is_empty() {
|
||||
capi_identities.reserve(self.identities.len());
|
||||
for i in self.identities.iter() {
|
||||
capi_identities.push(unsafe { (*i).to_capi() });
|
||||
}
|
||||
}
|
||||
if !self.networks.is_empty() {
|
||||
capi_networks.reserve(self.networks.len());
|
||||
for i in self.networks.iter() {
|
||||
capi_networks.push((*i).to_capi());
|
||||
}
|
||||
}
|
||||
if !self.certificates.is_empty() {
|
||||
capi_certificates.reserve(self.certificates.len());
|
||||
for i in self.certificates.iter() {
|
||||
capi_certificates.push((*i).0.as_ptr());
|
||||
}
|
||||
}
|
||||
if !self.updateURLs.is_empty() {
|
||||
capi_urls.reserve(self.updateURLs.len());
|
||||
for i in self.updateURLs.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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CertificateSubjectCAPIContainer {
|
||||
subject: ztcore::ZT_Certificate_Subject {
|
||||
timestamp: self.timestamp,
|
||||
identities: capi_identities.as_mut_ptr(),
|
||||
networks: capi_networks.as_mut_ptr(),
|
||||
certificates: capi_certificates.as_ptr(),
|
||||
updateURLs: capi_urls.as_ptr(),
|
||||
identityCount: capi_identities.len() as c_uint,
|
||||
networkCount: capi_networks.len() as c_uint,
|
||||
certificateCount: capi_certificates.len() as c_uint,
|
||||
updateURLCount: capi_urls.len() as c_uint,
|
||||
name: self.name.to_capi(),
|
||||
uniqueId: self.uniqueId.as_ptr(),
|
||||
uniqueIdProofSignature: self.uniqueIdProofSignature.as_ptr(),
|
||||
uniqueIdSize: self.uniqueId.len() as c_uint,
|
||||
uniqueIdProofSignatureSize: self.uniqueIdProofSignature.len() as c_uint,
|
||||
},
|
||||
subject_identities: capi_identities,
|
||||
subject_networks: capi_networks,
|
||||
subject_certificates: capi_certificates,
|
||||
subject_urls: capi_urls,
|
||||
subject_urls_strs: capi_urls_strs,
|
||||
};
|
||||
CertificateSubjectCAPIContainer {
|
||||
subject: ztcore::ZT_Certificate_Subject {
|
||||
timestamp: self.timestamp,
|
||||
identities: capi_identities.as_mut_ptr(),
|
||||
networks: capi_networks.as_mut_ptr(),
|
||||
certificates: capi_certificates.as_ptr(),
|
||||
updateURLs: capi_urls.as_ptr(),
|
||||
identityCount: capi_identities.len() as c_uint,
|
||||
networkCount: capi_networks.len() as c_uint,
|
||||
certificateCount: capi_certificates.len() as c_uint,
|
||||
updateURLCount: capi_urls.len() as c_uint,
|
||||
name: unsafe { self.name.to_capi() },
|
||||
uniqueId: self.uniqueId.as_ptr(),
|
||||
uniqueIdProofSignature: self.uniqueIdProofSignature.as_ptr(),
|
||||
uniqueIdSize: self.uniqueId.len() as c_uint,
|
||||
uniqueIdProofSignatureSize: self.uniqueIdProofSignature.len() as c_uint,
|
||||
},
|
||||
subject_identities: capi_identities,
|
||||
subject_networks: capi_networks,
|
||||
subject_certificates: capi_certificates,
|
||||
subject_urls: capi_urls,
|
||||
subject_urls_strs: capi_urls_strs,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_csr(&self, uid: Option<&CertificateSubjectUniqueIdSecret>) -> Result<Vec<u8>, ResultCode> {
|
||||
pub fn new_csr(&self, uid: Option<&CertificateSubjectUniqueIdSecret>) -> Result<Box<[u8]>, ResultCode> {
|
||||
let mut csr: Vec<u8> = Vec::new();
|
||||
csr.resize(16384, 0);
|
||||
let mut csr_size: c_int = 16384;
|
||||
|
||||
unsafe {
|
||||
let capi = self.to_capi();
|
||||
|
||||
let mut csr: Vec<u8> = Vec::new();
|
||||
csr.resize(16384, 0);
|
||||
let mut csr_size: c_int = 16384;
|
||||
|
||||
if uid.is_some() {
|
||||
let uid2 = uid.unwrap();
|
||||
if ztcore::ZT_Certificate_newCSR(&capi.subject as *const ztcore::ZT_Certificate_Subject, uid2.public.as_ptr() as *const c_void, uid2.public.len() as c_int, uid2.private.as_ptr() as *const c_void, uid2.private.len() as c_int, csr.as_mut_ptr() as *mut c_void, &mut csr_size as *mut c_int) != 0 {
|
||||
if ztcore::ZT_Certificate_newCSR(&capi.subject as *const ztcore::ZT_Certificate_Subject, uid2.public.as_ptr() as *const c_void, uid2.public.len() as c_int, uid2.private.as_ptr() as *const c_void, uid2.private.len() as c_int, csr.as_mut_ptr() as *mut c_void, &mut csr_size) != 0 {
|
||||
return Err(ResultCode::ErrorBadParameter);
|
||||
}
|
||||
} else {
|
||||
if ztcore::ZT_Certificate_newCSR(&capi.subject, null(), -1, null(), -1, csr.as_mut_ptr() as *mut c_void, &mut csr_size as *mut c_int) != 0 {
|
||||
if ztcore::ZT_Certificate_newCSR(&capi.subject, null(), -1, null(), -1, csr.as_mut_ptr() as *mut c_void, &mut csr_size) != 0 {
|
||||
return Err(ResultCode::ErrorBadParameter);
|
||||
}
|
||||
}
|
||||
csr.resize(csr_size as usize, 0);
|
||||
|
||||
return Ok(csr);
|
||||
}
|
||||
|
||||
return Ok(csr.into_boxed_slice());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -531,14 +550,18 @@ pub(crate) struct CertificateCAPIContainer {
|
|||
}
|
||||
|
||||
impl Certificate {
|
||||
pub(crate) fn new_from_capi(c: &ztcore::ZT_Certificate) -> Certificate {
|
||||
pub(crate) unsafe fn new_from_capi(c: &ztcore::ZT_Certificate) -> Certificate {
|
||||
unsafe {
|
||||
let ccrl: &[*const u8] = std::slice::from_raw_parts(c.crl, c.crlCount as usize);
|
||||
let mut crl: Vec<CertificateSerialNo> = Vec::new();
|
||||
let mut ctmp: [u8; 48] = [0; 48];
|
||||
for i in ccrl.iter() {
|
||||
copy_nonoverlapping(*i, ctmp.as_mut_ptr(), 48);
|
||||
crl.push(CertificateSerialNo(ctmp));
|
||||
if !c.crl.is_null() && c.crlCount > 0 {
|
||||
let ccrl: &[*const u8] = std::slice::from_raw_parts(c.crl, c.crlCount as usize);
|
||||
let mut ctmp: [u8; 48] = [0; 48];
|
||||
for i in ccrl.iter() {
|
||||
if !(*i).is_null() {
|
||||
copy_nonoverlapping(*i, ctmp.as_mut_ptr(), 48);
|
||||
crl.push(CertificateSerialNo(ctmp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Certificate {
|
||||
|
@ -557,85 +580,82 @@ impl Certificate {
|
|||
}
|
||||
}
|
||||
|
||||
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() };
|
||||
CertificateCAPIContainer {
|
||||
certificate: ztcore::ZT_Certificate {
|
||||
serialNo: self.serialNo.0,
|
||||
flags: self.flags,
|
||||
timestamp: self.timestamp,
|
||||
validity: self.validity,
|
||||
subject: subject.subject,
|
||||
issuer: self.issuer.capi,
|
||||
issuerName: unsafe { self.issuerName.to_capi() },
|
||||
extendedAttributes: self.extendedAttributes.as_ptr(),
|
||||
extendedAttributesSize: self.extendedAttributes.len() as c_uint,
|
||||
maxPathLength: self.maxPathLength as c_uint,
|
||||
crl: capi_crls.as_ptr(),
|
||||
crlCount: capi_crls.len() as c_uint,
|
||||
signature: self.signature.as_ptr(),
|
||||
signatureSize: self.signature.len() as c_uint,
|
||||
},
|
||||
certificate_crls: capi_crls,
|
||||
subject_container: subject,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_from_bytes(b: &[u8], verify: bool) -> Result<Certificate, CertificateError> {
|
||||
let mut capi_cert: *const ztcore::ZT_Certificate = null_mut();
|
||||
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));
|
||||
}
|
||||
if capi_cert.is_null() {
|
||||
return Err(CertificateError::InvalidFormat);
|
||||
}
|
||||
unsafe {
|
||||
let mut capi_cert: *const ztcore::ZT_Certificate = null_mut();
|
||||
let capi_verify: c_int = if verify { 1 } else { 0 };
|
||||
let result = 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));
|
||||
}
|
||||
if capi_cert.is_null() {
|
||||
return Err(CertificateError::InvalidFormat);
|
||||
}
|
||||
let cert = Certificate::new_from_capi(&*capi_cert);
|
||||
ztcore::ZT_Certificate_delete(capi_cert);
|
||||
return Ok(cert);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn to_capi(&self) -> CertificateCAPIContainer {
|
||||
unsafe {
|
||||
let subject = self.subject.to_capi();
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
return CertificateCAPIContainer {
|
||||
certificate: ztcore::ZT_Certificate {
|
||||
serialNo: self.serialNo.0,
|
||||
flags: self.flags,
|
||||
timestamp: self.timestamp,
|
||||
validity: self.validity,
|
||||
subject: subject.subject,
|
||||
issuer: self.issuer.capi,
|
||||
issuerName: self.issuerName.to_capi(),
|
||||
extendedAttributes: self.extendedAttributes.as_ptr(),
|
||||
extendedAttributesSize: self.extendedAttributes.len() as c_uint,
|
||||
maxPathLength: self.maxPathLength as c_uint,
|
||||
crl: capi_crls.as_ptr(),
|
||||
crlCount: capi_crls.len() as c_uint,
|
||||
signature: self.signature.as_ptr(),
|
||||
signatureSize: self.signature.len() as c_uint,
|
||||
},
|
||||
certificate_crls: capi_crls,
|
||||
subject_container: subject,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Result<Box<[u8]>, ResultCode> {
|
||||
let mut cert: Vec<u8> = Vec::new();
|
||||
cert.resize(16384, 0);
|
||||
let mut cert_size: c_int = 16384;
|
||||
unsafe {
|
||||
let mut cert: Vec<u8> = Vec::new();
|
||||
cert.resize(16384, 0);
|
||||
let mut cert_size: c_int = 16384;
|
||||
let capi = self.to_capi();
|
||||
if ztcore::ZT_Certificate_encode(&capi.certificate as *const ztcore::ZT_Certificate, cert.as_mut_ptr() as *mut c_void, &mut cert_size) != 0 {
|
||||
return Err(ResultCode::ErrorInternalNonFatal);
|
||||
}
|
||||
cert.resize(cert_size as usize, 0);
|
||||
return Ok(cert.into_boxed_slice());
|
||||
}
|
||||
cert.resize(cert_size as usize, 0);
|
||||
return Ok(cert.into_boxed_slice());
|
||||
}
|
||||
|
||||
pub fn sign(&self, id: &Identity) -> Result<Vec<u8>, ResultCode> {
|
||||
if !id.has_private() {
|
||||
return Err(ResultCode::ErrorBadParameter);
|
||||
}
|
||||
let mut signed_cert: Vec<u8> = Vec::new();
|
||||
signed_cert.resize(16384, 0);
|
||||
let mut signed_cert_size: c_int = 16384;
|
||||
unsafe {
|
||||
let capi = self.to_capi();
|
||||
let mut signed_cert: Vec<u8> = Vec::new();
|
||||
signed_cert.resize(16384, 0);
|
||||
let mut signed_cert_size: c_int = 16384;
|
||||
if ztcore::ZT_Certificate_sign(&capi.certificate as *const ztcore::ZT_Certificate, id.capi, signed_cert.as_mut_ptr() as *mut c_void, &mut signed_cert_size) != 0 {
|
||||
return Err(ResultCode::ErrorBadParameter);
|
||||
}
|
||||
signed_cert.resize(signed_cert_size as usize, 0);
|
||||
return Ok(signed_cert);
|
||||
}
|
||||
signed_cert.resize(signed_cert_size as usize, 0);
|
||||
return Ok(signed_cert);
|
||||
}
|
||||
|
||||
pub fn verify(&self) -> CertificateError {
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
use std::os::raw::{c_char, c_int};
|
||||
use num_derive::{FromPrimitive, ToPrimitive};
|
||||
|
||||
mod bindings;
|
||||
|
||||
mod identity;
|
||||
mod address;
|
||||
mod fingerprint;
|
||||
|
@ -14,13 +18,15 @@ mod buffer;
|
|||
mod portableatomici64;
|
||||
mod virtualnetworkconfig;
|
||||
|
||||
pub use identity::{Identity, IdentityType};
|
||||
use bindings::capi as ztcore;
|
||||
|
||||
pub use identity::*;
|
||||
pub use address::Address;
|
||||
pub use fingerprint::Fingerprint;
|
||||
pub use endpoint::Endpoint;
|
||||
pub use certificate::*;
|
||||
pub use networkid::NetworkId;
|
||||
pub use locator::Locator;
|
||||
pub use certificate::*;
|
||||
pub use path::Path;
|
||||
pub use peer::Peer;
|
||||
pub use node::Node;
|
||||
|
@ -29,10 +35,6 @@ pub use buffer::Buffer;
|
|||
pub use portableatomici64::PortableAtomicI64;
|
||||
pub use virtualnetworkconfig::*;
|
||||
|
||||
use bindings::capi as ztcore;
|
||||
use num_derive::{FromPrimitive, ToPrimitive};
|
||||
use std::os::raw::c_int;
|
||||
|
||||
pub const DEFAULT_PORT: u16 = ztcore::ZT_DEFAULT_PORT as u16;
|
||||
|
||||
pub const BUF_SIZE: u32 = ztcore::ZT_BUF_SIZE;
|
||||
|
@ -182,6 +184,24 @@ pub fn now() -> i64 {
|
|||
(std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_millis() & 0x7fffffffffffffff) as i64
|
||||
}
|
||||
|
||||
/// The CStr stuff is cumbersome, so this is an easier to use function to turn a C string into a String.
|
||||
/// This returns an empty string on a null pointer or invalid UTF-8. It's unsafe because it can crash if
|
||||
/// the string is not zero-terminated. A size limit can be passed in if available to reduce this risk, or
|
||||
/// the max_len parameter can be -1 if there is no known limit.
|
||||
pub unsafe fn cstr_to_string(cstr: *const c_char, max_len: isize) -> String {
|
||||
if !cstr.is_null() {
|
||||
let mut cstr_len: isize = 0;
|
||||
while max_len < 0 || cstr_len < max_len {
|
||||
if (unsafe { *cstr.offset(cstr_len) } == 0) {
|
||||
break;
|
||||
}
|
||||
cstr_len += 1;
|
||||
}
|
||||
return String::from(std::str::from_utf8(unsafe { std::slice::from_raw_parts(cstr as *const u8, cstr_len as usize) }).unwrap_or(""));
|
||||
}
|
||||
String::new()
|
||||
}
|
||||
|
||||
#[macro_export(crate)]
|
||||
macro_rules! implement_to_from_json {
|
||||
($struct_name:ident) => {
|
||||
|
@ -204,11 +224,3 @@ macro_rules! implement_to_from_json {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn it_works() {
|
||||
assert_eq!(2 + 2, 4);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue