fabaccess-bffh/src/connection.rs

143 lines
5.9 KiB
Rust
Raw Normal View History

2020-05-11 18:21:45 +02:00
use slog::Logger;
2020-09-07 17:23:42 +02:00
use smol::net::TcpStream;
2020-05-11 18:21:45 +02:00
use crate::error::Result;
use crate::auth;
use crate::api;
2020-05-11 18:21:45 +02:00
2020-09-08 09:56:40 +02:00
pub mod connection_capnp {
include!(concat!(env!("OUT_DIR"), "/schema/connection_capnp.rs"));
}
2020-05-11 18:21:45 +02:00
pub async fn handle_connection(log: Logger, mut stream: TcpStream) -> Result<()> {
let host = "localhost";
let program = "Difluoroborane-0.1.0";
let version = (0u32,1u32);
let receive_options = capnp::message::ReaderOptions::default();
2020-05-14 23:19:26 +02:00
{
let message = capnp_futures::serialize::read_message(&mut stream, receive_options).await.unwrap().unwrap();
2020-09-08 09:56:40 +02:00
let m = message.get_root::<connection_capnp::message::Reader>().unwrap();
2020-05-14 23:19:26 +02:00
if m.has_greet() {
match m.which() {
2020-09-08 09:56:40 +02:00
Ok(connection_capnp::message::Which::Greet(Ok(r))) => {
2020-05-14 23:19:26 +02:00
println!("Host {} with program {} is saying hello. They speak API version {}.{}.",
r.get_host().unwrap(),
r.get_program().unwrap(),
r.get_major(),
r.get_minor())
},
_ => {
// We *JUST* checked that it's a greeting. This can not happen
unreachable!()
}
2020-05-11 18:21:45 +02:00
}
}
}
2020-05-14 23:19:26 +02:00
{
let mut message = capnp::message::Builder::new_default();
2020-09-08 09:56:40 +02:00
let greet_outer = message.init_root::<connection_capnp::message::Builder>();
2020-05-14 23:19:26 +02:00
let mut greeting = greet_outer.init_greet();
greeting.set_host(host);
greeting.set_program(program);
greeting.set_major(version.0);
greeting.set_minor(version.1);
capnp_futures::serialize::write_message(&mut stream, message).await?;
}
{
let mut message = capnp::message::Builder::new_default();
2020-09-08 09:56:40 +02:00
let outer = message.init_root::<connection_capnp::message::Builder>();
let mut mechs = outer.init_auth().init_mechanisms(1);
mechs.set(0, "PLAIN");
capnp_futures::serialize::write_message(&mut stream, message).await?;
}
{
let message = capnp_futures::serialize::read_message(&mut stream, receive_options).await.unwrap().unwrap();
2020-09-08 09:56:40 +02:00
let m = message.get_root::<connection_capnp::message::Reader>().unwrap();
let mut auth_success = false;
match m.which() {
2020-09-08 09:56:40 +02:00
Ok(connection_capnp::message::Which::Auth(Ok(r))) => {
if let Ok(w) = r.which() {
2020-09-08 09:56:40 +02:00
use crate::auth::auth_capnp::auth_message::*;
match w {
Request(Ok(r)) => {
let m = r.get_mechanism().unwrap();
println!("Client wants to AUTH using {:?}",
m);
let cm = std::ffi::CString::new(m).unwrap();
let mut sasl = auth::Auth::new();
let mut sess = sasl.ctx.server_start(&cm).unwrap();
2020-05-14 23:19:26 +02:00
2020-09-08 09:56:40 +02:00
use crate::auth::auth_capnp::request::initial_response::*;
match r.get_initial_response().which() {
Ok(Initial(Ok(r))) => {
debug!(log, "Client Auth with initial data");
let mut message = capnp::message::Builder::new_default();
2020-09-08 09:56:40 +02:00
let mut outer = message.init_root::<connection_capnp::message::Builder>().init_auth();
match sess.step(r) {
Ok(rsasl::Step::Done(b)) => {
auth_success = true;
debug!(log, "Authentication successful");
let mut outcome= outer.init_outcome();
2020-09-08 09:56:40 +02:00
outcome.set_result(auth::auth_capnp::outcome::Result::Successful);
if !b.is_empty() {
let mut add_data = outcome.init_additional_data();
add_data.set_additional(&b);
}
},
Ok(rsasl::Step::NeedsMore(b)) => {
debug!(log, "Authentication needs more data");
outer.set_response(&b);
}
Err(e) => {
warn!(log, "Authentication error: {}", e);
let mut outcome = outer.init_outcome();
// TODO: Distinguish errors
2020-09-08 09:56:40 +02:00
outcome.set_result(auth::auth_capnp::outcome::Result::Failed);
outcome.set_action(auth::auth_capnp::outcome::Action::Retry);
outcome.set_help_text(&format!("{}", e));
}
}
capnp_futures::serialize::write_message(&mut stream, message).await?;
}
_ => {
}
}
},
_ => {
}
}
} else {
println!("Got unexpected message");
}
},
Ok(_) => {
println!("Got unexpected message");
}
Err(e) => {
println!("Got error {:?}", e);
}
}
if auth_success {
info!(log, "Handing off to API connection handler");
api::handle_connection(log, stream).await;
}
}
2020-05-14 23:19:26 +02:00
2020-05-11 18:21:45 +02:00
Ok(())
}