one-click registration works

main
_ 2021-05-02 22:23:12 +00:00
parent ebd1026903
commit ce82f7d6a3
4 changed files with 72 additions and 68 deletions

View File

@ -123,12 +123,9 @@ async fn handle_http_request (
let req_method = req.method.clone ();
{
let config = state.config.read ().await;
if ! config.servers.contains_key (server_name) {
if ! state.server_exists (server_name).await {
return Err (UnknownServer);
}
}
let user = get_user_name (&req);
@ -643,10 +640,16 @@ async fn handle_all (
let api_key = req.headers ().get ("X-ApiKey");
let api_key = match api_key {
None => return Ok (error_reply (StatusCode::FORBIDDEN, "Can't run server without an API key")?),
None => return Ok (error_reply (StatusCode::FORBIDDEN, "Forbidden")?),
Some (x) => x,
};
server_endpoint::handle_listen (state, listen_code.into (), api_key.as_bytes ()).await?
match check_server_api_key (state, listen_code, api_key.as_bytes ()).await {
Ok (_) => (),
Err (_) => return Ok (error_reply (StatusCode::FORBIDDEN, "Forbidden")?)
}
server_endpoint::handle_listen (state, listen_code.into ()).await?
},
ServerHttpResponse {
request_code,
@ -658,41 +661,42 @@ async fn handle_all (
Ok (response)
}
async fn check_server_api_key (state: &Relay, name: &str, req: &http::request::Parts)
async fn check_server_api_key (state: &Relay, name: &str, api_key: &[u8])
-> Result <(), anyhow::Error>
{
let api_key = req.headers.get ("X-ApiKey");
let actual_tripcode = key_validity::BlakeHashWrapper::from_key (api_key);
let api_key = match api_key {
None => bail! ("Can't run server without an API key"),
Some (x) => x,
};
let actual_tripcode = blake3::hash (api_key.as_bytes ());
let expected_tripcode = {
let expected_human = {
let config = state.config.read ().await;
match config.servers.get (name) {
None => {
config.servers.get (name).map (|s| s.tripcode.clone ())
};
let expected_machine = {
let me_config = state.me_config.read ().await;
me_config.servers.get (name).map (|s| s.tripcode.clone ())
};
if expected_machine.is_none () && expected_human.is_none () {
state.unregistered_servers.push (crate::RejectedServer {
name: name.to_string (),
tripcode: actual_tripcode,
tripcode: *actual_tripcode,
seen: Utc::now (),
}).await;
bail! ("Denied API request for non-existent server name {}", name);
},
Some (x) => *(*x).tripcode,
}
};
if expected_tripcode != actual_tripcode {
if Some (actual_tripcode) == expected_human {
return Ok (());
}
if Some (actual_tripcode) == expected_machine {
return Ok (());
}
bail! ("Denied API request for bad tripcode {}", base64::encode (actual_tripcode.as_bytes ()));
}
Ok (())
}
fn load_templates (asset_root: &Path)
-> Result <Handlebars <'static>, RelayError>
{

View File

@ -182,7 +182,7 @@ impl TryFrom <Config> for Relay {
let me_config = match machine_editable::Config::from_file (Path::new ("data/ptth_relay_me_config.toml"))
{
Err (e) => {
error! ("Can't load machine-editable config: {:?}", e);
warn! ("Can't load machine-editable config: {:?}", e);
me_config
},
Ok (x) => x,
@ -211,6 +211,24 @@ impl Relay {
.collect ()
}
pub async fn server_exists (&self, name: &str) -> bool {
{
let config = self.config.read ().await;
if config.servers.contains_key (name) {
return true;
}
}
{
let config = self.me_config.read ().await;
if config.servers.contains_key (name) {
return true;
}
}
false
}
pub fn build () -> Builder {
Builder::default ()
}

View File

@ -68,20 +68,31 @@ pub async fn v1_server_list (state: &Relay)
-> ServerList
{
// name --> display_name
let display_names: HashMap <String, String> = {
let mut display_names = HashMap::new ();
{
let guard = state.config.read ().await;
let servers = (*guard).servers.iter ()
.map (|(k, v)| {
for (k, v) in &guard.servers {
let display_name = v.display_name
.clone ()
.unwrap_or_else (|| k.clone ());
(k.clone (), display_name)
});
display_names.insert (k.clone (), display_name);
}
}
servers.collect ()
};
{
let guard = state.me_config.read ().await;
for (k, v) in &guard.servers {
let display_name = v.display_name
.clone ()
.unwrap_or_else (|| k.clone ());
display_names.insert (k.clone (), display_name);
}
}
// name --> status
let server_statuses = {

View File

@ -45,41 +45,12 @@ use super::{
pub async fn handle_listen (
state: &Relay,
watcher_code: String,
api_key: &[u8],
)
-> Result <Response <Body>, RequestError>
{
use super::RequestRendezvous::*;
let trip_error = || Ok (error_reply (StatusCode::UNAUTHORIZED, "Bad X-ApiKey")?);
let now = Utc::now ();
let actual_tripcode = blake3::hash (api_key);
let expected_tripcode = {
let config = state.config.read ().await;
match config.servers.get (&watcher_code) {
None => {
error! ("Denied http_listen for non-existent server name {}", watcher_code);
state.unregistered_servers.push (crate::RejectedServer {
name: watcher_code,
tripcode: actual_tripcode,
seen: now,
}).await;
return trip_error ();
},
Some (x) => *(*x).tripcode,
}
};
if expected_tripcode != actual_tripcode {
error! ("Denied http_listen for bad tripcode {}", base64::encode (actual_tripcode.as_bytes ()));
return trip_error ();
}
// End of early returns
{
// TODO: Move into relay_state.rs