From 04b9ef8222f6acec72a2176d3aa7579b24a46663 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Wed, 23 Jun 2021 17:59:22 -0600 Subject: [PATCH] appmgr: basic tor sync --- appmgr/Cargo.lock | 389 ++++++++++++---- appmgr/Cargo.toml | 33 +- appmgr/src/bin/embassyd.rs | 1 - appmgr/src/context/rpc.rs | 24 +- appmgr/src/error.rs | 5 + appmgr/src/id.rs | 12 + appmgr/src/net/mdns.rs | 2 + appmgr/src/net/tor.rs | 859 ++++++++++-------------------------- appmgr/src/s9pk/manifest.rs | 35 +- appmgr/src/util.rs | 3 + 10 files changed, 610 insertions(+), 753 deletions(-) diff --git a/appmgr/Cargo.lock b/appmgr/Cargo.lock index 1fbaf9e1e..a5e8f8b76 100644 --- a/appmgr/Cargo.lock +++ b/appmgr/Cargo.lock @@ -61,9 +61,9 @@ version = "0.1.51" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44318e776df68115a881de9a8fd1b9e53368d7a4a5ce4cc48517da3393233a5e" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.28", + "quote 1.0.9", + "syn 1.0.74", ] [[package]] @@ -107,6 +107,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23ce669cd6c8588f79e15cf450314f9638f967fc5770ff1c7c1deb0925ea7cfa" +[[package]] +name = "base64" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" +dependencies = [ + "byteorder", +] + [[package]] name = "base64" version = "0.13.0" @@ -129,8 +138,8 @@ dependencies = [ "lazycell", "log", "peeking_take_while", - "proc-macro2", - "quote", + "proc-macro2 1.0.28", + "quote 1.0.9", "regex", "rustc-hash", "shlex", @@ -166,13 +175,34 @@ dependencies = [ "constant_time_eq", ] +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding", + "byte-tools", + "byteorder", + "generic-array 0.12.4", +] + [[package]] name = "block-buffer" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "generic-array", + "generic-array 0.14.4", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", ] [[package]] @@ -181,7 +211,7 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "699194c00f3a2effd3358d47f880646818e3d483190b17ebcdf598c654fb77e9" dependencies = [ - "base64", + "base64 0.13.0", "bollard-stubs", "bytes 1.0.1", "chrono", @@ -241,6 +271,12 @@ version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631" +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + [[package]] name = "byteorder" version = "1.4.3" @@ -434,6 +470,16 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "crypto-mac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" +dependencies = [ + "generic-array 0.12.4", + "subtle 1.0.0", +] + [[package]] name = "csv" version = "1.1.6" @@ -472,9 +518,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" dependencies = [ "byteorder", - "digest", + "digest 0.9.0", "rand_core 0.5.1", - "subtle", + "subtle 2.4.1", "zeroize", ] @@ -496,10 +542,10 @@ checksum = "2c34d8efb62d0c2d7f60ece80f75e5c63c1588ba68032740494b0b9a996466e3" dependencies = [ "fnv", "ident_case", - "proc-macro2", - "quote", + "proc-macro2 1.0.28", + "quote 1.0.9", "strsim 0.10.0", - "syn", + "syn 1.0.74", ] [[package]] @@ -509,8 +555,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade7bff147130fe5e6d39f089c6bd49ec0250f35d70b2eebf72afdfc919f15cc" dependencies = [ "darling_core", - "quote", - "syn", + "quote 1.0.9", + "syn 1.0.74", +] + +[[package]] +name = "derive_more" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a141330240c921ec6d074a3e188a7c7ef95668bb95e7d44fa0e5778ec2a7afe" +dependencies = [ + "lazy_static", + "proc-macro2 0.4.30", + "quote 0.6.13", + "regex", + "rustc_version", + "syn 0.15.44", +] + +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array 0.12.4", ] [[package]] @@ -519,7 +588,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array", + "generic-array 0.14.4", ] [[package]] @@ -587,7 +656,7 @@ dependencies = [ "rand 0.7.3", "serde", "serde_bytes", - "sha2", + "sha2 0.9.5", "zeroize", ] @@ -608,7 +677,7 @@ dependencies = [ "bollard", "chrono", "clap", - "digest", + "digest 0.9.0", "ed25519-dalek", "emver", "futures", @@ -637,7 +706,7 @@ dependencies = [ "serde_cbor 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json", "serde_yaml", - "sha2", + "sha2 0.9.5", "simple-logging", "sqlx", "thiserror", @@ -647,6 +716,7 @@ dependencies = [ "tokio-tar", "tokio-util", "toml", + "torut", "typed-builder", "url", ] @@ -691,6 +761,12 @@ dependencies = [ "termcolor", ] +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + [[package]] name = "fd-lock-rs" version = "0.1.3" @@ -814,9 +890,9 @@ checksum = "c54913bae956fb8df7f4dc6fc90362aa72e69148e3f39041fbe8742d21e0ac57" dependencies = [ "autocfg", "proc-macro-hack", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.28", + "quote 1.0.9", + "syn 1.0.74", ] [[package]] @@ -852,6 +928,15 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + [[package]] name = "generic-array" version = "0.14.4" @@ -901,9 +986,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe69f1cbdb6e28af2bac214e943b99ce8a0a06b447d15d3e61161b0423139f3f" dependencies = [ "proc-macro-hack", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.28", + "quote 1.0.9", + "syn 1.0.74", ] [[package]] @@ -979,6 +1064,16 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hmac" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" +dependencies = [ + "crypto-mac", + "digest 0.8.1", +] + [[package]] name = "http" version = "0.2.4" @@ -1189,6 +1284,12 @@ dependencies = [ "serde_json", ] +[[package]] +name = "keccak" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" + [[package]] name = "lazy_static" version = "1.4.0" @@ -1429,6 +1530,12 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + [[package]] name = "opaque-debug" version = "0.3.0" @@ -1519,8 +1626,8 @@ name = "patch-db-macro" version = "0.1.0" dependencies = [ "patch-db-macro-internals", - "proc-macro2", - "syn", + "proc-macro2 1.0.28", + "syn 1.0.74", ] [[package]] @@ -1528,9 +1635,9 @@ name = "patch-db-macro-internals" version = "0.1.0" dependencies = [ "heck", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.28", + "quote 1.0.9", + "syn 1.0.74", ] [[package]] @@ -1560,9 +1667,9 @@ version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.28", + "quote 1.0.9", + "syn 1.0.74", ] [[package]] @@ -1621,13 +1728,22 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +dependencies = [ + "unicode-xid 0.1.0", +] + [[package]] name = "proc-macro2" version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612" dependencies = [ - "unicode-xid", + "unicode-xid 0.2.2", ] [[package]] @@ -1636,13 +1752,22 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +dependencies = [ + "proc-macro2 0.4.30", +] + [[package]] name = "quote" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" dependencies = [ - "proc-macro2", + "proc-macro2 1.0.28", ] [[package]] @@ -1814,7 +1939,7 @@ version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "246e9f61b9bb77df069a947682be06e31ac43ea37862e244a69f177694ea6d22" dependencies = [ - "base64", + "base64 0.13.0", "bytes 1.0.1", "encoding_rs", "futures-core", @@ -1891,18 +2016,18 @@ dependencies = [ name = "rpc-toolkit-macro" version = "0.1.0" dependencies = [ - "proc-macro2", + "proc-macro2 1.0.28", "rpc-toolkit-macro-internals", - "syn", + "syn 1.0.74", ] [[package]] name = "rpc-toolkit-macro-internals" version = "0.1.0" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.28", + "quote 1.0.9", + "syn 1.0.74", ] [[package]] @@ -1911,7 +2036,7 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb" dependencies = [ - "base64", + "base64 0.13.0", "blake2b_simd", "constant_time_eq", "crossbeam-utils", @@ -1923,13 +2048,22 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver", +] + [[package]] name = "rustls" version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" dependencies = [ - "base64", + "base64 0.13.0", "log", "ring", "sct", @@ -1997,6 +2131,21 @@ dependencies = [ "libc", ] +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + [[package]] name = "serde" version = "1.0.127" @@ -2039,9 +2188,9 @@ version = "1.0.127" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a024926d3432516606328597e0f224a51355a493b49fdd67e9209187cbe55ecc" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.28", + "quote 1.0.9", + "syn 1.0.74", ] [[package]] @@ -2086,9 +2235,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1569374bd54623ec8bd592cf22ba6e03c0f177ff55fbc8c29a49e296e7adecf" dependencies = [ "darling", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.28", + "quote 1.0.9", + "syn 1.0.74", ] [[package]] @@ -2103,17 +2252,48 @@ dependencies = [ "yaml-rust", ] +[[package]] +name = "sha1" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" + +[[package]] +name = "sha2" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug 0.2.3", +] + [[package]] name = "sha2" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b362ae5752fd2137731f9fa25fd4d9058af34666ca1966fb969119cc35719f12" dependencies = [ - "block-buffer", + "block-buffer 0.9.0", "cfg-if 1.0.0", "cpufeatures", - "digest", - "opaque-debug", + "digest 0.9.0", + "opaque-debug 0.3.0", +] + +[[package]] +name = "sha3" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf" +dependencies = [ + "block-buffer 0.7.3", + "byte-tools", + "digest 0.8.1", + "keccak", + "opaque-debug 0.2.3", ] [[package]] @@ -2229,7 +2409,7 @@ dependencies = [ "parking_lot", "percent-encoding", "rustls", - "sha2", + "sha2 0.9.5", "smallvec", "sqlformat", "sqlx-rt", @@ -2253,12 +2433,12 @@ dependencies = [ "futures", "heck", "once_cell", - "proc-macro2", - "quote", - "sha2", + "proc-macro2 1.0.28", + "quote 1.0.9", + "sha2 0.9.5", "sqlx-core", "sqlx-rt", - "syn", + "syn 1.0.74", "url", ] @@ -2301,21 +2481,38 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "subtle" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" + [[package]] name = "subtle" version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +[[package]] +name = "syn" +version = "0.15.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid 0.1.0", +] + [[package]] name = "syn" version = "1.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c" dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", + "proc-macro2 1.0.28", + "quote 1.0.9", + "unicode-xid 0.2.2", ] [[package]] @@ -2324,10 +2521,10 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "474aaa926faa1603c40b7885a9eaea29b444d1cb2850cb7c0e37bb1a4182f4fa" dependencies = [ - "proc-macro2", - "quote", - "syn", - "unicode-xid", + "proc-macro2 1.0.28", + "quote 1.0.9", + "syn 1.0.74", + "unicode-xid 0.2.2", ] [[package]] @@ -2394,9 +2591,9 @@ version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.28", + "quote 1.0.9", + "syn 1.0.74", ] [[package]] @@ -2488,9 +2685,9 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54473be61f4ebe4efd09cec9bd5d16fa51d70ea0192213d754d2d500457db110" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.28", + "quote 1.0.9", + "syn 1.0.74", ] [[package]] @@ -2563,6 +2760,28 @@ dependencies = [ "serde", ] +[[package]] +name = "torut" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b2cdfcb8b9dccc90fd618101a6f0a5a1f9e23e36956da9a2fe0abee901b04cc" +dependencies = [ + "base32", + "base64 0.10.1", + "derive_more", + "ed25519-dalek", + "hex", + "hmac", + "openssl", + "rand 0.7.3", + "serde", + "serde_derive", + "sha1", + "sha2 0.8.2", + "sha3", + "tokio 1.9.0", +] + [[package]] name = "tower-service" version = "0.3.1" @@ -2610,9 +2829,9 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "345426c7406aa355b60c5007c79a2d1f5b605540072795222f17f6443e6a9c6f" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.28", + "quote 1.0.9", + "syn 1.0.74", ] [[package]] @@ -2651,6 +2870,12 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" + [[package]] name = "unicode-xid" version = "0.2.2" @@ -2743,9 +2968,9 @@ dependencies = [ "bumpalo", "lazy_static", "log", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.28", + "quote 1.0.9", + "syn 1.0.74", "wasm-bindgen-shared", ] @@ -2767,7 +2992,7 @@ version = "0.2.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "171ebf0ed9e1458810dfcb31f2e766ad6b3a89dbda42d8901f2b268277e5f09c" dependencies = [ - "quote", + "quote 1.0.9", "wasm-bindgen-macro-support", ] @@ -2777,9 +3002,9 @@ version = "0.2.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c2657dd393f03aa2a659c25c6ae18a13a4048cebd220e147933ea837efc589f" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.28", + "quote 1.0.9", + "syn 1.0.74", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2927,8 +3152,8 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2c1e130bebaeab2f23886bf9acbaca14b092408c452543c857f66399cd6dab1" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.28", + "quote 1.0.9", + "syn 1.0.74", "synstructure", ] diff --git a/appmgr/Cargo.toml b/appmgr/Cargo.toml index bcf7b2a62..c8f92a46e 100644 --- a/appmgr/Cargo.toml +++ b/appmgr/Cargo.toml @@ -45,19 +45,19 @@ production = [] [dependencies] anyhow = "1.0.40" async-trait = "0.1.42" -avahi-sys = { git = "https://github.com/Start9Labs/avahi-sys", version = "0.10.0", branch = "feature/dynamic-linking", features = ["dynamic"], optional = true } +avahi-sys = { git="https://github.com/Start9Labs/avahi-sys", version="0.10.0", branch="feature/dynamic-linking", features=["dynamic"], optional=true } base32 = "0.4.0" bollard = "0.10.1" -chrono = { version = "0.4.19", features = ["serde"] } +chrono = { version="0.4.19", features=["serde"] } clap = "2.33" digest = "0.9.0" -ed25519-dalek = { version = "1.0.1", features = ["serde"] } -emver = { version = "0.1.2", features = ["serde"] } +ed25519-dalek = { version="1.0.1", features=["serde"] } +emver = { version="0.1.2", features=["serde"] } futures = "0.3.8" git-version = "0.3.4" http = "0.2.3" -id-pool = { version = "0.2.1", features = ["u16", "serde"], default-features = false } -indexmap = { version = "1.6.2", features = ["serde"] } +id-pool = { version="0.2.1", features=["u16", "serde"], default-features=false } +indexmap = { version="1.6.2", features=["serde"] } itertools = "0.10.0" jsonpath_lib = "0.2.6" lazy_static = "1.4" @@ -65,29 +65,30 @@ libc = "0.2.86" log = "0.4.11" nix = "0.20.0" openssl = "0.10.30" -patch-db = { version = "*", path = "../../patch-db/patch-db" } +patch-db = { version="*", path="../../patch-db/patch-db" } pin-project = "1.0.6" prettytable-rs = "0.8.0" rand = "0.8.3" regex = "1.4.2" -reqwest = { version = "0.11.2", features = ["stream", "json"] } +reqwest = { version="0.11.2", features=["stream", "json"] } rpassword = "5.0.0" -rpc-toolkit = { version = "*", path = "../../rpc-toolkit/rpc-toolkit" } +rpc-toolkit = { version="*", path="../../rpc-toolkit/rpc-toolkit" } rust-argon2 = "0.8.3" scopeguard = "1.1" # because avahi-sys fucks your shit up -serde = { version = "1.0.118", features = ["derive", "rc"] } +serde = { version="1.0.118", features=["derive", "rc"] } serde_cbor = "0.11.1" serde_json = "1.0.59" -serde_toml = { package = "toml", version = "0.5.8" } +serde_toml = { package="toml", version="0.5.8" } serde_yaml = "0.8.14" sha2 = "0.9.3" simple-logging = "2.0" -sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite"] } +sqlx = { version="0.5", features=["runtime-tokio-rustls", "sqlite"] } thiserror = "1.0.24" -tokio = { version = "1.5.0", features = ["full"] } +tokio = { version="1.5.0", features=["full"] } tokio-compat-02 = "0.2.0" -tokio-stream = { version = "0.1.5", features = ["io-util"] } +tokio-stream = { version="0.1.5", features=["io-util"] } tokio-tar = "0.3.0" -tokio-util = { version = "0.6.6", features = ["io"] } +tokio-util = { version="0.6.6", features=["io"] } +torut = "0.1.9" typed-builder = "0.9.0" -url = { version = "2.2.1", features = ["serde"] } +url = { version="2.2.1", features=["serde"] } diff --git a/appmgr/src/bin/embassyd.rs b/appmgr/src/bin/embassyd.rs index ae3da1d31..0a17ccc9b 100644 --- a/appmgr/src/bin/embassyd.rs +++ b/appmgr/src/bin/embassyd.rs @@ -28,7 +28,6 @@ async fn inner_main(cfg_path: Option<&str>) -> Result<(), Error> { command: embassy::main_api, context: ctx, status: status_fn, - }); let status_ctx = rpc_ctx.clone(); let status_daemon = daemon( diff --git a/appmgr/src/context/rpc.rs b/appmgr/src/context/rpc.rs index 816e95b65..c34ca5756 100644 --- a/appmgr/src/context/rpc.rs +++ b/appmgr/src/context/rpc.rs @@ -11,7 +11,8 @@ use serde::Deserialize; use sqlx::SqlitePool; use tokio::fs::File; -use crate::net::mdns::LanHandle; +use crate::net::mdns::{enable_lan, LanHandle}; +use crate::net::tor::TorController; use crate::util::{from_toml_async_reader, AsyncFileExt, Container}; use crate::{Error, ResultExt}; @@ -30,8 +31,8 @@ pub struct RpcContextSeed { pub db: PatchDb, pub secret_store: SqlitePool, pub docker: Docker, - // pub lan_handle: Container, - // pub + pub lan_handle: Container, + pub tor_controller: TorController, } #[derive(Clone)] @@ -50,14 +51,19 @@ impl RpcContext { } else { RpcContextConfig::default() }; + let db = PatchDb::open( + base.db + .unwrap_or_else(|| Path::new("/mnt/embassy-os/embassy.db").to_owned()), + ) + .await?; + let mut db_handle = db.handle(); + let lan_handle = Container::new(); + lan_handle.set(enable_lan(&mut db_handle).await?).await; + let tor_controller = TorController::init(&mut db_handle).await?; let seed = Arc::new(RpcContextSeed { bind_rpc: base.bind_rpc.unwrap_or(([127, 0, 0, 1], 5959).into()), bind_ws: base.bind_ws.unwrap_or(([127, 0, 0, 1], 5960).into()), - db: PatchDb::open( - base.db - .unwrap_or_else(|| Path::new("/mnt/embassy-os/embassy.db").to_owned()), - ) - .await?, + db, secret_store: SqlitePool::connect(&format!( "sqlite://{}", base.secret_store @@ -66,6 +72,8 @@ impl RpcContext { )) .await?, docker: Docker::connect_with_unix_defaults()?, + lan_handle, + tor_controller, }); Ok(Self(seed)) } diff --git a/appmgr/src/error.rs b/appmgr/src/error.rs index 4120a95d6..e3ac5b88a 100644 --- a/appmgr/src/error.rs +++ b/appmgr/src/error.rs @@ -173,6 +173,11 @@ impl From for Error { Error::new(e, ErrorKind::Docker) } } +impl From for Error { + fn from(e: torut::control::ConnError) -> Self { + Error::new(anyhow!("{:?}", e), ErrorKind::Tor) + } +} impl From for RpcError { fn from(e: Error) -> Self { let mut data_object = serde_json::Map::with_capacity(2); diff --git a/appmgr/src/id.rs b/appmgr/src/id.rs index 3a4e8dca0..35c67f3ea 100644 --- a/appmgr/src/id.rs +++ b/appmgr/src/id.rs @@ -90,6 +90,12 @@ impl<'a> Id<&'a str> { Id(self.0.to_owned()) } } +impl> std::ops::Deref for Id { + type Target = S; + fn deref(&self) -> &Self::Target { + &self.0 + } +} impl> std::fmt::Display for Id { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0.as_ref()) @@ -168,6 +174,12 @@ impl> std::fmt::Display for InterfaceId { write!(f, "{}", &self.0) } } +impl> std::ops::Deref for InterfaceId { + type Target = S; + fn deref(&self) -> &Self::Target { + &*self.0 + } +} impl> AsRef for InterfaceId { fn as_ref(&self) -> &str { self.0.as_ref() diff --git a/appmgr/src/net/mdns.rs b/appmgr/src/net/mdns.rs index fe233639a..c65905231 100644 --- a/appmgr/src/net/mdns.rs +++ b/appmgr/src/net/mdns.rs @@ -107,3 +107,5 @@ impl Drop for LanHandle { } } } +unsafe impl Send for LanHandle {} +unsafe impl Sync for LanHandle {} diff --git a/appmgr/src/net/tor.rs b/appmgr/src/net/tor.rs index bed57ea4d..811ef6576 100644 --- a/appmgr/src/net/tor.rs +++ b/appmgr/src/net/tor.rs @@ -1,664 +1,263 @@ -use std::collections::{BTreeSet, HashMap}; -use std::net::Ipv4Addr; -use std::os::unix::process::ExitStatusExt; -use std::path::{Path, PathBuf}; -use std::time::{Duration, Instant}; +use std::net::{Ipv4Addr, SocketAddr}; +use std::sync::Arc; use anyhow::anyhow; -use tokio::io::{AsyncReadExt, AsyncWriteExt}; +use futures::future::BoxFuture; +use futures::FutureExt; +use indexmap::IndexMap; +use patch_db::DbHandle; +use sqlx::pool::PoolConnection; +use sqlx::Sqlite; +use tokio::net::TcpStream; +use tokio::sync::RwLock; +use torut::control::{AsyncEvent, AuthenticatedConn, ConnError}; +use torut::onion::TorSecretKeyV3; -use crate::util::Invoke; +use crate::s9pk::manifest::TorConfig; use crate::{Error, ResultExt as _}; -#[derive(Debug, Clone, Copy, serde::Deserialize, serde::Serialize)] -#[serde(rename_all = "kebab-case")] -pub enum LanOptions { - Standard, - Custom { port: u16 }, +fn event_handler(event: AsyncEvent<'static>) -> BoxFuture<'static, Result<(), ConnError>> { + async move { Ok(()) }.boxed() } -#[derive(Debug, Clone, Copy, serde::Serialize)] -pub struct PortMapping { - pub internal: u16, - pub tor: u16, - pub lan: Option, // only for http interfaces -} -impl<'de> serde::de::Deserialize<'de> for PortMapping { - fn deserialize(deserializer: D) -> Result - where - D: serde::de::Deserializer<'de>, - { - #[derive(serde::Deserialize)] - pub struct PortMappingIF { - pub internal: u16, - pub tor: u16, - #[serde(default, deserialize_with = "deserialize_some")] - pub lan: Option>, +#[derive(Clone)] +pub struct TorController(Arc>); +impl TorController { + pub async fn init( + tor_cp: SocketAddr, + db: &mut Db, + secrets: &mut PoolConnection, + ) -> Result { + Ok(TorController(Arc::new(RwLock::new( + TorControllerInner::init(tor_cp, db, secrets).await?, + )))) + } + + pub async fn sync( + &self, + db: &mut Db, + secrets: &mut PoolConnection, + ) -> Result<(), Error> { + let new = TorControllerInner::get_services(db, secrets).await?; + if &new != &self.0.read().await.services { + self.0.write().await.sync(new).await?; } - - fn deserialize_some<'de, T, D>(deserializer: D) -> Result, D::Error> - where - T: serde::de::Deserialize<'de>, - D: serde::de::Deserializer<'de>, - { - serde::de::Deserialize::deserialize(deserializer).map(Some) - } - - let input_format: PortMappingIF = serde::de::Deserialize::deserialize(deserializer)?; - Ok(PortMapping { - internal: input_format.internal, - tor: input_format.tor, - lan: if let Some(lan) = input_format.lan { - lan - } else if input_format.tor == 80 { - Some(LanOptions::Standard) - } else { - None - }, - }) + Ok(()) } } -pub const ETC_TOR_RC: &'static str = "/etc/tor/torrc"; -pub const HIDDEN_SERVICE_DIR_ROOT: &'static str = "/var/lib/tor"; -pub const ETC_HOSTNAME: &'static str = "/etc/hostname"; -pub const ETC_NGINX_SERVICES_CONF: &'static str = "/etc/nginx/sites-available/start9-services.conf"; +type AuthenticatedConnection = AuthenticatedConn< + TcpStream, + fn(AsyncEvent<'static>) -> BoxFuture<'static, Result<(), ConnError>>, +>; -#[derive(Debug, Clone, Copy, serde::Deserialize, serde::Serialize)] -#[serde(rename_all = "lowercase")] -pub enum HiddenServiceVersion { - V1, - V2, - V3, -} -impl From for usize { - fn from(v: HiddenServiceVersion) -> Self { - match v { - HiddenServiceVersion::V1 => 1, - HiddenServiceVersion::V2 => 2, - HiddenServiceVersion::V3 => 3, - } - } -} -// impl std::convert::TryFrom for HiddenServiceVersion { -// type Error = anyhow::Error; -// fn try_from(v: usize) -> Result { -// Ok(match v { -// 1 => HiddenServiceVersion::V1, -// 2 => HiddenServiceVersion::V2, -// 3 => HiddenServiceVersion::V3, -// n => bail!("Invalid HiddenServiceVersion {}", n), -// }) -// } -// } -impl Default for HiddenServiceVersion { - fn default() -> Self { - HiddenServiceVersion::V3 - } -} -impl std::fmt::Display for HiddenServiceVersion { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "HiddenServiceVersion {}", usize::from(*self)) - } +#[derive(Clone, Debug, PartialEq, Eq)] +struct HiddenServiceConfig { + ip: Ipv4Addr, + cfg: TorConfig, } -#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] -pub struct Service { - pub ip: Ipv4Addr, - pub ports: Vec, - #[serde(default)] - pub hidden_service_version: HiddenServiceVersion, +pub struct TorControllerInner { + connection: AuthenticatedConnection, + services: IndexMap<[u8; 64], HiddenServiceConfig>, } - -#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] -pub struct NewService { - pub ports: Vec, - #[serde(default)] - pub hidden_service_version: HiddenServiceVersion, -} - -#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] -pub struct ServicesMap { - pub map: HashMap, - pub ips: BTreeSet, -} -impl Default for ServicesMap { - fn default() -> Self { - ServicesMap { - map: Default::default(), - ips: Default::default(), - } - } -} -impl ServicesMap { - pub fn add(&mut self, name: String, service: NewService) -> Ipv4Addr { - let ip = self - .map - .get(&name) - .map(|a| a.ip.clone()) - .unwrap_or_else(|| { - Ipv4Addr::from( - u32::from( - self.ips - .range(..) - .next_back() - .cloned() - .unwrap_or_else(|| crate::HOST_IP.into()), - ) + 1, - ) - }); - self.ips.insert(ip); - self.map.insert( - name, - Service { - ip, - ports: service.ports, - hidden_service_version: service.hidden_service_version, - }, - ); - ip - } - pub fn remove(&mut self, name: &str) { - let s = self.map.remove(name); - if let Some(s) = s { - self.ips.remove(&s.ip); - } - } -} - -pub async fn write_services(hidden_services: &ServicesMap) -> Result<(), Error> { - tokio::fs::copy(crate::TOR_RC, ETC_TOR_RC) - .await - .with_ctx(|_| { - ( - crate::ErrorKind::Filesystem, - format!("{} -> {}", crate::TOR_RC, ETC_TOR_RC), - ) - })?; - let mut f = tokio::fs::OpenOptions::new() - .append(true) - .open(ETC_TOR_RC) - .await?; - f.write_all(b"\n").await?; - for (name, service) in &hidden_services.map { - if service.ports.is_empty() { - continue; - } - f.write_all(b"\n").await?; - f.write_all(format!("# HIDDEN SERVICE FOR {}\n", name).as_bytes()) +impl TorControllerInner { + async fn get_services( + db: &mut Db, + secrets: &mut PoolConnection, + ) -> Result, Error> { + let pkg_ids = crate::db::DatabaseModel::new() + .package_data() + .keys(db) .await?; - f.write_all( - format!( - "HiddenServiceDir {}/app-{}/\n", - HIDDEN_SERVICE_DIR_ROOT, name - ) - .as_bytes(), - ) - .await?; - f.write_all(format!("{}\n", service.hidden_service_version).as_bytes()) - .await?; - for port in &service.ports { - f.write_all( - format!( - "HiddenServicePort {} {}:{}\n", - port.tor, service.ip, port.internal - ) - .as_bytes(), - ) - .await?; - } - f.write_all(b"\n").await?; - } - Ok(()) -} - -pub async fn write_lan_services(hidden_services: &ServicesMap) -> Result<(), Error> { - let mut f = tokio::fs::File::create(ETC_NGINX_SERVICES_CONF).await?; - for (app_id, service) in &hidden_services.map { - let hostname = tokio::fs::read_to_string( - Path::new(HIDDEN_SERVICE_DIR_ROOT) - .join(format!("app-{}", app_id)) - .join("hostname"), - ) - .await - .with_ctx(|_| { - ( - crate::ErrorKind::Filesystem, - format!("{}/app-{}/hostname", HIDDEN_SERVICE_DIR_ROOT, app_id), - ) - })?; - let hostname_str = hostname - .trim() - .strip_suffix(".onion") - .ok_or_else(|| anyhow!("{}", hostname)) - .with_kind(crate::ErrorKind::InvalidOnionAddress)?; - for mapping in &service.ports { - match &mapping.lan { - Some(LanOptions::Standard) => { - log::info!("Writing LAN certificates for {}", app_id); - let base_path: PathBuf = todo!(); //PersistencePath::from_ref("apps").join(&app_id); - let key_path = base_path.join("cert-local.key.pem"); - let conf_path = base_path.join("cert-local.csr.conf"); - let req_path = base_path.join("cert-local.csr"); - let cert_path = base_path.join("cert-local.crt.pem"); - let fullchain_path = base_path.join("cert-local.fullchain.crt.pem"); - if !fullchain_path.exists() || tokio::fs::metadata(&key_path).await.is_err() { - let mut fullchain_file = tokio::fs::File::create(&fullchain_path).await?; - tokio::process::Command::new("openssl") - .arg("ecparam") - .arg("-genkey") - .arg("-name") - .arg("prime256v1") - .arg("-noout") - .arg("-out") - .arg(&key_path) - .invoke(crate::ErrorKind::OpenSSL) - .await - .map_err(|e| { - let ctx = format!("GenKey: {}", e); - crate::Error::new(e.source.context(ctx), e.kind) - })?; - tokio::fs::write( - &conf_path, - format!( - include_str!("cert-local.csr.conf.template"), - hostname = hostname_str - ), - ) - .await?; - tokio::process::Command::new("openssl") - .arg("req") - .arg("-config") - .arg(&conf_path) - .arg("-key") - .arg(&key_path) - .arg("-new") - .arg("-addext") - .arg(format!( - "subjectAltName=DNS:{hostname}.local", - hostname = hostname_str - )) - .arg("-out") - .arg(&req_path) - .invoke(crate::ErrorKind::OpenSSL) - .await - .map_err(|e| { - let ctx = format!("Req: {}", e); - crate::Error::new(e.source.context(ctx), e.kind) - })?; - tokio::process::Command::new("openssl") - .arg("ca") - .arg("-batch") - .arg("-config") - .arg("/root/agent/ca/intermediate/openssl.conf") - .arg("-rand_serial") - .arg("-keyfile") - .arg("/root/agent/ca/intermediate/private/embassy-int-ca.key.pem") - .arg("-cert") - .arg("/root/agent/ca/intermediate/certs/embassy-int-ca.crt.pem") - .arg("-extensions") - .arg("server_cert") - .arg("-days") - .arg("365") - .arg("-notext") - .arg("-in") - .arg(&req_path) - .arg("-out") - .arg(&cert_path) - .invoke(crate::ErrorKind::OpenSSL) - .await - .map_err(|e| { - let ctx = format!("CA: {}", e); - crate::Error::new(e.source.context(ctx), e.kind) - })?; - log::info!("Writing fullchain to: {}", fullchain_path.display()); - tokio::io::copy( - &mut tokio::fs::File::open(&cert_path).await?, - &mut fullchain_file, - ) - .await?; - tokio::io::copy( - &mut tokio::fs::File::open( - "/root/agent/ca/intermediate/certs/embassy-int-ca.crt.pem", - ) - .await - .with_ctx(|_| { - ( - crate::ErrorKind::Filesystem, - "/root/agent/ca/intermediate/certs/embassy-int-ca.crt.pem", - ) - })?, - &mut fullchain_file, - ) - .await?; - tokio::io::copy( - &mut tokio::fs::File::open( - "/root/agent/ca/certs/embassy-root-ca.cert.pem", - ) - .await - .with_ctx(|_| { - ( - crate::ErrorKind::Filesystem, - "/root/agent/ca/certs/embassy-root-ca.cert.pem", - ) - })?, - &mut fullchain_file, - ) - .await?; - log::info!("{} written successfully", fullchain_path.display()); - } - f.write_all( - format!( - include_str!("nginx-standard.conf.template"), - hostname = hostname_str, - app_ip = service.ip, - internal_port = mapping.internal, - app_id = app_id, - ) - .as_bytes(), - ) - .await?; - f.sync_all().await?; - } - Some(LanOptions::Custom { port }) => { - f.write_all( - format!( - include_str!("nginx.conf.template"), - hostname = hostname_str, - app_ip = service.ip, - port = port, - internal_port = mapping.internal, - ) - .as_bytes(), - ) + let mut services = IndexMap::new(); + for pkg_id in pkg_ids { + if let Some(installed) = crate::db::DatabaseModel::new() + .package_data() + .idx_model(&pkg_id) + .expect(db) + .await? + .installed() + .check(db) + .await? + { + let ifaces = installed + .clone() + .manifest() + .interfaces() + .get(db) .await? - } - None => (), - } - } - } - - Ok(()) -} - -pub async fn read_tor_address(name: &str, timeout: Option) -> Result { - log::info!("Retrieving Tor hidden service address for {}.", name); - let addr_path = Path::new(HIDDEN_SERVICE_DIR_ROOT) - .join(format!("app-{}", name)) - .join("hostname"); - if let Some(timeout) = timeout { - let start = Instant::now(); - while { - if addr_path.exists() { - false - } else { - if start.elapsed() >= timeout { - log::warn!("Timed out waiting for tor to start."); - false - } else { - true + .to_owned(); + for (iface_id, cfgs) in ifaces.0 { + if let Some(tor_cfg) = cfgs.tor_config { + if let Some(key) = sqlx::query!( + "SELECT key FROM tor WHERE package = ? AND interface = ?", + *pkg_id, + *iface_id, + ) + .fetch_optional(&mut *secrets) + .await? + { + if key.key.len() != 64 { + return Err(Error::new( + anyhow!("Invalid key length"), + crate::ErrorKind::Database, + )); + } + let mut buf = [0; 64]; + buf.clone_from_slice(&key.key); + services.insert( + buf, + HiddenServiceConfig { + ip: installed + .clone() + .interface_info() + .ip() + .get(db) + .await? + .to_owned(), + cfg: tor_cfg, + }, + ); + } + } } } - } { - tokio::time::sleep(Duration::from_millis(100)).await; } + Ok(services) } - let tor_addr = match tokio::fs::read_to_string(&addr_path).await { - Err(e) if e.kind() == std::io::ErrorKind::NotFound => { - Err(e).with_ctx(|_| (crate::ErrorKind::NotFound, addr_path.display().to_string())) - } - a => a.with_ctx(|_| { - ( - crate::ErrorKind::Filesystem, - addr_path.display().to_string(), + + async fn add_svc( + &mut self, + key: &TorSecretKeyV3, + config: &HiddenServiceConfig, + ) -> Result<(), Error> { + self.connection + .add_onion_v3( + key, + false, + false, + false, + None, + &mut config + .cfg + .port_mapping + .iter() + .map(|(external, internal)| { + (*external, SocketAddr::from((config.ip, *internal))) + }) + .collect::>() + .iter(), ) - }), - }?; - Ok(tor_addr.trim().to_owned()) -} + .await?; + Ok(()) + } -pub async fn read_tor_key( - name: &str, - version: HiddenServiceVersion, - timeout: Option, -) -> Result { - log::info!("Retrieving Tor hidden service key for {}.", name); - let addr_path = Path::new(HIDDEN_SERVICE_DIR_ROOT) - .join(format!("app-{}", name)) - .join(match version { - HiddenServiceVersion::V3 => "hs_ed25519_secret_key", - _ => "private_key", - }); - if let Some(timeout) = timeout { - let start = Instant::now(); - while { - if addr_path.exists() { - false - } else { - if start.elapsed() >= timeout { - log::warn!("Timed out waiting for tor to start."); - false - } else { - true + async fn sync( + &mut self, + services: IndexMap<[u8; 64], HiddenServiceConfig>, + ) -> Result<(), Error> { + for (key, new) in &services { + let tor_key = TorSecretKeyV3::from(key.clone()); + if let Some(old) = self.services.remove(&key[..]) { + if new != &old { + self.connection + .del_onion( + &tor_key + .public() + .get_onion_address() + .get_address_without_dot_onion(), + ) + .await?; + self.add_svc(&tor_key, new).await?; } + } else { + self.add_svc(&tor_key, new).await?; } - } { - tokio::time::sleep(Duration::from_millis(100)).await; } - } - let tor_key = match version { - HiddenServiceVersion::V3 => { - let mut f = tokio::fs::File::open(&addr_path).await.with_ctx(|_| { - ( - crate::ErrorKind::Filesystem, - addr_path.display().to_string(), + for (key, _) in self.services.drain(..) { + self.connection + .del_onion( + &TorSecretKeyV3::from(key) + .public() + .get_onion_address() + .get_address_without_dot_onion(), ) - })?; - let mut buf = [0; 96]; - f.read_exact(&mut buf).await?; - base32::encode(base32::Alphabet::RFC4648 { padding: false }, &buf[32..]).to_lowercase() + .await?; } - _ => tokio::fs::read_to_string(&addr_path) - .await - .with_ctx(|_| { - ( - crate::ErrorKind::Filesystem, - addr_path.display().to_string(), - ) - })? - .trim_end_matches("\u{0}") - .to_string(), - }; - Ok(tor_key.trim().to_owned()) -} - -pub async fn set_svc( - name: &str, - service: NewService, -) -> Result<(Ipv4Addr, Option, Option), Error> { - log::info!( - "Adding Tor hidden service {} to {}.", - name, - crate::SERVICES_YAML - ); - let is_listening = !service.ports.is_empty(); - // let path = PersistencePath::from_ref(crate::SERVICES_YAML); - let mut hidden_services: ServicesMap = todo!(); //services_map_mut(path).await?; - let ver = service.hidden_service_version; - let ip = hidden_services.add(name.to_owned(), service); - log::info!("Adding Tor hidden service {} to {}.", name, ETC_TOR_RC); - write_services(&hidden_services).await?; - let addr_path = Path::new(HIDDEN_SERVICE_DIR_ROOT) - .join(format!("app-{}", name)) - .join("hostname"); - tokio::fs::remove_file(addr_path).await.or_else(|e| { - if e.kind() == std::io::ErrorKind::NotFound { - Ok(()) - } else { - Err(e) - } - })?; - #[cfg(target_os = "linux")] - nix::unistd::sync(); - log::info!("Reloading Tor."); - let svc_exit = std::process::Command::new("service") - .args(&["tor", "reload"]) - .status()?; - crate::ensure_code!( - svc_exit.success(), - crate::ErrorKind::Tor, - "Failed to Reload Tor: {}", - svc_exit - .code() - .or_else(|| { svc_exit.signal().map(|a| 128 + a) }) - .unwrap_or(0) - ); - let addr = if is_listening { - Some(read_tor_address(name, Some(Duration::from_secs(30))).await?) - } else { - None - }; - let key = if is_listening { - Some(read_tor_key(name, ver, Some(Duration::from_secs(30))).await?) - } else { - None - }; - write_lan_services(&hidden_services).await?; - log::info!("Reloading Nginx."); - let svc_exit = std::process::Command::new("service") - .args(&["nginx", "reload"]) - .status()?; - crate::ensure_code!( - svc_exit.success(), - crate::ErrorKind::Nginx, - "Failed to Reload Nginx: {}", - svc_exit - .code() - .or_else(|| { svc_exit.signal().map(|a| 128 + a) }) - .unwrap_or(0) - ); - Ok((ip, addr, key)) -} - -pub async fn rm_svc(name: &str) -> Result<(), Error> { - log::info!( - "Removing Tor hidden service {} from {}.", - name, - crate::SERVICES_YAML - ); - // let path = PersistencePath::from_ref(crate::SERVICES_YAML); - let mut hidden_services: ServicesMap = todo!(); //services_map_mut(path).await?; - hidden_services.remove(name); - let hidden_service_path = Path::new(HIDDEN_SERVICE_DIR_ROOT).join(format!("app-{}", name)); - log::info!("Removing {}", hidden_service_path.display()); - if hidden_service_path.exists() { - tokio::fs::remove_dir_all(hidden_service_path).await?; + self.services = services; + Ok(()) } - log::info!("Removing Tor hidden service {} from {}.", name, ETC_TOR_RC); - write_services(&hidden_services).await?; - log::info!("Reloading Tor."); - let svc_exit = std::process::Command::new("service") - .args(&["tor", "reload"]) - .status()?; - crate::ensure_code!( - svc_exit.success(), - crate::ErrorKind::Tor, - "Failed to Reload Tor: {}", - svc_exit.code().unwrap_or(0) - ); - write_lan_services(&hidden_services).await?; - log::info!("Reloading Nginx."); - let svc_exit = std::process::Command::new("service") - .args(&["nginx", "reload"]) - .status()?; - crate::ensure_code!( - svc_exit.success(), - crate::ErrorKind::Nginx, - "Failed to Reload Nginx: {}", - svc_exit - .code() - .or_else(|| { svc_exit.signal().map(|a| 128 + a) }) - .unwrap_or(0) - ); - Ok(()) -} -pub async fn change_key( - name: &str, - key: Option<&ed25519_dalek::ExpandedSecretKey>, -) -> Result<(), Error> { - let hidden_service_path = Path::new(HIDDEN_SERVICE_DIR_ROOT).join(format!("app-{}", name)); - log::info!("Removing {}", hidden_service_path.display()); - if hidden_service_path.exists() { - tokio::fs::remove_dir_all(&hidden_service_path) - .await - .with_ctx(|_| { - ( - crate::ErrorKind::Filesystem, - hidden_service_path.display().to_string(), - ) - })?; + async fn init( + tor_cp: SocketAddr, + db: &mut Db, + secrets: &mut PoolConnection, + ) -> Result { + let mut conn = torut::control::UnauthenticatedConn::new( + TcpStream::connect(tor_cp).await?, // TODO + ); + let auth = conn + .load_protocol_info() + .await? + .make_auth_data()? + .ok_or_else(|| anyhow!("Cookie Auth Not Available")) + .with_kind(crate::ErrorKind::Tor)?; + conn.authenticate(&auth).await?; + let mut connection: AuthenticatedConnection = conn.into_authenticated().await; + connection.set_async_event_handler(Some(event_handler)); + let mut res = TorControllerInner { + connection, + services: IndexMap::new(), + }; + res.sync(Self::get_services(db, secrets).await?).await?; + Ok(res) } - if let Some(key) = key { - tokio::fs::create_dir_all(&hidden_service_path).await?; - let key_path = hidden_service_path.join("hs_ed25519_secret_key"); - let mut key_data = b"== ed25519v1-secret: type0 ==".to_vec(); - key_data.extend_from_slice(&key.to_bytes()); - tokio::fs::write(&key_path, key_data) +} + +#[tokio::test] +async fn test() { + let mut conn = torut::control::UnauthenticatedConn::new( + TcpStream::connect(SocketAddr::from(([127, 0, 0, 1], 9051))) .await - .with_ctx(|_| (crate::ErrorKind::Filesystem, key_path.display().to_string()))?; - } - log::info!("Reloading Tor."); - let svc_exit = std::process::Command::new("service") - .args(&["tor", "reload"]) - .status()?; - crate::ensure_code!( - svc_exit.success(), - crate::ErrorKind::Tor, - "Failed to Reload Tor: {}", - svc_exit.code().unwrap_or(0) + .unwrap(), // TODO ); - // let mut info = crate::apps::list_info_mut().await?; - // if let Some(mut i) = info.get_mut(name) { - // if i.tor_address.is_some() { - // i.tor_address = Some(read_tor_address(name, Some(Duration::from_secs(30))).await?); - // } - // } - Ok(()) -} - -pub async fn reload() -> Result<(), Error> { - // let path = PersistencePath::from_ref(crate::SERVICES_YAML); - let hidden_services = todo!(); //services_map(&path).await?; - log::info!("Syncing Tor hidden services to {}.", ETC_TOR_RC); - write_services(&hidden_services).await?; - log::info!("Reloading Tor."); - let svc_exit = std::process::Command::new("service") - .args(&["tor", "reload"]) - .status()?; - crate::ensure_code!( - svc_exit.success(), - crate::ErrorKind::Tor, - "Failed to Reload Tor: {}", - svc_exit.code().unwrap_or(0) - ); - Ok(()) -} - -pub async fn restart() -> Result<(), Error> { - // let path = PersistencePath::from_ref(crate::SERVICES_YAML); - let hidden_services = todo!(); //services_map(&path).await?; - log::info!("Syncing Tor hidden services to {}.", ETC_TOR_RC); - write_services(&hidden_services).await?; - log::info!("Restarting Tor."); - let svc_exit = std::process::Command::new("service") - .args(&["tor", "restart"]) - .status()?; - crate::ensure_code!( - svc_exit.success(), - crate::ErrorKind::Tor, - "Failed to Restart Tor: {}", - svc_exit.code().unwrap_or(0) - ); - Ok(()) + let auth = conn + .load_protocol_info() + .await + .unwrap() + .make_auth_data() + .unwrap() + .ok_or_else(|| anyhow!("Cookie Auth Not Available")) + .with_kind(crate::ErrorKind::Tor) + .unwrap(); + conn.authenticate(&auth).await.unwrap(); + let mut connection: AuthenticatedConn< + TcpStream, + fn(AsyncEvent<'static>) -> BoxFuture<'static, Result<(), ConnError>>, + > = conn.into_authenticated().await; + let tor_key = torut::onion::TorSecretKeyV3::generate(); + dbg!(connection.get_conf("SocksPort").await.unwrap()); + connection + .add_onion_v3( + &tor_key, + false, + false, + false, + None, + &mut [(443_u16, SocketAddr::from(([127, 0, 0, 1], 8443)))].iter(), + ) + .await + .unwrap(); + connection + .add_onion_v3( + &tor_key, + false, + false, + false, + None, + &mut [(8443_u16, SocketAddr::from(([127, 0, 0, 1], 8443)))].iter(), + ) + .await + .unwrap(); } diff --git a/appmgr/src/s9pk/manifest.rs b/appmgr/src/s9pk/manifest.rs index 028f345a2..1b6aa420e 100644 --- a/appmgr/src/s9pk/manifest.rs +++ b/appmgr/src/s9pk/manifest.rs @@ -17,7 +17,6 @@ use crate::dependencies::Dependencies; use crate::id::{Id, InterfaceId, InvalidId, SYSTEM_ID}; use crate::migration::Migrations; use crate::net::host::Hosts; -use crate::net::tor::HiddenServiceVersion; use crate::status::health_check::{HealthCheckResult, HealthChecks}; use crate::util::Version; use crate::volume::Volumes; @@ -33,6 +32,12 @@ impl FromStr for PackageId { Ok(PackageId(Id::try_from(s.to_owned())?)) } } +impl> std::ops::Deref for PackageId { + type Target = S; + fn deref(&self) -> &Self::Target { + &*self.0 + } +} impl> AsRef> for PackageId { fn as_ref(&self) -> &PackageId { self @@ -129,7 +134,7 @@ pub struct Manifest { #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "kebab-case")] -pub struct Interfaces(IndexMap); // TODO +pub struct Interfaces(pub IndexMap); // TODO impl Interfaces { pub async fn install(&self, ip: Ipv4Addr) -> Result { todo!() @@ -139,37 +144,35 @@ impl Interfaces { #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "kebab-case")] pub struct Interface { - tor_config: Option, - lan_config: Option>, - ui: bool, - protocols: Vec, + pub tor_config: Option, + pub lan_config: Option>, + pub ui: bool, + pub protocols: Vec, } -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] #[serde(rename_all = "kebab-case")] pub struct TorConfig { - #[serde(default)] - hidden_service_version: HiddenServiceVersion, - port_mapping: IndexMap, + pub port_mapping: IndexMap, } #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "kebab-case")] pub struct LanPortConfig { - ssl: bool, - mapping: u16, + pub ssl: bool, + pub mapping: u16, } #[derive(Clone, Debug, Default, Deserialize, Serialize)] pub struct Assets { #[serde(default)] - license: Option, + pub license: Option, #[serde(default)] - icon: Option, + pub icon: Option, #[serde(default)] - docker_images: Option, + pub docker_images: Option, #[serde(default)] - instructions: Option, + pub instructions: Option, } impl Assets { pub fn license_path(&self) -> &Path { diff --git a/appmgr/src/util.rs b/appmgr/src/util.rs index 1d38853df..d79300481 100644 --- a/appmgr/src/util.rs +++ b/appmgr/src/util.rs @@ -798,6 +798,9 @@ pub fn parse_duration(arg: &str, matches: &ArgMatches<'_>) -> Result(RwLock>); impl Container { + pub fn new() -> Self { + Container(RwLock::new(None)) + } pub async fn set(&self, value: T) { *self.0.write().await = Some(value); }