Skip to content

Commit

Permalink
Parse an IP address into SANType from a x509 GeneralName.
Browse files Browse the repository at this point in the history
  • Loading branch information
iamjpotts authored and est31 committed Oct 11, 2022
1 parent e8a127b commit c2bcdbf
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/target
**/*.rs.bk
certs/
.idea
91 changes: 91 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ use std::fmt;
use std::convert::TryFrom;
use std::error::Error;
use std::net::IpAddr;
#[cfg(feature = "x509-parser")]
use std::net::{Ipv4Addr, Ipv6Addr};
use std::str::FromStr;
use std::hash::{Hash, Hasher};

Expand Down Expand Up @@ -159,6 +161,19 @@ pub enum SanType {
IpAddress(IpAddr),
}

#[cfg(feature = "x509-parser")]
fn ip_addr_from_octets(octets: &[u8]) -> Result<IpAddr, RcgenError> {
if let Ok(ipv6_octets) = <&[u8; 16]>::try_from(octets) {
Ok(Ipv6Addr::from(*ipv6_octets).into())
}
else if let Ok(ipv4_octets) = <&[u8; 4]>::try_from(octets) {
Ok(Ipv4Addr::from(*ipv4_octets).into())
}
else {
Err(RcgenError::InvalidIpAddressOctetLength(octets.len()))
}
}

impl SanType {
#[cfg(feature = "x509-parser")]
fn try_from_general(name :&x509_parser::extensions::GeneralName<'_>) -> Result<Self, RcgenError> {
Expand All @@ -172,6 +187,9 @@ impl SanType {
x509_parser::extensions::GeneralName::URI(name) => {
SanType::URI((*name).into())
}
x509_parser::extensions::GeneralName::IPAddress(octets) => {
SanType::IpAddress(ip_addr_from_octets(octets)?)
}
_ => return Err(RcgenError::InvalidNameType),
})
}
Expand Down Expand Up @@ -1585,6 +1603,8 @@ pub enum RcgenError {
#[cfg(feature = "x509-parser")]
/// Invalid subject alternative name type
InvalidNameType,
/// An IP address was provided as a byte array, but the byte array was an invalid length.
InvalidIpAddressOctetLength(usize),
/// There is no support for generating
/// keys for the given algorithm
KeyGenerationUnavailable,
Expand Down Expand Up @@ -1621,6 +1641,7 @@ impl fmt::Display for RcgenError {
CouldNotParseKeyPair => write!(f, "Could not parse key pair")?,
#[cfg(feature = "x509-parser")]
InvalidNameType => write!(f, "Invalid subject alternative name type")?,
InvalidIpAddressOctetLength(actual) => write!(f, "Invalid IP address octet length of {actual} bytes")?,
KeyGenerationUnavailable => write!(f, "There is no support for generating \
keys for the given algorithm")?,
UnsupportedSignatureAlgorithm => write!(f, "The requested signature algorithm \
Expand Down Expand Up @@ -2249,4 +2270,74 @@ mod tests {
}
}
}

#[cfg(feature = "x509-parser")]
mod test_ip_address_from_octets {
use std::net::IpAddr;
use super::super::ip_addr_from_octets;
use super::super::RcgenError;

#[test]
fn ipv4() {
let octets = [10, 20, 30, 40];

let actual = ip_addr_from_octets(&octets)
.unwrap();

assert_eq!(IpAddr::from(octets), actual)
}

#[test]
fn ipv6() {
let octets = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];

let actual = ip_addr_from_octets(&octets)
.unwrap();

assert_eq!(IpAddr::from(octets), actual)
}

#[test]
fn mismatch() {
let incorrect: Vec<u8> = (0..10).into_iter().collect();
let actual = ip_addr_from_octets(&incorrect)
.unwrap_err();

assert_eq!(RcgenError::InvalidIpAddressOctetLength(10), actual);
}

#[test]
fn none() {
let actual = ip_addr_from_octets(&[])
.unwrap_err();

assert_eq!(RcgenError::InvalidIpAddressOctetLength(0), actual);
}

#[test]
fn too_many() {
let incorrect: Vec<u8> = (0..20).into_iter().collect();
let actual = ip_addr_from_octets(&incorrect)
.unwrap_err();

assert_eq!(RcgenError::InvalidIpAddressOctetLength(20), actual);
}
}

#[cfg(feature = "x509-parser")]
mod test_san_type_from_general_name {
use std::net::IpAddr;
use x509_parser::extensions::GeneralName;
use crate::SanType;

#[test]
fn with_ipv4() {
let octets = [1, 2, 3, 4];
let value = GeneralName::IPAddress(&octets);
let actual = SanType::try_from_general(&value)
.unwrap();

assert_eq!(SanType::IpAddress(IpAddr::from(octets)), actual);
}
}
}

0 comments on commit c2bcdbf

Please sign in to comment.