Date: Sun, 13 Aug 2017 13:15:10 +0000 (UTC) From: Bernard Spil <brnrd@FreeBSD.org> To: ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org Subject: svn commit: r447884 - in head/www: . mod_md-devel mod_md-devel/files Message-ID: <201708131315.v7DDFAAj074343@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: brnrd Date: Sun Aug 13 13:15:10 2017 New Revision: 447884 URL: https://svnweb.freebsd.org/changeset/ports/447884 Log: www/mod_md-devel: Early experience LetsEncrypt module - New port Added: head/www/mod_md-devel/ head/www/mod_md-devel/Makefile (contents, props changed) head/www/mod_md-devel/distinfo (contents, props changed) head/www/mod_md-devel/files/ head/www/mod_md-devel/files/patch-src_md__crypt.c (contents, props changed) head/www/mod_md-devel/pkg-descr (contents, props changed) head/www/mod_md-devel/pkg-message (contents, props changed) Modified: head/www/Makefile Modified: head/www/Makefile ============================================================================== --- head/www/Makefile Sun Aug 13 12:58:43 2017 (r447883) +++ head/www/Makefile Sun Aug 13 13:15:10 2017 (r447884) @@ -463,6 +463,7 @@ SUBDIR += mod_log_sql2 SUBDIR += mod_log_sql2-dtc SUBDIR += mod_macro22 + SUBDIR += mod_md-devel SUBDIR += mod_memcache SUBDIR += mod_memcache_block SUBDIR += mod_mono Added: head/www/mod_md-devel/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/mod_md-devel/Makefile Sun Aug 13 13:15:10 2017 (r447884) @@ -0,0 +1,45 @@ +# Created by: Bernard Spil <brnrd@FreeBSD.org> +# $FreeBSD$ + +PORTNAME= mod_md-devel +PORTVERSION= 0.0.20170809 +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= apache:2.4+ autoreconf libtool ssl +USE_GITHUB= yes +USE_APACHE= 24 + +GH_ACCOUNT= icing +GH_PROJECT= mod_md +GH_TAGNAME= 1e07174 + +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/docs/mod_md +PORTDOCS= README README.md +PLIST_FILES= ${APACHEMODDIR}/mod_md.so.0.0.0 \ + ${APACHEMODDIR}/mod_md.so + +post-install: + ${STRIP_CMD} ${STAGEDIR}${PREFIX}/${APACHEMODDIR}/${MODULENAME}.so + ${MV} ${STAGEDIR}${PREFIX}/share/doc/mod_cert ${STAGEDIR}${PREFIX}/share/doc/mod_md-devel + ${RM} ${STAGEDIR}${PREFIX}/share/doc/mod_md-devel/LICENSE + ${RM} ${STAGEDIR}${PREFIX}/bin/ext-a2md + +.include <bsd.port.mk> Added: head/www/mod_md-devel/distinfo ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/mod_md-devel/distinfo Sun Aug 13 13:15:10 2017 (r447884) @@ -0,0 +1,3 @@ +TIMESTAMP = 1502629875 +SHA256 (icing-mod_md-0.0.20170809-1e07174_GH0.tar.gz) = 26a9f89eb822c21faa5805a666167f687c651baa68b4aed235f9dffec2c85a4f +SIZE (icing-mod_md-0.0.20170809-1e07174_GH0.tar.gz) = 163588 Added: head/www/mod_md-devel/files/patch-src_md__crypt.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/mod_md-devel/files/patch-src_md__crypt.c Sun Aug 13 13:15:10 2017 (r447884) @@ -0,0 +1,437 @@ +--- src/md_crypt.c.orig 2017-08-09 13:30:59 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) + { +@@ -328,7 +747,7 @@ apr_status_t md_pkey_gen_rsa(md_pkey_t * + return rv; + } + +-#if OPENSSL_VERSION_NUMBER < 0x10100000L ++#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + + #ifndef NID_tlsfeature + #define NID_tlsfeature 1020 Added: head/www/mod_md-devel/pkg-descr ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/mod_md-devel/pkg-descr Sun Aug 13 13:15:10 2017 (r447884) @@ -0,0 +1,9 @@ +mod_md a module for Apache httpd that adds support for Let's Encrypt +(and other ACME CAs) as an early experience version. + +This port is here to help people review and comment and test before +it is put into the main Apache httpd repository. Issues you can raise +on the project's website. General discussion is probably best at the +apache httpd-dev mailing list. + +WWW: https://github.com/icing/mod_md Added: head/www/mod_md-devel/pkg-message ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/mod_md-devel/pkg-message Sun Aug 13 13:15:10 2017 (r447884) @@ -0,0 +1,13 @@ +/!\ This is an early experience non-production-ready version /!\ + +If you want to have the h2 module enabled in your apache installation, +you need to add + + LoadModule md_module modules/mod_md.so + +somewhere in your config files and add a line like + + ManagedDomain your_domain.example.org www.your_domain.example.org + +Full documentation in the project's wiki + https://github.com/icing/mod_md/wiki
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201708131315.v7DDFAAj074343>