def admin_create_team(): name = request.form.get('name', None) password = request.form.get('password', None) email = request.form.get('email', None) website = request.form.get('website', None) affiliation = request.form.get('affiliation', None) country = request.form.get('country', None) admin_user = True if request.form.get('admin', None) == 'on' else False verified = True if request.form.get('verified', None) == 'on' else False hidden = True if request.form.get('hidden', None) == 'on' else False errors = [] if not name: errors.append('The team requires a name') elif Teams.query.filter(Teams.name == name).first(): errors.append('That name is taken') if utils.check_email_format(name) is True: errors.append('Team name cannot be an email address') if not email: errors.append('The team requires an email') elif Teams.query.filter(Teams.email == email).first(): errors.append('That email is taken') if email: valid_email = utils.check_email_format(email) if not valid_email: errors.append("That email address is invalid") if not password: errors.append('The team requires a password') if website and (website.startswith('http://') or website.startswith('https://')) is False: errors.append('Websites must start with http:// or https://') if errors: db.session.close() return jsonify({'data': errors}) team = Teams(name, email, password) team.website = website team.affiliation = affiliation team.country = country team.admin = admin_user team.verified = verified team.banned = hidden db.session.add(team) db.session.commit() db.session.close() return jsonify({'data': ['success']})
def login(): logger = logging.getLogger('logins') if request.method == 'POST': errors = [] name = request.form['name'] # Check if the user submitted an email address or a team name if utils.check_email_format(name) is True: team = Teams.query.filter_by(email=name).first() elif utils.check_sno_format(name) is True: team = Teams.query.filter_by(sno=name).first() else: team = Teams.query.filter_by(name=name).first() if team: if team and bcrypt_sha256.verify(request.form['password'], team.password): try: session.regenerate() # NO SESSION FIXATION FOR YOU except: pass # TODO: Some session objects don't implement regenerate :( session['username'] = team.name session['id'] = team.id session['admin'] = team.admin session['nonce'] = utils.sha512(os.urandom(10)) db.session.close() logger.warn("[{date}] {ip} - {username} logged in".format( date=time.strftime("%m/%d/%Y %X"), ip=utils.get_ip(), username=session['username'].encode('utf-8'))) if request.args.get('next') and utils.is_safe_url( request.args.get('next')): return redirect(request.args.get('next')) return redirect(url_for('challenges.challenges_view')) else: # This user exists but the password is wrong logger.warn( "[{date}] {ip} - submitted invalid password for {username}" .format(date=time.strftime("%m/%d/%Y %X"), ip=utils.get_ip(), username=team.name.encode('utf-8'))) errors.append("Your username or password is incorrect") db.session.close() return render_template('login.html', errors=errors) else: # This user just doesn't exist logger.warn( "[{date}] {ip} - submitted invalid account information".format( date=time.strftime("%m/%d/%Y %X"), ip=utils.get_ip())) errors.append("Your username or password is incorrect") db.session.close() return render_template('login.html', errors=errors) else: db.session.close() return render_template('login.html')
def test_check_email_format(): """Test that the check_email_format() works properly""" assert check_email_format('*****@*****.**') is True assert check_email_format('*****@*****.**') is True assert check_email_format('*****@*****.**') is True assert check_email_format('*****@*****.**') is True assert check_email_format('user.period1234@b') is False assert check_email_format('no.ampersand') is False assert check_email_format('user@') is False assert check_email_format('@ctfd.io') is False assert check_email_format('user.io@ctfd') is False assert check_email_format('user\@ctfd') is False for invalid_email in ['*****@*****.**', '*****@*****.**', '*****@*****.**']: try: assert check_email_format(invalid_email) is False except AssertionError: print(invalid_email, 'did not pass validation')
def register(): logger = logging.getLogger('regs') if not utils.can_register(): return redirect(url_for('auth.login')) if request.method == 'POST': errors = [] name = request.form['name'] email = request.form['email'] password = request.form['password'] name_len = len(name) == 0 names = Teams.query.add_columns( 'name', 'id').filter_by(name=name).first() emails = Teams.query.add_columns( 'email', 'id').filter_by(email=email).first() pass_short = len(password) == 0 pass_long = len(password) > 128 valid_email = utils.check_email_format(request.form['email']) team_name_email_check = utils.check_email_format(name) if not valid_email: errors.append("Please enter a valid email address") if names: errors.append('That team name is already taken') if team_name_email_check is True: errors.append('Your team name cannot be an email address') if emails: errors.append('That email has already been used') if pass_short: errors.append('Pick a longer password') if pass_long: errors.append('Pick a shorter password') if name_len: errors.append('Pick a longer team name') if len(errors) > 0: return render_template('register.html', errors=errors, name=request.form['name'], email=request.form['email'], password=request.form['password']) else: with app.app_context(): team = Teams(name, email.lower(), password) db.session.add(team) db.session.commit() db.session.flush() session['username'] = team.name session['id'] = team.id session['admin'] = team.admin session['nonce'] = utils.sha512(os.urandom(10)) # Confirming users is enabled and we can send email. if utils.can_send_mail() and utils.get_config('verify_emails'): logger = logging.getLogger('regs') logger.warn("[{date}] {ip} - {username} registered (UNCONFIRMED) with {email}".format( date=time.strftime("%m/%d/%Y %X"), ip=utils.get_ip(), username=request.form['name'].encode('utf-8'), email=request.form['email'].encode('utf-8') )) utils.verify_email(team.email) db.session.close() return redirect(url_for('auth.confirm_user')) else: # Don't care about confirming users if utils.can_send_mail(): # We want to notify the user that they have registered. utils.sendmail(request.form['email'], "You've successfully registered for {}".format( utils.get_config('ctf_name'))) logger.warn("[{date}] {ip} - {username} registered with {email}".format( date=time.strftime("%m/%d/%Y %X"), ip=utils.get_ip(), username=request.form['name'].encode('utf-8'), email=request.form['email'].encode('utf-8') )) db.session.close() return redirect(url_for('challenges.challenges_view')) else: return render_template('register.html')
def admin_team(teamid): user = Teams.query.filter_by(id=teamid).first_or_404() if request.method == 'GET': solves = Solves.query.filter_by(teamid=teamid).all() solve_ids = [s.chalid for s in solves] missing = Challenges.query.filter(not_(Challenges.id.in_(solve_ids))).all() last_seen = db.func.max(Tracking.date).label('last_seen') addrs = db.session.query(Tracking.ip, last_seen) \ .filter_by(team=teamid) \ .group_by(Tracking.ip) \ .order_by(last_seen.desc()).all() wrong_keys = WrongKeys.query.filter_by(teamid=teamid).order_by(WrongKeys.date.asc()).all() awards = Awards.query.filter_by(teamid=teamid).order_by(Awards.date.asc()).all() score = user.score(admin=True) place = user.place(admin=True) return render_template('admin/team.html', solves=solves, team=user, addrs=addrs, score=score, missing=missing, place=place, wrong_keys=wrong_keys, awards=awards) elif request.method == 'POST': name = request.form.get('name', None) password = request.form.get('password', None) email = request.form.get('email', None) website = request.form.get('website', None) affiliation = request.form.get('affiliation', None) country = request.form.get('country', None) admin_user = True if request.form.get('admin', None) == 'on' else False verified = True if request.form.get('verified', None) == 'on' else False hidden = True if request.form.get('hidden', None) == 'on' else False errors = [] # if email: # valid_email = utils.check_email_format(email) # if not valid_email: # errors.append("That email address is invalid") if email: valid_email = utils.check_id_format(email) if not valid_email: errors.append("That student id is invalid") name_used = Teams.query.filter(Teams.name == name).first() if name_used and int(name_used.id) != int(teamid): errors.append('That name is taken') if utils.check_email_format(name) is True: errors.append('Team name cannot be an email address') email_used = Teams.query.filter(Teams.email == email).first() if email_used and int(email_used.id) != int(teamid): errors.append('That student id is taken') if website and (website.startswith('http://') or website.startswith('https://')) is False: errors.append('Websites must start with http:// or https://') if errors: db.session.close() return jsonify({'data': errors}) else: user.name = name if email: user.email = email if password: user.password = bcrypt_sha256.encrypt(password) user.website = website user.affiliation = affiliation user.country = country user.admin = admin_user user.verified = verified user.banned = hidden db.session.commit() db.session.close() return jsonify({'data': ['success']})
def profile(): if utils.authed(): if request.method == "POST": errors = [] name = request.form.get('name').strip() email = request.form.get('email').strip() website = request.form.get('website').strip() affiliation = request.form.get('affiliation').strip() country = request.form.get('country').strip() user = Teams.query.filter_by(id=session['id']).first() if not utils.get_config('prevent_name_change'): names = Teams.query.filter_by(name=name).first() name_len = len(request.form['name']) == 0 emails = Teams.query.filter_by(email=email).first() valid_email = utils.check_email_format(email) if utils.check_email_format(name) is True: errors.append('Team name cannot be an email address') if ('password' in request.form.keys() and not len(request.form['password']) == 0) and \ (not bcrypt_sha256.verify(request.form.get('confirm').strip(), user.password)): errors.append("Your old password doesn't match what we have.") if not valid_email: errors.append("That email doesn't look right") if not utils.get_config( 'prevent_name_change' ) and names and name != session['username']: errors.append('That team name is already taken') if emails and emails.id != session['id']: errors.append('That email has already been used') if not utils.get_config('prevent_name_change') and name_len: errors.append('Pick a longer team name') if website.strip() and not utils.validate_url(website): errors.append("That doesn't look like a valid URL") if len(errors) > 0: return render_template('profile.html', name=name, email=email, website=website, affiliation=affiliation, country=country, errors=errors) else: team = Teams.query.filter_by(id=session['id']).first() if team.name != name: if not utils.get_config('prevent_name_change'): team.name = name session['username'] = team.name if team.email != email.lower(): team.email = email.lower() if utils.get_config('verify_emails'): team.verified = False if 'password' in request.form.keys() and not len( request.form['password']) == 0: team.password = bcrypt_sha256.encrypt( request.form.get('password')) team.website = website team.affiliation = affiliation team.country = country db.session.commit() db.session.close() return redirect(url_for('views.profile')) else: user = Teams.query.filter_by(id=session['id']).first() name = user.name email = user.email website = user.website affiliation = user.affiliation country = user.country prevent_name_change = utils.get_config('prevent_name_change') confirm_email = utils.get_config( 'verify_emails') and not user.verified return render_template('profile.html', name=name, email=email, website=website, affiliation=affiliation, country=country, prevent_name_change=prevent_name_change, confirm_email=confirm_email) else: return redirect(url_for('auth.login'))
def profile(): if utils.authed(): if request.method == "POST": errors = [] name = request.form.get('name').strip() email = request.form.get('email').strip() website = request.form.get('website').strip() affiliation = request.form.get('affiliation').strip() country = request.form.get('country').strip() member = request.form.get('member').strip() number = request.form.get('number').strip() print member,number user = Teams.query.filter_by(id=session['id']).first() if not utils.get_config('prevent_name_change'): names = Teams.query.filter_by(name=name).first() name_len = len(request.form['name']) == 0 emails = Teams.query.filter_by(email=email).first() valid_email = utils.check_email_format(email) if utils.check_email_format(name) is True: errors.append(get_tip('EMAIL_NOT_TEAM')) if ('password' in request.form.keys() and not len(request.form['password']) == 0) and \ (not bcrypt_sha256.verify(request.form.get('confirm').strip(), user.password)): errors.append(get_tip('PASS_NOT_MATCH')) if not valid_email: errors.append(get_tip('INVIDE_EMAIL')) if not utils.get_config('prevent_name_change') and names and name != session['username']: errors.append(get_tip('TEAM_EXIST')) if emails and emails.id != session['id']: errors.append(get_tip('EMAIL_HAVE_USE')) if not utils.get_config('prevent_name_change') and name_len: errors.append(get_tip('TOO_SHORT_TEAM')) if website.strip() and not utils.validate_url(website): errors.append(get_tip('INVIDE_LINK_FORMAT')) if len(errors) > 0: return render_template('profile.html', name=name, email=email, website=website, affiliation=affiliation, country=country,member=member, number=number, errors=errors) else: team = Teams.query.filter_by(id=session['id']).first() if team.name != name: if not utils.get_config('prevent_name_change'): team.name = name session['username'] = team.name if team.email != email.lower(): team.email = email.lower() if utils.get_config('verify_emails'): team.verified = False if 'password' in request.form.keys() and not len(request.form['password']) == 0: team.password = bcrypt_sha256.encrypt(request.form.get('password')) team.website = website team.affiliation = affiliation '''member info need lock ''' if not utils.get_config('prevent_name_change'): team.country = country team.member = member team.number = number db.session.commit() db.session.close() return redirect(url_for('views.profile')) else: user = Teams.query.filter_by(id=session['id']).first() name = user.name email = user.email website = user.website affiliation = user.affiliation country = user.country member = user.member number = user.number prevent_name_change = utils.get_config('prevent_name_change') confirm_email = utils.get_config('verify_emails') and not user.verified return render_template('profile.html', name=name, email=email, website=website, affiliation=affiliation, country=country,member=member,number=number, prevent_name_change=prevent_name_change, confirm_email=confirm_email) else: return redirect(url_for('auth.login'))
def admin_create_team_custom(): name = request.form.get('name', None) password = request.form.get('password', None) email = request.form.get('email', None) color = request.form.get('color', None) image = request.form.get('image', None) school = request.form.get('school', None) if not color in teamColors: color = "RED" if not image in teamImages: image = "HULK" admin_user = True if request.form.get('admin', None) == 'on' else False verified = True if request.form.get('verified', None) == 'on' else False hidden = True if request.form.get('hidden', None) == 'on' else False smart_color = SmartCityTeam.query.add_columns('color').filter_by( color=color).first() smart_image = SmartCityTeam.query.add_columns('image').filter_by( image=image).first() errors = [] if not name: errors.append('The team requires a name') elif Teams.query.filter(Teams.name == name).first(): errors.append('That name is taken') if utils.check_email_format(name) is True: errors.append('Team name cannot be an email address') if not email: errors.append('The team requires an email') elif Teams.query.filter(Teams.email == email).first(): errors.append('That email is taken') if email: valid_email = utils.check_email_format(email) if not valid_email: errors.append("That email address is invalid") if not password: errors.append('The team requires a password') if smart_color: errors.append('Color was taken. Available Colors: ' + getAvailableColors()) if smart_image: errors.append('Imagge already taken') if errors: db.session.close() return jsonify({'data': errors}) team = Teams(name, email, password) #team.website = website #team.affiliation = affiliation #team.country = country team.admin = admin_user team.verified = verified team.hidden = hidden db.session.add(team) db.session.commit() smart_team = SmartCityTeam(team.id, name, color, image, school) db.session.add(smart_team) db.session.commit() db.session.close() return jsonify({'data': ['success']})
def profile(): if utils.authed(): if request.method == "POST": errors = [] name = request.form.get('name').strip() email = request.form.get('email').strip() affiliation = request.form.get('grade').strip() website = request.form.get('major').strip() country = request.form.get('college').strip() user = Teams.query.filter_by(id=session['id']).first() if not utils.get_config('prevent_name_change'): names = Teams.query.filter_by(name=name).first() name_len = len(request.form['name']) == 0 emails = Teams.query.filter_by(email=email).first() valid_email = utils.check_email_format(email) if utils.check_email_format(name) is True: errors.append('用户名不能和邮箱一样') if ('password' in request.form.keys() and not len(request.form['password']) == 0) and \ (not bcrypt_sha256.verify(request.form.get('confirm').strip(), user.password)): errors.append("旧密码错误") if not valid_email: errors.append("邮箱格式不对") if not utils.get_config( 'prevent_name_change' ) and names and name != session['username']: errors.append('用户名已被其他用户使用') if emails and emails.id != session['id']: errors.append('邮箱已被其他用户使用') if not utils.get_config('prevent_name_change') and name_len: errors.append('用户名长度不够') #if website.strip() and not utils.validate_url(website): #errors.append("That doesn't look like a valid URL") if len(errors) > 0: return render_template('profile.html', name=name, email=email, website=website, affiliation=affiliation, country=country, errors=errors) else: team = Teams.query.filter_by(id=session['id']).first() if team.name != name: if not utils.get_config('prevent_name_change'): team.name = name session['username'] = team.name if team.email != email.lower(): team.email = email.lower() if utils.get_config('verify_emails'): team.verified = False if 'password' in request.form.keys() and not len( request.form['password']) == 0: team.password = bcrypt_sha256.encrypt( request.form.get('password')) team.website = website team.affiliation = affiliation team.country = country db.session.commit() db.session.close() return redirect(url_for('views.profile')) else: user = Teams.query.filter_by(id=session['id']).first() name = user.name email = user.email website = user.website affiliation = user.affiliation country = user.country prevent_name_change = utils.get_config('prevent_name_change') confirm_email = utils.get_config( 'verify_emails') and not user.verified return render_template('profile.html', name=name, email=email, major=website, grade=affiliation, college=country, prevent_name_change=prevent_name_change, confirm_email=confirm_email) else: return redirect(url_for('auth.login'))
def login(): logger = logging.getLogger('logins') if request.method == 'POST': errors = [] name = request.form['name'].strip() password = request.form['password'] # Check if email or password is empty if not name or not password: errors.append("Please enter your email and password") db.session.close() return render_template('login.html', errors=errors) # Check if the user submitted a valid email address if utils.check_email_format(name) is False: errors.append("Your email is not in a valid format") db.session.close() return render_template('login.html', errors=errors) # Send POST request to NCL SIO authentication API base64creds = base64.b64encode(name + ':' + password) headers = {'Authorization': 'Basic ' + base64creds} sio_url = utils.ncl_sio_url() try: r = requests.post(sio_url + '/authentications', headers=headers, timeout=30) except requests.exceptions.RequestException as e: logger.warn("[{date}] {ip} - error connecting to SIO authentication service: {exception}".format( date=time.strftime("%m/%d/%Y %X"), ip=utils.get_ip(), exception=e )) errors.append("There is a problem with your login request. Please contact the website administrator") db.session.close() return render_template('login.html', errors=errors) if r.status_code == 200: # Successful login # Check if this user has permission to login (i.e. is in this CTF NCL team) ncl_team_name = utils.ncl_team_name() is_user_in_ncl_team = False user_id = r.json()['id'] # Send GET request to NCL SIO teams API try: teams_r = requests.get(sio_url + '/teams?name=' + ncl_team_name, timeout=30) except requests.exceptions.RequestException as teams_re: logger.warn("[{date}] {ip} - error connecting to SIO teams service: {exception}".format( date=time.strftime("%m/%d/%Y %X"), ip=utils.get_ip(), exception=teams_re )) errors.append("There is a problem with connecting to login service. Please contact the website administrator") db.session.close() return render_template('login.html', errors=errors) if teams_r.status_code == 200: # teams GET success team_members = teams_r.json()['members'] for member in team_members: if member['userId'] == user_id: is_user_in_ncl_team = True break else: # teams GET failed logger.warn("[{date}] {ip} - invalid response status code: {status}".format( date=time.strftime("%m/%d/%Y %X"), ip=utils.get_ip(), status=str(teams_r.status_code) )) errors.append("Unknown response from login service. Please contact the website administrator") db.session.close() return render_template('login.html', errors=errors) if not is_user_in_ncl_team: # User is not part of NCL team, deny login! logger.warn("[{date}] {ip} - not in this CTF NCL team for {username}".format( date=time.strftime("%m/%d/%Y %X"), ip=utils.get_ip(), username=name.encode('utf-8') )) errors.append("You do not have permissions to login to this site") db.session.close() return render_template('login.html', errors=errors) # User is now allowed to login # Try to get info from DB team = Teams.query.filter_by(email=name).first() # Add to DB if it does not exist if not team: team = Teams(name.lower(), name.lower(), "unused_password") db.session.add(team) db.session.commit() db.session.flush() # Get info from DB session['username'] = team.name session['id'] = team.id session['admin'] = team.admin session['nonce'] = utils.sha512(os.urandom(10)) db.session.close() logger.warn("[{date}] {ip} - {username} logged in".format( date=time.strftime("%m/%d/%Y %X"), ip=utils.get_ip(), username=session['username'].encode('utf-8') )) if request.args.get('next') and utils.is_safe_url(request.args.get('next')): return redirect(request.args.get('next')) return redirect(url_for('challenges.challenges_view')) elif r.status_code == 404: # This user does not exist logger.warn("[{date}] {ip} - submitted invalid user email".format( date=time.strftime("%m/%d/%Y %X"), ip=utils.get_ip() )) errors.append("Your email or password is incorrect") db.session.close() return render_template('login.html', errors=errors) elif r.status_code == 500: # This user exists but the password is wrong logger.warn("[{date}] {ip} - submitted invalid password for {username}".format( date=time.strftime("%m/%d/%Y %X"), ip=utils.get_ip(), username=name.encode('utf-8') )) errors.append("Your email or password is incorrect") db.session.close() return render_template('login.html', errors=errors) else: # Unknown response status code logger.warn("[{date}] {ip} - unknown response status code: {status}".format( date=time.strftime("%m/%d/%Y %X"), ip=utils.get_ip(), status=str(r.status_code) )) errors.append("Unknown login error. Please contact the website administrator") db.session.close() return render_template('login.html', errors=errors) else: db.session.close() return render_template('login.html')
def register(): logger = logging.getLogger('regs') if not utils.can_register(): return redirect(url_for('auth.login')) if request.method == 'POST': errors = [] name = request.form['name'] email = request.form['email'] password = request.form['password'] name_len = len(name) == 0 names = Teams.query.add_columns('name', 'id').filter_by(name=name).first() emails = Teams.query.add_columns('email', 'id').filter_by(email=email).first() pass_short = len(password) == 0 pass_long = len(password) > 128 valid_email = utils.check_email_format(request.form['email']) team_name_email_check = utils.check_email_format(name) if not valid_email: errors.append(get_tip('INVIDE_EMAIL')) if names: errors.append(get_tip('TEAM_EXIST')) if team_name_email_check is True: errors.append(get_tip('EMAIL_NOT_TEAM')) if emails: errors.append(get_tip('EMAIL_HAVE_USE')) if pass_short: errors.append(get_tip('TOO_SHORT_PASS')) if pass_long: errors.append(get_tip('TOO_LONG_PASS')) if name_len: errors.append(get_tip('TOO_SHORT_TEAM')) if len(errors) > 0: return render_template('register.html', errors=errors, name=request.form['name'], email=request.form['email'], password=request.form['password']) else: with app.app_context(): token = os.urandom(16).encode('hex') team = Teams(name, email.lower(), password, token.lower()) db.session.add(team) db.session.commit() db.session.flush() session['username'] = team.name session['id'] = team.id session['admin'] = team.admin session['nonce'] = utils.sha512(os.urandom(10)) if utils.can_send_mail() and utils.get_config( 'verify_emails' ): # Confirming users is enabled and we can send email. logger = logging.getLogger('regs') logger.warn( get_tip('USER_REG_WARN').format( date=time.strftime("%m/%d/%Y %X"), ip=utils.get_ip(), username=request.form['name'].encode('utf-8'), email=request.form['email'].encode('utf-8'))) utils.verify_email(team.email) db.session.close() return redirect(url_for('auth.confirm_user')) else: # Don't care about confirming users if utils.can_send_mail( ): # We want to notify the user that they have registered. utils.sendmail( request.form['email'], get_tip('USER_REG_SUCCESS').format( utils.get_config('ctf_name'))) logger.warn( get_tip('USER_REGISTRED').format( date=time.strftime("%m/%d/%Y %X"), ip=utils.get_ip(), username=request.form['name'].encode('utf-8'), email=request.form['email'].encode('utf-8'))) db.session.close() return redirect(url_for('challenges.challenges_view')) else: return render_template('register.html')