OpenNTPD daemon with OpenSSL implementation & flexible configurability
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

706 lines
20 KiB

From: Pekka Helenius <fincer89@hotmail.com>
Date: Sun, 02 Aug 2020 14:12:40 +0300
Subject: Implement OpenSSL support, update manual, update ChangeLog
--- a/configure.ac 2020-07-31 23:00:40.000000000 +0300
+++ b/configure.ac 2020-08-02 01:23:30.696950640 +0300
@@ -59,35 +59,100 @@ AM_CONDITIONAL([HAVE_ADJFREQ], [test "x$
AM_CONDITIONAL([HAVE_CLOCK_GETRES], [test "x$ac_cv_func_clock_getres" = xyes])
AM_CONDITIONAL([HAVE_CLOCK_GETTIME], [test "x$ac_cv_func_clock_gettime" = xyes])
-# check for libtls
-AC_SEARCH_LIBS([tls_config_set_ca_mem],[tls],
- [LIBS="$LIBS -ltls -lssl -lcrypto"],,[-lssl -lcrypto])
-AC_CHECK_FUNCS([tls_config_set_ca_mem])
-
-# check if libtls uses 3-argument tls_write
-AC_CACHE_CHECK([if tls_write takes 3 arguments], ac_cv_have_tls_write_3_arg, [
- AC_LINK_IFELSE([AC_LANG_PROGRAM([[
-#include <tls.h>
-size_t outlen;
- ]], [[ tls_write(NULL, NULL, 0); ]])],
- [ ac_cv_have_tls_write_3_arg="yes" ],
- [ ac_cv_have_tls_write_3_arg="no"
+# NOTE: hard-set AC_CHECK_HEADER or friends can't really be checked since
+# libressl/openssl include header files must be determined by OS basis
+# during compilation. Use the following approach instead.
+
+AM_CONDITIONAL(HAVE_SSL, false)
+AM_CONDITIONAL([HAVE_LIBRESSL], false)
+AM_CONDITIONAL([HAVE_OPENSSL], false)
+
+# check for libressl
+AC_ARG_WITH([libressl],
+ AS_HELP_STRING([--without-libressl],
+ [Disable LibreSSL support for constraints]))
+
+AS_IF([test "x$with_libressl" != "xno" ],
+ [ have_libressl="yes" ],
+ [ have_libressl="no" ]
+)
+
+if test "x$have_libressl" == "xyes"; then
+
+ AC_SEARCH_LIBS([tls_config_set_ca_mem],[tls],
+ [LIBS="$LIBS -ltls -lssl -lcrypto"],,[-lssl -lcrypto])
+
+ AC_CHECK_FUNCS([tls_config_set_ca_mem])
+
+ # check if libressl uses 3-argument tls_write
+ AC_CACHE_CHECK(
+ [if LibreSSL tls_write takes 3 arguments],
+ ac_cv_have_libressl_write_3_arg,
+ [AC_LINK_IFELSE([AC_LANG_PROGRAM(
+ [[ #include <libressl/tls.h> ]],
+ [[ size_t outlen; ]],
+ [[ tls_write(NULL, NULL, 0); ]]
+ )],
+ [ ac_cv_have_libressl_write_3_arg="yes" ],
+ [ ac_cv_have_libressl_write_3_arg="no" ]
+ )
+ ])
+fi
+
+# check for openssl
+AC_ARG_WITH([openssl],
+ AS_HELP_STRING([--without-openssl],
+ [Disable OpenSSL support for constraints]))
+
+AS_IF([test "x$with_openssl" != "xno" ],
+ [ have_openssl="yes" ],
+ [ have_openssl="no" ]
+)
+
+if test "x$have_openssl" == "xyes"; then
+
+ AC_SEARCH_LIBS([X509_STORE_load_locations],[ssl],
+ [LIBS="$LIBS -lssl -lcrypto"],,[-lssl -lcrypto])
+
+ AC_CHECK_FUNCS([X509_STORE_load_locations])
+
+ # check if openssl uses 3-argument SSL_write
+ AC_CACHE_CHECK(
+ [if OpenSSL SSL_write takes 3 arguments],
+ ac_cv_have_openssl_write_3_arg,
+ [AC_LINK_IFELSE([AC_LANG_PROGRAM(
+ [[ #include <openssl/ssl.h> ]],
+ [[ SSL *a; SSL_CTX *ff; ]],
+ [[ ff = SSL_CTX_new(TLS_method()); ]],
+ [[ a = SSL_new(ff); ]],
+ [[ SSL_write(a, NULL, 0); ]]
+ )],
+ [ ac_cv_have_openssl_write_3_arg="yes" ],
+ [ ac_cv_have_openssl_write_3_arg="no" ]
+ )
])
-])
+fi
-AC_ARG_ENABLE([https-constraint],
- AS_HELP_STRING([--disable-https-constraint],
- [Disable HTTPS Constraint Functionality]))
-
-AM_CONDITIONAL([HAVE_LIBTLS],
- [test "x$ac_cv_func_tls_config_set_ca_mem" = xyes \
- -a "x$ac_cv_have_tls_write_3_arg" = xyes \
- -a "x$enable_https_constraint" != xno])
-
-if test "x$ac_cv_func_tls_config_set_ca_mem" = xyes \
- -a "x$ac_cv_have_tls_write_3_arg" = xyes \
- -a "x$enable_https_constraint" != xno; then
- AC_DEFINE([HAVE_LIBTLS], [yes])
+if test "x$with_libressl" != xno \
+ -a "x$ac_cv_func_tls_config_set_ca_mem" = xyes \
+ -a "x$ac_cv_have_libressl_write_3_arg" = xyes; then
+ AM_CONDITIONAL([HAVE_LIBRESSL], true)
+ AM_CONDITIONAL([HAVE_SSL], true)
+ AC_DEFINE([HAVE_LIBRESSL], [yes])
+ AC_DEFINE([HAVE_SSL], [yes])
+else
+ AC_MSG_WARN([LibreSSL support disabled])
+fi
+
+if test "x$with_openssl" != xno \
+ -a "x$ac_cv_func_X509_STORE_load_locations" = xyes \
+ -a "x$ac_cv_have_openssl_write_3_arg" = xyes; then
+ AM_CONDITIONAL([HAVE_OPENSSL], true)
+ AM_CONDITIONAL([HAVE_SSL], true)
+ AC_DEFINE([HAVE_OPENSSL], [yes])
+ AC_DEFINE([HAVE_SSL], [yes])
+else
+ AC_MSG_WARN([OpenSSL support disabled])
fi
# Share test results with automake
@@ -144,14 +209,6 @@ AC_ARG_WITH([privsep-path],
)
AC_SUBST(PRIVSEP_PATH)
-AC_ARG_WITH([cacert],
- AS_HELP_STRING([--with-cacert=path],
- [CA certificate location for HTTPS constraint validation]),
- CONSTRAINT_CA="$withval",
- CONSTRAINT_CA="/etc/ssl/cert.pem"
-)
-AC_DEFINE_UNQUOTED(CONSTRAINT_CA, "$CONSTRAINT_CA", [CA certificate path])
-
AC_CONFIG_FILES([
Makefile
include/Makefile
--- a/include/tls.h 2020-07-31 23:00:40.000000000 +0300
+++ b/include/tls.h 2020-08-01 19:24:29.153594762 +0300
@@ -1,8 +1,22 @@
/*
* Public domain
* tls.h compatibility shim
+ *
+ * __linux__
+ * __sun
+ * __FreeBSD__
+ * __NetBSD__
+ * __OpenBSD__
+ * __APPLE__
*/
-#ifdef HAVE_LIBTLS
+#if defined(HAVE_LIBRESSL) && __linux__
+#include_next <libressl/tls.h>
+#elif HAVE_LIBRESSL
#include_next <tls.h>
#endif
+
+#ifdef HAVE_OPENSSL
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#endif
--- a/src/constraint.c 2020-08-02 01:57:57.020286149 +0300
+++ b/src/constraint.c 2020-08-02 01:58:28.366952848 +0300
@@ -39,7 +39,6 @@
#include <unistd.h>
#include <time.h>
#include <ctype.h>
-#include <tls.h>
#include <pwd.h>
#include <math.h>
@@ -65,33 +64,11 @@ void priv_constraint_close(int, int);
void priv_constraint_readquery(struct constraint *, struct ntp_addr_msg *,
uint8_t **);
-struct httpsdate *
- httpsdate_init(const char *, const int *, const char *,
- const char *, const u_int8_t *, size_t);
-void httpsdate_free(void *);
-int httpsdate_request(struct httpsdate *, struct timeval *);
-void *httpsdate_query(const char *, const int *, const char *,
- const char *, const u_int8_t *, size_t,
- struct timeval *, struct timeval *);
-
-char *tls_readline(struct tls *, size_t *, size_t *, struct timeval *);
-
u_int constraint_cnt;
extern u_int peer_cnt;
extern struct imsgbuf *ibuf; /* priv */
extern struct imsgbuf *ibuf_main; /* chld */
-struct httpsdate {
- char *tls_addr;
- char *tls_port;
- char *tls_hostname;
- char *tls_path;
- char *tls_request;
- struct tls_config *tls_config;
- struct tls *tls_ctx;
- struct tm tls_tm;
-};
-
int
constraint_init(struct constraint *cstr)
{
@@ -155,7 +132,7 @@ constraint_query(struct constraint *cstr
{
time_t now;
struct ntp_addr_msg am;
- struct iovec iov[3];
+ struct iovec iov[4];
int iov_cnt = 0;
now = getmonotime();
@@ -252,7 +229,7 @@ priv_constraint_msg(u_int32_t id, u_int8
return;
}
memcpy(&am, data, sizeof(am));
- if (len != (sizeof(am) + am.namelen + am.pathlen + am.portlen)) {
+ if (len != (sizeof(am) + am.namelen + am.pathlen + am.portlen)) {
log_warnx("constraint id %d: invalid query received", id);
return;
}
@@ -343,13 +320,13 @@ priv_constraint_readquery(struct constra
memcpy(h, &am->a, sizeof(*h));
memcpy(&port, &am->port, sizeof(port));
h->next = NULL;
-
+
cstr->id = imsg.hdr.peerid;
cstr->addr = h;
cstr->addr_head.a = h;
cstr->port = port;
cstr->addr_head.port = port;
-
+
dptr = imsg.data;
memcpy(*data, dptr + sizeof(*am), mlen - sizeof(*am));
imsg_free(&imsg);
@@ -364,20 +341,46 @@ priv_constraint_child(const char *pw_dir
static char addr[NI_MAXHOST];
struct timeval rectv, xmttv;
struct sigaction sa;
- void *ctx;
+ void *ctx = NULL;
struct iovec iov[2];
int i, rv;
+#ifdef HAVE_OPENSSL
+ X509_STORE *o_store = NULL;
+#endif
if (setpriority(PRIO_PROCESS, 0, 0) == -1)
log_warn("constraint: can't set priority for subprocess");
-#ifdef HAVE_LIBTLS
- /* Init TLS and load CA certs before chroot() */
- if (tls_init() == -1)
- fatalx("constraint: can't initialize LibreSSL engine");
- if ((conf->ca = tls_load_file(tls_default_ca_cert_file(),
- &conf->ca_len, NULL)) == NULL)
- log_warnx("constraint: failed to load CA certificate bundle file");
+/* Init TLS and load CA certs before chroot() */
+#ifdef HAVE_LIBRESSL
+ if (strcmp("libressl", conf->constraint_engine) == 0) {
+ if (tls_init() == -1)
+ fatalx("constraint: can't initialize LibreSSL engine");
+ if (conf->constraint_ca_validation == 1) {
+ if ((conf->ca = tls_load_file(conf->constraint_ca,
+ &conf->ca_len, NULL)) == NULL)
+ log_warnx("constraint: failed to load CA certificate bundle file");
+ }
+ }
+#endif
+
+#ifdef HAVE_OPENSSL
+ if (strcmp("openssl", conf->constraint_engine) == 0) {
+ if (OPENSSL_init_ssl(0, NULL) == 0)
+ fatalx("constraint: can't initialize OpenSSL engine");
+ //SSL_library_init();
+ OpenSSL_add_all_algorithms();
+ OpenSSL_add_all_digests();
+ SSL_load_error_strings();
+ o_store = X509_STORE_new();
+
+ if (conf->constraint_ca_validation == 1) {
+ if ((conf->o_ca = X509_STORE_load_locations(o_store, conf->constraint_ca, NULL)) != 1) {
+ log_warnx("constraint: failed to load CA certificate bundle file");
+ openssl_lasterr();
+ }
+ }
+ }
#endif
if (chroot(pw_dir) == -1)
@@ -420,7 +423,13 @@ priv_constraint_child(const char *pw_dir
log_debug("constraint %s: setting HTTPS request", addr);
setproctitle("constraint %s: new HTTPS request", addr);
- (void)closefrom(CONSTRAINT_PASSFD + 1);
+
+ /*
+ * OpenSSL requires new file descriptors which must not be deleted.
+ * This restriction does not apply to LibreSSL implementation.
+ */
+ if (strcmp("libressl", conf->constraint_engine) == 0)
+ (void)closefrom(CONSTRAINT_PASSFD + 1);
/*
* Set the close-on-exec flag to prevent leaking the communication
@@ -449,14 +458,32 @@ priv_constraint_child(const char *pw_dir
fatalx("constraint %s: invalid port", addr);
}
- /* Run! */
- if ((ctx = httpsdate_query(addr,
- &cstr.addr_head.port, cstr.addr_head.name, cstr.addr_head.path,
- conf->ca, conf->ca_len, &rectv, &xmttv)) == NULL) {
- log_debug("constraint %s: failed to get proper time results", addr);
- /* Abort with failure but without warning */
- exit(1);
+#ifdef HAVE_LIBRESSL
+ if (strcmp("libressl", conf->constraint_engine) == 0) {
+ /* Run! */
+ log_debug("constraint %s: initializing HTTPS request", addr);
+ if ((ctx = httpsdate_query(addr,
+ &cstr.addr_head.port, cstr.addr_head.name, cstr.addr_head.path,
+ conf->ca, conf->ca_len, &rectv, &xmttv)) == NULL) {
+ log_debug("constraint %s: failed to get proper time results", addr);
+ /* Abort with failure but without warning */
+ exit(1);
+ }
}
+#endif
+
+#ifdef HAVE_OPENSSL
+ if (strcmp("openssl", conf->constraint_engine) == 0) {
+ /* Run! */
+ log_debug("constraint %s: initializing HTTPS request", addr);
+ if ((ctx = o_httpsdate_query(&cstr,
+ &conf->o_ca, &rectv, &xmttv)) == NULL) {
+ log_debug("constraint %s: failed to get proper time results", addr);
+ /* Abort with failure but without warning */
+ exit(1);
+ }
+ }
+#endif
iov[0].iov_base = &rectv;
iov[0].iov_len = sizeof(rectv);
@@ -468,8 +495,18 @@ priv_constraint_child(const char *pw_dir
rv = imsg_flush(&cstr.ibuf);
} while (rv == -1 && errno == EAGAIN);
- /* Tear down the TLS connection after sending the result */
- httpsdate_free(ctx);
+/* Tear down the TLS connection after sending the result */
+#ifdef HAVE_LIBRESSL
+ if (strcmp("libressl", conf->constraint_engine) == 0) {
+ httpsdate_free(ctx);
+ }
+#endif
+
+#ifdef HAVE_OPENSSL
+ if (strcmp("openssl", conf->constraint_engine) == 0) {
+ o_httpsdate_free(ctx);
+ }
+#endif
exit(0);
}
@@ -932,270 +969,6 @@ constraint_check(double val)
return (0);
}
-struct httpsdate *
-httpsdate_init(const char *addr, const int *port, const char *hostname,
- const char *path, const u_int8_t *ca, size_t ca_len)
-{
- struct httpsdate *httpsdate = NULL;
- char port_s[sizeof(port)];
-
- if ((httpsdate = calloc(1, sizeof(*httpsdate))) == NULL)
- goto fail;
-
- if (hostname == NULL)
- hostname = addr;
-
- sprintf(port_s, "%d", *port);
-
- if ((httpsdate->tls_addr = strdup(addr)) == NULL ||
- (httpsdate->tls_port = strdup(port_s)) == NULL ||
- (httpsdate->tls_hostname = strdup(hostname)) == NULL ||
- (httpsdate->tls_path = strdup(path)) == NULL)
- goto fail;
-
- if (asprintf(&httpsdate->tls_request,
- "HEAD %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n",
- httpsdate->tls_path, httpsdate->tls_hostname) == -1)
- goto fail;
-
- if ((httpsdate->tls_config = tls_config_new()) == NULL)
- goto fail;
- if (tls_config_set_ca_mem(httpsdate->tls_config, ca, ca_len) == -1)
- goto fail;
-
- /*
- * Due to the fact that we're trying to determine a constraint for time
- * we do our own certificate validity checking, since the automatic
- * version is based on our wallclock, which may well be inaccurate...
- */
- tls_config_insecure_noverifytime(httpsdate->tls_config);
-
- return (httpsdate);
-
- fail:
- httpsdate_free(httpsdate);
- return (NULL);
-}
-
-void
-httpsdate_free(void *arg)
-{
- struct httpsdate *httpsdate = arg;
- if (httpsdate == NULL)
- return;
- if (httpsdate->tls_ctx)
- tls_close(httpsdate->tls_ctx);
- tls_free(httpsdate->tls_ctx);
- tls_config_free(httpsdate->tls_config);
- free(httpsdate->tls_addr);
- free(httpsdate->tls_port);
- free(httpsdate->tls_hostname);
- free(httpsdate->tls_path);
- free(httpsdate->tls_request);
- free(httpsdate);
-}
-
-int
-httpsdate_request(struct httpsdate *httpsdate, struct timeval *when)
-{
- char timebuf1[32], timebuf2[32];
- size_t outlen = 0, maxlength = conf->constraint_maxheaderlength, len;
- char *line, *p, *buf;
- time_t httptime, notbefore, notafter;
- struct tm *tm;
- ssize_t ret;
-
- if ((httpsdate->tls_ctx = tls_client()) == NULL)
- goto fail;
-
- if (tls_configure(httpsdate->tls_ctx, httpsdate->tls_config) == -1)
- goto fail;
-
- /*
- * libtls expects an address string, which can also be a DNS name,
- * but we pass a pre-resolved IP address string in tls_addr so it
- * does not trigger any DNS operation and is safe to be called
- * without the dns pledge.
- */
- log_debug("constraint %s: establishing connection", httpsdate->tls_addr);
- if (tls_connect_servername(httpsdate->tls_ctx, httpsdate->tls_addr,
- httpsdate->tls_port, httpsdate->tls_hostname) == -1) {
- log_debug("constraint %s: TLS connection failed (%s): %s",
- httpsdate->tls_addr,
- httpsdate->tls_hostname,
- tls_error(httpsdate->tls_ctx)
- );
- goto fail;
- }
-
- buf = httpsdate->tls_request;
- len = strlen(httpsdate->tls_request);
- while (len > 0) {
- ret = tls_write(httpsdate->tls_ctx, buf, len);
- if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT)
- continue;
- if (ret == -1) {
- log_warnx("constraint %s: TLS write operation failed (%s): %s",
- httpsdate->tls_addr,
- httpsdate->tls_hostname,
- tls_error(httpsdate->tls_ctx)
- );
- goto fail;
- }
- buf += ret;
- len -= ret;
- }
-
- while ((line = tls_readline(httpsdate->tls_ctx, &outlen,
- &maxlength, when)) != NULL) {
- line[strcspn(line, "\r\n")] = '\0';
-
- if ((p = strchr(line, ' ')) == NULL || *p == '\0')
- goto next;
- *p++ = '\0';
- if (strcasecmp("Date:", line) != 0)
- goto next;
-
- /*
- * Expect the date/time format as IMF-fixdate which is
- * mandated by HTTP/1.1 in the new RFC 7231 and was
- * preferred by RFC 2616. Other formats would be RFC 850
- * or ANSI C's asctime() - the latter doesn't include
- * the timezone which is required here.
- */
- if (strptime(p, IMF_FIXDATE,
- &httpsdate->tls_tm) == NULL) {
- log_warnx("constraint %s: unsupported date format",
- httpsdate->tls_addr
- );
- free(line);
- return (-1);
- }
-
- free(line);
- break;
- next:
- free(line);
- }
-
- /*
- * Now manually check the validity of the certificate presented in the
- * TLS handshake, based on the time specified by the server's HTTP Date:
- * header.
- */
- notbefore = tls_peer_cert_notbefore(httpsdate->tls_ctx);
- notafter = tls_peer_cert_notafter(httpsdate->tls_ctx);
- if ((httptime = timegm(&httpsdate->tls_tm)) == -1)
- goto fail;
- if (httptime <= notbefore) {
- if ((tm = gmtime(&notbefore)) == NULL)
- goto fail;
- if (strftime(timebuf1, sizeof(timebuf1), X509_DATE, tm) == 0)
- goto fail;
- if (strftime(timebuf2, sizeof(timebuf2), X509_DATE,
- &httpsdate->tls_tm) == 0)
- goto fail;
- log_warnx("constraint %s: TLS certificate not yet valid (%s): "
- "not before %s, now is %s", httpsdate->tls_addr,
- httpsdate->tls_hostname, timebuf1, timebuf2);
- goto fail;
- }
- if (httptime >= notafter) {
- if ((tm = gmtime(&notafter)) == NULL)
- goto fail;
- if (strftime(timebuf1, sizeof(timebuf1), X509_DATE, tm) == 0)
- goto fail;
- if (strftime(timebuf2, sizeof(timebuf2), X509_DATE,
- &httpsdate->tls_tm) == 0)
- goto fail;
- log_warnx("constraint %s: TLS certificate has been expired (%s): "
- "not after %s, now is %s", httpsdate->tls_addr,
- httpsdate->tls_hostname, timebuf1, timebuf2);
- goto fail;
- }
-
- return (0);
-
- fail:
- httpsdate_free(httpsdate);
- return (-1);
-}
-
-void *
-httpsdate_query(const char *addr, const int *port, const char *hostname,
- const char *path, const u_int8_t *ca, size_t ca_len,
- struct timeval *rectv, struct timeval *xmttv)
-{
- struct httpsdate *httpsdate;
- struct timeval when;
- time_t t;
-
- if ((httpsdate = httpsdate_init(addr, port, hostname, path,
- ca, ca_len)) == NULL)
- return (NULL);
-
- if (httpsdate_request(httpsdate, &when) == -1)
- return (NULL);
-
- /* Return parsed date as local time */
- t = timegm(&httpsdate->tls_tm);
-
- /* Report parsed Date: as "received time" */
- rectv->tv_sec = t;
- rectv->tv_usec = 0;
-
- /* And add delay as "transmit time" */
- xmttv->tv_sec = when.tv_sec;
- xmttv->tv_usec = when.tv_usec;
-
- return (httpsdate);
-}
-
-/* Based on SSL_readline in ftp/fetch.c */
-char *
-tls_readline(struct tls *tls, size_t *lenp, size_t *maxlength,
- struct timeval *when)
-{
- size_t i, len;
- char *buf, *q, c;
- ssize_t ret;
-
- len = 128;
- if ((buf = malloc(len)) == NULL)
- fatal("constraint: can't allocate memory for TLS transfer buffer");
- for (i = 0; ; i++) {
- if (i >= len - 1) {
- if ((q = reallocarray(buf, len, 2)) == NULL)
- fatal("constraint: can't expand TLS transfer buffer");
- buf = q;
- len *= 2;
- }
- again:
- ret = tls_read(tls, &c, 1);
- if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT)
- goto again;
- if (ret == -1) {
- /* SSL read error, ignore */
- free(buf);
- return (NULL);
- }
-
- if (maxlength != NULL && (*maxlength)-- == 0) {
- log_warnx("constraint: maximum HTTP header length exceeded");
- free(buf);
- return (NULL);
- }
-
- buf[i] = c;
- if (c == '\n')
- break;
- }
- *lenp = i;
- if (gettimeofday(when, NULL) == -1)
- fatal("constraint: can't get a valid time stamp");
- return (buf);
-}
-
char *
get_string(u_int8_t *ptr, size_t len)
{
--- /dev/null 2020-07-26 15:23:52.401078754 +0300
+++ b/src/constraint-openssl.c 2020-08-01 19:56:30.010263450 +0300
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2020 Pekka Helenius <fincer89@hotmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include "ntpd.h"
+
+struct o_httpsdate *
+o_httpsdate_init(struct constraint *cstr, const int *ca)
+{
+ struct o_httpsdate *httpsdate = NULL;
+
+ if ((httpsdate = calloc(1, sizeof(*httpsdate))) == NULL)
+ goto fail;
+
+ if ((httpsdate->cstr = cstr) == NULL)
+ goto fail;
+
+ if (asprintf(&httpsdate->tls_request,
+ "HEAD %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n",
+ httpsdate->cstr->addr_head.path,
+ httpsdate->cstr->addr_head.name) == -1)
+ goto fail;
+
+ if ((httpsdate->tls_method = TLS_method()) == NULL)
+ goto fai