Beispiel #1
0
void ShuffleRound::HandlePrivateKey(QDataStream &stream, const Id &id)
{
    qDebug() << _group.GetIndex(_local_id) << _local_id.ToString() <<
             ": received private key from " << _group.GetIndex(id) <<
             id.ToString() << ", received" << _keys_received << "keys.";

    if(_state != Verification && _state != PrivateKeySharing) {
        qWarning() << "Received a private key message while in state " <<
                   StateToString(_state);
        return;
    }

    QByteArray key;
    stream >> key;
    int idx = _group.GetIndex(id);
    int kidx = _group.GetSize() - 1 - idx;
    _private_inner_keys[idx] = new CppPrivateKey(key);
    if(!_private_inner_keys[idx]->VerifyKey(*_public_inner_keys[kidx])) {
        qWarning() << "Invalid inner key for " << idx << id.ToString();
        return;
    }

    if(++_keys_received == _private_inner_keys.count()) {
        Decrypt();
    }
}
Beispiel #2
0
void ShuffleRound::HandleVerification(bool go, const Id &id)
{
    qDebug() << _group.GetIndex(_local_id) << _local_id.ToString() <<
             ": received" << go << " from " << _group.GetIndex(id)
             << id.ToString();

    if(_state != Verification && _state != ShuffleDone) {
        qWarning() << "Received a GoNoGo message while in state" <<
                   StateToString(_state);
        return;
    }

    if(!go) {
        return;
    }

    int idx = _group.GetIndex(id);
    if(_go_received[idx]) {
        qWarning() << "Multiple \"go\"s received from " << id.ToString();
        return;
    }
    _go_received[idx] = true;

    if(++_go == _group.GetSize()) {
        BroadcastPrivateKey();
    }
}
Beispiel #3
0
  void BulkRound::HandleBulkData(QDataStream &stream, const Id &from)
  {
    qDebug() << GetGroup().GetIndex(GetLocalId()) << GetLocalId().ToString() <<
      ": received bulk data from " << GetGroup().GetIndex(from) << from.ToString();

    if(IsLeader() || !_app_broadcast) {
      if(_state != DataSharing) {
        throw QRunTimeError("Received a misordered BulkData message");
      }
    } else if(_app_broadcast && _state != ProcessingLeaderData) {
      throw QRunTimeError("Waiting for data from leader, received something else.");
    }

    int idx = GetGroup().GetIndex(from);
    if(!_messages[idx].isEmpty()) {
      throw QRunTimeError("Already have bulk data.");
    }

    QByteArray payload;
    stream >> payload;

    if(payload.size() != _expected_bulk_size) {
      throw QRunTimeError("Incorrect bulk message length");
    }

    _messages[idx] = payload;

    if(++_received_messages == GetGroup().Count()) {
      ProcessMessages();
      Finish();
    }
  }
 void Round::HandleDisconnect(const Id &id)
 {
   if(_group.Contains(id)) {
     SetInterrupted();
     Stop(QString(id.ToString() + " disconnected"));
   }
 }
  void ConnectionManager::BindEdge(Edge *edge, const Id &rem_id)
  {
    /// @TODO add an extra variable to the connection message such as a session
    ///token so that quick reconnects can be enabled.
    if(_con_tab.GetConnection(rem_id) != 0) {
      qWarning() << "Already have a connection to: " << rem_id.ToString() << 
        " closing Edge: " << edge->ToString();
      QVariantMap notification;
      notification["method"] = "CM::Close";
      _rpc.SendNotification(notification, edge);
      Address addr = edge->GetRemoteAddress();
      edge->Close("Duplicate connection");
      emit ConnectionAttemptFailure(addr, "Duplicate connection");
      return;
    }
  
    QSharedPointer<Edge> pedge = _con_tab.GetEdge(edge);
    if(pedge.isNull()) {
      qCritical() << "An edge attempted to create a connection, but there "
       "is no record of it" << edge->ToString();
      return;
    }

    QVariantMap notification;
    notification["method"] = "CM::Connect";
    notification["peer_id"] = _local_id.GetByteArray();
    _rpc.SendNotification(notification, edge);

    CreateConnection(pedge, rem_id);
  }
