Skip to content

Commit

Permalink
begin
Browse files Browse the repository at this point in the history
  • Loading branch information
aumetra committed Dec 7, 2023
1 parent 491429c commit 301cf8b
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 0 deletions.
23 changes: 23 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ members = [
"kitsune-cli",
"kitsune-job-runner",
"lib/athena",
"lib/csurf",
"lib/masto-id-convert",
"lib/post-process",
"lib/speedy-uuid",
Expand Down
13 changes: 13 additions & 0 deletions lib/csurf/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "csurf"
authors.workspace = true
edition.workspace = true
version.workspace = true

[dependencies]
http = "0.2.11"
tower = { version = "0.4.13", default-features = false }
zeroize = { version = "1.7.0", features = ["derive"] }

[lints]
workspace = true
5 changes: 5 additions & 0 deletions lib/csurf/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# csurf

Small stateless CSRF crate for tower-based frameworks

Implements the [Signed Double-Submit Cookie](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#signed-double-submit-cookie-recommended) pattern, as recommended by OWASP.
50 changes: 50 additions & 0 deletions lib/csurf/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use http::{Request, Response};
use std::task::{self, Poll};
use tower::{Layer, Service};
use zeroize::{Zeroize, ZeroizeOnDrop};

#[derive(Zeroize, ZeroizeOnDrop)]
pub struct Signer {}

#[derive(Clone, Zeroize, ZeroizeOnDrop)]
pub struct CsrfLayer {
key: Vec<u8>,
}

impl<S> Layer<S> for CsrfLayer {
type Service = CsrfService<S>;

fn layer(&self, inner: S) -> Self::Service {
CsrfService::new(inner, self.key.clone())
}
}

#[derive(Clone, Zeroize, ZeroizeOnDrop)]
pub struct CsrfService<S> {
#[zeroize(skip)]
inner: S,
key: Vec<u8>,
}

impl<S> CsrfService<S> {
pub fn new(inner: S, key: Vec<u8>) -> Self {
Self { inner, key }
}
}

impl<S, ReqBody, ResBody> Service<Request<ReqBody>> for CsrfService<S>
where
S: Service<Request<ReqBody>, Response = Response<ResBody>>,
{
type Error = S::Error;
type Future = S::Future;
type Response = S::Response;

fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> {
self.inner.poll_ready(cx)
}

fn call(&mut self, req: Request<ReqBody>) -> Self::Future {
self.inner.call(req)
}
}

0 comments on commit 301cf8b

Please sign in to comment.