📄 cuftpd.c.c
字号:
}
if (cuftpd_port_connfd >= 0) {
close(cuftpd_port_connfd);
cuftpd_port_connfd = -1;
}
return CUFTPD_OK;
}
static int cuftpd_do_user(int ctrlfd, char *cmdline)
{
char *cp = strchr(cmdline, ' ');
if (cp) {
int i;
for (i = 0; i < CUFTPD_ARR_LEN(cuftpd_users); i++)
if (strcmp(cp + 1, cuftpd_users[i].user) == 0) {
CUFTPD_DEBUG("user(%s) is found\n", cp + 1);
cuftpd_cur_user = &cuftpd_users[i];
break;
}
if (!cuftpd_cur_user)
CUFTPD_DEBUG("user(%s) not found\n", cp + 1);
/*
* If user name is bad, we still don't close the connection
* and send back the 331 response to ask for password.
*/
return cuftpd_send_resp(ctrlfd, 331, cp + 1);
}
return cuftpd_send_resp(ctrlfd, 550);
}
static int cuftpd_do_pass(int ctrlfd, char *cmdline)
{
char *space = strchr(cmdline, ' ');
if (cuftpd_cur_user && space) {
if (strlen(cuftpd_cur_user->pass) == 0 ||
strcmp(space + 1, cuftpd_cur_user->pass) == 0) {
CUFTPD_DEBUG("password for %s OK\n", cuftpd_cur_user->user);
return cuftpd_send_resp(ctrlfd, 230, cuftpd_cur_user->user);
}
CUFTPD_DEBUG("password for %s ERR\n", cuftpd_cur_user->user);
}
/*
* User and pass don't match or
* cmd line does not contain a space character.
*/
cuftpd_cur_user = NULL;
return cuftpd_send_resp(ctrlfd, 530, "incorrect");
}
static int cuftpd_do_pwd(int ctrlfd, char *cmdline)
{
char curdir[PATH_MAX];
char *cp;
CUFTPD_CHECK_LOGIN();
getcwd(curdir, sizeof(curdir));
cp = &curdir[strlen(cuftpd_home_dir)];
return cuftpd_send_resp(ctrlfd, 257, (*cp == '\0') ? "/" : cp);
}
static int cuftpd_do_cwd(int ctrlfd, char *cmdline)
{
char *space = strchr(cmdline, ' ');
char curdir[PATH_MAX];
CUFTPD_CHECK_LOGIN();
if (!space)
return cuftpd_send_resp(ctrlfd, 550);
getcwd(curdir, sizeof(curdir));
if (strcmp(curdir, cuftpd_home_dir) == 0 &&
space[1] == '.' &&
space[2] == '.')
return cuftpd_send_resp(ctrlfd, 550);
/* Absolute path */
if (space[1] == '/') {
if (chdir(cuftpd_home_dir) == 0) {
if (space[2] == '\0' || chdir(space+2) == 0)
return cuftpd_send_resp(ctrlfd, 250);
}
chdir(curdir);
return cuftpd_send_resp(ctrlfd, 550);
}
/* Relative path */
if (chdir(space+1) == 0)
return cuftpd_send_resp(ctrlfd, 250);
chdir(curdir);
return cuftpd_send_resp(ctrlfd, 550);
}
/*
* This function acts as a implementation like 'ls -l' shell command.
*/
static int cuftpd_get_list(char buf[], int len)
{
DIR *dir;
struct dirent *ent;
int off = 0;
if ((dir = opendir(".")) < 0) {
CUFTPD_DEBUG("opendir() failed:%s\n", strerror(errno));
return CUFTPD_ERR;
}
buf[0] = '\0';
while ((ent = readdir(dir)) != NULL) {
char *filename = ent->d_name;
struct stat st;
char mode[] = "----------";
struct passwd *pwd;
struct group *grp;
struct tm *ptm;
char timebuf[BUFSIZ];
int timelen;
if (strcmp(filename, ".") == 0 ||
strcmp(filename, "..") == 0)
continue;
if (stat(filename, &st) < 0) {
closedir(dir);
CUFTPD_DEBUG("stat() failed:%s\n", strerror(errno));
return CUFTPD_ERR;
}
if (S_ISDIR(st.st_mode))
mode[0] = 'd';
if (st.st_mode & S_IRUSR)
mode[1] = 'r';
if (st.st_mode & S_IWUSR)
mode[2] = 'w';
if (st.st_mode & S_IXUSR)
mode[3] = 'x';
if (st.st_mode & S_IRGRP)
mode[4] = 'r';
if (st.st_mode & S_IWGRP)
mode[5] = 'w';
if (st.st_mode & S_IXGRP)
mode[6] = 'x';
if (st.st_mode & S_IROTH)
mode[7] = 'r';
if (st.st_mode & S_IWOTH)
mode[8] = 'w';
if (st.st_mode & S_IXOTH)
mode[9] = 'x';
mode[10] = '\0';
off += snprintf(buf + off, len - off, "%s ", mode);
/* hard link number, this field is nonsense for ftp */
off += snprintf(buf + off, len - off, "%d ", 1);
/* user */
if ((pwd = getpwuid(st.st_uid)) == NULL) {
closedir(dir);
return CUFTPD_ERR;
}
off += snprintf(buf + off, len - off, "%s ", pwd->pw_name);
/* group */
if ((grp = getgrgid(st.st_gid)) == NULL) {
closedir(dir);
return CUFTPD_ERR;
}
off += snprintf(buf + off, len - off, "%s ", grp->gr_name);
/* size */
off += snprintf(buf + off, len - off, "%*d ", 10, st.st_size);
/* mtime */
ptm = localtime(&st.st_mtime);
if (ptm && (timelen = strftime(timebuf, sizeof(timebuf), "%b %d %H:%S", ptm)) > 0) {
timebuf[timelen] = '\0';
off += snprintf(buf + off, len - off, "%s ", timebuf);
}
else {
closedir(dir);
return CUFTPD_ERR;
}
off += snprintf(buf + off, len - off, "%s\r\n", filename);
}
return off;
}
static int cuftpd_do_list(int ctrlfd, char *cmdline)
{
char buf[BUFSIZ];
int n;
int fd;
CUFTPD_CHECK_LOGIN();
if ((fd = cuftpd_get_connfd()) < 0) {
CUFTPD_DEBUG("LIST cmd:no available fd%s", "\n");
goto err_label;
}
cuftpd_send_resp(ctrlfd, 150);
/*
* Get the 'ls -l'-like result and send it to client.
*/
n = cuftpd_get_list(buf, sizeof(buf));
if (n >= 0) {
if (cuftpd_send_msg(fd, buf, n) != n) {
CUFTPD_DEBUG("cuftpd_send_msg() failed: %s\n", strerror(errno));
goto err_label;
}
}
else {
CUFTPD_DEBUG("cuftpd_get_list() failed %s", "\n");
goto err_label;
}
cuftpd_close_all_fd();
return cuftpd_send_resp(ctrlfd, 226);
err_label:
cuftpd_close_all_fd();
return cuftpd_send_resp(ctrlfd, 550);
}
static int cuftpd_do_syst(int ctrlfd, char *cmdline)
{
CUFTPD_CHECK_LOGIN();
return cuftpd_send_resp(ctrlfd, 215);
}
static int cuftpd_do_size(int ctrlfd, char *cmdline)
{
char *space = strchr(cmdline, ' ');
struct stat st;
CUFTPD_CHECK_LOGIN();
if (!space || lstat(space + 1, &st) < 0) {
CUFTPD_DEBUG("SIZE cmd err: %s\n", cmdline);
return cuftpd_send_resp(ctrlfd, 550);
}
return cuftpd_send_resp(ctrlfd, 213, st.st_size);
}
static int cuftpd_do_dele(int ctrlfd, char *cmdline)
{
char *space = strchr(cmdline, ' ');
struct stat st;
CUFTPD_CHECK_LOGIN();
if (!space || lstat(space+1, &st) < 0 ||
remove(space+1) < 0) {
CUFTPD_DEBUG("DELE cmd err: %s\n", cmdline);
return cuftpd_send_resp(ctrlfd, 550);
}
return cuftpd_send_resp(ctrlfd, 200);
}
static int cuftpd_do_type(int ctrlfd, char *cmdline)
{
CUFTPD_CHECK_LOGIN();
/*
* Just send back 200 response and do nothing
*/
return cuftpd_send_resp(ctrlfd, 200);
}
/*
* Parse PORT cmd and fetch the ip and port,
* and both in network byte order.
*/
static int cuftpd_get_port_mode_ipport(char *cmdline, unsigned int *ip, unsigned short *port)
{
char *cp = strchr(cmdline, ' ');
int i;
unsigned char buf[6];
if (!cp)
return CUFTPD_ERR;
for (cp++, i = 0; i < CUFTPD_ARR_LEN(buf); i++) {
buf[i] = atoi(cp);
cp = strchr(cp, ',');
if (!cp && i < CUFTPD_ARR_LEN(buf) - 1)
return CUFTPD_ERR;
cp++;
}
if (ip)
*ip = *(unsigned int*)&buf[0];
if (port)
*port = *(unsigned short*)&buf[4];
return CUFTPD_OK;
}
/*
* Ftp client shipped with Windows XP uses PORT
* mode as default to connect ftp server.
*/
static int cuftpd_do_port(int ctrlfd, char *cmdline)
{
unsigned int ip;
unsigned short port;
struct sockaddr_in sin;
CUFTPD_CHECK_LOGIN();
if (cuftpd_get_port_mode_ipport(cmdline, &ip, &port) != CUFTPD_OK) {
CUFTPD_DEBUG("cuftpd_get_port_mode_ipport() failed%s", "\n");
goto err_label;
}
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = ip;
sin.sin_port = port;
CUFTPD_DEBUG("PORT cmd:%s:%d\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
if (cuftpd_port_connfd >= 0) {
close(cuftpd_port_connfd);
cuftpd_port_connfd = -1;
}
cuftpd_port_connfd = socket(AF_INET, SOCK_STREAM, 0);
if (cuftpd_port_connfd < 0) {
CUFTPD_DEBUG("socket() failed:%s\n", strerror(errno));
goto err_label;
}
if (connect(cuftpd_port_connfd, (struct sockaddr*)&sin, sizeof(sin)) < 0) {
CUFTPD_DEBUG("bind() failed:%s\n", strerror(errno));
goto err_label;
}
CUFTPD_DEBUG("PORT mode connect OK%s", "\n");
return cuftpd_send_resp(ctrlfd, 200);
err_label:
if (cuftpd_port_connfd >= 0) {
close(cuftpd_port_connfd);
cuftpd_port_connfd = -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -