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.
kamailio/modules/ldap/ldap_exp_fn.c

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;
}