1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
use std::fmt;
use std::ops::Deref;
use ref_cast::RefCast;
use crate::mtls::x509::X509Name;
use crate::mtls::oid;
/// An X.509 Distinguished Name (DN) found in a
/// [`Certificate`](crate::mtls::Certificate).
///
/// This type is a wrapper over [`X509Name`] with convenient methods and
/// complete documentation. Should the data exposed by the inherent methods not
/// suffice, this type derefs to [`X509Name`].
#[repr(transparent)]
#[derive(Debug, PartialEq, RefCast)]
pub struct Name<'a>(X509Name<'a>);
impl<'a> Name<'a> {
/// Returns the _first_ UTF-8 _string_ common name, if any.
///
/// Note that common names need not be UTF-8 strings, or strings at all.
/// This method returns the first common name attribute that is.
///
/// # Example
///
/// ```rust
/// # #[macro_use] extern crate rocket;
/// use rocket::mtls::Certificate;
///
/// #[get("/auth")]
/// fn auth(cert: Certificate<'_>) {
/// if let Some(name) = cert.subject().common_name() {
/// println!("Hello, {}!", name);
/// }
/// }
/// ```
pub fn common_name(&self) -> Option<&'a str> {
self.common_names().next()
}
/// Returns an iterator over all of the UTF-8 _string_ common names in
/// `self`.
///
/// Note that common names need not be UTF-8 strings, or strings at all.
/// This method filters the common names in `self` to those that are. Use
/// the raw [`iter_common_name()`](#method.iter_common_name) to iterate over
/// all value types.
///
/// # Example
///
/// ```rust
/// # #[macro_use] extern crate rocket;
/// use rocket::mtls::Certificate;
///
/// #[get("/auth")]
/// fn auth(cert: Certificate<'_>) {
/// for name in cert.issuer().common_names() {
/// println!("Issued by {}.", name);
/// }
/// }
/// ```
pub fn common_names(&self) -> impl Iterator<Item = &'a str> + '_ {
self.iter_by_oid(&oid::OID_X509_COMMON_NAME).filter_map(|n| n.as_str().ok())
}
/// Returns the _first_ UTF-8 _string_ email address, if any.
///
/// Note that email addresses need not be UTF-8 strings, or strings at all.
/// This method returns the first email address attribute that is.
///
/// # Example
///
/// ```rust
/// # #[macro_use] extern crate rocket;
/// use rocket::mtls::Certificate;
///
/// #[get("/auth")]
/// fn auth(cert: Certificate<'_>) {
/// if let Some(email) = cert.subject().email() {
/// println!("Hello, {}!", email);
/// }
/// }
/// ```
pub fn email(&self) -> Option<&'a str> {
self.emails().next()
}
/// Returns an iterator over all of the UTF-8 _string_ email addresses in
/// `self`.
///
/// Note that email addresses need not be UTF-8 strings, or strings at all.
/// This method filters the email address in `self` to those that are. Use
/// the raw [`iter_email()`](#method.iter_email) to iterate over all value
/// types.
///
/// # Example
///
/// ```rust
/// # #[macro_use] extern crate rocket;
/// use rocket::mtls::Certificate;
///
/// #[get("/auth")]
/// fn auth(cert: Certificate<'_>) {
/// for email in cert.subject().emails() {
/// println!("Reach me at: {}", email);
/// }
/// }
/// ```
pub fn emails(&self) -> impl Iterator<Item = &'a str> + '_ {
self.iter_by_oid(&oid::OID_PKCS9_EMAIL_ADDRESS).filter_map(|n| n.as_str().ok())
}
/// Returns `true` if `self` has no data.
///
/// When this is the case for a `subject()`, the subject data can be found
/// in the `subjectAlt` [`extension`].
///
/// [`extension`]: crate::mtls::Certificate::extensions()
///
/// # Example
///
/// ```rust
/// # #[macro_use] extern crate rocket;
/// use rocket::mtls::Certificate;
///
/// #[get("/auth")]
/// fn auth(cert: Certificate<'_>) {
/// let no_data = cert.subject().is_empty();
/// }
/// ```
pub fn is_empty(&self) -> bool {
self.0.as_raw().is_empty()
}
}
impl<'a> Deref for Name<'a> {
type Target = X509Name<'a>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl fmt::Display for Name<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}