1 |
|
|
2 |
/* Copyright (C) 1999 Beau Kuiper |
/* Copyright (C) 1999 Beau Kuiper |
3 |
|
|
4 |
This program is free software; you can redistribute it and/or modify |
This program is free software; you can redistribute it and/or modify |
23 |
|
|
24 |
/* This will print a NICE! error to the user */ |
/* This will print a NICE! error to the user */ |
25 |
|
|
26 |
void reporterror(FTPSTATE *peer, char *filename, int errorno) |
void reporterror(FTPSTATE * peer, |
27 |
|
char *filename, |
28 |
|
int errorno) |
29 |
{ |
{ |
30 |
ftp_write(peer, FALSE, 550, "'%s': %s", filename, strerror(errorno)); |
ftp_write(peer, FALSE, 550, "'%s': %s", filename, strerror(errorno)); |
31 |
} |
} |
32 |
|
|
33 |
int readipstr(char *data, int *port, unsigned int *ip) |
int readipstr(char *data, |
34 |
|
int *port, |
35 |
|
unsigned int *ip) |
36 |
{ |
{ |
37 |
int a1,a2,a3,a4,a5,a6, result; |
int a1, a2, a3, a4, a5, a6, result; |
38 |
|
|
39 |
result = sscanf(data, "%d,%d,%d,%d,%d,%d",&a1, &a2, &a3, &a4, &a5, &a6); |
result = sscanf(data, "%d,%d,%d,%d,%d,%d", &a1, &a2, &a3, &a4, &a5, &a6); |
40 |
if (result != 6) |
if (result != 6) |
41 |
return(FALSE); |
return (FALSE); |
42 |
|
|
43 |
*ip = (a1 << 24) | (a2 << 16) | (a3 << 8) | (a4); |
*ip = (a1 << 24) | (a2 << 16) | (a3 << 8) | (a4); |
44 |
*port = (a5 * 256) + a6; |
*port = (a5 * 256) + a6; |
45 |
return(TRUE); |
return (TRUE); |
46 |
} |
} |
47 |
|
|
48 |
int readeipstr(char *ip, unsigned int *outip) |
int readeipstr(char *ip, |
49 |
|
unsigned int *outip) |
50 |
{ |
{ |
51 |
int a1, a2, a3, a4, result; |
int a1, a2, a3, a4, result; |
52 |
|
|
53 |
result = sscanf(ip, "%d.%d.%d.%d", &a1, &a2, &a3, &a4); |
result = sscanf(ip, "%d.%d.%d.%d", &a1, &a2, &a3, &a4); |
54 |
if (result != 4) |
if (result != 4) |
55 |
return(FALSE); |
return (FALSE); |
56 |
|
|
57 |
*outip = (a1 << 24) | (a2 << 16) | (a3 << 8) | (a4); |
*outip = (a1 << 24) | (a2 << 16) | (a3 << 8) | (a4); |
58 |
return(TRUE); |
return (TRUE); |
59 |
} |
} |
60 |
|
|
61 |
int ftp_dele(FTPSTATE *peer, char *filename) |
int ftp_dele(FTPSTATE * peer, |
62 |
|
char *filename) |
63 |
{ |
{ |
64 |
if (file_unlink(peer, filename) == 0) |
if (file_unlink(peer, filename) == 0) |
65 |
ftp_write(peer, FALSE, 250, REPLY_DELETE(filename)); |
ftp_write(peer, FALSE, 250, REPLY_DELETE(filename)); |
66 |
else |
else |
67 |
reporterror(peer, filename, errno); |
reporterror(peer, filename, errno); |
68 |
|
|
69 |
return(FALSE); |
return (FALSE); |
70 |
} |
} |
71 |
|
|
72 |
int ftp_chmod(FTPSTATE *peer, char *filename, int mode) |
int ftp_chmod(FTPSTATE * peer, |
73 |
|
char *filename, |
74 |
|
int mode) |
75 |
{ |
{ |
76 |
if (file_chmod(peer, filename, mode) == 0) |
if (file_chmod(peer, filename, mode) == 0) |
77 |
ftp_write(peer, FALSE, 250, REPLY_CHMOD(filename, mode)); |
ftp_write(peer, FALSE, 250, REPLY_CHMOD(filename, mode)); |
78 |
else |
else |
79 |
reporterror(peer, filename, errno); |
reporterror(peer, filename, errno); |
80 |
|
|
81 |
return(FALSE); |
return (FALSE); |
82 |
} |
} |
83 |
|
|
84 |
int ftp_size(FTPSTATE *peer, char *filename) |
int ftp_size(FTPSTATE * peer, |
85 |
|
char *filename) |
86 |
{ |
{ |
87 |
int filefd; |
int filefd; |
88 |
off_t size = 0; |
off_t size = 0; |
89 |
int asize; |
int asize; |
90 |
struct stat statdata; |
struct stat statdata; |
91 |
|
|
92 |
if (peer->binary) |
if (peer->binary) |
93 |
{ |
{ |
94 |
filefd = file_stat(peer, filename, &statdata); |
filefd = file_stat(peer, filename, &statdata); |
95 |
if (filefd == 0) |
if (filefd == 0) |
96 |
size = statdata.st_size; |
size = statdata.st_size; |
97 |
} |
} |
98 |
else |
else |
99 |
{ |
{ |
100 |
char *rname; |
char *rname; |
101 |
|
|
102 |
size = 0; |
size = 0; |
103 |
filefd = file_readopen(peer, filename, &rname); |
filefd = file_readopen(peer, filename, &rname); |
104 |
freewrapper(rname); |
freewrapper(rname); |
105 |
|
|
106 |
if (filefd > 0) |
if (filefd > 0) |
107 |
{ |
{ |
108 |
char *chin, buffer[BUFFERSIZE]; |
char *chin, buffer[BUFFERSIZE]; |
109 |
|
|
110 |
asize = read(filefd, buffer, BUFFERSIZE-1); |
asize = read(filefd, buffer, BUFFERSIZE - 1); |
111 |
while (asize > 0) |
while (asize > 0) |
112 |
{ |
{ |
113 |
buffer[asize] = 0; |
buffer[asize] = 0; |
118 |
chin++; |
chin++; |
119 |
size++; |
size++; |
120 |
} |
} |
121 |
asize = read(filefd, buffer, BUFFERSIZE-1); |
asize = read(filefd, buffer, BUFFERSIZE - 1); |
122 |
} |
} |
123 |
close(filefd); |
close(filefd); |
124 |
} |
} |
125 |
} |
} |
126 |
|
|
127 |
if (filefd >= 0) |
if (filefd >= 0) |
128 |
ftp_write(peer, FALSE, 213, "%s", offt_tostr(size)); |
ftp_write(peer, FALSE, 213, "%s", offt_tostr(size)); |
129 |
else |
else |
130 |
reporterror(peer, filename, errno); |
reporterror(peer, filename, errno); |
131 |
|
|
132 |
return(FALSE); |
return (FALSE); |
133 |
} |
} |
134 |
|
|
135 |
int ftp_mdtm(FTPSTATE *peer, char *filename) |
int ftp_mdtm(FTPSTATE * peer, |
136 |
|
char *filename) |
137 |
{ |
{ |
138 |
struct stat statdata; |
struct stat statdata; |
139 |
|
|
140 |
if (file_stat(peer, filename, &statdata) == 0) |
if (file_stat(peer, filename, &statdata) == 0) |
141 |
{ |
{ |
142 |
char timestr[20]; |
char timestr[20]; |
143 |
struct tm *resulttm = gmtime(&statdata.st_mtime); |
struct tm *resulttm = gmtime(&statdata.st_mtime); |
144 |
|
|
145 |
strftime(timestr, 20, "%Y%m%d%H%M%S", resulttm); |
strftime(timestr, 20, "%Y%m%d%H%M%S", resulttm); |
146 |
|
|
147 |
ftp_write(peer, FALSE, 213, timestr); |
ftp_write(peer, FALSE, 213, timestr); |
148 |
} |
} |
149 |
else |
else |
150 |
reporterror(peer, filename, errno); |
reporterror(peer, filename, errno); |
151 |
|
|
152 |
return(FALSE); |
return (FALSE); |
153 |
} |
} |
154 |
|
|
155 |
void setdumptokens(FTPSTATE *peer, TOKENSET *ts) |
void setdumptokens(FTPSTATE * peer, |
156 |
|
TOKENSET * ts) |
157 |
{ |
{ |
158 |
char *outstr; |
char *outstr; |
159 |
time_t mytime = time(NULL); |
time_t mytime = time(NULL); |
160 |
|
|
161 |
outstr = ctime(&mytime); |
outstr = ctime(&mytime); |
162 |
outstr[strlen(outstr) - 1] = 0; |
outstr[strlen(outstr) - 1] = 0; |
163 |
tokenset_settoken(ts, 'T', strdupwrapper(outstr)); |
tokenset_settoken(ts, 'T', strdupwrapper(outstr)); |
164 |
tokenset_settoken(ts, 'U', strdupwrapper(peer->username)); |
tokenset_settoken(ts, 'U', strdupwrapper(peer->username)); |
165 |
if (peer->pwd) |
if (peer->pwd) |
166 |
tokenset_settoken(ts, 'C', strdupwrapper(dir_getvirtual(peer, peer->pwd))); |
tokenset_settoken(ts, 'C', |
167 |
|
strdupwrapper(dir_getvirtual(peer, peer->pwd))); |
168 |
tokenset_settoken(ts, 'E', strdupwrapper(peer->vserver->email)); |
tokenset_settoken(ts, 'E', strdupwrapper(peer->vserver->email)); |
169 |
tokenset_settoken(ts, 'M', safe_snprintf("%d", peer->maxusers)); |
tokenset_settoken(ts, 'M', safe_snprintf("%d", peer->maxusers)); |
170 |
if (peer->loggedin) |
if (peer->loggedin) |
173 |
tokenset_settoken(ts, 'L', strdupwrapper(peer->vserver->vhostname)); |
tokenset_settoken(ts, 'L', strdupwrapper(peer->vserver->vhostname)); |
174 |
tokenset_settoken(ts, 'f', safe_snprintf("%d", peer->downloadedfiles)); |
tokenset_settoken(ts, 'f', safe_snprintf("%d", peer->downloadedfiles)); |
175 |
tokenset_settoken(ts, 'F', safe_snprintf("%d", peer->uploadedfiles)); |
tokenset_settoken(ts, 'F', safe_snprintf("%d", peer->uploadedfiles)); |
176 |
tokenset_settoken(ts, 'b', safe_snprintf("%s", offt_tostr(peer->downloadedfilebytes))); |
tokenset_settoken(ts, 'b', |
177 |
tokenset_settoken(ts, 'B', safe_snprintf("%s", offt_tostr(peer->uploadedfilebytes))); |
safe_snprintf("%s", |
178 |
tokenset_settoken(ts, 'I', safe_snprintf("%s", offt_tostr(peer->listdownloadedbytes))); |
offt_tostr(peer->downloadedfilebytes))); |
179 |
|
tokenset_settoken(ts, 'B', |
180 |
|
safe_snprintf("%s", |
181 |
|
offt_tostr(peer->uploadedfilebytes))); |
182 |
|
tokenset_settoken(ts, 'I', |
183 |
|
safe_snprintf("%s", |
184 |
|
offt_tostr(peer->listdownloadedbytes))); |
185 |
tokenset_settoken(ts, 'i', safe_snprintf("%d", peer->listconns)); |
tokenset_settoken(ts, 'i', safe_snprintf("%d", peer->listconns)); |
186 |
tokenset_settoken(ts, 'D', safe_snprintf("%s", offt_tostr(peer->listdownloadedbytes + peer->downloadedfilebytes))); |
tokenset_settoken(ts, 'D', |
187 |
tokenset_settoken(ts, 't', safe_snprintf("%s", offt_tostr(peer->listdownloadedbytes + peer->downloadedfilebytes + peer->uploadedfilebytes))); |
safe_snprintf("%s", |
188 |
tokenset_settoken(ts, 'c', safe_snprintf("%d", peer->listconns + peer->downloadedfiles + peer->uploadedfiles)); |
offt_tostr(peer->listdownloadedbytes + |
189 |
tokenset_settoken(ts, 'd', safe_snprintf("%d", peer->listconns + peer->downloadedfiles)); |
peer->downloadedfilebytes))); |
190 |
|
tokenset_settoken(ts, 't', |
191 |
|
safe_snprintf("%s", |
192 |
|
offt_tostr(peer->listdownloadedbytes + |
193 |
|
peer->downloadedfilebytes + |
194 |
|
peer->uploadedfilebytes))); |
195 |
|
tokenset_settoken(ts, 'c', |
196 |
|
safe_snprintf("%d", |
197 |
|
peer->listconns + peer->downloadedfiles + |
198 |
|
peer->uploadedfiles)); |
199 |
|
tokenset_settoken(ts, 'd', |
200 |
|
safe_snprintf("%d", |
201 |
|
peer->listconns + peer->downloadedfiles)); |
202 |
if (peer->ratioinfo) |
if (peer->ratioinfo) |
203 |
ratio_settokens(peer->ratioinfo, ts); |
ratio_settokens(peer->ratioinfo, ts); |
204 |
tokenset_settoken(ts, 'v', strdupwrapper(peer->vserver->sectionname)); |
tokenset_settoken(ts, 'v', strdupwrapper(peer->vserver->sectionname)); |
205 |
} |
} |
206 |
|
|
207 |
int ftp_dumper(FTPSTATE *peer, NEWFILE *infile, int number, char *fmessage, int dotokens, int endtokens) |
int ftp_dumper(FTPSTATE * peer, |
208 |
|
NEWFILE * infile, |
209 |
|
int number, |
210 |
|
char *fmessage, |
211 |
|
int dotokens, |
212 |
|
int endtokens) |
213 |
{ |
{ |
214 |
TOKENSET *ts = NULL; |
TOKENSET *ts = NULL; |
215 |
char *inp, *tfmessage; |
char *inp, *tfmessage; |
221 |
ts = tokenset_new(); |
ts = tokenset_new(); |
222 |
setdumptokens(peer, ts); |
setdumptokens(peer, ts); |
223 |
} |
} |
224 |
|
|
225 |
if (infile != NULL) |
if (infile != NULL) |
226 |
{ |
{ |
227 |
first = TRUE; |
first = TRUE; |
228 |
while ((inp = nfgetcs(infile, '\n')) != NULL) |
while ((inp = nfgetcs(infile, '\n')) != NULL) |
229 |
{ |
{ |
230 |
if (inp[strlen(inp)-1] == '\n') |
if (inp[strlen(inp) - 1] == '\n') |
231 |
inp[strlen(inp)-1] = 0; |
inp[strlen(inp) - 1] = 0; |
232 |
|
|
233 |
if (dotokens) |
if (dotokens) |
234 |
inp = tokenset_apply(ts, inp, FALSE); |
inp = tokenset_apply(ts, inp, FALSE); |
235 |
|
|
236 |
if (first || config->altlongreplies) |
if (first || config->altlongreplies) |
237 |
{ |
{ |
238 |
ftp_write(peer, TRUE, 0, "%d-%s", number, inp); |
ftp_write(peer, TRUE, 0, "%d-%s", number, inp); |
243 |
|
|
244 |
freewrapper(inp); |
freewrapper(inp); |
245 |
} |
} |
246 |
|
|
247 |
nfclose(infile); |
nfclose(infile); |
248 |
} |
} |
249 |
|
|
250 |
if (endtokens) |
if (endtokens) |
251 |
{ |
{ |
252 |
tfmessage = tokenset_apply(ts, strdupwrapper(fmessage), FALSE); |
tfmessage = tokenset_apply(ts, strdupwrapper(fmessage), FALSE); |
255 |
} |
} |
256 |
else |
else |
257 |
ftp_write(peer, FALSE, number, "%s", fmessage); |
ftp_write(peer, FALSE, number, "%s", fmessage); |
258 |
|
|
259 |
if (ts) |
if (ts) |
260 |
tokenset_finish(ts); |
tokenset_finish(ts); |
261 |
|
|
262 |
return(FALSE); |
return (FALSE); |
263 |
} |
} |
264 |
|
|
265 |
int ftp_dumpstr(FTPSTATE *peer, char *dumpstr, int number, char *fmessage, int endtokens) |
int ftp_dumpstr(FTPSTATE * peer, |
266 |
|
char *dumpstr, |
267 |
|
int number, |
268 |
|
char *fmessage, |
269 |
|
int endtokens) |
270 |
{ |
{ |
271 |
TOKENSET *ts = NULL; |
TOKENSET *ts = NULL; |
272 |
char *oldinp = dumpstr; |
char *oldinp = dumpstr; |
276 |
|
|
277 |
ts = tokenset_new(); |
ts = tokenset_new(); |
278 |
setdumptokens(peer, ts); |
setdumptokens(peer, ts); |
279 |
|
|
280 |
first = TRUE; |
first = TRUE; |
281 |
while (oldinp != NULL) |
while (oldinp != NULL) |
282 |
{ |
{ |
283 |
inp = strchr(inp, '\n'); |
inp = strchr(inp, '\n'); |
284 |
if (inp != NULL) |
if (inp != NULL) |
285 |
*inp = 0; |
*inp = 0; |
286 |
|
|
287 |
datline = strdupwrapper(oldinp); |
datline = strdupwrapper(oldinp); |
288 |
if (inp != NULL) |
if (inp != NULL) |
289 |
{ |
{ |
292 |
} |
} |
293 |
oldinp = inp; |
oldinp = inp; |
294 |
datline = tokenset_apply(ts, datline, FALSE); |
datline = tokenset_apply(ts, datline, FALSE); |
295 |
|
|
296 |
if (first || config->altlongreplies) |
if (first || config->altlongreplies) |
297 |
{ |
{ |
298 |
ftp_write(peer, TRUE, 0, "%d-%s", number, datline); |
ftp_write(peer, TRUE, 0, "%d-%s", number, datline); |
303 |
freewrapper(datline); |
freewrapper(datline); |
304 |
|
|
305 |
} |
} |
306 |
|
|
307 |
if (endtokens) |
if (endtokens) |
308 |
{ |
{ |
309 |
tfmessage = tokenset_apply(ts, strdupwrapper(fmessage), FALSE); |
tfmessage = tokenset_apply(ts, strdupwrapper(fmessage), FALSE); |
313 |
else |
else |
314 |
ftp_write(peer, FALSE, number, "%s", fmessage); |
ftp_write(peer, FALSE, number, "%s", fmessage); |
315 |
|
|
316 |
tokenset_finish(ts); |
tokenset_finish(ts); |
317 |
return(FALSE); |
return (FALSE); |
318 |
} |
} |
319 |
|
|
320 |
VSERVER *find_vserver_byname(char *name) |
VSERVER *find_vserver_byname(char *name) |
321 |
{ |
{ |
322 |
VSERVER *v = config->vservers; |
VSERVER *v = config->vservers; |
323 |
|
|
324 |
while((v != NULL) && (strcasecmp(v->vhostname, name) != 0)) |
while ((v != NULL) && (strcasecmp(v->vhostname, name) != 0)) |
325 |
v = v->next; |
v = v->next; |
326 |
|
|
327 |
return(v); |
return (v); |
328 |
} |
} |
329 |
|
|
330 |
int host_isip(char *name) |
int host_isip(char *name) |
331 |
{ |
{ |
332 |
while(((*name >= '0') && (*name <= '9')) || (*name == '.')) |
while (((*name >= '0') && (*name <= '9')) || (*name == '.')) |
333 |
name++; |
name++; |
334 |
return(*name == 0); |
return (*name == 0); |
335 |
} |
} |
336 |
|
|
337 |
int ftp_host(FTPSTATE *peer, char *params) |
int ftp_host(FTPSTATE * peer, |
338 |
|
char *params) |
339 |
{ |
{ |
340 |
VSERVER *v; |
VSERVER *v; |
341 |
/* if there are no vservers, or hostname vservers are not defined, |
|
342 |
return with not implemented */ |
/* |
343 |
|
* if there are no vservers, or hostname vservers are not defined, |
344 |
|
* return with not implemented |
345 |
|
*/ |
346 |
if ((!config->vservers) || (!config->hostvservers)) |
if ((!config->vservers) || (!config->hostvservers)) |
347 |
return(ftp_write(peer, FALSE, 502, REPLY_NOHOSTS)); |
return (ftp_write(peer, FALSE, 502, REPLY_NOHOSTS)); |
348 |
|
|
349 |
/* if a vserver has already been selected, return 530 */ |
/* |
350 |
|
* if a vserver has already been selected, return 530 |
351 |
|
*/ |
352 |
if (peer->vserver != config->defaults) |
if (peer->vserver != config->defaults) |
353 |
return(ftp_write(peer, FALSE, 530, REPLY_HOSTSELECTED)); |
return (ftp_write(peer, FALSE, 530, REPLY_HOSTSELECTED)); |
354 |
|
|
355 |
if (config->defaulthost && (host_isip(params))) |
if (config->defaulthost && (host_isip(params))) |
356 |
v = config->defaulthost; |
v = config->defaulthost; |
357 |
else |
else |
358 |
v = find_vserver_byname(params); |
v = find_vserver_byname(params); |
359 |
|
|
360 |
if (!v) |
if (!v) |
361 |
return(ftp_write(peer, FALSE, 533, REPLY_HOSTNOTFOUND(params))); |
return (ftp_write(peer, FALSE, 533, REPLY_HOSTNOTFOUND(params))); |
362 |
|
|
363 |
switch(vserver_select(peer, v)) |
switch (vserver_select(peer, v)) |
364 |
{ |
{ |
365 |
case 1: |
case 1: |
366 |
return(ftp_write(peer, FALSE, 533, REPLY_HOSTMISCONF(params))); |
return (ftp_write(peer, FALSE, 533, REPLY_HOSTMISCONF(params))); |
367 |
case 2: |
case 2: |
368 |
return(ftp_write(peer, FALSE, 533, REPLY_HOSTNOTFOUND(params))); |
return (ftp_write(peer, FALSE, 533, REPLY_HOSTNOTFOUND(params))); |
369 |
case 3: |
case 3: |
370 |
ftp_write(peer, FALSE, 421, REPLY_HOSTTOOBUSY(params)); |
ftp_write(peer, FALSE, 421, REPLY_HOSTTOOBUSY(params)); |
371 |
return(TRUE); |
return (TRUE); |
372 |
} |
} |
373 |
|
|
374 |
ftp_write(peer, FALSE, 202, REPLY_HOSTSEL(v->vhostname)); |
ftp_write(peer, FALSE, 202, REPLY_HOSTSEL(v->vhostname)); |
375 |
|
|
376 |
return(3); |
return (3); |
377 |
} |
} |
378 |
|
|
379 |
int ftp_rnto(FTPSTATE *peer, char *filename) |
int ftp_rnto(FTPSTATE * peer, |
380 |
{ |
char *filename) |
381 |
|
{ |
382 |
char *badfile; |
char *badfile; |
383 |
char *oldname; |
char *oldname; |
384 |
|
|
385 |
if (!peer->renameoldname) |
if (!peer->renameoldname) |
386 |
return(ftp_write(peer, FALSE, 503, REPLY_RENAMENOSOURCE)); |
return (ftp_write(peer, FALSE, 503, REPLY_RENAMENOSOURCE)); |
387 |
|
|
388 |
oldname = dir_getvirtual(peer, peer->renameoldname); |
oldname = dir_getvirtual(peer, peer->renameoldname); |
389 |
|
|
390 |
if ((badfile = file_rename(peer, oldname, filename)) == NULL) |
if ((badfile = file_rename(peer, oldname, filename)) == NULL) |
391 |
ftp_write(peer, FALSE, 250, REPLY_RENAME(oldname, filename)); |
ftp_write(peer, FALSE, 250, REPLY_RENAME(oldname, filename)); |
392 |
else |
else |
393 |
reporterror(peer, badfile, errno); |
reporterror(peer, badfile, errno); |
394 |
|
|
395 |
freewrapper(peer->renameoldname); |
freewrapper(peer->renameoldname); |
396 |
peer->renameoldname = NULL; |
peer->renameoldname = NULL; |
397 |
|
|
398 |
return(FALSE); |
return (FALSE); |
399 |
} |
} |
400 |
|
|
401 |
int ftp_mkd(FTPSTATE *peer, char *filename) |
int ftp_mkd(FTPSTATE * peer, |
402 |
|
char *filename) |
403 |
{ |
{ |
404 |
if (file_mkdir(peer, filename) == 0) |
if (file_mkdir(peer, filename) == 0) |
405 |
{ |
{ |
406 |
char *newfile = file_expand(peer, filename); |
char *newfile = file_expand(peer, filename); |
407 |
ftp_write(peer, FALSE, 257, REPLY_MKDIR(dir_getvirtual(peer, newfile))); |
|
408 |
|
ftp_write(peer, FALSE, 257, |
409 |
|
REPLY_MKDIR(dir_getvirtual(peer, newfile))); |
410 |
freewrapper(newfile); |
freewrapper(newfile); |
411 |
} |
} |
412 |
else |
else |
413 |
reporterror(peer, filename, errno); |
reporterror(peer, filename, errno); |
414 |
|
|
415 |
return(FALSE); |
return (FALSE); |
416 |
} |
} |
417 |
|
|
418 |
int ftp_rmd(FTPSTATE *peer, char *filename) |
int ftp_rmd(FTPSTATE * peer, |
419 |
|
char *filename) |
420 |
{ |
{ |
421 |
if (file_rmdir(peer, filename) == 0) |
if (file_rmdir(peer, filename) == 0) |
422 |
ftp_write(peer, FALSE, 250, REPLY_RMDIR(filename)); |
ftp_write(peer, FALSE, 250, REPLY_RMDIR(filename)); |
423 |
else |
else |
424 |
reporterror(peer, filename, errno); |
reporterror(peer, filename, errno); |
425 |
|
|
426 |
return(FALSE); |
return (FALSE); |
427 |
} |
} |
428 |
|
|
429 |
int ftp_cwddo(FTPSTATE *peer, char *newdir, int dump) |
int ftp_cwddo(FTPSTATE * peer, |
430 |
|
char *newdir, |
431 |
|
int dump) |
432 |
{ |
{ |
433 |
char *tmp = strdupwrapper(peer->pwd); |
char *tmp = strdupwrapper(peer->pwd); |
434 |
|
|
435 |
dir_combine(peer, &tmp, newdir); |
dir_combine(peer, &tmp, newdir); |
436 |
|
|
437 |
if (!checkchdir(peer, tmp)) |
if (!checkchdir(peer, tmp)) |
438 |
{ |
{ |
439 |
freewrapper(tmp); |
freewrapper(tmp); |
440 |
reporterror(peer, newdir, errno); |
reporterror(peer, newdir, errno); |
441 |
return(FALSE); |
return (FALSE); |
442 |
} |
} |
443 |
chdir(tmp); |
chdir(tmp); |
444 |
|
|
445 |
if (peer->realdir) |
if (peer->realdir) |
446 |
{ |
{ |
447 |
char *nt; |
char *nt; |
448 |
/* this relies on the side effect of checkchdir where |
|
449 |
the server changes dir to check */ |
/* |
450 |
nt = (char *)dir_getreal(peer); |
* this relies on the side effect of checkchdir where |
451 |
|
* the server changes dir to check |
452 |
|
*/ |
453 |
|
nt = (char *) dir_getreal(peer); |
454 |
if (nt != NULL) |
if (nt != NULL) |
455 |
{ |
{ |
456 |
freewrapper(tmp); |
freewrapper(tmp); |
457 |
tmp = nt; |
tmp = nt; |
458 |
} |
} |
459 |
} |
} |
460 |
|
|
|
|
|
461 |
{ |
{ |
462 |
NEWFILE *nfile = NULL; |
NEWFILE *nfile = NULL; |
463 |
char *outstr; |
char *outstr; |
464 |
int ret = 257; |
int ret = 257; |
465 |
/* If we need to print a file, then open it */ |
|
466 |
/* Oh bugger, crap, and other things, I left a big |
/* |
467 |
security hole here! :-(, now fixed */ |
* If we need to print a file, then open it |
468 |
|
*/ |
469 |
|
/* |
470 |
|
* Oh bugger, crap, and other things, I left a big |
471 |
|
* security hole here! :-(, now fixed |
472 |
|
*/ |
473 |
if (dump) |
if (dump) |
474 |
ret = 250; |
ret = 250; |
475 |
freewrapper(peer->pwd); |
freewrapper(peer->pwd); |
477 |
if ((dump) && (peer->cwddump) && (!peer->cwddumpdata)) |
if ((dump) && (peer->cwddump) && (!peer->cwddumpdata)) |
478 |
{ |
{ |
479 |
if (peer->cwddump[0] == '/') |
if (peer->cwddump[0] == '/') |
480 |
/* if it is an absolute file, don't worry |
/* |
481 |
about permissions accessing file */ |
* if it is an absolute file, don't worry |
482 |
|
* about permissions accessing file |
483 |
|
*/ |
484 |
nfile = nfopen(peer->cwddump); |
nfile = nfopen(peer->cwddump); |
485 |
else |
else |
486 |
/* worry like hell and pass request via |
/* |
487 |
both ACL's and file permissions! */ |
* worry like hell and pass request via |
488 |
|
* both ACL's and file permissions! |
489 |
|
*/ |
490 |
nfile = file_nfopen(peer, peer->cwddump); |
nfile = file_nfopen(peer, peer->cwddump); |
491 |
} |
} |
492 |
outstr = safe_snprintf(REPLY_PWD(dir_getvirtual(peer, peer->pwd))); |
outstr = safe_snprintf(REPLY_PWD(dir_getvirtual(peer, peer->pwd))); |
493 |
|
|
494 |
if ((dump) && (peer->cwddumpdata)) |
if ((dump) && (peer->cwddumpdata)) |
495 |
ftp_dumpstr(peer, peer->cwddumpdata, ret, outstr, FALSE); |
ftp_dumpstr(peer, peer->cwddumpdata, ret, outstr, FALSE); |
496 |
else |
else |
497 |
ftp_dumper(peer, nfile, ret, outstr, TRUE, FALSE); |
ftp_dumper(peer, nfile, ret, outstr, TRUE, FALSE); |
498 |
freewrapper(outstr); |
freewrapper(outstr); |
499 |
} |
} |
500 |
|
|
501 |
return(FALSE); |
return (FALSE); |
502 |
} |
} |
503 |
|
|
504 |
int ftp_cwd(FTPSTATE *peer, char *newdir) |
int ftp_cwd(FTPSTATE * peer, |
505 |
|
char *newdir) |
506 |
{ |
{ |
507 |
return(ftp_cwddo(peer, newdir, TRUE)); |
return (ftp_cwddo(peer, newdir, TRUE)); |
508 |
} |
} |
509 |
|
|
510 |
int ftp_run(FTPSTATE *peer, INPUTLINE *cmd, char *token) |
int ftp_run(FTPSTATE * peer, |
511 |
|
INPUTLINE * cmd, |
512 |
|
char *token) |
513 |
{ |
{ |
514 |
if ((cmd->command->ftpfunc) == NULL) |
if ((cmd->command->ftpfunc) == NULL) |
515 |
return(ftp_write(peer, FALSE, 500, REPLY_CMDNOTKNOWN(token))); |
return (ftp_write(peer, FALSE, 500, REPLY_CMDNOTKNOWN(token))); |
516 |
|
|
517 |
if (cmd->command->paramnum) |
if (cmd->command->paramnum) |
518 |
{ |
{ |
519 |
if (cmd->parameters == NULL) |
if (cmd->parameters == NULL) |
520 |
return(ftp_write(peer, FALSE, 500, REPLY_NOPARAM(token))); |
return (ftp_write(peer, FALSE, 500, REPLY_NOPARAM(token))); |
521 |
else if (cmd->parameters[0] == 0) |
else if (cmd->parameters[0] == 0) |
522 |
return(ftp_write(peer, FALSE, 500, REPLY_NOPARAM(token))); |
return (ftp_write(peer, FALSE, 500, REPLY_NOPARAM(token))); |
523 |
} |
} |
524 |
|
|
525 |
if ((cmd->command->needslogin) && (peer->loggedin != TRUE)) |
if ((cmd->command->needslogin) && (peer->loggedin != TRUE)) |
526 |
return(ftp_write(peer, FALSE, 530, REPLY_NOLOGIN)); |
return (ftp_write(peer, FALSE, 530, REPLY_NOLOGIN)); |
527 |
|
|
528 |
if ((!cmd->command->dataportok) && (peer->dport)) |
if ((!cmd->command->dataportok) && (peer->dport)) |
529 |
return(ftp_write(peer, FALSE, 520, REPLY_DATACONNINVALID(token))); |
return (ftp_write(peer, FALSE, 520, REPLY_DATACONNINVALID(token))); |
530 |
else |
else |
531 |
return(cmd->command->ftpfunc(peer, cmd->parameters)); |
return (cmd->command->ftpfunc(peer, cmd->parameters)); |
532 |
} |
} |
533 |
|
|
534 |
int ftp_quit(FTPSTATE *peer, char *param) |
int ftp_quit(FTPSTATE * peer, |
535 |
|
char *param) |
536 |
{ |
{ |
537 |
if (peer->quitdump) |
if (peer->quitdump) |
538 |
{ |
{ |
539 |
NEWFILE *nfile = nfopen(peer->quitdump); |
NEWFILE *nfile = nfopen(peer->quitdump); |
540 |
|
|
541 |
ftp_dumper(peer, nfile, 221, REPLY_QUIT, TRUE, FALSE); |
ftp_dumper(peer, nfile, 221, REPLY_QUIT, TRUE, FALSE); |
542 |
} |
} |
543 |
else if (peer->quitdumpdata) |
else if (peer->quitdumpdata) |
544 |
ftp_dumpstr(peer, peer->quitdumpdata, 221, REPLY_QUIT, FALSE); |
ftp_dumpstr(peer, peer->quitdumpdata, 221, REPLY_QUIT, FALSE); |
545 |
else |
else |
546 |
ftp_write(peer, FALSE, 221, REPLY_QUIT); |
ftp_write(peer, FALSE, 221, REPLY_QUIT); |
547 |
return(TRUE); |
return (TRUE); |
548 |
} |
} |
549 |
|
|
550 |
int ftp_user(FTPSTATE *peer, char *param) |
int ftp_user(FTPSTATE * peer, |
551 |
|
char *param) |
552 |
{ |
{ |
553 |
if (peer->jailenabled) |
if (peer->jailenabled) |
554 |
return(ftp_write(peer, FALSE, 530, REPLY_JAILUSER)); |
return (ftp_write(peer, FALSE, 530, REPLY_JAILUSER)); |
555 |
if (peer->loginsleft == 0) |
if (peer->loginsleft == 0) |
556 |
return(ftp_write(peer, FALSE, 530, REPLY_NOCREDITS)); |
return (ftp_write(peer, FALSE, 530, REPLY_NOCREDITS)); |
557 |
if (peer->loggedin) |
if (peer->loggedin) |
558 |
shinfo_delusergroup(peer->groupname); |
shinfo_delusergroup(peer->groupname); |
559 |
|
|
560 |
shinfo_changeuser(param); |
shinfo_changeuser(param); |
561 |
peer->loggedin = 0; |
peer->loggedin = 0; |
562 |
|
|
563 |
freewrapper(peer->username); |
freewrapper(peer->username); |
564 |
peer->username = strdupwrapper(param); |
peer->username = strdupwrapper(param); |
565 |
|
|
566 |
return(ftp_write(peer, FALSE, 331, REPLY_USER(peer->username))); |
return (ftp_write(peer, FALSE, 331, REPLY_USER(peer->username))); |
567 |
} |
} |
568 |
|
|
569 |
int ftp_host_compat(FTPSTATE *peer) |
int ftp_host_compat(FTPSTATE * peer) |
570 |
{ |
{ |
571 |
VSERVER *v; |
VSERVER *v; |
572 |
char *name; |
char *name; |
573 |
/* if there are no vservers, or hostname vservers are not defined, |
|
574 |
return with not implemented */ |
/* |
575 |
|
* if there are no vservers, or hostname vservers are not defined, |
576 |
|
* return with not implemented |
577 |
|
*/ |
578 |
if ((!config->vservers) || (!config->hostvservers)) |
if ((!config->vservers) || (!config->hostvservers)) |
579 |
return(1); |
return (1); |
580 |
|
|
581 |
/* if a vserver has already been selected, return 530 */ |
/* |
582 |
|
* if a vserver has already been selected, return 530 |
583 |
|
*/ |
584 |
if (peer->vserver != config->defaults) |
if (peer->vserver != config->defaults) |
585 |
return(1); |
return (1); |
586 |
|
|
587 |
name = strchr(peer->username, '%'); |
name = strchr(peer->username, '%'); |
588 |
|
|
589 |
if (!name) |
if (!name) |
590 |
v = config->defaulthost; |
v = config->defaulthost; |
591 |
else |
else |
592 |
{ |
{ |
593 |
*name = 0; |
*name = 0; |
594 |
name++; |
name++; |
595 |
|
|
596 |
if (config->defaulthost && (host_isip(name))) |
if (config->defaulthost && (host_isip(name))) |
597 |
v = config->defaulthost; |
v = config->defaulthost; |
598 |
else |
else |
599 |
v = find_vserver_byname(name); |
v = find_vserver_byname(name); |
600 |
} |
} |
601 |
|
|
602 |
if (!v) |
if (!v) |
603 |
return(0); |
return (0); |
604 |
|
|
605 |
switch(vserver_select(peer, v)) |
switch (vserver_select(peer, v)) |
606 |
{ |
{ |
607 |
case 1: |
case 1: |
608 |
case 2: |
case 2: |
609 |
return(0); |
return (0); |
610 |
case 3: |
case 3: |
611 |
return(2); |
return (2); |
612 |
} |
} |
613 |
|
|
614 |
return(1); |
return (1); |
615 |
} |
} |
616 |
|
|
617 |
int ftp_pass(FTPSTATE *peer, char *param) |
int ftp_pass(FTPSTATE * peer, |
618 |
|
char *param) |
619 |
{ |
{ |
620 |
int result = FALSE; |
int result = FALSE; |
621 |
int loginok, oldnice = peer->nicevalue; |
int loginok, oldnice = peer->nicevalue; |
622 |
int toomany = FALSE; |
int toomany = FALSE; |
623 |
char *errmsg = NULL; |
char *errmsg = NULL; |
624 |
|
|
625 |
switch(ftp_host_compat(peer)) |
switch (ftp_host_compat(peer)) |
626 |
{ |
{ |
627 |
case 0: |
case 0: |
628 |
return(ftp_write(peer, FALSE, 530, REPLY_LOGINFAIL(peer->username, "Bad password"))); |
return (ftp_write |
629 |
case 2: |
(peer, FALSE, 530, |
630 |
ftp_write(peer, FALSE, 421, REPLY_TOOMANYUSERS); |
REPLY_LOGINFAIL(peer->username, "Bad password"))); |
631 |
return(TRUE); |
case 2: |
632 |
|
ftp_write(peer, FALSE, 421, REPLY_TOOMANYUSERS); |
633 |
|
return (TRUE); |
634 |
} |
} |
635 |
|
|
636 |
if (peer->loggedin) |
if (peer->loggedin) |
637 |
return(ftp_write(peer, FALSE, 530, REPLY_ALREADYLOGGEDIN)); |
return (ftp_write(peer, FALSE, 530, REPLY_ALREADYLOGGEDIN)); |
638 |
|
|
639 |
if (strcmp(peer->username, "<unknown>") == 0) |
if (strcmp(peer->username, "<unknown>") == 0) |
640 |
return(ftp_write(peer, FALSE, 503, REPLY_USEUSERFIRST)); |
return (ftp_write(peer, FALSE, 503, REPLY_USEUSERFIRST)); |
641 |
|
|
642 |
loginok = (param != NULL); |
loginok = (param != NULL); |
643 |
|
|
644 |
if (loginok) |
if (loginok) |
645 |
{ |
{ |
646 |
file_becomeroot(peer); |
file_becomeroot(peer); |
649 |
loginok = (errmsg == NULL); |
loginok = (errmsg == NULL); |
650 |
} |
} |
651 |
|
|
652 |
/* check some stuff, set basedir to real pathname */ |
/* |
653 |
|
* check some stuff, set basedir to real pathname |
654 |
|
*/ |
655 |
if (loginok) |
if (loginok) |
656 |
{ |
{ |
657 |
file_becomeuser(peer); |
file_becomeuser(peer); |
658 |
if (chdir(peer->basedir) == -1) |
if (chdir(peer->basedir) == -1) |
659 |
{ |
{ |
660 |
loginok = FALSE; |
loginok = FALSE; |
661 |
log_giveentry(MYLOG_INFO, NULL, safe_snprintf("rootdir(%s) for user '%s' is not accessable. Check rootdir and rootdir permissions", peer->basedir, peer->username)); |
log_giveentry(MYLOG_INFO, NULL, |
662 |
|
safe_snprintf |
663 |
|
("rootdir(%s) for user '%s' is not accessable. Check rootdir and rootdir permissions", |
664 |
|
peer->basedir, peer->username)); |
665 |
} |
} |
666 |
else |
else |
667 |
{ |
{ |
668 |
char *curdir = getcwd2(); |
char *curdir = getcwd2(); |
669 |
|
|
670 |
if (strcmp(curdir, peer->basedir) != 0) |
if (strcmp(curdir, peer->basedir) != 0) |
671 |
{ |
{ |
672 |
log_giveentry(MYLOG_INFO, NULL, safe_snprintf("rootdir changed from '%s' to '%s', symbolic links resolved for user '%s'", peer->basedir, curdir, peer->username)); |
log_giveentry(MYLOG_INFO, NULL, |
673 |
|
safe_snprintf |
674 |
|
("rootdir changed from '%s' to '%s', symbolic links resolved for user '%s'", |
675 |
|
peer->basedir, curdir, peer->username)); |
676 |
freewrapper(peer->basedir); |
freewrapper(peer->basedir); |
677 |
peer->basedir = curdir; |
peer->basedir = curdir; |
678 |
} |
} |
684 |
|
|
685 |
if (loginok) |
if (loginok) |
686 |
{ |
{ |
687 |
peer->usercount = toomany = shinfo_addusergroup(peer->groupname, peer->maxusers); |
peer->usercount = toomany = |
688 |
|
shinfo_addusergroup(peer->groupname, peer->maxusers); |
689 |
toomany = (toomany == -1); |
toomany = (toomany == -1); |
690 |
if (toomany) |
if (toomany) |
691 |
loginok = FALSE; |
loginok = FALSE; |
695 |
{ |
{ |
696 |
char *outstr; |
char *outstr; |
697 |
NEWFILE *nfile; |
NEWFILE *nfile; |
698 |
|
|
699 |
log_addentry(MYLOG_LOGIN, peer, "Login successful."); |
log_addentry(MYLOG_LOGIN, peer, "Login successful."); |
700 |
outstr = safe_snprintf(REPLY_PASSOK(peer->username)); |
outstr = safe_snprintf(REPLY_PASSOK(peer->username)); |
701 |
|
|
702 |
/* perform chroot if needed */ |
/* |
703 |
|
* perform chroot if needed |
704 |
|
*/ |
705 |
if (peer->chroot) |
if (peer->chroot) |
706 |
dochroot(peer); |
dochroot(peer); |
707 |
|
|
708 |
if (nice(peer->nicevalue + (-oldnice)) == -1) |
if (nice(peer->nicevalue + (-oldnice)) == -1) |
709 |
{ |
{ |
710 |
log_giveentry(MYLOG_INFO, NULL, safe_snprintf("nice(%d) gave error %s", peer->nicevalue + (-oldnice), strerror(errno))); |
log_giveentry(MYLOG_INFO, NULL, |
711 |
|
safe_snprintf("nice(%d) gave error %s", |
712 |
|
peer->nicevalue + (-oldnice), |
713 |
|
strerror(errno))); |
714 |
peer->nicevalue = oldnice; |
peer->nicevalue = oldnice; |
715 |
} |
} |
716 |
|
|
717 |
if (config->rootmode) |
if (config->rootmode) |
718 |
setgroups(peer->supgids[0], peer->supgids + 1); |
setgroups(peer->supgids[0], peer->supgids + 1); |
719 |
|
|
720 |
/* see if rootdir == "/", change to "" */ |
/* |
721 |
|
* see if rootdir == "/", change to "" |
722 |
|
*/ |
723 |
if (peer->basedir[1] == 0) |
if (peer->basedir[1] == 0) |
724 |
peer->basedir[0] = 0; |
peer->basedir[0] = 0; |
725 |
|
|
726 |
if ((peer->droproot) && (config->rootmode)) |
if ((peer->droproot) && (config->rootmode)) |
727 |
{ |
{ |
728 |
if (giveuproot(peer->uidt_asuid, peer->gidt_asgid)) |
if (giveuproot(peer->uidt_asuid, peer->gidt_asgid)) |
729 |
log_addentry(MYLOG_INFO, peer, "Failed to set capabilities!"); |
log_addentry(MYLOG_INFO, peer, "Failed to set capabilities!"); |
730 |
peer->jailenabled = TRUE; |
peer->jailenabled = TRUE; |
731 |
/* we are not root anymore and can never be root |
/* |
732 |
again! */ |
* we are not root anymore and can never be root |
733 |
|
* again! |
734 |
|
*/ |
735 |
config->rootmode = FALSE; |
config->rootmode = FALSE; |
736 |
} |
} |
737 |
|
|
738 |
file_becomeuser(peer); |
file_becomeuser(peer); |
739 |
|
|
740 |
nfile = nfopen(peer->logindump); |
nfile = nfopen(peer->logindump); |
741 |
peer->pwd = strdupwrapper(peer->basedir); |
peer->pwd = strdupwrapper(peer->basedir); |
742 |
dir_combine(peer, &(peer->pwd), peer->homedir); |
dir_combine(peer, &(peer->pwd), peer->homedir); |
743 |
|
|
744 |
if (peer->logindumpdata) |
if (peer->logindumpdata) |
745 |
result = ftp_dumpstr(peer, peer->logindumpdata, 230, outstr, FALSE); |
result = |
746 |
|
ftp_dumpstr(peer, peer->logindumpdata, 230, outstr, FALSE); |
747 |
else |
else |
748 |
result = ftp_dumper(peer, nfile, 230, outstr, TRUE, FALSE); |
result = ftp_dumper(peer, nfile, 230, outstr, TRUE, FALSE); |
749 |
freewrapper(outstr); |
freewrapper(outstr); |
756 |
if (toomany) |
if (toomany) |
757 |
{ |
{ |
758 |
NEWFILE *nfile = nfopen(peer->busydump); |
NEWFILE *nfile = nfopen(peer->busydump); |
759 |
|
|
760 |
logfullmessage(GROUPFULL, peer->remoteip); |
logfullmessage(GROUPFULL, peer->remoteip); |
761 |
if (peer->busydumpdata) |
if (peer->busydumpdata) |
762 |
ftp_dumpstr(peer, peer->busydumpdata, 421, REPLY_TOOMANYUSERS, FALSE); |
ftp_dumpstr(peer, peer->busydumpdata, 421, REPLY_TOOMANYUSERS, |
763 |
|
FALSE); |
764 |
else |
else |
765 |
ftp_dumper(peer, nfile, 421, REPLY_TOOMANYUSERS, TRUE, FALSE); |
ftp_dumper(peer, nfile, 421, REPLY_TOOMANYUSERS, TRUE, FALSE); |
766 |
} |
} |
769 |
usleep(peer->vserver->authwait); |
usleep(peer->vserver->authwait); |
770 |
if (errmsg == NULL) |
if (errmsg == NULL) |
771 |
errmsg = strdupwrapper("Bad password"); |
errmsg = strdupwrapper("Bad password"); |
772 |
result = ftp_write(peer, FALSE, 530, REPLY_LOGINFAIL(peer->username, errmsg)); |
result = |
773 |
|
ftp_write(peer, FALSE, 530, |
774 |
|
REPLY_LOGINFAIL(peer->username, errmsg)); |
775 |
if (peer->loginsleft > 0) |
if (peer->loginsleft > 0) |
776 |
peer->loginsleft--; |
peer->loginsleft--; |
777 |
freewrapper(errmsg); |
freewrapper(errmsg); |
780 |
peer->username = strdupwrapper("<unknown>"); |
peer->username = strdupwrapper("<unknown>"); |
781 |
} |
} |
782 |
if (toomany) |
if (toomany) |
783 |
return(TRUE); /* quit */ |
return (TRUE); /* quit */ |
784 |
return(3); /* make sure timeout gets updated */ |
return (3); /* make sure timeout gets updated */ |
785 |
} |
} |
786 |
|
|
787 |
int ftp_rest(FTPSTATE *peer, char *param) |
int ftp_rest(FTPSTATE * peer, |
788 |
|
char *param) |
789 |
{ |
{ |
790 |
off_t newpos; |
off_t newpos; |
791 |
int res; |
int res; |
792 |
|
|
793 |
res = strto_offt(param, &newpos); |
res = strto_offt(param, &newpos); |
794 |
|
|
795 |
if ((res != 0) || (newpos < 0)) |
if ((res != 0) || (newpos < 0)) |
796 |
return(ftp_write(peer, FALSE, 501, REPLY_INVALIDREST)); |
return (ftp_write(peer, FALSE, 501, REPLY_INVALIDREST)); |
797 |
else |
else |
798 |
{ |
{ |
799 |
peer->restartpos = newpos; |
peer->restartpos = newpos; |
800 |
return(ftp_write(peer, FALSE, 350, REPLY_RESTOK(peer->restartpos))); |
return (ftp_write(peer, FALSE, 350, REPLY_RESTOK(peer->restartpos))); |
801 |
} |
} |
802 |
} |
} |
803 |
|
|
804 |
int ftp_syst(FTPSTATE *peer, char *param) |
int ftp_syst(FTPSTATE * peer, |
805 |
|
char *param) |
806 |
{ |
{ |
807 |
return(ftp_write(peer, FALSE, 215, "UNIX Type: L8")); |
return (ftp_write(peer, FALSE, 215, "UNIX Type: L8")); |
808 |
} |
} |
809 |
|
|
810 |
int ftp_port(FTPSTATE *peer, char *param) |
int ftp_port(FTPSTATE * peer, |
811 |
|
char *param) |
812 |
{ |
{ |
813 |
if (peer->epsv_forced) |
if (peer->epsv_forced) |
814 |
return(ftp_write(peer, FALSE, 500, REPLY_EPSVSET)); |
return (ftp_write(peer, FALSE, 500, REPLY_EPSVSET)); |
815 |
|
|
816 |
/* reset remoteport */ |
/* |
817 |
|
* reset remoteport |
818 |
|
*/ |
819 |
peer->remoteport = 0; |
peer->remoteport = 0; |
820 |
if (peer->passiveport) |
if (peer->passiveport) |
821 |
{ |
{ |
828 |
if ((peer->remoteport <= 1024) || (peer->remoteport >= 65536)) |
if ((peer->remoteport <= 1024) || (peer->remoteport >= 65536)) |
829 |
{ |
{ |
830 |
peer->remoteport = 0; |
peer->remoteport = 0; |
831 |
return(ftp_write(peer, FALSE, 500, REPLY_PORTBADPORT)); |
return (ftp_write(peer, FALSE, 500, REPLY_PORTBADPORT)); |
832 |
} |
} |
833 |
if ((peer->dataip != peer->remoteip) && (!peer->fxpallow)) |
if ((peer->dataip != peer->remoteip) && (!peer->fxpallow)) |
834 |
{ |
{ |
835 |
peer->remoteport = 0; |
peer->remoteport = 0; |
836 |
peer->dataip = peer->remoteip; |
peer->dataip = peer->remoteip; |
837 |
return(ftp_write(peer, FALSE, 500, REPLY_PORTBADFXP)); |
return (ftp_write(peer, FALSE, 500, REPLY_PORTBADFXP)); |
838 |
} |
} |
839 |
return(ftp_write(peer, FALSE, 200, REPLY_PORTOK( |
return (ftp_write |
840 |
peer->dataip >> 24, peer->dataip >> 16 & 255, peer->dataip >> 8 & 255, |
(peer, FALSE, 200, |
841 |
peer->dataip & 255, peer->remoteport))); |
REPLY_PORTOK(peer->dataip >> 24, peer->dataip >> 16 & 255, |
842 |
|
peer->dataip >> 8 & 255, peer->dataip & 255, |
843 |
|
peer->remoteport))); |
844 |
} |
} |
845 |
else |
else |
846 |
return(ftp_write(peer, FALSE, 501, REPLY_PORTBADPARM)); |
return (ftp_write(peer, FALSE, 501, REPLY_PORTBADPARM)); |
847 |
} |
} |
848 |
|
|
849 |
int ftp_eprt(FTPSTATE *peer, char *param) |
int ftp_eprt(FTPSTATE * peer, |
850 |
|
char *param) |
851 |
{ |
{ |
852 |
char *ipstr; |
char *ipstr; |
853 |
int proto, tcpport; |
int proto, tcpport; |
854 |
unsigned int remote_ip; |
unsigned int remote_ip; |
855 |
|
|
856 |
if (peer->epsv_forced) |
if (peer->epsv_forced) |
857 |
return(ftp_write(peer, FALSE, 500, REPLY_EPSVSET)); |
return (ftp_write(peer, FALSE, 500, REPLY_EPSVSET)); |
858 |
|
|
859 |
ipstr = mallocwrapper(strlen(param) + 1); |
ipstr = mallocwrapper(strlen(param) + 1); |
860 |
|
|
861 |
/* clear off old ports */ |
/* |
862 |
|
* clear off old ports |
863 |
|
*/ |
864 |
peer->remoteport = 0; |
peer->remoteport = 0; |
865 |
if (peer->passiveport) |
if (peer->passiveport) |
866 |
{ |
{ |
880 |
ftp_write(peer, FALSE, 500, REPLY_EPRTBADFXP); |
ftp_write(peer, FALSE, 500, REPLY_EPRTBADFXP); |
881 |
else |
else |
882 |
{ |
{ |
883 |
/* everything seems to be ok */ |
/* |
884 |
|
* everything seems to be ok |
885 |
|
*/ |
886 |
peer->remoteport = tcpport; |
peer->remoteport = tcpport; |
887 |
peer->dataip = remote_ip; |
peer->dataip = remote_ip; |
888 |
ftp_write(peer, FALSE, 200, REPLY_EPRTOK( |
ftp_write(peer, FALSE, 200, |
889 |
peer->dataip >> 24, peer->dataip >> 16 & 255, peer->dataip >> 8 & 255, |
REPLY_EPRTOK(peer->dataip >> 24, peer->dataip >> 16 & 255, |
890 |
peer->dataip & 255, peer->remoteport)); |
peer->dataip >> 8 & 255, peer->dataip & 255, |
891 |
|
peer->remoteport)); |
892 |
} |
} |
893 |
freewrapper(ipstr); |
freewrapper(ipstr); |
894 |
return(FALSE); |
return (FALSE); |
895 |
} |
} |
896 |
|
|
897 |
int ftp_pwd(FTPSTATE *peer, char *param) |
int ftp_pwd(FTPSTATE * peer, |
898 |
|
char *param) |
899 |
{ |
{ |
900 |
return(ftp_cwddo(peer, ".", FALSE)); |
return (ftp_cwddo(peer, ".", FALSE)); |
901 |
} |
} |
902 |
|
|
903 |
int ftp_type(FTPSTATE *peer, char *param) |
int ftp_type(FTPSTATE * peer, |
904 |
|
char *param) |
905 |
{ |
{ |
906 |
if ((param[0] & (255-32)) == 'A') |
if ((param[0] & (255 - 32)) == 'A') |
907 |
{ |
{ |
908 |
peer->binary = FALSE; |
peer->binary = FALSE; |
909 |
return(ftp_write(peer, FALSE, 200, REPLY_TYPEASCII)); |
return (ftp_write(peer, FALSE, 200, REPLY_TYPEASCII)); |
910 |
} |
} |
911 |
else if ((param[0] & (255-32)) == 'I') |
else if ((param[0] & (255 - 32)) == 'I') |
912 |
{ |
{ |
913 |
peer->binary = TRUE; |
peer->binary = TRUE; |
914 |
return(ftp_write(peer, FALSE, 200, REPLY_TYPEBINARY)); |
return (ftp_write(peer, FALSE, 200, REPLY_TYPEBINARY)); |
915 |
} |
} |
916 |
else |
else |
917 |
return(ftp_write(peer, FALSE, 504, REPLY_TYPEUNIMP)); |
return (ftp_write(peer, FALSE, 504, REPLY_TYPEUNIMP)); |
918 |
} |
} |
919 |
|
|
920 |
int ftp_abor(FTPSTATE *peer, char *param) |
int ftp_abor(FTPSTATE * peer, |
921 |
|
char *param) |
922 |
{ |
{ |
923 |
/* abort any active or pending data port */ |
/* |
924 |
|
* abort any active or pending data port |
925 |
|
*/ |
926 |
abortdatasocket(peer); |
abortdatasocket(peer); |
927 |
return(ftp_write(peer, FALSE, 226, REPLY_ABORT)); |
return (ftp_write(peer, FALSE, 226, REPLY_ABORT)); |
928 |
} |
} |
929 |
|
|
930 |
int ftp_pasv(FTPSTATE *peer, char *param) |
int ftp_pasv(FTPSTATE * peer, |
931 |
|
char *param) |
932 |
{ |
{ |
933 |
unsigned int a1, a2, a3, a4, a5, a6; |
unsigned int a1, a2, a3, a4, a5, a6; |
934 |
|
|
935 |
if (peer->epsv_forced) |
if (peer->epsv_forced) |
936 |
return(ftp_write(peer, FALSE, 500, REPLY_EPSVSET)); |
return (ftp_write(peer, FALSE, 500, REPLY_EPSVSET)); |
937 |
|
|
938 |
if (peer->passiveport != 0) |
if (peer->passiveport != 0) |
939 |
select_delfd(peer->sel, peer->passiveport); |
select_delfd(peer->sel, peer->passiveport); |
940 |
|
|
941 |
peer->remoteport = 0; |
peer->remoteport = 0; |
942 |
|
|
943 |
peer->passiveport = listenparrelelport(peer->remotefd, &(peer->remoteport), &a1, 5); |
peer->passiveport = |
944 |
|
listenparrelelport(peer->remotefd, &(peer->remoteport), &a1, 5); |
945 |
|
|
946 |
if (peer->passiveport == -1) |
if (peer->passiveport == -1) |
947 |
{ |
{ |
948 |
peer->passiveport = 0; |
peer->passiveport = 0; |
949 |
reporterror(peer, "passive port", errno); |
reporterror(peer, "passive port", errno); |
950 |
return(FALSE); |
return (FALSE); |
951 |
} |
} |
952 |
select_addfd(peer->sel, peer->passiveport); |
select_addfd(peer->sel, peer->passiveport); |
953 |
a2 = ((a1 >> 8) & 255); |
a2 = ((a1 >> 8) & 255); |
956 |
a1 = a1 & 255; |
a1 = a1 & 255; |
957 |
a5 = (peer->remoteport >> 8); |
a5 = (peer->remoteport >> 8); |
958 |
a6 = (peer->remoteport & 255); |
a6 = (peer->remoteport & 255); |
959 |
return(ftp_write(peer, FALSE, 227, REPLY_PASV(a4, a3, a2, a1, a5, a6))); |
return (ftp_write(peer, FALSE, 227, REPLY_PASV(a4, a3, a2, a1, a5, a6))); |
960 |
} |
} |
961 |
|
|
962 |
int ftp_epsv(FTPSTATE *peer, char *param) |
int ftp_epsv(FTPSTATE * peer, |
963 |
|
char *param) |
964 |
{ |
{ |
965 |
int proto, a1; |
int proto, a1; |
966 |
|
|
967 |
/* the all parameter means that only epsv can be used from now on */ |
/* |
968 |
|
* the all parameter means that only epsv can be used from now on |
969 |
|
*/ |
970 |
|
|
971 |
if (peer->passiveport != 0) |
if (peer->passiveport != 0) |
972 |
select_delfd(peer->sel, peer->passiveport); |
select_delfd(peer->sel, peer->passiveport); |
973 |
|
|
974 |
peer->remoteport = 0; |
peer->remoteport = 0; |
975 |
peer->passiveport = 0; |
peer->passiveport = 0; |
976 |
|
|
977 |
if (param) |
if (param) |
978 |
{ |
{ |
979 |
if (strcasecmp(param, "ALL") == 0) |
if (strcasecmp(param, "ALL") == 0) |
980 |
{ |
{ |
981 |
peer->epsv_forced = 1; |
peer->epsv_forced = 1; |
982 |
return(ftp_write(peer, FALSE, 200, REPLY_EPSVON)); |
return (ftp_write(peer, FALSE, 200, REPLY_EPSVON)); |
983 |
} |
} |
984 |
else if (sscanf(param, "%d", &proto) == 1) |
else if (sscanf(param, "%d", &proto) == 1) |
985 |
{ |
{ |
986 |
if (proto != FTP_IPV4) |
if (proto != FTP_IPV4) |
987 |
return(ftp_write(peer, FALSE, 522, REPLY_BADPROTO)); |
return (ftp_write(peer, FALSE, 522, REPLY_BADPROTO)); |
988 |
} |
} |
989 |
else |
else |
990 |
return(ftp_write(peer, FALSE, 500, REPLY_EPSVERR)); |
return (ftp_write(peer, FALSE, 500, REPLY_EPSVERR)); |
991 |
} |
} |
992 |
|
|
993 |
peer->passiveport = listenparrelelport(peer->remotefd, &(peer->remoteport), &a1, 5); |
peer->passiveport = |
994 |
|
listenparrelelport(peer->remotefd, &(peer->remoteport), &a1, 5); |
995 |
|
|
996 |
if (peer->passiveport == -1) |
if (peer->passiveport == -1) |
997 |
{ |
{ |
998 |
peer->passiveport = 0; |
peer->passiveport = 0; |
999 |
reporterror(peer, "passive port", errno); |
reporterror(peer, "passive port", errno); |
1000 |
return(FALSE); |
return (FALSE); |
1001 |
} |
} |
1002 |
select_addfd(peer->sel, peer->passiveport); |
select_addfd(peer->sel, peer->passiveport); |
1003 |
|
|
1004 |
return(ftp_write(peer, FALSE, 229, REPLY_EPSV(peer->remoteport))); |
return (ftp_write(peer, FALSE, 229, REPLY_EPSV(peer->remoteport))); |
1005 |
} |
} |
1006 |
|
|
1007 |
int ftp_list(FTPSTATE *peer, char *param) |
int ftp_list(FTPSTATE * peer, |
1008 |
|
char *param) |
1009 |
{ |
{ |
1010 |
char *p = param; |
char *p = param; |
1011 |
int done = FALSE; |
int done = FALSE; |
1012 |
int parm = 0; |
int parm = 0; |
1013 |
|
|
1014 |
while (!done) |
while (!done) |
1015 |
{ |
{ |
1016 |
if (p == NULL) |
if (p == NULL) |
1026 |
} |
} |
1027 |
} |
} |
1028 |
|
|
1029 |
return(ftp_lister(peer, p, FALSE, parm)); |
return (ftp_lister(peer, p, FALSE, parm)); |
1030 |
} |
} |
1031 |
|
|
1032 |
int ftp_nlst(FTPSTATE *peer, char *param) |
int ftp_nlst(FTPSTATE * peer, |
1033 |
|
char *param) |
1034 |
{ |
{ |
1035 |
char *p = param; |
char *p = param; |
1036 |
int done = FALSE; |
int done = FALSE; |
1037 |
int parm = 0; |
int parm = 0; |
1038 |
|
|
1039 |
while (!done) |
while (!done) |
1040 |
{ |
{ |
1041 |
if (p == NULL) |
if (p == NULL) |
1051 |
} |
} |
1052 |
} |
} |
1053 |
|
|
1054 |
return(ftp_lister(peer, p, TRUE, parm)); |
return (ftp_lister(peer, p, TRUE, parm)); |
1055 |
} |
} |
1056 |
|
|
1057 |
int ftp_cdup(FTPSTATE *peer, char *param) |
int ftp_cdup(FTPSTATE * peer, |
1058 |
|
char *param) |
1059 |
{ |
{ |
1060 |
return(ftp_cwd(peer, "..")); |
return (ftp_cwd(peer, "..")); |
1061 |
} |
} |
1062 |
|
|
1063 |
int ftp_rnfr(FTPSTATE *peer, char *param) |
int ftp_rnfr(FTPSTATE * peer, |
1064 |
|
char *param) |
1065 |
{ |
{ |
1066 |
freeifnotnull(peer->renameoldname); |
freeifnotnull(peer->renameoldname); |
1067 |
peer->renameoldname = file_expand(peer, param); |
peer->renameoldname = file_expand(peer, param); |
1068 |
return(ftp_write(peer, FALSE, 350, REPLY_RENAMESOURCE)); |
return (ftp_write(peer, FALSE, 350, REPLY_RENAMESOURCE)); |
1069 |
} |
} |
1070 |
|
|
1071 |
int ftp_noop(FTPSTATE *peer, char *param) |
int ftp_noop(FTPSTATE * peer, |
1072 |
|
char *param) |
1073 |
{ |
{ |
1074 |
return(ftp_write(peer, FALSE, 200, REPLY_NOOP)); |
return (ftp_write(peer, FALSE, 200, REPLY_NOOP)); |
1075 |
} |
} |
1076 |
|
|
1077 |
int ftp_rein(FTPSTATE *peer, char *param) |
int ftp_rein(FTPSTATE * peer, |
1078 |
|
char *param) |
1079 |
{ |
{ |
1080 |
if (peer->jailenabled) |
if (peer->jailenabled) |
1081 |
return(ftp_write(peer, FALSE, 530, REPLY_JAILUSER)); |
return (ftp_write(peer, FALSE, 530, REPLY_JAILUSER)); |
1082 |
if (peer->loggedin) |
if (peer->loggedin) |
1083 |
shinfo_delusergroup(peer->groupname); |
shinfo_delusergroup(peer->groupname); |
1084 |
|
|
1085 |
peer->loggedin = FALSE; |
peer->loggedin = FALSE; |
1086 |
abortdatasocket(peer); |
abortdatasocket(peer); |
1087 |
return(ftp_write(peer, FALSE, 220, "Reinitialize successful, enter username.")); |
return (ftp_write |
1088 |
} |
(peer, FALSE, 220, "Reinitialize successful, enter username.")); |
1089 |
|
} |
1090 |
|
|
1091 |
int ftp_none(FTPSTATE *peer, char *param) |
int ftp_none(FTPSTATE * peer, |
1092 |
|
char *param) |
1093 |
{ |
{ |
1094 |
return(FALSE); |
return (FALSE); |
1095 |
} |
} |
1096 |
|
|
1097 |
int ftp_help(FTPSTATE *peer, char *param) |
int ftp_help(FTPSTATE * peer, |
1098 |
|
char *param) |
1099 |
{ |
{ |
1100 |
return(ftp_dohelp(peer, mainftpcmd, param, peer->cmddisableset)); |
return (ftp_dohelp(peer, mainftpcmd, param, peer->cmddisableset)); |
1101 |
} |
} |
1102 |
|
|
1103 |
int ftp_dohelp(FTPSTATE *peer, FTPCMD *ftpcmds, char *command, int *disableset) |
int ftp_dohelp(FTPSTATE * peer, |
1104 |
|
FTPCMD * ftpcmds, |
1105 |
|
char *command, |
1106 |
|
int *disableset) |
1107 |
{ |
{ |
1108 |
char outstr[128]; |
char outstr[128]; |
1109 |
char cmd[10]; |
char cmd[10]; |
1110 |
int result = FALSE; |
int result = FALSE; |
1111 |
int count2,count = 0; |
int count2, count = 0; |
1112 |
|
|
1113 |
if (command != NULL) |
if (command != NULL) |
1114 |
{ |
{ |
1115 |
while(((strcasecmp(ftpcmds[count].command, command) != 0) && |
while (((strcasecmp(ftpcmds[count].command, command) != 0) && |
1116 |
(ftpcmds[count].ftpfunc != NULL)) || |
(ftpcmds[count].ftpfunc != NULL)) || |
1117 |
(peer->loggedin ? disableset[count] : ftpcmds[count].needslogin)) |
(peer->loggedin ? disableset[count] : ftpcmds[count]. |
1118 |
|
needslogin)) |
1119 |
count++; |
count++; |
1120 |
|
|
1121 |
if (ftpcmds[count].ftpfunc == NULL) |
if (ftpcmds[count].ftpfunc == NULL) |
1122 |
ftp_write(peer, FALSE, 502, REPLY_HELPUNKNOWN(command)); |
ftp_write(peer, FALSE, 502, REPLY_HELPUNKNOWN(command)); |
1123 |
else |
else |
1124 |
ftp_write(peer, FALSE, 214, "%-8s : %s", ftpcmds[count].command, ftpcmds[count].helpdesc); |
ftp_write(peer, FALSE, 214, "%-8s : %s", ftpcmds[count].command, |
1125 |
return(FALSE); |
ftpcmds[count].helpdesc); |
1126 |
|
return (FALSE); |
1127 |
} |
} |
1128 |
|
|
1129 |
ftp_write(peer, TRUE, 0, REPLY_HELPSTART); |
ftp_write(peer, TRUE, 0, REPLY_HELPSTART); |
1130 |
while (ftpcmds[count].ftpfunc != NULL) |
while (ftpcmds[count].ftpfunc != NULL) |
1131 |
{ |
{ |
1134 |
strcpy(outstr, "214-"); |
strcpy(outstr, "214-"); |
1135 |
else |
else |
1136 |
strcpy(outstr, " "); |
strcpy(outstr, " "); |
1137 |
/* now increment past disabled commands */ |
/* |
1138 |
while((peer->loggedin ? disableset[count] : ftpcmds[count].needslogin)) |
* now increment past disabled commands |
1139 |
|
*/ |
1140 |
|
while ((peer->loggedin ? disableset[count] : ftpcmds[count]. |
1141 |
|
needslogin)) |
1142 |
count++; |
count++; |
1143 |
|
|
1144 |
while ((count2 < 7) && (ftpcmds[count].ftpfunc != NULL)) |
while ((count2 < 7) && (ftpcmds[count].ftpfunc != NULL)) |
1147 |
strcat(outstr, cmd); |
strcat(outstr, cmd); |
1148 |
count2++; |
count2++; |
1149 |
count++; |
count++; |
1150 |
/* now increment past disabled commands */ |
/* |
1151 |
while((peer->loggedin ? disableset[count] : ftpcmds[count].needslogin)) |
* now increment past disabled commands |
1152 |
|
*/ |
1153 |
|
while ((peer->loggedin ? disableset[count] : ftpcmds[count]. |
1154 |
|
needslogin)) |
1155 |
count++; |
count++; |
1156 |
} |
} |
1157 |
ftp_write(peer, TRUE, 0, outstr); |
ftp_write(peer, TRUE, 0, outstr); |
1158 |
} |
} |
|
|
|
|
result = ftp_write(peer, FALSE, 214, REPLY_HELPEND(peer->vserver->email)); |
|
1159 |
|
|
1160 |
return(result); |
result = ftp_write(peer, FALSE, 214, REPLY_HELPEND(peer->vserver->email)); |
1161 |
|
|
1162 |
|
return (result); |
1163 |
} |
} |
1164 |
|
|
1165 |
int ftp_allo(FTPSTATE *peer, char *param) |
int ftp_allo(FTPSTATE * peer, |
1166 |
|
char *param) |
1167 |
{ |
{ |
1168 |
return(ftp_write(peer, FALSE, 202, REPLY_ALLO)); |
return (ftp_write(peer, FALSE, 202, REPLY_ALLO)); |
1169 |
} |
} |
1170 |
|
|
1171 |
int ftp_acct(FTPSTATE *peer, char *param) |
int ftp_acct(FTPSTATE * peer, |
1172 |
|
char *param) |
1173 |
{ |
{ |
1174 |
return(ftp_write(peer, FALSE, 200, REPLY_ACCT)); |
return (ftp_write(peer, FALSE, 200, REPLY_ACCT)); |
1175 |
} |
} |
1176 |
|
|
1177 |
int ftp_stru(FTPSTATE *peer, char *param) |
int ftp_stru(FTPSTATE * peer, |
1178 |
|
char *param) |
1179 |
{ |
{ |
1180 |
if ((param[0] & (255-32)) == 'F') |
if ((param[0] & (255 - 32)) == 'F') |
1181 |
return(ftp_write(peer, FALSE, 200, REPLY_STRUFILE)); |
return (ftp_write(peer, FALSE, 200, REPLY_STRUFILE)); |
1182 |
else |
else |
1183 |
return(ftp_write(peer, FALSE, 500, REPLY_STRUUNKNOWN)); |
return (ftp_write(peer, FALSE, 500, REPLY_STRUUNKNOWN)); |
1184 |
} |
} |