Beispiel #6
0
void ShuffleRound::HandleData(QDataStream &stream, const Id &id)
{
    qDebug() << _group.GetIndex(_local_id) << _local_id.ToString() <<
             ": received initial data from " << _group.GetIndex(id) << id.ToString();

    if(_state != KeySharing && _state != DataSubmission &&
            _state != WaitingForShuffle)
    {
        qWarning() << "Received a data message while in state " <<
                   StateToString(_state) << " from " << id.ToString();
        return;
    }

    int idx = _group.GetIndex(_local_id);
    if(idx != 0) {
        qWarning() << "Received a data message while not the first node " <<
                   " in the group.  Actual position: " << idx;
        return;
    }

    QByteArray data;
    stream >> data;

    idx = _group.GetIndex(id);

    if(data.isEmpty()) {
        qWarning() << _group.GetIndex(_local_id) << _local_id.ToString() <<
                   ": received null data from " << idx << id.ToString();
        return;
    }

    if(!_shuffle_data[idx].isEmpty()) {
        if(_shuffle_data[idx] != data) {
            qWarning() << "Received a second data message from " << id.ToString();
        } else {
            qWarning() << "Received a duplicate data message from " << id.ToString();
        }
        return;
    }

    _shuffle_data[idx] = data;

    if(++_data_received == _group.GetSize()) {
        Shuffle();
    }
}
Beispiel #7
0
  TEST(Id, InvalidString)
  {
    Id id;
    QString bad = "ABCD";
    QString good = id.ToString();

    EXPECT_EQ(Id::Zero(), Id(bad));
    EXPECT_EQ(id, Id(good));
  }
Beispiel #8
0
  void RelayAddress::Init(const Id &id)
  {
    QUrl url;
    url.setScheme(Scheme);

    url.setPath(id.ToString());

    _data = new RelayAddressData(url, id);
  }
Beispiel #9
0
RelayForwarder::RelayForwarder(const Id &local_id, const ConnectionTable &ct,
                               const QSharedPointer<RpcHandler> &rpc) :
    _local_id(local_id),
    _base_been(local_id.ToString()),
    _ct(ct),
    _rpc(rpc),
    _cache(4096)
{
    _rpc->Register("RF::Data", this, "IncomingData");
}
Beispiel #10
0
void RelayForwarder::Send(const QSharedPointer<Connection> &con,
                          const Id &to, const QByteArray &data, const QStringList &been,
                          const QStringList &reverse)
{
    QVariantHash msg;
    msg["to"] = to.ToString();
    msg["data"] = data;
    msg["been"] = been + _base_been;

    if(!reverse.isEmpty()) {
        msg["reverse"] = reverse;
    }

    qDebug() << con->GetLocalId().ToString() << "Forwarding message from" <<
             msg["been"].toStringList().value(0) << "to" << to.ToString() << "via" <<
             con->GetRemoteId().ToString() << "Reverse path" << !reverse.isEmpty();

    _rpc->SendNotification(con, "RF::Data", msg);
}
Beispiel #11
0
  void BulkRound::HandleLoggedBulkData(QDataStream &stream, const Id &from)
  {
    if(from == GetLocalId()) {
      return;
    }

    qDebug() << GetGroup().GetIndex(GetLocalId()) << GetLocalId().ToString() <<
      ": received logged bulk data from " << GetGroup().GetIndex(from) <<
      from.ToString();

    if(GetGroup().GetLeader() != from) {
      throw QRunTimeError("Received logged bulk data from non-leader.");
    }

    if(_state != ReceivingLeaderData) {
      throw QRunTimeError("Not expected at this time.");
    }

    QByteArray binary_log;
    stream >> binary_log;
    Log log(binary_log);
    
    if(log.Count() != GetGroup().Count()) {
      throw QRunTimeError("Incorrect number of log messages.");
    }

    _state = ProcessingLeaderData;
    for(int idx = 0; idx < log.Count(); idx++) {
      const QPair<QByteArray, Id> &res = log.At(idx);
      try {
        ProcessDataBase(res.second, res.first);
      } catch (QRunTimeError &err) {
        const Id &from = res.second;
        qWarning() << GetGroup().GetIndex(GetLocalId()) << GetLocalId().ToString() <<
          "leader equivocated in message from" << GetGroup().GetIndex(from) <<
          from.ToString() << "in session / round" << GetRoundId().ToString() <<
          "in state" << StateToString(_state) <<
          "causing the following exception: " << err.What();
        // Should end round.
        break;
      }
    }
  }
