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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6955eee6a2a6194ffed37756e37a08addf819630
4
- data.tar.gz: c034539b017c45656535e837435115a32b9a535d
3
+ metadata.gz: fbc7720cc112b9758de034e6fa6f28f9ae19c364
4
+ data.tar.gz: feebcd561f7f8b042b008ddb16ec3e304a2e273d
5
5
  SHA512:
6
- metadata.gz: 53625e5fc5e30459f56872633c8d32a4adcd542a3f85ce145bd2d6ea3a27485510f00593ea245c98ee3facff55d02211e8769e9319bdfbbe831fbd700e42f0e1
7
- data.tar.gz: afcecd2f7a8702c57cc7d94f477b0b73259aaf290e1444fa0eab6a876c86058d75932aac132ee8efe61d0713d93d8a172bbdc9370a8e934694d8e16b6dc655e3
6
+ metadata.gz: 813fc219225e95e0639863df5ce58c90ded9139f663664788ec2b4c948adafb11c02d97735380d08d4c098f6115357279138225061790411363d7a5f29f7b193
7
+ data.tar.gz: 7a2e93ee9961430d3642c43dfe34cc31383e75e3a7fd5740ab43d74def64ee667cee22acf275ae02e16e926633071e789505e59c7e4e212038a722ba627c2c81
@@ -22,5 +22,6 @@ Gem::Specification.new do |spec|
22
22
  spec.add_runtime_dependency "sqlite3"
23
23
  spec.add_runtime_dependency "xdg"
24
24
  spec.add_development_dependency "bundler", "~> 1.3"
25
+ spec.add_development_dependency "pry"
25
26
  spec.add_development_dependency "rake"
26
27
  end
@@ -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
- # we also need to verify that the OCSP response is signed by
110
- # a certificate that is allowed and chains up to a trusted root.
111
- # To do this you'll need to build an OpenSSL::X509::Store object
112
- # that contains the certificate you're checking + intermediates + root.
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
 
@@ -1,3 +1,3 @@
1
1
  module DevPKI
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
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.3
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-24 00:00:00.000000000 Z
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