# &develguide;

## Overview

The LDAP module API can be used by other &kamailio; modules to implement LDAP search functionality. This frees the module implementer from having to care about LDAP connection management and configuration.

In order to use this API, a module has to load the API using the `load_ldap_api` function which returns a pointer to a `ldap_api` structure. This structure includes pointers to the API functions described below. The LDAP module source file `api.h` includes all declarations needed to load the API, it has to be included in the file that use the API. Loading the API is typically done inside a module's `mod_init` call as the following example shows:

### Example code fragment to load LDAP module API

    #include "../../sr_module.h"
    #include "../ldap/api.h"

    /*
     * global pointer to ldap api
     */
    extern ldap_api_t ldap_api;

    ...

    static int mod_init(void)
    {
        /*
         * load the LDAP API
         */
        if (load_ldap_api(&ldap_api) != 0)
        {
            LM_ERR("Unable to load LDAP API - this module requires ldap module\n");
            return -1;
        }

        ...
    }

    ...

The API functions can then be used like in the following example:

### Example LDAP module API function call

    ...

        rc = ldap_api.ldap_rfc4515_escape(str1, str2, 0);

    ...

## API Functions

### ldap_params_search

Performs an LDAP search using the parameters given as function arguments.

    typedef int (*ldap_params_search_t)(int* _ld_result_count,
                                        char* _lds_name,
                                        char* _dn,
                                        int _scope,
                                        char** _attrs,
                                        char* _filter,
                                        ...);

### Function arguments:

int* _ld_result_count

- The function stores the number of returned LDAP entries in `_ld_result_count`.

char* _lds_name

- LDAP session name as configured in the LDAP module configuration file.

char* _dn

- LDAP search DN.

int _scope

- LDAP search scope, one of `LDAP_SCOPE_ONELEVEL`, `LDAP_SCOPE_BASE`, or `LDAP_SCOPE_SUBTREE`, as defined in OpenLDAP's `ldap.h`.

char** _attrs

- A null-terminated array of attribute types to return from entries. If empty (`NULL`), all attribute types are returned.

char* _filter

- LDAP search filter string according to RFC 4515. `printf` patterns in this string do get replaced with the function arguments' values following the `_filter` argument.

### Return Values:

-1

- Internal error.

0

- Success, `_ld_result_count` includes the number of LDAP entries found.

### ldap_url_search

Performs an LDAP search using an LDAP URL.

    typedef int (*ldap_url_search_t)(char* _ldap_url,
                                     int* _result_count);

### Function arguments:

char* _ldap_url

- LDAP URL as described in ldap-urls.

int* _result_count

- The function stores the number of returned LDAP entries in `_ld_result_count`.

### Return Values:

-1

- Internal error.

0

- Success, `_ld_result_count` includes the number of LDAP entries found.

### ldap_result_attr_vals

Retrieve the value(s) of a returned LDAP attribute. The function accesses the LDAP result returned by the last call of `ldap_params_search` or `ldap_url_search`. The `berval` structure is defined in OpenLDAP's `ldap.h`, which has to be included.

This function allocates memory to store the LDAP attribute value(s). This memory has to freed with the function `ldap_value_free_len` (see next section).

    typedef int (*ldap_result_attr_vals_t)(str* _attr_name,
                                           struct berval ***_vals);

    typedef struct berval {
            ber_len_t       bv_len;
            char            *bv_val;
    } BerValue;

### Function arguments:

str* _attr_name

- `str` structure holding the LDAP attribute name.

struct berval ***_vals

- A null-terminated array of the attribute's value(s).

### Return Values:

-1

- Internal error.

0

- Success, `_vals` includes the attribute's value(s).

1

- No attribute value found.

### ldap_value_free_len

Function used to free memory allocated by `ldap_result_attr_vals`. The `berval` structure is defined in OpenLDAP's `ldap.h`, which has to be included.

    typedef void (*ldap_value_free_len_t)(struct berval **_vals);

    typedef struct berval {
            ber_len_t       bv_len;
            char            *bv_val;
    } BerValue;

### Function arguments:

struct berval **_vals

- `berval` array returned by `ldap_result_attr_vals`.

### ldap_result_next

Increments the LDAP result pointer.

    typedef int (*ldap_result_next_t)();

### Return Values:

-1

- No LDAP result found, probably because `ldap_params_search` or `ldap_url_search` was not called.

0

