Hello community, here is the log from the commit of package psi for openSUSE:Factory checked in at Fri Feb 27 16:15:57 CET 2009. -------- --- psi/psi.changes 2008-11-19 16:50:39.000000000 +0100 +++ /mounts/work_src_done/STABLE/psi/psi.changes 2009-02-27 15:47:09.000000000 +0100 @@ -1,0 +2,7 @@ +Fri Feb 27 15:46:58 CET 2009 - prusnak@suse.cz + +- updated to 0.12.1 + * Bugfix for DOS vulnerability in the file transfer code. + Thanks to Jesus Olmos (jolmos@isecauditors.com) + +------------------------------------------------------------------- calling whatdependson for head-i586 Old: ---- psi-0.12-delete.patch psi-0.12.tar.bz2 New: ---- psi-0.12.1-delete.patch psi-0.12.1.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ psi.spec ++++++ --- /var/tmp/diff_new_pack.l29690/_old 2009-02-27 16:15:49.000000000 +0100 +++ /var/tmp/diff_new_pack.l29690/_new 2009-02-27 16:15:49.000000000 +0100 @@ -1,7 +1,7 @@ # -# spec file for package psi (Version 0.12) +# spec file for package psi (Version 0.12.1) # -# Copyright (c) 2008 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2009 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -22,8 +22,8 @@ Url: http://psi-im.org/ License: GPL v2 or later Group: Productivity/Networking/Talk/Clients -Version: 0.12 -Release: 28 +Version: 0.12.1 +Release: 1 Summary: PSI Jabber client using Qt Source: http://downloads.sourceforge.net/psi/%{name}-%{version}.tar.bz2 Source1: http://psi-im.org/download/lang/psi_cs.qm @@ -127,6 +127,10 @@ # %lang(zh_TW) %{_datadir}/psi/*_zh_TW.qm %changelog +* Fri Feb 27 2009 prusnak@suse.cz +- updated to 0.12.1 + * Bugfix for DOS vulnerability in the file transfer code. + Thanks to Jesus Olmos (jolmos@isecauditors.com) * Wed Nov 19 2008 prusnak@suse.cz - fix wrong delete usage (delete.patch) [bnc#445429] * Tue Oct 07 2008 prusnak@suse.cz ++++++ psi-0.12-delete.patch -> psi-0.12.1-delete.patch ++++++ ++++++ psi-0.12.tar.bz2 -> psi-0.12.1.tar.bz2 ++++++ diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/psi-0.12/cutestuff/network/socks.cpp new/psi-0.12.1/cutestuff/network/socks.cpp --- old/psi-0.12/cutestuff/network/socks.cpp 2007-05-13 21:35:04.000000000 +0200 +++ new/psi-0.12.1/cutestuff/network/socks.cpp 2008-12-17 18:46:31.000000000 +0100 @@ -261,7 +261,8 @@ return -1; if(from->size() < 2) return 0; - int num = from->at(1); + unsigned char mlen = from->at(1); + int num = mlen; if(num > 16) // who the heck has over 16 auth methods?? return -1; if(from->size() < 2 + num) diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/psi-0.12/cutestuff/network/socks.cpp.orig new/psi-0.12.1/cutestuff/network/socks.cpp.orig --- old/psi-0.12/cutestuff/network/socks.cpp.orig 1970-01-01 01:00:00.000000000 +0100 +++ new/psi-0.12.1/cutestuff/network/socks.cpp.orig 2008-12-17 18:33:45.000000000 +0100 @@ -0,0 +1,1231 @@ +/* + * socks.cpp - SOCKS5 TCP proxy client/server + * Copyright (C) 2003 Justin Karneges + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "socks.h" + +#include <qhostaddress.h> +#include <qstringlist.h> +#include <q3ptrlist.h> +#include <qtimer.h> +#include <qpointer.h> +#include <q3socketdevice.h> +#include <qsocketnotifier.h> +//Added by qt3to4: +#include <Q3CString> + +#ifdef Q_OS_UNIX +#include <sys/types.h> +#include <netinet/in.h> +#endif + +#ifdef Q_OS_WIN32 +#include <windows.h> +#endif + +#ifdef Q_OS_UNIX +#include <unistd.h> +#include <fcntl.h> +#endif + +#include "servsock.h" +#include "bsocket.h" + +#ifdef PROX_DEBUG +#include <stdio.h> +#endif + +// CS_NAMESPACE_BEGIN + +//---------------------------------------------------------------------------- +// SocksUDP +//---------------------------------------------------------------------------- +static QByteArray sp_create_udp(const QString &host, Q_UINT16 port, const QByteArray &buf) +{ + // detect for IP addresses + //QHostAddress addr; + //if(addr.setAddress(host)) + // return sp_set_request(addr, port, cmd1); + + Q3CString h = host.utf8(); + h.truncate(255); + h = QString::fromUtf8(h).utf8(); // delete any partial characters? + int hlen = h.length(); + + int at = 0; + QByteArray a(4); + a[at++] = 0x00; // reserved + a[at++] = 0x00; // reserved + a[at++] = 0x00; // frag + a[at++] = 0x03; // address type = domain + + // host + a.resize(at+hlen+1); + a[at++] = hlen; + memcpy(a.data() + at, h.data(), hlen); + at += hlen; + + // port + a.resize(at+2); + unsigned short p = htons(port); + memcpy(a.data() + at, &p, 2); + at += 2; + + a.resize(at+buf.size()); + memcpy(a.data() + at, buf.data(), buf.size()); + + return a; +} + +struct SPS_UDP +{ + QString host; + Q_UINT16 port; + QByteArray data; +}; + +static int sp_read_udp(QByteArray *from, SPS_UDP *s) +{ + int full_len = 4; + if((int)from->size() < full_len) + return 0; + + QString host; + QHostAddress addr; + unsigned char atype = from->at(3); + + if(atype == 0x01) { + full_len += 4; + if((int)from->size() < full_len) + return 0; + Q_UINT32 ip4; + memcpy(&ip4, from->data() + 4, 4); + addr.setAddress(ntohl(ip4)); + host = addr.toString(); + } + else if(atype == 0x03) { + ++full_len; + if((int)from->size() < full_len) + return 0; + unsigned char host_len = from->at(4); + full_len += host_len; + if((int)from->size() < full_len) + return 0; + Q3CString cs(host_len+1); + memcpy(cs.data(), from->data() + 5, host_len); + host = QString::fromLatin1(cs); + } + else if(atype == 0x04) { + full_len += 16; + if((int)from->size() < full_len) + return 0; + Q_UINT8 a6[16]; + memcpy(a6, from->data() + 4, 16); + addr.setAddress(a6); + host = addr.toString(); + } + + full_len += 2; + if((int)from->size() < full_len) + return 0; + + Q_UINT16 p; + memcpy(&p, from->data() + full_len - 2, 2); + + s->host = host; + s->port = ntohs(p); + s->data.resize(from->size() - full_len); + memcpy(s->data.data(), from->data() + full_len, s->data.size()); + + return 1; +} + +class SocksUDP::Private +{ +public: + Q3SocketDevice *sd; + QSocketNotifier *sn; + SocksClient *sc; + QHostAddress routeAddr; + int routePort; + QString host; + int port; +}; + +SocksUDP::SocksUDP(SocksClient *sc, const QString &host, int port, const QHostAddress &routeAddr, int routePort) +:QObject(sc) +{ + d = new Private; + d->sc = sc; + d->sd = new Q3SocketDevice(Q3SocketDevice::Datagram); + d->sd->setBlocking(false); + d->sn = new QSocketNotifier(d->sd->socket(), QSocketNotifier::Read); + connect(d->sn, SIGNAL(activated(int)), SLOT(sn_activated(int))); + d->host = host; + d->port = port; + d->routeAddr = routeAddr; + d->routePort = routePort; +} + +SocksUDP::~SocksUDP() +{ + delete d->sn; + delete d->sd; + delete d; +} + +void SocksUDP::change(const QString &host, int port) +{ + d->host = host; + d->port = port; +} + +void SocksUDP::write(const QByteArray &data) +{ + QByteArray buf = sp_create_udp(d->host, d->port, data); + d->sd->setBlocking(true); + d->sd->writeBlock(buf.data(), buf.size(), d->routeAddr, d->routePort); + d->sd->setBlocking(false); +} + +void SocksUDP::sn_activated(int) +{ + QByteArray buf(8192); + int actual = d->sd->readBlock(buf.data(), buf.size()); + buf.resize(actual); + packetReady(buf); +} + +//---------------------------------------------------------------------------- +// SocksClient +//---------------------------------------------------------------------------- +#define REQ_CONNECT 0x01 +#define REQ_BIND 0x02 +#define REQ_UDPASSOCIATE 0x03 + +#define RET_SUCCESS 0x00 +#define RET_UNREACHABLE 0x04 +#define RET_CONNREFUSED 0x05 + +// spc = socks packet client +// sps = socks packet server +// SPCS = socks packet client struct +// SPSS = socks packet server struct + +// Version +static QByteArray spc_set_version() +{ + QByteArray ver(4); + ver[0] = 0x05; // socks version 5 + ver[1] = 0x02; // number of methods + ver[2] = 0x00; // no-auth + ver[3] = 0x02; // username + return ver; +} + +static QByteArray sps_set_version(int method) +{ + QByteArray ver(2); + ver[0] = 0x05; + ver[1] = method; + return ver; +} + +struct SPCS_VERSION +{ + unsigned char version; + QByteArray methodList; +}; + +static int spc_get_version(QByteArray *from, SPCS_VERSION *s) +{ + if(from->size() < 1) + return 0; + if(from->at(0) != 0x05) // only SOCKS5 supported + return -1; + if(from->size() < 2) + return 0; + int num = from->at(1); + if(num > 16) // who the heck has over 16 auth methods?? + return -1; + if(from->size() < 2 + num) + return 0; + QByteArray a = ByteStream::takeArray(from, 2+num); + s->version = a[0]; + s->methodList.resize(num); + memcpy(s->methodList.data(), a.data() + 2, num); + return 1; +} + +struct SPSS_VERSION +{ + unsigned char version; + unsigned char method; +}; + +static int sps_get_version(QByteArray *from, SPSS_VERSION *s) +{ + if(from->size() < 2) + return 0; + QByteArray a = ByteStream::takeArray(from, 2); + s->version = a[0]; + s->method = a[1]; + return 1; +} + +// authUsername +static QByteArray spc_set_authUsername(const Q3CString &user, const Q3CString &pass) +{ + int len1 = user.length(); + int len2 = pass.length(); + if(len1 > 255) + len1 = 255; + if(len2 > 255) + len2 = 255; + QByteArray a(1+1+len1+1+len2); + a[0] = 0x01; // username auth version 1 + a[1] = len1; + memcpy(a.data() + 2, user.data(), len1); + a[2+len1] = len2; + memcpy(a.data() + 3 + len1, pass.data(), len2); + return a; +} + +static QByteArray sps_set_authUsername(bool success) +{ + QByteArray a(2); + a[0] = 0x01; + a[1] = success ? 0x00 : 0xff; + return a; +} + +struct SPCS_AUTHUSERNAME +{ + QString user, pass; +}; + +static int spc_get_authUsername(QByteArray *from, SPCS_AUTHUSERNAME *s) +{ + if(from->size() < 1) + return 0; + unsigned char ver = from->at(0); + if(ver != 0x01) + return -1; + if(from->size() < 2) + return 0; + unsigned char ulen = from->at(1); + if((int)from->size() < ulen + 3) + return 0; + unsigned char plen = from->at(ulen+2); + if((int)from->size() < ulen + plen + 3) + return 0; + QByteArray a = ByteStream::takeArray(from, ulen + plen + 3); + + Q3CString user, pass; + user.resize(ulen+1); + pass.resize(plen+1); + memcpy(user.data(), a.data()+2, ulen); + memcpy(pass.data(), a.data()+ulen+3, plen); + s->user = QString::fromUtf8(user); + s->pass = QString::fromUtf8(pass); + return 1; +} + +struct SPSS_AUTHUSERNAME +{ + unsigned char version; + bool success; +}; + +static int sps_get_authUsername(QByteArray *from, SPSS_AUTHUSERNAME *s) +{ + if(from->size() < 2) + return 0; + QByteArray a = ByteStream::takeArray(from, 2); + s->version = a[0]; + s->success = ((char) a[1] == 0 ? true: false); + return 1; +} + +// connectRequest +static QByteArray sp_set_request(const QHostAddress &addr, unsigned short port, unsigned char cmd1) +{ + int at = 0; + QByteArray a(4); + a[at++] = 0x05; // socks version 5 + a[at++] = cmd1; + a[at++] = 0x00; // reserved + if(addr.isIp4Addr()) { + a[at++] = 0x01; // address type = ipv4 + Q_UINT32 ip4 = htonl(addr.ip4Addr()); + a.resize(at+4); + memcpy(a.data() + at, &ip4, 4); + at += 4; + } + else { + a[at++] = 0x04; + Q_UINT8 a6[16]; + QStringList s6 = QStringList::split(':', addr.toString(), true); + int at = 0; + Q_UINT16 c; + bool ok; + for(QStringList::ConstIterator it = s6.begin(); it != s6.end(); ++it) { + c = (*it).toInt(&ok, 16); + a6[at++] = (c >> 8); + a6[at++] = c & 0xff; + } + a.resize(at+16); + memcpy(a.data() + at, a6, 16); + at += 16; + } + + // port + a.resize(at+2); + unsigned short p = htons(port); + memcpy(a.data() + at, &p, 2); + + return a; +} + +static QByteArray sp_set_request(const QString &host, Q_UINT16 port, unsigned char cmd1) +{ + // detect for IP addresses + QHostAddress addr; + if(addr.setAddress(host)) + return sp_set_request(addr, port, cmd1); + + Q3CString h = host.utf8(); + h.truncate(255); + h = QString::fromUtf8(h).utf8(); // delete any partial characters? + int hlen = h.length(); + + int at = 0; + QByteArray a(4); + a[at++] = 0x05; // socks version 5 + a[at++] = cmd1; + a[at++] = 0x00; // reserved + a[at++] = 0x03; // address type = domain + + // host + a.resize(at+hlen+1); + a[at++] = hlen; + memcpy(a.data() + at, h.data(), hlen); + at += hlen; + + // port + a.resize(at+2); + unsigned short p = htons(port); + memcpy(a.data() + at, &p, 2); + + return a; +} + +struct SPS_CONNREQ +{ + unsigned char version; + unsigned char cmd; + int address_type; + QString host; + QHostAddress addr; + Q_UINT16 port; +}; + +static int sp_get_request(QByteArray *from, SPS_CONNREQ *s) +{ + int full_len = 4; + if((int)from->size() < full_len) + return 0; + + QString host; + QHostAddress addr; + unsigned char atype = from->at(3); + + if(atype == 0x01) { + full_len += 4; + if((int)from->size() < full_len) + return 0; + Q_UINT32 ip4; + memcpy(&ip4, from->data() + 4, 4); + addr.setAddress(ntohl(ip4)); + } + else if(atype == 0x03) { + ++full_len; + if((int)from->size() < full_len) + return 0; + unsigned char host_len = from->at(4); + full_len += host_len; + if((int)from->size() < full_len) + return 0; + Q3CString cs(host_len+1); + memcpy(cs.data(), from->data() + 5, host_len); + host = QString::fromLatin1(cs); + } + else if(atype == 0x04) { + full_len += 16; + if((int)from->size() < full_len) + return 0; + Q_UINT8 a6[16]; + memcpy(a6, from->data() + 4, 16); + addr.setAddress(a6); + } + + full_len += 2; + if((int)from->size() < full_len) + return 0; + + QByteArray a = ByteStream::takeArray(from, full_len); + + Q_UINT16 p; + memcpy(&p, a.data() + full_len - 2, 2); + + s->version = a[0]; + s->cmd = a[1]; + s->address_type = atype; + s->host = host; + s->addr = addr; + s->port = ntohs(p); + + return 1; +} + +enum { StepVersion, StepAuth, StepRequest }; + +class SocksClient::Private +{ +public: + Private() {} + + BSocket sock; + QString host; + int port; + QString user, pass; + QString real_host; + int real_port; + + QByteArray recvBuf; + bool active; + int step; + int authMethod; + bool incoming, waiting; + + QString rhost; + int rport; + + int pending; + + bool udp; + QString udpAddr; + int udpPort; +}; + +SocksClient::SocksClient(QObject *parent) +:ByteStream(parent) +{ + init(); + + d->incoming = false; +} + +SocksClient::SocksClient(int s, QObject *parent) +:ByteStream(parent) +{ + init(); + + d->incoming = true; + d->waiting = true; + d->sock.setSocket(s); +} + +void SocksClient::init() +{ + d = new Private; + connect(&d->sock, SIGNAL(connected()), SLOT(sock_connected())); + connect(&d->sock, SIGNAL(connectionClosed()), SLOT(sock_connectionClosed())); + connect(&d->sock, SIGNAL(delayedCloseFinished()), SLOT(sock_delayedCloseFinished())); + connect(&d->sock, SIGNAL(readyRead()), SLOT(sock_readyRead())); + connect(&d->sock, SIGNAL(bytesWritten(int)), SLOT(sock_bytesWritten(int))); + connect(&d->sock, SIGNAL(error(int)), SLOT(sock_error(int))); + + reset(true); +} + +SocksClient::~SocksClient() +{ + reset(true); + delete d; +} + +void SocksClient::reset(bool clear) +{ + if(d->sock.state() != BSocket::Idle) + d->sock.close(); + if(clear) + clearReadBuffer(); + d->recvBuf.resize(0); + d->active = false; + d->waiting = false; + d->udp = false; + d->pending = 0; +} + +bool SocksClient::isIncoming() const +{ + return d->incoming; +} + +void SocksClient::setAuth(const QString &user, const QString &pass) +{ + d->user = user; + d->pass = pass; +} + +void SocksClient::connectToHost(const QString &proxyHost, int proxyPort, const QString &host, int port, bool udpMode) +{ + reset(true); + + d->host = proxyHost; + d->port = proxyPort; + d->real_host = host; + d->real_port = port; + d->udp = udpMode; + +#ifdef PROX_DEBUG + fprintf(stderr, "SocksClient: Connecting to %s:%d", proxyHost.latin1(), proxyPort); + if(d->user.isEmpty()) + fprintf(stderr, "\n"); + else + fprintf(stderr, ", auth {%s,%s}\n", d->user.latin1(), d->pass.latin1()); +#endif + d->sock.connectToHost(d->host, d->port); +} + +bool SocksClient::isOpen() const +{ + return d->active; +} + +void SocksClient::close() +{ + d->sock.close(); + if(d->sock.bytesToWrite() == 0) + reset(); +} + +void SocksClient::writeData(const QByteArray &buf) +{ + d->pending += buf.size(); + d->sock.write(buf); +} + +void SocksClient::write(const QByteArray &buf) +{ + if(d->active && !d->udp) + d->sock.write(buf); +} + +QByteArray SocksClient::read(int bytes) +{ + return ByteStream::read(bytes); +} + +int SocksClient::bytesAvailable() const +{ + return ByteStream::bytesAvailable(); +} + +int SocksClient::bytesToWrite() const +{ + if(d->active) + return d->sock.bytesToWrite(); + else + return 0; +} + +void SocksClient::sock_connected() +{ +#ifdef PROX_DEBUG + fprintf(stderr, "SocksClient: Connected\n"); +#endif + + d->step = StepVersion; + writeData(spc_set_version()); +} + +void SocksClient::sock_connectionClosed() +{ + if(d->active) { + reset(); + connectionClosed(); + } + else { + error(ErrProxyNeg); + } +} + +void SocksClient::sock_delayedCloseFinished() +{ + if(d->active) { + reset(); + delayedCloseFinished(); + } +} + +void SocksClient::sock_readyRead() +{ + QByteArray block = d->sock.read(); + + if(!d->active) { + if(d->incoming) + processIncoming(block); + else + processOutgoing(block); + } + else { + if(!d->udp) { + appendRead(block); + readyRead(); + } + } +} + +void SocksClient::processOutgoing(const QByteArray &block) +{ +#ifdef PROX_DEBUG + // show hex + fprintf(stderr, "SocksClient: client recv { "); + for(int n = 0; n < (int)block.size(); ++n) + fprintf(stderr, "%02X ", (unsigned char)block[n]); + fprintf(stderr, " } \n"); +#endif + ByteStream::appendArray(&d->recvBuf, block); + + if(d->step == StepVersion) { + SPSS_VERSION s; + int r = sps_get_version(&d->recvBuf, &s); + if(r == -1) { + reset(true); + error(ErrProxyNeg); + return; + } + else if(r == 1) { + if(s.version != 0x05 || s.method == 0xff) { +#ifdef PROX_DEBUG + fprintf(stderr, "SocksClient: Method selection failed\n"); +#endif + reset(true); + error(ErrProxyNeg); + return; + } + + QString str; + if(s.method == 0x00) { + str = "None"; + d->authMethod = AuthNone; + } + else if(s.method == 0x02) { + str = "Username/Password"; + d->authMethod = AuthUsername; + } + else { +#ifdef PROX_DEBUG + fprintf(stderr, "SocksClient: Server wants to use unknown method '%02x'\n", s.method); +#endif + reset(true); + error(ErrProxyNeg); + return; + } + + if(d->authMethod == AuthNone) { + // no auth, go straight to the request + do_request(); + } + else if(d->authMethod == AuthUsername) { + d->step = StepAuth; +#ifdef PROX_DEBUG + fprintf(stderr, "SocksClient: Authenticating [Username] ...\n"); +#endif + writeData(spc_set_authUsername(d->user.latin1(), d->pass.latin1())); + } + } + } + if(d->step == StepAuth) { + if(d->authMethod == AuthUsername) { + SPSS_AUTHUSERNAME s; + int r = sps_get_authUsername(&d->recvBuf, &s); + if(r == -1) { + reset(true); + error(ErrProxyNeg); + return; + } + else if(r == 1) { + if(s.version != 0x01) { + reset(true); + error(ErrProxyNeg); + return; + } + if(!s.success) { + reset(true); + error(ErrProxyAuth); + return; + } + + do_request(); + } + } + } + else if(d->step == StepRequest) { + SPS_CONNREQ s; + int r = sp_get_request(&d->recvBuf, &s); + if(r == -1) { + reset(true); + error(ErrProxyNeg); + return; + } + else if(r == 1) { + if(s.cmd != RET_SUCCESS) { +#ifdef PROX_DEBUG + fprintf(stderr, "SocksClient: client << Error >> [%02x]\n", s.cmd); +#endif + reset(true); + if(s.cmd == RET_UNREACHABLE) + error(ErrHostNotFound); + else if(s.cmd == RET_CONNREFUSED) + error(ErrConnectionRefused); + else + error(ErrProxyNeg); + return; + } + +#ifdef PROX_DEBUG + fprintf(stderr, "SocksClient: client << Success >>\n"); +#endif + if(d->udp) { + if(s.address_type == 0x03) + d->udpAddr = s.host; + else + d->udpAddr = s.addr.toString(); + d->udpPort = s.port; + } + + d->active = true; + + QPointer<QObject> self = this; + connected(); + if(!self) + return; + + if(!d->recvBuf.isEmpty()) { + appendRead(d->recvBuf); + d->recvBuf.resize(0); + readyRead(); + } + } + } +} + +void SocksClient::do_request() +{ +#ifdef PROX_DEBUG + fprintf(stderr, "SocksClient: Requesting ...\n"); +#endif + d->step = StepRequest; + int cmd = d->udp ? REQ_UDPASSOCIATE : REQ_CONNECT; + QByteArray buf; + if(!d->real_host.isEmpty()) + buf = sp_set_request(d->real_host, d->real_port, cmd); + else + buf = sp_set_request(QHostAddress(), 0, cmd); + writeData(buf); +} + +void SocksClient::sock_bytesWritten(int x) +{ + int bytes = x; + if(d->pending >= bytes) { + d->pending -= bytes; + bytes = 0; + } + else { + bytes -= d->pending; + d->pending = 0; + } + if(bytes > 0) + bytesWritten(bytes); +} + +void SocksClient::sock_error(int x) +{ + if(d->active) { + reset(); + error(ErrRead); + } + else { + reset(true); + if(x == BSocket::ErrHostNotFound) + error(ErrProxyConnect); + else if(x == BSocket::ErrConnectionRefused) + error(ErrProxyConnect); + else if(x == BSocket::ErrRead) + error(ErrProxyNeg); + } +} + +void SocksClient::serve() +{ + d->waiting = false; + d->step = StepVersion; + continueIncoming(); +} + +void SocksClient::processIncoming(const QByteArray &block) +{ +#ifdef PROX_DEBUG + // show hex + fprintf(stderr, "SocksClient: server recv { "); + for(int n = 0; n < (int)block.size(); ++n) + fprintf(stderr, "%02X ", (unsigned char)block[n]); + fprintf(stderr, " } \n"); +#endif + ByteStream::appendArray(&d->recvBuf, block); + + if(!d->waiting) + continueIncoming(); +} + +void SocksClient::continueIncoming() +{ + if(d->recvBuf.isEmpty()) + return; + + if(d->step == StepVersion) { + SPCS_VERSION s; + int r = spc_get_version(&d->recvBuf, &s); + if(r == -1) { + reset(true); + error(ErrProxyNeg); + return; + } + else if(r == 1) { + if(s.version != 0x05) { + reset(true); + error(ErrProxyNeg); + return; + } + + int methods = 0; + for(int n = 0; n < (int)s.methodList.size(); ++n) { + unsigned char c = s.methodList[n]; + if(c == 0x00) + methods |= AuthNone; + else if(c == 0x02) + methods |= AuthUsername; + } + d->waiting = true; + incomingMethods(methods); + } + } + else if(d->step == StepAuth) { + SPCS_AUTHUSERNAME s; + int r = spc_get_authUsername(&d->recvBuf, &s); + if(r == -1) { + reset(true); + error(ErrProxyNeg); + return; + } + else if(r == 1) { + d->waiting = true; + incomingAuth(s.user, s.pass); + } + } + else if(d->step == StepRequest) { + SPS_CONNREQ s; + int r = sp_get_request(&d->recvBuf, &s); + if(r == -1) { + reset(true); + error(ErrProxyNeg); + return; + } + else if(r == 1) { + d->waiting = true; + if(s.cmd == REQ_CONNECT) { + if(!s.host.isEmpty()) + d->rhost = s.host; + else + d->rhost = s.addr.toString(); + d->rport = s.port; + incomingConnectRequest(d->rhost, d->rport); + } + else if(s.cmd == REQ_UDPASSOCIATE) { + incomingUDPAssociateRequest(); + } + else { + requestDeny(); + return; + } + } + } +} + +void SocksClient::chooseMethod(int method) +{ + if(d->step != StepVersion || !d->waiting) + return; + + unsigned char c; + if(method == AuthNone) { + d->step = StepRequest; + c = 0x00; + } + else { + d->step = StepAuth; + c = 0x02; + } + + // version response + d->waiting = false; + writeData(sps_set_version(c)); + continueIncoming(); +} + +void SocksClient::authGrant(bool b) +{ + if(d->step != StepAuth || !d->waiting) + return; + + if(b) + d->step = StepRequest; + + // auth response + d->waiting = false; + writeData(sps_set_authUsername(b)); + if(!b) { + reset(true); + return; + } + continueIncoming(); +} + +void SocksClient::requestDeny() +{ + if(d->step != StepRequest || !d->waiting) + return; + + // response + d->waiting = false; + writeData(sp_set_request(d->rhost, d->rport, RET_UNREACHABLE)); + reset(true); +} + +void SocksClient::grantConnect() +{ + if(d->step != StepRequest || !d->waiting) + return; + + // response + d->waiting = false; + writeData(sp_set_request(d->rhost, d->rport, RET_SUCCESS)); + d->active = true; +#ifdef PROX_DEBUG + fprintf(stderr, "SocksClient: server << Success >>\n"); +#endif + + if(!d->recvBuf.isEmpty()) { + appendRead(d->recvBuf); + d->recvBuf.resize(0); + readyRead(); + } +} + +void SocksClient::grantUDPAssociate(const QString &relayHost, int relayPort) +{ + if(d->step != StepRequest || !d->waiting) + return; + + // response + d->waiting = false; + writeData(sp_set_request(relayHost, relayPort, RET_SUCCESS)); + d->udp = true; + d->active = true; +#ifdef PROX_DEBUG + fprintf(stderr, "SocksClient: server << Success >>\n"); +#endif + + if(!d->recvBuf.isEmpty()) + d->recvBuf.resize(0); +} + +QHostAddress SocksClient::peerAddress() const +{ + return d->sock.peerAddress(); +} + +Q_UINT16 SocksClient::peerPort() const +{ + return d->sock.peerPort(); +} + +QString SocksClient::udpAddress() const +{ + return d->udpAddr; +} + +Q_UINT16 SocksClient::udpPort() const +{ + return d->udpPort; +} + +SocksUDP *SocksClient::createUDP(const QString &host, int port, const QHostAddress &routeAddr, int routePort) +{ + return new SocksUDP(this, host, port, routeAddr, routePort); +} + +//---------------------------------------------------------------------------- +// SocksServer +//---------------------------------------------------------------------------- +class SocksServer::Private +{ +public: + Private() {} + + ServSock serv; + Q3PtrList<SocksClient> incomingConns; + Q3SocketDevice *sd; + QSocketNotifier *sn; +}; + +SocksServer::SocksServer(QObject *parent) +:QObject(parent) +{ + d = new Private; + d->sd = 0; + d->sn = 0; + connect(&d->serv, SIGNAL(connectionReady(int)), SLOT(connectionReady(int))); +} + +SocksServer::~SocksServer() +{ + stop(); + d->incomingConns.setAutoDelete(true); + d->incomingConns.clear(); + delete d; +} + +bool SocksServer::isActive() const +{ + return d->serv.isActive(); +} + +bool SocksServer::listen(Q_UINT16 port, bool udp) +{ + stop(); + if(!d->serv.listen(port)) + return false; + if(udp) { + d->sd = new Q3SocketDevice(Q3SocketDevice::Datagram); +#ifdef Q_OS_UNIX + ::fcntl(d->sd->socket(), F_SETFD, FD_CLOEXEC); +#endif + d->sd->setBlocking(false); + if(!d->sd->bind(QHostAddress(), port)) { + delete d->sd; + d->sd = 0; + d->serv.stop(); + return false; + } + d->sn = new QSocketNotifier(d->sd->socket(), QSocketNotifier::Read); + connect(d->sn, SIGNAL(activated(int)), SLOT(sn_activated(int))); + } + return true; +} + +void SocksServer::stop() +{ + delete d->sn; + d->sn = 0; + delete d->sd; + d->sd = 0; + d->serv.stop(); +} + +int SocksServer::port() const +{ + return d->serv.port(); +} + +QHostAddress SocksServer::address() const +{ + return d->serv.address(); +} + +SocksClient *SocksServer::takeIncoming() +{ + if(d->incomingConns.isEmpty()) + return 0; + + SocksClient *c = d->incomingConns.getFirst(); + d->incomingConns.removeRef(c); + + // we don't care about errors anymore + disconnect(c, SIGNAL(error(int)), this, SLOT(connectionError())); + + // don't serve the connection until the event loop, to give the caller a chance to map signals + QTimer::singleShot(0, c, SLOT(serve())); + + return c; +} + +void SocksServer::writeUDP(const QHostAddress &addr, int port, const QByteArray &data) +{ + if(d->sd) { + d->sd->setBlocking(true); + d->sd->writeBlock(data.data(), data.size(), addr, port); + d->sd->setBlocking(false); + } +} + +void SocksServer::connectionReady(int s) +{ + SocksClient *c = new SocksClient(s, this); + connect(c, SIGNAL(error(int)), this, SLOT(connectionError())); + d->incomingConns.append(c); + incomingReady(); +} + +void SocksServer::connectionError() +{ + SocksClient *c = (SocksClient *)sender(); + d->incomingConns.removeRef(c); + c->deleteLater(); +} + +void SocksServer::sn_activated(int) +{ + QByteArray buf(8192); + int actual = d->sd->readBlock(buf.data(), buf.size()); + buf.resize(actual); + QHostAddress pa = d->sd->peerAddress(); + int pp = d->sd->peerPort(); + SPS_UDP s; + int r = sp_read_udp(&buf, &s); + if(r != 1) + return; + incomingUDP(s.host, s.port, pa, pp, s.data); +} + +// CS_NAMESPACE_END diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/psi-0.12/mac/Info.plist new/psi-0.12.1/mac/Info.plist --- old/psi-0.12/mac/Info.plist 2008-07-25 23:02:44.000000000 +0200 +++ new/psi-0.12.1/mac/Info.plist 2008-12-17 18:46:32.000000000 +0100 @@ -7,7 +7,7 @@ <key>CFBundleExecutable</key> <string>psi</string> <key>CFBundleGetInfoString</key> - <string>Psi 0.12 by the Psi team. This program is licensed under the GNU GPL.</string> + <string>Psi 0.12.1 by the Psi team. This program is licensed under the GNU GPL.</string> <key>CFBundleIconFile</key> <string>application.icns</string> <key>CFBundleIdentifier</key> @@ -19,11 +19,11 @@ <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> - <string>Psi 0.12</string> + <string>Psi 0.12.1</string> <key>CFBundleSignature</key> <string>psi</string> <key>CFBundleVersion</key> - <string>0.12</string> + <string>0.12.1</string> <key>CSResourcesFileMapped</key> <true/> </dict> diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/psi-0.12/mac/Makefile new/psi-0.12.1/mac/Makefile --- old/psi-0.12/mac/Makefile 2008-07-25 23:02:44.000000000 +0200 +++ new/psi-0.12.1/mac/Makefile 2008-12-17 18:46:32.000000000 +0100 @@ -26,7 +26,7 @@ NAME=Psi VOLUME_NAME=$(NAME) #VERSION=0.12-devel_$(shell date +"%Y%m%d") -VERSION=0.12 +VERSION=0.12.1 APPFILE_NAME=Psi.app FILES=$(APPFILE_NAME) diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/psi-0.12/README new/psi-0.12.1/README --- old/psi-0.12/README 2008-07-25 23:02:44.000000000 +0200 +++ new/psi-0.12.1/README 2008-12-17 22:51:55.000000000 +0100 @@ -1,6 +1,6 @@ -Psi 0.12 +Psi 0.12.1 --------- -Date: July 25th, 2008 +Date: December 17th, 2008 Project Lead/Maintainer (2004-current): Kevin Smith @@ -52,6 +52,9 @@ Changes ------- + New in 0.12.1 + - Bugfix for DOS vulnerability in the file transfer code. + Thanks to Jesus Olmos (jolmos@isecauditors.com) New in 0.12 - Multi-user chat windows now join one on one chat windows and can be opened in tabbed form, either sharing a window, or seperately. diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/psi-0.12/src/applicationinfo.cpp new/psi-0.12.1/src/applicationinfo.cpp --- old/psi-0.12/src/applicationinfo.cpp 2008-07-25 23:02:44.000000000 +0200 +++ new/psi-0.12.1/src/applicationinfo.cpp 2008-12-17 18:46:32.000000000 +0100 @@ -27,9 +27,9 @@ #define PROG_NAME "Psi" //#define PROG_VERSION "0.12-dev" " (" __DATE__ ")"; //CVS Builds are dated -#define PROG_VERSION "0.12"; +#define PROG_VERSION "0.12.1"; #define PROG_CAPS_NODE "http://psi-im.org/caps"; -#define PROG_CAPS_VERSION "0.12"; +#define PROG_CAPS_VERSION "0.12.1"; #define PROG_IPC_NAME "org.psi-im.Psi" // must not contain '\\' character on Windows #define PROG_OPTIONS_NS "http://psi-im.org/options"; #define PROG_STORAGE_NS "http://psi-im.org/storage"; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Remember to have fun... -- To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-commit+help@opensuse.org
participants (1)
-
root@Hilbert.suse.de