annex.security.allowed-ip-addresses ports syntax
authorJoey Hess <joeyh@joeyh.name>
Tue, 25 Feb 2020 19:45:52 +0000 (15:45 -0400)
committerJoey Hess <joeyh@joeyh.name>
Tue, 25 Feb 2020 19:45:52 +0000 (15:45 -0400)
Extended annex.security.allowed-ip-addresses to let specific ports of an IP
address to be used, while denying use of other ports.

Annex/Url.hs
CHANGELOG
Utility/IPAddress.hs
doc/git-annex.mdwn
doc/todo/Provide_a_way_to_white_list_local_networks___40__not_just_specific_IPs__41__/comment_2_64ffa9a560bf11ba22c715da0b4b1cfe._comment
doc/todo/Provide_a_way_to_white_list_local_networks___40__not_just_specific_IPs__41__/comment_3_da5363a268008a88014972987de10323._comment [new file with mode: 0644]

index d7be5d243cf09d8f3b63453e7da4c29bca118253..29fe6997b390f7fd6b8c5d0a1b6953bc9778b42a 100644 (file)
@@ -41,6 +41,7 @@ import qualified BuildInfo
 import Network.Socket
 import Network.HTTP.Client
 import Network.HTTP.Client.TLS
+import Text.Read
 
 defaultUserAgent :: U.UserAgent
 defaultUserAgent = "git-annex/" ++ BuildInfo.packageversion
@@ -85,10 +86,11 @@ getUrlOptions = Annex.getState Annex.urloptions >>= \case
                        manager <- liftIO $ U.newManager $ 
                                avoidtimeout $ tlsManagerSettings
                        return (urldownloader, manager)
-               allowedaddrs -> do
+               allowedaddrsports -> do
                        addrmatcher <- liftIO $ 
                                (\l v -> any (\f -> f v) l) . catMaybes
-                                       <$> mapM makeAddressMatcher allowedaddrs
+                                       <$> mapM (uncurry makeAddressMatcher) 
+                                               (mapMaybe splitAddrPort allowedaddrsports)
                        -- Default to not allowing access to loopback
                        -- and private IP addresses to avoid data
                        -- leakage.
@@ -120,6 +122,19 @@ getUrlOptions = Annex.getState Annex.urloptions >>= \case
        -- separate timeout controls, so disable that.
        avoidtimeout s = s { managerResponseTimeout = responseTimeoutNone }
 
+splitAddrPort :: String -> Maybe (String, Maybe PortNumber)
+splitAddrPort s
+       -- "[addr]:port" (also allow "[addr]")
+       | "[" `isPrefixOf` s = case splitc ']' (drop 1 s) of
+               [a,cp] -> case splitc ':' cp of
+                       ["",p] -> do
+                               pn <- readMaybe p
+                               return (a, Just pn)
+                       [""] -> Just (a, Nothing)
+                       _ -> Nothing
+               _ -> Nothing
+       | otherwise = Just (s, Nothing)
+
 ipAddressesUnlimited :: Annex Bool
 ipAddressesUnlimited = 
        ("all" == ) . annexAllowedIPAddresses <$> Annex.getGitConfig
index 4891d6bcff4902a1b468ac508e94c9af50962a36..97009669981efea3bc448e9af3f327f951cf54d5 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -32,6 +32,8 @@ git-annex (8.20200221) UNRELEASED; urgency=medium
   * init --version: When the version given is one that automatically
     upgrades to a newer version, use the newer version instead.
   * Auto upgrades from older repo versions, like v5, now jump right to v8.
+  * Extended annex.security.allowed-ip-addresses to let specific ports
+    of an IP address to be used, while denying use of other ports.
 
  -- Joey Hess <id@joeyh.name>  Wed, 19 Feb 2020 12:48:58 -0400
 
index 52d9dc0f7c55db60fa0d09140588f77984a71811..5128bbf2c74f04aed93eb42a41dc669bc87e1520 100644 (file)
@@ -103,10 +103,12 @@ embeddedIpv4 v = case v of
  - match that address in a SockAddr. Nothing when the address cannot be
  - parsed.
  -
+ - When a port is specified, will only match a SockAddr using the same port.
+ -
  - This does not involve any DNS lookups.
  -}
-makeAddressMatcher :: String -> IO (Maybe (SockAddr -> Bool))
-makeAddressMatcher s = go
+makeAddressMatcher :: String -> Maybe PortNumber -> IO (Maybe (SockAddr -> Bool))
+makeAddressMatcher s mp = go
        <$> catchDefaultIO [] (getAddrInfo (Just hints) (Just s) Nothing)
   where
        hints = defaultHints
@@ -117,6 +119,11 @@ makeAddressMatcher s = go
        go [] = Nothing
        go l = Just $ \sockaddr -> any (match sockaddr) (map addrAddress l)
 
-       match (SockAddrInet _ a) (SockAddrInet _ b) = a == b
-       match (SockAddrInet6 _ _ a _) (SockAddrInet6 _ _ b _) = a == b
+       match (SockAddrInet p a) (SockAddrInet _ b) = a == b && matchport p
+       match (SockAddrInet6 p _ a _) (SockAddrInet6 _ _ b _) = a == b && matchport p
        match _ _ = False
+
+       matchport p = case mp of
+               Nothing -> True
+               Just p' -> p == p'
+
index 6034d8bd22e797415f3e40c6cc6b1efc6672f346..e1545523f0e05d5ec98427b2b0f0c0eca0d0bd75 100644 (file)
@@ -1608,6 +1608,11 @@ Remotes are configured using these settings in `.git/config`.
   Note that, since the interfaces of curl and youtube-dl do not allow
   these IP address restrictions to be enforced, curl and youtube-dl will
   never be used unless annex.security.allowed-ip-addresses=all.
+  
+  To allow accessing local or private IP addresses on only specific ports,
+  use the syntax "[addr]:port". For example,
+  "[127.0.0.1]:80 [127.0.0.1]:443 [::1]:80 [::1]:443" allows
+  localhost on the http ports only.
 
 * `annex.security.allowed-http-addresses`
 
index 7e304341cf91ce705a19e9c593ea12abb890ef2b..946577f65cdf9e2fa00b4b85022624d3a36ee9e7 100644 (file)
@@ -4,7 +4,7 @@
  date="2020-02-25T18:32:02Z"
  content="""
 As to ports, it seems reasonable to support eg
-security.allowed-ip-addresses=127.0.0.1:80 to make sure that the massive
+security.allowed-ip-addresses=[127.0.0.1]:80 to make sure that the massive
 electron app I have running on some random other port doesn't get abused
 to exfiltrate the contents of my $HOME. As a non-random example. :)
 """]]
diff --git a/doc/todo/Provide_a_way_to_white_list_local_networks___40__not_just_specific_IPs__41__/comment_3_da5363a268008a88014972987de10323._comment b/doc/todo/Provide_a_way_to_white_list_local_networks___40__not_just_specific_IPs__41__/comment_3_da5363a268008a88014972987de10323._comment
new file mode 100644 (file)
index 0000000..c9b29b3
--- /dev/null
@@ -0,0 +1,7 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 3"""
+ date="2020-02-25T19:30:35Z"
+ content="""
+Implemented specifying allowed ports.
+"""]]