mirror of https://github.com/sipwise/kamailio.git
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.
312 lines
6.0 KiB
312 lines
6.0 KiB
/*
|
|
* Kamailio LDAP Module
|
|
*
|
|
* Copyright (C) 2007 University of North Carolina
|
|
*
|
|
* Original author: Christian Schlatter, cs@unc.edu
|
|
*
|
|
*
|
|
* This file is part of Kamailio, a free SIP server.
|
|
*
|
|
* Kamailio is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version
|
|
*
|
|
* Kamailio is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
*/
|
|
|
|
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
|
|
#include <ldap.h>
|
|
|
|
#include "ldap_connect.h"
|
|
#include "ld_session.h"
|
|
#include "../../mem/mem.h"
|
|
#include "../../ut.h"
|
|
|
|
int ldap_connect_ex(char* _ld_name, int llevel)
|
|
{
|
|
int rc;
|
|
int ldap_bind_result_code;
|
|
char *ldap_err_str;
|
|
int ldap_proto_version;
|
|
int msgid;
|
|
LDAPMessage *result;
|
|
struct ld_session* lds;
|
|
struct berval ldap_cred;
|
|
|
|
/*
|
|
* get ld session and session config parameters
|
|
*/
|
|
|
|
if ((lds = get_ld_session(_ld_name)) == NULL)
|
|
{
|
|
LM_ERR("ld_session [%s] not found\n", _ld_name);
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* ldap_initialize
|
|
*/
|
|
|
|
rc = ldap_initialize(&lds->handle, lds->host_name);
|
|
if (rc != LDAP_SUCCESS)
|
|
{
|
|
LM_ERR( "[%s]: ldap_initialize (%s) failed: %s\n",
|
|
_ld_name,
|
|
lds->host_name,
|
|
ldap_err2string(rc));
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* set LDAP OPTIONS
|
|
*/
|
|
|
|
/* LDAP_OPT_PROTOCOL_VERSION */
|
|
switch (lds->version) {
|
|
case 2:
|
|
ldap_proto_version = LDAP_VERSION2;
|
|
break;
|
|
case 3:
|
|
ldap_proto_version = LDAP_VERSION3;
|
|
break;
|
|
default:
|
|
LM_ERR( "[%s]: Invalid LDAP protocol version [%d]\n",
|
|
_ld_name,
|
|
lds->version);
|
|
return -1;
|
|
}
|
|
if (ldap_set_option(lds->handle,
|
|
LDAP_OPT_PROTOCOL_VERSION,
|
|
&ldap_proto_version)
|
|
!= LDAP_OPT_SUCCESS)
|
|
{
|
|
LM_ERR( "[%s]: Could not set LDAP_OPT_PROTOCOL_VERSION [%d]\n",
|
|
_ld_name,
|
|
ldap_proto_version);
|
|
return -1;
|
|
}
|
|
|
|
/* LDAP_OPT_RESTART */
|
|
if (ldap_set_option(lds->handle,
|
|
LDAP_OPT_RESTART,
|
|
LDAP_OPT_ON)
|
|
!= LDAP_OPT_SUCCESS) {
|
|
LM_ERR("[%s]: Could not set LDAP_OPT_RESTART to ON\n", _ld_name);
|
|
return -1;
|
|
}
|
|
|
|
/* LDAP_OPT_TIMELIMIT */
|
|
/*
|
|
if (lds->server_search_timeout > 0) {
|
|
if (ldap_set_option(lds->handle,
|
|
LDAP_OPT_TIMELIMIT,
|
|
&lds->server_search_timeout)
|
|
!= LDAP_OPT_SUCCESS) {
|
|
LM_ERR("[%s]: Could not set LDAP_OPT_TIMELIMIT to [%d]\n",
|
|
_ld_name, lds->server_search_timeout);
|
|
return -1;
|
|
}
|
|
}
|
|
*/
|
|
|
|
/* LDAP_OPT_NETWORK_TIMEOUT */
|
|
if ((lds->network_timeout.tv_sec > 0) || (lds->network_timeout.tv_usec > 0))
|
|
{
|
|
if (ldap_set_option(lds->handle,
|
|
LDAP_OPT_NETWORK_TIMEOUT,
|
|
(const void *)&lds->network_timeout)
|
|
!= LDAP_OPT_SUCCESS)
|
|
{
|
|
LM_ERR( "[%s]: Could not set"
|
|
" LDAP_NETWORK_TIMEOUT to [%d.%d]\n",
|
|
_ld_name,
|
|
(int)lds->network_timeout.tv_sec,
|
|
(int)lds->network_timeout.tv_usec);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ldap_sasl_bind (LDAP_SASL_SIMPLE)
|
|
*/
|
|
|
|
|
|
ldap_cred.bv_val = lds->bind_pwd;
|
|
ldap_cred.bv_len = strlen(lds->bind_pwd);
|
|
rc = ldap_sasl_bind(
|
|
lds->handle,
|
|
lds->bind_dn,
|
|
LDAP_SASL_SIMPLE,
|
|
&ldap_cred,
|
|
NULL,
|
|
NULL,
|
|
&msgid);
|
|
if (rc != LDAP_SUCCESS)
|
|
{
|
|
LM_ERR( "[%s]: ldap bind failed: %s\n",
|
|
_ld_name,
|
|
ldap_err2string(rc));
|
|
return -1;
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((lds->client_bind_timeout.tv_sec == 0)
|
|
&& (lds->client_bind_timeout.tv_usec == 0))
|
|
{
|
|
rc = ldap_result(lds->handle, msgid, 1, NULL, &result);
|
|
} else
|
|
{
|
|
rc = ldap_result(lds->handle, msgid, 1, &lds->client_bind_timeout,
|
|
&result);
|
|
}
|
|
|
|
|
|
if (rc == -1)
|
|
{
|
|
ldap_get_option(lds->handle, LDAP_OPT_ERROR_NUMBER, &rc);
|
|
ldap_err_str = ldap_err2string(rc);
|
|
LM_ERR( "[%s]: ldap_result failed: %s\n",
|
|
_ld_name,
|
|
ldap_err_str);
|
|
return -1;
|
|
}
|
|
else if (rc == 0)
|
|
{
|
|
LM_ERR("[%s]: bind operation timed out\n", _ld_name);
|
|
return -1;
|
|
}
|
|
|
|
|
|
rc = ldap_parse_result(
|
|
lds->handle,
|
|
result,
|
|
&ldap_bind_result_code,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
1);
|
|
if (rc != LDAP_SUCCESS)
|
|
{
|
|
LM_ERR( "[%s]: ldap_parse_result failed: %s\n",
|
|
_ld_name,
|
|
ldap_err2string(rc));
|
|
return -1;
|
|
}
|
|
if (ldap_bind_result_code != LDAP_SUCCESS)
|
|
{
|
|
LM_ERR( "[%s]: ldap bind failed: %s\n",
|
|
_ld_name,
|
|
ldap_err2string(ldap_bind_result_code));
|
|
return -1;
|
|
}
|
|
|
|
|
|
/* freeing result leads to segfault ... bind result is probably used by openldap lib */
|
|
/* ldap_msgfree(result); */
|
|
|
|
|
|
LOG(llevel, "[%s]: LDAP bind successful (ldap_host [%s])\n",
|
|
_ld_name,
|
|
lds->host_name);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int ldap_connect(char* _ld_name)
|
|
{
|
|
return ldap_connect_ex(_ld_name, L_DBG);
|
|
}
|
|
|
|
int ldap_disconnect(char* _ld_name)
|
|
{
|
|
struct ld_session* lds;
|
|
|
|
/*
|
|
* get ld session
|
|
*/
|
|
|
|
if ((lds = get_ld_session(_ld_name)) == NULL)
|
|
{
|
|
LM_ERR("ld_session [%s] not found\n", _ld_name);
|
|
return -1;
|
|
}
|
|
|
|
if (lds->handle == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
ldap_unbind_ext(lds->handle, NULL, NULL);
|
|
lds->handle = NULL;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int ldap_reconnect(char* _ld_name)
|
|
{
|
|
int rc;
|
|
|
|
if (ldap_disconnect(_ld_name) != 0)
|
|
{
|
|
LM_ERR("[%s]: disconnect failed\n", _ld_name);
|
|
return -1;
|
|
}
|
|
|
|
if ((rc = ldap_connect_ex(_ld_name, L_INFO)) != 0)
|
|
{
|
|
LM_ERR("[%s]: reconnect failed\n",
|
|
_ld_name);
|
|
}
|
|
else
|
|
{
|
|
LM_NOTICE("[%s]: LDAP reconnect successful\n",
|
|
_ld_name);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
int ldap_get_vendor_version(char** _version)
|
|
{
|
|
static char version[128];
|
|
LDAPAPIInfo api;
|
|
int rc;
|
|
|
|
#ifdef LDAP_API_INFO_VERSION
|
|
api.ldapai_info_version = LDAP_API_INFO_VERSION;
|
|
#else
|
|
api.ldapai_info_version = 1;
|
|
#endif
|
|
|
|
if (ldap_get_option(NULL, LDAP_OPT_API_INFO, &api) != LDAP_SUCCESS)
|
|
{
|
|
LM_ERR("ldap_get_option(API_INFO) failed\n");
|
|
return -1;
|
|
}
|
|
|
|
rc = snprintf(version, 128, "%s - %d", api.ldapai_vendor_name,
|
|
api.ldapai_vendor_version);
|
|
if ((rc >= 128) || (rc < 0))
|
|
{
|
|
LM_ERR("snprintf failed\n");
|
|
return -1;
|
|
}
|
|
|
|
*_version = version;
|
|
return 0;
|
|
}
|