Commit 562dc6e0 authored by Dan Williams's avatar Dan Williams

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.
parent 2e2b4373
......@@ -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);
......
......@@ -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 */
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment