scouting: Make /sha256/ requests stricter

Before this patch, requesting a file via its checksum only required
the checksum itself. The path specified after the checksum was
ignored. This meant that it was actually pretty easy to screw up the
checksum with copy-paste errors.

Signed-off-by: Philipp Schrader <philipp.schrader@gmail.com>
Change-Id: I382ae36f3be3eb373e261186cf399b6316e5f21d
diff --git a/scouting/webserver/static/static.go b/scouting/webserver/static/static.go
index 4c46fe7..fbad476 100644
--- a/scouting/webserver/static/static.go
+++ b/scouting/webserver/static/static.go
@@ -81,7 +81,14 @@
 			log.Println(err)
 			return nil
 		}
-		shaSums[hash] = "/" + strings.TrimPrefix(path, directory)
+		// We want all paths relative to the original search directory.
+		// That means we remove the search directory from the Walk()
+		// result. Also make sure that the final path doesn't start
+		// with a "/" to make it independent of whether "directory"
+		// ends with a "/" or not.
+		trimmedPath := strings.TrimPrefix(path, directory)
+		trimmedPath = strings.TrimPrefix(trimmedPath, "/")
+		shaSums[hash] = trimmedPath
 		return nil
 	})
 	if err != nil {
@@ -101,9 +108,9 @@
 		// [0] ""
 		// [1] "sha256"
 		// [2] "<checksum>"
-		// [3-] path...
-		parts := strings.Split(r.URL.Path, "/")
-		if len(parts) < 4 {
+		// [3] path...
+		parts := strings.SplitN(r.URL.Path, "/", 4)
+		if len(parts) != 4 {
 			w.WriteHeader(http.StatusNotFound)
 			return
 		}
@@ -114,6 +121,14 @@
 		}
 		hash := parts[2]
 		if path, ok := shaSums[hash]; ok {
+			// The path must match what it would be without the
+			// /sha256/<checksum>/ prefix. Otherwise it's too easy
+			// to make copy-paste mistakes.
+			if path != parts[3] {
+				log.Println("Got ", parts[3], "expected", path)
+				w.WriteHeader(http.StatusBadRequest)
+				return
+			}
 			// We found a file with this checksum. Serve that file.
 			r.URL.Path = path
 		} else {