Development

This commit is contained in:
Matthew Grotke 2026-06-06 01:01:43 -04:00
parent 2c8153c004
commit 0f38304d60
5 changed files with 14 additions and 78 deletions

View file

@ -69,14 +69,17 @@ def auth_mode_save():
eap_protocol = request.form.get('eap_protocol', 'eap_peap') eap_protocol = request.form.get('eap_protocol', 'eap_peap')
if eap_protocol not in ('eap_peap', 'eap_ttls', 'eap_md5'): if eap_protocol not in ('eap_peap', 'eap_ttls', 'eap_md5'):
eap_protocol = 'eap_peap' eap_protocol = 'eap_peap'
tunneled_reply = 'tunneled_reply' in request.form
cfg = load_config() cfg = load_config()
before = copy.deepcopy(cfg.get('radius', {}).get('options', {})) before = copy.deepcopy(cfg.get('radius', {}).get('options', {}))
after = {**before, 'auth_mode': auth_mode} after = {**before, 'auth_mode': auth_mode}
if auth_mode == 'eap_password': if auth_mode == 'eap_password':
after['eap_protocol'] = eap_protocol after['eap_protocol'] = eap_protocol
after['tunneled_reply'] = tunneled_reply and eap_protocol in ('eap_peap', 'eap_ttls')
else: else:
after.pop('eap_protocol', None) after.pop('eap_protocol', None)
after.pop('tunneled_reply', None)
cfg.setdefault('radius', {})['options'] = after cfg.setdefault('radius', {})['options'] = after
changes = diff_fields(before, after) changes = diff_fields(before, after)
@ -134,21 +137,6 @@ def default_vlan_save():
return redirect(f'/{_PAGE}') return redirect(f'/{_PAGE}')
@bp.route('/action/radius/eap_save', methods=['POST'])
@require_level('administrator')
def eap_save():
allow_weak_eap = 'allow_weak_eap' in request.form
tunneled_reply = 'tunneled_reply' in request.form
cfg = load_config()
before = copy.deepcopy(cfg.get('radius', {}).get('eap', {}))
after = {'allow_weak_eap': allow_weak_eap, 'tunneled_reply': tunneled_reply}
cfg.setdefault('radius', {})['eap'] = after
changes = diff_fields(before, after)
flash(record_group(cfg, 'radius.eap', 'setting', 'radius', changes, 'core apply'), 'success')
return redirect(f'/{_PAGE}')
@bp.route('/action/radius/logging_save', methods=['POST']) @bp.route('/action/radius/logging_save', methods=['POST'])
@require_level('administrator') @require_level('administrator')

View file

@ -238,53 +238,6 @@
"options": "%RADIUS_EAP_PROTOCOL_OPTIONS%", "options": "%RADIUS_EAP_PROTOCOL_OPTIONS%",
"hint": "_" "hint": "_"
}, },
{
"type": "raw_html",
"html": "</div>"
},
{
"type": "button_row",
"items": [
{
"type": "button_primary",
"text": "Save"
},
{
"type": "button_cancel",
"text": "Cancel"
}
]
}
]
}
]
},
{
"type": "card",
"label": "EAP Settings",
"client_requirement": "client_is_administrator+",
"items": [
{
"type": "p",
"text": "These settings are required for MAC-based 802.1X authentication on managed switches."
},
{
"type": "hr"
},
{
"type": "form",
"action": "/action/radius/eap_save",
"method": "post",
"items": [
{
"type": "field",
"label": "",
"name": "allow_weak_eap",
"input_type": "checkbox",
"checkbox_label": "Allow weak EAP types",
"value": "%RADIUS_ALLOW_WEAK_EAP%",
"hint": "Enables EAP-MD5. Required for switch port MAC-based 802.1X authentication."
},
{ {
"type": "raw_html", "type": "raw_html",
"html": "<div id=\"eap-tunneled-row\">" "html": "<div id=\"eap-tunneled-row\">"

View file

@ -104,9 +104,7 @@ def collect_tokens(cfg):
tokens['RADIUS_LOGGING_HINT'] = 'Unchecking will clear logs.' if fr_gen.get('logging', False) else '' tokens['RADIUS_LOGGING_HINT'] = 'Unchecking will clear logs.' if fr_gen.get('logging', False) else ''
tokens['RADIUS_GEN_LOG_MAX_KB'] = str(fr_gen.get('log_max_kb', 1024)) tokens['RADIUS_GEN_LOG_MAX_KB'] = str(fr_gen.get('log_max_kb', 1024))
fr_eap = fr.get('eap', {}) tokens['RADIUS_TUNNELED_REPLY'] = 'true' if fr_opts.get('tunneled_reply', False) else ''
tokens['RADIUS_ALLOW_WEAK_EAP'] = 'true' if fr_eap.get('allow_weak_eap', False) else ''
tokens['RADIUS_TUNNELED_REPLY'] = 'true' if fr_eap.get('tunneled_reply', False) else ''
vlans = cfg.get('vlans', []) vlans = cfg.get('vlans', [])
default_vlan = next((v['name'] for v in vlans if v.get('radius_default') is True), '') default_vlan = next((v['name'] for v in vlans if v.get('radius_default') is True), '')

View file

@ -838,10 +838,6 @@
"mac_format": "aabbccddeeff", "mac_format": "aabbccddeeff",
"apply_to": "all", "apply_to": "all",
"ap_ips": [] "ap_ips": []
},
"eap": {
"allow_weak_eap": false,
"tunneled_reply": false
} }
} }
} }

