Skip to content

Commit ad93636

Browse files
committed
keep in line with MRI if possible
keep the default x509 certs and directories in line with MRI, only if they do not exists fallback on cacerts from the java.home/lib/security/cacerts fixes #49, #70 and keeps the idea of b914091 Sponsored by Lookout Inc.
1 parent 3b4bc77 commit ad93636

File tree

8 files changed

+188
-19
lines changed

8 files changed

+188
-19
lines changed

src/main/java/org/jruby/ext/openssl/x509store/Lookup.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -352,8 +352,7 @@ else if ( cert instanceof CRL ) {
352352
}
353353
}
354354

355-
public int loadDefaultJavaCACertsFile() throws IOException, GeneralSecurityException {
356-
final String certsFile = X509Utils.X509_CERT_FILE.replace('/', File.separatorChar);
355+
public int loadDefaultJavaCACertsFile(String certsFile) throws IOException, GeneralSecurityException {
357356
final FileInputStream fin = new FileInputStream(certsFile);
358357
int count = 0;
359358
try {
@@ -517,15 +516,15 @@ public int call(final Lookup ctx, final Integer cmd, final String argp, final Nu
517516
file = ctx.envEntry( getDefaultCertificateFileEnvironment() );
518517
}
519518
catch (RuntimeException e) { }
520-
521-
if (file != null) {
519+
if (file == null) {
520+
file = X509Utils.X509_CERT_FILE.replace('/', File.separatorChar);
521+
}
522+
if (file.matches(".*\\.(crt|cer|pem)$")) {
522523
ok = ctx.loadCertificateOrCRLFile(file, X509_FILETYPE_PEM) != 0 ? 1 : 0;
523524
} else {
524-
ok = (ctx.loadDefaultJavaCACertsFile() != 0) ? 1: 0;
525-
}
526-
if (ok == 0) {
527-
X509Error.addError(X509_R_LOADING_DEFAULTS);
525+
ok = (ctx.loadDefaultJavaCACertsFile(file) != 0) ? 1: 0;
528526
}
527+
// we ignore errors on loading default paths the same way MRI does it
529528
} else {
530529
if (arglInt == X509_FILETYPE_PEM) {
531530
ok = (ctx.loadCertificateOrCRLFile(argp, X509_FILETYPE_PEM) != 0) ? 1 : 0;

src/main/java/org/jruby/ext/openssl/x509store/X509Utils.java

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
package org.jruby.ext.openssl.x509store;
2929

3030

31+
import java.io.File;
3132
import java.io.IOException;
3233
import java.math.BigInteger;
3334
import java.util.Arrays;
@@ -292,13 +293,48 @@ else if ( keyUsage != null && ! keyUsage[5] ) { // KU_KEY_CERT_SIGN
292293
public static final String X509_PRIVATE_DIR;
293294

294295
static {
295-
OPENSSLDIR = "/usr/local/openssl"; // NOTE: blindly follow?!
296+
// roughly following the ideas from https://www.happyassassin.net/2015/01/12/a-note-about-ssltls-trusted-certificate-stores-and-platforms/
297+
// and falling back to trust store from java to be on the save side
298+
296299
// TODO usability in limited environments should be tested/reviewed
297300
final String JAVA_HOME = SafePropertyAccessor.getProperty("java.home", "");
298-
X509_CERT_AREA = JAVA_HOME + "/lib/security";
299-
X509_CERT_DIR = X509_CERT_AREA;
300-
X509_CERT_FILE = X509_CERT_DIR + "/cacerts";
301-
X509_PRIVATE_DIR = "/usr/lib/ssl/private"; // NOTE: blindly follow?!
301+
302+
// if the default files/dirs exist we use them. with this a switch
303+
// from MRI to JRuby produces the same results. otherwise we use the
304+
// certs from JAVA_HOME.
305+
final String MAYBE_CERT_FILE;
306+
final String LINUX_CERT_AREA = "/etc/ssl";
307+
final String MACOS_CERT_AREA = "/System/Library/OpenSSL";
308+
final String MAYBE_PKI_CERT_FILE = "/etc/pki/tls/certs/ca-bundle.crt";
309+
if (new File(LINUX_CERT_AREA).exists()) {
310+
X509_CERT_AREA = LINUX_CERT_AREA;
311+
X509_CERT_DIR = X509_CERT_AREA + "/certs";
312+
X509_PRIVATE_DIR = X509_CERT_AREA + "/private";
313+
MAYBE_CERT_FILE = X509_CERT_DIR + "/cert.pem";
314+
}
315+
else if (new File(MACOS_CERT_AREA).exists()) {
316+
X509_CERT_AREA = MACOS_CERT_AREA;
317+
X509_CERT_DIR = X509_CERT_AREA + "/certs";
318+
X509_PRIVATE_DIR = X509_CERT_AREA + "/private";
319+
MAYBE_CERT_FILE = X509_CERT_AREA + "/cert.pem";
320+
}
321+
else {
322+
X509_CERT_AREA = JAVA_HOME + "/lib/security";
323+
X509_CERT_DIR = X509_CERT_AREA;
324+
X509_PRIVATE_DIR = X509_CERT_AREA;
325+
MAYBE_CERT_FILE = MAYBE_PKI_CERT_FILE;
326+
}
327+
if (new File(MAYBE_PKI_CERT_FILE).exists()) {
328+
X509_CERT_FILE = MAYBE_PKI_CERT_FILE;
329+
}
330+
else if (new File(MAYBE_CERT_FILE).exists()) {
331+
X509_CERT_FILE = MAYBE_CERT_FILE;
332+
}
333+
else {
334+
X509_CERT_FILE = JAVA_HOME + "/lib/security/cacerts";
335+
}
336+
// keep it with some meaninful content as it is a public constant
337+
OPENSSLDIR = X509_CERT_AREA;
302338
}
303339

304340
public static final String X509_CERT_DIR_EVP = "SSL_CERT_DIR";

src/test/ruby/x509/ca.crt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIICATCCAWoCCQDbLK0ArLx6CTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB
3+
VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0
4+
cyBQdHkgTHRkMB4XDTE1MDkxMDE2NDIyNVoXDTQzMDEyNjE2NDIyNVowRTELMAkG
5+
A1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0
6+
IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAy3aH
7+
N4Pci0FwOpfwxFXKQ1IlXWrfUIuWTJs4bPek3kKmM4eJOfMLnQ2f/i0nrI1JHJBn
8+
GTMqiXti8lRhdy0HONVCVolc9rycdIj/batAwbCLxhg5lQMVOWzIJ3fW5R5DEcKK
9+
87PN8Dpf4nn9b2zyszGroExqgVFcp5q2zDzD+b0CAwEAATANBgkqhkiG9w0BAQUF
10+
AAOBgQCu+bibmVksOHFauNRRt2uDLzNw6rDJyL9X3UC6Wu2Dp8Sk44RxR+qNQMS/
11+
CqgW9P7TWZdhsRUcnVRpaRMsr8CpTzHMmKaR0APON7v1C0HaV0CBYfzuNraAnlsq
12+
e7KpTHJ+mwxwVvN1XDv/jGqiw83p1wA4jyxQe59Cmubv+jGksQ==
13+
-----END CERTIFICATE-----

src/test/ruby/x509/digicert.pem

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIEtjCCA56gAwIBAgIQDHmpRLCMEZUgkmFf4msdgzANBgkqhkiG9w0BAQsFADBs
3+
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
4+
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
5+
ZSBFViBSb290IENBMB4XDTEzMTAyMjEyMDAwMFoXDTI4MTAyMjEyMDAwMFowdTEL
6+
MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
7+
LmRpZ2ljZXJ0LmNvbTE0MDIGA1UEAxMrRGlnaUNlcnQgU0hBMiBFeHRlbmRlZCBW
8+
YWxpZGF0aW9uIFNlcnZlciBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
9+
ggEBANdTpARR+JmmFkhLZyeqk0nQOe0MsLAAh/FnKIaFjI5j2ryxQDji0/XspQUY
10+
uD0+xZkXMuwYjPrxDKZkIYXLBxA0sFKIKx9om9KxjxKws9LniB8f7zh3VFNfgHk/
11+
LhqqqB5LKw2rt2O5Nbd9FLxZS99RStKh4gzikIKHaq7q12TWmFXo/a8aUGxUvBHy
12+
/Urynbt/DvTVvo4WiRJV2MBxNO723C3sxIclho3YIeSwTQyJ3DkmF93215SF2AQh
13+
cJ1vb/9cuhnhRctWVyh+HA1BV6q3uCe7seT6Ku8hI3UarS2bhjWMnHe1c63YlC3k
14+
8wyd7sFOYn4XwHGeLN7x+RAoGTMCAwEAAaOCAUkwggFFMBIGA1UdEwEB/wQIMAYB
15+
Af8CAQAwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF
16+
BQcDAjA0BggrBgEFBQcBAQQoMCYwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRp
17+
Z2ljZXJ0LmNvbTBLBgNVHR8ERDBCMECgPqA8hjpodHRwOi8vY3JsNC5kaWdpY2Vy
18+
dC5jb20vRGlnaUNlcnRIaWdoQXNzdXJhbmNlRVZSb290Q0EuY3JsMD0GA1UdIAQ2
19+
MDQwMgYEVR0gADAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5j
20+
b20vQ1BTMB0GA1UdDgQWBBQ901Cl1qCt7vNKYApl0yHU+PjWDzAfBgNVHSMEGDAW
21+
gBSxPsNpA/i/RwHUmCYaCALvY2QrwzANBgkqhkiG9w0BAQsFAAOCAQEAnbbQkIbh
22+
hgLtxaDwNBx0wY12zIYKqPBKikLWP8ipTa18CK3mtlC4ohpNiAexKSHc59rGPCHg
23+
4xFJcKx6HQGkyhE6V6t9VypAdP3THYUYUN9XR3WhfVUgLkc3UHKMf4Ib0mKPLQNa
24+
2sPIoc4sUqIAY+tzunHISScjl2SFnjgOrWNoPLpSgVh5oywM395t6zHyuqB8bPEs
25+
1OG9d4Q3A84ytciagRpKkk47RpqF/oOi+Z6Mo8wNXrM9zwR4jxQUezKcxwCmXMS1
26+
oVWNWlZopCJwqjyBcdmdqEU79OX2olHdx3ti6G8MdOu42vi/hw15UJGQmxg7kVkn
27+
8TUoE6smftX3eg==
28+
-----END CERTIFICATE-----

src/test/ruby/x509/gibberish.pem

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
something but not any pem section

src/test/ruby/x509/server.crt

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
Certificate:
2+
Data:
3+
Version: 1 (0x0)
4+
Serial Number: 1 (0x1)
5+
Signature Algorithm: md5WithRSAEncryption
6+
Issuer: C=AU, ST=Some-State, O=Internet Widgits Pty Ltd
7+
Validity
8+
Not Before: Sep 10 16:45:04 2015 GMT
9+
Not After : Sep 9 16:45:04 2016 GMT
10+
Subject: C=AU, ST=Some-State, O=Internet Widgits Pty Ltd, CN=example.com
11+
Subject Public Key Info:
12+
Public Key Algorithm: rsaEncryption
13+
RSA Public Key: (1024 bit)
14+
Modulus (1024 bit):
15+
00:db:95:d0:12:c8:78:dc:eb:c2:6f:4a:ea:d2:cc:
16+
21:e1:e9:16:69:11:84:25:c6:d0:2a:4c:a9:50:7a:
17+
23:cb:89:ba:40:d9:14:7a:72:19:90:44:20:46:b0:
18+
5d:f2:f6:6f:53:e2:f0:6a:e5:1c:0e:08:4e:0e:89:
19+
96:af:97:6b:a3:bd:0a:bb:5f:b8:64:d2:12:ed:66:
20+
2c:64:36:90:41:78:61:95:72:84:da:50:53:f2:a4:
21+
02:a2:b2:9b:ee:7d:d4:bd:26:07:06:28:80:af:16:
22+
e1:3b:73:9a:93:dd:48:98:52:0a:cd:6a:d2:9a:95:
23+
02:a5:2c:b6:b7:eb:1f:de:5d
24+
Exponent: 65537 (0x10001)
25+
Signature Algorithm: md5WithRSAEncryption
26+
76:a4:3c:20:c8:4d:a2:bf:ac:34:93:a4:50:58:68:f1:a6:72:
27+
db:eb:27:00:f4:2d:81:97:cb:b8:7f:a6:21:45:53:dc:2d:a4:
28+
3a:62:66:bb:8b:a3:30:b1:e8:2d:d4:19:0d:36:22:2e:1d:77:
29+
f9:bc:b8:9a:47:7a:60:70:83:04:52:a5:e0:14:c9:2e:18:38:
30+
8a:7b:10:da:0a:48:45:3f:7c:97:65:aa:ea:0c:ae:9f:77:c0:
31+
9f:30:1c:e4:55:29:21:cf:b4:ba:60:72:b2:be:4e:29:9f:d3:
32+
1f:c3:82:ed:04:87:b7:11:3f:4a:71:84:9d:34:b8:bf:4f:41:
33+
f0:ed
34+
-----BEGIN CERTIFICATE-----
35+
MIICDzCCAXgCAQEwDQYJKoZIhvcNAQEEBQAwRTELMAkGA1UEBhMCQVUxEzARBgNV
36+
BAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0
37+
ZDAeFw0xNTA5MTAxNjQ1MDRaFw0xNjA5MDkxNjQ1MDRaMFsxCzAJBgNVBAYTAkFV
38+
MRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRz
39+
IFB0eSBMdGQxFDASBgNVBAMTC2V4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUA
40+
A4GNADCBiQKBgQDbldASyHjc68JvSurSzCHh6RZpEYQlxtAqTKlQeiPLibpA2RR6
41+
chmQRCBGsF3y9m9T4vBq5RwOCE4OiZavl2ujvQq7X7hk0hLtZixkNpBBeGGVcoTa
42+
UFPypAKispvufdS9JgcGKICvFuE7c5qT3UiYUgrNatKalQKlLLa36x/eXQIDAQAB
43+
MA0GCSqGSIb3DQEBBAUAA4GBAHakPCDITaK/rDSTpFBYaPGmctvrJwD0LYGXy7h/
44+
piFFU9wtpDpiZruLozCx6C3UGQ02Ii4dd/m8uJpHemBwgwRSpeAUyS4YOIp7ENoK
45+
SEU/fJdlquoMrp93wJ8wHORVKSHPtLpgcrK+Timf0x/Dgu0Eh7cRP0pxhJ00uL9P
46+
QfDt
47+
-----END CERTIFICATE-----

src/test/ruby/x509/store

578 Bytes
Binary file not shown.

src/test/ruby/x509/test_x509store.rb

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,66 @@
33

44
class TestX509Store < TestCase
55

6-
if defined? JRUBY_VERSION
7-
def setup; require 'jopenssl/load' end
8-
else
9-
def setup; require 'openssl' end
6+
def setup
7+
require 'openssl'
8+
@cert = OpenSSL::X509::Certificate.new(File.read(File.expand_path('../server.crt', __FILE__)))
9+
@ca_cert = File.expand_path('../ca.crt', __FILE__)
10+
@javastore = File.expand_path('../store', __FILE__)
11+
@pem = File.expand_path('../EntrustnetSecureServerCertificationAuthority.pem', __FILE__)
12+
end
13+
14+
def test_store_location_with_pem
15+
ENV['SSL_CERT_FILE'] = nil
16+
store = OpenSSL::X509::Store.new
17+
store.set_default_paths
18+
assert !store.verify(@cert)
19+
20+
ENV['SSL_CERT_FILE'] = @ca_cert
21+
store = OpenSSL::X509::Store.new
22+
assert !store.verify(@cert)
23+
store.set_default_paths
24+
assert store.verify(@cert)
25+
end
26+
27+
def test_store_location_with_java_truststore
28+
ENV['SSL_CERT_FILE'] = @javastore
29+
store = OpenSSL::X509::Store.new
30+
assert !store.verify(@cert)
31+
store.set_default_paths
32+
assert store.verify(@cert)
33+
end
34+
35+
def test_use_gibberish_cert_file
36+
ENV['SSL_CERT_FILE'] = File.expand_path('../gibberish.pem', __FILE__)
37+
store = OpenSSL::X509::Store.new
38+
store.set_default_paths
39+
assert !store.verify(@cert)
40+
end
41+
42+
def test_use_default_cert_file_as_custom_file
43+
ENV['SSL_CERT_FILE'] = OpenSSL::X509::DEFAULT_CERT_FILE
44+
store = OpenSSL::X509::Store.new
45+
store.set_default_paths
46+
cert = OpenSSL::X509::Certificate.new(File.read(File.expand_path('../digicert.pem', __FILE__)))
47+
assert store.verify(cert)
48+
end
49+
50+
def test_add_file_to_store_with_custom_cert_file
51+
ENV['SSL_CERT_FILE'] = @ca_cert
52+
store = OpenSSL::X509::Store.new
53+
store.set_default_paths
54+
store.add_file @pem
55+
assert store.verify( OpenSSL::X509::Certificate.new(File.read(@pem)))
1056
end
1157

1258
def test_add_cert_concurrently
13-
pem = File.expand_path('../EntrustnetSecureServerCertificationAuthority.pem', __FILE__)
1459
store = OpenSSL::X509::Store.new
1560
t = []
1661
(0..25).each do |i|
1762

1863
t << Thread.new do
1964
(0..2).each do
20-
store.add_file pem
65+
store.add_file @pem
2166
end
2267
end
2368
end

0 commit comments

Comments
 (0)