You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdenetworkmanager/tdenetworkmanager/vpn-plugins/openvpn/src/tdenetman-openvpn.cpp

603 lines
17 KiB

/***************************************************************************
*
* knetworkmanager-openvpn.cpp - A NetworkManager frontend for TDE
*
* Copyright (C) 2006 Novell, Inc.
*
* Author: Helmut Schaa <hschaa@suse.de>, <helmut.schaa@gmx.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/
#include <klocale.h>
#include <tqmessagebox.h>
#include <tqbutton.h>
#include <kcombobox.h>
#include <klineedit.h>
#include <kurlrequester.h>
#include <tqobjectlist.h>
#include <tqobject.h>
#include <tqcheckbox.h>
#include <kpassdlg.h>
#include <kgenericfactory.h>
#include <tqwidgetstack.h>
#include <tqfileinfo.h>
#include <tqhostaddress.h>
#include "tdenetman-openvpn.h"
typedef KGenericFactory<OpenVPNPlugin> OpenVPNPluginFactory;
K_EXPORT_COMPONENT_FACTORY( tdenetman_openvpn, OpenVPNPluginFactory("tdenetman_openvpn"));
/************************************
* OpenVPNPlugin
************************************/
OpenVPNPlugin::OpenVPNPlugin(TQObject* parent, const char* name, const TQStringList& args)
: VPNPlugin(parent, name, args)
{
}
OpenVPNPlugin::~OpenVPNPlugin()
{
}
VPNConfigWidget* OpenVPNPlugin::CreateConfigWidget(TQWidget* parent)
{
return new OpenVPNConfig(parent);
}
VPNAuthenticationWidget* OpenVPNPlugin::CreateAuthenticationWidget(TQWidget* parent)
{
return new OpenVPNAuthentication(parent);
}
/************************************
* OpenVPNConnectionType
************************************/
OpenVPNConnectionType::CONNECTIONTYPE OpenVPNConnectionType::mapString2ConnectionType(int prop)
{
if (prop == 0)
return X509;
else if (prop == 1)
return SHARED_KEY;
else if (prop == 2)
return PASSWORD;
else if (prop == 3)
return X509USERPASS;
return UNKNOWN;
}
int OpenVPNConnectionType::mapConnectionType2String(CONNECTIONTYPE connType)
{
switch(connType)
{
case X509:
return 0;
case SHARED_KEY:
return 1;
case PASSWORD:
return 2;
case X509USERPASS:
return 3;
default:
return -1;
}
return -1;
}
/************************************
* OpenVPNConfig
************************************/
OpenVPNConfig::OpenVPNConfig(TQWidget* parent)
: VPNConfigWidget(parent)
{
TQVBoxLayout* layout = new TQVBoxLayout(this, 1, 1);
_openvpnWidget = new OpenVPNConfigWidget(this);
layout->addWidget(_openvpnWidget);
connect(_openvpnWidget->chkUseCipher, TQT_SIGNAL(toggled(bool)), _openvpnWidget->cboCipher, TQT_SLOT(setEnabled(bool)));
connect(_openvpnWidget->chkUseTLS, TQT_SIGNAL(toggled(bool)), _openvpnWidget->cboDirection, TQT_SLOT(setEnabled(bool)));
connect(_openvpnWidget->chkUseTLS, TQT_SIGNAL(toggled(bool)), _openvpnWidget->editTLSAuth, TQT_SLOT(setEnabled(bool)));
connect(_openvpnWidget->chkIPAdresses, TQT_SIGNAL(toggled(bool)), _openvpnWidget->routes, TQT_SLOT(setEnabled(bool)));
// add all Cipher modes to the Combobox
getCipherModes();
// switch to the right configuration interface when selecting the connection type
connect(_openvpnWidget->cboConnectionType, TQT_SIGNAL( activated(int)), _openvpnWidget->widgetStack, TQT_SLOT(raiseWidget(int)));
this->languageChange();
}
OpenVPNConfig::~OpenVPNConfig()
{
}
void OpenVPNConfig::languageChange()
{
_openvpnWidget->cboConnectionType->insertItem(i18n("X.509 Certificates"), OpenVPNConnectionType::X509 );
_openvpnWidget->cboConnectionType->insertItem(i18n("Pre-shared key") , OpenVPNConnectionType::SHARED_KEY );
_openvpnWidget->cboConnectionType->insertItem(i18n("Password Authentication") , OpenVPNConnectionType::PASSWORD );
_openvpnWidget->cboConnectionType->insertItem(i18n("X.509 with Password Authentication") , OpenVPNConnectionType::X509USERPASS );
_openvpnWidget->cboDirection->insertItem(i18n("none"));
_openvpnWidget->cboDirection->insertItem(i18n("0"));
_openvpnWidget->cboDirection->insertItem(i18n("1"));
}
TQString OpenVPNConfig::findOpenVPNBinary()
{
static const char *openvpn_binary_paths[] =
{
"/usr/sbin/openvpn",
"/sbin/openvpn",
NULL
};
const char **openvpn_binary = openvpn_binary_paths;
while (*openvpn_binary != NULL) {
if ( TQFileInfo(*openvpn_binary).exists())
break;
openvpn_binary++;
}
return *openvpn_binary;
}
void OpenVPNConfig::receiveCipherData(KProcess*, char* buffer, int len)
{
// add possible cipher modes to the combobox
TQStringList cipherModes = TQStringList::split("\n", TQString::fromLatin1(buffer, len), false );
for (TQStringList::ConstIterator it = cipherModes.begin(); it != cipherModes.end(); ++it)
{
_openvpnWidget->cboCipher->insertItem((*it));
}
}
void OpenVPNConfig::getCipherModes()
{
// get all possible cipher modes
TQString openvpn = findOpenVPNBinary();
if (!openvpn.isNull()) {
KProcess* cipherHelper = new KProcess();
cipherHelper->setUseShell(true, "/bin/sh");
*cipherHelper << TQString::fromLatin1("%1 --show-ciphers | awk '/^[A-Z][A-Z0-9]+-/ { print $1 }'").arg(openvpn);
connect (cipherHelper, TQT_SIGNAL(receivedStdout(KProcess*, char*, int)), this, TQT_SLOT(receiveCipherData(KProcess*, char*, int)));
kdDebug() << "starting openvpn to get cipher modes" << endl;
if (!cipherHelper->start(KProcess::Block, KProcess::Stdout)) {
kdDebug() << "error starting openvpn" << endl;
}
}
}
void OpenVPNConfig::setVPNData(TDENetworkSingleRouteConfigurationList& routes, TDENetworkSettingsMap& properties, TDENetworkSettingsMap& secrets)
{
m_vpnProperties = properties;
m_vpnSecrets = secrets;
// fill up our inputfields
for(TQMap<TQString, TQString>::ConstIterator it = properties.begin(); it != properties.end(); ++it)
{
TQString entry = it.key();
TQString value = it.data();
if (entry == "connection-type")
{
OpenVPNConnectionType::CONNECTIONTYPE type = OpenVPNConnectionType::mapString2ConnectionType(value.toInt());
_openvpnWidget->cboConnectionType->setCurrentItem(type);
_openvpnWidget->widgetStack->raiseWidget(type);
}
else if (entry == "remote")
{
_openvpnWidget->gateway->setText(value);
}
else if (entry == "port")
{
if (value.toInt() > 0)
{
_openvpnWidget->port->setText(value);
_openvpnWidget->chkDefaultPort->setChecked(false);
}
else
{
_openvpnWidget->chkDefaultPort->setChecked(true);
}
}
else if (entry == "proto" || entry == "proto-tcp")
{
_openvpnWidget->chkUseTCP->setChecked( value == "yes");
}
else if (entry == "ca")
{
_openvpnWidget->editCA->setURL(value);
}
else if (entry == "cert")
{
_openvpnWidget->editCert->setURL(value);
}
else if (entry == "key")
{
_openvpnWidget->editKey->setURL(value);
}
else if (entry == "cipher")
{
_openvpnWidget->chkUseCipher->setChecked(true);
_openvpnWidget->cboCipher->setCurrentItem(value);
}
else if (entry == "comp-lzo")
{
_openvpnWidget->chkUseLZO->setChecked(value == "true");
}
else if (entry == "shared-key" || entry == "static-key")
{
_openvpnWidget->editSharedKey->setURL(value);
}
else if (entry == "username")
{
_openvpnWidget->editUsername->setText(value);
}
else if (entry == "local-ip")
{
_openvpnWidget->editLocalIP->setText(value);
}
else if (entry == "remote-ip")
{
_openvpnWidget->editRemoteIP->setText(value);
}
else if (entry == "dev" || entry == "tap-dev") {
_openvpnWidget->chkUseTAP->setChecked(value == "true");
}
else if (entry == "ta")
{
_openvpnWidget->chkUseTLS->setChecked(true);
_openvpnWidget->editTLSAuth->setURL(value);
}
else if (entry == "ta-dir")
{
_openvpnWidget->cboDirection->setCurrentItem(value);
}
else
{
kdDebug() << TQString("OpenVPN: Property '%1' not handled").arg(entry) << endl;
}
}
// set routes
if (!routes.empty())
{
_openvpnWidget->chkIPAdresses->setChecked(true);
TQStringList routesText;
for (TDENetworkSingleRouteConfigurationList::Iterator it = routes.begin(); it != routes.end(); ++it) {
routesText.append(TQString("%1/%2").arg((*it).ipAddress.toString()).arg((*it).networkMask.toCIDRMask()));
}
_openvpnWidget->routes->setText(routesText.join(" "));
}
}
TDENetworkSettingsMap OpenVPNConfig::getVPNProperties()
{
// Build a list of properties
m_vpnProperties.insert("connection-type", TQString::number(OpenVPNConnectionType::mapConnectionType2String((OpenVPNConnectionType::CONNECTIONTYPE)_openvpnWidget->cboConnectionType->currentItem())));
m_vpnProperties.insert("remote", TQString(_openvpnWidget->gateway->text()));
// port is not necessary
if (!_openvpnWidget->port->text().isEmpty() && !_openvpnWidget->chkDefaultPort->isChecked()) {
m_vpnProperties.insert("port", _openvpnWidget->port->text());
}
else {
m_vpnProperties.remove("port");
}
m_vpnProperties.insert("ca", TQString(_openvpnWidget->editCA->url()));
m_vpnProperties.insert("cert",TQString(_openvpnWidget->editCert->url() ));
m_vpnProperties.insert("key", TQString(_openvpnWidget->editKey->url()));
if (_openvpnWidget->chkUseCipher->isChecked()) {
m_vpnProperties.insert("cipher", TQString(_openvpnWidget->cboCipher->currentText()));
}
else {
m_vpnProperties.remove("cipher");
}
if (_openvpnWidget->chkUseLZO->isChecked()) {
m_vpnProperties.insert("comp-lzo", TQString("true"));
}
else {
m_vpnProperties.insert("comp-lzo", TQString("false"));
}
m_vpnProperties.insert("static-key", TQString(_openvpnWidget->editSharedKey->url()));
m_vpnProperties.insert("username", TQString(_openvpnWidget->editUsername->text()));
m_vpnProperties.insert("local-ip", TQString(_openvpnWidget->editLocalIP->text()));
m_vpnProperties.insert("remote-ip", TQString(_openvpnWidget->editRemoteIP->text()));
if (_openvpnWidget->chkUseTAP->isChecked()) {
m_vpnProperties.insert("tap-dev", "true");
m_vpnProperties.insert("proto-tcp", "true");
}
else {
m_vpnProperties.insert("tap-dev", "false");
m_vpnProperties.insert("proto-tcp", "false");
}
if (_openvpnWidget->chkUseTLS->isChecked()) {
m_vpnProperties.insert("ta", TQString(_openvpnWidget->editTLSAuth->url()));
}
else {
m_vpnProperties.remove("ta");
}
m_vpnProperties.insert("ta-dir", TQString(_openvpnWidget->cboDirection->currentText()));
return m_vpnProperties;
}
TDENetworkSettingsMap OpenVPNConfig::getVPNSecrets() {
// Build a list of secrets
// FIXME
return m_vpnSecrets;
}
TDENetworkSingleRouteConfigurationList OpenVPNConfig::getVPNRoutes()
{
TDENetworkSingleRouteConfigurationList ret;
TQStringList strlist;
if(_openvpnWidget->chkIPAdresses->isChecked()) {
strlist = TQStringList::split(" ", _openvpnWidget->routes->text());
}
for (TQStringList::Iterator it = strlist.begin(); it != strlist.end(); ++it) {
TQStringList pieces = TQStringList::split("/", (*it));
TDENetworkSingleRouteConfiguration routeconfig;
routeconfig.ipAddress.setAddress(pieces[0]);
if (pieces.count() > 1) {
routeconfig.networkMask.fromCIDRMask(pieces[1].toUInt());
}
ret.append(routeconfig);
}
return ret;
}
bool OpenVPNConfig::hasChanged()
{
return true;
}
bool OpenVPNConfig::isValid(TQStringList& err_msg)
{
bool retval = true;
// check gateway
if (_openvpnWidget->gateway->text().isEmpty())
{
err_msg.append(i18n("You have to specify a gateway"));
retval = false;
}
bool ok = false;
_openvpnWidget->port->text().toULong(&ok);
if (!ok && !_openvpnWidget->port->text().isEmpty() )
{
err_msg.append(i18n("The port number has to be numeric"));
retval = false;
}
switch(_openvpnWidget->cboConnectionType->currentItem())
{
case OpenVPNConnectionType::X509:
// check if ca file is correct
if (_openvpnWidget->editCA->url().isEmpty())
{
retval = false;
err_msg.append(i18n("no CA file provided"));
}
else if (!TQFileInfo(_openvpnWidget->editCA->url()).isFile())
{
retval = false;
err_msg.append(i18n("CA file not valid"));
}
// check if cert file is correct
if (_openvpnWidget->editCert->url().isEmpty())
{
retval = false;
err_msg.append(i18n("no CERT file provided"));
}
else if (!TQFileInfo(_openvpnWidget->editCert->url()).isFile())
{
retval = false;
err_msg.append(i18n("CERT file not valid"));
}
// check if key file is correct
if (_openvpnWidget->editKey->url().isEmpty())
{
retval = false;
err_msg.append(i18n("no Key file provided"));
}
else if (!TQFileInfo(_openvpnWidget->editKey->url()).isFile())
{
retval = false;
err_msg.append(i18n("Key file not valid"));
}
break;
case OpenVPNConnectionType::SHARED_KEY:
// check if a shared key is selected
if (_openvpnWidget->editSharedKey->url().isEmpty())
{
retval = false;
err_msg.append(i18n("Please provide a valid shared key"));
}
// check if the shared key file exists
else if (!TQFileInfo(_openvpnWidget->editSharedKey->url()).exists())
{
retval = false;
err_msg.append(i18n("Please provide a valid shared key"));
}
// check if local ip is valid
if (!TQHostAddress().setAddress(_openvpnWidget->editLocalIP->text()))
{
retval = false;
err_msg.append(i18n("local IP is invalid"));
}
// check if remote ip is valid
if (!TQHostAddress().setAddress(_openvpnWidget->editRemoteIP->text()))
{
retval = false;
err_msg.append(i18n("remote IP is invalid"));
}
break;
case OpenVPNConnectionType::PASSWORD:
// check if username is suplied
if (_openvpnWidget->editUsername->text().isEmpty())
{
retval = false;
err_msg.append(i18n("no username provided"));
}
// check if ca file is correct
if (_openvpnWidget->editCA->url().isEmpty())
{
retval = false;
err_msg.append(i18n("no CA file provided"));
}
else if (!TQFileInfo(_openvpnWidget->editCA->url()).isFile())
{
retval = false;
err_msg.append(i18n("CA file not valid"));
}
break;
case OpenVPNConnectionType::X509USERPASS:
// check if username is suplied
if (_openvpnWidget->editUsername->text().isEmpty())
{
retval = false;
err_msg.append(i18n("no username provided"));
}
// check if ca file is correct
if (_openvpnWidget->editCA->url().isEmpty())
{
retval = false;
err_msg.append(i18n("no CA file provided"));
}
else if (!TQFileInfo(_openvpnWidget->editCA->url()).isFile())
{
retval = false;
err_msg.append(i18n("CA file not valid"));
}
// check if cert file is correct
if (_openvpnWidget->editCert->url().isEmpty())
{
retval = false;
err_msg.append(i18n("no CERT file provided"));
}
else if (!TQFileInfo(_openvpnWidget->editCert->url()).isFile())
{
retval = false;
err_msg.append(i18n("CERT file not valid"));
}
// check if key file is correct
if (_openvpnWidget->editKey->url().isEmpty())
{
retval = false;
err_msg.append(i18n("no Key file provided"));
}
else if (!TQFileInfo(_openvpnWidget->editKey->url()).isFile())
{
retval = false;
err_msg.append(i18n("Key file not valid"));
}
break;
}
return retval;
}
/************************************
* OpenVPNAuthentication
************************************/
OpenVPNAuthentication::OpenVPNAuthentication(TQWidget* parent, char* name)
: VPNAuthenticationWidget(parent, name)
{
TQVBoxLayout* layout = new TQVBoxLayout(this, 1, 1);
_openvpnAuth = new OpenVPNAuthenticationWidget(this);
layout->addWidget(_openvpnAuth);
}
OpenVPNAuthentication::~OpenVPNAuthentication()
{
}
void OpenVPNAuthentication::setVPNData(TDENetworkSingleRouteConfigurationList& /*routes*/, TDENetworkSettingsMap& properties, TDENetworkSettingsMap& secrets)
{
// find the connection type property
for(TQMap<TQString, TQString>::ConstIterator it = properties.begin(); it != properties.end(); ++it)
{
if (it.key() == "connection-type")
{
_connectionType = OpenVPNConnectionType::mapString2ConnectionType(it.data().toInt());
break;
}
}
}
TDENetworkSettingsMap OpenVPNAuthentication::getPasswords()
{
TQMap<TQString, TQString> pwds;
if ((_connectionType == OpenVPNConnectionType::PASSWORD) || (_connectionType == OpenVPNConnectionType::X509USERPASS))
pwds.insert("password", TQString(_openvpnAuth->editUserPassword->password()));
else
pwds.insert("no-secret", TQString("true"));
return pwds;
}
void OpenVPNAuthentication::setPasswords(TDENetworkSettingsMap secrets) {
if (secrets.contains("password")) {
_openvpnAuth->editUserPassword->erase();
_openvpnAuth->editUserPassword->insert(secrets["password"]);
}
}
bool OpenVPNAuthentication::needsUserInteraction()
{
if ((_connectionType == OpenVPNConnectionType::PASSWORD) || (_connectionType == OpenVPNConnectionType::X509USERPASS))
return true;
return false;
}
#include "tdenetman-openvpn.moc"