diff options
author | joe <joe@jerkface.net> | 2014-05-05 20:32:36 -0400 |
---|---|---|
committer | joe <joe@jerkface.net> | 2014-05-05 20:32:36 -0400 |
commit | 67904f836d39cc844f85c2570d5a634d59a8f020 (patch) | |
tree | 1efc2f5cd2b002cfb92298724064f54d40e2af0a /kiki.hs | |
parent | 50da2308364e1c27d8d3fb7230f6e188b36a73b4 (diff) |
The 'merge' command exposes low-level KeyRingOperation functionality.
Diffstat (limited to 'kiki.hs')
-rw-r--r-- | kiki.hs | 107 |
1 files changed, 107 insertions, 0 deletions
@@ -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 | ||
875 | kiki "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 | |||
967 | splitArg :: String -> Either (String,Maybe String) String | ||
968 | splitArg 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 | |||
875 | commands :: [(String,String)] | 981 | commands :: [(String,String)] |
876 | commands = | 982 | commands = |
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 | ||
889 | main = do | 996 | main = do |