Skip to content

Commit

Permalink
Add Display implementation to X509NameRef
Browse files Browse the repository at this point in the history
Internally, call `X509_NAME_print_ex(3)` with RFC2253 flags and disable
UTF-8 escaping so the result is a UTF-8-encoded string.

Signed-off-by: Ross Williams <ross@ross-williams.net>
  • Loading branch information
overhacked committed May 13, 2024
1 parent 5095d7d commit 340e3e3
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 1 deletion.
6 changes: 6 additions & 0 deletions openssl-sys/src/handwritten/x509.rs
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,12 @@ const_ptr_api! {
pub fn X509_NAME_entry_count(n: #[const_ptr_if(any(ossl110, libressl280))] X509_NAME) -> c_int;
pub fn X509_NAME_get_index_by_NID(n: #[const_ptr_if(any(ossl300, libressl280))] X509_NAME, nid: c_int, last_pos: c_int) -> c_int;
pub fn X509_NAME_get_entry(n: #[const_ptr_if(any(ossl110, libressl280))] X509_NAME, loc: c_int) -> *mut X509_NAME_ENTRY;
pub fn X509_NAME_print_ex(
out: *mut BIO,
n: #[const_ptr_if(any(ossl110, libressl280))] X509_NAME,
indent: c_int,
flags: c_ulong,
) -> c_int;
pub fn X509_NAME_add_entry_by_NID(
x: *mut X509_NAME,
field: c_int,
Expand Down
23 changes: 23 additions & 0 deletions openssl-sys/src/x509.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,31 @@ pub const X509_FILETYPE_PEM: c_int = 1;
pub const X509_FILETYPE_ASN1: c_int = 2;
pub const X509_FILETYPE_DEFAULT: c_int = 3;

pub const XN_FLAG_SEP_COMMA_PLUS: c_ulong = 1 << 16;
pub const XN_FLAG_DN_REV: c_ulong = 1 << 20;
pub const XN_FLAG_FN_SN: c_ulong = 0;
pub const XN_FLAG_DUMP_UNKNOWN_FIELDS: c_ulong = 1 << 24;
pub const XN_FLAG_RFC2253: c_ulong = ASN1_STRFLGS_RFC2253
| XN_FLAG_SEP_COMMA_PLUS
| XN_FLAG_DN_REV
| XN_FLAG_FN_SN
| XN_FLAG_DUMP_UNKNOWN_FIELDS;

pub const ASN1_R_HEADER_TOO_LONG: c_int = 123;

pub const ASN1_STRFLGS_ESC_2253: c_ulong = 1;
pub const ASN1_STRFLGS_ESC_CTRL: c_ulong = 2;
pub const ASN1_STRFLGS_ESC_MSB: c_ulong = 4;
pub const ASN1_STRFLGS_UTF8_CONVERT: c_ulong = 0x10;
pub const ASN1_STRFLGS_DUMP_UNKNOWN: c_ulong = 0x100;
pub const ASN1_STRFLGS_DUMP_DER: c_ulong = 0x200;
pub const ASN1_STRFLGS_RFC2253: c_ulong = ASN1_STRFLGS_ESC_2253
| ASN1_STRFLGS_ESC_CTRL
| ASN1_STRFLGS_ESC_MSB
| ASN1_STRFLGS_UTF8_CONVERT
| ASN1_STRFLGS_DUMP_UNKNOWN
| ASN1_STRFLGS_DUMP_DER;

cfg_if! {
if #[cfg(not(any(ossl110, libressl350)))] {
pub const X509_LU_FAIL: c_int = 0;
Expand Down
22 changes: 21 additions & 1 deletion openssl/src/x509/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

use cfg_if::cfg_if;
use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
use libc::{c_int, c_long, c_uint, c_void};
use libc::{c_int, c_long, c_uint, c_ulong, c_void};
use std::cmp::{self, Ordering};
use std::convert::{TryFrom, TryInto};
use std::error::Error;
Expand Down Expand Up @@ -1288,6 +1288,26 @@ impl fmt::Debug for X509NameRef {
}
}

impl fmt::Display for X509NameRef {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
const INDENT: i32 = 0;
const FLAGS: c_ulong = ffi::XN_FLAG_RFC2253 & !ffi::ASN1_STRFLGS_ESC_MSB;

unsafe {
let bio = crate::bio::MemBio::new()?;
cvt_n(ffi::X509_NAME_print_ex(
bio.as_ptr(),
self.as_ptr(),
INDENT,
FLAGS,
))
.or(Err(fmt::Error))?;
let value = core::str::from_utf8_unchecked(bio.get_buf());
formatter.write_str(value)
}
}
}

/// A type to destructure and examine an `X509Name`.
pub struct X509NameEntries<'a> {
name: &'a X509NameRef,
Expand Down
27 changes: 27 additions & 0 deletions openssl/src/x509/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1192,3 +1192,30 @@ fn test_store_all_certificates() {

assert_eq!(store.all_certificates().len(), 1);
}

#[test]
fn test_name_display() {
let cert = include_bytes!("../../test/cert.pem");
let cert = X509::from_pem(cert).unwrap();

const EXPECTED_TO_STRING_OUTPUT: &str =
"CN=foobar.com,O=Internet Widgits Pty Ltd,ST=Some-State,C=AU";

let rdn = cert.subject_name().to_string();
assert_eq!(
rdn, EXPECTED_TO_STRING_OUTPUT,
"output did not match expected",
);

let emoji_cert = include_bytes!("../../test/emoji_cert.pem");
let emoji_cert = X509::from_pem(emoji_cert).unwrap();

const EXPECTED_EMOJI_OUTPUT: &str =
"CN=www.example.com,O=\u{1f980}\u{1f9ea}\u{1f44d},ST=YY,C=XX";

let rdn = emoji_cert.subject_name().to_string();
assert_eq!(
rdn, EXPECTED_EMOJI_OUTPUT,
"formatting of cert name with Unicode Emoji failed"
);
}
22 changes: 22 additions & 0 deletions openssl/test/emoji_cert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDqDCCApCgAwIBAgIUWZnfBdTaxSrLilsn6tHRTyZU6PgwDQYJKoZIhvcNAQEL
BQAwSzELMAkGA1UEBhMCWFgxCzAJBgNVBAgMAllZMR0wGwYDVQQKDBRTb21lIENB
IG9yZ2FuaXphdGlvbjEQMA4GA1UEAwwHY2EgdGVzdDAeFw0yMjA5MTMxNDI0MTZa
Fw0yMzA5MTMxNDI0MTZaMEsxCzAJBgNVBAYTAlhYMQswCQYDVQQIDAJZWTEVMBMG
A1UECgwM8J+mgPCfp6rwn5GNMRgwFgYDVQQDDA93d3cuZXhhbXBsZS5jb20wggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCujLOIv3hsSToo4GXYDhiJ7zzV
dKJhDp3ME5YJWyQs26tFztAUL8B6Ns/yy1ZfdTrRaPkMLilVcweFXmDP/cfy/sZZ
u/N912WPOo0xWZz/5frZXhOPcXUkYPIZ0A7DsCy2FzSTvgaPl2wqPtvPi/EEzrrR
Q46wdaq98O4HrfBUA6I/wCzpaos43dIsJCS+pnwfnlQBSIBXGEFa84j1MbVbQICK
O20GEVymNLpo5PubutX7o2nJKj/WSYtqUt31xs6vTH+uk/sgkrZviWM5Jm2QWirn
rDdB0JSS8w7l7qyqfeHFViDZRuJawwS+8qRKxYfT/tU3ebP8zGW/wCJa8vEfAgMB
AAGjgYMwgYAwCQYDVR0TBAIwADAOBgNVHQ8BAf8EBAMCBeAwHQYDVR0OBBYEFG9r
824kB/vwBdMAx/RhYFsiIcvTMB8GA1UdIwQYMBaAFKU8v/PGu848xpjGXj9j6wx0
Xw4CMCMGA1UdEQQcMBqCDSouZXhhbXBsZS5jb22CCWhlbGxvLmNvbTANBgkqhkiG
9w0BAQsFAAOCAQEATZriAaxJX36BpQv5em2oFH0XEJ1B6gCNkRtlMD8XHFOAt0HN
1vHIJ4Yx93UQbbV3h+teUj3B1ksAJByWFqcpMSQov0/v6pwYjUmeWcEDQKrhv7kS
h5GaHDAJezJnPMx4kxrM12r5yWw9lkf5J/TGA9zAzud+/0A8+K3AQLMSYljLynvY
EkK4cLHrQ6LRhwLq4jtj6qATwN1k0iQmwhMPrfOo9s+9CxvZNuf7a/OdWGU0qrt3
YNHMJsioM4Jvt+RvU8ccjXMviZbDe/2pIPv4eU309q1cSYf7pomK2vduk6vuTeAz
V1hhUFbr+gU00TVnzGIwpEMkoQEPlvYEXz7uVw==
-----END CERTIFICATE-----

0 comments on commit 340e3e3

Please sign in to comment.