Track B (milestone 5 / §16 hardening): - tests/hostile_network.rs: in-process UDP relay/shim between a test client and a real dosh-server that can drop, reorder, and duplicate datagrams, and rebind its upstream socket mid-session. Asserts: session survives loss/reorder, duplicated/replayed Input is applied at most once, stale packets after resume are ignored (not fatal), and a client source-address change preserves the session. - tests/parser_robustness.rs: deterministic randomized tests throwing garbage at every reachable public parser (packet decode, from_body for all protocol/native structs, authorized_keys, known_hosts, host-key line, ssh-ed25519 blob, bootstrap, attach ticket); asserts none panic. - fuzz/: standalone cargo-fuzz crate (own [workspace], non-default member) with libfuzzer-sys harnesses for packet decode, from_body, authorized_keys, known_hosts, handshake structs+verifiers, and attach tickets. README documents the run command. - .github/workflows/ci.yml: add fuzz-smoke job (nightly + cargo-fuzz, short -max_total_time per target, tolerant if tooling unavailable); existing fmt/test/build/bench steps unchanged. cargo fmt --check and cargo test are green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
63 lines
2.1 KiB
Rust
63 lines
2.1 KiB
Rust
#![no_main]
|
|
//! Fuzz `protocol::from_body` (bincode deserialization) for every protocol and
|
|
//! native struct that is decoded from untrusted wire bytes. None may panic.
|
|
|
|
use libfuzzer_sys::fuzz_target;
|
|
|
|
use dosh::auth::{AttachTicketPlain, BootstrapResponse, SealedAttachTicket};
|
|
use dosh::native::{
|
|
HostPublicKey, NativeAuthOk, NativeClientHello, NativeServerHello, NativeUserAuth,
|
|
};
|
|
use dosh::protocol::{
|
|
self, AttachOk, AttachReject, BootstrapAttachRequest, Frame, Input, NativeAuthCheckOkBody,
|
|
NativeAuthOkBody, NativeClientHelloBody, NativeServerHelloBody, NativeUserAuthBody, Resize,
|
|
ResumeRequest, StreamClose, StreamData, StreamEof, StreamOpen, StreamOpenOk, StreamOpenReject,
|
|
StreamWindowAdjust, TicketAttachBody, TicketAttachEnvelope, TicketAttachOkEnvelope,
|
|
};
|
|
|
|
macro_rules! try_body {
|
|
($data:expr, $ty:ty) => {
|
|
let _ = protocol::from_body::<$ty>($data);
|
|
};
|
|
}
|
|
|
|
fuzz_target!(|data: &[u8]| {
|
|
// protocol.rs structs
|
|
try_body!(data, BootstrapAttachRequest);
|
|
try_body!(data, TicketAttachEnvelope);
|
|
try_body!(data, TicketAttachBody);
|
|
try_body!(data, TicketAttachOkEnvelope);
|
|
try_body!(data, AttachOk);
|
|
try_body!(data, AttachReject);
|
|
try_body!(data, ResumeRequest);
|
|
try_body!(data, Input);
|
|
try_body!(data, Resize);
|
|
try_body!(data, Frame);
|
|
try_body!(data, StreamOpen);
|
|
try_body!(data, StreamOpenOk);
|
|
try_body!(data, StreamOpenReject);
|
|
try_body!(data, StreamData);
|
|
try_body!(data, StreamWindowAdjust);
|
|
try_body!(data, StreamEof);
|
|
try_body!(data, StreamClose);
|
|
|
|
// native handshake wrapper bodies
|
|
try_body!(data, NativeClientHelloBody);
|
|
try_body!(data, NativeServerHelloBody);
|
|
try_body!(data, NativeUserAuthBody);
|
|
try_body!(data, NativeAuthOkBody);
|
|
try_body!(data, NativeAuthCheckOkBody);
|
|
|
|
// bare native handshake structs
|
|
try_body!(data, NativeClientHello);
|
|
try_body!(data, NativeServerHello);
|
|
try_body!(data, NativeUserAuth);
|
|
try_body!(data, NativeAuthOk);
|
|
try_body!(data, HostPublicKey);
|
|
|
|
// auth.rs structs
|
|
try_body!(data, BootstrapResponse);
|
|
try_body!(data, SealedAttachTicket);
|
|
try_body!(data, AttachTicketPlain);
|
|
});
|