- Success, LDAP result pointer points now to next result.

1

- No more results available.

### ldap_str2scope

Converts LDAP search scope string into integer value e.g. for `ldap_params_search`.

    typedef int (*ldap_str2scope_t)(char* scope_str);

### Function arguments:

char* scope_str

- LDAP search scope string. One of "one", "onelevel", "base", "sub", or "subtree".

### Return Values:

-1

- `scope_str` not recognized.

n >= 0

- LDAP search scope integer.

### ldap_rfc4515_escape

Applies escaping rules described in ldap-filter-url-encode-fn.

    typedef int (*ldap_rfc4515_escape_t)(str *sin, str *sout, int url_encode);

### Function arguments:

str *sin

- `str` structure holding the string to apply the escaping rules.

str *sout

- `str` structure holding the escaped string. The length of this string must be at least three times the length of `sin` plus one.

int url_encode

- Flag that specifies if a '?' character gets escaped with '%3F' or not. If `url_encode` equals `0`, '?' does not get escaped.

### Return Values:

-1

- Internal error.

0

- Success, `sout` contains escaped string.

### get_ldap_handle

Returns the OpenLDAP LDAP handle for a specific LDAP session. This allows a module implementor to use the OpenLDAP API functions directly, instead of using the API functions exported by the &kamailio; LDAP module. The `LDAP` structure is defined in OpenLDAP's `ldap.h`, which has to be included.

    typedef int (*get_ldap_handle_t)(char* _lds_name, LDAP** _ldap_handle);

### Function arguments:

char* _lds_name

- LDAP session name as specified in the LDAP module configuration file.

LDAP** _ldap_handle

- OpenLDAP LDAP handle returned by this function.

### Return Values:

-1

- Internal error.

0

- Success, `_ldap_handle` contains the OpenLDAP LDAP handle.

### get_last_ldap_result

Returns the OpenLDAP LDAP handle and OpenLDAP result handle of the last LDAP search operation. These handles can be used as input for OpenLDAP LDAP result API functions. `LDAP` and `LDAPMessage` structures are defined in OpenLDAP's `ldap.h`, which has to be included.

    typedef void (*get_last_ldap_result_t)
    	     (LDAP** _last_ldap_handle, LDAPMessage** _last_ldap_result);

### Function arguments:

LDAP** _last_ldap_handle

- OpenLDAP LDAP handle returned by this function.

LDAPMessage** _last_ldap_result

- OpenLDAP result handle returned by this function.

## Example Usage

The following example shows how this API can be used to perform an LDAP search operation. It is assumed that the API is loaded and available through the `ldap_api` pointer.

    ...

    int rc, ld_result_count, scope = 0;
    char* sip_username = "test";

    /*
     * get LDAP search scope integer
     */
    scope = ldap_api.ldap_str2scope("sub");
    if (scope == -1)
    {
        LM_ERR("ldap_str2scope failed\n");
        return -1;
    }

    /*
     * perform LDAP search
     */

    if (ldap_api.ldap_params_search(
           &ld_result_count,
           "campus",
           "dc=example,dc=com",
           scope,
           NULL,
           "(&(objectClass=SIPIdentity)(SIPIdentityUserName=%s))",
           sip_username)
         != 0)
    {
        LM_ERR("LDAP search failed\n");
        return -1;
    }

    /*
     * check result count
     */
    if (ld_result_count < 1)
    {
        LM_ERR("LDAP search returned no entry\n");
        return 1;
    }

    /*
     * get password attribute value
     */

    struct berval **attr_vals = NULL;
    str ldap_pwd_attr_name = str_init("SIPIdentityPassword");
    str res_password;

    rc = ldap_api.ldap_result_attr_vals(&ldap_pwd_attr_name, &attr_vals);
    if (rc < 0)
    {
        LM_ERR("ldap_result_attr_vals failed\n");
        ldap_api.ldap_value_free_len(attr_vals);
        return -1;
    }
    if (rc == 1)
    {
        LM_INFO("No password attribute value found for [%s]\n", sip_username);
        ldap_api.ldap_value_free_len(attr_vals);
        return 2;
    }

    res_password.s = attr_vals[0]->bv_val;
    res_password.len = attr_vals[0]->bv_len;

    ldap_api.ldap_value_free_len(attr_vals);

    LM_INFO("Password for user [%s]: [%s]\n", sip_username, res_password.s);

    ...

    return 0;