summaryrefslogtreecommitdiff
path: root/lib/GnuPGAgent.hs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/GnuPGAgent.hs')
-rw-r--r--lib/GnuPGAgent.hs41
1 files changed, 34 insertions, 7 deletions
diff --git a/lib/GnuPGAgent.hs b/lib/GnuPGAgent.hs
index 8bffd1b..165fdf2 100644
--- a/lib/GnuPGAgent.hs
+++ b/lib/GnuPGAgent.hs
@@ -3,6 +3,8 @@
3{-# LANGUAGE PatternGuards #-} 3{-# LANGUAGE PatternGuards #-}
4module GnuPGAgent 4module GnuPGAgent
5 ( session 5 ( session
6 , Query(..)
7 , QueryMode(..)
6 , getPassphrase 8 , getPassphrase
7 , clearPassphrase 9 , clearPassphrase
8 , quit ) where 10 , quit ) where
@@ -44,6 +46,12 @@ session = do
44 connect sock (SockAddrUnix (gpghome ++ "/S.gpg-agent")) 46 connect sock (SockAddrUnix (gpghome ++ "/S.gpg-agent"))
45 agent <- socketToHandle sock ReadWriteMode 47 agent <- socketToHandle sock ReadWriteMode
46 hSetBuffering agent LineBuffering 48 hSetBuffering agent LineBuffering
49 lookupEnv "DISPLAY" >>= \case
50 Just display -> do hPutStrLn agent ("option putenv DISPLAY="++display)
51 _ <- hGetLine agent
52 return ()
53 Nothing -> return ()
54 -- TODO: GPG_TTY
47 return $ Just $ GnuPGAgent agent 55 return $ Just $ GnuPGAgent agent
48 Nothing -> do 56 Nothing -> do
49 hPutStrLn stderr "Unable to find home directory." 57 hPutStrLn stderr "Unable to find home directory."
@@ -64,23 +72,42 @@ clearPassphrase agent key = do
64 let cmd = "clear_passphrase "++fingerprint key 72 let cmd = "clear_passphrase "++fingerprint key
65 hPutStrLn (agentHandle agent) cmd 73 hPutStrLn (agentHandle agent) cmd
66 74
67getPassphrase :: GnuPGAgent -> Bool -> Packet -> String -> Maybe Packet -> IO (Maybe String) 75data Query = Query
68getPassphrase agent ask key uid masterkey = do 76 { queryPacket :: Packet
69 let askopt = if ask then "" else "--no-ask " 77 , queryUID :: String
70 (er,pr,desc) = prompts key uid masterkey 78 , queryMainKey :: Maybe Packet
79 }
80 deriving Show
81
82data QueryMode = AskNot | AskAgain String | Ask
83 deriving (Show,Eq,Ord)
84
85getPassphrase :: GnuPGAgent -> QueryMode -> Query -> IO (Maybe String)
86getPassphrase agent ask (Query key uid masterkey) = do
87 let (er0,pr,desc) = prompts key uid masterkey
88 (er,askopt) = case ask of
89 AskNot -> (er0,"--no-ask")
90 AskAgain ermsg -> (ermsg,"")
91 Ask -> (er0,"")
71 cmd = "get_passphrase "++askopt++fingerprint key++" "++unwords (map percentPlusEscape [er,pr,desc]) 92 cmd = "get_passphrase "++askopt++fingerprint key++" "++unwords (map percentPlusEscape [er,pr,desc])
72 putStrLn cmd 93 -- putStrLn cmd
73 hPutStrLn (agentHandle agent) cmd 94 hPutStrLn (agentHandle agent) cmd
74 r0 <- hGetLine (agentHandle agent) 95 r0 <- hGetLine (agentHandle agent)
96 -- putStrLn $ "agent says: " ++ r0
75 case takeWhile (/=' ') r0 of 97 case takeWhile (/=' ') r0 of
76 "OK" -> hGetLine (agentHandle agent) >>= unhex . drop 3 98 "OK" -> hGetLine (agentHandle agent) >>= unhex . drop 3
77 where 99 where
78#if defined(VERSION_memory) 100#if defined(VERSION_memory)
79 unhex hx = case convertFromBase Base16 (S8.pack hx) of 101 unhex hx = case convertFromBase Base16 (S8.pack hx) of
80 Left e -> return Nothing 102 Left e -> do
103 -- Useful for debugging but insecure generally ;)
104 -- putStrLn $ "convertFromBase error for input "++show hx++": "++show e
105 return Nothing
81 Right bs -> return $ Just $ S8.unpack bs 106 Right bs -> return $ Just $ S8.unpack bs
82#elif defined(VERSION_dataenc) 107#elif defined(VERSION_dataenc)
83 unhex hx = return $ fmap (map $ chr . fromIntegral) $ Base16.decode hx 108 unhex hx = maybe (return () {- putStrLn $ "dataenc error for input "++show hx -})
109 return
110 $ fmap (map $ chr . fromIntegral) $ Base16.decode hx
84#endif 111#endif
85 "ERR" -> return Nothing 112 "ERR" -> return Nothing
86 113