~ubuntu-branches/ubuntu/quantal/ruby1.9.1/quantal

« back to all changes in this revision

Viewing changes to test/openssl/test_ssl_session.rb

  • Committer: Bazaar Package Importer
  • Author(s): Lucas Nussbaum
  • Date: 2011-09-24 19:16:17 UTC
  • mfrom: (1.1.8 upstream) (13.1.7 experimental)
  • Revision ID: james.westby@ubuntu.com-20110924191617-o1qz4rcmqjot8zuy
Tags: 1.9.3~rc1-1
* New upstream release: 1.9.3 RC1.
  + Includes load.c fixes. Closes: #639959.
* Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
require_relative "utils"
 
2
 
 
3
if defined?(OpenSSL)
 
4
 
 
5
class OpenSSL::TestSSLSession < OpenSSL::SSLTestCase
 
6
  def test_session
 
7
    start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
 
8
      sock = TCPSocket.new("127.0.0.1", port)
 
9
      ctx = OpenSSL::SSL::SSLContext.new("TLSv1")
 
10
      ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
 
11
      ssl.sync_close = true
 
12
      ssl.connect
 
13
      session = ssl.session
 
14
      assert(session == OpenSSL::SSL::Session.new(session.to_pem))
 
15
      assert(session == OpenSSL::SSL::Session.new(ssl))
 
16
      assert_equal(300, session.timeout)
 
17
      session.timeout = 5
 
18
      assert_equal(5, session.timeout)
 
19
      assert_not_nil(session.time)
 
20
      # SSL_SESSION_time keeps long value so we can't keep nsec fragment.
 
21
      session.time = t1 = Time.now.to_i
 
22
      assert_equal(Time.at(t1), session.time)
 
23
      if session.respond_to?(:id)
 
24
        assert_not_nil(session.id)
 
25
      end
 
26
      pem = session.to_pem
 
27
      assert_match(/\A-----BEGIN SSL SESSION PARAMETERS-----/, pem)
 
28
      assert_match(/-----END SSL SESSION PARAMETERS-----\Z/, pem)
 
29
      pem.gsub!(/-----(BEGIN|END) SSL SESSION PARAMETERS-----/, '').gsub!(/[\r\n]+/m, '')
 
30
      assert_equal(session.to_der, pem.unpack('m*')[0])
 
31
      assert_not_nil(session.to_text)
 
32
      ssl.close
 
33
    end
 
34
  end
 
35
 
 
36
  DUMMY_SESSION = <<__EOS__
 
37
-----BEGIN SSL SESSION PARAMETERS-----
 
38
MIIDzQIBAQICAwEEAgA5BCAF219w9ZEV8dNA60cpEGOI34hJtIFbf3bkfzSgMyad
 
39
MQQwyGLbkCxE4OiMLdKKem+pyh8V7ifoP7tCxhdmwoDlJxI1v6nVCjai+FGYuncy
 
40
NNSWoQYCBE4DDWuiAwIBCqOCAo4wggKKMIIBcqADAgECAgECMA0GCSqGSIb3DQEB
 
41
BQUAMD0xEzARBgoJkiaJk/IsZAEZFgNvcmcxGTAXBgoJkiaJk/IsZAEZFglydWJ5
 
42
LWxhbmcxCzAJBgNVBAMMAkNBMB4XDTExMDYyMzA5NTQ1MVoXDTExMDYyMzEwMjQ1
 
43
MVowRDETMBEGCgmSJomT8ixkARkWA29yZzEZMBcGCgmSJomT8ixkARkWCXJ1Ynkt
 
44
bGFuZzESMBAGA1UEAwwJbG9jYWxob3N0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
 
45
iQKBgQDLwsSw1ECnPtT+PkOgHhcGA71nwC2/nL85VBGnRqDxOqjVh7CxaKPERYHs
 
46
k4BPCkE3brtThPWc9kjHEQQ7uf9Y1rbCz0layNqHyywQEVLFmp1cpIt/Q3geLv8Z
 
47
D9pihowKJDyMDiN6ArYUmZczvW4976MU3+l54E6lF/JfFEU5hwIDAQABoxIwEDAO
 
48
BgNVHQ8BAf8EBAMCBaAwDQYJKoZIhvcNAQEFBQADggEBACj5WhoZ/ODVeHpwgq1d
 
49
8fW/13ICRYHYpv6dzlWihyqclGxbKMlMnaVCPz+4JaVtMz3QB748KJQgL3Llg3R1
 
50
ek+f+n1MBCMfFFsQXJ2gtLB84zD6UCz8aaCWN5/czJCd7xMz7fRLy3TOIW5boXAU
 
51
zIa8EODk+477K1uznHm286ab0Clv+9d304hwmBZgkzLg6+31Of6d6s0E0rwLGiS2
 
