luci-app-strongswan-swanctl: add crypto proposal section
authorLukas Voegl <lvoegl@tdt.de>
Fri, 3 Nov 2023 14:14:30 +0000 (15:14 +0100)
committerLukas Voegl <lvoegl@tdt.de>
Wed, 22 Nov 2023 15:38:55 +0000 (16:38 +0100)
Signed-off-by: Lukas Voegl <lvoegl@tdt.de>
applications/luci-app-strongswan-swanctl/htdocs/luci-static/resources/strongswan_algorithms.js [new file with mode: 0644]
applications/luci-app-strongswan-swanctl/htdocs/luci-static/resources/view/strongswan-swanctl/swanctl.js

diff --git a/applications/luci-app-strongswan-swanctl/htdocs/luci-static/resources/strongswan_algorithms.js b/applications/luci-app-strongswan-swanctl/htdocs/luci-static/resources/strongswan_algorithms.js
new file mode 100644 (file)
index 0000000..1ebbe59
--- /dev/null
@@ -0,0 +1,143 @@
+'use strict';
+'require baseclass';
+
+return baseclass.extend({
+
+       _encryptionAlgorithms: new Map([
+               ['3des', true],
+               ['cast128', true],
+               ['blowfish128', true],
+               ['blowfish192', true],
+               ['blowfish256', true],
+               ['null', true],
+               ['aes128'],
+               ['aes192'],
+               ['aes256'],
+               ['aes128ctr'],
+               ['aes192ctr'],
+               ['aes256ctr'],
+               ['camellia128'],
+               ['camellia192'],
+               ['camellia256'],
+               ['camellia128ctr'],
+               ['camellia192ctr'],
+               ['camellia256ctr']
+       ]),
+
+       _authenticatedEncryptionAlgorithms: new Map([
+               ['aes128ccm64'],
+               ['aes192ccm64'],
+               ['aes256ccm64'],
+               ['aes128ccm96'],
+               ['aes192ccm96'],
+               ['aes256ccm96'],
+               ['aes128ccm128'],
+               ['aes192ccm128'],
+               ['aes256ccm128'],
+               ['aes128gcm64'],
+               ['aes192gcm64'],
+               ['aes256gcm64'],
+               ['aes128gcm96'],
+               ['aes192gcm96'],
+               ['aes256gcm96'],
+               ['aes128gcm128'],
+               ['aes192gcm128'],
+               ['aes256gcm128'],
+               ['aes128gmac'],
+               ['aes192gmac'],
+               ['aes256gmac'],
+               ['camellia128ccm64'],
+               ['camellia192ccm64'],
+               ['camellia256ccm64'],
+               ['camellia128ccm96'],
+               ['camellia192ccm96'],
+               ['camellia256ccm96'],
+               ['camellia128ccm128'],
+               ['camellia192ccm128'],
+               ['camellia256ccm128'],
+               ['chacha20poly1305']
+       ]),
+
+       _hashAlgorithms: new Map([
+               ['md5', true],
+               ['md5_128', true],
+               ['sha1', true],
+               ['sha1_160', true],
+               ['aesxcbc'],
+               ['aescmac'],
+               ['aes128gmac'],
+               ['aes192gmac'],
+               ['aes256gmac'],
+               ['sha256'],
+               ['sha384'],
+               ['sha512'],
+               ['sha256_96']
+       ]),
+
+       _dhAlgorithms: new Map([
+               ['modp768', true],
+               ['modp1024', true],
+               ['modp1536', true],
+               ['modp2048'],
+               ['modp3072'],
+               ['modp4096'],
+               ['modp6144'],
+               ['modp8192'],
+               ['modp1024s160', true],
+               ['modp2048s224', true],
+               ['modp2048s256', true],
+               ['ecp192', true],
+               ['ecp224'],
+               ['ecp256'],
+               ['ecp384'],
+               ['ecp521'],
+               ['ecp224bp'],
+               ['ecp256bp'],
+               ['ecp384bp'],
+               ['ecp512bp'],
+               ['curve25519'],
+               ['curve448']
+       ]),
+
+       _prfAlgorithms: new Map([
+               ['prfmd5', true],
+               ['prfsha1', true],
+               ['prfaesxcbc'],
+               ['prfaescmac'],
+               ['prfsha256'],
+               ['prfsha384'],
+               ['prfsha512']
+       ]),
+
+       _getAlgorithmNames: function (algorithms) {
+               return Array.from(algorithms.keys());
+       },
+
+       isInsecure: function (algorithmName) {
+               return this._encryptionAlgorithms.get(algorithmName) == true
+                       || this._authenticatedEncryptionAlgorithms.get(algorithmName) == true
+                       || this._hashAlgorithms.get(algorithmName) == true
+                       || this._dhAlgorithms.get(algorithmName) == true
+                       || this._prfAlgorithms.get(algorithmName) == true;
+       },
+
+       getEncryptionAlgorithms: function () {
+               return this._getAlgorithmNames(this._encryptionAlgorithms);
+       },
+
+       getAuthenticatedEncryptionAlgorithms: function () {
+               return this._getAlgorithmNames(this._authenticatedEncryptionAlgorithms);
+       },
+
+       getHashAlgorithms: function () {
+               return this._getAlgorithmNames(this._hashAlgorithms);
+       },
+
+       getDiffieHellmanAlgorithms: function () {
+               return this._getAlgorithmNames(this._dhAlgorithms);
+       },
+
+       getPrfAlgorithms: function () {
+               return this._getAlgorithmNames(this._prfAlgorithms);
+       }
+});
index 59d0db3f4add274ccbc71a503056465a7d63bdd7..c2aeff2a7bd54223bbcac494997f54d5dea57378 100644 (file)
@@ -3,6 +3,17 @@
 'require form';
 'require uci';
 'require tools.widgets as widgets';
