summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Bratch <luke@bratch.co.uk>2019-07-10 20:44:35 +0100
committerLuke Bratch <luke@bratch.co.uk>2019-07-10 20:44:35 +0100
commitb9a8951cf86214a3dcb430ae0d34e8d5dc1adb11 (patch)
treef868ace1f3e1763279eb513a49c3fdee9d3c0fab
parent22a4f361329ed4e303e2f1bdce9edf49e70970f3 (diff)
Ensure log filenames are safe for writing.
-rw-r--r--functions.c9
-rw-r--r--functions.h3
-rw-r--r--logging.c31
3 files changed, 39 insertions, 4 deletions
diff --git a/functions.c b/functions.c
index 8bbc213..938b8b1 100644
--- a/functions.c
+++ b/functions.c
@@ -1253,3 +1253,12 @@ int getclientcodetime(char *code, struct clientcodes *clientcodes) {
// If we got here, the code was never found
return 0;
}
+
+// Replace any instances of "find" with "replace" in the string "str"
+void replacechar(char *str, char find, char replace) {
+ for (size_t i = 0; i < strlen(str); i++) {
+ if (str[i] == find) {
+ str[i] = replace;
+ }
+ }
+}
diff --git a/functions.h b/functions.h
index 29ebff5..009a019 100644
--- a/functions.h
+++ b/functions.h
@@ -178,4 +178,7 @@ int setclientcodetime(char *code, struct clientcodes *clientcodes);
// Return the timestamp that a given client last disconnected, or 0 on failure.
int getclientcodetime(char *code, struct clientcodes *clientcodes);
+// Replace any instances of "find" with "replace" in the string "str"
+void replacechar(char *str, char find, char replace);
+
#endif
diff --git a/logging.c b/logging.c
index 5b790b1..6e8d9b7 100644
--- a/logging.c
+++ b/logging.c
@@ -77,10 +77,24 @@ int logline(char *str, char *ournick, char *basedir, int type) {
debugprint(DEBUG_FULL, "logline(): extracted '%s'.\n", tokens[i]);
}
+ // Make "filename safe" copies of from and to names to ensure filename ends up being safe
+ char from[MAXCHAR], to[MAXCHAR];
+ strcpy(from, tokens[0]);
+ strcpy(to, tokens[2]);
+ // Remove unsafe characters (assuming POSIX, just strip "/" and replace with "_")
+ replacechar(from, '/', '_');
+ replacechar(to, '/', '_');
+ // Ensure filename wouldn't be too long
+ if (strlen(from) > NAME_MAX || strlen(to) > NAME_MAX) {
+ debugprint(DEBUG_CRIT, "Filename would be too long if logging either '%s' or '%s', returning!\n", from, to);
+ return 0;
+ }
+
switch(type) {
case LOG_PRIVMSG:
// Extract the username from the prefix
extractnickfromprefix(tokens[0]);
+ extractnickfromprefix(from);
// Remove the leading ":" from the real message
stripprefix(str);
@@ -88,10 +102,16 @@ int logline(char *str, char *ournick, char *basedir, int type) {
// Build the log filename
// If the message was sent to us, then log it in the sender's log file
if (strncmp(tokens[2], ournick, strlen(tokens[0])) == 0) {
- snprintf(filename, MAXCHAR, "%s/logs/%s.log", basedir, tokens[0]);
+ if (!snprintf(filename, MAXCHAR, "%s/logs/%s.log", basedir, from)) {
+ debugprint(DEBUG_CRIT, "Error while log filename for from name, returning!\n");
+ return 0;
+ }
} else {
// Otherwise log it in the "to" log file
- snprintf(filename, MAXCHAR, "%s/logs/%s.log", basedir, tokens[2]);
+ if (!snprintf(filename, MAXCHAR, "%s/logs/%s.log", basedir, to)) {
+ debugprint(DEBUG_CRIT, "Error while log filename for to name, returning!\n");
+ return 0;
+ }
}
debugprint(DEBUG_FULL, "logline(): Logging PRIVMSG from '%s' to '%s' message '%s' in filename '%s'.\n", tokens[0], tokens[2], str, filename);
@@ -112,7 +132,7 @@ int logline(char *str, char *ournick, char *basedir, int type) {
return 0;
}
- snprintf(filename, MAXCHAR, "%s/logs/%s.log", basedir, tokens[2] + pos);
+ snprintf(filename, MAXCHAR, "%s/logs/%s.log", basedir, to + pos);
debugprint(DEBUG_FULL, "logline(): Logging JOIN/PART to/from '%s' in filename '%s'.\n", tokens[2] + pos, filename);
@@ -151,7 +171,10 @@ int logline(char *str, char *ournick, char *basedir, int type) {
// Remove the leading ":" from the topic
stripprefix(str);
- snprintf(filename, MAXCHAR, "%s/logs/%s.log", basedir, tokens[2]);
+ if (!snprintf(filename, MAXCHAR, "%s/logs/%s.log", basedir, to)) {
+ debugprint(DEBUG_CRIT, "Error while log filename for topic, returning!\n");
+ return 0;
+ }
debugprint(DEBUG_FULL, "logline(): Logging TOPIC for '%s' in filename '%s'.\n", tokens[2], filename);