Security type system

Run Settings
LanguageHaskell
Language Version
Run Command
{-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE OverloadedStrings #-} module Main ( main ) where import Control.Comonad (extract) import Control.Comonad.Cofree (Cofree (..)) import Control.Monad (unless) import Control.Monad.Error.Class (throwError) import Data.Map (Map) import Data.Semigroup ((<>)) import Data.Set (Set) import Data.Text (Text) import qualified Data.Map as Map import qualified Data.Set as Set import qualified Data.Text as Text import qualified Data.Text.IO as Text.IO type Environment = Map Text SecurityClass data Term a = Variable Text | Assign Text a a | If a a a deriving (Functor) type SecurityClass = Set Text check :: Environment -> Cofree Term () -> Either Text (Cofree Term SecurityClass) check env (() :< Variable name) | Just sc <- Map.lookup name env = pure $ sc :< Variable name | otherwise = throwError $ "No such variable: " <> name check env (() :< Assign variable value continuation) | Just variableSC <- Map.lookup variable env = do value' <- check env value let valueSC = extract value' unless (valueSC `Set.isSubsetOf` variableSC) $ throwError $ "Confidentiality violation in Assign: " <> tshow (variable, valueSC, variableSC) continuation' <- check env continuation let sc = variableSC `Set.union` extract continuation' pure $ sc :< Assign variable value' continuation' | otherwise = throwError $ "No such variable: " <> variable check env (() :< If condition consequent alternative) = do condition' <- check env condition consequent' <- check env consequent alternative' <- check env alternative let conditionSC = extract condition' let consequentSC = extract consequent' let alternativeSC = extract alternative' unless (conditionSC `Set.isSubsetOf` consequentSC && conditionSC `Set.isSubsetOf` alternativeSC) $ throwError $ "Confidentiality violation in If: " <> tshow (conditionSC, consequentSC, alternativeSC) let sc = consequentSC `Set.intersection` alternativeSC pure $ sc :< If condition' consequent' alternative' prettyTerm :: (a -> Text) -> Cofree Term a -> Text prettyTerm prettyAnn (ann :< Variable name) = name <> "<" <> prettyAnn ann <> ">" prettyTerm prettyAnn (ann :< Assign variable value continuation) = "assign<" <> prettyAnn ann <> "> " <> variable <> " := " <> prettyTerm prettyAnn value <> ";\n" <> prettyTerm prettyAnn continuation prettyTerm prettyAnn (ann :< If condition consequent alternative) = "if<" <> prettyAnn ann <> "> " <> prettyTerm prettyAnn condition <> " then\n" <> indent (prettyTerm prettyAnn consequent) <> "\nelse\n" <> indent (prettyTerm prettyAnn alternative) <> "\nend" prettySecurityClass :: SecurityClass -> Text prettySecurityClass = Text.intercalate ", " . Set.toList indent :: Text -> Text indent = Text.intercalate "\n" . fmap (" " <>) . Text.splitOn "\n" tshow :: Show a => a -> Text tshow = Text.pack . show main :: IO () main = do example $ variable "a" example $ variable "b" example $ variable "c" example $ if_ (variable "a") (variable "b") (variable "c") example $ if_ (variable "a") (variable "c") (variable "d") example $ if_ (variable "b") (variable "c") (variable "d") where variable name = () :< Variable name assign name value continuation = () :< Assign name value continuation if_ condition consequent alternative = () :< If condition consequent alternative example :: Cofree Term () -> IO () example term = do Text.IO.putStrLn $ prettyTerm (const "") term Text.IO.putStrLn $ "" Text.IO.putStrLn . either id (prettyTerm prettySecurityClass) $ check environment term Text.IO.putStrLn $ "---------------" environment :: Environment environment = Map.fromList [ ("a", Set.fromList []) , ("b", Set.fromList ["α"]) , ("c", Set.fromList ["β", "γ"]) , ("d", Set.fromList ["γ"]) ]
Editor Settings
Theme
Key bindings
Full width
Lines