Development
This commit is contained in:
parent
db837af548
commit
64f83d683e
8 changed files with 237 additions and 26 deletions
|
|
@ -18,14 +18,14 @@ bp = Blueprint(_PAGE, __name__)
|
|||
USER_TYPE_CAPTIVE = 0
|
||||
USER_TYPE_SUPPLICANT = 1
|
||||
|
||||
HASH_CLEARTEXT = 0
|
||||
HASH_BCRYPT = 2
|
||||
DIGEST_CYPHERTEXT_FERNET = 0
|
||||
DIGEST_HASH_BCRYPT = 2
|
||||
|
||||
VALID_USER_TYPES = {USER_TYPE_CAPTIVE, USER_TYPE_SUPPLICANT}
|
||||
|
||||
HASH_FOR_USER_TYPE = {
|
||||
USER_TYPE_CAPTIVE: HASH_BCRYPT,
|
||||
USER_TYPE_SUPPLICANT: HASH_CLEARTEXT,
|
||||
USER_TYPE_CAPTIVE: DIGEST_HASH_BCRYPT,
|
||||
USER_TYPE_SUPPLICANT: DIGEST_CYPHERTEXT_FERNET,
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ def _db_conn():
|
|||
password TEXT NOT NULL,
|
||||
description TEXT NOT NULL DEFAULT '',
|
||||
user_type INTEGER NOT NULL,
|
||||
hash_type INTEGER NOT NULL,
|
||||
digest_type INTEGER NOT NULL,
|
||||
vlan TEXT NOT NULL DEFAULT '',
|
||||
enabled INTEGER NOT NULL DEFAULT 1,
|
||||
date_set INTEGER NOT NULL,
|
||||
|
|
@ -95,12 +95,12 @@ def _get_by_index(conn, row_index):
|
|||
return rows[row_index]
|
||||
|
||||
|
||||
def _hash_password(plaintext, hash_type):
|
||||
if hash_type == HASH_CLEARTEXT:
|
||||
def _hash_password(plaintext, digest_type):
|
||||
if digest_type == DIGEST_CYPHERTEXT_FERNET:
|
||||
return encrypt_password(plaintext)
|
||||
if hash_type == HASH_BCRYPT:
|
||||
if digest_type == DIGEST_HASH_BCRYPT:
|
||||
return bcrypt.hashpw(plaintext.encode(), bcrypt.gensalt()).decode()
|
||||
raise ValueError(f"Unknown hash_type: {hash_type}")
|
||||
raise ValueError(f"Unknown digest_type: {digest_type}")
|
||||
|
||||
|
||||
def _parse_valid_for(value_str, unit_str):
|
||||
|
|
@ -166,7 +166,7 @@ def addedit():
|
|||
flash('Invalid user type.', 'error')
|
||||
return redirect(f'/{_PAGE}')
|
||||
|
||||
hash_type = HASH_FOR_USER_TYPE[user_type]
|
||||
digest_type = HASH_FOR_USER_TYPE[user_type]
|
||||
|
||||
vlan = sanitize.name(request.form.get('vlan', ''))
|
||||
if not vlan:
|
||||
|
|
@ -205,26 +205,26 @@ def addedit():
|
|||
|
||||
if password:
|
||||
try:
|
||||
hashed = _hash_password(password, hash_type)
|
||||
hashed = _hash_password(password, digest_type)
|
||||
except ValueError as exc:
|
||||
conn.close()
|
||||
flash(str(exc), 'error')
|
||||
return redirect(f'/{_PAGE}')
|
||||
stored_password = hashed
|
||||
stored_hash_type = hash_type
|
||||
stored_digest_type = digest_type
|
||||
date_set = int(time.time())
|
||||
else:
|
||||
stored_password = existing['password']
|
||||
stored_hash_type = existing['hash_type']
|
||||
stored_digest_type = existing['digest_type']
|
||||
date_set = existing['date_set']
|
||||
|
||||
try:
|
||||
conn.execute(
|
||||
"""UPDATE credentials
|
||||
SET username=?, password=?, description=?, user_type=?, hash_type=?,
|
||||
SET username=?, password=?, description=?, user_type=?, digest_type=?,
|
||||
vlan=?, enabled=?, date_set=?, valid_for=?
|
||||
WHERE id=?""",
|
||||
(username, stored_password, description, user_type, stored_hash_type,
|
||||
(username, stored_password, description, user_type, stored_digest_type,
|
||||
vlan, int(enabled), date_set, valid_for, existing['id']),
|
||||
)
|
||||
conn.commit()
|
||||
|
|
@ -242,7 +242,7 @@ def addedit():
|
|||
flash(f"Auto-generated password for '{username}': {password}", 'success')
|
||||
|
||||
try:
|
||||
hashed = _hash_password(password, hash_type)
|
||||
hashed = _hash_password(password, digest_type)
|
||||
except ValueError as exc:
|
||||
conn.close()
|
||||
flash(str(exc), 'error')
|
||||
|
|
@ -251,9 +251,9 @@ def addedit():
|
|||
try:
|
||||
conn.execute(
|
||||
"""INSERT INTO credentials
|
||||
(username, password, description, user_type, hash_type, vlan, enabled, date_set, valid_for)
|
||||
(username, password, description, user_type, digest_type, vlan, enabled, date_set, valid_for)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||
(username, hashed, description, user_type, hash_type,
|
||||
(username, hashed, description, user_type, digest_type,
|
||||
vlan, int(enabled), int(time.time()), valid_for),
|
||||
)
|
||||
conn.commit()
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ def _load_credentials():
|
|||
password TEXT NOT NULL,
|
||||
description TEXT NOT NULL DEFAULT '',
|
||||
user_type INTEGER NOT NULL,
|
||||
hash_type INTEGER NOT NULL,
|
||||
digest_type INTEGER NOT NULL,
|
||||
vlan TEXT NOT NULL DEFAULT '',
|
||||
enabled INTEGER NOT NULL DEFAULT 1,
|
||||
date_set INTEGER NOT NULL,
|
||||
|
|
|
|||
|
|
@ -59,10 +59,10 @@ def options_save():
|
|||
@auth.require_level('administrator')
|
||||
def auth_mode_save():
|
||||
auth_mode = request.form.get('auth_mode', 'mab')
|
||||
if auth_mode not in ('mab', 'eap_password', 'eap_credential'):
|
||||
if auth_mode not in ('mab', 'eap_password', 'eap_certificate'):
|
||||
flash('Invalid authentication mode.', 'error')
|
||||
return redirect(f'/{_PAGE}')
|
||||
if auth_mode in ('eap_password', 'eap_credential') and not PRO_LICENSE:
|
||||
if auth_mode in ('eap_password', 'eap_certificate') and not PRO_LICENSE:
|
||||
flash('This authentication mode requires a Routlin Pro license.', 'error')
|
||||
return redirect(f'/{_PAGE}')
|
||||
|
||||
|
|
@ -101,7 +101,7 @@ def auth_mode_save():
|
|||
after['default_session_seconds'] = dur_n * mult if dur_n > 0 else 0
|
||||
except (ValueError, TypeError):
|
||||
after['default_session_seconds'] = 0
|
||||
elif auth_mode == 'eap_credential':
|
||||
elif auth_mode == 'eap_certificate':
|
||||
after['include_length'] = include_length
|
||||
after['mab_first'] = mab_first
|
||||
after.pop('eap_protocol', None)
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ def collect_tokens(cfg):
|
|||
tokens['RADIUS_AUTH_MODE_OPTIONS'] = json.dumps([
|
||||
{'value': 'mab', 'label': 'MAC Authentication Bypass (MAB)'},
|
||||
{'value': 'eap_password', 'label': f'802.1X - Client Username/Password{pro_suffix}', 'disabled': pro_disabled},
|
||||
{'value': 'eap_credential', 'label': f'802.1X - Client Certificate{pro_suffix}', 'disabled': pro_disabled},
|
||||
{'value': 'eap_certificate', 'label': f'802.1X - Client Certificate{pro_suffix}', 'disabled': pro_disabled},
|
||||
])
|
||||
tokens['RADIUS_APPLY_TO'] = fr_opts.get('apply_to', 'all')
|
||||
tokens['RADIUS_AP_IPS'] = json.dumps(fr_opts.get('ap_ips', []))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue