module System.Certificate.X509.Unix
( getSystemPath
, readAll
, findCertificate
) where
import System.Directory (getDirectoryContents)
import System.Environment (getEnv)
import Data.List (isPrefixOf, find)
import Data.PEM (PEM(..), pemParseBS)
import Data.Either
import Data.Certificate.X509
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as L
import Control.Applicative ((<$>))
import Control.Exception
#if !MIN_VERSION_base(4,6,0)
import Prelude hiding (catch)
#endif
defaultSystemPath :: FilePath
defaultSystemPath = "/etc/ssl/certs/"
envPathOverride :: String
envPathOverride = "SYSTEM_CERTIFICATE_PATH"
listSystemCertificates :: IO [FilePath]
listSystemCertificates = do
path <- getSystemPath
map (path ++) . filter (not . isPrefixOf ".") <$> getDirectoryContents path
getSystemPath :: IO FilePath
getSystemPath = catch (getEnv envPathOverride) inDefault
where
inDefault :: IOException -> IO FilePath
inDefault _ = return defaultSystemPath
readCertificates :: FilePath -> IO [X509]
readCertificates file = either (const []) (rights . map getCert) . pemParseBS <$> B.readFile file
where getCert pem = decodeCertificate $ L.fromChunks [pemContent pem]
readAll :: IO [X509]
readAll = do
certfiles <- listSystemCertificates
concat . rights <$> mapM (trySE . readCertificates) certfiles
findCertificate :: (X509 -> Bool) -> IO (Maybe X509)
findCertificate f = find f <$> readAll
trySE :: IO a -> IO (Either SomeException a)
trySE = try