Commit 00ed793f authored by Jason Madden's avatar Jason Madden

Working on gevent/gevent#546 for CPython only.

Fixes several test failures under 2.7.9, notably test__pywsgi and test__ssl.
There are lots of whitespace differences in the tests due to forking for CPython
<= 2.7.8.

The complete failure list follows.

The ONLY failure in 2.7/test_ssl has this traceback; I'm not sure what the cause is yet:

  ======================================================================
  ERROR: test_protocol_sslv2 (__main__.ThreadedTests)
  ----------------------------------------------------------------------
  Traceback (most recent call last):
    File "test_ssl.py", line 71, in f
      return func(*args, **kwargs)
    File "test_ssl.py", line 1205, in test_protocol_sslv2
      try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
    File "test_ssl.py", line 979, in try_protocol_combo
      chatty=False, connectionchatty=False)
    File "test_ssl.py", line 909, in server_params_test
      s.connect((HOST, server.port))
    File "/gevent/gevent/_sslgte279.py", line 546, in connect
      self._real_connect(addr, False)
    File "/gevent/gevent/_sslgte279.py", line 537, in _real_connect
      self.do_handshake()
    File "/gevent/gevent/_sslgte279.py", line 504, in do_handshake
      return self._sslobj.do_handshake()
  SSLEOFError: EOF occurred in violation of protocol (_ssl.c:581)

  ----------------------------------------------------------------------

3/123 expected failures
 - //bin/python -u -m monkey_test test_ssl.py
 - //bin/python -u test__socket_dns6.py
 - //bin/python -u -m monkey_test --Event test_ssl.py

4/123 unexpected failures
 - //bin/python -u test__all__.py
 - //bin/python -u test_ares_timeout.py
 - //bin/python -u -m monkey_test test_httpservers.py
 - //bin/python -u -m monkey_test --Event test_httpservers.py
