ldap/
lib.rs

1extern crate asnom;
2
3extern crate futures;
4extern crate tokio_core;
5extern crate tokio_proto;
6extern crate tokio_service;
7
8extern crate byteorder;
9
10#[macro_use]
11extern crate log;
12
13use tokio_service::Service;
14
15use std::ops::Drop;
16use protocol::LdapProto;
17
18use std::io;
19use std::default::Default;
20use std::net::SocketAddr;
21
22use futures::Future;
23use tokio_core::reactor::Core;
24use tokio_core::net::TcpStream;
25use tokio_proto::TcpClient;
26use tokio_proto::multiplex::ClientService;
27
28use asnom::structures::*;
29use asnom::common::TagClass::*;
30
31mod protocol;
32
33pub struct LDAP {
34    inner: ClientService<TcpStream, LdapProto>,
35    core: Core
36}
37
38impl LDAP {
39    pub fn new(addr: &SocketAddr) -> Result<LDAP, io::Error> {
40        let mut core = Core::new().unwrap();
41
42        let handle = core.handle();
43
44        let client_fut = TcpClient::new(LdapProto).connect(addr, &handle);
45
46        let clientres = core.run(client_fut);
47
48        match clientres {
49            Ok(client) => {
50                Ok(LDAP {
51                    inner: client,
52                    core: core,
53                })
54            },
55            Err(e) => Err(e)
56        }
57    }
58
59    pub fn simple_bind(&self, dn: String, pw: String) -> Box<Future<Item = bool, Error = io::Error>> {
60        let req = Tag::Sequence(Sequence {
61            id: 0,
62            class: Application,
63            inner: vec![
64                   Tag::Integer(Integer {
65                       inner: 3,
66                       .. Default::default()
67                   }),
68                   Tag::OctetString(OctetString {
69                       inner: dn.into_bytes(),
70                       .. Default::default()
71                   }),
72                   Tag::OctetString(OctetString {
73                       id: 0,
74                       class: Context,
75                       inner: pw.into_bytes(),
76                   })
77            ],
78        });
79
80        let fut = self.inner.call(req).and_then(|res|
81            match res {
82                Tag::StructureTag(tag) => {
83                    if let Some(i) = tag.expect_constructed() {
84                        return Ok(i[0] == Tag::Integer(Integer {
85                            id: 10,
86                            class: Universal,
87                            inner: 0
88                        }).into_structure())
89                    } else {
90                        return Ok(false)
91                    }
92                }
93                _ => unimplemented!(),
94            }
95        );
96        Box::new(fut)
97    }
98
99    pub fn simple_bind_s(&mut self, dn: String, pw: String) -> Result<bool,io::Error> {
100        let fut = self.simple_bind(dn, pw);
101        self.core.run(fut)
102    }
103}
104
105impl Drop for LDAP {
106    fn drop(&mut self) {
107        let _ = self.core.run(self.inner.call(Tag::Null(Null {
108            id: 2,
109            class: Application,
110            inner: (),
111        })));
112    }
113}