1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 /* NetworkManager system settings service - keyfile plugin
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Copyright (C) 2008 Novell, Inc.
19 * Copyright (C) 2008 - 2015 Red Hat, Inc.
22 #include "nm-default.h"
24 #include "nm-keyfile-internal.h"
31 #include <arpa/inet.h>
34 #include "nm-core-internal.h"
35 #include "nm-keyfile-utils.h"
38 NMConnection *connection;
41 NMKeyfileWriteHandler handler;
46 /* Some setting properties also contain setting names, such as
47 * NMSettingConnection's 'type' property (which specifies the base type of the
48 * connection, eg ethernet or wifi) or the 802-11-wireless setting's
49 * 'security' property which specifies whether or not the AP requires
50 * encrpytion. This function handles translating those properties' values
51 * from the real setting name to the more-readable alias.
54 setting_alias_writer (KeyfileWriterInfo *info,
59 const char *str, *alias;
61 str = g_value_get_string (value);
62 alias = nm_keyfile_plugin_get_alias_for_setting_name (str);
63 nm_keyfile_plugin_kf_set_string (info->keyfile,
64 nm_setting_get_name (setting),
70 write_array_of_uint (GKeyFile *file,
79 array = (GArray *) g_value_get_boxed (value);
80 if (!array || !array->len)
83 tmp_array = g_new (gint, array->len);
84 for (i = 0; i < array->len; i++)
85 tmp_array[i] = g_array_index (array, int, i);
87 nm_keyfile_plugin_kf_set_integer_list (file, nm_setting_get_name (setting), key, tmp_array, array->len);
92 dns_writer (KeyfileWriterInfo *info,
99 list = g_value_get_boxed (value);
100 if (list && list[0]) {
101 nm_keyfile_plugin_kf_set_string_list (info->keyfile, nm_setting_get_name (setting), key,
102 (const char **) list, g_strv_length (list));
107 ip6_addr_gen_mode_writer (KeyfileWriterInfo *info,
112 NMSettingIP6ConfigAddrGenMode addr_gen_mode;
113 gs_free char *str = NULL;
115 addr_gen_mode = (NMSettingIP6ConfigAddrGenMode) g_value_get_int (value);
116 str = nm_utils_enum_to_str (nm_setting_ip6_config_addr_gen_mode_get_type (),
118 nm_keyfile_plugin_kf_set_string (info->keyfile,
119 nm_setting_get_name (setting),
125 write_ip_values (GKeyFile *file,
126 const char *setting_name,
133 const char *addr, *gw;
134 guint32 plen, metric;
135 char key_name[30], *key_name_idx;
140 family = !strcmp (setting_name, NM_SETTING_IP4_CONFIG_SETTING_NAME) ? AF_INET : AF_INET6;
142 strcpy (key_name, is_route ? "route" : "address");
143 key_name_idx = key_name + strlen (key_name);
145 output = g_string_sized_new (2*INET_ADDRSTRLEN + 10);
146 for (i = 0; i < array->len; i++) {
148 NMIPRoute *route = array->pdata[i];
150 addr = nm_ip_route_get_dest (route);
151 plen = nm_ip_route_get_prefix (route);
152 gw = nm_ip_route_get_next_hop (route);
153 metric = MAX (0, nm_ip_route_get_metric (route));
155 NMIPAddress *address = array->pdata[i];
157 addr = nm_ip_address_get_address (address);
158 plen = nm_ip_address_get_prefix (address);
159 gw = i == 0 ? gateway : NULL;
163 g_string_set_size (output, 0);
164 g_string_append_printf (output, "%s/%u", addr, plen);
166 /* Older versions of the plugin do not support the form
167 * "a.b.c.d/plen,,metric", so, we always have to write the
168 * gateway, even if there isn't one.
169 * The current version supports reading of the above form.
172 if (family == AF_INET)
178 g_string_append_printf (output, ",%s", gw);
180 g_string_append_printf (output, ",%lu", (unsigned long) metric);
183 sprintf (key_name_idx, "%d", i + 1);
184 nm_keyfile_plugin_kf_set_string (file, setting_name, key_name, output->str);
186 g_string_free (output, TRUE);
190 addr_writer (KeyfileWriterInfo *info,
196 const char *setting_name = nm_setting_get_name (setting);
197 const char *gateway = nm_setting_ip_config_get_gateway (NM_SETTING_IP_CONFIG (setting));
199 array = (GPtrArray *) g_value_get_boxed (value);
200 if (array && array->len)
201 write_ip_values (info->keyfile, setting_name, array, gateway, FALSE);
205 ip4_addr_label_writer (KeyfileWriterInfo *info,
214 gateway_writer (KeyfileWriterInfo *info,
223 route_writer (KeyfileWriterInfo *info,
229 const char *setting_name = nm_setting_get_name (setting);
231 array = (GPtrArray *) g_value_get_boxed (value);
232 if (array && array->len)
233 write_ip_values (info->keyfile, setting_name, array, NULL, TRUE);
237 write_hash_of_string (GKeyFile *file,
243 const char *property = NULL, *data = NULL;
244 const char *group_name = nm_setting_get_name (setting);
245 gboolean vpn_secrets = FALSE;
247 /* Write VPN secrets out to a different group to keep them separate */
248 if (NM_IS_SETTING_VPN (setting) && !strcmp (key, NM_SETTING_VPN_SECRETS)) {
249 group_name = NM_KEYFILE_GROUP_VPN_SECRETS;
253 g_hash_table_iter_init (&iter, (GHashTable *) g_value_get_boxed (value));
254 while (g_hash_table_iter_next (&iter, (gpointer *) &property, (gpointer *) &data)) {
255 gboolean write_item = TRUE;
257 /* Handle VPN secrets specially; they are nested in the property's hash;
258 * we don't want to write them if the secret is not saved, not required,
259 * or owned by a user's secret agent.
262 NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
264 nm_setting_get_secret_flags (setting, property, &secret_flags, NULL);
265 if (secret_flags != NM_SETTING_SECRET_FLAG_NONE)
270 nm_keyfile_plugin_kf_set_string (file, group_name, property, data);
275 ssid_writer (KeyfileWriterInfo *info,
281 const guint8 *ssid_data;
283 const char *setting_name = nm_setting_get_name (setting);
284 gboolean new_format = TRUE;
285 unsigned int semicolons = 0;
289 g_return_if_fail (G_VALUE_HOLDS (value, G_TYPE_BYTES));
291 bytes = g_value_get_boxed (value);
294 ssid_data = g_bytes_get_data (bytes, &ssid_len);
298 /* Check whether each byte is printable. If not, we have to use an
299 * integer list, otherwise we can just use a string.
301 for (i = 0; i < ssid_len; i++) {
302 char c = ssid_data[i] & 0xFF;
303 if (!g_ascii_isprint (c)) {
312 ssid = g_malloc0 (ssid_len + semicolons + 1);
314 memcpy (ssid, ssid_data, ssid_len);
316 /* Escape semicolons with backslashes to make strings
317 * containing ';', such as '16;17;' unambiguous */
319 for (i = 0; i < ssid_len; i++) {
320 if (ssid_data[i] == ';')
322 ssid[j++] = ssid_data[i];
325 nm_keyfile_plugin_kf_set_string (info->keyfile, setting_name, key, ssid);
328 tmp_array = g_new (gint, ssid_len);
329 for (i = 0; i < ssid_len; i++)
330 tmp_array[i] = (int) ssid_data[i];
331 nm_keyfile_plugin_kf_set_integer_list (info->keyfile, setting_name, key, tmp_array, ssid_len);
337 password_raw_writer (KeyfileWriterInfo *info,
342 const char *setting_name = nm_setting_get_name (setting);
348 g_return_if_fail (G_VALUE_HOLDS (value, G_TYPE_BYTES));
350 array = (GBytes *) g_value_get_boxed (value);
353 data = g_bytes_get_data (array, &len);
357 tmp_array = g_new (gint, len);
358 for (i = 0; i < len; i++)
359 tmp_array[i] = (int) data[i];
360 nm_keyfile_plugin_kf_set_integer_list (info->keyfile, setting_name, key, tmp_array, len);
364 typedef struct ObjectType {
367 NMSetting8021xCKScheme (*scheme_func) (NMSetting8021x *setting);
368 NMSetting8021xCKFormat (*format_func) (NMSetting8021x *setting);
369 const char * (*path_func) (NMSetting8021x *setting);
370 GBytes * (*blob_func) (NMSetting8021x *setting);
373 static const ObjectType objtypes[10] = {
374 { NM_SETTING_802_1X_CA_CERT,
376 nm_setting_802_1x_get_ca_cert_scheme,
378 nm_setting_802_1x_get_ca_cert_path,
379 nm_setting_802_1x_get_ca_cert_blob },
381 { NM_SETTING_802_1X_PHASE2_CA_CERT,
383 nm_setting_802_1x_get_phase2_ca_cert_scheme,
385 nm_setting_802_1x_get_phase2_ca_cert_path,
386 nm_setting_802_1x_get_phase2_ca_cert_blob },
388 { NM_SETTING_802_1X_CLIENT_CERT,
390 nm_setting_802_1x_get_client_cert_scheme,
392 nm_setting_802_1x_get_client_cert_path,
393 nm_setting_802_1x_get_client_cert_blob },
395 { NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
397 nm_setting_802_1x_get_phase2_client_cert_scheme,
399 nm_setting_802_1x_get_phase2_client_cert_path,
400 nm_setting_802_1x_get_phase2_client_cert_blob },
402 { NM_SETTING_802_1X_PRIVATE_KEY,
404 nm_setting_802_1x_get_private_key_scheme,
405 nm_setting_802_1x_get_private_key_format,
406 nm_setting_802_1x_get_private_key_path,
407 nm_setting_802_1x_get_private_key_blob },
409 { NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
411 nm_setting_802_1x_get_phase2_private_key_scheme,
412 nm_setting_802_1x_get_phase2_private_key_format,
413 nm_setting_802_1x_get_phase2_private_key_path,
414 nm_setting_802_1x_get_phase2_private_key_blob },
419 /**************************************************************************/
422 cert_writer_default (NMConnection *connection,
424 NMKeyfileWriteTypeDataCert *cert_data)
426 const char *setting_name = nm_setting_get_name (NM_SETTING (cert_data->setting));
427 NMSetting8021xCKScheme scheme;
429 scheme = cert_data->scheme_func (cert_data->setting);
430 if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
432 char *path_free = NULL, *tmp;
433 gs_free char *base_dir = NULL;
435 path = cert_data->path_func (cert_data->setting);
438 /* If the path is relative, make it an absolute path.
439 * Relative paths make a keyfile not easily usable in another
441 if (path[0] && path[0] != '/') {
442 base_dir = g_get_current_dir ();
443 path = path_free = g_strconcat (base_dir, "/", path, NULL);
445 base_dir = g_path_get_dirname (path);
447 /* path cannot start with "file://" or "data:;base64,", because it is an absolute path.
448 * Still, make sure that a prefix-less path will be recognized. This can happen
449 * for example if the path is longer then 500 chars. */
450 tmp = nm_keyfile_detect_unqualified_path_scheme (base_dir, path, -1, FALSE, NULL);
452 g_clear_pointer (&tmp, g_free);
454 path = tmp = g_strconcat (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH, path, NULL);
456 /* Path contains at least a '/', hence it cannot be recognized as the old
457 * binary format consisting of a list of integers. */
459 nm_keyfile_plugin_kf_set_string (file, setting_name, cert_data->property_name, path);
462 } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
464 const guint8 *blob_data;
466 char *blob_base64, *val;
468 blob = cert_data->blob_func (cert_data->setting);
470 blob_data = g_bytes_get_data (blob, &blob_len);
472 blob_base64 = g_base64_encode (blob_data, blob_len);
473 val = g_strconcat (NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB, blob_base64, NULL);
475 nm_keyfile_plugin_kf_set_string (file, setting_name, cert_data->property_name, val);
477 g_free (blob_base64);
479 /* scheme_func() returns UNKNOWN in all other cases. The only valid case
480 * where a scheme is allowed to be UNKNOWN, is unsetting the value. In this
481 * case, we don't expect the writer to be called, because the default value
482 * will not be serialized.
483 * The only other reason for the scheme to be UNKNOWN is an invalid cert.
484 * But our connection verifies, so that cannot happen either. */
485 g_return_if_reached ();
490 cert_writer (KeyfileWriterInfo *info,
495 const ObjectType *objtype = NULL;
497 NMKeyfileWriteTypeDataCert type_data = { 0 };
499 for (i = 0; i < G_N_ELEMENTS (objtypes) && objtypes[i].key; i++) {
500 if (g_strcmp0 (objtypes[i].key, key) == 0) {
501 objtype = &objtypes[i];
506 g_return_if_reached ();
508 type_data.setting = NM_SETTING_802_1X (setting);
509 type_data.property_name = key;
510 type_data.suffix = objtype->suffix;
511 type_data.scheme_func = objtype->scheme_func;
512 type_data.format_func = objtype->format_func;
513 type_data.path_func = objtype->path_func;
514 type_data.blob_func = objtype->blob_func;
517 if (info->handler (info->connection,
519 NM_KEYFILE_WRITE_TYPE_CERT,
528 cert_writer_default (info->connection, info->keyfile, &type_data);
531 /**************************************************************************/
534 const char *setting_name;
536 void (*writer) (KeyfileWriterInfo *info,
539 const GValue *value);
542 /* A table of keys that require further parsing/conversion because they are
543 * stored in a format that can't be automatically read using the key's type.
544 * i.e. IPv4 addresses, which are stored in NetworkManager as guint32, but are
545 * stored in keyfiles as strings, eg "10.1.1.2" or IPv6 addresses stored
546 * in struct in6_addr internally, but as string in keyfiles.
548 static KeyWriter key_writers[] = {
549 { NM_SETTING_CONNECTION_SETTING_NAME,
550 NM_SETTING_CONNECTION_TYPE,
551 setting_alias_writer },
552 { NM_SETTING_IP4_CONFIG_SETTING_NAME,
553 NM_SETTING_IP_CONFIG_ADDRESSES,
555 { NM_SETTING_IP4_CONFIG_SETTING_NAME,
557 ip4_addr_label_writer },
558 { NM_SETTING_IP6_CONFIG_SETTING_NAME,
559 NM_SETTING_IP_CONFIG_ADDRESSES,
561 { NM_SETTING_IP4_CONFIG_SETTING_NAME,
562 NM_SETTING_IP_CONFIG_GATEWAY,
564 { NM_SETTING_IP6_CONFIG_SETTING_NAME,
565 NM_SETTING_IP_CONFIG_GATEWAY,
567 { NM_SETTING_IP4_CONFIG_SETTING_NAME,
568 NM_SETTING_IP_CONFIG_ROUTES,
570 { NM_SETTING_IP6_CONFIG_SETTING_NAME,
571 NM_SETTING_IP_CONFIG_ROUTES,
573 { NM_SETTING_IP4_CONFIG_SETTING_NAME,
574 NM_SETTING_IP_CONFIG_DNS,
576 { NM_SETTING_IP6_CONFIG_SETTING_NAME,
577 NM_SETTING_IP_CONFIG_DNS,
579 { NM_SETTING_IP6_CONFIG_SETTING_NAME,
580 NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE,
581 ip6_addr_gen_mode_writer },
582 { NM_SETTING_WIRELESS_SETTING_NAME,
583 NM_SETTING_WIRELESS_SSID,
585 { NM_SETTING_802_1X_SETTING_NAME,
586 NM_SETTING_802_1X_PASSWORD_RAW,
587 password_raw_writer },
588 { NM_SETTING_802_1X_SETTING_NAME,
589 NM_SETTING_802_1X_CA_CERT,
591 { NM_SETTING_802_1X_SETTING_NAME,
592 NM_SETTING_802_1X_CLIENT_CERT,
594 { NM_SETTING_802_1X_SETTING_NAME,
595 NM_SETTING_802_1X_PRIVATE_KEY,
597 { NM_SETTING_802_1X_SETTING_NAME,
598 NM_SETTING_802_1X_PHASE2_CA_CERT,
600 { NM_SETTING_802_1X_SETTING_NAME,
601 NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
603 { NM_SETTING_802_1X_SETTING_NAME,
604 NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
610 can_omit_default_value (NMSetting *setting, const char *property)
612 if (NM_IS_SETTING_VLAN (setting)) {
613 if (!strcmp (property, NM_SETTING_VLAN_FLAGS))
615 } else if (NM_IS_SETTING_IP6_CONFIG (setting)) {
616 if (!strcmp (property, NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE))
618 } else if (NM_IS_SETTING_WIRELESS (setting)) {
619 if (!strcmp (property, NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION))
627 write_setting_value (NMSetting *setting,
633 KeyfileWriterInfo *info = user_data;
634 const char *setting_name;
635 GType type = G_VALUE_TYPE (value);
636 KeyWriter *writer = &key_writers[0];
642 /* Setting name gets picked up from the keyfile's section name instead */
643 if (!strcmp (key, NM_SETTING_NAME))
646 /* Don't write the NMSettingConnection object's 'read-only' property */
647 if ( NM_IS_SETTING_CONNECTION (setting)
648 && !strcmp (key, NM_SETTING_CONNECTION_READ_ONLY))
651 setting_name = nm_setting_get_name (setting);
653 /* If the value is the default value, remove the item from the keyfile */
654 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), key);
656 if ( can_omit_default_value (setting, key)
657 && g_param_value_defaults (pspec, (GValue *) value)) {
658 g_key_file_remove_key (info->keyfile, setting_name, key, NULL);
663 /* Don't write secrets that are owned by user secret agents or aren't
664 * supposed to be saved. VPN secrets are handled specially though since
665 * the secret flags there are in a third-level hash in the 'secrets'
668 if (pspec && (pspec->flags & NM_SETTING_PARAM_SECRET) && !NM_IS_SETTING_VPN (setting)) {
669 NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
671 if (!nm_setting_get_secret_flags (setting, key, &secret_flags, NULL))
672 g_assert_not_reached ();
673 if (secret_flags != NM_SETTING_SECRET_FLAG_NONE)
677 /* Look through the list of handlers for non-standard format key values */
678 while (writer->setting_name) {
679 if (!strcmp (writer->setting_name, setting_name) && !strcmp (writer->key, key)) {
680 (*writer->writer) (info, setting, key, value);
686 if (type == G_TYPE_STRING) {
689 str = g_value_get_string (value);
691 nm_keyfile_plugin_kf_set_string (info->keyfile, setting_name, key, str);
692 } else if (type == G_TYPE_UINT)
693 nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, (int) g_value_get_uint (value));
694 else if (type == G_TYPE_INT)
695 nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, g_value_get_int (value));
696 else if (type == G_TYPE_UINT64) {
699 numstr = g_strdup_printf ("%" G_GUINT64_FORMAT, g_value_get_uint64 (value));
700 nm_keyfile_plugin_kf_set_value (info->keyfile, setting_name, key, numstr);
702 } else if (type == G_TYPE_INT64) {
705 numstr = g_strdup_printf ("%" G_GINT64_FORMAT, g_value_get_int64 (value));
706 nm_keyfile_plugin_kf_set_value (info->keyfile, setting_name, key, numstr);
708 } else if (type == G_TYPE_BOOLEAN) {
709 nm_keyfile_plugin_kf_set_boolean (info->keyfile, setting_name, key, g_value_get_boolean (value));
710 } else if (type == G_TYPE_CHAR) {
711 nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, (int) g_value_get_schar (value));
712 } else if (type == G_TYPE_BYTES) {
717 bytes = g_value_get_boxed (value);
718 data = bytes ? g_bytes_get_data (bytes, &len) : NULL;
720 if (data != NULL && len > 0) {
724 tmp_array = g_new (gint, len);
725 for (i = 0; i < len; i++)
726 tmp_array[i] = (int) data[i];
728 nm_keyfile_plugin_kf_set_integer_list (info->keyfile, setting_name, key, tmp_array, len);
731 } else if (type == G_TYPE_STRV) {
734 array = (char **) g_value_get_boxed (value);
735 nm_keyfile_plugin_kf_set_string_list (info->keyfile, setting_name, key, (const gchar **const) array, g_strv_length (array));
736 } else if (type == G_TYPE_HASH_TABLE) {
737 write_hash_of_string (info->keyfile, setting, key, value);
738 } else if (type == G_TYPE_ARRAY) {
739 write_array_of_uint (info->keyfile, setting, key, value);
740 } else if (G_VALUE_HOLDS_FLAGS (value)) {
741 /* Flags are guint but GKeyFile has no uint reader, just uint64 */
742 nm_keyfile_plugin_kf_set_uint64 (info->keyfile, setting_name, key, (guint64) g_value_get_flags (value));
743 } else if (G_VALUE_HOLDS_ENUM (value))
744 nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, (gint) g_value_get_enum (value));
746 g_warn_if_reached ();
750 nm_keyfile_write (NMConnection *connection,
751 NMKeyfileWriteHandler handler,
755 KeyfileWriterInfo info = { 0 };
757 g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
758 g_return_val_if_fail (!error || !*error, NULL);
760 if (!nm_connection_verify (connection, error))
763 info.connection = connection;
764 info.keyfile = g_key_file_new ();
766 info.handler = handler;
767 info.user_data = user_data;
768 nm_connection_for_each_setting_value (connection, write_setting_value, &info);
771 g_propagate_error (error, info.error);
772 g_key_file_unref (info.keyfile);