Skip to content

Commit

Permalink
Move blocking operations to spawn_blocking
Browse files Browse the repository at this point in the history
Signed-off-by: Elizabeth Myers <[email protected]>
  • Loading branch information
Elizafox committed Apr 1, 2024
1 parent fe249ad commit 6265810
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 27 deletions.
62 changes: 37 additions & 25 deletions src/csrf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use rand::{
use serde::{Deserialize, Serialize};
use subtle::ConstantTimeEq;
use time::{Duration, OffsetDateTime};
use tokio::task::{spawn_blocking, JoinError};
use tower_sessions::Session;
use tracing::debug;

Expand All @@ -40,6 +41,9 @@ pub enum SessionError {
#[error(transparent)]
Session(#[from] tower_sessions::session::Error),

#[error(transparent)]
Join(#[from] JoinError),

#[error("No CSRF token")]
NoToken,

Expand All @@ -51,36 +55,44 @@ pub enum SessionError {
}

impl SessionData {
fn new() -> Self {
async fn new() -> Self {
let len_distr = Lazy::new(|| Uniform::new(24usize, 48usize));
let mut rng = thread_rng();
let len = (*len_distr).sample(&mut rng);
Self {
token: WebsafeAlphabet.sample_string(&mut rng, len),
time: OffsetDateTime::now_utc(),
}
spawn_blocking(move || {
let mut rng = thread_rng();
let len = (*len_distr).sample(&mut rng);
Self {
token: WebsafeAlphabet.sample_string(&mut rng, len),
time: OffsetDateTime::now_utc(),
}
})
.await
.expect("Unexpectedly failed to create session data")
}

fn cmp(&self, token: &str) -> Result<(), SessionError> {
if token.as_bytes().ct_ne(self.token.as_bytes()).into() {
debug!("CSRF tokens mismatched: {token} != {}", self.token);
return Err(SessionError::Mismatch);
}

// This isn't sensitive info, so it's okay not to compare in constant time
if OffsetDateTime::now_utc() - self.time > MAX_DURATION {
debug!(
"CSRF token expired: {}",
OffsetDateTime::now_utc() - self.time
);
return Err(SessionError::Expired);
}

Ok(())
async fn cmp(self, token: &str) -> Result<(), SessionError> {
let token = token.to_owned();
spawn_blocking(move || {
if token.as_bytes().ct_ne(self.token.as_bytes()).into() {
debug!("CSRF tokens mismatched");
return Err(SessionError::Mismatch);
}

// This isn't sensitive info, so it's okay not to compare in constant time
if OffsetDateTime::now_utc() - self.time > MAX_DURATION {
debug!(
"CSRF token expired: {}",
OffsetDateTime::now_utc() - self.time
);
return Err(SessionError::Expired);
}

Ok(())
})
.await?
}

pub async fn new_into_session(session: &Session) -> Result<String, SessionError> {
let data = Self::new();
let data = Self::new().await;
let token = data.token.clone();

session.insert(SESSION_KEY, data).await?;
Expand All @@ -96,6 +108,6 @@ impl SessionData {
.ok_or(SessionError::NoToken)?;

// Verify the token
data.cmp(token)
data.cmp(token).await
}
}
11 changes: 10 additions & 1 deletion src/generate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use rand::{
distributions::{DistString, Uniform},
prelude::*,
};
use tokio::task::spawn_blocking;

use crate::util::{macros::arr, string::WebsafeAlphabet};

Expand Down Expand Up @@ -166,7 +167,7 @@ impl Generator {
}

// Create a shady-looking filename for the URL
pub(crate) fn shady_filename() -> String {
fn generate_shady_filename() -> String {
arr!(const SEPS: [&str; _] = ["!", "_", "+", "~"]);

let mut rng = thread_rng();
Expand Down Expand Up @@ -230,6 +231,14 @@ impl Generator {

out.into_iter().collect()
}

// async wrapper around generate_shady_filename
pub(crate) async fn shady_filename() -> String {

spawn_blocking(Self::generate_shady_filename)
.await
.expect("shady_filename task unexpectedly failed")
}
}

mod strings {
Expand Down
2 changes: 1 addition & 1 deletion src/web/submission.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ mod post {
));
}

let shady = Generator::shady_filename();
let shady = Generator::shady_filename().await;
Mutation::create_url(&state.db, &url_form.url, &shady, Some(addr.to_string())).await?;

debug!("URL created: {} -> {shady}", url_form.url);
Expand Down

0 comments on commit 6265810

Please sign in to comment.