Browse Source

Merge pull request #69 from diafero/config-simplification

Config simplification
Darryl Pogue 13 years ago
parent
commit
c0a5199957
  1. 6
      Sources/Plasma/NucleusLib/pnNetCli/pnNcChannel.cpp
  2. 146
      Sources/Plasma/NucleusLib/pnNetCli/pnNcCli.cpp
  3. 28
      Sources/Plasma/NucleusLib/pnNetCli/pnNcEncrypt.cpp
  4. 4
      Sources/Plasma/NucleusLib/pnUtils/Private/pnUtBigNum.h
  5. 53
      Sources/Plasma/PubUtilLib/plNetClientComm/plNetClientComm.cpp
  6. 12
      Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglGateKeeper.cpp

6
Sources/Plasma/NucleusLib/pnNetCli/pnNcChannel.cpp

@ -341,9 +341,9 @@ void NetMsgChannelGetDhConstants (
const BigNum ** dh_xa, const BigNum ** dh_xa,
const BigNum ** dh_n const BigNum ** dh_n
) { ) {
*dh_g = channel->m_dh_g; if (dh_g) *dh_g = channel->m_dh_g;
*dh_xa = &channel->m_dh_xa; if (dh_xa) *dh_xa = &channel->m_dh_xa;
*dh_n = &channel->m_dh_n; if (dh_n) *dh_n = &channel->m_dh_n;
} }

146
Sources/Plasma/NucleusLib/pnNetCli/pnNcCli.cpp

