Skip to content

Commit 92bd1ce

Browse files
committed
Applied SOCKS5 changes to ppsp-03 branch of libswift
1 parent de94692 commit 92bd1ce

9 files changed

+551
-42
lines changed

.gitignore

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
*.obj
2+
*.dblite
3+
*.exe
4+
*.pdb
5+
*.lib
6+
*.exp

SConstruct

+5-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import os
1515
import re
1616
import sys
1717

18-
DEBUG = True
18+
DEBUG = False
1919
CODECOVERAGE = (DEBUG and True)
2020

2121
TestDir='tests'
@@ -25,12 +25,12 @@ source = [ 'bin.cpp', 'binmap.cpp', 'sha1.cpp','hashtree.cpp',
2525
'transfer.cpp', 'channel.cpp', 'sendrecv.cpp', 'send_control.cpp',
2626
'compat.cpp','avgspeed.cpp', 'avail.cpp', 'cmdgw.cpp', 'httpgw.cpp',
2727
'storage.cpp', 'zerostate.cpp', 'zerohashtree.cpp',
28-
'api.cpp', 'content.cpp', 'live.cpp', 'swarmmanager.cpp', 'address.cpp']
28+
'api.cpp', 'content.cpp', 'live.cpp', 'swarmmanager.cpp', 'address.cpp','Socks5Connection.cpp']
2929
# cmdgw.cpp now in there for SOCKTUNNEL
3030

3131
env = Environment()
3232
if sys.platform == "win32":
33-
libevent2path = '\\build\\libevent-2.0.20-stable-debug'
33+
libevent2path = '\\build\\libevent-2.0.19-stable'
3434

3535
# "MSVC works out of the box". Sure.
3636
# Make sure scons finds cl.exe, etc.
@@ -72,6 +72,8 @@ if sys.platform == "win32":
7272

7373
# Somehow linker can't find uuid.lib
7474
libpath += 'C:\\Program Files\\Microsoft SDKs\\Windows\\v6.0A\\Lib;'
75+
libpath += 'C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.1A\\Lib;'
76+
libpath += 'C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1A\\Lib;'
7577

7678
# Make the swift.exe a Windows program not a Console program when used inside another prog
7779
linkflags = '/SUBSYSTEM:WINDOWS'

Socks5Connection.cpp

