Convert ftp(1) to libressl, rather than rolling in^W^Whand rolling libssl.
authorjsing <jsing@openbsd.org>
Mon, 14 Jul 2014 09:26:27 +0000 (09:26 +0000)
committerjsing <jsing@openbsd.org>
Mon, 14 Jul 2014 09:26:27 +0000 (09:26 +0000)
ok beck@ deraadt@

usr.bin/ftp/Makefile
usr.bin/ftp/fetch.c
usr.bin/ftp/ftp_var.h
usr.bin/ftp/main.c

index 876cb49..4d1fc63 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: Makefile,v 1.25 2009/05/05 19:35:30 martynas Exp $
+#      $OpenBSD: Makefile,v 1.26 2014/07/14 09:26:27 jsing Exp $
 
 # Define SMALL to disable command line editing and https support
 #CFLAGS+=-DSMALL
@@ -17,8 +17,8 @@ SRCS= cmds.c cmdtab.c complete.c cookie.c domacro.c fetch.c ftp.c \
 
 CPPFLAGS+= -DINET6
 
-LDADD+=        -ledit -lcurses -lutil -lssl -lcrypto
-DPADD+=        ${LIBEDIT} ${LIBCURSES} ${LIBUTIL}
+LDADD+=        -ledit -lcurses -lutil -lressl -lssl -lcrypto
+DPADD+=        ${LIBEDIT} ${LIBCURSES} ${LIBUTIL} ${LIBRESSL} ${LIBSSL} ${LIBCRYPTO}
 LDSTATIC= ${STATIC}
 
 #COPTS+= -Wall -Wconversion -Wstrict-prototypes -Wmissing-prototypes
index 0c07aa0..8a83612 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: fetch.c,v 1.125 2014/07/11 18:19:45 halex Exp $       */
+/*     $OpenBSD: fetch.c,v 1.126 2014/07/14 09:26:27 jsing Exp $       */
 /*     $NetBSD: fetch.c,v 1.14 1997/08/18 10:20:20 lukem Exp $ */
 
 /*-
 #include <resolv.h>
 
 #ifndef SMALL
-#include <openssl/ssl.h>
-#include <openssl/err.h>
-#include <openssl/x509v3.h>
+#include <ressl.h>
 #else /* !SMALL */
-#define SSL void
+struct ressl;
 #endif /* !SMALL */
 
 #include "ftp_var.h"
@@ -77,18 +75,13 @@ void                abortfile(int);
 char           hextochar(const char *);
 char           *urldecode(const char *);
 char           *recode_credentials(const char *_userinfo);
-int            ftp_printf(FILE *, SSL *, const char *, ...) __attribute__((format(printf, 3, 4)));
-char           *ftp_readline(FILE *, SSL *, size_t *);
-size_t         ftp_read(FILE *, SSL *, char *, size_t);
+int            ftp_printf(FILE *, struct ressl *, const char *, ...) __attribute__((format(printf, 3, 4)));
+char           *ftp_readline(FILE *, struct ressl *, size_t *);
+size_t         ftp_read(FILE *, struct ressl *, char *, size_t);
 #ifndef SMALL
 int            proxy_connect(int, char *, char *);
-int            SSL_vprintf(SSL *, const char *, va_list);
-char           *SSL_readline(SSL *, size_t *);
-int            ssl_match_hostname(char *, char *);
-int            ssl_check_subject_altname(X509 *, char *);
-int            ssl_check_common_name(X509 *, char *);
-int            ssl_check_hostname(X509 *, char *);
-SSL_CTX                *ssl_get_ssl_ctx(void);
+int            SSL_vprintf(struct ressl *, const char *, va_list);
+char           *SSL_readline(struct ressl *, size_t *);
 #endif /* !SMALL */
 
 #define        FTP_URL         "ftp://"        /* ftp URL prefix */
@@ -172,211 +165,6 @@ url_encode(const char *path)
        return (epath);
 }
 
