jruby-openssl 0.16.1-java → 0.19.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -1,35 +1,34 @@
1
1
  # JRuby-OpenSSL
2
2
 
3
- [JRuby-OpenSSL](https://github.com/jruby/jruby-openssl) is an add-on gem for
4
- [JRuby](https://www.jruby.org/) that emulates the Ruby OpenSSL native library.
3
+ [JRuby-OpenSSL](https://github.com/jruby/jruby-openssl) is an extension gem for
4
+ [JRuby](https://www.jruby.org/) that emulates the Ruby `OpenSSL` native library.
5
5
 
6
6
  Under the hood it uses the [Bouncy Castle Crypto APIs](https://www.bouncycastle.org/java.html).
7
7
 
8
- Each jruby-openssl gem release includes the Bouncy Castle library (BC Provider and
9
- PKIX/CMS/EAC/PKCS/OCSP/TSP/OPENSSL jars), usually the latest available version.
8
+ All jruby-openssl gem releases include the Bouncy Castle library (BC Provider, BC JSSE
9
+ and PKIX/CMS/EAC/PKCS/OCSP/TSP/OPENSSL jars), usually the latest available version.
10
10
 
11
11
  Please report bugs and incompatibilities (preferably with test-cases) to either
12
12
  the JRuby [mailing list][1] or the [bug tracker][2].
13
13
 
14
14
  ## Compatibility
15
15
 
16
+ Check latest jruby-openssl gem spec's `jar` *requirements* for compatibility.
17
+
18
+ ```ruby
19
+ require 'openssl'
20
+ JOpenSSL::VERSION
21
+ ```
22
+
23
+ For older versions of the gem compatibility wasn't reported:
24
+
16
25
  | JRuby-OpenSSL | JRuby compat | JVM compat | supported BC |
17
26
  |---------------|:------------:|-----------:|-------------:|
18
- | 0.9.6 | 1.6.8-9.0.2 | Java 6-8 | 1.47-1.50 |
19
- | 0.9.12 | 1.6.8-9.0.5 | Java 6-8 | 1.47-1.52 |
20
- | 0.9.13 | 1.6.8-9.1.2 | Java 6-8 | 1.49-1.52 |
21
- | 0.9.14 | 1.6.8-9.1.5 | Java 6-8 | 1.49-1.54 |
22
- | 0.9.17 | 1.6.8-9.1.5 | Java 6-8 | 1.50-1.54 |
23
- | ~>0.9.18 | 1.6.8-9.1.x | Java 6-8 | 1.50-1.55 |
24
- | 0.10.0 | 1.7.20-9.2.x | Java 7-10 | 1.55-1.59 |
25
- | 0.10.3 | 1.7.20-9.2.x | Java 7-11 | 1.56-1.62 |
26
- | ~>0.10.5 | 1.7.20-9.3.x | Java 7-11 | 1.60-1.68 |
27
- | ~>0.11.x | 9.0.x-9.3.x | Java 7-11 | 1.62-1.68 |
28
27
  | ~>0.12.x | 9.1.x-9.3.x | Java 8-15 | 1.65-1.68 |
29
28
  | ~>0.13.x | 9.1.x-9.4.x | Java 8-17 | 1.68-1.69 |
30
29
  | ~>0.14.x | 9.1.x-9.4.x | Java 8-21 | 1.71-1.74 |
31
30
  | ~>0.15.x | 9.2.x-10.0.x | Java 8-25 | 1.78-1.83 |
32
- | ~>0.16.x | 9.3.x-10.0.x | Java 8-25 | 1.83-1.84 |
31
+ | ~>0.16.x | 9.3.x-10.0.x | Java 8-25 | 1.83-1.85 |
33
32
 
34
33
  ## Security
35
34
 
@@ -39,30 +38,103 @@ JRuby-OpenSSL is an essential part of [JRuby](https://www.jruby.org/), please re
39
38
  Please note that most OpenSSL vulnerabilities do not affect JRuby since it's not using
40
39
  any of OpenSSL's C code, only Ruby parts (*.rb) are the same as in MRI's OpenSSL library.
41
40
 
42
- ## Testing
41
+ ## Supported configuration
42
+
43
+ Most runtime knobs are Java system properties.
44
+ Under JRuby you pass them as `-J-D...` flags, e.g. `JRUBY_OPTS='-J-Djruby.openssl.debug=true'`.
45
+
46
+ ### Runtime / JVM properties
47
+
48
+ | Property | Default | Effect |
49
+ |----------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
50
+ | `jruby.openssl.load.jars` | `true` | If set to `false`, `lib/jopenssl/load.rb` skips auto-loading the bundled BouncyCastle jars - handy when the BC jars are on the JVM classpath. |
51
+ | `jruby.openssl.debug` | `false` | Turns on internal debug logging and stack traces from the Java extension, has the same effect as setting `OpenSSL.debug = true` at runtime. |
52
+ | `jruby.openssl.warn` | follows JRuby's warning mode (`runtime.warningsEnabled()`) | Enables or disables warnings from the extension, set `false` to stay quiet regardless of `-w`. |
53
+ | `jruby.openssl.log.logger` | default stdout/stderr logger | Selects the internal logger implementation, set to `JUL` to route logs through `java.util.logging`. |
54
+ | `jruby.openssl.log.silence` | `true` | Silences a few noisy BC / BC-JSSE loggers by default, set `false` to leave their levels untouched. |
55
+ | `jruby.openssl.provider.ssl` | `BCJSSE` | Selects the SSL provider. `BCJSSE`, `BC`, or `true` all mean BC-JSSE, an empty string or `false` falls back to the platform JSSE provider. |
56
+ | `jruby.openssl.ssl.error_wait_nonblock.backtrace` | falls back to `jruby.errno.backtrace` (which defaults to `false`) | Whether `SSLErrorWaitReadable` / `SSLErrorWaitWritable` carry backtraces. |
57
+ | `jruby.openssl.x509.lookup.cache` | disabled | Caching for X.509 lookup results. `true` turns on a soft cache; an integer such as `8` gives a bounded strong/soft cache of that size, unset or `false` disables it. |
58
+
59
+ ### Environment variables
60
+
61
+ | Variable | Default | Effect |
62
+ |----------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
63
+ | `SSL_CERT_FILE` | platform / packaged default CA file | Overrides the default certificate bundle used for X.509 default-path loading, `.crt`, `.cer`, or `.pem` are read as a PEM bundle, otherwise treated as a Java CA store path. |
64
+ | `SSL_CERT_DIR` | platform / packaged default CA directory | Overrides the default certificate directory list for X.509 default-path loading, separate multiple directories with the platform path separator. |
65
+ | `OPENSSL_ALLOW_PROXY_CERTS` | unset / disabled | When set to anything other than `false`, proxy certificates are allowed during certificate chain validation. |
66
+
67
+ ### Other supported customizations
68
+
69
+ - `OpenSSL.debug = true` gives you the same internal debug logging as `-Djruby.openssl.debug=true`
70
+ - when `jruby.openssl.warn` is unset, JRuby's own warning mode (`ruby -w`) decides whether warnings show
71
+ - `OpenSSL::Config` can look up variables from the process environment through the `ENV` section, matching the upstream Ruby OpenSSL config parser
72
+
73
+
74
+ ## Differences from OpenSSL
75
+
76
+ JRuby-OpenSSL aims to be a source-compatible drop-in for MRI's `openssl` - same Ruby API and
77
+ same `require 'openssl'`. But there are limitations on the JVM (with JCE and JSSE) as well as
78
+ Bouncy Castle libraries, so some entry points are unavailable, behave differently, or are no-ops.
79
+
80
+ **Engine**
81
+ - `OpenSSL::Engine` is not implemented - there is no hardware/engine layer, `OpenSSL::Engine.*`
82
+ raises `NameError` (uninitialized constant)
83
+
84
+ **SSL / TLS** (backed by JSSE)
85
+ - `SSLSocket#state` and NPN (`#npn_protocol`) are unimplemented and return `nil` - use ALPN instead
86
+ - Forced session resumption (`SSLSocket#session=`) is best-effort and only fully works with the
87
+ BouncyCastle JSSE provider; `session_reused?` may return `nil` ("can't decide")
88
+ - `SSL::Session#id=` / `#time=` are no-ops; `SSL::Session.new` on a non-socket raises `NotImplementedError`
89
+ - Hostname / `subjectAltName` matching runs over Java's certificate parsing and can differ from
90
+ MRI's `GeneralName` handling in edge cases
91
+
92
+ **Cipher** (JCE / Bouncy Castle)
93
+ - The available cipher set is provider-dependent (what JCE/BC offer on your JVM), not the fixed
94
+ libcrypto list (some OpenSSL ciphers may be missing or vary by JDK)
95
+ - CFB1 mode (`*-cfb1`) is excluded (doesn't match OpenSSL under BC)
96
+ - AEAD is limited to what JCE exposes; `iv_len=` on a non-AEAD cipher raises
43
97
 
44
- rake jar:all # creates pom.xml and generates jopenssl.jar under lib
45
- mvn test
98
+ **PKey** (EC / DH / EdDSA)
99
+ - EC is limited to prime curves (`:GFp`); binary-field curves (`:GF2m`) fail
100
+ - `EC::Point#mul` with array arguments, `:hybrid` point compression, and encrypted EC private-key
101
+ export are not implemented
102
+ - `DH#set_pqg` accepts but silently ignores the `q` parameter
103
+ - EdDSA (`Ed25519` / `Ed448`) rejects digest arguments
46
104
 
47
- This will run (JUnit as well as Ruby) tests against the default JRuby version.
48
- To pick a different JRuby version:
105
+ **X509**
106
+ - multi-valued RDNs (the `+` separator in a DN string) are not supported and raise `X509::NameError`.
107
+ - few `authorityKeyIdentifier` extension configurations are unsupported
49
108
 
50
- mvn test -Djruby.versions=9.4.14.0
109
+ **Random**
110
+ - randomness comes from the JVM's `SecureRandom`; the EGD and seed-file APIs (`Random.egd`,
111
+ `egd_bytes`, `load_random_file`, `write_random_file`) are no-ops
51
112
 
52
- For running integration tests the gem will be installed first and the same
53
- tests run for each supported Bouncy Castle version (see [listing][3]):
113
+ **Other**
114
+ - `OpenSSL.fips_mode = true` raises `NotImplementedError` unless the separate [FIPS variant](#fips)
115
+ gem is installed
116
+ - some rarely-used entry points are no-ops (`OpenSSL.check_func`, `deprecated_warning_flag`) and
117
+ `OPENSSL_NO_SOCK` is `nil` rather than a boolean
118
+ - a few PKCS7 content types can't be reconstructed purely from ASN.1 (may surface when parsing
119
+ some S/MIME structures)
54
120
 
55
- mvn verify -P test-9.4.14.0,test-9.2.21.0
121
+ Hitting something not listed here that MRI's OpenSSL supports?
122
+ Please report it on the [bug tracker][2], ideally with a test case.
56
123
 
57
- Or pick a specific Bouncy Castle version:
124
+ ## FIPS
58
125
 
59
- mvn verify -P test-9.4.14.0 -Dbc.versions=1.78
126
+ A FIPS 140-3 build of jruby-openssl is available as a separate gem.
127
+ It's the very same library but uses the NIST-validated BC FIPS module (BC-FJA) instead of
128
+ regular Bouncy Castle, for deployments that need a validated cryptographic module.
129
+ Ships separately under GPL 3.0, with commercial licensing available - see the
130
+ [FIPS variant][6] wiki page for details.
60
131
 
61
- NOTE: you can pick any JRuby version which is on [Maven Central][4] or on [ci.jruby][5]
132
+ NOTE: unlike C OpenSSL, `OpenSSL.fips_mode` cannot be changed at runtime, the flag reports
133
+ which gem variant is activated (`true` under the FIPS gem, `false` otherwise).
62
134
 
63
135
  ## License
64
136
 
65
- (c) 2009-2026 JRuby distributed under EPL 1.0/GPL 2.0/LGPL 2.1
137
+ (c) 2009-2026 JRuby distributed under EPL 1.0 / GPL 2.0 / LGPL 2.1
66
138
 
67
139
  [0]: https://github.com/jruby/jruby-openssl/security
68
140
  [1]: https://github.com/jruby/jruby/wiki/MailingLists
@@ -70,3 +142,4 @@ NOTE: you can pick any JRuby version which is on [Maven Central][4] or on [ci.jr
70
142
  [3]: https://github.com/jruby/jruby-openssl/tree/master/integration
71
143
  [4]: https://repo1.maven.org/maven2/org/jruby/
72
144
  [5]: https://www.jruby.org/nightly
145
+ [6]: https://github.com/jruby/jruby-openssl/wiki/FIPS
data/Rakefile CHANGED
@@ -1,57 +1,108 @@
1
- #-*- mode: ruby -*-
1
+ require 'rake/testtask'
2
+
3
+ mvnw = File.expand_path('./mvnw', File.dirname(__FILE__))
4
+
5
+ # reproducible build: SOURCE_DATE_EPOCH shared by jopenssl.jar and gem
6
+ # read from env by RubyGems; pass via -D so dev builds don't churn pom.xml
7
+ def source_date_epoch!
8
+ ENV['SOURCE_DATE_EPOCH'] ||= `git log -1 --pretty=%ct`.strip
9
+ end
10
+
11
+ def _build_output_timestamp
12
+ "-Dproject.build.outputTimestamp=#{ENV['SOURCE_DATE_EPOCH']}" if ENV['SOURCE_DATE_EPOCH']
13
+ end
2
14
 
3
- #Rake::Task[:jar].clear rescue nil
4
15
  desc "Package jopenssl.jar with the compiled classes"
5
16
  task :jar do
6
- sh( './mvnw prepare-package -Dmaven.test.skip=true' )
17
+ sh("#{mvnw} prepare-package -Dmaven.test.skip=true")
7
18
  end
8
- namespace :jar do
9
- desc "Package jopenssl.jar file (and dependendent jars)"
10
- task :all do
11
- sh( './mvnw package -Dmaven.test.skip=true' )
12
- end
13
- end
14
- task :test_prepare do
15
- sh( './mvnw prepare-package -Dmaven.test.skip=true' )
16
- sh( './mvnw test-compile' ) # separate step due -Dmaven.test.skip=true
19
+
20
+ task :test_prepare => :jar do
21
+ sh("#{mvnw} test-compile") # separate due -Dmaven.test.skip=true
17
22
  end
18
23
 
19
24
  task :clean do
20
- sh( './mvnw clean' )
25
+ sh("#{mvnw} clean")
21
26
  end
22
27
 
23
28
  task :build do
24
- sh( './mvnw clean package -Dmaven.test.skip=true' )
29
+ source_date_epoch!
30
+ sh("#{mvnw} -Prelease -DupdateReleaseInfo=true #{_build_output_timestamp} clean package")
31
+ end
32
+
33
+ desc "Sanity-check the tree/version, then build a reproducible release gem"
34
+ task :release => :release_check do
35
+ source_date_epoch! # pin to the release commit so the gem + jar use the same
36
+ puts "SOURCE_DATE_EPOCH=#{ENV['SOURCE_DATE_EPOCH']} (#{Time.at(ENV['SOURCE_DATE_EPOCH'].to_i).utc})"
37
+ Rake::Task[:build].invoke
38
+ gem = Dir['target/*.gem', 'pkg/*.gem'].max_by { |f| File.mtime(f) }
39
+ abort "release aborted - no .gem produced" unless gem
40
+ puts "built #{gem}"
41
+ # gem push #{gem} (or: #{File.basename(mvnw)} deploy -Pjar-release for the jar artifact)"
42
+ end
43
+
44
+ task :release_check do
45
+ dirty = `git status --porcelain`.strip
46
+ abort "release aborted - working tree is not clean:\n#{dirty}" unless dirty.empty?
47
+
48
+ load File.expand_path('lib/jopenssl/version.rb', File.dirname(__FILE__))
49
+ version = JOpenSSL::VERSION
50
+
51
+ if Gem::Version.new(version).prerelease? && ENV['PRERELEASE'] != 'true'
52
+ abort "release aborted - #{version} is a prerelease"
53
+ end
54
+
55
+ branch = `git rev-parse --abbrev-ref HEAD`.strip
56
+ warn "WARNING: releasing from '#{branch}' (not 'master')" unless branch == 'master'
57
+
58
+ tag = `git tag --points-at HEAD`.split("\n").find { |t| t =~ /#{Regexp.escape(version)}/ }
59
+ warn "WARNING: no git tag matching #{version} points at HEAD" unless tag
60
+
61
+ puts "release checks passed for #{version}"
62
+ end
63
+
64
+ desc "Build the self-contained jar-release artifacts (-Pjar-release)"
65
+ task :jar_release => :release_check do
66
+ source_date_epoch!
67
+ puts "SOURCE_DATE_EPOCH=#{ENV['SOURCE_DATE_EPOCH']} (#{Time.at(ENV['SOURCE_DATE_EPOCH'].to_i).utc})"
68
+ sh("#{mvnw} package -Pjar-release -Dmaven.test.skip=true #{_build_output_timestamp}")
69
+ # deploy (gpg-sign + push): #{File.basename(mvnw)} deploy -Prelease,jar-release -D...
25
70
  end
26
71
 
27
72
  task :default => :build
28
73
 
29
- file('lib/jopenssl.jar') { Rake::Task['jar'].invoke }
74
+ file('lib/jopenssl.jar') { Rake::Task[:jar].invoke }
75
+
76
+ file('pkg/test-classes/org/jruby/ext/openssl/SecurityHelperTest.class') do
77
+ Rake::Task[:test_prepare].invoke
78
+ end
30
79
 
31
- require 'rake/testtask'
32
80
  Rake::TestTask.new do |task|
33
- task.libs << File.expand_path('src/test/ruby', File.dirname(__FILE__))
34
- test_files = FileList['src/test/ruby/**/test*.rb'].to_a
35
- task.test_files = test_files.map { |path| path.sub('src/test/ruby/', '') }
81
+ task.libs << File.expand_path('test', File.dirname(__FILE__))
82
+ test_files = FileList['test/**/test*.rb'].to_a
83
+ task.test_files = test_files.map { |path| path.sub('test/', '') }
36
84
  task.verbose = false # using -v directly instead due issues with rake
37
85
  task.loader = :direct
38
- task.ruby_opts = [ '-v', '-C', 'src/test/ruby', '-rbundler/setup' ]
86
+ task.ruby_opts = [ '-v', '-rbundler/setup' ]
39
87
  end
40
- task :test => 'lib/jopenssl.jar'
88
+ task :test => ['lib/jopenssl.jar', 'pkg/test-classes/org/jruby/ext/openssl/SecurityHelperTest.class']
89
+
90
+ require_relative 'tasks/vendor_tests'
91
+ define_vendor_test_tasks # root + jopenssl_lib default to this tree
41
92
 
42
93
  namespace :integration do
43
- it_path = File.expand_path('../src/test/integration', __FILE__)
94
+ it_path = File.expand_path('integration', File.dirname(__FILE__))
44
95
  task :install do
45
96
  ruby "-C #{it_path} -S bundle install"
46
97
  end
47
- # desc "Run IT tests"
98
+ desc "Run tests via invoker (bc-compat)"
48
99
  task :test => 'lib/jopenssl.jar' do
49
100
  unless File.exist?(File.join(it_path, 'Gemfile.lock'))
50
- raise "bundle not installed, run `rake integration:install'"
101
+ fail "bundle not installed, run `rake integration:install'"
51
102
  end
52
103
  loader = "ARGV.each { |file| require(file) }"
53
104
  lib = [ File.expand_path('../lib', __FILE__), it_path ]
54
- test_files = FileList['src/test/integration/*_test.rb'].map { |path| path.sub('src/test/integration/', '') }
55
- ruby "-I#{lib.join(':')} -C src/test/integration -e \"#{loader}\" #{test_files.map { |f| "\"#{f}\"" }.join(' ')}"
105
+ test_files = FileList['integration/*_test.rb'].map { |path| path.sub('integration/', '') }
106
+ ruby "-I#{lib.join(':')} -C integration -e \"#{loader}\" #{test_files.map { |f| "\"#{f}\"" }.join(' ')}"
56
107
  end
57
108
  end
data/lib/jopenssl/load.rb CHANGED
@@ -1,71 +1,27 @@
1
- require 'jopenssl/version'
1
+ require_relative 'version'
2
2
 
3
- # NOTE: assuming user does pull in BC .jars from somewhere else on the CP
4
- unless ENV_JAVA['jruby.openssl.load.jars'].eql?('false')
3
+ # NOTE: assuming user does pull in BC .jars from somewhere else on the class-path
4
+ if ENV_JAVA['jruby.openssl.load.jars'] != 'false' &&
5
+ java.security.Security.getProvider('BC').nil?
5
6
  version = JOpenSSL::BOUNCY_CASTLE_VERSION
6
- begin
7
- require 'jar-dependencies'
8
- # if we have jar-dependencies we let it track the jars
7
+ bc_jars = begin
8
+ require 'jar_dependencies' unless respond_to?(:require_jar, true)
9
9
  require_jar 'org.bouncycastle', 'bcprov-jdk18on', version
10
10
  require_jar 'org.bouncycastle', 'bcpkix-jdk18on', version
11
11
  require_jar 'org.bouncycastle', 'bcutil-jdk18on', version
12
12
  require_jar 'org.bouncycastle', 'bctls-jdk18on', version
13
- bc_jars = true
13
+ true
14
14
  rescue LoadError, RuntimeError
15
- bc_jars = false
15
+ false
16
16
  end
17
17
  unless bc_jars
18
- load "org/bouncycastle/bcprov-jdk18on/#{version}/bcprov-jdk18on-#{version}.jar"
19
- load "org/bouncycastle/bcpkix-jdk18on/#{version}/bcpkix-jdk18on-#{version}.jar"
20
- load "org/bouncycastle/bcutil-jdk18on/#{version}/bcutil-jdk18on-#{version}.jar"
21
- load "org/bouncycastle/bctls-jdk18on/#{version}/bctls-jdk18on-#{version}.jar"
18
+ vendor = File.expand_path('../../vendor', __dir__)
19
+ load "#{vendor}/org/bouncycastle/bcprov-jdk18on/#{version}/bcprov-jdk18on-#{version}.jar"
20
+ load "#{vendor}/org/bouncycastle/bcpkix-jdk18on/#{version}/bcpkix-jdk18on-#{version}.jar"
21
+ load "#{vendor}/org/bouncycastle/bcutil-jdk18on/#{version}/bcutil-jdk18on-#{version}.jar"
22
+ load "#{vendor}/org/bouncycastle/bctls-jdk18on/#{version}/bctls-jdk18on-#{version}.jar"
22
23
  end
23
24
  end
24
25
 
25
26
  require 'jopenssl.jar'
26
27
  JRuby::Util.load_ext('org.jruby.ext.openssl.OpenSSL')
27
-
28
- # NOTE: content bellow should live in *lib/openssl.rb* but due RubyGems/Bundler
29
- # `autoload :OpenSSL` this will cause issues if an older version (0.11) is the
30
- # default gem under JRuby 9.2 (which on auto-load does not trigger a dynamic
31
- # require - this is only fixed in JRuby 9.3)
32
-
33
- module OpenSSL
34
- autoload :Config, 'openssl/config' unless const_defined?(:Config, false)
35
- autoload :ConfigError, 'openssl/config' unless const_defined?(:ConfigError, false)
36
- autoload :PKCS12, 'openssl/pkcs12'
37
- end
38
-
39
- =begin
40
- = Info
41
- 'OpenSSL for Ruby 2' project
42
- Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
43
- All rights reserved.
44
-
45
- = Licence
46
- This program is licensed under the same licence as Ruby.
47
- (See the file 'LICENCE'.)
48
- =end
49
-
50
- require 'openssl/bn'
51
- require 'openssl/pkey'
52
- require 'openssl/cipher'
53
- require 'openssl/digest'
54
- require 'openssl/hmac'
55
- require 'openssl/x509'
56
- require 'openssl/ssl'
57
- require 'openssl/pkcs5'
58
-
59
- module OpenSSL
60
- # call-seq:
61
- # OpenSSL.secure_compare(string, string) -> boolean
62
- #
63
- # Constant time memory comparison. Inputs are hashed using SHA-256 to mask
64
- # the length of the secret. Returns +true+ if the strings are identical,
65
- # +false+ otherwise.
66
- def self.secure_compare(a, b)
67
- hashed_a = OpenSSL::Digest.digest('SHA256', a)
68
- hashed_b = OpenSSL::Digest.digest('SHA256', b)
69
- OpenSSL.fixed_length_secure_compare(hashed_a, hashed_b) && a == b
70
- end
71
- end
@@ -1,10 +1,5 @@
1
+ # frozen_string_literal: true
1
2
  module JOpenSSL
2
- VERSION = '0.16.1'
3
- BOUNCY_CASTLE_VERSION = '1.84'
4
- end
5
-
6
- Object.class_eval do
7
- Jopenssl = JOpenSSL
8
- private_constant :Jopenssl if respond_to?(:private_constant)
9
- deprecate_constant :Jopenssl if respond_to?(:deprecate_constant)
3
+ VERSION = '0.19.0'
4
+ BOUNCY_CASTLE_VERSION = '1.85'
10
5
  end
data/lib/jopenssl.jar CHANGED
Binary file
@@ -80,7 +80,9 @@ module OpenSSL
80
80
  section = 'default'
81
81
  data = {section => {}}
82
82
  io_stack = [io]
83
- while definition = get_definition(io_stack)
83
+ # absolute paths of the currently-open .include chain, to break include cycles
84
+ included = [nil]
85
+ while definition = get_definition(io_stack, included)
84
86
  definition = clear_comments(definition)
85
87
  next if definition.empty?
86
88
  case definition
@@ -100,11 +102,16 @@ module OpenSSL
100
102
  end
101
103
 
102
104
  files.each do |filename|
105
+ real = File.expand_path(filename)
106
+ if included.include?(real)
107
+ raise ConfigError, "include cycle detected: '%s'" % filename
108
+ end
103
109
  begin
104
110
  io_stack << StringIO.new(File.read(filename))
105
111
  rescue
106
112
  raise ConfigError, "could not include file '%s'" % filename
107
113
  end
114
+ included << real
108
115
  end
109
116
  when /\A([^:\s]*)(?:::([^:\s]*))?\s*=(.*)\z/
110
117
  if $2
@@ -229,10 +236,10 @@ module OpenSSL
229
236
  scanned.join
230
237
  end
231
238
 
232
- def get_definition(io_stack)
233
- if line = get_line(io_stack)
239
+ def get_definition(io_stack, included = nil)
240
+ if line = get_line(io_stack, included)
234
241
  while /[^\\]\\\z/ =~ line
235
- if extra = get_line(io_stack)
242
+ if extra = get_line(io_stack, included)
236
243
  line += extra
237
244
  else
238
245
  break
@@ -242,12 +249,13 @@ module OpenSSL
242
249
  end
243
250
  end
244
251
 
245
- def get_line(io_stack)
252
+ def get_line(io_stack, included = nil)
246
253
  while io = io_stack.last
247
254
  if line = io.gets
248
255
  return line.gsub(/[\r\n]*/, '')
249
256
  end
250
257
  io_stack.pop
258
+ included.pop if included
251
259
  end
252
260
  end
253
261
  end
data/lib/openssl/ssl.rb CHANGED
@@ -12,6 +12,7 @@
12
12
 
13
13
  require "openssl/buffering"
14
14
  require "io/nonblock"
15
+ require "ipaddr"
15
16
  require "socket"
16
17
 
17
18
  module OpenSSL
@@ -84,7 +85,6 @@ YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3
84
85
 
85
86
  DEFAULT_CERT_STORE = OpenSSL::X509::Store.new # :nodoc:
86
87
  DEFAULT_CERT_STORE.set_default_paths
87
- DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
88
88
 
89
89
  # A callback invoked when DH parameters are required for ephemeral DH key
90
90
  # exchange.
@@ -137,7 +137,7 @@ YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3
137
137
  # used.
138
138
  def set_params(params={})
139
139
  params = DEFAULT_PARAMS.merge(params)
140
- self.options = params.delete(:options) # set before min_version/max_version
140
+ self.options |= params.delete(:options) # set before min_version/max_version
141
141
  params.each{ |name, value| self.__send__("#{name}=", value) }
142
142
  if self.verify_mode != OpenSSL::SSL::VERIFY_NONE
143
143
  unless self.ca_file or self.ca_path or self.cert_store
@@ -319,15 +319,10 @@ YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3
319
319
  #when 7 # iPAddress in GeneralName (RFC5280)
320
320
  elsif /\AIP(?: Address)?:(.*)/ =~ general_name
321
321
  should_verify_common_name = false
322
- return true if $1 == hostname
323
- # NOTE: bellow logic makes little sense JRuby reads exts differently
324
- # follows GENERAL_NAME_print() in x509v3/v3_alt.c
325
- # if san.value.size == 4 || san.value.size == 16
326
- # begin
327
- # return true if $1 == IPAddr.new(hostname).to_s
328
- # rescue IPAddr::InvalidAddressError
329
- # end
330
- # end
322
+ begin
323
+ return true if IPAddr.new($1) == IPAddr.new(hostname)
324
+ rescue IPAddr::InvalidAddressError
325
+ end
331
326
  end
332
327
  }
333
328
  }
@@ -431,6 +426,13 @@ YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3
431
426
  # This method MUST be called after calling #connect to ensure that the
432
427
  # hostname of a remote peer has been verified.
433
428
  def post_connection_check(hostname)
429
+ # if connect already verified this hostname (via verify_hostname), skip;
430
+ # avoids double-verification in libraries that call post_connection_check
431
+ if defined?(@verified_hostname) && @verified_hostname == hostname
432
+ @verified_hostname = nil
433
+ return true
434
+ end
435
+
434
436
  if peer_cert.nil?
435
437
  msg = "Peer verification enabled, but no certificate received."
436
438
  if using_anon_cipher?
@@ -446,6 +448,14 @@ YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3
446
448
  return true
447
449
  end
448
450
 
451
+ # @private JRuby due having to call this outside of post_connection_check
452
+ def verify_certificate_identity_internal(hostname)
453
+ peer_cert = self.peer_cert
454
+ return nil if peer_cert.nil?
455
+ OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname)
456
+ end
457
+ private :verify_certificate_identity_internal
458
+
449
459
  # call-seq:
450
460
  # ssl.session -> aSession
451
461
  #
data/lib/openssl.rb CHANGED
@@ -1,3 +1,46 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'jopenssl/load'
4
+
5
+ module OpenSSL
6
+ autoload :Config, 'openssl/config' unless const_defined?(:Config, false)
7
+ autoload :ConfigError, 'openssl/config' unless const_defined?(:ConfigError, false)
8
+ end
9
+
10
+ =begin
11
+ = Info
12
+ 'OpenSSL for Ruby 2' project
13
+ Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
14
+ All rights reserved.
15
+
16
+ = Licence
17
+ This program is licensed under the same licence as Ruby.
18
+ (See the file 'COPYING'.)
19
+ =end
20
+
21
+ require 'openssl/bn'
22
+ require 'openssl/cipher'
23
+ require 'openssl/digest'
24
+ require 'openssl/hmac'
25
+ require 'openssl/pkcs5'
26
+ require 'openssl/pkey'
27
+ require 'openssl/ssl'
28
+ require 'openssl/x509'
29
+
30
+ module OpenSSL
31
+ # :call-seq:
32
+ # OpenSSL.secure_compare(string, string) -> true or false
33
+ #
34
+ # Constant time memory comparison. Inputs are hashed using SHA-256 to mask
35
+ # the length of the secret. Returns +true+ if the strings are identical,
36
+ # +false+ otherwise.
37
+ #
38
+ # This method is expensive due to the SHA-256 hashing. In most cases, where
39
+ # the input lengths are known to be equal or are not sensitive,
40
+ # OpenSSL.fixed_length_secure_compare should be used instead.
41
+ def self.secure_compare(a, b)
42
+ hashed_a = OpenSSL::Digest.digest('SHA256', a)
43
+ hashed_b = OpenSSL::Digest.digest('SHA256', b)
44
+ OpenSSL.fixed_length_secure_compare(hashed_a, hashed_b) && a == b
45
+ end
46
+ end