Index: head/www/mod_md-devel/Makefile =================================================================== --- head/www/mod_md-devel/Makefile (revision 449712) +++ head/www/mod_md-devel/Makefile (revision 449713) @@ -1,52 +1,52 @@ # Created by: Bernard Spil # $FreeBSD$ PORTNAME= mod_md-devel -PORTVERSION= 0.9.2 +PORTVERSION= 0.9.4 DISTVERSIONPREFIX= v CATEGORIES= www MAINTAINER= brnrd@FreeBSD.org COMMENT= Early experience LetsEncrypt module for Apache httpd LICENSE= APACHE20 LICENSE_FILE= ${WRKSRC}/LICENSE LIB_DEPENDS= libcurl.so:ftp/curl \ libjansson.so:devel/jansson USES= autoreconf libtool ssl USE_GITHUB= yes USE_APACHE= 24+ GH_ACCOUNT= icing GH_PROJECT= mod_md GNU_CONFIGURE= yes CONFIGURE_ARGS= --program-prefix=ext- CONFIGURE_ENV= CONFIG_SHELL=/bin/sh MODULENAME= ${GH_PROJECT} CFLAGS+= -I${LOCALBASE}/include CPPFLAGS+= -I${LOCALBASE}/include DOCSDIR= share/doc/mod_md PORTDOCS= README README.md PLIST_FILES= ${APACHEMODDIR}/mod_md.so.0.0.0 \ ${APACHEMODDIR}/mod_md.so \ bin/a2md .include .if ${OPSYS} == FreeBSD && ${OSVERSION} < 1100085 && ${SSL_DEFAULT} == base IGNORE= port requires OpenSSL 1.0.2 or later, set DEFAULT_VERSIONS+= ssl=openssl .endif post-install: ${STRIP_CMD} ${STAGEDIR}${PREFIX}/${APACHEMODDIR}/${MODULENAME}.so ${INSTALL} ${WRKSRC}/src/a2md ${STAGEDIR}${PREFIX}/bin/a2md ${RM} ${STAGEDIR}${PREFIX}/share/doc/mod_md/LICENSE ${RM} ${STAGEDIR}${PREFIX}/bin/ext-a2md .include Index: head/www/mod_md-devel/distinfo =================================================================== --- head/www/mod_md-devel/distinfo (revision 449712) +++ head/www/mod_md-devel/distinfo (revision 449713) @@ -1,3 +1,3 @@ -TIMESTAMP = 1505041445 -SHA256 (icing-mod_md-v0.9.2_GH0.tar.gz) = 03ae47a2d76ad4e1cf63e6e98f5500e5810cd9e939481b779c8287816a1faff6 -SIZE (icing-mod_md-v0.9.2_GH0.tar.gz) = 182061 +TIMESTAMP = 1505234028 +SHA256 (icing-mod_md-v0.9.4_GH0.tar.gz) = f9798bc013053673d51109754cce45b720e4cebea59c292de5c006e55ded9c9d +SIZE (icing-mod_md-v0.9.4_GH0.tar.gz) = 187378 Index: head/www/mod_md-devel/files/patch-src_md__crypt.c =================================================================== --- head/www/mod_md-devel/files/patch-src_md__crypt.c (revision 449712) +++ head/www/mod_md-devel/files/patch-src_md__crypt.c (nonexistent) @@ -1,437 +0,0 @@ ---- src/md_crypt.c.orig 2017-09-08 14:09:36 UTC -+++ src/md_crypt.c -@@ -116,6 +116,425 @@ static void seed_RAND(int pid) - - #endif /*ifdef MD_HAVE_ARC4RANDOM (else part) */ - -+#ifdef LIBRESSL_VERSION_NUMBER -+ -+/* Extracted from OpenSSL 1.0.2 */ -+ -+struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result) -+{ -+ struct tm *ts = NULL; -+ -+#if defined(OPENSSL_THREADS) && defined(OPENSSL_SYS_VMS) -+ { -+ struct tm data, *ts2 = &data; -+ if (gmtime_r(timer, ts2) == NULL) -+ return NULL; -+ memcpy(result, ts2, sizeof(struct tm)); -+ ts = result; -+ } -+#elif defined(OPENSSL_THREADS) && !defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_SYS_MACOSX) -+ if (gmtime_r(timer, result) == NULL) -+ return NULL; -+ ts = result; -+#else -+ ts = gmtime(timer); -+ if (ts == NULL) -+ return NULL; -+ -+ memcpy(result, ts, sizeof(struct tm)); -+ ts = result; -+#endif -+ return ts; -+} -+ -+#define SECS_PER_DAY (24 * 60 * 60) -+# define ASN1_STRING_FLAG_X509_TIME 0x100 -+ -+static int leap_year(const int year) -+{ -+ if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) -+ return 1; -+ return 0; -+} -+ -+/* -+ * Compute the day of the week and the day of the year from the year, month -+ * and day. The day of the year is straightforward, the day of the week uses -+ * a form of Zeller's congruence. For this months start with March and are -+ * numbered 4 through 15. -+ */ -+static void determine_days(struct tm *tm) -+{ -+ static const int ydays[12] = { -+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 -+ }; -+ int y = tm->tm_year + 1900; -+ int m = tm->tm_mon; -+ int d = tm->tm_mday; -+ int c; -+ -+ tm->tm_yday = ydays[m] + d - 1; -+ if (m >= 2) { -+ /* March and onwards can be one day further into the year */ -+ tm->tm_yday += leap_year(y); -+ m += 2; -+ } else { -+ /* Treat January and February as part of the previous year */ -+ m += 14; -+ y--; -+ } -+ c = y / 100; -+ y %= 100; -+ /* Zeller's congruance */ -+ tm->tm_wday = (d + (13 * m) / 5 + y + y / 4 + c / 4 + 5 * c + 6) % 7; -+} -+ -+/* -+ * Convert date to and from julian day Uses Fliegel & Van Flandern algorithm -+ */ -+static long date_to_julian(int y, int m, int d) -+{ -+ return (1461 * (y + 4800 + (m - 14) / 12)) / 4 + -+ (367 * (m - 2 - 12 * ((m - 14) / 12))) / 12 - -+ (3 * ((y + 4900 + (m - 14) / 12) / 100)) / 4 + d - 32075; -+} -+ -+static void julian_to_date(long jd, int *y, int *m, int *d) -+{ -+ long L = jd + 68569; -+ long n = (4 * L) / 146097; -+ long i, j; -+ -+ L = L - (146097 * n + 3) / 4; -+ i = (4000 * (L + 1)) / 1461001; -+ L = L - (1461 * i) / 4 + 31; -+ j = (80 * L) / 2447; -+ *d = L - (2447 * j) / 80; -+ L = j / 11; -+ *m = j + 2 - (12 * L); -+ *y = 100 * (n - 49) + i + L; -+} -+ -+/* Convert tm structure and offset into julian day and seconds */ -+static int julian_adj(const struct tm *tm, int off_day, long offset_sec, -+ long *pday, int *psec) -+{ -+ int offset_hms, offset_day; -+ long time_jd; -+ int time_year, time_month, time_day; -+ /* split offset into days and day seconds */ -+ offset_day = offset_sec / SECS_PER_DAY; -+ /* Avoid sign issues with % operator */ -+ offset_hms = offset_sec - (offset_day * SECS_PER_DAY); -+ offset_day += off_day; -+ /* Add current time seconds to offset */ -+ offset_hms += tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec; -+ /* Adjust day seconds if overflow */ -+ if (offset_hms >= SECS_PER_DAY) { -+ offset_day++; -+ offset_hms -= SECS_PER_DAY; -+ } else if (offset_hms < 0) { -+ offset_day--; -+ offset_hms += SECS_PER_DAY; -+ } -+ -+ /* -+ * Convert date of time structure into a Julian day number. -+ */ -+ -+ time_year = tm->tm_year + 1900; -+ time_month = tm->tm_mon + 1; -+ time_day = tm->tm_mday; -+ -+ time_jd = date_to_julian(time_year, time_month, time_day); -+ -+ /* Work out Julian day of new date */ -+ time_jd += offset_day; -+ -+ if (time_jd < 0) -+ return 0; -+ -+ *pday = time_jd; -+ *psec = offset_hms; -+ return 1; -+} -+ -+int OPENSSL_gmtime_adj(struct tm *tm, int off_day, long offset_sec) -+{ -+ int time_sec, time_year, time_month, time_day; -+ long time_jd; -+ -+ /* Convert time and offset into Julian day and seconds */ -+ if (!julian_adj(tm, off_day, offset_sec, &time_jd, &time_sec)) -+ return 0; -+ -+ /* Convert Julian day back to date */ -+ -+ julian_to_date(time_jd, &time_year, &time_month, &time_day); -+ -+ if (time_year < 1900 || time_year > 9999) -+ return 0; -+ -+ /* Update tm structure */ -+ -+ tm->tm_year = time_year - 1900; -+ tm->tm_mon = time_month - 1; -+ tm->tm_mday = time_day; -+ -+ tm->tm_hour = time_sec / 3600; -+ tm->tm_min = (time_sec / 60) % 60; -+ tm->tm_sec = time_sec % 60; -+ -+ return 1; -+ -+} -+ -+int OPENSSL_gmtime_diff(int *pday, int *psec, -+ const struct tm *from, const struct tm *to) -+{ -+ int from_sec, to_sec, diff_sec; -+ long from_jd, to_jd, diff_day; -+ if (!julian_adj(from, 0, 0, &from_jd, &from_sec)) -+ return 0; -+ if (!julian_adj(to, 0, 0, &to_jd, &to_sec)) -+ return 0; -+ diff_day = to_jd - from_jd; -+ diff_sec = to_sec - from_sec; -+ /* Adjust differences so both positive or both negative */ -+ if (diff_day > 0 && diff_sec < 0) { -+ diff_day--; -+ diff_sec += SECS_PER_DAY; -+ } -+ if (diff_day < 0 && diff_sec > 0) { -+ diff_day++; -+ diff_sec -= SECS_PER_DAY; -+ } -+ -+ if (pday) -+ *pday = (int)diff_day; -+ if (psec) -+ *psec = diff_sec; -+ -+ return 1; -+ -+} -+ -+int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d) -+{ -+ static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 }; -+ static const int max[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 }; -+ static const int mdays[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; -+ char *a; -+ int n, i, i2, l, o, min_l = 11, strict = 0, end = 6, btz = 5, md; -+ struct tm tmp; -+ -+ /* -+ * ASN1_STRING_FLAG_X509_TIME is used to enforce RFC 5280 -+ * time string format, in which: -+ * -+ * 1. "seconds" is a 'MUST' -+ * 2. "Zulu" timezone is a 'MUST' -+ * 3. "+|-" is not allowed to indicate a time zone -+ */ -+ if (d->type == V_ASN1_UTCTIME) { -+ if (d->flags & ASN1_STRING_FLAG_X509_TIME) { -+ min_l = 13; -+ strict = 1; -+ } -+ } else if (d->type == V_ASN1_GENERALIZEDTIME) { -+ end = 7; -+ btz = 6; -+ if (d->flags & ASN1_STRING_FLAG_X509_TIME) { -+ min_l = 15; -+ strict = 1; -+ } else { -+ min_l = 13; -+ } -+ } else { -+ return 0; -+ } -+ -+ l = d->length; -+ a = (char *)d->data; -+ o = 0; -+ memset(&tmp, 0, sizeof(tmp)); -+ -+ /* -+ * GENERALIZEDTIME is similar to UTCTIME except the year is represented -+ * as YYYY. This stuff treats everything as a two digit field so make -+ * first two fields 00 to 99 -+ */ -+ -+ if (l < min_l) -+ goto err; -+ for (i = 0; i < end; i++) { -+ if (!strict && (i == btz) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) { -+ i++; -+ break; -+ } -+ if (!isdigit(a[o])) -+ goto err; -+ n = a[o] - '0'; -+ /* incomplete 2-digital number */ -+ if (++o == l) -+ goto err; -+ -+ if (!isdigit(a[o])) -+ goto err; -+ n = (n * 10) + a[o] - '0'; -+ /* no more bytes to read, but we haven't seen time-zone yet */ -+ if (++o == l) -+ goto err; -+ -+ i2 = (d->type == V_ASN1_UTCTIME) ? i + 1 : i; -+ -+ if ((n < min[i2]) || (n > max[i2])) -+ goto err; -+ switch (i2) { -+ case 0: -+ /* UTC will never be here */ -+ tmp.tm_year = n * 100 - 1900; -+ break; -+ case 1: -+ if (d->type == V_ASN1_UTCTIME) -+ tmp.tm_year = n < 50 ? n + 100 : n; -+ else -+ tmp.tm_year += n; -+ break; -+ case 2: -+ tmp.tm_mon = n - 1; -+ break; -+ case 3: -+ /* check if tm_mday is valid in tm_mon */ -+ if (tmp.tm_mon == 1) { -+ /* it's February */ -+ md = mdays[1] + leap_year(tmp.tm_year + 1900); -+ } else { -+ md = mdays[tmp.tm_mon]; -+ } -+ if (n > md) -+ goto err; -+ tmp.tm_mday = n; -+ determine_days(&tmp); -+ break; -+ case 4: -+ tmp.tm_hour = n; -+ break; -+ case 5: -+ tmp.tm_min = n; -+ break; -+ case 6: -+ tmp.tm_sec = n; -+ break; -+ } -+ } -+ -+ /* -+ * Optional fractional seconds: decimal point followed by one or more -+ * digits. -+ */ -+ if (d->type == V_ASN1_GENERALIZEDTIME && a[o] == '.') { -+ if (strict) -+ /* RFC 5280 forbids fractional seconds */ -+ goto err; -+ if (++o == l) -+ goto err; -+ i = o; -+ while ((o < l) && isdigit(a[o])) -+ o++; -+ /* Must have at least one digit after decimal point */ -+ if (i == o) -+ goto err; -+ /* no more bytes to read, but we haven't seen time-zone yet */ -+ if (o == l) -+ goto err; -+ } -+ -+ /* -+ * 'o' will never point to '\0' at this point, the only chance -+ * 'o' can point to '\0' is either the subsequent if or the first -+ * else if is true. -+ */ -+ if (a[o] == 'Z') { -+ o++; -+ } else if (!strict && ((a[o] == '+') || (a[o] == '-'))) { -+ int offsign = a[o] == '-' ? 1 : -1; -+ int offset = 0; -+ -+ o++; -+ /* -+ * if not equal, no need to do subsequent checks -+ * since the following for-loop will add 'o' by 4 -+ * and the final return statement will check if 'l' -+ * and 'o' are equal. -+ */ -+ if (o + 4 != l) -+ goto err; -+ for (i = end; i < end + 2; i++) { -+ if (!isdigit(a[o])) -+ goto err; -+ n = a[o] - '0'; -+ o++; -+ if (!isdigit(a[o])) -+ goto err; -+ n = (n * 10) + a[o] - '0'; -+ i2 = (d->type == V_ASN1_UTCTIME) ? i + 1 : i; -+ if ((n < min[i2]) || (n > max[i2])) -+ goto err; -+ /* if tm is NULL, no need to adjust */ -+ if (tm != NULL) { -+ if (i == end) -+ offset = n * 3600; -+ else if (i == end + 1) -+ offset += n * 60; -+ } -+ o++; -+ } -+ if (offset && !OPENSSL_gmtime_adj(&tmp, 0, offset * offsign)) -+ goto err; -+ } else { -+ /* not Z, or not +/- in non-strict mode */ -+ goto err; -+ } -+ if (o == l) { -+ /* success, check if tm should be filled */ -+ if (tm != NULL) -+ *tm = tmp; -+ return 1; -+ } -+ err: -+ return 0; -+} -+ -+int ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm) -+{ -+ if (s == NULL) { -+ time_t now_t; -+ -+ time(&now_t); -+ memset(tm, 0, sizeof(*tm)); -+ if (OPENSSL_gmtime(&now_t, tm) != NULL) -+ return 1; -+ return 0; -+ } -+ -+ return asn1_time_to_tm(tm, s); -+} -+ -+int ASN1_TIME_diff(int *pday, int *psec, -+ const ASN1_TIME *from, const ASN1_TIME *to) -+{ -+ struct tm tm_from, tm_to; -+ -+ if (!ASN1_TIME_to_tm(from, &tm_from)) -+ return 0; -+ if (!ASN1_TIME_to_tm(to, &tm_to)) -+ return 0; -+ return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to); -+} -+ -+#endif /*ifdef LIBRESSL_VERSION_NUMBER*/ -+ - - apr_status_t md_crypt_init(apr_pool_t *pool) - { -@@ -409,7 +828,7 @@ apr_status_t md_pkey_gen(md_pkey_t **ppk - } - } - --#if OPENSSL_VERSION_NUMBER < 0x10100000L -+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - - #ifndef NID_tlsfeature - #define NID_tlsfeature 1020 Property changes on: head/www/mod_md-devel/files/patch-src_md__crypt.c ___________________________________________________________________ Deleted: fbsd:nokeywords ## -1 +0,0 ## -yes \ No newline at end of property Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/www/mod_md-devel/files/extra-patch-mod_ssl =================================================================== --- head/www/mod_md-devel/files/extra-patch-mod_ssl (revision 449712) +++ head/www/mod_md-devel/files/extra-patch-mod_ssl (revision 449713) @@ -1,280 +1,279 @@ Index: modules/ssl/ssl_engine_init.c -24c84dc from https://github.com/icing/mod_md/blob/master/patches/mod_ssl_md-2.4.x-v4.diff =================================================================== ---- modules/ssl/ssl_engine_init.c (revision 1807228) +--- modules/ssl/ssl_engine_init.c (revision 1808124) +++ modules/ssl/ssl_engine_init.c (working copy) @@ -164,6 +164,41 @@ modver, AP_SERVER_BASEVERSION, incver); } +/**************************************************************************************************/ +/* Managed Domains Interface (temporary here) */ + +APR_DECLARE_OPTIONAL_FN(int, + md_is_managed, (struct server_rec *)); + +APR_DECLARE_OPTIONAL_FN(apr_status_t, + md_get_credentials, (struct server_rec *, apr_pool_t *, + const char **pkeyfile, + const char **pcertfile, + const char **pchainfile)); +APR_DECLARE_OPTIONAL_FN(apr_status_t, + md_get_certificate, (struct server_rec *, apr_pool_t *, + const char **pkeyfile, + const char **pcertfile)); +APR_DECLARE_OPTIONAL_FN(int, + md_is_challenge, (struct conn_rec *, const char *, + X509 **, EVP_PKEY **)); + +static APR_OPTIONAL_FN_TYPE(md_is_managed) *md_is_managed; +static APR_OPTIONAL_FN_TYPE(md_get_credentials) *md_get_credentials; +static APR_OPTIONAL_FN_TYPE(md_get_certificate) *md_get_certificate; +static APR_OPTIONAL_FN_TYPE(md_is_challenge) *md_is_challenge; + +int ssl_is_challenge(conn_rec *c, const char *servername, + X509 **pcert, EVP_PKEY **pkey) +{ + if (md_is_challenge) { + return md_is_challenge(c, servername, pcert, pkey); + } + *pcert = NULL; + *pkey = NULL; + return 0; +} + /* * Per-module initialization */ -@@ -204,6 +224,18 @@ +@@ -204,6 +239,18 @@ ssl_config_global_create(base_server); /* just to avoid problems */ ssl_config_global_fix(mc); + /* Initialize our interface to mod_md, if it is loaded + */ + md_is_managed = APR_RETRIEVE_OPTIONAL_FN(md_is_managed); + md_get_credentials = APR_RETRIEVE_OPTIONAL_FN(md_get_credentials); + md_get_certificate = APR_RETRIEVE_OPTIONAL_FN(md_get_certificate); + md_is_challenge = APR_RETRIEVE_OPTIONAL_FN(md_is_challenge); + if (!md_is_managed || (!md_get_credentials && !md_get_certificate)) { + md_is_managed = NULL; + md_get_credentials = NULL; + md_get_certificate = NULL; + } + /* * try to fix the configuration and open the dedicated SSL * logfile as early as possible -@@ -1606,6 +1638,57 @@ +@@ -1606,6 +1653,57 @@ return APR_EGENERAL; } + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO() + "Init: (%s) mod_md support is %s.", ssl_util_vhostid(p, s), + md_is_managed? "available" : "unavailable"); + if (md_is_managed && md_is_managed(s)) { + modssl_pk_server_t *const pks = sc->server->pks; + if (pks->cert_files->nelts > 0 || pks->key_files->nelts > 0) { + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO() + "Init: (%s) You configured certificate/key files on this host, but " + "is is covered by a Managed Domain. You need to remove these directives " + "for the Managed Domain to take over.", ssl_util_vhostid(p, s)); + } + else { + const char *key_file, *cert_file, *chain_file; + + key_file = cert_file = chain_file = NULL; + + if (md_get_certificate) { + /* mod_md >= v0.9.0 */ + rv = md_get_certificate(s, p, &key_file, &cert_file); + } + else if (md_get_credentials) { + /* mod_md < v0.9.0, remove this after a while */ + rv = md_get_credentials(s, p, &key_file, &cert_file, &chain_file); + } + else { + rv = APR_ENOTIMPL; + } + + if (key_file && cert_file) { ++ ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, s, ++ "%s: installing key=%s, cert=%s, chain=%s", ++ ssl_util_vhostid(p, s), key_file, cert_file, chain_file); + APR_ARRAY_PUSH(pks->key_files, const char *) = key_file; + APR_ARRAY_PUSH(pks->cert_files, const char *) = cert_file; -+ if (chain_file) { -+ sc->server->cert_chain = chain_file; -+ } ++ sc->server->cert_chain = chain_file; + } + + if (APR_STATUS_IS_EAGAIN(rv)) { + /* Managed Domain not ready yet. This is not a reason to fail the config */ + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO() + "Init: %s will respond with '503 Service Unavailable' for now. This " + "host is part of a Managed Domain, but no SSL certificate is " + "available (yet).", ssl_util_vhostid(p, s)); + pks->service_unavailable = 1; -+ return APR_SUCCESS; + } + else if (rv != APR_SUCCESS) { + return rv; + } + } + } + if ((rv = ssl_init_ctx(s, p, ptemp, sc->server)) != APR_SUCCESS) { return rv; } Index: modules/ssl/ssl_engine_kernel.c =================================================================== ---- modules/ssl/ssl_engine_kernel.c (revision 1807581) +--- modules/ssl/ssl_engine_kernel.c (revision 1808124) +++ modules/ssl/ssl_engine_kernel.c (working copy) @@ -264,6 +264,15 @@ return DECLINED; } + if (sslconn->service_unavailable) { + /* This is set when the SSL properties of this connection are + * incomplete or if this connection was made to challenge a + * particular hostname (ACME). We never serve any request on + * such a connection. */ + /* TODO: a retry-after indicator would be nice here */ + return HTTP_SERVICE_UNAVAILABLE; + } + if (sslconn->non_ssl_request == NON_SSL_SET_ERROR_MSG) { apr_table_setn(r->notes, "error-notes", "Reason: You're speaking plain HTTP to an SSL-enabled " @@ -2110,6 +2119,8 @@ static apr_status_t init_vhost(conn_rec *c, SSL *ssl) { const char *servername; + X509 *cert; + EVP_PKEY *key; if (c) { SSLConnRec *sslcon = myConnConfig(c); @@ -2126,8 +2137,35 @@ ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02043) "SSL virtual host for servername %s found", servername); + return APR_SUCCESS; } + else if (ssl_is_challenge(c, servername, &cert, &key)) { + + sslcon->service_unavailable = 1; + if ((SSL_use_certificate(ssl, cert) < 1)) { + ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, c, APLOGNO() + "Failed to configure challenge certificate %s", + servername); + return APR_EGENERAL; + } + + if (!SSL_use_PrivateKey(ssl, key)) { + ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, c, APLOGNO() + "error '%s' using Challenge key: %s", + ERR_error_string(ERR_peek_last_error(), NULL), + servername); + return APR_EGENERAL; + } + + if (SSL_check_private_key(ssl) < 1) { + ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, c, APLOGNO() + "Challenbge certificate and private key %s " + "do not match", servername); + return APR_EGENERAL; + } + + } else { ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02044) "No matching SSL virtual host for servername " @@ -2233,6 +2271,8 @@ */ sslcon->server = s; sslcon->cipher_suite = sc->server->auth.cipher_suite; + sslcon->service_unavailable = sc->server->pks? + sc->server->pks->service_unavailable : 0; ap_update_child_status_from_server(c->sbh, SERVER_BUSY_READ, c, s); /* Index: modules/ssl/ssl_private.h =================================================================== ---- modules/ssl/ssl_private.h (revision 1807581) +--- modules/ssl/ssl_private.h (revision 1808124) +++ modules/ssl/ssl_private.h (working copy) -@@ -505,6 +505,7 @@ +@@ -524,6 +524,7 @@ server_rec *server; const char *cipher_suite; /* cipher suite used in last reneg */ + int service_unavailable; /* thouugh we negotiate SSL, no requests will be served */ } SSLConnRec; /* BIG FAT WARNING: SSLModConfigRec has unusual memory lifetime: it is -@@ -581,6 +582,9 @@ +@@ -600,6 +601,9 @@ * sent in the CertificateRequest message: */ const char *ca_name_path; const char *ca_name_file; + + /* TLS service for this server is suspended */ + int service_unavailable; } modssl_pk_server_t; typedef struct { -@@ -1046,6 +1050,9 @@ +@@ -1063,6 +1067,9 @@ * memory. */ DH *modssl_get_dh_params(unsigned keylen); +int ssl_is_challenge(conn_rec *c, const char *servername, + X509 **pcert, EVP_PKEY **pkey); + #endif /* SSL_PRIVATE_H */ /** @} */ Index: modules/ssl/ssl_util_ssl.c =================================================================== ---- modules/ssl/ssl_util_ssl.c (revision 1807581) +--- modules/ssl/ssl_util_ssl.c (revision 1808124) +++ modules/ssl/ssl_util_ssl.c (working copy) @@ -115,6 +115,33 @@ return rc; } +typedef struct { + const char *pass; + int pass_len; +} pass_ctx; + +static int provide_pass(char *buf, int size, int rwflag, void *baton) +{ + pass_ctx *ctx = baton; + if (ctx->pass_len > 0) { + if (ctx->pass_len < size) { + size = (int)ctx->pass_len; + } + memcpy(buf, ctx->pass, size); + } + return ctx->pass_len; +} + +EVP_PKEY *modssl_read_encrypted_pkey(const char *filename, EVP_PKEY **key, + const char *pass, apr_size_t pass_len) +{ + pass_ctx ctx; + + ctx.pass = pass; + ctx.pass_len = pass_len; + return modssl_read_privatekey(filename, key, provide_pass, &ctx); +} + /* _________________________________________________________________ ** ** Smart shutdown Index: modules/ssl/ssl_util_ssl.h =================================================================== ---- modules/ssl/ssl_util_ssl.h (revision 1807581) +--- modules/ssl/ssl_util_ssl.h (revision 1808124) +++ modules/ssl/ssl_util_ssl.h (working copy) @@ -65,6 +65,7 @@ void *modssl_get_app_data2(SSL *); void modssl_set_app_data2(SSL *, void *); EVP_PKEY *modssl_read_privatekey(const char *, EVP_PKEY **, pem_password_cb *, void *); +EVP_PKEY *modssl_read_encrypted_pkey(const char *, EVP_PKEY **, const char *, apr_size_t); int modssl_smart_shutdown(SSL *ssl); BOOL modssl_X509_getBC(X509 *, int *, int *); char *modssl_X509_NAME_ENTRY_to_string(apr_pool_t *p, X509_NAME_ENTRY *xsne);