-#ifndef SMALL
-int
-ssl_match_hostname(char *cert_hostname, char *hostname)
-{
-       if (strcasecmp(cert_hostname, hostname) == 0)
-                       return 0;
-
-       /* wildcard match? */
-       if (cert_hostname[0] == '*') {
-               char    *cert_domain, *domain;
-
-               cert_domain = &cert_hostname[1];
-               if (cert_domain[0] != '.')
-                       return -1;
-               if (strlen(cert_domain) == 1)
-                       return -1;
-
-               domain = strchr(hostname, '.');
-               /* no wildcard match against a hostname with no domain part */
-               if (domain == NULL || strlen(domain) == 1)
-                       return -1;
-
-               if (strcasecmp(cert_domain, domain) == 0)
-                       return 0;
-       }
-
-       return -1;
-}
-
-int
-ssl_check_subject_altname(X509 *cert, char *host)
-{
-       STACK_OF(GENERAL_NAME)  *altname_stack = NULL;
-       union { struct in_addr ip4; struct in6_addr ip6; } addrbuf;
-       int     addrlen, type;
-       int     count, i;
-       int     rv = -1;
-
-       altname_stack =
-           X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
-       if (altname_stack == NULL)
-               return -1;
-
-       if (inet_pton(AF_INET, host, &addrbuf) == 1) {
-               type = GEN_IPADD;
-               addrlen = 4;
-       } else if (inet_pton(AF_INET6, host, &addrbuf) == 1) {
-               type = GEN_IPADD;
-               addrlen = 16;
-       } else
-               type = GEN_DNS;
-
-       count = sk_GENERAL_NAME_num(altname_stack);
-       for (i = 0; i < count; i++) {
-               GENERAL_NAME    *altname;
-
-               altname = sk_GENERAL_NAME_value(altname_stack, i);
-
-               if (altname->type != type)
-                       continue;
-
-               if (type == GEN_DNS) {
-                       unsigned char   *data;
-                       int              format;
-
-                       format = ASN1_STRING_type(altname->d.dNSName);
-                       if (format == V_ASN1_IA5STRING) {
-                               data = ASN1_STRING_data(altname->d.dNSName);
-
-                               if (ASN1_STRING_length(altname->d.dNSName) !=
-                                   (int)strlen(data)) {
-                                       fprintf(ttyout, "%s: NUL byte in "
-                                           "subjectAltName, probably a "
-                                           "malicious certificate.\n",
-                                           getprogname());
-                                       rv = -2;
-                                       break;
-                               }
-
-                               if (ssl_match_hostname(data, host) == 0) {
-                                       rv = 0;
-                                       break;
-                               }
-                       } else
-                               fprintf(ttyout, "%s: unhandled subjectAltName "
-                                   "dNSName encoding (%d)\n", getprogname(),
-                                   format);
-
-               } else if (type == GEN_IPADD) {
-                       unsigned char   *data;
-                       int              datalen;
-
-                       datalen = ASN1_STRING_length(altname->d.iPAddress);
-                       data = ASN1_STRING_data(altname->d.iPAddress);
-
-                       if (datalen == addrlen &&
-                           memcmp(data, &addrbuf, addrlen) == 0) {
-                               rv = 0;
-                               break;
-                       }
-               }
-       }
-
-       sk_GENERAL_NAME_free(altname_stack);
-       return rv;
-}
-
-int
-ssl_check_common_name(X509 *cert, char *host)
-{
-       X509_NAME       *name;
-       char            *common_name = NULL;
-       int              common_name_len;
-       int              rv = -1;
-
-       name = X509_get_subject_name(cert);
-       if (name == NULL)
-               goto out;
-
-       common_name_len = X509_NAME_get_text_by_NID(name, NID_commonName,
-           NULL, 0);
-       if (common_name_len < 0)
-               goto out;
-
-       common_name = calloc(common_name_len + 1, 1);
-       if (common_name == NULL)
-               goto out;
-
-       X509_NAME_get_text_by_NID(name, NID_commonName, common_name,
-           common_name_len + 1);
-
-       /* NUL bytes in CN? */
-       if (common_name_len != (int)strlen(common_name)) {
-               fprintf(ttyout, "%s: NUL byte in Common Name field, "
-                   "probably a malicious certificate.\n", getprogname());
-               rv = -2;
-               goto out;
-       }
-
-       if (ssl_match_hostname(common_name, host) == 0)
-               rv = 0;
-out:
-       free(common_name);
-       return rv;
-}
-
-int
-ssl_check_hostname(X509 *cert, char *host)
-{
-       int     rv;
-
-       rv = ssl_check_subject_altname(cert, host);
-       if (rv == 0 || rv == -2)
-               return rv;
-
-       return ssl_check_common_name(cert, host);
-}
-
-SSL_CTX *
-ssl_get_ssl_ctx(void)
-{
-       static SSL_CTX  *ssl_ctx = NULL;
-       static int       libssl_loaded = 0;
-
-       if (ssl_ctx != NULL)
-               return ssl_ctx;
-
-       if (!libssl_loaded) {
-               SSL_library_init();
-               SSL_load_error_strings();
-               libssl_loaded = 1;
-       }
-
-       ssl_ctx = SSL_CTX_new(SSLv23_client_method());
-       if (ssl_ctx == NULL)
-               goto err;
-
-       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)
-                       goto err;
-
-               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) == -1)
-               goto err;
-
-       return ssl_ctx;
-err:
-       if (ssl_ctx != NULL) {
-               SSL_CTX_free(ssl_ctx);
-               ssl_ctx = NULL;
-       }
-       return NULL;
-}
-#endif
-
 /*
  * Retrieve URL, via the proxy in $proxyvar if necessary.
  * Modifies the string argument given.
@@ -404,9 +192,8 @@ url_get(const char *origline, const char *proxyenv, const char *outfile)
        char *locbase, *full_host = NULL;
        const char *scheme;
        int ishttpurl = 0, ishttpsurl = 0;
-       SSL_CTX *ssl_ctx = NULL;
 #endif /* !SMALL */
