Date: Sunday, June 18, 2017 @ 19:30:55 Author: eworm Revision: 298960
archrelease: copy trunk to testing-i686, testing-x86_64 Added: openvpn/repos/testing-i686/ openvpn/repos/testing-i686/0004-openssl-1-1-0.patch (from rev 298959, openvpn/trunk/0004-openssl-1-1-0.patch) openvpn/repos/testing-i686/PKGBUILD (from rev 298959, openvpn/trunk/PKGBUILD) openvpn/repos/testing-i686/openvpn.install (from rev 298959, openvpn/trunk/openvpn.install) openvpn/repos/testing-x86_64/ openvpn/repos/testing-x86_64/0004-openssl-1-1-0.patch (from rev 298959, openvpn/trunk/0004-openssl-1-1-0.patch) openvpn/repos/testing-x86_64/PKGBUILD (from rev 298959, openvpn/trunk/PKGBUILD) openvpn/repos/testing-x86_64/openvpn.install (from rev 298959, openvpn/trunk/openvpn.install) -----------------------------------------+ testing-i686/0004-openssl-1-1-0.patch | 1614 ++++++++++++++++++++++++++++++ testing-i686/PKGBUILD | 78 + testing-i686/openvpn.install | 24 testing-x86_64/0004-openssl-1-1-0.patch | 1614 ++++++++++++++++++++++++++++++ testing-x86_64/PKGBUILD | 78 + testing-x86_64/openvpn.install | 24 6 files changed, 3432 insertions(+) Copied: openvpn/repos/testing-i686/0004-openssl-1-1-0.patch (from rev 298959, openvpn/trunk/0004-openssl-1-1-0.patch) =================================================================== --- testing-i686/0004-openssl-1-1-0.patch (rev 0) +++ testing-i686/0004-openssl-1-1-0.patch 2017-06-18 19:30:55 UTC (rev 298960) @@ -0,0 +1,1614 @@ +From 17d1ab90c228b1efbe774357bd3265b2af006899 Mon Sep 17 00:00:00 2001 +From: Emmanuel Deloget <log...@free.fr> +Date: Mon, 12 Jun 2017 15:43:23 +0200 +Subject: [PATCH 1/8] OpenSSL: don't use direct access to the internal of + X509 + +OpenSSL 1.1 does not allow us to directly access the internal of +any data type, including X509. We have to use the defined +functions to do so. + +In x509_verify_ns_cert_type() in particular, this means that we +cannot directly check for the extended flags to find whether the +certificate should be used as a client or as a server certificate. +We need to leverage the X509_check_purpose() API yet this API is +far stricter than the currently implemented check. So far, I have +not been able to find a situation where this stricter test fails +(although I must admit that I haven't tested that very well). + +We double-check the certificate purpose using "direct access" to the +internal of the certificate object (of course, this is not a real +direct access, but we still fetch ASN1 strings within the X509 object +and we check the internal value of these strings). This allow us to +warn the user if there is a discrepancy between the X509_check_purpose() +return value and our internal, less strict check. + +We use these changes to make peer_cert a non-const parameter to +x509_verify_ns_cert_type(). The underlying library waits for a +non-const pointer, and forcing it to be a const pointer does not make +much sense (please note that this has an effect on the mbedtls part +too). + +Compatibility with OpenSSL 1.0 is kept by defining the corresponding +functions when they are not found in the library. + +Signed-off-by: Emmanuel Deloget <log...@free.fr> +Acked-by: Steffan Karger <steffan.kar...@fox-it.com> +Message-Id: <20170612134330.20971-2-log...@free.fr> +URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg14792.html +Signed-off-by: Gert Doering <g...@greenie.muc.de> +--- + configure.ac | 1 + + src/openvpn/openssl_compat.h | 15 +++++++++ + src/openvpn/ssl_openssl.c | 3 +- + src/openvpn/ssl_verify_backend.h | 2 +- + src/openvpn/ssl_verify_mbedtls.c | 2 +- + src/openvpn/ssl_verify_openssl.c | 68 ++++++++++++++++++++++++++++++++++------ + 6 files changed, 78 insertions(+), 13 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 334247df..c30bf3d5 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -921,6 +921,7 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then + [ \ + SSL_CTX_get_default_passwd_cb \ + SSL_CTX_get_default_passwd_cb_userdata \ ++ X509_get0_pubkey \ + X509_STORE_get0_objects \ + X509_OBJECT_free \ + X509_OBJECT_get_type \ +diff --git a/src/openvpn/openssl_compat.h b/src/openvpn/openssl_compat.h +index 811d559c..612bfa56 100644 +--- a/src/openvpn/openssl_compat.h ++++ b/src/openvpn/openssl_compat.h +@@ -73,6 +73,21 @@ SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx) + } + #endif + ++#if !defined(HAVE_X509_GET0_PUBKEY) ++/** ++ * Get the public key from a X509 certificate ++ * ++ * @param x X509 certificate ++ * @return The certificate public key ++ */ ++static inline EVP_PKEY * ++X509_get0_pubkey(const X509 *x) ++{ ++ return (x && x->cert_info && x->cert_info->key) ? ++ x->cert_info->key->pkey : NULL; ++} ++#endif ++ + #if !defined(HAVE_X509_STORE_GET0_OBJECTS) + /** + * Fetch the X509 object stack from the X509 store +diff --git a/src/openvpn/ssl_openssl.c b/src/openvpn/ssl_openssl.c +index 1fa46e18..89c3b014 100644 +--- a/src/openvpn/ssl_openssl.c ++++ b/src/openvpn/ssl_openssl.c +@@ -1070,7 +1070,8 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx, + } + + /* get the public key */ +- ASSERT(cert->cert_info->key->pkey); /* NULL before SSL_CTX_use_certificate() is called */ ++ EVP_PKEY *pkey = X509_get0_pubkey(cert); ++ ASSERT(pkey); /* NULL before SSL_CTX_use_certificate() is called */ + pub_rsa = cert->cert_info->key->pkey->pkey.rsa; + + /* initialize RSA object */ +diff --git a/src/openvpn/ssl_verify_backend.h b/src/openvpn/ssl_verify_backend.h +index 35660532..978e54fd 100644 +--- a/src/openvpn/ssl_verify_backend.h ++++ b/src/openvpn/ssl_verify_backend.h +@@ -210,7 +210,7 @@ void x509_setenv_track(const struct x509_track *xt, struct env_set *es, + * the expected bit set. \c FAILURE if the certificate does + * not have NS cert type verification or the wrong bit set. + */ +-result_t x509_verify_ns_cert_type(const openvpn_x509_cert_t *cert, const int usage); ++result_t x509_verify_ns_cert_type(openvpn_x509_cert_t *cert, const int usage); + + /* + * Verify X.509 key usage extension field. +diff --git a/src/openvpn/ssl_verify_mbedtls.c b/src/openvpn/ssl_verify_mbedtls.c +index d80b7a53..27c5c3e1 100644 +--- a/src/openvpn/ssl_verify_mbedtls.c ++++ b/src/openvpn/ssl_verify_mbedtls.c +@@ -410,7 +410,7 @@ x509_setenv(struct env_set *es, int cert_depth, mbedtls_x509_crt *cert) + } + + result_t +-x509_verify_ns_cert_type(const mbedtls_x509_crt *cert, const int usage) ++x509_verify_ns_cert_type(mbedtls_x509_crt *cert, const int usage) + { + if (usage == NS_CERT_CHECK_NONE) + { +diff --git a/src/openvpn/ssl_verify_openssl.c b/src/openvpn/ssl_verify_openssl.c +index 5d897b6d..31c16389 100644 +--- a/src/openvpn/ssl_verify_openssl.c ++++ b/src/openvpn/ssl_verify_openssl.c +@@ -293,18 +293,20 @@ backend_x509_get_serial_hex(openvpn_x509_cert_t *cert, struct gc_arena *gc) + struct buffer + x509_get_sha1_fingerprint(X509 *cert, struct gc_arena *gc) + { +- struct buffer hash = alloc_buf_gc(sizeof(cert->sha1_hash), gc); +- memcpy(BPTR(&hash), cert->sha1_hash, sizeof(cert->sha1_hash)); +- ASSERT(buf_inc_len(&hash, sizeof(cert->sha1_hash))); ++ const EVP_MD *sha1 = EVP_sha1(); ++ struct buffer hash = alloc_buf_gc(EVP_MD_size(sha1), gc); ++ X509_digest(cert, EVP_sha1(), BPTR(&hash), NULL); ++ ASSERT(buf_inc_len(&hash, EVP_MD_size(sha1))); + return hash; + } + + struct buffer + x509_get_sha256_fingerprint(X509 *cert, struct gc_arena *gc) + { +- struct buffer hash = alloc_buf_gc((EVP_sha256())->md_size, gc); ++ const EVP_MD *sha256 = EVP_sha256(); ++ struct buffer hash = alloc_buf_gc(EVP_MD_size(sha256), gc); + X509_digest(cert, EVP_sha256(), BPTR(&hash), NULL); +- ASSERT(buf_inc_len(&hash, (EVP_sha256())->md_size)); ++ ASSERT(buf_inc_len(&hash, EVP_MD_size(sha256))); + return hash; + } + +@@ -569,7 +571,7 @@ x509_setenv(struct env_set *es, int cert_depth, openvpn_x509_cert_t *peer_cert) + } + + result_t +-x509_verify_ns_cert_type(const openvpn_x509_cert_t *peer_cert, const int usage) ++x509_verify_ns_cert_type(openvpn_x509_cert_t *peer_cert, const int usage) + { + if (usage == NS_CERT_CHECK_NONE) + { +@@ -577,13 +579,59 @@ x509_verify_ns_cert_type(const openvpn_x509_cert_t *peer_cert, const int usage) + } + if (usage == NS_CERT_CHECK_CLIENT) + { +- return ((peer_cert->ex_flags & EXFLAG_NSCERT) +- && (peer_cert->ex_nscert & NS_SSL_CLIENT)) ? SUCCESS : FAILURE; ++ /* ++ * Unfortunately, X509_check_purpose() does some weird thing that ++ * prevent it to take a const argument ++ */ ++ result_t result = X509_check_purpose(peer_cert, X509_PURPOSE_SSL_CLIENT, 0) ? ++ SUCCESS : FAILURE; ++ ++ /* ++ * old versions of OpenSSL allow us to make the less strict check we used to ++ * do. If this less strict check pass, warn user that this might not be the ++ * case when its distribution will update to OpenSSL 1.1 ++ */ ++ if (result == FAILURE) ++ { ++ ASN1_BIT_STRING *ns; ++ ns = X509_get_ext_d2i(peer_cert, NID_netscape_cert_type, NULL, NULL); ++ result = (ns && ns->length > 0 && (ns->data[0] & NS_SSL_CLIENT)) ? SUCCESS : FAILURE; ++ if (result == SUCCESS) ++ { ++ msg(M_WARN, "X509: Certificate is a client certificate yet it's purpose " ++ "cannot be verified (check may fail in the future)"); ++ } ++ ASN1_BIT_STRING_free(ns); ++ } ++ return result; + } + if (usage == NS_CERT_CHECK_SERVER) + { +- return ((peer_cert->ex_flags & EXFLAG_NSCERT) +- && (peer_cert->ex_nscert & NS_SSL_SERVER)) ? SUCCESS : FAILURE; ++ /* ++ * Unfortunately, X509_check_purpose() does some weird thing that ++ * prevent it to take a const argument ++ */ ++ result_t result = X509_check_purpose(peer_cert, X509_PURPOSE_SSL_SERVER, 0) ? ++ SUCCESS : FAILURE; ++ ++ /* ++ * old versions of OpenSSL allow us to make the less strict check we used to ++ * do. If this less strict check pass, warn user that this might not be the ++ * case when its distribution will update to OpenSSL 1.1 ++ */ ++ if (result == FAILURE) ++ { ++ ASN1_BIT_STRING *ns; ++ ns = X509_get_ext_d2i(peer_cert, NID_netscape_cert_type, NULL, NULL); ++ result = (ns && ns->length > 0 && (ns->data[0] & NS_SSL_SERVER)) ? SUCCESS : FAILURE; ++ if (result == SUCCESS) ++ { ++ msg(M_WARN, "X509: Certificate is a server certificate yet it's purpose " ++ "cannot be verified (check may fail in the future)"); ++ } ++ ASN1_BIT_STRING_free(ns); ++ } ++ return result; + } + + return FAILURE; +From b8ca5bc3593e539d0735a74b55ed41a792e55033 Mon Sep 17 00:00:00 2001 +From: Emmanuel Deloget <log...@free.fr> +Date: Mon, 12 Jun 2017 15:43:24 +0200 +Subject: [PATCH 2/8] OpenSSL: don't use direct access to the internal of + EVP_PKEY + +OpenSSL 1.1 does not allow us to directly access the internal of +any data type, including EVP_PKEY. We have to use the defined +functions to do so. + +Compatibility with OpenSSL 1.0 is kept by defining the corresponding +functions when they are not found in the library. + +Signed-off-by: Emmanuel Deloget <log...@free.fr> +Acked-by: Steffan Karger <steffan.kar...@fox-it.com> +Message-Id: <20170612134330.20971-3-log...@free.fr> +URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg14795.html +Signed-off-by: Gert Doering <g...@greenie.muc.de> +--- + configure.ac | 3 +++ + src/openvpn/openssl_compat.h | 42 ++++++++++++++++++++++++++++++++++++++++++ + src/openvpn/ssl_openssl.c | 6 +++--- + 3 files changed, 48 insertions(+), 3 deletions(-) + +diff --git a/configure.ac b/configure.ac +index c30bf3d5..43f332b2 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -925,6 +925,9 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then + X509_STORE_get0_objects \ + X509_OBJECT_free \ + X509_OBJECT_get_type \ ++ EVP_PKEY_id \ ++ EVP_PKEY_get0_RSA \ ++ EVP_PKEY_get0_DSA \ + RSA_meth_new \ + RSA_meth_free \ + RSA_meth_set_pub_enc \ +diff --git a/src/openvpn/openssl_compat.h b/src/openvpn/openssl_compat.h +index 612bfa56..60498595 100644 +--- a/src/openvpn/openssl_compat.h ++++ b/src/openvpn/openssl_compat.h +@@ -133,6 +133,48 @@ X509_OBJECT_get_type(const X509_OBJECT *obj) + } + #endif + ++#if !defined(HAVE_EVP_PKEY_GET0_RSA) ++/** ++ * Get the RSA object of a public key ++ * ++ * @param pkey Public key object ++ * @return The underlying RSA object ++ */ ++static inline RSA * ++EVP_PKEY_get0_RSA(EVP_PKEY *pkey) ++{ ++ return pkey ? pkey->pkey.rsa : NULL; ++} ++#endif ++ ++#if !defined(HAVE_EVP_PKEY_ID) ++/** ++ * Get the PKEY type ++ * ++ * @param pkey Public key object ++ * @return The key type ++ */ ++static inline int ++EVP_PKEY_id(const EVP_PKEY *pkey) ++{ ++ return pkey ? pkey->type : EVP_PKEY_NONE; ++} ++#endif ++ ++#if !defined(HAVE_EVP_PKEY_GET0_DSA) ++/** ++ * Get the DSA object of a public key ++ * ++ * @param pkey Public key object ++ * @return The underlying DSA object ++ */ ++static inline DSA * ++EVP_PKEY_get0_DSA(EVP_PKEY *pkey) ++{ ++ return pkey ? pkey->pkey.dsa : NULL; ++} ++#endif ++ + #if !defined(HAVE_RSA_METH_NEW) + /** + * Allocate a new RSA method object +diff --git a/src/openvpn/ssl_openssl.c b/src/openvpn/ssl_openssl.c +index 89c3b014..c84372d6 100644 +--- a/src/openvpn/ssl_openssl.c ++++ b/src/openvpn/ssl_openssl.c +@@ -1072,7 +1072,7 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx, + /* get the public key */ + EVP_PKEY *pkey = X509_get0_pubkey(cert); + ASSERT(pkey); /* NULL before SSL_CTX_use_certificate() is called */ +- pub_rsa = cert->cert_info->key->pkey->pkey.rsa; ++ pub_rsa = EVP_PKEY_get0_RSA(pkey); + + /* initialize RSA object */ + rsa->n = BN_dup(pub_rsa->n); +@@ -1677,13 +1677,13 @@ print_details(struct key_state_ssl *ks_ssl, const char *prefix) + EVP_PKEY *pkey = X509_get_pubkey(cert); + if (pkey != NULL) + { +- if (pkey->type == EVP_PKEY_RSA && pkey->pkey.rsa != NULL ++ if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA && EVP_PKEY_get0_RSA(pkey) != NULL + && pkey->pkey.rsa->n != NULL) + { + openvpn_snprintf(s2, sizeof(s2), ", %d bit RSA", + BN_num_bits(pkey->pkey.rsa->n)); + } +- else if (pkey->type == EVP_PKEY_DSA && pkey->pkey.dsa != NULL ++ else if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA && EVP_PKEY_get0_DSA(pkey) != NULL + && pkey->pkey.dsa->p != NULL) + { + openvpn_snprintf(s2, sizeof(s2), ", %d bit DSA", +From f7780af6f1aaffcbbfb8b4dde0f2af052f84b28a Mon Sep 17 00:00:00 2001 +From: Emmanuel Deloget <log...@free.fr> +Date: Mon, 12 Jun 2017 15:43:25 +0200 +Subject: [PATCH 3/8] OpenSSL: don't use direct access to the internal of RSA + +OpenSSL 1.1 does not allow us to directly access the internal of +any data type, including RSA. We have to use the defined +functions to do so. + +Compatibility with OpenSSL 1.0 is kept by defining the corresponding +functions when they are not found in the library. + +Signed-off-by: Emmanuel Deloget <log...@free.fr> +Acked-by: Steffan Karger <steffan.kar...@fox-it.com> +Message-Id: <20170612134330.20971-4-log...@free.fr> +URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg14790.html +Signed-off-by: Gert Doering <g...@greenie.muc.de> +--- + configure.ac | 4 ++ + src/openvpn/openssl_compat.h | 100 +++++++++++++++++++++++++++++++++++++++++++ + src/openvpn/ssl_openssl.c | 24 +++++++---- + 3 files changed, 119 insertions(+), 9 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 43f332b2..e9ac5a6e 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -928,6 +928,10 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then + EVP_PKEY_id \ + EVP_PKEY_get0_RSA \ + EVP_PKEY_get0_DSA \ ++ RSA_set_flags \ ++ RSA_bits \ ++ RSA_get0_key \ ++ RSA_set0_key \ + RSA_meth_new \ + RSA_meth_free \ + RSA_meth_set_pub_enc \ +diff --git a/src/openvpn/openssl_compat.h b/src/openvpn/openssl_compat.h +index 60498595..e3f20b73 100644 +--- a/src/openvpn/openssl_compat.h ++++ b/src/openvpn/openssl_compat.h +@@ -175,6 +175,106 @@ EVP_PKEY_get0_DSA(EVP_PKEY *pkey) + } + #endif + ++#if !defined(HAVE_RSA_SET_FLAGS) ++/** ++ * Set the RSA flags ++ * ++ * @param rsa The RSA object ++ * @param flags New flags value ++ */ ++static inline void ++RSA_set_flags(RSA *rsa, int flags) ++{ ++ if (rsa) ++ { ++ rsa->flags = flags; ++ } ++} ++#endif ++ ++#if !defined(HAVE_RSA_GET0_KEY) ++/** ++ * Get the RSA parameters ++ * ++ * @param rsa The RSA object ++ * @param n The @c n parameter ++ * @param e The @c e parameter ++ * @param d The @c d parameter ++ */ ++static inline void ++RSA_get0_key(const RSA *rsa, const BIGNUM **n, ++ const BIGNUM **e, const BIGNUM **d) ++{ ++ if (n != NULL) ++ { ++ *n = rsa ? rsa->n : NULL; ++ } ++ if (e != NULL) ++ { ++ *e = rsa ? rsa->e : NULL; ++ } ++ if (d != NULL) ++ { ++ *d = rsa ? rsa->d : NULL; ++ } ++} ++#endif ++ ++#if !defined(HAVE_RSA_SET0_KEY) ++/** ++ * Set the RSA parameters ++ * ++ * @param rsa The RSA object ++ * @param n The @c n parameter ++ * @param e The @c e parameter ++ * @param d The @c d parameter ++ * @return 1 on success, 0 on error ++ */ ++static inline int ++RSA_set0_key(RSA *rsa, BIGNUM *n, BIGNUM *e, BIGNUM *d) ++{ ++ if ((rsa->n == NULL && n == NULL) ++ || (rsa->e == NULL && e == NULL)) ++ { ++ return 0; ++ } ++ ++ if (n != NULL) ++ { ++ BN_free(rsa->n); ++ rsa->n = n; ++ } ++ if (e != NULL) ++ { ++ BN_free(rsa->e); ++ rsa->e = e; ++ } ++ if (d != NULL) ++ { ++ BN_free(rsa->d); ++ rsa->d = d; ++ } ++ ++ return 1; ++} ++#endif ++ ++#if !defined(HAVE_RSA_BITS) ++/** ++ * Number of significant RSA bits ++ * ++ * @param rsa The RSA object ; shall not be NULL ++ * @return The number of RSA bits or 0 on error ++ */ ++static inline int ++RSA_bits(const RSA *rsa) ++{ ++ const BIGNUM *n = NULL; ++ RSA_get0_key(rsa, &n, NULL, NULL); ++ return n ? BN_num_bits(n) : 0; ++} ++#endif ++ + #if !defined(HAVE_RSA_METH_NEW) + /** + * Allocate a new RSA method object +diff --git a/src/openvpn/ssl_openssl.c b/src/openvpn/ssl_openssl.c +index c84372d6..da801ed5 100644 +--- a/src/openvpn/ssl_openssl.c ++++ b/src/openvpn/ssl_openssl.c +@@ -973,10 +973,13 @@ rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, i + + /* called at RSA_free */ + static int +-rsa_finish(RSA *rsa) ++openvpn_extkey_rsa_finish(RSA *rsa) + { +- RSA_meth_free(rsa->meth); +- rsa->meth = NULL; ++ /* meth was allocated in tls_ctx_use_external_private_key() ; since ++ * this function is called when the parent RSA object is destroyed, ++ * it is no longer used after this point so kill it. */ ++ const RSA_METHOD *meth = RSA_get_method(rsa); ++ RSA_meth_free((RSA_METHOD *)meth); + return 1; + } + +@@ -1058,7 +1061,7 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx, + RSA_meth_set_priv_enc(rsa_meth, rsa_priv_enc); + RSA_meth_set_priv_dec(rsa_meth, rsa_priv_dec); + RSA_meth_set_init(rsa_meth, NULL); +- RSA_meth_set_finish(rsa_meth, rsa_finish); ++ RSA_meth_set_finish(rsa_meth, openvpn_extkey_rsa_finish); + RSA_meth_set0_app_data(rsa_meth, NULL); + + /* allocate RSA object */ +@@ -1075,8 +1078,11 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx, + pub_rsa = EVP_PKEY_get0_RSA(pkey); + + /* initialize RSA object */ +- rsa->n = BN_dup(pub_rsa->n); +- rsa->flags |= RSA_FLAG_EXT_PKEY; ++ const BIGNUM *n = NULL; ++ const BIGNUM *e = NULL; ++ RSA_get0_key(pub_rsa, &n, &e, NULL); ++ RSA_set0_key(rsa, BN_dup(n), BN_dup(e), NULL); ++ RSA_set_flags(rsa, RSA_flags(rsa) | RSA_FLAG_EXT_PKEY); + if (!RSA_set_method(rsa, rsa_meth)) + { + goto err; +@@ -1677,11 +1683,11 @@ print_details(struct key_state_ssl *ks_ssl, const char *prefix) + EVP_PKEY *pkey = X509_get_pubkey(cert); + if (pkey != NULL) + { +- if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA && EVP_PKEY_get0_RSA(pkey) != NULL +- && pkey->pkey.rsa->n != NULL) ++ if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA && EVP_PKEY_get0_RSA(pkey) != NULL) + { ++ RSA *rsa = EVP_PKEY_get0_RSA(pkey); + openvpn_snprintf(s2, sizeof(s2), ", %d bit RSA", +- BN_num_bits(pkey->pkey.rsa->n)); ++ RSA_bits(rsa)); + } + else if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA && EVP_PKEY_get0_DSA(pkey) != NULL + && pkey->pkey.dsa->p != NULL) +From c07c0358b553c519ed9d80e2e0a9ba48ca8850e4 Mon Sep 17 00:00:00 2001 +From: Emmanuel Deloget <log...@free.fr> +Date: Mon, 12 Jun 2017 15:43:26 +0200 +Subject: [PATCH 4/8] OpenSSL: don't use direct access to the internal of DSA + +OpenSSL 1.1 does not allow us to directly access the internal of +any data type, including DSA. We have to use the defined +functions to do so. + +Compatibility with OpenSSL 1.0 is kept by defining the corresponding +functions when they are not found in the library. + +Signed-off-by: Emmanuel Deloget <log...@free.fr> +Acked-by: Steffan Karger <steffan.kar...@fox-it.com> +Message-Id: <20170612134330.20971-5-log...@free.fr> +URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg14791.html +Signed-off-by: Gert Doering <g...@greenie.muc.de> +--- + configure.ac | 2 ++ + src/openvpn/openssl_compat.h | 44 ++++++++++++++++++++++++++++++++++++++++++++ + src/openvpn/ssl_openssl.c | 6 +++--- + 3 files changed, 49 insertions(+), 3 deletions(-) + +diff --git a/configure.ac b/configure.ac +index e9ac5a6e..52348780 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -932,6 +932,8 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then + RSA_bits \ + RSA_get0_key \ + RSA_set0_key \ ++ DSA_get0_pqg \ ++ DSA_bits \ + RSA_meth_new \ + RSA_meth_free \ + RSA_meth_set_pub_enc \ +diff --git a/src/openvpn/openssl_compat.h b/src/openvpn/openssl_compat.h +index e3f20b73..729fab6c 100644 +--- a/src/openvpn/openssl_compat.h ++++ b/src/openvpn/openssl_compat.h +@@ -275,6 +275,50 @@ RSA_bits(const RSA *rsa) + } + #endif + ++#if !defined(HAVE_DSA_GET0_PQG) ++/** ++ * Get the DSA parameters ++ * ++ * @param dsa The DSA object ++ * @param p The @c p parameter ++ * @param q The @c q parameter ++ * @param g The @c g parameter ++ */ ++static inline void ++DSA_get0_pqg(const DSA *dsa, const BIGNUM **p, ++ const BIGNUM **q, const BIGNUM **g) ++{ ++ if (p != NULL) ++ { ++ *p = dsa ? dsa->p : NULL; ++ } ++ if (q != NULL) ++ { ++ *q = dsa ? dsa->q : NULL; ++ } ++ if (g != NULL) ++ { ++ *g = dsa ? dsa->g : NULL; ++ } ++} ++#endif ++ ++#if !defined(HAVE_DSA_BITS) ++/** ++ * Number of significant DSA bits ++ * ++ * @param rsa The DSA object ; shall not be NULL ++ * @return The number of DSA bits or 0 on error ++ */ ++static inline int ++DSA_bits(const DSA *dsa) ++{ ++ const BIGNUM *p = NULL; ++ DSA_get0_pqg(dsa, &p, NULL, NULL); ++ return p ? BN_num_bits(p) : 0; ++} ++#endif ++ + #if !defined(HAVE_RSA_METH_NEW) + /** + * Allocate a new RSA method object +diff --git a/src/openvpn/ssl_openssl.c b/src/openvpn/ssl_openssl.c +index da801ed5..11f4a567 100644 +--- a/src/openvpn/ssl_openssl.c ++++ b/src/openvpn/ssl_openssl.c +@@ -1689,11 +1689,11 @@ print_details(struct key_state_ssl *ks_ssl, const char *prefix) + openvpn_snprintf(s2, sizeof(s2), ", %d bit RSA", + RSA_bits(rsa)); + } +- else if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA && EVP_PKEY_get0_DSA(pkey) != NULL +- && pkey->pkey.dsa->p != NULL) ++ else if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA && EVP_PKEY_get0_DSA(pkey) != NULL) + { ++ DSA *dsa = EVP_PKEY_get0_DSA(pkey); + openvpn_snprintf(s2, sizeof(s2), ", %d bit DSA", +- BN_num_bits(pkey->pkey.dsa->p)); ++ DSA_bits(dsa)); + } + EVP_PKEY_free(pkey); + } +From 3fd07c31fe8878dc75e760d151d291379c0f8743 Mon Sep 17 00:00:00 2001 +From: Emmanuel Deloget <log...@free.fr> +Date: Mon, 12 Jun 2017 15:43:30 +0200 +Subject: [PATCH 5/8] OpenSSL: force meth->name as non-const when we free() + it + +We are in control of meth->name (we string_alloc() it in RSA_meth_new()) +so we know that we can free() it when it's no longer needed. Yet we have +to force the value to be non-const to avoid a compiler warning -- due to +the fact that OpenSSL defines the value as a const char*, regardless of +its origin. + +Acked-by: Steffan Karger <steffan.kar...@fox-it.com> +Message-Id: <20170612134330.20971-9-log...@free.fr> +URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg14798.html + +Signed-off-by: Gert Doering <g...@greenie.muc.de> +--- + src/openvpn/openssl_compat.h | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/src/openvpn/openssl_compat.h b/src/openvpn/openssl_compat.h +index 729fab6c..eeacb525 100644 +--- a/src/openvpn/openssl_compat.h ++++ b/src/openvpn/openssl_compat.h +@@ -349,7 +349,13 @@ RSA_meth_free(RSA_METHOD *meth) + { + if (meth) + { +- free(meth->name); ++ /* OpenSSL defines meth->name to be a const pointer, yet we ++ * feed it with an allocated string (from RSA_meth_new()). ++ * Thus we are allowed to free it here. In order to avoid a ++ * "passing 'const char *' to parameter of type 'void *' discards ++ * qualifiers" warning, we force the pointer to be a non-const value. ++ */ ++ free((char *)meth->name); + free(meth); + } + } +From c481ef002803f360743c72727ae3ca971ce59a5d Mon Sep 17 00:00:00 2001 +From: Emmanuel Deloget <log...@free.fr> +Date: Mon, 12 Jun 2017 15:43:27 +0200 +Subject: [PATCH 6/8] OpenSSL: don't use direct access to the internal of + EVP_MD_CTX + +OpenSSL 1.1 does not allow us to directly access the internal of +any data type, including EVP_MD_CTX. We have to use the defined +functions to do so. + +Compatibility with OpenSSL 1.0 is kept by defining the corresponding +functions when they are not found in the library. + +Signed-off-by: Emmanuel Deloget <log...@free.fr> +Acked-by: Steffan Karger <steffan.kar...@fox-it.com> +Message-Id: <20170612134330.20971-6-log...@free.fr> +URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg14793.html +Signed-off-by: Gert Doering <g...@greenie.muc.de> +--- + configure.ac | 3 ++ + src/openvpn/crypto_backend.h | 14 ++++++++ + src/openvpn/crypto_mbedtls.c | 12 +++++++ + src/openvpn/crypto_openssl.c | 18 ++++++++-- + src/openvpn/httpdigest.c | 78 +++++++++++++++++++++++--------------------- + src/openvpn/misc.c | 14 ++++---- + src/openvpn/openssl_compat.h | 43 ++++++++++++++++++++++++ + src/openvpn/openvpn.h | 2 +- + src/openvpn/push.c | 11 ++++--- + 9 files changed, 143 insertions(+), 52 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 52348780..f971e54a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -919,6 +919,9 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then + + AC_CHECK_FUNCS( + [ \ ++ EVP_MD_CTX_new \ ++ EVP_MD_CTX_free \ ++ EVP_MD_CTX_reset \ + SSL_CTX_get_default_passwd_cb \ + SSL_CTX_get_default_passwd_cb_userdata \ + X509_get0_pubkey \ +diff --git a/src/openvpn/crypto_backend.h b/src/openvpn/crypto_backend.h +index e2d2c96f..f1da0432 100644 +--- a/src/openvpn/crypto_backend.h ++++ b/src/openvpn/crypto_backend.h +@@ -507,6 +507,20 @@ int md_kt_size(const md_kt_t *kt); + int md_full(const md_kt_t *kt, const uint8_t *src, int src_len, uint8_t *dst); + + /* ++ * Allocate a new message digest context ++ * ++ * @return a new zeroed MD context ++ */ ++md_ctx_t *md_ctx_new(void); ++ ++/* ++ * Free an existing, non-null message digest context ++ * ++ * @param ctx Message digest context ++ */ ++void md_ctx_free(md_ctx_t *ctx); ++ ++/* + * Initialises the given message digest context. + * + * @param ctx Message digest context +diff --git a/src/openvpn/crypto_mbedtls.c b/src/openvpn/crypto_mbedtls.c +index e6388dd5..03cc1308 100644 +--- a/src/openvpn/crypto_mbedtls.c ++++ b/src/openvpn/crypto_mbedtls.c +@@ -765,6 +765,18 @@ md_full(const md_kt_t *kt, const uint8_t *src, int src_len, uint8_t *dst) + return 0 == mbedtls_md(kt, src, src_len, dst); + } + ++mbedtls_md_context_t * ++md_ctx_new(void) ++{ ++ mbedtls_md_context_t *ctx; ++ ALLOC_OBJ_CLEAR(ctx, mbedtls_md_context_t); ++ return ctx; ++} ++ ++void md_ctx_free(mbedtls_md_context_t *ctx) ++{ ++ free(ctx); ++} + + void + md_ctx_init(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *kt) +diff --git a/src/openvpn/crypto_openssl.c b/src/openvpn/crypto_openssl.c +index ee20902f..3a5a26f8 100644 +--- a/src/openvpn/crypto_openssl.c ++++ b/src/openvpn/crypto_openssl.c +@@ -41,6 +41,7 @@ + #include "integer.h" + #include "crypto.h" + #include "crypto_backend.h" ++#include "openssl_compat.h" + + #include <openssl/des.h> + #include <openssl/err.h> +@@ -843,13 +844,24 @@ md_full(const EVP_MD *kt, const uint8_t *src, int src_len, uint8_t *dst) + return EVP_Digest(src, src_len, dst, &in_md_len, kt, NULL); + } + ++EVP_MD_CTX * ++md_ctx_new(void) ++{ ++ EVP_MD_CTX *ctx = EVP_MD_CTX_new(); ++ check_malloc_return(ctx); ++ return ctx; ++} ++ ++void md_ctx_free(EVP_MD_CTX *ctx) ++{ ++ EVP_MD_CTX_free(ctx); ++} ++ + void + md_ctx_init(EVP_MD_CTX *ctx, const EVP_MD *kt) + { + ASSERT(NULL != ctx && NULL != kt); + +- CLEAR(*ctx); +- + EVP_MD_CTX_init(ctx); + EVP_DigestInit(ctx, kt); + } +@@ -857,7 +869,7 @@ md_ctx_init(EVP_MD_CTX *ctx, const EVP_MD *kt) + void + md_ctx_cleanup(EVP_MD_CTX *ctx) + { +- EVP_MD_CTX_cleanup(ctx); ++ EVP_MD_CTX_reset(ctx); + } + + int +diff --git a/src/openvpn/httpdigest.c b/src/openvpn/httpdigest.c +index e578c85d..c553f939 100644 +--- a/src/openvpn/httpdigest.c ++++ b/src/openvpn/httpdigest.c +@@ -80,27 +80,28 @@ DigestCalcHA1( + ) + { + HASH HA1; +- md_ctx_t md5_ctx; ++ md_ctx_t *md5_ctx = md_ctx_new(); + const md_kt_t *md5_kt = md_kt_get("MD5"); + +- md_ctx_init(&md5_ctx, md5_kt); +- md_ctx_update(&md5_ctx, (const uint8_t *) pszUserName, strlen(pszUserName)); +- md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); +- md_ctx_update(&md5_ctx, (const uint8_t *) pszRealm, strlen(pszRealm)); +- md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); +- md_ctx_update(&md5_ctx, (const uint8_t *) pszPassword, strlen(pszPassword)); +- md_ctx_final(&md5_ctx, HA1); ++ md_ctx_init(md5_ctx, md5_kt); ++ md_ctx_update(md5_ctx, (const uint8_t *) pszUserName, strlen(pszUserName)); ++ md_ctx_update(md5_ctx, (const uint8_t *) ":", 1); ++ md_ctx_update(md5_ctx, (const uint8_t *) pszRealm, strlen(pszRealm)); ++ md_ctx_update(md5_ctx, (const uint8_t *) ":", 1); ++ md_ctx_update(md5_ctx, (const uint8_t *) pszPassword, strlen(pszPassword)); ++ md_ctx_final(md5_ctx, HA1); + if (pszAlg && strcasecmp(pszAlg, "md5-sess") == 0) + { +- md_ctx_init(&md5_ctx, md5_kt); +- md_ctx_update(&md5_ctx, HA1, HASHLEN); +- md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); +- md_ctx_update(&md5_ctx, (const uint8_t *) pszNonce, strlen(pszNonce)); +- md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); +- md_ctx_update(&md5_ctx, (const uint8_t *) pszCNonce, strlen(pszCNonce)); +- md_ctx_final(&md5_ctx, HA1); ++ md_ctx_init(md5_ctx, md5_kt); ++ md_ctx_update(md5_ctx, HA1, HASHLEN); ++ md_ctx_update(md5_ctx, (const uint8_t *) ":", 1); ++ md_ctx_update(md5_ctx, (const uint8_t *) pszNonce, strlen(pszNonce)); ++ md_ctx_update(md5_ctx, (const uint8_t *) ":", 1); ++ md_ctx_update(md5_ctx, (const uint8_t *) pszCNonce, strlen(pszCNonce)); ++ md_ctx_final(md5_ctx, HA1); + } +- md_ctx_cleanup(&md5_ctx); ++ md_ctx_cleanup(md5_ctx); ++ md_ctx_free(md5_ctx); + CvtHex(HA1, SessionKey); + } + +@@ -122,40 +123,41 @@ DigestCalcResponse( + HASH RespHash; + HASHHEX HA2Hex; + +- md_ctx_t md5_ctx; ++ md_ctx_t *md5_ctx = md_ctx_new(); + const md_kt_t *md5_kt = md_kt_get("MD5"); + + /* calculate H(A2) */ +- md_ctx_init(&md5_ctx, md5_kt); +- md_ctx_update(&md5_ctx, (const uint8_t *) pszMethod, strlen(pszMethod)); +- md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); +- md_ctx_update(&md5_ctx, (const uint8_t *) pszDigestUri, strlen(pszDigestUri)); ++ md_ctx_init(md5_ctx, md5_kt); ++ md_ctx_update(md5_ctx, (const uint8_t *) pszMethod, strlen(pszMethod)); ++ md_ctx_update(md5_ctx, (const uint8_t *) ":", 1); ++ md_ctx_update(md5_ctx, (const uint8_t *) pszDigestUri, strlen(pszDigestUri)); + if (strcasecmp(pszQop, "auth-int") == 0) + { +- md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); +- md_ctx_update(&md5_ctx, HEntity, HASHHEXLEN); ++ md_ctx_update(md5_ctx, (const uint8_t *) ":", 1); ++ md_ctx_update(md5_ctx, HEntity, HASHHEXLEN); + } +- md_ctx_final(&md5_ctx, HA2); ++ md_ctx_final(md5_ctx, HA2); + CvtHex(HA2, HA2Hex); + + /* calculate response */ +- md_ctx_init(&md5_ctx, md5_kt); +- md_ctx_update(&md5_ctx, HA1, HASHHEXLEN); +- md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); +- md_ctx_update(&md5_ctx, (const uint8_t *) pszNonce, strlen(pszNonce)); +- md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); ++ md_ctx_init(md5_ctx, md5_kt); ++ md_ctx_update(md5_ctx, HA1, HASHHEXLEN); ++ md_ctx_update(md5_ctx, (const uint8_t *) ":", 1); ++ md_ctx_update(md5_ctx, (const uint8_t *) pszNonce, strlen(pszNonce)); ++ md_ctx_update(md5_ctx, (const uint8_t *) ":", 1); + if (*pszQop) + { +- md_ctx_update(&md5_ctx, (const uint8_t *) pszNonceCount, strlen(pszNonceCount)); +- md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); +- md_ctx_update(&md5_ctx, (const uint8_t *) pszCNonce, strlen(pszCNonce)); +- md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); +- md_ctx_update(&md5_ctx, (const uint8_t *) pszQop, strlen(pszQop)); +- md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); ++ md_ctx_update(md5_ctx, (const uint8_t *) pszNonceCount, strlen(pszNonceCount)); ++ md_ctx_update(md5_ctx, (const uint8_t *) ":", 1); ++ md_ctx_update(md5_ctx, (const uint8_t *) pszCNonce, strlen(pszCNonce)); ++ md_ctx_update(md5_ctx, (const uint8_t *) ":", 1); ++ md_ctx_update(md5_ctx, (const uint8_t *) pszQop, strlen(pszQop)); ++ md_ctx_update(md5_ctx, (const uint8_t *) ":", 1); + } +- md_ctx_update(&md5_ctx, HA2Hex, HASHHEXLEN); +- md_ctx_final(&md5_ctx, RespHash); +- md_ctx_cleanup(&md5_ctx); ++ md_ctx_update(md5_ctx, HA2Hex, HASHHEXLEN); ++ md_ctx_final(md5_ctx, RespHash); ++ md_ctx_cleanup(md5_ctx); ++ md_ctx_free(md5_ctx); + CvtHex(RespHash, Response); + } + +diff --git a/src/openvpn/misc.c b/src/openvpn/misc.c +index d286c197..df108b08 100644 +--- a/src/openvpn/misc.c ++++ b/src/openvpn/misc.c +@@ -1387,7 +1387,7 @@ get_user_pass_auto_userid(struct user_pass *up, const char *tag) + static const uint8_t hashprefix[] = "AUTO_USERID_DIGEST"; + + const md_kt_t *md5_kt = md_kt_get("MD5"); +- md_ctx_t ctx; ++ md_ctx_t *ctx; + + CLEAR(*up); + buf_set_write(&buf, (uint8_t *)up->username, USER_PASS_LEN); +@@ -1395,11 +1395,13 @@ get_user_pass_auto_userid(struct user_pass *up, const char *tag) + if (get_default_gateway_mac_addr(macaddr)) + { + dmsg(D_AUTO_USERID, "GUPAU: macaddr=%s", format_hex_ex(macaddr, sizeof(macaddr), 0, 1, ":", &gc)); +- md_ctx_init(&ctx, md5_kt); +- md_ctx_update(&ctx, hashprefix, sizeof(hashprefix) - 1); +- md_ctx_update(&ctx, macaddr, sizeof(macaddr)); +- md_ctx_final(&ctx, digest); +- md_ctx_cleanup(&ctx) ++ ctx = md_ctx_new(); ++ md_ctx_init(ctx, md5_kt); ++ md_ctx_update(ctx, hashprefix, sizeof(hashprefix) - 1); ++ md_ctx_update(ctx, macaddr, sizeof(macaddr)); ++ md_ctx_final(ctx, digest); ++ md_ctx_cleanup(ctx); ++ md_ctx_free(ctx); + buf_printf(&buf, "%s", format_hex_ex(digest, sizeof(digest), 0, 256, " ", &gc)); + } + else +diff --git a/src/openvpn/openssl_compat.h b/src/openvpn/openssl_compat.h +index eeacb525..3d8fad10 100644 +--- a/src/openvpn/openssl_compat.h ++++ b/src/openvpn/openssl_compat.h +@@ -45,6 +45,49 @@ + #include <openssl/ssl.h> + #include <openssl/x509.h> + ++#if !defined(HAVE_EVP_MD_CTX_RESET) ++/** ++ * Reset a message digest context ++ * ++ * @param ctx The message digest context ++ * @return 1 on success, 0 on error ++ */ ++static inline int ++EVP_MD_CTX_reset(EVP_MD_CTX *ctx) ++{ ++ EVP_MD_CTX_cleanup(ctx); ++ return 1; ++} ++#endif ++ ++#if !defined(HAVE_EVP_MD_CTX_FREE) ++/** ++ * Free an existing message digest context ++ * ++ * @param ctx The message digest context ++ */ ++static inline void ++EVP_MD_CTX_free(EVP_MD_CTX *ctx) ++{ ++ free(ctx); ++} ++#endif ++ ++#if !defined(HAVE_EVP_MD_CTX_NEW) ++/** ++ * Allocate a new message digest object ++ * ++ * @return A zero'ed message digest object ++ */ ++static inline EVP_MD_CTX * ++EVP_MD_CTX_new(void) ++{ ++ EVP_MD_CTX *ctx = NULL; ++ ALLOC_OBJ_CLEAR(ctx, EVP_MD_CTX); ++ return ctx; ++} ++#endif ++ + #if !defined(HAVE_SSL_CTX_GET_DEFAULT_PASSWD_CB_USERDATA) + /** + * Fetch the default password callback user data from the SSL context +diff --git a/src/openvpn/openvpn.h b/src/openvpn/openvpn.h +index c01e8a2c..9262e68b 100644 +--- a/src/openvpn/openvpn.h ++++ b/src/openvpn/openvpn.h +@@ -472,7 +472,7 @@ struct context_2 + + /* hash of pulled options, so we can compare when options change */ + bool pulled_options_digest_init_done; +- md_ctx_t pulled_options_state; ++ md_ctx_t *pulled_options_state; + struct sha256_digest pulled_options_digest; + + struct event_timeout scheduled_exit; +diff --git a/src/openvpn/push.c b/src/openvpn/push.c +index 441d303e..5947a31f 100644 +--- a/src/openvpn/push.c ++++ b/src/openvpn/push.c +@@ -723,7 +723,8 @@ process_incoming_push_msg(struct context *c, + struct buffer buf_orig = buf; + if (!c->c2.pulled_options_digest_init_done) + { +- md_ctx_init(&c->c2.pulled_options_state, md_kt_get("SHA256")); ++ c->c2.pulled_options_state = md_ctx_new(); ++ md_ctx_init(c->c2.pulled_options_state, md_kt_get("SHA256")); + c->c2.pulled_options_digest_init_done = true; + } + if (!c->c2.did_pre_pull_restore) +@@ -737,14 +738,16 @@ process_incoming_push_msg(struct context *c, + option_types_found, + c->c2.es)) + { +- push_update_digest(&c->c2.pulled_options_state, &buf_orig, ++ push_update_digest(c->c2.pulled_options_state, &buf_orig, + &c->options); + switch (c->options.push_continuation) + { + case 0: + case 1: +- md_ctx_final(&c->c2.pulled_options_state, c->c2.pulled_options_digest.digest); +- md_ctx_cleanup(&c->c2.pulled_options_state); ++ md_ctx_final(c->c2.pulled_options_state, c->c2.pulled_options_digest.digest); ++ md_ctx_cleanup(c->c2.pulled_options_state); ++ md_ctx_free(c->c2.pulled_options_state); ++ c->c2.pulled_options_state = NULL; + c->c2.pulled_options_digest_init_done = false; + ret = PUSH_MSG_REPLY; + break; +From 6cbd48a3ead23f004f25943d067fa668efdc580e Mon Sep 17 00:00:00 2001 +From: Emmanuel Deloget <log...@free.fr> +Date: Mon, 12 Jun 2017 15:43:28 +0200 +Subject: [PATCH 7/8] OpenSSL: don't use direct access to the internal of + EVP_CIPHER_CTX + +OpenSSL 1.1 does not allow us to directly access the internal of +any data type, including EVP_CIPHER_CTX. We have to use the defined +functions to do so. + +Compatibility with OpenSSL 1.0 is kept by defining the corresponding +functions when they are not found in the library. + +Signed-off-by: Emmanuel Deloget <log...@free.fr> +Acked-by: Steffan Karger <steffan.kar...@fox-it.com> +Message-Id: <20170612134330.20971-7-log...@free.fr> +URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg14796.html +Signed-off-by: Gert Doering <g...@greenie.muc.de> +--- + configure.ac | 2 ++ + src/openvpn/crypto.c | 4 ++-- + src/openvpn/crypto_backend.h | 14 ++++++++++++++ + src/openvpn/crypto_mbedtls.c | 13 +++++++++++++ + src/openvpn/crypto_openssl.c | 15 +++++++++++++-- + src/openvpn/openssl_compat.h | 28 ++++++++++++++++++++++++++++ + 6 files changed, 72 insertions(+), 4 deletions(-) + +diff --git a/configure.ac b/configure.ac +index f971e54a..07fc3392 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -919,6 +919,8 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then + + AC_CHECK_FUNCS( + [ \ ++ EVP_CIPHER_CTX_new \ ++ EVP_CIPHER_CTX_free \ + EVP_MD_CTX_new \ + EVP_MD_CTX_free \ + EVP_MD_CTX_reset \ +diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c +index b6d0d550..f7c4d60a 100644 +--- a/src/openvpn/crypto.c ++++ b/src/openvpn/crypto.c +@@ -829,7 +829,7 @@ init_key_ctx(struct key_ctx *ctx, struct key *key, + if (kt->cipher && kt->cipher_length > 0) + { + +- ALLOC_OBJ(ctx->cipher, cipher_ctx_t); ++ ctx->cipher = cipher_ctx_new(); + cipher_ctx_init(ctx->cipher, key->cipher, kt->cipher_length, + kt->cipher, enc); + +@@ -878,7 +878,7 @@ free_key_ctx(struct key_ctx *ctx) + if (ctx->cipher) + { + cipher_ctx_cleanup(ctx->cipher); +- free(ctx->cipher); ++ cipher_ctx_free(ctx->cipher); + ctx->cipher = NULL; + } + if (ctx->hmac) +diff --git a/src/openvpn/crypto_backend.h b/src/openvpn/crypto_backend.h +index f1da0432..9679ee9b 100644 +--- a/src/openvpn/crypto_backend.h ++++ b/src/openvpn/crypto_backend.h +@@ -300,6 +300,20 @@ bool cipher_kt_mode_aead(const cipher_kt_t *cipher); + */ + + /** ++ * Allocate a new cipher context ++ * ++ * @return a new cipher context ++ */ ++cipher_ctx_t *cipher_ctx_new(void); ++ ++/** ++ * Free a cipher context ++ * ++ * @param ctx Cipher context. ++ */ ++void cipher_ctx_free(cipher_ctx_t *ctx); ++ ++/** + * Initialise a cipher context, based on the given key and key type. + * + * @param ctx Cipher context. May not be NULL +diff --git a/src/openvpn/crypto_mbedtls.c b/src/openvpn/crypto_mbedtls.c +index 03cc1308..5f16a1f0 100644 +--- a/src/openvpn/crypto_mbedtls.c ++++ b/src/openvpn/crypto_mbedtls.c +@@ -508,6 +508,19 @@ cipher_kt_mode_aead(const cipher_kt_t *cipher) + * + */ + ++mbedtls_cipher_context_t * ++cipher_ctx_new(void) ++{ ++ mbedtls_cipher_context_t *ctx; ++ ALLOC_OBJ(ctx, mbedtls_cipher_context_t); ++ return ctx; ++} ++ ++void ++cipher_ctx_free(mbedtls_cipher_context_t *ctx) ++{ ++ free(ctx); ++} + + void + cipher_ctx_init(mbedtls_cipher_context_t *ctx, uint8_t *key, int key_len, +diff --git a/src/openvpn/crypto_openssl.c b/src/openvpn/crypto_openssl.c +index 3a5a26f8..f4470fc0 100644 +--- a/src/openvpn/crypto_openssl.c ++++ b/src/openvpn/crypto_openssl.c +@@ -650,6 +650,19 @@ cipher_kt_mode_aead(const cipher_kt_t *cipher) + * + */ + ++cipher_ctx_t * ++cipher_ctx_new(void) ++{ ++ EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); ++ check_malloc_return(ctx); ++ return ctx; ++} ++ ++void ++cipher_ctx_free(EVP_CIPHER_CTX *ctx) ++{ ++ EVP_CIPHER_CTX_free(ctx); ++} + + void + cipher_ctx_init(EVP_CIPHER_CTX *ctx, uint8_t *key, int key_len, +@@ -657,8 +670,6 @@ cipher_ctx_init(EVP_CIPHER_CTX *ctx, uint8_t *key, int key_len, + { + ASSERT(NULL != kt && NULL != ctx); + +- CLEAR(*ctx); +- + EVP_CIPHER_CTX_init(ctx); + if (!EVP_CipherInit(ctx, kt, NULL, NULL, enc)) + { +diff --git a/src/openvpn/openssl_compat.h b/src/openvpn/openssl_compat.h +index 3d8fad10..c9e2692b 100644 +--- a/src/openvpn/openssl_compat.h ++++ b/src/openvpn/openssl_compat.h +@@ -88,6 +88,34 @@ EVP_MD_CTX_new(void) + } + #endif + ++#if !defined(HAVE_EVP_CIPHER_CTX_FREE) ++/** ++ * Free an existing cipher context ++ * ++ * @param ctx The cipher context ++ */ ++static inline void ++EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *c) ++{ ++ free(c); ++} ++#endif ++ ++#if !defined(HAVE_EVP_CIPHER_CTX_NEW) ++/** ++ * Allocate a new cipher context object ++ * ++ * @return A zero'ed cipher context object ++ */ ++static inline EVP_CIPHER_CTX * ++EVP_CIPHER_CTX_new(void) ++{ ++ EVP_CIPHER_CTX *ctx = NULL; ++ ALLOC_OBJ_CLEAR(ctx, EVP_CIPHER_CTX); ++ return ctx; ++} ++#endif ++ + #if !defined(HAVE_SSL_CTX_GET_DEFAULT_PASSWD_CB_USERDATA) + /** + * Fetch the default password callback user data from the SSL context +From aba98e9050eb54d72d921e70bcd422cb892b9c6c Mon Sep 17 00:00:00 2001 +From: Emmanuel Deloget <log...@free.fr> +Date: Mon, 12 Jun 2017 15:43:29 +0200 +Subject: [PATCH 8/8] OpenSSL: don't use direct access to the internal of + HMAC_CTX + +OpenSSL 1.1 does not allow us to directly access the internal of +any data type, including HMAC_CTX. We have to use the defined +functions to do so. + +Compatibility with OpenSSL 1.0 is kept by defining the corresponding +functions when they are not found in the library. + +Signed-off-by: Emmanuel Deloget <log...@free.fr> +Acked-by: Steffan Karger <steffan.kar...@fox-it.com> +Message-Id: <20170612134330.20971-8-log...@free.fr> +URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg14797.html +Signed-off-by: Gert Doering <g...@greenie.muc.de> +--- + configure.ac | 4 +++ + src/openvpn/crypto.c | 4 +-- + src/openvpn/crypto_backend.h | 14 ++++++++++ + src/openvpn/crypto_mbedtls.c | 15 ++++++++++ + src/openvpn/crypto_openssl.c | 17 ++++++++++-- + src/openvpn/ntlm.c | 12 ++++---- + src/openvpn/openssl_compat.h | 65 ++++++++++++++++++++++++++++++++++++++++++++ + src/openvpn/ssl.c | 38 ++++++++++++++------------ + 8 files changed, 140 insertions(+), 29 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 07fc3392..56ce5f82 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -921,6 +921,10 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then + [ \ + EVP_CIPHER_CTX_new \ + EVP_CIPHER_CTX_free \ ++ HMAC_CTX_new \ ++ HMAC_CTX_free \ ++ HMAC_CTX_reset \ ++ HMAC_CTX_init \ + EVP_MD_CTX_new \ + EVP_MD_CTX_free \ + EVP_MD_CTX_reset \ +diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c +index f7c4d60a..191fee8e 100644 +--- a/src/openvpn/crypto.c ++++ b/src/openvpn/crypto.c +@@ -853,7 +853,7 @@ init_key_ctx(struct key_ctx *ctx, struct key *key, + } + if (kt->digest && kt->hmac_length > 0) + { +- ALLOC_OBJ(ctx->hmac, hmac_ctx_t); ++ ctx->hmac = hmac_ctx_new(); + hmac_ctx_init(ctx->hmac, key->hmac, kt->hmac_length, kt->digest); + + msg(D_HANDSHAKE, +@@ -884,7 +884,7 @@ free_key_ctx(struct key_ctx *ctx) + if (ctx->hmac) + { + hmac_ctx_cleanup(ctx->hmac); +- free(ctx->hmac); ++ hmac_ctx_free(ctx->hmac); + ctx->hmac = NULL; + } + ctx->implicit_iv_len = 0; +diff --git a/src/openvpn/crypto_backend.h b/src/openvpn/crypto_backend.h +index 9679ee9b..b7f519b5 100644 +--- a/src/openvpn/crypto_backend.h ++++ b/src/openvpn/crypto_backend.h +@@ -583,6 +583,20 @@ void md_ctx_final(md_ctx_t *ctx, uint8_t *dst); + */ + + /* ++ * Create a new HMAC context ++ * ++ * @return A new HMAC context ++ */ ++hmac_ctx_t *hmac_ctx_new(void); ++ ++/* ++ * Free an existing HMAC context ++ * ++ * @param ctx HMAC context to free ++ */ ++void hmac_ctx_free(hmac_ctx_t *ctx); ++ ++/* + * Initialises the given HMAC context, using the given digest + * and key. + * +diff --git a/src/openvpn/crypto_mbedtls.c b/src/openvpn/crypto_mbedtls.c +index 5f16a1f0..24bc3158 100644 +--- a/src/openvpn/crypto_mbedtls.c ++++ b/src/openvpn/crypto_mbedtls.c +@@ -840,6 +840,21 @@ md_ctx_final(mbedtls_md_context_t *ctx, uint8_t *dst) + /* + * TODO: re-enable dmsg for crypto debug + */ ++ ++mbedtls_md_context_t * ++hmac_ctx_new(void) ++{ ++ mbedtls_md_context_t *ctx; ++ ALLOC_OBJ(ctx, mbedtls_md_context_t); ++ return ctx; ++} ++ ++void ++hmac_ctx_free(mbedtls_md_context_t *ctx) ++{ ++ free(ctx); ++} ++ + void + hmac_ctx_init(mbedtls_md_context_t *ctx, const uint8_t *key, int key_len, + const mbedtls_md_info_t *kt) +diff --git a/src/openvpn/crypto_openssl.c b/src/openvpn/crypto_openssl.c +index f4470fc0..a55e65c1 100644 +--- a/src/openvpn/crypto_openssl.c ++++ b/src/openvpn/crypto_openssl.c +@@ -910,6 +910,19 @@ md_ctx_final(EVP_MD_CTX *ctx, uint8_t *dst) + * + */ + ++HMAC_CTX * ++hmac_ctx_new(void) ++{ ++ HMAC_CTX *ctx = HMAC_CTX_new(); ++ check_malloc_return(ctx); ++ return ctx; ++} ++ ++void ++hmac_ctx_free(HMAC_CTX *ctx) ++{ ++ HMAC_CTX_free(ctx); ++} + + void + hmac_ctx_init(HMAC_CTX *ctx, const uint8_t *key, int key_len, +@@ -917,8 +930,6 @@ hmac_ctx_init(HMAC_CTX *ctx, const uint8_t *key, int key_len, + { + ASSERT(NULL != kt && NULL != ctx); + +- CLEAR(*ctx); +- + HMAC_CTX_init(ctx); + HMAC_Init_ex(ctx, key, key_len, kt, NULL); + +@@ -929,7 +940,7 @@ hmac_ctx_init(HMAC_CTX *ctx, const uint8_t *key, int key_len, + void + hmac_ctx_cleanup(HMAC_CTX *ctx) + { +- HMAC_CTX_cleanup(ctx); ++ HMAC_CTX_reset(ctx); + } + + int +diff --git a/src/openvpn/ntlm.c b/src/openvpn/ntlm.c +index 69b7d426..16d60d2c 100644 +--- a/src/openvpn/ntlm.c ++++ b/src/openvpn/ntlm.c +@@ -85,13 +85,13 @@ static void + gen_hmac_md5(const char *data, int data_len, const char *key, int key_len,char *result) + { + const md_kt_t *md5_kt = md_kt_get("MD5"); +- hmac_ctx_t hmac_ctx; +- CLEAR(hmac_ctx); ++ hmac_ctx_t *hmac_ctx = hmac_ctx_new(); + +- hmac_ctx_init(&hmac_ctx, key, key_len, md5_kt); +- hmac_ctx_update(&hmac_ctx, (const unsigned char *)data, data_len); +- hmac_ctx_final(&hmac_ctx, (unsigned char *)result); +- hmac_ctx_cleanup(&hmac_ctx); ++ hmac_ctx_init(hmac_ctx, key, key_len, md5_kt); ++ hmac_ctx_update(hmac_ctx, (const unsigned char *)data, data_len); ++ hmac_ctx_final(hmac_ctx, (unsigned char *)result); ++ hmac_ctx_cleanup(hmac_ctx); ++ hmac_ctx_free(hmac_ctx); + } + + static void +diff --git a/src/openvpn/openssl_compat.h b/src/openvpn/openssl_compat.h +index c9e2692b..c765f0bb 100644 +--- a/src/openvpn/openssl_compat.h ++++ b/src/openvpn/openssl_compat.h +@@ -116,6 +116,71 @@ EVP_CIPHER_CTX_new(void) + } + #endif + ++#if !defined(HAVE_HMAC_CTX_RESET) ++/** ++ * Reset a HMAC context ++ * ++ * @param ctx The HMAC context ++ * @return 1 on success, 0 on error ++ */ ++static inline int ++HMAC_CTX_reset(HMAC_CTX *ctx) ++{ ++ HMAC_CTX_cleanup(ctx); ++ return 1; ++} ++#endif ++ ++#if !defined(HAVE_HMAC_CTX_INIT) ++/** ++ * Init a HMAC context ++ * ++ * @param ctx The HMAC context ++ * ++ * Contrary to many functions in this file, HMAC_CTX_init() is not ++ * an OpenSSL 1.1 function: it comes from previous versions and was ++ * removed in v1.1. As a consequence, there is no distincting in ++ * v1.1 between a cleanup, and init and a reset. Yet, previous OpenSSL ++ * version need this distinction. ++ * ++ * In order to respect previous OpenSSL versions, we implement init ++ * as reset for OpenSSL 1.1+. ++ */ ++static inline void ++HMAC_CTX_init(HMAC_CTX *ctx) ++{ ++ HMAC_CTX_reset(ctx); ++} ++#endif ++ ++#if !defined(HAVE_HMAC_CTX_FREE) ++/** ++ * Free an existing HMAC context ++ * ++ * @param ctx The HMAC context ++ */ ++static inline void ++HMAC_CTX_free(HMAC_CTX *c) ++{ ++ free(c); ++} ++#endif ++ ++#if !defined(HAVE_HMAC_CTX_NEW) ++/** ++ * Allocate a new HMAC context object ++ * ++ * @return A zero'ed HMAC context object ++ */ ++static inline HMAC_CTX * ++HMAC_CTX_new(void) ++{ ++ HMAC_CTX *ctx = NULL; ++ ALLOC_OBJ_CLEAR(ctx, HMAC_CTX); ++ return ctx; ++} ++#endif ++ + #if !defined(HAVE_SSL_CTX_GET_DEFAULT_PASSWD_CB_USERDATA) + /** + * Fetch the default password callback user data from the SSL context +diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c +index cc7b1830..c658f377 100644 +--- a/src/openvpn/ssl.c ++++ b/src/openvpn/ssl.c +@@ -1606,8 +1606,8 @@ tls1_P_hash(const md_kt_t *md_kt, + { + struct gc_arena gc = gc_new(); + int chunk; +- hmac_ctx_t ctx; +- hmac_ctx_t ctx_tmp; ++ hmac_ctx_t *ctx; ++ hmac_ctx_t *ctx_tmp; + uint8_t A1[MAX_HMAC_KEY_LENGTH]; + unsigned int A1_len; + +@@ -1616,8 +1616,8 @@ tls1_P_hash(const md_kt_t *md_kt, + const uint8_t *out_orig = out; + #endif + +- CLEAR(ctx); +- CLEAR(ctx_tmp); ++ ctx = hmac_ctx_new(); ++ ctx_tmp = hmac_ctx_new(); + + dmsg(D_SHOW_KEY_SOURCE, "tls1_P_hash sec: %s", format_hex(sec, sec_len, 0, &gc)); + dmsg(D_SHOW_KEY_SOURCE, "tls1_P_hash seed: %s", format_hex(seed, seed_len, 0, &gc)); +@@ -1625,36 +1625,38 @@ tls1_P_hash(const md_kt_t *md_kt, + chunk = md_kt_size(md_kt); + A1_len = md_kt_size(md_kt); + +- hmac_ctx_init(&ctx, sec, sec_len, md_kt); +- hmac_ctx_init(&ctx_tmp, sec, sec_len, md_kt); ++ hmac_ctx_init(ctx, sec, sec_len, md_kt); ++ hmac_ctx_init(ctx_tmp, sec, sec_len, md_kt); + +- hmac_ctx_update(&ctx,seed,seed_len); +- hmac_ctx_final(&ctx, A1); ++ hmac_ctx_update(ctx,seed,seed_len); ++ hmac_ctx_final(ctx, A1); + + for (;; ) + { +- hmac_ctx_reset(&ctx); +- hmac_ctx_reset(&ctx_tmp); +- hmac_ctx_update(&ctx,A1,A1_len); +- hmac_ctx_update(&ctx_tmp,A1,A1_len); +- hmac_ctx_update(&ctx,seed,seed_len); ++ hmac_ctx_reset(ctx); ++ hmac_ctx_reset(ctx_tmp); ++ hmac_ctx_update(ctx,A1,A1_len); ++ hmac_ctx_update(ctx_tmp,A1,A1_len); ++ hmac_ctx_update(ctx,seed,seed_len); + + if (olen > chunk) + { +- hmac_ctx_final(&ctx, out); ++ hmac_ctx_final(ctx, out); + out += chunk; + olen -= chunk; +- hmac_ctx_final(&ctx_tmp, A1); /* calc the next A1 value */ ++ hmac_ctx_final(ctx_tmp, A1); /* calc the next A1 value */ + } + else /* last one */ + { +- hmac_ctx_final(&ctx, A1); ++ hmac_ctx_final(ctx, A1); + memcpy(out,A1,olen); + break; + } + } +- hmac_ctx_cleanup(&ctx); +- hmac_ctx_cleanup(&ctx_tmp); ++ hmac_ctx_cleanup(ctx); ++ hmac_ctx_free(ctx); ++ hmac_ctx_cleanup(ctx_tmp); ++ hmac_ctx_free(ctx_tmp); + secure_memzero(A1, sizeof(A1)); + + dmsg(D_SHOW_KEY_SOURCE, "tls1_P_hash out: %s", format_hex(out_orig, olen_orig, 0, &gc)); Copied: openvpn/repos/testing-i686/PKGBUILD (from rev 298959, openvpn/trunk/PKGBUILD) =================================================================== --- testing-i686/PKGBUILD (rev 0) +++ testing-i686/PKGBUILD 2017-06-18 19:30:55 UTC (rev 298960) @@ -0,0 +1,78 @@ +# $Id$ +# Maintainer: Christian Hesse <m...@eworm.de> + +pkgname=openvpn +pkgver=2.4.2 +pkgrel=2 +pkgdesc='An easy-to-use, robust and highly configurable VPN (Virtual Private Network)' +arch=('i686' 'x86_64') +url='http://openvpn.net/index.php/open-source.html' +depends=('openssl' 'lzo' 'iproute2' 'libsystemd' 'pkcs11-helper') +optdepends=('easy-rsa: easy CA and certificate handling') +makedepends=('systemd') +license=('custom') +install=openvpn.install +validpgpkeys=('6D04F8F1B0173111F499795E29584D9F40864578' # Samuli Seppänen <sam...@openvpn.net> + '7ACD56B74144925C6214329757DB9DAB613B8DA1') # David Sommerseth (OpenVPN Technologies, Inc) <dav...@openvpn.net> +source=("https://swupdate.openvpn.net/community/releases/openvpn-${pkgver}.tar.xz"{,.asc} + '0004-openssl-1-1-0.patch') +sha256sums=('df5c4f384b7df6b08a2f6fa8a84b9fd382baf59c2cef1836f82e2a7f62f1bff9' + 'SKIP' + '75259cb14ed8237c2ca5618eca902ed39f720df166e732911e21dd5abcc68b3e') + +prepare() { + cd "${srcdir}"/${pkgname}-${pkgver} + + # allow to build against openssl 1.1.0 + patch -Np1 < "${srcdir}"/0004-openssl-1-1-0.patch + + # regenerate configure script + autoreconf -fi +} + +build() { + cd "${srcdir}"/${pkgname}-${pkgver} + + ./configure \ + --prefix=/usr \ + --sbindir=/usr/bin \ + --enable-iproute2 \ + --enable-pkcs11 \ + --enable-plugins \ + --enable-systemd \ + --enable-x509-alt-username + make +} + +check() { + cd "${srcdir}"/${pkgname}-${pkgver} + + make check +} + +package() { + cd "${srcdir}"/${pkgname}-${pkgver} + + # Install openvpn + make DESTDIR="${pkgdir}" install + + # Create empty configuration directories + install -d -m0750 -g 90 "${pkgdir}"/etc/openvpn/{client,server} + + # Install examples + install -d -m0755 "${pkgdir}"/usr/share/openvpn + cp -r sample/sample-config-files "${pkgdir}"/usr/share/openvpn/examples + + # Install license + install -d -m0755 "${pkgdir}"/usr/share/licenses/openvpn/ + ln -sf /usr/share/doc/openvpn/{COPYING,COPYRIGHT.GPL} "${pkgdir}"/usr/share/licenses/openvpn/ + + # Install contrib + for FILE in $(find contrib -type f); do + case "$(file --brief --mime-type "${FILE}")" in + "text/x-shellscript") install -D -m0755 "${FILE}" "${pkgdir}/usr/share/openvpn/${FILE}" ;; + *) install -D -m0644 "${FILE}" "${pkgdir}/usr/share/openvpn/${FILE}" ;; + esac + done +} + Copied: openvpn/repos/testing-i686/openvpn.install (from rev 298959, openvpn/trunk/openvpn.install) =================================================================== --- testing-i686/openvpn.install (rev 0) +++ testing-i686/openvpn.install 2017-06-18 19:30:55 UTC (rev 298960) @@ -0,0 +1,24 @@ +#!/bin/sh + +post_upgrade() { + # return if old package version greater 2.4... + (( $(vercmp $2 '2.4') > 0 )) && return + + # upgrade from pre-2.4 version... + echo "This upgrade from openvpn $2 to openvpn $1 made changes that require" + echo "administrative interaction:" + echo " -> Configuration is expected in sub directories now. Move your files" + echo " from /etc/openvpn/ to /etc/openvpn/server/ or /etc/openvpn/client/." + echo " -> The plugin lookup path changed, remove extra 'plugins/' from relative paths." + echo " -> The systemd unit openvpn@.service was replaced with openvpn-client@.service" + echo " and openvpn-server@.service. Restart and reenable accordingly." + + local UNITS="$(systemctl list-units --quiet --no-pager --no-legend --plain | grep '^openvpn@' | cut -d' ' -f1)" + if (( ${#UNITS} )); then + echo "This is a (possibly incomplete) list of units that need to be acted on:" + for UNIT in ${UNITS}; do + echo " -> ${UNIT}" + done + fi +} + Copied: openvpn/repos/testing-x86_64/0004-openssl-1-1-0.patch (from rev 298959, openvpn/trunk/0004-openssl-1-1-0.patch) =================================================================== --- testing-x86_64/0004-openssl-1-1-0.patch (rev 0) +++ testing-x86_64/0004-openssl-1-1-0.patch 2017-06-18 19:30:55 UTC (rev 298960) @@ -0,0 +1,1614 @@ +From 17d1ab90c228b1efbe774357bd3265b2af006899 Mon Sep 17 00:00:00 2001 +From: Emmanuel Deloget <log...@free.fr> +Date: Mon, 12 Jun 2017 15:43:23 +0200 +Subject: [PATCH 1/8] OpenSSL: don't use direct access to the internal of + X509 + +OpenSSL 1.1 does not allow us to directly access the internal of +any data type, including X509. We have to use the defined +functions to do so. + +In x509_verify_ns_cert_type() in particular, this means that we +cannot directly check for the extended flags to find whether the +certificate should be used as a client or as a server certificate. +We need to leverage the X509_check_purpose() API yet this API is +far stricter than the currently implemented check. So far, I have +not been able to find a situation where this stricter test fails +(although I must admit that I haven't tested that very well). + +We double-check the certificate purpose using "direct access" to the +internal of the certificate object (of course, this is not a real +direct access, but we still fetch ASN1 strings within the X509 object +and we check the internal value of these strings). This allow us to +warn the user if there is a discrepancy between the X509_check_purpose() +return value and our internal, less strict check. + +We use these changes to make peer_cert a non-const parameter to +x509_verify_ns_cert_type(). The underlying library waits for a +non-const pointer, and forcing it to be a const pointer does not make +much sense (please note that this has an effect on the mbedtls part +too). + +Compatibility with OpenSSL 1.0 is kept by defining the corresponding +functions when they are not found in the library. + +Signed-off-by: Emmanuel Deloget <log...@free.fr> +Acked-by: Steffan Karger <steffan.kar...@fox-it.com> +Message-Id: <20170612134330.20971-2-log...@free.fr> +URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg14792.html +Signed-off-by: Gert Doering <g...@greenie.muc.de> +--- + configure.ac | 1 + + src/openvpn/openssl_compat.h | 15 +++++++++ + src/openvpn/ssl_openssl.c | 3 +- + src/openvpn/ssl_verify_backend.h | 2 +- + src/openvpn/ssl_verify_mbedtls.c | 2 +- + src/openvpn/ssl_verify_openssl.c | 68 ++++++++++++++++++++++++++++++++++------ + 6 files changed, 78 insertions(+), 13 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 334247df..c30bf3d5 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -921,6 +921,7 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then + [ \ + SSL_CTX_get_default_passwd_cb \ + SSL_CTX_get_default_passwd_cb_userdata \ ++ X509_get0_pubkey \ + X509_STORE_get0_objects \ + X509_OBJECT_free \ + X509_OBJECT_get_type \ +diff --git a/src/openvpn/openssl_compat.h b/src/openvpn/openssl_compat.h +index 811d559c..612bfa56 100644 +--- a/src/openvpn/openssl_compat.h ++++ b/src/openvpn/openssl_compat.h +@@ -73,6 +73,21 @@ SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx) + } + #endif + ++#if !defined(HAVE_X509_GET0_PUBKEY) ++/** ++ * Get the public key from a X509 certificate ++ * ++ * @param x X509 certificate ++ * @return The certificate public key ++ */ ++static inline EVP_PKEY * ++X509_get0_pubkey(const X509 *x) ++{ ++ return (x && x->cert_info && x->cert_info->key) ? ++ x->cert_info->key->pkey : NULL; ++} ++#endif ++ + #if !defined(HAVE_X509_STORE_GET0_OBJECTS) + /** + * Fetch the X509 object stack from the X509 store +diff --git a/src/openvpn/ssl_openssl.c b/src/openvpn/ssl_openssl.c +index 1fa46e18..89c3b014 100644 +--- a/src/openvpn/ssl_openssl.c ++++ b/src/openvpn/ssl_openssl.c +@@ -1070,7 +1070,8 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx, + } + + /* get the public key */ +- ASSERT(cert->cert_info->key->pkey); /* NULL before SSL_CTX_use_certificate() is called */ ++ EVP_PKEY *pkey = X509_get0_pubkey(cert); ++ ASSERT(pkey); /* NULL before SSL_CTX_use_certificate() is called */ + pub_rsa = cert->cert_info->key->pkey->pkey.rsa; + + /* initialize RSA object */ +diff --git a/src/openvpn/ssl_verify_backend.h b/src/openvpn/ssl_verify_backend.h +index 35660532..978e54fd 100644 +--- a/src/openvpn/ssl_verify_backend.h ++++ b/src/openvpn/ssl_verify_backend.h +@@ -210,7 +210,7 @@ void x509_setenv_track(const struct x509_track *xt, struct env_set *es, + * the expected bit set. \c FAILURE if the certificate does + * not have NS cert type verification or the wrong bit set. + */ +-result_t x509_verify_ns_cert_type(const openvpn_x509_cert_t *cert, const int usage); ++result_t x509_verify_ns_cert_type(openvpn_x509_cert_t *cert, const int usage); + + /* + * Verify X.509 key usage extension field. +diff --git a/src/openvpn/ssl_verify_mbedtls.c b/src/openvpn/ssl_verify_mbedtls.c +index d80b7a53..27c5c3e1 100644 +--- a/src/openvpn/ssl_verify_mbedtls.c ++++ b/src/openvpn/ssl_verify_mbedtls.c +@@ -410,7 +410,7 @@ x509_setenv(struct env_set *es, int cert_depth, mbedtls_x509_crt *cert) + } + + result_t +-x509_verify_ns_cert_type(const mbedtls_x509_crt *cert, const int usage) ++x509_verify_ns_cert_type(mbedtls_x509_crt *cert, const int usage) + { + if (usage == NS_CERT_CHECK_NONE) + { +diff --git a/src/openvpn/ssl_verify_openssl.c b/src/openvpn/ssl_verify_openssl.c +index 5d897b6d..31c16389 100644 +--- a/src/openvpn/ssl_verify_openssl.c ++++ b/src/openvpn/ssl_verify_openssl.c +@@ -293,18 +293,20 @@ backend_x509_get_serial_hex(openvpn_x509_cert_t *cert, struct gc_arena *gc) + struct buffer + x509_get_sha1_fingerprint(X509 *cert, struct gc_arena *gc) + { +- struct buffer hash = alloc_buf_gc(sizeof(cert->sha1_hash), gc); +- memcpy(BPTR(&hash), cert->sha1_hash, sizeof(cert->sha1_hash)); +- ASSERT(buf_inc_len(&hash, sizeof(cert->sha1_hash))); ++ const EVP_MD *sha1 = EVP_sha1(); ++ struct buffer hash = alloc_buf_gc(EVP_MD_size(sha1), gc); ++ X509_digest(cert, EVP_sha1(), BPTR(&hash), NULL); ++ ASSERT(buf_inc_len(&hash, EVP_MD_size(sha1))); + return hash; + } + + struct buffer + x509_get_sha256_fingerprint(X509 *cert, struct gc_arena *gc) + { +- struct buffer hash = alloc_buf_gc((EVP_sha256())->md_size, gc); ++ const EVP_MD *sha256 = EVP_sha256(); ++ struct buffer hash = alloc_buf_gc(EVP_MD_size(sha256), gc); + X509_digest(cert, EVP_sha256(), BPTR(&hash), NULL); +- ASSERT(buf_inc_len(&hash, (EVP_sha256())->md_size)); ++ ASSERT(buf_inc_len(&hash, EVP_MD_size(sha256))); + return hash; + } + +@@ -569,7 +571,7 @@ x509_setenv(struct env_set *es, int cert_depth, openvpn_x509_cert_t *peer_cert) + } + + result_t +-x509_verify_ns_cert_type(const openvpn_x509_cert_t *peer_cert, const int usage) ++x509_verify_ns_cert_type(openvpn_x509_cert_t *peer_cert, const int usage) + { + if (usage == NS_CERT_CHECK_NONE) + { +@@ -577,13 +579,59 @@ x509_verify_ns_cert_type(const openvpn_x509_cert_t *peer_cert, const int usage) + } + if (usage == NS_CERT_CHECK_CLIENT) + { +- return ((peer_cert->ex_flags & EXFLAG_NSCERT) +- && (peer_cert->ex_nscert & NS_SSL_CLIENT)) ? SUCCESS : FAILURE; ++ /* ++ * Unfortunately, X509_check_purpose() does some weird thing that ++ * prevent it to take a const argument ++ */ ++ result_t result = X509_check_purpose(peer_cert, X509_PURPOSE_SSL_CLIENT, 0) ? ++ SUCCESS : FAILURE; ++ ++ /* ++ * old versions of OpenSSL allow us to make the less strict check we used to ++ * do. If this less strict check pass, warn user that this might not be the ++ * case when its distribution will update to OpenSSL 1.1 ++ */ ++ if (result == FAILURE) ++ { ++ ASN1_BIT_STRING *ns; ++ ns = X509_get_ext_d2i(peer_cert, NID_netscape_cert_type, NULL, NULL); ++ result = (ns && ns->length > 0 && (ns->data[0] & NS_SSL_CLIENT)) ? SUCCESS : FAILURE; ++ if (result == SUCCESS) ++ { ++ msg(M_WARN, "X509: Certificate is a client certificate yet it's purpose " ++ "cannot be verified (check may fail in the future)"); ++ } ++ ASN1_BIT_STRING_free(ns); ++ } ++ return result; + } + if (usage == NS_CERT_CHECK_SERVER) + { +- return ((peer_cert->ex_flags & EXFLAG_NSCERT) +- && (peer_cert->ex_nscert & NS_SSL_SERVER)) ? SUCCESS : FAILURE; ++ /* ++ * Unfortunately, X509_check_purpose() does some weird thing that ++ * prevent it to take a const argument ++ */ ++ result_t result = X509_check_purpose(peer_cert, X509_PURPOSE_SSL_SERVER, 0) ? ++ SUCCESS : FAILURE; ++ ++ /* ++ * old versions of OpenSSL allow us to make the less strict check we used to ++ * do. If this less strict check pass, warn user that this might not be the ++ * case when its distribution will update to OpenSSL 1.1 ++ */ ++ if (result == FAILURE) ++ { ++ ASN1_BIT_STRING *ns; ++ ns = X509_get_ext_d2i(peer_cert, NID_netscape_cert_type, NULL, NULL); ++ result = (ns && ns->length > 0 && (ns->data[0] & NS_SSL_SERVER)) ? SUCCESS : FAILURE; ++ if (result == SUCCESS) ++ { ++ msg(M_WARN, "X509: Certificate is a server certificate yet it's purpose " ++ "cannot be verified (check may fail in the future)"); ++ } ++ ASN1_BIT_STRING_free(ns); ++ } ++ return result; + } + + return FAILURE; +From b8ca5bc3593e539d0735a74b55ed41a792e55033 Mon Sep 17 00:00:00 2001 +From: Emmanuel Deloget <log...@free.fr> +Date: Mon, 12 Jun 2017 15:43:24 +0200 +Subject: [PATCH 2/8] OpenSSL: don't use direct access to the internal of + EVP_PKEY + +OpenSSL 1.1 does not allow us to directly access the internal of +any data type, including EVP_PKEY. We have to use the defined +functions to do so. + +Compatibility with OpenSSL 1.0 is kept by defining the corresponding +functions when they are not found in the library. + +Signed-off-by: Emmanuel Deloget <log...@free.fr> +Acked-by: Steffan Karger <steffan.kar...@fox-it.com> +Message-Id: <20170612134330.20971-3-log...@free.fr> +URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg14795.html +Signed-off-by: Gert Doering <g...@greenie.muc.de> +--- + configure.ac | 3 +++ + src/openvpn/openssl_compat.h | 42 ++++++++++++++++++++++++++++++++++++++++++ + src/openvpn/ssl_openssl.c | 6 +++--- + 3 files changed, 48 insertions(+), 3 deletions(-) + +diff --git a/configure.ac b/configure.ac +index c30bf3d5..43f332b2 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -925,6 +925,9 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then + X509_STORE_get0_objects \ + X509_OBJECT_free \ + X509_OBJECT_get_type \ ++ EVP_PKEY_id \ ++ EVP_PKEY_get0_RSA \ ++ EVP_PKEY_get0_DSA \ + RSA_meth_new \ + RSA_meth_free \ + RSA_meth_set_pub_enc \ +diff --git a/src/openvpn/openssl_compat.h b/src/openvpn/openssl_compat.h +index 612bfa56..60498595 100644 +--- a/src/openvpn/openssl_compat.h ++++ b/src/openvpn/openssl_compat.h +@@ -133,6 +133,48 @@ X509_OBJECT_get_type(const X509_OBJECT *obj) + } + #endif + ++#if !defined(HAVE_EVP_PKEY_GET0_RSA) ++/** ++ * Get the RSA object of a public key ++ * ++ * @param pkey Public key object ++ * @return The underlying RSA object ++ */ ++static inline RSA * ++EVP_PKEY_get0_RSA(EVP_PKEY *pkey) ++{ ++ return pkey ? pkey->pkey.rsa : NULL; ++} ++#endif ++ ++#if !defined(HAVE_EVP_PKEY_ID) ++/** ++ * Get the PKEY type ++ * ++ * @param pkey Public key object ++ * @return The key type ++ */ ++static inline int ++EVP_PKEY_id(const EVP_PKEY *pkey) ++{ ++ return pkey ? pkey->type : EVP_PKEY_NONE; ++} ++#endif ++ ++#if !defined(HAVE_EVP_PKEY_GET0_DSA) ++/** ++ * Get the DSA object of a public key ++ * ++ * @param pkey Public key object ++ * @return The underlying DSA object ++ */ ++static inline DSA * ++EVP_PKEY_get0_DSA(EVP_PKEY *pkey) ++{ ++ return pkey ? pkey->pkey.dsa : NULL; ++} ++#endif ++ + #if !defined(HAVE_RSA_METH_NEW) + /** + * Allocate a new RSA method object +diff --git a/src/openvpn/ssl_openssl.c b/src/openvpn/ssl_openssl.c +index 89c3b014..c84372d6 100644 +--- a/src/openvpn/ssl_openssl.c ++++ b/src/openvpn/ssl_openssl.c +@@ -1072,7 +1072,7 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx, + /* get the public key */ + EVP_PKEY *pkey = X509_get0_pubkey(cert); + ASSERT(pkey); /* NULL before SSL_CTX_use_certificate() is called */ +- pub_rsa = cert->cert_info->key->pkey->pkey.rsa; ++ pub_rsa = EVP_PKEY_get0_RSA(pkey); + + /* initialize RSA object */ + rsa->n = BN_dup(pub_rsa->n); +@@ -1677,13 +1677,13 @@ print_details(struct key_state_ssl *ks_ssl, const char *prefix) + EVP_PKEY *pkey = X509_get_pubkey(cert); + if (pkey != NULL) + { +- if (pkey->type == EVP_PKEY_RSA && pkey->pkey.rsa != NULL ++ if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA && EVP_PKEY_get0_RSA(pkey) != NULL + && pkey->pkey.rsa->n != NULL) + { + openvpn_snprintf(s2, sizeof(s2), ", %d bit RSA", + BN_num_bits(pkey->pkey.rsa->n)); + } +- else if (pkey->type == EVP_PKEY_DSA && pkey->pkey.dsa != NULL ++ else if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA && EVP_PKEY_get0_DSA(pkey) != NULL + && pkey->pkey.dsa->p != NULL) + { + openvpn_snprintf(s2, sizeof(s2), ", %d bit DSA", +From f7780af6f1aaffcbbfb8b4dde0f2af052f84b28a Mon Sep 17 00:00:00 2001 +From: Emmanuel Deloget <log...@free.fr> +Date: Mon, 12 Jun 2017 15:43:25 +0200 +Subject: [PATCH 3/8] OpenSSL: don't use direct access to the internal of RSA + +OpenSSL 1.1 does not allow us to directly access the internal of +any data type, including RSA. We have to use the defined +functions to do so. + +Compatibility with OpenSSL 1.0 is kept by defining the corresponding +functions when they are not found in the library. + +Signed-off-by: Emmanuel Deloget <log...@free.fr> +Acked-by: Steffan Karger <steffan.kar...@fox-it.com> +Message-Id: <20170612134330.20971-4-log...@free.fr> +URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg14790.html +Signed-off-by: Gert Doering <g...@greenie.muc.de> +--- + configure.ac | 4 ++ + src/openvpn/openssl_compat.h | 100 +++++++++++++++++++++++++++++++++++++++++++ + src/openvpn/ssl_openssl.c | 24 +++++++---- + 3 files changed, 119 insertions(+), 9 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 43f332b2..e9ac5a6e 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -928,6 +928,10 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then + EVP_PKEY_id \ + EVP_PKEY_get0_RSA \ + EVP_PKEY_get0_DSA \ ++ RSA_set_flags \ ++ RSA_bits \ ++ RSA_get0_key \ ++ RSA_set0_key \ + RSA_meth_new \ + RSA_meth_free \ + RSA_meth_set_pub_enc \ +diff --git a/src/openvpn/openssl_compat.h b/src/openvpn/openssl_compat.h +index 60498595..e3f20b73 100644 +--- a/src/openvpn/openssl_compat.h ++++ b/src/openvpn/openssl_compat.h +@@ -175,6 +175,106 @@ EVP_PKEY_get0_DSA(EVP_PKEY *pkey) + } + #endif + ++#if !defined(HAVE_RSA_SET_FLAGS) ++/** ++ * Set the RSA flags ++ * ++ * @param rsa The RSA object ++ * @param flags New flags value ++ */ ++static inline void ++RSA_set_flags(RSA *rsa, int flags) ++{ ++ if (rsa) ++ { ++ rsa->flags = flags; ++ } ++} ++#endif ++ ++#if !defined(HAVE_RSA_GET0_KEY) ++/** ++ * Get the RSA parameters ++ * ++ * @param rsa The RSA object ++ * @param n The @c n parameter ++ * @param e The @c e parameter ++ * @param d The @c d parameter ++ */ ++static inline void ++RSA_get0_key(const RSA *rsa, const BIGNUM **n, ++ const BIGNUM **e, const BIGNUM **d) ++{ ++ if (n != NULL) ++ { ++ *n = rsa ? rsa->n : NULL; ++ } ++ if (e != NULL) ++ { ++ *e = rsa ? rsa->e : NULL; ++ } ++ if (d != NULL) ++ { ++ *d = rsa ? rsa->d : NULL; ++ } ++} ++#endif ++ ++#if !defined(HAVE_RSA_SET0_KEY) ++/** ++ * Set the RSA parameters ++ * ++ * @param rsa The RSA object ++ * @param n The @c n parameter ++ * @param e The @c e parameter ++ * @param d The @c d parameter ++ * @return 1 on success, 0 on error ++ */ ++static inline int ++RSA_set0_key(RSA *rsa, BIGNUM *n, BIGNUM *e, BIGNUM *d) ++{ ++ if ((rsa->n == NULL && n == NULL) ++ || (rsa->e == NULL && e == NULL)) ++ { ++ return 0; ++ } ++ ++ if (n != NULL) ++ { ++ BN_free(rsa->n); ++ rsa->n = n; ++ } ++ if (e != NULL) ++ { ++ BN_free(rsa->e); ++ rsa->e = e; ++ } ++ if (d != NULL) ++ { ++ BN_free(rsa->d); ++ rsa->d = d; ++ } ++ ++ return 1; ++} ++#endif ++ ++#if !defined(HAVE_RSA_BITS) ++/** ++ * Number of significant RSA bits ++ * ++ * @param rsa The RSA object ; shall not be NULL ++ * @return The number of RSA bits or 0 on error ++ */ ++static inline int ++RSA_bits(const RSA *rsa) ++{ ++ const BIGNUM *n = NULL; ++ RSA_get0_key(rsa, &n, NULL, NULL); ++ return n ? BN_num_bits(n) : 0; ++} ++#endif ++ + #if !defined(HAVE_RSA_METH_NEW) + /** + * Allocate a new RSA method object +diff --git a/src/openvpn/ssl_openssl.c b/src/openvpn/ssl_openssl.c +index c84372d6..da801ed5 100644 +--- a/src/openvpn/ssl_openssl.c ++++ b/src/openvpn/ssl_openssl.c +@@ -973,10 +973,13 @@ rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, i + + /* called at RSA_free */ + static int +-rsa_finish(RSA *rsa) ++openvpn_extkey_rsa_finish(RSA *rsa) + { +- RSA_meth_free(rsa->meth); +- rsa->meth = NULL; ++ /* meth was allocated in tls_ctx_use_external_private_key() ; since ++ * this function is called when the parent RSA object is destroyed, ++ * it is no longer used after this point so kill it. */ ++ const RSA_METHOD *meth = RSA_get_method(rsa); ++ RSA_meth_free((RSA_METHOD *)meth); + return 1; + } + +@@ -1058,7 +1061,7 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx, + RSA_meth_set_priv_enc(rsa_meth, rsa_priv_enc); + RSA_meth_set_priv_dec(rsa_meth, rsa_priv_dec); + RSA_meth_set_init(rsa_meth, NULL); +- RSA_meth_set_finish(rsa_meth, rsa_finish); ++ RSA_meth_set_finish(rsa_meth, openvpn_extkey_rsa_finish); + RSA_meth_set0_app_data(rsa_meth, NULL); + + /* allocate RSA object */ +@@ -1075,8 +1078,11 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx, + pub_rsa = EVP_PKEY_get0_RSA(pkey); + + /* initialize RSA object */ +- rsa->n = BN_dup(pub_rsa->n); +- rsa->flags |= RSA_FLAG_EXT_PKEY; ++ const BIGNUM *n = NULL; ++ const BIGNUM *e = NULL; ++ RSA_get0_key(pub_rsa, &n, &e, NULL); ++ RSA_set0_key(rsa, BN_dup(n), BN_dup(e), NULL); ++ RSA_set_flags(rsa, RSA_flags(rsa) | RSA_FLAG_EXT_PKEY); + if (!RSA_set_method(rsa, rsa_meth)) + { + goto err; +@@ -1677,11 +1683,11 @@ print_details(struct key_state_ssl *ks_ssl, const char *prefix) + EVP_PKEY *pkey = X509_get_pubkey(cert); + if (pkey != NULL) + { +- if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA && EVP_PKEY_get0_RSA(pkey) != NULL +- && pkey->pkey.rsa->n != NULL) ++ if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA && EVP_PKEY_get0_RSA(pkey) != NULL) + { ++ RSA *rsa = EVP_PKEY_get0_RSA(pkey); + openvpn_snprintf(s2, sizeof(s2), ", %d bit RSA", +- BN_num_bits(pkey->pkey.rsa->n)); ++ RSA_bits(rsa)); + } + else if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA && EVP_PKEY_get0_DSA(pkey) != NULL + && pkey->pkey.dsa->p != NULL) +From c07c0358b553c519ed9d80e2e0a9ba48ca8850e4 Mon Sep 17 00:00:00 2001 +From: Emmanuel Deloget <log...@free.fr> +Date: Mon, 12 Jun 2017 15:43:26 +0200 +Subject: [PATCH 4/8] OpenSSL: don't use direct access to the internal of DSA + +OpenSSL 1.1 does not allow us to directly access the internal of +any data type, including DSA. We have to use the defined +functions to do so. + +Compatibility with OpenSSL 1.0 is kept by defining the corresponding +functions when they are not found in the library. + +Signed-off-by: Emmanuel Deloget <log...@free.fr> +Acked-by: Steffan Karger <steffan.kar...@fox-it.com> +Message-Id: <20170612134330.20971-5-log...@free.fr> +URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg14791.html +Signed-off-by: Gert Doering <g...@greenie.muc.de> +--- + configure.ac | 2 ++ + src/openvpn/openssl_compat.h | 44 ++++++++++++++++++++++++++++++++++++++++++++ + src/openvpn/ssl_openssl.c | 6 +++--- + 3 files changed, 49 insertions(+), 3 deletions(-) + +diff --git a/configure.ac b/configure.ac +index e9ac5a6e..52348780 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -932,6 +932,8 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then + RSA_bits \ + RSA_get0_key \ + RSA_set0_key \ ++ DSA_get0_pqg \ ++ DSA_bits \ + RSA_meth_new \ + RSA_meth_free \ + RSA_meth_set_pub_enc \ +diff --git a/src/openvpn/openssl_compat.h b/src/openvpn/openssl_compat.h +index e3f20b73..729fab6c 100644 +--- a/src/openvpn/openssl_compat.h ++++ b/src/openvpn/openssl_compat.h +@@ -275,6 +275,50 @@ RSA_bits(const RSA *rsa) + } + #endif + ++#if !defined(HAVE_DSA_GET0_PQG) ++/** ++ * Get the DSA parameters ++ * ++ * @param dsa The DSA object ++ * @param p The @c p parameter ++ * @param q The @c q parameter ++ * @param g The @c g parameter ++ */ ++static inline void ++DSA_get0_pqg(const DSA *dsa, const BIGNUM **p, ++ const BIGNUM **q, const BIGNUM **g) ++{ ++ if (p != NULL) ++ { ++ *p = dsa ? dsa->p : NULL; ++ } ++ if (q != NULL) ++ { ++ *q = dsa ? dsa->q : NULL; ++ } ++ if (g != NULL) ++ { ++ *g = dsa ? dsa->g : NULL; ++ } ++} ++#endif ++ ++#if !defined(HAVE_DSA_BITS) ++/** ++ * Number of significant DSA bits ++ * ++ * @param rsa The DSA object ; shall not be NULL ++ * @return The number of DSA bits or 0 on error ++ */ ++static inline int ++DSA_bits(const DSA *dsa) ++{ ++ const BIGNUM *p = NULL; ++ DSA_get0_pqg(dsa, &p, NULL, NULL); ++ return p ? BN_num_bits(p) : 0; ++} ++#endif ++ + #if !defined(HAVE_RSA_METH_NEW) + /** + * Allocate a new RSA method object +diff --git a/src/openvpn/ssl_openssl.c b/src/openvpn/ssl_openssl.c +index da801ed5..11f4a567 100644 +--- a/src/openvpn/ssl_openssl.c ++++ b/src/openvpn/ssl_openssl.c +@@ -1689,11 +1689,11 @@ print_details(struct key_state_ssl *ks_ssl, const char *prefix) + openvpn_snprintf(s2, sizeof(s2), ", %d bit RSA", + RSA_bits(rsa)); + } +- else if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA && EVP_PKEY_get0_DSA(pkey) != NULL +- && pkey->pkey.dsa->p != NULL) ++ else if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA && EVP_PKEY_get0_DSA(pkey) != NULL) + { ++ DSA *dsa = EVP_PKEY_get0_DSA(pkey); + openvpn_snprintf(s2, sizeof(s2), ", %d bit DSA", +- BN_num_bits(pkey->pkey.dsa->p)); ++ DSA_bits(dsa)); + } + EVP_PKEY_free(pkey); + } +From 3fd07c31fe8878dc75e760d151d291379c0f8743 Mon Sep 17 00:00:00 2001 +From: Emmanuel Deloget <log...@free.fr> +Date: Mon, 12 Jun 2017 15:43:30 +0200 +Subject: [PATCH 5/8] OpenSSL: force meth->name as non-const when we free() + it + +We are in control of meth->name (we string_alloc() it in RSA_meth_new()) +so we know that we can free() it when it's no longer needed. Yet we have +to force the value to be non-const to avoid a compiler warning -- due to +the fact that OpenSSL defines the value as a const char*, regardless of +its origin. + +Acked-by: Steffan Karger <steffan.kar...@fox-it.com> +Message-Id: <20170612134330.20971-9-log...@free.fr> +URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg14798.html + +Signed-off-by: Gert Doering <g...@greenie.muc.de> +--- + src/openvpn/openssl_compat.h | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/src/openvpn/openssl_compat.h b/src/openvpn/openssl_compat.h +index 729fab6c..eeacb525 100644 +--- a/src/openvpn/openssl_compat.h ++++ b/src/openvpn/openssl_compat.h +@@ -349,7 +349,13 @@ RSA_meth_free(RSA_METHOD *meth) + { + if (meth) + { +- free(meth->name); ++ /* OpenSSL defines meth->name to be a const pointer, yet we ++ * feed it with an allocated string (from RSA_meth_new()). ++ * Thus we are allowed to free it here. In order to avoid a ++ * "passing 'const char *' to parameter of type 'void *' discards ++ * qualifiers" warning, we force the pointer to be a non-const value. ++ */ ++ free((char *)meth->name); + free(meth); + } + } +From c481ef002803f360743c72727ae3ca971ce59a5d Mon Sep 17 00:00:00 2001 +From: Emmanuel Deloget <log...@free.fr> +Date: Mon, 12 Jun 2017 15:43:27 +0200 +Subject: [PATCH 6/8] OpenSSL: don't use direct access to the internal of + EVP_MD_CTX + +OpenSSL 1.1 does not allow us to directly access the internal of +any data type, including EVP_MD_CTX. We have to use the defined +functions to do so. + +Compatibility with OpenSSL 1.0 is kept by defining the corresponding +functions when they are not found in the library. + +Signed-off-by: Emmanuel Deloget <log...@free.fr> +Acked-by: Steffan Karger <steffan.kar...@fox-it.com> +Message-Id: <20170612134330.20971-6-log...@free.fr> +URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg14793.html +Signed-off-by: Gert Doering <g...@greenie.muc.de> +--- + configure.ac | 3 ++ + src/openvpn/crypto_backend.h | 14 ++++++++ + src/openvpn/crypto_mbedtls.c | 12 +++++++ + src/openvpn/crypto_openssl.c | 18 ++++++++-- + src/openvpn/httpdigest.c | 78 +++++++++++++++++++++++--------------------- + src/openvpn/misc.c | 14 ++++---- + src/openvpn/openssl_compat.h | 43 ++++++++++++++++++++++++ + src/openvpn/openvpn.h | 2 +- + src/openvpn/push.c | 11 ++++--- + 9 files changed, 143 insertions(+), 52 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 52348780..f971e54a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -919,6 +919,9 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then + + AC_CHECK_FUNCS( + [ \ ++ EVP_MD_CTX_new \ ++ EVP_MD_CTX_free \ ++ EVP_MD_CTX_reset \ + SSL_CTX_get_default_passwd_cb \ + SSL_CTX_get_default_passwd_cb_userdata \ + X509_get0_pubkey \ +diff --git a/src/openvpn/crypto_backend.h b/src/openvpn/crypto_backend.h +index e2d2c96f..f1da0432 100644 +--- a/src/openvpn/crypto_backend.h ++++ b/src/openvpn/crypto_backend.h +@@ -507,6 +507,20 @@ int md_kt_size(const md_kt_t *kt); + int md_full(const md_kt_t *kt, const uint8_t *src, int src_len, uint8_t *dst); + + /* ++ * Allocate a new message digest context ++ * ++ * @return a new zeroed MD context ++ */ ++md_ctx_t *md_ctx_new(void); ++ ++/* ++ * Free an existing, non-null message digest context ++ * ++ * @param ctx Message digest context ++ */ ++void md_ctx_free(md_ctx_t *ctx); ++ ++/* + * Initialises the given message digest context. + * + * @param ctx Message digest context +diff --git a/src/openvpn/crypto_mbedtls.c b/src/openvpn/crypto_mbedtls.c +index e6388dd5..03cc1308 100644 +--- a/src/openvpn/crypto_mbedtls.c ++++ b/src/openvpn/crypto_mbedtls.c +@@ -765,6 +765,18 @@ md_full(const md_kt_t *kt, const uint8_t *src, int src_len, uint8_t *dst) + return 0 == mbedtls_md(kt, src, src_len, dst); + } + ++mbedtls_md_context_t * ++md_ctx_new(void) ++{ ++ mbedtls_md_context_t *ctx; ++ ALLOC_OBJ_CLEAR(ctx, mbedtls_md_context_t); ++ return ctx; ++} ++ ++void md_ctx_free(mbedtls_md_context_t *ctx) ++{ ++ free(ctx); ++} + + void + md_ctx_init(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *kt) +diff --git a/src/openvpn/crypto_openssl.c b/src/openvpn/crypto_openssl.c +index ee20902f..3a5a26f8 100644 +--- a/src/openvpn/crypto_openssl.c ++++ b/src/openvpn/crypto_openssl.c +@@ -41,6 +41,7 @@ + #include "integer.h" + #include "crypto.h" + #include "crypto_backend.h" ++#include "openssl_compat.h" + + #include <openssl/des.h> + #include <openssl/err.h> +@@ -843,13 +844,24 @@ md_full(const EVP_MD *kt, const uint8_t *src, int src_len, uint8_t *dst) + return EVP_Digest(src, src_len, dst, &in_md_len, kt, NULL); + } + ++EVP_MD_CTX * ++md_ctx_new(void) ++{ ++ EVP_MD_CTX *ctx = EVP_MD_CTX_new(); ++ check_malloc_return(ctx); ++ return ctx; ++} ++ ++void md_ctx_free(EVP_MD_CTX *ctx) ++{ ++ EVP_MD_CTX_free(ctx); ++} ++ + void + md_ctx_init(EVP_MD_CTX *ctx, const EVP_MD *kt) + { + ASSERT(NULL != ctx && NULL != kt); + +- CLEAR(*ctx); +- + EVP_MD_CTX_init(ctx); + EVP_DigestInit(ctx, kt); + } +@@ -857,7 +869,7 @@ md_ctx_init(EVP_MD_CTX *ctx, const EVP_MD *kt) + void + md_ctx_cleanup(EVP_MD_CTX *ctx) + { +- EVP_MD_CTX_cleanup(ctx); ++ EVP_MD_CTX_reset(ctx); + } + + int +diff --git a/src/openvpn/httpdigest.c b/src/openvpn/httpdigest.c +index e578c85d..c553f939 100644 +--- a/src/openvpn/httpdigest.c ++++ b/src/openvpn/httpdigest.c +@@ -80,27 +80,28 @@ DigestCalcHA1( + ) + { + HASH HA1; +- md_ctx_t md5_ctx; ++ md_ctx_t *md5_ctx = md_ctx_new(); + const md_kt_t *md5_kt = md_kt_get("MD5"); + +- md_ctx_init(&md5_ctx, md5_kt); +- md_ctx_update(&md5_ctx, (const uint8_t *) pszUserName, strlen(pszUserName)); +- md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); +- md_ctx_update(&md5_ctx, (const uint8_t *) pszRealm, strlen(pszRealm)); +- md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); +- md_ctx_update(&md5_ctx, (const uint8_t *) pszPassword, strlen(pszPassword)); +- md_ctx_final(&md5_ctx, HA1); ++ md_ctx_init(md5_ctx, md5_kt); ++ md_ctx_update(md5_ctx, (const uint8_t *) pszUserName, strlen(pszUserName)); ++ md_ctx_update(md5_ctx, (const uint8_t *) ":", 1); ++ md_ctx_update(md5_ctx, (const uint8_t *) pszRealm, strlen(pszRealm)); ++ md_ctx_update(md5_ctx, (const uint8_t *) ":", 1); ++ md_ctx_update(md5_ctx, (const uint8_t *) pszPassword, strlen(pszPassword)); ++ md_ctx_final(md5_ctx, HA1); + if (pszAlg && strcasecmp(pszAlg, "md5-sess") == 0) + { +- md_ctx_init(&md5_ctx, md5_kt); +- md_ctx_update(&md5_ctx, HA1, HASHLEN); +- md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); +- md_ctx_update(&md5_ctx, (const uint8_t *) pszNonce, strlen(pszNonce)); +- md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); +- md_ctx_update(&md5_ctx, (const uint8_t *) pszCNonce, strlen(pszCNonce)); +- md_ctx_final(&md5_ctx, HA1); ++ md_ctx_init(md5_ctx, md5_kt); ++ md_ctx_update(md5_ctx, HA1, HASHLEN); ++ md_ctx_update(md5_ctx, (const uint8_t *) ":", 1); ++ md_ctx_update(md5_ctx, (const uint8_t *) pszNonce, strlen(pszNonce)); ++ md_ctx_update(md5_ctx, (const uint8_t *) ":", 1); ++ md_ctx_update(md5_ctx, (const uint8_t *) pszCNonce, strlen(pszCNonce)); ++ md_ctx_final(md5_ctx, HA1); + } +- md_ctx_cleanup(&md5_ctx); ++ md_ctx_cleanup(md5_ctx); ++ md_ctx_free(md5_ctx); + CvtHex(HA1, SessionKey); + } + +@@ -122,40 +123,41 @@ DigestCalcResponse( + HASH RespHash; + HASHHEX HA2Hex; + +- md_ctx_t md5_ctx; ++ md_ctx_t *md5_ctx = md_ctx_new(); + const md_kt_t *md5_kt = md_kt_get("MD5"); + + /* calculate H(A2) */ +- md_ctx_init(&md5_ctx, md5_kt); +- md_ctx_update(&md5_ctx, (const uint8_t *) pszMethod, strlen(pszMethod)); +- md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); +- md_ctx_update(&md5_ctx, (const uint8_t *) pszDigestUri, strlen(pszDigestUri)); ++ md_ctx_init(md5_ctx, md5_kt); ++ md_ctx_update(md5_ctx, (const uint8_t *) pszMethod, strlen(pszMethod)); ++ md_ctx_update(md5_ctx, (const uint8_t *) ":", 1); ++ md_ctx_update(md5_ctx, (const uint8_t *) pszDigestUri, strlen(pszDigestUri)); + if (strcasecmp(pszQop, "auth-int") == 0) + { +- md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); +- md_ctx_update(&md5_ctx, HEntity, HASHHEXLEN); ++ md_ctx_update(md5_ctx, (const uint8_t *) ":", 1); ++ md_ctx_update(md5_ctx, HEntity, HASHHEXLEN); + } +- md_ctx_final(&md5_ctx, HA2); ++ md_ctx_final(md5_ctx, HA2); + CvtHex(HA2, HA2Hex); + + /* calculate response */ +- md_ctx_init(&md5_ctx, md5_kt); +- md_ctx_update(&md5_ctx, HA1, HASHHEXLEN); +- md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); +- md_ctx_update(&md5_ctx, (const uint8_t *) pszNonce, strlen(pszNonce)); +- md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); ++ md_ctx_init(md5_ctx, md5_kt); ++ md_ctx_update(md5_ctx, HA1, HASHHEXLEN); ++ md_ctx_update(md5_ctx, (const uint8_t *) ":", 1); ++ md_ctx_update(md5_ctx, (const uint8_t *) pszNonce, strlen(pszNonce)); ++ md_ctx_update(md5_ctx, (const uint8_t *) ":", 1); + if (*pszQop) + { +- md_ctx_update(&md5_ctx, (const uint8_t *) pszNonceCount, strlen(pszNonceCount)); +- md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); +- md_ctx_update(&md5_ctx, (const uint8_t *) pszCNonce, strlen(pszCNonce)); +- md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); +- md_ctx_update(&md5_ctx, (const uint8_t *) pszQop, strlen(pszQop)); +- md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); ++ md_ctx_update(md5_ctx, (const uint8_t *) pszNonceCount, strlen(pszNonceCount)); ++ md_ctx_update(md5_ctx, (const uint8_t *) ":", 1); ++ md_ctx_update(md5_ctx, (const uint8_t *) pszCNonce, strlen(pszCNonce)); ++ md_ctx_update(md5_ctx, (const uint8_t *) ":", 1); ++ md_ctx_update(md5_ctx, (const uint8_t *) pszQop, strlen(pszQop)); ++ md_ctx_update(md5_ctx, (const uint8_t *) ":", 1); + } +- md_ctx_update(&md5_ctx, HA2Hex, HASHHEXLEN); +- md_ctx_final(&md5_ctx, RespHash); +- md_ctx_cleanup(&md5_ctx); ++ md_ctx_update(md5_ctx, HA2Hex, HASHHEXLEN); ++ md_ctx_final(md5_ctx, RespHash); ++ md_ctx_cleanup(md5_ctx); ++ md_ctx_free(md5_ctx); + CvtHex(RespHash, Response); + } + +diff --git a/src/openvpn/misc.c b/src/openvpn/misc.c +index d286c197..df108b08 100644 +--- a/src/openvpn/misc.c ++++ b/src/openvpn/misc.c +@@ -1387,7 +1387,7 @@ get_user_pass_auto_userid(struct user_pass *up, const char *tag) + static const uint8_t hashprefix[] = "AUTO_USERID_DIGEST"; + + const md_kt_t *md5_kt = md_kt_get("MD5"); +- md_ctx_t ctx; ++ md_ctx_t *ctx; + + CLEAR(*up); + buf_set_write(&buf, (uint8_t *)up->username, USER_PASS_LEN); +@@ -1395,11 +1395,13 @@ get_user_pass_auto_userid(struct user_pass *up, const char *tag) + if (get_default_gateway_mac_addr(macaddr)) + { + dmsg(D_AUTO_USERID, "GUPAU: macaddr=%s", format_hex_ex(macaddr, sizeof(macaddr), 0, 1, ":", &gc)); +- md_ctx_init(&ctx, md5_kt); +- md_ctx_update(&ctx, hashprefix, sizeof(hashprefix) - 1); +- md_ctx_update(&ctx, macaddr, sizeof(macaddr)); +- md_ctx_final(&ctx, digest); +- md_ctx_cleanup(&ctx) ++ ctx = md_ctx_new(); ++ md_ctx_init(ctx, md5_kt); ++ md_ctx_update(ctx, hashprefix, sizeof(hashprefix) - 1); ++ md_ctx_update(ctx, macaddr, sizeof(macaddr)); ++ md_ctx_final(ctx, digest); ++ md_ctx_cleanup(ctx); ++ md_ctx_free(ctx); + buf_printf(&buf, "%s", format_hex_ex(digest, sizeof(digest), 0, 256, " ", &gc)); + } + else +diff --git a/src/openvpn/openssl_compat.h b/src/openvpn/openssl_compat.h +index eeacb525..3d8fad10 100644 +--- a/src/openvpn/openssl_compat.h ++++ b/src/openvpn/openssl_compat.h +@@ -45,6 +45,49 @@ + #include <openssl/ssl.h> + #include <openssl/x509.h> + ++#if !defined(HAVE_EVP_MD_CTX_RESET) ++/** ++ * Reset a message digest context ++ * ++ * @param ctx The message digest context ++ * @return 1 on success, 0 on error ++ */ ++static inline int ++EVP_MD_CTX_reset(EVP_MD_CTX *ctx) ++{ ++ EVP_MD_CTX_cleanup(ctx); ++ return 1; ++} ++#endif ++ ++#if !defined(HAVE_EVP_MD_CTX_FREE) ++/** ++ * Free an existing message digest context ++ * ++ * @param ctx The message digest context ++ */ ++static inline void ++EVP_MD_CTX_free(EVP_MD_CTX *ctx) ++{ ++ free(ctx); ++} ++#endif ++ ++#if !defined(HAVE_EVP_MD_CTX_NEW) ++/** ++ * Allocate a new message digest object ++ * ++ * @return A zero'ed message digest object ++ */ ++static inline EVP_MD_CTX * ++EVP_MD_CTX_new(void) ++{ ++ EVP_MD_CTX *ctx = NULL; ++ ALLOC_OBJ_CLEAR(ctx, EVP_MD_CTX); ++ return ctx; ++} ++#endif ++ + #if !defined(HAVE_SSL_CTX_GET_DEFAULT_PASSWD_CB_USERDATA) + /** + * Fetch the default password callback user data from the SSL context +diff --git a/src/openvpn/openvpn.h b/src/openvpn/openvpn.h +index c01e8a2c..9262e68b 100644 +--- a/src/openvpn/openvpn.h ++++ b/src/openvpn/openvpn.h +@@ -472,7 +472,7 @@ struct context_2 + + /* hash of pulled options, so we can compare when options change */ + bool pulled_options_digest_init_done; +- md_ctx_t pulled_options_state; ++ md_ctx_t *pulled_options_state; + struct sha256_digest pulled_options_digest; + + struct event_timeout scheduled_exit; +diff --git a/src/openvpn/push.c b/src/openvpn/push.c +index 441d303e..5947a31f 100644 +--- a/src/openvpn/push.c ++++ b/src/openvpn/push.c +@@ -723,7 +723,8 @@ process_incoming_push_msg(struct context *c, + struct buffer buf_orig = buf; + if (!c->c2.pulled_options_digest_init_done) + { +- md_ctx_init(&c->c2.pulled_options_state, md_kt_get("SHA256")); ++ c->c2.pulled_options_state = md_ctx_new(); ++ md_ctx_init(c->c2.pulled_options_state, md_kt_get("SHA256")); + c->c2.pulled_options_digest_init_done = true; + } + if (!c->c2.did_pre_pull_restore) +@@ -737,14 +738,16 @@ process_incoming_push_msg(struct context *c, + option_types_found, + c->c2.es)) + { +- push_update_digest(&c->c2.pulled_options_state, &buf_orig, ++ push_update_digest(c->c2.pulled_options_state, &buf_orig, + &c->options); + switch (c->options.push_continuation) + { + case 0: + case 1: +- md_ctx_final(&c->c2.pulled_options_state, c->c2.pulled_options_digest.digest); +- md_ctx_cleanup(&c->c2.pulled_options_state); ++ md_ctx_final(c->c2.pulled_options_state, c->c2.pulled_options_digest.digest); ++ md_ctx_cleanup(c->c2.pulled_options_state); ++ md_ctx_free(c->c2.pulled_options_state); ++ c->c2.pulled_options_state = NULL; + c->c2.pulled_options_digest_init_done = false; + ret = PUSH_MSG_REPLY; + break; +From 6cbd48a3ead23f004f25943d067fa668efdc580e Mon Sep 17 00:00:00 2001 +From: Emmanuel Deloget <log...@free.fr> +Date: Mon, 12 Jun 2017 15:43:28 +0200 +Subject: [PATCH 7/8] OpenSSL: don't use direct access to the internal of + EVP_CIPHER_CTX + +OpenSSL 1.1 does not allow us to directly access the internal of +any data type, including EVP_CIPHER_CTX. We have to use the defined +functions to do so. + +Compatibility with OpenSSL 1.0 is kept by defining the corresponding +functions when they are not found in the library. + +Signed-off-by: Emmanuel Deloget <log...@free.fr> +Acked-by: Steffan Karger <steffan.kar...@fox-it.com> +Message-Id: <20170612134330.20971-7-log...@free.fr> +URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg14796.html +Signed-off-by: Gert Doering <g...@greenie.muc.de> +--- + configure.ac | 2 ++ + src/openvpn/crypto.c | 4 ++-- + src/openvpn/crypto_backend.h | 14 ++++++++++++++ + src/openvpn/crypto_mbedtls.c | 13 +++++++++++++ + src/openvpn/crypto_openssl.c | 15 +++++++++++++-- + src/openvpn/openssl_compat.h | 28 ++++++++++++++++++++++++++++ + 6 files changed, 72 insertions(+), 4 deletions(-) + +diff --git a/configure.ac b/configure.ac +index f971e54a..07fc3392 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -919,6 +919,8 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then + + AC_CHECK_FUNCS( + [ \ ++ EVP_CIPHER_CTX_new \ ++ EVP_CIPHER_CTX_free \ + EVP_MD_CTX_new \ + EVP_MD_CTX_free \ + EVP_MD_CTX_reset \ +diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c +index b6d0d550..f7c4d60a 100644 +--- a/src/openvpn/crypto.c ++++ b/src/openvpn/crypto.c +@@ -829,7 +829,7 @@ init_key_ctx(struct key_ctx *ctx, struct key *key, + if (kt->cipher && kt->cipher_length > 0) + { + +- ALLOC_OBJ(ctx->cipher, cipher_ctx_t); ++ ctx->cipher = cipher_ctx_new(); + cipher_ctx_init(ctx->cipher, key->cipher, kt->cipher_length, + kt->cipher, enc); + +@@ -878,7 +878,7 @@ free_key_ctx(struct key_ctx *ctx) + if (ctx->cipher) + { + cipher_ctx_cleanup(ctx->cipher); +- free(ctx->cipher); ++ cipher_ctx_free(ctx->cipher); + ctx->cipher = NULL; + } + if (ctx->hmac) +diff --git a/src/openvpn/crypto_backend.h b/src/openvpn/crypto_backend.h +index f1da0432..9679ee9b 100644 +--- a/src/openvpn/crypto_backend.h ++++ b/src/openvpn/crypto_backend.h +@@ -300,6 +300,20 @@ bool cipher_kt_mode_aead(const cipher_kt_t *cipher); + */ + + /** ++ * Allocate a new cipher context ++ * ++ * @return a new cipher context ++ */ ++cipher_ctx_t *cipher_ctx_new(void); ++ ++/** ++ * Free a cipher context ++ * ++ * @param ctx Cipher context. ++ */ ++void cipher_ctx_free(cipher_ctx_t *ctx); ++ ++/** + * Initialise a cipher context, based on the given key and key type. + * + * @param ctx Cipher context. May not be NULL +diff --git a/src/openvpn/crypto_mbedtls.c b/src/openvpn/crypto_mbedtls.c +index 03cc1308..5f16a1f0 100644 +--- a/src/openvpn/crypto_mbedtls.c ++++ b/src/openvpn/crypto_mbedtls.c +@@ -508,6 +508,19 @@ cipher_kt_mode_aead(const cipher_kt_t *cipher) + * + */ + ++mbedtls_cipher_context_t * ++cipher_ctx_new(void) ++{ ++ mbedtls_cipher_context_t *ctx; ++ ALLOC_OBJ(ctx, mbedtls_cipher_context_t); ++ return ctx; ++} ++ ++void ++cipher_ctx_free(mbedtls_cipher_context_t *ctx) ++{ ++ free(ctx); ++} + + void + cipher_ctx_init(mbedtls_cipher_context_t *ctx, uint8_t *key, int key_len, +diff --git a/src/openvpn/crypto_openssl.c b/src/openvpn/crypto_openssl.c +index 3a5a26f8..f4470fc0 100644 +--- a/src/openvpn/crypto_openssl.c ++++ b/src/openvpn/crypto_openssl.c +@@ -650,6 +650,19 @@ cipher_kt_mode_aead(const cipher_kt_t *cipher) + * + */ + ++cipher_ctx_t * ++cipher_ctx_new(void) ++{ ++ EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); ++ check_malloc_return(ctx); ++ return ctx; ++} ++ ++void ++cipher_ctx_free(EVP_CIPHER_CTX *ctx) ++{ ++ EVP_CIPHER_CTX_free(ctx); ++} + + void + cipher_ctx_init(EVP_CIPHER_CTX *ctx, uint8_t *key, int key_len, +@@ -657,8 +670,6 @@ cipher_ctx_init(EVP_CIPHER_CTX *ctx, uint8_t *key, int key_len, + { + ASSERT(NULL != kt && NULL != ctx); + +- CLEAR(*ctx); +- + EVP_CIPHER_CTX_init(ctx); + if (!EVP_CipherInit(ctx, kt, NULL, NULL, enc)) + { +diff --git a/src/openvpn/openssl_compat.h b/src/openvpn/openssl_compat.h +index 3d8fad10..c9e2692b 100644 +--- a/src/openvpn/openssl_compat.h ++++ b/src/openvpn/openssl_compat.h +@@ -88,6 +88,34 @@ EVP_MD_CTX_new(void) + } + #endif + ++#if !defined(HAVE_EVP_CIPHER_CTX_FREE) ++/** ++ * Free an existing cipher context ++ * ++ * @param ctx The cipher context ++ */ ++static inline void ++EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *c) ++{ ++ free(c); ++} ++#endif ++ ++#if !defined(HAVE_EVP_CIPHER_CTX_NEW) ++/** ++ * Allocate a new cipher context object ++ * ++ * @return A zero'ed cipher context object ++ */ ++static inline EVP_CIPHER_CTX * ++EVP_CIPHER_CTX_new(void) ++{ ++ EVP_CIPHER_CTX *ctx = NULL; ++ ALLOC_OBJ_CLEAR(ctx, EVP_CIPHER_CTX); ++ return ctx; ++} ++#endif ++ + #if !defined(HAVE_SSL_CTX_GET_DEFAULT_PASSWD_CB_USERDATA) + /** + * Fetch the default password callback user data from the SSL context +From aba98e9050eb54d72d921e70bcd422cb892b9c6c Mon Sep 17 00:00:00 2001 +From: Emmanuel Deloget <log...@free.fr> +Date: Mon, 12 Jun 2017 15:43:29 +0200 +Subject: [PATCH 8/8] OpenSSL: don't use direct access to the internal of + HMAC_CTX + +OpenSSL 1.1 does not allow us to directly access the internal of +any data type, including HMAC_CTX. We have to use the defined +functions to do so. + +Compatibility with OpenSSL 1.0 is kept by defining the corresponding +functions when they are not found in the library. + +Signed-off-by: Emmanuel Deloget <log...@free.fr> +Acked-by: Steffan Karger <steffan.kar...@fox-it.com> +Message-Id: <20170612134330.20971-8-log...@free.fr> +URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg14797.html +Signed-off-by: Gert Doering <g...@greenie.muc.de> +--- + configure.ac | 4 +++ + src/openvpn/crypto.c | 4 +-- + src/openvpn/crypto_backend.h | 14 ++++++++++ + src/openvpn/crypto_mbedtls.c | 15 ++++++++++ + src/openvpn/crypto_openssl.c | 17 ++++++++++-- + src/openvpn/ntlm.c | 12 ++++---- + src/openvpn/openssl_compat.h | 65 ++++++++++++++++++++++++++++++++++++++++++++ + src/openvpn/ssl.c | 38 ++++++++++++++------------ + 8 files changed, 140 insertions(+), 29 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 07fc3392..56ce5f82 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -921,6 +921,10 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then + [ \ + EVP_CIPHER_CTX_new \ + EVP_CIPHER_CTX_free \ ++ HMAC_CTX_new \ ++ HMAC_CTX_free \ ++ HMAC_CTX_reset \ ++ HMAC_CTX_init \ + EVP_MD_CTX_new \ + EVP_MD_CTX_free \ + EVP_MD_CTX_reset \ +diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c +index f7c4d60a..191fee8e 100644 +--- a/src/openvpn/crypto.c ++++ b/src/openvpn/crypto.c +@@ -853,7 +853,7 @@ init_key_ctx(struct key_ctx *ctx, struct key *key, + } + if (kt->digest && kt->hmac_length > 0) + { +- ALLOC_OBJ(ctx->hmac, hmac_ctx_t); ++ ctx->hmac = hmac_ctx_new(); + hmac_ctx_init(ctx->hmac, key->hmac, kt->hmac_length, kt->digest); + + msg(D_HANDSHAKE, +@@ -884,7 +884,7 @@ free_key_ctx(struct key_ctx *ctx) + if (ctx->hmac) + { + hmac_ctx_cleanup(ctx->hmac); +- free(ctx->hmac); ++ hmac_ctx_free(ctx->hmac); + ctx->hmac = NULL; + } + ctx->implicit_iv_len = 0; +diff --git a/src/openvpn/crypto_backend.h b/src/openvpn/crypto_backend.h +index 9679ee9b..b7f519b5 100644 +--- a/src/openvpn/crypto_backend.h ++++ b/src/openvpn/crypto_backend.h +@@ -583,6 +583,20 @@ void md_ctx_final(md_ctx_t *ctx, uint8_t *dst); + */ + + /* ++ * Create a new HMAC context ++ * ++ * @return A new HMAC context ++ */ ++hmac_ctx_t *hmac_ctx_new(void); ++ ++/* ++ * Free an existing HMAC context ++ * ++ * @param ctx HMAC context to free ++ */ ++void hmac_ctx_free(hmac_ctx_t *ctx); ++ ++/* + * Initialises the given HMAC context, using the given digest + * and key. + * +diff --git a/src/openvpn/crypto_mbedtls.c b/src/openvpn/crypto_mbedtls.c +index 5f16a1f0..24bc3158 100644 +--- a/src/openvpn/crypto_mbedtls.c ++++ b/src/openvpn/crypto_mbedtls.c +@@ -840,6 +840,21 @@ md_ctx_final(mbedtls_md_context_t *ctx, uint8_t *dst) + /* + * TODO: re-enable dmsg for crypto debug + */ ++ ++mbedtls_md_context_t * ++hmac_ctx_new(void) ++{ ++ mbedtls_md_context_t *ctx; ++ ALLOC_OBJ(ctx, mbedtls_md_context_t); ++ return ctx; ++} ++ ++void ++hmac_ctx_free(mbedtls_md_context_t *ctx) ++{ ++ free(ctx); ++} ++ + void + hmac_ctx_init(mbedtls_md_context_t *ctx, const uint8_t *key, int key_len, + const mbedtls_md_info_t *kt) +diff --git a/src/openvpn/crypto_openssl.c b/src/openvpn/crypto_openssl.c +index f4470fc0..a55e65c1 100644 +--- a/src/openvpn/crypto_openssl.c ++++ b/src/openvpn/crypto_openssl.c +@@ -910,6 +910,19 @@ md_ctx_final(EVP_MD_CTX *ctx, uint8_t *dst) + * + */ + ++HMAC_CTX * ++hmac_ctx_new(void) ++{ ++ HMAC_CTX *ctx = HMAC_CTX_new(); ++ check_malloc_return(ctx); ++ return ctx; ++} ++ ++void ++hmac_ctx_free(HMAC_CTX *ctx) ++{ ++ HMAC_CTX_free(ctx); ++} + + void + hmac_ctx_init(HMAC_CTX *ctx, const uint8_t *key, int key_len, +@@ -917,8 +930,6 @@ hmac_ctx_init(HMAC_CTX *ctx, const uint8_t *key, int key_len, + { + ASSERT(NULL != kt && NULL != ctx); + +- CLEAR(*ctx); +- + HMAC_CTX_init(ctx); + HMAC_Init_ex(ctx, key, key_len, kt, NULL); + +@@ -929,7 +940,7 @@ hmac_ctx_init(HMAC_CTX *ctx, const uint8_t *key, int key_len, + void + hmac_ctx_cleanup(HMAC_CTX *ctx) + { +- HMAC_CTX_cleanup(ctx); ++ HMAC_CTX_reset(ctx); + } + + int +diff --git a/src/openvpn/ntlm.c b/src/openvpn/ntlm.c +index 69b7d426..16d60d2c 100644 +--- a/src/openvpn/ntlm.c ++++ b/src/openvpn/ntlm.c +@@ -85,13 +85,13 @@ static void + gen_hmac_md5(const char *data, int data_len, const char *key, int key_len,char *result) + { + const md_kt_t *md5_kt = md_kt_get("MD5"); +- hmac_ctx_t hmac_ctx; +- CLEAR(hmac_ctx); ++ hmac_ctx_t *hmac_ctx = hmac_ctx_new(); + +- hmac_ctx_init(&hmac_ctx, key, key_len, md5_kt); +- hmac_ctx_update(&hmac_ctx, (const unsigned char *)data, data_len); +- hmac_ctx_final(&hmac_ctx, (unsigned char *)result); +- hmac_ctx_cleanup(&hmac_ctx); ++ hmac_ctx_init(hmac_ctx, key, key_len, md5_kt); ++ hmac_ctx_update(hmac_ctx, (const unsigned char *)data, data_len); ++ hmac_ctx_final(hmac_ctx, (unsigned char *)result); ++ hmac_ctx_cleanup(hmac_ctx); ++ hmac_ctx_free(hmac_ctx); + } + + static void +diff --git a/src/openvpn/openssl_compat.h b/src/openvpn/openssl_compat.h +index c9e2692b..c765f0bb 100644 +--- a/src/openvpn/openssl_compat.h ++++ b/src/openvpn/openssl_compat.h +@@ -116,6 +116,71 @@ EVP_CIPHER_CTX_new(void) + } + #endif + ++#if !defined(HAVE_HMAC_CTX_RESET) ++/** ++ * Reset a HMAC context ++ * ++ * @param ctx The HMAC context ++ * @return 1 on success, 0 on error ++ */ ++static inline int ++HMAC_CTX_reset(HMAC_CTX *ctx) ++{ ++ HMAC_CTX_cleanup(ctx); ++ return 1; ++} ++#endif ++ ++#if !defined(HAVE_HMAC_CTX_INIT) ++/** ++ * Init a HMAC context ++ * ++ * @param ctx The HMAC context ++ * ++ * Contrary to many functions in this file, HMAC_CTX_init() is not ++ * an OpenSSL 1.1 function: it comes from previous versions and was ++ * removed in v1.1. As a consequence, there is no distincting in ++ * v1.1 between a cleanup, and init and a reset. Yet, previous OpenSSL ++ * version need this distinction. ++ * ++ * In order to respect previous OpenSSL versions, we implement init ++ * as reset for OpenSSL 1.1+. ++ */ ++static inline void ++HMAC_CTX_init(HMAC_CTX *ctx) ++{ ++ HMAC_CTX_reset(ctx); ++} ++#endif ++ ++#if !defined(HAVE_HMAC_CTX_FREE) ++/** ++ * Free an existing HMAC context ++ * ++ * @param ctx The HMAC context ++ */ ++static inline void ++HMAC_CTX_free(HMAC_CTX *c) ++{ ++ free(c); ++} ++#endif ++ ++#if !defined(HAVE_HMAC_CTX_NEW) ++/** ++ * Allocate a new HMAC context object ++ * ++ * @return A zero'ed HMAC context object ++ */ ++static inline HMAC_CTX * ++HMAC_CTX_new(void) ++{ ++ HMAC_CTX *ctx = NULL; ++ ALLOC_OBJ_CLEAR(ctx, HMAC_CTX); ++ return ctx; ++} ++#endif ++ + #if !defined(HAVE_SSL_CTX_GET_DEFAULT_PASSWD_CB_USERDATA) + /** + * Fetch the default password callback user data from the SSL context +diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c +index cc7b1830..c658f377 100644 +--- a/src/openvpn/ssl.c ++++ b/src/openvpn/ssl.c +@@ -1606,8 +1606,8 @@ tls1_P_hash(const md_kt_t *md_kt, + { + struct gc_arena gc = gc_new(); + int chunk; +- hmac_ctx_t ctx; +- hmac_ctx_t ctx_tmp; ++ hmac_ctx_t *ctx; ++ hmac_ctx_t *ctx_tmp; + uint8_t A1[MAX_HMAC_KEY_LENGTH]; + unsigned int A1_len; + +@@ -1616,8 +1616,8 @@ tls1_P_hash(const md_kt_t *md_kt, + const uint8_t *out_orig = out; + #endif + +- CLEAR(ctx); +- CLEAR(ctx_tmp); ++ ctx = hmac_ctx_new(); ++ ctx_tmp = hmac_ctx_new(); + + dmsg(D_SHOW_KEY_SOURCE, "tls1_P_hash sec: %s", format_hex(sec, sec_len, 0, &gc)); + dmsg(D_SHOW_KEY_SOURCE, "tls1_P_hash seed: %s", format_hex(seed, seed_len, 0, &gc)); +@@ -1625,36 +1625,38 @@ tls1_P_hash(const md_kt_t *md_kt, + chunk = md_kt_size(md_kt); + A1_len = md_kt_size(md_kt); + +- hmac_ctx_init(&ctx, sec, sec_len, md_kt); +- hmac_ctx_init(&ctx_tmp, sec, sec_len, md_kt); ++ hmac_ctx_init(ctx, sec, sec_len, md_kt); ++ hmac_ctx_init(ctx_tmp, sec, sec_len, md_kt); + +- hmac_ctx_update(&ctx,seed,seed_len); +- hmac_ctx_final(&ctx, A1); ++ hmac_ctx_update(ctx,seed,seed_len); ++ hmac_ctx_final(ctx, A1); + + for (;; ) + { +- hmac_ctx_reset(&ctx); +- hmac_ctx_reset(&ctx_tmp); +- hmac_ctx_update(&ctx,A1,A1_len); +- hmac_ctx_update(&ctx_tmp,A1,A1_len); +- hmac_ctx_update(&ctx,seed,seed_len); ++ hmac_ctx_reset(ctx); ++ hmac_ctx_reset(ctx_tmp); ++ hmac_ctx_update(ctx,A1,A1_len); ++ hmac_ctx_update(ctx_tmp,A1,A1_len); ++ hmac_ctx_update(ctx,seed,seed_len); + + if (olen > chunk) + { +- hmac_ctx_final(&ctx, out); ++ hmac_ctx_final(ctx, out); + out += chunk; + olen -= chunk; +- hmac_ctx_final(&ctx_tmp, A1); /* calc the next A1 value */ ++ hmac_ctx_final(ctx_tmp, A1); /* calc the next A1 value */ + } + else /* last one */ + { +- hmac_ctx_final(&ctx, A1); ++ hmac_ctx_final(ctx, A1); + memcpy(out,A1,olen); + break; + } + } +- hmac_ctx_cleanup(&ctx); +- hmac_ctx_cleanup(&ctx_tmp); ++ hmac_ctx_cleanup(ctx); ++ hmac_ctx_free(ctx); ++ hmac_ctx_cleanup(ctx_tmp); ++ hmac_ctx_free(ctx_tmp); + secure_memzero(A1, sizeof(A1)); + + dmsg(D_SHOW_KEY_SOURCE, "tls1_P_hash out: %s", format_hex(out_orig, olen_orig, 0, &gc)); Copied: openvpn/repos/testing-x86_64/PKGBUILD (from rev 298959, openvpn/trunk/PKGBUILD) =================================================================== --- testing-x86_64/PKGBUILD (rev 0) +++ testing-x86_64/PKGBUILD 2017-06-18 19:30:55 UTC (rev 298960) @@ -0,0 +1,78 @@ +# $Id$ +# Maintainer: Christian Hesse <m...@eworm.de> + +pkgname=openvpn +pkgver=2.4.2 +pkgrel=2 +pkgdesc='An easy-to-use, robust and highly configurable VPN (Virtual Private Network)' +arch=('i686' 'x86_64') +url='http://openvpn.net/index.php/open-source.html' +depends=('openssl' 'lzo' 'iproute2' 'libsystemd' 'pkcs11-helper') +optdepends=('easy-rsa: easy CA and certificate handling') +makedepends=('systemd') +license=('custom') +install=openvpn.install +validpgpkeys=('6D04F8F1B0173111F499795E29584D9F40864578' # Samuli Seppänen <sam...@openvpn.net> + '7ACD56B74144925C6214329757DB9DAB613B8DA1') # David Sommerseth (OpenVPN Technologies, Inc) <dav...@openvpn.net> +source=("https://swupdate.openvpn.net/community/releases/openvpn-${pkgver}.tar.xz"{,.asc} + '0004-openssl-1-1-0.patch') +sha256sums=('df5c4f384b7df6b08a2f6fa8a84b9fd382baf59c2cef1836f82e2a7f62f1bff9' + 'SKIP' + '75259cb14ed8237c2ca5618eca902ed39f720df166e732911e21dd5abcc68b3e') + +prepare() { + cd "${srcdir}"/${pkgname}-${pkgver} + + # allow to build against openssl 1.1.0 + patch -Np1 < "${srcdir}"/0004-openssl-1-1-0.patch + + # regenerate configure script + autoreconf -fi +} + +build() { + cd "${srcdir}"/${pkgname}-${pkgver} + + ./configure \ + --prefix=/usr \ + --sbindir=/usr/bin \ + --enable-iproute2 \ + --enable-pkcs11 \ + --enable-plugins \ + --enable-systemd \ + --enable-x509-alt-username + make +} + +check() { + cd "${srcdir}"/${pkgname}-${pkgver} + + make check +} + +package() { + cd "${srcdir}"/${pkgname}-${pkgver} + + # Install openvpn + make DESTDIR="${pkgdir}" install + + # Create empty configuration directories + install -d -m0750 -g 90 "${pkgdir}"/etc/openvpn/{client,server} + + # Install examples + install -d -m0755 "${pkgdir}"/usr/share/openvpn + cp -r sample/sample-config-files "${pkgdir}"/usr/share/openvpn/examples + + # Install license + install -d -m0755 "${pkgdir}"/usr/share/licenses/openvpn/ + ln -sf /usr/share/doc/openvpn/{COPYING,COPYRIGHT.GPL} "${pkgdir}"/usr/share/licenses/openvpn/ + + # Install contrib + for FILE in $(find contrib -type f); do + case "$(file --brief --mime-type "${FILE}")" in + "text/x-shellscript") install -D -m0755 "${FILE}" "${pkgdir}/usr/share/openvpn/${FILE}" ;; + *) install -D -m0644 "${FILE}" "${pkgdir}/usr/share/openvpn/${FILE}" ;; + esac + done +} + Copied: openvpn/repos/testing-x86_64/openvpn.install (from rev 298959, openvpn/trunk/openvpn.install) =================================================================== --- testing-x86_64/openvpn.install (rev 0) +++ testing-x86_64/openvpn.install 2017-06-18 19:30:55 UTC (rev 298960) @@ -0,0 +1,24 @@ +#!/bin/sh + +post_upgrade() { + # return if old package version greater 2.4... + (( $(vercmp $2 '2.4') > 0 )) && return + + # upgrade from pre-2.4 version... + echo "This upgrade from openvpn $2 to openvpn $1 made changes that require" + echo "administrative interaction:" + echo " -> Configuration is expected in sub directories now. Move your files" + echo " from /etc/openvpn/ to /etc/openvpn/server/ or /etc/openvpn/client/." + echo " -> The plugin lookup path changed, remove extra 'plugins/' from relative paths." + echo " -> The systemd unit openvpn@.service was replaced with openvpn-client@.service" + echo " and openvpn-server@.service. Restart and reenable accordingly." + + local UNITS="$(systemctl list-units --quiet --no-pager --no-legend --plain | grep '^openvpn@' | cut -d' ' -f1)" + if (( ${#UNITS} )); then + echo "This is a (possibly incomplete) list of units that need to be acted on:" + for UNIT in ${UNITS}; do + echo " -> ${UNIT}" + done + fi +} +