socksd.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
  9. *
  10. * This software is licensed as described in the file COPYING, which
  11. * you should have received as part of this distribution. The terms
  12. * are also available at https://curl.haxx.se/docs/copyright.html.
  13. *
  14. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15. * copies of the Software, and permit persons to whom the Software is
  16. * furnished to do so, under the terms of the COPYING file.
  17. *
  18. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19. * KIND, either express or implied.
  20. *
  21. ***************************************************************************/
  22. #include "server_setup.h"
  23. #include <stdlib.h>
  24. /* Function
  25. *
  26. * Accepts a TCP connection on a custom port (IPv4 or IPv6). Connects to a
  27. * given addr + port backend (that is NOT extracted form the client's
  28. * request). The backend server default to connect to can be set with
  29. * --backend and --backendport.
  30. *
  31. * Read commands from FILE (set with --config). The commands control how to
  32. * act and is reset to defaults each client TCP connect.
  33. *
  34. * Config file keywords:
  35. *
  36. * "version [number: 5]" - requires the communication to use this version.
  37. * "nmethods_min [number: 1]" - the minimum numberf NMETHODS the client must
  38. * state
  39. * "nmethods_max [number: 3]" - the minimum numberf NMETHODS the client must
  40. * state
  41. * "user [string]" - the user name that must match (if method is 2)
  42. * "password [string]" - the password that must match (if method is 2)
  43. * "backend [IPv4]" - numerical IPv4 address of backend to connect to
  44. * "backendport [number:0]" - TCP port of backend to connect to. 0 means use
  45. the client's specified port number.
  46. * "method [number: 0]" - connect method to respond with:
  47. * 0 - no auth
  48. * 1 - GSSAPI (not supported)
  49. * 2 - user + password
  50. * "response [number]" - the decimal number to repsond to a connect
  51. * SOCKS5: 0 is OK, SOCKS4: 90 is ok
  52. *
  53. */
  54. /* based on sockfilt.c */
  55. #ifdef HAVE_SIGNAL_H
  56. #include <signal.h>
  57. #endif
  58. #ifdef HAVE_NETINET_IN_H
  59. #include <netinet/in.h>
  60. #endif
  61. #ifdef HAVE_NETINET_IN6_H
  62. #include <netinet/in6.h>
  63. #endif
  64. #ifdef HAVE_ARPA_INET_H
  65. #include <arpa/inet.h>
  66. #endif
  67. #ifdef HAVE_NETDB_H
  68. #include <netdb.h>
  69. #endif
  70. #define ENABLE_CURLX_PRINTF
  71. /* make the curlx header define all printf() functions to use the curlx_*
  72. versions instead */
  73. #include "curlx.h" /* from the private lib dir */
  74. #include "getpart.h"
  75. #include "inet_pton.h"
  76. #include "util.h"
  77. #include "server_sockaddr.h"
  78. #include "warnless.h"
  79. /* include memdebug.h last */
  80. #include "memdebug.h"
  81. #ifdef USE_WINSOCK
  82. #undef EINTR
  83. #define EINTR 4 /* errno.h value */
  84. #undef EAGAIN
  85. #define EAGAIN 11 /* errno.h value */
  86. #undef ENOMEM
  87. #define ENOMEM 12 /* errno.h value */
  88. #undef EINVAL
  89. #define EINVAL 22 /* errno.h value */
  90. #endif
  91. #define DEFAULT_PORT 8905
  92. #ifndef DEFAULT_LOGFILE
  93. #define DEFAULT_LOGFILE "log/socksd.log"
  94. #endif
  95. #ifndef DEFAULT_CONFIG
  96. #define DEFAULT_CONFIG "socksd.config"
  97. #endif
  98. static const char *backendaddr = "127.0.0.1";
  99. static unsigned short backendport = 0; /* default is use client's */
  100. struct configurable {
  101. unsigned char version; /* initial version byte in the request must match
  102. this */
  103. unsigned char nmethods_min; /* minimum number of nmethods to expect */
  104. unsigned char nmethods_max; /* maximum number of nmethods to expect */
  105. unsigned char responseversion;
  106. unsigned char responsemethod;
  107. unsigned char reqcmd;
  108. unsigned char connectrep;
  109. unsigned short port; /* backend port */
  110. char addr[32]; /* backend IPv4 numerical */
  111. char user[256];
  112. char password[256];
  113. };
  114. #define CONFIG_VERSION 5
  115. #define CONFIG_NMETHODS_MIN 1 /* unauth, gssapi, auth */
  116. #define CONFIG_NMETHODS_MAX 3
  117. #define CONFIG_RESPONSEVERSION CONFIG_VERSION
  118. #define CONFIG_RESPONSEMETHOD 0 /* no auth */
  119. #define CONFIG_REQCMD 1 /* CONNECT */
  120. #define CONFIG_PORT backendport
  121. #define CONFIG_ADDR backendaddr
  122. #define CONFIG_CONNECTREP 0
  123. static struct configurable config;
  124. const char *serverlogfile = DEFAULT_LOGFILE;
  125. static const char *configfile = DEFAULT_CONFIG;
  126. #ifdef ENABLE_IPV6
  127. static bool use_ipv6 = FALSE;
  128. #endif
  129. static const char *ipv_inuse = "IPv4";
  130. static unsigned short port = DEFAULT_PORT;
  131. static void resetdefaults(void)
  132. {
  133. logmsg("Reset to defaults");
  134. config.version = CONFIG_VERSION;
  135. config.nmethods_min = CONFIG_NMETHODS_MIN;
  136. config.nmethods_max = CONFIG_NMETHODS_MAX;
  137. config.responseversion = CONFIG_RESPONSEVERSION;
  138. config.responsemethod = CONFIG_RESPONSEMETHOD;
  139. config.reqcmd = CONFIG_REQCMD;
  140. config.connectrep = CONFIG_CONNECTREP;
  141. config.port = CONFIG_PORT;
  142. strcpy(config.addr, CONFIG_ADDR);
  143. strcpy(config.user, "user");
  144. strcpy(config.password, "password");
  145. }
  146. static unsigned char byteval(char *value)
  147. {
  148. unsigned long num = strtoul(value, NULL, 10);
  149. return num & 0xff;
  150. }
  151. static unsigned short shortval(char *value)
  152. {
  153. unsigned long num = strtoul(value, NULL, 10);
  154. return num & 0xffff;
  155. }
  156. static void getconfig(void)
  157. {
  158. FILE *fp = fopen(configfile, FOPEN_READTEXT);
  159. resetdefaults();
  160. if(fp) {
  161. char buffer[512];
  162. logmsg("parse config file");
  163. while(fgets(buffer, sizeof(buffer), fp)) {
  164. char key[32];
  165. char value[32];
  166. if(2 == sscanf(buffer, "%31s %31s", key, value)) {
  167. if(!strcmp(key, "version")) {
  168. config.version = byteval(value);
  169. logmsg("version [%d] set", config.version);
  170. }
  171. else if(!strcmp(key, "nmethods_min")) {
  172. config.nmethods_min = byteval(value);
  173. logmsg("nmethods_min [%d] set", config.nmethods_min);
  174. }
  175. else if(!strcmp(key, "nmethods_max")) {
  176. config.nmethods_max = byteval(value);
  177. logmsg("nmethods_max [%d] set", config.nmethods_max);
  178. }
  179. else if(!strcmp(key, "backend")) {
  180. strcpy(config.addr, value);
  181. logmsg("backend [%s] set", config.addr);
  182. }
  183. else if(!strcmp(key, "backendport")) {
  184. config.port = shortval(value);
  185. logmsg("backendport [%d] set", config.port);
  186. }
  187. else if(!strcmp(key, "user")) {
  188. strcpy(config.user, value);
  189. logmsg("user [%s] set", config.user);
  190. }
  191. else if(!strcmp(key, "password")) {
  192. strcpy(config.password, value);
  193. logmsg("password [%s] set", config.password);
  194. }
  195. /* Methods:
  196. o X'00' NO AUTHENTICATION REQUIRED
  197. o X'01' GSSAPI
  198. o X'02' USERNAME/PASSWORD
  199. */
  200. else if(!strcmp(key, "method")) {
  201. config.responsemethod = byteval(value);
  202. logmsg("method [%d] set", config.responsemethod);
  203. }
  204. else if(!strcmp(key, "response")) {
  205. config.connectrep = byteval(value);
  206. logmsg("response [%d] set", config.connectrep);
  207. }
  208. }
  209. }
  210. fclose(fp);
  211. }
  212. }
  213. /* do-nothing macro replacement for systems which lack siginterrupt() */
  214. #ifndef HAVE_SIGINTERRUPT
  215. #define siginterrupt(x,y) do {} while(0)
  216. #endif
  217. /* vars used to keep around previous signal handlers */
  218. typedef RETSIGTYPE (*SIGHANDLER_T)(int);
  219. #ifdef SIGHUP
  220. static SIGHANDLER_T old_sighup_handler = SIG_ERR;
  221. #endif
  222. #ifdef SIGPIPE
  223. static SIGHANDLER_T old_sigpipe_handler = SIG_ERR;
  224. #endif
  225. #ifdef SIGALRM
  226. static SIGHANDLER_T old_sigalrm_handler = SIG_ERR;
  227. #endif
  228. #ifdef SIGINT
  229. static SIGHANDLER_T old_sigint_handler = SIG_ERR;
  230. #endif
  231. #if defined(SIGBREAK) && defined(WIN32)
  232. static SIGHANDLER_T old_sigbreak_handler = SIG_ERR;
  233. #endif
  234. /* var which if set indicates that the program should finish execution */
  235. SIG_ATOMIC_T got_exit_signal = 0;
  236. /* if next is set indicates the first signal handled in exit_signal_handler */
  237. static volatile int exit_signal = 0;
  238. /* signal handler that will be triggered to indicate that the program
  239. should finish its execution in a controlled manner as soon as possible.
  240. The first time this is called it will set got_exit_signal to one and
  241. store in exit_signal the signal that triggered its execution. */
  242. static RETSIGTYPE exit_signal_handler(int signum)
  243. {
  244. int old_errno = errno;
  245. if(got_exit_signal == 0) {
  246. got_exit_signal = 1;
  247. exit_signal = signum;
  248. }
  249. (void)signal(signum, exit_signal_handler);
  250. errno = old_errno;
  251. }
  252. static void install_signal_handlers(void)
  253. {
  254. #ifdef SIGHUP
  255. /* ignore SIGHUP signal */
  256. old_sighup_handler = signal(SIGHUP, SIG_IGN);
  257. if(old_sighup_handler == SIG_ERR)
  258. logmsg("cannot install SIGHUP handler: %s", strerror(errno));
  259. #endif
  260. #ifdef SIGPIPE
  261. /* ignore SIGPIPE signal */
  262. old_sigpipe_handler = signal(SIGPIPE, SIG_IGN);
  263. if(old_sigpipe_handler == SIG_ERR)
  264. logmsg("cannot install SIGPIPE handler: %s", strerror(errno));
  265. #endif
  266. #ifdef SIGALRM
  267. /* ignore SIGALRM signal */
  268. old_sigalrm_handler = signal(SIGALRM, SIG_IGN);
  269. if(old_sigalrm_handler == SIG_ERR)
  270. logmsg("cannot install SIGALRM handler: %s", strerror(errno));
  271. #endif
  272. #ifdef SIGINT
  273. /* handle SIGINT signal with our exit_signal_handler */
  274. old_sigint_handler = signal(SIGINT, exit_signal_handler);
  275. if(old_sigint_handler == SIG_ERR)
  276. logmsg("cannot install SIGINT handler: %s", strerror(errno));
  277. else
  278. siginterrupt(SIGINT, 1);
  279. #endif
  280. #if defined(SIGBREAK) && defined(WIN32)
  281. /* handle SIGBREAK signal with our exit_signal_handler */
  282. old_sigbreak_handler = signal(SIGBREAK, exit_signal_handler);
  283. if(old_sigbreak_handler == SIG_ERR)
  284. logmsg("cannot install SIGBREAK handler: %s", strerror(errno));
  285. else
  286. siginterrupt(SIGBREAK, 1);
  287. #endif
  288. }
  289. static void restore_signal_handlers(void)
  290. {
  291. #ifdef SIGHUP
  292. if(SIG_ERR != old_sighup_handler)
  293. (void)signal(SIGHUP, old_sighup_handler);
  294. #endif
  295. #ifdef SIGPIPE
  296. if(SIG_ERR != old_sigpipe_handler)
  297. (void)signal(SIGPIPE, old_sigpipe_handler);
  298. #endif
  299. #ifdef SIGALRM
  300. if(SIG_ERR != old_sigalrm_handler)
  301. (void)signal(SIGALRM, old_sigalrm_handler);
  302. #endif
  303. #ifdef SIGINT
  304. if(SIG_ERR != old_sigint_handler)
  305. (void)signal(SIGINT, old_sigint_handler);
  306. #endif
  307. #if defined(SIGBREAK) && defined(WIN32)
  308. if(SIG_ERR != old_sigbreak_handler)
  309. (void)signal(SIGBREAK, old_sigbreak_handler);
  310. #endif
  311. }
  312. static void loghex(unsigned char *buffer, ssize_t len)
  313. {
  314. char data[1200];
  315. ssize_t i;
  316. unsigned char *ptr = buffer;
  317. char *optr = data;
  318. ssize_t width = 0;
  319. int left = sizeof(data);
  320. for(i = 0; i<len && (left >= 0); i++) {
  321. msnprintf(optr, left, "%02x", ptr[i]);
  322. width += 2;
  323. optr += 2;
  324. left -= 2;
  325. }
  326. if(width)
  327. logmsg("'%s'", data);
  328. }
  329. /* RFC 1928, SOCKS5 byte index */
  330. #define SOCKS5_VERSION 0
  331. #define SOCKS5_NMETHODS 1 /* number of methods that is listed */
  332. /* in the request: */
  333. #define SOCKS5_REQCMD 1
  334. #define SOCKS5_RESERVED 2
  335. #define SOCKS5_ATYP 3
  336. #define SOCKS5_DSTADDR 4
  337. /* connect response */
  338. #define SOCKS5_REP 1
  339. #define SOCKS5_BNDADDR 4
  340. /* auth request */
  341. #define SOCKS5_ULEN 1
  342. #define SOCKS5_UNAME 2
  343. #define SOCKS4_CD 1
  344. #define SOCKS4_DSTPORT 2
  345. /* connect to a given IPv4 address, not the one asked for */
  346. static curl_socket_t socksconnect(unsigned short connectport,
  347. const char *connectaddr)
  348. {
  349. int rc;
  350. srvr_sockaddr_union_t me;
  351. curl_socket_t sock = socket(AF_INET, SOCK_STREAM, 0);
  352. if(sock == CURL_SOCKET_BAD)
  353. return CURL_SOCKET_BAD;
  354. memset(&me.sa4, 0, sizeof(me.sa4));
  355. me.sa4.sin_family = AF_INET;
  356. me.sa4.sin_port = htons(connectport);
  357. me.sa4.sin_addr.s_addr = INADDR_ANY;
  358. Curl_inet_pton(AF_INET, connectaddr, &me.sa4.sin_addr);
  359. rc = connect(sock, &me.sa, sizeof(me.sa4));
  360. if(rc) {
  361. int error = SOCKERRNO;
  362. logmsg("Error connecting to %s:%hu: (%d) %s",
  363. connectaddr, connectport, error, strerror(error));
  364. return CURL_SOCKET_BAD;
  365. }
  366. logmsg("Connected fine to %s:%d", connectaddr, connectport);
  367. return sock;
  368. }
  369. static curl_socket_t socks4(curl_socket_t fd,
  370. unsigned char *buffer,
  371. ssize_t rc)
  372. {
  373. unsigned char response[256 + 16];
  374. curl_socket_t connfd;
  375. unsigned char cd;
  376. unsigned short s4port;
  377. if(buffer[SOCKS4_CD] != 1) {
  378. logmsg("SOCKS4 CD is not 1: %d", buffer[SOCKS4_CD]);
  379. return CURL_SOCKET_BAD;
  380. }
  381. if(rc < 9) {
  382. logmsg("SOCKS4 connect message too short: %d", rc);
  383. return CURL_SOCKET_BAD;
  384. }
  385. if(!config.port)
  386. s4port = (unsigned short)((buffer[SOCKS4_DSTPORT]<<8) |
  387. (buffer[SOCKS4_DSTPORT + 1]));
  388. else
  389. s4port = config.port;
  390. connfd = socksconnect(s4port, config.addr);
  391. if(connfd == CURL_SOCKET_BAD) {
  392. /* failed */
  393. cd = 91;
  394. }
  395. else {
  396. /* success */
  397. cd = 90;
  398. }
  399. response[0] = 0; /* reply version 0 */
  400. response[1] = cd; /* result */
  401. /* copy port and address from connect request */
  402. memcpy(&response[2], &buffer[SOCKS4_DSTPORT], 6);
  403. rc = (send)(fd, (char *)response, 8, 0);
  404. if(rc != 8) {
  405. logmsg("Sending SOCKS4 response failed!");
  406. return CURL_SOCKET_BAD;
  407. }
  408. logmsg("Sent %d bytes", rc);
  409. loghex(response, rc);
  410. if(cd == 90)
  411. /* now do the transfer */
  412. return connfd;
  413. if(connfd != CURL_SOCKET_BAD)
  414. sclose(connfd);
  415. return CURL_SOCKET_BAD;
  416. }
  417. static curl_socket_t sockit(curl_socket_t fd)
  418. {
  419. unsigned char buffer[256 + 16];
  420. unsigned char response[256 + 16];
  421. ssize_t rc;
  422. unsigned char len;
  423. unsigned char type;
  424. unsigned char rep = 0;
  425. unsigned char *address;
  426. unsigned short socksport;
  427. curl_socket_t connfd = CURL_SOCKET_BAD;
  428. unsigned short s5port;
  429. getconfig();
  430. rc = recv(fd, (char *)buffer, sizeof(buffer), 0);
  431. logmsg("READ %d bytes", rc);
  432. loghex(buffer, rc);
  433. if(buffer[SOCKS5_VERSION] == 4)
  434. return socks4(fd, buffer, rc);
  435. if(buffer[SOCKS5_VERSION] != config.version) {
  436. logmsg("VERSION byte not %d", config.version);
  437. return CURL_SOCKET_BAD;
  438. }
  439. if((buffer[SOCKS5_NMETHODS] < config.nmethods_min) ||
  440. (buffer[SOCKS5_NMETHODS] > config.nmethods_max)) {
  441. logmsg("NMETHODS byte not within %d - %d ",
  442. config.nmethods_min, config.nmethods_max);
  443. return CURL_SOCKET_BAD;
  444. }
  445. /* after NMETHODS follows that many bytes listing the methods the client
  446. says it supports */
  447. if(rc != (buffer[SOCKS5_NMETHODS] + 2)) {
  448. logmsg("Expected %d bytes, got %d", buffer[SOCKS5_NMETHODS] + 2, rc);
  449. return CURL_SOCKET_BAD;
  450. }
  451. logmsg("Incoming request deemed fine!");
  452. /* respond with two bytes: VERSION + METHOD */
  453. response[0] = config.responseversion;
  454. response[1] = config.responsemethod;
  455. rc = (send)(fd, (char *)response, 2, 0);
  456. if(rc != 2) {
  457. logmsg("Sending response failed!");
  458. return CURL_SOCKET_BAD;
  459. }
  460. logmsg("Sent %d bytes", rc);
  461. loghex(response, rc);
  462. /* expect the request or auth */
  463. rc = recv(fd, (char *)buffer, sizeof(buffer), 0);
  464. logmsg("READ %d bytes", rc);
  465. loghex(buffer, rc);
  466. if(config.responsemethod == 2) {
  467. /* RFC 1929 authentication
  468. +----+------+----------+------+----------+
  469. |VER | ULEN | UNAME | PLEN | PASSWD |
  470. +----+------+----------+------+----------+
  471. | 1 | 1 | 1 to 255 | 1 | 1 to 255 |
  472. +----+------+----------+------+----------+
  473. */
  474. unsigned char ulen;
  475. unsigned char plen;
  476. bool login = TRUE;
  477. if(rc < 5) {
  478. logmsg("Too short auth input: %d", rc);
  479. return CURL_SOCKET_BAD;
  480. }
  481. if(buffer[SOCKS5_VERSION] != 1) {
  482. logmsg("Auth VERSION byte not 1, got %d", buffer[SOCKS5_VERSION]);
  483. return CURL_SOCKET_BAD;
  484. }
  485. ulen = buffer[SOCKS5_ULEN];
  486. if(rc < 4 + ulen) {
  487. logmsg("Too short packet for username: %d", rc);
  488. return CURL_SOCKET_BAD;
  489. }
  490. plen = buffer[SOCKS5_ULEN + ulen + 1];
  491. if(rc < 3 + ulen + plen) {
  492. logmsg("Too short packet for ulen %d plen %d: %d", ulen, plen, rc);
  493. return CURL_SOCKET_BAD;
  494. }
  495. if((ulen != strlen(config.user)) ||
  496. (plen != strlen(config.password)) ||
  497. memcmp(&buffer[SOCKS5_UNAME], config.user, ulen) ||
  498. memcmp(&buffer[SOCKS5_UNAME + ulen + 1], config.password, plen)) {
  499. /* no match! */
  500. logmsg("mismatched credentials!");
  501. login = FALSE;
  502. }
  503. response[0] = 1;
  504. response[1] = login ? 0 : 1;
  505. rc = (send)(fd, (char *)response, 2, 0);
  506. if(rc != 2) {
  507. logmsg("Sending auth response failed!");
  508. return CURL_SOCKET_BAD;
  509. }
  510. logmsg("Sent %d bytes", rc);
  511. loghex(response, rc);
  512. if(!login)
  513. return CURL_SOCKET_BAD;
  514. /* expect the request */
  515. rc = recv(fd, (char *)buffer, sizeof(buffer), 0);
  516. logmsg("READ %d bytes", rc);
  517. loghex(buffer, rc);
  518. }
  519. if(rc < 6) {
  520. logmsg("Too short for request: %d", rc);
  521. return CURL_SOCKET_BAD;
  522. }
  523. if(buffer[SOCKS5_VERSION] != config.version) {
  524. logmsg("Request VERSION byte not %d", config.version);
  525. return CURL_SOCKET_BAD;
  526. }
  527. /* 1 == CONNECT */
  528. if(buffer[SOCKS5_REQCMD] != config.reqcmd) {
  529. logmsg("Request COMMAND byte not %d", config.reqcmd);
  530. return CURL_SOCKET_BAD;
  531. }
  532. /* reserved, should be zero */
  533. if(buffer[SOCKS5_RESERVED] != 0) {
  534. logmsg("Request COMMAND byte not %d", config.reqcmd);
  535. return CURL_SOCKET_BAD;
  536. }
  537. /* ATYP:
  538. o IP V4 address: X'01'
  539. o DOMAINNAME: X'03'
  540. o IP V6 address: X'04'
  541. */
  542. type = buffer[SOCKS5_ATYP];
  543. address = &buffer[SOCKS5_DSTADDR];
  544. switch(type) {
  545. case 1:
  546. /* 4 bytes IPv4 address */
  547. len = 4;
  548. break;
  549. case 3:
  550. /* The first octet of the address field contains the number of octets of
  551. name that follow */
  552. len = buffer[SOCKS5_DSTADDR];
  553. len++;
  554. break;
  555. case 4:
  556. /* 16 bytes IPv6 address */
  557. len = 16;
  558. break;
  559. default:
  560. logmsg("Unknown ATYP %d", type);
  561. return CURL_SOCKET_BAD;
  562. }
  563. if(rc < (4 + len + 2)) {
  564. logmsg("Request too short: %d, expected %d", rc, 4 + len + 2);
  565. return CURL_SOCKET_BAD;
  566. }
  567. if(!config.port) {
  568. unsigned char *portp = &buffer[SOCKS5_DSTADDR + len];
  569. s5port = (unsigned short)((portp[0]<<8) | (portp[1]));
  570. }
  571. else
  572. s5port = config.port;
  573. if(!config.connectrep)
  574. connfd = socksconnect(s5port, config.addr);
  575. if(connfd == CURL_SOCKET_BAD) {
  576. /* failed */
  577. rep = 1;
  578. }
  579. else {
  580. rep = config.connectrep;
  581. }
  582. /* */
  583. response[SOCKS5_VERSION] = config.responseversion;
  584. /*
  585. o REP Reply field:
  586. o X'00' succeeded
  587. o X'01' general SOCKS server failure
  588. o X'02' connection not allowed by ruleset
  589. o X'03' Network unreachable
  590. o X'04' Host unreachable
  591. o X'05' Connection refused
  592. o X'06' TTL expired
  593. o X'07' Command not supported
  594. o X'08' Address type not supported
  595. o X'09' to X'FF' unassigned
  596. */
  597. response[SOCKS5_REP] = rep;
  598. response[SOCKS5_RESERVED] = 0; /* must be zero */
  599. response[SOCKS5_ATYP] = type; /* address type */
  600. /* mirror back the original addr + port */
  601. /* address or hostname */
  602. memcpy(&response[SOCKS5_BNDADDR], address, len);
  603. /* port number */
  604. memcpy(&response[SOCKS5_BNDADDR + len],
  605. &buffer[SOCKS5_DSTADDR + len], sizeof(socksport));
  606. rc = (send)(fd, (char *)response, len + 6, 0);
  607. if(rc != (len + 6)) {
  608. logmsg("Sending connect response failed!");
  609. return CURL_SOCKET_BAD;
  610. }
  611. logmsg("Sent %d bytes", rc);
  612. loghex(response, rc);
  613. if(!rep)
  614. return connfd;
  615. if(connfd != CURL_SOCKET_BAD)
  616. sclose(connfd);
  617. return CURL_SOCKET_BAD;
  618. }
  619. struct perclient {
  620. size_t fromremote;
  621. size_t fromclient;
  622. curl_socket_t remotefd;
  623. curl_socket_t clientfd;
  624. bool used;
  625. };
  626. /* return non-zero when transfer is done */
  627. static int tunnel(struct perclient *cp, fd_set *fds)
  628. {
  629. ssize_t nread;
  630. ssize_t nwrite;
  631. char buffer[512];
  632. if(FD_ISSET(cp->clientfd, fds)) {
  633. /* read from client, send to remote */
  634. nread = recv(cp->clientfd, buffer, sizeof(buffer), 0);
  635. if(nread > 0) {
  636. nwrite = send(cp->remotefd, (char *)buffer,
  637. (SEND_TYPE_ARG3)nread, 0);
  638. if(nwrite != nread)
  639. return 1;
  640. cp->fromclient += nwrite;
  641. }
  642. else
  643. return 1;
  644. }
  645. if(FD_ISSET(cp->remotefd, fds)) {
  646. /* read from remote, send to client */
  647. nread = recv(cp->remotefd, buffer, sizeof(buffer), 0);
  648. if(nread > 0) {
  649. nwrite = send(cp->clientfd, (char *)buffer,
  650. (SEND_TYPE_ARG3)nread, 0);
  651. if(nwrite != nread)
  652. return 1;
  653. cp->fromremote += nwrite;
  654. }
  655. else
  656. return 1;
  657. }
  658. return 0;
  659. }
  660. /*
  661. sockfdp is a pointer to an established stream or CURL_SOCKET_BAD
  662. if sockfd is CURL_SOCKET_BAD, listendfd is a listening socket we must
  663. accept()
  664. */
  665. static bool incoming(curl_socket_t listenfd)
  666. {
  667. fd_set fds_read;
  668. fd_set fds_write;
  669. fd_set fds_err;
  670. int clients = 0; /* connected clients */
  671. struct perclient c[2];
  672. memset(c, 0, sizeof(c));
  673. if(got_exit_signal) {
  674. logmsg("signalled to die, exiting...");
  675. return FALSE;
  676. }
  677. #ifdef HAVE_GETPPID
  678. /* As a last resort, quit if socks5 process becomes orphan. */
  679. if(getppid() <= 1) {
  680. logmsg("process becomes orphan, exiting");
  681. return FALSE;
  682. }
  683. #endif
  684. do {
  685. int i;
  686. ssize_t rc;
  687. int error = 0;
  688. curl_socket_t sockfd = listenfd;
  689. int maxfd = (int)sockfd;
  690. FD_ZERO(&fds_read);
  691. FD_ZERO(&fds_write);
  692. FD_ZERO(&fds_err);
  693. /* there's always a socket to wait for */
  694. FD_SET(sockfd, &fds_read);
  695. for(i = 0; i < 2; i++) {
  696. if(c[i].used) {
  697. curl_socket_t fd = c[i].clientfd;
  698. FD_SET(fd, &fds_read);
  699. if((int)fd > maxfd)
  700. maxfd = (int)fd;
  701. fd = c[i].remotefd;
  702. FD_SET(fd, &fds_read);
  703. if((int)fd > maxfd)
  704. maxfd = (int)fd;
  705. }
  706. }
  707. do {
  708. /* select() blocking behavior call on blocking descriptors please */
  709. rc = select(maxfd + 1, &fds_read, &fds_write, &fds_err, NULL);
  710. if(got_exit_signal) {
  711. logmsg("signalled to die, exiting...");
  712. return FALSE;
  713. }
  714. } while((rc == -1) && ((error = errno) == EINTR));
  715. if(rc < 0) {
  716. logmsg("select() failed with error: (%d) %s",
  717. error, strerror(error));
  718. return FALSE;
  719. }
  720. if((clients < 2) && FD_ISSET(sockfd, &fds_read)) {
  721. curl_socket_t newfd = accept(sockfd, NULL, NULL);
  722. if(CURL_SOCKET_BAD == newfd) {
  723. error = SOCKERRNO;
  724. logmsg("accept(%d, NULL, NULL) failed with error: (%d) %s",
  725. sockfd, error, strerror(error));
  726. }
  727. else {
  728. curl_socket_t remotefd;
  729. logmsg("====> Client connect, fd %d. Read config from %s",
  730. newfd, configfile);
  731. remotefd = sockit(newfd); /* SOCKS until done */
  732. if(remotefd == CURL_SOCKET_BAD) {
  733. logmsg("====> Client disconnect");
  734. sclose(newfd);
  735. }
  736. else {
  737. struct perclient *cp = &c[0];
  738. logmsg("====> Tunnel transfer");
  739. if(c[0].used)
  740. cp = &c[1];
  741. cp->fromremote = 0;
  742. cp->fromclient = 0;
  743. cp->clientfd = newfd;
  744. cp->remotefd = remotefd;
  745. cp->used = TRUE;
  746. clients++;
  747. }
  748. }
  749. }
  750. for(i = 0; i < 2; i++) {
  751. struct perclient *cp = &c[i];
  752. if(cp->used) {
  753. if(tunnel(cp, &fds_read)) {
  754. logmsg("SOCKS transfer completed. Bytes: < %zu > %zu",
  755. cp->fromremote, cp->fromclient);
  756. sclose(cp->clientfd);
  757. sclose(cp->remotefd);
  758. cp->used = FALSE;
  759. clients--;
  760. }
  761. }
  762. }
  763. } while(clients);
  764. return TRUE;
  765. }
  766. static curl_socket_t sockdaemon(curl_socket_t sock,
  767. unsigned short *listenport)
  768. {
  769. /* passive daemon style */
  770. srvr_sockaddr_union_t listener;
  771. int flag;
  772. int rc;
  773. int totdelay = 0;
  774. int maxretr = 10;
  775. int delay = 20;
  776. int attempt = 0;
  777. int error = 0;
  778. do {
  779. attempt++;
  780. flag = 1;
  781. rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
  782. (void *)&flag, sizeof(flag));
  783. if(rc) {
  784. error = SOCKERRNO;
  785. logmsg("setsockopt(SO_REUSEADDR) failed with error: (%d) %s",
  786. error, strerror(error));
  787. if(maxretr) {
  788. rc = wait_ms(delay);
  789. if(rc) {
  790. /* should not happen */
  791. error = errno;
  792. logmsg("wait_ms() failed with error: (%d) %s",
  793. error, strerror(error));
  794. sclose(sock);
  795. return CURL_SOCKET_BAD;
  796. }
  797. if(got_exit_signal) {
  798. logmsg("signalled to die, exiting...");
  799. sclose(sock);
  800. return CURL_SOCKET_BAD;
  801. }
  802. totdelay += delay;
  803. delay *= 2; /* double the sleep for next attempt */
  804. }
  805. }
  806. } while(rc && maxretr--);
  807. if(rc) {
  808. logmsg("setsockopt(SO_REUSEADDR) failed %d times in %d ms. Error: (%d) %s",
  809. attempt, totdelay, error, strerror(error));
  810. logmsg("Continuing anyway...");
  811. }
  812. /* When the specified listener port is zero, it is actually a
  813. request to let the system choose a non-zero available port. */
  814. #ifdef ENABLE_IPV6
  815. if(!use_ipv6) {
  816. #endif
  817. memset(&listener.sa4, 0, sizeof(listener.sa4));
  818. listener.sa4.sin_family = AF_INET;
  819. listener.sa4.sin_addr.s_addr = INADDR_ANY;
  820. listener.sa4.sin_port = htons(*listenport);
  821. rc = bind(sock, &listener.sa, sizeof(listener.sa4));
  822. #ifdef ENABLE_IPV6
  823. }
  824. else {
  825. memset(&listener.sa6, 0, sizeof(listener.sa6));
  826. listener.sa6.sin6_family = AF_INET6;
  827. listener.sa6.sin6_addr = in6addr_any;
  828. listener.sa6.sin6_port = htons(*listenport);
  829. rc = bind(sock, &listener.sa, sizeof(listener.sa6));
  830. }
  831. #endif /* ENABLE_IPV6 */
  832. if(rc) {
  833. error = SOCKERRNO;
  834. logmsg("Error binding socket on port %hu: (%d) %s",
  835. *listenport, error, strerror(error));
  836. sclose(sock);
  837. return CURL_SOCKET_BAD;
  838. }
  839. if(!*listenport) {
  840. /* The system was supposed to choose a port number, figure out which
  841. port we actually got and update the listener port value with it. */
  842. curl_socklen_t la_size;
  843. srvr_sockaddr_union_t localaddr;
  844. #ifdef ENABLE_IPV6
  845. if(!use_ipv6)
  846. #endif
  847. la_size = sizeof(localaddr.sa4);
  848. #ifdef ENABLE_IPV6
  849. else
  850. la_size = sizeof(localaddr.sa6);
  851. #endif
  852. memset(&localaddr.sa, 0, (size_t)la_size);
  853. if(getsockname(sock, &localaddr.sa, &la_size) < 0) {
  854. error = SOCKERRNO;
  855. logmsg("getsockname() failed with error: (%d) %s",
  856. error, strerror(error));
  857. sclose(sock);
  858. return CURL_SOCKET_BAD;
  859. }
  860. switch(localaddr.sa.sa_family) {
  861. case AF_INET:
  862. *listenport = ntohs(localaddr.sa4.sin_port);
  863. break;
  864. #ifdef ENABLE_IPV6
  865. case AF_INET6:
  866. *listenport = ntohs(localaddr.sa6.sin6_port);
  867. break;
  868. #endif
  869. default:
  870. break;
  871. }
  872. if(!*listenport) {
  873. /* Real failure, listener port shall not be zero beyond this point. */
  874. logmsg("Apparently getsockname() succeeded, with listener port zero.");
  875. logmsg("A valid reason for this failure is a binary built without");
  876. logmsg("proper network library linkage. This might not be the only");
  877. logmsg("reason, but double check it before anything else.");
  878. sclose(sock);
  879. return CURL_SOCKET_BAD;
  880. }
  881. }
  882. /* start accepting connections */
  883. rc = listen(sock, 5);
  884. if(0 != rc) {
  885. error = SOCKERRNO;
  886. logmsg("listen(%d, 5) failed with error: (%d) %s",
  887. sock, error, strerror(error));
  888. sclose(sock);
  889. return CURL_SOCKET_BAD;
  890. }
  891. return sock;
  892. }
  893. int main(int argc, char *argv[])
  894. {
  895. curl_socket_t sock = CURL_SOCKET_BAD;
  896. curl_socket_t msgsock = CURL_SOCKET_BAD;
  897. int wrotepidfile = 0;
  898. const char *pidname = ".socksd.pid";
  899. bool juggle_again;
  900. int error;
  901. int arg = 1;
  902. while(argc>arg) {
  903. if(!strcmp("--version", argv[arg])) {
  904. printf("socksd IPv4%s\n",
  905. #ifdef ENABLE_IPV6
  906. "/IPv6"
  907. #else
  908. ""
  909. #endif
  910. );
  911. return 0;
  912. }
  913. else if(!strcmp("--pidfile", argv[arg])) {
  914. arg++;
  915. if(argc>arg)
  916. pidname = argv[arg++];
  917. }
  918. else if(!strcmp("--config", argv[arg])) {
  919. arg++;
  920. if(argc>arg)
  921. configfile = argv[arg++];
  922. }
  923. else if(!strcmp("--backend", argv[arg])) {
  924. arg++;
  925. if(argc>arg)
  926. backendaddr = argv[arg++];
  927. }
  928. else if(!strcmp("--backendport", argv[arg])) {
  929. arg++;
  930. if(argc>arg)
  931. backendport = (unsigned short)atoi(argv[arg++]);
  932. }
  933. else if(!strcmp("--logfile", argv[arg])) {
  934. arg++;
  935. if(argc>arg)
  936. serverlogfile = argv[arg++];
  937. }
  938. else if(!strcmp("--ipv6", argv[arg])) {
  939. #ifdef ENABLE_IPV6
  940. ipv_inuse = "IPv6";
  941. use_ipv6 = TRUE;
  942. #endif
  943. arg++;
  944. }
  945. else if(!strcmp("--ipv4", argv[arg])) {
  946. /* for completeness, we support this option as well */
  947. #ifdef ENABLE_IPV6
  948. ipv_inuse = "IPv4";
  949. use_ipv6 = FALSE;
  950. #endif
  951. arg++;
  952. }
  953. else if(!strcmp("--port", argv[arg])) {
  954. arg++;
  955. if(argc>arg) {
  956. char *endptr;
  957. unsigned long ulnum = strtoul(argv[arg], &endptr, 10);
  958. if((endptr != argv[arg] + strlen(argv[arg])) ||
  959. ((ulnum != 0UL) && ((ulnum < 1025UL) || (ulnum > 65535UL)))) {
  960. fprintf(stderr, "socksd: invalid --port argument (%s)\n",
  961. argv[arg]);
  962. return 0;
  963. }
  964. port = curlx_ultous(ulnum);
  965. arg++;
  966. }
  967. }
  968. else {
  969. puts("Usage: socksd [option]\n"
  970. " --backend [ipv4 addr]\n"
  971. " --backendport [TCP port]\n"
  972. " --config [file]\n"
  973. " --version\n"
  974. " --logfile [file]\n"
  975. " --pidfile [file]\n"
  976. " --ipv4\n"
  977. " --ipv6\n"
  978. " --bindonly\n"
  979. " --port [port]\n");
  980. return 0;
  981. }
  982. }
  983. #ifdef WIN32
  984. win32_init();
  985. atexit(win32_cleanup);
  986. setmode(fileno(stdin), O_BINARY);
  987. setmode(fileno(stdout), O_BINARY);
  988. setmode(fileno(stderr), O_BINARY);
  989. #endif
  990. install_signal_handlers();
  991. #ifdef ENABLE_IPV6
  992. if(!use_ipv6)
  993. #endif
  994. sock = socket(AF_INET, SOCK_STREAM, 0);
  995. #ifdef ENABLE_IPV6
  996. else
  997. sock = socket(AF_INET6, SOCK_STREAM, 0);
  998. #endif
  999. if(CURL_SOCKET_BAD == sock) {
  1000. error = SOCKERRNO;
  1001. logmsg("Error creating socket: (%d) %s",
  1002. error, strerror(error));
  1003. goto socks5_cleanup;
  1004. }
  1005. {
  1006. /* passive daemon style */
  1007. sock = sockdaemon(sock, &port);
  1008. if(CURL_SOCKET_BAD == sock) {
  1009. goto socks5_cleanup;
  1010. }
  1011. msgsock = CURL_SOCKET_BAD; /* no stream socket yet */
  1012. }
  1013. logmsg("Running %s version", ipv_inuse);
  1014. logmsg("Listening on port %hu", port);
  1015. wrotepidfile = write_pidfile(pidname);
  1016. if(!wrotepidfile) {
  1017. goto socks5_cleanup;
  1018. }
  1019. do {
  1020. juggle_again = incoming(sock);
  1021. } while(juggle_again);
  1022. socks5_cleanup:
  1023. if((msgsock != sock) && (msgsock != CURL_SOCKET_BAD))
  1024. sclose(msgsock);
  1025. if(sock != CURL_SOCKET_BAD)
  1026. sclose(sock);
  1027. if(wrotepidfile)
  1028. unlink(pidname);
  1029. restore_signal_handlers();
  1030. if(got_exit_signal) {
  1031. logmsg("============> socksd exits with signal (%d)", exit_signal);
  1032. /*
  1033. * To properly set the return status of the process we
  1034. * must raise the same signal SIGINT or SIGTERM that we
  1035. * caught and let the old handler take care of it.
  1036. */
  1037. raise(exit_signal);
  1038. }
  1039. logmsg("============> socksd quits");
  1040. return 0;
  1041. }