diff options
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/api/api0/api.go | 41 | ||||
-rw-r--r-- | pkg/api/api0/client.go | 8 |
2 files changed, 48 insertions, 1 deletions
diff --git a/pkg/api/api0/api.go b/pkg/api/api0/api.go index e6ed251..f7b787c 100644 --- a/pkg/api/api0/api.go +++ b/pkg/api/api0/api.go @@ -20,6 +20,9 @@ import ( "net/http" "strconv" "strings" + + "github.com/rs/zerolog/hlog" + "golang.org/x/mod/semver" ) // Handler serves requests for the original master server API. @@ -40,6 +43,11 @@ type Handler struct { // makes the server trust that clients are who they say they are. Blame // @BobTheBob9 for this option even existing in the first place. InsecureDevNoCheckPlayerAuth bool + + // MinimumLauncherVersion restricts authentication and server registration + // to clients with at least this version, which must be valid semver. +dev + // versions are always allowed. + MinimumLauncherVersion string } // ServeHTTP routes requests to Handler. @@ -71,6 +79,39 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } } +// checkLauncherVersion checks if the r was made by NorthstarLauncher and if it +// is at least MinimumLauncherVersion. +func (h *Handler) checkLauncherVersion(r *http.Request) bool { + rver, _, _ := strings.Cut(r.Header.Get("User-Agent"), " ") + if x := strings.TrimPrefix(rver, "R2Northstar/"); rver != x { + if x[0] != 'v' { + rver = "v" + x + } else { + rver = x + } + } else { + return false // deny: not R2Northstar + } + + mver := h.MinimumLauncherVersion + if mver != "" { + if mver[0] != 'v' { + mver = "v" + mver + } + } else { + return true // allow: no minimum version + } + if !semver.IsValid(mver) { + hlog.FromRequest(r).Warn().Msgf("not checking invalid minimum version %q", mver) + return true // allow: invalid minimum version + } + + if strings.HasSuffix(rver, "+dev") { + return true // allow: dev versions + } + return semver.Compare(rver, mver) >= 0 +} + // respJSON writes the JSON encoding of obj with the provided response status. func respJSON(w http.ResponseWriter, r *http.Request, status int, obj any) { if r.Method == http.MethodHead { diff --git a/pkg/api/api0/client.go b/pkg/api/api0/client.go index 3f10dcb..b805261 100644 --- a/pkg/api/api0/client.go +++ b/pkg/api/api0/client.go @@ -75,7 +75,13 @@ func (h *Handler) handleClientAuthWithSelf(w http.ResponseWriter, r *http.Reques return } - // TODO: version gate + if !h.checkLauncherVersion(r) { + respJSON(w, r, http.StatusBadRequest, map[string]any{ + "success": false, + "error": ErrorCode_UNSUPPORTED_VERSION, + }) + return + } uidQ := r.URL.Query().Get("id") if uidQ == "" { |