OSS::IPAddress SIPWebSocketConnection::getRemoteAddress() const
/// Returns the last read source address
{
    if (_lastReadAddress.isValid())
        return _lastReadAddress;

    if (_pServerConnection)
    {
        boost::system::error_code ec;
        EndPoint ep = _pServerConnection->get_raw_socket().remote_endpoint(ec);
        if (!ec)
        {
            boost::asio::ip::address ip = ep.address();
            _lastReadAddress = OSS::IPAddress(ip.to_string(), ep.port());
            return _lastReadAddress;
        }
        else
        {
            OSS_LOG_WARNING("SIPWebSocketConnection::getRemoteAddress() Exception " << ec.message());
            return _connectAddress;
        }
    }

    return OSS::IPAddress();

}
Exemple #2
0
int DTLSBio::sslRead(char* buf, int bufLen)
{
  /// 1. Read available data from the external input (probably libnice)
  /// If packet is not a DTLS packet, return the read value, else goto 2
  /// 2. Store (encrypted) read data into the input BIO using BIO_write
  /// 3. Call SSL_read to decrypt the data
  /// Returns return value of SSL_read
  ///
  if (!_pSSL)
  {
    OSS_LOG_ERROR("DTLSBio::sslRead - _pSSL is not set.");
    return 0;
  }
  
  if (!SSL_is_init_finished(_pSSL))
  {
    OSS_LOG_ERROR("DTLSBio::sslRead - SSL Handshake is not yet completed.");
    return 0;
  }
  
  int ret = 0;
  char readBuf[DTLS_BIO_BUFFER_LEN];
  
  ret = readDirect(readBuf, DTLS_BIO_BUFFER_LEN);
  
  if (ret > 0)
  {
    //
    // We have read some packets
    //
    if (DTLSSession::peek(readBuf) != DTLSSession::DTLS)
    {
      //
      // Not a DTLS packet.  return the raw packet
      //
      if (ret > bufLen)
      {
        //
        // We have read a packet that is bigger than the buffer provided
        // we do not have any better option but to truncate
        //
        OSS_LOG_WARNING("DTLSBio::sslRead - buffer size is smaller than the packet in the buffer.  Packet will be truncated!");
        ret = bufLen;
      }
      memcpy(buf, readBuf, ret);
      return ret;
    }
    
    ret = BIO_write(_pInBIO, readBuf, ret);
    if (ret > 0)
    {
      //
      // Packets are written to the IN BIO.  Read it back unencrypted.
      //
      ret = SSL_read(_pSSL, buf, bufLen); 
    }
  }
  return ret;
}
OSS::IPAddress SIPWebSocketConnection::getLocalAddress() const
/// Returns the local address binding for this transport
{
    if (_localAddress.isValid())
        return _localAddress;

    if (_pServerConnection)
    {
        boost::system::error_code ec;
        EndPoint ep = _pServerConnection->get_raw_socket().local_endpoint(ec);
        if (!ec)
        {
            boost::asio::ip::address ip = ep.address();
            _localAddress = OSS::IPAddress(ip.to_string(), ep.port());
            return _localAddress;
        }
        else
        {
            OSS_LOG_WARNING("SIPWebSocketConnection::getLocalAddress() Exception " << ec.message());
        }
    }

    return OSS::IPAddress();
}
void SIPWebSocketConnection::handleRead(const boost::system::error_code& e, std::size_t bytes_transferred, OSS_HANDLE userData)
/// Handle completion of a read operation.
{
    if (e || bytes_transferred <=0)
    {
        OSS_LOG_DEBUG("SIPWebSocketConnection::handleRead Exception " << e.message());

        if (++_readExceptionCount >= 5)
        {
            OSS_LOG_ERROR("SIPWebSocketConnection::handleRead has reached maximum exception count.  Bailing out.");
            boost::system::error_code ignored_ec;

            _connectionManager.stop(shared_from_this());
        }
    }

    OSS_LOG_DEBUG("SIPWebSocketConnection::handleRead STARTING new connection");
    std::string* buffer = reinterpret_cast<std::string*>(userData);

    //
    // set the last read address
    //
    if (!_lastReadAddress.isValid())
    {
        boost::system::error_code ec;

        EndPoint ep = _pServerConnection->get_raw_socket().remote_endpoint(ec);
        if (!ec)
        {
            boost::asio::ip::address ip = ep.address();
            _lastReadAddress = OSS::IPAddress(ip.to_string(), ep.port());
        }
        else
        {
            OSS_LOG_WARNING("SIPWebSocketConnection::handleRead() Exception " << ec.message());
        }
    }

    //
    // Reset the read exception count
    //
    _readExceptionCount = 0;

    _bytesRead =  bytes_transferred;
    if (!_pRequest)
    {
        _pRequest = SIPMessage::Ptr(new SIPMessage());
    }

    boost::tribool result;
    const char* begin = buffer->data();
    const char* end = buffer->data() + bytes_transferred;

    boost::tuple<boost::tribool, const char*> ret =  _pRequest->consume(begin, end);
    result = ret.get<0>();
    const char* tail = ret.get<1>();

    if (result)
    {
        //
        // Message has been read in full
        //
        _pDispatch->onReceivedMessage(_pRequest->shared_from_this(), shared_from_this());
        if (tail >= end)
        {
            //
            // The end of the SIPMessage is reached so we can simply reset the
            // request buffer and start the read operation all over again
            //
            _pRequest.reset();

            //
            // We are done
            //
            return;
        }
        else
        {
            //
            // This should not happen as there is one full message per read.
            // The tail is within the range of the end of the read buffer.
            //
            OSS_ASSERT(false);
        }
    }
    else if (!result)
    {
        _pRequest.reset();
    }
    else
    {
        //
        // This should not happen as there is one full message per read.
        // Partial message?
        //
        OSS_ASSERT(false);
    }
}
Exemple #5
0
void AccessControl::logPacket(const boost::asio::ip::address& source, std::size_t bytesRead, ViolationReport* pReport)
{
   /****************************************************************************
    * The packet rate ratio allows the transport to detect a potential DoS     *
    * attack.  It works by detecting the packet read rate per second as        *
    * designated by the upper limit.  If the value of packet rate is 50/100,   *
    * the maximum packet rate before the SBC raises the alert level if a       *
    * potential denial of service attack is 100 packets per second.            *
    * When this happens, the transport layer checks if there is a particular   *
    * IP that is sending more than its allowable rate of 50 packets per second.*
    * If the sender is violating the threshold, it will be banned for 1 hour   *
    * which is the third parameter of 3600 seconds.                            *
    ****************************************************************************/
  
  if (!_enabled)
    return;
  _packetCounterMutex.lock();

  std::map<boost::asio::ip::address, unsigned int>::iterator iter = _packetCounter.find(source);
  if (iter != _packetCounter.end())
    _packetCounter[source] = ++iter->second;
  else
    _packetCounter[source] = 1;

  if (++_currentIterationCount >= _packetsPerSecondThreshold)
  {
    boost::posix_time::ptime now(boost::posix_time::microsec_clock::local_time());
    int currentCount = _currentIterationCount;
    _currentIterationCount = 0;
    boost::posix_time::time_duration timeDiff = now - _lastTime;
    if (timeDiff.total_milliseconds() <=  1000)
    {
      //
      // We got a ratelimit violation
      //
      OSS_LOG_WARNING("ALERT: Threshold Violation Detected.  Rate " << currentCount << " >= " << _packetsPerSecondThreshold);

      if (pReport)
        pReport->thresholdViolated = true;
      
      std::size_t watermark = 0;
      boost::asio::ip::address suspect;
      for (std::map<boost::asio::ip::address, unsigned int>::iterator iter = _packetCounter.begin();
        iter != _packetCounter.end(); iter++)
      {
        if (iter->second > watermark)
        {
          watermark = iter->second;
          suspect = iter->first;
          
          if (watermark >= _thresholdViolationRate && _autoBanThresholdViolators )
          {
            if (!isWhiteListed(suspect))
            {
              OSS_LOG_WARNING("ALERT: Threshold Violator Address = " << suspect.to_string() <<
                " Packets sent within the last second is " << watermark
                << ". Violator is now in jail for a maximum of " << _banLifeTime << " seconds.");
              banAddress(suspect);
              
              if (pReport)
                pReport->violators.push_back(suspect.to_string());
            }
            else
            {
              OSS_LOG_WARNING("ALERT: Threshold Violator Address = " << suspect.to_string() <<
                " Packets sent within the last second is " << watermark
                << ". Violator is TRUSTED and will be allowed to bombard.");
            }
          }
          else if (watermark >= _thresholdViolationRate && !_autoBanThresholdViolators )
          {
            OSS_LOG_WARNING("ALERT: Threshold Violator Address = " << suspect.to_string() <<
                " Packets sent within the last second is " << watermark
                << ". Automatic ban is disabled.  Allowing this IP to bombard.");
          }
        }
      }     
    }
    //
    // Reset
    //
    _packetCounter.clear();
    _lastTime = now;
  }


  _packetCounterMutex.unlock();
}
Exemple #6
0
void SIPFSMDispatch::onReceivedMessage(SIPMessage::Ptr pMsg, SIPTransportSession::Ptr pTransport)
{
  if (!pTransport->isEndpoint() && pTransport->getLastReadCount() < MIN_DATAGRAM_SIZE && !pTransport->isReliableTransport())
  {
    //
    // datagram is too short to be a SIP Message
    // Bailing out.  Take note that streamed connection
    // can split SIP messages to smaller frames
    // and the last frame can be smaller than MIN_DATAGRAM_SIZE
    // so we do not impose a limit for streams
    //
    return;
  }

  try
  {
    pMsg->parse();
  }
  catch(OSS::Exception e)
  {
    std::ostringstream logMsg;
    logMsg << "Incoming message failed to be parsed - " << e.message()
      << " LEN: " << pTransport->getLastReadCount()
      << " SRC: " << pTransport->getRemoteAddress().toIpPortString();
    OSS::log_warning(logMsg.str());
    return;
  }

  std::string id;
  if (!pMsg->getTransactionId(id))
    return;  // don't throw here
             // we don't have control over what we receive from the transport

  SIPTransaction::Ptr trn;
  SIPTransaction::Type transactionType = SIPTransaction::TYPE_UNKNOWN;
  if (pMsg->isRequest())
  {
    if (OSS::string_caseless_starts_with(pMsg->startLine(), "invite"))
    {
      transactionType = SIPTransaction::TYPE_IST;
      if (_istBlocker.has(id))
      {
        OSS_LOG_WARNING("Blocked request retransmission - " <<  pMsg->startLine());
        return;
      }
      
      trn = _ist.findTransaction(pMsg, pTransport);
    }
    else if (OSS::string_caseless_starts_with(pMsg->startLine(), "ack"))
    {
      //
      // ACK for error responses will get matched to a transaction
      //
      transactionType = SIPTransaction::TYPE_IST;
      trn = _ist.findTransaction(pMsg, pTransport, false);
    }
    else
    {
      transactionType = SIPTransaction::TYPE_NIST;
      trn = _nist.findTransaction(pMsg, pTransport);
    }
  }
  else if (!pMsg->isRequest())
  {
    std::string cseq;
    cseq = pMsg->hdrGet(OSS::SIP::HDR_CSEQ);
    if (OSS::string_caseless_ends_with(cseq, "invite"))
    {
      transactionType = SIPTransaction::TYPE_ICT;
      trn = _ict.findTransaction(pMsg, pTransport, false);
    }
    else
    {
      transactionType = SIPTransaction::TYPE_NICT;
      trn = _nict.findTransaction(pMsg, pTransport, false);
    }
  }
  if (trn)
  {
    std::ostringstream logMsg;
    if (!trn->getLogId().empty())
    {
      logMsg << trn->getLogId() << "Found Transaction " << trn->getId();
      OSS::log_debug(logMsg.str());
    }
    else
    {
      trn->setLogId(pMsg->createContextId(true));
      logMsg << trn->getLogId() << "Transaction " << trn->getId() << " CREATED";
      OSS::log_information(logMsg.str());
    }
  }

  if (!trn)
  {
    //
    // We did not get a transaction, check if this is an ack and find the IST ACK transaction
    //
    if (transactionType == SIPTransaction::TYPE_IST && pMsg->isRequest("ACK"))
    {
        //
        // No IST is existing in the ackable Pool.
        // Report this ACK as orphaned to the UA CORE
        //
        if (_ackOr2xxTransactionHandler)
          _ackOr2xxTransactionHandler(pMsg, pTransport);
    }
    else if (transactionType == SIPTransaction::TYPE_ICT && pMsg->is2xx())
    {
      if (_ackOr2xxTransactionHandler)
        _ackOr2xxTransactionHandler(pMsg, pTransport);
    }
    else
    {
      std::ostringstream logMsg;
      logMsg << pMsg->createContextId(true) << "Unable to match incoming request to a transaction - "
        << pMsg->startLine();
      OSS::log_warning(logMsg.str());
    }
  }
  else
  {
    if (!trn->transportService())
    {
      //
      // This is a newly created transaction
      //
      trn->transportService() = &_transport;
      trn->transport() = pTransport;
    }
    trn->onReceivedMessage(pMsg, pTransport);
  }
}