📄 ftpcmd.c
字号:
#include <stdio.h>
#include <unistd.h>
#include <pwd.h>
#include <sys/types.h>
#include <string.h>
#include <sys/stat.h>
#include <signal.h>
#include <time.h>
#include <sys/socket.h>
#include "ftpcmd.h"
#include "ftppub.h"
#include "ftpnet.h"
#include "ftpdatatrans.h"
FTPCMD cmd_list[] = {
{"USER", do_user, CHECK_NOLOGIN | NEED_PARAM },
{"PASS", do_pass, CHECK_NOLOGIN },
{"CWD", do_cwd, CHECK_LOGIN | NEED_PARAM },
{"XCWD", do_cwd, CHECK_LOGIN | NEED_PARAM },
{"CDUP", do_cdup, CHECK_LOGIN | NO_PARAM },
{"XCUP", do_cdup, CHECK_LOGIN | NO_PARAM },
{"SYST", do_syst, CHECK_LOGIN },
{"PWD", do_pwd, CHECK_LOGIN | NO_PARAM },
{"XPWD", do_pwd, CHECK_LOGIN | NO_PARAM },
{"TYPE", do_type, CHECK_LOGIN | NEED_PARAM },
{"PORT", do_port, CHECK_LOGIN | NEED_PARAM },
{"LIST", do_list, CHECK_LOGIN },
{"NLST", do_nlst, CHECK_LOGIN },
{"CWD", do_cwd, CHECK_LOGIN | NEED_PARAM },
{"XCWD", do_cwd, CHECK_LOGIN | NEED_PARAM },
{"CDUP", do_cdup, CHECK_LOGIN | NO_PARAM },
{"RMD", do_rmd, CHECK_LOGIN | NEED_PARAM },
{"XRMD", do_rmd, CHECK_LOGIN | NEED_PARAM },
{"MKD", do_mkd, CHECK_LOGIN | NEED_PARAM },
{"XMKD", do_mkd, CHECK_LOGIN | NEED_PARAM },
{"DELE", do_dele, CHECK_LOGIN | NEED_PARAM },
{"REIN", do_rein, CHECK_LOGIN },
{"HELP", do_help, CHECK_LOGIN },
{"QUIT", do_quit, NO_CHECK },
{"REST", do_rest, CHECK_LOGIN | NEED_PARAM },
{"PASV", do_pasv, CHECK_LOGIN | NO_PARAM },
{"RNFR", do_rnfr, CHECK_LOGIN | NEED_PARAM },
{"RNTO", do_rnto, CHECK_LOGIN | NEED_PARAM },
{"SIZE", do_size, CHECK_LOGIN | NEED_PARAM },
{"NOOP", do_noop, NO_CHECK },
{"STOR", do_stor, CHECK_LOGIN | NEED_PARAM },
{"RETR", do_retr, CHECK_LOGIN | NEED_PARAM },
{"APPE", do_appe, CHECK_LOGIN | NEED_PARAM },
{"ABOR", do_abor, CHECK_LOGIN | NO_PARAM },
{"ACCT", NULL },
{"SMNT", NULL },
{"STRU", NULL },
{"MODE", do_mode, },
{"STOU", NULL },
{"ALLO", NULL },
{"MDTM", NULL, CHECK_LOGIN | NEED_PARAM },
{"SITE", NULL, CHECK_LOGIN | NEED_PARAM },
{"STAT", do_stat, CHECK_LOGIN | NEED_PARAM },
{""}
};
int do_user(char *param)
{
if(userlogined==1)
{
Respond(500,"User is logined");
return -1;
}
char buff[PARAM_BUFF_SIZE]={0};//命 令参数缓冲区
int i=0;
Intercept_Parameter(buff,param);
//printf("%s\n",buff);
strcpy(userName,buff);
//将存放在临时变量中的用户名全转小写
for(;i<strlen(buff);i++)
{
userName[i]=tolower(userName[i]);
}
//判断用户是否为匿名用户
if(strcmp(userName,"anonymous")==0)
{
// printf("匿名用户登 入\n");
IsAnonymous=1;
strcpy(userName,"ftp");
}
Respond(331,"Please specify the password");
return 1;
}
int do_pass(char *param)
{
int state;//保存login返回值
char password[100]={0};
Intercept_Parameter(password,param);//取出密户端传送过来的密码
// printf("IsAnonymous 值为%d\n",IsAnonymous);
if(IsAnonymous==1) //匿名用户登入
{
//state=1;
// printf("匿名登入\n");
// printf("匿名登入的用户名为 %s \n",userName);
state=Anonymous_Login(userName,password);
// printf("匿名登入成功 Anonymous_Login函数返回值为%d\n",state);
}
else //正常用户登 入
{
state=Login(userName,password);
//printf("%d \n",state);
// printf("用户名为 %s,密码%s \n",userName,password);
}
if(state>0)//成功登入的情况
{
userlogined=1;//用户登入
Respond(230,"Please specify the password");
}
else
{
Respond(530,"User name or Password Error");
}
return 1;
}
/*
int do_cwd(char *param)
{
char buf[512]={0};
int stat=0;
Intercept_Parameter(buf,param);//分离出参数
if(IsAnonymous==1)//即匿名用户登入
{
}
else
{
char curpath[1024]={0};
getcwd(curpath,1024);
// printf("CWD命令中执行chdir前的当前路径是: %s\n",curpath);
stat=chdir(buf);
memset(curpath,0,sizeof(curpath));
getcwd(curpath,1024);
// printf("CWD命令中执行chdir后的当前路径是: %s\n",curpath);
if(stat==0)
{
if(buf[0]=='/') //以'/'开头的路径
{
strcpy(path,buf);
}
else
{
if( path[strlen(path)-1]!='/' ) //判断当前路径是否以'/'结尾
{
strcat(path,"/");//在路径后补一个'/'
strcat(path,buf);//然后再加上目录名
}
else
{
strcat(path,buf);
}
}
}
}
if(stat==0)
{
Respond(250,"Directory successfully changed.");
}
else
{
Respond(550,"Failed to change directory.");
}
return 1;
}
*/
int do_cwd(char *param)
{
char buf[512]={0};
int stat=0;
char curpath[1024]={0};
Intercept_Parameter(buf,param);//分离出参数
if(IsAnonymous==1)//即匿名用户登入
{
//strcpy(curpath,anonymous_dir);
// printf("path的值是 %s,目录的地址是...................................... %s\n",path,buf);
if(buf[0]=='/')
{
sprintf(buf,"%s%s",cur_anonymous_dir,buf);
}
stat=chdir(buf);
if(stat==0)
{
//printf("执行更改目录命令*********************************************\n");
getcwd(cur_anonymous_dir,sizeof(cur_anonymous_dir));
strcpy(path,cur_anonymous_dir+strlen(anonymous_dir));
Respond(250,"Directory successfully changed.%s",path);
}
else
{
Respond(550,"Failed to change directory.");
}
}
else
{
//getcwd(curpath,1024);
//printf("CWD命令中执行chdir前的当前路径是: %s\n",curpath);
stat=chdir(buf);
//printf("执行chdir函数后函数返回值为 ....................... %d\n",stat);
//memset(curpath,0,sizeof(curpath));
//getcwd(curpath,1024);
//printf("CWD命令中执行chdir后的当前路径是: %s\n",curpath);
//printf("-------------------------------------------------------------\n");
if(stat==0)
{
//printf("执行更改目录命令*********************************************\n");
getcwd(curpath,sizeof(curpath));
strcpy(path,curpath);
Respond(250,"Directory successfully changed.");
}
else
{
Respond(550,"Failed to change directory.");
}
}
return 1;
}
int do_cdup(char *param)
{
char tmpPath[PATH_MAX+1];
int stat;
if(IsAnonymous==1)//匿名用户的情况下
{
int path_len=strlen(anonymous_dir);
//int i;
strcpy(tmpPath,cur_anonymous_dir);
// printf("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^%s\n",tmpPath);
if(strlen(tmpPath)>path_len)//这个判断看看是不是返回到达匿名用户的相对路径的根目下边
{
stat=chdir("../");
if(stat==0)
{
//取得用户的当前路径
getcwd(cur_anonymous_dir,sizeof(cur_anonymous_dir));
//strcpy(cur_anonymous_dir,tmpPath);
strcpy(path,cur_anonymous_dir+strlen(anonymous_dir));
Respond(250,"Directory successfully changed.%s",path);
}
else
{
Respond(550,"Failed to change directory.%s",cur_anonymous_dir);
}
}
}
else
{
strcpy(tmpPath,path);
int len=strlen(tmpPath);
int i=0;
for(i=len-1;i>=0;i--)
{
if(tmpPath[i]=='/')
{
tmpPath[i]='\0';
break;
}
}
if(strlen(tmpPath)==0)
{
strcpy(tmpPath,"/");
}
stat=chdir(tmpPath);
if(stat==0)
{
strcpy(path,tmpPath);
Respond(250,"Directory successfully changed.");
}
else
{
Respond(550,"Failed to change directory.");
}
}
return 1;
}
int do_syst(char *param)
{
Respond(215,"UNIX Type:L8");
return 1;
}
int do_pwd(char *param)
{
Respond(257,"\"%s\"",path);
return 1;
}
int do_type(char *param)
{
char temp[2]={0};
Intercept_Parameter(temp,param);
//printf("Type %s\n",temp);
if(temp[0]=='A')
{
Respond(200,"Switching to ASCII mode.");
}else if(temp[0]=='I')
{
Respond(200,"Switching to Binary mode.");
}
return 1;
}
int do_port(char *param)
{
char temp[25]={0};
char ip[15]={0};//存放点分十进制IP地址
int port=0;
int stat;
Intercept_Parameter(temp,param);//取得客户端地址 例如:192,168,0,1,15,70
separate_ip_port(temp,ip,&port);
// printf("IP:%s Port:%d............................................\n",ip,port);
//下边是进行主动连接
IsPASV=0;//将这个值设成0是明说现在用主功模式
struct sockaddr_in cliaddr,servaddr;
memset(&cliaddr, 0, sizeof(cliaddr));//将客户端套接字地址清零
memset(&servaddr, 0, sizeof(servaddr));//将服务端套接字地址清零
init_socket_addr(&cliaddr,NULL,20);//服务端用20端口跟客户端进行数据传输
init_socket_addr(&servaddr,ip,port);
datatrans_socket=CreateSocket();//创建一个跟客户端进行数据传输的套接字
//只有root用户才可以对端口号低于1024的端口进行绑定所以在绑定端口前要更改当前进程的有效用户ID跟有效用户组ID
//获得当前的有效用户ID和有效用户组ID,以便 于在绑定后,进行还原
gid_t egid = getegid();//有效用户组ID
uid_t euid = geteuid();//有效用户ID
//切换为root用户的权限
//这里要先改有效用户组然后再改有效用户,如果先改有效用户,那就没有权限再更改有效用户组
// printf("更改有效用户权限为root用户...........................\n");
setegid(0);
seteuid(0);
//绑定套接字地址
stat=bind_socket(datatrans_socket,&cliaddr);
// printf("datatrans_socket=%d\n",datatrans_socket);
if(stat<0)
{
printf("绑定20端口错误\n");
}
//切换回原来用户的权限
setegid(egid);
seteuid(euid);
stat=connect_socket(datatrans_socket,&servaddr);
if(stat==0)
{
Respond(200,"PORT command successful. Consider using PASV.");
}
else
{
Respond(530,"Connect Error.");
}
return 1;
}
int do_list(char *param)
{
Respond(150,"Here comes the directory listing.");
if(IsPASV==0)//IsPASV==0代表是主动模式
{
char curpath[1024]={0};
getcwd(curpath,1024);
// printf("当前路径是: %s\n",curpath);
FileList(datatrans_socket);
// printf("datatrans_socket=%d\n",datatrans_socket);
close(datatrans_socket);
}
else
{
//下边做被动模式
struct sockaddr_in cliaddr;
//int socket;//这个套接字是用来在被动模式下进行数据传送用的
pasv_datatrans_socket=accept_socket(pasv_listen_socket,&cliaddr); //在被动模式下 datatrans_socket套接字是监听套接字
FileList(pasv_datatrans_socket);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -