/*************************************************************************** * * knetworkmanager-openvpn.cpp - A NetworkManager frontend for TDE * * Copyright (C) 2006 Novell, Inc. * * Author: Helmut Schaa , * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include "tdenetman-openvpn.h" typedef KGenericFactory 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::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::ConstIterator it = properties.begin(); it != properties.end(); ++it) { if (it.key() == "connection-type") { _connectionType = OpenVPNConnectionType::mapString2ConnectionType(it.data().toInt()); break; } } } TDENetworkSettingsMap OpenVPNAuthentication::getPasswords() { TQMap 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"