[NetworkManager-openvpn] properties: sanitize newlines ('\n') when exporting ovpn file



commit 79fe14bcd49fa8a2e1a66aa2d5549bc9e3a6a6c2
Author: Thomas Haller <thaller redhat com>
Date:   Sat Jul 14 11:13:06 2018 +0200

    properties: sanitize newlines ('\n') when exporting ovpn file
    
    Openvpn's ovpn configuration files cannot contain newlines as values,
    because
    
    - the parser reads the ovpn file line by line, splitting lines are
      newlines. Hence, quotation spaning multiple lines is not supported
      to express '\n'.
    - special escape sequences like "\n" or "\012" are not supported
      either. Escape sequences are only for "\'", "\"", and verbatim
      spaces like "\ " (but not newline itself).
    
    Note that newlines can be part of a valid configuration, for example
    as part of filenames.
    
    Instead of breaking the line, still try to escape the newline
    with "\n".
    
    Previously, openvpn would fail with
    
        $ openvpn --config my.ovpn
        Options error: No closing single quotation (') in my.ovpn:1
    
    Now, the configuration file has no more such line breaks and openvpn
    issues a warning instead:
    
        $ openvpn --config my.ovpn
        Options warning: Bad backslash ('\') usage in my.ovpn:1: remember that backslashes are treated as 
shell-escapes and if you need to pass backslash characters as part of a Windows filename, you should use 
double backslashes such as "c:\\openvpn\\static.key"
    
    The point of this change is not that the new warning behavior is better
    than the previous error behavior (it's arguably worse). However, I think
    if we write an invalid file, it's better to have an invalid escape sequence,
    instead of a spurious line break.
    
    https://gitlab.gnome.org/GNOME/NetworkManager-openvpn/merge_requests/5

 properties/import-export.c | 23 +++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)
---
diff --git a/properties/import-export.c b/properties/import-export.c
index b956fb7..5507ab8 100644
--- a/properties/import-export.c
+++ b/properties/import-export.c
@@ -1675,7 +1675,7 @@ escape_arg (const char *value, char **buf)
 {
        const char *s;
        char *result, *i_result;
-       gboolean has_single_quote = FALSE;
+       gboolean needs_double_quotes = FALSE;
        gboolean needs_quotation = FALSE;
        gsize len;
 
@@ -1696,14 +1696,15 @@ escape_arg (const char *value, char **buf)
                    || (c >= 'A' && c <= 'Z')
                    || NM_IN_SET (c, '_', '-', ':', '/'))
                        continue;
+
                needs_quotation = TRUE;
-               if (c == '\'')
-                       has_single_quote = TRUE;
+               if (NM_IN_SET (c, '\'', '\n'))
+                       needs_double_quotes = TRUE;
        }
        if (!needs_quotation)
                return value;
 
-       if (!has_single_quote) {
+       if (!needs_double_quotes) {
                result = g_malloc (len + 2 + 1);
                result[0] = '\'';
                memcpy (&result[1], value, len);
@@ -1713,9 +1714,19 @@ escape_arg (const char *value, char **buf)
                i_result = result = g_malloc (len * 2 + 3);
                *(i_result++) = '"';
                for (s = value; s[0]; s++) {
-                       if (NM_IN_SET (s[0], '\\', '"'))
+                       if (s[0] == '\n') {
+                               /* Openvpn does not support encoding '\n' in the ovpn configuration file.
+                                * This configuration cannot be expressed in an ovpn file.
+                                *
+                                * Still escape it as '\n', although openvpn's parser will warn
+                                * about the invalid escape sequence. */
                                *(i_result++) = '\\';
-                       *(i_result++) = s[0];
+                               *(i_result++) = 'n';
+                       } else {
+                               if (NM_IN_SET (s[0], '\\', '"'))
+                                       *(i_result++) = '\\';
+                               *(i_result++) = s[0];
+                       }
                }
                *(i_result++) = '"';
                *(i_result++) = '\0';


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]