Compare commits

...

4 Commits

Author SHA1 Message Date
Jonathan Lamothe a45a75c3e2 get the client certificate from the connection's context
...instead of the janky thing we were doing before
2023-01-04 10:26:56 -05:00
Jonathan Lamothe 77cfcce5df version 0.1.0.1 2023-01-04 10:09:48 -05:00
Jonathan Lamothe 115dcf3998 Merge pull request 'catch *any* exception' (#3) from crashfix into dev
Reviewed-on: https://codeberg.org/jlamothe/gemcap/pulls/3
2023-01-04 15:02:01 +00:00
Jonathan Lamothe 554efdabcb catch *any* exception
`listenLoop` was crashing when the client closed the connection during the handshake.  How this doesn't qualify as an `IOException` is beyond me.
2023-01-01 11:52:59 -05:00
4 changed files with 20 additions and 31 deletions

View File

@ -1,3 +1,6 @@
# Changelog for gemcap
## Unreleased changes
## 0.1.0.1
- updated underlying libraries to more current versions
- fixed a bug that would cause the server to crash when the client aborted the handshake by rejecting the key

View File

@ -5,7 +5,7 @@ cabal-version: 2.2
-- see: https://github.com/sol/hpack
name: gemcap
version: 0.1.0
version: 0.1.0.1
synopsis: a simple Gemini capsule (server)
description: a simple Gemini capsule (server) - see README.md for details
category: Gemini

View File

@ -1,5 +1,5 @@
name: gemcap
version: 0.1.0
version: 0.1.0.1
license: AGPL-3.0-or-later
author: "Jonathan Lamothe"
maintainer: "jonathan@jlamothe.net"

View File

@ -31,15 +31,15 @@ module Network.Gemini.Capsule (
) where
import Control.Concurrent (forkIO)
import Control.Exception (IOException, try)
import Control.Exception (SomeException, try)
import Control.Exception.Base (bracket, finally)
import Control.Monad (void)
import Control.Monad.Trans.Maybe (MaybeT (..), runMaybeT)
import qualified Data.Connection as C
import Data.IORef (IORef, newIORef, readIORef, writeIORef)
import Data.TLSSetting (makeServerParams)
import Data.X509 (Certificate, CertificateChain (..), getSigned, signedObject)
import Data.X509 (CertificateChain (..), getSigned, signedObject)
import qualified Network.Socket as S
import Network.TLS (ServerParams, onClientCertificate, serverHooks)
import Network.TLS (ServerParams, getClientCertificateChain)
import System.IO.Streams.TCP (bindAndListen)
import System.IO.Streams.TLS (accept)
@ -69,32 +69,18 @@ runGemCapsule settings handler = bracket
listenLoop :: S.Socket -> ServerParams -> GemHandler -> IO a
listenLoop sock params handler = do
certRef <- newIORef Nothing
let params' = adjustServerParams certRef params
try (accept params' sock) >>= \case
Left (_::IOException) -> return ()
try (accept params sock) >>= \case
Left (_::SomeException) -> return ()
Right conn -> void $ forkIO $ finally
(readIORef certRef >>= runConnection conn handler)
( do
let (context, _) = C.connExtraInfo conn
mCert <- runMaybeT $
MaybeT (getClientCertificateChain context) >>= \case
CertificateChain [] -> fail "no certificate"
CertificateChain (se:_) -> return $ signedObject $ getSigned se
runConnection conn handler mCert
)
(C.close conn)
listenLoop sock params handler
adjustServerParams
:: IORef (Maybe Certificate)
-> ServerParams
-> ServerParams
adjustServerParams certRef params = let
hooks = serverHooks params
certHook = onClientCertificate hooks
certHook' chain = do
case chain of
CertificateChain [] -> return ()
CertificateChain (se:_) -> do
let cert = signedObject $ getSigned se
writeIORef certRef (Just cert)
certHook chain
hooks' = hooks { onClientCertificate = certHook' }
in params { serverHooks = hooks' }
--jl