proxy.c 33 KB

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