fix(nano): drop oversized hasJoined parameters before asking sources
username, serverId and ip were forwarded to every configured source at whatever length the caller sent, up to the megabyte net/http allows in a request line. Velocity never sends more than a 16-character name, a 41-character signed SHA-1 serverId and a textual IP address, so only a direct caller reaches those sizes, and each such request cost one oversized upstream call per source. Any of the three over 64 bytes is now answered 204 before a source is asked, the same as a missing username or serverId. 64 bytes still leaves room for a 16-character name in multi-byte UTF-8. The subtest behind this points a source that validates anything at the handler and sends missing and oversized fields, expecting 204 and zero upstream requests, then a well-formed login that gets 200. It replaces the old missing-username case, whose only source was unreachable, so the test passed even with the guard removed. Dropping the length check now fails it on the long username; dropping the whole guard fails it on the first missing field.
This commit is contained in:
2 files changed
+34
-9
No files matched your search
@@ -116,13 +116,14 @@ func (a *API) handleHasJoined(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
q := r.URL.Query()
|
||||
username, serverID := q.Get("username"), q.Get("serverId")
|
||||
if username == "" || serverID == "" {
|
||||
username, serverID, ip := q.Get("username"), q.Get("serverId"), q.Get("ip")
|
||||
if username == "" || serverID == "" ||
|
||||
len(username) > maxHasJoinedParam || len(serverID) > maxHasJoinedParam || len(ip) > maxHasJoinedParam {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
|
||||
prof, src, failed := a.resolveHasJoined(r.Context(), username, serverID, q.Get("ip"))
|
||||
prof, src, failed := a.resolveHasJoined(r.Context(), username, serverID, ip)
|
||||
if prof == nil {
|
||||
// With a source down, "nobody knows this player" is not established: its player may
|
||||
// be the one logging in. 503 makes Velocity report the auth servers as down and log
|
||||
@@ -188,6 +189,11 @@ func (a *API) handleHasJoined(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, prof)
|
||||
}
|
||||
|
||||
// maxHasJoinedParam bounds each query value before it is forwarded to every source. What
|
||||
// Velocity sends fits with room to spare: a login name of at most 16 characters, a signed
|
||||
// SHA-1 hex serverId of at most 41, a textual IP address. Only a direct caller sends more.
|
||||
const maxHasJoinedParam = 64
|
||||
|
||||
// mcUsernameRe is Minecraft's username charset — the trust boundary on a third-party
|
||||
// source's self-asserted profile name.
|
||||
var mcUsernameRe = regexp.MustCompile(`^[A-Za-z0-9_]{3,16}$`)
|
||||
|
||||
Reference in new issue
Block a user