123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- /*
- * ser osp module.
- *
- * This module enables ser to communicate with an Open Settlement
- * Protocol (OSP) server. The Open Settlement Protocol is an ETSI
- * defined standard for Inter-Domain VoIP pricing, authorization
- * and usage exchange. The technical specifications for OSP
- * (ETSI TS 101 321 V4.1.1) are available at www.etsi.org.
- *
- * Uli Abend was the original contributor to this module.
- *
- * Copyright (C) 2001-2005 Fhg Fokus
- *
- * This file is part of ser, a free SIP server.
- *
- * ser 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
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- * [email protected]
- *
- * ser 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 "osp_mod.h"
- #include "term_transaction.h"
- #include "sipheader.h"
- #include "destination.h"
- #include "osptoolkit.h"
- #include "usage.h"
- extern char* _osp_device_ip;
- extern int _osp_token_format;
- extern int _osp_validate_callid;
- extern OSPTPROVHANDLE _osp_provider;
- /*
- * Get OSP token
- * param msg SIP message
- * param ignore1
- * param ignore2
- * return MODULE_RETURNCODE_TRUE success, MODULE_RETURNCODE_FALSE failure
- */
- int ospCheckHeader(
- struct sip_msg* msg,
- char* ignore1,
- char* ignore2)
- {
- unsigned char buffer[OSP_TOKENBUF_SIZE];
- unsigned int buffersize = sizeof(buffer);
- LOG(L_DBG, "osp: ospCheckHeader\n");
- if (ospGetOspHeader(msg, buffer, &buffersize) != 0) {
- return MODULE_RETURNCODE_FALSE;
- } else {
- return MODULE_RETURNCODE_TRUE;
- }
- }
- /*
- * Validate OSP token
- * param ignore1
- * param ignore2
- * return MODULE_RETURNCODE_TRUE success, MODULE_RETURNCODE_FALSE failure
- */
- int ospValidateHeader (
- struct sip_msg* msg,
- char* ignore1,
- char* ignore2)
- {
- int errorcode;
- OSPTTRANHANDLE transaction = -1;
- unsigned int authorized = 0;
- unsigned int timelimit = 0;
- void* detaillog = NULL;
- unsigned int logsize = 0;
- unsigned char* callidval = (unsigned char*)"";
- OSPTCALLID* callid = NULL;
- unsigned callidsize = 0;
- unsigned char token[OSP_TOKENBUF_SIZE];
- unsigned int tokensize = sizeof(token);
- osp_dest dest;
- int result = MODULE_RETURNCODE_FALSE;
- LOG(L_DBG, "osp: ospValidateHeader\n");
- ospInitDestination(&dest);
- if ((errorcode = OSPPTransactionNew(_osp_provider, &transaction) != OSPC_ERR_NO_ERROR)) {
- LOG(L_ERR, "osp: ERROR: failed to create a new OSP transaction handle (%d)\n", errorcode);
- } else if ((ospGetRpidUserpart(msg, dest.calling, sizeof(dest.calling)) != 0) &&
- (ospGetFromUserpart(msg, dest.calling, sizeof(dest.calling)) != 0))
- {
- LOG(L_ERR, "osp: ERROR: failed to extract calling number\n");
- } else if ((ospGetUriUserpart(msg, dest.called, sizeof(dest.called)) != 0) &&
- (ospGetToUserpart(msg, dest.called, sizeof(dest.called)) != 0))
- {
- LOG(L_ERR, "osp: ERROR: failed to extract called number\n");
- } else if (ospGetCallId(msg, &callid) != 0) {
- LOG(L_ERR, "osp: ERROR: failed to extract call id\n");
- } else if (ospGetSourceAddress(msg, dest.source, sizeof(dest.source)) != 0) {
- LOG(L_ERR, "osp: ERROR: failed to extract source address\n");
- } else if (ospGetOspHeader(msg, token, &tokensize) != 0) {
- LOG(L_ERR, "osp: ERROR: failed to extract OSP authorization token\n");
- } else {
- LOG(L_INFO,
- "osp: validate token for: "
- "transaction_handle '%i' "
- "e164_source '%s' "
- "e164_dest '%s' "
- "validate_call_id '%s' "
- "call_id '%.*s'\n",
- transaction,
- dest.calling,
- dest.called,
- _osp_validate_callid == 0 ? "No" : "Yes",
- callid->ospmCallIdLen,
- callid->ospmCallIdVal);
- if (_osp_validate_callid != 0) {
- callidsize = callid->ospmCallIdLen;
- callidval = callid->ospmCallIdVal;
- }
- errorcode = OSPPTransactionValidateAuthorisation(
- transaction,
- "",
- "",
- "",
- "",
- dest.calling,
- OSPC_E164,
- dest.called,
- OSPC_E164,
- callidsize,
- callidval,
- tokensize,
- token,
- &authorized,
- &timelimit,
- &logsize,
- detaillog,
- _osp_token_format);
-
- if (callid->ospmCallIdLen > sizeof(dest.callid) - 1) {
- dest.callidsize = sizeof(dest.callid) - 1;
- } else {
- dest.callidsize = callid->ospmCallIdLen;
- }
- memcpy(dest.callid, callid->ospmCallIdVal, dest.callidsize);
- dest.callid[dest.callidsize] = 0;
- dest.transid = ospGetTransactionId(transaction);
- dest.type = OSPC_DESTINATION;
- dest.authtime = time(NULL);
- strncpy(dest.host, _osp_device_ip, sizeof(dest.host) - 1);
- ospSaveTermDestination(&dest);
- if ((errorcode == OSPC_ERR_NO_ERROR) && (authorized == 1)) {
- LOG(L_DBG,
- "osp: call is authorized for %d seconds, call_id '%.*s' transaction_id '%llu'",
- timelimit,
- dest.callidsize,
- dest.callid,
- dest.transid);
- ospRecordTermTransaction(msg, dest.transid, dest.source, dest.calling, dest.called, dest.authtime);
- result = MODULE_RETURNCODE_TRUE;
- } else {
- LOG(L_ERR, "osp: ERROR: token is invalid (%i)\n", errorcode);
- /*
- * Update terminating status code to 401 and report terminating setup usage.
- * We may need to make 401 configurable, just in case a user decides to reply with
- * a different code. Other options - trigger call setup usage reporting from the cpl
- * (after replying with an error code), or maybe use a different tm callback.
- */
- ospRecordEvent(0, 401);
- }
- }
- if (transaction != -1) {
- OSPPTransactionDelete(transaction);
- }
- if (callid != NULL) {
- OSPPCallIdDelete(&callid);
- }
-
- return result;
- }
|