implement p2p command

This commit is contained in:
Joey Hess 2016-11-30 14:35:24 -04:00
parent ac0cb5c2cc
commit bfc8305814
No known key found for this signature in database
GPG key ID: C910D9222512E3C7
10 changed files with 110 additions and 33 deletions

View file

@ -13,12 +13,11 @@ import Types.Remote (RemoteConfig, RemoteConfigKey, typename, setup)
import Logs.Remote import Logs.Remote
import Logs.Trust import Logs.Trust
import qualified Git.Config import qualified Git.Config
import Git.Types (RemoteName)
import qualified Data.Map as M import qualified Data.Map as M
import Data.Ord import Data.Ord
type RemoteName = String
{- See if there's an existing special remote with this name. {- See if there's an existing special remote with this name.
- -
- Prefer remotes that are not dead when a name appears multiple times. -} - Prefer remotes that are not dead when a name appears multiple times. -}

View file

@ -1,6 +1,7 @@
git-annex (6.20161119) UNRELEASED; urgency=medium git-annex (6.20161119) UNRELEASED; urgency=medium
* enable-tor: New command, enables tor hidden service for P2P syncing. * enable-tor: New command, enables tor hidden service for P2P syncing.
* p2p: New command, allows linking repositories using a P2P network.
* remotedaemon: Serve tor hidden service. * remotedaemon: Serve tor hidden service.
* Added git-remote-tor-annex, which allows git pull and push to the tor * Added git-remote-tor-annex, which allows git pull and push to the tor
hidden service. hidden service.

View file

@ -96,6 +96,7 @@ import qualified Command.Direct
import qualified Command.Indirect import qualified Command.Indirect
import qualified Command.Upgrade import qualified Command.Upgrade
import qualified Command.Forget import qualified Command.Forget
import qualified Command.P2P
import qualified Command.Proxy import qualified Command.Proxy
import qualified Command.DiffDriver import qualified Command.DiffDriver
import qualified Command.Smudge import qualified Command.Smudge
@ -204,6 +205,7 @@ cmds testoptparser testrunner =
, Command.Indirect.cmd , Command.Indirect.cmd
, Command.Upgrade.cmd , Command.Upgrade.cmd
, Command.Forget.cmd , Command.Forget.cmd
, Command.P2P.cmd
, Command.Proxy.cmd , Command.Proxy.cmd
, Command.DiffDriver.cmd , Command.DiffDriver.cmd
, Command.Smudge.cmd , Command.Smudge.cmd

View file

@ -12,6 +12,7 @@ import qualified Annex
import qualified Logs.Remote import qualified Logs.Remote
import qualified Types.Remote as R import qualified Types.Remote as R
import qualified Git import qualified Git
import qualified Git.Types as Git
import qualified Annex.SpecialRemote import qualified Annex.SpecialRemote
import qualified Remote import qualified Remote
import qualified Types.Remote as Remote import qualified Types.Remote as Remote
@ -40,9 +41,7 @@ start (name:rest) = go =<< filter matchingname <$> Annex.fromRepo Git.remotes
=<< Annex.SpecialRemote.findExisting name =<< Annex.SpecialRemote.findExisting name
go (r:_) = startNormalRemote name r go (r:_) = startNormalRemote name r
type RemoteName = String startNormalRemote :: Git.RemoteName -> Git.Repo -> CommandStart
startNormalRemote :: RemoteName -> Git.Repo -> CommandStart
startNormalRemote name r = do startNormalRemote name r = do
showStart "enableremote" name showStart "enableremote" name
next $ next $ do next $ next $ do
@ -51,7 +50,7 @@ startNormalRemote name r = do
u <- getRepoUUID r' u <- getRepoUUID r'
return $ u /= NoUUID return $ u /= NoUUID
startSpecialRemote :: RemoteName -> Remote.RemoteConfig -> Maybe (UUID, Remote.RemoteConfig) -> CommandStart startSpecialRemote :: Git.RemoteName -> Remote.RemoteConfig -> Maybe (UUID, Remote.RemoteConfig) -> CommandStart
startSpecialRemote name config Nothing = do startSpecialRemote name config Nothing = do
m <- Annex.SpecialRemote.specialRemoteMap m <- Annex.SpecialRemote.specialRemoteMap
confm <- Logs.Remote.readRemoteLog confm <- Logs.Remote.readRemoteLog

61
Command/P2P.hs Normal file
View file

