diff options
author | Thomas Haller <thaller@redhat.com> | 2016-04-25 18:14:25 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2016-04-26 12:48:27 +0200 |
commit | d787b8c827965de885f5736c7b69a7042e798d36 (patch) | |
tree | bea98c1db30bf30265f06ee84911bba472b8551b | |
parent | dd4d8b24da29abfc786ce0b3030c74559b93d034 (diff) | |
download | NetworkManager-d787b8c827965de885f5736c7b69a7042e798d36.tar.gz |
core: add nm_utils_get_secret_key() util
-rw-r--r-- | src/nm-core-utils.c | 110 | ||||
-rw-r--r-- | src/nm-core-utils.h | 2 | ||||
-rw-r--r-- | src/tests/test-utils.c | 6 |
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"); } |