[pypy-commit] pypy py3.5-ssl: build openssl cffi backend now as _pypy_openssl (to not clash with cryptography)

plan_rich pypy.commits at gmail.com
Mon Nov 21 05:07:05 EST 2016


Author: Richard Plangger <planrichi at gmail.com>
Branch: py3.5-ssl
Changeset: r88508:359fdf344b44
Date: 2016-11-21 11:06 +0100
http://bitbucket.org/pypy/pypy/changeset/359fdf344b44/

Log:	build openssl cffi backend now as _pypy_openssl (to not clash with
	cryptography) several changes while discussing the PR back to
	cryptography. most of the functions are now contained in
	cryptography.

diff --git a/lib-python/3/test/test_ssl.py b/lib-python/3/test/test_ssl.py
--- a/lib-python/3/test/test_ssl.py
+++ b/lib-python/3/test/test_ssl.py
@@ -1738,6 +1738,10 @@
         return ret
 
     def test_handshake(self):
+        # NOTE: this test has been modified, CPython in newer versions
+        # removed the ability to get the shared ciphers of the session, but
+        # they always return the cipher of the ssl context. This test is fully
+        # removed in later versions
         with support.transient_internet(REMOTE_HOST):
             sock = socket.socket(socket.AF_INET)
             sock.connect((REMOTE_HOST, 443))
@@ -1750,13 +1754,13 @@
             sslobj = ctx.wrap_bio(incoming, outgoing, False, REMOTE_HOST)
             self.assertIs(sslobj._sslobj.owner, sslobj)
             self.assertIsNone(sslobj.cipher())
-            self.assertIsNone(sslobj.shared_ciphers())
+            #self.assertIsNone(sslobj.shared_ciphers())
             self.assertRaises(ValueError, sslobj.getpeercert)
             if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
                 self.assertIsNone(sslobj.get_channel_binding('tls-unique'))
             self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
             self.assertTrue(sslobj.cipher())
-            self.assertIsNone(sslobj.shared_ciphers())
+            #self.assertIsNone(sslobj.shared_ciphers())
             self.assertTrue(sslobj.getpeercert())
             if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
                 self.assertTrue(sslobj.get_channel_binding('tls-unique'))
@@ -3282,18 +3286,31 @@
             self.assertIn("TypeError", stderr.getvalue())
 
         def test_shared_ciphers(self):
+            # NOTE: This test case has been copied from master (~3.6)
+            # reason is the method SSL_get_ciphers (before that it used
+            # get_ciphers of the session which is not public)
             server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
             server_context.load_cert_chain(SIGNED_CERTFILE)
             client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
             client_context.verify_mode = ssl.CERT_REQUIRED
             client_context.load_verify_locations(SIGNING_CA)
-            client_context.set_ciphers("RC4")
-            server_context.set_ciphers("AES:RC4")
+            if ssl.OPENSSL_VERSION_INFO >= (1, 0, 2):
+                client_context.set_ciphers("AES128:AES256")
+                server_context.set_ciphers("AES256")
+                alg1 = "AES256"
+                alg2 = "AES-256"
+            else:
+                client_context.set_ciphers("AES:3DES")
+                server_context.set_ciphers("3DES")
+                alg1 = "3DES"
+                alg2 = "DES-CBC3"
+
             stats = server_params_test(client_context, server_context)
             ciphers = stats['server_shared_ciphers'][0]
             self.assertGreater(len(ciphers), 0)
             for name, tls_version, bits in ciphers:
-                self.assertIn("RC4", name.split("-"))
+                if not alg1 in name.split("-") and alg2 not in name:
+                    self.fail(name)
 
         def test_read_write_after_close_raises_valuerror(self):
             context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
diff --git a/lib_pypy/_cffi_ssl/README.md b/lib_pypy/_cffi_ssl/README.md
--- a/lib_pypy/_cffi_ssl/README.md
+++ b/lib_pypy/_cffi_ssl/README.md
@@ -1,8 +1,16 @@
 # PyPy's SSL module
 
-Most of the CFFI code is copied from cryptography
+All of the CFFI code is copied from cryptography, wich patches contributed
+back to cryptography. PyPy vendors it's own copy of the cffi backend thus
+it renames the compiled shared object to _pypy_openssl.so (which means
+that cryptography can ship their own cffi backend)
 
 # Tests?
 
 Currently this module is tested using CPython's standard library test suite.
 
+# Install it into PyPy's source tree
+
+Copy over all the sources into the folder `lib_pypy/_cffi_ssl/*`. Updating the cffi backend can be simply done by the following command:
+
+    $ cp -r <cloned cryptography folder>/src/_cffi_src/* .
diff --git a/lib_pypy/_cffi_ssl/_cffi_src/build_openssl.py b/lib_pypy/_cffi_ssl/_cffi_src/build_openssl.py
--- a/lib_pypy/_cffi_ssl/_cffi_src/build_openssl.py
+++ b/lib_pypy/_cffi_ssl/_cffi_src/build_openssl.py
@@ -73,7 +73,6 @@
         "rand",
         "rsa",
         "ssl",
-        "tls1",
         "x509",
         "x509name",
         "x509v3",
diff --git a/lib_pypy/_cffi_ssl/_cffi_src/openssl/bio.py b/lib_pypy/_cffi_ssl/_cffi_src/openssl/bio.py
--- a/lib_pypy/_cffi_ssl/_cffi_src/openssl/bio.py
+++ b/lib_pypy/_cffi_ssl/_cffi_src/openssl/bio.py
@@ -82,11 +82,12 @@
 int BIO_write(BIO *, const void *, int);
 int BIO_puts(BIO *, const char *);
 int BIO_method_type(const BIO *);
-
-int * Cryptography_bio_references(const BIO *);
 """
 
 MACROS = """
+/* Added in 1.1.0 */
+int BIO_up_ref(BIO *);
+
 /* These added const to BIO_METHOD in 1.1.0 */
 BIO *BIO_new(BIO_METHOD *);
 BIO_METHOD *BIO_s_mem(void);
