Skip to content

Commit dc1bf43

Browse files
author
Richard Macias
committed
Separate sensitive credentials into credentials.cfg
1 parent baba2fe commit dc1bf43

File tree

2 files changed

+213
-42
lines changed

2 files changed

+213
-42
lines changed

configuration.c

Lines changed: 203 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -779,7 +779,8 @@ static const enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_NULL;
779779
enum config_bool_flags
780780
{
781781
CFG_BOOL_FLG_DEF_ENABLE = (1 << 0),
782-
CFG_BOOL_FLG_HANDLE = (1 << 1)
782+
CFG_BOOL_FLG_HANDLE = (1 << 1),
783+
CFG_BOOL_FLG_SENSITIVE = (1 << 2)
783784
};
784785

785786
struct config_bool_setting
@@ -882,9 +883,21 @@ struct config_path_setting
882883
#define SETTING_OVERRIDE(override_setting) \
883884
tmp[count-1].override = override_setting
884885

886+
#define SETTING_SENSITIVE() \
887+
tmp[count-1].flags |= CFG_BOOL_FLG_SENSITIVE
888+
889+
#define SETTING_ARRAY_SENSITIVE(key, configval, default_enable, default_setting, handle_setting) \
890+
SETTING_ARRAY(key, configval, default_enable, default_setting, handle_setting) \
891+
SETTING_SENSITIVE()
892+
893+
#define SETTING_PATH_SENSITIVE(key, configval, default_enable, default_setting, handle_setting) \
894+
SETTING_PATH(key, configval, default_enable, default_setting, handle_setting) \
895+
SETTING_SENSITIVE()
896+
885897
/* Forward declarations */
886898
#ifdef HAVE_CONFIGFILE
887899
static void config_parse_file(global_t *global);
900+
static size_t config_get_credentials_path(char *s, size_t len);
888901
#endif
889902

