V2 network controller now provides a reply that at least parses!

This commit is contained in:
Adam Ierymenko 2022-10-28 16:03:06 -04:00
parent bc31c35ae8
commit bc7a9e41bf
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
5 changed files with 39 additions and 33 deletions

View file

@ -276,14 +276,16 @@ impl Controller {
tags: HashMap::new(), tags: HashMap::new(),
}; };
let mut coo = vl2::v1::CertificateOfOwnership::new(network_id, now, source_identity.address); if !nc.static_ips.is_empty() {
for ip in nc.static_ips.iter() { let mut coo = vl2::v1::CertificateOfOwnership::new(network_id, now, source_identity.address);
coo.add_ip(ip); for ip in nc.static_ips.iter() {
coo.add_ip(ip);
}
if !coo.sign(&self.local_identity, &source_identity) {
return Ok((AuthorizationResult::RejectedDueToError, None, None));
}
v1cred.certificates_of_ownership.push(coo);
} }
if !coo.sign(&self.local_identity, &source_identity) {
return Ok((AuthorizationResult::RejectedDueToError, None, None));
}
v1cred.certificates_of_ownership.push(coo);
for (id, value) in member.tags.iter() { for (id, value) in member.tags.iter() {
let tag = vl2::v1::Tag::new(*id, *value, &self.local_identity, network_id, &source_identity, now); let tag = vl2::v1::Tag::new(*id, *value, &self.local_identity, network_id, &source_identity, now);
@ -417,6 +419,7 @@ impl InnerProtocol for Controller {
let (result, config) = match self2.get_network_config(&peer.identity, network_id, now).await { let (result, config) = match self2.get_network_config(&peer.identity, network_id, now).await {
Result::Ok((result, Some(config), revocations)) => { Result::Ok((result, Some(config), revocations)) => {
dump_network_config(&config);
self2.send_network_config(peer.as_ref(), &config, Some(message_id)); self2.send_network_config(peer.as_ref(), &config, Some(message_id));
(result, Some(config)) (result, Some(config))
} }

View file

@ -113,6 +113,7 @@ pub struct Network {
pub min_supported_version: Option<u32>, pub min_supported_version: Option<u32>,
/// MTU inside the virtual network, default of 2800 is used if not set. /// MTU inside the virtual network, default of 2800 is used if not set.
#[serde(skip_serializing_if = "Option::is_none")]
pub mtu: Option<u16>, pub mtu: Option<u16>,
/// If true the network has access control, which is usually what you want. /// If true the network has access control, which is usually what you want.

View file

@ -122,6 +122,8 @@ impl NetworkConfig {
pub fn v1_proto_to_dictionary(&self, controller_identity: &Identity) -> Option<Dictionary> { pub fn v1_proto_to_dictionary(&self, controller_identity: &Identity) -> Option<Dictionary> {
let mut d = Dictionary::new(); let mut d = Dictionary::new();
d.set_u64(proto_v1_field_name::network_config::VERSION, 6);
d.set_str( d.set_str(
proto_v1_field_name::network_config::NETWORK_ID, proto_v1_field_name::network_config::NETWORK_ID,
self.network_id.to_string().as_str(), self.network_id.to_string().as_str(),
@ -191,7 +193,11 @@ impl NetworkConfig {
if let Some(v1cred) = self.v1_credentials.as_ref() { if let Some(v1cred) = self.v1_credentials.as_ref() {
d.set_bytes( d.set_bytes(
proto_v1_field_name::network_config::CERTIFICATE_OF_MEMBERSHIP, proto_v1_field_name::network_config::CERTIFICATE_OF_MEMBERSHIP,
v1cred.certificate_of_membership.to_bytes()?.as_bytes().to_vec(), v1cred
.certificate_of_membership
.to_bytes(self.network_id.network_controller())
.as_bytes()
.to_vec(),
); );
if !v1cred.certificates_of_ownership.is_empty() { if !v1cred.certificates_of_ownership.is_empty() {

View file

@ -19,7 +19,7 @@ pub struct CertificateOfMembership {
pub timestamp: i64, pub timestamp: i64,
pub max_delta: i64, pub max_delta: i64,
pub issued_to: Address, pub issued_to: Address,
pub issued_to_fingerprint: Blob<{ Identity::FINGERPRINT_SIZE }>, pub issued_to_fingerprint: Blob<32>,
pub signature: ArrayVec<u8, { Identity::MAX_SIGNATURE_SIZE }>, pub signature: ArrayVec<u8, { Identity::MAX_SIGNATURE_SIZE }>,
} }
@ -36,7 +36,7 @@ impl CertificateOfMembership {
signature: ArrayVec::new(), signature: ArrayVec::new(),
}; };
com.issued_to_fingerprint = Blob::from(Self::v1_proto_issued_to_fingerprint(issued_to, Some(issuer.address))); com.issued_to_fingerprint = Blob::from(Self::v1_proto_issued_to_fingerprint(issued_to));
if let Some(signature) = issuer.sign(&com.v1_proto_get_qualifier_bytes(), true) { if let Some(signature) = issuer.sign(&com.v1_proto_get_qualifier_bytes(), true) {
com.signature = signature; com.signature = signature;
Some(com) Some(com)
@ -77,32 +77,25 @@ impl CertificateOfMembership {
*memory::as_byte_array(&q) *memory::as_byte_array(&q)
} }
fn v1_proto_issued_to_fingerprint(issued_to: &Identity, signed_by: Option<Address>) -> [u8; 48] { /// Get the identity fingerprint used in V1, which only covers the curve25519 keys.
fn v1_proto_issued_to_fingerprint(issued_to: &Identity) -> [u8; 32] {
let mut v1_signee_hasher = SHA384::new(); let mut v1_signee_hasher = SHA384::new();
v1_signee_hasher.update(&issued_to.address.to_bytes()); v1_signee_hasher.update(&issued_to.address.to_bytes());
v1_signee_hasher.update(&issued_to.x25519); v1_signee_hasher.update(&issued_to.x25519);
v1_signee_hasher.update(&issued_to.ed25519); v1_signee_hasher.update(&issued_to.ed25519);
let mut fp = v1_signee_hasher.finish(); (&v1_signee_hasher.finish()[..32]).try_into().unwrap()
fp[32..].fill(0);
if let Some(signed_by) = signed_by {
fp[32..37].copy_from_slice(&signed_by.to_bytes());
}
fp
} }
/// Get this certificate of membership in byte encoded format. /// Get this certificate of membership in byte encoded format.
pub fn to_bytes(&self) -> Option<ArrayVec<u8, 384>> { pub fn to_bytes(&self, controller_address: Address) -> ArrayVec<u8, 384> {
if self.signature.len() == 96 { let mut v = ArrayVec::new();
let mut v = ArrayVec::new(); v.push(1); // version byte from v1 protocol
v.push(1); // version byte from v1 protocol v.push(0);
v.push(0); v.push(7); // 7 qualifiers, big-endian 16-bit
v.push(7); // 7 qualifiers, big-endian 16-bit let _ = v.write_all(&self.v1_proto_get_qualifier_bytes());
let _ = v.write_all(&self.v1_proto_get_qualifier_bytes()); let _ = v.write_all(&controller_address.to_bytes());
let _ = v.write_all(&self.issued_to_fingerprint.as_bytes()[32..38]); // issuer address let _ = v.write_all(self.signature.as_bytes());
let _ = v.write_all(self.signature.as_bytes()); v
return Some(v);
}
return None;
} }
/// Decode a V1 legacy format certificate of membership in byte format. /// Decode a V1 legacy format certificate of membership in byte format.
@ -117,7 +110,7 @@ impl CertificateOfMembership {
return Err(InvalidParameterError("incomplete")); return Err(InvalidParameterError("incomplete"));
} }
let (mut network_id, mut issued_to, mut timestamp, mut max_delta, mut v1_fingerprint) = (0, 0, 0, 0, [0u8; 48]); let (mut network_id, mut issued_to, mut timestamp, mut max_delta, mut v1_fingerprint) = (0, 0, 0, 0, [0u8; 32]);
for _ in 0..qualifier_count { for _ in 0..qualifier_count {
let qt = u64::from_be_bytes(b[..8].try_into().unwrap()); let qt = u64::from_be_bytes(b[..8].try_into().unwrap());
let q: [u8; 8] = b[8..16].try_into().unwrap(); let q: [u8; 8] = b[8..16].try_into().unwrap();
@ -150,8 +143,7 @@ impl CertificateOfMembership {
b = &b[24..]; b = &b[24..];
} }
v1_fingerprint[32..38].copy_from_slice(&b[..5]); // issuer address b = &b[5..]; // skip issuer address which is always the controller
b = &b[5..];
Ok(Self { Ok(Self {
network_id: NetworkId::from_u64(network_id).ok_or(InvalidParameterError("invalid network ID"))?, network_id: NetworkId::from_u64(network_id).ok_or(InvalidParameterError("invalid network ID"))?,
@ -169,7 +161,7 @@ impl CertificateOfMembership {
/// Verify this certificate of membership. /// Verify this certificate of membership.
pub fn verify(self, issuer: &Identity, expect_issued_to: &Identity) -> Option<Verified<Self>> { pub fn verify(self, issuer: &Identity, expect_issued_to: &Identity) -> Option<Verified<Self>> {
if Self::v1_proto_issued_to_fingerprint(expect_issued_to, None).eq(&self.issued_to_fingerprint.as_bytes()[..32]) { if Self::v1_proto_issued_to_fingerprint(expect_issued_to).eq(&self.issued_to_fingerprint.as_bytes()[..32]) {
if issuer.verify(&self.v1_proto_get_qualifier_bytes(), self.signature.as_bytes()) { if issuer.verify(&self.v1_proto_get_qualifier_bytes(), self.signature.as_bytes()) {
return Some(Verified(self)); return Some(Verified(self));
} }

View file

@ -65,6 +65,7 @@ impl<const L: usize> ToString for Blob<L> {
} }
impl<const L: usize> Serialize for Blob<L> { impl<const L: usize> Serialize for Blob<L> {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where where
S: Serializer, S: Serializer,
@ -82,10 +83,12 @@ struct BlobVisitor<const L: usize>;
impl<'de, const L: usize> serde::de::Visitor<'de> for BlobVisitor<L> { impl<'de, const L: usize> serde::de::Visitor<'de> for BlobVisitor<L> {
type Value = Blob<L>; type Value = Blob<L>;
#[inline]
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str(format!("array of {} bytes", L).as_str()) formatter.write_str(format!("array of {} bytes", L).as_str())
} }
#[inline]
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error> fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where where
A: serde::de::SeqAccess<'de>, A: serde::de::SeqAccess<'de>,
@ -99,6 +102,7 @@ impl<'de, const L: usize> serde::de::Visitor<'de> for BlobVisitor<L> {
} }
impl<'de, const L: usize> Deserialize<'de> for Blob<L> { impl<'de, const L: usize> Deserialize<'de> for Blob<L> {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Blob<L>, D::Error> fn deserialize<D>(deserializer: D) -> Result<Blob<L>, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,