Windows: Remember session cookie, bypasses MFA when logged in from same device

This commit is contained in:
UnknownShadow200 2020-12-30 20:04:56 +11:00
parent 8f888c0589
commit 3c3664b9cf
9 changed files with 56 additions and 10 deletions

View File

@ -924,7 +924,7 @@ static void MainScreen_TickGetToken(struct MainScreen* s) {
return;
}
if (String_CaselessEquals(&GetTokenTask.username, &s->iptUsername.text)) {
if (!GetTokenTask.error && String_CaselessEquals(&GetTokenTask.username, &s->iptUsername.text)) {
/* Already logged in, go straight to fetching servers */
MainScreen_LoginPhase2(s, &GetTokenTask.username);
} else {

View File

@ -9,6 +9,8 @@
#include "Options.h"
#include "PackedCol.h"
#include "Errors.h"
#include "Game.h"
#include "Utils.h"
/*########################################################################################################################*
*----------------------------------------------------------JSON-----------------------------------------------------------*
@ -239,6 +241,8 @@ static void GetTokenTask_OnValue(struct JsonContext* ctx, const cc_string* str)
String_Copy(&GetTokenTask.token, str);
} else if (String_CaselessEqualsConst(&ctx->curKey, "username")) {
String_Copy(&GetTokenTask.username, str);
} else if (String_CaselessEqualsConst(&ctx->curKey, "errors")) {
if (str->length) GetTokenTask.error = true;
}
}
@ -255,6 +259,7 @@ void GetTokenTask_Run(void) {
LWebTask_Reset(&GetTokenTask.Base);
String_InitArray(GetTokenTask.token, tokenBuffer);
String_InitArray(GetTokenTask.username, userBuffer);
GetTokenTask.error = false;
GetTokenTask.Base.Handle = GetTokenTask_Handle;
GetTokenTask.Base.reqID = Http_AsyncGetDataEx(&url, false, NULL, NULL, &ccCookies);
@ -416,6 +421,7 @@ static void FetchServersTask_Handle(cc_uint8* data, cc_uint32 len) {
int count;
Mem_Free(FetchServersTask.servers);
Mem_Free(FetchServersTask.orders);
Session_Save();
FetchServersTask.numServers = 0;
FetchServersTask.servers = NULL;
@ -533,7 +539,7 @@ void FetchUpdateTask_Run(cc_bool release, cc_bool d3d9) {
/*########################################################################################################################*
*-----------------------------------------------------FetchFlagsTask-----------------------------------------------------*
*-----------------------------------------------------FetchFlagsTask------------------------------------------------------*
*#########################################################################################################################*/
struct FetchFlagsData FetchFlagsTask;
static int flagsCount, flagsCapacity;
@ -639,4 +645,32 @@ void Flags_Free(void) {
flagsCount = 0;
FetchFlagsTask.count = 0;
}
/*########################################################################################################################*
*------------------------------------------------------Session cache------------------------------------------------------*
*#########################################################################################################################*/
static cc_string sessionKey = String_FromConst("session");
static cc_bool loadedSession;
void Session_Load(void) {
cc_string session; char buffer[3072];
if (loadedSession) return;
loadedSession = true;
/* Increase from max 512 to 2048 per entry */
StringsBuffer_SetLengthBits(&ccCookies, 11);
String_InitArray(session, buffer);
Options_GetSecure(LOPT_SESSION, &session, &Game_Username);
if (!session.length) return;
EntryList_Set(&ccCookies, &sessionKey, &session, '=');
}
void Session_Save(void) {
#ifdef CC_BUILD_WIN
cc_string session = EntryList_UNSAFE_Get(&ccCookies, &sessionKey, '=');
if (!session.length) return;
Options_SetSecure(LOPT_SESSION, &session, &Game_Username);
#endif
}
#endif

View File

@ -59,6 +59,7 @@ extern struct GetTokenTaskData {
struct LWebTask Base;
cc_string token; /* Random CSRF token for logging in. */
cc_string username; /* Username if session is already logged in. */
cc_bool error; /* Whether a signin error occurred */
} GetTokenTask;
void GetTokenTask_Run(void);
@ -118,4 +119,7 @@ void FetchFlagsTask_Add(const struct ServerInfo* server);
struct Bitmap* Flags_Get(const struct ServerInfo* server);
/* Frees all flag bitmaps. */
void Flags_Free(void);
void Session_Load(void);
void Session_Save(void);
#endif

View File

@ -299,6 +299,8 @@ void Launcher_Run(void) {
Drawer2D_BlackTextShadows = true;
InitFramebuffer();
Options_UNSAFE_Get("launcher-cc-username", &Game_Username);
Session_Load();
Launcher_LoadSkin();
Launcher_Init();
Launcher_TryLoadTexturePack();

View File

@ -33,6 +33,8 @@ static cc_bool Options_LoadFilter(const cc_string* entry) {
}
void Options_Load(void) {
/* Increase from max 512 to 2048 per entry */
StringsBuffer_SetLengthBits(&Options, 11);
EntryList_Load(&Options, "options-default.txt", '=', NULL);
EntryList_Load(&Options, "options.txt", '=', NULL);
}

View File

@ -72,6 +72,8 @@
#define OPT_TOUCH_SCALE "gui-touchscale"
#define OPT_HTTP_ONLY "http-no-https"
#define LOPT_SESSION "launcher-session"
struct StringsBuffer;
extern struct StringsBuffer Options;
/* Frees any memory allocated in storing options. */

View File

@ -756,7 +756,6 @@ cc_bool Convert_ParseBool(const cc_string* str, cc_bool* value) {
*------------------------------------------------------StringsBuffer------------------------------------------------------*
*#########################################################################################################################*/
#define STRINGSBUFFER_BUFFER_EXPAND_SIZE 8192
#define STRINGSBUFFER_DEFAULT_LEN_SHIFT 9
#define StringsBuffer_GetOffset(raw) ((raw) >> buffer->_lenShift)
#define StringsBuffer_GetLength(raw) ((raw) & buffer->_lenMask)
@ -771,7 +770,7 @@ CC_NOINLINE static void StringsBuffer_Init(struct StringsBuffer* buffer) {
buffer->_flagsCapacity = STRINGSBUFFER_FLAGS_DEF_ELEMS;
if (buffer->_lenShift) return;
StringsBuffer_SetLengthBits(buffer, STRINGSBUFFER_DEFAULT_LEN_SHIFT);
StringsBuffer_SetLengthBits(buffer, STRINGSBUFFER_DEF_LEN_SHIFT);
}
void StringsBuffer_SetLengthBits(struct StringsBuffer* buffer, int bits) {

View File

@ -207,7 +207,8 @@ CC_API cc_bool Convert_ParseBool(const cc_string* str, cc_bool* value);
#define STRINGSBUFFER_BUFFER_DEF_SIZE 4096
#define STRINGSBUFFER_FLAGS_DEF_ELEMS 256
#define STRINGSBUFFER_LEN_MASK 0x1FFUL
#define STRINGSBUFFER_DEF_LEN_SHIFT 9
#define STRINGSBUFFER_DEF_LEN_MASK 0x1FFUL
struct StringsBuffer {
char* textBuffer; /* Raw characters of all entries */
@ -223,6 +224,8 @@ struct StringsBuffer {
int _lenMask;
};
/* Sets the number of bits in an entry's flags that are used to store its length. */
/* (e.g. if bits is 9, then the maximum length of an entry is 2^9-1 = 511) */
void StringsBuffer_SetLengthBits(struct StringsBuffer* buffer, int bits);
/* Resets counts to 0, and frees any allocated memory. */
CC_NOINLINE void StringsBuffer_Clear(struct StringsBuffer* buffer);

View File

@ -225,16 +225,16 @@ int Convert_FromBase64(const char* src, int len, cc_uint8* dst) {
*#########################################################################################################################*/
void EntryList_Load(struct StringsBuffer* list, const char* file, char separator, EntryList_Filter filter) {
cc_string entry; char entryBuffer[768];
cc_string path; char pathBuffer[FILENAME_SIZE];
cc_string path;
cc_string key, value;
int lineLen;
int lineLen, maxLen;
cc_uint8 buffer[2048];
struct Stream stream, buffered;
cc_result res;
String_InitArray(path, pathBuffer);
String_AppendConst(&path, file);
path = String_FromReadonly(file);
maxLen = list->_lenMask ? list->_lenMask : STRINGSBUFFER_DEF_LEN_MASK;
res = Stream_OpenFile(&stream, &path);
if (res == ReturnCode_FileNotFound) return;
@ -258,7 +258,7 @@ void EntryList_Load(struct StringsBuffer* list, const char* file, char separator
/* Sometimes file becomes corrupted and replaced with NULL */
/* If don't prevent this here, client aborts in StringsBuffer_Add */
if (entry.length > STRINGSBUFFER_LEN_MASK) {
if (entry.length > maxLen) {
lineLen = entry.length;
entry.length = 0;
String_Format2(&entry, "Skipping very long (%i characters) line in %c, file may be corrupted", &lineLen, file);