コード例 #1
0
ファイル: netInterface.cpp プロジェクト: HwakyoungLee/opentnl
void NetInterface::handleConnectChallengeResponse(const Address &address, BitStream *stream)
{
   NetConnection *conn = findPendingConnection(address);
   if(!conn || conn->getConnectionState() != NetConnection::AwaitingChallengeResponse)
      return;
   
   Nonce theNonce;
   theNonce.read(stream);

   ConnectionParameters &theParams = conn->getConnectionParameters();
   if(theNonce != theParams.mNonce)
      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)
      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;
   }

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

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

   theParams.mPuzzleSolution = 0;
   conn->mConnectLastSendTime = getCurrentTime();
   continuePuzzleSolution(conn);   
}
コード例 #2
0
ファイル: netInterface.cpp プロジェクト: HwakyoungLee/opentnl
void NetInterface::sendConnectChallengeResponse(const Address &addr, Nonce &clientNonce, bool wantsKeyExchange, bool wantsCertificate)
{
   PacketStream out;
   out.write(U8(ConnectChallengeResponse));
   clientNonce.write(&out);
   
   U32 identityToken = computeClientIdentityToken(addr, clientNonce);
   out.write(identityToken);

   // write out a client puzzle
   Nonce serverNonce = mPuzzleManager.getCurrentNonce();
   U32 difficulty = mPuzzleManager.getCurrentDifficulty();
   serverNonce.write(&out);
   out.write(difficulty);

   if(out.writeFlag(mRequiresKeyExchange || (wantsKeyExchange && !mPrivateKey.isNull())))
   {
      if(out.writeFlag(wantsCertificate && !mCertificate.isNull()))
         out.write(mCertificate);
      else
         out.write(mPrivateKey->getPublicKey());
   }
   TNLLogMessageV(LogNetInterface, ("Sending Challenge Response: %8x", identityToken));

   out.sendto(mSocket, addr);
}
コード例 #3
0
ファイル: netInterface.cpp プロジェクト: HwakyoungLee/opentnl
void NetInterface::handleConnectChallengeRequest(const Address &addr, BitStream *stream)
{
   TNLLogMessageV(LogNetInterface, ("Received Connect Challenge Request from %s", addr.toString()));

   if(!mAllowConnections)
      return;
   Nonce clientNonce;
   clientNonce.read(stream);
   bool wantsKeyExchange = stream->readFlag();
   bool wantsCertificate = stream->readFlag();

   sendConnectChallengeResponse(addr, clientNonce, wantsKeyExchange, wantsCertificate);
}
コード例 #4
0
ファイル: netInterface.cpp プロジェクト: HwakyoungLee/opentnl
void NetInterface::sendConnectChallengeRequest(NetConnection *conn)
{
   TNLLogMessageV(LogNetInterface, ("Sending Connect Challenge Request to %s", conn->getNetAddress().toString()));
   PacketStream out;
   out.write(U8(ConnectChallengeRequest));
   ConnectionParameters &params = conn->getConnectionParameters();
   params.mNonce.write(&out);
   out.writeFlag(params.mRequestKeyExchange);
   out.writeFlag(params.mRequestCertificate);
 
   conn->mConnectSendCount++;
   conn->mConnectLastSendTime = getCurrentTime();
   out.sendto(mSocket, conn->getNetAddress());
}
コード例 #5
0
ファイル: netInterface.cpp プロジェクト: HwakyoungLee/opentnl
void NetInterface::handleConnectAccept(const Address &address, BitStream *stream)
{
   Nonce nonce, serverNonce;

   nonce.read(stream);
   serverNonce.read(stream);
   U32 decryptPos = stream->getBytePosition();
   stream->setBytePosition(decryptPos);

   NetConnection *conn = findPendingConnection(address);
   if(!conn || conn->getConnectionState() != NetConnection::AwaitingConnectResponse)
      return;

   ConnectionParameters &theParams = conn->getConnectionParameters();

   if(theParams.mNonce != nonce || theParams.mServerNonce != serverNonce)
      return;

   if(theParams.mUsingCrypto)
   {
      SymmetricCipher theCipher(theParams.mSharedSecret);
      if(!stream->decryptAndCheckHash(NetConnection::MessageSignatureBytes, decryptPos, &theCipher))
         return;
   }
   U32 recvSequence;
   stream->read(&recvSequence);
   conn->setInitialRecvSequence(recvSequence);

   const char *errorString = NULL;
   if(!conn->readConnectAccept(stream, &errorString))
   {
      removePendingConnection(conn);
      return;
   }
   if(theParams.mUsingCrypto)
   {
      stream->read(SymmetricCipher::KeySize, theParams.mInitVector);
      conn->setSymmetricCipher(new SymmetricCipher(theParams.mSymmetricKey, theParams.mInitVector));
   }

   addConnection(conn); // first, add it as a regular connection
   removePendingConnection(conn); // remove from the pending connection list

   conn->setConnectionState(NetConnection::Connected);
   conn->onConnectionEstablished(); // notify the connection that it has been established
   TNLLogMessageV(LogNetInterface, ("Received Connect Accept - connection established."));
}
コード例 #6
0
ファイル: netInterface.cpp プロジェクト: HwakyoungLee/opentnl
void NetInterface::sendConnectRequest(NetConnection *conn)
{
   TNLLogMessageV(LogNetInterface, ("Sending Connect Request"));
   PacketStream out;
   ConnectionParameters &theParams = conn->getConnectionParameters();

   out.write(U8(ConnectRequest));
   theParams.mNonce.write(&out);
   theParams.mServerNonce.write(&out);
   out.write(theParams.mClientIdentity);
   out.write(theParams.mPuzzleDifficulty);
   out.write(theParams.mPuzzleSolution);

   U32 encryptPos = 0;

   if(out.writeFlag(theParams.mUsingCrypto))
   {
      out.write(theParams.mPrivateKey->getPublicKey());
      encryptPos = out.getBytePosition();
      out.setBytePosition(encryptPos);
      out.write(SymmetricCipher::KeySize, theParams.mSymmetricKey);
   }
   out.writeFlag(theParams.mDebugObjectSizes);
   out.write(conn->getInitialSendSequence());
   out.writeString(conn->getClassName());
   conn->writeConnectRequest(&out);

   if(encryptPos)
   {
      // if we're using crypto on this connection,
      // then write a hash of everything we wrote into the packet
      // key.  Then we'll symmetrically encrypt the packet from
      // the end of the public key to the end of the signature.

      SymmetricCipher theCipher(theParams.mSharedSecret);
      out.hashAndEncrypt(NetConnection::MessageSignatureBytes, encryptPos, &theCipher);      
   }

   conn->mConnectSendCount++;
   conn->mConnectLastSendTime = getCurrentTime();

   out.sendto(mSocket, conn->getNetAddress());
}
コード例 #7
0
ファイル: netInterface.cpp プロジェクト: HwakyoungLee/opentnl
void NetInterface::sendPunchPackets(NetConnection *conn)
{
   ConnectionParameters &theParams = conn->getConnectionParameters();
   PacketStream out;
   out.write(U8(Punch));

   if(theParams.mIsInitiator)
      theParams.mNonce.write(&out);
   else
      theParams.mServerNonce.write(&out);

   U32 encryptPos = out.getBytePosition();
   out.setBytePosition(encryptPos);

   if(theParams.mIsInitiator)
      theParams.mServerNonce.write(&out);
   else
   {
      theParams.mNonce.write(&out);
      if(out.writeFlag(mRequiresKeyExchange || (theParams.mRequestKeyExchange && !mPrivateKey.isNull())))
      {
         if(out.writeFlag(theParams.mRequestCertificate && !mCertificate.isNull()))
            out.write(mCertificate);
         else
            out.write(mPrivateKey->getPublicKey());
      }
   }
   SymmetricCipher theCipher(theParams.mArrangedSecret);
   out.hashAndEncrypt(NetConnection::MessageSignatureBytes, encryptPos, &theCipher);

   for(S32 i = 0; i < theParams.mPossibleAddresses.size(); i++)
   {
      out.sendto(mSocket, theParams.mPossibleAddresses[i]);

      TNLLogMessageV(LogNetInterface, ("Sending punch packet (%s, %s) to %s",
         ByteBuffer(theParams.mNonce.data, Nonce::NonceSize).encodeBase64()->getBuffer(),
         ByteBuffer(theParams.mServerNonce.data, Nonce::NonceSize).encodeBase64()->getBuffer(),
         theParams.mPossibleAddresses[i].toString()));
   }
   conn->mConnectSendCount++;
   conn->mConnectLastSendTime = getCurrentTime();
}
コード例 #8
0
ファイル: netInterface.cpp プロジェクト: HwakyoungLee/opentnl
void NetInterface::sendArrangedConnectRequest(NetConnection *conn)
{
   TNLLogMessageV(LogNetInterface, ("Sending Arranged Connect Request"));
   PacketStream out;

   ConnectionParameters &theParams = conn->getConnectionParameters();

   out.write(U8(ArrangedConnectRequest));
   theParams.mNonce.write(&out);
   U32 encryptPos = out.getBytePosition();
   U32 innerEncryptPos = 0;

   out.setBytePosition(encryptPos);

   theParams.mServerNonce.write(&out);
   if(out.writeFlag(theParams.mUsingCrypto))
   {
      out.write(theParams.mPrivateKey->getPublicKey());
      innerEncryptPos = out.getBytePosition();
      out.setBytePosition(innerEncryptPos);
      out.write(SymmetricCipher::KeySize, theParams.mSymmetricKey);
   }
   out.writeFlag(theParams.mDebugObjectSizes);
   out.write(conn->getInitialSendSequence());
   conn->writeConnectRequest(&out);

   if(innerEncryptPos)
   {
      SymmetricCipher theCipher(theParams.mSharedSecret);
      out.hashAndEncrypt(NetConnection::MessageSignatureBytes, innerEncryptPos, &theCipher);
   }
   SymmetricCipher theCipher(theParams.mArrangedSecret);
   out.hashAndEncrypt(NetConnection::MessageSignatureBytes, encryptPos, &theCipher);

   conn->mConnectSendCount++;
   conn->mConnectLastSendTime = getCurrentTime();

   out.sendto(mSocket, conn->getNetAddress());
}
コード例 #9
0
void GhostConnection::activateGhosting()
{
   if(!doesGhostFrom())
      return;

   mGhostingSequence++;
   TNLLogMessageV(LogGhostConnection, ("Ghosting activated - %d", mGhostingSequence));
   
   TNLAssert((mGhostFreeIndex == 0) && (mGhostZeroUpdateIndex == 0), "Error: ghosts in the ghost list before activate.");
   
   // iterate through the ghost always objects and InScope them...
   // also post em all to the other side.

   S32 j;
   for(j = 0; j < MaxGhostCount; j++)
   {
      mGhostArray[j] = mGhostRefs + j;
      mGhostArray[j]->arrayIndex = j;
   }
   mScoping = true; // so that objectInScope will work

   rpcStartGhosting(mGhostingSequence);
   //TNLAssert(validateGhostArray(), "Invalid ghost array!");
}
コード例 #10
0
ファイル: netInterface.cpp プロジェクト: HwakyoungLee/opentnl
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);
}
コード例 #11
0
ファイル: netInterface.cpp プロジェクト: HwakyoungLee/opentnl
void NetInterface::sendConnectAccept(NetConnection *conn)
{
   TNLLogMessageV(LogNetInterface, ("Sending Connect Accept - connection established."));

   PacketStream out;
   out.write(U8(ConnectAccept));
   ConnectionParameters &theParams = conn->getConnectionParameters();

   theParams.mNonce.write(&out);
   theParams.mServerNonce.write(&out);
   U32 encryptPos = out.getBytePosition();
   out.setBytePosition(encryptPos);

   out.write(conn->getInitialSendSequence());
   conn->writeConnectAccept(&out);

   if(theParams.mUsingCrypto)
   {
      out.write(SymmetricCipher::KeySize, theParams.mInitVector);
      SymmetricCipher theCipher(theParams.mSharedSecret);
      out.hashAndEncrypt(NetConnection::MessageSignatureBytes, encryptPos, &theCipher);
   }
   out.sendto(mSocket, conn->getNetAddress());
}
コード例 #12
0
void GhostConnection::writePacket(BitStream *bstream, PacketNotify *pnotify)
{
   Parent::writePacket(bstream, pnotify);
   GhostPacketNotify *notify = static_cast<GhostPacketNotify *>(pnotify);

   if(mConnectionParameters.mDebugObjectSizes)
      bstream->writeInt(DebugChecksum, 32);

   notify->ghostList = NULL;
   
   if(!doesGhostFrom())
      return;
   
   if(!bstream->writeFlag(mGhosting && mScopeObject.isValid()))
      return;
      
   // fill a packet (or two) with ghosting data

   // 2. call scoped objects' priority functions if the flag set is nonzero
   //    A removed ghost is assumed to have a high priority
   // 3. call updates based on sorted priority until the packet is
   //    full.  set flags to zero for all updated objects

   GhostInfo *walk;

   for(S32 i = mGhostZeroUpdateIndex - 1; i >= 0; i--)
   {
      if(!(mGhostArray[i]->flags & GhostInfo::InScope))
         detachObject(mGhostArray[i]);
   }

   U32 maxIndex = 0;
   for(S32 i = mGhostZeroUpdateIndex - 1; i >= 0; i--)
   {
      walk = mGhostArray[i];
      if(walk->index > maxIndex)
         maxIndex = walk->index;

      // clear out any kill objects that haven't been ghosted yet
      if((walk->flags & GhostInfo::KillGhost) && (walk->flags & GhostInfo::NotYetGhosted))
      {
         freeGhostInfo(walk);
         continue;
      }
      // don't do any ghost processing on objects that are being killed
      // or in the process of ghosting
      else if(!(walk->flags & (GhostInfo::KillingGhost | GhostInfo::Ghosting)))
      {
         if(walk->flags & GhostInfo::KillGhost)
            walk->priority = 10000;
         else
            walk->priority = walk->obj->getUpdatePriority(mScopeObject, walk->updateMask, walk->updateSkipCount);
      }
      else
         walk->priority = 0;
   }
   GhostRef *updateList = NULL;
   qsort(mGhostArray, mGhostZeroUpdateIndex, sizeof(GhostInfo *), UQECompare);
   // reset the array indices...
   for(S32 i = mGhostZeroUpdateIndex - 1; i >= 0; i--)
      mGhostArray[i]->arrayIndex = i;

   S32 sendSize = 1;
   while(maxIndex >>= 1)
      sendSize++;

   if(sendSize < 3)
      sendSize = 3;

   bstream->writeInt(sendSize - 3, 3); // 0-7 3 bit number

   U32 count = 0;
   // 
   for(S32 i = mGhostZeroUpdateIndex - 1; i >= 0 && !bstream->isFull(); i--)
   {
      GhostInfo *walk = mGhostArray[i];
		if(walk->flags & (GhostInfo::KillingGhost | GhostInfo::Ghosting))
		   continue;

      size_t updateStart = bstream->getBitPosition();
      U32 updateMask = walk->updateMask;
      U32 retMask = 0;
		   
      bstream->writeFlag(true);
      bstream->writeInt(walk->index, sendSize);
      if(!bstream->writeFlag(walk->flags & GhostInfo::KillGhost))
      {
         // this is an update of some kind:
         if(mConnectionParameters.mDebugObjectSizes)
            bstream->advanceBitPosition(BitStreamPosBitSize);

         size_t startPos = bstream->getBitPosition();

         if(walk->flags & GhostInfo::NotYetGhosted)
         {
            S32 classId = walk->obj->getClassId(getNetClassGroup());
            bstream->writeClassId(classId, NetClassTypeObject, getNetClassGroup());
            NetObject::mIsInitialUpdate = true;
         }

         // update the object
         retMask = walk->obj->packUpdate(this, updateMask, bstream);

         if(NetObject::mIsInitialUpdate)
         {
            NetObject::mIsInitialUpdate = false;
            walk->obj->getClassRep()->addInitialUpdate(bstream->getBitPosition() - startPos);
         }
         else
            walk->obj->getClassRep()->addPartialUpdate(bstream->getBitPosition() - startPos);

		  if(mConnectionParameters.mDebugObjectSizes){
			  size_t bpL = bstream->getBitPosition();
			  U32 bp = static_cast<U32>(bpL);
			  TNLAssert(bp == bpL, "This stream position is too long");
			bstream->writeIntAt(bp, BitStreamPosBitSize, startPos - BitStreamPosBitSize);
		  }
		  

         TNLLogMessageV(LogGhostConnection, ("GhostConnection %s GHOST %d", walk->obj->getClassName(), bstream->getBitPosition() - 16 - startPos));

         TNLAssert((retMask & (~updateMask)) == 0, "Cannot set new bits in packUpdate return");
      }

      // check for packet overrun, and rewind this update if there
      // was one:
      if(bstream->getBitSpaceAvailable() < MinimumPaddingBits)
      {
         bstream->setBitPosition(updateStart);
         bstream->clearError();
         break;
      }

      // otherwise, create a record of this ghost update and
      // attach it to the packet.
      GhostRef *upd = new GhostRef;

      upd->nextRef = updateList;
      updateList = upd;

      if(walk->lastUpdateChain)
         walk->lastUpdateChain->updateChain = upd;
      walk->lastUpdateChain = upd;

      upd->ghost = walk;
      upd->ghostInfoFlags = 0;
      upd->updateChain = NULL;

      if(walk->flags & GhostInfo::KillGhost)
      {
         walk->flags &= ~GhostInfo::KillGhost;
         walk->flags |= GhostInfo::KillingGhost;
         walk->updateMask = 0;
         upd->mask = updateMask;
         ghostPushToZero(walk);
         upd->ghostInfoFlags = GhostInfo::KillingGhost;
      }
      else
      {
         if(walk->flags & GhostInfo::NotYetGhosted)
         {
            walk->flags &= ~GhostInfo::NotYetGhosted;
            walk->flags |= GhostInfo::Ghosting;
            upd->ghostInfoFlags = GhostInfo::Ghosting;
         }
         walk->updateMask = retMask;
         if(!retMask)
            ghostPushToZero(walk);
         upd->mask = updateMask & ~retMask;
         walk->updateSkipCount = 0;
         count++;
      }
   }
   // count # of ghosts have been updated,
   // mGhostZeroUpdateIndex # of ghosts remain to be updated.
   // no more objects...
   bstream->writeFlag(false);
   notify->ghostList = updateList;
}
コード例 #13
0
ファイル: netInterface.cpp プロジェクト: HwakyoungLee/opentnl
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);
}
コード例 #14
0
ファイル: netInterface.cpp プロジェクト: HwakyoungLee/opentnl
void NetInterface::handleConnectRequest(const Address &address, BitStream *stream)
{
   if(!mAllowConnections)
      return;

   ConnectionParameters theParams;
   theParams.mNonce.read(stream);
   theParams.mServerNonce.read(stream);
   stream->read(&theParams.mClientIdentity);

   if(theParams.mClientIdentity != computeClientIdentityToken(address, theParams.mNonce))
      return;

   stream->read(&theParams.mPuzzleDifficulty);
   stream->read(&theParams.mPuzzleSolution);

   // see if the connection is in the main connection table.
   // If the connection is in the connection table and it has
   // the same initiatorSequence, we'll just resend the connect
   // acceptance packet, assuming that the last time we sent it
   // it was dropped.
   NetConnection *connect = findConnection(address);
   if(connect)
   {
      ConnectionParameters &cp = connect->getConnectionParameters();
      if(cp.mNonce == theParams.mNonce && cp.mServerNonce == theParams.mServerNonce)
      {
         sendConnectAccept(connect);
         return;
      }
   }

   // check the puzzle solution
   ClientPuzzleManager::ErrorCode result = mPuzzleManager.checkSolution(
      theParams.mPuzzleSolution, theParams.mNonce, theParams.mServerNonce,
      theParams.mPuzzleDifficulty, theParams.mClientIdentity);

   if(result != ClientPuzzleManager::Success)
   {
      sendConnectReject(&theParams, address, "Puzzle");
      return;
   }

   if(stream->readFlag())
   {
      if(mPrivateKey.isNull())
         return;

      theParams.mUsingCrypto = true;
      theParams.mPublicKey = new AsymmetricKey(stream);
      theParams.mPrivateKey = mPrivateKey;

      U32 decryptPos = stream->getBytePosition();

      stream->setBytePosition(decryptPos);
      theParams.mSharedSecret = theParams.mPrivateKey->computeSharedSecretKey(theParams.mPublicKey);
      //logprintf("shared secret (server) %s", theParams.mSharedSecret->encodeBase64()->getBuffer());

      SymmetricCipher theCipher(theParams.mSharedSecret);

      if(!stream->decryptAndCheckHash(NetConnection::MessageSignatureBytes, decryptPos, &theCipher))
         return;

      // now read the first part of the connection's symmetric key
      stream->read(SymmetricCipher::KeySize, theParams.mSymmetricKey);
      Random::read(theParams.mInitVector, SymmetricCipher::KeySize);
   }

   U32 connectSequence;
   theParams.mDebugObjectSizes = stream->readFlag();
   stream->read(&connectSequence);
   TNLLogMessageV(LogNetInterface, ("Received Connect Request %8x", theParams.mClientIdentity));

   if(connect)
      disconnect(connect, NetConnection::ReasonSelfDisconnect, "NewConnection");

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

   NetConnection *conn = NetConnectionRep::create(connectionClass);

   if(!conn)
      return;

   RefPtr<NetConnection> theConnection = conn;
   conn->getConnectionParameters() = theParams;

   conn->setNetAddress(address);
   conn->setInitialRecvSequence(connectSequence);
   conn->setInterface(this);

   if(theParams.mUsingCrypto)
      conn->setSymmetricCipher(new SymmetricCipher(theParams.mSymmetricKey, theParams.mInitVector));

   const char *errorString = NULL;
   if(!conn->readConnectRequest(stream, &errorString))
   {
      sendConnectReject(&theParams, address, errorString);
      return;
   }
   addConnection(conn);
   conn->setConnectionState(NetConnection::Connected);
   conn->onConnectionEstablished();
   sendConnectAccept(conn);
}
コード例 #15
0
ファイル: netInterface.cpp プロジェクト: HwakyoungLee/opentnl
void NetInterface::handleArrangedConnectRequest(const Address &theAddress, BitStream *stream)
{
   S32 i, j;
   NetConnection *conn;
   Nonce nonce, serverNonce;
   nonce.read(stream);

   // see if the connection is in the main connection table.
   // If the connection is in the connection table and it has
   // the same initiatorSequence, we'll just resend the connect
   // acceptance packet, assuming that the last time we sent it
   // it was dropped.
   NetConnection *oldConnection = findConnection(theAddress);
   if(oldConnection)
   {
      ConnectionParameters &cp = oldConnection->getConnectionParameters();
      if(cp.mNonce == nonce)
      {
         sendConnectAccept(oldConnection);
         return;
      }
   }

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

      if(conn->getConnectionState() != NetConnection::SendingPunchPackets || theParams.mIsInitiator)
         continue;

      if(nonce != theParams.mNonce)
         continue;

      for(j = 0; j < theParams.mPossibleAddresses.size(); j++)
         if(theAddress.isEqualAddress(theParams.mPossibleAddresses[j]))
            break;
      if(j != theParams.mPossibleAddresses.size())
         break;
   }
   if(i == mPendingConnections.size())
      return;
   
   ConnectionParameters &theParams = conn->getConnectionParameters();
   SymmetricCipher theCipher(theParams.mArrangedSecret);
   if(!stream->decryptAndCheckHash(NetConnection::MessageSignatureBytes, stream->getBytePosition(), &theCipher))
      return;

   stream->setBytePosition(stream->getBytePosition());

   serverNonce.read(stream);
   if(serverNonce != theParams.mServerNonce)
      return;

   if(stream->readFlag())
   {
      if(mPrivateKey.isNull())
         return;
      theParams.mUsingCrypto = true;
      theParams.mPublicKey = new AsymmetricKey(stream);
      theParams.mPrivateKey = mPrivateKey;

      U32 decryptPos = stream->getBytePosition();
      stream->setBytePosition(decryptPos);
      theParams.mSharedSecret = theParams.mPrivateKey->computeSharedSecretKey(theParams.mPublicKey);
      SymmetricCipher theCipher(theParams.mSharedSecret);
      
      if(!stream->decryptAndCheckHash(NetConnection::MessageSignatureBytes, decryptPos, &theCipher))
         return;

      // now read the first part of the connection's session (symmetric) key
      stream->read(SymmetricCipher::KeySize, theParams.mSymmetricKey);
      Random::read(theParams.mInitVector, SymmetricCipher::KeySize);
   }

   U32 connectSequence;
   theParams.mDebugObjectSizes = stream->readFlag();
   stream->read(&connectSequence);
   TNLLogMessageV(LogNetInterface, ("Received Arranged Connect Request"));

   if(oldConnection)
      disconnect(oldConnection, NetConnection::ReasonSelfDisconnect, "");

   conn->setNetAddress(theAddress);
   conn->setInitialRecvSequence(connectSequence);
   if(theParams.mUsingCrypto)
      conn->setSymmetricCipher(new SymmetricCipher(theParams.mSymmetricKey, theParams.mInitVector));

   const char *errorString = NULL;
   if(!conn->readConnectRequest(stream, &errorString))
   {
      sendConnectReject(&theParams, theAddress, errorString);
      removePendingConnection(conn);
      return;
   }
   addConnection(conn);
   removePendingConnection(conn);
   conn->setConnectionState(NetConnection::Connected);
   conn->onConnectionEstablished();
   sendConnectAccept(conn);
}