1use {
8 crate::rfc4519::{
9 OID_COMMON_NAME, OID_COUNTRY_NAME, OID_LOCALITY_NAME, OID_ORGANIZATIONAL_UNIT_NAME,
10 OID_ORGANIZATION_NAME, OID_STATE_PROVINCE_NAME,
11 },
12 bcder::{
13 decode::{BytesSource, Constructed, DecodeError, Source},
14 encode,
15 encode::{PrimitiveContent, Values},
16 string::{Ia5String, PrintableString, Utf8String},
17 Captured, Mode, OctetString, Oid, Tag,
18 },
19 std::{
20 fmt::{Debug, Display, Formatter},
21 io::Write,
22 ops::{Deref, DerefMut},
23 str::FromStr,
24 },
25};
26
27pub type GeneralNames = Vec<GeneralName>;
28
29#[derive(Clone, Debug, Eq, PartialEq)]
44pub enum GeneralName {
45 OtherName(AnotherName),
46 Rfc822Name(Ia5String),
47 DnsName(Ia5String),
48 X400Address(OrAddress),
49 DirectoryName(Name),
50 EdiPartyName(EdiPartyName),
51 UniformResourceIdentifier(Ia5String),
52 IpAddress(OctetString),
53 RegisteredId(Oid),
54}
55
56impl GeneralName {
57 pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
58 match cons.take_opt_constructed_if(Tag::CTX_0, |cons| AnotherName::take_from(cons))?
59 { Some(name) => {
60 Ok(Self::OtherName(name))
61 } _ => { match cons.take_opt_constructed_if(Tag::CTX_1, |cons| Ia5String::take_from(cons))?
62 { Some(name) => {
63 Ok(Self::Rfc822Name(name))
64 } _ => { match cons.take_opt_constructed_if(Tag::CTX_2, |cons| Ia5String::take_from(cons))?
65 { Some(name) => {
66 Ok(Self::DnsName(name))
67 } _ => if let Some(name) =
68 cons.take_opt_constructed_if(Tag::CTX_3, |cons| OrAddress::take_from(cons))?
69 {
70 Ok(Self::X400Address(name))
71 } else { match cons.take_opt_constructed_if(Tag::CTX_4, |cons| Name::take_from(cons))?
72 { Some(name) => {
73 Ok(Self::DirectoryName(name))
74 } _ => { match cons.take_opt_constructed_if(Tag::CTX_5, |cons| EdiPartyName::take_from(cons))?
75 { Some(name) => {
76 Ok(Self::EdiPartyName(name))
77 } _ => { match cons.take_opt_constructed_if(Tag::CTX_6, |cons| Ia5String::take_from(cons))?
78 { Some(name) => {
79 Ok(Self::UniformResourceIdentifier(name))
80 } _ => { match cons.take_opt_constructed_if(Tag::ctx(7), |cons| OctetString::take_from(cons))?
81 { Some(name) => {
82 Ok(Self::IpAddress(name))
83 } _ => { match cons.take_opt_constructed_if(Tag::ctx(8), |cons| Oid::take_from(cons))?
84 { Some(name) => {
85 Ok(Self::RegisteredId(name))
86 } _ => {
87 Err(cons.content_err("unexpected GeneralName variant"))
88 }}}}}}}}}}}}}}}}
89 }
90
91 pub fn encode_ref(&self) -> impl Values + '_ {
92 match self {
93 Self::OtherName(name) => (
94 Some(name.explicit(Tag::CTX_0)),
95 None,
96 None,
97 None,
98 None,
99 None,
100 None,
101 None,
102 ),
103 Self::Rfc822Name(name) => (
104 None,
105 Some(name.encode_ref_as(Tag::CTX_1)),
106 None,
107 None,
108 None,
109 None,
110 None,
111 None,
112 ),
113 Self::DnsName(name) => (
114 None,
115 None,
116 Some(name.encode_ref_as(Tag::CTX_2)),
117 None,
118 None,
119 None,
120 None,
121 None,
122 ),
123 Self::X400Address(_name) => {
124 unimplemented!()
125 }
126 Self::DirectoryName(name) => (
127 None,
128 None,
129 None,
130 Some(name.encode_ref_as(Tag::CTX_4)),
131 None,
132 None,
133 None,
134 None,
135 ),
136 Self::EdiPartyName(name) => (
137 None,
138 None,
139 None,
140 None,
141 Some(name.encode_ref_as(Tag::CTX_5)),
142 None,
143 None,
144 None,
145 ),
146 Self::UniformResourceIdentifier(name) => (
147 None,
148 None,
149 None,
150 None,
151 None,
152 Some(name.encode_ref_as(Tag::CTX_6)),
153 None,
154 None,
155 ),
156 Self::IpAddress(name) => (
157 None,
158 None,
159 None,
160 None,
161 None,
162 None,
163 Some(name.encode_ref_as(Tag::ctx(7))),
164 None,
165 ),
166 Self::RegisteredId(name) => (
167 None,
168 None,
169 None,
170 None,
171 None,
172 None,
173 None,
174 Some(name.encode_ref_as(Tag::ctx(8))),
175 ),
176 }
177 }
178}
179
180#[derive(Clone, Debug)]
188pub struct AnotherName {
189 pub type_id: Oid,
190 pub value: Captured,
191}
192
193impl PartialEq for AnotherName {
194 fn eq(&self, other: &Self) -> bool {
195 self.type_id == other.type_id && self.value.as_slice() == other.value.as_slice()
196 }
197}
198
199impl Eq for AnotherName {}
200
201impl AnotherName {
202 pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
203 cons.take_sequence(|cons| {
204 let type_id = Oid::take_from(cons)?;
205 let value = cons.take_constructed_if(Tag::CTX_0, |cons| cons.capture_all())?;
206
207 Ok(Self { type_id, value })
208 })
209 }
210}
211
212impl Values for AnotherName {
213 fn encoded_len(&self, mode: Mode) -> usize {
214 encode::sequence((self.type_id.encode_ref(), &self.value)).encoded_len(mode)
215 }
216
217 fn write_encoded<W: Write>(&self, mode: Mode, target: &mut W) -> Result<(), std::io::Error> {
218 encode::sequence((self.type_id.encode_ref(), &self.value)).write_encoded(mode, target)
219 }
220}
221
222#[derive(Clone, Debug, Eq, PartialEq)]
230pub struct EdiPartyName {
231 pub name_assigner: Option<DirectoryString>,
232 pub party_name: DirectoryString,
233}
234
235impl EdiPartyName {
236 pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
237 cons.take_sequence(|cons| {
238 let name_assigner =
239 cons.take_opt_constructed_if(Tag::CTX_0, |cons| DirectoryString::take_from(cons))?;
240 let party_name =
241 cons.take_constructed_if(Tag::CTX_1, |cons| DirectoryString::take_from(cons))?;
242
243 Ok(Self {
244 name_assigner,
245 party_name,
246 })
247 })
248 }
249
250 pub fn encode_ref(&self) -> impl Values + '_ {
251 encode::sequence((
252 self.name_assigner
253 .as_ref()
254 .map(|name_assigner| name_assigner.encode_ref()),
255 self.party_name.encode_ref(),
256 ))
257 }
258
259 pub fn encode_ref_as(&self, tag: Tag) -> impl Values + '_ {
260 encode::sequence_as(
261 tag,
262 (
263 self.name_assigner
264 .as_ref()
265 .map(|name_assigner| name_assigner.encode_ref()),
266 self.party_name.encode_ref(),
267 ),
268 )
269 }
270}
271
272#[derive(Clone, Debug, Eq, PartialEq)]
283pub enum DirectoryString {
284 TeletexString,
286 PrintableString(PrintableString),
287 UniversalString,
289 Utf8String(Utf8String),
290 BmpString,
292}
293
294impl DirectoryString {
295 pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
296 cons.take_value(|tag, content| {
297 if tag == Tag::PRINTABLE_STRING {
298 Ok(Self::PrintableString(PrintableString::from_content(
299 content,
300 )?))
301 } else if tag == Tag::UTF8_STRING {
302 Ok(Self::Utf8String(Utf8String::from_content(content)?))
303 } else {
304 Err(content
305 .content_err("only decoding of PrintableString and UTF8String is implemented"))
306 }
307 })
308 }
309
310 pub fn encode_ref(&self) -> impl Values + '_ {
311 match self {
312 Self::PrintableString(ps) => (Some(ps.encode_ref()), None),
313 Self::Utf8String(s) => (None, Some(s.encode_ref())),
314 _ => unimplemented!(),
315 }
316 }
317}
318
319impl Display for DirectoryString {
320 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
321 let str = match self {
322 Self::PrintableString(s) => s.to_string(),
323 Self::Utf8String(s) => s.to_string(),
324 _ => unimplemented!(),
325 };
326 write!(f, "{}", str)
327 }
328}
329
330impl Values for DirectoryString {
331 fn encoded_len(&self, mode: Mode) -> usize {
332 self.encode_ref().encoded_len(mode)
333 }
334
335 fn write_encoded<W: Write>(&self, mode: Mode, target: &mut W) -> Result<(), std::io::Error> {
336 self.encode_ref().write_encoded(mode, target)
337 }
338}
339
340#[derive(Clone, Debug, Eq, PartialEq)]
341pub enum Name {
342 RdnSequence(RdnSequence),
343}
344
345impl Name {
346 pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
347 Ok(Self::RdnSequence(RdnSequence::take_from(cons)?))
348 }
349
350 pub fn encode_ref(&self) -> impl Values + '_ {
351 match self {
352 Self::RdnSequence(seq) => seq.encode_ref(),
353 }
354 }
355
356 pub fn encode_ref_as(&self, tag: Tag) -> impl Values + '_ {
357 match self {
358 Self::RdnSequence(seq) => seq.encode_ref_as(tag),
359 }
360 }
361
362 pub fn iter_rdn(&self) -> impl Iterator<Item = &RelativeDistinguishedName> {
364 self.0.iter()
365 }
366
367 pub fn iter_attributes(&self) -> impl Iterator<Item = &AttributeTypeAndValue> {
369 self.0.iter().flat_map(|rdn| rdn.iter())
370 }
371
372 pub fn iter_mut_attributes(&mut self) -> impl Iterator<Item = &mut AttributeTypeAndValue> {
374 self.0.iter_mut().flat_map(|rdn| rdn.iter_mut())
375 }
376
377 pub fn iter_by_oid(&self, oid: Oid) -> impl Iterator<Item = &AttributeTypeAndValue> {
379 self.iter_attributes().filter(move |atv| atv.typ == oid)
380 }
381
382 pub fn iter_mut_by_oid(
384 &mut self,
385 oid: Oid,
386 ) -> impl Iterator<Item = &mut AttributeTypeAndValue> {
387 self.iter_mut_attributes().filter(move |atv| atv.typ == oid)
388 }
389
390 pub fn iter_common_name(&self) -> impl Iterator<Item = &AttributeTypeAndValue> {
392 self.iter_by_oid(Oid(OID_COMMON_NAME.as_ref().into()))
393 }
394
395 pub fn iter_country(&self) -> impl Iterator<Item = &AttributeTypeAndValue> {
397 self.iter_by_oid(Oid(OID_COUNTRY_NAME.as_ref().into()))
398 }
399
400 pub fn iter_locality(&self) -> impl Iterator<Item = &AttributeTypeAndValue> {
402 self.iter_by_oid(Oid(OID_LOCALITY_NAME.as_ref().into()))
403 }
404
405 pub fn iter_state_province(&self) -> impl Iterator<Item = &AttributeTypeAndValue> {
407 self.iter_by_oid(Oid(OID_STATE_PROVINCE_NAME.as_ref().into()))
408 }
409
410 pub fn iter_organization(&self) -> impl Iterator<Item = &AttributeTypeAndValue> {
412 self.iter_by_oid(Oid(OID_ORGANIZATION_NAME.as_ref().into()))
413 }
414
415 pub fn iter_organizational_unit(&self) -> impl Iterator<Item = &AttributeTypeAndValue> {
417 self.iter_by_oid(Oid(OID_ORGANIZATIONAL_UNIT_NAME.as_ref().into()))
418 }
419
420 pub fn find_attribute(&self, oid: Oid) -> Option<&AttributeTypeAndValue> {
422 self.iter_by_oid(oid).next()
423 }
424
425 pub fn find_first_attribute_string(
427 &self,
428 oid: Oid,
429 ) -> Result<Option<String>, DecodeError<<BytesSource as Source>::Error>> {
430 if let Some(atv) = self.find_attribute(oid) {
431 Ok(Some(atv.to_string()?))
432 } else {
433 Ok(None)
434 }
435 }
436
437 pub fn user_friendly_str(&self) -> Result<String, DecodeError<<BytesSource as Source>::Error>> {
445 let mut fields = vec![];
446
447 for cn in self.iter_common_name() {
448 fields.push(format!("CN={}", cn.to_string()?));
449 }
450 for ou in self.iter_organizational_unit() {
451 fields.push(format!("OU={}", ou.to_string()?));
452 }
453 for o in self.iter_organization() {
454 fields.push(format!("O={}", o.to_string()?));
455 }
456 for l in self.iter_locality() {
457 fields.push(format!("L={}", l.to_string()?));
458 }
459 for state in self.iter_state_province() {
460 fields.push(format!("S={}", state.to_string()?));
461 }
462 for c in self.iter_country() {
463 fields.push(format!("C={}", c.to_string()?));
464 }
465
466 Ok(fields.join(", "))
467 }
468
469 pub fn append_printable_string(
473 &mut self,
474 oid: Oid,
475 value: &str,
476 ) -> Result<(), bcder::string::CharSetError> {
477 let mut rdn = RelativeDistinguishedName::default();
478 rdn.push(AttributeTypeAndValue::new_printable_string(oid, value)?);
479 self.0.push(rdn);
480
481 Ok(())
482 }
483
484 pub fn append_utf8_string(
488 &mut self,
489 oid: Oid,
490 value: &str,
491 ) -> Result<(), bcder::string::CharSetError> {
492 let mut rdn = RelativeDistinguishedName::default();
493 rdn.push(AttributeTypeAndValue::new_utf8_string(oid, value)?);
494 self.0.push(rdn);
495
496 Ok(())
497 }
498
499 pub fn append_common_name_utf8_string(
501 &mut self,
502 value: &str,
503 ) -> Result<(), bcder::string::CharSetError> {
504 self.append_utf8_string(Oid(OID_COMMON_NAME.as_ref().into()), value)
505 }
506
507 pub fn append_country_utf8_string(
509 &mut self,
510 value: &str,
511 ) -> Result<(), bcder::string::CharSetError> {
512 self.append_utf8_string(Oid(OID_COUNTRY_NAME.as_ref().into()), value)
513 }
514
515 pub fn append_organization_utf8_string(
517 &mut self,
518 value: &str,
519 ) -> Result<(), bcder::string::CharSetError> {
520 self.append_utf8_string(Oid(OID_ORGANIZATION_NAME.as_ref().into()), value)
521 }
522
523 pub fn append_organizational_unit_utf8_string(
525 &mut self,
526 value: &str,
527 ) -> Result<(), bcder::string::CharSetError> {
528 self.append_utf8_string(Oid(OID_ORGANIZATIONAL_UNIT_NAME.as_ref().into()), value)
529 }
530}
531
532impl Default for Name {
533 fn default() -> Self {
534 Self::RdnSequence(RdnSequence::default())
535 }
536}
537
538impl Deref for Name {
539 type Target = RdnSequence;
540
541 fn deref(&self) -> &Self::Target {
542 match self {
543 Self::RdnSequence(seq) => seq,
544 }
545 }
546}
547
548impl DerefMut for Name {
549 fn deref_mut(&mut self) -> &mut Self::Target {
550 match self {
551 Self::RdnSequence(seq) => seq,
552 }
553 }
554}
555
556#[derive(Clone, Debug, Default, Eq, PartialEq)]
557pub struct RdnSequence(Vec<RelativeDistinguishedName>);
558
559impl Deref for RdnSequence {
560 type Target = Vec<RelativeDistinguishedName>;
561
562 fn deref(&self) -> &Self::Target {
563 &self.0
564 }
565}
566
567impl DerefMut for RdnSequence {
568 fn deref_mut(&mut self) -> &mut Self::Target {
569 &mut self.0
570 }
571}
572
573impl RdnSequence {
574 pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
575 cons.take_sequence(|cons| {
576 let mut values = Vec::new();
577
578 while let Some(value) = RelativeDistinguishedName::take_opt_from(cons)? {
579 values.push(value);
580 }
581
582 Ok(Self(values))
583 })
584 }
585
586 pub fn encode_ref(&self) -> impl Values + '_ {
587 encode::sequence(&self.0)
588 }
589
590 pub fn encode_ref_as(&self, tag: Tag) -> impl Values + '_ {
591 encode::sequence_as(tag, &self.0)
592 }
593}
594
595pub type DistinguishedName = RdnSequence;
596
597#[derive(Clone, Debug, Default, Eq, PartialEq)]
604pub struct RelativeDistinguishedName(Vec<AttributeTypeAndValue>);
605
606impl Deref for RelativeDistinguishedName {
607 type Target = Vec<AttributeTypeAndValue>;
608
609 fn deref(&self) -> &Self::Target {
610 &self.0
611 }
612}
613
614impl DerefMut for RelativeDistinguishedName {
615 fn deref_mut(&mut self) -> &mut Self::Target {
616 &mut self.0
617 }
618}
619
620impl RelativeDistinguishedName {
621 pub fn take_opt_from<S: Source>(
622 cons: &mut Constructed<S>,
623 ) -> Result<Option<Self>, DecodeError<S::Error>> {
624 cons.take_opt_set(|cons| {
625 let mut values = Vec::new();
626
627 while let Some(value) = AttributeTypeAndValue::take_opt_from(cons)? {
628 values.push(value);
629 }
630
631 Ok(Self(values))
632 })
633 }
634
635 pub fn encode_ref(&self) -> impl Values + '_ {
636 encode::set(&self.0)
637 }
638}
639
640impl Values for RelativeDistinguishedName {
641 fn encoded_len(&self, mode: Mode) -> usize {
642 self.encode_ref().encoded_len(mode)
643 }
644
645 fn write_encoded<W: Write>(&self, mode: Mode, target: &mut W) -> Result<(), std::io::Error> {
646 self.encode_ref().write_encoded(mode, target)
647 }
648}
649
650#[derive(Clone, Debug, Eq, PartialEq)]
651pub struct OrAddress {}
652
653impl OrAddress {
654 pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
655 Err(cons.content_err("parsing of OrAddress not implemented"))
656 }
657}
658
659#[derive(Clone)]
667pub struct AttributeTypeAndValue {
668 pub typ: AttributeType,
669 pub value: AttributeValue,
670}
671
672impl Debug for AttributeTypeAndValue {
673 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
674 let mut s = f.debug_struct("AttributeTypeAndValue");
675 s.field("type", &format_args!("{}", self.typ));
676 s.field("value", &self.value);
677 s.finish()
678 }
679}
680
681impl AttributeTypeAndValue {
682 pub fn take_opt_from<S: Source>(
683 cons: &mut Constructed<S>,
684 ) -> Result<Option<Self>, DecodeError<S::Error>> {
685 cons.take_opt_sequence(|cons| {
686 let typ = AttributeType::take_from(cons)?;
687 let value = cons.capture_all()?;
688
689 Ok(Self {
690 typ,
691 value: value.into(),
692 })
693 })
694 }
695
696 pub fn encode_ref(&self) -> impl Values + '_ {
697 encode::sequence((self.typ.encode_ref(), self.value.deref()))
698 }
699
700 pub fn to_string(&self) -> Result<String, DecodeError<<BytesSource as Source>::Error>> {
702 self.value.to_string()
703 }
704
705 pub fn new_printable_string(oid: Oid, s: &str) -> Result<Self, bcder::string::CharSetError> {
707 Ok(Self {
708 typ: oid,
709 value: AttributeValue::new_printable_string(s)?,
710 })
711 }
712
713 pub fn new_utf8_string(oid: Oid, s: &str) -> Result<Self, bcder::string::CharSetError> {
715 Ok(Self {
716 typ: oid,
717 value: AttributeValue::new_utf8_string(s)?,
718 })
719 }
720
721 pub fn set_utf8_string_value(&mut self, s: &str) -> Result<(), bcder::string::CharSetError> {
723 self.value.set_utf8_string_value(s)
724 }
725}
726
727impl PartialEq for AttributeTypeAndValue {
728 fn eq(&self, other: &Self) -> bool {
729 self.typ == other.typ && self.value.as_slice() == other.value.as_slice()
730 }
731}
732
733impl Eq for AttributeTypeAndValue {}
734
735impl Values for AttributeTypeAndValue {
736 fn encoded_len(&self, mode: Mode) -> usize {
737 self.encode_ref().encoded_len(mode)
738 }
739
740 fn write_encoded<W: Write>(&self, mode: Mode, target: &mut W) -> Result<(), std::io::Error> {
741 self.encode_ref().write_encoded(mode, target)
742 }
743}
744
745pub type AttributeType = Oid;
746
747#[derive(Clone)]
748pub struct AttributeValue(Captured);
749
750impl Debug for AttributeValue {
751 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
752 f.write_fmt(format_args!("{}", hex::encode(self.0.as_slice())))
753 }
754}
755
756impl AttributeValue {
757 pub fn new_printable_string(s: &str) -> Result<Self, bcder::string::CharSetError> {
759 let mut slf = Self(Captured::empty(Mode::Der));
760
761 slf.set_printable_string_value(s)?;
762
763 Ok(slf)
764 }
765
766 pub fn new_utf8_string(s: &str) -> Result<Self, bcder::string::CharSetError> {
768 let mut slf = Self(Captured::empty(Mode::Der));
769
770 slf.set_utf8_string_value(s)?;
771
772 Ok(slf)
773 }
774
775 pub fn to_string(&self) -> Result<String, DecodeError<<BytesSource as Source>::Error>> {
782 self.0.clone().decode(|cons| {
783 match cons.take_opt_value_if(Tag::NUMERIC_STRING, |content| {
784 bcder::NumericString::from_content(content)
785 })? { Some(s) => {
786 Ok(s.to_string())
787 } _ => { match cons.take_opt_value_if(Tag::PRINTABLE_STRING, |content| {
788 bcder::PrintableString::from_content(content)
789 })? { Some(s) => {
790 Ok(s.to_string())
791 } _ => { match cons.take_opt_value_if(Tag::UTF8_STRING, |content| {
792 bcder::Utf8String::from_content(content)
793 })? { Some(s) => {
794 Ok(s.to_string())
795 } _ => { match cons.take_opt_value_if(Tag::IA5_STRING, |content| {
796 bcder::Ia5String::from_content(content)
797 })? { Some(s) => {
798 Ok(s.to_string())
799 } _ => {
800 Ok(DirectoryString::take_from(cons)?.to_string())
801 }}}}}}}}
802 })
803 }
804
805 pub fn set_printable_string_value(
807 &mut self,
808 value: &str,
809 ) -> Result<(), bcder::string::CharSetError> {
810 let ps = DirectoryString::PrintableString(PrintableString::from_str(value)?);
811 let captured = bcder::Captured::from_values(Mode::Der, ps);
812 self.0 = captured;
813
814 Ok(())
815 }
816
817 pub fn set_utf8_string_value(
819 &mut self,
820 value: &str,
821 ) -> Result<(), bcder::string::CharSetError> {
822 let ds = DirectoryString::Utf8String(Utf8String::from_str(value)?);
823 let captured = bcder::Captured::from_values(Mode::Der, ds);
824 self.0 = captured;
825
826 Ok(())
827 }
828}
829
830impl Deref for AttributeValue {
831 type Target = Captured;
832
833 fn deref(&self) -> &Self::Target {
834 &self.0
835 }
836}
837
838impl From<Captured> for AttributeValue {
839 fn from(v: Captured) -> Self {
840 Self(v)
841 }
842}