Example #1
0
// perform FTP TYPE command, switch binary mode on and off
void command_type(CLIENT_INFO * client_info)
{
	char line[BUFFER_SIZE] = { 0 };
	client_read_line(client_info->fd, client_info->buf, &client_info->buffer_pos);
	extract_line(line, client_info->buf, &client_info->buffer_pos);
	int len = strlen(line);
	if (len < 6)
	{
		send_code(client_info->fd, 500);
		return;
	}

	char * param = line + 5;
	if (strcmp(param, "A") == 0) client_info->binary_flag = 0;
	else if (strcmp(param, "A N") == 0) client_info->binary_flag = 0;
	else if (strcmp(param, "I") == 0) client_info->binary_flag = 1;
	else if (strcmp(param, "L 8") == 0) client_info->binary_flag = 1;
	else
	{
		send_code(client_info->fd, 500);
		return;
	}

	send_code(client_info->fd, 200);
}
Example #2
0
// perform FTP CWD command, changes directory
void command_cwd(CLIENT_INFO * client_info)
{
	char line[BUFFER_SIZE] = { 0 };
	client_read_line(client_info->fd, client_info->buf, &client_info->buffer_pos);
	extract_line(line, client_info->buf, &client_info->buffer_pos);
	int len = strlen(line);
	if (len < 5)
	{
		send_code(client_info->fd, 500);
		return;
	}

	char dirbackup[PATH_MAX + 1] = { 0 };
	strncpy(dirbackup, client_info->dir, PATH_MAX);

	char * dir = line + 4;
	if (dir[0] == '/')
	{
		strncpy(client_info->dir, dir, PATH_MAX);
	}
	else
	{
		strncat(client_info->dir, dir, PATH_MAX);
		strncat(client_info->dir, "/", PATH_MAX);
	}

	char dirbuf[PATH_MAX + 1] = { 0 };
	snprintf(dirbuf, PATH_MAX, "%s%s", basedir, client_info->dir);

	char pathbuf[PATH_MAX + 1] = { 0 };
	if (! realpath(dirbuf, pathbuf))
	{
		strncpy(client_info->dir, dirbackup, PATH_MAX);
		send_code(client_info->fd, 550);
		return;
	}

	strncpy(client_info->dir, pathbuf, PATH_MAX);

	if (strlen(client_info->dir) < strlen(basedir))
	{
		strncpy(client_info->dir, dirbackup, PATH_MAX);
		send_code(client_info->fd, 550);
		return;
	}

	memmove(client_info->dir, client_info->dir + strlen(basedir), strlen(client_info->dir) - strlen(basedir) + 1);

	if (client_info->dir[strlen(client_info->dir) - 1] != '/')
		strncat(client_info->dir, "/", PATH_MAX);

	send_code(client_info->fd, 250);
}
Example #3
0
// perform FTP RETR command, sends a file to the client
void command_retr(CLIENT_INFO * client_info)
{
	char line[BUFFER_SIZE] = { 0 };
	client_read_line(client_info->fd, client_info->buf, &client_info->buffer_pos);
	extract_line(line, client_info->buf, &client_info->buffer_pos);
	int len = strlen(line);
	if (len < 6) 
	{
		send_code(client_info->fd, 500);
		return;
	}

	char * filename = line + 5;
	char filenamebuf[PATH_MAX + 1] = { 0 };

	if (filename[0] == '/')
	{
		snprintf(filenamebuf, PATH_MAX, "%s%s", basedir, filename);
	}
	else
	{
		snprintf(filenamebuf, PATH_MAX, "%s%s%s", basedir, client_info->dir, filename);
	}

	int fd = open(filenamebuf, O_RDONLY);
	if (fd == -1)
	{
		// cannot open file
		send_code(client_info->fd, 550);
		return;
	}

	send_code(client_info->fd, 150);
	open_data_connection(client_info);

	while (1)
	{
		char buf[FILE_READ_BUFFER_SIZE];
		int bytes_read = read(fd, buf, FILE_READ_BUFFER_SIZE);
		if (bytes_read == 0) break;
		if (bytes_read == -1) epicfail("read");

		int res = data_connection_write_buffer(client_info, buf, bytes_read);
		if (res == -1) break;
	}

	close(fd);

	close_data_connection(client_info);

	send_code(client_info->fd, 226);
}
Example #4
0
// perform FTP PWD command, prints current directory
void command_pwd(CLIENT_INFO * client_info)
{
	char line[BUFFER_SIZE] = { 0 };
	client_read_line(client_info->fd, client_info->buf, &client_info->buffer_pos);
	extract_line(line, client_info->buf, &client_info->buffer_pos);
	int len = strlen(line);
	if (len != 3)
	{
		send_code(client_info->fd, 500);
		return;
	}

	send_code_param(client_info->fd, 257, client_info->dir);
}
Example #5
0
// perform FTP SYST command, identify as a standard UNIX FTP server
void command_syst(CLIENT_INFO * client_info)
{
	char line[BUFFER_SIZE] = { 0 };
	client_read_line(client_info->fd, client_info->buf, &client_info->buffer_pos);
	extract_line(line, client_info->buf, &client_info->buffer_pos);
	int len = strlen(line);
	if (len != 4)
	{
		send_code(client_info->fd, 500);
		return;
	}

	send_code_param(client_info->fd, 215, "UNIX Type: L8");
}
Example #6
0
// perform FTP USER command, take any username as valid
void command_user(CLIENT_INFO * client_info)
{
	char line[BUFFER_SIZE] = { 0 };
	client_read_line(client_info->fd, client_info->buf, &client_info->buffer_pos);
	extract_line(line, client_info->buf, &client_info->buffer_pos);
	int len = strlen(line);
	if (len < 6)
	{
		send_code(client_info->fd, 500);
		return;
	}

	send_code(client_info->fd, 331);
}
Example #7
0
// perform FTP PASV command, prepare for passive data connection
void command_pasv(CLIENT_INFO * client_info)
{
	char line[BUFFER_SIZE] = { 0 };
	client_read_line(client_info->fd, client_info->buf, &client_info->buffer_pos);
	extract_line(line, client_info->buf, &client_info->buffer_pos);
	int len = strlen(line);
	if (len != 4)
	{
		send_code(client_info->fd, 500);
		return;
	}

	if (client_info->passive_fd != 0) 
	{
		close(client_info->passive_fd);
		client_info->passive_fd = 0;
	}

	struct sockaddr_in s;
	socklen_t l;

	l = sizeof(s);
	getsockname(client_info->fd, (struct sockaddr *)&s, &l);
	char * ip = inet_ntoa(s.sin_addr);
	if (! ip) epicfail("inet_ntoa");

	client_info->data_connection_mode = CONN_MODE_PASSIVE;
	client_info->passive_fd = create_tcp_server_socket(ip, 0);

	l = sizeof(s);
	getsockname(client_info->passive_fd, (struct sockaddr *)&s, &l);
	int port = ntohs(s.sin_port);

	int ip1, ip2, ip3, ip4, port1, port2;
	if (sscanf(ip, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4) != 4) epicfail("command_pasv");
	port1 = port >> 8;
	port2 = port & 0xff;

	char p[64];
	sprintf(p, "%d,%d,%d,%d,%d,%d", ip1, ip2, ip3, ip4, port1, port2);

	send_code_param(client_info->fd, 227, p);
}
Example #8
0
File: client.c Project: azuwis/mpd
static int client_input_received(struct client *client, size_t bytesRead)
{
    char *line;
    int ret;

    fifo_buffer_append(client->input, bytesRead);

    /* process all lines */

    while ((line = client_read_line(client)) != NULL) {
        ret = client_process_line(client, line);
        g_free(line);

        if (ret == COMMAND_RETURN_KILL ||
                ret == COMMAND_RETURN_CLOSE)
            return ret;
        if (client_is_expired(client))
            return COMMAND_RETURN_CLOSE;
    }

    return 0;
}
Example #9
0
// perform FTP PORT command, prepare for active data connection
void command_port(CLIENT_INFO * client_info)
{
	char line[BUFFER_SIZE] = { 0 };
	client_read_line(client_info->fd, client_info->buf, &client_info->buffer_pos);
	extract_line(line, client_info->buf, &client_info->buffer_pos);

	int ip1, ip2, ip3, ip4, port1, port2;
	if (sscanf(line + 5, "%d,%d,%d,%d,%d,%d", &ip1, &ip2, &ip3, &ip4, &port1, &port2) != 6)
	{
		send_code(client_info->fd, 500);
		return;
	}

	client_info->data_connection_mode = CONN_MODE_ACTIVE;

	memset(&(client_info->active_addr), 0, sizeof(client_info->active_addr));
	client_info->active_addr.sin_family = AF_INET;
	char buf_addr[32];
	sprintf(buf_addr, "%d.%d.%d.%d", ip1, ip2, ip3, ip4);
	inet_pton(AF_INET, buf_addr, &(client_info->active_addr.sin_addr));
	client_info->active_addr.sin_port = htons((port1 << 8) + port2);

	send_code(client_info->fd, 200);
}
Example #10
0
// reads a line from the client buffer
void get_line(int fd, char * line, char * buf, int * buffer_pos)
{
	client_read_line(fd, buf, buffer_pos);
	extract_line(line, buf, buffer_pos);
}
Example #11
0
// perform FTP LIST command, sends a directory listing to the client
void command_list(CLIENT_INFO * client_info)
{
	char line[BUFFER_SIZE] = { 0 };
	client_read_line(client_info->fd, client_info->buf, &client_info->buffer_pos);
	extract_line(line, client_info->buf, &client_info->buffer_pos);
	int len = strlen(line);

	char * path = NULL;
	if (len != 4)
	{
		char * p = line + 5;
		if (*p == '-')
		{
			while (*p && (*p != ' ')) p++;
		}

		while (*p && (*p == ' ')) p++;
		path = p;
	}

	char dirbuf[PATH_MAX + 1] = { 0 };
	snprintf(dirbuf, PATH_MAX, "%s%s", basedir, client_info->dir);

	if (path)
	{
		if (path[0] == '/')
		{
			snprintf(dirbuf, PATH_MAX, "%s%s", basedir, path);
		}
		else
		{
			strcat(dirbuf, "/");
			strcat(dirbuf, path);
		}
	}

	char realpathbuf[PATH_MAX + 1] = { 0 };
	if (! realpath(dirbuf, realpathbuf))
	{
		send_code(client_info->fd, 550);
		return;
	}

	strcpy(dirbuf, realpathbuf);

	if (dirbuf[strlen(dirbuf) - 1] != '/')
		strncat(dirbuf, "/", PATH_MAX);

	DIR * dirp = opendir(dirbuf);
	if (! dirp)
	{
		send_code(client_info->fd, 550);
		return;
	}

	send_code(client_info->fd, 150);
	open_data_connection(client_info);

	while (1)
	{
		struct dirent * entry = readdir(dirp);
		if (! entry) break;

		char filenamebuf[PATH_MAX + 1] = { 0 };
		snprintf(filenamebuf, PATH_MAX, "%s%s", dirbuf, entry->d_name);

		struct stat s;
		if (stat(filenamebuf, &s) == -1)
		{
			// cannot stat
			continue;
		}

		char buf[PATH_MAX + 128 + 1] = { 0 };
		strmode(s.st_mode, buf);
		unsigned int size = (unsigned int)s.st_size;
		char date[64];
		struct tm * ts = localtime(&s.st_mtime);
		strftime(date, 64, "%b %e  %Y", ts);
		sprintf(buf + 11, "%3d %-8d %-8d %8u %s %s\r\n", s.st_nlink, (int)s.st_uid, (int)s.st_gid, size, date, entry->d_name);
		data_connection_write_string(client_info, buf);
	}

	close_data_connection(client_info);

	send_code(client_info->fd, 226);
}