-
-
Notifications
You must be signed in to change notification settings - Fork 749
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add other name support #1915
add other name support #1915
Conversation
note: i did not test with boringssl i hope the ci does that |
58a5e90
to
8f99f0f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for diving into this.
openssl/src/x509/extension.rs
Outdated
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." | ||
); | ||
} | ||
|
||
/// Sets the `otherName` flag to a ia5string value. | ||
pub fn other_name_string(&mut self, oid: &str, content: &str) -> &mut SubjectAlternativeName { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we want to use more precise types here: oid should be an Asn1ObjectIdentifier type, and contents should be &[u8]
since it's DER.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand that idea, but i would also propose to support a more "userfriendly" way of doing things.
When the user can add arbitrary data as &[u8]
it is not that easy to use that function anymore (and we need to define it as unsafe, since openssl has certain assumptions about the data).
If i know that field is a IA5STRING, then it would be ideal from my perspective if this library cares about the needed unsafe magic and i can just use the "easy" methods.
Would it be ok for you to add two versions? One that allows arbitrary (but unsafe) data, and one that is restricted to Strings?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO limiting to strings doesn't very much sense, OtherName is a very general purpose specification, and we should have an API that's similarly broad. Why do you think unsafe
would be required?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thats why i would allow both. To get the combination of ease of use and all the features you might need.
I see unsafe
as required as the data would then be passed to GENERAL_NAME_set0_othername
. In there the openssl lib expects (if i understood it correctly) certain data formats (e.g. during deserialization). At least the last parameter must be a ASN1_TYPE
as otherwise you will get a SegmentationFault (which is a clear sign to me that we need unsafe here, or guarantee that we do not need it like in the string case)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the public API takes &[u8]
, a sequence of DER bytes, then it will be the responsibility of rust-openssl to have the unsafe code to turn that into an ASN1_TYPE
, we can do that with d2i_ASN1_TYPE
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the clarification.
I have now added other_name2
that will take a provided &[u8]
and try to convert it to an ASN1_TYPE
.
For ease of use i have adapted the other_name_ia5string
method, but if you want to get rid of it that is also fine for me.
openssl/src/x509/mod.rs
Outdated
let s = cvt_p(ffi::ASN1_STRING_type_new(Asn1Type::IA5STRING.as_raw()))?; | ||
ffi::ASN1_STRING_set(s, value.as_ptr().cast(), value.len().try_into().unwrap()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't right, the value of an OtherName is not necessarily an IA5String, we need to handle arbitrary DER TLVs in the value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
8f99f0f
to
347545d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Getting close! Can you please add a test case or two to this.
openssl/src/x509/extension.rs
Outdated
) -> 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.to_string(), typ)); | ||
Ok(self) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would like @sfackler's take on this, specifically whether we should have this return a Result
, or if it should be consistent with the other ones and just return &mut SAN
and then do the error handling lazily.
openssl/src/x509/extension.rs
Outdated
/// If you want to add just a ia5string use `other_name_ia5string` | ||
pub fn other_name2( | ||
&mut self, | ||
oid: &str, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
openssl/src/x509/extension.rs
Outdated
/// Sets the `otherName` flag for ia5strings. | ||
pub fn other_name_ia5string( | ||
&mut self, | ||
oid: &str, | ||
content: &str, | ||
) -> &mut SubjectAlternativeName { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer not to expose this -- the right way to do this is a separate, orthogonal API that makes it easy to DER serialize a https://docs.rs/openssl/latest/openssl/asn1/struct.Asn1String.html
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done, added that api in a separate commit
openssl/src/x509/mod.rs
Outdated
let gn = cvt_p(ffi::GENERAL_NAME_new())?; | ||
(*gn).type_ = ffi::GEN_OTHERNAME; | ||
|
||
ffi::GENERAL_NAME_set0_othername(gn, oid.as_ptr().cast(), value); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can technically fail and we should handle that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
347545d
to
77c0850
Compare
i will add tests soon(tm) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few small comments, this is very close. Thanks for your work.
openssl/src/x509/extension.rs
Outdated
&mut self, | ||
oid: Asn1Object, | ||
content: &[u8], | ||
) -> Result<&mut SubjectAlternativeName, ErrorStack> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sfackler do you have an opinion on this returning a Result
, vs. returning &mut SAN
and doing the fallible ops in build
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that we're deferring the other fallible work to build currently, I'd have this do the same I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, so in that case this should just return the builder, and we can conver to ASN1_TYPE
in build
and I think that will fix the other soundness problem
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, done
openssl/src/x509/mod.rs
Outdated
cvt(ffi::GENERAL_NAME_set0_othername( | ||
gn, | ||
oid.as_ptr().cast(), | ||
value, | ||
))?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this fails then gn
is leaked.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
openssl/src/asn1.rs
Outdated
impl Asn1String { | ||
/// Converts a `&str` to an `Asn1String`. | ||
pub fn from_str(data: &str) -> Result<Self, ErrorStack> { | ||
unsafe { | ||
let s = cvt_p(ffi::ASN1_STRING_type_new(Asn1Type::IA5STRING.as_raw()))?; | ||
ffi::ASN1_STRING_set(s, data.as_ptr().cast(), data.len().try_into().unwrap()); | ||
Ok(Self::from_ptr(s)) | ||
} | ||
} | ||
|
||
/// Converts the Asn1String to the ASN.1 representation with a IA5String tag | ||
pub fn as_asn1type_der(&self) -> Result<Vec<u8>, ErrorStack> { | ||
unsafe { | ||
let typ = cvt_p(ffi::ASN1_TYPE_new()).unwrap(); | ||
ffi::ASN1_TYPE_set(typ, ffi::V_ASN1_IA5STRING, self.0.cast()); | ||
|
||
let len = cvt(ffi::i2d_ASN1_TYPE(typ, ptr::null_mut()))?; | ||
let mut buf = vec![0; len as usize]; | ||
crate::cvt(ffi::i2d_ASN1_TYPE(typ, &mut buf.as_mut_ptr()))?; | ||
Ok(buf) | ||
} | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we do this in a separate PR? It should be orthagonal to the rest of this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure, will open one soon
openssl/src/asn1.rs
Outdated
@@ -705,6 +729,12 @@ impl Asn1Object { | |||
} | |||
} | |||
|
|||
impl Clone for Asn1Object { | |||
fn clone(&self) -> Self { | |||
unsafe { Asn1Object::from_ptr(cvt_p(ffi::OBJ_dup(self.as_ptr())).unwrap()) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of this you can do clone = OBJ_dup;
in the foreign_type_and_impl_send_sync
macro.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks, done
openssl/src/x509/extension.rs
Outdated
/// 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 or other_name_ia5string."] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// 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 or other_name_ia5string."] | |
/// Not currently actually supported, always panics. Please use other_name2 | |
#[deprecated = "other_name is deprecated and always panics. Please use other_name2."] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks fixed
openssl/src/x509/extension.rs
Outdated
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." | ||
"This has not yet been adapted for the new internals. Use other_name2 or other_name_ia5string." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"This has not yet been adapted for the new internals. Use other_name2 or other_name_ia5string." | |
"This has not yet been adapted for the new internals. Use other_name2." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks fixed
77c0850
to
e1154cd
Compare
i added a small testcase. is that sufficient or would you like a larger one |
e1154cd
to
56f9813
Compare
8ae9cd1
to
b5a6abc
Compare
openssl/src/x509/extension.rs
Outdated
@@ -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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Not currently actually supported, always panics. Please use other_name2 or other_name_ia5string | |
/// Not currently actually supported, always panics. Please use other_name2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks fixed
openssl/src/x509/mod.rs
Outdated
if let Err(e) = cvt(ffi::GENERAL_NAME_set0_othername( | ||
gn, | ||
oid.as_ptr().cast(), | ||
value, | ||
)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately this isn't sound -- because build
takes &self
you can call it multiple times, in which case the value
ptr will be reused.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
handled as already commented somewhere else
b5a6abc
to
3c28987
Compare
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.
3c28987
to
56e94e3
Compare
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 the easiest way now is to do individual implementations per datatype.
We start with strings for now, but it should be quite easy to expand upon that.
Closes: #1911