packages feed

radius 0.3.0.0 → 0.4.0.0

raw patch · 4 files changed

+123/−9 lines, 4 filesdep +cryptonitedep +memorydep −cryptohash-md5dep −pretty-hexPVP ok

version bump matches the API change (PVP)

Dependencies added: cryptonite, memory

Dependencies removed: cryptohash-md5, pretty-hex

API changes (from Hackage documentation)

- Network.RADIUS.Types: [getVendorSpecificAttributeId] :: PacketAttribute -> Word32
+ Network.RADIUS.Encoding: hashMD5 :: ByteString -> ByteString
+ Network.RADIUS.Microsoft: encodeMPPEEncryptionPolicyAttribute :: Word32 -> PacketAttribute
+ Network.RADIUS.Microsoft: encodeMPPEEncryptionTypesAttribute :: Word32 -> PacketAttribute
+ Network.RADIUS.Microsoft: encodeMPPERecvKeyAttribute :: Word16 -> ByteString -> ByteString -> ByteString -> PacketAttribute
+ Network.RADIUS.Microsoft: encodeMPPESendKeyAttribute :: Word16 -> ByteString -> ByteString -> ByteString -> PacketAttribute
+ Network.RADIUS.Types: [getVendorIdAttribute] :: PacketAttribute -> Word32

Files

