Finished /upload endpoint
This commit is contained in:
parent
0b2a4f130e
commit
7570739ba4
40
Cargo.lock
generated
40
Cargo.lock
generated
@ -114,6 +114,7 @@ dependencies = [
|
||||
"matchit",
|
||||
"memchr",
|
||||
"mime",
|
||||
"multer",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"rustversion",
|
||||
@ -269,6 +270,15 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
version = "0.8.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
@ -572,6 +582,23 @@ dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "multer"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83e87776546dc87511aa5ee218730c92b666d7264ab6ed41f9d215af9cd5224b"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"encoding_rs",
|
||||
"futures-util",
|
||||
"http",
|
||||
"httparse",
|
||||
"memchr",
|
||||
"mime",
|
||||
"spin",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.4"
|
||||
@ -830,6 +857,12 @@ dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.9.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
@ -1032,6 +1065,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_yaml",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tower-http",
|
||||
]
|
||||
|
||||
@ -1041,6 +1075,12 @@ version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.9.0+wasi-snapshot-preview1"
|
||||
|
@ -6,11 +6,12 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
axum = "0.7.6"
|
||||
axum = { version = "0.7.6", features = ["multipart"] }
|
||||
clap = { version = "4.5.18", features = ["derive"] }
|
||||
expanduser = "1.2.2"
|
||||
if-addrs = "0.13.3"
|
||||
serde = { version = "1.0.216", features = ["derive"] }
|
||||
serde_yaml = "0.9.34"
|
||||
tokio = { version = "1.40.0", features = ["full"] }
|
||||
tokio-util = "0.7.13"
|
||||
tower-http = { version = "0.6.2", features = ["fs", "trace"] }
|
||||
|
@ -1,5 +1,5 @@
|
||||
use std::{io, fs};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::PathBuf;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use expanduser::expanduser;
|
||||
@ -12,8 +12,8 @@ pub fn load_config() -> Config {
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Config {
|
||||
download_path: PathBuf,
|
||||
upload_path: PathBuf,
|
||||
download_path: String,
|
||||
upload_path: String,
|
||||
pub web_port: u16,
|
||||
pub shell_port: u16,
|
||||
shells: HashMap<String, String>
|
||||
@ -32,11 +32,11 @@ impl Config {
|
||||
}
|
||||
|
||||
pub fn get_download_path(&self) -> PathBuf {
|
||||
self.download_path.clone()
|
||||
expanduser(self.download_path.clone()).unwrap()
|
||||
}
|
||||
|
||||
pub fn get_upload_path(&self) -> PathBuf {
|
||||
self.upload_path.clone()
|
||||
expanduser(self.upload_path.clone()).unwrap()
|
||||
}
|
||||
|
||||
pub fn get_shell<S: Into<String>>(&self, key: S) -> Option<String> {
|
||||
|
@ -6,7 +6,7 @@ use tokio::net::TcpListener;
|
||||
use tower_http::services::ServeDir;
|
||||
use axum::{
|
||||
middleware,
|
||||
routing::get,
|
||||
routing::{get, post},
|
||||
Router
|
||||
};
|
||||
|
||||
@ -15,6 +15,7 @@ mod print_dir;
|
||||
mod config;
|
||||
mod shells;
|
||||
mod logging;
|
||||
mod upload;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
@ -30,7 +31,7 @@ async fn main() {
|
||||
print_dir::print_interface(&args.interface, &port, &args.directory);
|
||||
|
||||
let app = Router::new()
|
||||
//.route("/upload", post(upload_handler))
|
||||
.route("/upload", post(upload::upload_handler))
|
||||
.route("/shells/:shell", get(shells::shells_handler))
|
||||
.nest_service("/download", ServeDir::new(conf.get_download_path()))
|
||||
.nest_service("/", ServeDir::new(cwd))
|
||||
|
@ -0,0 +1,53 @@
|
||||
use std::{
|
||||
fs::File,
|
||||
io::{BufWriter, Write},
|
||||
path::{Path, Component}
|
||||
};
|
||||
use axum::{
|
||||
http::StatusCode,
|
||||
extract::Multipart,
|
||||
response::IntoResponse
|
||||
};
|
||||
|
||||
use crate::config;
|
||||
|
||||
fn path_is_valid(path: &str) -> bool {
|
||||
let path = Path::new(path);
|
||||
let mut components = path.components().peekable();
|
||||
if let Some(first) = components.peek() {
|
||||
if !matches!(first, Component::Normal(_)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
components.count() == 1
|
||||
}
|
||||
|
||||
pub async fn upload_handler(mut multipart: Multipart) -> impl IntoResponse {
|
||||
|
||||
let conf = config::load_config();
|
||||
|
||||
while let Some(field) = multipart.next_field().await.unwrap() {
|
||||
let file_name = match field.name() {
|
||||
Some(file) => file.to_string(),
|
||||
None => continue
|
||||
};
|
||||
let data = field.bytes().await.unwrap();
|
||||
let path = conf.get_upload_path().join(&file_name);
|
||||
|
||||
if !path_is_valid(&file_name) {
|
||||
return (StatusCode::FORBIDDEN, format!("Directory Traversal: {}", path.display()));
|
||||
}
|
||||
|
||||
let Ok(file) = File::create(&path) else {
|
||||
return (StatusCode::FORBIDDEN, format!("Failed to create file: {}", path.display()));
|
||||
};
|
||||
|
||||
let mut writer = BufWriter::new(file);
|
||||
if let Err(e) = writer.write_all(&data) {
|
||||
return (StatusCode::INTERNAL_SERVER_ERROR, format!("An error occurred when writing to {}: {}", path.display(), e))
|
||||
}
|
||||
}
|
||||
|
||||
(StatusCode::CREATED, "Successfully uploaded file(s).".to_string())
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user