Пример #1
0
int
ftp_write_str(const struct vsf_session* p_sess, const struct mystr* p_str,
              enum EVSFRWTarget target)
{
  if (target == kVSFRWData)
  {
    if (p_sess->data_use_ssl)
    {
      return ssl_write_str(p_sess->p_data_ssl, p_str);
    }
    else
    {
      return str_netfd_write(p_str, p_sess->data_fd);
    }
  }
  else
  {
    if (p_sess->control_use_ssl && p_sess->ssl_slave_active)
    {
      priv_sock_send_cmd(p_sess->ssl_consumer_fd, PRIV_SOCK_WRITE_USER_RESP);
      priv_sock_send_str(p_sess->ssl_consumer_fd, p_str);
      return priv_sock_get_int(p_sess->ssl_consumer_fd);
    }
    else if (p_sess->control_use_ssl)
    {
      return ssl_write_str(p_sess->p_control_ssl, p_str);
    }
    else
    {
      return str_netfd_write(p_str, VSFTP_COMMAND_FD);
    }
  }
}
Пример #2
0
int
ftp_getline(struct vsf_session* p_sess, struct mystr* p_str, char* p_buf)
{
    if (p_sess->control_use_ssl && p_sess->ssl_slave_active)
    {
        int ret;
        priv_sock_send_cmd(p_sess->ssl_consumer_fd, PRIV_SOCK_GET_USER_CMD);
        ret = priv_sock_get_int(p_sess->ssl_consumer_fd);
        if (ret >= 0)
        {
            priv_sock_get_str(p_sess->ssl_consumer_fd, p_str);
        }
        return ret;
    }
    else
    {
        str_netfd_read_t p_peek = plain_peek_adapter;
        str_netfd_read_t p_read = plain_read_adapter;
        if (p_sess->control_use_ssl)
        {
            p_peek = ssl_peek_adapter;
            p_read = ssl_read_adapter;
        }
        return str_netfd_alloc(p_sess,
                               p_str,
                               '\n',
                               p_buf,
                               VSFTP_MAX_COMMAND_LINE,
                               p_peek,
                               p_read);
    }
}
Пример #3
0
static void privop_pasv_get_data_sock(session_t *sess)
{
    unsigned short port = (unsigned short)priv_sock_get_int(sess->parent_fd);
    char ip[16] = {0};
    priv_sock_recv_buf(sess->parent_fd, ip, sizeof(ip));
    printf("privop_pasv_get_data_sock port=%u and ip=%s\n", port, ip);
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = inet_addr(ip);

    int fd = tcp_client(20);
    if(fd == -1)
    {
        printf("aaaaaaaaaaaaaaaaaaa\n");
        priv_sock_send_result(sess->parent_fd, PRIV_SOCK_RESULT_BAD);
        return;
    }
    socklen_t len = sizeof(struct sockaddr_in);;
    if(connect(fd, (struct sockaddr*)&addr, len) < 0)
    {
        printf("bbbbbbbbbbbbbbbbb\n");
        ERR_EXIT("ccccconect");
        close(fd);
        priv_sock_send_result(sess->parent_fd, PRIV_SOCK_RESULT_BAD);
        ERR_EXIT("connect");
        return;
    }

    priv_sock_send_result(sess->parent_fd, PRIV_SOCK_RESULT_OK);
    priv_sock_send_fd(sess->parent_fd, fd);
    close(fd);
}
Пример #4
0
void priv_sock_recv_buf(int fd, char *buf, unsigned int len)
{
	unsigned int recv_len = (unsigned int)priv_sock_get_int(fd);
	if (recv_len > len)
	{
		FTPD_LOG(ERROR,"priv_sock_recv_buf error\n");
	}

	int ret = sysutil::readn(fd, buf, recv_len);
	if (ret != (int)recv_len)
	{
		FTPD_LOG(ERROR,"priv_sock_recv_buf error\n");
	}
}
Пример #5
0
int pasv_active(session_t* sess)
{
	priv_sock_send_cmd(sess->child_fd, PRIV_SOCK_PASV_ACTIVE);
	int active = priv_sock_get_int(sess->child_fd);
	
	if(active)
	{
		if(port_active(sess))
                {
                        fprintf(stderr, "both port and pasv are active");
                        exit(EXIT_FAILURE);
                }
                return 1;
	}
	return 0;
}
int
vsf_two_process_get_pasv_fd(struct vsf_session* p_sess)
{
  char res;
  priv_sock_send_cmd(p_sess->child_fd, PRIV_SOCK_PASV_ACCEPT);
  res = priv_sock_get_result(p_sess->child_fd);
  if (res == PRIV_SOCK_RESULT_BAD)
  {
    return priv_sock_get_int(p_sess->child_fd);
  }
  else if (res != PRIV_SOCK_RESULT_OK)
  {
    die("could not accept on listening socket");
  }
  return priv_sock_recv_fd(p_sess->child_fd);
}
Пример #7
0
void priv_sock_recv_buf(int fd, char *buf, unsigned int len)
{
    unsigned int recv_len = (unsigned int)priv_sock_get_int(fd);
    if (recv_len > len)
    {
        fprintf(stderr, "priv_sock_recv_buf error\n");
        exit(EXIT_FAILURE);
    }

    int ret = readn(fd, buf, recv_len);
    if (ret != (int)recv_len)
    {
        fprintf(stderr, "priv_sock_recv_buf error\n");
        exit(EXIT_FAILURE);
    }
}
Пример #8
0
static void do_pasv(session_t *sess)
{
	char ip[16] = {0};
	getlocalip(ip);

	priv_sock_send_cmd(sess->child_fd, PRIV_SOCK_PASV_LISTEN);
	unsigned short port = (unsigned short)priv_sock_get_int(sess->child_fd);

	unsigned int v[4];
	sscanf(ip, "%u.%u.%u.%u", &v[0], &v[1], &v[2], &v[3]);

	char text[1024] = {0};
	sprintf(text, "Entering Passive Mode (%u,%u,%u,%u,%u,%u).", 
	v[0], v[1], v[2], v[3], port >> 8, port & 0xFF);		
	
	ftp_reply(sess, FTP_PASVOK, text);
}
Пример #9
0
int pasv_active(session_t *pses)
{
    //向nobody进程发送命令,看看是否创建了监听套接字,如果是,被动模式处于激活状态
    priv_sock_send_cmd(pses->child_fd, PRIV_SOCK_PASV_ACTIVE);
    int iret = priv_sock_get_int(pses->child_fd);

    if(iret != -1)
    {
        if(port_active(pses) == 0) //主被动模式不能同时处于激活状态
        {
            handle_error_str("both port and pasv are active.");
        }
        return 0;
    }
    else
    {
        return -1;
    }
}
Пример #10
0
/**
 * 创建数据连接通道
 * @param sess [description]
 */
