From: kremlin Date: Sat, 16 Aug 2014 06:49:33 +0000 (-0500) Subject: tighten up polkit-auth, implement in hostnamed.c X-Git-Tag: gsoc-final~10 X-Git-Url: https://uglyman.kremlin.cc/gitweb/gitweb.cgi?p=systembsd.git;a=commitdiff_plain;h=2bc9066af4eaebe672d39265d9421c09fa086610 tighten up polkit-auth, implement in hostnamed.c --- diff --git a/src/interfaces/hostnamed/hostnamed.c b/src/interfaces/hostnamed/hostnamed.c index af15d9e..de06bf9 100644 --- a/src/interfaces/hostnamed/hostnamed.c +++ b/src/interfaces/hostnamed/hostnamed.c @@ -112,8 +112,7 @@ const gchar *server_archs[] = { /* --- 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, @@ -121,37 +120,71 @@ on_handle_set_hostname(Hostname1 *hn1_passed_interf, 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; } diff --git a/src/polkit-auth.c b/src/polkit-auth.c index 31320a9..00c2dc1 100644 --- a/src/polkit-auth.c +++ b/src/polkit-auth.c @@ -27,28 +27,43 @@ 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); @@ -61,7 +76,7 @@ check_auth_result polkit_try_auth(const gchar *bus, const gchar *action) { 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); diff --git a/src/polkit-auth.h b/src/polkit-auth.h index b672e67..5775fb4 100644 --- a/src/polkit-auth.h +++ b/src/polkit-auth.h @@ -20,4 +20,4 @@ typedef enum { ERROR_BADBUS, ERROR_BADACTION, ERROR_GENERIC } check_auth_result; -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);