async_postgres/pg_connection/ssl

Search:
Group by:

TLS/SSL negotiation for PostgreSQL connections.

Implements both libpq negotiation styles: the traditional SSLRequest handshake (sslnegotiation=postgres) and Direct SSL, which starts TLS immediately and requires the "postgresql" ALPN protocol (sslnegotiation=direct, PostgreSQL 17+). The TLS handshake itself is shared by establishTls under both async backends:

  • chronos: BearSSL-based TLS via chronos/streams/tlsstream, with custom trust anchor parsing (parseTrustAnchors) and X.509 capture for SCRAM-SHA-256-PLUS channel binding (installX509Capture).
  • asyncdispatch: OpenSSL via std/asyncnet.wrapConnectedSocket, with PEM trust anchors written to a temp file and SSL_get_peer_certificate used for channel binding.

Internal: not re-exported through pg_connection.nim; import this module directly.

Procs

proc negotiateSSL(conn: PgConnection; config: ConnConfig; sslHost: string): owned(
    Future[void]) {....stackTrace: false, raises: [Exception, PgConnectionError,
    ValueError, SslError], tags: [RootEffect, WriteIOEffect], forbids: [].}
Negotiate TLS. sslnegotiation=postgres (default) sends an SSLRequest first; sslnegotiation=direct starts TLS immediately (PostgreSQL 17+). sslHost is the name matched against the server certificate (libpq semantics: the entry's host, never hostaddr).
proc sniName(sslHost: string; sslSni: bool): string {....raises: [], tags: [],
    forbids: [].}
Value for the TLS SNI extension. Empty means "do not send SNI". Matches libpq: SNI is on by default and suppressed for IP literals (RFC 6066 ยง3 forbids IPs in server_name) and when the host name is unknown (hostaddr-only).
proc validateDirectSslCompatible(config: ConnConfig) {.
    ...raises: [PgConnectionError], tags: [], forbids: [].}
Reject sslnegotiation=direct under a weak sslmode. Direct SSL skips the SSLRequest probe so it has no plaintext fall-back path (libpq parity). Idempotent โ€” safe to call from any layer.