void PrivPar::privop_pasv_get_data_sock(session_t *sess)
{
	/*
	nobody进程接收PRIV_SOCK_GET_DATA_SOCK命令
进一步接收一个整数,也就是port
接收一个字符串,也就是ip

fd = socket 
bind(20)
connect(ip, port);

OK
send_fd
BAD
*/
	unsigned short port = (unsigned short)priv_sock_get_int(sess->parent_fd);
	char ip[16] = {0};
	priv_sock_recv_buf(sess->parent_fd, ip, sizeof(ip));
	//从ftp服务进程获取IP地址
	struct sockaddr_in addr;
	memset(&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = inet_addr(ip);

	int fd = sysutil::tcp_client(20);
	if (fd == -1)
	{
		priv_sock_send_result(sess->parent_fd, PRIV_SOCK_RESULT_BAD);
		return;
	}
	if (sysutil::connect_timeout(fd, &addr, parseconfig->get_accept_timeout()) < 0)
	{
		close(fd);
		priv_sock_send_result(sess->parent_fd, PRIV_SOCK_RESULT_BAD);
		return;
	}

	priv_sock_send_result(sess->parent_fd, PRIV_SOCK_RESULT_OK);
	priv_sock_send_fd(sess->parent_fd, fd);
	close(fd);
}
Пример #11
0
int
ftp_read_data(struct vsf_session* p_sess, char* p_buf, unsigned int len)
{
    if (p_sess->data_use_ssl && p_sess->ssl_slave_active)
    {
        int ret;
        priv_sock_send_cmd(p_sess->ssl_consumer_fd, PRIV_SOCK_DO_SSL_READ);
        ret = priv_sock_get_int(p_sess->ssl_consumer_fd);
        priv_sock_recv_buf(p_sess->ssl_consumer_fd, p_buf, len);
        /* Need to do this here too because it is useless in the slave process. */
        vsf_sysutil_check_pending_actions(kVSFSysUtilIO, ret, p_sess->data_fd);
        return ret;
    }
    else if (p_sess->data_use_ssl)
    {
        return ssl_read(p_sess, p_sess->p_data_ssl, p_buf, len);
    }
    else
    {
        return vsf_sysutil_read(p_sess->data_fd, p_buf, len);
    }
}
Пример #12
0
static void privop_pasv_get_data_sock(session_t *sess)
{
	/*
		socket
		bind 20
		connect
		*/
		// tcp_client(20);
		/*
	*/
	char ip[16] = {0};
	unsigned short port = (unsigned short)priv_sock_get_int(sess->parent_fd);
	priv_sock_recv_buf(sess->parent_fd, ip, sizeof(ip));
	
	struct sockaddr_in addr;
	memset(&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = inet_addr(ip);
	
	int fd = tcp_client(20);
	if (fd == -1) 
	{
		priv_sock_send_result(sess->parent_fd, PRIV_SOCK_RESULT_BAD);
		return;
	}
	
	if (connect_timeout(fd, &addr, tunable_connect_timeout) < 0)
	{
		close(fd);
		priv_sock_send_result(sess->parent_fd, PRIV_SOCK_RESULT_BAD);
		return;
	}
	
	priv_sock_send_result(sess->parent_fd, PRIV_SOCK_RESULT_OK);
	priv_sock_send_fd(sess->parent_fd, fd);
	close(fd);
}
Пример #13
0
void do_cmd_pasv(session_t *pses)
{
    char localip[16] = {0};
    if(getlocalip(localip) < 0)
    {
        handle_error("getlocalip");
    }


    //向nobody进程发送请求
    priv_sock_send_cmd(pses->child_fd, PRIV_SOCK_PASV_LISTEN);
    //接收nobody进程返回的端口号
    unsigned short port = (unsigned short)priv_sock_get_int(pses->child_fd);

    unsigned int v[4] = {0};
    sscanf(localip, "%u.%u.%u.%u",&v[0],&v[1],&v[2],&v[3]);
    char iptext[1024] = {0};
    sprintf(iptext, "Entering Passive Mode (%u,%u,%u,%u,%u,%u).",
            v[0],v[1],v[2],v[3],port>>8,port & 0xFF);

    ftp_reply(pses->ctrl_fd, FTP_PASVOK, iptext);

}
Пример #14
0
static void privop_port_get_data_sock(session_t *sess)
{
	unsigned short port = (unsigned short)priv_sock_get_int(sess->nobody_fd);
	char ip[20] = {0};
	priv_sock_recv_buf(sess->nobody_fd, ip, sizeof(ip));

	struct sockaddr_in addr;
	memset(&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = inet_addr(ip);

// 当多个客户端连接服务器时,可以同时有多个nobody进程bind 20端口+ip,因为此时客户端给出的端口是随机的,故
// 四元组还是能识别一个数据连接
// 当客户端位于NAT服务器之后使用PORT模式时,需要在NAT服务器上配置映射才能让服务器主动连接到客户端
// 所以采用的是标准固定的20端口,这样NAT服务器就不用维护很多的表目
	int fd = tcp_client(20);
	if (fd == -1)
	{
		priv_sock_send_result(sess->nobody_fd, PRIV_SOCK_RESULT_BAD);
		return;
	}

	if (connect_timeout(fd, &addr, tunable_connect_timeout) < 0)
	{
		close(fd);
		priv_sock_send_result(sess->nobody_fd, PRIV_SOCK_RESULT_BAD);
		return;
	}

	priv_sock_send_result(sess->nobody_fd, PRIV_SOCK_RESULT_OK);
	priv_sock_send_fd(sess->nobody_fd, fd);
	close(fd); //父进程必须close(fd),否则子进程关闭close(data_fd)的时候也不会发送FIN段。
	//因为通过unix域协议传递套接字等于是对方也打开套接字,而直接简单的赋值是没有这样的效果的。

}
int
vsf_two_process_pasv_active(struct vsf_session* p_sess)
{
  priv_sock_send_cmd(p_sess->child_fd, PRIV_SOCK_PASV_ACTIVE);
  return priv_sock_get_int(p_sess->child_fd);
}
unsigned short
vsf_two_process_listen(struct vsf_session* p_sess)
{
  priv_sock_send_cmd(p_sess->child_fd, PRIV_SOCK_PASV_LISTEN);
  return (unsigned short) priv_sock_get_int(p_sess->child_fd);
}
static void
process_login_req(struct vsf_session* p_sess)
{
  enum EVSFPrivopLoginResult e_login_result = kVSFLoginNull;
  char cmd;
  /* Blocks */
  cmd = priv_sock_get_cmd(p_sess->parent_fd);
  if (cmd != PRIV_SOCK_LOGIN)
  {
    die("bad request");
  }
  /* Get username and password - we must distrust these */
  {
    struct mystr password_str = INIT_MYSTR;
    priv_sock_get_str(p_sess->parent_fd, &p_sess->user_str);
    priv_sock_get_str(p_sess->parent_fd, &password_str);
    p_sess->control_use_ssl = priv_sock_get_int(p_sess->parent_fd);
    p_sess->data_use_ssl = priv_sock_get_int(p_sess->parent_fd);
    if (!tunable_ssl_enable)
    {
      p_sess->control_use_ssl = 0;
      p_sess->data_use_ssl = 0;
    }
    e_login_result = vsf_privop_do_login(p_sess, &password_str);
    str_free(&password_str);
  }
  switch (e_login_result)
  {
    case kVSFLoginFail:
      priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_BAD);
      return;
      break;
    case kVSFLoginAnon:
      str_alloc_text(&p_sess->user_str, tunable_ftp_username);
      common_do_login(p_sess, &p_sess->user_str, 1, 1);
      break;
    case kVSFLoginReal:
      {
        int do_chroot = 0;
        if (tunable_chroot_local_user)
        {
          do_chroot = 1;
        }
        if (tunable_chroot_list_enable)
        {
          struct mystr chroot_list_file = INIT_MYSTR;
          int retval = str_fileread(&chroot_list_file,
                                    tunable_chroot_list_file,
                                    VSFTP_CONF_FILE_MAX);
          if (vsf_sysutil_retval_is_error(retval))
          {
            die2("could not read chroot() list file:",
                 tunable_chroot_list_file);
          }
          if (str_contains_line(&chroot_list_file, &p_sess->user_str))
          {
            if (do_chroot)
            {
              do_chroot = 0;
            }
            else
            {
              do_chroot = 1;
            }
          }
          str_free(&chroot_list_file);
        }
        common_do_login(p_sess, &p_sess->user_str, do_chroot, 0);
      }
      break;
    case kVSFLoginNull:
      /* Fall through */
    default:
      bug("weird state in process_login_request");
      break;
  }
  /* NOTREACHED */
}