{-# LANGUAGE CPP #-} -- | -- Module : System.Certificate.X509 -- License : BSD-style -- Maintainer : Vincent Hanquez -- Stability : experimental -- Portability : unix only -- -- this module is portable to unix system where there is usually -- a /etc/ssl/certs with system X509 certificates. -- -- the path can be dynamically override using the environment variable -- defined by envPathOverride in the module, which by -- default is SYSTEM_CERTIFICATE_PATH -- 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