Author: Brian Kearns <[email protected]>
Branch: stdlib-2.7.9
Changeset: r75040:f92139314948
Date: 2014-12-19 17:26 -0500
http://bitbucket.org/pypy/pypy/changeset/f92139314948/

Log:    start working on _ssl

diff --git a/pypy/module/_ssl/__init__.py b/pypy/module/_ssl/__init__.py
--- a/pypy/module/_ssl/__init__.py
+++ b/pypy/module/_ssl/__init__.py
@@ -5,9 +5,19 @@
     See the socket module for documentation."""
 
     interpleveldefs = {
-        'sslwrap': 'interp_ssl.sslwrap',
-        'SSLError': 'interp_ssl.get_error(space)',
         '_test_decode_cert': 'interp_ssl._test_decode_cert',
+        'txt2obj': 'interp_ssl.txt2obj',
+        'nid2obj': 'interp_ssl.nid2obj',
+
+        'SSLError': "interp_ssl.get_exception_class(space, 'w_sslerror')",
+        'SSLZeroReturnError': "interp_ssl.get_exception_class(space, 
'w_sslzeroreturnerror')",
+        'SSLWantReadError': "interp_ssl.get_exception_class(space, 
'w_sslwantreaderror')",
+        'SSLWantWriteError': "interp_ssl.get_exception_class(space, 
'w_sslwantwriteerror')",
+        'SSLSyscallError': "interp_ssl.get_exception_class(space, 
'w_sslsyscallerror')",
+        'SSLEOFError': "interp_ssl.get_exception_class(space, 
'w_ssleoferror')",
+
+        '_SSLSocket': 'interp_ssl._SSLSocket',
+        '_SSLContext': 'interp_ssl._SSLContext',
     }
 
     appleveldefs = {
diff --git a/pypy/module/_ssl/interp_ssl.py b/pypy/module/_ssl/interp_ssl.py
--- a/pypy/module/_ssl/interp_ssl.py
+++ b/pypy/module/_ssl/interp_ssl.py
@@ -4,7 +4,7 @@
 from rpython.rtyper.lltypesystem import lltype, rffi
 
 from pypy.interpreter.baseobjspace import W_Root
-from pypy.interpreter.error import OperationError
+from pypy.interpreter.error import OperationError, oefmt
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.typedef import TypeDef
 from pypy.module._socket import interp_socket
@@ -50,6 +50,16 @@
 constants["CERT_OPTIONAL"] = PY_SSL_CERT_OPTIONAL
 constants["CERT_REQUIRED"] = PY_SSL_CERT_REQUIRED
 
+constants["VERIFY_DEFAULT"] = 0
+constants["VERIFY_CRL_CHECK_LEAF"] = X509_V_FLAG_CRL_CHECK
+constants["VERIFY_CRL_CHECK_CHAIN"] = 
X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL
+constants["VERIFY_X509_STRICT"] = X509_V_FLAG_X509_STRICT
+
+constants["HAS_SNI"] = HAS_SNI
+constants["HAS_TLS_UNIQUE"] = HAVE_OPENSSL_FINISHED
+constants["HAS_ECDH"] = not OPENSSL_NO_ECDH
+constants["HAS_NPN"] = OPENSSL_NPN_NEGOTIATED
+
 if not OPENSSL_NO_SSL2:
     constants["PROTOCOL_SSLv2"]  = PY_SSL_VERSION_SSL2
 if not OPENSSL_NO_SSL3:
@@ -64,11 +74,13 @@
 ver, fix    = divmod(ver, 256)
 ver, minor  = divmod(ver, 256)
 ver, major  = divmod(ver, 256)
-constants["OPENSSL_VERSION_INFO"] = (major, minor, fix, patch, status)
+version_info = (major, minor, fix, patch, status)
+constants["OPENSSL_VERSION_INFO"] = version_info
+constants["_OPENSSL_API_VERSION"] = version_info
 constants["OPENSSL_VERSION"] = SSLEAY_VERSION
 
-def ssl_error(space, msg, errno=0):
-    w_exception_class = get_error(space)
+def ssl_error(space, msg, errno=0, exc='w_sslerror'):
+    w_exception_class = get_exception_class(space, exc)
     w_exception = space.call_function(w_exception_class,
                                       space.wrap(errno), space.wrap(msg))
     return OperationError(w_exception_class, w_exception)
@@ -111,41 +123,54 @@
         return space.wrap(bytes)
 
 
-class SSLObject(W_Root):
-    def __init__(self, space):
+class _SSLSocket(W_Root):
+    @staticmethod
+    def descr_new(space, sslctx, w_sock, socket_type, hostname, w_ssl_sock):
+        self = _SSLSocket()
+
         self.space = space
-        self.w_socket = None
-        self.ctx = lltype.nullptr(SSL_CTX.TO)
-        self.ssl = lltype.nullptr(SSL.TO)
+        self.ctx = sslctx
         self.peer_cert = lltype.nullptr(X509.TO)
-        self._server = lltype.malloc(rffi.CCHARP.TO, X509_NAME_MAXLEN,
-                                     flavor='raw')
-        self._server[0] = '\0'
-        self._issuer = lltype.malloc(rffi.CCHARP.TO, X509_NAME_MAXLEN,
-                                     flavor='raw')
-        self._issuer[0] = '\0'
         self.shutdown_seen_zero = False
+        self.handshake_done = False
 
-    def server(self, space):
-        return space.wrap(rffi.charp2str(self._server))
+        sock_fd = space.int_w(space.call_method(w_sock, "fileno"))
+        self.ssl = libssl_SSL_new(sslctx.ctx) # new ssl struct
+        libssl_SSL_set_fd(self.ssl, sock_fd) # set the socket for SSL
+        # The ACCEPT_MOVING_WRITE_BUFFER flag is necessary because the address
+        # of a str object may be changed by the garbage collector.
+        libssl_SSL_set_mode(
+            self.ssl, SSL_MODE_AUTO_RETRY | 
SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)
 
-    def issuer(self, space):
-        return space.wrap(rffi.charp2str(self._issuer))
+        # If the socket is in non-blocking mode or timeout mode, set the BIO
+        # to non-blocking mode (blocking is the default)
+        w_timeout = space.call_method(w_sock, "gettimeout")
+        has_timeout = not space.is_none(w_timeout)
+        if has_timeout:
+            # Set both the read and write BIO's to non-blocking mode
+            libssl_BIO_set_nbio(libssl_SSL_get_rbio(self.ssl), 1)
+            libssl_BIO_set_nbio(libssl_SSL_get_wbio(self.ssl), 1)
+
+        if socket_type == PY_SSL_CLIENT:
+            libssl_SSL_set_connect_state(self.ssl)
+        else:
+            libssl_SSL_set_accept_state(self.ssl)
+
+        self.socket_type = socket_type
+        self.w_socket = w_sock
+        self.w_ssl_sock = None
+        return self
 
     def __del__(self):
-        self.enqueue_for_destruction(self.space, SSLObject.destructor,
+        self.enqueue_for_destruction(self.space, _SSLSocket.destructor,
                                      '__del__() method of ')
 
     def destructor(self):
-        assert isinstance(self, SSLObject)
+        assert isinstance(self, _SSLSocket)
         if self.peer_cert:
             libssl_X509_free(self.peer_cert)
         if self.ssl:
             libssl_SSL_free(self.ssl)
-        if self.ctx:
-            libssl_SSL_CTX_free(self.ctx)
-        lltype.free(self._server, flavor='raw')
-        lltype.free(self._issuer, flavor='raw')
 
     @unwrap_spec(data='bufferstr')
     def write(self, space, data):
@@ -205,7 +230,7 @@
         return space.wrap(count)
 
     @unwrap_spec(num_bytes=int)
-    def read(self, space, num_bytes=1024):
+    def read(self, space, num_bytes):
         """read([len]) -> string
 
         Read up to len bytes from the SSL socket."""
@@ -300,13 +325,7 @@
         if self.peer_cert:
             libssl_X509_free(self.peer_cert)
         self.peer_cert = libssl_SSL_get_peer_certificate(self.ssl)
-        if self.peer_cert:
-            libssl_X509_NAME_oneline(
-                libssl_X509_get_subject_name(self.peer_cert),
-                self._server, X509_NAME_MAXLEN)
-            libssl_X509_NAME_oneline(
-                libssl_X509_get_issuer_name(self.peer_cert),
-                self._issuer, X509_NAME_MAXLEN)
+        self.handshake_done = True
 
     def shutdown(self, space):
         # Guard against closed socket
@@ -625,110 +644,17 @@
 
     return space.newtuple([w_name, w_value])
 
-SSLObject.typedef = TypeDef("SSLObject",
-    server = interp2app(SSLObject.server),
-    issuer = interp2app(SSLObject.issuer),
-    write = interp2app(SSLObject.write),
-    pending = interp2app(SSLObject.pending),
-    read = interp2app(SSLObject.read),
-    do_handshake = interp2app(SSLObject.do_handshake),
-    shutdown = interp2app(SSLObject.shutdown),
-    cipher = interp2app(SSLObject.cipher),
-    peer_certificate = interp2app(SSLObject.peer_certificate),
+_SSLSocket.typedef = TypeDef("_SSLSocket",
+    do_handshake = interp2app(_SSLSocket.do_handshake),
+    write = interp2app(_SSLSocket.write),
+    read = interp2app(_SSLSocket.read),
+    pending = interp2app(_SSLSocket.pending),
+    peer_certificate = interp2app(_SSLSocket.peer_certificate),
+    cipher = interp2app(_SSLSocket.cipher),
+    shutdown = interp2app(_SSLSocket.shutdown),
 )
 
 
-def new_sslobject(space, w_sock, side, w_key_file, w_cert_file,
-                  cert_mode, protocol, w_cacerts_file, w_ciphers):
-    ss = SSLObject(space)
-
-    sock_fd = space.int_w(space.call_method(w_sock, "fileno"))
-    w_timeout = space.call_method(w_sock, "gettimeout")
-    has_timeout = not space.is_none(w_timeout)
-    key_file = space.str_or_None_w(w_key_file)
-    cert_file = space.str_or_None_w(w_cert_file)
-    cacerts_file = space.str_or_None_w(w_cacerts_file)
-    ciphers = space.str_or_None_w(w_ciphers)
-
-    if side == PY_SSL_SERVER and (not key_file or not cert_file):
-        raise ssl_error(space, "Both the key & certificate files "
-                        "must be specified for server-side operation")
-
-    # set up context
-    if protocol == PY_SSL_VERSION_TLS1:
-        method = libssl_TLSv1_method()
-    elif protocol == PY_SSL_VERSION_SSL3 and not OPENSSL_NO_SSL3:
-        method = libssl_SSLv3_method()
-    elif protocol == PY_SSL_VERSION_SSL2 and not OPENSSL_NO_SSL2:
-        method = libssl_SSLv2_method()
-    elif protocol == PY_SSL_VERSION_SSL23:
-        method = libssl_SSLv23_method()
-    else:
-        raise ssl_error(space, "Invalid SSL protocol variant specified")
-    ss.ctx = libssl_SSL_CTX_new(method)
-    if not ss.ctx:
-        raise ssl_error(space, "Could not create SSL context")
-
-    if ciphers:
-        ret = libssl_SSL_CTX_set_cipher_list(ss.ctx, ciphers)
-        if ret == 0:
-            raise ssl_error(space, "No cipher can be selected.")
-
-    if cert_mode != PY_SSL_CERT_NONE:
-        if not cacerts_file:
-            raise ssl_error(space,
-                            "No root certificates specified for "
-                            "verification of other-side certificates.")
-        ret = libssl_SSL_CTX_load_verify_locations(ss.ctx, cacerts_file, None)
-        if ret != 1:
-            raise _ssl_seterror(space, None, 0)
-
-    if key_file:
-        ret = libssl_SSL_CTX_use_PrivateKey_file(ss.ctx, key_file,
-                                                 SSL_FILETYPE_PEM)
-        if ret < 1:
-            raise ssl_error(space, "SSL_CTX_use_PrivateKey_file error")
-
-        ret = libssl_SSL_CTX_use_certificate_chain_file(ss.ctx, cert_file)
-        if ret < 1:
-            raise ssl_error(space, "SSL_CTX_use_certificate_chain_file error")
-
-    # ssl compatibility
-    options = SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
-    if protocol != PY_SSL_VERSION_SSL2:
-        # SSLv2 is extremely broken, don't use it unless a user specifically
-        # requests it
-        options |= SSL_OP_NO_SSLv2
-    libssl_SSL_CTX_set_options(ss.ctx, options)
-
-    verification_mode = SSL_VERIFY_NONE
-    if cert_mode == PY_SSL_CERT_OPTIONAL:
-        verification_mode = SSL_VERIFY_PEER
-    elif cert_mode == PY_SSL_CERT_REQUIRED:
-        verification_mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT
-    libssl_SSL_CTX_set_verify(ss.ctx, verification_mode, None)
-    ss.ssl = libssl_SSL_new(ss.ctx) # new ssl struct
-    libssl_SSL_set_fd(ss.ssl, sock_fd) # set the socket for SSL
-    # The ACCEPT_MOVING_WRITE_BUFFER flag is necessary because the address
-    # of a str object may be changed by the garbage collector.
-    libssl_SSL_set_mode(
-        ss.ssl, SSL_MODE_AUTO_RETRY | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)
-
-    # If the socket is in non-blocking mode or timeout mode, set the BIO
-    # to non-blocking mode (blocking is the default)
-    if has_timeout:
-        # Set both the read and write BIO's to non-blocking mode
-        libssl_BIO_set_nbio(libssl_SSL_get_rbio(ss.ssl), 1)
-        libssl_BIO_set_nbio(libssl_SSL_get_wbio(ss.ssl), 1)
-
-    if side == PY_SSL_CLIENT:
-        libssl_SSL_set_connect_state(ss.ssl)
-    else:
-        libssl_SSL_set_accept_state(ss.ssl)
-
-    ss.w_socket = w_sock
-    return ss
-
 def checkwait(space, w_sock, writing):
     """If the socket has a timeout, do a select()/poll() on the socket.
     The argument writing indicates the direction.
