jruby-openssl 0.16.2-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/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.2'
3
+ VERSION = '0.19.0'
3
4
  BOUNCY_CASTLE_VERSION = '1.85'
4
5
  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)
10
- 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