From f1312cadc6675fb29d02425775dd8a2a533d7e7c Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich <jo@mein.io> Date: Tue, 7 Feb 2023 11:52:17 +0100 Subject: [PATCH] luci-proto-openconnect: fix server url validation The OpenConnect configuration form incorrectly assumed that the server setting must be hostname while it actually may be a full URL. Fixes: #6184 Signed-off-by: Jo-Philipp Wich <jo@mein.io> --- .../htdocs/luci-static/resources/ui.js | 5 ++- .../resources/protocol/openconnect.js | 41 +++++++++++++++++-- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/modules/luci-base/htdocs/luci-static/resources/ui.js b/modules/luci-base/htdocs/luci-static/resources/ui.js index 51b6c0902d..9433659f7d 100644 --- a/modules/luci-base/htdocs/luci-static/resources/ui.js +++ b/modules/luci-base/htdocs/luci-static/resources/ui.js @@ -820,7 +820,7 @@ var UISelect = UIElement.extend(/** @lends LuCI.ui.Select.prototype */ { 'type': this.options.multiple ? 'checkbox' : 'radio', 'class': this.options.multiple ? 'cbi-input-checkbox' : 'cbi-input-radio', 'value': keys[i], - 'checked': (this.values.indexOf(keys[i]) > -1) ? '' : null, + 'checked': ((!i && !this.values.length) || this.values.indexOf(keys[i]) > -1) ? '' : null, 'disabled': this.options.disabled ? '' : null }), E('label', { 'for': this.options.id ? 'widget.%s.%d'.format(this.options.id, i) : null }), @@ -832,6 +832,9 @@ var UISelect = UIElement.extend(/** @lends LuCI.ui.Select.prototype */ { ])); frameEl.appendChild(brEl.cloneNode()); + + if (!frameEl.querySelector('> span > input[checked]') + frameEl.querySelector('> span > input').checked = true; } } diff --git a/protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js b/protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js index 91ad65cb34..e38afdc201 100644 --- a/protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js +++ b/protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js @@ -2,6 +2,7 @@ 'require rpc'; 'require form'; 'require network'; +'require validation'; var callGetCertificateFiles = rpc.declare({ object: 'luci.openconnect', @@ -100,7 +101,41 @@ return network.registerProtocol('openconnect', { o.value('pulse', 'Pulse Connect Secure SSL VPN'); o = s.taboption('general', form.Value, 'server', _('VPN Server')); - o.datatype = 'host(0)'; + o.validate = function(section_id, value) { + var m = String(value).match(/^(?:(\w+):\/\/|)(?:\[([0-9a-f:.]{2,45})\]|([^\/:]+))(?::([0-9]{1,5}))?(?:\/.*)?$/i); + + if (!m) + return _('Invalid server URL'); + + if (m[1] != null) { + if (!m[1].match(/^(?:http|https|socks|socks4|socks5)$/i)) + return _('Unsupported protocol'); + } + + if (m[2] != null) { + if (!validation.parseIPv6(m[2])) + return _('Invalid IPv6 address'); + } + + if (m[3] != null) { + if (!validation.parseIPv4(m[3])) { + if (!(m[3].length <= 253 && + (m[3].match(/^[a-zA-Z0-9_]+$/) != null || + (m[3].match(/^[a-zA-Z0-9_][a-zA-Z0-9_\-.]*[a-zA-Z0-9]$/) && + m[3].match(/[^0-9.]/))))) + return _('Invalid hostname or IPv4 address'); + } + } + + if (m[4] != null) { + var p = +m[4]; + + if (p < 0 || p > 65535) + return _('Invalid port'); + } + + return true; + }; o = s.taboption('general', form.Value, 'port', _('VPN Server port')); o.placeholder = '443'; @@ -116,7 +151,7 @@ return network.registerProtocol('openconnect', { o = s.taboption('general', form.Value, 'password2', _('Password2')); o.password = true; - + o = s.taboption('general', form.Value, 'proxy', _('Proxy Server')); o.optional = true; @@ -160,7 +195,7 @@ return network.registerProtocol('openconnect', { o.optional = true; o.placeholder = 1406; o.datatype = 'range(68, 9200)'; - + o = s.taboption('advanced', form.Value, 'reconnect_timeout', _('Reconnect Timeout')); o.optional = true; o.placeholder = 300; -- 2.30.2