{-# LINE 1 "OpenSSL/X509/Revocation.hsc" #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE ForeignFunctionInterface #-}
{-# OPTIONS_HADDOCK prune #-}
module OpenSSL.X509.Revocation
(
CRL
, X509_CRL
, RevokedCertificate(..)
, newCRL
, wrapCRL
, withCRLPtr
, signCRL
, verifyCRL
, printCRL
, sortCRL
, getVersion
, setVersion
, getLastUpdate
, setLastUpdate
, getNextUpdate
, setNextUpdate
, getIssuerName
, setIssuerName
, getRevokedList
, addRevoked
, getRevoked
)
where
import Control.Monad
{-# LINE 47 "OpenSSL/X509/Revocation.hsc" #-}
import Data.Time.Clock
import Data.Typeable
import Foreign
import Foreign.C
import OpenSSL.ASN1
import OpenSSL.BIO
import OpenSSL.EVP.Digest hiding (digest)
import OpenSSL.EVP.PKey
import OpenSSL.EVP.Verify
import OpenSSL.EVP.Internal
import OpenSSL.Stack
import OpenSSL.Utils
import OpenSSL.X509.Name
newtype CRL = CRL (ForeignPtr X509_CRL)
data X509_CRL
data X509_REVOKED
data RevokedCertificate
= RevokedCertificate {
revSerialNumber :: Integer
, revRevocationDate :: UTCTime
}
deriving (Show, Eq, Typeable)
foreign import ccall unsafe "X509_CRL_new"
_new :: IO (Ptr X509_CRL)
foreign import ccall unsafe "&X509_CRL_free"
_free :: FunPtr (Ptr X509_CRL -> IO ())
foreign import ccall unsafe "X509_CRL_sign"
_sign :: Ptr X509_CRL -> Ptr EVP_PKEY -> Ptr EVP_MD -> IO CInt
foreign import ccall unsafe "X509_CRL_verify"
_verify :: Ptr X509_CRL -> Ptr EVP_PKEY -> IO CInt
foreign import ccall unsafe "X509_CRL_print"
_print :: Ptr BIO_ -> Ptr X509_CRL -> IO CInt
foreign import ccall unsafe "HsOpenSSL_X509_CRL_get_version"
_get_version :: Ptr X509_CRL -> IO CLong
foreign import ccall unsafe "X509_CRL_set_version"
_set_version :: Ptr X509_CRL -> CLong -> IO CInt
foreign import ccall unsafe "HsOpenSSL_X509_CRL_get_lastUpdate"
_get_lastUpdate :: Ptr X509_CRL -> IO (Ptr ASN1_TIME)
foreign import ccall unsafe "HsOpenSSL_X509_CRL_get_nextUpdate"
_get_nextUpdate :: Ptr X509_CRL -> IO (Ptr ASN1_TIME)
{-# LINE 113 "OpenSSL/X509/Revocation.hsc" #-}
foreign import ccall unsafe "X509_CRL_set_lastUpdate"
_set_lastUpdate :: Ptr X509_CRL -> Ptr ASN1_TIME -> IO CInt
foreign import ccall unsafe "X509_CRL_set_nextUpdate"
_set_nextUpdate :: Ptr X509_CRL -> Ptr ASN1_TIME -> IO CInt
{-# LINE 119 "OpenSSL/X509/Revocation.hsc" #-}
foreign import ccall unsafe "HsOpenSSL_X509_CRL_get_issuer"
_get_issuer_name :: Ptr X509_CRL -> IO (Ptr X509_NAME)
foreign import ccall unsafe "X509_CRL_set_issuer_name"
_set_issuer_name :: Ptr X509_CRL -> Ptr X509_NAME -> IO CInt
foreign import ccall unsafe "HsOpenSSL_X509_CRL_get_REVOKED"
_get_REVOKED :: Ptr X509_CRL -> IO (Ptr STACK)
foreign import ccall unsafe "X509_CRL_add0_revoked"
_add0_revoked :: Ptr X509_CRL -> Ptr X509_REVOKED -> IO CInt
{-# LINE 133 "OpenSSL/X509/Revocation.hsc" #-}
foreign import ccall unsafe "X509_CRL_get0_by_serial"
_get0_by_serial :: Ptr X509_CRL -> Ptr (Ptr X509_REVOKED)
-> Ptr ASN1_INTEGER -> IO CInt
{-# LINE 138 "OpenSSL/X509/Revocation.hsc" #-}
foreign import ccall unsafe "X509_CRL_sort"
_sort :: Ptr X509_CRL -> IO CInt
foreign import ccall unsafe "X509_REVOKED_new"
_new_revoked :: IO (Ptr X509_REVOKED)
foreign import ccall unsafe "X509_REVOKED_free"
freeRevoked :: Ptr X509_REVOKED -> IO ()
foreign import ccall unsafe "X509_REVOKED_set_serialNumber"
_set_serialNumber :: Ptr X509_REVOKED -> Ptr ASN1_INTEGER -> IO CInt
foreign import ccall unsafe "X509_REVOKED_set_revocationDate"
_set_revocationDate :: Ptr X509_REVOKED -> Ptr ASN1_TIME -> IO CInt
newCRL :: IO CRL
newCRL = _new >>= wrapCRL
wrapCRL :: Ptr X509_CRL -> IO CRL
wrapCRL = fmap CRL . newForeignPtr _free
withCRLPtr :: CRL -> (Ptr X509_CRL -> IO a) -> IO a
withCRLPtr (CRL crl) = withForeignPtr crl
signCRL :: KeyPair key =>
CRL
-> key
-> Maybe Digest
-> IO ()
signCRL crl key mDigest
= withCRLPtr crl $ \ crlPtr ->
withPKeyPtr' key $ \ pkeyPtr ->
do digest <- case mDigest of
Just md -> return md
Nothing -> pkeyDefaultMD key
withMDPtr digest $ \ digestPtr ->
_sign crlPtr pkeyPtr digestPtr
>>= failIf_ (== 0)
return ()
verifyCRL :: PublicKey key => CRL -> key -> IO VerifyStatus
verifyCRL crl key
= withCRLPtr crl $ \ crlPtr ->
withPKeyPtr' key $ \ pkeyPtr ->
_verify crlPtr pkeyPtr
>>= interpret
where
interpret :: CInt -> IO VerifyStatus
interpret 1 = return VerifySuccess
interpret 0 = return VerifyFailure
interpret _ = raiseOpenSSLError
printCRL :: CRL -> IO String
printCRL crl
= do mem <- newMem
withBioPtr mem $ \ memPtr ->
withCRLPtr crl $ \ crlPtr ->
_print memPtr crlPtr
>>= failIf_ (/= 1)
bioRead mem
getVersion :: CRL -> IO Int
getVersion crl
= withCRLPtr crl $ \ crlPtr ->
liftM fromIntegral $ _get_version crlPtr
setVersion :: CRL -> Int -> IO ()
setVersion crl ver
= withCRLPtr crl $ \ crlPtr ->
_set_version crlPtr (fromIntegral ver)
>>= failIf (/= 1)
>> return ()
getLastUpdate :: CRL -> IO UTCTime
getLastUpdate crl
= withCRLPtr crl $ \ crlPtr ->
_get_lastUpdate crlPtr
>>= peekASN1Time
setLastUpdate :: CRL -> UTCTime -> IO ()
setLastUpdate crl utc
= withCRLPtr crl $ \ crlPtr ->
withASN1Time utc $ \ time ->
_set_lastUpdate crlPtr time
>>= failIf (/= 1)
>> return ()
getNextUpdate :: CRL -> IO UTCTime
getNextUpdate crl
= withCRLPtr crl $ \ crlPtr ->
_get_nextUpdate crlPtr
>>= peekASN1Time
setNextUpdate :: CRL -> UTCTime -> IO ()
setNextUpdate crl utc
= withCRLPtr crl $ \ crlPtr ->
withASN1Time utc $ \ time ->
_set_nextUpdate crlPtr time
>>= failIf (/= 1)
>> return ()
getIssuerName :: CRL -> Bool -> IO [(String, String)]
getIssuerName crl wantLongName
= withCRLPtr crl $ \ crlPtr ->
do namePtr <- _get_issuer_name crlPtr
peekX509Name namePtr wantLongName
setIssuerName :: CRL -> [(String, String)] -> IO ()
setIssuerName crl issuer
= withCRLPtr crl $ \ crlPtr ->
withX509Name issuer $ \ namePtr ->
_set_issuer_name crlPtr namePtr
>>= failIf (/= 1)
>> return ()
getRevokedList :: CRL -> IO [RevokedCertificate]
getRevokedList crl
= withCRLPtr crl $ \ crlPtr ->
_get_REVOKED crlPtr >>= mapStack peekRevoked
getSerialNumber :: Ptr X509_REVOKED -> IO (Ptr ASN1_INTEGER)
getRevocationDate :: Ptr X509_REVOKED -> IO (Ptr ASN1_TIME)
{-# LINE 315 "OpenSSL/X509/Revocation.hsc" #-}
getSerialNumber = ((\hsc_ptr -> peekByteOff hsc_ptr 0))
{-# LINE 317 "OpenSSL/X509/Revocation.hsc" #-}
getRevocationDate = ((\hsc_ptr -> peekByteOff hsc_ptr 8))
{-# LINE 318 "OpenSSL/X509/Revocation.hsc" #-}
{-# LINE 320 "OpenSSL/X509/Revocation.hsc" #-}
peekRevoked :: Ptr X509_REVOKED -> IO RevokedCertificate
peekRevoked rev = do
serial <- peekASN1Integer =<< getSerialNumber rev
date <- peekASN1Time =<< getRevocationDate rev
return RevokedCertificate { revSerialNumber = serial
, revRevocationDate = date
}
newRevoked :: RevokedCertificate -> IO (Ptr X509_REVOKED)
newRevoked revoked
= do revPtr <- _new_revoked
seriRet <- withASN1Integer (revSerialNumber revoked) $
_set_serialNumber revPtr
dateRet <- withASN1Time (revRevocationDate revoked) $
_set_revocationDate revPtr
if seriRet /= 1 || dateRet /= 1 then
freeRevoked revPtr >> raiseOpenSSLError
else
return revPtr
addRevoked :: CRL -> RevokedCertificate -> IO ()
addRevoked crl revoked
= withCRLPtr crl $ \ crlPtr ->
do revPtr <- newRevoked revoked
ret <- _add0_revoked crlPtr revPtr
case ret of
1 -> return ()
_ -> freeRevoked revPtr >> raiseOpenSSLError
getRevoked :: CRL -> Integer -> IO (Maybe RevokedCertificate)
{-# LINE 358 "OpenSSL/X509/Revocation.hsc" #-}
getRevoked crl serial =
withCRLPtr crl $ \crlPtr ->
alloca $ \revPtr ->
withASN1Integer serial $ \serialPtr -> do
r <- _get0_by_serial crlPtr revPtr serialPtr
if r == 1
then fmap Just $ peek revPtr >>= peekRevoked
else return Nothing
{-# LINE 372 "OpenSSL/X509/Revocation.hsc" #-}
sortCRL :: CRL -> IO ()
sortCRL crl
= withCRLPtr crl $ \ crlPtr ->
_sort crlPtr >>= failIf_ (/= 1)