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); }
void NetInterface::handleConnectReject(const NetAddress *address, BitStream *stream) { U32 connectSequence; stream->read(&connectSequence); NetConnection *conn = findPendingConnection(address, connectSequence); if(!conn || (conn->getConnectionState() != NetConnection::AwaitingChallengeResponse && conn->getConnectionState() != NetConnection::AwaitingConnectResponse)) return; removePendingConnection(conn); char reason[256]; stream->readString(reason); conn->onConnectionRejected(reason); conn->deleteObject(); }
void NetInterface::handleConnectAccept(const Address &address, BitStream *stream) { Nonce nonce, serverNonce; nonce.read(stream); serverNonce.read(stream); U32 decryptPos = stream->getBytePosition(); stream->setBytePosition(decryptPos); // Make sure we're actually waiting for a connection. If not, then there's something wrong, and we bail. 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); NetConnection::TerminationReason reason; if(!conn->readConnectAccept(stream, reason)) { 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); // then remove it from the pending connection list conn->setConnectionState(NetConnection::Connected); conn->onConnectionEstablished(); // notify the connection that it has been established logprintf(LogConsumer::LogNetInterface, "Received Connect Accept - connection established."); }
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.")); }
void NetInterface::handleConnectAccept(const NetAddress *address, BitStream *stream) { U32 connectSequence; stream->read(&connectSequence); NetConnection *conn = findPendingConnection(address, connectSequence); if(!conn || conn->getConnectionState() != NetConnection::AwaitingConnectResponse) return; const char *errorString = NULL; if(!conn->readConnectAccept(stream, &errorString)) { conn->handleStartupError(errorString); removePendingConnection(conn); conn->deleteObject(); return; } removePendingConnection(conn); // remove from the pending connection list conn->setNetworkConnection(true); conn->onConnectionEstablished(true); // notify the connection that it has been established conn->setEstablished(); // installs the connection in the connection table, and causes pings/timeouts to happen conn->setConnectSequence(connectSequence); }
void NetInterface::handleConnectChallengeResponse(const NetAddress *address, BitStream *stream) { Con::printf("Got Connect challenge Response"); U32 connectSequence; stream->read(&connectSequence); NetConnection *conn = findPendingConnection(address, connectSequence); if(!conn || conn->getConnectionState() != NetConnection::AwaitingChallengeResponse) return; U32 addressDigest[4]; stream->read(&addressDigest[0]); stream->read(&addressDigest[1]); stream->read(&addressDigest[2]); stream->read(&addressDigest[3]); conn->setAddressDigest(addressDigest); conn->setConnectionState(NetConnection::AwaitingConnectResponse); conn->mConnectSendCount = 0; Con::printf("Sending Connect Request"); sendConnectRequest(conn); }
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); }
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); }