@ -40,8 +40,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
# define NCCLI_LOG NULL_STMT # define NCCLI_LOG NULL_STMT
#endif #endif
//#define NO_ENCRYPTION
#ifndef PLASMA_EXTERNAL_RELEASE #ifndef PLASMA_EXTERNAL_RELEASE
struct NetLogMessage_Header struct NetLogMessage_Header
@ -120,8 +118,8 @@ struct NetCli : THashKeyVal<Uuid> {
ENetCliMode mode; ENetCliMode mode;
FNetCliEncrypt encryptFcn; FNetCliEncrypt encryptFcn;
byte seed[kNetMaxSymmetricSeedBytes]; byte seed[kNetMaxSymmetricSeedBytes];
CryptKey * cryptIn; CryptKey * cryptIn; // nil if encrytpion is disabled
CryptKey * cryptOut; CryptKey * cryptOut; // nil if encrytpion is disabled
void * encryptParam; void * encryptParam;
// Message buffers // Message buffers
@ -174,9 +172,8 @@ static void PutBufferOnWire (NetCli * cli, void * data, unsigned bytes) {
} }
#endif // PLASMA_EXTERNAL_RELEASE #endif // PLASMA_EXTERNAL_RELEASE
if (cli->mode == kNetCliModeEncrypted) { if (cli->mode == kNetCliModeEncrypted && cli->cryptOut) {
// Encrypt data... // Encrypt data...
#ifndef NO_ENCRYPTION
if (bytes <= 2048) if (bytes <= 2048)
// byte count is small, use stack-based buffer // byte count is small, use stack-based buffer
temp = ALLOCA(byte, bytes); temp = ALLOCA(byte, bytes);
@ -187,7 +184,6 @@ static void PutBufferOnWire (NetCli * cli, void * data, unsigned bytes) {
MemCopy(temp, data, bytes); MemCopy(temp, data, bytes);
CryptEncrypt(cli->cryptOut, bytes, temp); CryptEncrypt(cli->cryptOut, bytes, temp);
data = temp; data = temp;
#endif
} }
if (cli->sock) if (cli->sock)
AsyncSocketSend(cli->sock, data, bytes); AsyncSocketSend(cli->sock, data, bytes);
@ -644,7 +640,7 @@ static void ClientConnect (NetCli * cli) {
if (cli->sock) { if (cli->sock) {
unsigned bytes; unsigned bytes;
NetCli_Cli2Srv_Connect msg; NetCli_Cli2Srv_Connect msg;
unsigned char * data = serverSeed.GetData_LE(&bytes); unsigned char * data = serverSeed.GetData_LE(&bytes); // will be 0 if encryption is disabled, and thereby send an empty seed
ASSERTMSG(bytes <= sizeof(msg.dh_y_data), "4"); ASSERTMSG(bytes <= sizeof(msg.dh_y_data), "4");
msg.message = kNetCliCli2SrvConnect; msg.message = kNetCliCli2SrvConnect;
msg.length = (byte) (sizeof(msg) - sizeof(msg.dh_y_data) + bytes); msg.length = (byte) (sizeof(msg) - sizeof(msg.dh_y_data) + bytes);
@ -668,48 +664,55 @@ static bool ServerRecvConnect (
* (const NetCli_Cli2Srv_Connect *) &pkt; * (const NetCli_Cli2Srv_Connect *) &pkt;
if (pkt.length < sizeof(msg)) if (pkt.length < sizeof(msg))
return false; return false;
int seedLength = msg.length - sizeof(pkt);
// Send the server seed to the client (unencrypted) // Send the server seed to the client (unencrypted)
if (cli->sock) { if (cli->sock) {
NetCli_Srv2Cli_Encrypt reply; NetCli_Srv2Cli_Encrypt reply;
reply.message = kNetCliSrv2CliEncrypt; reply.message = kNetCliSrv2CliEncrypt;
reply.length = sizeof(reply); reply.length = seedLength == 0 ? 0 : sizeof(reply); // reply with empty seed if we got empty seed (this means: no encryption)
MemCopy(reply.serverSeed, cli->seed, sizeof(reply.serverSeed)); MemCopy(reply.serverSeed, cli->seed, sizeof(reply.serverSeed));
AsyncSocketSend(cli->sock, &reply, sizeof(reply)); AsyncSocketSend(cli->sock, &reply, reply.length);
} }
// Compute client seed if (seedLength == 0) { // client wishes no encryption (that's okay, nobody else can "fake" us as nobody has the private key, so if the client actually wants encryption it will only work with the correct peer)
byte clientSeed[kNetMaxSymmetricSeedBytes]; cli->cryptIn = nil;
{ cli->cryptOut = nil;
}
else {
// Compute client seed
byte clientSeed[kNetMaxSymmetricSeedBytes];
BigNum clientSeedValue; BigNum clientSeedValue;
NetMsgCryptServerConnect( {
cli->channel, NetMsgCryptServerConnect(
msg.length - sizeof(pkt), cli->channel,
msg.dh_y_data, seedLength,
&clientSeedValue msg.dh_y_data,
&clientSeedValue
);
ZERO(clientSeed);
unsigned bytes;
unsigned char * data = clientSeedValue.GetData_LE(&bytes);
MemCopy(clientSeed, data, min(bytes, sizeof(clientSeed)));
delete [] data;
}
// Create the symmetric key from a combination
// of the client seed and the server seed
byte sharedSeed[kNetMaxSymmetricSeedBytes];
CreateSymmetricKey(
sizeof(cli->seed), cli->seed, // server seed
sizeof(clientSeed), clientSeed, // client seed
sizeof(sharedSeed), sharedSeed // combined seed
); );
ZERO(clientSeed); // Switch to encrypted mode
unsigned bytes; cli->cryptIn = CryptKeyCreate(kCryptRc4, sizeof(sharedSeed), sharedSeed);
unsigned char * data = clientSeedValue.GetData_LE(&bytes); cli->cryptOut = CryptKeyCreate(kCryptRc4, sizeof(sharedSeed), sharedSeed);
MemCopy(clientSeed, data, min(bytes, sizeof(clientSeed)));
delete [] data;
} }
// Create the symmetric key from a combination cli->mode = kNetCliModeEncrypted; // should rather be called "established", but whatever
// of the client seed and the server seed
byte sharedSeed[kNetMaxSymmetricSeedBytes];
CreateSymmetricKey(
sizeof(cli->seed), cli->seed, // server seed
sizeof(clientSeed), clientSeed, // client seed
sizeof(sharedSeed), sharedSeed // combined seed
);
// Switch to encrypted mode
cli->mode = kNetCliModeEncrypted;
cli->cryptIn = CryptKeyCreate(kCryptRc4, sizeof(sharedSeed), sharedSeed);
cli->cryptOut = CryptKeyCreate(kCryptRc4, sizeof(sharedSeed), sharedSeed);
return cli->encryptFcn(kNetSuccess, cli->encryptParam); return cli->encryptFcn(kNetSuccess, cli->encryptParam);
} }
@ -722,26 +725,39 @@ static bool ClientRecvEncrypt (
if (cli->mode != kNetCliModeClientStart) if (cli->mode != kNetCliModeClientStart)
return false; return false;
// Validate message size // find out if we want encryption
const BigNum * DH_N;
NetMsgChannelGetDhConstants(cli->channel, nil, nil, &DH_N);
bool encrypt = !DH_N->isZero();
// Process message
const NetCli_Srv2Cli_Encrypt & msg = const NetCli_Srv2Cli_Encrypt & msg =
* (const NetCli_Srv2Cli_Encrypt *) &pkt; * (const NetCli_Srv2Cli_Encrypt *) &pkt;
if (pkt.length != sizeof(msg)) if (encrypt) { // we insist on encryption, don't let some MitM decide for us!
return false; if (pkt.length != sizeof(msg))
return false;
// Create the symmetric key from a combination // Create the symmetric key from a combination
// of the client seed and the server seed // of the client seed and the server seed
byte sharedSeed[kNetMaxSymmetricSeedBytes]; byte sharedSeed[kNetMaxSymmetricSeedBytes];
CreateSymmetricKey( CreateSymmetricKey(
sizeof(msg.serverSeed), msg.serverSeed, // server seed sizeof(msg.serverSeed), msg.serverSeed, // server seed
sizeof(cli->seed), cli->seed, // client seed sizeof(cli->seed), cli->seed, // client seed
sizeof(sharedSeed), sharedSeed // combined seed sizeof(sharedSeed), sharedSeed // combined seed
); );
// Switch to encrypted mode // Switch to encrypted mode
cli->mode = kNetCliModeEncrypted; cli->cryptIn = CryptKeyCreate(kCryptRc4, sizeof(sharedSeed), sharedSeed);
cli->cryptIn = CryptKeyCreate(kCryptRc4, sizeof(sharedSeed), sharedSeed); cli->cryptOut = CryptKeyCreate(kCryptRc4, sizeof(sharedSeed), sharedSeed);
cli->cryptOut = CryptKeyCreate(kCryptRc4, sizeof(sharedSeed), sharedSeed); }
else { // honestly we do not care what the other side sends, we will send plaintext
if (pkt.length != sizeof(pkt))
return false;
cli->cryptIn = nil;
cli->cryptOut = nil;
}
cli->mode = kNetCliModeEncrypted; // should rather be called "established", but whatever
return cli->encryptFcn(kNetSuccess, cli->encryptParam); return cli->encryptFcn(kNetSuccess, cli->encryptParam);
} }
@ -1061,18 +1077,18 @@ bool NetCliDispatch (
// Decrypt data... // Decrypt data...
byte * temp, * heap = NULL; byte * temp, * heap = NULL;
#ifndef NO_ENCRYPTION if (cli->cryptIn) {
if (bytes <= 2048) if (bytes <= 2048)
// byte count is small, use stack-based buffer // byte count is small, use stack-based buffer
temp = ALLOCA(byte, bytes); temp = ALLOCA(byte, bytes);
else else
// byte count is large, use heap-based buffer // byte count is large, use heap-based buffer
temp = heap = (byte *)ALLOC(bytes); temp = heap = (byte *)ALLOC(bytes);
MemCopy(temp, data, bytes); MemCopy(temp, data, bytes);
CryptDecrypt(cli->cryptIn, bytes, temp); CryptDecrypt(cli->cryptIn, bytes, temp);
data = temp; data = temp;
#endif }
// Add data to accumulator and dispatch // Add data to accumulator and dispatch
cli->input.Add(bytes, data); cli->input.Add(bytes, data);

28
Sources/Plasma/NucleusLib/pnNetCli/pnNcEncrypt.cpp

@ -83,6 +83,7 @@ static void GetCachedServerKey (
const BigNum * DH_A; const BigNum * DH_A;
const BigNum * DH_N; const BigNum * DH_N;
NetMsgChannelGetDhConstants(channel, &DH_G, &DH_A, &DH_N); NetMsgChannelGetDhConstants(channel, &DH_G, &DH_A, &DH_N);
hsAssert(!DH_N->isZero(), "DH_N must not be zero in encrypted mode");
// Compute the result // Compute the result
ka->PowMod(dh_y, *DH_A, *DH_N); ka->PowMod(dh_y, *DH_A, *DH_N);
@ -107,17 +108,22 @@ void NetMsgCryptClientStart (
const BigNum * DH_X; const BigNum * DH_X;
const BigNum * DH_N; const BigNum * DH_N;
NetMsgChannelGetDhConstants(channel, &DH_G, &DH_X, &DH_N); NetMsgChannelGetDhConstants(channel, &DH_G, &DH_X, &DH_N);
if (DH_N->isZero()) { // no actual encryption, but the caller expects a seed
// Client chooses b and y on connect clientSeed->SetZero();
BigNum g(DH_G); serverSeed->SetZero();
BigNum seed(seedBytes, seedData); }
BigNum b; b.Rand(kNetDiffieHellmanKeyBits, &seed); else {
// Client chooses b and y on connect
// Client computes key: kb = x^b mod n BigNum g(DH_G);
clientSeed->PowMod(*DH_X, b, *DH_N); BigNum seed(seedBytes, seedData);
BigNum b; b.Rand(kNetDiffieHellmanKeyBits, &seed);
// Client sends y to server
serverSeed->PowMod(g, b, *DH_N); // Client computes key: kb = x^b mod n
clientSeed->PowMod(*DH_X, b, *DH_N);
// Client sends y to server
serverSeed->PowMod(g, b, *DH_N);
}
} }
//============================================================================ //============================================================================

4
Sources/Plasma/NucleusLib/pnUtils/Private/pnUtBigNum.h

@ -89,6 +89,10 @@ public:
{ {
return BN_cmp(&m_number, &a.m_number); return BN_cmp(&m_number, &a.m_number);
} }
bool isZero() const
{
return BN_is_zero(&m_number);
}
void Div (const BigNum & a, dword b, dword * remainder) void Div (const BigNum & a, dword b, dword * remainder)
{ {

53
Sources/Plasma/PubUtilLib/plNetClientComm/plNetClientComm.cpp

@ -91,8 +91,10 @@ static NetCommAge s_age;
static NetCommAge s_startupAge; static NetCommAge s_startupAge;
static bool s_needAvatarLoad = true; static bool s_needAvatarLoad = true;
static bool s_loginComplete = false; static bool s_loginComplete = false;
static bool s_hasAuthSrvIpAddress = false;
static bool s_hasFileSrvIpAddress = false; static bool s_hasFileSrvIpAddress = false;
static ENetError s_authResult = kNetErrAuthenticationFailed; static ENetError s_authResult = kNetErrAuthenticationFailed;
static wchar s_authSrvAddr[256];
static wchar s_fileSrvAddr[256]; static wchar s_fileSrvAddr[256];
static wchar s_iniServerAddr[256]; static wchar s_iniServerAddr[256];
@ -829,6 +831,16 @@ static void IReadNetIni() {
IniClose(ini); IniClose(ini);
} }
//============================================================================
static void AuthSrvIpAddressCallback (
ENetError result,
void * param,
const wchar addr[]
) {
StrCopy(s_authSrvAddr, addr, arrsize(s_authSrvAddr));
s_hasAuthSrvIpAddress = true;
}
//============================================================================ //============================================================================
static void FileSrvIpAddressCallback ( static void FileSrvIpAddressCallback (
ENetError result, ENetError result,
@ -979,21 +991,47 @@ void NetCommConnect () {
const wchar ** addrs; const wchar ** addrs;
unsigned count; unsigned count;
hsBool connectedToKeeper = false;
count = GetAuthSrvHostnames(&addrs);
NetCliAuthStartConnect(addrs, count); // if a console override was specified for a authserv, connect directly to the authserver rather than going through the gatekeeper
if((count = GetAuthSrvHostnames(&addrs)) && wcslen(addrs[0]))
{
NetCliAuthStartConnect(addrs, count);
}
else
{
count = GetGateKeeperSrvHostnames(&addrs);
NetCliGateKeeperStartConnect(addrs, count);
connectedToKeeper = true;
// request an auth server ip address
NetCliGateKeeperAuthSrvIpAddressRequest(AuthSrvIpAddressCallback, nil);
while(!s_hasAuthSrvIpAddress && !s_netError) {
NetClientUpdate();
AsyncSleep(10);
}
const wchar * authSrv[] = {
s_authSrvAddr
};
NetCliAuthStartConnect(authSrv, 1);
}
if (!gDataServerLocal) { if (!gDataServerLocal) {
// if a console override was specified for a filesrv, connect directly to the fileserver rather than going through the gatekeeper // if a console override was specified for a filesrv, connect directly to the fileserver rather than going through the gatekeeper
if(GetFileSrvHostnames(&addrs) && wcslen(addrs[0])) if((count = GetFileSrvHostnames(&addrs)) && wcslen(addrs[0]))
{ {
NetCliFileStartConnect(addrs, count); NetCliFileStartConnect(addrs, count);
} }
else else
{ {
count = GetGateKeeperSrvHostnames(&addrs); if (!connectedToKeeper) {
NetCliGateKeeperStartConnect(addrs, count); count = GetGateKeeperSrvHostnames(&addrs);
NetCliGateKeeperStartConnect(addrs, count);
connectedToKeeper = true;
}
// request a file server ip address // request a file server ip address
NetCliGateKeeperFileSrvIpAddressRequest(FileSrvIpAddressCallback, nil, false); NetCliGateKeeperFileSrvIpAddressRequest(FileSrvIpAddressCallback, nil, false);
@ -1009,6 +1047,9 @@ void NetCommConnect () {
NetCliFileStartConnect(fileSrv, 1); NetCliFileStartConnect(fileSrv, 1);
} }
} }
if (connectedToKeeper)
NetCliGateKeeperDisconnect();
} }
//============================================================================ //============================================================================

12
Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglGateKeeper.cpp

@ -735,6 +735,7 @@ static NetMsgInitSend s_send[] = {
static NetMsgInitRecv s_recv[] = { static NetMsgInitRecv s_recv[] = {
{ MSG(PingReply) }, { MSG(PingReply) },
{ MSG(FileSrvIpAddressReply) }, { MSG(FileSrvIpAddressReply) },
{ MSG(AuthSrvIpAddressReply) },
}; };
#undef MSG #undef MSG
@ -1115,4 +1116,13 @@ void NetCliGateKeeperFileSrvIpAddressRequest (
) { ) {
FileSrvIpAddressRequestTrans * trans = NEW(FileSrvIpAddressRequestTrans)(callback, param, isPatcher); FileSrvIpAddressRequestTrans * trans = NEW(FileSrvIpAddressRequestTrans)(callback, param, isPatcher);
NetTransSend(trans); NetTransSend(trans);
} }
//============================================================================
void NetCliGateKeeperAuthSrvIpAddressRequest (
FNetCliGateKeeperAuthSrvIpAddressRequestCallback callback,
void * param
) {
AuthSrvIpAddressRequestTrans * trans = NEW(AuthSrvIpAddressRequestTrans)(callback, param);
NetTransSend(trans);
}

Loading…
Cancel
Save