proxy.c 35 KB

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