/* --- begin method/property/dbus signal code --- */
-/* TODO the extra boolean passed to these funcs is for policykit auth */
-/* TODO complete call with error, message, etc */
+/* TODO free some strings here */
static gboolean
on_handle_set_hostname(Hostname1 *hn1_passed_interf,
GDBusMethodInvocation *invoc,
gpointer data) {
GVariant *params;
gchar *proposed_hostname, *valid_hostname_buf;
- gboolean policykit_auth, ret;
+ const gchar *bus_name;
+ gboolean policykit_auth, ret, try_to_set;
size_t check_length;
+ check_auth_result is_authed;
proposed_hostname = NULL;
- ret = FALSE;
+ ret = try_to_set = FALSE;
params = g_dbus_method_invocation_get_parameters(invoc);
g_variant_get(params, "(sb)", &proposed_hostname, &policykit_auth);
+ bus_name = g_dbus_method_invocation_get_sender(invoc);
- if(proposed_hostname && (valid_hostname_buf = g_hostname_to_ascii(proposed_hostname))) {
+ /* verify caller has correct permissions via polkit */
+ is_authed = polkit_try_auth(bus_name, "org.freedesktop.hostname1.SetHostname", policykit_auth);
- check_length = strnlen(proposed_hostname, MAXHOSTNAMELEN + 1);
+ switch(is_authed) {
+
+ case AUTHORIZED_NATIVELY:
+ case AUTHORIZED_BY_PROMPT:
+ try_to_set = TRUE;
+ break;
+
+ case UNAUTHORIZED_NATIVELY:
+ case UNAUTHORIZED_FAILED_PROMPT:
+ g_dbus_method_invocation_return_dbus_error(invoc, "org.freedesktop.hostname1.Error.EACCES", "Insufficient permissions to set hostname.");
+ break;
+
+ case ERROR_BADBUS:
+ g_dbus_method_invocation_return_dbus_error(invoc, "org.freedesktop.hostname1.Error.EFAULT", "Provided bus name is invalid.");
+ break;
+
+ case ERROR_BADACTION:
+ g_dbus_method_invocation_return_dbus_error(invoc, "org.freedesktop.hostname1.Error.EFAULT", "Provided action ID is invalid.");
+ break;
+
+ case ERROR_GENERIC:
+ default:
+ g_dbus_method_invocation_return_dbus_error(invoc, "org.freedesktop.hostname1.Error.ECANCELED", "Failed to set hostname for unknown reason.");
+ break;
+ }
+
+ /* verify passed hostname's validity */
+ if(try_to_set && proposed_hostname && (valid_hostname_buf = g_hostname_to_ascii(proposed_hostname))) {
+
+ check_length = strnlen(valid_hostname_buf, MAXHOSTNAMELEN + 1);
+
+ if(check_length > MAXHOSTNAMELEN) {
- if(check_length > MAXHOSTNAMELEN)
g_dbus_method_invocation_return_dbus_error(invoc, "org.freedesktop.hostname1.Error.ENAMETOOLONG", "Hostname string exceeded maximum length.");
+ g_free(valid_hostname_buf);
- else if(sethostname(proposed_hostname, check_length))
- g_dbus_method_invocation_return_dbus_error(invoc, "org.freedesktop.hostname1.Error.EACCES", "Insufficient permissions to change hostname.");
+ } else if(sethostname(proposed_hostname, check_length)) {
- else {
- HOSTNAME = proposed_hostname;
+ g_dbus_method_invocation_return_dbus_error(invoc, "org.freedesktop.hostname1.Error.ECANCELED", "Failed to set hostname for unknown reason.");
+ g_free(valid_hostname_buf);
+
+ } else {
+
+ HOSTNAME = valid_hostname_buf;
hostname1_set_hostname(hn1_passed_interf, HOSTNAME);
+ g_ptr_array_add(hostnamed_freeable, valid_hostname_buf);
ret = TRUE;
hostname1_complete_set_hostname(hn1_passed_interf, invoc);
}
}
-
- if(proposed_hostname)
- g_free(proposed_hostname);
- if(valid_hostname_buf)
- g_free(valid_hostname_buf);
return ret;
}
static gboolean is_valid_action(GList *action_list, const gchar *action) {
PolkitActionDescription *action_descr;
- action_descr = (PolkitActionDescription *)g_list_first(action_list);
+ const gchar *action_descr_id;
+ GList *cur;
+ gboolean ret;
- while((action_descr = (PolkitActionDescription *)g_list_next(action_list)))
- if(!g_strcmp0(action, polkit_action_description_get_action_id(action_descr)))
- return TRUE;
+ ret = FALSE;
+ cur = g_list_first(action_list);
- return FALSE;
+ while(cur && (action_descr = ((PolkitActionDescription *)(cur->data))) && (action_descr_id = polkit_action_description_get_action_id(action_descr))) {
+
+ if(!g_strcmp0(action, action_descr_id)) {
+ ret = TRUE;
+ break;
+ }
+
+ cur = cur->next;
+ }
+
+ g_list_free(action_list);
+
+ return ret;
}
-check_auth_result polkit_try_auth(const gchar *bus, const gchar *action) {
+check_auth_result polkit_try_auth(const gchar *bus, const gchar *action, gboolean prompt) {
GList *valid_actions;
PolkitAuthority *auth;
PolkitSubject *subj;
PolkitAuthorizationResult *result;
+ PolkitCheckAuthorizationFlags prompt_flag;
gboolean authorized, challenge;
-
+
auth = NULL;
subj = NULL;
result = NULL;
valid_actions = NULL;
authorized = challenge = FALSE;
+ prompt_flag = prompt ? POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION : POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE;
auth = polkit_authority_get_sync(NULL, NULL); /* TODO timeout for this */
subj = polkit_system_bus_name_new(bus);
else if(!is_valid_action(valid_actions, action))
return ERROR_BADACTION;
- if(!(result = polkit_authority_check_authorization_sync(auth, subj, action, NULL, POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, NULL, NULL)))
+ if(!(result = polkit_authority_check_authorization_sync(auth, subj, action, NULL, prompt_flag, NULL, NULL)))
return ERROR_GENERIC; /* TODO pass, check gerror and return more relevant error */
authorized = polkit_authorization_result_get_is_authorized(result);