implement mutli domain support for auth headers

This commit is contained in:
BlockListed 2023-09-09 09:23:48 +02:00
parent 80d3c61cc2
commit 40edfa5990
No known key found for this signature in database
GPG Key ID: 2D204777C477B588

View File

@ -360,20 +360,38 @@ use crate::db::{
DbConn,
};
pub struct Host {
pub host: String,
pub struct Domain {
pub domain: String,
}
#[rocket::async_trait]
impl<'r> FromRequest<'r> for Host {
impl<'r> FromRequest<'r> for Domain {
type Error = &'static str;
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
let headers = request.headers();
// Get host
let host = if CONFIG.domain_set() {
CONFIG.domain()
// TODO: UPDATE THIS SECTION
let domain = if CONFIG.domain_set() {
let host = if let Some(host) = headers.get_one("X-Forwarded-Host") {
host
} else if let Some(host) = headers.get_one("Host") {
host
} else {
// TODO fix error handling
// This is probably a 400 bad request,
// because http requests require the host header
todo!()
};
let Some(domain) = CONFIG.host_to_domain(host) else {
// TODO fix error handling
// This is probably a 421 misdirected request.
todo!()
};
domain
} else if let Some(referer) = headers.get_one("Referer") {
referer.to_string()
} else {
@ -399,14 +417,14 @@ impl<'r> FromRequest<'r> for Host {
format!("{protocol}://{host}")
};
Outcome::Success(Host {
host,
Outcome::Success(Domain {
domain,
})
}
}
pub struct ClientHeaders {
pub host: String,
pub domain: String,
pub device_type: i32,
pub ip: ClientIp,
}
@ -416,7 +434,7 @@ impl<'r> FromRequest<'r> for ClientHeaders {
type Error = &'static str;
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
let host = try_outcome!(Host::from_request(request).await).host;
let domain = try_outcome!(Domain::from_request(request).await).domain;
let ip = match ClientIp::from_request(request).await {
Outcome::Success(ip) => ip,
_ => err_handler!("Error getting Client IP"),
@ -426,7 +444,7 @@ impl<'r> FromRequest<'r> for ClientHeaders {
request.headers().get_one("device-type").map(|d| d.parse().unwrap_or(14)).unwrap_or_else(|| 14);
Outcome::Success(ClientHeaders {
host,
domain,
device_type,
ip,
})
@ -434,7 +452,7 @@ impl<'r> FromRequest<'r> for ClientHeaders {
}
pub struct Headers {
pub host: String,
pub domain: String,
pub device: Device,
pub user: User,
pub ip: ClientIp,
@ -447,7 +465,7 @@ impl<'r> FromRequest<'r> for Headers {
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
let headers = request.headers();
let host = try_outcome!(Host::from_request(request).await).host;
let domain = try_outcome!(Domain::from_request(request).await).domain;
let ip = match ClientIp::from_request(request).await {
Outcome::Success(ip) => ip,
_ => err_handler!("Error getting Client IP"),
@ -518,7 +536,7 @@ impl<'r> FromRequest<'r> for Headers {
}
Outcome::Success(Headers {
host,
domain,
device,
user,
ip,
@ -527,7 +545,7 @@ impl<'r> FromRequest<'r> for Headers {
}
pub struct OrgHeaders {
pub host: String,
pub domain: String,
pub device: Device,
pub user: User,
pub org_user_type: UserOrgType,
@ -583,7 +601,7 @@ impl<'r> FromRequest<'r> for OrgHeaders {
};
Outcome::Success(Self {
host: headers.host,
domain: headers.domain,
device: headers.device,
user,
org_user_type: {
@ -605,7 +623,7 @@ impl<'r> FromRequest<'r> for OrgHeaders {
}
pub struct AdminHeaders {
pub host: String,
pub domain: String,
pub device: Device,
pub user: User,
pub org_user_type: UserOrgType,
@ -622,7 +640,7 @@ impl<'r> FromRequest<'r> for AdminHeaders {
let client_version = request.headers().get_one("Bitwarden-Client-Version").map(String::from);
if headers.org_user_type >= UserOrgType::Admin {
Outcome::Success(Self {
host: headers.host,
domain: headers.domain,
device: headers.device,
user: headers.user,
org_user_type: headers.org_user_type,
@ -638,7 +656,7 @@ impl<'r> FromRequest<'r> for AdminHeaders {
impl From<AdminHeaders> for Headers {
fn from(h: AdminHeaders) -> Headers {
Headers {
host: h.host,
domain: h.domain,
device: h.device,
user: h.user,
ip: h.ip,
@ -669,7 +687,7 @@ fn get_col_id(request: &Request<'_>) -> Option<String> {
/// and have access to the specific collection provided via the <col_id>/collections/collectionId.
/// This does strict checking on the collection_id, ManagerHeadersLoose does not.
pub struct ManagerHeaders {
pub host: String,
pub domain: String,
pub device: Device,
pub user: User,
pub org_user_type: UserOrgType,
@ -698,7 +716,7 @@ impl<'r> FromRequest<'r> for ManagerHeaders {
}
Outcome::Success(Self {
host: headers.host,
domain: headers.domain,
device: headers.device,
user: headers.user,
org_user_type: headers.org_user_type,
@ -713,7 +731,7 @@ impl<'r> FromRequest<'r> for ManagerHeaders {
impl From<ManagerHeaders> for Headers {
fn from(h: ManagerHeaders) -> Headers {
Headers {
host: h.host,
domain: h.domain,
device: h.device,
user: h.user,
ip: h.ip,
@ -724,7 +742,7 @@ impl From<ManagerHeaders> for Headers {
/// The ManagerHeadersLoose is used when you at least need to be a Manager,
/// but there is no collection_id sent with the request (either in the path or as form data).
pub struct ManagerHeadersLoose {
pub host: String,
pub domain: String,
pub device: Device,
pub user: User,
pub org_user: UserOrganization,
@ -740,7 +758,7 @@ impl<'r> FromRequest<'r> for ManagerHeadersLoose {
let headers = try_outcome!(OrgHeaders::from_request(request).await);
if headers.org_user_type >= UserOrgType::Manager {
Outcome::Success(Self {
host: headers.host,
domain: headers.domain,
device: headers.device,
user: headers.user,
org_user: headers.org_user,
@ -756,7 +774,7 @@ impl<'r> FromRequest<'r> for ManagerHeadersLoose {
impl From<ManagerHeadersLoose> for Headers {
fn from(h: ManagerHeadersLoose) -> Headers {
Headers {
host: h.host,
domain: h.domain,
device: h.device,
user: h.user,
ip: h.ip,
@ -784,7 +802,7 @@ impl ManagerHeaders {
}
Ok(ManagerHeaders {
host: h.host,
domain: h.domain,
device: h.device,
user: h.user,
org_user_type: h.org_user_type,