aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2016-12-27 21:53:30 +0300
committerIgor Pashev <pashev.igor@gmail.com>2016-12-27 21:53:30 +0300
commitd7e5277c680d73ac2e11aea0b473d98b2d48350c (patch)
tree8b2e2ae8b01ab984ea76a32d2b1bcfe1e78d6763
parent43bf95e21d4a616a55b211670076a8c7c48c06a3 (diff)
downloadsproxy2-d7e5277c680d73ac2e11aea0b473d98b2d48350c.tar.gz
Disregard possible port in the Host HTTP header
Motivation: to make it easy to switch Sproxy's primary port. This could be useful when running private (behind Sproxy) and public (e. g. nginx) HTTPS services on the same server. In such a setup one can use port 443 for public services and alt. HTTPS port 8443 for Sproxy. Before this change, Sproxy took possible port number into account when looking for backend and privileges. Now it ignores port and considers domain name only. This also gets Sproxy in line with browsers and SSL certificates: certificates do not include port numbers, browsers ignore ports when sending cookies.
-rw-r--r--sproxy.example.yml5
-rw-r--r--src/Sproxy/Application.hs24
2 files changed, 16 insertions, 13 deletions
diff --git a/sproxy.example.yml b/sproxy.example.yml
index 063f51e..0259dfc 100644
--- a/sproxy.example.yml
+++ b/sproxy.example.yml
@@ -147,11 +147,10 @@ ssl_key: /path/key.pem
# Unix sockets should be secured with proper unix file permissions.
#
# Backend attributes:
-# name - the host name as in the Host HTTP header.
+# name - the domain name as in the Host HTTP header (without optional colon and port).
# May include wildcards * and ?. The first matching
# backend will be used. Examples: "*.example.com", "wiki.corp.com".
-# Optional. Default is "*". Note, that the name must include
-# port number if non-standard.
+# Optional. Default is "*".
# address - backend IP address. Optional. Default is 127.0.0.1.
# port - backend TCP port. Required unless unix socket is defined.
# socket - unix socket. Highly recommended for security reasons.
diff --git a/src/Sproxy/Application.hs b/src/Sproxy/Application.hs
index ad3bec7..7376657 100644
--- a/src/Sproxy/Application.hs
+++ b/src/Sproxy/Application.hs
@@ -55,14 +55,13 @@ import qualified Sproxy.Logging as Log
redirect :: Word16 -> W.Application
redirect p req resp =
- case W.requestHeaderHost req of
+ case requestDomain req of
Nothing -> badRequest "missing host" req resp
- Just host -> do
+ Just domain -> do
Log.info $ "redirecting to " ++ show location ++ ": " ++ showReq req
resp $ W.responseBuilder status [(hLocation, location)] mempty
where
status = if W.requestMethod req == methodGet then movedPermanently301 else temporaryRedirect307
- (domain, _) = BS.break (== _colon) host
newhost = if p == 443 then domain else domain <> ":" <> pack (show p)
location = "https://" <> newhost <> W.rawPathInfo req <> W.rawQueryString req
@@ -70,10 +69,10 @@ redirect p req resp =
sproxy :: ByteString -> Database -> HashMap Text OAuth2Client -> [(Pattern, BackendConf, BE.Manager)] -> W.Application
sproxy key db oa2 backends = logException $ \req resp -> do
Log.debug $ "sproxy <<< " ++ showReq req
- case W.requestHeaderHost req of
+ case requestDomain req of
Nothing -> badRequest "missing host" req resp
- Just host ->
- case find (\(p, _, _) -> match p (unpack host)) backends of
+ Just domain ->
+ case find (\(p, _, _) -> match p (unpack domain)) backends of
Nothing -> notFound "backend" req resp
Just (_, be, mgr) -> do
let cookieName = pack $ beCookieName be
@@ -145,8 +144,7 @@ extractCookie key now name req = do
authenticate :: ByteString -> BackendConf -> AuthUser -> ByteString -> W.Application
authenticate key be user path req resp = do
now <- epochTime
- let host = fromJust $ W.requestHeaderHost req
- domain = pack <$> beCookieDomain be
+ let domain = pack <$> beCookieDomain be
expiry = now + CTime (beCookieMaxAge be)
authCookie = AuthCookie { acUser = user, acExpiry = expiry }
cookie = WC.def {
@@ -160,7 +158,7 @@ authenticate key be user path req resp = do
, WC.setCookieExpires = Just . posixSecondsToUTCTime . realToFrac $ expiry
}
resp $ W.responseLBS seeOther303 [
- (hLocation, "https://" <> host <> path)
+ (hLocation, "https://" <> fromJust (W.requestHeaderHost req) <> path)
, ("Set-Cookie", toByteString $ WC.renderSetCookie cookie)
] ""
@@ -169,7 +167,7 @@ authorize :: Database -> (AuthCookie, Cookies) -> W.Request -> IO (Maybe W.Reque
authorize db (authCookie, otherCookies) req = do
let
user = acUser authCookie
- domain = decodeUtf8 . fromJust $ W.requestHeaderHost req
+ domain = decodeUtf8 . fromJust $ requestDomain req
email = getEmail user
emailUtf8 = getEmailUtf8 user
familyUtf8 = getFamilyNameUtf8 user
@@ -388,6 +386,12 @@ redirectURL req provider =
<> "/.sproxy/oauth2/" <> encodeUtf8 provider
+requestDomain :: W.Request -> Maybe ByteString
+requestDomain req = do
+ h <- W.requestHeaderHost req
+ return . fst . BS.break (== _colon) $ h
+
+
-- XXX: make sure not to reveal the cookie, which can be valid (!)
showReq :: W.Request -> String
showReq req =