Commit Diff


commit - f3870eac196bf7bdcedf3aceeba7501d5211b9ae
commit + 2fd3ff87b97ca6e71113c93bb8a9cfbfcae60b2e
blob - 51256227dc2db4529554e695b72bb80083571457
blob + e0db612ff2630fcce59769e289058b77a42e793e
--- FICS/playerdb.c
+++ FICS/playerdb.c
@@ -67,6 +67,7 @@
 #include "ficsmain.h"
 #include "gamedb.h"
 #include "lists.h"
+#include "maxxes-utils.h"
 #include "network.h"
 #include "playerdb.h"
 #include "ratings.h"
@@ -1079,17 +1080,37 @@ PUBLIC int
 player_read(int p, char *name)
 {
 	FILE	*fp = NULL;
-	char	*attr, *value;
 	char	 fname[MAX_FILENAME_SIZE] = { '\0' };
 	char	 line[MAX_LINE_SIZE] = { '\0' };
+	char	*attr, *value;
+	char	*resolvedPath;
 	int	 len = 0;
 	int	 version = 0;
 
-	parray[p].login = stolower(xstrdup(name));
+	parray[p].login = stolower(xstrdup(name)); // free on error?
 
+	if (!is_valid_login_name(parray[p].login)) {
+		warnx("%s: invalid login name: %s", __func__, parray[p].login);
+		return -1;
+	}
+
 	snprintf(fname, sizeof fname, "%s/%c/%s", player_dir,
 	    parray[p].login[0], parray[p].login);
 
+	if ((resolvedPath = realpath(fname, NULL)) == NULL) {
+		warn("%s: realpath", __func__);
+		return -1;
+	}
+	if (strncmp(resolvedPath, player_dir, strlen(player_dir)) != 0) {
+		warnx("%s: path traversal detected", __func__);
+		free(resolvedPath);
+		return -1;
+	}
+
+	mstrlcpy(fname, resolvedPath, sizeof fname);
+	free(resolvedPath);
+	resolvedPath = NULL;
+
 	if ((fp = fopen(fname, "r")) == NULL) { // Unregistered player
 		parray[p].name = xstrdup(name);
 		parray[p].registered = 0;