Skip to content

Commit ce136ef

Browse files
committed
topology parsing: validate destination addresses
Do not allow `0.0.0.0` and `::` in topology files.
1 parent 79e974b commit ce136ef

File tree

2 files changed

+20
-4
lines changed

2 files changed

+20
-4
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
### Non-Breaking
2+
3+
- The `FromJSON RelayAccessPoints` instance has changed: `0.0.0.0` and `::`
4+
addresses are forbidden in topology file, they are not valid destination
5+
addresses and can lead to confusing situations.
6+

ouroboros-network-api/src/Ouroboros/Network/PeerSelection/RelayAccessPoint.hs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import Control.Monad (unless)
2020

2121
import Data.Aeson
2222
import Data.Aeson.Types
23+
import Data.ByteString (ByteString)
2324
import Data.ByteString.Char8 qualified as BSC
2425
import Data.IP qualified as IP
2526
import Data.Text qualified as Text
@@ -59,18 +60,22 @@ instance NFData RelayAccessPoint where
5960
IP.IPv4 ipv4 -> rnf (IP.fromIPv4w ipv4)
6061
IP.IPv6 ipv6 -> rnf (IP.fromIPv6w ipv6)
6162

63+
-- This instance is used to parse `RelayAccessPoint`s in topology files.
6264
instance FromJSON RelayAccessPoint where
6365
parseJSON = withObject "RelayAccessPoint" $ \o -> do
6466
addr <- encodeUtf8 <$> o .: "address"
6567
let res = flip parseMaybe o $ const do
6668
port <- o .: "port"
67-
return (toRelayAccessPoint addr port)
69+
return $ toRelayAccessPoint addr port
6870
case res of
6971
Nothing -> return $ RelayAccessSRVDomain (fullyQualified addr)
72+
Just rap@(RelayAccessAddress addr' _) -> do
73+
unless (isValidDestinationIPAddr addr') $
74+
fail (show addr' ++ " is not a valid destination address")
75+
return rap
7076
Just rap -> return rap
71-
7277
where
73-
toRelayAccessPoint :: DNS.Domain -> Int -> RelayAccessPoint
78+
toRelayAccessPoint :: ByteString -> Int -> RelayAccessPoint
7479
toRelayAccessPoint address port =
7580
case readMaybe (BSC.unpack address) of
7681
Nothing -> RelayAccessDomain (fullyQualified address) (fromIntegral port)
@@ -79,6 +84,10 @@ instance FromJSON RelayAccessPoint where
7984
domain | Just (_, '.') <- BSC.unsnoc domain -> domain
8085
| otherwise -> domain `BSC.snoc` '.'
8186

87+
isValidDestinationIPAddr :: IP.IP -> Bool
88+
isValidDestinationIPAddr (IP.IPv4 ipv4) = IP.fromIPv4w ipv4 /= 0
89+
isValidDestinationIPAddr (IP.IPv6 ipv6) = IP.fromIPv6w ipv6 /= (0,0,0,0)
90+
8291
instance ToJSON RelayAccessPoint where
8392
toJSON (RelayAccessDomain addr port) =
8493
object
@@ -190,11 +199,12 @@ instance FromJSON LedgerRelayAccessPoint where
190199
Just rap -> return rap
191200

192201
where
193-
toRelayAccessPoint :: DNS.Domain -> Int -> LedgerRelayAccessPoint
202+
toRelayAccessPoint :: ByteString -> Int -> LedgerRelayAccessPoint
194203
toRelayAccessPoint address port =
195204
case readMaybe (BSC.unpack address) of
196205
Nothing -> LedgerRelayAccessDomain (fullyQualified address) (fromIntegral port)
197206
Just addr -> LedgerRelayAccessAddress addr (fromIntegral port)
207+
198208
fullyQualified = \case
199209
domain | Just (_, '.') <- BSC.unsnoc domain -> domain
200210
| otherwise -> domain `BSC.snoc` '.'

0 commit comments

Comments
 (0)