From 5c76a93a44bdd0d6d15e644176a0257d9ce7bf9b Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Fri, 25 Sep 2015 09:23:26 +0100 Subject: [PATCH] Sanitise bad characters in log file names. On Windows, colons are illegal in filenames, because they're part of the path syntax. But colons can appear in automatically constructed log file names, if an IPv6 address is expanded from the &H placeholder. Now we coerce any such illegal characters to '.', which is a bit of a bodge but should at least cause a log file to be generated. (cherry picked from commit 64ec5e03d5362ed036e9de1a765085c571eaa3b7) --- logging.c | 15 +++++++++++++-- putty.h | 1 + unix/uxmisc.c | 7 +++++++ windows/winmisc.c | 7 +++++++ 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/logging.c b/logging.c index c4538300..954721b9 100644 --- a/logging.c +++ b/logging.c @@ -446,6 +446,7 @@ static Filename *xlatlognam(Filename *src, char *hostname, int port, s = filename_to_str(src); while (*s) { + int sanitise = FALSE; /* Let (bufp, len) be the string to append. */ bufp = buf; /* don't usually override this */ if (*s == '&') { @@ -478,6 +479,12 @@ static Filename *xlatlognam(Filename *src, char *hostname, int port, if (c != '&') buf[size++] = c; } + /* Never allow path separators - or any other illegal + * filename character - to come out of any of these + * auto-format directives. E.g. 'hostname' can contain + * colons, if it's an IPv6 address, and colons aren't + * legal in filenames on Windows. */ + sanitise = TRUE; } else { buf[0] = *s++; size = 1; @@ -486,8 +493,12 @@ static Filename *xlatlognam(Filename *src, char *hostname, int port, bufsize = (buflen + size) * 5 / 4 + 512; buffer = sresize(buffer, bufsize, char); } - memcpy(buffer + buflen, bufp, size); - buflen += size; + while (size-- > 0) { + char c = *bufp++; + if (sanitise) + c = filename_char_sanitise(c); + buffer[buflen++] = c; + } } buffer[buflen] = '\0'; diff --git a/putty.h b/putty.h index add92c8b..9580c3cd 100644 --- a/putty.h +++ b/putty.h @@ -1305,6 +1305,7 @@ int filename_serialise(const Filename *f, void *data); Filename *filename_deserialise(void *data, int maxsize, int *used); char *get_username(void); /* return value needs freeing */ char *get_random_data(int bytes); /* used in cmdgen.c */ +char filename_char_sanitise(char c); /* rewrite special pathname chars */ /* * Exports and imports from timing.c. diff --git a/unix/uxmisc.c b/unix/uxmisc.c index 61a44d57..b7727cb2 100644 --- a/unix/uxmisc.c +++ b/unix/uxmisc.c @@ -94,6 +94,13 @@ Filename *filename_deserialise(void *vdata, int maxsize, int *used) return filename_from_str(data); } +char filename_char_sanitise(char c) +{ + if (c == '/') + return '.'; + return c; +} + #ifdef DEBUG static FILE *debug_fp = NULL; diff --git a/windows/winmisc.c b/windows/winmisc.c index 5bf52141..ba15bad6 100644 --- a/windows/winmisc.c +++ b/windows/winmisc.c @@ -69,6 +69,13 @@ Filename *filename_deserialise(void *vdata, int maxsize, int *used) return filename_from_str(data); } +char filename_char_sanitise(char c) +{ + if (strchr("<>:\"/\\|?*", c)) + return '.'; + return c; +} + #ifndef NO_SECUREZEROMEMORY /* * Windows implementation of smemclr (see misc.c) using SecureZeroMemory. -- 2.45.2