@@ -134,12 +135,13 @@
 long BIO_set_nbio(BIO *, long);
 void BIO_set_retry_read(BIO *);
 void BIO_clear_retry_flags(BIO *);
-
-#define CRYPTO_LOCK_BIO ...
 """
 
 CUSTOMIZATIONS = """
-int * Cryptography_bio_references(const BIO * b) {
-    return &b->references;
+#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110PRE4 || defined(LIBRESSL_VERSION_NUMBER)
+int BIO_up_ref(BIO *b) {
+    CRYPTO_add(&b->references, 1, CRYPTO_LOCK_BIO);
+    return 1;
 }
+#endif
 """
diff --git a/lib_pypy/_cffi_ssl/_cffi_src/openssl/crypto.py b/lib_pypy/_cffi_ssl/_cffi_src/openssl/crypto.py
--- a/lib_pypy/_cffi_ssl/_cffi_src/openssl/crypto.py
+++ b/lib_pypy/_cffi_ssl/_cffi_src/openssl/crypto.py
@@ -57,8 +57,6 @@
 
 /* This was removed in 1.1.0 */
 void CRYPTO_lock(int, int, const char *, int);
-
-void CRYPTO_add(void*,int,int);
 """
 
 CUSTOMIZATIONS = """
diff --git a/lib_pypy/_cffi_ssl/_cffi_src/openssl/cryptography.py b/lib_pypy/_cffi_ssl/_cffi_src/openssl/cryptography.py
--- a/lib_pypy/_cffi_ssl/_cffi_src/openssl/cryptography.py
+++ b/lib_pypy/_cffi_ssl/_cffi_src/openssl/cryptography.py
@@ -36,8 +36,12 @@
     (OPENSSL_VERSION_NUMBER < 0x1000209fL)
 #define CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 \
     (OPENSSL_VERSION_NUMBER < 0x10100000)
+#define CRYPTOGRAPHY_OPENSSL_LESS_THAN_110PRE4 \
+    (OPENSSL_VERSION_NUMBER < 0x10100004)
 #define CRYPTOGRAPHY_OPENSSL_LESS_THAN_110PRE5 \
     (OPENSSL_VERSION_NUMBER < 0x10100005)
+#define CRYPTOGRAPHY_OPENSSL_LESS_THAN_110PRE6 \
+    (OPENSSL_VERSION_NUMBER < 0x10100006)
 
 #if defined(LIBRESSL_VERSION_NUMBER)
 #define CRYPTOGRAPHY_IS_LIBRESSL 1
diff --git a/lib_pypy/_cffi_ssl/_cffi_src/openssl/dh.py b/lib_pypy/_cffi_ssl/_cffi_src/openssl/dh.py
--- a/lib_pypy/_cffi_ssl/_cffi_src/openssl/dh.py
+++ b/lib_pypy/_cffi_ssl/_cffi_src/openssl/dh.py
@@ -26,6 +26,7 @@
 int i2d_DHparams(const DH *, unsigned char **);
 int DHparams_print_fp(FILE *, const DH *);
 int DHparams_print(BIO *, const DH *);
+DH *DHparams_dup(DH *);
 
 /* added in 1.1.0 when the DH struct was opaqued */
 void DH_get0_pqg(const DH *, const BIGNUM **, const BIGNUM **,
diff --git a/lib_pypy/_cffi_ssl/_cffi_src/openssl/ecdh.py b/lib_pypy/_cffi_ssl/_cffi_src/openssl/ecdh.py
--- a/lib_pypy/_cffi_ssl/_cffi_src/openssl/ecdh.py
+++ b/lib_pypy/_cffi_ssl/_cffi_src/openssl/ecdh.py
@@ -12,7 +12,7 @@
 
 TYPES = """
 static const int Cryptography_HAS_ECDH;
-static const int Cryptography_HAS_ECDH_SET_CURVE;
+static const int Cryptography_HAS_SET_ECDH_AUTO;
 """
 
 FUNCTIONS = """
@@ -21,7 +21,7 @@
 MACROS = """
 int ECDH_compute_key(void *, size_t, const EC_POINT *, EC_KEY *,
                      void *(*)(const void *, size_t, void *, size_t *));
-int SSL_CTX_set_ecdh_auto(SSL_CTX *ctx, int onoff);
+int SSL_CTX_set_ecdh_auto(SSL_CTX *, int);
 """
 
 CUSTOMIZATIONS = """
@@ -35,9 +35,11 @@
 #else
 static const long Cryptography_HAS_ECDH = 1;
 #endif
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 || defined(LIBRESSL_VERSION_NUMBER)
-static const long Cryptography_HAS_ECDH_SET_CURVE = 0;
+
+#ifndef SSL_CTX_set_ecdh_auto
+static const long Cryptography_HAS_SET_ECDH_AUTO = 0;
+int (*SSL_CTX_set_ecdh_auto)(SSL_CTX *, int) = NULL;
 #else
-static const long Cryptography_HAS_ECDH_SET_CURVE = 1;
+static const long Cryptography_HAS_SET_ECDH_AUTO = 1;
 #endif
 """
diff --git a/lib_pypy/_cffi_ssl/_cffi_src/openssl/err.py b/lib_pypy/_cffi_ssl/_cffi_src/openssl/err.py
--- a/lib_pypy/_cffi_ssl/_cffi_src/openssl/err.py
+++ b/lib_pypy/_cffi_ssl/_cffi_src/openssl/err.py
@@ -81,6 +81,7 @@
 static const int ASN1_R_NO_CONTENT_TYPE;
 static const int ASN1_R_NO_MULTIPART_BODY_FAILURE;
 static const int ASN1_R_NO_MULTIPART_BOUNDARY;
+static const int ASN1_R_HEADER_TOO_LONG;
 
 static const int DH_F_COMPUTE_KEY;
 
@@ -224,6 +225,8 @@
 static const int SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
 static const int SSL_AD_BAD_CERTIFICATE_HASH_VALUE;
 static const int SSL_AD_UNKNOWN_PSK_IDENTITY;
+
+static const int X509_R_CERT_ALREADY_IN_HASH_TABLE;
 """
 
 FUNCTIONS = """
@@ -280,24 +283,4 @@
 static const long Cryptography_HAS_RSA_R_PKCS_DECODING_ERROR = 0;
 static const long RSA_R_PKCS_DECODING_ERROR = 0;
 #endif
-
-#ifndef SSL_AD_UNSUPPORTED_EXTENSION
-    static const int SSL_AD_UNSUPPORTED_EXTENSION = -1;
-#endif
-#ifndef SSL_AD_CERTIFICATE_UNOBTAINABLE
-    static const int SSL_AD_CERTIFICATE_UNOBTAINABLE = -1;
-#endif
-#ifndef SSL_AD_UNRECOGNIZED_NAME
-    static const int SSL_AD_UNRECOGNIZED_NAME = -1;
-#endif
-#ifndef SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE
-    static const int SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE = -1;
-#endif
-#ifndef SSL_AD_BAD_CERTIFICATE_HASH_VALUE
-    static const int SSL_AD_BAD_CERTIFICATE_HASH_VALUE = -1;
-#endif
-#ifndef SSL_AD_UNKNOWN_PSK_IDENTITY
-    static const int SSL_AD_UNKNOWN_PSK_IDENTITY = -1;
-#endif
-
 """
diff --git a/lib_pypy/_cffi_ssl/_cffi_src/openssl/nid.py b/lib_pypy/_cffi_ssl/_cffi_src/openssl/nid.py
--- a/lib_pypy/_cffi_ssl/_cffi_src/openssl/nid.py
+++ b/lib_pypy/_cffi_ssl/_cffi_src/openssl/nid.py
@@ -215,14 +215,15 @@
 static const int NID_pseudonym;
 static const int NID_domainComponent;
 static const int NID_pkcs9_emailAddress;
+
+static const int NID_ad_OCSP;
+static const int NID_ad_ca_issuers;
 """
 
 FUNCTIONS = """
 """
 
 MACROS = """
-static const int NID_ad_OCSP;
-static const int NID_ad_ca_issuers;
 """
 
 CUSTOMIZATIONS = """
diff --git a/lib_pypy/_cffi_ssl/_cffi_src/openssl/rand.py b/lib_pypy/_cffi_ssl/_cffi_src/openssl/rand.py
--- a/lib_pypy/_cffi_ssl/_cffi_src/openssl/rand.py
+++ b/lib_pypy/_cffi_ssl/_cffi_src/openssl/rand.py
@@ -20,7 +20,6 @@
 int RAND_load_file(const char *, long);
 int RAND_write_file(const char *);
 int RAND_bytes(unsigned char *, int);
-int RAND_pseudo_bytes(unsigned char *buf, int num);
 """
 
 MACROS = """
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
@@ -26,9 +26,7 @@
 static const long Cryptography_HAS_SSL_CTX_SET_CLIENT_CERT_ENGINE;
 static const long Cryptography_HAS_SSL_CTX_CLEAR_OPTIONS;
 static const long Cryptography_HAS_NPN_NEGOTIATED;
-static const long Cryptography_NO_TLSEXT;
-
-static const long Cryptography_OPENSSL_NPN_NEGOTIATED;
+static const long Cryptography_OPENSSL_NO_TLSEXT;
 
 /* Internally invented symbol to tell us if SNI is supported */
 static const long Cryptography_HAS_TLSEXT_HOSTNAME;
@@ -134,6 +132,8 @@
 static const long TLS_ST_BEFORE;
 static const long TLS_ST_OK;
 
+static const long OPENSSL_NPN_NEGOTIATED;
+
 typedef ... SSL_METHOD;
 typedef ... SSL_CTX;
 
@@ -196,7 +196,6 @@
 int SSL_renegotiate_pending(SSL *);
 const char *SSL_get_cipher_list(const SSL *, int);
 Cryptography_STACK_OF_SSL_CIPHER *SSL_get_ciphers(const SSL *);
-Cryptography_STACK_OF_SSL_CIPHER * Cryptography_get_ssl_session_ciphers(const SSL_SESSION *);
 
 /*  context */
 void SSL_CTX_free(SSL_CTX *);
@@ -691,17 +690,9 @@
 static const long Cryptography_HAS_SSL_CTX_CLEAR_OPTIONS = 1;
 
 #ifdef OPENSSL_NO_TLSEXT
-static const long Cryptography_NO_TLSEXT = 1;
+static const long Cryptography_OPENSSL_NO_TLSEXT = 1;
 #else
-static const long Cryptography_NO_TLSEXT = 0;
-#endif
-
-#ifdef OPENSSL_NPN_NEGOTIATED
-static const long Cryptography_OPENSSL_NPN_NEGOTIATED = OPENSSL_NPN_NEGOTIATED;
-static const long Cryptography_HAS_NPN_NEGOTIATED = 1;
-#else
-static const long Cryptography_OPENSSL_NPN_NEGOTIATED = 0;
-static const long Cryptography_HAS_NPN_NEGOTIATED = 0;
+static const long Cryptography_OPENSSL_NO_TLSEXT = 0;
 #endif
 
 /* in OpenSSL 1.1.0 the SSL_ST values were renamed to TLS_ST and several were
@@ -723,7 +714,12 @@
 static const long TLS_ST_OK = 0;
 #endif
 
-Cryptography_STACK_OF_SSL_CIPHER * Cryptography_get_ssl_session_ciphers(const SSL_SESSION *s) {
-    return s->ciphers;
-}
+/* This define is available in 1.0.1+ so we can remove this when we drop
+   support for 1.0.0 */
+#ifdef OPENSSL_NPN_NEGOTIATED
+static const long Cryptography_HAS_NPN_NEGOTIATED = 1;
+#else
+static const long OPENSSL_NPN_NEGOTIATED = -1;
+static const long Cryptography_HAS_NPN_NEGOTIATED = 0;
+#endif
 """
diff --git a/lib_pypy/_cffi_ssl/_cffi_src/openssl/tls1.py b/lib_pypy/_cffi_ssl/_cffi_src/openssl/tls1.py
--- a/lib_pypy/_cffi_ssl/_cffi_src/openssl/tls1.py
+++ b/lib_pypy/_cffi_ssl/_cffi_src/openssl/tls1.py
@@ -12,7 +12,8 @@
 """
 
 FUNCTIONS = """
-long Cryptography_SSL_CTX_set_tlsext_servername_callback(SSL_CTX *, int(*)(SSL*,int*,void*));
+long Cryptography_SSL_CTX_set_tlsext_servername_callback(SSL_CTX *,
+                                            int(*)(SSL*,int*,void*));
 long Cryptography_SSL_CTX_set_tlsext_servername_arg(SSL_CTX *, void * arg);
 """
 
@@ -20,7 +21,8 @@
 """
 
 CUSTOMIZATIONS = """
-long Cryptography_SSL_CTX_set_tlsext_servername_callback(SSL_CTX * ctx, int(*cb)(SSL*,int*,void*)) {
+long Cryptography_SSL_CTX_set_tlsext_servername_callback(SSL_CTX * ctx,
+                                              int(*cb)(SSL*,int*,void*)) {
     return SSL_CTX_set_tlsext_servername_callback(ctx, cb);
 }
 long Cryptography_SSL_CTX_set_tlsext_servername_arg(SSL_CTX * ctx, void *arg) {
diff --git a/lib_pypy/_cffi_ssl/_cffi_src/openssl/x509.py b/lib_pypy/_cffi_ssl/_cffi_src/openssl/x509.py
--- a/lib_pypy/_cffi_ssl/_cffi_src/openssl/x509.py
+++ b/lib_pypy/_cffi_ssl/_cffi_src/openssl/x509.py
@@ -17,15 +17,12 @@
 typedef STACK_OF(X509) Cryptography_STACK_OF_X509;
 typedef STACK_OF(X509_CRL) Cryptography_STACK_OF_X509_CRL;
 typedef STACK_OF(X509_REVOKED) Cryptography_STACK_OF_X509_REVOKED;
-typedef STACK_OF(ACCESS_DESCRIPTION) Cryptography_AUTHORITY_INFO_ACCESS;
-typedef STACK_OF(X509_OBJECT) Cryptography_STACK_OF_X509_OBJECT;
 """
 
 TYPES = """
 typedef ... Cryptography_STACK_OF_X509;
 typedef ... Cryptography_STACK_OF_X509_CRL;
 typedef ... Cryptography_STACK_OF_X509_REVOKED;
-typedef ... Cryptography_AUTHORITY_INFO_ACCESS;
 
 typedef struct {
     ASN1_OBJECT *algorithm;
@@ -339,11 +336,6 @@
 int i2d_re_X509_CRL_tbs(X509_CRL *, unsigned char **);
 void X509_REQ_get0_signature(const X509_REQ *, const ASN1_BIT_STRING **,
                              const X509_ALGOR **);
-
-void AUTHORITY_INFO_ACCESS_free(Cryptography_AUTHORITY_INFO_ACCESS*);
-
-#define X509_R_CERT_ALREADY_IN_HASH_TABLE ...
-#define ASN1_R_HEADER_TOO_LONG ...
 """
 
 CUSTOMIZATIONS = """
diff --git a/lib_pypy/_cffi_ssl/_cffi_src/openssl/x509_vfy.py b/lib_pypy/_cffi_ssl/_cffi_src/openssl/x509_vfy.py
--- a/lib_pypy/_cffi_ssl/_cffi_src/openssl/x509_vfy.py
+++ b/lib_pypy/_cffi_ssl/_cffi_src/openssl/x509_vfy.py
@@ -23,17 +23,12 @@
 static const long Cryptography_HAS_102_VERIFICATION_PARAMS;
 static const long Cryptography_HAS_X509_V_FLAG_TRUSTED_FIRST;
 static const long Cryptography_HAS_X509_V_FLAG_PARTIAL_CHAIN;
-static const long Cryptography_X509_LU_X509;
-static const long Cryptography_X509_LU_CLR;
 
 typedef ... Cryptography_STACK_OF_ASN1_OBJECT;
 typedef ... Cryptography_STACK_OF_X509_OBJECT;
 
 typedef ... X509_OBJECT;
-typedef struct {
-    Cryptography_STACK_OF_X509_OBJECT * objs;
-    ...;
-} X509_STORE;
+typedef ... X509_STORE;
 typedef ... X509_VERIFY_PARAM;
 typedef ... X509_STORE_CTX;
 
@@ -128,6 +123,8 @@
 static const long X509_V_FLAG_SUITEB_128_LOS;
 static const long X509_V_FLAG_PARTIAL_CHAIN;
 
+static const long X509_LU_X509;
+static const long X509_LU_CRL;
 """
 
 FUNCTIONS = """
@@ -142,7 +139,6 @@
 int X509_STORE_set_default_paths(X509_STORE *);
 int X509_STORE_set_flags(X509_STORE *, unsigned long);
 void X509_STORE_free(X509_STORE *);
-X509_VERIFY_PARAM *_X509_STORE_get0_param(X509_STORE *);
 
 /* X509_STORE_CTX */
 X509_STORE_CTX *X509_STORE_CTX_new(void);
@@ -182,8 +178,6 @@
 void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *, int);
 int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *);
 void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *);
-int Cryptography_X509_OBJECT_get_type(const X509_OBJECT *);
-X509 * Cryptography_X509_OBJECT_data_x509(X509_OBJECT*);
 """
 
 MACROS = """
@@ -205,10 +199,12 @@
                               size_t);
 int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *, const char *);
 
-/* STACK_OF(X509_OBJECT) */
 int sk_X509_OBJECT_num(Cryptography_STACK_OF_X509_OBJECT *);
 X509_OBJECT *sk_X509_OBJECT_value(Cryptography_STACK_OF_X509_OBJECT *, int);
-
+X509_VERIFY_PARAM * X509_STORE_get0_param(X509_STORE *);
+Cryptography_STACK_OF_X509_OBJECT *X509_STORE_get0_objects(X509_STORE *);
+X509 *X509_OBJECT_get0_X509(X509_OBJECT *);
+int X509_OBJECT_get_type(const X509_OBJECT *);
 """
 
 CUSTOMIZATIONS = """
@@ -268,18 +264,21 @@
 static const long X509_V_FLAG_TRUSTED_FIRST = 0;
 #endif
 
-X509_VERIFY_PARAM *_X509_STORE_get0_param(X509_STORE *store) {
+#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110PRE6 || defined(LIBRESSL_VERSION_NUMBER)
+Cryptography_STACK_OF_X509_OBJECT *X509_STORE_get0_objects(X509_STORE *ctx) {
+    return ctx->objs;
+}
+X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *store) {
     return store->param;
 }
-
-int Cryptography_X509_OBJECT_get_type(const X509_OBJECT * x) {
+int X509_OBJECT_get_type(const X509_OBJECT *x) {
     return x->type;
 }
+#endif
 
-X509 * Cryptography_X509_OBJECT_data_x509(X509_OBJECT * x) {
+#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110PRE5 || defined(LIBRESSL_VERSION_NUMBER)
+X509 *X509_OBJECT_get0_X509(X509_OBJECT *x) {
     return x->data.x509;
 }
-
-static const long Cryptography_X509_LU_X509 = X509_LU_X509;
-static const long Cryptography_X509_LU_CLR = X509_LU_CRL;
+#endif
 """
diff --git a/lib_pypy/_cffi_ssl/_cffi_src/openssl/x509v3.py b/lib_pypy/_cffi_ssl/_cffi_src/openssl/x509v3.py
--- a/lib_pypy/_cffi_ssl/_cffi_src/openssl/x509v3.py
+++ b/lib_pypy/_cffi_ssl/_cffi_src/openssl/x509v3.py
@@ -171,25 +171,23 @@
     Cryptography_STACK_OF_POLICYQUALINFO *qualifiers;
 } POLICYINFO;
 
