~ubuntu-branches/ubuntu/saucy/kopete/saucy-proposed

« back to all changes in this revision

Viewing changes to protocols/jabber/libiris/src/irisnet/noncore/cutestuff/socks.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-06-21 02:22:39 UTC
  • Revision ID: package-import@ubuntu.com-20130621022239-63l3zc8p0nf26pt6
Tags: upstream-4.10.80
ImportĀ upstreamĀ versionĀ 4.10.80

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * socks.cpp - SOCKS5 TCP proxy client/server
 
3
 * Copyright (C) 2003  Justin Karneges
 
4
 *
 
5
 * This library is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU Lesser General Public
 
7
 * License as published by the Free Software Foundation; either
 
8
 * version 2.1 of the License, or (at your option) any later version.
 
9
 *
 
10
 * This library is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 * Lesser General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU Lesser General Public
 
16
 * License along with this library; if not, write to the Free Software
 
17
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
18
 *
 
19
 */
 
20
 
 
21
#include "socks.h"
 
22
 
 
23
#include <QHostAddress>
 
24
#include <QStringList>
 
25
#include <QTimer>
 
26
#include <QPointer>
 
27
#include <QSocketNotifier>
 
28
#include <QByteArray>
 
29
 
 
30
#ifdef Q_OS_UNIX
 
31
#include <sys/types.h>
 
32
#include <netinet/in.h>
 
33
#endif
 
34
 
 
35
#ifdef Q_OS_WIN32
 
36
#include <windows.h>
 
37
#endif
 
38
 
 
39
#ifdef Q_OS_UNIX
 
40
#include <unistd.h>
 
41
#include <fcntl.h>
 
42
#endif
 
43
 
 
44
#include "servsock.h"
 
45
#include "bsocket.h"
 
46
 
 
47
//#define PROX_DEBUG
 
48
 
 
49
#ifdef PROX_DEBUG
 
50
#include <stdio.h>
 
51
#endif
 
52
 
 
53
// CS_NAMESPACE_BEGIN
 
54
 
 
55
//----------------------------------------------------------------------------
 
56
// SocksUDP
 
57
//----------------------------------------------------------------------------
 
58
 
 
59
class SocksUDP::Private
 
60
{
 
61
public:
 
62
        QUdpSocket *sd;
 
63
        SocksClient *sc;
 
64
        QHostAddress routeAddr;
 
65
        int routePort;
 
66
        QString host;
 
67
        int port;
 
68
};
 
69
 
 
70
SocksUDP::SocksUDP(SocksClient *sc, const QString &host, int port, const QHostAddress &routeAddr, int routePort)
 
71
:QObject(sc)
 
72
{
 
73
        d = new Private;
 
74
        d->sc = sc;
 
75
        d->sd = new QUdpSocket(this);
 
76
        connect(d->sd, SIGNAL(readyRead()), SLOT(sd_readyRead()));
 
77
        d->host = host;
 
78
        d->port = port;
 
79
        d->routeAddr = routeAddr;
 
80
        d->routePort = routePort;
 
81
}
 
82
 
 
83
SocksUDP::~SocksUDP()
 
84
{
 
85
        delete d->sd;
 
86
        delete d;
 
87
}
 
88
 
 
89
void SocksUDP::change(const QString &host, int port)
 
90
{
 
91
        d->host = host;
 
92
        d->port = port;
 
93
}
 
94
 
 
95
void SocksUDP::write(const QByteArray &data)
 
96
{
 
97
        d->sd->writeDatagram(data.data(), data.size(), d->routeAddr, d->routePort);
 
98
}
 
99
 
 
100
void SocksUDP::sd_activated()
 
101
{
 
102
        while (d->sd->hasPendingDatagrams()) {
 
103
                QByteArray datagram;
 
104
                datagram.resize(d->sd->pendingDatagramSize());
 
105
                d->sd->readDatagram(datagram.data(), datagram.size());
 
106
                packetReady(datagram);
 
107
        }
 
108
}
 
109
 
 
110
//----------------------------------------------------------------------------
 
111
// SocksClient
 
112
//----------------------------------------------------------------------------
 
113
#define REQ_CONNECT      0x01
 
114
#define REQ_BIND         0x02
 
115
#define REQ_UDPASSOCIATE 0x03
 
116
 
 
117
#define RET_SUCCESS      0x00
 
118
#define RET_UNREACHABLE  0x04
 
119
#define RET_CONNREFUSED  0x05
 
120
 
 
121
// spc = socks packet client
 
122
// sps = socks packet server
 
123
// SPCS = socks packet client struct
 
124
// SPSS = socks packet server struct
 
125
 
 
126
// Version
 
127
static QByteArray spc_set_version(bool hasCreds)
 
128
{
 
129
        QByteArray ver;
 
130
        ver.resize(hasCreds? 4 : 3);
 
131
        ver[0] = 0x05; // socks version 5
 
132
        ver[2] = 0x00; // no-auth
 
133
        if (hasCreds) {
 
134
                ver[1] = 0x02; // number of methods
 
135
                ver[3] = 0x02; // username
 
136
        } else {
 
137
                ver[1] = 0x01; // number of methods
 
138
        }
 
139
        return ver;
 
140
}
 
141
 
 
142
static QByteArray sps_set_version(int method)
 
143
{
 
144
        QByteArray ver;
 
145
        ver.resize(2);
 
146
        ver[0] = 0x05;
 
147
        ver[1] = method;
 
148
        return ver;
 
149
}
 
150
 
 
151
struct SPCS_VERSION
 
152
{
 
153
        unsigned char version;
 
154
        QByteArray methodList;
 
155
};
 
156
 
 
157
static int spc_get_version(QByteArray &from, SPCS_VERSION *s)
 
158
{
 
159
        if(from.size() < 1)
 
160
                return 0;
 
161
        if(from.at(0) != 0x05) // only SOCKS5 supported
 
162
                return -1;
 
163
        if(from.size() < 2)
 
164
                return 0;
 
165
        unsigned char mlen = from.at(1);
 
166
        int num = mlen;
 
167
        if(num > 16) // who the heck has over 16 auth methods??
 
168
                return -1;
 
169
        if(from.size() < 2 + num)
 
170
                return 0;
 
171
        QByteArray a = ByteStream::takeArray(from, 2+num);
 
172
        s->version = a[0];
 
173
        s->methodList.resize(num);
 
174
        memcpy(s->methodList.data(), a.data() + 2, num);
 
175
        return 1;
 
176
}
 
177
 
 
178
struct SPSS_VERSION
 
179
{
 
180
        unsigned char version;
 
181
        unsigned char method;
 
182
};
 
183
 
 
184
static int sps_get_version(QByteArray &from, SPSS_VERSION *s)
 
185
{
 
186
        if(from.size() < 2)
 
187
                return 0;
 
188
        QByteArray a = ByteStream::takeArray(from, 2);
 
189
        s->version = a[0];
 
190
        s->method = a[1];
 
191
        return 1;
 
192
}
 
193
 
 
194
// authUsername
 
195
static QByteArray spc_set_authUsername(const QByteArray &user, const QByteArray &pass)
 
196
{
 
197
        int len1 = user.length();
 
198
        int len2 = pass.length();
 
199
        if(len1 > 255)
 
200
                len1 = 255;
 
201
        if(len2 > 255)
 
202
                len2 = 255;
 
203
        QByteArray a;
 
204
        a.resize(1+1+len1+1+len2);
 
205
        a[0] = 0x01; // username auth version 1
 
206
        a[1] = len1;
 
207
        memcpy(a.data() + 2, user.data(), len1);
 
208
        a[2+len1] = len2;
 
209
        memcpy(a.data() + 3 + len1, pass.data(), len2);
 
210
        return a;
 
211
}
 
212
 
 
213
static QByteArray sps_set_authUsername(bool success)
 
214
{
 
215
        QByteArray a;
 
216
        a.resize(2);
 
217
        a[0] = 0x01;
 
218
        a[1] = success ? 0x00 : 0xff;
 
219
        return a;
 
220
}
 
221
 
 
222
struct SPCS_AUTHUSERNAME
 
223
{
 
224
        QString user, pass;
 
225
};
 
226
 
 
227
static int spc_get_authUsername(QByteArray &from, SPCS_AUTHUSERNAME *s)
 
228
{
 
229
        if(from.size() < 1)
 
230
                return 0;
 
231
        unsigned char ver = from.at(0);
 
232
        if(ver != 0x01)
 
233
                return -1;
 
234
        if(from.size() < 2)
 
235
                return 0;
 
236
        unsigned char ulen = from.at(1);
 
237
        if((int)from.size() < ulen + 3)
 
238
                return 0;
 
239
        unsigned char plen = from.at(ulen+2);
 
240
        if((int)from.size() < ulen + plen + 3)
 
241
                return 0;
 
242
        QByteArray a = ByteStream::takeArray(from, ulen + plen + 3);
 
243
 
 
244
        QByteArray user, pass;
 
245
        user.resize(ulen);
 
246
        pass.resize(plen);
 
247
        memcpy(user.data(), a.data()+2, ulen);
 
248
        memcpy(pass.data(), a.data()+ulen+3, plen);
 
249
        s->user = QString::fromUtf8(user);
 
250
        s->pass = QString::fromUtf8(pass);
 
251
        return 1;
 
252
}
 
253
 
 
254
struct SPSS_AUTHUSERNAME
 
255
{
 
256
        unsigned char version;
 
257
        bool success;
 
258
};
 
259
 
 
260
static int sps_get_authUsername(QByteArray &from, SPSS_AUTHUSERNAME *s)
 
261
{
 
262
        if(from.size() < 2)
 
263
                return 0;
 
264
        QByteArray a = ByteStream::takeArray(from, 2);
 
265
        s->version = a[0];
 
266
        s->success = ((char) a[1] == 0 ? true: false);
 
267
        return 1;
 
268
}
 
269
 
 
270
// connectRequest
 
271
static QByteArray sp_set_request(const QHostAddress &addr, unsigned short port, unsigned char cmd1)
 
