fix: support one-sided TLS version ranges and warn on malformed input

parse_tls_version() silently discarded partially-specified ranges like
"TLSv1.2-" or "-TLSv1.3", leaving both min and max empty. This meant
the user's intent (e.g. "at least TLSv1.2") was lost without any
indication. Now one-sided ranges set the specified bound and leave the
other side to libpq defaults. A bare "-" logs a proxy_warning.
pull/5583/head
Rahim Kanji 1 month ago
parent ca75d563e9
commit 49553cfb0b

@ -49,6 +49,14 @@ Controls which TLS protocol versions are allowed for backend connections. This m
Allows connections using any TLS version from `min_version` to `max_version` inclusive.
**Min-only:** `<min_version>-`
Sets a minimum TLS version with no upper bound (libpq default max applies).
**Max-only:** `-<max_version>`
Sets a maximum TLS version. The minimum defaults to libpq's built-in default (`TLSv1.2`).
**Single version (pin):** `<version>`
Pins to exactly that TLS version. Both min and max are set to the same value.
@ -57,6 +65,8 @@ Pins to exactly that TLS version. Both min and max are set to the same value.
Uses libpq defaults (no restriction).
A bare `-` is treated as malformed and ignored (a warning is logged).
### Valid Version Tokens
`TLSv1`, `TLSv1.1`, `TLSv1.2`, `TLSv1.3`
@ -70,6 +80,8 @@ Uses libpq defaults (no restriction).
| `TLSv1.2-TLSv1.3` | Allow TLS 1.2 and TLS 1.3 |
| `TLSv1.3` | Pin to TLS 1.3 only |
| `TLSv1.2-TLSv1.2` | Pin to TLS 1.2 only (equivalent to `TLSv1.2`) |
| `TLSv1.2-` | Require at least TLS 1.2 (max defaults to highest OpenSSL supports) |
| `-TLSv1.3` | Allow up to TLS 1.3 (min defaults to libpq's built-in `TLSv1.2`) |
| `''` (empty) | Use libpq defaults |
## Lookup Hierarchy

@ -103,8 +103,8 @@ class PgSQLServers_SslParams : public Servers_SslParams {
private:
// Parse tls_version into ssl_min_protocol_version / ssl_max_protocol_version.
// Format: "MIN-MAX" for a range, or a single token to pin both ends.
// Empty or malformed values leave both fields empty.
// Format: "MIN-MAX" for a range, "MIN-" for min-only, "-MAX" for max-only,
// or a single token to pin both ends. A bare "-" is malformed and logged.
void parse_tls_version() {
if (tls_version.empty()) return;
size_t dash_pos = tls_version.find('-');
@ -115,10 +115,13 @@ class PgSQLServers_SslParams : public Servers_SslParams {
}
string min_ver = tls_version.substr(0, dash_pos);
string max_ver = tls_version.substr(dash_pos + 1);
if (!min_ver.empty() && !max_ver.empty()) {
ssl_min_protocol_version = min_ver;
ssl_max_protocol_version = max_ver;
if (min_ver.empty() && max_ver.empty()) {
proxy_warning("Malformed ssl_protocol_version_range '%s' for %s:%d — ignoring\n",
tls_version.c_str(), hostname.c_str(), port);
return;
}
ssl_min_protocol_version = min_ver;
ssl_max_protocol_version = max_ver;
}
};

@ -160,15 +160,35 @@ static void test_pgsql_derived_class() {
ok(empty.ssl_min_protocol_version == "", "PgSQL derived: empty tls_version -> empty min");
ok(empty.ssl_max_protocol_version == "", "PgSQL derived: empty tls_version -> empty max");
// Malformed (one side missing) leaves both empty
PgSQLServers_SslParams bad(
// One-sided range: min-only ("TLSv1.2-") sets min, leaves max empty
PgSQLServers_SslParams min_only(
string("bh"), 5432, string(""),
string(""), string(""), string(""),
string(""), string(""),
string("TLSv1.2-"), string("")
);
ok(bad.ssl_min_protocol_version == "", "PgSQL derived: malformed -> empty min");
ok(bad.ssl_max_protocol_version == "", "PgSQL derived: malformed -> empty max");
ok(min_only.ssl_min_protocol_version == "TLSv1.2", "PgSQL derived: min-only range -> min set");
ok(min_only.ssl_max_protocol_version == "", "PgSQL derived: min-only range -> max empty");
// One-sided range: max-only ("-TLSv1.3") sets max, leaves min empty
PgSQLServers_SslParams max_only(
string("bh2"), 5432, string(""),
string(""), string(""), string(""),
string(""), string(""),
string("-TLSv1.3"), string("")
);
ok(max_only.ssl_min_protocol_version == "", "PgSQL derived: max-only range -> min empty");
ok(max_only.ssl_max_protocol_version == "TLSv1.3", "PgSQL derived: max-only range -> max set");
// Bare dash is malformed: both stay empty (logged as warning)
PgSQLServers_SslParams bare_dash(
string("bh3"), 5432, string(""),
string(""), string(""), string(""),
string(""), string(""),
string("-"), string("")
);
ok(bare_dash.ssl_min_protocol_version == "", "PgSQL derived: bare dash -> empty min");
ok(bare_dash.ssl_max_protocol_version == "", "PgSQL derived: bare dash -> empty max");
}
static void test_pgsql_storable_in_map() {
@ -314,7 +334,7 @@ static void test_lookup_different_host() {
// ============================================================================
int main() {
plan(67);
plan(71);
test_init_minimal();

Loading…
Cancel
Save