├── .gitignore ├── .travis.yml ├── MANIFEST.in ├── Makefile ├── README.rst ├── setup.py ├── ssl ├── 2.3.6 │ └── socketmodule.h ├── 2.5.1 │ └── socketmodule.h ├── __init__.py └── _ssl2.c └── test ├── badcert.pem ├── badkey.pem ├── keycert.pem ├── nullcert.pem ├── root.crt └── test_ssl.py /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | *.egg-info 3 | *.so -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - 2.5 4 | before_install: 5 | - pip uninstall -y sslfix 6 | - pip uninstall -y ssl # just to be sure 7 | install: 8 | - pip install . 9 | script: python test/test_ssl.py 10 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include Makefile README.rst 2 | recursive-include test * 3 | recursive-include ssl *.c *.h 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: build 2 | 3 | build: ssl 4 | python setup.py build 5 | 6 | install: 7 | python setup.py install 8 | 9 | sdist: 10 | python setup.py sdist 11 | 12 | clean: 13 | python setup.py clean 14 | rm -rf build 15 | 16 | .PHONY: test 17 | 18 | test: 19 | python test/test_ssl.py 20 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ssl 2 | === 3 | 4 | The old socket.ssl() support for TLS over sockets is being 5 | superseded in Python 2.6 by a new 'ssl' module. This package 6 | brings that module to older Python releases, 2.3.5 and up (it may 7 | also work on older versions of 2.3, but we haven't tried it). 8 | 9 | It's quite similar to the 2.6 ssl module. There's no stand-alone 10 | documentation for this package; instead, just use the development 11 | branch documentation for the SSL module at 12 | http://docs.python.org/dev/library/ssl.html. 13 | 14 | Version 1.0 had a problem with Python 2.5.1 -- the structure of 15 | the socket object changed from earlier versions. 16 | 17 | Version 1.1 was missing various package metadata information. 18 | 19 | Version 1.2 added more package metadata, and support for 20 | ssl.get_server_certificate(), and the PEM-to-DER encode/decode 21 | routines. Plus integrated Paul Moore's patch to setup.py for 22 | Windows. Plus added support for asyncore, and asyncore HTTPS 23 | server test. 24 | 25 | Version 1.3 fixed a bug in the test suite. 26 | 27 | Version 1.4 incorporated use of -static switch. 28 | 29 | Version 1.5 fixed bug in Python version check affecting build on 30 | Python 2.5.0. 31 | 32 | Version 1.7 (and 1.6) fixed some bugs with asyncore support (recv and 33 | send not being called on the SSLSocket class, wrong semantics for 34 | sendall). 35 | 36 | Version 1.8 incorporated some code from Chris Stawarz to handle 37 | sockets which are set to non-blocking before negotiating the SSL 38 | session. 39 | 40 | Version 1.9 makes ssl.SSLError a subtype of socket.error. 41 | 42 | Version 1.10 fixes a bug in sendall(). 43 | 44 | Version 1.11 includes the MANIFEST file, and by default will turne 45 | unexpected EOFs occurring during a read into a regular EOF. It also 46 | removes the code for SSLFileStream, to use the regular socket module's 47 | _fileobject instead. 48 | 49 | Version 1.12 fixes the bug in SSLSocket.accept() reported by Georg 50 | Brandl, and adds a test case for that fix. 51 | 52 | Version 1.13 fixes a bug in calling do_handshake() automatically 53 | on non-blocking sockets. Thanks to Giampaolo Rodola. Now includes 54 | real asyncore test case. 55 | 56 | Version 1.14 incorporates some fixes to naming (rename "recv_from" to 57 | "recvfrom" and "send_to" to "sendto"), and a fix to the asyncore test 58 | case to unregister the connection handler when the connection is 59 | closed. It also exposes the SSL shutdown via the "unwrap" method 60 | on an SSLSocket. It exposes "subjectPublicKey" in the data received 61 | from a peer cert. 62 | 63 | Version 1.15 fixes a bug in write retries, where the output buffer has 64 | changed location because of garbage collection during the interim. 65 | It also provides the new flag, PROTOCOL_NOSSLv2, which selects SSL23, 66 | but disallows actual use of SSL2. 67 | 68 | Version 1.16 removes installing tests system-wide (which fixes the 69 | "permission denied" error when installing in virtualenvs), adds 70 | ``/usr/lib/i386-linux-gnu`` and ``/usr/lib/x86_64-linux-gnu`` to the 71 | search path (which fixes compilation on ubuntu 12.04) and stopped using 72 | ``SSLv2_method`` if it's not present. Many thanks to `Denis Bilenko`_ 73 | for providing those fixes through his temporary sslfix_ fork. 74 | 75 | The package is now maintained (bugfix only) by PyPA_. 76 | 77 | Authorship: A cast of dozens over the years have written the Python 78 | SSL support, including Marc-Alan Lemburg, Robin Dunn, GvR, Kalle 79 | Svensson, Skip Montanaro, Mark Hammond, Martin von Loewis, Jeremy 80 | Hylton, Andrew Kuchling, Georg Brandl, Bill Janssen, Chris Stawarz, 81 | Neal Norwitz, and many others. Thanks to Paul Moore, David Bolen and 82 | Mark Hammond for help with the Windows side of the house. And it's 83 | all based on OpenSSL, which has its own cast of dozens! 84 | 85 | .. _PyPA: https://github.com/pypa 86 | .. _`Denis Bilenko`: https://github.com/denik 87 | .. _`sslfix`: https://pypi.python.org/pypi/sslfix 88 | 89 | Installation 90 | ------------ 91 | 92 | To install it, run:: 93 | 94 | pip install ssl 95 | 96 | or download it from https://pypi.python.org/pypi/ssl 97 | 98 | Issues 99 | ------ 100 | 101 | Feel free to report issues at https://github.com/pypa/ssl/issues 102 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import codecs 2 | import os 3 | import re 4 | import sys 5 | 6 | from distutils.core import setup, Extension 7 | 8 | if (sys.version_info >= (2, 6, 0)): 9 | raise ValueError("This extension should not be used with " 10 | + "Python 2.6 or later (already built in), " 11 | + "and has not been tested with Python 2.3.4 " 12 | + "or earlier.") 13 | elif (sys.version_info < (2, 3, 5)): 14 | sys.stderr.write("Warning: This code has not been tested " 15 | + "with versions of Python less than 2.3.5.\n") 16 | 17 | 18 | def find_file(filename, std_dirs, paths): 19 | """Searches for the directory where a given file is located, 20 | and returns a possibly-empty list of additional directories, or None 21 | if the file couldn't be found at all. 22 | 23 | 'filename' is the name of a file, such as readline.h or libcrypto.a. 24 | 'std_dirs' is the list of standard system directories; if the 25 | file is found in one of them, no additional directives are needed. 26 | 'paths' is a list of additional locations to check; if the file is 27 | found in one of them, the resulting list will contain the directory. 28 | """ 29 | 30 | # Check the standard locations 31 | for dir in std_dirs: 32 | f = os.path.join(dir, filename) 33 | print 'looking for', f 34 | if os.path.exists(f): 35 | return [] 36 | 37 | # Check the additional directories 38 | for dir in paths: 39 | f = os.path.join(dir, filename) 40 | print 'looking for', f 41 | if os.path.exists(f): 42 | return [dir] 43 | 44 | # Not found anywhere 45 | return None 46 | 47 | 48 | def find_library_file(compiler, libname, std_dirs, paths): 49 | result = compiler.find_library_file(std_dirs + paths, libname) 50 | if result is None: 51 | return None 52 | 53 | # Check whether the found file is in one of the standard directories 54 | dirname = os.path.dirname(result) 55 | for p in std_dirs: 56 | # Ensure path doesn't end with path separator 57 | p = p.rstrip(os.sep) 58 | if p == dirname: 59 | return [] 60 | 61 | # Otherwise, it must have been in one of the additional directories, 62 | # so we have to figure out which one. 63 | for p in paths: 64 | # Ensure path doesn't end with path separator 65 | p = p.rstrip(os.sep) 66 | if p == dirname: 67 | return [p] 68 | else: 69 | assert False, "Internal error: Path not found in std_dirs or paths" 70 | 71 | 72 | def find_ssl(): 73 | 74 | # Detect SSL support for the socket module (via _ssl) 75 | from distutils.ccompiler import new_compiler 76 | 77 | compiler = new_compiler() 78 | inc_dirs = compiler.include_dirs + ['/usr/include'] 79 | 80 | search_for_ssl_incs_in = [ 81 | '/usr/local/ssl/include', 82 | '/usr/contrib/ssl/include/', 83 | ] 84 | ssl_incs = find_file('openssl/ssl.h', inc_dirs, search_for_ssl_incs_in) 85 | if ssl_incs is not None: 86 | krb5_h = find_file('krb5.h', inc_dirs, 87 | ['/usr/kerberos/include']) 88 | if krb5_h: 89 | ssl_incs += krb5_h 90 | 91 | ssl_libs = find_library_file(compiler, 'ssl', 92 | ['/usr/lib', '/usr/lib/i386-linux-gnu', '/usr/lib/x86_64-linux-gnu'], 93 | ['/usr/local/lib', '/usr/local/ssl/lib', '/usr/contrib/ssl/lib/']) 94 | 95 | if (ssl_incs is not None and ssl_libs is not None): 96 | return ssl_incs, ssl_libs, ['ssl', 'crypto'] 97 | 98 | raise Exception("No SSL support found") 99 | 100 | if (sys.version_info >= (2, 5, 1)): 101 | socket_inc = "./ssl/2.5.1" 102 | else: 103 | socket_inc = "./ssl/2.3.6" 104 | 105 | link_args = [] 106 | if sys.platform == 'win32': 107 | 108 | # Assume the openssl libraries from GnuWin32 are installed in the 109 | # following location: 110 | gnuwin32_dir = os.environ.get("GNUWIN32_DIR", r"C:\Utils\GnuWin32") 111 | 112 | # Set this to 1 for a dynamic build (depends on openssl DLLs) 113 | # Dynamic build is about 26k, static is 670k 114 | dynamic = int(os.environ.get("SSL_DYNAMIC", 0)) 115 | 116 | ssl_incs = [os.environ.get("C_INCLUDE_DIR") or os.path.join(gnuwin32_dir, "include")] 117 | ssl_libs = [os.environ.get("C_LIB_DIR") or os.path.join(gnuwin32_dir, "lib")] 118 | libs = ['ssl', 'crypto', 'wsock32'] 119 | if not dynamic: 120 | libs = libs + ['gdi32', 'gw32c', 'ole32', 'uuid'] 121 | link_args = ['-static'] 122 | else: 123 | ssl_incs, ssl_libs, libs = find_ssl() 124 | 125 | 126 | def read(*parts): 127 | here = os.path.abspath(os.path.dirname(__file__)) 128 | return codecs.open(os.path.join(here, *parts), 'r').read() 129 | 130 | 131 | def find_version(*file_paths): 132 | version_file = read(*file_paths) 133 | version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", 134 | version_file, re.M) 135 | if version_match: 136 | return version_match.group(1) 137 | raise RuntimeError("Unable to find version string.") 138 | 139 | 140 | setup(name='ssl', 141 | version=find_version('ssl', '__init__.py'), 142 | description='SSL wrapper for socket objects (2.3, 2.4, 2.5 compatible)', 143 | long_description=read('README.rst'), 144 | license='Python (MIT-like)', 145 | author='See long_description for details', 146 | author_email='distutils-sig@python.org', 147 | url='https://github.com/pypa/ssl', 148 | packages=['ssl'], 149 | ext_modules=[Extension('ssl._ssl2', ['ssl/_ssl2.c'], 150 | include_dirs=ssl_incs + [socket_inc], 151 | library_dirs=ssl_libs, 152 | libraries=libs, 153 | extra_link_args=link_args)] 154 | ) 155 | -------------------------------------------------------------------------------- /ssl/2.3.6/socketmodule.h: -------------------------------------------------------------------------------- 1 | /* Socket module header file */ 2 | 3 | /* Includes needed for the sockaddr_* symbols below */ 4 | #ifndef MS_WINDOWS 5 | #ifdef __VMS 6 | # include 7 | # else 8 | # include 9 | # endif 10 | # include 11 | # if !(defined(__BEOS__) || defined(__CYGWIN__) || (defined(PYOS_OS2) && defined(PYCC_VACPP))) 12 | # include 13 | # endif 14 | 15 | #else /* MS_WINDOWS */ 16 | #if _MSC_VER >= 1300 17 | # include 18 | # include 19 | # define HAVE_ADDRINFO 20 | # define HAVE_SOCKADDR_STORAGE 21 | # define HAVE_GETADDRINFO 22 | # define HAVE_GETNAMEINFO 23 | # define ENABLE_IPV6 24 | #else 25 | # include 26 | #endif 27 | #endif 28 | 29 | #ifdef HAVE_SYS_UN_H 30 | # include 31 | #else 32 | # undef AF_UNIX 33 | #endif 34 | 35 | #ifdef HAVE_NETPACKET_PACKET_H 36 | # include 37 | # include 38 | # include 39 | #endif 40 | 41 | #ifndef Py__SOCKET_H 42 | #define Py__SOCKET_H 43 | #ifdef __cplusplus 44 | extern "C" { 45 | #endif 46 | 47 | /* Python module and C API name */ 48 | #define PySocket_MODULE_NAME "_socket" 49 | #define PySocket_CAPI_NAME "CAPI" 50 | 51 | /* Abstract the socket file descriptor type */ 52 | #ifdef MS_WINDOWS 53 | typedef SOCKET SOCKET_T; 54 | # ifdef MS_WIN64 55 | # define SIZEOF_SOCKET_T 8 56 | # else 57 | # define SIZEOF_SOCKET_T 4 58 | # endif 59 | #else 60 | typedef int SOCKET_T; 61 | # define SIZEOF_SOCKET_T SIZEOF_INT 62 | #endif 63 | 64 | /* The object holding a socket. It holds some extra information, 65 | like the address family, which is used to decode socket address 66 | arguments properly. */ 67 | 68 | typedef struct { 69 | PyObject_HEAD 70 | SOCKET_T sock_fd; /* Socket file descriptor */ 71 | int sock_family; /* Address family, e.g., AF_INET */ 72 | int sock_type; /* Socket type, e.g., SOCK_STREAM */ 73 | int sock_proto; /* Protocol type, usually 0 */ 74 | union sock_addr { 75 | struct sockaddr_in in; 76 | #ifdef AF_UNIX 77 | struct sockaddr_un un; 78 | #endif 79 | #ifdef ENABLE_IPV6 80 | struct sockaddr_in6 in6; 81 | struct sockaddr_storage storage; 82 | #endif 83 | #ifdef HAVE_NETPACKET_PACKET_H 84 | struct sockaddr_ll ll; 85 | #endif 86 | } sock_addr; 87 | PyObject *(*errorhandler)(void); /* Error handler; checks 88 | errno, returns NULL and 89 | sets a Python exception */ 90 | double sock_timeout; /* Operation timeout in seconds; 91 | 0.0 means non-blocking */ 92 | } PySocketSockObject; 93 | 94 | /* --- C API ----------------------------------------------------*/ 95 | 96 | /* Short explanation of what this C API export mechanism does 97 | and how it works: 98 | 99 | The _ssl module needs access to the type object defined in 100 | the _socket module. Since cross-DLL linking introduces a lot of 101 | problems on many platforms, the "trick" is to wrap the 102 | C API of a module in a struct which then gets exported to 103 | other modules via a PyCObject. 104 | 105 | The code in socketmodule.c defines this struct (which currently 106 | only contains the type object reference, but could very 107 | well also include other C APIs needed by other modules) 108 | and exports it as PyCObject via the module dictionary 109 | under the name "CAPI". 110 | 111 | Other modules can now include the socketmodule.h file 112 | which defines the needed C APIs to import and set up 113 | a static copy of this struct in the importing module. 114 | 115 | After initialization, the importing module can then 116 | access the C APIs from the _socket module by simply 117 | referring to the static struct, e.g. 118 | 119 | Load _socket module and its C API; this sets up the global 120 | PySocketModule: 121 | 122 | if (PySocketModule_ImportModuleAndAPI()) 123 | return; 124 | 125 | 126 | Now use the C API as if it were defined in the using 127 | module: 128 | 129 | if (!PyArg_ParseTuple(args, "O!|zz:ssl", 130 | 131 | PySocketModule.Sock_Type, 132 | 133 | (PyObject*)&Sock, 134 | &key_file, &cert_file)) 135 | return NULL; 136 | 137 | Support could easily be extended to export more C APIs/symbols 138 | this way. Currently, only the type object is exported, 139 | other candidates would be socket constructors and socket 140 | access functions. 141 | 142 | */ 143 | 144 | /* C API for usage by other Python modules */ 145 | typedef struct { 146 | PyTypeObject *Sock_Type; 147 | } PySocketModule_APIObject; 148 | 149 | /* XXX The net effect of the following appears to be to define a function 150 | XXX named PySocketModule_APIObject in _ssl.c. It's unclear why it isn't 151 | XXX defined there directly. 152 | 153 | >>> It's defined here because other modules might also want to use 154 | >>> the C API. 155 | 156 | */ 157 | #ifndef PySocket_BUILDING_SOCKET 158 | 159 | /* --- C API ----------------------------------------------------*/ 160 | 161 | /* Interfacestructure to C API for other modules. 162 | Call PySocketModule_ImportModuleAndAPI() to initialize this 163 | structure. After that usage is simple: 164 | 165 | if (!PyArg_ParseTuple(args, "O!|zz:ssl", 166 | &PySocketModule.Sock_Type, (PyObject*)&Sock, 167 | &key_file, &cert_file)) 168 | return NULL; 169 | ... 170 | */ 171 | 172 | static 173 | PySocketModule_APIObject PySocketModule; 174 | 175 | /* You *must* call this before using any of the functions in 176 | PySocketModule and check its outcome; otherwise all accesses will 177 | result in a segfault. Returns 0 on success. */ 178 | 179 | #ifndef DPRINTF 180 | # define DPRINTF if (0) printf 181 | #endif 182 | 183 | static 184 | int PySocketModule_ImportModuleAndAPI(void) 185 | { 186 | PyObject *mod = 0, *v = 0; 187 | char *apimodule = PySocket_MODULE_NAME; 188 | char *apiname = PySocket_CAPI_NAME; 189 | void *api; 190 | 191 | DPRINTF("Importing the %s C API...\n", apimodule); 192 | mod = PyImport_ImportModule(apimodule); 193 | if (mod == NULL) 194 | goto onError; 195 | DPRINTF(" %s package found\n", apimodule); 196 | v = PyObject_GetAttrString(mod, apiname); 197 | if (v == NULL) 198 | goto onError; 199 | Py_DECREF(mod); 200 | DPRINTF(" API object %s found\n", apiname); 201 | api = PyCObject_AsVoidPtr(v); 202 | if (api == NULL) 203 | goto onError; 204 | Py_DECREF(v); 205 | memcpy(&PySocketModule, api, sizeof(PySocketModule)); 206 | DPRINTF(" API object loaded and initialized.\n"); 207 | return 0; 208 | 209 | onError: 210 | DPRINTF(" not found.\n"); 211 | Py_XDECREF(mod); 212 | Py_XDECREF(v); 213 | return -1; 214 | } 215 | 216 | #endif /* !PySocket_BUILDING_SOCKET */ 217 | 218 | #ifdef __cplusplus 219 | } 220 | #endif 221 | #endif /* !Py__SOCKET_H */ 222 | -------------------------------------------------------------------------------- /ssl/2.5.1/socketmodule.h: -------------------------------------------------------------------------------- 1 | /* Socket module header file */ 2 | 3 | /* Includes needed for the sockaddr_* symbols below */ 4 | #ifndef MS_WINDOWS 5 | #ifdef __VMS 6 | # include 7 | # else 8 | # include 9 | # endif 10 | # include 11 | # if !(defined(__BEOS__) || defined(__CYGWIN__) || (defined(PYOS_OS2) && defined(PYCC_VACPP))) 12 | # include 13 | # endif 14 | 15 | #else /* MS_WINDOWS */ 16 | #if _MSC_VER >= 1300 17 | # include 18 | # include 19 | # define HAVE_ADDRINFO 20 | # define HAVE_SOCKADDR_STORAGE 21 | # define HAVE_GETADDRINFO 22 | # define HAVE_GETNAMEINFO 23 | # define ENABLE_IPV6 24 | #else 25 | # include 26 | #endif 27 | #endif 28 | 29 | #ifdef HAVE_SYS_UN_H 30 | # include 31 | #else 32 | # undef AF_UNIX 33 | #endif 34 | 35 | #ifdef HAVE_LINUX_NETLINK_H 36 | # ifdef HAVE_ASM_TYPES_H 37 | # include 38 | # endif 39 | # include 40 | #else 41 | # undef AF_NETLINK 42 | #endif 43 | 44 | #ifdef HAVE_BLUETOOTH_BLUETOOTH_H 45 | #include 46 | #include 47 | #include 48 | #include 49 | #endif 50 | 51 | #ifdef HAVE_BLUETOOTH_H 52 | #include 53 | #endif 54 | 55 | #ifdef HAVE_NETPACKET_PACKET_H 56 | # include 57 | # include 58 | # include 59 | #endif 60 | 61 | #ifndef Py__SOCKET_H 62 | #define Py__SOCKET_H 63 | #ifdef __cplusplus 64 | extern "C" { 65 | #endif 66 | 67 | /* Python module and C API name */ 68 | #define PySocket_MODULE_NAME "_socket" 69 | #define PySocket_CAPI_NAME "CAPI" 70 | 71 | /* Abstract the socket file descriptor type */ 72 | #ifdef MS_WINDOWS 73 | typedef SOCKET SOCKET_T; 74 | # ifdef MS_WIN64 75 | # define SIZEOF_SOCKET_T 8 76 | # else 77 | # define SIZEOF_SOCKET_T 4 78 | # endif 79 | #else 80 | typedef int SOCKET_T; 81 | # define SIZEOF_SOCKET_T SIZEOF_INT 82 | #endif 83 | 84 | /* Socket address */ 85 | typedef union sock_addr { 86 | struct sockaddr_in in; 87 | #ifdef AF_UNIX 88 | struct sockaddr_un un; 89 | #endif 90 | #ifdef AF_NETLINK 91 | struct sockaddr_nl nl; 92 | #endif 93 | #ifdef ENABLE_IPV6 94 | struct sockaddr_in6 in6; 95 | struct sockaddr_storage storage; 96 | #endif 97 | #ifdef HAVE_BLUETOOTH_BLUETOOTH_H 98 | struct sockaddr_l2 bt_l2; 99 | struct sockaddr_rc bt_rc; 100 | struct sockaddr_sco bt_sco; 101 | #endif 102 | #ifdef HAVE_NETPACKET_PACKET_H 103 | struct sockaddr_ll ll; 104 | #endif 105 | } sock_addr_t; 106 | 107 | /* The object holding a socket. It holds some extra information, 108 | like the address family, which is used to decode socket address 109 | arguments properly. */ 110 | 111 | typedef struct { 112 | PyObject_HEAD 113 | SOCKET_T sock_fd; /* Socket file descriptor */ 114 | int sock_family; /* Address family, e.g., AF_INET */ 115 | int sock_type; /* Socket type, e.g., SOCK_STREAM */ 116 | int sock_proto; /* Protocol type, usually 0 */ 117 | PyObject *(*errorhandler)(void); /* Error handler; checks 118 | errno, returns NULL and 119 | sets a Python exception */ 120 | double sock_timeout; /* Operation timeout in seconds; 121 | 0.0 means non-blocking */ 122 | } PySocketSockObject; 123 | 124 | /* --- C API ----------------------------------------------------*/ 125 | 126 | /* Short explanation of what this C API export mechanism does 127 | and how it works: 128 | 129 | The _ssl module needs access to the type object defined in 130 | the _socket module. Since cross-DLL linking introduces a lot of 131 | problems on many platforms, the "trick" is to wrap the 132 | C API of a module in a struct which then gets exported to 133 | other modules via a PyCObject. 134 | 135 | The code in socketmodule.c defines this struct (which currently 136 | only contains the type object reference, but could very 137 | well also include other C APIs needed by other modules) 138 | and exports it as PyCObject via the module dictionary 139 | under the name "CAPI". 140 | 141 | Other modules can now include the socketmodule.h file 142 | which defines the needed C APIs to import and set up 143 | a static copy of this struct in the importing module. 144 | 145 | After initialization, the importing module can then 146 | access the C APIs from the _socket module by simply 147 | referring to the static struct, e.g. 148 | 149 | Load _socket module and its C API; this sets up the global 150 | PySocketModule: 151 | 152 | if (PySocketModule_ImportModuleAndAPI()) 153 | return; 154 | 155 | 156 | Now use the C API as if it were defined in the using 157 | module: 158 | 159 | if (!PyArg_ParseTuple(args, "O!|zz:ssl", 160 | 161 | PySocketModule.Sock_Type, 162 | 163 | (PyObject*)&Sock, 164 | &key_file, &cert_file)) 165 | return NULL; 166 | 167 | Support could easily be extended to export more C APIs/symbols 168 | this way. Currently, only the type object is exported, 169 | other candidates would be socket constructors and socket 170 | access functions. 171 | 172 | */ 173 | 174 | /* C API for usage by other Python modules */ 175 | typedef struct { 176 | PyTypeObject *Sock_Type; 177 | PyObject *error; 178 | } PySocketModule_APIObject; 179 | 180 | /* XXX The net effect of the following appears to be to define a function 181 | XXX named PySocketModule_APIObject in _ssl.c. It's unclear why it isn't 182 | XXX defined there directly. 183 | 184 | >>> It's defined here because other modules might also want to use 185 | >>> the C API. 186 | 187 | */ 188 | #ifndef PySocket_BUILDING_SOCKET 189 | 190 | /* --- C API ----------------------------------------------------*/ 191 | 192 | /* Interfacestructure to C API for other modules. 193 | Call PySocketModule_ImportModuleAndAPI() to initialize this 194 | structure. After that usage is simple: 195 | 196 | if (!PyArg_ParseTuple(args, "O!|zz:ssl", 197 | &PySocketModule.Sock_Type, (PyObject*)&Sock, 198 | &key_file, &cert_file)) 199 | return NULL; 200 | ... 201 | */ 202 | 203 | static 204 | PySocketModule_APIObject PySocketModule; 205 | 206 | /* You *must* call this before using any of the functions in 207 | PySocketModule and check its outcome; otherwise all accesses will 208 | result in a segfault. Returns 0 on success. */ 209 | 210 | #ifndef DPRINTF 211 | # define DPRINTF if (0) printf 212 | #endif 213 | 214 | static 215 | int PySocketModule_ImportModuleAndAPI(void) 216 | { 217 | PyObject *mod = 0, *v = 0; 218 | char *apimodule = PySocket_MODULE_NAME; 219 | char *apiname = PySocket_CAPI_NAME; 220 | void *api; 221 | 222 | DPRINTF("Importing the %s C API...\n", apimodule); 223 | mod = PyImport_ImportModule(apimodule); 224 | if (mod == NULL) 225 | goto onError; 226 | DPRINTF(" %s package found\n", apimodule); 227 | v = PyObject_GetAttrString(mod, apiname); 228 | if (v == NULL) 229 | goto onError; 230 | Py_DECREF(mod); 231 | DPRINTF(" API object %s found\n", apiname); 232 | api = PyCObject_AsVoidPtr(v); 233 | if (api == NULL) 234 | goto onError; 235 | Py_DECREF(v); 236 | memcpy(&PySocketModule, api, sizeof(PySocketModule)); 237 | DPRINTF(" API object loaded and initialized.\n"); 238 | return 0; 239 | 240 | onError: 241 | DPRINTF(" not found.\n"); 242 | Py_XDECREF(mod); 243 | Py_XDECREF(v); 244 | return -1; 245 | } 246 | 247 | #endif /* !PySocket_BUILDING_SOCKET */ 248 | 249 | #ifdef __cplusplus 250 | } 251 | #endif 252 | #endif /* !Py__SOCKET_H */ 253 | -------------------------------------------------------------------------------- /ssl/__init__.py: -------------------------------------------------------------------------------- 1 | # Wrapper module for _ssl, providing some additional facilities 2 | # implemented in Python. Written by Bill Janssen. 3 | 4 | """\ 5 | This module provides some more Pythonic support for SSL. 6 | 7 | Object types: 8 | 9 | SSLSocket -- subtype of socket.socket which does SSL over the socket 10 | 11 | Exceptions: 12 | 13 | SSLError -- exception raised for I/O errors 14 | 15 | Functions: 16 | 17 | cert_time_to_seconds -- convert time string used for certificate 18 | notBefore and notAfter functions to integer 19 | seconds past the Epoch (the time values 20 | returned from time.time()) 21 | 22 | fetch_server_certificate (HOST, PORT) -- fetch the certificate provided 23 | by the server running on HOST at port PORT. No 24 | validation of the certificate is performed. 25 | 26 | Integer constants: 27 | 28 | SSL_ERROR_ZERO_RETURN 29 | SSL_ERROR_WANT_READ 30 | SSL_ERROR_WANT_WRITE 31 | SSL_ERROR_WANT_X509_LOOKUP 32 | SSL_ERROR_SYSCALL 33 | SSL_ERROR_SSL 34 | SSL_ERROR_WANT_CONNECT 35 | 36 | SSL_ERROR_EOF 37 | SSL_ERROR_INVALID_ERROR_CODE 38 | 39 | The following group define certificate requirements that one side is 40 | allowing/requiring from the other side: 41 | 42 | CERT_NONE - no certificates from the other side are required (or will 43 | be looked at if provided) 44 | CERT_OPTIONAL - certificates are not required, but if provided will be 45 | validated, and if validation fails, the connection will 46 | also fail 47 | CERT_REQUIRED - certificates are required, and will be validated, and 48 | if validation fails, the connection will also fail 49 | 50 | The following constants identify various SSL protocol variants: 51 | 52 | PROTOCOL_SSLv2 53 | PROTOCOL_SSLv3 54 | PROTOCOL_SSLv23 55 | PROTOCOL_TLSv1 56 | PROTOCOL_NOSSLv2 -- anything except version 2 57 | """ 58 | 59 | import os, sys 60 | 61 | import _ssl2 # if we can't import it, let the error propagate 62 | 63 | from _ssl2 import SSLError 64 | from _ssl2 import CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED 65 | from _ssl2 import PROTOCOL_SSLv2, PROTOCOL_SSLv3, PROTOCOL_SSLv23, PROTOCOL_TLSv1, PROTOCOL_NOSSLv2 66 | from _ssl2 import RAND_status, RAND_egd, RAND_add 67 | from _ssl2 import \ 68 | SSL_ERROR_ZERO_RETURN, \ 69 | SSL_ERROR_WANT_READ, \ 70 | SSL_ERROR_WANT_WRITE, \ 71 | SSL_ERROR_WANT_X509_LOOKUP, \ 72 | SSL_ERROR_SYSCALL, \ 73 | SSL_ERROR_SSL, \ 74 | SSL_ERROR_WANT_CONNECT, \ 75 | SSL_ERROR_EOF, \ 76 | SSL_ERROR_INVALID_ERROR_CODE 77 | 78 | from socket import socket, _fileobject 79 | from socket import getnameinfo as _getnameinfo 80 | import base64 # for DER-to-PEM translation 81 | import select # for handshake 82 | 83 | # The version as used in the setup.py 84 | __version__ = "1.16" 85 | 86 | 87 | class SSLSocket (socket): 88 | 89 | """This class implements a subtype of socket.socket that wraps 90 | the underlying OS socket in an SSL context when necessary, and 91 | provides read and write methods over that channel.""" 92 | 93 | def __init__(self, sock, keyfile=None, certfile=None, 94 | server_side=False, cert_reqs=CERT_NONE, 95 | ssl_version=PROTOCOL_SSLv23, ca_certs=None, 96 | do_handshake_on_connect=True, 97 | suppress_ragged_eofs=True): 98 | socket.__init__(self, _sock=sock._sock) 99 | # the initializer for socket trashes the methods (tsk, tsk), so... 100 | self.send = lambda x, flags=0: SSLSocket.send(self, x, flags) 101 | self.recv = lambda x, flags=0: SSLSocket.recv(self, x, flags) 102 | self.sendto = lambda data, addr, flags=0: SSLSocket.sendto(self, data, addr, flags) 103 | self.recvfrom = lambda addr, buflen, flags: SSLSocket.recvfrom(self, addr, buflen, flags) 104 | 105 | if certfile and not keyfile: 106 | keyfile = certfile 107 | # see if it's connected 108 | try: 109 | socket.getpeername(self) 110 | except: 111 | # no, no connection yet 112 | self._sslobj = None 113 | else: 114 | # yes, create the SSL object 115 | self._sslobj = _ssl2.sslwrap(self._sock, server_side, 116 | keyfile, certfile, 117 | cert_reqs, ssl_version, ca_certs) 118 | if do_handshake_on_connect: 119 | timeout = self.gettimeout() 120 | if timeout == 0.0: 121 | # non-blocking 122 | raise ValueError("do_handshake_on_connect should not be specified for non-blocking sockets") 123 | self.do_handshake() 124 | self.keyfile = keyfile 125 | self.certfile = certfile 126 | self.cert_reqs = cert_reqs 127 | self.ssl_version = ssl_version 128 | self.ca_certs = ca_certs 129 | self.do_handshake_on_connect = do_handshake_on_connect 130 | self.suppress_ragged_eofs = suppress_ragged_eofs 131 | self._makefile_refs = 0 132 | 133 | def read(self, len=1024): 134 | 135 | """Read up to LEN bytes and return them. 136 | Return zero-length string on EOF.""" 137 | 138 | try: 139 | return self._sslobj.read(len) 140 | except SSLError, x: 141 | if x.args[0] == SSL_ERROR_EOF and self.suppress_ragged_eofs: 142 | return '' 143 | else: 144 | raise 145 | 146 | def write(self, data): 147 | 148 | """Write DATA to the underlying SSL channel. Returns 149 | number of bytes of DATA actually transmitted.""" 150 | 151 | return self._sslobj.write(data) 152 | 153 | def getpeercert(self, binary_form=False): 154 | 155 | """Returns a formatted version of the data in the 156 | certificate provided by the other end of the SSL channel. 157 | Return None if no certificate was provided, {} if a 158 | certificate was provided, but not validated.""" 159 | 160 | return self._sslobj.peer_certificate(binary_form) 161 | 162 | def cipher (self): 163 | 164 | if not self._sslobj: 165 | return None 166 | else: 167 | return self._sslobj.cipher() 168 | 169 | def send (self, data, flags=0): 170 | if self._sslobj: 171 | if flags != 0: 172 | raise ValueError( 173 | "non-zero flags not allowed in calls to send() on %s" % 174 | self.__class__) 175 | while True: 176 | try: 177 | v = self._sslobj.write(data) 178 | except SSLError, x: 179 | if x.args[0] == SSL_ERROR_WANT_READ: 180 | return 0 181 | elif x.args[0] == SSL_ERROR_WANT_WRITE: 182 | return 0 183 | else: 184 | raise 185 | else: 186 | return v 187 | else: 188 | return socket.send(self, data, flags) 189 | 190 | def sendto (self, data, addr, flags=0): 191 | if self._sslobj: 192 | raise ValueError("sendto not allowed on instances of %s" % 193 | self.__class__) 194 | else: 195 | return socket.sendto(self, data, addr, flags) 196 | 197 | def sendall (self, data, flags=0): 198 | if self._sslobj: 199 | if flags != 0: 200 | raise ValueError( 201 | "non-zero flags not allowed in calls to sendall() on %s" % 202 | self.__class__) 203 | amount = len(data) 204 | count = 0 205 | while (count < amount): 206 | v = self.send(data[count:]) 207 | count += v 208 | return amount 209 | else: 210 | return socket.sendall(self, data, flags) 211 | 212 | def recv (self, buflen=1024, flags=0): 213 | if self._sslobj: 214 | if flags != 0: 215 | raise ValueError( 216 | "non-zero flags not allowed in calls to recv() on %s" % 217 | self.__class__) 218 | while True: 219 | try: 220 | return self.read(buflen) 221 | except SSLError, x: 222 | if x.args[0] == SSL_ERROR_WANT_READ: 223 | continue 224 | else: 225 | raise x 226 | else: 227 | return socket.recv(self, buflen, flags) 228 | 229 | def recvfrom (self, addr, buflen=1024, flags=0): 230 | if self._sslobj: 231 | raise ValueError("recvfrom not allowed on instances of %s" % 232 | self.__class__) 233 | else: 234 | return socket.recvfrom(self, addr, buflen, flags) 235 | 236 | def pending(self): 237 | if self._sslobj: 238 | return self._sslobj.pending() 239 | else: 240 | return 0 241 | 242 | def unwrap (self): 243 | if self._sslobj: 244 | s = self._sslobj.shutdown() 245 | self._sslobj = None 246 | return s 247 | else: 248 | raise ValueError("No SSL wrapper around " + str(self)) 249 | 250 | def shutdown (self, how): 251 | self._sslobj = None 252 | socket.shutdown(self, how) 253 | 254 | def close (self): 255 | if self._makefile_refs < 1: 256 | self._sslobj = None 257 | socket.close(self) 258 | else: 259 | self._makefile_refs -= 1 260 | 261 | def do_handshake(self, block=False): 262 | 263 | """Perform a TLS/SSL handshake.""" 264 | 265 | timeout = self.gettimeout() 266 | try: 267 | if timeout == 0.0 and block: 268 | self.settimeout(None) 269 | self._sslobj.do_handshake() 270 | finally: 271 | self.settimeout(timeout) 272 | 273 | def connect(self, addr): 274 | 275 | """Connects to remote ADDR, and then wraps the connection in 276 | an SSL channel.""" 277 | 278 | # Here we assume that the socket is client-side, and not 279 | # connected at the time of the call. We connect it, then wrap it. 280 | if self._sslobj: 281 | raise ValueError("attempt to connect already-connected SSLSocket!") 282 | socket.connect(self, addr) 283 | self._sslobj = _ssl2.sslwrap(self._sock, False, self.keyfile, self.certfile, 284 | self.cert_reqs, self.ssl_version, 285 | self.ca_certs) 286 | if self.do_handshake_on_connect: 287 | self.do_handshake() 288 | 289 | def accept(self): 290 | 291 | """Accepts a new connection from a remote client, and returns 292 | a tuple containing that new connection wrapped with a server-side 293 | SSL channel, and the address of the remote client.""" 294 | 295 | newsock, addr = socket.accept(self) 296 | return (SSLSocket(newsock, 297 | keyfile=self.keyfile, 298 | certfile=self.certfile, 299 | server_side=True, 300 | cert_reqs=self.cert_reqs, 301 | ssl_version=self.ssl_version, 302 | ca_certs=self.ca_certs, 303 | do_handshake_on_connect=self.do_handshake_on_connect), 304 | addr) 305 | 306 | def makefile(self, mode='r', bufsize=-1): 307 | 308 | """Ouch. Need to make and return a file-like object that 309 | works with the SSL connection.""" 310 | 311 | self._makefile_refs += 1 312 | return _fileobject(self, mode, bufsize) 313 | 314 | 315 | 316 | def wrap_socket(sock, keyfile=None, certfile=None, 317 | server_side=False, cert_reqs=CERT_NONE, 318 | ssl_version=PROTOCOL_SSLv23, ca_certs=None, 319 | do_handshake_on_connect=True): 320 | 321 | return SSLSocket(sock, keyfile=keyfile, certfile=certfile, 322 | server_side=server_side, cert_reqs=cert_reqs, 323 | ssl_version=ssl_version, ca_certs=ca_certs, 324 | do_handshake_on_connect=do_handshake_on_connect) 325 | 326 | # some utility functions 327 | 328 | def cert_time_to_seconds(cert_time): 329 | 330 | """Takes a date-time string in standard ASN1_print form 331 | ("MON DAY 24HOUR:MINUTE:SEC YEAR TIMEZONE") and return 332 | a Python time value in seconds past the epoch.""" 333 | 334 | import time 335 | return time.mktime(time.strptime(cert_time, "%b %d %H:%M:%S %Y GMT")) 336 | 337 | PEM_HEADER = "-----BEGIN CERTIFICATE-----" 338 | PEM_FOOTER = "-----END CERTIFICATE-----" 339 | 340 | def DER_cert_to_PEM_cert(der_cert_bytes): 341 | 342 | """Takes a certificate in binary DER format and returns the 343 | PEM version of it as a string.""" 344 | 345 | if hasattr(base64, 'standard_b64encode'): 346 | # preferred because older API gets line-length wrong 347 | f = base64.standard_b64encode(der_cert_bytes) 348 | rval = PEM_HEADER + '\n' 349 | while len(f) > 0: 350 | l = min(len(f),64) 351 | rval += f[:l] + '\n' 352 | f = f[l:] 353 | rval += PEM_FOOTER + '\n' 354 | return rval 355 | else: 356 | return (PEM_HEADER + '\n' + 357 | base64.encodestring(der_cert_bytes) + 358 | PEM_FOOTER + '\n') 359 | 360 | def PEM_cert_to_DER_cert(pem_cert_string): 361 | 362 | """Takes a certificate in ASCII PEM format and returns the 363 | DER-encoded version of it as a byte sequence""" 364 | 365 | if not pem_cert_string.startswith(PEM_HEADER): 366 | raise ValueError("Invalid PEM encoding; must start with %s" 367 | % PEM_HEADER) 368 | if not pem_cert_string.strip().endswith(PEM_FOOTER): 369 | raise ValueError("Invalid PEM encoding; must end with %s" 370 | % PEM_FOOTER) 371 | d = pem_cert_string.strip()[len(PEM_HEADER):-len(PEM_FOOTER)] 372 | return base64.decodestring(d) 373 | 374 | def get_server_certificate (addr, ssl_version=PROTOCOL_SSLv3, ca_certs=None): 375 | 376 | """Retrieve the certificate from the server at the specified address, 377 | and return it as a PEM-encoded string. 378 | If 'ca_certs' is specified, validate the server cert against it. 379 | If 'ssl_version' is specified, use it in the connection attempt.""" 380 | 381 | host, port = addr 382 | if (ca_certs is not None): 383 | cert_reqs = CERT_REQUIRED 384 | else: 385 | cert_reqs = CERT_NONE 386 | s = wrap_socket(socket(), ssl_version=ssl_version, 387 | cert_reqs=cert_reqs, ca_certs=ca_certs) 388 | s.connect(addr) 389 | dercert = s.getpeercert(True) 390 | s.close() 391 | return DER_cert_to_PEM_cert(dercert) 392 | 393 | def get_protocol_name (protocol_code): 394 | if protocol_code == PROTOCOL_TLSv1: 395 | return "TLSv1" 396 | elif protocol_code == PROTOCOL_SSLv23: 397 | return "SSLv23" 398 | elif protocol_code == PROTOCOL_SSLv2: 399 | return "SSLv2" 400 | elif protocol_code == PROTOCOL_SSLv3: 401 | return "SSLv3" 402 | else: 403 | return "" 404 | 405 | 406 | # a replacement for the old socket.ssl function 407 | 408 | def sslwrap_simple (sock, keyfile=None, certfile=None): 409 | 410 | """A replacement for the old socket.ssl function. Designed 411 | for compability with Python 2.5 and earlier. Will disappear in 412 | Python 3.0.""" 413 | 414 | ssl_sock = _ssl2.sslwrap(sock._sock, 0, keyfile, certfile, CERT_NONE, 415 | PROTOCOL_SSLv23, None) 416 | ssl_sock.do_handshake() 417 | return ssl_sock() 418 | -------------------------------------------------------------------------------- /ssl/_ssl2.c: -------------------------------------------------------------------------------- 1 | /* SSL socket module 2 | 3 | 2.3 compatible version 4 | 5 | SSL support based on patches by Brian E Gallew and Laszlo Kovacs. 6 | Re-worked a bit by Bill Janssen to add server-side support and 7 | certificate decoding. 8 | 9 | This module is imported by ssl.py. It should *not* be used 10 | directly. 11 | 12 | XXX should partial writes be enabled, SSL_MODE_ENABLE_PARTIAL_WRITE? 13 | 14 | XXX what about SSL_MODE_AUTO_RETRY 15 | */ 16 | 17 | #include "Python.h" 18 | 19 | #ifdef WITH_THREAD 20 | #include "pythread.h" 21 | #define PySSL_BEGIN_ALLOW_THREADS { \ 22 | PyThreadState *_save = NULL; \ 23 | if (_ssl_locks_count>0) {_save = PyEval_SaveThread();} 24 | #define PySSL_BLOCK_THREADS if (_ssl_locks_count>0){PyEval_RestoreThread(_save)}; 25 | #define PySSL_UNBLOCK_THREADS if (_ssl_locks_count>0){_save = PyEval_SaveThread()}; 26 | #define PySSL_END_ALLOW_THREADS if (_ssl_locks_count>0){PyEval_RestoreThread(_save);} \ 27 | } 28 | 29 | #else /* no WITH_THREAD */ 30 | 31 | #define PySSL_BEGIN_ALLOW_THREADS 32 | #define PySSL_BLOCK_THREADS 33 | #define PySSL_UNBLOCK_THREADS 34 | #define PySSL_END_ALLOW_THREADS 35 | 36 | #endif 37 | 38 | /* bring in this define */ 39 | #define Py_Type(x) ((x)->ob_type) 40 | 41 | enum py_ssl_error { 42 | /* these mirror ssl.h */ 43 | PY_SSL_ERROR_NONE, 44 | PY_SSL_ERROR_SSL, 45 | PY_SSL_ERROR_WANT_READ, 46 | PY_SSL_ERROR_WANT_WRITE, 47 | PY_SSL_ERROR_WANT_X509_LOOKUP, 48 | PY_SSL_ERROR_SYSCALL, /* look at error stack/return value/errno */ 49 | PY_SSL_ERROR_ZERO_RETURN, 50 | PY_SSL_ERROR_WANT_CONNECT, 51 | /* start of non ssl.h errorcodes */ 52 | PY_SSL_ERROR_EOF, /* special case of SSL_ERROR_SYSCALL */ 53 | PY_SSL_ERROR_INVALID_ERROR_CODE 54 | }; 55 | 56 | enum py_ssl_server_or_client { 57 | PY_SSL_CLIENT, 58 | PY_SSL_SERVER 59 | }; 60 | 61 | enum py_ssl_cert_requirements { 62 | PY_SSL_CERT_NONE, 63 | PY_SSL_CERT_OPTIONAL, 64 | PY_SSL_CERT_REQUIRED 65 | }; 66 | 67 | enum py_ssl_version { 68 | PY_SSL_VERSION_SSL2, 69 | PY_SSL_VERSION_SSL3, 70 | PY_SSL_VERSION_SSL23, 71 | PY_SSL_VERSION_TLS1, 72 | PY_SSL_VERSION_NOSSL2, 73 | }; 74 | 75 | /* Include symbols from _socket module */ 76 | #include "socketmodule.h" 77 | 78 | #if defined(HAVE_POLL_H) 79 | #include 80 | #elif defined(HAVE_SYS_POLL_H) 81 | #include 82 | #endif 83 | 84 | /* Include OpenSSL header files */ 85 | #include "openssl/rsa.h" 86 | #include "openssl/crypto.h" 87 | #include "openssl/x509.h" 88 | #include "openssl/x509v3.h" 89 | #include "openssl/pem.h" 90 | #include "openssl/ssl.h" 91 | #include "openssl/err.h" 92 | #include "openssl/rand.h" 93 | 94 | /* SSL error object */ 95 | static PyObject *PySSLErrorObject; 96 | 97 | #ifdef WITH_THREAD 98 | 99 | /* serves as a flag to see whether we've initialized the SSL thread support. */ 100 | /* 0 means no, greater than 0 means yes */ 101 | 102 | static unsigned int _ssl_locks_count = 0; 103 | 104 | #endif /* def WITH_THREAD */ 105 | 106 | /* SSL socket object */ 107 | 108 | #define X509_NAME_MAXLEN 256 109 | 110 | /* RAND_* APIs got added to OpenSSL in 0.9.5 */ 111 | #if OPENSSL_VERSION_NUMBER >= 0x0090500fL 112 | # define HAVE_OPENSSL_RAND 1 113 | #else 114 | # undef HAVE_OPENSSL_RAND 115 | #endif 116 | 117 | typedef struct { 118 | PyObject_HEAD 119 | PySocketSockObject *Socket; /* Socket on which we're layered */ 120 | SSL_CTX* ctx; 121 | SSL* ssl; 122 | X509* peer_cert; 123 | char server[X509_NAME_MAXLEN]; 124 | char issuer[X509_NAME_MAXLEN]; 125 | 126 | } PySSLObject; 127 | 128 | static PyTypeObject PySSL_Type; 129 | static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args); 130 | static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args); 131 | static int check_socket_and_wait_for_timeout(PySocketSockObject *s, 132 | int writing); 133 | static PyObject *PySSL_peercert(PySSLObject *self, PyObject *args); 134 | static PyObject *PySSL_cipher(PySSLObject *self); 135 | static PyObject *PySSL_SSLshutdown(PySSLObject *self); 136 | 137 | #define PySSLObject_Check(v) (Py_Type(v) == &PySSL_Type) 138 | 139 | typedef enum { 140 | SOCKET_IS_NONBLOCKING, 141 | SOCKET_IS_BLOCKING, 142 | SOCKET_HAS_TIMED_OUT, 143 | SOCKET_HAS_BEEN_CLOSED, 144 | SOCKET_TOO_LARGE_FOR_SELECT, 145 | SOCKET_OPERATION_OK 146 | } timeout_state; 147 | 148 | /* Wrap error strings with filename and line # */ 149 | #define STRINGIFY1(x) #x 150 | #define STRINGIFY2(x) STRINGIFY1(x) 151 | #define ERRSTR1(x,y,z) (x ":" y ": " z) 152 | #define ERRSTR(x) ERRSTR1("_ssl.c", STRINGIFY2(__LINE__), x) 153 | 154 | /* XXX It might be helpful to augment the error message generated 155 | below with the name of the SSL function that generated the error. 156 | I expect it's obvious most of the time. 157 | */ 158 | 159 | static PyObject * 160 | PySSL_SetError(PySSLObject *obj, int ret, char *filename, int lineno) 161 | { 162 | PyObject *v; 163 | char buf[2048]; 164 | char *errstr; 165 | int err; 166 | enum py_ssl_error p = PY_SSL_ERROR_NONE; 167 | 168 | assert(ret <= 0); 169 | 170 | if (obj->ssl != NULL) { 171 | err = SSL_get_error(obj->ssl, ret); 172 | 173 | switch (err) { 174 | case SSL_ERROR_ZERO_RETURN: 175 | errstr = "TLS/SSL connection has been closed"; 176 | p = PY_SSL_ERROR_ZERO_RETURN; 177 | break; 178 | case SSL_ERROR_WANT_READ: 179 | errstr = "The operation did not complete (read)"; 180 | p = PY_SSL_ERROR_WANT_READ; 181 | break; 182 | case SSL_ERROR_WANT_WRITE: 183 | p = PY_SSL_ERROR_WANT_WRITE; 184 | errstr = "The operation did not complete (write)"; 185 | break; 186 | case SSL_ERROR_WANT_X509_LOOKUP: 187 | p = PY_SSL_ERROR_WANT_X509_LOOKUP; 188 | errstr = 189 | "The operation did not complete (X509 lookup)"; 190 | break; 191 | case SSL_ERROR_WANT_CONNECT: 192 | p = PY_SSL_ERROR_WANT_CONNECT; 193 | errstr = "The operation did not complete (connect)"; 194 | break; 195 | case SSL_ERROR_SYSCALL: 196 | { 197 | unsigned long e = ERR_get_error(); 198 | if (e == 0) { 199 | if (ret == 0 || !obj->Socket) { 200 | p = PY_SSL_ERROR_EOF; 201 | errstr = 202 | "EOF occurred in violation of protocol"; 203 | } else if (ret == -1) { 204 | /* underlying BIO reported an I/O error */ 205 | return obj->Socket->errorhandler(); 206 | } else { /* possible? */ 207 | p = PY_SSL_ERROR_SYSCALL; 208 | errstr = "Some I/O error occurred"; 209 | } 210 | } else { 211 | p = PY_SSL_ERROR_SYSCALL; 212 | /* XXX Protected by global interpreter lock */ 213 | errstr = ERR_error_string(e, NULL); 214 | } 215 | break; 216 | } 217 | case SSL_ERROR_SSL: 218 | { 219 | unsigned long e = ERR_get_error(); 220 | p = PY_SSL_ERROR_SSL; 221 | if (e != 0) 222 | /* XXX Protected by global interpreter lock */ 223 | errstr = ERR_error_string(e, NULL); 224 | else { /* possible? */ 225 | errstr = 226 | "A failure in the SSL library occurred"; 227 | } 228 | break; 229 | } 230 | default: 231 | p = PY_SSL_ERROR_INVALID_ERROR_CODE; 232 | errstr = "Invalid error code"; 233 | } 234 | } else { 235 | errstr = ERR_error_string(ERR_peek_last_error(), NULL); 236 | } 237 | PyOS_snprintf(buf, sizeof(buf), "_ssl.c:%d: %s", lineno, errstr); 238 | v = Py_BuildValue("(is)", p, buf); 239 | if (v != NULL) { 240 | PyErr_SetObject(PySSLErrorObject, v); 241 | Py_DECREF(v); 242 | } 243 | return NULL; 244 | } 245 | 246 | static PyObject * 247 | _setSSLError (char *errstr, int errcode, char *filename, int lineno) { 248 | 249 | char buf[2048]; 250 | PyObject *v; 251 | 252 | if (errstr == NULL) { 253 | errcode = ERR_peek_last_error(); 254 | errstr = ERR_error_string(errcode, NULL); 255 | } 256 | PyOS_snprintf(buf, sizeof(buf), "_ssl.c:%d: %s", lineno, errstr); 257 | v = Py_BuildValue("(is)", errcode, buf); 258 | if (v != NULL) { 259 | PyErr_SetObject(PySSLErrorObject, v); 260 | Py_DECREF(v); 261 | } 262 | return NULL; 263 | } 264 | 265 | static PySSLObject * 266 | newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file, 267 | enum py_ssl_server_or_client socket_type, 268 | enum py_ssl_cert_requirements certreq, 269 | enum py_ssl_version proto_version, 270 | char *cacerts_file) 271 | { 272 | PySSLObject *self; 273 | char *errstr = NULL; 274 | int ret; 275 | int verification_mode; 276 | 277 | self = PyObject_New(PySSLObject, &PySSL_Type); /* Create new object */ 278 | if (self == NULL) 279 | return NULL; 280 | memset(self->server, '\0', sizeof(char) * X509_NAME_MAXLEN); 281 | memset(self->issuer, '\0', sizeof(char) * X509_NAME_MAXLEN); 282 | self->peer_cert = NULL; 283 | self->ssl = NULL; 284 | self->ctx = NULL; 285 | self->Socket = NULL; 286 | 287 | /* Make sure the SSL error state is initialized */ 288 | (void) ERR_get_state(); 289 | ERR_clear_error(); 290 | 291 | if ((key_file && !cert_file) || (!key_file && cert_file)) { 292 | errstr = ERRSTR("Both the key & certificate files " 293 | "must be specified"); 294 | goto fail; 295 | } 296 | 297 | if ((socket_type == PY_SSL_SERVER) && 298 | ((key_file == NULL) || (cert_file == NULL))) { 299 | errstr = ERRSTR("Both the key & certificate files " 300 | "must be specified for server-side operation"); 301 | goto fail; 302 | } 303 | 304 | PySSL_BEGIN_ALLOW_THREADS 305 | if (proto_version == PY_SSL_VERSION_TLS1) 306 | self->ctx = SSL_CTX_new(TLSv1_method()); /* Set up context */ 307 | else if (proto_version == PY_SSL_VERSION_SSL3) 308 | self->ctx = SSL_CTX_new(SSLv3_method()); /* Set up context */ 309 | #ifndef OPENSSL_NO_SSL2 310 | else if (proto_version == PY_SSL_VERSION_SSL2) 311 | self->ctx = SSL_CTX_new(SSLv2_method()); /* Set up context */ 312 | #endif 313 | else if (proto_version == PY_SSL_VERSION_SSL23) 314 | self->ctx = SSL_CTX_new(SSLv23_method()); /* Set up context */ 315 | else if (proto_version == PY_SSL_VERSION_NOSSL2) { 316 | self->ctx = SSL_CTX_new(SSLv23_method()); 317 | SSL_CTX_set_options(self->ctx, SSL_OP_NO_SSLv2); 318 | }; 319 | PySSL_END_ALLOW_THREADS 320 | 321 | if (self->ctx == NULL) { 322 | errstr = ERRSTR("Invalid SSL protocol variant specified."); 323 | goto fail; 324 | } 325 | 326 | if (certreq != PY_SSL_CERT_NONE) { 327 | if (cacerts_file == NULL) { 328 | errstr = ERRSTR("No root certificates specified for " 329 | "verification of other-side certificates."); 330 | goto fail; 331 | } else { 332 | PySSL_BEGIN_ALLOW_THREADS 333 | ret = SSL_CTX_load_verify_locations(self->ctx, 334 | cacerts_file, 335 | NULL); 336 | PySSL_END_ALLOW_THREADS 337 | if (ret != 1) { 338 | _setSSLError(NULL, 0, __FILE__, __LINE__); 339 | goto fail; 340 | } 341 | } 342 | } 343 | if (key_file) { 344 | PySSL_BEGIN_ALLOW_THREADS 345 | ret = SSL_CTX_use_PrivateKey_file(self->ctx, key_file, 346 | SSL_FILETYPE_PEM); 347 | PySSL_END_ALLOW_THREADS 348 | if (ret != 1) { 349 | _setSSLError(NULL, ret, __FILE__, __LINE__); 350 | goto fail; 351 | } 352 | 353 | PySSL_BEGIN_ALLOW_THREADS 354 | ret = SSL_CTX_use_certificate_chain_file(self->ctx, 355 | cert_file); 356 | PySSL_END_ALLOW_THREADS 357 | if (ret != 1) { 358 | /* 359 | fprintf(stderr, "ret is %d, errcode is %lu, %lu, with file \"%s\"\n", 360 | ret, ERR_peek_error(), ERR_peek_last_error(), cert_file); 361 | */ 362 | if (ERR_peek_last_error() != 0) { 363 | _setSSLError(NULL, ret, __FILE__, __LINE__); 364 | goto fail; 365 | } 366 | } 367 | } 368 | 369 | /* ssl compatibility */ 370 | SSL_CTX_set_options(self->ctx, SSL_OP_ALL); 371 | SSL_CTX_set_mode(self->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); 372 | 373 | verification_mode = SSL_VERIFY_NONE; 374 | if (certreq == PY_SSL_CERT_OPTIONAL) 375 | verification_mode = SSL_VERIFY_PEER; 376 | else if (certreq == PY_SSL_CERT_REQUIRED) 377 | verification_mode = (SSL_VERIFY_PEER | 378 | SSL_VERIFY_FAIL_IF_NO_PEER_CERT); 379 | SSL_CTX_set_verify(self->ctx, verification_mode, 380 | NULL); /* set verify lvl */ 381 | 382 | PySSL_BEGIN_ALLOW_THREADS 383 | self->ssl = SSL_new(self->ctx); /* New ssl struct */ 384 | PySSL_END_ALLOW_THREADS 385 | SSL_set_fd(self->ssl, Sock->sock_fd); /* Set the socket for SSL */ 386 | 387 | /* If the socket is in non-blocking mode or timeout mode, set the BIO 388 | * to non-blocking mode (blocking is the default) 389 | */ 390 | if (Sock->sock_timeout >= 0.0) { 391 | /* Set both the read and write BIO's to non-blocking mode */ 392 | BIO_set_nbio(SSL_get_rbio(self->ssl), 1); 393 | BIO_set_nbio(SSL_get_wbio(self->ssl), 1); 394 | } 395 | 396 | PySSL_BEGIN_ALLOW_THREADS 397 | if (socket_type == PY_SSL_CLIENT) 398 | SSL_set_connect_state(self->ssl); 399 | else 400 | SSL_set_accept_state(self->ssl); 401 | PySSL_END_ALLOW_THREADS 402 | 403 | self->Socket = Sock; 404 | Py_INCREF(self->Socket); 405 | return self; 406 | fail: 407 | if (errstr) 408 | PyErr_SetString(PySSLErrorObject, errstr); 409 | Py_DECREF(self); 410 | return NULL; 411 | } 412 | 413 | static PyObject * 414 | PySSL_sslwrap(PyObject *self, PyObject *args) 415 | { 416 | PySocketSockObject *Sock; 417 | int server_side = 0; 418 | int verification_mode = PY_SSL_CERT_NONE; 419 | int protocol = PY_SSL_VERSION_SSL23; 420 | char *key_file = NULL; 421 | char *cert_file = NULL; 422 | char *cacerts_file = NULL; 423 | 424 | if (!PyArg_ParseTuple(args, "O!i|zziiz:sslwrap", 425 | PySocketModule.Sock_Type, 426 | &Sock, 427 | &server_side, 428 | &key_file, &cert_file, 429 | &verification_mode, &protocol, 430 | &cacerts_file)) 431 | return NULL; 432 | 433 | /* 434 | fprintf(stderr, 435 | "server_side is %d, keyfile %p, certfile %p, verify_mode %d, " 436 | "protocol %d, certs %p\n", 437 | server_side, key_file, cert_file, verification_mode, 438 | protocol, cacerts_file); 439 | */ 440 | 441 | return (PyObject *) newPySSLObject(Sock, key_file, cert_file, 442 | server_side, verification_mode, 443 | protocol, cacerts_file); 444 | } 445 | 446 | PyDoc_STRVAR(ssl_doc, 447 | "sslwrap(socket, server_side, [keyfile, certfile, certs_mode, protocol,\n" 448 | " cacertsfile]) -> sslobject"); 449 | 450 | /* SSL object methods */ 451 | 452 | static PyObject *PySSL_SSLdo_handshake(PySSLObject *self) 453 | { 454 | int ret; 455 | int err; 456 | int sockstate; 457 | 458 | /* Actually negotiate SSL connection */ 459 | /* XXX If SSL_do_handshake() returns 0, it's also a failure. */ 460 | sockstate = 0; 461 | do { 462 | PySSL_BEGIN_ALLOW_THREADS 463 | ret = SSL_do_handshake(self->ssl); 464 | err = SSL_get_error(self->ssl, ret); 465 | PySSL_END_ALLOW_THREADS 466 | if(PyErr_CheckSignals()) { 467 | return NULL; 468 | } 469 | if (err == SSL_ERROR_WANT_READ) { 470 | sockstate = check_socket_and_wait_for_timeout(self->Socket, 0); 471 | } else if (err == SSL_ERROR_WANT_WRITE) { 472 | sockstate = check_socket_and_wait_for_timeout(self->Socket, 1); 473 | } else { 474 | sockstate = SOCKET_OPERATION_OK; 475 | } 476 | if (sockstate == SOCKET_HAS_TIMED_OUT) { 477 | PyErr_SetString(PySSLErrorObject, 478 | ERRSTR("The handshake operation timed out")); 479 | return NULL; 480 | } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { 481 | PyErr_SetString(PySSLErrorObject, 482 | ERRSTR("Underlying socket has been closed.")); 483 | return NULL; 484 | } else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) { 485 | PyErr_SetString(PySSLErrorObject, 486 | ERRSTR("Underlying socket too large for select().")); 487 | return NULL; 488 | } else if (sockstate == SOCKET_IS_NONBLOCKING) { 489 | break; 490 | } 491 | } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE); 492 | if (ret < 1) 493 | return PySSL_SetError(self, ret, __FILE__, __LINE__); 494 | self->ssl->debug = 1; 495 | 496 | if (self->peer_cert) 497 | X509_free (self->peer_cert); 498 | PySSL_BEGIN_ALLOW_THREADS 499 | if ((self->peer_cert = SSL_get_peer_certificate(self->ssl))) { 500 | X509_NAME_oneline(X509_get_subject_name(self->peer_cert), 501 | self->server, X509_NAME_MAXLEN); 502 | X509_NAME_oneline(X509_get_issuer_name(self->peer_cert), 503 | self->issuer, X509_NAME_MAXLEN); 504 | } 505 | PySSL_END_ALLOW_THREADS 506 | 507 | Py_INCREF(Py_None); 508 | return Py_None; 509 | } 510 | 511 | static PyObject * 512 | PySSL_server(PySSLObject *self) 513 | { 514 | return PyString_FromString(self->server); 515 | } 516 | 517 | static PyObject * 518 | PySSL_issuer(PySSLObject *self) 519 | { 520 | return PyString_FromString(self->issuer); 521 | } 522 | 523 | static PyObject * 524 | _create_tuple_for_attribute (ASN1_OBJECT *name, ASN1_STRING *value) { 525 | 526 | char namebuf[X509_NAME_MAXLEN]; 527 | int buflen; 528 | PyObject *name_obj; 529 | PyObject *value_obj; 530 | PyObject *attr; 531 | unsigned char *valuebuf = NULL; 532 | 533 | buflen = OBJ_obj2txt(namebuf, sizeof(namebuf), name, 0); 534 | if (buflen < 0) { 535 | _setSSLError(NULL, 0, __FILE__, __LINE__); 536 | goto fail; 537 | } 538 | name_obj = PyString_FromStringAndSize(namebuf, buflen); 539 | if (name_obj == NULL) 540 | goto fail; 541 | 542 | buflen = ASN1_STRING_to_UTF8(&valuebuf, value); 543 | if (buflen < 0) { 544 | _setSSLError(NULL, 0, __FILE__, __LINE__); 545 | Py_DECREF(name_obj); 546 | goto fail; 547 | } 548 | value_obj = PyUnicode_DecodeUTF8((char *) valuebuf, 549 | buflen, "strict"); 550 | OPENSSL_free(valuebuf); 551 | if (value_obj == NULL) { 552 | Py_DECREF(name_obj); 553 | goto fail; 554 | } 555 | attr = PyTuple_New(2); 556 | if (attr == NULL) { 557 | Py_DECREF(name_obj); 558 | Py_DECREF(value_obj); 559 | goto fail; 560 | } 561 | PyTuple_SET_ITEM(attr, 0, name_obj); 562 | PyTuple_SET_ITEM(attr, 1, value_obj); 563 | return attr; 564 | 565 | fail: 566 | return NULL; 567 | } 568 | 569 | static PyObject * 570 | _create_tuple_for_X509_NAME (X509_NAME *xname) 571 | { 572 | PyObject *dn = NULL; /* tuple which represents the "distinguished name" */ 573 | PyObject *rdn = NULL; /* tuple to hold a "relative distinguished name" */ 574 | PyObject *rdnt; 575 | PyObject *attr = NULL; /* tuple to hold an attribute */ 576 | int entry_count = X509_NAME_entry_count(xname); 577 | X509_NAME_ENTRY *entry; 578 | ASN1_OBJECT *name; 579 | ASN1_STRING *value; 580 | int index_counter; 581 | int rdn_level = -1; 582 | int retcode; 583 | 584 | dn = PyList_New(0); 585 | if (dn == NULL) 586 | return NULL; 587 | /* now create another tuple to hold the top-level RDN */ 588 | rdn = PyList_New(0); 589 | if (rdn == NULL) 590 | goto fail0; 591 | 592 | for (index_counter = 0; 593 | index_counter < entry_count; 594 | index_counter++) 595 | { 596 | entry = X509_NAME_get_entry(xname, index_counter); 597 | 598 | /* check to see if we've gotten to a new RDN */ 599 | if (rdn_level >= 0) { 600 | if (rdn_level != entry->set) { 601 | /* yes, new RDN */ 602 | /* add old RDN to DN */ 603 | rdnt = PyList_AsTuple(rdn); 604 | Py_DECREF(rdn); 605 | if (rdnt == NULL) 606 | goto fail0; 607 | retcode = PyList_Append(dn, rdnt); 608 | Py_DECREF(rdnt); 609 | if (retcode < 0) 610 | goto fail0; 611 | /* create new RDN */ 612 | rdn = PyList_New(0); 613 | if (rdn == NULL) 614 | goto fail0; 615 | } 616 | } 617 | rdn_level = entry->set; 618 | 619 | /* now add this attribute to the current RDN */ 620 | name = X509_NAME_ENTRY_get_object(entry); 621 | value = X509_NAME_ENTRY_get_data(entry); 622 | attr = _create_tuple_for_attribute(name, value); 623 | /* 624 | fprintf(stderr, "RDN level %d, attribute %s: %s\n", 625 | entry->set, 626 | PyString_AS_STRING(PyTuple_GET_ITEM(attr, 0)), 627 | PyString_AS_STRING(PyTuple_GET_ITEM(attr, 1))); 628 | */ 629 | if (attr == NULL) 630 | goto fail1; 631 | retcode = PyList_Append(rdn, attr); 632 | Py_DECREF(attr); 633 | if (retcode < 0) 634 | goto fail1; 635 | } 636 | /* now, there's typically a dangling RDN */ 637 | if ((rdn != NULL) && (PyList_Size(rdn) > 0)) { 638 | rdnt = PyList_AsTuple(rdn); 639 | Py_DECREF(rdn); 640 | if (rdnt == NULL) 641 | goto fail0; 642 | retcode = PyList_Append(dn, rdnt); 643 | Py_DECREF(rdnt); 644 | if (retcode < 0) 645 | goto fail0; 646 | } 647 | 648 | /* convert list to tuple */ 649 | rdnt = PyList_AsTuple(dn); 650 | Py_DECREF(dn); 651 | if (rdnt == NULL) 652 | return NULL; 653 | return rdnt; 654 | 655 | fail1: 656 | Py_XDECREF(rdn); 657 | 658 | fail0: 659 | Py_XDECREF(dn); 660 | return NULL; 661 | } 662 | 663 | static PyObject * 664 | _get_peer_alt_names (X509 *certificate) { 665 | 666 | /* this code follows the procedure outlined in 667 | OpenSSL's crypto/x509v3/v3_prn.c:X509v3_EXT_print() 668 | function to extract the STACK_OF(GENERAL_NAME), 669 | then iterates through the stack to add the 670 | names. */ 671 | 672 | int i, j; 673 | PyObject *peer_alt_names = Py_None; 674 | PyObject *v, *t; 675 | X509_EXTENSION *ext = NULL; 676 | GENERAL_NAMES *names = NULL; 677 | GENERAL_NAME *name; 678 | X509V3_EXT_METHOD *method; 679 | BIO *biobuf = NULL; 680 | char buf[2048]; 681 | char *vptr; 682 | int len; 683 | unsigned char *p; 684 | 685 | if (certificate == NULL) 686 | return peer_alt_names; 687 | 688 | /* get a memory buffer */ 689 | biobuf = BIO_new(BIO_s_mem()); 690 | 691 | i = 0; 692 | while ((i = X509_get_ext_by_NID( 693 | certificate, NID_subject_alt_name, i)) >= 0) { 694 | 695 | if (peer_alt_names == Py_None) { 696 | peer_alt_names = PyList_New(0); 697 | if (peer_alt_names == NULL) 698 | goto fail; 699 | } 700 | 701 | /* now decode the altName */ 702 | ext = X509_get_ext(certificate, i); 703 | if(!(method = X509V3_EXT_get(ext))) { 704 | PyErr_SetString(PySSLErrorObject, 705 | ERRSTR("No method for internalizing subjectAltName!")); 706 | goto fail; 707 | } 708 | 709 | p = ext->value->data; 710 | if(method->it) 711 | names = (GENERAL_NAMES*) (ASN1_item_d2i(NULL, 712 | (const unsigned char **) (&p), 713 | ext->value->length, 714 | ASN1_ITEM_ptr(method->it))); 715 | else 716 | names = (GENERAL_NAMES*) (method->d2i(NULL, 717 | (const unsigned char **) (&p), 718 | ext->value->length)); 719 | 720 | for(j = 0; j < sk_GENERAL_NAME_num(names); j++) { 721 | 722 | /* get a rendering of each name in the set of names */ 723 | 724 | name = sk_GENERAL_NAME_value(names, j); 725 | if (name->type == GEN_DIRNAME) { 726 | 727 | /* we special-case DirName as a tuple of tuples of attributes */ 728 | 729 | t = PyTuple_New(2); 730 | if (t == NULL) { 731 | goto fail; 732 | } 733 | 734 | v = PyString_FromString("DirName"); 735 | if (v == NULL) { 736 | Py_DECREF(t); 737 | goto fail; 738 | } 739 | PyTuple_SET_ITEM(t, 0, v); 740 | 741 | v = _create_tuple_for_X509_NAME (name->d.dirn); 742 | if (v == NULL) { 743 | Py_DECREF(t); 744 | goto fail; 745 | } 746 | PyTuple_SET_ITEM(t, 1, v); 747 | 748 | } else { 749 | 750 | /* for everything else, we use the OpenSSL print form */ 751 | 752 | (void) BIO_reset(biobuf); 753 | GENERAL_NAME_print(biobuf, name); 754 | len = BIO_gets(biobuf, buf, sizeof(buf)-1); 755 | if (len < 0) { 756 | _setSSLError(NULL, 0, __FILE__, __LINE__); 757 | goto fail; 758 | } 759 | vptr = strchr(buf, ':'); 760 | if (vptr == NULL) 761 | goto fail; 762 | t = PyTuple_New(2); 763 | if (t == NULL) 764 | goto fail; 765 | v = PyString_FromStringAndSize(buf, (vptr - buf)); 766 | if (v == NULL) { 767 | Py_DECREF(t); 768 | goto fail; 769 | } 770 | PyTuple_SET_ITEM(t, 0, v); 771 | v = PyString_FromStringAndSize((vptr + 1), (len - (vptr - buf + 1))); 772 | if (v == NULL) { 773 | Py_DECREF(t); 774 | goto fail; 775 | } 776 | PyTuple_SET_ITEM(t, 1, v); 777 | } 778 | 779 | /* and add that rendering to the list */ 780 | 781 | if (PyList_Append(peer_alt_names, t) < 0) { 782 | Py_DECREF(t); 783 | goto fail; 784 | } 785 | Py_DECREF(t); 786 | } 787 | } 788 | BIO_free(biobuf); 789 | if (peer_alt_names != Py_None) { 790 | v = PyList_AsTuple(peer_alt_names); 791 | Py_DECREF(peer_alt_names); 792 | return v; 793 | } else { 794 | return peer_alt_names; 795 | } 796 | 797 | 798 | fail: 799 | if (biobuf != NULL) 800 | BIO_free(biobuf); 801 | 802 | if (peer_alt_names != Py_None) { 803 | Py_XDECREF(peer_alt_names); 804 | } 805 | 806 | return NULL; 807 | } 808 | 809 | static PyObject * 810 | _decode_certificate (X509 *certificate, int verbose) { 811 | 812 | PyObject *retval = NULL; 813 | BIO *biobuf = NULL; 814 | PyObject *peer; 815 | PyObject *peer_alt_names = NULL; 816 | PyObject *issuer; 817 | PyObject *version; 818 | PyObject *sn_obj; 819 | PyObject *pubkey_obj; 820 | ASN1_INTEGER *serialNumber; 821 | char buf[2048]; 822 | int len; 823 | ASN1_TIME *notBefore, *notAfter; 824 | PyObject *pnotBefore, *pnotAfter; 825 | 826 | retval = PyDict_New(); 827 | if (retval == NULL) 828 | return NULL; 829 | 830 | peer = _create_tuple_for_X509_NAME( 831 | X509_get_subject_name(certificate)); 832 | if (peer == NULL) 833 | goto fail0; 834 | if (PyDict_SetItemString(retval, (const char *) "subject", peer) < 0) { 835 | Py_DECREF(peer); 836 | goto fail0; 837 | } 838 | Py_DECREF(peer); 839 | 840 | if (verbose) { 841 | issuer = _create_tuple_for_X509_NAME( 842 | X509_get_issuer_name(certificate)); 843 | if (issuer == NULL) 844 | goto fail0; 845 | if (PyDict_SetItemString(retval, (const char *)"issuer", issuer) < 0) { 846 | Py_DECREF(issuer); 847 | goto fail0; 848 | } 849 | Py_DECREF(issuer); 850 | 851 | version = PyInt_FromLong(X509_get_version(certificate) + 1); 852 | if (PyDict_SetItemString(retval, "version", version) < 0) { 853 | Py_DECREF(version); 854 | goto fail0; 855 | } 856 | Py_DECREF(version); 857 | } 858 | 859 | /* get a memory buffer */ 860 | biobuf = BIO_new(BIO_s_mem()); 861 | 862 | if (verbose) { 863 | 864 | (void) BIO_reset(biobuf); 865 | serialNumber = X509_get_serialNumber(certificate); 866 | /* should not exceed 20 octets, 160 bits, so buf is big enough */ 867 | i2a_ASN1_INTEGER(biobuf, serialNumber); 868 | len = BIO_gets(biobuf, buf, sizeof(buf)-1); 869 | if (len < 0) { 870 | _setSSLError(NULL, 0, __FILE__, __LINE__); 871 | goto fail1; 872 | } 873 | sn_obj = PyString_FromStringAndSize(buf, len); 874 | if (sn_obj == NULL) 875 | goto fail1; 876 | if (PyDict_SetItemString(retval, "serialNumber", sn_obj) < 0) { 877 | Py_DECREF(sn_obj); 878 | goto fail1; 879 | } 880 | Py_DECREF(sn_obj); 881 | 882 | (void) BIO_reset(biobuf); 883 | notBefore = X509_get_notBefore(certificate); 884 | ASN1_TIME_print(biobuf, notBefore); 885 | len = BIO_gets(biobuf, buf, sizeof(buf)-1); 886 | if (len < 0) { 887 | _setSSLError(NULL, 0, __FILE__, __LINE__); 888 | goto fail1; 889 | } 890 | pnotBefore = PyString_FromStringAndSize(buf, len); 891 | if (pnotBefore == NULL) 892 | goto fail1; 893 | if (PyDict_SetItemString(retval, "notBefore", pnotBefore) < 0) { 894 | Py_DECREF(pnotBefore); 895 | goto fail1; 896 | } 897 | Py_DECREF(pnotBefore); 898 | } 899 | 900 | (void) BIO_reset(biobuf); 901 | notAfter = X509_get_notAfter(certificate); 902 | ASN1_TIME_print(biobuf, notAfter); 903 | len = BIO_gets(biobuf, buf, sizeof(buf)-1); 904 | if (len < 0) { 905 | _setSSLError(NULL, 0, __FILE__, __LINE__); 906 | goto fail1; 907 | } 908 | pnotAfter = PyString_FromStringAndSize(buf, len); 909 | if (pnotAfter == NULL) 910 | goto fail1; 911 | if (PyDict_SetItemString(retval, "notAfter", pnotAfter) < 0) { 912 | Py_DECREF(pnotAfter); 913 | goto fail1; 914 | } 915 | Py_DECREF(pnotAfter); 916 | 917 | /* Now look for subjectAltName */ 918 | 919 | peer_alt_names = _get_peer_alt_names(certificate); 920 | if (peer_alt_names == NULL) 921 | goto fail1; 922 | else if (peer_alt_names != Py_None) { 923 | if (PyDict_SetItemString(retval, "subjectAltName", 924 | peer_alt_names) < 0) { 925 | Py_DECREF(peer_alt_names); 926 | goto fail1; 927 | } 928 | Py_DECREF(peer_alt_names); 929 | } 930 | 931 | /* And get the public key of the subject */ 932 | (void) BIO_reset(biobuf); 933 | EVP_PKEY *key = X509_get_pubkey(certificate); 934 | len = i2d_PUBKEY_bio(biobuf, key); 935 | if (len < 0) { 936 | _setSSLError(NULL, 0, __FILE__, __LINE__); 937 | goto fail1; 938 | } 939 | len = BIO_gets(biobuf, buf, sizeof(buf)-1); 940 | if (len < 0) { 941 | _setSSLError(NULL, 0, __FILE__, __LINE__); 942 | goto fail1; 943 | } 944 | pubkey_obj = PyString_FromStringAndSize(buf, len); 945 | if (pubkey_obj == NULL) 946 | goto fail1; 947 | if (PyDict_SetItemString(retval, "subjectPublicKey", pubkey_obj) < 0) { 948 | Py_DECREF(pubkey_obj); 949 | goto fail1; 950 | } 951 | Py_DECREF(pubkey_obj); 952 | 953 | BIO_free(biobuf); 954 | return retval; 955 | 956 | fail1: 957 | if (biobuf != NULL) 958 | BIO_free(biobuf); 959 | fail0: 960 | Py_XDECREF(retval); 961 | return NULL; 962 | } 963 | 964 | 965 | static PyObject * 966 | PySSL_test_decode_certificate (PyObject *mod, PyObject *args) { 967 | 968 | PyObject *retval = NULL; 969 | char *filename = NULL; 970 | X509 *x=NULL; 971 | BIO *cert; 972 | int verbose = 1; 973 | 974 | if (!PyArg_ParseTuple(args, "s|i:test_decode_certificate", &filename, &verbose)) 975 | return NULL; 976 | 977 | if ((cert=BIO_new(BIO_s_file())) == NULL) { 978 | PyErr_SetString(PySSLErrorObject, "Can't malloc memory to read file"); 979 | goto fail0; 980 | } 981 | 982 | if (BIO_read_filename(cert,filename) <= 0) { 983 | PyErr_SetString(PySSLErrorObject, "Can't open file"); 984 | goto fail0; 985 | } 986 | 987 | x = PEM_read_bio_X509_AUX(cert,NULL, NULL, NULL); 988 | if (x == NULL) { 989 | PyErr_SetString(PySSLErrorObject, "Error decoding PEM-encoded file"); 990 | goto fail0; 991 | } 992 | 993 | retval = _decode_certificate(x, verbose); 994 | 995 | fail0: 996 | 997 | if (cert != NULL) BIO_free(cert); 998 | return retval; 999 | } 1000 | 1001 | 1002 | static PyObject * 1003 | PySSL_peercert(PySSLObject *self, PyObject *args) 1004 | { 1005 | PyObject *retval = NULL; 1006 | int len; 1007 | int verification; 1008 | PyObject *binary_mode = Py_None; 1009 | 1010 | if (!PyArg_ParseTuple(args, "|O:peer_certificate", &binary_mode)) 1011 | return NULL; 1012 | 1013 | if (!self->peer_cert) { 1014 | Py_INCREF(Py_None); 1015 | return Py_None; 1016 | } 1017 | 1018 | if (PyObject_IsTrue(binary_mode)) { 1019 | /* return cert in DER-encoded format */ 1020 | 1021 | unsigned char *bytes_buf = NULL; 1022 | 1023 | bytes_buf = NULL; 1024 | len = i2d_X509(self->peer_cert, &bytes_buf); 1025 | if (len < 0) { 1026 | PySSL_SetError(self, len, __FILE__, __LINE__); 1027 | return NULL; 1028 | } 1029 | retval = PyString_FromStringAndSize((const char *) bytes_buf, len); 1030 | OPENSSL_free(bytes_buf); 1031 | return retval; 1032 | 1033 | } else { 1034 | 1035 | verification = SSL_CTX_get_verify_mode(self->ctx); 1036 | if ((verification & SSL_VERIFY_PEER) == 0) 1037 | return PyDict_New(); 1038 | else 1039 | return _decode_certificate (self->peer_cert, 0); 1040 | } 1041 | } 1042 | 1043 | PyDoc_STRVAR(PySSL_peercert_doc, 1044 | "peer_certificate([der=False]) -> certificate\n\ 1045 | \n\ 1046 | Returns the certificate for the peer. If no certificate was provided,\n\ 1047 | returns None. If a certificate was provided, but not validated, returns\n\ 1048 | an empty dictionary. Otherwise returns a dict containing information\n\ 1049 | about the peer certificate.\n\ 1050 | \n\ 1051 | If the optional argument is True, returns a DER-encoded copy of the\n\ 1052 | peer certificate, or None if no certificate was provided. This will\n\ 1053 | return the certificate even if it wasn't validated."); 1054 | 1055 | static PyObject *PySSL_cipher (PySSLObject *self) { 1056 | 1057 | PyObject *retval, *v; 1058 | SSL_CIPHER *current; 1059 | char *cipher_name; 1060 | char *cipher_protocol; 1061 | 1062 | if (self->ssl == NULL) 1063 | return Py_None; 1064 | current = SSL_get_current_cipher(self->ssl); 1065 | if (current == NULL) 1066 | return Py_None; 1067 | 1068 | retval = PyTuple_New(3); 1069 | if (retval == NULL) 1070 | return NULL; 1071 | 1072 | cipher_name = (char *) SSL_CIPHER_get_name(current); 1073 | if (cipher_name == NULL) { 1074 | PyTuple_SET_ITEM(retval, 0, Py_None); 1075 | } else { 1076 | v = PyString_FromString(cipher_name); 1077 | if (v == NULL) 1078 | goto fail0; 1079 | PyTuple_SET_ITEM(retval, 0, v); 1080 | } 1081 | cipher_protocol = SSL_CIPHER_get_version(current); 1082 | if (cipher_protocol == NULL) { 1083 | PyTuple_SET_ITEM(retval, 1, Py_None); 1084 | } else { 1085 | v = PyString_FromString(cipher_protocol); 1086 | if (v == NULL) 1087 | goto fail0; 1088 | PyTuple_SET_ITEM(retval, 1, v); 1089 | } 1090 | v = PyInt_FromLong(SSL_CIPHER_get_bits(current, NULL)); 1091 | if (v == NULL) 1092 | goto fail0; 1093 | PyTuple_SET_ITEM(retval, 2, v); 1094 | return retval; 1095 | 1096 | fail0: 1097 | Py_DECREF(retval); 1098 | return NULL; 1099 | } 1100 | 1101 | static void PySSL_dealloc(PySSLObject *self) 1102 | { 1103 | if (self->peer_cert) /* Possible not to have one? */ 1104 | X509_free (self->peer_cert); 1105 | if (self->ssl) 1106 | SSL_free(self->ssl); 1107 | if (self->ctx) 1108 | SSL_CTX_free(self->ctx); 1109 | Py_XDECREF(self->Socket); 1110 | PyObject_Del(self); 1111 | } 1112 | 1113 | /* If the socket has a timeout, do a select()/poll() on the socket. 1114 | The argument writing indicates the direction. 1115 | Returns one of the possibilities in the timeout_state enum (above). 1116 | */ 1117 | 1118 | static int 1119 | check_socket_and_wait_for_timeout(PySocketSockObject *s, int writing) 1120 | { 1121 | fd_set fds; 1122 | struct timeval tv; 1123 | int rc; 1124 | 1125 | /* Nothing to do unless we're in timeout mode (not non-blocking) */ 1126 | if (s->sock_timeout < 0.0) 1127 | return SOCKET_IS_BLOCKING; 1128 | else if (s->sock_timeout == 0.0) 1129 | return SOCKET_IS_NONBLOCKING; 1130 | 1131 | /* Guard against closed socket */ 1132 | if (s->sock_fd < 0) 1133 | return SOCKET_HAS_BEEN_CLOSED; 1134 | 1135 | /* Prefer poll, if available, since you can poll() any fd 1136 | * which can't be done with select(). */ 1137 | #ifdef HAVE_POLL 1138 | { 1139 | struct pollfd pollfd; 1140 | int timeout; 1141 | 1142 | pollfd.fd = s->sock_fd; 1143 | pollfd.events = writing ? POLLOUT : POLLIN; 1144 | 1145 | /* s->sock_timeout is in seconds, timeout in ms */ 1146 | timeout = (int)(s->sock_timeout * 1000 + 0.5); 1147 | PySSL_BEGIN_ALLOW_THREADS 1148 | rc = poll(&pollfd, 1, timeout); 1149 | PySSL_END_ALLOW_THREADS 1150 | 1151 | goto normal_return; 1152 | } 1153 | #endif 1154 | 1155 | /* Guard against socket too large for select*/ 1156 | #ifndef Py_SOCKET_FD_CAN_BE_GE_FD_SETSIZE 1157 | if (s->sock_fd >= FD_SETSIZE) 1158 | return SOCKET_TOO_LARGE_FOR_SELECT; 1159 | #endif 1160 | 1161 | /* Construct the arguments to select */ 1162 | tv.tv_sec = (int)s->sock_timeout; 1163 | tv.tv_usec = (int)((s->sock_timeout - tv.tv_sec) * 1e6); 1164 | FD_ZERO(&fds); 1165 | FD_SET(s->sock_fd, &fds); 1166 | 1167 | /* See if the socket is ready */ 1168 | PySSL_BEGIN_ALLOW_THREADS 1169 | if (writing) 1170 | rc = select(s->sock_fd+1, NULL, &fds, NULL, &tv); 1171 | else 1172 | rc = select(s->sock_fd+1, &fds, NULL, NULL, &tv); 1173 | PySSL_END_ALLOW_THREADS 1174 | 1175 | #ifdef HAVE_POLL 1176 | normal_return: 1177 | #endif 1178 | /* Return SOCKET_TIMED_OUT on timeout, SOCKET_OPERATION_OK otherwise 1179 | (when we are able to write or when there's something to read) */ 1180 | return rc == 0 ? SOCKET_HAS_TIMED_OUT : SOCKET_OPERATION_OK; 1181 | } 1182 | 1183 | static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args) 1184 | { 1185 | char *data; 1186 | int len; 1187 | int count; 1188 | int sockstate; 1189 | int err; 1190 | int nonblocking; 1191 | 1192 | if (!PyArg_ParseTuple(args, "s#:write", &data, &count)) 1193 | return NULL; 1194 | 1195 | /* just in case the blocking state of the socket has been changed */ 1196 | nonblocking = (self->Socket->sock_timeout >= 0.0); 1197 | BIO_set_nbio(SSL_get_rbio(self->ssl), nonblocking); 1198 | BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking); 1199 | 1200 | sockstate = check_socket_and_wait_for_timeout(self->Socket, 1); 1201 | if (sockstate == SOCKET_HAS_TIMED_OUT) { 1202 | PyErr_SetString(PySSLErrorObject, 1203 | "The write operation timed out"); 1204 | return NULL; 1205 | } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { 1206 | PyErr_SetString(PySSLErrorObject, 1207 | "Underlying socket has been closed."); 1208 | return NULL; 1209 | } else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) { 1210 | PyErr_SetString(PySSLErrorObject, 1211 | "Underlying socket too large for select()."); 1212 | return NULL; 1213 | } 1214 | do { 1215 | err = 0; 1216 | PySSL_BEGIN_ALLOW_THREADS 1217 | len = SSL_write(self->ssl, data, count); 1218 | err = SSL_get_error(self->ssl, len); 1219 | PySSL_END_ALLOW_THREADS 1220 | if(PyErr_CheckSignals()) { 1221 | return NULL; 1222 | } 1223 | if (err == SSL_ERROR_WANT_READ) { 1224 | sockstate = 1225 | check_socket_and_wait_for_timeout(self->Socket, 0); 1226 | } else if (err == SSL_ERROR_WANT_WRITE) { 1227 | sockstate = 1228 | check_socket_and_wait_for_timeout(self->Socket, 1); 1229 | } else { 1230 | sockstate = SOCKET_OPERATION_OK; 1231 | } 1232 | if (sockstate == SOCKET_HAS_TIMED_OUT) { 1233 | PyErr_SetString(PySSLErrorObject, 1234 | "The write operation timed out"); 1235 | return NULL; 1236 | } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { 1237 | PyErr_SetString(PySSLErrorObject, 1238 | "Underlying socket has been closed."); 1239 | return NULL; 1240 | } else if (sockstate == SOCKET_IS_NONBLOCKING) { 1241 | break; 1242 | } 1243 | } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE); 1244 | if (len > 0) 1245 | return PyInt_FromLong(len); 1246 | else 1247 | return PySSL_SetError(self, len, __FILE__, __LINE__); 1248 | } 1249 | 1250 | PyDoc_STRVAR(PySSL_SSLwrite_doc, 1251 | "write(s) -> len\n\ 1252 | \n\ 1253 | Writes the string s into the SSL object. Returns the number\n\ 1254 | of bytes written."); 1255 | 1256 | static PyObject *PySSL_SSLpending(PySSLObject *self) 1257 | { 1258 | int count = 0; 1259 | 1260 | PySSL_BEGIN_ALLOW_THREADS 1261 | count = SSL_pending(self->ssl); 1262 | PySSL_END_ALLOW_THREADS 1263 | if (count < 0) 1264 | return PySSL_SetError(self, count, __FILE__, __LINE__); 1265 | else 1266 | return PyInt_FromLong(count); 1267 | } 1268 | 1269 | PyDoc_STRVAR(PySSL_SSLpending_doc, 1270 | "pending() -> count\n\ 1271 | \n\ 1272 | Returns the number of already decrypted bytes available for read,\n\ 1273 | pending on the connection.\n"); 1274 | 1275 | static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args) 1276 | { 1277 | PyObject *buf; 1278 | int count = 0; 1279 | int len = 1024; 1280 | int sockstate; 1281 | int err; 1282 | int nonblocking; 1283 | 1284 | if (!PyArg_ParseTuple(args, "|i:read", &len)) 1285 | return NULL; 1286 | 1287 | if (!(buf = PyString_FromStringAndSize((char *) 0, len))) 1288 | return NULL; 1289 | 1290 | /* just in case the blocking state of the socket has been changed */ 1291 | nonblocking = (self->Socket->sock_timeout >= 0.0); 1292 | BIO_set_nbio(SSL_get_rbio(self->ssl), nonblocking); 1293 | BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking); 1294 | 1295 | /* first check if there are bytes ready to be read */ 1296 | PySSL_BEGIN_ALLOW_THREADS 1297 | count = SSL_pending(self->ssl); 1298 | PySSL_END_ALLOW_THREADS 1299 | 1300 | if (!count) { 1301 | sockstate = check_socket_and_wait_for_timeout(self->Socket, 0); 1302 | if (sockstate == SOCKET_HAS_TIMED_OUT) { 1303 | PyErr_SetString(PySSLErrorObject, 1304 | "The read operation timed out"); 1305 | Py_DECREF(buf); 1306 | return NULL; 1307 | } else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) { 1308 | PyErr_SetString(PySSLErrorObject, 1309 | "Underlying socket too large for select()."); 1310 | Py_DECREF(buf); 1311 | return NULL; 1312 | } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { 1313 | if (SSL_get_shutdown(self->ssl) != 1314 | SSL_RECEIVED_SHUTDOWN) 1315 | { 1316 | Py_DECREF(buf); 1317 | PyErr_SetString(PySSLErrorObject, 1318 | "Socket closed without SSL shutdown handshake"); 1319 | return NULL; 1320 | } else { 1321 | /* should contain a zero-length string */ 1322 | _PyString_Resize(&buf, 0); 1323 | return buf; 1324 | } 1325 | } 1326 | } 1327 | do { 1328 | err = 0; 1329 | PySSL_BEGIN_ALLOW_THREADS 1330 | count = SSL_read(self->ssl, PyString_AsString(buf), len); 1331 | err = SSL_get_error(self->ssl, count); 1332 | PySSL_END_ALLOW_THREADS 1333 | if(PyErr_CheckSignals()) { 1334 | Py_DECREF(buf); 1335 | return NULL; 1336 | } 1337 | if (err == SSL_ERROR_WANT_READ) { 1338 | sockstate = 1339 | check_socket_and_wait_for_timeout(self->Socket, 0); 1340 | } else if (err == SSL_ERROR_WANT_WRITE) { 1341 | sockstate = 1342 | check_socket_and_wait_for_timeout(self->Socket, 1); 1343 | } else if ((err == SSL_ERROR_ZERO_RETURN) && 1344 | (SSL_get_shutdown(self->ssl) == 1345 | SSL_RECEIVED_SHUTDOWN)) 1346 | { 1347 | _PyString_Resize(&buf, 0); 1348 | return buf; 1349 | } else { 1350 | sockstate = SOCKET_OPERATION_OK; 1351 | } 1352 | if (sockstate == SOCKET_HAS_TIMED_OUT) { 1353 | PyErr_SetString(PySSLErrorObject, 1354 | "The read operation timed out"); 1355 | Py_DECREF(buf); 1356 | return NULL; 1357 | } else if (sockstate == SOCKET_IS_NONBLOCKING) { 1358 | break; 1359 | } 1360 | } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE); 1361 | if (count <= 0) { 1362 | Py_DECREF(buf); 1363 | return PySSL_SetError(self, count, __FILE__, __LINE__); 1364 | } 1365 | if (count != len) 1366 | _PyString_Resize(&buf, count); 1367 | return buf; 1368 | } 1369 | 1370 | PyDoc_STRVAR(PySSL_SSLread_doc, 1371 | "read([len]) -> string\n\ 1372 | \n\ 1373 | Read up to len bytes from the SSL socket."); 1374 | 1375 | static PyObject *PySSL_SSLshutdown(PySSLObject *self) 1376 | { 1377 | int err; 1378 | 1379 | /* Guard against closed socket */ 1380 | if (self->Socket->sock_fd < 0) { 1381 | PyErr_SetString(PySSLErrorObject, 1382 | "Underlying socket has been closed."); 1383 | return NULL; 1384 | } 1385 | 1386 | PySSL_BEGIN_ALLOW_THREADS 1387 | err = SSL_shutdown(self->ssl); 1388 | if (err == 0) { 1389 | /* we need to call it again to finish the shutdown */ 1390 | err = SSL_shutdown(self->ssl); 1391 | } 1392 | PySSL_END_ALLOW_THREADS 1393 | 1394 | if (err < 0) 1395 | return PySSL_SetError(self, err, __FILE__, __LINE__); 1396 | else { 1397 | Py_INCREF(self->Socket); 1398 | return (PyObject *) (self->Socket); 1399 | } 1400 | } 1401 | 1402 | PyDoc_STRVAR(PySSL_SSLshutdown_doc, 1403 | "shutdown(s) -> socket\n\ 1404 | \n\ 1405 | Does the SSL shutdown handshake with the remote end, and returns\n\ 1406 | the underlying socket object."); 1407 | 1408 | static PyMethodDef PySSLMethods[] = { 1409 | {"do_handshake", (PyCFunction)PySSL_SSLdo_handshake, METH_NOARGS}, 1410 | {"write", (PyCFunction)PySSL_SSLwrite, METH_VARARGS, 1411 | PySSL_SSLwrite_doc}, 1412 | {"read", (PyCFunction)PySSL_SSLread, METH_VARARGS, 1413 | PySSL_SSLread_doc}, 1414 | {"pending", (PyCFunction)PySSL_SSLpending, METH_NOARGS, 1415 | PySSL_SSLpending_doc}, 1416 | {"server", (PyCFunction)PySSL_server, METH_NOARGS}, 1417 | {"issuer", (PyCFunction)PySSL_issuer, METH_NOARGS}, 1418 | {"peer_certificate", (PyCFunction)PySSL_peercert, METH_VARARGS, 1419 | PySSL_peercert_doc}, 1420 | {"cipher", (PyCFunction)PySSL_cipher, METH_NOARGS}, 1421 | {"shutdown", (PyCFunction)PySSL_SSLshutdown, METH_NOARGS, 1422 | PySSL_SSLshutdown_doc}, 1423 | {NULL, NULL} 1424 | }; 1425 | 1426 | static PyObject *PySSL_getattr(PySSLObject *self, char *name) 1427 | { 1428 | return Py_FindMethod(PySSLMethods, (PyObject *)self, name); 1429 | } 1430 | 1431 | static PyTypeObject PySSL_Type = { 1432 | PyObject_HEAD_INIT(NULL) 1433 | 0, 1434 | "_ssl2.SSLContext", /*tp_name*/ 1435 | sizeof(PySSLObject), /*tp_basicsize*/ 1436 | 0, /*tp_itemsize*/ 1437 | /* methods */ 1438 | (destructor)PySSL_dealloc, /*tp_dealloc*/ 1439 | 0, /*tp_print*/ 1440 | (getattrfunc)PySSL_getattr, /*tp_getattr*/ 1441 | 0, /*tp_setattr*/ 1442 | 0, /*tp_compare*/ 1443 | 0, /*tp_repr*/ 1444 | 0, /*tp_as_number*/ 1445 | 0, /*tp_as_sequence*/ 1446 | 0, /*tp_as_mapping*/ 1447 | 0, /*tp_hash*/ 1448 | }; 1449 | 1450 | #ifdef HAVE_OPENSSL_RAND 1451 | 1452 | /* helper routines for seeding the SSL PRNG */ 1453 | static PyObject * 1454 | PySSL_RAND_add(PyObject *self, PyObject *args) 1455 | { 1456 | char *buf; 1457 | int len; 1458 | double entropy; 1459 | 1460 | if (!PyArg_ParseTuple(args, "s#d:RAND_add", &buf, &len, &entropy)) 1461 | return NULL; 1462 | RAND_add(buf, len, entropy); 1463 | Py_INCREF(Py_None); 1464 | return Py_None; 1465 | } 1466 | 1467 | PyDoc_STRVAR(PySSL_RAND_add_doc, 1468 | "RAND_add(string, entropy)\n\ 1469 | \n\ 1470 | Mix string into the OpenSSL PRNG state. entropy (a float) is a lower\n\ 1471 | bound on the entropy contained in string. See RFC 1750."); 1472 | 1473 | static PyObject * 1474 | PySSL_RAND_status(PyObject *self) 1475 | { 1476 | return PyInt_FromLong(RAND_status()); 1477 | } 1478 | 1479 | PyDoc_STRVAR(PySSL_RAND_status_doc, 1480 | "RAND_status() -> 0 or 1\n\ 1481 | \n\ 1482 | Returns 1 if the OpenSSL PRNG has been seeded with enough data and 0 if not.\n\ 1483 | It is necessary to seed the PRNG with RAND_add() on some platforms before\n\ 1484 | using the ssl() function."); 1485 | 1486 | static PyObject * 1487 | PySSL_RAND_egd(PyObject *self, PyObject *arg) 1488 | { 1489 | int bytes; 1490 | 1491 | if (!PyString_Check(arg)) 1492 | return PyErr_Format(PyExc_TypeError, 1493 | "RAND_egd() expected string, found %s", 1494 | Py_Type(arg)->tp_name); 1495 | bytes = RAND_egd(PyString_AS_STRING(arg)); 1496 | if (bytes == -1) { 1497 | PyErr_SetString(PySSLErrorObject, 1498 | "EGD connection failed or EGD did not return " 1499 | "enough data to seed the PRNG"); 1500 | return NULL; 1501 | } 1502 | return PyInt_FromLong(bytes); 1503 | } 1504 | 1505 | PyDoc_STRVAR(PySSL_RAND_egd_doc, 1506 | "RAND_egd(path) -> bytes\n\ 1507 | \n\ 1508 | Queries the entropy gather daemon (EGD) on the socket named by 'path'.\n\ 1509 | Returns number of bytes read. Raises SSLError if connection to EGD\n\ 1510 | fails or if it does provide enough data to seed PRNG."); 1511 | 1512 | #endif 1513 | 1514 | /* List of functions exported by this module. */ 1515 | 1516 | static PyMethodDef PySSL_methods[] = { 1517 | {"sslwrap", PySSL_sslwrap, 1518 | METH_VARARGS, ssl_doc}, 1519 | {"_test_decode_cert", PySSL_test_decode_certificate, 1520 | METH_VARARGS}, 1521 | #ifdef HAVE_OPENSSL_RAND 1522 | {"RAND_add", PySSL_RAND_add, METH_VARARGS, 1523 | PySSL_RAND_add_doc}, 1524 | {"RAND_egd", PySSL_RAND_egd, METH_O, 1525 | PySSL_RAND_egd_doc}, 1526 | {"RAND_status", (PyCFunction)PySSL_RAND_status, METH_NOARGS, 1527 | PySSL_RAND_status_doc}, 1528 | #endif 1529 | {NULL, NULL} /* Sentinel */ 1530 | }; 1531 | 1532 | 1533 | #ifdef WITH_THREAD 1534 | 1535 | /* an implementation of OpenSSL threading operations in terms 1536 | of the Python C thread library */ 1537 | 1538 | static PyThread_type_lock *_ssl_locks = NULL; 1539 | 1540 | static unsigned long _ssl_thread_id_function (void) { 1541 | return PyThread_get_thread_ident(); 1542 | } 1543 | 1544 | static void _ssl_thread_locking_function (int mode, int n, const char *file, int line) { 1545 | /* this function is needed to perform locking on shared data 1546 | structures. (Note that OpenSSL uses a number of global data 1547 | structures that will be implicitly shared whenever multiple threads 1548 | use OpenSSL.) Multi-threaded applications will crash at random if 1549 | it is not set. 1550 | 1551 | locking_function() must be able to handle up to CRYPTO_num_locks() 1552 | different mutex locks. It sets the n-th lock if mode & CRYPTO_LOCK, and 1553 | releases it otherwise. 1554 | 1555 | file and line are the file number of the function setting the 1556 | lock. They can be useful for debugging. 1557 | */ 1558 | 1559 | if ((_ssl_locks == NULL) || 1560 | (n < 0) || (n >= _ssl_locks_count)) 1561 | return; 1562 | 1563 | if (mode & CRYPTO_LOCK) { 1564 | PyThread_acquire_lock(_ssl_locks[n], 1); 1565 | } else { 1566 | PyThread_release_lock(_ssl_locks[n]); 1567 | } 1568 | } 1569 | 1570 | static int _setup_ssl_threads(void) { 1571 | 1572 | int i; 1573 | 1574 | if (_ssl_locks == NULL) { 1575 | _ssl_locks_count = CRYPTO_num_locks(); 1576 | _ssl_locks = (PyThread_type_lock *) 1577 | malloc(sizeof(PyThread_type_lock) * _ssl_locks_count); 1578 | if (_ssl_locks == NULL) 1579 | return 0; 1580 | memset(_ssl_locks, 0, sizeof(PyThread_type_lock) * _ssl_locks_count); 1581 | for (i = 0; i < _ssl_locks_count; i++) { 1582 | _ssl_locks[i] = PyThread_allocate_lock(); 1583 | if (_ssl_locks[i] == NULL) { 1584 | int j; 1585 | for (j = 0; j < i; j++) { 1586 | PyThread_free_lock(_ssl_locks[j]); 1587 | } 1588 | free(_ssl_locks); 1589 | return 0; 1590 | } 1591 | } 1592 | CRYPTO_set_locking_callback(_ssl_thread_locking_function); 1593 | CRYPTO_set_id_callback(_ssl_thread_id_function); 1594 | } 1595 | return 1; 1596 | } 1597 | 1598 | #endif /* def HAVE_THREAD */ 1599 | 1600 | PyDoc_STRVAR(module_doc, 1601 | "Implementation module for SSL socket operations. See the socket module\n\ 1602 | for documentation."); 1603 | 1604 | PyMODINIT_FUNC 1605 | init_ssl2(void) 1606 | { 1607 | PyObject *m, *d; 1608 | PyObject *socket_error = NULL; 1609 | 1610 | Py_Type(&PySSL_Type) = &PyType_Type; 1611 | 1612 | /* Load _socket module and its C API */ 1613 | if (PySocketModule_ImportModuleAndAPI()) 1614 | return; 1615 | 1616 | /* get the socket error object to subtype */ 1617 | m = PyImport_ImportModule("_socket"); 1618 | if (m == NULL) 1619 | return; 1620 | d = PyModule_GetDict(m); 1621 | if (d == NULL) 1622 | return; 1623 | socket_error = PyMapping_GetItemString(d, "error"); 1624 | if (socket_error == NULL) 1625 | return; 1626 | Py_INCREF(socket_error); 1627 | 1628 | m = Py_InitModule3("_ssl2", PySSL_methods, module_doc); 1629 | if (m == NULL) 1630 | return; 1631 | d = PyModule_GetDict(m); 1632 | if (d == NULL) 1633 | return; 1634 | 1635 | /* Init OpenSSL */ 1636 | SSL_load_error_strings(); 1637 | #ifdef WITH_THREAD 1638 | /* note that this will start threading if not already started */ 1639 | if (!_setup_ssl_threads()) { 1640 | return; 1641 | } 1642 | #endif 1643 | SSLeay_add_ssl_algorithms(); 1644 | 1645 | /* Add symbols to module dict */ 1646 | PySSLErrorObject = PyErr_NewException("ssl.SSLError", 1647 | socket_error, 1648 | NULL); 1649 | if (PySSLErrorObject == NULL) 1650 | return; 1651 | if (PyDict_SetItemString(d, "SSLError", PySSLErrorObject) != 0) 1652 | return; 1653 | if (PyDict_SetItemString(d, "SSLType", 1654 | (PyObject *)&PySSL_Type) != 0) 1655 | return; 1656 | PyModule_AddIntConstant(m, "SSL_ERROR_ZERO_RETURN", 1657 | PY_SSL_ERROR_ZERO_RETURN); 1658 | PyModule_AddIntConstant(m, "SSL_ERROR_WANT_READ", 1659 | PY_SSL_ERROR_WANT_READ); 1660 | PyModule_AddIntConstant(m, "SSL_ERROR_WANT_WRITE", 1661 | PY_SSL_ERROR_WANT_WRITE); 1662 | PyModule_AddIntConstant(m, "SSL_ERROR_WANT_X509_LOOKUP", 1663 | PY_SSL_ERROR_WANT_X509_LOOKUP); 1664 | PyModule_AddIntConstant(m, "SSL_ERROR_SYSCALL", 1665 | PY_SSL_ERROR_SYSCALL); 1666 | PyModule_AddIntConstant(m, "SSL_ERROR_SSL", 1667 | PY_SSL_ERROR_SSL); 1668 | PyModule_AddIntConstant(m, "SSL_ERROR_WANT_CONNECT", 1669 | PY_SSL_ERROR_WANT_CONNECT); 1670 | /* non ssl.h errorcodes */ 1671 | PyModule_AddIntConstant(m, "SSL_ERROR_EOF", 1672 | PY_SSL_ERROR_EOF); 1673 | PyModule_AddIntConstant(m, "SSL_ERROR_INVALID_ERROR_CODE", 1674 | PY_SSL_ERROR_INVALID_ERROR_CODE); 1675 | /* cert requirements */ 1676 | PyModule_AddIntConstant(m, "CERT_NONE", 1677 | PY_SSL_CERT_NONE); 1678 | PyModule_AddIntConstant(m, "CERT_OPTIONAL", 1679 | PY_SSL_CERT_OPTIONAL); 1680 | PyModule_AddIntConstant(m, "CERT_REQUIRED", 1681 | PY_SSL_CERT_REQUIRED); 1682 | 1683 | /* protocol versions */ 1684 | PyModule_AddIntConstant(m, "PROTOCOL_SSLv2", 1685 | PY_SSL_VERSION_SSL2); 1686 | PyModule_AddIntConstant(m, "PROTOCOL_SSLv3", 1687 | PY_SSL_VERSION_SSL3); 1688 | PyModule_AddIntConstant(m, "PROTOCOL_SSLv23", 1689 | PY_SSL_VERSION_SSL23); 1690 | PyModule_AddIntConstant(m, "PROTOCOL_TLSv1", 1691 | PY_SSL_VERSION_TLS1); 1692 | PyModule_AddIntConstant(m, "PROTOCOL_NOSSLv2", 1693 | PY_SSL_VERSION_NOSSL2); 1694 | } 1695 | -------------------------------------------------------------------------------- /test/badcert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICXwIBAAKBgQC8ddrhm+LutBvjYcQlnH21PPIseJ1JVG2HMmN2CmZk2YukO+9L 3 | opdJhTvbGfEj0DQs1IE8M+kTUyOmuKfVrFMKwtVeCJphrAnhoz7TYOuLBSqt7lVH 4 | fhi/VwovESJlaBOp+WMnfhcduPEYHYx/6cnVapIkZnLt30zu2um+DzA9jQIDAQAB 5 | AoGBAK0FZpaKj6WnJZN0RqhhK+ggtBWwBnc0U/ozgKz2j1s3fsShYeiGtW6CK5nU 6 | D1dZ5wzhbGThI7LiOXDvRucc9n7vUgi0alqPQ/PFodPxAN/eEYkmXQ7W2k7zwsDA 7 | IUK0KUhktQbLu8qF/m8qM86ba9y9/9YkXuQbZ3COl5ahTZrhAkEA301P08RKv3KM 8 | oXnGU2UHTuJ1MAD2hOrPxjD4/wxA/39EWG9bZczbJyggB4RHu0I3NOSFjAm3HQm0 9 | ANOu5QK9owJBANgOeLfNNcF4pp+UikRFqxk5hULqRAWzVxVrWe85FlPm0VVmHbb/ 10 | loif7mqjU8o1jTd/LM7RD9f2usZyE2psaw8CQQCNLhkpX3KO5kKJmS9N7JMZSc4j 11 | oog58yeYO8BBqKKzpug0LXuQultYv2K4veaIO04iL9VLe5z9S/Q1jaCHBBuXAkEA 12 | z8gjGoi1AOp6PBBLZNsncCvcV/0aC+1se4HxTNo2+duKSDnbq+ljqOM+E7odU+Nq 13 | ewvIWOG//e8fssd0mq3HywJBAJ8l/c8GVmrpFTx8r/nZ2Pyyjt3dH1widooDXYSV 14 | q6Gbf41Llo5sYAtmxdndTLASuHKecacTgZVhy0FryZpLKrU= 15 | -----END RSA PRIVATE KEY----- 16 | -----BEGIN CERTIFICATE----- 17 | Just bad cert data 18 | -----END CERTIFICATE----- 19 | -----BEGIN RSA PRIVATE KEY----- 20 | MIICXwIBAAKBgQC8ddrhm+LutBvjYcQlnH21PPIseJ1JVG2HMmN2CmZk2YukO+9L 21 | opdJhTvbGfEj0DQs1IE8M+kTUyOmuKfVrFMKwtVeCJphrAnhoz7TYOuLBSqt7lVH 22 | fhi/VwovESJlaBOp+WMnfhcduPEYHYx/6cnVapIkZnLt30zu2um+DzA9jQIDAQAB 23 | AoGBAK0FZpaKj6WnJZN0RqhhK+ggtBWwBnc0U/ozgKz2j1s3fsShYeiGtW6CK5nU 24 | D1dZ5wzhbGThI7LiOXDvRucc9n7vUgi0alqPQ/PFodPxAN/eEYkmXQ7W2k7zwsDA 25 | IUK0KUhktQbLu8qF/m8qM86ba9y9/9YkXuQbZ3COl5ahTZrhAkEA301P08RKv3KM 26 | oXnGU2UHTuJ1MAD2hOrPxjD4/wxA/39EWG9bZczbJyggB4RHu0I3NOSFjAm3HQm0 27 | ANOu5QK9owJBANgOeLfNNcF4pp+UikRFqxk5hULqRAWzVxVrWe85FlPm0VVmHbb/ 28 | loif7mqjU8o1jTd/LM7RD9f2usZyE2psaw8CQQCNLhkpX3KO5kKJmS9N7JMZSc4j 29 | oog58yeYO8BBqKKzpug0LXuQultYv2K4veaIO04iL9VLe5z9S/Q1jaCHBBuXAkEA 30 | z8gjGoi1AOp6PBBLZNsncCvcV/0aC+1se4HxTNo2+duKSDnbq+ljqOM+E7odU+Nq 31 | ewvIWOG//e8fssd0mq3HywJBAJ8l/c8GVmrpFTx8r/nZ2Pyyjt3dH1widooDXYSV 32 | q6Gbf41Llo5sYAtmxdndTLASuHKecacTgZVhy0FryZpLKrU= 33 | -----END RSA PRIVATE KEY----- 34 | -----BEGIN CERTIFICATE----- 35 | Just bad cert data 36 | -----END CERTIFICATE----- 37 | -------------------------------------------------------------------------------- /test/badkey.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | Bad Key, though the cert should be OK 3 | -----END RSA PRIVATE KEY----- 4 | -----BEGIN CERTIFICATE----- 5 | MIICpzCCAhCgAwIBAgIJAP+qStv1cIGNMA0GCSqGSIb3DQEBBQUAMIGJMQswCQYD 6 | VQQGEwJVUzERMA8GA1UECBMIRGVsYXdhcmUxEzARBgNVBAcTCldpbG1pbmd0b24x 7 | IzAhBgNVBAoTGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0aW9uMQwwCgYDVQQLEwNT 8 | U0wxHzAdBgNVBAMTFnNvbWVtYWNoaW5lLnB5dGhvbi5vcmcwHhcNMDcwODI3MTY1 9 | NDUwWhcNMTMwMjE2MTY1NDUwWjCBiTELMAkGA1UEBhMCVVMxETAPBgNVBAgTCERl 10 | bGF3YXJlMRMwEQYDVQQHEwpXaWxtaW5ndG9uMSMwIQYDVQQKExpQeXRob24gU29m 11 | dHdhcmUgRm91bmRhdGlvbjEMMAoGA1UECxMDU1NMMR8wHQYDVQQDExZzb21lbWFj 12 | aGluZS5weXRob24ub3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8ddrh 13 | m+LutBvjYcQlnH21PPIseJ1JVG2HMmN2CmZk2YukO+9LopdJhTvbGfEj0DQs1IE8 14 | M+kTUyOmuKfVrFMKwtVeCJphrAnhoz7TYOuLBSqt7lVHfhi/VwovESJlaBOp+WMn 15 | fhcduPEYHYx/6cnVapIkZnLt30zu2um+DzA9jQIDAQABoxUwEzARBglghkgBhvhC 16 | AQEEBAMCBkAwDQYJKoZIhvcNAQEFBQADgYEAF4Q5BVqmCOLv1n8je/Jw9K669VXb 17 | 08hyGzQhkemEBYQd6fzQ9A/1ZzHkJKb1P6yreOLSEh4KcxYPyrLRC1ll8nr5OlCx 18 | CMhKkTnR6qBsdNV0XtdU2+N25hqW+Ma4ZeqsN/iiJVCGNOZGnvQuvCAGWF8+J/f/ 19 | iHkC6gGdBJhogs4= 20 | -----END CERTIFICATE----- 21 | -----BEGIN RSA PRIVATE KEY----- 22 | Bad Key, though the cert should be OK 23 | -----END RSA PRIVATE KEY----- 24 | -----BEGIN CERTIFICATE----- 25 | MIICpzCCAhCgAwIBAgIJAP+qStv1cIGNMA0GCSqGSIb3DQEBBQUAMIGJMQswCQYD 26 | VQQGEwJVUzERMA8GA1UECBMIRGVsYXdhcmUxEzARBgNVBAcTCldpbG1pbmd0b24x 27 | IzAhBgNVBAoTGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0aW9uMQwwCgYDVQQLEwNT 28 | U0wxHzAdBgNVBAMTFnNvbWVtYWNoaW5lLnB5dGhvbi5vcmcwHhcNMDcwODI3MTY1 29 | NDUwWhcNMTMwMjE2MTY1NDUwWjCBiTELMAkGA1UEBhMCVVMxETAPBgNVBAgTCERl 30 | bGF3YXJlMRMwEQYDVQQHEwpXaWxtaW5ndG9uMSMwIQYDVQQKExpQeXRob24gU29m 31 | dHdhcmUgRm91bmRhdGlvbjEMMAoGA1UECxMDU1NMMR8wHQYDVQQDExZzb21lbWFj 32 | aGluZS5weXRob24ub3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8ddrh 33 | m+LutBvjYcQlnH21PPIseJ1JVG2HMmN2CmZk2YukO+9LopdJhTvbGfEj0DQs1IE8 34 | M+kTUyOmuKfVrFMKwtVeCJphrAnhoz7TYOuLBSqt7lVHfhi/VwovESJlaBOp+WMn 35 | fhcduPEYHYx/6cnVapIkZnLt30zu2um+DzA9jQIDAQABoxUwEzARBglghkgBhvhC 36 | AQEEBAMCBkAwDQYJKoZIhvcNAQEFBQADgYEAF4Q5BVqmCOLv1n8je/Jw9K669VXb 37 | 08hyGzQhkemEBYQd6fzQ9A/1ZzHkJKb1P6yreOLSEh4KcxYPyrLRC1ll8nr5OlCx 38 | CMhKkTnR6qBsdNV0XtdU2+N25hqW+Ma4ZeqsN/iiJVCGNOZGnvQuvCAGWF8+J/f/ 39 | iHkC6gGdBJhogs4= 40 | -----END CERTIFICATE----- 41 | -------------------------------------------------------------------------------- /test/keycert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICXwIBAAKBgQC8ddrhm+LutBvjYcQlnH21PPIseJ1JVG2HMmN2CmZk2YukO+9L 3 | opdJhTvbGfEj0DQs1IE8M+kTUyOmuKfVrFMKwtVeCJphrAnhoz7TYOuLBSqt7lVH 4 | fhi/VwovESJlaBOp+WMnfhcduPEYHYx/6cnVapIkZnLt30zu2um+DzA9jQIDAQAB 5 | AoGBAK0FZpaKj6WnJZN0RqhhK+ggtBWwBnc0U/ozgKz2j1s3fsShYeiGtW6CK5nU 6 | D1dZ5wzhbGThI7LiOXDvRucc9n7vUgi0alqPQ/PFodPxAN/eEYkmXQ7W2k7zwsDA 7 | IUK0KUhktQbLu8qF/m8qM86ba9y9/9YkXuQbZ3COl5ahTZrhAkEA301P08RKv3KM 8 | oXnGU2UHTuJ1MAD2hOrPxjD4/wxA/39EWG9bZczbJyggB4RHu0I3NOSFjAm3HQm0 9 | ANOu5QK9owJBANgOeLfNNcF4pp+UikRFqxk5hULqRAWzVxVrWe85FlPm0VVmHbb/ 10 | loif7mqjU8o1jTd/LM7RD9f2usZyE2psaw8CQQCNLhkpX3KO5kKJmS9N7JMZSc4j 11 | oog58yeYO8BBqKKzpug0LXuQultYv2K4veaIO04iL9VLe5z9S/Q1jaCHBBuXAkEA 12 | z8gjGoi1AOp6PBBLZNsncCvcV/0aC+1se4HxTNo2+duKSDnbq+ljqOM+E7odU+Nq 13 | ewvIWOG//e8fssd0mq3HywJBAJ8l/c8GVmrpFTx8r/nZ2Pyyjt3dH1widooDXYSV 14 | q6Gbf41Llo5sYAtmxdndTLASuHKecacTgZVhy0FryZpLKrU= 15 | -----END RSA PRIVATE KEY----- 16 | -----BEGIN CERTIFICATE----- 17 | MIICpzCCAhCgAwIBAgIJAP+qStv1cIGNMA0GCSqGSIb3DQEBBQUAMIGJMQswCQYD 18 | VQQGEwJVUzERMA8GA1UECBMIRGVsYXdhcmUxEzARBgNVBAcTCldpbG1pbmd0b24x 19 | IzAhBgNVBAoTGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0aW9uMQwwCgYDVQQLEwNT 20 | U0wxHzAdBgNVBAMTFnNvbWVtYWNoaW5lLnB5dGhvbi5vcmcwHhcNMDcwODI3MTY1 21 | NDUwWhcNMTMwMjE2MTY1NDUwWjCBiTELMAkGA1UEBhMCVVMxETAPBgNVBAgTCERl 22 | bGF3YXJlMRMwEQYDVQQHEwpXaWxtaW5ndG9uMSMwIQYDVQQKExpQeXRob24gU29m 23 | dHdhcmUgRm91bmRhdGlvbjEMMAoGA1UECxMDU1NMMR8wHQYDVQQDExZzb21lbWFj 24 | aGluZS5weXRob24ub3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8ddrh 25 | m+LutBvjYcQlnH21PPIseJ1JVG2HMmN2CmZk2YukO+9LopdJhTvbGfEj0DQs1IE8 26 | M+kTUyOmuKfVrFMKwtVeCJphrAnhoz7TYOuLBSqt7lVHfhi/VwovESJlaBOp+WMn 27 | fhcduPEYHYx/6cnVapIkZnLt30zu2um+DzA9jQIDAQABoxUwEzARBglghkgBhvhC 28 | AQEEBAMCBkAwDQYJKoZIhvcNAQEFBQADgYEAF4Q5BVqmCOLv1n8je/Jw9K669VXb 29 | 08hyGzQhkemEBYQd6fzQ9A/1ZzHkJKb1P6yreOLSEh4KcxYPyrLRC1ll8nr5OlCx 30 | CMhKkTnR6qBsdNV0XtdU2+N25hqW+Ma4ZeqsN/iiJVCGNOZGnvQuvCAGWF8+J/f/ 31 | iHkC6gGdBJhogs4= 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /test/nullcert.pem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pypa/ssl/53b55dcb92c03edec70690d3cd9177b4c7f16f7b/test/nullcert.pem -------------------------------------------------------------------------------- /test/root.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIHPTCCBSWgAwIBAgIBADANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290 3 | IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB 4 | IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA 5 | Y2FjZXJ0Lm9yZzAeFw0wMzAzMzAxMjI5NDlaFw0zMzAzMjkxMjI5NDlaMHkxEDAO 6 | BgNVBAoTB1Jvb3QgQ0ExHjAcBgNVBAsTFWh0dHA6Ly93d3cuY2FjZXJ0Lm9yZzEi 7 | MCAGA1UEAxMZQ0EgQ2VydCBTaWduaW5nIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJ 8 | ARYSc3VwcG9ydEBjYWNlcnQub3JnMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC 9 | CgKCAgEAziLA4kZ97DYoB1CW8qAzQIxL8TtmPzHlawI229Z89vGIj053NgVBlfkJ 10 | 8BLPRoZzYLdufujAWGSuzbCtRRcMY/pnCujW0r8+55jE8Ez64AO7NV1sId6eINm6 11 | zWYyN3L69wj1x81YyY7nDl7qPv4coRQKFWyGhFtkZip6qUtTefWIonvuLwphK42y 12 | fk1WpRPs6tqSnqxEQR5YYGUFZvjARL3LlPdCfgv3ZWiYUQXw8wWRBB0bF4LsyFe7 13 | w2t6iPGwcswlWyCR7BYCEo8y6RcYSNDHBS4CMEK4JZwFaz+qOqfrU0j36NK2B5jc 14 | G8Y0f3/JHIJ6BVgrCFvzOKKrF11myZjXnhCLotLddJr3cQxyYN/Nb5gznZY0dj4k 15 | epKwDpUeb+agRThHqtdB7Uq3EvbXG4OKDy7YCbZZ16oE/9KTfWgu3YtLq1i6L43q 16 | laegw1SJpfvbi1EinbLDvhG+LJGGi5Z4rSDTii8aP8bQUWWHIbEZAWV/RRyH9XzQ 17 | QUxPKZgh/TMfdQwEUfoZd9vUFBzugcMd9Zi3aQaRIt0AUMyBMawSB3s42mhb5ivU 18 | fslfrejrckzzAeVLIL+aplfKkQABi6F1ITe1Yw1nPkZPcCBnzsXWWdsC4PDSy826 19 | YreQQejdIOQpvGQpQsgi3Hia/0PsmBsJUUtaWsJx8cTLc6nloQsCAwEAAaOCAc4w 20 | ggHKMB0GA1UdDgQWBBQWtTIb1Mfz4OaO873SsDrusjkY0TCBowYDVR0jBIGbMIGY 21 | gBQWtTIb1Mfz4OaO873SsDrusjkY0aF9pHsweTEQMA4GA1UEChMHUm9vdCBDQTEe 22 | MBwGA1UECxMVaHR0cDovL3d3dy5jYWNlcnQub3JnMSIwIAYDVQQDExlDQSBDZXJ0 23 | IFNpZ25pbmcgQXV0aG9yaXR5MSEwHwYJKoZIhvcNAQkBFhJzdXBwb3J0QGNhY2Vy 24 | dC5vcmeCAQAwDwYDVR0TAQH/BAUwAwEB/zAyBgNVHR8EKzApMCegJaAjhiFodHRw 25 | czovL3d3dy5jYWNlcnQub3JnL3Jldm9rZS5jcmwwMAYJYIZIAYb4QgEEBCMWIWh0 26 | dHBzOi8vd3d3LmNhY2VydC5vcmcvcmV2b2tlLmNybDA0BglghkgBhvhCAQgEJxYl 27 | aHR0cDovL3d3dy5jYWNlcnQub3JnL2luZGV4LnBocD9pZD0xMDBWBglghkgBhvhC 28 | AQ0ESRZHVG8gZ2V0IHlvdXIgb3duIGNlcnRpZmljYXRlIGZvciBGUkVFIGhlYWQg 29 | b3ZlciB0byBodHRwOi8vd3d3LmNhY2VydC5vcmcwDQYJKoZIhvcNAQEEBQADggIB 30 | ACjH7pyCArpcgBLKNQodgW+JapnM8mgPf6fhjViVPr3yBsOQWqy1YPaZQwGjiHCc 31 | nWKdpIevZ1gNMDY75q1I08t0AoZxPuIrA2jxNGJARjtT6ij0rPtmlVOKTV39O9lg 32 | 18p5aTuxZZKmxoGCXJzN600BiqXfEVWqFcofN8CCmHBh22p8lqOOLlQ+TyGpkO/c 33 | gr/c6EWtTZBzCDyUZbAEmXZ/4rzCahWqlwQ3JNgelE5tDlG+1sSPypZt90Pf6DBl 34 | Jzt7u0NDY8RD97LsaMzhGY4i+5jhe1o+ATc7iwiwovOVThrLm82asduycPAtStvY 35 | sONvRUgzEv/+PDIqVPfE94rwiCPCR/5kenHA0R6mY7AHfqQv0wGP3J8rtsYIqQ+T 36 | SCX8Ev2fQtzzxD72V7DX3WnRBnc0CkvSyqD/HMaMyRa+xMwyN2hzXwj7UfdJUzYF 37 | CpUCTPJ5GhD22Dp1nPMd8aINcGeGG7MW9S/lpOt5hvk9C8JzC6WZrG/8Z7jlLwum 38 | GCSNe9FINSkYQKyTYOGWhlC0elnYjyELn8+CkcY7v2vcB5G5l1YjqrZslMZIBjzk 39 | zk6q5PYvCdxTby78dOs6Y5nCpqyJvKeyRKANihDjbPIky/qbn3BHLt4Ui9SyIAmW 40 | omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD 41 | -----END CERTIFICATE----- 42 | -------------------------------------------------------------------------------- /test/test_ssl.py: -------------------------------------------------------------------------------- 1 | # Test the support for SSL and sockets 2 | import sys 3 | import unittest 4 | from test import test_support 5 | import select 6 | import socket 7 | import os 8 | import pprint 9 | import urllib 10 | import urlparse 11 | import traceback 12 | import asyncore 13 | 14 | from BaseHTTPServer import HTTPServer 15 | from SimpleHTTPServer import SimpleHTTPRequestHandler 16 | 17 | # Optionally test SSL support, if we have it in the tested platform 18 | skip_expected = False 19 | try: 20 | import ssl 21 | except ImportError, x: 22 | print "error: ", x 23 | skip_expected = True 24 | 25 | CERTFILE = None 26 | SVN_PYTHON_ORG_ROOT_CERT = None 27 | 28 | TESTPORT = 10025 29 | 30 | # simply enable the network resource here to be able to run the test file directly 31 | test_support.use_resources = ['network'] 32 | 33 | 34 | def handle_error(prefix): 35 | exc_format = ' '.join(traceback.format_exception(*sys.exc_info())) 36 | if test_support.verbose: 37 | sys.stdout.write(prefix + exc_format) 38 | 39 | 40 | class BasicTests(unittest.TestCase): 41 | 42 | def testCrucialConstants(self): 43 | ssl.PROTOCOL_SSLv2 44 | ssl.PROTOCOL_SSLv23 45 | ssl.PROTOCOL_SSLv3 46 | ssl.PROTOCOL_TLSv1 47 | ssl.CERT_NONE 48 | ssl.CERT_OPTIONAL 49 | ssl.CERT_REQUIRED 50 | 51 | def testRAND(self): 52 | v = ssl.RAND_status() 53 | if test_support.verbose: 54 | sys.stdout.write("\n RAND_status is %d (%s)\n" 55 | % (v, (v and "sufficient randomness") or 56 | "insufficient randomness")) 57 | try: 58 | ssl.RAND_egd(1) 59 | except TypeError: 60 | pass 61 | else: 62 | print "didn't raise TypeError" 63 | ssl.RAND_add("this is a random string", 75.0) 64 | 65 | def testParseCert(self): 66 | # note that this uses an 'unofficial' function in _ssl.c, 67 | # provided solely for this test, to exercise the certificate 68 | # parsing code 69 | p = ssl._ssl2._test_decode_cert(CERTFILE, False) 70 | if test_support.verbose: 71 | sys.stdout.write("\n" + pprint.pformat(p) + "\n") 72 | 73 | def testDERtoPEM(self): 74 | pem = open(SVN_PYTHON_ORG_ROOT_CERT, 'r').read() 75 | d1 = ssl.PEM_cert_to_DER_cert(pem) 76 | p2 = ssl.DER_cert_to_PEM_cert(d1) 77 | d2 = ssl.PEM_cert_to_DER_cert(p2) 78 | if (d1 != d2): 79 | raise test_support.TestFailed("PEM-to-DER or DER-to-PEM translation failed") 80 | 81 | 82 | class NetworkedTests(unittest.TestCase): 83 | 84 | def testConnect(self): 85 | s = ssl.wrap_socket(socket.socket(socket.AF_INET), 86 | cert_reqs=ssl.CERT_NONE) 87 | s.connect(("pop.gmail.com", 995)) 88 | c = s.getpeercert() 89 | if c: 90 | raise test_support.TestFailed("Peer cert %s shouldn't be here!") 91 | s.close() 92 | 93 | # this should fail because we have no verification certs 94 | s = ssl.wrap_socket(socket.socket(socket.AF_INET), 95 | cert_reqs=ssl.CERT_REQUIRED) 96 | try: 97 | try: 98 | s.connect(("pop.gmail.com", 995)) 99 | except ssl.SSLError: 100 | pass 101 | finally: 102 | s.close() 103 | 104 | # this should succeed because we specify the root cert 105 | s = ssl.wrap_socket(socket.socket(socket.AF_INET), 106 | cert_reqs=ssl.CERT_REQUIRED, 107 | ca_certs=SVN_PYTHON_ORG_ROOT_CERT) 108 | try: 109 | try: 110 | s.connect(("svn.python.org", 443)) 111 | except ssl.SSLError, x: 112 | raise test_support.TestFailed("Unexpected exception %s" % x) 113 | finally: 114 | s.close() 115 | 116 | def testNonBlockingHandshake(self): 117 | s = socket.socket(socket.AF_INET) 118 | s.connect(("svn.python.org", 443)) 119 | s.setblocking(False) 120 | s = ssl.wrap_socket(s, 121 | cert_reqs=ssl.CERT_NONE, 122 | do_handshake_on_connect=False) 123 | count = 0 124 | while True: 125 | try: 126 | count += 1 127 | s.do_handshake() 128 | break 129 | except ssl.SSLError, err: 130 | if err.args[0] == ssl.SSL_ERROR_WANT_READ: 131 | select.select([s], [], []) 132 | elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE: 133 | select.select([], [s], []) 134 | else: 135 | raise 136 | s.close() 137 | if test_support.verbose: 138 | sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count) 139 | 140 | def testFetchServerCert(self): 141 | 142 | pem = ssl.get_server_certificate(("svn.python.org", 443)) 143 | if not pem: 144 | raise test_support.TestFailed("No server certificate on svn.python.org:443!") 145 | 146 | try: 147 | pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE) 148 | except ssl.SSLError: 149 | #should fail 150 | pass 151 | else: 152 | raise test_support.TestFailed("Got server certificate %s for svn.python.org!" % pem) 153 | 154 | pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT) 155 | if not pem: 156 | raise test_support.TestFailed("No server certificate on svn.python.org:443!") 157 | if test_support.verbose: 158 | sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem) 159 | 160 | 161 | try: 162 | import threading 163 | except ImportError: 164 | print "No threads!" 165 | _have_threads = False 166 | else: 167 | 168 | _have_threads = True 169 | 170 | class ThreadedEchoServer(threading.Thread): 171 | 172 | class ConnectionHandler(threading.Thread): 173 | 174 | """A mildly complicated class, because we want it to work both 175 | with and without the SSL wrapper around the socket connection, so 176 | that we can test the STARTTLS functionality.""" 177 | 178 | def __init__(self, server, connsock): 179 | self.server = server 180 | self.running = False 181 | self.sock = connsock 182 | self.sock.setblocking(1) 183 | self.sslconn = None 184 | threading.Thread.__init__(self) 185 | self.setDaemon(True) 186 | 187 | def show_conn_details(self): 188 | if self.server.certreqs == ssl.CERT_REQUIRED: 189 | cert = self.sslconn.getpeercert() 190 | if test_support.verbose and self.server.chatty: 191 | sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n") 192 | cert_binary = self.sslconn.getpeercert(True) 193 | if test_support.verbose and self.server.chatty: 194 | sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n") 195 | cipher = self.sslconn.cipher() 196 | if test_support.verbose and self.server.chatty: 197 | sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n") 198 | 199 | def wrap_conn(self): 200 | try: 201 | self.sslconn = ssl.wrap_socket(self.sock, server_side=True, 202 | certfile=self.server.certificate, 203 | ssl_version=self.server.protocol, 204 | ca_certs=self.server.cacerts, 205 | cert_reqs=self.server.certreqs) 206 | except: 207 | if self.server.chatty: 208 | handle_error("\n server: bad connection attempt from " + 209 | str(self.sock.getpeername()) + ":\n") 210 | self.close() 211 | if not self.server.expect_bad_connects: 212 | # here, we want to stop the server, because this shouldn't 213 | # happen in the context of our test case 214 | self.running = False 215 | # normally, we'd just stop here, but for the test 216 | # harness, we want to stop the server 217 | self.server.stop() 218 | return False 219 | 220 | else: 221 | return True 222 | 223 | def read(self): 224 | if self.sslconn: 225 | return self.sslconn.read() 226 | else: 227 | return self.sock.recv(1024) 228 | 229 | def write(self, bytes): 230 | if self.sslconn: 231 | return self.sslconn.write(bytes) 232 | else: 233 | return self.sock.send(bytes) 234 | 235 | def close(self): 236 | if self.sslconn: 237 | self.sslconn.close() 238 | else: 239 | # close is broken on sockets 240 | os.close(self.sock.fileno()) 241 | 242 | def run(self): 243 | self.running = True 244 | if not self.server.starttls_server: 245 | if isinstance(self.sock, ssl.SSLSocket): 246 | self.sslconn = self.sock 247 | elif not self.wrap_conn(): 248 | return 249 | self.show_conn_details() 250 | while self.running: 251 | try: 252 | msg = self.read() 253 | if not msg: 254 | # eof, so quit this handler 255 | self.running = False 256 | self.close() 257 | elif msg.strip() == 'over': 258 | if test_support.verbose and self.server.connectionchatty: 259 | sys.stdout.write(" server: client closed connection\n") 260 | self.close() 261 | return 262 | elif self.server.starttls_server and msg.strip() == 'STARTTLS': 263 | if test_support.verbose and self.server.connectionchatty: 264 | sys.stdout.write(" server: read STARTTLS from client, sending OK...\n") 265 | self.write("OK\n") 266 | if not self.wrap_conn(): 267 | return 268 | elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS': 269 | if test_support.verbose and self.server.connectionchatty: 270 | sys.stdout.write(" server: read ENDTLS from client, sending OK...\n") 271 | self.write("OK\n") 272 | self.sock = self.sslconn.unwrap() 273 | self.sslconn = None 274 | if test_support.verbose and self.server.connectionchatty: 275 | sys.stdout.write(" server: connection is now unencrypted...\n") 276 | else: 277 | if (test_support.verbose and 278 | self.server.connectionchatty): 279 | ctype = (self.sslconn and "encrypted") or "unencrypted" 280 | sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n" 281 | % (repr(msg), ctype, repr(msg.lower()), ctype)) 282 | self.write(msg.lower()) 283 | except ssl.SSLError: 284 | if self.server.chatty: 285 | handle_error("Test server failure:\n") 286 | self.close() 287 | self.running = False 288 | # normally, we'd just stop here, but for the test 289 | # harness, we want to stop the server 290 | self.server.stop() 291 | except: 292 | handle_error('') 293 | 294 | def __init__(self, port, certificate, ssl_version=None, 295 | certreqs=None, cacerts=None, expect_bad_connects=False, 296 | chatty=True, connectionchatty=False, starttls_server=False, 297 | wrap_accepting_socket=False): 298 | if ssl_version is None: 299 | ssl_version = ssl.PROTOCOL_TLSv1 300 | if certreqs is None: 301 | certreqs = ssl.CERT_NONE 302 | self.certificate = certificate 303 | self.protocol = ssl_version 304 | self.certreqs = certreqs 305 | self.cacerts = cacerts 306 | self.expect_bad_connects = expect_bad_connects 307 | self.chatty = chatty 308 | self.connectionchatty = connectionchatty 309 | self.starttls_server = starttls_server 310 | self.sock = socket.socket() 311 | self.flag = None 312 | if hasattr(socket, 'SO_REUSEADDR'): 313 | self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 314 | if hasattr(socket, 'SO_REUSEPORT'): 315 | self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) 316 | if wrap_accepting_socket: 317 | self.sock = ssl.wrap_socket(self.sock, server_side=True, 318 | certfile=self.certificate, 319 | cert_reqs=self.certreqs, 320 | ca_certs=self.cacerts, 321 | ssl_version=self.protocol) 322 | if test_support.verbose and self.chatty: 323 | sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock)) 324 | self.sock.bind(('127.0.0.1', port)) 325 | self.active = False 326 | threading.Thread.__init__(self) 327 | self.setDaemon(False) 328 | 329 | def start(self, flag=None): 330 | self.flag = flag 331 | threading.Thread.start(self) 332 | 333 | def run(self): 334 | self.sock.settimeout(0.5) 335 | self.sock.listen(5) 336 | self.active = True 337 | if self.flag: 338 | # signal an event 339 | self.flag.set() 340 | while self.active: 341 | try: 342 | newconn, connaddr = self.sock.accept() 343 | if test_support.verbose and self.chatty: 344 | sys.stdout.write(' server: new connection from ' 345 | + str(connaddr) + '\n') 346 | handler = self.ConnectionHandler(self, newconn) 347 | handler.start() 348 | except socket.timeout: 349 | pass 350 | except KeyboardInterrupt: 351 | self.stop() 352 | except: 353 | if self.chatty: 354 | handle_error("Test server failure:\n") 355 | self.sock.close() 356 | 357 | def stop(self): 358 | self.active = False 359 | 360 | class AsyncoreEchoServer(threading.Thread): 361 | 362 | class EchoServer (asyncore.dispatcher): 363 | 364 | class ConnectionHandler (asyncore.dispatcher_with_send): 365 | 366 | def __init__(self, conn, certfile): 367 | asyncore.dispatcher_with_send.__init__(self, conn) 368 | self.socket = ssl.wrap_socket(conn, server_side=True, 369 | certfile=certfile, 370 | do_handshake_on_connect=False) 371 | # now we have to do the handshake 372 | # we'll just do it the easy way, and block the connection 373 | # till it's finished. If we were doing it right, we'd 374 | # do this in multiple calls to handle_read... 375 | self.do_handshake(block=True) 376 | 377 | def readable(self): 378 | if isinstance(self.socket, ssl.SSLSocket): 379 | while self.socket.pending() > 0: 380 | self.handle_read_event() 381 | return True 382 | 383 | def handle_read(self): 384 | data = self.recv(1024) 385 | self.send(data.lower()) 386 | 387 | def handle_close(self): 388 | self.close() 389 | if test_support.verbose: 390 | sys.stdout.write(" server: closed connection %s\n" % self.socket) 391 | 392 | def handle_error(self): 393 | raise 394 | 395 | def __init__(self, port, certfile): 396 | self.port = port 397 | self.certfile = certfile 398 | asyncore.dispatcher.__init__(self) 399 | self.create_socket(socket.AF_INET, socket.SOCK_STREAM) 400 | self.bind(('', port)) 401 | self.listen(5) 402 | 403 | def handle_accept(self): 404 | sock_obj, addr = self.accept() 405 | if test_support.verbose: 406 | sys.stdout.write(" server: new connection from %s:%s\n" % 407 | addr) 408 | self.ConnectionHandler(sock_obj, self.certfile) 409 | 410 | def handle_error(self): 411 | raise 412 | 413 | def __init__(self, port, certfile): 414 | self.flag = None 415 | self.active = False 416 | self.server = self.EchoServer(port, certfile) 417 | threading.Thread.__init__(self) 418 | self.setDaemon(True) 419 | 420 | def __str__(self): 421 | return "<%s %s>" % (self.__class__.__name__, self.server) 422 | 423 | def start(self, flag=None): 424 | self.flag = flag 425 | threading.Thread.start(self) 426 | 427 | def run(self): 428 | self.active = True 429 | if self.flag: 430 | self.flag.set() 431 | while self.active: 432 | try: 433 | asyncore.loop(1) 434 | except: 435 | pass 436 | 437 | def stop(self): 438 | self.active = False 439 | self.server.close() 440 | 441 | class SocketServerHTTPSServer(threading.Thread): 442 | 443 | class HTTPSServer(HTTPServer): 444 | 445 | def __init__(self, server_address, RequestHandlerClass, certfile): 446 | 447 | HTTPServer.__init__(self, server_address, RequestHandlerClass) 448 | # we assume the certfile contains both private key and certificate 449 | self.certfile = certfile 450 | self.active = False 451 | self.allow_reuse_address = True 452 | 453 | def __str__(self): 454 | return ('<%s %s:%s>' % 455 | (self.__class__.__name__, 456 | self.server_name, 457 | self.server_port)) 458 | 459 | def get_request(self): 460 | # override this to wrap socket with SSL 461 | sock, addr = self.socket.accept() 462 | sslconn = ssl.wrap_socket(sock, server_side=True, 463 | certfile=self.certfile) 464 | return sslconn, addr 465 | 466 | def server_activate(self): 467 | # override this to set timeout, so we get 468 | # a chance to stop the server 469 | self.socket.settimeout(0.5) 470 | HTTPServer.server_activate(self) 471 | 472 | def serve_forever(self): 473 | # We want this to run in a thread, so we use a slightly 474 | # modified version of "forever". 475 | self.active = True 476 | while self.active: 477 | try: 478 | self.handle_request() 479 | except socket.timeout: 480 | pass 481 | except KeyboardInterrupt: 482 | self.server_close() 483 | return 484 | except: 485 | sys.stdout.write(''.join(traceback.format_exception(*sys.exc_info()))) 486 | 487 | def server_close(self): 488 | # Again, we want this to run in a thread, so we need to override 489 | # close to clear the "active" flag, so that serve_forever() will 490 | # terminate. 491 | HTTPServer.server_close(self) 492 | self.active = False 493 | 494 | class RootedHTTPRequestHandler(SimpleHTTPRequestHandler): 495 | 496 | # need to override translate_path to get a known root, 497 | # instead of using os.curdir, since the test could be 498 | # run from anywhere 499 | # 500 | # We also want to override log_request() to suppress logging 501 | 502 | root = None 503 | 504 | def translate_path(self, path): 505 | """Translate a /-separated PATH to the local filename syntax. 506 | 507 | Components that mean special things to the local file system 508 | (e.g. drive or directory names) are ignored. (XXX They should 509 | probably be diagnosed.) 510 | 511 | """ 512 | # abandon query parameters 513 | path = urlparse.urlparse(path)[2] 514 | path = os.path.normpath(urllib.unquote(path)) 515 | words = path.split('/') 516 | words = filter(None, words) 517 | path = self.root 518 | for word in words: 519 | drive, word = os.path.splitdrive(word) 520 | head, word = os.path.split(word) 521 | if word in self.root: 522 | continue 523 | path = os.path.join(path, word) 524 | return path 525 | 526 | def log_message(self, format, *args): 527 | 528 | # we override this to suppress logging unless "verbose" 529 | 530 | if test_support.verbose: 531 | sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" % 532 | (self.server.server_address, 533 | self.server.server_port, 534 | self.request.cipher(), 535 | self.log_date_time_string(), 536 | format % args)) 537 | 538 | def __init__(self, port, certfile): 539 | self.flag = None 540 | self.active = False 541 | self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0] 542 | self.server = self.HTTPSServer( 543 | ('127.0.0.1', port), self.RootedHTTPRequestHandler, certfile) 544 | threading.Thread.__init__(self) 545 | self.setDaemon(True) 546 | 547 | def __str__(self): 548 | return "<%s %s>" % (self.__class__.__name__, self.server) 549 | 550 | def start(self, flag=None): 551 | self.flag = flag 552 | threading.Thread.start(self) 553 | 554 | def run(self): 555 | self.active = True 556 | if self.flag: 557 | self.flag.set() 558 | self.server.serve_forever() 559 | self.active = False 560 | 561 | def stop(self): 562 | self.active = False 563 | self.server.server_close() 564 | 565 | def badCertTest(certfile): 566 | server = ThreadedEchoServer(TESTPORT, CERTFILE, 567 | certreqs=ssl.CERT_REQUIRED, 568 | cacerts=CERTFILE, chatty=False) 569 | flag = threading.Event() 570 | server.start(flag) 571 | # wait for it to start 572 | flag.wait() 573 | # try to connect 574 | try: 575 | try: 576 | s = ssl.wrap_socket(socket.socket(), 577 | certfile=certfile, 578 | ssl_version=ssl.PROTOCOL_TLSv1) 579 | s.connect(('127.0.0.1', TESTPORT)) 580 | except ssl.SSLError, x: 581 | if test_support.verbose: 582 | sys.stdout.write("\nSSLError is %s\n" % x[1]) 583 | else: 584 | raise test_support.TestFailed( 585 | "Use of invalid cert should have failed!") 586 | finally: 587 | server.stop() 588 | server.join() 589 | 590 | def serverParamsTest(certfile, protocol, certreqs, cacertsfile, 591 | client_certfile, client_protocol=None, indata="FOO\n", 592 | chatty=True, connectionchatty=False, 593 | wrap_accepting_socket=False): 594 | 595 | server = ThreadedEchoServer(TESTPORT, certfile, 596 | certreqs=certreqs, 597 | ssl_version=protocol, 598 | cacerts=cacertsfile, 599 | chatty=chatty, 600 | connectionchatty=connectionchatty, 601 | wrap_accepting_socket=wrap_accepting_socket) 602 | flag = threading.Event() 603 | server.start(flag) 604 | # wait for it to start 605 | flag.wait() 606 | # try to connect 607 | if client_protocol is None: 608 | client_protocol = protocol 609 | try: 610 | try: 611 | s = ssl.wrap_socket(socket.socket(), 612 | certfile=client_certfile, 613 | ca_certs=cacertsfile, 614 | cert_reqs=certreqs, 615 | ssl_version=client_protocol) 616 | s.connect(('127.0.0.1', TESTPORT)) 617 | except ssl.SSLError, x: 618 | raise test_support.TestFailed("Unexpected SSL error: " + str(x)) 619 | except Exception, x: 620 | raise test_support.TestFailed("Unexpected exception: " + str(x)) 621 | else: 622 | if connectionchatty: 623 | if test_support.verbose: 624 | sys.stdout.write( 625 | " client: sending %s...\n" % (repr(indata))) 626 | s.write(indata) 627 | outdata = s.read() 628 | if connectionchatty: 629 | if test_support.verbose: 630 | sys.stdout.write(" client: read %s\n" % repr(outdata)) 631 | if outdata != indata.lower(): 632 | raise test_support.TestFailed( 633 | "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n" 634 | % (outdata[:min(len(outdata), 20)], len(outdata), 635 | indata[:min(len(indata), 20)].lower(), len(indata))) 636 | s.write("over\n") 637 | if connectionchatty: 638 | if test_support.verbose: 639 | sys.stdout.write(" client: closing connection.\n") 640 | s.close() 641 | finally: 642 | server.stop() 643 | server.join() 644 | 645 | def tryProtocolCombo(server_protocol, 646 | client_protocol, 647 | expectedToWork, 648 | certsreqs=None): 649 | 650 | if certsreqs is None: 651 | certsreqs = ssl.CERT_NONE 652 | 653 | if certsreqs == ssl.CERT_NONE: 654 | certtype = "CERT_NONE" 655 | elif certsreqs == ssl.CERT_OPTIONAL: 656 | certtype = "CERT_OPTIONAL" 657 | elif certsreqs == ssl.CERT_REQUIRED: 658 | certtype = "CERT_REQUIRED" 659 | if test_support.verbose: 660 | formatstr = (expectedToWork and " %s->%s %s\n") or " {%s->%s} %s\n" 661 | sys.stdout.write(formatstr % 662 | (ssl.get_protocol_name(client_protocol), 663 | ssl.get_protocol_name(server_protocol), 664 | certtype)) 665 | try: 666 | serverParamsTest(CERTFILE, server_protocol, certsreqs, 667 | CERTFILE, CERTFILE, client_protocol, chatty=False) 668 | except test_support.TestFailed: 669 | if expectedToWork: 670 | raise 671 | else: 672 | if not expectedToWork: 673 | raise test_support.TestFailed( 674 | "Client protocol %s succeeded with server protocol %s!" 675 | % (ssl.get_protocol_name(client_protocol), 676 | ssl.get_protocol_name(server_protocol))) 677 | 678 | class ThreadedTests(unittest.TestCase): 679 | 680 | def testRudeShutdown(self): 681 | 682 | listener_ready = threading.Event() 683 | listener_gone = threading.Event() 684 | 685 | # `listener` runs in a thread. It opens a socket listening on 686 | # PORT, and sits in an accept() until the main thread connects. 687 | # Then it rudely closes the socket, and sets Event `listener_gone` 688 | # to let the main thread know the socket is gone. 689 | def listener(): 690 | s = socket.socket() 691 | if hasattr(socket, 'SO_REUSEADDR'): 692 | s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 693 | if hasattr(socket, 'SO_REUSEPORT'): 694 | s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) 695 | s.bind(('127.0.0.1', TESTPORT)) 696 | s.listen(5) 697 | listener_ready.set() 698 | s.accept() 699 | s = None # reclaim the socket object, which also closes it 700 | listener_gone.set() 701 | 702 | def connector(): 703 | listener_ready.wait() 704 | s = socket.socket() 705 | s.connect(('127.0.0.1', TESTPORT)) 706 | listener_gone.wait() 707 | try: 708 | ssl.wrap_socket(s) 709 | except socket.error: 710 | pass 711 | else: 712 | raise test_support.TestFailed( 713 | 'connecting to closed SSL socket should have failed') 714 | 715 | t = threading.Thread(target=listener) 716 | t.start() 717 | connector() 718 | t.join() 719 | 720 | def testEcho(self): 721 | 722 | if test_support.verbose: 723 | sys.stdout.write("\n") 724 | serverParamsTest(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE, 725 | CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1, 726 | chatty=True, connectionchatty=True) 727 | 728 | def testReadCert(self): 729 | 730 | if test_support.verbose: 731 | sys.stdout.write("\n") 732 | s2 = socket.socket() 733 | server = ThreadedEchoServer(TESTPORT, CERTFILE, 734 | certreqs=ssl.CERT_NONE, 735 | ssl_version=ssl.PROTOCOL_SSLv23, 736 | cacerts=CERTFILE, 737 | chatty=False) 738 | flag = threading.Event() 739 | server.start(flag) 740 | # wait for it to start 741 | flag.wait() 742 | # try to connect 743 | try: 744 | try: 745 | s = ssl.wrap_socket(socket.socket(), 746 | certfile=CERTFILE, 747 | ca_certs=CERTFILE, 748 | cert_reqs=ssl.CERT_REQUIRED, 749 | ssl_version=ssl.PROTOCOL_SSLv23) 750 | s.connect(('127.0.0.1', TESTPORT)) 751 | except ssl.SSLError, x: 752 | raise test_support.TestFailed( 753 | "Unexpected SSL error: " + str(x)) 754 | except Exception, x: 755 | raise test_support.TestFailed( 756 | "Unexpected exception: " + str(x)) 757 | else: 758 | if not s: 759 | raise test_support.TestFailed( 760 | "Can't SSL-handshake with test server") 761 | cert = s.getpeercert() 762 | if not cert: 763 | raise test_support.TestFailed( 764 | "Can't get peer certificate.") 765 | cipher = s.cipher() 766 | if test_support.verbose: 767 | sys.stdout.write(pprint.pformat(cert) + '\n') 768 | sys.stdout.write("Connection cipher is " + str(cipher) + '.\n') 769 | if not cert.has_key('subject'): 770 | raise test_support.TestFailed( 771 | "No subject field in certificate: %s." % 772 | pprint.pformat(cert)) 773 | if ((('organizationName', 'Python Software Foundation'),) 774 | not in cert['subject']): 775 | raise test_support.TestFailed( 776 | "Missing or invalid 'organizationName' field in certificate subject; " 777 | "should be 'Python Software Foundation'.") 778 | s.close() 779 | finally: 780 | server.stop() 781 | server.join() 782 | 783 | def testNULLcert(self): 784 | badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir, 785 | "nullcert.pem")) 786 | 787 | def testMalformedCert(self): 788 | badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir, 789 | "badcert.pem")) 790 | 791 | def testMalformedKey(self): 792 | badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir, 793 | "badkey.pem")) 794 | 795 | def testProtocolSSL2(self): 796 | if test_support.verbose: 797 | sys.stdout.write("\n") 798 | tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True) 799 | tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL) 800 | tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED) 801 | tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True) 802 | tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False) 803 | tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False) 804 | 805 | def testProtocolSSL23(self): 806 | if test_support.verbose: 807 | sys.stdout.write("\n") 808 | try: 809 | tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True) 810 | except test_support.TestFailed, x: 811 | # this fails on some older versions of OpenSSL (0.9.7l, for instance) 812 | if test_support.verbose: 813 | sys.stdout.write( 814 | " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n" 815 | % str(x)) 816 | tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True) 817 | tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True) 818 | tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True) 819 | 820 | tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL) 821 | tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL) 822 | tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL) 823 | 824 | tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED) 825 | tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED) 826 | tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED) 827 | 828 | def testProtocolSSL3(self): 829 | if test_support.verbose: 830 | sys.stdout.write("\n") 831 | tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True) 832 | tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL) 833 | tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED) 834 | tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False) 835 | tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False) 836 | tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False) 837 | 838 | def testProtocolTLS1(self): 839 | if test_support.verbose: 840 | sys.stdout.write("\n") 841 | tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True) 842 | tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL) 843 | tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED) 844 | tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False) 845 | tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False) 846 | tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False) 847 | 848 | def testSTARTTLS(self): 849 | 850 | msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6") 851 | 852 | server = ThreadedEchoServer(TESTPORT, CERTFILE, 853 | ssl_version=ssl.PROTOCOL_TLSv1, 854 | starttls_server=True, 855 | chatty=True, 856 | connectionchatty=True) 857 | flag = threading.Event() 858 | server.start(flag) 859 | # wait for it to start 860 | flag.wait() 861 | # try to connect 862 | wrapped = False 863 | try: 864 | try: 865 | s = socket.socket() 866 | s.setblocking(1) 867 | s.connect(('127.0.0.1', TESTPORT)) 868 | except Exception, x: 869 | raise test_support.TestFailed("Unexpected exception: " + str(x)) 870 | else: 871 | if test_support.verbose: 872 | sys.stdout.write("\n") 873 | for indata in msgs: 874 | if test_support.verbose: 875 | sys.stdout.write(" client: sending %s...\n" % repr(indata)) 876 | if wrapped: 877 | conn.write(indata) 878 | outdata = conn.read() 879 | else: 880 | s.send(indata) 881 | outdata = s.recv(1024) 882 | if indata == "STARTTLS" and outdata.strip().lower().startswith("ok"): 883 | if test_support.verbose: 884 | sys.stdout.write(" client: read %s from server, starting TLS...\n" % repr(outdata)) 885 | conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1) 886 | 887 | wrapped = True 888 | elif (indata == "ENDTLS" and 889 | outdata.strip().lower().startswith("ok")): 890 | if test_support.verbose: 891 | sys.stdout.write( 892 | " client: read %s from server, ending TLS...\n" 893 | % repr(outdata)) 894 | s = conn.unwrap() 895 | wrapped = False 896 | else: 897 | if test_support.verbose: 898 | sys.stdout.write(" client: read %s from server\n" % repr(outdata)) 899 | if test_support.verbose: 900 | sys.stdout.write(" client: closing connection.\n") 901 | if wrapped: 902 | conn.write("over\n") 903 | else: 904 | s.send("over\n") 905 | s.close() 906 | finally: 907 | server.stop() 908 | server.join() 909 | 910 | def testSocketServer(self): 911 | 912 | server = SocketServerHTTPSServer(TESTPORT, CERTFILE) 913 | flag = threading.Event() 914 | server.start(flag) 915 | # wait for it to start 916 | flag.wait() 917 | # try to connect 918 | try: 919 | try: 920 | if test_support.verbose: 921 | sys.stdout.write('\n') 922 | d1 = open(CERTFILE, 'rb').read() 923 | d2 = '' 924 | # now fetch the same data from the HTTPS server 925 | url = 'https://127.0.0.1:%d/%s' % ( 926 | TESTPORT, os.path.split(CERTFILE)[1]) 927 | f = urllib.urlopen(url) 928 | dlen = f.info().getheader("content-length") 929 | if dlen and (int(dlen) > 0): 930 | d2 = f.read(int(dlen)) 931 | if test_support.verbose: 932 | sys.stdout.write( 933 | " client: read %d bytes from remote server '%s'\n" 934 | % (len(d2), server)) 935 | f.close() 936 | except: 937 | print ''.join(traceback.format_exception(*sys.exc_info())) 938 | raise 939 | else: 940 | if not (d1 == d2): 941 | raise test_support.TestFailed("Couldn't fetch data from HTTPS server") 942 | finally: 943 | server.stop() 944 | server.join() 945 | 946 | def testWrappedAccept(self): 947 | 948 | if test_support.verbose: 949 | sys.stdout.write("\n") 950 | serverParamsTest(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED, 951 | CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23, 952 | chatty=True, connectionchatty=True, 953 | wrap_accepting_socket=True) 954 | 955 | def testAsyncoreServer(self): 956 | 957 | indata = "TEST MESSAGE of mixed case\n" 958 | 959 | if test_support.verbose: 960 | sys.stdout.write("\n") 961 | server = AsyncoreEchoServer(TESTPORT, CERTFILE) 962 | flag = threading.Event() 963 | server.start(flag) 964 | # wait for it to start 965 | flag.wait() 966 | # try to connect 967 | try: 968 | try: 969 | s = ssl.wrap_socket(socket.socket()) 970 | s.connect(('127.0.0.1', TESTPORT)) 971 | except ssl.SSLError, x: 972 | raise test_support.TestFailed("Unexpected SSL error: " + str(x)) 973 | except Exception, x: 974 | raise test_support.TestFailed("Unexpected exception: " + str(x)) 975 | else: 976 | if test_support.verbose: 977 | sys.stdout.write( 978 | " client: sending %s...\n" % (repr(indata))) 979 | s.write(indata) 980 | outdata = s.read() 981 | if test_support.verbose: 982 | sys.stdout.write(" client: read %s\n" % repr(outdata)) 983 | if outdata != indata.lower(): 984 | raise test_support.TestFailed( 985 | "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n" 986 | % (outdata[:min(len(outdata), 20)], len(outdata), 987 | indata[:min(len(indata), 20)].lower(), len(indata))) 988 | s.write("over\n") 989 | if test_support.verbose: 990 | sys.stdout.write(" client: closing connection.\n") 991 | s.close() 992 | finally: 993 | server.stop() 994 | # wait for server thread to end 995 | server.join() 996 | 997 | 998 | def findtestsocket(start, end): 999 | def testbind(i): 1000 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 1001 | try: 1002 | try: 1003 | s.bind(("127.0.0.1", i)) 1004 | except: 1005 | return 0 1006 | else: 1007 | return 1 1008 | finally: 1009 | s.close() 1010 | 1011 | for i in range(start, end): 1012 | if testbind(i) and testbind(i+1): 1013 | return i 1014 | return 0 1015 | 1016 | 1017 | def test_main(verbose=False): 1018 | if skip_expected: 1019 | raise test_support.TestSkipped("No SSL support") 1020 | 1021 | global CERTFILE, TESTPORT, SVN_PYTHON_ORG_ROOT_CERT 1022 | CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir, 1023 | "keycert.pem") 1024 | SVN_PYTHON_ORG_ROOT_CERT = os.path.join( 1025 | os.path.dirname(__file__) or os.curdir, "root.crt") 1026 | 1027 | if (not os.path.exists(CERTFILE) or 1028 | not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)): 1029 | raise test_support.TestFailed("Can't read certificate files!") 1030 | 1031 | TESTPORT = findtestsocket(10025, 12000) 1032 | if not TESTPORT: 1033 | raise test_support.TestFailed("Can't find open port to test servers on!") 1034 | 1035 | tests = [BasicTests] 1036 | 1037 | if test_support.is_resource_enabled('network'): 1038 | tests.append(NetworkedTests) 1039 | 1040 | if _have_threads: 1041 | if CERTFILE and test_support.is_resource_enabled('network'): 1042 | tests.append(ThreadedTests) 1043 | 1044 | test_support.run_unittest(*tests) 1045 | 1046 | 1047 | if __name__ == "__main__": 1048 | test_main() 1049 | --------------------------------------------------------------------------------