From 36cb273103f31a95d381166ebda904401ed6ac19 Mon Sep 17 00:00:00 2001 From: lare Date: Wed, 23 Nov 2022 16:47:55 +0100 Subject: [PATCH] implement server side form validation --- web/backend/main.py | 94 ++++++++++++++++++++++++++++++++++ web/frontend/peerings-new.html | 4 +- 2 files changed, 96 insertions(+), 2 deletions(-) diff --git a/web/backend/main.py b/web/backend/main.py index 4fa8403..9abca5a 100644 --- a/web/backend/main.py +++ b/web/backend/main.py @@ -1,6 +1,7 @@ #! /usr/bin/env python3 from flask import Flask, Response, redirect, render_template, request, session, abort +import werkzeug.exceptions as werkzeug_exceptions import json, os, base64, logging from functools import wraps from ipaddress import ip_address, ip_network @@ -188,6 +189,99 @@ def peerings_new(): else: return render_template("peerings-new.html", session=session,config=config, peerings=peerings) elif request.method == "POST": + print(request.args) + print(request.form) + if not "node" in request.args or not request.args["node"]: + return render_template("peerings-new.html", session=session,config=config, peerings=peerings, msg="no node specified, please click one of the buttons above") + + new_peering = {} + # errors = 0 + + ## check if all required (and enabled) options are specified + try: + new_peering["peer-wgkey"] = request.form["peer-wgkey"] + if request.form["peer-endpoint-enabled"] == "on": + new_peering["peer-endpoint"] = request.form["peer-endpoint"] + if new_peering["peer-endpoint"] == "": + raise ValueError("peer-endpoint") + else: + new_peering["peer-endpoint"] = None + + if "peer-v6ll-enabled" in request.form and request.form["peer-v6ll-enabled"] == "on": + new_peering["peer-v6ll"] = request.form["peer-v6ll"] + if new_peering["peer-v6ll"] == "": + raise ValueError("peer-v6ll") + else: + new_peering["peer-v6ll"] = None + if "peer-v4-enabled" in request.form and request.form["peer-v4-enabled"] == "on": + new_peering["peer-v4"] = request.form["peer-v4"] + if new_peering["peer-v4"] == "": + raise ValueError("peer-v4") + else: + new_peering["peer-v4"] = None + if "peer-v6-enabled" in request.form and request.form["peer-v6-enabled"] == "on": + new_peering["peer-v6"] = request.form["peer-v6"] + if new_peering["peer-v6"] == "": + raise ValueError("peer-v6") + else: + new_peering["peer-v6"] = None + #new_peering[""] = request.form["peer-wgkey"] + except ValueError as e: + print(f"error: {e.args}") + return render_template("peerings-new.html", session=session,config=config, peerings=peerings, msg="at least one of the required/enabled fields was not filled out"), 400 + + print(new_peering) + + ## check wireguard key + wg_key_invalid = False + if len(new_peering["peer-wgkey"]) != 44: + wg_key_invalid = True + try: + base64.b64decode(new_peering["peer-wgkey"]) + except: + wg_key_invalid = True + if wg_key_invalid: + return render_template("peerings-new.html", session=session,config=config, peerings=peerings, msg="invalid wireguard Key"), 400 + + ## check endpoint + if new_peering["peer-endpoint"]: + if not new_peering["peer-endpoint"].split(":")[-1].isnumeric(): + return render_template("peerings-new.html", session=session,config=config, peerings=peerings, msg="no port number in endpoint"), 400 + elif len(new_peering["peer-endpoint"].split(":")) < 2 and not "." in new_peering["peer-endpoint"]: + return render_template("peerings-new.html", session=session,config=config, peerings=peerings, msg="endpoint doesn't look like a ip address or fqdn"), 400 + + ## check if at least one ip is specified/enabled + try: + if not (new_peering["peer-v6ll"] or new_peering["peer-v4"] or new_peering["peer-v6"]): + return render_template("peerings-new.html", session=session,config=config, peerings=peerings, msg="at least one of the ip addresses must be enabled and specified"), 400 + except KeyError: + return render_template("peerings-new.html", session=session,config=config, peerings=peerings, msg="one of the values isn't valid"), 400 + + ## check if supplied ip addresses are valid + try: + if new_peering["peer-v6ll"]: + ipv6ll = ip_address(new_peering["peer-v6ll"]) + if not ipv6ll.version == 6: raise ValueError() + if not ipv6ll.is_link_local: raise ValueError() + if new_peering["peer-v4"]: + ipv4 = ip_address(new_peering["peer-v4"]) + if not ipv4.version == 4: raise ValueError() + if ipv4.is_private: + if not (ipv4.compressed.startswith("172.2") or ipv4.compressed.startswith("10.")): + raise ValueError() + elif ipv4.is_link_local: + pass + else: raise ValueError() + if new_peering["peer-v6"]: + ipv6 = ip_address(new_peering["peer-v6"]) + if not ipv6.version == 6: raise ValueError() + if not ipv6.is_private: raise ValueError() + + except ValueError: + return render_template("peerings-new.html", session=session,config=config, peerings=peerings, msg="invalid ip address(es) supplied"), 400 + + + return """
creating peerings is not (yet) implemented
return""" return f"{request.method} /peerings/new {str(request.args)}{str(request.form)}" @app.route("/peerings", methods=["GET","POST","DELETE"]) diff --git a/web/frontend/peerings-new.html b/web/frontend/peerings-new.html index 650b64a..83fc9a8 100644 --- a/web/frontend/peerings-new.html +++ b/web/frontend/peerings-new.html @@ -25,7 +25,7 @@ msg += "
  • endpoint enabled but non specified
  • "; } else if (isNaN(endpoint.split(":").at(-1))) { msg += "
  • endpoint doesn't end with a (port)number
  • "; - } else if (endpoint.split(":").length > 2 || endpoint.indexOf(".") == -1) { + } else if (endpoint.split(":").length < 2 && endpoint.indexOf(".") == -1) { msg += "
  • endpoint doesn't look like a ip address or fqdn
  • "; } } @@ -139,7 +139,7 @@ {% endfor %}
    -
    +
    {% if msg %}{{msg}}{%endif%}