2020-06-10 04:07:43 +02:00
|
|
|
use crate::actors::v1_read::{LdapRequestMessage, QueryServerReadV1};
|
|
|
|
use crate::ldap::{LdapBoundToken, LdapResponseState};
|
|
|
|
use openssl::ssl::{SslAcceptor, SslAcceptorBuilder};
|
|
|
|
|
2020-09-06 00:44:35 +02:00
|
|
|
use futures_util::sink::SinkExt;
|
2020-06-10 04:07:43 +02:00
|
|
|
use futures_util::stream::StreamExt;
|
2020-09-06 00:44:35 +02:00
|
|
|
// use ldap3_server::simple::*;
|
2020-06-10 04:07:43 +02:00
|
|
|
use ldap3_server::LdapCodec;
|
|
|
|
// use std::convert::TryFrom;
|
|
|
|
use std::marker::Unpin;
|
|
|
|
use std::net;
|
|
|
|
use std::str::FromStr;
|
2020-09-06 00:44:35 +02:00
|
|
|
use tokio::io::{AsyncRead, AsyncWrite};
|
|
|
|
use tokio::net::TcpListener;
|
|
|
|
use tokio_util::codec::{FramedRead, FramedWrite};
|
2020-06-10 04:07:43 +02:00
|
|
|
use uuid::Uuid;
|
|
|
|
|
2020-09-06 00:44:35 +02:00
|
|
|
struct LdapSession {
|
2020-06-10 04:07:43 +02:00
|
|
|
uat: Option<LdapBoundToken>,
|
|
|
|
}
|
|
|
|
|
2020-09-06 00:44:35 +02:00
|
|
|
impl LdapSession {
|
|
|
|
fn new() -> Self {
|
|
|
|
LdapSession {
|
|
|
|
// We start un-authenticated
|
|
|
|
uat: None,
|
|
|
|
}
|
|
|
|
}
|
2020-06-10 04:07:43 +02:00
|
|
|
}
|
|
|
|
|
2020-09-06 00:44:35 +02:00
|
|
|
async fn client_process<W: AsyncWrite + Unpin, R: AsyncRead + Unpin>(
|
|
|
|
mut r: FramedRead<R, LdapCodec>,
|
|
|
|
mut w: FramedWrite<W, LdapCodec>,
|
|
|
|
_paddr: net::SocketAddr,
|
|
|
|
qe_r_ref: &'static QueryServerReadV1,
|
|
|
|
) {
|
|
|
|
// This is a connected client session. we need to associate some state to the
|
|
|
|
// session
|
|
|
|
let mut session = LdapSession::new();
|
|
|
|
// Now that we have the session we begin an event loop to process input OR
|
|
|
|
// we return.
|
|
|
|
while let Some(Ok(protomsg)) = r.next().await {
|
|
|
|
// Start the event
|
2020-06-10 04:07:43 +02:00
|
|
|
let eventid = Uuid::new_v4();
|
2020-09-06 00:44:35 +02:00
|
|
|
let uat = session.uat.clone();
|
|
|
|
let qs_result = qe_r_ref
|
|
|
|
.handle_ldaprequest(LdapRequestMessage {
|
|
|
|
eventid,
|
|
|
|
protomsg,
|
|
|
|
uat,
|
|
|
|
})
|
|
|
|
.await;
|
|
|
|
|
|
|
|
match qs_result {
|
|
|
|
Some(LdapResponseState::Unbind) => return,
|
|
|
|
Some(LdapResponseState::Disconnect(rmsg)) => {
|
|
|
|
if let Err(_) = w.send(rmsg).await {
|
|
|
|
break;
|
2020-06-10 04:07:43 +02:00
|
|
|
}
|
2020-09-06 00:44:35 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
Some(LdapResponseState::Bind(uat, rmsg)) => {
|
|
|
|
session.uat = Some(uat);
|
|
|
|
if let Err(_) = w.send(rmsg).await {
|
|
|
|
break;
|
2020-06-10 04:07:43 +02:00
|
|
|
}
|
2020-09-06 00:44:35 +02:00
|
|
|
}
|
|
|
|
Some(LdapResponseState::Respond(rmsg)) => {
|
|
|
|
if let Err(_) = w.send(rmsg).await {
|
|
|
|
break;
|
2020-06-10 04:07:43 +02:00
|
|
|
}
|
2020-09-06 00:44:35 +02:00
|
|
|
}
|
|
|
|
Some(LdapResponseState::MultiPartResponse(v)) => {
|
|
|
|
for rmsg in v.into_iter() {
|
|
|
|
if let Err(_) = w.send(rmsg).await {
|
|
|
|
break;
|
|
|
|
}
|
2020-06-10 04:07:43 +02:00
|
|
|
}
|
2020-09-06 00:44:35 +02:00
|
|
|
}
|
|
|
|
Some(LdapResponseState::BindMultiPartResponse(uat, v)) => {
|
|
|
|
session.uat = Some(uat);
|
|
|
|
for rmsg in v.into_iter() {
|
|
|
|
if let Err(_) = w.send(rmsg).await {
|
|
|
|
break;
|
|
|
|
}
|
2020-06-10 04:07:43 +02:00
|
|
|
}
|
2020-09-06 00:44:35 +02:00
|
|
|
}
|
|
|
|
None => {
|
|
|
|
error!("Internal server error");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
};
|
2020-06-10 04:07:43 +02:00
|
|
|
}
|
2020-09-06 00:44:35 +02:00
|
|
|
// We now are leaving, so any cleanup done here.
|
2020-06-10 04:07:43 +02:00
|
|
|
}
|
|
|
|
|
2020-09-06 00:44:35 +02:00
|
|
|
async fn tls_acceptor(
|
|
|
|
mut listener: TcpListener,
|
|
|
|
tls_parms: SslAcceptor,
|
|
|
|
qe_r_ref: &'static QueryServerReadV1,
|
|
|
|
) {
|
|
|
|
// Do we need to do the silly ssl leak?
|
|
|
|
loop {
|
|
|
|
match listener.accept().await {
|
|
|
|
Ok((tcpstream, paddr)) => {
|
|
|
|
let res = tokio_openssl::accept(&tls_parms, tcpstream).await;
|
|
|
|
let tlsstream = match res {
|
|
|
|
Ok(ts) => ts,
|
|
|
|
Err(e) => {
|
|
|
|
error!("tls handshake error, continuing -> {:?}", e);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
let (r, w) = tokio::io::split(tlsstream);
|
|
|
|
let r = FramedRead::new(r, LdapCodec);
|
|
|
|
let w = FramedWrite::new(w, LdapCodec);
|
|
|
|
tokio::spawn(client_process(r, w, paddr, qe_r_ref));
|
|
|
|
}
|
|
|
|
Err(e) => {
|
|
|
|
error!("acceptor error, continuing -> {:?}", e);
|
2020-06-10 04:07:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-06 00:44:35 +02:00
|
|
|
async fn acceptor(mut listener: TcpListener, qe_r_ref: &'static QueryServerReadV1) {
|
|
|
|
loop {
|
|
|
|
match listener.accept().await {
|
|
|
|
Ok((tcpstream, paddr)) => {
|
|
|
|
let (r, w) = tokio::io::split(tcpstream);
|
|
|
|
let r = FramedRead::new(r, LdapCodec);
|
|
|
|
let w = FramedWrite::new(w, LdapCodec);
|
|
|
|
// Let it rip.
|
|
|
|
tokio::spawn(client_process(r, w, paddr, qe_r_ref));
|
|
|
|
}
|
|
|
|
Err(e) => {
|
|
|
|
error!("acceptor error, continuing -> {:?}", e);
|
|
|
|
}
|
2020-06-10 04:07:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) async fn create_ldap_server(
|
|
|
|
address: &str,
|
|
|
|
opt_tls_params: Option<SslAcceptorBuilder>,
|
2020-09-06 00:44:35 +02:00
|
|
|
qe_r_ref: &'static QueryServerReadV1,
|
2020-06-10 04:07:43 +02:00
|
|
|
) -> Result<(), ()> {
|
|
|
|
let addr = net::SocketAddr::from_str(address).map_err(|e| {
|
2020-06-18 02:30:42 +02:00
|
|
|
eprintln!("Could not parse ldap server address {} -> {:?}", address, e);
|
2020-06-10 04:07:43 +02:00
|
|
|
})?;
|
|
|
|
|
2020-09-06 00:44:35 +02:00
|
|
|
let listener = TcpListener::bind(&addr).await.map_err(|e| {
|
2020-08-04 04:58:11 +02:00
|
|
|
eprintln!(
|
|
|
|
"Could not bind to ldap server address {} -> {:?}",
|
|
|
|
address, e
|
|
|
|
);
|
2020-09-06 00:44:35 +02:00
|
|
|
})?;
|
2020-06-10 04:07:43 +02:00
|
|
|
|
|
|
|
match opt_tls_params {
|
|
|
|
Some(tls_params) => {
|
|
|
|
info!("Starting LDAPS interface ldaps://{} ...", address);
|
2020-09-06 00:44:35 +02:00
|
|
|
let tls_parms = tls_params.build();
|
|
|
|
tokio::spawn(tls_acceptor(listener, tls_parms, qe_r_ref));
|
2020-06-10 04:07:43 +02:00
|
|
|
}
|
|
|
|
None => {
|
|
|
|
info!("Starting LDAP interface ldap://{} ...", address);
|
2020-09-06 00:44:35 +02:00
|
|
|
tokio::spawn(acceptor(listener, qe_r_ref));
|
2020-06-10 04:07:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
info!("Created LDAP interface");
|
|
|
|
Ok(())
|
|
|
|
}
|