sasl: offer and relay SCRAM-SHA-256 (advertised on plaintext too)
This commit is contained in:
parent
a922a30bf1
commit
dfbe8e8c4a
4 changed files with 21 additions and 8 deletions
|
|
@ -31,7 +31,8 @@ operational limit exposed as a config key.
|
|||
- **IRCv3** — message-tags (+msgid), server-time, labeled-response, batch,
|
||||
echo-message, account-tag, **CHATHISTORY** + **event-playback**, **multiline**,
|
||||
**message-redaction**, **read-marker**, **relaymsg**, **web-push** (VAPID / RFC
|
||||
8291), SASL, standard-replies, and `WATCH`/`MONITOR`/`SILENCE`/caller-id.
|
||||
8291), SASL (PLAIN/EXTERNAL/SCRAM-SHA-256), standard-replies, and
|
||||
`WATCH`/`MONITOR`/`SILENCE`/caller-id.
|
||||
- **Operators** — `OPER`/`KILL`/`WALLOPS`/`GLOBOPS`, the `SA*`/`CHG*`/`SET*`
|
||||
override toolbox, x-lines (`K`/`G`/`Z`/`E`/`SHUN`/`QLINE`/`CBAN`/`RLINE`)
|
||||
persisted to disk, a **type/class privilege model** (per-type commands, named
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ informed as they change. This page groups what's supported.
|
|||
|
||||
| Capability | What it adds |
|
||||
|------------|--------------|
|
||||
| `sasl` | `AUTHENTICATE` with **PLAIN** or **EXTERNAL** (client-cert / CertFP), relayed to the services server. See [linking](linking.md). |
|
||||
| `sasl` | `AUTHENTICATE` with **PLAIN**, **SCRAM-SHA-256** (challenge-response — no password on the wire, offered on plaintext too), or **EXTERNAL** (client-cert / CertFP), relayed to the services server. See [linking](linking.md). |
|
||||
| `draft/account-registration` | Create and confirm an account in-band with `REGISTER` / `VERIFY`. |
|
||||
|
||||
## History & messaging
|
||||
|
|
|
|||
|
|
@ -333,7 +333,9 @@ impl Command for Authenticate {
|
|||
if arg == "*" {
|
||||
s.numeric(uid, ERR_SASLABORTED, ":SASL authentication aborted");
|
||||
CmdResult::Ok
|
||||
} else if arg.eq_ignore_ascii_case("PLAIN") {
|
||||
} else if arg.eq_ignore_ascii_case("PLAIN")
|
||||
|| arg.eq_ignore_ascii_case("SCRAM-SHA-256")
|
||||
{
|
||||
if !have_services {
|
||||
s.numeric(
|
||||
uid,
|
||||
|
|
@ -342,12 +344,19 @@ impl Command for Authenticate {
|
|||
);
|
||||
return CmdResult::Fail;
|
||||
}
|
||||
// SCRAM is challenge-response, so the password never crosses the wire —
|
||||
// it's fine to offer over plaintext too. The rounds relay mech-agnostically.
|
||||
let mech = if arg.eq_ignore_ascii_case("PLAIN") {
|
||||
"PLAIN"
|
||||
} else {
|
||||
"SCRAM-SHA-256"
|
||||
};
|
||||
if let Some(u) = s.users.get_mut(&uid) {
|
||||
u.sasl_mech = Some("PLAIN".to_string());
|
||||
u.sasl_mech = Some(mech.to_string());
|
||||
}
|
||||
// start the exchange at services; its `C` challenge is relayed
|
||||
// back to the client as the `AUTHENTICATE +` prompt
|
||||
s.sasl_relay(uid, "S PLAIN");
|
||||
s.sasl_relay(uid, &format!("S {mech}"));
|
||||
CmdResult::Ok
|
||||
} else if arg.eq_ignore_ascii_case("EXTERNAL") {
|
||||
// CertFP: only works on TLS with a client cert; the fingerprint
|
||||
|
|
@ -373,7 +382,7 @@ impl Command for Authenticate {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
s.numeric(uid, RPL_SASLMECHS, "PLAIN :are available SASL mechanisms");
|
||||
s.numeric(uid, RPL_SASLMECHS, "PLAIN,SCRAM-SHA-256 :are available SASL mechanisms");
|
||||
s.numeric(uid, ERR_SASLFAIL, ":Unsupported SASL mechanism");
|
||||
CmdResult::Fail
|
||||
}
|
||||
|
|
|
|||
|
|
@ -194,9 +194,9 @@ impl Caps {
|
|||
.map(|c| {
|
||||
if *c == "sasl" && cap302 {
|
||||
if secure {
|
||||
"sasl=PLAIN,EXTERNAL".to_string()
|
||||
"sasl=PLAIN,EXTERNAL,SCRAM-SHA-256".to_string()
|
||||
} else {
|
||||
"sasl=PLAIN".to_string()
|
||||
"sasl=PLAIN,SCRAM-SHA-256".to_string()
|
||||
}
|
||||
} else if *c == "draft/multiline" && cap302 {
|
||||
format!("draft/multiline=max-bytes={mline_bytes},max-lines={mline_lines}")
|
||||
|
|
@ -594,6 +594,9 @@ mod tests {
|
|||
assert!(Caps::ls_line(true, false, "", 4096, 24).contains("sasl=PLAIN")); // 302 shows mechs
|
||||
assert!(!Caps::ls_line(true, false, "", 4096, 24).contains("EXTERNAL")); // plaintext: no EXTERNAL
|
||||
assert!(Caps::ls_line(true, true, "", 4096, 24).contains("sasl=PLAIN,EXTERNAL")); // TLS offers it
|
||||
// SCRAM-SHA-256 is offered on both transports (challenge-response, no wire password)
|
||||
assert!(Caps::ls_line(true, false, "", 4096, 24).contains("SCRAM-SHA-256"));
|
||||
assert!(Caps::ls_line(true, true, "", 4096, 24).contains("SCRAM-SHA-256"));
|
||||
assert!(
|
||||
Caps::ls_line(false, false, "", 4096, 24).contains("sasl")
|
||||
&& !Caps::ls_line(false, false, "", 4096, 24).contains("sasl=")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue