diff options
author | Slávek Banko <[email protected]> | 2013-07-27 16:34:45 +0200 |
---|---|---|
committer | Slávek Banko <[email protected]> | 2013-07-27 16:34:45 +0200 |
commit | d76ff81b7c1beffef0b84e570914c8f2d47834e6 (patch) | |
tree | 284b80ce7c5456fbb041f7979ac2c0baeead8902 /src/torclient.cpp | |
download | tork-d76ff81b7c1beffef0b84e570914c8f2d47834e6.tar.gz tork-d76ff81b7c1beffef0b84e570914c8f2d47834e6.zip |
Initial import of tork 0.33
Diffstat (limited to 'src/torclient.cpp')
-rw-r--r-- | src/torclient.cpp | 1536 |
1 files changed, 1536 insertions, 0 deletions
diff --git a/src/torclient.cpp b/src/torclient.cpp new file mode 100644 index 0000000..a29051a --- /dev/null +++ b/src/torclient.cpp @@ -0,0 +1,1536 @@ +/**************************************************************************** + ** $Id: torclient.cpp,v 1.138 2009/10/13 20:19:51 hoganrobert Exp $ + * Copyright (C) 2006 - 2008 Robert Hogan * + * [email protected] * + * * + * 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., * + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + + +#include <qsocket.h> +#include <qtextstream.h> +#include <qstringlist.h> +#include <qregexp.h> +#include "torclient.h" +#include "tork.h" +#include "torkconfig.h" +#include "dndlistview.h" +#include "functions.h" + +#include <qtimer.h> +#include <klocale.h> +#include <assert.h> +#include <qfile.h> +#include <sys/socket.h> +#include <netdb.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <kstandarddirs.h> +#include <qdir.h> +#include "crypto.h" + +#ifndef EXTERNAL_GEOIP +# include "GeoIP-1.4.0/libGeoIP/GeoIP.h" +#else +# include <GeoIP.h> +#endif + +/* Linux-specific includes */ +#include <dirent.h> +#include <unistd.h> + +using namespace tk; + + +TorClient::TorClient( const QString &host, Q_UINT16 port ) +{ + // create the socket and connect various of its signals + socket = new QSocket( this ); + connect( socket, SIGNAL(connected()), + SLOT(socketConnected()) ); + connect( socket, SIGNAL(connectionClosed()), + SLOT(socketConnectionClosed()) ); + connect( socket, SIGNAL(readyRead()), + SLOT(socketReadyRead()) ); + connect( socket, SIGNAL(error(int)), + SLOT(socketError(int)) ); + + // connect to the server + //infoText->append( tr("Trying to connect to the server\n") ); + socket->connectToHost( host, port ); + m_expectingCircuitInfo= false; + m_expectingStreamInfo= false; + m_expectingOrconnInfo= false; + m_expectingGuardsInfo= false; + m_expectingDirStatus= false; + m_expectingServerInfo= false; + m_controllerWorking= false; + m_firstloadcomplete = false; + m_resolvingServerAddress = false; + + clearServers(); + + serverReport.append("<font color='#990000'>Status Not Known</font>"); + clientReport.append("<font color='#990000'>Status Not Known</font>"); + serverStatus["DANGEROUS_VERSION"] = "<font color='#990000'>Server Requires Upgrade</font>"; + serverStatus["TOO_MANY_CONNECTIONS"] = "<font color='#990000'>Recently Exceeded Local Connection Limit. Check Local System</font>"; + serverStatus["CLOCK_SKEW"] = "<font color='#990000'>Your Local Clock Is Skewed. Check Local System.</font>"; + serverStatus["BAD_LIBEVENT"] = "<font color='#990000'>Libevent Installation Requires Upgrade</font>"; + serverStatus["DIR_ALL_UNREACHABLE"] = "<font color='#990000'>Tor Network Unreachable.</font>"; +// serverStatus["NAMESERVER_ALL_DOWN"] = "Your DNS Servers are down."; + serverStatus["DNS_HIJACKED"] = "<font color='#990000'>Your Provider is Hijacking DNS Requests.</font>"; + serverStatus["DNS_USELESS"] = "<font color='#990000'>Your Provider is Hijacking DNS Requests.</font>"; + serverStatus["EXTERNAL_ADDRESS"] = "Using Address ADDRESS"; + + serverStatus["REACHABILITY_SUCCEEDED"] = "Reachable By Tor Network"; + serverStatus["REACHABILITY_FAILED"] = "<font color='#990000'>Reachability Tests Failed. Trying again..</font>"; + serverStatus["BAD_SERVER_DESCRIPTOR"] = "<font color='#990000'>Server Not Accepted By Tor Network Yet.</font>"; + serverStatus["GOOD_SERVER_DESCRIPTOR"] = "Accepted By Tor Network"; + + serverStatusIcon["REACHABILITY_SUCCEEDED"] = "tork_green"; + serverStatusIcon["REACHABILITY_FAILED"] = "tork_orange"; + serverStatusIcon["BAD_SERVER_DESCRIPTOR"] = "tork_little"; + serverStatusIcon["GOOD_SERVER_DESCRIPTOR"] = "tork_green"; + serverStatusIcon["DIR_ALL_UNREACHABLE"] = "tork_red"; + + clientStatus["NOT_ENOUGH_DIR_INFO"] = "<font color='#990000'>Not Enough Info To Try Network Yet</font>"; + clientStatus["ENOUGH_DIR_INFO"] = "Enough Info To Try Network"; + clientStatus["CIRCUIT_ESTABLISHED"] = "Connected to Network."; + clientStatus["CIRCUIT_NOT_ESTABLISHED"] = "<font color='#990000'>Still Trying Network</font>"; + + clientStatusIcon[clientStatus["NOT_ENOUGH_DIR_INFO"]] = "tork_red"; + clientStatusIcon[clientStatus["ENOUGH_DIR_INFO"]] = "tork_little"; + clientStatusIcon[clientStatus["CIRCUIT_ESTABLISHED"]] = "tork_green"; + clientStatusIcon[clientStatus["CIRCUIT_NOT_ESTABLISHED"]] = "tork_orange"; + + portMessage["23"] = " Port 23 is used by telnet, which transmits usernames " + "and passwords unencrypted."; + portMessage["110"] = " Port 110 is used to download email, so your login " + "details can be transmitted unencrypted."; + portMessage["109"] = " Port 109 is used to download email, so your login " + "details can be transmitted unencrypted."; + portMessage["143"] = " Port 143 is used to download email, so your login " + "details can be transmitted unencrypted."; + + + statusMessage["DANGEROUS_PORT"] = "QUESTIONMESSAGETraffic on Port PORT " + "has been rejected by Tor."; + statusMessage["DANGEROUS_VERSION"] = "QUESTIONMESSAGEYou are using Tor CURRENT." + " This version is REASON. " + "You should use Tor RECOMMENDED instead"; + statusMessage["TOO_MANY_CONNECTIONS"] = "MESSAGETor has reached its native" + " limit on file descriptors: CURRENT. "; + statusMessage["BUG"] = "WARNINGMESSAGETor encountered an unexpected error: REASON. "; + statusMessage["CLOCK_SKEW"] = "WARNINGMESSAGEYour local clock is skewed by SKEW seconds. "; + statusMessage["BAD_LIBEVENT"] = "WARNINGMESSAGEYour version of libevent, VERSION, is BADNESS. "; + statusMessage["DIR_ALL_UNREACHABLE"] = "WARNINGMESSAGEAll known directory servers are unreachable. "; + statusMessage["ENOUGH_DIR_INFO"] = "WARNINGMESSAGETor has gathered enough info to start working. "; + statusMessage["NOT_ENOUGH_DIR_INFO"] = "WARNINGMESSAGETor does not have enough info to work. "; + statusMessage["CIRCUIT_ESTABLISHED"] = "WARNINGMESSAGETor has gathered enough info to start working. "; + statusMessage["CIRCUIT_NOT_ESTABLISHED"] = "WARNINGMESSAGETor does not have enough info to work. "; + statusMessage["SOCKS_BAD_HOSTNAME"] = "WARNINGMESSAGESome application gave us" + " a funny-looking hostname." + "Perhaps it is broken?"; + statusMessage["NAMESERVER_ALL_DOWN"] = "WARNINGMESSAGEAll your configured nameservers appear to be down."; + statusMessage["DNS_HIJACKED"] = "WARNINGMESSAGEYour DNS requests are being hijacked by your provider."; + statusMessage["DNS_USELESS"] = "WARNINGMESSAGEYour DNS requests are being hijacked by your provider."; + statusMessage["BAD_SERVER_DESCRIPTOR"] = "WARNINGMESSAGEYour descriptor was rejected by DIRAUTH " + "because of REASON."; + + m_statustip = i18n("<b>Name:</b> $SERVERNAME<br>" + "<b>IP:</b> $IP ($HOSTNAME) <b>Port:</b> $PORT<br>" + "<b>Country:</b> $COUNTRY <br>" + "<b>Version:</b> $VERSION <b>OS:</b> $OS<br>" + "<b>Published:</b> $PUBLISHED <b>Up Time:</b> $UPTIME minutes<br>" + "<center><b>Avg BW up to $INTERVALTIME</b></center>" + " " + " " + " <b>24 hrs</b>" + " " // 1 space + " " // 1 space + " " // 1 space + " " // 1 space + " <b>12 hrs</b>" + " " // 1 space + " " // 1 space + " " // 1 space + " " // 1 space + " <b>6 hrs</b>" + " " // 1 space + " " // 1 space + " " // 1 space + " " // 1 space + " " // 1 space + " <b>1 hr</b><br>" + "<b>Up</b>" + " " // 1 space + " " // 1 space + " " // 1 space + "<font color='#990000'>$BWUP</font><br>" + "<b>Down</b>" + " " // 1 space + " " // 1 space + "<font color='#1c9a1c'>$BWDN</font><br>" + ); + +} + +void TorClient::configureServer( int orPort, int dirPort) +{ + + sendToServer(QString("SETCONF ContactInfo=%1").arg(TorkConfig::contactInfo())) ; + + sendToServer(QString("SETCONF ClientOnly=%1").arg(TorkConfig::clientOnly())) ; + + + if (TorkConfig::middleMan()) + ( sendToServer(QString("SETCONF ExitPolicy=%1").arg(("\"reject *:*\"")))) ; + else + ( sendToServer(QString("SETCONF ExitPolicy=\"%2\"").arg( TorkConfig::exitPolicy().join(",")))); + + sendToServer(QString("SETCONF NickName=%1").arg(TorkConfig::nickName())) ; + if (!TorkConfig::clientOnly()){ + //We send the orport configs together to avoid error messages from Tor + //telling us that one cannot be set without the other. + sendToServer(QString("SETCONF ORPort=%1 " + "ORListenAddress=0.0.0.0:%2") + .arg(orPort) + .arg(TorkConfig::oRListenAddress())) ; + //We send the dirport configs together to avoid error messages from Tor + //telling us that one cannot be set without the other. + sendToServer(QString("SETCONF DIRPort=%1 " + "DIRListenAddress=0.0.0.0:%2") + .arg(dirPort) + .arg(TorkConfig::dirListenAddress())) ; + sendToServer(QString("SETCONF BridgeRelay=%1").arg(TorkConfig::bridgeRelay())) ; + setBandwidth(QString("%1").arg(TorkConfig::bandwidthRate()), + QString("%1").arg(TorkConfig::bandwidthBurst()), + QString("%1").arg(TorkConfig::maxAdvertisedBandwidth())); + }else{ + sendToServer(QString("SETCONF ORPort= ORListenAddress=")) ; + sendToServer(QString("SETCONF DirPort= DirListenAddress=")) ; + sendToServer(QString("SETCONF BridgeRelay=")) ; + } + + if (TorkConfig::clientOnly()) + resetClientReport(); + TorkConfig::writeConfig(); +} +void TorClient::clearNodes( ) +{ + + sendToServer("SETCONF ExcludeNodes="); + sendToServer("SETCONF ExitNodes="); + sendToServer("SETCONF EntryNodes="); + TorkConfig::setCurrentExcludeNodes(""); + TorkConfig::setCurrentEntryNodes(""); + TorkConfig::setCurrentExitNodes(""); + emit copyOldConfig(); +} + +void TorClient::updateExcludeNodes( ) +{ + ////kdDebug() << "SETCONF ExcludeNodes=" + TorkConfig::currentExcludeNodes().join(",") << endl; + sendToServer("SETCONF ExcludeNodes=" + TorkConfig::currentExcludeNodes().join(",")); + sendToServer("GETCONF ExcludeNodes"); + sendToServer("signal newnym"); + +} + +void TorClient::updateExitNodes( ) +{ + ////kdDebug() << "SETCONF ExitNodes=" + TorkConfig::currentExitNodes().join(",") << endl; + sendToServer("SETCONF ExitNodes=" + TorkConfig::currentExitNodes().join(",")); + sendToServer("GETCONF ExitNodes"); + sendToServer("signal newnym"); + +} + +void TorClient::strictExitNodes( bool strict ) +{ + if (strict) + sendToServer("SETCONF StrictExitNodes=1"); + else + sendToServer("SETCONF StrictExitNodes=0"); + +} + +void TorClient::safeLogging( bool safe ) +{ + if (safe) + sendToServer("SETCONF SafeLogging=1"); + else + sendToServer("SETCONF SafeLogging=0"); + +} + +void TorClient::updateEntryNodes( ) +{ + ////kdDebug() << "SETCONF EntryNodes=" + TorkConfig::currentEntryNodes().join(",") << endl; + sendToServer("SETCONF EntryNodes=" + TorkConfig::currentEntryNodes().join(",")); + sendToServer("GETCONF EntryNodes"); + sendToServer("signal newnym"); + +} + +void TorClient::enableDNS( bool set ) +{ + if (set) + sendToServer("SETCONF DNSPort=9999"); + else + sendToServer("SETCONF DNSPort="); + +} + +void TorClient::enableTransPort( bool set ) +{ + if (set) + sendToServer("SETCONF TransPort=9040"); + else + sendToServer("SETCONF TransPort="); + +} + +void TorClient::fetchServerInfo( const QString & server) +{ + + QString fp = getFPFromFPDigest(server); + fp.replace("$",""); + + kdDebug() << fp << endl; +// emit showServerBW(fp); + + sendToServer("GETINFO dir/server/fp/" + fp); +} + +void TorClient::fetchServerInfoByNick( const QString & server) +{ + + + QString fp = getFPFromNickName(server); + fp.replace("$",""); + + sendToServer("GETINFO dir/server/fp/" + fp); +} + +void TorClient::slotCheckTorNet() +{ + sendToServer("GETINFO ns/all"); +} + +void TorClient::slotCheckGuards() +{ + + sendToServer("GETINFO entry-guards"); + +} + +void TorClient::terminateTor() +{ + + sendToServer("SIGNAL SHUTDOWN"); + +} + +void TorClient::createService(const QString &dir, const QString &port) +{ + sendToServer(QString("setconf hiddenservicedir=\"%1\" hiddenserviceport=\"%2\"").arg(dir).arg(port)); +} + +void TorClient::authenticate() +{ + +// if (TorkConfig::defaultRunningNormalOptions()){ +// sendToServer("AUTHENTICATE"); +// return; +// } + + if (TorkConfig::cookieAuthentication()){ + if (!readCookie()){ + emit processQuestion("cookienotfound", + QString("Couldn't find authentication" + " cookie in %1/.tor!").arg(getenv("HOME"))); + emit fatalError(); + } + }else if (!TorkConfig::hashedControlPassword().isEmpty()) + sendToServer(QString("AUTHENTICATE \"%1\"").arg(TorkConfig::hashedControlPassword())); + else{ + sendToServer("AUTHENTICATE"); + /* Lock the control port */ + if (TorkConfig::generateRandomPassword()){ + crypto_seed_rng(); + sendToServer(QString("setconf HashedControlPassword=16:%2") + .arg(hashPassword(crypto_rand_string(16)))); + } + } + +} + + +bool TorClient::readCookie() +{ + + QString hex; + char hx[2]; + + QStringList cookieCandidates; + cookieCandidates << QString("%1/.tor/control_auth_cookie").arg(getenv("HOME")); + cookieCandidates << QString("/var/lib/tor/control_auth_cookie"); + + for ( QStringList::Iterator it = cookieCandidates.begin(); it != cookieCandidates.end(); ++it ) { + QFile inf((*it)); + if ( inf.open(IO_ReadOnly) ) { + QByteArray array = inf.readAll(); + inf.close(); + if (array.size() != 32) + continue; + for ( unsigned int i = 0; i < array.size(); i++ ) { + sprintf(hx,"%02x",array[i]); + hex += QString(hx).right(2); + } + sendToServer(QString("AUTHENTICATE %1").arg(hex)); + return true; + + } + } + + return false; + +} + +void TorClient::readRouters() +{ + + QFile inf(QString("%1/.tor/cached-status/7EA6EAD6FD83083C538F44038BBFA077587DD755").arg(getenv("HOME"))); + if ( inf.open(IO_ReadOnly) ) { + QTextStream stream( &inf ); + QString line; + while ( !stream.atEnd() ) { + line = stream.readLine(); // line of text excluding '\n' + parseDirStatus(line); + } + inf.close(); + } + + +} + +void TorClient::newIdentity() +{ + kdDebug() << "changing id" << endl; + sendToServer("signal newnym"); + +} + +void TorClient::bandwidth() +{ + + sendToServer("usefeature verbose_names"); + sendToServer("usefeature extended_events"); + sendToServer("GETINFO ns/all"); + sendToServer("GETINFO circuit-status"); + sendToServer("GETINFO stream-status"); + sendToServer("GETINFO orconn-status"); + sendToServer("GETINFO version"); + sendToServer("GETINFO status/enough-dir-info"); + sendToServer("GETINFO status/good-server-descriptor"); + sendToServer("GETINFO status/reachability-succeeded/or"); + + //Always enable for each session, user can disable through yes/no + //interface when warned - but only for that session. + m_portsToReject.clear(); + m_portsToReject << "23" << "109" << "110" << "143"; + sendToServer(QString("SETCONF WarnPlainTextPorts=%1") + .arg(m_portsToReject.join(","))); + sendToServer(QString("SETCONF RejectPlainTextPorts=%1") + .arg(m_portsToReject.join(","))); + sendToServer("SETEVENTS EXTENDED CIRC STREAM ORCONN NOTICE " + "WARN ERR ADDRMAP BW STREAM_BW NS STATUS_GENERAL " + "STATUS_CLIENT STATUS_SERVER GUARD"); + sendToServer(QString("SETCONF __ReloadTorrcOnSIGHUP=0")); + + +} + +void TorClient::handle250(const QString &lin) +{ + + + QString line = lin; + + if ((line.contains("250-circuit-status="))){ + if (line != ".") + parseEvent("CIRC",line.replace("250-circuit-status=","")); + else + m_expectingCircuitInfo = false; + }else if ((line.contains("250-orconn-status="))){ + if (line != ".") + parseEvent("ORCONN",line.replace("250-orconn-status=","")); + else + m_expectingOrconnInfo = false; + }else if ((line.contains("250-stream-status="))){ + if (line != ".") + parseEvent("STREAM",line.replace("250-stream-status=","")); + else + m_expectingStreamInfo = false; + }else if (line.contains("250+circuit-status=")) + m_expectingCircuitInfo= true; + else if (line.contains("250+orconn-status=")) + m_expectingOrconnInfo= true; + else if (line.contains("250+stream-status=")) + m_expectingStreamInfo= true; + else if (line.contains("250+entry-guards=")) + m_expectingGuardsInfo= true; + else if (line.contains("250+dir/server/fp/")) + m_expectingServerInfo= true; + else if (line.contains("250+extra-info/digest/")) + m_expectingServerInfo= true; + else if (line.contains("250+ns/all=")){ + m_expectingDirStatus= true; + emit whatImDoing("Inspecting the Tor network.."); + }else if (line.contains("250-ns/all=")){ + emit warnNoServerInfo(); + emit shouldIApplySettings(); + }else if (line.contains("250-version=")) + handleTorVersion(line.section("=",1,1)); + else if (line.contains("250 BandwidthRate=")) + m_CurBandwidthRate = line.section("=",1,1).toInt(); + else if (line.contains("250 BandwidthBurst=")) + m_CurBandwidthBurst = line.section("=",1,1).toInt(); + else if (line.contains("250 MaxAdvertisedBandwidth=")) + m_CurMaxAdvertisedBandwidth = line.section("=",1,1).toInt(); + else if (line.contains("250 ExcludeNodes=")) + TorkConfig::setCurrentExcludeNodes(QStringList::split(",",line.replace("250 ExcludeNodes=",""))); + else if (line.contains("250 EntryNodes=")) + TorkConfig::setCurrentEntryNodes(QStringList::split(",",line.replace("250 EntryNodes=",""))); + else if (line.contains("250 ExitNodes=")) + TorkConfig::setCurrentExitNodes(QStringList::split(",",line.replace("250 ExitNodes=",""))); + else if (line.contains("250-status/circuit-established=1")) + updateClientReport("CIRCUIT_ESTABLISHED"); + else if (line.contains("250-status/circuit-established=0")) + updateClientReport("CIRCUIT_NOT_ESTABLISHED"); + else if (line.contains("250-status/enough-dir-info=1")){ + updateClientReport("ENOUGH_DIR_INFO"); + sendToServer("GETINFO status/circuit-established"); + }else if (line.contains("250-status/enough-dir-info=0")) + updateClientReport("NOT_ENOUGH_DIR_INFO"); + else if (line.contains("250-status/good-server-descriptor=1")) + updateServerReport("GOOD_SERVER_DESCRIPTOR", QString()); + else if (line.contains("250-status/good-server-descriptor=0")) + updateServerReport("BAD_SERVER_DESCRIPTOR", QString()); + else if (line.contains("250-status/reachability-succeeded/or=1")) + updateServerReport("REACHABILITY_SUCCEEDED", QString()); + else if (line.contains("250-status/reachability-succeeded/or=0")) + updateServerReport("REACHABILITY_FAILED", QString()); + +} + +void TorClient::socketReadyRead() +{ + QString line; + // read from the server + while ( socket->canReadLine() ) { + + line = (socket->readLine()).stripWhiteSpace(); + + if (line.contains("250 OK")){ + if (!m_controllerWorking){ + bandwidth(); + emit authenticated(); + m_controllerWorking = true; + } + continue; + } + + if (m_expectingDirStatus){ + if (!(line == ".")){ + parseDirStatus(line); + }else{ + m_expectingDirStatus = false; + sendToServer("GETINFO entry-guards"); + if (!m_firstloadcomplete) + emit shouldIApplySettings(); + m_firstloadcomplete = true; + } + continue; + }else if ((m_expectingCircuitInfo)){ + if (line != "."){ + parseEvent("CIRC",line); + }else + m_expectingCircuitInfo = false; + continue; + }else if ((m_expectingOrconnInfo)){ + if (line != "."){ + parseEvent("ORCONN",line); + }else + m_expectingOrconnInfo = false; + continue; + }else if ((m_expectingStreamInfo)){ + if (line != "."){ + parseEvent("STREAM",line); + }else + m_expectingStreamInfo = false; + continue; + }else if (m_expectingServerInfo){ + if (line != "."){ + parseEvent("SERVER",line); + }else + m_expectingServerInfo = false; + continue; + }else if (m_expectingGuardsInfo){ + if (line != "."){ + parseEvent("GUARDS",line); + emit whatImDoing(i18n("Ready for use.")); + }else{ + m_expectingGuardsInfo = false; + } + continue; + } + + if (line.contains("552 Unrecognized key \"ns/all\"")){ + emit needAlphaVersion(); + emit shouldIApplySettings(); + continue; + } + + QString code = line.left(3); + + if (code == "250") + handle250(line); + else if (code == "650"){ + if (line.contains("650+NS")){ + m_expectingDirStatus= true; + continue; + } + QString eventType = line.section(" ",1,1); + QString eventInfo = line.section(" ",2); + if (eventInfo.contains("circuit_testing_failed")) + emit serverError(); + parseEvent(eventType,eventInfo); + }else if (code == "552"){ + QString eventInfo = line.section(" ",1); + emit displayError("Sorry!", eventInfo); + }else if (code == "514"){ + QString eventInfo = line.section(" ",1); + emit processWarning("authenticationrequired", eventInfo); + emit fatalError(); + }else if (code == "515"){ + QString eventInfo = line.section(" ",1); + if (eventInfo.contains("Wrong length")) + emit processQuestion("cookierequired", eventInfo); + else{ + if (TorkConfig::generateRandomPassword()) + emit processQuestion("passwordlost", eventInfo); + else + emit processWarning("authenticationfailed", eventInfo); + } + //Only used by the first-run wizard + emit authenticationFailed(); + } + + + } +} + +void TorClient::parseEvent(const QString &type, const QString &info) +{ + + if (info.isEmpty()) + return; + + if (type == "STREAM") + parseStream(info); + else if (type == "ORCONN") + parseORConn(info); + else if (type == "CIRC") + parseCircuit(info); + else if (type == "GUARDS") + parseGuards(info); + else if (type == "GUARD") + parseGuards(info.section(" ",1)); + else if (type == "SERVER") + parseServer(info); + else if (type == "DIRSTATUS") + parseDirStatus(info); + else if (type == "BW") + parseBW(info); + else if (type == "STREAM_BW") + parseStreamBW(info); + else if (type.contains( "STATUS_")) + parseStatusGeneral(info); + else if (type == "ADDRMAP") + parseAddrmap(info); +/* else if (type == "STREAM_PORT") + parseStreamPort(info);*/ + else if ((type == "WARN") || (type == "NOTICE") || (type == "ERR")) + parseInfo(type,info); +} + +void TorClient::parseStatusGeneral(const QString &info) +{ + QString severity = info.section(" ",0,0); + QString action = info.section(" ",1,1); + QString message = statusMessage[action]; + + if (!serverStatus[action].isEmpty()) + updateServerReport(action, info); + + if (!clientStatus[action].isEmpty()) + updateClientReport(action); + +/* kdDebug() << info << endl; + kdDebug() << info.section(" ",2) << endl;*/ + populateMessageFromStatusDetail(info.section(" ",2), message); + + if (message.left(14) == "WARNINGMESSAGE"){ + message.replace("WARNINGMESSAGE",""); + emit processWarning(action, message); + }else{ + message.replace("QUESTIONMESSAGE",""); + emit processQuestion(action, message); + } + +} + +void TorClient::populateMessageFromStatusDetail(const QString &line, QString &message) +{ + QRegExp rx("[\\sA-Z0-9]+[=]([\\-\\:\\.\\(\\)a-zA-Z0-9]+|\\\"[\\-\\.\\,a-zA-Z0-9\\s]+\\\")"); + int pos = 0; + while ( (pos = rx.search(line, pos)) != -1 ) { +/* kdDebug() << rx.cap(0) << endl;*/ + QString keyword = rx.cap(0).section("=",0,0).stripWhiteSpace(); + QString value = rx.cap(0).section("=",1,1).stripWhiteSpace(); + message.replace(keyword,value); + pos += rx.matchedLength(); + if (keyword=="PORT"){ + m_WarnedPorts << value; + message.append(portMessage[value]); + } + } +} + +void TorClient::updateServerReport(const QString &message, const QString &info) +{ +// kdDebug() << serverStatusIcon[message] << endl; +// kdDebug() << message << endl; + + //If we're back to being a client, ensure the server symbol is removed from the tray icon + if (TorkConfig::clientOnly()){ + emit updateTrayIcon(serverStatusIcon[message].replace("server","")); + return; + } + if (!serverStatusIcon[message].isEmpty()) + emit updateTrayIcon(serverStatusIcon[message]); + + serverReport.remove("<font color='#990000'>Status Not Known</font>"); + QString msg = serverStatus[message]; + + if (message.contains("EXTERNAL_ADDRESS")){ + for ( QStringList::Iterator it = serverReport.begin(); it != serverReport.end(); ++it ) + { + // XXX Fixme + if ((*it).contains("Using Address")){ + serverReport.remove((*it)); + break; + } + } + populateMessageFromStatusDetail(info.section(" ",2),msg); + }else if (message.contains("REACHABILITY")){ + serverReport.remove(serverStatus["REACHABILITY_FAILED"]); + serverReport.remove(serverStatus["REACHABILITY_SUCCEEDED"]); + }else if (message.contains("SERVER_DESCRIPTOR")){ + serverReport.remove(serverStatus["DIR_ALL_UNREACHABLE"]); + serverReport.remove(serverStatus["BAD_SERVER_DESCRIPTOR"]); + serverReport.remove(serverStatus["GOOD_SERVER_DESCRIPTOR"]); + }else // Prevent multiple reports + serverReport.remove(msg); + + serverReport.append(msg); +} + +void TorClient::updateClientReport(const QString &message) +{ + if (!clientStatusIcon[message].isEmpty() && (TorkConfig::clientOnly())) + emit updateTrayIcon(clientStatusIcon[clientStatus[message]]); + clientReport.clear(); + clientReport.append(clientStatus[message]); +} + +void TorClient::resetClientReport() +{ + emit updateTrayIcon(clientStatusIcon[clientReport.first()]); +} + +void TorClient::parseBW(const QString &info) +{ + + QString in = info.section(" ",0,0); + QString out = info.section(" ",1,1); + + emit bwUpdate(in, out); + +} + + +void TorClient::parseStreamBW(const QString &info) +{ + + QString stream = info.section(" ",0,0); + /* Tor spec had it wrong way round! */ + QString out = info.section(" ",1,1); + QString in = info.section(" ",2,2); + + emit streamBwUpdate(stream, in, out); + +} + + +void TorClient::parseStream(const QString &info) +{ + + + QString streamID = info.section(" ",0,0); + QString status = info.section(" ",1,1); + QString circID = info.section(" ",2,2); + QString Target = info.section(" ",3,3); + + //We ignore REMAPs because we don't do anything with them + if (status == "REMAP") + return; + + emit streamStatusUpdate(streamID, status, circID, Target, info); + +} + +void TorClient::parseServer(const QString &info) +{ + + kdDebug() << "server info " << info << endl; + if (info.left(7) == "router "){ + QString ip = info.section(" ",2,2); + QString cc; + + GeoIP * gi = 0; + + if (geoip_db) +#ifndef EXTERNAL_GEOIP + gi = GeoIP_open(locate("data", "tork/geoip/GeoIP.dat").ascii(),0); +#else + gi = GeoIP_new(GEOIP_STANDARD); +#endif + + if (gi){ + int country_id = 0; + country_id = GeoIP_id_by_name(gi, ip); + cc = GeoIP_country_name[country_id]; + GeoIP_delete(gi); + }else + cc = "a1"; + + m_statustiptmp = m_statustip; + m_statustipIP = ip; + + m_statustiptmp.replace("$SERVERNAME",info.section(" ",1,1)); + m_statustiptmp.replace("$IP",ip); + m_statustiptmp.replace("$PORT",info.section(" ",3,3)); + m_statustiptmp.replace("$COUNTRY",cc); + + }else if (info.left(8) == "platform"){ + m_statustiptmp.replace("$VERSION",info.section(" ",1,2)); + m_statustiptmp.replace("$OS",info.section(" ",4).section("{",0,0)); + + }else if (info.left(9) == "published"){ + m_statustiptmp.replace("$PUBLISHED",info.section(" ",1)); + + }else if (info.left(6) == "uptime"){ + //from the clever ktorrent + KLocale* loc = KGlobal::locale(); + QTime t; + int nsecs = info.section(" ",1).toInt(); + int ndays = (nsecs) / 86400; + t = t.addSecs(nsecs % 86400); + QString s = loc->formatTime(t,true,true); + if (ndays > 0) + s = i18n("1 day ","%n days ",ndays) + s; + + m_statustiptmp.replace("$UPTIME",s); + + + }else if (info.left(20).contains("write-history")){ + QStringList bwlist = QStringList::split(",",info.section(" ",-1)); + + QValueList<int> bws; + bws << 4 << 24 << 48 << bwlist.count(); + + QString bwup; + QString avgbw; + for ( QValueList<int>::Iterator it = bws.begin(); it != bws.end(); ++it ){ + avgbw = calcBW(bwlist, (*it)); + for (int i = avgbw.length(); i < 14; i++) + avgbw.append(" "); + bwup.append(avgbw); + } + + m_statustiptmp.replace("$BWUP",bwup); + + m_statustiptmp.replace("$INTERVALTIME", info.section(" ",2,3)); + + }else if (info.left(20).contains("read-history")){ + QStringList bwlist = QStringList::split(",",info.section(" ",-1)); + QValueList<int> bws; + bws << 4 << 24 << 48 << bwlist.count(); + + QString bwup; + QString avgbw; + for ( QValueList<int>::Iterator it = bws.begin(); it != bws.end(); ++it ){ + avgbw = calcBW(bwlist, (*it)); + for (int i = avgbw.length(); i < 14; i++) + avgbw.append(" "); + bwup.append(avgbw); + } + m_statustiptmp.replace("$BWDN",bwup); + + + if (m_currentTorVersion.left(3) == "0.2"){ + m_resolvingServerAddress=true; + sendToServer("RESOLVE mode=reverse " + m_statustipIP); + }else{ + m_statustiptmp.replace("($HOSTNAME)",""); + emit displayServer("Server Info", m_statustiptmp); + } + }else if (info.left(25).contains("opt extra-info-digest")){ + if (m_currentTorVersion.left(3) == "0.2"){ + sendToServer("GETINFO extra-info/digest/" + info.section(" ",2)); + }else{ + m_statustiptmp.replace("($HOSTNAME)",""); + m_statustiptmp.replace("$BWDN","Unavailable"); + m_statustiptmp.replace("$BWUP","Unavailable"); + m_statustiptmp.replace("$INTERVALTIME", "Unavailable"); + emit displayServer("Server Info", m_statustiptmp); + } + + } +} + +void TorClient::parseAddrmap(const QString &info) +{ + + + QString type = info.section(" ",0,0); + QString address = info.section(" ",1,1); + + // If this is a request to resolve a hostname/address from the traffic + // logs + if (logResolveList.contains(type)){ + emit resolvedAddress(info); + logResolveList.remove(logResolveList.find(type)); + return; + } + + if (!m_resolvingServerAddress) + return; + + // If this is a request to resolve a node name from the server list + if (type.startsWith("REVERSE")){ + m_statustiptmp.replace("$HOSTNAME",address); + }else + m_statustiptmp.replace("$HOSTNAME","Cannot Resolve Hostname."); + + emit displayServer("Server Info", m_statustiptmp); + m_resolvingServerAddress = false; + +} + +void TorClient::parseGuards(const QString &info) +{ + + QString fp_identity = info.section(" ",0,0); + QString status = info.section(" ",1,1); + QRegExp rx("(\\$[A-Z0-9]{40})"); + rx.search(fp_identity); + QString server = getNickNameFromFP(rx.cap(0)); + + if (!server.isEmpty()){ + emit guardStatusUpdate(server, status); + } +} + +void TorClient::parseCircuit(const QString &info) +{ + + if (info.contains("FAILED")) + emit displayError("Circuit Failed - "+info.section(" ",3,3).replace("REASON=",""), "Circuit: " + info.section(" ",2,2)); + + QString circuitID = info.section(" ",0,0).stripWhiteSpace(); + QString status = info.section(" ",1,1).stripWhiteSpace(); + QString path = info.section(" ",2,2).stripWhiteSpace(); + + //Get the FP Digest (if any) of the last server in the circuit + QString exit; + QRegExp rx("(\\$[A-Z0-9]{40})"); + int count = 0; + int pos = 0; + while ( (pos = rx.search(path, pos)) != -1 ) { + count++; + pos += rx.matchedLength(); + exit = rx.cap(0); + } + if (!exit.isEmpty()) + exit = getFPDigestFromFP(exit); + //Strip out the FPs from the circuit, if any + path.replace(QRegExp("(\\$[A-Z0-9]{40})(~|=)"),""); + + emit circuitStatusUpdate(circuitID, status, path, exit); + +} + +void TorClient::parseORConn(const QString &info) +{ + QString serverID = info.section(" ",0,0); + QString status = info.section(" ",1,1); + + if (serverID.startsWith("$")){ + QString server = getNickNameFromFP(serverID); + if (!server.isEmpty()) + serverID = server; + } + + if (!status.contains("NEW")){ + serverID.replace(QRegExp("^[A-Z0-9$=~]{42}"),""); + emit ORStatusUpdate(serverID, status); + } +} + +void TorClient::parseInfo(const QString &type,const QString &info) +{ + + QString message = info; + message.replace(QRegExp("^[a-zA-Z0-9_]+\\(\\):"),""); +// QString summary = info.section(":",0,0); +// QString data = info.section(":",1); + + if (info.contains("Servers unavailable")) + emit displayServer("Server Info", "<b>Server appears to be down!</b>"); + emit infoUpdate(type, message, QString()); + +} + +void TorClient::updateCandidateServers(const QString &path) +{ + + QStringList servers = QStringList::split(",", path); + QStringList existingServers = TorkConfig::serversHistory(); + for ( QStringList::Iterator it = servers.begin(); it != servers.end(); ++it ) + { + if ((*it).isEmpty()) + continue; + if (existingServers.find(*it) == existingServers.end()) + existingServers.append(*it); + } + TorkConfig::setServersHistory(existingServers); + + TorkConfig::writeConfig(); +} + +void TorClient::attemptAttach(const QString &circid, const QString &streamid) +{ + + QStringList streams = QStringList::split( " ", streamid); + for ( QStringList::Iterator it = streams.begin(); it != streams.end(); ++it ) + { + if ((*it).isEmpty()) + continue; + sendToServer(QString("ATTACHSTREAM %1 %2").arg(*it).arg(circid)); + } + +} + +void TorClient::attemptExtendCircuit(const QString &circid, const QString &serverlist, bool usefp) +{ + + + QStringList servers = QStringList::split( " ", serverlist); + QStringList circuitlist; + for ( QStringList::Iterator it = servers.begin(); it != servers.end(); ++it ) + { + if ((*it).isEmpty()) + continue; + if (usefp) + circuitlist.append(getFPFromFPDigest((*it))); + else + circuitlist.append((*it)); + } + + QString circuit = circuitlist.join(","); + sendToServer(QString("EXTENDCIRCUIT %1 %2").arg(circid).arg(circuit)); +} + +void TorClient::attemptCreateCircuit(const QString &serverlist, bool usefp) +{ + + QStringList servers = QStringList::split( " ", serverlist); + QStringList circuitlist; + for ( QStringList::Iterator it = servers.begin(); it != servers.end(); ++it ) + { + if ((*it).isEmpty()) + continue; + if (usefp) + circuitlist.append(getFPFromFPDigest((*it))); + else + circuitlist.append((*it)); + } + + QString circuit = circuitlist.join(","); + sendToServer(QString("EXTENDCIRCUIT 0 %1").arg(circuit)); +} + +void TorClient::attemptCloseStream(const QString &streamid) +{ + sendToServer(QString("CLOSESTREAM %1 1").arg(streamid)); +} + +void TorClient::attemptAttachStreams( bool attachStreams) +{ + sendToServer(QString("SETCONF __LeaveStreamsUnattached=%1").arg(attachStreams)); +} + +void TorClient::attemptCloseCircuit(const QString &circuitid) +{ + sendToServer(QString("CLOSECIRCUIT %1").arg(circuitid)); +} + + +void TorClient::updatePrevConfig(PrevConfig::PrevConfigList prevlist) +{ + + m_previtems = prevlist; +} + + +void TorClient::applySettingsToRunningTor() +{ + + //FIXME: use function pointers and a list to do this + + + switch (TorkConfig::quickConfigure()) { + case 0 : //Tor client and server with default settings + return; + case 1 : //Tor client with default settings + return; + case 2 : //Tor server with default settings + return; + case 3 : //Tor server with default settings + return; + case 4 : //Tor server with default settings + return; + default: + break; + } + +// kdDebug() << "1" << endl; + KConfigSkeletonItem::List items = TorkConfig::self()->items(); + KConfigSkeletonItem::List::ConstIterator it; + + for( it = items.begin(); it != items.end(); ++it ) { + if (elementShouldBeUsed((*it))){ + if (noSpecialProcessing((*it))){ + PrevConfig::PrevConfigList::iterator mit; + QVariant oldvalue; + for( mit = m_previtems.begin(); mit != m_previtems.end(); ++mit ) { + if ((*mit).name() == (*it)->name()){ + oldvalue = (*mit).property(); + continue; + } + } + + + if ( (*it)->property().type() == QVariant::String ) { + if ((oldvalue !=(*it)->property())){ + ( sendToServer(QString("SETCONF %1=%2").arg((*it)->name()).arg((*it)->property().toString()))); + } + }else if ( (*it)->property().type() == QVariant::StringList ) { + if ((oldvalue !=(*it)->property())){ + ( sendToServer(QString("SETCONF %1=\"%2\"").arg((*it)->name()).arg( (*it)->property().toStringList().join(",")))); + } + }else if ( (*it)->property().type() == QVariant::Int ) { + if ((oldvalue !=(*it)->property())){ + ( sendToServer(QString("SETCONF %1=%2").arg((*it)->name()).arg( (*it)->property().toString()))); + } + }else if ( (*it)->property().type() == QVariant::Bool ) { + if ((oldvalue !=(*it)->property())){ + ( sendToServer(QString("SETCONF %1=%2").arg((*it)->name()).arg( (*it)->property().toInt()))); + } + } + + } + } + } + + if (TorkConfig::useProxy()){ + if ((TorkConfig::httpProxyPort() > 0) && (!TorkConfig::httpProxyHost().isEmpty())) + ( sendToServer(QString("SETCONF HttpProxy=%1:%2").arg(TorkConfig::httpProxyHost()).arg(TorkConfig::httpProxyPort()))) ; + if ((TorkConfig::httpsProxyPort() > 0) && (!TorkConfig::httpsProxyHost().isEmpty())) + ( sendToServer(QString("SETCONF HttpsProxy=%1:%2").arg(TorkConfig::httpsProxyHost()).arg(TorkConfig::httpsProxyPort()))) ; + + if ((!TorkConfig::httpProxyAuthenticatorUserName().isEmpty()) && (!TorkConfig::httpProxyAuthenticatorPassword().isEmpty())) + ( sendToServer(QString("SETCONF HttpProxyAuthenticator=%1:%2").arg(TorkConfig::httpProxyAuthenticatorUserName()).arg(TorkConfig::httpProxyAuthenticatorPassword()))); + + if ((!TorkConfig::httpsProxyAuthenticatorUserName().isEmpty()) && (!TorkConfig::httpsProxyAuthenticatorPassword().isEmpty())) + ( sendToServer(QString("SETCONF HttpsProxyAuthenticator=%1:%2").arg(TorkConfig::httpsProxyAuthenticatorUserName() ).arg(TorkConfig::httpsProxyAuthenticatorPassword()))); + }else{ + ( sendToServer(QString("SETCONF HttpProxy="))); + ( sendToServer(QString("SETCONF HttpsProxy="))); + ( sendToServer(QString("SETCONF HttpProxyAuthenticator="))); + ( sendToServer(QString("SETCONF HttpsProxyAuthenticator="))); + } + + if ((!TorkConfig::sOCKSBindAddressHost().isEmpty()) && (TorkConfig::sOCKSBindAddressPort() > -1)) + ( sendToServer(QString("SETCONF SOCKSListenAddress=%1:%2").arg(TorkConfig::sOCKSBindAddressHost()).arg( TorkConfig::sOCKSBindAddressPort()))) ; + + if ((TorkConfig::sOCKSBindAddressHost().isEmpty()) && (TorkConfig::sOCKSBindAddressPort() > -1)) + ( sendToServer(QString("SETCONF SOCKSPort=%2").arg(TorkConfig::sOCKSBindAddressPort()))) ; + + emit copyOldConfig(); + emit makeTorkStoppable(); + sendToServer(QString("GETCONF ExcludeNodes")) ; + sendToServer(QString("GETCONF ExitNodes")) ; + sendToServer(QString("GETCONF EntryNodes")) ; + +} + +bool TorClient::elementShouldBeUsed(const KConfigSkeletonItem* it) +{ + + //Maxmin Settings are always applied, defaults if 'let Tor decide' selected. + if (((*it).group() == "MaxMin") || + ((!(TorkConfig::clientOnly())) && ((*it).group() == "DefaultServerAddress")) || + ((*it).group() == "FirewallEvasion") || + ((*it).group() == "Censorship") || + (((*it).group() == "RunningSpecial")) || + (((*it).group() == "Servers")) || + // Server settings are applied by calling configureServer() later + //(((*it).group() == "MyServer")) || + (((*it).group() == "Usability")) || + (((*it).group() == "UsingTor")) || + (((*it).group() == "MyHiddenServices")) || + //Serverperformance Settings are always applied, defaults if 'let Tor decide' selected. + (((*it).group() == "ServerPerformance"))) + return true; + + + //Excluded: + //((*it).group() == "RunningNormal")) - Because they aren't appropriate for a running Tor + + return false; +} + +bool TorClient::noSpecialProcessing(const KConfigSkeletonItem* it) +{ + + if (((*it).name() == "PublishServerDescriptor") && (TorkConfig::bridgeRelay())){ + sendToServer(QString("setconf PublishServerDescriptor=bridge")); + return false; + } + + if ((*it).name() == "HashedControlPassword"){ + if ((*it).property().toString().isEmpty() && + (!TorkConfig::cookieAuthentication()) && + TorkConfig::generateRandomPassword()){ + crypto_seed_rng(); + sendToServer(QString("setconf %1=16:%2") + .arg((*it).name()) + .arg(hashPassword(crypto_rand_string(16)))); + return false; + } + return true; + } + + if ((*it).group() == "DefaultServerAddress"){ + if ((*it).name() == "ORPort") + ( sendToServer(QString("SETCONF %1=%2").arg((*it).name()) + .arg( (*it).property().toString()))); + return false; + } + + if (((*it).name() == "BandwidthBurst") || ((*it).name() == "BandwidthRate")){ + ( sendToServer(QString("SETCONF BandwidthBurst=%1KB BandwidthRate=%2KB") + .arg(TorkConfig::bandwidthBurst()).arg(TorkConfig::bandwidthRate()))); + getBandwidth(); + return false; + } + + if ((*it).name() == "MaxAdvertisedBandwidth"){ + ( sendToServer(QString("SETCONF %1=%2KB").arg((*it).name()).arg( (*it).property().toString()))); + getBandwidth(); + return false; + } + + if ((*it).name() == "AccountingMax"){ + ( sendToServer(QString("SETCONF %1=\"%2 bytes\"").arg((*it).name()).arg( ((*it).property().toInt() * 1024 * 1024)))); + return false; + } + + if ((*it).name() == "AccountingStart"){ + if ((*it).property().toString() == "day") + ( sendToServer(QString("SETCONF %1=\"%2 00:00\"").arg((*it).name()).arg( (*it).property().toString()))); + else + ( sendToServer(QString("SETCONF %1=\"%2 1 00:00\"").arg((*it).name()).arg( (*it).property().toString()))); + return false; + } + + + if ((*it).name() == "KeepalivePeriod"){ + if (!TorkConfig::reachableAddresses().isEmpty()){ + ( sendToServer(QString("SETCONF %1=%2").arg((*it).name()).arg( ((*it).property().toInt() * 60)))) ; + } + return false; + } + + if ((*it).name() == "TrackHostExits"){ + if (!TorkConfig::trackHostExits().isEmpty()){ + ( sendToServer(QString("SETCONF %1=%2").arg((*it).name()).arg( ((*it).property().toStringList().join(","))))) ; + if (TorkConfig::trackHostExitsExpire() > 0) + ( sendToServer(QString("SETCONF TrackHostExitsExpire=%2").arg((TorkConfig::trackHostExitsExpire() * 60)))) ; + } + return false; + } + + + if ((*it).name() == "SOCKSBindAddressMany"){ + + if (!TorkConfig::sOCKSBindAddressMany().isEmpty()){ + QStringList socksbind = TorkConfig::sOCKSBindAddressMany(); + for ( QStringList::Iterator it = (socksbind).begin(); it != (socksbind).end(); it++ ) + { + if ((*it).isEmpty()) + continue; + ( sendToServer(QString("SETCONF SOCKSListenAddress=%2").arg((*it)))) ; + } + } + return false; + } + + if ((*it).name() == "ExitPolicy"){ + if (TorkConfig::middleMan()) + ( sendToServer(QString("SETCONF ExitPolicy=%1").arg(("\"reject *:*\"")))) ; + else + ( sendToServer(QString("SETCONF %1=\"%2\"").arg((*it).name()).arg( (*it).property().toStringList().join(",")))); + return false; + } + + + if ((*it).name() == "HiddenServices"){ + QStringList hiddenServices = TorkConfig::hiddenServices(); + QString allservices; + for ( QStringList::Iterator it = (hiddenServices).begin(); it != (hiddenServices).end(); it++ ) + { + if ((*it).isEmpty()) + continue; + allservices += (QString("HiddenServiceDir=\"%1\" HiddenServicePort=\"%2 %3\" ").arg((*it).section("\n",-1)).arg((*it).section("\n",-4,-4)).arg((*it).section("\n",-3,-3))) ; + } + if (!allservices.isEmpty()) + ( sendToServer(QString("SETCONF %1").arg(allservices))) ; + else + ( sendToServer(QString("SETCONF HiddenServiceDir= HiddenServicePort="))) ; + + return false; + } + + if ((TorkConfig::useBridges()) && ((*it).name() == "Bridge")){ + + QStringList bridges = TorkConfig::bridge(); + QString allbridges; + for ( QStringList::Iterator it = (bridges).begin(); it != (bridges).end(); it++ ) + { + if ((*it).isEmpty()) + continue; + allbridges += (QString("Bridge=\"%1\" ") + .arg((*it))) ; + } + if (!allbridges.isEmpty()) + ( sendToServer(QString("SETCONF %1").arg(allbridges))) ; + else + ( sendToServer(QString("SETCONF Bridge="))) ; + + return false; + } + + if ((*it).name() == "MyFamily"){ + + QStringList family = TorkConfig::myFamily(); + QStringList allfamily; + for ( QStringList::Iterator it = (family).begin(); it != (family).end(); it++ ) + { + if ((*it).isEmpty()) + continue; + QString node = "$"+getFPFromFPDigest((*it).section("-",1,1)); + allfamily.append(node) ; + } + if (!allfamily.isEmpty()) + ( sendToServer(QString("SETCONF MyFamily=%1").arg(allfamily.join(",")))) ; + else + ( sendToServer(QString("SETCONF MyFamily="))) ; + + return false; + } + + if ((*it).name() == "MapAddress"){ + + QStringList maps = TorkConfig::mapAddress(); + for ( QStringList::Iterator it = (maps).begin(); + it != (maps).end(); it++ ) + { + if ((*it).isEmpty()) + continue; + ( sendToServer(QString("SETCONF MapAddress=%2").arg((*it)))) ; + } + return false; + } + + if ((!TorkConfig::fascistFirewall()) && ((*it).name() == "ReachableAddresses")){ + ( sendToServer(QString("SETCONF ReachableAddresses="))) ; + return false; + } + return true; +} + + +void TorClient::cleanUp() +{ + + if (TorkConfig::hashedControlPassword().isEmpty() && + (!TorkConfig::cookieAuthentication()) && + TorkConfig::generateRandomPassword()){ + sendToServer(QString("setconf HashedControlPassword=")); + socket->flush(); + } +} + +TorClient::~TorClient() +{ + +} + +void TorClient::parseDirStatus(const QString &info) +{ + + + if (info.left(2) == "r "){ + ds_identity = info.section(" ",2,2); + ds_ip = info.section(" ",6,6); + ds_server = info.section(" ",1,1); + ds_date = info.section(" ",4,4); + return; + } + + if (info.left(2) == "s "){ + + if (QDate::currentDate().daysTo(QDate(ds_date.left(4).toInt(), + ds_date.mid(5,2).toInt(),ds_date.right(2).toInt())) > -30) { + if (server(ds_identity).isEmpty()) + storeServer(ds_server,ds_identity); + + ds_statuses = info; + emit updateServerStatus(ds_ip, ds_identity, ds_server, ds_statuses); + } + } + +} + +bool TorClient::isControllerWorking() +{ + return m_controllerWorking; + +} + +void TorClient::setBandwidth(const QString &rate, const QString &burst, const QString &max) +{ + ( sendToServer(QString("SETCONF BandwidthRate=%2KB BandwidthBurst=%2KB") + .arg(rate).arg(burst))); + if (!max.isEmpty()) + ( sendToServer(QString("SETCONF MaxAdvertisedBandwidth=%2KB").arg(max))); + getBandwidth(); +} + +void TorClient::getBandwidth() +{ + ( sendToServer(QString("GETCONF BandwidthRate"))); + ( sendToServer(QString("GETCONF BandwidthBurst"))); + ( sendToServer(QString("GETCONF MaxAdvertisedBandwidth"))); +} + +void TorClient::handleTorVersion( const QString &caption) +{ + m_currentTorVersion = caption; + if (m_currentTorVersion.left(3) == "0.2") + sendToServer("SETCONF DownloadExtraInfo=1"); + emit setTorCaption(caption); +} + +void TorClient::closeAllCircuits( QListView* &circuitList) +{ + QListViewItemIterator cit(circuitList); + while ( cit.current() ) { + attemptCloseCircuit(cit.current()->text(0)); + ++cit; + } +} + +void TorClient::assignPortToRemove() +{ + //called by the warning message to get the port to remove in case + // user requests it. + if (m_WarnedPorts[0].isNull()) + return; + kdDebug() << "warnedports " << m_WarnedPorts[0] << endl; + m_portToRemove = m_WarnedPorts[0]; + kdDebug() << "porttoremove" << m_portToRemove << endl; + m_WarnedPorts.pop_front(); + kdDebug() << "porttoremove" << m_portToRemove << endl; + +} + +void TorClient::allowPlainTextPorts() +{ + + kdDebug() << "m_portsToReject " << m_portsToReject << endl; + + m_portsToReject.remove(m_portsToReject.find(m_portToRemove)); + sendToServer(QString("SETCONF WarnPlainTextPorts=%1") + .arg(m_portsToReject.join(","))); + sendToServer(QString("SETCONF RejectPlainTextPorts=%1") + .arg(m_portsToReject.join(","))); +} + +void TorClient::resolveAddress(const QString &address) +{ + QRegExp rx("[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}"); + rx.search(address); + QString tmp = rx.cap(0); + if (tmp.isEmpty()) { + sendToServer("RESOLVE " + address); + logResolveList << address; + }else{ + sendToServer("RESOLVE mode=reverse " + tmp); + logResolveList << QString("REVERSE[%1]").arg(tmp); + } + +} + +#include "torclient.moc" + |