+356
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,356 @@
1+
/*
2+
* Socks5Connection.cpp
3+
*
4+
* Created on: Jun 17, 2013
5+
* Author: chris
6+
*/
7+
8+
#include "Socks5Connection.h"
9+
#include <deque>
10+
#include <vector>
11+
#include <set>
12+
#include <map>
13+
#include <algorithm>
14+
#include <string>
15+
#include <math.h>
16+
17+
#include "compat.h"
18+
#include <event2/event.h>
19+
#include <event2/event_struct.h>
20+
#include <event2/buffer.h>
21+
#include "bin.h"
22+
#include "binmap.h"
23+
#include "hashtree.h"
24+
#include "avgspeed.h"
25+
// Arno, 2012-05-21: MacOS X has an Availability.h :-(
26+
#include "avail.h"
27+
28+
#include <event2/buffer.h>
29+
#include <event2/bufferevent.h>
30+
31+
using namespace swift;
32+
33+
#define errorOut(...) {\
34+
fprintf(stderr, "%s:%d: %s():\t", __FILE__, __LINE__, __FUNCTION__);\
35+
fprintf(stderr, __VA_ARGS__);\
36+
}
37+
38+
Socks5ConnectionState Socks5Connection::getCurrentState(){
39+
return this->state;
40+
}
41+
42+
void Socks5Connection::setCurrentState(Socks5ConnectionState state){
43+
this->state = state;
44+
}
45+
46+
int Socks5Connection::tryReadHandshakeResponse(struct bufferevent * bev){
47+
struct evbuffer * buff = bufferevent_get_input(bev);
48+
unsigned char * mem = evbuffer_pullup(buff,2);
49+
50+
if(mem == NULL){
51+
/* Not enough data in the buffer */
52+
return 0;
53+
} else if(mem[0] != 5 || mem[1] != 0){
54+
/* Incorrect version or unsupported method */
55+
return -1;
56+
} else {
57+
evbuffer_drain(buff, 2);
58+
this->setCurrentState(MethodSelected);
59+
this->tryUdpAssociateRequest(bev);
60+
return 1;
61+
}
62+
63+
64+
}
65+
66+
void Socks5Connection::tryUdpAssociateRequest(struct bufferevent * bev){
67+
unsigned char mem[10];
68+
mem[0] = 5; // Version
69+
mem[1] = 3; // UDP ASSOCIATE
70+
mem[2] = 0; // RSV
71+
72+
mem[3] = 1; // Atype = IPv4
73+
74+
mem[4] = 0; // IPv4 address all zero since we want to sent to any possible address in the future
75+
mem[5] = 0;
76+
mem[6] = 0;
77+
mem[7] = 0;
78+
79+
mem[8] = 0; // Port zero as well for the same reason
80+
mem[9] = 0;
81+
82+
bufferevent_write(bev, static_cast<const void *>(mem), 10);
83+
this->setCurrentState(UdpRequestSent);
84+
}
85+
86+
void Socks5Connection::setBindAddress(Address address){
87+
this->bind_address = address;
88+
}
89+
90+
Address Socks5Connection::getBindAddress(){
91+
return this->bind_address;
92+
}
93+
94+
int Socks5Connection::tryReadUdpAssociateResponse(struct bufferevent * bev){
95+
struct evbuffer * buff = bufferevent_get_input(bev);
96+
unsigned char * mem = evbuffer_pullup(buff,4);
97+
98+
Address bind_address;
99+
100+
if(mem == NULL){
101+
/* Not enough data in the buffer */
102+
return 0;
103+
} else if(mem[0] != 5 || mem[1] != 0 || mem[2] != 0){
104+
/* Incorrect version or request not succeeded or RSV != 0 */
105+
return -1;
106+
} else {
107+
// We have an ipv4 address
108+
if(mem[3] == 1){
109+
mem = evbuffer_pullup(buff, 4 + 4 + 2); // Pull up additional 4 bytes for the ipv4 address and 2 for the port
110+
111+
if(mem == NULL)
112+
return 0;
113+
else{
114+
uint32_t ipv4;
115+
uint16_t port;
116+
117+
memcpy(&ipv4, mem+4,4);
118+
memcpy(&port, mem+8,2);
119+
120+
port = ntohs(port);
121+
ipv4 = ntohl(ipv4);
122+
123+
bind_address.set_ipv4(ipv4);
124+
bind_address.set_port(port);
125+
126+
evbuffer_drain(buff, 10);
127+
}
128+
} else if(mem[3] == 3){ // We have a fqdn
129+
mem = evbuffer_pullup(buff, 4 + 1);
130+
131+
if(mem == NULL)
132+
return 0;
133+
else {
134+
unsigned char domain_length = mem[4];
135+
char * domain = new char[domain_length] ;
136+
uint16_t port;
137+
138+
mem = evbuffer_pullup(buff, 4 + 1 + domain_length + 2); // Pull up domain and port
139+
140+
if(mem == NULL)
141+
return 0;
142+
143+
memcpy(&domain, mem + 5, domain_length);
144+
memcpy(&port, mem + 5 + domain_length, 2);
145+
146+
port = ntohs(port);
147+
148+
bind_address.set_ipv4(domain);
149+
bind_address.set_port(port);
150+
151+
evbuffer_drain(buff, 4 + 1 + domain_length + 2);
152+
delete [] domain;
153+
}
154+
155+
} else if (mem[3] == 4)
156+
return -1; // IPv6 not supported!
157+
158+
159+
this->setBindAddress(bind_address);
160+
this->setCurrentState(UdpAssociated);
161+
162+
printf("Socks5 UDP proxy ready at %s:%d\n", bind_address.ipstr(), bind_address.port());
163+
this->working_ = true;
164+
165+
// this->setUDPsocket(AF_INET, SOCK_DGRAM, 0)
166+
167+
return 1;
168+
}
169+
170+
return 0;
171+
}
172+
173+
int Socks5Connection::consumeUdpHeader(struct evbuffer *buff, UdpEncapsulationHeader& header){
174+
unsigned char * mem = evbuffer_pullup(buff,4);
175+
176+
if(mem == NULL){
177+
/* Not enough data in the buffer */
178+
return 0;
179+
} else {
180+
memcpy(&header, mem, 4);
181+
182+
// We have an ipv4 address
183+
if(header.atyp == 1){
184+
mem = evbuffer_pullup(buff, 4 + 4 + 2); // Pull up additional 4 bytes for the ipv4 address and 2 for the port
185+
186+
if(mem == NULL)
187+
return 0;
188+
else{
189+
uint32_t ipv4;
190+
uint16_t port;
191+
192+
memcpy(&ipv4, mem+4,4);
193+
memcpy(&port, mem+8,2);
194+
195+
ipv4 = ntohl(ipv4);
196+
port = ntohs(port);
197+
198+
header.address.set_ipv4(ipv4);
199+
header.address.set_port(port);
200+
201+
evbuffer_drain(buff, 10);
202+
203+
return 10;
204+
}
205+
} else if(header.atyp == 3){ // We have a fqdn
206+
mem = evbuffer_pullup(buff, 4 + 1);
207+
208+
if(mem == NULL)
209+
return 0;
210+
else {
211+
unsigned char domain_length = mem[4];
212+
char * domain = new char[domain_length] ;
213+
uint16_t port;
214+
215+
mem = evbuffer_pullup(buff, 4 + 1 + domain_length + 2); // Pull up domain and port
216+
217+
if(mem == NULL)
218+
return 0;
219+
220+
memcpy(&domain, mem + 5, domain_length);
221+
memcpy(&port, mem + 5 + domain_length, 2);
222+
223+
port = ntohs(port);
224+
225+
header.address.set_ipv4(domain);
226+
header.address.set_port(port);
227+
228+
evbuffer_drain(buff, 4 + 1 + domain_length + 2);
229+
delete [] domain;
230+
231+
return 4 + 1 + domain_length + 2;
232+
}
233+
234+
} else if (header.atyp == 4)
235+
return -1; // IPv6 not supported!
236+
}
237+
}
238+
239+
int Socks5Connection::unwrapDatagram(Address & addr, struct evbuffer * evb){
240+
UdpEncapsulationHeader header;
241+
242+
int udpHeaderRead = consumeUdpHeader(evb, header);
243+
244+
if(udpHeaderRead <= 0)
245+
return -1;
246+
247+
addr.set_ipv4(header.address.ipv4());
248+
addr.set_port(header.address.port());
249+
250+
return sizeof(UdpEncapsulationHeader);
251+
}
252+
253+
/**
254+
* Called by libevent when there is data to read.
255+
*/
256+
void Socks5Connection::buffered_on_read(struct bufferevent *bev, void *cbarg) {
257+
258+
Socks5Connection *s5 = static_cast<Socks5Connection *>(cbarg);
259+
260+
switch(s5->getCurrentState()){
261+
case HandshakeSent:
262+
s5->tryReadHandshakeResponse(bev);
263+
return;
264+
case UdpRequestSent:
265+
s5->tryReadUdpAssociateResponse(bev);
266+
return;
267+
268+
}
269+
}
270+
271+
/**
272+
* Called by libevent when the write buffer reaches 0. We only
273+
* provide this because libevent expects it, but we don't use it.
274+
*/
275+
void Socks5Connection::buffered_on_write(struct bufferevent *bev, void *cbarg) {
276+
277+
}
278+
279+
/**
280+
* Called by libevent when the write buffer reaches 0. We only
281+
* provide this because libevent expects it, but we don't use it.
282+
*/
283+
void Socks5Connection::buffered_on_event(struct bufferevent *bev, short int what, void* cbarg) {
284+
285+
// Sock5 server closed the connection!
286+
if((what & BEV_EVENT_EOF) == BEV_EVENT_EOF){
287+
Socks5Connection * s5 = static_cast<Socks5Connection *> (cbarg);
288+
s5->setCurrentState(Closed);
289+
}
290+
291+
// Sock5 server closed the connection!
292+
if((what & BEV_EVENT_ERROR) == BEV_EVENT_ERROR){
293+
Socks5Connection * s5 = static_cast<Socks5Connection *> (cbarg);
294+
s5->setCurrentState(Closed);
295+
296+
errorOut("Error occurred =(");
297+
}
298+
}
299+
300+
void Socks5Connection::sendHandshake(struct bufferevent *bev){
301+
unsigned char buff[2];
302+
303+
buff[0] = 0x05;
304+
buff[1] = 0x00;
305+
306+
bufferevent_write(bev, static_cast<const void *>(buff), 2UL);
307+
}
308+
309+
Socks5Connection::Socks5Connection(): Operational(true){
310+
this->state = Closed;
311+
}
312+
313+
void Socks5Connection::open(struct event_base *evbase, Address socks5_server){
314+
working_ = false;
315+
316+
struct bufferevent *bev;
317+
318+
int addrlen = sizeof(struct sockaddr_in);
319+
320+
bev = bufferevent_socket_new(evbase, -1, BEV_OPT_CLOSE_ON_FREE);
321+
bufferevent_setcb(bev, buffered_on_read, buffered_on_write, buffered_on_event, this);
322+
bufferevent_enable(bev, EV_READ|EV_WRITE);
323+
324+
if(bufferevent_socket_connect(bev, (struct sockaddr*)&(socks5_server.addr), addrlen))
325+
errorOut("Cannot connect!");
326+
327+
328+
sendHandshake(bev);
329+
this->setCurrentState(HandshakeSent);
330+
}
331+
332+
bool Socks5Connection::isOpen(){
333+
return this->getCurrentState() == 4;
334+
}
335+
336+
int Socks5Connection::prependHeader(const Address & addr, struct evbuffer * evb){
337+
UdpEncapsulationHeader header;
338+
header.atyp = 1;
339+
header.fragment = 0;
340+
341+
unsigned char * buff = new unsigned char[10];
342+
memcpy(buff, &header, 4);
343+
uint32_t ipv4 = htonl(addr.ipv4());
344+
uint16_t port = htons(addr.port());
345+
346+
memcpy(buff + 4, &ipv4, 4);
347+
memcpy(buff + 8, &port, 2);
348+
349+
evbuffer_prepend(evb, buff, 10);
350+
351+
delete buff;
352+
353+
//printf("Prepending Socks5 header to UDP packet destined to %s:%d \r\n", header.address.ipstr(),header.address.port());
354+
355+
return 10;
356+
}

0 commit comments

Comments
 (0)