Vidalia 0.3.1
TorSocket.cpp
Go to the documentation of this file.
1/*
2** This file is part of Vidalia, and is subject to the license terms in the
3** LICENSE file, found in the top level directory of this distribution. If you
4** did not receive the LICENSE file with this file, you may obtain it from the
5** Vidalia source package distributed by the Vidalia Project at
6** http://www.torproject.org/projects/vidalia.html. No part of Vidalia,
7** including this file, may be copied, modified, propagated, or distributed
8** except according to the terms described in the LICENSE file.
9*/
10
11/*
12** \file TorSocket.cpp
13** \brief A QTcpSocket that makes requests over Tor
14*/
15
16#include "TorSocket.h"
17
18#include <QDataStream>
19
20#define SOCKS_VERSION 0x04 /**< SOCKS version. */
21#define SOCKS_CONNECT 0x01 /**< SOCKS connect command ID. */
22#define SOCKS_FAKE_IP 0x00000001 /**< Bogus IP. */
23#define SOCKS_RESPONSE_LEN 0x08 /**< SOCKS server response length. */
24#define SOCKS_RESPONSE_VERSION 0x00 /**< SOCKS server response version. */
25#define SOCKS_CONNECT_STATUS_OK 0x5A /**< SOCKS server response status. */
26
27
28/** Constructor. */
29TorSocket::TorSocket(const QHostAddress &socksAddr,
30 quint16 socksPort, QObject *parent)
31: QTcpSocket(parent),
32 _socksAddr(socksAddr),
33 _socksPort(socksPort)
34{
35 QObject::connect(this, SIGNAL(error(QAbstractSocket::SocketError)),
36 this, SLOT(onError(QAbstractSocket::SocketError)));
37 QObject::connect(this, SIGNAL(readyRead()),
38 this, SLOT(onHandshakeResponse()));
39 QObject::connect(this, SIGNAL(connected()),
40 this, SLOT(connectedToProxy()));
41}
42
43/** Connects to the specified hostname and port via Tor. */
44void
45TorSocket::connectToRemoteHost(const QString &remoteHost, quint16 remotePort)
46{
47 _remoteHost = remoteHost;
48 _remotePort = remotePort;
49 QTcpSocket::connectToHost(_socksAddr, _socksPort);
50}
51
52/** Called when a connection error has occurred. */
53void
54TorSocket::onError(QAbstractSocket::SocketError error)
55{
56 Q_UNUSED(error);
57 emit socketError(errorString());
58}
59
60/** Called when the socket is connected to the proxy and sends our
61 * half of a Socks4a handshake. */
62void
64{
66}
67
68/** Sends the first part of a Socks4a handshake, using the remote hostname and
69 * port specified in the previous call to connectToHost(). The message should
70 * be formatted as follows:
71 *
72 * 0x04 (socks version)
73 * 0x01 (connect)
74 * PORT (two bytes, most significant byte first)
75 * 0x00 0x00 0x00 0x01 (fake IP address: tells proxy to use SOCKS4a)
76 * 0x00 (empty username field)
77 * HOSTNAME (target hostname)
78 * 0x00 (marks the end of the hostname field)
79 */
80void
81TorSocket::sendSocksHandshake(const QString &remoteHost, quint16 remotePort)
82{
83 QDataStream sock(this);
84 sock << (quint8)SOCKS_VERSION;
85 sock << (quint8)SOCKS_CONNECT;
86 sock << (quint16)remotePort;
87 sock << (quint32)SOCKS_FAKE_IP;
88 sock << (quint8)0;
89 sock.writeRawData(qPrintable(remoteHost), remoteHost.length());
90 sock << (quint8)0;
91}
92
93/** Handles the second half of the handshake, received from the SOCKS
94 * proxy server. The response should be formatted as follows:
95 *
96 * 0x00 (response version)
97 * STATUS (0x5A means success; other values mean failure)
98 * PORT (not set)
99 * ADDRESS (not set)
100 */
101void
103{
104 QByteArray response;
105 if (bytesAvailable() >= SOCKS_RESPONSE_LEN) {
106 /* We've received our response, so stop waiting for it. */
107 QObject::disconnect(this, SIGNAL(readyRead()),
108 this, SLOT(onHandshakeResponse()));
109
110 /* Read the 8-byte response off the socket. */
111 response = read(SOCKS_RESPONSE_LEN);
112
113 /* Check to make sure we got a good response from the proxy. */
114 if ((uchar)response[0] == (uchar)SOCKS_RESPONSE_VERSION &&
115 (uchar)response[1] == (uchar)SOCKS_CONNECT_STATUS_OK) {
116 /* Connection status was okay. */
118 } else {
119 /* Remote connection failed, so close the connection to the proxy. */
120 disconnectFromHost();
121 }
122 }
123}
124
stop errmsg connect(const QHostAddress &address, quint16 port)
stop errmsg disconnect()
#define SOCKS_FAKE_IP
Definition: TorSocket.cpp:22
#define SOCKS_RESPONSE_VERSION
Definition: TorSocket.cpp:24
#define SOCKS_CONNECT_STATUS_OK
Definition: TorSocket.cpp:25
#define SOCKS_CONNECT
Definition: TorSocket.cpp:21
#define SOCKS_VERSION
Definition: TorSocket.cpp:20
#define SOCKS_RESPONSE_LEN
Definition: TorSocket.cpp:23
void onHandshakeResponse()
Definition: TorSocket.cpp:102
void sendSocksHandshake(const QString &remoteHost, quint16 remotePort)
Definition: TorSocket.cpp:81
void connectedToRemoteHost()
TorSocket(const QHostAddress &socksAddr, quint16 socksPort, QObject *parent=0)
Definition: TorSocket.cpp:29
void connectedToProxy()
Definition: TorSocket.cpp:63
void socketError(QString errmsg)
quint16 _remotePort
Definition: TorSocket.h:58
QHostAddress _socksAddr
Definition: TorSocket.h:55
quint16 _socksPort
Definition: TorSocket.h:57
void onError(QAbstractSocket::SocketError error)
Definition: TorSocket.cpp:54
void connectToRemoteHost(const QString &remoteHost, quint16 remotePort)
Definition: TorSocket.cpp:45
QString _remoteHost
Definition: TorSocket.h:56
DebugMessage error(const QString &fmt)
Definition: tcglobal.cpp:40