-
Notifications
You must be signed in to change notification settings - Fork 263
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 support for rfc822Name SAN in SMIME certificates #177
base: stable
Are you sure you want to change the base?
Conversation
Can anybody review my patch? |
SubjectAltName is undefined if there is no subjectaltname attribute in the certificate. In that case there is an error
I am not sure if Subject can ever be empty, but I guess it wouldn't hurt to check that is defined, too before using it and initializing data{String} to some placeholder string if the subject is empty. Then you should have covered all bases... I also think it would be better to prefer the email address from the dn if it is set. subjectAltName means "subject alternative name", thus it's only an alternative if the dn has also an email address... |
AFAIR rfc822Name should be preferred way to store email. |
You are correct. RFC 5280 says in section 4.1.2.6:
subjectAltName is the preferred way to set the email address. |
Added fixes for certificates w/o rfc822name |
I have also noticed that the smime verification does not verify the sender address against the address in the certificate. That seems strange. If the email is signed by a certificate of a trusted ca, it's shown as good signature with full trust, even though it may actually a certificate by someone else not matching the sender address... |
https://tools.ietf.org/html/rfc5750#section-3 So yes, RT must check sender address and should provide alternative variant (certificate in user certificate store?) if check is failed. |
$data{String} = 'DN: ' . join(',',@{$cert->Issuer}); | ||
} elsif ($type eq 'subject') { | ||
if ($cert->SubjectAltName && grep /rfc822name/i, @{$cert->SubjectAltName}) { | ||
$data{String} = join( ',', map { s/rfc822name=//i; $_ } grep /rfc822name/i, @{$cert->SubjectAltName}); |
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 would suggest
$data{String} = Email::Address->new( $data{'Name'}, join( ',', map { s/rfc822name=//i; $_ } grep /rfc822name/i, @{$cert->SubjectAltName}))->format;
to format the email address with the name if available.
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 am running my RT server with my suggestion and it looks good. Do you think you can update your pull request?
What's the chance to get this into the next release?
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.
Of course I can add you patch to my PR.
But nobody from BTS devs did not reply on this PR for more than a year so I think that BTS doesn't have any plans to fix SMIME support.
PS. If You have any time - please add some tests for new features.
I haven't time for this work right now :(
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.
While I no longer work at BPS, I'm the original author of the SMIME support, and can take a gander and potentially merge it.
Adding tests would make it much easier to review. I'll see if I understand the change well enough to add some.
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.
Hi, @alexmv. Glad to see You in this issue.
What Do You think about moving SMIME from openssl smime to openssl cms?
Or using some of existing perl smime packages (Crypt::SMIME / Crypt::OpenSSL::SMIME / Crypt::SMIMEEngine/etc).
Now RT work with smime keys/messages on their own. And I think that native smime in openssl (now openssl cms ) can do this better. I think that openssl cms already can verify sender email, key status (crl/ocsp), CA chains, etc.
So maybe we should switch to use native openssl functions instead of partially reimplement it in RT code?
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.
Please do take this suggestion and use Email::Address to construct the address.
That said, I don't think joining all of the rfc822name=
SubjectAltName addresses we find with ,
is correct. It constructs a String
which looks like "Someone" <alice@example.com, bob@example.com>
which we attempt to parse out later using Email::Address. Unfortunately, such a string doesn't round-trip, and Email::Address just finds alice@example.com
in it, with no name.
The Most Right thing here would be to make it a list of Email::Address objects, and later iterate over them looking for any one match, using Load -- and finally resort to calling LoadOrCreate using just one of them. I think the simple solution is just to take the first rfc822 name and be done with it, and I'd merge a change which simply did that.
I don't know for sure how SubjectAltNames are made, but I suspect that the grep
regex wants to be anchored. I would like it to also contain the =
that we later assume is there to strip off, and general code style is to use the block form of grep
, not the statement form.
I'm on board, in principal, with switching to openssl cms or openssl smime
… @mkosmach commented on this pull request.
In lib/RT/Crypt/SMIME.pm:
> @@ -883,8 +884,18 @@ sub GetCertificateInfo {
my $method = $type . "_" . $USER_MAP{$_};
$data{$_} = $cert->$method if $cert->can($method);
}
- $data{String} = Email::Address->new( @DaTa{'Name', 'EmailAddress'} )->format
- if $data{EmailAddress};
+ if ($type eq 'issuer') {
+ $data{String} = 'DN: ' . join(',',@{$cert->Issuer});
+ } elsif ($type eq 'subject') {
+ if ($cert->SubjectAltName && grep /rfc822name/i, @{$cert->SubjectAltName}) {
+ $data{String} = join( ',', map { s/rfc822name=//i; $_ } grep /rfc822name/i, @{$cert->SubjectAltName});
Hi, @alexmv. Glad to see You in this issue.
What Do You think about moving SMIME from openssl smime to openssl cms?
Or using some of existing perl smime packages (Crypt::SMIME / Crypt::OpenSSL::SMIME / Crypt::SMIMEEngine/etc).
Now RT work with smime keys/messages on their own. And I think that native smime in openssl (now openssl cms ) can do this better. I think that openssl cms already can verify sender email, key status (crl/ocsp), CA chains, etc.
So maybe we should switch to use native openssl functions instead of partially reimplement it in RT code?
―
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or mute the thread.
|
Would it still be possible to pull this? Currently, there are errors in the logs and the text shown is "broken" ('SMIME: The signature is good, signed by , trust is full') if the certificate has the only e-mail address set as subjectaltname. Reimplementing the code may be a better long-term solution but for now (as this pull request is dated back to January 2016...) a quick fix would be much appreciated... |
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 concur that discussing or planning a shift to openssl cms
is out of scope -- I have Feelings about it (openssl smime
is horrible and we actively decided against it) but this is not the place to discuss them.
I'm going to see if I can suss out how to use rt/t/data/smime/keys/demoCA/
to make a key. Without being able to test it, I have one bug that's visible by inspection, commented below.
Please squash your changes into one commit, as they're one logical change.
@@ -460,6 +460,7 @@ sub Verify { | |||
|
|||
$signer = $info{info}[0]; | |||
last unless $signer and $signer->{User}[0]{String}; | |||
last if $signer->{User}[0]{String} =~ 'DN:'; |
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.
DN:
could possibly be part of an RFC822-compliant email address: "Alex DN: Thing" <alex@example.com>
This needs to be =~ /^DN: /
in order to correctly not have false-positives
$data{String} = 'DN: ' . join(',',@{$cert->Issuer}); | ||
} elsif ($type eq 'subject') { | ||
if ($cert->SubjectAltName && grep /rfc822name/i, @{$cert->SubjectAltName}) { | ||
$data{String} = join( ',', map { s/rfc822name=//i; $_ } grep /rfc822name/i, @{$cert->SubjectAltName}); |
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.
Please do take this suggestion and use Email::Address to construct the address.
That said, I don't think joining all of the rfc822name=
SubjectAltName addresses we find with ,
is correct. It constructs a String
which looks like "Someone" <alice@example.com, bob@example.com>
which we attempt to parse out later using Email::Address. Unfortunately, such a string doesn't round-trip, and Email::Address just finds alice@example.com
in it, with no name.
The Most Right thing here would be to make it a list of Email::Address objects, and later iterate over them looking for any one match, using Load -- and finally resort to calling LoadOrCreate using just one of them. I think the simple solution is just to take the first rfc822 name and be done with it, and I'd merge a change which simply did that.
I don't know for sure how SubjectAltNames are made, but I suspect that the grep
regex wants to be anchored. I would like it to also contain the =
that we later assume is there to strip off, and general code style is to use the block form of grep
, not the statement form.
I've succeeded in bending |
Thank You very much, Alex! PS. Please add checks for sender email == signer email as Gerald suggested earlier. |
Pushed 4.2/smime-subjectaltname with tests. Will follow up with the commits to resolve this issue atop those. |
@alexmv, thank You |
Bugfixes are branched from the earliest supported release that the bug was found in. After it's merged into 4.2-trunk, 4.2-trunk will be merged up to 4.4-trunk, thus picking up the fix in 4.4. And 4.4-trunk is merged up into master. |
Now we have 4.4.4 and 2019 and this update still hasn't been merged. I can't help it but it seems to me RT is a dying product... For several years now I have to repatch our installation after each update. |
replace #176 request