[network-manager-openvpn/th/tmp] properties: fix parsing during import for openvpn special handling of comments and quoting



commit 36d175510d3be707d78778d62fdda1757dbc6ec1
Author: Thomas Haller <thaller redhat com>
Date:   Mon Jun 27 16:14:18 2016 +0200

    properties: fix parsing during import for openvpn special handling of comments and quoting
    
    openvpn doesn't treat quotes and comments like shell does. Instead:
    
      - quotes start with ';' or '#' and can start also not at the first
        charater of the line. 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 a unquoted word, quotes inside the word are ignored
        until the word ends with spaces. That means, "a'b'" becomes
        "a'b'".
    
    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]