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.Trust
import qualified Git.Config
import Git.Types (RemoteName)
import qualified Data.Map as M
import Data.Ord
type RemoteName = String
{- See if there's an existing special remote with this name.
-
- 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
* 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.
* Added git-remote-tor-annex, which allows git pull and push to the tor
hidden service.

View file

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

View file

@ -12,6 +12,7 @@ import qualified Annex
import qualified Logs.Remote
import qualified Types.Remote as R
import qualified Git
import qualified Git.Types as Git
import qualified Annex.SpecialRemote
import qualified 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
go (r:_) = startNormalRemote name r
type RemoteName = String
startNormalRemote :: RemoteName -> Git.Repo -> CommandStart
startNormalRemote :: Git.RemoteName -> Git.Repo -> CommandStart
startNormalRemote name r = do
showStart "enableremote" name
next $ next $ do
@ -51,7 +50,7 @@ startNormalRemote name r = do
u <- getRepoUUID r'
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
m <- Annex.SpecialRemote.specialRemoteMap
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
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
deriving (Eq, Show)

View file

@ -1,4 +1,4 @@
{- P2P protocol, authorization
{- P2P authtokens
-
- Copyright 2016 Joey Hess <id@joeyh.name>
-
@ -7,24 +7,29 @@
module P2P.Auth where
import Common
import Annex.Common
import Creds
import Utility.AuthToken
import qualified Data.Text as T
-- Use .git/annex/creds/p2p to hold AuthTokens of authorized peers.
getAuthTokens :: Annex AllowedAuthTokens
getAuthTokens = allowedAuthTokens <$> getAuthTokens'
-- | Load authtokens that are accepted by this repository.
loadP2PAuthTokens :: Annex AllowedAuthTokens
loadP2PAuthTokens = allowedAuthTokens <$> loadP2PAuthTokens'
getAuthTokens' :: Annex [AuthTokens]
getAuthTokens' = mapMaybe toAuthToken
. map T.pack
. lines
. fromMaybe []
<$> readCacheCreds "tor"
loadP2PAuthTokens' :: Annex [AuthToken]
loadP2PAuthTokens' = mapMaybe toAuthToken
. map T.pack
. lines
. fromMaybe []
<$> readCacheCreds p2pAuthCredsFile
addAuthToken :: AuthToken -> Annex ()
addAuthToken t = do
ts <- getAuthTokens'
let d = unlines $ map (T.unpack . fromAuthToken) (t:ts)
writeCacheCreds d "tor"
storeP2PAuthToken :: AuthToken -> Annex ()
storeP2PAuthToken t = do
ts <- loadP2PAuthTokens'
unless (t `elem` ts) $ do
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
networks.
Currently, the only P2P network supported by git-annex is Tor hidden
services.
# OPTIONS
* `--gen-address`
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
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:
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,
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
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 --link-remote`. It's often useful to link peers up in both directions,
p2p --gen-address`, and link other peers to that address using `git annex
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.
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
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-annex uses to make sure that only people you want to can access your
repository over Tor. That takes the form of a long string of numbers and
letters, like "7f53c5b65b8957ef626fd461ceaae8056e3dbc459ae715e4".
`.git/config` file. For security, there's a second level of authentication
that git-annex uses to make sure that only people you want to can access
your repository over Tor. That takes the form of a long string of numbers
and letters, like "7f53c5b65b8957ef626fd461ceaae8056e3dbc459ae715e4".
The addresses generated by `git annex peer --gen-address`
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
`.git/annex/creds/`

View file

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