From 731119ba9add87f47c219712aed70ff967485734 Mon Sep 17 00:00:00 2001 From: David Strauss Date: Tue, 4 Oct 2011 16:52:05 -0700 Subject: Minimal addition of set_session_cache_mode() support. --- OpenSSL/ssl/context.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/OpenSSL/ssl/context.c b/OpenSSL/ssl/context.c index aa4976d..b2d3431 100644 --- a/OpenSSL/ssl/context.c +++ b/OpenSSL/ssl/context.c @@ -984,6 +984,24 @@ ssl_Context_set_timeout(ssl_ContextObj *self, PyObject *args) return PyLong_FromLong(ret); } +static char ssl_Context_set_session_cache_mode_doc[] = "\n\ +Set session cache mode\n\ +\n\ +:param timeout: The mode as an integer\n\ +:return: The previous set cache mode\n\ +"; +static PyObject * +ssl_Context_set_session_cache_mode(ssl_ContextObj *self, PyObject *args) +{ + long t, ret; + + if (!PyArg_ParseTuple(args, "l:set_session_cache_mode", &t)) + return NULL; + + ret = SSL_CTX_set_session_cache_mode(self->ctx, t); + return PyLong_FromLong(ret); +} + static char ssl_Context_get_timeout_doc[] = "\n\ Get the session timeout\n\ \n\ @@ -1186,6 +1204,7 @@ static PyMethodDef ssl_Context_methods[] = { ADD_METHOD(add_client_ca), ADD_METHOD(set_timeout), ADD_METHOD(get_timeout), + ADD_METHOD(set_session_cache_mode), ADD_METHOD(set_info_callback), ADD_METHOD(get_app_data), ADD_METHOD(set_app_data), -- cgit v1.2.1 From 313bf01183d9831e59a9310610acf5a35621c7aa Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Wed, 8 Feb 2012 13:02:49 -0500 Subject: Grab Context.{set,get}_session_cache_mode from the sessions branch, plus the unit tests. --- OpenSSL/ssl/context.c | 34 ++++++++++++++++ OpenSSL/ssl/ssl.c | 14 +++++++ OpenSSL/test/test_ssl.py | 104 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 151 insertions(+), 1 deletion(-) diff --git a/OpenSSL/ssl/context.c b/OpenSSL/ssl/context.c index aa4976d..a92a476 100644 --- a/OpenSSL/ssl/context.c +++ b/OpenSSL/ssl/context.c @@ -717,6 +717,38 @@ ssl_Context_set_session_id(ssl_ContextObj *self, PyObject *args) } } +static char ssl_Context_set_session_cache_mode_doc[] = "\n\ +Enable/disable session caching and the mode used.\n\ +\n\ +@param mode: One or more of the SESS_CACHE_* flags (combine using bitwise or)\n\ +@return: The previously set caching mode.n\ +"; +static PyObject * +ssl_Context_set_session_cache_mode(ssl_ContextObj *self, PyObject *args) +{ + long mode, result; + + if (!PyArg_ParseTuple(args, "l:set_session_cache_mode", &mode)) + return NULL; + + result = SSL_CTX_set_session_cache_mode(self->ctx, mode); + return PyLong_FromLong(result); + +} + +static char ssl_Context_get_session_cache_mode_doc[] = "\n\ +Returns the currently used cache mode.\n\ +\n\ +@return: The currently used cache mode.\n\ +"; +static PyObject * +ssl_Context_get_session_cache_mode(ssl_ContextObj *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, ":get_session_cache_mode")) + return NULL; + return PyLong_FromLong((long)SSL_CTX_get_session_cache_mode(self->ctx)); +} + static char ssl_Context_set_verify_doc[] = "\n\ Set the verify mode and verify callback\n\ \n\ @@ -1176,6 +1208,8 @@ static PyMethodDef ssl_Context_methods[] = { ADD_METHOD(check_privatekey), ADD_METHOD(load_client_ca), ADD_METHOD(set_session_id), + ADD_METHOD(set_session_cache_mode), + ADD_METHOD(get_session_cache_mode), ADD_METHOD(set_verify), ADD_METHOD(set_verify_depth), ADD_METHOD(get_verify_mode), diff --git a/OpenSSL/ssl/ssl.c b/OpenSSL/ssl/ssl.c index cee3661..a68f447 100644 --- a/OpenSSL/ssl/ssl.c +++ b/OpenSSL/ssl/ssl.c @@ -274,6 +274,20 @@ do { \ PyModule_AddIntConstant(module, "SSLEAY_PLATFORM", SSLEAY_PLATFORM); PyModule_AddIntConstant(module, "SSLEAY_DIR", SSLEAY_DIR); + /* Cache modes */ +#define CACHE_MODE(mode) \ + PyModule_AddIntConstant(module, "SESS_CACHE_" #mode, SSL_SESS_CACHE_##mode) + + CACHE_MODE(OFF); + CACHE_MODE(CLIENT); + CACHE_MODE(SERVER); + CACHE_MODE(BOTH); + CACHE_MODE(NO_AUTO_CLEAR); + CACHE_MODE(NO_INTERNAL_LOOKUP); + CACHE_MODE(NO_INTERNAL_STORE); + CACHE_MODE(NO_INTERNAL); +#undef CACHE_MODE + /* Straight up version number */ PyModule_AddIntConstant(module, "OPENSSL_VERSION_NUMBER", OPENSSL_VERSION_NUMBER); diff --git a/OpenSSL/test/test_ssl.py b/OpenSSL/test/test_ssl.py index c9417b9..cda6d53 100644 --- a/OpenSSL/test/test_ssl.py +++ b/OpenSSL/test/test_ssl.py @@ -10,7 +10,7 @@ from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK from sys import platform, version_info from socket import error, socket from os import makedirs -from os.path import join +from os.path import join, dirname from unittest import main from weakref import ref @@ -27,6 +27,11 @@ from OpenSSL.SSL import OP_NO_SSLv2, OP_NO_SSLv3, OP_SINGLE_DH_USE from OpenSSL.SSL import ( VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE) +from OpenSSL.SSL import ( + SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH, + SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP, + SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL) + from OpenSSL.SSL import ( Error, SysCallError, WantReadError, ZeroReturnError, SSLeay_version) from OpenSSL.SSL import Context, ContextType, Connection, ConnectionType @@ -909,6 +914,37 @@ class ContextTests(TestCase, _LoopbackMixin): self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"]) + def test_set_session_cache_mode_wrong_args(self): + """ + L{Context.set_session_cache_mode} raises L{TypeError} if called with + other than one integer argument. + """ + context = Context(TLSv1_METHOD) + self.assertRaises(TypeError, context.set_session_cache_mode) + self.assertRaises(TypeError, context.set_session_cache_mode, object()) + + + def test_get_session_cache_mode_wrong_args(self): + """ + L{Context.get_session_cache_mode} raises L{TypeError} if called with any + arguments. + """ + context = Context(TLSv1_METHOD) + self.assertRaises(TypeError, context.get_session_cache_mode, 1) + + + def test_session_cache_mode(self): + """ + L{Context.set_session_cache_mode} specifies how sessions are cached. + The setting can be retrieved via L{Context.get_session_cache_mode}. + """ + context = Context(TLSv1_METHOD) + old = context.set_session_cache_mode(SESS_CACHE_OFF) + off = context.set_session_cache_mode(SESS_CACHE_BOTH) + self.assertEqual(SESS_CACHE_OFF, off) + self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode()) + + class ServerNameCallbackTests(TestCase, _LoopbackMixin): """ @@ -1627,6 +1663,72 @@ class ConstantsTests(TestCase): "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old" + def test_sess_cache_off(self): + """ + The value of L{OpenSSL.SSL.SESS_CACHE_OFF} 0x0, the value of + L{SSL_SESS_CACHE_OFF} defined by I{openssl/ssl.h}. + """ + self.assertEqual(0x0, SESS_CACHE_OFF) + + + def test_sess_cache_client(self): + """ + The value of L{OpenSSL.SSL.SESS_CACHE_CLIENT} 0x1, the value of + L{SSL_SESS_CACHE_CLIENT} defined by I{openssl/ssl.h}. + """ + self.assertEqual(0x1, SESS_CACHE_CLIENT) + + + def test_sess_cache_server(self): + """ + The value of L{OpenSSL.SSL.SESS_CACHE_SERVER} 0x2, the value of + L{SSL_SESS_CACHE_SERVER} defined by I{openssl/ssl.h}. + """ + self.assertEqual(0x2, SESS_CACHE_SERVER) + + + def test_sess_cache_both(self): + """ + The value of L{OpenSSL.SSL.SESS_CACHE_BOTH} 0x3, the value of + L{SSL_SESS_CACHE_BOTH} defined by I{openssl/ssl.h}. + """ + self.assertEqual(0x3, SESS_CACHE_BOTH) + + + def test_sess_cache_no_auto_clear(self): + """ + The value of L{OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR} 0x80, the value of + L{SSL_SESS_CACHE_NO_AUTO_CLEAR} defined by I{openssl/ssl.h}. + """ + self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR) + + + def test_sess_cache_no_internal_lookup(self): + """ + The value of L{OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP} 0x100, the + value of L{SSL_SESS_CACHE_NO_INTERNAL_LOOKUP} defined by + I{openssl/ssl.h}. + """ + self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP) + + + def test_sess_cache_no_internal_store(self): + """ + The value of L{OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE} 0x200, the + value of L{SSL_SESS_CACHE_NO_INTERNAL_STORE} defined by + I{openssl/ssl.h}. + """ + self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE) + + + def test_sess_cache_no_internal(self): + """ + The value of L{OpenSSL.SSL.SESS_CACHE_NO_INTERNAL} 0x300, the value of + L{SSL_SESS_CACHE_NO_INTERNAL} defined by I{openssl/ssl.h}. + """ + self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL) + + class MemoryBIOTests(TestCase, _LoopbackMixin): """ -- cgit v1.2.1 From 5f67135478fd0c3f0c932206e316a434002dc4bd Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Wed, 8 Feb 2012 13:07:47 -0500 Subject: Formatting and other mostly-stylistic changes. --- OpenSSL/ssl/context.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/OpenSSL/ssl/context.c b/OpenSSL/ssl/context.c index a92a476..0cb483d 100644 --- a/OpenSSL/ssl/context.c +++ b/OpenSSL/ssl/context.c @@ -690,8 +690,8 @@ ssl_Context_load_client_ca(ssl_ContextObj *self, PyObject *args) } static char ssl_Context_set_session_id_doc[] = "\n\ -Set the session identifier, this is needed if you want to do session\n\ -resumption (which, ironically, isn't implemented yet)\n\ +Set the session identifier. This is needed if you want to do session\n\ +resumption.\n\ \n\ :param buf: A Python object that can be safely converted to a string\n\ :returns: None\n\ @@ -720,16 +720,16 @@ ssl_Context_set_session_id(ssl_ContextObj *self, PyObject *args) static char ssl_Context_set_session_cache_mode_doc[] = "\n\ Enable/disable session caching and the mode used.\n\ \n\ -@param mode: One or more of the SESS_CACHE_* flags (combine using bitwise or)\n\ -@return: The previously set caching mode.n\ +:param mode: One or more of the SESS_CACHE_* flags (combine using bitwise or)\n\ +:returns: The previously set caching mode.\n\ "; static PyObject * -ssl_Context_set_session_cache_mode(ssl_ContextObj *self, PyObject *args) -{ +ssl_Context_set_session_cache_mode(ssl_ContextObj *self, PyObject *args) { long mode, result; - if (!PyArg_ParseTuple(args, "l:set_session_cache_mode", &mode)) + if (!PyArg_ParseTuple(args, "l:set_session_cache_mode", &mode)) { return NULL; + } result = SSL_CTX_set_session_cache_mode(self->ctx, mode); return PyLong_FromLong(result); @@ -737,16 +737,17 @@ ssl_Context_set_session_cache_mode(ssl_ContextObj *self, PyObject *args) } static char ssl_Context_get_session_cache_mode_doc[] = "\n\ -Returns the currently used cache mode.\n\ -\n\ -@return: The currently used cache mode.\n\ +:returns: The currently used cache mode.\n\ "; static PyObject * -ssl_Context_get_session_cache_mode(ssl_ContextObj *self, PyObject *args) -{ - if (!PyArg_ParseTuple(args, ":get_session_cache_mode")) +ssl_Context_get_session_cache_mode(ssl_ContextObj *self, PyObject *args) { + long result; + + if (!PyArg_ParseTuple(args, ":get_session_cache_mode")) { return NULL; - return PyLong_FromLong((long)SSL_CTX_get_session_cache_mode(self->ctx)); + } + result = SSL_CTX_get_session_cache_mode(self->ctx); + return PyLong_FromLong(result); } static char ssl_Context_set_verify_doc[] = "\n\ -- cgit v1.2.1 From 8e8f90c85a87ad23b3d55bc35081aa340c863467 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Wed, 8 Feb 2012 13:16:26 -0500 Subject: Add documentation for the new session cache related constants and methods --- doc/api/ssl.rst | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/doc/api/ssl.rst b/doc/api/ssl.rst index 1eed876..5014889 100644 --- a/doc/api/ssl.rst +++ b/doc/api/ssl.rst @@ -69,6 +69,20 @@ Context, Connection. information to retrieve. See the man page for the :py:func:`SSLeay_version` C API for details. +.. py:data:: SESS_CACHE_OFF + SESS_CACHE_CLIENT + SESS_CACHE_SERVER + SESS_CACHE_BOTH + SESS_CACHE_NO_AUTO_CLEAR + SESS_CACHE_NO_INTERNAL_LOOKUP + SESS_CACHE_NO_INTERNAL_STORE + SESS_CACHE_NO_INTERNAL + + Constants used with :py:meth:`Context.set_session_cache_mode` to specify + the behavior of the session cache and potential session reuse. See the man + page for the :py:func:`SSL_CTX_set_session_cache_mode` C API for details. + + .. versionadded:: 0.14 .. py:data:: OPENSSL_VERSION_NUMBER @@ -315,6 +329,22 @@ Context objects have the following methods: *callback* should return a false value (e.g. an empty string). +.. py:method:: Context.set_session_cache_mode(mode) + + Set the behavior of the session cache used by all connections using this + Context. The previously set mode is returned. See :py:const:`SESS_CACHE_*` + for details about particular modes. + + .. versionadded:: 0.14 + + +.. py:method:: Context.get_session_cache_mode() + + Get the current session cache mode. + + .. versionadded:: 0.14 + + .. py:method:: Context.set_session_id(name) Set the context *name* within which a session can be reused for this -- cgit v1.2.1 From 717aa445ea4f73936ebef719808378ebafb48f95 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Wed, 8 Feb 2012 14:11:07 -0500 Subject: minor doc tweak --- OpenSSL/ssl/context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSSL/ssl/context.c b/OpenSSL/ssl/context.c index 0cb483d..0b9f4b6 100644 --- a/OpenSSL/ssl/context.c +++ b/OpenSSL/ssl/context.c @@ -718,7 +718,7 @@ ssl_Context_set_session_id(ssl_ContextObj *self, PyObject *args) } static char ssl_Context_set_session_cache_mode_doc[] = "\n\ -Enable/disable session caching and the mode used.\n\ +Enable/disable session caching and specify the mode used.\n\ \n\ :param mode: One or more of the SESS_CACHE_* flags (combine using bitwise or)\n\ :returns: The previously set caching mode.\n\ -- cgit v1.2.1