Merge lp://staging/~rick-fdd/pyopenssl/actual_socket_test into lp://staging/~exarkun/pyopenssl/trunk

Proposed by rick_dean
Status: Merged
Merged at revision: not available
Proposed branch: lp://staging/~rick-fdd/pyopenssl/actual_socket_test
Merge into: lp://staging/~exarkun/pyopenssl/trunk
Diff against target: None lines
To merge this branch: bzr merge lp://staging/~rick-fdd/pyopenssl/actual_socket_test
Reviewer Review Type Date Requested Status
Jean-Paul Calderone Disapprove
Review via email: mp+8892@code.staging.launchpad.net
To post a comment you must log in.
Revision history for this message
rick_dean (rick-fdd) wrote :

"merging actual_socket_test sounds good to me." --Exarkun

Revision history for this message
Jean-Paul Calderone (exarkun) wrote :

Changes in the branch basically look good. I want to make some minor adjustments (actually I did already ;) - things like docstring style, method naming; nothing major.

This is the first time I have used the launchpad merge proposal review thingy, so I'm not really sure what I'm doing. I'm going to call this a "Disapprove" because I have a branch based off of this branch with my additional changes which I plan to merge.

Thanks!

review: Disapprove

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'doc/pyOpenSSL.tex'
2--- doc/pyOpenSSL.tex 2009-07-04 20:15:36 +0000
3+++ doc/pyOpenSSL.tex 2009-07-10 04:56:39 +0000
4@@ -725,10 +725,20 @@
5 The operation did not complete; the same I/O method should be called again
6 later, with the same arguments. Any I/O method can lead to this since new
7 handshakes can occur at any time.
8+
9+The wanted read is for "dirty" data sent over the network, not the
10+"clean" data inside the tunnel. For a socket based SSL connection,
11+"read" means data coming at us over the network. Until
12+that read succeeds, the attempted
13+\method{OpenSSL.SSL.Connection.recv},
14+\method{OpenSSL.SSL.Connection.send}, or
15+\method{OpenSSL.SSL.Connection.do_handshake} is prevented or incomplete.
16+You probably want to \method{select()} on the socket before trying again.
17 \end{excdesc}
18
19 \begin{excdesc}{WantWriteError}
20-See \exception{WantReadError}.
21+See \exception{WantReadError}. The socket may be too full to
22+write more data.
23 \end{excdesc}
24
25 \begin{excdesc}{WantX509LookupError}
26
27=== modified file 'test/test_ssl.py'
28--- test/test_ssl.py 2009-07-05 17:50:34 +0000
29+++ test/test_ssl.py 2009-07-10 04:52:39 +0000
30@@ -31,6 +31,31 @@
31 OP_NO_TICKET = None
32
33
34+def socket_pair():
35+ ''' Establish and return a pair of network sockets connected
36+ to each other. '''
37+ # Connect a pair of sockets
38+ port = socket()
39+ port.bind(('', 0))
40+ port.listen(1)
41+ client = socket()
42+ client.setblocking(False)
43+ client.connect_ex(port.getsockname())
44+ server = port.accept()[0]
45+ server.setblocking(False)
46+
47+ # Let's pass some unencrypted data to make sure our
48+ # socket connection is fine.
49+ stuff = "I've got a bad feeling about this."
50+ server.send(stuff)
51+ assert client.recv(1024) == stuff
52+ stuff = "What?!?! The First Bank of Alderaan!"
53+ client.send(stuff)
54+ assert server.recv(1024) == stuff
55+
56+ return (server, client)
57+
58+
59 class ContextTests(TestCase):
60 """
61 Unit tests for L{OpenSSL.SSL.Context}.
62@@ -88,13 +113,7 @@
63 L{Context.set_info_callback} accepts a callable which will be invoked
64 when certain information about an SSL connection is available.
65 """
66- port = socket()
67- port.bind(('', 0))
68- port.listen(1)
69-
70- client = socket()
71- client.setblocking(False)
72- client.connect_ex(port.getsockname())
73+ (server, client) = socket_pair()
74
75 clientSSL = Connection(Context(TLSv1_METHOD), client)
76 clientSSL.set_connect_state()
77@@ -109,9 +128,6 @@
78 context.use_privatekey(
79 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
80
81- server, ignored = port.accept()
82- server.setblocking(False)
83-
84 serverSSL = Connection(context, server)
85 serverSSL.set_accept_state()
86
87@@ -127,13 +143,7 @@
88
89
90 def _load_verify_locations_test(self, *args):
91- port = socket()
92- port.bind(('', 0))
93- port.listen(1)
94-
95- client = socket()
96- client.setblocking(False)
97- client.connect_ex(port.getsockname())
98+ (server, client) = socket_pair()
99
100 clientContext = Context(TLSv1_METHOD)
101 clientContext.load_verify_locations(*args)
102@@ -146,9 +156,6 @@
103 clientSSL = Connection(clientContext, client)
104 clientSSL.set_connect_state()
105
106- server, _ = port.accept()
107- server.setblocking(False)
108-
109 serverContext = Context(TLSv1_METHOD)
110 serverContext.use_certificate(
111 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
112@@ -412,7 +419,7 @@
113 """
114 Tests for L{OpenSSL.SSL.Connection} using a memory BIO.
115 """
116- def _server(self):
117+ def _server(self, sock=None):
118 # Create the server side Connection. This is mostly setup boilerplate
119 # - use TLSv1, use a particular certificate, etc.
120 server_ctx = Context(TLSv1_METHOD)
121@@ -423,14 +430,14 @@
122 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
123 server_ctx.check_privatekey()
124 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
125- # Here the Connection is actually created. None is passed as the 2nd
126- # parameter, indicating a memory BIO should be created.
127- server_conn = Connection(server_ctx, None)
128+ # Here the Connection is actually created. If None is passed as the 2nd
129+ # parameter, it indicates a memory BIO should be created.
130+ server_conn = Connection(server_ctx, sock)
131 server_conn.set_accept_state()
132 return server_conn
133
134
135- def _client(self):
136+ def _client(self, sock=None):
137 # Now create the client side Connection. Similar boilerplate to the above.
138 client_ctx = Context(TLSv1_METHOD)
139 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
140@@ -440,8 +447,7 @@
141 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
142 client_ctx.check_privatekey()
143 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
144- # Again, None to create a new memory BIO.
145- client_conn = Connection(client_ctx, None)
146+ client_conn = Connection(client_ctx, sock)
147 client_conn.set_connect_state()
148 return client_conn
149
150@@ -536,6 +542,42 @@
151 (server_conn, important_message[::-1]))
152
153
154+ def test_socket_connect(self):
155+ """
156+ Just like test_connect() but with an actual socket.
157+ """
158+ (server, client) = socket_pair()
159+
160+ # Let the encryption begin...
161+ client_conn = self._client(client)
162+ client_conn.set_connect_state()
163+ server_conn = self._server(server)
164+ server_conn.set_accept_state()
165+ # Establish the connection
166+ established = False
167+ while not established:
168+ established = True # assume the best
169+ for ssl in client_conn, server_conn:
170+ try:
171+ # Generally a recv() or send() could also work instead
172+ # of do_handshake(), and we would stop on the first
173+ # non-exception.
174+ ssl.do_handshake()
175+ except WantReadError:
176+ established = False
177+
178+ important_message = "Help me Obi Wan Kenobi, you're my only hope."
179+ client_conn.send(important_message)
180+ msg = server_conn.recv(1024)
181+ self.assertEqual(msg, important_message)
182+
183+ # Again in the other direction, just for fun.
184+ important_message = important_message[::-1]
185+ server_conn.send(important_message)
186+ msg = client_conn.recv(1024)
187+ self.assertEqual(msg, important_message)
188+
189+
190 def test_socketOverridesMemory(self):
191 """
192 Test that L{OpenSSL.SSL.bio_read} and L{OpenSSL.SSL.bio_write} don't

Subscribers

People subscribed via source and target branches

to status/vote changes: