From 4ea51eb744e0ede9215194c02a46db8611ea49e9 Mon Sep 17 00:00:00 2001 From: "Sascha L. Teichmann" Date: Sat, 15 Nov 2014 13:40:39 +0100 Subject: [PATCH] mtwebmapper: Only allow update requests from a white list of remote hosts. Defaults to localhost. To allow all hosts use command line option -u='' --- cmd/mtwebmapper/main.go | 35 ++++++++++++++++++++++++++++- cmd/mtwebmapper/tilesupdater.go | 39 +++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/cmd/mtwebmapper/main.go b/cmd/mtwebmapper/main.go index a70ffd2..4edd209 100644 --- a/cmd/mtwebmapper/main.go +++ b/cmd/mtwebmapper/main.go @@ -8,13 +8,34 @@ import ( "flag" "fmt" "log" + "net" "net/http" + "strings" "bitbucket.org/s_l_teichmann/mtsatellite/common" "github.com/gorilla/mux" ) +func ipsFromHosts(hosts string) ([]net.IP, error) { + + ips := []net.IP{} + + if len(hosts) == 0 { // Empty list: allow all hosts. + return ips, nil + } + + for _, host := range strings.Split(hosts, ";") { + if hips, err := net.LookupIP(host); err != nil { + return nil, err + } else { + ips = append(ips, hips...) + } + } + + return ips, nil +} + func main() { var ( webPort int @@ -26,6 +47,7 @@ func main() { colorsFile string workers int transparent bool + updateHosts string ) flag.IntVar(&webPort, "web-port", 8808, "port of the web server") flag.IntVar(&webPort, "p", 8808, "port of the web server (shorthand)") @@ -35,6 +57,10 @@ func main() { flag.StringVar(&webDir, "w", "web", "static served web files (shorthand)") flag.StringVar(&mapDir, "map", "map", "directory of prerendered tiles") flag.StringVar(&mapDir, "m", "map", "directory of prerendered tiles (shorthand)") + flag.StringVar(&updateHosts, "update-hosts", "localhost", + "';' separated list of hosts which are allowed to send map update requests") + flag.StringVar(&updateHosts, "u", "localhost", + "';' separated list of hosts which are allowed to send map update requests (shorthand)") flag.StringVar(&redisHost, "redis-host", "", "address of the backend Redis server") flag.StringVar(&redisHost, "rh", "", "address of the backend Redis server (shorthand)") flag.IntVar(&redisPort, "redis-port", 6379, "port of the backend Redis server") @@ -59,7 +85,14 @@ func main() { log.Fatalf("ERROR: problem loading colors: %s", err) } redisAddress := fmt.Sprintf("%s:%d", redisHost, redisPort) - tu := newTileUpdater(mapDir, redisAddress, colors, transparent, workers) + + var allowedUpdateIps []net.IP + if allowedUpdateIps, err = ipsFromHosts(updateHosts); err != nil { + log.Fatalf("ERROR: name resolving problem: %s", err) + } + + tu := newTileUpdater( + mapDir, redisAddress, allowedUpdateIps, colors, transparent, workers) go tu.doUpdates() router.Path("/update").Methods("POST").Handler(tu) } diff --git a/cmd/mtwebmapper/tilesupdater.go b/cmd/mtwebmapper/tilesupdater.go index 7047164..a0b07d4 100644 --- a/cmd/mtwebmapper/tilesupdater.go +++ b/cmd/mtwebmapper/tilesupdater.go @@ -10,13 +10,17 @@ import ( "image" "image/draw" "log" + "net" "net/http" "path/filepath" "strconv" + "strings" "sync" "github.com/nfnt/resize" + "bytes" + "bitbucket.org/s_l_teichmann/mtsatellite/common" ) @@ -24,6 +28,7 @@ type tileUpdater struct { changes map[xz]bool mapDir string redisAddress string + ips []net.IP colors *common.Colors workers int transparent bool @@ -59,6 +64,7 @@ func (c xz) parent() xzm { func newTileUpdater( mapDir, redisAddress string, + ips []net.IP, colors *common.Colors, transparent bool, workers int) *tileUpdater { @@ -66,6 +72,7 @@ func newTileUpdater( tu := tileUpdater{ mapDir: mapDir, redisAddress: redisAddress, + ips: ips, changes: map[xz]bool{}, colors: colors, transparent: transparent, @@ -74,7 +81,39 @@ func newTileUpdater( return &tu } +func (tu *tileUpdater) checkIP(r *http.Request) bool { + if len(tu.ips) == 0 { + return true + } + + var host []string + if host = strings.SplitN(r.RemoteAddr, ":", 2); len(host) < 1 { + log.Printf("WARN: cannot extract host from '%s'\n", r.RemoteAddr) + return false + } + + var ip net.IP + if ip = net.ParseIP(host[0]); ip == nil { + log.Printf("WARN: cannot get IP for host '%s'.\n", host[0]) + return false + } + + for i := range tu.ips { + if bytes.Compare(tu.ips[i], ip) == 0 { + return true + } + } + + return false +} + func (tu *tileUpdater) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + if !tu.checkIP(r) { + log.Printf("WARN: Unauthorized update request from '%s'", r.RemoteAddr) + http.Error(rw, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) + return + } + var err error var newChanges []xz decoder := json.NewDecoder(r.Body)