Skip to content

Commit 340e3e3

Browse files
committed
Add Display implementation to X509NameRef
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 <[email protected]>
1 parent 5095d7d commit 340e3e3

File tree

5 files changed

+99
-1
lines changed

5 files changed

+99
-1
lines changed

openssl-sys/src/handwritten/x509.rs

+6
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,12 @@ const_ptr_api! {
489489
pub fn X509_NAME_entry_count(n: #[const_ptr_if(any(ossl110, libressl280))] X509_NAME) -> c_int;
490490
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;
491491
pub fn X509_NAME_get_entry(n: #[const_ptr_if(any(ossl110, libressl280))] X509_NAME, loc: c_int) -> *mut X509_NAME_ENTRY;
492+
pub fn X509_NAME_print_ex(
493+
out: *mut BIO,
494+
n: #[const_ptr_if(any(ossl110, libressl280))] X509_NAME,
495+
indent: c_int,
496+
flags: c_ulong,
497+
) -> c_int;
492498
pub fn X509_NAME_add_entry_by_NID(
493499
x: *mut X509_NAME,
494500
field: c_int,

openssl-sys/src/x509.rs

+23
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,31 @@ pub const X509_FILETYPE_PEM: c_int = 1;
44
pub const X509_FILETYPE_ASN1: c_int = 2;
55
pub const X509_FILETYPE_DEFAULT: c_int = 3;
66

7+
pub const XN_FLAG_SEP_COMMA_PLUS: c_ulong = 1 << 16;
8+
pub const XN_FLAG_DN_REV: c_ulong = 1 << 20;
9+
pub const XN_FLAG_FN_SN: c_ulong = 0;
10+
pub const XN_FLAG_DUMP_UNKNOWN_FIELDS: c_ulong = 1 << 24;
11+
pub const XN_FLAG_RFC2253: c_ulong = ASN1_STRFLGS_RFC2253
12+
| XN_FLAG_SEP_COMMA_PLUS
13+
| XN_FLAG_DN_REV
14+
| XN_FLAG_FN_SN
15+
| XN_FLAG_DUMP_UNKNOWN_FIELDS;
16+
717
pub const ASN1_R_HEADER_TOO_LONG: c_int = 123;
818

19+
pub const ASN1_STRFLGS_ESC_2253: c_ulong = 1;
20+
pub const ASN1_STRFLGS_ESC_CTRL: c_ulong = 2;
21+
pub const ASN1_STRFLGS_ESC_MSB: c_ulong = 4;
22+
pub const ASN1_STRFLGS_UTF8_CONVERT: c_ulong = 0x10;
23+
pub const ASN1_STRFLGS_DUMP_UNKNOWN: c_ulong = 0x100;
24+
pub const ASN1_STRFLGS_DUMP_DER: c_ulong = 0x200;
25+
pub const ASN1_STRFLGS_RFC2253: c_ulong = ASN1_STRFLGS_ESC_2253
26+
| ASN1_STRFLGS_ESC_CTRL
27+
| ASN1_STRFLGS_ESC_MSB
28+
| ASN1_STRFLGS_UTF8_CONVERT
29+
| ASN1_STRFLGS_DUMP_UNKNOWN
30+
| ASN1_STRFLGS_DUMP_DER;
31+
932
cfg_if! {
1033
if #[cfg(not(any(ossl110, libressl350)))] {
1134
pub const X509_LU_FAIL: c_int = 0;

openssl/src/x509/mod.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
1010
use cfg_if::cfg_if;
1111
use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
12-
use libc::{c_int, c_long, c_uint, c_void};
12+
use libc::{c_int, c_long, c_uint, c_ulong, c_void};
1313
use std::cmp::{self, Ordering};
1414
use std::convert::{TryFrom, TryInto};
1515
use std::error::Error;
@@ -1288,6 +1288,26 @@ impl fmt::Debug for X509NameRef {
12881288
}
12891289
}
12901290

1291+
impl fmt::Display for X509NameRef {
1292+
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1293+
const INDENT: i32 = 0;
1294+
const FLAGS: c_ulong = ffi::XN_FLAG_RFC2253 & !ffi::ASN1_STRFLGS_ESC_MSB;
1295+
1296+
unsafe {
1297+
let bio = crate::bio::MemBio::new()?;
1298+
cvt_n(ffi::X509_NAME_print_ex(
1299+
bio.as_ptr(),
1300+
self.as_ptr(),
1301+
INDENT,
1302+
FLAGS,
1303+
))
1304+
.or(Err(fmt::Error))?;
1305+
let value = core::str::from_utf8_unchecked(bio.get_buf());
1306+
formatter.write_str(value)
1307+
}
1308+
}
1309+
}
1310+
12911311
/// A type to destructure and examine an `X509Name`.
12921312
pub struct X509NameEntries<'a> {
12931313
name: &'a X509NameRef,

openssl/src/x509/tests.rs

+27
Original file line numberDiff line numberDiff line change
@@ -1192,3 +1192,30 @@ fn test_store_all_certificates() {
11921192

11931193
assert_eq!(store.all_certificates().len(), 1);
11941194
}
1195+
1196+
#[test]
1197+
fn test_name_display() {
1198+
let cert = include_bytes!("../../test/cert.pem");
1199+
let cert = X509::from_pem(cert).unwrap();
1200+
1201+
const EXPECTED_TO_STRING_OUTPUT: &str =
1202+
"CN=foobar.com,O=Internet Widgits Pty Ltd,ST=Some-State,C=AU";
1203+
1204+
let rdn = cert.subject_name().to_string();
1205+
assert_eq!(
1206+
rdn, EXPECTED_TO_STRING_OUTPUT,
1207+
"output did not match expected",
1208+
);
1209+
1210+
let emoji_cert = include_bytes!("../../test/emoji_cert.pem");
1211+
let emoji_cert = X509::from_pem(emoji_cert).unwrap();
1212+
1213+
const EXPECTED_EMOJI_OUTPUT: &str =
1214+
"CN=www.example.com,O=\u{1f980}\u{1f9ea}\u{1f44d},ST=YY,C=XX";
1215+
1216+
let rdn = emoji_cert.subject_name().to_string();
1217+
assert_eq!(
1218+
rdn, EXPECTED_EMOJI_OUTPUT,
1219+
"formatting of cert name with Unicode Emoji failed"
1220+
);
1221+
}

openssl/test/emoji_cert.pem

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIDqDCCApCgAwIBAgIUWZnfBdTaxSrLilsn6tHRTyZU6PgwDQYJKoZIhvcNAQEL
3+
BQAwSzELMAkGA1UEBhMCWFgxCzAJBgNVBAgMAllZMR0wGwYDVQQKDBRTb21lIENB
4+
IG9yZ2FuaXphdGlvbjEQMA4GA1UEAwwHY2EgdGVzdDAeFw0yMjA5MTMxNDI0MTZa
5+
Fw0yMzA5MTMxNDI0MTZaMEsxCzAJBgNVBAYTAlhYMQswCQYDVQQIDAJZWTEVMBMG
6+
A1UECgwM8J+mgPCfp6rwn5GNMRgwFgYDVQQDDA93d3cuZXhhbXBsZS5jb20wggEi
7+
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCujLOIv3hsSToo4GXYDhiJ7zzV
8+
dKJhDp3ME5YJWyQs26tFztAUL8B6Ns/yy1ZfdTrRaPkMLilVcweFXmDP/cfy/sZZ
9+
u/N912WPOo0xWZz/5frZXhOPcXUkYPIZ0A7DsCy2FzSTvgaPl2wqPtvPi/EEzrrR
10+
Q46wdaq98O4HrfBUA6I/wCzpaos43dIsJCS+pnwfnlQBSIBXGEFa84j1MbVbQICK
11+
O20GEVymNLpo5PubutX7o2nJKj/WSYtqUt31xs6vTH+uk/sgkrZviWM5Jm2QWirn
12+
rDdB0JSS8w7l7qyqfeHFViDZRuJawwS+8qRKxYfT/tU3ebP8zGW/wCJa8vEfAgMB
13+
AAGjgYMwgYAwCQYDVR0TBAIwADAOBgNVHQ8BAf8EBAMCBeAwHQYDVR0OBBYEFG9r
14+
824kB/vwBdMAx/RhYFsiIcvTMB8GA1UdIwQYMBaAFKU8v/PGu848xpjGXj9j6wx0
15+
Xw4CMCMGA1UdEQQcMBqCDSouZXhhbXBsZS5jb22CCWhlbGxvLmNvbTANBgkqhkiG
16+
9w0BAQsFAAOCAQEATZriAaxJX36BpQv5em2oFH0XEJ1B6gCNkRtlMD8XHFOAt0HN
17+
1vHIJ4Yx93UQbbV3h+teUj3B1ksAJByWFqcpMSQov0/v6pwYjUmeWcEDQKrhv7kS
18+
h5GaHDAJezJnPMx4kxrM12r5yWw9lkf5J/TGA9zAzud+/0A8+K3AQLMSYljLynvY
19+
EkK4cLHrQ6LRhwLq4jtj6qATwN1k0iQmwhMPrfOo9s+9CxvZNuf7a/OdWGU0qrt3
20+
YNHMJsioM4Jvt+RvU8ccjXMviZbDe/2pIPv4eU309q1cSYf7pomK2vduk6vuTeAz
21+
V1hhUFbr+gU00TVnzGIwpEMkoQEPlvYEXz7uVw==
22+
-----END CERTIFICATE-----

0 commit comments

Comments
 (0)