[Rt-commit] rt branch, 4.4/provide-more-public-key-details, updated. rt-4.4.4-163-g0af4a3ca51

Dianne Skoll dianne at bestpractical.com
Tue Nov 17 10:42:32 EST 2020


The branch, 4.4/provide-more-public-key-details has been updated
       via  0af4a3ca511d05bdc0a5ecfe618a49245705f244 (commit)
      from  0692dcc46dcf6e60aa2eb7ccff9415c57e608393 (commit)

Summary of changes:
 lib/RT/Crypt/SMIME.pm                   | 45 +++++++++++++++++++++++++++++++++
 t/crypt/smime/extract-email-address.t   | 31 +++++++++++++++++++++++
 t/data/smime/keys/dianne at skoll.ca.crt   | 34 +++++++++++++++++++++++++
 t/data/smime/keys/smime at example.com.crt | 33 ++++++++++++++++++++++++
 4 files changed, 143 insertions(+)
 create mode 100644 t/crypt/smime/extract-email-address.t
 create mode 100644 t/data/smime/keys/dianne at skoll.ca.crt
 create mode 100644 t/data/smime/keys/smime at example.com.crt

- Log -----------------------------------------------------------------
commit 0af4a3ca511d05bdc0a5ecfe618a49245705f244
Author: Dianne Skoll <dianne at bestpractical.com>
Date:   Tue Nov 17 10:41:06 2020 -0500

    Extract email addresses from S/MIME certificates as specified in RFC 5750.
    
    Add a certificate with the email address only in SubjectAltName and add
    a unit test to ensure that email addresses are extracted correctly.
    
    Since RFC 5750 permits S/MIME certificates to contain no email addresses,
    do not attempt to set the SMIMECertificate for an RT::User if we could
    not extract an email address.

diff --git a/lib/RT/Crypt/SMIME.pm b/lib/RT/Crypt/SMIME.pm
index 271055afbd..f1043f3423 100644
--- a/lib/RT/Crypt/SMIME.pm
+++ b/lib/RT/Crypt/SMIME.pm
@@ -498,6 +498,7 @@ sub Verify {
         }
 
         my ($address) = Email::Address->parse($signer->{User}[0]{String});
