h350_exp_fn.c

Go to the documentation of this file.
00001 /*
00002  * $Id: $
00003  *
00004  * Kamailio H.350 Module
00005  *
00006  * Copyright (C) 2007 University of North Carolina
00007  *
00008  * Original author: Christian Schlatter, cs@unc.edu
00009  *
00010  *
00011  * This file is part of Kamailio, a free SIP server.
00012  *
00013  * Kamailio is free software; you can redistribute it and/or modify
00014  * it under the terms of the GNU General Public License as published by
00015  * the Free Software Foundation; either version 2 of the License, or
00016  * (at your option) any later version
00017  *
00018  * Kamailio is distributed in the hope that it will be useful,
00019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  * GNU General Public License for more details.
00022  *
00023  * You should have received a copy of the GNU General Public License
00024  * along with this program; if not, write to the Free Software
00025  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00026  *
00027  * History:
00028  * --------
00029  * 2007-03-12: Initial version
00030  */
00031 
00032 #include <regex.h>
00033 #include "ldap.h"
00034 
00035 #include "h350_mod.h"
00036 #include "h350_exp_fn.h"
00037 
00038 #include "../../pvar.h"
00039 #include "../../ut.h"
00040 #include "../../mem/mem.h"
00041 
00042 #define H350_SIPURI_LOOKUP_LDAP_FILTER "(&(objectClass=SIPIdentity)(SIPIdentitySIPURI=%s))"
00043 #define H350_AUTH_FILTER_PATTERN "(&(objectClass=SIPIdentity)(SIPIdentityUserName=%s))"
00044 
00045 static str h350_call_pref_name = str_init("callPreferenceURI");
00046 static str h350_sip_pwd_name = str_init("SIPIdentityPassword");
00047 static str h350_service_level_name = str_init("SIPIdentityServiceLevel");
00048 
00049 #define H350_CALL_PREF_REGEX "^([^ ]+) +([a-zA-Z]+)(:([0-9]+))?$"
00050 
00051 #define SIP_URI_ESCAPED_MAX_LEN 1024
00052 #define AVP_NAME_STR_BUF_LEN 1024
00053 #define DIGEST_USERNAME_BUF_SIZE 2048
00054 
00055 static regex_t* call_pref_preg;
00056 
00057 int h350_sipuri_lookup(struct sip_msg* _msg, pv_elem_t* _sip_uri)
00058 {
00059    str sip_uri, sip_uri_escaped;
00060    int ld_result_count;
00061    static char sip_uri_escaped_buf[SIP_URI_ESCAPED_MAX_LEN];
00062 
00063    /*
00064     * get sip_uri
00065     */
00066    if (pv_printf_s(_msg, _sip_uri, &sip_uri) != 0)
00067    {
00068       LM_ERR("pv_printf_s failed\n");
00069       return E_H350_INTERNAL;
00070    }
00071 
00072    /*
00073     * ldap filter escape sip_uri
00074     */
00075    sip_uri_escaped.s = sip_uri_escaped_buf;
00076    sip_uri_escaped.len = SIP_URI_ESCAPED_MAX_LEN - 1;
00077    if (ldap_api.ldap_rfc4515_escape(&sip_uri, &sip_uri_escaped, 0))
00078    {
00079       LM_ERR("ldap_rfc4515_escape failed\n");
00080       return E_H350_INTERNAL;
00081    }
00082    
00083    /*
00084     * do ldap search
00085     */
00086    if (ldap_api.ldap_params_search(&ld_result_count,
00087                h350_ldap_session.s,
00088                h350_base_dn.s,
00089                h350_search_scope_int,
00090                NULL,
00091                H350_SIPURI_LOOKUP_LDAP_FILTER,
00092                sip_uri_escaped.s)
00093        != 0)
00094    {
00095       LM_ERR("ldap search failed\n");
00096       return E_H350_INTERNAL;
00097    }
00098    
00099    if (ld_result_count < 1)
00100    {
00101       return E_H350_NO_SUCCESS;
00102    }
00103 
00104    return ld_result_count;
00105 }
00106 
00107 int h350_auth_lookup(
00108         struct sip_msg* _msg,
00109         pv_elem_t* _digest_username,
00110         struct h350_auth_lookup_avp_params* _avp_specs)
00111 {
00112    str                digest_username,
00113                       digest_username_escaped,
00114                       digest_password;
00115    static char        digest_username_buf[DIGEST_USERNAME_BUF_SIZE],
00116                       username_avp_name_buf[AVP_NAME_STR_BUF_LEN],
00117             password_avp_name_buf[AVP_NAME_STR_BUF_LEN];
00118    struct berval      **attr_vals = NULL;
00119    int_str            username_avp_name, password_avp_name, avp_val;
00120    unsigned short     username_avp_type, password_avp_type;
00121    int                rc, ld_result_count;
00122 
00123    /*
00124     * get digest_username str
00125     */
00126    if (_digest_username) 
00127    {
00128                 if (pv_printf_s(_msg, _digest_username, &digest_username) != 0) 
00129       {
00130                         LM_ERR("pv_printf_s failed\n");
00131                         return E_H350_INTERNAL;
00132                 }
00133         } else
00134    {
00135       LM_ERR("empty digest username\n");
00136       return E_H350_NO_SUCCESS;
00137    }
00138 
00139    /*
00140     * get AVP names for username and password
00141     */
00142 
00143    if (pv_get_avp_name( _msg,
00144             &(_avp_specs->username_avp_spec.pvp),
00145             &username_avp_name,
00146             &username_avp_type)
00147       != 0)
00148    {
00149       LM_ERR("error getting AVP name - pv_get_avp_name failed\n");
00150       return E_H350_INTERNAL;
00151    }
00152    if (username_avp_type & AVP_NAME_STR)
00153    {
00154       if (username_avp_name.s.len >= AVP_NAME_STR_BUF_LEN)
00155       {
00156          LM_ERR("username AVP name too long\n");
00157          return E_H350_INTERNAL;
00158       }
00159       strncpy(username_avp_name_buf, username_avp_name.s.s, username_avp_name.s.len);
00160                 username_avp_name_buf[username_avp_name.s.len] = '\0';
00161                 username_avp_name.s.s = username_avp_name_buf;
00162    }
00163 
00164    if (pv_get_avp_name(_msg,
00165                   &(_avp_specs->password_avp_spec.pvp),
00166                   &password_avp_name,
00167                   &password_avp_type)
00168                 != 0)
00169         {
00170                 LM_ERR("error getting AVP name - pv_get_avp_name failed\n");
00171                 return E_H350_INTERNAL;
00172         }
00173         if (password_avp_type & AVP_NAME_STR)
00174         {
00175                 if (password_avp_name.s.len >= AVP_NAME_STR_BUF_LEN)
00176                 {
00177                         LM_ERR("password AVP name too long\n");
00178                         return E_H350_INTERNAL;
00179                 }
00180                 strncpy(password_avp_name_buf, 
00181                   password_avp_name.s.s, 
00182                   password_avp_name.s.len);
00183                 password_avp_name_buf[password_avp_name.s.len] = '\0';
00184                 password_avp_name.s.s = password_avp_name_buf;
00185         }
00186    
00187 
00188    /* 
00189     * search for sip digest username in H.350, store digest password
00190     */
00191    
00192    /* ldap filter escape digest username */
00193    digest_username_escaped.s = digest_username_buf;
00194    digest_username_escaped.len = DIGEST_USERNAME_BUF_SIZE - 1;
00195    if (ldap_api.ldap_rfc4515_escape(
00196       &digest_username, 
00197       &digest_username_escaped, 
00198       0)
00199       )
00200         {
00201                 LM_ERR("ldap_rfc4515_escape() failed\n");
00202                 return E_H350_INTERNAL;
00203         }
00204 
00205    /* do ldap search */
00206    if (ldap_api.ldap_params_search(&ld_result_count,
00207                                         h350_ldap_session.s,
00208                                         h350_base_dn.s,
00209                                         h350_search_scope_int,
00210                                         NULL,
00211                                         H350_AUTH_FILTER_PATTERN,
00212                                         digest_username_escaped.s)
00213             != 0)
00214         {
00215                 LM_ERR("LDAP search failed\n");
00216       return E_H350_INTERNAL;
00217         }
00218 
00219    if (ld_result_count < 1)
00220    {
00221       LM_INFO("no H.350 entry found for username [%s]\n",
00222          digest_username_escaped.s);
00223       return E_H350_NO_SUCCESS;
00224    }
00225    if (ld_result_count > 1)
00226    {
00227       LM_WARN("more than one [%d] H.350 entry found for username [%s]\n",
00228          ld_result_count,
00229          digest_username_escaped.s);
00230    }
00231 
00232    /* get ldap result values */
00233    rc = ldap_api.ldap_result_attr_vals(&h350_sip_pwd_name, &attr_vals);
00234    if (rc < 0) 
00235    {
00236                 LM_ERR("getting LDAP attribute values failed\n");
00237                 ldap_api.ldap_value_free_len(attr_vals);
00238       return E_H350_INTERNAL;
00239         }
00240         if ((rc > 0) || (attr_vals == NULL)) 
00241    {
00242                 LM_INFO("no values found in LDAP entry for username [%s]\n",
00243          digest_username_escaped.s);
00244       ldap_api.ldap_value_free_len(attr_vals);
00245       return E_H350_INTERNAL;
00246         }
00247 
00248    digest_password.s = attr_vals[0]->bv_val;
00249         digest_password.len = attr_vals[0]->bv_len;
00250 
00251    /*
00252     * write AVPs
00253     */
00254    
00255    avp_val.s = digest_username;
00256    if (add_avp(   username_avp_type | AVP_VAL_STR, 
00257          username_avp_name, 
00258          avp_val) 
00259       < 0)
00260    {
00261       LM_ERR("failed to create new AVP\n");
00262       ldap_api.ldap_value_free_len(attr_vals);
00263       return E_H350_INTERNAL;
00264    }
00265 
00266    avp_val.s = digest_password;
00267    if (add_avp(    password_avp_type | AVP_VAL_STR,
00268                         password_avp_name,
00269                         avp_val)
00270                 < 0)
00271         {
00272                 LM_ERR("failed to create new AVP\n");
00273                 ldap_api.ldap_value_free_len(attr_vals);
00274                 return E_H350_INTERNAL;
00275         }
00276 
00277    ldap_api.ldap_value_free_len(attr_vals);
00278    return E_H350_SUCCESS;
00279 }
00280 
00281 int h350_call_preferences(struct sip_msg* _msg, pv_elem_t* _avp_name_prefix)
00282 {
00283    int           rc, i, avp_count = 0;
00284    struct berval **attr_vals;
00285    size_t        nmatch = 5;
00286    regmatch_t    pmatch[5];
00287    int_str       avp_name, avp_val;
00288    str           avp_val_str, avp_name_str, 
00289                  avp_name_prefix_str, call_pref_timeout_str;
00290    int           call_pref_timeout;
00291    static char   call_pref_avp_name[AVP_NAME_STR_BUF_LEN];
00292 
00293         /*
00294          * get avp_name_prefix_str
00295          */
00296         if (pv_printf_s(_msg, _avp_name_prefix, &avp_name_prefix_str) != 0)
00297         {
00298                 LM_ERR("pv_printf_s failed\n");
00299                 return E_H350_INTERNAL;
00300         }
00301 
00302    
00303    /*
00304     * get LDAP attribute values
00305     */
00306    if ((rc = ldap_api.ldap_result_attr_vals(
00307          &h350_call_pref_name, &attr_vals)) < 0)
00308    {
00309       LM_ERR("Getting LDAP attribute values failed\n");
00310       return E_H350_INTERNAL;
00311    }
00312 
00313    if (rc > 0)
00314    {
00315       /* no LDAP values found */
00316       return E_H350_NO_SUCCESS;
00317    }
00318 
00319    /*
00320     * loop through call pref values and add AVP(s)
00321     */
00322 
00323    /* copy avp name prefix into call_pref_avp_name */
00324    if (avp_name_prefix_str.len < AVP_NAME_STR_BUF_LEN)
00325    {
00326       memcpy(call_pref_avp_name, avp_name_prefix_str.s, avp_name_prefix_str.len);
00327    } else
00328    {
00329       LM_ERR("AVP name prefix too long [%d] (max [%d])", 
00330          avp_name_prefix_str.len, 
00331          AVP_NAME_STR_BUF_LEN);
00332       return E_H350_INTERNAL;
00333    }
00334 
00335    for (i = 0; attr_vals[i] != NULL; i++)
00336    {
00337       if ((rc = regexec(call_pref_preg, attr_vals[i]->bv_val, nmatch, pmatch, 0)) != 0)
00338       {
00339          switch (rc)
00340          {
00341          case REG_NOMATCH:
00342             LM_INFO("no h350 call preference regex match for [%s]\n", 
00343                   attr_vals[i]->bv_val);
00344             continue;
00345          case REG_ESPACE:
00346             LM_ERR("regexec returned REG_ESPACE - out of memory\n");
00347          default:
00348             LM_ERR("regexec failed\n");
00349             ldap_api.ldap_value_free_len(attr_vals);
00350             return E_H350_INTERNAL;
00351          }
00352       }
00353 
00354       /* calculate call preference sip uri */
00355       if (avp_name_prefix_str.len + pmatch[2].rm_eo - pmatch[2].rm_so 
00356          >= AVP_NAME_STR_BUF_LEN)
00357       {
00358          LM_ERR("AVP name too long for [%s]", attr_vals[i]->bv_val);
00359          continue;
00360       }
00361       avp_val_str.s = attr_vals[i]->bv_val + pmatch[1].rm_so;
00362       avp_val_str.len = pmatch[1].rm_eo - pmatch[1].rm_so;
00363 
00364       avp_val.s = avp_val_str;
00365       
00366       /* calculate call preference avp name */
00367       memcpy(  call_pref_avp_name + avp_name_prefix_str.len, 
00368          attr_vals[i]->bv_val + pmatch[2].rm_so,
00369          pmatch[2].rm_eo - pmatch[2].rm_so);
00370 
00371       avp_name_str.s = call_pref_avp_name;
00372       avp_name_str.len = avp_name_prefix_str.len + pmatch[2].rm_eo - pmatch[2].rm_so;
00373 
00374       avp_name.s = avp_name_str;
00375       
00376       /* add avp */
00377       if (add_avp(AVP_NAME_STR | AVP_VAL_STR, avp_name, avp_val) < 0)
00378       {
00379          LM_ERR("failed to create new AVP\n");
00380          ldap_api.ldap_value_free_len(attr_vals);
00381          return E_H350_INTERNAL;
00382       }
00383 
00384       avp_count++;
00385       
00386       /* check for call preference timeout */
00387       if ((pmatch[4].rm_eo - pmatch[4].rm_so) == 0)
00388       {
00389          continue;
00390       }
00391       
00392       /* calculate call preference timeout avp name */
00393       memcpy(  avp_name_str.s + avp_name_str.len, "_t", 2);
00394       avp_name_str.len += 2;
00395       avp_name.s = avp_name_str;
00396 
00397       /* calculate timeout avp value */
00398       call_pref_timeout_str.s = attr_vals[i]->bv_val + pmatch[4].rm_so;
00399       call_pref_timeout_str.len = pmatch[4].rm_eo - pmatch[4].rm_so;
00400       if (str2sint(&call_pref_timeout_str, &call_pref_timeout) != 0)
00401       {
00402          LM_ERR("str2sint failed\n");
00403          ldap_api.ldap_value_free_len(attr_vals);
00404          return E_H350_INTERNAL;
00405       }
00406       call_pref_timeout = call_pref_timeout / 1000;
00407 
00408       /* add timeout avp */
00409       avp_val.n = call_pref_timeout;
00410       if (add_avp(AVP_NAME_STR, avp_name, avp_val) < 0)
00411       {
00412               LM_ERR("failed to create new AVP\n");
00413          ldap_api.ldap_value_free_len(attr_vals);
00414                         return E_H350_INTERNAL;
00415       }     
00416    }
00417 
00418    ldap_api.ldap_value_free_len(attr_vals);
00419    if (avp_count > 0)
00420    {
00421       return avp_count;
00422    } else 
00423    {
00424       return E_H350_NO_SUCCESS;
00425    }
00426 }
00427 
00428 int h350_service_level(struct sip_msg* _msg, pv_elem_t* _avp_name_prefix)
00429 {
00430    int           i, rc, avp_count = 0;
00431         str           avp_name_prefix;
00432    int_str       avp_name, avp_val;
00433    struct berval **attr_vals;
00434    static char   service_level_avp_name[AVP_NAME_STR_BUF_LEN];
00435 
00436         /*
00437          * get service_level
00438          */
00439         if (pv_printf_s(_msg, _avp_name_prefix, &avp_name_prefix) != 0)
00440         {
00441                 LM_ERR("pv_printf_s failed\n");
00442                 return E_H350_INTERNAL;
00443         }
00444 
00445         /*
00446          * get LDAP attribute values
00447          */
00448         if ((rc = ldap_api.ldap_result_attr_vals(&h350_service_level_name, &attr_vals)) < 0)
00449         {
00450                 LM_ERR("Getting LDAP attribute values failed\n");
00451                 return E_H350_INTERNAL;
00452         }
00453         if (rc > 0)
00454         {
00455                 /* no LDAP values found */
00456                 return E_H350_NO_SUCCESS;
00457         }
00458 
00459         /* copy avp name prefix into service_level_avp_name */
00460         if (avp_name_prefix.len < AVP_NAME_STR_BUF_LEN)
00461         {
00462                 memcpy(service_level_avp_name, avp_name_prefix.s, avp_name_prefix.len);
00463         } else
00464         {
00465                 LM_ERR("AVP name prefix too long [%d] (max [%d])\n",
00466                         avp_name_prefix.len,
00467                         AVP_NAME_STR_BUF_LEN);
00468       ldap_api.ldap_value_free_len(attr_vals);
00469                 return E_H350_INTERNAL;
00470         }   
00471    
00472 
00473    /*
00474     * loop through service level values and add AVP(s)
00475     */
00476 
00477    for (i = 0; attr_vals[i] != NULL; i++)
00478    {
00479       /* get avp name */
00480       if (avp_name_prefix.len + attr_vals[i]->bv_len >= AVP_NAME_STR_BUF_LEN)
00481       {
00482          LM_ERR("AVP name too long for [%s]\n", attr_vals[i]->bv_val);
00483          continue;
00484       }
00485       memcpy(  service_level_avp_name + avp_name_prefix.len, 
00486          attr_vals[i]->bv_val,
00487          attr_vals[i]->bv_len);
00488       avp_name.s.s = service_level_avp_name;
00489       avp_name.s.len = avp_name_prefix.len + attr_vals[i]->bv_len;
00490       
00491       /* avp value = 1 */
00492       avp_val.n = 1;
00493 
00494                 if (add_avp(AVP_NAME_STR, avp_name, avp_val) < 0)
00495                 {
00496                         LM_ERR("failed to create new AVP\n");
00497                         ldap_api.ldap_value_free_len(attr_vals);
00498                         return E_H350_INTERNAL;
00499                 }
00500       avp_count++;
00501    }
00502 
00503    ldap_api.ldap_value_free_len(attr_vals);
00504    if (avp_count > 0)
00505         {
00506                 return avp_count;
00507         } else
00508         {
00509                 return E_H350_NO_SUCCESS;
00510         }
00511 }
00512 
00513 int h350_exp_fn_init(void)
00514 {
00515    int rc;
00516 
00517    if ((call_pref_preg = pkg_malloc(sizeof(regex_t))) == 0)
00518    {
00519       LM_ERR("allocating memory for regex failed\n");
00520       return -1;
00521    }
00522 
00523    if ((rc = regcomp(call_pref_preg, H350_CALL_PREF_REGEX, REG_EXTENDED)) != 0)
00524    {
00525       pkg_free(call_pref_preg);
00526       LM_ERR("regcomp failed - returned [%d]\n", rc);
00527       return -1;
00528    }
00529    return 0;
00530 }

Generated on Wed May 23 06:00:45 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6