From e83d56c8b346981b1be8ec700fd07cbab7c4cebe Mon Sep 17 00:00:00 2001
From: Dirkjan Bussink <d.bussink@gmail.com>
Date: Mon, 29 Aug 2016 13:26:37 +0200
Subject: [PATCH] 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.
---
 Makefile       |   3 +
 src/shctx.c    |  50 +++++++---
 src/ssl_sock.c | 289 ++++++++++++++++++++++++++++++++++++++++++++++++---------
 3 files changed, 286 insertions(+), 56 deletions(-)

diff --git a/Makefile b/Makefile
index 4d6ab1a..b7f7ab4 100644
--- a/Makefile
+++ b/Makefile
@@ -578,6 +578,9 @@ ifneq ($(USE_OPENSSL),)
 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/src/shctx.c b/src/shctx.c
index c561632..cccd914 100644
--- a/src/shctx.c
+++ b/src/shctx.c
@@ -390,16 +390,27 @@ int shctx_new_cb(SSL *ssl, SSL_SESSION *sess)
 	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;
 
 	/* Session id is already stored in to key and session id is known
 	 * so we dont store it to keep size.
 	 */
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+	const unsigned char *sid_ctx_data;
+
+	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);
+#else
 	sid_length = sess->session_id_length;
-	sess->session_id_length = 0;
 	sid_ctx_length = sess->sid_ctx_length;
+	sess->session_id_length = 0;
 	sess->sid_ctx_length = 0;
+	sid_data = sess->session_id;
+#endif
 
 	/* check if buffer is large enough for the ASN1 encoded session */
 	data_len = i2d_SSL_SESSION(sess, NULL);
@@ -410,7 +421,7 @@ int shctx_new_cb(SSL *ssl, SSL_SESSION *sess)
 	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 +434,19 @@ int shctx_new_cb(SSL *ssl, SSL_SESSION *sess)
 
 err:
 	/* reset original length values */
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+	SSL_SESSION_set1_id(sess, sid_data, sid_length);
+	SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
+#else
 	sess->session_id_length = sid_length;
 	sess->sid_ctx_length = sid_ctx_length;
+#endif
 
 	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, const unsigned char *key, int key_len, int *do_copy)
 {
 	struct shared_session *shsess;
 	unsigned char data[SHSESS_MAX_DATA_LEN], *p;
@@ -503,10 +519,15 @@ SSL_SESSION *shctx_get_cb(SSL *ssl, unsigned char *key, int key_len, int *do_cop
 	sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, data_len);
 	/* Reset session id and session id contenxt */
 	if (sess) {
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+		SSL_SESSION_set1_id(sess, key, key_len);
+		SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
+#else
 		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;
+#endif
 	}
 
 	return sess;
@@ -517,20 +538,27 @@ void shctx_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
 {
 	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;
 
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+	sid_data = SSL_SESSION_get_id(sess, &sid_length);
+#else
+	sid_data = sess->session_id;
+	sid_length = sess->session_id_length;
+#endif
 	/* 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 e5a6f0a..d7f8249 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>
@@ -305,6 +306,7 @@ static int ssl_sock_load_ocsp_response(struct chunk *ocsp_response, struct certi
 	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;
@@ -341,6 +343,12 @@ static int ssl_sock_load_ocsp_response(struct chunk *ocsp_response, struct certi
 		goto out;
 	}
 
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+	id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
+#else
+	id = sr->certId;
+#endif
+
 	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");
@@ -359,7 +367,7 @@ static int ssl_sock_load_ocsp_response(struct chunk *ocsp_response, struct certi
 	}
 
 	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;
 		}
@@ -369,7 +377,7 @@ static int ssl_sock_load_ocsp_response(struct chunk *ocsp_response, struct certi
 		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;
@@ -382,7 +390,7 @@ static int ssl_sock_load_ocsp_response(struct chunk *ocsp_response, struct certi
 
 		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");
@@ -621,7 +629,11 @@ int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
 	if (!ssl_pkey)
 		return SSL_TLSEXT_ERR_NOACK;
 
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+	key_type = EVP_PKEY_base_id(ssl_pkey);
+#else
 	key_type = EVP_PKEY_type(ssl_pkey->type);
+#endif
 
 	if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
 		ocsp = ocsp_arg->s_ocsp;
@@ -684,6 +696,9 @@ static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
 	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);
 
@@ -724,7 +739,15 @@ static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
 		if (BIO_read_filename(in, issuer_path) <= 0)
 			goto out;
 
-		xi = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+		passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
+		passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
+#else
+		passwd_cb = ctx->default_passwd_callback;
+		passwd_cb_userdata = ctx->default_passwd_callback_userdata;
+#endif
+
+		xi = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
 		if (!xi)
 			goto out;
 
@@ -753,12 +776,23 @@ static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
 	if (iocsp == ocsp)
 		ocsp = NULL;
 
-	if (!ctx->tlsext_status_cb) {
+#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 (!callback) {
 		struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
 
 		cb_arg->is_single = 1;
 		cb_arg->s_ocsp = iocsp;
+
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+		cb_arg->single_kt = EVP_PKEY_base_id(X509_get_pubkey(x));
+#else
 		cb_arg->single_kt = EVP_PKEY_type(X509_get_pubkey(x)->type);
+#endif
 
 		SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
 		SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
@@ -767,9 +801,16 @@ static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
 		 * 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
@@ -782,7 +823,12 @@ static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
 		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));
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+		key_type = EVP_PKEY_base_id(X509_get_pubkey(x));
+#else
+		key_type = EVP_PKEY_type(X509_get_pubkey(x)->type);
+#endif
+		index = ssl_sock_get_ocsp_arg_kt_index(key_type);
 		if (index >= 0 && !cb_arg->m_ocsp[index])
 			cb_arg->m_ocsp[index] = iocsp;
 
@@ -1131,6 +1177,7 @@ ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL
 	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)))
@@ -1192,11 +1239,18 @@ ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL
 	}
 
 	/* 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)
+
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+	key_type = EVP_PKEY_base_id(capkey);
+#else
+	key_type = EVP_PKEY_type(capkey->type);
+#endif
+
+	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)
@@ -1428,14 +1482,23 @@ static DH * ssl_get_dh_1024(void)
 		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 {
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+			DH_set0_pqg(dh, p, NULL, g);
+#else
+			dh->p = p;
+			dh->g = g;
+#endif
 		}
 	}
 	return dh;
@@ -1471,14 +1534,23 @@ static DH *ssl_get_dh_2048(void)
 		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 {
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+			DH_set0_pqg(dh, p, NULL, g);
+#else
+			dh->p = p;
+			dh->g = g;
+#endif
 		}
 	}
 	return dh;
@@ -1535,14 +1607,23 @@ static DH *ssl_get_dh_4096(void)
 		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 {
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+			DH_set0_pqg(dh, p, NULL, g);
+#else
+			dh->p = p;
+			dh->g = g;
+#endif
 		}
 	}
 	return dh;
@@ -1554,7 +1635,13 @@ static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
 {
 	DH *dh = NULL;
 	EVP_PKEY *pkey = SSL_get_privatekey(ssl);
-	int type = pkey ? EVP_PKEY_type(pkey->type) : EVP_PKEY_NONE;
+	int type;
+
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+	type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
+#else
+	type = pkey ? EVP_PKEY_type(pkey->type) : EVP_PKEY_NONE;
+#endif
 
 	/* The keylen supplied by OpenSSL can only be 512 or 1024.
 	   See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
@@ -1807,7 +1894,7 @@ static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_an
 	}
 
 	/* Seek back to beginning of file */
-	BIO_reset(in);
+	(void)BIO_reset(in);
 
 	/* Read Certificate */
 	ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
@@ -1990,8 +2077,13 @@ static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_con
 			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;
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+				value = X509_NAME_ENTRY_get_data(entry);
+#else
+				value = entry->value;
+#endif
+				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);
 
@@ -2162,6 +2254,9 @@ static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct
 	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
@@ -2173,7 +2268,16 @@ static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct
 	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);
+
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+	passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
+	passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
+#else
+	passwd_cb = ctx->default_passwd_callback;
+	passwd_cb_userdata = ctx->default_passwd_callback_userdata;
+#endif
+
+	x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
 	if (x == NULL)
 		goto end;
 
@@ -2201,7 +2305,14 @@ static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct
 		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;
+
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+			value = X509_NAME_ENTRY_get_data(entry);
+#else
+			value = entry->value;
+#endif
+			if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
 				order = ssl_sock_add_cert_sni(ctx, s, str, order);
 				OPENSSL_free(str);
 			}
@@ -2212,12 +2323,16 @@ static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct
 	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;
@@ -2899,7 +3014,13 @@ static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
 	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;
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+		value = X509_NAME_ENTRY_get_data(entry);
+#else
+		value = entry->value;
+#endif
+		if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
 			ok = ssl_sock_srv_hostcheck(str, servername);
 			OPENSSL_free(str);
 		}
@@ -3410,7 +3531,15 @@ int ssl_sock_handshake(struct connection *conn, unsigned int flag)
 				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;
@@ -3473,11 +3602,21 @@ int ssl_sock_handshake(struct connection *conn, unsigned int flag)
 			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;
@@ -3887,22 +4026,45 @@ static int
 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;
+
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+	name_count = X509_NAME_entry_count(a);
+#else
+	name_count = sk_X509_NAME_ENTRY_num(a->entries);
+#endif
 
 	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;
 
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+		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);
+#else
 		ne = sk_X509_NAME_ENTRY_value(a->entries, j);
-		n = OBJ_obj2nid(ne->object);
+		obj = ne->object;
+		data = ne->value;
+		data_ptr = data->data;
+		data_len = data->length;
+#endif
+		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;
 		}
 
@@ -3917,11 +4079,11 @@ ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct c
 		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;
 	}
 
@@ -3936,24 +4098,48 @@ static int
 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;
+
+
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+	name_count = X509_NAME_entry_count(a);
+#else
+	name_count = sk_X509_NAME_ENTRY_num(a->entries);
+#endif
 
 	out->len = 0;
 	p = out->str;
-	for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
+	for (i = 0; i < name_count; i++) {
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+		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);
+#else
 		ne = sk_X509_NAME_ENTRY_value(a->entries, i);
-		n = OBJ_obj2nid(ne->object);
+		obj = ne->object;
+		data = ne->value;
+		data_ptr = data->data;
+		data_len = data->length;
+#endif
+		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;
@@ -3962,8 +4148,8 @@ ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
 		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)
@@ -4490,6 +4676,7 @@ smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *
 {
 	int cert_peer = (kw[4] == 'c') ? 1 : 0;
 	X509 *crt;
+	const ASN1_OBJECT *algorithm;
 	int nid;
 	struct connection *conn;
 
@@ -4509,7 +4696,12 @@ smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *
 	if (!crt)
 		return 0;
 
-	nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+	X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
+#else
+	algorithm = (ASN1_OBJECT *)(crt->cert_info->signature->algorithm);
+#endif
+	nid = OBJ_obj2nid(algorithm);
 
 	smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
 	if (!smp->data.u.str.str) {
@@ -4538,6 +4730,7 @@ smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *
 {
 	int cert_peer = (kw[4] == 'c') ? 1 : 0;
 	X509 *crt;
+	ASN1_OBJECT *algorithm;
 	int nid;
 	struct connection *conn;
 
@@ -4557,7 +4750,13 @@ smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *
 	if (!crt)
 		return 0;
 
-	nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+	X509_get_X509_PUBKEY(crt);
+	X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
+#else
+	algorithm = (ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm);
+#endif
+	nid = OBJ_obj2nid(algorithm);
 
 	smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
 	if (!smp->data.u.str.str) {
-- 
2.9.3

