Controls

Many LDAP users may be unfamiliar with controls. RFC4511 defines controls as “providing a mechanism whereby the semantics and arguments of existing LDAP operations may be extended.” In other words, they can:

  1. Instruct the server to process a method differently
  2. Add new arguments to methods to control the altered processing
  3. Add additional data to the response to a method call

It is important to note that both the server and client must mutually support all controls used. Laurelin will automatically check for server support when using controls.

Using Controls

Once controls have been defined, they are very easy to use. Each control has a keyword and optionally a response_attr.

The keyword can be passed as a keyword argument to specific methods. The value type and format is up to the control implementation. Whatever value the control expects can be wrapped in critical or optional to declare the criticality of the control.

If defined, the response_attr will be set as an attribute on the object returned from the method call.

For search response controls, the control value will be set on the individual LDAPObject if it appeared on the associated search result entry. If it appeared on the search results done message, the control value will be set on the iterator object.

In the highly unusual case that a response control is set on a search result reference message, the control values will be inaccessible if fetch_result_refs is set to True. A warning will be issued in this case.

If fetch_result_refs is set to False, the response control values will be set on the SearchReferenceHandle that is yielded from the results iterator.

class laurelin.ldap.critical(value)[source]

Bases: object

used to mark controls with criticality

class laurelin.ldap.optional(value)[source]

Bases: object

used to mark controls as not having criticality

An LDAPSupportError will be raised if the control is marked critical and the server does not support it.

Defining Controls

Controls must subclass Control. As soon as they are defined as a subclass of Control, they are ready to use. Controls must define at least:

  • Control.method, a tuple of method names that this control supports. Current method names are bind, search, compare, add, delete, mod_dn, modify, and ext (extended request). Note that these method names do not necessarily correspond directly to LDAP method names. Even when they do, other methods may call the base method and pass through control keywords. For example, LDAPObject.find() ends up passing any control keywords through into LDAP.search() (which matches the search method). The bind method is used by both LDAP.simple_bind() and LDAP.sasl_bind().
  • Control.keyword, the keyword argument to be used for the request control.
  • Control.REQUEST_OID the OID of the reuqest control. If the control has criticality, the OID must be listed in the supportedControl attribute of the root DSE of the server at runtime.

If there is an associated response control, also define the following:

Most controls will not need to override methods if only strings are used for request and response values. However, if it is desirable to use a more complex data structure as a control value, you can override the Control.prepare() method to accept this structure as its first argument. You will need to process this into a single string for transmission to the server, and pass it into, and return, the base Control.prepare(). The second argument is a boolean describing criticality, and must also be passed into the base method.

To return a more complex value for the response, you can override the Control.handle() method. This will be passed the response control value string, and the return will be assigned to the response_attr attribute on the returned object.

class laurelin.ldap.controls.Control[source]

Bases: object

Request controls are exposed by allowing an additional keyword argument on a set of methods. The prepare() method takes the value passed in as a keyword argument and returns an rfc4511.Control.

Response controls are returned by setting an additional attribute on whichever object is returned by the called method. The raw response controlValue is passed to the handle() method, and any appropriate value may be returned.

Leave the RESPONSE_OID and response_attr attributes as a False value if there is no response control specified.

REQUEST_OID = ''

Request OID of the control

RESPONSE_OID = ''

Response OID of the control (may be equal to REQUEST_OID; may be left empty)

handle(ctrl_value)[source]

Accepts raw response ctrl_value and may return any useful value.

There is no need to call this base function when overriding.

Parameters:ctrl_value (str) – The string response control value received from the server.
Returns:The string ctrl_value unchanged by default. May be overridden to return any relevant value/type/structure.
keyword = ''

keyword argument name

method = ()

name(s) of the method which this control is used with

prepare(ctrl_value, criticality)[source]

Accepts string controlValue and returns an rfc4511.Control instance

When overriding this function, you must always call and return this base function.

Parameters:
  • ctrl_value (str or bytes) – The string request control value to send to the server
  • criticality (bool) – True if the control has criticality. This is indicated by wrapping the keyword argument in critical or optional, and by the default_criticality keyword passed to the LDAP constructor, and global default LDAP.DEFAULT_CRITICALITY.
Returns:

The protocol-level control object ready for transmission to the server

Return type:

rfc4511.Control

response_attr = ''

Name of the attribute where return of handle() will be stored