term_transaction.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. * ser osp module.
  3. *
  4. * This module enables ser 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 ser, a free SIP server.
  15. *
  16. * ser 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. * For a license to use the ser software under conditions
  22. * other than those described here, or to purchase support for this
  23. * software, please contact iptel.org by e-mail at the following addresses:
  24. * [email protected]
  25. *
  26. * ser is distributed in the hope that it will be useful,
  27. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  28. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  29. * GNU General Public License for more details.
  30. *
  31. * You should have received a copy of the GNU General Public License
  32. * along with this program; if not, write to the Free Software
  33. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  34. */
  35. #include "osp_mod.h"
  36. #include "term_transaction.h"
  37. #include "sipheader.h"
  38. #include "destination.h"
  39. #include "osptoolkit.h"
  40. #include "usage.h"
  41. extern char* _osp_device_ip;
  42. extern int _osp_token_format;
  43. extern int _osp_validate_callid;
  44. extern OSPTPROVHANDLE _osp_provider;
  45. /*
  46. * Get OSP token
  47. * param msg SIP message
  48. * param ignore1
  49. * param ignore2
  50. * return MODULE_RETURNCODE_TRUE success, MODULE_RETURNCODE_FALSE failure
  51. */
  52. int ospCheckHeader(
  53. struct sip_msg* msg,
  54. char* ignore1,
  55. char* ignore2)
  56. {
  57. unsigned char buffer[OSP_TOKENBUF_SIZE];
  58. unsigned int buffersize = sizeof(buffer);
  59. LOG(L_DBG, "osp: ospCheckHeader\n");
  60. if (ospGetOspHeader(msg, buffer, &buffersize) != 0) {
  61. return MODULE_RETURNCODE_FALSE;
  62. } else {
  63. return MODULE_RETURNCODE_TRUE;
  64. }
  65. }
  66. /*
  67. * Validate OSP token
  68. * param ignore1
  69. * param ignore2
  70. * return MODULE_RETURNCODE_TRUE success, MODULE_RETURNCODE_FALSE failure
  71. */
  72. int ospValidateHeader (
  73. struct sip_msg* msg,
  74. char* ignore1,
  75. char* ignore2)
  76. {
  77. int errorcode;
  78. OSPTTRANHANDLE transaction = -1;
  79. unsigned int authorized = 0;
  80. unsigned int timelimit = 0;
  81. void* detaillog = NULL;
  82. unsigned int logsize = 0;
  83. unsigned char* callidval = (unsigned char*)"";
  84. OSPTCALLID* callid = NULL;
  85. unsigned callidsize = 0;
  86. unsigned char token[OSP_TOKENBUF_SIZE];
  87. unsigned int tokensize = sizeof(token);
  88. osp_dest dest;
  89. int result = MODULE_RETURNCODE_FALSE;
  90. LOG(L_DBG, "osp: ospValidateHeader\n");
  91. ospInitDestination(&dest);
  92. if ((errorcode = OSPPTransactionNew(_osp_provider, &transaction) != OSPC_ERR_NO_ERROR)) {
  93. LOG(L_ERR, "osp: ERROR: failed to create a new OSP transaction handle (%d)\n", errorcode);
  94. } else if ((ospGetRpidUserpart(msg, dest.calling, sizeof(dest.calling)) != 0) &&
  95. (ospGetFromUserpart(msg, dest.calling, sizeof(dest.calling)) != 0))
  96. {
  97. LOG(L_ERR, "osp: ERROR: failed to extract calling number\n");
  98. } else if ((ospGetUriUserpart(msg, dest.called, sizeof(dest.called)) != 0) &&
  99. (ospGetToUserpart(msg, dest.called, sizeof(dest.called)) != 0))
  100. {
  101. LOG(L_ERR, "osp: ERROR: failed to extract called number\n");
  102. } else if (ospGetCallId(msg, &callid) != 0) {
  103. LOG(L_ERR, "osp: ERROR: failed to extract call id\n");
  104. } else if (ospGetSourceAddress(msg, dest.source, sizeof(dest.source)) != 0) {
  105. LOG(L_ERR, "osp: ERROR: failed to extract source address\n");
  106. } else if (ospGetOspHeader(msg, token, &tokensize) != 0) {
  107. LOG(L_ERR, "osp: ERROR: failed to extract OSP authorization token\n");
  108. } else {
  109. LOG(L_INFO,
  110. "osp: validate token for: "
  111. "transaction_handle '%i' "
  112. "e164_source '%s' "
  113. "e164_dest '%s' "
  114. "validate_call_id '%s' "
  115. "call_id '%.*s'\n",
  116. transaction,
  117. dest.calling,
  118. dest.called,
  119. _osp_validate_callid == 0 ? "No" : "Yes",
  120. callid->ospmCallIdLen,
  121. callid->ospmCallIdVal);
  122. if (_osp_validate_callid != 0) {
  123. callidsize = callid->ospmCallIdLen;
  124. callidval = callid->ospmCallIdVal;
  125. }
  126. errorcode = OSPPTransactionValidateAuthorisation(
  127. transaction,
  128. "",
  129. "",
  130. "",
  131. "",
  132. dest.calling,
  133. OSPC_E164,
  134. dest.called,
  135. OSPC_E164,
  136. callidsize,
  137. callidval,
  138. tokensize,
  139. token,
  140. &authorized,
  141. &timelimit,
  142. &logsize,
  143. detaillog,
  144. _osp_token_format);
  145. if (callid->ospmCallIdLen > sizeof(dest.callid) - 1) {
  146. dest.callidsize = sizeof(dest.callid) - 1;
  147. } else {
  148. dest.callidsize = callid->ospmCallIdLen;
  149. }
  150. memcpy(dest.callid, callid->ospmCallIdVal, dest.callidsize);
  151. dest.callid[dest.callidsize] = 0;
  152. dest.transid = ospGetTransactionId(transaction);
  153. dest.type = OSPC_DESTINATION;
  154. dest.authtime = time(NULL);
  155. strncpy(dest.host, _osp_device_ip, sizeof(dest.host) - 1);
  156. ospSaveTermDestination(&dest);
  157. if ((errorcode == OSPC_ERR_NO_ERROR) && (authorized == 1)) {
  158. LOG(L_DBG,
  159. "osp: call is authorized for %d seconds, call_id '%.*s' transaction_id '%llu'",
  160. timelimit,
  161. dest.callidsize,
  162. dest.callid,
  163. dest.transid);
  164. ospRecordTermTransaction(msg, dest.transid, dest.source, dest.calling, dest.called, dest.authtime);
  165. result = MODULE_RETURNCODE_TRUE;
  166. } else {
  167. LOG(L_ERR, "osp: ERROR: token is invalid (%i)\n", errorcode);
  168. /*
  169. * Update terminating status code to 401 and report terminating setup usage.
  170. * We may need to make 401 configurable, just in case a user decides to reply with
  171. * a different code. Other options - trigger call setup usage reporting from the cpl
  172. * (after replying with an error code), or maybe use a different tm callback.
  173. */
  174. ospRecordEvent(0, 401);
  175. }
  176. }
  177. if (transaction != -1) {
  178. OSPPTransactionDelete(transaction);
  179. }
  180. if (callid != NULL) {
  181. OSPPCallIdDelete(&callid);
  182. }
  183. return result;
  184. }