Add ssl_(supported|shared)_groups to sslinfo

First seen: 2026-02-19 17:44:57+00:00 · Messages: 13 · Participants: 4

Latest Update

2026-05-09 · opus 4.7

Analysis: Adding ssl_supported_groups / ssl_shared_groups to contrib/sslinfo

Core Problem & Motivation

The contrib/sslinfo extension is PostgreSQL's in-band introspection surface for the TLS session backing a given backend. Historically it was scoped to exposing X.509 client certificate attributes (subject, issuer, serial, certificate extensions via ssl_extension_info()), but over time it acquired functions covering connection-level TLS state such as ssl_cipher() and ssl_version(). The proposal from Dmitry Dolgov (9erthalion6) extends this further into the TLS handshake's key-exchange group negotiation: the set of elliptic-curve / finite-field Diffie-Hellman groups (the TLS 1.3 supported_groups extension, formerly elliptic_curves) that the client advertised, the intersection with what the server supports, and — after iteration — the single group actually chosen for the ephemeral key exchange.

This matters because PostgreSQL exposes a ssl_groups GUC for controlling the server-side group list; operators configuring that GUC currently have no server-side observability into whether their configuration is compatible with connecting clients, nor which group is actually being used for forward secrecy. Without this, debugging "why is my client failing / falling back?" requires out-of-band tools (Wireshark, openssl s_client), which are not always available on managed deployments.

Proposed Solution — Evolution Across Revisions

The patch went through three substantive redesigns driven by review, each more consonant with existing sslinfo conventions:

  1. v1: Two separate SQL-callable functions, ssl_supported_groups() and ssl_shared_groups(), each returning a colon/comma-delimited text. A brand-new sslinfo--1.3.sql script was shipped alongside the upgrade script.

  2. v2 (post-Gustafsson review): Daniel Gustafsson pushed back on three design points:

    • Packaging: shipping a full sslinfo--1.3.sql is redundant — the extension machinery chains upgrade scripts, so only sslinfo--1.2--1.3.sql is needed. This is the standard convention across contrib.
    • Return type: delimited strings are hostile to SQL consumers; text[] is idiomatic.
    • Function placement: ssl_extension_info() already exists and superficially looks like the right home — but Jacob Champion later pointed out this function is misnamed: it enumerates X.509 certificate extensions, not TLS protocol extensions. So folding the new data there would have been semantically wrong despite the name.
  3. v3+ (post-Champion review): The API was restructured into a single set-returning function ssl_group_info() returning (type text, name text) rows, where type is one of negotiated, shared, supported. This unifies the three concepts into one relational shape and, crucially, leaves room for future expansion (e.g., ciphersuite negotiation diagnostics following the same schema).

Key Design Tension: Connection Facts vs. Handshake Might-Have-Beens

Jacob Champion raised the most architecturally interesting objection: every existing sslinfo function reports a fact about the established connection (the cipher in use, the negotiated protocol version, the presented client cert). The supported_groups and shared_groups lists are fundamentally different — they describe the negotiation space, not the outcome. Champion's critique was that this conflates two different diagnostic axes:

Dolgov's rebuttal leaned on precedent: sslinfo's scope already drifted once (from cert-only to connection-level), so a second, documented broadening is defensible. Champion conceded but extracted a concrete concession: expose the negotiated group, since that is a connection fact and matches ssl_cipher() in spirit. The final design therefore treats negotiated as the primary datum, with shared/supported as supplementary debugging context.

Naming: TLS Spec vs. OpenSSL Vernacular

A subtle but important sub-debate concerned terminology. The OpenSSL API names (SSL_get_negotiated_group, SSL_get_shared_group, SSL_get0_peer_supported_groups) don't all map cleanly to RFC 8446 vocabulary:

Dolgov's resolution was pragmatic: keep the short OpenSSL-derived labels as the column values, and disambiguate in the documentation. This trades pedantic spec-fidelity for API brevity and alignment with what an OpenSSL-literate DBA would search for.

Portability Issue — OpenSSL API Matrix

A non-trivial wrinkle emerged at the v3 stage: not all supported OpenSSL versions and platforms provide all three accessor functions, and critically, some are real exported symbols while others are macro wrappers around SSL_ctrl. This forces the autoconf probing to do two distinct kinds of checks — AC_CHECK_FUNCS for real functions, and a declaration/compile check for the macro forms. The patch had to handle the case where SSL_get0_peer_supported_groups (for example) exists on newer OpenSSL but not on LibreSSL or older OpenSSL branches, gracefully degrading the exposed rows.

There was also an incidental configure.ac churn issue: autoconf 2.69 was spuriously reordering unrelated blocks, which Dolgov had to manually suppress — a familiar pitfall for anyone touching PostgreSQL's autoconf.

Robustness Point from Cary Huang

Huang's review caught a real bug in the SRF implementation: SSL_get_negotiated_group() / SSL_get_shared_group() can legitimately return NID_undef (e.g., no group negotiated, or no intersection on a connection that somehow survived). Passing NID_undef to SSL_group_to_name() returns NULL, and the current code treats that as an error. Since this is a set-returning function, the correct behavior is to elide the row rather than abort — consistent with the philosophy that sslinfo functions should return what's available without blowing up the query. This is both more user-friendly and avoids a class of failures when the function is joined against pg_stat_ssl or similar across many sessions.

Architectural Implications

The thread illustrates a recurring pattern in extending PostgreSQL's TLS surface:

  1. sslinfo is becoming a general TLS introspection namespace, not just a cert inspector. The documentation and comment ("information about SSL certificates") are now stale and should be updated as part of this work.
  2. ssl_extension_info() is misnamed — a latent papercut that will trip future contributors expecting to find TLS protocol extensions there. A rename or aliasing may be warranted eventually, though not in this patch.
  3. Set-returning functions with a typed discriminator column (type text) are a flexible pattern for grouping related-but-heterogeneous diagnostic data, and Champion explicitly flagged this as a template for future ciphersuite/parameter introspection.

The patch is small in LOC but represents a deliberate expansion of sslinfo's charter, negotiated through review to stay coherent with existing idioms.