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;
|
2020-09-07 09:45:55 +02:00
|
|
|
use crate::auth;
|
|
|
|
use crate::api;
|
2020-05-11 18:21:45 +02:00
|
|
|
|
2020-10-22 13:00:58 +02:00
|
|
|
pub use crate::schema::connection_capnp;
|
2020-05-10 17:23:43 +02:00
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
2020-09-07 09:45:55 +02:00
|
|
|
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?;
|
|
|
|
}
|
2020-09-07 09:45:55 +02:00
|
|
|
{
|
|
|
|
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>();
|
2020-09-07 09:45:55 +02:00
|
|
|
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();
|
2020-09-07 09:45:55 +02:00
|
|
|
|
|
|
|
let mut auth_success = false;
|
|
|
|
|
|
|
|
match m.which() {
|
2020-09-08 09:56:40 +02:00
|
|
|
Ok(connection_capnp::message::Which::Auth(Ok(r))) => {
|
2020-09-07 09:45:55 +02:00
|
|
|
if let Ok(w) = r.which() {
|
2020-09-08 09:56:40 +02:00
|
|
|
use crate::auth::auth_capnp::auth_message::*;
|
2020-09-07 09:45:55 +02:00
|
|
|
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::*;
|
2020-09-07 09:45:55 +02:00
|
|
|
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();
|
2020-09-07 09:45:55 +02:00
|
|
|
|
|
|
|
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);
|
2020-09-07 09:45:55 +02:00
|
|
|
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);
|
2020-09-07 09:45:55 +02:00
|
|
|
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(())
|
|
|
|
}
|