Skip to content

Commit 263a5c2

Browse files
author
Mathias Myrland
committed
Added start_tls_s support
1 parent 1f91324 commit 263a5c2

File tree

2 files changed

+100
-0
lines changed

2 files changed

+100
-0
lines changed

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,27 @@ fn main() {
4242
}
4343
```
4444

45+
### Security
46+
47+
You should use *start_tls* before calling bind to avoid sending credentials in plain text over an untrusted
48+
network. See https://linux.die.net/man/3/ldap_start_tls_s for more information
49+
50+
```rust
51+
fn some_ldap_function(ldap_uri: &str, ldap_user: &str, ldap_pass: &str) -> Result<(), LDAPError> {
52+
let ldap = try!(RustLDAP::new(ldap_uri));
53+
54+
ldap.set_option(codes::options::LDAP_OPT_PROTOCOL_VERSION,
55+
&codes::versions::LDAP_VERSION3);
56+
57+
ldap.set_option(codes::options::LDAP_OPT_X_TLS_REQUIRE_CERT,
58+
&codes::options::LDAP_OPT_X_TLS_DEMAND);
59+
ldap.set_option(openldap::codes::options::LDAP_OPT_X_TLS_NEWCTX, &0);
60+
ldap.start_tls(None, None);
61+
62+
try!(ldap.simple_bind(ldap_user, ldap_pass));
63+
}
64+
65+
```
4566
When performing an operation that can fail, use the `try!` macro. On failure,
4667
an `openldap::errors::LDAPError` will be returned that includes a detailed
4768
message from the native OpenLDAP library.

src/lib.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use std::ffi::{CStr, CString};
1010
use std::ptr;
1111
use std::slice;
1212
use std::boxed;
13+
use std::ptr::null_mut;
1314

1415
pub mod codes;
1516
pub mod errors;
@@ -78,6 +79,9 @@ extern "C" {
7879
sctrls: *mut *mut LDAPControl,
7980
cctrls: *mut *mut LDAPControl)
8081
-> c_int;
82+
fn ldap_start_tls_s(ldap: *mut LDAP,
83+
scrtrls: *mut *mut LDAPControl,
84+
cctrls: *mut *mut LDAPControl) -> c_int;
8185
}
8286

8387
/// A typedef for an `LDAPResponse` type.
@@ -270,6 +274,55 @@ impl RustLDAP {
270274
-1)
271275
}
272276

277+
/// Installs TLS handlers on the session
278+
///
279+
/// # Examples
280+
///
281+
/// ```
282+
/// use openldap::RustLDAP;
283+
/// let ldap = RustLDAP::new(&"ldaps://myserver:636");
284+
///
285+
/// ldap.set_option(
286+
/// openldap::codes::options::LDAP_OPT_PROTOCOL_VERSION,
287+
/// &openldap::codes::versions::LDAP_VERSION3,
288+
/// );
289+
///
290+
/// ldap.set_option(
291+
/// openldap::codes::options::LDAP_OPT_X_TLS_REQUIRE_CERT,
292+
/// &openldap::codes::options::LDAP_OPT_X_TLS_ALLOW,
293+
/// );
294+
///
295+
/// ldap.set_option(openldap::codes::options::LDAP_OPT_X_TLS_NEWCTX, &0);
296+
///
297+
/// ldap.start_tls(None, None);
298+
/// ldap.simple_bind("some-dn", "some-password").unwrap()
299+
/// ```
300+
pub fn start_tls(&self, serverctrls: Option<*mut *mut LDAPControl>, clientctrls: Option<*mut *mut LDAPControl>) -> Result<i32, errors::LDAPError> {
301+
let r_serverctrls = match serverctrls {
302+
Some(sc) => sc,
303+
None => ptr::null_mut(),
304+
};
305+
306+
let r_clientctrls = match clientctrls {
307+
Some(cc) => cc,
308+
None => ptr::null_mut(),
309+
};
310+
311+
unsafe {
312+
let res = ldap_start_tls_s(self.ldap_ptr, r_serverctrls, r_clientctrls);
313+
314+
if res < 0 {
315+
let raw_estr = ldap_err2string(res as c_int);
316+
return Err(errors::LDAPError::NativeError(CStr::from_ptr(raw_estr)
317+
.to_owned()
318+
.into_string()
319+
.unwrap()));
320+
}
321+
322+
Ok(res)
323+
}
324+
}
325+
273326
/// Advanced synchronous search.
274327
///
275328
/// Exposes a raw API around the underlying `ldap_search_ext_s` function from `OpenLDAP`.
@@ -483,6 +536,32 @@ mod tests {
483536

484537
}
485538

539+
#[test]
540+
fn test_simple_bind_with_start_tls() {
541+
let ldap = super::RustLDAP::new(TEST_ADDRESS).unwrap();
542+
543+
assert!(ldap.set_option(codes::options::LDAP_OPT_PROTOCOL_VERSION, &3));
544+
ldap.start_tls(None, None);
545+
546+
ldap.set_option(
547+
codes::options::LDAP_OPT_PROTOCOL_VERSION,
548+
&codes::versions::LDAP_VERSION3,
549+
);
550+
551+
ldap.set_option(
552+
codes::options::LDAP_OPT_X_TLS_REQUIRE_CERT,
553+
&codes::options::LDAP_OPT_X_TLS_ALLOW,
554+
);
555+
556+
ldap.set_option(codes::options::LDAP_OPT_X_TLS_NEWCTX, &0);
557+
558+
let res = ldap.simple_bind(TEST_BIND_DN, TEST_BIND_PASS).unwrap();
559+
assert_eq!(codes::results::LDAP_SUCCESS, res);
560+
println!("Bind result: {:?}", res);
561+
562+
}
563+
564+
486565
#[test]
487566
fn test_simple_search() {
488567

0 commit comments

Comments
 (0)