{-# LINE 1 "src/Hookup/OpenSSL.hsc" #-}
{-# Language CApiFFI #-}
{-# LINE 17 "src/Hookup/OpenSSL.hsc" #-}
module Hookup.OpenSSL (installVerification, getPubKeyDer) where
import Control.Monad (unless)
import Foreign.C (CString(..), CSize(..), CUInt(..), CInt(..), withCStringLen)
import Foreign.Ptr (Ptr, castPtr, nullPtr)
import Foreign.Marshal (with)
import OpenSSL.Session (SSLContext, SSLContext_, withContext)
import OpenSSL.X509 (withX509Ptr, X509, X509_)
import Data.ByteString (ByteString)
import qualified Data.ByteString.Internal as B
data X509_VERIFY_PARAM_
data {-# CTYPE "openssl/ssl.h" "X509_PUBKEY" #-} X509_PUBKEY_
data {-# CTYPE "openssl/ssl.h" "X509" #-} X509__
foreign import ccall unsafe "SSL_CTX_get0_param"
sslGet0Param ::
Ptr SSLContext_ ->
IO (Ptr X509_VERIFY_PARAM_)
foreign import ccall unsafe "X509_VERIFY_PARAM_set_hostflags"
x509VerifyParamSetHostflags ::
Ptr X509_VERIFY_PARAM_ ->
CUInt ->
IO ()
foreign import ccall unsafe "X509_VERIFY_PARAM_set1_host"
x509VerifyParamSet1Host ::
Ptr X509_VERIFY_PARAM_ ->
CString ->
CSize ->
IO CInt
foreign import capi unsafe "openssl/x509.h X509_get_X509_PUBKEY"
x509getX509Pubkey ::
Ptr X509__ -> IO (Ptr X509_PUBKEY_)
foreign import ccall unsafe "i2d_X509_PUBKEY"
i2dX509Pubkey ::
Ptr X509_PUBKEY_ ->
Ptr CString ->
IO CInt
getPubKeyDer :: X509 -> IO ByteString
getPubKeyDer x509 =
withX509Ptr x509 $ \x509ptr ->
do pubkey <- x509getX509Pubkey (castPtr x509ptr)
len <- fromIntegral <$> i2dX509Pubkey pubkey nullPtr
B.create len $ \bsPtr ->
with (castPtr bsPtr) $ \ptrPtr ->
() <$ i2dX509Pubkey pubkey ptrPtr
installVerification :: SSLContext -> String -> IO ()
installVerification ctx host =
withContext ctx $ \ctxPtr ->
withCStringLen host $ \(ptr,len) ->
do param <- sslGet0Param ctxPtr
x509VerifyParamSetHostflags param
(4)
{-# LINE 89 "src/Hookup/OpenSSL.hsc" #-}
success <- x509VerifyParamSet1Host param ptr (fromIntegral len)
unless (success == 1) (fail "Unable to set verification host")