devpki 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|