packages feed

rpf-0.2.0: RPF/Eval.hs

module RPF.Eval (evalRPF) where

import Control.Monad
import Data.List (foldl')
import Data.Maybe
import MailSpec
import RPF.Domain
import RPF.IP
import RPF.Types

----------------------------------------------------------------

evalRPF :: MailSpec -> Policy -> BlockName -> (Pline, Action)
evalRPF ms (Policy bs is ds) bn = evalBlock ms is ds (bs !! fromEnum bn)

----------------------------------------------------------------

evalBlock :: MailSpec -> [IPTable] -> [DomainTable] -> Block -> (Pline, Action)
evalBlock ms is ds (Block _ as) =
    fromJust $ foldl' mplus mzero (map (evalAction ms is ds) as)

----------------------------------------------------------------

evalAction :: MailSpec -> [IPTable] -> [DomainTable] -> ActionCond -> Maybe (Pline, Action)
evalAction _ _ _ (ActionCond l Nothing act) = Just (l, act)
evalAction ms is ds (ActionCond l (Just cnd) act) =
    if evalCnd ms is ds cnd
    then Just (l, act)
    else Nothing

----------------------------------------------------------------

evalCnd :: MailSpec -> [IPTable] -> [DomainTable] -> Cond -> Bool
evalCnd ms is ds (v :== d) = include ms is ds v d
evalCnd ms is ds (v :!= d) = exclude ms is ds v d
evalCnd ms is ds (c1 :&& c2) = evalCnd ms is ds c1 && evalCnd ms is ds c2

----------------------------------------------------------------

include :: MailSpec -> [IPTable] -> [DomainTable] -> Variable -> Constant -> Bool
include ms is _ (DT_IP,  _) (_, CV_Index n) = ipMatch (msPeerIP ms) (is!!n)
include ms _ ds (DT_Dom, vid) (_, CV_Index n) =
    case getDom vid of
      Nothing -> False
      Just dom -> domainMatch dom (ds!!n)
  where
    getDom V_PRA      = msPRA ms
    getDom V_MAILFROM = msMailFrom ms
    getDom V_FROM     = msFrom ms
    getDom V_DKIMFROM = msDKIMFrom ms
    getDom V_DKFROM   = msDKFrom ms
    getDom _          = error "getDom"
include ms _ _ (DT_Res, vid) (_, CV_Result rs) = getRes vid `elem` rs
  where
    getRes V_SPF  = msSPFResult ms
    getRes V_SID  = msSenderIDResult ms
    getRes V_ADSP = msADSPResult ms
    getRes V_DKIM = msDKIMResult ms
    getRes V_DK   = msDKResult ms
    getRes _      = error "getRes"
include ms _ _ (DT_Sig, vid) (_, CV_Sig b) = getSig vid == b
  where
    getSig V_SIGDKIM = msSigDKIM ms
    getSig V_SIGDK   = msSigDK ms
    getSig _         = error "getSig"
include _ _ _ _ _ = error "include"

----------------------------------------------------------------

exclude :: MailSpec -> [IPTable] -> [DomainTable] -> Variable -> Constant -> Bool
exclude a b c d e = not (include a b c d e)