parent 34d5a9a2
...@@ -334,10 +334,10 @@ class socket(object): ...@@ -334,10 +334,10 @@ class socket(object):
howlong = f() howlong = f()
if howlong < 0.0: if howlong < 0.0:
raise ValueError('Timeout value out of range') raise ValueError('Timeout value out of range')
self.timeout = howlong self.__dict__['timeout'] = howlong # avoid recursion with any property on self.timeout
def gettimeout(self): def gettimeout(self):
return self.timeout return self.__dict__['timeout'] # avoid recursion with any property on self.timeout
def shutdown(self, how): def shutdown(self, how):
if how == 0: # SHUT_RD if how == 0: # SHUT_RD
...@@ -396,5 +396,11 @@ if hasattr(_socket, 'fromfd'): ...@@ -396,5 +396,11 @@ if hasattr(_socket, 'fromfd'):
else: else:
__implements__.remove('fromfd') __implements__.remove('fromfd')
if hasattr(__socket__, 'ssl'):
def ssl(sock, keyfile=None, certfile=None):
# deprecated in 2.7.9 but still present
from . import _ssl2
return _ssl2.sslwrap_simple(sock, keyfile, certfile)
__implements__.append('ssl')
__all__ = __implements__ + __extensions__ + __imports__ __all__ = __implements__ + __extensions__ + __imports__
...@@ -379,6 +379,17 @@ class SSLSocket(socket): ...@@ -379,6 +379,17 @@ class SSLSocket(socket):
# the file-like object. # the file-like object.
return _fileobject(self, mode, bufsize, close=True) return _fileobject(self, mode, bufsize, close=True)
if PYPY or not hasattr(SSLSocket, 'timeout'):
# PyPy (and certain versions of CPython) doesn't have a direct
# 'timeout' property on raw sockets, because that's not part of
# the documented specification. We may wind up wrapping a raw
# socket (when ssl is used with PyWSGI) or a gevent socket, which
# does have a read/write timeout property as an alias for
# get/settimeout, so make sure that's always the case because
# pywsgi can depend on that.
SSLSocket.timeout = property(lambda self: self.gettimeout(),
lambda self, value: self.settimeout(value))
_SSLErrorReadTimeout = SSLError('The read operation timed out') _SSLErrorReadTimeout = SSLError('The read operation timed out')
_SSLErrorWriteTimeout = SSLError('The write operation timed out') _SSLErrorWriteTimeout = SSLError('The write operation timed out')
......
...@@ -15,7 +15,7 @@ _ssl = __ssl__._ssl ...@@ -15,7 +15,7 @@ _ssl = __ssl__._ssl
import errno import errno
from gevent.socket import socket, timeout_default from gevent.socket import socket, timeout_default
from gevent.socket import error as socket_error from gevent.socket import error as socket_error
from gevent.hub import PYPY
__implements__ = ['SSLContext', __implements__ = ['SSLContext',
'SSLSocket', 'SSLSocket',
...@@ -463,11 +463,31 @@ class SSLSocket(socket): ...@@ -463,11 +463,31 @@ class SSLSocket(socket):
else: else:
self._makefile_refs -= 1 self._makefile_refs -= 1
def _sslobj_shutdown(self):
while True:
try:
return self._sslobj.shutdown()
except SSLError as ex:
if ex.args[0] == SSL_ERROR_EOF and self.suppress_ragged_eofs:
return ''
elif ex.args[0] == SSL_ERROR_WANT_READ:
if self.timeout == 0.0:
raise
sys.exc_clear()
self._wait(self._read_event, timeout_exc=_SSLErrorReadTimeout)
elif ex.args[0] == SSL_ERROR_WANT_WRITE:
if self.timeout == 0.0:
raise
sys.exc_clear()
self._wait(self._write_event, timeout_exc=_SSLErrorWriteTimeout)
else:
raise
def unwrap(self): def unwrap(self):
if self._sslobj: if self._sslobj:
s = self._sslobj.shutdown() s = self._sslobj_shutdown()
self._sslobj = None self._sslobj = None
return s return socket(_sock=s) # match _ssl2; critical to drop/reuse here on PyPy
else: else:
raise ValueError("No SSL wrapper around " + str(self)) raise ValueError("No SSL wrapper around " + str(self))
...@@ -575,6 +595,18 @@ class SSLSocket(socket): ...@@ -575,6 +595,18 @@ class SSLSocket(socket):
return None return None
return self._sslobj.version() return self._sslobj.version()
if PYPY or not hasattr(SSLSocket, 'timeout'):
# PyPy (and certain versions of CPython) doesn't have a direct
# 'timeout' property on raw sockets, because that's not part of
# the documented specification. We may wind up wrapping a raw
# socket (when ssl is used with PyWSGI) or a gevent socket, which
# does have a read/write timeout property as an alias for
# get/settimeout, so make sure that's always the case because
# pywsgi can depend on that.
SSLSocket.timeout = property(lambda self: self.gettimeout(),
lambda self, value: self.settimeout(value))
_SSLErrorReadTimeout = SSLError('The read operation timed out') _SSLErrorReadTimeout = SSLError('The read operation timed out')
_SSLErrorWriteTimeout = SSLError('The write operation timed out') _SSLErrorWriteTimeout = SSLError('The write operation timed out')
......
-----BEGIN RSA PRIVATE KEY----- -----BEGIN PRIVATE KEY-----
MIICXwIBAAKBgQC8ddrhm+LutBvjYcQlnH21PPIseJ1JVG2HMmN2CmZk2YukO+9L MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANtb0+YrKuxevGpm
opdJhTvbGfEj0DQs1IE8M+kTUyOmuKfVrFMKwtVeCJphrAnhoz7TYOuLBSqt7lVH LrjaUhZSgz6zFAmuGFmKmUbdjmfv9zSmmdsQIksK++jK0Be9LeZy20j6ahOfuVa0
fhi/VwovESJlaBOp+WMnfhcduPEYHYx/6cnVapIkZnLt30zu2um+DzA9jQIDAQAB ufEmPoP7Fy4hXegKZR9cCWcIe/A6H2xWF1IIJLRTLaU8ol/I7T+um5HD5AwAwNPP
AoGBAK0FZpaKj6WnJZN0RqhhK+ggtBWwBnc0U/ozgKz2j1s3fsShYeiGtW6CK5nU USNU0Eegmvp+xxWu3NX2m1Veot85AgMBAAECgYA3ZdZ673X0oexFlq7AAmrutkHt
D1dZ5wzhbGThI7LiOXDvRucc9n7vUgi0alqPQ/PFodPxAN/eEYkmXQ7W2k7zwsDA CL7LvwrpOiaBjhyTxTeSNWzvtQBkIU8DOI0bIazA4UreAFffwtvEuPmonDb3F+Iq
IUK0KUhktQbLu8qF/m8qM86ba9y9/9YkXuQbZ3COl5ahTZrhAkEA301P08RKv3KM SMAu42XcGyVZEl+gHlTPU9XRX7nTOXVt+MlRRRxL6t9GkGfUAXI3XxJDXW3c0vBK
oXnGU2UHTuJ1MAD2hOrPxjD4/wxA/39EWG9bZczbJyggB4RHu0I3NOSFjAm3HQm0 UL9xqD8cORXOfE06rQJBAP8mEX1ERkR64Ptsoe4281vjTlNfIbs7NMPkUnrn9N/Y
ANOu5QK9owJBANgOeLfNNcF4pp+UikRFqxk5hULqRAWzVxVrWe85FlPm0VVmHbb/ BLhjNIfQ3HFZG8BTMLfX7kCS9D593DW5tV4Z9BP/c6cCQQDcFzCcVArNh2JSywOQ
loif7mqjU8o1jTd/LM7RD9f2usZyE2psaw8CQQCNLhkpX3KO5kKJmS9N7JMZSc4j ZfTfRbJg/Z5Lt9Fkngv1meeGNPgIMLN8Sg679pAOOWmzdMO3V706rNPzSVMME7E5
oog58yeYO8BBqKKzpug0LXuQultYv2K4veaIO04iL9VLe5z9S/Q1jaCHBBuXAkEA oPIfAkEA8pDddarP5tCvTTgUpmTFbakm0KoTZm2+FzHcnA4jRh+XNTjTOv98Y6Ik
z8gjGoi1AOp6PBBLZNsncCvcV/0aC+1se4HxTNo2+duKSDnbq+ljqOM+E7odU+Nq eO5d1ZnKXseWvkZncQgxfdnMqqpj5wJAcNq/RVne1DbYlwWchT2Si65MYmmJ8t+F
ewvIWOG//e8fssd0mq3HywJBAJ8l/c8GVmrpFTx8r/nZ2Pyyjt3dH1widooDXYSV 0mcsULqjOnEMwf5e+ptq5LzwbyrHZYq5FNk7ocufPv/ZQrcSSC+cFwJBAKvOJByS
q6Gbf41Llo5sYAtmxdndTLASuHKecacTgZVhy0FryZpLKrU= x56qyGeZLOQlWS2JS3KJo59XuLFGqcbgN9Om9xFa41Yb4N9NvplFivsvZdw3m1Q/
-----END RSA PRIVATE KEY----- SPIXQuT8RMPDVNQ=
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
MIICpzCCAhCgAwIBAgIJAP+qStv1cIGNMA0GCSqGSIb3DQEBBQUAMIGJMQswCQYD MIICVDCCAb2gAwIBAgIJANfHOBkZr8JOMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV
VQQGEwJVUzERMA8GA1UECBMIRGVsYXdhcmUxEzARBgNVBAcTCldpbG1pbmd0b24x BAYTAlhZMRcwFQYDVQQHEw5DYXN0bGUgQW50aHJheDEjMCEGA1UEChMaUHl0aG9u
IzAhBgNVBAoTGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0aW9uMQwwCgYDVQQLEwNT IFNvZnR3YXJlIEZvdW5kYXRpb24xEjAQBgNVBAMTCWxvY2FsaG9zdDAeFw0xMDEw
U0wxHzAdBgNVBAMTFnNvbWVtYWNoaW5lLnB5dGhvbi5vcmcwHhcNMDcwODI3MTY1 MDgyMzAxNTZaFw0yMDEwMDUyMzAxNTZaMF8xCzAJBgNVBAYTAlhZMRcwFQYDVQQH
NDUwWhcNMTMwMjE2MTY1NDUwWjCBiTELMAkGA1UEBhMCVVMxETAPBgNVBAgTCERl Ew5DYXN0bGUgQW50aHJheDEjMCEGA1UEChMaUHl0aG9uIFNvZnR3YXJlIEZvdW5k
bGF3YXJlMRMwEQYDVQQHEwpXaWxtaW5ndG9uMSMwIQYDVQQKExpQeXRob24gU29m YXRpb24xEjAQBgNVBAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
dHdhcmUgRm91bmRhdGlvbjEMMAoGA1UECxMDU1NMMR8wHQYDVQQDExZzb21lbWFj gYkCgYEA21vT5isq7F68amYuuNpSFlKDPrMUCa4YWYqZRt2OZ+/3NKaZ2xAiSwr7
aGluZS5weXRob24ub3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8ddrh 6MrQF70t5nLbSPpqE5+5VrS58SY+g/sXLiFd6AplH1wJZwh78DofbFYXUggktFMt
m+LutBvjYcQlnH21PPIseJ1JVG2HMmN2CmZk2YukO+9LopdJhTvbGfEj0DQs1IE8 pTyiX8jtP66bkcPkDADA089RI1TQR6Ca+n7HFa7c1fabVV6i3zkCAwEAAaMYMBYw
M+kTUyOmuKfVrFMKwtVeCJphrAnhoz7TYOuLBSqt7lVHfhi/VwovESJlaBOp+WMn FAYDVR0RBA0wC4IJbG9jYWxob3N0MA0GCSqGSIb3DQEBBQUAA4GBAHPctQBEQ4wd
fhcduPEYHYx/6cnVapIkZnLt30zu2um+DzA9jQIDAQABoxUwEzARBglghkgBhvhC BJ6+JcpIraopLn8BGhbjNWj40mmRqWB/NAWF6M5ne7KpGAu7tLeG4hb1zLaldK8G
AQEEBAMCBkAwDQYJKoZIhvcNAQEFBQADgYEAF4Q5BVqmCOLv1n8je/Jw9K669VXb lxy2GPSRF6LFS48dpEj2HbMv2nvv6xxalDMJ9+DicWgAKTQ6bcX2j3GUkCR0g/T1
08hyGzQhkemEBYQd6fzQ9A/1ZzHkJKb1P6yreOLSEh4KcxYPyrLRC1ll8nr5OlCx CRlNBAAlvhKzO7Clpf9l0YKBEfraJByX
CMhKkTnR6qBsdNV0XtdU2+N25hqW+Ma4ZeqsN/iiJVCGNOZGnvQuvCAGWF8+J/f/
iHkC6gGdBJhogs4=
-----END CERTIFICATE----- -----END CERTIFICATE-----
...@@ -2,41 +2,40 @@ ...@@ -2,41 +2,40 @@
0 s:/C=FR/postalCode=14000/ST=Calvados/L=CAEN/street=22 rue de Bretagne/O=TBS INTERNET/OU=0002 440443810/OU=sha-256 production/CN=sha256.tbs-internet.com 0 s:/C=FR/postalCode=14000/ST=Calvados/L=CAEN/street=22 rue de Bretagne/O=TBS INTERNET/OU=0002 440443810/OU=sha-256 production/CN=sha256.tbs-internet.com
i:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA SGC i:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA SGC
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
MIIGXTCCBUWgAwIBAgIRAMmag+ygSAdxZsbyzYjhuW0wDQYJKoZIhvcNAQELBQAw MIIGXDCCBUSgAwIBAgIRAKpVmHgg9nfCodAVwcP4siwwDQYJKoZIhvcNAQELBQAw
gcQxCzAJBgNVBAYTAkZSMREwDwYDVQQIEwhDYWx2YWRvczENMAsGA1UEBxMEQ2Fl gcQxCzAJBgNVBAYTAkZSMREwDwYDVQQIEwhDYWx2YWRvczENMAsGA1UEBxMEQ2Fl
bjEVMBMGA1UEChMMVEJTIElOVEVSTkVUMUgwRgYDVQQLEz9UZXJtcyBhbmQgQ29u bjEVMBMGA1UEChMMVEJTIElOVEVSTkVUMUgwRgYDVQQLEz9UZXJtcyBhbmQgQ29u
ZGl0aW9uczogaHR0cDovL3d3dy50YnMtaW50ZXJuZXQuY29tL0NBL3JlcG9zaXRv ZGl0aW9uczogaHR0cDovL3d3dy50YnMtaW50ZXJuZXQuY29tL0NBL3JlcG9zaXRv
cnkxGDAWBgNVBAsTD1RCUyBJTlRFUk5FVCBDQTEYMBYGA1UEAxMPVEJTIFg1MDkg cnkxGDAWBgNVBAsTD1RCUyBJTlRFUk5FVCBDQTEYMBYGA1UEAxMPVEJTIFg1MDkg
Q0EgU0dDMB4XDTEwMDIxODAwMDAwMFoXDTEyMDIxOTIzNTk1OVowgcsxCzAJBgNV Q0EgU0dDMB4XDTEyMDEwNDAwMDAwMFoXDTE0MDIxNzIzNTk1OVowgcsxCzAJBgNV
BAYTAkZSMQ4wDAYDVQQREwUxNDAwMDERMA8GA1UECBMIQ2FsdmFkb3MxDTALBgNV BAYTAkZSMQ4wDAYDVQQREwUxNDAwMDERMA8GA1UECBMIQ2FsdmFkb3MxDTALBgNV
BAcTBENBRU4xGzAZBgNVBAkTEjIyIHJ1ZSBkZSBCcmV0YWduZTEVMBMGA1UEChMM BAcTBENBRU4xGzAZBgNVBAkTEjIyIHJ1ZSBkZSBCcmV0YWduZTEVMBMGA1UEChMM
VEJTIElOVEVSTkVUMRcwFQYDVQQLEw4wMDAyIDQ0MDQ0MzgxMDEbMBkGA1UECxMS VEJTIElOVEVSTkVUMRcwFQYDVQQLEw4wMDAyIDQ0MDQ0MzgxMDEbMBkGA1UECxMS
c2hhLTI1NiBwcm9kdWN0aW9uMSAwHgYDVQQDExdzaGEyNTYudGJzLWludGVybmV0 c2hhLTI1NiBwcm9kdWN0aW9uMSAwHgYDVQQDExdzaGEyNTYudGJzLWludGVybmV0
LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbuM8VT7f0nntwu LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKQIX/zdJcyxty0m
N3F7v9KIBlhKNAxqCrziOXU5iqUt8HrQB3DtHbdmII+CpVUlwlmepsx6G+srEZ9a PM1XQSoSSifueS3AVcgqMsaIKS/u+rYzsv4hQ/qA6vLn5m5/ewUcZDj7zdi6rBVf
MIGAy0nxi5aLb7watkyIdPjJTMvTUBQ/+RPWzt5JtYbbY9BlJ+yci0dctP74f4NU PaVNXJ6YinLX0tkaW8TEjeVuZG5yksGZlhCt1CJ1Ho9XLiLaP4uJ7MCoNUntpJ+E
ISLtlrEjUbf2gTohLrcE01TfmOF6PDEbB5PKDi38cB3NzKfizWfrOaJW6Q1C1qOJ LfrOdgsIj91kPmwjDJeztVcQCvKzhjVJA/KxdInc0JvOATn7rpaSmQI5bvIjufgo
y4/4jkUREX1UFUIxzx7v62VfjXSGlcjGpBX1fvtABQOSLeE0a6gciDZs1REqroFf qVsTPwVFzuUYULXBk7KxRT7MiEqnd5HvviNh0285QC478zl3v0I0Fb5El4yD3p49
5eXtqYphpTa14Z83ITXMfgg5Nze1VtMnzI9Qx4blYBw4dgQVEuIsYr7FDBOITDzc IthcRnxzMKc0UhU5ogi0SbONyBfm/mzONVfSxpM+MlyvZmJqrbuuLoEDzJD+t8PU
VEVXZx0CAwEAAaOCAj8wggI7MB8GA1UdIwQYMBaAFAdEdoWTKLx/bXjSCuv6TEvf xSuzgbcCAwEAAaOCAj4wggI6MB8GA1UdIwQYMBaAFAdEdoWTKLx/bXjSCuv6TEvf
2YIfMB0GA1UdDgQWBBSJKI/AYVI9RQNY0QPIqc8ej2QivTAOBgNVHQ8BAf8EBAMC 2YIfMB0GA1UdDgQWBBT/qTGYdaj+f61c2IRFL/B1eEsM8DAOBgNVHQ8BAf8EBAMC
BaAwDAYDVR0TAQH/BAIwADA0BgNVHSUELTArBggrBgEFBQcDAQYIKwYBBQUHAwIG BaAwDAYDVR0TAQH/BAIwADA0BgNVHSUELTArBggrBgEFBQcDAQYIKwYBBQUHAwIG
CisGAQQBgjcKAwMGCWCGSAGG+EIEATBMBgNVHSAERTBDMEEGCysGAQQBgOU3AgQB CisGAQQBgjcKAwMGCWCGSAGG+EIEATBLBgNVHSAERDBCMEAGCisGAQQB5TcCBAEw
MDIwMAYIKwYBBQUHAgEWJGh0dHBzOi8vd3d3LnRicy1pbnRlcm5ldC5jb20vQ0Ev MjAwBggrBgEFBQcCARYkaHR0cHM6Ly93d3cudGJzLWludGVybmV0LmNvbS9DQS9D
Q1BTNDBtBgNVHR8EZjBkMDKgMKAuhixodHRwOi8vY3JsLnRicy1pbnRlcm5ldC5j UFM0MG0GA1UdHwRmMGQwMqAwoC6GLGh0dHA6Ly9jcmwudGJzLWludGVybmV0LmNv
b20vVEJTWDUwOUNBU0dDLmNybDAuoCygKoYoaHR0cDovL2NybC50YnMteDUwOS5j bS9UQlNYNTA5Q0FTR0MuY3JsMC6gLKAqhihodHRwOi8vY3JsLnRicy14NTA5LmNv
b20vVEJTWDUwOUNBU0dDLmNybDCBpgYIKwYBBQUHAQEEgZkwgZYwOAYIKwYBBQUH bS9UQlNYNTA5Q0FTR0MuY3JsMIGmBggrBgEFBQcBAQSBmTCBljA4BggrBgEFBQcw
MAKGLGh0dHA6Ly9jcnQudGJzLWludGVybmV0LmNvbS9UQlNYNTA5Q0FTR0MuY3J0 AoYsaHR0cDovL2NydC50YnMtaW50ZXJuZXQuY29tL1RCU1g1MDlDQVNHQy5jcnQw
MDQGCCsGAQUFBzAChihodHRwOi8vY3J0LnRicy14NTA5LmNvbS9UQlNYNTA5Q0FT NAYIKwYBBQUHMAKGKGh0dHA6Ly9jcnQudGJzLXg1MDkuY29tL1RCU1g1MDlDQVNH
R0MuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC50YnMteDUwOS5jb20wPwYD Qy5jcnQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLnRicy14NTA5LmNvbTA/BgNV
VR0RBDgwNoIXc2hhMjU2LnRicy1pbnRlcm5ldC5jb22CG3d3dy5zaGEyNTYudGJz HREEODA2ghdzaGEyNTYudGJzLWludGVybmV0LmNvbYIbd3d3LnNoYTI1Ni50YnMt
LWludGVybmV0LmNvbTANBgkqhkiG9w0BAQsFAAOCAQEAA5NL0D4QSqhErhlkdPmz aW50ZXJuZXQuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQA0pOuL8QvAa5yksTbGShzX
XtiMvdGL+ZehM4coTRIpasM/Agt36Rc0NzCvnQwKE+wkngg1Gy2qe7Q0E/ziqBtB ABApagunUGoEydv4YJT1MXy9tTp7DrWaozZSlsqBxrYAXP1d9r2fuKbEniYHxaQ0
fZYzdVgu1zdiL4kTaf+wFKYAFGsFbyeEmXysy+CMwaNoF2vpSjCU1UD56bEnTX/W UYaf1VSIlDo1yuC8wE7wxbHDIpQ/E5KAyxiaJ8obtDhFstWAPAH+UoGXq0kj2teN
fxVZYxtBQUpnu2wOsm8cDZuZRv9XrYgAhGj9Tt6F0aVHSDGn59uwShG1+BVF/uju 21sFQ5dXgA95nldvVFsFhrRUNB6xXAcaj0VZFhttI0ZfQZmQwEI/P+N9Jr40OGun
SCyPTTjL1oc7YElJUzR/x4mQJYvtQI8gDIDAGEOs7v3R/gKa5EMfbUQUI4C84UbI aa+Dn0TMeUH4U20YntfLbu2nDcJcYfyurm+8/0Tr4HznLnedXu9pCPYj0TaddrgT
Yz09Jdnws/MkC/Hm1BZEqk89u7Hvfv+oHqEb0XaUo0TDfsxE0M1sMdnLb91QNQBm XO0oFiyy7qGaY6+qKh71yD64Y3ycCJ/HR9Wm39mjZYc9ezYwT4noP6r7Lk8YO7/q
UQ==
-----END CERTIFICATE----- -----END CERTIFICATE-----
1 s:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA SGC 1 s:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA SGC
i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
......
...@@ -16,12 +16,18 @@ import traceback ...@@ -16,12 +16,18 @@ import traceback
import weakref import weakref
import functools import functools
import platform import platform
from contextlib import closing
from BaseHTTPServer import HTTPServer from BaseHTTPServer import HTTPServer
from SimpleHTTPServer import SimpleHTTPRequestHandler from SimpleHTTPServer import SimpleHTTPRequestHandler
ssl = test_support.import_module("ssl") ssl = test_support.import_module("ssl")
try:
PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
except AttributeError:
PROTOCOLS = ()
HOST = test_support.HOST HOST = test_support.HOST
CERTFILE = None CERTFILE = None
SVN_PYTHON_ORG_ROOT_CERT = None SVN_PYTHON_ORG_ROOT_CERT = None
...@@ -54,6 +60,17 @@ class BasicTests(unittest.TestCase): ...@@ -54,6 +60,17 @@ class BasicTests(unittest.TestCase):
# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2 # Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
def skip_if_broken_ubuntu_ssl(func): def skip_if_broken_ubuntu_ssl(func):
if hasattr(ssl, 'PROTOCOL_SSLv2'): if hasattr(ssl, 'PROTOCOL_SSLv2'):
if hasattr(ssl, 'SSLContext'): # >= 2.7.9
def f(*args, **kwargs):
try:
ssl.SSLContext(ssl.PROTOCOL_SSLv2)
except ssl.SSLError:
if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
return func(*args, **kwargs)
return f
# We need to access the lower-level wrapper in order to create an # We need to access the lower-level wrapper in order to create an
# implicit SSL context without trying to connect or listen. # implicit SSL context without trying to connect or listen.
try: try:
...@@ -61,6 +78,7 @@ def skip_if_broken_ubuntu_ssl(func): ...@@ -61,6 +78,7 @@ def skip_if_broken_ubuntu_ssl(func):
except ImportError: except ImportError:
# The returned function won't get executed, just ignore the error # The returned function won't get executed, just ignore the error
pass pass
@functools.wraps(func) @functools.wraps(func)
def f(*args, **kwargs): def f(*args, **kwargs):
try: try:
...@@ -107,17 +125,19 @@ class BasicSocketTests(unittest.TestCase): ...@@ -107,17 +125,19 @@ class BasicSocketTests(unittest.TestCase):
# note that this uses an 'unofficial' function in _ssl.c, # note that this uses an 'unofficial' function in _ssl.c,
# provided solely for this test, to exercise the certificate # provided solely for this test, to exercise the certificate
# parsing code # parsing code
p = ssl._ssl._test_decode_cert(CERTFILE, False) try:
p = ssl._ssl._test_decode_cert(CERTFILE, False)
except TypeError: # >= 2.7.9
p = ssl._ssl._test_decode_cert(CERTFILE)
if test_support.verbose: if test_support.verbose:
sys.stdout.write("\n" + pprint.pformat(p) + "\n") sys.stdout.write("\n" + pprint.pformat(p) + "\n")
self.assertEqual(p['subject'], self.assertEqual(p['subject'],
((('countryName', u'US'),), ((('countryName', 'XY'),),
(('stateOrProvinceName', u'Delaware'),), (('localityName', 'Castle Anthrax'),),
(('localityName', u'Wilmington'),), (('organizationName', 'Python Software Foundation'),),
(('organizationName', u'Python Software Foundation'),), (('commonName', 'localhost'),))
(('organizationalUnitName', u'SSL'),),
(('commonName', u'somemachine.python.org'),)),
) )
self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
# Issue #13034: the subjectAltName in some certificates # Issue #13034: the subjectAltName in some certificates
# (notably projects.developer.nokia.com:443) wasn't parsed # (notably projects.developer.nokia.com:443) wasn't parsed
p = ssl._ssl._test_decode_cert(NOKIACERT) p = ssl._ssl._test_decode_cert(NOKIACERT)
...@@ -178,11 +198,10 @@ class BasicSocketTests(unittest.TestCase): ...@@ -178,11 +198,10 @@ class BasicSocketTests(unittest.TestCase):
s = ssl.wrap_socket(socket.socket(socket.AF_INET), s = ssl.wrap_socket(socket.socket(socket.AF_INET),
cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
s.connect(remote) s.connect(remote)
# Error checking occurs when connecting, because the SSL context # Error checking can happen at instantiation (>=2.7.9) or when connecting
# isn't created before.
s = ssl.wrap_socket(socket.socket(socket.AF_INET),
cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"): with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
s = ssl.wrap_socket(socket.socket(socket.AF_INET),
cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
s.connect(remote) s.connect(remote)
@test_support.cpython_only @test_support.cpython_only
...@@ -358,10 +377,18 @@ class NetworkedTests(unittest.TestCase): ...@@ -358,10 +377,18 @@ class NetworkedTests(unittest.TestCase):
# NOTE: https://sha256.tbs-internet.com is another possible test host # NOTE: https://sha256.tbs-internet.com is another possible test host
remote = ("sha256.tbs-internet.com", 443) remote = ("sha256.tbs-internet.com", 443)
sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem") sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
with test_support.transient_internet("sha256.tbs-internet.com"): with test_support.transient_internet("sha256.tbs-internet.com"):
s = ssl.wrap_socket(socket.socket(socket.AF_INET), if not hasattr(ssl, 'SSLContext') or not getattr(ssl, 'HAS_SNI', True): # <= 2.7.9
cert_reqs=ssl.CERT_REQUIRED, s = ssl.wrap_socket(socket.socket(socket.AF_INET),
ca_certs=sha256_cert,) cert_reqs=ssl.CERT_REQUIRED,
ca_certs=sha256_cert,)
else:
ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
ctx.verify_mode = ssl.CERT_REQUIRED
ctx.load_verify_locations(sha256_cert)
s = ctx.wrap_socket(socket.socket(socket.AF_INET),
server_hostname="sha256.tbs-internet.com")
try: try:
s.connect(remote) s.connect(remote)
if test_support.verbose: if test_support.verbose:
...@@ -409,28 +436,66 @@ else: ...@@ -409,28 +436,66 @@ else:
if test_support.verbose and self.server.chatty: if test_support.verbose and self.server.chatty:
sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n") sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
def wrap_conn(self): if hasattr(ssl, 'SSLContext'): # >= 2.7.9
try: def wrap_conn(self):
self.sslconn = ssl.wrap_socket(self.sock, server_side=True, try:
certfile=self.server.certificate, self.sslconn = self.server.context.wrap_socket(
ssl_version=self.server.protocol, self.sock, server_side=True)
ca_certs=self.server.cacerts, self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
cert_reqs=self.server.certreqs, except socket.error as e:
ciphers=self.server.ciphers) # We treat ConnectionResetError as though it were an
except ssl.SSLError as e: # SSLError - OpenSSL on Ubuntu abruptly closes the
# XXX Various errors can have happened here, for example # connection when asked to use an unsupported protocol.
# a mismatching protocol version, an invalid certificate, #
# or a low-level bug. This should be made more discriminating. # XXX Various errors can have happened here, for example
self.server.conn_errors.append(e) # a mismatching protocol version, an invalid certificate,
if self.server.chatty: # or a low-level bug. This should be made more discriminating.
handle_error("\n server: bad connection attempt from " + if not isinstance(e, ssl.SSLError) and e.errno != errno.ECONNRESET:
str(self.sock.getpeername()) + ":\n") raise
self.close() self.server.conn_errors.append(e)
self.running = False if self.server.chatty:
self.server.stop() handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
return False self.running = False
else: self.server.stop()
return True self.close()
return False
else:
if self.server.context.verify_mode == ssl.CERT_REQUIRED:
cert = self.sslconn.getpeercert()
if support.verbose and self.server.chatty:
sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
cert_binary = self.sslconn.getpeercert(True)
if support.verbose and self.server.chatty:
sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
cipher = self.sslconn.cipher()
if support.verbose and self.server.chatty:
sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
sys.stdout.write(" server: selected protocol is now "
+ str(self.sslconn.selected_npn_protocol()) + "\n")
return True
else:
def wrap_conn(self):
try:
self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
certfile=self.server.certificate,
ssl_version=self.server.protocol,
ca_certs=self.server.cacerts,
cert_reqs=self.server.certreqs,
ciphers=self.server.ciphers)
except ssl.SSLError as e:
# XXX Various errors can have happened here, for example
# a mismatching protocol version, an invalid certificate,
# or a low-level bug. This should be made more discriminating.
self.server.conn_errors.append(e)
if self.server.chatty:
handle_error("\n server: bad connection attempt from " +
str(self.sock.getpeername()) + ":\n")
self.close()
self.running = False
self.server.stop()
return False
else:
return True
def read(self): def read(self):
if self.sslconn: if self.sslconn:
...@@ -457,7 +522,7 @@ else: ...@@ -457,7 +522,7 @@ else:
self.sslconn = self.sock self.sslconn = self.sock
elif not self.wrap_conn(): elif not self.wrap_conn():
return return
self.show_conn_details()
while self.running: while self.running:
try: try:
msg = self.read() msg = self.read()
...@@ -500,39 +565,72 @@ else: ...@@ -500,39 +565,72 @@ else:
# harness, we want to stop the server # harness, we want to stop the server
self.server.stop() self.server.stop()
def __init__(self, certificate, ssl_version=None, if hasattr(ssl, 'SSLContext'): # >= 2.7.9
certreqs=None, cacerts=None, def __init__(self, certificate=None, ssl_version=None,
chatty=True, connectionchatty=False, starttls_server=False, certreqs=None, cacerts=None,
wrap_accepting_socket=False, ciphers=None): chatty=True, connectionchatty=False, starttls_server=False,
npn_protocols=None, ciphers=None, context=None):
if ssl_version is None: if context:
ssl_version = ssl.PROTOCOL_TLSv1 self.context = context
if certreqs is None: else:
certreqs = ssl.CERT_NONE self.context = ssl.SSLContext(ssl_version
self.certificate = certificate if ssl_version is not None
self.protocol = ssl_version else ssl.PROTOCOL_TLSv1)
self.certreqs = certreqs self.context.verify_mode = (certreqs if certreqs is not None
self.cacerts = cacerts else ssl.CERT_NONE)
self.ciphers = ciphers if cacerts:
self.chatty = chatty self.context.load_verify_locations(cacerts)
self.connectionchatty = connectionchatty if certificate:
self.starttls_server = starttls_server self.context.load_cert_chain(certificate)
self.sock = socket.socket() if npn_protocols:
self.flag = None self.context.set_npn_protocols(npn_protocols)
if wrap_accepting_socket: if ciphers:
self.sock = ssl.wrap_socket(self.sock, server_side=True, self.context.set_ciphers(ciphers)
certfile=self.certificate, self.chatty = chatty
cert_reqs = self.certreqs, self.connectionchatty = connectionchatty
ca_certs = self.cacerts, self.starttls_server = starttls_server
ssl_version = self.protocol, self.sock = socket.socket()
ciphers = self.ciphers) self.port = support.bind_port(self.sock)
if test_support.verbose and self.chatty: self.flag = None
sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock)) self.active = False
self.port = test_support.bind_port(self.sock) self.selected_protocols = []
self.active = False self.conn_errors = []
self.conn_errors = [] threading.Thread.__init__(self)
threading.Thread.__init__(self) self.daemon = True
self.daemon = True else:
def __init__(self, certificate, ssl_version=None,
certreqs=None, cacerts=None,
chatty=True, connectionchatty=False, starttls_server=False,
wrap_accepting_socket=False, ciphers=None):
if ssl_version is None:
ssl_version = ssl.PROTOCOL_TLSv1
if certreqs is None:
certreqs = ssl.CERT_NONE
self.certificate = certificate
self.protocol = ssl_version
self.certreqs = certreqs
self.cacerts = cacerts
self.ciphers = ciphers
self.chatty = chatty
self.connectionchatty = connectionchatty
self.starttls_server = starttls_server
self.sock = socket.socket()
self.flag = None
if wrap_accepting_socket:
self.sock = ssl.wrap_socket(self.sock, server_side=True,
certfile=self.certificate,
cert_reqs = self.certreqs,
ca_certs = self.cacerts,
ssl_version = self.protocol,
ciphers = self.ciphers)
if test_support.verbose and self.chatty:
sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
self.port = test_support.bind_port(self.sock)
self.active = False
self.conn_errors = []
threading.Thread.__init__(self)
self.daemon = True
def __enter__(self): def __enter__(self):
self.start(threading.Event()) self.start(threading.Event())
...@@ -794,92 +892,197 @@ else: ...@@ -794,92 +892,197 @@ else:
else: else:
raise AssertionError("Use of invalid cert should have failed!") raise AssertionError("Use of invalid cert should have failed!")
def server_params_test(certfile, protocol, certreqs, cacertsfile, if hasattr(ssl, 'SSLContext'): # >= 2.7.9
client_certfile, client_protocol=None, indata="FOO\n", def server_params_test(client_context, server_context, indata=b"FOO\n",
ciphers=None, chatty=True, connectionchatty=False, chatty=True, connectionchatty=False, sni_name=None):
wrap_accepting_socket=False): """
""" Launch a server, connect a client to it and try various reads
Launch a server, connect a client to it and try various reads and writes.
and writes. """
""" stats = {}
server = ThreadedEchoServer(certfile, server = ThreadedEchoServer(context=server_context,
certreqs=certreqs, chatty=chatty,
ssl_version=protocol, connectionchatty=False)
cacerts=cacertsfile, with server:
with closing(client_context.wrap_socket(socket.socket(),
server_hostname=sni_name)) as s:
s.connect((HOST, server.port))
for arg in [indata, bytearray(indata), memoryview(indata)]:
if connectionchatty:
if support.verbose:
sys.stdout.write(
" client: sending %r...\n" % indata)
s.write(arg)
outdata = s.read()
if connectionchatty:
if support.verbose:
sys.stdout.write(" client: read %r\n" % outdata)
if outdata != indata.lower():
raise AssertionError(
"bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
% (outdata[:20], len(outdata),
indata[:20].lower(), len(indata)))
s.write(b"over\n")
if connectionchatty:
if support.verbose:
sys.stdout.write(" client: closing connection.\n")
stats.update({
'compression': s.compression(),
'cipher': s.cipher(),
'peercert': s.getpeercert(),
'client_npn_protocol': s.selected_npn_protocol(),
'version': s.version(),
})
s.close()
stats['server_npn_protocols'] = server.selected_protocols
return stats
def try_protocol_combo(server_protocol, client_protocol, expect_success,
certsreqs=None, server_options=0, client_options=0):
"""
Try to SSL-connect using *client_protocol* to *server_protocol*.
If *expect_success* is true, assert that the connection succeeds,
if it's false, assert that the connection fails.
Also, if *expect_success* is a string, assert that it is the protocol
version actually used by the connection.
"""
if certsreqs is None:
certsreqs = ssl.CERT_NONE
certtype = {
ssl.CERT_NONE: "CERT_NONE",
ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
ssl.CERT_REQUIRED: "CERT_REQUIRED",
}[certsreqs]
if support.verbose:
formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
sys.stdout.write(formatstr %
(ssl.get_protocol_name(client_protocol),
ssl.get_protocol_name(server_protocol),
certtype))
client_context = ssl.SSLContext(client_protocol)
client_context.options |= client_options
server_context = ssl.SSLContext(server_protocol)
server_context.options |= server_options
# NOTE: we must enable "ALL" ciphers on the client, otherwise an
# SSLv23 client will send an SSLv3 hello (rather than SSLv2)
# starting from OpenSSL 1.0.0 (see issue #8322).
if client_context.protocol == ssl.PROTOCOL_SSLv23:
client_context.set_ciphers("ALL")
for ctx in (client_context, server_context):
ctx.verify_mode = certsreqs
ctx.load_cert_chain(CERTFILE)
ctx.load_verify_locations(CERTFILE)
try:
stats = server_params_test(client_context, server_context,
chatty=False, connectionchatty=False)
# Protocol mismatch can result in either an SSLError, or a
# "Connection reset by peer" error.
except ssl.SSLError:
if expect_success:
raise
except socket.error as e:
if expect_success or e.errno != errno.ECONNRESET:
raise
else:
if not expect_success:
raise AssertionError(
"Client protocol %s succeeded with server protocol %s!"
% (ssl.get_protocol_name(client_protocol),
ssl.get_protocol_name(server_protocol)))
elif (expect_success is not True
and expect_success != stats['version']):
raise AssertionError("version mismatch: expected %r, got %r"
% (expect_success, stats['version']))
else:
def server_params_test(certfile, protocol, certreqs, cacertsfile,
client_certfile, client_protocol=None, indata="FOO\n",
ciphers=None, chatty=True, connectionchatty=False,
wrap_accepting_socket=False):
"""
Launch a server, connect a client to it and try various reads
and writes.
"""
server = ThreadedEchoServer(certfile,
certreqs=certreqs,
ssl_version=protocol,
cacerts=cacertsfile,
ciphers=ciphers,
chatty=chatty,
connectionchatty=connectionchatty,
wrap_accepting_socket=wrap_accepting_socket)
with server:
# try to connect
if client_protocol is None:
client_protocol = protocol
s = ssl.wrap_socket(socket.socket(),
certfile=client_certfile,
ca_certs=cacertsfile,
ciphers=ciphers, ciphers=ciphers,
chatty=chatty, cert_reqs=certreqs,
connectionchatty=connectionchatty, ssl_version=client_protocol)
wrap_accepting_socket=wrap_accepting_socket) s.connect((HOST, server.port))
with server: for arg in [indata, bytearray(indata), memoryview(indata)]:
# try to connect if connectionchatty:
if client_protocol is None: if test_support.verbose:
client_protocol = protocol sys.stdout.write(
s = ssl.wrap_socket(socket.socket(), " client: sending %s...\n" % (repr(arg)))
certfile=client_certfile, s.write(arg)
ca_certs=cacertsfile, outdata = s.read()
ciphers=ciphers, if connectionchatty:
cert_reqs=certreqs, if test_support.verbose:
ssl_version=client_protocol) sys.stdout.write(" client: read %s\n" % repr(outdata))
s.connect((HOST, server.port)) if outdata != indata.lower():
for arg in [indata, bytearray(indata), memoryview(indata)]: raise AssertionError(
if connectionchatty: "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
if test_support.verbose: % (outdata[:min(len(outdata),20)], len(outdata),
sys.stdout.write( indata[:min(len(indata),20)].lower(), len(indata)))
" client: sending %s...\n" % (repr(arg))) s.write("over\n")
s.write(arg)
outdata = s.read()
if connectionchatty: if connectionchatty:
if test_support.verbose: if test_support.verbose:
sys.stdout.write(" client: read %s\n" % repr(outdata)) sys.stdout.write(" client: closing connection.\n")
if outdata != indata.lower(): s.close()
raise AssertionError(
"bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
% (outdata[:min(len(outdata),20)], len(outdata),
indata[:min(len(indata),20)].lower(), len(indata)))
s.write("over\n")
if connectionchatty:
if test_support.verbose:
sys.stdout.write(" client: closing connection.\n")
s.close()
def try_protocol_combo(server_protocol, def try_protocol_combo(server_protocol,
client_protocol, client_protocol,
expect_success, expect_success,
certsreqs=None): certsreqs=None):
if certsreqs is None: if certsreqs is None:
certsreqs = ssl.CERT_NONE certsreqs = ssl.CERT_NONE
certtype = { certtype = {
ssl.CERT_NONE: "CERT_NONE", ssl.CERT_NONE: "CERT_NONE",
ssl.CERT_OPTIONAL: "CERT_OPTIONAL", ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
ssl.CERT_REQUIRED: "CERT_REQUIRED", ssl.CERT_REQUIRED: "CERT_REQUIRED",
}[certsreqs] }[certsreqs]
if test_support.verbose: if test_support.verbose:
formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n" formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
sys.stdout.write(formatstr % sys.stdout.write(formatstr %
(ssl.get_protocol_name(client_protocol), (ssl.get_protocol_name(client_protocol),
ssl.get_protocol_name(server_protocol), ssl.get_protocol_name(server_protocol),
certtype)) certtype))
try: try:
# NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
# will send an SSLv3 hello (rather than SSLv2) starting from # will send an SSLv3 hello (rather than SSLv2) starting from
# OpenSSL 1.0.0 (see issue #8322). # OpenSSL 1.0.0 (see issue #8322).
server_params_test(CERTFILE, server_protocol, certsreqs, server_params_test(CERTFILE, server_protocol, certsreqs,
CERTFILE, CERTFILE, client_protocol, CERTFILE, CERTFILE, client_protocol,
ciphers="ALL", chatty=False) ciphers="ALL", chatty=False)
# Protocol mismatch can result in either an SSLError, or a # Protocol mismatch can result in either an SSLError, or a
# "Connection reset by peer" error. # "Connection reset by peer" error.
except ssl.SSLError: except ssl.SSLError:
if expect_success: if expect_success:
raise raise
except socket.error as e: except socket.error as e:
if expect_success or e.errno != errno.ECONNRESET: if expect_success or e.errno != errno.ECONNRESET:
raise raise
else: else:
if not expect_success: if not expect_success:
raise AssertionError( raise AssertionError(
"Client protocol %s succeeded with server protocol %s!" "Client protocol %s succeeded with server protocol %s!"
% (ssl.get_protocol_name(client_protocol), % (ssl.get_protocol_name(client_protocol),
ssl.get_protocol_name(server_protocol))) ssl.get_protocol_name(server_protocol)))
class ThreadedTests(unittest.TestCase): class ThreadedTests(unittest.TestCase):
...@@ -929,9 +1132,16 @@ else: ...@@ -929,9 +1132,16 @@ else:
"""Basic test of an SSL client connecting to a server""" """Basic test of an SSL client connecting to a server"""
if test_support.verbose: if test_support.verbose:
sys.stdout.write("\n") sys.stdout.write("\n")
server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE, if hasattr(ssl, 'SSLContext'): # >= 2.7.9
CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1, for protocol in PROTOCOLS:
chatty=True, connectionchatty=True) context = ssl.SSLContext(protocol)
context.load_cert_chain(CERTFILE)
server_params_test(context, context,
chatty=True, connectionchatty=True)
else:
server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
chatty=True, connectionchatty=True)
def test_getpeercert(self): def test_getpeercert(self):
if test_support.verbose: if test_support.verbose:
...@@ -1111,7 +1321,14 @@ else: ...@@ -1111,7 +1321,14 @@ else:
url = 'https://127.0.0.1:%d/%s' % ( url = 'https://127.0.0.1:%d/%s' % (
server.port, os.path.split(CERTFILE)[1]) server.port, os.path.split(CERTFILE)[1])
with test_support.check_py3k_warnings(): with test_support.check_py3k_warnings():
f = urllib.urlopen(url) import ssl
if hasattr(ssl, '_create_unverified_context'):
# Disable verification for our self-signed cert
# on Python >= 2.7.9 and 3.4
ssl_ctx = ssl._create_unverified_context()
f = urllib.urlopen(url, context=ssl_ctx)
else:
f = urllib.urlopen(url)
dlen = f.info().getheader("content-length") dlen = f.info().getheader("content-length")
if dlen and (int(dlen) > 0): if dlen and (int(dlen) > 0):
d2 = f.read(int(dlen)) d2 = f.read(int(dlen))
...@@ -1125,6 +1342,7 @@ else: ...@@ -1125,6 +1342,7 @@ else:
server.stop() server.stop()
server.join() server.join()
@unittest.skipIf(hasattr(ssl, 'SSLContext'), "<= 2.7.9 only")
def test_wrapped_accept(self): def test_wrapped_accept(self):
"""Check the accept() method on SSL sockets.""" """Check the accept() method on SSL sockets."""
if test_support.verbose: if test_support.verbose:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment