MEDIUM: ssl: Add support for OpenSSL 1.1.0

In the last release a lot of the structures have become opaque for an
end user. This means the code using these needs to be changed to use the
proper functions to interact with these structures instead of trying to
manipulate them directly.

This does not fix any deprecations yet that are part of 1.1.0, it only
ensures that it can be compiled against that version and is still
compatible with older ones.

[wt: openssl-0.9.8 doesn't build with it, there are conflicts on certain
     function prototypes which we declare as inline here and which are
     defined differently there. But openssl-0.9.8 is not supported anymore
     so probably it's OK to go without it for now and we'll see later if
     some users still need it. Emeric has reviewed this change and didn't
     spot anything obvious which requires special care. Let's try it for
     real now]
diff --git a/Makefile b/Makefile
index 976524d..b2b748c 100644
--- a/Makefile
+++ b/Makefile
@@ -579,6 +579,9 @@
 BUILD_OPTIONS   += $(call ignore_implicit,USE_OPENSSL)
 OPTIONS_CFLAGS  += -DUSE_OPENSSL $(if $(SSL_INC),-I$(SSL_INC))
 OPTIONS_LDFLAGS += $(if $(SSL_LIB),-L$(SSL_LIB)) -lssl -lcrypto
+ifneq ($(USE_DL),)
+OPTIONS_LDFLAGS += -ldl
+endif
 OPTIONS_OBJS  += src/ssl_sock.o src/shctx.o
 ifneq ($(USE_PRIVATE_CACHE),)
 OPTIONS_CFLAGS  += -DUSE_PRIVATE_CACHE
diff --git a/include/proto/openssl-compat.h b/include/proto/openssl-compat.h
new file mode 100644
index 0000000..17b491f
--- /dev/null
+++ b/include/proto/openssl-compat.h
@@ -0,0 +1,142 @@
+#ifndef _PROTO_OPENSSL_COMPAT_H
+#define _PROTO_OPENSSL_COMPAT_H
+#include <openssl/crypto.h>
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/x509.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
+#include <openssl/ocsp.h>
+#endif
+#ifndef OPENSSL_NO_DH
+#include <openssl/dh.h>
+#endif
+
+#if (OPENSSL_VERSION_NUMBER < 0x1000000fL)
+/*
+ * Functions introduced in OpenSSL 1.0.1
+ */
+static inline int SSL_SESSION_set1_id_context(SSL_SESSION *s, const unsigned char *sid_ctx, unsigned int sid_ctx_len)
+{
+	s->sid_ctx_length = sid_ctx_len;
+	memcpy(s->sid_ctx, sid_ctx, sid_ctx_len);
+	return 1;
+}
+
+static inline int EVP_PKEY_base_id(const EVP_PKEY *pkey)
+{
+	return EVP_PKEY_type(pkey->type);
+}
+
+static inline const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *sess, unsigned int *sid_length)
+{
+	*sid_length = sess->session_id_length;
+	return sess->session_id;
+}
+
+static inline X509_NAME_ENTRY *X509_NAME_get_entry(const X509_NAME *name, int loc)
+{
+	return sk_X509_NAME_ENTRY_value(name->entries, loc);
+}
+
+static inline ASN1_OBJECT *X509_NAME_ENTRY_get_object(const X509_NAME_ENTRY *ne)
+{
+	return ne->object;
+}
+
+static inline ASN1_STRING *X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *ne)
+{
+	return ne->value;
+}
+
+static inline int ASN1_STRING_length(const ASN1_STRING *x)
+{
+	return x->length;
+}
+
+static inline int X509_NAME_entry_count(X509_NAME *name)
+{
+	return sk_X509_NAME_ENTRY_num(name->entries)
+}
+
+int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg, const unsigned char **pk, int *ppklen, X509_ALGOR **pa, X509_PUBKEY *pub)
+{
+	*ppkalg = pub->algor->algorithm;
+	return 1;
+}
+
+static inline void X509_ALGOR_get0(ASN1_OBJECT **paobj, int *pptype, const void **ppval, const X509_ALGOR *algor)
+{
+	*paobj = algor->algorithm;
+}
+
+#ifndef X509_get_X509_PUBKEY
+#define X509_get_X509_PUBKEY(x) ((x)->cert_info->key
+#endif
+
+#endif
+
+#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
+/*
+ * Functions introduced in OpenSSL 1.1.0
+ */
+
+static inline const unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *sess, unsigned int *sid_ctx_length)
+{
+	*sid_ctx_length = sess->sid_ctx_length;
+	return sess->sid_ctx;
+}
+
+static inline int SSL_SESSION_set1_id(SSL_SESSION *s, const unsigned char *sid, unsigned int sid_len)
+{
+	s->session_id_length = sid_len;
+	memcpy(s->session_id, sid, sid_len);
+	return 1;
+}
+
+static inline const OCSP_CERTID *OCSP_SINGLERESP_get0_id(const OCSP_SINGLERESP *single)
+{
+	return single->certId;
+}
+
+static inline pem_password_cb *SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx)
+{
+	return ctx->default_passwd_callback;
+}
+
+static inline void *SSL_CTX_get_default_passwd_cb_userdata(SSL_CTX *ctx)
+{
+	return ctx->default_passwd_callback_userdata;
+}
+
+#ifndef OPENSSL_NO_DH
+static inline int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
+{
+	/* Implements only the bare necessities for HAProxy */
+	dh->p = p;
+	dh->g = g;
+	return 1;
+}
+#endif
+
+static inline const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x)
+{
+	return x->data;
+}
+
+static inline X509_ALGOR *X509_get0_tbs_sigalg(const X509 *x)
+{
+	return x->cert_info->signature;
+}
+
+#endif
+
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+#define __OPENSSL_110_CONST__ const
+#else
+#define __OPENSSL_110_CONST__
+#endif
+
+#endif /* _PROTO_OPENSSL_COMPAT_H */
diff --git a/src/shctx.c b/src/shctx.c
index c561632..988832f 100644
--- a/src/shctx.c
+++ b/src/shctx.c
@@ -27,6 +27,7 @@
 #include <ebmbtree.h>
 #include <types/global.h>
 #include "proto/shctx.h"
+#include <proto/openssl-compat.h>
 
 struct shsess_packet_hdr {
 	unsigned int eol;
@@ -390,16 +391,19 @@
 	unsigned char encsess[sizeof(struct shsess_packet)+SHSESS_MAX_DATA_LEN];
 	struct shsess_packet *packet = (struct shsess_packet *)encsess;
 	unsigned char *p;
-	int data_len, sid_length, sid_ctx_length;
-
+	int data_len;
+	unsigned int sid_length, sid_ctx_length;
+	const unsigned char *sid_data;
+	const unsigned char *sid_ctx_data;
 
 	/* Session id is already stored in to key and session id is known
 	 * so we dont store it to keep size.
 	 */
-	sid_length = sess->session_id_length;
-	sess->session_id_length = 0;
-	sid_ctx_length = sess->sid_ctx_length;
-	sess->sid_ctx_length = 0;
+
+	sid_data = SSL_SESSION_get_id(sess, &sid_length);
+	sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
+	SSL_SESSION_set1_id(sess, sid_data, 0);
+	SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
 
 	/* check if buffer is large enough for the ASN1 encoded session */
 	data_len = i2d_SSL_SESSION(sess, NULL);
@@ -410,7 +414,7 @@
 	p = packet->data;
 	i2d_SSL_SESSION(sess, &p);
 
-	memcpy(packet->hdr.id, sess->session_id, sid_length);
+	memcpy(packet->hdr.id, sid_data, sid_length);
 	if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
 		memset(&packet->hdr.id[sid_length], 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
 
@@ -423,14 +427,14 @@
 
 err:
 	/* reset original length values */
-	sess->session_id_length = sid_length;
-	sess->sid_ctx_length = sid_ctx_length;
+	SSL_SESSION_set1_id(sess, sid_data, sid_length);
+	SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
 
 	return 0; /* do not increment session reference count */
 }
 
 /* SSL callback used on lookup an existing session cause none found in internal cache */
-SSL_SESSION *shctx_get_cb(SSL *ssl, unsigned char *key, int key_len, int *do_copy)
+SSL_SESSION *shctx_get_cb(SSL *ssl, __OPENSSL_110_CONST__ unsigned char *key, int key_len, int *do_copy)
 {
 	struct shared_session *shsess;
 	unsigned char data[SHSESS_MAX_DATA_LEN], *p;
@@ -503,10 +507,8 @@
 	sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, data_len);
 	/* Reset session id and session id contenxt */
 	if (sess) {
-		memcpy(sess->session_id, key, key_len);
-		sess->session_id_length = key_len;
-		memcpy(sess->sid_ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
-		sess->sid_ctx_length = ssl->sid_ctx_length;
+		SSL_SESSION_set1_id(sess, key, key_len);
+		SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
 	}
 
 	return sess;
@@ -517,20 +519,22 @@
 {
 	struct shared_session *shsess;
 	unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
-	unsigned char *key = sess->session_id;
+	unsigned int sid_length;
+	const unsigned char *sid_data;
 	(void)ctx;
 
+	sid_data = SSL_SESSION_get_id(sess, &sid_length);
 	/* tree key is zeros padded sessionid */
-	if (sess->session_id_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
-		memcpy(tmpkey, sess->session_id, sess->session_id_length);
-		memset(tmpkey+sess->session_id_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sess->session_id_length);
-		key = tmpkey;
+	if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
+		memcpy(tmpkey, sid_data, sid_length);
+		memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
+		sid_data = tmpkey;
 	}
 
 	shared_context_lock();
 
 	/* lookup for session */
-	shsess = shsess_tree_lookup(key);
+	shsess = shsess_tree_lookup(sid_data);
 	if (shsess) {
 		/* free session */
 		shsess_tree_delete(shsess);
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index 3eee173..b14bb8a 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -39,6 +39,7 @@
 #include <netdb.h>
 #include <netinet/tcp.h>
 
+#include <openssl/crypto.h>
 #include <openssl/ssl.h>
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
@@ -78,6 +79,7 @@
 #include <proto/freq_ctr.h>
 #include <proto/frontend.h>
 #include <proto/listener.h>
+#include <proto/openssl-compat.h>
 #include <proto/pattern.h>
 #include <proto/proto_tcp.h>
 #include <proto/server.h>
@@ -326,6 +328,7 @@
 	OCSP_RESPONSE *resp;
 	OCSP_BASICRESP *bs = NULL;
 	OCSP_SINGLERESP *sr;
+	OCSP_CERTID *id;
 	unsigned char *p = (unsigned char *)ocsp_response->str;
 	int rc , count_sr;
 	ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
@@ -362,6 +365,8 @@
 		goto out;
 	}
 
+	id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
+
 	rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
 	if (rc != V_OCSP_CERTSTATUS_GOOD) {
 		memprintf(err, "OCSP single response: certificate status not good");
@@ -380,7 +385,7 @@
 	}
 
 	if (cid) {
-		if (OCSP_id_cmp(sr->certId, cid)) {
+		if (OCSP_id_cmp(id, cid)) {
 			memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
 			goto out;
 		}
@@ -390,7 +395,7 @@
 		unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
 		unsigned char *p;
 
-		rc = i2d_OCSP_CERTID(sr->certId, NULL);
+		rc = i2d_OCSP_CERTID(id, NULL);
 		if (!rc) {
 			memprintf(err, "OCSP single response: Unable to encode Certificate ID");
 			goto out;
@@ -403,7 +408,7 @@
 
 		p = key;
 		memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
-		i2d_OCSP_CERTID(sr->certId, &p);
+		i2d_OCSP_CERTID(id, &p);
 		ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
 		if (!ocsp) {
 			memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
@@ -642,7 +647,7 @@
 	if (!ssl_pkey)
 		return SSL_TLSEXT_ERR_NOACK;
 
-	key_type = EVP_PKEY_type(ssl_pkey->type);
+	key_type = EVP_PKEY_base_id(ssl_pkey);
 
 	if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
 		ocsp = ocsp_arg->s_ocsp;
@@ -705,6 +710,9 @@
 	struct certificate_ocsp *ocsp = NULL, *iocsp;
 	char *warn = NULL;
 	unsigned char *p;
+	pem_password_cb *passwd_cb;
+	void *passwd_cb_userdata;
+	void (*callback) (void);
 
 	snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
 
@@ -745,7 +753,10 @@
 		if (BIO_read_filename(in, issuer_path) <= 0)
 			goto out;
 
+		passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
+		passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
+
-		xi = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
+		xi = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
 		if (!xi)
 			goto out;
 
@@ -774,12 +785,19 @@
 	if (iocsp == ocsp)
 		ocsp = NULL;
 
+#ifndef SSL_CTX_get_tlsext_status_cb
+# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
+	*cb = (void (*) (void))ctx->tlsext_status_cb;
+#endif
+	SSL_CTX_get_tlsext_status_cb(ctx, &callback);
+
-	if (!ctx->tlsext_status_cb) {
+	if (!callback) {
 		struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
 
 		cb_arg->is_single = 1;
 		cb_arg->s_ocsp = iocsp;
-		cb_arg->single_kt = EVP_PKEY_type(X509_get_pubkey(x)->type);
+
+		cb_arg->single_kt = EVP_PKEY_base_id(X509_get_pubkey(x));
 
 		SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
 		SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
@@ -788,9 +806,16 @@
 		 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
 		 * Update that cb_arg with the new cert's staple
 		 */
-		struct ocsp_cbk_arg *cb_arg = ctx->tlsext_status_arg;
+		struct ocsp_cbk_arg *cb_arg;
 		struct certificate_ocsp *tmp_ocsp;
 		int index;
+		int key_type;
+
+#ifdef SSL_CTX_get_tlsext_status_arg
+		SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
+#else
+		cb_arg = ctx->tlsext_status_arg;
+#endif
 
 		/*
 		 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
@@ -803,7 +828,8 @@
 		cb_arg->is_single = 0;
 		cb_arg->single_kt = 0;
 
-		index = ssl_sock_get_ocsp_arg_kt_index(EVP_PKEY_type(X509_get_pubkey(x)->type));
+		key_type = EVP_PKEY_base_id(X509_get_pubkey(x));
+		index = ssl_sock_get_ocsp_arg_kt_index(key_type);
 		if (index >= 0 && !cb_arg->m_ocsp[index])
 			cb_arg->m_ocsp[index] = iocsp;
 
@@ -1154,6 +1180,7 @@
 	const EVP_MD *digest;
 	X509V3_CTX    ctx;
 	unsigned int  i;
+	int 	      key_type;
 
 	/* Get the private key of the defautl certificate and use it */
 	if (!(pkey = SSL_get_privatekey(ssl)))
@@ -1215,11 +1242,14 @@
 	}
 
 	/* Sign the certificate with the CA private key */
-	if (EVP_PKEY_type(capkey->type) == EVP_PKEY_DSA)
-		digest = EVP_dss1();
-	else if (EVP_PKEY_type (capkey->type) == EVP_PKEY_RSA)
+
+	key_type = EVP_PKEY_base_id(capkey);
+
+	if (key_type == EVP_PKEY_DSA)
+		digest = EVP_sha1();
+	else if (key_type == EVP_PKEY_RSA)
 		digest = EVP_sha256();
-	else if (EVP_PKEY_type (capkey->type) == EVP_PKEY_EC)
+	else if (key_type == EVP_PKEY_EC)
 		digest = EVP_sha256();
 	else {
 #if (OPENSSL_VERSION_NUMBER >= 0x1000000fL)
@@ -1451,14 +1481,18 @@
 		0x02,
 		};
 
+	BIGNUM *p;
+	BIGNUM *g;
 	DH *dh = DH_new();
 	if (dh) {
-		dh->p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
-		dh->g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
+		p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
+		g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
 
-		if (!dh->p || !dh->g) {
+		if (!p || !g) {
 			DH_free(dh);
 			dh = NULL;
+		} else {
+			DH_set0_pqg(dh, p, NULL, g);
 		}
 	}
 	return dh;
@@ -1494,14 +1528,18 @@
 		0x02,
 		};
 
+	BIGNUM *p;
+	BIGNUM *g;
 	DH *dh = DH_new();
 	if (dh) {
-		dh->p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
-		dh->g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
+		p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
+		g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
 
-		if (!dh->p || !dh->g) {
+		if (!p || !g) {
 			DH_free(dh);
 			dh = NULL;
+		} else {
+			DH_set0_pqg(dh, p, NULL, g);
 		}
 	}
 	return dh;
@@ -1558,14 +1596,18 @@
 		0x02,
 		};
 
+	BIGNUM *p;
+	BIGNUM *g;
 	DH *dh = DH_new();
 	if (dh) {
-		dh->p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
-		dh->g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
+		p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
+		g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
 
-		if (!dh->p || !dh->g) {
+		if (!p || !g) {
 			DH_free(dh);
 			dh = NULL;
+		} else {
+			DH_set0_pqg(dh, p, NULL, g);
 		}
 	}
 	return dh;
@@ -1577,7 +1619,9 @@
 {
 	DH *dh = NULL;
 	EVP_PKEY *pkey = SSL_get_privatekey(ssl);
-	int type = pkey ? EVP_PKEY_type(pkey->type) : EVP_PKEY_NONE;
+	int type;
+
+	type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
 
 	/* The keylen supplied by OpenSSL can only be 512 or 1024.
 	   See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
@@ -2035,8 +2079,9 @@
 			i = -1;
 			while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
 				X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
-
-				if (ASN1_STRING_to_UTF8((unsigned char **)&str, entry->value) >= 0) {
+				ASN1_STRING *value;
+				value = X509_NAME_ENTRY_get_data(entry);
+				if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
 					/* Important line is here */
 					ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
 
@@ -2207,6 +2252,9 @@
 	int order = 0;
 	X509_NAME *xname;
 	char *str;
+	pem_password_cb *passwd_cb;
+	void *passwd_cb_userdata;
+
 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
 	STACK_OF(GENERAL_NAME) *names;
 #endif
@@ -2218,7 +2266,11 @@
 	if (BIO_read_filename(in, file) <= 0)
 		goto end;
 
+
-	x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
+	passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
+	passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
+
+	x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
 	if (x == NULL)
 		goto end;
 
@@ -2246,7 +2298,10 @@
 		i = -1;
 		while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
 			X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
-			if (ASN1_STRING_to_UTF8((unsigned char **)&str, entry->value) >= 0) {
+			ASN1_STRING *value;
+
+			value = X509_NAME_ENTRY_get_data(entry);
+			if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
 				order = ssl_sock_add_cert_sni(ctx, s, str, order);
 				OPENSSL_free(str);
 			}
@@ -2257,12 +2312,16 @@
 	if (!SSL_CTX_use_certificate(ctx, x))
 		goto end;
 
+#ifdef SSL_CTX_clear_extra_chain_certs
+	SSL_CTX_clear_extra_chain_certs(ctx);
+#else
 	if (ctx->extra_certs != NULL) {
 		sk_X509_pop_free(ctx->extra_certs, X509_free);
 		ctx->extra_certs = NULL;
 	}
+#endif
 
-	while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata))) {
+	while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
 		if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
 			X509_free(ca);
 			goto end;
@@ -2944,7 +3003,9 @@
 	i = -1;
 	while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
 		X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
-		if (ASN1_STRING_to_UTF8((unsigned char **)&str, entry->value) >= 0) {
+		ASN1_STRING *value;
+		value = X509_NAME_ENTRY_get_data(entry);
+		if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
 			ok = ssl_sock_srv_hostcheck(str, servername);
 			OPENSSL_free(str);
 		}
@@ -3455,7 +3516,15 @@
 				if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
 					conn->flags &= ~CO_FL_WAIT_L4_CONN;
 				if (!conn->err_code) {
-					if (!((SSL *)conn->xprt_ctx)->packet_length) {
+					int empty_handshake;
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+					OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
+					empty_handshake = state == TLS_ST_BEFORE;
+#else
+					empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
+#endif
+
+					if (empty_handshake) {
 						if (!errno) {
 							if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
 								conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
@@ -3518,11 +3587,21 @@
 			return 0;
 		}
 		else if (ret == SSL_ERROR_SYSCALL) {
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+			OSSL_HANDSHAKE_STATE state;
+#endif
+			int empty_handshake;
 			/* if errno is null, then connection was successfully established */
 			if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
 				conn->flags &= ~CO_FL_WAIT_L4_CONN;
 
-			if (!((SSL *)conn->xprt_ctx)->packet_length) {
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+			state = SSL_get_state((SSL *)conn->xprt_ctx);
+			empty_handshake = state == TLS_ST_BEFORE;
+#else
+			empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
+#endif
+			if (empty_handshake) {
 				if (!errno) {
 					if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
 						conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
@@ -3937,22 +4016,33 @@
 ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
 {
 	X509_NAME_ENTRY *ne;
+	ASN1_OBJECT *obj;
+	ASN1_STRING *data;
+	const unsigned char *data_ptr;
+	int data_len;
 	int i, j, n;
 	int cur = 0;
 	const char *s;
 	char tmp[128];
+	int name_count;
+
+	name_count = X509_NAME_entry_count(a);
 
 	out->len = 0;
-	for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
+	for (i = 0; i < name_count; i++) {
 		if (pos < 0)
-			j = (sk_X509_NAME_ENTRY_num(a->entries)-1) - i;
+			j = (name_count-1) - i;
 		else
 			j = i;
 
-		ne = sk_X509_NAME_ENTRY_value(a->entries, j);
-		n = OBJ_obj2nid(ne->object);
+		ne = X509_NAME_get_entry(a, j);
+		obj = X509_NAME_ENTRY_get_object(ne);
+		data = X509_NAME_ENTRY_get_data(ne);
+		data_ptr = ASN1_STRING_get0_data(data);
+		data_len = ASN1_STRING_length(data);
+		n = OBJ_obj2nid(obj);
 		if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
-			i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
+			i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
 			s = tmp;
 		}
 
@@ -3967,11 +4057,11 @@
 		if (cur != pos)
 			continue;
 
-		if (ne->value->length > out->size)
+		if (data_len > out->size)
 			return -1;
 
-		memcpy(out->str, ne->value->data, ne->value->length);
-		out->len = ne->value->length;
+		memcpy(out->str, data_ptr, data_len);
+		out->len = data_len;
 		return 1;
 	}
 
@@ -3986,24 +4076,36 @@
 ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
 {
 	X509_NAME_ENTRY *ne;
+	ASN1_OBJECT *obj;
+	ASN1_STRING *data;
+	const unsigned char *data_ptr;
+	int data_len;
 	int i, n, ln;
 	int l = 0;
 	const char *s;
 	char *p;
 	char tmp[128];
+	int name_count;
+
+
+	name_count = X509_NAME_entry_count(a);
 
 	out->len = 0;
 	p = out->str;
-	for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
-		ne = sk_X509_NAME_ENTRY_value(a->entries, i);
-		n = OBJ_obj2nid(ne->object);
+	for (i = 0; i < name_count; i++) {
+		ne = X509_NAME_get_entry(a, i);
+		obj = X509_NAME_ENTRY_get_object(ne);
+		data = X509_NAME_ENTRY_get_data(ne);
+		data_ptr = ASN1_STRING_get0_data(data);
+		data_len = ASN1_STRING_length(data);
+		n = OBJ_obj2nid(obj);
 		if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
-			i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
+			i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
 			s = tmp;
 		}
 		ln = strlen(s);
 
-		l += 1 + ln + 1 + ne->value->length;
+		l += 1 + ln + 1 + data_len;
 		if (l > out->size)
 			return -1;
 		out->len = l;
@@ -4012,8 +4114,8 @@
 		memcpy(p, s, ln);
 		p += ln;
 		*(p++)='=';
-		memcpy(p, ne->value->data, ne->value->length);
-		p += ne->value->length;
+		memcpy(p, data_ptr, data_len);
+		p += data_len;
 	}
 
 	if (!out->len)
@@ -4540,6 +4642,7 @@
 {
 	int cert_peer = (kw[4] == 'c') ? 1 : 0;
 	X509 *crt;
+	__OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
 	int nid;
 	struct connection *conn;
 
@@ -4559,7 +4662,8 @@
 	if (!crt)
 		return 0;
 
-	nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
+	X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
+	nid = OBJ_obj2nid(algorithm);
 
 	smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
 	if (!smp->data.u.str.str) {
@@ -4588,6 +4692,7 @@
 {
 	int cert_peer = (kw[4] == 'c') ? 1 : 0;
 	X509 *crt;
+	ASN1_OBJECT *algorithm;
 	int nid;
 	struct connection *conn;
 
@@ -4607,7 +4712,8 @@
 	if (!crt)
 		return 0;
 
-	nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
+	X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
+	nid = OBJ_obj2nid(algorithm);
 
 	smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
 	if (!smp->data.u.str.str) {