mdf bouncer safe

This commit is contained in:
Rakarake 2026-03-28 16:12:32 +01:00
parent 32a2c63a4e
commit bac4e5d8c6

View file

@ -1,6 +1,8 @@
use std::{env::{args, var}, io, sync::Arc}; use std::{env::{args, var}, io, sync::Arc};
use axum::{Router, body::{Body, Bytes}, extract::{DefaultBodyLimit, Path, State}, routing::{delete, post, put}}; use axum::{Router, body::{Body, Bytes}, extract::{DefaultBodyLimit, Path, State}, http::StatusCode, routing::{delete, post, put}};
use log::info;
use tokio::fs;
use std::path::PathBuf; use std::path::PathBuf;
const MAXIMUM_PACKET_SIZE: usize = (2 << 20) * 10; const MAXIMUM_PACKET_SIZE: usize = (2 << 20) * 10;
@ -12,6 +14,7 @@ struct AppState {
#[tokio::main] #[tokio::main]
async fn main() -> io::Result<()> { async fn main() -> io::Result<()> {
pretty_env_logger::init();
// get secret from secret file // get secret from secret file
let mut args = args().skip(1); let mut args = args().skip(1);
let target_path = args.next().expect("need to specify target path"); let target_path = args.next().expect("need to specify target path");
@ -39,13 +42,41 @@ async fn main() -> io::Result<()> {
Ok(()) Ok(())
} }
async fn delete_file(State(state): State<Arc<AppState>>, Path(path): Path<String>) { async fn delete_file(State(state): State<Arc<AppState>>, Path(path): Path<String>) -> Result<StatusCode, StatusCode> {
println!("about to delete: {path}"); let full_path = safe_join(&state.root, &path)?;
info!("about to delete: {:?}", full_path);
fs::remove_file(full_path)
.await
.map_err(|_| StatusCode::NOT_FOUND)?;
Ok(StatusCode::NO_CONTENT)
} }
async fn put_file(State(state): State<Arc<AppState>>, Path(path): Path<String>, body: Bytes) { async fn put_file(State(state): State<Arc<AppState>>, Path(path): Path<String>, body: Bytes) -> Result<StatusCode, StatusCode> {
println!("about to put: {path}"); let full_path = safe_join(&state.root, &path)?;
let bytes = Vec::from(body); info!("about to put: {:?}", full_path);
println!("body: {:?}", bytes);
if let Some(parent) = full_path.parent() {
fs::create_dir_all(parent).await.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
}
fs::write(full_path, body)
.await
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
Ok(StatusCode::CREATED)
} }
/// Make supplied path does not contain anything other than relative
/// paths.
fn safe_join(base: &PathBuf, user_path: &str) -> Result<PathBuf, StatusCode> {
let mut full = base.clone();
let path = PathBuf::from(user_path);
for comp in path.components() {
match comp {
std::path::Component::Normal(p) => full.push(p),
_ => return Err(StatusCode::BAD_REQUEST),
}
}
Ok(full)
}