All the code is under #ifndef SMALL, except for the getopt(3) goo; I saw
no size increase in the on-disk file, and build-checked that the
ramdisks still fit on i386.

Validation error messages straight from OpenSSL.

ok?

Index: fetch.c
===================================================================
RCS file: /cvs/src/usr.bin/ftp/fetch.c,v
retrieving revision 1.111
diff -u -p -r1.111 fetch.c
--- fetch.c     13 Nov 2013 20:41:10 -0000      1.111
+++ fetch.c     19 Dec 2013 23:25:41 -0000
@@ -606,8 +606,27 @@ again:
                SSL_load_error_strings();
                SSLeay_add_ssl_algorithms();
                ssl_ctx = SSL_CTX_new(SSLv23_client_method());
+               if (ssl_ctx == NULL) {
+                       ERR_print_errors_fp(ttyout);
+                       goto cleanup_url_get;
+               }
+               if (ssl_verify) {
+                       if (ssl_ca_file == NULL && ssl_ca_path == NULL)
+                               ssl_ca_file = _PATH_SSL_CAFILE;
+                       if (SSL_CTX_load_verify_locations(ssl_ctx,
+                           ssl_ca_file, ssl_ca_path) != 1) {
+                               ERR_print_errors_fp(ttyout);
+                               goto cleanup_url_get;
+                       }
+                       SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
+                       if (ssl_verify_depth != -1)
+                               SSL_CTX_set_verify_depth(ssl_ctx,
+                                   ssl_verify_depth);
+               }
+               if (ssl_ciphers != NULL)
+                       SSL_CTX_set_cipher_list(ssl_ctx, ssl_ciphers);
                ssl = SSL_new(ssl_ctx);
