summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--KeyRing.hs29
-rw-r--r--kiki.cabal3
-rw-r--r--kiki.hs41
3 files changed, 53 insertions, 20 deletions
diff --git a/KeyRing.hs b/KeyRing.hs
index d4bb099..620f9ad 100644
--- a/KeyRing.hs
+++ b/KeyRing.hs
@@ -45,6 +45,7 @@ module KeyRing
45 , KeyFilter(..) 45 , KeyFilter(..)
46 -- * Results of a KeyRing Operation 46 -- * Results of a KeyRing Operation
47 , KeyRingRuntime(..) 47 , KeyRingRuntime(..)
48 , MappedPacket(..)
48 , KeyDB 49 , KeyDB
49 , KeyData(..) 50 , KeyData(..)
50 , SubKey(..) 51 , SubKey(..)
@@ -97,6 +98,7 @@ module KeyRing
97 , keyPacket 98 , keyPacket
98 , KeySpec(..) 99 , KeySpec(..)
99 , getHostnames 100 , getHostnames
101 , secretPemFromPacket
100 ) where 102 ) where
101 103
102import System.Environment 104import System.Environment
@@ -132,7 +134,7 @@ import qualified Data.Map as Map
132import qualified Data.ByteString.Lazy as L ( unpack, null, readFile, writeFile 134import qualified Data.ByteString.Lazy as L ( unpack, null, readFile, writeFile
133 , ByteString, toChunks, hGetContents, hPut, concat, fromChunks, splitAt 135 , ByteString, toChunks, hGetContents, hPut, concat, fromChunks, splitAt
134 , index, break, pack ) 136 , index, break, pack )
135import qualified Data.ByteString as S ( ByteString, unpack, splitAt, concat, cons, spanEnd, hGetContents, readFile, breakSubstring, drop, length, null, putStr, singleton, unfoldr, reverse ) 137import qualified Data.ByteString as S ( ByteString, unpack, splitAt, concat, cons, spanEnd, hGetContents, readFile, breakSubstring, drop, length, null, hPutStr, singleton, unfoldr, reverse )
136import qualified Codec.Binary.Base32 as Base32 138import qualified Codec.Binary.Base32 as Base32
137import qualified Codec.Binary.Base64 as Base64 139import qualified Codec.Binary.Base64 as Base64
138#if !defined(VERSION_cryptonite) 140#if !defined(VERSION_cryptonite)
@@ -166,7 +168,7 @@ import Foreign.C.Error ( throwErrnoIfMinus1_ )
166import Foreign.Storable 168import Foreign.Storable
167#endif 169#endif
168import System.FilePath ( takeDirectory ) 170import System.FilePath ( takeDirectory )
169import System.IO (hPutStrLn,withFile,IOMode(..), Handle, hPutStr) 171import System.IO (hPutStrLn,withFile,IOMode(..), Handle, hPutStr, stderr)
170import Data.IORef 172import Data.IORef
171import System.Posix.IO ( fdToHandle ) 173import System.Posix.IO ( fdToHandle )
172import qualified Data.Traversable as Traversable 174import qualified Data.Traversable as Traversable
@@ -1181,7 +1183,7 @@ cachedContents maybePrompt ctx fd = do
1181 pw <- readIORef ref 1183 pw <- readIORef ref
1182 flip (flip maybe return) pw $ do 1184 flip (flip maybe return) pw $ do
1183 if fd == FileDesc 0 then case maybePrompt of 1185 if fd == FileDesc 0 then case maybePrompt of
1184 Just prompt -> S.putStr prompt 1186 Just prompt -> S.hPutStr stderr prompt
1185 Nothing -> return () 1187 Nothing -> return ()
1186 else return () 1188 else return ()
1187 pw <- fmap trimCR $ readInputFileS ctx fd 1189 pw <- fmap trimCR $ readInputFileS ctx fd
@@ -2059,20 +2061,23 @@ rsaPrivateKeyFromPacket pkt@(SecretKeyPacket {}) = do
2059 , rsaCoefficient = coefficient } 2061 , rsaCoefficient = coefficient }
2060rsaPrivateKeyFromPacket _ = Nothing 2062rsaPrivateKeyFromPacket _ = Nothing
2061 2063
2062 2064secretPemFromPacket packet =
2063writeKeyToFile ::
2064 Bool -> FileType -> InputFile -> Packet -> IO [(InputFile, KikiReportAction)]
2065writeKeyToFile False PEMFile fname packet = do
2066 case key_algorithm packet of 2065 case key_algorithm packet of
2067 RSA -> do 2066 RSA -> do
2068 flip (maybe (return [])) 2067 rsa <- rsaPrivateKeyFromPacket packet -- RSAPrivateKey
2069 (rsaPrivateKeyFromPacket packet) -- RSAPrivateKey
2070 $ \rsa -> do
2071 let asn1 = toASN1 rsa [] 2068 let asn1 = toASN1 rsa []
2072 bs = encodeASN1 DER asn1 2069 bs = encodeASN1 DER asn1
2073 dta = Base64.encode (L.unpack bs) 2070 dta = Base64.encode (L.unpack bs)
2074 output = writePEM "RSA PRIVATE KEY" dta 2071 output = writePEM "RSA PRIVATE KEY" dta
2075 stamp = toEnum . fromEnum $ timestamp packet 2072 Just output
2073 algo -> Nothing
2074
2075writeKeyToFile ::
2076 Bool -> FileType -> InputFile -> Packet -> IO [(InputFile, KikiReportAction)]
2077writeKeyToFile False PEMFile fname packet = do
2078 case secretPemFromPacket packet of
2079 Just output -> do
2080 let stamp = toEnum . fromEnum $ timestamp packet
2076 handleIO_ (return [(fname, FailedFileWrite)]) $ do 2081 handleIO_ (return [(fname, FailedFileWrite)]) $ do
2077 saved_mask <- setFileCreationMask 0o077 2082 saved_mask <- setFileCreationMask 0o077
2078 -- Note: The key's timestamp is included in it's fingerprint. 2083 -- Note: The key's timestamp is included in it's fingerprint.
@@ -2080,7 +2085,7 @@ writeKeyToFile False PEMFile fname packet = do
2080 writeStamped (InputFileContext "" "") fname stamp output 2085 writeStamped (InputFileContext "" "") fname stamp output
2081 setFileCreationMask saved_mask 2086 setFileCreationMask saved_mask
2082 return [(fname, ExportedSubkey)] 2087 return [(fname, ExportedSubkey)]
2083 algo -> return [(fname, UnableToExport algo $ fingerprint packet)] 2088 Nothing -> return [(fname, UnableToExport (key_algorithm packet) $ fingerprint packet)]
2084 2089
2085writeKeyToFile False DNSPresentation fname packet = do 2090writeKeyToFile False DNSPresentation fname packet = do
2086 case key_algorithm packet of 2091 case key_algorithm packet of
diff --git a/kiki.cabal b/kiki.cabal
index 3658aa4..176d09c 100644
--- a/kiki.cabal
+++ b/kiki.cabal
@@ -30,7 +30,8 @@ Executable kiki
30 bytestring -any, binary -any, 30 bytestring -any, binary -any,
31 unix, time, 31 unix, time,
32 containers -any, process -any, filepath -any, 32 containers -any, process -any, filepath -any,
33 network -any, old-locale -any, zlib -any 33 network -any, old-locale -any, zlib -any,
34 tar
34 if !flag(cryptonite) 35 if !flag(cryptonite)
35 Build-Depends: crypto-pubkey >=0.2.3, cryptohash -any, 36 Build-Depends: crypto-pubkey >=0.2.3, cryptohash -any,
36 crypto-pubkey-types -any 37 crypto-pubkey-types -any
diff --git a/kiki.hs b/kiki.hs
index d58ef2a..087e24f 100644
--- a/kiki.hs
+++ b/kiki.hs
@@ -10,6 +10,7 @@ module Main ( main ) where
10 10
11import Control.Applicative 11import Control.Applicative
12import Control.Monad 12import Control.Monad
13import Control.Monad.Fix
13import Data.ASN1.BinaryEncoding 14import Data.ASN1.BinaryEncoding
14import Data.ASN1.Encoding 15import Data.ASN1.Encoding
15import Data.ASN1.Types 16import Data.ASN1.Types
@@ -268,6 +269,9 @@ partitionStaticArguments specs args = psa args
268 psa [] = ([],[]) 269 psa [] = ([],[])
269 psa (a:as) = 270 psa (a:as) =
270 case Map.lookup a smap of 271 case Map.lookup a smap of
272 Nothing | (k,'=':v) <- break (=='=') a
273 , Just 1 <- Map.lookup k smap
274 -> first ([k,v]:) $ psa as
271 Nothing -> second (a:) $ psa as 275 Nothing -> second (a:) $ psa as
272 Just n -> first ((a:take n as):) $ psa (drop n as) 276 Just n -> first ((a:take n as):) $ psa (drop n as)
273 277
@@ -1729,25 +1733,48 @@ tarC (sargs,margs) = do
1729 KikiSuccess rt -> do 1733 KikiSuccess rt -> do
1730 CTime pubtime <- modificationTime <$> getFileStatus (rtPubring rt) 1734 CTime pubtime <- modificationTime <$> getFileStatus (rtPubring rt)
1731 let keyspec = concat . take 1 <$> Map.lookup "--secrets" margs 1735 let keyspec = concat . take 1 <$> Map.lookup "--secrets" margs
1732 fs = tarContent rt keyspec build_ipsec (build_ssh rt pubtime) (error "todo") 1736 fs = tarContent rt keyspec build_ipsec (build_ssh rt pubtime) (build_secret rt)
1733 es = do 1737 es = do
1734 (n,(epoch_time_int64,bs)) <- fs 1738 (n,(epoch_time_int64,ebs)) <- fs
1735 entry <- either (const []) (return . flip Tar.fileEntry bs) $ Tar.toTarPath False n 1739 let mktar' = mktar n epoch_time_int64
1736 return $ entry { Tar.entryTime = epoch_time_int64 } 1740 return $ case ebs of
1737 tarbs = Tar.write es 1741 Right bs -> return $ either (const Nothing) Just $ mktar' bs
1742 Left iombs -> do
1743 mbs <- iombs
1744 case mbs of
1745 Nothing -> return Nothing
1746 Just bs -> return $ either (const Nothing) Just $ mktar' bs
1747 tarbs <- Tar.write . mapMaybe id <$> sequence es
1738 L.putStr tarbs 1748 L.putStr tarbs
1739 err -> putStrLn $ errorString err 1749 err -> putStrLn $ errorString err
1740 where 1750 where
1741 build_ipsec ns addr ipsec sigs 1751 build_ipsec ns addr ipsec sigs
1742 = ( fromIntegral $ timestamp ipsec 1752 = ( fromIntegral $ timestamp ipsec
1743 , Char8.pack $ fromJust $ pemFromPacket ipsec) 1753 , Right $ Char8.pack $ fromJust $ pemFromPacket ipsec)
1744 build_ssh rt timestamp sshs = (timestamp, Char8.unlines $ map knownhost sshs) 1754 build_ssh rt timestamp sshs = (timestamp, Right $ Char8.unlines $ map knownhost sshs)
1745 where 1755 where
1746 knownhost (kk,hostkey,sigs) = Char8.intercalate "," ns <> " " <> Char8.pack (sshblobFromPacket hostkey) 1756 knownhost (kk,hostkey,sigs) = Char8.intercalate "," ns <> " " <> Char8.pack (sshblobFromPacket hostkey)
1747 where 1757 where
1748 ns = onames ++ others 1758 ns = onames ++ others
1749 (_,(onames,others)) = getHostnames $ rtKeyDB rt Map.! kk 1759 (_,(onames,others)) = getHostnames $ rtKeyDB rt Map.! kk
1750 1760
1761 build_secret rt k = ( fromIntegral $ timestamp k
1762 , Left $ fmap Char8.pack . (>>= secretPemFromPacket) <$> decrypt rt k )
1763
1764 mktar n epoch_time_int64 bs = do
1765 torpath <- Tar.toTarPath False n
1766 Right $ (Tar.fileEntry torpath bs) { Tar.entryTime = epoch_time_int64 }
1767
1768 decrypt :: KeyRingRuntime -> Packet -> IO (Maybe Packet)
1769 decrypt rt k@SecretKeyPacket { symmetric_algorithm = Unencrypted } = return $ Just k
1770 decrypt rt k = do
1771 r <- rtPassphrases rt (MappedPacket k Map.empty)
1772 case r of
1773 KikiSuccess p -> return $ Just p
1774 _ -> do
1775 hPutStrLn stderr $ "Failed to decrypt "++fingerprint k++"."
1776 return Nothing
1777
1751minimalOp :: CommonArgsParsed -> KeyRingOperation 1778minimalOp :: CommonArgsParsed -> KeyRingOperation
1752minimalOp cap = op 1779minimalOp cap = op
1753 where 1780 where