summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Cady <d@jerkface.net>2016-01-20 12:07:30 -0500
committerAndrew Cady <d@jerkface.net>2016-01-20 12:07:30 -0500
commit1d1190635c6de041eb9490d530cd32cad31c25e1 (patch)
tree56eb6ba648d9f3ce92c81e63bb66bb7df157c66d
parent507e230d6ce9304b359d6a2811d7b32760e3bc07 (diff)
remove 'writeBody'; minor cleanups
-rw-r--r--acme.hs65
1 files changed, 31 insertions, 34 deletions
diff --git a/acme.hs b/acme.hs
index 54bf324..ebcbe65 100644
--- a/acme.hs
+++ b/acme.hs
@@ -65,42 +65,43 @@ genKey privKeyFile = readProcess "openssl" (words "genrsa 4096 -out" ++ [privKey
65 65
66go :: CmdOpts -> IO () 66go :: CmdOpts -> IO ()
67go (CmdOpts privKeyFile domain email termOverride) = do 67go (CmdOpts privKeyFile domain email termOverride) = do
68 let terms = fromMaybe defaultTerms termOverride 68
69 doesFileExist privKeyFile >>= flip unless (genKey privKeyFile) 69 doesFileExist privKeyFile >>= flip unless (genKey privKeyFile)
70
70 priv <- readFile privKeyFile >>= flip readPrivateKey PwTTY 71 priv <- readFile privKeyFile >>= flip readPrivateKey PwTTY
71 pub <- maybe (return Nothing) (rsaCopyPublic >=> return . Just) (toKeyPair priv :: Maybe RSAKeyPair) 72 mbPub <- maybe (return Nothing) (rsaCopyPublic >=> return . Just)
72 case pub of 73 (toKeyPair priv :: Maybe RSAKeyPair)
73 Nothing -> error "Error: failed to parse RSA key."
74 Just (userKey :: RSAPubKey) -> do
75 74
76 Just nonce_ <- getNonce 75 let terms = fromMaybe defaultTerms termOverride
76 pub :: RSAPubKey
77 pub = fromMaybe (error "Error: failed to parse RSA key.") mbPub
77 78
78 let protected = b64 (header userKey nonce_) 79 Just nonce_ <- getNonce
79 80
80 -- Create user account 81 -- Create user account
81 forM_ email $ \m -> signPayload "registration" priv userKey protected (registration m terms) 82 forM_ email $ \m ->
83 LB.writeFile "registration.body" =<< signPayload priv pub nonce_ (registration m terms)
82 84
83 -- Obtain a challenge 85 -- Obtain a challenge
84 signPayload "challenge-request" priv userKey protected (authz domain) 86 LB.writeFile "challenge-request.body" =<< signPayload priv pub nonce_ (authz domain)
85 87
86 -- Answser the challenge 88 -- Answser the challenge
87 let thumb = thumbprint (JWK (rsaE userKey) "RSA" (rsaN userKey)) 89 let thumb = thumbprint (JWK (rsaE pub) "RSA" (rsaN pub))
88 -- Extracted from POST response above. 90 -- Extracted from POST response above.
89 token = "DjyJpI3HVWAmsAwMT5ZFpW8dj19cel6ml6qaBUeGpCg" 91 token = "DjyJpI3HVWAmsAwMT5ZFpW8dj19cel6ml6qaBUeGpCg"
90 thumbtoken = toStrict (LB.fromChunks [token, ".", thumb]) 92 thumbtoken = toStrict (LB.fromChunks [token, ".", thumb])
91 93
92 putStrLn ("Serve http://" ++ domain ++ "/.well-known/acme-challenge/" ++ 94 putStrLn ("Serve http://" ++ domain ++ "/.well-known/acme-challenge/" ++ BC.unpack token)
93 BC.unpack token) 95 putStrLn ("With content:\n" ++ BC.unpack thumbtoken)
94 putStrLn ("With content:\n" ++ BC.unpack thumbtoken)
95 96
96 -- Notify Let's Encrypt we answsered the challenge 97 -- Notify Let's Encrypt we answsered the challenge
97 signPayload "challenge-response" priv userKey protected (challenge thumbtoken) 98 LB.writeFile "challenge-response.body" =<< signPayload priv pub nonce_ (challenge thumbtoken)
98 99
99 -- Wait for challenge validation 100 -- Wait for challenge validation Send a CSR and get a certificate
101 csr_ <- B.readFile (domain ++ ".csr.der")
102 LB.writeFile "csr-request.body" =<< signPayload priv pub nonce_ (csr csr_)
100 103
101 -- Send a CSR and get a certificate 104 return ()
102 csr_ <- B.readFile (domain ++ ".csr.der")
103 signPayload "csr-request" priv userKey protected (csr csr_)
104 105
105data Directory = Directory { 106data Directory = Directory {
106 _newCert :: String, 107 _newCert :: String,
@@ -122,16 +123,12 @@ getNonce = fmap _nonce <$> getDirectory directoryUrl
122 123
123-------------------------------------------------------------------------------- 124--------------------------------------------------------------------------------
124-- | Sign and write a payload to a file with a nonce-protected header. 125-- | Sign and write a payload to a file with a nonce-protected header.
125signPayload :: (RSAKey k, KeyPair kp) => String -> kp -> k -> ByteString -> ByteString -> IO () 126signPayload :: (RSAKey k, KeyPair kp) => kp -> k -> String -> ByteString -> IO LC.ByteString
126signPayload name priv key protected payload = withOpenSSL $ do 127signPayload priv pub nonce_ payload = withOpenSSL $ do
128 let protected = b64 (header pub nonce_)
127 Just dig <- getDigestByName "SHA256" 129 Just dig <- getDigestByName "SHA256"
128 sig <- signBS dig priv (B.concat [protected, ".", payload]) 130 sig <- b64 <$> signBS dig priv (B.concat [protected, ".", payload])
129 writeBody name key protected payload sig 131 return $ buildBody pub protected payload sig
130
131-- | Write a signed payload to a file. It can be used as the body of a POST
132-- request.
133writeBody :: RSAKey k => String -> k -> ByteString -> ByteString -> ByteString -> IO ()
134writeBody name key protected payload sig = LB.writeFile (name ++ ".body") $ buildBody key protected payload sig
135 132
136buildBody :: RSAKey k => k -> ByteString -> ByteString -> ByteString -> LC.ByteString 133buildBody :: RSAKey k => k -> ByteString -> ByteString -> ByteString -> LC.ByteString
137buildBody key protected payload sig = encode (Request (header' key) protected payload sig) 134buildBody key protected payload sig = encode (Request (header' key) protected payload sig)