aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--go.mod1
-rw-r--r--go.sum2
-rw-r--r--pkg/api/api0/api.go41
-rw-r--r--pkg/api/api0/client.go8
4 files changed, 51 insertions, 1 deletions
diff --git a/go.mod b/go.mod
index b060632..83bbafa 100644
--- a/go.mod
+++ b/go.mod
@@ -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
)
diff --git a/go.sum b/go.sum
index 25e7995..d014445 100644
--- a/go.sum
+++ b/go.sum
@@ -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 == "" {