radius.cabal view
@@ -1,5 +1,5 @@ name:                radius-version:             0.3.0.0+version:             0.4.0.0 synopsis:            Remote Authentication Dial In User Service (RADIUS) description:         This module provides types and on the wire de/coding of RADIUS packets as per RFC2865 homepage:            https://github.com/erickg/radius#readme@@ -16,13 +16,14 @@ library   hs-source-dirs:      src   exposed-modules:     Network.RADIUS.Encoding+                     , Network.RADIUS.Microsoft                      , Network.RADIUS.Types   build-depends:       base >= 4.7 && < 5                      , binary                      , bytestring-                     , cryptohash-md5+                     , cryptonite                      , iproute-                     , pretty-hex+                     , memory   default-language:    Haskell2010   ghc-options:         -Wall 
src/Network/RADIUS/Encoding.hs view
@@ -18,15 +18,22 @@ import Control.Monad               (when) import Data.Binary                 (Binary(..), encode) import Data.Binary.Put             (Put, putLazyByteString, putWord8, putWord16be, putWord32be)-import Data.Binary.Get             (Get, getLazyByteString, getWord8, getWord16be, getWord32be, isEmpty)+import Data.Binary.Get             (Get,+                                    getLazyByteString,+                                    getWord8,+                                    getWord16be,+                                    getWord32be,+                                    isEmpty)+import Data.ByteArray              (convert) import Data.ByteString.Lazy.Char8  (ByteString, append) import Data.IP                     (IPv4, IPv6) import Data.Int                    (Int64) import Data.Word                   (Word8, Word16)+import Crypto.Hash.Algorithms      (MD5)+import Crypto.Hash                 (Digest, hashlazy) import Network.RADIUS.Types  import qualified Data.ByteString.Lazy.Char8 as B-import qualified Crypto.Hash.MD5            as MD5  -- | Self explanatory. It can be useful when reading a RADIUS packet from a socket for example, -- so one can retrieve the packet header (containing the packet length) first and then use that@@ -77,11 +84,14 @@  sign :: ByteString -> ByteString -> ByteString sign packet secret =-    let authenticator = B.fromStrict . MD5.hashlazy $ packet `append` secret+    let authenticator = hashMD5 $ packet `append` secret         prologue      = B.take 4 packet -- size of type, id, length         attributes    = B.drop (fromIntegral radiusHeaderSize) packet     in prologue `append` authenticator `append` attributes +hashMD5 :: ByteString -> ByteString+hashMD5 = B.fromStrict . convert . (hashlazy :: ByteString -> Digest MD5)+ instance Binary PacketType where     put = putWord8 . fromIntegral . fromEnum     get = getWord8 >>= return . toEnum . fromIntegral@@ -174,11 +184,11 @@       putWord8 0  -- reserved       putWord8 $ fromIntegral prefixLength       putLazyByteString attr-    put (VendorSpecificAttribute iD str) = do+    put (VendorSpecificAttribute vendorId str) = do       let attrLen = (fromIntegral . B.length $ str) + 6 -- Attribute header length + string       putWord8 26 -- Attribute Type       putWord8 attrLen-      put iD+      putWord32be vendorId       putLazyByteString str     put (CHAPPassword identity str)           = do       let attrLen = (fromIntegral . B.length $ str) + 3 -- Attribute header plus string
+ src/Network/RADIUS/Microsoft.hs view
@@ -0,0 +1,103 @@+{-# LANGUAGE RecordWildCards, OverloadedStrings #-}+{-|+Module      : Network.RADIUS.Microsoft+Description : Microsoft specific RADIUS Attributes+Copyright   : (c) Erick Gonzalez, 2017+License     : BSD3+Maintainer  : erick@codemonkeylabs.de+Stability   : experimental+Portability : POSIX++This module provides encoding for some of the Microsoft specific attributes, particularly those+needed for MSCHAPv2.++-}+module Network.RADIUS.Microsoft (encodeMPPESendKeyAttribute,+                                 encodeMPPERecvKeyAttribute,+                                 encodeMPPEEncryptionPolicyAttribute,+                                 encodeMPPEEncryptionTypesAttribute) where++import Prelude hiding (zipWith)+import Crypto.Hash.Algorithms    (MD5)+import Crypto.Hash               (Digest, hash)+import Data.Binary.Put           (Put, putByteString, putWord8, putWord16be, runPut, putWord32be)+import Data.Bits                 ((.|.), xor)+import Data.ByteArray            (convert)+import Data.ByteString           (ByteString, pack, zipWith)+import Data.ByteString.Internal  (w2c)+import Data.Monoid               ((<>))+import Data.Word                 (Word8, Word16, Word32)+import Network.RADIUS.Types++import qualified Data.ByteString.Lazy.Char8 as LB+import qualified Data.ByteString.Char8      as B++-- | Wraps the given encoded vendor specific attribute data into a PacketAttribute with+-- Microsoft SMI Network Management Enterprise Code+vendorSpecificAttribute :: LB.ByteString -> PacketAttribute+vendorSpecificAttribute = VendorSpecificAttribute 311++-- | Encode the MS-MPPE-Send-Key RADIUS attribute as per [RFC2548]+encodeMPPESendKeyAttribute :: Word16    -- ^ 16 bit random salt+                           -> ByteString -- ^ MPPE send key+                           -> ByteString -- ^ Password+                           -> ByteString -- ^ Authenticator in Access-Request message+                           -> PacketAttribute+encodeMPPESendKeyAttribute salt key secret authenticator =+    vendorSpecificAttribute . runPut $ encodeMPPEKeyAttribute 16 salt key secret authenticator++-- | Encode the MS-MPPE-Recv-Key RADIUS attribute as per [RFC2548]+encodeMPPERecvKeyAttribute :: Word16     -- ^ 16 bit random salt+                           -> ByteString -- ^ MPPE recv key+                           -> ByteString -- ^ Password+                           -> ByteString -- ^ Authenticator in Access-Request message+                           -> PacketAttribute+encodeMPPERecvKeyAttribute salt key secret authenticator =+    vendorSpecificAttribute . runPut $ encodeMPPEKeyAttribute 17 salt key secret authenticator++encodeMPPEKeyAttribute :: Word8+                       -> Word16+                       -> ByteString+                       -> ByteString+                       -> ByteString+                       -> Put+encodeMPPEKeyAttribute vendorType salt key secret authenticator = do+  putWord8 vendorType+  let salt'      = LB.toStrict . runPut . putWord16be $ salt .|. 0x8000 -- MSB in salt must be set+      keyLength  = w2c . fromIntegral $ B.length key+      str        = B.cons keyLength key+      n          = B.length str `mod` 16+      m          = if n == 0 then 0 else 16 - n+      str'       = str <> B.replicate m '\NUL'+      (_,result) = foldl encrypt ((authenticator <> salt'), B.empty) $ partition 16 str'+      vendorLen  = fromIntegral $ 4 + B.length result+  putWord8 vendorLen+  putByteString salt'+  putByteString result+      where md5                  = convert . (hash :: ByteString -> Digest MD5)+            partition n          = partition' [] n+            partition' acc _ ""  = reverse acc+            partition' acc n str =+                let (x, xs) = B.splitAt n str+                in partition' (x:acc) n xs+            encrypt (bytes, acc) chunk =+                let c = pack $ zipWith xor chunk (md5 $ secret <> bytes)+                in (c, acc <> c)++-- | Encode MS-MPPE-Encryption-Policy as per [RFC2548]+encodeMPPEEncryptionPolicyAttribute :: Word32         -- ^ Policy value+                                    -> PacketAttribute+encodeMPPEEncryptionPolicyAttribute policy =+    vendorSpecificAttribute . runPut $ do+      putWord8 7 -- for MS-MPPE-Encryption-Policy.+      putWord8 6 -- fixed length+      putWord32be policy++-- | Encode MS-MPPE-Encryption-Types as per [RFC2548]+encodeMPPEEncryptionTypesAttribute :: Word32+                                   -> PacketAttribute -- ^ Encryption types value (see RFC)+encodeMPPEEncryptionTypesAttribute types =+    vendorSpecificAttribute . runPut $ do+      putWord8 8 -- for MS-MPPE-Encryption-Types.+      putWord8 6 -- fixed length+      putWord32be types
src/Network/RADIUS/Types.hs view
@@ -95,7 +95,7 @@   | FramedIPXNetworkAttribute       { getFramedIPXNetworkAttribute       :: Word32            }   | StateAttribute                  { getStateAttribute                  :: ByteString        }   | ClassAttribute                  { getClassAttribute                  :: ByteString        }-  | VendorSpecificAttribute         { getVendorSpecificAttributeId       :: Word32,+  | VendorSpecificAttribute         { getVendorIdAttribute               :: Word32,                                       getVendorSpecificAttribute         :: ByteString        }   | SessionTimeoutAttribute         { getSessionTimeoutAttribute         :: Word32            }   | IdleTimeoutAttribute            { getIdleTimeoutAttribute            :: Word32            }