Module: SSLCertificateVerification

Included in:
Bridge::Tcp
Defined in:
lib/ssl_utils.rb

Overview

Verifies that the peer certificate is a valid chained certificate. That is, it’s signed by a root CA or a CA signed by a root CA.

This module will also perform hostname verification against the server’s certificate, but only if an instance variable called @hostname exists.

Class Attribute Summary collapse

Instance Method Summary collapse

Class Attribute Details

.ca_cert_fileObject



27
28
29
# File 'lib/ssl_utils.rb', line 27

def ca_cert_file
  @ca_cert_file
end

Instance Method Details

#ca_storeObject



30
31
32
33
34
35
36
37
38
39
40
# File 'lib/ssl_utils.rb', line 30

def ca_store
  unless @ca_store
    if file = SSLCertificateVerification.ca_cert_file
      @ca_store = OpenSSL::X509::Store.new
      @ca_store.add_file(file)
    else
      fail "you must specify a file with root CA certificates as `SSLCertificateVerification.ca_cert_file'"
    end
  end
  @ca_store
end

#ssl_handshake_completedObject



61
62
63
64
65
66
67
# File 'lib/ssl_utils.rb', line 61

def ssl_handshake_completed
  if @hostname
    unless OpenSSL::SSL.verify_certificate_identity(@last_seen_cert, @hostname)
      fail "the hostname `HOSTNAME' does not match the server certificate"
    end
  end
end

#ssl_verify_peer(cert_string) ⇒ Object

It’s important that we try to not add a certificate to the store that’s already in the store, because OpenSSL::X509::Store will raise an exception.



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/ssl_utils.rb', line 44

def ssl_verify_peer(cert_string)
  cert = OpenSSL::X509::Certificate.new(cert_string)
  # Some servers send the same certificate multiple times. I'm not even joking... (gmail.com)
  return true if cert == @last_seen_cert
  @last_seen_cert = cert

  if ca_store.verify(@last_seen_cert)
    # A server may send the root certifiacte, which we already have and thus
    # should not be added to the store again.
    ca_store.add_cert(@last_seen_cert) unless @last_seen_cert.root?
    true
  else
    fail "unable to verify the server certificate of `#{@hostname}'"
    false
  end
end