From 252ed8ab9b38413bf7d95429cc2fc0868a94c093 Mon Sep 17 00:00:00 2001 From: Michael Zhang Date: Wed, 6 Jan 2016 00:15:57 -0600 Subject: [PATCH] login/register system with tokens --- ctf.nginx | 2 +- scripts/requirements.txt | 1 + server/api/decorators.py | 2 +- server/api/models.py | 134 +++++++++++++--------- server/api/schemas.py | 24 ++++ server/api/user.py | 194 ++++++++++++++++++++++---------- server/api/utils.py | 12 +- web/css/easyctf.css | 13 +++ web/fonts/ProximaNova.woff2 | Bin 0 -> 17997 bytes web/fonts/ProximaNovaBold.woff2 | Bin 0 -> 18009 bytes web/index.html | 108 ++++++------------ web/js/easyctf.js | 181 ++++++++++++++++------------- web/js/login.js | 7 +- web/pages/blank.html | 0 web/pages/login.html | 65 ++++++++--- web/pages/profile.html | 0 web/pages/register.html | 157 ++++++++++++++++---------- 17 files changed, 547 insertions(+), 353 deletions(-) create mode 100644 server/api/schemas.py create mode 100644 web/css/easyctf.css create mode 100644 web/fonts/ProximaNova.woff2 create mode 100644 web/fonts/ProximaNovaBold.woff2 create mode 100644 web/pages/blank.html create mode 100644 web/pages/profile.html diff --git a/ctf.nginx b/ctf.nginx index 579eba7..f866686 100644 --- a/ctf.nginx +++ b/ctf.nginx @@ -13,7 +13,7 @@ server { # } # Put all the pages here so Angular doesn't fail. - location ~^/(about|login|register|scoreboard|chat|updates|problems|programming|shell|rules|admin/problems)$ { + location ~^/(about|chat|help|learn|login|profile|register|scoreboard|settings|team)$ { default_type text/html; try_files /index.html /index.html; } diff --git a/scripts/requirements.txt b/scripts/requirements.txt index ec2f247..7d8974f 100644 --- a/scripts/requirements.txt +++ b/scripts/requirements.txt @@ -4,3 +4,4 @@ Flask-SQLAlchemy SQLAlchemy gunicorn requests +voluptuous \ No newline at end of file diff --git a/server/api/decorators.py b/server/api/decorators.py index 59715a0..558f6b3 100644 --- a/server/api/decorators.py +++ b/server/api/decorators.py @@ -19,7 +19,7 @@ def api_wrapper(f): except Exception as error: response = 200 traceback.print_exc() - web_result = { "success": 0, "message": "Something went wrong! Please notify us about this immediately. %s: %s" % (error, traceback.format_exc()) } + web_result = { "success": 0, "message": "Something went wrong! Please notify us about this immediately.", "error": [ str(error), traceback.format_exc() ] } return json.dumps(web_result), response, { "Content-Type": "application/json; charset=utf-8" } return wrapper diff --git a/server/api/models.py b/server/api/models.py index a69ee79..2d2a9af 100644 --- a/server/api/models.py +++ b/server/api/models.py @@ -1,73 +1,99 @@ from flask.ext.sqlalchemy import SQLAlchemy +import datetime import utils db = SQLAlchemy() class Users(db.Model): - uid = db.Column(db.Integer, primary_key=True) - tid = db.Column(db.Integer) - name = db.Column(db.String(64)) - username = db.Column(db.String(64), unique=True) - username_lower = db.Column(db.String(64), unique=True) - email = db.Column(db.String(64), unique=True) - password = db.Column(db.String(128)) - admin = db.Column(db.Boolean, default=False) + uid = db.Column(db.Integer, unique=True, primary_key=True) + tid = db.Column(db.Integer) + name = db.Column(db.String(64)) + username = db.Column(db.String(64), unique=True) + username_lower = db.Column(db.String(64), unique=True) + email = db.Column(db.String(64), unique=True) + password = db.Column(db.String(128)) + utype = db.Column(db.Integer) - def __init__(self, name, username, email, password): - self.name = name - self.username = username - self.username_lower = username.lower() - self.email = email.lower() - self.password = utils.hash_password(password) + def __init__(self, name, username, email, password, utype=1): + self.name = name + self.username = username + self.username_lower = username.lower() + self.email = email.lower() + self.password = utils.hash_password(password) + self.utype = utype class Teams(db.Model): - tid = db.Column(db.Integer, primary_key=True) - name = db.Column(db.String(64), unique=True) - join_code = db.Column(db.String(128), unique=True) - school = db.Column(db.Text) - size = db.Column(db.Integer) - score = db.Column(db.Integer) - observer = db.Column(db.Boolean) - owner = db.Column(db.Integer) + tid = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(64), unique=True) + join_code = db.Column(db.String(128), unique=True) + school = db.Column(db.Text) + size = db.Column(db.Integer) + score = db.Column(db.Integer) + observer = db.Column(db.Boolean) + owner = db.Column(db.Integer) - def __init__(self, name, school): - self.name = name - self.school = school + def __init__(self, name, school): + self.name = name + self.school = school class Problems(db.Model): - pid = db.Column(db.Integer, primary_key=True) - name = db.Column(db.String(128)) - category = db.Column(db.String(128)) - description = db.Column(db.Text) - hint = db.Column(db.Text) - flag = db.Column(db.Text) - disabled = db.Column(db.Boolean, default=False) - value = db.Column(db.Integer) - solves = db.Column(db.Integer, default=0) + pid = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(128)) + category = db.Column(db.String(128)) + description = db.Column(db.Text) + hint = db.Column(db.Text) + flag = db.Column(db.Text) + disabled = db.Column(db.Boolean, default=False) + value = db.Column(db.Integer) + solves = db.Column(db.Integer, default=0) - def __init__(self, name, category, description, hint, flag, value): - self.name = name - self.category = category - self.description = description - self.hint = hint - self.flag = flag - self.value = value + def __init__(self, name, category, description, hint, flag, value): + self.name = name + self.category = category + self.description = description + self.hint = hint + self.flag = flag + self.value = value class Files(db.Model): - fid = db.Column(db.Integer, primary_key=True) - pid = db.Column(db.Integer) - location = db.Column(db.Text) + fid = db.Column(db.Integer, primary_key=True) + pid = db.Column(db.Integer) + location = db.Column(db.Text) - def __init__(self, pid, location): - self.pid = pid - self.location = location + def __init__(self, pid, location): + self.pid = pid + self.location = location class Solves(db.Model): - sid = db.Column(db.Integer, primary_key=True) - pid = db.Column(db.Integer) - tid = db.Column(db.Integer) - date = db.Column(db.Integer, default=utils.get_time_since_epoch()) + sid = db.Column(db.Integer, primary_key=True) + pid = db.Column(db.Integer) + tid = db.Column(db.Integer) + date = db.Column(db.Integer, default=utils.get_time_since_epoch()) - def __init__(self, pid, tid): - self.pid = pid - self.tid = tid + def __init__(self, pid, tid): + self.pid = pid + self.tid = tid + +########## +# TOKENS # +########## + +class LoginTokens(db.Model): + sid = db.Column(db.String(64), unique=True, primary_key=True) + uid = db.Column(db.Integer) + username = db.Column(db.String(32)) + active = db.Column(db.Boolean) + issued = db.Column(db.Integer) + expiry = db.Column(db.Integer) + ua = db.Column(db.String(128)) + ip = db.Column(db.String(16)) + + def __init__(self, uid, username, expiry=datetime.datetime.utcnow(), active=True, ua=None, ip=None): + self.sid = utils.generate_string() + self.uid = uid + self.username = username + self.issued = datetime.datetime.utcnow() + self.expiry = expiry + self.active = active + self.ua = ua + self.ip = ip \ No newline at end of file diff --git a/server/api/schemas.py b/server/api/schemas.py new file mode 100644 index 0000000..1648950 --- /dev/null +++ b/server/api/schemas.py @@ -0,0 +1,24 @@ +import api +import re + +from voluptuous import Required, Length, Schema, Invalid, MultipleInvalid +from decorators import WebException + +def check(*callback_tuples): + def v(value): + for callbacks, msg in callback_tuples: + for callback in callbacks: + try: + result = callback(value) + if not result and type(result) == bool: + raise Invalid(msg) + except Exception: + raise WebException(msg) + return value + return v + +def verify_to_schema(schema, data): + try: + schema(data) + except MultipleInvalid as error: + raise WebException(str(error)) \ No newline at end of file diff --git a/server/api/user.py b/server/api/user.py index 08aa15a..c8b4daf 100644 --- a/server/api/user.py +++ b/server/api/user.py @@ -1,96 +1,170 @@ from flask import Blueprint, session, request, redirect, url_for from flask import current_app as app +from voluptuous import Schema, Length, Required -from models import db, Users -from decorators import api_wrapper +from models import db, LoginTokens, Users +from decorators import api_wrapper, WebException +from schemas import verify_to_schema, check import logger +import re import requests import utils +############### +# USER ROUTES # +############### + blueprint = Blueprint("user", __name__) @blueprint.route("/register", methods=["POST"]) @api_wrapper def user_register(): - # if not validate_captcha(request.form): - # return { "success": 0, "message": "Please do the captcha." } + params = utils.flat_multi(request.form) - name = request.form["name"] - username = request.form["username"] - password = request.form["password"] - password_confirm = request.form["password_confirm"] - email = request.form["email"] + name = params.get("name") + email = params.get("email") + username = params.get("username") + password = params.get("password") + password_confirm = params.get("password_confirm") + utype = int(params.get("type")) - username_exists = Users.query.add_columns("name", "uid").filter_by(username_lower=username.lower()).first() - email_exists = Users.query.add_columns("name", "uid").filter_by(email=email.lower()).first() + if password != password_confirm: + raise WebException("Passwords do not match.") + verify_to_schema(UserSchema, params) - if password != password_confirm: - return { "success": 0, "message": "Passwords do not match." } - if len(password) > 128: - return { "success": 0, "message": "Password is too long." } - if len(password) == 0: - return { "success": 0, "message": "Password is too short." } - if len(username) > 64: - return { "success": 0, "message": "Username is too long." } - if username_exists: - return { "success": 0, "message": "Username is already taken." } - if email_exists: - return { "success": 0, "message": "Email has already been used." } + user = Users(name, username, email, password, utype) + with app.app_context(): + db.session.add(user) + db.session.commit() - add_user(name, username, email, password) - logger.log("registrations", logger.INFO, "%s registered with %s" % (name.encode("utf-8"), email.encode("utf-8"))) + logger.log("registrations", logger.INFO, "%s registered with %s" % (name.encode("utf-8"), email.encode("utf-8"))) + login_user(username, password) - return { "success": 1, "message": "Success!" } + return { "success": 1, "message": "Success!" } -@blueprint.route("/logout", methods=["POST"]) +@blueprint.route("/logout", methods=["GET", "POST"]) @api_wrapper def user_logout(): - session.clear() + sid = session["sid"] + username = session["username"] + LoginTokens.query.filter_by(sid=sid, username=username).delete() + session.clear() @blueprint.route("/login", methods=["POST"]) @api_wrapper def user_login(): - email = request.form["email"] - password = request.form["password"] - user = Users.query.filter_by(email=email).first() - if user is None: - return { "success": 0, "message": "Invalid credentials." } + params = utils.flat_multi(request.form) - if utils.check_password(user.password, password): - session["username"] = user.username - if user.admin: - session["admin"] = True - session["logged_in"] = True - return { "success": 1, "message": "Success!" } - else: - return { "success": 0, "message": "Invalid credentials." } + username = params.get("username") + password = params.get("password") + + result = login_user(username, password) + if result != True: + raise WebException("Please check if your username/password are correct.") + + return { "success": 1, "message": "Success!" } @blueprint.route("/status", methods=["POST"]) @api_wrapper def user_status(): - status = { - "logged_in": is_logged_in(), - "admin": is_admin(), - "username": session["username"] if is_logged_in() else "", - } - return status + logged_in = is_logged_in() + result = { + "success": 1, + "logged_in": logged_in, + "admin": is_admin(), + "username": session["username"] if logged_in else "", + } + return result + +################## +# USER FUNCTIONS # +################## + +__check_email_format = lambda email: re.match(".+@.+\..{2,}", email) is not None +__check_ascii = lambda s: all(ord(c) < 128 for c in s) +__check_username = lambda username: get_user(username_lower=username.lower()).first() is None +__check_email = lambda email: get_user(email=email.lower()).first() is None + +UserSchema = Schema({ + Required("email"): check( + ([str, Length(min=4, max=128)], "Your email should be between 4 and 128 characters long."), + ([__check_email], "Someone already registered this email."), + ([__check_email_format], "Please enter a legit email.") + ), + Required("name"): check( + ([str, Length(min=4, max=128)], "Your name should be between 4 and 128 characters long.") + ), + Required("username"): check( + ([str, Length(min=4, max=32)], "Your username should be between 4 and 32 characters long."), + ([__check_ascii], "Please only use ASCII characters in your username."), + ([__check_username], "This username is taken, did you forget your password?") + ), + Required("password"): check( + ([str, Length(min=4, max=64)], "Your password should be between 4 and 64 characters long."), + ([__check_ascii], "Please only use ASCII characters in your password."), + ), + Required("type"): check( + ([str, lambda x: x.isdigit()], "Please use the online form.") + ), + "notify": str +}, extra=True) + +def get_user(username=None, username_lower=None, email=None, uid=None): + with app.app_context(): + match = {} + if username != None: + match.update({ "username": username }) + elif username_lower != None: + match.update({ "username_lower": username_lower }) + elif uid != None: + match.update({ "uid": uid }) + elif email != None: + match.update({ "email": email }) + # elif api.auth.is_logged_in(): + # match.update({ "uid": api.auth.get_uid() }) + result = Users.query.filter_by(**match) + return result + +def login_user(username, password): + user = get_user(username_lower=username.lower()).first() + if user is None: return False + correct = utils.check_password(user.password, password) + if not correct: return False + + useragent = request.headers.get("User-Agent") + ip = request.remote_addr + token = LoginTokens(user.uid, user.username, ua=useragent, ip=ip) + with app.app_context(): + db.session.add(token) + db.session.commit() + + session["sid"] = token.sid + session["username"] = token.username + session["admin"] = user.utype == 0 + + return True def is_logged_in(): - return "logged_in" in session and session["logged_in"] + sid = session["sid"] + username = session["username"] + token = LoginTokens.query.filter_by(sid=sid).first() + if token is None: return False + + useragent = request.headers.get("User-Agent") + ip = request.remote_addr + + if token.username != username: return False + if token.ua != useragent: return False + return True def is_admin(): - return "admin" in session and session["admin"] - -def add_user(name, username, email, password): - user = Users(name, username, email, password) - db.session.add(user) - db.session.commit() + return is_logged_in() and "admin" in session and session["admin"] def validate_captcha(form): - if "captcha_response" not in form: - return False - captcha_response = form["captcha_response"] - data = {"secret": "6Lc4xhMTAAAAACFaG2NyuKoMdZQtSa_1LI76BCEu", "response": captcha_response} - response = requests.post("https://www.google.com/recaptcha/api/siteverify", data=data) - return response.json()["success"] + if "captcha_response" not in form: + return False + captcha_response = form["captcha_response"] + data = {"secret": "6Lc4xhMTAAAAACFaG2NyuKoMdZQtSa_1LI76BCEu", "response": captcha_response} + response = requests.post("https://www.google.com/recaptcha/api/siteverify", data=data) + return response.json()["success"] \ No newline at end of file diff --git a/server/api/utils.py b/server/api/utils.py index 4b2de57..a8802b6 100644 --- a/server/api/utils.py +++ b/server/api/utils.py @@ -3,6 +3,7 @@ import json import random import string import traceback +import unicodedata from functools import wraps from werkzeug.security import generate_password_hash, check_password_hash @@ -13,8 +14,8 @@ def hash_password(s): def check_password(hashed_password, try_password): return check_password_hash(hashed_password, try_password) -def generate_string(length): - return "".join([random.choice(string.letters + string.digits) for x in range(length)]) +def generate_string(length=32, alpha=string.hexdigits): + return "".join([random.choice(alpha) for x in range(length)]) def unix_time_millis(dt): epoch = datetime.datetime.utcfromtimestamp(0) @@ -22,3 +23,10 @@ def unix_time_millis(dt): def get_time_since_epoch(): return unix_time_millis(datetime.datetime.now()) + +def flat_multi(multidict): + flat = {} + for key, values in multidict.items(): + value = values[0] if type(values) == list and len(values) == 1 else values + flat[key] = unicodedata.normalize("NFKD", value).encode("ascii", "ignore") + return flat \ No newline at end of file diff --git a/web/css/easyctf.css b/web/css/easyctf.css new file mode 100644 index 0000000..4690001 --- /dev/null +++ b/web/css/easyctf.css @@ -0,0 +1,13 @@ +@font-face { + font-family: "Proxima Nova"; + src: url("/fonts/ProximaNova.woff2"); +} +@font-face { + font-family: "Proxima Nova"; + src: url("/fonts/ProximaNovaBold.woff2"); + font-weight: bold; +} + +* { + font-family: "Proxima Nova"; +} \ No newline at end of file diff --git a/web/fonts/ProximaNova.woff2 b/web/fonts/ProximaNova.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..a0ccdbca6d3f81b3dca7e01aeb3df0df5c5fe54f GIT binary patch literal 17997 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
  • Wr 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 literal 0 HcmV?d00001 diff --git a/web/index.html b/web/index.html index eb5ccf8..47c0305 100644 --- a/web/index.html +++ b/web/index.html @@ -8,15 +8,16 @@ - - + + + - -