actually check p2p authtokens for tor connections

This commit was sponsored by Ethan Aubin.
This commit is contained in:
Joey Hess 2016-11-30 16:38:16 -04:00
parent b88e44ea9a
commit e714e0f67a
No known key found for this signature in database
GPG key ID: C910D9222512E3C7
3 changed files with 49 additions and 29 deletions

View file

@ -60,7 +60,13 @@ connectService address port service = do
myuuid <- getUUID myuuid <- getUUID
g <- Annex.gitRepo g <- Annex.gitRepo
h <- liftIO $ torHandle =<< connectHiddenService address port h <- liftIO $ torHandle =<< connectHiddenService address port
runNetProtoHandle h h g $ do let runenv = RunEnv
{ runRepo = g
, runCheckAuth = const False
, runIhdl = h
, runOhdl = h
}
runNetProtoHandle runenv $ do
v <- auth myuuid authtoken v <- auth myuuid authtoken
case v of case v of
Just _theiruuid -> connect service stdin stdout Just _theiruuid -> connect service stdin stdout

View file

@ -5,17 +5,19 @@
- Licensed under the GNU GPL version 3 or higher. - Licensed under the GNU GPL version 3 or higher.
-} -}
{-# LANGUAGE RankNTypes, CPP #-} {-# LANGUAGE RankNTypes, ScopedTypeVariables, CPP #-}
module P2P.IO module P2P.IO
( RunProto ( RunEnv(..)
, runNetProtoHandle , runNetProtoHandle
, runNetHandle
) where ) where
import P2P.Protocol import P2P.Protocol
import Utility.Process import Utility.Process
import Git import Git
import Git.Command import Git.Command
import Utility.AuthToken
import Utility.SafeCommand import Utility.SafeCommand
import Utility.SimpleProtocol import Utility.SimpleProtocol
import Utility.Exception import Utility.Exception
@ -32,33 +34,34 @@ import qualified Data.ByteString.Lazy as L
type RunProto = forall a m. (MonadIO m, MonadMask m) => Proto a -> m (Maybe a) type RunProto = forall a m. (MonadIO m, MonadMask m) => Proto a -> m (Maybe a)
data S = S data RunEnv = RunEnv
{ repo :: Repo { runRepo :: Repo
, ihdl :: Handle , runCheckAuth :: (AuthToken -> Bool)
, ohdl :: Handle , runIhdl :: Handle
, runOhdl :: Handle
} }
-- Implementation of the protocol, communicating with a peer -- Implementation of the protocol, communicating with a peer
-- over a Handle. No Local actions will be run. -- over a Handle. No Local actions will be run.
runNetProtoHandle :: (MonadIO m, MonadMask m) => Handle -> Handle -> Repo -> Proto a -> m (Maybe a) runNetProtoHandle :: (MonadIO m, MonadMask m) => RunEnv -> Proto a -> m (Maybe a)
runNetProtoHandle i o r = go runNetProtoHandle runenv = go
where where
go :: RunProto go :: RunProto
go (Pure v) = pure (Just v) go (Pure v) = pure (Just v)
go (Free (Net n)) = runNetHandle (S r i o) go n go (Free (Net n)) = runNetHandle runenv go n
go (Free (Local _)) = return Nothing go (Free (Local _)) = return Nothing
runNetHandle :: (MonadIO m, MonadMask m) => S -> RunProto -> NetF (Proto a) -> m (Maybe a) runNetHandle :: (MonadIO m, MonadMask m) => RunEnv -> RunProto -> NetF (Proto a) -> m (Maybe a)
runNetHandle s runner f = case f of runNetHandle runenv runner f = case f of
SendMessage m next -> do SendMessage m next -> do
v <- liftIO $ tryIO $ do v <- liftIO $ tryIO $ do
hPutStrLn (ohdl s) (unwords (formatMessage m)) hPutStrLn (runOhdl runenv) (unwords (formatMessage m))
hFlush (ohdl s) hFlush (runOhdl runenv)
case v of case v of
Left _e -> return Nothing Left _e -> return Nothing
Right () -> runner next Right () -> runner next
ReceiveMessage next -> do ReceiveMessage next -> do
v <- liftIO $ tryIO $ hGetLine (ihdl s) v <- liftIO $ tryIO $ hGetLine (runIhdl runenv)
case v of case v of
Left _e -> return Nothing Left _e -> return Nothing
Right l -> case parseMessage l of Right l -> case parseMessage l of
@ -69,18 +72,18 @@ runNetHandle s runner f = case f of
next e next e
SendBytes _len b next -> do SendBytes _len b next -> do
v <- liftIO $ tryIO $ do v <- liftIO $ tryIO $ do
L.hPut (ohdl s) b L.hPut (runOhdl runenv) b
hFlush (ohdl s) hFlush (runOhdl runenv)
case v of case v of
Left _e -> return Nothing Left _e -> return Nothing
Right () -> runner next Right () -> runner next
ReceiveBytes (Len n) next -> do ReceiveBytes (Len n) next -> do
v <- liftIO $ tryIO $ L.hGet (ihdl s) (fromIntegral n) v <- liftIO $ tryIO $ L.hGet (runIhdl runenv) (fromIntegral n)
case v of case v of
Left _e -> return Nothing Left _e -> return Nothing
Right b -> runner (next b) Right b -> runner (next b)
CheckAuthToken u t next -> do CheckAuthToken _u t next -> do
authed <- return True -- TODO XXX FIXME really check let authed = runCheckAuth runenv t
runner (next authed) runner (next authed)
Relay hin hout next -> do Relay hin hout next -> do
v <- liftIO $ runRelay runner hin hout v <- liftIO $ runRelay runner hin hout
@ -88,7 +91,7 @@ runNetHandle s runner f = case f of
Nothing -> return Nothing Nothing -> return Nothing
Just exitcode -> runner (next exitcode) Just exitcode -> runner (next exitcode)
RelayService service next -> do RelayService service next -> do
v <- liftIO $ runRelayService s runner service v <- liftIO $ runRelayService runenv runner service
case v of case v of
Nothing -> return Nothing Nothing -> return Nothing
Just () -> runner next Just () -> runner next
@ -108,8 +111,8 @@ runRelay runner (RelayHandle hout) (RelayHandle hin) = bracket setup cleanup go
go v = relayHelper runner v hin go v = relayHelper runner v hin
runRelayService :: S -> RunProto -> Service -> IO (Maybe ()) runRelayService :: RunEnv -> RunProto -> Service -> IO (Maybe ())
runRelayService s runner service = bracket setup cleanup go runRelayService runenv runner service = bracket setup cleanup go
where where
cmd = case service of cmd = case service of
UploadPack -> "upload-pack" UploadPack -> "upload-pack"
@ -117,8 +120,8 @@ runRelayService s runner service = bracket setup cleanup go
serviceproc = gitCreateProcess serviceproc = gitCreateProcess
[ Param cmd [ Param cmd
, File (repoPath (repo s)) , File (repoPath (runRepo runenv))
] (repo s) ] (runRepo runenv)
setup = do setup = do
(Just hin, Just hout, _, pid) <- createProcess serviceproc (Just hin, Just hout, _, pid) <- createProcess serviceproc

View file

@ -12,9 +12,11 @@ import RemoteDaemon.Types
import RemoteDaemon.Common import RemoteDaemon.Common
import Utility.Tor import Utility.Tor
import Utility.FileMode import Utility.FileMode
import Utility.AuthToken
import Remote.Helper.Tor import Remote.Helper.Tor
import P2P.Protocol import P2P.Protocol
import P2P.IO import P2P.IO
import P2P.Auth
import Annex.UUID import Annex.UUID
import Types.UUID import Types.UUID
import Messages import Messages
@ -33,7 +35,7 @@ server th@(TransportHandle (LocalRepo r) _) = do
q <- newTBQueueIO maxConnections q <- newTBQueueIO maxConnections
replicateM_ maxConnections $ replicateM_ maxConnections $
forkIO $ forever $ serveClient u r q forkIO $ forever $ serveClient th u r q
uid <- getRealUserID uid <- getRealUserID
let ident = fromUUID u let ident = fromUUID u
@ -66,12 +68,21 @@ server th@(TransportHandle (LocalRepo r) _) = do
maxConnections :: Int maxConnections :: Int
maxConnections = 10 maxConnections = 10
serveClient :: UUID -> Repo -> TBQueue Handle -> IO () serveClient :: TransportHandle -> UUID -> Repo -> TBQueue Handle -> IO ()
serveClient u r q = bracket setup cleanup go serveClient th u r q = bracket setup cleanup go
where where
setup = atomically $ readTBQueue q setup = atomically $ readTBQueue q
cleanup = hClose cleanup = hClose
go h = do go h = do
debugM "remotedaemon" "serving a TOR connection" debugM "remotedaemon" "serving a TOR connection"
void $ runNetProtoHandle h h r (serve u) -- Load auth tokens for every connection, to notice
-- when the allowed set is changed.
allowed <- liftAnnex th loadP2PAuthTokens
let runenv = RunEnv
{ runRepo = r
, runCheckAuth = (`isAllowedAuthToken` allowed)
, runIhdl = h
, runOhdl = h
}
void $ runNetProtoHandle runenv (serve u)
debugM "remotedaemon" "done with TOR connection" debugM "remotedaemon" "done with TOR connection"