mirror of
https://github.com/python/cpython.git
synced 2025-12-04 00:30:19 +00:00
gh-136306: Add support for getting and setting SSL groups (#136307)
Add support for getting and setting groups used for key agreement. * `ssl.SSLSocket.group()` returns the name of the group used for the key agreement of the current session establishment. This feature requires Python to be built with OpenSSL 3.2 or later. * `ssl.SSLContext.get_groups()` returns the list of names of groups that are compatible with the TLS version of the current context. This feature requires Python to be built with OpenSSL 3.5 or later. * `ssl.SSLContext.set_groups()` sets the groups allowed for key agreement for sockets created with this context. This feature is always supported.
This commit is contained in:
parent
59e2330cf3
commit
377b787618
11 changed files with 370 additions and 1 deletions
113
Modules/_ssl.c
113
Modules/_ssl.c
|
|
@ -2176,6 +2176,33 @@ _ssl__SSLSocket_cipher_impl(PySSLSocket *self)
|
|||
return cipher_to_tuple(current);
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
@critical_section
|
||||
_ssl._SSLSocket.group
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
_ssl__SSLSocket_group_impl(PySSLSocket *self)
|
||||
/*[clinic end generated code: output=9c168ee877017b95 input=5f187d8bf0d433b7]*/
|
||||
{
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30200000L
|
||||
const char *group_name;
|
||||
|
||||
if (self->ssl == NULL) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
group_name = SSL_get0_group_name(self->ssl);
|
||||
if (group_name == NULL) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
return PyUnicode_DecodeFSDefault(group_name);
|
||||
#else
|
||||
PyErr_SetString(PyExc_NotImplementedError,
|
||||
"Getting selected group requires OpenSSL 3.2 or later.");
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
@critical_section
|
||||
_ssl._SSLSocket.version
|
||||
|
|
@ -3240,6 +3267,7 @@ static PyMethodDef PySSLMethods[] = {
|
|||
_SSL__SSLSOCKET_GETPEERCERT_METHODDEF
|
||||
_SSL__SSLSOCKET_GET_CHANNEL_BINDING_METHODDEF
|
||||
_SSL__SSLSOCKET_CIPHER_METHODDEF
|
||||
_SSL__SSLSOCKET_GROUP_METHODDEF
|
||||
_SSL__SSLSOCKET_SHARED_CIPHERS_METHODDEF
|
||||
_SSL__SSLSOCKET_VERSION_METHODDEF
|
||||
_SSL__SSLSOCKET_SELECTED_ALPN_PROTOCOL_METHODDEF
|
||||
|
|
@ -3622,6 +3650,89 @@ _ssl__SSLContext_get_ciphers_impl(PySSLContext *self)
|
|||
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
@critical_section
|
||||
_ssl._SSLContext.set_groups
|
||||
grouplist: str
|
||||
/
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
_ssl__SSLContext_set_groups_impl(PySSLContext *self, const char *grouplist)
|
||||
/*[clinic end generated code: output=0b5d05dfd371ffd0 input=2cc64cef21930741]*/
|
||||
{
|
||||
if (!SSL_CTX_set1_groups_list(self->ctx, grouplist)) {
|
||||
_setSSLError(get_state_ctx(self), "unrecognized group", 0, __FILE__, __LINE__);
|
||||
return NULL;
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
@critical_section
|
||||
_ssl._SSLContext.get_groups
|
||||
*
|
||||
include_aliases: bool = False
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
_ssl__SSLContext_get_groups_impl(PySSLContext *self, int include_aliases)
|
||||
/*[clinic end generated code: output=6d6209dd1051529b input=3e8ee5deb277dcc5]*/
|
||||
{
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30500000L
|
||||
STACK_OF(OPENSSL_CSTRING) *groups = NULL;
|
||||
const char *group;
|
||||
int i, num;
|
||||
PyObject *item, *result = NULL;
|
||||
|
||||
// This "groups" object is dynamically allocated, but the strings inside
|
||||
// it are internal constants which shouldn't ever be modified or freed.
|
||||
if ((groups = sk_OPENSSL_CSTRING_new_null()) == NULL) {
|
||||
_setSSLError(get_state_ctx(self), "Can't allocate stack", 0, __FILE__, __LINE__);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!SSL_CTX_get0_implemented_groups(self->ctx, include_aliases, groups)) {
|
||||
_setSSLError(get_state_ctx(self), "Can't get groups", 0, __FILE__, __LINE__);
|
||||
goto error;
|
||||
}
|
||||
|
||||
num = sk_OPENSSL_CSTRING_num(groups);
|
||||
result = PyList_New(num);
|
||||
if (result == NULL) {
|
||||
_setSSLError(get_state_ctx(self), "Can't allocate list", 0, __FILE__, __LINE__);
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (i = 0; i < num; ++i) {
|
||||
// There's no allocation here, so group won't ever be NULL.
|
||||
group = sk_OPENSSL_CSTRING_value(groups, i);
|
||||
assert(group != NULL);
|
||||
|
||||
// Group names are plain ASCII, so there's no chance of a decoding
|
||||
// error here. However, an allocation failure could occur when
|
||||
// constructing the Unicode version of the names.
|
||||
item = PyUnicode_DecodeASCII(group, strlen(group), "strict");
|
||||
if (item == NULL) {
|
||||
_setSSLError(get_state_ctx(self), "Can't allocate group name", 0, __FILE__, __LINE__);
|
||||
goto error;
|
||||
}
|
||||
|
||||
PyList_SET_ITEM(result, i, item);
|
||||
}
|
||||
|
||||
sk_OPENSSL_CSTRING_free(groups);
|
||||
return result;
|
||||
error:
|
||||
Py_XDECREF(result);
|
||||
sk_OPENSSL_CSTRING_free(groups);
|
||||
return NULL;
|
||||
#else
|
||||
PyErr_SetString(PyExc_NotImplementedError,
|
||||
"Getting implemented groups requires OpenSSL 3.5 or later.");
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
do_protocol_selection(int alpn, unsigned char **out, unsigned char *outlen,
|
||||
|
|
@ -5472,6 +5583,7 @@ static struct PyMethodDef context_methods[] = {
|
|||
_SSL__SSLCONTEXT__WRAP_SOCKET_METHODDEF
|
||||
_SSL__SSLCONTEXT__WRAP_BIO_METHODDEF
|
||||
_SSL__SSLCONTEXT_SET_CIPHERS_METHODDEF
|
||||
_SSL__SSLCONTEXT_SET_GROUPS_METHODDEF
|
||||
_SSL__SSLCONTEXT__SET_ALPN_PROTOCOLS_METHODDEF
|
||||
_SSL__SSLCONTEXT_LOAD_CERT_CHAIN_METHODDEF
|
||||
_SSL__SSLCONTEXT_LOAD_DH_PARAMS_METHODDEF
|
||||
|
|
@ -5482,6 +5594,7 @@ static struct PyMethodDef context_methods[] = {
|
|||
_SSL__SSLCONTEXT_CERT_STORE_STATS_METHODDEF
|
||||
_SSL__SSLCONTEXT_GET_CA_CERTS_METHODDEF
|
||||
_SSL__SSLCONTEXT_GET_CIPHERS_METHODDEF
|
||||
_SSL__SSLCONTEXT_GET_GROUPS_METHODDEF
|
||||
_SSL__SSLCONTEXT_SET_PSK_CLIENT_CALLBACK_METHODDEF
|
||||
_SSL__SSLCONTEXT_SET_PSK_SERVER_CALLBACK_METHODDEF
|
||||
{NULL, NULL} /* sentinel */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue