mirror of
https://github.com/nitnelave/lldap.git
synced 2023-04-12 14:25:13 +00:00
Introduce BackendHandler trait and impl
This commit is contained in:
parent
1a947358fa
commit
ff4e986a0d
@ -3,6 +3,7 @@ authors = ["Valentin Tolmer <valentin@tolmer.fr>", "Steve Barrau <steve.barrau@g
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
name = "lldap"
|
name = "lldap"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix = "0.11.0-beta.3"
|
actix = "0.11.0-beta.3"
|
||||||
actix-rt = "2.1.0"
|
actix-rt = "2.1.0"
|
||||||
@ -29,3 +30,6 @@ tracing-subscriber = "*"
|
|||||||
[dependencies.figment]
|
[dependencies.figment]
|
||||||
features = ["toml", "env"]
|
features = ["toml", "env"]
|
||||||
version = "*"
|
version = "*"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
mockall = "0.9.1"
|
||||||
|
49
src/domain/handler.rs
Normal file
49
src/domain/handler.rs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
use crate::infra::configuration::Configuration;
|
||||||
|
use anyhow::{bail, Result};
|
||||||
|
use sqlx::any::AnyPool;
|
||||||
|
|
||||||
|
pub struct BindRequest {
|
||||||
|
pub name: String,
|
||||||
|
pub password: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SearchRequest {}
|
||||||
|
|
||||||
|
pub struct SearchResponse {}
|
||||||
|
|
||||||
|
pub trait BackendHandler: Clone + Send {
|
||||||
|
fn bind(&mut self, request: BindRequest) -> Result<()>;
|
||||||
|
fn search(&mut self, request: SearchRequest) -> Result<SearchResponse>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct SqlBackendHandler {
|
||||||
|
config: Configuration,
|
||||||
|
sql_pool: AnyPool,
|
||||||
|
authenticated: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SqlBackendHandler {
|
||||||
|
pub fn new(config: Configuration, sql_pool: AnyPool) -> Self {
|
||||||
|
SqlBackendHandler {
|
||||||
|
config,
|
||||||
|
sql_pool,
|
||||||
|
authenticated: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BackendHandler for SqlBackendHandler {
|
||||||
|
fn bind(&mut self, request: BindRequest) -> Result<()> {
|
||||||
|
if request.name == self.config.admin_dn && request.password == self.config.admin_password {
|
||||||
|
self.authenticated = true;
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
bail!(r#"Authentication error for "{}""#, request.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn search(&mut self, request: SearchRequest) -> Result<SearchResponse> {
|
||||||
|
Ok(SearchResponse {})
|
||||||
|
}
|
||||||
|
}
|
1
src/domain/mod.rs
Normal file
1
src/domain/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod handler;
|
@ -13,7 +13,8 @@ pub struct Configuration {
|
|||||||
pub ldaps_port: u16,
|
pub ldaps_port: u16,
|
||||||
pub http_port: u16,
|
pub http_port: u16,
|
||||||
pub secret_pepper: String,
|
pub secret_pepper: String,
|
||||||
pub some_text: String,
|
pub admin_dn: String,
|
||||||
|
pub admin_password: String,
|
||||||
pub verbose: bool,
|
pub verbose: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,7 +25,8 @@ impl Default for Configuration {
|
|||||||
ldaps_port: 6360,
|
ldaps_port: 6360,
|
||||||
http_port: 17170,
|
http_port: 17170,
|
||||||
secret_pepper: String::from("secretsecretpepper"),
|
secret_pepper: String::from("secretsecretpepper"),
|
||||||
some_text: String::new(),
|
admin_dn: String::new(),
|
||||||
|
admin_password: String::new(),
|
||||||
verbose: false,
|
verbose: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::domain::handler::BackendHandler;
|
||||||
use crate::infra::configuration::Configuration;
|
use crate::infra::configuration::Configuration;
|
||||||
use actix_rt::net::TcpStream;
|
use actix_rt::net::TcpStream;
|
||||||
use actix_server::ServerBuilder;
|
use actix_server::ServerBuilder;
|
||||||
@ -6,28 +7,30 @@ use anyhow::bail;
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use futures_util::future::ok;
|
use futures_util::future::ok;
|
||||||
use log::*;
|
use log::*;
|
||||||
use sqlx::any::AnyPool;
|
|
||||||
use tokio::net::tcp::WriteHalf;
|
use tokio::net::tcp::WriteHalf;
|
||||||
use tokio_util::codec::{FramedRead, FramedWrite};
|
use tokio_util::codec::{FramedRead, FramedWrite};
|
||||||
|
|
||||||
use ldap3_server::simple::*;
|
use ldap3_server::simple::*;
|
||||||
use ldap3_server::LdapCodec;
|
use ldap3_server::LdapCodec;
|
||||||
|
|
||||||
pub struct LdapSession {
|
pub struct LdapHandler<Backend: BackendHandler> {
|
||||||
dn: String,
|
dn: String,
|
||||||
sql_pool: AnyPool,
|
backend_handler: Backend,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LdapSession {
|
impl<Backend: BackendHandler> LdapHandler<Backend> {
|
||||||
pub fn do_bind(&mut self, sbr: &SimpleBindRequest) -> LdapMsg {
|
pub fn do_bind(&mut self, sbr: &SimpleBindRequest) -> LdapMsg {
|
||||||
if sbr.dn == "cn=Directory Manager" && sbr.pw == "password" {
|
match self
|
||||||
self.dn = sbr.dn.to_string();
|
.backend_handler
|
||||||
sbr.gen_success()
|
.bind(crate::domain::handler::BindRequest {
|
||||||
} else if sbr.dn == "" && sbr.pw == "" {
|
name: sbr.dn.clone(),
|
||||||
self.dn = "Anonymous".to_string();
|
password: sbr.pw.clone(),
|
||||||
sbr.gen_success()
|
}) {
|
||||||
} else {
|
Ok(()) => {
|
||||||
sbr.gen_invalid_cred()
|
self.dn = sbr.dn.clone();
|
||||||
|
sbr.gen_success()
|
||||||
|
}
|
||||||
|
Err(_) => sbr.gen_invalid_cred(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,10 +84,10 @@ impl LdapSession {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_incoming_message(
|
async fn handle_incoming_message<Backend: BackendHandler>(
|
||||||
msg: Result<LdapMsg, std::io::Error>,
|
msg: Result<LdapMsg, std::io::Error>,
|
||||||
resp: &mut FramedWrite<WriteHalf<'_>, LdapCodec>,
|
resp: &mut FramedWrite<WriteHalf<'_>, LdapCodec>,
|
||||||
session: &mut LdapSession,
|
session: &mut LdapHandler<Backend>,
|
||||||
) -> Result<bool> {
|
) -> Result<bool> {
|
||||||
use futures_util::SinkExt;
|
use futures_util::SinkExt;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
@ -122,27 +125,30 @@ async fn handle_incoming_message(
|
|||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_ldap_server(
|
pub fn build_ldap_server<Backend>(
|
||||||
config: &Configuration,
|
config: &Configuration,
|
||||||
sql_pool: AnyPool,
|
backend_handler: Backend,
|
||||||
server_builder: ServerBuilder,
|
server_builder: ServerBuilder,
|
||||||
) -> Result<ServerBuilder> {
|
) -> Result<ServerBuilder>
|
||||||
|
where
|
||||||
|
Backend: BackendHandler + 'static,
|
||||||
|
{
|
||||||
use futures_util::StreamExt;
|
use futures_util::StreamExt;
|
||||||
|
|
||||||
Ok(
|
Ok(
|
||||||
server_builder.bind("ldap", ("0.0.0.0", config.ldap_port), move || {
|
server_builder.bind("ldap", ("0.0.0.0", config.ldap_port), move || {
|
||||||
let sql_pool = sql_pool.clone();
|
let backend_handler = backend_handler.clone();
|
||||||
pipeline_factory(fn_service(move |mut stream: TcpStream| {
|
pipeline_factory(fn_service(move |mut stream: TcpStream| {
|
||||||
let sql_pool = sql_pool.clone();
|
let backend_handler = backend_handler.clone();
|
||||||
async move {
|
async move {
|
||||||
// Configure the codec etc.
|
// Configure the codec etc.
|
||||||
let (r, w) = stream.split();
|
let (r, w) = stream.split();
|
||||||
let mut requests = FramedRead::new(r, LdapCodec);
|
let mut requests = FramedRead::new(r, LdapCodec);
|
||||||
let mut resp = FramedWrite::new(w, LdapCodec);
|
let mut resp = FramedWrite::new(w, LdapCodec);
|
||||||
|
|
||||||
let mut session = LdapSession {
|
let mut session = LdapHandler {
|
||||||
dn: "Anonymous".to_string(),
|
dn: "Unauthenticated".to_string(),
|
||||||
sql_pool,
|
backend_handler,
|
||||||
};
|
};
|
||||||
|
|
||||||
while let Some(msg) = requests.next().await {
|
while let Some(msg) = requests.next().await {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::domain::handler::*;
|
||||||
use crate::infra::configuration::Configuration;
|
use crate::infra::configuration::Configuration;
|
||||||
use actix_rt::net::TcpStream;
|
use actix_rt::net::TcpStream;
|
||||||
use actix_server::ServerBuilder;
|
use actix_server::ServerBuilder;
|
||||||
@ -5,14 +6,16 @@ use actix_service::pipeline_factory;
|
|||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use futures_util::future::ok;
|
use futures_util::future::ok;
|
||||||
use log::*;
|
use log::*;
|
||||||
use sqlx::any::AnyPool;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub fn build_tcp_server(
|
pub fn build_tcp_server<Backend>(
|
||||||
config: &Configuration,
|
config: &Configuration,
|
||||||
sql_pool: AnyPool,
|
backend_handler: Backend,
|
||||||
server_builder: ServerBuilder,
|
server_builder: ServerBuilder,
|
||||||
) -> Result<ServerBuilder> {
|
) -> Result<ServerBuilder>
|
||||||
|
where
|
||||||
|
Backend: BackendHandler + 'static,
|
||||||
|
{
|
||||||
use std::sync::atomic::AtomicUsize;
|
use std::sync::atomic::AtomicUsize;
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
use tokio::io::AsyncReadExt;
|
use tokio::io::AsyncReadExt;
|
||||||
|
@ -4,6 +4,7 @@ use futures_util::TryFutureExt;
|
|||||||
use log::*;
|
use log::*;
|
||||||
use sqlx::any::AnyPoolOptions;
|
use sqlx::any::AnyPoolOptions;
|
||||||
|
|
||||||
|
mod domain;
|
||||||
mod infra;
|
mod infra;
|
||||||
|
|
||||||
async fn run_server(config: Configuration) -> Result<()> {
|
async fn run_server(config: Configuration) -> Result<()> {
|
||||||
@ -11,12 +12,14 @@ async fn run_server(config: Configuration) -> Result<()> {
|
|||||||
.max_connections(5)
|
.max_connections(5)
|
||||||
.connect("sqlite://users.db?mode=rwc")
|
.connect("sqlite://users.db?mode=rwc")
|
||||||
.await?;
|
.await?;
|
||||||
|
let backend_handler = domain::handler::SqlBackendHandler::new(config.clone(), sql_pool.clone());
|
||||||
let server_builder = infra::ldap_server::build_ldap_server(
|
let server_builder = infra::ldap_server::build_ldap_server(
|
||||||
&config,
|
&config,
|
||||||
sql_pool.clone(),
|
backend_handler.clone(),
|
||||||
actix_server::Server::build(),
|
actix_server::Server::build(),
|
||||||
)?;
|
)?;
|
||||||
let server_builder = infra::tcp_server::build_tcp_server(&config, sql_pool, server_builder)?;
|
let server_builder =
|
||||||
|
infra::tcp_server::build_tcp_server(&config, backend_handler, server_builder)?;
|
||||||
server_builder.workers(1).run().await?;
|
server_builder.workers(1).run().await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user