mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-14 10:05:44 -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);
|
||||
|
||||
String_InitArray(mppass, mppassBuffer);
|
||||
Options_GetSecure("launcher-dc-mppass", &mppass, &user);
|
||||
Options_GetSecure("launcher-dc-mppass", &mppass);
|
||||
String_InitArray(addr, addrBuffer);
|
||||
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-ip", &ip);
|
||||
Options_Set("launcher-dc-port", &port);
|
||||
Options_SetSecure("launcher-dc-mppass", mppass, user);
|
||||
Options_SetSecure("launcher-dc-mppass", mppass);
|
||||
|
||||
DirectConnectScreen_SetStatus("");
|
||||
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;
|
||||
String_InitArray(info->mppass, info->_mppassBuffer);
|
||||
Options_GetSecure(ROPT_MPPASS, &info->mppass, &info->user);
|
||||
Options_GetSecure(ROPT_MPPASS, &info->mppass);
|
||||
|
||||
info->valid =
|
||||
info->user.length && info->mppass.length &&
|
||||
@ -740,7 +740,7 @@ static void MainScreen_DoLogin(void) {
|
||||
|
||||
if (GetTokenTask.Base.working) return;
|
||||
Options_Set(LOPT_USERNAME, user);
|
||||
Options_SetSecure(LOPT_PASSWORD, pass, user);
|
||||
Options_SetSecure(LOPT_PASSWORD, pass);
|
||||
|
||||
GetTokenTask_Run();
|
||||
LLabel_SetConst(&s->lblStatus, "&eSigning in..");
|
||||
@ -806,7 +806,7 @@ static void MainScreen_Init(struct LScreen* s_) {
|
||||
|
||||
String_InitArray(pass, passBuffer);
|
||||
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->iptPassword, &pass);
|
||||
|
@ -687,7 +687,7 @@ void Session_Load(void) {
|
||||
StringsBuffer_SetLengthBits(&ccCookies, 11);
|
||||
|
||||
String_InitArray(session, buffer);
|
||||
Options_GetSecure(LOPT_SESSION, &session, &Game_Username);
|
||||
Options_GetSecure(LOPT_SESSION, &session);
|
||||
if (!session.length) return;
|
||||
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
|
||||
cc_string session = EntryList_UNSAFE_Get(&ccCookies, &sessionKey, '=');
|
||||
if (!session.length) return;
|
||||
Options_SetSecure(LOPT_SESSION, &session, &Game_Username);
|
||||
Options_SetSecure(LOPT_SESSION, &session);
|
||||
#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_IP, ip);
|
||||
Options_Set(ROPT_PORT, port);
|
||||
Options_SetSecure(ROPT_MPPASS, mppass, user);
|
||||
Options_SetSecure(ROPT_MPPASS, mppass);
|
||||
}
|
||||
/* Save options BEFORE starting new game process */
|
||||
/* 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);
|
||||
}
|
||||
|
||||
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];
|
||||
cc_string tmp, enc;
|
||||
cc_result res;
|
||||
if (!src->length) return;
|
||||
|
||||
String_InitArray(enc, encData);
|
||||
if (!src->length || !key->length) return;
|
||||
if (Platform_Encrypt(key, src->buffer, src->length, &enc)) return;
|
||||
if (enc.length > 1500) Logger_Abort("too large to base64");
|
||||
res = Platform_Encrypt(src->buffer, src->length, &enc);
|
||||
if (res) { Platform_Log2("Error %h encrypting option %c", &res, opt); return; }
|
||||
|
||||
if (enc.length > 1500) Logger_Abort("too large to base64");
|
||||
tmp.buffer = data;
|
||||
tmp.length = Convert_ToBase64(enc.buffer, enc.length, data);
|
||||
tmp.capacity = tmp.length;
|
||||
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];
|
||||
int dataLen;
|
||||
cc_string raw;
|
||||
cc_result res;
|
||||
|
||||
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");
|
||||
|
||||
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);
|
||||
|
||||
/* Attempts to securely encode an option. */
|
||||
/* NOTE: Not all platforms support secure saving. DO NOT RELY ON THIS BEING SECURE! */
|
||||
void Options_SetSecure(const char* opt, const cc_string* data, const cc_string* key);
|
||||
/* NOTE: Not all platforms support secure saving. */
|
||||
void Options_SetSecure(const char* opt, const cc_string* data);
|
||||
/* Attempts to securely decode an option. */
|
||||
/* NOTE: Not all platforms support secure saving. DO NOT RELY ON THIS BEING SECURE! */
|
||||
void Options_GetSecure(const char* opt, cc_string* data, const cc_string* key);
|
||||
/* NOTE: Not all platforms support secure saving. */
|
||||
void Options_GetSecure(const char* opt, cc_string* data);
|
||||
#endif
|
||||
|
@ -1763,7 +1763,7 @@ void Platform_Init(void) { Platform_InitPosix(); }
|
||||
*-------------------------------------------------------Encryption--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
#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;
|
||||
int i;
|
||||
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);
|
||||
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;
|
||||
int i;
|
||||
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);
|
||||
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 */
|
||||
|
||||
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
|
||||
/* 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");
|
||||
char tmp[MACHINEID_LEN];
|
||||
struct Stream s;
|
||||
cc_result res;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++) key[i] = 0;
|
||||
if (Stream_OpenFile(&s, &idFile)) return;
|
||||
if ((res = Stream_OpenFile(&s, &idFile))) return res;
|
||||
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);
|
||||
return res;
|
||||
}
|
||||
#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;
|
||||
CFStringRef uuid = NULL;
|
||||
const char* src;
|
||||
struct Stream s;
|
||||
int i;
|
||||
const char* src = NULL;
|
||||
|
||||
for (i = 0; i < 4; i++) key[i] = 0;
|
||||
registry = IORegistryEntryFromPath(kIOMasterPortDefault, "IOService:/");
|
||||
if (!registry) return;
|
||||
if (!registry) return ERR_NOT_SUPPORTED;
|
||||
|
||||
#ifdef kIOPlatformUUIDKey
|
||||
uuid = IORegistryEntryCreateCFProperty(registry, CFSTR(kIOPlatformUUIDKey), kCFAllocatorDefault, 0);
|
||||
@ -1873,16 +1871,20 @@ static void GetMachineID(cc_uint32* key) {
|
||||
#endif
|
||||
if (uuid) CFRelease(uuid);
|
||||
IOObjectRelease(registry);
|
||||
return src ? 0 : ERR_NOT_SUPPORTED;
|
||||
}
|
||||
#else
|
||||
static cc_result GetMachineID(cc_uint32* key) { return ERR_NOT_SUPPORTED; }
|
||||
#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;
|
||||
cc_uint32 header[4], key[4];
|
||||
cc_result res;
|
||||
if ((res = GetMachineID(key))) return res;
|
||||
|
||||
header[0] = ENC1; header[1] = ENC2;
|
||||
header[2] = ENC3; header[3] = len;
|
||||
|
||||
GetMachineID(key);
|
||||
EncipherBlock(header + 0, 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;
|
||||
}
|
||||
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;
|
||||
cc_uint32 header[4], key[4];
|
||||
cc_result res;
|
||||
int dataLen;
|
||||
|
||||
/* Total size must be >= header size */
|
||||
if (len < 16) return ERR_END_OF_STREAM;
|
||||
if ((res = GetMachineID(key))) return res;
|
||||
|
||||
GetMachineID(key);
|
||||
Mem_Copy(header, src, 16);
|
||||
DecipherBlock(header + 0, 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;
|
||||
}
|
||||
#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
|
||||
|
||||
|
||||
|
@ -53,11 +53,9 @@ cc_result Platform_SetDefaultCurrentDirectory(int argc, char **argv);
|
||||
int Platform_GetCommandLineArgs(int argc, STRING_REF char** argv, cc_string* args);
|
||||
|
||||
/* 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 cc_string* key, const void* data, int len, cc_string* dst);
|
||||
cc_result Platform_Encrypt(const void* data, int len, cc_string* dst);
|
||||
/* 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 cc_string* key, const void* data, int len, cc_string* dst);
|
||||
cc_result Platform_Decrypt(const void* data, int len, cc_string* dst);
|
||||
/* Outputs more detailed information about errors with operating system functions. */
|
||||
/* NOTE: This is for general functions like file I/O. If a more specific
|
||||
describe exists (e.g. Http_DescribeError), that should be preferred. */
|
||||
|
Loading…
x
Reference in New Issue
Block a user