mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-05-08 14:43:44 +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::*;
|
||||||
use crate::bindings::capi as ztcore;
|
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).
|
/// 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.
|
/// 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;
|
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]);
|
pub struct CertificateSerialNo(pub [u8; 48]);
|
||||||
|
|
||||||
impl CertificateSerialNo {
|
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> {
|
pub fn new_from_string(s: &str) -> Result<CertificateSerialNo, ResultCode> {
|
||||||
let b = hex::decode(s);
|
let b = hex::decode(s);
|
||||||
if b.is_err() {
|
if b.is_err() {
|
||||||
return Err(ResultCode::ErrorBadParameter);
|
return Err(ResultCode::ErrorBadParameter);
|
||||||
}
|
}
|
||||||
return Ok(CertificateSerialNo::from(b.unwrap()));
|
return Ok(CertificateSerialNo::from(b.unwrap().as_slice()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Vec<u8>> for CertificateSerialNo {
|
impl From<&[u8; 48]> for CertificateSerialNo {
|
||||||
fn from(v: Vec<u8>) -> CertificateSerialNo {
|
fn from(a: &[u8; 48]) -> CertificateSerialNo {
|
||||||
|
CertificateSerialNo(*a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&[u8]> for CertificateSerialNo {
|
||||||
|
fn from(v: &[u8]) -> CertificateSerialNo {
|
||||||
let mut l = v.len();
|
let mut l = v.len();
|
||||||
if l > 48 {
|
if l > 48 {
|
||||||
l = 48;
|
l = 48;
|
||||||
}
|
}
|
||||||
unsafe {
|
let mut s = CertificateSerialNo::new();
|
||||||
let mut r: [u8; 48] = MaybeUninit::uninit().assume_init();
|
s.0[0..l].copy_from_slice(&v[0..l]);
|
||||||
copy_nonoverlapping(v.as_ptr(), r.as_mut_ptr(), l);
|
s
|
||||||
while l < 48 {
|
|
||||||
r[l] = 0;
|
|
||||||
l += 1;
|
|
||||||
}
|
|
||||||
return CertificateSerialNo(r);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,22 +165,24 @@ pub struct CertificateSubjectUniqueIdSecret {
|
||||||
pub type_: CertificateUniqueIdType,
|
pub type_: CertificateUniqueIdType,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CERTIFICATE_UNIQUE_ID_CREATE_BUF_SIZE: usize = 128;
|
||||||
|
|
||||||
impl CertificateSubjectUniqueIdSecret {
|
impl CertificateSubjectUniqueIdSecret {
|
||||||
pub fn new(t: CertificateUniqueIdType) -> Self {
|
pub fn new(t: CertificateUniqueIdType) -> Self {
|
||||||
unsafe {
|
let mut unique_id: [u8; CERTIFICATE_UNIQUE_ID_CREATE_BUF_SIZE] = [0; CERTIFICATE_UNIQUE_ID_CREATE_BUF_SIZE];
|
||||||
let mut unique_id: [u8; 128] = zeroed();
|
let mut unique_id_private: [u8; CERTIFICATE_UNIQUE_ID_CREATE_BUF_SIZE] = [0; CERTIFICATE_UNIQUE_ID_CREATE_BUF_SIZE];
|
||||||
let mut unique_id_private: [u8; 128] = zeroed();
|
let mut unique_id_size = CERTIFICATE_UNIQUE_ID_CREATE_BUF_SIZE as c_int;
|
||||||
let mut unique_id_size: c_int = unique_id.len() as c_int;
|
let mut unique_id_private_size = CERTIFICATE_UNIQUE_ID_CREATE_BUF_SIZE 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();
|
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 {
|
unsafe {
|
||||||
|
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.");
|
panic!("fatal internal error: ZT_Certificate_newSubjectUniqueId failed.");
|
||||||
}
|
}
|
||||||
return CertificateSubjectUniqueIdSecret {
|
}
|
||||||
|
CertificateSubjectUniqueIdSecret {
|
||||||
public: Vec::from(&unique_id[0..unique_id_size as usize]),
|
public: Vec::from(&unique_id[0..unique_id_size as usize]),
|
||||||
private: Vec::from(&unique_id_private[0..unique_id_private_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_u32(ct as u32).unwrap(),
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -235,7 +244,27 @@ pub struct CertificateName {
|
||||||
pub host: String,
|
pub host: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn str_to_cert_cstr(s: &String, cs: &mut [c_char; 128]) {
|
impl CertificateName {
|
||||||
|
pub(crate) unsafe fn new_from_capi(cn: &ztcore::ZT_Certificate_Name) -> CertificateName {
|
||||||
|
unsafe {
|
||||||
|
return CertificateName {
|
||||||
|
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();
|
let mut l = s.len();
|
||||||
if l == 0 {
|
if l == 0 {
|
||||||
cs[0] = 0;
|
cs[0] = 0;
|
||||||
|
@ -248,43 +277,23 @@ unsafe fn str_to_cert_cstr(s: &String, cs: &mut [c_char; 128]) {
|
||||||
copy_nonoverlapping(s.as_ptr(), cs.as_mut_ptr() as *mut u8, l);
|
copy_nonoverlapping(s.as_ptr(), cs.as_mut_ptr() as *mut u8, l);
|
||||||
}
|
}
|
||||||
cs[l + 1] = 0;
|
cs[l + 1] = 0;
|
||||||
}
|
|
||||||
|
|
||||||
impl CertificateName {
|
|
||||||
pub(crate) 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()),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
||||||
str_to_cert_cstr(&self.serialNo, &mut cn.serialNo);
|
Self::str_to_cert_cstr(&self.serialNo, &mut cn.serialNo);
|
||||||
str_to_cert_cstr(&self.commonName, &mut cn.commonName);
|
Self::str_to_cert_cstr(&self.commonName, &mut cn.commonName);
|
||||||
str_to_cert_cstr(&self.country, &mut cn.country);
|
Self::str_to_cert_cstr(&self.country, &mut cn.country);
|
||||||
str_to_cert_cstr(&self.organization, &mut cn.organization);
|
Self::str_to_cert_cstr(&self.organization, &mut cn.organization);
|
||||||
str_to_cert_cstr(&self.unit, &mut cn.unit);
|
Self::str_to_cert_cstr(&self.unit, &mut cn.unit);
|
||||||
str_to_cert_cstr(&self.locality, &mut cn.locality);
|
Self::str_to_cert_cstr(&self.locality, &mut cn.locality);
|
||||||
str_to_cert_cstr(&self.province, &mut cn.province);
|
Self::str_to_cert_cstr(&self.province, &mut cn.province);
|
||||||
str_to_cert_cstr(&self.streetAddress, &mut cn.streetAddress);
|
Self::str_to_cert_cstr(&self.streetAddress, &mut cn.streetAddress);
|
||||||
str_to_cert_cstr(&self.postalCode, &mut cn.postalCode);
|
Self::str_to_cert_cstr(&self.postalCode, &mut cn.postalCode);
|
||||||
str_to_cert_cstr(&self.email, &mut cn.email);
|
Self::str_to_cert_cstr(&self.email, &mut cn.email);
|
||||||
str_to_cert_cstr(&self.url, &mut cn.url);
|
Self::str_to_cert_cstr(&self.url, &mut cn.url);
|
||||||
str_to_cert_cstr(&self.host, &mut cn.host);
|
Self::str_to_cert_cstr(&self.host, &mut cn.host);
|
||||||
return cn;
|
return cn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -329,21 +338,24 @@ implement_to_from_json!(CertificateNetwork);
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct CertificateIdentity {
|
pub struct CertificateIdentity {
|
||||||
pub identity: Identity,
|
pub identity: Identity,
|
||||||
pub locator: Locator,
|
pub locator: Option<Locator>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CertificateIdentity {
|
impl CertificateIdentity {
|
||||||
pub(crate) fn new_from_capi(ci: &ztcore::ZT_Certificate_Identity) -> CertificateIdentity {
|
pub(crate) unsafe fn new_from_capi(ci: &ztcore::ZT_Certificate_Identity) -> Option<CertificateIdentity> {
|
||||||
CertificateIdentity {
|
if ci.identity.is_null() {
|
||||||
identity: Identity::new_from_capi(ci.identity, false).clone(),
|
return None;
|
||||||
locator: Locator::new_from_capi(ci.locator, false).clone(),
|
|
||||||
}
|
}
|
||||||
|
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 {
|
pub(crate) unsafe fn to_capi(&self) -> ztcore::ZT_Certificate_Identity {
|
||||||
ztcore::ZT_Certificate_Identity {
|
ztcore::ZT_Certificate_Identity {
|
||||||
identity: self.identity.capi,
|
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 {
|
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 {
|
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();
|
let mut identities: Vec<CertificateIdentity> = Vec::new();
|
||||||
|
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() {
|
for i in cidentities.iter() {
|
||||||
identities.push(CertificateIdentity::new_from_capi(i));
|
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();
|
let mut networks: Vec<CertificateNetwork> = Vec::new();
|
||||||
|
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() {
|
for i in cnetworks.iter() {
|
||||||
networks.push(CertificateNetwork::new_from_capi(i));
|
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 certificates: Vec<CertificateSerialNo> = Vec::new();
|
||||||
|
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];
|
let mut ctmp: [u8; 48] = [0; 48];
|
||||||
for i in ccertificates.iter() {
|
for i in ccertificates.iter() {
|
||||||
copy_nonoverlapping(*i, ctmp.as_mut_ptr(), 48);
|
copy_nonoverlapping(*i, ctmp.as_mut_ptr(), 48);
|
||||||
certificates.push(CertificateSerialNo(ctmp));
|
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();
|
let mut update_urls: Vec<String> = Vec::new();
|
||||||
|
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() {
|
for i in cupdate_urls.iter() {
|
||||||
update_urls.push(CStr::from_ptr(*i).to_str().unwrap().to_string());
|
update_urls.push(cstr_to_string(*i, CERTIFICATE_MAX_STRING_LENGTH - 1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return CertificateSubject {
|
return CertificateSubject {
|
||||||
|
@ -417,7 +440,6 @@ impl CertificateSubject {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) unsafe fn to_capi(&self) -> CertificateSubjectCAPIContainer {
|
pub(crate) unsafe fn to_capi(&self) -> CertificateSubjectCAPIContainer {
|
||||||
unsafe {
|
|
||||||
let mut capi_identities: Vec<ztcore::ZT_Certificate_Identity> = 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_networks: Vec<ztcore::ZT_Certificate_Network> = Vec::new();
|
||||||
let mut capi_certificates: Vec<*const u8> = Vec::new();
|
let mut capi_certificates: Vec<*const u8> = Vec::new();
|
||||||
|
@ -427,7 +449,7 @@ impl CertificateSubject {
|
||||||
if !self.identities.is_empty() {
|
if !self.identities.is_empty() {
|
||||||
capi_identities.reserve(self.identities.len());
|
capi_identities.reserve(self.identities.len());
|
||||||
for i in self.identities.iter() {
|
for i in self.identities.iter() {
|
||||||
capi_identities.push((*i).to_capi());
|
capi_identities.push(unsafe { (*i).to_capi() });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !self.networks.is_empty() {
|
if !self.networks.is_empty() {
|
||||||
|
@ -453,7 +475,7 @@ impl CertificateSubject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return CertificateSubjectCAPIContainer {
|
CertificateSubjectCAPIContainer {
|
||||||
subject: ztcore::ZT_Certificate_Subject {
|
subject: ztcore::ZT_Certificate_Subject {
|
||||||
timestamp: self.timestamp,
|
timestamp: self.timestamp,
|
||||||
identities: capi_identities.as_mut_ptr(),
|
identities: capi_identities.as_mut_ptr(),
|
||||||
|
@ -464,7 +486,7 @@ impl CertificateSubject {
|
||||||
networkCount: capi_networks.len() as c_uint,
|
networkCount: capi_networks.len() as c_uint,
|
||||||
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: self.name.to_capi(),
|
name: unsafe { self.name.to_capi() },
|
||||||
uniqueId: self.uniqueId.as_ptr(),
|
uniqueId: self.uniqueId.as_ptr(),
|
||||||
uniqueIdProofSignature: self.uniqueIdProofSignature.as_ptr(),
|
uniqueIdProofSignature: self.uniqueIdProofSignature.as_ptr(),
|
||||||
uniqueIdSize: self.uniqueId.len() as c_uint,
|
uniqueIdSize: self.uniqueId.len() as c_uint,
|
||||||
|
@ -475,32 +497,29 @@ impl CertificateSubject {
|
||||||
subject_certificates: capi_certificates,
|
subject_certificates: capi_certificates,
|
||||||
subject_urls: capi_urls,
|
subject_urls: capi_urls,
|
||||||
subject_urls_strs: capi_urls_strs,
|
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> {
|
||||||
unsafe {
|
|
||||||
let capi = self.to_capi();
|
|
||||||
|
|
||||||
let mut csr: Vec<u8> = Vec::new();
|
let mut csr: Vec<u8> = Vec::new();
|
||||||
csr.resize(16384, 0);
|
csr.resize(16384, 0);
|
||||||
let mut csr_size: c_int = 16384;
|
let mut csr_size: c_int = 16384;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let capi = self.to_capi();
|
||||||
if uid.is_some() {
|
if uid.is_some() {
|
||||||
let uid2 = uid.unwrap();
|
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);
|
return Err(ResultCode::ErrorBadParameter);
|
||||||
}
|
}
|
||||||
} else {
|
} 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);
|
return Err(ResultCode::ErrorBadParameter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
csr.resize(csr_size as usize, 0);
|
|
||||||
|
|
||||||
return Ok(csr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Ok(csr.into_boxed_slice());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,15 +550,19 @@ pub(crate) struct CertificateCAPIContainer {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Certificate {
|
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 {
|
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 crl: Vec<CertificateSerialNo> = Vec::new();
|
||||||
|
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];
|
let mut ctmp: [u8; 48] = [0; 48];
|
||||||
for i in ccrl.iter() {
|
for i in ccrl.iter() {
|
||||||
|
if !(*i).is_null() {
|
||||||
copy_nonoverlapping(*i, ctmp.as_mut_ptr(), 48);
|
copy_nonoverlapping(*i, ctmp.as_mut_ptr(), 48);
|
||||||
crl.push(CertificateSerialNo(ctmp));
|
crl.push(CertificateSerialNo(ctmp));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Certificate {
|
return Certificate {
|
||||||
serialNo: CertificateSerialNo(c.serialNo),
|
serialNo: CertificateSerialNo(c.serialNo),
|
||||||
|
@ -557,34 +580,15 @@ impl Certificate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_from_bytes(b: &[u8], verify: bool) -> Result<Certificate, CertificateError> {
|
|
||||||
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 {
|
pub(crate) unsafe fn to_capi(&self) -> CertificateCAPIContainer {
|
||||||
unsafe {
|
|
||||||
let subject = self.subject.to_capi();
|
|
||||||
|
|
||||||
let mut capi_crls: Vec<*const u8> = Vec::new();
|
let mut capi_crls: Vec<*const u8> = Vec::new();
|
||||||
capi_crls.reserve(self.crl.len());
|
capi_crls.reserve(self.crl.len());
|
||||||
for i in self.crl.iter() {
|
for i in self.crl.iter() {
|
||||||
capi_crls.push((*i).0.as_ptr());
|
capi_crls.push((*i).0.as_ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
return CertificateCAPIContainer {
|
let subject = unsafe { self.subject.to_capi() };
|
||||||
|
CertificateCAPIContainer {
|
||||||
certificate: ztcore::ZT_Certificate {
|
certificate: ztcore::ZT_Certificate {
|
||||||
serialNo: self.serialNo.0,
|
serialNo: self.serialNo.0,
|
||||||
flags: self.flags,
|
flags: self.flags,
|
||||||
|
@ -592,7 +596,7 @@ impl Certificate {
|
||||||
validity: self.validity,
|
validity: self.validity,
|
||||||
subject: subject.subject,
|
subject: subject.subject,
|
||||||
issuer: self.issuer.capi,
|
issuer: self.issuer.capi,
|
||||||
issuerName: self.issuerName.to_capi(),
|
issuerName: unsafe { self.issuerName.to_capi() },
|
||||||
extendedAttributes: self.extendedAttributes.as_ptr(),
|
extendedAttributes: self.extendedAttributes.as_ptr(),
|
||||||
extendedAttributesSize: self.extendedAttributes.len() as c_uint,
|
extendedAttributesSize: self.extendedAttributes.len() as c_uint,
|
||||||
maxPathLength: self.maxPathLength as c_uint,
|
maxPathLength: self.maxPathLength as c_uint,
|
||||||
|
@ -603,40 +607,56 @@ impl Certificate {
|
||||||
},
|
},
|
||||||
certificate_crls: capi_crls,
|
certificate_crls: capi_crls,
|
||||||
subject_container: subject,
|
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 cert = Certificate::new_from_capi(&*capi_cert);
|
||||||
|
ztcore::ZT_Certificate_delete(capi_cert);
|
||||||
|
return Ok(cert);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_bytes(&self) -> Result<Box<[u8]>, ResultCode> {
|
pub fn to_bytes(&self) -> Result<Box<[u8]>, ResultCode> {
|
||||||
unsafe {
|
|
||||||
let mut cert: Vec<u8> = Vec::new();
|
let mut cert: Vec<u8> = Vec::new();
|
||||||
cert.resize(16384, 0);
|
cert.resize(16384, 0);
|
||||||
let mut cert_size: c_int = 16384;
|
let mut cert_size: c_int = 16384;
|
||||||
|
unsafe {
|
||||||
let capi = self.to_capi();
|
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 {
|
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);
|
return Err(ResultCode::ErrorInternalNonFatal);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
cert.resize(cert_size as usize, 0);
|
cert.resize(cert_size as usize, 0);
|
||||||
return Ok(cert.into_boxed_slice());
|
return Ok(cert.into_boxed_slice());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn sign(&self, id: &Identity) -> Result<Vec<u8>, ResultCode> {
|
pub fn sign(&self, id: &Identity) -> Result<Vec<u8>, ResultCode> {
|
||||||
if !id.has_private() {
|
if !id.has_private() {
|
||||||
return Err(ResultCode::ErrorBadParameter);
|
return Err(ResultCode::ErrorBadParameter);
|
||||||
}
|
}
|
||||||
unsafe {
|
|
||||||
let capi = self.to_capi();
|
|
||||||
let mut signed_cert: Vec<u8> = Vec::new();
|
let mut signed_cert: Vec<u8> = Vec::new();
|
||||||
signed_cert.resize(16384, 0);
|
signed_cert.resize(16384, 0);
|
||||||
let mut signed_cert_size: c_int = 16384;
|
let mut signed_cert_size: c_int = 16384;
|
||||||
|
unsafe {
|
||||||
|
let capi = self.to_capi();
|
||||||
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 {
|
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);
|
return Err(ResultCode::ErrorBadParameter);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
signed_cert.resize(signed_cert_size as usize, 0);
|
signed_cert.resize(signed_cert_size as usize, 0);
|
||||||
return Ok(signed_cert);
|
return Ok(signed_cert);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn verify(&self) -> CertificateError {
|
pub fn verify(&self) -> CertificateError {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
|
use std::os::raw::{c_char, c_int};
|
||||||
|
use num_derive::{FromPrimitive, ToPrimitive};
|
||||||
|
|
||||||
mod bindings;
|
mod bindings;
|
||||||
|
|
||||||
mod identity;
|
mod identity;
|
||||||
mod address;
|
mod address;
|
||||||
mod fingerprint;
|
mod fingerprint;
|
||||||
|
@ -14,13 +18,15 @@ mod buffer;
|
||||||
mod portableatomici64;
|
mod portableatomici64;
|
||||||
mod virtualnetworkconfig;
|
mod virtualnetworkconfig;
|
||||||
|
|
||||||
pub use identity::{Identity, IdentityType};
|
use bindings::capi as ztcore;
|
||||||
|
|
||||||
|
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::Endpoint;
|
||||||
|
pub use certificate::*;
|
||||||
pub use networkid::NetworkId;
|
pub use networkid::NetworkId;
|
||||||
pub use locator::Locator;
|
pub use locator::Locator;
|
||||||
pub use certificate::*;
|
|
||||||
pub use path::Path;
|
pub use path::Path;
|
||||||
pub use peer::Peer;
|
pub use peer::Peer;
|
||||||
pub use node::Node;
|
pub use node::Node;
|
||||||
|
@ -29,10 +35,6 @@ pub use buffer::Buffer;
|
||||||
pub use portableatomici64::PortableAtomicI64;
|
pub use portableatomici64::PortableAtomicI64;
|
||||||
pub use virtualnetworkconfig::*;
|
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 DEFAULT_PORT: u16 = ztcore::ZT_DEFAULT_PORT as u16;
|
||||||
|
|
||||||
pub const BUF_SIZE: u32 = ztcore::ZT_BUF_SIZE;
|
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
|
(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_export(crate)]
|
||||||
macro_rules! implement_to_from_json {
|
macro_rules! implement_to_from_json {
|
||||||
($struct_name:ident) => {
|
($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