Skip to content

Commit

Permalink
Use regex for bearer token validation (#1998)
Browse files Browse the repository at this point in the history
  • Loading branch information
divergentdave authored Sep 26, 2023
1 parent b394036 commit 994f61e
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 30 deletions.
1 change: 1 addition & 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 core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ kube = { workspace = true, optional = true, features = ["rustls-tls"] }
k8s-openapi = { workspace = true, optional = true }
prio.workspace = true
rand = "0.8"
regex = "1.9.5"
reqwest = { version = "0.11.20", default-features = false, features = ["rustls-tls", "json"] }
ring = "0.16.20"
serde.workspace = true
Expand Down
40 changes: 10 additions & 30 deletions core/src/auth_tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine};
use derivative::Derivative;
use http::{header::AUTHORIZATION, HeaderValue};
use rand::{distributions::Standard, prelude::Distribution};
use regex::Regex;
use ring::{
constant_time,
digest::{digest, SHA256, SHA256_OUTPUT_LEN},
};
use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
use std::str;
use std::{str, sync::OnceLock};

/// HTTP header where auth tokens are provided in messages between participants.
pub const DAP_AUTH_HEADER: &str = "DAP-Auth-Token";
Expand Down Expand Up @@ -204,36 +205,15 @@ impl BearerToken {
/// Validate that a bearer token value matches the format in
/// https://datatracker.ietf.org/doc/html/rfc6750#section-2.1.
fn validate(value: &str) -> Result<(), anyhow::Error> {
let mut iter = value.chars();
let mut any_non_equals = false;
// First loop: consume "normal" characters, stop when we see an equals sign for padding or
// reach the end of the input.
for c in &mut iter {
match c {
'a'..='z' | 'A'..='Z' | '0'..='9' | '-' | '.' | '_' | '~' | '+' | '/' => {
any_non_equals = true;
}
'=' => {
if !any_non_equals {
return Err(anyhow::anyhow!("bearer token may not start with '='"));
}
break;
}
_ => return Err(anyhow::anyhow!("bearer token may not contain '{c}'")),
}
}
// Second loop: consume any further padding characters, if present.
for c in &mut iter {
match c {
'=' => {}
_ => {
return Err(anyhow::anyhow!(
"bearer token may only contain '=' at the end"
))
}
}
static REGEX: OnceLock<Regex> = OnceLock::new();

let regex = REGEX.get_or_init(|| Regex::new("^[-A-Za-z0-9._~+/]+=*$").unwrap());

if regex.is_match(value) {
Ok(())
} else {
Err(anyhow::anyhow!("bearer token has invalid format"))
}
Ok(())
}
}

Expand Down

0 comments on commit 994f61e

Please sign in to comment.