module System.X509.MacOS ( getSystemCertificateStore ) where import Data.PEM (pemParseLBS, PEM(..)) import System.Process import qualified Data.ByteString.Lazy as LBS import Control.Applicative import Data.Either import Data.X509 import Data.X509.CertificateStore rootCAKeyChain :: FilePath rootCAKeyChain :: FilePath rootCAKeyChain = FilePath "/System/Library/Keychains/SystemRootCertificates.keychain" systemKeyChain :: FilePath systemKeyChain :: FilePath systemKeyChain = FilePath "/Library/Keychains/System.keychain" listInKeyChains :: [FilePath] -> IO [SignedCertificate] listInKeyChains :: [FilePath] -> IO [SignedCertificate] listInKeyChains [FilePath] keyChains = do (Maybe Handle _, Just Handle hout, Maybe Handle _, ProcessHandle ph) <- CreateProcess -> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle) createProcess (FilePath -> [FilePath] -> CreateProcess proc FilePath "security" (FilePath "find-certificate" forall a. a -> [a] -> [a] : FilePath "-pa" forall a. a -> [a] -> [a] : [FilePath] keyChains)) { std_out :: StdStream std_out = StdStream CreatePipe } [PEM] pems <- forall a c b. (a -> c) -> (b -> c) -> Either a b -> c either forall a. HasCallStack => FilePath -> a error forall a. a -> a id forall b c a. (b -> c) -> (a -> b) -> a -> c . ByteString -> Either FilePath [PEM] pemParseLBS forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> Handle -> IO ByteString LBS.hGetContents Handle hout let targets :: [SignedCertificate] targets = forall a b. [Either a b] -> [b] rights forall a b. (a -> b) -> a -> b $ forall a b. (a -> b) -> [a] -> [b] map (ByteString -> Either FilePath SignedCertificate decodeSignedCertificate forall b c a. (b -> c) -> (a -> b) -> a -> c . PEM -> ByteString pemContent) forall a b. (a -> b) -> a -> b $ forall a. (a -> Bool) -> [a] -> [a] filter ((forall a. Eq a => a -> a -> Bool ==FilePath "CERTIFICATE") forall b c a. (b -> c) -> (a -> b) -> a -> c . PEM -> FilePath pemName) [PEM] pems ExitCode _ <- [SignedCertificate] targets seq :: forall a b. a -> b -> b `seq` ProcessHandle -> IO ExitCode waitForProcess ProcessHandle ph forall (m :: * -> *) a. Monad m => a -> m a return [SignedCertificate] targets getSystemCertificateStore :: IO CertificateStore getSystemCertificateStore :: IO CertificateStore getSystemCertificateStore = [SignedCertificate] -> CertificateStore makeCertificateStore forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> [FilePath] -> IO [SignedCertificate] listInKeyChains [FilePath rootCAKeyChain, FilePath systemKeyChain]