/*
ftpcommand.c
------------
FTP-protocol request handlers.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/stat.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#ifdef __CYGWIN__
#include <winsock2.h>
#else
#include <unistd.h>
#include <sys/socket.h>
#include <sys/param.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
#include <signal.h>
#include <errno.h>
#include "ftpcommand.h"
#include "stupid-ftpd.h"
#include "ftpdconfig.h"
#include "ftperror.h"
#include "ls.h"
#define TRFMSG_INTERVAL 1000000
#define REQ_COUNT 23
const char *request[REQ_COUNT]={
"SYST","QUIT","TYPE","PORT","LIST","CWD","PWD","RETR",
"USER","PASS","REST","SIZE","MDTM","STOR","CDUP","NOOP","GET",
"NLST","PASV","ABOR","MKD","RMD","DELE"
};
const char *ftp_returnstr[]={
"150 OK\r\n",
"501 Error in parameters.\r\n",
"226 Transfer complete.\r\n",
"221 Bye.\r\n",
"425 Can't open passive connection.\r\n",
"428 Server shutdown.\r\n",
"429 Server restart.\r\n",
"530 Server is busy, sorry.\r\n",
"220 Welcome to Stupid-FTPd server.\r\n",
"331 Guest login ok, send your e-mail address as password.\r\n",
"531 Anonymous access denied.\r\n",
"532 Login incorrect.\r\n",
"533 No multiple logins allowed.\r\n",
"534 Home directory not found.\r\n",
"422 Too busy to play with you.\r\n",
"423 Connection timed out.\r\n",
"215 UNIX Type: L8 (Linux).\r\n",
"500 Unknown type.\r\n",
"502 Illegal PORT request.\r\n",
"200 PORT command successful.\r\n",
"250 CWD command successful.\r\n",
"553 Permission denied.\r\n",
"350 Resume request successful.\r\n",
"451 Transmition error occured.\r\n",
"209 Received break, bye.\r\n",
"503 Command not understood.\r\n",
"227 Abort successful.\r\n",
"591 Data transmition stopped by admin.\r\n",
"491 Download in progress.\r\n",
"257 MKD command successful.\r\n",
"258 RMD command successful.\r\n",
"259 File successfully deleted.\r\n"
"540 User banned.\r\n",
"540 User banned.\r\n",
"550 not a file.\r\n",
NULL
};
/* prototypes */
void user_spool(int,int,char *);
int checkpath(int,char *,char *);
void childtimeout(int);
int waitaccept(int);
void do_list(int,char *,int);
int do_chdir(int,char *);
int do_retr(int,char *);
int do_stor(int,char *);
void do_user(int,char *);
void do_pass(int,char *);
void do_size(int,char *);
void do_mdtm(int,char *);
void do_pasv(int);
int do_mkdir(int,char *);
int do_rmdir(int,char *);
int do_dele(int,char *);
void user_return(int nr,int id)
{
/* printf("Sending '%s'\n",ftp_returnstr[id]); */
write(pchild[nr]->sock,ftp_returnstr[id],strlen(ftp_returnstr[id]));
}
void user_spool(int nr,int id,char *file)
{
char buffer[1024],marker[32];
FILE *fp;
fd_set fds;
struct timeval tv;
int n;
if (file[0]!=0) {
if ((fp=fopen(file,"r"))!=NULL) {
n=0;
while (fgets(buffer,sizeof(buffer)-1,fp)!=NULL) {
if (n==0) sprintf(marker,"%d- ",id);
write(pchild[nr]->sock,marker,strlen(marker));
if ((n=strlen(buffer))>0) {
if (buffer[n-1]=='\n') buffer[n-1]=0;
strcat(buffer,"\r\n");
}
do {
FD_ZERO(&fds);
FD_SET(pchild[nr]->sock,&fds);
tv.tv_sec=transfertimeout;tv.tv_usec=0;
if (select(pchild[nr]->sock+1,NULL,&fds,NULL,&tv)<=0) {
#ifdef DEBUG
fprintf(stderr,"Spool (%d) timeout to client %d.\n",id,nr+1);
#endif
kill_connection(nr);
return;
}
} while (!FD_ISSET(pchild[nr]->sock,&fds));
write(pchild[nr]->sock,buffer,strlen(buffer));
}
}
}
}
int checkpath(int nr,char *param,char *path)
{
char cmd[MAXPATHLEN+4];
char allowed[MAXPATHLEN+4];
if (!strcmp(pchild[nr]->rootdir,"/")) {
strcpy(allowed,pchild[nr]->rootdir);
}
else {
/* should not happen */
if (strlen(pchild[nr]->rootdir)>=MAXPATHLEN) return 1;
sprintf(allowed,"%s/",pchild[nr]->rootdir);
}
if (strlen(allowed)+strlen(pchild[nr]->reldir)>=sizeof(cmd)) return 1;
sprintf(cmd,"%s%s",allowed,pchild[nr]->reldir);
if (param) {
if (param[0]!='/') {
if (strlen(cmd)+strlen(param)>=sizeof(cmd)) return 1;
strcat(cmd,param);
} else {
if (strlen(allowed)+strlen(¶m[1])>=sizeof(cmd)) return 1;
strcpy(cmd,allowed);
strcat(cmd,¶m[1]);
}
}
#ifdef DEBUG
fprintf(stderr,"Checking path %s\n",cmd);
#endif
if (!realpath(cmd,path)) return 1;
#ifdef DEBUG
fprintf(stderr,"Converted to: %s\n",path);
#endif
if (strlen(path)>=MAXPATHLEN) return 1;
strcat(path,"/");
strcpy(cmd,path);
cmd[strlen(allowed)]=0;
#ifdef DEBUG
printf("Comparing (%s) '%s'=='%s'\n",
realchangeroot ? "real" : "virtual",
cmd,allowed);
#endif
if (strcmp(cmd,allowed)) return 1;
#ifdef DEBUG
printf("Debug: path has now %d/%d chars.\n",strlen(path),MAXPATHLEN);
#endif
return 0;
}
void kill_connection(int nr)
{
char buffer[256];
time_t tm;
if (!daemonmode) {
printf("User %d, killed.\n",nr+1);
out_prompt();
}
/* close passive port */
if (pchild[nr]->pasvsock) {
close(pchild[nr]->pasvsock);
pchild[nr]->pasvsock=0;
}
/* checking retr subprocess */
if (pchild[nr]->pid) kill(pchild[nr]->pid,SIGTERM);
pchild[nr]->pid=0;
/* close connection and tidy up */
close(pchild[nr]->sock);
pchild[nr]->sock=0;
pchild[nr]->dataport=0;
if (logfile!=NULL) {
tm=time(NULL);
strcpy(buffer,ctime(&tm));
buffer[strlen(buffer)-1]=0;
fprintf(logfile,"%s: LOGOUT: user %d ",buffer,nr+1);
if (pchild[nr]->usertype<logininfocount)
fprintf(logfile,"%s ",pchild[nr]->username);
else fprintf(logfile,"nologin ");
fprintf(logfile,"%s (%d.%d.%d.%d)\n",
pchild[nr]->url,
pchild[nr]->userip[0],pchild[nr]->userip[1],
pchild[nr]->userip[2],pchild[nr]->userip[3]);
fflush(logfile);
}
}
void childtimeout(int nr)
{
exit(0);
}
int waitaccept(int nr)
{
int socksize,soc;
struct sockaddr_in sai;
signal(SIGALRM,childtimeout);
alarm(transfertimeout);
socksize=sizeof(sai);
soc=accept(pchild[nr]->pasvsock,(struct sockaddr *)&sai,&socksize);
signal(SIGALRM,SIG_IGN);
return soc;
}
int list_callback(int soc,int nr,char *line) {
fd_set fds;
struct timeval tv;
do {
FD_ZERO(&fds);
FD_SET(soc,&fds);
tv.tv_sec=transfertimeout;tv.tv_usec=0;
if (select(soc+1,NULL,&fds,NULL,&tv)<=0) {
#ifdef DEBUG
fprintf(stderr,"LIST timeout to client %d.\n",nr+1);
#endif
close(soc);
user_return(nr,RET_501);
return 0;
}
} while (!FD_ISSET(soc,&fds));
write(soc,line,strlen(line));
return 1;
}
void do_list(int nr,char *param,int listtype)
{
struct hostent *hp;
char cmd[1024],path[1024],mask[1024]/*,cwd[1024]*/;
unsigned long addr;
int soc,n;
unsigned int socksize;
struct sockaddr_in sai;
char nullch[8];
char *cmask;
strcpy(nullch,".");
if (pchild[nr]->pasvsock<=0 && pchild[nr]->dataport==0) {
user_return(nr,RET_501);
exit(0);
}
mask[0]=0;
if (param) {
while (param[0]=='-') {
n=1;
while (param[n]!=' ' && param[n]!=0) n++;
if (param[n]==' ') param=¶m[n+1];
else param=¶m[n];
}
strcpy(cmd,param);
if (strrchr(cmd,'*') || strrchr(cmd,'?')) {
if (strrchr(cmd,'/')) {
strcpy(mask,strrchr(cmd,'/')+1);
*strrchr(cmd,'/')=0;
}
else {
strcpy(mask,cmd);
cmd[0]=0;
}
}
if (strrchr(cmd,'*') || strrchr(cmd,'?')) {
user_return(nr,RET_501);
exit(0);
}
} else {
cmd[0]=0;
param=nullch;
}
if (param[0]=='/') param++;
if (param[0]=='/') {
user_return(nr,RET_501);
exit(0);
}
cmask=strrchr(mask,'/');
if (cmask!=NULL) {
*cmask=0;
cmask++;
if (strlen(cmd)+strlen(mask)+2>sizeof(cmd)) {
user_return(nr,RET_501);
exit(0);
}
strcat(cmd,"/");
strcat(cmd,mask);
strcpy(mask,cmask);
}
#ifdef DEBUG
printf("path before: %s\n",cmd);
#endif
if (checkpath(nr,cmd,path) || !strncmp(mask,"..",2)) {
user_retu
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
stupid-ftpd-1.5beta.tar.gz (33个子文件)
stupid-ftpd
ftpdconfig.h 1KB
CHANGES 7KB
ftperror.h 685B
servercommand.h 90B
Makefile 1KB
BUILD.Linux6 85B
ls.h 261B
ls.c 4KB
Makefile.Linux6 1KB
Makefile.Solaris 527B
TODO 320B
BUILD.SunOS 160B
command.h 90B
stupid-ftpd.c 8KB
ftpdconfig.c 10KB
COPYING 18KB
Stupid-FTPD.INI 3KB
stupid-ftpd.conf 3KB
CREDITS 647B
Makefile.Linux5 1KB
ftpcommand.c 30KB
Makefile.win 960B
stupid-ftpd.h 498B
Makefile.SunOS 533B
ftpcommand.h 724B
command.c 12KB
Makefile.AIX 1KB
BUILD.AIX 92B
BUILD.SCO 92B
README 1KB
Makefile.SCO 1KB
servercommand.c 8KB
BUILD.Linux5 85B
共 33 条
- 1
gzshun
- 粉丝: 759
- 资源: 25
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- (源码)基于Spring Boot和Vue的高性能售票系统.zip
- (源码)基于Windows API的USB设备通信系统.zip
- (源码)基于Spring Boot框架的进销存管理系统.zip
- (源码)基于Java和JavaFX的学生管理系统.zip
- (源码)基于C语言和Easyx库的内存分配模拟系统.zip
- (源码)基于WPF和EdgeTTS的桌宠插件系统.zip
- (源码)基于PonyText的文本排版与预处理系统.zip
- joi_240913_8.8.0_73327_share-2EM46K.apk
- Library-rl78g15-fpb-1.2.1.zip
- llvm-17.0.1.202406-rl78-elf.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
- 1
- 2
- 3
- 4
- 5
- 6
前往页