mirror of
https://github.com/nitnelave/lldap.git
synced 2023-04-12 14:25:13 +00:00
WIP: sorry this does not compiles
This commit is contained in:
parent
ad445ac7b7
commit
6eaf859ba9
17
Cargo.toml
17
Cargo.toml
@ -4,21 +4,24 @@ edition = "2018"
|
|||||||
name = "lldap"
|
name = "lldap"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix = "*"
|
actix = "0.11.0-beta.3"
|
||||||
actix-rt = "1.1.1"
|
actix-rt = "*"
|
||||||
actix-server = "*"
|
actix-server = "2.0.0-beta.3"
|
||||||
actix-service = "*"
|
actix-service = "2.0.0-beta.4"
|
||||||
actix-web = "*"
|
actix-web = "4.0.0-beta.3"
|
||||||
anyhow = "*"
|
anyhow = "*"
|
||||||
clap = "3.0.0-beta.2"
|
clap = "3.0.0-beta.2"
|
||||||
|
futures = "*"
|
||||||
futures-util = "*"
|
futures-util = "*"
|
||||||
http = "*"
|
http = "*"
|
||||||
|
ldap3_server = "*"
|
||||||
log = "*"
|
log = "*"
|
||||||
serde = "*"
|
serde = "*"
|
||||||
thiserror = "*"
|
thiserror = "*"
|
||||||
tokio = "0.2.25"
|
tokio = { version = "*", features = ["full"] }
|
||||||
|
tokio-util = "*"
|
||||||
tracing = "*"
|
tracing = "*"
|
||||||
tracing-actix-web = "*"
|
tracing-actix-web = "0.3.0-beta.2"
|
||||||
tracing-log = "*"
|
tracing-log = "*"
|
||||||
tracing-subscriber = "*"
|
tracing-subscriber = "*"
|
||||||
|
|
||||||
|
150
examples/ldap_server.rs
Normal file
150
examples/ldap_server.rs
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
use tokio::net::{TcpListener, TcpStream};
|
||||||
|
// use tokio::stream::StreamExt;
|
||||||
|
use futures::SinkExt;
|
||||||
|
use futures::StreamExt;
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
use std::net;
|
||||||
|
use std::str::FromStr;
|
||||||
|
use tokio_util::codec::{FramedRead, FramedWrite};
|
||||||
|
|
||||||
|
use ldap3_server::simple::*;
|
||||||
|
use ldap3_server::LdapCodec;
|
||||||
|
|
||||||
|
pub struct LdapSession {
|
||||||
|
dn: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LdapSession {
|
||||||
|
pub fn do_bind(&mut self, sbr: &SimpleBindRequest) -> LdapMsg {
|
||||||
|
if sbr.dn == "cn=Directory Manager" && sbr.pw == "password" {
|
||||||
|
self.dn = sbr.dn.to_string();
|
||||||
|
sbr.gen_success()
|
||||||
|
} else if sbr.dn == "" && sbr.pw == "" {
|
||||||
|
self.dn = "Anonymous".to_string();
|
||||||
|
sbr.gen_success()
|
||||||
|
} else {
|
||||||
|
sbr.gen_invalid_cred()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_search(&mut self, lsr: &SearchRequest) -> Vec<LdapMsg> {
|
||||||
|
vec![
|
||||||
|
lsr.gen_result_entry(LdapSearchResultEntry {
|
||||||
|
dn: "cn=hello,dc=example,dc=com".to_string(),
|
||||||
|
attributes: vec![
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "objectClass".to_string(),
|
||||||
|
vals: vec!["cursed".to_string()],
|
||||||
|
},
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "cn".to_string(),
|
||||||
|
vals: vec!["hello".to_string()],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
lsr.gen_result_entry(LdapSearchResultEntry {
|
||||||
|
dn: "cn=world,dc=example,dc=com".to_string(),
|
||||||
|
attributes: vec![
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "objectClass".to_string(),
|
||||||
|
vals: vec!["cursed".to_string()],
|
||||||
|
},
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "cn".to_string(),
|
||||||
|
vals: vec!["world".to_string()],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
lsr.gen_success(),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_whoami(&mut self, wr: &WhoamiRequest) -> LdapMsg {
|
||||||
|
wr.gen_success(format!("dn: {}", self.dn).as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_client(socket: TcpStream, _paddr: net::SocketAddr) {
|
||||||
|
// Configure the codec etc.
|
||||||
|
let (r, w) = tokio::io::split(socket);
|
||||||
|
let mut reqs = FramedRead::new(r, LdapCodec);
|
||||||
|
let mut resp = FramedWrite::new(w, LdapCodec);
|
||||||
|
|
||||||
|
let mut session = LdapSession {
|
||||||
|
dn: "Anonymous".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
while let Some(msg) = reqs.next().await {
|
||||||
|
let server_op = match msg
|
||||||
|
.map_err(|_e| ())
|
||||||
|
.and_then(|msg| ServerOps::try_from(msg))
|
||||||
|
{
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(_) => {
|
||||||
|
let _err = resp
|
||||||
|
.send(DisconnectionNotice::gen(
|
||||||
|
LdapResultCode::Other,
|
||||||
|
"Internal Server Error",
|
||||||
|
))
|
||||||
|
.await;
|
||||||
|
let _err = resp.flush().await;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = match server_op {
|
||||||
|
ServerOps::SimpleBind(sbr) => vec![session.do_bind(&sbr)],
|
||||||
|
ServerOps::Search(sr) => session.do_search(&sr),
|
||||||
|
ServerOps::Unbind(_) => {
|
||||||
|
// No need to notify on unbind (per rfc4511)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ServerOps::Whoami(wr) => vec![session.do_whoami(&wr)],
|
||||||
|
};
|
||||||
|
|
||||||
|
for rmsg in result.into_iter() {
|
||||||
|
if let Err(_) = resp.send(rmsg).await {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(_) = resp.flush().await {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Client disconnected
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn acceptor(listener: Box<TcpListener>) {
|
||||||
|
println!("start function");
|
||||||
|
loop {
|
||||||
|
println!("loop");
|
||||||
|
match listener.accept().await {
|
||||||
|
Ok((socket, paddr)) => {
|
||||||
|
println!("OK listener");
|
||||||
|
tokio::spawn(handle_client(socket, paddr));
|
||||||
|
}
|
||||||
|
Err(_e) => {
|
||||||
|
println!("Err listener");
|
||||||
|
//pass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> () {
|
||||||
|
let addr = net::SocketAddr::from_str("0.0.0.0:12345").unwrap();
|
||||||
|
let listener = Box::new(TcpListener::bind(&addr).await.unwrap());
|
||||||
|
|
||||||
|
// Initiate the acceptor task.
|
||||||
|
let _handle = tokio::spawn(async move {
|
||||||
|
println!("inside tokio");
|
||||||
|
acceptor(listener).await
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.expect("tokio should start");
|
||||||
|
|
||||||
|
println!("started ldap://127.0.0.1:12345 ...");
|
||||||
|
tokio::signal::ctrl_c().await.unwrap();
|
||||||
|
}
|
124
src/infra/ldap_server.rs
Normal file
124
src/infra/ldap_server.rs
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
use crate::infra::configuration::Configuration;
|
||||||
|
use actix_rt::net::TcpStream;
|
||||||
|
use actix_server::Server;
|
||||||
|
use actix_service::pipeline_factory;
|
||||||
|
use anyhow::Result;
|
||||||
|
use futures_util::future::{err, ok};
|
||||||
|
use log::*;
|
||||||
|
|
||||||
|
use ldap3_server::simple::*;
|
||||||
|
use ldap3_server::LdapCodec;
|
||||||
|
|
||||||
|
pub struct LdapSession {
|
||||||
|
dn: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init(config: Configuration) -> Result<()> {
|
||||||
|
debug!("LDAP: init");
|
||||||
|
actix::run(run_ldap_server(config))?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LdapSession {
|
||||||
|
pub fn do_bind(&mut self, sbr: &SimpleBindRequest) -> LdapMsg {
|
||||||
|
if sbr.dn == "cn=Directory Manager" && sbr.pw == "password" {
|
||||||
|
self.dn = sbr.dn.to_string();
|
||||||
|
sbr.gen_success()
|
||||||
|
} else if sbr.dn == "" && sbr.pw == "" {
|
||||||
|
self.dn = "Anonymous".to_string();
|
||||||
|
sbr.gen_success()
|
||||||
|
} else {
|
||||||
|
sbr.gen_invalid_cred()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_search(&mut self, lsr: &SearchRequest) -> Vec<LdapMsg> {
|
||||||
|
vec![
|
||||||
|
lsr.gen_result_entry(LdapSearchResultEntry {
|
||||||
|
dn: "cn=hello,dc=example,dc=com".to_string(),
|
||||||
|
attributes: vec![
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "objectClass".to_string(),
|
||||||
|
vals: vec!["cursed".to_string()],
|
||||||
|
},
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "cn".to_string(),
|
||||||
|
vals: vec!["hello".to_string()],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
lsr.gen_result_entry(LdapSearchResultEntry {
|
||||||
|
dn: "cn=world,dc=example,dc=com".to_string(),
|
||||||
|
attributes: vec![
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "objectClass".to_string(),
|
||||||
|
vals: vec!["cursed".to_string()],
|
||||||
|
},
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "cn".to_string(),
|
||||||
|
vals: vec!["world".to_string()],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
lsr.gen_success(),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_whoami(&mut self, wr: &WhoamiRequest) -> LdapMsg {
|
||||||
|
wr.gen_success(format!("dn: {}", self.dn).as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn run_ldap_server(config: Configuration) {
|
||||||
|
use futures_util::SinkExt;
|
||||||
|
use futures_util::StreamExt;
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
use tokio_util::codec::{FramedRead, FramedWrite};
|
||||||
|
|
||||||
|
Server::build()
|
||||||
|
.bind("test-tcp", ("0.0.0.0", config.ldap_port), move || {
|
||||||
|
pipeline_factory(move |mut stream: TcpStream| async {
|
||||||
|
// Configure the codec etc.
|
||||||
|
let (r, w) = stream.split();
|
||||||
|
let mut reqs = FramedRead::new(r, LdapCodec);
|
||||||
|
let mut resp = FramedWrite::new(w, LdapCodec);
|
||||||
|
|
||||||
|
let mut session = LdapSession {
|
||||||
|
dn: "Anonymous".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
while let Some(msg) = reqs.next().await {
|
||||||
|
let server_op = match msg
|
||||||
|
.map_err(|_e| ())
|
||||||
|
.and_then(|msg| ServerOps::try_from(msg))
|
||||||
|
{
|
||||||
|
Ok(aValue) => aValue,
|
||||||
|
Err(anError) => {
|
||||||
|
let _err = resp
|
||||||
|
.send(DisconnectionNotice::gen(
|
||||||
|
LdapResultCode::Other,
|
||||||
|
"Internal Server Error",
|
||||||
|
))
|
||||||
|
.await;
|
||||||
|
let _err = resp.flush().await;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ok::<TcpStream, ()>(stream)
|
||||||
|
})
|
||||||
|
.map_err(|err| error!("Service Error: {:?}", err))
|
||||||
|
// catch
|
||||||
|
.and_then(move |_| {
|
||||||
|
// finally
|
||||||
|
ok(())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
.workers(1)
|
||||||
|
.run()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
pub mod cli;
|
pub mod cli;
|
||||||
pub mod configuration;
|
pub mod configuration;
|
||||||
|
pub mod ldap_server;
|
||||||
pub mod logging;
|
pub mod logging;
|
||||||
pub mod tcp_server;
|
pub mod tcp_server;
|
||||||
|
@ -13,7 +13,8 @@ fn main() -> Result<()> {
|
|||||||
debug!("CLI: {:#?}", cli_opts);
|
debug!("CLI: {:#?}", cli_opts);
|
||||||
debug!("Configuration: {:#?}", config);
|
debug!("Configuration: {:#?}", config);
|
||||||
|
|
||||||
infra::tcp_server::init(config)?;
|
// infra::tcp_server::init(config)?;
|
||||||
|
infra::ldap_server::init(config)?;
|
||||||
|
|
||||||
info!("End.");
|
info!("End.");
|
||||||
Ok(())
|
Ok(())
|
||||||
|
Loading…
Reference in New Issue
Block a user