Commit b5218771 authored by Antoine Pitrou's avatar Antoine Pitrou

Issue #4870: Add an `options` attribute to SSL contexts, as well as

several ``OP_*`` constants to the `ssl` module.  This allows to selectively
disable protocol versions, when used in combination with `PROTOCOL_SSLv23`.
parent 955d1b22
......@@ -257,6 +257,37 @@ Functions, Constants, and Exceptions
modern version, and probably the best choice for maximum protection, if both
sides can speak it.
.. data:: OP_ALL
Enables workarounds for various bugs present in other SSL implementations.
This option is set by default.
.. versionadded:: 3.2
.. data:: OP_NO_SSLv2
Prevents an SSLv2 connection. This option is only applicable in
conjunction with :const:`PROTOCOL_SSLv23`. It prevents the peers from
choosing SSLv2 as the protocol version.
.. versionadded:: 3.2
.. data:: OP_NO_SSLv3
Prevents an SSLv3 connection. This option is only applicable in
conjunction with :const:`PROTOCOL_SSLv23`. It prevents the peers from
choosing SSLv3 as the protocol version.
.. versionadded:: 3.2
.. data:: OP_NO_TLSv1
Prevents a TLSv1 connection. This option is only applicable in
conjunction with :const:`PROTOCOL_SSLv23`. It prevents the peers from
choosing TLSv1 as the protocol version.
.. versionadded:: 3.2
.. data:: OPENSSL_VERSION
The version string of the OpenSSL library loaded by the interpreter::
......@@ -440,6 +471,17 @@ SSL Contexts
and *suppress_ragged_eofs* have the same meaning as in the top-level
:func:`wrap_socket` function.
.. attribute:: SSLContext.options
An integer representing the set of SSL options enabled on this context.
The default value is :data:`OP_ALL`, but you can specify other options
such as :data:`OP_NO_SSLv2` by ORing them together.
.. note::
With versions of OpenSSL older than 0.9.8m, it is only possible
to set options, not to clear them. Attempting to clear an option
(by resetting the corresponding bits) will raise a ``ValueError``.
.. attribute:: SSLContext.protocol
The protocol version chosen when constructing the context. This attribute
......@@ -794,6 +836,20 @@ to specify :const:`CERT_REQUIRED` and similarly check the client certificate.
equivalent unless anonymous ciphers are enabled (they are disabled
by default).
Protocol versions
^^^^^^^^^^^^^^^^^
SSL version 2 is considered insecure and is therefore dangerous to use. If
you want maximum compatibility between clients and servers, it is recommended
to use :const:`PROTOCOL_SSLv23` as the protocol version and then disable
SSLv2 explicitly using the :data:`SSLContext.options` attribute::
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
context.options |= ssl.OP_NO_SSLv2
The SSL context created above will allow SSLv3 and TLSv1 connections, but
not SSLv2.
.. seealso::
......
......@@ -63,6 +63,7 @@ from _ssl import _SSLContext, SSLError
from _ssl import CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED
from _ssl import (PROTOCOL_SSLv2, PROTOCOL_SSLv3, PROTOCOL_SSLv23,
PROTOCOL_TLSv1)
from _ssl import OP_ALL, OP_NO_SSLv2, OP_NO_SSLv3, OP_NO_TLSv1
from _ssl import RAND_status, RAND_egd, RAND_add
from _ssl import (
SSL_ERROR_ZERO_RETURN,
......
This diff is collapsed.
......@@ -375,6 +375,10 @@ C-API
Library
-------
- Issue #4870: Add an `options` attribute to SSL contexts, as well as
several ``OP_*`` constants to the `ssl` module. This allows to selectively
disable protocol versions, when used in combination with `PROTOCOL_SSLv23`.
- Issue #8759: Fixed user paths in sysconfig for posix and os2 schemes.
- Issue #8663: distutils.log emulates backslashreplace error handler. Fix
......
......@@ -113,6 +113,13 @@ static unsigned int _ssl_locks_count = 0;
# undef HAVE_OPENSSL_RAND
#endif
/* SSL_CTX_clear_options() and SSL_clear_options() were first added in OpenSSL 0.9.8m */
#if OPENSSL_VERSION_NUMBER >= 0x009080dfL
# define HAVE_SSL_CTX_CLEAR_OPTIONS
#else
# undef HAVE_SSL_CTX_CLEAR_OPTIONS
#endif
typedef struct {
PyObject_HEAD
SSL_CTX *ctx;
......@@ -1513,6 +1520,35 @@ set_verify_mode(PySSLContext *self, PyObject *arg, void *c)
return 0;
}
static PyObject *
get_options(PySSLContext *self, void *c)
{
return PyLong_FromLong(SSL_CTX_get_options(self->ctx));
}
static int
set_options(PySSLContext *self, PyObject *arg, void *c)
{
long new_opts, opts, set, clear;
if (!PyArg_Parse(arg, "l", &new_opts))
return -1;
opts = SSL_CTX_get_options(self->ctx);
clear = opts & ~new_opts;
set = ~opts & new_opts;
if (clear) {
#ifdef HAVE_SSL_CTX_CLEAR_OPTIONS
SSL_CTX_clear_options(self->ctx, clear);
#else
PyErr_SetString(PyExc_ValueError,
"can't clear options before OpenSSL 0.9.8m");
return -1;
#endif
}
if (set)
SSL_CTX_set_options(self->ctx, set);
return 0;
}
static PyObject *
load_cert_chain(PySSLContext *self, PyObject *args, PyObject *kwds)
{
......@@ -1636,6 +1672,8 @@ context_wrap_socket(PySSLContext *self, PyObject *args, PyObject *kwds)
}
static PyGetSetDef context_getsetlist[] = {
{"options", (getter) get_options,
(setter) set_options, NULL},
{"verify_mode", (getter) get_verify_mode,
(setter) set_verify_mode, NULL},
{NULL}, /* sentinel */
......@@ -1953,6 +1991,12 @@ PyInit__ssl(void)
PyModule_AddIntConstant(m, "PROTOCOL_TLSv1",
PY_SSL_VERSION_TLS1);
/* protocol options */
PyModule_AddIntConstant(m, "OP_ALL", SSL_OP_ALL);
PyModule_AddIntConstant(m, "OP_NO_SSLv2", SSL_OP_NO_SSLv2);
PyModule_AddIntConstant(m, "OP_NO_SSLv3", SSL_OP_NO_SSLv3);
PyModule_AddIntConstant(m, "OP_NO_TLSv1", SSL_OP_NO_TLSv1);
/* OpenSSL version */
/* SSLeay() gives us the version of the library linked against,
which could be different from the headers version.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment