diff -up vsftpd-2.2.2/logging.h.dyn_host vsftpd-2.2.2/logging.h --- vsftpd-2.2.2/logging.h.dyn_host 2010-11-15 10:37:44.767026001 -0700 +++ vsftpd-2.2.2/logging.h 2010-11-19 22:06:32.516919272 -0700 @@ -20,6 +20,7 @@ enum EVSFLogEntryType kVSFLogEntryRmdir, kVSFLogEntryChmod, kVSFLogEntryDebug, + kVSFLogEntryDNSResolve, }; /* vsf_log_init() diff -up vsftpd-2.2.2/logging.c.dyn_host vsftpd-2.2.2/logging.c --- vsftpd-2.2.2/logging.c.dyn_host 2010-11-15 10:37:44.764025999 -0700 +++ vsftpd-2.2.2/logging.c 2010-11-20 00:10:10.500009753 -0700 @@ -330,6 +330,9 @@ vsf_log_do_log_vsftpd_format(struct vsf_ case kVSFLogEntryDebug: str_append_text(p_str, "DEBUG"); break; + case kVSFLogEntryDNSResolve: + str_append_text(p_str, "RESOLVE"); + break; default: bug("bad entry_type in vsf_log_do_log"); break; diff -up vsftpd-2.2.2/main.c.dyn_host vsftpd-2.2.2/main.c --- vsftpd-2.2.2/main.c.dyn_host 2009-07-17 22:55:53.000000000 -0700 +++ vsftpd-2.2.2/main.c 2010-11-28 09:13:23.646374366 -0700 @@ -118,16 +118,10 @@ main(int argc, const char* argv[]) } vsf_sysutil_free(p_statbuf); } - /* Resolve pasv_address if required */ - if (tunable_pasv_address && tunable_pasv_addr_resolve) + /* Get hostname from address field if specified */ + if (tunable_pasv_address && tunable_pasv_addr_resolve && !tunable_pasv_hostname) { - struct vsf_sysutil_sockaddr* p_addr = 0; - const char* p_numeric_addr; - vsf_sysutil_dns_resolve(&p_addr, tunable_pasv_address); - vsf_sysutil_free((char*) tunable_pasv_address); - p_numeric_addr = vsf_sysutil_inet_ntop(p_addr); - tunable_pasv_address = vsf_sysutil_strdup(p_numeric_addr); - vsf_sysutil_free(p_addr); + tunable_pasv_hostname = vsf_sysutil_strdup(tunable_pasv_address); } if (!tunable_run_as_launching_user) { diff -up vsftpd-2.2.2/parseconf.c.dyn_host vsftpd-2.2.2/parseconf.c --- vsftpd-2.2.2/parseconf.c.dyn_host 2010-11-15 10:37:44.806026001 -0700 +++ vsftpd-2.2.2/parseconf.c 2010-11-16 01:04:22.097017567 -0700 @@ -91,6 +91,7 @@ parseconf_bool_array[] = { "mdtm_write", &tunable_mdtm_write }, { "lock_upload_files", &tunable_lock_upload_files }, { "pasv_addr_resolve", &tunable_pasv_addr_resolve }, + { "pasv_addr_dynamic", &tunable_pasv_addr_dynamic }, { "userlist_log", &tunable_userlist_log }, { "debug_ssl", &tunable_debug_ssl }, { "require_cert", &tunable_require_cert }, @@ -161,6 +162,7 @@ parseconf_str_array[] = { "local_root", &tunable_local_root }, { "banner_file", &tunable_banner_file }, { "pasv_address", &tunable_pasv_address }, + { "pasv_hostname", &tunable_pasv_hostname }, { "listen_address", &tunable_listen_address }, { "user_config_dir", &tunable_user_config_dir }, { "listen_address6", &tunable_listen_address6 }, diff -up vsftpd-2.2.2/postlogin.c.dyn_host vsftpd-2.2.2/postlogin.c --- vsftpd-2.2.2/postlogin.c.dyn_host 2009-11-06 21:55:12.000000000 -0700 +++ vsftpd-2.2.2/postlogin.c 2010-12-13 18:10:09.079196225 -0700 @@ -62,7 +62,6 @@ static void handle_logged_in_user(struct static void handle_logged_in_pass(struct vsf_session* p_sess); static int pasv_active(struct vsf_session* p_sess); -static int port_active(struct vsf_session* p_sess); static void pasv_cleanup(struct vsf_session* p_sess); static void port_cleanup(struct vsf_session* p_sess); static void handle_dir_common(struct vsf_session* p_sess, int full_details, @@ -484,21 +483,6 @@ handle_cdup(struct vsf_session* p_sess) } static int -port_active(struct vsf_session* p_sess) -{ - int ret = 0; - if (p_sess->p_port_sockaddr != 0) - { - ret = 1; - if (pasv_active(p_sess)) - { - bug("port and pasv both active"); - } - } - return ret; -} - -static int pasv_active(struct vsf_session* p_sess) { int ret = 0; @@ -512,7 +496,7 @@ pasv_active(struct vsf_session* p_sess) } if (ret) { - if (port_active(p_sess)) + if (p_sess->p_port_sockaddr != 0) { bug("pasv and port both active"); } @@ -544,7 +528,7 @@ handle_pasv(struct vsf_session* p_sess, { unsigned short the_port; static struct mystr s_pasv_res_str; - static struct vsf_sysutil_sockaddr* s_p_sockaddr; + static struct vsf_sysutil_sockaddr* s_p_sockaddr = 0; int is_ipv6 = vsf_sysutil_sockaddr_is_ipv6(p_sess->p_local_addr); if (is_epsv && !str_isempty(&p_sess->ftp_arg_str)) { @@ -581,18 +565,37 @@ handle_pasv(struct vsf_session* p_sess, vsf_cmdio_write_str(p_sess, FTP_EPSVOK, &s_pasv_res_str); return; } - if (tunable_pasv_address != 0) + if (s_p_sockaddr == 0) { - vsf_sysutil_sockaddr_alloc_ipv4(&s_p_sockaddr); - /* Report passive address as specified in configuration */ - if (vsf_sysutil_inet_aton(tunable_pasv_address, s_p_sockaddr) == 0) + vsf_sysutil_sockaddr_clear(&s_p_sockaddr); + if (tunable_pasv_hostname) + { + vsf_sysutil_host_resolve(p_sess, &s_p_sockaddr); + } + else { - die("invalid pasv_address"); + if (tunable_pasv_address != 0) + { + vsf_sysutil_sockaddr_alloc_ipv4(&s_p_sockaddr); + /* Report passive address as specified in configuration */ + if (vsf_sysutil_inet_aton(tunable_pasv_address, s_p_sockaddr) == 0) + { + /* log message "invalid pasv_address, using default" */ + vsf_sysutil_sockaddr_clone(&s_p_sockaddr, p_sess->p_local_addr); + } + } + else + { + vsf_sysutil_sockaddr_clone(&s_p_sockaddr, p_sess->p_local_addr); + } } } else { - vsf_sysutil_sockaddr_clone(&s_p_sockaddr, p_sess->p_local_addr); + if (tunable_pasv_addr_dynamic) + { + vsf_sysutil_host_resolve(p_sess, &s_p_sockaddr); + } } str_alloc_text(&s_pasv_res_str, "Entering Passive Mode ("); if (!is_ipv6) @@ -1378,7 +1381,7 @@ static int get_remote_transfer_fd(struct vsf_session* p_sess, const char* p_status_msg) { int remote_fd; - if (!pasv_active(p_sess) && !port_active(p_sess)) + if (!pasv_active(p_sess) && p_sess->p_port_sockaddr == 0) { bug("neither PORT nor PASV active in get_remote_transfer_fd"); } @@ -1828,7 +1831,7 @@ handle_stat_file(struct vsf_session* p_s static int data_transfer_checks_ok(struct vsf_session* p_sess) { - if (!pasv_active(p_sess) && !port_active(p_sess)) + if (!pasv_active(p_sess) && p_sess->p_port_sockaddr == 0) { vsf_cmdio_write(p_sess, FTP_BADSENDCONN, "Use PORT or PASV first."); return 0; diff -up vsftpd-2.2.2/sysutil.h.dyn_host vsftpd-2.2.2/sysutil.h --- vsftpd-2.2.2/sysutil.h.dyn_host 2010-11-15 10:37:45.015026001 -0700 +++ vsftpd-2.2.2/sysutil.h 2010-11-29 08:43:42.901802833 -0700 @@ -261,8 +261,9 @@ int vsf_sysutil_accept_timeout(int fd, s int vsf_sysutil_connect_timeout(int fd, const struct vsf_sysutil_sockaddr* p_sockaddr, unsigned int wait_seconds); -void vsf_sysutil_dns_resolve(struct vsf_sysutil_sockaddr** p_sockptr, - const char* p_name); +struct vsf_session; +void vsf_sysutil_host_resolve(struct vsf_session* p_sess, + struct vsf_sysutil_sockaddr** p_sockptr); /* Option setting on sockets */ void vsf_sysutil_v6only(int fd); void vsf_sysutil_activate_keepalive(int fd); diff -up vsftpd-2.2.2/sysutil.c.dyn_host vsftpd-2.2.2/sysutil.c --- vsftpd-2.2.2/sysutil.c.dyn_host 2010-11-15 10:37:45.012025999 -0700 +++ vsftpd-2.2.2/sysutil.c 2010-12-14 10:48:18.796665459 -0700 @@ -16,6 +16,8 @@ #include "utility.h" #include "tunables.h" #include "sysdeputil.h" +#include "logging.h" +#include "str.h" /* Activate 64-bit file support on Linux/32bit plus others */ #define _FILE_OFFSET_BITS 64 @@ -2261,40 +2263,58 @@ vsf_sysutil_inet_aton(const char* p_text } void -vsf_sysutil_dns_resolve(struct vsf_sysutil_sockaddr** p_sockptr, - const char* p_name) +vsf_sysutil_host_resolve(struct vsf_session* p_sess, + struct vsf_sysutil_sockaddr** p_sockptr) { - struct hostent* hent = gethostbyname(p_name); + struct hostent* hent = gethostbyname(tunable_pasv_hostname); if (hent == NULL) { - die2("cannot resolve host:", p_name); - } - vsf_sysutil_sockaddr_clear(p_sockptr); - if (hent->h_addrtype == AF_INET) - { - unsigned int len = hent->h_length; - if (len > sizeof((*p_sockptr)->u.u_sockaddr_in.sin_addr)) + struct mystr str_log_line = INIT_MYSTR; + str_alloc_text(&str_log_line, "cannot resolve host:"); + str_append_text(&str_log_line, tunable_pasv_hostname); + str_append_text(&str_log_line, ", using:"); + if (tunable_pasv_address) { - len = sizeof((*p_sockptr)->u.u_sockaddr_in.sin_addr); + str_append_text(&str_log_line, tunable_pasv_address); } - vsf_sysutil_sockaddr_alloc_ipv4(p_sockptr); - vsf_sysutil_memcpy(&(*p_sockptr)->u.u_sockaddr_in.sin_addr, - hent->h_addr_list[0], len); - } - else if (hent->h_addrtype == AF_INET6) - { - unsigned int len = hent->h_length; - if (len > sizeof((*p_sockptr)->u.u_sockaddr_in6.sin6_addr)) + else { - len = sizeof((*p_sockptr)->u.u_sockaddr_in6.sin6_addr); + str_append_text(&str_log_line, "default (incoming socket address)"); } - vsf_sysutil_sockaddr_alloc_ipv6(p_sockptr); - vsf_sysutil_memcpy(&(*p_sockptr)->u.u_sockaddr_in6.sin6_addr, - hent->h_addr_list[0], len); + vsf_log_failed_line(p_sess, kVSFLogEntryDNSResolve, &str_log_line); + str_free(&str_log_line); } else { - die("gethostbyname(): neither IPv4 nor IPv6"); + if (hent->h_addrtype == AF_INET) + { + unsigned int len = hent->h_length; + if (len > sizeof((*p_sockptr)->u.u_sockaddr_in.sin_addr)) + { + len = sizeof((*p_sockptr)->u.u_sockaddr_in.sin_addr); + } + vsf_sysutil_sockaddr_alloc_ipv4(p_sockptr); + vsf_sysutil_memcpy(&(*p_sockptr)->u.u_sockaddr_in.sin_addr, + hent->h_addr_list[0], len); + } + else if (hent->h_addrtype == AF_INET6) + { + unsigned int len = hent->h_length; + if (len > sizeof((*p_sockptr)->u.u_sockaddr_in6.sin6_addr)) + { + len = sizeof((*p_sockptr)->u.u_sockaddr_in6.sin6_addr); + } + vsf_sysutil_sockaddr_alloc_ipv6(p_sockptr); + vsf_sysutil_memcpy(&(*p_sockptr)->u.u_sockaddr_in6.sin6_addr, + hent->h_addr_list[0], len); + } + else + { + struct mystr str_log_line = INIT_MYSTR; + str_alloc_text(&str_log_line, "neither IPv4 nor IPv6, using default"); + vsf_log_failed_line(p_sess, kVSFLogEntryDNSResolve, &str_log_line); + str_free(&str_log_line); + } } } diff -up vsftpd-2.2.2/tunables.h.dyn_host vsftpd-2.2.2/tunables.h --- vsftpd-2.2.2/tunables.h.dyn_host 2010-11-15 10:37:44.774026001 -0700 +++ vsftpd-2.2.2/tunables.h 2010-11-16 00:26:31.450026007 -0700 @@ -73,6 +73,7 @@ extern int tunable_force_anon_data_ssl; extern int tunable_mdtm_write; /* Allow MDTM to set timestamps */ extern int tunable_lock_upload_files; /* Lock uploading files */ extern int tunable_pasv_addr_resolve; /* DNS resolve pasv_addr */ +extern int tunable_pasv_addr_dynamic; /* DNS dynamic pasv_addr */ extern int tunable_userlist_log; /* Log every failed login attempt */ extern int tunable_debug_ssl; /* Verbose SSL logging */ extern int tunable_require_cert; /* SSL client cert required */ @@ -127,6 +128,7 @@ extern const char* tunable_anon_root; extern const char* tunable_local_root; extern const char* tunable_banner_file; extern const char* tunable_pasv_address; +extern const char* tunable_pasv_hostname; extern const char* tunable_listen_address; extern const char* tunable_user_config_dir; extern const char* tunable_listen_address6; diff -up vsftpd-2.2.2/tunables.c.dyn_host vsftpd-2.2.2/tunables.c --- vsftpd-2.2.2/tunables.c.dyn_host 2010-11-15 10:37:44.772026000 -0700 +++ vsftpd-2.2.2/tunables.c 2010-11-16 00:32:52.035039315 -0700 @@ -72,6 +72,7 @@ int tunable_force_anon_data_ssl; int tunable_mdtm_write; int tunable_lock_upload_files; int tunable_pasv_addr_resolve; +int tunable_pasv_addr_dynamic; int tunable_userlist_log; int tunable_debug_ssl; int tunable_require_cert; @@ -124,6 +125,7 @@ const char* tunable_anon_root; const char* tunable_local_root; const char* tunable_banner_file; const char* tunable_pasv_address; +const char* tunable_pasv_hostname; const char* tunable_listen_address; const char* tunable_user_config_dir; const char* tunable_listen_address6; @@ -209,6 +211,7 @@ tunables_load_defaults() tunable_mdtm_write = 1; tunable_lock_upload_files = 1; tunable_pasv_addr_resolve = 0; + tunable_pasv_addr_dynamic = 0; tunable_userlist_log = 0; tunable_debug_ssl = 0; tunable_require_cert = 0; @@ -265,6 +268,7 @@ tunables_load_defaults() install_str_setting(0, &tunable_local_root); install_str_setting(0, &tunable_banner_file); install_str_setting(0, &tunable_pasv_address); + install_str_setting(0, &tunable_pasv_hostname); install_str_setting(0, &tunable_listen_address); install_str_setting(0, &tunable_user_config_dir); install_str_setting(0, &tunable_listen_address6); diff -up vsftpd-2.2.2/vsftpd.conf.5.dyn_host vsftpd-2.2.2/vsftpd.conf.5 --- vsftpd-2.2.2/vsftpd.conf.5.dyn_host 2010-11-15 10:37:44.777025999 -0700 +++ vsftpd-2.2.2/vsftpd.conf.5 2010-12-13 17:22:51.733723842 -0700 @@ -361,6 +361,21 @@ option. Default: NO .TP +.B pasv_addr_dynamic +Set to YES if the hostname specified in the +.BR pasv_hostname +or +.BR pasv_address +option is associated with a dynamic IP address. +This causes the hostname's address to be DNS resolved with each PASV command. +The +.BR pasv_hostname +or +.BR pasv_addr_resolve +option must be used for this option to have any effect. + +Default: NO +.TP .B pasv_enable Set to NO if you want to disallow the PASV method of obtaining a data connection. @@ -955,10 +970,27 @@ Use this option to override the IP addre response to the PASV command. Provide a numeric IP address, unless .BR pasv_addr_resolve is enabled, in which case you can provide a hostname which will be DNS -resolved for you at startup. +resolved for you with the first PASV command. If the hostname is associated +with a dynamic address, enable the +.BR pasv_addr_dynamic +option to have the address DNS resolved with each subsequent PASV command. +If the +.BR pasv_hostname +option is used, this option is ignored. Default: (none - the address is taken from the incoming connected socket) .TP +.B pasv_hostname +Use this option to specify a hostname as an alternative to using the +.BR pasv_address +option in conjunction with the +.BR pasv_addr_resolve +option. If the hostname is associated with a dynamic address, enable the +.BR pasv_addr_dynamic +option to have the address DNS resolved with each PASV command. + +Default: (none) +.TP .B rsa_cert_file This option specifies the location of the RSA certificate to use for SSL encrypted connections.