272
{
 
273
        int at = 0;
 
274
        QByteArray a;
 
275
        a.resize(4);
 
276
        a[at++] = 0x05; // socks version 5
 
277
        a[at++] = cmd1;
 
278
        a[at++] = 0x00; // reserved
 
279
        if(addr.protocol() == QAbstractSocket::IPv4Protocol || addr.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol) {
 
280
                a[at++] = 0x01; // address type = ipv4
 
281
                quint32 ip4 = htonl(addr.toIPv4Address());
 
282
                a.resize(at+4);
 
283
                memcpy(a.data() + at, &ip4, 4);
 
284
                at += 4;
 
285
        }
 
286
        else {
 
287
                a[at++] = 0x04;
 
288
                Q_IPV6ADDR ip6 = addr.toIPv6Address();
 
289
                a.resize(at+16);
 
290
                for(int i = 0; i < 16; ++i)
 
291
                        a[at++] = ip6[i];
 
292
        }
 
293
 
 
294
        // port
 
295
        a.resize(at+2);
 
296
        quint16 p = htons(port);
 
297
        memcpy(a.data() + at, &p, 2);
 
298
 
 
299
        return a;
 
300
}
 
301
 
 
302
static QByteArray sp_set_request(const QString &host, quint16 port, unsigned char cmd1)
 
303
{
 
304
        // detect for IP addresses
 
305
        QHostAddress addr;
 
306
        if(addr.setAddress(host))
 
307
                return sp_set_request(addr, port, cmd1);
 
308
 
 
309
        QByteArray h = host.toUtf8();
 
310
        h.truncate(255);
 
311
        h = QString::fromUtf8(h).toUtf8(); // delete any partial characters?
 
312
        int hlen = h.length();
 
313
 
 
314
        int at = 0;
 
315
        QByteArray a;
 
316
        a.resize(4);
 
317
        a[at++] = 0x05; // socks version 5
 
318
        a[at++] = cmd1;
 
319
        a[at++] = 0x00; // reserved
 
320
        a[at++] = 0x03; // address type = domain
 
321
 
 
322
        // host
 
323
        a.resize(at+hlen+1);
 
324
        a[at++] = hlen;
 
325
        memcpy(a.data() + at, h.data(), hlen);
 
326
        at += hlen;
 
327
 
 
328
        // port
 
329
        a.resize(at+2);
 
330
        unsigned short p = htons(port);
 
331
        memcpy(a.data() + at, &p, 2);
 
332
 
 
333
        return a;
 
334
}
 
335
 
 
336
struct SPS_CONNREQ
 
337
{
 
338
        unsigned char version;
 
339
        unsigned char cmd;
 
340
        int address_type;
 
341
        QString host;
 
342
        QHostAddress addr;
 
343
        quint16 port;
 
344
};
 
345
 
 
346
static int sp_get_request(QByteArray &from, SPS_CONNREQ *s)
 
347
{
 
348
        int full_len = 4;
 
349
        if((int)from.size() < full_len)
 
350
                return 0;
 
351
 
 
352
        QString host;
 
353
        QHostAddress addr;
 
354
        unsigned char atype = from.at(3);
 
355
 
 
356
        if(atype == 0x01) {
 
357
                full_len += 4;
 
358
                if((int)from.size() < full_len)
 
359
                        return 0;
 
360
                quint32 ip4;
 
361
                memcpy(&ip4, from.data() + 4, 4);
 
362
                addr.setAddress(ntohl(ip4));
 
363
        }
 
364
        else if(atype == 0x03) {
 
365
                ++full_len;
 
366
                if((int)from.size() < full_len)
 
367
                        return 0;
 
368
                unsigned char host_len = from.at(4);
 
369
                full_len += host_len;
 
370
                if((int)from.size() < full_len)
 
371
                        return 0;
 
372
                QByteArray cs;
 
373
                cs.resize(host_len);
 
374
                memcpy(cs.data(), from.data() + 5, host_len);
 
375
                host = QString::fromLatin1(cs);
 
376
        }
 
377
        else if(atype == 0x04) {
 
378
                full_len += 16;
 
379
                if((int)from.size() < full_len)
 
380
                        return 0;
 
381
                quint8 a6[16];
 
382
                memcpy(a6, from.data() + 4, 16);
 
383
                addr.setAddress(a6);
 
384
        }
 
385
 
 
386
        full_len += 2;
 
387
        if((int)from.size() < full_len)
 
388
                return 0;
 
389
 
 
390
        QByteArray a = ByteStream::takeArray(from, full_len);
 
391
 
 
392
        quint16 p;
 
393
        memcpy(&p, a.data() + full_len - 2, 2);
 
394
 
 
395
        s->version = a[0];
 
396
        s->cmd = a[1];
 
397
        s->address_type = atype;
 
398
        s->host = host;
 
399
        s->addr = addr;
 
400
        s->port = ntohs(p);
 
401
 
 
402
        return 1;
 
403
}
 
404
 
 
405
enum { StepVersion, StepAuth, StepRequest };
 
406
 
 
407
class SocksClient::Private
 
408
{
 
409
public:
 
410
        Private(SocksClient *_q) :
 
411
                sock(_q)
 
412
        {
 
413
        }
 
414
 
 
415
        BSocket sock;
 
416
        QString host;
 
417
        int port;
 
418
        QString user, pass;
 
419
        QString real_host;
 
420
        int real_port;
 
421
 
 
422
        QByteArray recvBuf;
 
423
        int step;
 
424
        int authMethod;
 
425
        bool incoming, waiting;
 
426
 
 
427
        QString rhost;
 
428
        int rport;
 
429
 
 
430
        int pending;
 
431
 
 
432
        bool udp;
 
433
        QString udpAddr;
 
434
        int udpPort;
 
435
};
 
