diff options
author | Ross Lagerwall <rosslagerwall@gmail.com> | 2015-02-26 22:30:44 +0000 |
---|---|---|
committer | Ross Lagerwall <rosslagerwall@gmail.com> | 2015-04-09 22:10:36 +0100 |
commit | dccf4aeea3f94251062836f2c6f5f37219c64054 (patch) | |
tree | e7a0eaac29a1cb61ce248ab07cb4d502490de917 /daemon/gvfsftptask.c | |
parent | 7cf5d5ff55fcbdebe0fb7b60e52ecb0c95ca63ee (diff) | |
download | gvfs-dccf4aeea3f94251062836f2c6f5f37219c64054.tar.gz |
ftp: Implement TLS support
Implement TLS support (aka explicit ftps). This is done by using a
different URL scheme, ftps, so that it is only used if explicitly
specified.
Although the protocol allows transparently upgrading a normal
connection to a secure one, there are several problems with this.
FEAT is needed to determine support for it but some servers do not allow
this before login. Some servers are configured to allow AUTH TLS but
have firewalls that block data connections because they can't inspect
the traffic. Servers may disallow TLS on the data connection, making it
unclear to the user how secure the connection is. Finally, there may be
verification errors which need to be presented to the user, and these
are unexpected because they did not choose to use ftps.
Making secure ftp opt-in as a separate URL scheme side-steps most of
these issues as well as ensuring there are no regressions for normal
ftp. When using ftps, we assume that the server implements AUTH TLS so
the connection is secured before login. It is also assumed that TLS for
data connections is allowed, so both control and data connection are
secure before any information is transferred.
Verification errors are presented during mounting. If the identity
changes on subsequent reconnections, the connection is aborted.
While presenting verification errors to the user in this way is perhaps
not the best way of handling security, it is fairly standard.
The implementation has been successfully tested on vsftpd, ProFTPD,
Pure-FTPd, IIS, and FileZilla Server.
Based on a patch by Benjamin Otte.
https://bugzilla.gnome.org/show_bug.cgi?id=526582
Diffstat (limited to 'daemon/gvfsftptask.c')
-rw-r--r-- | daemon/gvfsftptask.c | 75 |
1 files changed, 73 insertions, 2 deletions
diff --git a/daemon/gvfsftptask.c b/daemon/gvfsftptask.c index c70262b1..2209c2b1 100644 --- a/daemon/gvfsftptask.c +++ b/daemon/gvfsftptask.c @@ -161,6 +161,28 @@ do_broadcast (GCancellable *cancellable, GCond *cond) g_cond_broadcast (cond); } +/* Decide whether to allow verification errors for control and data connections + * after the initial connection. The connection is only allowed if the + * identity is the same as for the initial connection. */ +static gboolean +reconnect_certificate_cb (GTlsConnection *conn, + GTlsCertificate *certificate, + GTlsCertificateFlags errors, + gpointer user_data) +{ + GVfsBackendFtp *ftp = G_VFS_BACKEND_FTP (user_data); + + /* If the verification result has changed in some way, abort the + * connection. */ + if (errors != ftp->certificate_errors) + return FALSE; + + /* Only allow the connection if the certificate presented is the same as for + * the initial connection which the user accepted. */ + return ftp->certificate && + g_tls_certificate_is_same (certificate, ftp->certificate); +} + /** * g_vfs_ftp_task_acquire_connection: * @task: a task without an associated connection @@ -229,6 +251,8 @@ g_vfs_ftp_task_acquire_connection (GVfsFtpTask *task) if (G_LIKELY (task->conn != NULL)) { g_vfs_ftp_task_receive (task, 0, NULL); + if (ftp->use_tls) + g_vfs_ftp_task_enable_tls (task, reconnect_certificate_cb, ftp); g_vfs_ftp_task_login (task, ftp->user, ftp->password); g_vfs_ftp_task_setup_connection (task); if (G_LIKELY (!g_vfs_ftp_task_is_in_error (task))) @@ -1144,8 +1168,8 @@ g_vfs_ftp_task_setup_data_connection (GVfsFtpTask *task) * g_vfs_ftp_task_open_data_connection: * @task: a task * - * Tries to open a data connection to the ftp server. If the operation fails, - * @task will be set into an error state. + * Tries to open a data connection to the ftp server and secures it if + * necessary. If the operation fails, @task will be set into an error state. **/ void g_vfs_ftp_task_open_data_connection (GVfsFtpTask *task) @@ -1160,5 +1184,52 @@ g_vfs_ftp_task_open_data_connection (GVfsFtpTask *task) g_vfs_ftp_connection_accept_data_connection (task->conn, task->cancellable, &task->error); + + if (g_vfs_ftp_task_is_in_error (task)) + return; + + if (task->backend->use_tls) + g_vfs_ftp_connection_data_connection_enable_tls (task->conn, + task->backend->server_identity, + reconnect_certificate_cb, + task->backend, + task->cancellable, + &task->error); } +/** + * g_vfs_ftp_task_enable_tls: + * @task: a task + * @cb: callback called if there's a verification error + * @user_data: user data passed to @cb + * + * Tries to enable tls on the control connection to an ftp server. + * If the operation fails, @task will be set into an error state. + **/ +gboolean +g_vfs_ftp_task_enable_tls (GVfsFtpTask *task, + CertificateCallback cb, + gpointer user_data) +{ + if (g_vfs_ftp_task_is_in_error (task)) + return FALSE; + + if (!g_vfs_ftp_task_send (task, 0, "AUTH TLS")) + return FALSE; + + if (!g_vfs_ftp_connection_enable_tls (task->conn, + task->backend->server_identity, + cb, + user_data, + task->cancellable, + &task->error)) + return FALSE; + + if (!g_vfs_ftp_task_send (task, 0, "PBSZ 0")) + return FALSE; + + if (!g_vfs_ftp_task_send (task, 0, "PROT P")) + return FALSE; + + return TRUE; +} |