|
|
f86c11 |
From 861d9f8e1593c573bb04572b1f89f83500df85df Mon Sep 17 00:00:00 2001
|
|
|
f86c11 |
From: Thomas Haller <thaller@redhat.com>
|
|
|
f86c11 |
Date: Wed, 12 Dec 2018 07:23:51 +0100
|
|
|
f86c11 |
Subject: [PATCH 01/10] shared: add nm_utils_error_is_notfound() helper
|
|
|
f86c11 |
|
|
|
f86c11 |
Inspired by bolt's bolt_err_notfound() in "bolt-error.c".
|
|
|
f86c11 |
|
|
|
f86c11 |
(cherry picked from commit b7fc328a66dd66f3f9d9f702e8b4a6d505ea3560)
|
|
|
f86c11 |
(cherry picked from commit d0f516a2bda68b22c456ef945e1c1fe8e36986ba)
|
|
|
f86c11 |
---
|
|
|
f86c11 |
shared/nm-utils/nm-shared-utils.c | 23 ++++++++++++++++++-----
|
|
|
f86c11 |
shared/nm-utils/nm-shared-utils.h | 2 ++
|
|
|
f86c11 |
2 files changed, 20 insertions(+), 5 deletions(-)
|
|
|
f86c11 |
|
|
|
f86c11 |
diff --git a/shared/nm-utils/nm-shared-utils.c b/shared/nm-utils/nm-shared-utils.c
|
|
|
f86c11 |
index 022c06528..0d4696cda 100644
|
|
|
f86c11 |
--- a/shared/nm-utils/nm-shared-utils.c
|
|
|
f86c11 |
+++ b/shared/nm-utils/nm-shared-utils.c
|
|
|
f86c11 |
@@ -1037,11 +1037,24 @@ nm_utils_error_is_cancelled (GError *error,
|
|
|
f86c11 |
gboolean consider_is_disposing)
|
|
|
f86c11 |
{
|
|
|
f86c11 |
if (error) {
|
|
|
f86c11 |
- if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
|
f86c11 |
- return TRUE;
|
|
|
f86c11 |
- if ( consider_is_disposing
|
|
|
f86c11 |
- && g_error_matches (error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING))
|
|
|
f86c11 |
- return TRUE;
|
|
|
f86c11 |
+ if (error->domain == G_IO_ERROR)
|
|
|
f86c11 |
+ return NM_IN_SET (error->code, G_IO_ERROR_CANCELLED);
|
|
|
f86c11 |
+ if (consider_is_disposing) {
|
|
|
f86c11 |
+ if (error->domain == NM_UTILS_ERROR)
|
|
|
f86c11 |
+ return NM_IN_SET (error->code, NM_UTILS_ERROR_CANCELLED_DISPOSING);
|
|
|
f86c11 |
+ }
|
|
|
f86c11 |
+ }
|
|
|
f86c11 |
+ return FALSE;
|
|
|
f86c11 |
+}
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+gboolean
|
|
|
f86c11 |
+nm_utils_error_is_notfound (GError *error)
|
|
|
f86c11 |
+{
|
|
|
f86c11 |
+ if (error) {
|
|
|
f86c11 |
+ if (error->domain == G_IO_ERROR)
|
|
|
f86c11 |
+ return NM_IN_SET (error->code, G_IO_ERROR_NOT_FOUND);
|
|
|
f86c11 |
+ if (error->domain == G_FILE_ERROR)
|
|
|
f86c11 |
+ return NM_IN_SET (error->code, G_FILE_ERROR_NOENT);
|
|
|
f86c11 |
}
|
|
|
f86c11 |
return FALSE;
|
|
|
f86c11 |
}
|
|
|
f86c11 |
diff --git a/shared/nm-utils/nm-shared-utils.h b/shared/nm-utils/nm-shared-utils.h
|
|
|
f86c11 |
index f1ff71e3b..20311d08a 100644
|
|
|
f86c11 |
--- a/shared/nm-utils/nm-shared-utils.h
|
|
|
f86c11 |
+++ b/shared/nm-utils/nm-shared-utils.h
|
|
|
f86c11 |
@@ -586,6 +586,8 @@ void nm_utils_error_set_cancelled (GError **error,
|
|
|
f86c11 |
gboolean nm_utils_error_is_cancelled (GError *error,
|
|
|
f86c11 |
gboolean consider_is_disposing);
|
|
|
f86c11 |
|
|
|
f86c11 |
+gboolean nm_utils_error_is_notfound (GError *error);
|
|
|
f86c11 |
+
|
|
|
f86c11 |
static inline void
|
|
|
f86c11 |
nm_utils_error_set_literal (GError **error, int error_code, const char *literal)
|
|
|
f86c11 |
{
|
|
|
f86c11 |
--
|
|
|
f86c11 |
2.19.2
|
|
|
f86c11 |
|
|
|
f86c11 |
|
|
|
f86c11 |
From cbc815117511279cbd976658313f59c43debf97a Mon Sep 17 00:00:00 2001
|
|
|
f86c11 |
From: Thomas Haller <thaller@redhat.com>
|
|
|
f86c11 |
Date: Wed, 12 Dec 2018 07:29:38 +0100
|
|
|
f86c11 |
Subject: [PATCH 02/10] core: fix printing error for failure reading secret-key
|
|
|
f86c11 |
|
|
|
f86c11 |
g_file_get_contents() fails with G_FILE_ERROR, G_FILE_ERROR_NOENT when the
|
|
|
f86c11 |
file does not exist.
|
|
|
f86c11 |
|
|
|
f86c11 |
That wasn't obvious to me, nm_utils_error_is_notfound() to the rescue.
|
|
|
f86c11 |
|
|
|
f86c11 |
Fixes: dbcb1d6d97c609d53dac4a86dc45d0e2595d8857
|
|
|
f86c11 |
(cherry picked from commit 7b9cd2e3d7206cc895fc2e27df3b7bd987da6ef5)
|
|
|
f86c11 |
(cherry picked from commit cfc0c6d5146513fba856894506542facde9fc914)
|
|
|
f86c11 |
---
|
|
|
f86c11 |
src/nm-core-utils.c | 2 +-
|
|
|
f86c11 |
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
f86c11 |
|
|
|
f86c11 |
diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c
|
|
|
f86c11 |
index f0efee461..44f0549e6 100644
|
|
|
f86c11 |
--- a/src/nm-core-utils.c
|
|
|
f86c11 |
+++ b/src/nm-core-utils.c
|
|
|
f86c11 |
@@ -2735,7 +2735,7 @@ _secret_key_read (guint8 **out_secret_key,
|
|
|
f86c11 |
nm_log_warn (LOGD_CORE, "secret-key: too short secret key in \"%s\" (generate new key)", NMSTATEDIR "/secret_key");
|
|
|
f86c11 |
nm_clear_g_free (&secret_key);
|
|
|
f86c11 |
} else {
|
|
|
f86c11 |
- if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) {
|
|
|
f86c11 |
+ if (!nm_utils_error_is_notfound (error)) {
|
|
|
f86c11 |
nm_log_warn (LOGD_CORE, "secret-key: failure reading secret key in \"%s\": %s (generate new key)",
|
|
|
f86c11 |
NMSTATEDIR "/secret_key", error->message);
|
|
|
f86c11 |
}
|
|
|
f86c11 |
--
|
|
|
f86c11 |
2.19.2
|
|
|
f86c11 |
|
|
|
f86c11 |
|
|
|
f86c11 |
From 3484e98ce766858a2cb9c33b91e955140b93e54a Mon Sep 17 00:00:00 2001
|
|
|
f86c11 |
From: Thomas Haller <thaller@redhat.com>
|
|
|
f86c11 |
Date: Wed, 12 Dec 2018 07:34:34 +0100
|
|
|
f86c11 |
Subject: [PATCH 03/10] core: use define for secret_key filename
|
|
|
f86c11 |
|
|
|
f86c11 |
(cherry picked from commit 2c7c333297a57d55efb2bd5a447391ea77861423)
|
|
|
f86c11 |
(cherry picked from commit 0b451b4c879c3c8178b235a5d9b2b669f4696f81)
|
|
|
f86c11 |
---
|
|
|
f86c11 |
src/nm-core-utils.c | 14 ++++++++------
|
|
|
f86c11 |
1 file changed, 8 insertions(+), 6 deletions(-)
|
|
|
f86c11 |
|
|
|
f86c11 |
diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c
|
|
|
f86c11 |
index 44f0549e6..ab433b292 100644
|
|
|
f86c11 |
--- a/src/nm-core-utils.c
|
|
|
f86c11 |
+++ b/src/nm-core-utils.c
|
|
|
f86c11 |
@@ -2716,6 +2716,8 @@ nm_utils_machine_id_is_fake (void)
|
|
|
f86c11 |
|
|
|
f86c11 |
/*****************************************************************************/
|
|
|
f86c11 |
|
|
|
f86c11 |
+#define SECRET_KEY_FILE NMSTATEDIR"/secret_key"
|
|
|
f86c11 |
+
|
|
|
f86c11 |
static gboolean
|
|
|
f86c11 |
_secret_key_read (guint8 **out_secret_key,
|
|
|
f86c11 |
gsize *out_key_len)
|
|
|
f86c11 |
@@ -2726,18 +2728,18 @@ _secret_key_read (guint8 **out_secret_key,
|
|
|
f86c11 |
gs_free_error GError *error = NULL;
|
|
|
f86c11 |
|
|
|
f86c11 |
/* Let's try to load a saved secret key first. */
|
|
|
f86c11 |
- if (g_file_get_contents (NMSTATEDIR "/secret_key", (char **) &secret_key, &key_len, &error)) {
|
|
|
f86c11 |
+ if (g_file_get_contents (SECRET_KEY_FILE, (char **) &secret_key, &key_len, &error)) {
|
|
|
f86c11 |
if (key_len >= 16)
|
|
|
f86c11 |
goto out;
|
|
|
f86c11 |
|
|
|
f86c11 |
/* the secret key is borked. Log a warning, but proceed below to generate
|
|
|
f86c11 |
* a new one. */
|
|
|
f86c11 |
- nm_log_warn (LOGD_CORE, "secret-key: too short secret key in \"%s\" (generate new key)", NMSTATEDIR "/secret_key");
|
|
|
f86c11 |
+ nm_log_warn (LOGD_CORE, "secret-key: too short secret key in \"%s\" (generate new key)", SECRET_KEY_FILE);
|
|
|
f86c11 |
nm_clear_g_free (&secret_key);
|
|
|
f86c11 |
} else {
|
|
|
f86c11 |
if (!nm_utils_error_is_notfound (error)) {
|
|
|
f86c11 |
nm_log_warn (LOGD_CORE, "secret-key: failure reading secret key in \"%s\": %s (generate new key)",
|
|
|
f86c11 |
- NMSTATEDIR "/secret_key", error->message);
|
|
|
f86c11 |
+ SECRET_KEY_FILE, error->message);
|
|
|
f86c11 |
}
|
|
|
f86c11 |
g_clear_error (&error);
|
|
|
f86c11 |
}
|
|
|
f86c11 |
@@ -2763,9 +2765,9 @@ _secret_key_read (guint8 **out_secret_key,
|
|
|
f86c11 |
goto out;
|
|
|
f86c11 |
}
|
|
|
f86c11 |
|
|
|
f86c11 |
- if (!nm_utils_file_set_contents (NMSTATEDIR "/secret_key", (char *) secret_key, key_len, 0077, &error)) {
|
|
|
f86c11 |
+ if (!nm_utils_file_set_contents (SECRET_KEY_FILE, (char *) secret_key, key_len, 0077, &error)) {
|
|
|
f86c11 |
nm_log_warn (LOGD_CORE, "secret-key: failure to persist secret key in \"%s\" (%s) (use non-persistent key)",
|
|
|
f86c11 |
- NMSTATEDIR "/secret_key", error->message);
|
|
|
f86c11 |
+ SECRET_KEY_FILE, error->message);
|
|
|
f86c11 |
success = FALSE;
|
|
|
f86c11 |
goto out;
|
|
|
f86c11 |
}
|
|
|
f86c11 |
@@ -2827,7 +2829,7 @@ nm_utils_secret_key_get_timestamp (void)
|
|
|
f86c11 |
if (!nm_utils_secret_key_get (&key, &key_len))
|
|
|
f86c11 |
return 0;
|
|
|
f86c11 |
|
|
|
f86c11 |
- if (stat (NMSTATEDIR "/secret_key", &stat_buf) != 0)
|
|
|
f86c11 |
+ if (stat (SECRET_KEY_FILE, &stat_buf) != 0)
|
|
|
f86c11 |
return 0;
|
|
|
f86c11 |
|
|
|
f86c11 |
return stat_buf.st_mtim.tv_sec;
|
|
|
f86c11 |
--
|
|
|
f86c11 |
2.19.2
|
|
|
f86c11 |
|
|
|
f86c11 |
|
|
|
f86c11 |
From 4ac908e32ac7c79a2ff7781e702d5d0f688bbcb3 Mon Sep 17 00:00:00 2001
|
|
|
f86c11 |
From: Thomas Haller <thaller@redhat.com>
|
|
|
f86c11 |
Date: Wed, 5 Dec 2018 13:42:33 +0100
|
|
|
f86c11 |
Subject: [PATCH 04/10] core: combine secret-key with /etc/machine-id
|
|
|
f86c11 |
|
|
|
f86c11 |
NetworkManager loads (and generates) a secret key as
|
|
|
f86c11 |
"/var/lib/NetworkManager/secret_key".
|
|
|
f86c11 |
|
|
|
f86c11 |
The secret key is used for seeding a per-host component when generating
|
|
|
f86c11 |
hashed, stable data. For example, it contributes to "ipv4.dhcp-client-id=duid"
|
|
|
f86c11 |
"ipv6.addr-gen-mode=stable-privacy", "ethernet.cloned-mac-address=stable", etc.
|
|
|
f86c11 |
As such, it corresponds to the identity of the host.
|
|
|
f86c11 |
|
|
|
f86c11 |
Also "/etc/machine-id" is the host's identity. When cloning a virtual machine,
|
|
|
f86c11 |
it may be a good idea to generate a new "/etc/machine-id", at least in those
|
|
|
f86c11 |
cases where the VM's identity shall be different. Systemd provides various
|
|
|
f86c11 |
mechanisms for doing that, like accepting a new machine-id via kernel command line.
|
|
|
f86c11 |
For the same reason, the user should also regenerate a new NetworkManager's
|
|
|
f86c11 |
secrey key when the host's identity shall change. However, that is less obvious,
|
|
|
f86c11 |
less understood and less documented.
|
|
|
f86c11 |
|
|
|
f86c11 |
Support and use a new variant of secret key. This secret key is combined
|
|
|
f86c11 |
with "/etc/machine-id" by sha256 hashing it together. That means, when the
|
|
|
f86c11 |
user generates a new machine-id, NetworkManager's per-host key also changes.
|
|
|
f86c11 |
|
|
|
f86c11 |
Since we don't want to change behavior for existing installations, we
|
|
|
f86c11 |
only do this when generating a new secret key file. For that, we encode
|
|
|
f86c11 |
a version tag inside the "/var/lib/NetworkManager/secret_key" file.
|
|
|
f86c11 |
|
|
|
f86c11 |
Note that this is all abstracted by nm_utils_secret_key_get(). For
|
|
|
f86c11 |
version 2 secret-keys, it internally combines the secret_key file with
|
|
|
f86c11 |
machine-id (via sha256). The advantage is that callers don't care that
|
|
|
f86c11 |
the secret-key now also contains the machine-id. Also, since we want to
|
|
|
f86c11 |
stick to the previous behavior if we have an old secret-key, this is
|
|
|
f86c11 |
nicely abstracted. Otherwise, the caller would not only need to handle
|
|
|
f86c11 |
two per-host parts, but it would also need to check the version to
|
|
|
f86c11 |
determine whether the machine-id should be explicitly included.
|
|
|
f86c11 |
At this point, nm_utils_secret_key_get() should be renamed to
|
|
|
f86c11 |
nm_utils_host_key_get().
|
|
|
f86c11 |
|
|
|
f86c11 |
(cherry picked from commit deb19abf22eca93bdb57f52d162b5d81f1a85fc1)
|
|
|
f86c11 |
(cherry picked from commit 7b68a574e9b4e242062db50ca36a8e77822cd646)
|
|
|
f86c11 |
---
|
|
|
f86c11 |
src/nm-core-utils.c | 185 +++++++++++++++++++++++++++++++++-----------
|
|
|
f86c11 |
1 file changed, 138 insertions(+), 47 deletions(-)
|
|
|
f86c11 |
|
|
|
f86c11 |
diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c
|
|
|
f86c11 |
index ab433b292..a379e405f 100644
|
|
|
f86c11 |
--- a/src/nm-core-utils.c
|
|
|
f86c11 |
+++ b/src/nm-core-utils.c
|
|
|
f86c11 |
@@ -41,6 +41,7 @@
|
|
|
f86c11 |
#include "nm-utils/nm-random-utils.h"
|
|
|
f86c11 |
#include "nm-utils/nm-io-utils.h"
|
|
|
f86c11 |
#include "nm-utils/unaligned.h"
|
|
|
f86c11 |
+#include "nm-utils/nm-secret-utils.h"
|
|
|
f86c11 |
#include "nm-utils.h"
|
|
|
f86c11 |
#include "nm-core-internal.h"
|
|
|
f86c11 |
#include "nm-setting-connection.h"
|
|
|
f86c11 |
@@ -2608,7 +2609,7 @@ _uuid_data_init (UuidData *uuid_data,
|
|
|
f86c11 |
/*****************************************************************************/
|
|
|
f86c11 |
|
|
|
f86c11 |
static const UuidData *
|
|
|
f86c11 |
-_machine_id_get (void)
|
|
|
f86c11 |
+_machine_id_get (gboolean allow_fake)
|
|
|
f86c11 |
{
|
|
|
f86c11 |
static const UuidData *volatile p_uuid_data;
|
|
|
f86c11 |
const UuidData *d;
|
|
|
f86c11 |
@@ -2650,6 +2651,12 @@ again:
|
|
|
f86c11 |
const char *hash_seed;
|
|
|
f86c11 |
gsize seed_len;
|
|
|
f86c11 |
|
|
|
f86c11 |
+ if (!allow_fake) {
|
|
|
f86c11 |
+ /* we don't allow generating (and memoizing) a fake key.
|
|
|
f86c11 |
+ * Signal that no valid machine-id exists. */
|
|
|
f86c11 |
+ return NULL;
|
|
|
f86c11 |
+ }
|
|
|
f86c11 |
+
|
|
|
f86c11 |
if (nm_utils_secret_key_get (&seed_bin, &seed_len)) {
|
|
|
f86c11 |
/* we have no valid machine-id. Generate a fake one by hashing
|
|
|
f86c11 |
* the secret-key. This key is commonly persisted, so it should be
|
|
|
f86c11 |
@@ -2699,84 +2706,168 @@ again:
|
|
|
f86c11 |
const char *
|
|
|
f86c11 |
nm_utils_machine_id_str (void)
|
|
|
f86c11 |
{
|
|
|
f86c11 |
- return _machine_id_get ()->str;
|
|
|
f86c11 |
+ return _machine_id_get (TRUE)->str;
|
|
|
f86c11 |
}
|
|
|
f86c11 |
|
|
|
f86c11 |
const NMUuid *
|
|
|
f86c11 |
nm_utils_machine_id_bin (void)
|
|
|
f86c11 |
{
|
|
|
f86c11 |
- return &_machine_id_get ()->bin;
|
|
|
f86c11 |
+ return &_machine_id_get (TRUE)->bin;
|
|
|
f86c11 |
}
|
|
|
f86c11 |
|
|
|
f86c11 |
gboolean
|
|
|
f86c11 |
nm_utils_machine_id_is_fake (void)
|
|
|
f86c11 |
{
|
|
|
f86c11 |
- return _machine_id_get ()->is_fake;
|
|
|
f86c11 |
+ return _machine_id_get (TRUE)->is_fake;
|
|
|
f86c11 |
}
|
|
|
f86c11 |
|
|
|
f86c11 |
/*****************************************************************************/
|
|
|
f86c11 |
|
|
|
f86c11 |
+/* prefix for version2 secret key. The secret key is hashed with /etc/machine-id. */
|
|
|
f86c11 |
+#define SECRET_KEY_V2_PREFIX "nm-v2:"
|
|
|
f86c11 |
#define SECRET_KEY_FILE NMSTATEDIR"/secret_key"
|
|
|
f86c11 |
|
|
|
f86c11 |
-static gboolean
|
|
|
f86c11 |
-_secret_key_read (guint8 **out_secret_key,
|
|
|
f86c11 |
- gsize *out_key_len)
|
|
|
f86c11 |
+static const guint8 *
|
|
|
f86c11 |
+_secret_key_hash_v2 (const guint8 *seed_arr,
|
|
|
f86c11 |
+ gsize seed_len,
|
|
|
f86c11 |
+ guint8 *out_digest /* 32 bytes (NM_UTILS_CHECKSUM_LENGTH_SHA256) */)
|
|
|
f86c11 |
{
|
|
|
f86c11 |
- guint8 *secret_key;
|
|
|
f86c11 |
- gboolean success = TRUE;
|
|
|
f86c11 |
- gsize key_len;
|
|
|
f86c11 |
- gs_free_error GError *error = NULL;
|
|
|
f86c11 |
+ nm_auto_free_checksum GChecksum *sum = g_checksum_new (G_CHECKSUM_SHA256);
|
|
|
f86c11 |
+ const UuidData *machine_id_data;
|
|
|
f86c11 |
+ char slen[100];
|
|
|
f86c11 |
|
|
|
f86c11 |
- /* Let's try to load a saved secret key first. */
|
|
|
f86c11 |
- if (g_file_get_contents (SECRET_KEY_FILE, (char **) &secret_key, &key_len, &error)) {
|
|
|
f86c11 |
- if (key_len >= 16)
|
|
|
f86c11 |
- goto out;
|
|
|
f86c11 |
+ /*
|
|
|
f86c11 |
+ (stat -c '%s' /var/lib/NetworkManager/secret_key;
|
|
|
f86c11 |
+ echo -n ' ';
|
|
|
f86c11 |
+ cat /var/lib/NetworkManager/secret_key;
|
|
|
f86c11 |
+ cat /etc/machine-id | tr -d '\n' | sed -n 's/[a-f0-9-]/\0/pg') | sha256sum
|
|
|
f86c11 |
+ */
|
|
|
f86c11 |
|
|
|
f86c11 |
- /* the secret key is borked. Log a warning, but proceed below to generate
|
|
|
f86c11 |
- * a new one. */
|
|
|
f86c11 |
- nm_log_warn (LOGD_CORE, "secret-key: too short secret key in \"%s\" (generate new key)", SECRET_KEY_FILE);
|
|
|
f86c11 |
- nm_clear_g_free (&secret_key);
|
|
|
f86c11 |
- } else {
|
|
|
f86c11 |
+ nm_sprintf_buf (slen, "%"G_GSIZE_FORMAT" ", seed_len);
|
|
|
f86c11 |
+ g_checksum_update (sum, (const guchar *) slen, strlen (slen));
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+ g_checksum_update (sum, (const guchar *) seed_arr, seed_len);
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+ machine_id_data = _machine_id_get (FALSE);
|
|
|
f86c11 |
+ if ( machine_id_data
|
|
|
f86c11 |
+ && !machine_id_data->is_fake)
|
|
|
f86c11 |
+ g_checksum_update (sum, (const guchar *) machine_id_data->str, strlen (machine_id_data->str));
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+ nm_utils_checksum_get_digest_len (sum, out_digest, NM_UTILS_CHECKSUM_LENGTH_SHA256);
|
|
|
f86c11 |
+ return out_digest;
|
|
|
f86c11 |
+}
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+static gboolean
|
|
|
f86c11 |
+_secret_key_read (guint8 **out_key,
|
|
|
f86c11 |
+ gsize *out_key_len)
|
|
|
f86c11 |
+{
|
|
|
f86c11 |
+#define SECRET_KEY_LEN 32u
|
|
|
f86c11 |
+ guint8 sha256_digest[NM_UTILS_CHECKSUM_LENGTH_SHA256];
|
|
|
f86c11 |
+ nm_auto_clear_secret_ptr NMSecretPtr file_content = { 0 };
|
|
|
f86c11 |
+ const guint8 *secret_arr;
|
|
|
f86c11 |
+ gsize secret_len;
|
|
|
f86c11 |
+ GError *error = NULL;
|
|
|
f86c11 |
+ gboolean success;
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+ if (nm_utils_file_get_contents (-1,
|
|
|
f86c11 |
+ SECRET_KEY_FILE,
|
|
|
f86c11 |
+ 10*1024,
|
|
|
f86c11 |
+ NM_UTILS_FILE_GET_CONTENTS_FLAG_SECRET,
|
|
|
f86c11 |
+ (char **) &file_content.str,
|
|
|
f86c11 |
+ &file_content.len,
|
|
|
f86c11 |
+ &error) < 0) {
|
|
|
f86c11 |
if (!nm_utils_error_is_notfound (error)) {
|
|
|
f86c11 |
nm_log_warn (LOGD_CORE, "secret-key: failure reading secret key in \"%s\": %s (generate new key)",
|
|
|
f86c11 |
SECRET_KEY_FILE, error->message);
|
|
|
f86c11 |
}
|
|
|
f86c11 |
g_clear_error (&error);
|
|
|
f86c11 |
- }
|
|
|
f86c11 |
-
|
|
|
f86c11 |
- /* RFC7217 mandates the key SHOULD be at least 128 bits.
|
|
|
f86c11 |
- * Let's use twice as much. */
|
|
|
f86c11 |
- key_len = 32;
|
|
|
f86c11 |
- secret_key = g_malloc (key_len + 1);
|
|
|
f86c11 |
-
|
|
|
f86c11 |
- /* the secret-key is binary. Still, ensure that it's NULL terminated, just like
|
|
|
f86c11 |
- * g_file_set_contents() does. */
|
|
|
f86c11 |
- secret_key[32] = '\0';
|
|
|
f86c11 |
+ } else if ( file_content.len >= NM_STRLEN (SECRET_KEY_V2_PREFIX) + SECRET_KEY_LEN
|
|
|
f86c11 |
+ && memcmp (file_content.bin, SECRET_KEY_V2_PREFIX, NM_STRLEN (SECRET_KEY_V2_PREFIX)) == 0) {
|
|
|
f86c11 |
+ /* for this type of secret key, we require a prefix followed at least SECRET_KEY_LEN (32) bytes. We
|
|
|
f86c11 |
+ * (also) do that, because older versions of NetworkManager wrote exactly 32 bytes without
|
|
|
f86c11 |
+ * prefix, so we won't wrongly interpret such legacy keys as v2 (if they accidentally have
|
|
|
f86c11 |
+ * a SECRET_KEY_V2_PREFIX prefix, they'll still have the wrong size).
|
|
|
f86c11 |
+ *
|
|
|
f86c11 |
+ * Note that below we generate the random seed in base64 encoding. But that is only done
|
|
|
f86c11 |
+ * to write an ASCII file. There is no base64 decoding and the ASCII is hashed as-is.
|
|
|
f86c11 |
+ * We would accept any binary data just as well (provided a suitable prefix and at least
|
|
|
f86c11 |
+ * 32 bytes).
|
|
|
f86c11 |
+ *
|
|
|
f86c11 |
+ * Note that when hashing the v2 content, we also hash the prefix. There is no strong reason,
|
|
|
f86c11 |
+ * except that it seems simpler not to distinguish between the v2 prefix and the content.
|
|
|
f86c11 |
+ * It's all just part of the seed. */
|
|
|
f86c11 |
|
|
|
f86c11 |
- if (!nm_utils_random_bytes (secret_key, key_len)) {
|
|
|
f86c11 |
- nm_log_warn (LOGD_CORE, "secret-key: failure to generate good random data for secret-key (use non-persistent key)");
|
|
|
f86c11 |
- success = FALSE;
|
|
|
f86c11 |
+ secret_arr = _secret_key_hash_v2 (file_content.bin, file_content.len, sha256_digest);
|
|
|
f86c11 |
+ secret_len = NM_UTILS_CHECKSUM_LENGTH_SHA256;
|
|
|
f86c11 |
+ success = TRUE;
|
|
|
f86c11 |
goto out;
|
|
|
f86c11 |
- }
|
|
|
f86c11 |
-
|
|
|
f86c11 |
- if (nm_utils_get_testing ()) {
|
|
|
f86c11 |
- /* for test code, we don't write the generated secret-key to disk. */
|
|
|
f86c11 |
- success = FALSE;
|
|
|
f86c11 |
+ } else if (file_content.len >= 16) {
|
|
|
f86c11 |
+ secret_arr = file_content.bin;
|
|
|
f86c11 |
+ secret_len = file_content.len;
|
|
|
f86c11 |
+ success = TRUE;
|
|
|
f86c11 |
goto out;
|
|
|
f86c11 |
+ } else {
|
|
|
f86c11 |
+ /* the secret key is borked. Log a warning, but proceed below to generate
|
|
|
f86c11 |
+ * a new one. */
|
|
|
f86c11 |
+ nm_log_warn (LOGD_CORE, "secret-key: too short secret key in \"%s\" (generate new key)", SECRET_KEY_FILE);
|
|
|
f86c11 |
}
|
|
|
f86c11 |
|
|
|
f86c11 |
- if (!nm_utils_file_set_contents (SECRET_KEY_FILE, (char *) secret_key, key_len, 0077, &error)) {
|
|
|
f86c11 |
- nm_log_warn (LOGD_CORE, "secret-key: failure to persist secret key in \"%s\" (%s) (use non-persistent key)",
|
|
|
f86c11 |
- SECRET_KEY_FILE, error->message);
|
|
|
f86c11 |
- success = FALSE;
|
|
|
f86c11 |
- goto out;
|
|
|
f86c11 |
+ /* generate and persist new key */
|
|
|
f86c11 |
+ {
|
|
|
f86c11 |
+#define SECRET_KEY_LEN_BASE64 ((((SECRET_KEY_LEN / 3) + 1) * 4) + 4)
|
|
|
f86c11 |
+ guint8 rnd_buf[SECRET_KEY_LEN];
|
|
|
f86c11 |
+ guint8 new_content[NM_STRLEN (SECRET_KEY_V2_PREFIX) + SECRET_KEY_LEN_BASE64];
|
|
|
f86c11 |
+ int base64_state = 0;
|
|
|
f86c11 |
+ int base64_save = 0;
|
|
|
f86c11 |
+ gsize len;
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+ success = nm_utils_random_bytes (rnd_buf, sizeof (rnd_buf));
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+ /* Our key is really binary data. But since we anyway generate a random seed
|
|
|
f86c11 |
+ * (with 32 random bytes), don't write it in binary, but instead create
|
|
|
f86c11 |
+ * an pure ASCII (base64) representation. Note that the ASCII will still be taken
|
|
|
f86c11 |
+ * as-is (no base64 decoding is done). The sole purpose is to write a ASCII file
|
|
|
f86c11 |
+ * instead of a binary. The content is gibberish either way. */
|
|
|
f86c11 |
+ memcpy (new_content, SECRET_KEY_V2_PREFIX, NM_STRLEN (SECRET_KEY_V2_PREFIX));
|
|
|
f86c11 |
+ len = NM_STRLEN (SECRET_KEY_V2_PREFIX);
|
|
|
f86c11 |
+ len += g_base64_encode_step (rnd_buf,
|
|
|
f86c11 |
+ sizeof (rnd_buf),
|
|
|
f86c11 |
+ FALSE,
|
|
|
f86c11 |
+ (char *) &new_content[len],
|
|
|
f86c11 |
+ &base64_state,
|
|
|
f86c11 |
+ &base64_save);
|
|
|
f86c11 |
+ len += g_base64_encode_close (FALSE,
|
|
|
f86c11 |
+ (char *) &new_content[len],
|
|
|
f86c11 |
+ &base64_state,
|
|
|
f86c11 |
+ &base64_save);
|
|
|
f86c11 |
+ nm_assert (len <= sizeof (new_content));
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+ secret_arr = _secret_key_hash_v2 (new_content, len, sha256_digest);
|
|
|
f86c11 |
+ secret_len = NM_UTILS_CHECKSUM_LENGTH_SHA256;
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+ if (!success)
|
|
|
f86c11 |
+ nm_log_warn (LOGD_CORE, "secret-key: failure to generate good random data for secret-key (use non-persistent key)");
|
|
|
f86c11 |
+ else if (nm_utils_get_testing ()) {
|
|
|
f86c11 |
+ /* for test code, we don't write the generated secret-key to disk. */
|
|
|
f86c11 |
+ } else if (!nm_utils_file_set_contents (SECRET_KEY_FILE,
|
|
|
f86c11 |
+ (const char *) new_content,
|
|
|
f86c11 |
+ len,
|
|
|
f86c11 |
+ 0077,
|
|
|
f86c11 |
+ &error)) {
|
|
|
f86c11 |
+ nm_log_warn (LOGD_CORE, "secret-key: failure to persist secret key in \"%s\" (%s) (use non-persistent key)",
|
|
|
f86c11 |
+ SECRET_KEY_FILE, error->message);
|
|
|
f86c11 |
+ g_clear_error (&error);
|
|
|
f86c11 |
+ success = FALSE;
|
|
|
f86c11 |
+ } else
|
|
|
f86c11 |
+ nm_log_dbg (LOGD_CORE, "secret-key: persist new secret key to \"%s\"", SECRET_KEY_FILE);
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+ nm_explicit_bzero (rnd_buf, sizeof (rnd_buf));
|
|
|
f86c11 |
+ nm_explicit_bzero (new_content, sizeof (new_content));
|
|
|
f86c11 |
}
|
|
|
f86c11 |
|
|
|
f86c11 |
out:
|
|
|
f86c11 |
- /* regardless of success or failue, we always return a secret-key. The
|
|
|
f86c11 |
- * caller may choose to ignore the error and proceed. */
|
|
|
f86c11 |
- *out_key_len = key_len;
|
|
|
f86c11 |
- *out_secret_key = secret_key;
|
|
|
f86c11 |
+ *out_key_len = secret_len;
|
|
|
f86c11 |
+ *out_key = nm_memdup (secret_arr, secret_len);
|
|
|
f86c11 |
return success;
|
|
|
f86c11 |
}
|
|
|
f86c11 |
|
|
|
f86c11 |
--
|
|
|
f86c11 |
2.19.2
|
|
|
f86c11 |
|
|
|
f86c11 |
|
|
|
f86c11 |
From adf0a12121b5adb9a47f9ca2e84a29597115c5a7 Mon Sep 17 00:00:00 2001
|
|
|
f86c11 |
From: Thomas Haller <thaller@redhat.com>
|
|
|
f86c11 |
Date: Tue, 11 Dec 2018 18:18:17 +0100
|
|
|
f86c11 |
Subject: [PATCH 05/10] core: fix race creating secret-key
|
|
|
f86c11 |
|
|
|
f86c11 |
Reading the secret key may result in generating and
|
|
|
f86c11 |
writing a new key to disk.
|
|
|
f86c11 |
|
|
|
f86c11 |
Do that under the lock.
|
|
|
f86c11 |
|
|
|
f86c11 |
(cherry picked from commit bc9f18c609b7aac84110b37ec280cb012364ecf4)
|
|
|
f86c11 |
(cherry picked from commit db535b693afc25f9d42cbd9178b624b67f080297)
|
|
|
f86c11 |
---
|
|
|
f86c11 |
src/nm-core-utils.c | 13 ++++---------
|
|
|
f86c11 |
1 file changed, 4 insertions(+), 9 deletions(-)
|
|
|
f86c11 |
|
|
|
f86c11 |
diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c
|
|
|
f86c11 |
index a379e405f..c3d2e3c2a 100644
|
|
|
f86c11 |
--- a/src/nm-core-utils.c
|
|
|
f86c11 |
+++ b/src/nm-core-utils.c
|
|
|
f86c11 |
@@ -2872,7 +2872,7 @@ out:
|
|
|
f86c11 |
}
|
|
|
f86c11 |
|
|
|
f86c11 |
typedef struct {
|
|
|
f86c11 |
- const guint8 *secret_key;
|
|
|
f86c11 |
+ guint8 *secret_key;
|
|
|
f86c11 |
gsize key_len;
|
|
|
f86c11 |
bool is_good:1;
|
|
|
f86c11 |
} SecretKeyData;
|
|
|
f86c11 |
@@ -2887,19 +2887,14 @@ nm_utils_secret_key_get (const guint8 **out_secret_key,
|
|
|
f86c11 |
again:
|
|
|
f86c11 |
secret_key = g_atomic_pointer_get (&secret_key_static);
|
|
|
f86c11 |
if (G_UNLIKELY (!secret_key)) {
|
|
|
f86c11 |
- static gsize init_value = 0;
|
|
|
f86c11 |
static SecretKeyData secret_key_data;
|
|
|
f86c11 |
- gboolean tmp_success;
|
|
|
f86c11 |
- gs_free guint8 *tmp_secret_key = NULL;
|
|
|
f86c11 |
- gsize tmp_key_len;
|
|
|
f86c11 |
+ static gsize init_value = 0;
|
|
|
f86c11 |
|
|
|
f86c11 |
- tmp_success = _secret_key_read (&tmp_secret_key, &tmp_key_len);
|
|
|
f86c11 |
if (!g_once_init_enter (&init_value))
|
|
|
f86c11 |
goto again;
|
|
|
f86c11 |
|
|
|
f86c11 |
- secret_key_data.secret_key = g_steal_pointer (&tmp_secret_key);
|
|
|
f86c11 |
- secret_key_data.key_len = tmp_key_len;
|
|
|
f86c11 |
- secret_key_data.is_good = tmp_success;
|
|
|
f86c11 |
+ secret_key_data.is_good = _secret_key_read (&secret_key_data.secret_key,
|
|
|
f86c11 |
+ &secret_key_data.key_len);
|
|
|
f86c11 |
secret_key = &secret_key_data;
|
|
|
f86c11 |
g_atomic_pointer_set (&secret_key_static, secret_key);
|
|
|
f86c11 |
g_once_init_leave (&init_value, 1);
|
|
|
f86c11 |
--
|
|
|
f86c11 |
2.19.2
|
|
|
f86c11 |
|
|
|
f86c11 |
|
|
|
f86c11 |
From e8a3a7e25472c74d66790fab14bded799631006b Mon Sep 17 00:00:00 2001
|
|
|
f86c11 |
From: Thomas Haller <thaller@redhat.com>
|
|
|
f86c11 |
Date: Wed, 12 Dec 2018 12:11:53 +0100
|
|
|
f86c11 |
Subject: [PATCH 06/10] shared: expose siphash24() related functionality in
|
|
|
f86c11 |
nm-hash-utils.h
|
|
|
f86c11 |
|
|
|
f86c11 |
CSiphash is a first class citizen, it's fine to use everwhere where we
|
|
|
f86c11 |
need it.
|
|
|
f86c11 |
|
|
|
f86c11 |
NMHash wraps CSiphash and provides three things:
|
|
|
f86c11 |
|
|
|
f86c11 |
1) Convenience macros that make hashing nicer to use.
|
|
|
f86c11 |
|
|
|
f86c11 |
2) it uses a randomly generated, per-run hash seed, that can be combined
|
|
|
f86c11 |
with a guint static seed.
|
|
|
f86c11 |
|
|
|
f86c11 |
3) it's a general API for hashing data. It nowhere promises that it
|
|
|
f86c11 |
actually uses siphash24, although currently it does everywhere.
|
|
|
f86c11 |
NMHash is not (officially) siphash24.
|
|
|
f86c11 |
|
|
|
f86c11 |
Add API nm_hash_siphash42_init() and nm_hash_siphash42() to "nm-hash-utils.h",
|
|
|
f86c11 |
that exposes (2) for use with regular CSiphash. You of course no longer
|
|
|
f86c11 |
get the convenice macros (1) but you get plain siphash24 (which
|
|
|
f86c11 |
NMHash does not give (3)).
|
|
|
f86c11 |
|
|
|
f86c11 |
While at it, also add a nm_hash_complete_u64(). Usually, for hasing we
|
|
|
f86c11 |
want guint types. But we don't need to hide the fact, that the
|
|
|
f86c11 |
underlying value is first uint64. Expose it.
|
|
|
f86c11 |
|
|
|
f86c11 |
(cherry picked from commit db791db4e1ff7a850b4ac49d24d159e2ccbe005c)
|
|
|
f86c11 |
(cherry picked from commit 0a4bbb18fe9fb80acf038177ae581b7aef2c7883)
|
|
|
f86c11 |
---
|
|
|
f86c11 |
shared/nm-utils/nm-hash-utils.c | 6 ++--
|
|
|
f86c11 |
shared/nm-utils/nm-hash-utils.h | 62 +++++++++++++++++++++++++++++----
|
|
|
f86c11 |
2 files changed, 59 insertions(+), 9 deletions(-)
|
|
|
f86c11 |
|
|
|
f86c11 |
diff --git a/shared/nm-utils/nm-hash-utils.c b/shared/nm-utils/nm-hash-utils.c
|
|
|
f86c11 |
index 9f164a119..80387c714 100644
|
|
|
f86c11 |
--- a/shared/nm-utils/nm-hash-utils.c
|
|
|
f86c11 |
+++ b/shared/nm-utils/nm-hash-utils.c
|
|
|
f86c11 |
@@ -122,17 +122,17 @@ nm_hash_static (guint static_seed)
|
|
|
f86c11 |
}
|
|
|
f86c11 |
|
|
|
f86c11 |
void
|
|
|
f86c11 |
-nm_hash_init (NMHashState *state, guint static_seed)
|
|
|
f86c11 |
+nm_hash_siphash42_init (CSipHash *h, guint static_seed)
|
|
|
f86c11 |
{
|
|
|
f86c11 |
const guint8 *g;
|
|
|
f86c11 |
guint seed[HASH_KEY_SIZE_GUINT];
|
|
|
f86c11 |
|
|
|
f86c11 |
- nm_assert (state);
|
|
|
f86c11 |
+ nm_assert (h);
|
|
|
f86c11 |
|
|
|
f86c11 |
g = _get_hash_key ();
|
|
|
f86c11 |
memcpy (seed, g, HASH_KEY_SIZE);
|
|
|
f86c11 |
seed[0] ^= static_seed;
|
|
|
f86c11 |
- c_siphash_init (&state->_state, (const guint8 *) seed);
|
|
|
f86c11 |
+ c_siphash_init (h, (const guint8 *) seed);
|
|
|
f86c11 |
}
|
|
|
f86c11 |
|
|
|
f86c11 |
guint
|
|
|
f86c11 |
diff --git a/shared/nm-utils/nm-hash-utils.h b/shared/nm-utils/nm-hash-utils.h
|
|
|
f86c11 |
index b797fb75a..cf71a7e9f 100644
|
|
|
f86c11 |
--- a/shared/nm-utils/nm-hash-utils.h
|
|
|
f86c11 |
+++ b/shared/nm-utils/nm-hash-utils.h
|
|
|
f86c11 |
@@ -25,6 +25,39 @@
|
|
|
f86c11 |
#include "c-siphash/src/c-siphash.h"
|
|
|
f86c11 |
#include "nm-macros-internal.h"
|
|
|
f86c11 |
|
|
|
f86c11 |
+/*****************************************************************************/
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+void nm_hash_siphash42_init (CSipHash *h, guint static_seed);
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+/* Siphash24 of binary buffer @arr and @len, using the randomized seed from
|
|
|
f86c11 |
+ * other NMHash functions.
|
|
|
f86c11 |
+ *
|
|
|
f86c11 |
+ * Note, that this is guaranteed to use siphash42 under the hood (contrary to
|
|
|
f86c11 |
+ * all other NMHash API, which leave this undefined). That matters at the point,
|
|
|
f86c11 |
+ * where the caller needs to be sure that a reasonably strong hasing algorithm
|
|
|
f86c11 |
+ * is used. (Yes, NMHash is all about siphash24, but otherwise that is not promised
|
|
|
f86c11 |
+ * anywhere).
|
|
|
f86c11 |
+ *
|
|
|
f86c11 |
+ * Another difference is, that this returns guint64 (not guint like other NMHash functions).
|
|
|
f86c11 |
+ *
|
|
|
f86c11 |
+ * Another difference is, that this may also return zero (not like nm_hash_complete()).
|
|
|
f86c11 |
+ *
|
|
|
f86c11 |
+ * Then, why not use c_siphash_hash() directly? Because this also uses the randomized,
|
|
|
f86c11 |
+ * per-run hash-seed like nm_hash_init(). So, you get siphash24 with a random
|
|
|
f86c11 |
+ * seed (which is cached for the current run of the program).
|
|
|
f86c11 |
+ */
|
|
|
f86c11 |
+static inline guint64
|
|
|
f86c11 |
+nm_hash_siphash42 (guint static_seed, const void *ptr, gsize n)
|
|
|
f86c11 |
+{
|
|
|
f86c11 |
+ CSipHash h;
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+ nm_hash_siphash42_init (&h, static_seed);
|
|
|
f86c11 |
+ c_siphash_append (&h, ptr, n);
|
|
|
f86c11 |
+ return c_siphash_finalize (&h);
|
|
|
f86c11 |
+}
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+/*****************************************************************************/
|
|
|
f86c11 |
+
|
|
|
f86c11 |
struct _NMHashState {
|
|
|
f86c11 |
CSipHash _state;
|
|
|
f86c11 |
};
|
|
|
f86c11 |
@@ -33,16 +66,33 @@ typedef struct _NMHashState NMHashState;
|
|
|
f86c11 |
|
|
|
f86c11 |
guint nm_hash_static (guint static_seed);
|
|
|
f86c11 |
|
|
|
f86c11 |
-void nm_hash_init (NMHashState *state, guint static_seed);
|
|
|
f86c11 |
+static inline void
|
|
|
f86c11 |
+nm_hash_init (NMHashState *state, guint static_seed)
|
|
|
f86c11 |
+{
|
|
|
f86c11 |
+ nm_assert (state);
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+ nm_hash_siphash42_init (&state->_state, static_seed);
|
|
|
f86c11 |
+}
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+static inline guint64
|
|
|
f86c11 |
+nm_hash_complete_u64 (NMHashState *state)
|
|
|
f86c11 |
+{
|
|
|
f86c11 |
+ nm_assert (state);
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+ /* this returns the native u64 hash value. Note that this differs
|
|
|
f86c11 |
+ * from nm_hash_complete() in two ways:
|
|
|
f86c11 |
+ *
|
|
|
f86c11 |
+ * - the type, guint64 vs. guint.
|
|
|
f86c11 |
+ * - nm_hash_complete() never returns zero. */
|
|
|
f86c11 |
+ return c_siphash_finalize (&state->_state);
|
|
|
f86c11 |
+}
|
|
|
f86c11 |
|
|
|
f86c11 |
static inline guint
|
|
|
f86c11 |
nm_hash_complete (NMHashState *state)
|
|
|
f86c11 |
{
|
|
|
f86c11 |
guint64 h;
|
|
|
f86c11 |
|
|
|
f86c11 |
- nm_assert (state);
|
|
|
f86c11 |
-
|
|
|
f86c11 |
- h = c_siphash_finalize (&state->_state);
|
|
|
f86c11 |
+ h = nm_hash_complete_u64 (state);
|
|
|
f86c11 |
|
|
|
f86c11 |
/* we don't ever want to return a zero hash.
|
|
|
f86c11 |
*
|
|
|
f86c11 |
@@ -218,8 +268,8 @@ guint nm_str_hash (gconstpointer str);
|
|
|
f86c11 |
({ \
|
|
|
f86c11 |
NMHashState _h; \
|
|
|
f86c11 |
\
|
|
|
f86c11 |
- nm_hash_init (&_h, static_seed); \
|
|
|
f86c11 |
- nm_hash_update_val (&_h, val); \
|
|
|
f86c11 |
+ nm_hash_init (&_h, (static_seed)); \
|
|
|
f86c11 |
+ nm_hash_update_val (&_h, (val)); \
|
|
|
f86c11 |
nm_hash_complete (&_h); \
|
|
|
f86c11 |
})
|
|
|
f86c11 |
|
|
|
f86c11 |
--
|
|
|
f86c11 |
2.19.2
|
|
|
f86c11 |
|
|
|
f86c11 |
|
|
|
f86c11 |
From 604bf0c568f821f50bc19aac91a6db15d31c2a29 Mon Sep 17 00:00:00 2001
|
|
|
f86c11 |
From: Thomas Haller <thaller@redhat.com>
|
|
|
f86c11 |
Date: Wed, 12 Dec 2018 10:10:38 +0100
|
|
|
f86c11 |
Subject: [PATCH 07/10] core/trivial: rename secret-key to host-key
|
|
|
f86c11 |
|
|
|
f86c11 |
Now that the secret-key is hashed with the machine-id, the name is
|
|
|
f86c11 |
no longer best.
|
|
|
f86c11 |
|
|
|
f86c11 |
Sure, part of the key are persisted in /var/lib/NetworkManager/secret_key
|
|
|
f86c11 |
file, which the user is well advised to keep secret.
|
|
|
f86c11 |
|
|
|
f86c11 |
But what nm_utils_secret_key_get() returns is first and foremost a binary
|
|
|
f86c11 |
key that is per-host and used for hashing a per-host component. It's
|
|
|
f86c11 |
really the "host-id". Compare that to what we also have, the
|
|
|
f86c11 |
"machine-id" and the "boot-id".
|
|
|
f86c11 |
|
|
|
f86c11 |
Rename.
|
|
|
f86c11 |
|
|
|
f86c11 |
(cherry picked from commit 6ffcd263177d01a528a89709609f06550ecded9b)
|
|
|
f86c11 |
(cherry picked from commit cdb7f6f6d2927aac501efba22557778301834d0e)
|
|
|
f86c11 |
---
|
|
|
f86c11 |
src/devices/nm-device.c | 24 ++++----
|
|
|
f86c11 |
src/nm-core-utils.c | 133 ++++++++++++++++++++++------------------
|
|
|
f86c11 |
src/nm-core-utils.h | 14 ++---
|
|
|
f86c11 |
3 files changed, 93 insertions(+), 78 deletions(-)
|
|
|
f86c11 |
|
|
|
f86c11 |
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
|
|
|
f86c11 |
index 8d5866266..8821dfaa9 100644
|
|
|
f86c11 |
--- a/src/devices/nm-device.c
|
|
|
f86c11 |
+++ b/src/devices/nm-device.c
|
|
|
f86c11 |
@@ -7528,8 +7528,8 @@ dhcp4_get_client_id (NMDevice *self,
|
|
|
f86c11 |
NMUtilsStableType stable_type;
|
|
|
f86c11 |
const char *stable_id;
|
|
|
f86c11 |
guint32 salted_header;
|
|
|
f86c11 |
- const guint8 *secret_key;
|
|
|
f86c11 |
- gsize secret_key_len;
|
|
|
f86c11 |
+ const guint8 *host_id;
|
|
|
f86c11 |
+ gsize host_id_len;
|
|
|
f86c11 |
|
|
|
f86c11 |
stable_id = _get_stable_id (self, connection, &stable_type);
|
|
|
f86c11 |
if (!stable_id)
|
|
|
f86c11 |
@@ -7537,12 +7537,12 @@ dhcp4_get_client_id (NMDevice *self,
|
|
|
f86c11 |
|
|
|
f86c11 |
salted_header = htonl (2011610591 + stable_type);
|
|
|
f86c11 |
|
|
|
f86c11 |
- nm_utils_secret_key_get (&secret_key, &secret_key_len);
|
|
|
f86c11 |
+ nm_utils_host_id_get (&host_id, &host_id_len);
|
|
|
f86c11 |
|
|
|
f86c11 |
sum = g_checksum_new (G_CHECKSUM_SHA1);
|
|
|
f86c11 |
g_checksum_update (sum, (const guchar *) &salted_header, sizeof (salted_header));
|
|
|
f86c11 |
g_checksum_update (sum, (const guchar *) stable_id, strlen (stable_id) + 1);
|
|
|
f86c11 |
- g_checksum_update (sum, (const guchar *) secret_key, secret_key_len);
|
|
|
f86c11 |
+ g_checksum_update (sum, (const guchar *) host_id, host_id_len);
|
|
|
f86c11 |
nm_utils_checksum_get_digest (sum, digest);
|
|
|
f86c11 |
|
|
|
f86c11 |
client_id_buf = g_malloc (1 + 15);
|
|
|
f86c11 |
@@ -8317,7 +8317,7 @@ dhcp6_get_duid (NMDevice *self, NMConnection *connection, GBytes *hwaddr, gboole
|
|
|
f86c11 |
} else {
|
|
|
f86c11 |
gint64 time;
|
|
|
f86c11 |
|
|
|
f86c11 |
- time = nm_utils_secret_key_get_timestamp ();
|
|
|
f86c11 |
+ time = nm_utils_host_id_get_timestamp ();
|
|
|
f86c11 |
if (!time) {
|
|
|
f86c11 |
duid_error = "cannot retrieve the secret key timestamp";
|
|
|
f86c11 |
goto out_fail;
|
|
|
f86c11 |
@@ -8334,8 +8334,8 @@ dhcp6_get_duid (NMDevice *self, NMConnection *connection, GBytes *hwaddr, gboole
|
|
|
f86c11 |
NMUtilsStableType stable_type;
|
|
|
f86c11 |
const char *stable_id = NULL;
|
|
|
f86c11 |
guint32 salted_header;
|
|
|
f86c11 |
- const guint8 *secret_key;
|
|
|
f86c11 |
- gsize secret_key_len;
|
|
|
f86c11 |
+ const guint8 *host_id;
|
|
|
f86c11 |
+ gsize host_id_len;
|
|
|
f86c11 |
union {
|
|
|
f86c11 |
guint8 sha256[NM_UTILS_CHECKSUM_LENGTH_SHA256];
|
|
|
f86c11 |
guint8 hwaddr[ETH_ALEN];
|
|
|
f86c11 |
@@ -8352,12 +8352,12 @@ dhcp6_get_duid (NMDevice *self, NMConnection *connection, GBytes *hwaddr, gboole
|
|
|
f86c11 |
|
|
|
f86c11 |
salted_header = htonl (670531087 + stable_type);
|
|
|
f86c11 |
|
|
|
f86c11 |
- nm_utils_secret_key_get (&secret_key, &secret_key_len);
|
|
|
f86c11 |
+ nm_utils_host_id_get (&host_id, &host_id_len);
|
|
|
f86c11 |
|
|
|
f86c11 |
sum = g_checksum_new (G_CHECKSUM_SHA256);
|
|
|
f86c11 |
g_checksum_update (sum, (const guchar *) &salted_header, sizeof (salted_header));
|
|
|
f86c11 |
g_checksum_update (sum, (const guchar *) stable_id, -1);
|
|
|
f86c11 |
- g_checksum_update (sum, (const guchar *) secret_key, secret_key_len);
|
|
|
f86c11 |
+ g_checksum_update (sum, (const guchar *) host_id, host_id_len);
|
|
|
f86c11 |
nm_utils_checksum_get_digest (sum, digest.sha256);
|
|
|
f86c11 |
|
|
|
f86c11 |
G_STATIC_ASSERT_EXPR (sizeof (digest) == sizeof (digest.sha256));
|
|
|
f86c11 |
@@ -8369,11 +8369,11 @@ dhcp6_get_duid (NMDevice *self, NMConnection *connection, GBytes *hwaddr, gboole
|
|
|
f86c11 |
|
|
|
f86c11 |
#define EPOCH_DATETIME_THREE_YEARS (356 * 24 * 3600 * 3)
|
|
|
f86c11 |
|
|
|
f86c11 |
- /* We want a variable time between the secret_key timestamp and three years
|
|
|
f86c11 |
+ /* We want a variable time between the host_id timestamp and three years
|
|
|
f86c11 |
* before. Let's compute the time (in seconds) from 0 to 3 years; then we'll
|
|
|
f86c11 |
- * subtract it from the secret_key timestamp.
|
|
|
f86c11 |
+ * subtract it from the host_id timestamp.
|
|
|
f86c11 |
*/
|
|
|
f86c11 |
- time = nm_utils_secret_key_get_timestamp ();
|
|
|
f86c11 |
+ time = nm_utils_host_id_get_timestamp ();
|
|
|
f86c11 |
if (!time) {
|
|
|
f86c11 |
duid_error = "cannot retrieve the secret key timestamp";
|
|
|
f86c11 |
goto out_fail;
|
|
|
f86c11 |
diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c
|
|
|
f86c11 |
index c3d2e3c2a..4ac68c2da 100644
|
|
|
f86c11 |
--- a/src/nm-core-utils.c
|
|
|
f86c11 |
+++ b/src/nm-core-utils.c
|
|
|
f86c11 |
@@ -2657,7 +2657,7 @@ again:
|
|
|
f86c11 |
return NULL;
|
|
|
f86c11 |
}
|
|
|
f86c11 |
|
|
|
f86c11 |
- if (nm_utils_secret_key_get (&seed_bin, &seed_len)) {
|
|
|
f86c11 |
+ if (nm_utils_host_id_get (&seed_bin, &seed_len)) {
|
|
|
f86c11 |
/* we have no valid machine-id. Generate a fake one by hashing
|
|
|
f86c11 |
* the secret-key. This key is commonly persisted, so it should be
|
|
|
f86c11 |
* stable accross reboots (despite having a broken system without
|
|
|
f86c11 |
@@ -2728,9 +2728,9 @@ nm_utils_machine_id_is_fake (void)
|
|
|
f86c11 |
#define SECRET_KEY_FILE NMSTATEDIR"/secret_key"
|
|
|
f86c11 |
|
|
|
f86c11 |
static const guint8 *
|
|
|
f86c11 |
-_secret_key_hash_v2 (const guint8 *seed_arr,
|
|
|
f86c11 |
- gsize seed_len,
|
|
|
f86c11 |
- guint8 *out_digest /* 32 bytes (NM_UTILS_CHECKSUM_LENGTH_SHA256) */)
|
|
|
f86c11 |
+_host_id_hash_v2 (const guint8 *seed_arr,
|
|
|
f86c11 |
+ gsize seed_len,
|
|
|
f86c11 |
+ guint8 *out_digest /* 32 bytes (NM_UTILS_CHECKSUM_LENGTH_SHA256) */)
|
|
|
f86c11 |
{
|
|
|
f86c11 |
nm_auto_free_checksum GChecksum *sum = g_checksum_new (G_CHECKSUM_SHA256);
|
|
|
f86c11 |
const UuidData *machine_id_data;
|
|
|
f86c11 |
@@ -2758,8 +2758,8 @@ _secret_key_hash_v2 (const guint8 *seed_arr,
|
|
|
f86c11 |
}
|
|
|
f86c11 |
|
|
|
f86c11 |
static gboolean
|
|
|
f86c11 |
-_secret_key_read (guint8 **out_key,
|
|
|
f86c11 |
- gsize *out_key_len)
|
|
|
f86c11 |
+_host_id_read (guint8 **out_host_id,
|
|
|
f86c11 |
+ gsize *out_host_id_len)
|
|
|
f86c11 |
{
|
|
|
f86c11 |
#define SECRET_KEY_LEN 32u
|
|
|
f86c11 |
guint8 sha256_digest[NM_UTILS_CHECKSUM_LENGTH_SHA256];
|
|
|
f86c11 |
@@ -2797,7 +2797,7 @@ _secret_key_read (guint8 **out_key,
|
|
|
f86c11 |
* except that it seems simpler not to distinguish between the v2 prefix and the content.
|
|
|
f86c11 |
* It's all just part of the seed. */
|
|
|
f86c11 |
|
|
|
f86c11 |
- secret_arr = _secret_key_hash_v2 (file_content.bin, file_content.len, sha256_digest);
|
|
|
f86c11 |
+ secret_arr = _host_id_hash_v2 (file_content.bin, file_content.len, sha256_digest);
|
|
|
f86c11 |
secret_len = NM_UTILS_CHECKSUM_LENGTH_SHA256;
|
|
|
f86c11 |
success = TRUE;
|
|
|
f86c11 |
goto out;
|
|
|
f86c11 |
@@ -2842,7 +2842,7 @@ _secret_key_read (guint8 **out_key,
|
|
|
f86c11 |
&base64_save);
|
|
|
f86c11 |
nm_assert (len <= sizeof (new_content));
|
|
|
f86c11 |
|
|
|
f86c11 |
- secret_arr = _secret_key_hash_v2 (new_content, len, sha256_digest);
|
|
|
f86c11 |
+ secret_arr = _host_id_hash_v2 (new_content, len, sha256_digest);
|
|
|
f86c11 |
secret_len = NM_UTILS_CHECKSUM_LENGTH_SHA256;
|
|
|
f86c11 |
|
|
|
f86c11 |
if (!success)
|
|
|
f86c11 |
@@ -2866,53 +2866,68 @@ _secret_key_read (guint8 **out_key,
|
|
|
f86c11 |
}
|
|
|
f86c11 |
|
|
|
f86c11 |
out:
|
|
|
f86c11 |
- *out_key_len = secret_len;
|
|
|
f86c11 |
- *out_key = nm_memdup (secret_arr, secret_len);
|
|
|
f86c11 |
+ *out_host_id_len = secret_len;
|
|
|
f86c11 |
+ *out_host_id = nm_memdup (secret_arr, secret_len);
|
|
|
f86c11 |
return success;
|
|
|
f86c11 |
}
|
|
|
f86c11 |
|
|
|
f86c11 |
typedef struct {
|
|
|
f86c11 |
- guint8 *secret_key;
|
|
|
f86c11 |
- gsize key_len;
|
|
|
f86c11 |
+ guint8 *host_id;
|
|
|
f86c11 |
+ gsize host_id_len;
|
|
|
f86c11 |
bool is_good:1;
|
|
|
f86c11 |
-} SecretKeyData;
|
|
|
f86c11 |
+} HostIdData;
|
|
|
f86c11 |
|
|
|
f86c11 |
+/**
|
|
|
f86c11 |
+ * nm_utils_host_id_get:
|
|
|
f86c11 |
+ * @out_host_id: (out) (transfer none): the binary host key
|
|
|
f86c11 |
+ * @out_host_id_len: the length of the host key.
|
|
|
f86c11 |
+ *
|
|
|
f86c11 |
+ * This returns a per-host key that depends on /var/lib/NetworkManage/secret_key
|
|
|
f86c11 |
+ * and (depending on the version) on /etc/machine-id. If /var/lib/NetworkManage/secret_key
|
|
|
f86c11 |
+ * does not exist, it will be generated and persisted for next boot.
|
|
|
f86c11 |
+ *
|
|
|
f86c11 |
+ * Returns: %TRUE, if the host key is "good". Note that this function
|
|
|
f86c11 |
+ * will always succeed to return a host-key, and that this key
|
|
|
f86c11 |
+ * won't change during the run of the program (no matter what).
|
|
|
f86c11 |
+ * A %FALSE return possibly means, that the secret_key is not persisted
|
|
|
f86c11 |
+ * to disk, and/or that it was generated with bad randomness.
|
|
|
f86c11 |
+ */
|
|
|
f86c11 |
gboolean
|
|
|
f86c11 |
-nm_utils_secret_key_get (const guint8 **out_secret_key,
|
|
|
f86c11 |
- gsize *out_key_len)
|
|
|
f86c11 |
+nm_utils_host_id_get (const guint8 **out_host_id,
|
|
|
f86c11 |
+ gsize *out_host_id_len)
|
|
|
f86c11 |
{
|
|
|
f86c11 |
- static const SecretKeyData *volatile secret_key_static;
|
|
|
f86c11 |
- const SecretKeyData *secret_key;
|
|
|
f86c11 |
+ static const HostIdData *volatile host_id_static;
|
|
|
f86c11 |
+ const HostIdData *host_id;
|
|
|
f86c11 |
|
|
|
f86c11 |
again:
|
|
|
f86c11 |
- secret_key = g_atomic_pointer_get (&secret_key_static);
|
|
|
f86c11 |
- if (G_UNLIKELY (!secret_key)) {
|
|
|
f86c11 |
- static SecretKeyData secret_key_data;
|
|
|
f86c11 |
+ host_id = g_atomic_pointer_get (&host_id_static);
|
|
|
f86c11 |
+ if (G_UNLIKELY (!host_id)) {
|
|
|
f86c11 |
+ static HostIdData host_id_data;
|
|
|
f86c11 |
static gsize init_value = 0;
|
|
|
f86c11 |
|
|
|
f86c11 |
if (!g_once_init_enter (&init_value))
|
|
|
f86c11 |
goto again;
|
|
|
f86c11 |
|
|
|
f86c11 |
- secret_key_data.is_good = _secret_key_read (&secret_key_data.secret_key,
|
|
|
f86c11 |
- &secret_key_data.key_len);
|
|
|
f86c11 |
- secret_key = &secret_key_data;
|
|
|
f86c11 |
- g_atomic_pointer_set (&secret_key_static, secret_key);
|
|
|
f86c11 |
+ host_id_data.is_good = _host_id_read (&host_id_data.host_id,
|
|
|
f86c11 |
+ &host_id_data.host_id_len);
|
|
|
f86c11 |
+ host_id = &host_id_data;
|
|
|
f86c11 |
+ g_atomic_pointer_set (&host_id_static, host_id);
|
|
|
f86c11 |
g_once_init_leave (&init_value, 1);
|
|
|
f86c11 |
}
|
|
|
f86c11 |
|
|
|
f86c11 |
- *out_secret_key = secret_key->secret_key;
|
|
|
f86c11 |
- *out_key_len = secret_key->key_len;
|
|
|
f86c11 |
- return secret_key->is_good;
|
|
|
f86c11 |
+ *out_host_id = host_id->host_id;
|
|
|
f86c11 |
+ *out_host_id_len = host_id->host_id_len;
|
|
|
f86c11 |
+ return host_id->is_good;
|
|
|
f86c11 |
}
|
|
|
f86c11 |
|
|
|
f86c11 |
gint64
|
|
|
f86c11 |
-nm_utils_secret_key_get_timestamp (void)
|
|
|
f86c11 |
+nm_utils_host_id_get_timestamp (void)
|
|
|
f86c11 |
{
|
|
|
f86c11 |
struct stat stat_buf;
|
|
|
f86c11 |
- const guint8 *key;
|
|
|
f86c11 |
- gsize key_len;
|
|
|
f86c11 |
+ const guint8 *host_id;
|
|
|
f86c11 |
+ gsize host_id_len;
|
|
|
f86c11 |
|
|
|
f86c11 |
- if (!nm_utils_secret_key_get (&key, &key_len))
|
|
|
f86c11 |
+ if (!nm_utils_host_id_get (&host_id, &host_id_len))
|
|
|
f86c11 |
return 0;
|
|
|
f86c11 |
|
|
|
f86c11 |
if (stat (SECRET_KEY_FILE, &stat_buf) != 0)
|
|
|
f86c11 |
@@ -3379,20 +3394,20 @@ _set_stable_privacy (NMUtilsStableType stable_type,
|
|
|
f86c11 |
const char *ifname,
|
|
|
f86c11 |
const char *network_id,
|
|
|
f86c11 |
guint32 dad_counter,
|
|
|
f86c11 |
- const guint8 *secret_key,
|
|
|
f86c11 |
- gsize key_len,
|
|
|
f86c11 |
+ const guint8 *host_id,
|
|
|
f86c11 |
+ gsize host_id_len,
|
|
|
f86c11 |
GError **error)
|
|
|
f86c11 |
{
|
|
|
f86c11 |
nm_auto_free_checksum GChecksum *sum = NULL;
|
|
|
f86c11 |
guint8 digest[NM_UTILS_CHECKSUM_LENGTH_SHA256];
|
|
|
f86c11 |
guint32 tmp[2];
|
|
|
f86c11 |
|
|
|
f86c11 |
- nm_assert (key_len);
|
|
|
f86c11 |
+ nm_assert (host_id_len);
|
|
|
f86c11 |
nm_assert (network_id);
|
|
|
f86c11 |
|
|
|
f86c11 |
sum = g_checksum_new (G_CHECKSUM_SHA256);
|
|
|
f86c11 |
|
|
|
f86c11 |
- key_len = MIN (key_len, G_MAXUINT32);
|
|
|
f86c11 |
+ host_id_len = MIN (host_id_len, G_MAXUINT32);
|
|
|
f86c11 |
|
|
|
f86c11 |
if (stable_type != NM_UTILS_STABLE_TYPE_UUID) {
|
|
|
f86c11 |
guint8 stable_type_uint8;
|
|
|
f86c11 |
@@ -3405,7 +3420,7 @@ _set_stable_privacy (NMUtilsStableType stable_type,
|
|
|
f86c11 |
*
|
|
|
f86c11 |
* That is no real problem and it is still impossible to
|
|
|
f86c11 |
* force a collision here, because of how the remaining
|
|
|
f86c11 |
- * fields are hashed. That is, as we also hash @key_len
|
|
|
f86c11 |
+ * fields are hashed. That is, as we also hash @host_id_len
|
|
|
f86c11 |
* and the terminating '\0' of @network_id, it is unambigiously
|
|
|
f86c11 |
* possible to revert the process and deduce the @stable_type.
|
|
|
f86c11 |
*/
|
|
|
f86c11 |
@@ -3416,9 +3431,9 @@ _set_stable_privacy (NMUtilsStableType stable_type,
|
|
|
f86c11 |
g_checksum_update (sum, (const guchar *) ifname, strlen (ifname) + 1);
|
|
|
f86c11 |
g_checksum_update (sum, (const guchar *) network_id, strlen (network_id) + 1);
|
|
|
f86c11 |
tmp[0] = htonl (dad_counter);
|
|
|
f86c11 |
- tmp[1] = htonl (key_len);
|
|
|
f86c11 |
+ tmp[1] = htonl (host_id_len);
|
|
|
f86c11 |
g_checksum_update (sum, (const guchar *) tmp, sizeof (tmp));
|
|
|
f86c11 |
- g_checksum_update (sum, (const guchar *) secret_key, key_len);
|
|
|
f86c11 |
+ g_checksum_update (sum, (const guchar *) host_id, host_id_len);
|
|
|
f86c11 |
nm_utils_checksum_get_digest (sum, digest);
|
|
|
f86c11 |
|
|
|
f86c11 |
while (_is_reserved_ipv6_iid (digest)) {
|
|
|
f86c11 |
@@ -3439,11 +3454,11 @@ nm_utils_ipv6_addr_set_stable_privacy_impl (NMUtilsStableType stable_type,
|
|
|
f86c11 |
const char *ifname,
|
|
|
f86c11 |
const char *network_id,
|
|
|
f86c11 |
guint32 dad_counter,
|
|
|
f86c11 |
- guint8 *secret_key,
|
|
|
f86c11 |
- gsize key_len,
|
|
|
f86c11 |
+ guint8 *host_id,
|
|
|
f86c11 |
+ gsize host_id_len,
|
|
|
f86c11 |
GError **error)
|
|
|
f86c11 |
{
|
|
|
f86c11 |
- return _set_stable_privacy (stable_type, addr, ifname, network_id, dad_counter, secret_key, key_len, error);
|
|
|
f86c11 |
+ return _set_stable_privacy (stable_type, addr, ifname, network_id, dad_counter, host_id, host_id_len, error);
|
|
|
f86c11 |
}
|
|
|
f86c11 |
|
|
|
f86c11 |
#define RFC7217_IDGEN_RETRIES 3
|
|
|
f86c11 |
@@ -3463,8 +3478,8 @@ nm_utils_ipv6_addr_set_stable_privacy (NMUtilsStableType stable_type,
|
|
|
f86c11 |
guint32 dad_counter,
|
|
|
f86c11 |
GError **error)
|
|
|
f86c11 |
{
|
|
|
f86c11 |
- const guint8 *secret_key;
|
|
|
f86c11 |
- gsize key_len;
|
|
|
f86c11 |
+ const guint8 *host_id;
|
|
|
f86c11 |
+ gsize host_id_len;
|
|
|
f86c11 |
|
|
|
f86c11 |
g_return_val_if_fail (network_id, FALSE);
|
|
|
f86c11 |
|
|
|
f86c11 |
@@ -3474,10 +3489,10 @@ nm_utils_ipv6_addr_set_stable_privacy (NMUtilsStableType stable_type,
|
|
|
f86c11 |
return FALSE;
|
|
|
f86c11 |
}
|
|
|
f86c11 |
|
|
|
f86c11 |
- nm_utils_secret_key_get (&secret_key, &key_len);
|
|
|
f86c11 |
+ nm_utils_host_id_get (&host_id, &host_id_len);
|
|
|
f86c11 |
|
|
|
f86c11 |
return _set_stable_privacy (stable_type, addr, ifname, network_id, dad_counter,
|
|
|
f86c11 |
- secret_key, key_len, error);
|
|
|
f86c11 |
+ host_id, host_id_len, error);
|
|
|
f86c11 |
}
|
|
|
f86c11 |
|
|
|
f86c11 |
/*****************************************************************************/
|
|
|
f86c11 |
@@ -3549,8 +3564,8 @@ nm_utils_hw_addr_gen_random_eth (const char *current_mac_address,
|
|
|
f86c11 |
static char *
|
|
|
f86c11 |
_hw_addr_gen_stable_eth (NMUtilsStableType stable_type,
|
|
|
f86c11 |
const char *stable_id,
|
|
|
f86c11 |
- const guint8 *secret_key,
|
|
|
f86c11 |
- gsize key_len,
|
|
|
f86c11 |
+ const guint8 *host_id,
|
|
|
f86c11 |
+ gsize host_id_len,
|
|
|
f86c11 |
const char *ifname,
|
|
|
f86c11 |
const char *current_mac_address,
|
|
|
f86c11 |
const char *generate_mac_address_mask)
|
|
|
f86c11 |
@@ -3562,19 +3577,19 @@ _hw_addr_gen_stable_eth (NMUtilsStableType stable_type,
|
|
|
f86c11 |
guint8 stable_type_uint8;
|
|
|
f86c11 |
|
|
|
f86c11 |
nm_assert (stable_id);
|
|
|
f86c11 |
- nm_assert (secret_key);
|
|
|
f86c11 |
+ nm_assert (host_id);
|
|
|
f86c11 |
|
|
|
f86c11 |
sum = g_checksum_new (G_CHECKSUM_SHA256);
|
|
|
f86c11 |
|
|
|
f86c11 |
- key_len = MIN (key_len, G_MAXUINT32);
|
|
|
f86c11 |
+ host_id_len = MIN (host_id_len, G_MAXUINT32);
|
|
|
f86c11 |
|
|
|
f86c11 |
nm_assert (stable_type < (NMUtilsStableType) 255);
|
|
|
f86c11 |
stable_type_uint8 = stable_type;
|
|
|
f86c11 |
g_checksum_update (sum, (const guchar *) &stable_type_uint8, sizeof (stable_type_uint8));
|
|
|
f86c11 |
|
|
|
f86c11 |
- tmp = htonl ((guint32) key_len);
|
|
|
f86c11 |
+ tmp = htonl ((guint32) host_id_len);
|
|
|
f86c11 |
g_checksum_update (sum, (const guchar *) &tmp, sizeof (tmp));
|
|
|
f86c11 |
- g_checksum_update (sum, (const guchar *) secret_key, key_len);
|
|
|
f86c11 |
+ g_checksum_update (sum, (const guchar *) host_id, host_id_len);
|
|
|
f86c11 |
g_checksum_update (sum, (const guchar *) (ifname ?: ""), ifname ? (strlen (ifname) + 1) : 1);
|
|
|
f86c11 |
g_checksum_update (sum, (const guchar *) stable_id, strlen (stable_id) + 1);
|
|
|
f86c11 |
|
|
|
f86c11 |
@@ -3588,13 +3603,13 @@ _hw_addr_gen_stable_eth (NMUtilsStableType stable_type,
|
|
|
f86c11 |
char *
|
|
|
f86c11 |
nm_utils_hw_addr_gen_stable_eth_impl (NMUtilsStableType stable_type,
|
|
|
f86c11 |
const char *stable_id,
|
|
|
f86c11 |
- const guint8 *secret_key,
|
|
|
f86c11 |
- gsize key_len,
|
|
|
f86c11 |
+ const guint8 *host_id,
|
|
|
f86c11 |
+ gsize host_id_len,
|
|
|
f86c11 |
const char *ifname,
|
|
|
f86c11 |
const char *current_mac_address,
|
|
|
f86c11 |
const char *generate_mac_address_mask)
|
|
|
f86c11 |
{
|
|
|
f86c11 |
- return _hw_addr_gen_stable_eth (stable_type, stable_id, secret_key, key_len, ifname, current_mac_address, generate_mac_address_mask);
|
|
|
f86c11 |
+ return _hw_addr_gen_stable_eth (stable_type, stable_id, host_id, host_id_len, ifname, current_mac_address, generate_mac_address_mask);
|
|
|
f86c11 |
}
|
|
|
f86c11 |
|
|
|
f86c11 |
char *
|
|
|
f86c11 |
@@ -3604,17 +3619,17 @@ nm_utils_hw_addr_gen_stable_eth (NMUtilsStableType stable_type,
|
|
|
f86c11 |
const char *current_mac_address,
|
|
|
f86c11 |
const char *generate_mac_address_mask)
|
|
|
f86c11 |
{
|
|
|
f86c11 |
- const guint8 *secret_key;
|
|
|
f86c11 |
- gsize key_len;
|
|
|
f86c11 |
+ const guint8 *host_id;
|
|
|
f86c11 |
+ gsize host_id_len;
|
|
|
f86c11 |
|
|
|
f86c11 |
g_return_val_if_fail (stable_id, NULL);
|
|
|
f86c11 |
|
|
|
f86c11 |
- nm_utils_secret_key_get (&secret_key, &key_len);
|
|
|
f86c11 |
+ nm_utils_host_id_get (&host_id, &host_id_len);
|
|
|
f86c11 |
|
|
|
f86c11 |
return _hw_addr_gen_stable_eth (stable_type,
|
|
|
f86c11 |
stable_id,
|
|
|
f86c11 |
- secret_key,
|
|
|
f86c11 |
- key_len,
|
|
|
f86c11 |
+ host_id,
|
|
|
f86c11 |
+ host_id_len,
|
|
|
f86c11 |
ifname,
|
|
|
f86c11 |
current_mac_address,
|
|
|
f86c11 |
generate_mac_address_mask);
|
|
|
f86c11 |
diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h
|
|
|
f86c11 |
index ab9dade21..c93e69bbd 100644
|
|
|
f86c11 |
--- a/src/nm-core-utils.h
|
|
|
f86c11 |
+++ b/src/nm-core-utils.h
|
|
|
f86c11 |
@@ -289,9 +289,9 @@ gboolean nm_utils_machine_id_is_fake (void);
|
|
|
f86c11 |
const char *nm_utils_get_boot_id_str (void);
|
|
|
f86c11 |
const struct _NMUuid *nm_utils_get_boot_id_bin (void);
|
|
|
f86c11 |
|
|
|
f86c11 |
-gboolean nm_utils_secret_key_get (const guint8 **out_secret_key,
|
|
|
f86c11 |
- gsize *out_key_len);
|
|
|
f86c11 |
-gint64 nm_utils_secret_key_get_timestamp (void);
|
|
|
f86c11 |
+gboolean nm_utils_host_id_get (const guint8 **out_host_id,
|
|
|
f86c11 |
+ gsize *out_host_id_len);
|
|
|
f86c11 |
+gint64 nm_utils_host_id_get_timestamp (void);
|
|
|
f86c11 |
|
|
|
f86c11 |
/* IPv6 Interface Identifier helpers */
|
|
|
f86c11 |
|
|
|
f86c11 |
@@ -359,8 +359,8 @@ gboolean nm_utils_ipv6_addr_set_stable_privacy_impl (NMUtilsStableType stable_ty
|
|
|
f86c11 |
const char *ifname,
|
|
|
f86c11 |
const char *network_id,
|
|
|
f86c11 |
guint32 dad_counter,
|
|
|
f86c11 |
- guint8 *secret_key,
|
|
|
f86c11 |
- gsize key_len,
|
|
|
f86c11 |
+ guint8 *host_id,
|
|
|
f86c11 |
+ gsize host_id_len,
|
|
|
f86c11 |
GError **error);
|
|
|
f86c11 |
|
|
|
f86c11 |
gboolean nm_utils_ipv6_addr_set_stable_privacy (NMUtilsStableType id_type,
|
|
|
f86c11 |
@@ -374,8 +374,8 @@ char *nm_utils_hw_addr_gen_random_eth (const char *current_mac_address,
|
|
|
f86c11 |
const char *generate_mac_address_mask);
|
|
|
f86c11 |
char *nm_utils_hw_addr_gen_stable_eth_impl (NMUtilsStableType stable_type,
|
|
|
f86c11 |
const char *stable_id,
|
|
|
f86c11 |
- const guint8 *secret_key,
|
|
|
f86c11 |
- gsize key_len,
|
|
|
f86c11 |
+ const guint8 *host_id,
|
|
|
f86c11 |
+ gsize host_id_len,
|
|
|
f86c11 |
const char *ifname,
|
|
|
f86c11 |
const char *current_mac_address,
|
|
|
f86c11 |
const char *generate_mac_address_mask);
|
|
|
f86c11 |
--
|
|
|
f86c11 |
2.19.2
|
|
|
f86c11 |
|
|
|
f86c11 |
|
|
|
f86c11 |
From f135dfbf60b58123e75a7d560a44b815332ad5d0 Mon Sep 17 00:00:00 2001
|
|
|
f86c11 |
From: Thomas Haller <thaller@redhat.com>
|
|
|
f86c11 |
Date: Wed, 12 Dec 2018 10:14:51 +0100
|
|
|
f86c11 |
Subject: [PATCH 08/10] core/trivial: rename nm_utils_get_boot_id_*()
|
|
|
f86c11 |
|
|
|
f86c11 |
Rename to nm_utils_boot_id_*(), it matches nm_utils_machine_id_*()
|
|
|
f86c11 |
and nm_utils_host_id_get().
|
|
|
f86c11 |
|
|
|
f86c11 |
(cherry picked from commit d693e03a74bee600ba14ee8dad666ff6fe658ca2)
|
|
|
f86c11 |
(cherry picked from commit 4482c4d4af091baa16f10f5ac42919095e079559)
|
|
|
f86c11 |
---
|
|
|
f86c11 |
src/devices/nm-device.c | 2 +-
|
|
|
f86c11 |
src/nm-core-utils.c | 6 +++---
|
|
|
f86c11 |
src/nm-core-utils.h | 4 ++--
|
|
|
f86c11 |
3 files changed, 6 insertions(+), 6 deletions(-)
|
|
|
f86c11 |
|
|
|
f86c11 |
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
|
|
|
f86c11 |
index 8821dfaa9..738e032e3 100644
|
|
|
f86c11 |
--- a/src/devices/nm-device.c
|
|
|
f86c11 |
+++ b/src/devices/nm-device.c
|
|
|
f86c11 |
@@ -1288,7 +1288,7 @@ _get_stable_id (NMDevice *self,
|
|
|
f86c11 |
stable_type = nm_utils_stable_id_parse (stable_id,
|
|
|
f86c11 |
nm_device_get_ip_iface (self),
|
|
|
f86c11 |
!hwaddr_is_fake ? hwaddr : NULL,
|
|
|
f86c11 |
- nm_utils_get_boot_id_str (),
|
|
|
f86c11 |
+ nm_utils_boot_id_str (),
|
|
|
f86c11 |
uuid,
|
|
|
f86c11 |
&generated);
|
|
|
f86c11 |
|
|
|
f86c11 |
diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c
|
|
|
f86c11 |
index 4ac68c2da..18d79bd1d 100644
|
|
|
f86c11 |
--- a/src/nm-core-utils.c
|
|
|
f86c11 |
+++ b/src/nm-core-utils.c
|
|
|
f86c11 |
@@ -2669,7 +2669,7 @@ again:
|
|
|
f86c11 |
* to read/write the secret-key to disk. Fallback to boot-id. The boot-id
|
|
|
f86c11 |
* itself may be fake and randomly generated ad-hoc, but that is as best
|
|
|
f86c11 |
* as it gets. */
|
|
|
f86c11 |
- seed_bin = (const guint8 *) nm_utils_get_boot_id_bin ();
|
|
|
f86c11 |
+ seed_bin = (const guint8 *) nm_utils_boot_id_bin ();
|
|
|
f86c11 |
seed_len = sizeof (NMUuid);
|
|
|
f86c11 |
fake_type = "boot-id";
|
|
|
f86c11 |
hash_seed = "7ff0c8f5-5399-4901-ab63-61bf594abe8b";
|
|
|
f86c11 |
@@ -2975,13 +2975,13 @@ again:
|
|
|
f86c11 |
}
|
|
|
f86c11 |
|
|
|
f86c11 |
const char *
|
|
|
f86c11 |
-nm_utils_get_boot_id_str (void)
|
|
|
f86c11 |
+nm_utils_boot_id_str (void)
|
|
|
f86c11 |
{
|
|
|
f86c11 |
return _boot_id_get ()->str;
|
|
|
f86c11 |
}
|
|
|
f86c11 |
|
|
|
f86c11 |
const NMUuid *
|
|
|
f86c11 |
-nm_utils_get_boot_id_bin (void)
|
|
|
f86c11 |
+nm_utils_boot_id_bin (void)
|
|
|
f86c11 |
{
|
|
|
f86c11 |
return &_boot_id_get ()->bin;
|
|
|
f86c11 |
}
|
|
|
f86c11 |
diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h
|
|
|
f86c11 |
index c93e69bbd..51a695f9f 100644
|
|
|
f86c11 |
--- a/src/nm-core-utils.h
|
|
|
f86c11 |
+++ b/src/nm-core-utils.h
|
|
|
f86c11 |
@@ -286,8 +286,8 @@ const char *nm_utils_machine_id_str (void);
|
|
|
f86c11 |
const struct _NMUuid *nm_utils_machine_id_bin (void);
|
|
|
f86c11 |
gboolean nm_utils_machine_id_is_fake (void);
|
|
|
f86c11 |
|
|
|
f86c11 |
-const char *nm_utils_get_boot_id_str (void);
|
|
|
f86c11 |
-const struct _NMUuid *nm_utils_get_boot_id_bin (void);
|
|
|
f86c11 |
+const char *nm_utils_boot_id_str (void);
|
|
|
f86c11 |
+const struct _NMUuid *nm_utils_boot_id_bin (void);
|
|
|
f86c11 |
|
|
|
f86c11 |
gboolean nm_utils_host_id_get (const guint8 **out_host_id,
|
|
|
f86c11 |
gsize *out_host_id_len);
|
|
|
f86c11 |
--
|
|
|
f86c11 |
2.19.2
|
|
|
f86c11 |
|
|
|
f86c11 |
|
|
|
f86c11 |
From 221a0ad9f6594ad0e91211f1fcc0bbe273b7c0cb Mon Sep 17 00:00:00 2001
|
|
|
f86c11 |
From: Thomas Haller <thaller@redhat.com>
|
|
|
f86c11 |
Date: Wed, 12 Dec 2018 11:03:02 +0100
|
|
|
f86c11 |
Subject: [PATCH 09/10] core: split initializing host-id singleton out of
|
|
|
f86c11 |
nm_utils_host_id_get()
|
|
|
f86c11 |
|
|
|
f86c11 |
(cherry picked from commit e9887d4816805d939e91215ad137b94ffa3c2c5d)
|
|
|
f86c11 |
(cherry picked from commit 164d796cf87e1f99ac2a2581f0f7096e6e230408)
|
|
|
f86c11 |
---
|
|
|
f86c11 |
src/nm-core-utils.c | 47 ++++++++++++++++++++++++++-------------------
|
|
|
f86c11 |
1 file changed, 27 insertions(+), 20 deletions(-)
|
|
|
f86c11 |
|
|
|
f86c11 |
diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c
|
|
|
f86c11 |
index 18d79bd1d..b4997db21 100644
|
|
|
f86c11 |
--- a/src/nm-core-utils.c
|
|
|
f86c11 |
+++ b/src/nm-core-utils.c
|
|
|
f86c11 |
@@ -2877,6 +2877,31 @@ typedef struct {
|
|
|
f86c11 |
bool is_good:1;
|
|
|
f86c11 |
} HostIdData;
|
|
|
f86c11 |
|
|
|
f86c11 |
+static const HostIdData *
|
|
|
f86c11 |
+_host_id_get (void)
|
|
|
f86c11 |
+{
|
|
|
f86c11 |
+ static const HostIdData *volatile host_id_static;
|
|
|
f86c11 |
+ const HostIdData *host_id;
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+again:
|
|
|
f86c11 |
+ host_id = g_atomic_pointer_get (&host_id_static);
|
|
|
f86c11 |
+ if (G_UNLIKELY (!host_id)) {
|
|
|
f86c11 |
+ static HostIdData host_id_data;
|
|
|
f86c11 |
+ static gsize init_value = 0;
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+ if (!g_once_init_enter (&init_value))
|
|
|
f86c11 |
+ goto again;
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+ host_id_data.is_good = _host_id_read (&host_id_data.host_id,
|
|
|
f86c11 |
+ &host_id_data.host_id_len);
|
|
|
f86c11 |
+ host_id = &host_id_data;
|
|
|
f86c11 |
+ g_atomic_pointer_set (&host_id_static, host_id);
|
|
|
f86c11 |
+ g_once_init_leave (&init_value, 1);
|
|
|
f86c11 |
+ }
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+ return host_id;
|
|
|
f86c11 |
+}
|
|
|
f86c11 |
+
|
|
|
f86c11 |
/**
|
|
|
f86c11 |
* nm_utils_host_id_get:
|
|
|
f86c11 |
* @out_host_id: (out) (transfer none): the binary host key
|
|
|
f86c11 |
@@ -2896,25 +2921,9 @@ gboolean
|
|
|
f86c11 |
nm_utils_host_id_get (const guint8 **out_host_id,
|
|
|
f86c11 |
gsize *out_host_id_len)
|
|
|
f86c11 |
{
|
|
|
f86c11 |
- static const HostIdData *volatile host_id_static;
|
|
|
f86c11 |
const HostIdData *host_id;
|
|
|
f86c11 |
|
|
|
f86c11 |
-again:
|
|
|
f86c11 |
- host_id = g_atomic_pointer_get (&host_id_static);
|
|
|
f86c11 |
- if (G_UNLIKELY (!host_id)) {
|
|
|
f86c11 |
- static HostIdData host_id_data;
|
|
|
f86c11 |
- static gsize init_value = 0;
|
|
|
f86c11 |
-
|
|
|
f86c11 |
- if (!g_once_init_enter (&init_value))
|
|
|
f86c11 |
- goto again;
|
|
|
f86c11 |
-
|
|
|
f86c11 |
- host_id_data.is_good = _host_id_read (&host_id_data.host_id,
|
|
|
f86c11 |
- &host_id_data.host_id_len);
|
|
|
f86c11 |
- host_id = &host_id_data;
|
|
|
f86c11 |
- g_atomic_pointer_set (&host_id_static, host_id);
|
|
|
f86c11 |
- g_once_init_leave (&init_value, 1);
|
|
|
f86c11 |
- }
|
|
|
f86c11 |
-
|
|
|
f86c11 |
+ host_id = _host_id_get ();
|
|
|
f86c11 |
*out_host_id = host_id->host_id;
|
|
|
f86c11 |
*out_host_id_len = host_id->host_id_len;
|
|
|
f86c11 |
return host_id->is_good;
|
|
|
f86c11 |
@@ -2924,10 +2933,8 @@ gint64
|
|
|
f86c11 |
nm_utils_host_id_get_timestamp (void)
|
|
|
f86c11 |
{
|
|
|
f86c11 |
struct stat stat_buf;
|
|
|
f86c11 |
- const guint8 *host_id;
|
|
|
f86c11 |
- gsize host_id_len;
|
|
|
f86c11 |
|
|
|
f86c11 |
- if (!nm_utils_host_id_get (&host_id, &host_id_len))
|
|
|
f86c11 |
+ if (!_host_id_get ()->is_good)
|
|
|
f86c11 |
return 0;
|
|
|
f86c11 |
|
|
|
f86c11 |
if (stat (SECRET_KEY_FILE, &stat_buf) != 0)
|
|
|
f86c11 |
--
|
|
|
f86c11 |
2.19.2
|
|
|
f86c11 |
|
|
|
f86c11 |
|
|
|
f86c11 |
From 51853f1456413b6ba45890932d4d4cf08b4f76b0 Mon Sep 17 00:00:00 2001
|
|
|
f86c11 |
From: Thomas Haller <thaller@redhat.com>
|
|
|
f86c11 |
Date: Wed, 12 Dec 2018 11:04:12 +0100
|
|
|
f86c11 |
Subject: [PATCH 10/10] core: never fail reading host-id timestamp and never
|
|
|
f86c11 |
change it
|
|
|
f86c11 |
|
|
|
f86c11 |
The timestamp of the host-id is the timestamp of the secret_key file.
|
|
|
f86c11 |
Under normal circumstances, reading the timestamp should never fail,
|
|
|
f86c11 |
and reading it multiple times should always yield the same result.
|
|
|
f86c11 |
|
|
|
f86c11 |
If we unexpectedly fail to read the timestamp from the file we want:
|
|
|
f86c11 |
|
|
|
f86c11 |
- log a warning, so that the user can find out what's wrong. But
|
|
|
f86c11 |
do so only once.
|
|
|
f86c11 |
|
|
|
f86c11 |
- we don't want to handle errors or fail operation due to a missing
|
|
|
f86c11 |
timestamp. Remember, it's not supposed to ever fail, and if it does,
|
|
|
f86c11 |
just log a warning and proceed with a fake timestamp instead. In
|
|
|
f86c11 |
that case something is wrong, but using a non-stable, fake timestamp
|
|
|
f86c11 |
is the least of the problems here.
|
|
|
f86c11 |
We already have a stable identifier (the host-id) which we can use to
|
|
|
f86c11 |
generate a fake timestamp. Use it.
|
|
|
f86c11 |
|
|
|
f86c11 |
In case the user would replace the secret_key file, we also don't want
|
|
|
f86c11 |
that accessing nm_utils_host_id_get_timestamp*() yields different
|
|
|
f86c11 |
results. It's not implemented (nor necessary) to support reloading a
|
|
|
f86c11 |
different timestamp. Hence, nm_utils_host_id_get_timestamp() should
|
|
|
f86c11 |
memoize the value and ensure that it never changes.
|
|
|
f86c11 |
|
|
|
f86c11 |
(cherry picked from commit a68d027ba4537a6e30272e39a9f7927bcdca0eee)
|
|
|
f86c11 |
(cherry picked from commit 62722347c58fc0dfc8805a41813781e5a4ecacdf)
|
|
|
f86c11 |
---
|
|
|
f86c11 |
src/devices/nm-device.c | 18 +++--------
|
|
|
f86c11 |
src/nm-core-utils.c | 66 ++++++++++++++++++++++++++++++++++-------
|
|
|
f86c11 |
src/nm-core-utils.h | 2 +-
|
|
|
f86c11 |
3 files changed, 61 insertions(+), 25 deletions(-)
|
|
|
f86c11 |
|
|
|
f86c11 |
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
|
|
|
f86c11 |
index 738e032e3..d72c946bd 100644
|
|
|
f86c11 |
--- a/src/devices/nm-device.c
|
|
|
f86c11 |
+++ b/src/devices/nm-device.c
|
|
|
f86c11 |
@@ -8315,15 +8315,8 @@ dhcp6_get_duid (NMDevice *self, NMConnection *connection, GBytes *hwaddr, gboole
|
|
|
f86c11 |
if (nm_streq (duid, "ll")) {
|
|
|
f86c11 |
duid_out = generate_duid_ll (g_bytes_get_data (hwaddr, NULL));
|
|
|
f86c11 |
} else {
|
|
|
f86c11 |
- gint64 time;
|
|
|
f86c11 |
-
|
|
|
f86c11 |
- time = nm_utils_host_id_get_timestamp ();
|
|
|
f86c11 |
- if (!time) {
|
|
|
f86c11 |
- duid_error = "cannot retrieve the secret key timestamp";
|
|
|
f86c11 |
- goto out_fail;
|
|
|
f86c11 |
- }
|
|
|
f86c11 |
-
|
|
|
f86c11 |
- duid_out = generate_duid_llt (g_bytes_get_data (hwaddr, NULL), time);
|
|
|
f86c11 |
+ duid_out = generate_duid_llt (g_bytes_get_data (hwaddr, NULL),
|
|
|
f86c11 |
+ nm_utils_host_id_get_timestamp_ns () / NM_UTILS_NS_PER_SECOND);
|
|
|
f86c11 |
}
|
|
|
f86c11 |
|
|
|
f86c11 |
goto out_good;
|
|
|
f86c11 |
@@ -8373,11 +8366,8 @@ dhcp6_get_duid (NMDevice *self, NMConnection *connection, GBytes *hwaddr, gboole
|
|
|
f86c11 |
* before. Let's compute the time (in seconds) from 0 to 3 years; then we'll
|
|
|
f86c11 |
* subtract it from the host_id timestamp.
|
|
|
f86c11 |
*/
|
|
|
f86c11 |
- time = nm_utils_host_id_get_timestamp ();
|
|
|
f86c11 |
- if (!time) {
|
|
|
f86c11 |
- duid_error = "cannot retrieve the secret key timestamp";
|
|
|
f86c11 |
- goto out_fail;
|
|
|
f86c11 |
- }
|
|
|
f86c11 |
+ time = nm_utils_host_id_get_timestamp_ns () / NM_UTILS_NS_PER_SECOND;
|
|
|
f86c11 |
+
|
|
|
f86c11 |
/* don't use too old timestamps. They cannot be expressed in DUID-LLT and
|
|
|
f86c11 |
* would all be truncated to zero. */
|
|
|
f86c11 |
time = NM_MAX (time, EPOCH_DATETIME_200001010000 + EPOCH_DATETIME_THREE_YEARS);
|
|
|
f86c11 |
diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c
|
|
|
f86c11 |
index b4997db21..d5e6346de 100644
|
|
|
f86c11 |
--- a/src/nm-core-utils.c
|
|
|
f86c11 |
+++ b/src/nm-core-utils.c
|
|
|
f86c11 |
@@ -2727,6 +2727,49 @@ nm_utils_machine_id_is_fake (void)
|
|
|
f86c11 |
#define SECRET_KEY_V2_PREFIX "nm-v2:"
|
|
|
f86c11 |
#define SECRET_KEY_FILE NMSTATEDIR"/secret_key"
|
|
|
f86c11 |
|
|
|
f86c11 |
+static gboolean
|
|
|
f86c11 |
+_host_id_read_timestamp (gboolean use_secret_key_file,
|
|
|
f86c11 |
+ const guint8 *host_id,
|
|
|
f86c11 |
+ gsize host_id_len,
|
|
|
f86c11 |
+ gint64 *out_timestamp_ns)
|
|
|
f86c11 |
+{
|
|
|
f86c11 |
+ struct stat st;
|
|
|
f86c11 |
+ gint64 now;
|
|
|
f86c11 |
+ guint64 v;
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+ if ( use_secret_key_file
|
|
|
f86c11 |
+ && stat (SECRET_KEY_FILE, &st) == 0) {
|
|
|
f86c11 |
+ /* don't check for overflow or timestamps in the future. We get whatever
|
|
|
f86c11 |
+ * (bogus) date is on the file. */
|
|
|
f86c11 |
+ *out_timestamp_ns = (st.st_mtim.tv_sec * NM_UTILS_NS_PER_SECOND) + st.st_mtim.tv_nsec;
|
|
|
f86c11 |
+ return TRUE;
|
|
|
f86c11 |
+ }
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+ /* generate a fake timestamp based on the host-id.
|
|
|
f86c11 |
+ *
|
|
|
f86c11 |
+ * This really should never happen under normal circumstances. We already
|
|
|
f86c11 |
+ * are in a code path, where the system has a problem (unable to get good randomness
|
|
|
f86c11 |
+ * and/or can't access the secret_key). In such a scenario, a fake timestamp is the
|
|
|
f86c11 |
+ * least of our problems.
|
|
|
f86c11 |
+ *
|
|
|
f86c11 |
+ * At least, generate something sensible so we don't have to worry about the
|
|
|
f86c11 |
+ * timestamp. It is wrong to worry about using a fake timestamp (which is tied to
|
|
|
f86c11 |
+ * the secret_key) if we are unable to access the secret_key file in the first place.
|
|
|
f86c11 |
+ *
|
|
|
f86c11 |
+ * Pick a random timestamp from the past two years. Yes, this timestamp
|
|
|
f86c11 |
+ * is not stable accross restarts, but apparently neither is the host-id
|
|
|
f86c11 |
+ * nor the secret_key itself. */
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+#define EPOCH_TWO_YEARS (G_GINT64_CONSTANT (2 * 365 * 24 * 3600) * NM_UTILS_NS_PER_SECOND)
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+ v = nm_hash_siphash42 (1156657133u, host_id, host_id_len);
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+ now = time (NULL);
|
|
|
f86c11 |
+ *out_timestamp_ns = NM_MAX ((gint64) 1,
|
|
|
f86c11 |
+ (now * NM_UTILS_NS_PER_SECOND) - ((gint64) (v % ((guint64) (EPOCH_TWO_YEARS)))));
|
|
|
f86c11 |
+ return FALSE;
|
|
|
f86c11 |
+}
|
|
|
f86c11 |
+
|
|
|
f86c11 |
static const guint8 *
|
|
|
f86c11 |
_host_id_hash_v2 (const guint8 *seed_arr,
|
|
|
f86c11 |
gsize seed_len,
|
|
|
f86c11 |
@@ -2874,7 +2917,9 @@ out:
|
|
|
f86c11 |
typedef struct {
|
|
|
f86c11 |
guint8 *host_id;
|
|
|
f86c11 |
gsize host_id_len;
|
|
|
f86c11 |
+ gint64 timestamp_ns;
|
|
|
f86c11 |
bool is_good:1;
|
|
|
f86c11 |
+ bool timestamp_is_good:1;
|
|
|
f86c11 |
} HostIdData;
|
|
|
f86c11 |
|
|
|
f86c11 |
static const HostIdData *
|
|
|
f86c11 |
@@ -2894,6 +2939,15 @@ again:
|
|
|
f86c11 |
|
|
|
f86c11 |
host_id_data.is_good = _host_id_read (&host_id_data.host_id,
|
|
|
f86c11 |
&host_id_data.host_id_len);
|
|
|
f86c11 |
+
|
|
|
f86c11 |
+ host_id_data.timestamp_is_good = _host_id_read_timestamp (host_id_data.is_good,
|
|
|
f86c11 |
+ host_id_data.host_id,
|
|
|
f86c11 |
+ host_id_data.host_id_len,
|
|
|
f86c11 |
+ &host_id_data.timestamp_ns);
|
|
|
f86c11 |
+ if ( !host_id_data.timestamp_is_good
|
|
|
f86c11 |
+ && host_id_data.is_good)
|
|
|
f86c11 |
+ nm_log_warn (LOGD_CORE, "secret-key: failure reading host timestamp (use fake one)");
|
|
|
f86c11 |
+
|
|
|
f86c11 |
host_id = &host_id_data;
|
|
|
f86c11 |
g_atomic_pointer_set (&host_id_static, host_id);
|
|
|
f86c11 |
g_once_init_leave (&init_value, 1);
|
|
|
f86c11 |
@@ -2930,17 +2984,9 @@ nm_utils_host_id_get (const guint8 **out_host_id,
|
|
|
f86c11 |
}
|
|
|
f86c11 |
|
|
|
f86c11 |
gint64
|
|
|
f86c11 |
-nm_utils_host_id_get_timestamp (void)
|
|
|
f86c11 |
+nm_utils_host_id_get_timestamp_ns (void)
|
|
|
f86c11 |
{
|
|
|
f86c11 |
- struct stat stat_buf;
|
|
|
f86c11 |
-
|
|
|
f86c11 |
- if (!_host_id_get ()->is_good)
|
|
|
f86c11 |
- return 0;
|
|
|
f86c11 |
-
|
|
|
f86c11 |
- if (stat (SECRET_KEY_FILE, &stat_buf) != 0)
|
|
|
f86c11 |
- return 0;
|
|
|
f86c11 |
-
|
|
|
f86c11 |
- return stat_buf.st_mtim.tv_sec;
|
|
|
f86c11 |
+ return _host_id_get ()->timestamp_ns;
|
|
|
f86c11 |
}
|
|
|
f86c11 |
|
|
|
f86c11 |
/*****************************************************************************/
|
|
|
f86c11 |
diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h
|
|
|
f86c11 |
index 51a695f9f..16ca50b60 100644
|
|
|
f86c11 |
--- a/src/nm-core-utils.h
|
|
|
f86c11 |
+++ b/src/nm-core-utils.h
|
|
|
f86c11 |
@@ -291,7 +291,7 @@ const struct _NMUuid *nm_utils_boot_id_bin (void);
|
|
|
f86c11 |
|
|
|
f86c11 |
gboolean nm_utils_host_id_get (const guint8 **out_host_id,
|
|
|
f86c11 |
gsize *out_host_id_len);
|
|
|
f86c11 |
-gint64 nm_utils_host_id_get_timestamp (void);
|
|
|
f86c11 |
+gint64 nm_utils_host_id_get_timestamp_ns (void);
|
|
|
f86c11 |
|
|
|
f86c11 |
/* IPv6 Interface Identifier helpers */
|
|
|
f86c11 |
|
|
|
f86c11 |
--
|
|
|
f86c11 |
2.19.2
|
|
|
f86c11 |
|