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.
567 lines
16 KiB
567 lines
16 KiB
/***************************************************************************
|
|
*
|
|
* knetworkmanager-openvpn.cpp - A NetworkManager frontend for KDE
|
|
*
|
|
* 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 <tqdbusdata.h>
|
|
|
|
#include "knetworkmanager-openvpn.h"
|
|
|
|
typedef KGenericFactory<OpenVPNPlugin> OpenVPNPluginFactory;
|
|
K_EXPORT_COMPONENT_FACTORY( knetworkmanager_openvpn, OpenVPNPluginFactory("knetworkmanager_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(const TQStringList& routes, const TQMap<TQString, TQString>& properties)
|
|
{
|
|
// 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);
|
|
_openvpnWidget->routes->setText(routes.join(" "));
|
|
}
|
|
}
|
|
|
|
TQMap<TQString, TQString>OpenVPNConfig::getVPNProperties()
|
|
{
|
|
// build a StingList of properties
|
|
TQMap<TQString, TQString> strlist;
|
|
|
|
strlist.insert("connection-type", TQString::number(OpenVPNConnectionType::mapConnectionType2String((OpenVPNConnectionType::CONNECTIONTYPE)_openvpnWidget->cboConnectionType->currentItem())));
|
|
strlist.insert("remote", TQString(_openvpnWidget->gateway->text()));
|
|
|
|
// port is not necessary
|
|
if (!_openvpnWidget->port->text().isEmpty() && !_openvpnWidget->chkDefaultPort->isChecked())
|
|
strlist.insert("port", _openvpnWidget->port->text());
|
|
|
|
strlist.insert("ca", TQString(_openvpnWidget->editCA->url()));
|
|
strlist.insert("cert",TQString(_openvpnWidget->editCert->url() ));
|
|
strlist.insert("key", TQString(_openvpnWidget->editKey->url()));
|
|
|
|
if (_openvpnWidget->chkUseCipher->isChecked())
|
|
strlist.insert("cipher", TQString(_openvpnWidget->cboCipher->currentText()));
|
|
|
|
if (_openvpnWidget->chkUseLZO->isChecked())
|
|
strlist.insert("comp-lzo", TQString("true"));
|
|
else
|
|
strlist.insert("comp-lzo", TQString("false"));
|
|
|
|
strlist.insert("static-key", TQString(_openvpnWidget->editSharedKey->url()));
|
|
strlist.insert("username", TQString(_openvpnWidget->editUsername->text()));
|
|
strlist.insert("local-ip", TQString(_openvpnWidget->editLocalIP->text()));
|
|
strlist.insert("remote-ip", TQString(_openvpnWidget->editRemoteIP->text()));
|
|
|
|
if (_openvpnWidget->chkUseTAP->isChecked()) {
|
|
strlist.insert("tap-dev", "true");
|
|
strlist.insert("proto-tcp", "true");
|
|
} else {
|
|
strlist.insert("tap-dev", "false");
|
|
strlist.insert("proto-tcp", "false");
|
|
}
|
|
|
|
if (_openvpnWidget->chkUseTLS->isChecked())
|
|
strlist.insert("ta", TQString(_openvpnWidget->editTLSAuth->url()));
|
|
|
|
strlist.insert("ta-dir", TQString(_openvpnWidget->cboDirection->currentText()));
|
|
|
|
return strlist;
|
|
}
|
|
|
|
TQStringList OpenVPNConfig::getVPNRoutes()
|
|
{
|
|
TQStringList strlist;
|
|
if(_openvpnWidget->chkIPAdresses->isChecked())
|
|
{
|
|
strlist = TQStringList::split(" ", _openvpnWidget->routes->text());
|
|
}
|
|
return strlist;
|
|
}
|
|
|
|
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(const TQStringList& /*routes*/, const TQMap<TQString, TQString>& properties)
|
|
{
|
|
// 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
TQMap<TQString, TQString> 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(TQString name, TQString value) {
|
|
if (name == TQString("password")) {
|
|
_openvpnAuth->editUserPassword->erase();
|
|
_openvpnAuth->editUserPassword->insert(value);
|
|
}
|
|
}
|
|
|
|
bool OpenVPNAuthentication::needsUserInteraction()
|
|
{
|
|
if ((_connectionType == OpenVPNConnectionType::PASSWORD) || (_connectionType == OpenVPNConnectionType::X509USERPASS))
|
|
return true;
|
|
return false;
|
|
}
|
|
|