/* * 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 #include #include #include #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; }