diff --git a/api/create.go b/api/create.go index 8864043..da8d706 100644 --- a/api/create.go +++ b/api/create.go @@ -41,8 +41,16 @@ func (s *Server) handleCreate(w http.ResponseWriter, r *http.Request) { return } - d, _ := strconv.Atoi(dur) - i, _ := strconv.ParseFloat(interval, 64) + d, err := strconv.Atoi(dur) + if err != nil || d <= 0 { + fmt.Fprintln(w, "Invalid duration!") + return + } + i, err := strconv.ParseFloat(interval, 64) + if err != nil || i <= 0 { + fmt.Fprintln(w, "Invalid interval!") + return + } mod, _ := strconv.Atoi(r.FormValue("mod")) adoptable := r.FormValue("ado") == "1" encrypted := r.FormValue("e2e") == "1" @@ -110,7 +118,7 @@ func (s *Server) handleCreate(w http.ResponseWriter, r *http.Request) { } if customLink != "" && linkIDRe.MatchString(customLink) { - if err := s.tryCustomLink(ctx, share, customLink); err == nil { + if err := s.tryCustomLink(ctx, customLink, user); err == nil { share.SetID(customLink) } } @@ -142,7 +150,7 @@ func (s *Server) handleCreate(w http.ResponseWriter, r *http.Request) { } if customLink != "" && linkIDRe.MatchString(customLink) { - if err := s.tryCustomLink(ctx, share, customLink); err == nil { + if err := s.tryCustomLink(ctx, customLink, user); err == nil { share.SetID(customLink) } } @@ -195,11 +203,32 @@ func (s *Server) handleCreate(w http.ResponseWriter, r *http.Request) { } } -type customLinkSetter interface { - SetID(string) -} +func (s *Server) tryCustomLink(ctx context.Context, link, user string) error { + if !s.cfg.AllowLinkReq { + return fmt.Errorf("custom links disabled") + } + + // check reserved links + if allowedUsers, reserved := s.cfg.ReservedLinks[link]; reserved { + allowed := false + for _, u := range allowedUsers { + if u == user { + allowed = true + break + } + } + if !allowed { + return fmt.Errorf("link reserved") + } + } + + // whitelist mode: only reserved links allowed + if s.cfg.ReserveWL { + if _, reserved := s.cfg.ReservedLinks[link]; !reserved { + return fmt.Errorf("link not in whitelist") + } + } -func (s *Server) tryCustomLink(ctx context.Context, _ customLinkSetter, link string) error { exists, err := s.store.Exists(ctx, "locdata-"+link) if err != nil { return err diff --git a/api/post.go b/api/post.go index 9338308..5fa7542 100644 --- a/api/post.go +++ b/api/post.go @@ -36,11 +36,12 @@ func (s *Server) handlePost(w http.ResponseWriter, r *http.Request) { var point []any if !session.Encrypted() { - latF, _ := strconv.ParseFloat(lat, 64) - lonF, _ := strconv.ParseFloat(lon, 64) - timeF, _ := strconv.ParseFloat(ts, 64) + latF, err1 := strconv.ParseFloat(lat, 64) + lonF, err2 := strconv.ParseFloat(lon, 64) + timeF, err3 := strconv.ParseFloat(ts, 64) - if latF < -90 || latF > 90 || lonF < -180 || lonF > 180 { + if err1 != nil || err2 != nil || err3 != nil || + latF < -90 || latF > 90 || lonF < -180 || lonF > 180 { fmt.Fprintln(w, "Invalid location!") return } diff --git a/model/session.go b/model/session.go index cb1f6a3..55a365b 100644 --- a/model/session.go +++ b/model/session.go @@ -95,14 +95,14 @@ func (s *Session) GetPoints(since float64) [][]any { if since <= 0 { return s.data.Points } - timeIdx := 2 + // encrypted sessions have opaque timestamps - can't filter server-side if s.data.Encrypted { - timeIdx = 3 + return s.data.Points } var pts [][]any for _, p := range s.data.Points { - if len(p) > timeIdx { - if t, ok := p[timeIdx].(float64); ok && t > since { + if len(p) > 2 { + if t, ok := p[2].(float64); ok && t > since { pts = append(pts, p) } } diff --git a/model/share.go b/model/share.go index 14a9783..6c25f91 100644 --- a/model/share.go +++ b/model/share.go @@ -2,7 +2,8 @@ package model import ( "context" - "math/rand" + "crypto/rand" + "encoding/binary" "strconv" "time" @@ -97,7 +98,7 @@ func NewGroupShare(s store.Store, publicURL string, linkGen func() (string, erro if err != nil { return nil, err } - pin := GroupPinMin + rand.Intn(GroupPinMax-GroupPinMin+1) + pin := GroupPinMin + cryptoRandInt(GroupPinMax-GroupPinMin+1) return &GroupShare{ store: s, id: id, @@ -201,3 +202,9 @@ func LoadShareType(ctx context.Context, s store.Store, id string) (int, error) { } return st.Type, nil } + +func cryptoRandInt(max int) int { + var b [8]byte + rand.Read(b[:]) + return int(binary.LittleEndian.Uint64(b[:]) % uint64(max)) +}