module Ecluse.Core.Security.Host (
LoweredHostSet,
lowerCaseHosts,
isAllowedUpstreamHost,
isBlockedTarget,
isBlockedIP,
parseIpLiteral,
parseBlockedRange,
hostAddress,
splitHostPort,
TarballHostPolicy (..),
Origin (..),
tarballHostAllowed,
TarballHostGate (..),
tarballHostGate,
isHex,
isDecimal,
) where
import Data.IP (
IP (IPv4, IPv6),
IPRange (IPv4Range, IPv6Range),
fromIPv6b,
isMatchedTo,
toIPv4,
toIPv6,
)
import Data.Set qualified as Set
import Data.Text qualified as T
newtype LoweredHostSet = LoweredHostSet (Set Text)
deriving stock (LoweredHostSet -> LoweredHostSet -> Bool
(LoweredHostSet -> LoweredHostSet -> Bool)
-> (LoweredHostSet -> LoweredHostSet -> Bool) -> Eq LoweredHostSet
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: LoweredHostSet -> LoweredHostSet -> Bool
== :: LoweredHostSet -> LoweredHostSet -> Bool
$c/= :: LoweredHostSet -> LoweredHostSet -> Bool
/= :: LoweredHostSet -> LoweredHostSet -> Bool
Eq, Int -> LoweredHostSet -> ShowS
[LoweredHostSet] -> ShowS
LoweredHostSet -> String
(Int -> LoweredHostSet -> ShowS)
-> (LoweredHostSet -> String)
-> ([LoweredHostSet] -> ShowS)
-> Show LoweredHostSet
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> LoweredHostSet -> ShowS
showsPrec :: Int -> LoweredHostSet -> ShowS
$cshow :: LoweredHostSet -> String
show :: LoweredHostSet -> String
$cshowList :: [LoweredHostSet] -> ShowS
showList :: [LoweredHostSet] -> ShowS
Show)
lowerCaseHosts :: Set Text -> LoweredHostSet
lowerCaseHosts :: Set Text -> LoweredHostSet
lowerCaseHosts = Set Text -> LoweredHostSet
LoweredHostSet (Set Text -> LoweredHostSet)
-> (Set Text -> Set Text) -> Set Text -> LoweredHostSet
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Text) -> Set Text -> Set Text
forall b a. Ord b => (a -> b) -> Set a -> Set b
Set.map Text -> Text
canonicalHostKey
isAllowedUpstreamHost :: LoweredHostSet -> Text -> Bool
isAllowedUpstreamHost :: LoweredHostSet -> Text -> Bool
isAllowedUpstreamHost (LoweredHostSet Set Text
allowed) Text
host =
Bool -> Bool
not (Text -> Bool
T.null Text
host) Bool -> Bool -> Bool
&& Text -> Text
canonicalHostKey Text
host Text -> Set Text -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.member` Set Text
allowed
isBlockedTarget :: [IPRange] -> Text -> Bool
isBlockedTarget :: [IPRange] -> Text -> Bool
isBlockedTarget [IPRange]
additionalRanges Text
host =
Bool -> (IpAddr -> Bool) -> Maybe IpAddr -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False ([IPRange] -> IP -> Bool
isBlockedIP [IPRange]
additionalRanges (IP -> Bool) -> (IpAddr -> IP) -> IpAddr -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IpAddr -> IP
ipAddrToIP) (Text -> Maybe IpAddr
parseIpLiteral Text
host)
isBlockedIP :: [IPRange] -> IP -> Bool
isBlockedIP :: [IPRange] -> IP -> Bool
isBlockedIP [IPRange]
additionalRanges IP
ip = (IPRange -> Bool) -> [IPRange] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any IPRange -> Bool
matches ([IPRange]
blockedRanges [IPRange] -> [IPRange] -> [IPRange]
forall a. Semigroup a => a -> a -> a
<> [IPRange]
additionalRanges)
where
decoded :: IP
decoded = IP -> IP
decodeMappedV4 IP
ip
matches :: IPRange -> Bool
matches = \case
IPv4Range AddrRange IPv4
r -> case IP
decoded of
IPv4 IPv4
a -> IPv4
a IPv4 -> AddrRange IPv4 -> Bool
forall a. Addr a => a -> AddrRange a -> Bool
`isMatchedTo` AddrRange IPv4
r
IPv6 IPv6
_ -> Bool
False
IPv6Range AddrRange IPv6
r -> case IP
decoded of
IPv6 IPv6
a -> IPv6
a IPv6 -> AddrRange IPv6 -> Bool
forall a. Addr a => a -> AddrRange a -> Bool
`isMatchedTo` AddrRange IPv6
r
IPv4 IPv4
_ -> Bool
False
blockedRanges :: [IPRange]
blockedRanges :: [IPRange]
blockedRanges =
[ IPRange
"0.0.0.0/8"
, IPRange
"10.0.0.0/8"
, IPRange
"100.64.0.0/10"
, IPRange
"127.0.0.0/8"
, IPRange
"169.254.0.0/16"
, IPRange
"172.16.0.0/12"
, IPRange
"192.168.0.0/16"
, IPRange
"::/128"
, IPRange
"::1/128"
, IPRange
"fe80::/10"
, IPRange
"fc00::/7"
]
parseBlockedRange :: Text -> Maybe IPRange
parseBlockedRange :: Text -> Maybe IPRange
parseBlockedRange = String -> Maybe IPRange
forall a. Read a => String -> Maybe a
readMaybe (String -> Maybe IPRange)
-> (Text -> String) -> Text -> Maybe IPRange
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
forall a. ToString a => a -> String
toString
ipAddrToIP :: IpAddr -> IP
ipAddrToIP :: IpAddr -> IP
ipAddrToIP = \case
IpV4 Word8
a Word8
b Word8
c Word8
d -> IPv4 -> IP
IPv4 ([Int] -> IPv4
toIPv4 ((Word8 -> Int) -> [Word8] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral [Word8
a, Word8
b, Word8
c, Word8
d]))
IpV6 [Word16]
groups -> IPv6 -> IP
IPv6 ([Int] -> IPv6
toIPv6 ((Word16 -> Int) -> [Word16] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Word16 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral [Word16]
groups))
canonicalHostKey :: Text -> Text
canonicalHostKey :: Text -> Text
canonicalHostKey Text
host = case Text -> Maybe IpAddr
parseIpLiteral Text
host of
Just IpAddr
addr -> IP -> Text
forall b a. (Show a, IsString b) => a -> b
show (IpAddr -> IP
ipAddrToIP IpAddr
addr)
Maybe IpAddr
Nothing -> Text -> Text
T.toLower Text
host
decodeMappedV4 :: IP -> IP
decodeMappedV4 :: IP -> IP
decodeMappedV4 = \case
IPv6 IPv6
v6 -> case IPv6 -> [Int]
fromIPv6b IPv6
v6 of
[Int
0, Int
0, Int
0, Int
0, Int
0, Int
0, Int
0, Int
0, Int
0, Int
0, Int
0xFF, Int
0xFF, Int
a, Int
b, Int
c, Int
d] ->
IPv4 -> IP
IPv4 ([Int] -> IPv4
toIPv4 [Int
a, Int
b, Int
c, Int
d])
[Int]
_ -> IPv6 -> IP
IPv6 IPv6
v6
IP
ip -> IP
ip
data IpAddr
=
IpV4 Word8 Word8 Word8 Word8
|
IpV6 [Word16]
hostAddress :: Text -> Text
hostAddress :: Text -> Text
hostAddress Text
raw =
let afterScheme :: Text
afterScheme = Text -> Text -> Text
afterLast Text
"://" Text
raw
authority :: Text
authority = (Char -> Bool) -> Text -> Text
T.takeWhile (Char -> String -> Bool
forall (f :: * -> *) a.
(Foldable f, DisallowElem f, Eq a) =>
a -> f a -> Bool
`notElem` [Char
'/', Char
'?', Char
'#']) Text
afterScheme
afterUserinfo :: Text
afterUserinfo = Text -> Text -> Text
afterLast Text
"@" Text
authority
in Text -> Text
T.toLower (Text -> ((Text, Text) -> Text) -> Maybe (Text, Text) -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"" (Text, Text) -> Text
forall a b. (a, b) -> a
fst (Text -> Maybe (Text, Text)
splitHostPort Text
afterUserinfo))
where
afterLast :: Text -> Text -> Text
afterLast :: Text -> Text -> Text
afterLast Text
needle Text
hay =
let (Text
pre, Text
post) = HasCallStack => Text -> Text -> (Text, Text)
Text -> Text -> (Text, Text)
T.breakOnEnd Text
needle Text
hay
in if Text -> Bool
T.null Text
pre then Text
hay else Text
post
splitHostPort :: Text -> Maybe (Text, Text)
splitHostPort :: Text -> Maybe (Text, Text)
splitHostPort Text
authority
| Text -> Bool
T.null Text
authority = Maybe (Text, Text)
forall a. Maybe a
Nothing
| Bool
otherwise = case Text -> Text -> Maybe Text
T.stripPrefix Text
"[" Text
authority of
Just Text
rest -> case HasCallStack => Text -> Text -> (Text, Text)
Text -> Text -> (Text, Text)
T.breakOn Text
"]" Text
rest of
(Text
_, Text
"") -> Maybe (Text, Text)
forall a. Maybe a
Nothing
(Text
inner, Text
afterBracket) -> (Text, Text) -> Maybe (Text, Text)
forall a. a -> Maybe a
Just (Text
inner, Int -> Text -> Text
T.drop Int
1 Text
afterBracket)
Maybe Text
Nothing -> case HasCallStack => Text -> Text -> (Text, Text)
Text -> Text -> (Text, Text)
T.breakOn Text
":" Text
authority of
(Text
"", Text
_) -> Maybe (Text, Text)
forall a. Maybe a
Nothing
(Text
h, Text
"") -> (Text, Text) -> Maybe (Text, Text)
forall a. a -> Maybe a
Just (Text
h, Text
"")
(Text
h, Text
p) -> if Text
p Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
":" then (Text, Text) -> Maybe (Text, Text)
forall a. a -> Maybe a
Just (Text
h, Text
"") else (Text, Text) -> Maybe (Text, Text)
forall a. a -> Maybe a
Just (Text
h, Text
p)
parseIpLiteral :: Text -> Maybe IpAddr
parseIpLiteral :: Text -> Maybe IpAddr
parseIpLiteral Text
host = case Text -> Maybe (Char, Text)
T.uncons Text
host of
Maybe (Char, Text)
Nothing -> Maybe IpAddr
forall a. Maybe a
Nothing
Just (Char, Text)
_ -> if (Char -> Bool) -> Text -> Bool
T.any (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
':') Text
host then Text -> Maybe IpAddr
parseIPv6 Text
host else (Text -> Maybe Word8) -> Text -> Maybe IpAddr
parseIPv4 Text -> Maybe Word8
octetInetAton Text
host
parseIPv4 :: (Text -> Maybe Word8) -> Text -> Maybe IpAddr
parseIPv4 :: (Text -> Maybe Word8) -> Text -> Maybe IpAddr
parseIPv4 Text -> Maybe Word8
octet Text
host = case HasCallStack => Text -> Text -> [Text]
Text -> Text -> [Text]
T.splitOn Text
"." Text
host of
[Text
a, Text
b, Text
c, Text
d] -> Word8 -> Word8 -> Word8 -> Word8 -> IpAddr
IpV4 (Word8 -> Word8 -> Word8 -> Word8 -> IpAddr)
-> Maybe Word8 -> Maybe (Word8 -> Word8 -> Word8 -> IpAddr)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Maybe Word8
octet Text
a Maybe (Word8 -> Word8 -> Word8 -> IpAddr)
-> Maybe Word8 -> Maybe (Word8 -> Word8 -> IpAddr)
forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> Maybe Word8
octet Text
b Maybe (Word8 -> Word8 -> IpAddr)
-> Maybe Word8 -> Maybe (Word8 -> IpAddr)
forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> Maybe Word8
octet Text
c Maybe (Word8 -> IpAddr) -> Maybe Word8 -> Maybe IpAddr
forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> Maybe Word8
octet Text
d
[Text]
_ -> Maybe IpAddr
forall a. Maybe a
Nothing
octetInetAton :: Text -> Maybe Word8
octetInetAton :: Text -> Maybe Word8
octetInetAton Text
tok = do
n <- Maybe Integer
value
if n <= 255 then Just (fromInteger n) else Nothing
where
value :: Maybe Integer
value :: Maybe Integer
value = case Text -> Maybe (Char, Text)
T.uncons Text
tok of
Just (Char
'0', Text
rest)
| Text -> Text
T.toLower (Int -> Text -> Text
T.take Int
1 Text
rest) Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"x" ->
let hex :: Text
hex = Int -> Text -> Text
T.drop Int
1 Text
rest
in if Text -> Bool
isHex Text
hex then String -> Maybe Integer
forall a. Read a => String -> Maybe a
readMaybe (String
"0x" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Text -> String
forall a. ToString a => a -> String
toString Text
hex) else Maybe Integer
forall a. Maybe a
Nothing
| Bool -> Bool
not (Text -> Bool
T.null Text
rest) ->
if Text -> Bool
isOctal Text
tok then String -> Maybe Integer
forall a. Read a => String -> Maybe a
readMaybe (String
"0o" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Text -> String
forall a. ToString a => a -> String
toString Text
tok) else Maybe Integer
forall a. Maybe a
Nothing
Maybe (Char, Text)
_ -> if Text -> Bool
isDecimal Text
tok then String -> Maybe Integer
forall a. Read a => String -> Maybe a
readMaybe (Text -> String
forall a. ToString a => a -> String
toString Text
tok) else Maybe Integer
forall a. Maybe a
Nothing
octetDecimal :: Text -> Maybe Word8
octetDecimal :: Text -> Maybe Word8
octetDecimal Text
t = do
n <- if Text -> Bool
isDecimal Text
t then String -> Maybe Integer
forall a. Read a => String -> Maybe a
readMaybe (Text -> String
forall a. ToString a => a -> String
toString Text
t) else Maybe Integer
forall a. Maybe a
Nothing :: Maybe Integer
if n <= 255 then Just (fromInteger n) else Nothing
parseIPv6 :: Text -> Maybe IpAddr
parseIPv6 :: Text -> Maybe IpAddr
parseIPv6 Text
host = case HasCallStack => Text -> Text -> [Text]
Text -> Text -> [Text]
T.splitOn Text
"::" Text
host of
[Text
single] -> [Word16] -> Maybe IpAddr
exactlyEightGroups ([Word16] -> Maybe IpAddr) -> Maybe [Word16] -> Maybe IpAddr
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Text -> Maybe [Word16]
parseV6Side Text
single
[Text
before, Text
after] -> do
hd <- Text -> Maybe [Word16]
parseV6Side Text
before
tl <- parseV6Side after
expandCompressedV6 hd tl
[Text]
_ -> Maybe IpAddr
forall a. Maybe a
Nothing
parseV6Side :: Text -> Maybe [Word16]
parseV6Side :: Text -> Maybe [Word16]
parseV6Side Text
t
| Text -> Bool
T.null Text
t = [Word16] -> Maybe [Word16]
forall a. a -> Maybe a
Just []
| Bool
otherwise = [Text] -> Maybe [Word16]
parseV6Tokens (HasCallStack => Text -> Text -> [Text]
Text -> Text -> [Text]
T.splitOn Text
":" Text
t)
parseV6Tokens :: [Text] -> Maybe [Word16]
parseV6Tokens :: [Text] -> Maybe [Word16]
parseV6Tokens [] = [Word16] -> Maybe [Word16]
forall a. a -> Maybe a
Just []
parseV6Tokens [Text
tok]
| (Char -> Bool) -> Text -> Bool
T.any (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'.') Text
tok = Text -> Maybe [Word16]
parseEmbeddedV4 Text
tok
| Bool
otherwise = (Word16 -> [Word16] -> [Word16]
forall a. a -> [a] -> [a]
: []) (Word16 -> [Word16]) -> Maybe Word16 -> Maybe [Word16]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Maybe Word16
parseV6Group Text
tok
parseV6Tokens (Text
tok : [Text]
rest) = (:) (Word16 -> [Word16] -> [Word16])
-> Maybe Word16 -> Maybe ([Word16] -> [Word16])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Maybe Word16
parseV6Group Text
tok Maybe ([Word16] -> [Word16]) -> Maybe [Word16] -> Maybe [Word16]
forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [Text] -> Maybe [Word16]
parseV6Tokens [Text]
rest
parseEmbeddedV4 :: Text -> Maybe [Word16]
parseEmbeddedV4 :: Text -> Maybe [Word16]
parseEmbeddedV4 Text
t = case (Text -> Maybe Word8) -> Text -> Maybe IpAddr
parseIPv4 Text -> Maybe Word8
octetDecimal Text
t of
Just (IpV4 Word8
a Word8
b Word8
c Word8
d) -> [Word16] -> Maybe [Word16]
forall a. a -> Maybe a
Just [Word8 -> Word8 -> Word16
forall {a} {a} {a}. (Integral a, Integral a, Num a) => a -> a -> a
pair Word8
a Word8
b, Word8 -> Word8 -> Word16
forall {a} {a} {a}. (Integral a, Integral a, Num a) => a -> a -> a
pair Word8
c Word8
d]
Maybe IpAddr
_ -> Maybe [Word16]
forall a. Maybe a
Nothing
where
pair :: a -> a -> a
pair a
hi a
lo = a -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
hi a -> a -> a
forall a. Num a => a -> a -> a
* a
256 a -> a -> a
forall a. Num a => a -> a -> a
+ a -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
lo
parseV6Group :: Text -> Maybe Word16
parseV6Group :: Text -> Maybe Word16
parseV6Group Text
t = do
n <- if Text -> Bool
isHex Text
t then String -> Maybe Integer
forall a. Read a => String -> Maybe a
readMaybe (String
"0x" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Text -> String
forall a. ToString a => a -> String
toString Text
t) else Maybe Integer
forall a. Maybe a
Nothing :: Maybe Integer
if n <= 0xFFFF then Just (fromInteger n) else Nothing
expandCompressedV6 :: [Word16] -> [Word16] -> Maybe IpAddr
expandCompressedV6 :: [Word16] -> [Word16] -> Maybe IpAddr
expandCompressedV6 [Word16]
hd [Word16]
tl =
let present :: Int
present = [Word16] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Word16]
hd Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [Word16] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Word16]
tl
in if Int
present Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
7
then IpAddr -> Maybe IpAddr
forall a. a -> Maybe a
Just ([Word16] -> IpAddr
IpV6 ([Word16]
hd [Word16] -> [Word16] -> [Word16]
forall a. Semigroup a => a -> a -> a
<> Int -> Word16 -> [Word16]
forall a. Int -> a -> [a]
replicate (Int
8 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
present) Word16
0 [Word16] -> [Word16] -> [Word16]
forall a. Semigroup a => a -> a -> a
<> [Word16]
tl))
else Maybe IpAddr
forall a. Maybe a
Nothing
exactlyEightGroups :: [Word16] -> Maybe IpAddr
exactlyEightGroups :: [Word16] -> Maybe IpAddr
exactlyEightGroups gs :: [Word16]
gs@[Word16
_, Word16
_, Word16
_, Word16
_, Word16
_, Word16
_, Word16
_, Word16
_] = IpAddr -> Maybe IpAddr
forall a. a -> Maybe a
Just ([Word16] -> IpAddr
IpV6 [Word16]
gs)
exactlyEightGroups [Word16]
_ = Maybe IpAddr
forall a. Maybe a
Nothing
isDecimal :: Text -> Bool
isDecimal :: Text -> Bool
isDecimal Text
t = Bool -> Bool
not (Text -> Bool
T.null Text
t) Bool -> Bool -> Bool
&& (Char -> Bool) -> Text -> Bool
T.all (Char -> String -> Bool
forall (f :: * -> *) a.
(Foldable f, DisallowElem f, Eq a) =>
a -> f a -> Bool
`elem` [Char
'0' .. Char
'9']) Text
t
isOctal :: Text -> Bool
isOctal :: Text -> Bool
isOctal Text
t = Bool -> Bool
not (Text -> Bool
T.null Text
t) Bool -> Bool -> Bool
&& (Char -> Bool) -> Text -> Bool
T.all (Char -> String -> Bool
forall (f :: * -> *) a.
(Foldable f, DisallowElem f, Eq a) =>
a -> f a -> Bool
`elem` [Char
'0' .. Char
'7']) Text
t
isHex :: Text -> Bool
isHex :: Text -> Bool
isHex Text
t = Bool -> Bool
not (Text -> Bool
T.null Text
t) Bool -> Bool -> Bool
&& (Char -> Bool) -> Text -> Bool
T.all Char -> Bool
isHexDigit Text
t
where
isHexDigit :: Char -> Bool
isHexDigit Char
c = Char
c Char -> String -> Bool
forall (f :: * -> *) a.
(Foldable f, DisallowElem f, Eq a) =>
a -> f a -> Bool
`elem` ([Char
'0' .. Char
'9'] String -> ShowS
forall a. Semigroup a => a -> a -> a
<> [Char
'a' .. Char
'f'] String -> ShowS
forall a. Semigroup a => a -> a -> a
<> [Char
'A' .. Char
'F'])
data TarballHostPolicy
=
SameHostAsPackument
|
AnyAllowlistedHost
deriving stock (TarballHostPolicy -> TarballHostPolicy -> Bool
(TarballHostPolicy -> TarballHostPolicy -> Bool)
-> (TarballHostPolicy -> TarballHostPolicy -> Bool)
-> Eq TarballHostPolicy
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: TarballHostPolicy -> TarballHostPolicy -> Bool
== :: TarballHostPolicy -> TarballHostPolicy -> Bool
$c/= :: TarballHostPolicy -> TarballHostPolicy -> Bool
/= :: TarballHostPolicy -> TarballHostPolicy -> Bool
Eq, Int -> TarballHostPolicy -> ShowS
[TarballHostPolicy] -> ShowS
TarballHostPolicy -> String
(Int -> TarballHostPolicy -> ShowS)
-> (TarballHostPolicy -> String)
-> ([TarballHostPolicy] -> ShowS)
-> Show TarballHostPolicy
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TarballHostPolicy -> ShowS
showsPrec :: Int -> TarballHostPolicy -> ShowS
$cshow :: TarballHostPolicy -> String
show :: TarballHostPolicy -> String
$cshowList :: [TarballHostPolicy] -> ShowS
showList :: [TarballHostPolicy] -> ShowS
Show)
data Origin
=
TrustedOrigin
|
UntrustedOrigin
deriving stock (Origin -> Origin -> Bool
(Origin -> Origin -> Bool)
-> (Origin -> Origin -> Bool) -> Eq Origin
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Origin -> Origin -> Bool
== :: Origin -> Origin -> Bool
$c/= :: Origin -> Origin -> Bool
/= :: Origin -> Origin -> Bool
Eq, Int -> Origin -> ShowS
[Origin] -> ShowS
Origin -> String
(Int -> Origin -> ShowS)
-> (Origin -> String) -> ([Origin] -> ShowS) -> Show Origin
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Origin -> ShowS
showsPrec :: Int -> Origin -> ShowS
$cshow :: Origin -> String
show :: Origin -> String
$cshowList :: [Origin] -> ShowS
showList :: [Origin] -> ShowS
Show)
tarballHostAllowed ::
Origin ->
TarballHostPolicy ->
LoweredHostSet ->
[IPRange] ->
Text ->
Text ->
Bool
tarballHostAllowed :: Origin
-> TarballHostPolicy
-> LoweredHostSet
-> [IPRange]
-> Text
-> Text
-> Bool
tarballHostAllowed Origin
origin TarballHostPolicy
policy LoweredHostSet
allowed [IPRange]
additionalBlockedRanges Text
packumentHost Text
tarballHost =
LoweredHostSet -> Text -> Bool
isAllowedUpstreamHost LoweredHostSet
allowed Text
tarballHost
Bool -> Bool -> Bool
&& Bool
internalRangeOk
Bool -> Bool -> Bool
&& case TarballHostPolicy
policy of
TarballHostPolicy
SameHostAsPackument -> Text -> Text
canonicalHostKey Text
tarballHost Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text -> Text
canonicalHostKey Text
packumentHost
TarballHostPolicy
AnyAllowlistedHost -> Bool
True
where
internalRangeOk :: Bool
internalRangeOk :: Bool
internalRangeOk = case Origin
origin of
Origin
TrustedOrigin -> Bool
True
Origin
UntrustedOrigin -> Bool -> Bool
not ([IPRange] -> Text -> Bool
isBlockedTarget [IPRange]
additionalBlockedRanges Text
tarballHost)
data TarballHostGate = TarballHostGate
{ TarballHostGate -> LoweredHostSet
thgAllowlist :: LoweredHostSet
, TarballHostGate -> Text
thgPrivateHost :: Text
, TarballHostGate -> Text
thgPublicHost :: Text
}
deriving stock (TarballHostGate -> TarballHostGate -> Bool
(TarballHostGate -> TarballHostGate -> Bool)
-> (TarballHostGate -> TarballHostGate -> Bool)
-> Eq TarballHostGate
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: TarballHostGate -> TarballHostGate -> Bool
== :: TarballHostGate -> TarballHostGate -> Bool
$c/= :: TarballHostGate -> TarballHostGate -> Bool
/= :: TarballHostGate -> TarballHostGate -> Bool
Eq, Int -> TarballHostGate -> ShowS
[TarballHostGate] -> ShowS
TarballHostGate -> String
(Int -> TarballHostGate -> ShowS)
-> (TarballHostGate -> String)
-> ([TarballHostGate] -> ShowS)
-> Show TarballHostGate
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TarballHostGate -> ShowS
showsPrec :: Int -> TarballHostGate -> ShowS
$cshow :: TarballHostGate -> String
show :: TarballHostGate -> String
$cshowList :: [TarballHostGate] -> ShowS
showList :: [TarballHostGate] -> ShowS
Show)
tarballHostGate :: Text -> Text -> Text -> TarballHostGate
tarballHostGate :: Text -> Text -> Text -> TarballHostGate
tarballHostGate Text
privateUrl Text
publicUrl Text
mirrorUrl =
TarballHostGate
{ thgAllowlist :: LoweredHostSet
thgAllowlist = Set Text -> LoweredHostSet
lowerCaseHosts ([Text] -> Set Text
forall a. Ord a => [a] -> Set a
Set.fromList [Text
privateHost, Text
publicHost, Text -> Text
hostAddress Text
mirrorUrl])
, thgPrivateHost :: Text
thgPrivateHost = Text
privateHost
, thgPublicHost :: Text
thgPublicHost = Text
publicHost
}
where
privateHost :: Text
privateHost = Text -> Text
hostAddress Text
privateUrl
publicHost :: Text
publicHost = Text -> Text
hostAddress Text
publicUrl