@@ -843,24 +769,25 @@
     return ssl_error(space, errstr, errval)
 
 
-@unwrap_spec(side=int, cert_mode=int, protocol=int)
-def sslwrap(space, w_socket, side, w_key_file=None, w_cert_file=None,
-            cert_mode=PY_SSL_CERT_NONE, protocol=PY_SSL_VERSION_SSL23,
-            w_cacerts_file=None, w_ciphers=None):
-    """sslwrap(socket, side, [keyfile, certfile]) -> sslobject"""
-    return space.wrap(new_sslobject(
-        space, w_socket, side, w_key_file, w_cert_file,
-        cert_mode, protocol,
-        w_cacerts_file, w_ciphers))
-
 class Cache:
     def __init__(self, space):
         w_socketerror = interp_socket.get_error(space, "error")
-        self.w_error = space.new_exception_class(
+        self.w_sslerror = space.new_exception_class(
             "_ssl.SSLError", w_socketerror)
+        self.w_sslzeroreturnerror = space.new_exception_class(
+            "_ssl.SSLZeroReturnError", self.w_sslerror)
+        self.w_sslwantreaderror = space.new_exception_class(
+            "_ssl.SSLWantReadError", self.w_sslerror)
+        self.w_sslwantwriteerror = space.new_exception_class(
+            "_ssl.SSLWantWriteError", self.w_sslerror)
+        self.w_sslsyscallerror = space.new_exception_class(
+            "_ssl.SSLSyscallError", self.w_sslerror)
+        self.w_ssleoferror = space.new_exception_class(
+            "_ssl.SSLEOFError", self.w_sslerror)
 
-def get_error(space):
-    return space.fromcache(Cache).w_error
+def get_exception_class(space, name):
+    return getattr(space.fromcache(Cache), name)
+
 
 @unwrap_spec(filename=str, verbose=bool)
 def _test_decode_cert(space, filename, verbose=True):
@@ -882,3 +809,76 @@
             libssl_X509_free(x)
     finally:
         libssl_BIO_free(cert)
+
+
+class _SSLContext(W_Root):
+    @staticmethod
+    @unwrap_spec(protocol=int)
+    def descr_new(space, w_subtype, protocol):
+        if protocol == PY_SSL_VERSION_TLS1:
+            method = libssl_TLSv1_method()
+        elif protocol == PY_SSL_VERSION_SSL3 and not OPENSSL_NO_SSL3:
+            method = libssl_SSLv3_method()
+        elif protocol == PY_SSL_VERSION_SSL2 and not OPENSSL_NO_SSL2:
+            method = libssl_SSLv2_method()
+        elif protocol == PY_SSL_VERSION_SSL23:
+            method = libssl_SSLv23_method()
+        else:
+            raise ssl_error(space, "invalid protocol version")
+        ctx = libssl_SSL_CTX_new(method)
+        if not ctx:
+            raise ssl_error(space, "failed to allocate SSL context")
+
+        self = space.allocate_instance(_SSLContext, w_subtype)
+        self.ctx = ctx
+        return self
+
+    @unwrap_spec(server_side=int)
+    def descr_wrap_socket(self, space, w_sock, server_side, 
w_server_hostname=None, w_ssl_sock=None):
+        return _SSLSocket.descr_new(space, self, w_sock, server_side, 
w_server_hostname, w_ssl_sock)
+
+    @unwrap_spec(cipherlist=str)
+    def descr_set_ciphers(self, space, cipherlist):
+        ret = libssl_SSL_CTX_set_cipher_list(self.ctx, cipherlist)
+        if ret == 0:
+            libssl_ERR_clear_error()
+            raise ssl_error(space, "No cipher can be selected.")
+
+_SSLContext.typedef = TypeDef("_SSLContext",
+    __module__ = "_ssl",
+    __new__ = interp2app(_SSLContext.descr_new),
+    _wrap_socket = interp2app(_SSLContext.descr_wrap_socket),
+    set_ciphers = interp2app(_SSLContext.descr_set_ciphers),
+)
+
+
+def _asn1obj2py(space, obj):
+    nid = libssl_OBJ_obj2nid(obj)
+    if nid == NID_undef:
+        raise oefmt(space.w_ValueError, "Unknown object")
+    with rffi.scoped_alloc_buffer(100) as buf:
+        buflen = libssl_OBJ_obj2txt(buf.raw, 100, obj, 1)
+        if buflen < 0:
+            raise _ssl_seterror(space, None, 0)
+        if buflen:
+            w_buf = space.wrap(buf.str(buflen))
+        else:
+            w_buf = space.w_None
+    w_sn = space.wrap(rffi.charp2str(libssl_OBJ_nid2sn(nid)))
+    w_ln = space.wrap(rffi.charp2str(libssl_OBJ_nid2ln(nid)))
+    return space.newtuple([space.wrap(nid), w_sn, w_ln, w_buf])
+
+
+@unwrap_spec(txt=str, name=bool)
+def txt2obj(space, txt, name=False):
+    obj = libssl_OBJ_txt2obj(txt, name)
+    if not obj:
+        raise oefmt(space.w_ValueError, "unknown object '%s'", txt)
+    result = _asn1obj2py(space, obj)
+    libssl_ASN1_OBJECT_free(obj)
+    return result
+
+
+@unwrap_spec(nid=int)
+def nid2obj(space, nid):
+    return space.newtuple([])
diff --git a/pypy/module/_ssl/test/test_ssl.py 
b/pypy/module/_ssl/test/test_ssl.py
--- a/pypy/module/_ssl/test/test_ssl.py
+++ b/pypy/module/_ssl/test/test_ssl.py
@@ -130,20 +130,6 @@
         self.s.close()
         del ss; gc.collect()
 
-    def test_server(self):
-        import socket, gc
-        ss = socket.ssl(self.s)
-        assert isinstance(ss.server(), str)
-        self.s.close()
-        del ss; gc.collect()
-
-    def test_issuer(self):
-        import socket, gc
-        ss = socket.ssl(self.s)
-        assert isinstance(ss.issuer(), str)
-        self.s.close()
-        del ss; gc.collect()
-
     def test_write(self):
         import socket, gc
         ss = socket.ssl(self.s)
@@ -157,9 +143,10 @@
     def test_read(self):
         import socket, gc
         ss = socket.ssl(self.s)
+        raises(TypeError, ss.read)
         raises(TypeError, ss.read, "foo")
         ss.write("hello\n")
-        data = ss.read()
+        data = ss.read(10)
         assert isinstance(data, str)
         self.s.close()
         del ss; gc.collect()
diff --git a/rpython/rlib/ropenssl.py b/rpython/rlib/ropenssl.py
--- a/rpython/rlib/ropenssl.py
+++ b/rpython/rlib/ropenssl.py
@@ -69,6 +69,8 @@
         "SSLEAY_VERSION", "SSLeay_version(SSLEAY_VERSION)")
     OPENSSL_NO_SSL2 = rffi_platform.Defined("OPENSSL_NO_SSL2")
     OPENSSL_NO_SSL3 = rffi_platform.Defined("OPENSSL_NO_SSL3")
+    OPENSSL_NO_ECDH = rffi_platform.Defined("OPENSSL_NO_ECDH")
+    OPENSSL_NPN_NEGOTIATED = rffi_platform.Defined("OPENSSL_NPN_NEGOTIATED")
     SSL_FILETYPE_PEM = rffi_platform.ConstantInteger("SSL_FILETYPE_PEM")
     SSL_OP_ALL = rffi_platform.ConstantInteger("SSL_OP_ALL")
     SSL_OP_NO_SSLv2 = rffi_platform.ConstantInteger("SSL_OP_NO_SSLv2")
@@ -80,6 +82,9 @@
     SSL_VERIFY_NONE = rffi_platform.ConstantInteger("SSL_VERIFY_NONE")
     SSL_VERIFY_PEER = rffi_platform.ConstantInteger("SSL_VERIFY_PEER")
     SSL_VERIFY_FAIL_IF_NO_PEER_CERT = 
rffi_platform.ConstantInteger("SSL_VERIFY_FAIL_IF_NO_PEER_CERT")
+    X509_V_FLAG_CRL_CHECK = 
rffi_platform.ConstantInteger("X509_V_FLAG_CRL_CHECK")
+    X509_V_FLAG_CRL_CHECK_ALL = 
rffi_platform.ConstantInteger("X509_V_FLAG_CRL_CHECK_ALL")
+    X509_V_FLAG_X509_STRICT = 
rffi_platform.ConstantInteger("X509_V_FLAG_X509_STRICT")
     SSL_ERROR_WANT_READ = rffi_platform.ConstantInteger(
         "SSL_ERROR_WANT_READ")
     SSL_ERROR_WANT_WRITE = rffi_platform.ConstantInteger(
@@ -97,6 +102,7 @@
     SSL_MODE_AUTO_RETRY = rffi_platform.ConstantInteger("SSL_MODE_AUTO_RETRY")
     SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER = 
rffi_platform.ConstantInteger("SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER")
 
+    NID_undef = rffi_platform.ConstantInteger("NID_undef")
     NID_subject_alt_name = 
rffi_platform.ConstantInteger("NID_subject_alt_name")
     GEN_DIRNAME = rffi_platform.ConstantInteger("GEN_DIRNAME")
     GEN_EMAIL = rffi_platform.ConstantInteger("GEN_EMAIL")
@@ -173,7 +179,10 @@
 OBJ_NAME = rffi.CArrayPtr(OBJ_NAME_st)
 
 HAVE_OPENSSL_RAND = OPENSSL_VERSION_NUMBER >= 0x0090500f
+HAVE_OPENSSL_FINISHED = OPENSSL_VERSION_NUMBER >= 0x0090500f
 HAVE_SSL_CTX_CLEAR_OPTIONS = OPENSSL_VERSION_NUMBER >= 0x009080df
+if OPENSSL_VERSION_NUMBER < 0x0090800f and not OPENSSL_NO_ECDH:
+    OPENSSL_NO_ECDH = True
 
 def external(name, argtypes, restype, **kw):
     kw['compilation_info'] = eci
@@ -265,6 +274,11 @@
 
 ssl_external('OBJ_obj2txt',
              [rffi.CCHARP, rffi.INT, ASN1_OBJECT, rffi.INT], rffi.INT)
+ssl_external('OBJ_obj2nid', [ASN1_OBJECT], rffi.INT)
+ssl_external('OBJ_nid2sn', [rffi.INT], rffi.CCHARP)
+ssl_external('OBJ_nid2ln', [rffi.INT], rffi.CCHARP)
+ssl_external('OBJ_txt2obj', [rffi.CCHARP, rffi.INT], ASN1_OBJECT)
+ssl_external('ASN1_OBJECT_free', [ASN1_OBJECT], lltype.Void)
 ssl_external('ASN1_STRING_data', [ASN1_STRING], rffi.CCHARP)
 ssl_external('ASN1_STRING_length', [ASN1_STRING], rffi.INT)
 ssl_external('ASN1_STRING_to_UTF8', [rffi.CCHARPP, ASN1_STRING], rffi.INT)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to