-typedef void (*sk_GENERAL_NAME_freefunc)(struct GENERAL_NAME_st *);
+typedef void (*sk_GENERAL_NAME_freefunc)(GENERAL_NAME *);
 """
 
 
 FUNCTIONS = """
 int X509V3_EXT_add_alias(int, int);
 void X509V3_set_ctx(X509V3_CTX *, X509 *, X509 *, X509_REQ *, X509_CRL *, int);
-GENERAL_NAME *GENERAL_NAME_new(void);
 int GENERAL_NAME_print(BIO *, GENERAL_NAME *);
 GENERAL_NAMES *GENERAL_NAMES_new(void);
 void GENERAL_NAMES_free(GENERAL_NAMES *);
 void *X509V3_EXT_d2i(X509_EXTENSION *);
-/* X509 is private, there is no way to access the field crldp other than
-   adding it to the typedef or expose a function like this: */
-Cryptography_STACK_OF_DIST_POINT * Cryptography_X509_get_crldp(const X509 *);
 int X509_check_ca(X509 *);
 """
 
 MACROS = """
+/* X509 became a const arg in 1.1.0 */
+void *X509_get_ext_d2i(X509 *, int, int *, int *);
 /* The last two char * args became const char * in 1.1.0 */
 X509_EXTENSION *X509V3_EXT_nconf(CONF *, X509V3_CTX *, char *, char *);
 /* This is a macro defined by a call to DECLARE_ASN1_FUNCTIONS in the
@@ -219,9 +217,8 @@
 int sk_GENERAL_NAME_num(struct stack_st_GENERAL_NAME *);
 int sk_GENERAL_NAME_push(struct stack_st_GENERAL_NAME *, GENERAL_NAME *);
 GENERAL_NAME *sk_GENERAL_NAME_value(struct stack_st_GENERAL_NAME *, int);
-
-void sk_GENERAL_NAME_pop_free(struct stack_st_GENERAL_NAME*, sk_GENERAL_NAME_freefunc);
-void GENERAL_NAME_free(struct GENERAL_NAME_st*);
+void sk_GENERAL_NAME_pop_free(struct stack_st_GENERAL_NAME *,
+                              sk_GENERAL_NAME_freefunc);
 
 Cryptography_STACK_OF_ACCESS_DESCRIPTION *sk_ACCESS_DESCRIPTION_new_null(void);
 int sk_ACCESS_DESCRIPTION_num(Cryptography_STACK_OF_ACCESS_DESCRIPTION *);
@@ -299,17 +296,9 @@
 DIST_POINT_NAME *DIST_POINT_NAME_new(void);
 void DIST_POINT_NAME_free(DIST_POINT_NAME *);
 
-void * X509_get_ext_d2i(const X509 *, int, int *, int *);
+GENERAL_NAME *GENERAL_NAME_new(void);
+void GENERAL_NAME_free(GENERAL_NAME *);
 """
 
 CUSTOMIZATIONS = """
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
-Cryptography_STACK_OF_DIST_POINT * Cryptography_X509_get_crldp(const X509 * x) {
-    return x->crldp;
-}
-#else
-Cryptography_STACK_OF_DIST_POINT * Cryptography_X509_get_crldp(const X509 * x) {
-    return NULL;
-}
-#endif
 """
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
@@ -3,8 +3,8 @@
 import _thread
 import socket
 import weakref
-from _openssl import ffi
-from _openssl import lib
+from _pypy_openssl import ffi
+from _pypy_openssl import lib
 from _cffi_ssl._stdssl.certificate import (_test_decode_cert,
     _decode_certificate, _certificate_to_der)
 from _cffi_ssl._stdssl.utility import (_str_with_len, _bytes_with_len,
@@ -37,7 +37,7 @@
 HAS_ECDH = bool(lib.Cryptography_HAS_ECDH)
 HAS_SNI = bool(lib.Cryptography_HAS_TLSEXT_HOSTNAME)
 HAS_ALPN = bool(lib.Cryptography_HAS_ALPN)
-HAS_NPN = lib.Cryptography_HAS_NPN_NEGOTIATED
+HAS_NPN = bool(lib.OPENSSL_NPN_NEGOTIATED)
 HAS_TLS_UNIQUE = True
 
 CLIENT = 0
@@ -225,10 +225,8 @@
             # BIOs are reference counted and SSL_set_bio borrows our reference.
             # To prevent a double free in memory_bio_dealloc() we need to take an
             # extra reference here.
-            irefaddr = lib.Cryptography_bio_references(inbio.bio);
-            orefaddr = lib.Cryptography_bio_references(outbio.bio);
-            lib.CRYPTO_add(irefaddr, 1, lib.CRYPTO_LOCK_BIO)
-            lib.CRYPTO_add(orefaddr, 1, lib.CRYPTO_LOCK_BIO)
+            lib.BIO_up_ref(inbio.bio);
+            lib.BIO_up_ref(outbio.bio);
             lib.SSL_set_bio(self.ssl, inbio.bio, outbio.bio)
 
         mode = lib.SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER
@@ -271,8 +269,6 @@
         self._owner = None
         self.server_hostname = None
         self.socket = None
-        #self.alpn_protocols = ffi.NULL
-        #self.npn_protocols = ffi.NULL
 
     @property
     def owner(self):
@@ -515,10 +511,7 @@
             return _str_with_len(out[0], outlen[0]);
 
     def shared_ciphers(self):
-        sess = lib.SSL_get_session(self.ssl)
-        if sess == ffi.NULL:
-            return None
-        ciphers = lib.Cryptography_get_ssl_session_ciphers(sess)
+        ciphers = lib.SSL_get_ciphers(self.ssl)
         if ciphers == ffi.NULL:
             return None
         res = []
@@ -732,7 +725,8 @@
 
 class _SSLContext(object):
     __slots__ = ('ctx', '_check_hostname', 'servername_callback',
-                 'alpn_protocols', 'npn_protocols', 'set_hostname',
+                 'alpn_protocols', '_alpn_protocols_handle',
+                 'npn_protocols', 'set_hostname',
                  '_set_hostname_handle', '_npn_protocols_handle')
 
     def __new__(cls, protocol):
@@ -758,7 +752,6 @@
             raise ssl_error("failed to allocate SSL context")
 
         self._check_hostname = False
-        # TODO self.register_finalizer(space)
 
         # Defaults
         lib.SSL_CTX_set_verify(self.ctx, lib.SSL_VERIFY_NONE, ffi.NULL)
@@ -775,7 +768,7 @@
             # OpenSSL 1.0.2+), or use prime256v1 by default.
             # This is Apache mod_ssl's initialization
             # policy, so we should be safe.
-            if lib.Cryptography_HAS_ECDH_SET_CURVE:
+            if lib.Cryptography_HAS_SET_ECDH_AUTO:
                 lib.SSL_CTX_set_ecdh_auto(self.ctx, 1)
             else:
                 key = lib.EC_KEY_new_by_curve_name(lib.NID_X9_62_prime256v1)
@@ -834,7 +827,7 @@
     @property
     def verify_flags(self):
         store = lib.SSL_CTX_get_cert_store(self.ctx)
-        param = lib._X509_STORE_get0_param(store)
+        param = lib.X509_STORE_get0_param(store)
         flags = lib.X509_VERIFY_PARAM_get_flags(param)
         return int(flags)
 
@@ -842,16 +835,16 @@
     def verify_flags(self, value):
         new_flags = int(value)
         store = lib.SSL_CTX_get_cert_store(self.ctx);
-        param = lib._X509_STORE_get0_param(store)
+        param = lib.X509_STORE_get0_param(store)
         flags = lib.X509_VERIFY_PARAM_get_flags(param);
         clear = flags & ~new_flags;
         set = ~flags & new_flags;
         if clear:
-            param = lib._X509_STORE_get0_param(store)
+            param = lib.X509_STORE_get0_param(store)
             if not lib.X509_VERIFY_PARAM_clear_flags(param, clear):
                 raise ssl_error(None, 0)
         if set:
-            param = lib._X509_STORE_get0_param(store)
+            param = lib.X509_STORE_get0_param(store)
             if not lib.X509_VERIFY_PARAM_set_flags(param, set):
                 raise ssl_error(None, 0)
 
@@ -1036,17 +1029,17 @@
         x509 = 0
         x509_ca = 0
         crl = 0
-        objs = store.objs
+        objs = lib.X509_STORE_get0_objects(store)
         count = lib.sk_X509_OBJECT_num(objs)
         for i in range(count):
             obj = lib.sk_X509_OBJECT_value(objs, i)
-            _type = lib.Cryptography_X509_OBJECT_get_type(obj)
-            if _type == lib.Cryptography_X509_LU_X509:
+            _type = lib.X509_OBJECT_get_type(obj)
+            if _type == lib.X509_LU_X509:
                 x509 += 1
-                cert = lib.Cryptography_X509_OBJECT_data_x509(obj)
+                cert = lib.X509_OBJECT_get0_X509(obj)
                 if lib.X509_check_ca(cert):
                     x509_ca += 1
-            elif _type == lib.Cryptography_X509_LU_CRL:
+            elif _type == lib.X509_LU_CRL:
                 crl += 1
             else:
                 # Ignore X509_LU_FAIL, X509_LU_RETRY, X509_LU_PKEY.
@@ -1056,12 +1049,14 @@
         return {'x509': x509, 'x509_ca': x509_ca, 'crl': crl}
 
 
-#    REVIEW, how to do that properly
-#    def _finalize_(self):
-#        ctx = self.ctx
-#        if ctx:
-#            self.ctx = lltype.nullptr(SSL_CTX.TO)
-#            libssl_SSL_CTX_free(ctx)
+    def __del__(self):
+        # REVIEW, is this done properly? In RPython the a finalizer
+        # function is added
+        ctx = self.ctx
+        if ctx:
+            self.ctx = None
+            lib.SSL_CTX_free(ctx)
+
 
     def session_stats(self):
         stats = {}
@@ -1106,16 +1101,16 @@
         binary_mode = bool(binary_form)
         _list = []
         store = lib.SSL_CTX_get_cert_store(self.ctx)
-        objs = store.objs
+        objs = lib.X509_STORE_get0_objects(store)
         count = lib.sk_X509_OBJECT_num(objs)
         for i in range(count):
             obj = lib.sk_X509_OBJECT_value(objs, i)
-            _type = lib.Cryptography_X509_OBJECT_get_type(obj)
-            if _type != lib.Cryptography_X509_LU_X509:
+            _type = lib.X509_OBJECT_get_type(obj)
+            if _type != lib.X509_LU_X509:
                 # not a x509 cert
                 continue
             # CA for any purpose
-            cert = lib.Cryptography_X509_OBJECT_data_x509(obj)
+            cert = lib.X509_OBJECT_get0_X509(obj)
             if not lib.X509_check_ca(cert):
                 continue
             if binary_mode:
@@ -1138,7 +1133,7 @@
             lib.EC_KEY_free(key)
 
     def set_servername_callback(self, callback):
-        if not HAS_SNI or lib.Cryptography_NO_TLSEXT:
+        if not HAS_SNI or lib.Cryptography_OPENSSL_NO_TLSEXT:
             raise NotImplementedError("The TLS extension servername callback, "
                     "SSL_CTX_set_tlsext_servername_callback, "
                     "is not in the current OpenSSL library.")
@@ -1150,8 +1145,8 @@
             raise TypeError("not a callable object")
         scb = ServernameCallback(callback, self)
         self._set_hostname_handle = ffi.new_handle(scb)
-        lib.Cryptography_SSL_CTX_set_tlsext_servername_callback(self.ctx, _servername_callback)
-        lib.Cryptography_SSL_CTX_set_tlsext_servername_arg(self.ctx, self._set_hostname_handle)
+        lib.SSL_CTX_set_tlsext_servername_callback(self.ctx, _servername_callback)
+        lib.SSL_CTX_set_tlsext_servername_arg(self.ctx, self._set_hostname_handle)
 
     def _set_alpn_protocols(self, protos):
         if HAS_ALPN:
@@ -1160,7 +1155,7 @@
 
             if lib.SSL_CTX_set_alpn_protos(self.ctx,ffi.cast("unsigned char*", protocols), length):
                 return MemoryError()
-            handle = ffi.new_handle(self)
+            self._alpn_protocols_handle = handle = ffi.new_handle(self)
             lib.SSL_CTX_set_alpn_select_cb(self.ctx, select_alpn_callback, handle)
         else:
             raise NotImplementedError("The ALPN extension requires OpenSSL 1.0.2 or later.")
@@ -1187,7 +1182,7 @@
 
 
 
-if HAS_SNI and not lib.Cryptography_NO_TLSEXT:
+if HAS_SNI and not lib.Cryptography_OPENSSL_NO_TLSEXT:
     @ffi.callback("int(SSL*,int*,void*)")
     def _servername_callback(s, al, arg):
         scb = ffi.from_handle(arg)
@@ -1386,13 +1381,15 @@
         raise ValueError("num must be positive")
     buf = ffi.new("unsigned char[%d]" % count)
     if pseudo:
-        ok = lib.RAND_pseudo_bytes(buf, count)
+        # note by reaperhulk, RAND_pseudo_bytes is deprecated in 3.6 already,
+        # it is totally fine to just call RAND_bytes instead
+        ok = lib.RAND_bytes(buf, count)
         if ok == 1 or ok == 0:
             _bytes = _bytes_with_len(buf, count)
             return (_bytes, ok == 1)
     else:
         ok = lib.RAND_bytes(buf, count)
-        if ok == 1:
+        if ok == 1 or (pseudo and ok == 0):
             return _bytes_with_len(buf, count)
     raise ssl_error(None, errcode=lib.ERR_get_error())
 
@@ -1429,7 +1426,7 @@
                                  ffi.cast("unsigned char*",ctx.alpn_protocols), len(ctx.alpn_protocols),
                                  client_protocols, client_protocols_len)
 
-if lib.Cryptography_HAS_NPN_NEGOTIATED:
+if lib.OPENSSL_NPN_NEGOTIATED:
     @ffi.callback("int(SSL*,unsigned char **,unsigned char *,const unsigned char *,unsigned int,void *)")
     def select_npn_callback(ssl, out, outlen, server_protocols, server_protocols_len, args):
         ctx = ffi.from_handle(args)
@@ -1463,7 +1460,7 @@
         ret = lib.SSL_select_next_proto(out, outlen,
                                         server_protocols, server_protocols_len,
                                         client_protocols, client_protocols_len);
-        if alpn and ret != lib.Cryptography_OPENSSL_NPN_NEGOTIATED:
+        if alpn and ret != lib.OPENSSL_NPN_NEGOTIATED:
             return lib.SSL_TLSEXT_ERR_NOACK
 
         return lib.SSL_TLSEXT_ERR_OK
diff --git a/lib_pypy/_cffi_ssl/_stdssl/certificate.py b/lib_pypy/_cffi_ssl/_stdssl/certificate.py
--- a/lib_pypy/_cffi_ssl/_stdssl/certificate.py
+++ b/lib_pypy/_cffi_ssl/_stdssl/certificate.py
@@ -1,8 +1,8 @@
 import warnings
 import base64
 import textwrap
-from _openssl import ffi
-from _openssl import lib
+from _pypy_openssl import ffi
+from _pypy_openssl import lib
 from _cffi_ssl._stdssl.utility import _string_from_asn1, _str_with_len, _bytes_with_len
 from _cffi_ssl._stdssl.error import ssl_error, pyssl_error
 
@@ -30,7 +30,7 @@
     if (info == ffi.NULL):
         return None;
     if lib.sk_ACCESS_DESCRIPTION_num(info) == 0:
-        lib.AUTHORITY_INFO_ACCESS_free(info)
+        lib.sk_ACCESS_DESCRIPTION_free(info)
         return None
 
     lst = []
@@ -44,7 +44,7 @@
         uri = ad.location.d.uniformResourceIdentifier
         ostr = _str_with_len(uri.data, uri.length)
         lst.append(ostr)
-    lib.AUTHORITY_INFO_ACCESS_free(info)
+    lib.sk_ACCESS_DESCRIPTION_free(info)
 
     # convert to tuple or None
     if len(lst) == 0: return None
@@ -244,12 +244,9 @@
 
 
 def _get_crl_dp(certificate):
-    if lib.OPENSSL_VERSION_NUMBER < 0x10001000:
-        dps = lib.X509_get_ext_d2i(certificate, lib.NID_crl_distribution_points, ffi.NULL, ffi.NULL)
-    else:
-        # Calls x509v3_cache_extensions and sets up crldp
+    if lib.OPENSSL_VERSION_NUMBER >= 0x10001000:
         lib.X509_check_ca(certificate)
-        dps = lib.Cryptography_X509_get_crldp(certificate)
+    dps = lib.X509_get_ext_d2i(certificate, lib.NID_crl_distribution_points, ffi.NULL, ffi.NULL)
     if dps is ffi.NULL:
         return None
 
diff --git a/lib_pypy/_cffi_ssl/_stdssl/error.py b/lib_pypy/_cffi_ssl/_stdssl/error.py
--- a/lib_pypy/_cffi_ssl/_stdssl/error.py
+++ b/lib_pypy/_cffi_ssl/_stdssl/error.py
@@ -1,7 +1,7 @@
 import sys
 import traceback
-from _openssl import ffi
-from _openssl import lib
+from _pypy_openssl import ffi
+from _pypy_openssl import lib
 
 from _cffi_ssl._stdssl.utility import _string_from_asn1, _str_to_ffi_buffer, _str_from_buf
 from _cffi_ssl._stdssl.errorcodes import _error_codes, _lib_codes
diff --git a/lib_pypy/_cffi_ssl/_stdssl/errorcodes.py b/lib_pypy/_cffi_ssl/_stdssl/errorcodes.py
--- a/lib_pypy/_cffi_ssl/_stdssl/errorcodes.py
+++ b/lib_pypy/_cffi_ssl/_stdssl/errorcodes.py
@@ -1,7 +1,7 @@
 # File generated by tools/make_ssl_data.py
 # Generated on 2016-11-10T17:38:59.402032
 
-from _openssl import ffi, lib 
+from _pypy_openssl import ffi, lib 
 _lib_codes = []
 _lib_codes.append(("PEM", lib.ERR_LIB_PEM))
 _lib_codes.append(("SSL", lib.ERR_LIB_SSL))
diff --git a/lib_pypy/_cffi_ssl/_stdssl/utility.py b/lib_pypy/_cffi_ssl/_stdssl/utility.py
--- a/lib_pypy/_cffi_ssl/_stdssl/utility.py
+++ b/lib_pypy/_cffi_ssl/_stdssl/utility.py
@@ -1,6 +1,6 @@
 import sys
-from _openssl import ffi
-from _openssl import lib
+from _pypy_openssl import ffi
+from _pypy_openssl import lib
 
 def _string_from_asn1(asn1):
     data = lib.ASN1_STRING_data(asn1)
diff --git a/lib_pypy/_ssl_build.py b/lib_pypy/_ssl_build.py
--- a/lib_pypy/_ssl_build.py
+++ b/lib_pypy/_ssl_build.py
@@ -2,7 +2,52 @@
 from _cffi_ssl import _cffi_src
 sys.modules['_cffi_src'] = _cffi_src
 #
-from _cffi_ssl._cffi_src.build_openssl import ffi
+from _cffi_ssl._cffi_src.build_openssl import (build_ffi_for_binding,
+        _get_openssl_libraries, extra_link_args, compiler_type)
+
+ffi = build_ffi_for_binding(
+    module_name="_pypy_openssl",
+    module_prefix="_cffi_src.openssl.",
+    modules=[
+        # This goes first so we can define some cryptography-wide symbols.
+        "cryptography",
+
+        "aes",
+        "asn1",
+        "bignum",
+        "bio",
+        "cmac",
+        "cms",
+        "conf",
+        "crypto",
+        "dh",
+        "dsa",
+        "ec",
+        "ecdh",
+        "ecdsa",
+        "engine",
+        "err",
+        "evp",
+        "hmac",
+        "nid",
+        "objects",
+        "ocsp",
+        "opensslv",
+        "pem",
+        "pkcs12",
+        "rand",
+        "rsa",
+        "ssl",
+        "x509",
+        "x509name",
+        "x509v3",
+        "x509_vfy",
+        "pkcs7",
+        "callbacks",
+    ],
+    libraries=_get_openssl_libraries(sys.platform),
+    extra_link_args=extra_link_args(compiler_type()),
+)
 
 if __name__ == '__main__':
     ffi.compile()


More information about the pypy-commit mailing list