From 5855965e24969b96aaac8870f556a81572edcee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Th=C3=A9riault?= Date: Wed, 15 Jan 2020 23:47:38 -0500 Subject: [PATCH] Switch to BLAKE3, slightly better security, simplify with globals --- Cargo.lock | 103 +++++++++---------------------- Cargo.toml | 6 +- build.rs | 15 +++++ src/globals.rs | 29 +++++++++ src/main.rs | 49 +++------------ src/queries.rs | 79 ++++++++++-------------- src/routes.rs | 164 +++++++++++++++++-------------------------------- src/setup.rs | 11 ++-- 8 files changed, 176 insertions(+), 280 deletions(-) create mode 100644 build.rs create mode 100644 src/globals.rs diff --git a/Cargo.lock b/Cargo.lock index f23d223..f1bb28b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -330,6 +330,11 @@ dependencies = [ "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "arrayvec" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "async-trait" version = "0.1.22" @@ -392,7 +397,7 @@ name = "backtrace-sys" version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -414,17 +419,6 @@ name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "blake2" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "blake2b_simd" version = "0.5.8" @@ -432,7 +426,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "blake3" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -440,7 +446,7 @@ name = "brotli-sys" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -458,11 +464,6 @@ name = "bumpalo" version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "byteorder" version = "1.3.2" @@ -491,7 +492,7 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.46" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -519,7 +520,7 @@ dependencies = [ [[package]] name = "constant_time_eq" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -544,15 +545,6 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "crypto-mac" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "derive_more" version = "0.99.2" @@ -593,14 +585,6 @@ dependencies = [ "migrations_macros 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "dirs" version = "2.0.2" @@ -697,7 +681,7 @@ dependencies = [ "actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "actix-web 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "blake2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "blake3 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "diesel 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "diesel_migrations 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -839,14 +823,6 @@ dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "generic-array" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "getrandom" version = "0.1.13" @@ -1002,7 +978,7 @@ name = "libsqlite3-sys" version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1176,11 +1152,6 @@ dependencies = [ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "parking_lot" version = "0.9.0" @@ -1438,7 +1409,7 @@ name = "ring" version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1590,11 +1561,6 @@ name = "spin" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "subtle" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "syn" version = "1.0.7" @@ -1737,11 +1703,6 @@ dependencies = [ "unchecked-index 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "typenum" -version = "1.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "unchecked-index" version = "0.2.2" @@ -2023,6 +1984,7 @@ dependencies = [ "checksum arc-swap 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f1a1eca3195b729bbd64e292ef2f5fff6b1c28504fed762ce2b1013dde4d8e92" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" +"checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" "checksum async-trait 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "c8df72488e87761e772f14ae0c2480396810e51b2c2ade912f97f0f7e5b95e3c" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" @@ -2032,30 +1994,27 @@ dependencies = [ "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -"checksum blake2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "94cb07b0da6a73955f8fb85d24c466778e70cda767a568229b104f0264089330" "checksum blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "5850aeee1552f495dd0250014cf64b82b7c8879a89d83b33bbdace2cc4f63182" +"checksum blake3 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ba0511b7f4f7d9cb1ef7b8dfda5293af6c1071578d65c8a05aa7d11c1985f08c" "checksum brotli-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd" "checksum brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e" "checksum bumpalo 3.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5fb8038c1ddc0a5f73787b130f4cc75151e96ed33e417fde765eb5a81e3532f4" -"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "10004c15deb332055f7a4a208190aed362cf9a7c2f6ab70a305fba50e1105f38" "checksum bytestring 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fc267467f58ef6cc8874064c62a0423eb0d099362c8a23edd1c6d044f46eead4" "checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" -"checksum cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)" = "0213d356d3c4ea2c18c40b037c3be23cd639825c18f25ee670ac7813beeef99c" +"checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" +"checksum constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" "checksum copyless 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ff9c56c9fb2a49c05ef0e431485a22400af20d33226dc0764d891d09e724127" "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" "checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" -"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" "checksum derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2159be042979966de68315bce7034bb000c775f22e3e834e1c52ff78f041cae8" "checksum diesel 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9d7cc03b910de9935007861dce440881f69102aaaedfd4bc5a6f40340ca5840c" "checksum diesel_derives 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3" "checksum diesel_migrations 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3cde8413353dc7f5d72fa8ce0b99a560a359d2c5ef1e5817ca731cd9008f4c" -"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" "checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" "checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" "checksum dotenv 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" @@ -2081,7 +2040,6 @@ dependencies = [ "checksum futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0bae52d6b29cf440e298856fec3965ee6fa71b06aa7495178615953fd669e5f9" "checksum futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d66274fb76985d3c62c886d1da7ac4c0903a8c9f754e8fe0f35a6a6cc39e76" "checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" "checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" "checksum h2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9433d71e471c1736fd5a61b671fc0b148d7a2992f666c958d03cd8feb3b88d1" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" @@ -2121,7 +2079,6 @@ dependencies = [ "checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" "checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72" -"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" "checksum parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc" "checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" "checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" @@ -2174,7 +2131,6 @@ dependencies = [ "checksum socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85" "checksum sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3" "checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" -"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" "checksum syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7bedb3320d0f3035594b0b723c8a28d7d336a3eda3881db79e61d676fb644c" "checksum synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f085a5855930c0441ca1288cf044ea4aecf4f43a91668abdb870b4ba546a203" "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" @@ -2187,7 +2143,6 @@ dependencies = [ "checksum trust-dns-proto 0.18.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2a7f3a2ab8a919f5eca52a468866a67ed7d3efa265d48a652a9a3452272b413f" "checksum trust-dns-resolver 0.18.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6f90b1502b226f8b2514c6d5b37bafa8c200d7ca4102d57dc36ee0f3b7a04a2f" "checksum twoway 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6b40075910de3a912adbd80b5d8bad6ad10a23eeb1f5bf9d4006839e899ba5bc" -"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" "checksum unchecked-index 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eeba86d422ce181a719445e51872fa30f1f7413b62becb52e95ec91aa262d85c" "checksum unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" diff --git a/Cargo.toml b/Cargo.toml index 1ee3c6f..8334c48 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ keywords = [ "pastebin" ] license = "MIT" +build = "build.rs" [dependencies] actix-files = "0.2.1" @@ -21,7 +22,7 @@ actix-rt = "1.0.0" actix-multipart = "0.2.0" actix-web = "2.0.0" base64 = "0.11.0" -blake2 = "0.8.1" +blake3 = "0.1.1" chrono = "0.4.10" diesel_migrations = "1.4.0" dirs = "2.0.2" @@ -43,6 +44,9 @@ features = ["bundled"] version = "1.0.104" features = ["derive"] +[build-dependencies] +rand = "0.7.3" + [features] default = [] dev = ["dotenv"] diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..c080d71 --- /dev/null +++ b/build.rs @@ -0,0 +1,15 @@ +use rand::Rng; +use std::{env, fs::File, io::Write, path::Path}; + +fn main() { + let mut key = [0; 32]; + let mut rng = rand::thread_rng(); + for b in key.iter_mut() { + *b = rng.gen(); + } + + let out_dir = env::var("OUT_DIR").unwrap(); + let dest_path = Path::new(&out_dir).join("key"); + let mut f = File::create(&dest_path).unwrap(); + f.write_all(&key).unwrap(); +} diff --git a/src/globals.rs b/src/globals.rs new file mode 100644 index 0000000..2325c9c --- /dev/null +++ b/src/globals.rs @@ -0,0 +1,29 @@ +pub const KEY: &[u8; 32] = include_bytes!(concat!(env!("OUT_DIR"), "/key")); + +lazy_static! { + pub static ref EMPTY_HASH: Vec = crate::setup::hash(b""); + pub static ref POOL: crate::Pool = + crate::setup::create_pool(&CONFIG.database_url, CONFIG.pool_size); +} + +#[cfg(feature = "dev")] +lazy_static! { + pub static ref CONFIG: crate::setup::Config = crate::setup::Config::debug(); + pub static ref PASSWORD_HASH: Vec = { + dotenv::dotenv().ok(); + let password = crate::get_env!("PASSWD"); + crate::setup::hash(password.as_bytes()) + }; +} + +#[cfg(not(feature = "dev"))] +lazy_static! { + pub static ref CONFIG: crate::setup::Config = crate::setup::init(); + pub static ref PASSWORD_HASH: Vec = { + let password_path = crate::setup::get_password_path(); + std::fs::read(&password_path).unwrap_or_else(|e| { + eprintln!("Can't read password hash from disk: {}", e); + std::process::exit(1); + }) + }; +} diff --git a/src/main.rs b/src/main.rs index 35212c8..2a13af0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,13 +16,7 @@ use diesel::{ }; use std::process; -#[cfg(feature = "dev")] -use crate::setup::Config; -#[cfg(feature = "dev")] -use dotenv; -#[cfg(not(feature = "dev"))] -use std::fs; - +pub mod globals; pub mod models; pub mod queries; pub mod routes; @@ -35,58 +29,29 @@ pub type Pool = r2d2::Pool>; #[cfg(not(feature = "dev"))] embed_migrations!(); +use globals::{CONFIG, KEY}; + #[actix_rt::main] async fn main() { - let config = { - #[cfg(feature = "dev")] - { - Config::debug() - } - #[cfg(not(feature = "dev"))] - { - setup::init() - } - }; setup::init_logger(); - let pool = setup::create_pool(&config.database_url, config.pool_size); #[cfg(not(feature = "dev"))] { - embedded_migrations::run(&pool.get().unwrap()).unwrap_or_else(|e| { + embedded_migrations::run(&globals::POOL.get().unwrap()).unwrap_or_else(|e| { eprintln!("Can't prepare database: {}", e); process::exit(1); }); } - let password_hash = { - #[cfg(feature = "dev")] - { - dotenv::dotenv().ok(); - let password = get_env!("PASSWD"); - setup::hash(&password) - } - #[cfg(not(feature = "dev"))] - { - let password_path = setup::get_password_path(); - fs::read(&password_path).unwrap_or_else(|e| { - eprintln!("Can't read password hash from disk: {}.", e); - process::exit(1); - }) - } - }; - - let port = config.port; + let port = CONFIG.port; println!("Listening on port {}", port); HttpServer::new(move || { App::new() - .data(pool.clone()) - .data(config.clone()) - .data(password_hash.clone()) .wrap(IdentityService::new( - CookieIdentityPolicy::new(&[0; 32]) + CookieIdentityPolicy::new(KEY) .name("filite-auth-cookie") - .secure(false), + .secure(true), )) .wrap(setup::logger_middleware()) .route("/", web::get().to(routes::index)) diff --git a/src/queries.rs b/src/queries.rs index e56c9e5..9a17422 100644 --- a/src/queries.rs +++ b/src/queries.rs @@ -42,11 +42,9 @@ macro_rules! common_select { if let Some(to) = $f.range.1 { $q = $q.filter(created.lt(to)); } - if let Some(limit) = $f.limit { $q = $q.limit(limit); } - $q = if $f.asc { $q.order(created.asc()) } else { @@ -58,8 +56,8 @@ macro_rules! common_select { /// SELECT a single entry given its id macro_rules! find { ($n:ident, $t:ty) => { - pub fn find(f_id: i32, pool: Data) -> QueryResult<$t> { - let conn: &SqliteConnection = &pool.get().unwrap(); + pub fn find(f_id: i32) -> diesel::result::QueryResult<$t> { + let conn: &SqliteConnection = &crate::globals::POOL.get().unwrap(); $n.find(f_id).first::<$t>(conn) } }; @@ -68,10 +66,9 @@ macro_rules! find { /// DELETE an entry macro_rules! delete { ($n:ident) => { - pub fn delete(d_id: i32, pool: Data) -> QueryResult<()> { - let conn: &SqliteConnection = &pool.get().unwrap(); + pub fn delete(d_id: i32) -> diesel::result::QueryResult<()> { + let conn: &SqliteConnection = &crate::globals::POOL.get().unwrap(); diesel::delete($n.find(d_id)).execute(conn)?; - Ok(()) } }; @@ -80,27 +77,27 @@ macro_rules! delete { /// Queries affecting the `files` table pub mod files { use crate::{ + globals::POOL, models::files::*, queries::SelectFilters, schema::files::{dsl::*, table}, - Pool, }; - use actix_web::web::Data; use diesel::{prelude::*, result::QueryResult}; + find!(files, File); + delete!(files); + /// SELECT multiple file entries - pub fn select(filters: SelectFilters, pool: Data) -> QueryResult> { - let conn: &SqliteConnection = &pool.get().unwrap(); + pub fn select(filters: SelectFilters) -> QueryResult> { + let conn: &SqliteConnection = &POOL.get().unwrap(); let mut query = files.into_boxed(); common_select!(query, filters); query.load::(conn) } - find!(files, File); - /// REPLACE a file entry - pub fn replace(r_id: i32, r_filepath: &str, pool: Data) -> QueryResult { - let conn: &SqliteConnection = &pool.get().unwrap(); + pub fn replace(r_id: i32, r_filepath: &str) -> QueryResult { + let conn: &SqliteConnection = &POOL.get().unwrap(); let new_file = NewFile { id: r_id, filepath: r_filepath, @@ -108,37 +105,34 @@ pub mod files { diesel::replace_into(table) .values(&new_file) .execute(conn)?; - - find(r_id, pool) + find(r_id) } - - delete!(files); } /// Queries affecting the `links` table pub mod links { use crate::{ + globals::POOL, models::links::*, queries::SelectFilters, schema::links::{dsl::*, table}, - Pool, }; - use actix_web::web::Data; use diesel::{prelude::*, result::QueryResult}; + find!(links, Link); + delete!(links); + /// SELECT multiple link entries - pub fn select(filters: SelectFilters, pool: Data) -> QueryResult> { - let conn: &SqliteConnection = &pool.get().unwrap(); + pub fn select(filters: SelectFilters) -> QueryResult> { + let conn: &SqliteConnection = &POOL.get().unwrap(); let mut query = links.into_boxed(); common_select!(query, filters); query.load::(conn) } - find!(links, Link); - /// REPLACE a link entry - pub fn replace(r_id: i32, r_forward: &str, pool: Data) -> QueryResult { - let conn: &SqliteConnection = &pool.get().unwrap(); + pub fn replace(r_id: i32, r_forward: &str) -> QueryResult { + let conn: &SqliteConnection = &POOL.get().unwrap(); let new_link = NewLink { id: r_id, forward: r_forward, @@ -146,42 +140,34 @@ pub mod links { diesel::replace_into(table) .values(&new_link) .execute(conn)?; - - find(r_id, pool) + find(r_id) } - - delete!(links); } /// Queries affecting the `texts` table pub mod texts { use crate::{ + globals::POOL, models::texts::*, queries::SelectFilters, schema::texts::{dsl::*, table}, - Pool, }; - use actix_web::web::Data; use diesel::{prelude::*, result::QueryResult}; + find!(texts, Text); + delete!(texts); + /// SELECT multiple text entries - pub fn select(filters: SelectFilters, pool: Data) -> QueryResult> { - let conn: &SqliteConnection = &pool.get().unwrap(); + pub fn select(filters: SelectFilters) -> QueryResult> { + let conn: &SqliteConnection = &POOL.get().unwrap(); let mut query = texts.into_boxed(); common_select!(query, filters); query.load::(conn) } - find!(texts, Text); - /// REPLACE a text entry - pub fn replace( - r_id: i32, - r_contents: &str, - r_highlight: bool, - pool: Data, - ) -> QueryResult { - let conn: &SqliteConnection = &pool.get().unwrap(); + pub fn replace(r_id: i32, r_contents: &str, r_highlight: bool) -> QueryResult { + let conn: &SqliteConnection = &POOL.get().unwrap(); let new_text = NewText { id: r_id, contents: r_contents, @@ -190,9 +176,6 @@ pub mod texts { diesel::replace_into(table) .values(&new_text) .execute(conn)?; - - find(r_id, pool) + find(r_id) } - - delete!(texts); } diff --git a/src/routes.rs b/src/routes.rs index 6c3349e..e5274a7 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -1,9 +1,11 @@ //! Actix route handlers -use crate::setup::{self, Config}; +use crate::{ + globals::{CONFIG, EMPTY_HASH, PASSWORD_HASH}, + setup, +}; use actix_identity::Identity; use actix_web::{error::BlockingError, web, Error, HttpRequest, HttpResponse, Responder}; -use base64; use chrono::{DateTime, NaiveDateTime, Utc}; use diesel; use serde::Serialize; @@ -22,21 +24,13 @@ fn parse_id(id: &str) -> Result { } } -lazy_static! { - static ref EMPTY_HASH: Vec = setup::hash(""); -} - /// Authenticates a user -async fn auth( - identity: Identity, - request: HttpRequest, - password_hash: &[u8], -) -> Result<(), HttpResponse> { +async fn auth(identity: Identity, request: HttpRequest) -> Result<(), HttpResponse> { if identity.identity().is_some() { return Ok(()); } - if password_hash == (&*EMPTY_HASH).as_slice() { + if *PASSWORD_HASH == *EMPTY_HASH { identity.remember("guest".into()); return Ok(()); } @@ -67,8 +61,8 @@ async fn auth( Err(_) => return Err(HttpResponse::BadRequest().body("Invalid Authorization header")), }; - let infallible_hash = move || -> Result, Infallible> { Ok(setup::hash(password)) }; - if web::block(infallible_hash).await.unwrap().as_slice() == password_hash { + let infallible_hash = move || -> Result, Infallible> { Ok(setup::hash(&password)) }; + if web::block(infallible_hash).await.unwrap() == *PASSWORD_HASH { match String::from_utf8(user.to_vec()) { Ok(u) => { identity.remember(u); @@ -133,14 +127,12 @@ macro_rules! select { pub async fn select( request: HttpRequest, query: actix_web::web::Query, - pool: actix_web::web::Data, identity: actix_identity::Identity, - password_hash: actix_web::web::Data>, ) -> Result { - crate::routes::auth(identity, request, &password_hash).await?; + crate::routes::auth(identity, request).await?; let filters = crate::queries::SelectFilters::from(query.into_inner()); - match actix_web::web::block(move || crate::queries::$m::select(filters, pool)).await { + match actix_web::web::block(move || crate::queries::$m::select(filters)).await { Ok(x) => Ok(actix_web::HttpResponse::Ok().json(x)), Err(_) => Err(actix_web::HttpResponse::InternalServerError() .body("Internal server error") @@ -156,14 +148,12 @@ macro_rules! delete { pub async fn delete( request: HttpRequest, path: actix_web::web::Path, - pool: actix_web::web::Data, identity: actix_identity::Identity, - password_hash: actix_web::web::Data>, ) -> Result { - crate::routes::auth(identity, request, &password_hash).await?; + crate::routes::auth(identity, request).await?; let id = crate::routes::parse_id(&path)?; - match actix_web::web::block(move || crate::queries::$m::delete(id, pool)).await { + match actix_web::web::block(move || crate::queries::$m::delete(id)).await { Ok(()) => Ok(actix_web::HttpResponse::NoContent().body("Deleted")), Err(e) => crate::routes::match_find_error(e), } @@ -176,13 +166,12 @@ macro_rules! random_id { ($m:ident) => { use rand::distributions::Distribution; - pub async fn random_id(pool: &actix_web::web::Data) -> Result { + pub async fn random_id() -> Result { let mut rng = rand::thread_rng(); let distribution = rand::distributions::Uniform::from(0..i32::max_value()); loop { let id = distribution.sample(&mut rng); - let pool = pool.clone(); - match actix_web::web::block(move || crate::queries::$m::find(id, pool)).await { + match actix_web::web::block(move || crate::queries::$m::find(id)).await { Ok(_) => continue, Err(e) => match e { actix_web::error::BlockingError::Error(e) => match e { @@ -223,12 +212,8 @@ static HIGHLIGHT_CONTENTS: &str = include_str!("../resources/highlight.html"); const HIGHLIGHT_LANGUAGE: &str = r#""#; /// Index page letting users upload via a UI -pub async fn index( - request: HttpRequest, - identity: Identity, - password_hash: web::Data>, -) -> impl Responder { - if let Err(response) = auth(identity, request, &password_hash).await { +pub async fn index(request: HttpRequest, identity: Identity) -> impl Responder { + if let Err(response) = auth(identity, request).await { return response; } @@ -242,21 +227,15 @@ pub async fn index( INDEX_CONTENTS.to_owned() } }; - HttpResponse::Ok() .header("Content-Type", "text/html") .body(contents) } /// GET the config info -pub async fn get_config( - request: HttpRequest, - config: web::Data, - identity: Identity, - password_hash: web::Data>, -) -> impl Responder { - match auth(identity, request, &password_hash).await { - Ok(_) => HttpResponse::Ok().json(config.get_ref()), +pub async fn get_config(request: HttpRequest, identity: Identity) -> impl Responder { + match auth(identity, request).await { + Ok(_) => HttpResponse::Ok().json(&*CONFIG), Err(response) => response, } } @@ -276,10 +255,9 @@ pub async fn logout(identity: Identity) -> impl Responder { pub mod files { use crate::routes::match_replace_result; use crate::{ + globals::CONFIG, queries::{self, SelectQuery}, routes::{auth, match_find_error, parse_id}, - setup::Config, - Pool, }; use actix_files::NamedFile; use actix_identity::Identity; @@ -298,15 +276,11 @@ pub mod files { random_id!(files); /// GET a file entry and statically serve it - pub async fn get( - path: web::Path, - pool: web::Data, - config: web::Data, - ) -> Result { + pub async fn get(path: web::Path) -> Result { let id = parse_id(&path)?; - match web::block(move || queries::files::find(id, pool)).await { + match web::block(move || queries::files::find(id)).await { Ok(file) => { - let mut path = config.files_dir.clone(); + let mut path = CONFIG.files_dir.clone(); path.push(file.filepath); match NamedFile::open(&path) { Ok(nf) => Ok(nf), @@ -318,13 +292,8 @@ pub mod files { } /// Common code for PUT and POST routes - async fn put_post( - id: i32, - mut body: Multipart, - pool: web::Data, - config: web::Data, - ) -> Result { - let mut path = config.files_dir.clone(); + async fn put_post(id: i32, mut body: Multipart) -> Result { + let mut path = CONFIG.files_dir.clone(); let mut relative_path = PathBuf::new(); let dir_path = path.clone(); if web::block(move || fs::create_dir_all(dir_path)) @@ -356,7 +325,11 @@ pub mod files { Some(n) => n, None => return Err(HttpResponse::BadRequest().body("Missing filename").into()), }; - let filename = format!("{:x}.{}", Utc::now().timestamp(), filename); + let filename = format!( + "{}.{}", + radix_fmt::radix_36(Utc::now().timestamp()), + filename + ); path.push(&filename); relative_path.push(&filename); let relative_path = match path.to_str() { @@ -402,7 +375,7 @@ pub mod files { } match_replace_result( - web::block(move || queries::files::replace(id, &relative_path, pool)).await, + web::block(move || queries::files::replace(id, &relative_path)).await, id, ) } @@ -412,28 +385,22 @@ pub mod files { request: HttpRequest, path: web::Path, body: Multipart, - pool: web::Data, - config: web::Data, identity: Identity, - password_hash: web::Data>, ) -> Result { - auth(identity, request, &password_hash).await?; + auth(identity, request).await?; let id = parse_id(&path)?; - put_post(id, body, pool, config).await + put_post(id, body).await } /// POST a new file entry using a multipart body pub async fn post( request: HttpRequest, body: Multipart, - pool: web::Data, - config: web::Data, identity: Identity, - password_hash: web::Data>, ) -> Result { - auth(identity, request, &password_hash).await?; - let id = random_id(&pool).await?; - put_post(id, body, pool, config).await + auth(identity, request).await?; + let id = random_id().await?; + put_post(id, body).await } } @@ -443,7 +410,6 @@ pub mod links { routes::{ auth, match_find_error, match_replace_result, parse_id, timestamp_to_last_modified, }, - Pool, }; use actix_identity::Identity; use actix_web::{web, Error, HttpRequest, HttpResponse}; @@ -453,12 +419,9 @@ pub mod links { random_id!(links); /// GET a link entry and redirect to it - pub async fn get( - path: web::Path, - pool: web::Data, - ) -> Result { + pub async fn get(path: web::Path) -> Result { let id = parse_id(&path)?; - match web::block(move || queries::links::find(id, pool)).await { + match web::block(move || queries::links::find(id)).await { Ok(link) => Ok(HttpResponse::Found() .header("Location", link.forward) .header("Last-Modified", timestamp_to_last_modified(link.created)) @@ -478,14 +441,12 @@ pub mod links { request: HttpRequest, path: web::Path, body: web::Json, - pool: web::Data, identity: Identity, - password_hash: web::Data>, ) -> Result { - auth(identity, request, &password_hash).await?; + auth(identity, request).await?; let id = parse_id(&path)?; match_replace_result( - web::block(move || queries::links::replace(id, &body.forward, pool)).await, + web::block(move || queries::links::replace(id, &body.forward)).await, id, ) } @@ -494,14 +455,12 @@ pub mod links { pub async fn post( request: HttpRequest, body: web::Json, - pool: web::Data, identity: Identity, - password_hash: web::Data>, ) -> Result { - auth(identity, request, &password_hash).await?; - let id = random_id(&pool).await?; + auth(identity, request).await?; + let id = random_id().await?; match_replace_result( - web::block(move || queries::links::replace(id, &body.forward, pool)).await, + web::block(move || queries::links::replace(id, &body.forward)).await, id, ) } @@ -509,16 +468,15 @@ pub mod links { pub mod texts { use crate::routes::escape_html; + use crate::{ + globals::CONFIG, + routes::{HIGHLIGHT_CONTENTS, HIGHLIGHT_LANGUAGE}, + }; use crate::{ queries::{self, SelectQuery}, routes::{ auth, match_find_error, match_replace_result, parse_id, timestamp_to_last_modified, }, - Pool, - }; - use crate::{ - routes::{HIGHLIGHT_CONTENTS, HIGHLIGHT_LANGUAGE}, - setup::Config, }; use actix_identity::Identity; use actix_web::{web, Error, HttpRequest, HttpResponse}; @@ -528,17 +486,13 @@ pub mod texts { random_id!(texts); /// GET a text entry and display it - pub async fn get( - config: web::Data, - path: web::Path, - pool: web::Data, - ) -> Result { + pub async fn get(path: web::Path) -> Result { let id = parse_id(&path)?; - match web::block(move || queries::texts::find(id, pool)).await { + match web::block(move || queries::texts::find(id)).await { Ok(text) => { let last_modified = timestamp_to_last_modified(text.created); if text.highlight { - let languages: Vec = config + let languages: Vec = CONFIG .highlight .languages .iter() @@ -547,7 +501,7 @@ pub mod texts { let languages = languages.join("\n"); let contents = HIGHLIGHT_CONTENTS .replace("{{ title }}", &path) - .replace("{{ theme }}", &config.highlight.theme) + .replace("{{ theme }}", &CONFIG.highlight.theme) .replace("{{ contents }}", &escape_html(&text.contents)) .replace("{{ languages }}", &languages); @@ -577,15 +531,12 @@ pub mod texts { request: HttpRequest, path: web::Path, body: web::Json, - pool: web::Data, identity: Identity, - password_hash: web::Data>, ) -> Result { - auth(identity, request, &password_hash).await?; + auth(identity, request).await?; let id = parse_id(&path)?; match_replace_result( - web::block(move || queries::texts::replace(id, &body.contents, body.highlight, pool)) - .await, + web::block(move || queries::texts::replace(id, &body.contents, body.highlight)).await, id, ) } @@ -594,15 +545,12 @@ pub mod texts { pub async fn post( request: HttpRequest, body: web::Json, - pool: web::Data, identity: Identity, - password_hash: web::Data>, ) -> Result { - auth(identity, request, &password_hash).await?; - let id = random_id(&pool).await?; + auth(identity, request).await?; + let id = random_id().await?; match_replace_result( - web::block(move || queries::texts::replace(id, &body.contents, body.highlight, pool)) - .await, + web::block(move || queries::texts::replace(id, &body.contents, body.highlight)).await, id, ) } diff --git a/src/setup.rs b/src/setup.rs index 138d628..af483df 100644 --- a/src/setup.rs +++ b/src/setup.rs @@ -1,8 +1,7 @@ //! Utilities used during the initial setup -use crate::Pool; +use crate::{globals::KEY, Pool}; use actix_web::middleware::Logger; -use blake2::{Blake2b, Digest}; use diesel::{ r2d2::{self, ConnectionManager}, sqlite::SqliteConnection, @@ -51,10 +50,8 @@ pub fn get_password_path() -> PathBuf { } /// Returns the BLAKE2b digest of the input string -pub fn hash>(input: T) -> Vec { - let mut hasher = Blake2b::new(); - hasher.input(input); - hasher.result().to_vec() +pub fn hash(input: &[u8]) -> Vec { + blake3::keyed_hash(KEY, input).as_bytes().to_vec() } /// Returns an environment variable and panic if it isn't found @@ -294,7 +291,7 @@ pub fn init() -> Config { } } - let password_hash = hash(&password); + let password_hash = hash(password.as_bytes()); fs::write(&password_path, password_hash.as_slice()).unwrap_or_else(|e| { eprintln!("Can't write password: {}", e); process::exit(1);