settings: check modify 'own' not 'system' for personal connections

When a connection is visible only to one user, check 'own' instead
of 'system', allowing 'own' to be less restrictive since the change
won't affect any other users.
This commit is contained in:
Dan Williams 2011-02-11 17:06:57 -06:00
parent 2e2b4373eb
commit 562dc6e0b6
3 changed files with 103 additions and 55 deletions

View file

@ -35,6 +35,7 @@
#include "nm-polkit-helpers.h"
#include "nm-manager-auth.h"
#include "nm-setting-vpn.h"
#include "nm-setting-connection.h"
G_DEFINE_TYPE (NMAgentManager, nm_agent_manager, G_TYPE_OBJECT)
@ -762,9 +763,9 @@ get_agent_modify_auth_cb (NMAuthChain *chain,
{
Request *req = user_data;
NMAuthCallResult result;
const char *perm;
req->chain = NULL;
nm_auth_chain_unref (chain);
if (error) {
nm_log_dbg (LOGD_AGENTS, "(%p/%s) agent MODIFY check error: (%d) %s",
@ -778,7 +779,9 @@ get_agent_modify_auth_cb (NMAuthChain *chain,
* to it. If it didn't, we still ask it for secrets, but we don't send
* any system secrets.
*/
result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM);
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)
req->current_has_modify = TRUE;
@ -787,12 +790,14 @@ get_agent_modify_auth_cb (NMAuthChain *chain,
get_agent_request_secrets (req, req->current_has_modify);
}
nm_auth_chain_unref (chain);
}
static void
get_next_cb (Request *req)
{
const char *agent_dbus_owner;
NMSettingConnection *s_con;
const char *agent_dbus_owner, *perm;
if (!next_generic (req, "getting"))
return;
@ -813,7 +818,20 @@ get_next_cb (Request *req)
get_agent_modify_auth_cb,
req);
g_assert (req->chain);
nm_auth_chain_add_call (req->chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM, TRUE);
/* If the caller is the only user in the connection's permissions, then
* we use the 'modify.own' permission instead of 'modify.system'. If the
* request affects more than just the caller, require 'modify.system'.
*/
s_con = (NMSettingConnection *) nm_connection_get_setting (req->connection, NM_TYPE_SETTING_CONNECTION);
g_assert (s_con);
if (nm_setting_connection_get_num_permissions (s_con) == 1)
perm = NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN;
else
perm = NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM;
nm_auth_chain_set_data (req->chain, "perm", (gpointer) perm, NULL);
nm_auth_chain_add_call (req->chain, perm, TRUE);
} else {
nm_log_dbg (LOGD_AGENTS, "(%p/%s) requesting user-owned secrets from agent %s",
req, req->setting_name, agent_dbus_owner);

View file

@ -696,12 +696,6 @@ typedef void (*AuthCallback) (NMSettingsConnection *connection,
GError *error,
gpointer data);
typedef struct {
AuthCallback callback;
gpointer callback_data;
gulong sender_uid;
} PkAuthInfo;
static void
pk_auth_cb (NMAuthChain *chain,
GError *chain_error,
@ -712,7 +706,10 @@ pk_auth_cb (NMAuthChain *chain,
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
GError *error = NULL;
NMAuthCallResult result;
PkAuthInfo *info;
const char *perm;
AuthCallback callback;
gpointer callback_data;
gulong sender_uid;
priv->pending_auths = g_slist_remove (priv->pending_auths, chain);
@ -723,7 +720,9 @@ pk_auth_cb (NMAuthChain *chain,
"Error checking authorization: %s",
chain_error->message ? chain_error->message : "(unknown)");
} else {
result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM);
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) {
@ -733,8 +732,10 @@ pk_auth_cb (NMAuthChain *chain,
}
}
info = nm_auth_chain_get_data (chain, "pk-auth-info");
info->callback (self, context, info->sender_uid, error, info->callback_data);
callback = nm_auth_chain_get_data (chain, "callback");
callback_data = nm_auth_chain_get_data (chain, "callback-data");
sender_uid = nm_auth_chain_get_data_ulong (chain, "sender-uid");
callback (self, context, sender_uid, error, callback_data);
g_clear_error (&error);
nm_auth_chain_unref (chain);
@ -750,7 +751,6 @@ auth_start (NMSettingsConnection *self,
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
NMAuthChain *chain;
gulong sender_uid = G_MAXULONG;
PkAuthInfo *info;
GError *error = NULL;
char *error_desc = NULL;
@ -778,16 +778,28 @@ auth_start (NMSettingsConnection *self,
}
if (check_modify) {
NMSettingConnection *s_con;
const char *perm;
/* If the caller is the only user in the connection's permissions, then
* we use the 'modify.own' permission instead of 'modify.system'. If the
* request affects more than just the caller, require 'modify.system'.
*/
s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (self), NM_TYPE_SETTING_CONNECTION);
g_assert (s_con);
if (nm_setting_connection_get_num_permissions (s_con) == 1)
perm = NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN;
else
perm = NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM;
chain = nm_auth_chain_new (priv->authority, context, NULL, pk_auth_cb, self);
g_assert (chain);
nm_auth_chain_set_data (chain, "perm", (gpointer) perm, 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);
info = g_malloc0 (sizeof (*info));
info->callback = callback;
info->callback_data = callback_data;
info->sender_uid = sender_uid;
nm_auth_chain_set_data (chain, "pk-auth-info", info, g_free);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM, TRUE);
nm_auth_chain_add_call (chain, perm, TRUE);
priv->pending_auths = g_slist_append (priv->pending_auths, chain);
} else {
/* Don't need polkit auth, automatic success */

View file

@ -800,10 +800,9 @@ pk_add_cb (NMAuthChain *chain,
GError *error = NULL, *add_error = NULL;
NMConnection *connection;
NMSettingsConnection *added = NULL;
gulong caller_uid = G_MAXULONG;
char *error_desc = NULL;
NMSettingsAddCallback callback;
gpointer callback_data;
const char *perm;
priv->auths = g_slist_remove (priv->auths, chain);
@ -815,7 +814,9 @@ pk_add_cb (NMAuthChain *chain,
goto done;
}
result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM);
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) {
@ -825,35 +826,8 @@ pk_add_cb (NMAuthChain *chain,
goto done;
}
/* If the caller isn't root, make sure the connection can be viewed by
* the user that's adding it.
*/
if (!nm_auth_get_caller_uid (context, priv->dbus_mgr, &caller_uid, &error_desc)) {
error = g_error_new (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_NOT_PRIVILEGED,
"Unable to determine UID of request: %s.",
error_desc ? error_desc : "(unknown)");
g_free (error_desc);
goto done;
}
connection = nm_auth_chain_get_data (chain, "connection");
/* Ensure the caller's username exists in the connection's permissions,
* or that the permissions is empty (ie, visible by everyone).
*/
if (0 != caller_uid) {
if (!nm_auth_uid_in_acl (connection, priv->session_monitor, caller_uid, &error_desc)) {
error = g_error_new_literal (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_NOT_PRIVILEGED,
error_desc);
g_free (error_desc);
goto done;
}
/* Caller is allowed to add this connection */
}
g_assert (connection);
added = add_new_connection (self, connection, &add_error);
if (!added) {
error = g_error_new (NM_SETTINGS_ERROR,
@ -895,8 +869,12 @@ nm_settings_add_connection (NMSettings *self,
gpointer user_data)
{
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
NMSettingConnection *s_con;
NMAuthChain *chain;
GError *error = NULL, *tmp_error = NULL;
gulong caller_uid = G_MAXULONG;
char *error_desc = NULL;
const char *perm;
/* Connection must be valid, of course */
if (!nm_connection_verify (connection, &tmp_error)) {
@ -905,7 +883,6 @@ nm_settings_add_connection (NMSettings *self,
"The connection was invalid: %s",
tmp_error ? tmp_error->message : "(unknown)");
g_error_free (tmp_error);
callback (self, NULL, error, context, user_data);
g_error_free (error);
return;
@ -921,11 +898,52 @@ nm_settings_add_connection (NMSettings *self,
return;
}
/* Get the caller's UID */
if (!nm_auth_get_caller_uid (context, priv->dbus_mgr, &caller_uid, &error_desc)) {
error = g_error_new (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_NOT_PRIVILEGED,
"Unable to determine UID of request: %s.",
error_desc ? error_desc : "(unknown)");
g_free (error_desc);
callback (self, NULL, error, context, user_data);
g_error_free (error);
return;
}
/* Ensure the caller's username exists in the connection's permissions,
* or that the permissions is empty (ie, visible by everyone).
*/
if (0 != caller_uid) {
if (!nm_auth_uid_in_acl (connection, priv->session_monitor, caller_uid, &error_desc)) {
error = g_error_new_literal (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_NOT_PRIVILEGED,
error_desc);
g_free (error_desc);
callback (self, NULL, error, context, user_data);
g_error_free (error);
return;
}
/* Caller is allowed to add this connection */
}
/* If the caller is the only user in the connection's permissions, then
* we use the 'modify.own' permission instead of 'modify.system'. If the
* request affects more than just the caller, require 'modify.system'.
*/
s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
g_assert (s_con);
if (nm_setting_connection_get_num_permissions (s_con) == 1)
perm = NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN;
else
perm = NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM;
/* Otherwise validate the user request */
chain = nm_auth_chain_new (priv->authority, context, NULL, pk_add_cb, self);
g_assert (chain);
priv->auths = g_slist_append (priv->auths, chain);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM, TRUE);
nm_auth_chain_add_call (chain, perm, TRUE);
nm_auth_chain_set_data (chain, "perm", (gpointer) perm, NULL);
nm_auth_chain_set_data (chain, "connection", g_object_ref (connection), g_object_unref);
nm_auth_chain_set_data (chain, "callback", callback, NULL);
nm_auth_chain_set_data (chain, "callback-data", user_data, NULL);