ldap_connect.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /*
  2. * Kamailio LDAP Module
  3. *
  4. * Copyright (C) 2007 University of North Carolina
  5. *
  6. * Original author: Christian Schlatter, [email protected]
  7. *
  8. *
  9. * This file is part of Kamailio, a free SIP server.
  10. *
  11. * Kamailio is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2 of the License, or
  14. * (at your option) any later version
  15. *
  16. * Kamailio is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program; if not, write to the Free Software
  23. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  24. *
  25. */
  26. #include <string.h>
  27. #include <unistd.h>
  28. #include <stdio.h>
  29. #include <ldap.h>
  30. #include "ldap_connect.h"
  31. #include "ld_session.h"
  32. #include "../../mem/mem.h"
  33. #include "../../ut.h"
  34. int ldap_connect_ex(char* _ld_name, int llevel)
  35. {
  36. int rc;
  37. int ldap_bind_result_code;
  38. char *ldap_err_str;
  39. int ldap_proto_version;
  40. int msgid;
  41. LDAPMessage *result;
  42. struct ld_session* lds;
  43. struct berval ldap_cred;
  44. /*
  45. * get ld session and session config parameters
  46. */
  47. if ((lds = get_ld_session(_ld_name)) == NULL)
  48. {
  49. LM_ERR("ld_session [%s] not found\n", _ld_name);
  50. return -1;
  51. }
  52. /*
  53. * ldap_initialize
  54. */
  55. rc = ldap_initialize(&lds->handle, lds->host_name);
  56. if (rc != LDAP_SUCCESS)
  57. {
  58. LM_ERR( "[%s]: ldap_initialize (%s) failed: %s\n",
  59. _ld_name,
  60. lds->host_name,
  61. ldap_err2string(rc));
  62. return -1;
  63. }
  64. /*
  65. * set LDAP OPTIONS
  66. */
  67. /* LDAP_OPT_PROTOCOL_VERSION */
  68. switch (lds->version) {
  69. case 2:
  70. ldap_proto_version = LDAP_VERSION2;
  71. break;
  72. case 3:
  73. ldap_proto_version = LDAP_VERSION3;
  74. break;
  75. default:
  76. LM_ERR( "[%s]: Invalid LDAP protocol version [%d]\n",
  77. _ld_name,
  78. lds->version);
  79. return -1;
  80. }
  81. if (ldap_set_option(lds->handle,
  82. LDAP_OPT_PROTOCOL_VERSION,
  83. &ldap_proto_version)
  84. != LDAP_OPT_SUCCESS)
  85. {
  86. LM_ERR( "[%s]: Could not set LDAP_OPT_PROTOCOL_VERSION [%d]\n",
  87. _ld_name,
  88. ldap_proto_version);
  89. return -1;
  90. }
  91. /* LDAP_OPT_RESTART */
  92. if (ldap_set_option(lds->handle,
  93. LDAP_OPT_RESTART,
  94. LDAP_OPT_ON)
  95. != LDAP_OPT_SUCCESS) {
  96. LM_ERR("[%s]: Could not set LDAP_OPT_RESTART to ON\n", _ld_name);
  97. return -1;
  98. }
  99. /* LDAP_OPT_TIMELIMIT */
  100. /*
  101. if (lds->server_search_timeout > 0) {
  102. if (ldap_set_option(lds->handle,
  103. LDAP_OPT_TIMELIMIT,
  104. &lds->server_search_timeout)
  105. != LDAP_OPT_SUCCESS) {
  106. LM_ERR("[%s]: Could not set LDAP_OPT_TIMELIMIT to [%d]\n",
  107. _ld_name, lds->server_search_timeout);
  108. return -1;
  109. }
  110. }
  111. */
  112. /* LDAP_OPT_NETWORK_TIMEOUT */
  113. if ((lds->network_timeout.tv_sec > 0) || (lds->network_timeout.tv_usec > 0))
  114. {
  115. if (ldap_set_option(lds->handle,
  116. LDAP_OPT_NETWORK_TIMEOUT,
  117. (const void *)&lds->network_timeout)
  118. != LDAP_OPT_SUCCESS)
  119. {
  120. LM_ERR( "[%s]: Could not set"
  121. " LDAP_NETWORK_TIMEOUT to [%d.%d]\n",
  122. _ld_name,
  123. (int)lds->network_timeout.tv_sec,
  124. (int)lds->network_timeout.tv_usec);
  125. }
  126. }
  127. /*
  128. * ldap_sasl_bind (LDAP_SASL_SIMPLE)
  129. */
  130. ldap_cred.bv_val = lds->bind_pwd;
  131. ldap_cred.bv_len = strlen(lds->bind_pwd);
  132. rc = ldap_sasl_bind(
  133. lds->handle,
  134. lds->bind_dn,
  135. LDAP_SASL_SIMPLE,
  136. &ldap_cred,
  137. NULL,
  138. NULL,
  139. &msgid);
  140. if (rc != LDAP_SUCCESS)
  141. {
  142. LM_ERR( "[%s]: ldap bind failed: %s\n",
  143. _ld_name,
  144. ldap_err2string(rc));
  145. return -1;
  146. }
  147. if ((lds->client_bind_timeout.tv_sec == 0)
  148. && (lds->client_bind_timeout.tv_usec == 0))
  149. {
  150. rc = ldap_result(lds->handle, msgid, 1, NULL, &result);
  151. } else
  152. {
  153. rc = ldap_result(lds->handle, msgid, 1, &lds->client_bind_timeout,
  154. &result);
  155. }
  156. if (rc == -1)
  157. {
  158. ldap_get_option(lds->handle, LDAP_OPT_ERROR_NUMBER, &rc);
  159. ldap_err_str = ldap_err2string(rc);
  160. LM_ERR( "[%s]: ldap_result failed: %s\n",
  161. _ld_name,
  162. ldap_err_str);
  163. return -1;
  164. }
  165. else if (rc == 0)
  166. {
  167. LM_ERR("[%s]: bind operation timed out\n", _ld_name);
  168. return -1;
  169. }
  170. rc = ldap_parse_result(
  171. lds->handle,
  172. result,
  173. &ldap_bind_result_code,
  174. NULL,
  175. NULL,
  176. NULL,
  177. NULL,
  178. 1);
  179. if (rc != LDAP_SUCCESS)
  180. {
  181. LM_ERR( "[%s]: ldap_parse_result failed: %s\n",
  182. _ld_name,
  183. ldap_err2string(rc));
  184. return -1;
  185. }
  186. if (ldap_bind_result_code != LDAP_SUCCESS)
  187. {
  188. LM_ERR( "[%s]: ldap bind failed: %s\n",
  189. _ld_name,
  190. ldap_err2string(ldap_bind_result_code));
  191. return -1;
  192. }
  193. /* freeing result leads to segfault ... bind result is probably used by openldap lib */
  194. /* ldap_msgfree(result); */
  195. LOG(llevel, "[%s]: LDAP bind successful (ldap_host [%s])\n",
  196. _ld_name,
  197. lds->host_name);
  198. return 0;
  199. }
  200. int ldap_connect(char* _ld_name)
  201. {
  202. return ldap_connect_ex(_ld_name, L_DBG);
  203. }
  204. int ldap_disconnect(char* _ld_name)
  205. {
  206. struct ld_session* lds;
  207. /*
  208. * get ld session
  209. */
  210. if ((lds = get_ld_session(_ld_name)) == NULL)
  211. {
  212. LM_ERR("ld_session [%s] not found\n", _ld_name);
  213. return -1;
  214. }
  215. if (lds->handle == NULL) {
  216. return 0;
  217. }
  218. ldap_unbind_ext(lds->handle, NULL, NULL);
  219. lds->handle = NULL;
  220. return 0;
  221. }
  222. int ldap_reconnect(char* _ld_name)
  223. {
  224. int rc;
  225. if (ldap_disconnect(_ld_name) != 0)
  226. {
  227. LM_ERR("[%s]: disconnect failed\n", _ld_name);
  228. return -1;
  229. }
  230. if ((rc = ldap_connect_ex(_ld_name, L_INFO)) != 0)
  231. {
  232. LM_ERR("[%s]: reconnect failed\n",
  233. _ld_name);
  234. }
  235. else
  236. {
  237. LM_NOTICE("[%s]: LDAP reconnect successful\n",
  238. _ld_name);
  239. }
  240. return rc;
  241. }
  242. int ldap_get_vendor_version(char** _version)
  243. {
  244. static char version[128];
  245. LDAPAPIInfo api;
  246. int rc;
  247. #ifdef LDAP_API_INFO_VERSION
  248. api.ldapai_info_version = LDAP_API_INFO_VERSION;
  249. #else
  250. api.ldapai_info_version = 1;
  251. #endif
  252. if (ldap_get_option(NULL, LDAP_OPT_API_INFO, &api) != LDAP_SUCCESS)
  253. {
  254. LM_ERR("ldap_get_option(API_INFO) failed\n");
  255. return -1;
  256. }
  257. rc = snprintf(version, 128, "%s - %d", api.ldapai_vendor_name,
  258. api.ldapai_vendor_version);
  259. if ((rc >= 128) || (rc < 0))
  260. {
  261. LM_ERR("snprintf failed\n");
  262. return -1;
  263. }
  264. *_version = version;
  265. return 0;
  266. }