mysql-haskell-0.3.0.0: Database/MySQL/OpenSSL.hs
{-|
Module : Database.MySQL.Connection
Description : Connection managment
Copyright : (c) Winterland, 2016
License : BSD
Maintainer : drkoster@qq.com
Stability : experimental
Portability : PORTABLE
This module provides secure MySQL connection using 'HsOpenSSL' package.
-}
module Database.MySQL.OpenSSL where
import Control.Exception (bracketOnError, throwIO)
import Control.Monad
import Data.IORef (newIORef)
import Database.MySQL.Connection hiding (connect, connectDetail)
import Database.MySQL.Protocol.Auth
import Database.MySQL.Protocol.Packet
import qualified Network.Socket as N
import qualified OpenSSL as SSL
import qualified OpenSSL.Session as Session
import qualified System.IO.Streams as Stream
import qualified System.IO.Streams.Binary as Binary
import qualified System.IO.Streams.OpenSSL as SSL
import qualified System.IO.Streams.TCP as TCP
--------------------------------------------------------------------------------
connect :: ConnectInfo -> Session.SSLContext -> IO MySQLConn
connect c cp = fmap snd (connectDetail c cp)
connectDetail :: ConnectInfo -> Session.SSLContext -> IO (Greeting, MySQLConn)
connectDetail ci@(ConnectInfo host port _ _ _) ctx =
bracketOnError (TCP.connectWithBufferSize host port bUFSIZE)
(\(_, _, sock) -> N.close sock) $ \ (is, os, sock) -> do
is' <- decodeInputStream is
os' <- Binary.encodeOutputStream os
p <- readPacket is'
greet <- decodeFromPacket p
if supportTLS (greetingCaps greet)
then SSL.withOpenSSL $ do
Stream.write (Just (encodeToPacket 1 sslRequest)) os'
bracketOnError (Session.connection ctx sock) SSL.close $ \ ssl -> do
Session.connect ssl
(sslIs, sslOs) <- SSL.sslToStreams ssl
sslIs' <- decodeInputStream sslIs
sslOs' <- Binary.encodeOutputStream sslOs
let auth = mkAuth ci greet
Stream.write (Just (encodeToPacket 2 auth)) sslOs'
q <- readPacket sslIs'
if isOK q
then do
consumed <- newIORef True
let conn = MySQLConn sslIs' sslOs' (SSL.close ssl) consumed
return (greet, conn)
else Stream.write Nothing sslOs' >> decodeFromPacket q >>= throwIO . ERRException
else error "Database.MySQL.OpenSSL: server doesn't support TLS connection"