r509 0.10.0 → 1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/README.mdown +2 -2
- data/Rakefile +2 -3
- data/bin/r509 +77 -80
- data/bin/r509-parse +4 -4
- data/doc/R509.html +60 -60
- data/doc/R509/ASN1.html +158 -48
- data/doc/R509/ASN1/GeneralName.html +157 -154
- data/doc/R509/ASN1/GeneralNames.html +246 -237
- data/doc/R509/CRL.html +41 -39
- data/doc/R509/CRL/Administrator.html +105 -100
- data/doc/R509/CRL/FileReaderWriter.html +146 -98
- data/doc/R509/CRL/ReaderWriter.html +57 -54
- data/doc/R509/CRL/SQLiteReaderWriter.html +727 -0
- data/doc/R509/CRL/SignedList.html +83 -80
- data/doc/R509/CSR.html +184 -162
- data/doc/R509/Cert.html +271 -269
- data/doc/R509/Cert/Extensions.html +62 -63
- data/doc/R509/Cert/Extensions/AuthorityInfoAccess.html +138 -108
- data/doc/R509/Cert/Extensions/AuthorityKeyIdentifier.html +100 -84
- data/doc/R509/Cert/Extensions/BasicConstraints.html +89 -88
- data/doc/R509/Cert/Extensions/CRLDistributionPoints.html +87 -83
- data/doc/R509/Cert/Extensions/CertificatePolicies.html +78 -76
- data/doc/R509/Cert/Extensions/ExtendedKeyUsage.html +128 -125
- data/doc/R509/Cert/Extensions/GeneralNamesMixin.html +83 -78
- data/doc/R509/Cert/Extensions/InhibitAnyPolicy.html +69 -67
- data/doc/R509/Cert/Extensions/KeyUsage.html +138 -135
- data/doc/R509/Cert/Extensions/NameConstraints.html +82 -81
- data/doc/R509/Cert/Extensions/NoticeReference.html +59 -56
- data/doc/R509/Cert/Extensions/OCSPNoCheck.html +70 -69
- data/doc/R509/Cert/Extensions/PolicyConstraints.html +71 -69
- data/doc/R509/Cert/Extensions/PolicyInformation.html +63 -60
- data/doc/R509/Cert/Extensions/PolicyQualifiers.html +60 -57
- data/doc/R509/Cert/Extensions/SubjectAlternativeName.html +91 -87
- data/doc/R509/Cert/Extensions/SubjectKeyIdentifier.html +72 -71
- data/doc/R509/Cert/Extensions/UserNotice.html +60 -57
- data/doc/R509/Cert/Extensions/ValidationMixin.html +43 -40
- data/doc/R509/CertificateAuthority.html +39 -37
- data/doc/R509/CertificateAuthority/OptionsBuilder.html +58 -55
- data/doc/R509/CertificateAuthority/Signer.html +277 -60
- data/doc/R509/Config.html +40 -38
- data/doc/R509/Config/CAConfig.html +255 -188
- data/doc/R509/Config/CAConfigPool.html +64 -61
- data/doc/R509/Config/CertProfile.html +119 -116
- data/doc/R509/Config/SubjectItemPolicy.html +94 -93
- data/doc/R509/Engine.html +60 -56
- data/doc/R509/Helpers.html +99 -96
- data/doc/R509/MessageDigest.html +69 -68
- data/doc/R509/NameSanitizer.html +51 -48
- data/doc/R509/OCSP.html +39 -37
- data/doc/R509/OCSP/Request.html +39 -37
- data/doc/R509/OCSP/Request/Nonce.html +67 -67
- data/doc/R509/OCSP/Response.html +93 -90
- data/doc/R509/OIDMapper.html +48 -46
- data/doc/R509/PrivateKey.html +170 -169
- data/doc/R509/R509Error.html +45 -42
- data/doc/R509/SPKI.html +99 -89
- data/doc/R509/Subject.html +86 -83
- data/doc/R509/Validity.html +57 -57
- data/doc/R509/Validity/Checker.html +63 -93
- data/doc/R509/Validity/DefaultChecker.html +58 -55
- data/doc/R509/Validity/DefaultWriter.html +62 -59
- data/doc/R509/Validity/Status.html +77 -74
- data/doc/R509/Validity/Writer.html +75 -123
- data/doc/_index.html +37 -31
- data/doc/class_list.html +25 -27
- data/doc/css/full_list.css +32 -31
- data/doc/css/style.css +221 -78
- data/doc/file.CONTRIBUTING.html +29 -30
- data/doc/file.LICENSE.html +29 -30
- data/doc/file.README.html +31 -32
- data/doc/file.YAML.html +33 -34
- data/doc/file.r509.html +39 -48
- data/doc/file_list.html +39 -30
- data/doc/frames.html +10 -21
- data/doc/index.html +31 -32
- data/doc/js/app.js +100 -71
- data/doc/js/full_list.js +168 -130
- data/doc/method_list.html +1788 -1119
- data/doc/top-level-namespace.html +45 -49
- data/lib/r509.rb +21 -7
- data/lib/r509/asn1.rb +45 -32
- data/lib/r509/cert.rb +45 -51
- data/lib/r509/cert/extensions/authority_info_access.rb +49 -23
- data/lib/r509/cert/extensions/authority_key_identifier.rb +16 -11
- data/lib/r509/cert/extensions/base.rb +22 -23
- data/lib/r509/cert/extensions/basic_constraints.rb +11 -12
- data/lib/r509/cert/extensions/certificate_policies.rb +26 -26
- data/lib/r509/cert/extensions/crl_distribution_points.rb +5 -7
- data/lib/r509/cert/extensions/extended_key_usage.rb +5 -5
- data/lib/r509/cert/extensions/inhibit_any_policy.rb +4 -3
- data/lib/r509/cert/extensions/key_usage.rb +5 -5
- data/lib/r509/cert/extensions/name_constraints.rb +16 -16
- data/lib/r509/cert/extensions/ocsp_no_check.rb +3 -3
- data/lib/r509/cert/extensions/policy_constraints.rb +8 -8
- data/lib/r509/cert/extensions/subject_alternative_name.rb +5 -4
- data/lib/r509/cert/extensions/subject_key_identifier.rb +5 -5
- data/lib/r509/cert/extensions/validation_mixin.rb +11 -10
- data/lib/r509/certificate_authority/options_builder.rb +19 -21
- data/lib/r509/certificate_authority/signer.rb +26 -27
- data/lib/r509/config.rb +1 -0
- data/lib/r509/config/ca_config.rb +70 -75
- data/lib/r509/config/cert_profile.rb +9 -8
- data/lib/r509/config/subject_item_policy.rb +25 -28
- data/lib/r509/crl/administrator.rb +19 -20
- data/lib/r509/crl/reader_writer.rb +10 -8
- data/lib/r509/crl/signed_list.rb +4 -4
- data/lib/r509/crl/sqlite_reader_writer.rb +75 -0
- data/lib/r509/csr.rb +54 -60
- data/lib/r509/ec-hack.rb +3 -2
- data/lib/r509/engine.rb +5 -6
- data/lib/r509/exceptions.rb +1 -1
- data/lib/r509/helpers.rb +11 -14
- data/lib/r509/io_helpers.rb +7 -7
- data/lib/r509/message_digest.rb +5 -6
- data/lib/r509/ocsp.rb +11 -13
- data/lib/r509/oid_mapper.rb +2 -2
- data/lib/r509/private_key.rb +28 -32
- data/lib/r509/spki.rb +17 -20
- data/lib/r509/subject.rb +26 -27
- data/lib/r509/trollop.rb +1 -0
- data/lib/r509/validity.rb +30 -21
- data/lib/r509/version.rb +4 -2
- data/r509.yaml +9 -17
- data/spec/asn1_spec.rb +145 -146
- data/spec/cert/extensions/authority_info_access_spec.rb +41 -41
- data/spec/cert/extensions/authority_key_identifier_spec.rb +29 -23
- data/spec/cert/extensions/base_spec.rb +38 -34
- data/spec/cert/extensions/basic_constraints_spec.rb +21 -21
- data/spec/cert/extensions/certificate_policies_spec.rb +99 -87
- data/spec/cert/extensions/crl_distribution_points_spec.rb +24 -25
- data/spec/cert/extensions/extended_key_usage_spec.rb +40 -36
- data/spec/cert/extensions/inhibit_any_policy_spec.rb +12 -12
- data/spec/cert/extensions/key_usage_spec.rb +44 -39
- data/spec/cert/extensions/name_constraints_spec.rb +83 -83
- data/spec/cert/extensions/ocsp_no_check_spec.rb +10 -10
- data/spec/cert/extensions/policy_constraints_spec.rb +19 -19
- data/spec/cert/extensions/subject_alternative_name_spec.rb +46 -47
- data/spec/cert/extensions/subject_key_identifier_spec.rb +10 -10
- data/spec/cert_spec.rb +105 -101
- data/spec/certificate_authority/options_builder_spec.rb +90 -90
- data/spec/certificate_authority/signer_spec.rb +41 -41
- data/spec/config/ca_config_spec.rb +169 -119
- data/spec/config/cert_profile_spec.rb +33 -33
- data/spec/config/subject_item_policy_spec.rb +22 -22
- data/spec/crl/administrator_spec.rb +65 -65
- data/spec/crl/reader_writer_spec.rb +20 -19
- data/spec/crl/signed_list_spec.rb +26 -26
- data/spec/crl/sqlite_reader_writer_spec.rb +42 -0
- data/spec/csr_spec.rb +149 -145
- data/spec/engine_spec.rb +14 -14
- data/spec/fixtures.rb +56 -39
- data/spec/fixtures/crl_list.sql +13 -0
- data/spec/fixtures/csr1.der +0 -0
- data/spec/fixtures/csr1.pem +6 -6
- data/spec/message_digest_spec.rb +43 -43
- data/spec/ocsp_spec.rb +25 -25
- data/spec/oid_mapper_spec.rb +18 -19
- data/spec/private_key_spec.rb +79 -81
- data/spec/r509_spec.rb +16 -16
- data/spec/spec_helper.rb +3 -3
- data/spec/spki_spec.rb +94 -94
- data/spec/subject_spec.rb +107 -107
- data/spec/validity_spec.rb +25 -25
- metadata +113 -111
- metadata.gz.sig +0 -0
@@ -36,7 +36,7 @@ module R509
|
|
36
36
|
# :value => [name]
|
37
37
|
# )
|
38
38
|
def initialize(arg)
|
39
|
-
|
39
|
+
unless R509::Cert::Extensions.is_extension?(arg)
|
40
40
|
arg = build_extension(arg)
|
41
41
|
end
|
42
42
|
|
@@ -60,7 +60,7 @@ module R509
|
|
60
60
|
private
|
61
61
|
|
62
62
|
def parse_extension
|
63
|
-
@general_names= R509::ASN1::GeneralNames.new
|
63
|
+
@general_names = R509::ASN1::GeneralNames.new
|
64
64
|
data = R509::ASN1.get_extension_payload(self)
|
65
65
|
data.entries.each do |distribution_point|
|
66
66
|
# DistributionPoint ::= SEQUENCE {
|
@@ -79,18 +79,16 @@ module R509
|
|
79
79
|
|
80
80
|
def build_extension(arg)
|
81
81
|
validate_crl_distribution_points(arg)
|
82
|
-
validate_location('crl_distribution_points',arg[:value])
|
82
|
+
validate_location('crl_distribution_points', arg[:value])
|
83
83
|
serialize = R509::ASN1::GeneralNames.new(arg[:value]).serialize_names
|
84
84
|
ef = OpenSSL::X509::ExtensionFactory.new
|
85
85
|
ef.config = OpenSSL::Config.parse(serialize[:conf])
|
86
86
|
critical = R509::Cert::Extensions.calculate_critical(arg[:critical], false)
|
87
|
-
|
87
|
+
ef.create_extension("crlDistributionPoints", serialize[:extension_string], critical)
|
88
88
|
end
|
89
89
|
|
90
90
|
def validate_crl_distribution_points(arg)
|
91
|
-
|
92
|
-
raise ArgumentError, "You must pass a hash with a :value key"
|
93
|
-
end
|
91
|
+
raise ArgumentError, "You must pass a hash with a :value key" unless arg.is_a?(Hash)
|
94
92
|
end
|
95
93
|
end
|
96
94
|
end
|
@@ -61,10 +61,10 @@ module R509
|
|
61
61
|
# @example
|
62
62
|
# R509::Cert::Extensions::ExtendedKeyUsage.new(
|
63
63
|
# :critical => false,
|
64
|
-
# :value => ['clientAuth,'serverAuth']
|
64
|
+
# :value => ['clientAuth','serverAuth']
|
65
65
|
# )
|
66
66
|
def initialize(arg)
|
67
|
-
|
67
|
+
unless R509::Cert::Extensions.is_extension?(arg)
|
68
68
|
arg = build_extension(arg)
|
69
69
|
end
|
70
70
|
|
@@ -74,8 +74,8 @@ module R509
|
|
74
74
|
|
75
75
|
# Returns true if the given use is allowed by this extension.
|
76
76
|
# @param [string] friendly_use_name One of the AU_* constants in this class.
|
77
|
-
def allows?(
|
78
|
-
@allowed_uses.include?(
|
77
|
+
def allows?(friendly_use_name)
|
78
|
+
@allowed_uses.include?(friendly_use_name)
|
79
79
|
end
|
80
80
|
|
81
81
|
def web_server_authentication?
|
@@ -181,7 +181,7 @@ module R509
|
|
181
181
|
validate_usage(arg)
|
182
182
|
ef = OpenSSL::X509::ExtensionFactory.new
|
183
183
|
critical = R509::Cert::Extensions.calculate_critical(arg[:critical], false)
|
184
|
-
|
184
|
+
ef.create_extension("extendedKeyUsage", arg[:value].join(","), critical)
|
185
185
|
end
|
186
186
|
end
|
187
187
|
end
|
@@ -31,7 +31,7 @@ module R509
|
|
31
31
|
# @option arg :value [Integer]
|
32
32
|
# @option arg :critical [Boolean] (true)
|
33
33
|
def initialize(arg)
|
34
|
-
|
34
|
+
unless R509::Cert::Extensions.is_extension?(arg)
|
35
35
|
arg = build_extension(arg)
|
36
36
|
end
|
37
37
|
|
@@ -50,6 +50,7 @@ module R509
|
|
50
50
|
end
|
51
51
|
|
52
52
|
private
|
53
|
+
|
53
54
|
def parse_extension
|
54
55
|
# id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 }
|
55
56
|
# InhibitAnyPolicy ::= SkipCerts
|
@@ -58,11 +59,11 @@ module R509
|
|
58
59
|
end
|
59
60
|
|
60
61
|
def build_extension(arg)
|
61
|
-
validate_non_negative_integer("Inhibit any policy",arg[:value])
|
62
|
+
validate_non_negative_integer("Inhibit any policy", arg[:value])
|
62
63
|
ef = OpenSSL::X509::ExtensionFactory.new
|
63
64
|
critical = R509::Cert::Extensions.calculate_critical(arg[:critical], true)
|
64
65
|
# must be set critical per RFC 5280
|
65
|
-
|
66
|
+
ef.create_extension("inhibitAnyPolicy", arg[:value].to_s, critical)
|
66
67
|
end
|
67
68
|
end
|
68
69
|
end
|
@@ -69,7 +69,7 @@ module R509
|
|
69
69
|
# :value => ['digitalSignature,'keyEncipherment']
|
70
70
|
# )
|
71
71
|
def initialize(arg)
|
72
|
-
|
72
|
+
unless R509::Cert::Extensions.is_extension?(arg)
|
73
73
|
arg = build_extension(arg)
|
74
74
|
end
|
75
75
|
|
@@ -81,8 +81,8 @@ module R509
|
|
81
81
|
# @param [String] friendly_use_name key usage short name (e.g. digitalSignature, cRLSign, etc)
|
82
82
|
# or one of the AU_* constants in this class
|
83
83
|
# @return [Boolean]
|
84
|
-
def allows?(
|
85
|
-
@allowed_uses.include?(
|
84
|
+
def allows?(friendly_use_name)
|
85
|
+
@allowed_uses.include?(friendly_use_name)
|
86
86
|
end
|
87
87
|
|
88
88
|
def digital_signature?
|
@@ -140,7 +140,7 @@ module R509
|
|
140
140
|
validate_usage(arg)
|
141
141
|
ef = OpenSSL::X509::ExtensionFactory.new
|
142
142
|
critical = R509::Cert::Extensions.calculate_critical(arg[:critical], false)
|
143
|
-
|
143
|
+
ef.create_extension("keyUsage", arg[:value].join(","), critical)
|
144
144
|
end
|
145
145
|
|
146
146
|
def parse_extension
|
@@ -152,7 +152,7 @@ module R509
|
|
152
152
|
# the second byte is not encoded. let's add it back so we can
|
153
153
|
# have the full bitmask for comparison
|
154
154
|
if data.size == 1
|
155
|
-
data
|
155
|
+
data += "\0"
|
156
156
|
end
|
157
157
|
bit_mask = data.unpack('n')[0] # treat it as a 16-bit unsigned big endian
|
158
158
|
# KeyUsage ::= BIT STRING {
|
@@ -31,7 +31,6 @@ module R509
|
|
31
31
|
# You can use this extension to parse an existing extension for easy access
|
32
32
|
# to the contents or create a new one.
|
33
33
|
class NameConstraints < OpenSSL::X509::Extension
|
34
|
-
|
35
34
|
# friendly name for CP OID
|
36
35
|
OID = "nameConstraints"
|
37
36
|
Extensions.register_class(self)
|
@@ -63,7 +62,7 @@ module R509
|
|
63
62
|
# @note When supplying dirName the value is an R509::Subject or the hash used to build an R509::Subject
|
64
63
|
#
|
65
64
|
def initialize(arg)
|
66
|
-
|
65
|
+
unless R509::Cert::Extensions.is_extension?(arg)
|
67
66
|
arg = build_extension(arg)
|
68
67
|
end
|
69
68
|
super(arg)
|
@@ -85,6 +84,7 @@ module R509
|
|
85
84
|
end
|
86
85
|
|
87
86
|
private
|
87
|
+
|
88
88
|
def parse_extension
|
89
89
|
@permitted = R509::ASN1::GeneralNames.new
|
90
90
|
@excluded = R509::ASN1::GeneralNames.new
|
@@ -96,7 +96,7 @@ module R509
|
|
96
96
|
gn = R509::ASN1::GeneralName.new(obj)
|
97
97
|
if gs.tag == 0 # permittedSubtrees
|
98
98
|
@permitted.add_item(gn)
|
99
|
-
elsif gs.tag == 1 #excludedSubtrees
|
99
|
+
elsif gs.tag == 1 # excludedSubtrees
|
100
100
|
@excluded.add_item(gn)
|
101
101
|
end
|
102
102
|
end
|
@@ -125,15 +125,15 @@ module R509
|
|
125
125
|
validate_name_constraints(arg)
|
126
126
|
nc_data = []
|
127
127
|
nc_conf = []
|
128
|
-
[:permitted
|
129
|
-
|
128
|
+
[:permitted, :excluded].each do |permit_exclude|
|
129
|
+
unless arg[permit_exclude].nil?
|
130
130
|
gns = R509::ASN1::GeneralNames.new
|
131
131
|
arg[permit_exclude].each do |p|
|
132
132
|
gns.create_item(p)
|
133
133
|
end
|
134
134
|
gns.names.each do |name|
|
135
135
|
serialize = name.serialize_name
|
136
|
-
nc_data.push "#{permit_exclude
|
136
|
+
nc_data.push "#{permit_exclude};#{serialize[:extension_string]}"
|
137
137
|
nc_conf.push serialize[:conf]
|
138
138
|
end
|
139
139
|
end
|
@@ -143,32 +143,32 @@ module R509
|
|
143
143
|
ef.config = OpenSSL::Config.parse nc_conf.join("\n")
|
144
144
|
critical = R509::Cert::Extensions.calculate_critical(arg[:critical], true)
|
145
145
|
# must be set critical per RFC 5280
|
146
|
-
|
146
|
+
ef.create_extension("nameConstraints", nc_data.join(","), critical)
|
147
147
|
end
|
148
148
|
|
149
149
|
def validate_name_constraints(nc)
|
150
|
-
|
150
|
+
unless nc.is_a?(Hash)
|
151
151
|
raise ArgumentError, "name_constraints must be provided as a hash"
|
152
152
|
end
|
153
|
-
[:permitted
|
154
|
-
|
155
|
-
validate_name_constraints_elements(key,nc[key])
|
153
|
+
[:permitted, :excluded].each do |key|
|
154
|
+
unless nc[key].nil?
|
155
|
+
validate_name_constraints_elements(key, nc[key])
|
156
156
|
end
|
157
157
|
end
|
158
|
-
if (nc[:permitted].nil?
|
158
|
+
if (nc[:permitted].nil? || nc[:permitted].empty?) && (nc[:excluded].nil? || nc[:excluded].empty?)
|
159
159
|
raise ArgumentError, "If name_constraints are supplied you must have at least one valid :permitted or :excluded element"
|
160
160
|
end
|
161
161
|
end
|
162
162
|
|
163
|
-
def validate_name_constraints_elements(type,arr)
|
164
|
-
|
163
|
+
def validate_name_constraints_elements(type, arr)
|
164
|
+
unless arr.is_a?(Array)
|
165
165
|
raise ArgumentError, "#{type} must be an array"
|
166
166
|
end
|
167
167
|
arr.each do |el|
|
168
|
-
if
|
168
|
+
if !el.is_a?(Hash) || !el.key?(:type) || !el.key?(:value)
|
169
169
|
raise ArgumentError, "Elements within the #{type} array must be hashes with both type and value"
|
170
170
|
end
|
171
|
-
if R509::ASN1::GeneralName.map_type_to_tag(el[:type])
|
171
|
+
if R509::ASN1::GeneralName.map_type_to_tag(el[:type]).nil?
|
172
172
|
raise ArgumentError, "#{el[:type]} is not an allowed type. Check R509::ASN1::GeneralName.map_type_to_tag to see a list of types"
|
173
173
|
end
|
174
174
|
end
|
@@ -18,7 +18,6 @@ module R509
|
|
18
18
|
# You can use this extension to parse an existing extension for easy access
|
19
19
|
# to the contents or create a new one.
|
20
20
|
class OCSPNoCheck < OpenSSL::X509::Extension
|
21
|
-
|
22
21
|
# friendly name for OCSP No Check
|
23
22
|
OID = "noCheck"
|
24
23
|
Extensions.register_class(self)
|
@@ -28,7 +27,7 @@ module R509
|
|
28
27
|
# @option arg :ocsp_no_check [Any] Pass any value. It's irrelevant.
|
29
28
|
# @option arg :critical [Boolean] (false)
|
30
29
|
def initialize(arg)
|
31
|
-
|
30
|
+
unless R509::Cert::Extensions.is_extension?(arg)
|
32
31
|
arg = build_extension(arg)
|
33
32
|
end
|
34
33
|
super(arg)
|
@@ -45,10 +44,11 @@ module R509
|
|
45
44
|
end
|
46
45
|
|
47
46
|
private
|
47
|
+
|
48
48
|
def build_extension(arg)
|
49
49
|
ef = OpenSSL::X509::ExtensionFactory.new
|
50
50
|
critical = R509::Cert::Extensions.calculate_critical(arg[:critical], false)
|
51
|
-
|
51
|
+
ef.create_extension("noCheck", "yes", critical)
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|
@@ -49,7 +49,7 @@ module R509
|
|
49
49
|
# @option arg :inhibit_policy_mapping [Integer]
|
50
50
|
# @option arg :critical [Boolean] (true)
|
51
51
|
def initialize(arg)
|
52
|
-
|
52
|
+
unless R509::Cert::Extensions.is_extension?(arg)
|
53
53
|
arg = build_extension(arg)
|
54
54
|
end
|
55
55
|
|
@@ -99,20 +99,20 @@ module R509
|
|
99
99
|
ef = OpenSSL::X509::ExtensionFactory.new
|
100
100
|
critical = R509::Cert::Extensions.calculate_critical(arg[:critical], true)
|
101
101
|
# must be set critical per RFC 5280
|
102
|
-
|
102
|
+
ef.create_extension("policyConstraints", constraints.join(","), critical)
|
103
103
|
end
|
104
104
|
|
105
105
|
def validate_policy_constraints(pc)
|
106
|
-
|
106
|
+
unless pc.is_a?(Hash)
|
107
107
|
raise ArgumentError, 'Policy constraints must be provided as a hash with at least one of the two allowed keys: :inhibit_policy_mapping and :require_explicit_policy'
|
108
108
|
end
|
109
|
-
|
110
|
-
ipm = validate_non_negative_integer("inhibit_policy_mapping",pc[:inhibit_policy_mapping])
|
109
|
+
unless pc[:inhibit_policy_mapping].nil?
|
110
|
+
ipm = validate_non_negative_integer("inhibit_policy_mapping", pc[:inhibit_policy_mapping])
|
111
111
|
end
|
112
|
-
|
113
|
-
rep = validate_non_negative_integer("require_explicit_policy",pc[:require_explicit_policy])
|
112
|
+
unless pc[:require_explicit_policy].nil?
|
113
|
+
rep = validate_non_negative_integer("require_explicit_policy", pc[:require_explicit_policy])
|
114
114
|
end
|
115
|
-
if
|
115
|
+
if !ipm && !rep
|
116
116
|
raise ArgumentError, 'Policy constraints must have at least one of two keys: :inhibit_policy_mapping and :require_explicit_policy and the value must be non-negative'
|
117
117
|
end
|
118
118
|
end
|
@@ -41,7 +41,7 @@ module R509
|
|
41
41
|
# You can also pass a pre-existing GeneralNames object
|
42
42
|
# @option arg :critical [Boolean] (false)
|
43
43
|
def initialize(arg)
|
44
|
-
|
44
|
+
unless R509::Cert::Extensions.is_extension?(arg)
|
45
45
|
arg = build_extension(arg)
|
46
46
|
end
|
47
47
|
super(arg)
|
@@ -50,7 +50,7 @@ module R509
|
|
50
50
|
|
51
51
|
# @return [Hash]
|
52
52
|
def to_h
|
53
|
-
{:critical => self.critical?, :value => @general_names.to_h }
|
53
|
+
{ :critical => self.critical?, :value => @general_names.to_h }
|
54
54
|
end
|
55
55
|
|
56
56
|
# @return [YAML]
|
@@ -59,6 +59,7 @@ module R509
|
|
59
59
|
end
|
60
60
|
|
61
61
|
private
|
62
|
+
|
62
63
|
def parse_extension
|
63
64
|
data = R509::ASN1.get_extension_payload(self)
|
64
65
|
@general_names = R509::ASN1::GeneralNames.new
|
@@ -73,11 +74,11 @@ module R509
|
|
73
74
|
ef = OpenSSL::X509::ExtensionFactory.new
|
74
75
|
ef.config = OpenSSL::Config.parse(serialize[:conf])
|
75
76
|
critical = R509::Cert::Extensions.calculate_critical(arg[:critical], false)
|
76
|
-
|
77
|
+
ef.create_extension("subjectAltName", serialize[:extension_string], critical)
|
77
78
|
end
|
78
79
|
|
79
80
|
def validate_subject_alternative_name(san)
|
80
|
-
if
|
81
|
+
if !san.is_a?(Hash) || !(san[:value].is_a?(R509::ASN1::GeneralNames) || san[:value].is_a?(Array))
|
81
82
|
raise ArgumentError, "You must supply a hash with a :value"
|
82
83
|
end
|
83
84
|
validate_general_name_hash_array(san[:value])
|
@@ -11,7 +11,6 @@ module R509
|
|
11
11
|
# You can use this extension to parse an existing extension for easy access
|
12
12
|
# to the contents or create a new one.
|
13
13
|
class SubjectKeyIdentifier < OpenSSL::X509::Extension
|
14
|
-
|
15
14
|
# friendly name for Subject Key Identifier OID
|
16
15
|
OID = "subjectKeyIdentifier"
|
17
16
|
# default extension behavior when generating
|
@@ -22,7 +21,7 @@ module R509
|
|
22
21
|
# @option arg :public_key [OpenSSL::PKey] (Cert/CSR/PrivateKey return this type from #public_key)
|
23
22
|
# @option arg :critical [Boolean] (false)
|
24
23
|
def initialize(arg)
|
25
|
-
|
24
|
+
unless R509::Cert::Extensions.is_extension?(arg)
|
26
25
|
arg = build_extension(arg)
|
27
26
|
end
|
28
27
|
super(arg)
|
@@ -30,10 +29,11 @@ module R509
|
|
30
29
|
|
31
30
|
# @return value of key
|
32
31
|
def key
|
33
|
-
|
32
|
+
self.value
|
34
33
|
end
|
35
34
|
|
36
35
|
private
|
36
|
+
|
37
37
|
def build_extension(arg)
|
38
38
|
validate_subject_key_identifier(arg)
|
39
39
|
ef = OpenSSL::X509::ExtensionFactory.new
|
@@ -41,11 +41,11 @@ module R509
|
|
41
41
|
cert.public_key = arg[:public_key]
|
42
42
|
ef.subject_certificate = cert
|
43
43
|
critical = R509::Cert::Extensions.calculate_critical(arg[:critical], false)
|
44
|
-
|
44
|
+
ef.create_extension("subjectKeyIdentifier", SKI_EXTENSION_DEFAULT, critical)
|
45
45
|
end
|
46
46
|
|
47
47
|
def validate_subject_key_identifier(ski)
|
48
|
-
if
|
48
|
+
if !ski.is_a?(Hash) || ski[:public_key].nil?
|
49
49
|
raise ArgumentError, "You must supply a hash with a :public_key"
|
50
50
|
end
|
51
51
|
ski
|
@@ -5,24 +5,25 @@ module R509
|
|
5
5
|
# Validation methods shared by multiple extensions
|
6
6
|
module ValidationMixin
|
7
7
|
private
|
8
|
+
|
8
9
|
# used by iap and pc validation methods
|
9
|
-
def validate_non_negative_integer(source,value)
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
def validate_non_negative_integer(source, value)
|
11
|
+
if !value.is_a?(Integer) || value < 0
|
12
|
+
raise ArgumentError, "#{source} must be a non-negative integer"
|
13
|
+
end
|
14
|
+
value
|
14
15
|
end
|
15
16
|
|
16
17
|
# validates key usage array
|
17
18
|
def validate_usage(ku)
|
18
|
-
if ku.nil?
|
19
|
+
if ku.nil? || !ku.is_a?(Hash) || !ku[:value].is_a?(Array)
|
19
20
|
raise ArgumentError, 'You must pass a hash with a key :value that contains an array of strings (see README)'
|
20
21
|
end
|
21
22
|
ku
|
22
23
|
end
|
23
24
|
|
24
|
-
def validate_location(type,location)
|
25
|
-
if
|
25
|
+
def validate_location(type, location)
|
26
|
+
if location && !(location.is_a?(Array) || location.is_a?(R509::ASN1::GeneralNames))
|
26
27
|
raise ArgumentError, "#{type} must contain an array or R509::ASN1::GeneralNames object if provided"
|
27
28
|
end
|
28
29
|
validate_general_name_hash_array(location) unless location.nil?
|
@@ -31,10 +32,10 @@ module R509
|
|
31
32
|
|
32
33
|
def validate_general_name_hash_array(arr)
|
33
34
|
arr.each do |l|
|
34
|
-
if
|
35
|
+
if !l.is_a?(Hash) || l[:type].nil? || l[:value].nil?
|
35
36
|
raise ArgumentError, "All elements of the array must be hashes with a :type and :value"
|
36
37
|
end
|
37
|
-
end unless arr.
|
38
|
+
end unless arr.is_a?(R509::ASN1::GeneralNames)
|
38
39
|
end
|
39
40
|
end
|
40
41
|
end
|
@@ -2,7 +2,7 @@ module R509::CertificateAuthority
|
|
2
2
|
# A class to build hashes to send to the R509::CertificateAuthority::Signer. These are built from R509::Config::CertProfile objects and additional data supplied to the #build_and_enforce method.
|
3
3
|
class OptionsBuilder
|
4
4
|
def initialize(config)
|
5
|
-
|
5
|
+
unless config.is_a?(R509::Config::CAConfig)
|
6
6
|
raise ArgumentError, "You must supply a R509::Config::CAConfig object to this class at instantiation"
|
7
7
|
end
|
8
8
|
@config = config
|
@@ -22,15 +22,15 @@ module R509::CertificateAuthority
|
|
22
22
|
|
23
23
|
R509::CertificateAuthority::Signer.check_options(options)
|
24
24
|
|
25
|
-
if (options.
|
26
|
-
(options.
|
25
|
+
if (options.key?(:csr) && !options[:csr].verify_signature) ||
|
26
|
+
(options.key?(:spki) && !options[:spki].verify_signature)
|
27
27
|
raise R509::R509Error, "Request signature is invalid."
|
28
28
|
end
|
29
29
|
|
30
30
|
raw_subject, public_key = R509::CertificateAuthority::Signer.extract_public_key_subject(options)
|
31
31
|
|
32
|
-
message_digest = enforce_md(options[:message_digest],profile)
|
33
|
-
subject = enforce_subject_item_policy(raw_subject,profile)
|
32
|
+
message_digest = enforce_md(options[:message_digest], profile)
|
33
|
+
subject = enforce_subject_item_policy(raw_subject, profile)
|
34
34
|
enforce_not_after(options[:not_after])
|
35
35
|
|
36
36
|
extensions = build_and_merge_extensions(options, profile, public_key)
|
@@ -44,7 +44,7 @@ module R509::CertificateAuthority
|
|
44
44
|
return_hash = {
|
45
45
|
:subject => subject,
|
46
46
|
:extensions => extensions,
|
47
|
-
:message_digest => message_digest
|
47
|
+
:message_digest => message_digest
|
48
48
|
}
|
49
49
|
return_hash[:csr] = options[:csr] unless options[:csr].nil?
|
50
50
|
return_hash[:spki] = options[:spki] unless options[:spki].nil?
|
@@ -54,18 +54,18 @@ module R509::CertificateAuthority
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def enforce_not_after(not_after)
|
57
|
-
if
|
57
|
+
if not_after && @config.ca_cert.not_after < not_after
|
58
58
|
raise R509::R509Error, 'The requested certificate lifetime would exceed the issuing CA.'
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
|
-
def enforce_md(requested_md,profile)
|
62
|
+
def enforce_md(requested_md, profile)
|
63
63
|
# prior to OpenSSL 1.0 DSA could only use DSS1 (aka SHA1) signatures. post-1.0 anything
|
64
64
|
# goes but at the moment we don't enforce this restriction so an OpenSSL error could
|
65
65
|
# bubble up if they do it wrong.
|
66
66
|
#
|
67
67
|
# First let's check to see if the config restricts the allowed mds
|
68
|
-
if
|
68
|
+
if profile.allowed_mds && requested_md
|
69
69
|
if profile.allowed_mds.include?(requested_md.upcase)
|
70
70
|
message_digest = R509::MessageDigest.new(requested_md)
|
71
71
|
else
|
@@ -73,14 +73,14 @@ module R509::CertificateAuthority
|
|
73
73
|
end
|
74
74
|
else
|
75
75
|
# it doesn't, so either use their md (if valid) or the default one
|
76
|
-
|
76
|
+
message_digest = (requested_md) ? R509::MessageDigest.new(requested_md) : R509::MessageDigest.new(profile.default_md)
|
77
77
|
end
|
78
78
|
message_digest.name
|
79
79
|
end
|
80
80
|
|
81
81
|
# @return [R509::Subject]
|
82
|
-
def enforce_subject_item_policy(subject,profile)
|
83
|
-
if profile.subject_item_policy.nil?
|
82
|
+
def enforce_subject_item_policy(subject, profile)
|
83
|
+
if profile.subject_item_policy.nil?
|
84
84
|
subject
|
85
85
|
else
|
86
86
|
profile.subject_item_policy.validate_subject(subject)
|
@@ -88,16 +88,15 @@ module R509::CertificateAuthority
|
|
88
88
|
end
|
89
89
|
|
90
90
|
def build_and_merge_extensions(options, profile, public_key)
|
91
|
-
extensions = build_extensions(
|
91
|
+
extensions = build_extensions(profile, public_key)
|
92
92
|
|
93
|
-
|
94
|
-
extensions = merge_extensions(options,extensions)
|
93
|
+
unless options[:extensions].nil?
|
94
|
+
extensions = merge_extensions(options, extensions)
|
95
95
|
end
|
96
96
|
extensions
|
97
97
|
end
|
98
98
|
|
99
|
-
|
100
|
-
def merge_extensions(options,extensions)
|
99
|
+
def merge_extensions(options, extensions)
|
101
100
|
ext_hash = {}
|
102
101
|
extensions.each do |e|
|
103
102
|
ext_hash[e.class] = e
|
@@ -106,13 +105,13 @@ module R509::CertificateAuthority
|
|
106
105
|
ext_hash[e.class] = e
|
107
106
|
end
|
108
107
|
merged_ext = []
|
109
|
-
ext_hash.each do |
|
108
|
+
ext_hash.each do |_k, v|
|
110
109
|
merged_ext.push(v)
|
111
110
|
end
|
112
|
-
|
111
|
+
merged_ext
|
113
112
|
end
|
114
113
|
|
115
|
-
def build_extensions(
|
114
|
+
def build_extensions(profile, public_key)
|
116
115
|
extensions = []
|
117
116
|
|
118
117
|
extensions << profile.basic_constraints unless profile.basic_constraints.nil?
|
@@ -137,6 +136,5 @@ module R509::CertificateAuthority
|
|
137
136
|
extensions << profile.ocsp_no_check
|
138
137
|
extensions.compact
|
139
138
|
end
|
140
|
-
|
141
139
|
end
|
142
140
|
end
|