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]