proxy.c 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120
  1. /*
  2. 3APA3A simpliest proxy server
  3. (c) 2002-2008 by ZARAZA <3APA3A@security.nnov.ru>
  4. please read License Agreement
  5. $Id: proxy.c,v 1.107 2014-04-07 20:35:07 vlad Exp $
  6. */
  7. #include "proxy.h"
  8. #define RETURN(xxx) { param->res = xxx; goto CLEANRET; }
  9. char * proxy_stringtable[] = {
  10. /* 0 */ "HTTP/1.0 400 Bad Request\r\n"
  11. "Proxy-Connection: close\r\n"
  12. "Content-type: text/html; charset=us-ascii\r\n"
  13. "\r\n"
  14. "<html><head><title>400 Bad Request</title></head>\r\n"
  15. "<body><h2>400 Bad Request</h2></body></html>\r\n",
  16. /* 1 */ "HTTP/1.0 502 Bad Gateway\r\n"
  17. "Proxy-Connection: close\r\n"
  18. "Content-type: text/html; charset=us-ascii\r\n"
  19. "\r\n"
  20. "<html><head><title>502 Bad Gateway</title></head>\r\n"
  21. "<body><h2>502 Bad Gateway</h2><h3>Host Not Found or connection failed</h3></body></html>\r\n",
  22. /* 2 */ "HTTP/1.0 503 Service Unavailable\r\n"
  23. "Proxy-Connection: close\r\n"
  24. "Content-type: text/html; charset=us-ascii\r\n"
  25. "\r\n"
  26. "<html><head><title>503 Service Unavailable</title></head>\r\n"
  27. "<body><h2>503 Service Unavailable</h2><h3>You have exceeded your traffic limit</h3></body></html>\r\n",
  28. /* 3 */ "HTTP/1.0 503 Service Unavailable\r\n"
  29. "Proxy-Connection: close\r\n"
  30. "Content-type: text/html; charset=us-ascii\r\n"
  31. "\r\n"
  32. "<html><head><title>503 Service Unavailable</title></head>\r\n"
  33. "<body><h2>503 Service Unavailable</h2><h3>Recursion detected</h3></body></html>\r\n",
  34. /* 4 */ "HTTP/1.0 501 Not Implemented\r\n"
  35. "Proxy-Connection: close\r\n"
  36. "Content-type: text/html; charset=us-ascii\r\n"
  37. "\r\n"
  38. "<html><head><title>501 Not Implemented</title></head>\r\n"
  39. "<body><h2>501 Not Implemented</h2><h3>Required action is not supported by proxy server</h3></body></html>\r\n",
  40. /* 5 */ "HTTP/1.0 502 Bad Gateway\r\n"
  41. "Proxy-Connection: close\r\n"
  42. "Content-type: text/html; charset=us-ascii\r\n"
  43. "\r\n"
  44. "<html><head><title>502 Bad Gateway</title></head>\r\n"
  45. "<body><h2>502 Bad Gateway</h2><h3>Failed to connect parent proxy</h3></body></html>\r\n",
  46. /* 6 */ "HTTP/1.0 500 Internal Error\r\n"
  47. "Proxy-Connection: close\r\n"
  48. "Content-type: text/html; charset=us-ascii\r\n"
  49. "\r\n"
  50. "<html><head><title>500 Internal Error</title></head>\r\n"
  51. "<body><h2>500 Internal Error</h2><h3>Internal proxy error during processing your request</h3></body></html>\r\n",
  52. /* 7 */ "HTTP/1.0 407 Proxy Authentication Required\r\n"
  53. "Proxy-Authenticate: Basic realm=\"proxy\"\r\n"
  54. "Proxy-Connection: close\r\n"
  55. "Content-type: text/html; charset=us-ascii\r\n"
  56. "\r\n"
  57. "<html><head><title>407 Proxy Authentication Required</title></head>\r\n"
  58. "<body><h2>407 Proxy Authentication Required</h2><h3>Access to requested resource disallowed by administrator or you need valid username/password to use this resource</h3></body></html>\r\n",
  59. /* 8 */ "HTTP/1.0 200 Connection established\r\n\r\n",
  60. /* 9 */ "HTTP/1.0 200 Connection established\r\n"
  61. "Content-Type: text/html\r\n\r\n",
  62. /* 10*/ "HTTP/1.0 404 Not Found\r\n"
  63. "Proxy-Connection: close\r\n"
  64. "Content-type: text/html; charset=us-ascii\r\n"
  65. "\r\n"
  66. "<html><head><title>404 Not Found</title></head>\r\n"
  67. "<body><h2>404 Not Found</h2><h3>File not found</body></html>\r\n",
  68. /* 11*/ "HTTP/1.0 403 Forbidden\r\n"
  69. "Proxy-Connection: close\r\n"
  70. "Content-type: text/html; charset=us-ascii\r\n"
  71. "\r\n"
  72. "<html><head><title>403 Access Denied</title></head>\r\n"
  73. "<body><h2>403 Access Denied</h2><h3>Access control list denies you to access this resource</body></html>\r\n",
  74. /* 12*/ "HTTP/1.0 407 Proxy Authentication Required\r\n"
  75. #ifndef NOCRYPT
  76. "Proxy-Authenticate: NTLM\r\n"
  77. #endif
  78. "Proxy-Authenticate: basic realm=\"proxy\"\r\n"
  79. "Proxy-Connection: close\r\n"
  80. "Content-type: text/html; charset=us-ascii\r\n"
  81. "\r\n"
  82. "<html><head><title>407 Proxy Authentication Required</title></head>\r\n"
  83. "<body><h2>407 Proxy Authentication Required</h2><h3>Access to requested resource disallowed by administrator or you need valid username/password to use this resource</h3></body></html>\r\n",
  84. /* 13*/ "HTTP/1.0 407 Proxy Authentication Required\r\n"
  85. "Proxy-Connection: keep-alive\r\n"
  86. "Content-Length: 0\r\n"
  87. "Proxy-Authenticate: NTLM ",
  88. /* 14*/ "HTTP/1.0 403 Forbidden\r\n"
  89. "Proxy-Connection: close\r\n"
  90. "Content-type: text/html; charset=us-ascii\r\n"
  91. "\r\n"
  92. "<pre>",
  93. /* 15*/ "HTTP/1.0 503 Service Unavailable\r\n"
  94. "Proxy-Connection: close\r\n"
  95. "Content-type: text/html; charset=us-ascii\r\n"
  96. "\r\n"
  97. "<html><head><title>503 Service Unavailable</title></head>\r\n"
  98. "<body><h2>503 Service Unavailable</h2><h3>Your request violates configured policy</h3></body></html>\r\n",
  99. /* 16*/ "HTTP/1.0 401 Authentication Required\r\n"
  100. "WWW-Authenticate: basic realm=\"FTP Server\"\r\n"
  101. "Proxy-Connection: close\r\n"
  102. "Content-type: text/html; charset=us-ascii\r\n"
  103. "\r\n"
  104. "<html><head><title>401 FTP Server requires authentication</title></head>\r\n"
  105. "<body><h2>401 FTP Server requires authentication</h2><h3>This FTP server rejects anonymous access</h3></body></html>\r\n",
  106. /* 17*/ "HTTP/1.1 100 Continue\r\n"
  107. "\r\n",
  108. NULL
  109. };
  110. #define LINESIZE 4096
  111. #define BUFSIZE (LINESIZE*2)
  112. static void logurl(struct clientparam * param, char * buf, char * req, int ftp){
  113. char *sb;
  114. char *se;
  115. int len;
  116. if(!buf) req = NULL;
  117. if(req) {
  118. len = (int)strlen(req);
  119. if(len > (LINESIZE - 1)) len = LINESIZE - 1;
  120. memcpy(buf, req, len + 1);
  121. buf[LINESIZE - 1] = 0;
  122. sb = strchr(buf, '\r');
  123. if(sb)*sb = 0;
  124. if(ftp && (se = strchr(buf + 10, ':')) && (sb = strchr(se, '@')) ) {
  125. strcpy(se, sb);
  126. }
  127. }
  128. if(param->res != 555)(*param->srv->logfunc)(param, (unsigned char *)(req?buf:NULL));
  129. }
  130. void decodeurl(unsigned char *s, int allowcr){
  131. unsigned char *d = s;
  132. unsigned u;
  133. while(*s){
  134. if(*s == '%' && ishex(s[1]) && ishex(s[2])){
  135. sscanf((char *)s+1, "%2x", &u);
  136. if(allowcr && u != '\r')*d++ = u;
  137. else if (u != '\r' && u != '\n') {
  138. if (u == '\"' || u == '\\') *d++ = '\\';
  139. else if (u == 255) *d++ = 255;
  140. *d++ = u;
  141. }
  142. s+=3;
  143. }
  144. else if(!allowcr && *s == '?') {
  145. break;
  146. }
  147. else if(*s == '+') {
  148. *d++ = ' ';
  149. s++;
  150. }
  151. else {
  152. *d++ = *s++;
  153. }
  154. }
  155. *d = 0;
  156. }
  157. void file2url(unsigned char *sb, unsigned char *buf, unsigned bufsize, int * inbuf, int skip255){
  158. for(; *sb; sb++){
  159. if((bufsize - *inbuf)<16)break;
  160. if(*sb=='\r'||*sb=='\n')continue;
  161. if(isallowed(*sb))buf[(*inbuf)++]=*sb;
  162. else if(*sb == '\"'){
  163. memcpy(buf+*inbuf, "%5C%22", 6);
  164. (*inbuf)+=6;
  165. }
  166. else if(skip255 && *sb == 255 && *(sb+1) == 255) {
  167. memcpy(buf+*inbuf, "%ff", 3);
  168. (*inbuf)+=3;
  169. sb++;
  170. }
  171. else {
  172. sprintf((char *)buf+*inbuf, "%%%.2x", (unsigned)*sb);
  173. (*inbuf)+=3;
  174. }
  175. }
  176. }
  177. void * proxychild(struct clientparam* param) {
  178. int res=0, i=0;
  179. unsigned char* buf = NULL, *newbuf;
  180. int inbuf;
  181. int bufsize;
  182. unsigned reqlen = 0;
  183. unsigned char *sb=NULL, *sg=NULL, *se=NULL, *sp=NULL,
  184. *req=NULL, *su=NULL, *ss = NULL;
  185. unsigned char *ftpbase=NULL;
  186. unsigned char username[1024];
  187. int keepalive = 0;
  188. unsigned long contentlength = 0;
  189. int hascontent =0;
  190. int isconnect = 0;
  191. int redirect = 0;
  192. int prefix = 0, ckeepalive=0;
  193. int ftp = 0;
  194. int anonymous;
  195. int sleeptime = 0;
  196. int reqsize, reqbufsize;
  197. int authenticate;
  198. struct pollfd fds[2];
  199. SOCKET ftps;
  200. SASIZETYPE sasize;
  201. #ifndef WITHMAIN
  202. FILTER_ACTION action;
  203. #endif
  204. if(!(buf = myalloc(BUFSIZE))) {RETURN(21);}
  205. bufsize = BUFSIZE;
  206. anonymous = param->srv->singlepacket;
  207. for(;;){
  208. memset(buf, 0, BUFSIZE);
  209. inbuf = 0;
  210. if(keepalive && (param->cliinbuf == param->clioffset) && (param->remsock != INVALID_SOCKET)){
  211. memset(fds, 0, sizeof(fds));
  212. fds[0].fd = param->clisock;
  213. fds[0].events = POLLIN;
  214. fds[1].fd = param->remsock;
  215. fds[1].events = POLLIN;
  216. res = so._poll(fds, 2, conf.timeouts[STRING_S]*1000);
  217. if(res<=0) {
  218. RETURN(555);
  219. }
  220. if((fds[1].revents & (POLLIN|POLLHUP|POLLERR|POLLNVAL))) {
  221. if(param->transparent || (!param->redirected && param->redirtype == R_HTTP)) RETURN(555);
  222. ckeepalive = 0;
  223. so._shutdown(param->remsock, SHUT_RDWR);
  224. so._closesocket(param->remsock);
  225. param->sins.sin_addr.s_addr = 0;
  226. param->sins.sin_port = 0;
  227. param->remsock = INVALID_SOCKET;
  228. param->redirected = 0;
  229. param->redirtype = 0;
  230. }
  231. }
  232. i = sockgetlinebuf(param, CLIENT, buf, LINESIZE - 1, '\n', conf.timeouts[STRING_L]);
  233. if(i<=0) {
  234. RETURN((keepalive)?555:(i)?507:508);
  235. }
  236. if (i==2 && buf[0]=='\r' && buf[1]=='\n') continue;
  237. buf[i] = 0;
  238. if(req) {
  239. if(!param->transparent && !param->srv->transparent && param->redirtype != R_HTTP && (i<=prefix || strncasecmp((char *)buf, (char *)req, prefix))){
  240. ckeepalive = 0;
  241. if(param->remsock != INVALID_SOCKET){
  242. so._shutdown(param->remsock, SHUT_RDWR);
  243. so._closesocket(param->remsock);
  244. }
  245. param->sins.sin_addr.s_addr = 0;
  246. param->sins.sin_port = 0;
  247. param->remsock = INVALID_SOCKET;
  248. param->redirected = 0;
  249. param->redirtype = 0;
  250. }
  251. myfree(req);
  252. }
  253. req = (unsigned char *)mystrdup((char *)buf);
  254. if(!req){RETURN(510);}
  255. if(i<10) {
  256. RETURN(511);
  257. }
  258. if(buf[i-3] == '1') keepalive = 2;
  259. if((isconnect = !strncasecmp((char *)buf, "CONNECT", 7))) keepalive = 2;
  260. if ((sb=(unsigned char *)(unsigned char *)strchr((char *)buf, ' ')) == NULL) {RETURN(512);}
  261. ss = ++sb;
  262. if(!isconnect) {
  263. if (!strncasecmp((char *)sb, "http://", 7)) {
  264. sb += 7;
  265. }
  266. else if (!strncasecmp((char *)sb, "ftp://", 6)) {
  267. ftp = 1;
  268. sb += 6;
  269. }
  270. else if(*sb == '/') {
  271. param->transparent = 1;
  272. }
  273. else {
  274. RETURN (513);
  275. }
  276. }
  277. else {
  278. if ((se=(unsigned char *)(unsigned char *)strchr((char *)sb, ' ')) == NULL || sb==se) {RETURN (514);}
  279. *se = 0;
  280. }
  281. if(!param->transparent || isconnect) {
  282. if(!isconnect) {
  283. if ((se=(unsigned char *)(unsigned char *)strchr((char *)sb, '/')) == NULL
  284. || sb==se
  285. || !(sg=(unsigned char *)strchr((char *)sb, ' '))) {RETURN (515);}
  286. if(se > sg) se=sg;
  287. *se = 0;
  288. }
  289. prefix = (int)(se - buf);
  290. su = (unsigned char*)strrchr((char *)sb, '@');
  291. if(su) {
  292. su = mystrdup(sb);
  293. decodeurl(su, 0);
  294. parseconnusername((char *)su, (struct clientparam *)param, 1, (unsigned short)((ftp)?21:80));
  295. myfree(su);
  296. }
  297. else parsehostname((char *)sb, (struct clientparam *)param, (unsigned short)((ftp)? 21:80));
  298. if(!isconnect){
  299. if(se==sg)*se-- = ' ';
  300. *se = '/';
  301. memmove(ss, se, i - (se - sb) + 1);
  302. }
  303. }
  304. reqlen = i = (int)strlen((char *)buf);
  305. if(!strncasecmp((char *)buf, "CONNECT", 7))param->operation = HTTP_CONNECT;
  306. else if(!strncasecmp((char *)buf, "GET", 3))param->operation = (ftp)?FTP_GET:HTTP_GET;
  307. else if(!strncasecmp((char *)buf, "PUT", 3))param->operation = (ftp)?FTP_PUT:HTTP_PUT;
  308. else if(!strncasecmp((char *)buf, "POST", 4)||!strncasecmp((char *)buf, "BITS_POST", 9))param->operation = HTTP_POST;
  309. else if(!strncasecmp((char *)buf, "HEAD", 4))param->operation = HTTP_HEAD;
  310. else param->operation = HTTP_OTHER;
  311. do {
  312. buf[inbuf+i]=0;
  313. /*printf("Got: %s\n", buf+inbuf);*/
  314. #ifndef WITHMAIN
  315. if(i > 25 && !param->srv->transparent && (!strncasecmp((char *)(buf+inbuf), "proxy-authorization", 19))){
  316. sb = (unsigned char *)strchr((char *)(buf+inbuf), ':');
  317. if(!sb)continue;
  318. ++sb;
  319. while(isspace(*sb))sb++;
  320. if(!*sb) continue;
  321. if(!strncasecmp((char *)sb, "basic", 5)){
  322. sb+=5;
  323. while(isspace(*sb))sb++;
  324. i = de64(sb, username, 255);
  325. if(i<=0)continue;
  326. username[i] = 0;
  327. sb = (unsigned char *)strchr((char *)username, ':');
  328. if(sb){
  329. *sb = 0;
  330. if(param->password)myfree(param->password);
  331. param->password = (unsigned char *)mystrdup((char *)sb+1);
  332. param->pwtype = 0;
  333. }
  334. if(param->username)myfree(param->username);
  335. param->username = (unsigned char *)mystrdup((char *)username);
  336. continue;
  337. }
  338. #ifndef NOCRYPT
  339. if(param->srv->usentlm && !strncasecmp((char *)sb, "ntlm", 4)){
  340. sb+=4;
  341. while(isspace(*sb))sb++;
  342. i = de64(sb, username, 1023);
  343. if(i<=16)continue;
  344. username[i] = 0;
  345. if(strncasecmp((char *)username, "NTLMSSP", 8)) continue;
  346. if(username[8] == 1) {
  347. while( (i = sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, '\n', conf.timeouts[STRING_S])) > 2){
  348. if(i> 15 && (!strncasecmp((char *)(buf), "content-length", 14))){
  349. buf[i]=0;
  350. sscanf((char *)buf + 15, "%lu", &contentlength);
  351. }
  352. }
  353. while( contentlength > 0 && (i = sockgetlinebuf(param, CLIENT, buf, (BUFSIZE < contentlength)? BUFSIZE - 1:contentlength, '\n', conf.timeouts[STRING_S])) > 0){
  354. if ((unsigned long)i > contentlength) break;
  355. contentlength-=i;
  356. }
  357. contentlength = 0;
  358. if(param->password)myfree(param->password);
  359. param->password = myalloc(32);
  360. param->pwtype = 2;
  361. i = (int)strlen(proxy_stringtable[13]);
  362. memcpy(buf, proxy_stringtable[13], i);
  363. genchallenge(param, (char *)param->password, (char *)buf + i);
  364. memcpy(buf + strlen((char *)buf), "\r\n\r\n", 5);
  365. socksend(param->clisock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]);
  366. ckeepalive = keepalive = 1;
  367. goto REQUESTEND;
  368. }
  369. if(username[8] == 3 && param->pwtype == 2 && i>=80) {
  370. unsigned offset, len;
  371. len = username[20] + (((unsigned)username[21]) << 8);
  372. offset = username[24] + (((unsigned)username[25]) << 8);
  373. if(len != 24 || len + offset > (unsigned)i) continue;
  374. memcpy(param->password + 8, username + offset, 24);
  375. len = username[36] + (((unsigned)username[37]) << 8);
  376. offset = username[40] + (((unsigned)username[41]) << 8);
  377. if(len> 255 || len + offset > (unsigned)i) continue;
  378. if(param->username) myfree(param->username);
  379. unicode2text((char *)username+offset, (char *)username+offset, (len>>1));
  380. param->username = (unsigned char *)mystrdup((char *)username+offset);
  381. }
  382. continue;
  383. }
  384. #endif
  385. }
  386. #endif
  387. if(!isconnect && (
  388. (i> 25 && !strncasecmp((char *)(buf+inbuf), "proxy-connection:", 17))
  389. ||
  390. (i> 16 && (!strncasecmp((char *)(buf+inbuf), "connection:", 11)))
  391. )){
  392. sb = (unsigned char *)strchr((char *)(buf+inbuf), ':');
  393. if(!sb)continue;
  394. ++sb;
  395. while(isspace(*sb))sb++;
  396. if(!strncasecmp((char *)sb,"keep-alive", 10))keepalive = 1;
  397. else keepalive = 0;
  398. continue;
  399. }
  400. if( i > 11 && !strncasecmp((char *)(buf+inbuf), "Expect: 100", 11)){
  401. keepalive = 1;
  402. socksend(param->clisock, (unsigned char *)proxy_stringtable[17], (int)strlen(proxy_stringtable[17]), conf.timeouts[STRING_S]);
  403. continue;
  404. }
  405. if(param->transparent && i > 6 && !strncasecmp((char *)buf + inbuf, "Host:", 5)){
  406. sb = (unsigned char *)strchr((char *)(buf+inbuf), ':');
  407. if(!sb)continue;
  408. ++sb;
  409. while(isspace(*sb))sb++;
  410. se = (unsigned char *)strchr((char *)sb, '\r');
  411. if(se) *se = 0;
  412. if(!param->hostname){
  413. parsehostname((char *)sb, param, 80);
  414. }
  415. newbuf = myalloc(strlen((char *)req) + strlen((char *)(buf+inbuf)) + 8);
  416. if(newbuf){
  417. sp = (unsigned char *)strchr((char *)req+1, '/');
  418. memcpy(newbuf, req, (sp - req));
  419. sprintf((char*)newbuf + (sp - req), "http://%s%s",sb,sp);
  420. myfree(req);
  421. req = newbuf;
  422. }
  423. if(se)*se = '\r';
  424. }
  425. if(ftp && i > 19 && (!strncasecmp((char *)(buf+inbuf), "authorization", 19))){
  426. sb = (unsigned char *)strchr((char *)(buf+inbuf), ':');
  427. if(!sb)continue;
  428. ++sb;
  429. while(isspace(*sb))sb++;
  430. if(!*sb) continue;
  431. if(!strncasecmp((char *)sb, "basic", 5)){
  432. sb+=5;
  433. while(isspace(*sb))sb++;
  434. i = de64(sb, username, 255);
  435. if(i<=0)continue;
  436. username[i] = 0;
  437. sb = (unsigned char *)strchr((char *)username, ':');
  438. if(sb){
  439. *sb = 0;
  440. if(param->extpassword)myfree(param->extpassword);
  441. param->extpassword = (unsigned char *)mystrdup((char *)sb+1);
  442. }
  443. if(param->extusername)myfree(param->extusername);
  444. param->extusername = (unsigned char *)mystrdup((char *)username);
  445. continue;
  446. }
  447. }
  448. if(i> 15 && (!strncasecmp((char *)(buf+inbuf), "content-length", 14))){
  449. sb = (unsigned char *)strchr((char *)(buf+inbuf), ':');
  450. if(!sb)continue;
  451. ++sb;
  452. while(isspace(*sb))sb++;
  453. sscanf(sb, "%lu",&contentlength);
  454. if(param->maxtrafout && (param->maxtrafout < param->statscli || (unsigned)contentlength > param->maxtrafout - param->statscli)){
  455. RETURN(10);
  456. }
  457. if(param->ndatfilterscli > 0 && contentlength > 0) continue;
  458. }
  459. inbuf += i;
  460. if((bufsize - inbuf) < LINESIZE){
  461. if (bufsize > 20000){
  462. RETURN (516);
  463. }
  464. if(!(newbuf = myrealloc(buf, bufsize + BUFSIZE))){RETURN (21);}
  465. buf = newbuf;
  466. bufsize += BUFSIZE;
  467. }
  468. } while( (i = sockgetlinebuf(param, CLIENT, buf + inbuf, LINESIZE - 2, '\n', conf.timeouts[STRING_S])) > 2);
  469. buf[inbuf] = 0;
  470. reqsize = (int)strlen(req);
  471. reqbufsize = reqsize + 1;
  472. #ifndef WITHMAIN
  473. action = handlereqfilters(param, &req, &reqbufsize, 0, &reqsize);
  474. if(action == HANDLED){
  475. RETURN(0);
  476. }
  477. if(action != PASS) RETURN(517);
  478. action = handlehdrfilterscli(param, &buf, &bufsize, 0, &inbuf);
  479. if(action == HANDLED){
  480. RETURN(0);
  481. }
  482. if(action != PASS) RETURN(517);
  483. if(param->ndatfilterscli > 0 && contentlength > 0){
  484. unsigned long newlen;
  485. newlen = sockfillbuffcli(param, contentlength, CONNECTION_S);
  486. if(newlen == contentlength) {
  487. action = handledatfltcli(param, &param->clibuf, &param->clibufsize, 0, &param->cliinbuf);
  488. if(action == HANDLED){
  489. RETURN(0);
  490. }
  491. if(action != PASS) RETURN(517);
  492. contentlength = param->cliinbuf;
  493. param->ndatfilterscli = 0;
  494. }
  495. sprintf((char*)buf+strlen((char *)buf), "Content-Length: %lu\r\n", contentlength);
  496. }
  497. #endif
  498. if((res = (*param->srv->authfunc)(param))) {RETURN(res);}
  499. if (param->sins.sin_addr.s_addr == param->srv->intip && param->sins.sin_port == param->srv->intport) {
  500. RETURN(519);
  501. }
  502. sasize = sizeof(struct sockaddr_in);
  503. if(so._getpeername(param->remsock, (struct sockaddr *)&param->sins, &sasize)){
  504. RETURN(520);
  505. }
  506. #define FTPBUFSIZE 1536
  507. if(ftp && param->redirtype != R_HTTP){
  508. SOCKET s;
  509. int mode = 0;
  510. int i=0;
  511. char ftpbuf[FTPBUFSIZE];
  512. int inftpbuf = 0;
  513. if(!ckeepalive){
  514. inftpbuf = FTPBUFSIZE - 20;
  515. res = ftplogin(param, ftpbuf, &inftpbuf);
  516. if(res){
  517. if (res == 700 || res == 701){
  518. socksend(param->clisock, (unsigned char *)proxy_stringtable[16], (int)strlen(proxy_stringtable[16]), conf.timeouts[STRING_S]);
  519. socksend(param->clisock, (unsigned char *)ftpbuf, inftpbuf, conf.timeouts[STRING_S]);
  520. }
  521. RETURN(res);
  522. }
  523. }
  524. ckeepalive = 1;
  525. if(ftpbase) myfree(ftpbase);
  526. ftpbase = NULL;
  527. if(!(sp = (unsigned char *)strchr((char *)ss, ' '))){RETURN(799);}
  528. *sp = 0;
  529. decodeurl(ss, 0);
  530. i = (int)strlen((char *)ss);
  531. if(!(ftpbase = myalloc(i+2))){RETURN(21);}
  532. memcpy(ftpbase, ss, i);
  533. if(ftpbase[i-1] != '/') ftpbase[i++] = '/';
  534. ftpbase[i] = 0;
  535. memcpy(buf, "<pre><hr>\n", 10);
  536. inbuf = 10;
  537. if(inftpbuf) {
  538. memcpy(buf+inbuf, ftpbuf, inftpbuf);
  539. inbuf += inftpbuf;
  540. memcpy(buf+inbuf, "<hr>", 4);
  541. inbuf += 4;
  542. }
  543. if(ftpbase[1] != 0){
  544. memcpy(buf+inbuf, "[<A HREF=\"..\">..</A>]\n", 22);
  545. inbuf += 22;
  546. }
  547. inftpbuf = FTPBUFSIZE - (20 + inftpbuf);
  548. res = ftpcd(param, ftpbase, ftpbuf, &inftpbuf);
  549. if(res){
  550. res = ftptype(param, (unsigned char *)"I");
  551. if(res)RETURN(res);
  552. ftpbase[--i] = 0;
  553. ftps = ftpcommand(param, param->operation == FTP_PUT? (unsigned char *)"PUT" : (unsigned char *)"RETR", ftpbase);
  554. }
  555. else {
  556. if(inftpbuf){
  557. memcpy(buf+inbuf, ftpbuf, inftpbuf);
  558. inbuf += inftpbuf;
  559. memcpy(buf+inbuf, "<hr>", 4);
  560. inbuf += 4;
  561. }
  562. ftps = ftpcommand(param, (unsigned char *)"LIST", NULL);
  563. mode = 1;
  564. }
  565. if(ftps == INVALID_SOCKET){RETURN(780);}
  566. if(!mode){
  567. socksend(param->clisock, (unsigned char *)proxy_stringtable[8], (int)strlen(proxy_stringtable[8]), conf.timeouts[STRING_S]);
  568. s = param->remsock;
  569. param->remsock = ftps;
  570. if((param->operation == FTP_PUT) && (contentlength > 0)) param->waitclient = contentlength;
  571. res = sockmap(param, conf.timeouts[CONNECTION_L]);
  572. if (res == 99) res = 0;
  573. so._closesocket(ftps);
  574. ftps = INVALID_SOCKET;
  575. param->remsock = s;
  576. }
  577. else {
  578. int headsent = 0;
  579. int gotres = -1;
  580. s = param->remsock;
  581. if(param->srvoffset < param->srvinbuf){
  582. gotres = ftpres(param, buf+inbuf, bufsize-(inbuf+100));
  583. if(gotres) inbuf= (int)strlen((char *)buf);
  584. }
  585. param->remsock = ftps;
  586. if(gotres <= 0) for(; (res = sockgetlinebuf(param, SERVER, (unsigned char *)ftpbuf, FTPBUFSIZE - 20, '\n', conf.timeouts[STRING_S])) > 0; i++){
  587. int isdir = 0;
  588. int islink = 0;
  589. int filetoken =-1;
  590. int sizetoken =-1;
  591. int modetoken =-1;
  592. int datetoken =-1;
  593. int spaces = 1;
  594. unsigned char * tokens[10];
  595. unsigned wordlen [10];
  596. unsigned char j=0;
  597. int space = 1;
  598. ftpbuf[res] = 0;
  599. if(!i && ftpbuf[0] == 't' && ftpbuf[1] == 'o' && ftpbuf[2] == 't'){
  600. mode = 2;
  601. continue;
  602. }
  603. if(!isnumber(*ftpbuf) && mode == 1) mode = 2;
  604. for(sb=(unsigned char *)ftpbuf; *sb; sb++){
  605. if(!space && isspace(*sb)){
  606. space = 1;
  607. wordlen[j]=(unsigned)(sb-tokens[j]);
  608. j++;
  609. }
  610. if(space && !isspace(*sb)){
  611. space = 0;
  612. tokens[j] = sb;
  613. if(j==8)break;
  614. }
  615. }
  616. if(mode == 1){
  617. if(j < 4) continue;
  618. if(!(isdir = !memcmp(tokens[2], "<DIR>", wordlen[2])) && !isnumber(*tokens[2])){
  619. continue;
  620. }
  621. datetoken = 0;
  622. wordlen[datetoken] = ((unsigned)(tokens[1] - tokens[0])) + wordlen[1];
  623. sizetoken = 2;
  624. filetoken = 3;
  625. spaces = 10;
  626. }
  627. else {
  628. if(j < 8 || wordlen[0]!=10) continue;
  629. if(j < 8 || !isnumber(*tokens[4])) mode = 3;
  630. if(*tokens[0] == 'd') isdir = 1;
  631. if(*tokens[0] == 'l') islink = 1;
  632. modetoken = 0;
  633. sizetoken = (mode == 2)? 4:3;
  634. filetoken = (mode == 2)? 8:7;
  635. datetoken = (mode == 2)? 5:4;
  636. tokens[filetoken] = tokens[filetoken-1];
  637. while(*tokens[filetoken] && !isspace(*tokens[filetoken]))tokens[filetoken]++;
  638. if(*tokens[filetoken]){
  639. tokens[filetoken]++;
  640. }
  641. wordlen[datetoken] = (unsigned)(tokens[filetoken] - tokens[datetoken]);
  642. wordlen[filetoken] = (unsigned)strlen((char *)tokens[filetoken]);
  643. }
  644. if(modetoken >= 0) memcpy(buf+inbuf, tokens[modetoken], 11);
  645. else memcpy(buf+inbuf, "---------- ", 11);
  646. inbuf += 11;
  647. if((int) wordlen[datetoken]+256 > bufsize-inbuf) continue;
  648. memcpy(buf+inbuf, tokens[datetoken], wordlen[datetoken]);
  649. inbuf += wordlen[datetoken];
  650. if(isdir){
  651. memcpy(buf+inbuf, " DIR", 10);
  652. inbuf+=10;
  653. }
  654. else if(islink){
  655. memcpy(buf+inbuf, " LINK", 10);
  656. inbuf+=10;
  657. }
  658. else{
  659. unsigned k;
  660. if(wordlen[sizetoken]>10) wordlen[sizetoken] = 10;
  661. for(k=10; k > wordlen[sizetoken]; k--){
  662. buf[inbuf++] = ' ';
  663. }
  664. memcpy(buf+inbuf, tokens[sizetoken], wordlen[sizetoken]);
  665. inbuf+=wordlen[sizetoken];
  666. }
  667. memcpy(buf+inbuf, " <A HREF=\"", 10);
  668. inbuf+=10;
  669. sb = NULL;
  670. if(islink) sb = (unsigned char *)strstr((char *)tokens[filetoken], " -> ");
  671. if(sb) sb+=4;
  672. else sb=tokens[filetoken];
  673. if(*sb != '/' && ftpbase)file2url(ftpbase, buf, bufsize, (int *)&inbuf, 1);
  674. file2url(sb, buf, bufsize, (int *)&inbuf, 0);
  675. if(isdir)buf[inbuf++] = '/';
  676. memcpy(buf+inbuf, "\">", 2);
  677. inbuf+=2;
  678. for(sb=tokens[filetoken]; *sb; sb++){
  679. if((bufsize - inbuf)<16)break;
  680. if(*sb == '<'){
  681. memcpy(buf+inbuf, "&lt;", 4);
  682. inbuf+=4;
  683. }
  684. else if(*sb == '>'){
  685. memcpy(buf+inbuf, "&gt;", 4);
  686. inbuf+=4;
  687. }
  688. else if(*sb == '\r' || *sb=='\n'){
  689. continue;
  690. }
  691. else if(islink && sb[0] == ' ' && sb[1] == '-'
  692. && sb[2] == '>'){
  693. memcpy(buf+inbuf, "</A> ", 5);
  694. inbuf+=5;
  695. }
  696. else buf[inbuf++]=*sb;
  697. }
  698. if(islink!=2){
  699. memcpy(buf+inbuf, "</A>", 4);
  700. inbuf+=4;
  701. }
  702. buf[inbuf++] = '\n';
  703. if((bufsize - inbuf) < LINESIZE){
  704. if (bufsize > 20000){
  705. if(!headsent++){
  706. socksend(param->clisock, (unsigned char *)proxy_stringtable[9], (int)strlen(proxy_stringtable[9]), conf.timeouts[STRING_S]);
  707. }
  708. if((unsigned)socksend(param->clisock, buf, inbuf, conf.timeouts[STRING_S]) != inbuf){
  709. RETURN(781);
  710. }
  711. inbuf = 0;
  712. }
  713. else {
  714. if(!(newbuf = myrealloc(buf, bufsize + BUFSIZE))){RETURN (21);}
  715. buf = newbuf;
  716. bufsize += BUFSIZE;
  717. }
  718. }
  719. }
  720. memcpy(buf+inbuf, "<hr>", 4);
  721. inbuf += 4;
  722. so._closesocket(ftps);
  723. ftps = INVALID_SOCKET;
  724. param->remsock = s;
  725. if(inbuf){
  726. buf[inbuf] = 0;
  727. if(gotres < 0 ) res = ftpres(param, buf+inbuf, bufsize-inbuf);
  728. else res = gotres;
  729. inbuf = (int)strlen((char *)buf);
  730. if(!headsent){
  731. sprintf(ftpbuf,
  732. "HTTP/1.0 200 OK\r\n"
  733. "Content-Type: text/html\r\n"
  734. "Proxy-Connection: keep-alive\r\n"
  735. "Content-Length: %d\r\n\r\n",
  736. inbuf);
  737. socksend(param->clisock, (unsigned char *)ftpbuf, (int)strlen(ftpbuf), conf.timeouts[STRING_S]);
  738. }
  739. socksend(param->clisock, buf, inbuf, conf.timeouts[STRING_S]);
  740. if(res){RETURN(res);}
  741. if(!headsent)goto REQUESTEND;
  742. }
  743. RETURN(0);
  744. }
  745. RETURN(res);
  746. }
  747. if(isconnect && param->redirtype != R_HTTP) {
  748. socksend(param->clisock, (unsigned char *)proxy_stringtable[8], (int)strlen(proxy_stringtable[8]), conf.timeouts[STRING_S]);
  749. if(param->redirectfunc) return (*param->redirectfunc)(param);
  750. param->res = sockmap(param, conf.timeouts[CONNECTION_L]);
  751. if(param->redirectfunc) return (*param->redirectfunc)(param);
  752. RETURN(param->res);
  753. }
  754. if(!req || param->redirtype != R_HTTP) {
  755. reqlen = 0;
  756. }
  757. else {
  758. redirect = 1;
  759. if(socksend(param->remsock, req , (res = (int)strlen((char *)req)), conf.timeouts[STRING_L]) != res) {
  760. RETURN(518);
  761. }
  762. param->statscli += res;
  763. param->nwrites++;
  764. }
  765. inbuf = 0;
  766. #ifndef ANONYMOUS
  767. if(anonymous!=1){
  768. sprintf((char*)buf+strlen((char *)buf), "Via: 1.1 ");
  769. gethostname((char *)(buf+strlen((char *)buf)), 256);
  770. sprintf((char*)buf+strlen((char *)buf), ":%d (%s %s)\r\nX-Forwarded-For: ", (int)ntohs(param->srv->intport), conf.stringtable?conf.stringtable[2]:(unsigned char *)"", conf.stringtable?conf.stringtable[3]:(unsigned char *)"");
  771. if(!anonymous)myinet_ntoa(param->sinc.sin_addr, (char *)buf + strlen((char *)buf));
  772. else {
  773. unsigned long tmp;
  774. tmp = param->sinc.sin_addr.s_addr;
  775. param->sinc.sin_addr.s_addr = ((unsigned long)myrand(param, sizeof(struct clientparam))<<16)^(unsigned long)rand();
  776. myinet_ntoa(param->sinc.sin_addr, (char *)buf + strlen((char *)buf));
  777. param->sinc.sin_addr.s_addr = tmp;
  778. }
  779. sprintf((char*)buf+strlen((char *)buf), "\r\n");
  780. }
  781. #endif
  782. if(keepalive <= 1) sprintf((char*)buf+strlen((char *)buf), "%s: %s\r\n", (param->redirtype == R_HTTP)?"Proxy-Connection":"Connection", keepalive? "keep-alive":"close");
  783. if(param->extusername){
  784. sprintf((char*)buf + strlen((char *)buf), "%s: basic ", (redirect)?"Proxy-Authorization":"Authorization");
  785. sprintf((char*)username, "%.32s:%.64s", param->extusername, param->extpassword?param->extpassword:(unsigned char*)"");
  786. en64(username, buf+strlen((char *)buf), (int)strlen((char *)username));
  787. sprintf((char*)buf + strlen((char *)buf), "\r\n");
  788. }
  789. sprintf((char*)buf+strlen((char *)buf), "\r\n");
  790. if ((res = socksend(param->remsock, buf+reqlen, (int)strlen((char *)buf+reqlen), conf.timeouts[STRING_S])) != (int)strlen((char *)buf+reqlen)) {
  791. RETURN(518);
  792. }
  793. param->statscli += res;
  794. param->nwrites++;
  795. if(param->bandlimfunc) {
  796. sleeptime = param->bandlimfunc(param, 0, (int)strlen((char *)buf));
  797. }
  798. if(contentlength > 0){
  799. param->nolongdatfilter = 0;
  800. param->waitclient = contentlength;
  801. res = sockmap(param, conf.timeouts[CONNECTION_S]);
  802. param->waitclient = 0;
  803. if(res != 99) {
  804. RETURN(res);
  805. }
  806. }
  807. contentlength = 0;
  808. inbuf = 0;
  809. ckeepalive = keepalive;
  810. res = 0;
  811. authenticate = 0;
  812. param->chunked = 0;
  813. hascontent = 0;
  814. while( (i = sockgetlinebuf(param, SERVER, buf + inbuf, LINESIZE - 1, '\n', conf.timeouts[(res)?STRING_S:STRING_L])) > 2) {
  815. if(!res && i>9)param->status = res = atoi((char *)buf + inbuf + 9);
  816. if(((i >= 25 && !strncasecmp((char *)(buf+inbuf), "proxy-connection:", 17))
  817. ||
  818. (i> 16 && !strncasecmp((char *)(buf+inbuf), "connection:", 11))
  819. )){
  820. sb = (unsigned char *)strchr((char *)(buf+inbuf), ':');
  821. if(!sb)continue;
  822. ++sb;
  823. while(isspace(*sb))sb++;
  824. if(strncasecmp((char *)sb,"keep-alive", 10))ckeepalive = 0;
  825. if(!param->srv->transparent)continue;
  826. }
  827. else if(i> 6 && !param->srv->transparent && (!strncasecmp((char *)(buf+inbuf), "proxy-", 6))){
  828. continue;
  829. }
  830. else if(i> 6 && (!strncasecmp((char *)(buf+inbuf), "www-authenticate", 16))){
  831. authenticate = 1;
  832. }
  833. else if(i > 15 && (!strncasecmp((char *)(buf+inbuf), "content-length", 14))){
  834. buf[inbuf+i]=0;
  835. sb = (unsigned char *)strchr((char *)(buf+inbuf), ':');
  836. if(!sb)continue;
  837. ++sb;
  838. while(isspace(*sb))sb++;
  839. sscanf(sb, "%lu", &contentlength);
  840. hascontent = 1;
  841. if(param->unsafefilter && param->ndatfilterssrv > 0) {
  842. hascontent = 2;
  843. continue;
  844. }
  845. if(param->maxtrafin && (param->maxtrafin < param->statssrv || (unsigned)contentlength > param->maxtrafin - param->statssrv)){
  846. RETURN(10);
  847. }
  848. }
  849. else if(i>25 && (!strncasecmp((char *)(buf+inbuf), "transfer-encoding", 17))){
  850. buf[inbuf+i]=0;
  851. sb = (unsigned char *)strchr((char *)(buf+inbuf), ':');
  852. if(!sb)continue;
  853. ++sb;
  854. while(isspace(*sb))sb++;
  855. if(!strncasecmp(sb, "chunked", 7)){
  856. param->chunked = 1;
  857. }
  858. }
  859. inbuf += i;
  860. if((bufsize - inbuf) < LINESIZE){
  861. if (bufsize > 20000){
  862. RETURN (516);
  863. }
  864. if(!(newbuf = myrealloc(buf, bufsize + BUFSIZE))){RETURN (21);}
  865. buf = newbuf;
  866. bufsize += BUFSIZE;
  867. }
  868. }
  869. if(res < 200 || res > 499) {
  870. ckeepalive = 0;
  871. }
  872. if((res == 304 || res == 204) && !hascontent){
  873. hascontent = 1;
  874. contentlength = 0;
  875. }
  876. if(param->bandlimfunc) {
  877. int st1;
  878. st1 = (*param->bandlimfunc)(param, inbuf, 0);
  879. if(st1 > sleeptime) sleeptime = st1;
  880. if(sleeptime > 0){
  881. /* if(sleeptime > 30) sleeptime = 30; */
  882. usleep(sleeptime * SLEEPTIME);
  883. }
  884. }
  885. buf[inbuf] = 0;
  886. if(inbuf < 9) {RETURN (522);}
  887. #ifndef WITHMAIN
  888. action = handlehdrfilterssrv(param, &buf, &bufsize, 0, &inbuf);
  889. if(action == HANDLED){
  890. RETURN(0);
  891. }
  892. if(action != PASS) RETURN(517);
  893. param->nolongdatfilter = 0;
  894. if (conf.filtermaxsize && contentlength > (unsigned long)conf.filtermaxsize) {
  895. param->nolongdatfilter = 1;
  896. }
  897. else if(param->unsafefilter && param->ndatfilterssrv > 0 && contentlength > 0 && param->operation != HTTP_HEAD && res != 204 && res != 304){
  898. unsigned long newlen;
  899. newlen = sockfillbuffsrv(param, (unsigned long) contentlength, CONNECTION_S);
  900. if(newlen == contentlength) {
  901. action = handledatfltsrv(param, &param->srvbuf, &param->srvbufsize, 0, &param->srvinbuf);
  902. param->nolongdatfilter = 1;
  903. if(action == HANDLED){
  904. RETURN(0);
  905. }
  906. if(action != PASS) RETURN(517);
  907. contentlength = param->srvinbuf;
  908. sprintf((char*)buf+strlen((char *)buf), "Content-Length: %lu\r\n", contentlength);
  909. hascontent = 1;
  910. }
  911. }
  912. if (contentlength > 0 && hascontent != 1) ckeepalive = 0;
  913. #else
  914. #endif
  915. if(!isconnect || param->operation){
  916. if(authenticate && !param->transparent) sprintf((char*)buf+strlen((char *)buf),
  917. "Proxy-support: Session-Based-Authentication\r\n"
  918. "Connection: Proxy-support\r\n"
  919. );
  920. if(!param->srv->transparent){
  921. if(ckeepalive <= 1) sprintf((char*)buf+strlen((char *)buf), "Connection: %s\r\n",
  922. (hascontent && ckeepalive)?"Keep-Alive":"Close");
  923. if(!param->transparent)sprintf((char*)buf+strlen((char *)buf), "Proxy-Connection: %s\r\n",
  924. (hascontent && ckeepalive)?"Keep-Alive":"Close");
  925. }
  926. sprintf((char*)buf + strlen((char *)buf), "\r\n");
  927. if((socksend(param->clisock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S])) != (int)strlen((char *)buf)) {
  928. RETURN(521);
  929. }
  930. }
  931. if((param->chunked || contentlength > 0) && param->operation != HTTP_HEAD && res != 204 && res != 304) {
  932. do {
  933. if(param->chunked){
  934. char smallbuf[32];
  935. while ((i = sockgetlinebuf(param, SERVER, smallbuf, 30, '\n', conf.timeouts[STRING_S])) == 2) {
  936. if (socksend(param->clisock, smallbuf, i, conf.timeouts[STRING_S]) != i){
  937. RETURN(533);
  938. }
  939. if(param->chunked == 2) break;
  940. }
  941. if(i<3) {
  942. keepalive = 0;
  943. break;
  944. }
  945. if (socksend(param->clisock, smallbuf, i, conf.timeouts[STRING_S]) != i){
  946. RETURN(535);
  947. }
  948. if(param->chunked == 2) {
  949. if((i = sockgetlinebuf(param, SERVER, smallbuf, 30, '\n', conf.timeouts[STRING_S])) != 2) RETURN(534);
  950. if (socksend(param->clisock, smallbuf, i, conf.timeouts[STRING_S]) != i){
  951. RETURN(533);
  952. }
  953. break;
  954. }
  955. smallbuf[i] = 0;
  956. contentlength = 0;
  957. sscanf(smallbuf, "%lx", &contentlength);
  958. if(contentlength == 0) {
  959. param->chunked = 2;
  960. }
  961. }
  962. if(param->chunked != 2){
  963. param->waitserver = contentlength;
  964. if((res = sockmap(param, conf.timeouts[CONNECTION_S])) != 98){
  965. RETURN(res);
  966. }
  967. param->waitserver = 0;
  968. }
  969. } while(param->chunked);
  970. }
  971. if(isconnect && res == 200 && param->operation){
  972. RETURN (sockmap(param, conf.timeouts[CONNECTION_S]));
  973. }
  974. else if(isconnect){
  975. ckeepalive = keepalive = 1;
  976. }
  977. else if(!hascontent && !param->chunked) {
  978. RETURN(sockmap(param, conf.timeouts[CONNECTION_S]));
  979. }
  980. contentlength = 0;
  981. REQUESTEND:
  982. if((!ckeepalive || !keepalive) && param->remsock != INVALID_SOCKET){
  983. so._shutdown(param->remsock, SHUT_RDWR);
  984. so._closesocket(param->remsock);
  985. param->remsock = INVALID_SOCKET;
  986. RETURN(0);
  987. }
  988. if(param->transparent && (!ckeepalive || !keepalive)) {RETURN (0);}
  989. logurl(param, buf, (char *)req, ftp);
  990. param->status = 0;
  991. }
  992. CLEANRET:
  993. if(param->res != 555 && param->res && param->clisock != INVALID_SOCKET && (param->res < 90 || param->res >=800 || param->res == 100 ||(param->res > 500 && param->res< 800))) {
  994. if((param->res>=509 && param->res < 517) || param->res > 900) while( (i = sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, '\n', conf.timeouts[STRING_S])) > 2);
  995. if(param->res == 10) {
  996. socksend(param->clisock, (unsigned char *)proxy_stringtable[2], (int)strlen(proxy_stringtable[2]), conf.timeouts[STRING_S]);
  997. }
  998. else if(param->res == 100 || (param->res >10 && param->res < 20) || (param->res >701 && param->res <= 705)) {
  999. socksend(param->clisock, (unsigned char *)proxy_stringtable[1], (int)strlen(proxy_stringtable[1]), conf.timeouts[STRING_S]);
  1000. }
  1001. else if(param->res >=20 && param->res < 30) {
  1002. socksend(param->clisock, (unsigned char *)proxy_stringtable[6], (int)strlen(proxy_stringtable[6]), conf.timeouts[STRING_S]);
  1003. }
  1004. else if(param->res >=30 && param->res < 80) {
  1005. socksend(param->clisock, (unsigned char *)proxy_stringtable[5], (int)strlen(proxy_stringtable[5]), conf.timeouts[STRING_S]);
  1006. }
  1007. else if(param->res == 1 || (param->srv->nouser && param->res < 10)) {
  1008. socksend(param->clisock, (unsigned char *)proxy_stringtable[11], (int)strlen(proxy_stringtable[11]), conf.timeouts[STRING_S]);
  1009. }
  1010. else if(param->res < 10) {
  1011. socksend(param->clisock, (unsigned char *)proxy_stringtable[param->srv->usentlm?12:7], (int)strlen(proxy_stringtable[param->srv->usentlm?12:7]), conf.timeouts[STRING_S]);
  1012. }
  1013. else if(param->res == 999) {
  1014. socksend(param->clisock, (unsigned char *)proxy_stringtable[4], (int)strlen(proxy_stringtable[4]), conf.timeouts[STRING_S]);
  1015. }
  1016. else if(param->res == 519) {
  1017. socksend(param->clisock, (unsigned char *)proxy_stringtable[3], (int)strlen(proxy_stringtable[3]), conf.timeouts[STRING_S]);
  1018. }
  1019. else if(param->res == 517) {
  1020. socksend(param->clisock, (unsigned char *)proxy_stringtable[15], (int)strlen(proxy_stringtable[15]), conf.timeouts[STRING_S]);
  1021. }
  1022. else if(param->res == 780) {
  1023. socksend(param->clisock, (unsigned char *)proxy_stringtable[10], (int)strlen(proxy_stringtable[10]), conf.timeouts[STRING_S]);
  1024. }
  1025. else if(param->res >= 511 && param->res<=516){
  1026. socksend(param->clisock, (unsigned char *)proxy_stringtable[0], (int)strlen(proxy_stringtable[0]), conf.timeouts[STRING_S]);
  1027. }
  1028. }
  1029. logurl(param, buf, (char *)req, ftp);
  1030. if(req)myfree(req);
  1031. if(buf)myfree(buf);
  1032. if(ftpbase)myfree(ftpbase);
  1033. freeparam(param);
  1034. return (NULL);
  1035. }
  1036. #ifdef WITHMAIN
  1037. struct proxydef childdef = {
  1038. proxychild,
  1039. 3128,
  1040. 0,
  1041. S_PROXY,
  1042. "-a - anonymous proxy\r\n"
  1043. "-a1 - anonymous proxy with random client IP spoofing\r\n"
  1044. };
  1045. #include "proxymain.c"
  1046. #endif