[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[vidalia-svn] r2149: Add a TorSslSocket that is capable of making encrypted reque (in trunk: . src/util)
Author: edmanm
Date: 2007-12-01 02:40:00 -0500 (Sat, 01 Dec 2007)
New Revision: 2149
Added:
trunk/src/util/torsslsocket.cpp
trunk/src/util/torsslsocket.h
Modified:
trunk/
trunk/src/util/util.pri
Log:
r2178@lysithea: edmanm | 2007-12-01 02:38:32 -0500
Add a TorSslSocket that is capable of making encrypted requests over Tor.
Since it is based on QSslSocket, this is only available on Qt >= 4.3.
Property changes on: trunk
___________________________________________________________________
svk:merge ticket from /local/vidalia/trunk [r2178] on 0108964c-5b0b-4c9e-969f-e2288315d100
Added: trunk/src/util/torsslsocket.cpp
===================================================================
--- trunk/src/util/torsslsocket.cpp (rev 0)
+++ trunk/src/util/torsslsocket.cpp 2007-12-01 07:40:00 UTC (rev 2149)
@@ -0,0 +1,174 @@
+/****************************************************************
+ * Vidalia is distributed under the following license:
+ *
+ * Copyright (C) 2006, Matt Edman, Justin Hipple
+ *
+ * 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 Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ ****************************************************************/
+
+/**
+ * \file torsslsocket.cpp
+ * \version $Id: /local/vidalia/trunk/src/util/torsocket.cpp 1564 2006-12-26T06:06:04.965088Z edmanm $
+ * \brief A QSslSocket that makes encrypted requests over Tor
+ */
+
+#include "torsslsocket.h"
+#if QT_VERSION >= 0x040300
+#include <QDataStream>
+#include <QStringList>
+
+
+#define SOCKS_VERSION 0x04 /**< SOCKS version. */
+#define SOCKS_CONNECT 0x01 /**< SOCKS connect command ID. */
+#define SOCKS_FAKE_IP 0x00000001 /**< Bogus IP. */
+#define SOCKS_RESPONSE_LEN 0x08 /**< SOCKS server response length. */
+#define SOCKS_RESPONSE_VERSION 0x00 /**< SOCKS server response version. */
+#define SOCKS_CONNECT_STATUS_OK 0x5A /**< SOCKS server response status. */
+
+
+/** Constructor. */
+TorSslSocket::TorSslSocket(const QHostAddress &socksAddr,
+ quint16 socksPort, QObject *parent)
+: QSslSocket(parent),
+ _socksAddr(socksAddr),
+ _socksPort(socksPort)
+{
+ QObject::connect(this, SIGNAL(sslErrors(QList<QSslError>)),
+ this, SLOT(onSslErrors(QList<QSslError>)));
+ QObject::connect(this, SIGNAL(error(QAbstractSocket::SocketError)),
+ this, SLOT(onError(QAbstractSocket::SocketError)));
+ QObject::connect(this, SIGNAL(readyRead()),
+ this, SLOT(onHandshakeResponse()));
+ QObject::connect(this, SIGNAL(connected()),
+ this, SLOT(connectedToProxy()));
+ QObject::connect(this, SIGNAL(encrypted()),
+ this, SLOT(onEncrypted()));
+}
+
+/** Connects to the specified hostname and port via Tor. */
+void
+TorSslSocket::connectToRemoteHost(const QString &remoteHost, quint16 remotePort,
+ bool encrypted)
+{
+ _remoteHost = remoteHost;
+ _remotePort = remotePort;
+ _encrypted = encrypted;
+ QTcpSocket::connectToHost(_socksAddr, _socksPort);
+}
+
+/** Called when a connection error has occurred. */
+void
+TorSslSocket::onError(QAbstractSocket::SocketError error)
+{
+ Q_UNUSED(error);
+ emit socketError(errorString());
+}
+
+/** Called when one or more SSL errors occur on the socket. */
+void
+TorSslSocket::onSslErrors(const QList<QSslError> &errors)
+{
+ QStringList errorStrings;
+ foreach (QSslError error, errors) {
+ errorStrings << "\"" + error.errorString() + "\"";
+ }
+ emit socketError(errorStrings.join(","));
+}
+
+/** Called when a connection has been established to the proxy host and starts
+ * a Socks4a handshake. */
+void
+TorSslSocket::connectedToProxy()
+{
+ sendSocksHandshake(_remoteHost, _remotePort);
+}
+
+/** Called when an encrypted connection has been established to the remote
+ * host. */
+void
+TorSslSocket::onEncrypted()
+{
+ emit connectedToRemoteHost();
+}
+
+/** Sends the first part of a Socks4a handshake, using the remote hostname and
+ * port specified in the previous call to connectToHost(). The message should
+ * be formatted as follows:
+ *
+ * 0x04 (socks version)
+ * 0x01 (connect)
+ * PORT (two bytes, most significant byte first)
+ * 0x00 0x00 0x00 0x01 (fake IP address: tells proxy to use SOCKS4a)
+ * 0x00 (empty username field)
+ * HOSTNAME (target hostname)
+ * 0x00 (marks the end of the hostname field)
+ */
+void
+TorSslSocket::sendSocksHandshake(const QString &remoteHost, quint16 remotePort)
+{
+ QDataStream sock(this);
+ sock << (quint8)SOCKS_VERSION;
+ sock << (quint8)SOCKS_CONNECT;
+ sock << (quint16)remotePort;
+ sock << (quint32)SOCKS_FAKE_IP;
+ sock << (quint8)0;
+ sock.writeRawData(qPrintable(remoteHost), remoteHost.length());
+ sock << (quint8)0;
+}
+
+/** Handles the second half of the handshake, received from the SOCKS
+ * proxy server. The response should be formatted as follows:
+ *
+ * 0x00 (response version)
+ * STATUS (0x5A means success; other values mean failure)
+ * PORT (not set)
+ * ADDRESS (not set)
+ */
+void
+TorSslSocket::onHandshakeResponse()
+{
+ QByteArray response;
+ if (bytesAvailable() >= SOCKS_RESPONSE_LEN) {
+ /* We've received our response, so stop waiting for it. */
+ QObject::disconnect(this, SIGNAL(readyRead()),
+ this, SLOT(onHandshakeResponse()));
+
+ /* Read the 8-byte response off the socket. */
+ response = read(SOCKS_RESPONSE_LEN);
+
+ /* Check to make sure we got a good response from the proxy. */
+ if ((uchar)response[0] == (uchar)SOCKS_RESPONSE_VERSION &&
+ (uchar)response[1] == (uchar)SOCKS_CONNECT_STATUS_OK) {
+ if (_encrypted) {
+ /* Connection status was okay, so start client encryption. */
+ /* We first need to set the peer name to the intended remote host,
+ * otherwise Qt will use the proxy (e.g., 127.0.0.1) as the peer name
+ * when validating the server certificate. */
+ setPeerName(_remoteHost);
+ startClientEncryption();
+ } else {
+ /* Caller wanted an unencrypted, unauthenticated, uncool conn. */
+ emit connectedToRemoteHost();
+ }
+ } else {
+ /* Remote connection failed, so close the connection to the proxy. */
+ disconnectFromHost();
+ }
+ }
+}
+
+#endif
+
Added: trunk/src/util/torsslsocket.h
===================================================================
--- trunk/src/util/torsslsocket.h (rev 0)
+++ trunk/src/util/torsslsocket.h 2007-12-01 07:40:00 UTC (rev 2149)
@@ -0,0 +1,87 @@
+/****************************************************************
+ * Vidalia is distributed under the following license:
+ *
+ * Copyright (C) 2006, Matt Edman, Justin Hipple
+ *
+ * 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 Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ ****************************************************************/
+
+/**
+ * \file torsslsocket.h
+ * \version $Id: /local/vidalia/trunk/src/util/torsocket.h 1564 2006-12-26T06:06:04.965088Z edmanm $
+ * \brief A QSslSocket that makes encrypted requests over Tor
+ */
+
+#ifndef _TORSSLSOCKET_H
+#define _TORSSLSOCKET_H
+
+#include <QtGlobal>
+#if QT_VERSION >= 0x040300
+/* XXX: We should do some autoconf magic to and define a HAVE_QSSLSOCKET_H
+ * appropriately. */
+#include <QSslSocket>
+#include <QHostAddress>
+
+
+class TorSslSocket : public QSslSocket
+{
+ Q_OBJECT
+
+public:
+ /** Constructor. */
+ TorSslSocket(const QHostAddress &socksAddr,
+ quint16 socksPort, QObject *parent = 0);
+
+ /** Connects to the specified hostname and port via Tor. */
+ void connectToRemoteHost(const QString &remoteHost, quint16 remotePort,
+ bool encrypted);
+
+signals:
+ /** Emitted when a connection has been established through Tor to the remote
+ * host specified in a prior call to connectToHost(). */
+ void connectedToRemoteHost();
+ /** Emmitted when a connection error has occurred. */
+ void socketError(QString errmsg);
+
+private slots:
+ /** Called when the socket is connected to the proxy and sends our
+ * half of a Socks4a handshake. */
+ void connectedToProxy();
+ /** Called when an encrypted connection has been established to the remote
+ * host. */
+ void onEncrypted();
+ /** Handles the server's response part of a Socks4a handshake. */
+ void onHandshakeResponse();
+ /** Called when a connection error has occurred. */
+ void onError(QAbstractSocket::SocketError error);
+ /** Called when one or more SSL errors occur on the socket. */
+ void onSslErrors(const QList<QSslError> &errors);
+
+private:
+ /** Sends the client part of a Socks4a handshake with a proxy server. */
+ void sendSocksHandshake(const QString &remoteHost, quint16 remotePort);
+
+ QHostAddress _socksAddr; /**< Address of Tor's SOCKS listener. */
+ QString _remoteHost; /**< Remote hostname. */
+ quint16 _socksPort; /**< Port of Tor's SOCKS listener. */
+ quint16 _remotePort; /**< Remote host port. */
+ bool _encrypted; /**< Set to true if the connection to the remote
+ host should be encrypted. */
+};
+
+#endif
+#endif
+
Modified: trunk/src/util/util.pri
===================================================================
--- trunk/src/util/util.pri 2007-12-01 07:39:48 UTC (rev 2148)
+++ trunk/src/util/util.pri 2007-12-01 07:40:00 UTC (rev 2149)
@@ -26,6 +26,7 @@
HEADERS += $$PWD/net.h \
$$PWD/stringutil.h \
$$PWD/torsocket.h \
+ $$PWD/torsslsocket.h \
$$PWD/html.h \
$$PWD/process.h \
$$PWD/file.h \
@@ -36,6 +37,7 @@
SOURCES += $$PWD/net.cpp \
$$PWD/stringutil.cpp \
$$PWD/torsocket.cpp \
+ $$PWD/torsslsocket.cpp \
$$PWD/html.cpp \
$$PWD/process.cpp \
$$PWD/file.cpp \