From e0fcf51edcddac12ed57fb5ef76bfa8f342b849a Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Mon, 13 Feb 2012 09:10:15 -0500 Subject: Minimal skeleton of a Python Session type --- OpenSSL/ssl/session.c | 146 +++++++++++++++++++++++++++++++++++++++++++++++ OpenSSL/ssl/session.h | 25 ++++++++ OpenSSL/ssl/ssl.c | 2 + OpenSSL/ssl/ssl.h | 1 + OpenSSL/test/test_ssl.py | 27 ++++++++- setup.py | 4 +- 6 files changed, 202 insertions(+), 3 deletions(-) create mode 100644 OpenSSL/ssl/session.c create mode 100644 OpenSSL/ssl/session.h diff --git a/OpenSSL/ssl/session.c b/OpenSSL/ssl/session.c new file mode 100644 index 0000000..5cd23b6 --- /dev/null +++ b/OpenSSL/ssl/session.c @@ -0,0 +1,146 @@ +/* + * session.c + * + * Copyright (C) Jean-Paul Calderone + * Copyright (C) Alejandro Alvarez Ayllon + * See LICENSE for details. + * + * SSL Session object data structures and functions. + * + */ +#include +#define SSL_MODULE +#include "ssl.h" + +static char ssl_Session_doc[] = "\n\ +Session() -> Session instance\n\ +\n\ +"; + +/* + * Initialize an already-constructed Session instance. + */ +static ssl_SessionObj *ssl_Session_init(ssl_SessionObj *self) { + /* + self->sess = d2i_SSL_SESSION(NULL, &buffer, len); + + if (!self->sess) { + exception_from_error_queue(ssl_Error); + return NULL; + } + */ + return self; + +} + + +/* + * Create a Session object + */ +static PyObject* +ssl_Session_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs) { + ssl_SessionObj *self; + + if (!PyArg_ParseTuple(args, ":Session")) { + return NULL; + } + + self = PyObject_New(ssl_SessionObj, &ssl_Session_Type); + if (self == NULL) { + return NULL; + } + + return (PyObject *)ssl_Session_init(self); +} + +/* + * Member methods in the Session object + * ADD_METHOD(name) expands to a correct PyMethodDef declaration + * { 'name', (PyCFunction)ssl_Session_name, METH_VARARGS } + * for convenience + * ADD_ALIAS(name,real) creates an "alias" of the ssl_Session_real + * function with the name 'name' + */ +#define ADD_METHOD(name) { #name, (PyCFunction)ssl_Session_##name, METH_VARARGS, ssl_Session_##name##_doc } +static PyMethodDef ssl_Session_methods[] = { +#if 0 + ADD_METHOD(asn1), + ADD_METHOD(get_time), + ADD_METHOD(get_timeout), +#ifdef SSL_SESSION_hash + ADD_METHOD(hash), +#endif + ADD_METHOD(set_time), + ADD_METHOD(set_timeout), +#endif + { NULL, NULL } +}; +#undef ADD_METHOD + +/* + * The Python Session type definition. + */ +PyTypeObject ssl_Session_Type = { + PyOpenSSL_HEAD_INIT(&PyType_Type, 0) + "OpenSSL.SSL.Session", + sizeof(ssl_SessionObj), + 0, + NULL, // (destructor)ssl_Session_dealloc, /* tp_dealloc */ + NULL, /* print */ + NULL, /* tp_getattr */ + NULL, /* setattr */ + NULL, /* compare */ + NULL, /* repr */ + NULL, /* as_number */ + NULL, /* as_sequence */ + NULL, /* as_mapping */ + NULL, /* hash */ + NULL, /* call */ + NULL, /* str */ + NULL, /* getattro */ + NULL, /* setattro */ + NULL, /* as_buffer */ + Py_TPFLAGS_DEFAULT, // Py_TPFLAGS_HAVE_GC, /* tp_flags */ + ssl_Session_doc, /* tp_doc */ + NULL, // (traverseproc)ssl_Session_traverse, /* tp_traverse */ + NULL, // (inquiry)ssl_Session_clear, /* tp_clear */ + NULL, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + NULL, /* tp_iter */ + NULL, /* tp_iternext */ + ssl_Session_methods, /* tp_methods */ + NULL, /* tp_members */ + NULL, /* tp_getset */ + NULL, /* tp_base */ + NULL, /* tp_dict */ + NULL, /* tp_descr_get */ + NULL, /* tp_descr_set */ + 0, /* tp_dictoffset */ + NULL, /* tp_init */ + NULL, /* tp_alloc */ + ssl_Session_new, /* tp_new */ +}; + +/* + * Initialize the Session part of the SSL sub module + * + * Arguments: dict - The OpenSSL.SSL module + * Returns: 1 for success, 0 otherwise + */ +int +init_ssl_session(PyObject *module) { + + if (PyType_Ready(&ssl_Session_Type) < 0) { + return 0; + } + + /* PyModule_AddObject steals a reference. + */ + Py_INCREF((PyObject *)&ssl_Session_Type); + if (PyModule_AddObject(module, "Session", (PyObject *)&ssl_Session_Type) < 0) { + return 0; + } + + return 1; +} + diff --git a/OpenSSL/ssl/session.h b/OpenSSL/ssl/session.h new file mode 100644 index 0000000..98cee80 --- /dev/null +++ b/OpenSSL/ssl/session.h @@ -0,0 +1,25 @@ +/* + * session.h + * Copyright (C) Jean-Paul Calderone + * See LICENSE for details. + * + * Defined here is the Python type which represents an SSL session by wrapping + * an OpenSSL SSL_SESSION*. + * + */ + +#ifndef PyOpenSSL_SSL_SESSION_H_ +#define PyOpenSSL_SSL_SESSION_H_ + +#include +#include + +typedef struct { + PyObject_HEAD +} ssl_SessionObj; + +extern PyTypeObject ssl_Session_Type; + +extern int init_ssl_session(PyObject *); + +#endif diff --git a/OpenSSL/ssl/ssl.c b/OpenSSL/ssl/ssl.c index a68f447..5725d5d 100644 --- a/OpenSSL/ssl/ssl.c +++ b/OpenSSL/ssl/ssl.c @@ -298,6 +298,8 @@ do { \ if (!init_ssl_context(module)) goto error; + if (!init_ssl_session(module)) + goto error; if (!init_ssl_connection(module)) goto error; diff --git a/OpenSSL/ssl/ssl.h b/OpenSSL/ssl/ssl.h index 6a0a57e..3074ba5 100644 --- a/OpenSSL/ssl/ssl.h +++ b/OpenSSL/ssl/ssl.h @@ -16,6 +16,7 @@ #include #include #include "context.h" +#include "session.h" #include "connection.h" #include "../util.h" #include "../crypto/crypto.h" diff --git a/OpenSSL/test/test_ssl.py b/OpenSSL/test/test_ssl.py index cda6d53..529a454 100644 --- a/OpenSSL/test/test_ssl.py +++ b/OpenSSL/test/test_ssl.py @@ -34,7 +34,8 @@ from OpenSSL.SSL import ( from OpenSSL.SSL import ( Error, SysCallError, WantReadError, ZeroReturnError, SSLeay_version) -from OpenSSL.SSL import Context, ContextType, Connection, ConnectionType +from OpenSSL.SSL import ( + Context, ContextType, Session, Connection, ConnectionType) from OpenSSL.test.util import TestCase, bytes, b from OpenSSL.test.test_crypto import ( @@ -1046,6 +1047,30 @@ class ServerNameCallbackTests(TestCase, _LoopbackMixin): +class SessionTests(TestCase): + """ + Unit tests for :py:obj:`OpenSSL.SSL.Session`. + """ + def test_construction(self): + """ + :py:class:`Session` can be constructed with no arguments, creating a new + instance of that type. + """ + new_session = Session() + self.assertTrue(isinstance(new_session, Session)) + + + def test_construction_wrong_args(self): + """ + If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError` + is raised. + """ + self.assertRaises(TypeError, Session, 123) + self.assertRaises(TypeError, Session, "hello") + self.assertRaises(TypeError, Session, object()) + + + class ConnectionTests(TestCase, _LoopbackMixin): """ Unit tests for :py:obj:`OpenSSL.SSL.Connection`. diff --git a/setup.py b/setup.py index 8441274..511c60c 100755 --- a/setup.py +++ b/setup.py @@ -34,9 +34,9 @@ crypto_dep = ['OpenSSL/crypto/crypto.h', 'OpenSSL/crypto/x509.h', rand_src = ['OpenSSL/rand/rand.c', 'OpenSSL/util.c'] rand_dep = ['OpenSSL/util.h'] ssl_src = ['OpenSSL/ssl/connection.c', 'OpenSSL/ssl/context.c', 'OpenSSL/ssl/ssl.c', - 'OpenSSL/util.c'] + 'OpenSSL/ssl/session.c', 'OpenSSL/util.c'] ssl_dep = ['OpenSSL/ssl/connection.h', 'OpenSSL/ssl/context.h', 'OpenSSL/ssl/ssl.h', - 'OpenSSL/util.h'] + 'OpenSSL/ssl/session.h', 'OpenSSL/util.h'] IncludeDirs = None LibraryDirs = None -- cgit v1.2.1