Skip to content

Commit

Permalink
[config] Set and get user specific mode. Fixes JB#49457
Browse files Browse the repository at this point in the history
Use device owner's config as a fallback if user doesn't have a mode set.
Prevent getting or setting invalid modes, i.e. those that are either not
whitelisted or not permitted, falling back to MODE_ASK.

Signed-off-by: Tomi Leppänen <tomi.leppanen@jolla.com>
  • Loading branch information
Tomin1 committed Jun 3, 2020
1 parent 9bfcbc8 commit 3993ba3
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 20 deletions.
11 changes: 9 additions & 2 deletions src/usb_moded-config-private.h
Expand Up @@ -52,6 +52,11 @@
# define USB_MODED_DYNAMIC_CONFIG_DIR "/var/lib/usb-moded"
# define USB_MODED_DYNAMIC_CONFIG_FILE USB_MODED_DYNAMIC_CONFIG_DIR"/usb-moded.ini"

#ifdef SAILFISH_ACCESS_CONTROL
# define MIN_ADDITIONAL_USER 100001
# define MAX_ADDITIONAL_USER 999999
#endif

/* ========================================================================= *
* Prototypes
* ========================================================================= */
Expand All @@ -71,9 +76,11 @@ char *config_get_trigger_mode (void);
char *config_get_trigger_property (void);
char *config_get_trigger_value (void);
char *config_get_conf_string (const gchar *entry, const gchar *key);
char *config_get_mode_setting (void);
gchar *config_get_user_conf_string (const gchar *entry, const gchar *base_key, uid_t uid);
char *config_get_mode_setting (uid_t uid);
set_config_result_t config_set_config_setting (const char *entry, const char *key, const char *value);
set_config_result_t config_set_mode_setting (const char *mode);
set_config_result_t config_set_user_config_setting (const char *entry, const char *base_key, const char *value, uid_t uid);
set_config_result_t config_set_mode_setting (const char *mode, uid_t uid);
set_config_result_t config_set_hide_mode_setting (const char *mode);
set_config_result_t config_set_unhide_mode_setting (const char *mode);
set_config_result_t config_set_mode_whitelist (const char *whitelist);
Expand Down
76 changes: 64 additions & 12 deletions src/usb_moded-config.c
Expand Up @@ -80,10 +80,13 @@ static char *config_get_network_netmask (void);
static char *config_get_network_nat_interface(void);
static int config_get_conf_int (const gchar *entry, const gchar *key);
char *config_get_conf_string (const gchar *entry, const gchar *key);
static gchar *config_make_user_key_string (const gchar *base_key, uid_t uid);
gchar *config_get_user_conf_string (const gchar *entry, const gchar *base_key, uid_t uid);
static char *config_get_kcmdline_string (const char *entry);
char *config_get_mode_setting (void);
char *config_get_mode_setting (uid_t uid);
set_config_result_t config_set_config_setting (const char *entry, const char *key, const char *value);
set_config_result_t config_set_mode_setting (const char *mode);
set_config_result_t config_set_user_config_setting (const char *entry, const char *base_key, const char *value, uid_t uid);
set_config_result_t config_set_mode_setting (const char *mode, uid_t uid);
static char *config_make_modes_string (const char *key, const char *mode_name, int include);
set_config_result_t config_set_hide_mode_setting (const char *mode);
set_config_result_t config_set_unhide_mode_setting (const char *mode);
Expand Down Expand Up @@ -290,6 +293,34 @@ char *config_get_conf_string(const gchar *entry, const gchar *key)
return val;
}

static gchar *config_make_user_key_string(const gchar *base_key, uid_t uid)
{
LOG_REGISTER_CONTEXT;

gchar *key = 0;
#ifdef SAILFISH_ACCESS_CONTROL
/* If uid is for an additional user, construct a key */
if( uid >= MIN_ADDITIONAL_USER && uid <= MAX_ADDITIONAL_USER )
key = g_strdup_printf("%s_%d", base_key, (int)uid);
#endif
return key;
}

gchar *config_get_user_conf_string(const gchar *entry, const gchar *base_key, uid_t uid)
{
LOG_REGISTER_CONTEXT;

gchar *value = 0;
gchar *key = config_make_user_key_string(base_key, uid);
if( key )
value = config_get_conf_string(entry, key);
/* Fallback to global config if user doesn't have a value set */
if( !value )
value = config_get_conf_string(entry, base_key);
g_free(key);
return value;
}

static char * config_get_kcmdline_string(const char *entry)
{
LOG_REGISTER_CONTEXT;
Expand Down Expand Up @@ -368,7 +399,7 @@ static char * config_get_kcmdline_string(const char *entry)
return ret;
}

