Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/gunnar

crates/gunnar-grpc/tests/tls13_provider_lost.rs

//! **The other answer**: what happens when the 1.3-only provider did NOT win.
//!
//! `install_default` is first-caller-wins and once per process, and a gunnar
//! server links three crates that pin a provider (`gunnar-grpc`, `gunnar-http`,
//! and `russh`'s aws-lc-rs). So "is this process TLS 1.3 only?" is an
//! order-dependent fact about one boot — and an order-dependent security
//! property that nothing reads back is exactly the health line that cannot
//! fail, the eighth of which this estate found in a single day.
//!
//! `refuse_unless_tls13_only` is the reader. This binary proves it can say NO,
//! by installing the ordinary, TLS-1.2-capable provider first and asking.
//! Its sibling `tls13_only.rs` proves it can say yes. Neither could prove both:
//! a process gets one provider.

/// Some other crate got there first with a 1.2-capable provider, and the check
/// catches it **before** a listener binds or a channel is dialled.
#[test]
fn a_downgradeable_provider_is_refused_by_name() {
    // The collision, staged: the ordinary provider wins the race.
    rustls::crypto::ring::default_provider()
        .install_default()
        .expect("this test binary owns the process's provider");

    // gunnar's own pin now loses, silently — which is the whole hazard.
    gunnar_grpc::ensure_crypto_provider();

    let offending = gunnar_grpc::non_tls13_suites().expect("a provider is installed");
    assert!(
        !offending.is_empty(),
        "the ordinary ring provider is supposed to carry TLS 1.2 suites; with none there this \
         test proves nothing and should be deleted rather than weakened"
    );

    let err = gunnar_grpc::refuse_unless_tls13_only()
        .expect_err("a process that can negotiate TLS 1.2 must be refused, not warned about")
        .to_string();
    assert!(
        err.contains("BELOW TLS 1.3"),
        "the refusal must say what is wrong: {err}"
    );
    assert!(
        err.contains("ensure_crypto_provider"),
        "and what to do about it: {err}"
    );
    for suite in &offending {
        assert!(
            err.contains(suite.as_str()),
            "the refusal must name the offending suite {suite}: {err}"
        );
    }
}