diff --git a/Cargo.lock b/Cargo.lock --- a/Cargo.lock +++ b/Cargo.lock @@ -554,7 +554,7 @@ "proc-macro2", "quote", "syn 2.0.65", - "synstructure", + "synstructure 0.13.1", ] [[package]] @@ -1002,7 +1002,7 @@ "http 0.2.12", "http 1.1.0", "once_cell", - "p256", + "p256 0.11.1", "percent-encoding", "ring 0.17.8", "sha2 0.10.8", @@ -1381,6 +1381,12 @@ "which", ] +[[package]] +name = "binstring" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e0d60973d9320722cb1206f412740e162a33b8547ea8d6be75d7cff237c7a85" + [[package]] name = "bitflags" version = "1.3.2" @@ -1663,12 +1669,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b77c319abfd5219629c45c34c89ba945ed3c5e49fcde9d16b6c3885f118a730" dependencies = [ - "const-oid", + "const-oid 0.9.6", "der 0.7.9", "spki 0.7.3", "x509-cert", ] +[[package]] +name = "coarsetime" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b3839cf01bb7960114be3ccf2340f541b6d0c81f8690b007b2b39f750f7e5d" +dependencies = [ + "libc", + "wasix", + "wasm-bindgen", +] + [[package]] name = "colorchoice" version = "1.0.1" @@ -1765,6 +1782,12 @@ "crossbeam-utils", ] +[[package]] +name = "const-oid" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d6f2aa4d0537bcc1c74df8755072bd31c1ef1a3a1b85a68e8404a8c353b7b8b" + [[package]] name = "const-oid" version = "0.9.6" @@ -1908,6 +1931,12 @@ "typenum", ] +[[package]] +name = "ct-codecs" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3b7eb4404b8195a9abb6356f4ac07d8ba267045c8d6d220ac4dc992e6cc75df" + [[package]] name = "ctor" version = "0.2.8" @@ -1994,13 +2023,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" +[[package]] +name = "der" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79b71cca7d95d7681a4b3b9cdf63c8dbc3730d0584c2c74e31416d64a90493f4" +dependencies = [ + "const-oid 0.6.2", + "der_derive 0.4.1", +] + [[package]] name = "der" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" dependencies = [ - "const-oid", + "const-oid 0.9.6", + "pem-rfc7468 0.6.0", "zeroize", ] @@ -2010,10 +2050,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ - "const-oid", - "der_derive", + "const-oid 0.9.6", + "der_derive 0.7.2", "flagset", - "pem-rfc7468", + "pem-rfc7468 0.7.0", "zeroize", ] @@ -2031,6 +2071,18 @@ "rusticata-macros", ] +[[package]] +name = "der_derive" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8aed3b3c608dc56cf36c45fe979d04eda51242e6703d8d0bb03426ef7c41db6a" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "synstructure 0.12.6", +] + [[package]] name = "der_derive" version = "0.7.2" @@ -2100,7 +2152,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", - "const-oid", + "const-oid 0.9.6", "crypto-common", "subtle", ] @@ -2154,6 +2206,24 @@ "spki 0.7.3", ] +[[package]] +name = "ece" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2ea1d2f2cc974957a4e2575d8e5bb494549bab66338d6320c2789abcfff5746" +dependencies = [ + "base64 0.21.7", + "byteorder", + "hex", + "hkdf", + "lazy_static", + "once_cell", + "openssl", + "serde", + "sha2 0.10.8", + "thiserror", +] + [[package]] name = "ed25519" version = "1.5.3" @@ -2163,6 +2233,16 @@ "signature 1.6.4", ] +[[package]] +name = "ed25519-compact" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9b3460f44bea8cd47f45a0c70892f1eff856d97cd55358b2f73f663789f6190" +dependencies = [ + "ct-codecs", + "getrandom 0.2.15", +] + [[package]] name = "ed25519-dalek" version = "1.0.1" @@ -2215,6 +2295,8 @@ "ff 0.13.0", "generic-array", "group 0.13.0", + "hkdf", + "pem-rfc7468 0.7.0", "pkcs8 0.10.2", "rand_core 0.6.4", "sec1 0.7.3", @@ -2713,6 +2795,30 @@ "digest 0.10.7", ] +[[package]] +name = "hmac-sha1-compact" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9d405ec732fa3fcde87264e54a32a84956a377b3e3107de96e59b798c84a7" + +[[package]] +name = "hmac-sha256" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3688e69b38018fec1557254f64c8dc2cc8ec502890182f395dbb0aa997aa5735" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "hmac-sha512" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ce1f4656bae589a3fab938f9f09bf58645b7ed01a2c5f8a3c238e01a4ef78a" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "home" version = "0.5.9" @@ -3086,13 +3192,39 @@ dependencies = [ "base64 0.21.7", "js-sys", - "pem", + "pem 3.0.4", "ring 0.17.8", "serde", "serde_json", "simple_asn1", ] +[[package]] +name = "jwt-simple" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357892bb32159d763abdea50733fadcb9a8e1c319a9aa77592db8555d05af83e" +dependencies = [ + "anyhow", + "binstring", + "coarsetime", + "ct-codecs", + "ed25519-compact", + "hmac-sha1-compact", + "hmac-sha256", + "hmac-sha512", + "k256", + "p256 0.13.2", + "p384", + "rand 0.8.5", + "rsa", + "serde", + "serde_json", + "spki 0.6.0", + "thiserror", + "zeroize", +] + [[package]] name = "k256" version = "0.13.3" @@ -3104,6 +3236,7 @@ "elliptic-curve 0.13.8", "once_cell", "sha2 0.10.8", + "signature 2.2.0", ] [[package]] @@ -3148,6 +3281,9 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin 0.5.2", +] [[package]] name = "lazycell" @@ -3171,6 +3307,12 @@ "windows-targets 0.52.5", ] +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + [[package]] name = "linux-raw-sys" version = "0.3.8" @@ -3443,6 +3585,23 @@ "num-traits", ] +[[package]] +name = "num-bigint-dig" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand 0.8.5", + "smallvec", + "zeroize", +] + [[package]] name = "num-conv" version = "0.1.0" @@ -3469,6 +3628,17 @@ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -3476,6 +3646,7 @@ checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -3629,6 +3800,30 @@ "sha2 0.10.8", ] +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa 0.16.9", + "elliptic-curve 0.13.8", + "primeorder", + "sha2 0.10.8", +] + +[[package]] +name = "p384" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209" +dependencies = [ + "ecdsa 0.16.9", + "elliptic-curve 0.13.8", + "primeorder", + "sha2 0.10.8", +] + [[package]] name = "parking" version = "2.2.0" @@ -3691,6 +3886,26 @@ "hmac", ] +[[package]] +name = "pem" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd56cbd21fea48d0c440b41cd69c589faacade08c992d9a54e471b79d0fd13eb" +dependencies = [ + "base64 0.13.1", + "once_cell", + "regex", +] + +[[package]] +name = "pem" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" +dependencies = [ + "base64 0.13.1", +] + [[package]] name = "pem" version = "3.0.4" @@ -3701,6 +3916,15 @@ "serde", ] +[[package]] +name = "pem-rfc7468" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d159833a9105500e0398934e205e0773f0b27529557134ecfc51c27646adac" +dependencies = [ + "base64ct", +] + [[package]] name = "pem-rfc7468" version = "0.7.0" @@ -3781,6 +4005,18 @@ "futures-io", ] +[[package]] +name = "pkcs1" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff33bdbdfc54cc98a2eca766ebdec3e1b8fb7387523d5c9c9a2891da856f719" +dependencies = [ + "der 0.6.1", + "pkcs8 0.9.0", + "spki 0.6.0", + "zeroize", +] + [[package]] name = "pkcs12" version = "0.1.0" @@ -3788,7 +4024,7 @@ checksum = "695b3df3d3cc1015f12d70235e35b6b79befc5fa7a9b95b951eab1dd07c9efc2" dependencies = [ "cms", - "const-oid", + "const-oid 0.9.6", "der 0.7.9", "digest 0.10.7", "spki 0.7.3", @@ -3929,6 +4165,15 @@ "syn 2.0.65", ] +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve 0.13.8", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -4303,6 +4548,27 @@ "windows-sys 0.52.0", ] +[[package]] +name = "rsa" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "094052d5470cbcef561cb848a7209968c9f12dfa6d668f4bca048ac5de51099c" +dependencies = [ + "byteorder", + "digest 0.10.7", + "num-bigint-dig", + "num-integer", + "num-iter", + "num-traits", + "pkcs1", + "pkcs8 0.9.0", + "rand_core 0.6.4", + "signature 1.6.4", + "smallvec", + "subtle", + "zeroize", +] + [[package]] name = "rust-node-addon" version = "0.1.0" @@ -4587,6 +4853,17 @@ "zeroize", ] +[[package]] +name = "sec1_decode" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6326ddc956378a0739200b2c30892dccaf198992dfd7323274690b9e188af23" +dependencies = [ + "der 0.4.5", + "pem 0.8.3", + "thiserror", +] + [[package]] name = "security-framework" version = "2.11.0" @@ -4917,6 +5194,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-xid", +] + [[package]] name = "synstructure" version = "0.13.1" @@ -5524,6 +5813,7 @@ "tracing-subscriber", "tunnelbroker_messages", "uuid", + "web-push", ] [[package]] @@ -5588,6 +5878,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + [[package]] name = "universal-hash" version = "0.5.1" @@ -5719,6 +6015,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasix" +version = "0.12.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1fbb4ef9bbca0c1170e0b00dd28abc9e3b68669821600cad1caaed606583c6d" +dependencies = [ + "wasi 0.11.0+wasi-snapshot-preview1", +] + [[package]] name = "wasm-bindgen" version = "0.2.92" @@ -5798,6 +6103,28 @@ "web-sys", ] +[[package]] +name = "web-push" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5c5c6deab45e8820b77c9c8ae168f1ded4595767c746584bb67b9100f2b71d" +dependencies = [ + "async-trait", + "base64 0.13.1", + "chrono", + "ece", + "http 0.2.12", + "hyper", + "hyper-tls", + "jwt-simple", + "log", + "pem 1.1.1", + "sec1_decode", + "serde", + "serde_derive", + "serde_json", +] + [[package]] name = "web-sys" version = "0.3.69" @@ -6029,7 +6356,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1301e935010a701ae5f8655edc0ad17c44bad3ac5ce8c39185f75453b720ae94" dependencies = [ - "const-oid", + "const-oid 0.9.6", "der 0.7.9", "spki 0.7.3", ] diff --git a/services/tunnelbroker/Cargo.toml b/services/tunnelbroker/Cargo.toml --- a/services/tunnelbroker/Cargo.toml +++ b/services/tunnelbroker/Cargo.toml @@ -31,6 +31,9 @@ chrono = { workspace = true } uuid = { workspace = true, features = ["v4"] } jsonwebtoken = "9.3.0" +web-push = { version = "0.10", features = [ + "hyper-client", +], default-features = false } reqwest = { workspace = true, features = ["json", "native-tls", "rustls-tls"] } serde.workspace = true diff --git a/services/tunnelbroker/src/notifs/web_push/error.rs b/services/tunnelbroker/src/notifs/web_push/error.rs --- a/services/tunnelbroker/src/notifs/web_push/error.rs +++ b/services/tunnelbroker/src/notifs/web_push/error.rs @@ -2,14 +2,13 @@ #[derive(Debug, From, Display, Error)] pub enum Error { - JWTError, - ReqwestError(reqwest::Error), - InvalidHeaderValue(reqwest::header::InvalidHeaderValue), + Jwt, + WebPush(web_push::WebPushError), SerdeJson(serde_json::Error), } impl From for Error { fn from(_: jsonwebtoken::errors::Error) -> Self { - Self::JWTError + Self::Jwt } } diff --git a/services/tunnelbroker/src/notifs/web_push/mod.rs b/services/tunnelbroker/src/notifs/web_push/mod.rs --- a/services/tunnelbroker/src/notifs/web_push/mod.rs +++ b/services/tunnelbroker/src/notifs/web_push/mod.rs @@ -1,3 +1,9 @@ +use web_push::{ + ContentEncoding, HyperWebPushClient, SubscriptionInfo, VapidSignatureBuilder, + WebPushMessageBuilder, +}; +use web_push::{PartialVapidSignatureBuilder, WebPushClient as _}; + use crate::notifs::web_push::config::WebPushConfig; pub mod config; @@ -5,16 +11,22 @@ #[derive(Clone)] pub struct WebPushClient { - http_client: reqwest::Client, - config: WebPushConfig, + _config: WebPushConfig, + inner_client: HyperWebPushClient, + signature_builder: PartialVapidSignatureBuilder, } impl WebPushClient { pub fn new(config: &WebPushConfig) -> Result { - let http_client = reqwest::Client::builder().build()?; + let inner_client = HyperWebPushClient::new(); + let signature_builder = VapidSignatureBuilder::from_base64_no_sub( + &config.private_key, + web_push::URL_SAFE_NO_PAD, + )?; Ok(WebPushClient { - http_client, - config: config.clone(), + _config: config.clone(), + inner_client, + signature_builder, }) } }