Merge branch 'mcfreis-clean-redo-in-steps' into incoming
This commit is contained in:
		
						commit
						343e243384
					
				
							
								
								
									
										183
									
								
								ChangeLog
									
									
									
									
									
								
							
							
						
						
									
										183
									
								
								ChangeLog
									
									
									
									
									
								
							@ -1,3 +1,186 @@
 | 
				
			|||||||
 | 
					2017-03-28  Björn Freise  <mcfreis@gmx.net>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Workaround for Windows concerning the MTU size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						* dtls/sslconnection.py: Hardcoded setting of the MTU size only for Windows and in case it is not already configured
 | 
				
			||||||
 | 
						* dtls/test/unit_wrapper.py: No user config of the MTU size; using the hardcoded one from SSLConnection
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2017-03-28  Björn Freise  <mcfreis@gmx.net>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Minor fixes and "hopefully" compatible to Ubuntu 16.04
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						* dtls/__init__.py: Removed wrapper import
 | 
				
			||||||
 | 
						* dtls/openssl.py: Fixed line endings to LF
 | 
				
			||||||
 | 
						* dtls/patch.py: Removed PROTOCOL_SSLv3 import and fixed line endings to LF
 | 
				
			||||||
 | 
						* dtls/sslconnection.py: Fixed line endings to LF
 | 
				
			||||||
 | 
						* dtls/test/certs/*_ec.pem: Fixed line endings to LF
 | 
				
			||||||
 | 
						* dtls/test/echo_seq.py: Fixed line endings to LF
 | 
				
			||||||
 | 
						* dtls/test/simple_client.py: Fixed line endings to LF
 | 
				
			||||||
 | 
						* dtls/test/unit.py: Fixed line endings to LF
 | 
				
			||||||
 | 
						* dtls/test/unit_wrapper.py: Corrected wrapper import and fixed line endings to LF
 | 
				
			||||||
 | 
						* dtls/util.py: Fixed line endings to LF
 | 
				
			||||||
 | 
						* dtls/wrapper.py: Corrected function naming to wrap_client() and wrap_server(); Fixed line endings to LF
 | 
				
			||||||
 | 
						* dtls/x509.py: Fixed line endings to LF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2017-03-23  Björn Freise  <mcfreis@gmx.net>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Patched ssl-Module with SSL_BUILD_*- and ERR_*- constants and added aliases for wrap_server() and wrap_client()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						* dtls/__init__.py: Added DtlsSocket() from wrapper and aliases for wrap_server() and wrap_client()
 | 
				
			||||||
 | 
						* dtls/err.py: Added patch_ssl_errors() to patch ssl-Module with ERR_* constants
 | 
				
			||||||
 | 
						* dtls/patch.py: Patched ssl-Module with SSL_BUILD_* constants and added call to patch_ssl_errors()
 | 
				
			||||||
 | 
						* dtls/wrapper.py:
 | 
				
			||||||
 | 
						    - Added a server and client function to alias/wrap DtlsSocket() creation
 | 
				
			||||||
 | 
						    - Cleanup of DtlsSocket.__init__()
 | 
				
			||||||
 | 
						    - Cleanup of exception handling in all member methods
 | 
				
			||||||
 | 
						    - Cleanup sendto() from client: no endless loop and first do a connect if not already connected
 | 
				
			||||||
 | 
						* dtls/test/unit_wrapper.py: Adopt the changes made described above
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2017-03-17  Björn Freise  <mcfreis@gmx.net>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Added a wrapper for a DTLS-Socket either as client or server - including unit tests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						* dtls/__init__.py: Import SSLContext() and SSL() for external use
 | 
				
			||||||
 | 
						* dtls/wrapper.py: Added class DtlsSocket() to be used as client or server
 | 
				
			||||||
 | 
						* dtls/test/unit_wrapper.py: unit test for DtlsSocket()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2017-03-17  Björn Freise  <mcfreis@gmx.net>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Added more on error evaluation and a method to get the peer certificate chain
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						* dtls/__init__.py: import error codes from err.py as error_codes for external access
 | 
				
			||||||
 | 
						* dtls/err.py: Added errors for ERR_WRONG_SSL_VERSION, ERR_CERTIFICATE_VERIFY_FAILED, ERR_NO_SHARED_CIPHER and ERR_SSL_HANDSHAKE_FAILURE
 | 
				
			||||||
 | 
						* dtls/openssl.py:
 | 
				
			||||||
 | 
							- Added constant SSL_BUILD_CHAIN_FLAG_NONE for SSL_CTX_build_cert_chain()
 | 
				
			||||||
 | 
							- Added method SSL_get_peer_cert_chain()
 | 
				
			||||||
 | 
						* dtls/patch.py: Added getpeercertchain() as method to ssl.SSLSocket()
 | 
				
			||||||
 | 
						* dtls/sslconnection.py:
 | 
				
			||||||
 | 
							- Bugfix SSLContext.set_ecdh_curve() returns 1 for success and 0 for failure
 | 
				
			||||||
 | 
							- SSLContext.build_cert_chain() changed default flags to SSL_BUILD_CHAIN_FLAG_NONE
 | 
				
			||||||
 | 
							- In SSLConnection() the mtu size gets only set if no user config function is given
 | 
				
			||||||
 | 
							- SSLConnection.listen() raises an exception for ERR_WRONG_VERSION_NUMBER, ERR_COOKIE_MISMATCH, ERR_NO_SHARED_CIPHER and all other unknown errors
 | 
				
			||||||
 | 
							- SSLConnection.read() and write() now can also raise ERR_PORT_UNREACHABLE
 | 
				
			||||||
 | 
							- If SSLConnection.write() successfully writes bytes to the peer, then the handshake is assumed to be okay
 | 
				
			||||||
 | 
							- Added method SSLConnection.getpeercertchain()
 | 
				
			||||||
 | 
						* dtls/test/unit.py: ThreadedEchoServer() with an extra exception branch for the newly raised exceptions in SSLConnection.listen()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2017-03-17  Björn Freise  <mcfreis@gmx.net>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Added certificate creation using ECDSA
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						* dtls/test/makecerts_ec.bat: creates ca-cert_ec.pem, keycert_ec.pem and server-cert_ec.pem
 | 
				
			||||||
 | 
						* dtls/test/openssl_ca.cnf and openssl_server.cnf: Added HOME to be able to use the conf file under windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2017-03-17  Björn Freise  <mcfreis@gmx.net>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Added an interface in SSLConnection() to access SSLContext() and SSL() for manipulating settings during creation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						* dtls/openssl.py:
 | 
				
			||||||
 | 
							- Added utility functions EC_curve_nist2nid() and EC_curve_nid2nist()
 | 
				
			||||||
 | 
						* dtls/patch.py:
 | 
				
			||||||
 | 
							- Extended wrap_socket() arguments with callbacks for user config functions of ssl context and ssl session values
 | 
				
			||||||
 | 
							- Extended SSLSocket() arguments with callbacks for user config functions of ssl context and ssl session values
 | 
				
			||||||
 | 
						* dtls/sslconnection.py:
 | 
				
			||||||
 | 
							- Extended SSLConnection() arguments with callbacks for user config functions of ssl context and ssl session values
 | 
				
			||||||
 | 
							- During the init of client and server the corresponding user config functions are called (if given)
 | 
				
			||||||
 | 
							- Added new classes SSLContext() [set_ciphers(), set_sigalgs(), set_curves(), set_ecdh_curve(), build_cert_chain(),
 | 
				
			||||||
 | 
							set_ssl_logging()] and SSL() [set_mtu(), set_link_mtu()]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2017-03-17  Björn Freise  <mcfreis@gmx.net>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Added methods getting the curves supported by the runtime openSSL lib
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						* dtls/openssl.py:
 | 
				
			||||||
 | 
							- Added class _EllipticCurve() for easy handling of the builtin curves
 | 
				
			||||||
 | 
							- Added wrapper get_elliptic_curves() - which uses _EllipticCurve()
 | 
				
			||||||
 | 
							- Added EC_get_builtin_curves(), EC_KEY_new_by_curve_name() and EC_KEY_free()
 | 
				
			||||||
 | 
							- Added OBJ_nid2sn() for translating numeric ids to names
 | 
				
			||||||
 | 
						* dtls/util.py: Added _EC_KEY() derived from _Rsrc() with own free/del method
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2017-03-17  Björn Freise  <mcfreis@gmx.net>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Added methods for setting and getting the curves used during negotiation and encryption
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						* dtls/openssl.py:
 | 
				
			||||||
 | 
							- Added SSL_CTX_set1_curves() and SSL_CTX_set1_curves_list()
 | 
				
			||||||
 | 
							- Added SSL_CTX_set_ecdh_auto() and SSL_CTX_set_tmp_ecdh()
 | 
				
			||||||
 | 
							- Added SSL_get1_curves(), SSL_get_shared_curve(), SSL_set1_curves() and SSL_set1_curves_list()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2017-03-17  Björn Freise  <mcfreis@gmx.net>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Added methods for setting the signature algorithms
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						* dtls/openssl.py:
 | 
				
			||||||
 | 
							- Added SSL_CTX_set1_client_sigalgs_list(), SSL_CTX_set1_client_sigalgs(), SSL_CTX_set1_sigalgs_list() and SSL_CTX_set1_sigalgs()
 | 
				
			||||||
 | 
							- Added SSL_set1_client_sigalgs_list(), SSL_set1_client_sigalgs(), SSL_set1_sigalgs_list() and SSL_set1_sigalgs()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2017-03-17  Björn Freise  <mcfreis@gmx.net>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Added method SSL_CTX_build_cert_chain()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						* dtls/openssl.py: Added SSL_CTX_build_cert_chain() and corresponding constants
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2017-03-17  Björn Freise  <mcfreis@gmx.net>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Added methods *_clear_options() and *_get_options()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						* dtls/openssl.py:
 | 
				
			||||||
 | 
							- Added SSL_CTX_clear_options() and SSL_CTX_get_options()
 | 
				
			||||||
 | 
							- Added SSL_clear_options() and SSL_get_options()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2017-03-17  Björn Freise  <mcfreis@gmx.net>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Added new methods for DTLSv1.2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						* dtls/err.py: Added error code ERR_WRONG_VERSION_NUMBER
 | 
				
			||||||
 | 
						* dtls/openssl.py: Added DTLS_server_method(), DTLSv1_2_server_method() and DTLSv1_2_client_method()
 | 
				
			||||||
 | 
						* dtls/patch.py: Default protocol DTLS for ssl.wrap_socket() and ssl.SSLSocket()
 | 
				
			||||||
 | 
						* dtls/sslconnection.py:
 | 
				
			||||||
 | 
							- Introduced PROTOCOL_DTLSv1_2 and PROTOCOL_DTLS (the latter one is a synonym for the "higher" version)
 | 
				
			||||||
 | 
							- Updated _init_client() and _init_server() with the new protocol methods
 | 
				
			||||||
 | 
							- Default protocol DTLS for SSLConnection()
 | 
				
			||||||
 | 
							- Return on ERR_WRONG_VERSION_NUMBER if client and server cannot agree on protocol version
 | 
				
			||||||
 | 
						* dtls/test/unit.py:
 | 
				
			||||||
 | 
							- Extended test_get_server_certificate() to iterate over the different protocol combinations
 | 
				
			||||||
 | 
							- Extended test_protocol_dtlsv1() to try the different protocol combinations between client and server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2017-03-17  Björn Freise  <mcfreis@gmx.net>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Updating openSSL libs to v1.0.2l-dev
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						* dtls/openssl.py: Added mtu-functions SSL_set_mtu() and DTLS_set_link_mtu()
 | 
				
			||||||
 | 
						* dtls/prebuilt/win32-*: Updated libs for x86 and x86_64 to version 1.0.2l-dev
 | 
				
			||||||
 | 
						* dtls/sslconnection.py: mtu size set hardcoded to 1500 - otherwise the windows implementation has problems
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2017-03-17  Björn Freise  <mcfreis@gmx.net>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Added interface for SSL_CTX_set_info_callback()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						* dtls/openssl.py:
 | 
				
			||||||
 | 
							- Added methods SSL_CTX_set_info_callback(), SSL_state_string_long(), SSL_alert_type_string_long() and SSL_alert_desc_string_long()
 | 
				
			||||||
 | 
							- Added constants for state and error evaluation during callback
 | 
				
			||||||
 | 
						* dtls/sslconnection.py: Added _ssl_logging_cb() as default callback function - only outputs messages when logger is active
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2017-03-17  Björn Freise  <mcfreis@gmx.net>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						SSL_write() extended to handle ctypes.Array as data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						* dtls/openssl.py: SSL_write() can handle ctypes.Array data
 | 
				
			||||||
 | 
						* dtls/sslconnection.py: Added missing import ERR_BOTH_KEY_CERT_FILES
 | 
				
			||||||
 | 
						* dtls/test/simple_client.py: Added basic test client to use with dtls/test/echo_seq.py
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2017-03-17  Björn Freise  <mcfreis@gmx.net>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Beautified lists and maps, grouped imports for easy merges in the future - no changed functionality!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						* dtls/openssl.py:
 | 
				
			||||||
 | 
							- Ordered constants according to header file from openSSL
 | 
				
			||||||
 | 
							- Beautified __all__-list and map for _make_function() in order to easy merges in the future
 | 
				
			||||||
 | 
							- Added a few returns in order to evaluate the success of the called methods
 | 
				
			||||||
 | 
						* dtls/patch.py: Grouped imports in the following order - system, local
 | 
				
			||||||
 | 
						* dtls/sslconnection.py: ssl protocol not hardcoded anymore for forked objects
 | 
				
			||||||
 | 
						* dtls/x509.py: logger messages working again
 | 
				
			||||||
 | 
					
 | 
				
			||||||
2017-02-27  Ray Brown  <code@liquibits.com>
 | 
					2017-02-27  Ray Brown  <code@liquibits.com>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	* dtls/openssl.py: support reading directly into given buffer instead of forcing buffer copy (for ssl module compatibility)
 | 
						* dtls/openssl.py: support reading directly into given buffer instead of forcing buffer copy (for ssl module compatibility)
 | 
				
			||||||
 | 
				
			|||||||
@ -59,5 +59,5 @@ def _prep_bins():
 | 
				
			|||||||
_prep_bins()  # prepare before module imports
 | 
					_prep_bins()  # prepare before module imports
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from patch import do_patch
 | 
					from patch import do_patch
 | 
				
			||||||
from sslconnection import SSLConnection
 | 
					from sslconnection import SSLContext, SSL, SSLConnection
 | 
				
			||||||
from demux import force_routing_demux, reset_default_demux
 | 
					from demux import force_routing_demux, reset_default_demux
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										15
									
								
								dtls/err.py
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								dtls/err.py
									
									
									
									
									
								
							@ -47,8 +47,21 @@ ERR_READ_TIMEOUT = 502
 | 
				
			|||||||
ERR_WRITE_TIMEOUT = 503
 | 
					ERR_WRITE_TIMEOUT = 503
 | 
				
			||||||
ERR_HANDSHAKE_TIMEOUT = 504
 | 
					ERR_HANDSHAKE_TIMEOUT = 504
 | 
				
			||||||
ERR_PORT_UNREACHABLE = 505
 | 
					ERR_PORT_UNREACHABLE = 505
 | 
				
			||||||
ERR_COOKIE_MISMATCH = 0x1408A134
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ERR_WRONG_SSL_VERSION = 0x1409210A
 | 
				
			||||||
 | 
					ERR_WRONG_VERSION_NUMBER = 0x1408A10B
 | 
				
			||||||
 | 
					ERR_COOKIE_MISMATCH = 0x1408A134
 | 
				
			||||||
 | 
					ERR_CERTIFICATE_VERIFY_FAILED = 0x14090086
 | 
				
			||||||
 | 
					ERR_NO_SHARED_CIPHER = 0x1408A0C1
 | 
				
			||||||
 | 
					ERR_SSL_HANDSHAKE_FAILURE = 0x1410C0E5
 | 
				
			||||||
 | 
					ERR_TLSV1_ALERT_UNKNOWN_CA = 0x14102418
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def patch_ssl_errors():
 | 
				
			||||||
 | 
					    import ssl
 | 
				
			||||||
 | 
					    errors = [i for i in globals().iteritems() if type(i[1]) == int and str(i[0]).startswith('ERR_')]
 | 
				
			||||||
 | 
					    for k, v in errors:
 | 
				
			||||||
 | 
					        if not hasattr(ssl, k):
 | 
				
			||||||
 | 
					            setattr(ssl, k, v)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SSLError(socket_error):
 | 
					class SSLError(socket_error):
 | 
				
			||||||
    """This exception is raised by modules in the dtls package."""
 | 
					    """This exception is raised by modules in the dtls package."""
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										505
									
								
								dtls/openssl.py
									
									
									
									
									
								
							
							
						
						
									
										505
									
								
								dtls/openssl.py
									
									
									
									
									
								
							@ -40,7 +40,7 @@ from os import path
 | 
				
			|||||||
from datetime import timedelta
 | 
					from datetime import timedelta
 | 
				
			||||||
from err import openssl_error
 | 
					from err import openssl_error
 | 
				
			||||||
from err import SSL_ERROR_NONE
 | 
					from err import SSL_ERROR_NONE
 | 
				
			||||||
from util import _BIO
 | 
					from util import _EC_KEY, _BIO
 | 
				
			||||||
import ctypes
 | 
					import ctypes
 | 
				
			||||||
from ctypes import CDLL
 | 
					from ctypes import CDLL
 | 
				
			||||||
from ctypes import CFUNCTYPE
 | 
					from ctypes import CFUNCTYPE
 | 
				
			||||||
@ -83,6 +83,7 @@ else:
 | 
				
			|||||||
BIO_NOCLOSE = 0x00
 | 
					BIO_NOCLOSE = 0x00
 | 
				
			||||||
BIO_CLOSE = 0x01
 | 
					BIO_CLOSE = 0x01
 | 
				
			||||||
SSLEAY_VERSION = 0
 | 
					SSLEAY_VERSION = 0
 | 
				
			||||||
 | 
					SSL_OP_NO_QUERY_MTU = 0x00001000
 | 
				
			||||||
SSL_OP_NO_COMPRESSION = 0x00020000
 | 
					SSL_OP_NO_COMPRESSION = 0x00020000
 | 
				
			||||||
SSL_VERIFY_NONE = 0x00
 | 
					SSL_VERIFY_NONE = 0x00
 | 
				
			||||||
SSL_VERIFY_PEER = 0x01
 | 
					SSL_VERIFY_PEER = 0x01
 | 
				
			||||||
@ -97,28 +98,128 @@ SSL_SESS_CACHE_NO_INTERNAL_LOOKUP = 0x0100
 | 
				
			|||||||
SSL_SESS_CACHE_NO_INTERNAL_STORE = 0x0200
 | 
					SSL_SESS_CACHE_NO_INTERNAL_STORE = 0x0200
 | 
				
			||||||
SSL_SESS_CACHE_NO_INTERNAL = \
 | 
					SSL_SESS_CACHE_NO_INTERNAL = \
 | 
				
			||||||
  SSL_SESS_CACHE_NO_INTERNAL_LOOKUP | SSL_SESS_CACHE_NO_INTERNAL_STORE
 | 
					  SSL_SESS_CACHE_NO_INTERNAL_LOOKUP | SSL_SESS_CACHE_NO_INTERNAL_STORE
 | 
				
			||||||
 | 
					SSL_BUILD_CHAIN_FLAG_NONE = 0x0
 | 
				
			||||||
 | 
					SSL_BUILD_CHAIN_FLAG_UNTRUSTED = 0x1
 | 
				
			||||||
 | 
					SSL_BUILD_CHAIN_FLAG_NO_ROOT = 0x2
 | 
				
			||||||
 | 
					SSL_BUILD_CHAIN_FLAG_CHECK = 0x4
 | 
				
			||||||
 | 
					SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR = 0x8
 | 
				
			||||||
 | 
					SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR = 0x10
 | 
				
			||||||
SSL_FILE_TYPE_PEM = 1
 | 
					SSL_FILE_TYPE_PEM = 1
 | 
				
			||||||
GEN_DIRNAME = 4
 | 
					GEN_DIRNAME = 4
 | 
				
			||||||
NID_subject_alt_name = 85
 | 
					NID_subject_alt_name = 85
 | 
				
			||||||
CRYPTO_LOCK = 1
 | 
					CRYPTO_LOCK = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SSL_ST_MASK = 0x0FFF
 | 
				
			||||||
 | 
					SSL_ST_CONNECT = 0x1000
 | 
				
			||||||
 | 
					SSL_ST_ACCEPT = 0x2000
 | 
				
			||||||
 | 
					SSL_ST_INIT = (SSL_ST_CONNECT | SSL_ST_ACCEPT)
 | 
				
			||||||
 | 
					SSL_ST_BEFORE = 0x4000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SSL_ST_OK = 0x03
 | 
				
			||||||
 | 
					SSL_ST_RENEGOTIATE = (0x04 | SSL_ST_INIT)
 | 
				
			||||||
 | 
					SSL_ST_ERR = 0x05
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SSL_CB_LOOP = 0x01
 | 
				
			||||||
 | 
					SSL_CB_EXIT = 0x02
 | 
				
			||||||
 | 
					SSL_CB_READ = 0x04
 | 
				
			||||||
 | 
					SSL_CB_WRITE = 0x08
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SSL_CB_ALERT = 0x4000
 | 
				
			||||||
 | 
					SSL_CB_READ_ALERT = (SSL_CB_ALERT | SSL_CB_READ)
 | 
				
			||||||
 | 
					SSL_CB_WRITE_ALERT = (SSL_CB_ALERT | SSL_CB_WRITE)
 | 
				
			||||||
 | 
					SSL_CB_ACCEPT_LOOP = (SSL_ST_ACCEPT | SSL_CB_LOOP)
 | 
				
			||||||
 | 
					SSL_CB_ACCEPT_EXIT = (SSL_ST_ACCEPT | SSL_CB_EXIT)
 | 
				
			||||||
 | 
					SSL_CB_CONNECT_LOOP = (SSL_ST_CONNECT | SSL_CB_LOOP)
 | 
				
			||||||
 | 
					SSL_CB_CONNECT_EXIT = (SSL_ST_CONNECT | SSL_CB_EXIT)
 | 
				
			||||||
 | 
					SSL_CB_HANDSHAKE_START = 0x10
 | 
				
			||||||
 | 
					SSL_CB_HANDSHAKE_DONE = 0x20
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Integer constants - internal
 | 
					# Integer constants - internal
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
SSL_CTRL_SET_SESS_CACHE_MODE = 44
 | 
					SSL_CTRL_SET_TMP_ECDH = 4
 | 
				
			||||||
SSL_CTRL_SET_READ_AHEAD = 41
 | 
					SSL_CTRL_SET_MTU = 17
 | 
				
			||||||
SSL_CTRL_OPTIONS = 32
 | 
					SSL_CTRL_OPTIONS = 32
 | 
				
			||||||
 | 
					SSL_CTRL_SET_READ_AHEAD = 41
 | 
				
			||||||
 | 
					SSL_CTRL_SET_SESS_CACHE_MODE = 44
 | 
				
			||||||
 | 
					SSL_CTRL_CLEAR_OPTIONS = 77
 | 
				
			||||||
 | 
					SSL_CTRL_GET_CURVES = 90
 | 
				
			||||||
 | 
					SSL_CTRL_SET_CURVES = 91
 | 
				
			||||||
 | 
					SSL_CTRL_SET_CURVES_LIST = 92
 | 
				
			||||||
 | 
					SSL_CTRL_GET_SHARED_CURVE = 93
 | 
				
			||||||
 | 
					SSL_CTRL_SET_ECDH_AUTO = 94
 | 
				
			||||||
 | 
					SSL_CTRL_SET_SIGALGS = 97
 | 
				
			||||||
 | 
					SSL_CTRL_SET_SIGALGS_LIST = 98
 | 
				
			||||||
 | 
					SSL_CTRL_SET_CLIENT_SIGALGS = 101
 | 
				
			||||||
 | 
					SSL_CTRL_SET_CLIENT_SIGALGS_LIST = 102
 | 
				
			||||||
 | 
					SSL_CTRL_BUILD_CERT_CHAIN = 105
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BIO_CTRL_INFO = 3
 | 
					BIO_CTRL_INFO = 3
 | 
				
			||||||
BIO_CTRL_DGRAM_SET_CONNECTED = 32
 | 
					BIO_CTRL_DGRAM_SET_CONNECTED = 32
 | 
				
			||||||
BIO_CTRL_DGRAM_GET_PEER = 46
 | 
					 | 
				
			||||||
BIO_CTRL_DGRAM_SET_PEER = 44
 | 
					BIO_CTRL_DGRAM_SET_PEER = 44
 | 
				
			||||||
 | 
					BIO_CTRL_DGRAM_GET_PEER = 46
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BIO_C_SET_NBIO = 102
 | 
					BIO_C_SET_NBIO = 102
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DTLS_CTRL_GET_TIMEOUT = 73
 | 
					DTLS_CTRL_GET_TIMEOUT = 73
 | 
				
			||||||
DTLS_CTRL_HANDLE_TIMEOUT = 74
 | 
					DTLS_CTRL_HANDLE_TIMEOUT = 74
 | 
				
			||||||
DTLS_CTRL_LISTEN = 75
 | 
					DTLS_CTRL_LISTEN = 75
 | 
				
			||||||
 | 
					DTLS_CTRL_SET_LINK_MTU = 120
 | 
				
			||||||
 | 
					
 | 
				
			||||||
X509_NAME_MAXLEN = 256
 | 
					X509_NAME_MAXLEN = 256
 | 
				
			||||||
GETS_MAXLEN = 2048
 | 
					GETS_MAXLEN = 2048
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _EllipticCurve(object):
 | 
				
			||||||
 | 
					    _curves = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @classmethod
 | 
				
			||||||
 | 
					    def _get_elliptic_curves(cls):
 | 
				
			||||||
 | 
					        if cls._curves is None:
 | 
				
			||||||
 | 
					            # Load once
 | 
				
			||||||
 | 
					            cls._curves = cls._load_elliptic_curves()
 | 
				
			||||||
 | 
					        return cls._curves
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @classmethod
 | 
				
			||||||
 | 
					    def _load_elliptic_curves(cls):
 | 
				
			||||||
 | 
					        num_curves = EC_get_builtin_curves(None, 0)
 | 
				
			||||||
 | 
					        if num_curves > 0:
 | 
				
			||||||
 | 
					            builtin_curves = create_string_buffer(sizeof(EC_builtin_curve) * num_curves)
 | 
				
			||||||
 | 
					            EC_get_builtin_curves(cast(builtin_curves, POINTER(EC_builtin_curve)), num_curves)
 | 
				
			||||||
 | 
					            return [cls(c.nid, OBJ_nid2sn(c.nid)) for c in cast(builtin_curves, POINTER(EC_builtin_curve))[:num_curves]]
 | 
				
			||||||
 | 
					        return []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, nid, name):
 | 
				
			||||||
 | 
					        self.nid = nid
 | 
				
			||||||
 | 
					        self.name = name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __repr__(self):
 | 
				
			||||||
 | 
					        return "<Curve %d %r>" % (self.nid, self.name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def to_EC_KEY(self):
 | 
				
			||||||
 | 
					        key = _EC_KEY(EC_KEY_new_by_curve_name(self.nid))
 | 
				
			||||||
 | 
					        return key if bool(key.value) else None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_elliptic_curves():
 | 
				
			||||||
 | 
					    u''' Return the available curves. If not yet loaded, then load them once.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    :rtype: list
 | 
				
			||||||
 | 
					    '''
 | 
				
			||||||
 | 
					    return _EllipticCurve._get_elliptic_curves()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_elliptic_curve(name):
 | 
				
			||||||
 | 
					    u''' Return the curve from the given name.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    :rtype: _EllipticCurve
 | 
				
			||||||
 | 
					    '''
 | 
				
			||||||
 | 
					    for curve in get_elliptic_curves():
 | 
				
			||||||
 | 
					        if curve.name == name:
 | 
				
			||||||
 | 
					            return curve
 | 
				
			||||||
 | 
					    raise ValueError("unknown curve name", name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Parameter data types
 | 
					# Parameter data types
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
@ -151,9 +252,9 @@ class FuncParam(object):
 | 
				
			|||||||
        return self._as_parameter.value
 | 
					        return self._as_parameter.value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DTLSv1Method(FuncParam):
 | 
					class DTLS_Method(FuncParam):
 | 
				
			||||||
    def __init__(self, value):
 | 
					    def __init__(self, value):
 | 
				
			||||||
        super(DTLSv1Method, self).__init__(value)
 | 
					        super(DTLS_Method, self).__init__(value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class BIO_METHOD(FuncParam):
 | 
					class BIO_METHOD(FuncParam):
 | 
				
			||||||
@ -176,6 +277,11 @@ class BIO(FuncParam):
 | 
				
			|||||||
        super(BIO, self).__init__(value)
 | 
					        super(BIO, self).__init__(value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class EC_KEY(FuncParam):
 | 
				
			||||||
 | 
					    def __init__(self, value):
 | 
				
			||||||
 | 
					        super(EC_KEY, self).__init__(value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class X509(FuncParam):
 | 
					class X509(FuncParam):
 | 
				
			||||||
    def __init__(self, value):
 | 
					    def __init__(self, value):
 | 
				
			||||||
        super(X509, self).__init__(value)
 | 
					        super(X509, self).__init__(value)
 | 
				
			||||||
@ -246,6 +352,13 @@ class GENERAL_NAMES(STACK):
 | 
				
			|||||||
        super(GENERAL_NAMES, self).__init__(value)
 | 
					        super(GENERAL_NAMES, self).__init__(value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class STACK_OF_X509(STACK):
 | 
				
			||||||
 | 
					    stack_element_type = X509
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, value):
 | 
				
			||||||
 | 
					        super(STACK_OF_X509, self).__init__(value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class X509_NAME_ENTRY(Structure):
 | 
					class X509_NAME_ENTRY(Structure):
 | 
				
			||||||
    _fields_ = [("object", c_void_p),
 | 
					    _fields_ = [("object", c_void_p),
 | 
				
			||||||
                ("value", c_void_p),
 | 
					                ("value", c_void_p),
 | 
				
			||||||
@ -281,6 +394,11 @@ class TIMEVAL(Structure):
 | 
				
			|||||||
                ("tv_usec", c_long)]
 | 
					                ("tv_usec", c_long)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class EC_builtin_curve(Structure):
 | 
				
			||||||
 | 
					    _fields_ = [("nid", c_int),
 | 
				
			||||||
 | 
					                ("comment", c_char_p)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Socket address conversions
 | 
					# Socket address conversions
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
@ -470,85 +588,139 @@ def _make_function(name, lib, args, export=True, errcheck="default"):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
_subst = {c_long_parm: c_long}
 | 
					_subst = {c_long_parm: c_long}
 | 
				
			||||||
_sigs = {}
 | 
					_sigs = {}
 | 
				
			||||||
__all__ = ["BIO_NOCLOSE", "BIO_CLOSE",
 | 
					__all__ = [
 | 
				
			||||||
 | 
					    # Constants
 | 
				
			||||||
 | 
					    "BIO_NOCLOSE", "BIO_CLOSE",
 | 
				
			||||||
    "SSLEAY_VERSION",
 | 
					    "SSLEAY_VERSION",
 | 
				
			||||||
           "SSL_OP_NO_COMPRESSION",
 | 
					    "SSL_OP_NO_QUERY_MTU", "SSL_OP_NO_COMPRESSION",
 | 
				
			||||||
    "SSL_VERIFY_NONE", "SSL_VERIFY_PEER",
 | 
					    "SSL_VERIFY_NONE", "SSL_VERIFY_PEER",
 | 
				
			||||||
    "SSL_VERIFY_FAIL_IF_NO_PEER_CERT", "SSL_VERIFY_CLIENT_ONCE",
 | 
					    "SSL_VERIFY_FAIL_IF_NO_PEER_CERT", "SSL_VERIFY_CLIENT_ONCE",
 | 
				
			||||||
    "SSL_SESS_CACHE_OFF", "SSL_SESS_CACHE_CLIENT",
 | 
					    "SSL_SESS_CACHE_OFF", "SSL_SESS_CACHE_CLIENT",
 | 
				
			||||||
    "SSL_SESS_CACHE_SERVER", "SSL_SESS_CACHE_BOTH",
 | 
					    "SSL_SESS_CACHE_SERVER", "SSL_SESS_CACHE_BOTH",
 | 
				
			||||||
    "SSL_SESS_CACHE_NO_AUTO_CLEAR", "SSL_SESS_CACHE_NO_INTERNAL_LOOKUP",
 | 
					    "SSL_SESS_CACHE_NO_AUTO_CLEAR", "SSL_SESS_CACHE_NO_INTERNAL_LOOKUP",
 | 
				
			||||||
    "SSL_SESS_CACHE_NO_INTERNAL_STORE", "SSL_SESS_CACHE_NO_INTERNAL",
 | 
					    "SSL_SESS_CACHE_NO_INTERNAL_STORE", "SSL_SESS_CACHE_NO_INTERNAL",
 | 
				
			||||||
 | 
					    "SSL_ST_MASK", "SSL_ST_CONNECT", "SSL_ST_ACCEPT", "SSL_ST_INIT", "SSL_ST_BEFORE", "SSL_ST_OK",
 | 
				
			||||||
 | 
					    "SSL_ST_RENEGOTIATE", "SSL_ST_ERR", "SSL_CB_LOOP", "SSL_CB_EXIT", "SSL_CB_READ", "SSL_CB_WRITE",
 | 
				
			||||||
 | 
					    "SSL_CB_ALERT", "SSL_CB_READ_ALERT", "SSL_CB_WRITE_ALERT",
 | 
				
			||||||
 | 
					    "SSL_CB_ACCEPT_LOOP", "SSL_CB_ACCEPT_EXIT",
 | 
				
			||||||
 | 
					    "SSL_CB_CONNECT_LOOP", "SSL_CB_CONNECT_EXIT",
 | 
				
			||||||
 | 
					    "SSL_CB_HANDSHAKE_START", "SSL_CB_HANDSHAKE_DONE",
 | 
				
			||||||
 | 
					    "SSL_BUILD_CHAIN_FLAG_NONE", "SSL_BUILD_CHAIN_FLAG_UNTRUSTED", "SSL_BUILD_CHAIN_FLAG_NO_ROOT",
 | 
				
			||||||
 | 
					    "SSL_BUILD_CHAIN_FLAG_CHECK", "SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR", "SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR",
 | 
				
			||||||
    "SSL_FILE_TYPE_PEM",
 | 
					    "SSL_FILE_TYPE_PEM",
 | 
				
			||||||
    "GEN_DIRNAME", "NID_subject_alt_name",
 | 
					    "GEN_DIRNAME", "NID_subject_alt_name",
 | 
				
			||||||
    "CRYPTO_LOCK",
 | 
					    "CRYPTO_LOCK",
 | 
				
			||||||
 | 
					    # Methods
 | 
				
			||||||
    "CRYPTO_set_locking_callback",
 | 
					    "CRYPTO_set_locking_callback",
 | 
				
			||||||
    "DTLSv1_get_timeout", "DTLSv1_handle_timeout",
 | 
					    "DTLSv1_get_timeout", "DTLSv1_handle_timeout",
 | 
				
			||||||
    "DTLSv1_listen",
 | 
					    "DTLSv1_listen",
 | 
				
			||||||
 | 
					    "DTLS_set_link_mtu",
 | 
				
			||||||
    "BIO_gets", "BIO_read", "BIO_get_mem_data",
 | 
					    "BIO_gets", "BIO_read", "BIO_get_mem_data",
 | 
				
			||||||
    "BIO_dgram_set_connected",
 | 
					    "BIO_dgram_set_connected",
 | 
				
			||||||
    "BIO_dgram_get_peer", "BIO_dgram_set_peer",
 | 
					    "BIO_dgram_get_peer", "BIO_dgram_set_peer",
 | 
				
			||||||
    "BIO_set_nbio",
 | 
					    "BIO_set_nbio",
 | 
				
			||||||
    "SSL_CTX_set_session_cache_mode", "SSL_CTX_set_read_ahead",
 | 
					    "SSL_CTX_set_session_cache_mode", "SSL_CTX_set_read_ahead",
 | 
				
			||||||
           "SSL_CTX_set_options",
 | 
					    "SSL_CTX_set_options", "SSL_CTX_clear_options", "SSL_CTX_get_options",
 | 
				
			||||||
 | 
					    "SSL_CTX_set1_client_sigalgs_list", "SSL_CTX_set1_client_sigalgs",
 | 
				
			||||||
 | 
					    "SSL_CTX_set1_sigalgs_list", "SSL_CTX_set1_sigalgs",
 | 
				
			||||||
 | 
					    "SSL_CTX_set1_curves", "SSL_CTX_set1_curves_list",
 | 
				
			||||||
 | 
					    "SSL_CTX_set_info_callback",
 | 
				
			||||||
 | 
					    "SSL_CTX_build_cert_chain",
 | 
				
			||||||
 | 
					    "SSL_CTX_set_ecdh_auto",
 | 
				
			||||||
 | 
					    "SSL_CTX_set_tmp_ecdh",
 | 
				
			||||||
    "SSL_read", "SSL_write",
 | 
					    "SSL_read", "SSL_write",
 | 
				
			||||||
 | 
					    "SSL_set_options", "SSL_clear_options", "SSL_get_options",
 | 
				
			||||||
 | 
					    "SSL_set1_client_sigalgs_list", "SSL_set1_client_sigalgs",
 | 
				
			||||||
 | 
					    "SSL_set1_sigalgs_list", "SSL_set1_sigalgs",
 | 
				
			||||||
 | 
					    "SSL_get1_curves", "SSL_get_shared_curve",
 | 
				
			||||||
 | 
					    "SSL_set1_curves", "SSL_set1_curves_list",
 | 
				
			||||||
 | 
					    "SSL_set_mtu",
 | 
				
			||||||
 | 
					    "SSL_state_string_long", "SSL_alert_type_string_long", "SSL_alert_desc_string_long",
 | 
				
			||||||
 | 
					    "SSL_get_peer_cert_chain",
 | 
				
			||||||
    "SSL_CTX_set_cookie_cb",
 | 
					    "SSL_CTX_set_cookie_cb",
 | 
				
			||||||
    "OBJ_obj2txt", "decode_ASN1_STRING", "ASN1_TIME_print",
 | 
					    "OBJ_obj2txt", "decode_ASN1_STRING", "ASN1_TIME_print",
 | 
				
			||||||
 | 
					    "OBJ_nid2sn",
 | 
				
			||||||
    "X509_get_notAfter",
 | 
					    "X509_get_notAfter",
 | 
				
			||||||
    "ASN1_item_d2i", "GENERAL_NAME_print",
 | 
					    "ASN1_item_d2i", "GENERAL_NAME_print",
 | 
				
			||||||
    "sk_value",
 | 
					    "sk_value",
 | 
				
			||||||
    "sk_pop_free",
 | 
					    "sk_pop_free",
 | 
				
			||||||
           "i2d_X509"]  # note: the following map adds to this list
 | 
					    "i2d_X509",
 | 
				
			||||||
 | 
					    "get_elliptic_curves",
 | 
				
			||||||
 | 
					]  # note: the following map adds to this list
 | 
				
			||||||
 | 
					
 | 
				
			||||||
map(lambda x: _make_function(*x), (
 | 
					map(lambda x: _make_function(*x), (
 | 
				
			||||||
    ("SSL_library_init", libssl, ((c_int, "ret"),)),
 | 
					    ("SSL_library_init", libssl,
 | 
				
			||||||
    ("SSL_load_error_strings", libssl, ((None, "ret"),)),
 | 
					     ((c_int, "ret"),)),
 | 
				
			||||||
    ("SSLeay", libcrypto, ((c_long_parm, "ret"),)),
 | 
					    ("SSL_load_error_strings", libssl,
 | 
				
			||||||
    ("SSLeay_version", libcrypto, ((c_char_p, "ret"), (c_int, "t"))),
 | 
					     ((None, "ret"),)),
 | 
				
			||||||
 | 
					    ("SSLeay", libcrypto,
 | 
				
			||||||
 | 
					     ((c_long_parm, "ret"),)),
 | 
				
			||||||
 | 
					    ("SSLeay_version", libcrypto,
 | 
				
			||||||
 | 
					     ((c_char_p, "ret"), (c_int, "t"))),
 | 
				
			||||||
    ("CRYPTO_set_locking_callback", libcrypto,
 | 
					    ("CRYPTO_set_locking_callback", libcrypto,
 | 
				
			||||||
     ((None, "ret"), (c_void_p, "func")), False),
 | 
					     ((None, "ret"), (c_void_p, "func")), False),
 | 
				
			||||||
    ("CRYPTO_get_id_callback", libcrypto, ((c_void_p, "ret"),), True, None),
 | 
					    ("CRYPTO_get_id_callback", libcrypto,
 | 
				
			||||||
    ("CRYPTO_num_locks", libcrypto, ((c_int, "ret"),)),
 | 
					     ((c_void_p, "ret"),), True, None),
 | 
				
			||||||
    ("DTLSv1_server_method", libssl, ((DTLSv1Method, "ret"),)),
 | 
					    ("CRYPTO_num_locks", libcrypto,
 | 
				
			||||||
    ("DTLSv1_client_method", libssl, ((DTLSv1Method, "ret"),)),
 | 
					     ((c_int, "ret"),)),
 | 
				
			||||||
    ("SSL_CTX_new", libssl, ((SSLCTX, "ret"), (DTLSv1Method, "meth"))),
 | 
					    ("DTLS_server_method", libssl,
 | 
				
			||||||
    ("SSL_CTX_free", libssl, ((None, "ret"), (SSLCTX, "ctx"))),
 | 
					     ((DTLS_Method, "ret"),)),
 | 
				
			||||||
 | 
					    ("DTLSv1_server_method", libssl,
 | 
				
			||||||
 | 
					     ((DTLS_Method, "ret"),)),
 | 
				
			||||||
 | 
					    ("DTLSv1_2_server_method", libssl,
 | 
				
			||||||
 | 
					     ((DTLS_Method, "ret"),)),
 | 
				
			||||||
 | 
					    ("DTLSv1_client_method", libssl,
 | 
				
			||||||
 | 
					     ((DTLS_Method, "ret"),)),
 | 
				
			||||||
 | 
					    ("DTLSv1_2_client_method", libssl,
 | 
				
			||||||
 | 
					     ((DTLS_Method, "ret"),)),
 | 
				
			||||||
 | 
					    ("SSL_CTX_new", libssl,
 | 
				
			||||||
 | 
					     ((SSLCTX, "ret"), (DTLS_Method, "meth"))),
 | 
				
			||||||
 | 
					    ("SSL_CTX_free", libssl,
 | 
				
			||||||
 | 
					     ((None, "ret"), (SSLCTX, "ctx"))),
 | 
				
			||||||
    ("SSL_CTX_set_cookie_generate_cb", libssl,
 | 
					    ("SSL_CTX_set_cookie_generate_cb", libssl,
 | 
				
			||||||
     ((None, "ret"), (SSLCTX, "ctx"), (c_void_p, "app_gen_cookie_cb")), False),
 | 
					     ((None, "ret"), (SSLCTX, "ctx"), (c_void_p, "app_gen_cookie_cb")), False),
 | 
				
			||||||
    ("SSL_CTX_set_cookie_verify_cb", libssl,
 | 
					    ("SSL_CTX_set_cookie_verify_cb", libssl,
 | 
				
			||||||
     ((None, "ret"), (SSLCTX, "ctx"), (c_void_p, "app_verify_cookie_cb")),
 | 
					     ((None, "ret"), (SSLCTX, "ctx"), (c_void_p, "app_verify_cookie_cb")), False),
 | 
				
			||||||
     False),
 | 
					    ("SSL_CTX_set_info_callback", libssl,
 | 
				
			||||||
    ("SSL_new", libssl, ((SSL, "ret"), (SSLCTX, "ctx"))),
 | 
					     ((None, "ret"), (SSLCTX, "ctx"), (c_void_p, "app_info_cb")), False),
 | 
				
			||||||
    ("SSL_free", libssl, ((None, "ret"), (SSL, "ssl"))),
 | 
					    ("SSL_new", libssl,
 | 
				
			||||||
 | 
					     ((SSL, "ret"), (SSLCTX, "ctx"))),
 | 
				
			||||||
 | 
					    ("SSL_free", libssl,
 | 
				
			||||||
 | 
					     ((None, "ret"), (SSL, "ssl"))),
 | 
				
			||||||
    ("SSL_set_bio", libssl,
 | 
					    ("SSL_set_bio", libssl,
 | 
				
			||||||
     ((None, "ret"), (SSL, "ssl"), (BIO, "rbio"), (BIO, "wbio"))),
 | 
					     ((None, "ret"), (SSL, "ssl"), (BIO, "rbio"), (BIO, "wbio"))),
 | 
				
			||||||
    ("BIO_new", libcrypto, ((BIO, "ret"), (BIO_METHOD, "type"))),
 | 
					    ("BIO_new", libcrypto,
 | 
				
			||||||
    ("BIO_s_mem", libcrypto, ((BIO_METHOD, "ret"),)),
 | 
					     ((BIO, "ret"), (BIO_METHOD, "type"))),
 | 
				
			||||||
 | 
					    ("BIO_s_mem", libcrypto,
 | 
				
			||||||
 | 
					     ((BIO_METHOD, "ret"),)),
 | 
				
			||||||
    ("BIO_new_file", libcrypto,
 | 
					    ("BIO_new_file", libcrypto,
 | 
				
			||||||
     ((BIO, "ret"), (c_char_p, "filename"), (c_char_p, "mode"))),
 | 
					     ((BIO, "ret"), (c_char_p, "filename"), (c_char_p, "mode"))),
 | 
				
			||||||
    ("BIO_new_dgram", libcrypto,
 | 
					    ("BIO_new_dgram", libcrypto,
 | 
				
			||||||
     ((BIO, "ret"), (c_int, "fd"), (c_int, "close_flag"))),
 | 
					     ((BIO, "ret"), (c_int, "fd"), (c_int, "close_flag"))),
 | 
				
			||||||
    ("BIO_free", libcrypto, ((c_int, "ret"), (BIO, "a"))),
 | 
					    ("BIO_free", libcrypto,
 | 
				
			||||||
 | 
					     ((c_int, "ret"), (BIO, "a"))),
 | 
				
			||||||
    ("BIO_gets", libcrypto,
 | 
					    ("BIO_gets", libcrypto,
 | 
				
			||||||
     ((c_int, "ret"), (BIO, "b"), (POINTER(c_char), "buf"), (c_int, "size")),
 | 
					     ((c_int, "ret"), (BIO, "b"), (POINTER(c_char), "buf"), (c_int, "size")), False),
 | 
				
			||||||
     False),
 | 
					 | 
				
			||||||
    ("BIO_read", libcrypto,
 | 
					    ("BIO_read", libcrypto,
 | 
				
			||||||
     ((c_int, "ret"), (BIO, "b"), (c_void_p, "buf"), (c_int, "len")), False),
 | 
					     ((c_int, "ret"), (BIO, "b"), (c_void_p, "buf"), (c_int, "len")), False),
 | 
				
			||||||
    ("SSL_CTX_ctrl", libssl,
 | 
					    ("SSL_CTX_ctrl", libssl,
 | 
				
			||||||
     ((c_long_parm, "ret"), (SSLCTX, "ctx"), (c_int, "cmd"), (c_long, "larg"),
 | 
					     ((c_long_parm, "ret"), (SSLCTX, "ctx"), (c_int, "cmd"), (c_long, "larg"), (c_void_p, "parg")), False),
 | 
				
			||||||
      (c_void_p, "parg")), False),
 | 
					 | 
				
			||||||
    ("BIO_ctrl", libcrypto,
 | 
					    ("BIO_ctrl", libcrypto,
 | 
				
			||||||
     ((c_long_parm, "ret"), (BIO, "bp"), (c_int, "cmd"), (c_long, "larg"),
 | 
					     ((c_long_parm, "ret"), (BIO, "bp"), (c_int, "cmd"), (c_long, "larg"), (c_void_p, "parg")), False),
 | 
				
			||||||
      (c_void_p, "parg")), False),
 | 
					 | 
				
			||||||
    ("SSL_ctrl", libssl,
 | 
					    ("SSL_ctrl", libssl,
 | 
				
			||||||
     ((c_long_parm, "ret"), (SSL, "ssl"), (c_int, "cmd"), (c_long, "larg"),
 | 
					     ((c_long_parm, "ret"), (SSL, "ssl"), (c_int, "cmd"), (c_long, "larg"), (c_void_p, "parg")), False),
 | 
				
			||||||
      (c_void_p, "parg")), False),
 | 
					    ("ERR_get_error", libcrypto,
 | 
				
			||||||
    ("ERR_get_error", libcrypto, ((c_long_parm, "ret"),), False),
 | 
					     ((c_long_parm, "ret"),), False),
 | 
				
			||||||
    ("ERR_error_string_n", libcrypto,
 | 
					    ("ERR_error_string_n", libcrypto,
 | 
				
			||||||
     ((None, "ret"), (c_ulong, "e"), (c_char_p, "buf"), (c_size_t, "len")),
 | 
					     ((None, "ret"), (c_ulong, "e"), (c_char_p, "buf"), (c_size_t, "len")), False),
 | 
				
			||||||
     False),
 | 
					    ("SSL_get_error", libssl,
 | 
				
			||||||
    ("SSL_get_error", libssl, ((c_int, "ret"), (SSL, "ssl"), (c_int, "ret")),
 | 
					     ((c_int, "ret"), (SSL, "ssl"), (c_int, "ret")), False, None),
 | 
				
			||||||
     False, None),
 | 
					    ("SSL_state_string_long", libssl,
 | 
				
			||||||
 | 
					     ((c_char_p, "ret"), (SSL, "ssl")), False),
 | 
				
			||||||
 | 
					    ("SSL_alert_type_string_long", libssl,
 | 
				
			||||||
 | 
					     ((c_char_p, "ret"), (c_int, "value")), False),
 | 
				
			||||||
 | 
					    ("SSL_alert_desc_string_long", libssl,
 | 
				
			||||||
 | 
					     ((c_char_p, "ret"), (c_int, "value")), False),
 | 
				
			||||||
    ("SSL_CTX_set_cipher_list", libssl,
 | 
					    ("SSL_CTX_set_cipher_list", libssl,
 | 
				
			||||||
     ((c_int, "ret"), (SSLCTX, "ctx"), (c_char_p, "str"))),
 | 
					     ((c_int, "ret"), (SSLCTX, "ctx"), (c_char_p, "str"))),
 | 
				
			||||||
    ("SSL_CTX_use_certificate_file", libssl,
 | 
					    ("SSL_CTX_use_certificate_file", libssl,
 | 
				
			||||||
@ -558,36 +730,45 @@ map(lambda x: _make_function(*x), (
 | 
				
			|||||||
    ("SSL_CTX_use_PrivateKey_file", libssl,
 | 
					    ("SSL_CTX_use_PrivateKey_file", libssl,
 | 
				
			||||||
     ((c_int, "ret"), (SSLCTX, "ctx"), (c_char_p, "file"), (c_int, "type"))),
 | 
					     ((c_int, "ret"), (SSLCTX, "ctx"), (c_char_p, "file"), (c_int, "type"))),
 | 
				
			||||||
    ("SSL_CTX_load_verify_locations", libssl,
 | 
					    ("SSL_CTX_load_verify_locations", libssl,
 | 
				
			||||||
     ((c_int, "ret"), (SSLCTX, "ctx"), (c_char_p, "CAfile"),
 | 
					     ((c_int, "ret"), (SSLCTX, "ctx"), (c_char_p, "CAfile"), (c_char_p, "CApath"))),
 | 
				
			||||||
      (c_char_p, "CApath"))),
 | 
					 | 
				
			||||||
    ("SSL_CTX_set_verify", libssl,
 | 
					    ("SSL_CTX_set_verify", libssl,
 | 
				
			||||||
     ((None, "ret"), (SSLCTX, "ctx"), (c_int, "mode"),
 | 
					     ((None, "ret"), (SSLCTX, "ctx"), (c_int, "mode"), (c_void_p, "verify_callback", 1, None))),
 | 
				
			||||||
      (c_void_p, "verify_callback", 1, None))),
 | 
					    ("SSL_accept", libssl,
 | 
				
			||||||
    ("SSL_accept", libssl, ((c_int, "ret"), (SSL, "ssl"))),
 | 
					     ((c_int, "ret"), (SSL, "ssl"))),
 | 
				
			||||||
    ("SSL_connect", libssl, ((c_int, "ret"), (SSL, "ssl"))),
 | 
					    ("SSL_connect", libssl,
 | 
				
			||||||
    ("SSL_set_connect_state", libssl, ((None, "ret"), (SSL, "ssl"))),
 | 
					     ((c_int, "ret"), (SSL, "ssl"))),
 | 
				
			||||||
    ("SSL_set_accept_state", libssl, ((None, "ret"), (SSL, "ssl"))),
 | 
					    ("SSL_set_connect_state", libssl,
 | 
				
			||||||
    ("SSL_do_handshake", libssl, ((c_int, "ret"), (SSL, "ssl"))),
 | 
					     ((None, "ret"), (SSL, "ssl"))),
 | 
				
			||||||
    ("SSL_get_peer_certificate", libssl, ((X509, "ret"), (SSL, "ssl"))),
 | 
					    ("SSL_set_accept_state", libssl,
 | 
				
			||||||
 | 
					     ((None, "ret"), (SSL, "ssl"))),
 | 
				
			||||||
 | 
					    ("SSL_do_handshake", libssl,
 | 
				
			||||||
 | 
					     ((c_int, "ret"), (SSL, "ssl"))),
 | 
				
			||||||
 | 
					    ("SSL_get_peer_certificate", libssl,
 | 
				
			||||||
 | 
					     ((X509, "ret"), (SSL, "ssl"))),
 | 
				
			||||||
 | 
					    ("SSL_get_peer_cert_chain", libssl,
 | 
				
			||||||
 | 
					     ((STACK_OF_X509, "ret"), (SSL, "ssl")), False),
 | 
				
			||||||
    ("SSL_read", libssl,
 | 
					    ("SSL_read", libssl,
 | 
				
			||||||
     ((c_int, "ret"), (SSL, "ssl"), (c_void_p, "buf"), (c_int, "num")), False),
 | 
					     ((c_int, "ret"), (SSL, "ssl"), (c_void_p, "buf"), (c_int, "num")), False),
 | 
				
			||||||
    ("SSL_write", libssl,
 | 
					    ("SSL_write", libssl,
 | 
				
			||||||
     ((c_int, "ret"), (SSL, "ssl"), (c_void_p, "buf"), (c_int, "num")), False),
 | 
					     ((c_int, "ret"), (SSL, "ssl"), (c_void_p, "buf"), (c_int, "num")), False),
 | 
				
			||||||
    ("SSL_pending", libssl, ((c_int, "ret"), (SSL, "ssl")), True, None),
 | 
					    ("SSL_pending", libssl,
 | 
				
			||||||
    ("SSL_shutdown", libssl, ((c_int, "ret"), (SSL, "ssl"))),
 | 
					     ((c_int, "ret"), (SSL, "ssl")), True, None),
 | 
				
			||||||
 | 
					    ("SSL_shutdown", libssl,
 | 
				
			||||||
 | 
					     ((c_int, "ret"), (SSL, "ssl"))),
 | 
				
			||||||
    ("SSL_set_read_ahead", libssl,
 | 
					    ("SSL_set_read_ahead", libssl,
 | 
				
			||||||
     ((None, "ret"), (SSL, "ssl"), (c_int, "yes"))),
 | 
					     ((None, "ret"), (SSL, "ssl"), (c_int, "yes"))),
 | 
				
			||||||
    ("X509_free", libcrypto, ((None, "ret"), (X509, "a"))),
 | 
					    ("X509_free", libcrypto,
 | 
				
			||||||
 | 
					     ((None, "ret"), (X509, "a"))),
 | 
				
			||||||
    ("PEM_read_bio_X509_AUX", libcrypto,
 | 
					    ("PEM_read_bio_X509_AUX", libcrypto,
 | 
				
			||||||
     ((X509, "ret"), (BIO, "bp"), (c_void_p, "x", 1, None),
 | 
					     ((X509, "ret"), (BIO, "bp"), (c_void_p, "x", 1, None), (c_void_p, "cb", 1, None), (c_void_p, "u", 1, None))),
 | 
				
			||||||
      (c_void_p, "cb", 1, None), (c_void_p, "u", 1, None))),
 | 
					 | 
				
			||||||
    ("OBJ_obj2txt", libcrypto,
 | 
					    ("OBJ_obj2txt", libcrypto,
 | 
				
			||||||
     ((c_int, "ret"), (POINTER(c_char), "buf"), (c_int, "buf_len"),
 | 
					     ((c_int, "ret"), (POINTER(c_char), "buf"), (c_int, "buf_len"), (ASN1_OBJECT, "a"), (c_int, "no_name")), False),
 | 
				
			||||||
      (ASN1_OBJECT, "a"), (c_int, "no_name")), False),
 | 
					    ("OBJ_nid2sn", libcrypto,
 | 
				
			||||||
    ("CRYPTO_free", libcrypto, ((None, "ret"), (c_void_p, "ptr"))),
 | 
					     ((c_char_p, "ret"), (c_int, "n")), False),
 | 
				
			||||||
 | 
					    ("CRYPTO_free", libcrypto,
 | 
				
			||||||
 | 
					     ((None, "ret"), (c_void_p, "ptr"))),
 | 
				
			||||||
    ("ASN1_STRING_to_UTF8", libcrypto,
 | 
					    ("ASN1_STRING_to_UTF8", libcrypto,
 | 
				
			||||||
     ((c_int, "ret"), (POINTER(POINTER(c_ubyte)), "out"), (ASN1_STRING, "in")),
 | 
					     ((c_int, "ret"), (POINTER(POINTER(c_ubyte)), "out"), (ASN1_STRING, "in")), False),
 | 
				
			||||||
     False),
 | 
					 | 
				
			||||||
    ("X509_NAME_entry_count", libcrypto,
 | 
					    ("X509_NAME_entry_count", libcrypto,
 | 
				
			||||||
     ((c_int, "ret"), (POINTER(X509_name_st), "name")), True, None),
 | 
					     ((c_int, "ret"), (POINTER(X509_name_st), "name")), True, None),
 | 
				
			||||||
    ("X509_NAME_get_entry", libcrypto,
 | 
					    ("X509_NAME_get_entry", libcrypto,
 | 
				
			||||||
@ -602,34 +783,41 @@ map(lambda x: _make_function(*x), (
 | 
				
			|||||||
    ("ASN1_TIME_print", libcrypto,
 | 
					    ("ASN1_TIME_print", libcrypto,
 | 
				
			||||||
     ((c_int, "ret"), (BIO, "fp"), (ASN1_TIME, "a")), False),
 | 
					     ((c_int, "ret"), (BIO, "fp"), (ASN1_TIME, "a")), False),
 | 
				
			||||||
    ("X509_get_ext_by_NID", libcrypto,
 | 
					    ("X509_get_ext_by_NID", libcrypto,
 | 
				
			||||||
     ((c_int, "ret"), (X509, "x"), (c_int, "nid"), (c_int, "lastpos")),
 | 
					     ((c_int, "ret"), (X509, "x"), (c_int, "nid"), (c_int, "lastpos")), True, None),
 | 
				
			||||||
     True, None),
 | 
					 | 
				
			||||||
    ("X509_get_ext", libcrypto,
 | 
					    ("X509_get_ext", libcrypto,
 | 
				
			||||||
     ((POINTER(X509_EXTENSION), "ret"), (X509, "x"), (c_int, "loc")),
 | 
					     ((POINTER(X509_EXTENSION), "ret"), (X509, "x"), (c_int, "loc")), True, errcheck_p),
 | 
				
			||||||
     True, errcheck_p),
 | 
					 | 
				
			||||||
    ("X509V3_EXT_get", libcrypto,
 | 
					    ("X509V3_EXT_get", libcrypto,
 | 
				
			||||||
     ((POINTER(X509V3_EXT_METHOD), "ret"), (POINTER(X509_EXTENSION), "ext")),
 | 
					     ((POINTER(X509V3_EXT_METHOD), "ret"), (POINTER(X509_EXTENSION), "ext")), True, errcheck_p),
 | 
				
			||||||
     True, errcheck_p),
 | 
					 | 
				
			||||||
    ("ASN1_item_d2i", libcrypto,
 | 
					    ("ASN1_item_d2i", libcrypto,
 | 
				
			||||||
     ((c_void_p, "ret"), (c_void_p, "val"), (POINTER(POINTER(c_ubyte)), "in"),
 | 
					     ((c_void_p, "ret"), (c_void_p, "val"), (POINTER(POINTER(c_ubyte)), "in"), (c_long, "len"), (c_void_p, "it")), False, None),
 | 
				
			||||||
      (c_long, "len"), (c_void_p, "it")), False, None),
 | 
					    ("sk_num", libcrypto,
 | 
				
			||||||
    ("sk_num", libcrypto, ((c_int, "ret"), (STACK, "stack")), True, None),
 | 
					     ((c_int, "ret"), (STACK, "stack")), True, None),
 | 
				
			||||||
    ("sk_value", libcrypto,
 | 
					    ("sk_value", libcrypto,
 | 
				
			||||||
     ((c_void_p, "ret"), (STACK, "stack"), (c_int, "loc")), False),
 | 
					     ((c_void_p, "ret"), (STACK, "stack"), (c_int, "loc")), False),
 | 
				
			||||||
    ("GENERAL_NAME_print", libcrypto,
 | 
					    ("GENERAL_NAME_print", libcrypto,
 | 
				
			||||||
     ((c_int, "ret"), (BIO, "out"), (POINTER(GENERAL_NAME), "gen")), False),
 | 
					     ((c_int, "ret"), (BIO, "out"), (POINTER(GENERAL_NAME), "gen")), False),
 | 
				
			||||||
    ("sk_pop_free", libcrypto,
 | 
					    ("sk_pop_free", libcrypto,
 | 
				
			||||||
     ((None, "ret"), (STACK, "st"), (c_void_p, "func")), False),
 | 
					     ((None, "ret"), (STACK, "st"), (c_void_p, "func")), False),
 | 
				
			||||||
    ("i2d_X509_bio", libcrypto, ((c_int, "ret"), (BIO, "bp"), (X509, "x")),
 | 
					    ("i2d_X509_bio", libcrypto,
 | 
				
			||||||
     False),
 | 
					     ((c_int, "ret"), (BIO, "bp"), (X509, "x")), False),
 | 
				
			||||||
    ("SSL_get_current_cipher", libssl, ((SSL_CIPHER, "ret"), (SSL, "ssl"))),
 | 
					    ("SSL_get_current_cipher", libssl,
 | 
				
			||||||
 | 
					     ((SSL_CIPHER, "ret"), (SSL, "ssl"))),
 | 
				
			||||||
    ("SSL_CIPHER_get_name", libssl,
 | 
					    ("SSL_CIPHER_get_name", libssl,
 | 
				
			||||||
     ((c_char_p, "ret"), (SSL_CIPHER, "cipher"))),
 | 
					     ((c_char_p, "ret"), (SSL_CIPHER, "cipher"))),
 | 
				
			||||||
    ("SSL_CIPHER_get_version", libssl,
 | 
					    ("SSL_CIPHER_get_version", libssl,
 | 
				
			||||||
     ((c_char_p, "ret"), (SSL_CIPHER, "cipher"))),
 | 
					     ((c_char_p, "ret"), (SSL_CIPHER, "cipher"))),
 | 
				
			||||||
    ("SSL_CIPHER_get_bits", libssl,
 | 
					    ("SSL_CIPHER_get_bits", libssl,
 | 
				
			||||||
     ((c_int, "ret"), (SSL_CIPHER, "cipher"),
 | 
					     ((c_int, "ret"), (SSL_CIPHER, "cipher"), (POINTER(c_int), "alg_bits", 1, None)), True, None),
 | 
				
			||||||
      (POINTER(c_int), "alg_bits", 1, None)), True, None),
 | 
					    ("EC_get_builtin_curves", libcrypto,
 | 
				
			||||||
 | 
					     ((c_int, "ret"), (POINTER(EC_builtin_curve), "r"), (c_int, "nitems"))),
 | 
				
			||||||
 | 
					    ("EC_KEY_new_by_curve_name", libcrypto,
 | 
				
			||||||
 | 
					     ((EC_KEY, "ret"), (c_int, "nid"))),
 | 
				
			||||||
 | 
					    ("EC_KEY_free", libcrypto,
 | 
				
			||||||
 | 
					     ((None, "ret"), (EC_KEY, "key"))),
 | 
				
			||||||
 | 
					    ("EC_curve_nist2nid", libcrypto,
 | 
				
			||||||
 | 
					     ((c_int, "ret"), (POINTER(c_char), "name")), True, None),
 | 
				
			||||||
 | 
					    ("EC_curve_nid2nist", libcrypto,
 | 
				
			||||||
 | 
					     ((c_char_p, "ret"), (c_int, "nid")), True, None),
 | 
				
			||||||
    ))
 | 
					    ))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
@ -650,15 +838,78 @@ def CRYPTO_set_locking_callback(locking_function):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def SSL_CTX_set_session_cache_mode(ctx, mode):
 | 
					def SSL_CTX_set_session_cache_mode(ctx, mode):
 | 
				
			||||||
    # Returns the previous value of mode
 | 
					    # Returns the previous value of mode
 | 
				
			||||||
    _SSL_CTX_ctrl(ctx, SSL_CTRL_SET_SESS_CACHE_MODE, mode, None)
 | 
					    return _SSL_CTX_ctrl(ctx, SSL_CTRL_SET_SESS_CACHE_MODE, mode, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def SSL_CTX_set_read_ahead(ctx, m):
 | 
					def SSL_CTX_set_read_ahead(ctx, m):
 | 
				
			||||||
    # Returns the previous value of m
 | 
					    # Returns the previous value of m
 | 
				
			||||||
    _SSL_CTX_ctrl(ctx, SSL_CTRL_SET_READ_AHEAD, m, None)
 | 
					    return _SSL_CTX_ctrl(ctx, SSL_CTRL_SET_READ_AHEAD, m, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def SSL_CTX_set_options(ctx, options):
 | 
					def SSL_CTX_set_options(ctx, options):
 | 
				
			||||||
    # Returns the new option bitmaks after adding the given options
 | 
					    # Returns the new option bitmaks after adding the given options
 | 
				
			||||||
    _SSL_CTX_ctrl(ctx, SSL_CTRL_OPTIONS, options, None)
 | 
					    return _SSL_CTX_ctrl(ctx, SSL_CTRL_OPTIONS, options, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_CTX_clear_options(ctx, options):
 | 
				
			||||||
 | 
					    return _SSL_CTX_ctrl(ctx, SSL_CTRL_CLEAR_OPTIONS, options, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_CTX_get_options(ctx):
 | 
				
			||||||
 | 
					    return _SSL_CTX_ctrl(ctx, SSL_CTRL_OPTIONS, 0, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_CTX_set1_client_sigalgs(ctx, slist, slistlen):
 | 
				
			||||||
 | 
					    _slist = (c_int * len(slist))(*slist)
 | 
				
			||||||
 | 
					    return _SSL_CTX_ctrl(ctx, SSL_CTRL_SET_CLIENT_SIGALGS, len(_slist), _slist)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_CTX_set1_client_sigalgs_list(ctx, s):
 | 
				
			||||||
 | 
					    _s = cast(s, POINTER(c_char))
 | 
				
			||||||
 | 
					    return _SSL_CTX_ctrl(ctx, SSL_CTRL_SET_CLIENT_SIGALGS_LIST, 0, _s)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_CTX_set1_sigalgs(ctx, slist, slistlen):
 | 
				
			||||||
 | 
					    _slist = (c_int * len(slist))(*slist)
 | 
				
			||||||
 | 
					    return _SSL_CTX_ctrl(ctx, SSL_CTRL_SET_SIGALGS, len(_slist), _slist)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_CTX_set1_sigalgs_list(ctx, s):
 | 
				
			||||||
 | 
					    _s = cast(s, POINTER(c_char))
 | 
				
			||||||
 | 
					    return _SSL_CTX_ctrl(ctx, SSL_CTRL_SET_SIGALGS_LIST, 0, _s)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_CTX_set1_curves(ctx, clist, clistlen):
 | 
				
			||||||
 | 
					    _curves = (c_int * len(clist))(*clist)
 | 
				
			||||||
 | 
					    return _SSL_CTX_ctrl(ctx, SSL_CTRL_SET_CURVES, len(_curves), _curves)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_CTX_set1_curves_list(ctx, s):
 | 
				
			||||||
 | 
					    _s = cast(s, POINTER(c_char))
 | 
				
			||||||
 | 
					    return _SSL_CTX_ctrl(ctx, SSL_CTRL_SET_CURVES_LIST, 0, _s)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_rvoid_voidp_int_int = CFUNCTYPE(None, c_void_p, c_int, c_int)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_info_callback = dict()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_CTX_set_info_callback(ctx, app_info_cb):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Set the info callback
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    :param callback: The Python callback to use
 | 
				
			||||||
 | 
					    :return: None
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    def py_info_callback(ssl, where, ret):
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            app_info_cb(SSL(ssl), where, ret)
 | 
				
			||||||
 | 
					        except:
 | 
				
			||||||
 | 
					            pass
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    global _info_callback
 | 
				
			||||||
 | 
					    _info_callback[ctx] = _rvoid_voidp_int_int(py_info_callback)
 | 
				
			||||||
 | 
					    _SSL_CTX_set_info_callback(ctx, _info_callback[ctx])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_CTX_build_cert_chain(ctx, flags):
 | 
				
			||||||
 | 
					    return _SSL_CTX_ctrl(ctx, SSL_CTRL_BUILD_CERT_CHAIN, flags, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_CTX_set_ecdh_auto(ctx, onoff):
 | 
				
			||||||
 | 
					    return _SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_CTX_set_tmp_ecdh(ctx, ec_key):
 | 
				
			||||||
 | 
					    # return 1 on success and 0 on failure
 | 
				
			||||||
 | 
					    _ec_key_p = cast(ec_key.raw, c_void_p)
 | 
				
			||||||
 | 
					    return _SSL_CTX_ctrl(ctx, SSL_CTRL_SET_TMP_ECDH, 0, _ec_key_p)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_rint_voidp_ubytep_uintp = CFUNCTYPE(c_int, c_void_p, POINTER(c_ubyte),
 | 
					_rint_voidp_ubytep_uintp = CFUNCTYPE(c_int, c_void_p, POINTER(c_ubyte),
 | 
				
			||||||
                                     POINTER(c_uint))
 | 
					                                     POINTER(c_uint))
 | 
				
			||||||
@ -693,7 +944,7 @@ def SSL_CTX_set_cookie_cb(ctx, generate, verify):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def BIO_dgram_set_connected(bio, peer_address):
 | 
					def BIO_dgram_set_connected(bio, peer_address):
 | 
				
			||||||
    su = sockaddr_u_from_addr_tuple(peer_address)
 | 
					    su = sockaddr_u_from_addr_tuple(peer_address)
 | 
				
			||||||
    _BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_CONNECTED, 0, byref(su))
 | 
					    return _BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_CONNECTED, 0, byref(su))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def BIO_dgram_get_peer(bio):
 | 
					def BIO_dgram_get_peer(bio):
 | 
				
			||||||
    su = sockaddr_u()
 | 
					    su = sockaddr_u()
 | 
				
			||||||
@ -702,10 +953,10 @@ def BIO_dgram_get_peer(bio):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def BIO_dgram_set_peer(bio, peer_address):
 | 
					def BIO_dgram_set_peer(bio, peer_address):
 | 
				
			||||||
    su = sockaddr_u_from_addr_tuple(peer_address)
 | 
					    su = sockaddr_u_from_addr_tuple(peer_address)
 | 
				
			||||||
    _BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_PEER, 0, byref(su))
 | 
					    return _BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_PEER, 0, byref(su))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def BIO_set_nbio(bio, n):
 | 
					def BIO_set_nbio(bio, n):
 | 
				
			||||||
    _BIO_ctrl(bio, BIO_C_SET_NBIO, 1 if n else 0, None)
 | 
					    return _BIO_ctrl(bio, BIO_C_SET_NBIO, 1 if n else 0, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def DTLSv1_get_timeout(ssl):
 | 
					def DTLSv1_get_timeout(ssl):
 | 
				
			||||||
    tv = TIMEVAL()
 | 
					    tv = TIMEVAL()
 | 
				
			||||||
@ -727,7 +978,7 @@ def DTLSv1_handle_timeout(ssl):
 | 
				
			|||||||
    assert ret < 0
 | 
					    assert ret < 0
 | 
				
			||||||
    if ret > 0:
 | 
					    if ret > 0:
 | 
				
			||||||
        ret = -10
 | 
					        ret = -10
 | 
				
			||||||
    errcheck_p(ret, _SSL_ctrl, (ssl, DTLS_CTRL_HANDLE_TIMEOUT, 0, None))
 | 
					    return errcheck_p(ret, _SSL_ctrl, (ssl, DTLS_CTRL_HANDLE_TIMEOUT, 0, None))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def DTLSv1_listen(ssl):
 | 
					def DTLSv1_listen(ssl):
 | 
				
			||||||
    su = sockaddr_u()
 | 
					    su = sockaddr_u()
 | 
				
			||||||
@ -735,6 +986,9 @@ def DTLSv1_listen(ssl):
 | 
				
			|||||||
    errcheck_ord(ret, _SSL_ctrl, (ssl, DTLS_CTRL_LISTEN, 0, byref(su)))
 | 
					    errcheck_ord(ret, _SSL_ctrl, (ssl, DTLS_CTRL_LISTEN, 0, byref(su)))
 | 
				
			||||||
    return addr_tuple_from_sockaddr_u(su)
 | 
					    return addr_tuple_from_sockaddr_u(su)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def DTLS_set_link_mtu(ssl, mtu):
 | 
				
			||||||
 | 
					    return _SSL_ctrl(ssl, DTLS_CTRL_SET_LINK_MTU, mtu, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def SSL_read(ssl, length, buffer):
 | 
					def SSL_read(ssl, length, buffer):
 | 
				
			||||||
    if buffer:
 | 
					    if buffer:
 | 
				
			||||||
        length = min(length, len(buffer))
 | 
					        length = min(length, len(buffer))
 | 
				
			||||||
@ -751,15 +1005,94 @@ def SSL_write(ssl, data):
 | 
				
			|||||||
        str_data = data
 | 
					        str_data = data
 | 
				
			||||||
    elif hasattr(data, "tobytes") and callable(data.tobytes):
 | 
					    elif hasattr(data, "tobytes") and callable(data.tobytes):
 | 
				
			||||||
        str_data = data.tobytes()
 | 
					        str_data = data.tobytes()
 | 
				
			||||||
 | 
					    elif isinstance(data, ctypes.Array):
 | 
				
			||||||
 | 
					        str_data = data.raw
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        str_data = str(data)
 | 
					        str_data = str(data)
 | 
				
			||||||
    return _SSL_write(ssl, str_data, len(str_data))
 | 
					    return _SSL_write(ssl, str_data, len(str_data))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_set_options(ssl, op):
 | 
				
			||||||
 | 
					    return _SSL_ctrl(ssl, SSL_CTRL_OPTIONS, op, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_clear_options(ssl, op):
 | 
				
			||||||
 | 
					    return _SSL_ctrl(ssl, SSL_CTRL_CLEAR_OPTIONS, op, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_get_options(ssl):
 | 
				
			||||||
 | 
					    return _SSL_ctrl(ssl, SSL_CTRL_OPTIONS, 0, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_set1_client_sigalgs(ssl, slist, slistlen):
 | 
				
			||||||
 | 
					    _slist = (c_int * len(slist))(*slist)
 | 
				
			||||||
 | 
					    return _SSL_ctrl(ssl, SSL_CTRL_SET_CLIENT_SIGALGS, len(_slist), _slist)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_set1_client_sigalgs_list(ssl, s):
 | 
				
			||||||
 | 
					    _s = cast(s, POINTER(c_char))
 | 
				
			||||||
 | 
					    return _SSL_ctrl(ssl, SSL_CTRL_SET_CLIENT_SIGALGS_LIST, 0, _s)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_set1_sigalgs(ssl, slist, slistlen):
 | 
				
			||||||
 | 
					    _slist = (c_int * len(slist))(*slist)
 | 
				
			||||||
 | 
					    return _SSL_ctrl(ssl, SSL_CTRL_SET_SIGALGS, len(_slist), _slist)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_set1_sigalgs_list(ssl, s):
 | 
				
			||||||
 | 
					    _s = cast(s, POINTER(c_char))
 | 
				
			||||||
 | 
					    return _SSL_ctrl(ssl, SSL_CTRL_SET_SIGALGS_LIST, 0, _s)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_get1_curves(ssl, curves=None):
 | 
				
			||||||
 | 
					    assert curves is None or isinstance(curves, list)
 | 
				
			||||||
 | 
					    if curves is not None:
 | 
				
			||||||
 | 
					        cnt = SSL_get1_curves(ssl, None)
 | 
				
			||||||
 | 
					        if cnt:
 | 
				
			||||||
 | 
					            mem = create_string_buffer(sizeof(POINTER(c_int)) * cnt)
 | 
				
			||||||
 | 
					            _SSL_ctrl(ssl, SSL_CTRL_GET_CURVES, 0, mem)
 | 
				
			||||||
 | 
					            for x in cast(mem, POINTER(c_int))[:cnt]:
 | 
				
			||||||
 | 
					                curves.append(x)
 | 
				
			||||||
 | 
					        return cnt
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        return _SSL_ctrl(ssl, SSL_CTRL_GET_CURVES, 0, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_get_shared_curve(ssl, n):
 | 
				
			||||||
 | 
					    return _SSL_ctrl(ssl, SSL_CTRL_GET_SHARED_CURVE, n, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_set1_curves(ssl, clist, clistlen):
 | 
				
			||||||
 | 
					    _curves = (c_int * len(clist))(*clist)
 | 
				
			||||||
 | 
					    return _SSL_ctrl(ssl, SSL_CTRL_SET_CURVES, len(_curves), _curves)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_set1_curves_list(ssl, s):
 | 
				
			||||||
 | 
					    _s = cast(s, POINTER(c_char))
 | 
				
			||||||
 | 
					    return _SSL_ctrl(ssl, SSL_CTRL_SET_CURVES_LIST, 0, _s)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_set_mtu(ssl, mtu):
 | 
				
			||||||
 | 
					    return _SSL_ctrl(ssl, SSL_CTRL_SET_MTU, mtu, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_state_string_long(ssl):
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        ret = _SSL_state_string_long(ssl)
 | 
				
			||||||
 | 
					    except:
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					    return ret
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_alert_type_string_long(value):
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        ret = _SSL_alert_type_string_long(value)
 | 
				
			||||||
 | 
					    except:
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					    return ret
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_alert_desc_string_long(value):
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        ret = _SSL_alert_desc_string_long(value)
 | 
				
			||||||
 | 
					    except:
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					    return ret
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def OBJ_obj2txt(asn1_object, no_name):
 | 
					def OBJ_obj2txt(asn1_object, no_name):
 | 
				
			||||||
    buf = create_string_buffer(X509_NAME_MAXLEN)
 | 
					    buf = create_string_buffer(X509_NAME_MAXLEN)
 | 
				
			||||||
    res_len = _OBJ_obj2txt(buf, sizeof(buf), asn1_object, 1 if no_name else 0)
 | 
					    res_len = _OBJ_obj2txt(buf, sizeof(buf), asn1_object, 1 if no_name else 0)
 | 
				
			||||||
    return buf.raw[:res_len]
 | 
					    return buf.raw[:res_len]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def OBJ_nid2sn(nid):
 | 
				
			||||||
 | 
					    _name = _OBJ_nid2sn(nid)
 | 
				
			||||||
 | 
					    return cast(_name, c_char_p).value.decode("ascii")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def decode_ASN1_STRING(asn1_string):
 | 
					def decode_ASN1_STRING(asn1_string):
 | 
				
			||||||
    utf8_buf_ptr = POINTER(c_ubyte)()
 | 
					    utf8_buf_ptr = POINTER(c_ubyte)()
 | 
				
			||||||
    res_len = _ASN1_STRING_to_UTF8(byref(utf8_buf_ptr), asn1_string)
 | 
					    res_len = _ASN1_STRING_to_UTF8(byref(utf8_buf_ptr), asn1_string)
 | 
				
			||||||
@ -833,3 +1166,13 @@ def i2d_X509(x509):
 | 
				
			|||||||
    bio = _BIO(BIO_new(BIO_s_mem()))
 | 
					    bio = _BIO(BIO_new(BIO_s_mem()))
 | 
				
			||||||
    _i2d_X509_bio(bio.value, x509)
 | 
					    _i2d_X509_bio(bio.value, x509)
 | 
				
			||||||
    return BIO_get_mem_data(bio.value)
 | 
					    return BIO_get_mem_data(bio.value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def SSL_get_peer_cert_chain(ssl):
 | 
				
			||||||
 | 
					    stack = _SSL_get_peer_cert_chain(ssl)
 | 
				
			||||||
 | 
					    num = sk_num(stack)
 | 
				
			||||||
 | 
					    certs = []
 | 
				
			||||||
 | 
					    if num:
 | 
				
			||||||
 | 
					        # why not use sk_value(): because it doesn't cast correct in this case?!
 | 
				
			||||||
 | 
					        # certs = [(sk_value(stack, i)) for i in xrange(num)]
 | 
				
			||||||
 | 
					        certs = [X509(_sk_value(stack, i)) for i in xrange(num)]
 | 
				
			||||||
 | 
					    return stack, num, certs
 | 
				
			||||||
 | 
				
			|||||||
@ -34,16 +34,20 @@ has the following effects:
 | 
				
			|||||||
      PROTOCOL_DTLSv1 for the parameter ssl_version is supported
 | 
					      PROTOCOL_DTLSv1 for the parameter ssl_version is supported
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from socket import SOCK_DGRAM, socket, _delegate_methods, error as socket_error
 | 
					from socket import socket, getaddrinfo, _delegate_methods, error as socket_error
 | 
				
			||||||
from socket import AF_INET, SOCK_STREAM, SOCK_DGRAM, getaddrinfo
 | 
					from socket import AF_INET, SOCK_STREAM, SOCK_DGRAM
 | 
				
			||||||
from sslconnection import SSLConnection, PROTOCOL_DTLSv1, CERT_NONE
 | 
					from ssl import PROTOCOL_SSLv23, CERT_NONE
 | 
				
			||||||
from sslconnection import DTLS_OPENSSL_VERSION_NUMBER, DTLS_OPENSSL_VERSION
 | 
					 | 
				
			||||||
from sslconnection import DTLS_OPENSSL_VERSION_INFO
 | 
					 | 
				
			||||||
from err import raise_as_ssl_module_error
 | 
					 | 
				
			||||||
from types import MethodType
 | 
					from types import MethodType
 | 
				
			||||||
from weakref import proxy
 | 
					from weakref import proxy
 | 
				
			||||||
import errno
 | 
					import errno
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from sslconnection import SSLConnection, PROTOCOL_DTLS, PROTOCOL_DTLSv1, PROTOCOL_DTLSv1_2
 | 
				
			||||||
 | 
					from sslconnection import DTLS_OPENSSL_VERSION_NUMBER, DTLS_OPENSSL_VERSION, DTLS_OPENSSL_VERSION_INFO
 | 
				
			||||||
 | 
					from sslconnection import SSL_BUILD_CHAIN_FLAG_NONE, SSL_BUILD_CHAIN_FLAG_UNTRUSTED, \
 | 
				
			||||||
 | 
					    SSL_BUILD_CHAIN_FLAG_NO_ROOT, SSL_BUILD_CHAIN_FLAG_CHECK, SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR, SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR
 | 
				
			||||||
 | 
					from err import raise_as_ssl_module_error, patch_ssl_errors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def do_patch():
 | 
					def do_patch():
 | 
				
			||||||
    import ssl as _ssl  # import to be avoided if ssl module is never patched
 | 
					    import ssl as _ssl  # import to be avoided if ssl module is never patched
 | 
				
			||||||
    global _orig_SSLSocket_init, _orig_get_server_certificate
 | 
					    global _orig_SSLSocket_init, _orig_get_server_certificate
 | 
				
			||||||
@ -51,18 +55,47 @@ def do_patch():
 | 
				
			|||||||
    ssl = _ssl
 | 
					    ssl = _ssl
 | 
				
			||||||
    if hasattr(ssl, "PROTOCOL_DTLSv1"):
 | 
					    if hasattr(ssl, "PROTOCOL_DTLSv1"):
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
 | 
					    _orig_wrap_socket = ssl.wrap_socket
 | 
				
			||||||
 | 
					    ssl.wrap_socket = _wrap_socket
 | 
				
			||||||
 | 
					    ssl.PROTOCOL_DTLS = PROTOCOL_DTLS
 | 
				
			||||||
    ssl.PROTOCOL_DTLSv1 = PROTOCOL_DTLSv1
 | 
					    ssl.PROTOCOL_DTLSv1 = PROTOCOL_DTLSv1
 | 
				
			||||||
 | 
					    ssl.PROTOCOL_DTLSv1_2 = PROTOCOL_DTLSv1_2
 | 
				
			||||||
 | 
					    ssl._PROTOCOL_NAMES[PROTOCOL_DTLS] = "DTLS"
 | 
				
			||||||
    ssl._PROTOCOL_NAMES[PROTOCOL_DTLSv1] = "DTLSv1"
 | 
					    ssl._PROTOCOL_NAMES[PROTOCOL_DTLSv1] = "DTLSv1"
 | 
				
			||||||
 | 
					    ssl._PROTOCOL_NAMES[PROTOCOL_DTLSv1_2] = "DTLSv1.2"
 | 
				
			||||||
    ssl.DTLS_OPENSSL_VERSION_NUMBER = DTLS_OPENSSL_VERSION_NUMBER
 | 
					    ssl.DTLS_OPENSSL_VERSION_NUMBER = DTLS_OPENSSL_VERSION_NUMBER
 | 
				
			||||||
    ssl.DTLS_OPENSSL_VERSION = DTLS_OPENSSL_VERSION
 | 
					    ssl.DTLS_OPENSSL_VERSION = DTLS_OPENSSL_VERSION
 | 
				
			||||||
    ssl.DTLS_OPENSSL_VERSION_INFO = DTLS_OPENSSL_VERSION_INFO
 | 
					    ssl.DTLS_OPENSSL_VERSION_INFO = DTLS_OPENSSL_VERSION_INFO
 | 
				
			||||||
 | 
					    ssl.SSL_BUILD_CHAIN_FLAG_NONE = SSL_BUILD_CHAIN_FLAG_NONE
 | 
				
			||||||
 | 
					    ssl.SSL_BUILD_CHAIN_FLAG_UNTRUSTED = SSL_BUILD_CHAIN_FLAG_UNTRUSTED
 | 
				
			||||||
 | 
					    ssl.SSL_BUILD_CHAIN_FLAG_NO_ROOT = SSL_BUILD_CHAIN_FLAG_NO_ROOT
 | 
				
			||||||
 | 
					    ssl.SSL_BUILD_CHAIN_FLAG_CHECK = SSL_BUILD_CHAIN_FLAG_CHECK
 | 
				
			||||||
 | 
					    ssl.SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR = SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR
 | 
				
			||||||
 | 
					    ssl.SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR = SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR
 | 
				
			||||||
    _orig_SSLSocket_init = ssl.SSLSocket.__init__
 | 
					    _orig_SSLSocket_init = ssl.SSLSocket.__init__
 | 
				
			||||||
    _orig_get_server_certificate = ssl.get_server_certificate
 | 
					    _orig_get_server_certificate = ssl.get_server_certificate
 | 
				
			||||||
    ssl.SSLSocket.__init__ = _SSLSocket_init
 | 
					    ssl.SSLSocket.__init__ = _SSLSocket_init
 | 
				
			||||||
    ssl.get_server_certificate = _get_server_certificate
 | 
					    ssl.get_server_certificate = _get_server_certificate
 | 
				
			||||||
 | 
					    patch_ssl_errors()
 | 
				
			||||||
    raise_as_ssl_module_error()
 | 
					    raise_as_ssl_module_error()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PROTOCOL_SSLv23 = 2
 | 
					def _wrap_socket(sock, keyfile=None, certfile=None,
 | 
				
			||||||
 | 
					                 server_side=False, cert_reqs=CERT_NONE,
 | 
				
			||||||
 | 
					                 ssl_version=PROTOCOL_DTLS, ca_certs=None,
 | 
				
			||||||
 | 
					                 do_handshake_on_connect=True,
 | 
				
			||||||
 | 
					                 suppress_ragged_eofs=True,
 | 
				
			||||||
 | 
					                 ciphers=None,
 | 
				
			||||||
 | 
					                 cb_user_config_ssl_ctx=None,
 | 
				
			||||||
 | 
					                 cb_user_config_ssl=None):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ssl.SSLSocket(sock, keyfile=keyfile, certfile=certfile,
 | 
				
			||||||
 | 
					                         server_side=server_side, cert_reqs=cert_reqs,
 | 
				
			||||||
 | 
					                         ssl_version=ssl_version, ca_certs=ca_certs,
 | 
				
			||||||
 | 
					                         do_handshake_on_connect=do_handshake_on_connect,
 | 
				
			||||||
 | 
					                         suppress_ragged_eofs=suppress_ragged_eofs,
 | 
				
			||||||
 | 
					                         ciphers=ciphers,
 | 
				
			||||||
 | 
					                         cb_user_config_ssl_ctx=cb_user_config_ssl_ctx,
 | 
				
			||||||
 | 
					                         cb_user_config_ssl=cb_user_config_ssl)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _get_server_certificate(addr, ssl_version=PROTOCOL_SSLv23, ca_certs=None):
 | 
					def _get_server_certificate(addr, ssl_version=PROTOCOL_SSLv23, ca_certs=None):
 | 
				
			||||||
    """Retrieve a server certificate
 | 
					    """Retrieve a server certificate
 | 
				
			||||||
@ -73,10 +106,10 @@ def _get_server_certificate(addr, ssl_version=PROTOCOL_SSLv23, ca_certs=None):
 | 
				
			|||||||
    If 'ssl_version' is specified, use it in the connection attempt.
 | 
					    If 'ssl_version' is specified, use it in the connection attempt.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ssl_version != PROTOCOL_DTLSv1:
 | 
					    if ssl_version not in (PROTOCOL_DTLS, PROTOCOL_DTLSv1, PROTOCOL_DTLSv1_2):
 | 
				
			||||||
        return _orig_get_server_certificate(addr, ssl_version, ca_certs)
 | 
					        return _orig_get_server_certificate(addr, ssl_version, ca_certs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (ca_certs is not None):
 | 
					    if ca_certs is not None:
 | 
				
			||||||
        cert_reqs = ssl.CERT_REQUIRED
 | 
					        cert_reqs = ssl.CERT_REQUIRED
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        cert_reqs = ssl.CERT_NONE
 | 
					        cert_reqs = ssl.CERT_NONE
 | 
				
			||||||
@ -91,12 +124,14 @@ def _get_server_certificate(addr, ssl_version=PROTOCOL_SSLv23, ca_certs=None):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def _SSLSocket_init(self, sock=None, keyfile=None, certfile=None,
 | 
					def _SSLSocket_init(self, sock=None, keyfile=None, certfile=None,
 | 
				
			||||||
                    server_side=False, cert_reqs=CERT_NONE,
 | 
					                    server_side=False, cert_reqs=CERT_NONE,
 | 
				
			||||||
                    ssl_version=PROTOCOL_SSLv23, ca_certs=None,
 | 
					                    ssl_version=PROTOCOL_DTLS, ca_certs=None,
 | 
				
			||||||
                    do_handshake_on_connect=True,
 | 
					                    do_handshake_on_connect=True,
 | 
				
			||||||
                    family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None,
 | 
					                    family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None,
 | 
				
			||||||
                    suppress_ragged_eofs=True, npn_protocols=None, ciphers=None,
 | 
					                    suppress_ragged_eofs=True, npn_protocols=None, ciphers=None,
 | 
				
			||||||
                    server_hostname=None,
 | 
					                    server_hostname=None,
 | 
				
			||||||
                    _context=None):
 | 
					                    _context=None,
 | 
				
			||||||
 | 
					                    cb_user_config_ssl_ctx=None,
 | 
				
			||||||
 | 
					                    cb_user_config_ssl=None):
 | 
				
			||||||
    is_connection = is_datagram = False
 | 
					    is_connection = is_datagram = False
 | 
				
			||||||
    if isinstance(sock, SSLConnection):
 | 
					    if isinstance(sock, SSLConnection):
 | 
				
			||||||
        is_connection = True
 | 
					        is_connection = True
 | 
				
			||||||
@ -148,7 +183,9 @@ def _SSLSocket_init(self, sock=None, keyfile=None, certfile=None,
 | 
				
			|||||||
                                         server_side, cert_reqs,
 | 
					                                         server_side, cert_reqs,
 | 
				
			||||||
                                         ssl_version, ca_certs,
 | 
					                                         ssl_version, ca_certs,
 | 
				
			||||||
                                         do_handshake_on_connect,
 | 
					                                         do_handshake_on_connect,
 | 
				
			||||||
                                         suppress_ragged_eofs, ciphers)
 | 
					                                         suppress_ragged_eofs, ciphers,
 | 
				
			||||||
 | 
					                                         cb_user_config_ssl_ctx=cb_user_config_ssl_ctx,
 | 
				
			||||||
 | 
					                                         cb_user_config_ssl=cb_user_config_ssl)
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        self._connected = True
 | 
					        self._connected = True
 | 
				
			||||||
        self._sslobj = sock
 | 
					        self._sslobj = sock
 | 
				
			||||||
@ -166,6 +203,8 @@ def _SSLSocket_init(self, sock=None, keyfile=None, certfile=None,
 | 
				
			|||||||
    self.do_handshake_on_connect = do_handshake_on_connect
 | 
					    self.do_handshake_on_connect = do_handshake_on_connect
 | 
				
			||||||
    self.suppress_ragged_eofs = suppress_ragged_eofs
 | 
					    self.suppress_ragged_eofs = suppress_ragged_eofs
 | 
				
			||||||
    self._makefile_refs = 0
 | 
					    self._makefile_refs = 0
 | 
				
			||||||
 | 
					    self._user_config_ssl_ctx = cb_user_config_ssl_ctx
 | 
				
			||||||
 | 
					    self._user_config_ssl = cb_user_config_ssl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Perform method substitution and addition (without reference cycle)
 | 
					    # Perform method substitution and addition (without reference cycle)
 | 
				
			||||||
    self._real_connect = MethodType(_SSLSocket_real_connect, proxy(self))
 | 
					    self._real_connect = MethodType(_SSLSocket_real_connect, proxy(self))
 | 
				
			||||||
@ -174,6 +213,12 @@ def _SSLSocket_init(self, sock=None, keyfile=None, certfile=None,
 | 
				
			|||||||
    self.get_timeout = MethodType(_SSLSocket_get_timeout, proxy(self))
 | 
					    self.get_timeout = MethodType(_SSLSocket_get_timeout, proxy(self))
 | 
				
			||||||
    self.handle_timeout = MethodType(_SSLSocket_handle_timeout, proxy(self))
 | 
					    self.handle_timeout = MethodType(_SSLSocket_handle_timeout, proxy(self))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Extra
 | 
				
			||||||
 | 
					    self.getpeercertchain = MethodType(_getpeercertchain, proxy(self))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _getpeercertchain(self, binary_form=False):
 | 
				
			||||||
 | 
					    return self._sslobj.getpeercertchain(binary_form)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _SSLSocket_listen(self, ignored):
 | 
					def _SSLSocket_listen(self, ignored):
 | 
				
			||||||
    if self._connected:
 | 
					    if self._connected:
 | 
				
			||||||
        raise ValueError("attempt to listen on connected SSLSocket!")
 | 
					        raise ValueError("attempt to listen on connected SSLSocket!")
 | 
				
			||||||
@ -184,7 +229,9 @@ def _SSLSocket_listen(self, ignored):
 | 
				
			|||||||
                                 self.cert_reqs, self.ssl_version,
 | 
					                                 self.cert_reqs, self.ssl_version,
 | 
				
			||||||
                                 self.ca_certs,
 | 
					                                 self.ca_certs,
 | 
				
			||||||
                                 self.do_handshake_on_connect,
 | 
					                                 self.do_handshake_on_connect,
 | 
				
			||||||
                                 self.suppress_ragged_eofs, self.ciphers)
 | 
					                                 self.suppress_ragged_eofs, self.ciphers,
 | 
				
			||||||
 | 
					                                 cb_user_config_ssl_ctx=self._user_config_ssl_ctx,
 | 
				
			||||||
 | 
					                                 cb_user_config_ssl=self._user_config_ssl)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _SSLSocket_accept(self):
 | 
					def _SSLSocket_accept(self):
 | 
				
			||||||
    if self._connected:
 | 
					    if self._connected:
 | 
				
			||||||
@ -199,7 +246,9 @@ def _SSLSocket_accept(self):
 | 
				
			|||||||
                                 self.cert_reqs, self.ssl_version,
 | 
					                                 self.cert_reqs, self.ssl_version,
 | 
				
			||||||
                                 self.ca_certs,
 | 
					                                 self.ca_certs,
 | 
				
			||||||
                                 self.do_handshake_on_connect,
 | 
					                                 self.do_handshake_on_connect,
 | 
				
			||||||
                                 self.suppress_ragged_eofs, self.ciphers)
 | 
					                                 self.suppress_ragged_eofs, self.ciphers,
 | 
				
			||||||
 | 
					                                 cb_user_config_ssl_ctx=self._user_config_ssl_ctx,
 | 
				
			||||||
 | 
					                                 cb_user_config_ssl=self._user_config_ssl)
 | 
				
			||||||
    return new_ssl_sock, addr
 | 
					    return new_ssl_sock, addr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _SSLSocket_real_connect(self, addr, return_errno):
 | 
					def _SSLSocket_real_connect(self, addr, return_errno):
 | 
				
			||||||
@ -210,7 +259,9 @@ def _SSLSocket_real_connect(self, addr, return_errno):
 | 
				
			|||||||
                                 self.cert_reqs, self.ssl_version,
 | 
					                                 self.cert_reqs, self.ssl_version,
 | 
				
			||||||
                                 self.ca_certs,
 | 
					                                 self.ca_certs,
 | 
				
			||||||
                                 self.do_handshake_on_connect,
 | 
					                                 self.do_handshake_on_connect,
 | 
				
			||||||
                                 self.suppress_ragged_eofs, self.ciphers)
 | 
					                                 self.suppress_ragged_eofs, self.ciphers,
 | 
				
			||||||
 | 
					                                 cb_user_config_ssl_ctx=self._user_config_ssl_ctx,
 | 
				
			||||||
 | 
					                                 cb_user_config_ssl=self._user_config_ssl)
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        self._sslobj.connect(addr)
 | 
					        self._sslobj.connect(addr)
 | 
				
			||||||
    except socket_error as e:
 | 
					    except socket_error as e:
 | 
				
			||||||
 | 
				
			|||||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							@ -40,6 +40,7 @@ library's ssl module, since its values can be passed to this module.
 | 
				
			|||||||
  CERT_REQUIRED
 | 
					  CERT_REQUIRED
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
import errno
 | 
					import errno
 | 
				
			||||||
import socket
 | 
					import socket
 | 
				
			||||||
import hmac
 | 
					import hmac
 | 
				
			||||||
@ -48,13 +49,14 @@ from logging import getLogger
 | 
				
			|||||||
from os import urandom
 | 
					from os import urandom
 | 
				
			||||||
from select import select
 | 
					from select import select
 | 
				
			||||||
from weakref import proxy
 | 
					from weakref import proxy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from err import openssl_error, InvalidSocketError
 | 
					from err import openssl_error, InvalidSocketError
 | 
				
			||||||
from err import raise_ssl_error
 | 
					from err import raise_ssl_error
 | 
				
			||||||
from err import SSL_ERROR_WANT_READ, SSL_ERROR_SYSCALL
 | 
					from err import SSL_ERROR_WANT_READ, SSL_ERROR_SYSCALL
 | 
				
			||||||
from err import ERR_COOKIE_MISMATCH, ERR_NO_CERTS
 | 
					from err import ERR_WRONG_VERSION_NUMBER, ERR_COOKIE_MISMATCH, ERR_NO_SHARED_CIPHER
 | 
				
			||||||
from err import ERR_NO_CIPHER, ERR_HANDSHAKE_TIMEOUT, ERR_PORT_UNREACHABLE
 | 
					from err import ERR_NO_CIPHER, ERR_HANDSHAKE_TIMEOUT, ERR_PORT_UNREACHABLE
 | 
				
			||||||
from err import ERR_READ_TIMEOUT, ERR_WRITE_TIMEOUT
 | 
					from err import ERR_READ_TIMEOUT, ERR_WRITE_TIMEOUT
 | 
				
			||||||
from err import ERR_BOTH_KEY_CERT_FILES_SVR
 | 
					from err import ERR_BOTH_KEY_CERT_FILES, ERR_BOTH_KEY_CERT_FILES_SVR, ERR_NO_CERTS
 | 
				
			||||||
from x509 import _X509, decode_cert
 | 
					from x509 import _X509, decode_cert
 | 
				
			||||||
from tlock import tlock_init
 | 
					from tlock import tlock_init
 | 
				
			||||||
from openssl import *
 | 
					from openssl import *
 | 
				
			||||||
@ -63,6 +65,8 @@ from util import _Rsrc, _BIO
 | 
				
			|||||||
_logger = getLogger(__name__)
 | 
					_logger = getLogger(__name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PROTOCOL_DTLSv1 = 256
 | 
					PROTOCOL_DTLSv1 = 256
 | 
				
			||||||
 | 
					PROTOCOL_DTLSv1_2 = 258
 | 
				
			||||||
 | 
					PROTOCOL_DTLS = 259
 | 
				
			||||||
CERT_NONE = 0
 | 
					CERT_NONE = 0
 | 
				
			||||||
CERT_OPTIONAL = 1
 | 
					CERT_OPTIONAL = 1
 | 
				
			||||||
CERT_REQUIRED = 2
 | 
					CERT_REQUIRED = 2
 | 
				
			||||||
@ -83,6 +87,58 @@ DTLS_OPENSSL_VERSION_INFO = (
 | 
				
			|||||||
    DTLS_OPENSSL_VERSION_NUMBER       & 0xF)   # status
 | 
					    DTLS_OPENSSL_VERSION_NUMBER       & 0xF)   # status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _ssl_logging_cb(conn, where, return_code):
 | 
				
			||||||
 | 
					    _state = where & ~SSL_ST_MASK
 | 
				
			||||||
 | 
					    state = "SSL"
 | 
				
			||||||
 | 
					    if _state & SSL_ST_INIT == SSL_ST_INIT:
 | 
				
			||||||
 | 
					        if _state & SSL_ST_RENEGOTIATE == SSL_ST_RENEGOTIATE:
 | 
				
			||||||
 | 
					            state += "_renew"
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            state += "_init"
 | 
				
			||||||
 | 
					    elif _state & SSL_ST_CONNECT:
 | 
				
			||||||
 | 
					        state += "_connect"
 | 
				
			||||||
 | 
					    elif _state & SSL_ST_ACCEPT:
 | 
				
			||||||
 | 
					        state += "_accept"
 | 
				
			||||||
 | 
					    elif _state == 0:
 | 
				
			||||||
 | 
					        if where & SSL_CB_HANDSHAKE_START:
 | 
				
			||||||
 | 
					            state += "_handshake_start"
 | 
				
			||||||
 | 
					        elif where & SSL_CB_HANDSHAKE_DONE:
 | 
				
			||||||
 | 
					            state += "_handshake_done"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if where & SSL_CB_LOOP:
 | 
				
			||||||
 | 
					        state += '_loop'
 | 
				
			||||||
 | 
					        _logger.debug("%s:%s:%d" % (state,
 | 
				
			||||||
 | 
					                                    SSL_state_string_long(conn),
 | 
				
			||||||
 | 
					                                    return_code))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    elif where & SSL_CB_ALERT:
 | 
				
			||||||
 | 
					        state += '_alert'
 | 
				
			||||||
 | 
					        state += "_read" if where & SSL_CB_READ else "_write"
 | 
				
			||||||
 | 
					        _logger.debug("%s:%s:%s" % (state,
 | 
				
			||||||
 | 
					                                    SSL_alert_type_string_long(return_code),
 | 
				
			||||||
 | 
					                                    SSL_alert_desc_string_long(return_code)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    elif where & SSL_CB_EXIT:
 | 
				
			||||||
 | 
					        state += '_exit'
 | 
				
			||||||
 | 
					        if return_code == 0:
 | 
				
			||||||
 | 
					            _logger.debug("%s:%s:%d(failed)" % (state,
 | 
				
			||||||
 | 
					                                                SSL_state_string_long(conn),
 | 
				
			||||||
 | 
					                                                return_code))
 | 
				
			||||||
 | 
					        elif return_code < 0:
 | 
				
			||||||
 | 
					            _logger.debug("%s:%s:%d(error)" % (state,
 | 
				
			||||||
 | 
					                                               SSL_state_string_long(conn),
 | 
				
			||||||
 | 
					                                               return_code))
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            _logger.debug("%s:%s:%d" % (state,
 | 
				
			||||||
 | 
					                                        SSL_state_string_long(conn),
 | 
				
			||||||
 | 
					                                        return_code))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        _logger.debug("%s:%s:%d" % (state,
 | 
				
			||||||
 | 
					                                    SSL_state_string_long(conn),
 | 
				
			||||||
 | 
					                                    return_code))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _CTX(_Rsrc):
 | 
					class _CTX(_Rsrc):
 | 
				
			||||||
    """SSL_CTX wrapper"""
 | 
					    """SSL_CTX wrapper"""
 | 
				
			||||||
    def __init__(self, value):
 | 
					    def __init__(self, value):
 | 
				
			||||||
@ -122,6 +178,124 @@ class _CallbackProxy(object):
 | 
				
			|||||||
        return self.ssl_func(self.ssl_connection, *args, **kwargs)
 | 
					        return self.ssl_func(self.ssl_connection, *args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SSLContext(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, ctx):
 | 
				
			||||||
 | 
					        self._ctx = ctx
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def set_ciphers(self, ciphers):
 | 
				
			||||||
 | 
					        u'''
 | 
				
			||||||
 | 
					        s.a. https://www.openssl.org/docs/man1.1.0/apps/ciphers.html
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param str ciphers: Example "AES256-SHA:ECDHE-ECDSA-AES256-SHA", ...
 | 
				
			||||||
 | 
					        :return: 1 for success and 0 for failure
 | 
				
			||||||
 | 
					        '''
 | 
				
			||||||
 | 
					        retVal = SSL_CTX_set_cipher_list(self._ctx, ciphers)
 | 
				
			||||||
 | 
					        return retVal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def set_sigalgs(self, sigalgs):
 | 
				
			||||||
 | 
					        u'''
 | 
				
			||||||
 | 
					        s.a. https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_set1_sigalgs_list.html
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param str sigalgs: Example "RSA+SHA256", "ECDSA+SHA256", ...
 | 
				
			||||||
 | 
					        :return: 1 for success and 0 for failure
 | 
				
			||||||
 | 
					        '''
 | 
				
			||||||
 | 
					        retVal = SSL_CTX_set1_sigalgs_list(self._ctx, sigalgs)
 | 
				
			||||||
 | 
					        return retVal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def set_curves(self, curves):
 | 
				
			||||||
 | 
					        u''' Set supported curves by name, nid or nist.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param str | tuple(int) curves: Example "secp384r1:secp256k1", (715, 714), "P-384", "K-409:B-409:K-571", ...
 | 
				
			||||||
 | 
					        :return: 1 for success and 0 for failure
 | 
				
			||||||
 | 
					        '''
 | 
				
			||||||
 | 
					        retVal = None
 | 
				
			||||||
 | 
					        if isinstance(curves, str):
 | 
				
			||||||
 | 
					            retVal = SSL_CTX_set1_curves_list(self._ctx, curves)
 | 
				
			||||||
 | 
					        elif isinstance(curves, tuple):
 | 
				
			||||||
 | 
					            retVal = SSL_CTX_set1_curves(self._ctx, curves, len(curves))
 | 
				
			||||||
 | 
					        return retVal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @staticmethod
 | 
				
			||||||
 | 
					    def get_ec_nist2nid(nist):
 | 
				
			||||||
 | 
					        if not isinstance(nist, tuple):
 | 
				
			||||||
 | 
					            nist = nist.split(":")
 | 
				
			||||||
 | 
					        nid = tuple(EC_curve_nist2nid(x) for x in nist)
 | 
				
			||||||
 | 
					        return nid
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @staticmethod
 | 
				
			||||||
 | 
					    def get_ec_nid2nist(nid):
 | 
				
			||||||
 | 
					        if not isinstance(nid, tuple):
 | 
				
			||||||
 | 
					            nid = (nid, )
 | 
				
			||||||
 | 
					        nist = ":".join([EC_curve_nid2nist(x) for x in nid])
 | 
				
			||||||
 | 
					        return nist
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @staticmethod
 | 
				
			||||||
 | 
					    def get_ec_available(bAsName=True):
 | 
				
			||||||
 | 
					        curves = get_elliptic_curves()
 | 
				
			||||||
 | 
					        return sorted([x.name for x in curves] if bAsName else [x.nid for x in curves])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def set_ecdh_curve(self, curve_name=None):
 | 
				
			||||||
 | 
					        u''' Select a curve to use for ECDH(E) key exchange or set it to auto mode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Used for server only!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        s.a. openssl.exe ecparam -list_curves
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param None | str curve_name: None = Auto-mode, "secp256k1", "secp384r1", ...
 | 
				
			||||||
 | 
					        :return: 1 for success and 0 for failure
 | 
				
			||||||
 | 
					        '''
 | 
				
			||||||
 | 
					        if curve_name:
 | 
				
			||||||
 | 
					            retVal = SSL_CTX_set_ecdh_auto(self._ctx, 0)
 | 
				
			||||||
 | 
					            avail_curves = get_elliptic_curves()
 | 
				
			||||||
 | 
					            key = [curve for curve in avail_curves if curve.name == curve_name][0].to_EC_KEY()
 | 
				
			||||||
 | 
					            retVal &= SSL_CTX_set_tmp_ecdh(self._ctx, key)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            retVal = SSL_CTX_set_ecdh_auto(self._ctx, 1)
 | 
				
			||||||
 | 
					        return retVal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def build_cert_chain(self, flags=SSL_BUILD_CHAIN_FLAG_NONE):
 | 
				
			||||||
 | 
					        u'''
 | 
				
			||||||
 | 
					        Used for server side only!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param flags:
 | 
				
			||||||
 | 
					        :return: 1 for success and 0 for failure
 | 
				
			||||||
 | 
					        '''
 | 
				
			||||||
 | 
					        retVal = SSL_CTX_build_cert_chain(self._ctx, flags)
 | 
				
			||||||
 | 
					        return retVal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def set_ssl_logging(self, enable=False, func=_ssl_logging_cb):
 | 
				
			||||||
 | 
					        u''' Enable or disable SSL logging
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param True | False enable: Enable or disable SSL logging
 | 
				
			||||||
 | 
					        :param func: Callback function for logging
 | 
				
			||||||
 | 
					        '''
 | 
				
			||||||
 | 
					        if enable:
 | 
				
			||||||
 | 
					            SSL_CTX_set_info_callback(self._ctx, func)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            SSL_CTX_set_info_callback(self._ctx, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SSL(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, ssl):
 | 
				
			||||||
 | 
					        self._ssl = ssl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def set_mtu(self, mtu=None):
 | 
				
			||||||
 | 
					        if mtu:
 | 
				
			||||||
 | 
					            SSL_set_options(self._ssl, SSL_OP_NO_QUERY_MTU)
 | 
				
			||||||
 | 
					            SSL_set_mtu(self._ssl, mtu)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            SSL_clear_options(self._ssl, SSL_OP_NO_QUERY_MTU)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def set_link_mtu(self, mtu=None):
 | 
				
			||||||
 | 
					        if mtu:
 | 
				
			||||||
 | 
					            SSL_set_options(self._ssl, SSL_OP_NO_QUERY_MTU)
 | 
				
			||||||
 | 
					            DTLS_set_link_mtu(self._ssl, mtu)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            SSL_clear_options(self._ssl, SSL_OP_NO_QUERY_MTU)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SSLConnection(object):
 | 
					class SSLConnection(object):
 | 
				
			||||||
    """DTLS peer association
 | 
					    """DTLS peer association
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -149,7 +323,13 @@ class SSLConnection(object):
 | 
				
			|||||||
        else:
 | 
					        else:
 | 
				
			||||||
            self._rsock = rsock
 | 
					            self._rsock = rsock
 | 
				
			||||||
            self._rbio = _BIO(BIO_new_dgram(self._rsock.fileno(), BIO_NOCLOSE))
 | 
					            self._rbio = _BIO(BIO_new_dgram(self._rsock.fileno(), BIO_NOCLOSE))
 | 
				
			||||||
        self._ctx = _CTX(SSL_CTX_new(DTLSv1_server_method()))
 | 
					        server_method = DTLS_server_method
 | 
				
			||||||
 | 
					        if self._ssl_version == PROTOCOL_DTLSv1_2:
 | 
				
			||||||
 | 
					            server_method = DTLSv1_2_server_method
 | 
				
			||||||
 | 
					        elif self._ssl_version == PROTOCOL_DTLSv1:
 | 
				
			||||||
 | 
					            server_method = DTLSv1_server_method
 | 
				
			||||||
 | 
					        self._ctx = _CTX(SSL_CTX_new(server_method()))
 | 
				
			||||||
 | 
					        self._intf_ssl_ctx = SSLContext(self._ctx.value)
 | 
				
			||||||
        SSL_CTX_set_session_cache_mode(self._ctx.value, SSL_SESS_CACHE_OFF)
 | 
					        SSL_CTX_set_session_cache_mode(self._ctx.value, SSL_SESS_CACHE_OFF)
 | 
				
			||||||
        if self._cert_reqs == CERT_NONE:
 | 
					        if self._cert_reqs == CERT_NONE:
 | 
				
			||||||
            verify_mode = SSL_VERIFY_NONE
 | 
					            verify_mode = SSL_VERIFY_NONE
 | 
				
			||||||
@ -169,6 +349,7 @@ class SSLConnection(object):
 | 
				
			|||||||
                _CallbackProxy(self._generate_cookie_cb),
 | 
					                _CallbackProxy(self._generate_cookie_cb),
 | 
				
			||||||
                _CallbackProxy(self._verify_cookie_cb))
 | 
					                _CallbackProxy(self._verify_cookie_cb))
 | 
				
			||||||
        self._ssl = _SSL(SSL_new(self._ctx.value))
 | 
					        self._ssl = _SSL(SSL_new(self._ctx.value))
 | 
				
			||||||
 | 
					        self._intf_ssl = SSL(self._ssl.value)
 | 
				
			||||||
        SSL_set_accept_state(self._ssl.value)
 | 
					        SSL_set_accept_state(self._ssl.value)
 | 
				
			||||||
        if peer_address and self._do_handshake_on_connect:
 | 
					        if peer_address and self._do_handshake_on_connect:
 | 
				
			||||||
            return lambda: self.do_handshake()
 | 
					            return lambda: self.do_handshake()
 | 
				
			||||||
@ -179,13 +360,20 @@ class SSLConnection(object):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        self._wbio = _BIO(BIO_new_dgram(self._sock.fileno(), BIO_NOCLOSE))
 | 
					        self._wbio = _BIO(BIO_new_dgram(self._sock.fileno(), BIO_NOCLOSE))
 | 
				
			||||||
        self._rbio = self._wbio
 | 
					        self._rbio = self._wbio
 | 
				
			||||||
        self._ctx = _CTX(SSL_CTX_new(DTLSv1_client_method()))
 | 
					        client_method = DTLSv1_2_client_method  # no "any" exists, therefore use v1_2 (highest possible)
 | 
				
			||||||
 | 
					        if self._ssl_version == PROTOCOL_DTLSv1_2:
 | 
				
			||||||
 | 
					            client_method = DTLSv1_2_client_method
 | 
				
			||||||
 | 
					        elif self._ssl_version == PROTOCOL_DTLSv1:
 | 
				
			||||||
 | 
					            client_method = DTLSv1_client_method
 | 
				
			||||||
 | 
					        self._ctx = _CTX(SSL_CTX_new(client_method()))
 | 
				
			||||||
 | 
					        self._intf_ssl_ctx = SSLContext(self._ctx.value)
 | 
				
			||||||
        if self._cert_reqs == CERT_NONE:
 | 
					        if self._cert_reqs == CERT_NONE:
 | 
				
			||||||
            verify_mode = SSL_VERIFY_NONE
 | 
					            verify_mode = SSL_VERIFY_NONE
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            verify_mode = SSL_VERIFY_PEER
 | 
					            verify_mode = SSL_VERIFY_PEER
 | 
				
			||||||
        self._config_ssl_ctx(verify_mode)
 | 
					        self._config_ssl_ctx(verify_mode)
 | 
				
			||||||
        self._ssl = _SSL(SSL_new(self._ctx.value))
 | 
					        self._ssl = _SSL(SSL_new(self._ctx.value))
 | 
				
			||||||
 | 
					        self._intf_ssl = SSL(self._ssl.value)
 | 
				
			||||||
        SSL_set_connect_state(self._ssl.value)
 | 
					        SSL_set_connect_state(self._ssl.value)
 | 
				
			||||||
        if peer_address:
 | 
					        if peer_address:
 | 
				
			||||||
            return lambda: self.connect(peer_address)
 | 
					            return lambda: self.connect(peer_address)
 | 
				
			||||||
@ -208,6 +396,8 @@ class SSLConnection(object):
 | 
				
			|||||||
                SSL_CTX_set_cipher_list(self._ctx.value, self._ciphers)
 | 
					                SSL_CTX_set_cipher_list(self._ctx.value, self._ciphers)
 | 
				
			||||||
            except openssl_error() as err:
 | 
					            except openssl_error() as err:
 | 
				
			||||||
                raise_ssl_error(ERR_NO_CIPHER, err)
 | 
					                raise_ssl_error(ERR_NO_CIPHER, err)
 | 
				
			||||||
 | 
					        if self._user_config_ssl_ctx:
 | 
				
			||||||
 | 
					            self._user_config_ssl_ctx(self._intf_ssl_ctx)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _copy_server(self):
 | 
					    def _copy_server(self):
 | 
				
			||||||
        source = self._sock
 | 
					        source = self._sock
 | 
				
			||||||
@ -233,7 +423,10 @@ class SSLConnection(object):
 | 
				
			|||||||
            BIO_dgram_set_connected(self._wbio.value,
 | 
					            BIO_dgram_set_connected(self._wbio.value,
 | 
				
			||||||
                                    source._pending_peer_address)
 | 
					                                    source._pending_peer_address)
 | 
				
			||||||
        source._ssl = _SSL(SSL_new(self._ctx.value))
 | 
					        source._ssl = _SSL(SSL_new(self._ctx.value))
 | 
				
			||||||
 | 
					        self._intf_ssl = SSL(source._ssl.value)
 | 
				
			||||||
        SSL_set_accept_state(source._ssl.value)
 | 
					        SSL_set_accept_state(source._ssl.value)
 | 
				
			||||||
 | 
					        if self._user_config_ssl:
 | 
				
			||||||
 | 
					            self._user_config_ssl(self._intf_ssl)
 | 
				
			||||||
        source._rbio = new_source_rbio
 | 
					        source._rbio = new_source_rbio
 | 
				
			||||||
        source._wbio = new_source_wbio
 | 
					        source._wbio = new_source_wbio
 | 
				
			||||||
        SSL_set_bio(source._ssl.value,
 | 
					        SSL_set_bio(source._ssl.value,
 | 
				
			||||||
@ -252,7 +445,10 @@ class SSLConnection(object):
 | 
				
			|||||||
        self._rbio = _BIO(BIO_new_dgram(self._rsock.fileno(), BIO_NOCLOSE))
 | 
					        self._rbio = _BIO(BIO_new_dgram(self._rsock.fileno(), BIO_NOCLOSE))
 | 
				
			||||||
        BIO_dgram_set_peer(self._wbio.value, source._peer_address)
 | 
					        BIO_dgram_set_peer(self._wbio.value, source._peer_address)
 | 
				
			||||||
        self._ssl = _SSL(SSL_new(self._ctx.value))
 | 
					        self._ssl = _SSL(SSL_new(self._ctx.value))
 | 
				
			||||||
 | 
					        self._intf_ssl = SSL(self._ssl.value)
 | 
				
			||||||
        SSL_set_accept_state(self._ssl.value)
 | 
					        SSL_set_accept_state(self._ssl.value)
 | 
				
			||||||
 | 
					        if self._user_config_ssl:
 | 
				
			||||||
 | 
					            self._user_config_ssl(self._intf_ssl)
 | 
				
			||||||
        if self._do_handshake_on_connect:
 | 
					        if self._do_handshake_on_connect:
 | 
				
			||||||
            return lambda: self.do_handshake()
 | 
					            return lambda: self.do_handshake()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -310,9 +506,11 @@ class SSLConnection(object):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def __init__(self, sock, keyfile=None, certfile=None,
 | 
					    def __init__(self, sock, keyfile=None, certfile=None,
 | 
				
			||||||
                 server_side=False, cert_reqs=CERT_NONE,
 | 
					                 server_side=False, cert_reqs=CERT_NONE,
 | 
				
			||||||
                 ssl_version=PROTOCOL_DTLSv1, ca_certs=None,
 | 
					                 ssl_version=PROTOCOL_DTLS, ca_certs=None,
 | 
				
			||||||
                 do_handshake_on_connect=True,
 | 
					                 do_handshake_on_connect=True,
 | 
				
			||||||
                 suppress_ragged_eofs=True, ciphers=None):
 | 
					                 suppress_ragged_eofs=True, ciphers=None,
 | 
				
			||||||
 | 
					                 cb_user_config_ssl_ctx=None,
 | 
				
			||||||
 | 
					                 cb_user_config_ssl=None):
 | 
				
			||||||
        """Constructor
 | 
					        """Constructor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Arguments:
 | 
					        Arguments:
 | 
				
			||||||
@ -334,6 +532,7 @@ class SSLConnection(object):
 | 
				
			|||||||
        self._keyfile = keyfile
 | 
					        self._keyfile = keyfile
 | 
				
			||||||
        self._certfile = certfile
 | 
					        self._certfile = certfile
 | 
				
			||||||
        self._cert_reqs = cert_reqs
 | 
					        self._cert_reqs = cert_reqs
 | 
				
			||||||
 | 
					        self._ssl_version = ssl_version
 | 
				
			||||||
        self._ca_certs = ca_certs
 | 
					        self._ca_certs = ca_certs
 | 
				
			||||||
        self._do_handshake_on_connect = do_handshake_on_connect
 | 
					        self._do_handshake_on_connect = do_handshake_on_connect
 | 
				
			||||||
        self._suppress_ragged_eofs = suppress_ragged_eofs
 | 
					        self._suppress_ragged_eofs = suppress_ragged_eofs
 | 
				
			||||||
@ -341,6 +540,11 @@ class SSLConnection(object):
 | 
				
			|||||||
        self._handshake_done = False
 | 
					        self._handshake_done = False
 | 
				
			||||||
        self._wbio_nb = self._rbio_nb = False
 | 
					        self._wbio_nb = self._rbio_nb = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self._user_config_ssl_ctx = cb_user_config_ssl_ctx
 | 
				
			||||||
 | 
					        self._intf_ssl_ctx = None
 | 
				
			||||||
 | 
					        self._user_config_ssl = cb_user_config_ssl
 | 
				
			||||||
 | 
					        self._intf_ssl = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if isinstance(sock, SSLConnection):
 | 
					        if isinstance(sock, SSLConnection):
 | 
				
			||||||
            post_init = self._copy_server()
 | 
					            post_init = self._copy_server()
 | 
				
			||||||
        elif isinstance(sock, _UnwrappedSocket):
 | 
					        elif isinstance(sock, _UnwrappedSocket):
 | 
				
			||||||
@ -355,12 +559,18 @@ class SSLConnection(object):
 | 
				
			|||||||
            else:
 | 
					            else:
 | 
				
			||||||
                post_init = self._init_client(peer_address)
 | 
					                post_init = self._init_client(peer_address)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if self._user_config_ssl:
 | 
				
			||||||
 | 
					            self._user_config_ssl(self._intf_ssl)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if sys.platform.startswith('win') and not (SSL_get_options(self._ssl.value) & SSL_OP_NO_QUERY_MTU):
 | 
				
			||||||
 | 
					            SSL_set_options(self._ssl.value, SSL_OP_NO_QUERY_MTU)
 | 
				
			||||||
 | 
					            DTLS_set_link_mtu(self._ssl.value, 1500)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        SSL_set_bio(self._ssl.value, self._rbio.value, self._wbio.value)
 | 
					        SSL_set_bio(self._ssl.value, self._rbio.value, self._wbio.value)
 | 
				
			||||||
        self._rbio.disown()
 | 
					        self._rbio.disown()
 | 
				
			||||||
        self._wbio.disown()
 | 
					        self._wbio.disown()
 | 
				
			||||||
        if post_init:
 | 
					        if post_init:
 | 
				
			||||||
            post_init()
 | 
					            post_init()
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_socket(self, inbound):
 | 
					    def get_socket(self, inbound):
 | 
				
			||||||
        """Retrieve a socket used by this connection
 | 
					        """Retrieve a socket used by this connection
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -430,9 +640,15 @@ class SSLConnection(object):
 | 
				
			|||||||
                # This method must be called again to forward the next datagram
 | 
					                # This method must be called again to forward the next datagram
 | 
				
			||||||
                _logger.debug("DTLSv1_listen must be resumed")
 | 
					                _logger.debug("DTLSv1_listen must be resumed")
 | 
				
			||||||
                return
 | 
					                return
 | 
				
			||||||
 | 
					            elif err.errqueue and err.errqueue[0][0] == ERR_WRONG_VERSION_NUMBER:
 | 
				
			||||||
 | 
					                _logger.debug("Wrong version number; aborting handshake")
 | 
				
			||||||
 | 
					                raise
 | 
				
			||||||
            elif err.errqueue and err.errqueue[0][0] == ERR_COOKIE_MISMATCH:
 | 
					            elif err.errqueue and err.errqueue[0][0] == ERR_COOKIE_MISMATCH:
 | 
				
			||||||
                _logger.debug("Mismatching cookie received; aborting handshake")
 | 
					                _logger.debug("Mismatching cookie received; aborting handshake")
 | 
				
			||||||
                return
 | 
					                raise
 | 
				
			||||||
 | 
					            elif err.errqueue and err.errqueue[0][0] == ERR_NO_SHARED_CIPHER:
 | 
				
			||||||
 | 
					                _logger.debug("No shared cipher; aborting handshake")
 | 
				
			||||||
 | 
					                raise
 | 
				
			||||||
            _logger.exception("Unexpected error in DTLSv1_listen")
 | 
					            _logger.exception("Unexpected error in DTLSv1_listen")
 | 
				
			||||||
            raise
 | 
					            raise
 | 
				
			||||||
        finally:
 | 
					        finally:
 | 
				
			||||||
@ -462,9 +678,11 @@ class SSLConnection(object):
 | 
				
			|||||||
                _logger.debug("Accept returning without connection")
 | 
					                _logger.debug("Accept returning without connection")
 | 
				
			||||||
                return
 | 
					                return
 | 
				
			||||||
        new_conn = SSLConnection(self, self._keyfile, self._certfile, True,
 | 
					        new_conn = SSLConnection(self, self._keyfile, self._certfile, True,
 | 
				
			||||||
                                 self._cert_reqs, PROTOCOL_DTLSv1,
 | 
					                                 self._cert_reqs, self._ssl_version,
 | 
				
			||||||
                                 self._ca_certs, self._do_handshake_on_connect,
 | 
					                                 self._ca_certs, self._do_handshake_on_connect,
 | 
				
			||||||
                                 self._suppress_ragged_eofs, self._ciphers)
 | 
					                                 self._suppress_ragged_eofs, self._ciphers,
 | 
				
			||||||
 | 
					                                 cb_user_config_ssl_ctx=self._user_config_ssl_ctx,
 | 
				
			||||||
 | 
					                                 cb_user_config_ssl=self._user_config_ssl)
 | 
				
			||||||
        new_peer = self._pending_peer_address
 | 
					        new_peer = self._pending_peer_address
 | 
				
			||||||
        self._pending_peer_address = None
 | 
					        self._pending_peer_address = None
 | 
				
			||||||
        if self._do_handshake_on_connect:
 | 
					        if self._do_handshake_on_connect:
 | 
				
			||||||
@ -525,8 +743,13 @@ class SSLConnection(object):
 | 
				
			|||||||
        string containing read bytes
 | 
					        string containing read bytes
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
            return self._wrap_socket_library_call(
 | 
					            return self._wrap_socket_library_call(
 | 
				
			||||||
                lambda: SSL_read(self._ssl.value, len, buffer), ERR_READ_TIMEOUT)
 | 
					                lambda: SSL_read(self._ssl.value, len, buffer), ERR_READ_TIMEOUT)
 | 
				
			||||||
 | 
					        except openssl_error() as err:
 | 
				
			||||||
 | 
					            if err.ssl_error == SSL_ERROR_SYSCALL and err.result == -1:
 | 
				
			||||||
 | 
					                raise_ssl_error(ERR_PORT_UNREACHABLE, err)
 | 
				
			||||||
 | 
					            raise
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def write(self, data):
 | 
					    def write(self, data):
 | 
				
			||||||
        """Write data to connection
 | 
					        """Write data to connection
 | 
				
			||||||
@ -540,8 +763,16 @@ class SSLConnection(object):
 | 
				
			|||||||
        number of bytes actually transmitted
 | 
					        number of bytes actually transmitted
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return self._wrap_socket_library_call(
 | 
					        try:
 | 
				
			||||||
 | 
					            ret = self._wrap_socket_library_call(
 | 
				
			||||||
                lambda: SSL_write(self._ssl.value, data), ERR_WRITE_TIMEOUT)
 | 
					                lambda: SSL_write(self._ssl.value, data), ERR_WRITE_TIMEOUT)
 | 
				
			||||||
 | 
					        except openssl_error() as err:
 | 
				
			||||||
 | 
					            if err.ssl_error == SSL_ERROR_SYSCALL and err.result == -1:
 | 
				
			||||||
 | 
					                raise_ssl_error(ERR_PORT_UNREACHABLE, err)
 | 
				
			||||||
 | 
					            raise
 | 
				
			||||||
 | 
					        if ret:
 | 
				
			||||||
 | 
					            self._handshake_done = True
 | 
				
			||||||
 | 
					        return ret
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def shutdown(self):
 | 
					    def shutdown(self):
 | 
				
			||||||
        """Shut down the DTLS connection
 | 
					        """Shut down the DTLS connection
 | 
				
			||||||
@ -605,6 +836,21 @@ class SSLConnection(object):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    peer_certificate = getpeercert  # compatibility with _ssl call interface
 | 
					    peer_certificate = getpeercert  # compatibility with _ssl call interface
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def getpeercertchain(self, binary_form=False):
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            stack, num, certs = SSL_get_peer_cert_chain(self._ssl.value)
 | 
				
			||||||
 | 
					        except openssl_error():
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        peer_cert_chain = [_Rsrc(cert) for cert in certs]
 | 
				
			||||||
 | 
					        ret = []
 | 
				
			||||||
 | 
					        if binary_form:
 | 
				
			||||||
 | 
					            ret = [i2d_X509(x.value) for x in peer_cert_chain]
 | 
				
			||||||
 | 
					        elif len(peer_cert_chain):
 | 
				
			||||||
 | 
					            ret = [decode_cert(x) for x in peer_cert_chain]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return ret
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def cipher(self):
 | 
					    def cipher(self):
 | 
				
			||||||
        """Retrieve information about the current cipher
 | 
					        """Retrieve information about the current cipher
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										11
									
								
								dtls/test/certs/ca-cert_ec.pem
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								dtls/test/certs/ca-cert_ec.pem
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					-----BEGIN CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIBgzCCASoCCQDdMwvUA/R3lzAKBggqhkjOPQQDAzBKMQswCQYDVQQGEwJVUzET
 | 
				
			||||||
 | 
					MBEGA1UECAwKV2FzaGluZ3RvbjETMBEGA1UECgwKUmF5IENBIEluYzERMA8GA1UE
 | 
				
			||||||
 | 
					AwwIUmF5Q0FJbmMwHhcNMTcwMzA3MDgzNjU3WhcNMjcwMzA1MDgzNjU3WjBKMQsw
 | 
				
			||||||
 | 
					CQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjETMBEGA1UECgwKUmF5IENB
 | 
				
			||||||
 | 
					IEluYzERMA8GA1UEAwwIUmF5Q0FJbmMwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC
 | 
				
			||||||
 | 
					AASD4xiQkPryjEwUl/GYeGu1CSA3UC6BUY3TiGED3zrC5Bn/POaVVn9GGOQMZUFi
 | 
				
			||||||
 | 
					rCkuTgfg/qeIzTrTFndiR5C/MAoGCCqGSM49BAMDA0cAMEQCIHpd9qMvZZV6iaB5
 | 
				
			||||||
 | 
					HrmlyfmhIuLBxDQra20Uxl2Y8N64AiAmPKqwPPp7z6IT2AzAXyHCPoVxwWA0NfGx
 | 
				
			||||||
 | 
					nmXoYpDFlw==
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----
 | 
				
			||||||
							
								
								
									
										19
									
								
								dtls/test/certs/keycert_ec.pem
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								dtls/test/certs/keycert_ec.pem
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					-----BEGIN EC PARAMETERS-----
 | 
				
			||||||
 | 
					BggqhkjOPQMBBw==
 | 
				
			||||||
 | 
					-----END EC PARAMETERS-----
 | 
				
			||||||
 | 
					-----BEGIN EC PRIVATE KEY-----
 | 
				
			||||||
 | 
					MHcCAQEEIEMWCku4TqKwrQdeECm5LQPCBnr7+cqE4InlRYeObLOxoAoGCCqGSM49
 | 
				
			||||||
 | 
					AwEHoUQDQgAEgroFe2fym1V7E3zr/zjuJixpyAjwfig+UTsxxm/04IvXzk2jQCQC
 | 
				
			||||||
 | 
					TgbDVohJ8dgh4iEENZv2axWye7XCBzbftQ==
 | 
				
			||||||
 | 
					-----END EC PRIVATE KEY-----
 | 
				
			||||||
 | 
					-----BEGIN CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIBhjCCASwCCQCZ3L2TA/e93zAKBggqhkjOPQQDAzBKMQswCQYDVQQGEwJVUzET
 | 
				
			||||||
 | 
					MBEGA1UECAwKV2FzaGluZ3RvbjETMBEGA1UECgwKUmF5IENBIEluYzERMA8GA1UE
 | 
				
			||||||
 | 
					AwwIUmF5Q0FJbmMwHhcNMTcwMzA3MDgzNjU4WhcNMjcwMzA1MDgzNjU4WjBMMQsw
 | 
				
			||||||
 | 
					CQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEUMBIGA1UECgwLUmF5IFNy
 | 
				
			||||||
 | 
					diBJbmMxEjAQBgNVBAMMCVJheVNydkluYzBZMBMGByqGSM49AgEGCCqGSM49AwEH
 | 
				
			||||||
 | 
					A0IABIK6BXtn8ptVexN86/847iYsacgI8H4oPlE7McZv9OCL185No0AkAk4Gw1aI
 | 
				
			||||||
 | 
					SfHYIeIhBDWb9msVsnu1wgc237UwCgYIKoZIzj0EAwMDSAAwRQIhAK4caAt0QSTz
 | 
				
			||||||
 | 
					A1WYlrEAA2AH181P7USiXkqQ5qRyoWQNAiBm3vKaoB+0p4B98HeI+h5V/7loomQg
 | 
				
			||||||
 | 
					sW3uB0zEuJyqIQ==
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----
 | 
				
			||||||
							
								
								
									
										11
									
								
								dtls/test/certs/server-cert_ec.pem
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								dtls/test/certs/server-cert_ec.pem
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					-----BEGIN CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIBhjCCASwCCQCZ3L2TA/e93zAKBggqhkjOPQQDAzBKMQswCQYDVQQGEwJVUzET
 | 
				
			||||||
 | 
					MBEGA1UECAwKV2FzaGluZ3RvbjETMBEGA1UECgwKUmF5IENBIEluYzERMA8GA1UE
 | 
				
			||||||
 | 
					AwwIUmF5Q0FJbmMwHhcNMTcwMzA3MDgzNjU4WhcNMjcwMzA1MDgzNjU4WjBMMQsw
 | 
				
			||||||
 | 
					CQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEUMBIGA1UECgwLUmF5IFNy
 | 
				
			||||||
 | 
					diBJbmMxEjAQBgNVBAMMCVJheVNydkluYzBZMBMGByqGSM49AgEGCCqGSM49AwEH
 | 
				
			||||||
 | 
					A0IABIK6BXtn8ptVexN86/847iYsacgI8H4oPlE7McZv9OCL185No0AkAk4Gw1aI
 | 
				
			||||||
 | 
					SfHYIeIhBDWb9msVsnu1wgc237UwCgYIKoZIzj0EAwMDSAAwRQIhAK4caAt0QSTz
 | 
				
			||||||
 | 
					A1WYlrEAA2AH181P7USiXkqQ5qRyoWQNAiBm3vKaoB+0p4B98HeI+h5V/7loomQg
 | 
				
			||||||
 | 
					sW3uB0zEuJyqIQ==
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----
 | 
				
			||||||
@ -39,6 +39,7 @@ basicConfig(level=DEBUG)  # set now for dtls import code
 | 
				
			|||||||
from dtls.sslconnection import SSLConnection
 | 
					from dtls.sslconnection import SSLConnection
 | 
				
			||||||
from dtls.err import SSLError, SSL_ERROR_WANT_READ, SSL_ERROR_ZERO_RETURN
 | 
					from dtls.err import SSLError, SSL_ERROR_WANT_READ, SSL_ERROR_ZERO_RETURN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def main():
 | 
					def main():
 | 
				
			||||||
    sck = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
 | 
					    sck = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
 | 
				
			||||||
    sck.bind(("127.0.0.1", 28000))
 | 
					    sck.bind(("127.0.0.1", 28000))
 | 
				
			||||||
@ -46,8 +47,8 @@ def main():
 | 
				
			|||||||
    cert_path = path.join(path.abspath(path.dirname(__file__)), "certs")
 | 
					    cert_path = path.join(path.abspath(path.dirname(__file__)), "certs")
 | 
				
			||||||
    scn = SSLConnection(
 | 
					    scn = SSLConnection(
 | 
				
			||||||
        sck,
 | 
					        sck,
 | 
				
			||||||
        keyfile=path.join(cert_path, "server-key.pem"),
 | 
					        keyfile=path.join(cert_path, "keycert.pem"),
 | 
				
			||||||
        certfile=path.join(cert_path, "server-cert.pem"),
 | 
					        certfile=path.join(cert_path, "keycert.pem"),
 | 
				
			||||||
        server_side=True,
 | 
					        server_side=True,
 | 
				
			||||||
        ca_certs=path.join(cert_path, "ca-cert.pem"),
 | 
					        ca_certs=path.join(cert_path, "ca-cert.pem"),
 | 
				
			||||||
        do_handshake_on_connect=False)
 | 
					        do_handshake_on_connect=False)
 | 
				
			||||||
@ -76,7 +77,7 @@ def main():
 | 
				
			|||||||
        try:
 | 
					        try:
 | 
				
			||||||
            conn.do_handshake()
 | 
					            conn.do_handshake()
 | 
				
			||||||
        except SSLError as err:
 | 
					        except SSLError as err:
 | 
				
			||||||
            if str(err).startswith("504:"):
 | 
					            if err.errno == 504:
 | 
				
			||||||
                continue
 | 
					                continue
 | 
				
			||||||
            raise
 | 
					            raise
 | 
				
			||||||
        print "Completed handshaking with peer"
 | 
					        print "Completed handshaking with peer"
 | 
				
			||||||
@ -92,7 +93,7 @@ def main():
 | 
				
			|||||||
        try:
 | 
					        try:
 | 
				
			||||||
            message = conn.read()
 | 
					            message = conn.read()
 | 
				
			||||||
        except SSLError as err:
 | 
					        except SSLError as err:
 | 
				
			||||||
            if str(err).startswith("502:"):
 | 
					            if err.errno == 502:
 | 
				
			||||||
                continue
 | 
					                continue
 | 
				
			||||||
            if err.args[0] == SSL_ERROR_ZERO_RETURN:
 | 
					            if err.args[0] == SSL_ERROR_ZERO_RETURN:
 | 
				
			||||||
                break
 | 
					                break
 | 
				
			||||||
@ -111,7 +112,7 @@ def main():
 | 
				
			|||||||
            s = conn.shutdown()
 | 
					            s = conn.shutdown()
 | 
				
			||||||
            s.shutdown(socket.SHUT_RDWR)
 | 
					            s.shutdown(socket.SHUT_RDWR)
 | 
				
			||||||
        except SSLError as err:
 | 
					        except SSLError as err:
 | 
				
			||||||
            if str(err).startswith("502:"):
 | 
					            if err.errno == 502:
 | 
				
			||||||
                continue
 | 
					                continue
 | 
				
			||||||
            raise
 | 
					            raise
 | 
				
			||||||
        break
 | 
					        break
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										24
									
								
								dtls/test/makecerts_ec.bat
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								dtls/test/makecerts_ec.bat
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					@echo off
 | 
				
			||||||
 | 
					set RANDFILE=.rnd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rem # Generate self-signed certificate for the certificate authority
 | 
				
			||||||
 | 
					echo Generating CA...
 | 
				
			||||||
 | 
					openssl ecparam -name prime256v1 -genkey -out tmp_ca_ec.key
 | 
				
			||||||
 | 
					openssl req -config "openssl_ca.cnf" -x509 -new -SHA384 -nodes -key tmp_ca_ec.key -days 3650 -out ca-cert_ec.pem
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rem # Generate a certificate request
 | 
				
			||||||
 | 
					echo Generating certificate request...
 | 
				
			||||||
 | 
					openssl ecparam -name prime256v1 -genkey -out tmp_server_ec.key
 | 
				
			||||||
 | 
					openssl req -config "openssl_server.cnf" -new -SHA384 -nodes -key tmp_server_ec.key -out tmp_server_ec.req
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rem # Sign the request with the certificate authority's certificate created above
 | 
				
			||||||
 | 
					echo Signing certificate request...
 | 
				
			||||||
 | 
					openssl req -in tmp_server_ec.req -noout -text
 | 
				
			||||||
 | 
					openssl x509 -req -SHA384 -days 3650 -in tmp_server_ec.req -CA ca-cert_ec.pem -CAkey tmp_ca_ec.key -CAcreateserial -out server-cert_ec.pem
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rem # Build pem file with private and public keys, ready for unprompted server use
 | 
				
			||||||
 | 
					cat tmp_server_ec.key server-cert_ec.pem > keycert_ec.pem
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rem # Clean up
 | 
				
			||||||
 | 
					rm tmp_ca_ec.key tmp_server_ec.key tmp_server_ec.req ca-cert_ec.srl
 | 
				
			||||||
@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					HOME                   = .
 | 
				
			||||||
RANDFILE               = $ENV::HOME/.rnd
 | 
					RANDFILE               = $ENV::HOME/.rnd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[ req ]
 | 
					[ req ]
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					HOME                   = .
 | 
				
			||||||
RANDFILE               = $ENV::HOME/.rnd
 | 
					RANDFILE               = $ENV::HOME/.rnd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[ req ]
 | 
					[ req ]
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										15
									
								
								dtls/test/simple_client.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								dtls/test/simple_client.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					from os import path
 | 
				
			||||||
 | 
					import ssl
 | 
				
			||||||
 | 
					from socket import socket, AF_INET, SOCK_DGRAM, SHUT_RDWR
 | 
				
			||||||
 | 
					from logging import basicConfig, DEBUG
 | 
				
			||||||
 | 
					basicConfig(level=DEBUG)  # set now for dtls import code
 | 
				
			||||||
 | 
					from dtls import do_patch
 | 
				
			||||||
 | 
					do_patch()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cert_path = path.join(path.abspath(path.dirname(__file__)), "certs")
 | 
				
			||||||
 | 
					sock = ssl.wrap_socket(socket(AF_INET, SOCK_DGRAM), cert_reqs=ssl.CERT_REQUIRED, ca_certs=path.join(cert_path, "ca-cert.pem"))
 | 
				
			||||||
 | 
					sock.connect(('localhost', 28000))
 | 
				
			||||||
 | 
					sock.send('Hi there')
 | 
				
			||||||
 | 
					print sock.recv()
 | 
				
			||||||
 | 
					sock.unwrap()
 | 
				
			||||||
 | 
					sock.shutdown(SHUT_RDWR)
 | 
				
			||||||
@ -80,6 +80,8 @@ class BasicSocketTests(unittest.TestCase):
 | 
				
			|||||||
        ssl.PROTOCOL_SSLv23
 | 
					        ssl.PROTOCOL_SSLv23
 | 
				
			||||||
        ssl.PROTOCOL_TLSv1
 | 
					        ssl.PROTOCOL_TLSv1
 | 
				
			||||||
        ssl.PROTOCOL_DTLSv1  # added
 | 
					        ssl.PROTOCOL_DTLSv1  # added
 | 
				
			||||||
 | 
					        ssl.PROTOCOL_DTLSv1_2  # added
 | 
				
			||||||
 | 
					        ssl.PROTOCOL_DTLS  # added
 | 
				
			||||||
        ssl.CERT_NONE
 | 
					        ssl.CERT_NONE
 | 
				
			||||||
        ssl.CERT_OPTIONAL
 | 
					        ssl.CERT_OPTIONAL
 | 
				
			||||||
        ssl.CERT_REQUIRED
 | 
					        ssl.CERT_REQUIRED
 | 
				
			||||||
@ -92,8 +94,8 @@ class BasicSocketTests(unittest.TestCase):
 | 
				
			|||||||
        self.assertIsInstance(t, tuple)
 | 
					        self.assertIsInstance(t, tuple)
 | 
				
			||||||
        self.assertIsInstance(s, str)
 | 
					        self.assertIsInstance(s, str)
 | 
				
			||||||
        # Some sanity checks follow
 | 
					        # Some sanity checks follow
 | 
				
			||||||
        # >= 1.0
 | 
					        # >= 1.0.2
 | 
				
			||||||
        self.assertGreaterEqual(n, 0x10000000)
 | 
					        self.assertGreaterEqual(n, 0x10002000)
 | 
				
			||||||
        # < 2.0
 | 
					        # < 2.0
 | 
				
			||||||
        self.assertLess(n, 0x20000000)
 | 
					        self.assertLess(n, 0x20000000)
 | 
				
			||||||
        major, minor, fix, patch, status = t
 | 
					        major, minor, fix, patch, status = t
 | 
				
			||||||
@ -101,7 +103,7 @@ class BasicSocketTests(unittest.TestCase):
 | 
				
			|||||||
        self.assertLess(major, 2)
 | 
					        self.assertLess(major, 2)
 | 
				
			||||||
        self.assertGreaterEqual(minor, 0)
 | 
					        self.assertGreaterEqual(minor, 0)
 | 
				
			||||||
        self.assertLess(minor, 256)
 | 
					        self.assertLess(minor, 256)
 | 
				
			||||||
        self.assertGreaterEqual(fix, 0)
 | 
					        self.assertGreaterEqual(fix, 2)
 | 
				
			||||||
        self.assertLess(fix, 256)
 | 
					        self.assertLess(fix, 256)
 | 
				
			||||||
        self.assertGreaterEqual(patch, 0)
 | 
					        self.assertGreaterEqual(patch, 0)
 | 
				
			||||||
        self.assertLessEqual(patch, 26)
 | 
					        self.assertLessEqual(patch, 26)
 | 
				
			||||||
@ -300,23 +302,25 @@ class NetworkedTests(unittest.TestCase):
 | 
				
			|||||||
                                  "to establish session.\n") % count)
 | 
					                                  "to establish session.\n") % count)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_get_server_certificate(self):
 | 
					    def test_get_server_certificate(self):
 | 
				
			||||||
 | 
					        for prot in (ssl.PROTOCOL_DTLSv1, ssl.PROTOCOL_DTLSv1_2, ssl.PROTOCOL_DTLS):
 | 
				
			||||||
            with test_support.transient_internet() as remote:
 | 
					            with test_support.transient_internet() as remote:
 | 
				
			||||||
            pem = ssl.get_server_certificate(remote, ssl.PROTOCOL_DTLSv1)
 | 
					                pem = ssl.get_server_certificate(remote,
 | 
				
			||||||
 | 
					                                                 prot)
 | 
				
			||||||
                if not pem:
 | 
					                if not pem:
 | 
				
			||||||
                    self.fail("No server certificate!")
 | 
					                    self.fail("No server certificate!")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                try:
 | 
					                try:
 | 
				
			||||||
                    pem = ssl.get_server_certificate(remote,
 | 
					                    pem = ssl.get_server_certificate(remote,
 | 
				
			||||||
                                                 ssl.PROTOCOL_DTLSv1,
 | 
					                                                     prot,
 | 
				
			||||||
                                                     ca_certs=OTHER_CERTFILE)
 | 
					                                                     ca_certs=OTHER_CERTFILE)
 | 
				
			||||||
                except ssl.SSLError:
 | 
					                except ssl.SSLError:
 | 
				
			||||||
                #should fail
 | 
					                    # should fail
 | 
				
			||||||
                    pass
 | 
					                    pass
 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    self.fail("Got server certificate %s!" % pem)
 | 
					                    self.fail("Got server certificate %s!" % pem)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                pem = ssl.get_server_certificate(remote,
 | 
					                pem = ssl.get_server_certificate(remote,
 | 
				
			||||||
                                             ssl.PROTOCOL_DTLSv1,
 | 
					                                                 prot,
 | 
				
			||||||
                                                 ca_certs=ISSUER_CERTFILE)
 | 
					                                                 ca_certs=ISSUER_CERTFILE)
 | 
				
			||||||
                if not pem:
 | 
					                if not pem:
 | 
				
			||||||
                    self.fail("No server certificate!")
 | 
					                    self.fail("No server certificate!")
 | 
				
			||||||
@ -534,6 +538,8 @@ class ThreadedEchoServer(threading.Thread):
 | 
				
			|||||||
                    handler.start()
 | 
					                    handler.start()
 | 
				
			||||||
            except socket.timeout:
 | 
					            except socket.timeout:
 | 
				
			||||||
                pass
 | 
					                pass
 | 
				
			||||||
 | 
					            except ssl.SSLError:
 | 
				
			||||||
 | 
					                pass
 | 
				
			||||||
            except KeyboardInterrupt:
 | 
					            except KeyboardInterrupt:
 | 
				
			||||||
                self.stop()
 | 
					                self.stop()
 | 
				
			||||||
        self.sock.close()
 | 
					        self.sock.close()
 | 
				
			||||||
@ -1039,11 +1045,34 @@ class ThreadedTests(unittest.TestCase):
 | 
				
			|||||||
        """Connecting to a DTLSv1 server with various client options"""
 | 
					        """Connecting to a DTLSv1 server with various client options"""
 | 
				
			||||||
        if test_support.verbose:
 | 
					        if test_support.verbose:
 | 
				
			||||||
            sys.stdout.write("\n")
 | 
					            sys.stdout.write("\n")
 | 
				
			||||||
 | 
					        # server: 1.0 - client: 1.0 -> ok
 | 
				
			||||||
        try_protocol_combo(ssl.PROTOCOL_DTLSv1, ssl.PROTOCOL_DTLSv1, True)
 | 
					        try_protocol_combo(ssl.PROTOCOL_DTLSv1, ssl.PROTOCOL_DTLSv1, True)
 | 
				
			||||||
        try_protocol_combo(ssl.PROTOCOL_DTLSv1, ssl.PROTOCOL_DTLSv1, True,
 | 
					        try_protocol_combo(ssl.PROTOCOL_DTLSv1, ssl.PROTOCOL_DTLSv1, True,
 | 
				
			||||||
                           ssl.CERT_OPTIONAL)
 | 
					                           ssl.CERT_OPTIONAL)
 | 
				
			||||||
        try_protocol_combo(ssl.PROTOCOL_DTLSv1, ssl.PROTOCOL_DTLSv1, True,
 | 
					        try_protocol_combo(ssl.PROTOCOL_DTLSv1, ssl.PROTOCOL_DTLSv1, True,
 | 
				
			||||||
                           ssl.CERT_REQUIRED)
 | 
					                           ssl.CERT_REQUIRED)
 | 
				
			||||||
 | 
					        # server: any - client: 1.0 and 1.2(any) -> ok
 | 
				
			||||||
 | 
					        try_protocol_combo(ssl.PROTOCOL_DTLS, ssl.PROTOCOL_DTLSv1, True)
 | 
				
			||||||
 | 
					        try_protocol_combo(ssl.PROTOCOL_DTLS, ssl.PROTOCOL_DTLSv1, True,
 | 
				
			||||||
 | 
					                           ssl.CERT_REQUIRED)
 | 
				
			||||||
 | 
					        try_protocol_combo(ssl.PROTOCOL_DTLS, ssl.PROTOCOL_DTLSv1_2, True)
 | 
				
			||||||
 | 
					        try_protocol_combo(ssl.PROTOCOL_DTLS, ssl.PROTOCOL_DTLSv1_2, True,
 | 
				
			||||||
 | 
					                           ssl.CERT_REQUIRED)
 | 
				
			||||||
 | 
					        try_protocol_combo(ssl.PROTOCOL_DTLS, ssl.PROTOCOL_DTLS, True)
 | 
				
			||||||
 | 
					        try_protocol_combo(ssl.PROTOCOL_DTLS, ssl.PROTOCOL_DTLS, True,
 | 
				
			||||||
 | 
					                           ssl.CERT_REQUIRED)
 | 
				
			||||||
 | 
					        # server: 1.0 - client: 1.2 -> fail
 | 
				
			||||||
 | 
					        try_protocol_combo(ssl.PROTOCOL_DTLSv1, ssl.PROTOCOL_DTLSv1_2, False)
 | 
				
			||||||
 | 
					        try_protocol_combo(ssl.PROTOCOL_DTLSv1, ssl.PROTOCOL_DTLSv1_2, False,
 | 
				
			||||||
 | 
					                           ssl.CERT_REQUIRED)
 | 
				
			||||||
 | 
					        # server: 1.2 - client: 1.0 -> fail
 | 
				
			||||||
 | 
					        try_protocol_combo(ssl.PROTOCOL_DTLSv1_2, ssl.PROTOCOL_DTLSv1, False)
 | 
				
			||||||
 | 
					        try_protocol_combo(ssl.PROTOCOL_DTLSv1_2, ssl.PROTOCOL_DTLSv1, False,
 | 
				
			||||||
 | 
					                           ssl.CERT_REQUIRED)
 | 
				
			||||||
 | 
					        # server: 1.2 - client: 1.2 -> ok
 | 
				
			||||||
 | 
					        try_protocol_combo(ssl.PROTOCOL_DTLSv1_2, ssl.PROTOCOL_DTLSv1_2, True)
 | 
				
			||||||
 | 
					        try_protocol_combo(ssl.PROTOCOL_DTLSv1_2, ssl.PROTOCOL_DTLSv1_2, True,
 | 
				
			||||||
 | 
					                           ssl.CERT_REQUIRED)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_starttls(self):
 | 
					    def test_starttls(self):
 | 
				
			||||||
        """Switching from clear text to encrypted and back again."""
 | 
					        """Switching from clear text to encrypted and back again."""
 | 
				
			||||||
@ -1062,7 +1091,7 @@ class ThreadedTests(unittest.TestCase):
 | 
				
			|||||||
        # try to connect
 | 
					        # try to connect
 | 
				
			||||||
        wrapped = False
 | 
					        wrapped = False
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            s = ssl.wrap_socket(socket.socket(AF_INET4_6, socket.SOCK_DGRAM))
 | 
					            s = ssl.wrap_socket(socket.socket(AF_INET4_6, socket.SOCK_DGRAM), ssl_version=ssl.PROTOCOL_DTLSv1)
 | 
				
			||||||
            s.connect((HOST, server.port))
 | 
					            s.connect((HOST, server.port))
 | 
				
			||||||
            s = s.unwrap()
 | 
					            s = s.unwrap()
 | 
				
			||||||
            if test_support.verbose:
 | 
					            if test_support.verbose:
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										648
									
								
								dtls/test/unit_wrapper.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										648
									
								
								dtls/test/unit_wrapper.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,648 @@
 | 
				
			|||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Test the support for DTLS through the SSL module. Adapted from the Python
 | 
				
			||||||
 | 
					# standard library's test_ssl.py regression test module by Björn Freise.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import unittest
 | 
				
			||||||
 | 
					import threading
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					import socket
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					import pprint
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from logging import basicConfig, DEBUG, getLogger
 | 
				
			||||||
 | 
					# basicConfig(level=DEBUG, format="%(asctime)s - %(threadName)-10s - %(name)s - %(levelname)s - %(message)s")
 | 
				
			||||||
 | 
					_logger = getLogger(__name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import ssl
 | 
				
			||||||
 | 
					from dtls.wrapper import DtlsSocket
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					HOST = "localhost"
 | 
				
			||||||
 | 
					CHATTY = True
 | 
				
			||||||
 | 
					CHATTY_CLIENT = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ThreadedEchoServer(threading.Thread):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, certificate, ssl_version=None, certreqs=None, cacerts=None,
 | 
				
			||||||
 | 
					                 ciphers=None, curves=None, sigalgs=None,
 | 
				
			||||||
 | 
					                 mtu=None, server_key_exchange_curve=None, server_cert_options=None,
 | 
				
			||||||
 | 
					                 chatty=True):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ssl_version is None:
 | 
				
			||||||
 | 
					            ssl_version = ssl.PROTOCOL_DTLSv1
 | 
				
			||||||
 | 
					        if certreqs is None:
 | 
				
			||||||
 | 
					            certreqs = ssl.CERT_NONE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.certificate = certificate
 | 
				
			||||||
 | 
					        self.protocol = ssl_version
 | 
				
			||||||
 | 
					        self.certreqs = certreqs
 | 
				
			||||||
 | 
					        self.cacerts = cacerts
 | 
				
			||||||
 | 
					        self.ciphers = ciphers
 | 
				
			||||||
 | 
					        self.curves = curves
 | 
				
			||||||
 | 
					        self.sigalgs = sigalgs
 | 
				
			||||||
 | 
					        self.mtu = mtu
 | 
				
			||||||
 | 
					        self.server_key_exchange_curve = server_key_exchange_curve
 | 
				
			||||||
 | 
					        self.server_cert_options = server_cert_options
 | 
				
			||||||
 | 
					        self.chatty = chatty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.flag = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.sock = DtlsSocket(socket.socket(socket.AF_INET, socket.SOCK_DGRAM),
 | 
				
			||||||
 | 
					                               keyfile=self.certificate,
 | 
				
			||||||
 | 
					                               certfile=self.certificate,
 | 
				
			||||||
 | 
					                               server_side=True,
 | 
				
			||||||
 | 
					                               cert_reqs=self.certreqs,
 | 
				
			||||||
 | 
					                               ssl_version=self.protocol,
 | 
				
			||||||
 | 
					                               ca_certs=self.cacerts,
 | 
				
			||||||
 | 
					                               ciphers=self.ciphers,
 | 
				
			||||||
 | 
					                               curves=self.curves,
 | 
				
			||||||
 | 
					                               sigalgs=self.sigalgs,
 | 
				
			||||||
 | 
					                               user_mtu=self.mtu,
 | 
				
			||||||
 | 
					                               server_key_exchange_curve=self.server_key_exchange_curve,
 | 
				
			||||||
 | 
					                               server_cert_options=self.server_cert_options)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if self.chatty:
 | 
				
			||||||
 | 
					            sys.stdout.write(' server:  wrapped server socket as %s\n' % str(self.sock))
 | 
				
			||||||
 | 
					        self.sock.bind((HOST, 0))
 | 
				
			||||||
 | 
					        self.port = self.sock.getsockname()[1]
 | 
				
			||||||
 | 
					        self.active = False
 | 
				
			||||||
 | 
					        threading.Thread.__init__(self)
 | 
				
			||||||
 | 
					        self.daemon = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def start(self, flag=None):
 | 
				
			||||||
 | 
					        self.flag = flag
 | 
				
			||||||
 | 
					        self.starter = threading.current_thread().ident
 | 
				
			||||||
 | 
					        threading.Thread.start(self)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def run(self):
 | 
				
			||||||
 | 
					        self.sock.settimeout(0.05)
 | 
				
			||||||
 | 
					        self.sock.listen(0)
 | 
				
			||||||
 | 
					        self.active = True
 | 
				
			||||||
 | 
					        if self.flag:
 | 
				
			||||||
 | 
					            # signal an event
 | 
				
			||||||
 | 
					            self.flag.set()
 | 
				
			||||||
 | 
					        while self.active:
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                acc_ret = self.sock.recvfrom(4096)
 | 
				
			||||||
 | 
					                if acc_ret:
 | 
				
			||||||
 | 
					                    newdata, connaddr = acc_ret
 | 
				
			||||||
 | 
					                    if self.chatty:
 | 
				
			||||||
 | 
					                        sys.stdout.write(' server:  new data from ' + str(connaddr) + '\n')
 | 
				
			||||||
 | 
					                    self.sock.sendto(newdata.lower(), connaddr)
 | 
				
			||||||
 | 
					            except socket.timeout:
 | 
				
			||||||
 | 
					                pass
 | 
				
			||||||
 | 
					            except KeyboardInterrupt:
 | 
				
			||||||
 | 
					                self.stop()
 | 
				
			||||||
 | 
					            except Exception as e:
 | 
				
			||||||
 | 
					                if self.chatty:
 | 
				
			||||||
 | 
					                    sys.stdout.write(' server:  error ' + str(e) + '\n')
 | 
				
			||||||
 | 
					                pass
 | 
				
			||||||
 | 
					        if self.chatty:
 | 
				
			||||||
 | 
					            sys.stdout.write(' server:  closing socket as %s\n' % str(self.sock))
 | 
				
			||||||
 | 
					        self.sock.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def stop(self):
 | 
				
			||||||
 | 
					        self.active = False
 | 
				
			||||||
 | 
					        if self.starter != threading.current_thread().ident:
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					        self.join()  # don't allow spawning new handlers after we've checked
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir, "certs", "keycert.pem")
 | 
				
			||||||
 | 
					CERTFILE_EC = os.path.join(os.path.dirname(__file__) or os.curdir, "certs", "keycert_ec.pem")
 | 
				
			||||||
 | 
					ISSUER_CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir, "certs", "ca-cert.pem")
 | 
				
			||||||
 | 
					ISSUER_CERTFILE_EC = os.path.join(os.path.dirname(__file__) or os.curdir, "certs", "ca-cert_ec.pem")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# certfile, protocol, certreqs, cacertsfile,
 | 
				
			||||||
 | 
					# ciphers=None, curves=None, sigalgs=None,
 | 
				
			||||||
 | 
					tests = [
 | 
				
			||||||
 | 
					    {'testcase':
 | 
				
			||||||
 | 
					        {'name': 'standard dtls v1',
 | 
				
			||||||
 | 
					         'desc': 'Standard DTLS v1 test with out-of-the box configuration and RSA certificate',
 | 
				
			||||||
 | 
					         'start_server': True},
 | 
				
			||||||
 | 
					     'input':
 | 
				
			||||||
 | 
					        {'certfile': CERTFILE,
 | 
				
			||||||
 | 
					         'protocol': ssl.PROTOCOL_DTLSv1,
 | 
				
			||||||
 | 
					         'certreqs': None,
 | 
				
			||||||
 | 
					         'cacertsfile': ISSUER_CERTFILE,
 | 
				
			||||||
 | 
					         'ciphers': None,
 | 
				
			||||||
 | 
					         'curves': None,
 | 
				
			||||||
 | 
					         'sigalgs': None,
 | 
				
			||||||
 | 
					         'client_certfile': None,
 | 
				
			||||||
 | 
					         'client_protocol': ssl.PROTOCOL_DTLSv1,
 | 
				
			||||||
 | 
					         'client_certreqs': ssl.CERT_REQUIRED,
 | 
				
			||||||
 | 
					         'client_cacertsfile': ISSUER_CERTFILE,
 | 
				
			||||||
 | 
					         'client_ciphers': None,
 | 
				
			||||||
 | 
					         'client_curves': None,
 | 
				
			||||||
 | 
					         'client_sigalgs': None},
 | 
				
			||||||
 | 
					     'result':
 | 
				
			||||||
 | 
					         {'ret_success': True,
 | 
				
			||||||
 | 
					          'error_code': None,
 | 
				
			||||||
 | 
					          'exception': None}},
 | 
				
			||||||
 | 
					    {'testcase':
 | 
				
			||||||
 | 
					        {'name': 'standard dtls v1_2',
 | 
				
			||||||
 | 
					         'desc': 'Standard DTLS v1_2 test with out-of-the box configuration and ECDSA certificate',
 | 
				
			||||||
 | 
					         'start_server': True},
 | 
				
			||||||
 | 
					     'input':
 | 
				
			||||||
 | 
					        {'certfile': CERTFILE_EC,
 | 
				
			||||||
 | 
					         'protocol': ssl.PROTOCOL_DTLSv1_2,
 | 
				
			||||||
 | 
					         'certreqs': None,
 | 
				
			||||||
 | 
					         'cacertsfile': ISSUER_CERTFILE_EC,
 | 
				
			||||||
 | 
					         'ciphers': None,
 | 
				
			||||||
 | 
					         'curves': None,
 | 
				
			||||||
 | 
					         'sigalgs': None,
 | 
				
			||||||
 | 
					         'client_certfile': None,
 | 
				
			||||||
 | 
					         'client_protocol': ssl.PROTOCOL_DTLSv1_2,
 | 
				
			||||||
 | 
					         'client_certreqs': ssl.CERT_REQUIRED,
 | 
				
			||||||
 | 
					         'client_cacertsfile': ISSUER_CERTFILE_EC,
 | 
				
			||||||
 | 
					         'client_ciphers': None,
 | 
				
			||||||
 | 
					         'client_curves': None,
 | 
				
			||||||
 | 
					         'client_sigalgs': None},
 | 
				
			||||||
 | 
					     'result':
 | 
				
			||||||
 | 
					         {'ret_success': True,
 | 
				
			||||||
 | 
					          'error_code': None,
 | 
				
			||||||
 | 
					          'exception': None}},
 | 
				
			||||||
 | 
					    {'testcase':
 | 
				
			||||||
 | 
					        {'name': 'protocol version mismatch',
 | 
				
			||||||
 | 
					         'desc': 'Client and server have different protocol versions',
 | 
				
			||||||
 | 
					         'start_server': True},
 | 
				
			||||||
 | 
					     'input':
 | 
				
			||||||
 | 
					         {'certfile': CERTFILE,
 | 
				
			||||||
 | 
					          'protocol': ssl.PROTOCOL_DTLSv1,
 | 
				
			||||||
 | 
					          'certreqs': None,
 | 
				
			||||||
 | 
					          'cacertsfile': ISSUER_CERTFILE,
 | 
				
			||||||
 | 
					          'ciphers': None,
 | 
				
			||||||
 | 
					          'curves': None,
 | 
				
			||||||
 | 
					          'sigalgs': None,
 | 
				
			||||||
 | 
					          'client_certfile': None,
 | 
				
			||||||
 | 
					          'client_protocol': ssl.PROTOCOL_DTLSv1_2,
 | 
				
			||||||
 | 
					          'client_certreqs': ssl.CERT_REQUIRED,
 | 
				
			||||||
 | 
					          'client_cacertsfile': ISSUER_CERTFILE,
 | 
				
			||||||
 | 
					          'client_ciphers': None,
 | 
				
			||||||
 | 
					          'client_curves': None,
 | 
				
			||||||
 | 
					          'client_sigalgs': None},
 | 
				
			||||||
 | 
					     'result':
 | 
				
			||||||
 | 
					         {'ret_success': False,
 | 
				
			||||||
 | 
					          'error_code': ssl.ERR_WRONG_SSL_VERSION,
 | 
				
			||||||
 | 
					          'exception': None}},
 | 
				
			||||||
 | 
					    {'testcase':
 | 
				
			||||||
 | 
					        {'name': 'certificate verify fails',
 | 
				
			||||||
 | 
					         'desc': 'Server certificate cannot be verified by client',
 | 
				
			||||||
 | 
					         'start_server': True},
 | 
				
			||||||
 | 
					     'input':
 | 
				
			||||||
 | 
					         {'certfile': CERTFILE_EC,
 | 
				
			||||||
 | 
					          'protocol': ssl.PROTOCOL_DTLSv1_2,
 | 
				
			||||||
 | 
					          'certreqs': None,
 | 
				
			||||||
 | 
					          'cacertsfile': ISSUER_CERTFILE_EC,
 | 
				
			||||||
 | 
					          'ciphers': None,
 | 
				
			||||||
 | 
					          'curves': None,
 | 
				
			||||||
 | 
					          'sigalgs': None,
 | 
				
			||||||
 | 
					          'client_certfile': None,
 | 
				
			||||||
 | 
					          'client_protocol': ssl.PROTOCOL_DTLSv1_2,
 | 
				
			||||||
 | 
					          'client_certreqs': ssl.CERT_REQUIRED,
 | 
				
			||||||
 | 
					          'client_cacertsfile': ISSUER_CERTFILE,
 | 
				
			||||||
 | 
					          'client_ciphers': None,
 | 
				
			||||||
 | 
					          'client_curves': None,
 | 
				
			||||||
 | 
					          'client_sigalgs': None},
 | 
				
			||||||
 | 
					     'result':
 | 
				
			||||||
 | 
					         {'ret_success': False,
 | 
				
			||||||
 | 
					          'error_code': ssl.ERR_CERTIFICATE_VERIFY_FAILED,
 | 
				
			||||||
 | 
					          'exception': None}},
 | 
				
			||||||
 | 
					    {'testcase':
 | 
				
			||||||
 | 
					        {'name': 'no matching curve',
 | 
				
			||||||
 | 
					         'desc': 'Client doesn\'t support curve used by server ECDSA certificate',
 | 
				
			||||||
 | 
					         'start_server': True},
 | 
				
			||||||
 | 
					     'input':
 | 
				
			||||||
 | 
					         {'certfile': CERTFILE_EC,
 | 
				
			||||||
 | 
					          'protocol': ssl.PROTOCOL_DTLSv1_2,
 | 
				
			||||||
 | 
					          'certreqs': None,
 | 
				
			||||||
 | 
					          'cacertsfile': ISSUER_CERTFILE_EC,
 | 
				
			||||||
 | 
					          'ciphers': None,
 | 
				
			||||||
 | 
					          'curves': None,
 | 
				
			||||||
 | 
					          'sigalgs': None,
 | 
				
			||||||
 | 
					          'client_certfile': None,
 | 
				
			||||||
 | 
					          'client_protocol': ssl.PROTOCOL_DTLSv1_2,
 | 
				
			||||||
 | 
					          'client_certreqs': ssl.CERT_REQUIRED,
 | 
				
			||||||
 | 
					          'client_cacertsfile': ISSUER_CERTFILE_EC,
 | 
				
			||||||
 | 
					          'client_ciphers': None,
 | 
				
			||||||
 | 
					          'client_curves': 'secp384r1',
 | 
				
			||||||
 | 
					          'client_sigalgs': None},
 | 
				
			||||||
 | 
					     'result':
 | 
				
			||||||
 | 
					         {'ret_success': False,
 | 
				
			||||||
 | 
					          'error_code': ssl.ERR_SSL_HANDSHAKE_FAILURE,
 | 
				
			||||||
 | 
					          'exception': None}},
 | 
				
			||||||
 | 
					    {'testcase':
 | 
				
			||||||
 | 
					         {'name': 'matching curve',
 | 
				
			||||||
 | 
					          'desc': '',
 | 
				
			||||||
 | 
					          'start_server': True},
 | 
				
			||||||
 | 
					     'input':
 | 
				
			||||||
 | 
					         {'certfile': CERTFILE_EC,
 | 
				
			||||||
 | 
					          'protocol': ssl.PROTOCOL_DTLSv1_2,
 | 
				
			||||||
 | 
					          'certreqs': None,
 | 
				
			||||||
 | 
					          'cacertsfile': ISSUER_CERTFILE_EC,
 | 
				
			||||||
 | 
					          'ciphers': None,
 | 
				
			||||||
 | 
					          'curves': None,
 | 
				
			||||||
 | 
					          'sigalgs': None,
 | 
				
			||||||
 | 
					          'client_certfile': None,
 | 
				
			||||||
 | 
					          'client_protocol': ssl.PROTOCOL_DTLSv1_2,
 | 
				
			||||||
 | 
					          'client_certreqs': ssl.CERT_REQUIRED,
 | 
				
			||||||
 | 
					          'client_cacertsfile': ISSUER_CERTFILE_EC,
 | 
				
			||||||
 | 
					          'client_ciphers': None,
 | 
				
			||||||
 | 
					          'client_curves': 'prime256v1',
 | 
				
			||||||
 | 
					          'client_sigalgs': None},
 | 
				
			||||||
 | 
					     'result':
 | 
				
			||||||
 | 
					         {'ret_success': True,
 | 
				
			||||||
 | 
					          'error_code': None,
 | 
				
			||||||
 | 
					          'exception': None}},
 | 
				
			||||||
 | 
					    {'testcase':
 | 
				
			||||||
 | 
					        {'name': 'no host',
 | 
				
			||||||
 | 
					         'desc': 'No server port is listening',
 | 
				
			||||||
 | 
					         'start_server': False},
 | 
				
			||||||
 | 
					     'input':
 | 
				
			||||||
 | 
					         {'certfile': CERTFILE_EC,
 | 
				
			||||||
 | 
					          'protocol': ssl.PROTOCOL_DTLSv1_2,
 | 
				
			||||||
 | 
					          'certreqs': None,
 | 
				
			||||||
 | 
					          'cacertsfile': ISSUER_CERTFILE_EC,
 | 
				
			||||||
 | 
					          'ciphers': None,
 | 
				
			||||||
 | 
					          'curves': None,
 | 
				
			||||||
 | 
					          'sigalgs': None,
 | 
				
			||||||
 | 
					          'client_certfile': None,
 | 
				
			||||||
 | 
					          'client_protocol': ssl.PROTOCOL_DTLSv1_2,
 | 
				
			||||||
 | 
					          'client_certreqs': ssl.CERT_REQUIRED,
 | 
				
			||||||
 | 
					          'client_cacertsfile': ISSUER_CERTFILE_EC,
 | 
				
			||||||
 | 
					          'client_ciphers': None,
 | 
				
			||||||
 | 
					          'client_curves': None,
 | 
				
			||||||
 | 
					          'client_sigalgs': None},
 | 
				
			||||||
 | 
					     'result':
 | 
				
			||||||
 | 
					         {'ret_success': False,
 | 
				
			||||||
 | 
					          'error_code': ssl.ERR_PORT_UNREACHABLE,
 | 
				
			||||||
 | 
					          'exception': None}},
 | 
				
			||||||
 | 
					    {'testcase':
 | 
				
			||||||
 | 
					        {'name': 'no matching sigalgs',
 | 
				
			||||||
 | 
					         'desc': '',
 | 
				
			||||||
 | 
					         'start_server': True},
 | 
				
			||||||
 | 
					     'input':
 | 
				
			||||||
 | 
					         {'certfile': CERTFILE_EC,
 | 
				
			||||||
 | 
					          'protocol': ssl.PROTOCOL_DTLSv1_2,
 | 
				
			||||||
 | 
					          'certreqs': None,
 | 
				
			||||||
 | 
					          'cacertsfile': ISSUER_CERTFILE_EC,
 | 
				
			||||||
 | 
					          'ciphers': None,
 | 
				
			||||||
 | 
					          'curves': None,
 | 
				
			||||||
 | 
					          'sigalgs': None,
 | 
				
			||||||
 | 
					          'client_certfile': None,
 | 
				
			||||||
 | 
					          'client_protocol': ssl.PROTOCOL_DTLSv1_2,
 | 
				
			||||||
 | 
					          'client_certreqs': ssl.CERT_REQUIRED,
 | 
				
			||||||
 | 
					          'client_cacertsfile': ISSUER_CERTFILE_EC,
 | 
				
			||||||
 | 
					          'client_ciphers': None,
 | 
				
			||||||
 | 
					          'client_curves': None,
 | 
				
			||||||
 | 
					          'client_sigalgs': "RSA+SHA256"},
 | 
				
			||||||
 | 
					     'result':
 | 
				
			||||||
 | 
					         {'ret_success': False,
 | 
				
			||||||
 | 
					          'error_code': ssl.ERR_SSL_HANDSHAKE_FAILURE,
 | 
				
			||||||
 | 
					          'exception': None}},
 | 
				
			||||||
 | 
					    {'testcase':
 | 
				
			||||||
 | 
					        {'name': 'matching sigalgs',
 | 
				
			||||||
 | 
					         'desc': '',
 | 
				
			||||||
 | 
					         'start_server': True},
 | 
				
			||||||
 | 
					     'input':
 | 
				
			||||||
 | 
					         {'certfile': CERTFILE_EC,
 | 
				
			||||||
 | 
					          'protocol': ssl.PROTOCOL_DTLSv1_2,
 | 
				
			||||||
 | 
					          'certreqs': None,
 | 
				
			||||||
 | 
					          'cacertsfile': ISSUER_CERTFILE_EC,
 | 
				
			||||||
 | 
					          'ciphers': None,
 | 
				
			||||||
 | 
					          'curves': None,
 | 
				
			||||||
 | 
					          'sigalgs': None,
 | 
				
			||||||
 | 
					          'client_certfile': None,
 | 
				
			||||||
 | 
					          'client_protocol': ssl.PROTOCOL_DTLSv1_2,
 | 
				
			||||||
 | 
					          'client_certreqs': ssl.CERT_REQUIRED,
 | 
				
			||||||
 | 
					          'client_cacertsfile': ISSUER_CERTFILE_EC,
 | 
				
			||||||
 | 
					          'client_ciphers': None,
 | 
				
			||||||
 | 
					          'client_curves': None,
 | 
				
			||||||
 | 
					          'client_sigalgs': "ECDSA+SHA256"},
 | 
				
			||||||
 | 
					     'result':
 | 
				
			||||||
 | 
					         {'ret_success': True,
 | 
				
			||||||
 | 
					          'error_code': None,
 | 
				
			||||||
 | 
					          'exception': None}},
 | 
				
			||||||
 | 
					    {'testcase':
 | 
				
			||||||
 | 
					        {'name': 'no matching cipher',
 | 
				
			||||||
 | 
					         'desc': 'Server using a ECDSA certificate while client is only able to use RSA encryption',
 | 
				
			||||||
 | 
					         'start_server': True},
 | 
				
			||||||
 | 
					     'input':
 | 
				
			||||||
 | 
					         {'certfile': CERTFILE_EC,
 | 
				
			||||||
 | 
					          'protocol': ssl.PROTOCOL_DTLSv1_2,
 | 
				
			||||||
 | 
					          'certreqs': None,
 | 
				
			||||||
 | 
					          'cacertsfile': ISSUER_CERTFILE_EC,
 | 
				
			||||||
 | 
					          'ciphers': None,
 | 
				
			||||||
 | 
					          'curves': None,
 | 
				
			||||||
 | 
					          'sigalgs': None,
 | 
				
			||||||
 | 
					          'client_certfile': None,
 | 
				
			||||||
 | 
					          'client_protocol': ssl.PROTOCOL_DTLSv1_2,
 | 
				
			||||||
 | 
					          'client_certreqs': ssl.CERT_REQUIRED,
 | 
				
			||||||
 | 
					          'client_cacertsfile': ISSUER_CERTFILE_EC,
 | 
				
			||||||
 | 
					          'client_ciphers': "AES256-SHA",
 | 
				
			||||||
 | 
					          'client_curves': None,
 | 
				
			||||||
 | 
					          'client_sigalgs': None},
 | 
				
			||||||
 | 
					     'result':
 | 
				
			||||||
 | 
					         {'ret_success': False,
 | 
				
			||||||
 | 
					          'error_code': ssl.ERR_SSL_HANDSHAKE_FAILURE,
 | 
				
			||||||
 | 
					          'exception': None}},
 | 
				
			||||||
 | 
					    {'testcase':
 | 
				
			||||||
 | 
					        {'name': 'matching cipher',
 | 
				
			||||||
 | 
					         'desc': '',
 | 
				
			||||||
 | 
					         'start_server': True},
 | 
				
			||||||
 | 
					     'input':
 | 
				
			||||||
 | 
					         {'certfile': CERTFILE_EC,
 | 
				
			||||||
 | 
					          'protocol': ssl.PROTOCOL_DTLSv1_2,
 | 
				
			||||||
 | 
					          'certreqs': None,
 | 
				
			||||||
 | 
					          'cacertsfile': ISSUER_CERTFILE_EC,
 | 
				
			||||||
 | 
					          'ciphers': None,
 | 
				
			||||||
 | 
					          'curves': None,
 | 
				
			||||||
 | 
					          'sigalgs': None,
 | 
				
			||||||
 | 
					          'client_certfile': None,
 | 
				
			||||||
 | 
					          'client_protocol': ssl.PROTOCOL_DTLSv1_2,
 | 
				
			||||||
 | 
					          'client_certreqs': ssl.CERT_REQUIRED,
 | 
				
			||||||
 | 
					          'client_cacertsfile': ISSUER_CERTFILE_EC,
 | 
				
			||||||
 | 
					          'client_ciphers': "ECDHE-ECDSA-AES256-SHA",
 | 
				
			||||||
 | 
					          'client_curves': None,
 | 
				
			||||||
 | 
					          'client_sigalgs': None},
 | 
				
			||||||
 | 
					     'result':
 | 
				
			||||||
 | 
					         {'ret_success': True,
 | 
				
			||||||
 | 
					          'error_code': None,
 | 
				
			||||||
 | 
					          'exception': None}},
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def params_test(start_server, certfile, protocol, certreqs, cacertsfile,
 | 
				
			||||||
 | 
					                client_certfile=None, client_protocol=None, client_certreqs=None, client_cacertsfile=None,
 | 
				
			||||||
 | 
					                ciphers=None, curves=None, sigalgs=None,
 | 
				
			||||||
 | 
					                client_ciphers=None, client_curves=None, client_sigalgs=None,
 | 
				
			||||||
 | 
					                mtu=None, server_key_exchange_curve=None, server_cert_options=None,
 | 
				
			||||||
 | 
					                indata="FOO\n", chatty=False, connectionchatty=False):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Launch a server, connect a client to it and try various reads
 | 
				
			||||||
 | 
					    and writes.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    server = ThreadedEchoServer(certfile,
 | 
				
			||||||
 | 
					                                ssl_version=protocol,
 | 
				
			||||||
 | 
					                                certreqs=certreqs,
 | 
				
			||||||
 | 
					                                cacerts=cacertsfile,
 | 
				
			||||||
 | 
					                                ciphers=ciphers,
 | 
				
			||||||
 | 
					                                curves=curves,
 | 
				
			||||||
 | 
					                                sigalgs=sigalgs,
 | 
				
			||||||
 | 
					                                mtu=mtu,
 | 
				
			||||||
 | 
					                                server_key_exchange_curve=server_key_exchange_curve,
 | 
				
			||||||
 | 
					                                server_cert_options=server_cert_options,
 | 
				
			||||||
 | 
					                                chatty=chatty)
 | 
				
			||||||
 | 
					    # should we really run the server?
 | 
				
			||||||
 | 
					    if start_server:
 | 
				
			||||||
 | 
					        flag = threading.Event()
 | 
				
			||||||
 | 
					        server.start(flag)
 | 
				
			||||||
 | 
					        # wait for it to start
 | 
				
			||||||
 | 
					        flag.wait()
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        server.sock.close()
 | 
				
			||||||
 | 
					    # try to connect
 | 
				
			||||||
 | 
					    if client_protocol is None:
 | 
				
			||||||
 | 
					        client_protocol = protocol
 | 
				
			||||||
 | 
					    if client_ciphers is None:
 | 
				
			||||||
 | 
					        client_ciphers = ciphers
 | 
				
			||||||
 | 
					    if client_curves is None:
 | 
				
			||||||
 | 
					        client_curves = curves
 | 
				
			||||||
 | 
					    if client_sigalgs is None:
 | 
				
			||||||
 | 
					        client_sigalgs = sigalgs
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        s = DtlsSocket(socket.socket(socket.AF_INET, socket.SOCK_DGRAM),
 | 
				
			||||||
 | 
					                       keyfile=client_certfile,
 | 
				
			||||||
 | 
					                       certfile=client_certfile,
 | 
				
			||||||
 | 
					                       cert_reqs=client_certreqs,
 | 
				
			||||||
 | 
					                       ssl_version=client_protocol,
 | 
				
			||||||
 | 
					                       ca_certs=client_cacertsfile,
 | 
				
			||||||
 | 
					                       ciphers=client_ciphers,
 | 
				
			||||||
 | 
					                       curves=client_curves,
 | 
				
			||||||
 | 
					                       sigalgs=client_sigalgs,
 | 
				
			||||||
 | 
					                       user_mtu=mtu)
 | 
				
			||||||
 | 
					        s.connect((HOST, server.port))
 | 
				
			||||||
 | 
					        if connectionchatty:
 | 
				
			||||||
 | 
					            sys.stdout.write(" client:  sending %s...\n" % (repr(indata)))
 | 
				
			||||||
 | 
					        s.write(indata)
 | 
				
			||||||
 | 
					        outdata = s.read()
 | 
				
			||||||
 | 
					        if connectionchatty:
 | 
				
			||||||
 | 
					            sys.stdout.write(" client:  read %s\n" % repr(outdata))
 | 
				
			||||||
 | 
					        if outdata != indata.lower():
 | 
				
			||||||
 | 
					            raise AssertionError("bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
 | 
				
			||||||
 | 
					                                 % (outdata[:min(len(outdata), 20)], len(outdata),
 | 
				
			||||||
 | 
					                                    indata[:min(len(indata), 20)].lower(), len(indata)))
 | 
				
			||||||
 | 
					        cert = s.getpeercert()
 | 
				
			||||||
 | 
					        cipher = s.cipher()
 | 
				
			||||||
 | 
					        if connectionchatty:
 | 
				
			||||||
 | 
					            sys.stdout.write("cert:\n" + pprint.pformat(cert) + "\n")
 | 
				
			||||||
 | 
					            sys.stdout.write("cipher:\n" + pprint.pformat(cipher) + "\n")
 | 
				
			||||||
 | 
					        if connectionchatty:
 | 
				
			||||||
 | 
					            sys.stdout.write(" client:  closing connection.\n")
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            s.close()
 | 
				
			||||||
 | 
					        except Exception as e:
 | 
				
			||||||
 | 
					            if connectionchatty:
 | 
				
			||||||
 | 
					                sys.stdout.write(" client:  error closing connection %s...\n" % (repr(e)))
 | 
				
			||||||
 | 
					            pass
 | 
				
			||||||
 | 
					    except Exception as e:
 | 
				
			||||||
 | 
					        if connectionchatty:
 | 
				
			||||||
 | 
					            sys.stdout.write(" client:  aborting with exception %s...\n" % (repr(e)))
 | 
				
			||||||
 | 
					        return False, e
 | 
				
			||||||
 | 
					    finally:
 | 
				
			||||||
 | 
					        if start_server:
 | 
				
			||||||
 | 
					            server.stop()
 | 
				
			||||||
 | 
					    return True, None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TestSequenceMeta(type):
 | 
				
			||||||
 | 
					    def __new__(mcs, name, bases, dict):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        def gen_test(_case, _input, _result):
 | 
				
			||||||
 | 
					            def test(self):
 | 
				
			||||||
 | 
					                try:
 | 
				
			||||||
 | 
					                    if CHATTY or CHATTY_CLIENT:
 | 
				
			||||||
 | 
					                        sys.stdout.write("\nTestcase: %s\n" % _case['name'])
 | 
				
			||||||
 | 
					                    ret, e = params_test(_case['start_server'], chatty=CHATTY, connectionchatty=CHATTY_CLIENT, **_input)
 | 
				
			||||||
 | 
					                    if _result['ret_success']:
 | 
				
			||||||
 | 
					                        self.assertEqual(ret, _result['ret_success'])
 | 
				
			||||||
 | 
					                    else:
 | 
				
			||||||
 | 
					                        try:
 | 
				
			||||||
 | 
					                            last_error = e.errqueue[-1][0]
 | 
				
			||||||
 | 
					                        except:
 | 
				
			||||||
 | 
					                            try:
 | 
				
			||||||
 | 
					                                last_error = e.errno
 | 
				
			||||||
 | 
					                            except:
 | 
				
			||||||
 | 
					                                last_error = None
 | 
				
			||||||
 | 
					                        self.assertEqual(last_error, _result['error_code'])
 | 
				
			||||||
 | 
					                except Exception as e:
 | 
				
			||||||
 | 
					                    raise
 | 
				
			||||||
 | 
					            return test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for testcase in tests:
 | 
				
			||||||
 | 
					            _case, _input, _result = testcase.itervalues()
 | 
				
			||||||
 | 
					            test_name = "test_%s" % _case['name'].lower().replace(' ', '_')
 | 
				
			||||||
 | 
					            dict[test_name] = gen_test(_case, _input, _result)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return type.__new__(mcs, name, bases, dict)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class WrapperTests(unittest.TestCase):
 | 
				
			||||||
 | 
					    __metaclass__ = TestSequenceMeta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_build_cert_chain(self):
 | 
				
			||||||
 | 
					        steps = [ssl.SSL_BUILD_CHAIN_FLAG_NONE, ssl.SSL_BUILD_CHAIN_FLAG_NO_ROOT]
 | 
				
			||||||
 | 
					        chatty, connectionchatty = CHATTY, CHATTY_CLIENT
 | 
				
			||||||
 | 
					        indata = 'FOO'
 | 
				
			||||||
 | 
					        certs = dict()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if chatty or connectionchatty:
 | 
				
			||||||
 | 
					            sys.stdout.write("\nTestcase: test_build_cert_chain\n")
 | 
				
			||||||
 | 
					        for step in steps:
 | 
				
			||||||
 | 
					            server = ThreadedEchoServer(certificate=CERTFILE,
 | 
				
			||||||
 | 
					                                        ssl_version=ssl.PROTOCOL_DTLSv1_2,
 | 
				
			||||||
 | 
					                                        certreqs=ssl.CERT_NONE,
 | 
				
			||||||
 | 
					                                        cacerts=ISSUER_CERTFILE,
 | 
				
			||||||
 | 
					                                        ciphers=None,
 | 
				
			||||||
 | 
					                                        curves=None,
 | 
				
			||||||
 | 
					                                        sigalgs=None,
 | 
				
			||||||
 | 
					                                        mtu=None,
 | 
				
			||||||
 | 
					                                        server_key_exchange_curve=None,
 | 
				
			||||||
 | 
					                                        server_cert_options=step,
 | 
				
			||||||
 | 
					                                        chatty=chatty)
 | 
				
			||||||
 | 
					            flag = threading.Event()
 | 
				
			||||||
 | 
					            server.start(flag)
 | 
				
			||||||
 | 
					            # wait for it to start
 | 
				
			||||||
 | 
					            flag.wait()
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                s = DtlsSocket(socket.socket(socket.AF_INET, socket.SOCK_DGRAM),
 | 
				
			||||||
 | 
					                               keyfile=None,
 | 
				
			||||||
 | 
					                               certfile=None,
 | 
				
			||||||
 | 
					                               cert_reqs=ssl.CERT_REQUIRED,
 | 
				
			||||||
 | 
					                               ssl_version=ssl.PROTOCOL_DTLSv1_2,
 | 
				
			||||||
 | 
					                               ca_certs=ISSUER_CERTFILE,
 | 
				
			||||||
 | 
					                               ciphers=None,
 | 
				
			||||||
 | 
					                               curves=None,
 | 
				
			||||||
 | 
					                               sigalgs=None,
 | 
				
			||||||
 | 
					                               user_mtu=None)
 | 
				
			||||||
 | 
					                s.connect((HOST, server.port))
 | 
				
			||||||
 | 
					                if connectionchatty:
 | 
				
			||||||
 | 
					                    sys.stdout.write(" client:  sending %s...\n" % (repr(indata)))
 | 
				
			||||||
 | 
					                s.write(indata)
 | 
				
			||||||
 | 
					                outdata = s.read()
 | 
				
			||||||
 | 
					                if connectionchatty:
 | 
				
			||||||
 | 
					                    sys.stdout.write(" client:  read %s\n" % repr(outdata))
 | 
				
			||||||
 | 
					                if outdata != indata.lower():
 | 
				
			||||||
 | 
					                    raise AssertionError("bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
 | 
				
			||||||
 | 
					                                         % (outdata[:min(len(outdata), 20)], len(outdata),
 | 
				
			||||||
 | 
					                                            indata[:min(len(indata), 20)].lower(), len(indata)))
 | 
				
			||||||
 | 
					                # cert = s.getpeercert()
 | 
				
			||||||
 | 
					                # cipher = s.cipher()
 | 
				
			||||||
 | 
					                # if connectionchatty:
 | 
				
			||||||
 | 
					                #     sys.stdout.write("cert:\n" + pprint.pformat(cert) + "\n")
 | 
				
			||||||
 | 
					                #     sys.stdout.write("cipher:\n" + pprint.pformat(cipher) + "\n")
 | 
				
			||||||
 | 
					                certs[step] = s.getpeercertchain()
 | 
				
			||||||
 | 
					                if connectionchatty:
 | 
				
			||||||
 | 
					                    sys.stdout.write(" client:  closing connection.\n")
 | 
				
			||||||
 | 
					                try:
 | 
				
			||||||
 | 
					                    s.close()
 | 
				
			||||||
 | 
					                except Exception as e:
 | 
				
			||||||
 | 
					                    if connectionchatty:
 | 
				
			||||||
 | 
					                        sys.stdout.write(" client:  error closing connection %s...\n" % (repr(e)))
 | 
				
			||||||
 | 
					                    pass
 | 
				
			||||||
 | 
					            except Exception as e:
 | 
				
			||||||
 | 
					                if connectionchatty:
 | 
				
			||||||
 | 
					                    sys.stdout.write(" client:  aborting with exception %s...\n" % (repr(e)))
 | 
				
			||||||
 | 
					                raise
 | 
				
			||||||
 | 
					            finally:
 | 
				
			||||||
 | 
					                server.stop()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if chatty:
 | 
				
			||||||
 | 
					            sys.stdout.write("certs:\n")
 | 
				
			||||||
 | 
					            for step in steps:
 | 
				
			||||||
 | 
					                sys.stdout.write("SSL_CTX_build_cert_chain: %s\n%s\n" % (step, pprint.pformat(certs[step])))
 | 
				
			||||||
 | 
					        self.assertNotEqual(certs[steps[0]], certs[steps[1]])
 | 
				
			||||||
 | 
					        self.assertEqual(len(certs[steps[0]]) - len(certs[steps[1]]), 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_set_ecdh_curve(self):
 | 
				
			||||||
 | 
					        steps = {
 | 
				
			||||||
 | 
					            # server, client, result
 | 
				
			||||||
 | 
					            'all auto':                 (None, None,                            True),      # Auto
 | 
				
			||||||
 | 
					            'client restricted':        (None, "secp256k1:prime256v1",          True),      # client can handle key curve
 | 
				
			||||||
 | 
					            'client too restricted':    (None, "secp256k1",                     False),     # client _cannot_ handle key curve
 | 
				
			||||||
 | 
					            'client minimum':           (None, "prime256v1",                    True),      # client can only handle key curve
 | 
				
			||||||
 | 
					            'server restricted':        ("secp384r1", None,                     True),      # client can handle key curve
 | 
				
			||||||
 | 
					            'server one, client two':   ("secp384r1", "prime256v1:secp384r1",   True),      # client can handle key curve
 | 
				
			||||||
 | 
					            'server one, client one':   ("secp384r1", "secp384r1",              False),     # client _cannot_ handle key curve
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        chatty, connectionchatty = CHATTY, CHATTY_CLIENT
 | 
				
			||||||
 | 
					        indata = 'FOO'
 | 
				
			||||||
 | 
					        certs = dict()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if chatty or connectionchatty:
 | 
				
			||||||
 | 
					            sys.stdout.write("\nTestcase: test_ecdh_curve\n")
 | 
				
			||||||
 | 
					        for step, tmp in steps.iteritems():
 | 
				
			||||||
 | 
					            if chatty or connectionchatty:
 | 
				
			||||||
 | 
					                sys.stdout.write("\n Subcase: %s\n" % step)
 | 
				
			||||||
 | 
					            server_curve, client_curve, result = tmp
 | 
				
			||||||
 | 
					            server = ThreadedEchoServer(certificate=CERTFILE_EC,
 | 
				
			||||||
 | 
					                                        ssl_version=ssl.PROTOCOL_DTLSv1_2,
 | 
				
			||||||
 | 
					                                        certreqs=ssl.CERT_NONE,
 | 
				
			||||||
 | 
					                                        cacerts=ISSUER_CERTFILE_EC,
 | 
				
			||||||
 | 
					                                        ciphers=None,
 | 
				
			||||||
 | 
					                                        curves=None,
 | 
				
			||||||
 | 
					                                        sigalgs=None,
 | 
				
			||||||
 | 
					                                        mtu=None,
 | 
				
			||||||
 | 
					                                        server_key_exchange_curve=server_curve,
 | 
				
			||||||
 | 
					                                        server_cert_options=None,
 | 
				
			||||||
 | 
					                                        chatty=chatty)
 | 
				
			||||||
 | 
					            flag = threading.Event()
 | 
				
			||||||
 | 
					            server.start(flag)
 | 
				
			||||||
 | 
					            # wait for it to start
 | 
				
			||||||
 | 
					            flag.wait()
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                s = DtlsSocket(socket.socket(socket.AF_INET, socket.SOCK_DGRAM),
 | 
				
			||||||
 | 
					                               keyfile=None,
 | 
				
			||||||
 | 
					                               certfile=None,
 | 
				
			||||||
 | 
					                               cert_reqs=ssl.CERT_REQUIRED,
 | 
				
			||||||
 | 
					                               ssl_version=ssl.PROTOCOL_DTLSv1_2,
 | 
				
			||||||
 | 
					                               ca_certs=ISSUER_CERTFILE_EC,
 | 
				
			||||||
 | 
					                               ciphers=None,
 | 
				
			||||||
 | 
					                               curves=client_curve,
 | 
				
			||||||
 | 
					                               sigalgs=None,
 | 
				
			||||||
 | 
					                               user_mtu=None)
 | 
				
			||||||
 | 
					                s.connect((HOST, server.port))
 | 
				
			||||||
 | 
					                if connectionchatty:
 | 
				
			||||||
 | 
					                    sys.stdout.write(" client:  sending %s...\n" % (repr(indata)))
 | 
				
			||||||
 | 
					                s.write(indata)
 | 
				
			||||||
 | 
					                outdata = s.read()
 | 
				
			||||||
 | 
					                if connectionchatty:
 | 
				
			||||||
 | 
					                    sys.stdout.write(" client:  read %s\n" % repr(outdata))
 | 
				
			||||||
 | 
					                if outdata != indata.lower():
 | 
				
			||||||
 | 
					                    raise AssertionError("bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
 | 
				
			||||||
 | 
					                                         % (outdata[:min(len(outdata), 20)], len(outdata),
 | 
				
			||||||
 | 
					                                            indata[:min(len(indata), 20)].lower(), len(indata)))
 | 
				
			||||||
 | 
					                if connectionchatty:
 | 
				
			||||||
 | 
					                    sys.stdout.write(" client:  closing connection.\n")
 | 
				
			||||||
 | 
					                try:
 | 
				
			||||||
 | 
					                    s.close()
 | 
				
			||||||
 | 
					                except Exception as e:
 | 
				
			||||||
 | 
					                    if connectionchatty:
 | 
				
			||||||
 | 
					                        sys.stdout.write(" client:  error closing connection %s...\n" % (repr(e)))
 | 
				
			||||||
 | 
					                    pass
 | 
				
			||||||
 | 
					            except Exception as e:
 | 
				
			||||||
 | 
					                if connectionchatty:
 | 
				
			||||||
 | 
					                    sys.stdout.write(" client:  aborting with exception %s...\n" % (repr(e)))
 | 
				
			||||||
 | 
					                if result:
 | 
				
			||||||
 | 
					                    raise
 | 
				
			||||||
 | 
					            finally:
 | 
				
			||||||
 | 
					                server.stop()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					    unittest.main()
 | 
				
			||||||
							
								
								
									
										12
									
								
								dtls/util.py
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								dtls/util.py
									
									
									
									
									
								
							@ -57,3 +57,15 @@ class _BIO(_Rsrc):
 | 
				
			|||||||
            BIO_free(self._value)
 | 
					            BIO_free(self._value)
 | 
				
			||||||
            self.owned = False
 | 
					            self.owned = False
 | 
				
			||||||
        self._value = None
 | 
					        self._value = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _EC_KEY(_Rsrc):
 | 
				
			||||||
 | 
					    """EC KEY wrapper"""
 | 
				
			||||||
 | 
					    def __init__(self, value):
 | 
				
			||||||
 | 
					        super(_EC_KEY, self).__init__(value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __del__(self):
 | 
				
			||||||
 | 
					        _logger.debug("Freeing EC_KEY: %d", self.raw)
 | 
				
			||||||
 | 
					        from openssl import EC_KEY_free
 | 
				
			||||||
 | 
					        EC_KEY_free(self._value)
 | 
				
			||||||
 | 
					        self._value = None
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										370
									
								
								dtls/wrapper.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										370
									
								
								dtls/wrapper.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,370 @@
 | 
				
			|||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# DTLS Socket: A wrapper for a server and client using a DTLS connection.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Copyright 2017 Björn Freise
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					# you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					# You may obtain a copy of the License at
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The License is also distributed with this work in the file named "LICENSE."
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					# distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					# See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					# limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"""DTLS Socket
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This wrapper encapsulates the state and behavior associated with the connection
 | 
				
			||||||
 | 
					between the OpenSSL library and an individual peer when using the DTLS
 | 
				
			||||||
 | 
					protocol.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Classes:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  DtlsSocket -- DTLS Socket wrapper for use as a client or server
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import select
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from logging import getLogger
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import ssl
 | 
				
			||||||
 | 
					import socket
 | 
				
			||||||
 | 
					from patch import do_patch
 | 
				
			||||||
 | 
					do_patch()
 | 
				
			||||||
 | 
					from sslconnection import SSLContext, SSL
 | 
				
			||||||
 | 
					import err as err_codes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_logger = getLogger(__name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def wrap_client(sock, keyfile=None, certfile=None,
 | 
				
			||||||
 | 
					                cert_reqs=ssl.CERT_NONE, ssl_version=ssl.PROTOCOL_DTLSv1_2, ca_certs=None,
 | 
				
			||||||
 | 
					                do_handshake_on_connect=True, suppress_ragged_eofs=True,
 | 
				
			||||||
 | 
					                ciphers=None, curves=None, sigalgs=None, user_mtu=None):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return DtlsSocket(sock=sock, keyfile=keyfile, certfile=certfile, server_side=False,
 | 
				
			||||||
 | 
					                      cert_reqs=cert_reqs, ssl_version=ssl_version, ca_certs=ca_certs,
 | 
				
			||||||
 | 
					                      do_handshake_on_connect=do_handshake_on_connect, suppress_ragged_eofs=suppress_ragged_eofs,
 | 
				
			||||||
 | 
					                      ciphers=ciphers, curves=curves, sigalgs=sigalgs, user_mtu=user_mtu,
 | 
				
			||||||
 | 
					                      server_key_exchange_curve=None, server_cert_options=ssl.SSL_BUILD_CHAIN_FLAG_NONE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def wrap_server(sock, keyfile=None, certfile=None,
 | 
				
			||||||
 | 
					                cert_reqs=ssl.CERT_NONE, ssl_version=ssl.PROTOCOL_DTLS, ca_certs=None,
 | 
				
			||||||
 | 
					                do_handshake_on_connect=False, suppress_ragged_eofs=True,
 | 
				
			||||||
 | 
					                ciphers=None, curves=None, sigalgs=None, user_mtu=None,
 | 
				
			||||||
 | 
					                server_key_exchange_curve=None, server_cert_options=ssl.SSL_BUILD_CHAIN_FLAG_NONE):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return DtlsSocket(sock=sock, keyfile=keyfile, certfile=certfile, server_side=True,
 | 
				
			||||||
 | 
					                      cert_reqs=cert_reqs, ssl_version=ssl_version, ca_certs=ca_certs,
 | 
				
			||||||
 | 
					                      do_handshake_on_connect=do_handshake_on_connect, suppress_ragged_eofs=suppress_ragged_eofs,
 | 
				
			||||||
 | 
					                      ciphers=ciphers, curves=curves, sigalgs=sigalgs, user_mtu=user_mtu,
 | 
				
			||||||
 | 
					                      server_key_exchange_curve=server_key_exchange_curve, server_cert_options=server_cert_options)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DtlsSocket(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class _ClientSession(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        def __init__(self, host, port, handshake_done=False):
 | 
				
			||||||
 | 
					            self.host = host
 | 
				
			||||||
 | 
					            self.port = int(port)
 | 
				
			||||||
 | 
					            self.handshake_done = handshake_done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        def getAddr(self):
 | 
				
			||||||
 | 
					            return self.host, self.port
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self,
 | 
				
			||||||
 | 
					                 sock=None,
 | 
				
			||||||
 | 
					                 keyfile=None,
 | 
				
			||||||
 | 
					                 certfile=None,
 | 
				
			||||||
 | 
					                 server_side=False,
 | 
				
			||||||
 | 
					                 cert_reqs=ssl.CERT_NONE,
 | 
				
			||||||
 | 
					                 ssl_version=ssl.PROTOCOL_DTLSv1_2,
 | 
				
			||||||
 | 
					                 ca_certs=None,
 | 
				
			||||||
 | 
					                 do_handshake_on_connect=False,
 | 
				
			||||||
 | 
					                 suppress_ragged_eofs=True,
 | 
				
			||||||
 | 
					                 ciphers=None,
 | 
				
			||||||
 | 
					                 curves=None,
 | 
				
			||||||
 | 
					                 sigalgs=None,
 | 
				
			||||||
 | 
					                 user_mtu=None,
 | 
				
			||||||
 | 
					                 server_key_exchange_curve=None,
 | 
				
			||||||
 | 
					                 server_cert_options=ssl.SSL_BUILD_CHAIN_FLAG_NONE):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if server_cert_options is None:
 | 
				
			||||||
 | 
					            server_cert_options = ssl.SSL_BUILD_CHAIN_FLAG_NONE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self._ssl_logging = False
 | 
				
			||||||
 | 
					        self._server_side = server_side
 | 
				
			||||||
 | 
					        self._ciphers = ciphers
 | 
				
			||||||
 | 
					        self._curves = curves
 | 
				
			||||||
 | 
					        self._sigalgs = sigalgs
 | 
				
			||||||
 | 
					        self._user_mtu = user_mtu
 | 
				
			||||||
 | 
					        self._server_key_exchange_curve = server_key_exchange_curve
 | 
				
			||||||
 | 
					        self._server_cert_options = server_cert_options
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Default socket creation
 | 
				
			||||||
 | 
					        _sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
 | 
				
			||||||
 | 
					        if isinstance(sock, socket.socket):
 | 
				
			||||||
 | 
					            _sock = sock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self._sock = ssl.wrap_socket(_sock,
 | 
				
			||||||
 | 
					                                     keyfile=keyfile,
 | 
				
			||||||
 | 
					                                     certfile=certfile,
 | 
				
			||||||
 | 
					                                     server_side=self._server_side,
 | 
				
			||||||
 | 
					                                     cert_reqs=cert_reqs,
 | 
				
			||||||
 | 
					                                     ssl_version=ssl_version,
 | 
				
			||||||
 | 
					                                     ca_certs=ca_certs,
 | 
				
			||||||
 | 
					                                     do_handshake_on_connect=do_handshake_on_connect,
 | 
				
			||||||
 | 
					                                     suppress_ragged_eofs=suppress_ragged_eofs,
 | 
				
			||||||
 | 
					                                     ciphers=self._ciphers,
 | 
				
			||||||
 | 
					                                     cb_user_config_ssl_ctx=self.user_config_ssl_ctx,
 | 
				
			||||||
 | 
					                                     cb_user_config_ssl=self.user_config_ssl)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if self._server_side:
 | 
				
			||||||
 | 
					            self._clients = {}
 | 
				
			||||||
 | 
					            self._timeout = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __getattr__(self, item):
 | 
				
			||||||
 | 
					        if hasattr(self, "_sock") and hasattr(self._sock, item):
 | 
				
			||||||
 | 
					            return getattr(self._sock, item)
 | 
				
			||||||
 | 
					        raise AttributeError
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def user_config_ssl_ctx(self, _ctx):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param SSLContext _ctx:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        _ctx.set_ssl_logging(self._ssl_logging)
 | 
				
			||||||
 | 
					        if self._ciphers:
 | 
				
			||||||
 | 
					            _ctx.set_ciphers(self._ciphers)
 | 
				
			||||||
 | 
					        if self._curves:
 | 
				
			||||||
 | 
					            _ctx.set_curves(self._curves)
 | 
				
			||||||
 | 
					        if self._sigalgs:
 | 
				
			||||||
 | 
					            _ctx.set_sigalgs(self._sigalgs)
 | 
				
			||||||
 | 
					        if self._server_side:
 | 
				
			||||||
 | 
					            _ctx.build_cert_chain(flags=self._server_cert_options)
 | 
				
			||||||
 | 
					            _ctx.set_ecdh_curve(curve_name=self._server_key_exchange_curve)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def user_config_ssl(self, _ssl):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param SSL _ssl:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        if self._user_mtu:
 | 
				
			||||||
 | 
					            _ssl.set_link_mtu(self._user_mtu)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def settimeout(self, t):
 | 
				
			||||||
 | 
					        if self._server_side:
 | 
				
			||||||
 | 
					            self._timeout = t
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            self._sock.settimeout(t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def close(self):
 | 
				
			||||||
 | 
					        if self._server_side:
 | 
				
			||||||
 | 
					            for cli in self._clients.keys():
 | 
				
			||||||
 | 
					                cli.close()
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                self._sock.unwrap()
 | 
				
			||||||
 | 
					            except:
 | 
				
			||||||
 | 
					                pass
 | 
				
			||||||
 | 
					        self._sock.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def recvfrom(self, bufsize, flags=0):
 | 
				
			||||||
 | 
					        if self._server_side:
 | 
				
			||||||
 | 
					            return self._recvfrom_on_server_side(bufsize, flags=flags)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            return self._recvfrom_on_client_side(bufsize, flags=flags)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _recvfrom_on_server_side(self, bufsize, flags):
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            r, _, _ = select.select(self._getAllReadingSockets(), [], [], self._timeout)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        except socket.timeout:
 | 
				
			||||||
 | 
					            # __Nothing__ received from any client
 | 
				
			||||||
 | 
					            raise socket.timeout
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            for conn in r:
 | 
				
			||||||
 | 
					                _last_peer = conn.getpeername() if conn._connected else None
 | 
				
			||||||
 | 
					                if self._sockIsServerSock(conn):
 | 
				
			||||||
 | 
					                    # Connect
 | 
				
			||||||
 | 
					                    self._clientAccept(conn)
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    # Handshake
 | 
				
			||||||
 | 
					                    if not self._clientHandshakeDone(conn):
 | 
				
			||||||
 | 
					                        self._clientDoHandshake(conn)
 | 
				
			||||||
 | 
					                    # Normal read
 | 
				
			||||||
 | 
					                    else:
 | 
				
			||||||
 | 
					                        buf = self._clientRead(conn, bufsize)
 | 
				
			||||||
 | 
					                        if buf:
 | 
				
			||||||
 | 
					                            if conn in self._clients:
 | 
				
			||||||
 | 
					                                return buf, self._clients[conn].getAddr()
 | 
				
			||||||
 | 
					                            else:
 | 
				
			||||||
 | 
					                                _logger.debug('Received data from an already disconnected client!')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        except Exception as e:
 | 
				
			||||||
 | 
					            setattr(e, 'peer', _last_peer)
 | 
				
			||||||
 | 
					            raise e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            for conn in self._getClientReadingSockets():
 | 
				
			||||||
 | 
					                if conn.get_timeout():
 | 
				
			||||||
 | 
					                    ret = conn.handle_timeout()
 | 
				
			||||||
 | 
					                    _logger.debug('Retransmission triggered for %s: %d' % (str(self._clients[conn].getAddr()), ret))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        except Exception as e:
 | 
				
			||||||
 | 
					            raise e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # __No_data__ received from any client
 | 
				
			||||||
 | 
					        raise socket.timeout
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _recvfrom_on_client_side(self, bufsize, flags):
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            buf = self._sock.recv(bufsize, flags)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        except ssl.SSLError as e:
 | 
				
			||||||
 | 
					            if e.errno == ssl.ERR_READ_TIMEOUT or e.args[0] == ssl.SSL_ERROR_WANT_READ:
 | 
				
			||||||
 | 
					                pass
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                raise e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            if buf:
 | 
				
			||||||
 | 
					                return buf, self._sock.getpeername()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # __No_data__ received from any client
 | 
				
			||||||
 | 
					        raise socket.timeout
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def sendto(self, buf, address):
 | 
				
			||||||
 | 
					        if self._server_side:
 | 
				
			||||||
 | 
					            return self._sendto_from_server_side(buf, address)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            return self._sendto_from_client_side(buf, address)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _sendto_from_server_side(self, buf, address):
 | 
				
			||||||
 | 
					        for conn, client in self._clients.iteritems():
 | 
				
			||||||
 | 
					            if client.getAddr() == address:
 | 
				
			||||||
 | 
					                return self._clientWrite(conn, buf)
 | 
				
			||||||
 | 
					        return 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _sendto_from_client_side(self, buf, address):
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            if not self._sock._connected:
 | 
				
			||||||
 | 
					                self._sock.connect(address)
 | 
				
			||||||
 | 
					            bytes_sent = self._sock.send(buf)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        except ssl.SSLError as e:
 | 
				
			||||||
 | 
					            raise e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return bytes_sent
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _getClientReadingSockets(self):
 | 
				
			||||||
 | 
					        return [x for x in self._clients.keys()]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _getAllReadingSockets(self):
 | 
				
			||||||
 | 
					        return [self._sock] + self._getClientReadingSockets()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _sockIsServerSock(self, conn):
 | 
				
			||||||
 | 
					        return conn is self._sock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _clientHandshakeDone(self, conn):
 | 
				
			||||||
 | 
					        return conn in self._clients and self._clients[conn].handshake_done is True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _clientAccept(self, conn):
 | 
				
			||||||
 | 
					        _logger.debug('+' * 60)
 | 
				
			||||||
 | 
					        ret = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            ret = conn.accept()
 | 
				
			||||||
 | 
					            _logger.debug('Accept returned with ... %s' % (str(ret)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        except Exception as e:
 | 
				
			||||||
 | 
					            raise e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            if ret:
 | 
				
			||||||
 | 
					                client, addr = ret
 | 
				
			||||||
 | 
					                host, port = addr
 | 
				
			||||||
 | 
					                if client in self._clients:
 | 
				
			||||||
 | 
					                    _logger.debug('Client already connected %s' % str(client))
 | 
				
			||||||
 | 
					                    raise ValueError
 | 
				
			||||||
 | 
					                self._clients[client] = self._ClientSession(host=host, port=port)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                self._clientDoHandshake(client)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _clientDoHandshake(self, conn):
 | 
				
			||||||
 | 
					        _logger.debug('-' * 60)
 | 
				
			||||||
 | 
					        conn.setblocking(False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            conn.do_handshake()
 | 
				
			||||||
 | 
					            _logger.debug('Connection from %s successful' % (str(self._clients[conn].getAddr())))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self._clients[conn].handshake_done = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        except ssl.SSLError as e:
 | 
				
			||||||
 | 
					            if e.errno == err_codes.ERR_HANDSHAKE_TIMEOUT or e.args[0] == ssl.SSL_ERROR_WANT_READ:
 | 
				
			||||||
 | 
					                pass
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                self._clientDrop(conn, error=e)
 | 
				
			||||||
 | 
					                raise e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _clientRead(self, conn, bufsize=4096):
 | 
				
			||||||
 | 
					        _logger.debug('*' * 60)
 | 
				
			||||||
 | 
					        ret = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            ret = conn.recv(bufsize)
 | 
				
			||||||
 | 
					            _logger.debug('From client %s ... bytes received %s' % (str(self._clients[conn].getAddr()), str(len(ret))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        except ssl.SSLError as e:
 | 
				
			||||||
 | 
					            if e.args[0] == ssl.SSL_ERROR_WANT_READ:
 | 
				
			||||||
 | 
					                pass
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                self._clientDrop(conn, error=e)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return ret
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _clientWrite(self, conn, data):
 | 
				
			||||||
 | 
					        _logger.debug('#' * 60)
 | 
				
			||||||
 | 
					        ret = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            _data = data
 | 
				
			||||||
 | 
					            if False:
 | 
				
			||||||
 | 
					                _data = data.raw
 | 
				
			||||||
 | 
					            ret = conn.send(_data)
 | 
				
			||||||
 | 
					            _logger.debug('To client %s ... bytes sent %s' % (str(self._clients[conn].getAddr()), str(ret)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        except Exception as e:
 | 
				
			||||||
 | 
					            raise e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return ret
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _clientDrop(self, conn, error=None):
 | 
				
			||||||
 | 
					        _logger.debug('$' * 60)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            if error:
 | 
				
			||||||
 | 
					                _logger.debug('Drop client %s ... with error: %s' % (self._clients[conn].getAddr(), error))
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                _logger.debug('Drop client %s' % str(self._clients[conn].getAddr()))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if conn in self._clients:
 | 
				
			||||||
 | 
					                del self._clients[conn]
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                conn.unwrap()
 | 
				
			||||||
 | 
					            except:
 | 
				
			||||||
 | 
					                pass
 | 
				
			||||||
 | 
					            conn.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        except Exception as e:
 | 
				
			||||||
 | 
					            pass
 | 
				
			||||||
@ -43,7 +43,7 @@ class _X509(_Rsrc):
 | 
				
			|||||||
        super(_X509, self).__init__(value)
 | 
					        super(_X509, self).__init__(value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __del__(self):
 | 
					    def __del__(self):
 | 
				
			||||||
        _logger.debug("Freeing X509: %d", self._value._as_parameter)
 | 
					        _logger.debug("Freeing X509: %d", self.raw)
 | 
				
			||||||
        X509_free(self._value)
 | 
					        X509_free(self._value)
 | 
				
			||||||
        self._value = None
 | 
					        self._value = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -54,11 +54,10 @@ class _STACK(_Rsrc):
 | 
				
			|||||||
        super(_STACK, self).__init__(value)
 | 
					        super(_STACK, self).__init__(value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __del__(self):
 | 
					    def __del__(self):
 | 
				
			||||||
        _logger.debug("Freeing stack: %d", self._value._as_parameter)
 | 
					        _logger.debug("Freeing stack: %d", self.raw)
 | 
				
			||||||
        sk_pop_free(self._value)
 | 
					        sk_pop_free(self._value)
 | 
				
			||||||
        self._value = None
 | 
					        self._value = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
def decode_cert(cert):
 | 
					def decode_cert(cert):
 | 
				
			||||||
    """Convert an X509 certificate into a Python dictionary
 | 
					    """Convert an X509 certificate into a Python dictionary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user