890903
struct defaults g_defaults;
@@ -1593,33 +1606,33 @@ static struct config_array_setting *populate_settings_array(
15931606
SETTING_ARRAY("cloud_sync_driver", settings->arrays.cloud_sync_driver, false, NULL, true);
15941607

15951608
#ifdef HAVE_CHEEVOS
1596-
SETTING_ARRAY("cheevos_custom_host", settings->arrays.cheevos_custom_host, false, NULL, true);
1597-
SETTING_ARRAY("cheevos_username", settings->arrays.cheevos_username, false, NULL, true);
1598-
SETTING_ARRAY("cheevos_password", settings->arrays.cheevos_password, false, NULL, true);
1599-
SETTING_ARRAY("cheevos_token", settings->arrays.cheevos_token, false, NULL, true);
1600-
SETTING_ARRAY("cheevos_leaderboards_enable", settings->arrays.cheevos_leaderboards_enable, true, "", true); /* deprecated */
1609+
SETTING_ARRAY("cheevos_custom_host", settings->arrays.cheevos_custom_host, false, NULL, true);
1610+
SETTING_ARRAY_SENSITIVE("cheevos_username", settings->arrays.cheevos_username, false, NULL, true);
1611+
SETTING_ARRAY_SENSITIVE("cheevos_password", settings->arrays.cheevos_password, false, NULL, true);
1612+
SETTING_ARRAY_SENSITIVE("cheevos_token", settings->arrays.cheevos_token, false, NULL, true);
1613+
SETTING_ARRAY("cheevos_leaderboards_enable", settings->arrays.cheevos_leaderboards_enable, true, "", true); /* deprecated */
16011614
#endif
16021615

16031616
#ifdef HAVE_NETWORKING
1604-
SETTING_ARRAY("netplay_mitm_server", settings->arrays.netplay_mitm_server, false, NULL, true);
1605-
SETTING_ARRAY("webdav_url", settings->arrays.webdav_url, false, NULL, true);
1606-
SETTING_ARRAY("webdav_username", settings->arrays.webdav_username, false, NULL, true);
1607-
SETTING_ARRAY("webdav_password", settings->arrays.webdav_password, false, NULL, true);
1608-
SETTING_ARRAY("google_drive_refresh_token", settings->arrays.google_drive_refresh_token, false, NULL, true);
1609-
SETTING_ARRAY("youtube_stream_key", settings->arrays.youtube_stream_key, true, NULL, true);
1610-
SETTING_ARRAY("twitch_stream_key", settings->arrays.twitch_stream_key, true, NULL, true);
1611-
SETTING_ARRAY("facebook_stream_key", settings->arrays.facebook_stream_key, true, NULL, true);
1612-
SETTING_ARRAY("discord_app_id", settings->arrays.discord_app_id, true, DEFAULT_DISCORD_APP_ID, true);
1613-
SETTING_ARRAY("ai_service_url", settings->arrays.ai_service_url, true, DEFAULT_AI_SERVICE_URL, true);
1617+
SETTING_ARRAY("netplay_mitm_server", settings->arrays.netplay_mitm_server, false, NULL, true);
1618+
SETTING_ARRAY("webdav_url", settings->arrays.webdav_url, false, NULL, true);
1619+
SETTING_ARRAY_SENSITIVE("webdav_username", settings->arrays.webdav_username, false, NULL, true);
1620+
SETTING_ARRAY_SENSITIVE("webdav_password", settings->arrays.webdav_password, false, NULL, true);
1621+
SETTING_ARRAY_SENSITIVE("google_drive_refresh_token", settings->arrays.google_drive_refresh_token, false, NULL, true);
1622+
SETTING_ARRAY_SENSITIVE("youtube_stream_key", settings->arrays.youtube_stream_key, true, NULL, true);
1623+
SETTING_ARRAY_SENSITIVE("twitch_stream_key", settings->arrays.twitch_stream_key, true, NULL, true);
1624+
SETTING_ARRAY_SENSITIVE("facebook_stream_key", settings->arrays.facebook_stream_key, true, NULL, true);
1625+
SETTING_ARRAY("discord_app_id", settings->arrays.discord_app_id, true, DEFAULT_DISCORD_APP_ID, true);
1626+
SETTING_ARRAY("ai_service_url", settings->arrays.ai_service_url, true, DEFAULT_AI_SERVICE_URL, true);
16141627
#endif
16151628

16161629
#ifdef HAVE_SMBCLIENT
1617-
SETTING_ARRAY("smb_client_server_address", settings->arrays.smb_client_server_address, false, NULL, true);
1618-
SETTING_ARRAY("smb_client_share", settings->arrays.smb_client_share, false, NULL, true);
1619-
SETTING_ARRAY("smb_client_subdir", settings->arrays.smb_client_subdir, false, NULL, true);
1620-
SETTING_ARRAY("smb_client_username", settings->arrays.smb_client_username, false, NULL, true);
1621-
SETTING_ARRAY("smb_client_password", settings->arrays.smb_client_password, false, NULL, true);
1622-
SETTING_ARRAY("smb_client_workgroup", settings->arrays.smb_client_workgroup, false, NULL, true);
1630+
SETTING_ARRAY("smb_client_server_address", settings->arrays.smb_client_server_address, false, NULL, true);
1631+
SETTING_ARRAY("smb_client_share", settings->arrays.smb_client_share, false, NULL, true);
1632+
SETTING_ARRAY("smb_client_subdir", settings->arrays.smb_client_subdir, false, NULL, true);
1633+
SETTING_ARRAY_SENSITIVE("smb_client_username", settings->arrays.smb_client_username, false, NULL, true);
1634+
SETTING_ARRAY_SENSITIVE("smb_client_password", settings->arrays.smb_client_password, false, NULL, true);
1635+
SETTING_ARRAY("smb_client_workgroup", settings->arrays.smb_client_workgroup, false, NULL, true);
16231636
#endif
16241637

16251638
#ifdef HAVE_LAKKA
@@ -1715,11 +1728,11 @@ static struct config_path_setting *populate_settings_path(
17151728
#endif
17161729

17171730
#ifdef HAVE_NETWORKING
1718-
SETTING_PATH("netplay_ip_address", settings->paths.netplay_server, false, NULL, true);
1719-
SETTING_PATH("netplay_custom_mitm_server", settings->paths.netplay_custom_mitm_server, false, NULL, true);
1720-
SETTING_PATH("netplay_nickname", settings->paths.username, false, NULL, true);
1721-
SETTING_PATH("netplay_password", settings->paths.netplay_password, false, NULL, true);
1722-
SETTING_PATH("netplay_spectate_password", settings->paths.netplay_spectate_password, false, NULL, true);
1731+
SETTING_PATH("netplay_ip_address", settings->paths.netplay_server, false, NULL, true);
1732+
SETTING_PATH("netplay_custom_mitm_server", settings->paths.netplay_custom_mitm_server, false, NULL, true);
1733+
SETTING_PATH("netplay_nickname", settings->paths.username, false, NULL, true);
1734+
SETTING_PATH_SENSITIVE("netplay_password", settings->paths.netplay_password, false, NULL, true);
1735+
SETTING_PATH_SENSITIVE("netplay_spectate_password", settings->paths.netplay_spectate_password, false, NULL, true);
17231736
#endif
17241737

17251738
#ifdef _3DS
@@ -3955,6 +3968,27 @@ static bool config_load_file(global_t *global,
39553968
#endif
39563969
}
39573970

3971+
/* Merge credentials from separate file.
3972+
* Credentials are stored in credentials.cfg alongside
3973+
* the main config to keep sensitive data (passwords,
3974+
* tokens, keys) out of retroarch.cfg. */
3975+
{
3976+
char credentials_path[PATH_MAX_LENGTH];
3977+
credentials_path[0] = '\0';
3978+
config_get_credentials_path(credentials_path,
3979+
sizeof(credentials_path));
3980+
if (!string_is_empty(credentials_path)
3981+
&& path_is_valid(credentials_path))
3982+
{
3983+
bool result = config_append_file(conf, credentials_path);
3984+
RARCH_LOG("[Config] Merging credentials from \"%s\".\n",
3985+
credentials_path);
3986+
if (!result)
3987+
RARCH_ERR("[Config] Failed to merge credentials from \"%s\".\n",
3988+
credentials_path);
3989+
}
3990+
}
3991+
39583992
/* Special case for perfcnt_enable */
39593993
{
39603994
bool tmp = false;
@@ -5560,6 +5594,107 @@ bool config_save_autoconf_profile(const char *device_name, unsigned user)
55605594
return ret;
55615595
}
55625596

5597+
/**
5598+
* config_get_credentials_path:
5599+
*
5600+
* Builds the path to the credentials config file.
5601+
* Uses the same directory as the main config file.
5602+
*
5603+
* Returns: length of the string written to @s.
5604+
**/
5605+
static size_t config_get_credentials_path(char *s, size_t len)
5606+
{
5607+
char config_directory[DIR_MAX_LENGTH];
5608+
config_directory[0] = '\0';
5609+
5610+
if (path_is_empty(RARCH_PATH_CONFIG))
5611+
{
5612+
s[0] = '\0';
5613+
return 0;
5614+
}
5615+
5616+
fill_pathname_basedir(config_directory,
5617+
path_get(RARCH_PATH_CONFIG),
5618+
sizeof(config_directory));
5619+
5620+
return fill_pathname_join_special(s, config_directory,
5621+
"credentials.cfg", len);
5622+
}
5623+
5624+
/**
5625+
* config_save_credentials:
5626+
*
5627+
* Writes only sensitive settings (passwords, tokens, keys)
5628+
* to a separate credentials.cfg file.
5629+
*
5630+
* Returns: true (1) on success, otherwise returns false (0).
5631+
**/
5632+
bool config_save_credentials(void)
5633+
{
5634+
unsigned i;
5635+
bool ret = false;
5636+
char credentials_path[PATH_MAX_LENGTH];
5637+
struct config_array_setting *array_settings = NULL;
5638+
struct config_path_setting *path_settings = NULL;
5639+
settings_t *settings = config_st;
5640+
int array_settings_size = sizeof(settings->arrays) / sizeof(settings->arrays.placeholder);
5641+
int path_settings_size = sizeof(settings->paths) / sizeof(settings->paths.placeholder);
5642+
config_file_t *conf = NULL;
5643+
5644+
credentials_path[0] = '\0';
5645+
config_get_credentials_path(credentials_path, sizeof(credentials_path));
5646+
5647+
if (string_is_empty(credentials_path))
5648+
return false;
5649+
5650+
conf = config_file_new_from_path_to_string(credentials_path);
5651+
if (!conf)
5652+
conf = config_file_new_alloc();
5653+
if (!conf)
5654+
return false;
5655+
5656+
array_settings = populate_settings_array(settings, &array_settings_size);
5657+
path_settings = populate_settings_path(settings, &path_settings_size);
5658+
5659+
if (array_settings && (array_settings_size > 0))
5660+
{
5661+
for (i = 0; i < (unsigned)array_settings_size; i++)
5662+
{
5663+
if (!(array_settings[i].flags & CFG_BOOL_FLG_SENSITIVE))
5664+
continue;
5665+
config_set_string(conf,
5666+
array_settings[i].ident,
5667+
array_settings[i].ptr);
5668+
}
5669+
free(array_settings);
5670+
array_settings = NULL;
5671+
}
5672+
5673+
if (path_settings && (path_settings_size > 0))
5674+
{
5675+
for (i = 0; i < (unsigned)path_settings_size; i++)
5676+
{
5677+
if (!(path_settings[i].flags & CFG_BOOL_FLG_SENSITIVE))
5678+
continue;
5679+
config_set_path(conf,
5680+
path_settings[i].ident,
5681+
path_settings[i].ptr);
5682+
}
5683+
free(path_settings);
5684+
path_settings = NULL;
5685+
}
5686+
5687+
ret = config_file_write(conf, credentials_path, true);
5688+
config_file_free(conf);
5689+
5690+
if (ret)
5691+
RARCH_LOG("[Config] Saved credentials to \"%s\".\n", credentials_path);
5692+
else
5693+
RARCH_ERR("[Config] Failed to save credentials to \"%s\".\n", credentials_path);
5694+
5695+
return ret;
5696+
}
5697+
55635698
/**
55645699
* config_save_file:
55655700
* @path : Path that shall be written to.
@@ -5573,6 +5708,7 @@ bool config_save_file(const char *path)
55735708
float msg_color;
55745709
unsigned i = 0;
55755710
bool ret = false;
5711+
bool credentials_saved = false;
55765712
struct config_bool_setting *bool_settings = NULL;
55775713
struct config_int_setting *int_settings = NULL;
55785714
struct config_uint_setting *uint_settings = NULL;
@@ -5610,13 +5746,31 @@ bool config_save_file(const char *path)
56105746
array_settings = populate_settings_array (settings, &array_settings_size);
56115747
path_settings = populate_settings_path (settings, &path_settings_size);
56125748

5749+
/* Save credentials to a separate file.
5750+
* Only strip sensitive fields from retroarch.cfg
5751+
* when credentials.cfg was written successfully. */
5752+
credentials_saved = config_save_credentials();
5753+
if (!credentials_saved)
5754+
RARCH_WARN("[Config] Credentials save failed, "
5755+
"keeping sensitive fields in main config.\n");
5756+
56135757
/* Path settings */
56145758
if (path_settings && (path_settings_size > 0))
56155759
{
56165760
for (i = 0; i < (unsigned)path_settings_size; i++)
56175761
{
56185762
const char *value = path_settings[i].ptr;
56195763

5764+
/* Sensitive settings are stored in credentials.cfg.
5765+
* Unset removes stale values from existing configs.
5766+
* Only strip when credentials.cfg was written OK. */
5767+
if ( credentials_saved
5768+
&& (path_settings[i].flags & CFG_BOOL_FLG_SENSITIVE))
5769+
{
5770+
config_unset(conf, path_settings[i].ident);
5771+
continue;
5772+
}
5773+
56205774
if (path_settings[i].flags & CFG_BOOL_FLG_DEF_ENABLE)
56215775
if (string_is_empty(path_settings[i].ptr))
56225776
value = "default";
@@ -5640,11 +5794,22 @@ bool config_save_file(const char *path)
56405794
if (array_settings && (array_settings_size > 0))
56415795
{
56425796
for (i = 0; i < (unsigned)array_settings_size; i++)
5797+
{
5798+
/* Sensitive settings are stored in credentials.cfg.
5799+
* Unset removes stale values from existing configs.
5800+
* Only strip when credentials.cfg was written OK. */
5801+
if ( credentials_saved
5802+
&& (array_settings[i].flags & CFG_BOOL_FLG_SENSITIVE))
5803+
{
5804+
config_unset(conf, array_settings[i].ident);
5805+
continue;
5806+
}
56435807
if ( !array_settings[i].override
56445808
|| !retroarch_override_setting_is_set(array_settings[i].override, NULL))
56455809
config_set_string(conf,
56465810
array_settings[i].ident,
56475811
array_settings[i].ptr);
5812+
}
56485813

56495814
free(array_settings);
56505815
}
@@ -6004,22 +6169,14 @@ int8_t config_save_overrides(enum override_type type,
60046169
{
60056170
if (!string_is_equal(array_settings[i].ptr, array_overrides[i].ptr))
60066171
{
6007-
#ifdef HAVE_CHEEVOS
6008-
/* As authentication doesn't occur until after content is loaded,
6009-
* the achievement authentication token might only exist in the
6010-
* override set, and therefore differ from the master config set.
6011-
* Storing the achievement authentication token in an override
6012-
* is a recipe for disaster. If it expires and the user generates
6013-
* a new token, then the override will be out of date and the
6014-
* user will have to reauthenticate for each override (and also
6015-
* remember to update each override). Also exclude the username
6016-
* as it's directly tied to the token and password.
6017-
*/
6018-
if ( string_is_equal(array_settings[i].ident, "cheevos_token")
6019-
|| string_is_equal(array_settings[i].ident, "cheevos_password")
6020-
|| string_is_equal(array_settings[i].ident, "cheevos_username"))
6172+
/* Authentication tokens stored in overrides become stale
6173+
* when they expire and get regenerated in the master
6174+
* config, forcing users to reauthenticate per override.
6175+
* Originally applied to cheevos credentials, now
6176+
* generalized to all sensitive settings via
6177+
* credentials.cfg. */
6178+
if (array_settings[i].flags & CFG_BOOL_FLG_SENSITIVE)
60216179
continue;
6022-
#endif
60236180
config_set_string(conf, array_overrides[i].ident,
60246181
array_overrides[i].ptr);
60256182
RARCH_DBG("[Override] %s = \"%s\"\n",
@@ -6029,6 +6186,10 @@ int8_t config_save_overrides(enum override_type type,
60296186

60306187
for (i = 0; i < (unsigned)path_settings_size; i++)
60316188
{
6189+
/* Sensitive settings are managed via credentials.cfg */
6190+
if (path_settings[i].flags & CFG_BOOL_FLG_SENSITIVE)
6191+
continue;
6192+
60326193
if (!string_is_equal(path_settings[i].ptr, path_overrides[i].ptr))
60336194
{
60346195
#if IOS

configuration.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,6 +1362,16 @@ bool config_save_autoconf_profile(const char *device_name, unsigned user);
13621362
**/
13631363
bool config_save_file(const char *path);
13641364

1365+
/**
1366+
* config_save_credentials:
1367+
*
1368+
* Writes only sensitive settings (passwords, tokens, keys)
1369+
* to a separate credentials.cfg file.
1370+
*
1371+
* Returns: true (1) on success, otherwise returns false (0).
1372+
**/
1373+
bool config_save_credentials(void);
1374+
13651375
/**
13661376
* config_save_overrides:
13671377
* @path : Path that shall be written to.

0 commit comments

Comments
 (0)