feat: add CertFP authentication with SASL EXTERNAL

Per-network, per-nick client certificates (EC P-256, self-signed,
10-year validity) stored as combined PEM files. Authentication
cascade: SASL EXTERNAL > SASL PLAIN > NickServ IDENTIFY.

New commands: GENCERT, CERTFP, DELCERT. GENCERT auto-registers
the fingerprint with NickServ CERT ADD when the network is connected.

Includes email verification module for NickServ registration and
expanded NickServ interaction (IDENTIFY, REGISTER, VERIFY).
This commit is contained in:
user
2026-02-21 01:15:25 +01:00
parent e6b1ce4c6d
commit 2f40f5e508
14 changed files with 1912 additions and 49 deletions

View File

@@ -196,6 +196,55 @@ autojoin = true # auto-join channels on ready (default: true)
password = "" # IRC server password (optional, for PASS command)
```
## CertFP Authentication
The bouncer supports client certificate fingerprint (CertFP) authentication
via SASL EXTERNAL. Each certificate is unique per (network, nick) pair and
stored as a combined PEM file at `{data_dir}/certs/{network}/{nick}.pem`.
### Authentication Cascade
When connecting, the bouncer selects the strongest available method:
| Priority | Method | Condition |
|----------|--------|-----------|
| 1 | SASL EXTERNAL | Stored creds + cert file exists |
| 2 | SASL PLAIN | Stored creds, no cert |
| 3 | NickServ IDENTIFY | Fallback after SASL failure |
### Setup
1. Generate a certificate:
```
/msg *bouncer GENCERT libera
```
This creates an EC P-256 self-signed cert (10-year validity) and
auto-sends `NickServ CERT ADD <fingerprint>` if the network is connected.
2. Reconnect to use CertFP:
```
/msg *bouncer RECONNECT libera
```
The bouncer will now present the client certificate during TLS and
authenticate via SASL EXTERNAL.
3. Verify the fingerprint is registered:
```
/msg *bouncer CERTFP libera
```
### Certificate Storage
Certificates are stored alongside the config file:
```
{data_dir}/certs/
libera/
fabesune.pem # cert + private key (chmod 600)
oftc/
mynick.pem
```
## Bouncer Commands
Send a PRIVMSG to `*bouncer` (or `bouncer`) from your IRC client to inspect
@@ -248,6 +297,14 @@ Responses arrive as NOTICE messages from `*bouncer`.
| `REGISTER <network>` | Trigger NickServ registration attempt |
| `DROPCREDS <network> [nick]` | Delete stored NickServ credentials |
### CertFP
| Command | Description |
|---------|-------------|
| `GENCERT <network> [nick]` | Generate client cert, auto-register with NickServ |
| `CERTFP [network]` | Show certificate fingerprints (all or per-network) |
| `DELCERT <network> [nick]` | Delete a client certificate |
### Examples
```
@@ -272,6 +329,12 @@ Responses arrive as NOTICE messages from `*bouncer`.
/msg *bouncer REGISTER libera
/msg *bouncer DROPCREDS libera
/msg *bouncer DROPCREDS libera oldnick
/msg *bouncer GENCERT libera
/msg *bouncer GENCERT libera fabesune
/msg *bouncer CERTFP
/msg *bouncer CERTFP libera
/msg *bouncer DELCERT libera
/msg *bouncer DELCERT libera fabesune
```
### Example Output