diff --git a/src/nm-manager-auth.c b/src/nm-manager-auth.c index 5a64774a1..373e2e297 100644 --- a/src/nm-manager-auth.c +++ b/src/nm-manager-auth.c @@ -42,8 +42,11 @@ struct NMAuthChain { DBusGMethodInvocation *context; char *owner; + gulong user_uid; GError *error; + guint idle_id; + NMAuthChainResultFunc done_func; gpointer user_data; }; @@ -72,6 +75,20 @@ free_data (gpointer data) g_free (tmp); } +static gboolean +auth_chain_finish (gpointer user_data) +{ + NMAuthChain *self = user_data; + + self->idle_id = 0; + + /* Ensure we say alive across the callback */ + self->refcount++; + self->done_func (self, self->error, self->context, self->user_data); + nm_auth_chain_unref (self); + return FALSE; +} + #if WITH_POLKIT static PolkitAuthority * pk_authority_get (GError **error) @@ -92,6 +109,7 @@ _auth_chain_new (DBusGMethodInvocation *context, DBusGProxy *proxy, DBusMessage *message, const char *dbus_sender, + gulong user_uid, NMAuthChainResultFunc done_func, gpointer user_data) { @@ -108,6 +126,7 @@ _auth_chain_new (DBusGMethodInvocation *context, self->done_func = done_func; self->user_data = user_data; self->context = context; + self->user_uid = user_uid; if (proxy) self->owner = g_strdup (dbus_g_proxy_get_bus_name (proxy)); @@ -118,7 +137,7 @@ _auth_chain_new (DBusGMethodInvocation *context, else if (dbus_sender) self->owner = g_strdup (dbus_sender); - if (!self->owner) { + if (user_uid > 0 && !self->owner) { /* Need an owner */ g_warn_if_fail (self->owner); nm_auth_chain_unref (self); @@ -131,26 +150,29 @@ _auth_chain_new (DBusGMethodInvocation *context, NMAuthChain * nm_auth_chain_new (DBusGMethodInvocation *context, DBusGProxy *proxy, + gulong user_uid, NMAuthChainResultFunc done_func, gpointer user_data) { - return _auth_chain_new (context, proxy, NULL, NULL, done_func, user_data); + return _auth_chain_new (context, proxy, NULL, NULL, user_uid, done_func, user_data); } NMAuthChain * nm_auth_chain_new_raw_message (DBusMessage *message, + gulong user_uid, NMAuthChainResultFunc done_func, gpointer user_data) { - return _auth_chain_new (NULL, NULL, message, NULL, done_func, user_data); + return _auth_chain_new (NULL, NULL, message, NULL, user_uid, done_func, user_data); } NMAuthChain * nm_auth_chain_new_dbus_sender (const char *dbus_sender, + gulong user_uid, NMAuthChainResultFunc done_func, gpointer user_data) { - return _auth_chain_new (NULL, NULL, NULL, dbus_sender, done_func, user_data); + return _auth_chain_new (NULL, NULL, NULL, dbus_sender, user_uid, done_func, user_data); } gpointer @@ -261,10 +283,8 @@ nm_auth_chain_check_done (NMAuthChain *self) g_return_if_fail (self != NULL); if (g_slist_length (self->calls) == 0) { - /* Ensure we say alive across the callback */ - self->refcount++; - self->done_func (self, self->error, self->context, self->user_data); - nm_auth_chain_unref (self); + g_assert (self->idle_id == 0); + self->idle_id = g_idle_add (auth_chain_finish, self); } } @@ -372,7 +392,6 @@ pk_call_cb (GObject *object, GAsyncResult *result, gpointer user_data) auth_call_complete (call); } -#endif static void auth_call_schedule_complete_with_error (AuthCall *call, const char *msg) @@ -382,16 +401,14 @@ auth_call_schedule_complete_with_error (AuthCall *call, const char *msg) call->idle_id = g_idle_add ((GSourceFunc) auth_call_complete, call); } -gboolean -nm_auth_chain_add_call (NMAuthChain *self, - const char *permission, - gboolean allow_interaction) +static gboolean +_add_call_polkit (NMAuthChain *self, + const char *permission, + gboolean allow_interaction) { - AuthCall *call; - -#if WITH_POLKIT PolkitSubject *subject; PolkitCheckAuthorizationFlags flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE; + AuthCall *call; g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (self->owner != NULL, FALSE); @@ -423,17 +440,29 @@ nm_auth_chain_add_call (NMAuthChain *self, pk_call_cb, call); g_object_unref (subject); -#else - /* -- NO POLKIT -- */ + return TRUE; +} +#endif + +gboolean +nm_auth_chain_add_call (NMAuthChain *self, + const char *permission, + gboolean allow_interaction) +{ + AuthCall *call; g_return_val_if_fail (self != NULL, FALSE); - /* When PolicyKit is disabled, everything is authorized */ +#if WITH_POLKIT + /* Non-root always gets authenticated when using polkit */ + if (self->user_uid > 0) + return _add_call_polkit (self, permission, allow_interaction); +#endif + + /* Root user or non-polkit always gets the permission */ call = auth_call_new (self, permission); nm_auth_chain_set_data (self, permission, GUINT_TO_POINTER (NM_AUTH_CALL_RESULT_YES), NULL); call->idle_id = g_idle_add ((GSourceFunc) auth_call_complete, call); -#endif - return TRUE; } @@ -448,6 +477,9 @@ nm_auth_chain_unref (NMAuthChain *self) if (self->refcount > 0) return; + if (self->idle_id) + g_source_remove (self->idle_id); + #if WITH_POLKIT if (self->authority) g_object_unref (self->authority); diff --git a/src/nm-manager-auth.h b/src/nm-manager-auth.h index 15317c718..d3597ab6d 100644 --- a/src/nm-manager-auth.h +++ b/src/nm-manager-auth.h @@ -57,14 +57,17 @@ typedef void (*NMAuthChainResultFunc) (NMAuthChain *chain, NMAuthChain *nm_auth_chain_new (DBusGMethodInvocation *context, DBusGProxy *proxy, + gulong user_uid, NMAuthChainResultFunc done_func, gpointer user_data); NMAuthChain *nm_auth_chain_new_raw_message (DBusMessage *message, + gulong user_uid, NMAuthChainResultFunc done_func, gpointer user_data); NMAuthChain *nm_auth_chain_new_dbus_sender (const char *dbus_sender, + gulong user_uid, NMAuthChainResultFunc done_func, gpointer user_data); diff --git a/src/nm-manager.c b/src/nm-manager.c index 194d0ca92..6e99b3040 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -848,27 +848,22 @@ pending_auth_done (NMAuthChain *chain, /* Caller has had a chance to obtain authorization, so we only need to * check for 'yes' here. */ - result = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL)); - if (result != NM_AUTH_CALL_RESULT_YES) { + result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL); + if (error) + tmp_error = g_error_copy (error); + else if (result != NM_AUTH_CALL_RESULT_YES) { tmp_error = g_error_new_literal (NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, "Not authorized to control networking."); - goto out; - } - - if (pending->wifi_shared_permission) { + } else if (pending->wifi_shared_permission) { result = nm_auth_chain_get_result (chain, pending->wifi_shared_permission); if (result != NM_AUTH_CALL_RESULT_YES) { tmp_error = g_error_new_literal (NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, "Not authorized to share connections via wifi."); - goto out; } } - /* Otherwise authorized and available to activate */ - -out: pending->callback (pending, tmp_error); g_clear_error (&tmp_error); } @@ -900,12 +895,6 @@ pending_activation_check_authorized (PendingActivation *pending, return; } - /* Yay for root */ - if (0 == sender_uid) { - pending->callback (pending, NULL); - return; - } - /* By this point we have an auto-completed connection (for AddAndActivate) * or an existing connection (for Activate). */ @@ -929,6 +918,7 @@ pending_activation_check_authorized (PendingActivation *pending, */ pending->chain = nm_auth_chain_new (pending->context, NULL, + sender_uid, pending_auth_done, pending); g_assert (pending->chain); @@ -1738,7 +1728,8 @@ device_auth_done_cb (NMAuthChain *chain, device = nm_auth_chain_get_data (chain, "device"); g_assert (device); - result = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, permission)); + result = nm_auth_chain_get_result (chain, permission); + if (auth_error) { /* translate the auth error into a manager permission denied error */ nm_log_dbg (LOGD_CORE, "%s request failed: %s", permission, auth_error->message); @@ -1791,21 +1782,16 @@ device_auth_request_cb (NMDevice *device, return; } - /* Yay for root */ - if (0 == sender_uid) - callback (device, context, NULL, user_data); - else { - /* Otherwise validate the non-root request */ - chain = nm_auth_chain_new (context, NULL, device_auth_done_cb, self); - g_assert (chain); - priv->auth_chains = g_slist_append (priv->auth_chains, chain); + /* Validate the request */ + chain = nm_auth_chain_new (context, NULL, sender_uid, device_auth_done_cb, self); + g_assert (chain); + priv->auth_chains = g_slist_append (priv->auth_chains, chain); - nm_auth_chain_set_data (chain, "device", g_object_ref (device), g_object_unref); - nm_auth_chain_set_data (chain, "requested-permission", g_strdup (permission), g_free); - nm_auth_chain_set_data (chain, "callback", callback, NULL); - nm_auth_chain_set_data (chain, "user-data", user_data, NULL); - nm_auth_chain_add_call (chain, permission, allow_interaction); - } + nm_auth_chain_set_data (chain, "device", g_object_ref (device), g_object_unref); + nm_auth_chain_set_data (chain, "requested-permission", g_strdup (permission), g_free); + nm_auth_chain_set_data (chain, "callback", callback, NULL); + nm_auth_chain_set_data (chain, "user-data", user_data, NULL); + nm_auth_chain_add_call (chain, permission, allow_interaction); } static void @@ -3171,11 +3157,11 @@ deactivate_net_auth_done_cb (NMAuthChain *chain, NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); GError *error = NULL; NMAuthCallResult result; - const char *active_path; priv->auth_chains = g_slist_remove (priv->auth_chains, chain); - result = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL)); + result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL); + if (auth_error) { nm_log_dbg (LOGD_CORE, "Disconnect request failed: %s", auth_error->message); error = g_error_new (NM_MANAGER_ERROR, @@ -3188,9 +3174,8 @@ deactivate_net_auth_done_cb (NMAuthChain *chain, "Not authorized to deactivate connections"); } else { /* success; deactivation allowed */ - active_path = nm_auth_chain_get_data (chain, "path"); if (!nm_manager_deactivate_connection (self, - active_path, + nm_auth_chain_get_data (chain, "path"), NM_DEVICE_STATE_REASON_USER_REQUESTED, &error)) g_assert (error); @@ -3253,22 +3238,8 @@ impl_manager_deactivate_connection (NMManager *self, return; } - /* Yay for root */ - if (0 == sender_uid) { - if (!nm_manager_deactivate_connection (self, - active_path, - NM_DEVICE_STATE_REASON_USER_REQUESTED, - &error)) { - dbus_g_method_return_error (context, error); - g_clear_error (&error); - } else - dbus_g_method_return (context); - - return; - } - /* Otherwise validate the user request */ - chain = nm_auth_chain_new (context, NULL, deactivate_net_auth_done_cb, self); + chain = nm_auth_chain_new (context, NULL, sender_uid, deactivate_net_auth_done_cb, self); g_assert (chain); priv->auth_chains = g_slist_append (priv->auth_chains, chain); @@ -3372,7 +3343,7 @@ sleep_auth_done_cb (NMAuthChain *chain, priv->auth_chains = g_slist_remove (priv->auth_chains, chain); - result = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, NM_AUTH_PERMISSION_SLEEP_WAKE)); + result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_SLEEP_WAKE); if (error) { nm_log_dbg (LOGD_SUSPEND, "Sleep/wake request failed: %s", error->message); ret_error = g_error_new (NM_MANAGER_ERROR, @@ -3446,17 +3417,9 @@ impl_manager_sleep (NMManager *self, return; } - /* Root doesn't need PK authentication */ - if (0 == sender_uid) { - _internal_sleep (self, do_sleep); - dbus_g_method_return (context); - return; - } - - chain = nm_auth_chain_new (context, NULL, sleep_auth_done_cb, self); + chain = nm_auth_chain_new (context, NULL, sender_uid, sleep_auth_done_cb, self); g_assert (chain); priv->auth_chains = g_slist_append (priv->auth_chains, chain); - nm_auth_chain_set_data (chain, "sleep", GUINT_TO_POINTER (do_sleep), NULL); nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SLEEP_WAKE, TRUE); #endif @@ -3516,27 +3479,23 @@ enable_net_done_cb (NMAuthChain *chain, { NMManager *self = NM_MANAGER (user_data); NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - GError *ret_error; + GError *ret_error = NULL; NMAuthCallResult result; gboolean enable; priv->auth_chains = g_slist_remove (priv->auth_chains, chain); - result = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK)); + result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK); if (error) { nm_log_dbg (LOGD_CORE, "Enable request failed: %s", error->message); ret_error = g_error_new (NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, "Enable request failed: %s", error->message); - dbus_g_method_return_error (context, ret_error); - g_error_free (ret_error); } else if (result != NM_AUTH_CALL_RESULT_YES) { ret_error = g_error_new_literal (NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, "Not authorized to enable/disable networking"); - dbus_g_method_return_error (context, ret_error); - g_error_free (ret_error); } else { /* Auth success */ enable = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "enable")); @@ -3544,6 +3503,11 @@ enable_net_done_cb (NMAuthChain *chain, dbus_g_method_return (context); } + if (ret_error) { + dbus_g_method_return_error (context, ret_error); + g_error_free (ret_error); + } + nm_auth_chain_unref (chain); } @@ -3581,14 +3545,7 @@ impl_manager_enable (NMManager *self, return; } - /* Root doesn't need PK authentication */ - if (0 == sender_uid) { - _internal_enable (self, enable); - dbus_g_method_return (context); - return; - } - - chain = nm_auth_chain_new (context, NULL, enable_net_done_cb, self); + chain = nm_auth_chain_new (context, NULL, sender_uid, enable_net_done_cb, self); g_assert (chain); priv->auth_chains = g_slist_append (priv->auth_chains, chain); @@ -3603,7 +3560,7 @@ get_perm_add_result (NMAuthChain *chain, GHashTable *results, const char *permis { NMAuthCallResult result; - result = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, permission)); + result = nm_auth_chain_get_result (chain, permission); if (result == NM_AUTH_CALL_RESULT_YES) g_hash_table_insert (results, (char *) permission, "yes"); else if (result == NM_AUTH_CALL_RESULT_NO) @@ -3637,6 +3594,7 @@ get_permissions_done_cb (NMAuthChain *chain, g_error_free (ret_error); } else { results = g_hash_table_new (g_str_hash, g_str_equal); + get_perm_add_result (chain, results, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK); get_perm_add_result (chain, results, NM_AUTH_PERMISSION_SLEEP_WAKE); get_perm_add_result (chain, results, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI); @@ -3648,6 +3606,7 @@ get_permissions_done_cb (NMAuthChain *chain, get_perm_add_result (chain, results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM); get_perm_add_result (chain, results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN); get_perm_add_result (chain, results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME); + dbus_g_method_return (context, results); g_hash_table_destroy (results); } @@ -3661,22 +3620,35 @@ impl_manager_get_permissions (NMManager *self, { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); NMAuthChain *chain; + gulong sender_uid = G_MAXULONG; + GError *error; - chain = nm_auth_chain_new (context, NULL, get_permissions_done_cb, self); - g_assert (chain); - priv->auth_chains = g_slist_append (priv->auth_chains, chain); + if (!nm_dbus_manager_get_caller_info (priv->dbus_mgr, + context, + NULL, + &sender_uid)) { + error = g_error_new_literal (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "Unable to determine request UID."); + dbus_g_method_return_error (context, error); + g_error_free (error); + } else { + chain = nm_auth_chain_new (context, NULL, sender_uid, get_permissions_done_cb, self); + g_assert (chain); + priv->auth_chains = g_slist_append (priv->auth_chains, chain); - nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK, FALSE); - nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SLEEP_WAKE, FALSE); - nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI, FALSE); - nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN, FALSE); - nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX, FALSE); - nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, FALSE); - nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, FALSE); - nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN, FALSE); - nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM, FALSE); - nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN, FALSE); - nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME, FALSE); + nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK, FALSE); + nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SLEEP_WAKE, FALSE); + nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI, FALSE); + nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN, FALSE); + nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX, FALSE); + nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, FALSE); + nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, FALSE); + nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN, FALSE); + nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM, FALSE); + nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN, FALSE); + nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME, FALSE); + } } static gboolean @@ -3871,7 +3843,6 @@ prop_set_auth_done_cb (NMAuthChain *chain, const char *permission, *prop; GObject *obj; gboolean set_enabled = TRUE; - gboolean is_device = FALSE; priv->auth_chains = g_slist_remove (priv->auth_chains, chain); @@ -3880,31 +3851,23 @@ prop_set_auth_done_cb (NMAuthChain *chain, prop = nm_auth_chain_get_data (chain, "prop"); set_enabled = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "enabled")); obj = nm_auth_chain_get_data (chain, "object"); - is_device = NM_IS_DEVICE (obj); - if (error) { - reply = dbus_message_new_error (message, is_device ? DEV_PERM_DENIED_ERROR : NM_PERM_DENIED_ERROR, + result = nm_auth_chain_get_result (chain, permission); + if (error || (result != NM_AUTH_CALL_RESULT_YES)) { + reply = dbus_message_new_error (message, + NM_IS_DEVICE (obj) ? DEV_PERM_DENIED_ERROR : NM_PERM_DENIED_ERROR, "Not authorized to perform this operation"); } else { - /* Caller has had a chance to obtain authorization, so we only need to - * check for 'yes' here. - */ - result = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, permission)); - if (result != NM_AUTH_CALL_RESULT_YES) { - reply = dbus_message_new_error (message, is_device ? DEV_PERM_DENIED_ERROR : NM_PERM_DENIED_ERROR, - "Not authorized to perform this operation"); - } else { - g_object_set (obj, prop, set_enabled, NULL); - reply = dbus_message_new_method_return (message); - } + g_object_set (obj, prop, set_enabled, NULL); + reply = dbus_message_new_method_return (message); } - if (reply) { - connection = nm_auth_chain_get_data (chain, "connection"); - g_assert (connection); - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - } + g_assert (reply); + connection = nm_auth_chain_get_data (chain, "connection"); + g_assert (connection); + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); + nm_auth_chain_unref (chain); } @@ -3992,23 +3955,17 @@ prop_filter (DBusConnection *connection, goto out; } - if (caller_uid > 0) { - /* Otherwise validate the user request */ - chain = nm_auth_chain_new_raw_message (message, prop_set_auth_done_cb, self); - g_assert (chain); - priv->auth_chains = g_slist_append (priv->auth_chains, chain); - nm_auth_chain_set_data (chain, "prop", g_strdup (glib_propname), g_free); - nm_auth_chain_set_data (chain, "permission", g_strdup (permission), g_free); - nm_auth_chain_set_data (chain, "enabled", GUINT_TO_POINTER (set_enabled), NULL); - nm_auth_chain_set_data (chain, "message", dbus_message_ref (message), (GDestroyNotify) dbus_message_unref); - nm_auth_chain_set_data (chain, "connection", dbus_connection_ref (connection), (GDestroyNotify) dbus_connection_unref); - nm_auth_chain_set_data (chain, "object", g_object_ref (obj), (GDestroyNotify) g_object_unref); - nm_auth_chain_add_call (chain, permission, TRUE); - } else { - /* Yay for root */ - g_object_set (self, glib_propname, set_enabled, NULL); - reply = dbus_message_new_method_return (message); - } + /* Otherwise validate the user request */ + chain = nm_auth_chain_new_raw_message (message, caller_uid, prop_set_auth_done_cb, self); + g_assert (chain); + priv->auth_chains = g_slist_append (priv->auth_chains, chain); + nm_auth_chain_set_data (chain, "prop", g_strdup (glib_propname), g_free); + nm_auth_chain_set_data (chain, "permission", g_strdup (permission), g_free); + nm_auth_chain_set_data (chain, "enabled", GUINT_TO_POINTER (set_enabled), NULL); + nm_auth_chain_set_data (chain, "message", dbus_message_ref (message), (GDestroyNotify) dbus_message_unref); + nm_auth_chain_set_data (chain, "connection", dbus_connection_ref (connection), (GDestroyNotify) dbus_connection_unref); + nm_auth_chain_set_data (chain, "object", g_object_ref (obj), (GDestroyNotify) g_object_unref); + nm_auth_chain_add_call (chain, permission, TRUE); out: if (reply) { diff --git a/src/settings/nm-agent-manager.c b/src/settings/nm-agent-manager.c index 545cc1d0e..36086a75d 100644 --- a/src/settings/nm-agent-manager.c +++ b/src/settings/nm-agent-manager.c @@ -212,6 +212,7 @@ agent_register_permissions_done (NMAuthChain *chain, g_error_free (local); } else { agent = nm_auth_chain_steal_data (chain, "agent"); + g_assert (agent); result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED); if (result == NM_AUTH_CALL_RESULT_YES) @@ -297,13 +298,13 @@ impl_agent_manager_register (NMAgentManager *self, nm_secret_agent_get_description (agent)); /* Kick off permissions requests for this agent */ - chain = nm_auth_chain_new (context, NULL, agent_register_permissions_done, self); + chain = nm_auth_chain_new (context, NULL, sender_uid, agent_register_permissions_done, self); + g_assert (chain); + priv->chains = g_slist_append (priv->chains, chain); nm_auth_chain_set_data (chain, "agent", agent, g_object_unref); nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, FALSE); nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN, FALSE); - priv->chains = g_slist_append (priv->chains, chain); - done: if (error) dbus_g_method_return_error (context, error); @@ -816,7 +817,6 @@ get_agent_modify_auth_cb (NMAuthChain *chain, gpointer user_data) { Request *req = user_data; - NMAuthCallResult result; const char *perm; req->chain = NULL; @@ -835,15 +835,15 @@ get_agent_modify_auth_cb (NMAuthChain *chain, */ perm = nm_auth_chain_get_data (chain, "perm"); g_assert (perm); - result = nm_auth_chain_get_result (chain, perm); - if (result == NM_AUTH_CALL_RESULT_YES) + if (nm_auth_chain_get_result (chain, perm) == NM_AUTH_CALL_RESULT_YES) req->current_has_modify = TRUE; - nm_log_dbg (LOGD_AGENTS, "(%p/%s) agent MODIFY check result %d", - req, req->setting_name, result); + nm_log_dbg (LOGD_AGENTS, "(%p/%s) agent MODIFY check result %s", + req, req->setting_name, req->current_has_modify ? "YES" : "NO"); get_agent_request_secrets (req, req->current_has_modify); } + nm_auth_chain_unref (chain); } @@ -912,6 +912,7 @@ get_next_cb (Request *req) req, req->setting_name, agent_dbus_owner); req->chain = nm_auth_chain_new_dbus_sender (agent_dbus_owner, + nm_secret_agent_get_owner_uid (NM_SECRET_AGENT (req->current)), get_agent_modify_auth_cb, req); g_assert (req->chain); @@ -1337,32 +1338,29 @@ agent_permissions_changed_done (NMAuthChain *chain, NMAgentManager *self = NM_AGENT_MANAGER (user_data); NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (self); NMSecretAgent *agent; - NMAuthCallResult result; + gboolean share_protected = FALSE, share_open = FALSE; priv->chains = g_slist_remove (priv->chains, chain); agent = nm_auth_chain_get_data (chain, "agent"); + g_assert (agent); if (error) { nm_log_dbg (LOGD_AGENTS, "(%s) failed to request updated agent permissions", nm_secret_agent_get_description (agent)); - nm_secret_agent_add_permission (agent, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, FALSE); - nm_secret_agent_add_permission (agent, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN, FALSE); } else { nm_log_dbg (LOGD_AGENTS, "(%s) updated agent permissions", nm_secret_agent_get_description (agent)); - result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED); - nm_secret_agent_add_permission (agent, - NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, - (result == NM_AUTH_CALL_RESULT_YES)); - - result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN); - nm_secret_agent_add_permission (agent, - NM_AUTH_PERMISSION_WIFI_SHARE_OPEN, - (result == NM_AUTH_CALL_RESULT_YES)); + if (nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED) == NM_AUTH_CALL_RESULT_YES) + share_protected = TRUE; + if (nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN) == NM_AUTH_CALL_RESULT_YES) + share_open = TRUE; } + nm_secret_agent_add_permission (agent, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, share_protected); + nm_secret_agent_add_permission (agent, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN, share_open); + nm_auth_chain_unref (chain); } @@ -1378,11 +1376,14 @@ authority_changed_cb (gpointer user_data) g_hash_table_iter_init (&iter, priv->agents); while (g_hash_table_iter_next (&iter, NULL, (gpointer) &agent)) { NMAuthChain *chain; - const char *sender; /* Kick off permissions requests for this agent */ - sender = nm_secret_agent_get_dbus_owner (agent); - chain = nm_auth_chain_new_dbus_sender (sender, agent_permissions_changed_done, self); + chain = nm_auth_chain_new_dbus_sender (nm_secret_agent_get_dbus_owner (agent), + nm_secret_agent_get_owner_uid (agent), + agent_permissions_changed_done, + self); + g_assert (chain); + priv->chains = g_slist_append (priv->chains, chain); /* Make sure if the agent quits while the permissions call is in progress * that the object sticks around until our callback. @@ -1390,8 +1391,6 @@ authority_changed_cb (gpointer user_data) nm_auth_chain_set_data (chain, "agent", g_object_ref (agent), g_object_unref); nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, FALSE); nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN, FALSE); - - priv->chains = g_slist_append (priv->chains, chain); } } diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c index 59c85ccc4..1e6d94a7f 100644 --- a/src/settings/nm-settings-connection.c +++ b/src/settings/nm-settings-connection.c @@ -896,23 +896,20 @@ pk_auth_cb (NMAuthChain *chain, priv->pending_auths = g_slist_remove (priv->pending_auths, chain); + perm = nm_auth_chain_get_data (chain, "perm"); + g_assert (perm); + result = nm_auth_chain_get_result (chain, perm); + /* If our NMSettingsConnection is already gone, do nothing */ if (chain_error) { error = g_error_new (NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_GENERAL, "Error checking authorization: %s", chain_error->message ? chain_error->message : "(unknown)"); - } else { - perm = nm_auth_chain_get_data (chain, "perm"); - g_assert (perm); - result = nm_auth_chain_get_result (chain, perm); - - /* Caller didn't successfully authenticate */ - if (result != NM_AUTH_CALL_RESULT_YES) { - error = g_error_new_literal (NM_SETTINGS_ERROR, - NM_SETTINGS_ERROR_NOT_PRIVILEGED, - "Insufficient privileges."); - } + } else if (result != NM_AUTH_CALL_RESULT_YES) { + error = g_error_new_literal (NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_PERMISSION_DENIED, + "Insufficient privileges."); } callback = nm_auth_chain_get_data (chain, "callback"); @@ -990,15 +987,16 @@ auth_start (NMSettingsConnection *self, } if (check_permission) { - chain = nm_auth_chain_new (context, NULL, pk_auth_cb, self); + chain = nm_auth_chain_new (context, NULL, sender_uid, pk_auth_cb, self); g_assert (chain); + priv->pending_auths = g_slist_append (priv->pending_auths, chain); + nm_auth_chain_set_data (chain, "perm", (gpointer) check_permission, NULL); nm_auth_chain_set_data (chain, "callback", callback, NULL); nm_auth_chain_set_data (chain, "callback-data", callback_data, NULL); nm_auth_chain_set_data_ulong (chain, "sender-uid", sender_uid); nm_auth_chain_add_call (chain, check_permission, TRUE); - priv->pending_auths = g_slist_append (priv->pending_auths, chain); } else { /* Don't need polkit auth, automatic success */ callback (self, context, sender_uid, NULL, callback_data); diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index a8ae43455..482eadd24 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -997,39 +997,34 @@ pk_add_cb (NMAuthChain *chain, priv->auths = g_slist_remove (priv->auths, chain); + perm = nm_auth_chain_get_data (chain, "perm"); + g_assert (perm); + result = nm_auth_chain_get_result (chain, perm); + if (chain_error) { error = g_error_new (NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_GENERAL, "Error checking authorization: %s", chain_error->message ? chain_error->message : "(unknown)"); - goto done; - } - - perm = nm_auth_chain_get_data (chain, "perm"); - g_assert (perm); - result = nm_auth_chain_get_result (chain, perm); - - /* Caller didn't successfully authenticate */ - if (result != NM_AUTH_CALL_RESULT_YES) { + } else if (result != NM_AUTH_CALL_RESULT_YES) { error = g_error_new_literal (NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_NOT_PRIVILEGED, "Insufficient privileges."); - goto done; + } else { + /* Authorized */ + connection = nm_auth_chain_get_data (chain, "connection"); + g_assert (connection); + added = add_new_connection (self, connection, &add_error); + if (!added) { + error = g_error_new (NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_ADD_FAILED, + "Saving connection failed: (%d) %s", + add_error ? add_error->code : -1, + (add_error && add_error->message) ? add_error->message : "(unknown)"); + g_clear_error (&add_error); + } } - connection = nm_auth_chain_get_data (chain, "connection"); - g_assert (connection); - added = add_new_connection (self, connection, &add_error); - if (!added) { - error = g_error_new (NM_SETTINGS_ERROR, - NM_SETTINGS_ERROR_ADD_FAILED, - "Saving connection failed: (%d) %s", - add_error ? add_error->code : -1, - (add_error && add_error->message) ? add_error->message : "(unknown)"); - g_error_free (add_error); - } - -done: callback = nm_auth_chain_get_data (chain, "callback"); callback_data = nm_auth_chain_get_data (chain, "callback-data"); caller_uid = nm_auth_chain_get_data_ulong (chain, "caller-uid"); @@ -1180,7 +1175,7 @@ nm_settings_add_connection (NMSettings *self, perm = NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM; /* Otherwise validate the user request */ - chain = nm_auth_chain_new (context, NULL, pk_add_cb, self); + chain = nm_auth_chain_new (context, NULL, caller_uid, pk_add_cb, self); g_assert (chain); priv->auths = g_slist_append (priv->auths, chain); nm_auth_chain_add_call (chain, perm, TRUE); @@ -1219,51 +1214,43 @@ pk_hostname_cb (NMAuthChain *chain, NMSettings *self = NM_SETTINGS (user_data); NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self); NMAuthCallResult result; - gboolean success = FALSE; GError *error = NULL; GSList *iter; const char *hostname; priv->auths = g_slist_remove (priv->auths, chain); + result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME); + /* If our NMSettingsConnection is already gone, do nothing */ if (chain_error) { error = g_error_new (NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_GENERAL, "Error checking authorization: %s", chain_error->message ? chain_error->message : "(unknown)"); - goto done; - } - - result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME); - - /* Caller didn't successfully authenticate */ - if (result != NM_AUTH_CALL_RESULT_YES) { + } else if (result != NM_AUTH_CALL_RESULT_YES) { error = g_error_new_literal (NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_NOT_PRIVILEGED, "Insufficient privileges."); - goto done; - } + } else { + /* Set the hostname in all plugins */ + hostname = nm_auth_chain_get_data (chain, "hostname"); + for (iter = priv->plugins; iter; iter = iter->next) { + NMSystemConfigInterfaceCapabilities caps = NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE; - /* Set the hostname in all plugins */ - hostname = nm_auth_chain_get_data (chain, "hostname"); - for (iter = priv->plugins; iter; iter = iter->next) { - NMSystemConfigInterfaceCapabilities caps = NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE; + /* error will be cleared if any plugin supports saving the hostname */ + error = g_error_new_literal (NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_SAVE_HOSTNAME_FAILED, + "Saving the hostname failed."); - g_object_get (G_OBJECT (iter->data), NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES, &caps, NULL); - if (caps & NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME) { - g_object_set (G_OBJECT (iter->data), NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME, hostname, NULL); - success = TRUE; + g_object_get (G_OBJECT (iter->data), NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES, &caps, NULL); + if (caps & NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME) { + g_object_set (G_OBJECT (iter->data), NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME, hostname, NULL); + g_clear_error (&error); + } } } - if (!success) { - error = g_error_new_literal (NM_SETTINGS_ERROR, - NM_SETTINGS_ERROR_SAVE_HOSTNAME_FAILED, - "Saving the hostname failed."); - } - -done: if (error) dbus_g_method_return_error (context, error); else @@ -1281,23 +1268,29 @@ impl_settings_save_hostname (NMSettings *self, NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self); NMAuthChain *chain; GError *error = NULL; + gulong sender_uid = G_MAXULONG; /* Do any of the plugins support setting the hostname? */ if (!get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME)) { error = g_error_new_literal (NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_SAVE_HOSTNAME_NOT_SUPPORTED, "None of the registered plugins support setting the hostname."); - dbus_g_method_return_error (context, error); - g_error_free (error); - return; + } else if (!nm_dbus_manager_get_caller_info (priv->dbus_mgr, context, NULL, &sender_uid)) { + error = g_error_new_literal (NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_PERMISSION_DENIED, + "Unable to determine request UID."); + } else { + chain = nm_auth_chain_new (context, NULL, sender_uid, pk_hostname_cb, self); + g_assert (chain); + priv->auths = g_slist_append (priv->auths, chain); + nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME, TRUE); + nm_auth_chain_set_data (chain, "hostname", g_strdup (hostname), g_free); } - /* Otherwise validate the user request */ - chain = nm_auth_chain_new (context, NULL, pk_hostname_cb, self); - g_assert (chain); - priv->auths = g_slist_append (priv->auths, chain); - nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME, TRUE); - nm_auth_chain_set_data (chain, "hostname", g_strdup (hostname), g_free); + if (error) { + dbus_g_method_return_error (context, error); + g_error_free (error); + } } static gboolean