-       SSL *ssl = NULL;
+       struct ressl *ssl = NULL;
        int status;
        int save_errno;
        const size_t buflen = 128 * 1024;
@@ -799,62 +586,28 @@ again:
 
 #ifndef SMALL
        if (ishttpsurl) {
-               union { struct in_addr ip4; struct in6_addr ip6; } addrbuf;
-
                if (proxyenv && sslpath) {
                        ishttpsurl = 0;
                        proxyurl = NULL;
                        path = sslpath;
                }
-               ssl_ctx = ssl_get_ssl_ctx();
-               if (ssl_ctx == NULL) {
-                       ERR_print_errors_fp(ttyout);
+               if (ressl_init() != 0) {
+                       fprintf(ttyout, "SSL initialisation failed\n");
                        goto cleanup_url_get;
                }
-               ssl = SSL_new(ssl_ctx);
-               if (ssl == NULL) {
-                       ERR_print_errors_fp(ttyout);
+               if ((ssl = ressl_client()) == NULL) {
+                       fprintf(ttyout, "failed to create SSL client\n");
                        goto cleanup_url_get;
                }
-               if (SSL_set_fd(ssl, s) == 0) {
-                       ERR_print_errors_fp(ttyout);
+               if (ressl_configure(ssl, ressl_config) != 0) {
+                       fprintf(ttyout, "SSL configuration failure: %s\n",
+                           ressl_error(ssl));
                        goto cleanup_url_get;
                }
-               /*
-                * RFC4366 (SNI): Literal IPv4 and IPv6 addresses are not
-                * permitted in "HostName".
-                */
-               if (inet_pton(AF_INET,  host, &addrbuf) != 1 &&
-                   inet_pton(AF_INET6, host, &addrbuf) != 1) {
-                       if (SSL_set_tlsext_host_name(ssl, host) == 0) {
-                               ERR_print_errors_fp(ttyout);
-                               goto cleanup_url_get;
-                       }
-               }
-               if (SSL_connect(ssl) <= 0) {
-                       ERR_print_errors_fp(ttyout);
+               if (ressl_connect_socket(ssl, s, host) != 0) {
+                       fprintf(ttyout, "SSL failure: %s\n", ressl_error(ssl));
                        goto cleanup_url_get;
                }
-               if (ssl_verify) {
-                       X509    *cert;
-
-                       cert = SSL_get_peer_certificate(ssl);
-                       if (cert == NULL) {
-                               fprintf(ttyout, "%s: no server certificate\n",
-                                   getprogname());
-                               goto cleanup_url_get;
-                       }
-
-                       if (ssl_check_hostname(cert, host) != 0) {
-                               X509_free(cert);
-                               fprintf(ttyout, "%s: host `%s' not present in"
-                                   " server certificate\n",
-                                   getprogname(), host);
-                               goto cleanup_url_get;
-                       }
-
-                       X509_free(cert);
-               }
        } else {
                fin = fdopen(s, "r+");
        }
@@ -1217,9 +970,9 @@ improper:
 
 cleanup_url_get:
 #ifndef SMALL
-       if (ssl) {
-               SSL_shutdown(ssl);
-               SSL_free(ssl);
+       if (ssl != NULL) {
+               ressl_close(ssl);
+               ressl_free(ssl);
        }
        free(full_host);
        free(credentials);
@@ -1673,7 +1426,7 @@ isurl(const char *p)
 }
 
 char *
-ftp_readline(FILE *fp, SSL *ssl, size_t *lenp)
+ftp_readline(FILE *fp, struct ressl *ssl, size_t *lenp)
 {
        if (fp != NULL)
                return fparseln(fp, lenp, NULL, "\0\0\0", 0);
@@ -1686,18 +1439,16 @@ ftp_readline(FILE *fp, SSL *ssl, size_t *lenp)
 }
 
 size_t
-ftp_read(FILE *fp, SSL *ssl, char *buf, size_t len)
+ftp_read(FILE *fp, struct ressl *ssl, char *buf, size_t len)
 {
        size_t ret;
        if (fp != NULL)
                ret = fread(buf, sizeof(char), len, fp);
 #ifndef SMALL
        else if (ssl != NULL) {
-               int nr;
+               size_t nr;
 
-               if (len > INT_MAX)
-                       len = INT_MAX;
-               if ((nr = SSL_read(ssl, buf, (int)len)) <= 0)
+               if ((ret = ressl_read(ssl, buf, len, &nr)) != 0)
                        ret = 0;
                else
                        ret = nr;
@@ -1709,7 +1460,7 @@ ftp_read(FILE *fp, SSL *ssl, char *buf, size_t len)
 }
 
 int
-ftp_printf(FILE *fp, SSL *ssl, const char *fmt, ...)
+ftp_printf(FILE *fp, struct ressl *ssl, const char *fmt, ...)
 {
        int ret;
        va_list ap;
@@ -1720,7 +1471,7 @@ ftp_printf(FILE *fp, SSL *ssl, const char *fmt, ...)
                ret = vfprintf(fp, fmt, ap);
 #ifndef SMALL
        else if (ssl != NULL)
-               ret = SSL_vprintf((SSL*)ssl, fmt, ap);
+               ret = SSL_vprintf(ssl, fmt, ap);
 #endif /* !SMALL */
        else
                ret = 0;
@@ -1731,22 +1482,23 @@ ftp_printf(FILE *fp, SSL *ssl, const char *fmt, ...)
 
 #ifndef SMALL
 int
-SSL_vprintf(SSL *ssl, const char *fmt, va_list ap)
+SSL_vprintf(struct ressl *ssl, const char *fmt, va_list ap)
 {
-       int ret;
        char *string;
+       size_t nw;
+       int ret;
 
        if ((ret = vasprintf(&string, fmt, ap)) == -1)
                return ret;
-       ret = SSL_write(ssl, string, ret);
+       ret = ressl_write(ssl, string, ret, &nw);
        free(string);
        return ret;
 }
 
 char *
-SSL_readline(SSL *ssl, size_t *lenp)
+SSL_readline(struct ressl *ssl, size_t *lenp)
 {
-       size_t i, len;
+       size_t i, len, nr;
        char *buf, *q, c;
        int ret;
 
@@ -1761,14 +1513,12 @@ SSL_readline(SSL *ssl, size_t *lenp)
                        len *= 2;
                }
 again:
-               ret = SSL_read(ssl, &c, 1);
-               if (ret <= 0) {
-                       if (SSL_get_error(ssl, ret) == SSL_ERROR_WANT_READ)
-                               goto again;
-                       else
-                               errx(1, "SSL_read error: %u",
-                                   SSL_get_error(ssl, ret));
-               }
+               ret = ressl_read(ssl, &c, 1, &nr);
+               if (ret == -2)
+                       goto again;
+               if (ret != 0)
+                       errx(1, "SSL read error: %u", ret);
+
                buf[i] = c;
                if (c == '\n')
                        break;
index eef6ba2..5d8cf41 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ftp_var.h,v 1.34 2014/07/11 03:31:52 lteo Exp $       */
+/*     $OpenBSD: ftp_var.h,v 1.35 2014/07/14 09:26:27 jsing Exp $      */
 /*     $NetBSD: ftp_var.h,v 1.18 1997/08/18 10:20:25 lukem Exp $       */
 
 /*
@@ -77,6 +77,8 @@
 int fclose(FILE *);
 #endif
 
+#include <ressl.h>
+
 #include "stringlist.h"
 #include "extern.h"
 #include "small.h"
@@ -232,12 +234,5 @@ 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
+extern struct ressl_config *ressl_config;
 #endif /* !SMALL */
index 5d68d21..7631889 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: main.c,v 1.90 2014/07/14 05:54:12 deraadt Exp $       */
+/*     $OpenBSD: main.c,v 1.91 2014/07/14 09:26:27 jsing Exp $ */
 /*     $NetBSD: main.c,v 1.24 1997/08/18 10:20:26 lukem Exp $  */
 
 /*
 #include <string.h>
 #include <unistd.h>
 
-#include "ftp_var.h"
+#include <ressl.h>
+
 #include "cmds.h"
+#include "ftp_var.h"
 
 #ifndef SMALL
 char * const ssl_verify_opts[] = {
@@ -95,11 +97,8 @@ char * const ssl_verify_opts[] = {
        "depth",
        NULL
 };
-char   *ssl_ciphers;
-int     ssl_verify = 1;
-int     ssl_verify_depth = -1;
-char   *ssl_ca_file;
-char   *ssl_ca_path;
+
+struct ressl_config *ressl_config;
 #endif /* !SMALL */
 
 int family = PF_UNSPEC;
@@ -114,6 +113,9 @@ main(volatile int argc, char *argv[])
        char *outfile = NULL;
        const char *errstr;
        int dumb_terminal = 0;
+#ifndef SMALL
+       long long depth;
+#endif
 
        ftpport = "ftp";
        httpport = "http";
@@ -307,6 +309,12 @@ main(volatile int argc, char *argv[])
 
                case 'S':
 #ifndef SMALL
+                       if (ressl_config == NULL) {
+                               ressl_config = ressl_config_new();
+                               if (ressl_config == NULL)
+                                       errx(1, "ressl config failed");
+                       }
+
                        cp = optarg;
                        while (*cp) {
                                char    *str;
@@ -314,34 +322,40 @@ main(volatile int argc, char *argv[])
                                case SSL_CAFILE:
                                        if (str == NULL)
                                                errx(1, "missing CA file");
-                                       ssl_ca_file = str;
+                                       ressl_config_set_ca_file(ressl_config,
+                                           str);
                                        break;
                                case SSL_CAPATH:
                                        if (str == NULL)
                                                errx(1, "missing CA directory"
                                                    " path");
-                                       ssl_ca_path = str;
+                                       ressl_config_set_ca_path(ressl_config,
+                                           str);
                                        break;
                                case SSL_CIPHERS:
                                        if (str == NULL)
                                                errx(1, "missing cipher list");
-                                       ssl_ciphers = str;
+                                       ressl_config_set_ciphers(ressl_config,
+                                           str);
                                        break;
                                case SSL_DONTVERIFY:
-                                       ssl_verify = 0;
+                                       ressl_config_insecure_no_verify(
+                                           ressl_config);
                                        break;
                                case SSL_DOVERIFY:
-                                       ssl_verify = 1;
+                                       ressl_config_verify(ressl_config);
                                        break;
                                case SSL_VERIFYDEPTH:
                                        if (str == NULL)
                                                errx(1, "missing depth");
-                                       ssl_verify_depth = strtonum(str, 0,
-                                           INT_MAX, &errstr);
+                                       depth = strtonum(str, 0, INT_MAX,
+                                           &errstr);
                                        if (errstr)
                                                errx(1, "certificate "
                                                    "validation depth is %s",
                                                    errstr);
+                                       ressl_config_set_verify_depth(
+                                           ressl_config, (int)depth);
                                        break;
                                default:
                                        errx(1, "unknown -S suboption `%s'",