ldap_devel.xml 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. <?xml version="1.0" encoding='ISO-8859-1'?>
  2. <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
  3. "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
  4. <!-- Include general documentation entities -->
  5. <!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
  6. %docentities;
  7. ]>
  8. <!-- LDAP_H350 Module Developer's Guide -->
  9. <chapter>
  10. <title>&develguide;</title>
  11. <section>
  12. <title>Overview</title>
  13. <para>
  14. The LDAP module API can be used by other &kamailio; modules to implement
  15. LDAP search functionality. This frees the module implementer from having
  16. to care about LDAP connection management and configuration.
  17. </para>
  18. <para>
  19. In order to use this API, a module has to load the API using the <varname>load_ldap_api</varname>
  20. function which returns a pointer to a <varname>ldap_api</varname> structure. This structure
  21. includes pointers to the API functions described below. The LDAP module source file
  22. <varname>api.h</varname> includes all declarations needed to load the API, it has to
  23. be included in the file that use the API. Loading the API is typically done inside a
  24. module's <varname>mod_init</varname> call as the following example shows:
  25. <example>
  26. <title>Example code fragment to load LDAP module API</title>
  27. <programlisting><![CDATA[
  28. #include "../../sr_module.h"
  29. #include "../ldap/api.h"
  30. /*
  31. * global pointer to ldap api
  32. */
  33. extern ldap_api_t ldap_api;
  34. ...
  35. static int mod_init(void)
  36. {
  37. /*
  38. * load the LDAP API
  39. */
  40. if (load_ldap_api(&ldap_api) != 0)
  41. {
  42. LM_ERR("Unable to load LDAP API - this module requires ldap module\n");
  43. return -1;
  44. }
  45. ...
  46. }
  47. ...
  48. ]]>
  49. </programlisting>
  50. </example>
  51. </para>
  52. <para>
  53. The API functions can then be used like in the following example:
  54. <example>
  55. <title>Example LDAP module API function call</title>
  56. <programlisting><![CDATA[
  57. ...
  58. rc = ldap_api.ldap_rfc4515_escape(str1, str2, 0);
  59. ...
  60. ]]>
  61. </programlisting>
  62. </example>
  63. </para>
  64. </section>
  65. <section>
  66. <title>API Functions</title>
  67. <section>
  68. <title>ldap_params_search</title>
  69. <para>
  70. Performs an LDAP search using the parameters given as function arguments.
  71. </para>
  72. <programlisting><![CDATA[
  73. typedef int (*ldap_params_search_t)(int* _ld_result_count,
  74. char* _lds_name,
  75. char* _dn,
  76. int _scope,
  77. char** _attrs,
  78. char* _filter,
  79. ...);
  80. ]]>
  81. </programlisting>
  82. <variablelist>
  83. <title>Function arguments:</title>
  84. <varlistentry>
  85. <term>int* _ld_result_count</term>
  86. <listitem>
  87. <para>
  88. The function stores the number of returned LDAP entries
  89. in <varname>_ld_result_count</varname>.
  90. </para>
  91. </listitem>
  92. </varlistentry>
  93. <varlistentry>
  94. <term>char* _lds_name</term>
  95. <listitem>
  96. <para>
  97. LDAP session name as configured in the LDAP
  98. module configuration file.
  99. </para>
  100. </listitem>
  101. </varlistentry>
  102. <varlistentry>
  103. <term>char* _dn</term>
  104. <listitem>
  105. <para>
  106. LDAP search DN.
  107. </para>
  108. </listitem>
  109. </varlistentry>
  110. <varlistentry>
  111. <term>int _scope</term>
  112. <listitem>
  113. <para>
  114. LDAP search scope, one of <varname>LDAP_SCOPE_ONELEVEL</varname>,
  115. <varname>LDAP_SCOPE_BASE</varname>, or <varname>LDAP_SCOPE_SUBTREE</varname>,
  116. as defined in OpenLDAP's <varname>ldap.h</varname>.
  117. </para>
  118. </listitem>
  119. </varlistentry>
  120. <varlistentry>
  121. <term>char** _attrs</term>
  122. <listitem>
  123. <para>
  124. A null-terminated array of attribute types to return from entries.
  125. If empty (<varname>NULL</varname>), all attribute types are returned.
  126. </para>
  127. </listitem>
  128. </varlistentry>
  129. <varlistentry>
  130. <term>char* _filter</term>
  131. <listitem>
  132. <para>
  133. LDAP search filter string according to RFC 4515.
  134. <varname>printf</varname> patterns in this string do get replaced with
  135. the function arguments' values following the <varname>_filter</varname> argument.
  136. </para>
  137. </listitem>
  138. </varlistentry>
  139. </variablelist>
  140. <variablelist>
  141. <title>Return Values:</title>
  142. <varlistentry>
  143. <term>-1</term>
  144. <listitem>
  145. <para>
  146. Internal error.
  147. </para>
  148. </listitem>
  149. </varlistentry>
  150. <varlistentry>
  151. <term>0</term>
  152. <listitem>
  153. <para>
  154. Success, <varname>_ld_result_count</varname> includes the number of LDAP entries found.
  155. </para>
  156. </listitem>
  157. </varlistentry>
  158. </variablelist>
  159. </section>
  160. <section>
  161. <title>ldap_url_search</title>
  162. <para>
  163. Performs an LDAP search using an LDAP URL.
  164. </para>
  165. <programlisting><![CDATA[
  166. typedef int (*ldap_url_search_t)(char* _ldap_url,
  167. int* _result_count);
  168. ]]>
  169. </programlisting>
  170. <variablelist>
  171. <title>Function arguments:</title>
  172. <varlistentry>
  173. <term>char* _ldap_url</term>
  174. <listitem>
  175. <para>
  176. LDAP URL as described in <xref linkend="ldap-urls" />.
  177. </para>
  178. </listitem>
  179. </varlistentry>
  180. <varlistentry>
  181. <term>int* _result_count</term>
  182. <listitem>
  183. <para>
  184. The function stores the number of returned LDAP entries in <varname>_ld_result_count</varname>.
  185. </para>
  186. </listitem>
  187. </varlistentry>
  188. </variablelist>
  189. <variablelist>
  190. <title>Return Values:</title>
  191. <varlistentry>
  192. <term>-1</term>
  193. <listitem>
  194. <para>
  195. Internal error.
  196. </para>
  197. </listitem>
  198. </varlistentry>
  199. <varlistentry>
  200. <term>0</term>
  201. <listitem>
  202. <para>
  203. Success, <varname>_ld_result_count</varname> includes the number of LDAP entries found.
  204. </para>
  205. </listitem>
  206. </varlistentry>
  207. </variablelist>
  208. </section>
  209. <section>
  210. <title>ldap_result_attr_vals</title>
  211. <para>
  212. Retrieve the value(s) of a returned LDAP attribute. The function accesses
  213. the LDAP result returned by the last call of <varname>ldap_params_search</varname>
  214. or <varname>ldap_url_search</varname>. The <varname>berval</varname> structure is
  215. defined in OpenLDAP's <varname>ldap.h</varname>, which has to be included.
  216. </para>
  217. <para>
  218. This function allocates memory to store the LDAP attribute value(s). This memory
  219. has to freed with the function <varname>ldap_value_free_len</varname> (see next section).
  220. </para>
  221. <programlisting><![CDATA[
  222. typedef int (*ldap_result_attr_vals_t)(str* _attr_name,
  223. struct berval ***_vals);
  224. typedef struct berval {
  225. ber_len_t bv_len;
  226. char *bv_val;
  227. } BerValue;
  228. ]]>
  229. </programlisting>
  230. <variablelist>
  231. <title>Function arguments:</title>
  232. <varlistentry>
  233. <term>str* _attr_name</term>
  234. <listitem>
  235. <para>
  236. <varname>str</varname> structure holding the LDAP attribute name.
  237. </para>
  238. </listitem>
  239. </varlistentry>
  240. <varlistentry>
  241. <term>struct berval ***_vals</term>
  242. <listitem>
  243. <para>
  244. A null-terminated array of the attribute's value(s).
  245. </para>
  246. </listitem>
  247. </varlistentry>
  248. </variablelist>
  249. <variablelist>
  250. <title>Return Values:</title>
  251. <varlistentry>
  252. <term>-1</term>
  253. <listitem>
  254. <para>
  255. Internal error.
  256. </para>
  257. </listitem>
  258. </varlistentry>
  259. <varlistentry>
  260. <term>0</term>
  261. <listitem>
  262. <para>
  263. Success, <varname>_vals</varname> includes the attribute's value(s).
  264. </para>
  265. </listitem>
  266. </varlistentry>
  267. <varlistentry>
  268. <term>1</term>
  269. <listitem>
  270. <para>
  271. No attribute value found.
  272. </para>
  273. </listitem>
  274. </varlistentry>
  275. </variablelist>
  276. </section>
  277. <section>
  278. <title>ldap_value_free_len</title>
  279. <para>
  280. Function used to free memory allocated by <varname>ldap_result_attr_vals</varname>.
  281. The <varname>berval</varname> structure is defined in OpenLDAP's
  282. <varname>ldap.h</varname>, which has to be included.
  283. </para>
  284. <programlisting><![CDATA[
  285. typedef void (*ldap_value_free_len_t)(struct berval **_vals);
  286. typedef struct berval {
  287. ber_len_t bv_len;
  288. char *bv_val;
  289. } BerValue;
  290. ]]>
  291. </programlisting>
  292. <variablelist>
  293. <title>Function arguments:</title>
  294. <varlistentry>
  295. <term>struct berval **_vals</term>
  296. <listitem>
  297. <para>
  298. <varname>berval</varname> array returned by <varname>ldap_result_attr_vals</varname>.
  299. </para>
  300. </listitem>
  301. </varlistentry>
  302. </variablelist>
  303. </section>
  304. <section>
  305. <title>ldap_result_next</title>
  306. <para>
  307. Increments the LDAP result pointer.
  308. </para>
  309. <programlisting><![CDATA[
  310. typedef int (*ldap_result_next_t)();
  311. ]]>
  312. </programlisting>
  313. <variablelist>
  314. <title>Return Values:</title>
  315. <varlistentry>
  316. <term>-1</term>
  317. <listitem>
  318. <para>
  319. No LDAP result found, probably because <varname>ldap_params_search</varname>
  320. or <varname>ldap_url_search</varname> was not called.
  321. </para>
  322. </listitem>
  323. </varlistentry>
  324. <varlistentry>
  325. <term>0</term>
  326. <listitem>
  327. <para>
  328. Success, LDAP result pointer points now to next result.
  329. </para>
  330. </listitem>
  331. </varlistentry>
  332. <varlistentry>
  333. <term>1</term>
  334. <listitem>
  335. <para>
  336. No more results available.
  337. </para>
  338. </listitem>
  339. </varlistentry>
  340. </variablelist>
  341. </section>
  342. <section>
  343. <title>ldap_str2scope</title>
  344. <para>
  345. Converts LDAP search scope string into integer value e.g. for <varname>ldap_params_search</varname>.
  346. </para>
  347. <programlisting><![CDATA[
  348. typedef int (*ldap_str2scope_t)(char* scope_str);
  349. ]]>
  350. </programlisting>
  351. <variablelist>
  352. <title>Function arguments:</title>
  353. <varlistentry>
  354. <term>char* scope_str</term>
  355. <listitem>
  356. <para>
  357. LDAP search scope string. One of "one", "onelevel", "base", "sub", or "subtree".
  358. </para>
  359. </listitem>
  360. </varlistentry>
  361. </variablelist>
  362. <variablelist>
  363. <title>Return Values:</title>
  364. <varlistentry>
  365. <term>-1</term>
  366. <listitem>
  367. <para>
  368. <varname>scope_str</varname> not recognized.
  369. </para>
  370. </listitem>
  371. </varlistentry>
  372. <varlistentry>
  373. <term>n &gt;= 0</term>
  374. <listitem>
  375. <para>
  376. LDAP search scope integer.
  377. </para>
  378. </listitem>
  379. </varlistentry>
  380. </variablelist>
  381. </section>
  382. <section>
  383. <title>ldap_rfc4515_escape</title>
  384. <para>
  385. Applies escaping rules described in <xref linkend="ldap-filter-url-encode-fn" />.
  386. </para>
  387. <programlisting><![CDATA[
  388. typedef int (*ldap_rfc4515_escape_t)(str *sin, str *sout, int url_encode);
  389. ]]>
  390. </programlisting>
  391. <variablelist>
  392. <title>Function arguments:</title>
  393. <varlistentry>
  394. <term>str *sin</term>
  395. <listitem>
  396. <para>
  397. <varname>str</varname> structure holding the string to apply the escaping rules.
  398. </para>
  399. </listitem>
  400. </varlistentry>
  401. <varlistentry>
  402. <term>str *sout</term>
  403. <listitem>
  404. <para>
  405. <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.
  406. </para>
  407. </listitem>
  408. </varlistentry>
  409. <varlistentry>
  410. <term>int url_encode</term>
  411. <listitem>
  412. <para>
  413. 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.
  414. </para>
  415. </listitem>
  416. </varlistentry>
  417. </variablelist>
  418. <variablelist>
  419. <title>Return Values:</title>
  420. <varlistentry>
  421. <term>-1</term>
  422. <listitem>
  423. <para>
  424. Internal error.
  425. </para>
  426. </listitem>
  427. </varlistentry>
  428. <varlistentry>
  429. <term>0</term>
  430. <listitem>
  431. <para>
  432. Success, <varname>sout</varname> contains escaped string.
  433. </para>
  434. </listitem>
  435. </varlistentry>
  436. </variablelist>
  437. </section>
  438. <section>
  439. <title>get_ldap_handle</title>
  440. <para>
  441. Returns the OpenLDAP LDAP handle for a specific LDAP session. This allows a module
  442. implementor to use the OpenLDAP API functions directly, instead of using the API
  443. functions exported by the &kamailio; LDAP module. The <varname>LDAP</varname> structure
  444. is defined in OpenLDAP's <varname>ldap.h</varname>, which has to be included.
  445. </para>
  446. <programlisting><![CDATA[
  447. typedef int (*get_ldap_handle_t)(char* _lds_name, LDAP** _ldap_handle);
  448. ]]>
  449. </programlisting>
  450. <variablelist>
  451. <title>Function arguments:</title>
  452. <varlistentry>
  453. <term>char* _lds_name</term>
  454. <listitem>
  455. <para>
  456. LDAP session name as specified in the LDAP module configuration file.
  457. </para>
  458. </listitem>
  459. </varlistentry>
  460. <varlistentry>
  461. <term>LDAP** _ldap_handle</term>
  462. <listitem>
  463. <para>
  464. OpenLDAP LDAP handle returned by this function.
  465. </para>
  466. </listitem>
  467. </varlistentry>
  468. </variablelist>
  469. <variablelist>
  470. <title>Return Values:</title>
  471. <varlistentry>
  472. <term>-1</term>
  473. <listitem>
  474. <para>
  475. Internal error.
  476. </para>
  477. </listitem>
  478. </varlistentry>
  479. <varlistentry>
  480. <term>0</term>
  481. <listitem>
  482. <para>
  483. Success, <varname>_ldap_handle</varname> contains the OpenLDAP LDAP handle.
  484. </para>
  485. </listitem>
  486. </varlistentry>
  487. </variablelist>
  488. </section>
  489. <section>
  490. <title>get_last_ldap_result</title>
  491. <para>
  492. Returns the OpenLDAP LDAP handle and OpenLDAP result handle of the last LDAP search
  493. operation. These handles can be used as input for OpenLDAP LDAP result API functions.
  494. <varname>LDAP</varname> and <varname>LDAPMessage</varname> structures are defined in
  495. OpenLDAP's <varname>ldap.h</varname>, which has to be included.
  496. </para>
  497. <programlisting><![CDATA[
  498. typedef void (*get_last_ldap_result_t)
  499. (LDAP** _last_ldap_handle, LDAPMessage** _last_ldap_result);
  500. ]]>
  501. </programlisting>
  502. <variablelist>
  503. <title>Function arguments:</title>
  504. <varlistentry>
  505. <term>LDAP** _last_ldap_handle</term>
  506. <listitem>
  507. <para>
  508. OpenLDAP LDAP handle returned by this function.
  509. </para>
  510. </listitem>
  511. </varlistentry>
  512. <varlistentry>
  513. <term>LDAPMessage** _last_ldap_result</term>
  514. <listitem>
  515. <para>
  516. OpenLDAP result handle returned by this function.
  517. </para>
  518. </listitem>
  519. </varlistentry>
  520. </variablelist>
  521. </section>
  522. </section>
  523. <section>
  524. <title>Example Usage</title>
  525. <para>
  526. The following example shows how this API can be used to perform an LDAP search operation.
  527. It is assumed that the API is loaded and available through the <varname>ldap_api</varname> pointer.
  528. </para>
  529. <programlisting><![CDATA[
  530. ...
  531. int rc, ld_result_count, scope = 0;
  532. char* sip_username = "test";
  533. /*
  534. * get LDAP search scope integer
  535. */
  536. scope = ldap_api.ldap_str2scope("sub");
  537. if (scope == -1)
  538. {
  539. LM_ERR("ldap_str2scope failed\n");
  540. return -1;
  541. }
  542. /*
  543. * perform LDAP search
  544. */
  545. if (ldap_api.ldap_params_search(
  546. &ld_result_count,
  547. "campus",
  548. "dc=example,dc=com",
  549. scope,
  550. NULL,
  551. "(&(objectClass=SIPIdentity)(SIPIdentityUserName=%s))",
  552. sip_username)
  553. != 0)
  554. {
  555. LM_ERR("LDAP search failed\n");
  556. return -1;
  557. }
  558. /*
  559. * check result count
  560. */
  561. if (ld_result_count < 1)
  562. {
  563. LM_ERR("LDAP search returned no entry\n");
  564. return 1;
  565. }
  566. /*
  567. * get password attribute value
  568. */
  569. struct berval **attr_vals = NULL;
  570. str ldap_pwd_attr_name = str_init("SIPIdentityPassword");
  571. str res_password;
  572. rc = ldap_api.ldap_result_attr_vals(&ldap_pwd_attr_name, &attr_vals);
  573. if (rc < 0)
  574. {
  575. LM_ERR("ldap_result_attr_vals failed\n");
  576. ldap_api.ldap_value_free_len(attr_vals);
  577. return -1;
  578. }
  579. if (rc == 1)
  580. {
  581. LM_INFO("No password attribute value found for [%s]\n", sip_username);
  582. ldap_api.ldap_value_free_len(attr_vals);
  583. return 2;
  584. }
  585. res_password.s = attr_vals[0]->bv_val;
  586. res_password.len = attr_vals[0]->bv_len;
  587. ldap_api.ldap_value_free_len(attr_vals);
  588. LM_INFO("Password for user [%s]: [%s]\n", sip_username, res_password.s);
  589. ...
  590. return 0;
  591. ]]>
  592. </programlisting>
  593. </section>
  594. </chapter>