whois: show negotiated TLS version/group/cipher in 671; sslgroup crate reads the KEX group

This commit is contained in:
Jean Chevronnet 2026-08-24 21:45:46 +00:00
parent 85eb8218f0
commit 009bea734a
No known key found for this signature in database
GPG key ID: 439666D63A9477E4
13 changed files with 103 additions and 7 deletions

12
sslgroup/Cargo.toml Normal file
View file

@ -0,0 +1,12 @@
[package]
name = "sslgroup"
version = "0.1.0"
edition = "2021"
description = "Read the negotiated TLS key-exchange group name via SSL_get0_group_name (not exposed by the safe openssl crate)."
license = "MIT"
[dependencies]
# Same versions echoircd resolves, so the SslRef / SSL pointer types match.
openssl = "0.10"
openssl-sys = "0.9"
foreign-types = "0.3"

23
sslgroup/src/lib.rs Normal file
View file

@ -0,0 +1,23 @@
//! Reads the negotiated TLS key-exchange group name (e.g. `X25519MLKEM768`) via
//! OpenSSL's `SSL_get0_group_name`, which the safe `openssl` crate does not expose.
//! Isolated in its own crate so the daemon can stay `#![forbid(unsafe_code)]` — the
//! single `unsafe` FFI call lives here, exactly like the FFI inside `openssl`/`ring`.
use foreign_types::ForeignTypeRef;
use openssl::ssl::SslRef;
use std::ffi::CStr;
/// The TLS key-exchange group name for an accepted session (OpenSSL 3.2+), or
/// `None` if unavailable (before the handshake, or an OpenSSL without the API).
pub fn group_name(ssl: &SslRef) -> Option<String> {
// SAFETY: `ssl` is a live, accepted `SSL`. `SSL_get0_group_name` returns a
// NUL-terminated string OpenSSL owns for the session's lifetime; we copy it out
// here, so the borrow does not escape.
unsafe {
let name = openssl_sys::SSL_get0_group_name(ssl.as_ptr());
if name.is_null() {
return None;
}
CStr::from_ptr(name).to_str().ok().map(String::from)
}
}