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 *)&param->sinsl, &sasize)){return INVALID_SOCKET;}
193 	sasize = sizeof(param->sinsr);
194 	if(so._getpeername(param->remsock, (struct sockaddr *)&param->sinsr, &sasize)){return INVALID_SOCKET;}
195 	rem = param->remsock;
196 	param->remsock = INVALID_SOCKET;
197 	param->req = param->sinsr;
198 	*SAPORT(&param->req) = *SAPORT(&param->sinsr) = htons((unsigned short)((b5<<8)^b6));
199 	*SAPORT(&param->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(&param->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