term_transaction.c

Go to the documentation of this file.
00001 /*
00002  * openser osp module. 
00003  *
00004  * This module enables openser to communicate with an Open Settlement 
00005  * Protocol (OSP) server.  The Open Settlement Protocol is an ETSI 
00006  * defined standard for Inter-Domain VoIP pricing, authorization
00007  * and usage exchange.  The technical specifications for OSP 
00008  * (ETSI TS 101 321 V4.1.1) are available at www.etsi.org.
00009  *
00010  * Uli Abend was the original contributor to this module.
00011  * 
00012  * Copyright (C) 2001-2005 Fhg Fokus
00013  *
00014  * This file is part of Kamailio, a free SIP server.
00015  *
00016  * Kamailio is free software; you can redistribute it and/or modify
00017  * it under the terms of the GNU General Public License as published by
00018  * the Free Software Foundation; either version 2 of the License, or
00019  * (at your option) any later version
00020  *
00021  * Kamailio is distributed in the hope that it will be useful,
00022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024  * GNU General Public License for more details.
00025  *
00026  * You should have received a copy of the GNU General Public License
00027  * along with this program; if not, write to the Free Software
00028  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00029  */
00030 
00031 #include "osp_mod.h"
00032 #include "term_transaction.h"
00033 #include "sipheader.h"
00034 #include "destination.h"
00035 #include "osptoolkit.h"
00036 #include "usage.h"
00037 
00038 extern char* _osp_device_ip;
00039 extern int _osp_token_format;
00040 extern int _osp_validate_callid;
00041 extern OSPTPROVHANDLE _osp_provider;
00042 
00043 /*
00044  * Get OSP token
00045  * param msg SIP message
00046  * param ignore1
00047  * param ignore2
00048  * return  MODULE_RETURNCODE_TRUE success, MODULE_RETURNCODE_FALSE failure
00049  */
00050 int ospCheckHeader(
00051     struct sip_msg* msg, 
00052     char* ignore1, 
00053     char* ignore2)
00054 {
00055     unsigned char buffer[OSP_TOKENBUF_SIZE];
00056     unsigned int  buffersize = sizeof(buffer);
00057 
00058     if (ospGetOspHeader(msg, buffer, &buffersize) != 0) {
00059         return MODULE_RETURNCODE_FALSE;
00060     } else {
00061         return MODULE_RETURNCODE_TRUE;
00062     }
00063 }
00064 
00065 /*
00066  * Validate OSP token
00067  * param ignore1
00068  * param ignore2
00069  * return  MODULE_RETURNCODE_TRUE success, MODULE_RETURNCODE_FALSE failure MODULE_RETURNCODE_ERROR error
00070  */
00071 int ospValidateHeader (
00072     struct sip_msg* msg, 
00073     char* ignore1, 
00074     char* ignore2)
00075 {
00076     int errorcode; 
00077     OSPTTRANHANDLE transaction = -1;
00078     unsigned int authorized = 0;
00079     unsigned int timelimit = 0;
00080     void* detaillog = NULL;
00081     unsigned int logsize = 0;
00082     unsigned char* callidval = (unsigned char*)"";
00083     OSPTCALLID* callid = NULL;
00084     unsigned callidsize = 0;
00085     unsigned char token[OSP_TOKENBUF_SIZE];
00086     unsigned int tokensize = sizeof(token);
00087     osp_dest dest;
00088     int result = MODULE_RETURNCODE_FALSE;
00089 
00090     ospInitDestination(&dest);
00091 
00092     if ((errorcode = OSPPTransactionNew(_osp_provider, &transaction) != OSPC_ERR_NO_ERROR)) {
00093         LM_ERR("failed to create a new OSP transaction handle (%d)\n", errorcode);
00094     } else if ((ospGetRpidUserpart(msg, dest.calling, sizeof(dest.calling)) != 0) && 
00095         (ospGetFromUserpart(msg, dest.calling, sizeof(dest.calling)) != 0))
00096     {
00097         LM_ERR("failed to extract calling number\n");
00098     } else if ((ospGetUriUserpart(msg, dest.called, sizeof(dest.called)) != 0) &&
00099         (ospGetToUserpart(msg, dest.called, sizeof(dest.called)) != 0))
00100     {
00101         LM_ERR("failed to extract called number\n");
00102     } else if (ospGetCallId(msg, &callid) != 0) {
00103         LM_ERR("failed to extract call id\n");
00104     } else if (ospGetSourceAddress(msg, dest.source, sizeof(dest.source)) != 0) {
00105         LM_ERR("failed to extract source address\n");
00106     } else if (ospGetOspHeader(msg, token, &tokensize) != 0) {
00107         LM_ERR("failed to extract OSP authorization token\n");
00108     } else {
00109         LM_INFO( "validate token for: "
00110             "transaction_handle '%d' "
00111             "e164_source '%s' "
00112             "e164_dest '%s' "
00113             "validate_call_id '%s' "
00114             "call_id '%.*s'\n",
00115             transaction,
00116             dest.calling,
00117             dest.called,
00118             _osp_validate_callid == 0 ? "No" : "Yes",
00119             callid->ospmCallIdLen,
00120             callid->ospmCallIdVal);
00121 
00122         if (_osp_validate_callid != 0) {
00123             callidsize = callid->ospmCallIdLen;
00124             callidval = callid->ospmCallIdVal;
00125         }
00126 
00127         errorcode = OSPPTransactionValidateAuthorisation(
00128             transaction,
00129             "",
00130             "",
00131             "",
00132             "",
00133             dest.calling,
00134             OSPC_E164,
00135             dest.called,
00136             OSPC_E164,
00137             callidsize,
00138             callidval,
00139             tokensize,
00140             token,
00141             &authorized,
00142             &timelimit,
00143             &logsize,
00144             detaillog,
00145             _osp_token_format);
00146     
00147         if ((errorcode == OSPC_ERR_NO_ERROR) && (authorized == 1)) {
00148             if (callid->ospmCallIdLen > sizeof(dest.callid) - 1) {
00149                 dest.callidsize = sizeof(dest.callid) - 1;
00150             } else {
00151                 dest.callidsize = callid->ospmCallIdLen;
00152             }
00153             memcpy(dest.callid, callid->ospmCallIdVal, dest.callidsize);
00154             dest.callid[dest.callidsize] = 0;
00155             dest.transid = ospGetTransactionId(transaction);
00156             dest.type = OSPC_DESTINATION;
00157             dest.authtime = time(NULL);
00158             strncpy(dest.host, _osp_device_ip, sizeof(dest.host) - 1);
00159             strncpy(dest.origcalled, dest.called, sizeof(dest.origcalled) - 1);
00160 
00161             if (ospSaveTermDestination(&dest) == -1) {
00162                 LM_ERR("failed to save terminate destination\n");
00163                 ospRecordEvent(0, 500);
00164                 result = MODULE_RETURNCODE_ERROR;
00165             } else {
00166                 LM_DBG("call is authorized for %d seconds, call_id '%.*s' transaction_id '%llu'", 
00167                     timelimit,
00168                     dest.callidsize,
00169                     dest.callid,
00170                     dest.transid);
00171                 ospRecordTermTransaction(msg, dest.transid, dest.source, dest.calling, dest.called, dest.authtime);
00172                 result = MODULE_RETURNCODE_TRUE;
00173             }
00174         } else {
00175             LM_ERR("token is invalid (%d)\n", errorcode);
00176 
00177             /* 
00178              * Update terminating status code to 401 and report terminating setup usage.
00179              * We may need to make 401 configurable, just in case a user decides to reply with
00180              * a different code.  Other options - trigger call setup usage reporting from the cpl
00181              * (after replying with an error code), or maybe use a different tm callback.
00182              */
00183             ospRecordEvent(0, 401);
00184             result = MODULE_RETURNCODE_FALSE;
00185         }
00186     }
00187 
00188     if (transaction != -1) {
00189         OSPPTransactionDelete(transaction);
00190     }
00191 
00192     if (callid != NULL) {
00193         OSPPCallIdDelete(&callid);
00194     }
00195     
00196     return result;
00197 }
00198 

Generated on Thu May 24 20:00:33 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6