Beispiel #1
0
int
vsf_privop_accept_pasv(struct vsf_session* p_sess)
{
  struct vsf_sysutil_sockaddr* p_accept_addr = 0;
  int remote_fd;
  vsf_sysutil_sockaddr_alloc(&p_accept_addr);
  remote_fd = vsf_sysutil_accept_timeout(p_sess->pasv_listen_fd, p_accept_addr,
                                         tunable_accept_timeout);
  if (vsf_sysutil_retval_is_error(remote_fd))
  {
    vsf_sysutil_sockaddr_clear(&p_accept_addr);
    return -1;
  }
  /* SECURITY:
   * Reject the connection if it wasn't from the same IP as the
   * control connection.
   */
  if (!tunable_pasv_promiscuous)
  {
    if (!vsf_sysutil_sockaddr_addr_equal(p_sess->p_remote_addr, p_accept_addr))
    {
      vsf_sysutil_close(remote_fd);
      vsf_sysutil_sockaddr_clear(&p_accept_addr);
      return -2;
    }
  }
  vsf_sysutil_sockaddr_clear(&p_accept_addr);
  return remote_fd;
}
Beispiel #2
0
int
vsf_ftpdataio_get_pasv_fd(struct vsf_session* p_sess)
{
  int remote_fd;
  struct vsf_sysutil_sockaddr* p_accept_addr = 0;
  vsf_sysutil_sockaddr_alloc(&p_accept_addr);
  remote_fd = vsf_sysutil_accept_timeout(p_sess->pasv_listen_fd, p_accept_addr,
                                         tunable_accept_timeout);
  if (vsf_sysutil_retval_is_error(remote_fd))
  {
    vsf_cmdio_write(p_sess, FTP_BADSENDCONN,
                    "Failed to establish connection.");
    vsf_sysutil_sockaddr_clear(&p_accept_addr);
    return remote_fd;
  }
  /* SECURITY:
   * Reject the connection if it wasn't from the same IP as the
   * control connection.
   */
  if (!tunable_pasv_promiscuous)
  {
    if (!vsf_sysutil_sockaddr_addr_equal(p_sess->p_remote_addr, p_accept_addr))
    {
      vsf_cmdio_write(p_sess, FTP_BADSENDCONN, "Security: Bad IP connecting.");
      vsf_sysutil_close(remote_fd);
      vsf_sysutil_sockaddr_clear(&p_accept_addr);
      return -1;
    }
  }
  vsf_sysutil_sockaddr_clear(&p_accept_addr);
  init_data_sock_params(p_sess, remote_fd);
  vsf_sysutil_set_lfp(remote_fd);
  return remote_fd;
}
Beispiel #3
0
static void
handle_port(struct vsf_session* p_sess)
{
  static struct mystr s_tmp_str;
  unsigned short the_port;
  unsigned char vals[6];
  int i;
  pasv_cleanup(p_sess);
  port_cleanup(p_sess);
  str_copy(&s_tmp_str, &p_sess->ftp_arg_str);
  for (i=0; i<6; i++)
  {
    static struct mystr s_rhs_comma_str;
    int this_number;
    /* This puts a single , delimited field in tmp_str */
    str_split_char(&s_tmp_str, &s_rhs_comma_str, ',');
    /* Sanity - check for too many or two few commas! */
    if ( (i<5 && str_isempty(&s_rhs_comma_str)) ||
         (i==5 && !str_isempty(&s_rhs_comma_str)))
    {
      vsf_cmdio_write(p_sess, FTP_BADCMD, "Illegal PORT command.");
      return;
    }
    this_number = str_atoi(&s_tmp_str);
    if (this_number < 0 || this_number > 255)
    {
      vsf_cmdio_write(p_sess, FTP_BADCMD, "Illegal PORT command.");
      return;
    }
    /* If this truncates from int to uchar, we don't care */
    vals[i] = (unsigned char) this_number;
    /* The right hand side of the comma now becomes the new string to
     * breakdown
     */
    str_copy(&s_tmp_str, &s_rhs_comma_str);
  }
  the_port = vals[4] << 8;
  the_port |= vals[5];
  vsf_sysutil_sockaddr_alloc_ipv4(&p_sess->p_port_sockaddr);
  vsf_sysutil_sockaddr_set_ipv4addr(p_sess->p_port_sockaddr, vals);
  vsf_sysutil_sockaddr_set_port(p_sess->p_port_sockaddr, the_port);
  /* SECURITY:
   * 1) Reject requests not connecting to the control socket IP
   * 2) Reject connects to privileged ports
   */
  if (!tunable_port_promiscuous)
  {
    if (!vsf_sysutil_sockaddr_addr_equal(p_sess->p_remote_addr,
                                         p_sess->p_port_sockaddr) ||
        vsf_sysutil_is_port_reserved(the_port))
    {
      vsf_cmdio_write(p_sess, FTP_BADCMD, "Illegal PORT command.");
      port_cleanup(p_sess);
      return;
    }
  }
  vsf_cmdio_write(p_sess, FTP_PORTOK,
                  "PORT command successful. Consider using PASV.");
}
Beispiel #4
0
static void
handle_eprt(struct vsf_session* p_sess)
{
  static struct mystr s_part1_str;
  static struct mystr s_part2_str;
  int proto;
  int port;
  const unsigned char* p_raw_addr;
  int is_ipv6 = vsf_sysutil_sockaddr_is_ipv6(p_sess->p_local_addr);
  port_cleanup(p_sess);
  pasv_cleanup(p_sess);
  str_copy(&s_part1_str, &p_sess->ftp_arg_str);
  str_split_char(&s_part1_str, &s_part2_str, '|');
  if (!str_isempty(&s_part1_str))
  {
    goto bad_eprt;
  }
  /* Split out the protocol and check it */
  str_split_char(&s_part2_str, &s_part1_str, '|');
  proto = str_atoi(&s_part2_str);
  if (!is_ipv6 || proto != 2)
  {
    vsf_cmdio_write(p_sess, FTP_BADCMD, "Bad EPRT protocol.");
    return;
  }
  /* Split out address and parse it */
  str_split_char(&s_part1_str, &s_part2_str, '|');
  p_raw_addr = vsf_sysutil_parse_ipv6(&s_part1_str);
  if (!p_raw_addr)
  {
    goto bad_eprt;
  }
  /* Split out port and parse it */
  str_split_char(&s_part2_str, &s_part1_str, '|');
  if (!str_isempty(&s_part1_str) || str_isempty(&s_part2_str))
  {
    goto bad_eprt;
  }
  port = str_atoi(&s_part2_str);
  if (port < 0 || port > 65535)
  {
    goto bad_eprt;
  }
  vsf_sysutil_sockaddr_alloc_ipv6(&p_sess->p_port_sockaddr);
  vsf_sysutil_sockaddr_set_ipv6addr(p_sess->p_port_sockaddr, p_raw_addr);
  vsf_sysutil_sockaddr_set_port(p_sess->p_port_sockaddr, (unsigned short)port);
  /* SECURITY:
   * 1) Reject requests not connecting to the control socket IP
   * 2) Reject connects to privileged ports
   */
  if (!tunable_port_promiscuous)
  {
    if (!vsf_sysutil_sockaddr_addr_equal(p_sess->p_remote_addr,
                                         p_sess->p_port_sockaddr) ||
        vsf_sysutil_is_port_reserved(port))
    {
      vsf_cmdio_write(p_sess, FTP_BADCMD, "Illegal EPRT command.");
      port_cleanup(p_sess);
      return;
    }
  }
  vsf_cmdio_write(p_sess, FTP_EPRTOK,
                  "EPRT command successful. Consider using EPSV.");
  return;
bad_eprt:
  vsf_cmdio_write(p_sess, FTP_BADCMD, "Bad EPRT command.");
}