summaryrefslogtreecommitdiff
path: root/kiki.hs
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2014-05-05 20:32:36 -0400
committerjoe <joe@jerkface.net>2014-05-05 20:32:36 -0400
commit67904f836d39cc844f85c2570d5a634d59a8f020 (patch)
tree1efc2f5cd2b002cfb92298724064f54d40e2af0a /kiki.hs
parent50da2308364e1c27d8d3fb7230f6e188b36a73b4 (diff)
The 'merge' command exposes low-level KeyRingOperation functionality.
Diffstat (limited to 'kiki.hs')
-rw-r--r--kiki.hs107
1 files changed, 107 insertions, 0 deletions
diff --git a/kiki.hs b/kiki.hs
index cae8ae8..f99a928 100644
--- a/kiki.hs
+++ b/kiki.hs
@@ -872,6 +872,112 @@ kiki "show" args = do
872 forM_ report $ \(fname,act) -> do 872 forM_ report $ \(fname,act) -> do
873 putStrLn $ fname ++ ": " ++ reportString act 873 putStrLn $ fname ++ ": " ++ reportString act
874 874
875kiki "merge" args = do
876 let op = snd $ foldl' buildOp (flow,noop) args
877 noop = KeyRingOperation
878 { opFiles = Map.empty
879 , opTransforms = []
880 , opHome = Nothing
881 , opPassphrases = []
882 }
883 flow = StreamInfo
884 { access = AutoAccess
885 , typ = KeyRingFile
886 , spill = KF_None
887 , fill = KF_None
888 , initializer = Nothing
889 , transforms = []
890 }
891 updateFlow fil spil mtch flow = spill' $ fill' $ flow
892 where
893 fill' flow = flow { fill = if fil then val else KF_None }
894 spill' flow = flow { spill = if spil then val else KF_None }
895 val = either (\subkeys -> if subkeys then KF_Subkeys else KF_All)
896 KF_Match
897 mtch
898 parseFlow spec =
899 if null bads
900 then Just ( ( "spill" `elem` goods
901 || "sync" `elem` goods
902 , "fill" `elem` goods
903 || "sync" `elem` goods )
904 , maybe (Left $ "subkeys" `elem` goods)
905 Right
906 match )
907 else Nothing
908 where
909 ws = case groupBy (\_ c->c/=',') spec of
910 w:xs -> w:map (drop 1) xs
911 [] -> []
912 (goods,bads) = partition acceptable ws
913 acceptable "spill" = True
914 acceptable "fill" = True
915 acceptable "sync" = True
916 acceptable "subkeys" = True
917 acceptable s | "match=" `isPrefixOf` s = True
918 acceptable _ = False
919 match = listToMaybe $ do
920 m <- filter ("match=" `isPrefixOf`) goods
921 return $ drop 6 m
922
923 buildOp (flow,op) arg =
924 case splitArg arg of
925 Right fname ->
926 ( flow
927 , op { opFiles= Map.insert (ArgFile fname) flow (opFiles op) })
928 Left ("autosign",Nothing) ->
929 if Map.null (opFiles op)
930 then (flow, op { opTransforms = opTransforms op ++ [Autosign] })
931 else (flow { transforms = transforms flow ++ [Autosign] }, op)
932 Left ("noautosign",Nothing) ->
933 ( flow { transforms = filter (/=Autosign) (transforms flow) }
934 , op { opTransforms = filter (/=Autosign) (opTransforms op) } )
935 Left ("create",Just cmd) ->
936 ( flow { initializer = if null cmd then Nothing else Just cmd }
937 , op )
938 Left ("type",Just "keyring") -> ( flow { typ = KeyRingFile }, op )
939 Left ("type",Just "pem" ) -> ( flow { typ = PEMFile }, op )
940 Left ("type",Just "wallet" ) -> ( flow { typ = WalletFile }, op )
941 Left ("type",Just "hosts" ) -> ( flow { typ = Hosts }, op )
942 Left ("access",Just "public") -> ( flow { access = Pub }, op )
943 Left ("access",Just "secret") -> ( flow { access = Sec }, op )
944 Left ("access",Just "auto") -> ( flow { access = AutoAccess }, op )
945 Left ("home",mb) ->
946 ( flow
947 , op { opFiles = Map.insert HomePub flow { access=Pub }
948 $ Map.insert HomeSec flow { access=Sec }
949 $ opFiles op
950 , opHome = opHome op `mplus` mb
951 }
952 )
953 Left ("flow",Just flowspec) ->
954 case parseFlow flowspec of
955 Just ( (fil,spil), mtch ) ->
956 ( updateFlow fil spil mtch flow
957 , op )
958 Nothing -> error "Valid flow words are: spill,fill,sync,subkeys or match=KEYSPEC"
959 Left (option,_) -> error $ "Unrecognized option: " ++ option
960 KikiResult rt report <- runKeyRing op
961 case rt of
962 KikiSuccess rt -> return ()
963 err -> putStrLn $ errorString err
964 forM_ report $ \(fname,act) -> do
965 putStrLn $ fname ++ ": " ++ reportString act
966
967splitArg :: String -> Either (String,Maybe String) String
968splitArg arg =
969 case hyphens of
970 "" -> Right name
971 "-" -> error $ "Unrecognized option: " ++ arg
972 _ -> Left $ parseLongOption name
973 where
974 (hyphens, name) = span (=='-') arg
975 parseLongOption name = (key,val v)
976 where
977 (key,v) = break (=='=') name
978 val ('=':vs) = Just vs
979 val _ = Nothing
980
875commands :: [(String,String)] 981commands :: [(String,String)]
876commands = 982commands =
877 [ ( "help", "display usage information" ) 983 [ ( "help", "display usage information" )
@@ -884,6 +990,7 @@ commands =
884 , ( "export-secret", "export (both public and secret) information into your keyring" ) 990 , ( "export-secret", "export (both public and secret) information into your keyring" )
885 , ( "export-public", "import (public) information into your keyring" ) 991 , ( "export-public", "import (public) information into your keyring" )
886 , ( "working-key", "show the current working master key and its subkeys" ) 992 , ( "working-key", "show the current working master key and its subkeys" )
993 , ( "merge", "low level import/export operation" )
887 ] 994 ]
888 995
889main = do 996main = do