* Copyright (C) 2014-2015 Deciso B.V. * Copyright (C) 2008 Shrew Soft Inc. * Copyright (C) 2003-2005 Manuel Kasper * Copyright (C) 2014 Ermal Luçi * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ require_once("guiconfig.inc"); require_once("system.inc"); require_once("filter.inc"); require_once("interfaces.inc"); require_once("plugins.inc.d/ipsec.inc"); /* * ikeid management functions */ function ipsec_ikeid_used($ikeid) { global $config; if (!empty($config['ipsec']['phase1'])) { foreach ($config['ipsec']['phase1'] as $ph1ent) { if( $ikeid == $ph1ent['ikeid'] ) { return true; } } } return false; } function ipsec_ikeid_next() { $ikeid = 1; while(ipsec_ikeid_used($ikeid)) { $ikeid++; } return $ikeid; } function ipsec_keypairs() { $mdl = new \OPNsense\IPsec\IPsec(); $node = $mdl->getNodeByReference('keyPairs.keyPair'); return $node ? $node->getNodes() : []; } config_read_array('ipsec', 'phase1'); config_read_array('ipsec', 'phase2'); if ($_SERVER['REQUEST_METHOD'] === 'GET') { // fetch data if (isset($_GET['dup']) && is_numericint($_GET['dup'])) { $p1index = $_GET['dup']; } elseif (isset($_GET['p1index']) && is_numericint($_GET['p1index'])) { $p1index = $_GET['p1index']; } $pconfig = array(); // generice defaults $pconfig['interface'] = "wan"; $pconfig['iketype'] = "ikev2"; $phase1_fields = "mode,protocol,myid_type,myid_data,peerid_type,peerid_data ,encryption-algorithm,lifetime,authentication_method,descr,nat_traversal,rightallowany,inactivity_timeout ,interface,iketype,dpd_delay,dpd_maxfail,dpd_action,remote-gateway,pre-shared-key,certref,margintime,rekeyfuzz ,caref,local-kpref,peer-kpref,reauth_enable,rekey_enable,auto,tunnel_isolation,authservers,mobike,keyingtries ,closeaction"; if (isset($p1index) && isset($config['ipsec']['phase1'][$p1index])) { // 1-on-1 copy foreach (explode(",", $phase1_fields) as $fieldname) { $fieldname = trim($fieldname); if(isset($config['ipsec']['phase1'][$p1index][$fieldname])) { $pconfig[$fieldname] = $config['ipsec']['phase1'][$p1index][$fieldname]; } elseif (!isset($pconfig[$fieldname])) { // initialize element $pconfig[$fieldname] = null; } } // attributes with some kind of logic behind them... if (!isset($_GET['dup']) || !is_numericint($_GET['dup'])) { // don't copy the ikeid on dup $pconfig['ikeid'] = $config['ipsec']['phase1'][$p1index]['ikeid']; } $pconfig['disabled'] = isset($config['ipsec']['phase1'][$p1index]['disabled']); $pconfig['sha256_96'] = !empty($config['ipsec']['phase1'][$p1index]['sha256_96']); $pconfig['installpolicy'] = empty($config['ipsec']['phase1'][$p1index]['noinstallpolicy']); // XXX: reversed foreach (array('authservers', 'dhgroup', 'hash-algorithm') as $fieldname) { if (!empty($config['ipsec']['phase1'][$p1index][$fieldname])) { $pconfig[$fieldname] = explode(',', $config['ipsec']['phase1'][$p1index][$fieldname]); } else { $pconfig[$fieldname] = array(); } } $pconfig['remotebits'] = null; $pconfig['remotenet'] = null ; if (isset($a_phase1[$p1index]['remote-subnet']) && strpos($config['ipsec']['phase1'][$p1index]['remote-subnet'],'/') !== false) { list($pconfig['remotenet'],$pconfig['remotebits']) = explode("/", $config['ipsec']['phase1'][$p1index]['remote-subnet']); } elseif (isset($config['ipsec']['phase1'][$p1index]['remote-subnet'])) { $pconfig['remotenet'] = $config['ipsec']['phase1'][$p1index]['remote-subnet']; } if (isset($config['ipsec']['phase1'][$p1index]['mobile'])) { $pconfig['mobile'] = true; } } else { /* defaults new */ if (isset($config['interfaces']['lan'])) { $pconfig['localnet'] = "lan"; } $pconfig['mode'] = "main"; $pconfig['protocol'] = "inet"; $pconfig['myid_type'] = "myaddress"; $pconfig['peerid_type'] = "peeraddress"; $pconfig['authentication_method'] = "pre_shared_key"; $pconfig['encryption-algorithm'] = array("name" => "aes", "keylen" => "128"); $pconfig['hash-algorithm'] = array('sha256'); $pconfig['dhgroup'] = array('14'); $pconfig['lifetime'] = "28800"; $pconfig['nat_traversal'] = "on"; $pconfig['installpolicy'] = true; $pconfig['authservers'] = array(); /* mobile client */ if (isset($_GET['mobile'])) { $pconfig['mobile'] = true; } // init empty foreach (explode(",", $phase1_fields) as $fieldname) { $fieldname = trim($fieldname); if (!isset($pconfig[$fieldname])) { $pconfig[$fieldname] = null; } } } } elseif ($_SERVER['REQUEST_METHOD'] === 'POST') { $a_phase1 = &config_read_array('ipsec', 'phase1'); if (isset($_POST['p1index']) && is_numericint($_POST['p1index'])) { $p1index = $_POST['p1index']; } $input_errors = array(); $pconfig = $_POST; $old_ph1ent = $a_phase1[$p1index]; // unset dpd on post if (!isset($pconfig['dpd_enable'])) { unset($pconfig['dpd_delay']); unset($pconfig['dpd_maxfail']); unset($pconfig['dpd_action']); } /* My identity */ if ($pconfig['myid_type'] == "myaddress") { $pconfig['myid_data'] = ""; } /* Peer identity */ if ($pconfig['myid_type'] == "peeraddress") { $pconfig['peerid_data'] = ""; } /* input validation */ $method = $pconfig['authentication_method']; // Only require PSK here for normal PSK tunnels (not mobile) or xauth. // For RSA methods, require the CA/Cert. switch ($method) { case "eap-tls": case "psk_eap-tls": case "eap-mschapv2": case "rsa_eap-mschapv2": case "eap-radius": if (!in_array($pconfig['iketype'], array('ikev2', 'ike'))) { $input_errors[] = sprintf(gettext("%s can only be used with IKEv2 type VPNs."), strtoupper($method)); } if ($method == 'eap-radius' && empty($pconfig['authservers'])) { $input_errors[] = gettext("Please select radius servers to use."); } break; case "pre_shared_key": // If this is a mobile PSK tunnel the user PSKs go on // the PSK tab, not here, so skip the check. if ($pconfig['mobile']) { break; } case "xauth_psk_server": $reqdfields = explode(" ", "pre-shared-key"); $reqdfieldsn = array(gettext("Pre-Shared Key")); break; case "hybrid_rsa_server": $reqdfields = explode(' ', 'certref'); $reqdfieldsn = array(gettext("Certificate")); break; case "xauth_rsa_server": case "rsasig": $reqdfields = explode(" ", "caref certref"); $reqdfieldsn = array(gettext("Certificate Authority"),gettext("Certificate")); break; case "pubkey": $reqdfields = explode(" ", "local-kpref peer-kpref"); $reqdfieldsn = array(gettext("Local Key Pair"),gettext("Peer Key Pair")); break; } if (empty($pconfig['mobile'])) { $reqdfields[] = "remote-gateway"; $reqdfieldsn[] = gettext("Remote gateway"); } do_input_validation($pconfig, $reqdfields, $reqdfieldsn, $input_errors); if (!empty($pconfig['inactivity_timeout']) && !is_numericint($pconfig['inactivity_timeout'])) { $input_errors[] = gettext("The inactivity timeout must be an integer."); } if (!empty($pconfig['keyingtries']) && !is_numericint($pconfig['keyingtries']) && $pconfig['keyingtries'] != "-1") { $input_errors[] = gettext("The keyingtries must be an integer."); } if ((!empty($pconfig['lifetime']) && !is_numeric($pconfig['lifetime']))) { $input_errors[] = gettext("The P1 lifetime must be an integer."); } if (!empty($pconfig['margintime'])) { if (!is_numericint($pconfig['margintime'])) { $input_errors[] = gettext("The margintime must be an integer."); } else { $rekeyfuzz = empty($pconfig['rekeyfuzz']) || !is_numeric($pconfig['rekeyfuzz']) ? 100 : $pconfig['rekeyfuzz']; if (((int)$pconfig['margintime'] * 2) * ($rekeyfuzz / 100.0) > (int)$pconfig['lifetime']) { $input_errors[] = gettext("The value margin... + margin... * rekeyfuzz must not exceed the original lifetime limit."); } } } if (!empty($pconfig['rekeyfuzz']) && !is_numericint($pconfig['rekeyfuzz'])) { $input_errors[] = gettext("Rekeyfuzz must be an integer."); } if (!empty($pconfig['remote-gateway'])) { if (!is_ipaddr($pconfig['remote-gateway']) && !is_domain($pconfig['remote-gateway'])) { $input_errors[] = gettext("A valid remote gateway address or host name must be specified."); } elseif (is_ipaddrv4($pconfig['remote-gateway']) && ($pconfig['protocol'] != "inet")) { $input_errors[] = gettext("A valid remote gateway IPv4 address must be specified or you need to change protocol to IPv6"); } elseif (is_ipaddrv6($pconfig['remote-gateway']) && ($pconfig['protocol'] != "inet6")) { $input_errors[] = gettext("A valid remote gateway IPv6 address must be specified or you need to change protocol to IPv4"); } } if (!empty($pconfig['remote-gateway']) && is_ipaddr($pconfig['remote-gateway']) && !isset($pconfig['disabled']) && (empty($pconfig['iketype']) || $pconfig['iketype'] == "ikev1")) { $t = 0; foreach ($a_phase1 as $ph1tmp) { if ($p1index != $t) { if (isset($ph1tmp['remote-gateway']) && $ph1tmp['remote-gateway'] == $pconfig['remote-gateway'] && !isset($ph1tmp['disabled'])) { $input_errors[] = sprintf(gettext('The remote gateway "%s" is already used by phase1 "%s".'), $pconfig['remote-gateway'], $ph1tmp['descr']); } } $t++; } } if ($pconfig['interface'] == 'any' && $pconfig['myid_type'] == "myaddress") { $input_errors[] = gettext("Please select an identifier (My Identifier) other then 'any' when selecting 'Any' interface"); } elseif ($pconfig['myid_type'] == "address" && $pconfig['myid_data'] == "") { $input_errors[] = gettext("Please enter an address for 'My Identifier'"); } elseif ($pconfig['myid_type'] == "keyid tag" && $pconfig['myid_data'] == "") { $input_errors[] = gettext("Please enter a keyid tag for 'My Identifier'"); } elseif ($pconfig['myid_type'] == "fqdn" && $pconfig['myid_data'] == "") { $input_errors[] = gettext("Please enter a fully qualified domain name for 'My Identifier'"); } elseif ($pconfig['myid_type'] == "user_fqdn" && $pconfig['myid_data'] == "") { $input_errors[] = gettext("Please enter a user and fully qualified domain name for 'My Identifier'"); } elseif ($pconfig['myid_type'] == "dyn_dns" && $pconfig['myid_data'] == "") { $input_errors[] = gettext("Please enter a dynamic domain name for 'My Identifier'"); } elseif ((($pconfig['myid_type'] == "address") && !is_ipaddr($pconfig['myid_data']))) { $input_errors[] = gettext("A valid IP address for 'My identifier' must be specified."); } elseif ((($pconfig['myid_type'] == "fqdn") && !is_domain($pconfig['myid_data']))) { $input_errors[] = gettext("A valid domain name for 'My identifier' must be specified."); } elseif ($pconfig['myid_type'] == "fqdn" && !is_domain($pconfig['myid_data'])) { $input_errors[] = gettext("A valid FQDN for 'My identifier' must be specified."); } elseif ($pconfig['myid_type'] == "user_fqdn") { $user_fqdn = explode("@", $pconfig['myid_data']); if (is_domain($user_fqdn[1]) == false) { $input_errors[] = gettext("A valid User FQDN in the form of user@my.domain.com for 'My identifier' must be specified."); } } elseif ($pconfig['myid_type'] == "dyn_dns") { if (is_domain($pconfig['myid_data']) == false) { $input_errors[] = gettext("A valid Dynamic DNS address for 'My identifier' must be specified."); } } // Only enforce peer ID if we are not dealing with a pure-psk mobile config. if (!(($pconfig['authentication_method'] == "pre_shared_key") && !empty($pconfig['mobile']))) { if ($pconfig['peerid_type'] == "address" and $pconfig['peerid_data'] == "") { $input_errors[] = gettext("Please enter an address for 'Peer Identifier'"); } if ($pconfig['peerid_type'] == "keyid tag" and $pconfig['peerid_data'] == "") { $input_errors[] = gettext("Please enter a keyid tag for 'Peer Identifier'"); } if ($pconfig['peerid_type'] == "fqdn" and $pconfig['peerid_data'] == "") { $input_errors[] = gettext("Please enter a fully qualified domain name for 'Peer Identifier'"); } if ($pconfig['peerid_type'] == "user_fqdn" and $pconfig['peerid_data'] == "") { $input_errors[] = gettext("Please enter a user and fully qualified domain name for 'Peer Identifier'"); } if ((($pconfig['peerid_type'] == "address") && !is_ipaddr($pconfig['peerid_data']))) { $input_errors[] = gettext("A valid IP address for 'Peer identifier' must be specified."); } if ((($pconfig['peerid_type'] == "fqdn") && !is_domain($pconfig['peerid_data']))) { $input_errors[] = gettext("A valid domain name for 'Peer identifier' must be specified."); } if ($pconfig['peerid_type'] == "fqdn") { if (is_domain($pconfig['peerid_data']) == false) { $input_errors[] = gettext("A valid FQDN for 'Peer identifier' must be specified."); } } if ($pconfig['peerid_type'] == "user_fqdn") { $user_fqdn = explode("@", $pconfig['peerid_data']); if (is_domain($user_fqdn[1]) == false) { $input_errors[] = gettext("A valid User FQDN in the form of user@my.domain.com for 'Peer identifier' must be specified."); } } } if (!empty($pconfig['closeaction']) && !in_array($pconfig['closeaction'], ['clear', 'hold', 'restart'])) { $input_errors[] = gettext('Invalid argument for close action.'); } if (!empty($pconfig['dpd_enable'])) { if (!is_numeric($pconfig['dpd_delay'])) { $input_errors[] = gettext("A numeric value must be specified for DPD delay."); } if (!is_numeric($pconfig['dpd_maxfail'])) { $input_errors[] = gettext("A numeric value must be specified for DPD retries."); } if (!empty($pconfig['dpd_action']) && !in_array($pconfig['dpd_action'], array("restart", "clear"))) { $input_errors[] = gettext('Invalid argument for DPD action.'); } } if (!empty($pconfig['iketype']) && !in_array($pconfig['iketype'], array("ike", "ikev1", "ikev2"))) { $input_errors[] = gettext('Invalid argument for key exchange protocol version.'); } /* build our encryption algorithms array */ if (!isset($pconfig['encryption-algorithm']) || !is_array($pconfig['encryption-algorithm'])) { $pconfig['encryption-algorithm'] = array(); } $pconfig['encryption-algorithm']['name'] = $pconfig['ealgo']; if (!empty($pconfig['ealgo_keylen'])) { $pconfig['encryption-algorithm']['keylen'] = $pconfig['ealgo_keylen']; } if (empty($pconfig['hash-algorithm'])) { $input_errors[] = gettext("At least one hashing algorithm needs to be selected."); $pconfig['hash-algorithm'] = array(); } if (empty($pconfig['dhgroup'])) { $pconfig['dhgroup'] = array(); } foreach (ipsec_p1_ealgos() as $algo => $algodata) { if (!empty($pconfig['iketype']) && !empty($pconfig['encryption-algorithm']['name']) && !empty($algodata['iketype']) && $pconfig['iketype'] != $algodata['iketype'] && $pconfig['encryption-algorithm']['name'] == $algo) { $input_errors[] = sprintf(gettext("%s can only be used with IKEv2 type VPNs."), $algodata['name']); } } if (!empty($pconfig['ikeid']) && !empty($pconfig['installpolicy'])) { foreach ($config['ipsec']['phase2'] as $phase2ent) { if ($phase2ent['ikeid'] == $pconfig['ikeid'] && $phase2ent['mode'] == 'route-based') { $input_errors[] = gettext( "Install policy on phase1 is not a valid option when using Route-based phase 2 entries." ); break; } } } if (count($input_errors) == 0) { $copy_fields = "ikeid,iketype,interface,mode,protocol,myid_type,myid_data ,peerid_type,peerid_data,encryption-algorithm,margintime,rekeyfuzz,inactivity_timeout,keyingtries ,lifetime,pre-shared-key,certref,caref,authentication_method,descr,local-kpref,peer-kpref ,nat_traversal,auto,mobike,closeaction"; foreach (explode(",",$copy_fields) as $fieldname) { $fieldname = trim($fieldname); if(!empty($pconfig[$fieldname])) { $ph1ent[$fieldname] = $pconfig[$fieldname]; } } foreach (array('authservers', 'dhgroup', 'hash-algorithm') as $fieldname) { if (!empty($pconfig[$fieldname])) { $ph1ent[$fieldname] = implode(',', $pconfig[$fieldname]); } } $ph1ent['disabled'] = !empty($pconfig['disabled']); $ph1ent['sha256_96'] = !empty($pconfig['sha256_96']); $ph1ent['noinstallpolicy'] = empty($pconfig['installpolicy']); // XXX: reversed $ph1ent['private-key'] =isset($pconfig['privatekey']) ? base64_encode($pconfig['privatekey']) : null; if (!empty($pconfig['mobile'])) { $ph1ent['mobile'] = true; } else { $ph1ent['remote-gateway'] = $pconfig['remote-gateway']; } if (isset($pconfig['reauth_enable'])) { $ph1ent['reauth_enable'] = true; } if (isset($pconfig['rekey_enable'])) { $ph1ent['rekey_enable'] = true; } if (isset($pconfig['tunnel_isolation'])) { $ph1ent['tunnel_isolation'] = true; } if (isset($pconfig['rightallowany'])) { $ph1ent['rightallowany'] = true; } if (isset($pconfig['dpd_enable'])) { $ph1ent['dpd_delay'] = $pconfig['dpd_delay']; $ph1ent['dpd_maxfail'] = $pconfig['dpd_maxfail']; $ph1ent['dpd_action'] = $pconfig['dpd_action']; } /* generate unique phase1 ikeid */ if ($ph1ent['ikeid'] == 0) { $ph1ent['ikeid'] = ipsec_ikeid_next(); } if (isset($p1index) && isset($a_phase1[$p1index])) { $a_phase1[$p1index] = $ph1ent; } else { if (!empty($pconfig['clone_phase2']) && !empty($a_phase1[$_GET['dup']]) && !empty($config['ipsec']['phase2'])) { // clone phase 2 entries in disabled state if requested. $prev_ike_id = $a_phase1[$_GET['dup']]['ikeid']; foreach ($config['ipsec']['phase2'] as $phase2ent) { if ($phase2ent['ikeid'] == $prev_ike_id) { $new_phase2 = $phase2ent; $new_phase2['disabled'] = true; $new_phase2['uniqid'] = uniqid(); $new_phase2['ikeid'] = $ph1ent['ikeid']; $config['ipsec']['phase2'][] = $new_phase2; } } } $a_phase1[] = $ph1ent; } /* if the remote gateway changed and the interface is not WAN then remove route */ if ($pconfig['interface'] != 'wan') { if ($old_ph1ent['remote-gateway'] != $pconfig['remote-gateway']) { /* XXX does this even apply? only use of system.inc at the top! */ system_host_route($old_ph1ent['remote-gateway'], $old_ph1ent['remote-gateway'], true, false); } } write_config(); mark_subsystem_dirty('ipsec'); header(url_safe('Location: /vpn_ipsec.php')); exit; } } $service_hook = 'strongswan'; legacy_html_escape_form_data($pconfig); include("head.inc"); ?>
0) { print_input_errors($input_errors); } ?>
/>
/>
/>
 
" />
/>
/>
/>
/>
/>
/>
/>