+        last unless $address;
         my $user = RT::User->new( $RT::SystemUser );
         $user->LoadOrCreateByEmail(
             EmailAddress => $address->address,
@@ -940,6 +941,13 @@ sub GetCertificateInfo {
             my $method = $type . "_" . $USER_MAP{$_};
             $data{$_} = $cert->$method if $cert->can($method);
         }
+
+        # Use the correct procedure as per
+        # https://tools.ietf.org/html/rfc5750#section-3
+        # to extract the subject's email address
+        if ($type eq 'subject') {
+            $data{EmailAddress} = RT::Crypt::SMIME::ExtractSubjectEmailAddress($cert);
+        }
         if ($data{EmailAddress}) {
             $data{String} = Email::Address->new( @data{'Name', 'EmailAddress'} )->format
         } else {
@@ -1013,4 +1021,41 @@ sub GetCertificateInfo {
     return %res;
 }
 
+# Extract the subject email address from an S/MIME certificate.
+# https://tools.ietf.org/html/rfc5750#section-3
+sub ExtractSubjectEmailAddress
+{
+    my ($cert) = @_;
+    # 1: Check SubjectAltName
+    # "The email address SHOULD be in the subjectAltName extension"
+
+    my $altnames = $cert->SubjectAltName;
+    if ($altnames && (ref($altnames) eq 'ARRAY')) {
+        # Pick the first email address from the array.
+        foreach my $alt (@$altnames) {
+            if ($alt =~ /^rfc822name=/i) {
+                $alt =~ s/^rfc822name=//i;
+                return $alt;
+            }
+        }
+    }
+
+    # 2: Check subject_email
+    my $ret = $cert->subject_email;
+    return $ret if (defined($ret) && ($ret ne ''));
+
+    # 3: If the subject_cn looks like an email address,
+    # return that
+    my $email_address;
+    eval {
+        ($email_address) = Email::Address->parse($cert->subject_cn);
+    };
+    if ($email_address) {
+        return $email_address->address;
+    }
+
+    # No sensible email address found
+    return undef;
+}
+
 1;
diff --git a/t/crypt/smime/extract-email-address.t b/t/crypt/smime/extract-email-address.t
new file mode 100644
index 0000000000..f6da2d7bb0
--- /dev/null
+++ b/t/crypt/smime/extract-email-address.t
@@ -0,0 +1,31 @@
+use strict;
+use warnings;
+
+use RT::Test::SMIME tests => undef;
+
+sub extract_email_address
+{
+    my ($base) = @_;
+    my $cert;
+    {
+        local $/;
+        open(my $fh, "<t/data/smime/keys/$base.crt") or die ("Cannot open t/data/smime/keys/$base.crt: $!");
+        $cert = <$fh>;
+        close($fh);
+    }
+    if ($cert =~ /^-----BEGIN \s+ CERTIFICATE----- \s* $
+    (.*?)
+    ^-----END \s+ CERTIFICATE----- \s* $/smx) {
+        $cert = MIME::Base64::decode_base64($1);
+    }
+
+    my $c = Crypt::X509->new(cert => $cert);
+    return RT::Crypt::SMIME::ExtractSubjectEmailAddress($c);
+}
+
+foreach my $addr ('dianne at skoll.ca', 'root at example.com', 'sender at example.com', 'smime at example.com') {
+    is (extract_email_address($addr), $addr, "$addr: Correct email address extracted from S/MIME certificate");
+}
+
+
+done_testing;
diff --git a/t/data/smime/keys/dianne at skoll.ca.crt b/t/data/smime/keys/dianne at skoll.ca.crt
new file mode 100644
index 0000000000..e629e26977
--- /dev/null
+++ b/t/data/smime/keys/dianne at skoll.ca.crt
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIIF2DCCA8CgAwIBAgIQeWotbvwZpc0h6+xjcJRMHzANBgkqhkiG9w0BAQsFADCB
+gTELMAkGA1UEBhMCSVQxEDAOBgNVBAgMB0JlcmdhbW8xGTAXBgNVBAcMEFBvbnRl
+IFNhbiBQaWV0cm8xFzAVBgNVBAoMDkFjdGFsaXMgUy5wLkEuMSwwKgYDVQQDDCNB
+Y3RhbGlzIENsaWVudCBBdXRoZW50aWNhdGlvbiBDQSBHMzAeFw0yMDEwMjYxOTQx
+MjJaFw0yMTEwMjYxODQxMjJaMBoxGDAWBgNVBAMMD2RpYW5uZUBza29sbC5jYTCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf0P/jWD9Ik6kc+vW8OGZvw
+kz7hAuMnIaO/BWlzVYCfcao5Yy4nZ2IERDJVn5ZCJ7mSsva0BComzvFad0M6FpzY
+G/RejmZKYF+PHEVPKbSFh2g0FlE/XWqH7XHw/LUS+kr5ZbydmV69BFkE9gZvW0Gw
+FXSvm9WOVucyom1MZNErrG6s1xBMnmDmwbIhWUPlCWCimmwJETfoCBfz7TDAVhaD
+DikSUN7PgZqpJgKyUo0uk8KvmgeHFAxwmNqrpMUqcA9TDJxygX8PCRMeShula8kD
+SM1VJpbfnDt179v/1aGc46NzDX1oWMSVmrF6hqD+FmVzBCck+WvinD3CFKggbdEC
+AwEAAaOCAbAwggGsMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUvpepqoS/gL8Q
+U30JMvnhLjIbz3cwfgYIKwYBBQUHAQEEcjBwMDsGCCsGAQUFBzAChi9odHRwOi8v
+Y2FjZXJ0LmFjdGFsaXMuaXQvY2VydHMvYWN0YWxpcy1hdXRjbGlnMzAxBggrBgEF
+BQcwAYYlaHR0cDovL29jc3AwOS5hY3RhbGlzLml0L1ZBL0FVVEhDTC1HMzAaBgNV
+HREEEzARgQ9kaWFubmVAc2tvbGwuY2EwRwYDVR0gBEAwPjA8BgYrgR8BGAEwMjAw
+BggrBgEFBQcCARYkaHR0cHM6Ly93d3cuYWN0YWxpcy5pdC9hcmVhLWRvd25sb2Fk
+MB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDBDBIBgNVHR8EQTA/MD2gO6A5
+hjdodHRwOi8vY3JsMDkuYWN0YWxpcy5pdC9SZXBvc2l0b3J5L0FVVEhDTC1HMy9n
+ZXRMYXN0Q1JMMB0GA1UdDgQWBBTKp2AtrJ2Uv2Gp8P7nnWQeFvb5eTAOBgNVHQ8B
+Af8EBAMCBaAwDQYJKoZIhvcNAQELBQADggIBAAJN7u/aFe6yLTgGJHxiPdPRv4mO
+fw3js/qAf2QTVjanMBhsvvvLFc9tprkfXOltRacYylEk3VqSDuMOwinAZvVx0g7d
+JU8jieYVAclS5bKx0LGfKWKVTEODXtNBSrxVfPQVjJLye4aXqWBfERHl7YRGKGUU
+LvaMJcYbJZI2IR4KYutGz5BIP19Jc6Lwyg2pju/2ifugYnYYpvLTwhQmaH3hf6Gx
+cL3OFoBfWZYLSBl22tdJURxTI0LOyIsR24eslxmazvGuXCpu6SR6bCc0aW4fJ5yk
+3dDlJ4PT8zdLGKxkeI+q/JXR+zZieqObkaQinhzibecq/UhqllnCb7aICuC7M8tU
+ZkIpYSHMzPJatM99/r4HcgVDpBiAJd5Py7uwuZ11PDqt6u7i469D+Z8fUWCs7I65
+BtfDWPOBo0liq3qm5qvchg+c2VF/9Bk//N/eJpmnzMsaAPLQSxnpVqxO3seA9+KM
++Ni1qjX8dN0L4/uMhLJY0Sz1L19h/8298zGrPgW6qL6kGHGJuimbHchPysLZN6x2
+dLcejDyrCnDFOnoG7pNkORKNF5RRHCfp1pCcEBIiCiZdT/YzNRYPzzSaAN3SgQpx
+VfA142WIeFE/0wqwDV2f9y9ng1AgZ6j6NoxY/SMBhvh1LMjgpW/n0K9zKXlHuA+H
+Zs2fapeVA9JAMrIG
+-----END CERTIFICATE-----
diff --git a/t/data/smime/keys/smime at example.com.crt b/t/data/smime/keys/smime at example.com.crt
new file mode 100644
index 0000000000..575c2ec094
--- /dev/null
+++ b/t/data/smime/keys/smime at example.com.crt
@@ -0,0 +1,33 @@
+-----BEGIN CERTIFICATE-----
+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
+-----END CERTIFICATE-----

-----------------------------------------------------------------------


More information about the rt-commit mailing list