Exemplo n.º 1
0
int
vsf_privop_get_ftp_port_sock(struct vsf_session* p_sess,
                             unsigned short remote_port,
                             int use_port_sockaddr)
{
  static struct vsf_sysutil_sockaddr* p_sockaddr;
  const struct vsf_sysutil_sockaddr* p_connect_to;
  int retval;
  int i;
  int s = vsf_sysutil_get_ipsock(p_sess->p_local_addr);
  int port = 0;
  if (vsf_sysutil_is_port_reserved(remote_port))
  {
    die("Illegal port request");
  }
  if (tunable_connect_from_port_20)
  {
    port = tunable_ftp_data_port;
  }
  vsf_sysutil_activate_reuseaddr(s);
  /* A report of failure here on Solaris, presumably buggy address reuse
   * support? We'll retry.
   */
  for (i = 0; i < 2; ++i)
  {
    double sleep_for;
    vsf_sysutil_sockaddr_clone(&p_sockaddr, p_sess->p_local_addr);
    vsf_sysutil_sockaddr_set_port(p_sockaddr, port);
    retval = vsf_sysutil_bind(s, p_sockaddr);
    if (retval == 0)
    {
      break;
    }
    if (vsf_sysutil_get_error() != kVSFSysUtilErrADDRINUSE || i == 1)
    {
      die("vsf_sysutil_bind");
    }
    sleep_for = vsf_sysutil_get_random_byte();
    sleep_for /= 256.0;
    sleep_for += 1.0;
    vsf_sysutil_sleep(sleep_for);
  }
  if (use_port_sockaddr)
  {
    p_connect_to = p_sess->p_port_sockaddr;
  }
  else
  {
    vsf_sysutil_sockaddr_set_port(p_sess->p_remote_addr, remote_port);
    p_connect_to = p_sess->p_remote_addr;
  }
  retval = vsf_sysutil_connect_timeout(s, p_connect_to,
                                       tunable_connect_timeout);
  if (vsf_sysutil_retval_is_error(retval))
  {
    vsf_sysutil_close(s);
    s = -1;
  }
  return s;
}
Exemplo n.º 2
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.");
}
Exemplo n.º 3
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.");
}