diff options
-rw-r--r-- | go.mod | 1 | ||||
-rw-r--r-- | go.sum | 2 | ||||
-rw-r--r-- | pkg/api/api0/api.go | 41 | ||||
-rw-r--r-- | pkg/api/api0/client.go | 8 |
4 files changed, 51 insertions, 1 deletions
@@ -7,6 +7,7 @@ require ( github.com/cardigann/harhar v0.0.0-20161005032312-acb91b7a8682 github.com/rs/zerolog v1.28.0 github.com/spf13/pflag v1.0.5 + golang.org/x/mod v0.5.1 golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458 ) @@ -15,6 +15,8 @@ github.com/rs/zerolog v1.28.0 h1:MirSo27VyNi7RJYP3078AA1+Cyzd2GB66qy3aUHvsWY= github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458 h1:MgJ6t2zo8v0tbmLCueaCbF1RM+TtB0rs3Lv8DGtOIpY= golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= 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 == "" { |