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