436
 
 
437
SocksClient::SocksClient(QObject *parent)
 
438
:ByteStream(parent)
 
439
{
 
440
        init();
 
441
 
 
442
        d->incoming = false;
 
443
}
 
444
 
 
445
SocksClient::SocksClient(int s, QObject *parent)
 
446
:ByteStream(parent)
 
447
{
 
448
        init();
 
449
 
 
450
        d->incoming = true;
 
451
        d->waiting = true;
 
452
        d->sock.setSocket(s);
 
453
}
 
454
 
 
455
void SocksClient::init()
 
456
{
 
457
        d = new Private(this);
 
458
        connect(&d->sock, SIGNAL(connected()), SLOT(sock_connected()));
 
459
        connect(&d->sock, SIGNAL(connectionClosed()), SLOT(sock_connectionClosed()));
 
460
        connect(&d->sock, SIGNAL(delayedCloseFinished()), SLOT(sock_delayedCloseFinished()));
 
461
        connect(&d->sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
 
462
        connect(&d->sock, SIGNAL(bytesWritten(qint64)), SLOT(sock_bytesWritten(qint64)));
 
463
        connect(&d->sock, SIGNAL(error(int)), SLOT(sock_error(int)));
 
464
 
 
465
        resetConnection(true);
 
466
}
 
467
 
 
468
SocksClient::~SocksClient()
 
469
{
 
470
        resetConnection(true);
 
471
        delete d;
 
472
}
 
473
 
 
474
QAbstractSocket* SocksClient::abstractSocket() const
 
475
{
 
476
        return d->sock.abstractSocket();
 
477
}
 
478
 
 
479
void SocksClient::resetConnection(bool clear)
 
480
{
 
481
        if(d->sock.state() != BSocket::Idle)
 
482
                d->sock.close();
 
483
        if(clear)
 
484
                clearReadBuffer();
 
485
        d->recvBuf.resize(0);
 
486
        d->waiting = false;
 
487
        d->udp = false;
 
488
        d->pending = 0;
 
489
        if (bytesAvailable()) {
 
490
                setOpenMode(QIODevice::ReadOnly);
 
491
        } else {
 
492
                setOpenMode(QIODevice::NotOpen);
 
493
        }
 
494
}
 
495
 
 
496
bool SocksClient::isIncoming() const
 
497
{
 
498
        return d->incoming;
 
499
}
 
500
 
 
501
void SocksClient::setAuth(const QString &user, const QString &pass)
 
502
{
 
503
        d->user = user;
 
504
        d->pass = pass;
 
505
}
 
506
 
 
507
void SocksClient::connectToHost(const QString &proxyHost, int proxyPort, const QString &host, int port, bool udpMode)
 
508
{
 
509
        resetConnection(true);
 
510
 
 
511
        d->host = proxyHost;
 
512
        d->port = proxyPort;
 
513
        d->real_host = host;
 
514
        d->real_port = port;
 
515
        d->udp = udpMode;
 
516
 
 
517
#ifdef PROX_DEBUG
 
518
        fprintf(stderr, "SocksClient: Connecting to %s:%d", qPrintable(proxyHost), proxyPort);
 
519
        if(d->user.isEmpty())
 
520
                fprintf(stderr, "\n");
 
521
        else
 
522
                fprintf(stderr, ", auth {%s,%s}\n", qPrintable(d->user), qPrintable(d->pass));
 
523
#endif
 
524
        d->sock.connectToHost(d->host, d->port);
 
525
}
 
526
 
 
527
void SocksClient::close()
 
528
{
 
529
        d->sock.close();
 
530
        if(d->sock.bytesToWrite() == 0)
 
531
                resetConnection();
 
532
}
 
533
 
 
534
void SocksClient::writeData(const QByteArray &buf)
 
535
{
 
536
#ifdef PROX_DEBUG
 
537
        // show hex
 
538
        fprintf(stderr, "SocksClient: client write { ");
 
539
        for(int n = 0; n < (int)buf.size(); ++n)
 
540
                fprintf(stderr, "%02X ", (unsigned char)buf[n]);
 
541
        fprintf(stderr, " } \n");
 
542
#endif
 
543
        d->pending += buf.size();
 
544
        d->sock.write(buf);
 
545
}
 
546
 
 
547
qint64 SocksClient::writeData(const char *data, qint64 maxSize)
 
548
{
 
549
        if(isOpen() && !d->udp)
 
550
                return d->sock.write(data, maxSize);
 
551
        return 0;
 
552
}
 
553
 
 
554
qint64 SocksClient::readData(char *data, qint64 maxSize)
 
555
{
 
556
        qint64 ret = ByteStream::readData(data, maxSize);
 
557
        if (d->sock.state() != BSocket::Connected && !bytesAvailable()) {
 
558
                setOpenMode(QIODevice::NotOpen);
 
559
        }
 
560
        return ret;
 
561
}
 
562
 
 
563
qint64 SocksClient::bytesAvailable() const
 
564
{
 
565
        return ByteStream::bytesAvailable();
 
566
}
 
567
 
 
568
qint64 SocksClient::bytesToWrite() const
 
569
{
 
570
        if(isOpen())
 
571
                return d->sock.bytesToWrite();
 
572
        else
 
573
                return 0;
 
574
}
 
575
 
 
576
void SocksClient::sock_connected()
 
577
{
 
578
#ifdef PROX_DEBUG
 
579
        fprintf(stderr, "SocksClient: Connected\n");
 
580
#endif
 
581
 
 
582
        d->step = StepVersion;
 
583
        writeData(spc_set_version(!d->user.isEmpty())); // fixme requirement for auth should set outside
 
584
}
 
585
 
 
586
void SocksClient::sock_connectionClosed()
 
587
{
 
588
        if(isOpen()) {
 
589
                resetConnection();
 
590
                emit connectionClosed();
 
591
        }
 
592
        else {
 
593
                setError(ErrProxyNeg);
 
594
        }
 
595
}
 
596
 
 
597
void SocksClient::sock_delayedCloseFinished()
 
598
{
 
599
        if(isOpen()) {
 
600
                resetConnection();
 
601
                delayedCloseFinished();
 
602
        }
 
603
}
 
604
 
 
605
void SocksClient::sock_readyRead()
 
606
{
 
607
        QByteArray block = d->sock.readAll();
 
608
 
 
609
        //qDebug() << this << "::sock_readyRead " << block.size() << " bytes." <<
 
610
        //                      "udp=" << d->udp << openMode();
 
611
        if(!isOpen()) {
 
612
                if(d->incoming)
 
613
                        processIncoming(block);
 
614
                else
 
615
                        processOutgoing(block);
 
616
        }
 
617
        else {
 
618
                if(!d->udp) {
 
619
                        appendRead(block);
 
620
                        emit readyRead();
 
621
                }
 
622
        }
 
623
}
 
624
 
 
625
void SocksClient::processOutgoing(const QByteArray &block)
 
626
{
 
627
#ifdef PROX_DEBUG
 
628
        // show hex
 
629
        fprintf(stderr, "SocksClient: client recv { ");
 
630
        for(int n = 0; n < (int)block.size(); ++n)
 
631
                fprintf(stderr, "%02X ", (unsigned char)block[n]);
 
632
        fprintf(stderr, " } \n");
 
633
#endif
 
634
        d->recvBuf += block;
 
635
 
 
636
        if(d->step == StepVersion) {
 
637
                SPSS_VERSION s;
 
638
                int r = sps_get_version(d->recvBuf, &s);
 
639
                if(r == -1) {
 
640
                        resetConnection(true);
 
641
                        setError(ErrProxyNeg);
 
642
                        return;
 
643
                }
 
644
                else if(r == 1) {
 
645
                        if(s.version != 0x05 || s.method == 0xff) {
 
646
#ifdef PROX_DEBUG
 
647
                                fprintf(stderr, "SocksClient: Method selection failed\n");
 
648
#endif
 
649
                                resetConnection(true);
 
650
                                setError(ErrProxyNeg);
 
651
                                return;
 
652
                        }
 
653
 
 
654
                        QString str;
 
655
                        if(s.method == 0x00) {
 
656
                                str = "None";
 
657
                                d->authMethod = AuthNone;
 
658
                        }
 
659
                        else if(s.method == 0x02) {
 
660
                                str = "Username/Password";
 
661
                                d->authMethod = AuthUsername;
 
662
                        }
 
663
                        else {
 
664
#ifdef PROX_DEBUG
 
665
                                fprintf(stderr, "SocksClient: Server wants to use unknown method '%02x'\n", s.method);
 
666
#endif
 
667
                                resetConnection(true);
 
668
                                setError(ErrProxyNeg);
 
669
                                return;
 
670
                        }
 
671
 
 
672
                        if(d->authMethod == AuthNone) {
 
673
                                // no auth, go straight to the request
 
674
                                do_request();
 
675
                        }
 
676
                        else if(d->authMethod == AuthUsername) {
 
677
                                d->step = StepAuth;
 
678
#ifdef PROX_DEBUG
 
679
                                fprintf(stderr, "SocksClient: Authenticating [Username] ...\n");
 
680
#endif
 
681
                                writeData(spc_set_authUsername(d->user.toLatin1(), d->pass.toLatin1()));
 
682
                        }
 
683
                }
 
684
        }
 
685
        if(d->step == StepAuth) {
 
686
                if(d->authMethod == AuthUsername) {
 
687
                        SPSS_AUTHUSERNAME s;
 
688
                        int r = sps_get_authUsername(d->recvBuf, &s);
 
689
                        if(r == -1) {
 
690
                                resetConnection(true);
 
691
                                setError(ErrProxyNeg);
 
692
                                return;
 
693
                        }
 
694
                        else if(r == 1) {
 
695
                                if(s.version != 0x01) {
 
696
                                        resetConnection(true);
 
697
                                        setError(ErrProxyNeg);
 
698
                                        return;
 
699
                                }
 
700
                                if(!s.success) {
 
701
                                        resetConnection(true);
 
702
                                        setError(ErrProxyAuth);
 
703
                                        return;
 
704
                                }
 
705
 
 
706
                                do_request();
 
707
                        }
 
708
                }
 
709
        }
 
710
        else if(d->step == StepRequest) {
 
711
                SPS_CONNREQ s;
 
712
                int r = sp_get_request(d->recvBuf, &s);
 
713
                if(r == -1) {
 
714
                        resetConnection(true);
 
715
                        setError(ErrProxyNeg);
 
716
                        return;
 
717
                }
 
718
                else if(r == 1) {
 
719
                        if(s.cmd != RET_SUCCESS) {
 
720
#ifdef PROX_DEBUG
 
721
                                fprintf(stderr, "SocksClient: client << Error >> [%02x]\n", s.cmd);
 
722
#endif
 
723
                                resetConnection(true);
 
724
                                if(s.cmd == RET_UNREACHABLE)
 
725
                                        setError(ErrHostNotFound);
 
726
                                else if(s.cmd == RET_CONNREFUSED)
 
727
                                        setError(ErrConnectionRefused);
 
728
                                else
 
729
                                        setError(ErrProxyNeg);
 
730
                                return;
 
731
                        }
 
732
 
 
733
#ifdef PROX_DEBUG
 
734
                        fprintf(stderr, "SocksClient: client << Success >>\n");
 
735
#endif
 
736
                        if(d->udp) {
 
737
                                if(s.address_type == 0x03)
 
738
                                        d->udpAddr = s.host;
 
739
                                else
 
740
                                        d->udpAddr = s.addr.toString();
 
741
                                d->udpPort = s.port;
 
742
                        }
 
743
 
 
744
                        setOpenMode(QIODevice::ReadWrite);
 
745
 
 
746
                        QPointer<QObject> self = this;
 
747
                        setOpenMode(QIODevice::ReadWrite);
 
748
                        emit connected();
 
749
                        if(!self)
 
750
                                return;
 
751
 
 
752
                        if(!d->recvBuf.isEmpty()) {
 
753
                                appendRead(d->recvBuf);
 
754
                                d->recvBuf.resize(0);
 
755
                                readyRead();
 
756
                        }
 
757
                }
 
758
        }
 
759
}
 
760
 
 
761
void SocksClient::do_request()
 
762
{
 
763
#ifdef PROX_DEBUG
 
764
        fprintf(stderr, "SocksClient: Requesting ...\n");
 
765
#endif
 
766
        d->step = StepRequest;
 
767
        int cmd = d->udp ? REQ_UDPASSOCIATE : REQ_CONNECT;
 
768
        QByteArray buf;
 
769
        if(!d->real_host.isEmpty())
 
770
                buf = sp_set_request(d->real_host, d->real_port, cmd);
 
771
        else
 
772
                buf = sp_set_request(QHostAddress(), 0, cmd);
 
773
        writeData(buf);
 
774
}
 
775
 
 
776
void SocksClient::sock_bytesWritten(qint64 x)
 
777
{
 
778
        int bytes = x;
 
779
        if(d->pending >= bytes) {
 
780
                d->pending -= bytes;
 
781
                bytes = 0;
 
782
        }
 
783
        else {
 
784
                bytes -= d->pending;
 
785
                d->pending = 0;
 
786
        }
 
787
        if(bytes > 0)
 
788
                bytesWritten(bytes);
 
789
}
 
790
 
 
791
void SocksClient::sock_error(int x)
 
792
{
 
793
        if(isOpen()) {
 
794
                resetConnection();
 
795
                setError(ErrRead);
 
796
        }
 
797
        else {
 
798
                resetConnection(true);
 
799
                if(x == BSocket::ErrHostNotFound)
 
800
                        setError(ErrProxyConnect);
 
801
                else if(x == BSocket::ErrConnectionRefused)
 
802
                        setError(ErrProxyConnect);
 
803
                else if(x == BSocket::ErrRead)
 
804
                        setError(ErrProxyNeg);
 
805
        }
 
806
}
 
807
 
 
808
void SocksClient::serve()
 
809
{
 
810
        d->waiting = false;
 
811
        d->step = StepVersion;
 
812
        continueIncoming();
 
813
}
 
814
 
 
815
void SocksClient::processIncoming(const QByteArray &block)
 
816
{
 
817
#ifdef PROX_DEBUG
 
818
        // show hex
 
819
        fprintf(stderr, "SocksClient: server recv { ");
 
820
        for(int n = 0; n < (int)block.size(); ++n)
 
821
                fprintf(stderr, "%02X ", (unsigned char)block[n]);
 
822
        fprintf(stderr, " } \n");
 
823
#endif
 
824
        d->recvBuf += block;
 
825
 
 
826
        if(!d->waiting)
 
827
                continueIncoming();
 
828
}
 
829
 
 
830
void SocksClient::continueIncoming()
 
831
{
 
832
        if(d->recvBuf.isEmpty())
 
833
                return;
 
834
 
 
835
        if(d->step == StepVersion) {
 
836
                SPCS_VERSION s;
 
837
                int r = spc_get_version(d->recvBuf, &s);
 
838
                if(r == -1) {
 
839
                        resetConnection(true);
 
840
                        setError(ErrProxyNeg);
 
841
                        return;
 
842
                }
 
843
                else if(r == 1) {
 
844
                        if(s.version != 0x05) {
 
845
                                resetConnection(true);
 
846
                                setError(ErrProxyNeg);
 
847
                                return;
 
848
                        }
 
849
 
 
850
                        int methods = 0;
 
851
                        for(int n = 0; n < (int)s.methodList.size(); ++n) {
 
852
                                unsigned char c = s.methodList[n];
 
853
                                if(c == 0x00)
 
854
                                        methods |= AuthNone;
 
855
                                else if(c == 0x02)
 
856
                                        methods |= AuthUsername;
 
857
                        }
 
858
                        d->waiting = true;
 
859
                        emit incomingMethods(methods);
 
860
                }
 
861
        }
 
862
        else if(d->step == StepAuth) {
 
863
                SPCS_AUTHUSERNAME s;
 
864
                int r = spc_get_authUsername(d->recvBuf, &s);
 
865
                if(r == -1) {
 
866
                        resetConnection(true);
 
867
                        setError(ErrProxyNeg);
 
868
                        return;
 
869
                }
 
870
                else if(r == 1) {
 
871
                        d->waiting = true;
 
872
                        incomingAuth(s.user, s.pass);
 
873
                }
 
874
        }
 
875
        else if(d->step == StepRequest) {
 
876
                SPS_CONNREQ s;
 
877
                int r = sp_get_request(d->recvBuf, &s);
 
878
                if(r == -1) {
 
879
                        resetConnection(true);
 
880
                        setError(ErrProxyNeg);
 
881
                        return;
 
882
                }
 
883
                else if(r == 1) {
 
884
                        d->waiting = true;
 
885
                        if(s.cmd == REQ_CONNECT) {
 
886
                                if(!s.host.isEmpty())
 
887
                                        d->rhost = s.host;
 
888
                                else
 
889
                                        d->rhost = s.addr.toString();
 
890
                                d->rport = s.port;
 
891
                                incomingConnectRequest(d->rhost, d->rport);
 
892
                        }
 
893
                        else if(s.cmd == REQ_UDPASSOCIATE) {
 
894
                                incomingUDPAssociateRequest();
 
895
                        }
 
896
                        else {
 
897
                                requestDeny();
 
898
                                return;
 
899
                        }
 
900
                }
 
901
        }
 
902
}
 
903
 
 
904
void SocksClient::chooseMethod(int method)
 
905
{
 
906
        if(d->step != StepVersion || !d->waiting)
 
907
                return;
 
908
 
 
909
        unsigned char c;
 
910
        if(method == AuthNone) {
 
911
                d->step = StepRequest;
 
912
                c = 0x00;
 
913
        }
 
914
        else {
 
915
                d->step = StepAuth;
 
916
                c = 0x02;
 
917
        }
 
918
 
 
919
        // version response
 
920
        d->waiting = false;
 
921
        writeData(sps_set_version(c));
 
922
        continueIncoming();
 
923
}
 
924
 
 
925
void SocksClient::authGrant(bool b)
 
926
{
 
927
        if(d->step != StepAuth || !d->waiting)
 
928
                return;
 
929
 
 
930
        if(b)
 
931
                d->step = StepRequest;
 
932
 
 
933
        // auth response
 
934
        d->waiting = false;
 
935
        writeData(sps_set_authUsername(b));
 
936
        if(!b) {
 
937
                resetConnection(true);
 
938
                return;
 
939
        }
 
940
        continueIncoming();
 
941
}
 
942
 
 
943
void SocksClient::requestDeny()
 
944
{
 
945
        if(d->step != StepRequest || !d->waiting)
 
946
                return;
 
947
 
 
948
        // response
 
949
        d->waiting = false;
 
950
        writeData(sp_set_request(d->rhost, d->rport, RET_UNREACHABLE));
 
951
        resetConnection(true);
 
952
}
 
953
 
 
954
void SocksClient::grantConnect()
 
955
{
 
956
        if(d->step != StepRequest || !d->waiting)
 
957
                return;
 
958
 
 
959
        // response
 
960
        d->waiting = false;
 
961
        writeData(sp_set_request(d->rhost, d->rport, RET_SUCCESS));
 
962
        setOpenMode(QIODevice::ReadWrite);
 
963
#ifdef PROX_DEBUG
 
964
        fprintf(stderr, "SocksClient: server << Success >>\n");
 
965
#endif
 
966
 
 
967
        if(!d->recvBuf.isEmpty()) {
 
968
                appendRead(d->recvBuf);
 
969
                d->recvBuf.resize(0);
 
970
                readyRead();
 
971
        }
 
972
}
 
973
 
 
974
void SocksClient::grantUDPAssociate(const QString &relayHost, int relayPort)
 
975
{
 
976
        if(d->step != StepRequest || !d->waiting)
 
977
                return;
 
978
 
 
979
        // response
 
980
        d->waiting = false;
 
981
        writeData(sp_set_request(relayHost, relayPort, RET_SUCCESS));
 
982
        d->udp = true;
 
983
        setOpenMode(QIODevice::ReadWrite);
 
984
#ifdef PROX_DEBUG
 
985
        fprintf(stderr, "SocksClient: server << Success >>\n");
 
986
#endif
 
987
 
 
988
        if(!d->recvBuf.isEmpty())
 
989
                d->recvBuf.resize(0);
 
990
}
 
991
 
 
992
QHostAddress SocksClient::peerAddress() const
 
993
{
 
994
        return d->sock.peerAddress();
 
995
}
 
996
 
 
997
quint16 SocksClient::peerPort() const
 
998
{
 
999
        return d->sock.peerPort();
 
1000
}
 
1001
 
 
1002
QString SocksClient::udpAddress() const
 
1003
{
 
1004
        return d->udpAddr;
 
1005
}
 
1006
 
 
1007
quint16 SocksClient::udpPort() const
 
1008
{
 
1009
        return d->udpPort;
 
1010
}
 
1011
 
 
1012
SocksUDP *SocksClient::createUDP(const QString &host, int port, const QHostAddress &routeAddr, int routePort)
 
1013
{
 
1014
        return new SocksUDP(this, host, port, routeAddr, routePort);
 
1015
}
 
1016
 
 
1017
//----------------------------------------------------------------------------
 
1018
// SocksServer
 
1019
//----------------------------------------------------------------------------
 
1020
class SocksServer::Private
 
1021
{
 
1022
public:
 
1023
        Private(SocksServer *_q) :
 
1024
                serv(_q)
 
1025
        {
 
1026
        }
 
1027
 
 
1028
        ServSock serv;
 
1029
        QList<SocksClient*> incomingConns;
 
1030
        QUdpSocket *sd;
 
1031
};
 
1032
 
 
1033
SocksServer::SocksServer(QObject *parent)
 
1034
:QObject(parent)
 
1035
{
 
1036
        d = new Private(this);
 
1037
        d->sd = 0;
 
1038
        connect(&d->serv, SIGNAL(connectionReady(int)), SLOT(connectionReady(int)));
 
1039
}
 
1040
 
 
1041
SocksServer::~SocksServer()
 
1042
{
 
1043
        stop();
 
1044
        while (d->incomingConns.count()) {
 
1045
                delete d->incomingConns.takeFirst();
 
1046
        }
 
1047
        delete d;
 
1048
}
 
1049
 
 
1050
bool SocksServer::isActive() const
 
1051
{
 
1052
        return d->serv.isActive();
 
1053
}
 
1054
 
 
1055
bool SocksServer::listen(quint16 port, bool udp)
 
1056
{
 
1057
        stop();
 
1058
        if(!d->serv.listen(port))
 
1059
                return false;
 
1060
        if(udp) {
 
1061
                d->sd = new QUdpSocket(this);
 
1062
                if(!d->sd->bind(QHostAddress::LocalHost, port)) {
 
1063
                        delete d->sd;
 
1064
                        d->sd = 0;
 
1065
                        d->serv.stop();
 
1066
                        return false;
 
1067
                }
 
1068
                connect(d->sd, SIGNAL(readyRead()), SLOT(sd_activated()));
 
1069
        }
 
1070
        return true;
 
1071
}
 
1072
 
 
1073
void SocksServer::stop()
 
1074
{
 
1075
        delete d->sd;
 
1076
        d->sd = 0;
 
1077
        d->serv.stop();
 
1078
}
 
1079
 
 
1080
int SocksServer::port() const
 
1081
{
 
1082
        return d->serv.port();
 
1083
}
 
1084
 
 
1085
QHostAddress SocksServer::address() const
 
1086
{
 
1087
        return d->serv.address();
 
1088
}
 
1089
 
 
1090
SocksClient *SocksServer::takeIncoming()
 
1091
{
 
1092
        if(d->incomingConns.isEmpty())
 
1093
                return 0;
 
1094
 
 
1095
        SocksClient *c = d->incomingConns.takeFirst();
 
1096
 
 
1097
        // we don't care about errors anymore
 
1098
        disconnect(c, SIGNAL(error(int)), this, SLOT(connectionError()));
 
1099
 
 
1100
        // don't serve the connection until the event loop, to give the caller a chance to map signals
 
1101
        QTimer::singleShot(0, c, SLOT(serve()));
 
1102
 
 
1103
        return c;
 
1104
}
 
1105
 
 
1106
void SocksServer::writeUDP(const QHostAddress &addr, int port, const QByteArray &data)
 
1107
{
 
1108
        if(d->sd) {
 
1109
                d->sd->writeDatagram(data.data(), data.size(), addr, port);
 
1110
        }
 
1111
}
 
1112
 
 
1113
void SocksServer::connectionReady(int s)
 
1114
{
 
1115
        SocksClient *c = new SocksClient(s, this);
 
1116
        connect(c, SIGNAL(error(int)), this, SLOT(connectionError()));
 
1117
        d->incomingConns.append(c);
 
1118
        incomingReady();
 
1119
}
 
1120
 
 
1121
void SocksServer::connectionError()
 
1122
{
 
1123
        SocksClient *c = (SocksClient *)sender();
 
1124
        d->incomingConns.removeAll(c);
 
1125
        c->deleteLater();
 
1126
}
 
1127
 
 
1128
void SocksServer::sd_activated()
 
1129
{
 
1130
        while (d->sd->hasPendingDatagrams()) {
 
1131
                QByteArray datagram;
 
1132
                QHostAddress sender;
 
1133
                quint16 senderPort;
 
1134
                datagram.resize(d->sd->pendingDatagramSize());
 
1135
                d->sd->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
 
1136
                incomingUDP(sender.toString(), senderPort, d->sd->peerAddress(), d->sd->peerPort(), datagram);
 
1137
        }
 
1138
}
 
1139
 
 
1140
// CS_NAMESPACE_END