mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-04-22 11:19:32 -06:00
GF shell restricted mode
By setting the environment variable GF_RESTRICTED before starting GF, the shell will be run in restricted mode. This will prevent the GF shell from starting arbitrary system commands (most uses of System.Cmd.system are blocked) and writing arbitrary files (most commands that use writeFile et al are blocked). Restricted mode is intended minimize the potential security risks involved in allowing public access to the GF shell over the internet. It should be used in conjuction with system level protection mechanisms (e.g. file permissions) to make sure that a publicly acessible GF shell does not give access to parts of the system that should not be publicly accessible.
This commit is contained in:
@@ -45,7 +45,7 @@ import Data.Binary (encodeFile)
|
|||||||
import Data.List
|
import Data.List
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
import System.Cmd
|
--import System.Cmd(system) -- use GF.Infra.UseIO.restricedSystem instead!
|
||||||
import Text.PrettyPrint
|
import Text.PrettyPrint
|
||||||
import Data.List (sort)
|
import Data.List (sort)
|
||||||
import Debug.Trace
|
import Debug.Trace
|
||||||
@@ -172,8 +172,8 @@ allCommands env@(pgf, mos) = Map.fromList [
|
|||||||
let view = optViewGraph opts
|
let view = optViewGraph opts
|
||||||
let format = optViewFormat opts
|
let format = optViewFormat opts
|
||||||
writeUTF8File (file "dot") grph
|
writeUTF8File (file "dot") grph
|
||||||
system $ "dot -T" ++ format ++ " " ++ file "dot" ++ " > " ++ file format
|
restrictedSystem $ "dot -T" ++ format ++ " " ++ file "dot" ++ " > " ++ file format
|
||||||
system $ view ++ " " ++ file format
|
restrictedSystem $ view ++ " " ++ file format
|
||||||
return void
|
return void
|
||||||
else return $ fromString grph,
|
else return $ fromString grph,
|
||||||
examples = [
|
examples = [
|
||||||
@@ -769,9 +769,9 @@ allCommands env@(pgf, mos) = Map.fromList [
|
|||||||
exec = \opts arg -> do
|
exec = \opts arg -> do
|
||||||
let tmpi = "_tmpi" ---
|
let tmpi = "_tmpi" ---
|
||||||
let tmpo = "_tmpo"
|
let tmpo = "_tmpo"
|
||||||
writeFile tmpi $ toString arg
|
restricted $ writeFile tmpi $ toString arg
|
||||||
let syst = optComm opts ++ " " ++ tmpi
|
let syst = optComm opts ++ " " ++ tmpi
|
||||||
system $ syst ++ " <" ++ tmpi ++ " >" ++ tmpo
|
restrictedSystem $ syst ++ " <" ++ tmpi ++ " >" ++ tmpo
|
||||||
s <- readFile tmpo
|
s <- readFile tmpo
|
||||||
return $ fromString s,
|
return $ fromString s,
|
||||||
flags = [
|
flags = [
|
||||||
@@ -843,9 +843,9 @@ allCommands env@(pgf, mos) = Map.fromList [
|
|||||||
let file s = "_grphd." ++ s
|
let file s = "_grphd." ++ s
|
||||||
let view = optViewGraph opts
|
let view = optViewGraph opts
|
||||||
let format = optViewFormat opts
|
let format = optViewFormat opts
|
||||||
writeUTF8File (file "dot") grphs
|
restricted $ writeUTF8File (file "dot") grphs
|
||||||
system $ "dot -T" ++ format ++ " " ++ file "dot" ++ " > " ++ file format
|
restrictedSystem $ "dot -T" ++ format ++ " " ++ file "dot" ++ " > " ++ file format
|
||||||
system $ view ++ " " ++ file format
|
restrictedSystem $ view ++ " " ++ file format
|
||||||
return void
|
return void
|
||||||
else return $ fromString grphs,
|
else return $ fromString grphs,
|
||||||
examples = [
|
examples = [
|
||||||
@@ -884,9 +884,9 @@ allCommands env@(pgf, mos) = Map.fromList [
|
|||||||
let file s = "_grph." ++ s
|
let file s = "_grph." ++ s
|
||||||
let view = optViewGraph opts
|
let view = optViewGraph opts
|
||||||
let format = optViewFormat opts
|
let format = optViewFormat opts
|
||||||
writeUTF8File (file "dot") grph
|
restricted $ writeUTF8File (file "dot") grph
|
||||||
system $ "dot -T" ++ format ++ " " ++ file "dot" ++ " > " ++ file format
|
restrictedSystem $ "dot -T" ++ format ++ " " ++ file "dot" ++ " > " ++ file format
|
||||||
system $ view ++ " " ++ file format
|
restrictedSystem $ view ++ " " ++ file format
|
||||||
return void
|
return void
|
||||||
else return $ fromString grph,
|
else return $ fromString grph,
|
||||||
examples = [
|
examples = [
|
||||||
@@ -929,9 +929,9 @@ allCommands env@(pgf, mos) = Map.fromList [
|
|||||||
let file s = "_grph." ++ s
|
let file s = "_grph." ++ s
|
||||||
let view = optViewGraph opts
|
let view = optViewGraph opts
|
||||||
let format = optViewFormat opts
|
let format = optViewFormat opts
|
||||||
writeUTF8File (file "dot") grph
|
restricted $ writeUTF8File (file "dot") grph
|
||||||
system $ "dot -T" ++ format ++ " " ++ file "dot" ++ " > " ++ file format
|
restrictedSystem $ "dot -T" ++ format ++ " " ++ file "dot" ++ " > " ++ file format
|
||||||
system $ view ++ " " ++ file format
|
restrictedSystem $ view ++ " " ++ file format
|
||||||
return void
|
return void
|
||||||
else return $ fromString grph,
|
else return $ fromString grph,
|
||||||
examples = [
|
examples = [
|
||||||
@@ -955,8 +955,8 @@ allCommands env@(pgf, mos) = Map.fromList [
|
|||||||
exec = \opts arg -> do
|
exec = \opts arg -> do
|
||||||
let file = valStrOpts "file" "_gftmp" opts
|
let file = valStrOpts "file" "_gftmp" opts
|
||||||
if isOpt "append" opts
|
if isOpt "append" opts
|
||||||
then appendFile file (toString arg)
|
then restricted $ appendFile file (toString arg)
|
||||||
else writeUTF8File file (toString arg)
|
else restricted $ writeUTF8File file (toString arg)
|
||||||
return void,
|
return void,
|
||||||
options = [
|
options = [
|
||||||
("append","append to file, instead of overwriting it")
|
("append","append to file, instead of overwriting it")
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import System.IO.Error
|
|||||||
import System.Environment
|
import System.Environment
|
||||||
import System.Exit
|
import System.Exit
|
||||||
import System.CPUTime
|
import System.CPUTime
|
||||||
|
import System.Cmd
|
||||||
import Text.Printf
|
import Text.Printf
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
import Control.Exception(evaluate)
|
import Control.Exception(evaluate)
|
||||||
@@ -191,3 +192,19 @@ writeUTF8File fpath content = do
|
|||||||
hSetEncoding h utf8
|
hSetEncoding h utf8
|
||||||
hPutStr h content
|
hPutStr h content
|
||||||
hClose h
|
hClose h
|
||||||
|
|
||||||
|
-- * Functions to limit acesss to arbitrary IO and system commands
|
||||||
|
restricted io =
|
||||||
|
either (const io) (const $ fail message) =<< try (getEnv "GF_RESTRICTED")
|
||||||
|
where
|
||||||
|
message =
|
||||||
|
"This operation is not allowed when GF is running in restricted mode."
|
||||||
|
|
||||||
|
restrictedSystem = restricted . system
|
||||||
|
|
||||||
|
|
||||||
|
-- Because GHC adds the confusing text "user error" for failures cased by
|
||||||
|
-- calls to fail.
|
||||||
|
ioErrorText e = if isUserError e
|
||||||
|
then ioeGetErrorString e
|
||||||
|
else show e
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ import qualified Data.Map as Map
|
|||||||
import qualified Data.ByteString.Char8 as BS
|
import qualified Data.ByteString.Char8 as BS
|
||||||
import qualified Text.ParserCombinators.ReadP as RP
|
import qualified Text.ParserCombinators.ReadP as RP
|
||||||
import System.IO
|
import System.IO
|
||||||
import System.Cmd
|
|
||||||
import System.CPUTime
|
import System.CPUTime
|
||||||
import System.Directory
|
import System.Directory
|
||||||
import Control.Exception
|
import Control.Exception
|
||||||
@@ -107,7 +106,7 @@ loop opts gfenv0 = do
|
|||||||
r <- runInterruptibly $ case pwords of
|
r <- runInterruptibly $ case pwords of
|
||||||
|
|
||||||
"!":ws -> do
|
"!":ws -> do
|
||||||
system $ unwords ws
|
restrictedSystem $ unwords ws
|
||||||
loopNewCPU gfenv
|
loopNewCPU gfenv
|
||||||
"cc":ws -> do
|
"cc":ws -> do
|
||||||
let
|
let
|
||||||
@@ -154,7 +153,7 @@ loop opts gfenv0 = do
|
|||||||
let stop = case ws of
|
let stop = case ws of
|
||||||
('-':'o':'n':'l':'y':'=':fs):_ -> Just $ chunks ',' fs
|
('-':'o':'n':'l':'y':'=':fs):_ -> Just $ chunks ',' fs
|
||||||
_ -> Nothing
|
_ -> Nothing
|
||||||
writeFile "_gfdepgraph.dot" (depGraph stop sgr)
|
restricted $ writeFile "_gfdepgraph.dot" (depGraph stop sgr)
|
||||||
putStrLn "wrote graph in file _gfdepgraph.dot"
|
putStrLn "wrote graph in file _gfdepgraph.dot"
|
||||||
loopNewCPU gfenv
|
loopNewCPU gfenv
|
||||||
"eh":w:_ -> do
|
"eh":w:_ -> do
|
||||||
@@ -220,9 +219,11 @@ loop opts gfenv0 = do
|
|||||||
interpretCommandLine env s0
|
interpretCommandLine env s0
|
||||||
loopNewCPU gfenv
|
loopNewCPU gfenv
|
||||||
-- gfenv' <- return $ either (const gfenv) id r
|
-- gfenv' <- return $ either (const gfenv) id r
|
||||||
gfenv' <- either (\e -> (print e >> return gfenv)) return r
|
gfenv' <- either (\e -> (printException e >> return gfenv)) return r
|
||||||
loop opts gfenv'
|
loop opts gfenv'
|
||||||
|
|
||||||
|
printException e = maybe (print e) (putStrLn . ioErrorText) (fromException e)
|
||||||
|
|
||||||
checkComputeTerm sgr t = do
|
checkComputeTerm sgr t = do
|
||||||
mo <- maybe (Bad "no source grammar in scope") return $ greatestResource sgr
|
mo <- maybe (Bad "no source grammar in scope") return $ greatestResource sgr
|
||||||
((t,_),_) <- runCheck $ do t <- renameSourceTerm sgr mo t
|
((t,_),_) <- runCheck $ do t <- renameSourceTerm sgr mo t
|
||||||
|
|||||||
Reference in New Issue
Block a user