#include "hostnamed-gen.h"
#include "hostnamed.h"
+#include "../../polkit-auth.h"
+
/* format: {
* (1) string to be matched against runtime machine's sysctl output.
* can be either the exact string or a substring contained
/* --- 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;
- size_t check_length, bad_length;
+ const gchar *bus_name;
+ gboolean policykit_auth, ret, try_to_set;
+ size_t check_length;
+ check_auth_result is_authed;
- bad_length = MAXHOSTNAMELEN + 1;
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, bad_length);
+ switch(is_authed) {
- if(check_length < bad_length && !sethostname(proposed_hostname, check_length))
- ret = TRUE;
+ 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;
}
- if(ret)
- hostname1_complete_set_hostname(hn1_passed_interf, invoc);
+ /* 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) {
+
+ 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.ECANCELED", "Failed to set hostname for unknown reason.");
+ g_free(valid_hostname_buf);
+
+ } else {
- if(proposed_hostname)
- g_free(proposed_hostname);
- if(valid_hostname_buf)
- g_free(valid_hostname_buf);
+ 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);
+ }
+ }
return ret;
}
const gchar *
our_get_hostname() {
- if(HOSTNAME)
+ gchar *hostname_buf;
+ hostname_buf = (gchar *)g_malloc0(MAXHOSTNAMELEN);
+
+ if(gethostname(hostname_buf, MAXHOSTNAMELEN))
+ return "localhost.home.network"; /* TODO bomb out here probably */
+
+ else if(!g_strcmp0(HOSTNAME, hostname_buf)) {
+
+ g_free(hostname_buf);
return HOSTNAME;
+ }
+
+ g_ptr_array_add(hostnamed_freeable, hostname_buf);
+ HOSTNAME = hostname_buf;
+ hostname1_set_hostname(hostnamed_interf, HOSTNAME);
- return "localhost";
+ return HOSTNAME;
}
const gchar *
our_get_static_hostname() {
- if(STATIC_HOSTNAME)
+ if(STATIC_HOSTNAME && g_strcmp0(STATIC_HOSTNAME, ""))
return STATIC_HOSTNAME;
else if(HOSTNAME)
return HOSTNAME;
- return "localhost";
+ return "localhost.home.network";
}
const gchar *
/* --- end method/property/dbus signal code, begin bus/name handlers --- */
static void hostnamed_on_bus_acquired(GDBusConnection *conn,
- const gchar *name,
- gpointer user_data) {
+ const gchar *name,
+ gpointer user_data) {
g_printf("got bus/name, exporting %s's interface...\n", name);
CHASSIS = ICON = OS_CPENAME = 0;
KERN_NAME = KERN_RELEASE = KERN_VERS = 0;
HOSTNAME = STATIC_HOSTNAME = PRETTY_HOSTNAME = NULL;
-
+
set_signal_handlers();
if(!determine_chassis_and_icon() || !set_uname_properties() || !set_names())