52
sOWYg34Y3r4j8BS9Ak4jzpoLY6cJ0QAKCOJCgmjGr4XHpyXMLbicp3ga1uSbwtVO
 
53
gF/gTfpLhJC+y0EQ5x3Ftl88Cq7ZJuLBDMo/TLIfReJMQu/HlrTT7+LwtneSWGmr
 
54
KkSkAgQApQMCAROqgcMEgcAuDkAVfj6QAJMz9yqTzW5wPFyty7CxUEcwKjUqj5UP
 
55
/Yvky1EkRuM/eQfN7ucY+MUvMqv+R8ZSkHPsnjkBN5ChvZXjrUSZKFVjR4eFVz2V
 
56
jismLEJvIFhQh6pqTroRrOjMfTaM5Lwoytr2FTGobN9rnjIRsXeFQW1HLFbXn7Dh
 
57
8uaQkMwIVVSGRB8T7t6z6WIdWruOjCZ6G5ASI5XoqAHwGezhLodZuvJEfsVyCF9y
 
58
j+RBGfCFrrQbBdnkFI/ztgM=
 
59
-----END SSL SESSION PARAMETERS-----
 
60
__EOS__
 
61
 
 
62
  DUMMY_SESSION_NO_EXT = <<-__EOS__
 
63
-----BEGIN SSL SESSION PARAMETERS-----
 
64
MIIDCAIBAQICAwAEAgA5BCDyAW7rcpzMjDSosH+Tv6sukymeqgq3xQVVMez628A+
 
65
lAQw9TrKzrIqlHEh6ltuQaqv/Aq83AmaAlogYktZgXAjOGnhX7ifJDNLMuCfQq53
 
66
hPAaoQYCBE4iDeeiBAICASyjggKOMIICijCCAXKgAwIBAgIBAjANBgkqhkiG9w0B
 
67
AQUFADA9MRMwEQYKCZImiZPyLGQBGRYDb3JnMRkwFwYKCZImiZPyLGQBGRYJcnVi
 
68
eS1sYW5nMQswCQYDVQQDDAJDQTAeFw0xMTA3MTYyMjE3MTFaFw0xMTA3MTYyMjQ3
 
69
MTFaMEQxEzARBgoJkiaJk/IsZAEZFgNvcmcxGTAXBgoJkiaJk/IsZAEZFglydWJ5
 
70
LWxhbmcxEjAQBgNVBAMMCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
 
71
gYkCgYEAy8LEsNRApz7U/j5DoB4XBgO9Z8Atv5y/OVQRp0ag8Tqo1YewsWijxEWB
 
72
7JOATwpBN267U4T1nPZIxxEEO7n/WNa2ws9JWsjah8ssEBFSxZqdXKSLf0N4Hi7/
 
73
GQ/aYoaMCiQ8jA4jegK2FJmXM71uPe+jFN/peeBOpRfyXxRFOYcCAwEAAaMSMBAw
 
74
DgYDVR0PAQH/BAQDAgWgMA0GCSqGSIb3DQEBBQUAA4IBAQA3TRzABRG3kz8jEEYr
 
75
tDQqXgsxwTsLhTT5d1yF0D8uFw+y15hJAJnh6GJHjqhWBrF4zNoTApFo+4iIL6g3
 
76
q9C3mUsxIVAHx41DwZBh/FI7J4FqlAoGOguu7892CNVY3ZZjc3AXMTdKjcNoWPzz
 
77
FCdj5fNT24JMMe+ZdGZK97ChahJsdn/6B3j6ze9NK9mfYEbiJhejGTPLOFVHJCGR
 
78
KYYZ3ZcKhLDr9ql4d7cCo1gBtemrmFQGPui7GttNEqmXqUKvV8mYoa8farf5i7T4
 
79
L6a/gp2cVZTaDIS1HjbJsA/Ag7AajZqiN6LfqShNUVsrMZ+5CoV8EkBDTZPJ9MSr
 
80
a3EqpAIEAKUDAgET
 
81
-----END SSL SESSION PARAMETERS-----
 
82
__EOS__
 
83
 
 
84
 
 
85
  def test_session_time
 
86
    sess = OpenSSL::SSL::Session.new(DUMMY_SESSION_NO_EXT)
 
87
    sess.time = (now = Time.now)
 
88
    assert_equal(now.to_i, sess.time.to_i)
 
89
    sess.time = 1
 
90
    assert_equal(1, sess.time.to_i)
 
91
    sess.time = 1.2345
 
92
    assert_equal(1, sess.time.to_i)
 
93
    # Can OpenSSL handle t>2038y correctly? Version?
 
94
    sess.time = 2**31 - 1
 
