@@ -785,6 +785,30 @@ channel_op_res_t channel_set_options(channel_t *this, channel_data_t *channel_da
}
}
+ /*
+ * Check if the TLS key exchange groups are specified, the
+ * server is required to support one of them. Setting this fails the
+ * handshake instead of falling back to another group, so it can be
+ * used to enforce a group
+ */
+ if (channel_data->tls_group) {
+#if LIBCURL_VERSION_NUM >= 0x074900 /* 7.73.0 */
+ if (curl_easy_setopt(channel_curl->handle,
+ CURLOPT_SSL_EC_CURVES,
+ channel_data->tls_group) != CURLE_OK) {
+ ERROR("tls_group set to %s, but not supported by the TLS backend",
+ channel_data->tls_group);
+ result = CHANNEL_EINIT;
+ goto cleanup;
+ }
+#else
+ ERROR("tls_group set to %s but libcurl %s is too old, minimum 7.73.0 versio required",
+ channel_data->tls_group, LIBCURL_VERSION);
+ result = CHANNEL_EINIT;
+ goto cleanup;
+#endif
+ }
+
if (channel_data->auth_token != NULL) {
if (((channel_curl->header = curl_slist_append(
channel_curl->header, channel_data->auth_token)) == NULL)) {
@@ -50,6 +50,9 @@ int channel_settings(void *elem, void *data)
GET_FIELD_STRING_RESET(LIBCFG_PARSER, elem, "ciphers", tmp);
if (strlen(tmp))
SETSTRING(chan->ciphers, tmp);
+ GET_FIELD_STRING_RESET(LIBCFG_PARSER, elem, "tls_group", tmp);
+ if (strlen(tmp))
+ SETSTRING(chan->tls_group, tmp);
GET_FIELD_STRING_RESET(LIBCFG_PARSER, elem, "sslcert", tmp);
if (strlen(tmp))
SETSTRING(chan->sslcert, tmp);
@@ -478,6 +478,9 @@ The available configuration options for the ``gservice`` section are:
+----------------------------+---------+-------------------------------------------------------------+
| ``ciphers`` | string | Allowed ciphers suite list in CURL format. |
+----------------------------+---------+-------------------------------------------------------------+
+| ``tls_group`` | string | Allowed TLS key exchange groups, colon separated. The |
+| | | handshake fails if the server supports none of them. |
++----------------------------+---------+-------------------------------------------------------------+
| ``proxy`` | string | HTTP proxy address to reach the server. |
+----------------------------+---------+-------------------------------------------------------------+
| ``interface`` | string | Network interface or IP address to bind communication to. |
@@ -59,6 +59,7 @@ typedef struct {
char *sslkeypassword;
char *sslcert;
char *ciphers;
+ char *tls_group; /* TLS key exchange groups */
char *proxy;
char *info;
char *auth_token;
@@ -524,6 +524,7 @@ static void channel_push_options(lua_State *L, channel_data_t *channel_data)
push_to_table(L, "sslkeypassword", channel_data->sslkeypassword);
push_to_table(L, "sslcert", channel_data->sslcert);
push_to_table(L, "ciphers", channel_data->ciphers);
+ push_to_table(L, "tls_group", channel_data->tls_group);
if (channel_data->proxy && channel_data->proxy == USE_PROXY_ENV) {
push_to_table(L, "proxy", "");
} else {
@@ -571,6 +572,7 @@ static void channel_set_options(lua_State *L, channel_data_t *channel_data)
get_from_table(L, "sslkeypassword", channel_data->sslkeypassword, COPY_DEST);
get_from_table(L, "sslcert", channel_data->sslcert, COPY_DEST);
get_from_table(L, "ciphers", channel_data->ciphers, COPY_DEST);
+ get_from_table(L, "tls_group", channel_data->tls_group, COPY_DEST);
get_from_table(L, "info", channel_data->info, COPY_DEST);
get_from_table(L, "auth_token", channel_data->auth_token, COPY_DEST);
get_from_table(L, "content_type", channel_data->content_type, COPY_DEST);
@@ -627,6 +629,7 @@ static void channel_free_options(channel_data_t *channel_data)
free(channel_data->sslkeypassword);
free(channel_data->sslcert);
free(channel_data->ciphers);
+ free(channel_data->tls_group);
if (channel_data->proxy && channel_data->proxy != USE_PROXY_ENV) {
free(channel_data->proxy);
}
@@ -235,6 +235,7 @@ suricatta.channel = {
--- @field sslkey string | nil `CURLOPT_SSLKEY` - private key file for TLS and SSL client cert
--- @field sslcert string | nil `CURLOPT_SSLCERT` - SSL client certificate
--- @field ciphers string | nil `CURLOPT_SSL_CIPHER_LIST` - ciphers to use for TLS
+ --- @field tls_group string | nil `CURLOPT_SSL_EC_CURVES` - TLS key exchange groups to require
--- @field proxy string | nil `CURLOPT_PROXY` - proxy to use
--- @field info string | nil `swupdate_request`'s info field as in `include/network_ipc.h`
--- @field auth_token string | nil String appended to Header
Add "tls_group" option mapped to curl CURLOPT_SSL_EC_CURVES taking a colon separated list example tls_group = "X25519MLKEM768:secp256r1". The handshake will fail if the server supports none of the listed groups. Needs at least libcurl 7.73.0 version Signed-off-by: Ayoub Zaki <ayoub.zaki@embetrix.com> --- corelib/channel_curl.c | 24 ++++++++++++++++++++++++ corelib/server_utils.c | 3 +++ doc/source/suricatta.rst | 3 +++ include/channel_curl.h | 1 + suricatta/server_lua.c | 3 +++ suricatta/suricatta.lua | 1 + 6 files changed, 35 insertions(+)