Hi, I need to remember to recompile/install bozohttpd(8) on every binary upgrade if I change the minimum protocol version using 'BOZO_SSL_OPTIONS' at compile time. Similar to '-z' ciphers option, the attached diff allows to specify a minimum protocol version at runtime using an option '-m' that accepts "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2" and "TLSv1.3" as valid values.
For setting protocol version (using the recommeneded SSL_CTX_set_min_proto_version(3)), this works identical to the compile time BOZO_SSL_OPTIONS. However, it takes away the option of setting any other SSL_CTX_set_options(3) in combination to the version selection options that one could set during compile time. Is this a good idea?
diff --git a/libexec/httpd/bozohttpd.8 b/libexec/httpd/bozohttpd.8 --- a/libexec/httpd/bozohttpd.8 +++ b/libexec/httpd/bozohttpd.8 @@ -39,6 +39,7 @@ .Op Fl I Ar port .Op Fl L Ar prefix script .Op Fl M Ar suffix type encoding encoding11 +.Op Fl m Ar version .Op Fl P Ar pidfile .Op Fl R Ar readme .Op Fl S Ar version @@ -221,6 +222,18 @@ Multiple .Fl M options may be passed. +.It Fl m Ar version +Set the minimum supported SSL protocol +.Ar version . +The valid values of +.Ar version +are +.Dq SSLv3 , +.Dq TLSv1 , +.Dq TLSv1.1 , +.Dq TLSv1.2 , +and +.Dq TLSv1.3 . .It Fl n Stops .Nm diff --git a/libexec/httpd/bozohttpd.h b/libexec/httpd/bozohttpd.h --- a/libexec/httpd/bozohttpd.h +++ b/libexec/httpd/bozohttpd.h @@ -313,6 +313,7 @@ #ifdef NO_SSL_SUPPORT #define bozo_ssl_set_opts(w, x, y) bozo_noop #define bozo_ssl_set_ciphers(w, x) bozo_noop +#define bozo_ssl_set_min_proto(x) bozo_noop #define bozo_ssl_init(x) bozo_noop #define bozo_ssl_accept(x) (0) #define bozo_ssl_shutdown(x) bozo_noop @@ -321,6 +322,7 @@ #else void bozo_ssl_set_opts(bozohttpd_t *, const char *, const char *); void bozo_ssl_set_ciphers(bozohttpd_t *, const char *); +void bozo_ssl_set_min_proto(bozohttpd_t *, const char *); void bozo_ssl_init(bozohttpd_t *); int bozo_ssl_accept(bozohttpd_t *); void bozo_ssl_shutdown(bozohttpd_t *); diff --git a/libexec/httpd/main.c b/libexec/httpd/main.c --- a/libexec/httpd/main.c +++ b/libexec/httpd/main.c @@ -165,7 +165,7 @@ */ while ((c = getopt(argc, argv, - "C:EGHI:L:M:P:R:S:T:U:VXZ:bc:defhi:np:st:uv:x:z:")) != -1) { + "C:EGHI:L:M:m:P:R:S:T:U:VXZ:bc:defhi:np:st:uv:x:z:")) != -1) { switch (c) { case 'b': @@ -283,6 +283,13 @@ optind += 3; break; + case 'm': + if (!have_ssl) + goto no_ssl; + + bozo_ssl_set_min_proto(&httpd, optarg); + break; + case 'n': bozo_set_pref(&httpd, &prefs, "numeric", "true"); break; diff --git a/libexec/httpd/ssl-bozo.c b/libexec/httpd/ssl-bozo.c --- a/libexec/httpd/ssl-bozo.c +++ b/libexec/httpd/ssl-bozo.c @@ -61,13 +61,6 @@ "!KRB5-DES-CBC3-SHA" #endif -#ifndef BOZO_SSL_OPTIONS -#define BOZO_SSL_OPTIONS \ - ((long)(SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1)) -#endif - - /* this structure encapsulates the ssl info */ - /* this structure encapsulates the ssl info */ typedef struct sslinfo_t { SSL_CTX *ssl_context; @@ -76,6 +69,7 @@ char *certificate_file; char *privatekey_file; char *ciphers; + char *min_proto_version; } sslinfo_t; /* @@ -204,11 +198,32 @@ return (ssize_t)ret; } +static int +bozo_ssl_version(const char *version) +{ + + if (strcmp(version, "SSLv3") == 0) + return SSL3_VERSION; + + if (strcmp(version, "TLSv1") == 0) + return TLS1_VERSION; + + if (strcmp(version, "TLSv1.1") == 0) + return TLS1_1_VERSION; + + if (strcmp(version, "TLSv1.2") == 0) + return TLS1_2_VERSION; + + if (strcmp(version, "TLSv1.3") == 0) + return TLS1_3_VERSION; + + return -1; +} void bozo_ssl_init(bozohttpd_t *httpd) { sslinfo_t *sslinfo = httpd->sslinfo; - long options; + int proto; if (sslinfo == NULL || !sslinfo->certificate_file) return; @@ -222,12 +237,13 @@ bozo_ssl_err(httpd, EXIT_FAILURE, "SSL context creation failed"); - options = SSL_CTX_set_options(sslinfo->ssl_context, - BOZO_SSL_OPTIONS); - if ((options & BOZO_SSL_OPTIONS) != BOZO_SSL_OPTIONS) + proto = sslinfo->min_proto_version ? + bozo_ssl_version(sslinfo->min_proto_version) : TLS1_1_VERSION; + + if (!SSL_CTX_set_min_proto_version(sslinfo->ssl_context, proto)) bozo_ssl_err(httpd, EXIT_FAILURE, - "Error setting ssl options requested %#lx, got %#lx", - BOZO_SSL_OPTIONS, options); + "Error setting minimum protocol version '%s'", + sslinfo->min_proto_version); if (!SSL_CTX_set_cipher_list(sslinfo->ssl_context, sslinfo->ciphers ? sslinfo->ciphers : BOZO_SSL_CIPHERS)) @@ -340,6 +356,15 @@ debug((httpd, DEBUG_NORMAL, "using ciphers: %s", sslinfo->ciphers)); } +void +bozo_ssl_set_min_proto(bozohttpd_t *httpd, const char *version) +{ + sslinfo_t *sslinfo = bozo_get_sslinfo(httpd); + + sslinfo->min_proto_version = bozostrdup(httpd, NULL, version); + debug((httpd, DEBUG_NORMAL, + "using minimum protocol version: %s", version)); +} #endif /* NO_SSL_SUPPORT */ /*