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

@@ -87,6 +87,17 @@ PASS <password> # authenticate (all networks)
/msg *bouncer DROPCREDS libera nick # delete one nick's creds
```
### CertFP
```
/msg *bouncer GENCERT libera # generate cert (current nick)
/msg *bouncer GENCERT libera nick # generate cert (specific nick)
/msg *bouncer CERTFP # list all cert fingerprints
/msg *bouncer CERTFP libera # list certs for one network
/msg *bouncer DELCERT libera # delete cert (current nick)
/msg *bouncer DELCERT libera nick # delete cert (specific nick)
```
## Namespacing
```
@@ -114,6 +125,12 @@ DISCONNECTED -> CONNECTING -> REGISTERING -> PROBATION (15s) -> READY
| PROBATION | 15s wait, watching for K-line |
| READY | Switch to configured nick, join channels |
## Auth Cascade
```
SASL EXTERNAL (cert + creds) > SASL PLAIN (creds) > NickServ IDENTIFY
```
## Reconnect Backoff
```
@@ -144,6 +161,7 @@ password # optional, IRC server PASS
| `config/bouncer.toml` | Active config (gitignored) |
| `config/bouncer.example.toml` | Example template |
| `config/bouncer.db` | SQLite backlog (auto-created) |
| `{data_dir}/certs/{net}/{nick}.pem` | Client certificates (auto-created) |
## Backlog Queries
@@ -167,10 +185,11 @@ src/bouncer/
config.py # TOML loader
irc.py # IRC message parse/format
namespace.py # /network encode/decode for multiplexing
proxy.py # SOCKS5 connector (local DNS, multi-IP)
network.py # server connection + state machine
proxy.py # SOCKS5 connector (local DNS, multi-IP, CertFP)
network.py # server connection + state machine + SASL
client.py # client session handler
commands.py # 22 bouncer control commands (/msg *bouncer)
cert.py # client certificate generation + management
commands.py # 25 bouncer control commands (/msg *bouncer)
router.py # message routing + backlog trigger
server.py # TCP listener
backlog.py # SQLite store/replay/prune