X-Git-Url: https://uglyman.kremlin.cc/gitweb/gitweb.cgi?p=systembsd.git;a=blobdiff_plain;f=src%2Finterfaces%2Ftimedated%2Ftimedated.c;h=c4f5033876abd4368383cb8e5f3b413efccce18d;hp=61a48cb4873c47afcccf6c721cb8638a21aa4537;hb=5b56a1e839b2572e0aa1d4b6143700a424ff509c;hpb=644bae40970b7fdc5731db4c3e4ee93a1a436a22 diff --git a/src/interfaces/timedated/timedated.c b/src/interfaces/timedated/timedated.c index 61a48cb..c4f5033 100644 --- a/src/interfaces/timedated/timedated.c +++ b/src/interfaces/timedated/timedated.c @@ -20,8 +20,11 @@ #include #include +#include +#include #include #include +#include #include #include @@ -33,6 +36,8 @@ #include "../../util.h" +#define TZNAME_MAX PATH_MAX + GPtrArray *timedated_freeable; Timedate1 *timedated_interf; @@ -162,7 +167,102 @@ on_handle_set_timezone(Timedate1 *td1_passed_interf, GDBusMethodInvocation *invoc, const gchar *greet, gpointer data) { - return FALSE; + + GVariant *params; + gchar *proposed_tz; + const gchar *bus_name; + gboolean policykit_auth; + check_auth_result is_authed; + + gchar *tz_target_path; + struct stat *statbuf; + extern int errno; + + params = g_dbus_method_invocation_get_parameters(invoc); + g_variant_get(params, "(sb)", &proposed_tz, &policykit_auth); + bus_name = g_dbus_method_invocation_get_sender(invoc); + + is_authed = polkit_try_auth(bus_name, "org.freedesktop.timedate1.set-timezone", policykit_auth); + + switch(is_authed) { + + case AUTHORIZED_NATIVELY: + case AUTHORIZED_BY_PROMPT: + break; + + case UNAUTHORIZED_NATIVELY: + case UNAUTHORIZED_FAILED_PROMPT: + g_dbus_method_invocation_return_dbus_error(invoc, "org.freedesktop.timedate1.Error.EACCES", "Insufficient permissions to set timezone."); + return FALSE; + + case ERROR_BADBUS: + g_dbus_method_invocation_return_dbus_error(invoc, "org.freedesktop.timedate1.Error.EFAULT", "Provided bus name is invalid."); + return FALSE; + + case ERROR_BADACTION: + g_dbus_method_invocation_return_dbus_error(invoc, "org.freedesktop.timedate1.Error.EFAULT", "Provided action ID is invalid."); + return FALSE; + + case ERROR_GENERIC: + default: + g_dbus_method_invocation_return_dbus_error(invoc, "org.freedesktop.timedate1.Error.ECANCELED", "Failed to set timezone for unknown reasons."); + return FALSE; + } + + statbuf = (struct stat*) calloc(1, sizeof(struct stat)); + tz_target_path = (gchar *) calloc(1, TZNAME_MAX); + + g_ptr_array_add(timedated_freeable, statbuf); + g_ptr_array_add(timedated_freeable, tz_target_path); + + strlcat(tz_target_path, TZDIR, TZNAME_MAX); + strlcat(tz_target_path, "/", TZNAME_MAX); + strlcat(tz_target_path, proposed_tz, TZNAME_MAX); + + if(strstr(tz_target_path, "../")) { + + g_dbus_method_invocation_return_dbus_error(invoc, "org.freedesktop.timedate1.Error.EBADF", "Provided timezone is invalid."); + return FALSE; + } + + if(!statbuf) + return FALSE; + + if(lstat(tz_target_path, statbuf)) { + + switch(errno) { + + case ENOENT: + g_dbus_method_invocation_return_dbus_error(invoc, "org.freedesktop.timedate1.Error.ENOENT", "Specified timezone does not exist."); + break; + + default: + g_dbus_method_invocation_return_dbus_error(invoc, "org.freedesktop.timedate1.Error.EBADF", "Specified timezone is invalid."); + break; + } + + return FALSE; + } + + if(!S_ISREG(statbuf->st_mode)) { + + g_dbus_method_invocation_return_dbus_error(invoc, "org.freedesktop.timedate1.Error.EBADF", "Specified path is of an inappropriate type."); + return FALSE; + } + + memset(statbuf, 0, sizeof statbuf); + + if(!lstat(TZDEFAULT, statbuf)) + if(remove(TZDEFAULT)) + return FALSE; + + if(symlink(tz_target_path, TZDEFAULT)) + return FALSE; + + + timedate1_complete_set_timezone(td1_passed_interf, invoc); + + return TRUE; } static gboolean @@ -170,7 +270,9 @@ on_handle_set_local_rtc(Timedate1 *td1_passed_interf, GDBusMethodInvocation *invoc, const gchar *greet, gpointer data) { - return FALSE; + + g_dbus_method_invocation_return_dbus_error(invoc, "org.freedesktop.timedate1.Error.ENODEV", "Unix RTC must be in UTC."); + return TRUE; } static gboolean @@ -178,9 +280,82 @@ on_handle_set_ntp(Timedate1 *td1_passed_interf, GDBusMethodInvocation *invoc, const gchar *greet, gpointer data) { - return FALSE; -} + GVariant *params; + const gchar *bus_name; + gboolean policykit_auth; + check_auth_result is_authed; + + /* revert to rcctl when 5.7 rolls around */ + gint ntpd_notrunning, ntpd_notenabled; /* this logic flip is due to rcctl returning 0 on success, + * in this case an error means ntpd is not running or not enabled */ + gboolean proposed_ntpstate; + GError *sh_errors; + + extern int errno; + + params = g_dbus_method_invocation_get_parameters(invoc); + g_variant_get(params, "(bb)", &proposed_ntpstate, &policykit_auth); + bus_name = g_dbus_method_invocation_get_sender(invoc); + + is_authed = polkit_try_auth(bus_name, "org.freedesktop.timedate1.set-ntp", policykit_auth); + + switch(is_authed) { + + case AUTHORIZED_NATIVELY: + case AUTHORIZED_BY_PROMPT: + break; + + case UNAUTHORIZED_NATIVELY: + case UNAUTHORIZED_FAILED_PROMPT: + g_dbus_method_invocation_return_dbus_error(invoc, "org.freedesktop.timedate1.Error.EACCES", "Insufficient permissions to toggle the NTP daemon."); + return FALSE; + + case ERROR_BADBUS: + g_dbus_method_invocation_return_dbus_error(invoc, "org.freedesktop.timedate1.Error.EFAULT", "Provided bus name is invalid."); + return FALSE; + + case ERROR_BADACTION: + g_dbus_method_invocation_return_dbus_error(invoc, "org.freedesktop.timedate1.Error.EFAULT", "Provided action ID is invalid."); + return FALSE; + + case ERROR_GENERIC: + default: + g_dbus_method_invocation_return_dbus_error(invoc, "org.freedesktop.timedate1.Error.ECANCELED", "Failed to toggle the NTP daemon for unknown reasons."); + return FALSE; + } + + ntpd_notrunning = 0; /* GLib does not bother asserting the passed return value int to zero */ + ntpd_notenabled = 0; /* if the program's exit status is also zero, hence this decl. */ + + if((ntpd_notrunning = system("/etc/rc.d/ntpd check > /dev/null 2>&1")) == -1) + return FALSE; + + if((ntpd_notenabled = system("/etc/rc.d/ntpd status > /dev/null 2>&1")) == -1) + return FALSE; + + if(proposed_ntpstate) { + + if(ntpd_notrunning) + system("/etc/rc.d/ntpd -f start > /dev/null 2>&1"); + + if(ntpd_notenabled) + system("/etc/rc.d/ntpd enable > /dev/null 2>&1"); + + } else { + + if(!ntpd_notrunning) + system("/etc/rc.d/ntpd stop > /dev/null 2>&1"); + + if(!ntpd_notenabled) + system("/etc/rc.d/ntpd disable > /dev/null 2>&1"); + } + + timedate1_complete_set_ntp(td1_passed_interf, invoc); + + return TRUE; +} +/* NOTE: you should be using gobject->set_property() for these ! */ const gchar * our_get_timezone() { @@ -222,42 +397,49 @@ our_get_timezone() { if(hash_to_match) g_free(hash_to_match); } - + return ret; } +/* Unix time is in UTC. */ gboolean our_get_local_rtc() { - gboolean ret = FALSE; - - return ret; + return FALSE; } gboolean our_get_can_ntp() { - const gboolean ret = FALSE; + /* ntpd is part of the default install */ - return ret; + return TRUE; } gboolean our_get_ntp() { - const gboolean ret = FALSE; + int system_ret; - return ret; + system_ret = system("/etc/rc.d/ntpd check > /dev/null 2>&1"); + + if(system_ret) + return FALSE; + + return TRUE; } +/* undocumented feature present in systemd */ gboolean our_get_ntpsynchronized() { - const gboolean ret = FALSE; + gboolean ntp; + ntp = our_get_ntp(); - return ret; + return ntp; } +/* undocumented feature present in systemd */ guint64 our_get_time_usec() { @@ -266,6 +448,7 @@ our_get_time_usec() { return ret; } +/* undocumented feature present in systemd */ guint64 our_get_rtc_time_usec() { @@ -291,6 +474,7 @@ static void timedated_on_bus_acquired(GDBusConnection *conn, g_signal_connect(timedated_interf, "handle-set-ntp", G_CALLBACK(on_handle_set_ntp), NULL); /* set our properties before export */ + timedate1_set_timezone(timedated_interf, our_get_timezone()); timedate1_set_local_rtc(timedated_interf, our_get_local_rtc()); timedate1_set_can_ntp(timedated_interf, our_get_can_ntp()); @@ -299,6 +483,16 @@ static void timedated_on_bus_acquired(GDBusConnection *conn, timedate1_set_time_usec(timedated_interf, our_get_time_usec()); timedate1_set_rtctime_usec(timedated_interf, our_get_rtc_time_usec()); + /* WIP + + timedated_interf->get_timezone = our_get_timezone(); + timedated_interf->get_local_rtc = our_get_local_rtc(); + timedated_interf->get_can_ntp = our_get_can_ntp(); + timedated_interf->get_ntp = our_get_ntp(); + timedated_interf->get_ntpsynchronized = our_get_ntpsynchronized(); + timedated_interf->get_time_usec = our_get_time_usec(); + timedated_interf->get_rtctime_usec = our_get_rtc_time_usec(); */ + if(!g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(timedated_interf), conn, "/org/freedesktop/timedate1",