packages feed

tls-session-manager (empty) → 0.0.0.0

raw patch · 5 files changed

+192/−0 lines, 5 filesdep +auto-updatedep +basedep +clocksetup-changed

Dependencies added: auto-update, base, clock, psqueues, time, tls

Files

+ ChangeLog.md view
@@ -0,0 +1,2 @@+# 0.0.0.0+- A first release.
+ LICENSE view
@@ -0,0 +1,29 @@+Copyright (c) 2017, IIJ Innovation Institute Inc.+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:++  * Redistributions of source code must retain the above copyright+    notice, this list of conditions and the following disclaimer.+  * Redistributions in binary form must reproduce the above copyright+    notice, this list of conditions and the following disclaimer in+    the documentation and/or other materials provided with the+    distribution.+  * Neither the name of the copyright holders nor the names of its+    contributors may be used to endorse or promote products derived+    from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.
+ Network/TLS/SessionManager.hs view
@@ -0,0 +1,132 @@+{-# LANGUAGE BangPatterns #-}++-- | In-memory TLS session manager.+--+-- * Limitation: you can set the maximum size of the session data database.+-- * Automatic pruning: old session data over their lifetime are pruned automatically.+-- * Energy saving: no dedicate pruning thread is running when the size of session data database is zero.+-- * (Replay resistance: each session data is used at most once to prevent replay attacks against 0RTT early data of TLS 1.3.)++module Network.TLS.SessionManager (+    Config(..)+  , defaultConfig+  , newSessionManager+  ) where++import Control.Exception (assert)+import Control.Reaper+import Data.IORef+import Data.Int (Int64)+import Data.List (foldl')+import Data.OrdPSQ (OrdPSQ)+import qualified Data.OrdPSQ as Q+import Network.TLS (SessionID, SessionData, SessionManager(..))+import qualified System.Clock as C++----------------------------------------------------------------++-- | Configuration for session managers.+data Config = Config {+    -- | Ticket lifetime in seconds.+      ticketLifetime :: !Int+    -- | Pruning delay in seconds. This is set to 'reaperDelay'.+    , pruningDelay   :: !Int+    -- | The limit size of session data entries.+    , dbMaxSize      :: !Int+    }++-- | Lifetime: 1 day , delay: 10 minutes, limit: 10,000 entries.+defaultConfig :: Config+defaultConfig = Config {+      ticketLifetime = 86400+    , pruningDelay   = 6000+    , dbMaxSize      = 10000+    }++----------------------------------------------------------------++type Sec = Int64+type Value = (SessionData, IORef Availability)+type DB = OrdPSQ SessionID Sec Value+type Item = (SessionID, Sec, Value, Operation)++data Operation = Add | Del+data Use = SingleUse | MultipleUse+data Availability = Fresh | Used++----------------------------------------------------------------++-- | Creating an in-memory session manager.+newSessionManager :: Config -> IO SessionManager+newSessionManager conf = do+    let lifetime = fromIntegral $ ticketLifetime conf+        maxsiz = dbMaxSize conf+    reaper <- mkReaper defaultReaperSettings {+          reaperEmpty  = Q.empty+        , reaperCons   = cons maxsiz+        , reaperAction = clean+        , reaperNull   = Q.null+        , reaperDelay  = pruningDelay conf * 1000000+        }+    return SessionManager {+        sessionResume     = resume reaper MultipleUse+      , sessionEstablish  = establish reaper lifetime+      , sessionInvalidate = invalidate reaper+      }++cons :: Int -> Item -> DB -> DB+cons lim (k,t,v,Add) db+  | lim <= 0            = Q.empty+  | Q.size db == lim    = case Q.minView db of+      Nothing          -> assert False $ Q.insert k t v Q.empty+      Just (_,_,_,db') -> Q.insert k t v db'+  | otherwise           = Q.insert k t v db+cons _   (k,_,_,Del) db = Q.delete k db++clean :: DB -> IO (DB -> DB)+clean olddb = do+    currentTime <- C.sec <$> C.getTime C.Monotonic+    let !pruned = snd $ Q.atMostView currentTime olddb+    return $ merge pruned+  where+    ins db (k,p,v) = Q.insert k p v db+    -- There is not 'merge' API.+    -- We hope that newdb is smaller than pruned.+    merge pruned newdb = foldl' ins pruned entries+      where+        entries = Q.toList newdb++----------------------------------------------------------------++establish :: Reaper DB Item -> Sec+          -> SessionID -> SessionData -> IO ()+establish reaper lifetime k sd = do+    ref <- newIORef Fresh+    !p <- ((+ lifetime) . C.sec) <$> C.getTime C.Monotonic+    let !v = (sd,ref)+    reaperAdd reaper (k,p,v,Add)++resume :: Reaper DB Item -> Use+       -> SessionID -> IO (Maybe SessionData)+resume reaper use k = do+    db <- reaperRead reaper+    case Q.lookup k db of+      Nothing             -> return Nothing+      Just (p,v@(sd,ref)) -> do+           case use of+               SingleUse -> do+                   available <- atomicModifyIORef' ref check+                   reaperAdd reaper (k,p,v,Del)+                   return $ if available then Just sd else Nothing+               MultipleUse -> return $ Just sd+  where+    check Fresh = (Used,True)+    check Used  = (Used,False)++invalidate :: Reaper DB Item+           -> SessionID -> IO ()+invalidate reaper k = do+    db <- reaperRead reaper+    case Q.lookup k db of+      Nothing    -> return ()+      Just (p,v) -> reaperAdd reaper (k,p,v,Del)
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ tls-session-manager.cabal view
@@ -0,0 +1,27 @@+name:                tls-session-manager+version:             0.0.0.0+synopsis:            In-memory TLS session manager+description:         TLS session manager with limitation, automatic pruning, energy saving and replay resistance+license:             BSD3+license-file:        LICENSE+author:              Kazu Yamamoto+maintainer:          kazu@iij.ad.jp+-- copyright:+category:            Web+build-type:          Simple+extra-source-files:  ChangeLog.md+cabal-version:       >= 1.10++library+  exposed-modules:     Network.TLS.SessionManager+  -- other-modules:+  -- other-extensions:+  build-depends:       base >= 4.9 && < 5+                     , auto-update+                     , clock+                     , psqueues >= 0.2.3+                     , time+                     , tls+  -- hs-source-dirs:+  default-language:    Haskell2010+  ghc-options:       -Wall