{-# LINE 1 "OpenSSL/X509.hsc" #-}
{-# LANGUAGE EmptyDataDecls           #-}
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE CApiFFI                  #-}
{-# OPTIONS_HADDOCK prune             #-}
-- |An interface to X.509 certificate.
module OpenSSL.X509
    ( -- * Type
      X509
    , X509_

      -- * Functions to manipulate certificate
    , newX509
    , wrapX509 -- private
    , withX509Ptr -- private
    , withX509Stack -- private
    , unsafeX509ToPtr -- private
    , touchX509 -- private

    , writeDerX509
    , readDerX509
    , compareX509

    , signX509
    , verifyX509

    , printX509

      -- * Accessors
    , getVersion
    , setVersion

    , getSerialNumber
    , setSerialNumber

    , getIssuerName
    , setIssuerName

    , getSubjectName
    , setSubjectName

    , getNotBefore
    , setNotBefore

    , getNotAfter
    , setNotAfter

    , getPublicKey
    , setPublicKey

    , getSubjectEmail
    )
    where

import Control.Monad
import Data.Time.Clock
import Data.Maybe
import Foreign.ForeignPtr

{-# LINE 59 "OpenSSL/X509.hsc" #-}
import Foreign.ForeignPtr.Unsafe as Unsafe

{-# LINE 63 "OpenSSL/X509.hsc" #-}
import Foreign.Ptr
import Foreign.C
import OpenSSL.ASN1
import OpenSSL.BIO
import OpenSSL.EVP.Digest
import OpenSSL.EVP.PKey
import OpenSSL.EVP.Verify
import OpenSSL.EVP.Internal
import OpenSSL.Utils
import OpenSSL.Stack
import OpenSSL.X509.Name
import Data.ByteString.Lazy (ByteString)

-- |@'X509'@ is an opaque object that represents X.509 certificate.
newtype X509  = X509 (ForeignPtr X509_)
data {-# CTYPE "openssl/x509.h" "X509" #-} X509_


foreign import capi unsafe "openssl/x509.h X509_new"
        _new :: IO (Ptr X509_)

foreign import capi unsafe "openssl/x509.h &X509_free"
        _free :: FunPtr (Ptr X509_ -> IO ())

foreign import capi unsafe "openssl/x509.h X509_print"
        _print :: Ptr BIO_ -> Ptr X509_ -> IO CInt

foreign import capi unsafe "openssl/x509.h X509_cmp"
        _cmp :: Ptr X509_ -> Ptr X509_ -> IO CInt

foreign import capi unsafe "HsOpenSSL.h HsOpenSSL_X509_get_version"
        _get_version :: Ptr X509_ -> IO CLong

foreign import capi unsafe "openssl/x509.h X509_set_version"
        _set_version :: Ptr X509_ -> CLong -> IO CInt

foreign import capi unsafe "openssl/x509.h X509_get_serialNumber"
        _get_serialNumber :: Ptr X509_ -> IO (Ptr ASN1_INTEGER)

foreign import capi unsafe "openssl/x509.h X509_set_serialNumber"
        _set_serialNumber :: Ptr X509_ -> Ptr ASN1_INTEGER -> IO CInt

foreign import capi unsafe "openssl/x509.h X509_get_issuer_name"
        _get_issuer_name :: Ptr X509_ -> IO (Ptr X509_NAME)

foreign import capi unsafe "openssl/x509.h X509_set_issuer_name"
        _set_issuer_name :: Ptr X509_ -> Ptr X509_NAME -> IO CInt

foreign import capi unsafe "openssl/x509.h X509_get_subject_name"
        _get_subject_name :: Ptr X509_ -> IO (Ptr X509_NAME)

foreign import capi unsafe "openssl/x509.h X509_set_subject_name"
        _set_subject_name :: Ptr X509_ -> Ptr X509_NAME -> IO CInt

foreign import capi unsafe "HsOpenSSL.h HsOpenSSL_X509_get_notBefore"
        _get_notBefore :: Ptr X509_ -> IO (Ptr ASN1_TIME)

foreign import capi unsafe "HsOpenSSL.h HsOpenSSL_X509_get_notAfter"
        _get_notAfter :: Ptr X509_ -> IO (Ptr ASN1_TIME)


{-# LINE 124 "OpenSSL/X509.hsc" #-}
foreign import capi unsafe "openssl/x509.h X509_set1_notBefore"
        _set_notBefore :: Ptr X509_ -> Ptr ASN1_TIME -> IO CInt

foreign import capi unsafe "openssl/x509.h X509_set1_notAfter"
        _set_notAfter :: Ptr X509_ -> Ptr ASN1_TIME -> IO CInt

{-# LINE 136 "OpenSSL/X509.hsc" #-}

foreign import capi unsafe "openssl/x509.h X509_get_pubkey"
        _get_pubkey :: Ptr X509_ -> IO (Ptr EVP_PKEY)

foreign import capi unsafe "openssl/x509.h X509_set_pubkey"
        _set_pubkey :: Ptr X509_ -> Ptr EVP_PKEY -> IO CInt

foreign import capi unsafe "openssl/x509v3.h X509_get1_email"
        _get1_email :: Ptr X509_ -> IO (Ptr STACK)

foreign import capi unsafe "openssl/x509v3.h X509_email_free"
        _email_free :: Ptr STACK -> IO ()

foreign import capi unsafe "openssl/x509.h X509_sign"
        _sign :: Ptr X509_ -> Ptr EVP_PKEY -> Ptr EVP_MD -> IO CInt

foreign import capi unsafe "openssl/x509.h X509_verify"
        _verify :: Ptr X509_ -> Ptr EVP_PKEY -> IO CInt

foreign import capi safe "openssl/x509.h i2d_X509_bio"
        _write_bio_X509 :: Ptr BIO_
                        -> Ptr X509_
                        -> IO CInt

foreign import capi safe "openssl/x509.h d2i_X509_bio"
        _read_bio_X509 :: Ptr BIO_
                       -> Ptr (Ptr X509_)
                       -> IO (Ptr X509_)

-- |@'newX509'@ creates an empty certificate. You must set the
-- following properties to and sign it (see 'signX509') to actually
-- use the certificate.
--
--   [/Version/] See 'setVersion'.
--
--   [/Serial number/] See 'setSerialNumber'.
--
--   [/Issuer name/] See 'setIssuerName'.
--
--   [/Subject name/] See 'setSubjectName'.
--
--   [/Validity/] See 'setNotBefore' and 'setNotAfter'.
--
--   [/Public Key/] See 'setPublicKey'.
--
newX509 :: IO X509
newX509 :: IO X509
newX509 = IO (Ptr X509_)
_new IO (Ptr X509_) -> (Ptr X509_ -> IO (Ptr X509_)) -> IO (Ptr X509_)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Ptr X509_ -> IO (Ptr X509_)
forall a. Ptr a -> IO (Ptr a)
failIfNull IO (Ptr X509_) -> (Ptr X509_ -> IO X509) -> IO X509
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Ptr X509_ -> IO X509
wrapX509


wrapX509 :: Ptr X509_ -> IO X509
wrapX509 :: Ptr X509_ -> IO X509
wrapX509 = (ForeignPtr X509_ -> X509) -> IO (ForeignPtr X509_) -> IO X509
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ForeignPtr X509_ -> X509
X509 (IO (ForeignPtr X509_) -> IO X509)
-> (Ptr X509_ -> IO (ForeignPtr X509_)) -> Ptr X509_ -> IO X509
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FinalizerPtr X509_ -> Ptr X509_ -> IO (ForeignPtr X509_)
forall a. FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
newForeignPtr FinalizerPtr X509_
_free


withX509Ptr :: X509 -> (Ptr X509_ -> IO a) -> IO a
withX509Ptr :: forall a. X509 -> (Ptr X509_ -> IO a) -> IO a
withX509Ptr (X509 ForeignPtr X509_
x509) = ForeignPtr X509_ -> (Ptr X509_ -> IO a) -> IO a
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr X509_
x509


withX509Stack :: [X509] -> (Ptr STACK -> IO a) -> IO a
withX509Stack :: forall a. [X509] -> (Ptr STACK -> IO a) -> IO a
withX509Stack = (X509 -> Ptr X509_)
-> (X509 -> IO ()) -> [X509] -> (Ptr STACK -> IO a) -> IO a
forall fp obj ret.
(fp -> Ptr obj)
-> (fp -> IO ()) -> [fp] -> (Ptr STACK -> IO ret) -> IO ret
withForeignStack X509 -> Ptr X509_
unsafeX509ToPtr X509 -> IO ()
touchX509


unsafeX509ToPtr :: X509 -> Ptr X509_
unsafeX509ToPtr :: X509 -> Ptr X509_
unsafeX509ToPtr (X509 ForeignPtr X509_
x509) = ForeignPtr X509_ -> Ptr X509_
forall a. ForeignPtr a -> Ptr a
Unsafe.unsafeForeignPtrToPtr ForeignPtr X509_
x509


touchX509 :: X509 -> IO ()
touchX509 :: X509 -> IO ()
touchX509 (X509 ForeignPtr X509_
x509) = ForeignPtr X509_ -> IO ()
forall a. ForeignPtr a -> IO ()
touchForeignPtr ForeignPtr X509_
x509

writeX509' :: BIO -> X509 -> IO ()
writeX509' :: BIO -> X509 -> IO ()
writeX509' BIO
bio X509
x509
    = BIO -> (Ptr BIO_ -> IO ()) -> IO ()
forall a. BIO -> (Ptr BIO_ -> IO a) -> IO a
withBioPtr BIO
bio   ((Ptr BIO_ -> IO ()) -> IO ()) -> (Ptr BIO_ -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ Ptr BIO_
bioPtr ->
      X509 -> (Ptr X509_ -> IO ()) -> IO ()
forall a. X509 -> (Ptr X509_ -> IO a) -> IO a
withX509Ptr X509
x509 ((Ptr X509_ -> IO ()) -> IO ()) -> (Ptr X509_ -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ Ptr X509_
x509Ptr ->
      Ptr BIO_ -> Ptr X509_ -> IO CInt
_write_bio_X509 Ptr BIO_
bioPtr Ptr X509_
x509Ptr
           IO CInt -> (CInt -> IO CInt) -> IO CInt
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (CInt -> Bool) -> CInt -> IO CInt
forall a. (a -> Bool) -> a -> IO a
failIf (CInt -> CInt -> Bool
forall a. Ord a => a -> a -> Bool
< CInt
0)
           IO CInt -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>  () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

-- |@'writeDerX509' cert@ writes an X.509 certificate to DER string.
writeDerX509 :: X509 -> IO ByteString
writeDerX509 :: X509 -> IO ByteString
writeDerX509 X509
x509
    = do BIO
mem <- IO BIO
newMem
         BIO -> X509 -> IO ()
writeX509' BIO
mem X509
x509
         BIO -> IO ByteString
bioReadLBS BIO
mem

readX509' :: BIO -> IO X509
readX509' :: BIO -> IO X509
readX509' BIO
bio
    = BIO -> (Ptr BIO_ -> IO X509) -> IO X509
forall a. BIO -> (Ptr BIO_ -> IO a) -> IO a
withBioPtr BIO
bio ((Ptr BIO_ -> IO X509) -> IO X509)
-> (Ptr BIO_ -> IO X509) -> IO X509
forall a b. (a -> b) -> a -> b
$ \ Ptr BIO_
bioPtr ->
      Ptr BIO_ -> Ptr (Ptr X509_) -> IO (Ptr X509_)
_read_bio_X509 Ptr BIO_
bioPtr Ptr (Ptr X509_)
forall a. Ptr a
nullPtr
           IO (Ptr X509_) -> (Ptr X509_ -> IO (Ptr X509_)) -> IO (Ptr X509_)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Ptr X509_ -> IO (Ptr X509_)
forall a. Ptr a -> IO (Ptr a)
failIfNull
           IO (Ptr X509_) -> (Ptr X509_ -> IO X509) -> IO X509
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Ptr X509_ -> IO X509
wrapX509

-- |@'readDerX509' der@ reads in a certificate.
readDerX509 :: ByteString -> IO X509
readDerX509 :: ByteString -> IO X509
readDerX509 ByteString
derStr
    = ByteString -> IO BIO
newConstMemLBS ByteString
derStr IO BIO -> (BIO -> IO X509) -> IO X509
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= BIO -> IO X509
readX509'

-- |@'compareX509' cert1 cert2@ compares two certificates.
compareX509 :: X509 -> X509 -> IO Ordering
compareX509 :: X509 -> X509 -> IO Ordering
compareX509 X509
cert1 X509
cert2
    = X509 -> (Ptr X509_ -> IO Ordering) -> IO Ordering
forall a. X509 -> (Ptr X509_ -> IO a) -> IO a
withX509Ptr X509
cert1 ((Ptr X509_ -> IO Ordering) -> IO Ordering)
-> (Ptr X509_ -> IO Ordering) -> IO Ordering
forall a b. (a -> b) -> a -> b
$ \ Ptr X509_
cert1Ptr ->
      X509 -> (Ptr X509_ -> IO Ordering) -> IO Ordering
forall a. X509 -> (Ptr X509_ -> IO a) -> IO a
withX509Ptr X509
cert2 ((Ptr X509_ -> IO Ordering) -> IO Ordering)
-> (Ptr X509_ -> IO Ordering) -> IO Ordering
forall a b. (a -> b) -> a -> b
$ \ Ptr X509_
cert2Ptr ->
      (CInt -> Ordering) -> IO CInt -> IO Ordering
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap CInt -> Ordering
interpret (Ptr X509_ -> Ptr X509_ -> IO CInt
_cmp Ptr X509_
cert1Ptr Ptr X509_
cert2Ptr)
    where
      interpret :: CInt -> Ordering
      interpret :: CInt -> Ordering
interpret CInt
n
          | CInt
n CInt -> CInt -> Bool
forall a. Ord a => a -> a -> Bool
> CInt
0     = Ordering
GT
          | CInt
n CInt -> CInt -> Bool
forall a. Ord a => a -> a -> Bool
< CInt
0     = Ordering
LT
          | Bool
otherwise = Ordering
EQ

-- |@'signX509'@ signs a certificate with an issuer private key.
signX509 :: KeyPair key =>
            X509         -- ^ The certificate to be signed.
         -> key          -- ^ The private key to sign with.
         -> Maybe Digest -- ^ A hashing algorithm to use. If @Nothing@
                         --   the most suitable algorithm for the key
                         --   is automatically used.
         -> IO ()
signX509 :: forall key. KeyPair key => X509 -> key -> Maybe Digest -> IO ()
signX509 X509
x509 key
key Maybe Digest
mDigest
    = X509 -> (Ptr X509_ -> IO ()) -> IO ()
forall a. X509 -> (Ptr X509_ -> IO a) -> IO a
withX509Ptr X509
x509 ((Ptr X509_ -> IO ()) -> IO ()) -> (Ptr X509_ -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ Ptr X509_
x509Ptr ->
      key -> (Ptr EVP_PKEY -> IO ()) -> IO ()
forall k a. PKey k => k -> (Ptr EVP_PKEY -> IO a) -> IO a
withPKeyPtr' key
key ((Ptr EVP_PKEY -> IO ()) -> IO ())
-> (Ptr EVP_PKEY -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ Ptr EVP_PKEY
pkeyPtr ->
      do Digest
dig <- case Maybe Digest
mDigest of
                  Just Digest
md -> Digest -> IO Digest
forall (m :: * -> *) a. Monad m => a -> m a
return Digest
md
                  Maybe Digest
Nothing -> key -> IO Digest
forall k. PKey k => k -> IO Digest
pkeyDefaultMD key
key
         Digest -> (Ptr EVP_MD -> IO ()) -> IO ()
forall a. Digest -> (Ptr EVP_MD -> IO a) -> IO a
withMDPtr Digest
dig ((Ptr EVP_MD -> IO ()) -> IO ()) -> (Ptr EVP_MD -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ Ptr EVP_MD
digestPtr ->
             Ptr X509_ -> Ptr EVP_PKEY -> Ptr EVP_MD -> IO CInt
_sign Ptr X509_
x509Ptr Ptr EVP_PKEY
pkeyPtr Ptr EVP_MD
digestPtr
                  IO CInt -> (CInt -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (CInt -> Bool) -> CInt -> IO ()
forall a. (a -> Bool) -> a -> IO ()
failIf_ (CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
0)
         () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

-- |@'verifyX509'@ verifies a signature of certificate with an issuer
-- public key.
verifyX509 :: PublicKey key =>
              X509 -- ^ The certificate to be verified.
           -> key  -- ^ The public key to verify with.
           -> IO VerifyStatus
verifyX509 :: forall key. PublicKey key => X509 -> key -> IO VerifyStatus
verifyX509 X509
x509 key
key
    = X509 -> (Ptr X509_ -> IO VerifyStatus) -> IO VerifyStatus
forall a. X509 -> (Ptr X509_ -> IO a) -> IO a
withX509Ptr X509
x509 ((Ptr X509_ -> IO VerifyStatus) -> IO VerifyStatus)
-> (Ptr X509_ -> IO VerifyStatus) -> IO VerifyStatus
forall a b. (a -> b) -> a -> b
$ \ Ptr X509_
x509Ptr ->
      key -> (Ptr EVP_PKEY -> IO VerifyStatus) -> IO VerifyStatus
forall k a. PKey k => k -> (Ptr EVP_PKEY -> IO a) -> IO a
withPKeyPtr' key
key ((Ptr EVP_PKEY -> IO VerifyStatus) -> IO VerifyStatus)
-> (Ptr EVP_PKEY -> IO VerifyStatus) -> IO VerifyStatus
forall a b. (a -> b) -> a -> b
$ \ Ptr EVP_PKEY
pkeyPtr ->
      Ptr X509_ -> Ptr EVP_PKEY -> IO CInt
_verify Ptr X509_
x509Ptr Ptr EVP_PKEY
pkeyPtr
           IO CInt -> (CInt -> IO VerifyStatus) -> IO VerifyStatus
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= CInt -> IO VerifyStatus
interpret
    where
      interpret :: CInt -> IO VerifyStatus
      interpret :: CInt -> IO VerifyStatus
interpret CInt
1 = VerifyStatus -> IO VerifyStatus
forall (m :: * -> *) a. Monad m => a -> m a
return VerifyStatus
VerifySuccess
      interpret CInt
0 = VerifyStatus -> IO VerifyStatus
forall (m :: * -> *) a. Monad m => a -> m a
return VerifyStatus
VerifyFailure
      interpret CInt
_ = IO VerifyStatus
forall a. IO a
raiseOpenSSLError

-- |@'printX509' cert@ translates a certificate into human-readable
-- format.
printX509 :: X509 -> IO String
printX509 :: X509 -> IO String
printX509 X509
x509
    = do BIO
mem <- IO BIO
newMem
         X509 -> (Ptr X509_ -> IO ()) -> IO ()
forall a. X509 -> (Ptr X509_ -> IO a) -> IO a
withX509Ptr X509
x509 ((Ptr X509_ -> IO ()) -> IO ()) -> (Ptr X509_ -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ Ptr X509_
x509Ptr ->
             BIO -> (Ptr BIO_ -> IO ()) -> IO ()
forall a. BIO -> (Ptr BIO_ -> IO a) -> IO a
withBioPtr BIO
mem ((Ptr BIO_ -> IO ()) -> IO ()) -> (Ptr BIO_ -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ Ptr BIO_
memPtr ->
                 Ptr BIO_ -> Ptr X509_ -> IO CInt
_print Ptr BIO_
memPtr Ptr X509_
x509Ptr
                      IO CInt -> (CInt -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (CInt -> Bool) -> CInt -> IO ()
forall a. (a -> Bool) -> a -> IO ()
failIf_ (CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1)
         BIO -> IO String
bioRead BIO
mem

-- |@'getVersion' cert@ returns the version number of certificate. It
-- seems the number is 0-origin: version 2 means X.509 v3.
getVersion :: X509 -> IO Int
getVersion :: X509 -> IO Int
getVersion X509
x509
    = X509 -> (Ptr X509_ -> IO Int) -> IO Int
forall a. X509 -> (Ptr X509_ -> IO a) -> IO a
withX509Ptr X509
x509 ((Ptr X509_ -> IO Int) -> IO Int)
-> (Ptr X509_ -> IO Int) -> IO Int
forall a b. (a -> b) -> a -> b
$ \ Ptr X509_
x509Ptr ->
      (CLong -> Int) -> IO CLong -> IO Int
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM CLong -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (IO CLong -> IO Int) -> IO CLong -> IO Int
forall a b. (a -> b) -> a -> b
$ Ptr X509_ -> IO CLong
_get_version Ptr X509_
x509Ptr

-- |@'setVersion' cert ver@ updates the version number of certificate.
setVersion :: X509 -> Int -> IO ()
setVersion :: X509 -> Int -> IO ()
setVersion X509
x509 Int
ver
    = X509 -> (Ptr X509_ -> IO ()) -> IO ()
forall a. X509 -> (Ptr X509_ -> IO a) -> IO a
withX509Ptr X509
x509 ((Ptr X509_ -> IO ()) -> IO ()) -> (Ptr X509_ -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ Ptr X509_
x509Ptr ->
      Ptr X509_ -> CLong -> IO CInt
_set_version Ptr X509_
x509Ptr (Int -> CLong
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
ver)
           IO CInt -> (CInt -> IO CInt) -> IO CInt
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (CInt -> Bool) -> CInt -> IO CInt
forall a. (a -> Bool) -> a -> IO a
failIf (CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1)
           IO CInt -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>  () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

-- |@'getSerialNumber' cert@ returns the serial number of certificate.
getSerialNumber :: X509 -> IO Integer
getSerialNumber :: X509 -> IO Integer
getSerialNumber X509
x509
    = X509 -> (Ptr X509_ -> IO Integer) -> IO Integer
forall a. X509 -> (Ptr X509_ -> IO a) -> IO a
withX509Ptr X509
x509 ((Ptr X509_ -> IO Integer) -> IO Integer)
-> (Ptr X509_ -> IO Integer) -> IO Integer
forall a b. (a -> b) -> a -> b
$ \ Ptr X509_
x509Ptr ->
      Ptr X509_ -> IO (Ptr ASN1_INTEGER)
_get_serialNumber Ptr X509_
x509Ptr
           IO (Ptr ASN1_INTEGER)
-> (Ptr ASN1_INTEGER -> IO Integer) -> IO Integer
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Ptr ASN1_INTEGER -> IO Integer
peekASN1Integer

-- |@'setSerialNumber' cert num@ updates the serial number of
-- certificate.
setSerialNumber :: X509 -> Integer -> IO ()
setSerialNumber :: X509 -> Integer -> IO ()
setSerialNumber X509
x509 Integer
serial
    = X509 -> (Ptr X509_ -> IO ()) -> IO ()
forall a. X509 -> (Ptr X509_ -> IO a) -> IO a
withX509Ptr X509
x509 ((Ptr X509_ -> IO ()) -> IO ()) -> (Ptr X509_ -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ Ptr X509_
x509Ptr ->
      Integer -> (Ptr ASN1_INTEGER -> IO ()) -> IO ()
forall a. Integer -> (Ptr ASN1_INTEGER -> IO a) -> IO a
withASN1Integer Integer
serial ((Ptr ASN1_INTEGER -> IO ()) -> IO ())
-> (Ptr ASN1_INTEGER -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ Ptr ASN1_INTEGER
serialPtr ->
      Ptr X509_ -> Ptr ASN1_INTEGER -> IO CInt
_set_serialNumber Ptr X509_
x509Ptr Ptr ASN1_INTEGER
serialPtr
           IO CInt -> (CInt -> IO CInt) -> IO CInt
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (CInt -> Bool) -> CInt -> IO CInt
forall a. (a -> Bool) -> a -> IO a
failIf (CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1)
           IO CInt -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>  () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

-- |@'getIssuerName'@ returns the issuer name of certificate.
getIssuerName :: X509 -- ^ The certificate to examine.
              -> Bool -- ^ @True@ if you want the keys of each parts
                      --   to be of long form (e.g. \"commonName\"),
                      --   or @False@ if you don't (e.g. \"CN\").
              -> IO [(String, String)] -- ^ Pairs of key and value,
                                       -- for example \[(\"C\",
                                       -- \"JP\"), (\"ST\",
                                       -- \"Some-State\"), ...\].
getIssuerName :: X509 -> Bool -> IO [(String, String)]
getIssuerName X509
x509 Bool
wantLongName
    = X509
-> (Ptr X509_ -> IO [(String, String)]) -> IO [(String, String)]
forall a. X509 -> (Ptr X509_ -> IO a) -> IO a
withX509Ptr X509
x509 ((Ptr X509_ -> IO [(String, String)]) -> IO [(String, String)])
-> (Ptr X509_ -> IO [(String, String)]) -> IO [(String, String)]
forall a b. (a -> b) -> a -> b
$ \ Ptr X509_
x509Ptr ->
      do Ptr X509_NAME
namePtr <- Ptr X509_ -> IO (Ptr X509_NAME)
_get_issuer_name Ptr X509_
x509Ptr
         Ptr X509_NAME -> Bool -> IO [(String, String)]
peekX509Name Ptr X509_NAME
namePtr Bool
wantLongName

-- |@'setIssuerName' cert name@ updates the issuer name of
-- certificate. Keys of each parts may be of either long form or short
-- form. See 'getIssuerName'.
setIssuerName :: X509 -> [(String, String)] -> IO ()
setIssuerName :: X509 -> [(String, String)] -> IO ()
setIssuerName X509
x509 [(String, String)]
issuer
    = X509 -> (Ptr X509_ -> IO ()) -> IO ()
forall a. X509 -> (Ptr X509_ -> IO a) -> IO a
withX509Ptr X509
x509 ((Ptr X509_ -> IO ()) -> IO ()) -> (Ptr X509_ -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ Ptr X509_
x509Ptr ->
      [(String, String)] -> (Ptr X509_NAME -> IO ()) -> IO ()
forall a. [(String, String)] -> (Ptr X509_NAME -> IO a) -> IO a
withX509Name [(String, String)]
issuer ((Ptr X509_NAME -> IO ()) -> IO ())
-> (Ptr X509_NAME -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ Ptr X509_NAME
namePtr ->
      Ptr X509_ -> Ptr X509_NAME -> IO CInt
_set_issuer_name Ptr X509_
x509Ptr Ptr X509_NAME
namePtr
           IO CInt -> (CInt -> IO CInt) -> IO CInt
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (CInt -> Bool) -> CInt -> IO CInt
forall a. (a -> Bool) -> a -> IO a
failIf (CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1)
           IO CInt -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>  () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

-- |@'getSubjectName' cert wantLongName@ returns the subject name of
-- certificate. See 'getIssuerName'.
getSubjectName :: X509 -> Bool -> IO [(String, String)]
getSubjectName :: X509 -> Bool -> IO [(String, String)]
getSubjectName X509
x509 Bool
wantLongName
    = X509
-> (Ptr X509_ -> IO [(String, String)]) -> IO [(String, String)]
forall a. X509 -> (Ptr X509_ -> IO a) -> IO a
withX509Ptr X509
x509 ((Ptr X509_ -> IO [(String, String)]) -> IO [(String, String)])
-> (Ptr X509_ -> IO [(String, String)]) -> IO [(String, String)]
forall a b. (a -> b) -> a -> b
$ \ Ptr X509_
x509Ptr ->
      do Ptr X509_NAME
namePtr <- Ptr X509_ -> IO (Ptr X509_NAME)
_get_subject_name Ptr X509_
x509Ptr
         Ptr X509_NAME -> Bool -> IO [(String, String)]
peekX509Name Ptr X509_NAME
namePtr Bool
wantLongName

-- |@'setSubjectName' cert name@ updates the subject name of
-- certificate. See 'setIssuerName'.
setSubjectName :: X509 -> [(String, String)] -> IO ()
setSubjectName :: X509 -> [(String, String)] -> IO ()
setSubjectName X509
x509 [(String, String)]
subject
    = X509 -> (Ptr X509_ -> IO ()) -> IO ()
forall a. X509 -> (Ptr X509_ -> IO a) -> IO a
withX509Ptr X509
x509 ((Ptr X509_ -> IO ()) -> IO ()) -> (Ptr X509_ -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ Ptr X509_
x509Ptr ->
      [(String, String)] -> (Ptr X509_NAME -> IO ()) -> IO ()
forall a. [(String, String)] -> (Ptr X509_NAME -> IO a) -> IO a
withX509Name [(String, String)]
subject ((Ptr X509_NAME -> IO ()) -> IO ())
-> (Ptr X509_NAME -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ Ptr X509_NAME
namePtr ->
      Ptr X509_ -> Ptr X509_NAME -> IO CInt
_set_subject_name Ptr X509_
x509Ptr Ptr X509_NAME
namePtr
           IO CInt -> (CInt -> IO CInt) -> IO CInt
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (CInt -> Bool) -> CInt -> IO CInt
forall a. (a -> Bool) -> a -> IO a
failIf (CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1)
           IO CInt -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>  () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

-- |@'getNotBefore' cert@ returns the time when the certificate begins
-- to be valid.
getNotBefore :: X509 -> IO UTCTime
getNotBefore :: X509 -> IO UTCTime
getNotBefore X509
x509
    = X509 -> (Ptr X509_ -> IO UTCTime) -> IO UTCTime
forall a. X509 -> (Ptr X509_ -> IO a) -> IO a
withX509Ptr X509
x509 ((Ptr X509_ -> IO UTCTime) -> IO UTCTime)
-> (Ptr X509_ -> IO UTCTime) -> IO UTCTime
forall a b. (a -> b) -> a -> b
$ \ Ptr X509_
x509Ptr ->
      Ptr X509_ -> IO (Ptr ASN1_TIME)
_get_notBefore Ptr X509_
x509Ptr
           IO (Ptr ASN1_TIME) -> (Ptr ASN1_TIME -> IO UTCTime) -> IO UTCTime
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Ptr ASN1_TIME -> IO UTCTime
peekASN1Time

-- |@'setNotBefore' cert utc@ updates the time when the certificate
-- begins to be valid.
setNotBefore :: X509 -> UTCTime -> IO ()
setNotBefore :: X509 -> UTCTime -> IO ()
setNotBefore X509
x509 UTCTime
utc
    = X509 -> (Ptr X509_ -> IO ()) -> IO ()
forall a. X509 -> (Ptr X509_ -> IO a) -> IO a
withX509Ptr X509
x509 ((Ptr X509_ -> IO ()) -> IO ()) -> (Ptr X509_ -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ Ptr X509_
x509Ptr ->
      UTCTime -> (Ptr ASN1_TIME -> IO ()) -> IO ()
forall a. UTCTime -> (Ptr ASN1_TIME -> IO a) -> IO a
withASN1Time UTCTime
utc ((Ptr ASN1_TIME -> IO ()) -> IO ())
-> (Ptr ASN1_TIME -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ Ptr ASN1_TIME
time ->
      Ptr X509_ -> Ptr ASN1_TIME -> IO CInt
_set_notBefore Ptr X509_
x509Ptr Ptr ASN1_TIME
time
           IO CInt -> (CInt -> IO CInt) -> IO CInt
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (CInt -> Bool) -> CInt -> IO CInt
forall a. (a -> Bool) -> a -> IO a
failIf (CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1)
           IO CInt -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>  () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

-- |@'getNotAfter' cert@ returns the time when the certificate
-- expires.
getNotAfter :: X509 -> IO UTCTime
getNotAfter :: X509 -> IO UTCTime
getNotAfter X509
x509
    = X509 -> (Ptr X509_ -> IO UTCTime) -> IO UTCTime
forall a. X509 -> (Ptr X509_ -> IO a) -> IO a
withX509Ptr X509
x509 ((Ptr X509_ -> IO UTCTime) -> IO UTCTime)
-> (Ptr X509_ -> IO UTCTime) -> IO UTCTime
forall a b. (a -> b) -> a -> b
$ \ Ptr X509_
x509Ptr ->
      Ptr X509_ -> IO (Ptr ASN1_TIME)
_get_notAfter Ptr X509_
x509Ptr
           IO (Ptr ASN1_TIME) -> (Ptr ASN1_TIME -> IO UTCTime) -> IO UTCTime
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Ptr ASN1_TIME -> IO UTCTime
peekASN1Time

-- |@'setNotAfter' cert utc@ updates the time when the certificate
-- expires.
setNotAfter :: X509 -> UTCTime -> IO ()
setNotAfter :: X509 -> UTCTime -> IO ()
setNotAfter X509
x509 UTCTime
utc
    = X509 -> (Ptr X509_ -> IO ()) -> IO ()
forall a. X509 -> (Ptr X509_ -> IO a) -> IO a
withX509Ptr X509
x509 ((Ptr X509_ -> IO ()) -> IO ()) -> (Ptr X509_ -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ Ptr X509_
x509Ptr ->
      UTCTime -> (Ptr ASN1_TIME -> IO ()) -> IO ()
forall a. UTCTime -> (Ptr ASN1_TIME -> IO a) -> IO a
withASN1Time UTCTime
utc ((Ptr ASN1_TIME -> IO ()) -> IO ())
-> (Ptr ASN1_TIME -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ Ptr ASN1_TIME
time ->
      Ptr X509_ -> Ptr ASN1_TIME -> IO CInt
_set_notAfter Ptr X509_
x509Ptr Ptr ASN1_TIME
time
           IO CInt -> (CInt -> IO CInt) -> IO CInt
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (CInt -> Bool) -> CInt -> IO CInt
forall a. (a -> Bool) -> a -> IO a
failIf (CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1)
           IO CInt -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>  () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

-- |@'getPublicKey' cert@ returns the public key of the subject of
-- certificate.
getPublicKey :: X509 -> IO SomePublicKey
getPublicKey :: X509 -> IO SomePublicKey
getPublicKey X509
x509
    = X509 -> (Ptr X509_ -> IO SomePublicKey) -> IO SomePublicKey
forall a. X509 -> (Ptr X509_ -> IO a) -> IO a
withX509Ptr X509
x509 ((Ptr X509_ -> IO SomePublicKey) -> IO SomePublicKey)
-> (Ptr X509_ -> IO SomePublicKey) -> IO SomePublicKey
forall a b. (a -> b) -> a -> b
$ \ Ptr X509_
x509Ptr ->
      (Maybe SomePublicKey -> SomePublicKey)
-> IO (Maybe SomePublicKey) -> IO SomePublicKey
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Maybe SomePublicKey -> SomePublicKey
forall a. HasCallStack => Maybe a -> a
fromJust ( Ptr X509_ -> IO (Ptr EVP_PKEY)
_get_pubkey Ptr X509_
x509Ptr
                      IO (Ptr EVP_PKEY)
-> (Ptr EVP_PKEY -> IO (Ptr EVP_PKEY)) -> IO (Ptr EVP_PKEY)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Ptr EVP_PKEY -> IO (Ptr EVP_PKEY)
forall a. Ptr a -> IO (Ptr a)
failIfNull
                      IO (Ptr EVP_PKEY) -> (Ptr EVP_PKEY -> IO VaguePKey) -> IO VaguePKey
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Ptr EVP_PKEY -> IO VaguePKey
wrapPKeyPtr
                      IO VaguePKey
-> (VaguePKey -> IO (Maybe SomePublicKey))
-> IO (Maybe SomePublicKey)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= VaguePKey -> IO (Maybe SomePublicKey)
forall k. PKey k => VaguePKey -> IO (Maybe k)
fromPKey
                    )

-- |@'setPublicKey' cert pubkey@ updates the public key of the subject
-- of certificate.
setPublicKey :: PublicKey key => X509 -> key -> IO ()
setPublicKey :: forall key. PublicKey key => X509 -> key -> IO ()
setPublicKey X509
x509 key
key
    = X509 -> (Ptr X509_ -> IO ()) -> IO ()
forall a. X509 -> (Ptr X509_ -> IO a) -> IO a
withX509Ptr X509
x509 ((Ptr X509_ -> IO ()) -> IO ()) -> (Ptr X509_ -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ Ptr X509_
x509Ptr ->
      key -> (Ptr EVP_PKEY -> IO ()) -> IO ()
forall k a. PKey k => k -> (Ptr EVP_PKEY -> IO a) -> IO a
withPKeyPtr' key
key ((Ptr EVP_PKEY -> IO ()) -> IO ())
-> (Ptr EVP_PKEY -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ Ptr EVP_PKEY
pkeyPtr ->
      Ptr X509_ -> Ptr EVP_PKEY -> IO CInt
_set_pubkey Ptr X509_
x509Ptr Ptr EVP_PKEY
pkeyPtr
           IO CInt -> (CInt -> IO CInt) -> IO CInt
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (CInt -> Bool) -> CInt -> IO CInt
forall a. (a -> Bool) -> a -> IO a
failIf (CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1)
           IO CInt -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>  () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

-- |@'getSubjectEmail' cert@ returns every subject email addresses in
-- the certificate.
getSubjectEmail :: X509 -> IO [String]
getSubjectEmail :: X509 -> IO [String]
getSubjectEmail X509
x509
    = X509 -> (Ptr X509_ -> IO [String]) -> IO [String]
forall a. X509 -> (Ptr X509_ -> IO a) -> IO a
withX509Ptr X509
x509 ((Ptr X509_ -> IO [String]) -> IO [String])
-> (Ptr X509_ -> IO [String]) -> IO [String]
forall a b. (a -> b) -> a -> b
$ \ Ptr X509_
x509Ptr ->
      do Ptr STACK
st   <- Ptr X509_ -> IO (Ptr STACK)
_get1_email Ptr X509_
x509Ptr
         [String]
list <- (Ptr CChar -> IO String) -> Ptr STACK -> IO [String]
forall a b. (Ptr a -> IO b) -> Ptr STACK -> IO [b]
mapStack Ptr CChar -> IO String
peekCString Ptr STACK
st
         Ptr STACK -> IO ()
_email_free Ptr STACK
st
         [String] -> IO [String]
forall (m :: * -> *) a. Monad m => a -> m a
return [String]
list