diff options
Diffstat (limited to 'src/Network/Tox/Onion/Transport.hs')
-rw-r--r-- | src/Network/Tox/Onion/Transport.hs | 98 |
1 files changed, 83 insertions, 15 deletions
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 |