char * config_get_mode_setting(void)
char * config_get_mode_setting(uid_t uid)
{
LOG_REGISTER_CONTEXT;

Expand All @@ -378,11 +409,18 @@ char * config_get_mode_setting(void)
if( (mode = config_get_kcmdline_string(MODE_SETTING_KEY)) )
goto EXIT;

if( (mode = config_get_conf_string(MODE_SETTING_ENTRY, MODE_SETTING_KEY)) )
goto EXIT;
mode = config_get_user_conf_string(MODE_SETTING_ENTRY, MODE_SETTING_KEY, uid);

/* If no default mode is configured, treat it as charging only */
mode = g_strdup(MODE_CHARGING);
if( !mode )
mode = g_strdup(MODE_CHARGING);
/* If mode is not allowed, i.e. non-existent or not whitelisted or permitted, use MODE_ASK */
else if( strcmp(mode, MODE_ASK) && (common_valid_mode(mode) || !usbmoded_is_mode_permitted(mode, uid)) ) {
log_warning("default mode '%s' is not valid for uid '%d', reset to '%s'",
mode, (int)uid, MODE_ASK);
g_free(mode), mode = g_strdup(MODE_ASK);
config_set_mode_setting(mode, uid);
}

EXIT:
return mode;
Expand Down Expand Up @@ -426,17 +464,30 @@ set_config_result_t config_set_config_setting(const char *entry, const char *key
return ret;
}

set_config_result_t config_set_mode_setting(const char *mode)
set_config_result_t config_set_user_config_setting(const char *entry, const char *base_key, const char *value, uid_t uid)
{
LOG_REGISTER_CONTEXT;

gchar *key = config_make_user_key_string(base_key, uid);
set_config_result_t ret = config_set_config_setting(entry, key ?: base_key, value);
g_free(key);
return ret;
}

set_config_result_t config_set_mode_setting(const char *mode, uid_t uid)
{
LOG_REGISTER_CONTEXT;

/* Don't write values that don't exist */
if (strcmp(mode, MODE_ASK) && common_valid_mode(mode))
return SET_CONFIG_ERROR;

int ret = config_set_config_setting(MODE_SETTING_ENTRY,
MODE_SETTING_KEY, mode);
/* Don't write values that are not permitted */
if (!usbmoded_is_mode_permitted(mode, uid))
return SET_CONFIG_ERROR;

return ret;
return config_set_user_config_setting(MODE_SETTING_ENTRY,
MODE_SETTING_KEY, mode, uid);
}

/* Builds the string used for hidden modes, when hide set to one builds the
Expand Down Expand Up @@ -558,9 +609,10 @@ set_config_result_t config_set_mode_whitelist(const char *whitelist)
char *mode_setting;
const char *current_mode;

mode_setting = config_get_mode_setting();
uid_t current_user = control_get_current_user();
mode_setting = config_get_mode_setting(current_user);
if (strcmp(mode_setting, MODE_ASK) && common_valid_mode(mode_setting))
config_set_mode_setting(MODE_ASK);
config_set_mode_setting(MODE_ASK, current_user);
g_free(mode_setting);

current_mode = control_get_usb_mode();
Expand Down
6 changes: 5 additions & 1 deletion src/usb_moded-control.c
Expand Up @@ -344,7 +344,11 @@ void control_select_usb_mode(void)
}

uid_t current_user = control_get_current_user();
mode_to_set = config_get_mode_setting();
/* If current user could not be determined, assume that device is
* booting up or between sessions. Therefore we either must use whatever
* is configured as global mode or let device lock to prevent the mode
* so that it can be set again once the device is unlocked */
mode_to_set = config_get_mode_setting((current_user == UID_UNKNOWN) ? 0 : current_user);

/* If there is only one allowed mode, use it without
* going through ask-mode */
Expand Down
8 changes: 5 additions & 3 deletions src/usb_moded-dbus.c
Expand Up @@ -424,15 +424,16 @@ static DBusHandlerResult umdbus_msg_handler(DBusConnection *const connection, DB
}
else if(!strcmp(member, USB_MODE_CONFIG_SET))
{
char *config = 0;
char *config = 0;
DBusError err = DBUS_ERROR_INIT;
uid_t uid = umdbus_get_sender_uid(sender);

if(!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &config, DBUS_TYPE_INVALID))
reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member);
else
{
/* error checking is done when setting configuration */
int ret = config_set_mode_setting(config);
int ret = config_set_mode_setting(config, uid);
if (SET_CONFIG_OK(ret))
{
if((reply = dbus_message_new_method_return(msg)))
Expand Down Expand Up @@ -551,7 +552,8 @@ static DBusHandlerResult umdbus_msg_handler(DBusConnection *const connection, DB
}
else if(!strcmp(member, USB_MODE_CONFIG_GET))
{
char *config = config_get_mode_setting();
uid_t uid = umdbus_get_sender_uid(sender);
char *config = config_get_mode_setting(uid);

if((reply = dbus_message_new_method_return(msg)))
dbus_message_append_args (reply, DBUS_TYPE_STRING, &config, DBUS_TYPE_INVALID);
Expand Down
5 changes: 3 additions & 2 deletions src/usb_moded.c
Expand Up @@ -627,12 +627,13 @@ void usbmoded_handle_signal(int signum)

/* If default mode selection became invalid,
* revert setting to "ask" */
gchar *config = config_get_mode_setting();
uid_t current_user = control_get_current_user();
gchar *config = config_get_mode_setting(current_user);
if( g_strcmp0(config, MODE_ASK) &&
common_valid_mode(config) ) {
log_warning("default mode '%s' is not valid, reset to '%s'",
config, MODE_ASK);
config_set_mode_setting(MODE_ASK);
config_set_mode_setting(MODE_ASK, current_user);
}
else {
log_debug("default mode '%s' is still valid", config);
Expand Down

0 comments on commit 3993ba3

Please sign in to comment.