"Daemon", "mgr" => "SA Manager", "ike" => "IKE SA", "chd" => "IKE Child SA", "job" => "Job Processing", "cfg" => "Configuration backend", "knl" => "Kernel Interface", "net" => "Networking", "asn" => "ASN encoding", "enc" => "Message encoding", "imc" => "Integrity checker", "imv" => "Integrity Verifier", "pts" => "Platform Trust Service", "tls" => "TLS handler", "esp" => "IPsec traffic", "lib" => "StrongSwan Lib"); global $ipsec_log_sevs; $ipsec_log_sevs = array( '-1' => 'Silent', '0' => 'Audit', '1' => 'Control', '2' => 'Diag', '3' => 'Raw', '4' => 'Highest' ); global $ipsec_log_cats; $ipsec_log_cats = array( "dmn" => "Daemon", "mgr" => "SA Manager", "ike" => "IKE SA", "chd" => "IKE Child SA", "job" => "Job Processing", "cfg" => "Configuration backend", "knl" => "Kernel Interface", "net" => "Networking", "asn" => "ASN encoding", "enc" => "Message encoding", "imc" => "Integrity checker", "imv" => "Integrity Verifier", "pts" => "Platform Trust Service", "tls" => "TLS handler", "esp" => "IPsec traffic", "lib" => "StrongSwan Lib" ); global $my_identifier_list; $my_identifier_list = array( 'myaddress' => array('desc' => gettext('My IP address'), 'mobile' => true), 'address' => array('desc' => gettext('IP address'), 'mobile' => true), 'fqdn' => array('desc' => gettext('Distinguished name'), 'mobile' => true), 'user_fqdn' => array('desc' => gettext('User distinguished name'), 'mobile' => true), 'asn1dn' => array('desc' => gettext('ASN.1 distinguished Name'), 'mobile' => true), 'keyid tag' => array('desc' => gettext('KeyID tag'), 'mobile' => true), 'dyn_dns' => array('desc' => gettext('Dynamic DNS'), 'mobile' => true)); global $peer_identifier_list; $peer_identifier_list = array( 'any' => array('desc' => gettext('Any'), 'mobile' => true), 'peeraddress' => array('desc' => gettext('Peer IP address'), 'mobile' => false), 'address' => array('desc' => gettext('IP address'), 'mobile' => false), 'fqdn' => array('desc' => gettext('Distinguished name'), 'mobile' => true), 'user_fqdn' => array('desc' => gettext('User distinguished name'), 'mobile' => true), 'asn1dn' => array('desc' => gettext('ASN.1 distinguished Name'), 'mobile' => true), 'keyid tag' => array('desc' =>gettext('KeyID tag'), 'mobile' => true)); global $ipsec_idhandling; $ipsec_idhandling = array( 'yes' => 'YES', 'no' => 'NO', 'never' => 'NEVER', 'keep' => 'KEEP' ); global $p1_ealgos; $p1_ealgos = array( 'aes' => array('name' => 'AES', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)), 'aes128gcm' => array('name' => 'AES128-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)), 'aes192gcm' => array('name' => 'AES192-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)), 'aes256gcm' => array('name' => 'AES256-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)), 'blowfish' => array('name' => 'Blowfish', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)), '3des' => array('name' => '3DES'), 'cast128' => array('name' => 'CAST128'), 'des' => array('name' => 'DES')); global $p2_ealgos; $p2_ealgos = array( 'aes' => array('name' => 'AES', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)), 'aes128gcm' => array('name' => 'AES128-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)), 'aes192gcm' => array('name' => 'AES192-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)), 'aes256gcm' => array('name' => 'AES256-GCM', 'keysel' => array('lo' => 64, 'hi' => 128, 'step' => 32)), 'blowfish' => array('name' => 'Blowfish', 'keysel' => array('lo' => 128, 'hi' => 256, 'step' => 64)), '3des' => array('name' => '3DES'), 'cast128' => array('name' => 'CAST128'), 'des' => array('name' => 'DES')); global $p1_halgos; $p1_halgos = array( 'md5' => 'MD5', 'sha1' => 'SHA1', 'sha256' => 'SHA256', 'sha384' => 'SHA384', 'sha512' => 'SHA512', 'aesxcbc' => 'AES-XCBC' ); global $p1_dhgroups; $p1_dhgroups = array( 1 => '1 (768 bit)', 2 => '2 (1024 bit)', 5 => '5 (1536 bit)', 14 => '14 (2048 bit)', 15 => '15 (3072 bit)', 16 => '16 (4096 bit)', 17 => '17 (6144 bit)', 18 => '18 (8192 bit)', 19 => '19 (nist ecp256)', 20 => '20 (nist ecp384)', 21 => '21 (nist ecp521)', 22 => '22 (1024(sub 160) bit)', 23 => '23 (2048(sub 224) bit)', 24 => '24 (2048(sub 256) bit)', 28 => '28 (brainpool ecp256)', 29 => '29 (brainpool ecp384)', 30 => '30 (brainpool ecp512)' ); global $p2_halgos; $p2_halgos = array( 'hmac_md5' => 'MD5', 'hmac_sha1' => 'SHA1', 'hmac_sha256' => 'SHA256', 'hmac_sha384' => 'SHA384', 'hmac_sha512' => 'SHA512', 'aesxcbc' => 'AES-XCBC' ); global $p1_authentication_methods; $p1_authentication_methods = array( 'hybrid_rsa_server' => array('name' => 'Hybrid RSA + Xauth', 'mobile' => true), 'xauth_rsa_server' => array('name' => 'Mutual RSA + Xauth', 'mobile' => true), 'xauth_psk_server' => array('name' => 'Mutual PSK + Xauth', 'mobile' => true), 'eap-tls' => array('name' => 'EAP-TLS', 'mobile' => true), 'eap-radius' => array('name' => 'EAP-RADIUS', 'mobile' => true), 'eap-mschapv2' => array('name' => 'EAP-MSChapv2', 'mobile' => true), 'rsasig' => array('name' => 'Mutual RSA', 'mobile' => false), 'pre_shared_key' => array('name' => 'Mutual PSK', 'mobile' => false)); global $ipsec_preshared_key_type; $ipsec_preshared_key_type = array( 'PSK' => 'PSK', 'EAP' => 'EAP' ); global $p2_modes; $p2_modes = array( 'tunnel' => 'Tunnel IPv4', 'tunnel6' => 'Tunnel IPv6', 'transport' => 'Transport'); global $p2_protos; $p2_protos = array( 'esp' => 'ESP', 'ah' => 'AH'); global $p2_pfskeygroups; $p2_pfskeygroups = array( 0 => 'off', 1 => '1 (768 bit)', 2 => '2 (1024 bit)', 5 => '5 (1536 bit)', 14 => '14 (2048 bit)', 15 => '15 (3072 bit)', 16 => '16 (4096 bit)', 17 => '17 (6144 bit)', 18 => '18 (8192 bit)', 19 => '19 (nist ecp256)', 20 => '20 (nist ecp384)', 21 => '21 (nist ecp521)', 28 => '28 (brainpool ecp256)', 29 => '29 (brainpool ecp384)', 30 => '30 (brainpool ecp512)' ); function ipsec_enabled() { global $config; if (!isset($config['ipsec']) || !is_array($config['ipsec'])) return false; /* Check if we have at least one phase 1 entry. */ if (!isset($config['ipsec']['phase1']) || !is_array($config['ipsec']['phase1']) || empty($config['ipsec']['phase1'])) { return false; } /* Check if at least one phase 1 entry is enabled. */ foreach ($config['ipsec']['phase1'] as $phase1) { if (!isset($phase1['disabled'])) return true; } return false; } /* * ikeid management functions */ function ipsec_ikeid_used($ikeid) { global $config; 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; } /* * Return phase1 local address */ function ipsec_get_phase1_src(& $ph1ent) { if ($ph1ent['interface']) { if (!is_ipaddr($ph1ent['interface'])) { if (strpos($ph1ent['interface'], '_vip')) { $if = $ph1ent['interface']; } else { $if = get_failover_interface($ph1ent['interface']); } if ($ph1ent['protocol'] == "inet6") { $interfaceip = get_interface_ipv6($if); } else { $interfaceip = get_interface_ip($if); } } else { $interfaceip = $ph1ent['interface']; } } else { $if = "wan"; if ($ph1ent['protocol'] == "inet6") { $interfaceip = get_interface_ipv6($if); } else { $interfaceip = get_interface_ip($if); } } return $interfaceip; } /* * Return phase1 local address */ function ipsec_get_phase1_dst(& $ph1ent) { global $g; if (empty($ph1ent['remote-gateway'])) { return false; } $rg = $ph1ent['remote-gateway']; if (!is_ipaddr($rg)) { if (!platform_booting()) { return resolve_retry($rg); } } if (!is_ipaddr($rg)) { return false; } return $rg; } /* * Return phase2 idinfo in cidr format */ function ipsec_idinfo_to_cidr(& $idinfo, $addrbits = false, $mode = "") { global $config; switch ($idinfo['type']) { case "address": if ($addrbits) { if ($mode == "tunnel6") { return $idinfo['address']."/128"; } else { return $idinfo['address']."/32"; } } else { return $idinfo['address']; } break; /* NOTREACHED */ case "network": return "{$idinfo['address']}/{$idinfo['netbits']}"; break; /* NOTREACHED */ case "none": case "mobile": return '0.0.0.0/0'; break; /* NOTREACHED */ default: if (empty($mode) && !empty($idinfo['mode'])) { $mode = $idinfo['mode']; } if ($mode == "tunnel6") { $address = get_interface_ipv6($idinfo['type']); $netbits = get_interface_subnetv6($idinfo['type']); $address = gen_subnetv6($address, $netbits); return "{$address}/{$netbits}"; } else { $address = get_interface_ip($idinfo['type']); $netbits = get_interface_subnet($idinfo['type']); $address = gen_subnet($address, $netbits); return "{$address}/{$netbits}"; } break; /* NOTREACHED */ } } /* * Return phase2 idinfo in address/netmask format */ function ipsec_idinfo_to_subnet(& $idinfo, $addrbits = false) { global $config; switch ($idinfo['type']) { case "address": if ($addrbits) { if ($idinfo['mode'] == "tunnel6") { return $idinfo['address']."/128"; } else { return $idinfo['address']."/255.255.255.255"; } } else { return $idinfo['address']; } break; /* NOTREACHED */ case "none": case "network": return $idinfo['address']."/".gen_subnet_mask($idinfo['netbits']); break; /* NOTREACHED */ case "mobile": return "0.0.0.0/0"; break; /* NOTREACHED */ default: if ($idinfo['mode'] == "tunnel6") { $address = get_interface_ipv6($idinfo['type']); $netbits = get_interface_subnetv6($idinfo['type']); $address = gen_subnetv6($address, $netbits); return $address."/".$netbits; } else { $address = get_interface_ip($idinfo['type']); $netbits = get_interface_subnet($idinfo['type']); $address = gen_subnet($address, $netbits); return $address."/".$netbits; } break; /* NOTREACHED */ } } /* * Return phase2 idinfo in text format */ function ipsec_idinfo_to_text(& $idinfo) { global $config; switch ($idinfo['type']) { case "address": return $idinfo['address']; break; /* NOTREACHED */ case "network": return $idinfo['address']."/".$idinfo['netbits']; break; /* NOTREACHED */ case "mobile": return gettext("Mobile Client"); break; /* NOTREACHED */ case "none": return gettext("None"); break; /* NOTREACHED */ default: if (!empty($config['interfaces'][$idinfo['type']])) { return convert_friendly_interface_to_friendly_descr($idinfo['type']); } else { return strtoupper($idinfo['type']); } break; /* NOTREACHED */ } } /* * Return phase1 association for phase2 */ function ipsec_lookup_phase1(& $ph2ent, & $ph1ent) { global $config; if (!is_array($config['ipsec'])) { return false; } if (!is_array($config['ipsec']['phase1'])) { return false; } if (empty($config['ipsec']['phase1'])) { return false; } foreach ($config['ipsec']['phase1'] as $ph1tmp) { if ($ph1tmp['ikeid'] == $ph2ent['ikeid']) { $ph1ent = $ph1tmp; return $ph1ent; } } return false; } /* * Check phase1 communications status */ function ipsec_phase1_status(&$ipsec_status, $ikeid) { foreach ($ipsec_status as $ike) { if ($ike['id'] == $ikeid) { if ($ike['status'] == 'established') { return true; } } } return false; } /* * Check phase2 communications status */ function ipsec_phase2_status(&$ipsec_status, &$phase2) { if (ipsec_lookup_phase1($ph2ent, $ph1ent)) { return ipsec_phase1_status($ipsec_status, $ph1ent['ikeid']); } return false; } /* * Wrapper to call pfSense_ipsec_list_sa() when IPsec is enabled */ function ipsec_list_sa() { if (ipsec_enabled()) return pfSense_ipsec_list_sa(); return array(); } /* * Return dump of SPD table */ function ipsec_dump_spd() { $fd = @popen("/sbin/setkey -DP", "r"); $spd = array(); if ($fd) { while (!feof($fd)) { $line = chop(fgets($fd)); if (!$line) { continue; } if ($line == "No SPD entries.") { break; } if ($line[0] != "\t") { if (is_array($cursp)) { $spd[] = $cursp; } $cursp = array(); $linea = explode(" ", $line); $cursp['srcid'] = substr($linea[0], 0, strpos($linea[0], "[")); $cursp['dstid'] = substr($linea[1], 0, strpos($linea[1], "[")); $i = 0; } else if (is_array($cursp)) { $line = trim($line, "\t\r\n "); $linea = explode(" ", $line); switch ($i) { case 1: if ($linea[1] == "none") /* don't show default anti-lockout rule */ { unset($cursp); } else { $cursp['dir'] = $linea[0]; } break; case 2: $upperspec = explode("/", $linea[0]); $cursp['proto'] = $upperspec[0]; list($cursp['src'], $cursp['dst']) = explode("-", $upperspec[2]); $cursp['reqid'] = substr($upperspec[3], strpos($upperspec[3], "#")+1); break; } } $i++; } if (is_array($cursp) && count($cursp)) { $spd[] = $cursp; } pclose($fd); } return $spd; } /* * Return dump of SAD table */ function ipsec_dump_sad() { $fd = @popen("/sbin/setkey -D", "r"); $sad = array(); if ($fd) { while (!feof($fd)) { $line = chop(fgets($fd)); if (!$line || $line[0] == " ") { continue; } if ($line == "No SAD entries.") { break; } if ($line[0] != "\t") { if (is_array($cursa)) { $sad[] = $cursa; } $cursa = array(); list($cursa['src'], $cursa['dst']) = explode(" ", $line); } else { $line = trim($line, "\t\n\r "); $linea = explode(" ", $line); foreach ($linea as $idx => $linee) { if ($linee == 'esp' || $linee == 'ah' || $linee[0] == '#') { $cursa['proto'] = $linee; } else if (substr($linee, 0, 3) == 'spi') { $cursa['spi'] = substr($linee, strpos($linee, 'x') + 1, -1); } else if (substr($linee, 0, 5) == 'reqid') { $cursa['reqid'] = substr($linee, strpos($linee, 'x') + 1, -1); } else if (substr($linee, 0, 2) == 'E:') { $cursa['ealgo'] = $linea[$idx + 1]; break; } else if (substr($linee, 0, 2) == 'A:') { $cursa['aalgo'] = $linea[$idx + 1]; break; } else if (substr($linee, 0, 8) == 'current:') { $cursa['data'] = substr($linea[$idx + 1], 0, strpos($linea[$idx + 1], 'bytes') - 1) . ' B'; break; } } } } if (is_array($cursa) && count($cursa)) { $sad[] = $cursa; } pclose($fd); } return $sad; } /* * Return dump of mobile user list */ function ipsec_dump_mobile() { global $g; $_gb = exec("/usr/local/sbin/ipsec leases 2>/dev/null", $output, $rc); if ($rc != 0) { log_error(gettext("Unable to find IPsec daemon leases file. Could not display mobile user stats!")); return array(); } $response = array(); $id = -1; /* Leases in pool '10.7.200.0/24', usage: 1/254, 1 online */ $lease_regex='/^Leases *in *pool *\'(?P.+)\', *usage: *(?P\d+)\/(?P\d+), *(?P\d+) *online/'; /* 10.7.200.1 online 'jimp' */ $pool_regex='/\s*(?P[\d\.]+)\s+(?Ponline|offline)\s+\'(?P.*)\'/'; /* no matching leases found */ $nopool_regex='/no *matching *leases *found/'; $lease=false; foreach ($output as $line) { if (preg_match($lease_regex, $line, $matches)) { $id++; $response['pool'][$id] = array( 'name' => $matches['name'], 'usage' => $matches['usage'], 'size' => $matches['size'], 'online' => $matches['online'], ); $lease=true; } else if ($lease) { if (preg_match($nopool_regex, $line)) { $response['pool'][$id]['lease'][] = array(); $lease=false; } else if (preg_match($pool_regex, $line, $matches)) { $response['pool'][$id]['lease'][] = array( 'host' => $matches['host'], 'status' => $matches['status'], 'id' => $matches['id'] ); } } } unset($_gb, $lease, $output, $rc, $id, $lease_regex, $pool_regex, $nopool_regex); return $response; } function ipsec_mobilekey_sort() { global $config; function mobilekeycmp($a, $b) { return strcmp($a['ident'][0], $b['ident'][0]); } usort($config['ipsec']['mobilekey'], "mobilekeycmp"); } function ipsec_get_number_of_phase2($ikeid) { global $config; $a_phase2 = $config['ipsec']['phase2']; $nbph2 = 0; if (is_array($a_phase2) && count($a_phase2)) { foreach ($a_phase2 as $ph2tmp) { if ($ph2tmp['ikeid'] == $ikeid) { $nbph2++; } } } return $nbph2; } function ipsec_get_descr($ikeid) { global $config; if (!isset($config['ipsec']['phase1']) || !is_array($config['ipsec']['phase1'])) { return ''; } foreach ($config['ipsec']['phase1'] as $p1) { if ($p1['ikeid'] == $ikeid) { return $p1['descr']; } } return ''; } function ipsec_get_phase1($ikeid) { global $config; if (!isset($config['ipsec']['phase1']) || !is_array($config['ipsec']['phase1'])) { return ''; } $a_phase1 = $config['ipsec']['phase1']; foreach ($a_phase1 as $p1) { if ($p1['ikeid'] == $ikeid) { return $p1; } } unset($a_phase1); } function ipsec_fixup_ip($ipaddr) { if (is_ipaddrv6($ipaddr) || is_subnetv6($ipaddr)) { return Net_IPv6::compress(Net_IPv6::uncompress($ipaddr)); } else { return $ipaddr; } } function ipsec_find_id(& $ph1ent, $side = "local", $rgmap = array()) { if ($side == "local") { $id_type = $ph1ent['myid_type']; $id_data = $ph1ent['myid_data']; $addr = ipsec_get_phase1_src($ph1ent); if (!$addr) { return array(); } } elseif ($side == "peer") { $id_type = $ph1ent['peerid_type']; $id_data = $ph1ent['peerid_data']; if (isset($ph1ent['mobile'])) { $addr = "%any"; } else { $addr = $ph1ent['remote-gateway']; } } else { return array(); } $thisid_type = $id_type; switch ($thisid_type) { case 'myaddress': $thisid_type = 'address'; $thisid_data = $addr; break; case 'dyn_dns': $thisid_type = 'dns'; $thisid_data = $id_data; break; case 'peeraddress': $thisid_type = 'address'; $thisid_data = $rgmap[$ph1ent['remote-gateway']]; break; case 'address': $thisid_data = $id_data; break; case 'fqdn': $thisid_data = "{$id_data}"; break; case 'keyid tag': $thisid_type = 'keyid'; $thisid_data = "{$id_data}"; break; case 'user_fqdn': $thisid_type = 'userfqdn'; $thisid_data = "{$id_data}"; break; case 'asn1dn': $thisid_data = $id_data; break; } return array($thisid_type, $thisid_data); } function ipsec_fixup_network($network) { if (substr($network, -3) == '|/0') { $result = substr($network, 0, -3); } else { $tmp = explode('|', $network); if (isset($tmp[1])) { $result = $tmp[1]; } else { $result = $tmp[0]; } unset($tmp); } return $result; } function ipsec_new_reqid() { global $config; if (!is_array($config['ipsec']) || !is_array($config['ipsec']['phase2'])) { return; } $ipsecreqid = lock('ipsecreqids', LOCK_EX); $keyids = array(); $keyid = 1; foreach ($config['ipsec']['phase2'] as $ph2) { $keyids[$ph2['reqid']] = $ph2['reqid']; } for ($i = 1; $i < 16000; $i++) { if (!isset($keyids[$i])) { $keyid = $i; break; } } unlock($ipsecreqid); return $keyid; } ?>