summaryrefslogtreecommitdiff
path: root/OnionTransport.hs
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2017-09-14 06:07:25 -0400
committerjoe <joe@jerkface.net>2017-09-14 06:07:25 -0400
commit384db9531ad8ffe4e9021fa07e396c7c68c1242f (patch)
tree6a489c277ae503d8643ad8ed41ae457608f782ba /OnionTransport.hs
parente6680dfb566c692d410a357f32ce021da871eb64 (diff)
Fixed onion protocol.
Diffstat (limited to 'OnionTransport.hs')
-rw-r--r--OnionTransport.hs81
1 files changed, 58 insertions, 23 deletions
diff --git a/OnionTransport.hs b/OnionTransport.hs
index 2a1003dc..96f9443f 100644
--- a/OnionTransport.hs
+++ b/OnionTransport.hs
@@ -46,6 +46,7 @@ import DHTTransport (NodeInfo(..),NodeId(..),SendNodes,nodeInfo,DHTPublicKey)
46import Debug.Trace 46import Debug.Trace
47import Control.Arrow 47import Control.Arrow
48import Control.Concurrent.STM 48import Control.Concurrent.STM
49import Control.Monad
49import qualified Data.ByteString as B 50import qualified Data.ByteString as B
50 ;import Data.ByteString (ByteString) 51 ;import Data.ByteString (ByteString)
51import Data.Coerce 52import Data.Coerce
@@ -62,6 +63,7 @@ import Data.Word
62import GHC.Generics () 63import GHC.Generics ()
63import GHC.TypeLits 64import GHC.TypeLits
64import Network.Socket 65import Network.Socket
66import System.IO
65 67
66type HandleLo a = Maybe (Either String (ByteString, SockAddr)) -> IO a 68type HandleLo a = Maybe (Either String (ByteString, SockAddr)) -> IO a
67 69
@@ -159,10 +161,9 @@ putOnionMsg (OnionAnnounceResponse n8 n24 x) = put (0x84 :: Word8) >> put n8 >>
159putOnionMsg (OnionToRouteResponse a) = putOnionAssym 0x86 (return ()) a 161putOnionMsg (OnionToRouteResponse a) = putOnionAssym 0x86 (return ()) a
160 162
161encodeOnionAddr :: (OnionMessage Encrypted,OnionToOwner) -> (ByteString, SockAddr) 163encodeOnionAddr :: (OnionMessage Encrypted,OnionToOwner) -> (ByteString, SockAddr)
162encodeOnionAddr (msg,addr) = ( runPut (putOnionMsg msg >> putpath), saddr ) 164encodeOnionAddr (msg,OnionToOwner ni p) = ( runPut $ putResponse (OnionResponse p msg)
163 where 165 , nodeAddr ni )
164 (saddr,putpath) | OnionToOwner ni p <- addr = (nodeAddr ni, put p) 166encodeOnionAddr (msg,OnionToMe a) = ( runPut (putOnionMsg msg), a)
165 | OnionToMe a <- addr = (a, return ())
166 167
167forwardOnions :: TransportCrypto -> UDPTransport -> UDPTransport -- HandleHi a -> IO a -> HandleLo a 168forwardOnions :: TransportCrypto -> UDPTransport -> UDPTransport -- HandleHi a -> IO a -> HandleLo a
168forwardOnions crypto udp = udp { awaitMessage = forwardAwait crypto udp } 169forwardOnions crypto udp = udp { awaitMessage = forwardAwait crypto udp }
@@ -224,6 +225,7 @@ instance ( Serialize (Forwarding (ThreeMinus n) (OnionMessage Encrypted))
224 , Serialize (ReturnPath n) 225 , Serialize (ReturnPath n)
225 ) => Serialize (OnionRequest n) where 226 ) => Serialize (OnionRequest n) where
226 get = do 227 get = do
228 -- TODO share code with 'getOnionRequest'
227 n24 <- get 229 n24 <- get
228 cnt <- remaining 230 cnt <- remaining
229 let fwdsize = case size :: Size (ReturnPath n) of ConstSize n -> cnt - n 231 let fwdsize = case size :: Size (ReturnPath n) of ConstSize n -> cnt - n
@@ -288,6 +290,14 @@ type N1 = S N0
288type N2 = S N1 290type N2 = S N1
289type N3 = S N2 291type N3 = S N2
290 292
293class KnownPeanoNat n where
294 peanoVal :: p n -> Int
295
296instance KnownPeanoNat N0 where
297 peanoVal _ = 0
298instance KnownPeanoNat n => KnownPeanoNat (S n) where
299 peanoVal _ = 1 + peanoVal (Proxy :: Proxy n)
300
291type family PeanoNat p where 301type family PeanoNat p where
292 PeanoNat N0 = 0 302 PeanoNat N0 = 0
293 PeanoNat (S n) = 1 + PeanoNat n 303 PeanoNat (S n) = 1 + PeanoNat n
@@ -339,7 +349,7 @@ instance KnownNat (PeanoNat n) => Show (ReturnPath n) where
339 349
340data Forwarding n msg where 350data Forwarding n msg where
341 NotForwarded :: msg -> Forwarding N0 msg 351 NotForwarded :: msg -> Forwarding N0 msg
342 Forwarding :: Assym (Encrypted (Addressed (Forwarding n msg))) -> Forwarding (S n) msg 352 Forwarding :: PublicKey -> Encrypted (Addressed (Forwarding n msg)) -> Forwarding (S n) msg
343 353
344instance Show msg => Show (Forwarding N0 msg) where 354instance Show msg => Show (Forwarding N0 msg) where
345 show (NotForwarded x) = "NotForwarded "++show x 355 show (NotForwarded x) = "NotForwarded "++show x
@@ -347,10 +357,11 @@ instance Show msg => Show (Forwarding N0 msg) where
347instance ( KnownNat (PeanoNat (S n)) 357instance ( KnownNat (PeanoNat (S n))
348 , Show (Encrypted (Addressed (Forwarding n msg))) 358 , Show (Encrypted (Addressed (Forwarding n msg)))
349 ) => Show (Forwarding (S n) msg) where 359 ) => Show (Forwarding (S n) msg) where
350 show (Forwarding a) = unwords [ "Forwarding" 360 show (Forwarding k a) = unwords [ "Forwarding"
351 , "("++show (natVal (Proxy :: Proxy (PeanoNat (S n))))++")" 361 , "("++show (natVal (Proxy :: Proxy (PeanoNat (S n))))++")"
352 , show a 362 , show (key2id k)
353 ] 363 , show a
364 ]
354 365
355instance Sized msg => Sized (Forwarding N0 msg) 366instance Sized msg => Sized (Forwarding N0 msg)
356 where size = case size :: Size msg of 367 where size = case size :: Size msg of
@@ -358,32 +369,36 @@ instance Sized msg => Sized (Forwarding N0 msg)
358 VarSize f -> VarSize $ \(NotForwarded x) -> f x 369 VarSize f -> VarSize $ \(NotForwarded x) -> f x
359 370
360instance Sized (Forwarding n msg) => Sized (Forwarding (S n) msg) 371instance Sized (Forwarding n msg) => Sized (Forwarding (S n) msg)
361 where size = case size :: Size (Assym (Encrypted (Addressed (Forwarding n msg)))) of 372 where size = ConstSize 32
362 ConstSize n -> ConstSize n 373 <> contramap (\(Forwarding _ e) -> e)
363 VarSize f -> VarSize $ \(Forwarding a) -> f a 374 (size :: Size (Encrypted (Addressed (Forwarding n msg))))
364 375
365instance Serialize msg => Serialize (Forwarding N0 msg) where 376instance Serialize msg => Serialize (Forwarding N0 msg) where
366 get = NotForwarded <$> get 377 get = NotForwarded <$> get
367 put (NotForwarded msg) = put msg 378 put (NotForwarded msg) = put msg
368 379
369instance (Serialize (Encrypted (Addressed (Forwarding n msg)))) => Serialize (Forwarding (S n) msg) where 380instance (Serialize (Encrypted (Addressed (Forwarding n msg)))) => Serialize (Forwarding (S n) msg) where
370 get = Forwarding <$> getAliasedAssym 381 get = Forwarding <$> getPublicKey <*> get
371 put (Forwarding x) = putAliasedAssym x 382 put (Forwarding k x) = putPublicKey k >> put x
372 383
373handleOnionRequest :: ( LessThanThree n 384handleOnionRequest :: forall a proxy n.
385 ( LessThanThree n
386 , KnownPeanoNat n
374 , Sized (ReturnPath n) 387 , Sized (ReturnPath n)
375 ) => proxy n -> TransportCrypto -> SockAddr -> UDPTransport -> IO a -> OnionRequest n -> IO a 388 ) => proxy n -> TransportCrypto -> SockAddr -> UDPTransport -> IO a -> OnionRequest n -> IO a
376handleOnionRequest proxy crypto saddr udp kont (OnionRequest nonce msg rpath) = do 389handleOnionRequest proxy crypto saddr udp kont (OnionRequest nonce msg rpath) = do
377 putStrLn "handleOnionRequest" 390 let n = peanoVal rpath
391 hPutStrLn stderr $ "handleOnionRequest " ++ show n
378 (sym, snonce) <- atomically ( (,) <$> transportSymmetric crypto 392 (sym, snonce) <- atomically ( (,) <$> transportSymmetric crypto
379 <*> transportNewNonce crypto ) 393 <*> transportNewNonce crypto )
380 case peelOnion crypto msg of 394 case peelOnion crypto nonce msg of
381 Left e -> do 395 Left e -> do
382 -- todo report encryption error 396 -- todo report encryption error
383 putStrLn $ "peelOnion: " ++ e 397 hPutStrLn stderr $ unwords [ "peelOnion:", show n, either show show (either4or6 saddr), e]
384 kont 398 kont
385 Right (Addressed dst msg') -> do 399 Right (Addressed dst msg') -> do
386 sendMessage udp dst (S.encode $ OnionRequest nonce msg' $ wrapSymmetric sym snonce saddr rpath) 400 hPutStrLn stderr $ unwords [ "peelOnion:", show n, either show show (either4or6 saddr), "SUCCESS"]
401 sendMessage udp dst (runPut $ putRequest $ OnionRequest nonce msg' $ wrapSymmetric sym snonce saddr rpath)
387 kont 402 kont
388 403
389wrapSymmetric :: Serialize (ReturnPath n) => 404wrapSymmetric :: Serialize (ReturnPath n) =>
@@ -397,20 +412,23 @@ peelSymmetric sym (ReturnPath nonce e) = decryptSymmetric sym nonce e >>= decode
397 412
398peelOnion :: Serialize (Addressed (Forwarding n t)) 413peelOnion :: Serialize (Addressed (Forwarding n t))
399 => TransportCrypto 414 => TransportCrypto
415 -> Nonce24
400 -> Forwarding (S n) t 416 -> Forwarding (S n) t
401 -> Either String (Addressed (Forwarding n t)) 417 -> Either String (Addressed (Forwarding n t))
402peelOnion crypto (Forwarding fwd) = 418peelOnion crypto nonce (Forwarding k fwd) =
403 fmap runIdentity $ uncomposed $ decryptMessage crypto (assymNonce fwd) (Right fwd) 419 fmap runIdentity $ uncomposed $ decryptMessage crypto nonce (Right $ Assym k nonce fwd)
404 420
405handleOnionResponse :: Serialize (ReturnPath n) => proxy (S n) -> TransportCrypto -> SockAddr -> UDPTransport -> IO a -> OnionResponse (S n) -> IO a 421handleOnionResponse :: (KnownPeanoNat n, Sized (ReturnPath n), Serialize (ReturnPath n)) => proxy (S n) -> TransportCrypto -> SockAddr -> UDPTransport -> IO a -> OnionResponse (S n) -> IO a
406handleOnionResponse proxy crypto saddr udp kont (OnionResponse path msg) = do 422handleOnionResponse proxy crypto saddr udp kont (OnionResponse path msg) = do
407 sym <- atomically $ transportSymmetric crypto 423 sym <- atomically $ transportSymmetric crypto
408 case peelSymmetric sym path of 424 case peelSymmetric sym path of
409 Left e -> do 425 Left e -> do
410 -- todo report encryption error 426 -- todo report encryption error
427 let n = peanoVal path
428 hPutStrLn stderr $ unwords [ "peelSymmetric:", show n, either show show (either4or6 saddr), e]
411 kont 429 kont
412 Right (Addressed dst path') -> do 430 Right (Addressed dst path') -> do
413 sendMessage udp dst (S.encode $ OnionResponse path' msg) 431 sendMessage udp dst (runPut $ putResponse $ OnionResponse path' msg)
414 kont 432 kont
415 433
416 434
@@ -419,6 +437,7 @@ data AnnounceRequest = AnnounceRequest
419 , announceSeeking :: NodeId -- Public key we are searching for 437 , announceSeeking :: NodeId -- Public key we are searching for
420 , announceKey :: NodeId -- Public key that we want those sending back data packets to use 438 , announceKey :: NodeId -- Public key that we want those sending back data packets to use
421 } 439 }
440 deriving Show
422 441
423instance Sized AnnounceRequest where size = ConstSize (32*3) 442instance Sized AnnounceRequest where size = ConstSize (32*3)
424 443
@@ -436,9 +455,24 @@ getOnionRequest = do
436 path <- get 455 path <- get
437 return (a,path) 456 return (a,path)
438 457
458putRequest :: (KnownPeanoNat n, Serialize (OnionRequest n)) => OnionRequest n -> Put
459putRequest req = do
460 putWord8 $ 0x80 + fromIntegral (peanoVal req)
461 put req
462
463putResponse :: (KnownPeanoNat n, Serialize (OnionResponse n)) => OnionResponse n -> Put
464putResponse resp = do
465 let tag = 0x8f - fromIntegral (peanoVal resp)
466 -- OnionResponse N0 is an alias for the OnionMessage Encrypted type which includes a tag
467 -- in it's Serialize instance.
468 when (tag /= 0x8f) (putWord8 tag)
469 put resp
470
471
439data KeyRecord = NotStored Nonce32 472data KeyRecord = NotStored Nonce32
440 | SendBackKey PublicKey 473 | SendBackKey PublicKey
441 | Acknowledged Nonce32 474 | Acknowledged Nonce32
475 deriving Show
442 476
443instance Sized KeyRecord where size = ConstSize 33 477instance Sized KeyRecord where size = ConstSize 33
444 478
@@ -457,6 +491,7 @@ data AnnounceResponse = AnnounceResponse
457 { is_stored :: KeyRecord 491 { is_stored :: KeyRecord
458 , announceNodes :: SendNodes 492 , announceNodes :: SendNodes
459 } 493 }
494 deriving Show
460 495
461instance Sized AnnounceResponse where 496instance Sized AnnounceResponse where
462 size = contramap is_stored size <> contramap announceNodes size 497 size = contramap is_stored size <> contramap announceNodes size