ftp.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /*
  2. * Copyright (c) 2002-2008 3APA3A
  3. *
  4. * please read License Agreement
  5. *
  6. * $Id: ftp.c,v 1.34 2009/09/17 12:21:06 v.dubrovin Exp $
  7. */
  8. #include "proxy.h"
  9. int ftplogin(struct clientparam *param, char *nbuf, int *innbuf) {
  10. char tbuf[1024];
  11. int i;
  12. char *buf;
  13. int len;
  14. int res;
  15. buf = nbuf?nbuf:tbuf;
  16. len = nbuf?*innbuf:1024;
  17. if(innbuf)*innbuf = 0;
  18. if(len < 48) return 707;
  19. while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, len - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){
  20. }
  21. if(i < 3) return 706;
  22. buf[i] = 0;
  23. if(atoi(buf)/100 != 2) {
  24. *innbuf = i;
  25. return 702;
  26. }
  27. sprintf(buf, "USER %.32s\r\n", param->extusername?param->extusername:(unsigned char *)"anonymous");
  28. if((int)socksend(param->remsock, (unsigned char *)buf, (int)strlen(buf), conf.timeouts[STRING_S]) != (int)strlen(buf)){
  29. return 703;
  30. }
  31. param->statscli += (int)strlen(buf);
  32. param->nwrites++;
  33. while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, len - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){
  34. }
  35. if(i < 3) return 704;
  36. buf[i] = 0;
  37. res = atoi(buf)/100;
  38. if(res == 3){
  39. sprintf(buf, "PASS %.32s\r\n",
  40. param->extusername?
  41. (param->extpassword?
  42. param->extpassword:(unsigned char *)"")
  43. :(unsigned char *)"3proxy@");
  44. res = (int)strlen(buf);
  45. if((int)socksend(param->remsock, (unsigned char *)buf, res, conf.timeouts[STRING_S]) != (int)strlen(buf)){
  46. return 705;
  47. }
  48. param->statscli += res;
  49. param->nwrites++;
  50. while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, len - 1, '\n', conf.timeouts[STRING_L])) > 0){
  51. buf[i] = 0;
  52. res = (i>3 && buf[3] != '-')? atoi(buf)/100 : 0;
  53. if(res || (nbuf && (len-i) > 256 && i > 3)) {
  54. buf += i;
  55. len -= i;
  56. if(innbuf)*innbuf += i;
  57. }
  58. if(res) break;
  59. }
  60. if(i < 3) {
  61. return 701;
  62. }
  63. }
  64. if(res != 2) {
  65. return 700;
  66. }
  67. return 0;
  68. }
  69. int ftpcd(struct clientparam *param, unsigned char* path, char *nbuf, int *innbuf){
  70. char buf[1024];
  71. int i;
  72. int inbuf = 0;
  73. sprintf(buf, "CWD %.512s\r\n", path);
  74. if((int)socksend(param->remsock, (unsigned char *)buf, (int)strlen(buf), conf.timeouts[STRING_S]) != (int)strlen(buf)){
  75. return 711;
  76. }
  77. param->statscli += (int)strlen(buf);
  78. param->nwrites++;
  79. while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){
  80. if(nbuf && innbuf && inbuf + i < *innbuf && i > 6) {
  81. memcpy(nbuf + inbuf, buf, i);
  82. inbuf += i;
  83. }
  84. }
  85. if(innbuf)*innbuf = inbuf;
  86. if(i < 3) return 712;
  87. buf[3] = 0;
  88. if(buf[0] != '2') return 710;
  89. return 0;
  90. }
  91. int ftpres(struct clientparam *param, unsigned char * buf, int l){
  92. int i;
  93. if (l < 16) return 755;
  94. while((i = sockgetlinebuf(param, SERVER, buf, l - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){
  95. }
  96. buf[i] = 0;
  97. if(i < 3) return 751;
  98. if(buf[0] != '2' && buf[0] != '1') return 750;
  99. return 0;
  100. }
  101. int ftpsyst(struct clientparam *param, unsigned char *buf, unsigned len){
  102. int i;
  103. if(socksend(param->remsock, (unsigned char *)"SYST\r\n", 6, conf.timeouts[STRING_S]) != 6){
  104. return 721;
  105. }
  106. param->statscli+=6;
  107. param->nwrites++;
  108. while((i = sockgetlinebuf(param, SERVER, buf, len - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){
  109. }
  110. if(i < 7) return 722;
  111. buf[3] = 0;
  112. if(atoi((char *)buf)/100 != 2) return 723;
  113. buf[i-2] = 0;
  114. strcpy((char *)buf, (char *)buf+4);
  115. return 0;
  116. }
  117. int ftppwd(struct clientparam *param, unsigned char *buf, unsigned len){
  118. int i;
  119. char *b, *e;
  120. if(socksend(param->remsock, (unsigned char *)"PWD\r\n", 5, conf.timeouts[STRING_S]) != 5){
  121. return 731;
  122. }
  123. param->statscli += 5;
  124. param->nwrites++;
  125. while((i = sockgetlinebuf(param, SERVER, buf, len - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){
  126. }
  127. if(i < 7) return 732;
  128. buf[3] = 0;
  129. if(atoi((char *)buf)/100 != 2) return 733;
  130. buf[i-2] = 0;
  131. b = (char *)buf+4;
  132. if(*b == '\"' && (e = strchr(b+1, '\"'))){
  133. b++;
  134. *e = 0;
  135. }
  136. strcpy((char *)buf, b);
  137. return 0;
  138. }
  139. int ftptype(struct clientparam *param, unsigned char* f_type){
  140. char buf[1024];
  141. int i;
  142. sprintf(buf, "TYPE %.512s\r\n", f_type);
  143. if((int)socksend(param->remsock, (unsigned char *)buf, (int)strlen(buf), conf.timeouts[STRING_S]) != (int)strlen(buf)){
  144. return 741;
  145. }
  146. param->statscli += (int)strlen(buf);
  147. param->nwrites++;
  148. while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){
  149. }
  150. if(i < 3) return 742;
  151. if(buf[0] != '2') return 740;
  152. return 0;
  153. }
  154. SOCKET ftpdata(struct clientparam *param){
  155. char buf[1024];
  156. int i;
  157. char *sb, *se;
  158. SOCKET s = INVALID_SOCKET, rem;
  159. unsigned long b1, b2, b3, b4;
  160. unsigned short b5, b6;
  161. if(socksend(param->remsock, (unsigned char *)"PASV\r\n", 6, conf.timeouts[STRING_S]) != 6){
  162. return INVALID_SOCKET;
  163. }
  164. param->statscli+=6;
  165. param->nwrites++;
  166. while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){
  167. }
  168. if(i < 7) return INVALID_SOCKET;
  169. if(buf[0] != '2') return INVALID_SOCKET;
  170. buf[i-2] = 0;
  171. if(!(sb = strchr(buf+4, '(')) || !(se= strchr(sb, ')'))) return INVALID_SOCKET;
  172. if(sscanf(sb+1, "%lu,%lu,%lu,%lu,%hu,%hu", &b1, &b2, &b3, &b4, &b5, &b6)!=6) return INVALID_SOCKET;
  173. rem = param->remsock;
  174. param->remsock = INVALID_SOCKET;
  175. param->req.sin_family = AF_INET;
  176. param->req.sin_port = param->sins.sin_port = htons((unsigned short)((b5<<8)^b6));
  177. param->req.sin_addr.s_addr = param->sins.sin_addr.s_addr = htonl((b1<<24)^(b2<<16)^(b3<<8)^b4);
  178. i = param->operation;
  179. param->operation = FTP_DATA;
  180. if((param->res = (*param->srv->authfunc)(param))) return INVALID_SOCKET;
  181. param->operation = i;
  182. s = param->remsock;
  183. param->remsock = rem;
  184. return s;
  185. }
  186. SOCKET ftpcommand(struct clientparam *param, unsigned char * command, unsigned char *arg) {
  187. char buf[1024];
  188. int i;
  189. SOCKET s;
  190. s = ftpdata(param);
  191. if(s==INVALID_SOCKET) return INVALID_SOCKET;
  192. sprintf(buf, "%.15s%s%.512s\r\n", command, arg?
  193. (unsigned char *)" ":(unsigned char *)"",
  194. arg?arg:(unsigned char *)"");
  195. if((int)socksend(param->remsock, (unsigned char *)buf, (int)strlen(buf), conf.timeouts[STRING_S]) != (int)strlen(buf)){
  196. so._closesocket(s);
  197. return INVALID_SOCKET;
  198. }
  199. param->statscli += (int)strlen(buf);
  200. param->nwrites++;
  201. while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){
  202. }
  203. if(i < 3) {
  204. so._closesocket(s);
  205. return INVALID_SOCKET;
  206. }
  207. if(buf[0] != '1') {
  208. so._closesocket(s);
  209. return INVALID_SOCKET;
  210. }
  211. return s;
  212. }