diff options
author | joe <joe@jerkface.net> | 2017-09-14 06:07:25 -0400 |
---|---|---|
committer | joe <joe@jerkface.net> | 2017-09-14 06:07:25 -0400 |
commit | 384db9531ad8ffe4e9021fa07e396c7c68c1242f (patch) | |
tree | 6a489c277ae503d8643ad8ed41ae457608f782ba /OnionTransport.hs | |
parent | e6680dfb566c692d410a357f32ce021da871eb64 (diff) |
Fixed onion protocol.
Diffstat (limited to 'OnionTransport.hs')
-rw-r--r-- | OnionTransport.hs | 81 |
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) | |||
46 | import Debug.Trace | 46 | import Debug.Trace |
47 | import Control.Arrow | 47 | import Control.Arrow |
48 | import Control.Concurrent.STM | 48 | import Control.Concurrent.STM |
49 | import Control.Monad | ||
49 | import qualified Data.ByteString as B | 50 | import qualified Data.ByteString as B |
50 | ;import Data.ByteString (ByteString) | 51 | ;import Data.ByteString (ByteString) |
51 | import Data.Coerce | 52 | import Data.Coerce |
@@ -62,6 +63,7 @@ import Data.Word | |||
62 | import GHC.Generics () | 63 | import GHC.Generics () |
63 | import GHC.TypeLits | 64 | import GHC.TypeLits |
64 | import Network.Socket | 65 | import Network.Socket |
66 | import System.IO | ||
65 | 67 | ||
66 | type HandleLo a = Maybe (Either String (ByteString, SockAddr)) -> IO a | 68 | type 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 >> | |||
159 | putOnionMsg (OnionToRouteResponse a) = putOnionAssym 0x86 (return ()) a | 161 | putOnionMsg (OnionToRouteResponse a) = putOnionAssym 0x86 (return ()) a |
160 | 162 | ||
161 | encodeOnionAddr :: (OnionMessage Encrypted,OnionToOwner) -> (ByteString, SockAddr) | 163 | encodeOnionAddr :: (OnionMessage Encrypted,OnionToOwner) -> (ByteString, SockAddr) |
162 | encodeOnionAddr (msg,addr) = ( runPut (putOnionMsg msg >> putpath), saddr ) | 164 | encodeOnionAddr (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) | 166 | encodeOnionAddr (msg,OnionToMe a) = ( runPut (putOnionMsg msg), a) |
165 | | OnionToMe a <- addr = (a, return ()) | ||
166 | 167 | ||
167 | forwardOnions :: TransportCrypto -> UDPTransport -> UDPTransport -- HandleHi a -> IO a -> HandleLo a | 168 | forwardOnions :: TransportCrypto -> UDPTransport -> UDPTransport -- HandleHi a -> IO a -> HandleLo a |
168 | forwardOnions crypto udp = udp { awaitMessage = forwardAwait crypto udp } | 169 | forwardOnions 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 | |||
288 | type N2 = S N1 | 290 | type N2 = S N1 |
289 | type N3 = S N2 | 291 | type N3 = S N2 |
290 | 292 | ||
293 | class KnownPeanoNat n where | ||
294 | peanoVal :: p n -> Int | ||
295 | |||
296 | instance KnownPeanoNat N0 where | ||
297 | peanoVal _ = 0 | ||
298 | instance KnownPeanoNat n => KnownPeanoNat (S n) where | ||
299 | peanoVal _ = 1 + peanoVal (Proxy :: Proxy n) | ||
300 | |||
291 | type family PeanoNat p where | 301 | type 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 | ||
340 | data Forwarding n msg where | 350 | data 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 | ||
344 | instance Show msg => Show (Forwarding N0 msg) where | 354 | instance 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 | |||
347 | instance ( KnownNat (PeanoNat (S n)) | 357 | instance ( 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 | ||
355 | instance Sized msg => Sized (Forwarding N0 msg) | 366 | instance 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 | ||
360 | instance Sized (Forwarding n msg) => Sized (Forwarding (S n) msg) | 371 | instance 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 | ||
365 | instance Serialize msg => Serialize (Forwarding N0 msg) where | 376 | instance 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 | ||
369 | instance (Serialize (Encrypted (Addressed (Forwarding n msg)))) => Serialize (Forwarding (S n) msg) where | 380 | instance (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 | ||
373 | handleOnionRequest :: ( LessThanThree n | 384 | handleOnionRequest :: 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 |
376 | handleOnionRequest proxy crypto saddr udp kont (OnionRequest nonce msg rpath) = do | 389 | handleOnionRequest 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 | ||
389 | wrapSymmetric :: Serialize (ReturnPath n) => | 404 | wrapSymmetric :: Serialize (ReturnPath n) => |
@@ -397,20 +412,23 @@ peelSymmetric sym (ReturnPath nonce e) = decryptSymmetric sym nonce e >>= decode | |||
397 | 412 | ||
398 | peelOnion :: Serialize (Addressed (Forwarding n t)) | 413 | peelOnion :: 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)) |
402 | peelOnion crypto (Forwarding fwd) = | 418 | peelOnion 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 | ||
405 | handleOnionResponse :: Serialize (ReturnPath n) => proxy (S n) -> TransportCrypto -> SockAddr -> UDPTransport -> IO a -> OnionResponse (S n) -> IO a | 421 | handleOnionResponse :: (KnownPeanoNat n, Sized (ReturnPath n), Serialize (ReturnPath n)) => proxy (S n) -> TransportCrypto -> SockAddr -> UDPTransport -> IO a -> OnionResponse (S n) -> IO a |
406 | handleOnionResponse proxy crypto saddr udp kont (OnionResponse path msg) = do | 422 | handleOnionResponse 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 | ||
423 | instance Sized AnnounceRequest where size = ConstSize (32*3) | 442 | instance 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 | ||
458 | putRequest :: (KnownPeanoNat n, Serialize (OnionRequest n)) => OnionRequest n -> Put | ||
459 | putRequest req = do | ||
460 | putWord8 $ 0x80 + fromIntegral (peanoVal req) | ||
461 | put req | ||
462 | |||
463 | putResponse :: (KnownPeanoNat n, Serialize (OnionResponse n)) => OnionResponse n -> Put | ||
464 | putResponse 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 | |||
439 | data KeyRecord = NotStored Nonce32 | 472 | data KeyRecord = NotStored Nonce32 |
440 | | SendBackKey PublicKey | 473 | | SendBackKey PublicKey |
441 | | Acknowledged Nonce32 | 474 | | Acknowledged Nonce32 |
475 | deriving Show | ||
442 | 476 | ||
443 | instance Sized KeyRecord where size = ConstSize 33 | 477 | instance 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 | ||
461 | instance Sized AnnounceResponse where | 496 | instance Sized AnnounceResponse where |
462 | size = contramap is_stored size <> contramap announceNodes size | 497 | size = contramap is_stored size <> contramap announceNodes size |