Skip to content

Commit 6f2b01f

Browse files
committed
Store issuer items as vec and not map
There can be multiple of the same entry, e.g. DC (domain component) entries in an issuer. Using a HashMap is too restrictive.
1 parent 12d6533 commit 6f2b01f

File tree

3 files changed

+37
-43
lines changed

3 files changed

+37
-43
lines changed

rcgen/src/certificate.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,7 @@ impl CertificateParams {
601601
let der = subject_key.sign_der(|writer| {
602602
// Write version
603603
writer.next().write_u8(0);
604-
write_distinguished_name(writer.next(), distinguished_name);
604+
write_distinguished_name(writer.next(), distinguished_name.clone());
605605
serialize_public_key_der(subject_key, writer.next());
606606

607607
// According to the spec in RFC 2986, even if attributes are empty we need the empty attribute tag
@@ -663,7 +663,7 @@ impl CertificateParams {
663663
// Write signature algorithm
664664
issuer.key_pair.alg.write_alg_ident(writer.next());
665665
// Write issuer name
666-
write_distinguished_name(writer.next(), &issuer.distinguished_name);
666+
write_distinguished_name(writer.next(), issuer.distinguished_name.clone());
667667
// Write validity
668668
writer.next().write_sequence(|writer| {
669669
// Not before
@@ -673,7 +673,7 @@ impl CertificateParams {
673673
Ok::<(), Error>(())
674674
})?;
675675
// Write subject
676-
write_distinguished_name(writer.next(), &self.distinguished_name);
676+
write_distinguished_name(writer.next(), self.distinguished_name.clone());
677677
// Write subjectPublicKeyInfo
678678
serialize_public_key_der(pub_key, writer.next());
679679
// write extensions
@@ -856,7 +856,7 @@ fn write_general_subtrees(writer: DERWriter, tag: u64, general_subtrees: &[Gener
856856
GeneralSubtree::Rfc822Name(name)
857857
| GeneralSubtree::DnsName(name) => writer.write_ia5_string(name),
858858
GeneralSubtree::DirectoryName(name) => {
859-
write_distinguished_name(writer, name)
859+
write_distinguished_name(writer, name.clone())
860860
},
861861
GeneralSubtree::IpAddress(subnet) => {
862862
writer.write_bytes(&subnet.to_bytes())

rcgen/src/crl.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ impl CertificateRevocationListParams {
234234
// Write issuer.
235235
// RFC 5280 §5.1.2.3:
236236
// The issuer field MUST contain a non-empty X.500 distinguished name (DN).
237-
write_distinguished_name(writer.next(), &issuer.distinguished_name);
237+
write_distinguished_name(writer.next(), issuer.distinguished_name.clone());
238238

239239
// Write thisUpdate date.
240240
// RFC 5280 §5.1.2.4:

rcgen/src/lib.rs

Lines changed: 32 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ println!("{}", key_pair.serialize_pem());
3333
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
3434
#![warn(unreachable_pub)]
3535

36-
use std::collections::HashMap;
3736
use std::fmt;
3837
use std::hash::Hash;
3938
use std::net::IpAddr;
@@ -299,8 +298,7 @@ See also the RFC 5280 sections on the [issuer](https://tools.ietf.org/html/rfc52
299298
and [subject](https://tools.ietf.org/html/rfc5280#section-4.1.2.6) fields.
300299
*/
301300
pub struct DistinguishedName {
302-
entries: HashMap<DnType, DnValue>,
303-
order: Vec<DnType>,
301+
entries: Vec<(DnType, DnValue)>,
304302
}
305303

306304
impl DistinguishedName {
@@ -309,20 +307,32 @@ impl DistinguishedName {
309307
Self::default()
310308
}
311309
/// Obtains the attribute value for the given attribute type
312-
pub fn get(&self, ty: &DnType) -> Option<&DnValue> {
313-
self.entries.get(ty)
310+
pub fn get(&self, ty: &DnType) -> Vec<&DnValue> {
311+
self.entries
312+
.iter()
313+
.filter_map(|(dn_type, dn_value)| if ty == dn_type { Some(dn_value) } else { None })
314+
.collect()
314315
}
315316
/// Removes the attribute with the specified DnType
316317
///
317318
/// Returns true when an actual removal happened, false
318319
/// when no attribute with the specified DnType was
319320
/// found.
320321
pub fn remove(&mut self, ty: DnType) -> bool {
321-
let removed = self.entries.remove(&ty).is_some();
322-
if removed {
323-
self.order.retain(|ty_o| &ty != ty_o);
322+
let mut remove_indices = vec![];
323+
for (index, (dn_type, _dn_val)) in self.entries.iter().enumerate() {
324+
if dn_type == &ty {
325+
remove_indices.push(index);
326+
}
327+
}
328+
329+
let is_remove_indices = !remove_indices.is_empty();
330+
331+
for index in remove_indices {
332+
self.entries.remove(index);
324333
}
325-
removed
334+
335+
is_remove_indices
326336
}
327337
/// Inserts or updates an attribute that consists of type and name
328338
///
@@ -331,21 +341,11 @@ impl DistinguishedName {
331341
/// let mut dn = DistinguishedName::new();
332342
/// dn.push(DnType::OrganizationName, "Crab widgits SE");
333343
/// dn.push(DnType::CommonName, DnValue::PrintableString("Master Cert".try_into().unwrap()));
334-
/// assert_eq!(dn.get(&DnType::OrganizationName), Some(&DnValue::Utf8String("Crab widgits SE".to_string())));
335-
/// assert_eq!(dn.get(&DnType::CommonName), Some(&DnValue::PrintableString("Master Cert".try_into().unwrap())));
344+
/// assert_eq!(dn.get(&DnType::OrganizationName).get(0), Some(&DnValue::Utf8String("Crab widgits SE".to_string())).as_ref());
345+
/// assert_eq!(dn.get(&DnType::CommonName).get(0), Some(&DnValue::PrintableString("Master Cert".try_into().unwrap())).as_ref());
336346
/// ```
337347
pub fn push(&mut self, ty: DnType, s: impl Into<DnValue>) {
338-
if !self.entries.contains_key(&ty) {
339-
self.order.push(ty.clone());
340-
}
341-
self.entries.insert(ty, s.into());
342-
}
343-
/// Iterate over the entries
344-
pub fn iter(&self) -> DistinguishedNameIterator<'_> {
345-
DistinguishedNameIterator {
346-
distinguished_name: self,
347-
iter: self.order.iter(),
348-
}
348+
self.entries.push((ty, s.into()));
349349
}
350350

351351
#[cfg(feature = "x509-parser")]
@@ -393,21 +393,15 @@ impl DistinguishedName {
393393
}
394394
}
395395

396-
/**
397-
Iterator over [`DistinguishedName`] entries
398-
*/
399-
pub struct DistinguishedNameIterator<'a> {
400-
distinguished_name: &'a DistinguishedName,
401-
iter: std::slice::Iter<'a, DnType>,
402-
}
403-
404-
impl<'a> Iterator for DistinguishedNameIterator<'a> {
405-
type Item = (&'a DnType, &'a DnValue);
396+
impl Iterator for DistinguishedName {
397+
type Item = (DnType, DnValue);
406398

407399
fn next(&mut self) -> Option<Self::Item> {
408-
self.iter
409-
.next()
410-
.and_then(|ty| self.distinguished_name.entries.get(ty).map(|v| (ty, v)))
400+
self.entries.pop()
401+
}
402+
403+
fn size_hint(&self) -> (usize, Option<usize>) {
404+
self.entries.iter().size_hint()
411405
}
412406
}
413407

@@ -568,9 +562,9 @@ fn write_dt_utc_or_generalized(writer: DERWriter, dt: OffsetDateTime) {
568562
}
569563
}
570564

571-
fn write_distinguished_name(writer: DERWriter, dn: &DistinguishedName) {
565+
fn write_distinguished_name(writer: DERWriter, dn: DistinguishedName) {
572566
writer.write_sequence(|writer| {
573-
for (ty, content) in dn.iter() {
567+
for (ty, content) in dn.into_iter() {
574568
writer.next().write_set(|writer| {
575569
writer.next().write_sequence(|writer| {
576570
writer.next().write_oid(&ty.to_oid());
@@ -596,7 +590,7 @@ fn write_distinguished_name(writer: DERWriter, dn: &DistinguishedName) {
596590
.write_tagged_implicit(TAG_UNIVERSALSTRING, |writer| {
597591
writer.write_bytes(s.as_bytes())
598592
}),
599-
DnValue::Utf8String(s) => writer.next().write_utf8_string(s),
593+
DnValue::Utf8String(s) => writer.next().write_utf8_string(s.as_str()),
600594
}
601595
});
602596
});

0 commit comments

Comments
 (0)