+'require strongswan_algorithms';
+
+function addAlgorithms(o, algorithms) {
+       algorithms.forEach(function (algorithm) {
+               if (strongswan_algorithms.isInsecure(algorithm)) {
+                       o.value(algorithm, '%s*'.format(algorithm));
+               } else {
+                       o.value(algorithm);
+               }
+       });
+}
 
 return view.extend({
        render: function () {
@@ -103,12 +114,26 @@ return view.extend({
                o.default = 'yes';
                o.modalonly = true;
 
-               o = s.option(form.ListValue, 'crypto_proposal', _('Crypto Proposal'),
+               o = s.option(form.MultiValue, 'crypto_proposal', _('Crypto Proposal'),
                        _('List of IKE (phase 1) proposals to use for authentication'));
-               o.value('encryption_algorithm');
-               o.value('hash_algorithm');
-               o.value('dh_group');
-               o.value('prf_algorithm');
+               o.load = function (section_id) {
+                       this.keylist = [];
+                       this.vallist = [];
+
+                       var sections = uci.sections('ipsec', 'crypto_proposal');
+                       if (sections.length == 0) {
+                               this.value('', _('Please create a Proposal first'));
+                       } else {
+                               sections.forEach(L.bind(function (section) {
+                                       if (section.is_esp != '1') {
+                                               this.value(section['.name']);
+                                       }
+                               }, this));
+                       }
+
+                       return this.super('load', [section_id]);
+               };
+               o.rmempty = false;
 
                o = s.option(form.MultiValue, 'tunnel', _('Tunnel'),
                        _('Name of ESP (phase 2) section'));
@@ -129,61 +154,6 @@ return view.extend({
                };
                o.rmempty = false;
 
-               o = s.option(form.Value, 'authentication_method',
-                       _('Authentication Method'), _('IKE authentication (phase 1)'));
-               o.datatype = 'string';
-
-               s = m.section(form.TypedSection, 'ipsec',
-                       _('strongSwan General Settings'));
-               s.anonymous = true;
-
-               o = s.option(form.ListValue, 'encryption_algorithm',
-                       _('Encryption Algorithm'),
-                       '%s (aes128, aes192, aes256, 3des)'.format(_('Encryption method')));
-               o.value('aes128');
-               o.value('aes192');
-               o.value('aes256');
-               o.value('3des');
-               o.rmempty = false;
-
-               o = s.option(form.ListValue, 'hash_algorithm', _('Hash Algorithm'),
-                       '%s (md5, sha1, sha2, ...)'.format(_('Hash algorithm')));
-               o.value('md5');
-               o.value('sha1');
-               o.value('sha2');
-               o.value('sha256');
-               o.value('sha384');
-               o.value('sha512');
-               o.value('sha3_256');
-               o.value('sha3_384');
-               o.value('sha3_512');
-               o.value('blake2s256');
-               o.value('blake2b512');
-               o.value('blake2s256');
-               o.value('blake2b512');
-               o.value('whirlpool');
-               o.value('tiger');
-               o.rmempty = false;
-
-               o = s.option(form.ListValue, 'dh_group', _('Diffie-Hellman Group'),
-                       '%s (modp768, modp1024, ...)'.format(_('Diffie-Hellman exponentiation')));
-               o.value('modp768');
-               o.value('modp1024');
-               o.value('modp1536');
-               o.value('modp2048');
-               o.value('modp3072');
-               o.value('modp4096');
-               o.rmempty = false;
-
-               o = s.option(form.ListValue, 'prf_algorithm', _('PRF Algorithm'),
-                       _('Pseudo-Random Functions to use with IKE'));
-               o.value('prf_hmac_md5');
-               o.value('prfmd5');
-               o.value('prfsha1');
-               o.value('prfsha256');
-               o.value('pfsha384');
-               o.value('prfsha512');
-
                // Tunnel Configuration
                s = m.section(form.GridSection, 'tunnel', _('Tunnel Configuration'),
                        _('Define Connection Children to be used as Tunnels in Remote Configurations.'));
@@ -207,13 +177,27 @@ return view.extend({
                o.datatype = 'subnet';
                o.modalonly = true;
 
-               o = s.option(form.ListValue, 'crypto_proposal',
-                       _('Crypto Proposal (Phase 2)'), _('List of ESP (phase two) proposals'));
-               o.value('encryption_algorithm');
-               o.value('hash_algorithm');
-               o.value('dh_group');
-               o.value('prf_algorithm');
-               o.required = true;
+               o = s.option(form.MultiValue, 'crypto_proposal',
+                       _('Crypto Proposal (Phase 2)'),
+                       _('List of ESP (phase two) proposals. Only Proposals with checked ESP flag are selectable'));
+               o.load = function (section_id) {
+                       this.keylist = [];
+                       this.vallist = [];
+
+                       var sections = uci.sections('ipsec', 'crypto_proposal');
+                       if (sections.length == 0) {
+                               this.value('', _('Please create an ESP Proposal first'));
+                       } else {
+                               sections.forEach(L.bind(function (section) {
+                                       if (section.is_esp == '1') {
+                                               this.value(section['.name']);
+                                       }
+                               }, this));
+                       }
+
+                       return this.super('load', [section_id]);
+               };
+               o.rmempty = false;
 
                o = s.option(form.ListValue, 'startaction', _('Start Action'),
                        _('Action on initial configuration load'));
@@ -228,6 +212,54 @@ return view.extend({
                o.datatype = 'file';
                o.modalonly = true;
 
+               // Crypto Proposals
+               s = m.section(form.GridSection, 'crypto_proposal',
+                       _('Encryption Proposals'),
+                       _('Configure Cipher Suites to define IKE (Phase 1) or ESP (Phase 2) Proposals.'));
+               s.addremove = true;
+               s.nodescriptions = true;
+
+               o = s.option(form.Flag, 'is_esp', _('ESP Proposal'),
+                       _('Whether this is an ESP (phase 2) proposal or not'));
+
+               o = s.option(form.ListValue, 'encryption_algorithm',
+                       _('Encryption Algorithm'),
+                       _('Algorithms marked with * are considered insecure'));
+               o.default = 'aes256gcm128';
+               addAlgorithms(o, strongswan_algorithms.getEncryptionAlgorithms());
+               addAlgorithms(o, strongswan_algorithms.getAuthenticatedEncryptionAlgorithms());
+
+
+               o = s.option(form.ListValue, 'hash_algorithm', _('Hash Algorithm'),
+                       _('Algorithms marked with * are considered insecure'));
+               strongswan_algorithms.getEncryptionAlgorithms().forEach(function (algorithm) {
+                       o.depends('encryption_algorithm', algorithm);
+               });
+               o.default = 'sha512';
+               o.rmempty = false;
+               addAlgorithms(o, strongswan_algorithms.getHashAlgorithms());
+
+               o = s.option(form.ListValue, 'dh_group', _('Diffie-Hellman Group'),
+                       _('Algorithms marked with * are considered insecure'));
+               o.default = 'modp3072';
+               addAlgorithms(o, strongswan_algorithms.getDiffieHellmanAlgorithms());
+
+               o = s.option(form.ListValue, 'prf_algorithm', _('PRF Algorithm'),
+                       _('Algorithms marked with * are considered insecure'));
+               o.validate = function (section_id, value) {
+                       var encryptionAlgorithm = this.section.formvalue(section_id, 'encryption_algorithm');
+
+                       if (strongswan_algorithms.getAuthenticatedEncryptionAlgorithms().includes(
+                                       encryptionAlgorithm) && !value) {
+                               return _('PRF Algorithm must be configured when using an Authenticated Encryption Algorithm');
+                       }
+
+                       return true;
+               };
+               o.optional = true;
+               o.depends('is_esp', '0');
+               addAlgorithms(o, strongswan_algorithms.getPrfAlgorithms());
+
                return m.render();
        }
 });