-
Notifications
You must be signed in to change notification settings - Fork 0
/
t.rb
109 lines (94 loc) · 2.99 KB
/
t.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
require 'rubygems'
require 'eventmachine'
require 'openssl'
class OpenSSL::X509::Certificate
def ==(other)
other.respond_to?(:to_pem) && to_pem == other.to_pem
end
# A serial *must* be unique for each certificate. Self-signed certificates,
# and thus root CA certificates, have the same `issuer' as `subject'.
def top_level?
serial == serial && issuer.to_s == subject.to_s
end
alias_method :root?, :top_level?
alias_method :self_signed?, :top_level?
end
# 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.
module SSLCertificateVerification
class << self
# In PEM format.
#
# Eg: http://curl.haxx.se/docs/caextract.html
attr_accessor :ca_cert_file
end
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
# 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.
def ssl_verify_peer(cert_string)
#puts cert_string
#puts
cert = OpenSSL::X509::Certificate.new(cert_string)
#p cert
# 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
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
else
warn "Skipping hostname verification because `@hostname' is not available."
end
end
end
module Handler
include SSLCertificateVerification
attr_accessor :hostname
def self.connect(hostname, port)
conn = EventMachine.connect(hostname, port, self)
conn.hostname = hostname
conn
end
def post_init
start_tls(:verify_peer => true)
end
def receive_data(data)
super
puts data
unless @sent
send_data "x CAPABILITY\r\n"
@sent = true
end
end
end
SSLCertificateVerification.ca_cert_file = File.expand_path('../lib/cacert.pem', __FILE__)
EventMachine.run do
#Handler.connect("imap.gmail.com", 993)
#Handler.connect("imap.mail.yahoo.com", 993)
Handler.connect("mx.easymail.ca", 993)
end