summaryrefslogtreecommitdiff
path: root/src/Network/Tox
diff options
context:
space:
mode:
Diffstat (limited to 'src/Network/Tox')
-rw-r--r--src/Network/Tox/Onion/Handlers.hs23
-rw-r--r--src/Network/Tox/Onion/Transport.hs85
2 files changed, 59 insertions, 49 deletions
diff --git a/src/Network/Tox/Onion/Handlers.hs b/src/Network/Tox/Onion/Handlers.hs
index 9702cbb8..047b902d 100644
--- a/src/Network/Tox/Onion/Handlers.hs
+++ b/src/Network/Tox/Onion/Handlers.hs
@@ -79,9 +79,15 @@ announceH routing toks keydb oaddr req = do
79 let naddr = onionNodeInfo oaddr 79 let naddr = onionNodeInfo oaddr
80 ns <- getNodesH routing naddr (GetNodes (announceSeeking req)) 80 ns <- getNodesH routing naddr (GetNodes (announceSeeking req))
81 tm <- getPOSIXTime 81 tm <- getPOSIXTime
82
82 let storing = case oaddr of 83 let storing = case oaddr of
83 OnionToOwner _ pth -> guard (nodeId naddr == announceSeeking req) >> Just pth 84 OnionToOwner _ pth -> guard (nodeId naddr == announceSeeking req) >> Just pth
84 _ -> Nothing 85 _ -> Nothing
86 hPutStrLn stderr $ unlines [ "announceH: nodeId = " ++ show (nodeId naddr)
87 , " announceSeeking = " ++ show (announceSeeking req)
88 , " withTok = " ++ show withTok
89 , " storing = " ++ maybe "False" (const "True") storing
90 ]
85 record <- atomically $ do 91 record <- atomically $ do
86 forM_ storing $ \retpath -> when withTok $ do 92 forM_ storing $ \retpath -> when withTok $ do
87 let toxpath = AnnouncedRoute naddr{ nodeId = announceKey req } retpath 93 let toxpath = AnnouncedRoute naddr{ nodeId = announceKey req } retpath
@@ -186,7 +192,7 @@ announceSerializer getTimeout = MethodSerializer
186 { -- The public key is our real long term public key if we want to 192 { -- The public key is our real long term public key if we want to
187 -- announce ourselves, a temporary one if we are searching for 193 -- announce ourselves, a temporary one if we are searching for
188 -- friends. 194 -- friends.
189 senderKey = fromJust $ onionKey src -- TODO: FIXME: this should be a temporary alias key 195 senderKey = onionKey src
190 , assymNonce = n24 196 , assymNonce = n24
191 , assymData = Identity (req, n8) 197 , assymData = Identity (req, n8)
192 } 198 }
@@ -224,16 +230,15 @@ unwrapAnnounceResponse ni (AnnounceResponse is_stored (SendNodes ns))
224sendOnion :: (TransactionId -> OnionDestination r -> STM (OnionDestination r, Int)) 230sendOnion :: (TransactionId -> OnionDestination r -> STM (OnionDestination r, Int))
225 -> Client r 231 -> Client r
226 -> AnnounceRequest 232 -> AnnounceRequest
227 -> NodeInfo 233 -> OnionDestination r
228 -> (NodeInfo -> AnnounceResponse -> t) 234 -> (NodeInfo -> AnnounceResponse -> t)
229 -> IO (Maybe t) 235 -> IO (Maybe t)
230sendOnion getTimeout client req ni unwrap = 236sendOnion getTimeout client req oaddr unwrap =
231 -- Four tries and then we tap out. 237 -- Four tries and then we tap out.
232 flip fix 4 $ \loop n -> do 238 flip fix 4 $ \loop n -> do
233 let oaddr = OnionDestination ni Nothing
234 mb <- QR.sendQuery client (announceSerializer getTimeout) req oaddr 239 mb <- QR.sendQuery client (announceSerializer getTimeout) req oaddr
235 maybe (if n>0 then loop $! n - 1 else return Nothing) 240 maybe (if n>0 then loop $! n - 1 else return Nothing)
236 (return . Just . unwrap ni) 241 (return . Just . unwrap (onionNodeInfo oaddr))
237 $ join mb 242 $ join mb
238 243
239getRendezvous :: (TransactionId -> OnionDestination r -> STM (OnionDestination r, Int)) 244getRendezvous :: (TransactionId -> OnionDestination r -> STM (OnionDestination r, Int))
@@ -241,8 +246,9 @@ getRendezvous :: (TransactionId -> OnionDestination r -> STM (OnionDestination r
241 -> NodeId 246 -> NodeId
242 -> NodeInfo 247 -> NodeInfo
243 -> IO (Maybe ([NodeInfo],[Rendezvous],Maybe Nonce32)) 248 -> IO (Maybe ([NodeInfo],[Rendezvous],Maybe Nonce32))
244getRendezvous getTimeout client nid ni = 249getRendezvous getTimeout client nid ni = do
245 sendOnion getTimeout client (AnnounceRequest zeros32 nid zeroID) ni unwrapAnnounceResponse 250 let oaddr = OnionDestination SearchingAlias ni Nothing
251 sendOnion getTimeout client (AnnounceRequest zeros32 nid zeroID) oaddr unwrapAnnounceResponse
246 252
247putRendezvous :: (TransactionId -> OnionDestination r -> STM (OnionDestination r, Int)) 253putRendezvous :: (TransactionId -> OnionDestination r -> STM (OnionDestination r, Int))
248 -> TransportCrypto 254 -> TransportCrypto
@@ -255,5 +261,6 @@ putRendezvous getTimeout crypto client pubkey nonce32 ni = do
255 let longTermKey = key2id pubkey 261 let longTermKey = key2id pubkey
256 rkey = rendezvousPublic crypto 262 rkey = rendezvousPublic crypto
257 rendezvousKey = key2id rkey 263 rendezvousKey = key2id rkey
258 sendOnion getTimeout client (AnnounceRequest nonce32 longTermKey rendezvousKey) ni 264 let oaddr = OnionDestination (AnnouncingAlias longTermKey) ni Nothing
265 sendOnion getTimeout client (AnnounceRequest nonce32 longTermKey rendezvousKey) oaddr
259 $ \ni resp -> (Rendezvous rkey ni, resp) 266 $ \ni resp -> (Rendezvous rkey ni, resp)
diff --git a/src/Network/Tox/Onion/Transport.hs b/src/Network/Tox/Onion/Transport.hs
index 34ba23f6..e52c8faa 100644
--- a/src/Network/Tox/Onion/Transport.hs
+++ b/src/Network/Tox/Onion/Transport.hs
@@ -20,6 +20,7 @@ module Network.Tox.Onion.Transport
20 , parseDataToRoute 20 , parseDataToRoute
21 , encodeDataToRoute 21 , encodeDataToRoute
22 , forwardOnions 22 , forwardOnions
23 , AliasSelector(..)
23 , OnionDestination(..) 24 , OnionDestination(..)
24 , OnionMessage(..) 25 , OnionMessage(..)
25 , Rendezvous(..) 26 , Rendezvous(..)
@@ -39,7 +40,7 @@ module Network.Tox.Onion.Transport
39 , OnionRoute(..) 40 , OnionRoute(..)
40 , N3 41 , N3
41 , onionKey 42 , onionKey
42 , onionNodeInfo 43 , onionAliasSelector
43 ) where 44 ) where
44 45
45import Network.Address (fromSockAddr,toSockAddr,setPort,either4or6,sockAddrPort) 46import Network.Address (fromSockAddr,toSockAddr,setPort,either4or6,sockAddrPort)
@@ -100,17 +101,27 @@ msgNonce (OnionAnnounceResponse _ n24 _) = n24
100msgNonce (OnionToRoute _ a) = assymNonce a 101msgNonce (OnionToRoute _ a) = assymNonce a
101msgNonce (OnionToRouteResponse a) = assymNonce a 102msgNonce (OnionToRouteResponse a) = assymNonce a
102 103
104data AliasSelector = SearchingAlias | AnnouncingAlias NodeId
105 deriving (Eq,Ord,Show)
106
103data OnionDestination r 107data OnionDestination r
104 = OnionToOwner NodeInfo (ReturnPath N3) -- ^ Somebody else's path to us. 108 = OnionToOwner
105 | OnionDestination NodeInfo (Maybe r) -- ^ Our own onion-path. 109 { onionNodeInfo :: NodeInfo
110 , onionReturnPath :: ReturnPath N3 -- ^ Somebody else's path to us.
111 }
112 | OnionDestination
113 { onionAliasSelector' :: AliasSelector
114 , onionNodeInfo :: NodeInfo
115 , onionRouteSpec :: Maybe r -- ^ Our own onion-path.
116 }
106 deriving Show 117 deriving Show
107 118
108onionNodeInfo :: OnionDestination r -> NodeInfo 119onionAliasSelector :: OnionDestination r -> AliasSelector
109onionNodeInfo (OnionToOwner ni _) = ni 120onionAliasSelector (OnionToOwner {} ) = SearchingAlias
110onionNodeInfo (OnionDestination ni _) = ni 121onionAliasSelector (OnionDestination{onionAliasSelector' = sel}) = sel
111 122
112onionKey :: OnionDestination r -> Maybe PublicKey 123onionKey :: OnionDestination r -> PublicKey
113onionKey od = Just $ id2key . nodeId $ onionNodeInfo od 124onionKey od = id2key . nodeId $ onionNodeInfo od
114 125
115instance Sized (OnionMessage Encrypted) where 126instance Sized (OnionMessage Encrypted) where
116 size = VarSize $ \case 127 size = VarSize $ \case
@@ -152,7 +163,7 @@ onion bs saddr getf = do (f,(assym,ret3)) <- runGet ((,) <$> getf <*> getOnionRe
152 oaddr <- onionToOwner assym ret3 saddr 163 oaddr <- onionToOwner assym ret3 saddr
153 return (f assym, oaddr) 164 return (f assym, oaddr)
154 165
155parseOnionAddr :: (SockAddr -> Nonce8 -> IO (Maybe (NodeInfo,r))) 166parseOnionAddr :: (SockAddr -> Nonce8 -> IO (Maybe (OnionDestination r)))
156 -> (ByteString, SockAddr) 167 -> (ByteString, SockAddr)
157 -> IO (Either (OnionMessage Encrypted,OnionDestination r) 168 -> IO (Either (OnionMessage Encrypted,OnionDestination r)
158 (ByteString,SockAddr)) 169 (ByteString,SockAddr))
@@ -167,11 +178,11 @@ parseOnionAddr lookupSender (msg,saddr)
167 Just (Right msg@(OnionAnnounceResponse n8 _ _)) -> do 178 Just (Right msg@(OnionAnnounceResponse n8 _ _)) -> do
168 maddr <- lookupSender saddr n8 179 maddr <- lookupSender saddr n8
169 maybe (return right) -- Response unsolicited or too late. 180 maybe (return right) -- Response unsolicited or too late.
170 (return . Left . \(ni,r) -> (msg,OnionDestination ni (Just r))) 181 (return . Left . \od -> (msg,od))
171 maddr 182 maddr
172 Just (Right msg@(OnionToRouteResponse asym)) -> do 183 Just (Right msg@(OnionToRouteResponse asym)) -> do
173 let ni = asymNodeInfo saddr asym 184 let ni = asymNodeInfo saddr asym
174 return $ Left (msg, OnionDestination ni Nothing) 185 return $ Left (msg, OnionDestination SearchingAlias ni Nothing)
175 _ -> return right 186 _ -> return right
176 187
177getOnionReply :: Word8 -> Maybe (Get (OnionMessage Encrypted)) 188getOnionReply :: Word8 -> Maybe (Get (OnionMessage Encrypted))
@@ -191,10 +202,10 @@ encodeOnionAddr :: (NodeInfo -> r -> IO (Maybe OnionRoute))
191encodeOnionAddr _ (msg,OnionToOwner ni p) = 202encodeOnionAddr _ (msg,OnionToOwner ni p) =
192 return $ Just ( runPut $ putResponse (OnionResponse p msg) 203 return $ Just ( runPut $ putResponse (OnionResponse p msg)
193 , nodeAddr ni ) 204 , nodeAddr ni )
194encodeOnionAddr _ (msg,OnionDestination _ Nothing ) = do 205encodeOnionAddr _ (msg,OnionDestination _ _ Nothing) = do
195 hPutStrLn stderr $ "ONION encode missing routeid" 206 hPutStrLn stderr $ "ONION encode missing routeid"
196 return Nothing 207 return Nothing
197encodeOnionAddr getRoute (msg,OnionDestination ni (Just rid)) = do 208encodeOnionAddr getRoute (msg,OnionDestination _ ni (Just rid)) = do
198 let go route = do 209 let go route = do
199 return ( runPut $ putRequest $ wrapForRoute msg ni route 210 return ( runPut $ putRequest $ wrapForRoute msg ni route
200 , nodeAddr $ routeNodeA route) 211 , nodeAddr $ routeNodeA route)
@@ -599,26 +610,19 @@ instance Sized OnionData where
599 VarSize f -> f req 610 VarSize f -> f req
600 611
601 612
602selectKey :: TransportCrypto -> OnionMessage Identity -> OnionDestination r -> IO (SecretKey, PublicKey) 613selectKey :: TransportCrypto -> OnionMessage f -> OnionDestination r -> IO (SecretKey, PublicKey)
603selectKey crypto 614selectKey crypto _ rpath@(OnionDestination (AnnouncingAlias pkey) _ _)
604 (OnionAnnounce a@Assym { assymData = Identity (AnnounceRequest _ pkey akey, _) }) 615 = atomically $ do ks <- filter (\(sk,pk) -> pk == id2key pkey)
605 rpath 616 <$> readTVar (userKeys crypto)
606 | (akey /= zeroID) = atomically $ do 617 maybe (return $ aliasKey crypto rpath)
607 ks <- filter (\(sk,pk) -> pk == id2key pkey) 618 return
608 <$> readTVar (userKeys crypto) 619 (listToMaybe ks)
609 maybe (return $ aliasKey crypto rpath)
610 return
611 (listToMaybe ks)
612selectKey crypto msg rpath = return $ aliasKey crypto rpath 620selectKey crypto msg rpath = return $ aliasKey crypto rpath
613 621
614encrypt :: TransportCrypto -> OnionMessage Identity -> OnionDestination r -> IO (OnionMessage Encrypted, OnionDestination r) 622encrypt :: TransportCrypto -> OnionMessage Identity -> OnionDestination r -> IO (OnionMessage Encrypted, OnionDestination r)
615encrypt crypto msg rpath = do 623encrypt crypto msg rpath = do
616 (skey,pkey) <- selectKey crypto msg rpath 624 (skey,pkey) <- selectKey crypto msg rpath -- source key
617 let skey = fst $ aliasKey crypto rpath 625 let okey = onionKey rpath -- destination key
618
619 -- The OnionToMe case shouldn't happen, but we'll use our own public
620 -- key in this situation.
621 okey = fromMaybe (transportPublic crypto) $ onionKey rpath
622 return ( transcode ( (. (runIdentity . either id assymData)) 626 return ( transcode ( (. (runIdentity . either id assymData))
623 . encryptMessage skey okey) 627 . encryptMessage skey okey)
624 msg 628 msg
@@ -632,11 +636,13 @@ encryptMessage skey destKey n a = ToxCrypto.encrypt secret plain
632 plain = encodePlain a 636 plain = encodePlain a
633 637
634decrypt :: TransportCrypto -> OnionMessage Encrypted -> OnionDestination r -> IO (Either String (OnionMessage Identity, OnionDestination r)) 638decrypt :: TransportCrypto -> OnionMessage Encrypted -> OnionDestination r -> IO (Either String (OnionMessage Identity, OnionDestination r))
635decrypt crypto msg addr = return $ do 639decrypt crypto msg addr = do
636 msg <- sequenceMessage $ transcode (\n -> decryptMessage (aliasKey crypto addr) n . left (senderkey addr)) msg 640 (skey,pkey) <- selectKey crypto msg addr
641 return $ do
642 msg <- sequenceMessage $ transcode (\n -> decryptMessage (skey,pkey) n . left (senderkey addr)) msg
637 Right (msg, addr) 643 Right (msg, addr)
638 644
639senderkey :: OnionDestination r -> t -> (Maybe PublicKey, t) 645senderkey :: OnionDestination r -> t -> (PublicKey, t)
640senderkey addr e = (onionKey addr, e) 646senderkey addr e = (onionKey addr, e)
641 647
642aliasKey :: TransportCrypto -> OnionDestination r -> (SecretKey,PublicKey) 648aliasKey :: TransportCrypto -> OnionDestination r -> (SecretKey,PublicKey)
@@ -649,17 +655,14 @@ dhtKey crypto = (transportSecret &&& transportPublic) crypto
649decryptMessage :: Serialize x => 655decryptMessage :: Serialize x =>
650 (SecretKey,PublicKey) 656 (SecretKey,PublicKey)
651 -> Nonce24 657 -> Nonce24
652 -> Either (Maybe PublicKey, Encrypted x) 658 -> Either (PublicKey, Encrypted x)
653 (Assym (Encrypted x)) 659 (Assym (Encrypted x))
654 -> (Either String ∘ Identity) x 660 -> (Either String ∘ Identity) x
655decryptMessage crypto n arg 661decryptMessage crypto n arg = plain $ ToxCrypto.decrypt secret e
656 | Just secret <- msecret = plain $ ToxCrypto.decrypt secret e
657 | otherwise = Composed $ Left "decryptMessage: Unknown sender"
658 where 662 where
659 msecret = do sender <- mkey 663 secret = computeSharedSecret (fst crypto) sender n
660 Just $ computeSharedSecret (fst crypto) sender n 664 (sender,e) = either id (senderKey &&& assymData) arg
661 (mkey,e) = either id (Just . senderKey &&& assymData) arg 665 plain = Composed . fmap Identity . (>>= decodePlain)
662 plain = Composed . fmap Identity . (>>= decodePlain)
663 666
664 667
665sequenceMessage :: Applicative m => OnionMessage (m ∘ f) -> m (OnionMessage f) 668sequenceMessage :: Applicative m => OnionMessage (m ∘ f) -> m (OnionMessage f)
@@ -751,4 +754,4 @@ encodeDataToRoute :: TransportCrypto
751encodeDataToRoute crypto (dta, Rendezvous pub ni) 754encodeDataToRoute crypto (dta, Rendezvous pub ni)
752 = Just ( OnionToRoute pub -- Public key of destination node 755 = Just ( OnionToRoute pub -- Public key of destination node
753 dta 756 dta
754 , OnionDestination ni Nothing ) 757 , OnionDestination SearchingAlias ni Nothing )