aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock93
-rw-r--r--Cargo.toml1
-rwxr-xr-xbin/dev-server2
-rw-r--r--src/routes.rs93
4 files changed, 146 insertions, 43 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 398ff68..62ff04b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -95,18 +95,47 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
+name = "bcrypt"
+version = "0.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "523ab528ce3a7ada6597f8ccf5bd8d85ebe26d5edf311cad4d1d3cfb2d357ac6"
+dependencies = [
+ "base64",
+ "blowfish",
+ "getrandom",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
name = "bitflags"
version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
[[package]]
+name = "blowfish"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7"
+dependencies = [
+ "byteorder",
+ "cipher",
+]
+
+[[package]]
name = "bumpalo"
version = "3.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
[[package]]
+name = "byteorder"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
+
+[[package]]
name = "bytes"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -153,6 +182,16 @@ dependencies = [
]
[[package]]
+name = "cipher"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
+dependencies = [
+ "crypto-common",
+ "inout",
+]
+
+[[package]]
name = "colorchoice"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -219,6 +258,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
+name = "crypto-common"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
+[[package]]
name = "env_filter"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -280,6 +329,7 @@ name = "files"
version = "0.1.0"
dependencies = [
"anyhow",
+ "bcrypt",
"chrono",
"const_format",
"env_logger",
@@ -368,6 +418,16 @@ dependencies = [
]
[[package]]
+name = "generic-array"
+version = "0.14.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
+[[package]]
name = "getrandom"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -576,6 +636,15 @@ dependencies = [
]
[[package]]
+name = "inout"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
name = "ipnet"
version = "2.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -995,6 +1064,12 @@ dependencies = [
]
[[package]]
+name = "subtle"
+version = "2.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
+
+[[package]]
name = "syn"
version = "2.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1129,6 +1204,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
[[package]]
+name = "typenum"
+version = "1.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
+
+[[package]]
name = "unicode-ident"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1159,6 +1240,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
+name = "version_check"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
+
+[[package]]
name = "want"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1438,6 +1525,12 @@ dependencies = [
]
[[package]]
+name = "zeroize"
+version = "1.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
+
+[[package]]
name = "zmij"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index bc1b62c..372dd3b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2021"
[dependencies]
anyhow = "1.0"
+bcrypt = "0.19"
chrono = "0.4"
const_format = "0.2"
env_logger = "0.11"
diff --git a/bin/dev-server b/bin/dev-server
index b45b595..5938b9f 100755
--- a/bin/dev-server
+++ b/bin/dev-server
@@ -3,7 +3,7 @@ set -euo pipefail
export HOST="127.0.0.1"
export PORT="8080"
-export KEY="1234"
+export KEY='$2y$12$1k/1ZFalf8ZNV1pGoLRU0e3ppvCgPxevp9ay8vtJUxhECZuoVMgBu'
export DB="db.sqlite3"
export FILES_DIR="files"
diff --git a/src/routes.rs b/src/routes.rs
index ca1cc41..f5deeb4 100644
--- a/src/routes.rs
+++ b/src/routes.rs
@@ -59,52 +59,61 @@ async fn upload_file(
authorized_key: String,
files_dir: &Path,
) -> Result<Response<BoxBody<Bytes, std::io::Error>>> {
- let key = get_header(&request, "X-Key");
- if key != Some(authorized_key) {
- log::info!("Unauthorized file upload");
- Ok(response(StatusCode::UNAUTHORIZED, "Unauthorized"))
- } else {
- let file_id = model::generate_file_id();
- let filename = get_header(&request, "X-Filename").map(|s| util::sanitize_filename(&s));
- let expiration_days: Option<i64> =
- get_header(&request, "X-Expiration").and_then(|s| s.parse().ok());
- let content_length: Option<usize> =
- get_header(&request, "Content-Length").and_then(|s| s.parse().ok());
-
- match (filename, expiration_days, content_length) {
- (Some(filename), Some(expiration_days), Some(content_length)) => {
- let _ = fs::create_dir(files_dir).await;
- let path = files_dir.join(&file_id);
- let mut file = File::create(&path).await.unwrap();
-
- let mut incoming = request.into_body();
- while let Some(frame) = incoming.frame().await {
- if let Ok(data) = frame {
- let _ = file.write_all(&data.into_data().unwrap()).await;
- let _ = file.flush().await;
- }
- }
-
- let file = model::File {
- id: file_id.clone(),
- name: filename,
- expires_at: model::local_time().add(Duration::days(expiration_days)),
- content_length,
- };
-
- match db::files::insert(&db_conn, file.clone()).await {
- Ok(_) => Ok(response(StatusCode::OK, file_id)),
- Err(msg) => {
- log::error!("Insert file: {msg}");
- if let Err(msg) = fs::remove_file(path).await {
- log::error!("Remove file: {msg}");
+ match get_header(&request, "X-Key") {
+ None => {
+ log::info!("Unauthorized file upload");
+ Ok(response(StatusCode::UNAUTHORIZED, "Unauthorized"))
+ }
+ Some(key) => match bcrypt::verify(key, &authorized_key) {
+ Ok(true) => {
+ let file_id = model::generate_file_id();
+ let filename =
+ get_header(&request, "X-Filename").map(|s| util::sanitize_filename(&s));
+ let expiration_days: Option<i64> =
+ get_header(&request, "X-Expiration").and_then(|s| s.parse().ok());
+ let content_length: Option<usize> =
+ get_header(&request, "Content-Length").and_then(|s| s.parse().ok());
+
+ match (filename, expiration_days, content_length) {
+ (Some(filename), Some(expiration_days), Some(content_length)) => {
+ let _ = fs::create_dir(files_dir).await;
+ let path = files_dir.join(&file_id);
+ let mut file = File::create(&path).await.unwrap();
+
+ let mut incoming = request.into_body();
+ while let Some(frame) = incoming.frame().await {
+ if let Ok(data) = frame {
+ let _ = file.write_all(&data.into_data().unwrap()).await;
+ let _ = file.flush().await;
+ }
+ }
+
+ let file = model::File {
+ id: file_id.clone(),
+ name: filename,
+ expires_at: model::local_time().add(Duration::days(expiration_days)),
+ content_length,
};
- Ok(internal_server_error())
+
+ match db::files::insert(&db_conn, file.clone()).await {
+ Ok(_) => Ok(response(StatusCode::OK, file_id)),
+ Err(msg) => {
+ log::error!("Insert file: {msg}");
+ if let Err(msg) = fs::remove_file(path).await {
+ log::error!("Remove file: {msg}");
+ };
+ Ok(internal_server_error())
+ }
+ }
}
+ _ => Ok(bad_request()),
}
}
- _ => Ok(bad_request()),
- }
+ _ => {
+ log::info!("Unauthorized file upload");
+ Ok(response(StatusCode::UNAUTHORIZED, "Unauthorized"))
+ }
+ },
}
}