diff options
-rw-r--r-- | kiki.hs | 105 |
1 files changed, 72 insertions, 33 deletions
@@ -227,6 +227,9 @@ isEmbeddedSignature _ = False | |||
227 | isCertificationSig (CertificationSignature {}) = True | 227 | isCertificationSig (CertificationSignature {}) = True |
228 | isCertificationSig _ = True | 228 | isCertificationSig _ = True |
229 | 229 | ||
230 | isTrust (TrustPacket {}) = True | ||
231 | isTrust _ = False | ||
232 | |||
230 | issuer (IssuerPacket issuer) = Just issuer | 233 | issuer (IssuerPacket issuer) = Just issuer |
231 | issuer _ = Nothing | 234 | issuer _ = Nothing |
232 | backsig (EmbeddedSignaturePacket s) = Just s | 235 | backsig (EmbeddedSignaturePacket s) = Just s |
@@ -783,6 +786,9 @@ data Arguments = | |||
783 | { homedir :: Maybe FilePath | 786 | { homedir :: Maybe FilePath |
784 | , files :: [FilePath] | 787 | , files :: [FilePath] |
785 | } | 788 | } |
789 | | Merge { homedir :: Maybe FilePath | ||
790 | , files :: [FilePath] | ||
791 | } | ||
786 | | DumpPackets { homedir :: Maybe FilePath | 792 | | DumpPackets { homedir :: Maybe FilePath |
787 | , marshal_test :: String | 793 | , marshal_test :: String |
788 | , files :: [FilePath] } | 794 | , files :: [FilePath] } |
@@ -817,22 +823,31 @@ is40digitHex xs = ys == xs && length ys==40 | |||
817 | ishex c = False | 823 | ishex c = False |
818 | 824 | ||
819 | scanPackets [] = [] | 825 | scanPackets [] = [] |
820 | scanPackets (p:ps) = scanl doit (doit (MarkerPacket,MarkerPacket,MarkerPacket) p) ps | 826 | scanPackets (p:ps) = scanl doit (doit (MarkerPacket,MarkerPacket,ret MarkerPacket) p) ps |
821 | where | 827 | where |
822 | doit (top,sub,_) p = | 828 | ret p = (p,Nothing,Nothing) |
829 | doit (top,sub,prev) p = | ||
823 | case p of | 830 | case p of |
824 | _ | isKey p && not (is_subkey p) -> (p,MarkerPacket,p) | 831 | _ | isKey p && not (is_subkey p) -> (p,MarkerPacket,ret p) |
825 | _ | isKey p && is_subkey p -> (top,p,p) | 832 | _ | isKey p && is_subkey p -> (top,p,ret p) |
826 | _ | isUserID p -> (top,p,p) | 833 | _ | isUserID p -> (top,p,ret p) |
827 | _ | otherwise -> (top,sub,p) | 834 | _ | isTrust p -> (top,sub,updateTrust top sub prev p) |
835 | _ | otherwise -> (top,sub,ret p) | ||
828 | 836 | ||
837 | updateTrust top (PublicKeyPacket {}) (pre,a,b) p = (pre,a,Just p) | ||
838 | updateTrust (PublicKeyPacket {}) _ (pre,a,b) p = (pre,a,Just p) | ||
839 | updateTrust _ _ (pre,a,b) p = (pre,Just p,b) | ||
829 | 840 | ||
830 | 841 | ||
842 | type SigAndTrust = ( Packet | ||
843 | , Maybe Packet -- secret trust packet | ||
844 | , Maybe Packet) -- public trust packet | ||
845 | |||
831 | type KeyKey = [Char8.ByteString] | 846 | type KeyKey = [Char8.ByteString] |
832 | data SubKey = SubKey Packet [Packet] | 847 | data SubKey = SubKey Packet [SigAndTrust] |
833 | data KeyData = KeyData Packet -- main key | 848 | data KeyData = KeyData Packet -- main key |
834 | [Packet] -- sigs on main key | 849 | [SigAndTrust] -- sigs on main key |
835 | (Map.Map String [Packet]) -- uids | 850 | (Map.Map String [SigAndTrust]) -- uids |
836 | (Map.Map KeyKey SubKey) -- subkeys | 851 | (Map.Map KeyKey SubKey) -- subkeys |
837 | 852 | ||
838 | type KeyDB = Map.Map KeyKey KeyData | 853 | type KeyDB = Map.Map KeyKey KeyData |
@@ -866,8 +881,8 @@ merge :: Map.Map KeyKey KeyData -> Message -> Map.Map KeyKey KeyData | |||
866 | merge db (Message ps) = foldl mergeit db qs | 881 | merge db (Message ps) = foldl mergeit db qs |
867 | where | 882 | where |
868 | qs = scanPackets ps | 883 | qs = scanPackets ps |
869 | mergeit db (_,_,TrustPacket {}) = db -- Filter TrustPackets | 884 | -- mergeit db (_,_,TrustPacket {}) = db -- Filter TrustPackets |
870 | mergeit db (top,sub,p) | isKey top = Map.alter update (keykey top) db | 885 | mergeit db (top,sub,ptt@(p,sectrust,pubtrust)) | isKey top = Map.alter update (keykey top) db |
871 | where | 886 | where |
872 | update v | isKey p && not (is_subkey p) | 887 | update v | isKey p && not (is_subkey p) |
873 | = case v of | 888 | = case v of |
@@ -879,18 +894,18 @@ merge db (Message ps) = foldl mergeit db qs | |||
879 | update (Just (KeyData key sigs uids subkeys)) | isKey p && is_subkey p | 894 | update (Just (KeyData key sigs uids subkeys)) | isKey p && is_subkey p |
880 | = Just $ KeyData key sigs uids (Map.alter (mergeSubkey p) (keykey p) subkeys) | 895 | = Just $ KeyData key sigs uids (Map.alter (mergeSubkey p) (keykey p) subkeys) |
881 | update (Just (KeyData key sigs uids subkeys)) | isUserID p | 896 | update (Just (KeyData key sigs uids subkeys)) | isUserID p |
882 | = Just $ KeyData key sigs (Map.alter (mergeUid p) (uidkey p) uids) subkeys | 897 | = Just $ KeyData key sigs (Map.alter (mergeUid ptt) (uidkey p) uids) subkeys |
883 | update (Just (KeyData key sigs uids subkeys)) | 898 | update (Just (KeyData key sigs uids subkeys)) |
884 | = case sub of | 899 | = case sub of |
885 | MarkerPacket -> Just $ KeyData key (mergeSig p sigs) uids subkeys | 900 | MarkerPacket -> Just $ KeyData key (mergeSig ptt sigs) uids subkeys |
886 | UserIDPacket {} -> Just $ KeyData key | 901 | UserIDPacket {} -> Just $ KeyData key |
887 | sigs | 902 | sigs |
888 | (Map.alter (mergeUidSig p) (uidkey sub) uids) | 903 | (Map.alter (mergeUidSig ptt) (uidkey sub) uids) |
889 | subkeys | 904 | subkeys |
890 | _ | isKey sub -> Just $ KeyData key | 905 | _ | isKey sub -> Just $ KeyData key |
891 | sigs | 906 | sigs |
892 | uids | 907 | uids |
893 | (Map.alter (mergeSubSig p) (keykey sub) subkeys) | 908 | (Map.alter (mergeSubSig ptt) (keykey sub) subkeys) |
894 | _ -> error $ "Unexpected PGP packet 1: "++(words (show p) >>= take 1) | 909 | _ -> error $ "Unexpected PGP packet 1: "++(words (show p) >>= take 1) |
895 | update _ = error $ "Unexpected PGP packet 2: "++(words (show p) >>= take 1) | 910 | update _ = error $ "Unexpected PGP packet 2: "++(words (show p) >>= take 1) |
896 | 911 | ||
@@ -900,11 +915,11 @@ merge db (Message ps) = foldl mergeit db qs | |||
900 | mergeSubkey p (Just (SubKey key sigs)) = Just $ | 915 | mergeSubkey p (Just (SubKey key sigs)) = Just $ |
901 | SubKey (minimumBy subcomp [key,p]) sigs | 916 | SubKey (minimumBy subcomp [key,p]) sigs |
902 | 917 | ||
903 | mergeUid (UserIDPacket s) Nothing = Just [] | 918 | mergeUid (UserIDPacket s,_,_) Nothing = Just [] |
904 | mergeUid (UserIDPacket s) (Just sigs) = Just sigs | 919 | mergeUid (UserIDPacket s,_,_) (Just sigs) = Just sigs |
905 | mergeUid p _ = error $ "Unable to merge into UID record: " ++whatP p | 920 | mergeUid p _ = error $ "Unable to merge into UID record: " ++whatP p |
906 | 921 | ||
907 | whatP = concat . take 1 . words . show | 922 | whatP (a,_,_) = concat . take 1 . words . show $ a |
908 | 923 | ||
909 | 924 | ||
910 | mergeSig sig sigs = | 925 | mergeSig sig sigs = |
@@ -915,14 +930,16 @@ merge db (Message ps) = foldl mergeit db qs | |||
915 | in xs ++ (mergeSameSig sig y : ys') | 930 | in xs ++ (mergeSameSig sig y : ys') |
916 | 931 | ||
917 | 932 | ||
918 | isSameSig a b | isSignaturePacket a && isSignaturePacket b = | 933 | isSameSig (a,_,_) (b,_,_) | isSignaturePacket a && isSignaturePacket b = |
919 | a { unhashed_subpackets=[] } == b { unhashed_subpackets = [] } | 934 | a { unhashed_subpackets=[] } == b { unhashed_subpackets = [] } |
920 | isSameSig a b = a==b | 935 | isSameSig (a,_,_) (b,_,_) = a==b |
921 | 936 | ||
922 | mergeSameSig a b | isSignaturePacket a && isSignaturePacket b = | 937 | mergeSameSig (a,sa,pa) (b,sb,pb) | isSignaturePacket a && isSignaturePacket b = |
923 | b { unhashed_subpackets = | 938 | ( b { unhashed_subpackets = |
924 | foldl mergeItem (unhashed_subpackets b) (unhashed_subpackets a) | 939 | foldl mergeItem (unhashed_subpackets b) (unhashed_subpackets a) } |
925 | } | 940 | , sb `mplus` sa |
941 | , pb `mplus` pa ) | ||
942 | |||
926 | where | 943 | where |
927 | mergeItem ys x = if x `elem` ys then ys else ys++[x] | 944 | mergeItem ys x = if x `elem` ys then ys else ys++[x] |
928 | 945 | ||
@@ -935,16 +952,23 @@ merge db (Message ps) = foldl mergeit db qs | |||
935 | mergeSubSig sig Nothing = error $ | 952 | mergeSubSig sig Nothing = error $ |
936 | "Unable to merge subkey signature: "++(words (show sig) >>= take 1) | 953 | "Unable to merge subkey signature: "++(words (show sig) >>= take 1) |
937 | 954 | ||
938 | flattenKeys :: Map.Map KeyKey KeyData -> Message | 955 | flattenKeys :: Bool -> Map.Map KeyKey KeyData -> Message |
939 | flattenKeys db = Message $ concatMap flattenTop (Map.assocs db) | 956 | flattenKeys isPublic db = Message $ concatMap flattenTop (prefilter . Map.assocs $ db) |
940 | where | 957 | where |
941 | flattenTop (_,(KeyData key sigs uids subkeys)) = | 958 | flattenTop (_,(KeyData key sigs uids subkeys)) = |
942 | key : ( concatMap flattenUid (Map.assocs uids) | 959 | unk key : ( concatMap flattenUid (Map.assocs uids) |
943 | ++ concatMap flattenSub (Map.assocs subkeys)) | 960 | ++ concatMap flattenSub (Map.assocs subkeys)) |
944 | 961 | ||
945 | flattenUid (str,sigs) = UserIDPacket str : sigs | 962 | flattenUid (str,sigs) = UserIDPacket str : concatMap unsig sigs |
946 | 963 | ||
947 | flattenSub (_,SubKey key sigs) = key:sigs | 964 | flattenSub (_,SubKey key sigs) = unk key: concatMap unsig sigs |
965 | |||
966 | unk k = if isPublic then secretToPublic k else k | ||
967 | unsig (sig,sectrust,pubtrust) = [sig]++maybeToList (if isPublic then pubtrust else sectrust) | ||
968 | |||
969 | prefilter = if isPublic then id else filter isSecret | ||
970 | where isSecret (_,(KeyData (SecretKeyPacket {}) _ _ _)) = True | ||
971 | isSecret _ = False | ||
948 | 972 | ||
949 | {- | 973 | {- |
950 | merge db (Message ps) = scanl mergeit db qs | 974 | merge db (Message ps) = scanl mergeit db qs |
@@ -1008,7 +1032,10 @@ main = do | |||
1008 | &= help "Extract a public subkey to stdout." | 1032 | &= help "Extract a public subkey to stdout." |
1009 | , MergeSecrets HOMEOPTION | 1033 | , MergeSecrets HOMEOPTION |
1010 | (def &= args &= typFile) | 1034 | (def &= args &= typFile) |
1011 | &= help "Merge multiple keyrings to stdout." | 1035 | &= help "Merge multiple secret keyrings to stdout." |
1036 | , Merge HOMEOPTION | ||
1037 | (def &= args &= typFile) | ||
1038 | &= help "Merge multiple keyrings to stdout. Secrets are filtered." | ||
1012 | , DumpPackets HOMEOPTION | 1039 | , DumpPackets HOMEOPTION |
1013 | (def &= opt ("n" ::String)) | 1040 | (def &= opt ("n" ::String)) |
1014 | (def &= args &= typFile) | 1041 | (def &= args &= typFile) |
@@ -1284,7 +1311,19 @@ main = do | |||
1284 | let db = merge Map.empty (Message sec) | 1311 | let db = merge Map.empty (Message sec) |
1285 | ms <- mapM readPacketsFromFile (files cmd) | 1312 | ms <- mapM readPacketsFromFile (files cmd) |
1286 | let db' = foldl' merge db ms | 1313 | let db' = foldl' merge db ms |
1287 | m = flattenKeys db' | 1314 | m = flattenKeys False db' |
1315 | L.putStr (encode m) | ||
1316 | return () | ||
1317 | |||
1318 | doCmd cmd@(Merge {}) = do | ||
1319 | ( homedir -- e3ozbhvej4jvlu43.onion/gpg/gnupghome | ||
1320 | , sec -- e3ozbhvej4jvlu43.onion/gpg/gnupghome/secring.gpg | ||
1321 | , grip -- Just "AD1CA892FCF4ED9829C762269BDEA5B4D5643321" | ||
1322 | ) <- getPGPEnviron cmd | ||
1323 | let db = merge Map.empty (Message sec) | ||
1324 | ms <- mapM readPacketsFromFile (files cmd) | ||
1325 | let db' = foldl' merge db ms | ||
1326 | m = flattenKeys True db' | ||
1288 | L.putStr (encode m) | 1327 | L.putStr (encode m) |
1289 | return () | 1328 | return () |
1290 | 1329 | ||
@@ -1309,7 +1348,7 @@ main = do | |||
1309 | ms <- mapM readPacketsFromFile files | 1348 | ms <- mapM readPacketsFromFile files |
1310 | let db = merge Map.empty (Message sec) | 1349 | let db = merge Map.empty (Message sec) |
1311 | db' = foldl' merge db ms | 1350 | db' = foldl' merge db ms |
1312 | m = flattenKeys db' | 1351 | m = flattenKeys True db' |
1313 | Message allpkts = m | 1352 | Message allpkts = m |
1314 | 1353 | ||
1315 | let topspec = case () of | 1354 | let topspec = case () of |