summaryrefslogtreecommitdiff
path: root/src/Network/Tox
diff options
context:
space:
mode:
Diffstat (limited to 'src/Network/Tox')
-rw-r--r--src/Network/Tox/DHT/Transport.hs3
-rw-r--r--src/Network/Tox/Onion/Handlers.hs3
-rw-r--r--src/Network/Tox/Onion/Transport.hs98
3 files changed, 89 insertions, 15 deletions
diff --git a/src/Network/Tox/DHT/Transport.hs b/src/Network/Tox/DHT/Transport.hs
index 0787c2c1..47505a21 100644
--- a/src/Network/Tox/DHT/Transport.hs
+++ b/src/Network/Tox/DHT/Transport.hs
@@ -210,6 +210,8 @@ data DHTPublicKey = DHTPublicKey
210 , dhtpk :: PublicKey -- dht public key 210 , dhtpk :: PublicKey -- dht public key
211 , dhtpkNodes :: SendNodes -- other reachable nodes 211 , dhtpkNodes :: SendNodes -- other reachable nodes
212 } 212 }
213 deriving (Eq, Show)
214
213 215
214-- int8_t (0x20 sent over onion, 0x12 for sent over net_crypto) 216-- int8_t (0x20 sent over onion, 0x12 for sent over net_crypto)
215-- [uint32_t nospam][Message (UTF8) 1 to ONION_CLIENT_MAX_DATA_SIZE bytes] 217-- [uint32_t nospam][Message (UTF8) 1 to ONION_CLIENT_MAX_DATA_SIZE bytes]
@@ -217,6 +219,7 @@ data FriendRequest = FriendRequest
217 { friendNoSpam :: Word32 219 { friendNoSpam :: Word32
218 , friendRequestText :: ByteString -- UTF8 220 , friendRequestText :: ByteString -- UTF8
219 } 221 }
222 deriving (Eq, Show)
220 223
221-- When sent as a DHT request packet (this is the data sent in the DHT request 224-- When sent as a DHT request packet (this is the data sent in the DHT request
222-- packet): 225-- packet):
diff --git a/src/Network/Tox/Onion/Handlers.hs b/src/Network/Tox/Onion/Handlers.hs
index 3eec0390..76908df8 100644
--- a/src/Network/Tox/Onion/Handlers.hs
+++ b/src/Network/Tox/Onion/Handlers.hs
@@ -117,13 +117,16 @@ dataToRouteH ::
117 -> IO () 117 -> IO ()
118dataToRouteH keydb udp _ (OnionToRoute pub asymm) = do 118dataToRouteH keydb udp _ (OnionToRoute pub asymm) = do
119 let k = key2id pub 119 let k = key2id pub
120 hPutStrLn stderr $ "dataToRouteH "++ show k
120 mb <- atomically $ do 121 mb <- atomically $ do
121 ks <- readTVar keydb 122 ks <- readTVar keydb
122 forM (MinMaxPSQ.lookup' k (keyAssoc ks)) $ \(p,(cnt,rpath)) -> do 123 forM (MinMaxPSQ.lookup' k (keyAssoc ks)) $ \(p,(cnt,rpath)) -> do
123 writeTVar keydb $ ks { keyAssoc = MinMaxPSQ.insert' k (cnt + 1, rpath) p (keyAssoc ks) } 124 writeTVar keydb $ ks { keyAssoc = MinMaxPSQ.insert' k (cnt + 1, rpath) p (keyAssoc ks) }
124 return rpath 125 return rpath
126 hPutStrLn stderr $ "dataToRouteH "++ show (fmap (const ()) mb)
125 forM_ mb $ \rpath -> do 127 forM_ mb $ \rpath -> do
126 -- forward 128 -- forward
129 hPutStrLn stderr $ "dataToRouteH sendMessage"
127 sendMessage udp (toOnionDestination rpath) $ OnionToRouteResponse asymm 130 sendMessage udp (toOnionDestination rpath) $ OnionToRouteResponse asymm
128 hPutStrLn stderr $ "Forwarding data-to-route -->"++show k 131 hPutStrLn stderr $ "Forwarding data-to-route -->"++show k
129 132
diff --git a/src/Network/Tox/Onion/Transport.hs b/src/Network/Tox/Onion/Transport.hs
index 6635fad1..85cf095d 100644
--- a/src/Network/Tox/Onion/Transport.hs
+++ b/src/Network/Tox/Onion/Transport.hs
@@ -44,6 +44,8 @@ module Network.Tox.Onion.Transport
44 , onionKey 44 , onionKey
45 , onionAliasSelector 45 , onionAliasSelector
46 , selectAlias 46 , selectAlias
47 , RouteId(..)
48 , routeId
47 ) where 49 ) where
48 50
49import Network.Address (fromSockAddr,toSockAddr,setPort,either4or6,sockAddrPort) 51import Network.Address (fromSockAddr,toSockAddr,setPort,either4or6,sockAddrPort)
@@ -51,7 +53,7 @@ import Network.QueryResponse
51import Crypto.Tox hiding (encrypt,decrypt) 53import Crypto.Tox hiding (encrypt,decrypt)
52import Network.Tox.NodeId 54import Network.Tox.NodeId
53import qualified Crypto.Tox as ToxCrypto 55import qualified Crypto.Tox as ToxCrypto
54import Network.Tox.DHT.Transport (NodeInfo(..),NodeId(..),SendNodes(..),nodeInfo,DHTPublicKey,FriendRequest,asymNodeInfo) 56import Network.Tox.DHT.Transport (NodeInfo(..),NodeId(..),SendNodes(..),nodeInfo,DHTPublicKey(..),FriendRequest,asymNodeInfo)
55 57
56import Control.Applicative 58import Control.Applicative
57import Control.Arrow 59import Control.Arrow
@@ -76,6 +78,7 @@ import GHC.TypeLits
76import Network.Socket 78import Network.Socket
77import System.IO 79import System.IO
78import qualified Text.ParserCombinators.ReadP as RP 80import qualified Text.ParserCombinators.ReadP as RP
81import Data.Hashable
79 82
80type HandleLo a = Maybe (Either String (ByteString, SockAddr)) -> IO a 83type HandleLo a = Maybe (Either String (ByteString, SockAddr)) -> IO a
81 84
@@ -200,15 +203,44 @@ putOnionMsg (OnionToRoute pubkey a) = putOnionAsymm 0x85 (putPublicKey
200putOnionMsg (OnionAnnounceResponse n8 n24 x) = put (0x84 :: Word8) >> put n8 >> put n24 >> put x 203putOnionMsg (OnionAnnounceResponse n8 n24 x) = put (0x84 :: Word8) >> put n8 >> put n24 >> put x
201putOnionMsg (OnionToRouteResponse a) = putOnionAsymm 0x86 (return ()) a 204putOnionMsg (OnionToRouteResponse a) = putOnionAsymm 0x86 (return ()) a
202 205
203encodeOnionAddr :: (NodeInfo -> r -> IO (Maybe OnionRoute)) 206newtype RouteId = RouteId Int
204 -> (OnionMessage Encrypted,OnionDestination r) 207 deriving Show
208
209
210-- We used to derive the RouteId from the Nonce8 associated with the query.
211-- This is problematic because a nonce generated by toxcore will not validate
212-- if it is received via a different route than it was issued. This is
213-- described by the Tox spec:
214--
215-- Toxcore generates `ping_id`s by taking a 32 byte sha hash of the current
216-- time, some secret bytes generated when the instance is created, the
217-- current time divided by a 20 second timeout, the public key of the
218-- requester and the source ip/port that the packet was received from. Since
219-- the ip/port that the packet was received from is in the `ping_id`, the
220-- announce packets being sent with a ping id must be sent using the same
221-- path as the packet that we received the `ping_id` from or announcing will
222-- fail.
223--
224-- The original idea was:
225--
226-- > routeId :: Nonce8 -> RouteId
227-- > routeId (Nonce8 w8) = RouteId $ mod (fromIntegral w8) 12
228--
229-- Instead, we'll just hash the destination node id.
230routeId :: NodeId -> RouteId
231routeId nid = RouteId $ mod (hash nid) 12
232
233
234encodeOnionAddr :: (NodeInfo -> RouteId -> IO (Maybe OnionRoute))
235 -> (OnionMessage Encrypted,OnionDestination RouteId)
205 -> IO (Maybe (ByteString, SockAddr)) 236 -> IO (Maybe (ByteString, SockAddr))
206encodeOnionAddr _ (msg,OnionToOwner ni p) = 237encodeOnionAddr _ (msg,OnionToOwner ni p) =
207 return $ Just ( runPut $ putResponse (OnionResponse p msg) 238 return $ Just ( runPut $ putResponse (OnionResponse p msg)
208 , nodeAddr ni ) 239 , nodeAddr ni )
209encodeOnionAddr _ (msg,OnionDestination _ _ Nothing) = do 240encodeOnionAddr getRoute (msg,OnionDestination x ni Nothing) = do
210 hPutStrLn stderr $ "ONION encode missing routeid" 241 encodeOnionAddr getRoute (msg,OnionDestination x ni (Just $ routeId $ nodeId ni) )
211 return Nothing 242 -- hPutStrLn stderr $ "ONION encode missing routeid"
243 -- return Nothing
212encodeOnionAddr getRoute (msg,OnionDestination _ ni (Just rid)) = do 244encodeOnionAddr getRoute (msg,OnionDestination _ ni (Just rid)) = do
213 let go route = do 245 let go route = do
214 return ( runPut $ putRequest $ wrapForRoute msg ni route 246 return ( runPut $ putRequest $ wrapForRoute msg ni route
@@ -601,6 +633,7 @@ data OnionData
601 -- 633 --
602 -- 634 --
603 OnionFriendRequest FriendRequest -- 0x20 635 OnionFriendRequest FriendRequest -- 0x20
636 deriving (Eq,Show)
604 637
605instance Sized OnionData where 638instance Sized OnionData where
606 size = VarSize $ \case 639 size = VarSize $ \case
@@ -790,26 +823,46 @@ parseDataToRoute
790 :: TransportCrypto 823 :: TransportCrypto
791 -> (OnionMessage Encrypted,OnionDestination r) 824 -> (OnionMessage Encrypted,OnionDestination r)
792 -> IO (Either ((PublicKey,OnionData),AnnouncedRendezvous) (OnionMessage Encrypted, OnionDestination r)) 825 -> IO (Either ((PublicKey,OnionData),AnnouncedRendezvous) (OnionMessage Encrypted, OnionDestination r))
793parseDataToRoute crypto (OnionToRouteResponse dta, od) = 826parseDataToRoute crypto (OnionToRouteResponse dta, od) = do
794 return $ either (const $ Right (OnionToRouteResponse dta,od)) Left $ do 827 ks <- atomically $ readTVar $ userKeys crypto
795 -- XXX: Do something with decryption failure? 828
796 dtr <- fmap runIdentity 829 let eOuter = do
830 fmap runIdentity
797 $ uncomposed 831 $ uncomposed
798 $ decryptMessage (rendezvousSecret crypto,rendezvousPublic crypto) 832 $ decryptMessage (rendezvousSecret crypto,rendezvousPublic crypto)
799 (asymmNonce dta) 833 (asymmNonce dta)
800 (Right dta) 834 (Right dta) -- using Asymm{senderKey} as remote key
801 let (sk,pk) = case onionAliasSelector od of 835
802 SearchingAlias -> (onionAliasSecret &&& onionAliasPublic) crypto 836 -- TODO: We don't currently have a way to look up which user key we
803 AnnouncingAlias sk pk -> (sk,pk) 837 -- announced using along this onion route. Therefore, for now, we will
838 -- try all our user keys to see if any can decrypt the packet.
839 eInners = flip map ks $ \(sk,pk) -> do
840 dtr <- eOuter
804 omsg <- fmap runIdentity 841 omsg <- fmap runIdentity
805 $ uncomposed 842 $ uncomposed
806 $ decryptMessage (sk,pk) 843 $ decryptMessage (sk,pk)
807 (asymmNonce dta) 844 (asymmNonce dta)
808 (Left (dataFromKey dtr, dataToRoute dtr)) 845 (Left (dataFromKey dtr, dataToRoute dtr))
846 return (pk,dtr,omsg)
847
848 eInner = foldr1 (<|>) eInners
849
850 e = do
851 (pk,dtr,omsg) <- eInner
809 return ( (pk, omsg) 852 return ( (pk, omsg)
810 , AnnouncedRendezvous 853 , AnnouncedRendezvous
811 (dataFromKey dtr) 854 (dataFromKey dtr)
812 $ Rendezvous (rendezvousPublic crypto) $ onionNodeInfo od ) 855 $ Rendezvous (rendezvousPublic crypto) $ onionNodeInfo od )
856 r = either (const $ Right (OnionToRouteResponse dta,od)) Left e
857 -- parseDataToRoute OnionToRouteResponse decipherAndAuth: auth fail
858 hPutStrLn stderr $ unlines
859 [ "parseDataToRoute " ++ either id (const "Right") e
860 , " crypto inner.me =" ++ either id (\(pk,_,_) -> show $ key2id pk) eInner
861 , " inner.you=" ++ either id (show . key2id . dataFromKey) eOuter
862 , " outer.me =" ++ show (key2id $ rendezvousPublic crypto)
863 , " outer.you=" ++ show (key2id $ senderKey dta)
864 ]
865 return r
813parseDataToRoute _ msg = return $ Right msg 866parseDataToRoute _ msg = return $ Right msg
814 867
815encodeDataToRoute :: TransportCrypto 868encodeDataToRoute :: TransportCrypto
@@ -825,7 +878,22 @@ encodeDataToRoute crypto ((me,omsg), AnnouncedRendezvous toxid (Rendezvous pub n
825 , dataToRoute = encryptMessage sk toxid nonce omsg 878 , dataToRoute = encryptMessage sk toxid nonce omsg
826 } 879 }
827 let dta = encryptMessage (onionAliasSecret crypto) pub nonce plain 880 let dta = encryptMessage (onionAliasSecret crypto) pub nonce plain
828 return $ Just ( OnionToRoute pub -- Public key of destination node 881 hPutStrLn stderr $ unlines
882 [ "encodeDataToRoute me=" ++ show (key2id me)
883 , " dhtpk=" ++ case omsg of
884 OnionDHTPublicKey dmsg -> show (key2id $ dhtpk dmsg)
885 OnionFriendRequest fr -> "friend request"
886 , " ns=" ++ case omsg of
887 OnionDHTPublicKey dmsg -> show (dhtpkNodes dmsg)
888 OnionFriendRequest fr -> "friend request"
889 , " crypto inner.me =" ++ show (key2id pk)
890 , " inner.you=" ++ show (key2id toxid)
891 , " outer.me =" ++ show (key2id $ onionAliasPublic crypto)
892 , " outer.you=" ++ show (key2id pub)
893 , " " ++ show (AnnouncedRendezvous toxid (Rendezvous pub ni))
894 , " " ++ show dta
895 ]
896 return $ Just ( OnionToRoute toxid -- Public key of destination node
829 Asymm { senderKey = onionAliasPublic crypto 897 Asymm { senderKey = onionAliasPublic crypto
830 , asymmNonce = nonce 898 , asymmNonce = nonce
831 , asymmData = dta 899 , asymmData = dta