mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-11 07:10:36 +01:00
keyfile: extend internal API to re-read keyfile connection after writing
Add API to re-read the keyfile after writing it. Usually, we would expect that whenever we serialize something to disk, it can be read back exactly the same. That is however not true for certificates, where we mangle path and blobs while writing to file. Anyway, extend the write-API to re-read what we just wrote. The tests got extended to assert that whatever we write can be read back the same. Later, we want to reinject the reread connection into the settings plugin again.
This commit is contained in:
parent
8b1b6f3d1a
commit
e636d28116
7 changed files with 172 additions and 18 deletions
|
|
@ -64,6 +64,8 @@ commit_changes (NMSettingsConnection *connection,
|
|||
NM_FLAGS_ALL (commit_reason, NM_SETTINGS_CONNECTION_COMMIT_REASON_USER_ACTION
|
||||
| NM_SETTINGS_CONNECTION_COMMIT_REASON_ID_CHANGED),
|
||||
&path,
|
||||
NULL,
|
||||
NULL,
|
||||
&error)) {
|
||||
callback (connection, error, user_data);
|
||||
g_clear_error (&error);
|
||||
|
|
|
|||
|
|
@ -532,7 +532,13 @@ add_connection (NMSettingsPlugin *config,
|
|||
gs_free char *path = NULL;
|
||||
|
||||
if (save_to_disk) {
|
||||
if (!nms_keyfile_writer_connection (connection, NULL, FALSE, &path, error))
|
||||
if (!nms_keyfile_writer_connection (connection,
|
||||
NULL,
|
||||
FALSE,
|
||||
&path,
|
||||
NULL,
|
||||
NULL,
|
||||
error))
|
||||
return NULL;
|
||||
}
|
||||
return NM_SETTINGS_CONNECTION (update_connection (self, connection, path, NULL, FALSE, NULL, error));
|
||||
|
|
|
|||
|
|
@ -56,6 +56,10 @@ _fmt_warn (const char *group, NMSetting *setting, const char *property_name, con
|
|||
return message;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
bool verbose;
|
||||
} HandlerReadData;
|
||||
|
||||
static gboolean
|
||||
_handler_read (GKeyFile *keyfile,
|
||||
NMConnection *connection,
|
||||
|
|
@ -64,11 +68,16 @@ _handler_read (GKeyFile *keyfile,
|
|||
void *user_data,
|
||||
GError **error)
|
||||
{
|
||||
const HandlerReadData *handler_data = user_data;
|
||||
|
||||
if (type == NM_KEYFILE_READ_TYPE_WARN) {
|
||||
NMKeyfileReadTypeDataWarn *warn_data = type_data;
|
||||
NMLogLevel level;
|
||||
char *message_free = NULL;
|
||||
|
||||
if (!handler_data->verbose)
|
||||
return TRUE;
|
||||
|
||||
if (warn_data->severity > NM_KEYFILE_WARN_SEVERITY_WARN)
|
||||
level = LOGL_ERR;
|
||||
else if (warn_data->severity >= NM_KEYFILE_WARN_SEVERITY_WARN)
|
||||
|
|
@ -88,6 +97,19 @@ _handler_read (GKeyFile *keyfile,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
NMConnection *
|
||||
nms_keyfile_reader_from_keyfile (GKeyFile *key_file,
|
||||
const char *filename,
|
||||
gboolean verbose,
|
||||
GError **error)
|
||||
{
|
||||
HandlerReadData data = {
|
||||
.verbose = verbose,
|
||||
};
|
||||
|
||||
return nm_keyfile_read (key_file, filename, NULL, _handler_read, &data, error);
|
||||
}
|
||||
|
||||
NMConnection *
|
||||
nms_keyfile_reader_from_file (const char *filename, GError **error)
|
||||
{
|
||||
|
|
@ -122,7 +144,7 @@ nms_keyfile_reader_from_file (const char *filename, GError **error)
|
|||
if (!g_key_file_load_from_file (key_file, filename, G_KEY_FILE_NONE, error))
|
||||
goto out;
|
||||
|
||||
connection = nm_keyfile_read (key_file, filename, NULL, _handler_read, NULL, error);
|
||||
connection = nms_keyfile_reader_from_keyfile (key_file, filename, TRUE, error);
|
||||
if (!connection)
|
||||
goto out;
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,11 @@
|
|||
|
||||
#include <nm-connection.h>
|
||||
|
||||
NMConnection *nms_keyfile_reader_from_keyfile (GKeyFile *key_file,
|
||||
const char *filename,
|
||||
gboolean verbose,
|
||||
GError **error);
|
||||
|
||||
NMConnection *nms_keyfile_reader_from_file (const char *filename, GError **error);
|
||||
|
||||
#endif /* __NMS_KEYFILE_READER_H__ */
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "nm-keyfile-internal.h"
|
||||
|
||||
#include "nms-keyfile-utils.h"
|
||||
#include "nms-keyfile-reader.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -174,9 +175,11 @@ _internal_write_connection (NMConnection *connection,
|
|||
const char *existing_path,
|
||||
gboolean force_rename,
|
||||
char **out_path,
|
||||
NMConnection **out_reread,
|
||||
gboolean *out_reread_same,
|
||||
GError **error)
|
||||
{
|
||||
GKeyFile *key_file;
|
||||
gs_unref_keyfile GKeyFile *key_file = NULL;
|
||||
gs_free char *data = NULL;
|
||||
gsize len;
|
||||
gs_free char *path = NULL;
|
||||
|
|
@ -188,8 +191,15 @@ _internal_write_connection (NMConnection *connection,
|
|||
g_return_val_if_fail (!out_path || !*out_path, FALSE);
|
||||
g_return_val_if_fail (keyfile_dir && keyfile_dir[0] == '/', FALSE);
|
||||
|
||||
if (!nm_connection_verify (connection, error))
|
||||
switch (_nm_connection_verify (connection, error)) {
|
||||
case NM_SETTING_VERIFY_NORMALIZABLE:
|
||||
nm_assert_not_reached ();
|
||||
/* fall-through */
|
||||
case NM_SETTING_VERIFY_SUCCESS:
|
||||
break;
|
||||
default:
|
||||
g_return_val_if_reached (FALSE);
|
||||
}
|
||||
|
||||
id = nm_connection_get_id (connection);
|
||||
g_assert (id && *id);
|
||||
|
|
@ -200,7 +210,6 @@ _internal_write_connection (NMConnection *connection,
|
|||
if (!key_file)
|
||||
return FALSE;
|
||||
data = g_key_file_to_data (key_file, &len, error);
|
||||
g_key_file_unref (key_file);
|
||||
if (!data)
|
||||
return FALSE;
|
||||
|
||||
|
|
@ -290,15 +299,48 @@ _internal_write_connection (NMConnection *connection,
|
|||
path = NULL;
|
||||
}
|
||||
|
||||
if (out_reread || out_reread_same)
|
||||
{
|
||||
gs_unref_object NMConnection *reread = NULL;
|
||||
gboolean reread_same = FALSE;
|
||||
|
||||
reread = nms_keyfile_reader_from_keyfile (key_file, path, FALSE, NULL);
|
||||
|
||||
nm_assert (NM_IS_CONNECTION (reread));
|
||||
|
||||
if ( reread
|
||||
&& !nm_connection_normalize (reread, NULL, NULL, NULL)) {
|
||||
nm_assert_not_reached ();
|
||||
g_clear_object (&reread);
|
||||
}
|
||||
|
||||
if (reread && out_reread_same) {
|
||||
reread_same = !!nm_connection_compare (reread, connection, NM_SETTING_COMPARE_FLAG_EXACT);
|
||||
|
||||
nm_assert (reread_same == nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
|
||||
nm_assert (reread_same == ({
|
||||
gs_unref_hashtable GHashTable *_settings = NULL;
|
||||
|
||||
( nm_connection_diff (reread, connection, NM_SETTING_COMPARE_FLAG_EXACT, &_settings)
|
||||
&& !_settings);
|
||||
}));
|
||||
}
|
||||
|
||||
NM_SET_OUT (out_reread, g_steal_pointer (&reread));
|
||||
NM_SET_OUT (out_reread_same, reread_same);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nms_keyfile_writer_connection (NMConnection *connection,
|
||||
const char *existing_path,
|
||||
gboolean force_rename,
|
||||
char **out_path,
|
||||
GError **error)
|
||||
const char *existing_path,
|
||||
gboolean force_rename,
|
||||
char **out_path,
|
||||
NMConnection **out_reread,
|
||||
gboolean *out_reread_same,
|
||||
GError **error)
|
||||
{
|
||||
return _internal_write_connection (connection,
|
||||
nms_keyfile_utils_get_path (),
|
||||
|
|
@ -306,16 +348,20 @@ nms_keyfile_writer_connection (NMConnection *connection,
|
|||
existing_path,
|
||||
force_rename,
|
||||
out_path,
|
||||
out_reread,
|
||||
out_reread_same,
|
||||
error);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nms_keyfile_writer_test_connection (NMConnection *connection,
|
||||
const char *keyfile_dir,
|
||||
uid_t owner_uid,
|
||||
pid_t owner_grp,
|
||||
char **out_path,
|
||||
GError **error)
|
||||
const char *keyfile_dir,
|
||||
uid_t owner_uid,
|
||||
pid_t owner_grp,
|
||||
char **out_path,
|
||||
NMConnection **out_reread,
|
||||
gboolean *out_reread_same,
|
||||
GError **error)
|
||||
{
|
||||
return _internal_write_connection (connection,
|
||||
keyfile_dir,
|
||||
|
|
@ -323,6 +369,8 @@ nms_keyfile_writer_test_connection (NMConnection *connection,
|
|||
NULL,
|
||||
FALSE,
|
||||
out_path,
|
||||
out_reread,
|
||||
out_reread_same,
|
||||
error);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ gboolean nms_keyfile_writer_connection (NMConnection *connection,
|
|||
const char *existing_path,
|
||||
gboolean force_rename,
|
||||
char **out_path,
|
||||
NMConnection **out_reread,
|
||||
gboolean *out_reread_same,
|
||||
GError **error);
|
||||
|
||||
gboolean nms_keyfile_writer_test_connection (NMConnection *connection,
|
||||
|
|
@ -35,6 +37,8 @@ gboolean nms_keyfile_writer_test_connection (NMConnection *connection,
|
|||
uid_t owner_uid,
|
||||
pid_t owner_grp,
|
||||
char **out_path,
|
||||
NMConnection **out_reread,
|
||||
gboolean *out_reread_same,
|
||||
GError **error);
|
||||
|
||||
#endif /* __NMS_KEYFILE_WRITER_H__ */
|
||||
|
|
|
|||
|
|
@ -113,13 +113,25 @@ assert_reread_and_unlink (NMConnection *connection, gboolean normalize_connectio
|
|||
}
|
||||
|
||||
static void
|
||||
write_test_connection (NMConnection *connection, char **testfile)
|
||||
assert_reread_same (NMConnection *connection,
|
||||
NMConnection *reread)
|
||||
{
|
||||
nmtst_assert_connection_verifies_without_normalization (reread);
|
||||
nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
write_test_connection_reread (NMConnection *connection,
|
||||
char **testfile,
|
||||
NMConnection **out_reread,
|
||||
gboolean *out_reread_same)
|
||||
{
|
||||
uid_t owner_uid;
|
||||
gid_t owner_grp;
|
||||
gboolean success;
|
||||
GError *error = NULL;
|
||||
GError **p_error = (nmtst_get_rand_int () % 2) ? &error : NULL;
|
||||
gs_unref_object NMConnection *connection_normalized = NULL;
|
||||
|
||||
g_assert (NM_IS_CONNECTION (connection));
|
||||
g_assert (testfile && !*testfile);
|
||||
|
|
@ -127,12 +139,32 @@ write_test_connection (NMConnection *connection, char **testfile)
|
|||
owner_uid = geteuid ();
|
||||
owner_grp = getegid ();
|
||||
|
||||
success = nms_keyfile_writer_test_connection (connection, TEST_SCRATCH_DIR, owner_uid, owner_grp, testfile, p_error);
|
||||
connection_normalized = nmtst_connection_duplicate_and_normalize (connection);
|
||||
|
||||
success = nms_keyfile_writer_test_connection (connection_normalized,
|
||||
TEST_SCRATCH_DIR,
|
||||
owner_uid,
|
||||
owner_grp,
|
||||
testfile,
|
||||
out_reread,
|
||||
out_reread_same,
|
||||
p_error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (success);
|
||||
g_assert (*testfile && (*testfile)[0]);
|
||||
}
|
||||
|
||||
static void
|
||||
write_test_connection (NMConnection *connection, char **testfile)
|
||||
{
|
||||
gs_unref_object NMConnection *reread = NULL;
|
||||
gboolean reread_same = FALSE;
|
||||
|
||||
write_test_connection_reread (connection, testfile, &reread, &reread_same);
|
||||
assert_reread_same (connection, reread);
|
||||
g_assert (reread_same);
|
||||
}
|
||||
|
||||
static void
|
||||
write_test_connection_and_reread (NMConnection *connection, gboolean normalize_connection)
|
||||
{
|
||||
|
|
@ -161,6 +193,27 @@ keyfile_load_from_file (const char *testfile)
|
|||
return keyfile;
|
||||
}
|
||||
|
||||
static void
|
||||
_setting_copy_property_gbytes (NMConnection *src, NMConnection *dst, const char *setting_name, const char *property_name)
|
||||
{
|
||||
gs_unref_bytes GBytes *blob = NULL;
|
||||
NMSetting *s_src;
|
||||
NMSetting *s_dst;
|
||||
|
||||
g_assert (NM_IS_CONNECTION (src));
|
||||
g_assert (NM_IS_CONNECTION (dst));
|
||||
g_assert (setting_name);
|
||||
g_assert (property_name);
|
||||
|
||||
s_src = nm_connection_get_setting_by_name (src, setting_name);
|
||||
g_assert (NM_IS_SETTING (s_src));
|
||||
s_dst = nm_connection_get_setting_by_name (dst, setting_name);
|
||||
g_assert (NM_IS_SETTING (s_dst));
|
||||
|
||||
g_object_get (s_src, property_name, &blob, NULL);
|
||||
g_object_set (s_dst, property_name, blob, NULL);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
|
|
@ -1639,11 +1692,18 @@ test_write_wired_8021x_tls_connection_path (void)
|
|||
gs_free_error GError *error = NULL;
|
||||
gs_unref_keyfile GKeyFile *keyfile = NULL;
|
||||
gboolean relative = FALSE;
|
||||
gboolean reread_same = FALSE;
|
||||
|
||||
connection = create_wired_tls_connection (NM_SETTING_802_1X_CK_SCHEME_PATH);
|
||||
g_assert (connection != NULL);
|
||||
|
||||
write_test_connection (connection, &testfile);
|
||||
write_test_connection_reread (connection, &testfile, &reread, &reread_same);
|
||||
nmtst_assert_connection_verifies_without_normalization (reread);
|
||||
_setting_copy_property_gbytes (connection, reread, NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_CA_CERT);
|
||||
_setting_copy_property_gbytes (connection, reread, NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_CLIENT_CERT);
|
||||
_setting_copy_property_gbytes (connection, reread, NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PRIVATE_KEY);
|
||||
assert_reread_same (connection, reread);
|
||||
g_clear_object (&reread);
|
||||
|
||||
/* Read the connection back in and compare it to the one we just wrote out */
|
||||
reread = nms_keyfile_reader_from_file (testfile, &error);
|
||||
|
|
@ -1716,6 +1776,7 @@ test_write_wired_8021x_tls_connection_blob (void)
|
|||
char *new_client_cert;
|
||||
char *new_priv_key;
|
||||
const char *uuid;
|
||||
gboolean reread_same = FALSE;
|
||||
gs_free_error GError *error = NULL;
|
||||
GBytes *password_raw = NULL;
|
||||
#define PASSWORD_RAW "password-raw\0test"
|
||||
|
|
@ -1733,7 +1794,13 @@ test_write_wired_8021x_tls_connection_blob (void)
|
|||
NULL);
|
||||
g_bytes_unref (password_raw);
|
||||
|
||||
write_test_connection (connection, &testfile);
|
||||
write_test_connection_reread (connection, &testfile, &reread, &reread_same);
|
||||
nmtst_assert_connection_verifies_without_normalization (reread);
|
||||
_setting_copy_property_gbytes (connection, reread, NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_CA_CERT);
|
||||
_setting_copy_property_gbytes (connection, reread, NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_CLIENT_CERT);
|
||||
_setting_copy_property_gbytes (connection, reread, NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PRIVATE_KEY);
|
||||
assert_reread_same (connection, reread);
|
||||
g_clear_object (&reread);
|
||||
|
||||
/* Check that the new certs got written out */
|
||||
s_con = nm_connection_get_setting_connection (connection);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue