Author: Amaury Forgeot d'Arc <[email protected]>
Branch: py3.6
Changeset: r94414:6dc2dbf20397
Date: 2018-04-22 20:41 +0200
http://bitbucket.org/pypy/pypy/changeset/6dc2dbf20397/

Log:    Implement SSLSession.

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
@@ -198,6 +198,8 @@
 const char *SSL_get_cipher_list(const SSL *, int);
 Cryptography_STACK_OF_SSL_CIPHER *SSL_get_ciphers(const SSL *);
 
+int SSL_is_init_finished(const SSL*);
+
 /*  context */
 void SSL_CTX_free(SSL_CTX *);
 long SSL_CTX_set_timeout(SSL_CTX *, long);
@@ -265,6 +267,10 @@
 
 SSL_SESSION *SSL_get_session(const SSL *);
 const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *, unsigned int *);
+long SSL_SESSION_get_time(const SSL_SESSION *);
+long SSL_SESSION_get_timeout(const SSL_SESSION *);
+int SSL_SESSION_has_ticket(const SSL_SESSION *);
+long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *);
 
 /* not a macro, but older OpenSSLs don't pass the args as const */
 char *SSL_CIPHER_description(const SSL_CIPHER *, char *, int);
@@ -509,6 +515,14 @@
     memcpy(out, session->master_key, outlen);
     return outlen;
 }
+
+int SSL_SESSION_has_ticket(const SSL_SESSION *s) {
+    return (s->tlsext_ticklen > 0) ? 1 : 0;
+}
+unsigned long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s)
+{
+    return s->tlsext_tick_lifetime_hint;
+}
 #endif
 
 static const long Cryptography_HAS_SECURE_RENEGOTIATION = 1;
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
@@ -693,7 +693,20 @@
     @property
     def session(self):
         "Get / set SSLSession."
-        return None
+        return Session(self)
+
+    @session.setter
+    def session(self, value):
+        if not isinstance(value, Session):
+            raise TypeError("Value is not a SSLSession.")
+        if self.ctx.ctx != value._ctx.ctx:
+            raise ValueError("Session refers to a different SSLContext.")
+        if self.socket_type != SSL_CLIENT:
+            raise ValueError("Cannot set session for server-side SSLSocket.")
+        if lib.SSL_is_init_finished(self.ssl):
+            raise ValueError("Cannot set session after handshake.")
+        if not lib.SSL_set_session(self.ssl, value._session):
+            raise pyssl_error(self, 0)
 
     @property
     def session_reused(self):
@@ -727,6 +740,43 @@
     return (cipher_name, cipher_protocol, bits)
 
 
+class Session(object):
+    def __new__(cls, ssl):
+        self = object.__new__(cls)
+        session = lib.SSL_get1_session(ssl.ssl)
+        if not session:
+            return None
+        self._session = ffi.gc(session, lib.SSL_SESSION_free)
+        self._ctx = ssl.ctx
+        return self
+
+    def __eq__(self, other):
+        if not isinstance(other, Session):
+            return NotImplemented;
+        return self.id == other.id
+
+    @property
+    def id(self):
+        lenp = ffi.new("unsigned int*")
+        id = lib.SSL_SESSION_get_id(self._session, lenp)
+        return ffi.string(id, lenp[0])
+
+    @property
+    def time(self):
+        return lib.SSL_SESSION_get_time(self._session)
+
+    @property
+    def timeout(self):
+        return lib.SSL_SESSION_get_timeout(self._session)
+
+    @property
+    def has_ticket(self):
+        return bool(lib.SSL_SESSION_has_ticket(self._session))
+
+    @property
+    def ticket_lifetime_hint(self):
+        return lib.SSL_SESSION_get_ticket_lifetime_hint(self._session)
+
 
 SSL_CTX_STATS_NAMES = """
     number connect connect_good connect_renegotiate accept accept_good
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to