From a66db18392a22245bbe804437d65132308ee3ace Mon Sep 17 00:00:00 2001 From: jsing Date: Sat, 10 Feb 2018 06:25:16 +0000 Subject: [PATCH] Add TLS session support to ftp(1). If a session file is specified via the `-S session=...', ftp(1) will attempt to resume TLS sessions based on the session data contained within this file. Upon completion of a successful TLS handshake the session file will be updated with new session data, if available. Discussed with deraadt@ and beck@. Requested by and input from espie@. --- usr.bin/ftp/fetch.c | 5 ++++- usr.bin/ftp/ftp.1 | 11 +++++++++-- usr.bin/ftp/ftp_var.h | 3 ++- usr.bin/ftp/main.c | 34 +++++++++++++++++++++++++--------- 4 files changed, 40 insertions(+), 13 deletions(-) diff --git a/usr.bin/ftp/fetch.c b/usr.bin/ftp/fetch.c index 7c3363cfd61..30f73122da5 100644 --- a/usr.bin/ftp/fetch.c +++ b/usr.bin/ftp/fetch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fetch.c,v 1.166 2018/02/07 23:04:50 procter Exp $ */ +/* $OpenBSD: fetch.c,v 1.167 2018/02/10 06:25:16 jsing Exp $ */ /* $NetBSD: fetch.c,v 1.14 1997/08/18 10:20:20 lukem Exp $ */ /*- @@ -1037,6 +1037,9 @@ improper: cleanup_url_get: #ifndef NOSSL if (tls != NULL) { + if (tls_session_fd != -1) + dprintf(STDERR_FILENO, "tls session resumed: %s\n", + tls_conn_session_resumed(tls) ? "yes" : "no"); do { i = tls_close(tls); } while (i == TLS_WANT_POLLIN || i == TLS_WANT_POLLOUT); diff --git a/usr.bin/ftp/ftp.1 b/usr.bin/ftp/ftp.1 index 3f93dbb2785..2527b7ef5e3 100644 --- a/usr.bin/ftp/ftp.1 +++ b/usr.bin/ftp/ftp.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ftp.1,v 1.107 2017/01/25 07:21:18 jmc Exp $ +.\" $OpenBSD: ftp.1,v 1.108 2018/02/10 06:25:16 jsing Exp $ .\" $NetBSD: ftp.1,v 1.22 1997/08/18 10:20:22 lukem Exp $ .\" .\" Copyright (c) 1985, 1989, 1990, 1993 @@ -30,7 +30,7 @@ .\" .\" @(#)ftp.1 8.3 (Berkeley) 10/9/94 .\" -.Dd $Mdocdate: January 25 2017 $ +.Dd $Mdocdate: February 10 2018 $ .Dt FTP 1 .Os .Sh NAME @@ -253,6 +253,13 @@ Don't perform server certificate validation. Require the server to present a valid OCSP stapling in the TLS handshake. .It Cm noverifytime Disable validation of certificate times and OCSP validation. +.It Cm session Ns = Ns Ar /path/to/session +Specify a file to use for TLS session data. +If this file has a non-zero length, the session data will be read from this file +and the client will attempt to resume the TLS session with the server. +Upon completion of a successful TLS handshake this file will be updated +with new session data, if available. +This file will be created if it does not already exist. .El .Pp By default, server certificate validation is performed, and if it fails diff --git a/usr.bin/ftp/ftp_var.h b/usr.bin/ftp/ftp_var.h index 952eb945093..de6b1b17369 100644 --- a/usr.bin/ftp/ftp_var.h +++ b/usr.bin/ftp/ftp_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ftp_var.h,v 1.40 2017/01/21 08:33:07 krw Exp $ */ +/* $OpenBSD: ftp_var.h,v 1.41 2018/02/10 06:25:16 jsing Exp $ */ /* $NetBSD: ftp_var.h,v 1.18 1997/08/18 10:20:25 lukem Exp $ */ /* @@ -227,4 +227,5 @@ extern struct cmd cmdtab[]; #ifndef NOSSL extern struct tls_config *tls_config; +extern int tls_session_fd; #endif /* !NOSSL */ diff --git a/usr.bin/ftp/main.c b/usr.bin/ftp/main.c index 66642f9ff7c..eae8ec8b3c2 100644 --- a/usr.bin/ftp/main.c +++ b/usr.bin/ftp/main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.119 2017/01/24 23:47:34 beck Exp $ */ +/* $OpenBSD: main.c,v 1.120 2018/02/10 06:25:16 jsing Exp $ */ /* $NetBSD: main.c,v 1.24 1997/08/18 10:20:26 lukem Exp $ */ /* @@ -67,6 +67,7 @@ #include #include +#include #include #include #include @@ -84,26 +85,29 @@ int connect_timeout; #ifndef NOSSL char * const ssl_verify_opts[] = { -#define SSL_CAFILE 0 +#define SSL_CAFILE 0 "cafile", -#define SSL_CAPATH 1 +#define SSL_CAPATH 1 "capath", -#define SSL_CIPHERS 2 +#define SSL_CIPHERS 2 "ciphers", -#define SSL_DONTVERIFY 3 +#define SSL_DONTVERIFY 3 "dont", -#define SSL_DOVERIFY 4 +#define SSL_DOVERIFY 4 "do", -#define SSL_VERIFYDEPTH 5 +#define SSL_VERIFYDEPTH 5 "depth", -#define SSL_MUSTSTAPLE 6 +#define SSL_MUSTSTAPLE 6 "muststaple", #define SSL_NOVERIFYTIME 7 "noverifytime", +#define SSL_SESSION 8 + "session", NULL }; struct tls_config *tls_config; +int tls_session_fd = -1; static void process_ssl_options(char *cp) @@ -157,6 +161,18 @@ process_ssl_options(char *cp) case SSL_NOVERIFYTIME: tls_config_insecure_noverifytime(tls_config); break; + case SSL_SESSION: + if (str == NULL) + errx(1, "missing session file"); + if ((tls_session_fd = open(str, O_RDWR|O_CREAT, + 0600)) == -1) + err(1, "failed to open or create session file " + "'%s'", str); + if (tls_config_set_session_fd(tls_config, + tls_session_fd) == -1) + errx(1, "failed to set session: %s", + tls_config_error(tls_config)); + break; default: errx(1, "unknown -S suboption `%s'", suboptarg ? suboptarg : ""); @@ -276,7 +292,7 @@ main(volatile int argc, char *argv[]) errx(1, "tls set ciphers failed: %s", tls_config_error(tls_config)); } -#endif /* !SMALL */ +#endif /* !NOSSL */ httpuseragent = NULL; -- 2.20.1