summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2020-05-04 13:33:35 +0200
committerThomas Haller <thaller@redhat.com>2020-05-13 10:28:04 +0200
commit360f0fae111a76cc47fb559d035096221a3a5993 (patch)
tree1a4b21a601fda382658ca2dfce409f392923e235
parent1086a47cdae5b1e10c7fcf4a4f8242381027f6a1 (diff)
downloadNetworkManager-360f0fae111a76cc47fb559d035096221a3a5993.tar.gz
cli: move nmc_utils_read_passwd_file() to "common/nm-client-utils.c"
-rw-r--r--clients/cli/connections.c180
-rw-r--r--clients/common/nm-client-utils.c180
-rw-r--r--clients/common/nm-client-utils.h4
3 files changed, 184 insertions, 180 deletions
diff --git a/clients/cli/connections.c b/clients/cli/connections.c
index b2dd0a60a7..a6bbe5669b 100644
--- a/clients/cli/connections.c
+++ b/clients/cli/connections.c
@@ -16,8 +16,6 @@
#include <readline/history.h>
#include <fcntl.h>
-#include "nm-glib-aux/nm-secret-utils.h"
-#include "nm-glib-aux/nm-io-utils.h"
#include "nm-client-utils.h"
#include "nm-vpn-helpers.h"
#include "nm-meta-setting-access.h"
@@ -2696,182 +2694,6 @@ activate_connection_cb (GObject *client, GAsyncResult *result, gpointer user_dat
}
}
-/**
- * parse_passwords:
- * @passwd_file: file with passwords to parse
- * @out_error_line: returns in case of a syntax error in the file, the line
- * on which it occurred.
- * @error: location to store error, or %NULL
- *
- * Parse passwords given in @passwd_file and insert them into a hash table.
- * Example of @passwd_file contents:
- * wifi.psk:tajne heslo
- * 802-1x.password:krakonos
- * 802-11-wireless-security:leap-password:my leap password
- *
- * Returns: hash table with parsed passwords, or %NULL on an error
- */
-static GHashTable *
-parse_passwords (const char *passwd_file,
- gssize *out_error_line,
- GError **error)
-{
- nm_auto_clear_secret_ptr NMSecretPtr contents = { 0 };
- gs_unref_hashtable GHashTable *pwds_hash = NULL;
- const char *contents_str;
- gsize contents_line;
-
- pwds_hash = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, (GDestroyNotify) nm_free_secret);
-
- NM_SET_OUT (out_error_line, -1);
-
- if (!passwd_file)
- return g_steal_pointer (&pwds_hash);
-
- if (!nm_utils_file_get_contents (-1,
- passwd_file,
- 1024*1024,
- NM_UTILS_FILE_GET_CONTENTS_FLAG_SECRET,
- &contents.str,
- &contents.len,
- NULL,
- error))
- return NULL;
-
- contents_str = contents.str;
- contents_line = 0;
- while (contents_str[0]) {
- nm_auto_free_secret char *l_hash_key = NULL;
- nm_auto_free_secret char *l_hash_val = NULL;
- const char *l_content_line;
- const char *l_setting;
- const char *l_prop;
- const char *l_val;
- const char *s;
- gsize l_hash_val_len;
-
- /* consume first line. As line delimiters we accept "\r\n", "\n", and "\r". */
- l_content_line = contents_str;
- s = l_content_line;
- while (!NM_IN_SET (s[0], '\0', '\r', '\n'))
- s++;
- if (s[0] != '\0') {
- if ( s[0] == '\r'
- && s[1] == '\n') {
- ((char *) s)[0] = '\0';
- s += 2;
- } else {
- ((char *) s)[0] = '\0';
- s += 1;
- }
- }
- contents_str = s;
- contents_line++;
-
- l_content_line = nm_str_skip_leading_spaces (l_content_line);
- if (NM_IN_SET (l_content_line[0], '\0', '#')) {
- /* a comment or empty line. Ignore. */
- continue;
- }
-
- l_setting = l_content_line;
-
- s = l_setting;
- while (!NM_IN_SET (s[0], '\0', ':', '='))
- s++;
- if (s[0] == '\0') {
- NM_SET_OUT (out_error_line, contents_line);
- nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
- _("missing colon for \"<setting>.<property>:<secret>\" format"));
- return NULL;
- }
- ((char *) s)[0] = '\0';
- s++;
-
- l_val = s;
-
- g_strchomp ((char *) l_setting);
-
- nm_assert (nm_str_is_stripped (l_setting));
-
- s = strchr (l_setting, '.');
- if (!s) {
- NM_SET_OUT (out_error_line, contents_line);
- nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
- _("missing dot for \"<setting>.<property>:<secret>\" format"));
- return NULL;
- } else if (s == l_setting) {
- NM_SET_OUT (out_error_line, contents_line);
- nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
- _("missing setting for \"<setting>.<property>:<secret>\" format"));
- return NULL;
- }
- ((char *) s)[0] = '\0';
- s++;
-
- l_prop = s;
- if (l_prop[0] == '\0') {
- NM_SET_OUT (out_error_line, contents_line);
- nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
- _("missing property for \"<setting>.<property>:<secret>\" format"));
- return NULL;
- }
-
- /* Accept wifi-sec or wifi instead of cumbersome '802-11-wireless-security' */
- if (NM_IN_STRSET (l_setting, "wifi-sec", "wifi"))
- l_setting = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME;
-
- if (nm_setting_lookup_type (l_setting) == G_TYPE_INVALID) {
- NM_SET_OUT (out_error_line, contents_line);
- nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
- _("invalid setting name"));
- return NULL;
- }
-
- if ( nm_streq (l_setting, "vpn")
- && NM_STR_HAS_PREFIX (l_prop, "secret.")) {
- /* in 1.12.0, we wrongly required the VPN secrets to be named
- * "vpn.secret". It should be "vpn.secrets". Work around it
- * (rh#1628833). */
- l_hash_key = g_strdup_printf ("vpn.secrets.%s", &l_prop[NM_STRLEN ("secret.")]);
- } else
- l_hash_key = g_strdup_printf ("%s.%s", l_setting, l_prop);
-
- if (!g_utf8_validate (l_hash_key, -1, NULL)) {
- NM_SET_OUT (out_error_line, contents_line);
- nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
- _("property name is not UTF-8"));
- return NULL;
- }
-
- /* Support backslash escaping in the secret value. We strip non-escaped leading/trailing whitespaces. */
- s = nm_utils_buf_utf8safe_unescape (l_val, NM_UTILS_STR_UTF8_SAFE_UNESCAPE_STRIP_SPACES, &l_hash_val_len, (gpointer *) &l_hash_val);
- if (!l_hash_val)
- l_hash_val = g_strdup (s);
-
- if (!g_utf8_validate (l_hash_val, -1, NULL)) {
- /* In some cases it might make sense to support binary secrets (like the WPA-PSK which has no
- * defined encoding. However, all API that follows can only handle UTF-8, and no mechanism
- * to escape the secrets. Reject non-UTF-8 early. */
- NM_SET_OUT (out_error_line, contents_line);
- nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
- _("secret is not UTF-8"));
- return NULL;
- }
-
- if (strlen (l_hash_val) != l_hash_val_len) {
- NM_SET_OUT (out_error_line, contents_line);
- nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
- _("secret is not UTF-8"));
- return NULL;
- }
-
- g_hash_table_insert (pwds_hash, g_steal_pointer (&l_hash_key), g_steal_pointer (&l_hash_val));
- }
-
- return g_steal_pointer (&pwds_hash);
-}
-
static gboolean
nmc_activate_connection (NmCli *nmc,
NMConnection *connection,
@@ -2924,7 +2746,7 @@ nmc_activate_connection (NmCli *nmc,
gs_free_error GError *local = NULL;
gssize error_line;
- pwds_hash = parse_passwords (pwds, &error_line, &local);
+ pwds_hash = nmc_utils_read_passwd_file (pwds, &error_line, &local);
if (!pwds_hash) {
if (error_line >= 0) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
diff --git a/clients/common/nm-client-utils.c b/clients/common/nm-client-utils.c
index cf8b478560..a296a3b9dc 100644
--- a/clients/common/nm-client-utils.c
+++ b/clients/common/nm-client-utils.c
@@ -6,8 +6,10 @@
#include "nm-default.h"
#include "nm-client-utils.h"
-#include "nm-utils.h"
+#include "nm-glib-aux/nm-secret-utils.h"
+#include "nm-glib-aux/nm-io-utils.h"
+#include "nm-utils.h"
#include "nm-device-bond.h"
#include "nm-device-bridge.h"
#include "nm-device-team.h"
@@ -587,3 +589,179 @@ nmc_print_qrcode (const char *str)
}
}
}
+
+/**
+ * nmc_utils_read_passwd_file:
+ * @passwd_file: file with passwords to parse
+ * @out_error_line: returns in case of a syntax error in the file, the line
+ * on which it occurred.
+ * @error: location to store error, or %NULL
+ *
+ * Parse passwords given in @passwd_file and insert them into a hash table.
+ * Example of @passwd_file contents:
+ * wifi.psk:tajne heslo
+ * 802-1x.password:krakonos
+ * 802-11-wireless-security:leap-password:my leap password
+ *
+ * Returns: (transfer full): hash table with parsed passwords, or %NULL on an error
+ */
+GHashTable *
+nmc_utils_read_passwd_file (const char *passwd_file,
+ gssize *out_error_line,
+ GError **error)
+{
+ nm_auto_clear_secret_ptr NMSecretPtr contents = { 0 };
+ gs_unref_hashtable GHashTable *pwds_hash = NULL;
+ const char *contents_str;
+ gsize contents_line;
+
+ pwds_hash = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, (GDestroyNotify) nm_free_secret);
+
+ NM_SET_OUT (out_error_line, -1);
+
+ if (!passwd_file)
+ return g_steal_pointer (&pwds_hash);
+
+ if (!nm_utils_file_get_contents (-1,
+ passwd_file,
+ 1024*1024,
+ NM_UTILS_FILE_GET_CONTENTS_FLAG_SECRET,
+ &contents.str,
+ &contents.len,
+ NULL,
+ error))
+ return NULL;
+
+ contents_str = contents.str;
+ contents_line = 0;
+ while (contents_str[0]) {
+ nm_auto_free_secret char *l_hash_key = NULL;
+ nm_auto_free_secret char *l_hash_val = NULL;
+ const char *l_content_line;
+ const char *l_setting;
+ const char *l_prop;
+ const char *l_val;
+ const char *s;
+ gsize l_hash_val_len;
+
+ /* consume first line. As line delimiters we accept "\r\n", "\n", and "\r". */
+ l_content_line = contents_str;
+ s = l_content_line;
+ while (!NM_IN_SET (s[0], '\0', '\r', '\n'))
+ s++;
+ if (s[0] != '\0') {
+ if ( s[0] == '\r'
+ && s[1] == '\n') {
+ ((char *) s)[0] = '\0';
+ s += 2;
+ } else {
+ ((char *) s)[0] = '\0';
+ s += 1;
+ }
+ }
+ contents_str = s;
+ contents_line++;
+
+ l_content_line = nm_str_skip_leading_spaces (l_content_line);
+ if (NM_IN_SET (l_content_line[0], '\0', '#')) {
+ /* a comment or empty line. Ignore. */
+ continue;
+ }
+
+ l_setting = l_content_line;
+
+ s = l_setting;
+ while (!NM_IN_SET (s[0], '\0', ':', '='))
+ s++;
+ if (s[0] == '\0') {
+ NM_SET_OUT (out_error_line, contents_line);
+ nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
+ _("missing colon for \"<setting>.<property>:<secret>\" format"));
+ return NULL;
+ }
+ ((char *) s)[0] = '\0';
+ s++;
+
+ l_val = s;
+
+ g_strchomp ((char *) l_setting);
+
+ nm_assert (nm_str_is_stripped (l_setting));
+
+ s = strchr (l_setting, '.');
+ if (!s) {
+ NM_SET_OUT (out_error_line, contents_line);
+ nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
+ _("missing dot for \"<setting>.<property>:<secret>\" format"));
+ return NULL;
+ } else if (s == l_setting) {
+ NM_SET_OUT (out_error_line, contents_line);
+ nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
+ _("missing setting for \"<setting>.<property>:<secret>\" format"));
+ return NULL;
+ }
+ ((char *) s)[0] = '\0';
+ s++;
+
+ l_prop = s;
+ if (l_prop[0] == '\0') {
+ NM_SET_OUT (out_error_line, contents_line);
+ nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
+ _("missing property for \"<setting>.<property>:<secret>\" format"));
+ return NULL;
+ }
+
+ /* Accept wifi-sec or wifi instead of cumbersome '802-11-wireless-security' */
+ if (NM_IN_STRSET (l_setting, "wifi-sec", "wifi"))
+ l_setting = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME;
+
+ if (nm_setting_lookup_type (l_setting) == G_TYPE_INVALID) {
+ NM_SET_OUT (out_error_line, contents_line);
+ nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
+ _("invalid setting name"));
+ return NULL;
+ }
+
+ if ( nm_streq (l_setting, "vpn")
+ && NM_STR_HAS_PREFIX (l_prop, "secret.")) {
+ /* in 1.12.0, we wrongly required the VPN secrets to be named
+ * "vpn.secret". It should be "vpn.secrets". Work around it
+ * (rh#1628833). */
+ l_hash_key = g_strdup_printf ("vpn.secrets.%s", &l_prop[NM_STRLEN ("secret.")]);
+ } else
+ l_hash_key = g_strdup_printf ("%s.%s", l_setting, l_prop);
+
+ if (!g_utf8_validate (l_hash_key, -1, NULL)) {
+ NM_SET_OUT (out_error_line, contents_line);
+ nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
+ _("property name is not UTF-8"));
+ return NULL;
+ }
+
+ /* Support backslash escaping in the secret value. We strip non-escaped leading/trailing whitespaces. */
+ s = nm_utils_buf_utf8safe_unescape (l_val, NM_UTILS_STR_UTF8_SAFE_UNESCAPE_STRIP_SPACES, &l_hash_val_len, (gpointer *) &l_hash_val);
+ if (!l_hash_val)
+ l_hash_val = g_strdup (s);
+
+ if (!g_utf8_validate (l_hash_val, -1, NULL)) {
+ /* In some cases it might make sense to support binary secrets (like the WPA-PSK which has no
+ * defined encoding. However, all API that follows can only handle UTF-8, and no mechanism
+ * to escape the secrets. Reject non-UTF-8 early. */
+ NM_SET_OUT (out_error_line, contents_line);
+ nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
+ _("secret is not UTF-8"));
+ return NULL;
+ }
+
+ if (strlen (l_hash_val) != l_hash_val_len) {
+ NM_SET_OUT (out_error_line, contents_line);
+ nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
+ _("secret is not UTF-8"));
+ return NULL;
+ }
+
+ g_hash_table_insert (pwds_hash, g_steal_pointer (&l_hash_key), g_steal_pointer (&l_hash_val));
+ }
+
+ return g_steal_pointer (&pwds_hash);
+}
diff --git a/clients/common/nm-client-utils.h b/clients/common/nm-client-utils.h
index 1e3085d56d..f4f67544e7 100644
--- a/clients/common/nm-client-utils.h
+++ b/clients/common/nm-client-utils.h
@@ -43,4 +43,8 @@ const char *nmc_password_subst_char (void);
void nmc_print_qrcode (const char *str);
+GHashTable *nmc_utils_read_passwd_file (const char *passwd_file,
+ gssize *out_error_line,
+ GError **error);
+
#endif /* __NM_CLIENT_UTILS_H__ */