Name parsing!
This commit is contained in:
104
src/lib.rs
104
src/lib.rs
@@ -20,7 +20,7 @@ enum X509ParseError {
|
|||||||
ASN1DecodeError(ASN1DecodeErr),
|
ASN1DecodeError(ASN1DecodeErr),
|
||||||
NotEnoughData, ItemNotFound, IllegalFormat, NoSerialNumber,
|
NotEnoughData, ItemNotFound, IllegalFormat, NoSerialNumber,
|
||||||
NoSignatureAlgorithm, NoNameInformation, IllFormedNameInformation,
|
NoSignatureAlgorithm, NoNameInformation, IllFormedNameInformation,
|
||||||
NoValueForName, UnknownAttrTypeValue
|
NoValueForName, UnknownAttrTypeValue, IllegalStringValue
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ASN1DecodeErr> for X509ParseError {
|
impl From<ASN1DecodeErr> for X509ParseError {
|
||||||
@@ -366,6 +366,7 @@ fn get_tbs_certificate(x: &ASN1Block)
|
|||||||
//
|
//
|
||||||
println!("version: {}", version);
|
println!("version: {}", version);
|
||||||
println!("serial#: {}", serial);
|
println!("serial#: {}", serial);
|
||||||
|
println!("names: {:?}", names);
|
||||||
Err(X509ParseError::IllegalFormat)
|
Err(X509ParseError::IllegalFormat)
|
||||||
}
|
}
|
||||||
_ =>
|
_ =>
|
||||||
@@ -436,14 +437,49 @@ fn get_signature_info(bs: &[ASN1Block])
|
|||||||
|
|
||||||
#[derive(Clone,Debug,PartialEq)]
|
#[derive(Clone,Debug,PartialEq)]
|
||||||
struct InfoBlock {
|
struct InfoBlock {
|
||||||
country: String,
|
name: String,
|
||||||
|
surname: String,
|
||||||
|
given_name: String,
|
||||||
|
initials: String,
|
||||||
|
generation_qualifier: String,
|
||||||
|
common_name: String,
|
||||||
|
locality: String,
|
||||||
|
state_province: String,
|
||||||
organization: String,
|
organization: String,
|
||||||
unit: String,
|
unit: String,
|
||||||
|
title: String,
|
||||||
|
dn_qualifier: String,
|
||||||
|
country: String,
|
||||||
|
serial_number: String,
|
||||||
|
pseudonym: String,
|
||||||
|
domain_component: String,
|
||||||
email: String
|
email: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn empty_block() -> InfoBlock {
|
||||||
|
InfoBlock {
|
||||||
|
name: "".to_string(),
|
||||||
|
surname: "".to_string(),
|
||||||
|
given_name: "".to_string(),
|
||||||
|
initials: "".to_string(),
|
||||||
|
generation_qualifier: "".to_string(),
|
||||||
|
common_name: "".to_string(),
|
||||||
|
locality: "".to_string(),
|
||||||
|
state_province: "".to_string(),
|
||||||
|
organization: "".to_string(),
|
||||||
|
unit: "".to_string(),
|
||||||
|
title: "".to_string(),
|
||||||
|
dn_qualifier: "".to_string(),
|
||||||
|
country: "".to_string(),
|
||||||
|
serial_number: "".to_string(),
|
||||||
|
pseudonym: "".to_string(),
|
||||||
|
domain_component: "".to_string(),
|
||||||
|
email: "".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_name_data(bs: &[ASN1Block])
|
fn get_name_data(bs: &[ASN1Block])
|
||||||
-> Result<((),&[ASN1Block]),X509ParseError>
|
-> Result<(InfoBlock,&[ASN1Block]),X509ParseError>
|
||||||
{
|
{
|
||||||
match bs.first() {
|
match bs.first() {
|
||||||
Some(x) => {
|
Some(x) => {
|
||||||
@@ -455,10 +491,7 @@ fn get_name_data(bs: &[ASN1Block])
|
|||||||
&ASN1Block::Sequence(_, ref items) => {
|
&ASN1Block::Sequence(_, ref items) => {
|
||||||
// RelativeDistinguishedName ::=
|
// RelativeDistinguishedName ::=
|
||||||
// SET SIZE (1..MAX) OF AttributeTypeAndValue
|
// SET SIZE (1..MAX) OF AttributeTypeAndValue
|
||||||
let mut iblock = InfoBlock { country: "".to_string(),
|
let mut iblock = empty_block();
|
||||||
organization: "".to_string(),
|
|
||||||
unit: "".to_string(),
|
|
||||||
email: "".to_string() };
|
|
||||||
|
|
||||||
for item in items.iter() {
|
for item in items.iter() {
|
||||||
match item {
|
match item {
|
||||||
@@ -471,7 +504,7 @@ fn get_name_data(bs: &[ASN1Block])
|
|||||||
return Err(X509ParseError::IllFormedNameInformation)
|
return Err(X509ParseError::IllFormedNameInformation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(X509ParseError::NoNameInformation)
|
Ok((iblock, &bs[1..]))
|
||||||
}
|
}
|
||||||
_ =>
|
_ =>
|
||||||
Err(X509ParseError::NoNameInformation)
|
Err(X509ParseError::NoNameInformation)
|
||||||
@@ -522,51 +555,60 @@ fn process_atv(oid: &OID, val: &ASN1Block, iblock: &mut InfoBlock)
|
|||||||
//
|
//
|
||||||
//id-at-name AttributeType ::= { id-at 41 }
|
//id-at-name AttributeType ::= { id-at 41 }
|
||||||
if oid == oid!(2,5,4,41) {
|
if oid == oid!(2,5,4,41) {
|
||||||
|
iblock.name = getStringValue(val)?;
|
||||||
}
|
}
|
||||||
//id-at-surname AttributeType ::= { id-at 4 }
|
//id-at-surname AttributeType ::= { id-at 4 }
|
||||||
if oid == oid!(2,5,4,4) {
|
if oid == oid!(2,5,4,4) {
|
||||||
|
iblock.surname = getStringValue(val)?;
|
||||||
}
|
}
|
||||||
//id-at-givenName AttributeType ::= { id-at 42 }
|
//id-at-givenName AttributeType ::= { id-at 42 }
|
||||||
if oid == oid!(2,5,4,42) {
|
if oid == oid!(2,5,4,42) {
|
||||||
|
iblock.given_name = getStringValue(val)?;
|
||||||
}
|
}
|
||||||
//id-at-initials AttributeType ::= { id-at 43 }
|
//id-at-initials AttributeType ::= { id-at 43 }
|
||||||
if oid == oid!(2,5,4,43) {
|
if oid == oid!(2,5,4,43) {
|
||||||
|
iblock.initials = getStringValue(val)?;
|
||||||
}
|
}
|
||||||
//id-at-generationQualifier AttributeType ::= { id-at 44 }
|
//id-at-generationQualifier AttributeType ::= { id-at 44 }
|
||||||
if oid == oid!(2,5,4,44) {
|
if oid == oid!(2,5,4,44) {
|
||||||
|
iblock.generation_qualifier = getStringValue(val)?;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
//-- Naming attributes of type X520CommonName
|
//-- Naming attributes of type X520CommonName
|
||||||
//
|
//
|
||||||
//id-at-commonName AttributeType ::= { id-at 3 }
|
//id-at-commonName AttributeType ::= { id-at 3 }
|
||||||
if oid == oid!(2,5,4,3) {
|
if oid == oid!(2,5,4,3) {
|
||||||
|
iblock.common_name = getStringValue(val)?;
|
||||||
}
|
}
|
||||||
//-- Naming attributes of type X520LocalityName
|
//-- Naming attributes of type X520LocalityName
|
||||||
//
|
//
|
||||||
//id-at-localityName AttributeType ::= { id-at 7 }
|
//id-at-localityName AttributeType ::= { id-at 7 }
|
||||||
if oid == oid!(2,5,4,7) {
|
if oid == oid!(2,5,4,7) {
|
||||||
|
iblock.locality = getStringValue(val)?;
|
||||||
}
|
}
|
||||||
//-- Naming attributes of type X520StateOrProvinceName
|
//-- Naming attributes of type X520StateOrProvinceName
|
||||||
//
|
//
|
||||||
//id-at-stateOrProvinceName AttributeType ::= { id-at 8 }
|
//id-at-stateOrProvinceName AttributeType ::= { id-at 8 }
|
||||||
if oid == oid!(2,5,4,8) {
|
if oid == oid!(2,5,4,8) {
|
||||||
|
iblock.state_province = getStringValue(val)?;
|
||||||
}
|
}
|
||||||
//-- Naming attributes of type X520OrganizationName
|
//-- Naming attributes of type X520OrganizationName
|
||||||
//
|
//
|
||||||
//id-at-organizationName AttributeType ::= { id-at 10 }
|
//id-at-organizationName AttributeType ::= { id-at 10 }
|
||||||
if oid == oid!(2,5,4,10) {
|
if oid == oid!(2,5,4,10) {
|
||||||
println!("Organization {:?}", val);
|
iblock.organization = getStringValue(val)?;
|
||||||
}
|
}
|
||||||
//-- Naming attributes of type X520OrganizationalUnitName
|
//-- Naming attributes of type X520OrganizationalUnitName
|
||||||
//
|
//
|
||||||
//id-at-organizationalUnitName AttributeType ::= { id-at 11 }
|
//id-at-organizationalUnitName AttributeType ::= { id-at 11 }
|
||||||
if oid == oid!(2,5,4,11) {
|
if oid == oid!(2,5,4,11) {
|
||||||
println!("organizational unit {:?}", val);
|
iblock.unit = getStringValue(val)?;
|
||||||
}
|
}
|
||||||
//-- Naming attributes of type X520Title
|
//-- Naming attributes of type X520Title
|
||||||
//
|
//
|
||||||
//id-at-title AttributeType ::= { id-at 12 }
|
//id-at-title AttributeType ::= { id-at 12 }
|
||||||
if oid == oid!(2,5,4,12) {
|
if oid == oid!(2,5,4,12) {
|
||||||
|
iblock.title = getStringValue(val)?;
|
||||||
}
|
}
|
||||||
//-- Naming attributes of type X520dnQualifier
|
//-- Naming attributes of type X520dnQualifier
|
||||||
//
|
//
|
||||||
@@ -574,6 +616,7 @@ fn process_atv(oid: &OID, val: &ASN1Block, iblock: &mut InfoBlock)
|
|||||||
//
|
//
|
||||||
//X520dnQualifier ::= PrintableString
|
//X520dnQualifier ::= PrintableString
|
||||||
if oid == oid!(2,5,4,46) {
|
if oid == oid!(2,5,4,46) {
|
||||||
|
iblock.dn_qualifier = getPrintableStringValue(val)?;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
//-- Naming attributes of type X520countryName (digraph from IS 3166)
|
//-- Naming attributes of type X520countryName (digraph from IS 3166)
|
||||||
@@ -582,7 +625,10 @@ fn process_atv(oid: &OID, val: &ASN1Block, iblock: &mut InfoBlock)
|
|||||||
//
|
//
|
||||||
//X520countryName ::= PrintableString (SIZE (2))
|
//X520countryName ::= PrintableString (SIZE (2))
|
||||||
if oid == oid!(2,5,4,6) {
|
if oid == oid!(2,5,4,6) {
|
||||||
println!("Country {:?}", val);
|
iblock.country = getPrintableStringValue(val)?;
|
||||||
|
if iblock.country.len() != 2 {
|
||||||
|
return Err(X509ParseError::IllegalStringValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
//-- Naming attributes of type X520SerialNumber
|
//-- Naming attributes of type X520SerialNumber
|
||||||
@@ -591,12 +637,14 @@ fn process_atv(oid: &OID, val: &ASN1Block, iblock: &mut InfoBlock)
|
|||||||
//
|
//
|
||||||
//X520SerialNumber ::= PrintableString (SIZE (1..ub-serial-number))
|
//X520SerialNumber ::= PrintableString (SIZE (1..ub-serial-number))
|
||||||
if oid == oid!(2,5,4,5) {
|
if oid == oid!(2,5,4,5) {
|
||||||
|
iblock.serial_number = getPrintableStringValue(val)?;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
//-- Naming attributes of type X520Pseudonym
|
//-- Naming attributes of type X520Pseudonym
|
||||||
//
|
//
|
||||||
//id-at-pseudonym AttributeType ::= { id-at 65 }
|
//id-at-pseudonym AttributeType ::= { id-at 65 }
|
||||||
if oid == oid!(2,5,4,65) {
|
if oid == oid!(2,5,4,65) {
|
||||||
|
iblock.pseudonym = getStringValue(val)?;
|
||||||
}
|
}
|
||||||
//-- Naming attributes of type DomainComponent (from RFC 4519)
|
//-- Naming attributes of type DomainComponent (from RFC 4519)
|
||||||
//
|
//
|
||||||
@@ -604,6 +652,7 @@ fn process_atv(oid: &OID, val: &ASN1Block, iblock: &mut InfoBlock)
|
|||||||
//
|
//
|
||||||
//DomainComponent ::= IA5String
|
//DomainComponent ::= IA5String
|
||||||
if oid == oid!(0,9,2342,19200300,100,1,25) {
|
if oid == oid!(0,9,2342,19200300,100,1,25) {
|
||||||
|
iblock.domain_component = getIA5StringValue(val)?;
|
||||||
}
|
}
|
||||||
//-- Legacy attributes
|
//-- Legacy attributes
|
||||||
//
|
//
|
||||||
@@ -614,12 +663,43 @@ fn process_atv(oid: &OID, val: &ASN1Block, iblock: &mut InfoBlock)
|
|||||||
//
|
//
|
||||||
//EmailAddress ::= IA5String (SIZE (1..ub-emailaddress-length))
|
//EmailAddress ::= IA5String (SIZE (1..ub-emailaddress-length))
|
||||||
if oid == oid!(1,2,840,113549,1,9,1) {
|
if oid == oid!(1,2,840,113549,1,9,1) {
|
||||||
println!("email {:?}", val);
|
iblock.email = getIA5StringValue(val)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(X509ParseError::UnknownAttrTypeValue)
|
Err(X509ParseError::UnknownAttrTypeValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn getStringValue(a: &ASN1Block) -> Result<String,X509ParseError>
|
||||||
|
{
|
||||||
|
match a {
|
||||||
|
&ASN1Block::TeletexString(_,ref v) => Ok(v.clone()),
|
||||||
|
&ASN1Block::PrintableString(_,ref v) => Ok(v.clone()),
|
||||||
|
&ASN1Block::UniversalString(_,ref v) => Ok(v.clone()),
|
||||||
|
&ASN1Block::UTF8String(_,ref v) => Ok(v.clone()),
|
||||||
|
&ASN1Block::BMPString(_,ref v) => Ok(v.clone()),
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::IllegalStringValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getPrintableStringValue(a: &ASN1Block) -> Result<String,X509ParseError>
|
||||||
|
{
|
||||||
|
match a {
|
||||||
|
&ASN1Block::PrintableString(_,ref v) => Ok(v.clone()),
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::IllegalStringValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getIA5StringValue(a: &ASN1Block) -> Result<String,X509ParseError>
|
||||||
|
{
|
||||||
|
match a {
|
||||||
|
&ASN1Block::IA5String(_,ref v) => Ok(v.clone()),
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::IllegalStringValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|||||||
Reference in New Issue
Block a user