Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 314952 Details for
Bug 459607
SSL connections are not correctly shutdown
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
backport of changes from upstream version
vsftpd-2.0.7-fix_ssl.patch (text/plain), 29.47 KB, created by
Justin Payne
on 2008-08-25 23:14:22 UTC
(
hide
)
Description:
backport of changes from upstream version
Filename:
MIME Type:
Creator:
Justin Payne
Created:
2008-08-25 23:14:22 UTC
Size:
29.47 KB
patch
obsolete
>diff -up ssl/tunables.c.fix ssl/tunables.c >--- ssl/tunables.c.fix 2008-08-25 16:09:52.000000000 -0400 >+++ ssl/tunables.c 2008-08-25 16:31:01.000000000 -0400 >@@ -49,7 +49,7 @@ int tunable_force_dot_files = 0; > int tunable_listen_ipv6 = 0; > int tunable_dual_log_enable = 0; > int tunable_syslog_enable = 0; >-int tunable_background = 1; >+int tunable_background = 0; > int tunable_virtual_use_local_privs = 0; > int tunable_session_support = 0; > int tunable_download_enable = 1; >@@ -72,6 +72,13 @@ int tunable_mdtm_write = 1; > int tunable_lock_upload_files = 1; > int tunable_pasv_addr_resolve = 0; > int tunable_userlist_log = 0; >+int tunable_debug_ssl = 0; >+int tunable_require_cert = 0; >+int tunable_validate_cert = 0; >+int tunable_strict_ssl_read_eof = 0; >+int tunable_strict_ssl_write_shutdown = 0; >+int tunable_ssl_request_cert = 1; >+int tunable_delete_failed_uploads = 0; > > unsigned int tunable_accept_timeout = 60; > unsigned int tunable_connect_timeout = 60; >@@ -95,6 +102,8 @@ unsigned int tunable_trans_chunk_size = > unsigned int tunable_delay_failed_login = 1; > unsigned int tunable_delay_successful_login = 0; > unsigned int tunable_max_login_fails = 3; >+/* -rw------- */ >+unsigned int tunable_chown_upload_mode = 0600; > > const char* tunable_secure_chroot_dir = "/usr/share/empty"; > const char* tunable_ftp_username = "ftp"; >@@ -104,11 +113,11 @@ const char* tunable_vsftpd_log_file = "/ > const char* tunable_message_file = ".message"; > const char* tunable_nopriv_user = "nobody"; > const char* tunable_ftpd_banner = 0; >-const char* tunable_banned_email_file = "/etc/vsftpd/banned_emails"; >-const char* tunable_chroot_list_file = "/etc/vsftpd/chroot_list"; >+const char* tunable_banned_email_file = "/etc/vsftpd.banned_emails"; >+const char* tunable_chroot_list_file = "/etc/vsftpd.chroot_list"; > const char* tunable_pam_service_name = "ftp"; > const char* tunable_guest_username = "ftp"; >-const char* tunable_userlist_file = "/etc/vsftpd/user_list"; >+const char* tunable_userlist_file = "/etc/vsftpd.user_list"; > const char* tunable_anon_root = 0; > const char* tunable_local_root = 0; > const char* tunable_banner_file = 0; >@@ -120,10 +129,11 @@ const char* tunable_cmds_allowed = 0; > const char* tunable_hide_file = 0; > const char* tunable_deny_file = 0; > const char* tunable_user_sub_token = 0; >-const char* tunable_email_password_file = "/etc/vsftpd/email_passwords"; >+const char* tunable_email_password_file = "/etc/vsftpd.email_passwords"; > const char* tunable_rsa_cert_file = "/usr/share/ssl/certs/vsftpd.pem"; > const char* tunable_dsa_cert_file = 0; > const char* tunable_ssl_ciphers = "DES-CBC3-SHA"; > const char* tunable_rsa_private_key_file = 0; > const char* tunable_dsa_private_key_file = 0; >+const char* tunable_ca_certs_file = 0; > >diff -up ssl/twoprocess.c.fix ssl/twoprocess.c >--- ssl/twoprocess.c.fix 2008-08-25 16:11:41.000000000 -0400 >+++ ssl/twoprocess.c 2008-08-25 14:46:50.000000000 -0400 >@@ -282,6 +282,7 @@ process_login_req(struct vsf_session* p_ > static void > process_ssl_slave_req(struct vsf_session* p_sess) > { >+ priv_sock_send_str(p_sess->ssl_slave_fd, &p_sess->control_cert_digest); > while (1) > { > char cmd = priv_sock_get_cmd(p_sess->ssl_slave_fd); >@@ -342,9 +343,15 @@ common_do_login(struct vsf_session* p_se > if (tunable_ssl_enable) > { > vsf_sysutil_close(p_sess->ssl_slave_fd); >+ if (p_sess->ssl_slave_active) >+ { >+ priv_sock_get_str(p_sess->ssl_consumer_fd, >+ &p_sess->control_cert_digest); >+ } > } > if (tunable_guest_enable && !anon) > { >+ p_sess->is_guest = 1; > /* Remap to the guest user */ > str_alloc_text(&guest_user_str, tunable_guest_username); > p_user_str = &guest_user_str; >@@ -416,17 +423,11 @@ handle_per_user_config(const struct myst > str_append_char(&filename_str, '/'); > str_append_str(&filename_str, p_user_str); > retval = str_stat(&filename_str, &p_statbuf); >- /* Security - die unless owned by root */ >- if (!vsf_sysutil_retval_is_error(retval)) >+ /* Security - ignore unless owned by root */ >+ if (!vsf_sysutil_retval_is_error(retval) && >+ vsf_sysutil_statbuf_get_uid(p_statbuf) == VSFTP_ROOT_UID) > { >- if (vsf_sysutil_statbuf_get_uid(p_statbuf) == VSFTP_ROOT_UID) >- { >- vsf_parseconf_load_file(str_getbuf(&filename_str), 1); >- } >- else >- { >- die("reading non-root config file"); >- } >+ vsf_parseconf_load_file(str_getbuf(&filename_str), 1); > } > str_free(&filename_str); > vsf_sysutil_free(p_statbuf); >diff -up ssl/tunables.h.fix ssl/tunables.h >--- ssl/tunables.h.fix 2008-08-25 16:10:02.000000000 -0400 >+++ ssl/tunables.h 2008-08-25 16:31:55.000000000 -0400 >@@ -68,6 +68,13 @@ extern int tunable_mdtm_write; > extern int tunable_lock_upload_files; /* Lock uploading files */ > extern int tunable_pasv_addr_resolve; /* DNS resolve 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 */ >+extern int tunable_validate_cert; /* SSL certs must be valid */ >+extern int tunable_strict_ssl_read_eof; /* Need SSL_shutdown() on read */ >+extern int tunable_strict_ssl_write_shutdown; /* Need SSL_shutdown() on write */ >+extern int tunable_ssl_request_cert; /* Ask client for cert */ >+extern int tunable_delete_failed_uploads; /* Delete an upload that failed */ > > /* Integer/numeric defines */ > extern unsigned int tunable_accept_timeout; >@@ -89,6 +96,7 @@ extern unsigned int tunable_trans_chunk_ > extern unsigned int tunable_delay_failed_login; > extern unsigned int tunable_delay_successful_login; > extern unsigned int tunable_max_login_fails; >+extern unsigned int tunable_chown_upload_mode; > > /* String defines */ > extern const char* tunable_secure_chroot_dir; >@@ -121,6 +129,7 @@ extern const char* tunable_dsa_cert_file > extern const char* tunable_ssl_ciphers; > extern const char* tunable_rsa_private_key_file; > extern const char* tunable_dsa_private_key_file; >+extern const char* tunable_ca_certs_file; > > #endif /* VSF_TUNABLES_H */ > >diff -up ssl/logging.c.fix ssl/logging.c >--- ssl/logging.c.fix 2008-08-25 16:12:38.000000000 -0400 >+++ ssl/logging.c 2008-08-25 14:43:25.000000000 -0400 >@@ -106,6 +106,12 @@ vsf_log_entry_pending(struct vsf_session > } > > void >+vsf_log_clear_entry(struct vsf_session* p_sess) >+{ >+ p_sess->log_type = 0; >+} >+ >+void > vsf_log_do_log(struct vsf_session* p_sess, int succeeded) > { > vsf_log_common(p_sess, succeeded, (enum EVSFLogEntryType) p_sess->log_type, >@@ -211,14 +217,21 @@ vsf_log_do_log_wuftpd_format(struct vsf_ > str_append_text(p_str, "o "); > } > /* Access mode: anonymous/real user, and identity */ >- if (p_sess->is_anonymous) >+ if (p_sess->is_anonymous && !p_sess->is_guest) > { > str_append_text(p_str, "a "); > str_append_str(p_str, &p_sess->anon_pass_str); > } > else > { >- str_append_text(p_str, "r "); >+ if (p_sess->is_guest) >+ { >+ str_append_text(p_str, "g "); >+ } >+ else >+ { >+ str_append_text(p_str, "r "); >+ } > str_append_str(p_str, &p_sess->user_str); > } > str_append_char(p_str, ' '); >@@ -255,7 +268,7 @@ vsf_log_do_log_vsftpd_format(struct vsf_ > } > /* And the action */ > if (what != kVSFLogEntryFTPInput && what != kVSFLogEntryFTPOutput && >- what != kVSFLogEntryConnection) >+ what != kVSFLogEntryConnection && what != kVSFLogEntryDebug) > { > if (succeeded) > { >@@ -301,6 +314,9 @@ vsf_log_do_log_vsftpd_format(struct vsf_ > case kVSFLogEntryChmod: > str_append_text(p_str, "CHMOD"); > break; >+ case kVSFLogEntryDebug: >+ str_append_text(p_str, "DEBUG"); >+ break; > default: > bug("bad entry_type in vsf_log_do_log"); > break; >@@ -320,7 +336,8 @@ vsf_log_do_log_vsftpd_format(struct vsf_ > str_append_str(p_str, p_log_str); > str_append_char(p_str, '"'); > } >- if (what != kVSFLogEntryFTPInput && what != kVSFLogEntryFTPOutput) >+ if (what != kVSFLogEntryFTPInput && what != kVSFLogEntryFTPOutput && >+ what != kVSFLogEntryDebug) > { > if (p_sess->transfer_size) > { >diff -up ssl/parseconf.c.fix ssl/parseconf.c >--- ssl/parseconf.c.fix 2008-08-25 16:10:55.000000000 -0400 >+++ ssl/parseconf.c 2008-08-25 16:30:09.000000000 -0400 >@@ -15,7 +15,6 @@ > #include "defs.h" > #include "sysutil.h" > #include "utility.h" >-#include "sysstr.h" > > static const char* s_p_saved_filename; > static int s_strings_copied; >@@ -100,6 +99,13 @@ parseconf_bool_array[] = > { "mdtm_write", &tunable_mdtm_write }, > { "lock_upload_files", &tunable_lock_upload_files }, > { "pasv_addr_resolve", &tunable_pasv_addr_resolve }, >+ { "debug_ssl", &tunable_debug_ssl }, >+ { "require_cert", &tunable_require_cert }, >+ { "validate_cert", &tunable_validate_cert }, >+ { "strict_ssl_read_eof", &tunable_strict_ssl_read_eof }, >+ { "strict_ssl_write_shutdown", &tunable_strict_ssl_write_shutdown }, >+ { "ssl_request_cert", &tunable_ssl_request_cert }, >+ { "delete_failed_uploads", &tunable_delete_failed_uploads }, > { "userlist_log", &tunable_userlist_log }, > { 0, 0 } > }; >@@ -130,6 +136,7 @@ parseconf_uint_array[] = > { "delay_failed_login", &tunable_delay_failed_login }, > { "delay_successful_login", &tunable_delay_successful_login }, > { "max_login_fails", &tunable_max_login_fails }, >+ { "chown_upload_mode", &tunable_chown_upload_mode }, > { 0, 0 } > }; > >@@ -170,6 +177,7 @@ parseconf_str_array[] = > { "ssl_ciphers", &tunable_ssl_ciphers }, > { "rsa_private_key_file", &tunable_rsa_private_key_file }, > { "dsa_private_key_file", &tunable_dsa_private_key_file }, >+ { "ca_certs_file", &tunable_ca_certs_file }, > { 0, 0 } > }; > >@@ -179,8 +187,6 @@ vsf_parseconf_load_file(const char* p_fi > struct mystr config_file_str = INIT_MYSTR; > struct mystr config_setting_str = INIT_MYSTR; > struct mystr config_value_str = INIT_MYSTR; >- struct vsf_sysutil_statbuf* p_statbuf = 0; >- > unsigned int str_pos = 0; > int retval; > if (!p_filename) >@@ -209,9 +215,7 @@ vsf_parseconf_load_file(const char* p_fi > copy_string_settings(); > } > retval = str_fileread(&config_file_str, p_filename, VSFTP_CONF_FILE_MAX); >- (int)vsf_sysutil_stat(p_filename, &p_statbuf); >- /* Security - die unless the conf file is owned by root */ >- if (vsf_sysutil_retval_is_error(retval) || vsf_sysutil_statbuf_get_uid(p_statbuf) != VSFTP_ROOT_UID) >+ if (vsf_sysutil_retval_is_error(retval)) > { > if (errs_fatal) > { >diff -up ssl/ssl.c.fix ssl/ssl.c >--- ssl/ssl.c.fix 2008-08-25 15:56:39.000000000 -0400 >+++ ssl/ssl.c 2008-08-25 14:07:16.000000000 -0400 >@@ -20,6 +20,7 @@ > #include "tunables.h" > #include "utility.h" > #include "builddefs.h" >+#include "logging.h" > > #ifdef VSF_BUILD_SSL > >@@ -27,6 +28,7 @@ > #include <openssl/err.h> > #include <openssl/rand.h> > #include <openssl/bio.h> >+#include <errno.h> > > static char* get_ssl_error(); > static SSL* get_ssl(struct vsf_session* p_sess, int fd); >@@ -34,8 +36,14 @@ static int ssl_session_init(struct vsf_s > static void setup_bio_callbacks(); > static long bio_callback( > BIO* p_bio, int oper, const char* p_arg, int argi, long argl, long retval); >+static int ssl_verify_callback(int verify_ok, X509_STORE_CTX* p_ctx); >+static int ssl_cert_digest( >+ SSL* p_ssl, struct vsf_session* p_sess, struct mystr* p_str); >+static void maybe_log_shutdown_state(struct vsf_session* p_sess); >+static void maybe_log_ssl_error_state(struct vsf_session* p_sess, int ret); > > static int ssl_inited; >+static struct mystr debug_str; > > void > ssl_init(struct vsf_session* p_sess) >@@ -44,6 +52,7 @@ ssl_init(struct vsf_session* p_sess) > { > SSL_CTX* p_ctx; > long options; >+ int verify_option = 0; > SSL_library_init(); > p_ctx = SSL_CTX_new(SSLv23_server_method()); > if (p_ctx == NULL) >@@ -105,6 +114,25 @@ ssl_init(struct vsf_session* p_sess) > { > die("SSL: RNG is not seeded"); > } >+ if (tunable_ssl_request_cert) >+ { >+ verify_option |= SSL_VERIFY_PEER; >+ } >+ if (tunable_require_cert) >+ { >+ verify_option |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; >+ } >+ if (verify_option) >+ { >+ SSL_CTX_set_verify(p_ctx, verify_option, ssl_verify_callback); >+ if (tunable_ca_certs_file) >+ { >+ if (!SSL_CTX_load_verify_locations(p_ctx, tunable_ca_certs_file, NULL)) >+ { >+ die("SSL: could not load verify file"); >+ } >+ } >+ } > p_sess->p_ssl_ctx = p_ctx; > ssl_inited = 1; > } >@@ -124,6 +152,7 @@ handle_auth(struct vsf_session* p_sess) > { > struct mystr err_str = INIT_MYSTR; > str_alloc_text(&err_str, "Negotiation failed: "); >+ /* Technically, we shouldn't leak such detailed error messages. */ > str_append_text(&err_str, get_ssl_error()); > vsf_cmdio_write_str(p_sess, FTP_TLS_FAIL, &err_str); > vsf_sysutil_exit(0); >@@ -187,17 +216,27 @@ void > ssl_getline(const struct vsf_session* p_sess, struct mystr* p_str, > char end_char, char* p_buf, unsigned int buflen) > { >- char* p_buf_start = p_buf; >- p_buf[buflen - 1] = '\0'; >+ char* p_buf_start; >+ if (buflen == 0) >+ { >+ return; >+ } >+ p_buf_start = p_buf; >+ p_buf[buflen - 1] = end_char; > buflen--; > while (1) > { >+ /* Should I use SSL_peek here? Won't lack of it break pipelining? (SSL >+ * clients seem to work just fine, mind you, so maybe pipelining is banned >+ * over SSL connections. Also note that OpenSSL didn't always have >+ * SSL_peek). >+ */ > int retval = SSL_read(p_sess->p_control_ssl, p_buf, buflen); > if (retval <= 0) > { > die("SSL_read"); > } >- p_buf[retval] = '\0'; >+ p_buf[retval] = end_char; > buflen -= retval; > if (p_buf[retval - 1] == end_char || buflen == 0) > { >@@ -209,17 +248,30 @@ ssl_getline(const struct vsf_session* p_ > } > > int >-ssl_read(void* p_ssl, char* p_buf, unsigned int len) >+ssl_read(struct vsf_session* p_sess, char* p_buf, unsigned int len) > { > int retval; > int err; >+ SSL* p_ssl = p_sess->p_data_ssl; > do > { >- retval = SSL_read((SSL*) p_ssl, p_buf, len); >- err = SSL_get_error((SSL*) p_ssl, retval); >+ retval = SSL_read(p_ssl, p_buf, len); >+ err = SSL_get_error(p_ssl, retval); > } > while (retval < 0 && (err == SSL_ERROR_WANT_READ || > err == SSL_ERROR_WANT_WRITE)); >+ // If we hit an EOF, make sure it was from the peer, not injected by the >+ // attacker. >+ if (retval == 0 && SSL_get_shutdown(p_ssl) != SSL_RECEIVED_SHUTDOWN) >+ { >+ str_alloc_text(&debug_str, "Connection terminated without SSL shutdown " >+ "- buggy client?"); >+ vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); >+ if (tunable_strict_ssl_read_eof) >+ { >+ return -1; >+ } >+ } > return retval; > } > >@@ -250,26 +302,147 @@ ssl_write_str(void* p_ssl, const struct > return 0; > } > >+static void >+maybe_log_shutdown_state(struct vsf_session* p_sess) >+{ >+ if (tunable_debug_ssl) >+ { >+ int ret = SSL_get_shutdown(p_sess->p_data_ssl); >+ str_alloc_text(&debug_str, "SSL shutdown state is: "); >+ if (ret == 0) >+ { >+ str_append_text(&debug_str, "NONE"); >+ } >+ else if (ret == SSL_SENT_SHUTDOWN) >+ { >+ str_append_text(&debug_str, "SSL_SENT_SHUTDOWN"); >+ } >+ else if (ret == SSL_RECEIVED_SHUTDOWN) >+ { >+ str_append_text(&debug_str, "SSL_RECEIVED_SHUTDOWN"); >+ } >+ else >+ { >+ str_append_ulong(&debug_str, ret); >+ } >+ vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); >+ } >+} >+ >+static void >+maybe_log_ssl_error_state(struct vsf_session* p_sess, int ret) >+{ >+ if (tunable_debug_ssl) >+ { >+ str_alloc_text(&debug_str, "SSL ret: "); >+ str_append_ulong(&debug_str, ret); >+ str_append_text(&debug_str, ", SSL error: "); >+ str_append_text(&debug_str, get_ssl_error()); >+ str_append_text(&debug_str, ", errno: "); >+ str_append_ulong(&debug_str, errno); >+ vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); >+ } >+} >+ >+int >+ssl_data_close(struct vsf_session* p_sess) >+{ >+ int success = 1; >+ SSL* p_ssl = p_sess->p_data_ssl; >+ if (p_ssl) >+ { >+ int ret; >+ maybe_log_shutdown_state(p_sess); >+ // This is a mess. Ideally, when we're the sender, we'd like to get to the >+ // SSL_RECEIVED_SHUTDOWN state to get a cryptographic guarantee that the >+ // peer received all the data and shut the connection down cleanly. It >+ // doesn't matter hugely apart from logging, but it's a nagging detail. >+ // Unfortunately, no FTP client I found was able to get sends into that >+ // state, so the best we can do is issue SSL_shutdown but not check the >+ // errors / returns. At least this enables the receiver to be sure of the >+ // integrity of the send in terms of unwanted truncation. >+ ret = SSL_shutdown(p_ssl); >+ maybe_log_shutdown_state(p_sess); >+ if (ret == 0) >+ { >+ ret = SSL_shutdown(p_ssl); >+ maybe_log_shutdown_state(p_sess); >+ if (ret != 1) >+ { >+ if (tunable_strict_ssl_write_shutdown) >+ { >+ success = 0; >+ } >+ maybe_log_shutdown_state(p_sess); >+ maybe_log_ssl_error_state(p_sess, ret); >+ } >+ } >+ else if (ret < 0) >+ { >+ if (tunable_strict_ssl_write_shutdown) >+ { >+ success = 0; >+ } >+ maybe_log_ssl_error_state(p_sess, ret); >+ } >+ SSL_free(p_ssl); >+ p_sess->p_data_ssl = NULL; >+ } >+ return success; >+} >+ > int > ssl_accept(struct vsf_session* p_sess, int fd) > { >- SSL* p_ssl = get_ssl(p_sess, fd); >+ /* SECURITY: data SSL connections don't have any auth on them as part of the >+ * protocol. If a client sends an unfortunately optional client cert then >+ * we can check for a match between the control and data connections. >+ */ >+ SSL* p_ssl; >+ if (p_sess->p_data_ssl != NULL) >+ { >+ die("p_data_ssl should be NULL."); >+ } >+ p_ssl = get_ssl(p_sess, fd); > if (p_ssl == NULL) > { > return 0; > } > p_sess->p_data_ssl = p_ssl; > setup_bio_callbacks(p_ssl); >+ if (str_getlen(&p_sess->control_cert_digest) > 0) >+ { >+ static struct mystr data_cert_digest; >+ if (!ssl_cert_digest(p_ssl, p_sess, &data_cert_digest)) >+ { >+ if (tunable_debug_ssl) >+ { >+ str_alloc_text(&debug_str, "Missing cert on data channel."); >+ vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); >+ } >+ ssl_data_close(p_sess); >+ return 0; >+ } >+ if (str_strcmp(&p_sess->control_cert_digest, &data_cert_digest)) >+ { >+ if (tunable_debug_ssl) >+ { >+ str_alloc_text(&debug_str, "DIFFERENT cert on data channel."); >+ vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); >+ } >+ ssl_data_close(p_sess); >+ return 0; >+ } >+ if (tunable_debug_ssl) >+ { >+ str_alloc_text(&debug_str, "Matching cert on data channel."); >+ vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); >+ } >+ } > return 1; > } > > void >-ssl_data_close(struct vsf_session* p_sess) >-{ >- SSL_free(p_sess->p_data_ssl); >-} >- >-void > ssl_comm_channel_init(struct vsf_session* p_sess) > { > const struct vsf_sysutil_socketpair_retval retval = >@@ -284,19 +457,66 @@ get_ssl(struct vsf_session* p_sess, int > SSL* p_ssl = SSL_new(p_sess->p_ssl_ctx); > if (p_ssl == NULL) > { >+ if (tunable_debug_ssl) >+ { >+ str_alloc_text(&debug_str, "SSL_new failed"); >+ vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); >+ } > return NULL; > } > if (!SSL_set_fd(p_ssl, fd)) > { >+ if (tunable_debug_ssl) >+ { >+ str_alloc_text(&debug_str, "SSL_set_fd failed"); >+ vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); >+ } > SSL_free(p_ssl); > return NULL; > } > if (SSL_accept(p_ssl) != 1) > { >- die(get_ssl_error()); >+ const char* p_err = get_ssl_error(); >+ if (tunable_debug_ssl) >+ { >+ str_alloc_text(&debug_str, "SSL_accept failed: "); >+ str_append_text(&debug_str, p_err); >+ vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); >+ } >+ die(p_err); > SSL_free(p_ssl); > return NULL; > } >+ if (tunable_debug_ssl) >+ { >+ const char* p_ssl_version = SSL_get_cipher_version(p_ssl); >+ SSL_CIPHER* p_ssl_cipher = SSL_get_current_cipher(p_ssl); >+ const char* p_cipher_name = SSL_CIPHER_get_name(p_ssl_cipher); >+ int reused = SSL_session_reused(p_ssl); >+ X509* p_ssl_cert = SSL_get_peer_certificate(p_ssl); >+ str_alloc_text(&debug_str, "SSL version: "); >+ str_append_text(&debug_str, p_ssl_version); >+ str_append_text(&debug_str, ", SSL cipher: "); >+ str_append_text(&debug_str, p_cipher_name); >+ if (reused) >+ { >+ str_append_text(&debug_str, ", reused"); >+ } >+ else >+ { >+ str_append_text(&debug_str, ", not reused"); >+ } >+ if (p_ssl_cert != NULL) >+ { >+ str_append_text(&debug_str, ", CERT PRESENTED"); >+ X509_free(p_ssl_cert); >+ } >+ else >+ { >+ str_append_text(&debug_str, ", no cert"); >+ } >+ vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); >+ } > return p_ssl; > } > >@@ -309,10 +529,45 @@ ssl_session_init(struct vsf_session* p_s > return 0; > } > p_sess->p_control_ssl = p_ssl; >+ (void) ssl_cert_digest(p_ssl, p_sess, &p_sess->control_cert_digest); > setup_bio_callbacks(p_ssl); > return 1; > } > >+static int >+ssl_cert_digest(SSL* p_ssl, struct vsf_session* p_sess, struct mystr* p_str) >+{ >+ X509* p_cert = SSL_get_peer_certificate(p_ssl); >+ unsigned int num_bytes = 0; >+ if (p_cert == NULL) >+ { >+ return 0; >+ } >+ str_reserve(p_str, EVP_MAX_MD_SIZE); >+ str_empty(p_str); >+ str_rpad(p_str, EVP_MAX_MD_SIZE); >+ if (!X509_digest(p_cert, EVP_sha256(), (unsigned char*) str_getbuf(p_str), >+ &num_bytes)) >+ { >+ die("X509_digest failed"); >+ } >+ X509_free(p_cert); >+ if (tunable_debug_ssl) >+ { >+ unsigned int i; >+ str_alloc_text(&debug_str, "Cert digest:"); >+ for (i = 0; i < num_bytes; ++i) >+ { >+ str_append_char(&debug_str, ' '); >+ str_append_ulong( >+ &debug_str, (unsigned long) (unsigned char) str_get_char_at(p_str, i)); >+ } >+ vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); >+ } >+ str_trunc(p_str, num_bytes); >+ return 1; >+} >+ > static char* > get_ssl_error() > { >@@ -347,6 +602,17 @@ bio_callback( > return ret; > } > >+static int >+ssl_verify_callback(int verify_ok, X509_STORE_CTX* p_ctx) >+{ >+ (void) p_ctx; >+ if (tunable_validate_cert) >+ { >+ return verify_ok; >+ } >+ return 1; >+} >+ > #else /* VSF_BUILD_SSL */ > > void >@@ -386,9 +652,9 @@ ssl_getline(const struct vsf_session* p_ > } > > int >-ssl_read(void* p_ssl, char* p_buf, unsigned int len) >+ssl_read(struct vsf_session* p_sess, char* p_buf, unsigned int len) > { >- (void) p_ssl; >+ (void) p_sess; > (void) p_buf; > (void) len; > return -1; >@@ -419,10 +685,11 @@ ssl_accept(struct vsf_session* p_sess, i > return -1; > } > >-void >+int > ssl_data_close(struct vsf_session* p_sess) > { > (void) p_sess; >+ return 1; > } > > void >diff -up ssl/vsftpd.conf.5.fix ssl/vsftpd.conf.5 >--- ssl/vsftpd.conf.5.fix 2008-08-25 15:59:24.000000000 -0400 >+++ ssl/vsftpd.conf.5 2008-08-25 14:52:44.000000000 -0400 >@@ -163,6 +163,17 @@ slightly less privilege. > > Default: NO (but the sample config file enables it) > .TP >+.B debug_ssl >+If true, OpenSSL connection diagnostics are dumped to the vsftpd log file. >+(Added in v2.0.6). >+ >+Default: NO >+.TP >+.B delete_failed_uploads >+If true, any failed upload files are deleted. (Added in v2.0.7). >+ >+Default: NO >+.TP > .B deny_email_enable > If activated, you may provide a list of anonymous password e-mail responses > which cause login to be denied. By default, the file containing this list is >@@ -282,7 +293,7 @@ downloads proceed with a shared read loc > Before enabling this, be aware that malicious readers could starve a writer > wanting to e.g. append a file. > >-Default: NO >+Default: YES > .TP > .B log_ftp_protocol > When enabled, all FTP requests and responses are logged, providing the option >@@ -371,6 +382,15 @@ you know what you are doing! > > Default: NO > .TP >+.B require_cert >+If set to yes, all SSL client connections are required to present a client >+certificate. The degree of validation applied to this certificate is >+controlled by >+.BR validate_cert >+(Added in v2.0.6). >+ >+Default: NO >+.TP > .B run_as_launching_user > Set to YES if you want vsftpd to run as the user which launched vsftpd. This is > useful where root access is not available. MASSIVE WARNING! Do NOT enable this >@@ -430,6 +450,14 @@ OpenSSL library. > > Default: NO > .TP >+.B ssl_request_cert >+If enabled, vsftpd will request (but not necessarily require; see >+.BR require_cert) a certificate on incoming SSL connections. Normally this >+should not cause any trouble at all, but IBM zOS seems to have issues. >+(New in v2.0.7). >+ >+Default: YES >+.TP > .B ssl_sslv2 > Only applies if > .BR ssl_enable >@@ -454,6 +482,23 @@ TLS v1 connections are preferred. > > Default: YES > .TP >+.B strict_ssl_read_eof >+If enabled, SSL data uploads are required to terminate via SSL, not an >+EOF on the socket. This option is required to be sure that an attacker did >+not terminate an upload prematurely with a faked TCP FIN. Unfortunately, it >+is not enabled by default because so few clients get it right. (New in v2.0.7). >+ >+Default: NO >+.TP >+.B strict_ssl_write_shutdown >+If enabled, SSL data downloads are required to terminate via SSL, not an >+EOF on the socket. This is off by default as I was unable to find a single >+FTP client that does this. It is minor. All it affects is our ability to tell >+whether the client confirmed full receipt of the file. Even without this option, >+the client is able to check the integrity of the download. (New in v2.0.7). >+ >+Default: NO >+.TP > .B syslog_enable > If enabled, then any log output which would have gone to /var/log/vsftpd.log > goes to the system log instead. Logging is done under the FTPD facility. >@@ -520,6 +565,12 @@ cleartext passwords being transmitted. S > > Default: NO > .TP >+.B validate_cert >+If set to yes, all SSL client certificates received must validate OK. >+Self-signed certs do not constitute OK validation. (New in v2.0.6). >+ >+Default: NO >+.TP > .B virtual_use_local_privs > If enabled, virtual users will use the same privileges as local users. By > default, virtual users will use the same privileges as anonymous users, which >@@ -575,6 +626,11 @@ value will be treated as a base 10 integ > > Default: 077 > .TP >+.B chown_upload_mode >+The file mode to force for chown()ed anonymous uploads. (Added in v2.0.6). >+ >+Default: 0600 >+.TP > .B connect_timeout > The timeout, in seconds, for a remote client to respond to our PORT style > data connection. >@@ -588,12 +644,12 @@ client is kicked off. > > Default: 300 > .TP >-.B delay_failed_logins >+.B delay_failed_login > The number of seconds to pause prior to reporting a failed login. > > Default: 1 > .TP >-.B delay_successful_logins >+.B delay_successful_login > The number of seconds to pause prior to allowing a successful login. > > Default: 0 >@@ -702,6 +758,14 @@ option. > > Default: (none) > .TP >+.B ca_certs_file >+This option is the name of a file to load Certificate Authority certs from, for >+the purpose of validating client certs. Regrettably, the default SSL CA cert >+paths are not used, because of vsftpd's use of restricted filesystem spaces >+(chroot). (Added in v2.0.6). >+ >+Default: (none) >+.TP > .B chown_username > This is the name of the user who is given ownership of anonymously uploaded > files. This option is only relevant if another option, >@@ -881,7 +945,7 @@ Default: /usr/share/empty > .TP > .B ssl_ciphers > This option can be used to select which SSL ciphers vsftpd will allow for >-encrpyted SSL connections. See the >+encrypted SSL connections. See the > .BR ciphers > man page for further details. Note that restricting ciphers can be a useful > security precaution as it prevents malicious remote parties forcing a cipher >@@ -962,5 +1026,5 @@ Alternatively, it is written if you have > Default: /var/log/xferlog > > .SH AUTHOR >-chris@scary.beasts.org >+scarybeasts@gmail.com > >diff -up ssl/ssl.h.fix ssl/ssl.h >--- ssl/ssl.h.fix 2008-08-25 17:13:50.000000000 -0400 >+++ ssl/ssl.h 2008-08-25 17:13:36.000000000 -0400 >@@ -6,12 +6,12 @@ struct mystr; > > void ssl_getline(const struct vsf_session* p_sess, struct mystr* p_str, > char end_char, char* p_buf, unsigned int buflen); >-int ssl_read(void* p_ssl, char* p_buf, unsigned int len); >+int ssl_read(struct vsf_session* p_sess, char* p_buf, unsigned int len); > int ssl_write(void* p_ssl, const char* p_buf, unsigned int len); > int ssl_write_str(void* p_ssl, const struct mystr* p_str); > void ssl_init(struct vsf_session* p_sess); > int ssl_accept(struct vsf_session* p_sess, int fd); >-void ssl_data_close(struct vsf_session* p_sess); >+int ssl_data_close(struct vsf_session* p_sess); > void ssl_comm_channel_init(struct vsf_session* p_sess); > void handle_auth(struct vsf_session* p_sess); > void handle_pbsz(struct vsf_session* p_sess); >diff -up ssl/logging.h.fix ssl/logging.h >--- ssl/logging.h.fix 2008-08-25 16:12:47.000000000 -0400 >+++ ssl/logging.h 2008-08-25 14:43:29.000000000 -0400 >@@ -18,7 +18,8 @@ enum EVSFLogEntryType > kVSFLogEntryDelete, > kVSFLogEntryRename, > kVSFLogEntryRmdir, >- kVSFLogEntryChmod >+ kVSFLogEntryChmod, >+ kVSFLogEntryDebug, > }; > > /* vsf_log_init() >@@ -49,6 +50,12 @@ void vsf_log_start_entry(struct vsf_sess > */ > int vsf_log_entry_pending(struct vsf_session* p_sess); > >+/* vsf_log_clear_entry() >+ * PURPOSE >+ * Clears any pending log entry. >+ */ >+void vsf_log_clear_entry(struct vsf_session* p_sess); >+ > /* vsf_log_do_log() > * PURPOSE > * Denote the end of a logged operation, specifying whether the operation >diff -up ssl/session.h.fix ssl/session.h >--- ssl/session.h.fix 2008-08-25 16:36:49.000000000 -0400 >+++ ssl/session.h 2008-08-25 16:54:18.000000000 -0400 >@@ -33,6 +33,7 @@ struct vsf_session > > /* Details of the login */ > int is_anonymous; >+ int is_guest; > struct mystr user_str; > struct mystr anon_pass_str; > >@@ -87,6 +88,7 @@ struct vsf_session > void* p_ssl_ctx; > void* p_control_ssl; > void* p_data_ssl; >+ struct mystr control_cert_digest; > int ssl_slave_active; > int ssl_slave_fd; > int ssl_consumer_fd;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 459607
:
314952
|
316749
|
317331
|
333868