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; }
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."); }
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."); }