devpki 0.0.3 → 0.0.4
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.
- checksums.yaml +4 -4
- data/devpki.gemspec +1 -0
- data/lib/devpki/cli/ocsp.rb +65 -15
- data/lib/devpki/version.rb +1 -1
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fbc7720cc112b9758de034e6fa6f28f9ae19c364
|
4
|
+
data.tar.gz: feebcd561f7f8b042b008ddb16ec3e304a2e273d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 813fc219225e95e0639863df5ce58c90ded9139f663664788ec2b4c948adafb11c02d97735380d08d4c098f6115357279138225061790411363d7a5f29f7b193
|
7
|
+
data.tar.gz: 7a2e93ee9961430d3642c43dfe34cc31383e75e3a7fd5740ab43d74def64ee667cee22acf275ae02e16e926633071e789505e59c7e4e212038a722ba627c2c81
|
data/devpki.gemspec
CHANGED
data/lib/devpki/cli/ocsp.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
require 'devpki'
|
2
2
|
require 'thor'
|
3
3
|
require 'net/http'
|
4
|
+
require 'pry'
|
4
5
|
|
5
6
|
module DevPKI
|
6
7
|
class CLI < Thor
|
7
|
-
desc "ocsp [--method=get|post] --uri=<ocsp uri> ISSUER_CER_FILE:SUBJ_A.CER[,SUBJ_B.CER...]...", "Performs an OCSP query"
|
8
|
+
desc "ocsp [--method=get|post] --uri=<ocsp uri> [--chain-certs=ca1.cer,ca2.cer...] ISSUER_CER_FILE:SUBJ_A.CER[,SUBJ_B.CER...]...", "Performs an OCSP query"
|
8
9
|
long_desc <<-LONGDESC
|
9
10
|
This command performs an OCSP query against the given OCSP URI, over HTTP. To perform
|
10
11
|
a query, at least 2 certificates are needed - the CA certificate and the subject certificate
|
@@ -22,13 +23,20 @@ module DevPKI
|
|
22
23
|
LONGDESC
|
23
24
|
option :method, :default => "post", :banner => "get|post", :desc => "Method to use. GET as per RFC5019, or POST as per RFC2560. Defaults to POST."
|
24
25
|
option :uri, :banner => "<ocsp uri>", :required => true, :desc => "OCSP responder URI."
|
26
|
+
option :"chain-certs", :banner => "ca1.cer,ca2.cer...", :desc => "Trusted certificates that can be used, when verifying OCSP response signature."
|
25
27
|
|
26
28
|
def ocsp(*cer_files)
|
27
29
|
|
28
30
|
raise InvalidOption.new("Please specify at least one CA and subject certificate file.") if cer_files.empty?
|
29
31
|
|
32
|
+
chain_cert_files = []
|
33
|
+
if options[:"chain-certs"] != nil
|
34
|
+
chain_cert_files=options[:"chain-certs"].split(",")
|
35
|
+
end
|
36
|
+
|
30
37
|
ca_subj_map = {}
|
31
38
|
cer_files.each do |ca_subj_pair|
|
39
|
+
|
32
40
|
raise InvalidOption.new("\"#{ca_subj_pair}\" is an invalid CA and subject pair. Please pass a pair with format similar to \"ca.cer:a.cer[,b.cer...]\"") if not ca_subj_pair.include?(":")
|
33
41
|
|
34
42
|
ca_subjlist_split = ca_subj_pair.split(":")
|
@@ -55,6 +63,12 @@ module DevPKI
|
|
55
63
|
|
56
64
|
cert_ids = []
|
57
65
|
store = OpenSSL::X509::Store.new
|
66
|
+
chain_cert_files.each do |chain_cert_file|
|
67
|
+
puts "Adding #{chain_cert_file} to store"
|
68
|
+
store.add_file(chain_cert_file)
|
69
|
+
end
|
70
|
+
#store.set_default_paths
|
71
|
+
#store.add_file("root.crt")
|
58
72
|
|
59
73
|
ca_subj_map.each_pair do |ca_file, subj_file_list|
|
60
74
|
ca_cert = OpenSSL::X509::Certificate.new File.read(ca_file)
|
@@ -73,6 +87,7 @@ module DevPKI
|
|
73
87
|
end
|
74
88
|
|
75
89
|
request_uri = URI(options[:uri])
|
90
|
+
request_uri.path = "/" if request_uri.path.to_s.empty?
|
76
91
|
|
77
92
|
http_req = Net::HTTP::Post.new(request_uri.path)
|
78
93
|
http_req.content_type = "application/ocsp-request"
|
@@ -92,26 +107,61 @@ module DevPKI
|
|
92
107
|
puts "Status: #{response.status}"
|
93
108
|
puts "Status string: #{response.status_string}"
|
94
109
|
|
110
|
+
# Statuses from http://tools.ietf.org/html/rfc2560 section 4.2.1
|
111
|
+
#
|
112
|
+
# successful (0), --Response has valid confirmations
|
113
|
+
# malformedRequest (1), --Illegal confirmation request
|
114
|
+
# internalError (2), --Internal error in issuer
|
115
|
+
# tryLater (3), --Try again later
|
116
|
+
# --(4) is not used
|
117
|
+
# sigRequired (5), --Must sign the request
|
118
|
+
# unauthorized (6) --Request unauthorized
|
95
119
|
if response.status != 0
|
96
120
|
raise StandardError, "Not a successful status"
|
97
121
|
end
|
98
|
-
if response.basic[0][0].serial != cert.serial
|
99
|
-
raise StandardError, "Not the same serial"
|
100
|
-
end
|
101
|
-
if response.basic[0][1] != 0 # 0 is good, 1 is revoked, 2 is unknown.
|
102
|
-
raise StandardError, "Not a good status"
|
103
|
-
end
|
104
|
-
current_time = Time.now
|
105
|
-
if response.basic[0][4] > current_time or response.basic[0][5] < current_time
|
106
|
-
raise StandardError, "The response is not within its validity window"
|
107
|
-
end
|
108
122
|
|
109
|
-
#
|
110
|
-
|
111
|
-
|
112
|
-
|
123
|
+
# response.basic.status will be populated, if response.status == 0
|
124
|
+
cert_ids.each_with_index do |cert_id,ix|
|
125
|
+
|
126
|
+
# SingleResponse structure from http://tools.ietf.org/html/rfc2560 section 4.2.1
|
127
|
+
#
|
128
|
+
# SingleResponse ::= SEQUENCE {
|
129
|
+
# certID CertID,
|
130
|
+
# certStatus CertStatus,
|
131
|
+
# thisUpdate GeneralizedTime,
|
132
|
+
# nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL,
|
133
|
+
# singleExtensions [1] EXPLICIT Extensions OPTIONAL }
|
134
|
+
# single_response = response.basic.status[ix]
|
135
|
+
|
136
|
+
# Find the single response that matches current cert_id
|
137
|
+
single_response = nil
|
138
|
+
response.basic.status.each do |single_response_candidate|
|
139
|
+
if single_response_candidate[0].serial.to_s == cert_id.serial.to_s
|
140
|
+
single_response = single_response_candidate
|
141
|
+
break
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
raise StandardError.new("SingleResponse for certificate s/n ##{cert_id.serial.to_s} not found.") if single_response == nil
|
146
|
+
|
147
|
+
# CertStatus from from http://tools.ietf.org/html/rfc2560 section 4.2.1
|
148
|
+
#
|
149
|
+
# CertStatus ::= CHOICE {
|
150
|
+
# good [0] IMPLICIT NULL,
|
151
|
+
# revoked [1] IMPLICIT RevokedInfo,
|
152
|
+
# unknown [2] IMPLICIT UnknownInfo }
|
153
|
+
if single_response[1] != 0
|
154
|
+
raise StandardError, "CertStatus for cert s/n #{cert_id.serial.to_s} is #{single_response[1]}"
|
155
|
+
end
|
156
|
+
|
157
|
+
current_time = Time.now
|
158
|
+
if single_response[4] > current_time or single_response[5] < current_time
|
159
|
+
raise StandardError, "The response for cert_id s/n #{cert_id.serial.to_s} is not within its validity window"
|
160
|
+
end
|
161
|
+
end
|
113
162
|
|
114
163
|
if response.basic.verify([],store) != true
|
164
|
+
binding.pry
|
115
165
|
raise StandardError, "Response not signed by a trusted certificate"
|
116
166
|
end
|
117
167
|
|
data/lib/devpki/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: devpki
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jānis Kiršteins
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-10-
|
11
|
+
date: 2013-10-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - ~>
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '1.3'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: rake
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|