95
    assert_equal(2**31 - 1, sess.time.to_i)
 
96
  end
 
97
 
 
98
  def test_session_timeout
 
99
    sess = OpenSSL::SSL::Session.new(DUMMY_SESSION_NO_EXT)
 
100
    assert_raise(TypeError) do
 
101
      sess.timeout = (now = Time.now)
 
102
    end
 
103
    sess.timeout = 1
 
104
    assert_equal(1, sess.timeout.to_i)
 
105
    sess.timeout = 1.2345
 
106
    assert_equal(1, sess.timeout.to_i)
 
107
    sess.timeout = 2**31 - 1
 
108
    assert_equal(2**31 - 1, sess.timeout.to_i)
 
109
  end
 
110
 
 
111
  def test_session_exts_read
 
112
    assert(OpenSSL::SSL::Session.new(DUMMY_SESSION))
 
113
  end if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x009080bf
 
114
 
 
115
  def test_client_session
 
116
    last_session = nil
 
117
    start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
 
118
      2.times do
 
119
        sock = TCPSocket.new("127.0.0.1", port)
 
120
        # Debian's openssl 0.9.8g-13 failed at assert(ssl.session_reused?),
 
121
        # when use default SSLContext. [ruby-dev:36167]
 
122
        ctx = OpenSSL::SSL::SSLContext.new("TLSv1")
 
123
        ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
 
124
        ssl.sync_close = true
 
125
        ssl.session = last_session if last_session
 
126
        ssl.connect
 
127
 
 
128
        session = ssl.session
 
129
        if last_session
 
130
          assert(ssl.session_reused?)
 
131
 
 
132
          if session.respond_to?(:id)
 
133
            assert_equal(session.id, last_session.id)
 
134
          end
 
135
          assert_equal(session.to_pem, last_session.to_pem)
 
136
          assert_equal(session.to_der, last_session.to_der)
 
137
          # Older version of OpenSSL may not be consistent.  Look up which versions later.
 
138
          assert_equal(session.to_text, last_session.to_text)
 
139
        else
 
140
          assert(!ssl.session_reused?)
 
141
        end
 
142
        last_session = session
 
143
 
 
144
        str = "x" * 100 + "\n"
 
145
        ssl.puts(str)
 
146
        assert_equal(str, ssl.gets)
 
147
 
 
148
        ssl.close
 
149
      end
 
150
    end
 
151
  end
 
152
 
 
153
  def test_server_session
 
154
    connections = 0
 
155
    saved_session = nil
 
156
 
 
157
    ctx_proc = Proc.new do |ctx, ssl|
 
158
# add test for session callbacks here
 
159
    end
 
160
 
 
161
    server_proc = Proc.new do |ctx, ssl|
 
162
      session = ssl.session
 
163
      stats = ctx.session_cache_stats
 
164
 
 
165
      case connections
 
166
      when 0
 
167
        assert_equal(stats[:cache_num], 1)
 
168
        assert_equal(stats[:cache_hits], 0)
 
169
        assert_equal(stats[:cache_misses], 0)
 
170
        assert(!ssl.session_reused?)
 
171
      when 1
 
172
        assert_equal(stats[:cache_num], 1)
 
173
        assert_equal(stats[:cache_hits], 1)
 
174
        assert_equal(stats[:cache_misses], 0)
 
175
        assert(ssl.session_reused?)
 
176
        ctx.session_remove(session)
 
177
        saved_session = session
 
178
      when 2
 
179
        assert_equal(stats[:cache_num], 1)
 
180
        assert_equal(stats[:cache_hits], 1)
 
181
        assert_equal(stats[:cache_misses], 1)
 
182
        assert(!ssl.session_reused?)
 
183
        ctx.session_add(saved_session)
 
184
      when 3
 
185
        assert_equal(stats[:cache_num], 2)
 
186
        assert_equal(stats[:cache_hits], 2)
 
187
        assert_equal(stats[:cache_misses], 1)
 
188
        assert(ssl.session_reused?)
 
189
        ctx.flush_sessions(Time.now + 5000)
 
190
      when 4
 
191
        assert_equal(stats[:cache_num], 1)
 
192
        assert_equal(stats[:cache_hits], 2)
 
193
        assert_equal(stats[:cache_misses], 2)
 
194
        assert(!ssl.session_reused?)
 
195
        ctx.session_add(saved_session)
 
196
      end
 
197
      connections += 1
 
198
 
 
199
      readwrite_loop(ctx, ssl)
 
200
    end
 
201
 
 
202
    first_session = nil
 
203
    start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => ctx_proc, :server_proc => server_proc) do |server, port|
 
204
      10.times do |i|
 
205
        sock = TCPSocket.new("127.0.0.1", port)
 
206
        ctx = OpenSSL::SSL::SSLContext.new
 
