diff pkg/middleware/modifyquery.go @ 419:6627c48363a0

First attempt for user injection of proxy for using GeoServer with role based security.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Thu, 16 Aug 2018 13:39:13 +0200
parents
children ffdb507d5b42
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pkg/middleware/modifyquery.go	Thu Aug 16 13:39:13 2018 +0200
@@ -0,0 +1,89 @@
+package middleware
+
+import (
+	"log"
+	"net/http"
+	"net/url"
+	"strings"
+
+	"gemma.intevation.de/gemma/pkg/auth"
+)
+
+// ParseQuery is a modified version of the internal query
+// parser of the url.parseQuery of the standard library.
+func ParseQuery(
+	m url.Values,
+	query string,
+	keySep, valueSep string,
+	unescape func(string) (string, error),
+) error {
+	if unescape == nil {
+		unescape = url.QueryUnescape
+	}
+	for query != "" {
+		key := query
+		if i := strings.Index(key, keySep); i >= 0 {
+			key, query = key[:i], key[i+1:]
+
+		} else {
+			query = ""
+		}
+		if key == "" {
+			continue
+		}
+		value := ""
+		if i := strings.Index(key, valueSep); i >= 0 {
+			key, value = key[:i], key[i+1:]
+		}
+		key, err := unescape(key)
+		if err != nil {
+			return err
+		}
+		value, err = unescape(value)
+		if err != nil {
+			return err
+		}
+		m[key] = append(m[key], value)
+	}
+	return nil
+}
+
+func ModifyQuery(next http.Handler, modify func(*http.Request, url.Values) error) http.Handler {
+
+	return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
+
+		// GeoServer query parameters contain ';' as sub key separators.
+		// If we would use req.URL.Query() this would be split
+		// at the wrong level resulting in broken key/value pairs.
+		// So we do the splitting ourselves.
+
+		parameters := make(url.Values)
+
+		if err := ParseQuery(parameters, req.URL.RawQuery, "&", "=", nil); err != nil {
+			log.Printf("parsing query failed: %v\n", err)
+			http.Error(rw, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
+			return
+		}
+
+		if err := modify(req, parameters); err != nil {
+			log.Printf("modifying query parameters failed: %v\n", err)
+			http.Error(rw, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
+		}
+
+		req.URL.RawQuery = parameters.Encode()
+
+		next.ServeHTTP(rw, req)
+	})
+}
+
+func InjectUser(req *http.Request, parameters url.Values) error {
+	// To prevent SQL injections
+	parameters.Del("env")
+
+	session, ok := auth.GetSession(req)
+	if ok && !strings.ContainsAny(session.User, `\"':;`) {
+		log.Printf("Injecting user %s\n", session.User)
+		parameters.Set("env", "user:"+session.User)
+	}
+	return nil
+}