PageRenderTime 53ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/Lib/test/test_ssl.py

https://bitbucket.org/hacman/python
Python | 1427 lines | 1244 code | 99 blank | 84 comment | 196 complexity | 7626f6467c0d74eadb76d29d0737be15 MD5 | raw file
Possible License(s): 0BSD

Large files files are truncated, but you can click here to view the full file

  1. # Test the support for SSL and sockets
  2. import sys
  3. import unittest
  4. from test import test_support
  5. import asyncore
  6. import socket
  7. import select
  8. import time
  9. import gc
  10. import os
  11. import errno
  12. import pprint
  13. import urllib, urlparse
  14. import traceback
  15. import weakref
  16. import functools
  17. import platform
  18. from BaseHTTPServer import HTTPServer
  19. from SimpleHTTPServer import SimpleHTTPRequestHandler
  20. ssl = test_support.import_module("ssl")
  21. HOST = test_support.HOST
  22. CERTFILE = None
  23. SVN_PYTHON_ORG_ROOT_CERT = None
  24. NULLBYTECERT = None
  25. def handle_error(prefix):
  26. exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
  27. if test_support.verbose:
  28. sys.stdout.write(prefix + exc_format)
  29. class BasicTests(unittest.TestCase):
  30. def test_sslwrap_simple(self):
  31. # A crude test for the legacy API
  32. try:
  33. ssl.sslwrap_simple(socket.socket(socket.AF_INET))
  34. except IOError, e:
  35. if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
  36. pass
  37. else:
  38. raise
  39. try:
  40. ssl.sslwrap_simple(socket.socket(socket.AF_INET)._sock)
  41. except IOError, e:
  42. if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
  43. pass
  44. else:
  45. raise
  46. # Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
  47. def skip_if_broken_ubuntu_ssl(func):
  48. if hasattr(ssl, 'PROTOCOL_SSLv2'):
  49. # We need to access the lower-level wrapper in order to create an
  50. # implicit SSL context without trying to connect or listen.
  51. try:
  52. import _ssl
  53. except ImportError:
  54. # The returned function won't get executed, just ignore the error
  55. pass
  56. @functools.wraps(func)
  57. def f(*args, **kwargs):
  58. try:
  59. s = socket.socket(socket.AF_INET)
  60. _ssl.sslwrap(s._sock, 0, None, None,
  61. ssl.CERT_NONE, ssl.PROTOCOL_SSLv2, None, None)
  62. except ssl.SSLError as e:
  63. if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
  64. platform.linux_distribution() == ('debian', 'squeeze/sid', '')
  65. and 'Invalid SSL protocol variant specified' in str(e)):
  66. raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
  67. return func(*args, **kwargs)
  68. return f
  69. else:
  70. return func
  71. class BasicSocketTests(unittest.TestCase):
  72. def test_constants(self):
  73. #ssl.PROTOCOL_SSLv2
  74. ssl.PROTOCOL_SSLv23
  75. ssl.PROTOCOL_SSLv3
  76. ssl.PROTOCOL_TLSv1
  77. ssl.CERT_NONE
  78. ssl.CERT_OPTIONAL
  79. ssl.CERT_REQUIRED
  80. def test_random(self):
  81. v = ssl.RAND_status()
  82. if test_support.verbose:
  83. sys.stdout.write("\n RAND_status is %d (%s)\n"
  84. % (v, (v and "sufficient randomness") or
  85. "insufficient randomness"))
  86. self.assertRaises(TypeError, ssl.RAND_egd, 1)
  87. self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
  88. ssl.RAND_add("this is a random string", 75.0)
  89. def test_parse_cert(self):
  90. # note that this uses an 'unofficial' function in _ssl.c,
  91. # provided solely for this test, to exercise the certificate
  92. # parsing code
  93. p = ssl._ssl._test_decode_cert(CERTFILE, False)
  94. if test_support.verbose:
  95. sys.stdout.write("\n" + pprint.pformat(p) + "\n")
  96. self.assertEqual(p['subject'],
  97. ((('countryName', 'XY'),),
  98. (('localityName', 'Castle Anthrax'),),
  99. (('organizationName', 'Python Software Foundation'),),
  100. (('commonName', 'localhost'),))
  101. )
  102. self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
  103. # Issue #13034: the subjectAltName in some certificates
  104. # (notably projects.developer.nokia.com:443) wasn't parsed
  105. p = ssl._ssl._test_decode_cert(NOKIACERT)
  106. if test_support.verbose:
  107. sys.stdout.write("\n" + pprint.pformat(p) + "\n")
  108. self.assertEqual(p['subjectAltName'],
  109. (('DNS', 'projects.developer.nokia.com'),
  110. ('DNS', 'projects.forum.nokia.com'))
  111. )
  112. def test_parse_cert_CVE_2013_4238(self):
  113. p = ssl._ssl._test_decode_cert(NULLBYTECERT)
  114. if test_support.verbose:
  115. sys.stdout.write("\n" + pprint.pformat(p) + "\n")
  116. subject = ((('countryName', 'US'),),
  117. (('stateOrProvinceName', 'Oregon'),),
  118. (('localityName', 'Beaverton'),),
  119. (('organizationName', 'Python Software Foundation'),),
  120. (('organizationalUnitName', 'Python Core Development'),),
  121. (('commonName', 'null.python.org\x00example.org'),),
  122. (('emailAddress', 'python-dev@python.org'),))
  123. self.assertEqual(p['subject'], subject)
  124. self.assertEqual(p['issuer'], subject)
  125. if ssl.OPENSSL_VERSION_INFO >= (0, 9, 8):
  126. san = (('DNS', 'altnull.python.org\x00example.com'),
  127. ('email', 'null@python.org\x00user@example.org'),
  128. ('URI', 'http://null.python.org\x00http://example.org'),
  129. ('IP Address', '192.0.2.1'),
  130. ('IP Address', '2001:DB8:0:0:0:0:0:1\n'))
  131. else:
  132. # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
  133. san = (('DNS', 'altnull.python.org\x00example.com'),
  134. ('email', 'null@python.org\x00user@example.org'),
  135. ('URI', 'http://null.python.org\x00http://example.org'),
  136. ('IP Address', '192.0.2.1'),
  137. ('IP Address', '<invalid>'))
  138. self.assertEqual(p['subjectAltName'], san)
  139. def test_DER_to_PEM(self):
  140. with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
  141. pem = f.read()
  142. d1 = ssl.PEM_cert_to_DER_cert(pem)
  143. p2 = ssl.DER_cert_to_PEM_cert(d1)
  144. d2 = ssl.PEM_cert_to_DER_cert(p2)
  145. self.assertEqual(d1, d2)
  146. if not p2.startswith(ssl.PEM_HEADER + '\n'):
  147. self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
  148. if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
  149. self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
  150. def test_openssl_version(self):
  151. n = ssl.OPENSSL_VERSION_NUMBER
  152. t = ssl.OPENSSL_VERSION_INFO
  153. s = ssl.OPENSSL_VERSION
  154. self.assertIsInstance(n, (int, long))
  155. self.assertIsInstance(t, tuple)
  156. self.assertIsInstance(s, str)
  157. # Some sanity checks follow
  158. # >= 0.9
  159. self.assertGreaterEqual(n, 0x900000)
  160. # < 2.0
  161. self.assertLess(n, 0x20000000)
  162. major, minor, fix, patch, status = t
  163. self.assertGreaterEqual(major, 0)
  164. self.assertLess(major, 2)
  165. self.assertGreaterEqual(minor, 0)
  166. self.assertLess(minor, 256)
  167. self.assertGreaterEqual(fix, 0)
  168. self.assertLess(fix, 256)
  169. self.assertGreaterEqual(patch, 0)
  170. self.assertLessEqual(patch, 26)
  171. self.assertGreaterEqual(status, 0)
  172. self.assertLessEqual(status, 15)
  173. # Version string as returned by OpenSSL, the format might change
  174. self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
  175. (s, t))
  176. def test_ciphers(self):
  177. if not test_support.is_resource_enabled('network'):
  178. return
  179. remote = ("svn.python.org", 443)
  180. with test_support.transient_internet(remote[0]):
  181. s = ssl.wrap_socket(socket.socket(socket.AF_INET),
  182. cert_reqs=ssl.CERT_NONE, ciphers="ALL")
  183. s.connect(remote)
  184. s = ssl.wrap_socket(socket.socket(socket.AF_INET),
  185. cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
  186. s.connect(remote)
  187. # Error checking occurs when connecting, because the SSL context
  188. # isn't created before.
  189. s = ssl.wrap_socket(socket.socket(socket.AF_INET),
  190. cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
  191. with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
  192. s.connect(remote)
  193. @test_support.cpython_only
  194. def test_refcycle(self):
  195. # Issue #7943: an SSL object doesn't create reference cycles with
  196. # itself.
  197. s = socket.socket(socket.AF_INET)
  198. ss = ssl.wrap_socket(s)
  199. wr = weakref.ref(ss)
  200. del ss
  201. self.assertEqual(wr(), None)
  202. def test_wrapped_unconnected(self):
  203. # The _delegate_methods in socket.py are correctly delegated to by an
  204. # unconnected SSLSocket, so they will raise a socket.error rather than
  205. # something unexpected like TypeError.
  206. s = socket.socket(socket.AF_INET)
  207. ss = ssl.wrap_socket(s)
  208. self.assertRaises(socket.error, ss.recv, 1)
  209. self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
  210. self.assertRaises(socket.error, ss.recvfrom, 1)
  211. self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
  212. self.assertRaises(socket.error, ss.send, b'x')
  213. self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
  214. class NetworkedTests(unittest.TestCase):
  215. def test_connect(self):
  216. with test_support.transient_internet("svn.python.org"):
  217. s = ssl.wrap_socket(socket.socket(socket.AF_INET),
  218. cert_reqs=ssl.CERT_NONE)
  219. s.connect(("svn.python.org", 443))
  220. c = s.getpeercert()
  221. if c:
  222. self.fail("Peer cert %s shouldn't be here!")
  223. s.close()
  224. # this should fail because we have no verification certs
  225. s = ssl.wrap_socket(socket.socket(socket.AF_INET),
  226. cert_reqs=ssl.CERT_REQUIRED)
  227. try:
  228. s.connect(("svn.python.org", 443))
  229. except ssl.SSLError:
  230. pass
  231. finally:
  232. s.close()
  233. # this should succeed because we specify the root cert
  234. s = ssl.wrap_socket(socket.socket(socket.AF_INET),
  235. cert_reqs=ssl.CERT_REQUIRED,
  236. ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
  237. try:
  238. s.connect(("svn.python.org", 443))
  239. finally:
  240. s.close()
  241. def test_connect_ex(self):
  242. # Issue #11326: check connect_ex() implementation
  243. with test_support.transient_internet("svn.python.org"):
  244. s = ssl.wrap_socket(socket.socket(socket.AF_INET),
  245. cert_reqs=ssl.CERT_REQUIRED,
  246. ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
  247. try:
  248. self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
  249. self.assertTrue(s.getpeercert())
  250. finally:
  251. s.close()
  252. def test_non_blocking_connect_ex(self):
  253. # Issue #11326: non-blocking connect_ex() should allow handshake
  254. # to proceed after the socket gets ready.
  255. with test_support.transient_internet("svn.python.org"):
  256. s = ssl.wrap_socket(socket.socket(socket.AF_INET),
  257. cert_reqs=ssl.CERT_REQUIRED,
  258. ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
  259. do_handshake_on_connect=False)
  260. try:
  261. s.setblocking(False)
  262. rc = s.connect_ex(('svn.python.org', 443))
  263. # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
  264. self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
  265. # Wait for connect to finish
  266. select.select([], [s], [], 5.0)
  267. # Non-blocking handshake
  268. while True:
  269. try:
  270. s.do_handshake()
  271. break
  272. except ssl.SSLError as err:
  273. if err.args[0] == ssl.SSL_ERROR_WANT_READ:
  274. select.select([s], [], [], 5.0)
  275. elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
  276. select.select([], [s], [], 5.0)
  277. else:
  278. raise
  279. # SSL established
  280. self.assertTrue(s.getpeercert())
  281. finally:
  282. s.close()
  283. def test_timeout_connect_ex(self):
  284. # Issue #12065: on a timeout, connect_ex() should return the original
  285. # errno (mimicking the behaviour of non-SSL sockets).
  286. with test_support.transient_internet("svn.python.org"):
  287. s = ssl.wrap_socket(socket.socket(socket.AF_INET),
  288. cert_reqs=ssl.CERT_REQUIRED,
  289. ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
  290. do_handshake_on_connect=False)
  291. try:
  292. s.settimeout(0.0000001)
  293. rc = s.connect_ex(('svn.python.org', 443))
  294. if rc == 0:
  295. self.skipTest("svn.python.org responded too quickly")
  296. self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
  297. finally:
  298. s.close()
  299. def test_connect_ex_error(self):
  300. with test_support.transient_internet("svn.python.org"):
  301. s = ssl.wrap_socket(socket.socket(socket.AF_INET),
  302. cert_reqs=ssl.CERT_REQUIRED,
  303. ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
  304. try:
  305. self.assertEqual(errno.ECONNREFUSED,
  306. s.connect_ex(("svn.python.org", 444)))
  307. finally:
  308. s.close()
  309. @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
  310. def test_makefile_close(self):
  311. # Issue #5238: creating a file-like object with makefile() shouldn't
  312. # delay closing the underlying "real socket" (here tested with its
  313. # file descriptor, hence skipping the test under Windows).
  314. with test_support.transient_internet("svn.python.org"):
  315. ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
  316. ss.connect(("svn.python.org", 443))
  317. fd = ss.fileno()
  318. f = ss.makefile()
  319. f.close()
  320. # The fd is still open
  321. os.read(fd, 0)
  322. # Closing the SSL socket should close the fd too
  323. ss.close()
  324. gc.collect()
  325. with self.assertRaises(OSError) as e:
  326. os.read(fd, 0)
  327. self.assertEqual(e.exception.errno, errno.EBADF)
  328. def test_non_blocking_handshake(self):
  329. with test_support.transient_internet("svn.python.org"):
  330. s = socket.socket(socket.AF_INET)
  331. s.connect(("svn.python.org", 443))
  332. s.setblocking(False)
  333. s = ssl.wrap_socket(s,
  334. cert_reqs=ssl.CERT_NONE,
  335. do_handshake_on_connect=False)
  336. count = 0
  337. while True:
  338. try:
  339. count += 1
  340. s.do_handshake()
  341. break
  342. except ssl.SSLError, err:
  343. if err.args[0] == ssl.SSL_ERROR_WANT_READ:
  344. select.select([s], [], [])
  345. elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
  346. select.select([], [s], [])
  347. else:
  348. raise
  349. s.close()
  350. if test_support.verbose:
  351. sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
  352. def test_get_server_certificate(self):
  353. with test_support.transient_internet("svn.python.org"):
  354. pem = ssl.get_server_certificate(("svn.python.org", 443))
  355. if not pem:
  356. self.fail("No server certificate on svn.python.org:443!")
  357. try:
  358. pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
  359. except ssl.SSLError:
  360. #should fail
  361. pass
  362. else:
  363. self.fail("Got server certificate %s for svn.python.org!" % pem)
  364. pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
  365. if not pem:
  366. self.fail("No server certificate on svn.python.org:443!")
  367. if test_support.verbose:
  368. sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
  369. def test_algorithms(self):
  370. # Issue #8484: all algorithms should be available when verifying a
  371. # certificate.
  372. # SHA256 was added in OpenSSL 0.9.8
  373. if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
  374. self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
  375. self.skipTest("remote host needs SNI, only available on Python 3.2+")
  376. # NOTE: https://sha2.hboeck.de is another possible test host
  377. remote = ("sha256.tbs-internet.com", 443)
  378. sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
  379. with test_support.transient_internet("sha256.tbs-internet.com"):
  380. s = ssl.wrap_socket(socket.socket(socket.AF_INET),
  381. cert_reqs=ssl.CERT_REQUIRED,
  382. ca_certs=sha256_cert,)
  383. try:
  384. s.connect(remote)
  385. if test_support.verbose:
  386. sys.stdout.write("\nCipher with %r is %r\n" %
  387. (remote, s.cipher()))
  388. sys.stdout.write("Certificate is:\n%s\n" %
  389. pprint.pformat(s.getpeercert()))
  390. finally:
  391. s.close()
  392. try:
  393. import threading
  394. except ImportError:
  395. _have_threads = False
  396. else:
  397. _have_threads = True
  398. class ThreadedEchoServer(threading.Thread):
  399. class ConnectionHandler(threading.Thread):
  400. """A mildly complicated class, because we want it to work both
  401. with and without the SSL wrapper around the socket connection, so
  402. that we can test the STARTTLS functionality."""
  403. def __init__(self, server, connsock):
  404. self.server = server
  405. self.running = False
  406. self.sock = connsock
  407. self.sock.setblocking(1)
  408. self.sslconn = None
  409. threading.Thread.__init__(self)
  410. self.daemon = True
  411. def show_conn_details(self):
  412. if self.server.certreqs == ssl.CERT_REQUIRED:
  413. cert = self.sslconn.getpeercert()
  414. if test_support.verbose and self.server.chatty:
  415. sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
  416. cert_binary = self.sslconn.getpeercert(True)
  417. if test_support.verbose and self.server.chatty:
  418. sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
  419. cipher = self.sslconn.cipher()
  420. if test_support.verbose and self.server.chatty:
  421. sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
  422. def wrap_conn(self):
  423. try:
  424. self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
  425. certfile=self.server.certificate,
  426. ssl_version=self.server.protocol,
  427. ca_certs=self.server.cacerts,
  428. cert_reqs=self.server.certreqs,
  429. ciphers=self.server.ciphers)
  430. except ssl.SSLError as e:
  431. # XXX Various errors can have happened here, for example
  432. # a mismatching protocol version, an invalid certificate,
  433. # or a low-level bug. This should be made more discriminating.
  434. self.server.conn_errors.append(e)
  435. if self.server.chatty:
  436. handle_error("\n server: bad connection attempt from " +
  437. str(self.sock.getpeername()) + ":\n")
  438. self.close()
  439. self.running = False
  440. self.server.stop()
  441. return False
  442. else:
  443. return True
  444. def read(self):
  445. if self.sslconn:
  446. return self.sslconn.read()
  447. else:
  448. return self.sock.recv(1024)
  449. def write(self, bytes):
  450. if self.sslconn:
  451. return self.sslconn.write(bytes)
  452. else:
  453. return self.sock.send(bytes)
  454. def close(self):
  455. if self.sslconn:
  456. self.sslconn.close()
  457. else:
  458. self.sock._sock.close()
  459. def run(self):
  460. self.running = True
  461. if not self.server.starttls_server:
  462. if isinstance(self.sock, ssl.SSLSocket):
  463. self.sslconn = self.sock
  464. elif not self.wrap_conn():
  465. return
  466. self.show_conn_details()
  467. while self.running:
  468. try:
  469. msg = self.read()
  470. if not msg:
  471. # eof, so quit this handler
  472. self.running = False
  473. self.close()
  474. elif msg.strip() == 'over':
  475. if test_support.verbose and self.server.connectionchatty:
  476. sys.stdout.write(" server: client closed connection\n")
  477. self.close()
  478. return
  479. elif self.server.starttls_server and msg.strip() == 'STARTTLS':
  480. if test_support.verbose and self.server.connectionchatty:
  481. sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
  482. self.write("OK\n")
  483. if not self.wrap_conn():
  484. return
  485. elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
  486. if test_support.verbose and self.server.connectionchatty:
  487. sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
  488. self.write("OK\n")
  489. self.sslconn.unwrap()
  490. self.sslconn = None
  491. if test_support.verbose and self.server.connectionchatty:
  492. sys.stdout.write(" server: connection is now unencrypted...\n")
  493. else:
  494. if (test_support.verbose and
  495. self.server.connectionchatty):
  496. ctype = (self.sslconn and "encrypted") or "unencrypted"
  497. sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
  498. % (repr(msg), ctype, repr(msg.lower()), ctype))
  499. self.write(msg.lower())
  500. except ssl.SSLError:
  501. if self.server.chatty:
  502. handle_error("Test server failure:\n")
  503. self.close()
  504. self.running = False
  505. # normally, we'd just stop here, but for the test
  506. # harness, we want to stop the server
  507. self.server.stop()
  508. def __init__(self, certificate, ssl_version=None,
  509. certreqs=None, cacerts=None,
  510. chatty=True, connectionchatty=False, starttls_server=False,
  511. wrap_accepting_socket=False, ciphers=None):
  512. if ssl_version is None:
  513. ssl_version = ssl.PROTOCOL_TLSv1
  514. if certreqs is None:
  515. certreqs = ssl.CERT_NONE
  516. self.certificate = certificate
  517. self.protocol = ssl_version
  518. self.certreqs = certreqs
  519. self.cacerts = cacerts
  520. self.ciphers = ciphers
  521. self.chatty = chatty
  522. self.connectionchatty = connectionchatty
  523. self.starttls_server = starttls_server
  524. self.sock = socket.socket()
  525. self.flag = None
  526. if wrap_accepting_socket:
  527. self.sock = ssl.wrap_socket(self.sock, server_side=True,
  528. certfile=self.certificate,
  529. cert_reqs = self.certreqs,
  530. ca_certs = self.cacerts,
  531. ssl_version = self.protocol,
  532. ciphers = self.ciphers)
  533. if test_support.verbose and self.chatty:
  534. sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
  535. self.port = test_support.bind_port(self.sock)
  536. self.active = False
  537. self.conn_errors = []
  538. threading.Thread.__init__(self)
  539. self.daemon = True
  540. def __enter__(self):
  541. self.start(threading.Event())
  542. self.flag.wait()
  543. return self
  544. def __exit__(self, *args):
  545. self.stop()
  546. self.join()
  547. def start(self, flag=None):
  548. self.flag = flag
  549. threading.Thread.start(self)
  550. def run(self):
  551. self.sock.settimeout(0.05)
  552. self.sock.listen(5)
  553. self.active = True
  554. if self.flag:
  555. # signal an event
  556. self.flag.set()
  557. while self.active:
  558. try:
  559. newconn, connaddr = self.sock.accept()
  560. if test_support.verbose and self.chatty:
  561. sys.stdout.write(' server: new connection from '
  562. + str(connaddr) + '\n')
  563. handler = self.ConnectionHandler(self, newconn)
  564. handler.start()
  565. handler.join()
  566. except socket.timeout:
  567. pass
  568. except KeyboardInterrupt:
  569. self.stop()
  570. self.sock.close()
  571. def stop(self):
  572. self.active = False
  573. class AsyncoreEchoServer(threading.Thread):
  574. class EchoServer(asyncore.dispatcher):
  575. class ConnectionHandler(asyncore.dispatcher_with_send):
  576. def __init__(self, conn, certfile):
  577. asyncore.dispatcher_with_send.__init__(self, conn)
  578. self.socket = ssl.wrap_socket(conn, server_side=True,
  579. certfile=certfile,
  580. do_handshake_on_connect=False)
  581. self._ssl_accepting = True
  582. def readable(self):
  583. if isinstance(self.socket, ssl.SSLSocket):
  584. while self.socket.pending() > 0:
  585. self.handle_read_event()
  586. return True
  587. def _do_ssl_handshake(self):
  588. try:
  589. self.socket.do_handshake()
  590. except ssl.SSLError, err:
  591. if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
  592. ssl.SSL_ERROR_WANT_WRITE):
  593. return
  594. elif err.args[0] == ssl.SSL_ERROR_EOF:
  595. return self.handle_close()
  596. raise
  597. except socket.error, err:
  598. if err.args[0] == errno.ECONNABORTED:
  599. return self.handle_close()
  600. else:
  601. self._ssl_accepting = False
  602. def handle_read(self):
  603. if self._ssl_accepting:
  604. self._do_ssl_handshake()
  605. else:
  606. data = self.recv(1024)
  607. if data and data.strip() != 'over':
  608. self.send(data.lower())
  609. def handle_close(self):
  610. self.close()
  611. if test_support.verbose:
  612. sys.stdout.write(" server: closed connection %s\n" % self.socket)
  613. def handle_error(self):
  614. raise
  615. def __init__(self, certfile):
  616. self.certfile = certfile
  617. asyncore.dispatcher.__init__(self)
  618. self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
  619. self.port = test_support.bind_port(self.socket)
  620. self.listen(5)
  621. def handle_accept(self):
  622. sock_obj, addr = self.accept()
  623. if test_support.verbose:
  624. sys.stdout.write(" server: new connection from %s:%s\n" %addr)
  625. self.ConnectionHandler(sock_obj, self.certfile)
  626. def handle_error(self):
  627. raise
  628. def __init__(self, certfile):
  629. self.flag = None
  630. self.active = False
  631. self.server = self.EchoServer(certfile)
  632. self.port = self.server.port
  633. threading.Thread.__init__(self)
  634. self.daemon = True
  635. def __str__(self):
  636. return "<%s %s>" % (self.__class__.__name__, self.server)
  637. def __enter__(self):
  638. self.start(threading.Event())
  639. self.flag.wait()
  640. return self
  641. def __exit__(self, *args):
  642. if test_support.verbose:
  643. sys.stdout.write(" cleanup: stopping server.\n")
  644. self.stop()
  645. if test_support.verbose:
  646. sys.stdout.write(" cleanup: joining server thread.\n")
  647. self.join()
  648. if test_support.verbose:
  649. sys.stdout.write(" cleanup: successfully joined.\n")
  650. def start(self, flag=None):
  651. self.flag = flag
  652. threading.Thread.start(self)
  653. def run(self):
  654. self.active = True
  655. if self.flag:
  656. self.flag.set()
  657. while self.active:
  658. asyncore.loop(0.05)
  659. def stop(self):
  660. self.active = False
  661. self.server.close()
  662. class SocketServerHTTPSServer(threading.Thread):
  663. class HTTPSServer(HTTPServer):
  664. def __init__(self, server_address, RequestHandlerClass, certfile):
  665. HTTPServer.__init__(self, server_address, RequestHandlerClass)
  666. # we assume the certfile contains both private key and certificate
  667. self.certfile = certfile
  668. self.allow_reuse_address = True
  669. def __str__(self):
  670. return ('<%s %s:%s>' %
  671. (self.__class__.__name__,
  672. self.server_name,
  673. self.server_port))
  674. def get_request(self):
  675. # override this to wrap socket with SSL
  676. sock, addr = self.socket.accept()
  677. sslconn = ssl.wrap_socket(sock, server_side=True,
  678. certfile=self.certfile)
  679. return sslconn, addr
  680. class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
  681. # need to override translate_path to get a known root,
  682. # instead of using os.curdir, since the test could be
  683. # run from anywhere
  684. server_version = "TestHTTPS/1.0"
  685. root = None
  686. def translate_path(self, path):
  687. """Translate a /-separated PATH to the local filename syntax.
  688. Components that mean special things to the local file system
  689. (e.g. drive or directory names) are ignored. (XXX They should
  690. probably be diagnosed.)
  691. """
  692. # abandon query parameters
  693. path = urlparse.urlparse(path)[2]
  694. path = os.path.normpath(urllib.unquote(path))
  695. words = path.split('/')
  696. words = filter(None, words)
  697. path = self.root
  698. for word in words:
  699. drive, word = os.path.splitdrive(word)
  700. head, word = os.path.split(word)
  701. if word in self.root: continue
  702. path = os.path.join(path, word)
  703. return path
  704. def log_message(self, format, *args):
  705. # we override this to suppress logging unless "verbose"
  706. if test_support.verbose:
  707. sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
  708. (self.server.server_address,
  709. self.server.server_port,
  710. self.request.cipher(),
  711. self.log_date_time_string(),
  712. format%args))
  713. def __init__(self, certfile):
  714. self.flag = None
  715. self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
  716. self.server = self.HTTPSServer(
  717. (HOST, 0), self.RootedHTTPRequestHandler, certfile)
  718. self.port = self.server.server_port
  719. threading.Thread.__init__(self)
  720. self.daemon = True
  721. def __str__(self):
  722. return "<%s %s>" % (self.__class__.__name__, self.server)
  723. def start(self, flag=None):
  724. self.flag = flag
  725. threading.Thread.start(self)
  726. def run(self):
  727. if self.flag:
  728. self.flag.set()
  729. self.server.serve_forever(0.05)
  730. def stop(self):
  731. self.server.shutdown()
  732. def bad_cert_test(certfile):
  733. """
  734. Launch a server with CERT_REQUIRED, and check that trying to
  735. connect to it with the given client certificate fails.
  736. """
  737. server = ThreadedEchoServer(CERTFILE,
  738. certreqs=ssl.CERT_REQUIRED,
  739. cacerts=CERTFILE, chatty=False)
  740. with server:
  741. try:
  742. s = ssl.wrap_socket(socket.socket(),
  743. certfile=certfile,
  744. ssl_version=ssl.PROTOCOL_TLSv1)
  745. s.connect((HOST, server.port))
  746. except ssl.SSLError, x:
  747. if test_support.verbose:
  748. sys.stdout.write("\nSSLError is %s\n" % x[1])
  749. except socket.error, x:
  750. if test_support.verbose:
  751. sys.stdout.write("\nsocket.error is %s\n" % x[1])
  752. else:
  753. raise AssertionError("Use of invalid cert should have failed!")
  754. def server_params_test(certfile, protocol, certreqs, cacertsfile,
  755. client_certfile, client_protocol=None, indata="FOO\n",
  756. ciphers=None, chatty=True, connectionchatty=False,
  757. wrap_accepting_socket=False):
  758. """
  759. Launch a server, connect a client to it and try various reads
  760. and writes.
  761. """
  762. server = ThreadedEchoServer(certfile,
  763. certreqs=certreqs,
  764. ssl_version=protocol,
  765. cacerts=cacertsfile,
  766. ciphers=ciphers,
  767. chatty=chatty,
  768. connectionchatty=connectionchatty,
  769. wrap_accepting_socket=wrap_accepting_socket)
  770. with server:
  771. # try to connect
  772. if client_protocol is None:
  773. client_protocol = protocol
  774. s = ssl.wrap_socket(socket.socket(),
  775. certfile=client_certfile,
  776. ca_certs=cacertsfile,
  777. ciphers=ciphers,
  778. cert_reqs=certreqs,
  779. ssl_version=client_protocol)
  780. s.connect((HOST, server.port))
  781. for arg in [indata, bytearray(indata), memoryview(indata)]:
  782. if connectionchatty:
  783. if test_support.verbose:
  784. sys.stdout.write(
  785. " client: sending %s...\n" % (repr(arg)))
  786. s.write(arg)
  787. outdata = s.read()
  788. if connectionchatty:
  789. if test_support.verbose:
  790. sys.stdout.write(" client: read %s\n" % repr(outdata))
  791. if outdata != indata.lower():
  792. raise AssertionError(
  793. "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
  794. % (outdata[:min(len(outdata),20)], len(outdata),
  795. indata[:min(len(indata),20)].lower(), len(indata)))
  796. s.write("over\n")
  797. if connectionchatty:
  798. if test_support.verbose:
  799. sys.stdout.write(" client: closing connection.\n")
  800. s.close()
  801. def try_protocol_combo(server_protocol,
  802. client_protocol,
  803. expect_success,
  804. certsreqs=None):
  805. if certsreqs is None:
  806. certsreqs = ssl.CERT_NONE
  807. certtype = {
  808. ssl.CERT_NONE: "CERT_NONE",
  809. ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
  810. ssl.CERT_REQUIRED: "CERT_REQUIRED",
  811. }[certsreqs]
  812. if test_support.verbose:
  813. formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
  814. sys.stdout.write(formatstr %
  815. (ssl.get_protocol_name(client_protocol),
  816. ssl.get_protocol_name(server_protocol),
  817. certtype))
  818. try:
  819. # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
  820. # will send an SSLv3 hello (rather than SSLv2) starting from
  821. # OpenSSL 1.0.0 (see issue #8322).
  822. server_params_test(CERTFILE, server_protocol, certsreqs,
  823. CERTFILE, CERTFILE, client_protocol,
  824. ciphers="ALL", chatty=False)
  825. # Protocol mismatch can result in either an SSLError, or a
  826. # "Connection reset by peer" error.
  827. except ssl.SSLError:
  828. if expect_success:
  829. raise
  830. except socket.error as e:
  831. if expect_success or e.errno != errno.ECONNRESET:
  832. raise
  833. else:
  834. if not expect_success:
  835. raise AssertionError(
  836. "Client protocol %s succeeded with server protocol %s!"
  837. % (ssl.get_protocol_name(client_protocol),
  838. ssl.get_protocol_name(server_protocol)))
  839. class ThreadedTests(unittest.TestCase):
  840. def test_rude_shutdown(self):
  841. """A brutal shutdown of an SSL server should raise an IOError
  842. in the client when attempting handshake.
  843. """
  844. listener_ready = threading.Event()
  845. listener_gone = threading.Event()
  846. s = socket.socket()
  847. port = test_support.bind_port(s, HOST)
  848. # `listener` runs in a thread. It sits in an accept() until
  849. # the main thread connects. Then it rudely closes the socket,
  850. # and sets Event `listener_gone` to let the main thread know
  851. # the socket is gone.
  852. def listener():
  853. s.listen(5)
  854. listener_ready.set()
  855. s.accept()
  856. s.close()
  857. listener_gone.set()
  858. def connector():
  859. listener_ready.wait()
  860. c = socket.socket()
  861. c.connect((HOST, port))
  862. listener_gone.wait()
  863. try:
  864. ssl_sock = ssl.wrap_socket(c)
  865. except IOError:
  866. pass
  867. else:
  868. self.fail('connecting to closed SSL socket should have failed')
  869. t = threading.Thread(target=listener)
  870. t.start()
  871. try:
  872. connector()
  873. finally:
  874. t.join()
  875. @skip_if_broken_ubuntu_ssl
  876. def test_echo(self):
  877. """Basic test of an SSL client connecting to a server"""
  878. if test_support.verbose:
  879. sys.stdout.write("\n")
  880. server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
  881. CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
  882. chatty=True, connectionchatty=True)
  883. def test_getpeercert(self):
  884. if test_support.verbose:
  885. sys.stdout.write("\n")
  886. s2 = socket.socket()
  887. server = ThreadedEchoServer(CERTFILE,
  888. certreqs=ssl.CERT_NONE,
  889. ssl_version=ssl.PROTOCOL_SSLv23,
  890. cacerts=CERTFILE,
  891. chatty=False)
  892. with server:
  893. s = ssl.wrap_socket(socket.socket(),
  894. certfile=CERTFILE,
  895. ca_certs=CERTFILE,
  896. cert_reqs=ssl.CERT_REQUIRED,
  897. ssl_version=ssl.PROTOCOL_SSLv23)
  898. s.connect((HOST, server.port))
  899. cert = s.getpeercert()
  900. self.assertTrue(cert, "Can't get peer certificate.")
  901. cipher = s.cipher()
  902. if test_support.verbose:
  903. sys.stdout.write(pprint.pformat(cert) + '\n')
  904. sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
  905. if 'subject' not in cert:
  906. self.fail("No subject field in certificate: %s." %
  907. pprint.pformat(cert))
  908. if ((('organizationName', 'Python Software Foundation'),)
  909. not in cert['subject']):
  910. self.fail(
  911. "Missing or invalid 'organizationName' field in certificate subject; "
  912. "should be 'Python Software Foundation'.")
  913. s.close()
  914. def test_empty_cert(self):
  915. """Connecting with an empty cert file"""
  916. bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
  917. "nullcert.pem"))
  918. def test_malformed_cert(self):
  919. """Connecting with a badly formatted certificate (syntax error)"""
  920. bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
  921. "badcert.pem"))
  922. def test_nonexisting_cert(self):
  923. """Connecting with a non-existing cert file"""
  924. bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
  925. "wrongcert.pem"))
  926. def test_malformed_key(self):
  927. """Connecting with a badly formatted key (syntax error)"""
  928. bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
  929. "badkey.pem"))
  930. @skip_if_broken_ubuntu_ssl
  931. def test_protocol_sslv2(self):
  932. """Connecting to an SSLv2 server with various client options"""
  933. if test_support.verbose:
  934. sys.stdout.write("\n")
  935. if not hasattr(ssl, 'PROTOCOL_SSLv2'):
  936. self.skipTest("PROTOCOL_SSLv2 needed")
  937. try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
  938. try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
  939. try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
  940. try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
  941. try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
  942. try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
  943. @skip_if_broken_ubuntu_ssl
  944. def test_protocol_sslv23(self):
  945. """Connecting to an SSLv23 server with various client options"""
  946. if test_support.verbose:
  947. sys.stdout.write("\n")
  948. try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
  949. try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
  950. try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
  951. try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
  952. try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
  953. try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
  954. try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
  955. try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
  956. try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
  957. @skip_if_broken_ubuntu_ssl
  958. def test_protocol_sslv3(self):
  959. """Connecting to an SSLv3 server with various client options"""
  960. if test_support.verbose:
  961. sys.stdout.write("\n")
  962. try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
  963. try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
  964. try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
  965. if hasattr(ssl, 'PROTOCOL_SSLv2'):
  966. try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
  967. try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
  968. @skip_if_broken_ubuntu_ssl
  969. def test_protocol_tlsv1(self):
  970. """Connecting to a TLSv1 server with various client options"""
  971. if test_support.verbose:
  972. sys.stdout.write("\n")
  973. try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
  974. try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
  975. try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
  976. if hasattr(ssl, 'PROTOCOL_SSLv2'):
  977. try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
  978. try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
  979. def test_starttls(self):
  980. """Switching from clear text to encrypted and back again."""
  981. msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
  982. server = ThreadedEchoServer(CERTFILE,
  983. ssl_version=ssl.PROTOCOL_TLSv1,
  984. starttls_server=True,
  985. chatty=True,
  986. connectionchatty=True)
  987. wrapped = False
  988. with server:
  989. s = socket.socket()
  990. s.setblocking(1)
  991. s.connect((HOST, server.port))
  992. if test_support.verbose:
  993. sys.stdout.write("\n")
  994. for indata in msgs:
  995. if test_support.verbose:
  996. sys.stdout.write(
  997. " client: sending %s...\n" % repr(indata))
  998. if wrapped:
  999. conn.write(indata)
  1000. outdata = conn.read()
  1001. else:
  1002. s.send(indata)
  1003. outdata = s.recv(1024)
  1004. if (indata == "STARTTLS" and
  1005. outdata.strip().lower().startswith("ok")):
  1006. # STARTTLS ok, switch to secure mode
  1007. if test_support.verbose:
  1008. sys.stdout.write(
  1009. " client: read %s from server, starting TLS...\n"
  1010. % repr(outdata))
  1011. conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
  1012. wrapped = True
  1013. elif (indata == "ENDTLS" and
  1014. outdata.strip().lower().startswith("ok")):
  1015. # ENDTLS ok, switch back to clear text
  1016. if test_support.verbose:
  1017. sys.stdout.write(
  1018. " client: read %s from server, ending TLS...\n"
  1019. % repr(outdata))
  1020. s = conn.unwrap()
  1021. wrapped = False
  1022. else:
  1023. if test_support.verbose:
  1024. sys.stdout.write(
  1025. " client: read %s from server\n" % repr(outdata))
  1026. if test_support.verbose:

Large files files are truncated, but you can click here to view the full file