ldap3/
lib.rs

1//! A pure-Rust LDAP client library using the Tokio stack.
2//!
3//! ## Usage
4//!
5//! In `Cargo.toml`:
6//!
7//! ```toml
8//! [dependencies.ldap3]
9//! version = "0.12.1"
10//! ```
11//!
12//! ## Summary
13//!
14//! The library provides both synchronous and asynchronous interfaces. The [`LdapConn`](struct.LdapConn.html)
15//! structure is the starting point for all synchronous operations. [`LdapConnAsync`](struct.LdapConnAsync.html)
16//! is its asynchronous analogue, and [`Ldap`](struct.Ldap.html) is the low-level asynchronous handle used
17//! internally by `LdapConn`, and explicitly by the users of the asynchronous interface.
18//!
19//! In the [struct list](#structs), async-related structs have an asterisk (__*__) after
20//! the short description.
21//!
22//! The documentation is written for readers familiar with LDAP concepts and terminology,
23//! which it won't attempt to explain. If you need an introductory text, you can try the
24//! [primer](https://github.com/inejge/ldap3/blob/27a247c8a6e4e2c86f664f4280c4c6499f0e9fe5/LDAP-primer.md)
25//! included in this library.
26//!
27//! ## Compile-time features
28//!
29//! The following features are available at compile time:
30//!
31//! * __sync__ (enabled by default): Synchronous API support.
32//!
33//! * __gssapi__ (disabled by default): Kerberos/GSSAPI support. On Windows, system support
34//!   crates and SDK libraries are used. Elsewhere, the feature needs Clang and its development
35//!   libraries (for `bindgen`), as well as the Kerberos development libraries. On Debian/Ubuntu,
36//!   that means `clang-N`, `libclang-N-dev` and `libkrb5-dev`. It should be clear from these
37//!   requirements that GSSAPI support uses FFI to C libraries; you should consider the security
38//!   implications of this fact.
39//!
40//!   For usage notes and caveats, see the documentation for
41//!   [`Ldap::sasl_gssapi_bind()`](struct.Ldap.html#method.sasl_gssapi_bind).
42//!
43//! * __ntlm__ (disabled by default): NTLM authentication support. Username and password must
44//!   be provided, and the password must be in cleartext. It works on TLS connections, or clear
45//!   connections with no signing or sealing. With TLS, a channel binding token is sent to the
46//!   server if possible. See [`Ldap::sasl_ntlm_bind()`](struct.Ldap.html#method.sasl_ntlm_bind).
47//!
48//! * __tls__ (enabled by default): TLS support, backed by the `native-tls` crate, which uses
49//!  a platform-specific TLS backend. This is an alias for __tls-native__.
50//!
51//! * __tls-rustls-...__ (disabled by default): TLS support, backed by the Rustls library. The
52//!   bare __tls-rustls__ flag, used previously for this purpose, won't work by itself; one
53//!   must choose the crypto provider for Rustls. There are two predefined flags for this
54//!   purpose, __tls-rustls-aws-lc-rs__ and __tls-rustls-ring__. If another provider is
55//!   needed, it can be chosen by activating the corresponding feature in Rustls and setting
56//!   the flags __tls-rustls__ and __rustls-provider__. For example the AWS FIPS provider can
57//!   be chosen with:
58//!
59//!   ... `--features tls-rustls,rustls/fips,rustls-provider`
60//!
61//!   Not selecting a provider, or selecting one without specifying __rustls-provider__, will
62//!   produce a compile-time error.
63//!
64//! Without any features, only plain TCP connections (and Unix domain sockets on Unix-like
65//! platforms) are available. For TLS support, __tls__ and __tls-rustls__ are mutually
66//! exclusive: choosing both will produce a compile-time error.
67//!
68//! ## Examples
69//!
70//! The following two examples perform exactly the same operation and should produce identical
71//! results. They should be run against the example server in the `data` subdirectory of the crate source.
72//! Other sample programs expecting the same server setup can be found in the `examples` subdirectory.
73//!
74//! ### Synchronous search
75//!
76//! ```rust,no_run
77//! use ldap3::{LdapConn, Scope, SearchEntry};
78//! use ldap3::result::Result;
79//!
80//! fn main() -> Result<()> {
81//!     let mut ldap = LdapConn::new("ldap://localhost:2389")?;
82//!     let (rs, _res) = ldap.search(
83//!         "ou=Places,dc=example,dc=org",
84//!         Scope::Subtree,
85//!         "(&(objectClass=locality)(l=ma*))",
86//!         vec!["l"]
87//!     )?.success()?;
88//!     for entry in rs {
89//!         println!("{:?}", SearchEntry::construct(entry));
90//!     }
91//!     Ok(ldap.unbind()?)
92//! }
93//! ```
94//!
95//! ### Asynchronous search
96//!
97//! ```rust,no_run
98//! use ldap3::{LdapConnAsync, Scope, SearchEntry};
99//! use ldap3::result::Result;
100//!
101//! #[tokio::main]
102//! async fn main() -> Result<()> {
103//!     let (conn, mut ldap) = LdapConnAsync::new("ldap://localhost:2389").await?;
104//!     ldap3::drive!(conn);
105//!     let (rs, _res) = ldap.search(
106//!         "ou=Places,dc=example,dc=org",
107//!         Scope::Subtree,
108//!         "(&(objectClass=locality)(l=ma*))",
109//!         vec!["l"]
110//!     ).await?.success()?;
111//!     for entry in rs {
112//!         println!("{:?}", SearchEntry::construct(entry));
113//!     }
114//!     Ok(ldap.unbind().await?)
115//! }
116//! ```
117
118#![cfg_attr(docsrs, feature(doc_cfg))]
119
120#[doc(hidden)]
121#[macro_use]
122pub extern crate log;
123#[doc(hidden)]
124pub use tokio;
125
126/// Type alias for the LDAP message ID.
127pub type RequestId = i32;
128
129pub mod adapters;
130pub mod asn1 {
131    //! ASN.1 structure construction and parsing.
132    //!
133    //! This section is deliberately under-documented; it's expected that the ASN.1 subsystem will
134    //! be extensively overhauled in the future. If you need examples of using the present interface
135    //! for, e.g., implementing a new extended operation or a control, consult the source of existing
136    //! exops/controls.
137    pub use lber::IResult;
138    pub use lber::common::TagClass;
139    pub use lber::parse::{parse_tag, parse_uint};
140    pub use lber::structure::{PL, StructureTag};
141    pub use lber::structures::{
142        ASNTag, Boolean, Enumerated, ExplicitTag, Integer, Null, OctetString, Sequence, Set, Tag,
143    };
144    pub use lber::universal::Types;
145    pub use lber::write;
146}
147mod conn;
148pub mod controls {
149    //! Control construction and parsing.
150    //!
151    //! A control can be associated with a request or a response. Several common
152    //! controls, such as [`PagedResults`](struct.PagedResults.html), are implemented
153    //! directly by this library. If an implemented control has the same form for
154    //! the request and the response, there will be a single structure for both.
155    //! (This is the case for `PagedResults`.) If the response control is different,
156    //! its name will consist of the request control name with the `Resp` suffix.
157    //!
158    //! A request control can be created by instantiating its structure and converting
159    //! it to ASN.1 with `into()` when passing the instance or constructing the request
160    //! control vector in the call to [`with_controls()`](../struct.LdapConn.html#method.with_controls).
161    //! A third-party control must implement the conversion from an instance
162    //! of itself to [`RawControl`](struct.RawControl.html), a general form of control.
163    //!
164    //! `RawControl`, together with an optional instance of [`ControlType`](enum.ControlType.html),
165    //! forms the type [`Control`](struct.Control.html); a vector of `Control`s is part
166    //! of the result of all LDAP operation which return one.
167    //!
168    //! The first element of `Control` will have a value if the parser recognizes
169    //! the control's OID as one that is implemented by the library itself. Since the
170    //! list of implemented controls is expected to grow, the `ControlType` enum cannot
171    //! be exhaustively matched.
172    //!
173    //! A recognized response control can be parsed by calling
174    //! [`parse()`](struct.RawControl.html#method.parse) on the instance of `RawControl`
175    //! representing it. A third-party control must implement the
176    //! [`ControlParser`](trait.ControlParser.html) trait to support this interface.
177    //!
178    //! ### Example
179    //!
180    //! With an `LdapResult` in `res`, iterating through controls and matching the desired ones
181    //! could be done like this:
182    //!
183    //! ```rust,no_run
184    //! # use ldap3::controls::{Control, ControlType, PagedResults};
185    //! # use ldap3::result::Result;
186    //! # use ldap3::LdapConn;
187    //! # fn main() -> Result<()> {
188    //! # let mut ldap = LdapConn::new("ldap://localhost")?;
189    //! # let res = ldap.simple_bind("", "")?.success()?;
190    //! for ctrl in res.ctrls {
191    //!     match ctrl {
192    //!         // matching a control implemented by the library
193    //!         Control(Some(ControlType::PagedResults), ref raw) => {
194    //!             dbg!(raw.parse::<PagedResults>());
195    //!         },
196    //!         // matching a control unknown to the library
197    //!         // the OID is actually that of PagedResults
198    //!         Control(None, ref raw) if raw.ctype == "1.2.840.113556.1.4.319" => {
199    //!             dbg!(raw.parse::<PagedResults>());
200    //!         },
201    //!         _ => (),
202    //!     }
203    //! }
204    //! # Ok(())
205    //! # }
206    pub use crate::controls_impl::TxnSpec;
207    pub use crate::controls_impl::parse_syncinfo;
208    pub use crate::controls_impl::{
209        Assertion, ManageDsaIt, MatchedValues, PagedResults, ProxyAuth, RelaxRules,
210    };
211    pub use crate::controls_impl::{
212        Control, ControlParser, ControlType, CriticalControl, IntoRawControlVec, MakeCritical,
213        RawControl,
214    };
215    pub use crate::controls_impl::{
216        EntryState, RefreshMode, SyncDone, SyncInfo, SyncRequest, SyncState,
217    };
218    pub use crate::controls_impl::{PostRead, PostReadResp, PreRead, PreReadResp, ReadEntryResp};
219}
220mod controls_impl;
221mod exop_impl;
222pub mod exop {
223    //! Extended operation construction and parsing.
224    //!
225    //! A generic exop is represented by [`Exop`](struct.Exop.html). If a particular
226    //! exop is implemented by this library, it may have one or two associated structs;
227    //! one for constructing requests, and another for parsing responses. If request and
228    //! response are the same, there is only the request struct; if they are different,
229    //! the response struct's name will consist of the request struct name with the
230    //! `Resp` suffix.
231    //!
232    //! A request struct must implement the `From` conversion of itself into `Exop`.
233    //! A response struct must implement the [`ExopParser`](trait.ExopParser.html)
234    //! trait.
235    pub use crate::exop_impl::{
236        EndTxn, EndTxnResp, Exop, ExopParser, PasswordModify, PasswordModifyResp, StartTxn,
237        StartTxnResp, WhoAmI, WhoAmIResp,
238    };
239}
240mod filter;
241mod ldap;
242mod protocol;
243pub mod result;
244mod search;
245#[cfg(feature = "sync")]
246mod sync;
247mod util;
248
249pub use conn::{LdapConnAsync, LdapConnSettings, StdStream};
250pub use filter::parse as parse_filter;
251pub use ldap::{Ldap, Mod};
252pub use result::{LdapError, LdapResult, SearchResult};
253pub use search::parse_refs;
254pub use search::{
255    DerefAliases, ResultEntry, Scope, SearchEntry, SearchOptions, SearchStream, StreamState,
256};
257#[cfg(feature = "sync")]
258pub use sync::{EntryStream, LdapConn};
259pub use util::{LdapUrlExt, LdapUrlParams, dn_escape, get_url_params, ldap_escape, ldap_unescape};