From 64ec5e03d5362ed036e9de1a765085c571eaa3b7 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. --- 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 19eb2cb3..563dcded 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 4b22c38e..cfdc8154 100644 --- a/putty.h +++ b/putty.h @@ -1322,6 +1322,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 2e13b3bb..a7a2fcb9 100644 --- a/unix/uxmisc.c +++ b/unix/uxmisc.c @@ -95,6 +95,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 ce0a0d1d..f2e4f223 100644 --- a/windows/winmisc.c +++ b/windows/winmisc.c @@ -71,6 +71,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