module Data.X509.Validation.Cache
(
ValidationCacheResult(..)
, ValidationCacheQueryCallback
, ValidationCacheAddCallback
, ValidationCache(..)
, exceptionValidationCache
, tofuValidationCache
) where
import Control.Concurrent
import Data.Default.Class
import Data.X509
import Data.X509.Validation.Types
import Data.X509.Validation.Fingerprint
data ValidationCacheResult =
ValidationCachePass
| ValidationCacheDenied String
| ValidationCacheUnknown
deriving (Show,Eq)
type ValidationCacheQueryCallback = ServiceID
-> Fingerprint
-> Certificate
-> IO ValidationCacheResult
type ValidationCacheAddCallback = ServiceID
-> Fingerprint
-> Certificate
-> IO ()
data ValidationCache = ValidationCache
{ cacheQuery :: ValidationCacheQueryCallback
, cacheAdd :: ValidationCacheAddCallback
}
instance Default ValidationCache where
def = exceptionValidationCache []
exceptionValidationCache :: [(ServiceID, Fingerprint)] -> ValidationCache
exceptionValidationCache fingerprints =
ValidationCache (queryListCallback fingerprints)
(\_ _ _ -> return ())
tofuValidationCache :: [(ServiceID, Fingerprint)]
-> IO ValidationCache
tofuValidationCache fingerprints = do
l <- newMVar fingerprints
return $ ValidationCache (\s f c -> readMVar l >>= \list -> (queryListCallback list) s f c)
(\s f _ -> modifyMVar_ l (\list -> return ((s,f) : list)))
queryListCallback :: [(ServiceID, Fingerprint)] -> ValidationCacheQueryCallback
queryListCallback list = query
where query serviceID fingerprint _ = return $
case lookup serviceID list of
Nothing -> ValidationCacheUnknown
Just f | fingerprint == f -> ValidationCachePass
| otherwise -> ValidationCacheDenied (show serviceID ++ " expected " ++ show f ++ " but got: " ++ show fingerprint)