PageRenderTime 59ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/dj14_py27/mac/lib/python2.7/test/test_ssl.py

https://bitbucket.org/kenial/portable-django
Python | 1370 lines | 1205 code | 91 blank | 74 comment | 179 complexity | d6755c6c8d9def10f9e1318bf9a86a9b MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-3.0

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

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