View file

@ -248,26 +248,27 @@ def toggle_freeradius_block(content, block_name, enable):
def set_freeradius_eap(data): def set_freeradius_eap(data):
"""Patch EAP config for tunneled_reply and allow_weak_eap settings. """Patch EAP config for eap_protocol and tunneled_reply settings.
Returns True if the file was modified, False if unchanged or not found. Returns True if the file was modified, False if unchanged or not found.
""" """
if not RADIUS_EAP_FILE.exists(): if not RADIUS_EAP_FILE.exists():
return False return False
eap_cfg = data.get('radius', {}).get('eap', {}) opts = data.get('radius', {}).get('options', {})
tunneled_reply = eap_cfg.get('tunneled_reply', False) eap_protocol = opts.get('eap_protocol', 'eap_peap')
allow_weak_eap = eap_cfg.get('allow_weak_eap', False) tunneled_reply = opts.get('tunneled_reply', False)
use_md5 = eap_protocol == 'eap_md5'
eap_type = {'eap_peap': 'peap', 'eap_ttls': 'ttls', 'eap_md5': 'md5'}.get(eap_protocol, 'peap')
content = RADIUS_EAP_FILE.read_text() content = RADIUS_EAP_FILE.read_text()
tr_val = 'yes' if tunneled_reply else 'no' tr_val = 'yes' if tunneled_reply else 'no'
eap_type = 'md5' if allow_weak_eap else 'peap'
content2 = re.sub(r'(?m)^(\s*use_tunneled_reply\s*=\s*)(yes|no)', rf'\g<1>{tr_val}', content) content2 = re.sub(r'(?m)^(\s*use_tunneled_reply\s*=\s*)(yes|no)', rf'\g<1>{tr_val}', content)
# Only replace the first occurrence -- that is the outer eap{} block's default. # Only replace the first occurrence -- that is the outer eap{} block's default.
# Inner blocks (e.g. peap's tunneled default) must not be touched. # Inner blocks (e.g. peap's tunneled default) must not be touched.
content3 = re.sub(r'(?m)^(\s*default_eap_type\s*=\s*)\w+', rf'\g<1>{eap_type}', content2, count=1) content3 = re.sub(r'(?m)^(\s*default_eap_type\s*=\s*)\w+', rf'\g<1>{eap_type}', content2, count=1)
content4 = toggle_freeradius_block(content3, 'md5', allow_weak_eap) content4 = toggle_freeradius_block(content3, 'md5', use_md5)
if content4 == content: if content4 == content:
return False return False
RADIUS_EAP_FILE.write_text(content4) RADIUS_EAP_FILE.write_text(content4)
print(f"EAP: default_eap_type={eap_type}, tunneled_reply={tr_val}, allow_weak_eap={allow_weak_eap}") print(f"EAP: default_eap_type={eap_type}, tunneled_reply={tr_val}")
return True return True