From a77e93940fcf8262d9e4fcb005331a5848466e62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iwo=20Strzebo=C5=84ski?= Date: Fri, 28 Aug 2026 21:22:16 +0000 Subject: [PATCH] Fix ensure_trusted(): pin by serial number, not the arbitrary id label id in printers.toml is just a label you chose for config purposes - nothing ties it to a specific physical printer, and renaming it (or reusing it for a different unit down the line) would silently break the pin lookup and re-trigger trust-on-first-connect for hardware that was already trusted. The serial number is the one thing about a printer that can't change, so that's what a pin should be keyed by: certs/pinned/.pem instead of certs/pinned/.pem. Verified against a real TLS server: pinned a printer under one id, renamed it in printers.toml with the sn left unchanged, and confirmed the second run found the existing pin silently (no re-TOFU) rather than re-pinning. --- examples/auto_connect_bambu.rs | 6 +++--- src/printer/bambu.rs | 13 +++++++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/examples/auto_connect_bambu.rs b/examples/auto_connect_bambu.rs index 4a5c57f..a9ef5b0 100644 --- a/examples/auto_connect_bambu.rs +++ b/examples/auto_connect_bambu.rs @@ -4,9 +4,9 @@ //! fetch_bambu_cert combined: for each Bambu printer in printers.toml, //! makes sure it has a working certificate, auto-pinning one via //! trust-on-first-connect if the bundled CA doesn't verify. Safe to run -//! repeatedly — a printer that's already pinned (certs/pinned/.pem) -//! just gets re-verified against its pin, no network trust decision is -//! made again. +//! repeatedly — a printer that's already pinned (certs/pinned/.pem) just gets re-verified against its pin, no network trust +//! decision is made again. use continuum_proxy::fleet; use continuum_proxy::printer::PrinterHandle; diff --git a/src/printer/bambu.rs b/src/printer/bambu.rs index 47f8907..841f823 100644 --- a/src/printer/bambu.rs +++ b/src/printer/bambu.rs @@ -168,14 +168,19 @@ impl BambuGenericPrinter { /// the "smooth, no manual steps" version of the fetch_bambu_cert /// workflow, built the way SSH handles host keys: /// - /// - A pinned certificate already on disk (`cert_dir/.pem`) is used + /// - A pinned certificate already on disk (`cert_dir/.pem`) is used /// directly. No new trust decision gets made on every run — that - /// already happened once, this just re-verifies against it. + /// already happened once, this just re-verifies against it. Keyed by + /// *serial number*, not `id`: `id` is just an arbitrary label you + /// picked in printers.toml — rename a printer's `id` and the pin + /// should still find it, because a pin certifies "this physical + /// printer", and the serial number is the one thing about it that + /// can't change. /// - No pin yet, and the bundled CA verifies fine (current-generation /// printers): nothing to do. /// - No pin yet, and the bundled CA does *not* verify (P1P, etc.): /// fetches the certificate the printer presents, confirms it - /// produces a working connection, and saves it to `cert_dir/.pem` + /// produces a working connection, and saves it to `cert_dir/.pem` /// for every run after this one. This is the one moment a MITM /// active on your network *right now* could plant a certificate that /// gets trusted from then on — the same tradeoff SSH accepts on a @@ -186,7 +191,7 @@ impl BambuGenericPrinter { /// since that's exactly the signal pinning exists to give you (the /// cert rotated, or something worse). pub fn ensure_trusted(&mut self, cert_dir: &Path) -> anyhow::Result<()> { - let pinned_path = cert_dir.join(format!("{}.pem", self.base.id)); + let pinned_path = cert_dir.join(format!("{}.pem", self.sn)); if matches!(self.tls, BambuTls::BundledCa) && pinned_path.exists() { self.tls = BambuTls::Custom(std::fs::read(&pinned_path)?);