ftp.c 7.1 KB

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