inejge / ldap3

A pure-Rust LDAP library using the Tokio stack
Apache License 2.0
220 stars 38 forks source link

Example of connection to TLS-enabled LDAP server #14

Closed pwrdwnsys closed 7 years ago

pwrdwnsys commented 7 years ago

Is it possible to have an example of connecting to LDAPS? I've used v0.5.0 on crates.io and I'm struggling to find the correct way to build the connection. Thanks.

inejge commented 7 years ago

To solve your immediate problem first, a TLS connection is requested by using the ldaps scheme in the URL passed to LdapConn::new(). E.g., if your server is at ldap.example.org and accepting TLS requests at port 636/tcp, you'd have something like

let ldap = LdapConn::new("ldaps://ldap.example.org")?;

As for documenting this more explicitly, there are a couple of candidate places. Would you consider the docs for LdapConn::new() a good match? (Actually, TLS is implicitly documented for LdapConnAsync::new(). You'd need to be familiar with LDAP URLs to know this, though.)

pwrdwnsys commented 7 years ago

Thank you @inejge - that appears to have created a connection, but now the simple_bind which follows it generates a "broken pipe" - this does not happen on the plain ldap:// connection.

let ldap = LdapConn::new(LDAP_SERVER)?;
trace!("Binding to LDAP server with {}", LDAP_SERVICE_USER_DN);
ldap.simple_bind(LDAP_SERVICE_USER_DN, LDAP_SERVICE_USER_PW)?.success()?;
trace!("Bind completed.");

results in

TRACE:ldapdemo: Binding to LDAP server with CN=demouser,CN=Users,DC=demo,DC=example,DC=com
broken pipe

From the same system I have been able to successfully bind against the server's TLS connection using JXplorer, and the domain matches the certificate.

inejge commented 7 years ago

The "broken pipe" sounds like an OS-level error, e.g., an attempt to read a closed connection. To get a better idea what's happening, change the program to something like:

let ldap = LdapConn::new(LDAP_SERVER).expect("handle");
ldap.simple_bind(LDAP_SERVICE_USER_DN, LDAP_SERVICE_USER_PW).expect("bind");

Run it with RUST_BACKTRACE=1 set in the environment, maybe also RUST_LOG=tokio=trace.

It would also help a) to know what kind of server are you connecting to, b) to have the most detailed server logs possible.

pwrdwnsys commented 7 years ago

Thank you very much - this identified the problem. I ran RUST_BACKTRACE=1 RUST_LOG=tokio=trace cargo run which reported "The trust policy was not trusted." Another user had encountered this with native-tls on macOS, originating from with libsecurity-keychain when the root CA certificate was missing or incorrectly configured. I had imported my CA certificate incorrectly - removing it from Keychain and re-installing it fixed the problem. Debug and trace is copied below.

Is there a way to expose this tokio error to users of my application?

DEBUG:tokio_core::reactor: loop time - Instant { t: 91258213539826 }
TRACE:tokio_core::reactor: event Ready {Readable} Token(3)
DEBUG:tokio_core::reactor: consuming notification queue
DEBUG:tokio_core::reactor: dropping I/O source: 0
DEBUG:tokio_proto::streaming::multiplex::client: multiplex task failed with error; err=Error { repr: Custom(Custom { kind: Other, error: Error { code: -67843, message: "The trust policy was not trusted." } }) }
DEBUG:tokio_core::reactor: loop process - 1 events, Duration { secs: 0, nanos: 29479183 }
DEBUG:tokio_core::reactor: loop poll - Duration { secs: 0, nanos: 17387 }
DEBUG:tokio_core::reactor: loop time - Instant { t: 91258243048144 }
TRACE:tokio_core::reactor: event Ready {Readable} Token(1)
DEBUG:tokio_core::reactor: loop process - 1 events, Duration { secs: 0, nanos: 16236 }
thread 'main' panicked at 'bind: Error { repr: Custom(Custom { kind: BrokenPipe, error: StringError("broken pipe") }) }', src/libcore/result.rs:860:4
stack backtrace:
   0: std::sys::imp::backtrace::tracing::imp::unwind_backtrace
   1: std::panicking::default_hook::{{closure}}
   2: std::panicking::default_hook
   3: std::panicking::rust_panic_with_hook
   4: std::panicking::begin_panic
   5: std::panicking::begin_panic_fmt
   6: rust_begin_unwind
   7: core::panicking::panic_fmt
   8: core::result::unwrap_failed
   9: <core::result::Result<T, E>>::expect
  10: ldapdemo::do_search
  11: ldapdemo::main
  12: __rust_maybe_catch_panic
  13: std::rt::lang_start
  14: main
inejge commented 7 years ago

removing [the root CA] from Keychain and re-installing it fixed the problem.

Excellent!

Is there a way to expose this tokio error to users of my application?

I don't think there is, presently. Handling this kind of error is one of tokio-proto's architectural loose ends, see the place in the code where it happens.

inejge commented 7 years ago

Version 0.5.1 has just been published, with a TLS example from #15, so I'm going to close this.