summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2016-04-25 18:14:25 +0200
committerThomas Haller <thaller@redhat.com>2016-04-26 12:48:27 +0200
commitd787b8c827965de885f5736c7b69a7042e798d36 (patch)
treebea98c1db30bf30265f06ee84911bba472b8551b
parentdd4d8b24da29abfc786ce0b3030c74559b93d034 (diff)
downloadNetworkManager-d787b8c827965de885f5736c7b69a7042e798d36.tar.gz
core: add nm_utils_get_secret_key() util
-rw-r--r--src/nm-core-utils.c110
-rw-r--r--src/nm-core-utils.h2
-rw-r--r--src/tests/test-utils.c6
3 files changed, 69 insertions, 49 deletions
diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c
index 188e4737af..b93de1e2a5 100644
--- a/src/nm-core-utils.c
+++ b/src/nm-core-utils.c
@@ -2588,6 +2588,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)
@@ -2715,7 +2772,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)
{
@@ -2773,9 +2830,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,
@@ -2783,50 +2839,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;
-
- 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);
- }
+ secret_key = nm_utils_secret_key_read (&key_len, error);
+ if (!secret_key)
+ return FALSE;
- g_free (secret_key);
- return success;
+ return _set_stable_privacy (addr, ifname, uuid, dad_counter,
+ secret_key, key_len, error);
}
/**
diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h
index 486942a22a..83794b092a 100644
--- a/src/nm-core-utils.h
+++ b/src/nm-core-utils.h
@@ -307,6 +307,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 */
/**
diff --git a/src/tests/test-utils.c b/src/tests/test-utils.c
index c8c82aefe4..6fc3978b9c 100644
--- a/src/tests/test-utils.c
+++ b/src/tests/test-utils.c
@@ -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");
}