[network-manager-openvpn: 3/4] properties/import: fix parsing for openvpn's special handling of comments and quoting
- From: Thomas Haller <thaller src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [network-manager-openvpn: 3/4] properties/import: fix parsing for openvpn's special handling of comments and quoting
- Date: Thu, 30 Jun 2016 07:42:50 +0000 (UTC)
commit 7cc6312779556cc53cb546fcce6f4d2e30ad20e3
Author: Thomas Haller <thaller redhat com>
Date: Mon Jun 27 16:14:18 2016 +0200
properties/import: fix parsing for openvpn's special handling of comments and quoting
openvpn doesn't treat quotes and comments like shell does. Instead:
- comments start with ';' or '#'. They can not only start at the first
characther of the line. Instead comments can start at every beginning
of a word (but not inside a word). E.g. "a#comment" is not taken as "a"
followed by a comment, instead it is taken literally.
- quotation is quite peculiar. On the first character of a word,
openvpn decides whether it has a quoted word at hand or not.
In case of a quoted word, the word ends with the closing quote.
That means, "'a'b" becomes "a","b", not "ab".
In case of an unquoted word, quotes inside the word are ignored
until the word ends with spaces. That means, "a'b'" is taken
literally as "a'b'".
*Sigh*
See:
https://github.com/OpenVPN/openvpn/blob/2011b8324feca30df753a4a0a116d37c04742520/src/openvpn/options.c#L3639
properties/import-export.c | 87 +++++++++++++++++++--------------
properties/tests/conf/password.conf | 2 +-
properties/tests/test-import-export.c | 6 +-
3 files changed, 55 insertions(+), 40 deletions(-)
---
diff --git a/properties/import-export.c b/properties/import-export.c
index a558867..62d5f74 100644
--- a/properties/import-export.c
+++ b/properties/import-export.c
@@ -459,7 +459,7 @@ args_parse_line (const char *line,
index = g_array_new (FALSE, FALSE, sizeof (gsize));
- do {
+ for (;;) {
char quote, ch0;
gssize word_start = line - line_start;
gsize index_i;
@@ -467,51 +467,66 @@ args_parse_line (const char *line,
index_i = str_buf - str_buf_orig;
g_array_append_val (index, index_i);
- do {
- switch ((ch0 = _ch_step_1 (&line, &line_len))) {
- case '"':
- case '\'':
- quote = ch0;
-
- while (line_len > 0 && line[0] != quote) {
- if (quote == '"' && line[0] == '\\') {
- _ch_step_1 (&line, &line_len);
- if (line_len <= 0)
- break;
- }
- _strbuf_append_c (&str_buf, &str_buf_len, _ch_step_1 (&line,
&line_len));
- }
+ switch ((ch0 = _ch_step_1 (&line, &line_len))) {
+ case '"':
+ case '\'':
+ quote = ch0;
- if (line_len <= 0) {
- *out_error = g_strdup_printf (_("unterminated %s at position %lld"),
- quote == '"' ? _("double quote") :
_("single quote"),
- (long long) word_start);
- return FALSE;
+ while (line_len > 0 && line[0] != quote) {
+ if (quote == '"' && line[0] == '\\') {
+ _ch_step_1 (&line, &line_len);
+ if (line_len <= 0)
+ break;
}
+ _strbuf_append_c (&str_buf, &str_buf_len, _ch_step_1 (&line, &line_len));
+ }
+
+ if (line_len <= 0) {
+ *out_error = g_strdup_printf (_("unterminated %s at position %lld"),
+ quote == '"' ? _("double quote") : _("single
quote"),
+ (long long) word_start);
+ return FALSE;
+ }
- _ch_step_1 (&line, &line_len);
- break;
- case '\\':
- if (line_len <= 0) {
- *out_error = g_strdup_printf (_("trailing escaping backslash at
position %lld"),
- (long long) word_start);
- return FALSE;
+ /* openvpn terminates parsing of quoted paramaters after the closing quote.
+ * E.g. "'a'b" gives "a", "b". */
+ _ch_step_1 (&line, &line_len);
+ break;
+ default:
+ /* once openvpn encounters a non-quoted word, it doesn't consider quoting
+ * inside the word.
+ * E.g. "a'b'" gives "a'b'". */
+ for (;;) {
+ if (ch0 == '\\') {
+ if (line_len <= 0) {
+ *out_error = g_strdup_printf (_("trailing escaping backslash
at position %lld"),
+ (long long) word_start);
+ return FALSE;
+ }
+ ch0 = _ch_step_1 (&line, &line_len);
}
- _strbuf_append_c (&str_buf, &str_buf_len, _ch_step_1 (&line, &line_len));
- break;
- default:
- if (g_ascii_isspace (ch0))
- goto word_completed;
_strbuf_append_c (&str_buf, &str_buf_len, ch0);
- break;
+ if (line_len <= 0)
+ break;
+ ch0 = _ch_step_1 (&line, &line_len);
+ if (g_ascii_isspace (ch0))
+ break;
}
- } while (line_len > 0);
-word_completed:
+ break;
+ }
/* the current word is complete.*/
_strbuf_append_c (&str_buf, &str_buf_len, '\0');
_ch_skip_over_leading_whitespace (&line, &line_len);
- } while (line_len > 0);
+
+ if (line_len <= 0)
+ break;
+
+ if (NM_IN_SET (line[0], ';', '#')) {
+ /* comments are allowed to start at the beginning of the next word. */
+ break;
+ }
+ }
str_buf_len = str_buf - str_buf_orig;
diff --git a/properties/tests/conf/password.conf b/properties/tests/conf/password.conf
index c924a4f..cfe5835 100644
--- a/properties/tests/conf/password.conf
+++ b/properties/tests/conf/password.conf
@@ -14,7 +14,7 @@ group openvpn
ca cacert.pem
-cipher AES-256-CBC
+cipher AES-256-CBC #xcomment
reneg-sec 0
auth-user-pass
diff --git a/properties/tests/test-import-export.c b/properties/tests/test-import-export.c
index 936662c..a78d2d2 100644
--- a/properties/tests/test-import-export.c
+++ b/properties/tests/test-import-export.c
@@ -1287,9 +1287,9 @@ test_args_parse_line (void)
do_test_args_parse_line (" b \\ \\a ", TRUE, "b", " a");
do_test_args_parse_line ("\\ b \\ \\a ", TRUE, " b", " a");
do_test_args_parse_line ("'\\ b \\ \\a '", TRUE, "\\ b \\ \\a ");
- do_test_args_parse_line ("\"\\ b \\ \\a \"a'b'", TRUE, " b a ab");
- do_test_args_parse_line ("\"\\ b \\ \\a \"a\\ 'b'", TRUE, " b a a b");
- do_test_args_parse_line ("\"\\ b \\ \\a \"a\\ 'b' sd\\ \t", TRUE, " b a a b", "sd ");
+ do_test_args_parse_line ("\"\\ b \\ \\a \"a'b'", TRUE, " b a ", "a'b'");
+ do_test_args_parse_line ("\"\\ b \\ \\a \"a\\ 'b'", TRUE, " b a ", "a 'b'");
+ do_test_args_parse_line ("\"\\ b \\ \\a \"a\\ 'b' sd\\ \t", TRUE, " b a ", "a 'b'", "sd ");
do_test_args_parse_line ("\"adfdaf adf ", FALSE);
do_test_args_parse_line ("\"adfdaf adf \\\"", FALSE);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]