Commit 7dfcd3e2 authored by Ad Schellevis's avatar Ad Schellevis Committed by Franco Fichtner

(openvpn, client export) remove windows installer

(cherry picked from commit 35b96a9d)
(cherry picked from commit e0083264)
(cherry picked from commit 84b04888)
parent a3909ca7
ROOT= /usr/local/opnsense/contrib
TREES= mobile-broadband-provider-info openvpn tzdata
TREES= mobile-broadband-provider-info tzdata
.include "../Mk/tree.mk"
;!@Install@!UTF-8!
RunProgram="procchain.exe procchain-import"
;!@InstallEnd@!
;!@Install@!UTF-8!
RunProgram="procchain.exe procchain-standard"
;!@InstallEnd@!
<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly xsi:schemaLocation="urn:schemas-microsoft-com:asm.v1 assembly.adaptive.xsd" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:co.v1="urn:schemas-microsoft-com:clickonce.v1" xmlns:co.v2="urn:schemas-microsoft-com:clickonce.v2" xmlns="urn:schemas-microsoft-com:asm.v2" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xrml="urn:mpeg:mpeg21:2003:01-REL-R-NS" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<assemblyIdentity name="OpenVPNManager.application" version="0.0.3.3" publicKeyToken="0000000000000000" language="neutral" processorArchitecture="msil" xmlns="urn:schemas-microsoft-com:asm.v1" />
<description asmv2:publisher="Jochen Wierum" asmv2:product="OpenVPN Manager" asmv2:supportUrl="http://jowisoftware.dyndns.org/~jochen/OpenVPN_Manager" xmlns="urn:schemas-microsoft-com:asm.v1" />
<deployment install="true" mapFileExtensions="true">
<subscription>
<update>
<beforeApplicationStartup />
</update>
</subscription>
<deploymentProvider codebase="http://jowisoftware.dyndns.org/~jochen/OpenVPN_Manager/OpenVPNManager.application" />
</deployment>
<dependency>
<dependentAssembly dependencyType="install" codebase="OpenVPNManager.exe.manifest" size="5378">
<assemblyIdentity name="OpenVPNManager.exe" version="0.0.3.3" publicKeyToken="0000000000000000" language="neutral" processorArchitecture="msil" type="win32" />
<hash>
<dsig:Transforms>
<dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
</dsig:Transforms>
<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<dsig:DigestValue>XT90/vo/vuC6FKm0d16lyYf4VLc=</dsig:DigestValue>
</hash>
</dependentAssembly>
</dependency>
</asmv1:assembly>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="OpenVPNManager.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<userSettings>
<OpenVPNManager.Properties.Settings>
<setting name="vpnbin" serializeAs="String">
<value />
</setting>
<setting name="vpnconf" serializeAs="String">
<value />
</setting>
<setting name="debugLevel" serializeAs="String">
<value>1</value>
</setting>
<setting name="firstStart" serializeAs="String">
<value>True</value>
</setting>
<setting name="startMinimized" serializeAs="String">
<value>True</value>
</setting>
<setting name="searchUpdate" serializeAs="String">
<value>0</value>
</setting>
<setting name="lastUpdateCheck" serializeAs="String">
<value />
</setting>
<setting name="allowRemoteControl" serializeAs="String">
<value>False</value>
</setting>
<setting name="callUpdate" serializeAs="String">
<value>True</value>
</setting>
<setting name="smartCardSupport" serializeAs="String">
<value>False</value>
</setting>
</OpenVPNManager.Properties.Settings>
</userSettings>
</configuration>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly manifestVersion="1.0" xsi:schemaLocation="urn:schemas-microsoft-com:asm.v1 assembly.adaptive.xsd" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:co.v2="urn:schemas-microsoft-com:clickonce.v2" xmlns="urn:schemas-microsoft-com:asm.v2" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:co.v1="urn:schemas-microsoft-com:clickonce.v1">
<asmv1:assemblyIdentity version="0.0.3.3" name="OpenVPNManager.exe" publicKeyToken="0000000000000000" language="neutral" processorArchitecture="msil" type="win32" />
<description asmv2:iconFile="Resources\icon.ico" xmlns="urn:schemas-microsoft-com:asm.v1" />
<application />
<entryPoint>
<assemblyIdentity name="OpenVPNManager" version="0.0.3.6" publicKeyToken="CBDAF510072A0F11" language="neutral" processorArchitecture="msil" />
<commandLine file="OpenVPNManager.exe" parameters="" />
</entryPoint>
<trustInfo>
<security>
<applicationRequestMinimum>
<PermissionSet class="System.Security.PermissionSet" version="1" ID="Custom" SameSite="site" Unrestricted="true" />
<defaultAssemblyRequest permissionSetReference="Custom" />
</applicationRequestMinimum>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- UAC-Manifestoptionen
Wenn Sie die Ebene der Benutzerkontensteuerung für Windows ändern
möchten, ersetzen Sie den Knoten "requestedExecutionLevel" wie folgt:
-->
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
<dependency>
<dependentOS>
<osVersionInfo>
<os majorVersion="4" minorVersion="10" buildNumber="0" servicePackMajor="0" />
</osVersionInfo>
</dependentOS>
</dependency>
<dependency>
<dependentAssembly dependencyType="preRequisite" allowDelayedBinding="true">
<assemblyIdentity name="Microsoft.Windows.CommonLanguageRuntime" version="2.0.50727.0" />
</dependentAssembly>
</dependency>
<dependency>
<dependentAssembly dependencyType="install" allowDelayedBinding="true" codebase="OpenVPN.dll" size="34816">
<assemblyIdentity name="OpenVPN" version="0.0.3.6" publicKeyToken="CBDAF510072A0F11" language="neutral" processorArchitecture="msil" />
<hash>
<dsig:Transforms>
<dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
</dsig:Transforms>
<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<dsig:DigestValue>oEuOAn0+Ihgt2BeRcJ4LL1v9cxg=</dsig:DigestValue>
</hash>
</dependentAssembly>
</dependency>
<dependency>
<dependentAssembly dependencyType="install" allowDelayedBinding="true" codebase="OpenVPNManager.exe" size="348160">
<assemblyIdentity name="OpenVPNManager" version="0.0.3.6" publicKeyToken="CBDAF510072A0F11" language="neutral" processorArchitecture="msil" />
<hash>
<dsig:Transforms>
<dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
</dsig:Transforms>
<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<dsig:DigestValue>Wjl/w91fCfDa6PJr/BjVc91QBkM=</dsig:DigestValue>
</hash>
</dependentAssembly>
</dependency>
<dependency>
<dependentAssembly dependencyType="install" allowDelayedBinding="true" codebase="de\OpenVPNManager.resources.dll" size="57344">
<assemblyIdentity name="OpenVPNManager.resources" version="0.0.3.6" publicKeyToken="CBDAF510072A0F11" language="de" processorArchitecture="msil" />
<hash>
<dsig:Transforms>
<dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
</dsig:Transforms>
<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<dsig:DigestValue>nXALIba1RuoneuzYgzYAjkZA70c=</dsig:DigestValue>
</hash>
</dependentAssembly>
</dependency>
<file name="license.txt" size="18282">
<hash>
<dsig:Transforms>
<dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
</dsig:Transforms>
<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<dsig:DigestValue>RX3X90u9Cg0J+ZgyIVKgiGjAZHg=</dsig:DigestValue>
</hash>
</file>
<file name="OpenVPNManager.exe.config" size="1919">
<hash>
<dsig:Transforms>
<dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
</dsig:Transforms>
<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<dsig:DigestValue>K7eDMvkLnFQNVnJnsYCU+W+tUkY=</dsig:DigestValue>
</hash>
</file>
<file name="Resources\icon.ico" size="4286">
<hash>
<dsig:Transforms>
<dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
</dsig:Transforms>
<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<dsig:DigestValue>BDfrWnbambquEU7H76KpaKGK+U4=</dsig:DigestValue>
</hash>
</file>
</asmv1:assembly>
\ No newline at end of file
"openvpn-install.exe"
"openvpn-postinstall.exe" /Import
"openvpn-install.exe"
"openvpn-postinstall.exe"
......@@ -29,10 +29,6 @@
POSSIBILITY OF SUCH DAMAGE.
*/
global $current_openvpn_version, $current_openvpn_version_rev;
$current_openvpn_version = "2.3.6";
$current_openvpn_version_rev = "01";
function openvpn_client_export_prefix($srvid, $usrid = null, $crtid = null)
{
global $config;
......@@ -455,134 +451,12 @@ function openvpn_client_export_config($srvid, $usrid, $crtid, $useaddr, $verifys
}
}
function openvpn_client_export_installer($srvid, $usrid, $crtid, $useaddr, $verifyservercn, $randomlocalport, $usetoken, $outpass, $proxy, $openvpnmanager, $advancedoptions, $openvpn_version = "x86-xp")
{
global $config, $input_errors, $current_openvpn_version, $current_openvpn_version_rev;
switch ($openvpn_version) {
case "x86-xp":
$client_install_exe = "openvpn-install-{$current_openvpn_version}-I0{$current_openvpn_version_rev}-i686.exe";
break;
case "x64-xp":
$client_install_exe = "openvpn-install-{$current_openvpn_version}-I0{$current_openvpn_version_rev}-x86_64.exe";
break;
case "x86-win6":
$client_install_exe = "openvpn-install-{$current_openvpn_version}-I6{$current_openvpn_version_rev}-i686.exe";
break;
case "x64-win6":
$client_install_exe = "openvpn-install-{$current_openvpn_version}-I6{$current_openvpn_version_rev}-x86_64.exe";
break;
default:
$input_errors[] = gettext("Could not find matching OpenVPN architecture.");
return false;
}
$validconfig = openvpn_client_export_validate_config($srvid, $usrid, $crtid);
if (!$validconfig) {
$input_errors[] = gettext("Could not validate OpenVPN config.");
return false;
}
list($settings, $server_cert, $server_ca, $servercn, $user, $cert, $nokeys) = $validconfig;
// create template directory
$tempdir = '/tmp/openvpn-export-' . uniqid();
mkdir($tempdir, 0700, true);
// create config directory
$confdir = "{$tempdir}/config";
if (!is_dir($conf_dir)) {
mkdir($confdir, 0700, true);
}
// copy the template directory
exec("cp -r /usr/local/opnsense/contrib/openvpn/client-export/template/* {$tempdir}");
// and put the required installer exe in place
exec("/bin/cp {$tempdir}/{$client_install_exe} {$tempdir}/openvpn-install.exe");
if (stristr($openvpn_version, "x64")) {
rename("{$tempdir}/openvpn-postinstall64.exe", "{$tempdir}/openvpn-postinstall.exe");
}
// write configuration file
$prefix = openvpn_client_export_prefix($srvid, $usrid, $crtid);
$cfgfile = "{$confdir}/{$prefix}-config.ovpn";
if (!empty($proxy) && $proxy['proxy_authtype'] != "none") {
$proxy['passwdfile'] = "{$prefix}-password";
$pwdfle = "{$proxy['user']}\r\n";
$pwdfle .= "{$proxy['password']}\r\n";
file_put_contents("{$confdir}/{$proxy['passwdfile']}", $pwdfle);
}
$conf = openvpn_client_export_config($srvid, $usrid, $crtid, $useaddr, $verifyservercn, $randomlocalport, $usetoken, $nokeys, $proxy, "", "baseconf", false, true, $openvpnmanager, $advancedoptions);
if (!$conf) {
$input_errors[] = gettext("Could not create a config to export.");
return false;
}
file_put_contents($cfgfile, $conf);
$cafile = "{$tempdir}/config/{$prefix}-ca.crt";
file_put_contents($cafile, $server_ca);
if ($settings['tls']) {
$tlsfile = "{$tempdir}/config/{$prefix}-tls.key";
file_put_contents($tlsfile, base64_decode($settings['tls']));
}
// write key files
if ($settings['mode'] != "server_user") {
$crtfile = "{$tempdir}/config/{$prefix}-{$user['name']}.crt";
file_put_contents($crtfile, base64_decode($cert['crt']));
$keyfile = "{$tempdir}/config/{$prefix}-{$user['name']}.key";
file_put_contents($keyfile, base64_decode($cert['prv']));
// convert to pkcs12 format
$p12file = "{$tempdir}/config/{$prefix}.p12";
if ($usetoken) {
openvpn_client_pem_to_pk12($p12file, $outpass, $crtfile, $keyfile);
} else {
openvpn_client_pem_to_pk12($p12file, $outpass, $crtfile, $keyfile, $cafile);
}
}
// 7zip the configuration data
chdir($tempdir);
$files = "config ";
if ($openvpnmanager) {
$files .= "openvpnmanager ";
}
$files .= "openvpn-install.exe ";
$files .= "openvpn-postinstall.exe ";
if ($usetoken) {
$procchain = ';!@Install@!UTF-8!
RunProgram="openvpn-postinstall.exe /Import"
;!@InstallEnd@!'
;
} else {
$procchain = ';!@Install@!UTF-8!
RunProgram="openvpn-postinstall.exe"
;!@InstallEnd@!';
}
file_put_contents("{$tempdir}/7zipConfig",$procchain);
exec("/usr/local/bin/7z -y a archive.7z {$files}");
// create the final installer
$outfile = "{$tempdir}-install.exe";
chdir('/tmp');
exec("/bin/cat {$tempdir}/7zS.sfx {$tempdir}/7zipConfig {$tempdir}/archive.7z > {$outfile}");
// cleanup
exec("/bin/rm -r {$tempdir}");
return $outfile;
}
function viscosity_openvpn_client_config_exporter($srvid, $usrid, $crtid, $useaddr, $verifyservercn, $randomlocalport, $usetoken, $outpass, $proxy, $openvpnmanager, $advancedoptions)
function viscosity_openvpn_client_config_exporter($srvid, $usrid, $crtid, $useaddr, $verifyservercn, $randomlocalport, $usetoken, $outpass, $proxy, $openvpnmanager, $advancedoptions, $compression_type)
{
global $config;
$uniq = uniqid();
$tempdir = "/tmp/openvpn-export-{$uniq}";
$zipfile = "/tmp/{$uniq}-Viscosity.visc.zip";
$validconfig = openvpn_client_export_validate_config($srvid, $usrid, $crtid);
if (!$validconfig) {
......@@ -678,12 +552,18 @@ EOF;
}
// Zip Viscosity file
exec("cd {$tempdir}/.. && /usr/local/bin/7z -tzip -y a {$zipfile} Viscosity.visc");
if ($compression_type == 'targz') {
$outputfile = "/tmp/{$uniq}-Viscosity.visz";
exec("cd {$tempdir}/.. && /usr/bin/tar cfz {$outputfile} Viscosity.visc");
} else {
$outputfile = "/tmp/{$uniq}-Viscosity.visc.zip";
exec("cd {$tempdir}/.. && /usr/local/bin/7z -tzip -y a {$outputfile} Viscosity.visc");
}
// Remove temporary directory
exec("rm -rf {$tempdir}");
return $zipfile;
return $outputfile;
}
function openvpn_client_export_sharedkey_config($srvid, $useaddr, $proxy, $zipconf = false)
......
......@@ -224,10 +224,10 @@ if (isset($config['openvpn']['openvpn-server'])) {
$exp_path = openvpn_client_export_config($srvid, $usrid, $crtid, $useaddr, $verifyservercn, $randomlocalport, $usetoken, $nokeys, $proxy, $expformat, $password, false, false, $openvpnmanager, $advancedoptions);
} elseif ($act == "visc") {
$exp_name = urlencode($exp_name."-Viscosity.visc.zip");
$exp_path = viscosity_openvpn_client_config_exporter($srvid, $usrid, $crtid, $useaddr, $verifyservercn, $randomlocalport, $usetoken, $password, $proxy, $openvpnmanager, $advancedoptions);
} elseif (substr($act, 0, 4) == "inst") {
$exp_name = urlencode($exp_name."-install.exe");
$exp_path = openvpn_client_export_installer($srvid, $usrid, $crtid, $useaddr, $verifyservercn, $randomlocalport, $usetoken, $password, $proxy, $openvpnmanager, $advancedoptions, substr($act, 5));
$exp_path = viscosity_openvpn_client_config_exporter($srvid, $usrid, $crtid, $useaddr, $verifyservercn, $randomlocalport, $usetoken, $password, $proxy, $openvpnmanager, $advancedoptions, 'zip');
} elseif ($act == "visz") {
$exp_name = urlencode($exp_name."-Viscosity.visz");
$exp_path = viscosity_openvpn_client_config_exporter($srvid, $usrid, $crtid, $useaddr, $verifyservercn, $randomlocalport, $usetoken, $password, $proxy, $openvpnmanager, $advancedoptions, 'targz');
} elseif ( $act == 'skconf') {
$exp_path = openvpn_client_export_sharedkey_config($srvid, $useaddr, $proxy, false);
$exp_name = urlencode($exp_name."-config.ovpn");
......@@ -559,9 +559,6 @@ if (isset($savemsg)) {
</div>
</td>
</tr>
<tr>
<td colspan="2" class="list" height="12">&nbsp;</td>
</tr>
<tr class="mode_server">
<td valign="top"><a id="help_for_advancedoptions" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Additional configuration options");?></td>
<td >
......@@ -604,14 +601,9 @@ if (isset($savemsg)) {
<option value="confinlineios"><?=gettext("OpenVPN Connect (iOS/Android)");?></option>
<option value="confinline"><?=gettext("Others");?></option>
</optgroup>
<optgroup label="<?=sprintf(gettext("Windows Installers (%s-Ix%s)"), $current_openvpn_version, $current_openvpn_version_rev);?>">
<option value="inst-x86-xp"><?=gettext("x86-xp");?></option>
<option value="inst-x64-xp"><?=gettext("x64-xp");?></option>
<option value="inst-x86-win6"><?=gettext("x86-win6");?></option>
<option value="inst-x64-win6"><?=gettext("x64-win6");?></option>
</optgroup>
<optgroup label="<?=gettext("Mac OSX");?>">
<option value="visc"><?=gettext("Viscosity Bundle");?></option>
<optgroup label="<?=gettext("Mac OSX / Windows");?>">
<option value="visc"><?=gettext("Viscosity Bundle (OSX)");?></option>
<option value="visz"><?=gettext("Viscosity Bundle (Windows)");?></option>
</optgroup>
</select>
</td>
......@@ -636,14 +628,9 @@ if (isset($savemsg)) {
<option value="confinlineios"><?=gettext("OpenVPN Connect (iOS/Android)");?></option>
<option value="confinline"><?=gettext("Others");?></option>
</optgroup>
<optgroup label="<?=sprintf(gettext("Windows Installers (%s-Ix%s)"), $current_openvpn_version, $current_openvpn_version_rev);?>">
<option value="inst-x86-xp"><?=gettext("x86-xp");?></option>
<option value="inst-x64-xp"><?=gettext("x64-xp");?></option>
<option value="inst-x86-win6"><?=gettext("x86-win6");?></option>
<option value="inst-x64-win6"><?=gettext("x64-win6");?></option>
</optgroup>
<optgroup label="<?=gettext("Mac OSX");?>">
<option value="visc"><?=gettext("Viscosity Bundle");?></option>
<optgroup label="<?=gettext("Mac OSX / Windows");?>">
<option value="visc"><?=gettext("Viscosity Bundle (OSX)");?></option>
<option value="visz"><?=gettext("Viscosity Bundle (Windows)");?></option>
</optgroup>
<?php
if ($server['mode'] == 'server_tls'):?>
......@@ -679,14 +666,9 @@ if (isset($savemsg)) {
<option value="confinlineios"><?=gettext("OpenVPN Connect (iOS/Android)");?></option>
<option value="confinline"><?=gettext("Others");?></option>
</optgroup>
<optgroup label="<?=sprintf(gettext("Windows Installers (%s-Ix%s)"), $current_openvpn_version, $current_openvpn_version_rev);?>">
<option value="inst-x86-xp"><?=gettext("x86-xp");?></option>
<option value="inst-x64-xp"><?=gettext("x64-xp");?></option>
<option value="inst-x86-win6"><?=gettext("x86-win6");?></option>
<option value="inst-x64-win6"><?=gettext("x64-win6");?></option>
</optgroup>
<optgroup label="<?=gettext("Mac OSX");?>">
<option value="visc"><?=gettext("Viscosity Bundle");?></option>
<optgroup label="<?=gettext("Mac OSX / Windows");?>">
<option value="visc"><?=gettext("Viscosity Bundle (OSX)");?></option>
<option value="visz"><?=gettext("Viscosity Bundle (Windows)");?></option>
</optgroup>
</select>
</td>
......@@ -715,19 +697,20 @@ if (isset($savemsg)) {
</tbody>
</table>
<div class="hidden" for="help_for_clientpkg">
<br/>
<?= gettext('The "XP" Windows installers work on Windows XP and later versions. The "win6" Windows installers include a new tap-windows6 driver that works only on Windows Vista and later.') ?><br/>
<br/><br/>
<strong><?= gettext("Links to OpenVPN clients for various platforms:") ?></strong><br/>
<a href="http://openvpn.net/index.php/open-source/downloads.html"><?= gettext("OpenVPN Community Client") ?></a> - <?=gettext("Binaries for Windows, Source for other platforms. Packaged above in the Windows Installers")?><br/>
<?= gettext("If you expect to see a certain client in the list but it is not there, it is usually due to a CA mismatch between the OpenVPN server instance and the client certificates found in the User Manager.") ?>
</div>
</td>
</tr>
<tr>
<td valign="top"><i class="fa fa-info-circle text-muted"></i> <?=gettext("Links to OpenVPN clients");?></td>
<td>
<a href="http://www.sparklabs.com/viscosity/"><?= gettext("Viscosity") ?></a> - <?= gettext("Recommended client for Mac OSX and Windows") ?><br/>
<a href="http://openvpn.net/index.php/open-source/downloads.html"><?= gettext("OpenVPN Community Client") ?></a> - <?=gettext("Binaries for Windows, Source for other platforms.")?><br/>
<a href="https://play.google.com/store/apps/details?id=de.blinkt.openvpn"><?= gettext("OpenVPN For Android") ?></a> - <?=gettext("Recommended client for Android")?><br/>
<a href="http://www.featvpn.com/"><?= gettext("FEAT VPN For Android") ?></a> - <?=gettext("For older versions of Android")?><br/>
<?= gettext("OpenVPN Connect") ?>: <a href="https://play.google.com/store/apps/details?id=net.openvpn.openvpn"><?=gettext("Android (Google Play)")?></a> or <a href="https://itunes.apple.com/us/app/openvpn-connect/id590379981"><?=gettext("iOS (App Store)")?></a> - <?= gettext("Recommended client for iOS") ?>
<br/><a href="http://www.sparklabs.com/viscosity/"><?= gettext("Viscosity") ?></a> - <?= gettext("Recommended client for Mac OSX") ?>
<br/><a href="http://code.google.com/p/tunnelblick/"><?= gettext("Tunnelblick") ?></a> - <?= gettext("Free client for OSX") ?>
<br/><br/>
<?= gettext("If you expect to see a certain client in the list but it is not there, it is usually due to a CA mismatch between the OpenVPN server instance and the client certificates found in the User Manager.") ?><br/>
</div>
<?= gettext("OpenVPN Connect") ?>: <a href="https://play.google.com/store/apps/details?id=net.openvpn.openvpn"><?=gettext("Android (Google Play)")?></a> or <a href="https://itunes.apple.com/us/app/openvpn-connect/id590379981"><?=gettext("iOS (App Store)")?></a> - <?= gettext("Recommended client for iOS") ?><br/>
<a href="http://code.google.com/p/tunnelblick/"><?= gettext("Tunnelblick") ?></a> - <?= gettext("Free client for OSX") ?>
</td>
</tr>
</table>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment