Linux: Implement session caching and switch to using /var/lib/dbus/machine-id for a device specific encryption key

Unfortunately, this means previously stored passwords and resume mpasses aren't valid anymore and so will be lost. Sorry about that.
This commit is contained in:
UnknownShadow200 2021-01-01 09:55:44 +11:00
parent 18fe4411eb
commit b2f23fc28c
6 changed files with 164 additions and 49 deletions

View File

@ -460,9 +460,7 @@ static void LogInvalidSkin(cc_result res, const cc_string* url, const cc_uint8*
if (res != PNG_ERR_INVALID_SIG) { Logger_WarnFunc(&msg); return; } if (res != PNG_ERR_INVALID_SIG) { Logger_WarnFunc(&msg); return; }
String_AppendConst(&msg, " (got "); String_AppendConst(&msg, " (got ");
for (i = 0; i < min(size, 8); i++) { String_AppendAll( &msg, data, min(size, 8));
String_Append(&msg, data[i]);
}
String_AppendConst(&msg, ")"); String_AppendConst(&msg, ")");
Logger_WarnFunc(&msg); Logger_WarnFunc(&msg);
} }

View File

@ -667,7 +667,7 @@ void Session_Load(void) {
} }
void Session_Save(void) { void Session_Save(void) {
#ifdef CC_BUILD_WIN #if defined CC_BUILD_WIN || defined CC_BUILD_LINUX
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, &Game_Username);

View File

@ -1618,31 +1618,6 @@ void Platform_Free(void) {
HeapDestroy(heap); HeapDestroy(heap);
} }
cc_result Platform_Encrypt(const cc_string* key, const void* data, int len, cc_string* dst) {
DATA_BLOB input, output;
int i;
input.cbData = len; input.pbData = (BYTE*)data;
if (!CryptProtectData(&input, NULL, NULL, NULL, NULL, 0, &output)) return GetLastError();
for (i = 0; i < output.cbData; i++) {
String_Append(dst, output.pbData[i]);
}
LocalFree(output.pbData);
return 0;
}
cc_result Platform_Decrypt(const cc_string* key, const void* data, int len, cc_string* dst) {
DATA_BLOB input, output;
int i;
input.cbData = len; input.pbData = (BYTE*)data;
if (!CryptUnprotectData(&input, NULL, NULL, NULL, NULL, 0, &output)) return GetLastError();
for (i = 0; i < output.cbData; i++) {
String_Append(dst, output.pbData[i]);
}
LocalFree(output.pbData);
return 0;
}
cc_bool Platform_DescribeErrorExt(cc_result res, cc_string* dst, void* lib) { cc_bool Platform_DescribeErrorExt(cc_result res, cc_string* dst, void* lib) {
TCHAR chars[NATIVE_STR_LEN]; TCHAR chars[NATIVE_STR_LEN];
DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS; DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
@ -1684,24 +1659,6 @@ static void Platform_InitPosix(void) {
} }
void Platform_Free(void) { } void Platform_Free(void) { }
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);
}
cc_bool Platform_DescribeError(cc_result res, cc_string* dst) { cc_bool Platform_DescribeError(cc_result res, cc_string* dst) {
char chars[NATIVE_STR_LEN]; char chars[NATIVE_STR_LEN];
int len; int len;
@ -1790,7 +1747,159 @@ void Platform_Init(void) { Platform_InitPosix(); }
/*########################################################################################################################* /*########################################################################################################################*
*--------------------------------------------------------Platform---------------------------------------------------------* *-------------------------------------------------------Encryption--------------------------------------------------------*
*#########################################################################################################################*/
#if defined CC_BUILD_WIN
cc_result Platform_Encrypt(const cc_string* key, const void* data, int len, cc_string* dst) {
DATA_BLOB input, output;
int i;
input.cbData = len; input.pbData = (BYTE*)data;
if (!CryptProtectData(&input, NULL, NULL, NULL, NULL, 0, &output)) return GetLastError();
for (i = 0; i < output.cbData; i++) {
String_Append(dst, output.pbData[i]);
}
LocalFree(output.pbData);
return 0;
}
cc_result Platform_Decrypt(const cc_string* key, const void* data, int len, cc_string* dst) {
DATA_BLOB input, output;
int i;
input.cbData = len; input.pbData = (BYTE*)data;
if (!CryptUnprotectData(&input, NULL, NULL, NULL, NULL, 0, &output)) return GetLastError();
for (i = 0; i < output.cbData; i++) {
String_Append(dst, output.pbData[i]);
}
LocalFree(output.pbData);
return 0;
}
#elif defined CC_BUILD_LINUX
/* Encrypts data using XTEA block cipher, with /var/lib/dbus/machine-id as the key */
static void EncipherBlock(cc_uint32* v, const cc_uint32* key, cc_string* dst) {
cc_uint32 v0 = v[0], v1 = v[1], sum = 0, delta = 0x9E3779B9;
int i;
for (i = 0; i < 12; i++) {
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
sum += delta;
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
}
v[0] = v0; v[1] = v1;
String_AppendAll(dst, v, 8);
}
static void DecipherBlock(cc_uint32* v, const cc_uint32* key) {
cc_uint32 v0 = v[0], v1 = v[1], delta = 0x9E3779B9, sum = delta * 12;
int i;
for (i = 0; i < 12; i++) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
sum -= delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
}
v[0] = v0; v[1] = v1;
}
#define ENC1 0xCC005EC0
#define ENC2 0x0DA4A0DE
#define ENC3 0xC0DED000
#define MACHINEID_LEN 32
#define ENC_SIZE 8 /* 2 32 bit ints per block */
/* "b3c5a0d9" --> 0xB3C5A0D9 */
static void DecodeMachineID(char* tmp, cc_uint8* key) {
int hex[MACHINEID_LEN], i;
PackedCol_Unhex(tmp, hex, MACHINEID_LEN);
for (i = 0; i < MACHINEID_LEN / 2; i++) {
key[i] = (hex[i * 2] << 4) | hex[i * 2 + 1];
}
}
static void GetMachineID(cc_uint32* key) {
const cc_string idFile = String_FromConst("/var/lib/dbus/machine-id");
char tmp[MACHINEID_LEN];
struct Stream s;
int i;
for (i = 0; i < 4; i++) key[i] = 0;
if (Stream_OpenFile(&s, &idFile)) return;
if (!Stream_Read(&s, tmp, MACHINEID_LEN)) {
DecodeMachineID(tmp, (cc_uint8*)key);
}
s.Close(&s);
}
cc_result Platform_Encrypt(const cc_string* key_, const void* data, int len, cc_string* dst) {
const cc_uint8* src = (const cc_uint8*)data;
cc_uint32 header[4], key[4];
header[0] = ENC1; header[1] = ENC2;
header[2] = ENC3; header[3] = len;
GetMachineID(key);
EncipherBlock(header + 0, key, dst);
EncipherBlock(header + 2, key, dst);
for (; len > 0; len -= ENC_SIZE, src += ENC_SIZE) {
header[0] = 0; header[1] = 0;
Mem_Copy(header, src, min(len, ENC_SIZE));
EncipherBlock(header, key, dst);
}
return 0;
}
cc_result Platform_Decrypt(const cc_string* key__, const void* data, int len, cc_string* dst) {
const cc_uint8* src = (const cc_uint8*)data;
cc_uint32 header[4], key[4];
int dataLen;
/* Total size must be >= header size */
if (len < 16) return ERR_END_OF_STREAM;
GetMachineID(key);
Mem_Copy(header, src, 16);
DecipherBlock(header + 0, key);
DecipherBlock(header + 2, key);
if (header[0] != ENC1 || header[1] != ENC2 || header[2] != ENC3) return ERR_INVALID_ARGUMENT;
len -= 16; src += 16;
if (header[3] > len) return ERR_INVALID_ARGUMENT;
dataLen = header[3];
for (; dataLen > 0; len -= ENC_SIZE, src += ENC_SIZE, dataLen -= ENC_SIZE) {
header[0] = 0; header[1] = 0;
Mem_Copy(header, src, min(len, ENC_SIZE));
DecipherBlock(header, key);
String_AppendAll(dst, header, min(dataLen, ENC_SIZE));
}
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
/*########################################################################################################################*
*-----------------------------------------------------Configuration-------------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
#if defined CC_BUILD_WIN #if defined CC_BUILD_WIN
static cc_string Platform_NextArg(STRING_REF cc_string* args) { static cc_string Platform_NextArg(STRING_REF cc_string* args) {

View File

@ -115,7 +115,7 @@ static void ReadString(cc_uint8** ptr, cc_string* str) {
length = i + 1; break; length = i + 1; break;
} }
for (i = 0; i < length; i++) { String_Append(str, data[i]); } String_AppendAll(str, data, length);
*ptr = data + STRING_SIZE; *ptr = data + STRING_SIZE;
} }

View File

@ -250,6 +250,12 @@ void String_AppendConst(cc_string* str, const char* src) {
} }
} }
void String_AppendAll(cc_string* str, const void* data, int len) {
const char* src = (const char*)data;
int i;
for (i = 0; i < len; i++) String_Append(str, src[i]);
}
void String_AppendString(cc_string* str, const cc_string* src) { void String_AppendString(cc_string* str, const cc_string* src) {
int i; int i;
for (i = 0; i < src->length; i++) { for (i = 0; i < src->length; i++) {

View File

@ -98,6 +98,8 @@ CC_API void String_AppendPaddedInt(cc_string* str, int num, int minDigits);
CC_API void String_AppendFloat(cc_string* str, float num, int fracDigits); /* TODO: Need to account for , or . for decimal */ CC_API void String_AppendFloat(cc_string* str, float num, int fracDigits); /* TODO: Need to account for , or . for decimal */
/* Attempts to append characters. src MUST be null-terminated. */ /* Attempts to append characters. src MUST be null-terminated. */
CC_API void String_AppendConst(cc_string* str, const char* src); CC_API void String_AppendConst(cc_string* str, const char* src);
/* Attempts to append characters. */
void String_AppendAll(cc_string* str, const void* data, int len);
/* Attempts to append characters of a string. */ /* Attempts to append characters of a string. */
CC_API void String_AppendString(cc_string* str, const cc_string* src); CC_API void String_AppendString(cc_string* str, const cc_string* src);
/* Attempts to append characters of a string, skipping any colour codes. */ /* Attempts to append characters of a string, skipping any colour codes. */