term_transaction.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. * Kamailio osp module.
  3. *
  4. * This module enables Kamailio to communicate with an Open Settlement
  5. * Protocol (OSP) server. The Open Settlement Protocol is an ETSI
  6. * defined standard for Inter-Domain VoIP pricing, authorization
  7. * and usage exchange. The technical specifications for OSP
  8. * (ETSI TS 101 321 V4.1.1) are available at www.etsi.org.
  9. *
  10. * Uli Abend was the original contributor to this module.
  11. *
  12. * Copyright (C) 2001-2005 Fhg Fokus
  13. *
  14. * This file is part of Kamailio, a free SIP server.
  15. *
  16. * Kamailio is free software; you can redistribute it and/or modify
  17. * it under the terms of the GNU General Public License as published by
  18. * the Free Software Foundation; either version 2 of the License, or
  19. * (at your option) any later version
  20. *
  21. * Kamailio is distributed in the hope that it will be useful,
  22. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24. * GNU General Public License for more details.
  25. *
  26. * You should have received a copy of the GNU General Public License
  27. * along with this program; if not, write to the Free Software
  28. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  29. */
  30. #include "osp_mod.h"
  31. #include "term_transaction.h"
  32. #include "sipheader.h"
  33. #include "destination.h"
  34. #include "osptoolkit.h"
  35. #include "usage.h"
  36. extern char* _osp_device_ip;
  37. extern int _osp_token_format;
  38. extern int _osp_validate_callid;
  39. extern OSPTPROVHANDLE _osp_provider;
  40. /*
  41. * Get OSP token
  42. * param msg SIP message
  43. * param ignore1
  44. * param ignore2
  45. * return MODULE_RETURNCODE_TRUE success, MODULE_RETURNCODE_FALSE failure
  46. */
  47. int ospCheckHeader(
  48. struct sip_msg* msg,
  49. char* ignore1,
  50. char* ignore2)
  51. {
  52. unsigned char buffer[OSP_TOKENBUF_SIZE];
  53. unsigned int buffersize = sizeof(buffer);
  54. if (ospGetOspHeader(msg, buffer, &buffersize) != 0) {
  55. return MODULE_RETURNCODE_FALSE;
  56. } else {
  57. return MODULE_RETURNCODE_TRUE;
  58. }
  59. }
  60. /*
  61. * Validate OSP token
  62. * param ignore1
  63. * param ignore2
  64. * return MODULE_RETURNCODE_TRUE success, MODULE_RETURNCODE_FALSE failure MODULE_RETURNCODE_ERROR error
  65. */
  66. int ospValidateHeader (
  67. struct sip_msg* msg,
  68. char* ignore1,
  69. char* ignore2)
  70. {
  71. int errorcode;
  72. OSPTTRANHANDLE transaction = -1;
  73. unsigned int authorized = 0;
  74. unsigned int timelimit = 0;
  75. void* detaillog = NULL;
  76. unsigned int logsize = 0;
  77. unsigned char* callidval = (unsigned char*)"";
  78. OSPTCALLID* callid = NULL;
  79. unsigned callidsize = 0;
  80. unsigned char token[OSP_TOKENBUF_SIZE];
  81. unsigned int tokensize = sizeof(token);
  82. osp_dest dest;
  83. int result = MODULE_RETURNCODE_FALSE;
  84. ospInitDestination(&dest);
  85. if ((errorcode = OSPPTransactionNew(_osp_provider, &transaction) != OSPC_ERR_NO_ERROR)) {
  86. LM_ERR("failed to create a new OSP transaction handle (%d)\n", errorcode);
  87. } else if ((ospGetRpidUserpart(msg, dest.calling, sizeof(dest.calling)) != 0) &&
  88. (ospGetFromUserpart(msg, dest.calling, sizeof(dest.calling)) != 0))
  89. {
  90. LM_ERR("failed to extract calling number\n");
  91. } else if ((ospGetUriUserpart(msg, dest.called, sizeof(dest.called)) != 0) &&
  92. (ospGetToUserpart(msg, dest.called, sizeof(dest.called)) != 0))
  93. {
  94. LM_ERR("failed to extract called number\n");
  95. } else if (ospGetCallId(msg, &callid) != 0) {
  96. LM_ERR("failed to extract call id\n");
  97. } else if (ospGetSourceAddress(msg, dest.source, sizeof(dest.source)) != 0) {
  98. LM_ERR("failed to extract source address\n");
  99. } else if (ospGetOspHeader(msg, token, &tokensize) != 0) {
  100. LM_ERR("failed to extract OSP authorization token\n");
  101. } else {
  102. LM_INFO( "validate token for: "
  103. "transaction_handle '%d' "
  104. "e164_source '%s' "
  105. "e164_dest '%s' "
  106. "validate_call_id '%s' "
  107. "call_id '%.*s'\n",
  108. transaction,
  109. dest.calling,
  110. dest.called,
  111. _osp_validate_callid == 0 ? "No" : "Yes",
  112. callid->ospmCallIdLen,
  113. callid->ospmCallIdVal);
  114. if (_osp_validate_callid != 0) {
  115. callidsize = callid->ospmCallIdLen;
  116. callidval = callid->ospmCallIdVal;
  117. }
  118. errorcode = OSPPTransactionValidateAuthorisation(
  119. transaction,
  120. "",
  121. "",
  122. "",
  123. "",
  124. dest.calling,
  125. OSPC_E164,
  126. dest.called,
  127. OSPC_E164,
  128. callidsize,
  129. callidval,
  130. tokensize,
  131. token,
  132. &authorized,
  133. &timelimit,
  134. &logsize,
  135. detaillog,
  136. _osp_token_format);
  137. if ((errorcode == OSPC_ERR_NO_ERROR) && (authorized == 1)) {
  138. if (callid->ospmCallIdLen > sizeof(dest.callid) - 1) {
  139. dest.callidsize = sizeof(dest.callid) - 1;
  140. } else {
  141. dest.callidsize = callid->ospmCallIdLen;
  142. }
  143. memcpy(dest.callid, callid->ospmCallIdVal, dest.callidsize);
  144. dest.callid[dest.callidsize] = 0;
  145. dest.transid = ospGetTransactionId(transaction);
  146. dest.type = OSPC_DESTINATION;
  147. dest.authtime = time(NULL);
  148. strncpy(dest.host, _osp_device_ip, sizeof(dest.host) - 1);
  149. strncpy(dest.origcalled, dest.called, sizeof(dest.origcalled) - 1);
  150. if (ospSaveTermDestination(&dest) == -1) {
  151. LM_ERR("failed to save terminate destination\n");
  152. ospRecordEvent(0, 500);
  153. result = MODULE_RETURNCODE_ERROR;
  154. } else {
  155. LM_DBG("call is authorized for %d seconds, call_id '%.*s' transaction_id '%llu'",
  156. timelimit,
  157. dest.callidsize,
  158. dest.callid,
  159. dest.transid);
  160. ospRecordTermTransaction(msg, dest.transid, dest.source, dest.calling, dest.called, dest.authtime);
  161. result = MODULE_RETURNCODE_TRUE;
  162. }
  163. } else {
  164. LM_ERR("token is invalid (%d)\n", errorcode);
  165. /*
  166. * Update terminating status code to 401 and report terminating setup usage.
  167. * We may need to make 401 configurable, just in case a user decides to reply with
  168. * a different code. Other options - trigger call setup usage reporting from the cpl
  169. * (after replying with an error code), or maybe use a different tm callback.
  170. */
  171. ospRecordEvent(0, 401);
  172. result = MODULE_RETURNCODE_FALSE;
  173. }
  174. }
  175. if (transaction != -1) {
  176. OSPPTransactionDelete(transaction);
  177. }
  178. if (callid != NULL) {
  179. OSPPCallIdDelete(&callid);
  180. }
  181. return result;
  182. }