From: Joey Hess Date: Wed, 30 Jul 2025 16:02:33 +0000 (-0400) Subject: add P2PAnnex constructor X-Git-Tag: archive/raspbian/10.20251029-1+rpi1~1^2~3^2~245 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=f631bc9e567447c7c0f3c0d0bb5f77f8bdd66303;p=git-annex.git add P2PAnnex constructor This is for p2p-annex:: urls that will use the new generic P2P transport. In addressCredsFile, threw in an url encoding of any non-alphanumeric characters that are in the address. This is to avoid any possible path traversal attacks via a p2p-annex:: url, since the address part of it could contain any characters. And, went ahead and did the same url encoding of tor-annex:: urls, even though tor onion addresses are all alphanumerics, on the off chance that might avoid a similar problem. (It does not seem likely enough to treat it as a security hole.) --- diff --git a/Command/EnableTor.hs b/Command/EnableTor.hs index 03293d2af4..b36136553a 100644 --- a/Command/EnableTor.hs +++ b/Command/EnableTor.hs @@ -102,6 +102,7 @@ checkHiddenService = bracket setup cleanup go go _ = check (150 :: Int) =<< filter istoraddr <$> loadP2PAddresses istoraddr (TorAnnex _ _) = True + istoraddr _ = False check 0 _ = giveup "Still unable to connect to hidden service. It might not yet be usable by others. Please check Tor's logs for details." check _ [] = giveup "Somehow didn't get an onion address." diff --git a/P2P/Address.hs b/P2P/Address.hs index 1a3186aca9..052f0af6ce 100644 --- a/P2P/Address.hs +++ b/P2P/Address.hs @@ -1,6 +1,6 @@ {- P2P protocol addresses - - - Copyright 2016 Joey Hess + - Copyright 2016-2025 Joey Hess - - Licensed under the GNU AGPL version 3 or higher. -} @@ -25,7 +25,15 @@ import System.PosixCompat.Files (fileOwner, fileGroup) -- -- This is enough information to connect to the peer, -- but not enough to authenticate with it. -data P2PAddress = TorAnnex OnionAddress OnionPort +data P2PAddress + = TorAnnex OnionAddress OnionPort + | P2PAnnex P2PNetName UnderlyingP2PAddress + deriving (Eq, Show) + +newtype P2PNetName = P2PNetName String + deriving (Eq, Show) + +newtype UnderlyingP2PAddress = UnderlyingP2PAddress String deriving (Eq, Show) -- | A P2P address, with an AuthToken. @@ -42,17 +50,26 @@ class FormatP2PAddress a where instance FormatP2PAddress P2PAddress where formatP2PAddress (TorAnnex (OnionAddress onionaddr) onionport) = torAnnexScheme ++ ":" ++ onionaddr ++ ":" ++ show onionport + formatP2PAddress (P2PAnnex (P2PNetName netname) (UnderlyingP2PAddress address)) = + p2pAnnexScheme ++ ":" ++ netname ++ ":" ++ address unformatP2PAddress s - | (torAnnexScheme ++ ":") `isPrefixOf` s = do - let s' = dropWhile (== ':') $ dropWhile (/= ':') s - let (onionaddr, ps) = separate (== ':') s' - onionport <- readish ps - return (TorAnnex (OnionAddress onionaddr) onionport) + | schemeprefixed torAnnexScheme = do + onionport <- readish bs + return (TorAnnex (OnionAddress as) onionport) + | schemeprefixed p2pAnnexScheme = + return (P2PAnnex (P2PNetName as) (UnderlyingP2PAddress bs)) | otherwise = Nothing + where + schemeprefixed scheme = (scheme ++ ":") `isPrefixOf` s + (as, bs) = separate (== ':') $ + dropWhile (== ':') $ dropWhile (/= ':') s torAnnexScheme :: String torAnnexScheme = "tor-annex:" +p2pAnnexScheme :: String +p2pAnnexScheme = "p2p-annex:" + instance FormatP2PAddress P2PAddressAuth where formatP2PAddress (P2PAddressAuth addr authtoken) = formatP2PAddress addr ++ ":" ++ T.unpack (fromAuthToken authtoken) diff --git a/P2P/Auth.hs b/P2P/Auth.hs index 8de3eda39c..f7b79678e6 100644 --- a/P2P/Auth.hs +++ b/P2P/Auth.hs @@ -16,6 +16,8 @@ import Utility.AuthToken import Utility.Tor import Utility.Env +import Network.URI +import Data.Char import qualified Data.Text as T -- | Load authtokens that are accepted by this repository for tor. @@ -55,7 +57,7 @@ storeP2PAuthToken addr t = do where v = case addr of TorAnnex _ _ -> (t, Nothing) - -- _ -> (t, Just addr) + _ -> (t, Just addr) fmt (tok, Nothing) = T.unpack (fromAuthToken tok) fmt (tok, Just addr') = T.unpack (fromAuthToken tok) @@ -86,9 +88,13 @@ storeP2PRemoteAuthToken addr t = writeCreds (T.unpack $ fromAuthToken t) (addressCredsFile addr) +-- | Unusual characters in the address are url encoded. addressCredsFile :: P2PAddress -> OsPath --- We can omit the port and just use the onion address for the creds file, --- because any given tor hidden service runs on a single port and has a --- unique onion address. -addressCredsFile (TorAnnex (OnionAddress onionaddr) _port) = - toOsPath onionaddr +addressCredsFile addr = toOsPath $ escapeURIString isAlphaNum $ case addr of + -- We can omit the port and just use the onion address for the + -- creds file, because any given tor hidden service runs on a + -- single port and has a unique onion address. + TorAnnex (OnionAddress onionaddr) _port -> + onionaddr + P2PAnnex (P2PNetName netname) (UnderlyingP2PAddress address) -> + netname ++ ":" ++ address diff --git a/doc/design/generic_p2p_transport.mdwn b/doc/design/generic_p2p_transport.mdwn index 20860504e9..2e06da195b 100644 --- a/doc/design/generic_p2p_transport.mdwn +++ b/doc/design/generic_p2p_transport.mdwn @@ -7,7 +7,7 @@ Such a P2P network has some form of address, which can be used to connect to a given peer by address across the network. A git remote using the P2P network has an url of the form -`p2p-annex::+
` +`p2p-annex:::
` To connect to that remote, git-annex runs the command `git-annex-p2p-`, giving it the P2P network address as its only