--[[ Copyright (c) 2012-2019 Kaarle Ritvanen See LICENSE file for license details --]] local M = require('aconf.model') local util = require('aconf.util') local cipher_suites local function combine(ciphers, ...) if not ciphers then return {{{}, {}}} end local res = {} for _, a in ipairs(cipher_suites(ciphers)) do for _, b in ipairs(combine(...)) do local c = {} for i=1,2 do c[i] = {a[i]} util.extend(c[i], b[i]) end table.insert(res, c) end end return res end function cipher_suites(ciphers) local res = {} for _, cs in ipairs(ciphers) do if type(cs) ~= 'table' then cs = {cs} end if #cs < 3 then table.insert(res, {cs[1], cs[2] or cs[1]}) else local variants = {} for i=3,#cs do table.insert(variants, cs[i]) end for _, c in ipairs(combine(table.unpack(variants))) do table.insert( res, { cs[1]:format(table.unpack(c[1])), cs[2]:format(table.unpack(c[2])) } ) end end end return res end local Connection = M.new() Connection.esp_proposals = M.List{ type=M.List{ type=M.String{ choice=cipher_suites{ {'null', 'No encryption'}, {'3des', '168-bit 3DES-EDE-CBC'}, {'cast128', '128-bit CAST-CBC'}, {'blowfish%d', '%d-bit Blowfish-CBC', {128, 192, 256}}, { 'aes%d%s', '%d-bit AES-%s', {128, 192, 256}, { {'', 'CBC'}, {'ctr', 'CTR'}, { '%s%d', '%s with %d-bit ICV', {{'ccm', 'CCM'}, {'gcm', 'GCM'}}, {{8, 64}, {12, 96}, {16, 128}} }, {'gmac', 'GMAC (no encryption)'} } }, { 'camellia%d%s', '%d-bit Camellia-%s', {128, 192, 256}, { {'', 'CBC'}, {'ctr', 'CTR'}, { 'ccm%d', 'CCM with %d-bit ICV', {{8, 64}, {12, 96}, {16, 128}} } } }, {'chacha20poly1305', '256-bit ChaCha20/Poly1305 with 128-bit ICV'}, {'md5%s', '%d-bit HMAC-MD5', {{'', 96}, {'_128', 128}}}, {'sha1%s', '%d-bit HMAC-SHA1', {{'', 96}, {'_160', 160}}}, {'aes%s', '96-bit AES-%s', {{'xcbc', 'XCBC'}, {'cmac', 'CMAC'}}}, {'sha256%s', '%d-bit HMAC-SHA256', {{'_96', 96}, {'', 128}}}, {'sha384', '192-bit HMAC-SHA384'}, {'sha512', '256-bit HMAC-SHA512'}, { 'prf%s', '%s PRF', { {'md5', 'MD5'}, {'sha1', 'SHA1'}, {'aes%s', 'AES-%s', {{'xcbc', 'XCBC'}, {'cmac', 'CMAC'}}}, {'sha%d', 'SHA%d', {256, 384, 512}} } }, { 'modp%d', '%d-bit modulo prime group', {768, 1024, 1536, 2048, 3072, 4096, 6144, 8192} }, { 'modp1024s160', '1024-bit group with 160-bit prime order subgroup' }, { 'modp2048s%d', '2048-bit group with %d-bit prime order subgroup', {224, 256} }, { 'ecp%d', '%d-bit NIST elliptic curve group', {192, 224, 256, 384, 521} }, { 'ecp%dbp', '%d-bit Brainpool elliptic curve group', {224, 256, 384, 512} }, {'curve25519', '256-bit elliptic curve 25519'}, {'curve448', '448-bit elliptic curve 25519'}, { 'ntru%d', '%d-bit post-quantum key exchange using NTRU encryption', {112, 128, 192, 256} }, {'newhope128', '128-bit post-quantum key exchange using NewHope'} } }, ui_member='Algorithm' }, addr='children/default/#proposals/esp_proposals', ui_name='ESP proposals', ui_member='Proposal', widget='inline' } Connection.pools = M.Set{ type=M.Reference{scope='../../../pools'}, addr='#list/pools' } local Credentials = M.new() Credentials.priv_keys = M.Collection{ type=M.String{widget='textarea'}, addr='private', ui_name='Private keys', widget='inline' } Credentials.certs = M.Collection{ type=M.String{widget='textarea'}, addr='x509', ui_name='Certificates', widget='inline' } Credentials.ca_certs = M.Collection{ type=M.String{widget='textarea'}, addr='x509ca', ui_name='Authority certificates', widget='inline' } local Pool = M.new() Pool.addresses = M.Union{ types={M.net.IPAddress{cidr=true}, M.Range{type=M.net.IPAddress}}, required=true, addr='addrs', error='Invalid IP address range' } local IPsec = M.service('charon') IPsec.connections = M.Collection{ type=M.Model{ model=Connection, be_mode={['#list']='value', ['children/default/#proposals']='value'} } } IPsec.credentials = M.Model{model=Credentials, addr='/files/etc/swanctl'} IPsec.pools = M.Collection{type=Pool} M.register( 'ipsec', IPsec, {addr='/augeas/etc/swanctl/swanctl.conf', ui_name='IPsec'} ) M.permission.defaults('/ipsec')