Beispiel #12
0
void ShuffleRound::HandleShuffle(QDataStream &stream, const Id &id)
{
    qDebug() << _group.GetIndex(_local_id) << _local_id.ToString() <<
             ": received shuffle data from " << _group.GetIndex(id) << id.ToString();

    if(_state != WaitingForShuffle) {
        qWarning() << "Received a shuffle message while in state " <<
                   StateToString(_state) << " from " << id.ToString();
        return;
    }

    if(_group.Previous(_local_id) != id) {
        qWarning() << "Received shuffle out of order from " << id.ToString();
        return;
    }

    stream >> _shuffle_data;

    Shuffle();
}
Beispiel #13
0
void ShuffleRound::ProcessData(const QByteArray &data, const Id &id)
{
    QByteArray payload;
    if(!Verify(data, payload, id)) {
        return;
    }

    QDataStream stream(payload);
    int mtype;

    QByteArray session_id;
    stream >> mtype >> session_id;

    MessageType msg_type = (MessageType) mtype;

    Id sid(session_id);
    if(sid != GetId()) {
        qWarning() << "Invalid session, expected " << GetId().ToString()
                   << ", found " << sid.ToString();
        return;
    }

    _in_log.Append(data, id);

    switch(msg_type) {
    case PublicKeys:
        HandlePublicKeys(stream, id);
        break;
    case Data:
        HandleData(stream, id);
        break;
    case ShuffleData:
        HandleShuffle(stream, id);
        break;
    case EncryptedData:
        HandleDataBroadcast(stream, id);
        break;
    case GoMessage:
        HandleVerification(true, id);
        break;
    case NoGoMessage:
        HandleVerification(false, id);
        break;
    case PrivateKey:
        HandlePrivateKey(stream, id);
        break;
    default:
        qWarning() << "Unknown message type: " << MessageTypeToString(msg_type)
                   << " from " << id.ToString();
        return;
    }
}
 void RepeatingBulkRound::ProcessData(const Id &from, const QByteArray &data)
 {
   _log.Append(data, from);
   try {
     ProcessDataBase(from, data);
   } catch (QRunTimeError &err) {
     qWarning() << GetGroup().GetIndex(GetLocalId()) << GetLocalId().ToString() <<
       "received a message from" << GetGroup().GetIndex(from) << from.ToString() <<
       "in session / round" << GetRoundId().ToString() << "in state" <<
       StateToString(_state) << "causing the following exception: " << err.What();
     _log.Pop();
     return;
   }
 }
Beispiel #15
0
void ShuffleRound::HandlePublicKeys(QDataStream &stream, const Id &id)
{
    qDebug() << _group.GetIndex(_local_id) << _local_id.ToString() <<
             ": received public keys from " << _group.GetIndex(id) << id.ToString();

    if(_state != Offline && _state != KeySharing) {
        qWarning() << "Received a key message while in state " <<
                   StateToString(_state) << " from " << id.ToString();
        return;
    }

    int idx = _group.GetIndex(id);
    int kidx = _group.GetSize() - 1 - idx;
    if(_public_inner_keys[kidx] != 0 || _public_outer_keys[kidx] != 0) {
        qWarning() << _group.GetIndex(_local_id) << _local_id.ToString() <<
                   ": received duplicate public keys from " << _group.GetIndex(id)
                   << id.ToString();
        return;
    }

    QByteArray inner_key, outer_key;
    stream >> inner_key >> outer_key;
    _public_inner_keys[kidx] = new CppPublicKey(inner_key);
    _public_outer_keys[kidx] = new CppPublicKey(outer_key);

    if(!_public_inner_keys[kidx]->IsValid()) {
        qWarning() << _group.GetIndex(_local_id) << _local_id.ToString() <<
                   ": invalid inner key from " << idx << id.ToString();
    } else if(!_public_outer_keys[kidx]->IsValid()) {
        qWarning() << _group.GetIndex(_local_id) << _local_id.ToString() <<
                   ": invalid outer key from " << idx << id.ToString();
    }

    if(++_keys_received == _group.GetSize()) {
        SubmitData();
    }
}
  void RepeatingBulkRound::HandleBulkData(QDataStream &stream, const Id &from)
  {
    qDebug() << GetGroup().GetIndex(GetLocalId()) << GetLocalId().ToString() <<
      ": received bulk data from " << GetGroup().GetIndex(from) << from.ToString()
      << "Have" << (_received_messages + 1) << "expecting" << _messages.count();

    if(_state != DataSharing) {
      throw QRunTimeError("Received a misordered BulkData message");
    }

    uint idx = GetGroup().GetIndex(from);
    if(!_messages[idx].isEmpty()) {
      throw QRunTimeError("Already have bulk data.");
    }

    QByteArray payload;
    stream >> payload;

    if(static_cast<uint>(payload.size()) != _expected_bulk_size) {
      throw QRunTimeError("Incorrect bulk message length, got " +
          QString::number(payload.size()) + " expected " +
          QString::number(_expected_bulk_size));
    }

    _messages[idx] = payload;

    if(++_received_messages == static_cast<uint>(GetGroup().Count())) {
      ProcessMessages();

      SetState(PhasePreparation);
      qDebug() << "In" << ToString() << "ending phase.";
      _phase++;
      if(!PrepForNextPhase()) {
        return;
      }

      SetState(DataSharing);

      uint count = static_cast<uint>(_offline_log.Count());
      for(uint idx = 0; idx < count; idx++) {
        QPair<QByteArray, Id> entry = _offline_log.At(idx);
        ProcessData(entry.second, entry.first);
      }

      _offline_log.Clear();

      NextPhase();
    }
  }
