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 (Int -> ValidationCacheResult -> ShowS
[ValidationCacheResult] -> ShowS
ValidationCacheResult -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ValidationCacheResult] -> ShowS
$cshowList :: [ValidationCacheResult] -> ShowS
show :: ValidationCacheResult -> String
$cshow :: ValidationCacheResult -> String
showsPrec :: Int -> ValidationCacheResult -> ShowS
$cshowsPrec :: Int -> ValidationCacheResult -> ShowS
Show,ValidationCacheResult -> ValidationCacheResult -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ValidationCacheResult -> ValidationCacheResult -> Bool
$c/= :: ValidationCacheResult -> ValidationCacheResult -> Bool
== :: ValidationCacheResult -> ValidationCacheResult -> Bool
$c== :: ValidationCacheResult -> ValidationCacheResult -> Bool
Eq)
type ValidationCacheQueryCallback = ServiceID
-> Fingerprint
-> Certificate
-> IO ValidationCacheResult
type ValidationCacheAddCallback = ServiceID
-> Fingerprint
-> Certificate
-> IO ()
data ValidationCache = ValidationCache
{ ValidationCache -> ValidationCacheQueryCallback
cacheQuery :: ValidationCacheQueryCallback
, ValidationCache -> ValidationCacheAddCallback
cacheAdd :: ValidationCacheAddCallback
}
instance Default ValidationCache where
def :: ValidationCache
def = [(ServiceID, Fingerprint)] -> ValidationCache
exceptionValidationCache []
exceptionValidationCache :: [(ServiceID, Fingerprint)] -> ValidationCache
exceptionValidationCache :: [(ServiceID, Fingerprint)] -> ValidationCache
exceptionValidationCache [(ServiceID, Fingerprint)]
fingerprints =
ValidationCacheQueryCallback
-> ValidationCacheAddCallback -> ValidationCache
ValidationCache ([(ServiceID, Fingerprint)] -> ValidationCacheQueryCallback
queryListCallback [(ServiceID, Fingerprint)]
fingerprints)
(\ServiceID
_ Fingerprint
_ Certificate
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return ())
tofuValidationCache :: [(ServiceID, Fingerprint)]
-> IO ValidationCache
tofuValidationCache :: [(ServiceID, Fingerprint)] -> IO ValidationCache
tofuValidationCache [(ServiceID, Fingerprint)]
fingerprints = do
MVar [(ServiceID, Fingerprint)]
l <- forall a. a -> IO (MVar a)
newMVar [(ServiceID, Fingerprint)]
fingerprints
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ ValidationCacheQueryCallback
-> ValidationCacheAddCallback -> ValidationCache
ValidationCache (\ServiceID
s Fingerprint
f Certificate
c -> forall a. MVar a -> IO a
readMVar MVar [(ServiceID, Fingerprint)]
l forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \[(ServiceID, Fingerprint)]
list -> ([(ServiceID, Fingerprint)] -> ValidationCacheQueryCallback
queryListCallback [(ServiceID, Fingerprint)]
list) ServiceID
s Fingerprint
f Certificate
c)
(\ServiceID
s Fingerprint
f Certificate
_ -> forall a. MVar a -> (a -> IO a) -> IO ()
modifyMVar_ MVar [(ServiceID, Fingerprint)]
l (\[(ServiceID, Fingerprint)]
list -> forall (m :: * -> *) a. Monad m => a -> m a
return ((ServiceID
s,Fingerprint
f) forall a. a -> [a] -> [a]
: [(ServiceID, Fingerprint)]
list)))
queryListCallback :: [(ServiceID, Fingerprint)] -> ValidationCacheQueryCallback
queryListCallback :: [(ServiceID, Fingerprint)] -> ValidationCacheQueryCallback
queryListCallback [(ServiceID, Fingerprint)]
list = forall {m :: * -> *} {p}.
Monad m =>
ServiceID -> Fingerprint -> p -> m ValidationCacheResult
query
where query :: ServiceID -> Fingerprint -> p -> m ValidationCacheResult
query ServiceID
serviceID Fingerprint
fingerprint p
_ = forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$
case forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup ServiceID
serviceID [(ServiceID, Fingerprint)]
list of
Maybe Fingerprint
Nothing -> ValidationCacheResult
ValidationCacheUnknown
Just Fingerprint
f | Fingerprint
fingerprint forall a. Eq a => a -> a -> Bool
== Fingerprint
f -> ValidationCacheResult
ValidationCachePass
| Bool
otherwise -> String -> ValidationCacheResult
ValidationCacheDenied (forall a. Show a => a -> String
show ServiceID
serviceID forall a. [a] -> [a] -> [a]
++ String
" expected " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Fingerprint
f forall a. [a] -> [a] -> [a]
++ String
" but got: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Fingerprint
fingerprint)