modules/siputils/rpid.c
31ccf6a2
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
27642a08
  * This file is part of Kamailio, a free SIP server.
31ccf6a2
  *
27642a08
  * Kamailio is free software; you can redistribute it and/or modify
31ccf6a2
  * 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
  *
27642a08
  * Kamailio is distributed in the hope that it will be useful,
31ccf6a2
  * 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 
9e1ff448
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
31ccf6a2
  *
  */
 
fc54405e
 /*!
  * \file
  * \brief Remote-Party-ID related functions
  * \ingroup auth
  * - Module: \ref auth
  */
 
31ccf6a2
 #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"
b0a7f212
 #include "../../pvar.h"
31ccf6a2
 #include "rpid.h"
 
 
 #define RPID_HF_NAME "Remote-Party-ID: "
 #define RPID_HF_NAME_LEN (sizeof(RPID_HF_NAME) - 1)
 
90763a85
 extern str rpid_prefix;       /*!< Remote-Party-ID prefix */
 extern str rpid_suffix;       /*!< Remote-Party-ID suffix */
 
31ccf6a2
 /* rpid AVP specs */
cdece58c
 static unsigned short rpid_avp_type;
 static int_str rpid_avp_name;
31ccf6a2
 
 
fc54405e
 /*!
  * \brief Parse and set the RPID AVP specs
  * \param rpid_avp_param RPID AVP parameter
  * \return 0 on success, -1 on failure
31ccf6a2
  */
 int init_rpid_avp(char *rpid_avp_param)
 {
b0a7f212
 	pv_spec_t avp_spec;
 	str stmp;
31ccf6a2
 	if (rpid_avp_param && *rpid_avp_param) {
b0a7f212
 		stmp.s = rpid_avp_param; stmp.len = strlen(stmp.s);
 		if (pv_parse_spec(&stmp, &avp_spec)==0
 				|| avp_spec.type!=PVT_AVP) {
789504a6
 			LM_ERR("malformed or non AVP %s AVP definition\n", rpid_avp_param);
cdece58c
 			return -1;
 		}
 
b0a7f212
 		if(pv_get_avp_name(0, &(avp_spec.pvp), &rpid_avp_name,
 					&rpid_avp_type)!=0)
cdece58c
 		{
789504a6
 			LM_ERR("[%s]- invalid AVP definition\n", rpid_avp_param);
31ccf6a2
 			return -1;
 		}
4daf42dc
 	} else {
cdece58c
 		rpid_avp_name.n = 0;
4daf42dc
 		rpid_avp_type = 0;
31ccf6a2
 	}
cdece58c
 
31ccf6a2
 	return 0;
 }
 
 
fc54405e
 /*!
  * \brief Gets the RPID avp specs
  * \param rpid_avp_p AVP name
  * \param rpid_avp_type_p AVP type
31ccf6a2
  */
 void get_rpid_avp( int_str *rpid_avp_p, int *rpid_avp_type_p )
 {
cdece58c
 	*rpid_avp_p = rpid_avp_name;
31ccf6a2
 	*rpid_avp_type_p = rpid_avp_type;
 }
 
 
fc54405e
 /*!
  * \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
31ccf6a2
  */
 static inline int is_e164(str* _user)
 {
 	int i;
 	char c;
 	
 	if ((_user->len > 2) && (_user->len < 17) && ((_user->s)[0] == '+')) {
66803efa
 		for (i = 1; i < _user->len; i++) {
31ccf6a2
 			c = (_user->s)[i];
66803efa
 			if ((c < '0') || (c > '9')) return -1;
31ccf6a2
 		}
 		return 1;
66803efa
 	} else {
 	    return -1;
31ccf6a2
 	}
 }
 
 
fc54405e
 /*!
  * \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
31ccf6a2
  */
 static inline int append_rpid_helper(struct sip_msg* _m, str *_s)
 {
 	struct lump* anchor;
 	
b68fbcd1
 	if (parse_headers(_m, HDR_EOH_F, 0) == -1) {
789504a6
 		LM_ERR("failed to parse message\n");
31ccf6a2
 		return -1;
 	}
 	
 	anchor = anchor_lump(_m, _m->unparsed - _m->buf, 0, 0);
 	if (!anchor) {
789504a6
 		LM_ERR("can't get anchor\n");
31ccf6a2
 		return -2;
 	}
 	
 	if (!insert_new_lump_before(anchor, _s->s, _s->len, 0)) {
789504a6
 		LM_ERR("can't insert lump\n");
31ccf6a2
 		return -3;
 	}
 
 	return 0;
 }
 
 
