summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--KeyRing.hs254
-rw-r--r--kiki.hs198
2 files changed, 250 insertions, 202 deletions
diff --git a/KeyRing.hs b/KeyRing.hs
index 5149da4..c6aa6a4 100644
--- a/KeyRing.hs
+++ b/KeyRing.hs
@@ -57,10 +57,13 @@ import qualified Data.Traversable as Traversable (mapM,forM,sequence)
57#if ! MIN_VERSION_base(4,6,0) 57#if ! MIN_VERSION_base(4,6,0)
58import GHC.Exts ( Down(..) ) 58import GHC.Exts ( Down(..) )
59#endif 59#endif
60import Network.Socket -- (SockAddr)
61import qualified Data.ByteString.Lazy.Char8 as Char8
60 62
61 63
62 64
63import qualified CryptoCoins as CryptoCoins 65import qualified Hosts
66import qualified CryptoCoins
64import Base58 67import Base58
65import FunctorToMaybe 68import FunctorToMaybe
66import DotLock 69import DotLock
@@ -95,6 +98,7 @@ type PassWordFile = InputFile
95data FileType = KeyRingFile (Maybe PassWordFile) 98data FileType = KeyRingFile (Maybe PassWordFile)
96 | PEMFile UsageTag 99 | PEMFile UsageTag
97 | WalletFile -- (Maybe UsageTag) 100 | WalletFile -- (Maybe UsageTag)
101 | Hosts
98 102
99-- | RefType is perhaps not a good name for this... 103-- | RefType is perhaps not a good name for this...
100-- It is sort of like a read/write flag, although 104-- It is sort of like a read/write flag, although
@@ -308,6 +312,7 @@ data KikiReportAction =
308 | ExternallyGeneratedFile 312 | ExternallyGeneratedFile
309 | UnableToExport KeyAlgorithm String 313 | UnableToExport KeyAlgorithm String
310 | FailedFileWrite 314 | FailedFileWrite
315 | HostsDiff ByteString
311 deriving Show 316 deriving Show
312 317
313data KikiResult a = KikiResult 318data KikiResult a = KikiResult
@@ -683,9 +688,114 @@ importPEMKey doDecrypt db' tup = do
683 try r $ \(db'',report) -> do 688 try r $ \(db'',report) -> do
684 return $ KikiSuccess (db'', report0 ++ report) 689 return $ KikiSuccess (db'', report0 ++ report)
685 690
691
692mergeHostFiles :: KeyRingOperation -> KeyDB
693 -> FilePath
694 -> FilePath
695 -> IO
696 (KikiCondition
697 ( ( Map.Map [Char8.ByteString] KeyData
698 , ( [Hosts.Hosts]
699 , [Hosts.Hosts]
700 , Hosts.Hosts
701 , [(SockAddr, ([Char8.ByteString], [Char8.ByteString]))]
702 , [SockAddr]))
703 , [(FilePath,KikiReportAction)]))
704mergeHostFiles krd db secring pubring = do
705 let hns = files ishosts
706 ishosts Hosts = True
707 ishosts _ = False
708 files istyp = do
709 (f,(rtyp,ftyp)) <- Map.toList (kFiles krd)
710 guard (istyp ftyp)
711 resolveInputFile secring pubring f
712
713 hostdbs0 <- mapM (fmap Hosts.decode . L.readFile) hns
714
715 let gpgnames = map getHostnames $ Map.elems db
716 os = do
717 (addr,(ns,_)) <- gpgnames
718 n <- ns
719 return (addr,n)
720 setOnions hosts = foldl' (flip $ uncurry Hosts.assignName) hosts os
721 -- we ensure .onion names are set properly
722 hostdbs = map setOnions hostdbs0
723 outgoing_names = do
724 (addr,(_,gns)) <- gpgnames
725 guard . not $ null gns
726 guard $ all (null . Hosts.namesForAddress addr) hostdbs0
727 return addr
728 -- putStrLn $ "hostdbs = " ++ show hostdbs
729
730 -- 1. let U = union all the host dbs
731 -- preserving whitespace and comments of the first
732 let u0 = foldl' Hosts.plus Hosts.empty hostdbs
733 -- we filter U to be only finger-dresses
734 u1 = Hosts.filterAddrs (hasFingerDress db) u0
735
736 -- let nf h = map Char8.unpack $ Hosts.namesForAddress (fromJust $ Hosts.inet_pton "fdf4:ed98:29c7:6226:9bde:a5b4:d564:3321") h
737 {-
738 putStrLn $ "_ = {\n" ++ show (head hostdbs) ++ "}"
739 putStrLn $ "--> " ++ show (nf (head hostdbs))
740 putStrLn $ "u0 = {\n" ++ show u0 ++ "}"
741 putStrLn $ "--> " ++ show (nf u0)
742 putStrLn $ "u1 = {\n" ++ show u1 ++ "}"
743 putStrLn $ "--> " ++ show (nf u1)
744 -}
745
746 -- 2. replace gpg annotations with those in U
747 -- forM use_db
748 db' <- Traversable.mapM (setHostnames (\a -> not $ elem a outgoing_names) u1) db
749
750 return $ KikiSuccess ((db',(hostdbs0,hostdbs,u1,gpgnames,outgoing_names)),[])
751
752writeHostsFiles
753 :: KeyRingOperation
754 -> [Char]
755 -> [Char]
756 -> ([Hosts.Hosts],
757 [Hosts.Hosts],
758 Hosts.Hosts,
759 [(SockAddr, (t1, [Char8.ByteString]))],
760 [SockAddr])
761 -> IO [(FilePath, KikiReportAction)]
762writeHostsFiles krd secring pubring (hostdbs0,hostdbs,u1,gpgnames,outgoing_names) = do
763 let hns = files ishosts
764 ishosts Hosts = True
765 ishosts _ = False
766 files istyp = do
767 (f,(rtyp,ftyp)) <- Map.toList (kFiles krd)
768 guard (istyp ftyp)
769 resolveInputFile secring pubring f
770
771 -- 3. add hostnames from gpg for addresses not in U
772 let u = foldl' f u1 ans
773 ans = reverse $ do
774 (addr,(_,ns)) <- gpgnames
775 guard $ addr `elem` outgoing_names -- . null $ Hosts.namesForAddress addr u0
776 n <- ns
777 return (addr,n)
778 f h (addr,n) = Hosts.assignNewName addr n h
779
780 -- 4. for each host db H, union H with U and write it out as H'
781 -- only if there is a non-empty diff
782 rss <- forM (zip hns $ zip hostdbs0 hostdbs) $ \(fname,(h0,h1)) -> do
783 let h = h1 `Hosts.plus` u
784 d = Hosts.diff h0 h
785 rs = map ((fname,) . HostsDiff) d
786 when (not $ null d) $ L.writeFile fname $ Hosts.encode h
787 return rs
788 return $ concat rss
789
790
686buildKeyDB :: (MappedPacket -> IO (KikiCondition Packet)) 791buildKeyDB :: (MappedPacket -> IO (KikiCondition Packet))
687 -> FilePath -> FilePath -> Maybe String -> KeyRingOperation 792 -> FilePath -> FilePath -> Maybe String -> KeyRingOperation
688 -> IO (KikiCondition ((KeyDB,Maybe String,Maybe MappedPacket) 793 -> IO (KikiCondition ((KeyDB,Maybe String,Maybe MappedPacket,
794 ([Hosts.Hosts],
795 [Hosts.Hosts],
796 Hosts.Hosts,
797 [(SockAddr, ([ByteString], [ByteString]))],
798 [SockAddr]) )
689 ,[(FilePath,KikiReportAction)])) 799 ,[(FilePath,KikiReportAction)]))
690buildKeyDB doDecrypt secring pubring grip0 keyring = do 800buildKeyDB doDecrypt secring pubring grip0 keyring = do
691 let 801 let
@@ -754,7 +864,10 @@ buildKeyDB doDecrypt secring pubring grip0 keyring = do
754 db <- foldM (importPEMKey doDecrypt) (KikiSuccess (db,[])) imports 864 db <- foldM (importPEMKey doDecrypt) (KikiSuccess (db,[])) imports
755 try db $ \(db,reportPEMs) -> do 865 try db $ \(db,reportPEMs) -> do
756 866
757 return $ KikiSuccess ( (db, grip, mwk), reportWallets ++ reportPEMs ) 867 r <- mergeHostFiles keyring db secring pubring
868 try r $ \((db,hs),reportHosts) -> do
869
870 return $ KikiSuccess ( (db, grip, mwk, hs), reportWallets ++ reportPEMs )
758 871
759torhash key = maybe "" id $ derToBase32 <$> derRSA key 872torhash key = maybe "" id $ derToBase32 <$> derRSA key
760 873
@@ -1372,7 +1485,7 @@ runKeyRing operation = do
1372 1485
1373 -- merge all keyrings, PEM files, and wallets 1486 -- merge all keyrings, PEM files, and wallets
1374 bresult <- buildKeyDB decrypt secring pubring grip0 operation 1487 bresult <- buildKeyDB decrypt secring pubring grip0 operation
1375 try' bresult $ \((db,grip,wk),report_imports) -> do 1488 try' bresult $ \((db,grip,wk,hs),report_imports) -> do
1376 1489
1377 externals_ret <- initializeMissingPEMFiles operation 1490 externals_ret <- initializeMissingPEMFiles operation
1378 secring pubring grip 1491 secring pubring grip
@@ -1402,6 +1515,8 @@ runKeyRing operation = do
1402 1515
1403 r <- writePEMKeys decrypt (rtKeyDB rt) exports 1516 r <- writePEMKeys decrypt (rtKeyDB rt) exports
1404 try' r $ \report_pems -> do 1517 try' r $ \report_pems -> do
1518
1519 import_hosts <- writeHostsFiles operation secring pubring hs
1405 1520
1406 return $ KikiResult (KikiSuccess rt) 1521 return $ KikiResult (KikiSuccess rt)
1407 $ concat [ report_imports 1522 $ concat [ report_imports
@@ -2005,6 +2120,137 @@ flattenUid :: FilePath -> Bool -> (String,([SigAndTrust],OriginMap)) -> [MappedP
2005flattenUid fname ispub (str,(sigs,om)) = 2120flattenUid fname ispub (str,(sigs,om)) =
2006 (mappedPacket "" $ UserIDPacket str) {locations=om} : concatSort fname head (unsig fname ispub) sigs 2121 (mappedPacket "" $ UserIDPacket str) {locations=om} : concatSort fname head (unsig fname ispub) sigs
2007 2122
2123getHostnames :: KeyData -> (SockAddr, ([L.ByteString],[L.ByteString]))
2124getHostnames (KeyData topmp _ uids subs) = (addr,(onames,othernames))
2125 where
2126 othernames = do
2127 mp <- flattenAllUids "" True uids
2128 let p = packet mp
2129 guard $ isSignaturePacket p
2130 uh <- unhashed_subpackets p
2131 case uh of
2132 NotationDataPacket True "hostname@" v
2133 -> return $ Char8.pack v
2134 _ -> mzero
2135
2136 addr = fingerdress topk
2137 -- name = maybe "" id $ listToMaybe onames -- TODO: more than one tor key?
2138 topk = packet topmp
2139 torkeys = do
2140 SubKey k sigs <- Map.elems subs
2141 let subk = packet k
2142 let sigs' = do
2143 torsig <- filter (has_tag "tor") $ map (packet . fst) sigs
2144 sig <- (signatures $ Message [topk,subk,torsig])
2145 let v = verify (Message [topk]) sig
2146 -- Require parent's signature
2147 guard (not . null $ signatures_over v)
2148 let unhashed = unhashed_subpackets torsig
2149 subsigs = mapMaybe backsig unhashed
2150 -- This should consist only of 0x19 values
2151 -- subtypes = map signature_type subsigs
2152 sig' <- signatures . Message $ [topk,subk]++subsigs
2153 let v' = verify (Message [subk]) sig'
2154 -- Require subkey's signature
2155 guard . not . null $ signatures_over v'
2156 return torsig
2157 guard (not $ null sigs')
2158 return $ subk
2159 has_tag tag p = isSignaturePacket p
2160 && or [ tag `elem` mapMaybe usage (hashed_subpackets p)
2161 , tag `elem` map usageString (mapMaybe keyflags (hashed_subpackets p)) ]
2162 -- subkeyPacket (SubKey k _ ) = k
2163 onames :: [L.ByteString]
2164 onames = map ( (<> ".onion")
2165 . Char8.pack
2166 . take 16
2167 . torhash )
2168 torkeys
2169
2170hasFingerDress :: KeyDB -> SockAddr -> Bool
2171hasFingerDress db addr | socketFamily addr/=AF_INET6 = False
2172hasFingerDress db addr = pre=="fd" && isJust (selectPublicKey (KeyGrip g',Nothing) db)
2173 where
2174 (pre,g) = splitAt 2 $ filter (/=':') $ Hosts.inet_ntop addr
2175 g' = map toUpper g
2176
2177-- We return into IO in case we want to make a signature here.
2178setHostnames :: (SockAddr -> Bool) -> Hosts.Hosts -> KeyData -> IO KeyData
2179setHostnames pred hosts kd@(KeyData topmp topsigs uids subs) =
2180 -- TODO: we are removing the origin from the UID OriginMap,
2181 -- when we should be removing origins from the locations
2182 -- field of the sig's MappedPacket records.
2183 -- Call getHostnames and compare to see if no-op.
2184 if not (pred addr) || names0 == names \\ onions
2185 then {- trace (unlines [ "setHostnames NO-OP: gpg: "++show (map Char8.unpack onions, map Char8.unpack names0)
2186 , " file: "++show (map Char8.unpack names)
2187 , " pred: "++show (pred addr)]) -}
2188 (return kd)
2189 else do
2190 -- We should be sure to remove origins so that the data is written
2191 -- (but only if something changed).
2192 -- Filter all hostnames present in uids
2193 -- Write notations into first uid
2194 {-
2195 trace (unlines [ "setHostnames ACTION: gpg: "++show (map Char8.unpack onions, map Char8.unpack names0)
2196 , " file: "++show (map Char8.unpack names) ]) $ do
2197 -}
2198 return $ KeyData topmp topsigs uids1 subs
2199 where
2200 topk = packet topmp
2201 addr = fingerdress topk
2202 names :: [Char8.ByteString]
2203 names = Hosts.namesForAddress addr hosts
2204 (_,(onions,names0)) = getHostnames kd
2205 notations = map (NotationDataPacket True "hostname@" . Char8.unpack) (names \\ onions)
2206 isName (NotationDataPacket True "hostname@" _) = True
2207 isName _ = False
2208 uids0 = fmap zapIfHasName uids
2209 fstuid = head $ do
2210 p <- map packet $ flattenAllUids "" True uids
2211 guard $ isUserID p
2212 return $ uidkey p
2213 uids1 = Map.adjust addnames fstuid uids0
2214 addnames (sigs,om) = (fmap f ss ++ ts, om ) -- XXX: removed om=Map.empty, preserve UserId origin
2215 where
2216 (ss,ts) = splitAt 1 sigs
2217 f (sig,tm) = if isSignaturePacket (packet sig) then (sig { packet = p', locations=Map.empty }, tm)
2218 else (sig, tm)
2219 where p' = (packet sig) { unhashed_subpackets=uh }
2220 uh = unhashed_subpackets (packet sig) ++ notations
2221 zapIfHasName (sigs,om) = if or bs then (sigs',om) -- XXX: removed om=Map.empty to preserve UserID origin
2222 else (sigs,om)
2223 where
2224 (bs, sigs') = unzip $ map unhash sigs
2225
2226 unhash (sig,tm) = ( not (null ns)
2227 , ( sig { packet = p', locations = Map.empty }
2228 , tm ) )
2229 where
2230 psig = packet sig
2231 p' = if isSignaturePacket psig then psig { unhashed_subpackets = ps }
2232 else psig
2233 uh = unhashed_subpackets $ psig
2234 (ns,ps) = partition isName uh
2235
2236fingerdress :: Packet -> SockAddr
2237fingerdress topk = maybe zero id $ Hosts.inet_pton addr_str
2238 where
2239 zero = SockAddrInet 0 0
2240 addr_str = colons $ "fd" ++ (drop 10 $ map toLower $ fingerprint topk)
2241 colons (a:b:c:d:xs@(_:_)) = [a,b,c,d,':'] ++ colons xs
2242 colons xs = xs
2243
2244backsig (EmbeddedSignaturePacket s) = Just s
2245backsig _ = Nothing
2246
2247socketFamily (SockAddrInet _ _) = AF_INET
2248socketFamily (SockAddrInet6 _ _ _ _) = AF_INET6
2249socketFamily (SockAddrUnix _) = AF_UNIX
2250
2251
2252
2253{-----------------------------------------------}
2008 2254
2009 2255
2010{- 2256{-
diff --git a/kiki.hs b/kiki.hs
index 6b67449..60c0b6b 100644
--- a/kiki.hs
+++ b/kiki.hs
@@ -145,9 +145,6 @@ isCertificationSig _ = True
145 145
146issuer (IssuerPacket issuer) = Just issuer 146issuer (IssuerPacket issuer) = Just issuer
147issuer _ = Nothing 147issuer _ = Nothing
148backsig (EmbeddedSignaturePacket s) = Just s
149backsig _ = Nothing
150
151isSubkeySignature (SubkeySignature {}) = True 148isSubkeySignature (SubkeySignature {}) = True
152isSubkeySignature _ = False 149isSubkeySignature _ = False
153 150
@@ -814,85 +811,6 @@ doBTCImport doDecrypt db (ms,subspec,content) = do
814 doImportG doDecrypt db m0 tag "" key 811 doImportG doDecrypt db m0 tag "" key
815-} 812-}
816 813
817-- We return into IO in case we want to make a signature here.
818setHostnames :: (SockAddr -> Bool) -> Hosts.Hosts -> KeyData -> IO KeyData
819setHostnames pred hosts kd@(KeyData topmp topsigs uids subs) =
820 -- TODO: we are removing the origin from the UID OriginMap,
821 -- when we should be removing origins from the locations
822 -- field of the sig's MappedPacket records.
823 -- Call getHostnames and compare to see if no-op.
824 if not (pred addr) || names0 == names \\ onions
825 then {- trace (unlines [ "setHostnames NO-OP: gpg: "++show (map Char8.unpack onions, map Char8.unpack names0)
826 , " file: "++show (map Char8.unpack names)
827 , " pred: "++show (pred addr)]) -}
828 (return kd)
829 else do
830 -- We should be sure to remove origins so that the data is written
831 -- (but only if something changed).
832 -- Filter all hostnames present in uids
833 -- Write notations into first uid
834 {-
835 trace (unlines [ "setHostnames ACTION: gpg: "++show (map Char8.unpack onions, map Char8.unpack names0)
836 , " file: "++show (map Char8.unpack names) ]) $ do
837 -}
838 return $ KeyData topmp topsigs uids1 subs
839 where
840 topk = packet topmp
841 addr = fingerdress topk
842 names :: [Char8.ByteString]
843 names = Hosts.namesForAddress addr hosts
844 (_,(onions,names0)) = getHostnames kd
845 notations = map (NotationDataPacket True "hostname@" . Char8.unpack) (names \\ onions)
846 isName (NotationDataPacket True "hostname@" _) = True
847 isName _ = False
848 uids0 = fmap zapIfHasName uids
849 fstuid = head $ do
850 p <- map packet $ flattenAllUids "" True uids
851 guard $ isUserID p
852 return $ uidkey p
853 uids1 = Map.adjust addnames fstuid uids0
854 addnames (sigs,om) = (fmap f ss ++ ts, om ) -- XXX: removed om=Map.empty, preserve UserId origin
855 where
856 (ss,ts) = splitAt 1 sigs
857 f (sig,tm) = if isSignaturePacket (packet sig) then (sig { packet = p', locations=Map.empty }, tm)
858 else (sig, tm)
859 where p' = (packet sig) { unhashed_subpackets=uh }
860 uh = unhashed_subpackets (packet sig) ++ notations
861 zapIfHasName (sigs,om) = if or bs then (sigs',om) -- XXX: removed om=Map.empty to preserve UserID origin
862 else (sigs,om)
863 where
864 (bs, sigs') = unzip $ map unhash sigs
865
866 unhash (sig,tm) = ( not (null ns)
867 , ( sig { packet = p', locations = Map.empty }
868 , tm ) )
869 where
870 psig = packet sig
871 p' = if isSignaturePacket psig then psig { unhashed_subpackets = ps }
872 else psig
873 uh = unhashed_subpackets $ psig
874 (ns,ps) = partition isName uh
875
876socketFamily (SockAddrInet _ _) = AF_INET
877socketFamily (SockAddrInet6 _ _ _ _) = AF_INET6
878socketFamily (SockAddrUnix _) = AF_UNIX
879
880
881hasFingerDress :: KeyDB -> SockAddr -> Bool
882hasFingerDress db addr | socketFamily addr/=AF_INET6 = False
883hasFingerDress db addr = pre=="fd" && isJust (selectPublicKey (KeyGrip g',Nothing) db)
884 where
885 (pre,g) = splitAt 2 $ filter (/=':') $ Hosts.inet_ntop addr
886 g' = map toUpper g
887
888fingerdress :: Packet -> SockAddr
889fingerdress topk = maybe zero id $ Hosts.inet_pton addr_str
890 where
891 zero = SockAddrInet 0 0
892 addr_str = colons $ "fd" ++ (drop 10 $ map toLower $ fingerprint topk)
893 colons (a:b:c:d:xs@(_:_)) = [a,b,c,d,':'] ++ colons xs
894 colons xs = xs
895
896 814
897{- 815{-
898onionName :: KeyData -> (SockAddr,L.ByteString) 816onionName :: KeyData -> (SockAddr,L.ByteString)
@@ -901,53 +819,6 @@ onionName kd = (addr,name)
901 (addr,(name:_,_)) = getHostnames kd 819 (addr,(name:_,_)) = getHostnames kd
902-} 820-}
903 821
904getHostnames :: KeyData -> (SockAddr, ([L.ByteString],[L.ByteString]))
905getHostnames (KeyData topmp _ uids subs) = (addr,(onames,othernames))
906 where
907 othernames = do
908 mp <- flattenAllUids "" True uids
909 let p = packet mp
910 guard $ isSignaturePacket p
911 uh <- unhashed_subpackets p
912 case uh of
913 NotationDataPacket True "hostname@" v
914 -> return $ Char8.pack v
915 _ -> mzero
916
917 addr = fingerdress topk
918 -- name = maybe "" id $ listToMaybe onames -- TODO: more than one tor key?
919 topk = packet topmp
920 torkeys = do
921 SubKey k sigs <- Map.elems subs
922 let subk = packet k
923 let sigs' = do
924 torsig <- filter (has_tag "tor") $ map (packet . fst) sigs
925 sig <- (signatures $ Message [topk,subk,torsig])
926 let v = verify (Message [topk]) sig
927 -- Require parent's signature
928 guard (not . null $ signatures_over v)
929 let unhashed = unhashed_subpackets torsig
930 subsigs = mapMaybe backsig unhashed
931 -- This should consist only of 0x19 values
932 -- subtypes = map signature_type subsigs
933 sig' <- signatures . Message $ [topk,subk]++subsigs
934 let v' = verify (Message [subk]) sig'
935 -- Require subkey's signature
936 guard . not . null $ signatures_over v'
937 return torsig
938 guard (not $ null sigs')
939 return $ subk
940 has_tag tag p = isSignaturePacket p
941 && or [ tag `elem` mapMaybe usage (hashed_subpackets p)
942 , tag `elem` map usageString (mapMaybe keyflags (hashed_subpackets p)) ]
943 -- subkeyPacket (SubKey k _ ) = k
944 onames :: [L.ByteString]
945 onames = map ( (<> ".onion")
946 . Char8.pack
947 . take 16
948 . torhash )
949 torkeys
950
951whoseKey :: RSAPublicKey -> KeyDB -> [KeyData] 822whoseKey :: RSAPublicKey -> KeyDB -> [KeyData]
952whoseKey rsakey db = filter matchkey (Map.elems db) 823whoseKey rsakey db = filter matchkey (Map.elems db)
953 where 824 where
@@ -1255,75 +1126,6 @@ main = do
1255 Traversable.mapM (signTorIds wkun keys) (rtKeyDB rt) 1126 Traversable.mapM (signTorIds wkun keys) (rtKeyDB rt)
1256 return use_db 1127 return use_db
1257 1128
1258 let doHostNames db = do
1259 let hns = maybe [] id $ Map.lookup "--hosts" margs
1260 hostdbs0 <- mapM (fmap Hosts.decode . L.readFile) hns
1261
1262 let gpgnames = map getHostnames $ Map.elems db
1263 os = do
1264 (addr,(ns,_)) <- gpgnames
1265 n <- ns
1266 return (addr,n)
1267 setOnions hosts = foldl' (flip $ uncurry Hosts.assignName) hosts os
1268 -- we ensure .onion names are set properly
1269 hostdbs = map setOnions hostdbs0
1270 outgoing_names = do
1271 (addr,(_,gns)) <- gpgnames
1272 guard . not $ null gns
1273 guard $ all (null . Hosts.namesForAddress addr) hostdbs0
1274 return addr
1275 -- putStrLn $ "hostdbs = " ++ show hostdbs
1276
1277 -- 1. let U = union all the host dbs
1278 -- preserving whitespace and comments of the first
1279 let u0 = foldl' Hosts.plus Hosts.empty hostdbs
1280 -- we filter U to be only finger-dresses
1281 u1 = Hosts.filterAddrs (hasFingerDress db) u0
1282
1283 -- let nf h = map Char8.unpack $ Hosts.namesForAddress (fromJust $ Hosts.inet_pton "fdf4:ed98:29c7:6226:9bde:a5b4:d564:3321") h
1284 {-
1285 putStrLn $ "_ = {\n" ++ show (head hostdbs) ++ "}"
1286 putStrLn $ "--> " ++ show (nf (head hostdbs))
1287 putStrLn $ "u0 = {\n" ++ show u0 ++ "}"
1288 putStrLn $ "--> " ++ show (nf u0)
1289 putStrLn $ "u1 = {\n" ++ show u1 ++ "}"
1290 putStrLn $ "--> " ++ show (nf u1)
1291 -}
1292
1293 -- 2. replace gpg annotations with those in U
1294 -- forM use_db
1295 db' <- Traversable.mapM (setHostnames (\a -> not $ elem a outgoing_names) u1) db
1296
1297 -- 3. add hostnames from gpg for addresses not in U
1298 let u = foldl' f u1 ans
1299 ans = reverse $ do
1300 (addr,(_,ns)) <- gpgnames
1301 guard $ addr `elem` outgoing_names -- . null $ Hosts.namesForAddress addr u0
1302 n <- ns
1303 return (addr,n)
1304 f h (addr,n) = Hosts.assignNewName addr n h
1305
1306 {-
1307 putStrLn $ "u = {\n" ++ show u ++ "}"
1308 putStrLn $ "--> " ++ show (nf u)
1309 -}
1310
1311 -- 4. for each host db H, union H with U and write it out as H'
1312 -- only if there is a non-empty diff
1313 forM_ (zip hns $ zip hostdbs0 hostdbs) $ \(fname,(h0,h1)) -> do
1314 let h = h1 `Hosts.plus` u
1315 d = Hosts.diff h0 h
1316 fnamecolon = Char8.pack fname <> ": "
1317 {-
1318 putStrLn $ "h = {\n" ++ show h ++ "}"
1319 putStrLn $ "--> " ++ show (nf h)
1320 -}
1321 Char8.hPutStrLn stderr $ Char8.unlines (map (fnamecolon <>) d)
1322 when (not $ null d) $ L.writeFile fname $ Hosts.encode h
1323 return ()
1324
1325 return db'
1326
1327 let homespec = join . take 1 <$> Map.lookup "--homedir" margs 1129 let homespec = join . take 1 <$> Map.lookup "--homedir" margs
1328 passfd = fmap (FileDesc . read) passphrase_fd 1130 passfd = fmap (FileDesc . read) passphrase_fd
1329 pems = flip map keypairs 1131 pems = flip map keypairs