-               if (ssl == NULL || ssl_ctx == NULL) {
+               if (ssl == NULL) {
                        ERR_print_errors_fp(ttyout);
                        goto cleanup_url_get;
                }
Index: ftp.1
===================================================================
RCS file: /cvs/src/usr.bin/ftp/ftp.1,v
retrieving revision 1.88
diff -u -p -r1.88 ftp.1
--- ftp.1       28 Apr 2013 18:03:40 -0000      1.88
+++ ftp.1       19 Dec 2013 23:41:16 -0000
@@ -59,6 +59,7 @@
 .Op Fl C
 .Op Fl c Ar cookie
 .Op Fl o Ar output
+.Op Fl S Ar ssl_options
 .Op Fl s Ar srcaddr
 .Sm off
 .No http[s]:// Oo Ar user : password No @
@@ -216,6 +217,43 @@ if the server does not support passive c
 .It Fl r Ar seconds
 Retry to connect if failed, pausing for number of
 .Ar seconds .
+.It Fl S Ar ssl_options
+SSL/TLS options to use with HTTPS transfers.
+The following settings are available:
+.Bl -tag -width Ds
+.It Cm cafile Ns = Ns Ar /path/to/cert.pem
+PEM encoded file containing CA certificates used for certificate
+validation.
+.It Cm capath Ns = Ns Ar /path/to/certs/
+Directory containing PEM encoded CA certificates used for certificate
+validation.
+Such a directory can be prepared using the c_rehash OpenSSL utility.
+.It Cm ciphers Ns = Ns Ar cipher_list
+Specify the list of ciphers that will be used by
+.Nm .
+See the
+.Xr openssl 1
+.Cm ciphers
+subcommand.
+.It Cm depth Ns = Ns Ar max_depth
+Maximum depth of the certificate chain allowed when performing
+validation.
+.It Cm do
+Perform server certificate validation.
+.It Cm dont
+Don't perform server certificate validation.
+.El
+.Pp
+By default, server certificate validation is performed, and if it fails
+.Nm
+will abort.
+If no
+.Cm cafile
+or
+.Cm capath
+setting is provided,
+.Pa /etc/ssl/cert.pem
+will be used.
 .It Fl s Ar srcaddr
 Use
 .Ar srcaddr
Index: ftp_var.h
===================================================================
RCS file: /cvs/src/usr.bin/ftp/ftp_var.h,v
retrieving revision 1.32
diff -u -p -r1.32 ftp_var.h
--- ftp_var.h   30 Apr 2012 13:41:26 -0000      1.32
+++ ftp_var.h   17 Dec 2013 10:59:48 -0000
@@ -229,3 +229,14 @@ char macbuf[4096];
 FILE   *ttyout;                /* stdout or stderr, depending on interactive */
 
 extern struct cmd cmdtab[];
+
+#ifndef SMALL
+extern char    *ssl_ciphers;
+extern char    *ssl_ca_file;
+extern char    *ssl_ca_path;
+extern int      ssl_verify;
+extern int      ssl_verify_depth;
+# ifndef       _PATH_SSL_CAFILE
+#  define      _PATH_SSL_CAFILE "/etc/ssl/cert.pem"
+# endif
+#endif /* !SMALL */
Index: main.c
===================================================================
RCS file: /cvs/src/usr.bin/ftp/main.c,v
retrieving revision 1.85
diff -u -p -r1.85 main.c
--- main.c      26 Aug 2012 02:16:02 -0000      1.85
+++ main.c      19 Dec 2013 23:49:50 -0000
@@ -67,6 +67,7 @@
 
 #include <ctype.h>
 #include <err.h>
+#include <limits.h>
 #include <netdb.h>
 #include <pwd.h>
 #include <stdio.h>
@@ -78,6 +79,29 @@
 #include "ftp_var.h"
 #include "cmds.h"
 
+#ifndef SMALL
+char * const ssl_verify_opts[] = {
+#define SSL_CAFILE     0
+       "cafile",
+#define SSL_CAPATH     1
+       "capath",
+#define SSL_CIPHERS    2
+       "ciphers",
+#define SSL_DONTVERIFY 3
+       "dont",
+#define SSL_DOVERIFY   4
+       "do",
+#define SSL_VERIFYDEPTH        5
+       "depth",
+       NULL
+};
+char   *ssl_ciphers;
+int     ssl_verify = 1;
+int     ssl_verify_depth = -1;
+char   *ssl_ca_file;
+char   *ssl_ca_path;
+#endif /* !SMALL */
+
 int family = PF_UNSPEC;
 int pipeout;
 
@@ -175,7 +199,8 @@ main(volatile int argc, char *argv[])
        cookiefile = getenv("http_cookies");
 #endif /* !SMALL */
 
-       while ((ch = getopt(argc, argv, "46AaCc:dEegik:mno:pP:r:s:tvV")) != -1) 
{
+       while ((ch = getopt(argc, argv,
+                   "46AaCc:dEegik:mno:pP:r:S:s:tvV")) != -1) {
                switch (ch) {
                case '4':
                        family = PF_INET;
@@ -276,6 +301,53 @@ main(volatile int argc, char *argv[])
                        }
                        break;
 
+               case 'S':
+#ifndef SMALL
+                       cp = optarg;
+                       while (*cp) {
+                               char    *str;
+                               switch (getsubopt(&cp, ssl_verify_opts, &str)) {
+                               case SSL_CAFILE:
+                                       if (str == NULL)
+                                               errx(1, "missing CA file");
+                                       ssl_ca_file = str;
+                                       break;
+                               case SSL_CAPATH:
+                                       if (str == NULL)
+                                               errx(1, "missing CA directory"
+                                                   " path");
+                                       ssl_ca_path = str;
+                                       break;
+                               case SSL_CIPHERS:
+                                       if (str == NULL)
+                                               errx(1, "missing cipher list");
+                                       ssl_ciphers = str;
+                                       break;
+                               case SSL_DONTVERIFY:
+                                       ssl_verify = 0;
+                                       break;
+                               case SSL_DOVERIFY:
+                                       ssl_verify = 1;
+                                       break;
+                               case SSL_VERIFYDEPTH:
+                                       if (str == NULL)
+                                               errx(1, "missing depth");
+                                       ssl_verify_depth = strtonum(str, 0,
+                                           INT_MAX, &errstr);
+                                       if (errstr)
+                                               errx(1, "certificate "
+                                                   "validation depth is %s",
+                                                   errstr);
+                                       break;
+                               default:
+                                       errx(1, "unknown -S suboption `%s'",
+                                           suboptarg ? suboptarg : "");
+                                       /* NOTREACHED */
+                               }
+                       }
+#endif
+                       break;
+
                case 's':
 #ifndef SMALL
                        srcaddr = optarg;
@@ -775,6 +847,7 @@ usage(void)
 #endif /* !SMALL */
            "[-o output] "
 #ifndef SMALL
+           "[-S ssl_options] "
            "[-s srcaddr]\n"
            "           "
 #endif /* !SMALL */


-- 
jca | PGP: 0x06A11494 / 61DB D9A0 00A4 67CF 2A90  8961 6191 8FBF 06A1 1494

Reply via email to