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.
371 lines
7.1 KiB
371 lines
7.1 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 <stdio.h>
|
|
|
|
#include <ldap.h>
|
|
|
|
#include "../../ut.h"
|
|
#include "../../str.h"
|
|
#include "../../pvar.h"
|
|
#include "../../usr_avp.h"
|
|
#include "../../mem/mem.h"
|
|
#include "ldap_exp_fn.h"
|
|
#include "ldap_connect.h"
|
|
#include "ldap_api_fn.h"
|
|
#include "ldap_escape.h"
|
|
|
|
|
|
#define STR_BUF_SIZE 1024
|
|
#define ESC_BUF_SIZE 65536
|
|
|
|
static char str_buf[STR_BUF_SIZE];
|
|
static char esc_buf[ESC_BUF_SIZE];
|
|
|
|
|
|
/*
|
|
* exported functions
|
|
*/
|
|
|
|
int ldap_search_impl(
|
|
struct sip_msg* _msg,
|
|
pv_elem_t* _ldap_url)
|
|
{
|
|
str ldap_url;
|
|
int ld_result_count = 0;
|
|
|
|
/*
|
|
* do variable substitution for _ldap_url (pv_printf_s)
|
|
*/
|
|
if (_ldap_url==NULL) {
|
|
LM_ERR("empty ldap_url\n");
|
|
return -2;
|
|
}
|
|
if ( _ldap_url->spec!=NULL && _ldap_url->spec->getf!=NULL) {
|
|
if (pv_printf_s( _msg, _ldap_url, &ldap_url)!=0 || ldap_url.len<=0) {
|
|
LM_ERR("pv_printf_s failed\n");
|
|
return -2;
|
|
}
|
|
} else {
|
|
ldap_url = _ldap_url->text;
|
|
}
|
|
|
|
/*
|
|
* perform LDAP search
|
|
*/
|
|
if (ldap_url_search(ldap_url.s, &ld_result_count) != 0)
|
|
{
|
|
/* LDAP search error */
|
|
return -2;
|
|
}
|
|
if (ld_result_count < 1)
|
|
{
|
|
/* no LDAP entry found */
|
|
LM_INFO("no LDAP entry found\n");
|
|
return -1;
|
|
}
|
|
return ld_result_count;
|
|
}
|
|
|
|
int ldap_write_result(
|
|
struct sip_msg* _msg,
|
|
struct ldap_result_params* _lrp,
|
|
struct subst_expr* _se)
|
|
{
|
|
int_str dst_avp_name, dst_avp_val;
|
|
unsigned short dst_avp_type;
|
|
int nmatches, rc, i, added_avp_count = 0;
|
|
struct berval **attr_vals;
|
|
str avp_val_str, *subst_result = NULL;
|
|
int avp_val_int;
|
|
|
|
/*
|
|
* get dst AVP name (dst_avp_name)
|
|
*/
|
|
|
|
if (pv_get_avp_name( _msg,
|
|
&(_lrp->dst_avp_spec.pvp),
|
|
&dst_avp_name,
|
|
&dst_avp_type)
|
|
!= 0)
|
|
{
|
|
LM_ERR("error getting dst AVP name\n");
|
|
return -2;
|
|
}
|
|
if (dst_avp_type & AVP_NAME_STR)
|
|
{
|
|
if (dst_avp_name.s.len >= STR_BUF_SIZE)
|
|
{
|
|
LM_ERR("dst AVP name too long\n");
|
|
return -2;
|
|
}
|
|
strncpy(str_buf, dst_avp_name.s.s, dst_avp_name.s.len);
|
|
str_buf[dst_avp_name.s.len] = '\0';
|
|
dst_avp_name.s.s = str_buf;
|
|
}
|
|
|
|
/*
|
|
* get LDAP attr values
|
|
*/
|
|
if ((rc = ldap_get_attr_vals(&_lrp->ldap_attr_name, &attr_vals)) != 0)
|
|
{
|
|
if (rc > 0) {
|
|
return -1;
|
|
} else {
|
|
return -2;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* add AVPs
|
|
*/
|
|
for (i = 0; attr_vals[i] != NULL; i++)
|
|
{
|
|
if (_se == NULL)
|
|
{
|
|
avp_val_str.s = attr_vals[i]->bv_val;
|
|
avp_val_str.len = attr_vals[i]->bv_len;
|
|
}
|
|
else
|
|
{
|
|
subst_result = subst_str(attr_vals[i]->bv_val, _msg, _se,
|
|
&nmatches);
|
|
if ((subst_result == NULL) || (nmatches < 1))
|
|
{
|
|
continue;
|
|
}
|
|
avp_val_str = *subst_result;
|
|
}
|
|
|
|
if (_lrp->dst_avp_val_type == 1)
|
|
{
|
|
/* try to convert ldap value to integer */
|
|
if (!str2sint(&avp_val_str, &avp_val_int))
|
|
{
|
|
dst_avp_val.n = avp_val_int;
|
|
rc = add_avp(dst_avp_type, dst_avp_name, dst_avp_val);
|
|
} else
|
|
{
|
|
continue;
|
|
}
|
|
} else
|
|
{
|
|
/* save ldap value as string */
|
|
dst_avp_val.s = avp_val_str;
|
|
rc = add_avp(dst_avp_type|AVP_VAL_STR, dst_avp_name, dst_avp_val);
|
|
}
|
|
|
|
if (subst_result != NULL) {
|
|
if (subst_result->s != 0) {
|
|
pkg_free(subst_result->s);
|
|
}
|
|
pkg_free(subst_result);
|
|
subst_result = NULL;
|
|
}
|
|
|
|
if (rc < 0)
|
|
{
|
|
LM_ERR("failed to create new AVP\n");
|
|
ldap_value_free_len(attr_vals);
|
|
return -2;
|
|
}
|
|
added_avp_count++;
|
|
}
|
|
ldap_value_free_len(attr_vals);
|
|
|
|
if (added_avp_count > 0)
|
|
{
|
|
return added_avp_count;
|
|
} else
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int ldap_result_next(void)
|
|
{
|
|
int rc;
|
|
|
|
rc = ldap_inc_result_pointer();
|
|
switch (rc)
|
|
{
|
|
case 1:
|
|
return -1;
|
|
case 0:
|
|
return 1;
|
|
case -1:
|
|
default:
|
|
return -2;
|
|
}
|
|
}
|
|
|
|
int ldap_result_check(
|
|
struct sip_msg* _msg,
|
|
struct ldap_result_check_params* _lrp,
|
|
struct subst_expr* _se)
|
|
{
|
|
str check_str, *subst_result = NULL;
|
|
int rc, i, nmatches;
|
|
char *attr_val;
|
|
struct berval **attr_vals;
|
|
|
|
/*
|
|
* do variable substitution for check_str
|
|
*/
|
|
|
|
if (_lrp->check_str_elem_p)
|
|
{
|
|
if (pv_printf_s(_msg, _lrp->check_str_elem_p, &check_str) != 0)
|
|
{
|
|
LM_ERR("pv_printf_s failed\n");
|
|
return -2;
|
|
}
|
|
} else
|
|
{
|
|
LM_ERR("empty check string\n");
|
|
return -2;
|
|
}
|
|
|
|
LM_DBG("check_str [%s]\n", check_str.s);
|
|
|
|
/*
|
|
* get LDAP attr values
|
|
*/
|
|
|
|
if ((rc = ldap_get_attr_vals(&_lrp->ldap_attr_name, &attr_vals)) != 0)
|
|
{
|
|
if (rc > 0) {
|
|
return -1;
|
|
} else {
|
|
return -2;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* loop through attribute values
|
|
*/
|
|
|
|
for (i = 0; attr_vals[i] != NULL; i++)
|
|
{
|
|
if (_se == NULL)
|
|
{
|
|
attr_val = attr_vals[i]->bv_val;
|
|
} else
|
|
{
|
|
subst_result = subst_str(attr_vals[i]->bv_val, _msg, _se,
|
|
&nmatches);
|
|
if ((subst_result == NULL) || (nmatches < 1))
|
|
{
|
|
continue;
|
|
}
|
|
attr_val = subst_result->s;
|
|
}
|
|
|
|
LM_DBG("attr_val [%s]\n", attr_val);
|
|
rc = strncmp(check_str.s, attr_val, check_str.len);
|
|
if (_se != NULL)
|
|
{
|
|
pkg_free(subst_result->s);
|
|
}
|
|
if (rc == 0)
|
|
{
|
|
ldap_value_free_len(attr_vals);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
ldap_value_free_len(attr_vals);
|
|
return -1;
|
|
}
|
|
|
|
int ldap_filter_url_encode(
|
|
struct sip_msg* _msg,
|
|
pv_elem_t* _filter_component,
|
|
pv_spec_t* _dst_avp_spec)
|
|
{
|
|
str filter_component_str, esc_str;
|
|
int_str dst_avp_name;
|
|
unsigned short dst_avp_type;
|
|
|
|
/*
|
|
* variable substitution for _filter_component
|
|
*/
|
|
if (_filter_component) {
|
|
if (pv_printf_s(_msg, _filter_component, &filter_component_str) != 0) {
|
|
LM_ERR("pv_printf_s failed\n");
|
|
return -1;
|
|
}
|
|
} else {
|
|
LM_ERR("empty first argument\n");
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* get dst AVP name (dst_avp_name)
|
|
*/
|
|
if (pv_get_avp_name(_msg, &(_dst_avp_spec->pvp), &dst_avp_name,
|
|
&dst_avp_type) != 0)
|
|
{
|
|
LM_ERR("error getting dst AVP name\n");
|
|
return -1;
|
|
}
|
|
if (dst_avp_type & AVP_NAME_STR)
|
|
{
|
|
if (dst_avp_name.s.len >= STR_BUF_SIZE)
|
|
{
|
|
LM_ERR("dst AVP name too long\n");
|
|
return -1;
|
|
}
|
|
strncpy(str_buf, dst_avp_name.s.s, dst_avp_name.s.len);
|
|
str_buf[dst_avp_name.s.len] = '\0';
|
|
dst_avp_name.s.s = str_buf;
|
|
}
|
|
|
|
/*
|
|
* apply LDAP filter escaping rules
|
|
*/
|
|
esc_str.s = esc_buf;
|
|
esc_str.len = ESC_BUF_SIZE;
|
|
if (ldap_rfc4515_escape(&filter_component_str, &esc_str, 1) != 0)
|
|
{
|
|
LM_ERR("ldap_rfc4515_escape() failed\n");
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* add dst AVP
|
|
*/
|
|
if (add_avp(dst_avp_type|AVP_VAL_STR, dst_avp_name, (int_str)esc_str) != 0)
|
|
{
|
|
LM_ERR("failed to add new AVP\n");
|
|
return -1;
|
|
}
|
|
|
|
return 1;
|
|
}
|