Commit d47e952
feat(algorithms): M17.1 — denylist + +/-/^ parser + catalogue (FR-77, FR-78, FR-79 lib side) (#25)
Adds the library-side scaffold M17 needs to honour KexAlgorithms /
Ciphers / MACs / HostKeyAlgorithms from `~/.ssh/config` (FR-76),
parse OpenSSH-format CLI overrides (FR-77), enforce the permanent
denylist (FR-78), and surface the algorithm catalogue for
`gitway list-algorithms` (FR-79).
src/algorithms.rs (new, ~470 lines + ~250 lines of tests):
- pub const DENYLIST: &[&str] — DSA, 3DES, Arcfour variants,
hmac-sha1-96, ssh-1.0. Per FR-78 the list is permanent: an
override referencing any entry is rejected with a
tips-thinking hint pointing at `gitway list-algorithms` and an
external `ssh -W` workaround.
- pub fn is_denylisted(alg) / apply_denylist(list) — case-insensitive
ASCII matching helpers.
- pub enum AlgCategory { Kex, Cipher, Mac, HostKey } with .label().
- pub fn apply_overrides(category, base, override_str) — the
OpenSSH-format `+algo` (append) / `-algo` (remove) / `^algo`
(front-load) / `algo,algo` (replace) parser. Trims whitespace,
drops empty tokens, deduplicates appends case-insensitively,
preserves ordering on front-loads, silently skips removes for
absent entries (matches OpenSSH behaviour). Calls apply_denylist
after every transformation. Errors hard on a denylisted token
in any prefix form.
- pub fn anvil_default_kex / _ciphers / _macs / _host_keys — the
curated default lists used as the base for `+/-/^` overrides.
Kex matches what build_russh_config currently hardcodes;
ciphers/macs/host-keys are the safe set Gitway will negotiate
once M17.2 plumbs them through.
- pub struct AlgEntry { name, is_default, denylisted } and
pub struct Catalogue { kex, cipher, mac, host_key } with
pub fn all_supported() — enumerates every name russh advertises
(sourced from russh::{kex,cipher,mac}::* constants) and tags
each with the two flags.
src/lib.rs:
- pub mod algorithms;
Public API: pure additive. Version bump to 0.8.0 lands in M17.3.
23 unit tests covering: denylist case-insensitivity, Arcfour
variant matching, safe-algorithm pass-through, denylist-preserving
filter, all five prefix branches (none/+/-/^/empty), case-insensitive
dedup on append, silent skip on remove of absent, OpenSSH front-load
semantics (reorder-not-add), hard error on denylisted token in
override (in both replace and append forms), error hint mentioning
`gitway list-algorithms`, empty-token drop, whitespace trim,
catalogue completeness (≥1 default per category, denylisted entries
tagged, default+denylisted disjoint), curated-defaults exclude
denylist, host-key default excludes ssh-dss / includes ssh-ed25519,
category labels stable.
Plan: M17.1 of anvil-gitway-milestone-plan.md.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 110bb91 commit d47e952
2 files changed
Lines changed: 633 additions & 0 deletions
0 commit comments