mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-31 14:50:10 +01:00
core: add nm_utils_get_secret_key() util
(cherry picked from commit d787b8c827)
This commit is contained in:
parent
50dc5fecab
commit
de22249183
3 changed files with 69 additions and 49 deletions
|
|
@ -2559,6 +2559,63 @@ nm_utils_is_specific_hostname (const char *name)
|
|||
|
||||
/******************************************************************/
|
||||
|
||||
guint8 *
|
||||
nm_utils_secret_key_read (gsize *out_key_len, GError **error)
|
||||
{
|
||||
guint8 *secret_key = NULL;
|
||||
gsize key_len;
|
||||
|
||||
/* out_key_len is not optional, because without it you cannot safely
|
||||
* access the returned memory. */
|
||||
*out_key_len = 0;
|
||||
|
||||
/* Let's try to load a saved secret key first. */
|
||||
if (g_file_get_contents (NMSTATEDIR "/secret_key", (char **) &secret_key, &key_len, NULL)) {
|
||||
if (key_len < 16) {
|
||||
g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
|
||||
"Key is too short to be usable");
|
||||
key_len = 0;
|
||||
}
|
||||
} else {
|
||||
int urandom = open ("/dev/urandom", O_RDONLY);
|
||||
mode_t key_mask;
|
||||
|
||||
if (urandom == -1) {
|
||||
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
|
||||
"Can't open /dev/urandom: %s", strerror (errno));
|
||||
key_len = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* RFC7217 mandates the key SHOULD be at least 128 bits.
|
||||
* Let's use twice as much. */
|
||||
key_len = 32;
|
||||
secret_key = g_malloc (key_len);
|
||||
|
||||
key_mask = umask (0077);
|
||||
if (read (urandom, secret_key, key_len) == key_len) {
|
||||
if (!g_file_set_contents (NMSTATEDIR "/secret_key", (char *) secret_key, key_len, error)) {
|
||||
g_prefix_error (error, "Can't write " NMSTATEDIR "/secret_key: ");
|
||||
key_len = 0;
|
||||
}
|
||||
} else {
|
||||
g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
|
||||
"Could not obtain a secret");
|
||||
key_len = 0;
|
||||
}
|
||||
umask (key_mask);
|
||||
close (urandom);
|
||||
}
|
||||
|
||||
out:
|
||||
if (key_len) {
|
||||
*out_key_len = key_len;
|
||||
return secret_key;
|
||||
}
|
||||
g_free (secret_key);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Returns the "u" (universal/local) bit value for a Modified EUI-64 */
|
||||
static gboolean
|
||||
get_gre_eui64_u_bit (guint32 addr)
|
||||
|
|
@ -2686,7 +2743,7 @@ _set_stable_privacy (struct in6_addr *addr,
|
|||
const char *ifname,
|
||||
const char *uuid,
|
||||
guint dad_counter,
|
||||
gchar *secret_key,
|
||||
guint8 *secret_key,
|
||||
gsize key_len,
|
||||
GError **error)
|
||||
{
|
||||
|
|
@ -2744,9 +2801,8 @@ nm_utils_ipv6_addr_set_stable_privacy (struct in6_addr *addr,
|
|||
guint dad_counter,
|
||||
GError **error)
|
||||
{
|
||||
gchar *secret_key = NULL;
|
||||
gs_free guint8 *secret_key = NULL;
|
||||
gsize key_len = 0;
|
||||
gboolean success = FALSE;
|
||||
|
||||
if (dad_counter >= RFC7217_IDGEN_RETRIES) {
|
||||
g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
|
||||
|
|
@ -2754,50 +2810,12 @@ nm_utils_ipv6_addr_set_stable_privacy (struct in6_addr *addr,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/* Let's try to load a saved secret key first. */
|
||||
if (g_file_get_contents (NMSTATEDIR "/secret_key", &secret_key, &key_len, NULL)) {
|
||||
if (key_len < 16) {
|
||||
g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
|
||||
"Key is too short to be usable");
|
||||
key_len = 0;
|
||||
}
|
||||
} else {
|
||||
int urandom = open ("/dev/urandom", O_RDONLY);
|
||||
mode_t key_mask;
|
||||
secret_key = nm_utils_secret_key_read (&key_len, error);
|
||||
if (!secret_key)
|
||||
return FALSE;
|
||||
|
||||
if (urandom == -1) {
|
||||
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
|
||||
"Can't open /dev/urandom: %s", strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* RFC7217 mandates the key SHOULD be at least 128 bits.
|
||||
* Let's use twice as much. */
|
||||
key_len = 32;
|
||||
secret_key = g_malloc (key_len);
|
||||
|
||||
key_mask = umask (0077);
|
||||
if (read (urandom, secret_key, key_len) == key_len) {
|
||||
if (!g_file_set_contents (NMSTATEDIR "/secret_key", secret_key, key_len, error)) {
|
||||
g_prefix_error (error, "Can't write " NMSTATEDIR "/secret_key: ");
|
||||
key_len = 0;
|
||||
}
|
||||
} else {
|
||||
g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
|
||||
"Could not obtain a secret");
|
||||
key_len = 0;
|
||||
}
|
||||
umask (key_mask);
|
||||
close (urandom);
|
||||
}
|
||||
|
||||
if (key_len) {
|
||||
success = _set_stable_privacy (addr, ifname, uuid, dad_counter,
|
||||
secret_key, key_len, error);
|
||||
}
|
||||
|
||||
g_free (secret_key);
|
||||
return success;
|
||||
return _set_stable_privacy (addr, ifname, uuid, dad_counter,
|
||||
secret_key, key_len, error);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -306,6 +306,8 @@ const char *nm_utils_ip4_property_path (const char *ifname, const char *property
|
|||
|
||||
gboolean nm_utils_is_specific_hostname (const char *name);
|
||||
|
||||
guint8 *nm_utils_secret_key_read (gsize *out_key_len, GError **error);
|
||||
|
||||
/* IPv6 Interface Identifer helpers */
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -34,17 +34,17 @@ test_stable_privacy (void)
|
|||
struct in6_addr addr1;
|
||||
|
||||
inet_pton (AF_INET6, "1234::", &addr1);
|
||||
_set_stable_privacy (&addr1, "eth666", "6b138152-9f3e-4b97-aaf7-e6e553f2a24e", 0, "key", 3, NULL);
|
||||
_set_stable_privacy (&addr1, "eth666", "6b138152-9f3e-4b97-aaf7-e6e553f2a24e", 0, (guint8 *) "key", 3, NULL);
|
||||
nmtst_assert_ip6_address (&addr1, "1234::4ceb:14cd:3d54:793f");
|
||||
|
||||
/* We get an address without the UUID. */
|
||||
inet_pton (AF_INET6, "1::", &addr1);
|
||||
_set_stable_privacy (&addr1, "eth666", NULL, 384, "key", 3, NULL);
|
||||
_set_stable_privacy (&addr1, "eth666", NULL, 384, (guint8 *) "key", 3, NULL);
|
||||
nmtst_assert_ip6_address (&addr1, "1::11aa:2530:9144:dafa");
|
||||
|
||||
/* We get a different address in a different network. */
|
||||
inet_pton (AF_INET6, "2::", &addr1);
|
||||
_set_stable_privacy (&addr1, "eth666", NULL, 384, "key", 3, NULL);
|
||||
_set_stable_privacy (&addr1, "eth666", NULL, 384, (guint8 *) "key", 3, NULL);
|
||||
nmtst_assert_ip6_address (&addr1, "2::338e:8d:c11:8726");
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue