Author: Matti Picus <matti.pi...@gmail.com> Branch: py3.6 Changeset: r98286:a56889d5df88 Date: 2019-12-14 23:33 +0200 http://bitbucket.org/pypy/pypy/changeset/a56889d5df88/
Log: handle OpenSSL v1.1, in _ssl, add post_handshake_auth for TLSv1_3 diff --git a/lib_pypy/_cffi_ssl/_cffi_src/openssl/ssl.py b/lib_pypy/_cffi_ssl/_cffi_src/openssl/ssl.py --- a/lib_pypy/_cffi_ssl/_cffi_src/openssl/ssl.py +++ b/lib_pypy/_cffi_ssl/_cffi_src/openssl/ssl.py @@ -76,6 +76,7 @@ static const long SSL_OP_SINGLE_DH_USE; static const long SSL_OP_EPHEMERAL_RSA; static const long SSL_OP_MICROSOFT_SESS_ID_BUG; +static const long SSL_OP_ENABLE_MIDDLEBOX_COMPAT; static const long SSL_OP_NETSCAPE_CHALLENGE_BUG; static const long SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG; static const long SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG; diff --git a/lib_pypy/_cffi_ssl/_stdssl/__init__.py b/lib_pypy/_cffi_ssl/_stdssl/__init__.py --- a/lib_pypy/_cffi_ssl/_stdssl/__init__.py +++ b/lib_pypy/_cffi_ssl/_stdssl/__init__.py @@ -84,6 +84,9 @@ OP_NO_SSLv2 = lib.SSL_OP_NO_SSLv2 OP_NO_SSLv3 = lib.SSL_OP_NO_SSLv3 OP_NO_TLSv1_3 = lib.SSL_OP_NO_TLSv1_3 +if OPENSSL_VERSION_INFO > (1, 1, 0, 0, 0): + OP_ENABLE_MIDDLEBOX_COMPAT = lib.SSL_OP_ENABLE_MIDDLEBOX_COMPAT + SSL_CLIENT = 0 @@ -271,6 +274,20 @@ mode |= lib.SSL_MODE_AUTO_RETRY lib.SSL_set_mode(ssl, mode) + if HAS_TLSv1_3: + if sslctx._post_handshake_auth: + if socket_type == SSL_SERVER: + # bpo-37428: OpenSSL does not ignore SSL_VERIFY_POST_HANDSHAKE. + # Set SSL_VERIFY_POST_HANDSHAKE flag only for server sockets and + # only in combination with SSL_VERIFY_PEER flag. + mode = lib.SSL_CTX_get_verify_mode(lib.SSL_get_SSL_CTX(self.ssl)) + if (mode & lib.SSL_VERIFY_PEER): + verify_cb = lib.SSL_get_verify_callback(self.ssl) + mode |= lib.SSL_VERIFY_POST_HANDSHAKE + lib.SSL_set_verify(ssl, mode, verify_cb) + else: + lib.SSL_set_post_handshake_auth(ssl, 1) + if HAS_SNI and self.server_hostname: name = _str_to_ffi_buffer(self.server_hostname) lib.SSL_set_tlsext_host_name(ssl, name) @@ -688,6 +705,15 @@ else: return None + def verify_client_post_handshake(self): + + if not HAS_TLSv1_3: + raise NotImplementedError("Post-handshake auth is not supported by " + "your OpenSSL version.") + err = lib.SSL_verify_client_post_handshake(self.ssl); + if err == 0: + raise pyssl_error(self, err) + def pending(self): count = lib.SSL_pending(self.ssl) if count < 0: @@ -744,6 +770,7 @@ return bool(lib.SSL_session_reused(self.ssl)) + def _fs_decode(name): return name.decode(sys.getfilesystemencoding()) def _fs_converter(name): @@ -799,13 +826,13 @@ if OPENSSL_VERSION_INFO > (1, 1, 0, 0, 0): aead = lib.SSL_CIPHER_is_aead(cipher) nid = lib.SSL_CIPHER_get_cipher_nid(cipher) - skcipher = OBJ_nid2ln(nid) if nid != NID_undef else None + skcipher = lib.OBJ_nid2ln(nid) if nid != lib.NID_undef else None nid = lib.SSL_CIPHER_get_digest_nid(cipher); - digest = OBJ_nid2ln(nid) if nid != NID_undef else None + digest = lib.OBJ_nid2ln(nid) if nid != lib.NID_undef else None nid = lib.SSL_CIPHER_get_kx_nid(cipher); - kx = OBJ_nid2ln(nid) if nid != NID_undef else None - nid = SSL_CIPHER_get_auth_nid(cipher); - auth = OBJ_nid2ln(nid) if nid != NID_undef else None + kx = lib.OBJ_nid2ln(nid) if nid != lib.NID_undef else None + nid = lib.SSL_CIPHER_get_auth_nid(cipher); + auth = lib.OBJ_nid2ln(nid) if nid != lib.NID_undef else None ret.update({'aead' : bool(aead), 'symmmetric' : skcipher, 'digest' : digest, @@ -865,9 +892,8 @@ class _SSLContext(object): __slots__ = ('ctx', '_check_hostname', 'servername_callback', 'alpn_protocols', '_alpn_protocols_handle', - 'npn_protocols', 'set_hostname', + 'npn_protocols', 'set_hostname', '_post_handshake_auth', '_set_hostname_handle', '_npn_protocols_handle') - def __new__(cls, protocol): self = object.__new__(cls) self.ctx = ffi.NULL @@ -944,6 +970,9 @@ if lib.Cryptography_HAS_X509_V_FLAG_TRUSTED_FIRST: store = lib.SSL_CTX_get_cert_store(self.ctx) lib.X509_STORE_set_flags(store, lib.X509_V_FLAG_TRUSTED_FIRST) + if HAS_TLSv1_3: + self.post_handshake_auth = 0; + lib.SSL_CTX_set_post_handshake_auth(self.ctx, self.post_handshake_auth) return self @property @@ -1029,6 +1058,7 @@ "CERT_OPTIONAL or CERT_REQUIRED") self._check_hostname = check_hostname + def set_ciphers(self, cipherlist): cipherlistbuf = _str_to_ffi_buffer(cipherlist) ret = lib.SSL_CTX_set_cipher_list(self.ctx, cipherlistbuf) @@ -1362,6 +1392,25 @@ sock = _SSLSocket._new__ssl_socket(self, None, server_side, hostname, incoming, outgoing) return sock + @property + def post_handshake_auth(self): + if HAS_TLSv1_3: + return bool(self._post_handshake_auth) + return None + + @post_handshake_auth.setter + def post_handshake_auth(self, arg): + if arg is None: + raise AttributeError("cannot delete attribute") + + pha = bool(arg) + self._post_handshake_auth = pha; + + # bpo-37428: newPySSLSocket() sets SSL_VERIFY_POST_HANDSHAKE flag for + # server sockets and SSL_set_post_handshake_auth() for client + + return 0; + # cryptography constraint: OPENSSL_NO_TLSEXT will never be set! _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit