diff --git a/introspection/nm-settings-connection.xml b/introspection/nm-settings-connection.xml index d7e5dbf033..9cfa935db8 100644 --- a/introspection/nm-settings-connection.xml +++ b/introspection/nm-settings-connection.xml @@ -9,10 +9,11 @@ - Update the connection with new settings and properties, replacing - all previous settings and properties. Secrets may be part of the - update request, and will be either stored in persistent storage or - given to a Secret Agent for storage, depending on the request. + Update the connection with new settings and properties (replacing + all previous settings and properties) and save the connection to + disk. Secrets may be part of the update request, and will be either + stored in persistent storage or sent to a Secret Agent for storage, + depending on the flags associated with each secret. @@ -23,6 +24,23 @@ + + + Update the connection with new settings and properties (replacing + all previous settings and properties) but do not immediately save + the connection to disk. Secrets may be part of the update request + and may sent to a Secret Agent for storage, depending on the the + flags associated with each secret. + + + + + + New connection settings, properties, and (optionally) secrets. + + + + Delete the connection. diff --git a/introspection/nm-settings.xml b/introspection/nm-settings.xml index c791466843..794e302b23 100644 --- a/introspection/nm-settings.xml +++ b/introspection/nm-settings.xml @@ -56,6 +56,27 @@ + + + Add new connection but do not save it to disk immediately. This + operation does not start the network connection unless (1) device is + idle and able to connect to the network described by the new connection, + and (2) the connection is allowed to be started automatically. + + + + + + Connection settings and properties. + + + + + Object path of the new connection that was just added. + + + + Save the hostname to persistent configuration. diff --git a/src/nm-manager.c b/src/nm-manager.c index 170abdae64..21a20945c0 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -3089,6 +3089,7 @@ add_and_activate_auth_done (PendingActivation *pending, GError *error) /* Basic sender auth checks performed; try to add the connection */ nm_settings_add_connection (priv->settings, pending->connection, + TRUE, pending->context, activation_add_done, pending); diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c index 093bc38fa1..747a66c531 100644 --- a/src/settings/nm-settings-connection.c +++ b/src/settings/nm-settings-connection.c @@ -52,6 +52,10 @@ static void impl_settings_connection_update (NMSettingsConnection *connection, GHashTable *new_settings, DBusGMethodInvocation *context); +static void impl_settings_connection_update_unsaved (NMSettingsConnection *connection, + GHashTable *new_settings, + DBusGMethodInvocation *context); + static void impl_settings_connection_delete (NMSettingsConnection *connection, DBusGMethodInvocation *context); @@ -1159,8 +1163,26 @@ typedef struct { DBusGMethodInvocation *context; NMAgentManager *agent_mgr; gulong sender_uid; + NMConnection *new_settings; + gboolean save_to_disk; } UpdateInfo; +static void +update_complete (NMSettingsConnection *self, + UpdateInfo *info, + GError *error) +{ + if (error) + dbus_g_method_return_error (info->context, error); + else + dbus_g_method_return (info->context); + + g_clear_object (&info->agent_mgr); + g_clear_object (&info->new_settings); + memset (info, 0, sizeof (*info)); + g_free (info); +} + static void con_update_cb (NMSettingsConnection *self, GError *error, @@ -1169,9 +1191,7 @@ con_update_cb (NMSettingsConnection *self, UpdateInfo *info = user_data; NMConnection *for_agent; - if (error) - dbus_g_method_return_error (info->context, error); - else { + if (!error) { /* Dupe the connection so we can clear out non-agent-owned secrets, * as agent-owned secrets are the only ones we send back be saved. * Only send secrets to agents of the same UID that called update too. @@ -1186,9 +1206,7 @@ con_update_cb (NMSettingsConnection *self, dbus_g_method_return (info->context); } - g_object_unref (info->agent_mgr); - memset (info, 0, sizeof (*info)); - g_free (info); + update_complete (self, info, error); } static void @@ -1198,32 +1216,36 @@ update_auth_cb (NMSettingsConnection *self, GError *error, gpointer data) { - NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); - NMConnection *new_settings = data; - UpdateInfo *info; + UpdateInfo *info = data; + GError *local = NULL; - if (error) - dbus_g_method_return_error (context, error); - else { - info = g_malloc0 (sizeof (*info)); - info->context = context; - info->agent_mgr = g_object_ref (priv->agent_mgr); - info->sender_uid = sender_uid; - - /* Cache the new secrets from the agent, as stuff like inotify-triggered - * changes to connection's backing config files will blow them away if - * they're in the main connection. - */ - update_agent_secrets_cache (self, new_settings); - - /* Update and commit our settings. */ - nm_settings_connection_replace_and_commit (self, - new_settings, - con_update_cb, - info); + if (error) { + update_complete (self, info, error); + return; } - g_object_unref (new_settings); + info->sender_uid = sender_uid; + + /* Cache the new secrets from the agent, as stuff like inotify-triggered + * changes to connection's backing config files will blow them away if + * they're in the main connection. + */ + update_agent_secrets_cache (self, info->new_settings); + + if (info->save_to_disk) { + nm_settings_connection_replace_and_commit (self, + info->new_settings, + con_update_cb, + info); + } else { + /* Do nothing if there's nothing to update */ + if (!nm_connection_compare (NM_CONNECTION (self), info->new_settings, NM_SETTING_COMPARE_FLAG_EXACT)) { + if (!nm_settings_connection_replace_settings (self, info->new_settings, TRUE, &local)) + g_assert (local); + } + con_update_cb (self, local, info); + g_clear_error (&local); + } } static const char * @@ -1253,13 +1275,15 @@ get_modify_permission_update (NMConnection *old, NMConnection *new) } static void -impl_settings_connection_update (NMSettingsConnection *self, - GHashTable *new_settings, - DBusGMethodInvocation *context) +impl_settings_connection_update_helper (NMSettingsConnection *self, + GHashTable *new_settings, + DBusGMethodInvocation *context, + gboolean save_to_disk) { NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); NMConnection *tmp; GError *error = NULL; + UpdateInfo *info; /* If the connection is read-only, that has to be changed at the source of * the problem (ex a system settings plugin that can't write connections out) @@ -1295,11 +1319,34 @@ impl_settings_connection_update (NMSettingsConnection *self, return; } + info = g_malloc0 (sizeof (*info)); + info->context = context; + info->agent_mgr = g_object_ref (priv->agent_mgr); + info->sender_uid = G_MAXULONG; + info->save_to_disk = save_to_disk; + info->new_settings = tmp; + auth_start (self, context, - get_modify_permission_update (NM_CONNECTION (self), tmp), + get_modify_permission_update (NM_CONNECTION (self), info->new_settings), update_auth_cb, - tmp); + info); +} + +static void +impl_settings_connection_update (NMSettingsConnection *self, + GHashTable *new_settings, + DBusGMethodInvocation *context) +{ + impl_settings_connection_update_helper (self, new_settings, context, TRUE); +} + +static void +impl_settings_connection_update_unsaved (NMSettingsConnection *self, + GHashTable *new_settings, + DBusGMethodInvocation *context) +{ + impl_settings_connection_update_helper (self, new_settings, context, FALSE); } static void diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index 9eeee9ead0..9e82003f90 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -100,6 +100,10 @@ static void impl_settings_add_connection (NMSettings *self, GHashTable *settings, DBusGMethodInvocation *context); +static void impl_settings_add_connection_unsaved (NMSettings *self, + GHashTable *settings, + DBusGMethodInvocation *context); + static void impl_settings_save_hostname (NMSettings *self, const char *hostname, DBusGMethodInvocation *context); @@ -894,6 +898,7 @@ remove_default_wired_connection (NMSettings *self, static NMSettingsConnection * add_new_connection (NMSettings *self, NMConnection *connection, + gboolean save_to_disk, GError **error) { NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self); @@ -927,14 +932,20 @@ add_new_connection (NMSettings *self, NMSystemConfigInterface *plugin = NM_SYSTEM_CONFIG_INTERFACE (iter->data); GError *add_error = NULL; - g_clear_error (error); - added = nm_system_config_interface_add_connection (plugin, connection, &add_error); + added = nm_system_config_interface_add_connection (plugin, connection, save_to_disk, &add_error); if (added) { claim_connection (self, added, TRUE); return added; } - g_propagate_error (error, add_error); + nm_log_dbg (LOGD_SETTINGS, "Failed to add %s/'%s': %s", + nm_connection_get_uuid (connection), + nm_connection_get_id (connection), + add_error ? add_error->message : "(unknown)"); + g_clear_error (&add_error); } + + g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_ADD_FAILED, + "No plugin supported adding this connection"); return NULL; } @@ -986,13 +997,14 @@ pk_add_cb (NMAuthChain *chain, NMSettings *self = NM_SETTINGS (user_data); NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self); NMAuthCallResult result; - GError *error = NULL, *add_error = NULL; + GError *error = NULL; NMConnection *connection; NMSettingsConnection *added = NULL; NMSettingsAddCallback callback; gpointer callback_data; gulong caller_uid; const char *perm; + gboolean save_to_disk; priv->auths = g_slist_remove (priv->auths, chain); @@ -1013,15 +1025,8 @@ pk_add_cb (NMAuthChain *chain, /* 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); - } + save_to_disk = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "save-to-disk")); + added = add_new_connection (self, connection, save_to_disk, &error); } callback = nm_auth_chain_get_data (chain, "callback"); @@ -1038,19 +1043,6 @@ pk_add_cb (NMAuthChain *chain, nm_auth_chain_unref (chain); } -static void -add_cb (NMSettings *self, - NMSettingsConnection *connection, - GError *error, - DBusGMethodInvocation *context, - gpointer user_data) -{ - if (error) - dbus_g_method_return_error (context, error); - else - dbus_g_method_return (context, nm_connection_get_path (NM_CONNECTION (connection))); -} - /* FIXME: remove if/when kernel supports adhoc wpa */ static gboolean is_adhoc_wpa (NMConnection *connection) @@ -1086,6 +1078,7 @@ is_adhoc_wpa (NMConnection *connection) void nm_settings_add_connection (NMSettings *self, NMConnection *connection, + gboolean save_to_disk, DBusGMethodInvocation *context, NMSettingsAddCallback callback, gpointer user_data) @@ -1178,6 +1171,7 @@ nm_settings_add_connection (NMSettings *self, nm_auth_chain_set_data (chain, "callback", callback, NULL); nm_auth_chain_set_data (chain, "callback-data", user_data, NULL); nm_auth_chain_set_data_ulong (chain, "caller-uid", caller_uid); + nm_auth_chain_set_data (chain, "save-to-disk", GUINT_TO_POINTER (save_to_disk), NULL); } else { error = g_error_new_literal (NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_PERMISSION_DENIED, @@ -1188,16 +1182,35 @@ nm_settings_add_connection (NMSettings *self, } static void -impl_settings_add_connection (NMSettings *self, - GHashTable *settings, - DBusGMethodInvocation *context) +impl_settings_add_connection_add_cb (NMSettings *self, + NMSettingsConnection *connection, + GError *error, + DBusGMethodInvocation *context, + gpointer user_data) +{ + if (error) + dbus_g_method_return_error (context, error); + else + dbus_g_method_return (context, nm_connection_get_path (NM_CONNECTION (connection))); +} + +static void +impl_settings_add_connection_helper (NMSettings *self, + GHashTable *settings, + gboolean save_to_disk, + DBusGMethodInvocation *context) { NMConnection *connection; GError *error = NULL; connection = nm_connection_new_from_hash (settings, &error); if (connection) { - nm_settings_add_connection (self, connection, context, add_cb, NULL); + nm_settings_add_connection (self, + connection, + save_to_disk, + context, + impl_settings_add_connection_add_cb, + NULL); g_object_unref (connection); } else { g_assert (error); @@ -1206,6 +1219,22 @@ impl_settings_add_connection (NMSettings *self, } } +static void +impl_settings_add_connection (NMSettings *self, + GHashTable *settings, + DBusGMethodInvocation *context) +{ + impl_settings_add_connection_helper (self, settings, TRUE, context); +} + +static void +impl_settings_add_connection_unsaved (NMSettings *self, + GHashTable *settings, + DBusGMethodInvocation *context) +{ + impl_settings_add_connection_helper (self, settings, FALSE, context); +} + static void pk_hostname_cb (NMAuthChain *chain, GError *chain_error, @@ -1406,7 +1435,7 @@ default_wired_try_update (NMDefaultWiredConnection *wired, g_assert (id); remove_default_wired_connection (self, NM_SETTINGS_CONNECTION (wired), FALSE); - added = add_new_connection (self, NM_CONNECTION (wired), &error); + added = add_new_connection (self, NM_CONNECTION (wired), TRUE, &error); if (added) { nm_settings_connection_delete (NM_SETTINGS_CONNECTION (wired), delete_cb, NULL); diff --git a/src/settings/nm-settings.h b/src/settings/nm-settings.h index 66dbcac094..351c2931e1 100644 --- a/src/settings/nm-settings.h +++ b/src/settings/nm-settings.h @@ -94,6 +94,7 @@ typedef void (*NMSettingsAddCallback) (NMSettings *settings, void nm_settings_add_connection (NMSettings *self, NMConnection *connection, + gboolean save_to_disk, DBusGMethodInvocation *context, NMSettingsAddCallback callback, gpointer user_data); diff --git a/src/settings/nm-system-config-interface.c b/src/settings/nm-system-config-interface.c index 45aa6305da..1a9d5d58ed 100644 --- a/src/settings/nm-system-config-interface.c +++ b/src/settings/nm-system-config-interface.c @@ -150,13 +150,14 @@ nm_system_config_interface_get_unmanaged_specs (NMSystemConfigInterface *config) NMSettingsConnection * nm_system_config_interface_add_connection (NMSystemConfigInterface *config, NMConnection *connection, + gboolean save_to_disk, GError **error) { g_return_val_if_fail (config != NULL, NULL); g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); if (NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->add_connection) - return NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->add_connection (config, connection, error); + return NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->add_connection (config, connection, save_to_disk, error); return NULL; } diff --git a/src/settings/nm-system-config-interface.h b/src/settings/nm-system-config-interface.h index 96a640619e..9648fdb5d9 100644 --- a/src/settings/nm-system-config-interface.h +++ b/src/settings/nm-system-config-interface.h @@ -110,12 +110,14 @@ struct _NMSystemConfigInterface { GSList * (*get_unmanaged_specs) (NMSystemConfigInterface *config); /* - * Save the given connection to backing storage, and return a new + * Initialize the plugin-specific connection and return a new * NMSettingsConnection subclass that contains the same settings as the - * original connection. + * original connection. The connection should only be saved to backing + * storage if @save_to_disk is TRUE. */ NMSettingsConnection * (*add_connection) (NMSystemConfigInterface *config, NMConnection *connection, + gboolean save_to_disk, GError **error); /* Signals */ @@ -139,6 +141,7 @@ GSList *nm_system_config_interface_get_unmanaged_specs (NMSystemConfigInterface NMSettingsConnection *nm_system_config_interface_add_connection (NMSystemConfigInterface *config, NMConnection *connection, + gboolean save_to_disk, GError **error); G_END_DECLS diff --git a/src/settings/plugins/example/plugin.c b/src/settings/plugins/example/plugin.c index 3a1ea96baa..8d4b627705 100644 --- a/src/settings/plugins/example/plugin.c +++ b/src/settings/plugins/example/plugin.c @@ -503,6 +503,7 @@ get_connections (NMSystemConfigInterface *config) static NMSettingsConnection * add_connection (NMSystemConfigInterface *config, NMConnection *connection, + gboolean save_to_disk, GError **error) { SCPluginExample *self = SC_PLUGIN_EXAMPLE (config); @@ -513,10 +514,11 @@ add_connection (NMSystemConfigInterface *config, * way we don't trigger the new NMSettingsConnection subclass' file watch * functions needlessly. */ - if (write_connection (connection, NULL, &path, error)) { - added = _internal_new_connection (self, path, connection, error); - g_free (path); - } + if (save_to_disk && !write_connection (connection, NULL, &path, error)) + return NULL; + + added = _internal_new_connection (self, path, connection, error); + g_free (path); return added; } diff --git a/src/settings/plugins/ifcfg-rh/plugin.c b/src/settings/plugins/ifcfg-rh/plugin.c index d6b3c447c0..13edfb17ea 100644 --- a/src/settings/plugins/ifcfg-rh/plugin.c +++ b/src/settings/plugins/ifcfg-rh/plugin.c @@ -452,17 +452,26 @@ get_unmanaged_specs (NMSystemConfigInterface *config) static NMSettingsConnection * add_connection (NMSystemConfigInterface *config, NMConnection *connection, + gboolean save_to_disk, GError **error) { SCPluginIfcfg *self = SC_PLUGIN_IFCFG (config); NMIfcfgConnection *added = NULL; char *path = NULL; - /* Write it out first, then add the connection to our internal list */ - if (writer_new_connection (connection, IFCFG_DIR, &path, error)) { - added = _internal_new_connection (self, path, connection, error); - g_free (path); + /* Ensure we reject attempts to add the connection long before we're + * asked to write it to disk. + */ + if (!writer_can_write_connection (connection, error)) + return NULL; + + if (save_to_disk) { + if (!writer_new_connection (connection, IFCFG_DIR, &path, error)) + return NULL; } + + added = _internal_new_connection (self, path, connection, error); + g_free (path); return (NMSettingsConnection *) added; } diff --git a/src/settings/plugins/ifcfg-rh/writer.c b/src/settings/plugins/ifcfg-rh/writer.c index e393a6da9c..022af1a14b 100644 --- a/src/settings/plugins/ifcfg-rh/writer.c +++ b/src/settings/plugins/ifcfg-rh/writer.c @@ -2105,12 +2105,11 @@ write_connection (NMConnection *connection, gboolean no_8021x = FALSE; gboolean wired = FALSE; - s_con = nm_connection_get_setting_connection (connection); - if (!s_con) { - g_set_error (error, IFCFG_PLUGIN_ERROR, 0, - "Missing '%s' setting", NM_SETTING_CONNECTION_SETTING_NAME); + if (!writer_can_write_connection (connection, error)) return FALSE; - } + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); if (filename) { /* For existing connections, 'filename' should be full path to ifcfg file */ @@ -2235,6 +2234,30 @@ out: return success; } +gboolean +writer_can_write_connection (NMConnection *connection, GError **error) +{ + NMSettingConnection *s_con; + + if ( ( nm_connection_is_type (connection, NM_SETTING_WIRED_SETTING_NAME) + && !nm_connection_get_setting_pppoe (connection)) + || nm_connection_is_type (connection, NM_SETTING_VLAN_SETTING_NAME) + || nm_connection_is_type (connection, NM_SETTING_WIRELESS_SETTING_NAME) + || nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME) + || nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME) + || nm_connection_is_type (connection, NM_SETTING_BRIDGE_SETTING_NAME)) + return TRUE; + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + g_set_error (error, IFCFG_PLUGIN_ERROR, 0, + "The ifcfg-rh plugin cannot write the connection '%s' (type '%s' pppoe %d)", + nm_connection_get_id (connection), + nm_setting_connection_get_connection_type (s_con), + !!nm_connection_get_setting_pppoe (connection)); + return FALSE; +} + gboolean writer_new_connection (NMConnection *connection, const char *ifcfg_dir, diff --git a/src/settings/plugins/ifcfg-rh/writer.h b/src/settings/plugins/ifcfg-rh/writer.h index edeac0cccc..894313dd06 100644 --- a/src/settings/plugins/ifcfg-rh/writer.h +++ b/src/settings/plugins/ifcfg-rh/writer.h @@ -25,6 +25,9 @@ #include #include +gboolean writer_can_write_connection (NMConnection *connection, + GError **error); + gboolean writer_new_connection (NMConnection *connection, const char *ifcfg_dir, char **out_filename, diff --git a/src/settings/plugins/ifnet/Makefile.am b/src/settings/plugins/ifnet/Makefile.am index 234d4adbbb..ed387e583a 100644 --- a/src/settings/plugins/ifnet/Makefile.am +++ b/src/settings/plugins/ifnet/Makefile.am @@ -45,7 +45,9 @@ lib_ifnet_io_la_SOURCES = \ net_utils.h\ net_utils.c\ wpa_parser.h\ - wpa_parser.c + wpa_parser.c \ + errors.h \ + errors.c lib_ifnet_io_la_CPPFLAGS = \ $(GLIB_CFLAGS) \ diff --git a/src/settings/plugins/ifnet/connection_parser.c b/src/settings/plugins/ifnet/connection_parser.c index 5ccf5b3495..8aed34437b 100644 --- a/src/settings/plugins/ifnet/connection_parser.c +++ b/src/settings/plugins/ifnet/connection_parser.c @@ -43,6 +43,7 @@ #include "wpa_parser.h" #include "connection_parser.h" #include "nm-ifnet-connection.h" +#include "errors.h" static char * connection_id_from_ifnet_name (const char *conn_name) @@ -2806,16 +2807,11 @@ ifnet_update_parsers_by_connection (NMConnection *connection, gboolean wired = FALSE, pppoe = TRUE; const char *new_name = NULL; - s_con = - NM_SETTING_CONNECTION (nm_connection_get_setting - (connection, NM_TYPE_SETTING_CONNECTION)); - if (!s_con) { - g_set_error (error, ifnet_plugin_error_quark (), 0, - "Missing '%s' setting", - NM_SETTING_CONNECTION_SETTING_NAME); + if (!ifnet_can_write_connection (connection, error)) return FALSE; - } + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); type = nm_setting_connection_get_connection_type (s_con); if (!type) { @@ -2910,6 +2906,66 @@ ifnet_delete_connection_in_parsers (const char *conn_name, return result; } +static void +check_unsupported_secrets (NMSetting *setting, + const char *key, + const GValue *value, + GParamFlags flags, + gpointer user_data) +{ + gboolean *unsupported_secret = user_data; + + if (flags & NM_SETTING_PARAM_SECRET) { + NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; + + nm_setting_get_secret_flags (setting, key, &secret_flags, NULL); + if (secret_flags != NM_SETTING_SECRET_FLAG_NONE) + *unsupported_secret = TRUE; + } +} + +gboolean +ifnet_can_write_connection (NMConnection *connection, GError **error) +{ + NMSettingConnection *s_con; + gboolean has_unsupported_secrets = FALSE; + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + + /* If the connection is not available for all users, ignore + * it as this plugin only deals with System Connections */ + if (nm_setting_connection_get_num_permissions (s_con)) { + g_set_error_literal (error, IFNET_PLUGIN_ERROR, 0, + "The ifnet plugin does not support non-system-wide connections."); + return FALSE; + } + + /* If the connection has flagged secrets, ignore + * it as this plugin does not deal with user agent service */ + nm_connection_for_each_setting_value (connection, + check_unsupported_secrets, + &has_unsupported_secrets); + if (has_unsupported_secrets) { + g_set_error_literal (error, IFNET_PLUGIN_ERROR, 0, + "The ifnet plugin only supports persistent system secrets."); + return FALSE; + } + + /* Only support wired, wifi, and PPPoE */ + if ( !nm_connection_is_type (connection, NM_SETTING_WIRED_SETTING_NAME) + && !nm_connection_is_type (connection, NM_SETTING_WIRELESS_SETTING_NAME) + && !nm_connection_is_type (connection, NM_SETTING_PPPOE_SETTING_NAME)) { + g_set_error (error, IFNET_PLUGIN_ERROR, 0, + "The ifnet plugin cannot write the connection '%s' (type '%s')", + nm_connection_get_id (connection), + nm_setting_connection_get_connection_type (s_con)); + return FALSE; + } + + return TRUE; +} + /* get the available wired name(eth*). */ static gchar * get_wired_name () @@ -3003,6 +3059,9 @@ ifnet_add_new_connection (NMConnection *connection, const char *type; gchar *new_type, *new_name = NULL; + if (!ifnet_can_write_connection (connection, error)) + return FALSE; + s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); type = nm_setting_connection_get_connection_type (s_con); @@ -3053,3 +3112,4 @@ out: *out_new_name = new_name; return success; } + diff --git a/src/settings/plugins/ifnet/connection_parser.h b/src/settings/plugins/ifnet/connection_parser.h index 54046b05a3..74213669de 100644 --- a/src/settings/plugins/ifnet/connection_parser.h +++ b/src/settings/plugins/ifnet/connection_parser.h @@ -24,6 +24,8 @@ #include #include "net_parser.h" +gboolean ifnet_can_write_connection (NMConnection *connection, GError **error); + NMConnection *ifnet_update_connection_from_config_block (const char *conn_name, const char *basepath, GError **error); diff --git a/src/settings/plugins/ifnet/errors.c b/src/settings/plugins/ifnet/errors.c new file mode 100644 index 0000000000..295db18bae --- /dev/null +++ b/src/settings/plugins/ifnet/errors.c @@ -0,0 +1,35 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager system settings service + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * (C) Copyright 2013 Red Hat, Inc. + */ + +#include +#include "errors.h" + +GQuark +ifnet_plugin_error_quark (void) +{ + static GQuark error_quark = 0; + + if (G_UNLIKELY (error_quark == 0)) + error_quark = g_quark_from_static_string ("ifnet-plugin-error-quark"); + + return error_quark; +} + + diff --git a/src/settings/plugins/ifnet/errors.h b/src/settings/plugins/ifnet/errors.h new file mode 100644 index 0000000000..52517d007e --- /dev/null +++ b/src/settings/plugins/ifnet/errors.h @@ -0,0 +1,30 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager system settings service + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * (C) Copyright 2013 Red Hat, Inc. + */ + +#ifndef __ERRORS_H__ +#define __ERRORS_H__ + +#include + +#define IFNET_PLUGIN_ERROR (ifnet_plugin_error_quark ()) +GQuark ifnet_plugin_error_quark (void); + +#endif /* __ERRORS_H__ */ + diff --git a/src/settings/plugins/ifnet/net_utils.c b/src/settings/plugins/ifnet/net_utils.c index ae2307f913..672e686bb8 100644 --- a/src/settings/plugins/ifnet/net_utils.c +++ b/src/settings/plugins/ifnet/net_utils.c @@ -95,17 +95,6 @@ is_true (const char *str) return FALSE; } -GQuark -ifnet_plugin_error_quark (void) -{ - static GQuark error_quark = 0; - - if (G_UNLIKELY (error_quark == 0)) - error_quark = - g_quark_from_static_string ("ifnet-plugin-error-quark"); - return error_quark; -} - static char * find_default_gateway_str (char *str) { diff --git a/src/settings/plugins/ifnet/net_utils.h b/src/settings/plugins/ifnet/net_utils.h index 71430c838f..cee71d57e5 100644 --- a/src/settings/plugins/ifnet/net_utils.h +++ b/src/settings/plugins/ifnet/net_utils.h @@ -67,8 +67,6 @@ void set_ip6_dns_servers (NMSettingIP6Config * s_ip6, const char *conn_name); gchar *strip_string (gchar *str, gchar t); gboolean is_managed (const char *conn_name); -GQuark ifnet_plugin_error_quark (void); - gboolean is_hex (const char *value); gboolean is_ascii (const char *value); gboolean is_true (const char *str); diff --git a/src/settings/plugins/ifnet/plugin.c b/src/settings/plugins/ifnet/plugin.c index 486f893514..8b056a6701 100644 --- a/src/settings/plugins/ifnet/plugin.c +++ b/src/settings/plugins/ifnet/plugin.c @@ -335,54 +335,36 @@ reload_connections (gpointer config) g_list_free (conn_names); } -static void -check_flagged_secrets (NMSetting *setting, - const char *key, - const GValue *value, - GParamFlags flags, - gpointer user_data) -{ - gboolean *is_system_secret = user_data; - - if (flags & NM_SETTING_PARAM_SECRET) { - NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; - - nm_setting_get_secret_flags (setting, key, &secret_flags, NULL); - - if (secret_flags != NM_SETTING_SECRET_FLAG_NONE) { - *is_system_secret = TRUE; - } - } -} - static NMSettingsConnection * add_connection (NMSystemConfigInterface *config, NMConnection *source, + gboolean save_to_disk, GError **error) { SCPluginIfnetPrivate *priv = SC_PLUGIN_IFNET_GET_PRIVATE (config); - gboolean has_flagged_secrets = FALSE; - NMSettingConnection *s_con; + NMIfnetConnection *new = NULL; - s_con = nm_connection_get_setting_connection (source); - g_assert (s_con); - - /* If the connection is not available for all users, ignore - * it as this plugin only deals with System Connections */ - if (nm_setting_connection_get_num_permissions (s_con)) + /* Ensure we reject attempts to add the connection long before we're + * asked to write it to disk. + */ + if (!ifnet_can_write_connection (source, error)) return NULL; - /* If the connection has flagged secrets, ignore - * it as this plugin does not deal with user agent service */ - nm_connection_for_each_setting_value (source, check_flagged_secrets, &has_flagged_secrets); - if (has_flagged_secrets) - return NULL; + if (save_to_disk) { + if (!ifnet_add_new_connection (source, CONF_NET_FILE, WPA_SUPPLICANT_CONF, NULL, NULL, error)) + return NULL; + reload_connections (config); + new = g_hash_table_lookup (priv->connections, nm_connection_get_uuid (source)); + } else { + new = nm_ifnet_connection_new (source, NULL); + if (new) { + g_hash_table_insert (priv->connections, + (gpointer) nm_connection_get_uuid (NM_CONNECTION (new)), + new); + } + } - if (!ifnet_add_new_connection (source, CONF_NET_FILE, WPA_SUPPLICANT_CONF, NULL, NULL, error)) - return NULL; - - reload_connections (config); - return g_hash_table_lookup (priv->connections, nm_connection_get_uuid (source)); + return (NMSettingsConnection *) new; } static void diff --git a/src/settings/plugins/ifnet/tests/Makefile.am b/src/settings/plugins/ifnet/tests/Makefile.am index 2c39ed6337..f3dc6cbe27 100644 --- a/src/settings/plugins/ifnet/tests/Makefile.am +++ b/src/settings/plugins/ifnet/tests/Makefile.am @@ -18,7 +18,8 @@ check_ifnet_SOURCES = \ ../connection_parser.c \ ../net_parser.c \ ../net_utils.c \ - ../wpa_parser.c + ../wpa_parser.c \ + ../errors.c check_ifnet_CPPFLAGS = \ $(CHECK_CFLAGS) \ diff --git a/src/settings/plugins/keyfile/plugin.c b/src/settings/plugins/keyfile/plugin.c index 5980809d3a..b216eda246 100644 --- a/src/settings/plugins/keyfile/plugin.c +++ b/src/settings/plugins/keyfile/plugin.c @@ -78,8 +78,6 @@ _internal_new_connection (SCPluginKeyfile *self, SCPluginKeyfilePrivate *priv = SC_PLUGIN_KEYFILE_GET_PRIVATE (self); NMKeyfileConnection *connection; - g_return_val_if_fail (full_path != NULL, NULL); - connection = nm_keyfile_connection_new (source, full_path, error); if (connection) { g_hash_table_insert (priv->connections, @@ -347,17 +345,20 @@ get_connections (NMSystemConfigInterface *config) static NMSettingsConnection * add_connection (NMSystemConfigInterface *config, NMConnection *connection, + gboolean save_to_disk, GError **error) { SCPluginKeyfile *self = SC_PLUGIN_KEYFILE (config); NMSettingsConnection *added = NULL; char *path = NULL; - /* Write it out first, then add the connection to our internal list */ - if (nm_keyfile_plugin_write_connection (connection, NULL, &path, error)) { - added = _internal_new_connection (self, path, connection, error); - g_free (path); + if (save_to_disk) { + if (!nm_keyfile_plugin_write_connection (connection, NULL, &path, error)) + return NULL; } + + added = _internal_new_connection (self, path, connection, error); + g_free (path); return added; }