diff options
Diffstat (limited to 'kopete/plugins/smpppdcs/libsmpppdclient')
9 files changed, 683 insertions, 0 deletions
diff --git a/kopete/plugins/smpppdcs/libsmpppdclient/Makefile.am b/kopete/plugins/smpppdcs/libsmpppdclient/Makefile.am new file mode 100644 index 00000000..9fc9258c --- /dev/null +++ b/kopete/plugins/smpppdcs/libsmpppdclient/Makefile.am @@ -0,0 +1,10 @@ +AM_CPPFLAGS = $(all_includes) + +noinst_LTLIBRARIES = libsmpppdclient.la +libsmpppdclient_la_LDFLAGS = -avoid-version $(all_libraries) + +noinst_HEADERS = smpppdclient.h smpppdstate.h smpppdready.h smpppdunsettled.h +libsmpppdclient_la_SOURCES = smpppdclient.cpp smpppdstate.cpp smpppdready.cpp \ + smpppdunsettled.cpp + +libsmpppdclient_la_LIBADD = -lcrypto diff --git a/kopete/plugins/smpppdcs/libsmpppdclient/smpppdclient.cpp b/kopete/plugins/smpppdcs/libsmpppdclient/smpppdclient.cpp new file mode 100644 index 00000000..d386b669 --- /dev/null +++ b/kopete/plugins/smpppdcs/libsmpppdclient/smpppdclient.cpp @@ -0,0 +1,104 @@ +/* + smpppdclient.cpp + + Copyright (c) 2006 by Heiko Schaefer <heiko@rangun.de> + + Kopete (c) 2002-2006 by the Kopete developers <kopete-devel@kde.org> + + ************************************************************************* + * * + * 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; version 2 of the License. * + * * + ************************************************************************* +*/ + +#include <kstreamsocket.h> + +#include "smpppdunsettled.h" +#include "smpppdclient.h" + +using namespace SMPPPD; + +Client::Client() + : m_state(NULL), m_sock(NULL), m_serverID(QString::null), m_serverVer(QString::null), m_password(QString::null) { + changeState(Unsettled::instance()); +} + +Client::~Client() { + disconnect(); +} + +bool Client::connect(const QString& server, uint port) { + return m_state->connect(this, server, port); +} + +void Client::disconnect() { + m_state->disconnect(this); +} + +QStringList Client::getInterfaceConfigurations() { + return m_state->getInterfaceConfigurations(this); +} + +bool Client::statusInterface(const QString& ifcfg) { + return m_state->statusInterface(this, ifcfg); +} + +QString Client::serverID() const { + return m_serverID; +} + +QString Client::serverVersion() const { + return m_serverVer; +} + +QStringList Client::read() const { + QStringList qsl; + + if(isReady()) { + QDataStream stream(m_sock); + char s[1024]; + + stream.readRawBytes(s, 1023); + char *sp = s; + + for(int i = 0; i < 1024; i++) { + if(s[i] == '\n') { + s[i] = 0; + qsl.push_back(sp); + sp = &(s[i+1]); + } + } + } + + return qsl; +} + +void Client::write(const char * cmd) { + if(isReady()) { + QDataStream stream(m_sock); + stream.writeRawBytes(cmd, strlen(cmd)); + stream.writeRawBytes("\n", strlen("\n")); + m_sock->flush(); + } +} + +bool Client::isReady() const { + return m_sock && m_sock->state() == KNetwork::KStreamSocket::Connected; +} + +bool Client::isOnline() { + + if(isReady()) { + QStringList ifcfgs = getInterfaceConfigurations(); + for(uint i = 0; i < ifcfgs.count(); i++) { + if(statusInterface(ifcfgs[i])) { + return true; + } + } + } + + return false; +} diff --git a/kopete/plugins/smpppdcs/libsmpppdclient/smpppdclient.h b/kopete/plugins/smpppdcs/libsmpppdclient/smpppdclient.h new file mode 100644 index 00000000..a123cd4c --- /dev/null +++ b/kopete/plugins/smpppdcs/libsmpppdclient/smpppdclient.h @@ -0,0 +1,80 @@ +/* + smpppdclient.h + + Copyright (c) 2006 by Heiko Schaefer <heiko@rangun.de> + + Kopete (c) 2002-2006 by the Kopete developers <kopete-devel@kde.org> + + ************************************************************************* + * * + * 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; version 2 of the License. * + * * + ************************************************************************* +*/ + +#ifndef SMPPPDCLIENT_H +#define SMPPPDCLIENT_H + +#include <qstringlist.h> + +namespace KNetwork { +class KStreamSocket; +}; + +namespace SMPPPD { + +class State; + +/** + @author Heiko Schaefer <heiko@rangun.de> +*/ +class Client { + Client(const Client&); + Client& operator=(const Client&); + +public: + Client(); + ~Client(); + + bool isReady() const; + + bool connect(const QString& server, uint port = 3185); + void disconnect(); + + QStringList getInterfaceConfigurations(); + bool statusInterface(const QString& ifcfg); + + bool isOnline(); + QString serverID() const; + QString serverVersion() const; + + void setPassword(const QString& password); + +private: + friend class State; + + void changeState(State * newState); + QStringList read() const; + void write(const char * cmd); + +private: + State * m_state; + KNetwork::KStreamSocket * m_sock; + QString m_serverID; + QString m_serverVer; + QString m_password; +}; + +inline void Client::changeState(State * newState) { + m_state = newState; +} + +inline void Client::setPassword(const QString& password) { + m_password = password; +} + +}; + +#endif diff --git a/kopete/plugins/smpppdcs/libsmpppdclient/smpppdready.cpp b/kopete/plugins/smpppdcs/libsmpppdclient/smpppdready.cpp new file mode 100644 index 00000000..421914bb --- /dev/null +++ b/kopete/plugins/smpppdcs/libsmpppdclient/smpppdready.cpp @@ -0,0 +1,104 @@ +/* + smpppdready.cpp + + Copyright (c) 2006 by Heiko Schaefer <heiko@rangun.de> + + Kopete (c) 2002-2006 by the Kopete developers <kopete-devel@kde.org> + + ************************************************************************* + * * + * 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; version 2 of the License. * + * * + ************************************************************************* +*/ + +#include <qregexp.h> + +#include <kdebug.h> +#include <kstreamsocket.h> + +#include "smpppdunsettled.h" +#include "smpppdclient.h" +#include "smpppdready.h" + +using namespace SMPPPD; + +Ready * Ready::m_instance = NULL; + +Ready::Ready() {} + +Ready::~Ready() {} + +Ready * Ready::instance() { + if(!m_instance) { + m_instance = new Ready; + } + + return m_instance; +} + +void Ready::disconnect(Client * client) { + kdDebug(14312) << k_funcinfo << endl; + if(socket(client)) { + socket(client)->flush(); + socket(client)->close(); + + delete socket(client); + setSocket(client, NULL); + + setServerID(client, QString::null); + setServerVersion(client, QString::null); + } + + changeState(client, Unsettled::instance()); +} + +QStringList Ready::getInterfaceConfigurations(Client * client) { + + QStringList ifcfgs; + + // we want all ifcfgs + kdDebug(14312) << k_funcinfo << "smpppd req: list-ifcfgs" << endl; + write(client, "list-ifcfgs"); + QStringList stream = read(client); + kdDebug(14312) << k_funcinfo << "smpppd ack: " << stream[0] << endl; + if(stream[0].startsWith("ok")) { + // we have now a QStringList with all ifcfgs + // we extract them and put them in the global ifcfgs-list + // stream[1] tells us how many ifcfgs are coming next + QRegExp numIfcfgsRex("^BEGIN IFCFGS ([0-9]+).*"); + if(numIfcfgsRex.exactMatch(stream[1])) { + int count_ifcfgs = numIfcfgsRex.cap(1).toInt(); + kdDebug(14312) << k_funcinfo << "ifcfgs: " << count_ifcfgs << endl; + + for(int i = 0; i < count_ifcfgs; i++) { + QRegExp ifcfgRex("^i \"(ifcfg-[a-zA-Z]+[0-9]+)\".*"); + if(ifcfgRex.exactMatch(stream[i+2])) { + ifcfgs.push_back(ifcfgRex.cap(1)); + } + } + } + } + + return ifcfgs; +} + +bool Ready::statusInterface(Client * client, const QString& ifcfg) { + + QString cmd = "list-status " + ifcfg; + + write(client, cmd.latin1()); + socket(client)->waitForMore(0); + + QStringList stream = read(client); + + if(stream[0].startsWith("ok")) { + if(stream[2].startsWith("status connected")) { + return true; + } + } + + return false; +} diff --git a/kopete/plugins/smpppdcs/libsmpppdclient/smpppdready.h b/kopete/plugins/smpppdcs/libsmpppdclient/smpppdready.h new file mode 100644 index 00000000..9ec3ab93 --- /dev/null +++ b/kopete/plugins/smpppdcs/libsmpppdclient/smpppdready.h @@ -0,0 +1,49 @@ +/* + smpppdready.h + + Copyright (c) 2006 by Heiko Schaefer <heiko@rangun.de> + + Kopete (c) 2002-2006 by the Kopete developers <kopete-devel@kde.org> + + ************************************************************************* + * * + * 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; version 2 of the License. * + * * + ************************************************************************* +*/ + +#ifndef SMPPPDREADY_H +#define SMPPPDREADY_H + +#include "smpppdstate.h" + +namespace SMPPPD { + +/** + @author Heiko Schaefer <heiko@rangun.de> +*/ +class Ready : public State +{ + Ready(const Ready&); + Ready& operator=(const Ready&); + + Ready(); + +public: + virtual ~Ready(); + + static Ready * instance(); + + virtual void disconnect(Client * client); + virtual QStringList getInterfaceConfigurations(Client * client); + virtual bool statusInterface(Client * client, const QString& ifcfg); + +private: + static Ready * m_instance; +}; + +}; + +#endif diff --git a/kopete/plugins/smpppdcs/libsmpppdclient/smpppdstate.cpp b/kopete/plugins/smpppdcs/libsmpppdclient/smpppdstate.cpp new file mode 100644 index 00000000..9e4bd508 --- /dev/null +++ b/kopete/plugins/smpppdcs/libsmpppdclient/smpppdstate.cpp @@ -0,0 +1,76 @@ +/* + smpppdstate.cpp + + Copyright (c) 2006 by Heiko Schaefer <heiko@rangun.de> + + Kopete (c) 2002-2006 by the Kopete developers <kopete-devel@kde.org> + + ************************************************************************* + * * + * 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; version 2 of the License. * + * * + ************************************************************************* +*/ + +#include <kstreamsocket.h> + +#include "smpppdclient.h" +#include "smpppdstate.h" + +using namespace SMPPPD; + +State::State() {} + +State::~State() {} + +QStringList State::read(Client * client) const { + return client->read(); +} + +void State::write(Client * client, const char * cmd) { + client->write(cmd); +} + +void State::changeState(Client * client, State * state) { + client->changeState(state); +} + +KNetwork::KStreamSocket * State::socket(Client * client) const { + return client->m_sock; +} + +QString State::password(Client * client) const { + return client->m_password; +} + +void State::setPassword(Client * client, const QString& pass) { + client->m_password = pass; +} + +void State::setServerID(Client * client, const QString& id) { + client->m_serverID = id; +} + +void State::setServerVersion(Client * client, const QString& ver) { + client->m_serverVer = ver; +} + +void State::setSocket(Client * client, KNetwork::KStreamSocket * sock) { + client->m_sock = sock; +} + +bool State::connect(Client * /* client */, const QString& /* server */, uint /* port */) { + return false; +} + +void State::disconnect(Client * /* client */) {} + +QStringList State::getInterfaceConfigurations(Client * /* client */) { + return QStringList(); +} + +bool State::statusInterface(Client * /* client */, const QString& /* ifcfg */) { + return false; +} diff --git a/kopete/plugins/smpppdcs/libsmpppdclient/smpppdstate.h b/kopete/plugins/smpppdcs/libsmpppdclient/smpppdstate.h new file mode 100644 index 00000000..0e7d393b --- /dev/null +++ b/kopete/plugins/smpppdcs/libsmpppdclient/smpppdstate.h @@ -0,0 +1,58 @@ +/* + smpppdstate.h + + Copyright (c) 2006 by Heiko Schaefer <heiko@rangun.de> + + Kopete (c) 2002-2006 by the Kopete developers <kopete-devel@kde.org> + + ************************************************************************* + * * + * 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; version 2 of the License. * + * * + ************************************************************************* +*/ + +#ifndef SMPPPDSTATE_H +#define SMPPPDSTATE_H + +#include <qstringlist.h> + +namespace SMPPPD { + +class Client; + +/** + @author Heiko Schaefer <heiko@rangun.de> +*/ +class State { + State(const State&); + State& operator=(const State&); + +public: + State(); + virtual ~State(); + + virtual bool connect(Client * client, const QString& server, uint port = 3185); + virtual void disconnect(Client * client); + + virtual QStringList getInterfaceConfigurations(Client * client); + virtual bool statusInterface(Client * client, const QString& ifcfg); + +protected: + QStringList read(Client * client) const; + void write(Client * client, const char * cmd); + void changeState(Client * client, State * state); + KNetwork::KStreamSocket * socket(Client * client) const; + void setSocket(Client * client, KNetwork::KStreamSocket * sock); + QString password(Client * client) const; + void setPassword(Client * client, const QString& pass); + void setServerID(Client * client, const QString& id); + void setServerVersion(Client * client, const QString& ver); + +}; + +}; + +#endif diff --git a/kopete/plugins/smpppdcs/libsmpppdclient/smpppdunsettled.cpp b/kopete/plugins/smpppdcs/libsmpppdclient/smpppdunsettled.cpp new file mode 100644 index 00000000..7ed5f516 --- /dev/null +++ b/kopete/plugins/smpppdcs/libsmpppdclient/smpppdunsettled.cpp @@ -0,0 +1,153 @@ +/* + smpppdunsettled.cpp + + Copyright (c) 2006 by Heiko Schaefer <heiko@rangun.de> + + Kopete (c) 2002-2006 by the Kopete developers <kopete-devel@kde.org> + + ************************************************************************* + * * + * 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; version 2 of the License. * + * * + ************************************************************************* +*/ + +#include <cstdlib> +#include <openssl/md5.h> + +#include <qregexp.h> + +#include <kdebug.h> +#include <kstreamsocket.h> + +#include "smpppdready.h" +#include "smpppdunsettled.h" + +using namespace SMPPPD; + +Unsettled * Unsettled::m_instance = NULL; + +Unsettled::Unsettled() {} + +Unsettled::~Unsettled() {} + +Unsettled * Unsettled::instance() { + if(!m_instance) { + m_instance = new Unsettled(); + } + + return m_instance; +} + +bool Unsettled::connect(Client * client, const QString& server, uint port) { + if(!socket(client) || + socket(client)->state() != KNetwork::KStreamSocket::Connected || + socket(client)->state() != KNetwork::KStreamSocket::Connecting) { + + QString resolvedServer = server; + + changeState(client, Ready::instance()); + disconnect(client); + + // since a lookup on a non-existant host can take a lot of time we + // try to get the IP of server before and we do the lookup ourself + KNetwork::KResolver resolver(server); + resolver.start(); + if(resolver.wait(500)) { + KNetwork::KResolverResults results = resolver.results(); + if(!results.empty()) { + QString ip = results[0].address().asInet().ipAddress().toString(); + kdDebug(14312) << k_funcinfo << "Found IP-Address for " << server << ": " << ip << endl; + resolvedServer = ip; + } else { + kdWarning(14312) << k_funcinfo << "No IP-Address found for " << server << endl; + return false; + } + } else { + kdWarning(14312) << k_funcinfo << "Looking up hostname timed out, consider to use IP or correct host" << endl; + return false; + } + + setSocket(client, new KNetwork::KStreamSocket(resolvedServer, QString::number(port))); + socket(client)->setBlocking(TRUE); + + if(!socket(client)->connect()) { + kdDebug(14312) << k_funcinfo << "Socket Error: " << KNetwork::KStreamSocket::errorString(socket(client)->error()) << endl; + } else { + kdDebug(14312) << k_funcinfo << "Successfully connected to smpppd \"" << server << ":" << port << "\"" << endl; + + static QString verRex = "^SuSE Meta pppd \\(smpppd\\), Version (.*)$"; + static QString clgRex = "^challenge = (.*)$"; + + QRegExp ver(verRex); + QRegExp clg(clgRex); + + QString response = read(client)[0]; + + if(response != QString::null && + ver.exactMatch(response)) { + setServerID(client, response); + setServerVersion(client, ver.cap(1)); + changeState(client, Ready::instance()); + return true; + } else if(response != QString::null && + clg.exactMatch(response)) { + if(password(client) != QString::null) { + // we are challenged, ok, respond + write(client, QString("response = %1\n").arg(make_response(clg.cap(1).stripWhiteSpace(), password(client))).latin1()); + response = read(client)[0]; + if(ver.exactMatch(response)) { + setServerID(client, response); + setServerVersion(client, ver.cap(1)); + return true; + } else { + kdWarning(14312) << k_funcinfo << "SMPPPD responded: " << response << endl; + changeState(client, Ready::instance()); + disconnect(client); + } + } else { + kdWarning(14312) << k_funcinfo << "SMPPPD requested a challenge, but no password was supplied!" << endl; + changeState(client, Ready::instance()); + disconnect(client); + } + } + } + } + + return false; +} + +QString Unsettled::make_response(const QString& chex, const QString& password) const { + + int size = chex.length (); + if (size & 1) + return "error"; + size >>= 1; + + // convert challenge from hex to bin + QString cbin; + for (int i = 0; i < size; i++) { + QString tmp = chex.mid (2 * i, 2); + cbin.append ((char) strtol (tmp.ascii (), 0, 16)); + } + + // calculate response + unsigned char rbin[MD5_DIGEST_LENGTH]; + MD5state_st md5; + MD5_Init (&md5); + MD5_Update (&md5, cbin.ascii (), size); + MD5_Update (&md5, password.ascii(), password.length ()); + MD5_Final (rbin, &md5); + + // convert response from bin to hex + QString rhex; + for (int i = 0; i < MD5_DIGEST_LENGTH; i++) { + char buffer[3]; + snprintf (buffer, 3, "%02x", rbin[i]); + rhex.append (buffer); + } + + return rhex; +} diff --git a/kopete/plugins/smpppdcs/libsmpppdclient/smpppdunsettled.h b/kopete/plugins/smpppdcs/libsmpppdclient/smpppdunsettled.h new file mode 100644 index 00000000..57a83752 --- /dev/null +++ b/kopete/plugins/smpppdcs/libsmpppdclient/smpppdunsettled.h @@ -0,0 +1,49 @@ +/* + smpppdunsettled.h + + Copyright (c) 2006 by Heiko Schaefer <heiko@rangun.de> + + Kopete (c) 2002-2006 by the Kopete developers <kopete-devel@kde.org> + + ************************************************************************* + * * + * 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; version 2 of the License. * + * * + ************************************************************************* +*/ + +#ifndef SMPPPDSMPPPDUNSETTLED_H +#define SMPPPDSMPPPDUNSETTLED_H + +#include "smpppdstate.h" + +namespace SMPPPD { + +/** + @author Heiko Schaefer <heiko@rangun.de> +*/ +class Unsettled : public State +{ + Unsettled(const Unsettled&); + Unsettled& operator=(const Unsettled&); + + Unsettled(); +public: + virtual ~Unsettled(); + + static Unsettled * instance(); + + virtual bool connect(Client * client, const QString& server, uint port = 3185); + +private: + QString make_response(const QString& chex, const QString& password) const; + +private: + static Unsettled * m_instance; +}; + +} + +#endif |