mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-08 15:00:35 +01:00
keyfile: write certificates and keys in a human-readable manner
Write actual paths, not integer lists. When given certificate or key blobs, write those out to files and put the path to that file into the keyfile.
This commit is contained in:
parent
e3cddc8d9f
commit
ecca85066d
2 changed files with 507 additions and 20 deletions
|
|
@ -15,7 +15,7 @@
|
|||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 Red Hat, Inc.
|
||||
* Copyright (C) 2008 - 2011 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
|
@ -1965,7 +1965,7 @@ test_read_wired_8021x_tls_old_connection (void)
|
|||
const char *tmp;
|
||||
gboolean success;
|
||||
|
||||
connection = connection_from_file (TEST_WIRED_TLS_OLD_FILE, &error);
|
||||
connection = nm_keyfile_plugin_connection_from_file (TEST_WIRED_TLS_OLD_FILE, &error);
|
||||
if (connection == NULL) {
|
||||
g_assert (error);
|
||||
g_warning ("Failed to read %s: %s", TEST_WIRED_TLS_OLD_FILE, error->message);
|
||||
|
|
@ -2021,7 +2021,7 @@ test_read_wired_8021x_tls_new_connection (void)
|
|||
const char *tmp;
|
||||
gboolean success;
|
||||
|
||||
connection = connection_from_file (TEST_WIRED_TLS_NEW_FILE, &error);
|
||||
connection = nm_keyfile_plugin_connection_from_file (TEST_WIRED_TLS_NEW_FILE, &error);
|
||||
if (connection == NULL) {
|
||||
g_assert (error);
|
||||
g_warning ("Failed to read %s: %s", TEST_WIRED_TLS_NEW_FILE, error->message);
|
||||
|
|
@ -2066,9 +2066,249 @@ test_read_wired_8021x_tls_new_connection (void)
|
|||
}
|
||||
|
||||
#define TEST_WIRED_TLS_CA_CERT TEST_KEYFILES_DIR"/test-ca-cert.pem"
|
||||
#define TEST_WIRED_TLS_CLI_CERT TEST_KEYFILES_DIR"/test-key-and-cert.pem"
|
||||
#define TEST_WIRED_TLS_CLIENT_CERT TEST_KEYFILES_DIR"/test-key-and-cert.pem"
|
||||
#define TEST_WIRED_TLS_PRIVKEY TEST_KEYFILES_DIR"/test-key-and-cert.pem"
|
||||
|
||||
static NMConnection *
|
||||
create_wired_tls_connection (NMSetting8021xCKScheme scheme)
|
||||
{
|
||||
NMConnection *connection;
|
||||
NMSettingConnection *s_con;
|
||||
NMSettingIP4Config *s_ip4;
|
||||
NMSetting *s_wired;
|
||||
NMSetting8021x *s_8021x;
|
||||
char *uuid;
|
||||
gboolean success;
|
||||
GError *error = NULL;
|
||||
|
||||
connection = nm_connection_new ();
|
||||
g_assert (connection != NULL);
|
||||
|
||||
/* Connection setting */
|
||||
s_con = (NMSettingConnection *) nm_setting_connection_new ();
|
||||
g_assert (s_con);
|
||||
nm_connection_add_setting (connection, NM_SETTING (s_con));
|
||||
|
||||
uuid = nm_utils_uuid_generate ();
|
||||
g_object_set (s_con,
|
||||
NM_SETTING_CONNECTION_ID, "Wired Really Secure TLS",
|
||||
NM_SETTING_CONNECTION_UUID, uuid,
|
||||
NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
|
||||
NULL);
|
||||
g_free (uuid);
|
||||
|
||||
/* IP4 setting */
|
||||
s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
|
||||
g_assert (s_ip4);
|
||||
g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
|
||||
nm_connection_add_setting (connection, NM_SETTING (s_ip4));
|
||||
|
||||
/* Wired setting */
|
||||
s_wired = nm_setting_wired_new ();
|
||||
g_assert (s_wired);
|
||||
nm_connection_add_setting (connection, s_wired);
|
||||
|
||||
/* 802.1x setting */
|
||||
s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
|
||||
g_assert (s_8021x);
|
||||
nm_connection_add_setting (connection, NM_SETTING (s_8021x));
|
||||
|
||||
nm_setting_802_1x_add_eap_method (s_8021x, "tls");
|
||||
g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, "Bill Smith", NULL);
|
||||
|
||||
success = nm_setting_802_1x_set_ca_cert (s_8021x,
|
||||
TEST_WIRED_TLS_CA_CERT,
|
||||
scheme,
|
||||
NULL,
|
||||
&error);
|
||||
if (!success) {
|
||||
g_assert (error);
|
||||
g_warning ("Failed to set CA cert %s: %s", TEST_WIRED_TLS_CA_CERT, error->message);
|
||||
g_assert (success);
|
||||
}
|
||||
|
||||
success = nm_setting_802_1x_set_client_cert (s_8021x,
|
||||
TEST_WIRED_TLS_CLIENT_CERT,
|
||||
scheme,
|
||||
NULL,
|
||||
&error);
|
||||
if (!success) {
|
||||
g_assert (error);
|
||||
g_warning ("Failed to set client cert %s: %s", TEST_WIRED_TLS_CA_CERT, error->message);
|
||||
g_assert (success);
|
||||
}
|
||||
|
||||
success = nm_setting_802_1x_set_private_key (s_8021x,
|
||||
TEST_WIRED_TLS_PRIVKEY,
|
||||
"test1",
|
||||
scheme,
|
||||
NULL,
|
||||
&error);
|
||||
if (!success) {
|
||||
g_assert (error);
|
||||
g_warning ("Failed to set private key %s: %s", TEST_WIRED_TLS_CA_CERT, error->message);
|
||||
g_assert (success);
|
||||
}
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
static void
|
||||
test_write_wired_8021x_tls_connection_path (void)
|
||||
{
|
||||
NMConnection *connection;
|
||||
char *tmp;
|
||||
gboolean success;
|
||||
NMConnection *reread;
|
||||
char *testfile = NULL;
|
||||
GError *error = NULL;
|
||||
GKeyFile *keyfile;
|
||||
|
||||
connection = create_wired_tls_connection (NM_SETTING_802_1X_CK_SCHEME_PATH);
|
||||
g_assert (connection != NULL);
|
||||
|
||||
/* Write out the connection */
|
||||
success = nm_keyfile_plugin_write_test_connection (connection, TEST_SCRATCH_DIR, geteuid (), getegid (), &testfile, &error);
|
||||
if (!success) {
|
||||
g_assert (error);
|
||||
g_warning ("Failed to write keyfile: %s", error->message);
|
||||
g_assert (success);
|
||||
}
|
||||
g_assert (testfile);
|
||||
|
||||
/* Read the connection back in and compare it to the one we just wrote out */
|
||||
reread = nm_keyfile_plugin_connection_from_file (testfile, &error);
|
||||
if (!reread) {
|
||||
g_assert (error);
|
||||
g_warning ("Failed to re-read test connection: %s", error->message);
|
||||
g_assert (reread);
|
||||
}
|
||||
|
||||
success = nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT);
|
||||
if (!reread) {
|
||||
g_warning ("Written and re-read connection weren't the same");
|
||||
g_assert (success);
|
||||
}
|
||||
|
||||
/* Ensure the cert and key values are properly written out */
|
||||
keyfile = g_key_file_new ();
|
||||
g_assert (keyfile);
|
||||
success = g_key_file_load_from_file (keyfile, testfile, G_KEY_FILE_NONE, &error);
|
||||
if (!success) {
|
||||
g_assert (error);
|
||||
g_warning ("Failed to re-read test file %s: %s", testfile, error->message);
|
||||
g_assert (success);
|
||||
}
|
||||
|
||||
/* CA cert */
|
||||
tmp = g_key_file_get_string (keyfile,
|
||||
NM_SETTING_802_1X_SETTING_NAME,
|
||||
NM_SETTING_802_1X_CA_CERT,
|
||||
NULL);
|
||||
g_assert (g_strcmp0 (tmp, TEST_WIRED_TLS_CA_CERT) == 0);
|
||||
g_free (tmp);
|
||||
|
||||
/* Client cert */
|
||||
tmp = g_key_file_get_string (keyfile,
|
||||
NM_SETTING_802_1X_SETTING_NAME,
|
||||
NM_SETTING_802_1X_CLIENT_CERT,
|
||||
NULL);
|
||||
g_assert (g_strcmp0 (tmp, TEST_WIRED_TLS_CLIENT_CERT) == 0);
|
||||
g_free (tmp);
|
||||
|
||||
/* Private key */
|
||||
tmp = g_key_file_get_string (keyfile,
|
||||
NM_SETTING_802_1X_SETTING_NAME,
|
||||
NM_SETTING_802_1X_PRIVATE_KEY,
|
||||
NULL);
|
||||
g_assert (g_strcmp0 (tmp, TEST_WIRED_TLS_PRIVKEY) == 0);
|
||||
g_free (tmp);
|
||||
|
||||
g_key_file_free (keyfile);
|
||||
unlink (testfile);
|
||||
g_free (testfile);
|
||||
|
||||
g_object_unref (reread);
|
||||
g_object_unref (connection);
|
||||
}
|
||||
|
||||
static void
|
||||
test_write_wired_8021x_tls_connection_blob (void)
|
||||
{
|
||||
NMConnection *connection;
|
||||
NMSettingConnection *s_con;
|
||||
NMSetting8021x *s_8021x;
|
||||
gboolean success;
|
||||
NMConnection *reread;
|
||||
char *testfile = NULL;
|
||||
char *new_ca_cert;
|
||||
char *new_client_cert;
|
||||
char *new_priv_key;
|
||||
const char *uuid;
|
||||
GError *error = NULL;
|
||||
|
||||
connection = create_wired_tls_connection (NM_SETTING_802_1X_CK_SCHEME_BLOB);
|
||||
g_assert (connection != NULL);
|
||||
|
||||
/* Write out the connection */
|
||||
success = nm_keyfile_plugin_write_test_connection (connection, TEST_SCRATCH_DIR, geteuid (), getegid (), &testfile, &error);
|
||||
if (!success) {
|
||||
g_assert (error);
|
||||
g_warning ("Failed to write keyfile: %s", error->message);
|
||||
g_assert (success);
|
||||
}
|
||||
g_assert (testfile);
|
||||
|
||||
/* Check that the new certs got written out */
|
||||
s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
|
||||
g_assert (s_con);
|
||||
uuid = nm_setting_connection_get_uuid (s_con);
|
||||
g_assert (uuid);
|
||||
|
||||
new_ca_cert = g_strdup_printf ("%s/%s-ca-cert.pem", TEST_SCRATCH_DIR, uuid);
|
||||
g_assert (new_ca_cert);
|
||||
g_assert (g_file_test (new_ca_cert, G_FILE_TEST_EXISTS));
|
||||
|
||||
new_client_cert = g_strdup_printf ("%s/%s-client-cert.pem", TEST_SCRATCH_DIR, uuid);
|
||||
g_assert (new_client_cert);
|
||||
g_assert (g_file_test (new_client_cert, G_FILE_TEST_EXISTS));
|
||||
|
||||
new_priv_key = g_strdup_printf ("%s/%s-private-key.pem", TEST_SCRATCH_DIR, uuid);
|
||||
g_assert (new_priv_key);
|
||||
g_assert (g_file_test (new_priv_key, G_FILE_TEST_EXISTS));
|
||||
|
||||
/* Read the connection back in and compare it to the one we just wrote out */
|
||||
reread = nm_keyfile_plugin_connection_from_file (testfile, &error);
|
||||
if (!reread) {
|
||||
g_assert (error);
|
||||
g_warning ("Failed to re-read test connection: %s", error->message);
|
||||
g_assert (reread);
|
||||
}
|
||||
|
||||
/* Ensure the re-read connection's certificates use the path scheme */
|
||||
s_8021x = (NMSetting8021x *) nm_connection_get_setting (reread, NM_TYPE_SETTING_802_1X);
|
||||
g_assert (s_8021x);
|
||||
g_assert (nm_setting_802_1x_get_ca_cert_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH);
|
||||
g_assert (nm_setting_802_1x_get_client_cert_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH);
|
||||
g_assert (nm_setting_802_1x_get_private_key_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH);
|
||||
|
||||
unlink (testfile);
|
||||
g_free (testfile);
|
||||
|
||||
/* Clean up written certs */
|
||||
unlink (new_ca_cert);
|
||||
g_free (new_ca_cert);
|
||||
|
||||
unlink (new_client_cert);
|
||||
g_free (new_client_cert);
|
||||
|
||||
unlink (new_priv_key);
|
||||
g_free (new_priv_key);
|
||||
|
||||
g_object_unref (reread);
|
||||
g_object_unref (connection);
|
||||
}
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
|
@ -2102,6 +2342,8 @@ int main (int argc, char **argv)
|
|||
|
||||
test_read_wired_8021x_tls_old_connection ();
|
||||
test_read_wired_8021x_tls_new_connection ();
|
||||
test_write_wired_8021x_tls_connection_path ();
|
||||
test_write_wired_8021x_tls_connection_blob ();
|
||||
|
||||
base = g_path_get_basename (argv[0]);
|
||||
fprintf (stdout, "%s: SUCCESS\n", base);
|
||||
|
|
|
|||
|
|
@ -19,9 +19,13 @@
|
|||
* Copyright (C) 2008 - 2011 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <dbus/dbus-glib.h>
|
||||
#include <nm-setting.h>
|
||||
#include <nm-setting-connection.h>
|
||||
|
|
@ -32,6 +36,7 @@
|
|||
#include <nm-setting-wireless.h>
|
||||
#include <nm-setting-ip4-config.h>
|
||||
#include <nm-setting-bluetooth.h>
|
||||
#include <nm-setting-8021x.h>
|
||||
#include <nm-utils.h>
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
|
|
@ -67,6 +72,8 @@ write_array_of_uint (GKeyFile *file,
|
|||
|
||||
static void
|
||||
ip4_dns_writer (GKeyFile *file,
|
||||
const char *keyfile_dir,
|
||||
const char *uuid,
|
||||
NMSetting *setting,
|
||||
const char *key,
|
||||
const GValue *value)
|
||||
|
|
@ -156,6 +163,8 @@ write_ip4_values (GKeyFile *file,
|
|||
|
||||
static void
|
||||
ip4_addr_writer (GKeyFile *file,
|
||||
const char *keyfile_dir,
|
||||
const char *uuid,
|
||||
NMSetting *setting,
|
||||
const char *key,
|
||||
const GValue *value)
|
||||
|
|
@ -172,6 +181,8 @@ ip4_addr_writer (GKeyFile *file,
|
|||
|
||||
static void
|
||||
ip4_route_writer (GKeyFile *file,
|
||||
const char *keyfile_dir,
|
||||
const char *uuid,
|
||||
NMSetting *setting,
|
||||
const char *key,
|
||||
const GValue *value)
|
||||
|
|
@ -188,6 +199,8 @@ ip4_route_writer (GKeyFile *file,
|
|||
|
||||
static void
|
||||
ip6_dns_writer (GKeyFile *file,
|
||||
const char *keyfile_dir,
|
||||
const char *uuid,
|
||||
NMSetting *setting,
|
||||
const char *key,
|
||||
const GValue *value)
|
||||
|
|
@ -296,6 +309,8 @@ ip6_array_to_addr_prefix (GValueArray *values)
|
|||
|
||||
static void
|
||||
ip6_addr_writer (GKeyFile *file,
|
||||
const char *keyfile_dir,
|
||||
const char *uuid,
|
||||
NMSetting *setting,
|
||||
const char *key,
|
||||
const GValue *value)
|
||||
|
|
@ -334,6 +349,8 @@ ip6_addr_writer (GKeyFile *file,
|
|||
|
||||
static void
|
||||
ip6_route_writer (GKeyFile *file,
|
||||
const char *keyfile_dir,
|
||||
const char *uuid,
|
||||
NMSetting *setting,
|
||||
const char *key,
|
||||
const GValue *value)
|
||||
|
|
@ -389,6 +406,8 @@ ip6_route_writer (GKeyFile *file,
|
|||
|
||||
static void
|
||||
mac_address_writer (GKeyFile *file,
|
||||
const char *keyfile_dir,
|
||||
const char *uuid,
|
||||
NMSetting *setting,
|
||||
const char *key,
|
||||
const GValue *value)
|
||||
|
|
@ -450,6 +469,8 @@ write_hash_of_string (GKeyFile *file,
|
|||
|
||||
static void
|
||||
ssid_writer (GKeyFile *file,
|
||||
const char *keyfile_dir,
|
||||
const char *uuid,
|
||||
NMSetting *setting,
|
||||
const char *key,
|
||||
const GValue *value)
|
||||
|
|
@ -491,10 +512,206 @@ ssid_writer (GKeyFile *file,
|
|||
}
|
||||
}
|
||||
|
||||
typedef struct ObjectType {
|
||||
const char *key;
|
||||
const char *suffix;
|
||||
const char *privkey_pw_prop;
|
||||
NMSetting8021xCKScheme (*scheme_func) (NMSetting8021x *setting);
|
||||
NMSetting8021xCKFormat (*format_func) (NMSetting8021x *setting);
|
||||
const char * (*path_func) (NMSetting8021x *setting);
|
||||
const GByteArray * (*blob_func) (NMSetting8021x *setting);
|
||||
} ObjectType;
|
||||
|
||||
static const ObjectType objtypes[10] = {
|
||||
{ NM_SETTING_802_1X_CA_CERT,
|
||||
"ca-cert",
|
||||
NULL,
|
||||
nm_setting_802_1x_get_ca_cert_scheme,
|
||||
NULL,
|
||||
nm_setting_802_1x_get_ca_cert_path,
|
||||
nm_setting_802_1x_get_ca_cert_blob },
|
||||
|
||||
{ NM_SETTING_802_1X_PHASE2_CA_CERT,
|
||||
"inner-ca-cert",
|
||||
NULL,
|
||||
nm_setting_802_1x_get_phase2_ca_cert_scheme,
|
||||
NULL,
|
||||
nm_setting_802_1x_get_phase2_ca_cert_path,
|
||||
nm_setting_802_1x_get_phase2_ca_cert_blob },
|
||||
|
||||
{ NM_SETTING_802_1X_CLIENT_CERT,
|
||||
"client-cert",
|
||||
NULL,
|
||||
nm_setting_802_1x_get_client_cert_scheme,
|
||||
NULL,
|
||||
nm_setting_802_1x_get_client_cert_path,
|
||||
nm_setting_802_1x_get_client_cert_blob },
|
||||
|
||||
{ NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
|
||||
"inner-client-cert",
|
||||
NULL,
|
||||
nm_setting_802_1x_get_phase2_client_cert_scheme,
|
||||
NULL,
|
||||
nm_setting_802_1x_get_phase2_client_cert_path,
|
||||
nm_setting_802_1x_get_phase2_client_cert_blob },
|
||||
|
||||
{ NM_SETTING_802_1X_PRIVATE_KEY,
|
||||
"private-key",
|
||||
NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD,
|
||||
nm_setting_802_1x_get_private_key_scheme,
|
||||
nm_setting_802_1x_get_private_key_format,
|
||||
nm_setting_802_1x_get_private_key_path,
|
||||
nm_setting_802_1x_get_private_key_blob },
|
||||
|
||||
{ NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
|
||||
"inner-private-key",
|
||||
NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD,
|
||||
nm_setting_802_1x_get_phase2_private_key_scheme,
|
||||
nm_setting_802_1x_get_phase2_private_key_format,
|
||||
nm_setting_802_1x_get_phase2_private_key_path,
|
||||
nm_setting_802_1x_get_phase2_private_key_blob },
|
||||
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
static gboolean
|
||||
write_cert_key_file (const char *path,
|
||||
const GByteArray *data,
|
||||
GError **error)
|
||||
{
|
||||
char *tmppath;
|
||||
int fd = -1, written;
|
||||
gboolean success = FALSE;
|
||||
|
||||
tmppath = g_malloc0 (strlen (path) + 10);
|
||||
g_assert (tmppath);
|
||||
memcpy (tmppath, path, strlen (path));
|
||||
strcat (tmppath, ".XXXXXX");
|
||||
|
||||
errno = 0;
|
||||
fd = mkstemp (tmppath);
|
||||
if (fd < 0) {
|
||||
g_set_error (error, KEYFILE_PLUGIN_ERROR, 0,
|
||||
"Could not create temporary file for '%s': %d",
|
||||
path, errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Only readable by root */
|
||||
errno = 0;
|
||||
if (fchmod (fd, S_IRUSR | S_IWUSR) != 0) {
|
||||
close (fd);
|
||||
unlink (tmppath);
|
||||
g_set_error (error, KEYFILE_PLUGIN_ERROR, 0,
|
||||
"Could not set permissions for temporary file '%s': %d",
|
||||
path, errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
written = write (fd, data->data, data->len);
|
||||
if (written != data->len) {
|
||||
close (fd);
|
||||
unlink (tmppath);
|
||||
g_set_error (error, KEYFILE_PLUGIN_ERROR, 0,
|
||||
"Could not write temporary file for '%s': %d",
|
||||
path, errno);
|
||||
goto out;
|
||||
}
|
||||
close (fd);
|
||||
|
||||
/* Try to rename */
|
||||
errno = 0;
|
||||
if (rename (tmppath, path) == 0)
|
||||
success = TRUE;
|
||||
else {
|
||||
unlink (tmppath);
|
||||
g_set_error (error, KEYFILE_PLUGIN_ERROR, 0,
|
||||
"Could not rename temporary file to '%s': %d",
|
||||
path, errno);
|
||||
}
|
||||
|
||||
out:
|
||||
g_free (tmppath);
|
||||
return success;
|
||||
}
|
||||
|
||||
static void
|
||||
cert_writer (GKeyFile *file,
|
||||
const char *keyfile_dir,
|
||||
const char *uuid,
|
||||
NMSetting *setting,
|
||||
const char *key,
|
||||
const GValue *value)
|
||||
{
|
||||
const char *setting_name = nm_setting_get_name (setting);
|
||||
NMSetting8021xCKScheme scheme;
|
||||
NMSetting8021xCKFormat format;
|
||||
const char *path = NULL, *ext = "pem";
|
||||
const ObjectType *objtype = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (objtypes) && objtypes[i].key; i++) {
|
||||
if (g_strcmp0 (objtypes[i].key, key) == 0) {
|
||||
objtype = &objtypes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_return_if_fail (objtype != NULL);
|
||||
|
||||
scheme = objtypes->scheme_func (NM_SETTING_802_1X (setting));
|
||||
if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
|
||||
path = objtype->path_func (NM_SETTING_802_1X (setting));
|
||||
g_assert (path);
|
||||
g_key_file_set_string (file, setting_name, key, path);
|
||||
} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
|
||||
const GByteArray *blob;
|
||||
gboolean success;
|
||||
GError *error = NULL;
|
||||
char *new_path;
|
||||
|
||||
blob = objtype->blob_func (NM_SETTING_802_1X (setting));
|
||||
g_assert (blob);
|
||||
|
||||
if (objtype->format_func) {
|
||||
/* Get the extension for a private key */
|
||||
format = objtype->format_func (NM_SETTING_802_1X (setting));
|
||||
if (format == NM_SETTING_802_1X_CK_FORMAT_PKCS12)
|
||||
ext = "p12";
|
||||
} else {
|
||||
/* DER or PEM format certificate? */
|
||||
if (blob->len > 2 && blob->data[0] == 0x30 && blob->data[1] == 0x82)
|
||||
ext = "der";
|
||||
}
|
||||
|
||||
/* Write the raw data out to the standard file so that we can use paths
|
||||
* from now on instead of pushing around the certificate data.
|
||||
*/
|
||||
new_path = g_strdup_printf ("%s/%s-%s.%s", keyfile_dir, uuid, objtype->suffix, ext);
|
||||
g_assert (new_path);
|
||||
|
||||
success = write_cert_key_file (new_path, blob, &error);
|
||||
if (success) {
|
||||
/* Write the path value to the keyfile */
|
||||
g_key_file_set_string (file, setting_name, key, new_path);
|
||||
} else {
|
||||
g_warning ("Failed to write certificate/key %s: %s", new_path, error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
g_free (new_path);
|
||||
} else
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const char *setting_name;
|
||||
const char *key;
|
||||
void (*writer) (GKeyFile *keyfile, NMSetting *setting, const char *key, const GValue *value);
|
||||
void (*writer) (GKeyFile *keyfile,
|
||||
const char *keyfile_dir,
|
||||
const char *uuid,
|
||||
NMSetting *setting,
|
||||
const char *key,
|
||||
const GValue *value);
|
||||
} KeyWriter;
|
||||
|
||||
/* A table of keys that require further parsing/conversion because they are
|
||||
|
|
@ -543,9 +760,33 @@ static KeyWriter key_writers[] = {
|
|||
{ NM_SETTING_WIRELESS_SETTING_NAME,
|
||||
NM_SETTING_WIRELESS_SSID,
|
||||
ssid_writer },
|
||||
{ NM_SETTING_802_1X_SETTING_NAME,
|
||||
NM_SETTING_802_1X_CA_CERT,
|
||||
cert_writer },
|
||||
{ NM_SETTING_802_1X_SETTING_NAME,
|
||||
NM_SETTING_802_1X_CLIENT_CERT,
|
||||
cert_writer },
|
||||
{ NM_SETTING_802_1X_SETTING_NAME,
|
||||
NM_SETTING_802_1X_PRIVATE_KEY,
|
||||
cert_writer },
|
||||
{ NM_SETTING_802_1X_SETTING_NAME,
|
||||
NM_SETTING_802_1X_PHASE2_CA_CERT,
|
||||
cert_writer },
|
||||
{ NM_SETTING_802_1X_SETTING_NAME,
|
||||
NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
|
||||
cert_writer },
|
||||
{ NM_SETTING_802_1X_SETTING_NAME,
|
||||
NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
|
||||
cert_writer },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
GKeyFile *keyfile;
|
||||
const char *keyfile_dir;
|
||||
const char *uuid;
|
||||
} WriteInfo;
|
||||
|
||||
static void
|
||||
write_setting_value (NMSetting *setting,
|
||||
const char *key,
|
||||
|
|
@ -553,7 +794,7 @@ write_setting_value (NMSetting *setting,
|
|||
GParamFlags flag,
|
||||
gpointer user_data)
|
||||
{
|
||||
GKeyFile *file = (GKeyFile *) user_data;
|
||||
WriteInfo *info = user_data;
|
||||
const char *setting_name;
|
||||
GType type = G_VALUE_TYPE (value);
|
||||
KeyWriter *writer = &key_writers[0];
|
||||
|
|
@ -575,7 +816,7 @@ write_setting_value (NMSetting *setting,
|
|||
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), key);
|
||||
if (pspec) {
|
||||
if (g_param_value_defaults (pspec, (GValue *) value)) {
|
||||
g_key_file_remove_key (file, setting_name, key, NULL);
|
||||
g_key_file_remove_key (info->keyfile, setting_name, key, NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -591,7 +832,7 @@ write_setting_value (NMSetting *setting,
|
|||
/* Look through the list of handlers for non-standard format key values */
|
||||
while (writer->setting_name) {
|
||||
if (!strcmp (writer->setting_name, setting_name) && !strcmp (writer->key, key)) {
|
||||
(*writer->writer) (file, setting, key, value);
|
||||
(*writer->writer) (info->keyfile, info->keyfile_dir, info->uuid, setting, key, value);
|
||||
return;
|
||||
}
|
||||
writer++;
|
||||
|
|
@ -602,21 +843,21 @@ write_setting_value (NMSetting *setting,
|
|||
|
||||
str = g_value_get_string (value);
|
||||
if (str)
|
||||
g_key_file_set_string (file, setting_name, key, str);
|
||||
g_key_file_set_string (info->keyfile, setting_name, key, str);
|
||||
} else if (type == G_TYPE_UINT)
|
||||
g_key_file_set_integer (file, setting_name, key, (int) g_value_get_uint (value));
|
||||
g_key_file_set_integer (info->keyfile, setting_name, key, (int) g_value_get_uint (value));
|
||||
else if (type == G_TYPE_INT)
|
||||
g_key_file_set_integer (file, setting_name, key, g_value_get_int (value));
|
||||
g_key_file_set_integer (info->keyfile, setting_name, key, g_value_get_int (value));
|
||||
else if (type == G_TYPE_UINT64) {
|
||||
char *numstr;
|
||||
|
||||
numstr = g_strdup_printf ("%" G_GUINT64_FORMAT, g_value_get_uint64 (value));
|
||||
g_key_file_set_value (file, setting_name, key, numstr);
|
||||
g_key_file_set_value (info->keyfile, setting_name, key, numstr);
|
||||
g_free (numstr);
|
||||
} else if (type == G_TYPE_BOOLEAN) {
|
||||
g_key_file_set_boolean (file, setting_name, key, g_value_get_boolean (value));
|
||||
g_key_file_set_boolean (info->keyfile, setting_name, key, g_value_get_boolean (value));
|
||||
} else if (type == G_TYPE_CHAR) {
|
||||
g_key_file_set_integer (file, setting_name, key, (int) g_value_get_char (value));
|
||||
g_key_file_set_integer (info->keyfile, setting_name, key, (int) g_value_get_char (value));
|
||||
} else if (type == DBUS_TYPE_G_UCHAR_ARRAY) {
|
||||
GByteArray *array;
|
||||
|
||||
|
|
@ -629,7 +870,7 @@ write_setting_value (NMSetting *setting,
|
|||
for (i = 0; i < array->len; i++)
|
||||
tmp_array[i] = (int) array->data[i];
|
||||
|
||||
g_key_file_set_integer_list (file, setting_name, key, tmp_array, array->len);
|
||||
g_key_file_set_integer_list (info->keyfile, setting_name, key, tmp_array, array->len);
|
||||
g_free (tmp_array);
|
||||
}
|
||||
} else if (type == DBUS_TYPE_G_LIST_OF_STRING) {
|
||||
|
|
@ -645,13 +886,13 @@ write_setting_value (NMSetting *setting,
|
|||
for (iter = list; iter; iter = iter->next)
|
||||
array[i++] = iter->data;
|
||||
|
||||
g_key_file_set_string_list (file, setting_name, key, (const gchar **const) array, i);
|
||||
g_key_file_set_string_list (info->keyfile, setting_name, key, (const gchar **const) array, i);
|
||||
g_free (array);
|
||||
}
|
||||
} else if (type == DBUS_TYPE_G_MAP_OF_STRING) {
|
||||
write_hash_of_string (file, setting, key, value);
|
||||
write_hash_of_string (info->keyfile, setting, key, value);
|
||||
} else if (type == DBUS_TYPE_G_UINT_ARRAY) {
|
||||
if (!write_array_of_uint (file, setting, key, value)) {
|
||||
if (!write_array_of_uint (info->keyfile, setting, key, value)) {
|
||||
g_warning ("Unhandled setting property type (write) '%s/%s' : '%s'",
|
||||
setting_name, key, g_type_name (type));
|
||||
}
|
||||
|
|
@ -696,6 +937,7 @@ _internal_write_connection (NMConnection *connection,
|
|||
gboolean success = FALSE;
|
||||
char *filename = NULL, *path;
|
||||
const char *id;
|
||||
WriteInfo info;
|
||||
|
||||
if (out_path)
|
||||
g_return_val_if_fail (*out_path == NULL, FALSE);
|
||||
|
|
@ -707,8 +949,11 @@ _internal_write_connection (NMConnection *connection,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
key_file = g_key_file_new ();
|
||||
nm_connection_for_each_setting_value (connection, write_setting_value, key_file);
|
||||
info.keyfile = key_file = g_key_file_new ();
|
||||
info.keyfile_dir = keyfile_dir;
|
||||
info.uuid = nm_connection_get_uuid (connection);
|
||||
g_assert (info.uuid);
|
||||
nm_connection_for_each_setting_value (connection, write_setting_value, &info);
|
||||
data = g_key_file_to_data (key_file, &len, error);
|
||||
if (!data)
|
||||
goto out;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue