finish git-annex enable-tor
Make it stash the address away for git-annex p2p to use later, rather than outputting it. And, look up the UUID itself.
This commit is contained in:
parent
398345cb26
commit
38425fdc39
6 changed files with 106 additions and 26 deletions
|
@ -8,27 +8,28 @@
|
||||||
module Command.EnableTor where
|
module Command.EnableTor where
|
||||||
|
|
||||||
import Command
|
import Command
|
||||||
|
import P2P.Address
|
||||||
import Utility.Tor
|
import Utility.Tor
|
||||||
|
import Annex.UUID
|
||||||
|
|
||||||
-- This runs as root, so avoid making any commits or initializing
|
-- This runs as root, so avoid making any commits or initializing
|
||||||
-- git-annex, as that would create root-owned files.
|
-- git-annex, or doing other things that create root-owned files.
|
||||||
cmd :: Command
|
cmd :: Command
|
||||||
cmd = noCommit $ dontCheck repoExists $
|
cmd = noCommit $ dontCheck repoExists $
|
||||||
command "enable-tor" SectionSetup ""
|
command "enable-tor" SectionSetup "enable tor hidden service"
|
||||||
"userid uuid" (withParams seek)
|
"uid" (withParams seek)
|
||||||
|
|
||||||
seek :: CmdParams -> CommandSeek
|
seek :: CmdParams -> CommandSeek
|
||||||
seek = withWords start
|
seek = withWords start
|
||||||
|
|
||||||
start :: CmdParams -> CommandStart
|
start :: [String] -> CommandStart
|
||||||
start (suserid:uuid:[]) = case readish suserid of
|
start ps = case readish =<< headMaybe ps of
|
||||||
Nothing -> error "Bad userid"
|
Nothing -> giveup "Bad params"
|
||||||
Just userid -> do
|
Just userid -> do
|
||||||
(OnionAddress onionaddr, onionport) <- liftIO $
|
uuid <- getUUID
|
||||||
addHiddenService userid uuid
|
when (uuid == NoUUID) $
|
||||||
liftIO $ putStrLn $
|
giveup "This can only be run in a git-annex repository."
|
||||||
"tor-annex::" ++
|
(onionaddr, onionport) <- liftIO $
|
||||||
onionaddr ++ ":" ++
|
addHiddenService userid (fromUUID uuid)
|
||||||
show onionport ++ " "
|
storeP2PAddress $ TorAnnex onionaddr onionport
|
||||||
stop
|
stop
|
||||||
start _ = error "Bad params"
|
|
||||||
|
|
1
Creds.hs
1
Creds.hs
|
@ -15,6 +15,7 @@ module Creds (
|
||||||
getEnvCredPair,
|
getEnvCredPair,
|
||||||
writeCacheCreds,
|
writeCacheCreds,
|
||||||
readCacheCreds,
|
readCacheCreds,
|
||||||
|
cacheCredsFile,
|
||||||
removeCreds,
|
removeCreds,
|
||||||
includeCredsInfo,
|
includeCredsInfo,
|
||||||
) where
|
) where
|
||||||
|
|
79
P2P/Address.hs
Normal file
79
P2P/Address.hs
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
{- P2P protocol addresses
|
||||||
|
-
|
||||||
|
- Copyright 2016 Joey Hess <id@joeyh.name>
|
||||||
|
-
|
||||||
|
- Licensed under the GNU GPL version 3 or higher.
|
||||||
|
-}
|
||||||
|
|
||||||
|
module P2P.Address where
|
||||||
|
|
||||||
|
import qualified Annex
|
||||||
|
import Annex.Common
|
||||||
|
import Git
|
||||||
|
import Creds
|
||||||
|
import Utility.AuthToken
|
||||||
|
import Utility.Tor
|
||||||
|
|
||||||
|
import qualified Data.Text as T
|
||||||
|
|
||||||
|
-- | A P2P address, without an AuthToken.
|
||||||
|
--
|
||||||
|
-- This is enough information to connect to the peer,
|
||||||
|
-- but not enough to authenticate with it.
|
||||||
|
data P2PAddress = TorAnnex OnionAddress OnionPort
|
||||||
|
deriving (Eq, Show)
|
||||||
|
|
||||||
|
-- | A P2P address, with an AuthToken
|
||||||
|
data P2PAddressAuth = P2PAddressAuth P2PAddress AuthToken
|
||||||
|
deriving (Eq, Show)
|
||||||
|
|
||||||
|
class FormatP2PAddress a where
|
||||||
|
formatP2PAddress :: a -> String
|
||||||
|
unformatP2PAddress :: String -> Maybe a
|
||||||
|
|
||||||
|
instance FormatP2PAddress P2PAddress where
|
||||||
|
formatP2PAddress (TorAnnex (OnionAddress onionaddr) onionport) =
|
||||||
|
"tor-annex::" ++ onionaddr ++ ":" ++ show onionport
|
||||||
|
unformatP2PAddress s
|
||||||
|
| "tor-annex::" `isPrefixOf` s = do
|
||||||
|
let s' = dropWhile (== ':') $ dropWhile (/= ':') s
|
||||||
|
let (onionaddr, ps) = separate (== ':') s'
|
||||||
|
onionport <- readish ps
|
||||||
|
return (TorAnnex (OnionAddress onionaddr) onionport)
|
||||||
|
| otherwise = Nothing
|
||||||
|
|
||||||
|
instance FormatP2PAddress P2PAddressAuth where
|
||||||
|
formatP2PAddress (P2PAddressAuth addr authtoken) =
|
||||||
|
formatP2PAddress addr ++ ":" ++ T.unpack (fromAuthToken authtoken)
|
||||||
|
unformatP2PAddress s = do
|
||||||
|
let (ra, rs) = separate (== ':') (reverse s)
|
||||||
|
addr <- unformatP2PAddress (reverse rs)
|
||||||
|
authtoken <- toAuthToken (T.pack $ reverse ra)
|
||||||
|
return (P2PAddressAuth addr authtoken)
|
||||||
|
|
||||||
|
loadP2PAddresses :: Annex [P2PAddress]
|
||||||
|
loadP2PAddresses = mapMaybe unformatP2PAddress . maybe [] lines
|
||||||
|
<$> readCacheCreds p2pAddressCredsFile
|
||||||
|
|
||||||
|
storeP2PAddress :: P2PAddress -> Annex ()
|
||||||
|
storeP2PAddress addr = do
|
||||||
|
addrs <- loadP2PAddresses
|
||||||
|
unless (addr `elem` addrs) $ do
|
||||||
|
let s = unlines $ map formatP2PAddress (addr:addrs)
|
||||||
|
let tmpnam = p2pAddressCredsFile ++ ".new"
|
||||||
|
writeCacheCreds s tmpnam
|
||||||
|
tmpf <- cacheCredsFile tmpnam
|
||||||
|
destf <- cacheCredsFile p2pAddressCredsFile
|
||||||
|
-- This may be run by root, so make the creds file
|
||||||
|
-- and directory have the same owner and group as
|
||||||
|
-- the git repository directory has.
|
||||||
|
st <- liftIO . getFileStatus =<< Annex.fromRepo repoLocation
|
||||||
|
let fixowner f = setOwnerAndGroup f (fileOwner st) (fileGroup st)
|
||||||
|
liftIO $ do
|
||||||
|
fixowner tmpf
|
||||||
|
fixowner (takeDirectory tmpf)
|
||||||
|
fixowner (takeDirectory (takeDirectory tmpf))
|
||||||
|
renameFile tmpf destf
|
||||||
|
|
||||||
|
p2pAddressCredsFile :: FilePath
|
||||||
|
p2pAddressCredsFile = "p2paddrs"
|
|
@ -21,7 +21,7 @@ import qualified System.Random as R
|
||||||
type OnionPort = Int
|
type OnionPort = Int
|
||||||
|
|
||||||
newtype OnionAddress = OnionAddress String
|
newtype OnionAddress = OnionAddress String
|
||||||
deriving (Show)
|
deriving (Show, Eq)
|
||||||
|
|
||||||
type OnionSocket = FilePath
|
type OnionSocket = FilePath
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ addHiddenService uid ident = do
|
||||||
case filter (\(_, s) -> s == sockfile) portssocks of
|
case filter (\(_, s) -> s == sockfile) portssocks of
|
||||||
((p, _s):_) -> waithiddenservice 1 p
|
((p, _s):_) -> waithiddenservice 1 p
|
||||||
_ -> do
|
_ -> do
|
||||||
highports <- R.getStdRandom highports
|
highports <- R.getStdRandom mkhighports
|
||||||
let newport = Prelude.head $
|
let newport = Prelude.head $
|
||||||
filter (`notElem` map fst portssocks) highports
|
filter (`notElem` map fst portssocks) highports
|
||||||
writeFile torrc $ unlines $
|
writeFile torrc $ unlines $
|
||||||
|
@ -74,7 +74,7 @@ addHiddenService uid ident = do
|
||||||
, ("sefvice", [Param "tor", Param "reload"])
|
, ("sefvice", [Param "tor", Param "reload"])
|
||||||
]
|
]
|
||||||
unless reloaded $
|
unless reloaded $
|
||||||
error "failed to reload tor, perhaps the tor service is not running"
|
giveup "failed to reload tor, perhaps the tor service is not running"
|
||||||
waithiddenservice 120 newport
|
waithiddenservice 120 newport
|
||||||
where
|
where
|
||||||
parseportsock ("HiddenServicePort", l) = do
|
parseportsock ("HiddenServicePort", l) = do
|
||||||
|
@ -85,12 +85,12 @@ addHiddenService uid ident = do
|
||||||
sockfile = hiddenServiceSocketFile uid ident
|
sockfile = hiddenServiceSocketFile uid ident
|
||||||
|
|
||||||
-- An infinite random list of high ports.
|
-- An infinite random list of high ports.
|
||||||
highports g =
|
mkhighports g =
|
||||||
let (g1, g2) = R.split g
|
let (g1, g2) = R.split g
|
||||||
in (R.randomRs (1025, 65534) g1, g2)
|
in (R.randomRs (1025, 65534) g1, g2)
|
||||||
|
|
||||||
waithiddenservice :: Int -> OnionPort -> IO (OnionAddress, OnionPort)
|
waithiddenservice :: Int -> OnionPort -> IO (OnionAddress, OnionPort)
|
||||||
waithiddenservice 0 _ = error "tor failed to create hidden service, perhaps the tor service is not running"
|
waithiddenservice 0 _ = giveup "tor failed to create hidden service, perhaps the tor service is not running"
|
||||||
waithiddenservice n p = do
|
waithiddenservice n p = do
|
||||||
v <- tryIO $ readFile $ hiddenServiceHostnameFile uid ident
|
v <- tryIO $ readFile $ hiddenServiceHostnameFile uid ident
|
||||||
case v of
|
case v of
|
||||||
|
|
|
@ -4,20 +4,18 @@ git-annex enable-tor - enable tor hidden service
|
||||||
|
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
|
|
||||||
git annex enable-tor userid uuid
|
sudo git annex enable-tor $(id -u)
|
||||||
|
|
||||||
# DESCRIPTION
|
# DESCRIPTION
|
||||||
|
|
||||||
This plumbing-level command enables a tor hidden service for git-annex,
|
This command enables a tor hidden service for git-annex.
|
||||||
using the specified repository uuid and userid.
|
|
||||||
|
|
||||||
This command has to be run by root, since it modifies `/etc/tor/torrc`.
|
It has to be run by root, since it modifies `/etc/tor/torrc`.
|
||||||
|
Pass it your user id number, as output by `id -u`
|
||||||
|
|
||||||
After this command is run, `git annex remotedaemon` can be run to serve the
|
After this command is run, `git annex remotedaemon` can be run to serve the
|
||||||
tor hidden service.
|
tor hidden service, and then `git-annex p2p --gen-address` can be run to
|
||||||
|
give other users access to your repository via the tor hidden service.
|
||||||
Use the `git-annex p2p --gen-address` command to give other users access
|
|
||||||
to your repository via the tor hidden service.
|
|
||||||
|
|
||||||
# SEE ALSO
|
# SEE ALSO
|
||||||
|
|
||||||
|
|
|
@ -904,6 +904,7 @@ Executable git-annex
|
||||||
Messages.Internal
|
Messages.Internal
|
||||||
Messages.JSON
|
Messages.JSON
|
||||||
Messages.Progress
|
Messages.Progress
|
||||||
|
P2P.Address
|
||||||
P2P.Auth
|
P2P.Auth
|
||||||
P2P.IO
|
P2P.IO
|
||||||
P2P.Protocol
|
P2P.Protocol
|
||||||
|
|
Loading…
Reference in a new issue