Python-ldap notes

From Helpful
Jump to navigation Jump to search
This article/section is a stub — some half-sorted notes, not necessarily checked, not necessarily correct. Feel free to ignore, or tell me about it.

The py-ldap (a.k.a. python-ldap) package is one of a few that allow interaction with LDAP servers. It mostly wraps OpenLDAP 2.

Note that the below generally assumes synchronous interaction (function names end with _s). (Asynchronous communication is done by using exceptions as messages)


Options

It is often simple to set options globally (ldap.set_option()), to be used by everything, since the common case probably connects to just one LDAP server.

Alternatively, you can set options per connection (connref.set_option())


You probably want to avoid indefinite blocking:

ldap.set_option(ldap.OPT_NETWORK_TIMEOUT, seconds) 

For connections to work with LDAPv3, you want to:

connref.set_option(ldap.OPT_PROTOCOL_VERSION, ldap.VERSION3)

or (verify)

connref.protocol_version = ldap.VERSION3

You should do this after initialize and before any interaction.


ActiveDirectory is somewhat quirky, and you probably need:

ldap.set_option(ldap.OPT_REFERRALS, 0)

Connecting

The deprecated alternative is to use open(), handing in a host and port.

The now preferred way is to hand in LDAP URLs (see RFC 4516) like:

ldapurl = 'ldap://ldap1.exmaple.com'
ldapurl = 'ldaps://localhost:389'


Which you hand in to initialize:

connref = ldap.initialize( ldapurl )

Note that initialize does not connect yet - the first function that needs the connection does(verify), often bind or start_tls , but possibly later such as search (e.g. in case the server is an entirely public store of information).

SSL

This article/section is a stub — some half-sorted notes, not necessarily checked, not necessarily correct. Feel free to ignore, or tell me about it.

Unless you can some how know/trust the network connection will never be snooped, you usually want a secure connection between LDAP client and server.

Note however that unless you can also know that all the parts between the place the user types the password and the the LDAP code are also secure, then securing the network connection does nothing for security. (Same goes for the server, but that's one central place under admin control - we're pointing out that the the client side often is not)

python-ldap supports TLS/SSL, apparently since 2.0.0pre06. (You want a version since then anyway, since LDAPv3 support was introduced about the same time) To test whether python-ldap was compiled with TLS support, look at the value of ldap.TLS_AVAIL.


One way to tell the module you want to use a secure connection is to hand in an ldap:// url and call start_tls_s() (after initialize(), and note this only works if you have already set VERSION3). This will raise an ldap.SERVER_DOWN exception if TLS fails.

Another way is to initialize using a https:// url. It seems that in this case you want to avoid calling start_tls_s().(verify)

Notes:

  • TLS-related options mostly control the conditions for a connection. The default is to be strict, which is a good idea so usually you don't need to touch them.
  • Hanging connections can be caused by trying non-secured connection on a secure-only port.
(i.e. using ldap: when you should use ldaps:)


For certificate verification, you want to point ldap.OPT_X_TLS_CERTFILE (TLS equivalent: TLS_CACERTFILE) to a file containing main/relevant certificates, or perhaps (TLS equivalent: TLS_CACERTDIR) (if you use it; if you haven't heard of c_rehash, you probably don't)

(You can ignore ldap.OPT_X_TLS_CERTFILE (TLS_CERTFILE) and ldap.OPT_X_TLS_KEYFILE (TLS_KEYFILE) unless you know you specifically want client authentication (instead of the more usual server authentification).)


The TLS equivalents of the following can be used in various areas:

  • OPT_X_TLS_NEVER
  • OPT_X_TLS_ALLOW
  • OPT_X_TLS_TRY
  • OPT_X_TLS_DEMAND
  • OPT_X_TLS_HARD
  • When you set them as if they were options and set them to 1:
    • OPT_X_TLS_TRY: Use TLS when available, but don't fail if it isn't.
    • OPT_X_TLS_DEMAND: Fail if TLS is not available


  • Also interesting is their use as values on ldap.OPT_X_TLS_REQUIRE_CERT (TLS equivalent: TLS_REQCERT)
    • demand and hard (default):
      • no certificate provided: quits
      • bad certificate provided: quits
    • try
      • no certificate provided: continues
      • bad certificate provided: quits
    • allow
      • no certificate provided: continues
      • bad certificate provided: continues
    • never
      • no certificate is requested


allow doesn't make too much sense (though this comes from a man page, not the module docs).

never is useful when a certificate cannot be authoritatively verified, e.g. in quick tests with self-signed test certificates.

Helpers

ldaphelper eases searching

Debugging

While debugging, the LDIFWriter may be convenient.

Also, you can see an on-screen trace by using

ldap.set_option(ldap.OPT_DEBUG_LEVEL,level)

(where level is e.g. 2 for basic details, or e.g. 255 for everything) Alternatively, use

trace_level=3, trace_file=sys.stderr)

Errors

This article/section is a stub — some half-sorted notes, not necessarily checked, not necessarily correct. Feel free to ignore, or tell me about it.

ldap.LDAPError is based on a plain Python exception (has an args member).

Depending on the exception/error/message(verify), it may also have a dictionary member called message with keys 'desc' (describing the basic error/message) and 'info' (lower-level details).


There are a number of subclasses of LDAPError meant for asynchronous interaction.


A SERVER_DOWN in the context of SSL/TLS points to a failture to establish a secure connection.

A PROTOCOL_ERROR mentioning 'Unrecognized extended operation' points to the attempt to use a function that the server/protocol does not support.


See also

Tutorials: