| 
									
										
										
										
											2001-08-20 22:39:42 +00:00
										 |  |  | # Test just the SSL support in the socket module, in a moderately bogus way. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-31 19:09:56 +00:00
										 |  |  | import sys | 
					
						
							| 
									
										
										
										
											2007-04-03 14:05:08 +00:00
										 |  |  | import unittest | 
					
						
							| 
									
										
										
										
											2002-07-23 19:04:11 +00:00
										 |  |  | from test import test_support | 
					
						
							| 
									
										
										
										
											2002-12-04 03:26:57 +00:00
										 |  |  | import socket | 
					
						
							| 
									
										
										
										
											2006-06-20 17:30:26 +00:00
										 |  |  | import errno | 
					
						
							| 
									
										
										
										
											2007-04-03 14:05:08 +00:00
										 |  |  | import threading | 
					
						
							|  |  |  | import subprocess | 
					
						
							|  |  |  | import time | 
					
						
							| 
									
										
										
										
											2007-04-03 17:29:48 +00:00
										 |  |  | import os | 
					
						
							|  |  |  | import urllib | 
					
						
							| 
									
										
										
										
											2007-04-03 14:05:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | # Optionally test SSL support, if we have it in the tested platform | 
					
						
							|  |  |  | skip_expected = not hasattr(socket, "ssl") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ConnectedTests(unittest.TestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testBasic(self): | 
					
						
							|  |  |  |         socket.RAND_status() | 
					
						
							| 
									
										
										
										
											2003-06-30 03:25:20 +00:00
										 |  |  |         try: | 
					
						
							| 
									
										
										
										
											2007-04-03 14:05:08 +00:00
										 |  |  |             socket.RAND_egd(1) | 
					
						
							|  |  |  |         except TypeError: | 
					
						
							| 
									
										
										
										
											2003-06-30 03:25:20 +00:00
										 |  |  |             pass | 
					
						
							|  |  |  |         else: | 
					
						
							| 
									
										
										
										
											2007-04-03 14:05:08 +00:00
										 |  |  |             print "didn't raise TypeError" | 
					
						
							|  |  |  |         socket.RAND_add("this is a random string", 75.0) | 
					
						
							| 
									
										
										
										
											2007-04-25 06:30:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-03 14:05:08 +00:00
										 |  |  |         with test_support.transient_internet(): | 
					
						
							|  |  |  |             f = urllib.urlopen('https://sf.net') | 
					
						
							|  |  |  |         buf = f.read() | 
					
						
							|  |  |  |         f.close() | 
					
						
							| 
									
										
										
										
											2007-04-25 06:30:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-03 14:05:08 +00:00
										 |  |  |     def testTimeout(self): | 
					
						
							|  |  |  |         def error_msg(extra_msg): | 
					
						
							|  |  |  |             print >> sys.stderr, """\
 | 
					
						
							|  |  |  |         WARNING:  an attempt to connect to %r %s, in | 
					
						
							|  |  |  |         test_timeout.  That may be legitimate, but is not the outcome we | 
					
						
							|  |  |  |         hoped for.  If this message is seen often, test_timeout should be | 
					
						
							|  |  |  |         changed to use a more reliable address.""" % (ADDR, extra_msg)
 | 
					
						
							| 
									
										
										
										
											2007-04-25 06:30:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-03 14:05:08 +00:00
										 |  |  |         # A service which issues a welcome banner (without need to write | 
					
						
							|  |  |  |         # anything). | 
					
						
							|  |  |  |         # XXX ("gmail.org", 995) has been unreliable so far, from time to | 
					
						
							| 
									
										
										
										
											2007-04-25 06:30:05 +00:00
										 |  |  |         # XXX time non-responsive for hours on end (& across all buildbot | 
					
						
							| 
									
										
										
										
											2007-04-03 14:05:08 +00:00
										 |  |  |         # XXX slaves, so that's not just a local thing). | 
					
						
							|  |  |  |         ADDR = "gmail.org", 995 | 
					
						
							| 
									
										
										
										
											2007-04-25 06:30:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-03 14:05:08 +00:00
										 |  |  |         s = socket.socket() | 
					
						
							|  |  |  |         s.settimeout(30.0) | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             s.connect(ADDR) | 
					
						
							|  |  |  |         except socket.timeout: | 
					
						
							|  |  |  |             error_msg('timed out') | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         except socket.error, exc:  # In case connection is refused. | 
					
						
							|  |  |  |             if exc.args[0] == errno.ECONNREFUSED: | 
					
						
							|  |  |  |                 error_msg('was refused') | 
					
						
							|  |  |  |                 return | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 raise | 
					
						
							| 
									
										
										
										
											2007-04-25 06:30:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-03 14:05:08 +00:00
										 |  |  |         ss = socket.ssl(s) | 
					
						
							|  |  |  |         # Read part of return welcome banner twice. | 
					
						
							|  |  |  |         ss.read(1) | 
					
						
							|  |  |  |         ss.read(1) | 
					
						
							|  |  |  |         s.close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class BasicTests(unittest.TestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testRudeShutdown(self): | 
					
						
							|  |  |  |         # Some random port to connect to. | 
					
						
							|  |  |  |         PORT = [9934] | 
					
						
							| 
									
										
										
										
											2007-04-25 06:30:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-03 14:05:08 +00:00
										 |  |  |         listener_ready = threading.Event() | 
					
						
							|  |  |  |         listener_gone = threading.Event() | 
					
						
							| 
									
										
										
										
											2007-04-25 06:30:05 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # `listener` runs in a thread.  It opens a socket listening on | 
					
						
							| 
									
										
										
										
											2007-04-03 14:05:08 +00:00
										 |  |  |         # PORT, and sits in an accept() until the main thread connects. | 
					
						
							|  |  |  |         # Then it rudely closes the socket, and sets Event `listener_gone` | 
					
						
							|  |  |  |         # to let the main thread know the socket is gone. | 
					
						
							|  |  |  |         def listener(): | 
					
						
							|  |  |  |             s = socket.socket() | 
					
						
							|  |  |  |             PORT[0] = test_support.bind_port(s, '', PORT[0]) | 
					
						
							|  |  |  |             s.listen(5) | 
					
						
							|  |  |  |             listener_ready.set() | 
					
						
							|  |  |  |             s.accept() | 
					
						
							|  |  |  |             s = None # reclaim the socket object, which also closes it | 
					
						
							|  |  |  |             listener_gone.set() | 
					
						
							| 
									
										
										
										
											2007-04-25 06:30:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-03 14:05:08 +00:00
										 |  |  |         def connector(): | 
					
						
							|  |  |  |             listener_ready.wait() | 
					
						
							|  |  |  |             s = socket.socket() | 
					
						
							|  |  |  |             s.connect(('localhost', PORT[0])) | 
					
						
							|  |  |  |             listener_gone.wait() | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 ssl_sock = socket.ssl(s) | 
					
						
							|  |  |  |             except socket.sslerror: | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 raise test_support.TestFailed( | 
					
						
							| 
									
										
										
										
											2006-01-24 22:44:54 +00:00
										 |  |  |                       'connecting to closed SSL socket should have failed') | 
					
						
							| 
									
										
										
										
											2007-04-25 06:30:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-03 14:05:08 +00:00
										 |  |  |         t = threading.Thread(target=listener) | 
					
						
							|  |  |  |         t.start() | 
					
						
							|  |  |  |         connector() | 
					
						
							|  |  |  |         t.join() | 
					
						
							| 
									
										
										
										
											2003-06-30 03:25:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-03 17:29:48 +00:00
										 |  |  | class OpenSSLTests(unittest.TestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testBasic(self): | 
					
						
							|  |  |  |         s = socket.socket() | 
					
						
							|  |  |  |         s.connect(("localhost", 4433)) | 
					
						
							|  |  |  |         ss = socket.ssl(s) | 
					
						
							|  |  |  |         ss.write("Foo\n") | 
					
						
							|  |  |  |         i = ss.read(4) | 
					
						
							|  |  |  |         self.assertEqual(i, "Foo\n") | 
					
						
							| 
									
										
										
										
											2007-04-03 21:15:34 +00:00
										 |  |  |         s.close() | 
					
						
							| 
									
										
										
										
											2007-04-03 17:29:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-22 01:18:56 +00:00
										 |  |  |     def testMethods(self): | 
					
						
							|  |  |  |         # read & write is already tried in the Basic test | 
					
						
							|  |  |  |         # now we'll try to get the server info about certificates | 
					
						
							|  |  |  |         # this came from the certificate I used, one I found in /usr/share/openssl | 
					
						
							|  |  |  |         info = "/C=PT/ST=Queensland/L=Lisboa/O=Neuronio, Lda./OU=Desenvolvimento/CN=brutus.neuronio.pt/emailAddress=sampo@iki.fi" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         s = socket.socket() | 
					
						
							|  |  |  |         s.connect(("localhost", 4433)) | 
					
						
							|  |  |  |         ss = socket.ssl(s) | 
					
						
							|  |  |  |         cert = ss.server() | 
					
						
							|  |  |  |         self.assertEqual(cert, info) | 
					
						
							|  |  |  |         cert = ss.issuer() | 
					
						
							|  |  |  |         self.assertEqual(cert, info) | 
					
						
							|  |  |  |         s.close() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-03 17:29:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | class OpenSSLServer(threading.Thread): | 
					
						
							|  |  |  |     def __init__(self): | 
					
						
							|  |  |  |         self.s = None | 
					
						
							|  |  |  |         self.keepServing = True | 
					
						
							| 
									
										
										
										
											2007-04-03 21:15:34 +00:00
										 |  |  |         self._external() | 
					
						
							|  |  |  |         if self.haveServer: | 
					
						
							|  |  |  |             threading.Thread.__init__(self) | 
					
						
							| 
									
										
										
										
											2003-06-30 03:25:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-03 21:15:34 +00:00
										 |  |  |     def _external(self): | 
					
						
							| 
									
										
										
										
											2007-04-04 14:10:40 +00:00
										 |  |  |         # let's find the .pem files | 
					
						
							|  |  |  |         curdir = os.path.dirname(__file__) or os.curdir | 
					
						
							|  |  |  |         cert_file = os.path.join(curdir, "ssl_cert.pem") | 
					
						
							|  |  |  |         if not os.access(cert_file, os.F_OK): | 
					
						
							|  |  |  |             raise ValueError("No cert file found! (tried %r)" % cert_file) | 
					
						
							|  |  |  |         key_file = os.path.join(curdir, "ssl_key.pem") | 
					
						
							|  |  |  |         if not os.access(key_file, os.F_OK): | 
					
						
							|  |  |  |             raise ValueError("No key file found! (tried %r)" % key_file) | 
					
						
							| 
									
										
										
										
											2007-04-03 17:29:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-03 21:15:34 +00:00
										 |  |  |         try: | 
					
						
							|  |  |  |             cmd = "openssl s_server -cert %s -key %s -quiet" % (cert_file, key_file) | 
					
						
							| 
									
										
										
										
											2007-04-25 06:30:05 +00:00
										 |  |  |             self.s = subprocess.Popen(cmd.split(), stdin=subprocess.PIPE, | 
					
						
							|  |  |  |                                        stdout=subprocess.PIPE, | 
					
						
							| 
									
										
										
										
											2007-04-03 17:29:48 +00:00
										 |  |  |                                        stderr=subprocess.STDOUT) | 
					
						
							| 
									
										
										
										
											2007-04-03 21:15:34 +00:00
										 |  |  |             time.sleep(1) | 
					
						
							|  |  |  |         except: | 
					
						
							|  |  |  |             self.haveServer = False | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             # let's try if it is actually up | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 s = socket.socket() | 
					
						
							|  |  |  |                 s.connect(("localhost", 4433)) | 
					
						
							|  |  |  |                 s.close() | 
					
						
							| 
									
										
										
										
											2007-04-10 03:00:37 +00:00
										 |  |  |                 if self.s.stdout.readline() != "ERROR\n": | 
					
						
							| 
									
										
										
										
											2007-04-10 04:44:49 +00:00
										 |  |  |                     raise ValueError | 
					
						
							| 
									
										
										
										
											2007-04-03 21:15:34 +00:00
										 |  |  |             except: | 
					
						
							|  |  |  |                 self.haveServer = False | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 self.haveServer = True | 
					
						
							| 
									
										
										
										
											2007-04-25 06:30:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-03 21:15:34 +00:00
										 |  |  |     def run(self): | 
					
						
							| 
									
										
										
										
											2007-04-03 17:29:48 +00:00
										 |  |  |         while self.keepServing: | 
					
						
							|  |  |  |             time.sleep(.5) | 
					
						
							|  |  |  |             l = self.s.stdout.readline() | 
					
						
							|  |  |  |             self.s.stdin.write(l) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def shutdown(self): | 
					
						
							|  |  |  |         self.keepServing = False | 
					
						
							|  |  |  |         if not self.s: | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         if sys.platform == "win32": | 
					
						
							| 
									
										
										
										
											2007-04-04 14:10:40 +00:00
										 |  |  |             subprocess.TerminateProcess(int(self.s._handle), -1) | 
					
						
							| 
									
										
										
										
											2007-04-03 17:29:48 +00:00
										 |  |  |         else: | 
					
						
							|  |  |  |             os.kill(self.s.pid, 15) | 
					
						
							| 
									
										
										
										
											2007-04-25 06:30:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-06-30 03:25:20 +00:00
										 |  |  | def test_main(): | 
					
						
							| 
									
										
										
										
											2003-07-01 13:44:28 +00:00
										 |  |  |     if not hasattr(socket, "ssl"): | 
					
						
							|  |  |  |         raise test_support.TestSkipped("socket module has no ssl support") | 
					
						
							| 
									
										
										
										
											2007-04-03 14:05:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     tests = [BasicTests] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if test_support.is_resource_enabled('network'): | 
					
						
							|  |  |  |         tests.append(ConnectedTests) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-03 17:29:48 +00:00
										 |  |  |     # in these platforms we can kill the openssl process | 
					
						
							|  |  |  |     if sys.platform in ("sunos5", "darwin", "linux1", | 
					
						
							|  |  |  |                         "linux2", "win32", "hp-ux11"): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         server = OpenSSLServer() | 
					
						
							| 
									
										
										
										
											2007-04-03 21:15:34 +00:00
										 |  |  |         if server.haveServer: | 
					
						
							|  |  |  |             tests.append(OpenSSLTests) | 
					
						
							|  |  |  |             server.start() | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         server = None | 
					
						
							| 
									
										
										
										
											2007-04-03 17:29:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-03 14:05:08 +00:00
										 |  |  |     thread_info = test_support.threading_setup() | 
					
						
							| 
									
										
										
										
											2003-06-30 03:25:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-03 21:15:34 +00:00
										 |  |  |     try: | 
					
						
							|  |  |  |         test_support.run_unittest(*tests) | 
					
						
							|  |  |  |     finally: | 
					
						
							|  |  |  |         if server is not None and server.haveServer: | 
					
						
							|  |  |  |             server.shutdown() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     test_support.threading_cleanup(*thread_info) | 
					
						
							| 
									
										
										
										
											2007-04-03 17:29:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-12-04 03:26:57 +00:00
										 |  |  | if __name__ == "__main__": | 
					
						
							|  |  |  |     test_main() |