From 9fb8ea615d99af30b60871202183f14e03172b40 Mon Sep 17 00:00:00 2001 From: Darryl Pogue Date: Sat, 6 Jul 2013 00:30:43 -0700 Subject: [PATCH 1/6] Add a password storage system. --- Sources/Plasma/FeatureLib/CMakeLists.txt | 1 + .../FeatureLib/pfPasswordStore/CMakeLists.txt | 20 ++ .../pfPasswordStore/pfPasswordStore.cpp | 196 ++++++++++++++++++ .../pfPasswordStore/pfPasswordStore.h | 59 ++++++ .../pfPasswordStore/pfPasswordStore_impl.h | 83 ++++++++ 5 files changed, 359 insertions(+) create mode 100644 Sources/Plasma/FeatureLib/pfPasswordStore/CMakeLists.txt create mode 100644 Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore.cpp create mode 100644 Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore.h create mode 100644 Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_impl.h diff --git a/Sources/Plasma/FeatureLib/CMakeLists.txt b/Sources/Plasma/FeatureLib/CMakeLists.txt index 5faa5ada..39acaf4a 100644 --- a/Sources/Plasma/FeatureLib/CMakeLists.txt +++ b/Sources/Plasma/FeatureLib/CMakeLists.txt @@ -18,6 +18,7 @@ add_subdirectory(pfJournalBook) add_subdirectory(pfLocalizationMgr) add_subdirectory(pfMessage) add_subdirectory(pfMoviePlayer) +add_subdirectory(pfPasswordStore) add_subdirectory(pfPatcher) add_subdirectory(pfPython) add_subdirectory(pfSurface) diff --git a/Sources/Plasma/FeatureLib/pfPasswordStore/CMakeLists.txt b/Sources/Plasma/FeatureLib/pfPasswordStore/CMakeLists.txt new file mode 100644 index 00000000..2ab83c4e --- /dev/null +++ b/Sources/Plasma/FeatureLib/pfPasswordStore/CMakeLists.txt @@ -0,0 +1,20 @@ +include_directories("../../CoreLib") +include_directories("../../NucleusLib") +include_directories("../../NucleusLib/inc") +include_directories("../../PubUtilLib") + +set(pfPasswordStore_HEADERS + pfPasswordStore.h + pfPasswordStore_impl.h +) + +set(pfPasswordStore_SOURCES + pfPasswordStore.cpp +) + +add_library(pfPasswordStore STATIC ${pfPasswordStore_HEADERS} ${pfPasswordStore_SOURCES}) +target_link_libraries(pfPasswordStore CoreLib plFile) + +source_group("Header Files" FILES ${pfPasswordStore_HEADERS}) +source_group("Source Files" FILES ${pfPasswordStore_SOURCES}) + diff --git a/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore.cpp b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore.cpp new file mode 100644 index 00000000..b3faeae4 --- /dev/null +++ b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore.cpp @@ -0,0 +1,196 @@ +/*==LICENSE==* + +CyanWorlds.com Engine - MMOG client, server and tools +Copyright (C) 2011 Cyan Worlds, Inc. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Additional permissions under GNU GPL version 3 section 7 + +If you modify this Program, or any covered work, by linking or +combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, +NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent +JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK +(or a modified version of those libraries), +containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, +PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG +JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the +licensors of this Program grant you additional +permission to convey the resulting work. Corresponding Source for a +non-source form of such a combination shall include the source code for +the parts of OpenSSL and IJG JPEG Library used as well as that of the covered +work. + +You can contact Cyan Worlds, Inc. by email legal@cyan.com + or by snail mail at: + Cyan Worlds, Inc. + 14617 N Newport Hwy + Mead, WA 99021 + +*==LICENSE==*/ + +#include "pfPasswordStore.h" +#include "pfPasswordStore_impl.h" + +#include "plProduct.h" +#include "plFile/plEncryptedStream.h" + +/* Get the pfPasswordStore instance */ +pfPasswordStore* pfPasswordStore::Instance() +{ + static pfPasswordStore* store = nullptr; + + if (store == nullptr) { +#ifdef HS_BUILD_FOR_WIN32 + store = new pfWin32PasswordStore(); +#else + store = new pfFilePasswordStore(); +#endif + } + + return store; +} + + + +/***************************************************************************** + ** pfFilePasswordStore ** + *****************************************************************************/ + +pfFilePasswordStore::pfFilePasswordStore() +{ + // TODO: Cross-platform CryptKey initialization + uint32_t* product = (uint32_t*)plProduct::UUID(); + for (int i = 0; i < 4; i++) { + fCryptKey[i] = product[i]; + } +} + + +const plString pfFilePasswordStore::GetPassword(const plString& username) +{ + plFileName loginDat = plFileName::Join(plFileSystem::GetInitPath(), "login.dat"); + plString password = plString::Null; + +#ifndef PLASMA_EXTERNAL_RELEASE + // internal builds can use the local init directory + plFileName local("init\\login.dat"); + if (plFileInfo(local).Exists()) + loginDat = local; +#endif + + hsStream* stream = plEncryptedStream::OpenEncryptedFile(loginDat, fCryptKey); + if (stream && !stream->AtEnd()) + { + uint32_t savedKey[4]; + stream->Read(sizeof(savedKey), savedKey); + + if (memcmp(fCryptKey, savedKey, sizeof(savedKey)) == 0 && !stream->AtEnd()) + { + plString uname = stream->ReadSafeString(); + if (username.CompareI(uname) == 0) { + password = stream->ReadSafeString(); + } + } + + stream->Close(); + delete stream; + } + + return password; +} + + +bool pfFilePasswordStore::SetPassword(const plString& username, const plString& password) +{ + plFileName loginDat = plFileName::Join(plFileSystem::GetInitPath(), "login.dat"); + +#ifndef PLASMA_EXTERNAL_RELEASE + // internal builds can use the local init directory + plFileName local("init\\login.dat"); + if (plFileInfo(local).Exists()) + loginDat = local; +#endif + + hsStream* stream = plEncryptedStream::OpenEncryptedFileWrite(loginDat, fCryptKey); + if (stream) + { + stream->Write(sizeof(fCryptKey), fCryptKey); + stream->WriteSafeString(username); + stream->WriteSafeString(password); + + stream->Close(); + delete stream; + + return true; + } + + return false; +} + + + +#ifdef HS_BUILD_FOR_WIN32 +#include + +/***************************************************************************** + ** pfWin32PasswordStore ** + *****************************************************************************/ +const plString pfWin32PasswordStore::GetPassword(const plString& username) +{ + PCREDENTIALW credential; + plString target = plString::Format("%s__%s", plProduct::UUID(), username.c_str()); + plString password = plString::Null; + + if (!CredReadW(target.ToUtf16(), CRED_TYPE_GENERIC, 0, &credential)) { + return password; + } + + password = plString::FromUtf16((uint16_t*)credential->CredentialBlob, credential->CredentialBlobSize); + + memset(credential->CredentialBlob, 0, credential->CredentialBlobSize); + CredFree(credential); + + return password; +} + + +bool pfWin32PasswordStore::SetPassword(const plString& username, const plString& password) +{ + CREDENTIALW credential; + plString target = plString::Format("%s__%s", plProduct::UUID(), username.c_str()); + + if (password.IsNull()) { + if (CredDeleteW(target.ToUtf16(), CRED_TYPE_GENERIC, 0)) { + return true; + } + + return false; + } + + memset(&credential, 0, sizeof(CREDENTIALW)); + credential.Type = CRED_TYPE_GENERIC; + credential.TargetName = target.ToUtf16(); + credential.CredentialBlobSize = password.GetSize(); + credential.CredentialBlob = (LPBYTE)password.ToUtf16(); + credential.Persist = CRED_PERSIST_LOCAL_MACHINE; + credential.UserName = username.ToUtf16(); + + if (!CredWriteW(&credential, 0)) { + return false; + } + + return true; +} +#endif diff --git a/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore.h b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore.h new file mode 100644 index 00000000..fd794ba2 --- /dev/null +++ b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore.h @@ -0,0 +1,59 @@ +/*==LICENSE==* + +CyanWorlds.com Engine - MMOG client, server and tools +Copyright (C) 2011 Cyan Worlds, Inc. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Additional permissions under GNU GPL version 3 section 7 + +If you modify this Program, or any covered work, by linking or +combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, +NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent +JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK +(or a modified version of those libraries), +containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, +PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG +JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the +licensors of this Program grant you additional +permission to convey the resulting work. Corresponding Source for a +non-source form of such a combination shall include the source code for +the parts of OpenSSL and IJG JPEG Library used as well as that of the covered +work. + +You can contact Cyan Worlds, Inc. by email legal@cyan.com + or by snail mail at: + Cyan Worlds, Inc. + 14617 N Newport Hwy + Mead, WA 99021 + +*==LICENSE==*/ + +#ifndef pfPasswordStore_inc +#define pfPasswordStore_inc + +#include "HeadSpin.h" +#include "plString.h" + +class pfPasswordStore +{ +public: + static pfPasswordStore* Instance(); + + + virtual const plString GetPassword(const plString& username) = 0; + virtual bool SetPassword(const plString& username, const plString& password) = 0; +}; + +#endif //pfPasswordStore_inc diff --git a/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_impl.h b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_impl.h new file mode 100644 index 00000000..ebbe0a08 --- /dev/null +++ b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_impl.h @@ -0,0 +1,83 @@ +/*==LICENSE==* + +CyanWorlds.com Engine - MMOG client, server and tools +Copyright (C) 2011 Cyan Worlds, Inc. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Additional permissions under GNU GPL version 3 section 7 + +If you modify this Program, or any covered work, by linking or +combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, +NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent +JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK +(or a modified version of those libraries), +containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, +PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG +JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the +licensors of this Program grant you additional +permission to convey the resulting work. Corresponding Source for a +non-source form of such a combination shall include the source code for +the parts of OpenSSL and IJG JPEG Library used as well as that of the covered +work. + +You can contact Cyan Worlds, Inc. by email legal@cyan.com + or by snail mail at: + Cyan Worlds, Inc. + 14617 N Newport Hwy + Mead, WA 99021 + +*==LICENSE==*/ + +#ifndef pfPasswordStore_impl_inc +#define pfPasswordStore_impl_inc + +#include "pfPasswordStore.h" + +/** + * An encrypted file-based password storage mechanism. + */ +class pfFilePasswordStore : public pfPasswordStore +{ +private: + uint32_t fCryptKey[4]; + +public: + pfFilePasswordStore(); + + virtual const plString GetPassword(const plString& username); + virtual bool SetPassword(const plString& username, const plString& password); +}; + + +#ifdef HS_BUILD_FOR_WIN32 +/** + * A Windows Credential Vault password storage mechanism. + */ +class pfWin32PasswordStore : public pfPasswordStore +{ +public: + pfWin32PasswordStore() { } + + virtual const plString GetPassword(const plString& username); + virtual bool SetPassword(const plString& username, const plString& password); +}; +#endif //HS_BUILD_FOR_WIN32 + + +// TODO: A Linux libsecret-based storage mechanism + +// TODO: An OSX KeyChain-based storage mechanism + +#endif //pfPasswordStore_impl_inc From 8c03aaf3530237b21fd75acf88b1cead78d43bdf Mon Sep 17 00:00:00 2001 From: Joseph Davies Date: Tue, 28 Jan 2014 16:14:31 -0800 Subject: [PATCH 2/6] Fix string conversions in pfPasswordStore. --- .../pfPasswordStore/pfPasswordStore.cpp | 20 +++++++++++-------- .../pfPasswordStore/pfPasswordStore_impl.h | 8 ++++++-- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore.cpp b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore.cpp index b3faeae4..e3880f1b 100644 --- a/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore.cpp +++ b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore.cpp @@ -142,6 +142,7 @@ bool pfFilePasswordStore::SetPassword(const plString& username, const plString& #ifdef HS_BUILD_FOR_WIN32 +#include "hsWindows.h" #include /***************************************************************************** @@ -153,11 +154,11 @@ const plString pfWin32PasswordStore::GetPassword(const plString& username) plString target = plString::Format("%s__%s", plProduct::UUID(), username.c_str()); plString password = plString::Null; - if (!CredReadW(target.ToUtf16(), CRED_TYPE_GENERIC, 0, &credential)) { + if (!CredReadW(target.ToWchar().GetData(), CRED_TYPE_GENERIC, 0, &credential)) { return password; } - password = plString::FromUtf16((uint16_t*)credential->CredentialBlob, credential->CredentialBlobSize); + password = plString::FromUtf8(reinterpret_cast(credential->CredentialBlob), credential->CredentialBlobSize); memset(credential->CredentialBlob, 0, credential->CredentialBlobSize); CredFree(credential); @@ -172,20 +173,23 @@ bool pfWin32PasswordStore::SetPassword(const plString& username, const plString& plString target = plString::Format("%s__%s", plProduct::UUID(), username.c_str()); if (password.IsNull()) { - if (CredDeleteW(target.ToUtf16(), CRED_TYPE_GENERIC, 0)) { + if (CredDeleteW(target.ToWchar().GetData(), CRED_TYPE_GENERIC, 0)) { return true; } - return false; } + plStringBuffer tbuff = target.ToWchar(); + plStringBuffer pbuff = password.ToUtf8(); + plStringBuffer ubuff = username.ToWchar(); + memset(&credential, 0, sizeof(CREDENTIALW)); credential.Type = CRED_TYPE_GENERIC; - credential.TargetName = target.ToUtf16(); - credential.CredentialBlobSize = password.GetSize(); - credential.CredentialBlob = (LPBYTE)password.ToUtf16(); + credential.TargetName = (LPWSTR)tbuff.GetData(); + credential.CredentialBlobSize = pbuff.GetSize(); + credential.CredentialBlob = (LPBYTE)pbuff.GetData(); credential.Persist = CRED_PERSIST_LOCAL_MACHINE; - credential.UserName = username.ToUtf16(); + credential.UserName = (LPWSTR)ubuff.GetData(); if (!CredWriteW(&credential, 0)) { return false; diff --git a/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_impl.h b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_impl.h index ebbe0a08..0f104ef9 100644 --- a/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_impl.h +++ b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_impl.h @@ -76,8 +76,12 @@ public: #endif //HS_BUILD_FOR_WIN32 -// TODO: A Linux libsecret-based storage mechanism +/** +* @todo A Linux libsecret-based storage mechanism. +*/ -// TODO: An OSX KeyChain-based storage mechanism +/** +* @todo An OSX KeyChain-based storage mechanism. +*/ #endif //pfPasswordStore_impl_inc From bb2ea46c69aa863997082e4053de23cca07af6c0 Mon Sep 17 00:00:00 2001 From: Joseph Davies Date: Sat, 11 Oct 2014 11:49:59 -0700 Subject: [PATCH 3/6] Store plClient password using platform-specific credential storage. - Removes old drive-based "cryptography" for stored passwords, which often caused them to be invalidated when removable storage on the system is used. - Uses pfPasswordStore to store passwords. - Uses the Windows Registry to store account/password preferences. --- Sources/Plasma/Apps/plClient/CMakeLists.txt | 1 + Sources/Plasma/Apps/plClient/winmain.cpp | 182 ++++++------------ .../NucleusLib/pnEncryption/plChecksum.cpp | 2 +- .../NucleusLib/pnEncryption/plChecksum.h | 2 +- 4 files changed, 66 insertions(+), 121 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/CMakeLists.txt b/Sources/Plasma/Apps/plClient/CMakeLists.txt index d6faa923..b2f439e6 100644 --- a/Sources/Plasma/Apps/plClient/CMakeLists.txt +++ b/Sources/Plasma/Apps/plClient/CMakeLists.txt @@ -83,6 +83,7 @@ target_link_libraries(plClient pfJournalBook) target_link_libraries(plClient pfLocalizationMgr) target_link_libraries(plClient pfMessage) target_link_libraries(plClient pfMoviePlayer) +target_link_libraries(plClient pfPasswordStore) target_link_libraries(plClient pfPython) target_link_libraries(plClient pfSurface) target_link_libraries(plClient plAgeDescription) diff --git a/Sources/Plasma/Apps/plClient/winmain.cpp b/Sources/Plasma/Apps/plClient/winmain.cpp index 782c27f3..3c37fcbc 100644 --- a/Sources/Plasma/Apps/plClient/winmain.cpp +++ b/Sources/Plasma/Apps/plClient/winmain.cpp @@ -60,7 +60,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "plResMgr/plResManager.h" #include "plResMgr/plLocalization.h" #include "plFile/plEncryptedStream.h" - +#include "pfPasswordStore/pfPasswordStore.h" #include "pnEncryption/plChallengeHash.h" #include "plStatusLog/plStatusLog.h" #include "plProduct.h" @@ -155,7 +155,6 @@ struct LoginDialogParam { }; static bool AuthenticateNetClientComm(ENetError* result, HWND parentWnd); -static void GetCryptKey(uint32_t* cryptKey, unsigned size); static void SaveUserPass (LoginDialogParam *pLoginParam, char *password); static void LoadUserPass (LoginDialogParam *pLoginParam); static void AuthFailedStrings (ENetError authError, @@ -766,114 +765,90 @@ BOOL CALLBACK UruTOSDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM l return FALSE; } -static void SaveUserPass (LoginDialogParam *pLoginParam, char *password) +static void StoreHash(const plString& username, const plString& password, LoginDialogParam *pLoginParam) { - uint32_t cryptKey[4]; - memset(cryptKey, 0, sizeof(cryptKey)); - GetCryptKey(cryptKey, arrsize(cryptKey)); + // Hash username and password before sending over the 'net. + // -- Legacy compatibility: @gametap (and other usernames with domains in them) need + // to be hashed differently. + std::vector match = username.RESearch("[^@]+@([^.]+\\.)*([^.]+)\\.[^.]+"); + if (match.empty() || match[2].CompareI("gametap") == 0) { + // Plain Usernames... + plSHA1Checksum shasum(password.GetSize(), reinterpret_cast(password.c_str())); + uint32_t* dest = reinterpret_cast(pLoginParam->namePassHash); + const uint32_t* from = reinterpret_cast(shasum.GetValue()); + + dest[0] = hsToBE32(from[0]); + dest[1] = hsToBE32(from[1]); + dest[2] = hsToBE32(from[2]); + dest[3] = hsToBE32(from[3]); + dest[4] = hsToBE32(from[4]); + } + else { + // Domain-based Usernames... + CryptHashPassword(username, password, pLoginParam->namePassHash); + } +} +static void SaveUserPass(LoginDialogParam *pLoginParam, char *password) +{ plString theUser = pLoginParam->username; - plString thePass = plString(password).Left(kMaxPasswordLength); + plString thePass = password; + + HKEY hKey; + RegCreateKeyEx(HKEY_CURRENT_USER, plFormat("Software\\Cyan, Inc.\\{}\\{}", plProduct::LongName(), GetServerDisplayName()).c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL); + RegSetValueEx(hKey, "LastAccountName", NULL, REG_SZ, (LPBYTE) pLoginParam->username, kMaxAccountNameLength); + RegSetValueEx(hKey, "RememberPassword", NULL, REG_DWORD, (LPBYTE) &(pLoginParam->remember), sizeof(LPBYTE)); + RegCloseKey(hKey); - // if the password field is the fake string then we've already - // loaded the namePassHash from the file + // If the password field is the fake string + // then we've already loaded the hash. if (thePass.Compare(FAKE_PASS_STRING) != 0) { - // Regex search for primary email domain - std::vector match = theUser.RESearch("[^@]+@([^.]+\\.)*([^.]+)\\.[^.]+"); - - if (match.empty() || match[2].CompareI("gametap") == 0) { - plSHA1Checksum shasum(StrLen(password) * sizeof(password[0]), (uint8_t*)password); - uint32_t* dest = reinterpret_cast(pLoginParam->namePassHash); - const uint32_t* from = reinterpret_cast(shasum.GetValue()); - - // I blame eap for this ass shit - dest[0] = hsToBE32(from[0]); - dest[1] = hsToBE32(from[1]); - dest[2] = hsToBE32(from[2]); - dest[3] = hsToBE32(from[3]); - dest[4] = hsToBE32(from[4]); - } + StoreHash(theUser, thePass, pLoginParam); + + pfPasswordStore* store = pfPasswordStore::Instance(); + if (pLoginParam->remember) + store->SetPassword(pLoginParam->username, thePass); else - { - CryptHashPassword(theUser, thePass, pLoginParam->namePassHash); - } + store->SetPassword(pLoginParam->username, plString::Null); } NetCommSetAccountUsernamePassword(theUser.ToWchar(), pLoginParam->namePassHash); // FIXME: Real OS detection NetCommSetAuthTokenAndOS(nil, L"win"); - - plFileName loginDat = plFileName::Join(plFileSystem::GetInitPath(), "login.dat"); -#ifndef PLASMA_EXTERNAL_RELEASE - // internal builds can use the local init directory - plFileName local("init\\login.dat"); - if (plFileInfo(local).Exists()) - loginDat = local; -#endif - hsStream* stream = plEncryptedStream::OpenEncryptedFileWrite(loginDat, cryptKey); - if (stream) - { - stream->Write(sizeof(cryptKey), cryptKey); - stream->WriteSafeString(pLoginParam->username); - stream->WriteBool(pLoginParam->remember); - if (pLoginParam->remember) - stream->Write(sizeof(pLoginParam->namePassHash), pLoginParam->namePassHash); - stream->Close(); - delete stream; - } } - -static void LoadUserPass (LoginDialogParam *pLoginParam) +static void LoadUserPass(LoginDialogParam *pLoginParam) { - uint32_t cryptKey[4]; - ZeroMemory(cryptKey, sizeof(cryptKey)); - GetCryptKey(cryptKey, arrsize(cryptKey)); + HKEY hKey; + char accountName[kMaxAccountNameLength]; + memset(accountName, 0, kMaxAccountNameLength); + uint32_t rememberAccount = 0; + DWORD acctLen = kMaxAccountNameLength, remLen = sizeof(rememberAccount); + RegOpenKeyEx(HKEY_CURRENT_USER, plFormat("Software\\Cyan, Inc.\\{}\\{}", plProduct::LongName(), GetServerDisplayName()).c_str(), 0, KEY_QUERY_VALUE, &hKey); + RegQueryValueEx(hKey, "LastAccountName", 0, NULL, (LPBYTE) &accountName, &acctLen); + RegQueryValueEx(hKey, "RememberPassword", 0, NULL, (LPBYTE) &rememberAccount, &remLen); + RegCloseKey(hKey); - plString temp; pLoginParam->remember = false; pLoginParam->username[0] = '\0'; - plFileName loginDat = plFileName::Join(plFileSystem::GetInitPath(), "login.dat"); -#ifndef PLASMA_EXTERNAL_RELEASE - // internal builds can use the local init directory - plFileName local("init\\login.dat"); - if (plFileInfo(local).Exists()) - loginDat = local; -#endif - hsStream* stream = plEncryptedStream::OpenEncryptedFile(loginDat, cryptKey); - if (stream && !stream->AtEnd()) + if (acctLen > 0) + strncpy(pLoginParam->username, accountName, kMaxAccountNameLength); + pLoginParam->remember = (rememberAccount != 0); + if (pLoginParam->remember && pLoginParam->username[0] != '\0') { - uint32_t savedKey[4]; - stream->Read(sizeof(savedKey), savedKey); - - if (memcmp(cryptKey, savedKey, sizeof(savedKey)) == 0) - { - temp = stream->ReadSafeString(); - - if (!temp.IsEmpty()) - { - StrCopy(pLoginParam->username, temp.c_str(), kMaxAccountNameLength); - } - - pLoginParam->remember = stream->ReadBool(); - - if (pLoginParam->remember) - { - stream->Read(sizeof(pLoginParam->namePassHash), pLoginParam->namePassHash); - pLoginParam->focus = IDOK; - } - else - { - pLoginParam->focus = IDC_URULOGIN_PASSWORD; - } - } - - stream->Close(); - delete stream; + pfPasswordStore* store = pfPasswordStore::Instance(); + plString password = store->GetPassword(pLoginParam->username); + if (!password.IsNull()) + StoreHash(pLoginParam->username, password, pLoginParam); + pLoginParam->focus = IDOK; } + else if (pLoginParam->username[0] == '\0') + pLoginParam->focus = IDC_URULOGIN_USERNAME; + else + pLoginParam->focus = IDC_URULOGIN_PASSWORD; } static size_t CurlCallback(void *buffer, size_t size, size_t nmemb, void *param) @@ -1430,37 +1405,6 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC return PARABLE_NORMAL_EXIT; } -static void GetCryptKey(uint32_t* cryptKey, unsigned numElements) -{ - char volName[] = "C:\\"; - int index = 0; - DWORD logicalDrives = GetLogicalDrives(); - - for (int i = 0; i < 32; ++i) - { - if (logicalDrives & (1 << i)) - { - volName[0] = ('C' + i); - - DWORD volSerialNum = 0; - BOOL result = GetVolumeInformation( - volName, //LPCTSTR lpRootPathName, - NULL, //LPTSTR lpVolumeNameBuffer, - 0, //DWORD nVolumeNameSize, - &volSerialNum, //LPDWORD lpVolumeSerialNumber, - NULL, //LPDWORD lpMaximumComponentLength, - NULL, //LPDWORD lpFileSystemFlags, - NULL, //LPTSTR lpFileSystemNameBuffer, - 0 //DWORD nFileSystemNameSize - ); - - cryptKey[index] = (cryptKey[index] ^ volSerialNum); - - index = (++index) % numElements; - } - } -} - /* Enable themes in Windows XP and later */ #pragma comment(linker,"\"/manifestdependency:type='win32' \ name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \ diff --git a/Sources/Plasma/NucleusLib/pnEncryption/plChecksum.cpp b/Sources/Plasma/NucleusLib/pnEncryption/plChecksum.cpp index b7bec1db..b6c1b3cf 100644 --- a/Sources/Plasma/NucleusLib/pnEncryption/plChecksum.cpp +++ b/Sources/Plasma/NucleusLib/pnEncryption/plChecksum.cpp @@ -362,7 +362,7 @@ bool plSHAChecksum::operator==(const plSHAChecksum& rhs) const //============================================================================ -plSHA1Checksum::plSHA1Checksum(size_t size, uint8_t* buffer) +plSHA1Checksum::plSHA1Checksum(size_t size, const uint8_t* buffer) { fValid = false; Start(); diff --git a/Sources/Plasma/NucleusLib/pnEncryption/plChecksum.h b/Sources/Plasma/NucleusLib/pnEncryption/plChecksum.h index a60ffddb..5508cf4c 100644 --- a/Sources/Plasma/NucleusLib/pnEncryption/plChecksum.h +++ b/Sources/Plasma/NucleusLib/pnEncryption/plChecksum.h @@ -153,7 +153,7 @@ class plSHA1Checksum ShaDigest fChecksum; public: - plSHA1Checksum(size_t size, uint8_t* buffer); + plSHA1Checksum(size_t size, const uint8_t* buffer); plSHA1Checksum(); plSHA1Checksum(const plSHA1Checksum& rhs); plSHA1Checksum(const plFileName& fileName); From 1554546bdb7050275542c87898f7a48f2b2b1a78 Mon Sep 17 00:00:00 2001 From: Darryl Pogue Date: Sun, 12 Oct 2014 23:52:20 -0700 Subject: [PATCH 4/6] pfMacPasswordStore implementation. Conflicts: Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_impl.h --- .../FeatureLib/pfPasswordStore/CMakeLists.txt | 5 ++ .../pfPasswordStore/pfPasswordStore.cpp | 53 +++++++++++++++++++ .../pfPasswordStore/pfPasswordStore_impl.h | 14 ++++- 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/Sources/Plasma/FeatureLib/pfPasswordStore/CMakeLists.txt b/Sources/Plasma/FeatureLib/pfPasswordStore/CMakeLists.txt index 2ab83c4e..cfd25436 100644 --- a/Sources/Plasma/FeatureLib/pfPasswordStore/CMakeLists.txt +++ b/Sources/Plasma/FeatureLib/pfPasswordStore/CMakeLists.txt @@ -15,6 +15,11 @@ set(pfPasswordStore_SOURCES add_library(pfPasswordStore STATIC ${pfPasswordStore_HEADERS} ${pfPasswordStore_SOURCES}) target_link_libraries(pfPasswordStore CoreLib plFile) +if(APPLE) + find_library(SECURITY_LIBRARY Security) + target_link_libraries(pfPasswordStore ${SECURITY_LIBRARY}) +endif(APPLE) + source_group("Header Files" FILES ${pfPasswordStore_HEADERS}) source_group("Source Files" FILES ${pfPasswordStore_SOURCES}) diff --git a/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore.cpp b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore.cpp index e3880f1b..3395a87e 100644 --- a/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore.cpp +++ b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore.cpp @@ -54,8 +54,12 @@ pfPasswordStore* pfPasswordStore::Instance() if (store == nullptr) { #ifdef HS_BUILD_FOR_WIN32 store = new pfWin32PasswordStore(); +#else +#ifdef HS_BUILD_FOR_OSX + store = new pfMacPasswordStore(); #else store = new pfFilePasswordStore(); +#endif #endif } @@ -198,3 +202,52 @@ bool pfWin32PasswordStore::SetPassword(const plString& username, const plString& return true; } #endif + + + +#ifdef HS_BUILD_FOR_OSX +#include + +/***************************************************************************** + ** pfMacPasswordStore ** + *****************************************************************************/ +const plString pfMacPasswordStore::GetPassword(const plString& username) +{ + plString service = plProduct::UUID(); + + void* passwd = nullptr; + uint32_t passwd_len = 0; + + if (SecKeychainFindGenericPassword(nullptr, + service.GetSize(), + service.c_str(), + username.GetSize(), + username.c_str(), + &passwd_len, + &passwd, + nullptr) != errSecSuccess) + { + return plString::Null; + } + + plString ret(reinterpret_cast(passwd), size_t(passwd_len)); + + SecKeychainItemFreeContent(nullptr, passwd); + + return ret; +} + +bool pfMacPasswordStore::SetPassword(const plString& username, const plString& password) +{ + plString service = plProduct::UUID(); + + return SecKeychainAddGenericPassword(nullptr, + service.GetSize(), + service.c_str(), + username.GetSize(), + username.c_str(), + password.GetSize(), + password.c_str(), + nullptr) == errSecSuccess; +} +#endif diff --git a/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_impl.h b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_impl.h index 0f104ef9..637f9842 100644 --- a/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_impl.h +++ b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_impl.h @@ -80,8 +80,18 @@ public: * @todo A Linux libsecret-based storage mechanism. */ +#ifdef HS_BUILD_FOR_OSX /** -* @todo An OSX KeyChain-based storage mechanism. -*/ + * An OSX Keychain password storage mechanism. + */ +class pfMacPasswordStore : public pfPasswordStore +{ +public: + pfMacPasswordStore() { } + + virtual const plString GetPassword(const plString& username); + virtual bool SetPassword(const plString& username, const plString& password); +}; +#endif //HS_BUILD_FOR_OSX #endif //pfPasswordStore_impl_inc From 55872d6baea2e501bde161d3e3530d6e64c44dbb Mon Sep 17 00:00:00 2001 From: Joseph Davies Date: Fri, 26 Dec 2014 22:10:29 -0800 Subject: [PATCH 5/6] Split pfPasswordStore into platform-specific files. --- .../FeatureLib/pfPasswordStore/CMakeLists.txt | 18 +++ .../pfPasswordStore/pfPasswordStore.cpp | 109 ------------------ .../pfPasswordStore/pfPasswordStore_Mac.cpp | 91 +++++++++++++++ .../pfPasswordStore/pfPasswordStore_Unix.cpp | 58 ++++++++++ .../pfPasswordStore/pfPasswordStore_Win.cpp | 103 +++++++++++++++++ 5 files changed, 270 insertions(+), 109 deletions(-) create mode 100644 Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_Mac.cpp create mode 100644 Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_Unix.cpp create mode 100644 Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_Win.cpp diff --git a/Sources/Plasma/FeatureLib/pfPasswordStore/CMakeLists.txt b/Sources/Plasma/FeatureLib/pfPasswordStore/CMakeLists.txt index cfd25436..db876e3b 100644 --- a/Sources/Plasma/FeatureLib/pfPasswordStore/CMakeLists.txt +++ b/Sources/Plasma/FeatureLib/pfPasswordStore/CMakeLists.txt @@ -12,6 +12,24 @@ set(pfPasswordStore_SOURCES pfPasswordStore.cpp ) +if(WIN32 AND NOT CYGWIN) + set(pfPasswordStore_SOURCES ${pfPasswordStore_SOURCES} + pfPasswordStore_Win.cpp + ) +endif(WIN32 AND NOT CYGWIN) + +if(UNIX) + set(pfPasswordStore_SOURCES ${pfPasswordStore_SOURCES} + pfPasswordStore_Unix.cpp + ) +endif(UNIX) + +if(APPLE) + set(pfPasswordStore_SOURCES ${pfPasswordStore_SOURCES} + pfPasswordStore_Mac.cpp + ) +endif(APPLE) + add_library(pfPasswordStore STATIC ${pfPasswordStore_HEADERS} ${pfPasswordStore_SOURCES}) target_link_libraries(pfPasswordStore CoreLib plFile) diff --git a/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore.cpp b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore.cpp index 3395a87e..32d85f33 100644 --- a/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore.cpp +++ b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore.cpp @@ -142,112 +142,3 @@ bool pfFilePasswordStore::SetPassword(const plString& username, const plString& return false; } - - - -#ifdef HS_BUILD_FOR_WIN32 -#include "hsWindows.h" -#include - -/***************************************************************************** - ** pfWin32PasswordStore ** - *****************************************************************************/ -const plString pfWin32PasswordStore::GetPassword(const plString& username) -{ - PCREDENTIALW credential; - plString target = plString::Format("%s__%s", plProduct::UUID(), username.c_str()); - plString password = plString::Null; - - if (!CredReadW(target.ToWchar().GetData(), CRED_TYPE_GENERIC, 0, &credential)) { - return password; - } - - password = plString::FromUtf8(reinterpret_cast(credential->CredentialBlob), credential->CredentialBlobSize); - - memset(credential->CredentialBlob, 0, credential->CredentialBlobSize); - CredFree(credential); - - return password; -} - - -bool pfWin32PasswordStore::SetPassword(const plString& username, const plString& password) -{ - CREDENTIALW credential; - plString target = plString::Format("%s__%s", plProduct::UUID(), username.c_str()); - - if (password.IsNull()) { - if (CredDeleteW(target.ToWchar().GetData(), CRED_TYPE_GENERIC, 0)) { - return true; - } - return false; - } - - plStringBuffer tbuff = target.ToWchar(); - plStringBuffer pbuff = password.ToUtf8(); - plStringBuffer ubuff = username.ToWchar(); - - memset(&credential, 0, sizeof(CREDENTIALW)); - credential.Type = CRED_TYPE_GENERIC; - credential.TargetName = (LPWSTR)tbuff.GetData(); - credential.CredentialBlobSize = pbuff.GetSize(); - credential.CredentialBlob = (LPBYTE)pbuff.GetData(); - credential.Persist = CRED_PERSIST_LOCAL_MACHINE; - credential.UserName = (LPWSTR)ubuff.GetData(); - - if (!CredWriteW(&credential, 0)) { - return false; - } - - return true; -} -#endif - - - -#ifdef HS_BUILD_FOR_OSX -#include - -/***************************************************************************** - ** pfMacPasswordStore ** - *****************************************************************************/ -const plString pfMacPasswordStore::GetPassword(const plString& username) -{ - plString service = plProduct::UUID(); - - void* passwd = nullptr; - uint32_t passwd_len = 0; - - if (SecKeychainFindGenericPassword(nullptr, - service.GetSize(), - service.c_str(), - username.GetSize(), - username.c_str(), - &passwd_len, - &passwd, - nullptr) != errSecSuccess) - { - return plString::Null; - } - - plString ret(reinterpret_cast(passwd), size_t(passwd_len)); - - SecKeychainItemFreeContent(nullptr, passwd); - - return ret; -} - -bool pfMacPasswordStore::SetPassword(const plString& username, const plString& password) -{ - plString service = plProduct::UUID(); - - return SecKeychainAddGenericPassword(nullptr, - service.GetSize(), - service.c_str(), - username.GetSize(), - username.c_str(), - password.GetSize(), - password.c_str(), - nullptr) == errSecSuccess; -} -#endif diff --git a/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_Mac.cpp b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_Mac.cpp new file mode 100644 index 00000000..78b728b7 --- /dev/null +++ b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_Mac.cpp @@ -0,0 +1,91 @@ +/*==LICENSE==* + +CyanWorlds.com Engine - MMOG client, server and tools +Copyright (C) 2011 Cyan Worlds, Inc. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Additional permissions under GNU GPL version 3 section 7 + +If you modify this Program, or any covered work, by linking or +combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, +NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent +JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK +(or a modified version of those libraries), +containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, +PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG +JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the +licensors of this Program grant you additional +permission to convey the resulting work. Corresponding Source for a +non-source form of such a combination shall include the source code for +the parts of OpenSSL and IJG JPEG Library used as well as that of the covered +work. + +You can contact Cyan Worlds, Inc. by email legal@cyan.com + or by snail mail at: + Cyan Worlds, Inc. + 14617 N Newport Hwy + Mead, WA 99021 + +*==LICENSE==*/ + +#include "pfPasswordStore.h" +#include "pfPasswordStore_impl.h" + +#include "plProduct.h" + +#include + +/***************************************************************************** + ** pfMacPasswordStore ** + *****************************************************************************/ +const plString pfMacPasswordStore::GetPassword(const plString& username) +{ + plString service = plProduct::UUID(); + + void* passwd = nullptr; + uint32_t passwd_len = 0; + + if (SecKeychainFindGenericPassword(nullptr, + service.GetSize(), + service.c_str(), + username.GetSize(), + username.c_str(), + &passwd_len, + &passwd, + nullptr) != errSecSuccess) + { + return plString::Null; + } + + plString ret(reinterpret_cast(passwd), size_t(passwd_len)); + + SecKeychainItemFreeContent(nullptr, passwd); + + return ret; +} + +bool pfMacPasswordStore::SetPassword(const plString& username, const plString& password) +{ + plString service = plProduct::UUID(); + + return SecKeychainAddGenericPassword(nullptr, + service.GetSize(), + service.c_str(), + username.GetSize(), + username.c_str(), + password.GetSize(), + password.c_str(), + nullptr) == errSecSuccess; +} diff --git a/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_Unix.cpp b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_Unix.cpp new file mode 100644 index 00000000..6725c885 --- /dev/null +++ b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_Unix.cpp @@ -0,0 +1,58 @@ +/*==LICENSE==* + +CyanWorlds.com Engine - MMOG client, server and tools +Copyright (C) 2011 Cyan Worlds, Inc. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Additional permissions under GNU GPL version 3 section 7 + +If you modify this Program, or any covered work, by linking or +combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, +NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent +JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK +(or a modified version of those libraries), +containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, +PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG +JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the +licensors of this Program grant you additional +permission to convey the resulting work. Corresponding Source for a +non-source form of such a combination shall include the source code for +the parts of OpenSSL and IJG JPEG Library used as well as that of the covered +work. + +You can contact Cyan Worlds, Inc. by email legal@cyan.com + or by snail mail at: + Cyan Worlds, Inc. + 14617 N Newport Hwy + Mead, WA 99021 + +*==LICENSE==*/ + +#include "pfPasswordStore.h" +#include "pfPasswordStore_impl.h" + +#include "plProduct.h" + + +/***************************************************************************** + ** pfUnixPasswordStore ** + *****************************************************************************/ +const plString pfUnixPasswordStore::GetPassword(const plString& username) +{ +} + +bool pfUnixPasswordStore::SetPassword(const plString& username, const plString& password) +{ +} diff --git a/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_Win.cpp b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_Win.cpp new file mode 100644 index 00000000..ca0ecd6b --- /dev/null +++ b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_Win.cpp @@ -0,0 +1,103 @@ +/*==LICENSE==* + +CyanWorlds.com Engine - MMOG client, server and tools +Copyright (C) 2011 Cyan Worlds, Inc. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Additional permissions under GNU GPL version 3 section 7 + +If you modify this Program, or any covered work, by linking or +combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, +NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent +JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK +(or a modified version of those libraries), +containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, +PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG +JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the +licensors of this Program grant you additional +permission to convey the resulting work. Corresponding Source for a +non-source form of such a combination shall include the source code for +the parts of OpenSSL and IJG JPEG Library used as well as that of the covered +work. + +You can contact Cyan Worlds, Inc. by email legal@cyan.com + or by snail mail at: + Cyan Worlds, Inc. + 14617 N Newport Hwy + Mead, WA 99021 + +*==LICENSE==*/ + +#include "pfPasswordStore.h" +#include "pfPasswordStore_impl.h" + +#include "plProduct.h" +#include "plFormat.h" + +#include "hsWindows.h" +#include + +/***************************************************************************** + ** pfWin32PasswordStore ** + *****************************************************************************/ +const plString pfWin32PasswordStore::GetPassword(const plString& username) +{ + PCREDENTIALW credential; + plString target = plFormat("%s__%s", plProduct::UUID(), username); + plString password = plString::Null; + + if (!CredReadW(target.ToWchar().GetData(), CRED_TYPE_GENERIC, 0, &credential)) { + return password; + } + + password = plString::FromUtf8(reinterpret_cast(credential->CredentialBlob), credential->CredentialBlobSize); + + memset(credential->CredentialBlob, 0, credential->CredentialBlobSize); + CredFree(credential); + + return password; +} + + +bool pfWin32PasswordStore::SetPassword(const plString& username, const plString& password) +{ + CREDENTIALW credential; + plString target = plFormat("%s__%s", plProduct::UUID(), username); + + if (password.IsNull()) { + if (CredDeleteW(target.ToWchar().GetData(), CRED_TYPE_GENERIC, 0)) { + return true; + } + return false; + } + + plStringBuffer tbuff = target.ToWchar(); + plStringBuffer pbuff = password.ToUtf8(); + plStringBuffer ubuff = username.ToWchar(); + + memset(&credential, 0, sizeof(CREDENTIALW)); + credential.Type = CRED_TYPE_GENERIC; + credential.TargetName = (LPWSTR)tbuff.GetData(); + credential.CredentialBlobSize = pbuff.GetSize(); + credential.CredentialBlob = (LPBYTE)pbuff.GetData(); + credential.Persist = CRED_PERSIST_LOCAL_MACHINE; + credential.UserName = (LPWSTR)ubuff.GetData(); + + if (!CredWriteW(&credential, 0)) { + return false; + } + + return true; +} From 0ee8d028527683970fad133d3a4365edbc2baa54 Mon Sep 17 00:00:00 2001 From: Joseph Davies Date: Wed, 31 Dec 2014 23:42:02 -0800 Subject: [PATCH 6/6] Use servername instead of UUID for credential store. Unfortunately, the UUID is used in such a way that makes it unlikely to be unique. The server name is the current best option. --- .../FeatureLib/pfPasswordStore/pfPasswordStore_Mac.cpp | 6 +++--- .../FeatureLib/pfPasswordStore/pfPasswordStore_Win.cpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_Mac.cpp b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_Mac.cpp index 78b728b7..e31d6575 100644 --- a/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_Mac.cpp +++ b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_Mac.cpp @@ -43,7 +43,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "pfPasswordStore.h" #include "pfPasswordStore_impl.h" -#include "plProduct.h" +#include "pnNetBase/pnNbSrvs.h" #include @@ -52,7 +52,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com *****************************************************************************/ const plString pfMacPasswordStore::GetPassword(const plString& username) { - plString service = plProduct::UUID(); + plString service = GetServerDisplayName(); void* passwd = nullptr; uint32_t passwd_len = 0; @@ -78,7 +78,7 @@ const plString pfMacPasswordStore::GetPassword(const plString& username) bool pfMacPasswordStore::SetPassword(const plString& username, const plString& password) { - plString service = plProduct::UUID(); + plString service = GetServerDisplayName(); return SecKeychainAddGenericPassword(nullptr, service.GetSize(), diff --git a/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_Win.cpp b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_Win.cpp index ca0ecd6b..78da4413 100644 --- a/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_Win.cpp +++ b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_Win.cpp @@ -43,8 +43,8 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "pfPasswordStore.h" #include "pfPasswordStore_impl.h" -#include "plProduct.h" #include "plFormat.h" +#include "pnNetBase/pnNbSrvs.h" #include "hsWindows.h" #include @@ -55,7 +55,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com const plString pfWin32PasswordStore::GetPassword(const plString& username) { PCREDENTIALW credential; - plString target = plFormat("%s__%s", plProduct::UUID(), username); + plString target = plFormat("{}__{}", GetServerDisplayName(), username); plString password = plString::Null; if (!CredReadW(target.ToWchar().GetData(), CRED_TYPE_GENERIC, 0, &credential)) { @@ -74,7 +74,7 @@ const plString pfWin32PasswordStore::GetPassword(const plString& username) bool pfWin32PasswordStore::SetPassword(const plString& username, const plString& password) { CREDENTIALW credential; - plString target = plFormat("%s__%s", plProduct::UUID(), username); + plString target = plFormat("{}__{}", GetServerDisplayName(), username); if (password.IsNull()) { if (CredDeleteW(target.ToWchar().GetData(), CRED_TYPE_GENERIC, 0)) {