jruby-openssl-maven 0.7.4.1
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/History.txt +171 -0
- data/License.txt +30 -0
- data/Manifest.txt +115 -0
- data/README.txt +13 -0
- data/Rakefile +79 -0
- data/lib/jopenssl.jar +0 -0
- data/lib/jopenssl/version.rb +5 -0
- data/lib/openssl.rb +76 -0
- data/lib/openssl/bn.rb +35 -0
- data/lib/openssl/buffering.rb +239 -0
- data/lib/openssl/cipher.rb +65 -0
- data/lib/openssl/config.rb +316 -0
- data/lib/openssl/digest.rb +61 -0
- data/lib/openssl/dummy.rb +33 -0
- data/lib/openssl/dummyssl.rb +14 -0
- data/lib/openssl/pkcs7.rb +25 -0
- data/lib/openssl/ssl.rb +179 -0
- data/lib/openssl/x509.rb +154 -0
- data/test/cert_with_ec_pk.cer +27 -0
- data/test/fixture/ca-bundle.crt +2794 -0
- data/test/fixture/ca_path/72fa7371.0 +19 -0
- data/test/fixture/ca_path/verisign.pem +19 -0
- data/test/fixture/cacert.pem +23 -0
- data/test/fixture/cert_localhost.pem +19 -0
- data/test/fixture/common.pem +48 -0
- data/test/fixture/imaps/cacert.pem +60 -0
- data/test/fixture/imaps/server.crt +61 -0
- data/test/fixture/imaps/server.key +15 -0
- data/test/fixture/key_then_cert.pem +34 -0
- data/test/fixture/keypair.pem +27 -0
- data/test/fixture/localhost_keypair.pem +18 -0
- data/test/fixture/max.pem +29 -0
- data/test/fixture/purpose/b70a5bc1.0 +24 -0
- data/test/fixture/purpose/ca/PASSWD_OF_CA_KEY_IS_1234 +0 -0
- data/test/fixture/purpose/ca/ca_config.rb +37 -0
- data/test/fixture/purpose/ca/cacert.pem +24 -0
- data/test/fixture/purpose/ca/newcerts/2_cert.pem +19 -0
- data/test/fixture/purpose/ca/newcerts/3_cert.pem +19 -0
- data/test/fixture/purpose/ca/private/cakeypair.pem +30 -0
- data/test/fixture/purpose/ca/serial +1 -0
- data/test/fixture/purpose/cacert.pem +24 -0
- data/test/fixture/purpose/scripts/gen_cert.rb +127 -0
- data/test/fixture/purpose/scripts/gen_csr.rb +50 -0
- data/test/fixture/purpose/scripts/init_ca.rb +66 -0
- data/test/fixture/purpose/sslclient.pem +19 -0
- data/test/fixture/purpose/sslclient/csr.pem +10 -0
- data/test/fixture/purpose/sslclient/keypair.pem +15 -0
- data/test/fixture/purpose/sslclient/sslclient.pem +19 -0
- data/test/fixture/purpose/sslserver.pem +19 -0
- data/test/fixture/purpose/sslserver/csr.pem +10 -0
- data/test/fixture/purpose/sslserver/keypair.pem +15 -0
- data/test/fixture/purpose/sslserver/sslserver.pem +19 -0
- data/test/fixture/selfcert.pem +23 -0
- data/test/fixture/verisign.pem +19 -0
- data/test/fixture/verisign_c3.pem +14 -0
- data/test/java/pkcs7_mime_enveloped.message +19 -0
- data/test/java/pkcs7_mime_signed.message +30 -0
- data/test/java/pkcs7_multipart_signed.message +45 -0
- data/test/java/test_java_attribute.rb +25 -0
- data/test/java/test_java_bio.rb +42 -0
- data/test/java/test_java_mime.rb +173 -0
- data/test/java/test_java_pkcs7.rb +772 -0
- data/test/java/test_java_smime.rb +177 -0
- data/test/openssl/ssl_server.rb +99 -0
- data/test/openssl/test_asn1.rb +197 -0
- data/test/openssl/test_cipher.rb +193 -0
- data/test/openssl/test_config.rb +290 -0
- data/test/openssl/test_digest.rb +88 -0
- data/test/openssl/test_ec.rb +128 -0
- data/test/openssl/test_hmac.rb +46 -0
- data/test/openssl/test_ns_spki.rb +59 -0
- data/test/openssl/test_pair.rb +141 -0
- data/test/openssl/test_pkcs7.rb +489 -0
- data/test/openssl/test_pkey_rsa.rb +49 -0
- data/test/openssl/test_ssl.rb +1035 -0
- data/test/openssl/test_x509cert.rb +277 -0
- data/test/openssl/test_x509crl.rb +253 -0
- data/test/openssl/test_x509ext.rb +99 -0
- data/test/openssl/test_x509name.rb +290 -0
- data/test/openssl/test_x509req.rb +195 -0
- data/test/openssl/test_x509store.rb +246 -0
- data/test/openssl/utils.rb +144 -0
- data/test/ref/a.out +0 -0
- data/test/ref/compile.rb +8 -0
- data/test/ref/pkcs1 +0 -0
- data/test/ref/pkcs1.c +21 -0
- data/test/test_all.rb +1 -0
- data/test/test_certificate.rb +123 -0
- data/test/test_cipher.rb +197 -0
- data/test/test_imaps.rb +107 -0
- data/test/test_integration.rb +144 -0
- data/test/test_java.rb +98 -0
- data/test/test_openssl.rb +4 -0
- data/test/test_parse_certificate.rb +27 -0
- data/test/test_pkcs7.rb +40 -0
- data/test/test_pkey.rb +204 -0
- data/test/test_ssl.rb +97 -0
- data/test/test_x509store.rb +160 -0
- data/test/ut_eof.rb +128 -0
- metadata +161 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
= $RCSfile$ -- Ruby-space predefined Digest subclasses
|
|
3
|
+
|
|
4
|
+
= Info
|
|
5
|
+
'OpenSSL for Ruby 2' project
|
|
6
|
+
Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
|
|
7
|
+
All rights reserved.
|
|
8
|
+
|
|
9
|
+
= Licence
|
|
10
|
+
This program is licenced under the same licence as Ruby.
|
|
11
|
+
(See the file 'LICENCE'.)
|
|
12
|
+
|
|
13
|
+
= Version
|
|
14
|
+
$Id: digest.rb 15600 2008-02-25 08:48:57Z technorama $
|
|
15
|
+
=end
|
|
16
|
+
|
|
17
|
+
##
|
|
18
|
+
# Should we care what if somebody require this file directly?
|
|
19
|
+
#require 'openssl'
|
|
20
|
+
|
|
21
|
+
module OpenSSL
|
|
22
|
+
class Digest
|
|
23
|
+
|
|
24
|
+
alg = %w(DSS DSS1 MD2 MD4 MD5 MDC2 RIPEMD160 SHA SHA1)
|
|
25
|
+
if OPENSSL_VERSION_NUMBER > 0x00908000
|
|
26
|
+
alg += %w(SHA224 SHA256 SHA384 SHA512)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.digest(name, data)
|
|
30
|
+
super(data, name)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
alg.each{|name|
|
|
34
|
+
klass = Class.new(Digest){
|
|
35
|
+
define_method(:initialize){|*data|
|
|
36
|
+
if data.length > 1
|
|
37
|
+
raise ArgumentError,
|
|
38
|
+
"wrong number of arguments (#{data.length} for 1)"
|
|
39
|
+
end
|
|
40
|
+
super(name, data.first)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
singleton = (class <<klass; self; end)
|
|
44
|
+
singleton.class_eval{
|
|
45
|
+
define_method(:digest){|data| Digest.digest(name, data) }
|
|
46
|
+
define_method(:hexdigest){|data| Digest.hexdigest(name, data) }
|
|
47
|
+
}
|
|
48
|
+
const_set(name, klass)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
# This class is only provided for backwards compatibility. Use OpenSSL::Digest in the future.
|
|
52
|
+
class Digest < Digest
|
|
53
|
+
def initialize(*args)
|
|
54
|
+
# add warning
|
|
55
|
+
super(*args)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end # Digest
|
|
60
|
+
end # OpenSSL
|
|
61
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
warn "OpenSSL ASN1/PKey/X509/Netscape/PKCS7 implementation unavailable"
|
|
2
|
+
warn "gem install bouncy-castle-java for full support."
|
|
3
|
+
module OpenSSL
|
|
4
|
+
module ASN1
|
|
5
|
+
class ASN1Error < OpenSSLError; end
|
|
6
|
+
class ASN1Data; end
|
|
7
|
+
class Primitive; end
|
|
8
|
+
class Constructive; end
|
|
9
|
+
end
|
|
10
|
+
module X509
|
|
11
|
+
class Name; end
|
|
12
|
+
class Certificate; end
|
|
13
|
+
class Extension; end
|
|
14
|
+
class CRL; end
|
|
15
|
+
class Revoked; end
|
|
16
|
+
class Store
|
|
17
|
+
def set_default_paths; end
|
|
18
|
+
end
|
|
19
|
+
class Request; end
|
|
20
|
+
class Attribute; end
|
|
21
|
+
end
|
|
22
|
+
module Netscape
|
|
23
|
+
class SPKI; end
|
|
24
|
+
end
|
|
25
|
+
class PKCS7
|
|
26
|
+
# this definition causes TypeError "superclass mismatch for class PKCS7"
|
|
27
|
+
# MRI also crashes following definition;
|
|
28
|
+
# class Foo; class Foo < Foo; end; end
|
|
29
|
+
# class Foo; class Foo < Foo; end; end
|
|
30
|
+
#
|
|
31
|
+
# class PKCS7 < PKCS7; end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
warn "Warning: OpenSSL SSL implementation unavailable"
|
|
2
|
+
warn "You must run on JDK 1.5 (Java 5) or higher to use SSL"
|
|
3
|
+
module OpenSSL
|
|
4
|
+
module SSL
|
|
5
|
+
class SSLError < OpenSSLError; end
|
|
6
|
+
class SSLContext; end
|
|
7
|
+
class SSLSocket; end
|
|
8
|
+
VERIFY_NONE = 0
|
|
9
|
+
VERIFY_PEER = 1
|
|
10
|
+
VERIFY_FAIL_IF_NO_PEER_CERT = 2
|
|
11
|
+
VERIFY_CLIENT_ONCE = 4
|
|
12
|
+
OP_ALL = 0x00000FFF
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
= $RCSfile$ -- PKCS7
|
|
3
|
+
|
|
4
|
+
= Licence
|
|
5
|
+
This program is licenced under the same licence as Ruby.
|
|
6
|
+
(See the file 'LICENCE'.)
|
|
7
|
+
|
|
8
|
+
= Version
|
|
9
|
+
$Id: digest.rb 12148 2007-04-05 05:59:22Z technorama $
|
|
10
|
+
=end
|
|
11
|
+
|
|
12
|
+
module OpenSSL
|
|
13
|
+
class PKCS7
|
|
14
|
+
# This class is only provided for backwards compatibility. Use OpenSSL::PKCS7 in the future.
|
|
15
|
+
class PKCS7 < PKCS7
|
|
16
|
+
def initialize(*args)
|
|
17
|
+
super(*args)
|
|
18
|
+
|
|
19
|
+
warn("Warning: OpenSSL::PKCS7::PKCS7 is deprecated after Ruby 1.9; use OpenSSL::PKCS7 instead")
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end # PKCS7
|
|
24
|
+
end # OpenSSL
|
|
25
|
+
|
data/lib/openssl/ssl.rb
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
= $RCSfile$ -- Ruby-space definitions that completes C-space funcs for SSL
|
|
3
|
+
|
|
4
|
+
= Info
|
|
5
|
+
'OpenSSL for Ruby 2' project
|
|
6
|
+
Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo@notwork.org>
|
|
7
|
+
All rights reserved.
|
|
8
|
+
|
|
9
|
+
= Licence
|
|
10
|
+
This program is licenced under the same licence as Ruby.
|
|
11
|
+
(See the file 'LICENCE'.)
|
|
12
|
+
|
|
13
|
+
= Version
|
|
14
|
+
$Id: ssl.rb 16193 2008-04-25 06:51:21Z knu $
|
|
15
|
+
=end
|
|
16
|
+
|
|
17
|
+
require "openssl"
|
|
18
|
+
require "openssl/buffering"
|
|
19
|
+
require "fcntl"
|
|
20
|
+
|
|
21
|
+
module OpenSSL
|
|
22
|
+
module SSL
|
|
23
|
+
class SSLContext
|
|
24
|
+
DEFAULT_PARAMS = {
|
|
25
|
+
:ssl_version => "SSLv23",
|
|
26
|
+
:verify_mode => OpenSSL::SSL::VERIFY_PEER,
|
|
27
|
+
:ciphers => "ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW",
|
|
28
|
+
:options => OpenSSL::SSL::OP_ALL,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
DEFAULT_CERT_STORE = OpenSSL::X509::Store.new
|
|
32
|
+
DEFAULT_CERT_STORE.set_default_paths
|
|
33
|
+
if defined?(OpenSSL::X509::V_FLAG_CRL_CHECK_ALL)
|
|
34
|
+
DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def set_params(params={})
|
|
38
|
+
params = DEFAULT_PARAMS.merge(params)
|
|
39
|
+
self.ssl_version = params.delete(:ssl_version)
|
|
40
|
+
params.each{|name, value| self.__send__("#{name}=", value) }
|
|
41
|
+
if self.verify_mode != OpenSSL::SSL::VERIFY_NONE
|
|
42
|
+
unless self.ca_file or self.ca_path or self.cert_store
|
|
43
|
+
self.cert_store = DEFAULT_CERT_STORE
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
return params
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
module SocketForwarder
|
|
51
|
+
def addr
|
|
52
|
+
to_io.addr
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def peeraddr
|
|
56
|
+
to_io.peeraddr
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def setsockopt(level, optname, optval)
|
|
60
|
+
to_io.setsockopt(level, optname, optval)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def getsockopt(level, optname)
|
|
64
|
+
to_io.getsockopt(level, optname)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def fcntl(*args)
|
|
68
|
+
to_io.fcntl(*args)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def closed?
|
|
72
|
+
to_io.closed?
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def do_not_reverse_lookup=(flag)
|
|
76
|
+
to_io.do_not_reverse_lookup = flag
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
module Nonblock
|
|
81
|
+
def initialize(*args)
|
|
82
|
+
flag = File::NONBLOCK
|
|
83
|
+
flag |= @io.fcntl(Fcntl::F_GETFL) if defined?(Fcntl::F_GETFL)
|
|
84
|
+
@io.fcntl(Fcntl::F_SETFL, flag)
|
|
85
|
+
super
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def verify_certificate_identity(cert, hostname)
|
|
90
|
+
should_verify_common_name = true
|
|
91
|
+
cert.extensions.each{|ext|
|
|
92
|
+
next if ext.oid != "subjectAltName"
|
|
93
|
+
ext.value.split(/,\s+/).each{|general_name|
|
|
94
|
+
if /\ADNS:(.*)/ =~ general_name
|
|
95
|
+
should_verify_common_name = false
|
|
96
|
+
reg = Regexp.escape($1).gsub(/\\\*/, "[^.]+")
|
|
97
|
+
return true if /\A#{reg}\z/i =~ hostname
|
|
98
|
+
elsif /\AIP Address:(.*)/ =~ general_name
|
|
99
|
+
should_verify_common_name = false
|
|
100
|
+
return true if $1 == hostname
|
|
101
|
+
end
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if should_verify_common_name
|
|
105
|
+
cert.subject.to_a.each{|oid, value|
|
|
106
|
+
if oid == "CN"
|
|
107
|
+
reg = Regexp.escape(value).gsub(/\\\*/, "[^.]+")
|
|
108
|
+
return true if /\A#{reg}\z/i =~ hostname
|
|
109
|
+
end
|
|
110
|
+
}
|
|
111
|
+
end
|
|
112
|
+
return false
|
|
113
|
+
end
|
|
114
|
+
module_function :verify_certificate_identity
|
|
115
|
+
|
|
116
|
+
class SSLSocket
|
|
117
|
+
include Buffering
|
|
118
|
+
include SocketForwarder
|
|
119
|
+
include Nonblock
|
|
120
|
+
|
|
121
|
+
def post_connection_check(hostname)
|
|
122
|
+
unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname)
|
|
123
|
+
raise SSLError, "hostname was not match with the server certificate"
|
|
124
|
+
end
|
|
125
|
+
return true
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def session
|
|
129
|
+
SSL::Session.new(self)
|
|
130
|
+
rescue SSL::Session::SessionError
|
|
131
|
+
nil
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
class SSLServer
|
|
136
|
+
include SocketForwarder
|
|
137
|
+
attr_accessor :start_immediately
|
|
138
|
+
|
|
139
|
+
def initialize(svr, ctx)
|
|
140
|
+
@svr = svr
|
|
141
|
+
@ctx = ctx
|
|
142
|
+
unless ctx.session_id_context
|
|
143
|
+
session_id = OpenSSL::Digest::MD5.hexdigest($0)
|
|
144
|
+
@ctx.session_id_context = session_id
|
|
145
|
+
end
|
|
146
|
+
@start_immediately = true
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def to_io
|
|
150
|
+
@svr
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def listen(backlog=5)
|
|
154
|
+
@svr.listen(backlog)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def shutdown(how=Socket::SHUT_RDWR)
|
|
158
|
+
@svr.shutdown(how)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def accept
|
|
162
|
+
sock = @svr.accept
|
|
163
|
+
begin
|
|
164
|
+
ssl = OpenSSL::SSL::SSLSocket.new(sock, @ctx)
|
|
165
|
+
ssl.sync_close = true
|
|
166
|
+
ssl.accept if @start_immediately
|
|
167
|
+
ssl
|
|
168
|
+
rescue SSLError => ex
|
|
169
|
+
sock.close
|
|
170
|
+
raise ex
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def close
|
|
175
|
+
@svr.close
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
data/lib/openssl/x509.rb
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
= $RCSfile$ -- Ruby-space definitions that completes C-space funcs for X509 and subclasses
|
|
3
|
+
|
|
4
|
+
= Info
|
|
5
|
+
'OpenSSL for Ruby 2' project
|
|
6
|
+
Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
|
|
7
|
+
All rights reserved.
|
|
8
|
+
|
|
9
|
+
= Licence
|
|
10
|
+
This program is licenced under the same licence as Ruby.
|
|
11
|
+
(See the file 'LICENCE'.)
|
|
12
|
+
|
|
13
|
+
= Version
|
|
14
|
+
$Id: x509.rb 11708 2007-02-12 23:01:19Z shyouhei $
|
|
15
|
+
=end
|
|
16
|
+
|
|
17
|
+
require "openssl"
|
|
18
|
+
|
|
19
|
+
module OpenSSL
|
|
20
|
+
module X509
|
|
21
|
+
class ExtensionFactory
|
|
22
|
+
def create_extension(*arg)
|
|
23
|
+
if arg.size > 1
|
|
24
|
+
create_ext(*arg)
|
|
25
|
+
else
|
|
26
|
+
send("create_ext_from_"+arg[0].class.name.downcase, arg[0])
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def create_ext_from_array(ary)
|
|
31
|
+
raise ExtensionError, "unexpected array form" if ary.size > 3
|
|
32
|
+
create_ext(ary[0], ary[1], ary[2])
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def create_ext_from_string(str) # "oid = critical, value"
|
|
36
|
+
oid, value = str.split(/=/, 2)
|
|
37
|
+
oid.strip!
|
|
38
|
+
value.strip!
|
|
39
|
+
create_ext(oid, value)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def create_ext_from_hash(hash)
|
|
43
|
+
create_ext(hash["oid"], hash["value"], hash["critical"])
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
class Extension
|
|
48
|
+
def to_s # "oid = critical, value"
|
|
49
|
+
str = self.oid
|
|
50
|
+
str << " = "
|
|
51
|
+
str << "critical, " if self.critical?
|
|
52
|
+
str << self.value.gsub(/\n/, ", ")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def to_h # {"oid"=>sn|ln, "value"=>value, "critical"=>true|false}
|
|
56
|
+
{"oid"=>self.oid,"value"=>self.value,"critical"=>self.critical?}
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def to_a
|
|
60
|
+
[ self.oid, self.value, self.critical? ]
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
class Name
|
|
65
|
+
module RFC2253DN
|
|
66
|
+
Special = ',=+<>#;'
|
|
67
|
+
HexChar = /[0-9a-fA-F]/
|
|
68
|
+
HexPair = /#{HexChar}#{HexChar}/
|
|
69
|
+
HexString = /#{HexPair}+/
|
|
70
|
+
Pair = /\\(?:[#{Special}]|\\|"|#{HexPair})/
|
|
71
|
+
StringChar = /[^#{Special}\\"]/
|
|
72
|
+
QuoteChar = /[^\\"]/
|
|
73
|
+
AttributeType = /[a-zA-Z][0-9a-zA-Z]*|[0-9]+(?:\.[0-9]+)*/
|
|
74
|
+
AttributeValue = /
|
|
75
|
+
(?!["#])((?:#{StringChar}|#{Pair})*)|
|
|
76
|
+
\#(#{HexString})|
|
|
77
|
+
"((?:#{QuoteChar}|#{Pair})*)"
|
|
78
|
+
/x
|
|
79
|
+
TypeAndValue = /\A(#{AttributeType})=#{AttributeValue}/
|
|
80
|
+
|
|
81
|
+
module_function
|
|
82
|
+
|
|
83
|
+
def expand_pair(str)
|
|
84
|
+
return nil unless str
|
|
85
|
+
return str.gsub(Pair){|pair|
|
|
86
|
+
case pair.size
|
|
87
|
+
when 2 then pair[1,1]
|
|
88
|
+
when 3 then Integer("0x#{pair[1,2]}").chr
|
|
89
|
+
else raise OpenSSL::X509::NameError, "invalid pair: #{str}"
|
|
90
|
+
end
|
|
91
|
+
}
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def expand_hexstring(str)
|
|
95
|
+
return nil unless str
|
|
96
|
+
der = str.gsub(HexPair){|hex| Integer("0x#{hex}").chr }
|
|
97
|
+
a1 = OpenSSL::ASN1.decode(der)
|
|
98
|
+
return a1.value, a1.tag
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def expand_value(str1, str2, str3)
|
|
102
|
+
value = expand_pair(str1)
|
|
103
|
+
value, tag = expand_hexstring(str2) unless value
|
|
104
|
+
value = expand_pair(str3) unless value
|
|
105
|
+
return value, tag
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def scan(dn)
|
|
109
|
+
str = dn
|
|
110
|
+
ary = []
|
|
111
|
+
while true
|
|
112
|
+
if md = TypeAndValue.match(str)
|
|
113
|
+
matched = md.to_s
|
|
114
|
+
remain = md.post_match
|
|
115
|
+
type = md[1]
|
|
116
|
+
value, tag = expand_value(md[2], md[3], md[4]) rescue nil
|
|
117
|
+
if value
|
|
118
|
+
type_and_value = [type, value]
|
|
119
|
+
type_and_value.push(tag) if tag
|
|
120
|
+
ary.unshift(type_and_value)
|
|
121
|
+
if remain.length > 2 && remain[0] == ?,
|
|
122
|
+
str = remain[1..-1]
|
|
123
|
+
next
|
|
124
|
+
elsif remain.length > 2 && remain[0] == ?+
|
|
125
|
+
raise OpenSSL::X509::NameError,
|
|
126
|
+
"multi-valued RDN is not supported: #{dn}"
|
|
127
|
+
elsif remain.empty?
|
|
128
|
+
break
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
msg_dn = dn[0, dn.length - str.length] + " =>" + str
|
|
133
|
+
raise OpenSSL::X509::NameError, "malformed RDN: #{msg_dn}"
|
|
134
|
+
end
|
|
135
|
+
return ary
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
class <<self
|
|
140
|
+
def parse_rfc2253(str, template=OBJECT_TYPE_TEMPLATE)
|
|
141
|
+
ary = OpenSSL::X509::Name::RFC2253DN.scan(str)
|
|
142
|
+
self.new(ary, template)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def parse_openssl(str, template=OBJECT_TYPE_TEMPLATE)
|
|
146
|
+
ary = str.scan(/\s*([^\/,]+)\s*/).collect{|i| i[0].split("=", 2) }
|
|
147
|
+
self.new(ary, template)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
alias parse parse_openssl
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|