diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Network/Tox.hs | 4 | ||||
-rw-r--r-- | src/Network/Tox/DHT/Transport.hs | 3 | ||||
-rw-r--r-- | src/Network/Tox/Onion/Handlers.hs | 3 | ||||
-rw-r--r-- | src/Network/Tox/Onion/Transport.hs | 98 |
4 files changed, 91 insertions, 17 deletions
diff --git a/src/Network/Tox.hs b/src/Network/Tox.hs index 93e3c663..29591a23 100644 --- a/src/Network/Tox.hs +++ b/src/Network/Tox.hs | |||
@@ -247,12 +247,12 @@ addVerbosity :: Transport err SockAddr ByteString -> Transport err SockAddr Byte | |||
247 | addVerbosity tr = | 247 | addVerbosity tr = |
248 | tr { awaitMessage = \kont -> awaitMessage tr $ \m -> do | 248 | tr { awaitMessage = \kont -> awaitMessage tr $ \m -> do |
249 | forM_ m $ mapM_ $ \(msg,addr) -> do | 249 | forM_ m $ mapM_ $ \(msg,addr) -> do |
250 | when (isLocalHost addr || not (B.null msg || elem (B.head msg) [0,1,2,4,0x81,0x82,0x8c,0x8d])) $ do | 250 | when (not (B.null msg || elem (B.head msg) [0,1,2,4,0x81,0x82,0x8c,0x8d])) $ do |
251 | mapM_ (\x -> hPutStrLn stderr ( (show addr) ++ " --> " ++ x)) | 251 | mapM_ (\x -> hPutStrLn stderr ( (show addr) ++ " --> " ++ x)) |
252 | $ xxd 0 msg | 252 | $ xxd 0 msg |
253 | kont m | 253 | kont m |
254 | , sendMessage = \addr msg -> do | 254 | , sendMessage = \addr msg -> do |
255 | when (isLocalHost addr || not (B.null msg || elem (B.head msg) [0,1,2,4,0x81,0x82,0x8c,0x8d])) $ do | 255 | when (not (B.null msg || elem (B.head msg) [0,1,2,4,0x81,0x8c,0x8d])) $ do |
256 | mapM_ (\x -> hPutStrLn stderr ( (show addr) ++ " <-- " ++ x)) | 256 | mapM_ (\x -> hPutStrLn stderr ( (show addr) ++ " <-- " ++ x)) |
257 | $ xxd 0 msg | 257 | $ xxd 0 msg |
258 | sendMessage tr addr msg | 258 | sendMessage tr addr msg |
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 () |
118 | dataToRouteH keydb udp _ (OnionToRoute pub asymm) = do | 118 | dataToRouteH 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 | ||
49 | import Network.Address (fromSockAddr,toSockAddr,setPort,either4or6,sockAddrPort) | 51 | import Network.Address (fromSockAddr,toSockAddr,setPort,either4or6,sockAddrPort) |
@@ -51,7 +53,7 @@ import Network.QueryResponse | |||
51 | import Crypto.Tox hiding (encrypt,decrypt) | 53 | import Crypto.Tox hiding (encrypt,decrypt) |
52 | import Network.Tox.NodeId | 54 | import Network.Tox.NodeId |
53 | import qualified Crypto.Tox as ToxCrypto | 55 | import qualified Crypto.Tox as ToxCrypto |
54 | import Network.Tox.DHT.Transport (NodeInfo(..),NodeId(..),SendNodes(..),nodeInfo,DHTPublicKey,FriendRequest,asymNodeInfo) | 56 | import Network.Tox.DHT.Transport (NodeInfo(..),NodeId(..),SendNodes(..),nodeInfo,DHTPublicKey(..),FriendRequest,asymNodeInfo) |
55 | 57 | ||
56 | import Control.Applicative | 58 | import Control.Applicative |
57 | import Control.Arrow | 59 | import Control.Arrow |
@@ -76,6 +78,7 @@ import GHC.TypeLits | |||
76 | import Network.Socket | 78 | import Network.Socket |
77 | import System.IO | 79 | import System.IO |
78 | import qualified Text.ParserCombinators.ReadP as RP | 80 | import qualified Text.ParserCombinators.ReadP as RP |
81 | import Data.Hashable | ||
79 | 82 | ||
80 | type HandleLo a = Maybe (Either String (ByteString, SockAddr)) -> IO a | 83 | type HandleLo a = Maybe (Either String (ByteString, SockAddr)) -> IO a |
81 | 84 | ||
@@ -200,15 +203,44 @@ putOnionMsg (OnionToRoute pubkey a) = putOnionAsymm 0x85 (putPublicKey | |||
200 | putOnionMsg (OnionAnnounceResponse n8 n24 x) = put (0x84 :: Word8) >> put n8 >> put n24 >> put x | 203 | putOnionMsg (OnionAnnounceResponse n8 n24 x) = put (0x84 :: Word8) >> put n8 >> put n24 >> put x |
201 | putOnionMsg (OnionToRouteResponse a) = putOnionAsymm 0x86 (return ()) a | 204 | putOnionMsg (OnionToRouteResponse a) = putOnionAsymm 0x86 (return ()) a |
202 | 205 | ||
203 | encodeOnionAddr :: (NodeInfo -> r -> IO (Maybe OnionRoute)) | 206 | newtype 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. | ||
230 | routeId :: NodeId -> RouteId | ||
231 | routeId nid = RouteId $ mod (hash nid) 12 | ||
232 | |||
233 | |||
234 | encodeOnionAddr :: (NodeInfo -> RouteId -> IO (Maybe OnionRoute)) | ||
235 | -> (OnionMessage Encrypted,OnionDestination RouteId) | ||
205 | -> IO (Maybe (ByteString, SockAddr)) | 236 | -> IO (Maybe (ByteString, SockAddr)) |
206 | encodeOnionAddr _ (msg,OnionToOwner ni p) = | 237 | encodeOnionAddr _ (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 ) |
209 | encodeOnionAddr _ (msg,OnionDestination _ _ Nothing) = do | 240 | encodeOnionAddr 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 | ||
212 | encodeOnionAddr getRoute (msg,OnionDestination _ ni (Just rid)) = do | 244 | encodeOnionAddr 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 | ||
605 | instance Sized OnionData where | 638 | instance 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)) |
793 | parseDataToRoute crypto (OnionToRouteResponse dta, od) = | 826 | parseDataToRoute 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 | ||
813 | parseDataToRoute _ msg = return $ Right msg | 866 | parseDataToRoute _ msg = return $ Right msg |
814 | 867 | ||
815 | encodeDataToRoute :: TransportCrypto | 868 | encodeDataToRoute :: 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 |