1 /*
2    3APA3A simpliest proxy server
3    (c) 2002-2016 by Vladimir Dubrovin <3proxy@3proxy.ru>
4 
5    please read License Agreement
6 
7 */
8 
9 #include "proxy.h"
10 
11 #define RETURN(xxx) { param->res = xxx; goto CLEANRET; }
12 
13 unsigned char * commands[] = {(unsigned char *)"UNKNOWN", (unsigned char *)"CONNECT", (unsigned char *)"BIND", (unsigned char *)"UDPMAP"};
14 
15 #define BUFSIZE 1024
16 #define LARGEBUFSIZE 67000
17 
sockschild(struct clientparam * param)18 void * sockschild(struct clientparam* param) {
19  int res;
20  unsigned i=0;
21  SOCKET s;
22  unsigned size;
23  SASIZETYPE sasize;
24  unsigned short port = 0;
25  unsigned char * buf=NULL;
26  unsigned char c;
27  unsigned char command=0;
28  struct pollfd fds[3];
29  int ver=0;
30  int havepass = 0;
31 #ifndef NOIPV6
32  struct sockaddr_in6 sin = {AF_INET6};
33 #else
34  struct sockaddr_in sin = {AF_INET};
35 #endif
36  int len;
37 
38 
39  param->service = S_SOCKS;
40 
41  if(!(buf = myalloc(BUFSIZE))) {RETURN(21);}
42  memset(buf, 0, BUFSIZE);
43  if ((ver = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0)) != 5 && ver != 4) {
44 	RETURN(401);
45  } /* version */
46  param->service = ver;
47  if(ver == 5){
48 	 if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);} /* nmethods */
49 	 for (; i; i--) {
50 		if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
51 		if (res == 2 && param->srv->needuser) {
52 			havepass = res;
53 		}
54 	 }
55 	 buf[0] = 5;
56 	 buf[1] = (param->srv->needuser > 1 && !havepass)? 255 : havepass;
57 	 if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(401);}
58 	 if (param->srv->needuser > 1 && !havepass) RETURN(4);
59 	 if (havepass) {
60 		if (((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0))) != 1) {
61 			RETURN(412);
62 		}
63 		if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(451);}
64 		if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(441);};
65 		buf[i] = 0;
66 		if(!param->username)param->username = (unsigned char *)mystrdup((char *)buf);
67 		if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(445);}
68 		if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(441);};
69 		buf[i] = 0;
70 		if(!param->password)param->password = (unsigned char *)mystrdup((char *)buf);
71 		buf[0] = 1;
72 		buf[1] = 0;
73 		if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(481);}
74 	 }
75 	 if ((c = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0)) != 5) {
76 		RETURN(421);
77          } /* version */
78  }
79  if( (command = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) < 1 || command > 3){command = 0; RETURN(407);} /* command */
80  if(ver == 5){
81 	 if (sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0) == EOF) {RETURN(447);} /* reserved */
82 	 c = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0); /* atype */
83  }
84  else {
85 	if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
86 	buf[0] = (unsigned char) res;
87 	if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
88 	buf[1] = (unsigned char) res;
89 	port = *(unsigned short*)buf;
90 	c = 1;
91  }
92 
93  size = 4;
94  *SAFAMILY(&param->sinsr) = *SAFAMILY(&param->req) = AF_INET;
95  switch(c) {
96 #ifndef NOIPV6
97 	case 4:
98 		if(param->srv->family == 4) RETURN(997);
99 		size = 16;
100 		*SAFAMILY(&param->sinsr) = *SAFAMILY(&param->req) = AF_INET6;
101 #endif
102 	case 1:
103 		for (i = 0; i<size; i++){
104 			if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
105 			buf[i] = (unsigned char)res;
106 		}
107 #ifndef NOIPV6
108 		if (c == 1 && param->srv->family==6){
109 			char prefix[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255};
110 			*SAFAMILY(&param->sinsr) = *SAFAMILY(&param->req) = AF_INET6;
111 			memcpy(SAADDR(&param->sinsr), prefix, 12);
112 			memcpy(12 + (char *)SAADDR(&param->sinsr), buf, 4);
113 			memcpy(SAADDR(&param->req), prefix, 12);
114 			memcpy(12 + (char *)SAADDR(&param->req), buf, 4);
115 		}
116 		else {
117 #endif
118 			memcpy(SAADDR(&param->sinsr), buf, size);
119 			memcpy(SAADDR(&param->req), buf, size);
120 #ifndef NOIPV6
121 		}
122 #endif
123 		if(command == 1 && SAISNULL(&param->req)) {
124 			RETURN(431);
125 		}
126 		myinet_ntop(*SAFAMILY(&param->sinsr), SAADDR(&param->sinsr), (char *)buf, 64);
127 		break;
128 	case 3:
129 		if ((size = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(451);} /* nmethods */
130 		for (i=0; i<size; i++){ /* size < 256 */
131 			if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(451);}
132 			buf[i] = (unsigned char)res;
133 		}
134 		buf[i] = 0;
135 		if(!getip46(param->srv->family, buf, (struct sockaddr *) &param->req)) RETURN(100);
136 		param->sinsr = param->req;
137 		break;
138 	default:
139 		RETURN(997);
140  }
141  if(param->hostname)myfree(param->hostname);
142  param->hostname = (unsigned char *)mystrdup((char *)buf);
143  if (ver == 5) {
144 	 if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
145 	 buf[0] = (unsigned char) res;
146 	 if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
147 	 buf[1] = (unsigned char) res;
148 	 port = *(unsigned short*)buf;
149 
150  }
151  else {
152 	sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]);
153 	buf[127] = 0;
154 	if(param->srv->needuser && *buf && !param->username)param->username = (unsigned char *)mystrdup((char *)buf);
155 	if(!memcmp(SAADDR(&param->req), "\0\0\0", 3)){
156 		param->service = S_SOCKS45;
157 		sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]);
158 		buf[127] = 0;
159 		if(param->hostname)myfree(param->hostname);
160 		param->hostname = (unsigned char *)mystrdup((char *)buf);
161 		if(!getip46(param->srv->family, buf, (struct sockaddr *) &param->req)) RETURN(100);
162 		param->sinsr = param->req;
163 	}
164  }
165 
166  *SAPORT(&param->sinsr) = *SAPORT(&param->req) = port;
167  if(command == 1 && !*SAPORT(&param->sinsr)) {RETURN(461);}
168  switch(command) {
169 	case 1:
170 	 param->operation = CONNECT;
171 	 break;
172  	case 2:
173 	case 3:
174 
175 #ifndef NOIPV6
176 	 param->sinsl = *SAFAMILY(&param->req)==AF_INET6? param->srv->extsa6 : (SAISNULL(&param->srv->extNat)?param->srv->extsa:param->srv->extNat);
177 #else
178 	 param->sinsl = SAISNULL(&param->srv->extNat)?param->srv->extsa:param->srv->extNat;
179 #endif
180 	 if ((param->remsock=so._socket(SASOCK(&param->req), command == 2? SOCK_STREAM:SOCK_DGRAM, command == 2?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);}
181 	 param->operation = command == 2?BIND:UDPASSOC;
182 #ifdef REUSE
183 	if (command == 2){
184 		int opt;
185 
186 #ifdef SO_REUSEADDR
187 		opt = 1;
188 		so._setsockopt(param->remsock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&opt, sizeof(int));
189 #endif
190 #ifdef SO_REUSEPORT
191 		opt = 1;
192 		so._setsockopt(param->remsock, SOL_SOCKET, SO_REUSEPORT, (unsigned char *)&opt, sizeof(int));
193 #endif
194 	}
195 #endif
196 	 break;
197 
198 	default:
199 	 RETURN(997);
200  }
201 
202  if((res = (*param->srv->authfunc)(param))) {
203 	RETURN(res);
204  }
205 
206  if(command > 1) {
207 	if(so._bind(param->remsock,(struct sockaddr *)&param->sinsl,SASIZE(&param->sinsl))) {
208 		*SAPORT(&param->sinsl) = 0;
209 		if(so._bind(param->remsock,(struct sockaddr *)&param->sinsl,SASIZE(&param->sinsl)))RETURN (12);
210 #if SOCKSTRACE > 0
211 fprintf(stderr, "%hu bound to communicate with server\n", *SAPORT(&param->sins));
212 fflush(stderr);
213 #endif
214 	}
215 	sasize = SASIZE(&param->sinsl);
216 	so._getsockname(param->remsock, (struct sockaddr *)&param->sinsl,  &sasize);
217 	if(command == 3) {
218 		param->ctrlsock = param->clisock;
219 		param->clisock = so._socket(SASOCK(&param->sincr), SOCK_DGRAM, IPPROTO_UDP);
220 		if(param->clisock == INVALID_SOCKET) {RETURN(11);}
221 		sin = param->sincl;
222 		*SAPORT(&sin) = 0;
223 		if(so._bind(param->clisock,(struct sockaddr *)&sin,SASIZE(&sin))) {RETURN (12);}
224 #if SOCKSTRACE > 0
225 fprintf(stderr, "%hu binded to communicate with client\n",
226 			ntohs(*SAPORT(&sin))
227 	);
228 fflush(stderr);
229 #endif
230 	}
231  }
232  param->res = 0;
233 
234 CLEANRET:
235 
236  if(param->clisock != INVALID_SOCKET){
237 	int repcode;
238 
239 	sasize = sizeof(sin);
240 	if(command != 3 && param->remsock != INVALID_SOCKET) so._getsockname(param->remsock, (struct sockaddr *)&sin,  &sasize);
241 	else so._getsockname(param->clisock, (struct sockaddr *)&sin,  &sasize);
242 #if SOCKSTRACE > 0
243 fprintf(stderr, "Sending confirmation to client with code %d for %s with %s:%hu\n",
244 			param->res,
245 			commands[command],
246 			inet_ntoa(sin.sin_addr),
247 			ntohs(sin.sin_port)
248 	);
249 fflush(stderr);
250 #endif
251 	if(!param->res) repcode = 0;
252 	else if(param->res <= 10) repcode = 2;
253 	else if (param->res < 20) repcode = 5;
254 	else if (param->res < 30) repcode = 1;
255 	else if (param->res < 100) repcode = 4;
256 	else repcode = param->res%10;
257 
258 	if(ver == 5){
259 		buf[0] = 5;
260 		buf[1] = repcode;
261 		buf[2] = 0;
262 		buf[3] = (*SAFAMILY(&sin) == AF_INET)?1:4;
263 		memcpy(buf+4, SAADDR(&sin), SAADDRLEN(&sin));
264 		memcpy(buf+4+SAADDRLEN(&sin), SAPORT(&sin), 2);
265 		socksend((command == 3)?param->ctrlsock:param->clisock, buf, 6+SAADDRLEN(&sin), conf.timeouts[STRING_S]);
266 	}
267 	else{
268 		buf[0] = 0;
269 		buf[1] = 90 + !!(repcode);
270 		memcpy(buf+2, SAPORT(&sin), 2);
271 		memcpy(buf+4, SAADDR(&sin), 4);
272 		socksend(param->clisock, buf, 8, conf.timeouts[STRING_S]);
273 	}
274 
275 	if (param->res == 0) {
276 		switch(command) {
277 			case 1:
278 				if(param->redirectfunc){
279 					if(buf)myfree(buf);
280 					return (*param->redirectfunc)(param);
281 				}
282 				param->res = mapsocket(param, conf.timeouts[CONNECTION_L]);
283 				break;
284 			case 2:
285 				so._listen (param->remsock, 1);
286 
287 				fds[0].fd = param->remsock;
288 				fds[1].fd = param->clisock;
289 				fds[0].events = fds[1].events = POLLIN;
290 				res = so._poll(fds, 2, conf.timeouts[CONNECTION_L] * 1000);
291 				if (res < 1 || fds[1].revents) {
292 					res = 460;
293 					break;
294 				}
295 				sasize = sizeof(param->sinsr);
296 				s = so._accept(param->remsock, (struct sockaddr *)&param->sinsr, &sasize);
297 				so._closesocket(param->remsock);
298 				param->remsock = s;
299 				if(s == INVALID_SOCKET) {
300 					param->res = 462;
301 					break;
302 				}
303 				if(SAISNULL(&param->req) &&
304 				 memcmp(SAADDR(&param->req),SAADDR(&param->sinsr),SAADDRLEN(&param->req))) {
305 					param->res = 470;
306 					break;
307 				}
308 #if SOCKSTRACE > 0
309 fprintf(stderr, "Sending incoming connection to client with code %d for %s with %hu\n",
310 			param->res,
311 			commands[command],
312 			*SAPORT(param->sins);
313 	);
314 fflush(stderr);
315 #endif
316 				if(ver == 5){
317 					buf[3] = (*SAFAMILY(&param->sinsr) == AF_INET)?1:4;
318 					memcpy(buf+4, SAADDR(&param->sinsr), SAADDRLEN(&param->sinsr));
319 					memcpy(buf+4+SAADDRLEN(&param->sinsr), SAPORT(&param->sinsr), 2);
320 					socksend(param->clisock, buf, 6+SAADDRLEN(&param->sinsr), conf.timeouts[STRING_S]);
321 				}
322 				else {
323 					memcpy (buf+2, SAPORT(&param->sinsr), 2);
324 					memcpy (buf+4, SAADDR(&param->sinsr), 4);
325 					socksend(param->clisock, buf, 8, conf.timeouts[STRING_S]);
326 				}
327 
328 				param->res = mapsocket(param, conf.timeouts[CONNECTION_S]);
329 				break;
330 			case 3:
331 				param->sinsr = param->req;
332 				myfree(buf);
333 				if(!(buf = myalloc(LARGEBUFSIZE))) {RETURN(21);}
334 				sin = param->sincr;
335 
336 				for(;;){
337 					fds[0].fd = param->remsock;
338 					fds[1].fd = param->clisock;
339 					fds[2].fd = param->ctrlsock;
340 					fds[2].events = fds[1].events = fds[0].events = POLLIN;
341 
342 					res = so._poll(fds, 3, conf.timeouts[CONNECTION_L]*1000);
343 					if(res <= 0) {
344 						param->res = 463;
345 						break;
346 					}
347 					if (fds[2].revents) {
348 						param->res = 0;
349 						break;
350 					}
351 					if (fds[1].revents) {
352 						sasize = sizeof(sin);
353 						if((len = so._recvfrom(param->clisock, (char *)buf, 65535, 0, (struct sockaddr *)&sin, &sasize)) <= 10) {
354 							param->res = 464;
355 							break;
356 						}
357 						if(SAADDRLEN(&sin) != SAADDRLEN(&param->sincr) || memcmp(SAADDR(&sin), SAADDR(&param->sincr), SAADDRLEN(&sin))){
358 							param->res = 465;
359 							break;
360 						}
361 						if(buf[0] || buf[1] || buf[2]) {
362 							param->res = 466;
363 							break;
364 						}
365 						size = 4;
366 						switch(buf[3]) {
367 							case 4:
368 								size = 16;
369 							case 1:
370 								i = 4+size;
371 								memcpy(SAADDR(&param->sinsr), buf+4, size);
372 								*SAFAMILY(&param->sinsr) = (size == 4)?AF_INET:AF_INET6;
373 								break;
374 							case 3:
375 								size = buf[4];
376 								for (i=4; size; i++, size--){
377 									buf[i] = buf[i+1];
378 								}
379 								buf[i++] = 0;
380 								if(!getip46(param->srv->family, buf+4, (struct sockaddr *) &param->sinsr)) RETURN(100);
381 								break;
382 							default:
383 								RETURN(997);
384 						 }
385 
386 						memcpy(SAPORT(&param->sinsr), buf+i, 2);
387 						i+=2;
388 
389 						sasize = sizeof(param->sinsr);
390 						if(len > (int)i){
391 							socksendto(param->remsock, (struct sockaddr *)&param->sinsr, buf+i, len - i, conf.timeouts[SINGLEBYTE_L]*1000);
392 							param->statscli64+=(len - i);
393 							param->nwrites++;
394 #if SOCKSTRACE > 1
395 fprintf(stderr, "UDP packet relayed from client to %s:%hu size %d, header %d\n",
396 			inet_ntoa(param->sins.sin_addr),
397 			ntohs(param->sins.sin_port),
398 			(len - i),
399 			i
400 	);
401 fprintf(stderr, "client address is assumed to be %s:%hu\n",
402 			inet_ntoa(sin.sin_addr),
403 			ntohs(sin.sin_port)
404 	);
405 fflush(stderr);
406 #endif
407 						}
408 
409 					}
410 					if (fds[0].revents) {
411 						sasize = sizeof(param->sinsr);
412 						buf[0]=buf[1]=buf[2]=0;
413 						buf[3]=(*SAFAMILY(&param->sinsl) == AF_INET)?1:4;
414 						if((len = so._recvfrom(param->remsock, (char *)buf+6+SAADDRLEN(&param->sinsl), 65535 - (6+SAADDRLEN(&param->sinsl)), 0, (struct sockaddr *)&param->sinsr, &sasize)) <= 0) {
415 							param->res = 468;
416 							break;
417 						}
418 						param->statssrv64+=len;
419 						param->nreads++;
420 						memcpy(buf+4, SAADDR(&param->sinsr), SAADDRLEN(&param->sinsr));
421 						memcpy(buf+4+SAADDRLEN(&param->sinsr), SAPORT(&param->sinsr), 2);
422 						sasize = sizeof(sin);
423 						socksendto(param->clisock, (struct sockaddr *)&sin, buf, len + 6 + SAADDRLEN(&param->sinsr), conf.timeouts[SINGLEBYTE_L]*1000);
424 #if SOCKSTRACE > 1
425 fprintf(stderr, "UDP packet relayed to client from %hu size %d\n",
426 			ntohs(*SAPORT(&param->sinsr)),
427 			len
428 	);
429 fflush(stderr);
430 #endif
431 
432 					}
433 				}
434 				break;
435 			default:
436 				param->res = 417;
437 				break;
438 		}
439 	}
440  }
441 
442  if(command > 3) command = 0;
443  if(buf){
444 	 sprintf((char *)buf, "%s ", commands[command]);
445 	 if(param->hostname){
446 	  sprintf((char *)buf + strlen((char *)buf), "%.265s", param->hostname);
447 	 }
448 	 else
449 		myinet_ntop(*SAFAMILY(&param->req), SAADDR(&param->req), (char *)buf + strlen((char *)buf), 64);
450          sprintf((char *)buf+strlen((char *)buf), ":%hu", ntohs(*SAPORT(&param->req)));
451 	 dolog(param, buf);
452 	 myfree(buf);
453  }
454  freeparam(param);
455  return (NULL);
456 }
457 
458 #ifdef WITHMAIN
459 struct proxydef childdef = {
460 	sockschild,
461 	1080,
462 	0,
463 	S_SOCKS,
464 	"-N(EXTERNAL_IP) External NAT address to report to client for BIND\n"
465 };
466 #include "proxymain.c"
467 #endif
468