diff --git a/Cargo.lock b/Cargo.lock index 14cf33f92..2f3fec720 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -89,6 +89,21 @@ name = "anyhow" version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" +dependencies = [ + "backtrace", +] + +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" + +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" [[package]] name = "ascii_utils" @@ -96,6 +111,45 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71938f30533e4d95a6d17aa530939da3842c2ab6f4f84b9dae68447e4129f74a" +[[package]] +name = "asn1-rs" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf6690c370453db30743b373a60ba498fc0d6d83b11f4abfd87a84a075db5dd4" +dependencies = [ + "asn1-rs-derive", + "asn1-rs-impl", + "displaydoc", + "nom 7.1.1", + "num-traits", + "rusticata-macros", + "thiserror", + "time 0.3.17", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "asn1-rs-impl" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "async-channel" version = "1.8.0" @@ -353,6 +407,23 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "bao" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3663af8a469bf3a2d818b8c1a7b62e4dc55c4547b4c14f5dab35fc9e707bef83" +dependencies = [ + "arrayref", + "arrayvec", + "blake3", +] + +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + [[package]] name = "base64" version = "0.11.0" @@ -401,6 +472,20 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "blake3" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ae2468a89544a466886840aa467a25b766499f4f04bf7d9fcd10ecee9fccef" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "digest 0.10.5", +] + [[package]] name = "block-buffer" version = "0.9.0" @@ -544,7 +629,7 @@ dependencies = [ "js-sys", "num-integer", "num-traits", - "time", + "time 0.1.44", "wasm-bindgen", "winapi", ] @@ -593,11 +678,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" dependencies = [ "bitflags", - "clap_lex", + "clap_lex 0.2.4", "indexmap", "textwrap", ] +[[package]] +name = "clap" +version = "4.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f13b9c79b5d1dd500d20ef541215a6423c75829ef43117e1b4d17fd8af0b5d76" +dependencies = [ + "bitflags", + "clap_derive", + "clap_lex 0.3.1", + "is-terminal", + "once_cell", + "strsim", + "termcolor", +] + +[[package]] +name = "clap_derive" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "684a277d672e91966334af371f1a7b5833f9aa00b07c84e92fbce95e00208ce8" +dependencies = [ + "heck", + "proc-macro-error 1.0.4", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "clap_lex" version = "0.2.4" @@ -607,6 +720,15 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "clap_lex" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "clipboard-win" version = "4.4.2" @@ -618,6 +740,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "cobs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" + [[package]] name = "color_quant" version = "1.1.0" @@ -633,12 +761,51 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "console" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d79fbe8970a77e3e34151cc13d3b3e248aa0faaecb9f6091fa07ebefe5ad60" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "unicode-width", + "windows-sys 0.42.0", +] + [[package]] name = "const-oid" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "722e23542a15cea1f65d4a1419c4cfd7a26706c70871a13a04238ca3f40f1661" +[[package]] +name = "const_format" +version = "0.2.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7309d9b4d3d2c0641e018d449232f2e28f1b22933c137f157d3dbc14228b8c0e" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f47bf7270cf70d370f8f98c1abb6d2d4cf60a6845d30e05bfb90c6568650" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "constant_time_eq" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3ad85c1f65dc7b37604eb0e89748faf0b9653065f2a8ef69f96a687ec1e9279" + [[package]] name = "convert_case" version = "0.5.0" @@ -695,7 +862,7 @@ dependencies = [ "atty", "cast", "ciborium", - "clap", + "clap 3.2.23", "criterion-plot", "futures", "itertools", @@ -753,7 +920,7 @@ dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", - "memoffset", + "memoffset 0.6.5", "once_cell", "scopeguard", ] @@ -778,6 +945,18 @@ dependencies = [ "once_cell", ] +[[package]] +name = "crypto-bigint" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +dependencies = [ + "generic-array", + "rand_core 0.6.3", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -788,6 +967,17 @@ dependencies = [ "typenum", ] +[[package]] +name = "cuckoofilter" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b810a8449931679f64cd7eef1bbd0fa315801b6d5d9cdc1ace2804d6529eee18" +dependencies = [ + "byteorder", + "fnv", + "rand 0.7.3", +] + [[package]] name = "curve25519-dalek" version = "3.2.0" @@ -931,6 +1121,7 @@ dependencies = [ "rust-hsluv", "rustyline", "sanitize-filename", + "sendme", "serde", "serde_json", "sha-1", @@ -1021,10 +1212,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13dd2ae565c0a381dde7fade45fce95984c568bdcb4700a4fdbe3175e0380b2f" dependencies = [ "const-oid", + "der_derive", "pem-rfc7468", "zeroize", ] +[[package]] +name = "der-parser" +version = "8.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d4bc9b0db0a0df9ae64634ac5bdefb7afcb534e182275ca0beadbe486701c1" +dependencies = [ + "asn1-rs", + "displaydoc", + "nom 7.1.1", + "num-bigint", + "num-traits", + "rusticata-macros", +] + +[[package]] +name = "der_derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ef71ddb5b3a1f53dee24817c8f70dfa1cb29e804c18d88c228d4bc9c86ee3b9" +dependencies = [ + "proc-macro-error 1.0.4", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "derive_builder" version = "0.11.2" @@ -1083,6 +1301,7 @@ dependencies = [ "block-buffer 0.10.2", "const-oid", "crypto-common", + "subtle", ] [[package]] @@ -1126,12 +1345,36 @@ dependencies = [ "winapi", ] +[[package]] +name = "displaydoc" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "ecdsa" +version = "0.14.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" +dependencies = [ + "der", + "elliptic-curve", + "rfc6979", + "signature", +] + [[package]] name = "ed25519" version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9c280362032ea4203659fc489832d0204ef09f247a0506f170dafcac08c369" dependencies = [ + "serde", "signature", ] @@ -1145,6 +1388,7 @@ dependencies = [ "ed25519", "rand 0.7.3", "serde", + "serde_bytes", "sha2 0.9.9", "zeroize", ] @@ -1155,6 +1399,25 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" +[[package]] +name = "elliptic-curve" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +dependencies = [ + "base16ct", + "crypto-bigint", + "der", + "digest 0.10.5", + "ff", + "generic-array", + "group", + "rand_core 0.6.3", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "email" version = "0.0.21" @@ -1166,10 +1429,16 @@ dependencies = [ "encoding", "lazy_static", "rand 0.7.3", - "time", + "time 0.1.44", "version_check 0.9.4", ] +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + [[package]] name = "encoded-words" version = "0.2.0" @@ -1407,6 +1676,16 @@ dependencies = [ "windows-sys 0.36.1", ] +[[package]] +name = "ff" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +dependencies = [ + "rand_core 0.6.3", + "subtle", +] + [[package]] name = "filetime" version = "0.2.17" @@ -1567,6 +1846,37 @@ dependencies = [ "slab", ] +[[package]] +name = "genawaiter" +version = "0.99.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c86bd0361bcbde39b13475e6e36cb24c329964aa2611be285289d1e4b751c1a0" +dependencies = [ + "futures-core", + "genawaiter-macro", + "genawaiter-proc-macro", + "proc-macro-hack", +] + +[[package]] +name = "genawaiter-macro" +version = "0.99.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b32dfe1fdfc0bbde1f22a5da25355514b5e450c33a6af6770884c8750aedfbc" + +[[package]] +name = "genawaiter-proc-macro" +version = "0.99.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784f84eebc366e15251c4a8c3acee82a6a6f427949776ecb88377362a9621738" +dependencies = [ + "proc-macro-error 0.4.12", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "generic-array" version = "0.14.6" @@ -1615,6 +1925,17 @@ version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793" +[[package]] +name = "group" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +dependencies = [ + "ff", + "rand_core 0.6.3", + "subtle", +] + [[package]] name = "h2" version = "0.3.13" @@ -1640,6 +1961,12 @@ version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" +[[package]] +name = "hash_hasher" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74721d007512d0cb3338cd20f0654ac913920061a4c4d0d8708edb3f2a698c0c" + [[package]] name = "hashbrown" version = "0.11.2" @@ -1697,6 +2024,21 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hex-literal" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.5", +] + [[package]] name = "hostname" version = "0.3.1" @@ -1899,6 +2241,19 @@ dependencies = [ "hashbrown 0.12.3", ] +[[package]] +name = "indicatif" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cef509aa9bc73864d6756f0d34d35504af3cf0844373afe9b8669a5b8005a729" +dependencies = [ + "console", + "number_prefix", + "portable-atomic", + "tokio", + "unicode-width", +] + [[package]] name = "inout" version = "0.1.3" @@ -1917,6 +2272,15 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "intrusive-collections" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f4f90afb01281fdeffb0f8e082d230cbe4f888f837cc90759696b858db1a700" +dependencies = [ + "memoffset 0.8.0", +] + [[package]] name = "io-lifetimes" version = "0.7.2" @@ -2037,7 +2401,7 @@ dependencies = [ "lettre", "mime", "regex", - "time", + "time 0.1.44", "uuid 0.8.2", ] @@ -2128,6 +2492,15 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata", +] + [[package]] name = "matches" version = "0.1.9" @@ -2170,6 +2543,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memoffset" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +dependencies = [ + "autocfg", +] + [[package]] name = "mime" version = "0.3.16" @@ -2285,6 +2667,17 @@ dependencies = [ "memchr", ] +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-bigint-dig" version = "0.8.1" @@ -2366,6 +2759,12 @@ dependencies = [ "libc", ] +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + [[package]] name = "object" version = "0.30.0" @@ -2375,6 +2774,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "oid-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff" +dependencies = [ + "asn1-rs", +] + [[package]] name = "once_cell" version = "1.17.0" @@ -2480,12 +2888,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "734aa7a4a6390b162112523cac2923a18e4f23b917880a68c826bf6e8bf48f06" dependencies = [ "Inflector", - "proc-macro-error", + "proc-macro-error 1.0.4", "proc-macro2", "quote", "syn", ] +[[package]] +name = "p256" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" +dependencies = [ + "ecdsa", + "elliptic-curve", + "sha2 0.10.6", +] + +[[package]] +name = "p384" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc8c5bf642dde52bb9e87c0ecd8ca5a76faac2eeed98dedb7c717997e1080aa" +dependencies = [ + "ecdsa", + "elliptic-curve", + "sha2 0.10.6", +] + [[package]] name = "parking" version = "2.0.0" @@ -2515,6 +2945,15 @@ dependencies = [ "windows-sys 0.36.1", ] +[[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-rfc7468" version = "0.6.0" @@ -2675,6 +3114,35 @@ dependencies = [ "miniz_oxide 0.6.2", ] +[[package]] +name = "portable-atomic" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26f6a7b87c2e435a3241addceeeff740ff8b7e76b74c13bf9acb17fa454ea00b" + +[[package]] +name = "postcard" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c2b180dc0bade59f03fd005cb967d3f1e5f69b13922dad0cd6e047cb8af2363" +dependencies = [ + "cobs", + "const_format", + "postcard-derive", + "serde", +] + +[[package]] +name = "postcard-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9a87b20c0f64e4a835a7f006bff0bbcefed3bf67828fd4608579e6b51e1ebd0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "ppv-lite86" version = "0.2.16" @@ -2691,19 +3159,45 @@ dependencies = [ "log", ] +[[package]] +name = "proc-macro-error" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7" +dependencies = [ + "proc-macro-error-attr 0.4.12", + "proc-macro2", + "quote", + "syn", + "version_check 0.9.4", +] + [[package]] name = "proc-macro-error" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ - "proc-macro-error-attr", + "proc-macro-error-attr 1.0.4", "proc-macro2", "quote", "syn", "version_check 0.9.4", ] +[[package]] +name = "proc-macro-error-attr" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a5b4b77fdb63c1eca72173d68d24501c54ab1269409f6b672c85deb18af69de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "syn-mid", + "version_check 0.9.4", +] + [[package]] name = "proc-macro-error-attr" version = "1.0.4" @@ -2715,6 +3209,12 @@ dependencies = [ "version_check 0.9.4", ] +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + [[package]] name = "proc-macro2" version = "1.0.46" @@ -2922,6 +3422,18 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "rcgen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b" +dependencies = [ + "pem", + "ring", + "time 0.3.17", + "yasna", +] + [[package]] name = "redox_syscall" version = "0.2.16" @@ -2953,6 +3465,15 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax", +] + [[package]] name = "regex-syntax" version = "0.6.27" @@ -3015,6 +3536,32 @@ dependencies = [ "quick-error 1.2.3", ] +[[package]] +name = "rfc6979" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +dependencies = [ + "crypto-bigint", + "hmac", + "zeroize", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + [[package]] name = "ripemd" version = "0.1.3" @@ -3072,6 +3619,15 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" +[[package]] +name = "rusticata-macros" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" +dependencies = [ + "nom 7.1.1", +] + [[package]] name = "rustix" version = "0.35.7" @@ -3100,6 +3656,27 @@ dependencies = [ "windows-sys 0.42.0", ] +[[package]] +name = "rustls" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" +dependencies = [ + "log", + "ring", + "sct", + "webpki", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" +dependencies = [ + "base64 0.21.0", +] + [[package]] name = "rustversion" version = "1.0.9" @@ -3135,6 +3712,125 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +[[package]] +name = "s2n-codec" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c76a52949171a784415293428d2c9315c249ba2091d49b27279601a55375bbb2" +dependencies = [ + "byteorder", + "bytes", + "zerocopy", + "zerocopy-derive", +] + +[[package]] +name = "s2n-quic" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501b93c392899600caafd6f7b19b43a181b6afcb05c2ba0a61e65589469fd863" +dependencies = [ + "bytes", + "cfg-if", + "cuckoofilter", + "futures", + "hash_hasher", + "rand 0.8.5", + "rand_chacha 0.3.1", + "ring", + "s2n-codec", + "s2n-quic-core", + "s2n-quic-platform", + "s2n-quic-rustls", + "s2n-quic-transport", + "tokio", + "zerocopy", + "zerocopy-derive", + "zeroize", +] + +[[package]] +name = "s2n-quic-core" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7ea949a1e82375bc7d05ac76372fd95992e8db42485c85228b3ce421d1a9af" +dependencies = [ + "byteorder", + "bytes", + "hex-literal", + "num-rational", + "num-traits", + "once_cell", + "s2n-codec", + "subtle", + "zerocopy", + "zerocopy-derive", +] + +[[package]] +name = "s2n-quic-crypto" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb2a457eebfdd37f792fdfc9283893d90767cbb6fff623cbc7ec12531d29e1a7" +dependencies = [ + "cfg-if", + "lazy_static", + "ring", + "s2n-codec", + "s2n-quic-core", + "zeroize", +] + +[[package]] +name = "s2n-quic-platform" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8926e4b76c64a06ddb7e413d18d045c619f0daef8b93bcb04dd8f322ed293755" +dependencies = [ + "cfg-if", + "errno", + "futures", + "lazy_static", + "libc", + "pin-project", + "s2n-quic-core", + "socket2", + "tokio", + "zeroize", +] + +[[package]] +name = "s2n-quic-rustls" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ec8decad668229de67f0b90e98ffbba8f844dc294084af3d7e86bfee4f6f040" +dependencies = [ + "bytes", + "rustls", + "rustls-pemfile", + "s2n-codec", + "s2n-quic-core", + "s2n-quic-crypto", +] + +[[package]] +name = "s2n-quic-transport" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b0506c95a703cf12dc21352275f699f9508485c89b257cf99c2b3c2f1cc25c9" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "hashbrown 0.12.3", + "intrusive-collections", + "once_cell", + "s2n-codec", + "s2n-quic-core", + "siphasher", + "smallvec", +] + [[package]] name = "safemem" version = "0.3.3" @@ -3185,6 +3881,30 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "sec1" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + [[package]] name = "security-framework" version = "2.6.1" @@ -3208,6 +3928,42 @@ dependencies = [ "libc", ] +[[package]] +name = "sendme" +version = "0.1.0" +dependencies = [ + "anyhow", + "bao", + "blake3", + "bytes", + "clap 4.1.4", + "console", + "der", + "ed25519-dalek", + "futures", + "genawaiter", + "hex", + "indicatif", + "is-terminal", + "postcard", + "rand 0.7.3", + "rcgen", + "ring", + "rustls", + "s2n-quic", + "serde", + "ssh-key", + "tempfile", + "thiserror", + "tokio", + "tokio-util", + "tracing", + "tracing-subscriber", + "webpki", + "x509-parser", + "zeroize", +] + [[package]] name = "serde" version = "1.0.152" @@ -3217,6 +3973,15 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde_bytes" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "718dc5fff5b36f99093fc49b280cfc96ce6fc824317783bff5a1fed0c7a64819" +dependencies = [ + "serde", +] + [[package]] name = "serde_derive" version = "1.0.152" @@ -3325,6 +4090,15 @@ dependencies = [ "keccak", ] +[[package]] +name = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + [[package]] name = "signal-hook-registry" version = "1.4.0" @@ -3344,6 +4118,12 @@ dependencies = [ "rand_core 0.6.3", ] +[[package]] +name = "siphasher" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" + [[package]] name = "slab" version = "0.4.7" @@ -3391,6 +4171,35 @@ dependencies = [ "der", ] +[[package]] +name = "ssh-encoding" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19cfdc32e0199062113edf41f344fbf784b8205a94600233c84eb838f45191e1" +dependencies = [ + "base64ct", + "pem-rfc7468", + "sha2 0.10.6", +] + +[[package]] +name = "ssh-key" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "288d8f5562af5a3be4bda308dd374b2c807b940ac370b5efa1c99311da91d9a1" +dependencies = [ + "ed25519-dalek", + "p256", + "p384", + "rand_core 0.6.3", + "rsa", + "sec1", + "sha2 0.10.6", + "signature", + "ssh-encoding", + "zeroize", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -3457,6 +4266,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn-mid" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baa8e7560a164edb1621a55d18a0c59abf49d360f47aa7b821061dd7eea7fac9" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "sync_wrapper" version = "0.1.1" @@ -3535,6 +4355,15 @@ dependencies = [ "syn", ] +[[package]] +name = "thread_local" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +dependencies = [ + "once_cell", +] + [[package]] name = "time" version = "0.1.44" @@ -3546,6 +4375,33 @@ dependencies = [ "winapi", ] +[[package]] +name = "time" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" +dependencies = [ + "itoa", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + +[[package]] +name = "time-macros" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" +dependencies = [ + "time-core", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -3807,6 +4663,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60db860322da191b40952ad9affe65ea23e7dd6a5c442c2c42865810c6ab8e6b" +dependencies = [ + "ansi_term", + "matchers", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", ] [[package]] @@ -3931,7 +4817,7 @@ checksum = "e5c1bfe689e4067733530495b04959b00f05cd95f038bed59af4fc70b3e26240" dependencies = [ "darling 0.13.4", "ident_case", - "proc-macro-error", + "proc-macro-error 1.0.4", "proc-macro2", "quote", "syn", @@ -3986,6 +4872,12 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "url" version = "2.3.1" @@ -4028,6 +4920,12 @@ dependencies = [ "serde", ] +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "vcpkg" version = "0.2.15" @@ -4167,6 +5065,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "weezl" version = "0.1.7" @@ -4339,6 +5247,24 @@ dependencies = [ "zeroize", ] +[[package]] +name = "x509-parser" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0ecbeb7b67ce215e40e3cc7f2ff902f94a223acf44995934763467e7b1febc8" +dependencies = [ + "asn1-rs", + "base64 0.13.1", + "data-encoding", + "der-parser", + "lazy_static", + "nom 7.1.1", + "oid-registry", + "rusticata-macros", + "thiserror", + "time 0.3.17", +] + [[package]] name = "xattr" version = "0.2.3" @@ -4348,6 +5274,15 @@ dependencies = [ "libc", ] +[[package]] +name = "yasna" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aed2e7a52e3744ab4d0c05c20aa065258e84c49fd4226f5191b2ed29712710b4" +dependencies = [ + "time 0.3.17", +] + [[package]] name = "yerpc" version = "0.4.0" @@ -4383,6 +5318,27 @@ dependencies = [ "syn", ] +[[package]] +name = "zerocopy" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae0f717764196a220d8c58500e3a3595e2c9054f95d66267f9fd5f6e74ad0fec" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0af017aca1fa6181f5dd7a802456fe6f7666ecdcc18d0910431f0fc89d474e51" +dependencies = [ + "proc-macro2", + "syn", + "synstructure", +] + [[package]] name = "zeroize" version = "1.5.7" diff --git a/Cargo.toml b/Cargo.toml index 6a8fd9872..06909ee96 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,12 +30,11 @@ ratelimit = { path = "./deltachat-ratelimit" } ansi_term = { version = "0.12.1", optional = true } anyhow = "1" +async-channel = "1.8.0" async-imap = { git = "https://github.com/async-email/async-imap", branch = "master", default-features = false, features = ["runtime-tokio"] } async-native-tls = { version = "0.4", default-features = false, features = ["runtime-tokio"] } async-smtp = { version = "0.6", default-features = false, features = ["smtp-transport", "socks5", "runtime-tokio"] } -trust-dns-resolver = "0.22" -tokio = { version = "1", features = ["fs", "rt-multi-thread", "macros"] } -tokio-tar = { version = "0.3" } # TODO: integrate tokio into async-tar +async_zip = { version = "0.0.9", default-features = false, features = ["deflate"] } backtrace = "0.3" base64 = "0.21" bitflags = "1.3" @@ -44,8 +43,11 @@ dirs = { version = "4", optional=true } email = { git = "https://github.com/deltachat/rust-email", branch = "master" } encoded-words = { git = "https://github.com/async-email/encoded-words", branch = "master" } escaper = "0.1" +fast-socks5 = "0.8" futures = "0.3" +futures-lite = "1.12.0" hex = "0.4.0" +humansize = "2" image = { version = "0.24.5", default-features=false, features = ["gif", "jpeg", "ico", "png", "pnm", "webp", "bmp"] } kamadak-exif = "0.5" lettre_email = { git = "https://github.com/deltachat/lettre", branch = "master" } @@ -53,44 +55,43 @@ libc = "0.2" log = {version = "0.4.16", optional = true } mailparse = "0.14" native-tls = "0.2" -num_cpus = "1.15" num-derive = "0.3" num-traits = "0.2" +num_cpus = "1.15" once_cell = "1.17.0" percent-encoding = "2.2" pgp = { version = "0.9", default-features = false } pretty_env_logger = { version = "0.4", optional = true } +qrcodegen = "1.7.0" quick-xml = "0.27" r2d2 = "0.8" r2d2_sqlite = "0.20" rand = "0.8" regex = "1.7" +reqwest = { version = "0.11.14", features = ["json"] } rusqlite = { version = "0.27", features = ["sqlcipher"] } rust-hsluv = "0.1" rustyline = { version = "10", optional = true } sanitize-filename = "0.4" -serde_json = "1.0" +sendme = { git = "https://github.com/n0-computer/sendme", branch = "main" } serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" sha-1 = "0.10" sha2 = "0.10" smallvec = "1" strum = "0.24" strum_macros = "0.24" -thiserror = "1" -toml = "0.7" -url = "2" -uuid = { version = "1", features = ["serde", "v4"] } -fast-socks5 = "0.8" -humansize = "2" -qrcodegen = "1.7.0" tagger = "4.3.4" textwrap = "0.16.0" -async-channel = "1.8.0" -futures-lite = "1.12.0" -tokio-stream = { version = "0.1.11", features = ["fs"] } +thiserror = "1" +tokio = { version = "1", features = ["fs", "rt-multi-thread", "macros"] } tokio-io-timeout = "1.2.0" -reqwest = { version = "0.11.14", features = ["json"] } -async_zip = { version = "0.0.9", default-features = false, features = ["deflate"] } +tokio-stream = { version = "0.1.11", features = ["fs"] } +tokio-tar = { version = "0.3" } # TODO: integrate tokio into async-tar +toml = "0.7" +trust-dns-resolver = "0.22" +url = "2" +uuid = { version = "1", features = ["serde", "v4"] } [dev-dependencies] ansi_term = "0.12.0" @@ -161,3 +162,6 @@ vendored = [ "rusqlite/bundled-sqlcipher-vendored-openssl", "reqwest/native-tls-vendored" ] + +[patch.'https://github.com/n0-computer/sendme'] +sendme = { path = "/home/flub/n0/sendme" } \ No newline at end of file diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index 507fbe76c..d3b1219f1 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -2320,7 +2320,7 @@ void dc_stop_ongoing_process (dc_context_t* context); * ask whether to verify the contact; * if so, start the protocol with dc_join_securejoin(). * - * - DC_QR_ASK_VERIFYGROUP withdc_lot_t::text1=Group name: + * - DC_QR_ASK_VERIFYGROUP with dc_lot_t::text1=Group name: * ask whether to join the group; * if so, start the protocol with dc_join_securejoin(). * @@ -2340,6 +2340,10 @@ void dc_stop_ongoing_process (dc_context_t* context); * ask the user if they want to create an account on the given domain, * if so, call dc_set_config_from_qr() and then dc_configure(). * + * - DC_QR_BACKUP: + * ask the user if they want to set up a new device. + * If so, pass the qr-code to dc_receive_backup(). + * * - DC_QR_WEBRTC_INSTANCE with dc_lot_t::text1=domain: * ask the user if they want to use the given service for video chats; * if so, call dc_set_config_from_qr(). @@ -2630,6 +2634,9 @@ char* dc_get_last_error (dc_context_t* context); void dc_str_unref (char* str); +// TODO: add New stuff + + /** * @class dc_accounts_t * diff --git a/deltachat-ffi/src/lot.rs b/deltachat-ffi/src/lot.rs index 1e6a7831a..270cd34ea 100644 --- a/deltachat-ffi/src/lot.rs +++ b/deltachat-ffi/src/lot.rs @@ -52,6 +52,7 @@ impl Lot { Qr::FprMismatch { .. } => None, Qr::FprWithoutAddr { fingerprint, .. } => Some(fingerprint), Qr::Account { domain } => Some(domain), + Qr::Backup { .. } => None, Qr::WebrtcInstance { domain, .. } => Some(domain), Qr::Addr { draft, .. } => draft.as_deref(), Qr::Url { url } => Some(url), @@ -103,6 +104,7 @@ impl Lot { Qr::FprMismatch { .. } => LotState::QrFprMismatch, Qr::FprWithoutAddr { .. } => LotState::QrFprWithoutAddr, Qr::Account { .. } => LotState::QrAccount, + Qr::Backup { .. } => LotState::QrBackup, Qr::WebrtcInstance { .. } => LotState::QrWebrtcInstance, Qr::Addr { .. } => LotState::QrAddr, Qr::Url { .. } => LotState::QrUrl, @@ -127,6 +129,7 @@ impl Lot { Qr::FprMismatch { contact_id } => contact_id.unwrap_or_default().to_u32(), Qr::FprWithoutAddr { .. } => Default::default(), Qr::Account { .. } => Default::default(), + Qr::Backup { .. } => Default::default(), Qr::WebrtcInstance { .. } => Default::default(), Qr::Addr { contact_id, .. } => contact_id.to_u32(), Qr::Url { .. } => Default::default(), @@ -175,6 +178,8 @@ pub enum LotState { /// text1=domain QrAccount = 250, + QrBackup = 251, + /// text1=domain, text2=instance pattern QrWebrtcInstance = 260, diff --git a/deltachat-jsonrpc/src/api/types/qr.rs b/deltachat-jsonrpc/src/api/types/qr.rs index 0a38d43ce..143792477 100644 --- a/deltachat-jsonrpc/src/api/types/qr.rs +++ b/deltachat-jsonrpc/src/api/types/qr.rs @@ -32,6 +32,9 @@ pub enum QrObject { Account { domain: String, }, + Backup { + ticket: Vec, + }, WebrtcInstance { domain: String, instance_pattern: String, @@ -126,6 +129,9 @@ impl From for QrObject { } Qr::FprWithoutAddr { fingerprint } => QrObject::FprWithoutAddr { fingerprint }, Qr::Account { domain } => QrObject::Account { domain }, + Qr::Backup { ticket } => QrObject::Backup { + ticket: ticket.to_bytes(), + }, Qr::WebrtcInstance { domain, instance_pattern, diff --git a/src/blob.rs b/src/blob.rs index ecca8129c..ef2869bed 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -160,9 +160,9 @@ impl<'a> BlobObject<'a> { pub fn from_path(context: &'a Context, path: &Path) -> Result> { let rel_path = path .strip_prefix(context.get_blobdir()) - .context("wrong blobdir")?; + .with_context(|| format!("wrong blobdir: {}", path.display()))?; if !BlobObject::is_acceptible_blob_name(rel_path) { - return Err(format_err!("wrong name")); + return Err(format_err!("bad blob name: {}", rel_path.display())); } let name = rel_path.to_str().context("wrong name")?; BlobObject::from_name(context, name.to_string()) diff --git a/src/context.rs b/src/context.rs index 54aedceb2..2b3bb17dd 100644 --- a/src/context.rs +++ b/src/context.rs @@ -513,6 +513,13 @@ impl Context { // Ongoing process allocation/free/check + /// Tries to acquire the global UI "ongoing" mutex. + /// + /// This is for modal operations during which no other user actions are allowed. Only + /// one such operation is allowed at any given time. + /// + /// The return value is a cancel token, which will release the ongoing mutex when + /// dropped. pub(crate) async fn alloc_ongoing(&self) -> Result> { let mut s = self.running_state.write().await; ensure!( diff --git a/src/imex.rs b/src/imex.rs index bcedd8b99..f19b02c4c 100644 --- a/src/imex.rs +++ b/src/imex.rs @@ -4,14 +4,18 @@ use std::any::Any; use std::ffi::OsStr; +use std::iter::FusedIterator; use std::path::{Path, PathBuf}; use ::pgp::types::KeyTrait; use anyhow::{bail, ensure, format_err, Context as _, Result}; +use async_channel::Receiver; use futures::StreamExt; use futures_lite::FutureExt; use rand::{thread_rng, Rng}; use tokio::fs::{self, File}; +use tokio::task::JoinError; +use tokio_stream::wrappers::ReadDirStream; use tokio_tar::Archive; use crate::blob::BlobObject; @@ -19,6 +23,7 @@ use crate::chat::{self, delete_and_reset_all_device_msgs, ChatId}; use crate::config::Config; use crate::contact::ContactId; use crate::context::Context; +use crate::e2ee; use crate::events::EventType; use crate::key::{self, DcKey, DcSecretKey, SignedPublicKey, SignedSecretKey}; use crate::log::LogExt; @@ -26,13 +31,13 @@ use crate::message::{Message, MsgId, Viewtype}; use crate::mimeparser::SystemMessage; use crate::param::Param; use crate::pgp; +use crate::qr::Qr; use crate::sql; use crate::stock_str; use crate::tools::{ create_folder, delete_file, get_filesuffix_lc, open_file_std, read_file, time, write_file, EmailAddress, }; -use crate::{e2ee, tools}; // Name of the database file in the backup. const DBFILE_BACKUP_NAME: &str = "dc_database_backup.sqlite"; @@ -511,23 +516,9 @@ async fn export_backup(context: &Context, dir: &Path, passphrase: String) -> Res let _d1 = DeleteOnDrop(temp_db_path.clone()); let _d2 = DeleteOnDrop(temp_path.clone()); - context - .sql - .set_raw_config_int("backup_time", now as i32) - .await?; - sql::housekeeping(context).await.ok_or_log(context); - - context - .sql - .execute("VACUUM;", paramsv![]) + export_database(context, &temp_db_path, passphrase) .await - .map_err(|e| warn!(context, "Vacuum failed, exporting anyway {}", e)) - .ok(); - - ensure!( - context.scheduler.read().await.is_none(), - "cannot export backup, IO is running" - ); + .context("could not export database")?; info!( context, @@ -536,12 +527,6 @@ async fn export_backup(context: &Context, dir: &Path, passphrase: String) -> Res dest_path.display(), ); - context - .sql - .export(&temp_db_path, passphrase) - .await - .with_context(|| format!("failed to backup plaintext database to {temp_db_path:?}"))?; - let res = export_backup_inner(context, &temp_db_path, &temp_path).await; match &res { @@ -579,32 +564,11 @@ async fn export_backup_inner( .append_path_with_name(temp_db_path, DBFILE_BACKUP_NAME) .await?; - let read_dir = tools::read_dir(context.get_blobdir()).await?; - let count = read_dir.len(); - let mut written_files = 0; - - let mut last_progress = 0; - for entry in read_dir.into_iter() { - let name = entry.file_name(); - if !entry.file_type().await?.is_file() { - warn!( - context, - "Export: Found dir entry {} that is not a file, ignoring", - name.to_string_lossy() - ); - continue; - } - let mut file = File::open(entry.path()).await?; - let path_in_archive = PathBuf::from(BLOBS_BACKUP_NAME).join(name); + let blobdir = BlobDirContents::new(context).await?; + for blob in blobdir.iter() { + let mut file = File::open(blob.to_abs_path()).await?; + let path_in_archive = PathBuf::from(BLOBS_BACKUP_NAME).join(blob.as_name()); builder.append_file(path_in_archive, &mut file).await?; - - written_files += 1; - let progress = 1000 * written_files / count; - if progress != last_progress && progress > 10 && progress < 1000 { - // We already emitted ImexProgress(10) above - context.emit_event(EventType::ImexProgress(progress)); - last_progress = progress; - } } builder.finish().await?; @@ -763,6 +727,242 @@ where Ok(()) } +/// Exports the database to *file*, encrypted using *passphrase*. +/// +/// The directory of *file* must already exist, if *file* itself exists it will be +/// overwritten. +/// +/// This also verifies that IO is not running during the export. +async fn export_database(context: &Context, dest: &Path, passphrase: String) -> Result<()> { + ensure!( + context.scheduler.read().await.is_none(), + "cannot export backup, IO is running" + ); + let now = time().try_into().context("32-bit UNIX time overflow")?; + + context.sql.set_raw_config_int("backup_time", now).await?; + sql::housekeeping(context).await.ok_or_log(context); + context + .sql + .execute("VACUUM;", paramsv![]) + .await + .map_err(|e| warn!(context, "Vacuum failed, exporting anyway {}", e)) + .ok(); + context + .sql + .export(dest, passphrase) + .await + .with_context(|| format!("failed to backup database to {}", dest.display()))?; + Ok(()) +} + +#[derive(Debug)] +pub struct BackupSender { + /// A handle to the running provider. + provider: sendme::provider::Provider, + /// The ticket to retrieve the backup collection. + ticket: sendme::provider::Ticket, + /// Token holding the "ongoing" mutex. When this completes the provider should shut + /// down. + cancel_token: Receiver<()>, +} + +impl BackupSender { + // - [x] check i/o is not running + // - [x] check we have secret key + // - [x] alloc ongoing + // - [ ] correctly cancel Provider when cancelled + // - [x] create auth token + // - [x] export backup with generated token as password + // - needs a path to store the database + // - [x] create the sendme database + // - [x] start provider + // - [ ] wait for one successful connection + // - [ ] shutdown when a connection is closed, successful or not. + // + // - [ ] provide progress report + /// Prepares for sending a backup to a second device. + /// + /// Before calling this function all I/O must be stopped so that no changes to the blobs + /// or database are happening, this is done by calling the `dc_accounts_stop_io` or + /// `dc_stop_io` APIs first. TODO: Add the rust equivalents. + /// + /// This will acquire the global "ongoing" mutex. + pub async fn perpare(context: &Context, dir: &Path) -> Result { + ensure!( + // TODO: Should we worry about path normalisation? + dir != context.get_blobdir(), + "Temporary database export directory should not be in blobdir" + ); + e2ee::ensure_secret_key_exists(context) + .await + .context("Private key not available, aborting backup export")?; + + // Acquire global "ongoing" mutex. + let cancel_token = context.alloc_ongoing().await?; + let res = tokio::select! { + biased; + res = Self::prepare_inner(context, dir) => { + match res { + Ok(slf) => { + // TODO: maybe this is the wrong place to log this + // TODO: Also needs to log progress somehow. + info!(context, "Waiting for remote to connect"); + Ok(slf) + }, + Err(err) => { + error!(context, "Failed to set up second device setup: {:#}", err); + Err(err) + }, + } + }, + _ = cancel_token.recv() => Err(format_err!("cancelled")), + }; + + // TODO: This is all wrong, too early to release + context.free_ongoing().await; + res + } + + async fn prepare_inner(context: &Context, dir: &Path) -> Result { + // Generate the token up front: we also use it to encrypt the database. + let token = sendme::protocol::AuthToken::generate(); + let dbfile = dir.join(DBFILE_BACKUP_NAME); + export_database(context, &dbfile, token.to_string()) + .await + .context("Database export failed")?; + + // Now we can be sure IO is not running. + let mut files = vec![sendme::provider::DataSource::from(dbfile)]; + let blobdir = BlobDirContents::new(context).await?; + for blob in blobdir.iter() { + files.push(blob.to_abs_path().into()); + } + + // Start listening. + let (db, hash) = sendme::provider::create_collection(files).await?; + let provider = sendme::provider::Provider::builder(db) + .auth_token(token) + .spawn()?; + let ticket = provider.ticket(hash); + Ok(Self { provider, ticket }) + } + + pub fn qr(&self) -> Qr { + Qr::Backup { + ticket: self.ticket.clone(), + } + } + + pub async fn join(self) -> Result<(), JoinError> { + // TODO: should wait for 1 transfer to complete or abort + self.provider.join().await + } + + pub fn abort(&self) { + self.provider.abort() + } +} + +/// All files in the blobdir. +/// +/// This exists so we can have a [`BlobDirIter`] which needs something to own the data of +/// it's `&Path`. Use [`BlobDirContents::iter`] to create the iterator. +/// +/// Additionally pre-allocating this means we get a length for progress report. +struct BlobDirContents<'a> { + inner: Vec, + context: &'a Context, +} + +impl<'a> BlobDirContents<'a> { + async fn new(context: &'a Context) -> Result> { + let readdir = fs::read_dir(context.get_blobdir()).await?; + let inner = ReadDirStream::new(readdir) + .filter_map(|entry| async move { + match entry { + Ok(entry) => Some(entry), + Err(err) => { + error!(context, "Failed to read blob file: {err}"); + None + } + } + }) + .filter_map(|entry| async move { + match entry.file_type().await.ok()?.is_file() { + true => Some(entry.path()), + false => { + warn!( + context, + "Export: Found blob dir entry {} that is not a file, ignoring", + entry.path().display() + ); + None + } + } + }) + .collect() + .await; + Ok(Self { inner, context }) + } + + fn iter(&self) -> BlobDirIter<'_> { + BlobDirIter::new(self.context, &self.inner) + } +} + +/// A stream for [`Blob`]s. +/// +/// The stream emits [`EventType::ImexProgress`] events as it being consumed. +/// +/// Because we like to know the total number of blobs to emit progress all the blobs are +/// read up front and stored. Luckily this also makes our life easier, since we now only +/// need to implement `Iterator` and not `Stream`. +struct BlobDirIter<'a> { + paths: &'a [PathBuf], + offset: usize, + last_progress: usize, + context: &'a Context, +} + +impl<'a> BlobDirIter<'a> { + fn new(context: &'a Context, paths: &'a [PathBuf]) -> BlobDirIter<'a> { + Self { + paths, + offset: 0, + last_progress: 0, + context, + } + } +} + +impl<'a> Iterator for BlobDirIter<'a> { + type Item = BlobObject<'a>; + + fn next(&mut self) -> Option { + while let Some(path) = self.paths.get(self.offset) { + self.offset += 1; + + // In theory this can error but we'd have corrupted filenames in the blobdir, so + // silently skipping them is fine. + match BlobObject::from_path(self.context, path) { + Ok(blob) => { + let progress = 1000 * self.offset / self.paths.len(); + if progress != self.last_progress && progress > 10 && progress < 1000 { + self.context.emit_event(EventType::ImexProgress(progress)); + self.last_progress = progress; + } + return Some(blob); + } + Err(err) => warn!(self.context, "{err}"), + } + } + None + } +} + +impl FusedIterator for BlobDirIter<'_> {} + #[cfg(test)] mod tests { use ::pgp::armor::BlockType; diff --git a/src/qr.rs b/src/qr.rs index 4fa8138cf..a29062f59 100644 --- a/src/qr.rs +++ b/src/qr.rs @@ -64,6 +64,9 @@ pub enum Qr { Account { domain: String, }, + Backup { + ticket: sendme::provider::Ticket, + }, WebrtcInstance { domain: String, instance_pattern: String,