diff --git a/NHO8HV5OO57PVC3A.png b/NHO8HV5OO57PVC3A.png new file mode 100644 index 0000000..bdf6b08 Binary files /dev/null and b/NHO8HV5OO57PVC3A.png differ diff --git a/_2fa.tpl b/_2fa.tpl index 7cbd698..dde5a30 100644 --- a/_2fa.tpl +++ b/_2fa.tpl @@ -16,11 +16,12 @@

2FA

% if data['secureAuth'] == True: - +
+ +
- - +
@@ -30,11 +31,10 @@ % else: - +
- - +
diff --git a/app.py b/app.py index 5f936f1..f93756c 100644 --- a/app.py +++ b/app.py @@ -27,9 +27,10 @@ from ldap3 import Server, Connection, ALL from ldap3 import SIMPLE, SUBTREE, MODIFY_REPLACE, MODIFY_ADD, MODIFY_DELETE, ALL_ATTRIBUTES from ldap3.core.exceptions import LDAPBindError, LDAPConstraintViolationResult, \ LDAPInvalidCredentialsResult, LDAPUserNameIsMandatoryError, \ - LDAPSocketOpenError, LDAPExceptionError, LDAPAttributeOrValueExistsResult + LDAPSocketOpenError, LDAPExceptionError, LDAPAttributeOrValueExistsResult, \ + LDAPNoSuchAttributeResult import logging -from os import getenv, environ, path +from os import getenv, environ, path, remove from libs import flist, slist from libs.localization import * from libs.helper import tools @@ -118,11 +119,22 @@ def get_index(): @get('/_2fa') def get_index(): + #newSession().get() try: + reload(newSession().get()['username'], None, None) + #add_auth_attribute_step1(newSession().get()['username'], None, None) return _2fa_tpl(data=newSession().get(), str=i18n.str) except Exception as e: return index_tpl(str=i18n.str) +@get('/enable_2fa') +@get('/disable_2fa') +def get_index(): + try: + return user_tpl(data=newSession().get(), str=i18n.str) + except Exception as e: + return index_tpl(str=i18n.str) + @post('/user') def post_user(): form = request.forms.getunicode @@ -276,33 +288,47 @@ def post_edit_email(): @post('/enable_2fa') def post_enable_2fa(): - try: - username=newSession().get()['username'] - add_auth_attribute_step1(username, tools.generate_secret(), action='enable') - ''' - add attribute authCode - set session data - ''' - except Error as e: - LOG.warning("akatsa") - return error(str(e)) - return _2fa_tpl(data=newSession().get(), str=i18n.str) + def error(msg): + return _2fa_tpl(alerts=[('error', msg, 'fadeOut')], data=newSession().get(), str=i18n.str) + + try: + if(not newSession().get()['secureAuth']): + try: + username=newSession().get()['username'] + add_auth_attribute_step1(username, tools.generate_secret(), action='enable') + except Error as e: + #add_auth_attribute_step1(newSession().get()['username'], None, None) + reload(newSession().get()['username'], None, None) + LOG.warning(e) + return error('2 urratseko autentifikazioa birgaitua izan da.') + except Error as e: + LOG.warning(e) + return index_tpl(alerts=[('error', e, 'fadeOut')], str=i18n.str) + + return _2fa_tpl(alerts=[('success', 'Bikain, 2 urratseko autentifikazioa gaitu da.', 'fadeOut')], data=newSession().get(), str=i18n.str) @post('/disable_2fa') def post_disable_2fa(): - try: - username=newSession().get()['username'] - add_auth_attribute_step1(username, tools.generate_secret(), action='disable') - ''' - add attribute authCode - set session data - ''' - except Error as e: - LOG.warning("akatsa") - return error(str(e)) - return _2fa_tpl(data=newSession().get(), str=i18n.str) + def error(msg): + return _2fa_tpl(alerts=[('error', msg, 'fadeOut')], data=newSession().get(), str=i18n.str) + + try: + if(newSession().get()['secureAuth']): + try: + username=newSession().get()['username'] + add_auth_attribute_step1(username, None, action='disable') + except Error as e: + #add_auth_attribute_step1(newSession().get()['username'], None, None) + reload(newSession().get()['username'], None, None) + LOG.warning(e) + return error(str(e)) + except Error as e: + LOG.warning(e) + return index_tpl(alerts=[('error', e, 'fadeOut')], str=i18n.str) + + return _2fa_tpl(alerts=[('error', '2 urratseko autentifikazioa desgaitua izan da.', 'fadeOut')], data=newSession().get(), str=i18n.str) @post('/change_pwd') def post_change_pwd(): @@ -366,6 +392,10 @@ def serve_static(filename): def font(filepath): return static_file(filepath, root="static/fonts") +@get("/static/tmp/") +def font(filepath): + return static_file(filepath, root="static/tmp") + def index_tpl(**kwargs): return template('index', **kwargs) @@ -728,6 +758,10 @@ def add_auth_attribute_step2(conf, *args): LOG.error('{}: {!s}'.format(e.__class__.__name__, e)) raise Error(i18n.msg[23]) + except LDAPNoSuchAttributeResult as e: + LOG.error('{}: {!s}'.format(e.__class__.__name__, e)) + raise Error('Dagoeneko desgaiturik zeneukan 2 urratseko autentifikazioa.') + except LDAPExceptionError as e: LOG.error('{}: {!s}'.format(e.__class__.__name__, e)) raise Error(i18n.msg[23]) @@ -746,8 +780,18 @@ def add_auth_attribute_step3(conf, username, code, action): elif(action == 'disable'): c.modify(user_dn,{'authCode': [(MODIFY_DELETE, [])]}) c.modify(user_dn,{'secureAuth': [MODIFY_REPLACE, [False]]}) + #remove file + try: + remove('static/tmp/'+newSession().get()['authCode']+'.png') + except OSError as e: + LOG.warning(str(e)) + #raise Error(e) + pass + newSession().set(get_user_data(user_dn, c)) +reload=add_auth_attribute_step1 + #CHANGE PASSWORD def change_passwords(username, old_pass, new_pass): changed = [] diff --git a/libs/helper.py b/libs/helper.py index 690edf3..d3220c6 100644 --- a/libs/helper.py +++ b/libs/helper.py @@ -4,6 +4,7 @@ import sqlite3 import re from onetimepass import valid_totp from secrets import choice +import segno class Tools(): @@ -44,12 +45,14 @@ class Tools(): def pwd_validation(self, e): regex = r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!#%*?&]{8,18}$' return(bool(re.fullmatch(regex, e))) - + + # 2FA def generate_secret(self): # Function to return a random string with length 16. secret = '' while len(secret) < 16: secret += choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567') + qrcode = segno.make(secret, micro=False) + qrcode.save('static/tmp/'+secret+'.png', scale=10) return secret - tools = Tools() diff --git a/static/style.css b/static/style.css index 1dd02e8..cb15d75 100644 --- a/static/style.css +++ b/static/style.css @@ -194,6 +194,13 @@ button.red:hover{ animation-name: fadeOut; } +/**/ +.qr-code { + margin: 0 auto; + width: max-content; + text-align: center; +} + /**/ .grid-container { display: grid;