summaryrefslogtreecommitdiff
path: root/src/util.rs
diff options
context:
space:
mode:
authorDaniel García <[email protected]>2021-07-15 19:15:55 +0200
committerDaniel García <[email protected]>2021-07-15 19:15:55 +0200
commite5ec245626e4a4d232b6a709338fe1e9811845e7 (patch)
tree73b4736a701948328c23c27b9880a6905b4e1cea /src/util.rs
parent3968bc8016611cdf9a84db68990f27624ab17889 (diff)
downloadvaultwarden-e5ec245626e4a4d232b6a709338fe1e9811845e7.tar.gz
vaultwarden-e5ec245626e4a4d232b6a709338fe1e9811845e7.zip
Protect namedfile against path traversal, rocket only does it for pathbuf
Diffstat (limited to 'src/util.rs')
-rw-r--r--src/util.rs33
1 files changed, 32 insertions, 1 deletions
diff --git a/src/util.rs b/src/util.rs
index 8512bc7b..9e216d72 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -5,7 +5,8 @@ use std::io::Cursor;
use rocket::{
fairing::{Fairing, Info, Kind},
- http::{ContentType, Header, HeaderMap, Method, Status},
+ http::{ContentType, Header, HeaderMap, Method, RawStr, Status},
+ request::FromParam,
response::{self, Responder},
Data, Request, Response, Rocket,
};
@@ -125,6 +126,36 @@ impl<'r, R: Responder<'r>> Responder<'r> for Cached<R> {
}
}
+pub struct SafeString(String);
+
+impl std::fmt::Display for SafeString {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ self.0.fmt(f)
+ }
+}
+
+impl AsRef<Path> for SafeString {
+ #[inline]
+ fn as_ref(&self) -> &Path {
+ Path::new(&self.0)
+ }
+}
+
+impl<'r> FromParam<'r> for SafeString {
+ type Error = ();
+
+ #[inline(always)]
+ fn from_param(param: &'r RawStr) -> Result<Self, Self::Error> {
+ let s = param.percent_decode().map(|cow| cow.into_owned()).map_err(|_| ())?;
+
+ if s.chars().all(|c| matches!(c, 'a'..='z' | 'A'..='Z' |'0'..='9' | '-')) {
+ Ok(SafeString(s))
+ } else {
+ Err(())
+ }
+ }
+}
+
// Log all the routes from the main paths list, and the attachments endpoint
// Effectively ignores, any static file route, and the alive endpoint
const LOGGED_ROUTES: [&str; 6] =