changeset 467:73c7b2d6246e

Used hex-encoded usernames and a stored procedure to decode them to impersonate with the metamorph user.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Wed, 22 Aug 2018 17:43:30 +0200
parents e3035621cc52
children ff9dbe14f033
files cmd/gemma/geoserver.go pkg/auth/opendb.go pkg/middleware/modifyquery.go pkg/models/types.go schema/manage_users.sql
diffstat 5 files changed, 23 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/cmd/gemma/geoserver.go	Wed Aug 22 17:30:12 2018 +0200
+++ b/cmd/gemma/geoserver.go	Wed Aug 22 17:43:30 2018 +0200
@@ -21,7 +21,7 @@
 )
 
 const (
-	startupSQL = `SET ROLE "${user,sys_admin}"`
+	startupSQL = `SELECT public.setrole("${user}")`
 	closeupSQL = `RESET ROLE`
 )
 
--- a/pkg/auth/opendb.go	Wed Aug 22 17:30:12 2018 +0200
+++ b/pkg/auth/opendb.go	Wed Aug 22 17:43:30 2018 +0200
@@ -2,8 +2,8 @@
 
 import (
 	"database/sql"
+	"encoding/hex"
 	"errors"
-	"strings"
 
 	"github.com/jackc/pgx"
 	"github.com/jackc/pgx/stdlib"
@@ -41,12 +41,7 @@
 WHERE oid IN (SELECT oid FROM cte) AND rolname <> current_user
 AND EXISTS (SELECT 1 FROM users.list_users WHERE username = current_user)`
 
-const InvalidRoleCharacters = `\"':;`
-
-var (
-	ErrInvalidRoleCharacters = errors.New("rolename contains invalid character")
-	ErrNoMetamorphUser       = errors.New("No metamorphic user configured")
-)
+var ErrNoMetamorphUser = errors.New("No metamorphic user configured")
 
 func AllOtherRoles(user, password string) (Roles, error) {
 	db, err := OpenDB(user, password)
@@ -73,9 +68,6 @@
 }
 
 func RunAs(role string, fn func(*sql.DB) error) error {
-	if strings.Contains(role, InvalidRoleCharacters) {
-		return ErrInvalidRoleCharacters
-	}
 	user := config.MetamorphDBUser()
 	if user == "" {
 		return ErrNoMetamorphUser
@@ -85,8 +77,10 @@
 		return nil
 	}
 	defer db.Close()
-	if _, err := db.Exec(`SET ROLE "` + role + `"`); err != nil {
-		return err
+	if _, err = db.Exec(
+		`SELECT public.setrole($1)`, hex.EncodeToString([]byte(role)),
+	); err == nil {
+		err = fn(db)
 	}
-	return fn(db)
+	return err
 }
--- a/pkg/middleware/modifyquery.go	Wed Aug 22 17:30:12 2018 +0200
+++ b/pkg/middleware/modifyquery.go	Wed Aug 22 17:43:30 2018 +0200
@@ -1,6 +1,7 @@
 package middleware
 
 import (
+	"encoding/hex"
 	"log"
 	"net/http"
 	"net/url"
@@ -81,9 +82,9 @@
 	parameters.Del("env")
 
 	session, ok := auth.GetSession(req)
-	if ok && !strings.ContainsAny(session.User, auth.InvalidRoleCharacters) {
+	if ok {
 		log.Printf("Injecting user %s\n", session.User)
-		parameters.Set("env", "user:"+session.User)
+		parameters.Set("env", "user:"+hex.EncodeToString([]byte(session.User)))
 	}
 	return nil
 }
--- a/pkg/models/types.go	Wed Aug 22 17:30:12 2018 +0200
+++ b/pkg/models/types.go	Wed Aug 22 17:43:30 2018 +0200
@@ -6,8 +6,6 @@
 	"errors"
 	"regexp"
 	"strings"
-
-	"gemma.intevation.de/gemma/pkg/auth"
 )
 
 type (
@@ -82,8 +80,7 @@
 var errNoValidUser = errors.New("Not a valid user")
 
 func (u UserName) IsValid() bool {
-	return u != "" &&
-		!strings.ContainsAny(string(u), auth.InvalidRoleCharacters)
+	return u != ""
 }
 
 func (u *UserName) UnmarshalJSON(data []byte) error {
--- a/schema/manage_users.sql	Wed Aug 22 17:30:12 2018 +0200
+++ b/schema/manage_users.sql	Wed Aug 22 17:43:30 2018 +0200
@@ -204,3 +204,14 @@
 
 CREATE OR REPLACE VIEW pw_reset.list_users AS
     SELECT username, pw, email_address FROM users.list_users;
+
+-- To set a role from a hex-encoded user name (which is save from SQL injections).
+CREATE OR REPLACE FUNCTION public.setrole(role text) RETURNS void
+AS $$
+BEGIN
+    IF role IS NOT NULL AND role <> '' THEN
+        EXECUTE format('SET ROLE %I', convert_from(decode(role, 'hex'), 'UTF-8'));
+    END IF;
+END;
+$$
+    LANGUAGE plpgsql;