2
0

login/logout: check client mac from form as csrf protection, check accept in login

This commit is contained in:
Stefan Bühler 2022-04-07 15:11:24 +02:00
parent 237640f0d7
commit 2e6b368670
3 changed files with 25 additions and 5 deletions

View File

@ -5,9 +5,11 @@ You already accepted out conditions and are currently granted access to the inte
Your current session will last for {{ state.allowed_remaining }} seconds. Your current session will last for {{ state.allowed_remaining }} seconds.
<form method="POST" action="/login"> <form method="POST" action="/login">
<input type="hidden" name="accept" value="1"> <input type="hidden" name="accept" value="1">
<input type="hidden" name="mac" value="{{ state.mac }}">
<button type="submit" class="btn btn-primary mb-3">Extend session</button> <button type="submit" class="btn btn-primary mb-3">Extend session</button>
</form> </form>
<form method="POST" action="/logout"> <form method="POST" action="/logout">
<input type="hidden" name="mac" value="{{ state.mac }}">
<button type="submit" class="btn btn-danger mb-3">Terminate session</button> <button type="submit" class="btn btn-danger mb-3">Terminate session</button>
</form> </form>
<br> <br>

View File

@ -3,6 +3,7 @@
To get access to the internet please accept our usage guidelines by clicking this button: To get access to the internet please accept our usage guidelines by clicking this button:
<form method="POST" action="/login"> <form method="POST" action="/login">
<input type="hidden" name="accept" value="1"> <input type="hidden" name="accept" value="1">
<input type="hidden" name="mac" value="{{ state.mac }}">
<button type="submit" class="btn btn-primary mb-3">Accept</button> <button type="submit" class="btn btn-primary mb-3">Accept</button>
</form> </form>
{% endblock %} {% endblock %}

View File

@ -10,12 +10,12 @@ import capport.database
import capport.utils.cli import capport.utils.cli
import capport.utils.ipneigh import capport.utils.ipneigh
import quart import quart
import trio
from capport import cptypes from capport import cptypes
from .app import app from .app import app
from .lang import render_i18n_template from .lang import render_i18n_template
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
@ -97,27 +97,44 @@ async def user_lookup() -> cptypes.MacPublicState:
@app.route('/', methods=['GET']) @app.route('/', methods=['GET'])
async def index(): async def index(missing_accept: bool=False):
state = await user_lookup() state = await user_lookup()
return await render_i18n_template('index_active.html', state=state, missing_accept=missing_accept)
if not state.mac: if not state.mac:
return await render_i18n_template('index_unknown.html', state=state) return await render_i18n_template('index_unknown.html', state=state, missing_accept=missing_accept)
elif state.allowed: elif state.allowed:
return await render_i18n_template('index_active.html', state=state) return await render_i18n_template('index_active.html', state=state, missing_accept=missing_accept)
else: else:
return await render_i18n_template('index_inactive.html', state=state) return await render_i18n_template('index_inactive.html', state=state, missing_accept=missing_accept)
@app.route('/login', methods=['POST']) @app.route('/login', methods=['POST'])
async def login(): async def login():
with trio.fail_after(5.0):
form = await quart.request.form
if form.get('accept') != '1':
return await index(missing_accept=True)
req_mac = form.get('mac')
if not req_mac:
quart.abort(400, description='Missing MAC in request form data')
address = get_client_ip() address = get_client_ip()
mac = await get_client_mac(address) mac = await get_client_mac(address)
if str(mac) != req_mac:
quart.abort(403, description="Passed MAC in request form doesn't match client address")
await user_login(address, mac) await user_login(address, mac)
return quart.redirect('/', code=303) return quart.redirect('/', code=303)
@app.route('/logout', methods=['POST']) @app.route('/logout', methods=['POST'])
async def logout(): async def logout():
with trio.fail_after(5.0):
form = await quart.request.form
req_mac = form.get('mac')
if not req_mac:
quart.abort(400, description='Missing MAC in request form data')
mac = await get_client_mac() mac = await get_client_mac()
if str(mac) != req_mac:
quart.abort(403, description="Passed MAC in request form doesn't match client address")
await user_logout(mac) await user_logout(mac)
return quart.redirect('/', code=303) return quart.redirect('/', code=303)