@ -0,0 +1,61 @@
{- git-annex command
-
- Copyright 2016 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU GPL version 3 or higher.
-}
module Command.P2P where
import Command
import Git.Types
import P2P.Address
import P2P.Auth
import Utility.AuthToken
cmd :: Command
cmd = command "p2p" SectionSetup
"configure peer-2-peer links between repositories"
paramNothing (seek <$$> optParser)
data P2POpts
= GenAddresses
| LinkRemote P2PAddressAuth RemoteName
optParser :: CmdParamsDesc -> Parser P2POpts
optParser _ = genaddresses <|> linkremote
where
genaddresses = flag' GenAddresses
( long "gen-addresses"
<> help "generate addresses that allow accessing this repository over P2P networks"
)
linkremote = LinkRemote
<$> option readaddr
( long "link"
<> metavar paramAddress
<> help "address of the peer to link with"
)
<*> strOption
( long "named"
<> metavar paramRemote
<> help "specify name to use for git remote"
)
readaddr = eitherReader $ maybe (Left "address parse error") Right
. unformatP2PAddress
seek :: P2POpts -> CommandSeek
seek GenAddresses = do
addrs <- loadP2PAddresses
if null addrs
then giveup "No P2P networks are currrently available."
else do
authtoken <- liftIO $ genAuthToken 128
storeP2PAuthToken authtoken
-- Only addresses are output to stdout, to allow
-- scripting.
earlyWarning "These addresses allow access to this git-annex repository. Only share them with people you trust with that access, using trusted communication channels!"
liftIO $ putStr $ unlines $
map formatP2PAddress $
map (`P2PAddressAuth` authtoken) addrs
seek (LinkRemote addr name) = do

View file

@ -23,7 +23,10 @@ import qualified Data.Text as T
data P2PAddress = TorAnnex OnionAddress OnionPort data P2PAddress = TorAnnex OnionAddress OnionPort
deriving (Eq, Show) deriving (Eq, Show)
-- | A P2P address, with an AuthToken -- | A P2P address, with an AuthToken.
--
-- This is enough information to connect to the peer, and authenticate with
-- it.
data P2PAddressAuth = P2PAddressAuth P2PAddress AuthToken data P2PAddressAuth = P2PAddressAuth P2PAddress AuthToken
deriving (Eq, Show) deriving (Eq, Show)

View file

