void NetInterface::handleConnectReject(const Address &address, BitStream *stream)
{
   Nonce nonce;
   Nonce serverNonce;

   nonce.read(stream);
   serverNonce.read(stream);

   NetConnection *conn = findPendingConnection(address);
   if(!conn || (conn->getConnectionState() != NetConnection::AwaitingChallengeResponse &&
                conn->getConnectionState() != NetConnection::AwaitingConnectResponse))
      return;
   ConnectionParameters &p = conn->getConnectionParameters();
   if(p.mNonce != nonce || p.mServerNonce != serverNonce)
      return;


   NetConnection::TerminationReason reason = (NetConnection::TerminationReason) stream->readEnum(NetConnection::TerminationReasons);

   char reasonStr[256];
   stream->readString(reasonStr);

   logprintf(LogConsumer::LogNetInterface, "Received Connect Reject - reason code %d (%s)", reason, reasonStr);

   // If the reason is a bad puzzle solution, try once more with a new nonce
   if(reason == NetConnection::ReasonPuzzle && !p.mPuzzleRetried)
   {
      p.mPuzzleRetried = true;
      conn->setConnectionState(NetConnection::AwaitingChallengeResponse);
      conn->mConnectSendCount = 0;
      p.mNonce.getRandom();                  // Generate new nonce
      sendConnectChallengeRequest(conn);
      return;
   }

   conn->setConnectionState(NetConnection::ConnectRejected);
   conn->onConnectTerminated(reason, reasonStr);
   removePendingConnection(conn);
}
Exemplo n.º 2
0
void NetInterface::handleConnectReject(const Address &address, BitStream *stream)
{
   Nonce nonce;
   Nonce serverNonce;

   nonce.read(stream);
   serverNonce.read(stream);

   NetConnection *conn = findPendingConnection(address);
   if(!conn || (conn->getConnectionState() != NetConnection::AwaitingChallengeResponse &&
                conn->getConnectionState() != NetConnection::AwaitingConnectResponse))
      return;
   ConnectionParameters &p = conn->getConnectionParameters();
   if(p.mNonce != nonce || p.mServerNonce != serverNonce)
      return;

   char reason[256];
   stream->readString(reason);

   TNLLogMessageV(LogNetInterface, ("Received Connect Reject - reason %s", reason));
   // if the reason is a bad puzzle solution, try once more with a
   // new nonce.
   if(!strcmp(reason, "Puzzle") && !p.mPuzzleRetried)
   {
      p.mPuzzleRetried = true;
      conn->setConnectionState(NetConnection::AwaitingChallengeResponse);
      conn->mConnectSendCount = 0;
      p.mNonce.getRandom();
      sendConnectChallengeRequest(conn);
      return;
   }

   conn->setConnectionState(NetConnection::ConnectRejected);
   conn->onConnectTerminated(NetConnection::ReasonRemoteHostRejectedConnection, reason);
   removePendingConnection(conn);
}
Exemplo n.º 3
0
static void handlePing(Game *game, const Address &remoteAddress, Socket &socket, BitStream *stream, S32 clientId)
{
   TNLAssert(game->isServer(), "Expected this to be a server!");

   Nonce clientNonce;
   clientNonce.read(stream);

   U32 protocolVersion;
   stream->read(&protocolVersion);

   if(protocolVersion != CS_PROTOCOL_VERSION)   // Ignore pings from incompatible versions
      return;

   U32 clientIdentityToken = computeSimpleToken(clientNonce);
   PacketStream pingResponse;

   pingResponse.write(U8(GameNetInterface::PingResponse));
   clientNonce.write(&pingResponse);
   pingResponse.write(clientIdentityToken);

   pingResponse.write(clientId);  // older 019 ignore this or won't read this

   pingResponse.sendto(socket, remoteAddress);
}
Exemplo n.º 4
0
TEST(HeaderField, Serialize)
{
    std::list<HeaderField> list;

    std::list<Certificate> certificates;
    for (unsigned i = 0; i < 2; ++i) {
        auto rand_gen = random_byte_generator(i + 8 * 3);
        Certificate cert;
        HashedId8 cert_digest;
        std::generate(cert_digest.begin(), cert_digest.end(), rand_gen);
        cert.signer_info = cert_digest;
        cert.subject_info = { SubjectType::Enrollment_Credential, random_byte_sequence(28, i) };
        cert.signature = create_random_ecdsa_signature(i + 8);
        certificates.push_back(cert);
    }
    list.push_back(SignerInfo { certificates });

    list.push_back(Time64 { 983 });

    Time64WithStandardDeviation time_dev;
    time_dev.log_std_dev = 1;
    time_dev.time64 = 2000;
    list.push_back(time_dev);

    list.push_back(Time32 { 434 });

    ThreeDLocation loc;
    loc.latitude.from_value(838);
    loc.longitude.from_value(37);
    loc.elevation = {{ 83, 17 }};
    list.push_back(loc);

    std::list<HashedId3> hashed;
    for (unsigned i = 0; i < 3; ++i) {
        HashedId3 id;
        std::generate(id.begin(), id.end(), random_byte_generator(i + 8943));
        hashed.push_back(id);
    }
    list.push_back(hashed);

    list.push_back(IntX { 43 });

    Nonce nonce;
    std::generate(nonce.begin(), nonce.end(), random_byte_generator(22));
    list.push_back(EncryptionParameter { nonce });

    std::list<RecipientInfo> recipients;
    for (unsigned i = 0; i < 2; ++i) {
        const std::size_t length = field_size(PublicKeyAlgorithm::ECIES_NISTP256);
        auto rand_gen = random_byte_generator(i + 93);
        RecipientInfo info;
        EciesEncryptedKey key;
        std::generate(info.cert_id.begin(), info.cert_id.end(), rand_gen);
        key.c = random_byte_sequence(field_size(SymmetricAlgorithm::AES128_CCM), rand_gen());
        std::generate(key.t.begin(), key.t.end(), rand_gen);
        key.v = Uncompressed {
            random_byte_sequence(length, rand_gen()),
            random_byte_sequence(length, rand_gen()) };
        info.enc_key = key;
        recipients.push_back(info);
    }
    list.push_back(recipients);

    check(list, serialize_roundtrip(list));
}
Exemplo n.º 5
0
void NetInterface::handlePunch(const Address &theAddress, BitStream *stream)
{
   S32 i, j;
   NetConnection *conn;

   Nonce firstNonce;
   firstNonce.read(stream);

   ByteBuffer b(firstNonce.data, Nonce::NonceSize);

   TNLLogMessageV(LogNetInterface, ("Received punch packet from %s - %s", theAddress.toString(), b.encodeBase64()->getBuffer()));

   for(i = 0; i < mPendingConnections.size(); i++)
   {
      conn = mPendingConnections[i];
      ConnectionParameters &theParams = conn->getConnectionParameters();

      if(conn->getConnectionState() != NetConnection::SendingPunchPackets)
         continue;

      if((theParams.mIsInitiator && firstNonce != theParams.mServerNonce) ||
            (!theParams.mIsInitiator && firstNonce != theParams.mNonce))
         continue;

      // first see if the address is in the possible addresses list:
      
      for(j = 0; j < theParams.mPossibleAddresses.size(); j++)
         if(theAddress == theParams.mPossibleAddresses[j])
            break;

      // if there was an exact match, just exit the loop, or
      // continue on to the next pending if this is not an initiator:
      if(j != theParams.mPossibleAddresses.size())
      {
         if(theParams.mIsInitiator)
            break;
         else
            continue;
      }

      // if there was no exact match, we may have a funny NAT in the
      // middle.  But since a packet got through from the remote host
      // we'll want to send a punch to the address it came from, as long
      // as only the port is not an exact match:
      for(j = 0; j < theParams.mPossibleAddresses.size(); j++)
         if(theAddress.isEqualAddress(theParams.mPossibleAddresses[j]))
            break;

      // if the address wasn't even partially in the list, just exit out
      if(j == theParams.mPossibleAddresses.size())
         continue;

      // otherwise, as long as we don't have too many ping addresses,
      // add this one to the list:
      if(theParams.mPossibleAddresses.size() < 5)
         theParams.mPossibleAddresses.push_back(theAddress);      

      // if this is the initiator of the arranged connection, then
      // process the punch packet from the remote host by issueing a
      // connection request.
      if(theParams.mIsInitiator)
         break;
   }
   if(i == mPendingConnections.size())
      return;

   ConnectionParameters &theParams = conn->getConnectionParameters();
   SymmetricCipher theCipher(theParams.mArrangedSecret);
   if(!stream->decryptAndCheckHash(NetConnection::MessageSignatureBytes, stream->getBytePosition(), &theCipher))
      return;

   Nonce nextNonce;
   nextNonce.read(stream);

   if(nextNonce != theParams.mNonce)
      return;

   // see if the connection needs to be authenticated or uses key exchange
   if(stream->readFlag())
   {
      if(stream->readFlag())
      {
         theParams.mCertificate = new Certificate(stream);
         if(!theParams.mCertificate->isValid() || !conn->validateCertficate(theParams.mCertificate, true))
            return;         
         theParams.mPublicKey = theParams.mCertificate->getPublicKey();
      }
      else
      {
         theParams.mPublicKey = new AsymmetricKey(stream);
         if(!theParams.mPublicKey->isValid() || !conn->validatePublicKey(theParams.mPublicKey, true))
            return;
      }
      if(mPrivateKey.isNull() || mPrivateKey->getKeySize() != theParams.mPublicKey->getKeySize())
      {
         // we don't have a private key, so generate one for this connection
         theParams.mPrivateKey = new AsymmetricKey(theParams.mPublicKey->getKeySize());
      }
      else
         theParams.mPrivateKey = mPrivateKey;
      theParams.mSharedSecret = theParams.mPrivateKey->computeSharedSecretKey(theParams.mPublicKey);
      //logprintf("shared secret (client) %s", theParams.mSharedSecret->encodeBase64()->getBuffer());
      Random::read(theParams.mSymmetricKey, SymmetricCipher::KeySize);
      theParams.mUsingCrypto = true;
   }
   conn->setNetAddress(theAddress);
   TNLLogMessageV(LogNetInterface, ("Punch from %s matched nonces - connecting...", theAddress.toString()));

   conn->setConnectionState(NetConnection::AwaitingConnectResponse);
   conn->mConnectSendCount = 0;
   conn->mConnectLastSendTime = getCurrentTime();

   sendArrangedConnectRequest(conn);
}
void NetInterface::handleConnectChallengeResponse(const Address &address, BitStream *stream)
{
   NetConnection *conn = findPendingConnection(address);
   if(!conn || conn->getConnectionState() != NetConnection::AwaitingChallengeResponse)    // Not expecting a connection, abort!
      return;

   Nonce theNonce;
   theNonce.read(stream);

   ConnectionParameters &theParams = conn->getConnectionParameters();

   if(theNonce != theParams.mNonce)    // Nonces don't match, abort!
      return;

   stream->read(&theParams.mClientIdentity);

   // See if the server wants us to solve a client puzzle
   theParams.mServerNonce.read(stream);
   stream->read(&theParams.mPuzzleDifficulty);

   if(theParams.mPuzzleDifficulty > ClientPuzzleManager::MaxPuzzleDifficulty)    // Puzzle too hard, abort!
      return;

   // See if the connection needs to be authenticated or uses key exchange
   if(stream->readFlag())
   {
      if(stream->readFlag())
      {
         theParams.mCertificate = new Certificate(stream);
         if(!theParams.mCertificate->isValid() || !conn->validateCertficate(theParams.mCertificate, true))  // Invalid cert, abort!
            return;

         theParams.mPublicKey = theParams.mCertificate->getPublicKey();
      }
      else
      {
         theParams.mPublicKey = new AsymmetricKey(stream);
         if(!theParams.mPublicKey->isValid() || !conn->validatePublicKey(theParams.mPublicKey, true))
            return;
      }
      if(mPrivateKey.isNull() || mPrivateKey->getKeySize() != theParams.mPublicKey->getKeySize())
      {
         // we don't have a private key, so generate one for this connection
         theParams.mPrivateKey = new AsymmetricKey(theParams.mPublicKey->getKeySize());
      }
      else
         theParams.mPrivateKey = mPrivateKey;
      theParams.mSharedSecret = theParams.mPrivateKey->computeSharedSecretKey(theParams.mPublicKey);
      //logprintf("shared secret (client) %s", theParams.mSharedSecret->encodeBase64()->getBuffer());
      Random::read(theParams.mSymmetricKey, SymmetricCipher::KeySize);
      theParams.mUsingCrypto = true;
   }

   logprintf(LogConsumer::LogNetInterface, "Received Challenge Response: %8x", theParams.mClientIdentity);

   conn->setConnectionState(NetConnection::ComputingPuzzleSolution);
   conn->mConnectSendCount = 0;

   theParams.mPuzzleSolution = 0;
   conn->mConnectLastSendTime = getCurrentTime();
   continuePuzzleSolution(conn);
}