207
        if defined?(OpenSSL::SSL::OP_NO_TICKET)
 
208
          # disable RFC4507 support
 
209
          ctx.options = OpenSSL::SSL::OP_NO_TICKET
 
210
        end
 
211
        ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
 
212
        ssl.sync_close = true
 
213
        ssl.session = first_session if first_session
 
214
        ssl.connect
 
215
 
 
216
        session = ssl.session
 
217
        if first_session
 
218
          case i
 
219
          when 1; assert(ssl.session_reused?)
 
220
          when 2; assert(!ssl.session_reused?)
 
221
          when 3; assert(ssl.session_reused?)
 
222
          when 4; assert(!ssl.session_reused?)
 
223
          when 5..10; assert(ssl.session_reused?)
 
224
          end
 
225
        end
 
226
        first_session ||= session
 
227
 
 
228
        str = "x" * 100 + "\n"
 
229
        ssl.puts(str)
 
230
        assert_equal(str, ssl.gets)
 
231
 
 
232
        ssl.close
 
233
      end
 
234
    end
 
235
  end
 
236
 
 
237
  def test_ctx_client_session_cb
 
238
    called = {}
 
239
    ctx = OpenSSL::SSL::SSLContext.new("SSLv3")
 
240
    ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT
 
241
 
 
242
    ctx.session_new_cb = lambda { |ary|
 
243
      sock, sess = ary
 
244
      called[:new] = [sock, sess]
 
245
    }
 
246
 
 
247
    ctx.session_remove_cb = lambda { |ary|
 
248
      ctx, sess = ary
 
249
      called[:remove] = [ctx, sess]
 
250
      # any resulting value is OK (ignored)
 
251
    }
 
252
 
 
253
    start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
 
254
      sock = TCPSocket.new("127.0.0.1", port)
 
255
      ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
 
256
      ssl.sync_close = true
 
257
      ssl.connect
 
258
      assert_equal(1, ctx.session_cache_stats[:cache_num])
 
259
      assert_equal(1, ctx.session_cache_stats[:connect_good])
 
260
      assert_equal([ssl, ssl.session], called[:new])
 
261
      assert(ctx.session_remove(ssl.session))
 
262
      assert(!ctx.session_remove(ssl.session))
 
263
      assert_equal([ctx, ssl.session], called[:remove])
 
264
      ssl.close
 
265
    end
 
266
  end
 
267
 
 
268
  def test_ctx_server_session_cb
 
269
    called = {}
 
270
 
 
271
    ctx_proc = Proc.new { |ctx, ssl|
 
272
      ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_SERVER
 
273
      last_server_session = nil
 
274
 
 
275
      # get_cb is called whenever a client proposed to resume a session but
 
276
      # the session could not be found in the internal session cache.
 
277
      ctx.session_get_cb = lambda { |ary|
 
278
        sess, data = ary
 
279
        if last_server_session
 
280
          called[:get2] = [sess, data]
 
281
          last_server_session
 
282
        else
 
283
          called[:get1] = [sess, data]
 
284
          last_server_session = sess
 
285
          nil
 
286
        end
 
287
      }
 
288
 
 
289
      ctx.session_new_cb = lambda { |ary|
 
290
        sock, sess = ary
 
291
        called[:new] = [sock, sess]
 
292
        # SSL server doesn't cache sessions so get_cb is called next time.
 
293
        ctx.session_remove(sess)
 
294
      }
 
295
 
 
296
      ctx.session_remove_cb = lambda { |ary|
 
297
        ctx, sess = ary
 
298
        called[:remove] = [ctx, sess]
 
299
      }
 
300
    }
 
301
 
 
302
    server_proc = Proc.new { |c, ssl|
 
303
      session = ssl.session
 
304
      stats = c.session_cache_stats
 
305
      readwrite_loop(c, ssl)
 
306
    }
 
307
    start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => ctx_proc, :server_proc => server_proc) do |server, port|
 
308
      last_client_session = nil
 
309
      3.times do
 
310
        sock = TCPSocket.new("127.0.0.1", port)
 
311
        ssl = OpenSSL::SSL::SSLSocket.new(sock, OpenSSL::SSL::SSLContext.new("SSLv3"))
 
312
        ssl.sync_close = true
 
313
        ssl.session = last_client_session if last_client_session
 
314
        ssl.connect
 
315
        last_client_session = ssl.session
 
316
        ssl.close
 
317
        Thread.pass # try to ensure server calls callbacks
 
318
        assert(called.delete(:new))
 
319
        assert(called.delete(:remove))
 
320
      end
 
321
    end
 
322
    assert(called[:get1])
 
323
    assert(called[:get2])
 
324
  end
 
325
end
 
326
 
 
327
end