mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-14 18:15:28 -04:00
For security, just fail instead of falling back to using key of 0 or XOR obfuscating data
This commit is contained in:
parent
e31adc09e3
commit
6eee7a735f
@ -522,7 +522,7 @@ static void DirectConnectScreen_Load(struct DirectConnectScreen* s) {
|
|||||||
Options_UNSAFE_Get("launcher-dc-port", &port);
|
Options_UNSAFE_Get("launcher-dc-port", &port);
|
||||||
|
|
||||||
String_InitArray(mppass, mppassBuffer);
|
String_InitArray(mppass, mppassBuffer);
|
||||||
Options_GetSecure("launcher-dc-mppass", &mppass, &user);
|
Options_GetSecure("launcher-dc-mppass", &mppass);
|
||||||
String_InitArray(addr, addrBuffer);
|
String_InitArray(addr, addrBuffer);
|
||||||
String_Format2(&addr, "%s:%s", &ip, &port);
|
String_Format2(&addr, "%s:%s", &ip, &port);
|
||||||
|
|
||||||
@ -568,7 +568,7 @@ static void DirectConnectScreen_StartClient(void* w, int idx) {
|
|||||||
Options_Set("launcher-dc-username", user);
|
Options_Set("launcher-dc-username", user);
|
||||||
Options_Set("launcher-dc-ip", &ip);
|
Options_Set("launcher-dc-ip", &ip);
|
||||||
Options_Set("launcher-dc-port", &port);
|
Options_Set("launcher-dc-port", &port);
|
||||||
Options_SetSecure("launcher-dc-mppass", mppass, user);
|
Options_SetSecure("launcher-dc-mppass", mppass);
|
||||||
|
|
||||||
DirectConnectScreen_SetStatus("");
|
DirectConnectScreen_SetStatus("");
|
||||||
Launcher_StartGame(user, mppass, &ip, &port, &String_Empty);
|
Launcher_StartGame(user, mppass, &ip, &port, &String_Empty);
|
||||||
@ -706,7 +706,7 @@ CC_NOINLINE static void MainScreen_GetResume(struct ResumeInfo* info, cc_bool fu
|
|||||||
|
|
||||||
if (!full) return;
|
if (!full) return;
|
||||||
String_InitArray(info->mppass, info->_mppassBuffer);
|
String_InitArray(info->mppass, info->_mppassBuffer);
|
||||||
Options_GetSecure(ROPT_MPPASS, &info->mppass, &info->user);
|
Options_GetSecure(ROPT_MPPASS, &info->mppass);
|
||||||
|
|
||||||
info->valid =
|
info->valid =
|
||||||
info->user.length && info->mppass.length &&
|
info->user.length && info->mppass.length &&
|
||||||
@ -740,7 +740,7 @@ static void MainScreen_DoLogin(void) {
|
|||||||
|
|
||||||
if (GetTokenTask.Base.working) return;
|
if (GetTokenTask.Base.working) return;
|
||||||
Options_Set(LOPT_USERNAME, user);
|
Options_Set(LOPT_USERNAME, user);
|
||||||
Options_SetSecure(LOPT_PASSWORD, pass, user);
|
Options_SetSecure(LOPT_PASSWORD, pass);
|
||||||
|
|
||||||
GetTokenTask_Run();
|
GetTokenTask_Run();
|
||||||
LLabel_SetConst(&s->lblStatus, "&eSigning in..");
|
LLabel_SetConst(&s->lblStatus, "&eSigning in..");
|
||||||
@ -806,7 +806,7 @@ static void MainScreen_Init(struct LScreen* s_) {
|
|||||||
|
|
||||||
String_InitArray(pass, passBuffer);
|
String_InitArray(pass, passBuffer);
|
||||||
Options_UNSAFE_Get(LOPT_USERNAME, &user);
|
Options_UNSAFE_Get(LOPT_USERNAME, &user);
|
||||||
Options_GetSecure(LOPT_PASSWORD, &pass, &user);
|
Options_GetSecure(LOPT_PASSWORD, &pass);
|
||||||
|
|
||||||
LInput_SetText(&s->iptUsername, &user);
|
LInput_SetText(&s->iptUsername, &user);
|
||||||
LInput_SetText(&s->iptPassword, &pass);
|
LInput_SetText(&s->iptPassword, &pass);
|
||||||
|
@ -687,7 +687,7 @@ void Session_Load(void) {
|
|||||||
StringsBuffer_SetLengthBits(&ccCookies, 11);
|
StringsBuffer_SetLengthBits(&ccCookies, 11);
|
||||||
|
|
||||||
String_InitArray(session, buffer);
|
String_InitArray(session, buffer);
|
||||||
Options_GetSecure(LOPT_SESSION, &session, &Game_Username);
|
Options_GetSecure(LOPT_SESSION, &session);
|
||||||
if (!session.length) return;
|
if (!session.length) return;
|
||||||
EntryList_Set(&ccCookies, &sessionKey, &session, '=');
|
EntryList_Set(&ccCookies, &sessionKey, &session, '=');
|
||||||
}
|
}
|
||||||
@ -696,7 +696,7 @@ void Session_Save(void) {
|
|||||||
#if defined CC_BUILD_WIN || defined CC_BUILD_LINUX || defined CC_BUILD_MACOS
|
#if defined CC_BUILD_WIN || defined CC_BUILD_LINUX || defined CC_BUILD_MACOS
|
||||||
cc_string session = EntryList_UNSAFE_Get(&ccCookies, &sessionKey, '=');
|
cc_string session = EntryList_UNSAFE_Get(&ccCookies, &sessionKey, '=');
|
||||||
if (!session.length) return;
|
if (!session.length) return;
|
||||||
Options_SetSecure(LOPT_SESSION, &session, &Game_Username);
|
Options_SetSecure(LOPT_SESSION, &session);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -96,7 +96,7 @@ cc_bool Launcher_StartGame(const cc_string* user, const cc_string* mppass, const
|
|||||||
Options_Set(ROPT_USER, user);
|
Options_Set(ROPT_USER, user);
|
||||||
Options_Set(ROPT_IP, ip);
|
Options_Set(ROPT_IP, ip);
|
||||||
Options_Set(ROPT_PORT, port);
|
Options_Set(ROPT_PORT, port);
|
||||||
Options_SetSecure(ROPT_MPPASS, mppass, user);
|
Options_SetSecure(ROPT_MPPASS, mppass);
|
||||||
}
|
}
|
||||||
/* Save options BEFORE starting new game process */
|
/* Save options BEFORE starting new game process */
|
||||||
/* Otherwise can get 'file already in use' errors on startup */
|
/* Otherwise can get 'file already in use' errors on startup */
|
||||||
|
@ -165,30 +165,34 @@ void Options_SetString(const cc_string* key, const cc_string* value) {
|
|||||||
StringsBuffer_Add(&changedOpts, key);
|
StringsBuffer_Add(&changedOpts, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Options_SetSecure(const char* opt, const cc_string* src, const cc_string* key) {
|
void Options_SetSecure(const char* opt, const cc_string* src) {
|
||||||
char data[2000], encData[1500+1];
|
char data[2000], encData[1500+1];
|
||||||
cc_string tmp, enc;
|
cc_string tmp, enc;
|
||||||
|
cc_result res;
|
||||||
|
if (!src->length) return;
|
||||||
|
|
||||||
String_InitArray(enc, encData);
|
String_InitArray(enc, encData);
|
||||||
if (!src->length || !key->length) return;
|
res = Platform_Encrypt(src->buffer, src->length, &enc);
|
||||||
if (Platform_Encrypt(key, src->buffer, src->length, &enc)) return;
|
if (res) { Platform_Log2("Error %h encrypting option %c", &res, opt); return; }
|
||||||
if (enc.length > 1500) Logger_Abort("too large to base64");
|
|
||||||
|
|
||||||
|
if (enc.length > 1500) Logger_Abort("too large to base64");
|
||||||
tmp.buffer = data;
|
tmp.buffer = data;
|
||||||
tmp.length = Convert_ToBase64(enc.buffer, enc.length, data);
|
tmp.length = Convert_ToBase64(enc.buffer, enc.length, data);
|
||||||
tmp.capacity = tmp.length;
|
tmp.capacity = tmp.length;
|
||||||
Options_Set(opt, &tmp);
|
Options_Set(opt, &tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Options_GetSecure(const char* opt, cc_string* dst, const cc_string* key) {
|
void Options_GetSecure(const char* opt, cc_string* dst) {
|
||||||
cc_uint8 data[1500];
|
cc_uint8 data[1500];
|
||||||
int dataLen;
|
int dataLen;
|
||||||
cc_string raw;
|
cc_string raw;
|
||||||
|
cc_result res;
|
||||||
|
|
||||||
Options_UNSAFE_Get(opt, &raw);
|
Options_UNSAFE_Get(opt, &raw);
|
||||||
if (!raw.length || !key->length) return;
|
if (!raw.length) return;
|
||||||
if (raw.length > 2000) Logger_Abort("too large to base64");
|
if (raw.length > 2000) Logger_Abort("too large to base64");
|
||||||
|
|
||||||
dataLen = Convert_FromBase64(raw.buffer, raw.length, data);
|
dataLen = Convert_FromBase64(raw.buffer, raw.length, data);
|
||||||
Platform_Decrypt(key, data, dataLen, dst);
|
res = Platform_Decrypt(data, dataLen, dst);
|
||||||
|
if (res) Platform_Log2("Error %h decrypting option %c", &res, opt);
|
||||||
}
|
}
|
||||||
|
@ -124,9 +124,9 @@ CC_API void Options_Set(const char* keyRaw, const cc_string* value);
|
|||||||
CC_API void Options_SetString(const cc_string* key, const cc_string* value);
|
CC_API void Options_SetString(const cc_string* key, const cc_string* value);
|
||||||
|
|
||||||
/* Attempts to securely encode an option. */
|
/* Attempts to securely encode an option. */
|
||||||
/* NOTE: Not all platforms support secure saving. DO NOT RELY ON THIS BEING SECURE! */
|
/* NOTE: Not all platforms support secure saving. */
|
||||||
void Options_SetSecure(const char* opt, const cc_string* data, const cc_string* key);
|
void Options_SetSecure(const char* opt, const cc_string* data);
|
||||||
/* Attempts to securely decode an option. */
|
/* Attempts to securely decode an option. */
|
||||||
/* NOTE: Not all platforms support secure saving. DO NOT RELY ON THIS BEING SECURE! */
|
/* NOTE: Not all platforms support secure saving. */
|
||||||
void Options_GetSecure(const char* opt, cc_string* data, const cc_string* key);
|
void Options_GetSecure(const char* opt, cc_string* data);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1763,7 +1763,7 @@ void Platform_Init(void) { Platform_InitPosix(); }
|
|||||||
*-------------------------------------------------------Encryption--------------------------------------------------------*
|
*-------------------------------------------------------Encryption--------------------------------------------------------*
|
||||||
*#########################################################################################################################*/
|
*#########################################################################################################################*/
|
||||||
#if defined CC_BUILD_WIN
|
#if defined CC_BUILD_WIN
|
||||||
cc_result Platform_Encrypt(const cc_string* key, const void* data, int len, cc_string* dst) {
|
cc_result Platform_Encrypt(const void* data, int len, cc_string* dst) {
|
||||||
DATA_BLOB input, output;
|
DATA_BLOB input, output;
|
||||||
int i;
|
int i;
|
||||||
input.cbData = len; input.pbData = (BYTE*)data;
|
input.cbData = len; input.pbData = (BYTE*)data;
|
||||||
@ -1775,7 +1775,7 @@ cc_result Platform_Encrypt(const cc_string* key, const void* data, int len, cc_s
|
|||||||
LocalFree(output.pbData);
|
LocalFree(output.pbData);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
cc_result Platform_Decrypt(const cc_string* key, const void* data, int len, cc_string* dst) {
|
cc_result Platform_Decrypt(const void* data, int len, cc_string* dst) {
|
||||||
DATA_BLOB input, output;
|
DATA_BLOB input, output;
|
||||||
int i;
|
int i;
|
||||||
input.cbData = len; input.pbData = (BYTE*)data;
|
input.cbData = len; input.pbData = (BYTE*)data;
|
||||||
@ -1787,7 +1787,7 @@ cc_result Platform_Decrypt(const cc_string* key, const void* data, int len, cc_s
|
|||||||
LocalFree(output.pbData);
|
LocalFree(output.pbData);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#elif defined CC_BUILD_LINUX || defined CC_BUILD_MACOS
|
#elif defined CC_BUILD_POSIX
|
||||||
/* Encrypts data using XTEA block cipher, with OS specific method to get machine-specific key */
|
/* Encrypts data using XTEA block cipher, with OS specific method to get machine-specific key */
|
||||||
|
|
||||||
static void EncipherBlock(cc_uint32* v, const cc_uint32* key, cc_string* dst) {
|
static void EncipherBlock(cc_uint32* v, const cc_uint32* key, cc_string* dst) {
|
||||||
@ -1839,31 +1839,29 @@ static void DecodeMachineID(char* tmp, int len, cc_uint32* key) {
|
|||||||
|
|
||||||
#if defined CC_BUILD_LINUX
|
#if defined CC_BUILD_LINUX
|
||||||
/* Read /var/lib/dbus/machine-id for the key */
|
/* Read /var/lib/dbus/machine-id for the key */
|
||||||
static void GetMachineID(cc_uint32* key) {
|
static cc_result GetMachineID(cc_uint32* key) {
|
||||||
const cc_string idFile = String_FromConst("/var/lib/dbus/machine-id");
|
const cc_string idFile = String_FromConst("/var/lib/dbus/machine-id");
|
||||||
char tmp[MACHINEID_LEN];
|
char tmp[MACHINEID_LEN];
|
||||||
struct Stream s;
|
struct Stream s;
|
||||||
|
cc_result res;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < 4; i++) key[i] = 0;
|
if ((res = Stream_OpenFile(&s, &idFile))) return res;
|
||||||
if (Stream_OpenFile(&s, &idFile)) return;
|
res = Stream_Read(&s, tmp, MACHINEID_LEN);
|
||||||
|
if (!res) DecodeMachineID(tmp, MACHINEID_LEN, key);
|
||||||
|
|
||||||
if (!Stream_Read(&s, tmp, MACHINEID_LEN)) {
|
|
||||||
DecodeMachineID(tmp, MACHINEID_LEN, key);
|
|
||||||
}
|
|
||||||
(void)s.Close(&s);
|
(void)s.Close(&s);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
#elif defined CC_BUILD_MACOS
|
#elif defined CC_BUILD_MACOS
|
||||||
static void GetMachineID(cc_uint32* key) {
|
/* Read kIOPlatformUUIDKey from I/O registry for the key */
|
||||||
|
static cc_result GetMachineID(cc_uint32* key) {
|
||||||
io_registry_entry_t registry;
|
io_registry_entry_t registry;
|
||||||
CFStringRef uuid = NULL;
|
CFStringRef uuid = NULL;
|
||||||
const char* src;
|
const char* src = NULL;
|
||||||
struct Stream s;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < 4; i++) key[i] = 0;
|
|
||||||
registry = IORegistryEntryFromPath(kIOMasterPortDefault, "IOService:/");
|
registry = IORegistryEntryFromPath(kIOMasterPortDefault, "IOService:/");
|
||||||
if (!registry) return;
|
if (!registry) return ERR_NOT_SUPPORTED;
|
||||||
|
|
||||||
#ifdef kIOPlatformUUIDKey
|
#ifdef kIOPlatformUUIDKey
|
||||||
uuid = IORegistryEntryCreateCFProperty(registry, CFSTR(kIOPlatformUUIDKey), kCFAllocatorDefault, 0);
|
uuid = IORegistryEntryCreateCFProperty(registry, CFSTR(kIOPlatformUUIDKey), kCFAllocatorDefault, 0);
|
||||||
@ -1873,16 +1871,20 @@ static void GetMachineID(cc_uint32* key) {
|
|||||||
#endif
|
#endif
|
||||||
if (uuid) CFRelease(uuid);
|
if (uuid) CFRelease(uuid);
|
||||||
IOObjectRelease(registry);
|
IOObjectRelease(registry);
|
||||||
|
return src ? 0 : ERR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
static cc_result GetMachineID(cc_uint32* key) { return ERR_NOT_SUPPORTED; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
cc_result Platform_Encrypt(const cc_string* key_, const void* data, int len, cc_string* dst) {
|
cc_result Platform_Encrypt(const void* data, int len, cc_string* dst) {
|
||||||
const cc_uint8* src = (const cc_uint8*)data;
|
const cc_uint8* src = (const cc_uint8*)data;
|
||||||
cc_uint32 header[4], key[4];
|
cc_uint32 header[4], key[4];
|
||||||
|
cc_result res;
|
||||||
|
if ((res = GetMachineID(key))) return res;
|
||||||
|
|
||||||
header[0] = ENC1; header[1] = ENC2;
|
header[0] = ENC1; header[1] = ENC2;
|
||||||
header[2] = ENC3; header[3] = len;
|
header[2] = ENC3; header[3] = len;
|
||||||
|
|
||||||
GetMachineID(key);
|
|
||||||
EncipherBlock(header + 0, key, dst);
|
EncipherBlock(header + 0, key, dst);
|
||||||
EncipherBlock(header + 2, key, dst);
|
EncipherBlock(header + 2, key, dst);
|
||||||
|
|
||||||
@ -1893,14 +1895,16 @@ cc_result Platform_Encrypt(const cc_string* key_, const void* data, int len, cc_
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
cc_result Platform_Decrypt(const cc_string* key__, const void* data, int len, cc_string* dst) {
|
cc_result Platform_Decrypt(const void* data, int len, cc_string* dst) {
|
||||||
const cc_uint8* src = (const cc_uint8*)data;
|
const cc_uint8* src = (const cc_uint8*)data;
|
||||||
cc_uint32 header[4], key[4];
|
cc_uint32 header[4], key[4];
|
||||||
|
cc_result res;
|
||||||
int dataLen;
|
int dataLen;
|
||||||
|
|
||||||
/* Total size must be >= header size */
|
/* Total size must be >= header size */
|
||||||
if (len < 16) return ERR_END_OF_STREAM;
|
if (len < 16) return ERR_END_OF_STREAM;
|
||||||
|
if ((res = GetMachineID(key))) return res;
|
||||||
|
|
||||||
GetMachineID(key);
|
|
||||||
Mem_Copy(header, src, 16);
|
Mem_Copy(header, src, 16);
|
||||||
DecipherBlock(header + 0, key);
|
DecipherBlock(header + 0, key);
|
||||||
DecipherBlock(header + 2, key);
|
DecipherBlock(header + 2, key);
|
||||||
@ -1920,24 +1924,6 @@ cc_result Platform_Decrypt(const cc_string* key__, const void* data, int len, cc
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#elif defined CC_BUILD_POSIX
|
|
||||||
cc_result Platform_Encrypt(const cc_string* key, const void* data, int len, cc_string* dst) {
|
|
||||||
/* TODO: Is there a similar API for macOS/Linux? */
|
|
||||||
/* Fallback to NOT SECURE XOR. Prevents simple reading from options.txt */
|
|
||||||
const cc_uint8* src = data;
|
|
||||||
cc_uint8 c;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
c = (cc_uint8)(src[i] ^ key->buffer[i % key->length] ^ 0x43);
|
|
||||||
String_Append(dst, c);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
cc_result Platform_Decrypt(const cc_string* key, const void* data, int len, cc_string* dst) {
|
|
||||||
/* TODO: Is there a similar API for macOS/Linux? */
|
|
||||||
return Platform_Encrypt(key, data, len, dst);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,11 +53,9 @@ cc_result Platform_SetDefaultCurrentDirectory(int argc, char **argv);
|
|||||||
int Platform_GetCommandLineArgs(int argc, STRING_REF char** argv, cc_string* args);
|
int Platform_GetCommandLineArgs(int argc, STRING_REF char** argv, cc_string* args);
|
||||||
|
|
||||||
/* Encrypts data in a platform-specific manner. (may not be supported) */
|
/* Encrypts data in a platform-specific manner. (may not be supported) */
|
||||||
/* NOTE: THIS IS NOT SECURE! Some platforms just use a simple xor obfuscation. */
|
cc_result Platform_Encrypt(const void* data, int len, cc_string* dst);
|
||||||
cc_result Platform_Encrypt(const cc_string* key, const void* data, int len, cc_string* dst);
|
|
||||||
/* Decrypts data in a platform-specific manner. (may not be supported) */
|
/* Decrypts data in a platform-specific manner. (may not be supported) */
|
||||||
/* NOTE: THIS IS NOT SECURE! Some platforms just use a simple xor obfuscation. */
|
cc_result Platform_Decrypt(const void* data, int len, cc_string* dst);
|
||||||
cc_result Platform_Decrypt(const cc_string* key, const void* data, int len, cc_string* dst);
|
|
||||||
/* Outputs more detailed information about errors with operating system functions. */
|
/* Outputs more detailed information about errors with operating system functions. */
|
||||||
/* NOTE: This is for general functions like file I/O. If a more specific
|
/* NOTE: This is for general functions like file I/O. If a more specific
|
||||||
describe exists (e.g. Http_DescribeError), that should be preferred. */
|
describe exists (e.g. Http_DescribeError), that should be preferred. */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user