You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kamailio/modules/ldap/doc/ldap_devel.xml

633 lines
16 KiB

<?xml version="1.0" encoding='ISO-8859-1'?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
<!-- Include general documentation entities -->
<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
%docentities;
]>
<!-- LDAP_H350 Module Developer's Guide -->
<chapter>
<title>&develguide;</title>
<section>
<title>Overview</title>
<para>
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.
</para>
<para>
In order to use this API, a module has to load the API using the <varname>load_ldap_api</varname>
function which returns a pointer to a <varname>ldap_api</varname> structure. This structure
includes pointers to the API functions described below. The LDAP module source file
<varname>api.h</varname> 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 <varname>mod_init</varname> call as the following example shows:
<example>
<title>Example code fragment to load LDAP module API</title>
<programlisting><![CDATA[
#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;
}
...
}
...
]]>
</programlisting>
</example>
</para>
<para>
The API functions can then be used like in the following example:
<example>
<title>Example LDAP module API function call</title>
<programlisting><![CDATA[
...
rc = ldap_api.ldap_rfc4515_escape(str1, str2, 0);
...
]]>
</programlisting>
</example>
</para>
</section>
<section>
<title>API Functions</title>
<section>
<title>ldap_params_search</title>
<para>
Performs an LDAP search using the parameters given as function arguments.
</para>
<programlisting><![CDATA[
typedef int (*ldap_params_search_t)(int* _ld_result_count,
char* _lds_name,
char* _dn,
int _scope,
char** _attrs,
char* _filter,
...);
]]>
</programlisting>
<variablelist>
<title>Function arguments:</title>
<varlistentry>
<term>int* _ld_result_count</term>
<listitem>
<para>
The function stores the number of returned LDAP entries
in <varname>_ld_result_count</varname>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>char* _lds_name</term>
<listitem>
<para>
LDAP session name as configured in the LDAP
module configuration file.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>char* _dn</term>
<listitem>
<para>
LDAP search DN.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>int _scope</term>
<listitem>
<para>
LDAP search scope, one of <varname>LDAP_SCOPE_ONELEVEL</varname>,
<varname>LDAP_SCOPE_BASE</varname>, or <varname>LDAP_SCOPE_SUBTREE</varname>,
as defined in OpenLDAP's <varname>ldap.h</varname>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>char** _attrs</term>
<listitem>
<para>
A null-terminated array of attribute types to return from entries.
If empty (<varname>NULL</varname>), all attribute types are returned.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>char* _filter</term>
<listitem>
<para>
LDAP search filter string according to RFC 4515.
<varname>printf</varname> patterns in this string do get replaced with
the function arguments' values following the <varname>_filter</varname> argument.
</para>
</listitem>
</varlistentry>
</variablelist>
<variablelist>
<title>Return Values:</title>
<varlistentry>
<term>-1</term>
<listitem>
<para>
Internal error.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>0</term>
<listitem>
<para>
Success, <varname>_ld_result_count</varname> includes the number of LDAP entries found.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section>
<title>ldap_url_search</title>
<para>
Performs an LDAP search using an LDAP URL.
</para>
<programlisting><![CDATA[
typedef int (*ldap_url_search_t)(char* _ldap_url,
int* _result_count);
]]>
</programlisting>
<variablelist>
<title>Function arguments:</title>
<varlistentry>
<term>char* _ldap_url</term>
<listitem>
<para>
LDAP URL as described in <xref linkend="ldap-urls" />.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>int* _result_count</term>
<listitem>
<para>
The function stores the number of returned LDAP entries in <varname>_ld_result_count</varname>.
</para>
</listitem>
</varlistentry>
</variablelist>
<variablelist>
<title>Return Values:</title>
<varlistentry>
<term>-1</term>
<listitem>
<para>
Internal error.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>0</term>
<listitem>
<para>
Success, <varname>_ld_result_count</varname> includes the number of LDAP entries found.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section>
<title>ldap_result_attr_vals</title>
<para>
Retrieve the value(s) of a returned LDAP attribute. The function accesses
the LDAP result returned by the last call of <varname>ldap_params_search</varname>
or <varname>ldap_url_search</varname>. The <varname>berval</varname> structure is
defined in OpenLDAP's <varname>ldap.h</varname>, which has to be included.
</para>
<para>
This function allocates memory to store the LDAP attribute value(s). This memory
has to freed with the function <varname>ldap_value_free_len</varname> (see next section).
</para>
<programlisting><![CDATA[
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;
]]>
</programlisting>
<variablelist>
<title>Function arguments:</title>
<varlistentry>
<term>str* _attr_name</term>
<listitem>
<para>
<varname>str</varname> structure holding the LDAP attribute name.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>struct berval ***_vals</term>
<listitem>
<para>
A null-terminated array of the attribute's value(s).
</para>
</listitem>
</varlistentry>
</variablelist>
<variablelist>
<title>Return Values:</title>
<varlistentry>
<term>-1</term>
<listitem>
<para>
Internal error.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>0</term>
<listitem>
<para>
Success, <varname>_vals</varname> includes the attribute's value(s).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>1</term>
<listitem>
<para>
No attribute value found.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section>
<title>ldap_value_free_len</title>
<para>
Function used to free memory allocated by <varname>ldap_result_attr_vals</varname>.
The <varname>berval</varname> structure is defined in OpenLDAP's
<varname>ldap.h</varname>, which has to be included.
</para>
<programlisting><![CDATA[
typedef void (*ldap_value_free_len_t)(struct berval **_vals);
typedef struct berval {
ber_len_t bv_len;
char *bv_val;
} BerValue;
]]>
</programlisting>
<variablelist>
<title>Function arguments:</title>
<varlistentry>
<term>struct berval **_vals</term>
<listitem>
<para>
<varname>berval</varname> array returned by <varname>ldap_result_attr_vals</varname>.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section>
<title>ldap_result_next</title>
<para>
Increments the LDAP result pointer.
</para>
<programlisting><![CDATA[
typedef int (*ldap_result_next_t)();
]]>
</programlisting>
<variablelist>
<title>Return Values:</title>
<varlistentry>
<term>-1</term>
<listitem>
<para>
No LDAP result found, probably because <varname>ldap_params_search</varname>
or <varname>ldap_url_search</varname> was not called.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>0</term>
<listitem>
<para>
Success, LDAP result pointer points now to next result.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>1</term>
<listitem>
<para>
No more results available.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section>
<title>ldap_str2scope</title>
<para>
Converts LDAP search scope string into integer value e.g. for <varname>ldap_params_search</varname>.
</para>
<programlisting><![CDATA[
typedef int (*ldap_str2scope_t)(char* scope_str);
]]>
</programlisting>
<variablelist>
<title>Function arguments:</title>
<varlistentry>
<term>char* scope_str</term>
<listitem>
<para>
LDAP search scope string. One of "one", "onelevel", "base", "sub", or "subtree".
</para>
</listitem>
</varlistentry>
</variablelist>
<variablelist>
<title>Return Values:</title>
<varlistentry>
<term>-1</term>
<listitem>
<para>
<varname>scope_str</varname> not recognized.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>n &gt;= 0</term>
<listitem>
<para>
LDAP search scope integer.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section>
<title>ldap_rfc4515_escape</title>
<para>
Applies escaping rules described in <xref linkend="ldap-filter-url-encode-fn" />.
</para>
<programlisting><![CDATA[
typedef int (*ldap_rfc4515_escape_t)(str *sin, str *sout, int url_encode);
]]>
</programlisting>
<variablelist>
<title>Function arguments:</title>
<varlistentry>
<term>str *sin</term>
<listitem>
<para>
<varname>str</varname> structure holding the string to apply the escaping rules.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>str *sout</term>
<listitem>
<para>
<varname>str</varname> structure holding the escaped string. The length of this string must be at least three times the length of <varname>sin</varname> plus one.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>int url_encode</term>
<listitem>
<para>
Flag that specifies if a '?' character gets escaped with '%3F' or not. If <varname>url_encode</varname> equals <varname>0</varname>, '?' does not get escaped.
</para>
</listitem>
</varlistentry>
</variablelist>
<variablelist>
<title>Return Values:</title>
<varlistentry>
<term>-1</term>
<listitem>
<para>
Internal error.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>0</term>
<listitem>
<para>
Success, <varname>sout</varname> contains escaped string.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section>
<title>get_ldap_handle</title>
<para>
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 <varname>LDAP</varname> structure
is defined in OpenLDAP's <varname>ldap.h</varname>, which has to be included.
</para>
<programlisting><![CDATA[
typedef int (*get_ldap_handle_t)(char* _lds_name, LDAP** _ldap_handle);
]]>
</programlisting>
<variablelist>
<title>Function arguments:</title>
<varlistentry>
<term>char* _lds_name</term>
<listitem>
<para>
LDAP session name as specified in the LDAP module configuration file.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>LDAP** _ldap_handle</term>
<listitem>
<para>
OpenLDAP LDAP handle returned by this function.
</para>
</listitem>
</varlistentry>
</variablelist>
<variablelist>
<title>Return Values:</title>
<varlistentry>
<term>-1</term>
<listitem>
<para>
Internal error.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>0</term>
<listitem>
<para>
Success, <varname>_ldap_handle</varname> contains the OpenLDAP LDAP handle.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section>
<title>get_last_ldap_result</title>
<para>
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.
<varname>LDAP</varname> and <varname>LDAPMessage</varname> structures are defined in
OpenLDAP's <varname>ldap.h</varname>, which has to be included.
</para>
<programlisting><![CDATA[
typedef void (*get_last_ldap_result_t)
(LDAP** _last_ldap_handle, LDAPMessage** _last_ldap_result);
]]>
</programlisting>
<variablelist>
<title>Function arguments:</title>
<varlistentry>
<term>LDAP** _last_ldap_handle</term>
<listitem>
<para>
OpenLDAP LDAP handle returned by this function.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>LDAPMessage** _last_ldap_result</term>
<listitem>
<para>
OpenLDAP result handle returned by this function.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
</section>
<section>
<title>Example Usage</title>
<para>
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 <varname>ldap_api</varname> pointer.
</para>
<programlisting><![CDATA[
...
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;
]]>
</programlisting>
</section>
</chapter>