📄 ftpcmd.c
字号:
#include <stdlib.h>
#include "Public.h"
#include "Ftpcmd.h"
// ftp 全局变量结构体
//extern FtpGlobalVar ftp_global_var;
/************************************
用户登入处理函数
**************************************/
int do_user(char * param)
{
// 没有办法测试
if (ftp_global_var.IsLogin)
{
ServiceEcho(503,"Already logged in.");
return -1; // 已经登入 不做处理
}
//int isanonymous =0;
if (ftp_config.anonymous_enable==1 && strcmp("anonymous",param)==0)
{
ftp_global_var.isanonymous =1;
}
// 参数判断
if (0== strlen(param))
{
ServiceEcho(500,"USER conmond request a param.");
return -1;
}
ServiceEcho(311,"Please specify the password.");
// ServiceEcho(311,temp);
strcpy(ftp_global_var.username,param);
return 0;
}
/****************************************
用户和密码同时进行验证的 最重要的是对匿名登入的一个处理
****************************************/
int do_pass(char * param)
{
//if (ftp_global_var.isanonymous) // 为匿名用户登入时
if(strcmp(ftp_global_var.username,"anonymous")==0)
{
strcpy(ftp_global_var.username,"ftp"); // 用默认的FTP 登入系统
}
strcpy(ftp_global_var.pass,param);
struct passwd * pwd;
struct spwd * showpwd;
/*
char temp11[80]={0};
sprintf(temp11,"username=%s",ftp_global_var.username);
ServiceEcho(200,temp11);
*/
pwd=getpwnam(ftp_global_var.username);
showpwd=getspnam(ftp_global_var.username);
if (pwd ==NULL || showpwd==NULL)
{
ServiceEcho(530,"Login Error.");
return -1; // 登入失败
}
char temp[13];
strncpy(temp,showpwd->sp_pwdp,12);
//temp[13]='\0';
if (!ftp_global_var.isanonymous) //
{
// 不是匿名用户登入时,需要验证
if (strcmp( ((char *) (crypt(param,temp) ) ),showpwd->sp_pwdp )!=0)
{
// 登入失败
ServiceEcho(530,"Login Error.");
}
}
// 成功登入的情况
strcpy(ftp_global_var.currpath,pwd->pw_dir); // 当前目录
strcpy(ftp_global_var.pass,param); // 保存密码
ftp_global_var.IsLogin = 1; // 登入状态
setegid(pwd->pw_gid); // 用户ID
seteuid(pwd->pw_uid); // 组ID
ftp_global_var.uid = pwd->pw_uid;
ftp_global_var.gid = pwd->pw_gid;
chdir(pwd->pw_dir); // 改变当前工作目录
ServiceEcho(230,pwd->pw_dir);
return 0;
}
int set_path(char * param)
{
//getcwd(ftp_global_var.currpath,PATH_MAX); // 当前工作目录
/*
if (strcmp(param,"."))
{
}else if (strcmp(param,".."))
{
}else
*/
if (strcmp(ftp_global_var.username,"ftp")==0)
{
//ftp匿名变量的时候
if (strstr(param,"/")!=0)
{ // 绝对路径
char tempdir[PATH_MAX]={0};
strcat(tempdir,"/var/ftp/");
strcat(tempdir,param);
strcpy(ftp_global_var.currpath,tempdir);
}
else //if(strcmp(param,""))
{
// 相对路
getcwd(ftp_global_var.currpath,PATH_MAX);
strcat(ftp_global_var.currpath,"/");
strcat(ftp_global_var.currpath,param);
}
return 0;
}
if (strstr(param,"/")!=NULL)
{
//found 绝对路径
strcpy(ftp_global_var.currpath,param);
}
else
{
//not found
strcat(ftp_global_var.currpath,"/");
strcat(ftp_global_var.currpath,param);
}
}
/********************
改变工作目录
*************************/
int do_cwd(char * param)
{
// 路径变更
// ?????? 关于路径的判断
/*
getcwd(ftp_global_var.currpath,PATH_MAX); // 更新
strcat(ftp_global_var.currpath,"/");
strcat(ftp_global_var.currpath,param);
*/
set_path(param);
if (chdir(ftp_global_var.currpath)<0)
{
ServiceEcho(550,"Failed to change directory.");
//ServiceEcho(550,ftp_global_var.currpath);
getcwd(ftp_global_var.currpath,PATH_MAX); // 更新
return -1;
}
getcwd(ftp_global_var.currpath,PATH_MAX); // 更新
ServiceEcho(250,"Directory successfully changed");
//ServiceEcho(250,ftp_global_var.currpath);
return 0;
}
/*回到上一层目录*/
int do_cdup(char * param)
{
if (strcmp(ftp_global_var.username,"ftp") == 0 && strcmp(ftp_global_var.currpath,"/var/ftp")==0)
{
do_cwd(".");
}
else
{
do_cwd("..");
}
return 0;
}
int do_syst(char * param)
{
ServiceEcho(215,"UNIX Type: L8");
return 0;
}
// 打印当前目录
int do_pwd(char * param)
{
char temp[PATH_MAX]={0};
char * p=NULL;
if ( strcmp(ftp_global_var.username,"ftp") == 0 )
{
if(p=strstr(ftp_global_var.currpath,"/var/ftp"))
{
if (strlen(ftp_global_var.currpath)==8)
{
sprintf(temp,"\"%s\"","/");
}else
{
sprintf(temp,"\"%s\"",&ftp_global_var.currpath[8]);
}
ServiceEcho(257, temp);
}
else
{
// 相对路径
}
}
else
{
sprintf(temp,"\"%s\"",ftp_global_var.currpath);
ServiceEcho(257, temp);
}
return 0;
}
int do_type(char * param)
{
if (strcmp(param,"A")==0)
{
ftp_global_var.transmode='A';
ServiceEcho(200,"Switching to ASCII mode.");
}else if(strcmp(param,"I")==0)
{
ftp_global_var.transmode='I';
ServiceEcho(200,"Switching to BINARY mode.");
}
return 0;
}
/*
数据端口,主要向服务器发送客户数据连接的端口,
格式为PORT h1,h2,h3,h4,p1,p2,其中32位的IP地址用h1,h2,h3,h4表示,
16位的TCP端口号用 p1,p2表示。
*/
// TO DO 超过时间 应该自动却换为 psav 进行处理
// ?????????????????
// ??????????????????????????????????????
int do_port(char * param)
{
int ip[4]={0}; // ip四个段
int port[2]={0}; // port 两个段
char str_ip[16]={0};
int resport=-1;
// 提取IP
sscanf(param,"%d,%d,%d,%d,%d,%d",&ip[0],&ip[1],&ip[2],&ip[3],&port[0],&port[1]);
sprintf(str_ip,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]);
// 计算port
resport=port[0]*256+port[1];
char temp[10]={0};
// sprintf(temp,"%d",resport);
//保存到相应的全局变量
strcpy(ftp_global_var.datacon_ip,str_ip);
ftp_global_var.datacon_port = resport;
ServiceEcho(200,"PORT command successful. Consider using PSAV");
ftp_global_var.IsPort =1; // 保存主动模式
ftp_global_var.port_port = resport;
strcpy(ftp_global_var.port_ip,str_ip);
return 0;
}
/*************************
主动连接
*************************/
int Port_connect()
{
struct sockaddr_in servaddr,cliaddr;
int servfd;
int clifd;
memset(&servaddr,0,sizeof(servaddr));
memset(&cliaddr,0,sizeof(cliaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(20);
//servaddr.sin_addr.s_addr = inet_addr();
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
cliaddr.sin_family =AF_INET;
cliaddr.sin_port = htons(ftp_global_var.port_port);
cliaddr.sin_addr.s_addr = inet_addr(ftp_global_var.port_ip);
int len=sizeof(cliaddr);
ftp_global_var.uid = geteuid();
ftp_global_var.gid = getegid();
seteuid(0);
setegid(0);
// 只有ROOT 用户才有权限绑定20端口
// ????????????? 调用语义是有问题的 借用一个函数
servfd = Tcp_service(ftp_global_var.port_ip,20);
//servfd = socket(AF_INET,SOCK_DGRAM,0);
seteuid(ftp_global_var.uid);
setegid(ftp_global_var.gid);
connect(servfd,(struct sockaddr *)&cliaddr,len);
ServiceEcho(150,"Here comes the directory listing");
}
/*****************************
被动连接
****************************/
int Pasv_connect()
{
int clisockfd;
clisockfd = Tcp_accept(ftp_global_var.pasv_mode_sockfd,NULL,NULL);
ServiceEcho(150,"Here comes the directory listing"); // 说明已经连接上了。
Tcp_close(ftp_global_var.pasv_mode_sockfd); // 关闭监听
return clisockfd;
}
/********************************
列目录详细清单
*********************************/
int do_list(char * param)
{
// 两种模式,调用不同的方式
if (ftp_global_var.IsPasv == 0 && ftp_global_var.IsPort==0)
{
ServiceEcho(425,"Use PORT or PASV first.");
return 0;
}
if (ftp_global_var.IsPasv)
{
// 被动模式
//int clisockfd = Pasv_connect();
int clisockfd = Tcp_accept(ftp_global_var.pasv_mode_sockfd,NULL,NULL);
ServiceEcho(150,"Here comes the directory listing"); // 说明已经连接上了。
Tcp_close(ftp_global_var.pasv_mode_sockfd); // 关闭监听
// 发送目录
send_list(clisockfd);
Tcp_close(clisockfd);
ftp_global_var.IsPasv = 0;
ServiceEcho(226,"Directory send Ok");
}else if (ftp_global_var.IsPort==1)
{
// 主动模式
struct sockaddr_in servaddr,cliaddr;
int servfd;
int clifd;
memset(&servaddr,0,sizeof(servaddr));
memset(&cliaddr,0,sizeof(cliaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(20);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
cliaddr.sin_family =AF_INET;
cliaddr.sin_port = htons(ftp_global_var.port_port);
cliaddr.sin_addr.s_addr = inet_addr(ftp_global_var.port_ip);
int len=sizeof(cliaddr);
ftp_global_var.uid = geteuid();
ftp_global_var.gid = getegid();
seteuid(0);
setegid(0);
// 只有ROOT 用户才有权限绑定20端口
// ????????????? 调用语义是有问题的 借用一个函数
servfd = Tcp_service(ftp_global_var.port_ip,20);
//servfd = socket(AF_INET,SOCK_DGRAM,0);
seteuid(ftp_global_var.uid);
setegid(ftp_global_var.gid);
connect(servfd,(struct sockaddr *)&cliaddr,len);
ServiceEcho(150,"Here comes the directory listing");
send_list(servfd);
shutdown(servfd,0);
Tcp_close(servfd);
//Tcp_close(clifd);
ftp_global_var.IsPort=0;
ServiceEcho(226,"Directory send Ok");
// 主动模式 服务器20 端口去。链接客户端
}
return 0;
}
// 列出段清单
int do_nlst(char * param)
{return 0;}
// 删除目录
int do_rmd(char * param)
{
// ?????????????
// ??????????????
if (rmdir(param)==-1)
{
//perror("do_param remove error.");
ServiceEcho(550,"Permission denied");
}
else
{
ServiceEcho(250,"Remove directory operation successful.");
}
return 0;
}
// 创建目录
int do_mkd(char * param)
{
if (mkdir(param,0755)==-1)
{
perror("mkdir error.\n");
}
char temp[PATH_MAX]={0};
getcwd(temp,PATH_MAX);
strcat(temp,param);
ServiceEcho(205,temp);
return 0;
}
/* 删除文件*/
int do_dele(char * param)
{
if (remove(param)==-1)
{
}
ServiceEcho(205,"Delete file ok.");
return 0;
}
/********************************************
重新初始化。此命令终止USER,重置所有参数,
控制连接仍然打开,用户可以再次使用USER命令。
*********************************************/
int do_rein(char * param)
{
ftp_global_var.IsLogin=0; // 设置为没有登入状态
memset(ftp_global_var.username,0,sizeof(ftp_global_var.username));
ftp_global_var.isanonymous=0;
ServiceEcho(200,"Rein OK.");
seteuid(0);
setegid(0);
return 0;
}
/***********************
帮助命令
**************************/
int do_help(char * param)
{
//ServiceEcho(502,"I don't have help.");
ServiceEcho(214,"------sitehelp-----");
ServiceEcho(214,"USER - 登入用户名 PASS - 登入密码 QUIT 退出");
ServiceEcho(214,"CWD - 改变工作目录 RMD - 删除目录 MKD - 新建目录");
ServiceEcho(214,"PWD - 打印当前目录 LIST- 列出详细清单" );
ServiceEcho(214,"STAT - 控制状态 SIZE - 获取文件大小");
ServiceEcho(214,"------help----------");
return 0;
}
// 退出
int do_quit(char * param)
{
ServiceEcho(221,"Goodbye!");
// 退出USER 登入
Tcp_close(ftp_global_var.CtrSockfd); // 关闭控制连接
return 0;
}
/****************************************
断点续传
*****************************************/
int do_rest(char * param)
{
long endseek=atoi(param);
char temp[80]={0};
//puts(param);
if (ftp_global_var.IsPasv == 0 && ftp_global_var.IsPort == 0)
{
sprintf(temp,"Restart position accepted (%d)",0);
}else
{
sprintf(temp,"Restart position accepted (%d)",param);
}
ServiceEcho(350,temp);
return 0;
}
/*********************************
被动连接
此命令要求服务器数据传输进程在随机端口上监听,进入被动接收请求的状态
**********************************/
int do_pasv(char * param)
{
// 被动方式 建立数据链接 发送IP 和随机端口给 客户端,
// 然后客服端会来链接他
int datalistenfd=0;
char localip[16]={0};
getlocalip(localip);
datalistenfd = Tcp_service(localip,0); // 0#port 就是随机port
//提取端口
struct sockaddr_in pasv_addr;
int len=sizeof(pasv_addr);
memset(&pasv_addr,0,sizeof(pasv_addr));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -