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.
334 lines
7.0 KiB
334 lines
7.0 KiB
/*
|
|
* Copyright (C) 2001-2003 FhG Fokus
|
|
*
|
|
* 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
|
|
*
|
|
*/
|
|
|
|
/*!
|
|
* \file
|
|
* \brief Remote-Party-ID related functions
|
|
* \ingroup auth
|
|
* - Module: \ref auth
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <strings.h>
|
|
#include "../../str.h"
|
|
#include "../../data_lump.h"
|
|
#include "../../dprint.h"
|
|
#include "../../mem/mem.h"
|
|
#include "../../parser/parse_nameaddr.h"
|
|
#include "../../parser/parse_uri.h"
|
|
#include "../../parser/parser_f.h"
|
|
#include "../../ut.h"
|
|
#include "../../pvar.h"
|
|
#include "rpid.h"
|
|
|
|
|
|
#define RPID_HF_NAME "Remote-Party-ID: "
|
|
#define RPID_HF_NAME_LEN (sizeof(RPID_HF_NAME) - 1)
|
|
|
|
extern str rpid_prefix; /*!< Remote-Party-ID prefix */
|
|
extern str rpid_suffix; /*!< Remote-Party-ID suffix */
|
|
|
|
/* rpid AVP specs */
|
|
static unsigned short rpid_avp_type;
|
|
static int_str rpid_avp_name;
|
|
|
|
|
|
/*!
|
|
* \brief Parse and set the RPID AVP specs
|
|
* \param rpid_avp_param RPID AVP parameter
|
|
* \return 0 on success, -1 on failure
|
|
*/
|
|
int init_rpid_avp(char *rpid_avp_param)
|
|
{
|
|
pv_spec_t avp_spec;
|
|
str stmp;
|
|
if (rpid_avp_param && *rpid_avp_param) {
|
|
stmp.s = rpid_avp_param; stmp.len = strlen(stmp.s);
|
|
if (pv_parse_spec(&stmp, &avp_spec)==0
|
|
|| avp_spec.type!=PVT_AVP) {
|
|
LM_ERR("malformed or non AVP %s AVP definition\n", rpid_avp_param);
|
|
return -1;
|
|
}
|
|
|
|
if(pv_get_avp_name(0, &(avp_spec.pvp), &rpid_avp_name,
|
|
&rpid_avp_type)!=0)
|
|
{
|
|
LM_ERR("[%s]- invalid AVP definition\n", rpid_avp_param);
|
|
return -1;
|
|
}
|
|
} else {
|
|
rpid_avp_name.n = 0;
|
|
rpid_avp_type = 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*!
|
|
* \brief Gets the RPID avp specs
|
|
* \param rpid_avp_p AVP name
|
|
* \param rpid_avp_type_p AVP type
|
|
*/
|
|
void get_rpid_avp( int_str *rpid_avp_p, int *rpid_avp_type_p )
|
|
{
|
|
*rpid_avp_p = rpid_avp_name;
|
|
*rpid_avp_type_p = rpid_avp_type;
|
|
}
|
|
|
|
|
|
/*!
|
|
* \brief Check if user is a E164 number
|
|
* \param _user user
|
|
* \note Copy of is_e164 from enum module
|
|
* \return 1 if its a E164 number, -1 if not
|
|
*/
|
|
static inline int is_e164(str* _user)
|
|
{
|
|
int i;
|
|
char c;
|
|
|
|
if ((_user->len > 2) && (_user->len < 17) && ((_user->s)[0] == '+')) {
|
|
for (i = 1; i < _user->len; i++) {
|
|
c = (_user->s)[i];
|
|
if ((c < '0') || (c > '9')) return -1;
|
|
}
|
|
return 1;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
/*!
|
|
* \brief Append RPID helper function
|
|
* \param _m SIP message
|
|
* \param _s appended string
|
|
* \note Copy of append_hf_helper from textops
|
|
* \return 0 on success, negative on failure
|
|
*/
|
|
static inline int append_rpid_helper(struct sip_msg* _m, str *_s)
|
|
{
|
|
struct lump* anchor;
|
|
|
|
if (parse_headers(_m, HDR_EOH_F, 0) == -1) {
|
|
LM_ERR("failed to parse message\n");
|
|
return -1;
|
|
}
|
|
|
|
anchor = anchor_lump(_m, _m->unparsed - _m->buf, 0, 0);
|
|
if (!anchor) {
|
|
LM_ERR("can't get anchor\n");
|
|
return -2;
|
|
}
|
|
|
|
if (!insert_new_lump_before(anchor, _s->s, _s->len, 0)) {
|
|
LM_ERR("can't insert lump\n");
|
|
return -3;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*!
|
|
* \brief Append RPID header field to the message
|
|
* \param _m SIP message
|
|
* \param _s1 unused
|
|
* \param _s2 unused
|
|
* \return 1 on success, -1 on failure
|
|
*/
|
|
int append_rpid_hf(struct sip_msg* _m, char* _s1, char* _s2)
|
|
{
|
|
struct usr_avp *avp;
|
|
str rpid_hf, rpid;
|
|
char *at;
|
|
int_str val;
|
|
|
|
if (rpid_avp_name.n==0) {
|
|
LM_ERR("rpid avp not defined\n");
|
|
return -1;
|
|
}
|
|
|
|
if ( (avp=search_first_avp( rpid_avp_type , rpid_avp_name, &val, 0))==0 ) {
|
|
LM_DBG("no rpid AVP\n");
|
|
return -1;
|
|
}
|
|
|
|
if ( !(avp->flags&AVP_VAL_STR) || !val.s.s || !val.s.len) {
|
|
LM_DBG("empty or non-string rpid, nothing to append\n");
|
|
return -1;
|
|
}
|
|
|
|
rpid = val.s;
|
|
|
|
rpid_hf.len = RPID_HF_NAME_LEN + rpid_prefix.len + rpid.len
|
|
+ rpid_suffix.len + CRLF_LEN;
|
|
rpid_hf.s = pkg_malloc(rpid_hf.len);
|
|
if (!rpid_hf.s) {
|
|
LM_ERR("no memory left\n");
|
|
return -1;
|
|
}
|
|
|
|
at = rpid_hf.s;
|
|
memcpy(at, RPID_HF_NAME, RPID_HF_NAME_LEN);
|
|
at += RPID_HF_NAME_LEN;
|
|
|
|
memcpy(at, rpid_prefix.s, rpid_prefix.len);
|
|
at += rpid_prefix.len;
|
|
|
|
memcpy(at, rpid.s, rpid.len);
|
|
at += rpid.len;
|
|
|
|
memcpy(at, rpid_suffix.s, rpid_suffix.len);
|
|
at += rpid_suffix.len;
|
|
|
|
memcpy(at, CRLF, CRLF_LEN);
|
|
|
|
if (append_rpid_helper(_m, &rpid_hf) < 0) {
|
|
pkg_free(rpid_hf.s);
|
|
return -1;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
/*!
|
|
* \brief Append RPID header field to the message with parameters
|
|
* \param _m SIP message
|
|
* \param _prefix prefix
|
|
* \param _suffix suffix
|
|
* \return 1 on success, -1 on failure
|
|
*/
|
|
int append_rpid_hf_p(struct sip_msg* _m, char* _prefix, char* _suffix)
|
|
{
|
|
struct usr_avp *avp;
|
|
str rpid_hf, rpid;
|
|
char* at;
|
|
str* p, *s;
|
|
int_str val;
|
|
|
|
if (rpid_avp_name.n==0) {
|
|
LM_ERR("rpid avp not defined\n");
|
|
return -1;
|
|
}
|
|
|
|
if ( (avp=search_first_avp( rpid_avp_type , rpid_avp_name, &val, 0))==0 ) {
|
|
LM_DBG("no rpid AVP\n");
|
|
return -1;
|
|
}
|
|
|
|
if ( !(avp->flags&AVP_VAL_STR) || !val.s.s || !val.s.len) {
|
|
LM_DBG("empty or non-string rpid, nothing to append\n");
|
|
return -1;
|
|
}
|
|
|
|
rpid = val.s;
|
|
|
|
p = (str*)_prefix;
|
|
s = (str*)_suffix;
|
|
|
|
rpid_hf.len = RPID_HF_NAME_LEN + p->len + rpid.len + s->len + CRLF_LEN;
|
|
rpid_hf.s = pkg_malloc(rpid_hf.len);
|
|
if (!rpid_hf.s) {
|
|
LM_ERR("no pkg memory left\n");
|
|
return -1;
|
|
}
|
|
|
|
at = rpid_hf.s;
|
|
memcpy(at, RPID_HF_NAME, RPID_HF_NAME_LEN);
|
|
at += RPID_HF_NAME_LEN;
|
|
|
|
memcpy(at, p->s, p->len);
|
|
at += p->len;
|
|
|
|
memcpy(at, rpid.s, rpid.len);
|
|
at += rpid.len;
|
|
|
|
memcpy(at, s->s, s->len);
|
|
at += s->len;
|
|
|
|
memcpy(at, CRLF, CRLF_LEN);
|
|
|
|
if (append_rpid_helper(_m, &rpid_hf) < 0) {
|
|
pkg_free(rpid_hf.s);
|
|
return -1;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
/*!
|
|
* \brief Check if URI in RPID AVP contains an E164 user part
|
|
* \param _m SIP message
|
|
* \param _s1 unused
|
|
* \param _s2 unused
|
|
* \return 1 if the URI contains an E164 user part, -1 if not
|
|
*/
|
|
int is_rpid_user_e164(struct sip_msg* _m, char* _s1, char* _s2)
|
|
{
|
|
struct usr_avp *avp;
|
|
name_addr_t parsed;
|
|
str tmp, rpid;
|
|
struct sip_uri uri;
|
|
int_str val;
|
|
|
|
if (rpid_avp_name.n==0) {
|
|
LM_ERR("rpid avp not defined\n");
|
|
return -1;
|
|
}
|
|
|
|
if ( (avp=search_first_avp( rpid_avp_type , rpid_avp_name, &val, 0))==0 ) {
|
|
LM_DBG("no rpid AVP\n");
|
|
goto err;
|
|
}
|
|
|
|
if ( !(avp->flags&AVP_VAL_STR) || !val.s.s || !val.s.len) {
|
|
LM_DBG("empty or non-string rpid, nothing to append\n");
|
|
return -1;
|
|
}
|
|
|
|
rpid = val.s;
|
|
|
|
if (find_not_quoted(&rpid, '<')) {
|
|
if (parse_nameaddr(&rpid, &parsed) < 0) {
|
|
LM_ERR("failed to parse RPID\n");
|
|
goto err;
|
|
}
|
|
tmp = parsed.uri;
|
|
} else {
|
|
tmp = rpid;
|
|
}
|
|
|
|
if (parse_uri(tmp.s, tmp.len, &uri) < 0) {
|
|
LM_ERR("failed to parse RPID URI\n");
|
|
goto err;
|
|
}
|
|
|
|
return is_e164(&uri.user);
|
|
|
|
err:
|
|
return -1;
|
|
}
|
|
|