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); }
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); }
void NetInterface::handleConnectRequest(const NetAddress *address, BitStream *stream) { if(!mAllowConnections) return; Con::printf("Got Connect Request"); U32 connectSequence; stream->read(&connectSequence); // see if the connection is in the main connection table: NetConnection *connect = NetConnection::lookup(address); if(connect && connect->getSequence() == connectSequence) { sendConnectAccept(connect); return; } U32 addressDigest[4]; U32 computedAddressDigest[4]; stream->read(&addressDigest[0]); stream->read(&addressDigest[1]); stream->read(&addressDigest[2]); stream->read(&addressDigest[3]); computeNetMD5(address, connectSequence, computedAddressDigest); if(addressDigest[0] != computedAddressDigest[0] || addressDigest[1] != computedAddressDigest[1] || addressDigest[2] != computedAddressDigest[2] || addressDigest[3] != computedAddressDigest[3]) return; // bogus connection attempt if(connect) { if(connect->getSequence() > connectSequence) return; // the existing connection should be kept - the incoming request is stale. else connect->deleteObject(); // disconnect this one, and allow the new one to be created. } char connectionClass[255]; stream->readString(connectionClass); ConsoleObject *co = ConsoleObject::create(connectionClass); NetConnection *conn = dynamic_cast<NetConnection *>(co); if(!conn || !conn->canRemoteCreate()) { delete co; return; } conn->registerObject(); conn->setNetAddress(address); conn->setNetworkConnection(true); conn->setSequence(connectSequence); const char *errorString = NULL; if(!conn->readConnectRequest(stream, &errorString)) { sendConnectReject(conn, errorString); conn->deleteObject(); return; } conn->setNetworkConnection(true); conn->onConnectionEstablished(false); conn->setEstablished(); conn->setConnectSequence(connectSequence); sendConnectAccept(conn); }