diff --git a/capport-example.yaml b/capport-example.yaml index 7e124f2..27bba9a 100644 --- a/capport-example.yaml +++ b/capport-example.yaml @@ -1,7 +1,11 @@ --- -secret: mysecret +comm-secret: mysecret +cookie-secret: mysecret controllers: - capport-controller1.example.com - capport-controller2.example.com session-timeout: 3600 # in seconds venue-info-url: 'https://example.com' +server-names: +- localhost +- ... diff --git a/src/capport/api/__init__.py b/src/capport/api/__init__.py index ac785e2..8a018e1 100644 --- a/src/capport/api/__init__.py +++ b/src/capport/api/__init__.py @@ -131,7 +131,8 @@ async def _run_hub(*, task_status=trio.TASK_STATUS_IGNORED) -> None: @app.before_serving async def init(): global config - config = Config.load() + config = Config.load_default_once() + app.secret_key = config.cookie_secret capport.utils.cli.init_logger(config) await app.nursery.start(_run_hub) @@ -152,6 +153,7 @@ async def login(): address = get_client_ip() mac = await get_client_mac(address) await user_login(address, mac) + await quart.flash('Logged in') return quart.redirect('/', code=303) @@ -159,6 +161,7 @@ async def login(): async def logout(): mac = await get_client_mac() await user_logout(mac) + await quart.flash('Logged out') return quart.redirect('/', code=303) diff --git a/src/capport/api/hypercorn_conf.py b/src/capport/api/hypercorn_conf.py new file mode 100644 index 0000000..4661c0a --- /dev/null +++ b/src/capport/api/hypercorn_conf.py @@ -0,0 +1,12 @@ +from __future__ import annotations + +import capport.config + +_config = capport.config.Config.load_default_once() + +worker_class = 'trio' + +if _config.server_names: + server_names = _config.server_names +elif not _config.debug: + raise Exception("production setup requires server-names in config (list of accepted hostnames in http requests)") diff --git a/src/capport/api/templates/base.html b/src/capport/api/templates/base.html new file mode 100644 index 0000000..88b314c --- /dev/null +++ b/src/capport/api/templates/base.html @@ -0,0 +1,14 @@ + + + + + {% block title %}Captive Portal Universität Stuttgart{% endblock %} + + + + {% block content %}{% endblock %} + {% for message in get_flashed_messages() %} +
{{ message }}
+ {% endfor %} + + diff --git a/src/capport/api/templates/index.html b/src/capport/api/templates/index.html index bc762a7..b5ad377 100644 --- a/src/capport/api/templates/index.html +++ b/src/capport/api/templates/index.html @@ -1,22 +1,16 @@ - - - - - Captive Portal Universität Stuttgart - - - - {% if not state.mac %} - It seems you're accessing this site from outside the network this captive portal is running for. - {% elif state.captive %} - To get access to the internet please accept our usage guidelines by clicking this button: -
- {% else %} - You already accepted out conditions and are currently granted access to the internet: -
-
-
- Your current session will last for {{ state.allowed_remaining }} seconds. - {% endif %} - - \ No newline at end of file +{% extends "base.html" %} +{% block content %} + {% if not state.mac %} +

It seems you're accessing this site from outside the network this captive portal is running for.

+

Your clients IP address is {{ state.address }}

+ {% elif state.captive %} + To get access to the internet please accept our usage guidelines by clicking this button: +
+ {% else %} + You already accepted out conditions and are currently granted access to the internet: +
+
+
+ Your current session will last for {{ state.allowed_remaining }} seconds. + {% endif %} +{% endblock %} \ No newline at end of file diff --git a/src/capport/comm/hub.py b/src/capport/comm/hub.py index 2401f4e..6f02aa0 100644 --- a/src/capport/comm/hub.py +++ b/src/capport/comm/hub.py @@ -339,7 +339,7 @@ class Hub: await trio.sleep_forever() def _calc_authentication(self, ssl_binding: bytes, server_side: bool) -> bytes: - m = hmac.new(self._config.secret.encode('utf8'), digestmod=hashlib.sha256) + m = hmac.new(self._config.comm_secret.encode('utf8'), digestmod=hashlib.sha256) if server_side: m.update(b'server$') else: diff --git a/src/capport/config.py b/src/capport/config.py index 6ebb52d..eb43a53 100644 --- a/src/capport/config.py +++ b/src/capport/config.py @@ -7,16 +7,28 @@ import typing import yaml +_cached_config: typing.Optional[Config] = None + + @dataclasses.dataclass class Config: controllers: typing.List[str] - secret: str + server_names: typing.List[str] + comm_secret: str + cookie_secret: str venue_info_url: typing.Optional[str] session_timeout: int # in seconds debug: bool @staticmethod - def load(filename: typing.Optional[str]=None) -> 'Config': + def load_default_once() -> Config: + global _cached_config + if not _cached_config: + _cached_config = Config.load() + return _cached_config + + @staticmethod + def load(filename: typing.Optional[str]=None) -> Config: if filename is None: for name in ('capport.yaml', '/etc/capport.yaml'): if os.path.exists(name): @@ -27,7 +39,9 @@ class Config: controllers = list(map(str, data['controllers'])) return Config( controllers=controllers, - secret=str(data['secret']), + server_names=data.get('server-names', []), + comm_secret=str(data.get('comm-secret', None) or data['secret']), + cookie_secret=str(data['cookie-secret']), venue_info_url=str(data.get('venue-info-url')), session_timeout=data.get('session-timeout', 3600), debug=data.get('debug', False) diff --git a/src/capport/control/run.py b/src/capport/control/run.py index 106c5c5..4ce75f2 100644 --- a/src/capport/control/run.py +++ b/src/capport/control/run.py @@ -48,7 +48,7 @@ async def amain(config: capport.config.Config) -> None: def main() -> None: - config = capport.config.Config.load() + config = capport.config.Config.load_default_once() capport.utils.cli.init_logger(config) try: trio.run(amain, config) diff --git a/start-api.sh b/start-api.sh index 50c2163..1d9d365 100755 --- a/start-api.sh +++ b/start-api.sh @@ -5,4 +5,4 @@ set -e base=$(dirname "$(readlink -f "$0")") cd "${base}" -exec ./venv/bin/hypercorn -k trio capport.api "$@" +exec ./venv/bin/hypercorn --config python:capport.api.hypercorn_conf capport.api "$@"