Class: Puppet::SSL::Verifier Private
Overview
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
Verify an SSL connection.
Constant Summary collapse
- FIVE_MINUTES_AS_SECONDS =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
5 * 60
Instance Attribute Summary collapse
- #ssl_context ⇒ Object readonly private
Instance Method Summary collapse
-
#call(preverify_ok, store_context) ⇒ Boolean
private
OpenSSL will call this method with the verification result for each cert in the server’s chain, working from the root CA to the server’s cert.
-
#handle_connection_error(http, error) ⇒ Object
private
This method is called if ‘Net::HTTP#start` raises an exception, which could be a result of an openssl error during cert verification, due to ruby’s ‘Socket#post_connection_check`, or general SSL connection error.
-
#initialize(hostname, ssl_context) ⇒ Verifier
constructor
private
Create a verifier using an ‘ssl_context`.
-
#reusable?(verifier) ⇒ Boolean
private
Return true if ‘self` is reusable with `verifier` meaning they are using the same `ssl_context`, so there’s no loss of security when using a cached connection.
-
#setup_connection(http) ⇒ Object
private
Configure the ‘http` connection based on the current `ssl_context`.
Constructor Details
#initialize(hostname, ssl_context) ⇒ Verifier
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Create a verifier using an ‘ssl_context`.
19 20 21 22 |
# File 'lib/puppet/ssl/verifier.rb', line 19 def initialize(hostname, ssl_context) @hostname = hostname @ssl_context = ssl_context end |
Instance Attribute Details
#ssl_context ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
11 12 13 |
# File 'lib/puppet/ssl/verifier.rb', line 11 def ssl_context @ssl_context end |
Instance Method Details
#call(preverify_ok, store_context) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
OpenSSL will call this method with the verification result for each cert in the server’s chain, working from the root CA to the server’s cert. If preverify_ok is ‘true`, then that cert passed verification. If it’s ‘false` then the current verification error is contained in `store_context.error`. and the current cert is in `store_context.current_cert`.
If this method returns ‘false`, then verification stops and ruby will raise an `OpenSSL::SSL::Error` with “certificate verification failed”. If this method returns `true`, then verification continues.
If this method ignores a verification error, such as the cert’s CRL will be valid within the next 5 minutes, then this method may be called with a different verification error for the same cert.
WARNING: If ‘store_context.error` returns `OpenSSL::X509::V_OK`, don’t assume verification passed. Ruby 2.4+ implements certificate hostname checking by default, and if the cert doesn’t match the hostname, then the error will be V_OK. Always use ‘preverify_ok` to determine if verification succeeded or not.
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/puppet/ssl/verifier.rb', line 105 def call(preverify_ok, store_context) return true if preverify_ok peer_cert = store_context.current_cert case store_context.error when OpenSSL::X509::V_OK # chain is from leaf to root, opposite of the order that `call` is invoked chain_cert = store_context.chain.first # ruby 2.4 doesn't compare certs based on value, so force to DER byte array if peer_cert && chain_cert && peer_cert.to_der == chain_cert.to_der && !OpenSSL::SSL.verify_certificate_identity(peer_cert, @hostname) @last_error = Puppet::SSL::CertMismatchError.new(peer_cert, @hostname) return false end # ruby-openssl#74ef8c0cc56b840b772240f2ee2b0fc0aafa2743 now sets the # store_context error when the cert is mismatched when OpenSSL::X509::V_ERR_HOSTNAME_MISMATCH @last_error = Puppet::SSL::CertMismatchError.new(peer_cert, @hostname) return false when OpenSSL::X509::V_ERR_CRL_NOT_YET_VALID crl = store_context.current_crl if crl && crl.last_update && crl.last_update < Time.now + FIVE_MINUTES_AS_SECONDS Puppet.debug("Ignoring CRL not yet valid, current time #{Time.now.utc}, CRL last updated #{crl.last_update.utc}") return true end end # TRANSLATORS: `error` is an untranslated message from openssl describing why a certificate in the server's chain is invalid, and `subject` is the identity/name of the failed certificate @last_error = Puppet::SSL::CertVerifyError.new( _("certificate verify failed [%{error} for %{subject}]") % { error: store_context.error_string, subject: peer_cert.subject.to_utf8 }, store_context.error, peer_cert ) false end |
#handle_connection_error(http, error) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method is called if ‘Net::HTTP#start` raises an exception, which could be a result of an openssl error during cert verification, due to ruby’s ‘Socket#post_connection_check`, or general SSL connection error.
65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/puppet/ssl/verifier.rb', line 65 def handle_connection_error(http, error) raise @last_error if @last_error # ruby can pass SSL validation but fail post_connection_check peer_cert = http.peer_cert if peer_cert && !OpenSSL::SSL.verify_certificate_identity(peer_cert, @hostname) raise Puppet::SSL::CertMismatchError.new(peer_cert, @hostname) else raise error end end |
#reusable?(verifier) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Return true if ‘self` is reusable with `verifier` meaning they are using the same `ssl_context`, so there’s no loss of security when using a cached connection.
31 32 33 34 |
# File 'lib/puppet/ssl/verifier.rb', line 31 def reusable?(verifier) verifier.instance_of?(self.class) && verifier.ssl_context.equal?(@ssl_context) # same object? end |
#setup_connection(http) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Configure the ‘http` connection based on the current `ssl_context`.
40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/puppet/ssl/verifier.rb', line 40 def setup_connection(http) http.cert_store = @ssl_context[:store] http.cert = @ssl_context[:client_cert] http.key = @ssl_context[:private_key] # default to VERIFY_PEER http.verify_mode = if !@ssl_context[:verify_peer] OpenSSL::SSL::VERIFY_NONE else OpenSSL::SSL::VERIFY_PEER end http.verify_callback = self end |