|
|
|
@ -200,13 +200,25 @@ struct LoginDialogParam {
|
|
|
|
|
wchar accountName[kMaxAccountNameLength]; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// List of hash styles we are going to test against the server
|
|
|
|
|
// ... this method of trying multiple hashes against the server has risks of being more compromised than just testing one hash.
|
|
|
|
|
// ... So, if you know your unique client is only going to connect to your server then it would be wise to limit the testing to one hash.
|
|
|
|
|
// ... Which can be done simply by setting FIRST_PASSWORD_HASH and LAST_PASSWORD_HASH to the hash that you use.
|
|
|
|
|
enum
|
|
|
|
|
{ |
|
|
|
|
kPasswordHashSHA0, |
|
|
|
|
kPasswordHashSHA1 |
|
|
|
|
}; |
|
|
|
|
static const int FIRST_PASSWORD_HASH = kPasswordHashSHA1; |
|
|
|
|
static const int LAST_PASSWORD_HASH = kPasswordHashSHA0; |
|
|
|
|
|
|
|
|
|
bool AuthenticateNetClientComm(ENetError* result, HWND parentWnd); |
|
|
|
|
bool IsExpired(); |
|
|
|
|
bool GetDisksProperty(HANDLE hDevice, PSTORAGE_DEVICE_DESCRIPTOR pDevDesc); |
|
|
|
|
void GetOldCryptKey(UInt32* cryptKey, unsigned size); |
|
|
|
|
void GetCryptKey(UInt32* cryptKey, unsigned size); |
|
|
|
|
static void SaveUserPass (char *username, char *password, ShaDigest *pNamePassHash, bool remember_password, |
|
|
|
|
bool fromGT); |
|
|
|
|
int whichHash); |
|
|
|
|
static void LoadUserPass (const wchar *accountName, char *username, ShaDigest *pNamePassHash, bool *pRemember, |
|
|
|
|
bool fromGT, int *pFocus); |
|
|
|
|
static void AuthFailedStrings (ENetError authError, bool fromGT, |
|
|
|
@ -322,11 +334,22 @@ static bool TGRunLoginDialog (const wchar *accountName, bool fromGT)
|
|
|
|
|
if (Remember[0] == 'y') |
|
|
|
|
bRemember = true; |
|
|
|
|
|
|
|
|
|
SaveUserPass (Username, Password, &NamePassHash, bRemember, fromGT); |
|
|
|
|
|
|
|
|
|
// Do login & see if it failed
|
|
|
|
|
// cycle through the hash types until we find one that matches or errors out
|
|
|
|
|
ENetError auth; |
|
|
|
|
bool cancelled = AuthenticateNetClientComm(&auth, NULL); |
|
|
|
|
bool cancelled; |
|
|
|
|
for (int whichHash=FIRST_PASSWORD_HASH; whichHash >= LAST_PASSWORD_HASH; whichHash-- ) |
|
|
|
|
{ |
|
|
|
|
SaveUserPass (Username, Password, &NamePassHash, bRemember, whichHash); |
|
|
|
|
|
|
|
|
|
// Do login & see if it failed
|
|
|
|
|
cancelled = AuthenticateNetClientComm(&auth, NULL); |
|
|
|
|
// if the password was successful then go to the end processing
|
|
|
|
|
if (IS_NET_SUCCESS(auth) && !cancelled) |
|
|
|
|
break; |
|
|
|
|
// if it was cancelled or any error other than wrong password then go to end processing
|
|
|
|
|
if (cancelled || auth != kNetErrAuthenticationFailed) |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (IS_NET_SUCCESS (auth) && !cancelled) |
|
|
|
|
break; |
|
|
|
@ -933,18 +956,6 @@ void DebugMsgF(const char* format, ...)
|
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static bool IsMachineLittleEndian() { |
|
|
|
|
int i = 1; |
|
|
|
|
char *p = (char *) &i; |
|
|
|
|
if (p[0] == 1) // Lowest address contains the least significant byte
|
|
|
|
|
return true; |
|
|
|
|
else |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
inline static dword ToBigEndian (dword value) { |
|
|
|
|
return ((value) << 24) | ((value & 0x0000ff00) << 8) | ((value & 0x00ff0000) >> 8) | ((value) >> 24); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void AuthFailedStrings (ENetError authError, bool fromGT, |
|
|
|
|
const char **ppStr1, const char **ppStr2, |
|
|
|
@ -1081,7 +1092,7 @@ BOOL CALLBACK UruTOSDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM l
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void SaveUserPass (char *username, char *password, ShaDigest *pNamePassHash, bool remember_password, |
|
|
|
|
bool fromGT) |
|
|
|
|
int whichHash) |
|
|
|
|
{ |
|
|
|
|
UInt32 cryptKey[4]; |
|
|
|
|
ZeroMemory(cryptKey, sizeof(cryptKey)); |
|
|
|
@ -1097,7 +1108,31 @@ static void SaveUserPass (char *username, char *password, ShaDigest *pNamePassHa
|
|
|
|
|
if (StrCmp(password, FAKE_PASS_STRING) != 0) |
|
|
|
|
{ |
|
|
|
|
StrToUnicode(wpassword, password, arrsize(wpassword)); |
|
|
|
|
CryptHashPassword(wusername, wpassword, pNamePassHash); |
|
|
|
|
|
|
|
|
|
switch( whichHash ) |
|
|
|
|
{ |
|
|
|
|
case kPasswordHashSHA1: |
|
|
|
|
CryptDigest( |
|
|
|
|
kCryptSha1, |
|
|
|
|
pNamePassHash, |
|
|
|
|
StrLen(password) * sizeof(password[0]), |
|
|
|
|
password |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
// switch the endianness of the hash to big endian
|
|
|
|
|
// NOTE: this is legacy from GameTap days to match GameTap's endianness
|
|
|
|
|
pNamePassHash->data[0] = hsUNSWAP32(pNamePassHash->data[0]); |
|
|
|
|
pNamePassHash->data[1] = hsUNSWAP32(pNamePassHash->data[1]); |
|
|
|
|
pNamePassHash->data[2] = hsUNSWAP32(pNamePassHash->data[2]); |
|
|
|
|
pNamePassHash->data[3] = hsUNSWAP32(pNamePassHash->data[3]); |
|
|
|
|
pNamePassHash->data[4] = hsUNSWAP32(pNamePassHash->data[4]); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case kPasswordHashSHA0: |
|
|
|
|
default: |
|
|
|
|
CryptHashPassword(wusername, wpassword, pNamePassHash); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
NetCommSetAccountUsernamePassword(wusername, *pNamePassHash); |
|
|
|
@ -1106,28 +1141,26 @@ static void SaveUserPass (char *username, char *password, ShaDigest *pNamePassHa
|
|
|
|
|
else |
|
|
|
|
NetCommSetAuthTokenAndOS(nil, L"win"); |
|
|
|
|
|
|
|
|
|
if (!fromGT) { |
|
|
|
|
wchar fileAndPath[MAX_PATH]; |
|
|
|
|
PathGetInitDirectory(fileAndPath, arrsize(fileAndPath)); |
|
|
|
|
PathAddFilename(fileAndPath, fileAndPath, L"login.dat", arrsize(fileAndPath)); |
|
|
|
|
wchar fileAndPath[MAX_PATH]; |
|
|
|
|
PathGetInitDirectory(fileAndPath, arrsize(fileAndPath)); |
|
|
|
|
PathAddFilename(fileAndPath, fileAndPath, L"login.dat", arrsize(fileAndPath)); |
|
|
|
|
#ifndef PLASMA_EXTERNAL_RELEASE |
|
|
|
|
// internal builds can use the local init directory
|
|
|
|
|
wchar localFileAndPath[MAX_PATH]; |
|
|
|
|
StrCopy(localFileAndPath, L"init\\login.dat", arrsize(localFileAndPath)); |
|
|
|
|
if (PathDoesFileExist(localFileAndPath)) |
|
|
|
|
StrCopy(fileAndPath, localFileAndPath, arrsize(localFileAndPath)); |
|
|
|
|
// internal builds can use the local init directory
|
|
|
|
|
wchar localFileAndPath[MAX_PATH]; |
|
|
|
|
StrCopy(localFileAndPath, L"init\\login.dat", arrsize(localFileAndPath)); |
|
|
|
|
if (PathDoesFileExist(localFileAndPath)) |
|
|
|
|
StrCopy(fileAndPath, localFileAndPath, arrsize(localFileAndPath)); |
|
|
|
|
#endif |
|
|
|
|
hsStream* stream = plEncryptedStream::OpenEncryptedFileWrite(fileAndPath, cryptKey); |
|
|
|
|
if (stream) |
|
|
|
|
{ |
|
|
|
|
stream->Write(sizeof(cryptKey), cryptKey); |
|
|
|
|
stream->WriteSafeString(username); |
|
|
|
|
stream->Writebool(remember_password); |
|
|
|
|
if (remember_password) |
|
|
|
|
stream->Write(sizeof(pNamePassHash->data), pNamePassHash->data); |
|
|
|
|
stream->Close(); |
|
|
|
|
delete stream; |
|
|
|
|
} |
|
|
|
|
hsStream* stream = plEncryptedStream::OpenEncryptedFileWrite(fileAndPath, cryptKey); |
|
|
|
|
if (stream) |
|
|
|
|
{ |
|
|
|
|
stream->Write(sizeof(cryptKey), cryptKey); |
|
|
|
|
stream->WriteSafeString(username); |
|
|
|
|
stream->Writebool(remember_password); |
|
|
|
|
if (remember_password) |
|
|
|
|
stream->Write(sizeof(pNamePassHash->data), pNamePassHash->data); |
|
|
|
|
stream->Close(); |
|
|
|
|
delete stream; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1418,11 +1451,22 @@ BOOL CALLBACK UruLoginDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM
|
|
|
|
|
GetDlgItemText(hwndDlg, IDC_URULOGIN_PASSWORD, password, kMaxPasswordLength); |
|
|
|
|
remember_password = (IsDlgButtonChecked(hwndDlg, IDC_URULOGIN_REMEMBERPASS) == BST_CHECKED); |
|
|
|
|
|
|
|
|
|
SaveUserPass (username, password, &namePassHash, remember_password, loginParam->fromGT); |
|
|
|
|
|
|
|
|
|
// cycle through the hash types until we find one that matches or errors out
|
|
|
|
|
LoginDialogParam loginParam; |
|
|
|
|
MemSet(&loginParam, 0, sizeof(loginParam)); |
|
|
|
|
bool cancelled = AuthenticateNetClientComm(&loginParam.authError, hwndDlg); |
|
|
|
|
bool cancelled; |
|
|
|
|
for (int whichHash=FIRST_PASSWORD_HASH; whichHash >= LAST_PASSWORD_HASH; whichHash-- ) |
|
|
|
|
{ |
|
|
|
|
SaveUserPass (username, password, &namePassHash, remember_password, whichHash); |
|
|
|
|
|
|
|
|
|
MemSet(&loginParam, 0, sizeof(loginParam)); |
|
|
|
|
cancelled = AuthenticateNetClientComm(&loginParam.authError, hwndDlg); |
|
|
|
|
// if the password was successful then go to the end processing
|
|
|
|
|
if (IS_NET_SUCCESS(loginParam.authError) && !cancelled) |
|
|
|
|
break; |
|
|
|
|
// if it was cancelled or any error other than wrong password then go to end processing
|
|
|
|
|
if (cancelled || loginParam.authError != kNetErrAuthenticationFailed) |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (IS_NET_SUCCESS(loginParam.authError) && !cancelled) |
|
|
|
|
EndDialog(hwndDlg, ok); |
|
|
|
|