From 3dfb72b92687131a030a1c19e21f29ac26c26a32 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 16 Jul 2018 12:59:08 +0200 Subject: [PATCH] service-plugin: allow continuations in the auth-dialog protocol Equals sign was picked as a continuation character arbitratily. It would simplify parsing, if we cared. DATA_KEY=some-key DATA_VAL=string =continued after a line break SECRET_KEY=key names =can have =continuations too SECRET_VAL=value DONE --- libnm/nm-vpn-service-plugin.c | 68 ++++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/libnm/nm-vpn-service-plugin.c b/libnm/nm-vpn-service-plugin.c index 56f5dc6b7d..94a1ebbc04 100644 --- a/libnm/nm-vpn-service-plugin.c +++ b/libnm/nm-vpn-service-plugin.c @@ -787,10 +787,13 @@ nm_vpn_service_plugin_read_vpn_details (int fd, gs_unref_hashtable GHashTable *data = NULL; gs_unref_hashtable GHashTable *secrets = NULL; gboolean success = FALSE; - char *key = NULL, *val = NULL; + GHashTable *hash = NULL; + GString *key = NULL, *val = NULL; nm_auto_free_gstring GString *line = NULL; char c; + GString *str = NULL; + if (out_data) g_return_val_if_fail (*out_data == NULL, FALSE); if (out_secrets) @@ -804,7 +807,6 @@ nm_vpn_service_plugin_read_vpn_details (int fd, /* Read stdin for data and secret items until we get a DONE */ while (1) { ssize_t nr; - GHashTable *hash = NULL; errno = 0; nr = read (fd, &c, 1); @@ -821,32 +823,50 @@ nm_vpn_service_plugin_read_vpn_details (int fd, continue; } - /* Check for the finish marker */ - if (strcmp (line->str, "DONE") == 0) - break; - - /* Otherwise it's a data/secret item */ - if (strncmp (line->str, DATA_KEY_TAG, strlen (DATA_KEY_TAG)) == 0) { - hash = data; - key = g_strdup (line->str + strlen (DATA_KEY_TAG)); - } else if (strncmp (line->str, DATA_VAL_TAG, strlen (DATA_VAL_TAG)) == 0) { - hash = data; - val = g_strdup (line->str + strlen (DATA_VAL_TAG)); - } else if (strncmp (line->str, SECRET_KEY_TAG, strlen (SECRET_KEY_TAG)) == 0) { - hash = secrets; - key = g_strdup (line->str + strlen (SECRET_KEY_TAG)); - } else if (strncmp (line->str, SECRET_VAL_TAG, strlen (SECRET_VAL_TAG)) == 0) { - hash = secrets; - val = g_strdup (line->str + strlen (SECRET_VAL_TAG)); - } - g_string_truncate (line, 0); - - if (key && val && hash) { - g_hash_table_insert (hash, key, val); + if (str && *line->str == '=') { + /* continuation */ + g_string_append_c (str, '\n'); + g_string_append (str, line->str + 1); + } else if (key && val) { + /* done a line */ + g_return_val_if_fail (hash, FALSE); + g_hash_table_insert (hash, + g_string_free (key, FALSE), + g_string_free (val, FALSE)); key = NULL; val = NULL; + hash = NULL; success = TRUE; /* Got at least one value */ } + + if (strcmp (line->str, "DONE") == 0) { + /* finish marker */ + break; + } else if (strncmp (line->str, DATA_KEY_TAG, strlen (DATA_KEY_TAG)) == 0) { + if (key != NULL) + g_string_free (key, TRUE); + key = g_string_new (line->str + strlen (DATA_KEY_TAG)); + str = key; + hash = data; + } else if (strncmp (line->str, DATA_VAL_TAG, strlen (DATA_VAL_TAG)) == 0) { + if (val != NULL) + g_string_free (val, TRUE); + val = g_string_new (line->str + strlen (DATA_VAL_TAG)); + str = val; + } else if (strncmp (line->str, SECRET_KEY_TAG, strlen (SECRET_KEY_TAG)) == 0) { + if (key != NULL) + g_string_free (key, TRUE); + key = g_string_new (line->str + strlen (SECRET_KEY_TAG)); + str = key; + hash = secrets; + } else if (strncmp (line->str, SECRET_VAL_TAG, strlen (SECRET_VAL_TAG)) == 0) { + if (val != NULL) + g_string_free (val, TRUE); + val = g_string_new (line->str + strlen (SECRET_VAL_TAG)); + str = val; + } + + g_string_truncate (line, 0); } if (success) {