diff options
| author | Michael Biebl <biebl@debian.org> | 2018-10-20 01:30:31 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2018-10-20 01:30:31 +0200 |
| commit | 6518e361171f64bcaaa4bf868139362ed95cc2e0 (patch) | |
| tree | d2d5b53faf80646a40ec2c0c7f2a42b3959612f5 /libnm-core/nm-utils.c | |
| parent | e126f3e804c35480c4f075777430419d6ece23da (diff) | |
New upstream version 1.14.2 upstream/1.14.2
Diffstat (limited to 'libnm-core/nm-utils.c')
| -rw-r--r-- | libnm-core/nm-utils.c | 779 |
1 files changed, 420 insertions, 359 deletions
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index b700c7f5..0f524e11 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -43,7 +43,7 @@ #include "nm-common-macros.h" #include "nm-utils-private.h" #include "nm-setting-private.h" -#include "crypto.h" +#include "nm-crypto.h" #include "nm-setting-bond.h" #include "nm-setting-bridge.h" #include "nm-setting-infiniband.h" @@ -230,31 +230,33 @@ get_system_encodings (void) return cached_encodings; } -/* init libnm */ - -static gboolean initialized = FALSE; +/*****************************************************************************/ static void __attribute__((constructor)) _nm_utils_init (void) { - GModule *self; - gpointer func; + static int initialized = 0; - if (initialized) + if (g_atomic_int_get (&initialized) != 0) return; - initialized = TRUE; - self = g_module_open (NULL, 0); - if (g_module_symbol (self, "nm_util_get_private", &func)) - g_error ("libnm-util symbols detected; Mixing libnm with libnm-util/libnm-glib is not supported"); - g_module_close (self); + /* we don't expect this code to run multiple times, nor on multiple threads. + * + * In practice, it would not be a problem if two threads concurrently try to + * run the initialization code below, all code below itself is thread-safe, + * Hence, a poor-man guard "initialized" above is more than sufficient, + * although it does not guarantee that the code is not run concurrently. */ bindtextdomain (GETTEXT_PACKAGE, NMLOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); _nm_dbus_errors_init (); + + g_atomic_int_set (&initialized, 1); } +/*****************************************************************************/ + gboolean _nm_utils_is_manager_process; /* ssid helpers */ @@ -300,19 +302,19 @@ nm_utils_ssid_to_utf8 (const guint8 *ssid, gsize len) g_return_val_if_fail (ssid != NULL, NULL); - if (g_utf8_validate ((const gchar *) ssid, len, NULL)) - return g_strndup ((const gchar *) ssid, len); + if (g_utf8_validate ((const char *) ssid, len, NULL)) + return g_strndup ((const char *) ssid, len); encodings = get_system_encodings (); for (e = encodings; *e; e++) { - converted = g_convert ((const gchar *) ssid, len, "UTF-8", *e, NULL, NULL, NULL); + converted = g_convert ((const char *) ssid, len, "UTF-8", *e, NULL, NULL, NULL); if (converted) break; } if (!converted) { - converted = g_convert_with_fallback ((const gchar *) ssid, len, + converted = g_convert_with_fallback ((const char *) ssid, len, "UTF-8", encodings[0], "?", NULL, NULL, NULL); } @@ -323,7 +325,7 @@ nm_utils_ssid_to_utf8 (const guint8 *ssid, gsize len) */ /* Use the printable range of 0x20-0x7E */ - gchar *valid_chars = " !\"#$%&'()*+,-./0123456789:;<=>?@" + char *valid_chars = " !\"#$%&'()*+,-./0123456789:;<=>?@" "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`" "abcdefghijklmnopqrstuvwxyz{|}~"; @@ -334,6 +336,18 @@ nm_utils_ssid_to_utf8 (const guint8 *ssid, gsize len) return converted; } +char * +_nm_utils_ssid_to_utf8 (GBytes *ssid) +{ + const guint8 *p; + gsize l; + + g_return_val_if_fail (ssid, NULL); + + p = g_bytes_get_data (ssid, &l); + return nm_utils_ssid_to_utf8 (p, l); +} + /* Shamelessly ripped from the Linux kernel ieee80211 stack */ /** * nm_utils_is_empty_ssid: @@ -361,6 +375,18 @@ nm_utils_is_empty_ssid (const guint8 *ssid, gsize len) return TRUE; } +gboolean +_nm_utils_is_empty_ssid (GBytes *ssid) +{ + const guint8 *p; + gsize l; + + g_return_val_if_fail (ssid, FALSE); + + p = g_bytes_get_data (ssid, &l); + return nm_utils_is_empty_ssid (p, l); +} + #define ESSID_MAX_SIZE 32 /** @@ -402,6 +428,37 @@ nm_utils_escape_ssid (const guint8 *ssid, gsize len) return escaped; } +char * +_nm_utils_ssid_to_string_arr (const guint8 *ssid, gsize len) +{ + gs_free char *s_copy = NULL; + const char *s_cnst; + + if (len == 0) + return g_strdup ("(empty)"); + + s_cnst = nm_utils_buf_utf8safe_escape (ssid, len, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL, &s_copy); + nm_assert (s_cnst); + + if (nm_utils_is_empty_ssid (ssid, len)) + return g_strdup_printf ("\"%s\" (hidden)", s_cnst); + + return g_strdup_printf ("\"%s\"", s_cnst); +} + +char * +_nm_utils_ssid_to_string (GBytes *ssid) +{ + gconstpointer p; + gsize l; + + if (!ssid) + return g_strdup ("(none)"); + + p = g_bytes_get_data (ssid, &l); + return _nm_utils_ssid_to_string_arr (p, l); +} + /** * nm_utils_same_ssid: * @ssid1: (array length=len1): the first SSID to compare @@ -566,39 +623,6 @@ _nm_utils_copy_strdict (GHashTable *strdict) } GPtrArray * -_nm_utils_copy_slist_to_array (const GSList *list, - NMUtilsCopyFunc copy_func, - GDestroyNotify unref_func) -{ - const GSList *iter; - GPtrArray *array; - - array = g_ptr_array_new_with_free_func (unref_func); - for (iter = list; iter; iter = iter->next) - g_ptr_array_add (array, copy_func ? copy_func (iter->data) : iter->data); - return array; -} - -GSList * -_nm_utils_copy_array_to_slist (const GPtrArray *array, - NMUtilsCopyFunc copy_func) -{ - GSList *slist = NULL; - gpointer item; - int i; - - if (!array) - return NULL; - - for (i = 0; i < array->len; i++) { - item = array->pdata[i]; - slist = g_slist_prepend (slist, copy_func (item)); - } - - return g_slist_reverse (slist); -} - -GPtrArray * _nm_utils_copy_array (const GPtrArray *array, NMUtilsCopyFunc copy_func, GDestroyNotify free_func) @@ -645,136 +669,6 @@ _nm_utils_ptrarray_find_first (gconstpointer *list, gssize len, gconstpointer ne return -1; } -gssize -_nm_utils_ptrarray_find_binary_search (gconstpointer *list, - gsize len, - gconstpointer needle, - GCompareDataFunc cmpfcn, - gpointer user_data, - gssize *out_idx_first, - gssize *out_idx_last) -{ - gssize imin, imax, imid, i2min, i2max, i2mid; - int cmp; - - g_return_val_if_fail (list || !len, ~((gssize) 0)); - g_return_val_if_fail (cmpfcn, ~((gssize) 0)); - - imin = 0; - if (len > 0) { - imax = len - 1; - - while (imin <= imax) { - imid = imin + (imax - imin) / 2; - - cmp = cmpfcn (list[imid], needle, user_data); - if (cmp == 0) { - /* we found a matching entry at index imid. - * - * Does the caller request the first/last index as well (in case that - * there are multiple entries which compare equal). */ - - if (out_idx_first) { - i2min = imin; - i2max = imid + 1; - while (i2min <= i2max) { - i2mid = i2min + (i2max - i2min) / 2; - - cmp = cmpfcn (list[i2mid], needle, user_data); - if (cmp == 0) - i2max = i2mid -1; - else { - nm_assert (cmp < 0); - i2min = i2mid + 1; - } - } - *out_idx_first = i2min; - } - if (out_idx_last) { - i2min = imid + 1; - i2max = imax; - while (i2min <= i2max) { - i2mid = i2min + (i2max - i2min) / 2; - - cmp = cmpfcn (list[i2mid], needle, user_data); - if (cmp == 0) - i2min = i2mid + 1; - else { - nm_assert (cmp > 0); - i2max = i2mid - 1; - } - } - *out_idx_last = i2min - 1; - } - return imid; - } - - if (cmp < 0) - imin = imid + 1; - else - imax = imid - 1; - } - } - - /* return the inverse of @imin. This is a negative number, but - * also is ~imin the position where the value should be inserted. */ - imin = ~imin; - NM_SET_OUT (out_idx_first, imin); - NM_SET_OUT (out_idx_last, imin); - return imin; -} - -gssize -_nm_utils_array_find_binary_search (gconstpointer list, gsize elem_size, gsize len, gconstpointer needle, GCompareDataFunc cmpfcn, gpointer user_data) -{ - gssize imin, imax, imid; - int cmp; - - g_return_val_if_fail (list || !len, ~((gssize) 0)); - g_return_val_if_fail (cmpfcn, ~((gssize) 0)); - g_return_val_if_fail (elem_size > 0, ~((gssize) 0)); - - imin = 0; - if (len == 0) - return ~imin; - - imax = len - 1; - - while (imin <= imax) { - imid = imin + (imax - imin) / 2; - - cmp = cmpfcn (&((const char *) list)[elem_size * imid], needle, user_data); - if (cmp == 0) - return imid; - - if (cmp < 0) - imin = imid + 1; - else - imax = imid - 1; - } - - /* return the inverse of @imin. This is a negative number, but - * also is ~imin the position where the value should be inserted. */ - return ~imin; -} - -GVariant * -_nm_utils_bytes_to_dbus (const GValue *prop_value) -{ - GBytes *bytes = g_value_get_boxed (prop_value); - - if (bytes) { - return g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, - g_bytes_get_data (bytes, NULL), - g_bytes_get_size (bytes), - 1); - } else { - return g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, - NULL, 0, - 1); - } -} - void _nm_utils_bytes_from_dbus (GVariant *dbus_value, GValue *prop_value) @@ -2247,10 +2141,10 @@ _tc_read_common_opts (const char *str, gs_unref_hashtable GHashTable *ht = NULL; GVariant *variant; - ht = nm_utils_parse_variant_attributes (str, - ' ', ' ', FALSE, - tc_object_attribute_spec, - error); + ht = nm_utils_parse_variant_attributes (str, + ' ', ' ', FALSE, + tc_object_attribute_spec, + error); if (!ht) return FALSE; @@ -2610,10 +2504,10 @@ nm_utils_tc_tfilter_from_str (const char *str, GError **error) return NULL; if (rest) { - ht = nm_utils_parse_variant_attributes (rest, - ' ', ' ', FALSE, - tc_tfilter_attribute_spec, - error); + ht = nm_utils_parse_variant_attributes (rest, + ' ', ' ', FALSE, + tc_tfilter_attribute_spec, + error); if (!ht) return NULL; @@ -2648,6 +2542,249 @@ nm_utils_tc_tfilter_from_str (const char *str, GError **error) /*****************************************************************************/ +extern const NMVariantAttributeSpec *const _nm_sriov_vf_attribute_spec[]; + +/** + * nm_utils_sriov_vf_to_str: + * @vf: the %NMSriovVF + * @omit_index: if %TRUE, the VF index will be omitted from output string + * @error: (out) (allow-none): location to store the error on failure + * + * Converts a SR-IOV virtual function object to its string representation. + * + * Returns: a newly allocated string or %NULL on error + * + * Since: 1.14 + */ +char * +nm_utils_sriov_vf_to_str (const NMSriovVF *vf, gboolean omit_index, GError **error) +{ + gs_free NMUtilsNamedValue *values = NULL; + gs_free const char **names = NULL; + const guint *vlan_ids; + guint num_vlans, num_attrs; + guint i; + GString *str; + + str = g_string_new (""); + if (!omit_index) + g_string_append_printf (str, "%u", nm_sriov_vf_get_index (vf)); + + names = nm_sriov_vf_get_attribute_names (vf); + num_attrs = names ? g_strv_length ((char **) names) : 0; + values = g_new0 (NMUtilsNamedValue, num_attrs); + + for (i = 0; i < num_attrs; i++) { + values[i].name = names[i]; + values[i].value_ptr = nm_sriov_vf_get_attribute (vf, names[i]); + } + + if (num_attrs > 0) { + if (!omit_index) + g_string_append_c (str, ' '); + _nm_utils_format_variant_attributes_full (str, values, num_attrs, ' ', '='); + } + + vlan_ids = nm_sriov_vf_get_vlan_ids (vf, &num_vlans); + if (num_vlans != 0) { + g_string_append (str, " vlans"); + for (i = 0; i < num_vlans; i++) { + guint32 qos; + NMSriovVFVlanProtocol protocol; + + qos = nm_sriov_vf_get_vlan_qos (vf, vlan_ids[i]); + protocol = nm_sriov_vf_get_vlan_protocol (vf, vlan_ids[i]); + + g_string_append_c (str, i == 0 ? '=' : ';'); + + g_string_append_printf (str, "%u", vlan_ids[i]); + + if ( qos != 0 + || protocol != NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q) { + g_string_append_printf (str, + ".%u%s", + (unsigned) qos, + protocol == NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q ? "" : ".ad"); + } + } + } + + return g_string_free (str, FALSE); +} + +gboolean +_nm_sriov_vf_parse_vlans (NMSriovVF *vf, const char *str, GError **error) +{ + gs_free const char **vlans = NULL; + guint i; + + vlans = nm_utils_strsplit_set (str, ";", FALSE); + if (!vlans) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "empty VF VLAN"); + return FALSE; + } + + for (i = 0; vlans[i]; i++) { + gs_strfreev char **params = NULL; + guint id = G_MAXUINT; + gint64 qos = -1; + + /* we accept leading/trailing whitespace around vlans[1]. Hence + * the nm_str_skip_leading_spaces() and g_strchomp() below. + * + * However, we don't accept any whitespace inside the specifier. + * Hence the NM_STRCHAR_ALL() checks. */ + + params = g_strsplit (nm_str_skip_leading_spaces (vlans[i]), ".", 3); + if (!params || !params[0] || *params[0] == '\0') { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "empty VF VLAN"); + return FALSE; + } + + if (!params[1]) + g_strchomp (params[0]); + if (NM_STRCHAR_ALL (params[0], ch, ch == 'x' || g_ascii_isdigit (ch))) + id = _nm_utils_ascii_str_to_int64 (params[0], 0, 0, 4095, G_MAXUINT); + if (id == G_MAXUINT) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "invalid VF VLAN id '%s'", + params[0]); + return FALSE; + } + if (!nm_sriov_vf_add_vlan (vf, id)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "duplicate VLAN id %u", + id); + return FALSE; + } + + if (!params[1]) + continue; + + if (!params[2]) + g_strchomp (params[1]); + if (NM_STRCHAR_ALL (params[1], ch, ch == 'x' || g_ascii_isdigit (ch))) + qos = _nm_utils_ascii_str_to_int64 (params[1], 0, 0, G_MAXUINT32, -1); + if (qos == -1) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "invalid VF VLAN QoS '%s'", + params[1]); + return FALSE; + } + nm_sriov_vf_set_vlan_qos (vf, id, qos); + + if (!params[2]) + continue; + + g_strchomp (params[2]); + + if (nm_streq (params[2], "ad")) + nm_sriov_vf_set_vlan_protocol (vf, id, NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD); + else if (nm_streq (params[2], "q")) + nm_sriov_vf_set_vlan_protocol (vf, id, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); + else { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "invalid VF VLAN protocol '%s'", + params[2]); + return FALSE; + } + } + + return TRUE; +} + +/** + * nm_utils_sriov_vf_from_str: + * @str: the input string + * @error: (out) (allow-none): location to store the error on failure + * + * Converts a string to a SR-IOV virtual function object. + * + * Returns: (transfer full): the virtual function object + * + * Since: 1.14 + */ +NMSriovVF * +nm_utils_sriov_vf_from_str (const char *str, GError **error) +{ + gs_free char *index_free = NULL; + const char *detail; + + g_return_val_if_fail (str, NULL); + g_return_val_if_fail (!error || !*error, NULL); + + while (*str == ' ') + str++; + + detail = strchr (str, ' '); + if (detail) { + index_free = g_strndup (str, detail - str); + str = index_free; + detail++; + } + + return _nm_utils_sriov_vf_from_strparts (str, detail, error); +} + +NMSriovVF * +_nm_utils_sriov_vf_from_strparts (const char *index, const char *detail, GError **error) +{ + NMSriovVF *vf; + guint32 n_index; + GHashTableIter iter; + char *key; + GVariant *variant; + gs_unref_hashtable GHashTable *ht = NULL; + + n_index = _nm_utils_ascii_str_to_int64 (index, 10, 0, G_MAXUINT32, 0); + if (errno) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "invalid index"); + return NULL; + } + + vf = nm_sriov_vf_new (n_index); + if (detail) { + ht = nm_utils_parse_variant_attributes (detail, ' ', '=', TRUE, _nm_sriov_vf_attribute_spec, error); + if (!ht) { + nm_sriov_vf_unref (vf); + return NULL; + } + + if ((variant = g_hash_table_lookup (ht, "vlans"))) { + if (!_nm_sriov_vf_parse_vlans (vf, g_variant_get_string (variant, NULL), error)) { + nm_sriov_vf_unref (vf); + return NULL; + } + g_hash_table_remove (ht, "vlans"); + } + + g_hash_table_iter_init (&iter, ht); + while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &variant)) + nm_sriov_vf_set_attribute (vf, key, g_variant_ref_sink (variant)); + } + + return vf; +} + +/*****************************************************************************/ + /** * nm_utils_uuid_generate_buf_: * @buf: input buffer, must contain at least 37 bytes @@ -2701,9 +2838,17 @@ nm_utils_uuid_generate_from_string (const char *s, gssize slen, int uuid_type, g g_return_val_if_fail (uuid_type == NM_UTILS_UUID_TYPE_LEGACY || uuid_type == NM_UTILS_UUID_TYPE_VARIANT3, NULL); g_return_val_if_fail (!type_args || uuid_type == NM_UTILS_UUID_TYPE_VARIANT3, NULL); + if (slen < 0) + slen = s ? strlen (s) : 0; + switch (uuid_type) { case NM_UTILS_UUID_TYPE_LEGACY: - crypto_md5_hash (NULL, 0, s, slen, (char *) uuid, sizeof (uuid)); + nm_crypto_md5_hash (NULL, + 0, + (guint8 *) s, + slen, + (guint8 *) uuid, + sizeof (uuid)); break; case NM_UTILS_UUID_TYPE_VARIANT3: { uuid_t ns_uuid = { 0 }; @@ -2714,7 +2859,12 @@ nm_utils_uuid_generate_from_string (const char *s, gssize slen, int uuid_type, g g_return_val_if_reached (NULL); } - crypto_md5_hash (s, slen, (char *) ns_uuid, sizeof (ns_uuid), (char *) uuid, sizeof (uuid)); + nm_crypto_md5_hash ((guint8 *) s, + slen, + (guint8 *) ns_uuid, + sizeof (ns_uuid), + (guint8 *) uuid, + sizeof (uuid)); uuid[6] = (uuid[6] & 0x0F) | 0x30; uuid[8] = (uuid[8] & 0x3F) | 0x80; @@ -2774,110 +2924,6 @@ _nm_utils_uuid_generate_from_strings (const char *string1, ...) /*****************************************************************************/ -/** - * nm_utils_rsa_key_encrypt: - * @data: (array length=len): RSA private key data to be encrypted - * @len: length of @data - * @in_password: (allow-none): existing password to use, if any - * @out_password: (out) (allow-none): if @in_password was %NULL, a random - * password will be generated and returned in this argument - * @error: detailed error information on return, if an error occurred - * - * Encrypts the given RSA private key data with the given password (or generates - * a password if no password was given) and converts the data to PEM format - * suitable for writing to a file. It uses Triple DES cipher for the encryption. - * - * Returns: (transfer full): on success, PEM-formatted data suitable for writing - * to a PEM-formatted certificate/private key file. - **/ -GByteArray * -nm_utils_rsa_key_encrypt (const guint8 *data, - gsize len, - const char *in_password, - char **out_password, - GError **error) -{ - char salt[16]; - int salt_len; - char *key = NULL, *enc = NULL, *pw_buf[32]; - gsize key_len = 0, enc_len = 0; - GString *pem = NULL; - char *tmp, *tmp_password = NULL; - int left; - const char *p; - GByteArray *ret = NULL; - - g_return_val_if_fail (data != NULL, NULL); - g_return_val_if_fail (len > 0, NULL); - if (out_password) - g_return_val_if_fail (*out_password == NULL, NULL); - - /* Make the password if needed */ - if (!in_password) { - if (!crypto_randomize (pw_buf, sizeof (pw_buf), error)) - return NULL; - in_password = tmp_password = nm_utils_bin2hexstr (pw_buf, sizeof (pw_buf), -1); - } - - salt_len = 8; - if (!crypto_randomize (salt, salt_len, error)) - goto out; - - key = crypto_make_des_aes_key (CIPHER_DES_EDE3_CBC, &salt[0], salt_len, in_password, &key_len, NULL); - if (!key) - g_return_val_if_reached (NULL); - - enc = crypto_encrypt (CIPHER_DES_EDE3_CBC, data, len, salt, salt_len, key, key_len, &enc_len, error); - if (!enc) - goto out; - - pem = g_string_sized_new (enc_len * 2 + 100); - g_string_append (pem, "-----BEGIN RSA PRIVATE KEY-----\n"); - g_string_append (pem, "Proc-Type: 4,ENCRYPTED\n"); - - /* Convert the salt to a hex string */ - tmp = nm_utils_bin2hexstr (salt, salt_len, salt_len * 2); - g_string_append_printf (pem, "DEK-Info: %s,%s\n\n", CIPHER_DES_EDE3_CBC, tmp); - g_free (tmp); - - /* Convert the encrypted key to a base64 string */ - p = tmp = g_base64_encode ((const guchar *) enc, enc_len); - left = strlen (tmp); - while (left > 0) { - g_string_append_len (pem, p, (left < 64) ? left : 64); - g_string_append_c (pem, '\n'); - left -= 64; - p += 64; - } - g_free (tmp); - - g_string_append (pem, "-----END RSA PRIVATE KEY-----\n"); - - ret = g_byte_array_sized_new (pem->len); - g_byte_array_append (ret, (const unsigned char *) pem->str, pem->len); - if (tmp_password && out_password) - *out_password = g_strdup (tmp_password); - -out: - if (key) { - memset (key, 0, key_len); - g_free (key); - } - if (enc) { - memset (enc, 0, enc_len); - g_free (enc); - } - if (pem) - g_string_free (pem, TRUE); - - if (tmp_password) { - memset (tmp_password, 0, strlen (tmp_password)); - g_free (tmp_password); - } - - return ret; -} - static gboolean file_has_extension (const char *filename, const char *extensions[]) { @@ -2910,18 +2956,15 @@ gboolean nm_utils_file_is_certificate (const char *filename) { const char *extensions[] = { ".der", ".pem", ".crt", ".cer", NULL }; - NMCryptoFileFormat file_format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; - GByteArray *cert; + NMCryptoFileFormat file_format; g_return_val_if_fail (filename != NULL, FALSE); if (!file_has_extension (filename, extensions)) return FALSE; - cert = crypto_load_and_verify_certificate (filename, &file_format, NULL); - if (cert) - g_byte_array_unref (cert); - + if (!nm_crypto_load_and_verify_certificate (filename, &file_format, NULL, NULL)) + return FALSE; return file_format = NM_CRYPTO_FILE_FORMAT_X509; } @@ -2947,7 +2990,7 @@ nm_utils_file_is_private_key (const char *filename, gboolean *out_encrypted) if (!file_has_extension (filename, extensions)) return FALSE; - return crypto_verify_private_key (filename, NULL, out_encrypted, NULL) != NM_CRYPTO_FILE_FORMAT_UNKNOWN; + return nm_crypto_verify_private_key (filename, NULL, out_encrypted, NULL) != NM_CRYPTO_FILE_FORMAT_UNKNOWN; } /** @@ -2963,7 +3006,7 @@ nm_utils_file_is_pkcs12 (const char *filename) { g_return_val_if_fail (filename != NULL, FALSE); - return crypto_is_pkcs12_file (filename, NULL); + return nm_crypto_is_pkcs12_file (filename, NULL); } /*****************************************************************************/ @@ -3483,13 +3526,13 @@ nm_utils_hwaddr_len (int type) g_return_val_if_reached (0); } -static guint8 * -_str2bin (const char *asc, - gboolean delimiter_required, - const char *delimiter_candidates, - guint8 *buffer, - gsize buffer_length, - gsize *out_len) +guint8 * +_nm_utils_str2bin_full (const char *asc, + gboolean delimiter_required, + const char *delimiter_candidates, + guint8 *buffer, + gsize buffer_length, + gsize *out_len) { const char *in = asc; guint8 *out = buffer; @@ -3559,7 +3602,7 @@ _str2bin (const char *asc, return buffer; } -#define hwaddr_aton(asc, buffer, buffer_length, out_len) _str2bin ((asc), TRUE, ":-", (buffer), (buffer_length), (out_len)) +#define hwaddr_aton(asc, buffer, buffer_length, out_len) _nm_utils_str2bin_full ((asc), TRUE, ":-", (buffer), (buffer_length), (out_len)) /** * nm_utils_hexstr2bin: @@ -3585,7 +3628,7 @@ nm_utils_hexstr2bin (const char *hex) buffer_length = strlen (hex) / 2 + 3; buffer = g_malloc (buffer_length); - if (!_str2bin (hex, FALSE, ":", buffer, buffer_length, &len)) { + if (!_nm_utils_str2bin_full (hex, FALSE, ":", buffer, buffer_length, &len)) { g_free (buffer); return NULL; } @@ -4290,6 +4333,8 @@ nm_utils_is_uuid (const char *str) const char *p = str; int num_dashes = 0; + g_return_val_if_fail (str, FALSE); + while (*p) { if (*p == '-') num_dashes++; @@ -4465,7 +4510,7 @@ _nm_utils_dhcp_duid_valid (const char *duid, GBytes **out_duid_bin) return TRUE; } - if (_str2bin (duid, FALSE, ":", duid_arr, sizeof (duid_arr), &duid_len)) { + if (_nm_utils_str2bin_full (duid, FALSE, ":", duid_arr, sizeof (duid_arr), &duid_len)) { /* MAX DUID length is 128 octects + the type code (2 octects). */ if ( duid_len > 2 && duid_len <= (128 + 2)) { @@ -4886,7 +4931,7 @@ nm_utils_enum_from_str (GType type, const char *str, * * Since: 1.2 */ -const char **nm_utils_enum_get_values (GType type, gint from, gint to) +const char **nm_utils_enum_get_values (GType type, int from, int to) { return _nm_utils_enum_get_values (type, from, to); } @@ -4896,18 +4941,18 @@ const char **nm_utils_enum_get_values (GType type, gint from, gint to) static gboolean _nm_utils_is_json_object_no_validation (const char *str, GError **error) { - if (str) { - /* libjansson also requires only utf-8 encoding. */ - if (!g_utf8_validate (str, -1, NULL)) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("not valid utf-8")); - return FALSE; - } - while (g_ascii_isspace (str[0])) - str++; + nm_assert (str); + + /* libjansson also requires only utf-8 encoding. */ + if (!g_utf8_validate (str, -1, NULL)) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("not valid utf-8")); + return FALSE; } + while (g_ascii_isspace (str[0])) + str++; /* do some very basic validation to see if this might be a JSON object. */ if (str[0] == '{') { @@ -5539,7 +5584,7 @@ _nm_utils_team_config_get (const char *conf, g_ptr_array_free (data, TRUE); } else if (json_is_array (json_element)) { - GPtrArray *data = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free); + GPtrArray *data = g_ptr_array_new_with_free_func (g_free); json_t *str_element; int index; @@ -5990,7 +6035,9 @@ attribute_unescape (const char *start, const char *end) * Parse attributes from a string. * * Returns: (transfer full) (element-type utf8 GVariant): a #GHashTable mapping - * attribute names to #GVariant values. + * attribute names to #GVariant values. Warning: the variant are still floating + * references, owned by the hash table. If you take a reference, ensure to sink + * the one of the hash table first. * * Since: 1.8 */ @@ -6147,44 +6194,21 @@ next: return g_steal_pointer (&ht); } -/* - * nm_utils_format_variant_attributes: - * @attributes: (element-type utf8 GVariant): a #GHashTable mapping attribute names to #GVariant values - * @attr_separator: the attribute separator character - * @key_value_separator: character separating key and values - * - * Format attributes to a string. - * - * Returns: (transfer full): the string representing attributes, or %NULL - * in case there are no attributes - * - * Since: 1.8 - */ -char * -nm_utils_format_variant_attributes (GHashTable *attributes, - char attr_separator, - char key_value_separator) +void +_nm_utils_format_variant_attributes_full (GString *str, + const NMUtilsNamedValue *values, + guint num_values, + char attr_separator, + char key_value_separator) { - GString *str = NULL; - GVariant *variant; - char sep = 0; const char *name, *value; + GVariant *variant; char *escaped; char buf[64]; - gs_free NMUtilsNamedValue *values = NULL; - guint i, len; - - g_return_val_if_fail (attr_separator, NULL); - g_return_val_if_fail (key_value_separator, NULL); - - if (!attributes || !g_hash_table_size (attributes)) - return NULL; - - values = nm_utils_named_values_from_str_dict (attributes, &len); - - str = g_string_new (""); + char sep = 0; + guint i; - for (i = 0; i < len; i++) { + for (i = 0; i < num_values; i++) { name = values[i].name; variant = (GVariant *) values[i].value_ptr; value = NULL; @@ -6217,7 +6241,44 @@ nm_utils_format_variant_attributes (GHashTable *attributes, sep = attr_separator; } +} + +/* + * nm_utils_format_variant_attributes: + * @attributes: (element-type utf8 GVariant): a #GHashTable mapping attribute names to #GVariant values + * @attr_separator: the attribute separator character + * @key_value_separator: character separating key and values + * + * Format attributes to a string. + * + * Returns: (transfer full): the string representing attributes, or %NULL + * in case there are no attributes + * + * Since: 1.8 + */ +char * +nm_utils_format_variant_attributes (GHashTable *attributes, + char attr_separator, + char key_value_separator) +{ + GString *str = NULL; + gs_free NMUtilsNamedValue *values = NULL; + guint len; + + g_return_val_if_fail (attr_separator, NULL); + g_return_val_if_fail (key_value_separator, NULL); + + if (!attributes || !g_hash_table_size (attributes)) + return NULL; + values = nm_utils_named_values_from_str_dict (attributes, &len); + + str = g_string_new (""); + _nm_utils_format_variant_attributes_full (str, + values, + len, + attr_separator, + key_value_separator); return g_string_free (str, FALSE); } |