diff options
Diffstat (limited to 'src/Network/ACME.hs')
-rw-r--r-- | src/Network/ACME.hs | 71 |
1 files changed, 45 insertions, 26 deletions
diff --git a/src/Network/ACME.hs b/src/Network/ACME.hs index 85a27e4..2734132 100644 --- a/src/Network/ACME.hs +++ b/src/Network/ACME.hs | |||
@@ -1,4 +1,5 @@ | |||
1 | {-# LANGUAGE FlexibleContexts #-} | 1 | {-# LANGUAGE FlexibleContexts #-} |
2 | {-# LANGUAGE MultiParamTypeClasses #-} | ||
2 | {-# LANGUAGE OverloadedStrings #-} | 3 | {-# LANGUAGE OverloadedStrings #-} |
3 | {-# LANGUAGE ScopedTypeVariables #-} | 4 | {-# LANGUAGE ScopedTypeVariables #-} |
4 | 5 | ||
@@ -9,41 +10,44 @@ | |||
9 | 10 | ||
10 | module Network.ACME where | 11 | module Network.ACME where |
11 | 12 | ||
12 | import Control.Lens hiding (each, (.=)) | 13 | import Control.Arrow |
14 | import Control.Error | ||
15 | import Control.Lens hiding (each, (.=)) | ||
13 | import Control.Monad | 16 | import Control.Monad |
14 | import Control.Monad.RWS.Strict | 17 | import Control.Monad.RWS.Strict |
15 | import Data.Aeson (Value) | 18 | import Control.Monad.Trans.Resource hiding (register) |
16 | import Data.Aeson.Lens hiding (key) | 19 | import Data.Aeson (Value) |
17 | import qualified Data.Aeson.Lens as JSON | 20 | import Data.Aeson.Lens hiding (key) |
18 | import Data.ByteString (ByteString) | 21 | import qualified Data.Aeson.Lens as JSON |
19 | import qualified Data.ByteString.Char8 as BC | 22 | import Data.ByteString (ByteString) |
20 | import qualified Data.ByteString.Lazy as LB | 23 | import qualified Data.ByteString.Char8 as BC |
21 | import qualified Data.ByteString.Lazy.Char8 as LC | 24 | import qualified Data.ByteString.Lazy as LB |
25 | import qualified Data.ByteString.Lazy.Char8 as LC | ||
22 | import Data.Coerce | 26 | import Data.Coerce |
23 | import Data.String (fromString) | 27 | import Data.List |
24 | import qualified Data.Text as T | 28 | import Data.String (fromString) |
25 | import Data.Text.Encoding (decodeUtf8, encodeUtf8) | 29 | import qualified Data.Text as T |
26 | import Data.Time.Clock.POSIX (getPOSIXTime) | 30 | import Data.Text.Encoding (decodeUtf8, encodeUtf8) |
31 | import Data.Time.Clock.POSIX (getPOSIXTime) | ||
27 | import Network.ACME.Encoding | 32 | import Network.ACME.Encoding |
28 | import Network.Wreq (Response, checkStatus, defaults, | ||
29 | responseBody, responseHeader, | ||
30 | responseStatus, statusCode, | ||
31 | statusMessage) | ||
32 | import qualified Network.Wreq as W | ||
33 | import qualified Network.Wreq.Session as WS | ||
34 | import System.Directory | ||
35 | import Text.Email.Validate | ||
36 | import Text.Domain.Validate hiding (validate) | ||
37 | import Network.URI | 33 | import Network.URI |
34 | import Network.Wreq (Response, checkStatus, defaults, | ||
35 | responseBody, responseHeader, | ||
36 | responseStatus, statusCode, | ||
37 | statusMessage) | ||
38 | import qualified Network.Wreq as W | ||
39 | import qualified Network.Wreq.Session as WS | ||
38 | import OpenSSL | 40 | import OpenSSL |
39 | import OpenSSL.EVP.Digest | 41 | import OpenSSL.EVP.Digest |
42 | import OpenSSL.EVP.PKey | ||
43 | import OpenSSL.EVP.Sign hiding (sign) | ||
44 | import OpenSSL.PEM | ||
40 | import OpenSSL.RSA | 45 | import OpenSSL.RSA |
46 | import OpenSSL.X509 (X509, readDerX509) | ||
41 | import OpenSSL.X509.Request | 47 | import OpenSSL.X509.Request |
42 | import OpenSSL.X509 (readDerX509, X509) | 48 | import System.Directory |
43 | import Data.List | 49 | import Text.Domain.Validate hiding (validate) |
44 | import Control.Error | 50 | import Text.Email.Validate |
45 | import Control.Arrow | ||
46 | import Control.Monad.Trans.Resource hiding (register) | ||
47 | 51 | ||
48 | genReq :: Keys -> [DomainName] -> IO CSR | 52 | genReq :: Keys -> [DomainName] -> IO CSR |
49 | genReq _ [] = error "genReq called with zero domains" | 53 | genReq _ [] = error "genReq called with zero domains" |
@@ -59,6 +63,21 @@ genReq (Keys priv pub) domains@(domain:_) = withOpenSSL $ do | |||
59 | where | 63 | where |
60 | nidSubjectAltName = 85 | 64 | nidSubjectAltName = 85 |
61 | 65 | ||
66 | data Keys = Keys RSAKeyPair RSAPubKey | ||
67 | readKeys :: String -> IO (Maybe Keys) | ||
68 | readKeys privKeyData = do | ||
69 | keypair :: SomeKeyPair <- readPrivateKey privKeyData PwTTY | ||
70 | let (priv :: Maybe RSAKeyPair) = toKeyPair keypair | ||
71 | pub <- maybe (return Nothing) (fmap Just . rsaCopyPublic) priv | ||
72 | return $ Keys <$> priv <*> pub | ||
73 | |||
74 | signPayload :: Keys -> String -> ByteString -> IO LC.ByteString | ||
75 | signPayload (Keys priv pub) = signPayload' sign pub | ||
76 | where | ||
77 | sign x = do | ||
78 | Just dig <- getDigestByName "SHA256" | ||
79 | signBS dig priv x | ||
80 | |||
62 | type HttpProvisioner = URI -> ByteString -> ResIO () | 81 | type HttpProvisioner = URI -> ByteString -> ResIO () |
63 | fileProvisioner :: WritableDir -> HttpProvisioner | 82 | fileProvisioner :: WritableDir -> HttpProvisioner |
64 | fileProvisioner challengeDir uri thumbtoken = do | 83 | fileProvisioner challengeDir uri thumbtoken = do |