From 4c39eae490435454623701095d326262862935ae Mon Sep 17 00:00:00 2001 From: Nicolas Schodet Date: Thu, 11 Oct 2018 21:18:56 +0200 Subject: Mysql: changes following Joey's review - add a comment about database names, - do not use Show to generate configuration, - use Enum for privileges, - safely quote strings given as SQL parameters. Also always use uppercase for SQL. --- src/Propellor/Property/Mysql.hs | 82 +++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 44 deletions(-) (limited to 'src/Propellor/Property') diff --git a/src/Propellor/Property/Mysql.hs b/src/Propellor/Property/Mysql.hs index 77775889..f7639a29 100644 --- a/src/Propellor/Property/Mysql.hs +++ b/src/Propellor/Property/Mysql.hs @@ -21,6 +21,7 @@ import Propellor.Base import Data.List import qualified Propellor.Property.Apt as Apt +-- | A database is defined by its name. newtype Database = Database String data Privilege @@ -41,48 +42,30 @@ data Privilege | AlterRoutine | Event | Trigger - deriving (Eq, Ord) + deriving (Eq, Ord, Enum) -instance Show Privilege where - show Select = "SELECT" - show Insert = "INSERT" - show Update = "UPDATE" - show Delete = "DELETE" - show Create = "CREATE" - show Drop = "DROP" - show Index = "INDEX" - show Alter = "ALTER" - show CreateTemporaryTables = "CREATE TEMPORARY TABLES" - show LockTables = "LOCK TABLES" - show Execute = "EXECUTE" - show CreateView = "CREATE VIEW" - show ShowView = "SHOW VIEW" - show CreateRoutine = "CREATE ROUTINE" - show AlterRoutine = "ALTER ROUTINE" - show Event = "EVENT" - show Trigger = "TRIGGER" +sqlPrivilege :: Privilege -> String +sqlPrivilege Select = "SELECT" +sqlPrivilege Insert = "INSERT" +sqlPrivilege Update = "UPDATE" +sqlPrivilege Delete = "DELETE" +sqlPrivilege Create = "CREATE" +sqlPrivilege Drop = "DROP" +sqlPrivilege Index = "INDEX" +sqlPrivilege Alter = "ALTER" +sqlPrivilege CreateTemporaryTables = "CREATE TEMPORARY TABLES" +sqlPrivilege LockTables = "LOCK TABLES" +sqlPrivilege Execute = "EXECUTE" +sqlPrivilege CreateView = "CREATE VIEW" +sqlPrivilege ShowView = "SHOW VIEW" +sqlPrivilege CreateRoutine = "CREATE ROUTINE" +sqlPrivilege AlterRoutine = "ALTER ROUTINE" +sqlPrivilege Event = "EVENT" +sqlPrivilege Trigger = "TRIGGER" -- | All privileges allPrivileges :: [Privilege] -allPrivileges = - [ Select - , Insert - , Update - , Delete - , Create - , Drop - , Index - , Alter - , CreateTemporaryTables - , LockTables - , Execute - , CreateView - , ShowView - , CreateRoutine - , AlterRoutine - , Event - , Trigger - ] +allPrivileges = [Select .. Trigger] -- | Basic privileges needed to use a classic database already created. basicPrivileges :: [Privilege] @@ -156,7 +139,8 @@ databaseExists (Database dbname) = dbPresent :: IO Bool dbPresent = (== trueResult) <$> readProcess "mysql" ["-BNre", sql] where - sql = "show databases like '" ++ dbname ++ "'" + sql = "SHOW DATABASES LIKE " ++ qdbname + qdbname = sqlQuote '\'' dbname trueResult = dbname ++ "\n" -- Create an user and make sure he has grants on the specific database but no @@ -183,7 +167,7 @@ userGrantedOnDatabase user@(User username) (Database dbname) privs context = ++ "GRANT " ++ privList ++ " ON " ++ privLevel ++ " TO " ++ quser ++ "\n" -- Privilege level for database access. - privLevel = "`" ++ dbname ++ "`.*" + privLevel = (sqlQuote '`' dbname) ++ ".*" -- Create an user and make sure he has global grants but no other grant. userGranted @@ -266,16 +250,26 @@ userGranted' (User username) privs context setupDesc setupSql userGrants = (Just writer) Nothing where writer h = hPutStr h sql - sql = "select password('" ++ password ++ "')" + sql = "SELECT PASSWORD(" ++ qpassword ++ ")" + qpassword = sqlQuote '\'' password -- Request current user grants from MySQL. getUserGrants :: IO String getUserGrants = catchDefaultIO "" $ readProcess "mysql" ["-BNre", sql] where - sql = "show grants for " ++ quser + sql = "SHOW GRANTS FOR " ++ quser -- Privilege list as output by MySQL. - privList = intercalate ", " $ map show $ nub $ sort privs + privList = intercalate ", " $ map sqlPrivilege $ nub $ sort privs -- Qualified user name. - quser = "'" ++ username ++ "'@'localhost'" + quser = (sqlQuote '\'' username) ++ "@'localhost'" + +-- | Quote a string using the given quote character. +sqlQuote :: Char -> String -> String +sqlQuote quote s = + [quote] ++ (concatMap escape s) ++ [quote] + where + escape c + | c == quote = [quote, quote] + | otherwise = [c] -- cgit v1.2.3