@ -1,4 +1,4 @@
{- P2P protocol, authorization {- P2P authtokens
- -
- Copyright 2016 Joey Hess <id@joeyh.name> - Copyright 2016 Joey Hess <id@joeyh.name>
- -
@ -7,24 +7,29 @@
module P2P.Auth where module P2P.Auth where
import Common import Annex.Common
import Creds
import Utility.AuthToken import Utility.AuthToken
import qualified Data.Text as T import qualified Data.Text as T
-- Use .git/annex/creds/p2p to hold AuthTokens of authorized peers. -- | Load authtokens that are accepted by this repository.
getAuthTokens :: Annex AllowedAuthTokens loadP2PAuthTokens :: Annex AllowedAuthTokens
getAuthTokens = allowedAuthTokens <$> getAuthTokens' loadP2PAuthTokens = allowedAuthTokens <$> loadP2PAuthTokens'
getAuthTokens' :: Annex [AuthTokens] loadP2PAuthTokens' :: Annex [AuthToken]
getAuthTokens' = mapMaybe toAuthToken loadP2PAuthTokens' = mapMaybe toAuthToken
. map T.pack . map T.pack
. lines . lines
. fromMaybe [] . fromMaybe []
<$> readCacheCreds "tor" <$> readCacheCreds p2pAuthCredsFile
addAuthToken :: AuthToken -> Annex () storeP2PAuthToken :: AuthToken -> Annex ()
addAuthToken t = do storeP2PAuthToken t = do
ts <- getAuthTokens' ts <- loadP2PAuthTokens'
let d = unlines $ map (T.unpack . fromAuthToken) (t:ts) unless (t `elem` ts) $ do
writeCacheCreds d "tor" let d = unlines $ map (T.unpack . fromAuthToken) (t:ts)
writeCacheCreds d p2pAuthCredsFile
p2pAuthCredsFile :: FilePath
p2pAuthCredsFile = "p2pauth"

View file

@ -11,14 +11,18 @@ git annex p2p [options]
This command can be used to link git-annex repositories over peer-2-peer This command can be used to link git-annex repositories over peer-2-peer
networks. networks.
Currently, the only P2P network supported by git-annex is Tor hidden
services.
# OPTIONS # OPTIONS
* `--gen-address` * `--gen-address`
Generates addresses that can be used to access this git-annex repository Generates addresses that can be used to access this git-annex repository
over a P2P network. The address or addresses is output to stdout. over the available P2P networks. The address or addresses is output to
stdout.
* `--link-remote remotename address` * `--link address --named remotename`
Sets up a git remote with the specified remotename that is accessed over Sets up a git remote with the specified remotename that is accessed over
a P2P network. The address is one generated in the remote repository using a P2P network. The address is one generated in the remote repository using

View file

@ -44,7 +44,7 @@ repository:
Now, tell the new peer about the address of the first peer: Now, tell the new peer about the address of the first peer:
git annex p2p --link-remote peer1 tor-annnex::eeaytkuhaupbarfi.onion:4412:7f53c5b65b8957ef626fd461ceaae8056e3dbc459ae715e4 git annex p2p --link tor-annnex::eeaytkuhaupbarfi.onion:4412:7f53c5b65b8957ef626fd461ceaae8056e3dbc459ae715e4 --named peer1
(Of course, you should paste in the address you generated earlier, (Of course, you should paste in the address you generated earlier,
not the example one shown above.) not the example one shown above.)
@ -56,8 +56,8 @@ You can run any commands you normally would to sync with that remote:
git annex sync --content peer1 git annex sync --content peer1
You can also generate an address for this new peer, by running `git annex You can also generate an address for this new peer, by running `git annex
p2p --gen-address`, and add that address to other peers using `git annex p2p --gen-address`, and link other peers to that address using `git annex
p2p --link-remote`. It's often useful to link peers up in both directions, p2p --link`. It's often useful to link peers up in both directions,
so peer1 is a remote of peer2 and peer2 is a remote of peer1. so peer1 is a remote of peer2 and peer2 is a remote of peer1.
Any number of peers can be connected this way, within reason. Any number of peers can be connected this way, within reason.
@ -88,14 +88,14 @@ You can `git pull`, push, etc with those onion addresses:
git remote add peer1 tor-annnex::eeaytkuhaupbarfi.onion:4412 git remote add peer1 tor-annnex::eeaytkuhaupbarfi.onion:4412
Onion addresses are semi-public. When you add a remote, they appear in your Onion addresses are semi-public. When you add a remote, they appear in your
`.git/config` file. So, there's a second level of authentication that `.git/config` file. For security, there's a second level of authentication
git-annex uses to make sure that only people you want to can access your that git-annex uses to make sure that only people you want to can access
repository over Tor. That takes the form of a long string of numbers and your repository over Tor. That takes the form of a long string of numbers
letters, like "7f53c5b65b8957ef626fd461ceaae8056e3dbc459ae715e4". and letters, like "7f53c5b65b8957ef626fd461ceaae8056e3dbc459ae715e4".
The addresses generated by `git annex peer --gen-address` The addresses generated by `git annex peer --gen-address`
combine the onion address with the authentication data. combine the onion address with the authentication data.
When you run `git annex peer --link-remote`, it sets up a git remote using When you run `git annex peer --link`, it sets up a git remote using
the onion address, and it stashes the authentication data away in a file in the onion address, and it stashes the authentication data away in a file in
`.git/annex/creds/` `.git/annex/creds/`

View file

@ -91,6 +91,7 @@ Extra-Source-Files:
doc/git-annex-mirror.mdwn doc/git-annex-mirror.mdwn
doc/git-annex-move.mdwn doc/git-annex-move.mdwn
doc/git-annex-numcopies.mdwn doc/git-annex-numcopies.mdwn
doc/git-annex-p2p.mdwn
doc/git-annex-pre-commit.mdwn doc/git-annex-pre-commit.mdwn
doc/git-annex-preferred-content.mdwn doc/git-annex-preferred-content.mdwn
doc/git-annex-proxy.mdwn doc/git-annex-proxy.mdwn
@ -727,6 +728,7 @@ Executable git-annex
Command.DropKey Command.DropKey
Command.DropUnused Command.DropUnused
Command.EnableRemote Command.EnableRemote
Command.EnableTor
Command.ExamineKey Command.ExamineKey
Command.Expire Command.Expire
Command.Find Command.Find
@ -762,6 +764,7 @@ Executable git-annex
Command.Move Command.Move
Command.NotifyChanges Command.NotifyChanges
Command.NumCopies Command.NumCopies
Command.P2P
Command.PreCommit Command.PreCommit
Command.Proxy Command.Proxy
Command.ReKey Command.ReKey