Skip to content

Commit

Permalink
add other name support
Browse files Browse the repository at this point in the history
the issue with other name SANs is that they can contain arbitary data.
As we can no longer use the old method for other_name for security
reasons we now add `other_name2` as an alternative.
  • Loading branch information
huettner94 committed May 17, 2023
1 parent c7e89d9 commit 8ae9cd1
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 5 deletions.
9 changes: 9 additions & 0 deletions openssl-sys/src/handwritten/asn1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub struct ASN1_ENCODING {

extern "C" {
pub fn ASN1_OBJECT_free(x: *mut ASN1_OBJECT);
pub fn OBJ_dup(x: *const ASN1_OBJECT) -> *mut ASN1_OBJECT;
}

stack!(stack_st_ASN1_OBJECT);
Expand Down Expand Up @@ -94,13 +95,21 @@ extern "C" {
#[cfg(ossl110)]
pub fn ASN1_ENUMERATED_get_int64(pr: *mut i64, a: *const ASN1_ENUMERATED) -> c_int;

pub fn ASN1_TYPE_new() -> *mut ASN1_TYPE;
pub fn ASN1_TYPE_set(a: *mut ASN1_TYPE, type_: c_int, value: *mut c_void);
pub fn ASN1_TYPE_free(x: *mut ASN1_TYPE);
pub fn d2i_ASN1_TYPE(
k: *mut *mut ASN1_TYPE,
buf: *mut *const u8,
len: c_long,
) -> *mut ASN1_TYPE;
}

const_ptr_api! {
extern "C" {
pub fn ASN1_STRING_to_UTF8(out: *mut *mut c_uchar, s: #[const_ptr_if(any(ossl110, libressl280))] ASN1_STRING) -> c_int;
pub fn ASN1_STRING_type(x: #[const_ptr_if(any(ossl110, libressl280))] ASN1_STRING) -> c_int;
pub fn ASN1_generate_v3(str: #[const_ptr_if(any(ossl110, libressl280))] c_char, cnf: *mut X509V3_CTX) -> *mut ASN1_TYPE;
pub fn i2d_ASN1_TYPE(a: #[const_ptr_if(ossl300)] ASN1_TYPE, pp: *mut *mut c_uchar) -> c_int;
}
}
5 changes: 5 additions & 0 deletions openssl-sys/src/handwritten/x509v3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ pub enum CONF_METHOD {}
extern "C" {
pub fn GENERAL_NAME_new() -> *mut GENERAL_NAME;
pub fn GENERAL_NAME_free(name: *mut GENERAL_NAME);
pub fn GENERAL_NAME_set0_othername(
gen: *mut GENERAL_NAME,
oid: *mut ASN1_OBJECT,
value: *mut ASN1_TYPE,
) -> c_int;
}

#[repr(C)]
Expand Down
1 change: 1 addition & 0 deletions openssl/src/asn1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,7 @@ impl Asn1OctetStringRef {
foreign_type_and_impl_send_sync! {
type CType = ffi::ASN1_OBJECT;
fn drop = ffi::ASN1_OBJECT_free;
fn clone = ffi::OBJ_dup;

/// Object Identifier
///
Expand Down
40 changes: 35 additions & 5 deletions openssl/src/x509/extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@
//!
//! let extension: X509Extension = bc.build().unwrap();
//! ```
use std::convert::TryInto;
use std::fmt::Write;
use std::ptr;

use crate::asn1::Asn1Object;
use crate::cvt_p;
use crate::error::ErrorStack;
use crate::nid::Nid;
use crate::x509::{GeneralName, Stack, X509Extension, X509v3Context};
use ffi::ASN1_TYPE;
use foreign_types::ForeignType;

/// An extension which indicates whether a certificate is a CA certificate.
Expand Down Expand Up @@ -434,6 +438,7 @@ enum RustGeneralName {
Uri(String),
Ip(String),
Rid(String),
OtherName(Asn1Object, *mut ASN1_TYPE),
}

/// An extension that allows additional identities to be bound to the subject
Expand Down Expand Up @@ -506,12 +511,34 @@ impl SubjectAlternativeName {

/// Sets the `otherName` flag.
///
/// Not currently actually supported, always panics.
#[deprecated = "other_name is deprecated and always panics. Please file a bug if you have a use case for this."]
/// Not currently actually supported, always panics. Please use other_name2 or other_name_ia5string
#[deprecated = "other_name is deprecated and always panics. Please use other_name2."]
pub fn other_name(&mut self, _other_name: &str) -> &mut SubjectAlternativeName {
unimplemented!(
"This has not yet been adapted for the new internals. File a bug if you need this."
);
unimplemented!("This has not yet been adapted for the new internals. Use other_name2.");
}

/// Sets the `otherName` flag.
///
/// `content` must be a valid der encoded ASN1_TYPE
///
/// If you want to add just a ia5string use `other_name_ia5string`
pub fn other_name2(
&mut self,
oid: Asn1Object,
content: &[u8],
) -> Result<&mut SubjectAlternativeName, ErrorStack> {
let typ: *mut ASN1_TYPE;
unsafe {
ffi::init();

typ = cvt_p(ffi::d2i_ASN1_TYPE(
ptr::null_mut(),
&mut content.as_ptr().cast(),
content.len().try_into().unwrap(),
))?;
}
self.items.push(RustGeneralName::OtherName(oid, typ));
Ok(self)
}

/// Return a `SubjectAlternativeName` extension as an `X509Extension`.
Expand All @@ -526,6 +553,9 @@ impl SubjectAlternativeName {
GeneralName::new_ip(s.parse().map_err(|_| ErrorStack::get())?)?
}
RustGeneralName::Rid(s) => GeneralName::new_rid(Asn1Object::from_str(s)?)?,
RustGeneralName::OtherName(oid, content) => {
GeneralName::new_other_name(oid.clone(), *content)?
}
};
stack.push(gn)?;
}
Expand Down
25 changes: 25 additions & 0 deletions openssl/src/x509/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
//! the secure protocol for browsing the web.

use cfg_if::cfg_if;
use ffi::ASN1_TYPE;
use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
use libc::{c_int, c_long, c_uint, c_void};
use std::cmp::{self, Ordering};
Expand Down Expand Up @@ -2054,6 +2055,30 @@ impl GeneralName {
Ok(GeneralName::from_ptr(gn))
}
}

pub(crate) fn new_other_name(
oid: Asn1Object,
value: *mut ASN1_TYPE,
) -> Result<GeneralName, ErrorStack> {
unsafe {
ffi::init();
let gn = cvt_p(ffi::GENERAL_NAME_new())?;
(*gn).type_ = ffi::GEN_OTHERNAME;

if let Err(e) = cvt(ffi::GENERAL_NAME_set0_othername(
gn,
oid.as_ptr().cast(),
value,
)) {
ffi::GENERAL_NAME_free(gn);
return Err(e);
}

mem::forget(oid);

Ok(GeneralName::from_ptr(gn))
}
}
}

impl GeneralNameRef {
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 @@ -27,6 +27,7 @@ use crate::x509::{CrlReason, X509Builder};
use crate::x509::{
CrlStatus, X509Crl, X509Extension, X509Name, X509Req, X509StoreContext, X509VerifyResult, X509,
};
use foreign_types::ForeignType;
use hex::{self, FromHex};
#[cfg(any(ossl102, libressl261))]
use libc::time_t;
Expand Down Expand Up @@ -1105,6 +1106,32 @@ fn ipv6_as_subject_alternative_name_is_formatted_in_debug() {
]);
}

#[cfg(ossl110)]
#[test]
fn other_name_as_subject_alternative_name() {
let oid = Asn1Object::from_str("1.3.6.1.5.5.7.8.11").unwrap();
// this is the hex representation of "test" encoded as a ia5string
let content = [0x16, 0x04, 0x74, 0x65, 0x73, 0x74];

let mut builder = X509Builder::new().unwrap();
let san = SubjectAlternativeName::new()
.other_name2(oid, &content)
.unwrap()
.build(&builder.x509v3_context(None, None))
.unwrap();
builder.append_extension(san).unwrap();
let cert = builder.build();
let general_name = cert
.subject_alt_names()
.into_iter()
.flatten()
.next()
.unwrap();
unsafe {
assert_eq!((*general_name.as_ptr()).type_, 0);
}
}

#[test]
fn test_dist_point() {
let cert = include_bytes!("../../test/certv3.pem");
Expand Down

0 comments on commit 8ae9cd1

Please sign in to comment.