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/ims_icscf/nds.c

223 lines
6.7 KiB

/*
* $Id$
*
* Copyright (C) 2012 Smile Communications, jason.penton@smilecoms.com
* Copyright (C) 2012 Smile Communications, richard.good@smilecoms.com
*
* The initial version of this code was written by Dragos Vingarzan
* (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
* Fruanhofer Institute. It was and still is maintained in a separate
* branch of the original SER. We are therefore migrating it to
* Kamailio/SR and look forward to maintaining it from here on out.
* 2011/2012 Smile Communications, Pty. Ltd.
* ported/maintained/improved by
* Jason Penton (jason(dot)penton(at)smilecoms.com and
* Richard Good (richard(dot)good(at)smilecoms.com) as part of an
* effort to add full IMS support to Kamailio/SR using a new and
* improved architecture
*
* NB: Alot of this code was originally part of OpenIMSCore,
* FhG Fokus.
* Copyright (C) 2004-2006 FhG Fokus
* Thanks for great work! This is an effort to
* break apart the various CSCF functions into logically separate
* components. We hope this will drive wider use. We also feel
* that in this way the architecture is more complete and thereby easier
* to manage in the Kamailio/SR environment
*
* 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
*
* Interrogating-CSCF - Network Domain Security Operations
*
* \author Dragos Vingarzan vingarzan -at- fokus dot fraunhofer dot de
*
*/
#include "nds.h"
#include "../../parser/hf.h"
#include "../../parser/msg_parser.h"
#include "../../parser/parse_via.h"
#include "../../mem/shm_mem.h"
#include "../../modules/sl/sl.h"
#include "mod.h"
#include "db.h"
extern sl_api_t slb;
static str str_msg_403 = {MSG_403, 9};
static str str_msg_500 = {MSG_500, 46};
/** Defines the untrusted headers */
str untrusted_headers[]={
{"P-Asserted-Identity",19},
{"P-Access-Network-Info",21},
{"P-Charging-Vector",17},
{"P-Charging-Function-Addresses",29},
{0,0}
};
/** The cached list of trusted domains */
static str *trusted_domains=0;
/**
* Checks if a request comes from a trusted domain.
* If not calls function to respond with 403 to REGISTER or clean the message of
* untrusted headers
* @param msg - the SIP message
* @param str1 - not used
* @param str2 - not used
* @returns #CSCF_RETURN_TRUE if trusted, #CSCF_RETURN_FALSE if not , #CSCF_RETURN_ERROR on REGISTER or error
*/
int I_NDS_check_trusted(struct sip_msg* msg, char* str1, char* str2)
{
int result;
LM_DBG("DBG:I_NDS_check_trusted: Starting ...\n");
if (msg->first_line.type!=SIP_REQUEST) {
LM_ERR("ERR:I_NDS_check_trusted: The message is not a request\n");
result = CSCF_RETURN_TRUE;
goto done;
}
if (I_NDS_is_trusted(msg,str1,str2)){
LM_DBG("INF:I_NDS_check_trusted: Message comes from a trusted domain\n");
result = CSCF_RETURN_TRUE;
goto done;
} else {
LM_DBG("INF:I_NDS_check_trusted: Message comes from an untrusted domain\n");
result = CSCF_RETURN_FALSE;
if (msg->first_line.u.request.method.len==8 &&
memcmp(msg->first_line.u.request.method.s,"REGISTER",8)==0){
slb.sreply(msg,403,&str_msg_403);
LM_DBG("INF:I_NDS_check_trusted: REGISTER request terminated.\n");
} else {
if (!I_NDS_strip_headers(msg,str1,str2)){
result = CSCF_RETURN_ERROR;
slb.sreply(msg,500,&str_msg_500);
LM_DBG("INF:I_NDS_check_trusted: Stripping untrusted headers failed, Responding with 500.\n");
}
}
}
done:
LM_DBG("DBG:I_NDS_check_trusted: ... Done\n");
return result;
}
/**
* Decides if a message comes from a trusted domain.
* \todo - SOLVE THE LOCKING PROBLEM - THIS IS A READER
* @param msg - the SIP request message
* @param str1 - not used
* @param str2 - not used
* @returns #CSCF_RETURN_TRUE if trusted, #CSCF_RETURN_FALSE
*/
int I_NDS_is_trusted(struct sip_msg *msg, char* str1, char* str2)
{
struct via_body *vb;
str subdomain;
int i;
vb = msg->via1;
if (!vb) {
LM_ERR("ERR:I_NDS_is_trusted: Error VIA1 hdr not found\n");
return 0;
}
subdomain=vb->host;
LM_DBG("DBG:I_NDS_is_trusted: Message comes from <%.*s>\n",
subdomain.len,subdomain.s);
i=0;
while(trusted_domains[i].len){
if (trusted_domains[i].len<=subdomain.len){
if (strncasecmp(subdomain.s+subdomain.len-trusted_domains[i].len,
trusted_domains[i].s,
trusted_domains[i].len)==0 &&
(trusted_domains[i].len==subdomain.len ||
subdomain.s[subdomain.len-trusted_domains[i].len-1]=='.'))
{
LM_DBG("DBG:I_NDS_is_trusted: <%.*s> matches <%.*s>\n",
subdomain.len,subdomain.s,trusted_domains[i].len,trusted_domains[i].s);
return CSCF_RETURN_TRUE;
} else {
// LM_DBG("DBG:I_NDS_is_trusted: <%.*s> !matches <%.*s>\n",
// subdomain.len,subdomain.s,trusted_domains[i].len,trusted_domains[i].s);
}
}
i++;
}
return CSCF_RETURN_FALSE;
}
/**
* Strips untrusty headers from a SIP request.
* Searched headers are declared in untrusted_headers
* @param msg - the SIP request message
* @param str1 - not used
* @param str2 - not used
* @returns the number of headers stripped
*/
int I_NDS_strip_headers(struct sip_msg *msg, char* str1, char* str2)
{
struct hdr_field *hdr;
int i,cnt=0;
if (parse_headers(msg,HDR_EOH_F,0)<0) return 0;
for (hdr = msg->headers;hdr;hdr = hdr->next)
for (i=0;untrusted_headers[i].len;i++)
if (hdr->name.len == untrusted_headers[i].len &&
strncasecmp(hdr->name.s,untrusted_headers[i].s,hdr->name.len)==0){
//if (!cscf_del_header(msg,hdr)) return 0; TODO
cnt++;
}
LM_DBG("DBG:I_NDS_strip_headers: Deleted %d headers\n",cnt);
return cnt;
}
/**
* Refreshes the trusted domain list reading them from the db.
* Drops the old cache and queries the db
* \todo - IMPLEMENT A WAY TO PUSH AN EXTERNAL EVENT FOR THIS
* \todo - SOLVE THE LOCKING PROBLEM - THIS IS A WRITER
* @returns 1 on success, 0 on failure
*/
int I_NDS_get_trusted_domains()
{
int i;
/* free the old cache */
if (trusted_domains!=0){
i=0;
while(trusted_domains[i].s){
shm_free(trusted_domains[i].s);
i++;
}
shm_free(trusted_domains);
}
return ims_icscf_db_get_nds(&trusted_domains);
}