Merge "scouting: Make /sha256/ requests stricter"
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 {
diff --git a/scouting/webserver/static/static_test.go b/scouting/webserver/static/static_test.go
index 09ed940..1d036a0 100644
--- a/scouting/webserver/static/static_test.go
+++ b/scouting/webserver/static/static_test.go
@@ -92,6 +92,14 @@
 		t.Fatal("Failed to get data ", err)
 	}
 	expectEqual(t, resp.Status, "404 Not Found")
+
+	// Make a request with a valid checksum but invalid path and make sure
+	// we get a 400.
+	resp, err = http.Get("http://localhost:8080/sha256/553b9b29647a112136986cf93c57b988d1f12dc43d3b774f14a24e58d272dbff/not_root.txt")
+	if err != nil {
+		t.Fatal("Failed to get data ", err)
+	}
+	expectEqual(t, resp.Status, "400 Bad Request")
 }
 
 // Retrieves the data at the specified path. If an error occurs, the test case