fc54405e
 /*!
  * \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
31ccf6a2
  */
 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;
 
cdece58c
 	if (rpid_avp_name.n==0) {
789504a6
 		LM_ERR("rpid avp not defined\n");
31ccf6a2
 		return -1;
 	}
 
cdece58c
 	if ( (avp=search_first_avp( rpid_avp_type , rpid_avp_name, &val, 0))==0 ) {
789504a6
 		LM_DBG("no rpid AVP\n");
31ccf6a2
 		return -1;
 	}
 
2e017606
 	if ( !(avp->flags&AVP_VAL_STR) ||  !val.s.s || !val.s.len) {
789504a6
 		LM_DBG("empty or non-string rpid, nothing to append\n");
31ccf6a2
 		return -1;
 	}
 
2e017606
 	rpid = val.s;
31ccf6a2
 
2e017606
 	rpid_hf.len = RPID_HF_NAME_LEN + rpid_prefix.len + rpid.len
 					+ rpid_suffix.len + CRLF_LEN;
31ccf6a2
 	rpid_hf.s = pkg_malloc(rpid_hf.len);
 	if (!rpid_hf.s) {
789504a6
 		LM_ERR("no memory left\n");
31ccf6a2
 		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;
 }
 
 
fc54405e
 /*!
  * \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
31ccf6a2
  */
 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;
 
cdece58c
 	if (rpid_avp_name.n==0) {
789504a6
 		LM_ERR("rpid avp not defined\n");
31ccf6a2
 		return -1;
 	}
 
cdece58c
 	if ( (avp=search_first_avp( rpid_avp_type , rpid_avp_name, &val, 0))==0 ) {
789504a6
 		LM_DBG("no rpid AVP\n");
31ccf6a2
 		return -1;
 	}
 
2e017606
 	if ( !(avp->flags&AVP_VAL_STR) ||  !val.s.s || !val.s.len) {
789504a6
 		LM_DBG("empty or non-string rpid, nothing to append\n");
31ccf6a2
 		return -1;
 	}
 
2e017606
 	rpid = val.s;
31ccf6a2
 
 	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) {
789504a6
 		LM_ERR("no pkg memory left\n");
31ccf6a2
 		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;
 }
 
 
fc54405e
 /*!
  * \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
31ccf6a2
  */
 int is_rpid_user_e164(struct sip_msg* _m, char* _s1, char* _s2)
 {
 	struct usr_avp *avp;
 	name_addr_t parsed;
9de51327
 	str tmp, rpid;
31ccf6a2
 	struct sip_uri uri;
 	int_str val;
 
cdece58c
 	if (rpid_avp_name.n==0) {
789504a6
 		LM_ERR("rpid avp not defined\n");
31ccf6a2
 		return -1;
 	}
 
cdece58c
 	if ( (avp=search_first_avp( rpid_avp_type , rpid_avp_name, &val, 0))==0 ) {
789504a6
 		LM_DBG("no rpid AVP\n");
31ccf6a2
 		goto err;
 	}
 
2e017606
 	if ( !(avp->flags&AVP_VAL_STR) ||  !val.s.s || !val.s.len) {
789504a6
 		LM_DBG("empty or non-string rpid, nothing to append\n");
31ccf6a2
 		return -1;
 	}
 
2e017606
 	rpid = val.s;
31ccf6a2
 
 	if (find_not_quoted(&rpid, '<')) {
 		if (parse_nameaddr(&rpid, &parsed) < 0) {
789504a6
 			LM_ERR("failed to parse RPID\n");
31ccf6a2
 			goto err;
 		}
 		tmp = parsed.uri;
 	} else {
 		tmp = rpid;
 	}
 
9de51327
 	if (parse_uri(tmp.s, tmp.len, &uri) < 0) {
 	    LM_ERR("failed to parse RPID URI\n");
 	    goto err;
31ccf6a2
 	}
 
9de51327
 	return is_e164(&uri.user);
 
31ccf6a2
 err:
 	return -1;
 }