1 /* Socks Server 5
2 * Copyright (C) 2002 - 2011 by Matteo Ricchetti - <matteo.ricchetti@libero.it>
3
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19
20 #include"SS5Main.h"
21 #include"SS5Mod_dump.h"
22 #include"SS5Utils.h"
23
24 char *ss5ver=SS5_VERSION;
25
InitModule(struct _module * m)26 UINT InitModule( struct _module *m )
27 {
28 m->AddDump = AddDump;
29 m->FreeDump = FreeDump;
30 m->GetDump = GetDump;
31 m->OpenDump = OpenDump;
32 m->WritingDump = WritingDump;
33 m->CloseDump = CloseDump;
34 m->SrvDump = SrvDump;
35 m->ListDump = ListDump;
36
37 return OK;
38 }
39
ListDump(UINT s)40 UINT ListDump( UINT s)
41 {
42 UINT count;
43
44 struct _S5DumpNode *node, *lnode;
45
46 char buf[53];
47
48 for(count = 0;count < MAXDUMPLIST; count++) {
49 if( (node=S5DumpList[count]) != NULL) {
50
51 lnode=node;
52 do {
53 if(lnode != NULL ) {
54 snprintf(buf,sizeof(buf),"%16lu\n%2u\n%16lu\n%5u\n%5u\n%1u\n%1u\n", lnode->DstAddr,lnode->Mask,lnode->DstPort,
55 lnode->DstRangeMin,lnode->DstRangeMax,lnode->DumpDir,lnode->DumpMode);
56 lnode=lnode->next;
57 }
58
59 if( send(s,buf,sizeof(buf),0) == -1) {
60 perror("Send err:");
61 return ERR;
62 }
63
64 } while( lnode != NULL );
65 }
66 }
67 return OK;
68 }
69
SrvDump(struct _SS5ClientInfo * ci,struct _SS5Socks5Data * sd)70 INT SrvDump( struct _SS5ClientInfo *ci, struct _SS5Socks5Data *sd )
71 {
72 UINT dstMask,sdr,dct;
73
74 char da[64],dp[16],dc[1],dm[1], srvResponse[16];
75
76 if( STREQ(sd->MethodRequest,"ET /list=DUMP HTTP/1.",sizeof("ET /list=DUMP HTTP/1.") - 1) ) {
77 ListDump(ci->Socket);
78 return OK;
79 }
80 else if( STREQ(sd->MethodRequest,"DD /dump=",sizeof("DD /dump=") - 1) ) {
81
82 sscanf(sd->MethodRequest,"DD /dump=%64s\n%16s\n%1s\n%1s\n",da,dp,dc,dm);
83
84 dstMask=S5GetNetmask(da);
85
86 switch(dm[0]) {
87 case 'r': sdr=0; break;
88 case 't': sdr=1; break;
89 case 'b': sdr=2; break;
90 default: sdr=0; break;
91 }
92
93 switch(dc[0]) {
94 case 's': dct=0; break;
95 case 'd': dct=1; break;
96 default: dct=0; break;
97 }
98
99 if( da[0] > 64 ) {
100 if( AddDump(ONLINE,S5StrHash(da),S5GetRange(dp),dct,sdr,32-dstMask) && (NDumpList < MAXDUMPLIST)) {
101 strncpy(srvResponse,"OK\0",sizeof("OK\0"));
102 NDumpList++;
103 SS5SocksOpt.IsDump = OK;
104 }
105 else
106 strncpy(srvResponse,"ERR\0",sizeof("ERR\0"));
107 }
108 else {
109 if( AddDump(ONLINE,inet_network(da),S5GetRange(dp),dct,sdr,32-dstMask) && (NDumpList < MAXDUMPLIST)) {
110 strncpy(srvResponse,"OK\0",sizeof("OK\0"));
111 NDumpList++;
112 SS5SocksOpt.IsDump = OK;
113 }
114 else
115 strncpy(srvResponse,"ERR\0",sizeof("ERR\0"));
116 }
117
118 if( send(ci->Socket,srvResponse,strlen(srvResponse),0) == -1) {
119 perror("Send err:");
120 return ERR;
121 }
122 return OK;
123 }
124 else if( STREQ(sd->MethodRequest,"DEL /dump=",sizeof("DEL /dump=") - 1) ) {
125
126 sscanf(sd->MethodRequest,"DEL /dump=%64s\n%16s\n%1s\n",da,dp,dm);
127
128 dstMask=S5GetNetmask(da);
129
130 if( da[0] > 64 ) {
131 if( DelDump(S5StrHash(da),S5GetRange(dp),32-dstMask) && (NDumpList < MAXDUMPLIST)) {
132 strncpy(srvResponse,"OK\0",sizeof("OK\0"));
133 NDumpList++;
134 SS5SocksOpt.IsDump = OK;
135 }
136 else
137 strncpy(srvResponse,"ERR\0",sizeof("ERR\0"));
138 }
139 else {
140 if( DelDump(inet_network(da),S5GetRange(dp),32-dstMask) && (NDumpList < MAXDUMPLIST)) {
141 strncpy(srvResponse,"OK\0",sizeof("OK\0"));
142 NDumpList++;
143 SS5SocksOpt.IsDump = OK;
144 }
145 else
146 strncpy(srvResponse,"ERR\0",sizeof("ERR\0"));
147 }
148
149 if( send(ci->Socket,srvResponse,strlen(srvResponse),0) == -1) {
150 perror("Send err:");
151 return ERR;
152 }
153 return OK;
154 }
155
156 return ERR_SRV_REQUEST;
157 }
158
159 UINT
WritingDump(FILE * df,struct _SS5ProxyData * pd,UINT dumpMode)160 WritingDump( FILE *df, struct _SS5ProxyData *pd, UINT dumpMode )
161 {
162 char headerTitle[128];
163
164 static UINT tx=0;
165 static UINT rx=0;
166
167 /*
168 * TX
169 */
170 if( pd->Fd == 0 ) {
171 if( (dumpMode == TX) || (dumpMode == RTX) ) {
172 if( tx == 0 ) {
173 sprintf(headerTitle,"\n------------------------------ TX SEGMENT ------------------------------\n");
174 fwrite(headerTitle,sizeof(char),strlen(headerTitle),df);
175 tx++;
176 rx = 0;
177 }
178
179 fwrite(pd->Recv,sizeof(char),pd->TcpRBufLen,df);
180 }
181 }
182 /* RX */
183 else {
184 if( (dumpMode == RX) || (dumpMode == RTX) ) {
185 if( rx == 0 ) {
186 sprintf(headerTitle,"\n------------------------------ RX SEGMENT ------------------------------\n");
187 fwrite(headerTitle,sizeof(char),strlen(headerTitle),df);
188 rx++;
189 tx = 0;
190 }
191
192 fwrite(pd->Recv,sizeof(char),pd->TcpRBufLen,df);
193 }
194 }
195 return OK;
196 }
197
198 UINT
OpenDump(FILE ** df,struct _SS5ClientInfo * ci)199 OpenDump( FILE **df, struct _SS5ClientInfo *ci )
200 {
201 char logString[128];
202 char dumpFileName[64];
203 char timeLog[32];
204
205 pid_t pid;
206
207 time_t now;
208 now = time(NULL);
209
210 /*
211 * Get child/thread pid
212 */
213 if( NOTTHREADED() )
214 pid=getpid();
215 else
216 pid=(UINT)(uintmax_t)pthread_self();
217
218 strftime(timeLog,sizeof(timeLog),"%d-%b-%Y-%H-%M-%S",localtime(&now));
219
220 sprintf(dumpFileName,"%s/ss5.%s.%u.%s.trc",S5TracePath,timeLog,pid,ci->Username);
221
222 if( (*df = fopen(dumpFileName,"wb")) == NULL ) {
223 ERRNO(pid)
224 return ERR;
225 }
226 else
227 return OK;
228 }
229
230 UINT
CloseDump(FILE * df)231 CloseDump( FILE *df )
232 {
233
234 fflush(df);
235 fclose(df);
236
237 return OK;
238 }
239
240 /* ***************************** HASH for DUMP **************************** */
S5DumpHash(ULINT da,UINT dp)241 inline UINT S5DumpHash( ULINT da, UINT dp )
242 {
243 register int idx;
244 register int len;
245
246 register long int hashVal = 0;
247
248 char s[32];
249
250 snprintf(s,sizeof(s) - 1,"%lu%u",da,dp);
251
252 len = strlen(s);
253 for(idx = 0; idx < len; idx++)
254 hashVal = 37*hashVal + s[idx];
255
256 hashVal %= MAXDUMPLIST;
257 if(hashVal < 0)
258 hashVal += MAXDUMPLIST;
259
260 return hashVal;
261
262 }
263
GetDump(ULINT sa,UINT sp,ULINT da,UINT dp,struct _SS5DumpInfo * di)264 UINT GetDump(ULINT sa, UINT sp, ULINT da, UINT dp, struct _SS5DumpInfo *di)
265 {
266 register UINT index,nm;
267
268 register ULINT n_da;
269
270 struct _S5DumpNode *node;
271
272 /* Look for SRC DUMP */
273
274 for(nm=0;nm<=32;nm++) {
275 if( nm < 32)
276 n_da=((sa >> nm) << nm);
277 else
278 n_da=0;
279
280 index=S5DumpHash( n_da, sp );
281
282 if( S5DumpList[index]!= NULL ) {
283 node=S5DumpList[index];
284 do {
285 if( (node->DstAddr == n_da) && (node->Mask == (nm)) && (node->DstPort == sp) && (node->DumpDir == SRC_DUMP) ) {
286 di->DumpMode=node->DumpMode;
287 di->DumpDir=node->DumpDir;
288 return OK;
289 }
290 node=node->next;
291 } while(node != NULL );
292 }
293 }
294
295 for(nm=0;nm<=32;nm++) {
296 if( nm < 32)
297 n_da=((sa >> nm) << nm);
298 else
299 n_da=0;
300
301 index=S5DumpHash( n_da, 0 );
302
303 if( S5DumpList[index]!= NULL ) {
304 node=S5DumpList[index];
305 do {
306 if( (node->DstAddr == n_da) && (node->Mask == (nm)) && (sp >= node->DstRangeMin) && (sp <= node->DstRangeMax) && (node->DumpDir == SRC_DUMP) ) {
307 di->DumpMode=node->DumpMode;
308 di->DumpDir=node->DumpDir;
309 return OK;
310 }
311 node=node->next;
312 } while(node != NULL );
313 }
314 }
315
316 /* Look for DST DUMP */
317
318 for(nm=0;nm<=32;nm++) {
319 if( nm < 32)
320 n_da=((da >> nm) << nm);
321 else
322 n_da=0;
323
324 index=S5DumpHash( n_da, dp );
325
326 if( S5DumpList[index]!= NULL ) {
327 node=S5DumpList[index];
328 do {
329 if( (node->DstAddr == n_da) && (node->Mask == (nm)) && (node->DstPort == dp) && (node->DumpDir == DST_DUMP) ) {
330 di->DumpMode=node->DumpMode;
331 di->DumpDir=node->DumpDir;
332 return OK;
333 }
334 node=node->next;
335 } while(node != NULL );
336 }
337 }
338
339 for(nm=0;nm<=32;nm++) {
340 if( nm < 32)
341 n_da=((da >> nm) << nm);
342 else
343 n_da=0;
344
345 index=S5DumpHash( n_da, 0 );
346
347 if( S5DumpList[index]!= NULL ) {
348 node=S5DumpList[index];
349 do {
350 if( (node->DstAddr == n_da) && (node->Mask == (nm)) && (dp >= node->DstRangeMin) && (dp <= node->DstRangeMax) && (node->DumpDir == DST_DUMP) ) {
351 di->DumpMode=node->DumpMode;
352 di->DumpDir=node->DumpDir;
353 return OK;
354 }
355 node=node->next;
356 } while(node != NULL );
357 }
358 }
359
360 return ERR;
361 }
362
DelDump(ULINT da,ULINT dp,UINT mask)363 UINT DelDump(ULINT da, ULINT dp, UINT mask )
364 {
365 int index;
366 struct _S5DumpNode *node, *prevnode=NULL;
367
368 if( dp > 65535 )
369 index=S5DumpHash( da, 0 );
370 else
371 index=S5DumpHash( da, dp );
372
373
374 node=S5DumpList[index];
375
376 if( node == NULL )
377 return ERR;
378
379 if( (node->DstAddr == da) && (node->Mask == mask) && (dp == node->DstPort) ) {
380 if( node->next == NULL ) {
381
382 free(node);
383 S5DumpList[index]=NULL;
384 return OK;
385 }
386 else {
387 S5DumpList[index]=node->next;
388 free(node);
389 return OK;
390 }
391 }
392
393 while( node->next != NULL ) {
394 prevnode=node;
395 node=node->next;
396
397 if( (node->DstAddr == da) && (node->Mask == mask) && (dp == node->DstPort) ) {
398 if( node->next != NULL )
399 prevnode->next=node->next;
400 else
401 prevnode->next=NULL;
402
403 free(node);
404 node=NULL;
405
406 return OK;
407 }
408 }
409 return ERR;
410 }
411
412
AddDump(UINT ctx,ULINT da,ULINT dp,UINT dumpDir,UINT dumpMode,UINT mask)413 UINT AddDump(UINT ctx, ULINT da, ULINT dp, UINT dumpDir, UINT dumpMode, UINT mask )
414 {
415 int index;
416 struct _S5DumpNode *node, *prevnode;
417
418 if( dp > 65535 )
419 index=S5DumpHash( da, 0 );
420 else
421 index=S5DumpHash( da, dp );
422
423 if( ctx == OFFLINE )
424 node=_tmp_S5DumpList[index];
425 else
426 node=S5DumpList[index];
427
428 if( node == NULL ) {
429 if( (node=(struct _S5DumpNode *)calloc(1,sizeof(struct _S5DumpNode))) == NULL )
430 return ERR;
431
432 node->Mask=mask;
433 node->DstAddr=da;
434
435 if( dp > 65535 ) {
436 node->DstPort=dp;
437 node->DstRangeMax=dp;
438 node->DstRangeMax >>= 16;
439 node->DstRangeMax <<= 16;
440 node->DstRangeMin = dp - node->DstRangeMax;
441 node->DstRangeMax >>= 16;
442
443 }
444 else
445 node->DstPort=dp;
446
447 node->DumpDir=dumpDir;
448 node->DumpMode=dumpMode;
449 node->next=NULL;
450
451 if( ctx == OFFLINE )
452 _tmp_S5DumpList[index]=node;
453 else
454 S5DumpList[index]=node;
455 }
456 else {
457 if( ctx == OFFLINE )
458 node=_tmp_S5DumpList[index];
459 else
460 node=S5DumpList[index];
461
462 do {
463 if( (node->DstAddr == da) && (node->Mask == mask) && (node->DstPort == dp) ) {
464 return ERR;
465 }
466 prevnode=node;
467 node=node->next;
468
469 } while(node != NULL );
470
471 if( (node=(struct _S5DumpNode *)calloc(1,sizeof(struct _S5DumpNode))) == NULL )
472 return ERR;
473
474 node->Mask=mask;
475 node->DstAddr=da;
476
477 if( dp > 65535 ) {
478 node->DstPort=dp;
479 node->DstRangeMax=dp;
480 node->DstRangeMax >>= 16;
481 node->DstRangeMax <<= 16;
482 node->DstRangeMin = dp - node->DstRangeMax;
483 node->DstRangeMax >>= 16;
484 }
485 else
486 node->DstPort=dp;
487
488 node->DumpMode=dumpMode;
489 node->DumpDir=dumpDir;
490 node->next=NULL;
491
492 prevnode->next=node;
493 }
494 return OK;
495 }
496
FreeDump(struct _S5DumpNode ** node)497 UINT FreeDump( struct _S5DumpNode **node )
498 {
499 struct _S5DumpNode *lnode;
500 struct _S5DumpNode *lnode_prev=NULL;
501
502 lnode=*node;
503
504 if( lnode != NULL ) {
505 do {
506 while( lnode->next != NULL ) {
507 lnode_prev=lnode;
508 lnode=lnode->next;
509 }
510 free(lnode);
511 if( lnode_prev != NULL ) {
512 lnode_prev->next=NULL;
513 lnode=lnode_prev;
514 lnode_prev=NULL;
515 }
516 else
517 lnode=NULL;
518 } while( (lnode) != NULL );
519 }
520 *node=NULL;
521
522 return OK;
523
524 }
525
526