diff options
author | Joey Hess <joeyh@joeyh.name> | 2017-04-29 12:23:29 -0400 |
---|---|---|
committer | Joey Hess <joeyh@joeyh.name> | 2017-04-29 13:07:48 -0400 |
commit | 237b94f6c687675215f78fba28d7e003a2b9ab7d (patch) | |
tree | e4c2c6144e1d5563218b8686cee508146a1370c8 /Gpg.hs | |
parent | 46245781f26d49037102a4c74001f47a345fa567 (diff) | |
download | debug-me-237b94f6c687675215f78fba28d7e003a2b9ab7d.tar.gz |
add Gpg web of trust parser
Diffstat (limited to 'Gpg.hs')
-rw-r--r-- | Gpg.hs | 39 |
1 files changed, 29 insertions, 10 deletions
@@ -1,5 +1,3 @@ -{-# LANGUAGE OverloadedStrings, RankNTypes, DeriveGeneric #-} - module Gpg where import Val @@ -10,11 +8,15 @@ import Crypto import Data.ByteArray (convert) import qualified Data.ByteString as B import System.IO +import System.Posix.IO hiding (createPipe) import System.Process import System.Exit import Data.List import Control.Exception import System.Directory +import Control.Concurrent.Async + +newtype GpgKeyId = GpgKeyId String newtype GpgSign = GpgSign Bool @@ -47,13 +49,20 @@ gpgSign pk = do ExitSuccess -> return $ GpgSigned pk sig ExitFailure _ -> error "gpg failed" --- | Verify the gpg signature. The key will be retrieved from a keyserver --- if possible. Gpg outputs to stderr information about who signed the +-- | Verify the gpg signature and return the keyid that signed it. +-- Also makes sure that the gpg signed data is the hash of the +-- debug-me PublicKey. +-- +-- The gpg key will be retrieved from a keyserver if necessary. +-- +-- Gpg outputs to stderr information about who signed the -- data, so that will be visible to the user when eg, prompting -- them if they want to accept a connection from that person. -gpgVerify :: [String] -> PerhapsSigned PublicKey -> IO Bool -gpgVerify _ (UnSigned _) = return False -gpgVerify gpgopts (GpgSigned pk (GpgSig (Val sig))) = do +gpgVerify :: [String] -> PerhapsSigned PublicKey -> IO (Maybe GpgKeyId) +gpgVerify _ (UnSigned _) = return Nothing +gpgVerify gpgopts (GpgSigned pk (GpgSig (Val sig))) = do + (statusreadh, statuswriteh) <- createPipe + statuswritefd <- handleToFd statuswriteh -- This relies on gpgSign using --clearsign, so on successful -- verification, the JSON encoded PublicKey is output to gpg's -- stdout. @@ -62,14 +71,17 @@ gpgVerify gpgopts (GpgSigned pk (GpgSig (Val sig))) = do { std_in = CreatePipe , std_out = CreatePipe } + closeFd statuswritefd B.hPut hin sig hClose hin hSetBinaryMode hout True - signeddata <- B.hGetContents hout + (signeddata, gpgkeyid) <- B.hGetContents hout + `concurrently` (parseStatusFd <$> hGetContents statusreadh) st <- waitForProcess pid return $ case st of - ExitFailure _ -> False - ExitSuccess -> val (hashValue (hash pk)) == signeddata + ExitSuccess + | val (hashValue (hash pk)) == signeddata -> gpgkeyid + _ -> Nothing where extraopts = if any ("--keyserver" `isPrefixOf`) gpgopts then gpgopts @@ -81,3 +93,10 @@ defaultKeyServers = [ "pool.sks-keyservers.net" , "pgpkeys.mit.edu" ] + +parseStatusFd :: String -> Maybe GpgKeyId +parseStatusFd = go . map words . lines + where + go [] = Nothing + go ((_:"VALIDSIG":keyid:_):_) = Just (GpgKeyId keyid) + go (_:rest) = go rest |