╭ changed ─────────────────╮ │src/serve_ssh_protocol.zig│ ╰──────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────╮ │463 try sendChannelMessage(conn, self.channel, SSH_MSG_CHANNEL_CLOSE);│ │464 }, │ │465 SSH_MSG_GLOBAL_REQUEST => try handleGlobalRequest(conn, packet), │ │466 + // RFC 4252 §5.1: silently ignored once authenticated │ │467 + SSH_MSG_USERAUTH_REQUEST => {}, │ │468 else => try sendUnimplemented(conn), │ │469 } │ │470 } │ ╰───────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1642 defer allocator.free(req); │ │1643 if (req.len < 1 or req[0] != SSH_MSG_USERAUTH_REQUEST) return error.UnexpectedMessage;│ │1644 │ │1645 + // every request counts, probes included, so a client can't loop here │ │1646 + // forever │ │1647 + if (auth_attempts >= max_auth_attempts) return error.TooManyAuthAttempts; │ │1648 + auth_attempts += 1; │ │1649 + │ │1650 var req_reader = std.Io.Reader.fixed(req[1..]); │ │1651 const user_name = try takeString(&req_reader, 256); │ │1652 const service_name = try takeString(&req_reader, 64); │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────╮ │1654 │ │1655 // RFC 4252 §5: the server must verify the requested service │ │1656 if (!std.mem.eql(u8, service_name, "ssh-connection")) { │ │1650 - auth_attempts += 1; │ │1651 - if (auth_attempts >= max_auth_attempts) return error.TooManyAuthAttempts;│ │1657 try sendUserauthFailure(conn); │ │1658 continue; │ │1659 } │ ╰───────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────╮ │1660 │ │1661 if (!std.mem.eql(u8, method, "publickey")) { │ │1657 - auth_attempts += 1; │ │1658 - if (auth_attempts >= max_auth_attempts) return error.TooManyAuthAttempts;│ │1662 try sendUserauthFailure(conn); │ │1663 continue; │ │1664 } │ ╰───────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────╮ │1668 const pubkey_blob = try takeString(&req_reader, 4096); │ │1669 │ │1670 if (!std.mem.eql(u8, algo, "ssh-ed25519")) { │ │1668 - auth_attempts += 1; │ │1669 - if (auth_attempts >= max_auth_attempts) return error.TooManyAuthAttempts;│ │1671 try sendUserauthFailure(conn); │ │1672 continue; │ │1673 } │ ╰───────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────╮ │1674 │ │1675 if (!has_signature) { │ │1675 - // probes count as attempts so a client can't loop here forever │ │1676 - auth_attempts += 1; │ │1677 - if (auth_attempts >= max_auth_attempts) return error.TooManyAuthAttempts;│ │1676 // probe — tell the client this key is acceptable so it'll send │ │1677 // the signed version next. │ │1678 var pk_ok: std.ArrayList(u8) = .empty; │ ╰───────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────╮ │1695 algo, │ │1696 pubkey_blob, │ │1697 signature_blob, │ │1700 - ) catch false; │ │1698 + ) catch |err| switch (err) { │ │1699 + error.OutOfMemory => return err, │ │1700 + // a malformed key or signature blob │ │1701 + else => false, │ │1702 + }; │ │1703 │ │1704 if (!ok) { │ │1703 - auth_attempts += 1; │ │1704 - if (auth_attempts >= max_auth_attempts) return error.TooManyAuthAttempts;│ │1705 try sendUserauthFailure(conn); │ │1706 continue; │ │1707 } │ ╰───────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────╮ │1883 return; │ │1884 }, │ │1885 │ │1886 + // RFC 4252 §5.1: silently ignored once authenticated│ │1887 + SSH_MSG_USERAUTH_REQUEST => {}, │ │1888 else => try sendUnimplemented(conn), │ │1889 } │ │1890 } │ ╰───────────────────────────────────────────────────────────────────────╯