Beispiel #17
0
void ShuffleRound::HandleDataBroadcast(QDataStream &stream, const Id &id)
{
    qDebug() << _group.GetIndex(_local_id) << _local_id.ToString() <<
             ": received data broadcast from " << _group.GetIndex(id) << id.ToString();

    if(_state != ShuffleDone) {
        return;
    }

    if(_group.GetSize() - 1 != _group.GetIndex(id)) {
        qWarning() << "Received data broadcast from wrong node.";
        return;
    }

    stream >> _encrypted_data;
    Verify();
}
Beispiel #18
0
  void BulkRound::HandleAggregatedBulkData(QDataStream &stream, const Id &from)
  {
    if(from == GetLocalId()) {
      return;
    }

    qDebug() << GetGroup().GetIndex(GetLocalId()) << GetLocalId().ToString() <<
      ": received aggregated bulk data from " << GetGroup().GetIndex(from) <<
      from.ToString();

    if(GetGroup().GetLeader() != from) {
      throw QRunTimeError("Received aggregated bulk data from non-leader.");
    }

    if(_state != ReceivingLeaderData) {
      throw QRunTimeError("Not expected at this time.");
    }

    QVector<QByteArray> cleartexts;
    stream >> cleartexts;

    const QVector<Descriptor> &des = GetDescriptors();

    if(cleartexts.count() != des.count()) {
      throw QRunTimeError("Cleartext count does not match descriptor count: " +
          QString::number(cleartexts.count()) + " " +
          QString::number(des.count()));
    }

    Hash hashalgo;

    for(int idx = 0; idx < cleartexts.count(); idx++) {
      QByteArray cleartext = cleartexts[idx];
      QByteArray hash = hashalgo.ComputeHash(cleartext);
      if(hash != des[idx].CleartextHash()) {
        throw QRunTimeError("Cleartext hash does not match descriptor hash.");
      }
      if(!cleartext.isEmpty()) {
        PushData(GetSharedPointer(), cleartext);
      }
    }

    Finish();
  }
Beispiel #19
0
  void ConnectionManager::BindEdge(const QSharedPointer<Edge> &edge,
      const Id &rem_id)
  {
    /// @TODO add an extra variable to the connection message such as a session
    ///token so that quick reconnects can be enabled.
    if(_con_tab.GetConnection(rem_id) != 0) {
      qDebug() << "Already have a connection to: " << rem_id.ToString() << 
        " closing Edge: " << edge->ToString();

      _rpc->SendNotification(edge, "CM::Close", QVariant());
      Address addr = edge->GetRemoteAddress();
      edge->Stop("Duplicate connection");
      emit ConnectionAttemptFailure(addr, "Duplicate connection");
      return;
    }
  
    _rpc->SendNotification(edge, "CM::Connect", _local_id.GetByteArray());
    CreateConnection(edge, rem_id);
  }
