aboutsummaryrefslogtreecommitdiff
path: root/vendor/certificate_authority/lib/certificate_authority/ocsp_handler.rb
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/certificate_authority/lib/certificate_authority/ocsp_handler.rb')
-rw-r--r--vendor/certificate_authority/lib/certificate_authority/ocsp_handler.rb144
1 files changed, 144 insertions, 0 deletions
diff --git a/vendor/certificate_authority/lib/certificate_authority/ocsp_handler.rb b/vendor/certificate_authority/lib/certificate_authority/ocsp_handler.rb
new file mode 100644
index 0000000..e101f98
--- /dev/null
+++ b/vendor/certificate_authority/lib/certificate_authority/ocsp_handler.rb
@@ -0,0 +1,144 @@
+module CertificateAuthority
+ class OCSPResponseBuilder
+ attr_accessor :ocsp_response
+ attr_accessor :verification_mechanism
+ attr_accessor :ocsp_request_reader
+ attr_accessor :parent
+ attr_accessor :next_update
+
+ GOOD = OpenSSL::OCSP::V_CERTSTATUS_GOOD
+ REVOKED = OpenSSL::OCSP::V_CERTSTATUS_REVOKED
+
+ NO_REASON=0
+ KEY_COMPROMISED=OpenSSL::OCSP::REVOKED_STATUS_KEYCOMPROMISE
+ UNSPECIFIED=OpenSSL::OCSP::REVOKED_STATUS_UNSPECIFIED
+
+ def build_response()
+ raise "Requires a parent for signing" if @parent.nil?
+ if @verification_mechanism.nil?
+ ## If no verification callback is provided we're marking it GOOD
+ @verification_mechanism = lambda {|cert_id| [GOOD,NO_REASON] }
+ end
+
+ @ocsp_request_reader.ocsp_request.certid.each do |cert_id|
+ result,reason = verification_mechanism.call(cert_id.serial)
+
+ ## cert_id, status, reason, rev_time, this update, next update, ext
+ ## - unit of time is seconds
+ ## - rev_time is currently set to "now"
+ @ocsp_response.add_status(cert_id,
+ result, reason,
+ 0, 0, @next_update, nil)
+ end
+
+ @ocsp_response.sign(OpenSSL::X509::Certificate.new(@parent.to_pem), @parent.key_material.private_key, nil, nil)
+ OpenSSL::OCSP::Response.create(OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL, @ocsp_response)
+ end
+
+ def self.from_request_reader(request_reader,verification_mechanism=nil)
+ response_builder = OCSPResponseBuilder.new
+ response_builder.ocsp_request_reader = request_reader
+
+ ocsp_response = OpenSSL::OCSP::BasicResponse.new
+ ocsp_response.copy_nonce(request_reader.ocsp_request)
+ response_builder.ocsp_response = ocsp_response
+ response_builder.next_update = 60*15 #Default of 15 minutes
+ response_builder
+ end
+ end
+
+ class OCSPRequestReader
+ attr_accessor :raw_ocsp_request
+ attr_accessor :ocsp_request
+
+ def serial_numbers
+ @ocsp_request.certid.collect do |cert_id|
+ cert_id.serial
+ end
+ end
+
+ def self.from_der(request_body)
+ reader = OCSPRequestReader.new
+ reader.raw_ocsp_request = request_body
+ reader.ocsp_request = OpenSSL::OCSP::Request.new(request_body)
+
+ reader
+ end
+ end
+
+ ## DEPRECATED
+ class OCSPHandler
+ include ActiveModel::Validations
+
+ attr_accessor :ocsp_request
+ attr_accessor :certificate_ids
+
+ attr_accessor :certificates
+ attr_accessor :parent
+
+ attr_accessor :ocsp_response_body
+
+ validate do |crl|
+ errors.add :parent, "A parent entity must be set" if parent.nil?
+ end
+ validate :all_certificates_available
+
+ def initialize
+ self.certificates = {}
+ end
+
+ def <<(cert)
+ self.certificates[cert.serial_number.number.to_s] = cert
+ end
+
+ def extract_certificate_serials
+ openssl_request = OpenSSL::OCSP::Request.new(@ocsp_request)
+
+ self.certificate_ids = openssl_request.certid.collect do |cert_id|
+ cert_id.serial
+ end
+
+ self.certificate_ids
+ end
+
+
+ def response
+ raise "Invalid response" unless valid?
+
+ openssl_ocsp_response = OpenSSL::OCSP::BasicResponse.new
+ openssl_ocsp_request = OpenSSL::OCSP::Request.new(self.ocsp_request)
+ openssl_ocsp_response.copy_nonce(openssl_ocsp_request)
+
+ openssl_ocsp_request.certid.each do |cert_id|
+ certificate = self.certificates[cert_id.serial.to_s]
+
+ openssl_ocsp_response.add_status(cert_id,
+ OpenSSL::OCSP::V_CERTSTATUS_GOOD, 0,
+ 0, 0, 30, nil)
+ end
+
+
+ openssl_ocsp_response.sign(OpenSSL::X509::Certificate.new(self.parent.to_pem), self.parent.key_material.private_key, nil, nil)
+ final_response = OpenSSL::OCSP::Response.create(OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL, openssl_ocsp_response)
+ self.ocsp_response_body = final_response
+ self.ocsp_response_body
+ end
+
+ def to_der
+ raise "No signed OCSP response body available" if self.ocsp_response_body.nil?
+ self.ocsp_response_body.to_der
+ end
+
+ private
+
+ def all_certificates_available
+ openssl_ocsp_request = OpenSSL::OCSP::Request.new(self.ocsp_request)
+
+ openssl_ocsp_request.certid.each do |cert_id|
+ certificate = self.certificates[cert_id.serial.to_s]
+ errors.add(:base, "Certificate #{cert_id.serial} has not been added yet") if certificate.nil?
+ end
+ end
+
+ end
+end