Beispiel #20
0
  RelayAddress::RelayAddress(const QUrl &url)
  {
    if(url.scheme() != Scheme) {
      qWarning() << "Supplied an invalid scheme" << url.scheme();
      _data = new AddressData(url);
      return;
    }

    QString sid = url.path().mid(1);
    Id id = Id(sid);
    if(id.ToString() != sid) {
      qWarning() << "Supplied an invalid Id:" << sid;
      _data = new AddressData(url);
      return;
    }

    Init(id);
    _data = new RelayAddressData(url, id);
  }
Beispiel #21
0
  void TestRoundBad(CreateRound good_cr, CreateRound bad_cr,
      const BadGuyCB &callback, bool client, bool will_finish)
  {
    int servers = 3, clients = 10;
    ConnectionManager::UseTimer = false;
    Timer::GetInstance().UseVirtualTime();
    OverlayNetwork net = ConstructOverlay(servers, clients);
    VerifyStoppedNetwork(net);
    StartNetwork(net);
    VerifyNetwork(net);

    Sessions sessions = BuildSessions(net, good_cr);
    // Find a bad guy and replace him...
    int badguy = Random::GetInstance().GetInt(0, clients);
    Id badid = net.second[badguy]->GetId();

    if(!client) {
      badguy = Random::GetInstance().GetInt(0, servers);
      badid = net.first[badguy]->GetId();
    }

    qDebug() << "Bad guy at" << badguy << badid;
    QSharedPointer<AsymmetricKey> key =
      sessions.private_keys[badid.ToString()];

    if(client) {
      ClientPointer cs = MakeSession<ClientSession>(
          net.second[badguy], key, sessions.keys, bad_cr);
      cs->SetSink(sessions.sink_multiplexers[servers + badguy].data());
      sessions.clients[badguy] = cs;
    } else {
      ServerPointer ss = MakeSession<ServerSession>(
          net.first[badguy], key, sessions.keys, bad_cr);
      ss->SetSink(sessions.sink_multiplexers[badguy].data());
      sessions.servers[badguy] = ss;
    }

    // Find a sender != badguy
    int sender = Random::GetInstance().GetInt(0, clients);
    if(client) {
      while(sender == badguy) {
        sender = Random::GetInstance().GetInt(0, clients);
      }
    }
    QByteArray msg(64, 0);
    CryptoRandom().GenerateBlock(msg);
    sessions.clients[sender]->Send(msg);

    qDebug() << "Starting sessions...";
    StartSessions(sessions);
    StartRound(sessions);

    QSharedPointer<Round> bad_round;
    if(client) {
      bad_round = sessions.clients[badguy]->GetRound();
    } else {
      bad_round = sessions.servers[badguy]->GetRound();
    }

    SignalCounter sc;
    for(int idx = 0; idx < servers; idx++) {
      QObject::connect(sessions.servers[idx].data(),
          SIGNAL(RoundFinished(const QSharedPointer<Anonymity::Round> &)),
          &sc, SLOT(Counter()));
    }

    for(int idx = 0; idx < clients; idx++) {
      QObject::connect(sessions.clients[idx].data(),
          SIGNAL(RoundFinished(const QSharedPointer<Anonymity::Round> &)),
          &sc, SLOT(Counter()));
    }

    RunUntil(sc, clients + servers);
    if(will_finish) {
      ASSERT_EQ(sc.GetCount(), clients + servers);
      ASSERT_EQ(bad_round->GetBadMembers().size(), 1);
      ASSERT_EQ(badid, bad_round->GetBadMembers()[0]);
    }

    if(!callback(bad_round.data())) {
      std::cout << "RoundTest_BadGuy was never triggered, "
        "consider rerunning." << std::endl;
    }

    StopNetwork(sessions.network);
    VerifyStoppedNetwork(sessions.network);
    ConnectionManager::UseTimer = true;
  }
Beispiel #22
0
 /**
  * Send a notification -- a request without expecting a response
  * @param notification message for the remote side
  * @param to id to destination
  */
 inline virtual void Send(const QByteArray &data, const Id &to)
 {
   Connection *con = _ct.GetConnection(to);
   if(con == 0) {
     qWarning() << "Attempting to send a notification when no such peer exists," << to.ToString();
     return;
   }
   Send(data, con);
 }