diff -u -r -N squid-4.0.19/acinclude/lib-checks.m4 squid-4.0.20/acinclude/lib-checks.m4 --- squid-4.0.19/acinclude/lib-checks.m4 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/acinclude/lib-checks.m4 2017-06-02 00:49:17.000000000 +1200 @@ -46,6 +46,61 @@ SQUID_STATE_ROLLBACK(iphlpapi) ]) +dnl Checks whether the -lssl library provides OpenSSL TLS_*_method() definitions +AC_DEFUN([SQUID_CHECK_OPENSSL_TLS_METHODS],[ + AH_TEMPLATE(HAVE_OPENSSL_TLS_METHOD, "Define to 1 if the TLS_method() OpenSSL API function exists") + AH_TEMPLATE(HAVE_OPENSSL_TLS_CLIENT_METHOD, "Define to 1 if the TLS_client_method() OpenSSL API function exists") + AH_TEMPLATE(HAVE_OPENSSL_TLS_SERVER_METHOD, "Define to 1 if the TLS_server_method() OpenSSL API function exists") + SQUID_STATE_SAVE(check_openssl_TLS_METHODS) + LIBS="$LIBS $SSLLIB" + AC_CHECK_LIB(ssl, TLS_method, AC_DEFINE(HAVE_OPENSSL_TLS_METHOD, 1)) + AC_CHECK_LIB(ssl, TLS_client_method, AC_DEFINE(HAVE_OPENSSL_TLS_CLIENT_METHOD, 1)) + AC_CHECK_LIB(ssl, TLS_server_method, AC_DEFINE(HAVE_OPENSSL_TLS_SERVER_METHOD, 1)) + SQUID_STATE_ROLLBACK(check_openssl_TLS_METHODS) +]) + +dnl Checks whether the -lcrypto library provides various OpenSSL API functions +AC_DEFUN([SQUID_CHECK_LIBCRYPTO_API],[ + AH_TEMPLATE(HAVE_LIBCRYPTO_EVP_PKEY_GET0_RSA, "Define to 1 if the EVP_PKEY_get0_RSA() OpenSSL API function exists") + AH_TEMPLATE(HAVE_LIBCRYPTO_BIO_METH_NEW, "Define to 1 if the BIO_meth_new() OpenSSL API function exists") + AH_TEMPLATE(HAVE_LIBCRYPTO_BIO_GET_INIT, "Define to 1 if the BIO_get_init() OpenSSL API function exists") + AH_TEMPLATE(HAVE_LIBCRYPTO_ASN1_STRING_GET0_DATA, "Define to 1 if the ASN1_STRING_get0_data() OpenSSL API function exists") + AH_TEMPLATE(HAVE_LIBCRYPTO_X509_STORE_CTX_GET0_CERT, "Define to 1 if the X509_STORE_CTX_get0_cert() OpenSSL API function exists") + AH_TEMPLATE(HAVE_LIBCRYPTO_X509_VERIFY_PARAM_GET_DEPTH, "Define to 1 if the X509_VERIFY_PARAM_get_depth() OpenSSL API function exists") + AH_TEMPLATE(HAVE_LIBCRYPTO_X509_STORE_CTX_GET0_UNTRUSTED, "Define to 1 if the X509_STORE_CTX_get0_untrusted() OpenSSL API function exists") + AH_TEMPLATE(HAVE_LIBCRYPTO_X509_STORE_CTX_SET0_UNTRUSTED, "Define to 1 if the X509_STORE_CTX_set0_untrusted() OpenSSL API function exists") + AH_TEMPLATE(HAVE_LIBCRYPTO_X509_UP_REF, "Define to 1 if the X509_up_ref() OpenSSL API function exists") + AH_TEMPLATE(HAVE_LIBCRYPTO_X509_CRL_UP_REF, "Define to 1 if the X509_CRL_up_ref() OpenSSL API function exists") + AH_TEMPLATE(HAVE_LIBCRYPTO_DH_UP_REF, "Define to 1 if the DH_up_ref() OpenSSL API function exists") + SQUID_STATE_SAVE(check_openssl_libcrypto_api) + LIBS="$LIBS $SSLLIB" + AC_CHECK_LIB(crypto, EVP_PKEY_get0_RSA, AC_DEFINE(HAVE_LIBCRYPTO_EVP_PKEY_GET0_RSA, 1)) + AC_CHECK_LIB(crypto, BIO_meth_new, AC_DEFINE(HAVE_LIBCRYPTO_BIO_METH_NEW, 1)) + AC_CHECK_LIB(crypto, BIO_get_init, AC_DEFINE(HAVE_LIBCRYPTO_BIO_GET_INIT, 1)) + AC_CHECK_LIB(crypto, ASN1_STRING_get0_data, AC_DEFINE(HAVE_LIBCRYPTO_ASN1_STRING_GET0_DATA, 1)) + AC_CHECK_LIB(crypto, X509_STORE_CTX_get0_cert, AC_DEFINE(HAVE_LIBCRYPTO_X509_STORE_CTX_GET0_CERT, 1)) + AC_CHECK_LIB(crypto, X509_VERIFY_PARAM_get_depth, AC_DEFINE(HAVE_LIBCRYPTO_X509_VERIFY_PARAM_GET_DEPTH, 1)) + AC_CHECK_LIB(crypto, X509_STORE_CTX_get0_untrusted, AC_DEFINE(HAVE_LIBCRYPTO_X509_STORE_CTX_GET0_UNTRUSTED, 1)) + AC_CHECK_LIB(crypto, X509_STORE_CTX_set0_untrusted, AC_DEFINE(HAVE_LIBCRYPTO_X509_STORE_CTX_SET0_UNTRUSTED, 1)) + AC_CHECK_LIB(crypto, X509_up_ref, AC_DEFINE(HAVE_LIBCRYPTO_X509_UP_REF, 1)) + AC_CHECK_LIB(crypto, X509_CRL_up_ref, AC_DEFINE(HAVE_LIBCRYPTO_X509_CRL_UP_REF, 1)) + AC_CHECK_LIB(crypto, DH_up_ref, AC_DEFINE(HAVE_LIBCRYPTO_DH_UP_REF, 1)) + SQUID_STATE_ROLLBACK(check_openssl_libcrypto_api) +]) + +dnl Checks whether the -lssl library provides various OpenSSL API functions +AC_DEFUN([SQUID_CHECK_LIBSSL_API],[ + AH_TEMPLATE(HAVE_LIBSSL_SSL_CIPHER_FIND, "Define to 1 if the SSL_CIPHER_find() OpenSSL API function exists") + AH_TEMPLATE(HAVE_LIBSSL_SSL_CTX_SET_TMP_RSA_CALLBACK, "Define to 1 if the SSL_CTX_set_tmp_rsa_callback() OpenSSL API function exists") + AH_TEMPLATE(HAVE_LIBSSL_SSL_SESSION_GET_ID, "Define to 1 if the SSL_SESSION_get_id() OpenSSL API function exists") + SQUID_STATE_SAVE(check_openssl_libssl_api) + LIBS="$LIBS $SSLLIB" + AC_CHECK_LIB(ssl, SSL_CIPHER_find, AC_DEFINE(HAVE_LIBSSL_SSL_CIPHER_FIND, 1)) + AC_CHECK_LIB(ssl, SSL_CTX_set_tmp_rsa_callback, AC_DEFINE(HAVE_LIBSSL_SSL_CTX_SET_TMP_RSA_CALLBACK, 1)) + AC_CHECK_LIB(ssl, SSL_SESSION_get_id, AC_DEFINE(HAVE_LIBSSL_SSL_SESSION_GET_ID, 1)) + SQUID_STATE_ROLLBACK(check_openssl_libssl_api) +]) + dnl Checks whether the OpenSSL SSL_get_certificate crashes squid and if a dnl workaround can be used instead of using the SSL_get_certificate AC_DEFUN([SQUID_CHECK_OPENSSL_GETCERTIFICATE_WORKS],[ @@ -66,7 +121,7 @@ ], [ SSLeay_add_ssl_algorithms(); -#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) +#if HAVE_OPENSSL_TLS_METHOD SSL_CTX *sslContext = SSL_CTX_new(TLS_method()); #else SSL_CTX *sslContext = SSL_CTX_new(SSLv23_method()); @@ -97,7 +152,7 @@ ], [ SSLeay_add_ssl_algorithms(); -#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) +#if HAVE_OPENSSL_TLS_METHOD SSL_CTX *sslContext = SSL_CTX_new(TLS_method()); #else SSL_CTX *sslContext = SSL_CTX_new(SSLv23_method()); @@ -153,8 +208,54 @@ []) SQUID_STATE_ROLLBACK(check_const_SSL_METHOD) -] -) +]) + +dnl Checks whether the CRYPTO_EX_DATA duplication callback for SSL_get_ex_new_index() has a const argument +AC_DEFUN([SQUID_CHECK_OPENSSL_CONST_CRYPTO_EX_DATA],[ + AH_TEMPLATE(SQUID_USE_CONST_CRYPTO_EX_DATA_DUP, "Define to 1 if the SSL_get_new_ex_index() dup callback accepts 'const CRYPTO_EX_DATA *'") + SQUID_STATE_SAVE(check_const_CRYPTO_EX_DATA) + AC_MSG_CHECKING(whether SSL_get_new_ex_index() dup callback accepts 'const CRYPTO_EX_DATA *'") + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ +#include + +int const_dup_func(CRYPTO_EX_DATA *, const CRYPTO_EX_DATA *, void *, int, long, void *) { + return 0; +} + ],[ +return SSL_get_ex_new_index(0, (void*)"foo", NULL, &const_dup_func, NULL); + ]) + ],[ + AC_DEFINE(SQUID_USE_CONST_CRYPTO_EX_DATA_DUP, 1) + AC_MSG_RESULT([yes]) + ],[ + AC_MSG_RESULT([no]) + ]) + SQUID_STATE_ROLLBACK(check_const_CRYPTO_EX_DATA) +]) + +dnl Checks whether the callback for SSL_CTX_sess_set_get_cb() accepts a const ID argument +AC_DEFUN([SQUID_CHECK_OPENSSL_CONST_SSL_SESSION_CB_ARG],[ + AH_TEMPLATE(SQUID_USE_CONST_SSL_SESSION_CBID, "Define to 1 if the SSL_CTX_sess_set_get_cb() callback accepts a const ID argument") + SQUID_STATE_SAVE(check_const_SSL_CTX_sess_set_get_cb) + AC_MSG_CHECKING(whether SSL_CTX_sess_set_get_cb() callback accepts a const ID argument") + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ +#include + +SSL_SESSION *get_session_cb(SSL *, const unsigned char *ID, int, int *) { + return NULL; +} + ],[ +SSL_CTX_sess_set_get_cb(NULL, get_session_cb); +return 0; + ]) + ],[ + AC_DEFINE(SQUID_USE_CONST_SSL_SESSION_CBID, 1) + AC_MSG_RESULT([yes]) + ],[ + AC_MSG_RESULT([no]) + ]) + SQUID_STATE_ROLLBACK(check_const_SSL_CTX_sess_set_get_cb) +]) dnl Try to handle TXT_DB related problems: dnl 1) The type of TXT_DB::data member changed in openSSL-1.0.1 version diff -u -r -N squid-4.0.19/ChangeLog squid-4.0.20/ChangeLog --- squid-4.0.19/ChangeLog 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/ChangeLog 2017-06-02 00:49:17.000000000 +1200 @@ -1,3 +1,23 @@ +Changes to squid-4.0.20 (01 Jun 2017): + + - Bug #4692: SslBump breaks intercepted IPv6 connections + - Bug #4682: ignoring http_access deny when client-first bumping mode is used + - Bug #4662: build errors with LibreSSL 2.4.4 + - Bug #4659: sslproxy_foreign_intermediate_certs does not work + - Bug #4321: ssl_bump terminate does not terminate at step1 + - Add 'has' ACL + - Do not forward HTTP requests to dead idle peers + - Do not unconditionally revive dead peers after a DNS refresh + - Make PID file check/creation atomic to avoid associated race conditions + - Count failures and use peer-specific connect timeouts when tunneling + - SSL-Bump: Fix crashes when server-first bumping mode is used with openSSL-1.1.0 + - eCAP: Fix empty header handling in Ecap::HeaderRep::hasAny() + - SSL-Bump: Second adaptation missing for CONNECTs + - ext_session_acl: cope with new logformat inputs + - ... and some documentation updates + - ... and some code stability fixes + - ... and all fixes from 3.5.25 + Changes to squid-4.0.19 (02 Apr 2017): - Bug 4674: delay_parameters for class 3 and 4 assertion failed @@ -285,6 +305,19 @@ - ... and many documentation changes - ... and much code cleanup and polishing +Changes to squid-3.5.26 (01 Jun 2017): + + - Bug 4711: SubjectAlternativeNames is missing in some generated certificates + - Bug 4695: squidpurge: GCC 7 build errors + - Bug 4682: ignoring http_access deny when client-first bumping mode is used + - Bug 4682: Fix ssl_bump "bump" action documentation + - Bug 4653: %st lies about tunneled traffic volumes + - Bug 4589: ssl_crtd: returning zero on failure + - Bug 3772: message from FTP server gets mangled + - Bug 3102: FTP directory listing drops fist character of file names + - Add OpenSSL library details to -v output + - ... and some documentatino updates + Changes to squid-3.5.25 (02 Apr 2017): - Bug 4688: various typo error(s) in man page(s) diff -u -r -N squid-4.0.19/compat/xstring.h squid-4.0.20/compat/xstring.h --- squid-4.0.19/compat/xstring.h 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/compat/xstring.h 2017-06-02 00:49:17.000000000 +1200 @@ -41,7 +41,10 @@ char *xstrncpy(char *dst, const char *src, size_t n); /** - * xstrndup() - same as strndup(3). Used for portability. + * xstrndup() - Somewhat similar(XXX) to strndup(3): Allocates up to n bytes, + * while strndup(3) copies up to n bytes and allocates up to n+1 bytes + * to fit the terminating character. Assumes s is 0-terminated (another XXX). + * * Never returns NULL; fatal on error. * * Sets errno to EINVAL if a NULL pointer or negative diff -u -r -N squid-4.0.19/configure squid-4.0.20/configure --- squid-4.0.19/configure 2017-04-02 19:46:37.000000000 +1200 +++ squid-4.0.20/configure 2017-06-02 01:01:44.000000000 +1200 @@ -1,7 +1,7 @@ #! /bin/sh # From configure.ac Revision. # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for Squid Web Proxy 4.0.19. +# Generated by GNU Autoconf 2.69 for Squid Web Proxy 4.0.20. # # Report bugs to . # @@ -595,8 +595,8 @@ # Identity of this package. PACKAGE_NAME='Squid Web Proxy' PACKAGE_TARNAME='squid' -PACKAGE_VERSION='4.0.19' -PACKAGE_STRING='Squid Web Proxy 4.0.19' +PACKAGE_VERSION='4.0.20' +PACKAGE_STRING='Squid Web Proxy 4.0.20' PACKAGE_BUGREPORT='http://bugs.squid-cache.org/' PACKAGE_URL='' @@ -1647,7 +1647,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures Squid Web Proxy 4.0.19 to adapt to many kinds of systems. +\`configure' configures Squid Web Proxy 4.0.20 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1718,7 +1718,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of Squid Web Proxy 4.0.19:";; + short | recursive ) echo "Configuration of Squid Web Proxy 4.0.20:";; esac cat <<\_ACEOF @@ -2147,7 +2147,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -Squid Web Proxy configure 4.0.19 +Squid Web Proxy configure 4.0.20 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -3251,7 +3251,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by Squid Web Proxy $as_me 4.0.19, which was +It was created by Squid Web Proxy $as_me 4.0.20, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -4118,7 +4118,7 @@ # Define the identity of the package. PACKAGE='squid' - VERSION='4.0.19' + VERSION='4.0.20' cat >>confdefs.h <<_ACEOF @@ -4674,6 +4674,16 @@ + + + + + + + + + + ## Copyright (C) 1996-2017 The Squid Software Foundation and contributors ## ## Squid software is distributed under GPLv2+ license and includes @@ -23910,7 +23920,962 @@ $as_echo "#define USE_OPENSSL 1" >>confdefs.h + # check for API functions + + + + + + + + + + + + + +# save state, key is check_openssl_libcrypto_api +check_openssl_libcrypto_api_CFLAGS="${CFLAGS}" +check_openssl_libcrypto_api_CXXFLAGS="${CXXFLAGS}" +check_openssl_libcrypto_api_LDFLAGS="${LDFLAGS}" +check_openssl_libcrypto_api_LIBS="${LIBS}" +check_openssl_libcrypto_api_CC="${CC}" +check_openssl_libcrypto_api_CXX="${CXX}" +check_openssl_libcrypto_api_CPPFLAGS="${CPPFLAGS}" +check_openssl_libcrypto_api_squid_saved_vars="" +for squid_util_var_tosave in $check_openssl_libcrypto_api_squid_saved_vars +do + squid_util_var_tosave2="check_openssl_libcrypto_api_${squid_util_var_tosave}" + eval "${squid_util_var_tosave2}=\"${squid_util_var_tosave}\"" +done + + LIBS="$LIBS $SSLLIB" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EVP_PKEY_get0_RSA in -lcrypto" >&5 +$as_echo_n "checking for EVP_PKEY_get0_RSA in -lcrypto... " >&6; } +if ${ac_cv_lib_crypto_EVP_PKEY_get0_RSA+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypto $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char EVP_PKEY_get0_RSA (); +int +main () +{ +return EVP_PKEY_get0_RSA (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_crypto_EVP_PKEY_get0_RSA=yes +else + ac_cv_lib_crypto_EVP_PKEY_get0_RSA=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_EVP_PKEY_get0_RSA" >&5 +$as_echo "$ac_cv_lib_crypto_EVP_PKEY_get0_RSA" >&6; } +if test "x$ac_cv_lib_crypto_EVP_PKEY_get0_RSA" = xyes; then : + $as_echo "#define HAVE_LIBCRYPTO_EVP_PKEY_GET0_RSA 1" >>confdefs.h + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BIO_meth_new in -lcrypto" >&5 +$as_echo_n "checking for BIO_meth_new in -lcrypto... " >&6; } +if ${ac_cv_lib_crypto_BIO_meth_new+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypto $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char BIO_meth_new (); +int +main () +{ +return BIO_meth_new (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_crypto_BIO_meth_new=yes +else + ac_cv_lib_crypto_BIO_meth_new=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_BIO_meth_new" >&5 +$as_echo "$ac_cv_lib_crypto_BIO_meth_new" >&6; } +if test "x$ac_cv_lib_crypto_BIO_meth_new" = xyes; then : + $as_echo "#define HAVE_LIBCRYPTO_BIO_METH_NEW 1" >>confdefs.h + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BIO_get_init in -lcrypto" >&5 +$as_echo_n "checking for BIO_get_init in -lcrypto... " >&6; } +if ${ac_cv_lib_crypto_BIO_get_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypto $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char BIO_get_init (); +int +main () +{ +return BIO_get_init (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_crypto_BIO_get_init=yes +else + ac_cv_lib_crypto_BIO_get_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_BIO_get_init" >&5 +$as_echo "$ac_cv_lib_crypto_BIO_get_init" >&6; } +if test "x$ac_cv_lib_crypto_BIO_get_init" = xyes; then : + $as_echo "#define HAVE_LIBCRYPTO_BIO_GET_INIT 1" >>confdefs.h + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ASN1_STRING_get0_data in -lcrypto" >&5 +$as_echo_n "checking for ASN1_STRING_get0_data in -lcrypto... " >&6; } +if ${ac_cv_lib_crypto_ASN1_STRING_get0_data+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypto $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ASN1_STRING_get0_data (); +int +main () +{ +return ASN1_STRING_get0_data (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_crypto_ASN1_STRING_get0_data=yes +else + ac_cv_lib_crypto_ASN1_STRING_get0_data=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_ASN1_STRING_get0_data" >&5 +$as_echo "$ac_cv_lib_crypto_ASN1_STRING_get0_data" >&6; } +if test "x$ac_cv_lib_crypto_ASN1_STRING_get0_data" = xyes; then : + $as_echo "#define HAVE_LIBCRYPTO_ASN1_STRING_GET0_DATA 1" >>confdefs.h + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X509_STORE_CTX_get0_cert in -lcrypto" >&5 +$as_echo_n "checking for X509_STORE_CTX_get0_cert in -lcrypto... " >&6; } +if ${ac_cv_lib_crypto_X509_STORE_CTX_get0_cert+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypto $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char X509_STORE_CTX_get0_cert (); +int +main () +{ +return X509_STORE_CTX_get0_cert (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_crypto_X509_STORE_CTX_get0_cert=yes +else + ac_cv_lib_crypto_X509_STORE_CTX_get0_cert=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_X509_STORE_CTX_get0_cert" >&5 +$as_echo "$ac_cv_lib_crypto_X509_STORE_CTX_get0_cert" >&6; } +if test "x$ac_cv_lib_crypto_X509_STORE_CTX_get0_cert" = xyes; then : + $as_echo "#define HAVE_LIBCRYPTO_X509_STORE_CTX_GET0_CERT 1" >>confdefs.h + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X509_VERIFY_PARAM_get_depth in -lcrypto" >&5 +$as_echo_n "checking for X509_VERIFY_PARAM_get_depth in -lcrypto... " >&6; } +if ${ac_cv_lib_crypto_X509_VERIFY_PARAM_get_depth+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypto $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char X509_VERIFY_PARAM_get_depth (); +int +main () +{ +return X509_VERIFY_PARAM_get_depth (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_crypto_X509_VERIFY_PARAM_get_depth=yes +else + ac_cv_lib_crypto_X509_VERIFY_PARAM_get_depth=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_X509_VERIFY_PARAM_get_depth" >&5 +$as_echo "$ac_cv_lib_crypto_X509_VERIFY_PARAM_get_depth" >&6; } +if test "x$ac_cv_lib_crypto_X509_VERIFY_PARAM_get_depth" = xyes; then : + $as_echo "#define HAVE_LIBCRYPTO_X509_VERIFY_PARAM_GET_DEPTH 1" >>confdefs.h + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X509_STORE_CTX_get0_untrusted in -lcrypto" >&5 +$as_echo_n "checking for X509_STORE_CTX_get0_untrusted in -lcrypto... " >&6; } +if ${ac_cv_lib_crypto_X509_STORE_CTX_get0_untrusted+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypto $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char X509_STORE_CTX_get0_untrusted (); +int +main () +{ +return X509_STORE_CTX_get0_untrusted (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_crypto_X509_STORE_CTX_get0_untrusted=yes +else + ac_cv_lib_crypto_X509_STORE_CTX_get0_untrusted=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_X509_STORE_CTX_get0_untrusted" >&5 +$as_echo "$ac_cv_lib_crypto_X509_STORE_CTX_get0_untrusted" >&6; } +if test "x$ac_cv_lib_crypto_X509_STORE_CTX_get0_untrusted" = xyes; then : + $as_echo "#define HAVE_LIBCRYPTO_X509_STORE_CTX_GET0_UNTRUSTED 1" >>confdefs.h + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X509_STORE_CTX_set0_untrusted in -lcrypto" >&5 +$as_echo_n "checking for X509_STORE_CTX_set0_untrusted in -lcrypto... " >&6; } +if ${ac_cv_lib_crypto_X509_STORE_CTX_set0_untrusted+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypto $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char X509_STORE_CTX_set0_untrusted (); +int +main () +{ +return X509_STORE_CTX_set0_untrusted (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_crypto_X509_STORE_CTX_set0_untrusted=yes +else + ac_cv_lib_crypto_X509_STORE_CTX_set0_untrusted=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_X509_STORE_CTX_set0_untrusted" >&5 +$as_echo "$ac_cv_lib_crypto_X509_STORE_CTX_set0_untrusted" >&6; } +if test "x$ac_cv_lib_crypto_X509_STORE_CTX_set0_untrusted" = xyes; then : + $as_echo "#define HAVE_LIBCRYPTO_X509_STORE_CTX_SET0_UNTRUSTED 1" >>confdefs.h + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X509_up_ref in -lcrypto" >&5 +$as_echo_n "checking for X509_up_ref in -lcrypto... " >&6; } +if ${ac_cv_lib_crypto_X509_up_ref+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypto $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char X509_up_ref (); +int +main () +{ +return X509_up_ref (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_crypto_X509_up_ref=yes +else + ac_cv_lib_crypto_X509_up_ref=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_X509_up_ref" >&5 +$as_echo "$ac_cv_lib_crypto_X509_up_ref" >&6; } +if test "x$ac_cv_lib_crypto_X509_up_ref" = xyes; then : + $as_echo "#define HAVE_LIBCRYPTO_X509_UP_REF 1" >>confdefs.h + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X509_CRL_up_ref in -lcrypto" >&5 +$as_echo_n "checking for X509_CRL_up_ref in -lcrypto... " >&6; } +if ${ac_cv_lib_crypto_X509_CRL_up_ref+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypto $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char X509_CRL_up_ref (); +int +main () +{ +return X509_CRL_up_ref (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_crypto_X509_CRL_up_ref=yes +else + ac_cv_lib_crypto_X509_CRL_up_ref=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_X509_CRL_up_ref" >&5 +$as_echo "$ac_cv_lib_crypto_X509_CRL_up_ref" >&6; } +if test "x$ac_cv_lib_crypto_X509_CRL_up_ref" = xyes; then : + $as_echo "#define HAVE_LIBCRYPTO_X509_CRL_UP_REF 1" >>confdefs.h + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DH_up_ref in -lcrypto" >&5 +$as_echo_n "checking for DH_up_ref in -lcrypto... " >&6; } +if ${ac_cv_lib_crypto_DH_up_ref+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypto $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char DH_up_ref (); +int +main () +{ +return DH_up_ref (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_crypto_DH_up_ref=yes +else + ac_cv_lib_crypto_DH_up_ref=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_DH_up_ref" >&5 +$as_echo "$ac_cv_lib_crypto_DH_up_ref" >&6; } +if test "x$ac_cv_lib_crypto_DH_up_ref" = xyes; then : + $as_echo "#define HAVE_LIBCRYPTO_DH_UP_REF 1" >>confdefs.h + +fi + + +# rollback state, key is check_openssl_libcrypto_api +CFLAGS="${check_openssl_libcrypto_api_CFLAGS}" +CXXFLAGS="${check_openssl_libcrypto_api_CXXFLAGS}" +LDFLAGS="${check_openssl_libcrypto_api_LDFLAGS}" +LIBS="${check_openssl_libcrypto_api_LIBS}" +CC="${check_openssl_libcrypto_api_CC}" +CXX="${check_openssl_libcrypto_api_CXX}" +CPPFLAGS="${check_openssl_libcrypto_api_CPPFLAGS}" +for squid_util_var_tosave in $check_openssl_libcrypto_api_squid_saved_vars +do + squid_util_var_tosave2="\$check_openssl_libcrypto_api_${squid_util_var_tosave}" + eval "$squid_util_var_tosave=\"${squid_util_var_tosave2}\"" +done + +# commit state, key is check_openssl_libcrypto_api +unset check_openssl_libcrypto_api_CFLAGS +unset check_openssl_libcrypto_api_CXXFLAGS +unset check_openssl_libcrypto_api_LDFLAGS +unset check_openssl_libcrypto_api_LIBS +unset check_openssl_libcrypto_api_CC +unset check_openssl_libcrypto_api_CXX +unset check_openssl_libcrypto_api_CPPFLAGS +for squid_util_var_tosave in $check_openssl_libcrypto_api_squid_saved_vars +do + unset ${squid_util_var_tosave} +done + + + + + + + + +# save state, key is check_openssl_libssl_api +check_openssl_libssl_api_CFLAGS="${CFLAGS}" +check_openssl_libssl_api_CXXFLAGS="${CXXFLAGS}" +check_openssl_libssl_api_LDFLAGS="${LDFLAGS}" +check_openssl_libssl_api_LIBS="${LIBS}" +check_openssl_libssl_api_CC="${CC}" +check_openssl_libssl_api_CXX="${CXX}" +check_openssl_libssl_api_CPPFLAGS="${CPPFLAGS}" +check_openssl_libssl_api_squid_saved_vars="" +for squid_util_var_tosave in $check_openssl_libssl_api_squid_saved_vars +do + squid_util_var_tosave2="check_openssl_libssl_api_${squid_util_var_tosave}" + eval "${squid_util_var_tosave2}=\"${squid_util_var_tosave}\"" +done + + LIBS="$LIBS $SSLLIB" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_CIPHER_find in -lssl" >&5 +$as_echo_n "checking for SSL_CIPHER_find in -lssl... " >&6; } +if ${ac_cv_lib_ssl_SSL_CIPHER_find+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lssl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char SSL_CIPHER_find (); +int +main () +{ +return SSL_CIPHER_find (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_ssl_SSL_CIPHER_find=yes +else + ac_cv_lib_ssl_SSL_CIPHER_find=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_SSL_CIPHER_find" >&5 +$as_echo "$ac_cv_lib_ssl_SSL_CIPHER_find" >&6; } +if test "x$ac_cv_lib_ssl_SSL_CIPHER_find" = xyes; then : + $as_echo "#define HAVE_LIBSSL_SSL_CIPHER_FIND 1" >>confdefs.h + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_CTX_set_tmp_rsa_callback in -lssl" >&5 +$as_echo_n "checking for SSL_CTX_set_tmp_rsa_callback in -lssl... " >&6; } +if ${ac_cv_lib_ssl_SSL_CTX_set_tmp_rsa_callback+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lssl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char SSL_CTX_set_tmp_rsa_callback (); +int +main () +{ +return SSL_CTX_set_tmp_rsa_callback (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_ssl_SSL_CTX_set_tmp_rsa_callback=yes +else + ac_cv_lib_ssl_SSL_CTX_set_tmp_rsa_callback=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_SSL_CTX_set_tmp_rsa_callback" >&5 +$as_echo "$ac_cv_lib_ssl_SSL_CTX_set_tmp_rsa_callback" >&6; } +if test "x$ac_cv_lib_ssl_SSL_CTX_set_tmp_rsa_callback" = xyes; then : + $as_echo "#define HAVE_LIBSSL_SSL_CTX_SET_TMP_RSA_CALLBACK 1" >>confdefs.h + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_SESSION_get_id in -lssl" >&5 +$as_echo_n "checking for SSL_SESSION_get_id in -lssl... " >&6; } +if ${ac_cv_lib_ssl_SSL_SESSION_get_id+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lssl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char SSL_SESSION_get_id (); +int +main () +{ +return SSL_SESSION_get_id (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_ssl_SSL_SESSION_get_id=yes +else + ac_cv_lib_ssl_SSL_SESSION_get_id=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_SSL_SESSION_get_id" >&5 +$as_echo "$ac_cv_lib_ssl_SSL_SESSION_get_id" >&6; } +if test "x$ac_cv_lib_ssl_SSL_SESSION_get_id" = xyes; then : + $as_echo "#define HAVE_LIBSSL_SSL_SESSION_GET_ID 1" >>confdefs.h + +fi + + +# rollback state, key is check_openssl_libssl_api +CFLAGS="${check_openssl_libssl_api_CFLAGS}" +CXXFLAGS="${check_openssl_libssl_api_CXXFLAGS}" +LDFLAGS="${check_openssl_libssl_api_LDFLAGS}" +LIBS="${check_openssl_libssl_api_LIBS}" +CC="${check_openssl_libssl_api_CC}" +CXX="${check_openssl_libssl_api_CXX}" +CPPFLAGS="${check_openssl_libssl_api_CPPFLAGS}" +for squid_util_var_tosave in $check_openssl_libssl_api_squid_saved_vars +do + squid_util_var_tosave2="\$check_openssl_libssl_api_${squid_util_var_tosave}" + eval "$squid_util_var_tosave=\"${squid_util_var_tosave2}\"" +done + +# commit state, key is check_openssl_libssl_api +unset check_openssl_libssl_api_CFLAGS +unset check_openssl_libssl_api_CXXFLAGS +unset check_openssl_libssl_api_LDFLAGS +unset check_openssl_libssl_api_LIBS +unset check_openssl_libssl_api_CC +unset check_openssl_libssl_api_CXX +unset check_openssl_libssl_api_CPPFLAGS +for squid_util_var_tosave in $check_openssl_libssl_api_squid_saved_vars +do + unset ${squid_util_var_tosave} +done + + + + + + + + +# save state, key is check_openssl_TLS_METHODS +check_openssl_TLS_METHODS_CFLAGS="${CFLAGS}" +check_openssl_TLS_METHODS_CXXFLAGS="${CXXFLAGS}" +check_openssl_TLS_METHODS_LDFLAGS="${LDFLAGS}" +check_openssl_TLS_METHODS_LIBS="${LIBS}" +check_openssl_TLS_METHODS_CC="${CC}" +check_openssl_TLS_METHODS_CXX="${CXX}" +check_openssl_TLS_METHODS_CPPFLAGS="${CPPFLAGS}" +check_openssl_TLS_METHODS_squid_saved_vars="" +for squid_util_var_tosave in $check_openssl_TLS_METHODS_squid_saved_vars +do + squid_util_var_tosave2="check_openssl_TLS_METHODS_${squid_util_var_tosave}" + eval "${squid_util_var_tosave2}=\"${squid_util_var_tosave}\"" +done + + LIBS="$LIBS $SSLLIB" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for TLS_method in -lssl" >&5 +$as_echo_n "checking for TLS_method in -lssl... " >&6; } +if ${ac_cv_lib_ssl_TLS_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lssl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char TLS_method (); +int +main () +{ +return TLS_method (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_ssl_TLS_method=yes +else + ac_cv_lib_ssl_TLS_method=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_TLS_method" >&5 +$as_echo "$ac_cv_lib_ssl_TLS_method" >&6; } +if test "x$ac_cv_lib_ssl_TLS_method" = xyes; then : + $as_echo "#define HAVE_OPENSSL_TLS_METHOD 1" >>confdefs.h + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for TLS_client_method in -lssl" >&5 +$as_echo_n "checking for TLS_client_method in -lssl... " >&6; } +if ${ac_cv_lib_ssl_TLS_client_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lssl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char TLS_client_method (); +int +main () +{ +return TLS_client_method (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_ssl_TLS_client_method=yes +else + ac_cv_lib_ssl_TLS_client_method=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_TLS_client_method" >&5 +$as_echo "$ac_cv_lib_ssl_TLS_client_method" >&6; } +if test "x$ac_cv_lib_ssl_TLS_client_method" = xyes; then : + $as_echo "#define HAVE_OPENSSL_TLS_CLIENT_METHOD 1" >>confdefs.h + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for TLS_server_method in -lssl" >&5 +$as_echo_n "checking for TLS_server_method in -lssl... " >&6; } +if ${ac_cv_lib_ssl_TLS_server_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lssl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char TLS_server_method (); +int +main () +{ +return TLS_server_method (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_ssl_TLS_server_method=yes +else + ac_cv_lib_ssl_TLS_server_method=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_TLS_server_method" >&5 +$as_echo "$ac_cv_lib_ssl_TLS_server_method" >&6; } +if test "x$ac_cv_lib_ssl_TLS_server_method" = xyes; then : + $as_echo "#define HAVE_OPENSSL_TLS_SERVER_METHOD 1" >>confdefs.h + +fi + + +# rollback state, key is check_openssl_TLS_METHODS +CFLAGS="${check_openssl_TLS_METHODS_CFLAGS}" +CXXFLAGS="${check_openssl_TLS_METHODS_CXXFLAGS}" +LDFLAGS="${check_openssl_TLS_METHODS_LDFLAGS}" +LIBS="${check_openssl_TLS_METHODS_LIBS}" +CC="${check_openssl_TLS_METHODS_CC}" +CXX="${check_openssl_TLS_METHODS_CXX}" +CPPFLAGS="${check_openssl_TLS_METHODS_CPPFLAGS}" +for squid_util_var_tosave in $check_openssl_TLS_METHODS_squid_saved_vars +do + squid_util_var_tosave2="\$check_openssl_TLS_METHODS_${squid_util_var_tosave}" + eval "$squid_util_var_tosave=\"${squid_util_var_tosave2}\"" +done + +# commit state, key is check_openssl_TLS_METHODS +unset check_openssl_TLS_METHODS_CFLAGS +unset check_openssl_TLS_METHODS_CXXFLAGS +unset check_openssl_TLS_METHODS_LDFLAGS +unset check_openssl_TLS_METHODS_LIBS +unset check_openssl_TLS_METHODS_CC +unset check_openssl_TLS_METHODS_CXX +unset check_openssl_TLS_METHODS_CPPFLAGS +for squid_util_var_tosave in $check_openssl_TLS_METHODS_squid_saved_vars +do + unset ${squid_util_var_tosave} +done + + + + +# save state, key is check_SSL_CTX_get0_certificate +check_SSL_CTX_get0_certificate_CFLAGS="${CFLAGS}" +check_SSL_CTX_get0_certificate_CXXFLAGS="${CXXFLAGS}" +check_SSL_CTX_get0_certificate_LDFLAGS="${LDFLAGS}" +check_SSL_CTX_get0_certificate_LIBS="${LIBS}" +check_SSL_CTX_get0_certificate_CC="${CC}" +check_SSL_CTX_get0_certificate_CXX="${CXX}" +check_SSL_CTX_get0_certificate_CPPFLAGS="${CPPFLAGS}" +check_SSL_CTX_get0_certificate_squid_saved_vars="" +for squid_util_var_tosave in $check_SSL_CTX_get0_certificate_squid_saved_vars +do + squid_util_var_tosave2="check_SSL_CTX_get0_certificate_${squid_util_var_tosave}" + eval "${squid_util_var_tosave2}=\"${squid_util_var_tosave}\"" +done + + LIBS="$LIBS $SSLLIB" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_CTX_get0_certificate in -lssl" >&5 +$as_echo_n "checking for SSL_CTX_get0_certificate in -lssl... " >&6; } +if ${ac_cv_lib_ssl_SSL_CTX_get0_certificate+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lssl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char SSL_CTX_get0_certificate (); +int +main () +{ +return SSL_CTX_get0_certificate (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_ssl_SSL_CTX_get0_certificate=yes +else + ac_cv_lib_ssl_SSL_CTX_get0_certificate=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_SSL_CTX_get0_certificate" >&5 +$as_echo "$ac_cv_lib_ssl_SSL_CTX_get0_certificate" >&6; } +if test "x$ac_cv_lib_ssl_SSL_CTX_get0_certificate" = xyes; then : + + +$as_echo "#define HAVE_SSL_CTX_GET0_CERTIFICATE 1" >>confdefs.h + + +else + + missing_SSL_CTX_get0_certificate=yes + +fi + + +# rollback state, key is check_SSL_CTX_get0_certificate +CFLAGS="${check_SSL_CTX_get0_certificate_CFLAGS}" +CXXFLAGS="${check_SSL_CTX_get0_certificate_CXXFLAGS}" +LDFLAGS="${check_SSL_CTX_get0_certificate_LDFLAGS}" +LIBS="${check_SSL_CTX_get0_certificate_LIBS}" +CC="${check_SSL_CTX_get0_certificate_CC}" +CXX="${check_SSL_CTX_get0_certificate_CXX}" +CPPFLAGS="${check_SSL_CTX_get0_certificate_CPPFLAGS}" +for squid_util_var_tosave in $check_SSL_CTX_get0_certificate_squid_saved_vars +do + squid_util_var_tosave2="\$check_SSL_CTX_get0_certificate_${squid_util_var_tosave}" + eval "$squid_util_var_tosave=\"${squid_util_var_tosave2}\"" +done + +# commit state, key is check_SSL_CTX_get0_certificate +unset check_SSL_CTX_get0_certificate_CFLAGS +unset check_SSL_CTX_get0_certificate_CXXFLAGS +unset check_SSL_CTX_get0_certificate_LDFLAGS +unset check_SSL_CTX_get0_certificate_LIBS +unset check_SSL_CTX_get0_certificate_CC +unset check_SSL_CTX_get0_certificate_CXX +unset check_SSL_CTX_get0_certificate_CPPFLAGS +for squid_util_var_tosave in $check_SSL_CTX_get0_certificate_squid_saved_vars +do + unset ${squid_util_var_tosave} +done + + + # check for other specific broken implementations + if test "x$missing_SSL_CTX_get0_certificate" = "xyes"; then @@ -23957,7 +24922,7 @@ { SSLeay_add_ssl_algorithms(); -#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) +#if HAVE_OPENSSL_TLS_METHOD SSL_CTX *sslContext = SSL_CTX_new(TLS_method()); #else SSL_CTX *sslContext = SSL_CTX_new(SSLv23_method()); @@ -24011,7 +24976,7 @@ { SSLeay_add_ssl_algorithms(); -#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) +#if HAVE_OPENSSL_TLS_METHOD SSL_CTX *sslContext = SSL_CTX_new(TLS_method()); #else SSL_CTX *sslContext = SSL_CTX_new(SSLv23_method()); @@ -24075,6 +25040,7 @@ + fi @@ -24164,6 +25130,174 @@ +# save state, key is check_const_CRYPTO_EX_DATA +check_const_CRYPTO_EX_DATA_CFLAGS="${CFLAGS}" +check_const_CRYPTO_EX_DATA_CXXFLAGS="${CXXFLAGS}" +check_const_CRYPTO_EX_DATA_LDFLAGS="${LDFLAGS}" +check_const_CRYPTO_EX_DATA_LIBS="${LIBS}" +check_const_CRYPTO_EX_DATA_CC="${CC}" +check_const_CRYPTO_EX_DATA_CXX="${CXX}" +check_const_CRYPTO_EX_DATA_CPPFLAGS="${CPPFLAGS}" +check_const_CRYPTO_EX_DATA_squid_saved_vars="" +for squid_util_var_tosave in $check_const_CRYPTO_EX_DATA_squid_saved_vars +do + squid_util_var_tosave2="check_const_CRYPTO_EX_DATA_${squid_util_var_tosave}" + eval "${squid_util_var_tosave2}=\"${squid_util_var_tosave}\"" +done + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether SSL_get_new_ex_index() dup callback accepts 'const CRYPTO_EX_DATA *'\"" >&5 +$as_echo_n "checking whether SSL_get_new_ex_index() dup callback accepts 'const CRYPTO_EX_DATA *'\"... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include + +int const_dup_func(CRYPTO_EX_DATA *, const CRYPTO_EX_DATA *, void *, int, long, void *) { + return 0; +} + +int +main () +{ + +return SSL_get_ex_new_index(0, (void*)"foo", NULL, &const_dup_func, NULL); + + ; + return 0; +} + +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + + $as_echo "#define SQUID_USE_CONST_CRYPTO_EX_DATA_DUP 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +# rollback state, key is check_const_CRYPTO_EX_DATA +CFLAGS="${check_const_CRYPTO_EX_DATA_CFLAGS}" +CXXFLAGS="${check_const_CRYPTO_EX_DATA_CXXFLAGS}" +LDFLAGS="${check_const_CRYPTO_EX_DATA_LDFLAGS}" +LIBS="${check_const_CRYPTO_EX_DATA_LIBS}" +CC="${check_const_CRYPTO_EX_DATA_CC}" +CXX="${check_const_CRYPTO_EX_DATA_CXX}" +CPPFLAGS="${check_const_CRYPTO_EX_DATA_CPPFLAGS}" +for squid_util_var_tosave in $check_const_CRYPTO_EX_DATA_squid_saved_vars +do + squid_util_var_tosave2="\$check_const_CRYPTO_EX_DATA_${squid_util_var_tosave}" + eval "$squid_util_var_tosave=\"${squid_util_var_tosave2}\"" +done + +# commit state, key is check_const_CRYPTO_EX_DATA +unset check_const_CRYPTO_EX_DATA_CFLAGS +unset check_const_CRYPTO_EX_DATA_CXXFLAGS +unset check_const_CRYPTO_EX_DATA_LDFLAGS +unset check_const_CRYPTO_EX_DATA_LIBS +unset check_const_CRYPTO_EX_DATA_CC +unset check_const_CRYPTO_EX_DATA_CXX +unset check_const_CRYPTO_EX_DATA_CPPFLAGS +for squid_util_var_tosave in $check_const_CRYPTO_EX_DATA_squid_saved_vars +do + unset ${squid_util_var_tosave} +done + + + + + + +# save state, key is check_const_SSL_CTX_sess_set_get_cb +check_const_SSL_CTX_sess_set_get_cb_CFLAGS="${CFLAGS}" +check_const_SSL_CTX_sess_set_get_cb_CXXFLAGS="${CXXFLAGS}" +check_const_SSL_CTX_sess_set_get_cb_LDFLAGS="${LDFLAGS}" +check_const_SSL_CTX_sess_set_get_cb_LIBS="${LIBS}" +check_const_SSL_CTX_sess_set_get_cb_CC="${CC}" +check_const_SSL_CTX_sess_set_get_cb_CXX="${CXX}" +check_const_SSL_CTX_sess_set_get_cb_CPPFLAGS="${CPPFLAGS}" +check_const_SSL_CTX_sess_set_get_cb_squid_saved_vars="" +for squid_util_var_tosave in $check_const_SSL_CTX_sess_set_get_cb_squid_saved_vars +do + squid_util_var_tosave2="check_const_SSL_CTX_sess_set_get_cb_${squid_util_var_tosave}" + eval "${squid_util_var_tosave2}=\"${squid_util_var_tosave}\"" +done + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether SSL_CTX_sess_set_get_cb() callback accepts a const ID argument\"" >&5 +$as_echo_n "checking whether SSL_CTX_sess_set_get_cb() callback accepts a const ID argument\"... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include + +SSL_SESSION *get_session_cb(SSL *, const unsigned char *ID, int, int *) { + return NULL; +} + +int +main () +{ + +SSL_CTX_sess_set_get_cb(NULL, get_session_cb); +return 0; + + ; + return 0; +} + +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + + $as_echo "#define SQUID_USE_CONST_SSL_SESSION_CBID 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +# rollback state, key is check_const_SSL_CTX_sess_set_get_cb +CFLAGS="${check_const_SSL_CTX_sess_set_get_cb_CFLAGS}" +CXXFLAGS="${check_const_SSL_CTX_sess_set_get_cb_CXXFLAGS}" +LDFLAGS="${check_const_SSL_CTX_sess_set_get_cb_LDFLAGS}" +LIBS="${check_const_SSL_CTX_sess_set_get_cb_LIBS}" +CC="${check_const_SSL_CTX_sess_set_get_cb_CC}" +CXX="${check_const_SSL_CTX_sess_set_get_cb_CXX}" +CPPFLAGS="${check_const_SSL_CTX_sess_set_get_cb_CPPFLAGS}" +for squid_util_var_tosave in $check_const_SSL_CTX_sess_set_get_cb_squid_saved_vars +do + squid_util_var_tosave2="\$check_const_SSL_CTX_sess_set_get_cb_${squid_util_var_tosave}" + eval "$squid_util_var_tosave=\"${squid_util_var_tosave2}\"" +done + +# commit state, key is check_const_SSL_CTX_sess_set_get_cb +unset check_const_SSL_CTX_sess_set_get_cb_CFLAGS +unset check_const_SSL_CTX_sess_set_get_cb_CXXFLAGS +unset check_const_SSL_CTX_sess_set_get_cb_LDFLAGS +unset check_const_SSL_CTX_sess_set_get_cb_LIBS +unset check_const_SSL_CTX_sess_set_get_cb_CC +unset check_const_SSL_CTX_sess_set_get_cb_CXX +unset check_const_SSL_CTX_sess_set_get_cb_CPPFLAGS +for squid_util_var_tosave in $check_const_SSL_CTX_sess_set_get_cb_squid_saved_vars +do + unset ${squid_util_var_tosave} +done + + + + + @@ -34652,15 +35786,23 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include +#include +int +main () +{ + DB *db = dbopen("/tmp", O_CREAT | O_RDWR, 0666, DB_BTREE, NULL); + + ; + return 0; +} _ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "dbopen" >/dev/null 2>&1; then : - BUILD_HELPER="time_quota" -fi -rm -f conftest* +if ac_fn_cxx_try_compile "$LINENO"; then : + + BUILD_HELPER="time_quota" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi @@ -42514,7 +43656,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by Squid Web Proxy $as_me 4.0.19, which was +This file was extended by Squid Web Proxy $as_me 4.0.20, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -42580,7 +43722,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -Squid Web Proxy config.status 4.0.19 +Squid Web Proxy config.status 4.0.20 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -u -r -N squid-4.0.19/configure.ac squid-4.0.20/configure.ac --- squid-4.0.19/configure.ac 2017-04-02 19:46:37.000000000 +1200 +++ squid-4.0.20/configure.ac 2017-06-02 01:01:44.000000000 +1200 @@ -5,7 +5,7 @@ ## Please see the COPYING and CONTRIBUTORS files for details. ## -AC_INIT([Squid Web Proxy],[4.0.19],[http://bugs.squid-cache.org/],[squid]) +AC_INIT([Squid Web Proxy],[4.0.20],[http://bugs.squid-cache.org/],[squid]) AC_PREREQ(2.61) AC_CONFIG_HEADERS([include/autoconf.h]) AC_CONFIG_AUX_DIR(cfgaux) @@ -1347,9 +1347,26 @@ SSLLIB="$LIBOPENSSL_PATH $LIBOPENSSL_LIBS $SSLLIB" AC_DEFINE(USE_OPENSSL,1,[OpenSSL support is available]) + # check for API functions + SQUID_CHECK_LIBCRYPTO_API + SQUID_CHECK_LIBSSL_API + SQUID_CHECK_OPENSSL_TLS_METHODS + SQUID_STATE_SAVE(check_SSL_CTX_get0_certificate) + LIBS="$LIBS $SSLLIB" + AC_CHECK_LIB(ssl, SSL_CTX_get0_certificate, [ + AC_DEFINE(HAVE_SSL_CTX_GET0_CERTIFICATE, 1, [SSL_CTX_get0_certificate is available]) + ], [ + missing_SSL_CTX_get0_certificate=yes + ]) + SQUID_STATE_ROLLBACK(check_SSL_CTX_get0_certificate) + # check for other specific broken implementations - SQUID_CHECK_OPENSSL_GETCERTIFICATE_WORKS + if test "x$missing_SSL_CTX_get0_certificate" = "xyes"; then + SQUID_CHECK_OPENSSL_GETCERTIFICATE_WORKS + fi SQUID_CHECK_OPENSSL_CONST_SSL_METHOD + SQUID_CHECK_OPENSSL_CONST_CRYPTO_EX_DATA + SQUID_CHECK_OPENSSL_CONST_SSL_SESSION_CB_ARG SQUID_CHECK_OPENSSL_TXTDB SQUID_CHECK_OPENSSL_HELLO_OVERWRITE_HACK fi diff -u -r -N squid-4.0.19/doc/release-notes/release-4.html squid-4.0.20/doc/release-notes/release-4.html --- squid-4.0.19/doc/release-notes/release-4.html 2017-04-02 23:47:27.000000000 +1200 +++ squid-4.0.20/doc/release-notes/release-4.html 2017-06-02 09:49:09.000000000 +1200 @@ -2,10 +2,10 @@ - Squid 4.0.19 release notes + Squid 4.0.20 release notes -

Squid 4.0.19 release notes

+

Squid 4.0.20 release notes

Squid Developers


@@ -62,7 +62,7 @@

1. Notice

-

The Squid Team are pleased to announce the release of Squid-4.0.19 for testing.

+

The Squid Team are pleased to announce the release of Squid-4.0.20 for testing.

This new release is available for download from http://www.squid-cache.org/Versions/v4/ or the mirrors.

@@ -340,6 +340,8 @@

New connections_encrypted type for matching transactions where all HTTP messages were received over TLS transport connections, including messages received from ICAP servers.

+

New has type for matching whether or not Squid is able to provide +certain sets of transaction state. For example HTTP reply headers.

auth_param

New parameter queue-size= to set the maximum number diff -u -r -N squid-4.0.19/include/autoconf.h.in squid-4.0.20/include/autoconf.h.in --- squid-4.0.19/include/autoconf.h.in 2017-04-02 19:44:46.000000000 +1200 +++ squid-4.0.20/include/autoconf.h.in 2017-06-02 00:51:15.000000000 +1200 @@ -492,6 +492,43 @@ /* Define to 1 if you have the `cap' library (-lcap). */ #undef HAVE_LIBCAP +/* "Define to 1 if the ASN1_STRING_get0_data() OpenSSL API function exists" */ +#undef HAVE_LIBCRYPTO_ASN1_STRING_GET0_DATA + +/* "Define to 1 if the BIO_get_init() OpenSSL API function exists" */ +#undef HAVE_LIBCRYPTO_BIO_GET_INIT + +/* "Define to 1 if the BIO_meth_new() OpenSSL API function exists" */ +#undef HAVE_LIBCRYPTO_BIO_METH_NEW + +/* "Define to 1 if the DH_up_ref() OpenSSL API function exists" */ +#undef HAVE_LIBCRYPTO_DH_UP_REF + +/* "Define to 1 if the EVP_PKEY_get0_RSA() OpenSSL API function exists" */ +#undef HAVE_LIBCRYPTO_EVP_PKEY_GET0_RSA + +/* "Define to 1 if the X509_CRL_up_ref() OpenSSL API function exists" */ +#undef HAVE_LIBCRYPTO_X509_CRL_UP_REF + +/* "Define to 1 if the X509_STORE_CTX_get0_cert() OpenSSL API function exists" + */ +#undef HAVE_LIBCRYPTO_X509_STORE_CTX_GET0_CERT + +/* "Define to 1 if the X509_STORE_CTX_get0_untrusted() OpenSSL API function + exists" */ +#undef HAVE_LIBCRYPTO_X509_STORE_CTX_GET0_UNTRUSTED + +/* "Define to 1 if the X509_STORE_CTX_set0_untrusted() OpenSSL API function + exists" */ +#undef HAVE_LIBCRYPTO_X509_STORE_CTX_SET0_UNTRUSTED + +/* "Define to 1 if the X509_up_ref() OpenSSL API function exists" */ +#undef HAVE_LIBCRYPTO_X509_UP_REF + +/* "Define to 1 if the X509_VERIFY_PARAM_get_depth() OpenSSL API function + exists" */ +#undef HAVE_LIBCRYPTO_X509_VERIFY_PARAM_GET_DEPTH + /* Define to 1 if you have the header file. */ #undef HAVE_LIBC_H @@ -521,6 +558,16 @@ header file. */ #undef HAVE_LIBNETFILTER_CONNTRACK_LIBNETFILTER_CONNTRACK_TCP_H +/* "Define to 1 if the SSL_CIPHER_find() OpenSSL API function exists" */ +#undef HAVE_LIBSSL_SSL_CIPHER_FIND + +/* "Define to 1 if the SSL_CTX_set_tmp_rsa_callback() OpenSSL API function + exists" */ +#undef HAVE_LIBSSL_SSL_CTX_SET_TMP_RSA_CALLBACK + +/* "Define to 1 if the SSL_SESSION_get_id() OpenSSL API function exists" */ +#undef HAVE_LIBSSL_SSL_SESSION_GET_ID + /* Define to 1 if you have the libxml2 library */ #undef HAVE_LIBXML2 @@ -717,6 +764,15 @@ /* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_SSL_H +/* "Define to 1 if the TLS_client_method() OpenSSL API function exists" */ +#undef HAVE_OPENSSL_TLS_CLIENT_METHOD + +/* "Define to 1 if the TLS_method() OpenSSL API function exists" */ +#undef HAVE_OPENSSL_TLS_METHOD + +/* "Define to 1 if the TLS_server_method() OpenSSL API function exists" */ +#undef HAVE_OPENSSL_TLS_SERVER_METHOD + /* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_TXT_DB_H @@ -887,6 +943,9 @@ /* SPNEGO support */ #undef HAVE_SPNEGO +/* SSL_CTX_get0_certificate is available */ +#undef HAVE_SSL_CTX_GET0_CERTIFICATE + /* Define if sockaddr_storage has field ss_len */ #undef HAVE_SS_LEN_IN_SS @@ -1312,10 +1371,18 @@ /* TCP send buffer size */ #undef SQUID_TCP_SO_SNDBUF +/* "Define to 1 if the SSL_get_new_ex_index() dup callback accepts 'const + CRYPTO_EX_DATA *'" */ +#undef SQUID_USE_CONST_CRYPTO_EX_DATA_DUP + /* "Define to 1 if the SSL_CTX_new and similar openSSL API functions require 'const SSL_METHOD *'" */ #undef SQUID_USE_CONST_SSL_METHOD +/* "Define to 1 if the SSL_CTX_sess_set_get_cb() callback accepts a const ID + argument" */ +#undef SQUID_USE_CONST_SSL_SESSION_CBID + /* "Define to 1 if hello message can be overwritten in SSL struct" */ #undef SQUID_USE_OPENSSL_HELLO_OVERWRITE_HACK diff -u -r -N squid-4.0.19/include/version.h squid-4.0.20/include/version.h --- squid-4.0.19/include/version.h 2017-04-02 19:46:37.000000000 +1200 +++ squid-4.0.20/include/version.h 2017-06-02 01:01:44.000000000 +1200 @@ -7,7 +7,7 @@ */ #ifndef SQUID_RELEASE_TIME -#define SQUID_RELEASE_TIME 1491119016 +#define SQUID_RELEASE_TIME 1496321346 #endif /* diff -u -r -N squid-4.0.19/RELEASENOTES.html squid-4.0.20/RELEASENOTES.html --- squid-4.0.19/RELEASENOTES.html 2017-04-02 23:47:27.000000000 +1200 +++ squid-4.0.20/RELEASENOTES.html 2017-06-02 09:49:09.000000000 +1200 @@ -2,10 +2,10 @@ - Squid 4.0.19 release notes + Squid 4.0.20 release notes -

Squid 4.0.19 release notes

+

Squid 4.0.20 release notes

Squid Developers


@@ -62,7 +62,7 @@

1. Notice

-

The Squid Team are pleased to announce the release of Squid-4.0.19 for testing.

+

The Squid Team are pleased to announce the release of Squid-4.0.20 for testing.

This new release is available for download from http://www.squid-cache.org/Versions/v4/ or the mirrors.

@@ -340,6 +340,8 @@

New connections_encrypted type for matching transactions where all HTTP messages were received over TLS transport connections, including messages received from ICAP servers.

+

New has type for matching whether or not Squid is able to provide +certain sets of transaction state. For example HTTP reply headers.

auth_param

New parameter queue-size= to set the maximum number diff -u -r -N squid-4.0.19/src/acl/external/delayer/ext_delayer_acl.8 squid-4.0.20/src/acl/external/delayer/ext_delayer_acl.8 --- squid-4.0.19/src/acl/external/delayer/ext_delayer_acl.8 2017-04-02 23:48:24.000000000 +1200 +++ squid-4.0.20/src/acl/external/delayer/ext_delayer_acl.8 2017-06-02 09:52:23.000000000 +1200 @@ -129,7 +129,7 @@ .\" ======================================================================== .\" .IX Title "EXT_DELAYER_ACL 8" -.TH EXT_DELAYER_ACL 8 "2017-04-02" "perl v5.24.1" "User Contributed Perl Documentation" +.TH EXT_DELAYER_ACL 8 "2017-06-01" "perl v5.24.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff -u -r -N squid-4.0.19/src/acl/external/file_userip/ext_file_userip_acl.8 squid-4.0.20/src/acl/external/file_userip/ext_file_userip_acl.8 --- squid-4.0.19/src/acl/external/file_userip/ext_file_userip_acl.8 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/acl/external/file_userip/ext_file_userip_acl.8 2017-06-02 00:49:17.000000000 +1200 @@ -68,7 +68,7 @@ .B ALL and .B NONE -, which mean \"any user on this IP address may authenticate\" or \"no user on this IP address may authenticate\". +, which mean \(dqany user on this IP address may authenticate\(dq or \(dqno user on this IP address may authenticate\(dq. . .SH AUTHOR This program was written by diff -u -r -N squid-4.0.19/src/acl/external/session/ext_session_acl.cc squid-4.0.20/src/acl/external/session/ext_session_acl.cc --- squid-4.0.19/src/acl/external/session/ext_session_acl.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/acl/external/session/ext_session_acl.cc 2017-06-02 00:49:17.000000000 +1200 @@ -210,6 +210,11 @@ action = -1; detail_len = (size_t)(lastdetail-detail); *lastdetail = '\0'; + } else if (!default_action && strcmp(lastdetail, " -") == 0) { + // no action; LOGIN/LOGOUT not supplied + // but truncate the '-' %DATA value given by Squid-4 and later + detail_len = (size_t)(lastdetail-detail); + *lastdetail = '\0'; } } if (action == -1) { diff -u -r -N squid-4.0.19/src/acl/external/SQL_session/ext_sql_session_acl.8 squid-4.0.20/src/acl/external/SQL_session/ext_sql_session_acl.8 --- squid-4.0.19/src/acl/external/SQL_session/ext_sql_session_acl.8 2017-04-02 23:48:36.000000000 +1200 +++ squid-4.0.20/src/acl/external/SQL_session/ext_sql_session_acl.8 2017-06-02 09:52:58.000000000 +1200 @@ -129,7 +129,7 @@ .\" ======================================================================== .\" .IX Title "EXT_SQL_SESSION_ACL 8" -.TH EXT_SQL_SESSION_ACL 8 "2017-04-02" "perl v5.24.1" "User Contributed Perl Documentation" +.TH EXT_SQL_SESSION_ACL 8 "2017-06-01" "perl v5.24.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff -u -r -N squid-4.0.19/src/acl/external/time_quota/required.m4 squid-4.0.20/src/acl/external/time_quota/required.m4 --- squid-4.0.19/src/acl/external/time_quota/required.m4 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/acl/external/time_quota/required.m4 2017-06-02 00:49:17.000000000 +1200 @@ -7,6 +7,10 @@ AC_CHECK_HEADERS(db_185.h,[BUILD_HELPER="time_quota"],[ AC_CHECK_HEADERS(db.h,[ - AC_EGREP_HEADER([dbopen],[/usr/include/db.h],[BUILD_HELPER="time_quota"]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]],[[ + DB *db = dbopen("/tmp", O_CREAT | O_RDWR, 0666, DB_BTREE, NULL); + ]])],[ + BUILD_HELPER="time_quota" + ],[]) ]) ]) diff -u -r -N squid-4.0.19/src/acl/external/wbinfo_group/ext_wbinfo_group_acl.8 squid-4.0.20/src/acl/external/wbinfo_group/ext_wbinfo_group_acl.8 --- squid-4.0.19/src/acl/external/wbinfo_group/ext_wbinfo_group_acl.8 2017-04-02 23:48:41.000000000 +1200 +++ squid-4.0.20/src/acl/external/wbinfo_group/ext_wbinfo_group_acl.8 2017-06-02 09:53:11.000000000 +1200 @@ -129,7 +129,7 @@ .\" ======================================================================== .\" .IX Title "EXT_WBINFO_GROUP_ACL 8" -.TH EXT_WBINFO_GROUP_ACL 8 "2017-04-02" "perl v5.24.1" "User Contributed Perl Documentation" +.TH EXT_WBINFO_GROUP_ACL 8 "2017-06-01" "perl v5.24.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff -u -r -N squid-4.0.19/src/acl/FilledChecklist.h squid-4.0.20/src/acl/FilledChecklist.h --- squid-4.0.19/src/acl/FilledChecklist.h 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/acl/FilledChecklist.h 2017-06-02 00:49:17.000000000 +1200 @@ -35,7 +35,7 @@ public: ACLFilledChecklist(); - ACLFilledChecklist(const acl_access *, HttpRequest *, const char *ident); + ACLFilledChecklist(const acl_access *, HttpRequest *, const char *ident = nullptr); ~ACLFilledChecklist(); public: diff -u -r -N squid-4.0.19/src/acl/HasComponent.cc squid-4.0.20/src/acl/HasComponent.cc --- squid-4.0.19/src/acl/HasComponent.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-4.0.20/src/acl/HasComponent.cc 2017-06-02 00:49:17.000000000 +1200 @@ -0,0 +1,28 @@ +/* + * Copyright (C) 1996-2017 The Squid Software Foundation and contributors + * + * Squid software is distributed under GPLv2+ license and includes + * contributions from numerous individuals and organizations. + * Please see the COPYING and CONTRIBUTORS files for details. + */ + +#include "squid.h" +#include "acl/HasComponent.h" +#include "acl/HasComponentData.h" + +int +ACLHasComponentStrategy::match(ACLData * &data, ACLFilledChecklist *checklist, ACLFlags &flags) +{ + ACLHasComponentData *cdata = dynamic_cast(data); + assert(cdata); + return cdata->match(checklist); +} + +ACLHasComponentStrategy * +ACLHasComponentStrategy::Instance() +{ + return &Instance_; +} + +ACLHasComponentStrategy ACLHasComponentStrategy::Instance_; + diff -u -r -N squid-4.0.19/src/acl/HasComponentData.cc squid-4.0.20/src/acl/HasComponentData.cc --- squid-4.0.19/src/acl/HasComponentData.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-4.0.20/src/acl/HasComponentData.cc 2017-06-02 00:49:17.000000000 +1200 @@ -0,0 +1,82 @@ +/* + * Copyright (C) 1996-2017 The Squid Software Foundation and contributors + * + * Squid software is distributed under GPLv2+ license and includes + * contributions from numerous individuals and organizations. + * Please see the COPYING and CONTRIBUTORS files for details. + */ + +#include "squid.h" +#include "acl/HasComponentData.h" +#include "cache_cf.h" +#include "ConfigParser.h" +#include "sbuf/Algorithms.h" + +const SBuf ACLHasComponentData::RequestStr("request"); +const SBuf ACLHasComponentData::ResponseStr("response"); +const SBuf ACLHasComponentData::AleStr("ALE"); + +ACLHasComponentData::ACLHasComponentData() + : componentMethods(coEnd, nullptr) +{ } + +void +ACLHasComponentData::parse() +{ + const char *tok = ConfigParser::NextToken(); + if (!tok) { + debugs(28, DBG_CRITICAL, "FATAL: \"has\" acl argument missing"); + self_destruct(); + return; + } + if (ConfigParser::PeekAtToken()) { + debugs(28, DBG_CRITICAL, "FATAL: multiple components not supported for \"has\" acl"); + self_destruct(); + return; + } + parseComponent(tok); +} + +bool +ACLHasComponentData::match(ACLChecklist *checklist) +{ + for (const auto method: componentMethods) + if (method && (checklist->*method)()) + return true; + return false; +} + +SBufList +ACLHasComponentData::dump() const +{ + SBufList sl; + if (componentMethods.at(coRequest)) + sl.push_back(RequestStr); + if (componentMethods.at(coResponse)) + sl.push_back(ResponseStr); + if (componentMethods.at(coAle)) + sl.push_back(AleStr); + return sl; +} + +void +ACLHasComponentData::parseComponent(const char *token) +{ + if (RequestStr.cmp(token) == 0) + componentMethods[coRequest] = &ACLChecklist::hasRequest; + else if (ResponseStr.cmp(token) == 0) + componentMethods[coResponse] = &ACLChecklist::hasReply; + else if (AleStr.cmp(token) == 0) + componentMethods[coAle] = &ACLChecklist::hasAle; + else { + debugs(28, DBG_CRITICAL, "FATAL: unsupported component '" << token << "' for 'has' acl"); + self_destruct(); + } +} + +ACLData * +ACLHasComponentData::clone() const +{ + return new ACLHasComponentData(*this); +} + diff -u -r -N squid-4.0.19/src/acl/HasComponentData.h squid-4.0.20/src/acl/HasComponentData.h --- squid-4.0.19/src/acl/HasComponentData.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-4.0.20/src/acl/HasComponentData.h 2017-06-02 00:49:17.000000000 +1200 @@ -0,0 +1,44 @@ +/* + * Copyright (C) 1996-2017 The Squid Software Foundation and contributors + * + * Squid software is distributed under GPLv2+ license and includes + * contributions from numerous individuals and organizations. + * Please see the COPYING and CONTRIBUTORS files for details. + */ + +#ifndef SQUID_ACLHASCOMPONENTDATA_H +#define SQUID_ACLHASCOMPONENTDATA_H + +#include "acl/Checklist.h" +#include "acl/Data.h" + +/// \ingroup ACLAPI +class ACLHasComponentData : public ACLData +{ + MEMPROXY_CLASS(ACLHasComponentData); + +public: + ACLHasComponentData(); + + /* ACLData API */ + virtual bool match(ACLChecklist *) override; + virtual SBufList dump() const override; + virtual void parse() override; + virtual bool empty() const override { return false; } + virtual ACLData *clone() const override; + +private: + enum ComponentKind { coRequest = 0, coResponse, coAle, coEnd }; + void parseComponent(const char *token); + + static const SBuf RequestStr; + static const SBuf ResponseStr; + static const SBuf AleStr; + + typedef bool (ACLChecklist::*ComponentCheck)() const; + /// component check callbacks, ordered by component kind ID + std::vector componentMethods; +}; + +#endif + diff -u -r -N squid-4.0.19/src/acl/HasComponent.h squid-4.0.20/src/acl/HasComponent.h --- squid-4.0.19/src/acl/HasComponent.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-4.0.20/src/acl/HasComponent.h 2017-06-02 00:49:17.000000000 +1200 @@ -0,0 +1,38 @@ +/* + * Copyright (C) 1996-2017 The Squid Software Foundation and contributors + * + * Squid software is distributed under GPLv2+ license and includes + * contributions from numerous individuals and organizations. + * Please see the COPYING and CONTRIBUTORS files for details. + */ + +#ifndef SQUID_ACLHASCOMPONENT_H +#define SQUID_ACLHASCOMPONENT_H + +#include "acl/Strategised.h" +#include "acl/Strategy.h" + +/// \ingroup ACLAPI +class ACLHasComponentStrategy : public ACLStrategy +{ +public: + static ACLHasComponentStrategy *Instance(); + ACLHasComponentStrategy(ACLHasComponentStrategy const &) = delete; + ACLHasComponentStrategy& operator=(ACLHasComponentStrategy const &) = delete; + virtual int match(ACLData * &, ACLFilledChecklist *, ACLFlags &); + +private: + static ACLHasComponentStrategy Instance_; + ACLHasComponentStrategy() { } +}; + +/// \ingroup ACLAPI +class ACLHasComponent +{ +private: + static ACL::Prototype RegistryProtoype; + static ACLStrategised RegistryEntry_; +}; + +#endif + diff -u -r -N squid-4.0.19/src/acl/HttpHeaderData.cc squid-4.0.20/src/acl/HttpHeaderData.cc --- squid-4.0.19/src/acl/HttpHeaderData.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/acl/HttpHeaderData.cc 2017-06-02 00:49:17.000000000 +1200 @@ -48,7 +48,7 @@ return false; value = hdr->getStrOrList(hdrId); } else { - if (!hdr->getByNameIfPresent(hdrName, value)) + if (!hdr->hasNamed(hdrName, &value)) return false; } diff -u -r -N squid-4.0.19/src/acl/Makefile.am squid-4.0.20/src/acl/Makefile.am --- squid-4.0.19/src/acl/Makefile.am 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/acl/Makefile.am 2017-06-02 00:49:17.000000000 +1200 @@ -69,6 +69,10 @@ DomainData.h \ ExtUser.cc \ ExtUser.h \ + HasComponent.cc \ + HasComponent.h \ + HasComponentData.cc \ + HasComponentData.h \ HierCodeData.cc \ HierCodeData.h \ HierCode.cc \ diff -u -r -N squid-4.0.19/src/acl/Makefile.in squid-4.0.20/src/acl/Makefile.in --- squid-4.0.19/src/acl/Makefile.in 2017-04-02 19:45:35.000000000 +1200 +++ squid-4.0.20/src/acl/Makefile.in 2017-06-02 00:54:27.000000000 +1200 @@ -173,8 +173,9 @@ ConnectionsEncrypted.h DestinationAsn.h DestinationDomain.cc \ DestinationDomain.h DestinationIp.cc DestinationIp.h \ DomainData.cc DomainData.h ExtUser.cc ExtUser.h \ - HierCodeData.cc HierCodeData.h HierCode.cc HierCode.h \ - HttpHeaderData.cc HttpHeaderData.h HttpRepHeader.cc \ + HasComponent.cc HasComponent.h HasComponentData.cc \ + HasComponentData.h HierCodeData.cc HierCodeData.h HierCode.cc \ + HierCode.h HttpHeaderData.cc HttpHeaderData.h HttpRepHeader.cc \ HttpRepHeader.h HttpReqHeader.cc HttpReqHeader.h HttpStatus.cc \ HttpStatus.h Ip.cc Ip.h LocalIp.cc LocalIp.h LocalPort.cc \ LocalPort.h MaxConnection.cc MaxConnection.h Method.cc \ @@ -208,12 +209,12 @@ am_libacls_la_OBJECTS = IntRange.lo RegexData.lo StringData.lo Time.lo \ TimeData.lo AllOf.lo AnyOf.lo Asn.lo Browser.lo \ ConnectionsEncrypted.lo DestinationDomain.lo DestinationIp.lo \ - DomainData.lo ExtUser.lo HierCodeData.lo HierCode.lo \ - HttpHeaderData.lo HttpRepHeader.lo HttpReqHeader.lo \ - HttpStatus.lo Ip.lo LocalIp.lo LocalPort.lo MaxConnection.lo \ - Method.lo MethodData.lo MyPortName.lo Note.lo NoteData.lo \ - PeerName.lo Protocol.lo ProtocolData.lo Random.lo Referer.lo \ - ReplyMimeType.lo RequestMimeType.lo SourceDomain.lo \ + DomainData.lo ExtUser.lo HasComponent.lo HasComponentData.lo \ + HierCodeData.lo HierCode.lo HttpHeaderData.lo HttpRepHeader.lo \ + HttpReqHeader.lo HttpStatus.lo Ip.lo LocalIp.lo LocalPort.lo \ + MaxConnection.lo Method.lo MethodData.lo MyPortName.lo Note.lo \ + NoteData.lo PeerName.lo Protocol.lo ProtocolData.lo Random.lo \ + Referer.lo ReplyMimeType.lo RequestMimeType.lo SourceDomain.lo \ SourceIp.lo SquidError.lo SquidErrorData.lo Tag.lo Url.lo \ UrlLogin.lo UrlPath.lo UrlPort.lo UserData.lo Gadgets.lo \ AclSizeLimit.lo $(am__objects_2) $(am__objects_4) \ @@ -848,8 +849,9 @@ ConnectionsEncrypted.h DestinationAsn.h DestinationDomain.cc \ DestinationDomain.h DestinationIp.cc DestinationIp.h \ DomainData.cc DomainData.h ExtUser.cc ExtUser.h \ - HierCodeData.cc HierCodeData.h HierCode.cc HierCode.h \ - HttpHeaderData.cc HttpHeaderData.h HttpRepHeader.cc \ + HasComponent.cc HasComponent.h HasComponentData.cc \ + HasComponentData.h HierCodeData.cc HierCodeData.h HierCode.cc \ + HierCode.h HttpHeaderData.cc HttpHeaderData.h HttpRepHeader.cc \ HttpRepHeader.h HttpReqHeader.cc HttpReqHeader.h HttpStatus.cc \ HttpStatus.h Ip.cc Ip.h LocalIp.cc LocalIp.h LocalPort.cc \ LocalPort.h MaxConnection.cc MaxConnection.h Method.cc \ @@ -986,6 +988,8 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ExtUser.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FilledChecklist.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Gadgets.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HasComponent.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HasComponentData.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HierCode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HierCodeData.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpHeaderData.Plo@am__quote@ diff -u -r -N squid-4.0.19/src/AclRegs.cc squid-4.0.20/src/AclRegs.cc --- squid-4.0.19/src/AclRegs.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/AclRegs.cc 2017-06-02 00:49:17.000000000 +1200 @@ -41,6 +41,8 @@ #endif #include "acl/FilledChecklist.h" #include "acl/Gadgets.h" +#include "acl/HasComponent.h" +#include "acl/HasComponentData.h" #include "acl/HierCode.h" #include "acl/HierCodeData.h" #include "acl/HttpHeaderData.h" @@ -235,3 +237,6 @@ ACL::Prototype Acl::ConnectionsEncrypted::RegistryProtoype(&Acl::ConnectionsEncrypted::RegistryEntry_, "connections_encrypted"); Acl::ConnectionsEncrypted Acl::ConnectionsEncrypted::RegistryEntry_("connections_encrypted"); +ACL::Prototype ACLHasComponent::RegistryProtoype(&ACLHasComponent::RegistryEntry_, "has"); +ACLStrategised ACLHasComponent::RegistryEntry_(new ACLHasComponentData, ACLHasComponentStrategy::Instance(), "has"); + diff -u -r -N squid-4.0.19/src/adaptation/ecap/MessageRep.cc squid-4.0.20/src/adaptation/ecap/MessageRep.cc --- squid-4.0.19/src/adaptation/ecap/MessageRep.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/adaptation/ecap/MessageRep.cc 2017-06-02 00:49:17.000000000 +1200 @@ -33,10 +33,9 @@ Adaptation::Ecap::HeaderRep::hasAny(const Name &name) const { const Http::HdrType squidId = TranslateHeaderId(name); - // XXX: optimize to remove getByName: we do not need the value here return squidId == Http::HdrType::OTHER ? - theHeader.getByName(name.image().c_str()).size() > 0: - (bool)theHeader.has(squidId); + theHeader.hasNamed(name.image().c_str(), name.image().size()) : + static_cast(theHeader.has(squidId)); } Adaptation::Ecap::HeaderRep::Value diff -u -r -N squid-4.0.19/src/auth/basic/DB/basic_db_auth.8 squid-4.0.20/src/auth/basic/DB/basic_db_auth.8 --- squid-4.0.19/src/auth/basic/DB/basic_db_auth.8 2017-04-02 23:49:15.000000000 +1200 +++ squid-4.0.20/src/auth/basic/DB/basic_db_auth.8 2017-06-02 09:55:21.000000000 +1200 @@ -129,7 +129,7 @@ .\" ======================================================================== .\" .IX Title "BASIC_DB_AUTH 8" -.TH BASIC_DB_AUTH 8 "2017-04-02" "perl v5.24.1" "User Contributed Perl Documentation" +.TH BASIC_DB_AUTH 8 "2017-06-01" "perl v5.24.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff -u -r -N squid-4.0.19/src/auth/basic/LDAP/basic_ldap_auth.8 squid-4.0.20/src/auth/basic/LDAP/basic_ldap_auth.8 --- squid-4.0.19/src/auth/basic/LDAP/basic_ldap_auth.8 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/auth/basic/LDAP/basic_ldap_auth.8 2017-06-02 00:49:17.000000000 +1200 @@ -5,9 +5,9 @@ . .SH SYNOPSIS .if !'po4a'hide' .B basic_ldap_auth -.if !'po4a'hide' .B \-b\ \" +.if !'po4a'hide' .B \-b\ \(dq base DN -.if !'po4a'hide' .B \"\ [\-u +.if !'po4a'hide' .B \(dq\ [\-u attribute .if !'po4a'hide' .B ]\ [ options @@ -20,11 +20,11 @@ .if !'po4a'hide' .B ]... .br .if !'po4a'hide' .B basic_ldap_auth -.if !'po4a'hide' .B \-b\ \" +.if !'po4a'hide' .B \-b\ \(dq base DN -.if !'po4a'hide' .B \"\ \-f\ \" +.if !'po4a'hide' .B \(dq\ \-f\ \(dq LDAP search filter -.if !'po4a'hide' .B \"\ [ +.if !'po4a'hide' .B \(dq\ [ options .if !'po4a'hide' .B ]\ [ LDAP server name @@ -74,7 +74,7 @@ The search filter can contain up to 15 occurrences of .B %s which will be replaced by the username, as in -.B "\"uid\=%s\"" +.B "\(dquid\=%s\(dq" for RFC2037 directories. For a detailed description of LDAP search filter syntax see RFC2254. .br diff -u -r -N squid-4.0.19/src/auth/basic/POP3/basic_pop3_auth.8 squid-4.0.20/src/auth/basic/POP3/basic_pop3_auth.8 --- squid-4.0.19/src/auth/basic/POP3/basic_pop3_auth.8 2017-04-02 23:49:25.000000000 +1200 +++ squid-4.0.20/src/auth/basic/POP3/basic_pop3_auth.8 2017-06-02 09:56:01.000000000 +1200 @@ -129,7 +129,7 @@ .\" ======================================================================== .\" .IX Title "BASIC_POP3_AUTH 8" -.TH BASIC_POP3_AUTH 8 "2017-04-02" "perl v5.24.1" "User Contributed Perl Documentation" +.TH BASIC_POP3_AUTH 8 "2017-06-01" "perl v5.24.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff -u -r -N squid-4.0.19/src/auth/basic/RADIUS/basic_radius_auth.8 squid-4.0.20/src/auth/basic/RADIUS/basic_radius_auth.8 --- squid-4.0.19/src/auth/basic/RADIUS/basic_radius_auth.8 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/auth/basic/RADIUS/basic_radius_auth.8 2017-06-02 00:49:17.000000000 +1200 @@ -9,9 +9,9 @@ config file .br .if !'po4a'hide' .B basic_radius_auth -.if !'po4a'hide' .B "\-h \"" +.if !'po4a'hide' .B "\-h \(dq" server name -.if !'po4a'hide' .B "\" [\-p " +.if !'po4a'hide' .B "\(dq [\-p " port .if !'po4a'hide' .B "] [\-i " identifier diff -u -r -N squid-4.0.19/src/base/File.cc squid-4.0.20/src/base/File.cc --- squid-4.0.19/src/base/File.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-4.0.20/src/base/File.cc 2017-06-02 00:49:17.000000000 +1200 @@ -0,0 +1,374 @@ +/* + * Copyright (C) 1996-2017 The Squid Software Foundation and contributors + * + * Squid software is distributed under GPLv2+ license and includes + * contributions from numerous individuals and organizations. + * Please see the COPYING and CONTRIBUTORS files for details. + */ + +#include "squid.h" +#include "base/File.h" +#include "Debug.h" +#include "sbuf/Stream.h" +#include "tools.h" +#include "xusleep.h" + +#include + +#if HAVE_FCNTL_H +#include +#endif +#if HAVE_SYS_FILE_H +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif + +/* FileOpeningConfig */ + +FileOpeningConfig +FileOpeningConfig::ReadOnly() +{ + FileOpeningConfig cfg; + + /* I/O */ +#if _SQUID_WINDOWS_ + cfg.desiredAccess = GENERIC_READ; + cfg.shareMode = FILE_SHARE_READ; +#else + cfg.openFlags = O_RDONLY; +#endif + + /* locking (if enabled later) */ +#if _SQUID_WINDOWS_ + cfg.lockFlags = 0; // no named constant for a shared lock +#elif _SQUID_SOLARIS_ + cfg.lockType = F_RDLCK; +#else + cfg.flockMode = LOCK_SH | LOCK_NB; +#endif + + return cfg; +} + +FileOpeningConfig +FileOpeningConfig::ReadWrite() +{ + FileOpeningConfig cfg; + + /* I/O */ +#if _SQUID_WINDOWS_ + cfg.desiredAccess = GENERIC_READ | GENERIC_WRITE; + cfg.shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; +#else + cfg.openFlags = O_RDWR; +#endif + + /* locking (if enabled later) */ +#if _SQUID_WINDOWS_ + cfg.lockFlags = LOCKFILE_EXCLUSIVE_LOCK; +#elif _SQUID_SOLARIS_ + cfg.lockType = F_WRLCK; +#else + cfg.flockMode = LOCK_EX | LOCK_NB; +#endif + + return cfg; +} + +FileOpeningConfig & +FileOpeningConfig::locked(unsigned int attempts) +{ + lockAttempts = attempts; + // for simplicity, correct locking flags are preset in constructing methods + return *this; +} + +FileOpeningConfig & +FileOpeningConfig::createdIfMissing() +{ +#if _SQUID_WINDOWS_ + Must((desiredAccess & GENERIC_WRITE) == GENERIC_WRITE); + creationDisposition = OPEN_ALWAYS; +#else + Must((openFlags & O_RDWR) == O_RDWR); + openFlags |= O_CREAT; + creationMask = (S_IXUSR | S_IXGRP|S_IWGRP | S_IXOTH|S_IWOTH); // unwanted bits +#endif + return *this; +} + +/* File */ + +#if _SQUID_SOLARIS_ +// XXX: fcntl() locks are incompatible with complex applications that may lock +// multiple open descriptors corresponding to the same underlying file. There is +// nothing better on Solaris, but do not be tempted to use this elsewhere. For +// more info, see http://bugs.squid-cache.org/show_bug.cgi?id=4212#c14 +/// fcntl(... struct flock) convenience wrapper +int +fcntlLock(const int fd, const short lockType) +{ + // the exact composition and order of flock data members is unknown! + struct flock fl; + memset(&fl, 0, sizeof(fl)); + fl.l_type = lockType; + fl.l_whence = SEEK_SET; // with zero l_len and l_start, means "whole file" + return ::fcntl(fd, F_SETLK, &fl); +} +#endif // _SQUID_SOLARIS_ + +File * +File::Optional(const SBuf &filename, const FileOpeningConfig &cfg) +{ + try { + return new File(filename, cfg); + } + catch (const std::exception &ex) { + debugs(54, 5, "will not lock: " << ex.what()); + } + return nullptr; +} + +File::File(const SBuf &aName, const FileOpeningConfig &cfg): + name_(aName) +{ + debugs(54, 7, "constructing, this=" << this << ' ' << name_); + // close the file during post-open constructor exceptions + try { + open(cfg); + lock(cfg); + } + catch (...) + { + close(); + throw; + } +} + +File::~File() +{ + debugs(54, 7, "destructing, this=" << this << ' ' << name_); + close(); +} + +File::File(File &&other) +{ + *this = std::move(other); +} + +File & +File::operator = (File &&other) +{ + std::swap(fd_, other.fd_); + return *this; +} + +/// opens (or creates) the file +void +File::open(const FileOpeningConfig &cfg) +{ +#if _SQUID_WINDOWS_ + fd_ = CreateFile(TEXT(name_.c_str()), desiredAccess, shareMode, nullptr, creationDisposition, FILE_ATTRIBUTE_NORMAL, nullptr); + if (fd_ == InvalidHandle) { + const auto savedError = GetLastError(); + throw TexcHere(sysCallFailure("CreateFile", WindowsErrorMessage(savedError).c_str())); + } +#else + mode_t oldCreationMask = 0; + const auto filename = name_.c_str(); // avoid complex operations inside enter_suid() + enter_suid(); + if (cfg.creationMask) + oldCreationMask = umask(cfg.creationMask); // XXX: Why here? Should not this be set for the whole Squid? + fd_ = ::open(filename, cfg.openFlags, cfg.openMode); + const auto savedErrno = errno; + if (cfg.creationMask) + umask(oldCreationMask); + leave_suid(); + if (fd_ < 0) + throw TexcHere(sysCallError("open", savedErrno)); +#endif +} + +void +File::close() +{ + if (!isOpen()) + return; +#if _SQUID_WINDOWS_ + if (!CloseHandle(fd_)) { + const auto savedError = GetLastError(); + debugs(54, DBG_IMPORTANT, sysCallFailure("CloseHandle", WindowsErrorMessage(savedError))); + } +#else + if (::close(fd_) != 0) { + const auto savedErrno = errno; + debugs(54, DBG_IMPORTANT, sysCallError("close", savedErrno)); + } +#endif + // closing the file handler implicitly removes all associated locks +} + +void +File::truncate() +{ +#if _SQUID_WINDOWS_ + if (!SetFilePointer(fd_, 0, nullptr, FILE_BEGIN)) { + const auto savedError = GetLastError(); + throw TexcHere(sysCallFailure("SetFilePointer", WindowsErrorMessage(savedError).c_str())); + } + + if (!SetEndOfFile(fd_)) { + const auto savedError = GetLastError(); + throw TexcHere(sysCallFailure("SetEndOfFile", WindowsErrorMessage(savedError).c_str())); + } +#else + if (::lseek(fd_, SEEK_SET, 0) < 0) { + const auto savedErrno = errno; + throw TexcHere(sysCallError("lseek", savedErrno)); + } + + if (::ftruncate(fd_, 0) != 0) { + const auto savedErrno = errno; + throw TexcHere(sysCallError("ftruncate", savedErrno)); + } +#endif +} + +SBuf +File::readSmall(const SBuf::size_type minBytes, const SBuf::size_type maxBytes) +{ + SBuf buf; + const auto readLimit = maxBytes + 1; // to detect excessively large files that we do not handle +#if _SQUID_WINDOWS_ + DWORD result = 0; + if (!ReadFile(fd_, buf.rawSpace(readLimit), readLimit, &result, nullptr)) { + const auto savedError = GetLastError(); + throw TexcHere(sysCallFailure("ReadFile", WindowsErrorMessage(savedError).c_str())); + } +#else + const auto result = ::read(fd_, buf.rawSpace(readLimit), readLimit); + if (result < 0) { + const auto savedErrno = errno; + throw TexcHere(sysCallError("read", savedErrno)); + } +#endif + const auto bytesRead = static_cast(result); + assert(bytesRead <= readLimit); + Must(!buf.length()); + buf.forceSize(bytesRead); + + if (buf.length() < minBytes) { + const auto failure = buf.length() ? "premature eof" : "empty file"; + throw TexcHere(sysCallFailure("read", failure)); + } + + if (buf.length() > maxBytes) { + const auto failure = "unreasonably large file"; + throw TexcHere(sysCallFailure("read", failure)); + } + + Must(minBytes <= buf.length() && buf.length() <= maxBytes); + return buf; +} + +void +File::writeAll(const SBuf &data) +{ +#if _SQUID_WINDOWS_ + DWORD nBytesWritten = 0; + if (!WriteFile(fd_, data.rawContent(), data.length(), &nBytesWritten, nullptr)) { + const auto savedError = GetLastError(); + throw TexcHere(sysCallFailure("WriteFile", WindowsErrorMessage(savedError).c_str())); + } + const auto bytesWritten = static_cast(nBytesWritten); +#else + const auto result = ::write(fd_, data.rawContent(), data.length()); + if (result < 0) { + const auto savedErrno = errno; + throw TexcHere(sysCallError("write", savedErrno)); + } + const auto bytesWritten = static_cast(result); +#endif + if (bytesWritten != data.length()) + throw TexcHere(sysCallFailure("write", "partial write")); +} + +void +File::synchronize() +{ +#if _SQUID_WINDOWS_ + if (!FlushFileBuffers(fd_)) { + const auto savedError = GetLastError(); + throw TexcHere(sysCallFailure("FlushFileBuffers", WindowsErrorMessage(savedError).c_str())); + } +#else + if (::fsync(fd_) != 0) { + const auto savedErrno = errno; + throw TexcHere(sysCallError("fsync", savedErrno)); + } +#endif +} + +/// calls lockOnce() as many times as necessary (including zero) +void +File::lock(const FileOpeningConfig &cfg) +{ + unsigned int attemptsLeft = cfg.lockAttempts; + while (attemptsLeft) { + try { + --attemptsLeft; + return lockOnce(cfg); + } catch (const std::exception &ex) { + if (!attemptsLeft) + throw; + debugs(54, 4, "sleeping and then trying up to " << attemptsLeft << + " more time(s) after a failure: " << ex.what()); + } + Must(attemptsLeft); // the catch statement handles the last attempt + xusleep(cfg.RetryGapUsec); + } + debugs(54, 9, "disabled"); +} + +/// locks, blocking or returning immediately depending on the lock waiting mode +void +File::lockOnce(const FileOpeningConfig &cfg) +{ +#if _SQUID_WINDOWS_ + if (!LockFileEx(fd_, cfg.lockFlags, 0, 0, 1, 0)) { + const auto savedError = GetLastError(); + throw TexcHere(sysCallFailure("LockFileEx", WindowsErrorMessage(savedError).c_str())); + } +#elif _SQUID_SOLARIS_ + if (fcntlLock(fd_, cfg.lockType) != 0) { + const auto savedErrno = errno; + throw TexcHere(sysCallError("fcntl(flock)", savedErrno)); + } +#else + if (::flock(fd_, cfg.flockMode) != 0) { + const auto savedErrno = errno; + throw TexcHere(sysCallError("flock", savedErrno)); + } +#endif + debugs(54, 3, "succeeded for " << name_); +} + +/// \returns a description a system call-related failure +SBuf +File::sysCallFailure(const char *callName, const char *error) const +{ + return ToSBuf("failed to ", callName, ' ', name_, ": ", error); +} + +/// \returns a description of an errno-based system call failure +SBuf +File::sysCallError(const char *callName, const int savedErrno) const +{ + return sysCallFailure(callName, xstrerr(savedErrno)); +} + diff -u -r -N squid-4.0.19/src/base/File.h squid-4.0.20/src/base/File.h --- squid-4.0.19/src/base/File.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-4.0.20/src/base/File.h 2017-06-02 00:49:17.000000000 +1200 @@ -0,0 +1,123 @@ +/* + * Copyright (C) 1996-2017 The Squid Software Foundation and contributors + * + * Squid software is distributed under GPLv2+ license and includes + * contributions from numerous individuals and organizations. + * Please see the COPYING and CONTRIBUTORS files for details. + */ + +#ifndef SQUID_BASE_FILE_H +#define SQUID_BASE_FILE_H + +#include "sbuf/SBuf.h" + +/// How should a file be opened/created? Should it be locked? +class FileOpeningConfig +{ +public: + static FileOpeningConfig ReadOnly(); // shared reading + static FileOpeningConfig ReadWrite(); // exclusive creation and/or reading/writing + + /* adjustment methods; named to work well with the File::Be::X shorthand */ + + /// protect concurrent accesses by attempting to obtain an appropriate lock + FileOpeningConfig &locked(unsigned int attempts = 5); + + /// when opening a file for writing, create it if it does not exist + FileOpeningConfig &createdIfMissing(); + + /// enter_suid() to open the file; leaves suid ASAP after that + FileOpeningConfig &openedByRoot() { openByRoot = true; return *this; } + + /* add more mode adjustment methods as needed */ + +private: + friend class File; + + /* file opening parameters */ +#if _SQUID_WINDOWS_ + DWORD desiredAccess = 0; ///< 2nd CreateFile() parameter + DWORD shareMode = 0; ///< 3rd CreateFile() parameter + DWORD creationDisposition = OPEN_EXISTING; ///< 5th CreateFile() parameter +#else + mode_t creationMask = 0; ///< umask() parameter; the default is S_IWGRP|S_IWOTH + int openFlags = 0; ///< opening flags; 2nd open(2) parameter + mode_t openMode = 0644; ///< access mode; 3rd open(2) parameter +#endif + + /* file locking (disabled unless lock(n) sets positive lockAttempts) */ +#if _SQUID_WINDOWS_ + DWORD lockFlags = 0; ///< 2nd LockFileEx() parameter +#elif _SQUID_SOLARIS_ + int lockType = F_UNLCK; ///< flock::type member for fcntl(F_SETLK) +#else + int flockMode = LOCK_UN; ///< 2nd flock(2) parameter +#endif + static const unsigned int RetryGapUsec = 500000; /// pause before each lock retry + unsigned int lockAttempts = 0; ///< how many times to try locking + bool openByRoot = false; +}; + +/// a portable locking-aware exception-friendly file (with RAII API) +class File +{ +public: + typedef FileOpeningConfig Be; ///< convenient shorthand for File() callers + + /// \returns nil if File() throws or a new File object (otherwise) + static File *Optional(const SBuf &aName, const FileOpeningConfig &cfg); + + File(const SBuf &aFilename, const FileOpeningConfig &cfg); ///< opens + ~File(); ///< closes + + /* can move but cannot copy */ + File(const File &) = delete; + File &operator = (const File &) = delete; + File(File &&other); + File &operator = (File &&other); + + const SBuf &name() const { return name_; } + + /* system call wrappers */ + + /// makes the file size (and the current I/O offset) zero + void truncate(); + SBuf readSmall(SBuf::size_type minBytes, SBuf::size_type maxBytes); ///< read(2) for small files + void writeAll(const SBuf &data); ///< write(2) with a "wrote everything" check + void synchronize(); ///< fsync(2) + +protected: + bool isOpen() const { +#if _SQUID_WINDOWS_ + return fd_ != InvalidHandle; +#else + return fd_ >= 0; +#endif + } + + void open(const FileOpeningConfig &cfg); + void lock(const FileOpeningConfig &cfg); + void lockOnce(const FileOpeningConfig &cfg); + void close(); + + /// \returns a description a system call-related failure + SBuf sysCallFailure(const char *callName, const char *error) const; + /// \returns a description of an errno-based system call failure + SBuf sysCallError(const char *callName, const int savedErrno) const; + +private: + SBuf name_; ///< location on disk + + // Windows-specific HANDLE is needed because LockFileEx() does not take POSIX FDs. +#if _SQUID_WINDOWS_ + typedef HANDLE Handle; + static const Handle InvalidHandle = INVALID_HANDLE_VALUE; +#else + typedef int Handle; + static const Handle InvalidHandle = -1; +#endif + Handle fd_ = InvalidHandle; ///< OS-specific file handle +}; + +#endif + diff -u -r -N squid-4.0.19/src/base/Makefile.am squid-4.0.20/src/base/Makefile.am --- squid-4.0.19/src/base/Makefile.am 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/base/Makefile.am 2017-06-02 00:49:17.000000000 +1200 @@ -25,6 +25,8 @@ CharacterSet.h \ CharacterSet.cc \ EnumIterator.h \ + File.h \ + File.cc \ HardFun.h \ InstanceId.h \ Lock.h \ diff -u -r -N squid-4.0.19/src/base/Makefile.in squid-4.0.20/src/base/Makefile.in --- squid-4.0.19/src/base/Makefile.in 2017-04-02 19:46:02.000000000 +1200 +++ squid-4.0.20/src/base/Makefile.in 2017-06-02 00:58:40.000000000 +1200 @@ -164,7 +164,7 @@ LTLIBRARIES = $(noinst_LTLIBRARIES) libbase_la_LIBADD = am_libbase_la_OBJECTS = AsyncCall.lo AsyncJob.lo AsyncCallQueue.lo \ - CharacterSet.lo RegexPattern.lo RunnersRegistry.lo \ + CharacterSet.lo File.lo RegexPattern.lo RunnersRegistry.lo \ TextException.lo libbase_la_OBJECTS = $(am_libbase_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) @@ -729,6 +729,8 @@ CharacterSet.h \ CharacterSet.cc \ EnumIterator.h \ + File.h \ + File.cc \ HardFun.h \ InstanceId.h \ Lock.h \ @@ -813,6 +815,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AsyncCallQueue.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AsyncJob.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CharacterSet.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/File.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RegexPattern.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RunnersRegistry.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TextException.Plo@am__quote@ diff -u -r -N squid-4.0.19/src/base/TextException.cc squid-4.0.20/src/base/TextException.cc --- squid-4.0.19/src/base/TextException.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/base/TextException.cc 2017-06-02 00:49:17.000000000 +1200 @@ -9,6 +9,7 @@ #include "squid.h" #include "base/TextException.h" #include "Debug.h" +#include "sbuf/SBuf.h" #include "util.h" TextException::TextException() @@ -28,6 +29,10 @@ message(aMsg?xstrdup(aMsg):NULL), theFileName(aFileName), theLineNo(aLineNo), theId(anId) {} +TextException::TextException(SBuf msg, const char *aFileName, int aLineNo, unsigned int anId): + TextException(msg.c_str(), aFileName, aLineNo, anId) +{} + TextException::~TextException() throw() { if (message) xfree(message); diff -u -r -N squid-4.0.19/src/base/TextException.h squid-4.0.20/src/base/TextException.h --- squid-4.0.19/src/base/TextException.h 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/base/TextException.h 2017-06-02 00:49:17.000000000 +1200 @@ -13,6 +13,8 @@ #include +class SBuf; + static unsigned int FileNameHashCached(const char *fname); // simple exception to report custom errors @@ -24,6 +26,7 @@ public: TextException(); TextException(const char *aMessage, const char *aFileName = 0, int aLineNo = -1, unsigned int anId =0); + TextException(SBuf aMessage, const char *aFileName = 0, int aLineNo = -1, unsigned int anId =0); TextException(const TextException& right); virtual ~TextException() throw(); diff -u -r -N squid-4.0.19/src/cache_cf.cc squid-4.0.20/src/cache_cf.cc --- squid-4.0.19/src/cache_cf.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/cache_cf.cc 2017-06-02 00:49:17.000000000 +1200 @@ -2205,7 +2205,7 @@ } else if (!strcmp(token, "auth-no-keytab")) { p->options.auth_no_keytab = 1; } else if (!strncmp(token, "connect-timeout=", 16)) { - p->connect_timeout = xatoi(token + 16); + p->connect_timeout_raw = xatoi(token + 16); } else if (!strncmp(token, "connect-fail-limit=", 19)) { p->connect_fail_limit = xatoi(token + 19); #if USE_CACHE_DIGESTS diff -u -r -N squid-4.0.19/src/CachePeer.cc squid-4.0.20/src/CachePeer.cc --- squid-4.0.19/src/CachePeer.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/CachePeer.cc 2017-06-02 00:49:17.000000000 +1200 @@ -31,12 +31,13 @@ digest_url(NULL), #endif tcp_up(0), + reprobe(false), n_addresses(0), rr_count(0), next(NULL), testing_now(false), login(NULL), - connect_timeout(0), + connect_timeout_raw(0), connect_fail_limit(0), max_conn(0), domain(NULL), diff -u -r -N squid-4.0.19/src/CachePeer.h squid-4.0.20/src/CachePeer.h --- squid-4.0.19/src/CachePeer.h 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/CachePeer.h 2017-06-02 00:49:17.000000000 +1200 @@ -144,6 +144,8 @@ #endif int tcp_up; /* 0 if a connect() fails */ + /// whether to do another TCP probe after current TCP probes + bool reprobe; Ip::Address addresses[10]; int n_addresses; @@ -170,7 +172,7 @@ } sourcehash; char *login; /* Proxy authorization */ - time_t connect_timeout; + time_t connect_timeout_raw; ///< connect_timeout; use peerConnectTimeout() instead! int connect_fail_limit; int max_conn; struct { diff -u -r -N squid-4.0.19/src/cf.data.pre squid-4.0.20/src/cf.data.pre --- squid-4.0.19/src/cf.data.pre 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/cf.data.pre 2017-06-02 00:49:17.000000000 +1200 @@ -1242,6 +1242,33 @@ # adaptation_meta because it starts matching immediately after # the service has been selected for adaptation. + acl aclname has component + # matches a transaction "component" [fast] + # + # Supported transaction components are: + # request: transaction has a request header (at least) + # response: transaction has a response header (at least) + # ALE: transaction has an internally-generated Access Log Entry + # structure; bugs notwithstanding, all transaction have it + # + # For example, the following configuration helps when dealing with HTTP + # clients that close connections without sending a request header: + # + # acl hasRequest has request + # acl logMe note important_transaction + # # avoid "logMe ACL is used in context without an HTTP request" warnings + # access_log ... logformat=detailed hasRequest logMe + # # log request-less transactions, instead of ignoring them + # access_log ... logformat=brief !hasRequest + # + # Multiple components are not supported for one "acl" rule, but + # can be specified (and are ORed) using multiple same-name rules: + # + # # OK, this strange logging daemon needs request or response, + # # but can work without either a request or a response: + # acl hasWhatMyLoggingDaemonNeeds has request + # acl hasWhatMyLoggingDaemonNeeds has response + IF USE_OPENSSL acl aclname ssl_error errorname # match against SSL certificate validation error [fast] @@ -2753,8 +2780,11 @@ This is the default action. bump - Establish a secure connection with the server and, using a - mimicked server certificate, with the client. + When used on step SslBump1, establishes a secure connection + with the client first, then connect to the server. + When used on step SslBump2 or SslBump3, establishes a secure + connection with the server and, using a mimicked server + certificate, with the client. peek Receive client (step SslBump1) or server (step SslBump2) @@ -4308,13 +4338,14 @@ For CONNECT requests that initiated bumping of a connection and for any request received on an already bumped connection, Squid logs the - corresponding SslBump mode ("server-first" or - "client-first"). See the ssl_bump option for - more information about these modes. + corresponding SslBump mode ("splice", "bump", + "peek", "stare", "terminate", "server-first" + or "client-first"). See the ssl_bump option + for more information about these modes. A "none" token is logged for requests that triggered "ssl_bump" ACL evaluation matching - either a "none" rule or no rules at all. + a "none" rule. In all other cases, a single dash ("-") is logged. diff -u -r -N squid-4.0.19/src/clients/FtpGateway.cc squid-4.0.20/src/clients/FtpGateway.cc --- squid-4.0.19/src/clients/FtpGateway.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/clients/FtpGateway.cc 2017-06-02 00:49:17.000000000 +1200 @@ -619,10 +619,17 @@ while (strchr(w_space, *copyFrom)) ++copyFrom; } else { - /* XXX assumes a single space between date and filename + /* Handle the following four formats: + * "MMM DD YYYY Name" + * "MMM DD YYYYName" + * "MMM DD YYYY Name" + * "MMM DD YYYY Name" + * Assuming a single space between date and filename * suggested by: Nathan.Bailey@cc.monash.edu.au and * Mike Battersby */ - copyFrom += strlen(tbuf) + 1; + copyFrom += strlen(tbuf); + if (strchr(w_space, *copyFrom)) + ++copyFrom; } p->name = xstrdup(copyFrom); @@ -1507,7 +1514,7 @@ /* Reset cwd_message to only include the last message */ ftpState->cwd_message.reset(""); for (wordlist *w = ftpState->ctrl.message; w; w = w->next) { - ftpState->cwd_message.append(' '); + ftpState->cwd_message.append('\n'); ftpState->cwd_message.append(w->key); } ftpState->ctrl.message = NULL; diff -u -r -N squid-4.0.19/src/client_side.cc squid-4.0.20/src/client_side.cc --- squid-4.0.19/src/client_side.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/client_side.cc 2017-06-02 00:49:17.000000000 +1200 @@ -2727,8 +2727,6 @@ /** * A callback function to use with the ACLFilledChecklist callback. - * In the case of ACCESS_ALLOWED answer initializes a bumped SSL connection, - * else reverts the connection to tunnel mode. */ static void httpsSslBumpAccessCheckDone(allow_t answer, void *data) @@ -2739,15 +2737,19 @@ if (!connState->isOpen()) return; - // Require both a match and a positive bump mode to work around exceptional - // cases where ACL code may return ACCESS_ALLOWED with zero answer.kind. - if (answer == ACCESS_ALLOWED && answer.kind != Ssl::bumpNone) { - debugs(33, 2, "sslBump needed for " << connState->clientConnection << " method " << answer.kind); + if (answer == ACCESS_ALLOWED) { + debugs(33, 2, "sslBump action " << Ssl::bumpMode(answer.kind) << "needed for " << connState->clientConnection); connState->sslBumpMode = static_cast(answer.kind); } else { - debugs(33, 2, HERE << "sslBump not needed for " << connState->clientConnection); - connState->sslBumpMode = Ssl::bumpNone; + debugs(33, 3, "sslBump not needed for " << connState->clientConnection); + connState->sslBumpMode = Ssl::bumpSplice; + } + + if (connState->sslBumpMode == Ssl::bumpTerminate) { + connState->clientConnection->close(); + return; } + if (!connState->fakeAConnectRequest("ssl-bump", connState->inBuf)) connState->clientConnection->close(); } @@ -3145,8 +3147,9 @@ parsingTlsHandshake = false; - if (mayTunnelUnsupportedProto()) - preservedClientData = inBuf; + // client data may be needed for splicing and for + // tunneling unsupportedProtocol after an error + preservedClientData = inBuf; // Even if the parser failed, each TLS detail should either be set // correctly or still be "unknown"; copying unknown detail is a no-op. @@ -3167,7 +3170,8 @@ Must(context && context->http); HttpRequest::Pointer request = context->http->request; debugs(83, 5, "Got something other than TLS Client Hello. Cannot SslBump."); - sslBumpMode = Ssl::bumpNone; + sslBumpMode = Ssl::bumpSplice; + context->http->al->ssl.bumpMode = Ssl::bumpSplice; if (!clientTunnelOnError(this, context, request, HttpRequestMethod(), ERR_PROTOCOL_UNKNOWN)) clientConnection->close(); return; @@ -3203,6 +3207,9 @@ connState->serverBump()->act.step2 = bumpAction; connState->sslBumpMode = bumpAction; + Http::StreamPointer context = connState->pipeline.front(); + if (ClientHttpRequest *http = (context ? context->http : nullptr)) + http->al->ssl.bumpMode = bumpAction; if (bumpAction == Ssl::bumpTerminate) { connState->clientConnection->close(); @@ -3228,9 +3235,23 @@ transferProtocol = Http::ProtocolVersion(); assert(!pipeline.empty()); Http::StreamPointer context = pipeline.front(); + Must(context); + Must(context->http); ClientHttpRequest *http = context->http; - tunnelStart(http); - return true; + HttpRequest::Pointer request = http->request; + context->finished(); + if (transparent()) { + // For transparent connections, make a new fake CONNECT request, now + // with SNI as target. doCallout() checks, adaptations may need that. + return fakeAConnectRequest("splice", preservedClientData); + } else { + // For non transparent connections make a new tunneled CONNECT, which + // also sets the HttpRequest::flags::forceTunnel flag to avoid + // respond with "Connection Established" to the client. + // This fake CONNECT request required to allow use of SNI in + // doCallout() checks and adaptations. + return initiateTunneledRequest(request, Http::METHOD_CONNECT, "splice", preservedClientData); + } } void @@ -3338,7 +3359,8 @@ if (pinning.serverConnection != nullptr) { static char ip[MAX_IPSTRLEN]; - connectHost.assign(pinning.serverConnection->remote.toStr(ip, sizeof(ip))); + pinning.serverConnection->remote.toHostStr(ip, sizeof(ip)); + connectHost.assign(ip); connectPort = pinning.serverConnection->remote.port(); } else if (cause && cause->method == Http::METHOD_CONNECT) { // We are inside a (not fully established) CONNECT request @@ -3375,7 +3397,8 @@ #endif { static char ip[MAX_IPSTRLEN]; - connectHost.assign(clientConnection->local.toStr(ip, sizeof(ip))); + clientConnection->local.toHostStr(ip, sizeof(ip)); + connectHost.assign(ip); } ClientHttpRequest *http = buildFakeRequest(Http::METHOD_CONNECT, connectHost, connectPort, payload); diff -u -r -N squid-4.0.19/src/client_side_request.cc squid-4.0.20/src/client_side_request.cc --- squid-4.0.19/src/client_side_request.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/client_side_request.cc 2017-06-02 00:49:17.000000000 +1200 @@ -193,7 +193,7 @@ { assert(request); return request->cache_control && - request->cache_control->onlyIfCached(); + request->cache_control->hasOnlyIfCached(); } /** @@ -1415,17 +1415,29 @@ return false; } + const Ssl::BumpMode bumpMode = http->getConn()->sslBumpMode; if (http->request->flags.forceTunnel) { debugs(85, 5, "not needed; already decided to tunnel " << http->getConn()); + if (bumpMode != Ssl::bumpEnd) + http->al->ssl.bumpMode = bumpMode; // inherited from bumped connection return false; } // If SSL connection tunneling or bumping decision has been made, obey it. - const Ssl::BumpMode bumpMode = http->getConn()->sslBumpMode; if (bumpMode != Ssl::bumpEnd) { debugs(85, 5, HERE << "SslBump already decided (" << bumpMode << "), " << "ignoring ssl_bump for " << http->getConn()); - if (!http->getConn()->serverBump()) + + // We need the following "if" for transparently bumped TLS connection, + // because in this case we are running ssl_bump access list before + // the doCallouts runs. It can be removed after the bug #4340 fixed. + // We do not want to proceed to bumping steps: + // - if the TLS connection with the client is already established + // because we are accepting normal HTTP requests on TLS port, + // or because of the client-first bumping mode + // - When the bumping is already started + if (!http->getConn()->switchedToHttps() && + !http->getConn()->serverBump()) http->sslBumpNeed(bumpMode); // for processRequest() to bump if needed and not already bumped http->al->ssl.bumpMode = bumpMode; // inherited from bumped connection return false; @@ -1487,10 +1499,19 @@ return; const Ssl::BumpMode bumpMode = answer == ACCESS_ALLOWED ? - static_cast(answer.kind) : Ssl::bumpNone; + static_cast(answer.kind) : Ssl::bumpSplice; http->sslBumpNeed(bumpMode); // for processRequest() to bump if needed http->al->ssl.bumpMode = bumpMode; // for logging + if (bumpMode == Ssl::bumpTerminate) { + const Comm::ConnectionPointer clientConn = http->getConn() ? http->getConn()->clientConnection : nullptr; + if (Comm::IsConnOpen(clientConn)) { + debugs(85, 3, "closing after Ssl::bumpTerminate "); + clientConn->close(); + } + return; + } + http->doCallouts(); } #endif diff -u -r -N squid-4.0.19/src/comm/Connection.cc squid-4.0.20/src/comm/Connection.cc --- squid-4.0.19/src/comm/Connection.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/comm/Connection.cc 2017-06-02 00:49:17.000000000 +1200 @@ -12,6 +12,7 @@ #include "comm.h" #include "comm/Connection.h" #include "fde.h" +#include "FwdState.h" #include "neighbors.h" #include "security/NegotiationHistory.h" #include "SquidConfig.h" @@ -131,3 +132,23 @@ return tlsHistory; } +time_t +Comm::Connection::connectTimeout(const time_t fwdStart) const +{ + // a connection opening timeout (ignoring forwarding time limits for now) + const CachePeer *peer = getPeer(); + const time_t ctimeout = peer ? peerConnectTimeout(peer) : Config.Timeout.connect; + + // time we have left to finish the whole forwarding process + const time_t fwdTimeLeft = FwdState::ForwardTimeout(fwdStart); + + // The caller decided to connect. If there is no time left, to protect + // connecting code from trying to establish a connection while a zero (i.e., + // "immediate") timeout notification is firing, ensure a positive timeout. + // XXX: This hack gives some timed-out forwarding sequences more time than + // some sequences that have not quite reached the forwarding timeout yet! + const time_t ftimeout = fwdTimeLeft ? fwdTimeLeft : 5; // seconds + + return min(ctimeout, ftimeout); +} + diff -u -r -N squid-4.0.19/src/comm/Connection.h squid-4.0.20/src/comm/Connection.h --- squid-4.0.19/src/comm/Connection.h 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/comm/Connection.h 2017-06-02 00:49:17.000000000 +1200 @@ -111,6 +111,13 @@ /** The time left for this connection*/ time_t timeLeft(const time_t idleTimeout) const; + /// Connection establishment timeout for callers that have already decided + /// to connect(2), either for the first time or after checking + /// EnoughTimeToReForward() during any re-forwarding attempts. + /// \returns the time left for this connection to become connected + /// \param fwdStart The start time of the peer selection/connection process. + time_t connectTimeout(const time_t fwdStart) const; + void noteStart() {startTime_ = squid_curtime;} Security::NegotiationHistory *tlsNegotiations(); diff -u -r -N squid-4.0.19/src/comm/ConnOpener.cc squid-4.0.20/src/comm/ConnOpener.cc --- squid-4.0.19/src/comm/ConnOpener.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/comm/ConnOpener.cc 2017-06-02 00:49:17.000000000 +1200 @@ -39,7 +39,9 @@ totalTries_(0), failRetries_(0), deadline_(squid_curtime + static_cast(ctimeout)) -{} +{ + debugs(5, 3, "will connect to " << c << " with " << ctimeout << " timeout"); +} Comm::ConnOpener::~ConnOpener() { diff -u -r -N squid-4.0.19/src/errorpage.cc squid-4.0.20/src/errorpage.cc --- squid-4.0.19/src/errorpage.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/errorpage.cc 2017-06-02 00:49:17.000000000 +1200 @@ -332,7 +332,7 @@ /* with dynamic locale negotiation we may see some failures before a success. */ if (!silent && templateCode < TCP_RESET) { int xerrno = errno; - debugs(4, DBG_CRITICAL, MYNAME << "'" << path << "': " << xstrerr(xerrno)); + debugs(4, DBG_CRITICAL, "ERROR: loading file '" << path << "': " << xstrerr(xerrno)); } wasLoaded = false; return wasLoaded; @@ -340,7 +340,7 @@ while ((len = FD_READ_METHOD(fd, buf, sizeof(buf))) > 0) { if (!parse(buf, len, false)) { - debugs(4, DBG_CRITICAL, MYNAME << "parse error while reading template file: " << path); + debugs(4, DBG_CRITICAL, "ERROR: parsing error in template file: " << path); wasLoaded = false; return wasLoaded; } diff -u -r -N squid-4.0.19/src/esi/Expression.cc squid-4.0.20/src/esi/Expression.cc --- squid-4.0.19/src/esi/Expression.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/esi/Expression.cc 2017-06-02 00:49:17.000000000 +1200 @@ -743,7 +743,7 @@ /* Special case for zero length strings */ if (t - s - 1) - rv.value.string = xstrndup(s + 1, t - s - 1); + rv.value.string = xstrndup(s + 1, t - (s + 1) + 1); else rv.value.string = static_cast(xcalloc(1,1)); diff -u -r -N squid-4.0.19/src/FwdState.cc squid-4.0.20/src/FwdState.cc --- squid-4.0.19/src/FwdState.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/FwdState.cc 2017-06-02 00:49:17.000000000 +1200 @@ -389,6 +389,29 @@ Start(clientConn, entry, request, NULL); } +/// subtracts time_t values, returning zero if smaller exceeds the larger value +/// time_t might be unsigned so we need to be careful when subtracting times... +static inline time_t +diffOrZero(const time_t larger, const time_t smaller) +{ + return (larger > smaller) ? (larger - smaller) : 0; +} + +/// time left to finish the whole forwarding process (which started at fwdStart) +time_t +FwdState::ForwardTimeout(const time_t fwdStart) +{ + // time already spent on forwarding (0 if clock went backwards) + const time_t timeSpent = diffOrZero(squid_curtime, fwdStart); + return diffOrZero(Config.Timeout.forward, timeSpent); +} + +bool +FwdState::EnoughTimeToReForward(const time_t fwdStart) +{ + return ForwardTimeout(fwdStart) > 0; +} + void FwdState::startConnectionOrFail() { @@ -568,7 +591,7 @@ if (n_tries > Config.forward_max_tries) return false; - if (squid_curtime - start_t > Config.Timeout.forward) + if (!EnoughTimeToReForward(start_t)) return false; if (flags.dont_retry) @@ -696,7 +719,8 @@ "FwdState::ConnectedToPeer", FwdStatePeerAnswerDialer(&FwdState::connectedToPeer, this)); // Use positive timeout when less than one second is left. - const time_t sslNegotiationTimeout = max(static_cast(1), timeLeft()); + const time_t connTimeout = serverDestinations[0]->connectTimeout(start_t); + const time_t sslNegotiationTimeout = positiveTimeout(connTimeout); Security::PeerConnector *connector = nullptr; #if USE_OPENSSL if (request->flags.sslPeek) @@ -769,29 +793,6 @@ } } -time_t -FwdState::timeLeft() const -{ - /* connection timeout */ - int ctimeout; - if (serverDestinations[0]->getPeer()) { - ctimeout = serverDestinations[0]->getPeer()->connect_timeout > 0 ? - serverDestinations[0]->getPeer()->connect_timeout : Config.Timeout.peer_connect; - } else { - ctimeout = Config.Timeout.connect; - } - - /* calculate total forwarding timeout ??? */ - int ftimeout = Config.Timeout.forward - (squid_curtime - start_t); - if (ftimeout < 0) - ftimeout = 5; - - if (ftimeout < ctimeout) - return (time_t)ftimeout; - else - return (time_t)ctimeout; -} - /// called when serverConn is set to an _open_ to-peer connection void FwdState::syncWithServerConn(const char *host) @@ -917,7 +918,8 @@ GetMarkingsToServer(request, *serverDestinations[0]); calls.connector = commCbCall(17,3, "fwdConnectDoneWrapper", CommConnectCbPtrFun(fwdConnectDoneWrapper, this)); - Comm::ConnOpener *cs = new Comm::ConnOpener(serverDestinations[0], calls.connector, timeLeft()); + const time_t connTimeout = serverDestinations[0]->connectTimeout(start_t); + Comm::ConnOpener *cs = new Comm::ConnOpener(serverDestinations[0], calls.connector, connTimeout); if (host) cs->setHost(host); AsyncJob::Start(cs); diff -u -r -N squid-4.0.19/src/FwdState.h squid-4.0.20/src/FwdState.h --- squid-4.0.19/src/FwdState.h 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/FwdState.h 2017-06-02 00:49:17.000000000 +1200 @@ -68,6 +68,11 @@ static void Start(const Comm::ConnectionPointer &client, StoreEntry *, HttpRequest *, const AccessLogEntryPointer &alp); /// Same as Start() but no master xaction info (AccessLogEntry) available. static void fwdStart(const Comm::ConnectionPointer &client, StoreEntry *, HttpRequest *); + /// time left to finish the whole forwarding process (which started at fwdStart) + static time_t ForwardTimeout(const time_t fwdStart); + /// Whether there is still time to re-try after a previous connection failure. + /// \param fwdStart The start time of the peer selection/connection process. + static bool EnoughTimeToReForward(const time_t fwdStart); /// This is the real beginning of server connection. Call it whenever /// the forwarding server destination has changed and a new one needs to be opened. @@ -85,7 +90,6 @@ void connectStart(); void connectDone(const Comm::ConnectionPointer & conn, Comm::Flag status, int xerrno); void connectTimeout(int fd); - time_t timeLeft() const; ///< the time left before the forwarding timeout expired bool checkRetry(); bool checkRetriable(); void dispatch(); diff -u -r -N squid-4.0.19/src/http/url_rewriters/LFS/url_lfs_rewrite.8 squid-4.0.20/src/http/url_rewriters/LFS/url_lfs_rewrite.8 --- squid-4.0.19/src/http/url_rewriters/LFS/url_lfs_rewrite.8 2017-04-02 23:49:59.000000000 +1200 +++ squid-4.0.20/src/http/url_rewriters/LFS/url_lfs_rewrite.8 2017-06-02 09:57:33.000000000 +1200 @@ -129,7 +129,7 @@ .\" ======================================================================== .\" .IX Title "URL_LFS_REWRITE 8" -.TH URL_LFS_REWRITE 8 "2017-04-02" "perl v5.24.1" "User Contributed Perl Documentation" +.TH URL_LFS_REWRITE 8 "2017-06-01" "perl v5.24.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff -u -r -N squid-4.0.19/src/http.cc squid-4.0.20/src/http.cc --- squid-4.0.19/src/http.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/http.cc 2017-06-02 00:49:17.000000000 +1200 @@ -284,7 +284,7 @@ HttpHdrScTarget *sctusable = reply->surrogate_control->getMergedTarget(Config.Accel.surrogate_id); if (sctusable) { - if (sctusable->noStore() || + if (sctusable->hasNoStore() || (Config.onoff.surrogate_is_remote && sctusable->noStoreRemote())) { surrogateNoStore = true; @@ -361,14 +361,14 @@ // for now we are not reliably doing that so we waste CPU re-checking request CC // RFC 2616 section 14.9.2 - MUST NOT cache any response with request CC:no-store - if (request && request->cache_control && request->cache_control->noStore() && + if (request && request->cache_control && request->cache_control->hasNoStore() && !REFRESH_OVERRIDE(ignore_no_store)) { debugs(22, 3, HERE << "NO because client request Cache-Control:no-store"); return 0; } // NP: request CC:no-cache only means cache READ is forbidden. STORE is permitted. - if (rep->cache_control && rep->cache_control->hasNoCache() && rep->cache_control->noCache().size() > 0) { + if (rep->cache_control && rep->cache_control->hasNoCacheWithParameters()) { /* TODO: we are allowed to cache when no-cache= has parameters. * Provided we strip away any of the listed headers unless they are revalidated * successfully (ie, must revalidate AND these headers are prohibited on stale replies). @@ -382,7 +382,7 @@ // NP: other request CC flags are limiters on HIT/MISS. We don't care about here. // RFC 2616 section 14.9.2 - MUST NOT cache any response with CC:no-store - if (rep->cache_control && rep->cache_control->noStore() && + if (rep->cache_control && rep->cache_control->hasNoStore() && !REFRESH_OVERRIDE(ignore_no_store)) { debugs(22, 3, HERE << "NO because server reply Cache-Control:no-store"); return 0; @@ -419,12 +419,12 @@ bool mayStore = false; // HTTPbis pt6 section 3.2: a response CC:public is present - if (rep->cache_control->Public()) { + if (rep->cache_control->hasPublic()) { debugs(22, 3, HERE << "Authenticated but server reply Cache-Control:public"); mayStore = true; // HTTPbis pt6 section 3.2: a response CC:must-revalidate is present - } else if (rep->cache_control->mustRevalidate()) { + } else if (rep->cache_control->hasMustRevalidate()) { debugs(22, 3, HERE << "Authenticated but server reply Cache-Control:must-revalidate"); mayStore = true; @@ -433,13 +433,13 @@ // HTTPbis WG verdict on this is that it is omitted from the spec due to being 'unexpected' by // some. The caching+revalidate is not exactly unsafe though with Squids interpretation of no-cache // (without parameters) as equivalent to must-revalidate in the reply. - } else if (rep->cache_control->hasNoCache() && rep->cache_control->noCache().size() == 0) { + } else if (rep->cache_control->hasNoCacheWithoutParameters()) { debugs(22, 3, HERE << "Authenticated but server reply Cache-Control:no-cache (equivalent to must-revalidate)"); mayStore = true; #endif // HTTPbis pt6 section 3.2: a response CC:s-maxage is present - } else if (rep->cache_control->sMaxAge()) { + } else if (rep->cache_control->hasSMaxAge()) { debugs(22, 3, HERE << "Authenticated but server reply Cache-Control:s-maxage"); mayStore = true; } @@ -997,10 +997,10 @@ // For security reasons we do so even if storage was caused by refresh_pattern ignore-* option // CC:must-revalidate or CC:proxy-revalidate - const bool ccMustRevalidate = (rep->cache_control->proxyRevalidate() || rep->cache_control->mustRevalidate()); + const bool ccMustRevalidate = (rep->cache_control->hasProxyRevalidate() || rep->cache_control->hasMustRevalidate()); // CC:no-cache (only if there are no parameters) - const bool ccNoCacheNoParams = (rep->cache_control->hasNoCache() && rep->cache_control->noCache().size()==0); + const bool ccNoCacheNoParams = rep->cache_control->hasNoCacheWithoutParameters(); // CC:s-maxage=N const bool ccSMaxAge = rep->cache_control->hasSMaxAge(); diff -u -r -N squid-4.0.19/src/HttpHdrCc.cc squid-4.0.20/src/HttpHdrCc.cc --- squid-4.0.19/src/HttpHdrCc.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/HttpHdrCc.cc 2017-06-02 00:49:17.000000000 +1200 @@ -245,13 +245,13 @@ case HttpHdrCcType::CC_PUBLIC: break; case HttpHdrCcType::CC_PRIVATE: - if (Private().size()) - p->appendf("=\"" SQUIDSTRINGPH "\"", SQUIDSTRINGPRINT(Private())); + if (private_.size()) + p->appendf("=\"" SQUIDSTRINGPH "\"", SQUIDSTRINGPRINT(private_)); break; case HttpHdrCcType::CC_NO_CACHE: - if (noCache().size()) - p->appendf("=\"" SQUIDSTRINGPH "\"", SQUIDSTRINGPRINT(noCache())); + if (no_cache.size()) + p->appendf("=\"" SQUIDSTRINGPH "\"", SQUIDSTRINGPRINT(no_cache)); break; case HttpHdrCcType::CC_NO_STORE: break; @@ -262,24 +262,24 @@ case HttpHdrCcType::CC_PROXY_REVALIDATE: break; case HttpHdrCcType::CC_MAX_AGE: - p->appendf("=%d", maxAge()); + p->appendf("=%d", max_age); break; case HttpHdrCcType::CC_S_MAXAGE: - p->appendf("=%d", sMaxAge()); + p->appendf("=%d", s_maxage); break; case HttpHdrCcType::CC_MAX_STALE: /* max-stale's value is optional. If we didn't receive it, don't send it */ - if (maxStale()!=MAX_STALE_ANY) - p->appendf("=%d", maxStale()); + if (max_stale != MAX_STALE_ANY) + p->appendf("=%d", max_stale); break; case HttpHdrCcType::CC_MIN_FRESH: - p->appendf("=%d", minFresh()); + p->appendf("=%d", min_fresh); break; case HttpHdrCcType::CC_ONLY_IF_CACHED: break; case HttpHdrCcType::CC_STALE_IF_ERROR: - p->appendf("=%d", staleIfError()); + p->appendf("=%d", stale_if_error); break; case HttpHdrCcType::CC_IMMUTABLE: break; diff -u -r -N squid-4.0.19/src/HttpHdrCc.h squid-4.0.20/src/HttpHdrCc.h --- squid-4.0.19/src/HttpHdrCc.h 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/HttpHdrCc.h 2017-06-02 00:49:17.000000000 +1200 @@ -66,13 +66,11 @@ //manipulation for Cache-Control: public header bool hasPublic() const {return isSet(HttpHdrCcType::CC_PUBLIC);} - bool Public() const {return isSet(HttpHdrCcType::CC_PUBLIC);} void Public(bool v) {setMask(HttpHdrCcType::CC_PUBLIC,v);} void clearPublic() {setMask(HttpHdrCcType::CC_PUBLIC,false);} //manipulation for Cache-Control: private header - bool hasPrivate() const {return isSet(HttpHdrCcType::CC_PRIVATE);} - const String &Private() const {return private_;} + bool hasPrivate(const String **val = nullptr) const { return hasDirective(HttpHdrCcType::CC_PRIVATE, &private_, val); } void Private(const String &v) { setMask(HttpHdrCcType::CC_PRIVATE,true); if (!v.size()) @@ -85,8 +83,9 @@ void clearPrivate() {setMask(HttpHdrCcType::CC_PRIVATE,false); private_.clean();} //manipulation for Cache-Control: no-cache header - bool hasNoCache() const {return isSet(HttpHdrCcType::CC_NO_CACHE);} - const String &noCache() const {return no_cache;} + bool hasNoCacheWithParameters() const { return hasNoCache() && no_cache.size(); } + bool hasNoCacheWithoutParameters() const { return hasNoCache() && !no_cache.size(); } + bool hasNoCache(const String **val = nullptr) const { return hasDirective(HttpHdrCcType::CC_NO_CACHE, &no_cache, val); } void noCache(const String &v) { setMask(HttpHdrCcType::CC_NO_CACHE,true); if (!v.size()) @@ -100,43 +99,36 @@ //manipulation for Cache-Control: no-store header bool hasNoStore() const {return isSet(HttpHdrCcType::CC_NO_STORE);} - bool noStore() const {return isSet(HttpHdrCcType::CC_NO_STORE);} void noStore(bool v) {setMask(HttpHdrCcType::CC_NO_STORE,v);} void clearNoStore() {setMask(HttpHdrCcType::CC_NO_STORE,false);} //manipulation for Cache-Control: no-transform header bool hasNoTransform() const {return isSet(HttpHdrCcType::CC_NO_TRANSFORM);} - bool noTransform() const {return isSet(HttpHdrCcType::CC_NO_TRANSFORM);} void noTransform(bool v) {setMask(HttpHdrCcType::CC_NO_TRANSFORM,v);} void clearNoTransform() {setMask(HttpHdrCcType::CC_NO_TRANSFORM,false);} //manipulation for Cache-Control: must-revalidate header bool hasMustRevalidate() const {return isSet(HttpHdrCcType::CC_MUST_REVALIDATE);} - bool mustRevalidate() const {return isSet(HttpHdrCcType::CC_MUST_REVALIDATE);} void mustRevalidate(bool v) {setMask(HttpHdrCcType::CC_MUST_REVALIDATE,v);} void clearMustRevalidate() {setMask(HttpHdrCcType::CC_MUST_REVALIDATE,false);} //manipulation for Cache-Control: proxy-revalidate header bool hasProxyRevalidate() const {return isSet(HttpHdrCcType::CC_PROXY_REVALIDATE);} - bool proxyRevalidate() const {return isSet(HttpHdrCcType::CC_PROXY_REVALIDATE);} void proxyRevalidate(bool v) {setMask(HttpHdrCcType::CC_PROXY_REVALIDATE,v);} void clearProxyRevalidate() {setMask(HttpHdrCcType::CC_PROXY_REVALIDATE,false);} //manipulation for Cache-Control: max-age header - bool hasMaxAge() const {return isSet(HttpHdrCcType::CC_MAX_AGE);} - int32_t maxAge() const { return max_age;} + bool hasMaxAge(int32_t *val = nullptr) const { return hasDirective(HttpHdrCcType::CC_MAX_AGE, max_age, val); } void maxAge(int32_t v) {setValue(max_age,v,HttpHdrCcType::CC_MAX_AGE); } void clearMaxAge() {setValue(max_age,MAX_AGE_UNKNOWN,HttpHdrCcType::CC_MAX_AGE,false);} //manipulation for Cache-Control: s-maxage header - bool hasSMaxAge() const {return isSet(HttpHdrCcType::CC_S_MAXAGE);} - int32_t sMaxAge() const { return s_maxage;} + bool hasSMaxAge(int32_t *val = nullptr) const { return hasDirective(HttpHdrCcType::CC_S_MAXAGE, s_maxage, val); } void sMaxAge(int32_t v) {setValue(s_maxage,v,HttpHdrCcType::CC_S_MAXAGE); } void clearSMaxAge() {setValue(s_maxage,MAX_AGE_UNKNOWN,HttpHdrCcType::CC_S_MAXAGE,false);} //manipulation for Cache-Control: max-stale header - bool hasMaxStale() const {return isSet(HttpHdrCcType::CC_MAX_STALE);} - int32_t maxStale() const { return max_stale;} + bool hasMaxStale(int32_t *val = nullptr) const { return hasDirective(HttpHdrCcType::CC_MAX_STALE, max_stale, val); } // max-stale has a special value (MAX_STALE_ANY) which correspond to having // the directive without a numeric specification, and directs to consider the object // as always-expired. @@ -144,25 +136,22 @@ void clearMaxStale() {setValue(max_stale,MAX_STALE_UNKNOWN,HttpHdrCcType::CC_MAX_STALE,false);} //manipulation for Cache-Control:min-fresh header - bool hasMinFresh() const {return isSet(HttpHdrCcType::CC_MIN_FRESH);} - int32_t minFresh() const { return min_fresh;} + bool hasMinFresh(int32_t *val = nullptr) const { return hasDirective(HttpHdrCcType::CC_MIN_FRESH, max_stale, val); } void minFresh(int32_t v) {if (v < 0) return; setValue(min_fresh,v,HttpHdrCcType::CC_MIN_FRESH); } void clearMinFresh() {setValue(min_fresh,MIN_FRESH_UNKNOWN,HttpHdrCcType::CC_MIN_FRESH,false);} //manipulation for Cache-Control: only-if-cached header bool hasOnlyIfCached() const {return isSet(HttpHdrCcType::CC_ONLY_IF_CACHED);} - bool onlyIfCached() const {return isSet(HttpHdrCcType::CC_ONLY_IF_CACHED);} void onlyIfCached(bool v) {setMask(HttpHdrCcType::CC_ONLY_IF_CACHED,v);} void clearOnlyIfCached() {setMask(HttpHdrCcType::CC_ONLY_IF_CACHED,false);} //manipulation for Cache-Control: stale-if-error header - bool hasStaleIfError() const {return isSet(HttpHdrCcType::CC_STALE_IF_ERROR);} - int32_t staleIfError() const { return stale_if_error;} + bool hasStaleIfError(int32_t *val = nullptr) const { return hasDirective(HttpHdrCcType::CC_STALE_IF_ERROR, stale_if_error, val); } void staleIfError(int32_t v) {setValue(stale_if_error,v,HttpHdrCcType::CC_STALE_IF_ERROR); } void clearStaleIfError() {setValue(stale_if_error,STALE_IF_ERROR_UNKNOWN,HttpHdrCcType::CC_STALE_IF_ERROR,false);} //manipulation for Cache-Control: immutable header - bool Immutable() const {return isSet(HttpHdrCcType::CC_IMMUTABLE);} + bool hasImmutable() const {return isSet(HttpHdrCcType::CC_IMMUTABLE);} void Immutable(bool v) {setMask(HttpHdrCcType::CC_IMMUTABLE,v);} void clearImmutable() {setMask(HttpHdrCcType::CC_IMMUTABLE,false);} @@ -186,6 +175,17 @@ String private_; ///< List of headers sent as value for CC:private="...". May be empty/undefined if the value is missing. String no_cache; ///< List of headers sent as value for CC:no-cache="...". May be empty/undefined if the value is missing. + /// implements typical has*() method logic + template + bool hasDirective(const HttpHdrCcType hdrType, const Value &parsedVal, Value *outVal = nullptr) const { + if (isSet(hdrType)) { + if (outVal) + *outVal = parsedVal; + return true; + } + return false; + } + /// low-level part of the public set method, performs no checks _SQUID_INLINE_ void setMask(HttpHdrCcType id, bool newval=true); _SQUID_INLINE_ void setValue(int32_t &value, int32_t new_value, HttpHdrCcType hdr, bool setting=true); diff -u -r -N squid-4.0.19/src/HttpHeader.cc squid-4.0.20/src/HttpHeader.cc --- squid-4.0.19/src/HttpHeader.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/HttpHeader.cc 2017-06-02 00:49:17.000000000 +1200 @@ -248,7 +248,7 @@ continue; String value; const char *name = e->name.termedBuf(); - if (!getByNameIfPresent(name, strlen(name), value) || + if (!hasNamed(name, strlen(name), &value) || (value != fresh->getByName(name))) return true; } @@ -825,7 +825,7 @@ { String result; // ignore presence: return undefined string if an empty header is present - (void)getByNameIfPresent(name, strlen(name), result); + (void)hasNamed(name, strlen(name), &result); return result; } @@ -834,7 +834,7 @@ { String result; // ignore presence: return undefined string if an empty header is present - (void)getByNameIfPresent(name, result); + (void)hasNamed(name, &result); return result; } @@ -842,29 +842,30 @@ HttpHeader::getById(Http::HdrType id) const { String result; - (void)getByIdIfPresent(id,result); + (void)getByIdIfPresent(id, &result); return result; } bool -HttpHeader::getByNameIfPresent(const SBuf &s, String &result) const +HttpHeader::hasNamed(const SBuf &s, String *result) const { - return getByNameIfPresent(s.rawContent(), s.length(), result); + return hasNamed(s.rawContent(), s.length(), result); } bool -HttpHeader::getByIdIfPresent(Http::HdrType id, String &result) const +HttpHeader::getByIdIfPresent(Http::HdrType id, String *result) const { if (id == Http::HdrType::BAD_HDR) return false; if (!has(id)) return false; - result = getStrOrList(id); + if (result) + *result = getStrOrList(id); return true; } bool -HttpHeader::getByNameIfPresent(const char *name, int namelen, String &result) const +HttpHeader::hasNamed(const char *name, int namelen, String *result) const { Http::HdrType id; HttpHeaderPos pos = HttpHeaderInitPos; @@ -885,7 +886,9 @@ while ((e = getEntry(&pos))) { if (e->id == Http::HdrType::OTHER && e->name.size() == static_cast(namelen) && e->name.caseCmp(name, namelen) == 0) { found = true; - strListAdd(&result, e->value.termedBuf(), ','); + if (!result) + break; + strListAdd(result, e->value.termedBuf(), ','); } } diff -u -r -N squid-4.0.19/src/HttpHeader.h squid-4.0.20/src/HttpHeader.h --- squid-4.0.19/src/HttpHeader.h 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/HttpHeader.h 2017-06-02 00:49:17.000000000 +1200 @@ -101,11 +101,13 @@ String getByName(const SBuf &name) const; String getByName(const char *name) const; String getById(Http::HdrType id) const; - /// sets value and returns true iff a [possibly empty] field identified by id is there - bool getByIdIfPresent(Http::HdrType id, String &result) const; - /// sets value and returns true iff a [possibly empty] named field is there - bool getByNameIfPresent(const SBuf &s, String &value) const; - bool getByNameIfPresent(const char *name, int namelen, String &value) const; + /// returns true iff a [possibly empty] field identified by id is there + /// when returning true, also sets the `result` parameter (if it is not nil) + bool getByIdIfPresent(Http::HdrType id, String *result) const; + /// returns true iff a [possibly empty] named field is there + /// when returning true, also sets the `value` parameter (if it is not nil) + bool hasNamed(const SBuf &s, String *value = 0) const; + bool hasNamed(const char *name, int namelen, String *value = 0) const; String getByNameListMember(const char *name, const char *member, const char separator) const; String getListMember(Http::HdrType id, const char *member, const char separator) const; int has(Http::HdrType id) const; diff -u -r -N squid-4.0.19/src/HttpReply.cc squid-4.0.20/src/HttpReply.cc --- squid-4.0.19/src/HttpReply.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/HttpReply.cc 2017-06-02 00:49:17.000000000 +1200 @@ -262,24 +262,13 @@ /* The s-maxage and max-age directive takes priority over Expires */ if (cache_control) { - if (date >= 0) { - if (cache_control->hasSMaxAge()) - return date + cache_control->sMaxAge(); - - if (cache_control->hasMaxAge()) - return date + cache_control->maxAge(); - } else { - /* - * Conservatively handle the case when we have a max-age - * header, but no Date for reference? - */ - - if (cache_control->hasSMaxAge()) - return squid_curtime; - - if (cache_control->hasMaxAge()) - return squid_curtime; - } + int maxAge = -1; + /* + * Conservatively handle the case when we have a max-age + * header, but no Date for reference? + */ + if (cache_control->hasSMaxAge(&maxAge) || cache_control->hasMaxAge(&maxAge)) + return (date >= 0) ? date + maxAge : squid_curtime; } if (Config.onoff.vary_ignore_expire && diff -u -r -N squid-4.0.19/src/HttpRequest.cc squid-4.0.20/src/HttpRequest.cc --- squid-4.0.19/src/HttpRequest.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/HttpRequest.cc 2017-06-02 00:49:17.000000000 +1200 @@ -548,7 +548,7 @@ // // NP: refresh_pattern ignore-no-store only applies to response messages // this test is handling request message CC header. - if (!flags.ignoreCc && cache_control && cache_control->noStore()) + if (!flags.ignoreCc && cache_control && cache_control->hasNoStore()) return false; break; diff -u -r -N squid-4.0.19/src/Instance.cc squid-4.0.20/src/Instance.cc --- squid-4.0.19/src/Instance.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-4.0.20/src/Instance.cc 2017-06-02 00:49:17.000000000 +1200 @@ -0,0 +1,215 @@ +/* + * Copyright (C) 1996-2017 The Squid Software Foundation and contributors + * + * Squid software is distributed under GPLv2+ license and includes + * contributions from numerous individuals and organizations. + * Please see the COPYING and CONTRIBUTORS files for details. + */ + +#include "squid.h" +#include "base/File.h" +#include "fs_io.h" +#include "Instance.h" +#include "parser/Tokenizer.h" +#include "sbuf/Stream.h" +#include "SquidConfig.h" +#include "tools.h" + +#include + +/* To support concurrent PID files, convert local statics into PidFile class */ + +/// Describes the (last) instance PID file being processed. +/// This hack shortens reporting code while keeping its messages consistent. +static SBuf TheFile; + +/// PidFilename() helper +/// \returns PID file name or, if PID signaling was disabled, an empty SBuf +static SBuf +PidFilenameCalc() +{ + if (!Config.pidFilename || strcmp(Config.pidFilename, "none") == 0) + return SBuf(); + + // If chroot has been requested, then we first read the PID file before + // chroot() and then create/update it inside a chrooted environment. + // TODO: Consider removing half-baked chroot support from Squid. + extern bool Chrooted; + if (!Config.chroot_dir || Chrooted) // no need to compensate + return SBuf(Config.pidFilename); + + SBuf filename; + filename.append(Config.chroot_dir); + filename.append("/"); + filename.append(Config.pidFilename); + debugs(50, 3, "outside chroot: " << filename); + return filename; +} + +/// \returns PID file description for debugging messages and error reporting +static SBuf +PidFileDescription(const SBuf &filename) +{ + return ToSBuf("PID file (", filename, ')'); +} + +/// Instance entry points are expected to call this first. +/// \returns PidFilenameCalc() result while updating TheFile context +static SBuf +PidFilename() +{ + const auto name = PidFilenameCalc(); + TheFile = PidFileDescription(name); + return name; +} + +/// \returns the PID of another Squid instance (or throws) +static pid_t +GetOtherPid(File &pidFile) +{ + const auto input = pidFile.readSmall(1, 32); + int64_t rawPid = -1; + + Parser::Tokenizer tok(input); + if (!(tok.int64(rawPid, 10, false) && // PID digits + (tok.skipOne(CharacterSet::CR)||true) && // optional CR (Windows/etc.) + tok.skipOne(CharacterSet::LF) && // required end of line + tok.atEnd())) { // no trailing garbage + throw TexcHere(ToSBuf("Malformed ", TheFile)); + } + + debugs(50, 7, "found PID " << rawPid << " in " << TheFile); + + if (rawPid <= 1) + throw TexcHere(ToSBuf("Bad ", TheFile, " contains unreasonably small PID value: ", rawPid)); + const auto finalPid = static_cast(rawPid); + if (static_cast(finalPid) != rawPid) + throw TexcHere(ToSBuf("Bad ", TheFile, " contains unreasonably large PID value: ", rawPid)); + + return finalPid; +} + +/// determines whether a given process is running at the time of the call +static bool +ProcessIsRunning(const pid_t pid) +{ + const auto result = kill(pid, 0); + const auto savedErrno = errno; + if (result != 0) + debugs(50, 3, "kill(" << pid << ", 0) failed: " << xstrerr(savedErrno)); + // if we do not have permissions to signal the process, then it is running + return (result == 0 || savedErrno == EPERM); +} + +/// quits if another Squid instance (that owns the given PID file) is running +static void +ThrowIfAlreadyRunningWith(File &pidFile) +{ + bool running = false; + SBuf description; + try { + const auto pid = GetOtherPid(pidFile); + description = ToSBuf(TheFile, " with PID ", pid); + running = ProcessIsRunning(pid); + } + catch (const std::exception &ex) { + debugs(50, 5, "assuming no other Squid instance: " << ex.what()); + return; + } + + if (running) + throw TexcHere(ToSBuf("Squid is already running: Found fresh instance ", description)); + + debugs(50, 5, "assuming stale instance " << description); +} + +pid_t +Instance::Other() +{ + const auto filename = PidFilename(); + if (filename.isEmpty()) + throw TexcHere("no pid_filename configured"); + + File pidFile(filename, File::Be::ReadOnly().locked()); + return GetOtherPid(pidFile); +} + +void +Instance::ThrowIfAlreadyRunning() +{ + const auto filename = PidFilename(); + if (filename.isEmpty()) + return; // the check is impossible + + if (const auto filePtr = File::Optional(filename, File::Be::ReadOnly().locked())) { + const std::unique_ptr pidFile(filePtr); + ThrowIfAlreadyRunningWith(*pidFile); + } else { + // It is best to assume then to check because checking without a lock + // might lead to false positives that lead to no Squid starting at all! + debugs(50, 5, "cannot lock " << TheFile << "; assuming no other Squid is running"); + // If our assumption is false, we will fail to _create_ the PID file, + // and, hence, will not start, allowing that other Squid to run. + } +} + +/// ties Instance::WriteOurPid() scheduler and RemoveInstance(void) handler +static SBuf ThePidFileToRemove; + +/// atexit() handler; removes the PID file created with Instance::WriteOurPid() +static void +RemoveInstance() +{ + if (ThePidFileToRemove.isEmpty()) // not the PidFilename()! + return; // nothing to do + + debugs(50, DBG_IMPORTANT, "Removing " << PidFileDescription(ThePidFileToRemove)); + const char *filename = ThePidFileToRemove.c_str(); // avoid complex operations inside enter_suid() + enter_suid(); + safeunlink(filename, 0); + leave_suid(); + + ThePidFileToRemove.clear(); +} + +/// creates a PID file; throws on error +void +Instance::WriteOurPid() +{ + // Instance code assumes that we do not support PID filename reconfiguration + static bool called = false; + Must(!called); + called = true; + + const auto filename = PidFilename(); + if (filename.isEmpty()) + return; // nothing to do + + File pidFile(filename, File::Be::ReadWrite().locked().createdIfMissing().openedByRoot()); + + // another instance may have started after the caller checked (if it did) + ThrowIfAlreadyRunningWith(pidFile); + + /* now we know that we own the PID file created and/or locked above */ + + // Cleanup is scheduled through atexit() to ensure both: + // - cleanup upon fatal() and similar "unplanned" exits and + // - enter_suid() existence and proper logging support during cleanup. + // Even without PID filename reconfiguration support, we have to remember + // the file name we have used because Config.pidFilename may change! + (void)std::atexit(&RemoveInstance); // failures leave the PID file on disk + ThePidFileToRemove = filename; + + /* write our PID to the locked file */ + SBuf pidBuf; + pidBuf.Printf("%d\n", static_cast(getpid())); + pidFile.truncate(); + pidFile.writeAll(pidBuf); + + // We must fsync before releasing the lock or other Squid processes may not see + // our written PID (and decide that they are dealing with a corrupted PID file). + pidFile.synchronize(); + + debugs(50, DBG_IMPORTANT, "Created " << TheFile); +} + diff -u -r -N squid-4.0.19/src/Instance.h squid-4.0.20/src/Instance.h --- squid-4.0.19/src/Instance.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-4.0.20/src/Instance.h 2017-06-02 00:49:17.000000000 +1200 @@ -0,0 +1,36 @@ +/* + * Copyright (C) 1996-2017 The Squid Software Foundation and contributors + * + * Squid software is distributed under GPLv2+ license and includes + * contributions from numerous individuals and organizations. + * Please see the COPYING and CONTRIBUTORS files for details. + */ + +#ifndef SQUID_INSTANCE_H +#define SQUID_INSTANCE_H + +#if HAVE_SYS_TYPES_H +#include +#endif + +/// code related to Squid Instance and PID file management +namespace Instance { + +/// Usually throws if another Squid instance is running. False positives are +/// highly unlikely, but the caller must tolerate false negatives well: +/// We may not detect another running instance and, hence, may not throw. +/// Does nothing if PID file maintenance is disabled. +void ThrowIfAlreadyRunning(); + +/// Creates or updates the PID file for the current process. +/// Does nothing if PID file maintenance is disabled. +void WriteOurPid(); + +/// \returns another Squid instance PID +/// Throws if PID file maintenance is disabled. +pid_t Other(); + +} // namespace Instance + +#endif + diff -u -r -N squid-4.0.19/src/log/DB/log_db_daemon.8 squid-4.0.20/src/log/DB/log_db_daemon.8 --- squid-4.0.19/src/log/DB/log_db_daemon.8 2017-04-02 23:50:09.000000000 +1200 +++ squid-4.0.20/src/log/DB/log_db_daemon.8 2017-06-02 09:57:57.000000000 +1200 @@ -129,7 +129,7 @@ .\" ======================================================================== .\" .IX Title "LOG_DB_DAEMON 8" -.TH LOG_DB_DAEMON 8 "2017-04-02" "perl v5.24.1" "User Contributed Perl Documentation" +.TH LOG_DB_DAEMON 8 "2017-06-01" "perl v5.24.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff -u -r -N squid-4.0.19/src/main.cc squid-4.0.20/src/main.cc --- squid-4.0.19/src/main.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/main.cc 2017-06-02 00:49:17.000000000 +1200 @@ -46,6 +46,7 @@ #include "icmp/net_db.h" #include "ICP.h" #include "ident/Ident.h" +#include "Instance.h" #include "ip/tools.h" #include "ipc/Coordinator.h" #include "ipc/Kids.h" @@ -61,6 +62,7 @@ #include "profiler/Profiler.h" #include "redirect.h" #include "refresh.h" +#include "sbuf/Stream.h" #include "SBufStatsAction.h" #include "send-announce.h" #include "SquidConfig.h" @@ -171,7 +173,6 @@ static void setEffectiveUser(void); static void SquidShutdown(void); static void mainSetCwd(void); -static int checkRunningPid(void); #if !_SQUID_WINDOWS_ static const char *squid_start_script = "squid_start"; @@ -662,6 +663,10 @@ printf("Service Name: " SQUIDSBUFPH "\n", SQUIDSBUFPRINT(service_name)); if (strlen(SQUID_BUILD_INFO)) printf("%s\n",SQUID_BUILD_INFO); +#if USE_OPENSSL + printf("\nThis binary uses %s. ", SSLeay_version(SSLEAY_VERSION)); + printf("For legal restrictions on distribution see https://www.openssl.org/source/license.html\n\n"); +#endif printf( "configure options: %s\n", SQUID_CONFIGURE_OPTIONS); #if USE_WIN32_SERVICE @@ -1003,9 +1008,6 @@ eventDelete(start_announce, NULL); } - if (!InDaemonMode()) - writePidFile(); /* write PID file */ - reconfiguring = 0; } @@ -1069,13 +1071,16 @@ return false; } +/// Hack: Have we called chroot()? This exposure is needed because some code has +/// to open the same files before and after chroot() +bool Chrooted = false; + /// set the working directory. static void mainSetCwd(void) { - static bool chrooted = false; - if (Config.chroot_dir && !chrooted) { - chrooted = true; + if (Config.chroot_dir && !Chrooted) { + Chrooted = true; if (chroot(Config.chroot_dir) != 0) { int xerrno = errno; @@ -1257,9 +1262,6 @@ if (Config.chroot_dir) no_suid(); - if (!configured_once && !InDaemonMode()) - writePidFile(); /* write PID file */ - #if defined(_SQUID_LINUX_THREADS_) squid_signal(SIGQUIT, rotate_logs, SA_RESTART); @@ -1373,14 +1375,11 @@ try { return SquidMain(argc, argv); } catch (const std::exception &e) { - debugs(1, DBG_CRITICAL, "FATAL: dying from an unhandled exception: " << - e.what()); - throw; + debugs(1, DBG_CRITICAL, "FATAL: " << e.what()); } catch (...) { debugs(1, DBG_CRITICAL, "FATAL: dying from an unhandled exception."); - throw; } - return -1; // not reached + return -1; // TODO: return EXIT_FAILURE instead } /// computes name and ID for the current kid process @@ -1409,6 +1408,12 @@ } } +static void StartUsingConfig() +{ + RunRegisteredHere(RegisteredRunner::claimMemoryNeeds); + RunRegisteredHere(RegisteredRunner::useConfig); +} + int SquidMain(int argc, char **argv) { @@ -1536,9 +1541,12 @@ return parse_err; } setUmask(Config.umask); - if (-1 == opt_send_signal) - if (checkRunningPid()) - exit(0); + + // Master optimization: Where possible, avoid pointless daemon fork() and/or + // pointless wait for the exclusive PID file lock. This optional/weak check + // is not applicable to kids because they always co-exist with their master. + if (opt_send_signal == -1 && IamMasterProcess()) + Instance::ThrowIfAlreadyRunning(); #if TEST_ACCESS @@ -1563,21 +1571,25 @@ } sendSignal(); - /* NOTREACHED */ + return 0; } debugs(1,2, HERE << "Doing post-config initialization\n"); leave_suid(); RunRegisteredHere(RegisteredRunner::finalizeConfig); - RunRegisteredHere(RegisteredRunner::claimMemoryNeeds); - RunRegisteredHere(RegisteredRunner::useConfig); - enter_suid(); - if (InDaemonMode() && IamMasterProcess()) { - watch_child(argv); - // NOTREACHED + if (IamMasterProcess()) { + if (InDaemonMode()) { + watch_child(argv); + // NOTREACHED + } else { + Instance::WriteOurPid(); + } } + StartUsingConfig(); + enter_suid(); + if (opt_create_swap_dirs) { /* chroot if configured to run inside chroot */ mainSetCwd(); @@ -1667,50 +1679,26 @@ static void sendSignal(void) { - pid_t pid; debug_log = stderr; - if (strcmp(Config.pidFilename, "none") == 0) { - debugs(0, DBG_IMPORTANT, "No pid_filename specified. Trusting you know what you are doing."); - } - - pid = readPidFile(); - - if (pid > 1) { #if USE_WIN32_SERVICE - if (opt_signal_service) { - WIN32_sendSignal(opt_send_signal); - exit(0); - } else { - fprintf(stderr, "%s: ERROR: Could not send ", APP_SHORTNAME); - fprintf(stderr, "signal to Squid Service:\n"); - fprintf(stderr, "missing -n command line switch.\n"); - exit(1); - } - /* NOTREACHED */ -#endif - - if (kill(pid, opt_send_signal) && - /* ignore permissions if just running check */ - !(opt_send_signal == 0 && errno == EPERM)) { - int xerrno = errno; - fprintf(stderr, "%s: ERROR: Could not send ", APP_SHORTNAME); - fprintf(stderr, "signal %d to process %d: %s\n", - opt_send_signal, (int) pid, xstrerr(xerrno)); - exit(1); - } - } else { - if (opt_send_signal != SIGTERM) { - fprintf(stderr, "%s: ERROR: No running copy\n", APP_SHORTNAME); - exit(1); - } else { - fprintf(stderr, "%s: No running copy\n", APP_SHORTNAME); - exit(0); - } + // WIN32_sendSignal() does not need the PID value to signal, + // but we must exit if there is no valid PID (TODO: Why?). + (void)Instance::Other(); + if (!opt_signal_service) + throw TexcHere("missing -n command line switch"); + WIN32_sendSignal(opt_send_signal); +#else + const auto pid = Instance::Other(); + if (kill(pid, opt_send_signal) && + /* ignore permissions if just running check */ + !(opt_send_signal == 0 && errno == EPERM)) { + const auto savedErrno = errno; + throw TexcHere(ToSBuf("failed to send signal ", opt_send_signal, + " to Squid instance with PID ", pid, ": ", xstrerr(savedErrno))); } - +#endif /* signal successfully sent */ - exit(0); } #if !_SQUID_WINDOWS_ @@ -1751,31 +1739,6 @@ #endif /* _SQUID_WINDOWS_ */ -static int -checkRunningPid(void) -{ - // master process must start alone, but its kids processes may co-exist - if (!IamMasterProcess()) - return 0; - - pid_t pid; - - if (!debug_log) - debug_log = stderr; - - pid = readPidFile(); - - if (pid < 2) - return 0; - - if (kill(pid, 0) < 0) - return 0; - - debugs(0, DBG_CRITICAL, "Squid is already running! Process ID " << pid); - - return 1; -} - #if !_SQUID_WINDOWS_ static void masterCheckAndBroadcastSignals() @@ -1813,6 +1776,8 @@ int nullfd; + enter_suid(); + openlog(APP_SHORTNAME, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4); if ((pid = fork()) < 0) { @@ -1866,8 +1831,10 @@ dup2(nullfd, 2); } - writePidFile(); - enter_suid(); // writePidFile() uses leave_suid() + leave_suid(); + Instance::WriteOurPid(); + StartUsingConfig(); + enter_suid(); #if defined(_SQUID_LINUX_THREADS_) squid_signal(SIGQUIT, rotate_logs, 0); @@ -1973,8 +1940,6 @@ RunRegisteredHere(RegisteredRunner::finishShutdown); enter_suid(); - removePidFile(); - enter_suid(); // removePidFile() uses leave_suid() if (TheKids.someSignaled(SIGINT) || TheKids.someSignaled(SIGTERM)) { syslog(LOG_ALERT, "Exiting due to unexpected forced shutdown"); exit(1); @@ -2094,10 +2059,6 @@ memClean(); - if (!InDaemonMode()) { - removePidFile(); - } - debugs(1, DBG_IMPORTANT, "Squid Cache (Version " << version_string << "): Exiting normally."); /* diff -u -r -N squid-4.0.19/src/Makefile.am squid-4.0.20/src/Makefile.am --- squid-4.0.19/src/Makefile.am 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/Makefile.am 2017-06-02 00:49:17.000000000 +1200 @@ -348,6 +348,8 @@ icp_opcode.h \ icp_v2.cc \ icp_v3.cc \ + Instance.h \ + Instance.cc \ int.h \ int.cc \ internal.h \ @@ -1159,6 +1161,7 @@ tests/testBoilerplate.h \ tests/stub_debug.cc \ tests/stub_libmem.cc \ + tests/stub_SBuf.cc \ tests/stub_time.cc nodist_tests_testBoilerplate_SOURCES = \ tests/stub_cbdata.cc \ @@ -1182,7 +1185,8 @@ tests/stub_cbdata.cc \ tests/stub_debug.cc \ tests/stub_libmem.cc \ - tests/stub_MemBuf.cc + tests/stub_MemBuf.cc \ + tests/stub_SBuf.cc tests_testCharacterSet_LDFLAGS = $(LIBADD_DL) tests_testCharacterSet_LDADD= \ base/libbase.la \ @@ -2638,6 +2642,7 @@ SquidTime.h \ tests/stub_debug.cc \ tests/stub_libmem.cc \ + tests/stub_SBuf.cc \ time.cc \ globals.cc tests_testIcmp_LDFLAGS = $(LIBADD_DL) @@ -2656,6 +2661,7 @@ SquidTime.h \ tests/stub_debug.cc \ tests/stub_libmem.cc \ + tests/stub_SBuf.cc \ time.cc \ globals.cc tests_testNetDb_LDFLAGS = $(LIBADD_DL) @@ -3621,6 +3627,7 @@ base/EnumIterator.h \ tests/stub_debug.cc \ tests/stub_libmem.cc \ + tests/stub_SBuf.cc \ tests/testEnumIterator.h \ tests/testEnumIterator.cc nodist_tests_testEnumIterator_SOURCES = \ @@ -3639,6 +3646,7 @@ tests/STUB.h \ tests/stub_debug.cc \ tests/stub_libmem.cc \ + tests/stub_SBuf.cc \ base/YesNoNone.h tests_testYesNoNone_LDADD= \ base/libbase.la \ diff -u -r -N squid-4.0.19/src/Makefile.in squid-4.0.20/src/Makefile.in --- squid-4.0.19/src/Makefile.in 2017-04-02 19:45:34.000000000 +1200 +++ squid-4.0.20/src/Makefile.in 2017-06-02 00:54:20.000000000 +1200 @@ -273,14 +273,14 @@ HttpHeaderTools.cc HttpBody.h HttpBody.cc HttpControlMsg.cc \ HttpControlMsg.h HttpMsg.cc HttpMsg.h HttpReply.cc HttpReply.h \ RequestFlags.h RequestFlags.cc HttpRequest.cc HttpRequest.h \ - ICP.h icp_opcode.h icp_v2.cc icp_v3.cc int.h int.cc internal.h \ - internal.cc SquidIpc.h ipc.cc ipc_win32.cc ipcache.cc \ - ipcache.h LeakFinder.cc LogTags.cc LogTags.h lookup_t.h \ - main.cc MasterXaction.cc MasterXaction.h mem_node.cc \ - mem_node.h MemBuf.cc MemObject.cc MemObject.h MessageSizes.h \ - mime.h mime.cc mime_header.h mime_header.cc multicast.h \ - multicast.cc neighbors.h neighbors.cc Notes.h Notes.cc \ - Parsing.cc Parsing.h ProfStats.cc pconn.cc pconn.h \ + ICP.h icp_opcode.h icp_v2.cc icp_v3.cc Instance.h Instance.cc \ + int.h int.cc internal.h internal.cc SquidIpc.h ipc.cc \ + ipc_win32.cc ipcache.cc ipcache.h LeakFinder.cc LogTags.cc \ + LogTags.h lookup_t.h main.cc MasterXaction.cc MasterXaction.h \ + mem_node.cc mem_node.h MemBuf.cc MemObject.cc MemObject.h \ + MessageSizes.h mime.h mime.cc mime_header.h mime_header.cc \ + multicast.h multicast.cc neighbors.h neighbors.cc Notes.h \ + Notes.cc Parsing.cc Parsing.h ProfStats.cc pconn.cc pconn.h \ PeerDigest.h peer_digest.cc peer_proxy_negotiate_auth.h \ peer_proxy_negotiate_auth.cc peer_select.cc peer_sourcehash.h \ peer_sourcehash.cc peer_userhash.h peer_userhash.cc \ @@ -357,13 +357,13 @@ HttpBody.$(OBJEXT) HttpControlMsg.$(OBJEXT) HttpMsg.$(OBJEXT) \ HttpReply.$(OBJEXT) RequestFlags.$(OBJEXT) \ HttpRequest.$(OBJEXT) icp_v2.$(OBJEXT) icp_v3.$(OBJEXT) \ - int.$(OBJEXT) internal.$(OBJEXT) $(am__objects_6) \ - ipcache.$(OBJEXT) $(am__objects_7) LogTags.$(OBJEXT) \ - main.$(OBJEXT) MasterXaction.$(OBJEXT) mem_node.$(OBJEXT) \ - MemBuf.$(OBJEXT) MemObject.$(OBJEXT) mime.$(OBJEXT) \ - mime_header.$(OBJEXT) multicast.$(OBJEXT) neighbors.$(OBJEXT) \ - Notes.$(OBJEXT) Parsing.$(OBJEXT) $(am__objects_8) \ - pconn.$(OBJEXT) peer_digest.$(OBJEXT) \ + Instance.$(OBJEXT) int.$(OBJEXT) internal.$(OBJEXT) \ + $(am__objects_6) ipcache.$(OBJEXT) $(am__objects_7) \ + LogTags.$(OBJEXT) main.$(OBJEXT) MasterXaction.$(OBJEXT) \ + mem_node.$(OBJEXT) MemBuf.$(OBJEXT) MemObject.$(OBJEXT) \ + mime.$(OBJEXT) mime_header.$(OBJEXT) multicast.$(OBJEXT) \ + neighbors.$(OBJEXT) Notes.$(OBJEXT) Parsing.$(OBJEXT) \ + $(am__objects_8) pconn.$(OBJEXT) peer_digest.$(OBJEXT) \ peer_proxy_negotiate_auth.$(OBJEXT) peer_select.$(OBJEXT) \ peer_sourcehash.$(OBJEXT) peer_userhash.$(OBJEXT) \ PeerPoolMgr.$(OBJEXT) Pipeline.$(OBJEXT) redirect.$(OBJEXT) \ @@ -499,7 +499,7 @@ $(LDFLAGS) -o $@ am_tests_testBoilerplate_OBJECTS = tests/testBoilerplate.$(OBJEXT) \ tests/stub_debug.$(OBJEXT) tests/stub_libmem.$(OBJEXT) \ - tests/stub_time.$(OBJEXT) + tests/stub_SBuf.$(OBJEXT) tests/stub_time.$(OBJEXT) nodist_tests_testBoilerplate_OBJECTS = tests/stub_cbdata.$(OBJEXT) \ tests/stub_MemBuf.$(OBJEXT) $(am__objects_18) tests_testBoilerplate_OBJECTS = $(am_tests_testBoilerplate_OBJECTS) \ @@ -652,7 +652,8 @@ am_tests_testCharacterSet_OBJECTS = tests/testCharacterSet.$(OBJEXT) nodist_tests_testCharacterSet_OBJECTS = $(am__objects_18) \ tests/stub_cbdata.$(OBJEXT) tests/stub_debug.$(OBJEXT) \ - tests/stub_libmem.$(OBJEXT) tests/stub_MemBuf.$(OBJEXT) + tests/stub_libmem.$(OBJEXT) tests/stub_MemBuf.$(OBJEXT) \ + tests/stub_SBuf.$(OBJEXT) tests_testCharacterSet_OBJECTS = $(am_tests_testCharacterSet_OBJECTS) \ $(nodist_tests_testCharacterSet_OBJECTS) tests_testCharacterSet_DEPENDENCIES = base/libbase.la \ @@ -801,7 +802,8 @@ $(AM_CXXFLAGS) $(CXXFLAGS) $(tests_testDns_LDFLAGS) $(LDFLAGS) \ -o $@ am_tests_testEnumIterator_OBJECTS = tests/stub_debug.$(OBJEXT) \ - tests/stub_libmem.$(OBJEXT) tests/testEnumIterator.$(OBJEXT) + tests/stub_libmem.$(OBJEXT) tests/stub_SBuf.$(OBJEXT) \ + tests/testEnumIterator.$(OBJEXT) nodist_tests_testEnumIterator_OBJECTS = $(am__objects_18) tests_testEnumIterator_OBJECTS = $(am_tests_testEnumIterator_OBJECTS) \ $(nodist_tests_testEnumIterator_OBJECTS) @@ -1297,7 +1299,8 @@ $(LDFLAGS) -o $@ am_tests_testIcmp_OBJECTS = tests/testIcmp.$(OBJEXT) nodist_tests_testIcmp_OBJECTS = tests/stub_debug.$(OBJEXT) \ - tests/stub_libmem.$(OBJEXT) time.$(OBJEXT) globals.$(OBJEXT) + tests/stub_libmem.$(OBJEXT) tests/stub_SBuf.$(OBJEXT) \ + time.$(OBJEXT) globals.$(OBJEXT) tests_testIcmp_OBJECTS = $(am_tests_testIcmp_OBJECTS) \ $(nodist_tests_testIcmp_OBJECTS) tests_testIcmp_DEPENDENCIES = icmp/libicmpcore.la ip/libip.la \ @@ -1334,7 +1337,8 @@ $(LDFLAGS) -o $@ am_tests_testNetDb_OBJECTS = tests/testNetDb.$(OBJEXT) nodist_tests_testNetDb_OBJECTS = tests/stub_debug.$(OBJEXT) \ - tests/stub_libmem.$(OBJEXT) time.$(OBJEXT) globals.$(OBJEXT) + tests/stub_libmem.$(OBJEXT) tests/stub_SBuf.$(OBJEXT) \ + time.$(OBJEXT) globals.$(OBJEXT) tests_testNetDb_OBJECTS = $(am_tests_testNetDb_OBJECTS) \ $(nodist_tests_testNetDb_OBJECTS) tests_testNetDb_DEPENDENCIES = icmp/libicmp.la ip/libip.la \ @@ -1885,7 +1889,7 @@ -o $@ am_tests_testYesNoNone_OBJECTS = tests/testYesNoNone.$(OBJEXT) nodist_tests_testYesNoNone_OBJECTS = tests/stub_debug.$(OBJEXT) \ - tests/stub_libmem.$(OBJEXT) + tests/stub_libmem.$(OBJEXT) tests/stub_SBuf.$(OBJEXT) tests_testYesNoNone_OBJECTS = $(am_tests_testYesNoNone_OBJECTS) \ $(nodist_tests_testYesNoNone_OBJECTS) tests_testYesNoNone_DEPENDENCIES = base/libbase.la \ @@ -2870,15 +2874,15 @@ HttpBody.h HttpBody.cc HttpControlMsg.cc HttpControlMsg.h \ HttpMsg.cc HttpMsg.h HttpReply.cc HttpReply.h RequestFlags.h \ RequestFlags.cc HttpRequest.cc HttpRequest.h ICP.h \ - icp_opcode.h icp_v2.cc icp_v3.cc int.h int.cc internal.h \ - internal.cc $(IPC_SOURCE) ipcache.cc ipcache.h \ - $(LEAKFINDERSOURCE) LogTags.cc LogTags.h lookup_t.h main.cc \ - MasterXaction.cc MasterXaction.h mem_node.cc mem_node.h \ - MemBuf.cc MemObject.cc MemObject.h MessageSizes.h mime.h \ - mime.cc mime_header.h mime_header.cc multicast.h multicast.cc \ - neighbors.h neighbors.cc Notes.h Notes.cc Parsing.cc Parsing.h \ - $(XPROF_STATS_SOURCE) pconn.cc pconn.h PeerDigest.h \ - peer_digest.cc peer_proxy_negotiate_auth.h \ + icp_opcode.h icp_v2.cc icp_v3.cc Instance.h Instance.cc int.h \ + int.cc internal.h internal.cc $(IPC_SOURCE) ipcache.cc \ + ipcache.h $(LEAKFINDERSOURCE) LogTags.cc LogTags.h lookup_t.h \ + main.cc MasterXaction.cc MasterXaction.h mem_node.cc \ + mem_node.h MemBuf.cc MemObject.cc MemObject.h MessageSizes.h \ + mime.h mime.cc mime_header.h mime_header.cc multicast.h \ + multicast.cc neighbors.h neighbors.cc Notes.h Notes.cc \ + Parsing.cc Parsing.h $(XPROF_STATS_SOURCE) pconn.cc pconn.h \ + PeerDigest.h peer_digest.cc peer_proxy_negotiate_auth.h \ peer_proxy_negotiate_auth.cc peer_select.cc peer_sourcehash.h \ peer_sourcehash.cc peer_userhash.h peer_userhash.cc \ PeerPoolMgr.h PeerPoolMgr.cc PeerSelectState.h PingData.h \ @@ -3422,6 +3426,7 @@ tests/testBoilerplate.h \ tests/stub_debug.cc \ tests/stub_libmem.cc \ + tests/stub_SBuf.cc \ tests/stub_time.cc nodist_tests_testBoilerplate_SOURCES = \ @@ -3447,7 +3452,8 @@ tests/stub_cbdata.cc \ tests/stub_debug.cc \ tests/stub_libmem.cc \ - tests/stub_MemBuf.cc + tests/stub_MemBuf.cc \ + tests/stub_SBuf.cc tests_testCharacterSet_LDFLAGS = $(LIBADD_DL) tests_testCharacterSet_LDADD = \ @@ -4920,6 +4926,7 @@ SquidTime.h \ tests/stub_debug.cc \ tests/stub_libmem.cc \ + tests/stub_SBuf.cc \ time.cc \ globals.cc @@ -4940,6 +4947,7 @@ SquidTime.h \ tests/stub_debug.cc \ tests/stub_libmem.cc \ + tests/stub_SBuf.cc \ time.cc \ globals.cc @@ -5916,6 +5924,7 @@ base/EnumIterator.h \ tests/stub_debug.cc \ tests/stub_libmem.cc \ + tests/stub_SBuf.cc \ tests/testEnumIterator.h \ tests/testEnumIterator.cc @@ -5937,6 +5946,7 @@ tests/STUB.h \ tests/stub_debug.cc \ tests/stub_libmem.cc \ + tests/stub_SBuf.cc \ base/YesNoNone.h tests_testYesNoNone_LDADD = \ @@ -6268,6 +6278,8 @@ $(AM_V_CXXLD)$(tests_testACLMaxUserIP_LINK) $(tests_testACLMaxUserIP_OBJECTS) $(tests_testACLMaxUserIP_LDADD) $(LIBS) tests/testBoilerplate.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) +tests/stub_SBuf.$(OBJEXT): tests/$(am__dirstamp) \ + tests/$(DEPDIR)/$(am__dirstamp) tests/testBoilerplate$(EXEEXT): $(tests_testBoilerplate_OBJECTS) $(tests_testBoilerplate_DEPENDENCIES) $(EXTRA_tests_testBoilerplate_DEPENDENCIES) tests/$(am__dirstamp) @rm -f tests/testBoilerplate$(EXEEXT) @@ -6354,8 +6366,6 @@ $(AM_V_CXXLD)$(tests_testDiskIO_LINK) $(tests_testDiskIO_OBJECTS) $(tests_testDiskIO_LDADD) $(LIBS) tests/testRFC1035.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) -tests/stub_SBuf.$(OBJEXT): tests/$(am__dirstamp) \ - tests/$(DEPDIR)/$(am__dirstamp) tests/testDns$(EXEEXT): $(tests_testDns_OBJECTS) $(tests_testDns_DEPENDENCIES) $(EXTRA_tests_testDns_DEPENDENCIES) tests/$(am__dirstamp) @rm -f tests/testDns$(EXEEXT) @@ -6569,6 +6579,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpMsg.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpReply.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpRequest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Instance.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LeakFinder.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LoadableModule.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LoadableModules.Po@am__quote@ diff -u -r -N squid-4.0.19/src/neighbors.cc squid-4.0.20/src/neighbors.cc --- squid-4.0.19/src/neighbors.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/neighbors.cc 2017-06-02 00:49:17.000000000 +1200 @@ -59,7 +59,7 @@ static void neighborCountIgnored(CachePeer *); static void peerRefreshDNS(void *); static IPH peerDNSConfigure; -static bool peerProbeConnect(CachePeer *); +static void peerProbeConnect(CachePeer *, const bool reprobeIfBusy = false); static CNCB peerProbeConnectDone; static void peerCountMcastPeersDone(void *data); static void peerCountMcastPeersStart(void *data); @@ -1123,10 +1123,8 @@ neighborUp(const CachePeer * p) { if (!p->tcp_up) { - if (!peerProbeConnect((CachePeer *) p)) { - debugs(15, 8, "neighborUp: DOWN (probed): " << p->host << " (" << p->in_addr << ")"); - return 0; - } + peerProbeConnect(const_cast(p)); + return 0; } /* @@ -1161,6 +1159,20 @@ #endif } +/// \returns the effective connect timeout for this peer +time_t +peerConnectTimeout(const CachePeer *peer) +{ + return peer->connect_timeout_raw > 0 ? + peer->connect_timeout_raw : Config.Timeout.peer_connect; +} + +time_t +positiveTimeout(const time_t timeout) +{ + return max(static_cast(1), timeout); +} + static void peerDNSConfigure(const ipcache_addrs *ia, const Dns::LookupDetails &, void *data) { @@ -1190,8 +1202,6 @@ return; } - p->tcp_up = p->connect_fail_limit; - for (j = 0; j < (int) ia->count && j < PEER_MAX_ADDRESSES; ++j) { p->addresses[j] = ia->in_addrs[j]; debugs(15, 2, "--> IP address #" << j << ": " << p->addresses[j]); @@ -1202,6 +1212,8 @@ p->in_addr = p->addresses[0]; p->in_addr.port(p->icp.port); + peerProbeConnect(p, true); // detect any died or revived peers ASAP + if (p->type == PEER_MULTICAST) peerCountMcastPeersSchedule(p, 10); @@ -1275,21 +1287,33 @@ p->tcp_up = p->connect_fail_limit; } +/// whether new TCP probes are currently banned +static bool +peerProbeIsBusy(const CachePeer *p) +{ + if (p->testing_now > 0) { + debugs(15, 8, "yes, probing " << p); + return true; + } + if (squid_curtime - p->stats.last_connect_probe == 0) { + debugs(15, 8, "yes, just probed " << p); + return true; + } + return false; +} /* * peerProbeConnect will be called on dead peers by neighborUp */ -static bool -peerProbeConnect(CachePeer * p) +static void +peerProbeConnect(CachePeer *p, const bool reprobeIfBusy) { - time_t ctimeout = p->connect_timeout > 0 ? p->connect_timeout : Config.Timeout.peer_connect; - bool ret = (squid_curtime - p->stats.last_connect_failure) > (ctimeout * 10); - - if (p->testing_now > 0) - return ret;/* probe already running */ - - if (squid_curtime - p->stats.last_connect_probe == 0) - return ret;/* don't probe to often */ + if (peerProbeIsBusy(p)) { + p->reprobe = reprobeIfBusy; + return; + } + p->reprobe = false; + const time_t ctimeout = peerConnectTimeout(p); /* for each IP address of this CachePeer. find one that we can connect to and probe it. */ for (int i = 0; i < p->n_addresses; ++i) { Comm::ConnectionPointer conn = new Comm::Connection; @@ -1307,8 +1331,6 @@ } p->stats.last_connect_probe = squid_curtime; - - return ret; } static void @@ -1325,6 +1347,9 @@ -- p->testing_now; conn->close(); // TODO: log this traffic. + + if (p->reprobe) + peerProbeConnect(p); } static void @@ -1528,8 +1553,8 @@ if (p->mcast.ttl > 0) storeAppendPrintf(sentry, " ttl=%d", p->mcast.ttl); - if (p->connect_timeout > 0) - storeAppendPrintf(sentry, " connect-timeout=%d", (int) p->connect_timeout); + if (p->connect_timeout_raw > 0) + storeAppendPrintf(sentry, " connect-timeout=%d", (int)p->connect_timeout_raw); if (p->connect_fail_limit != PEER_TCP_MAGIC_COUNT) storeAppendPrintf(sentry, " connect-fail-limit=%d", p->connect_fail_limit); diff -u -r -N squid-4.0.19/src/neighbors.h squid-4.0.20/src/neighbors.h --- squid-4.0.19/src/neighbors.h 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/neighbors.h 2017-06-02 00:49:17.000000000 +1200 @@ -60,6 +60,13 @@ void dump_peer_options(StoreEntry *, CachePeer *); int peerHTTPOkay(const CachePeer *, HttpRequest *); +// TODO: Consider moving this method to CachePeer class. +/// \returns the effective connect timeout for the given peer +time_t peerConnectTimeout(const CachePeer *peer); + +/// \returns max(1, timeout) +time_t positiveTimeout(const time_t timeout); + /// Whether we can open new connections to the peer (e.g., despite max-conn) bool peerCanOpenMore(const CachePeer *p); /// Whether the peer has idle or standby connections that can be used now diff -u -r -N squid-4.0.19/src/PeerPoolMgr.cc squid-4.0.20/src/PeerPoolMgr.cc --- squid-4.0.19/src/PeerPoolMgr.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/PeerPoolMgr.cc 2017-06-02 00:49:17.000000000 +1200 @@ -118,11 +118,10 @@ securer = asyncCall(48, 4, "PeerPoolMgr::handleSecuredPeer", MyAnswerDialer(this, &PeerPoolMgr::handleSecuredPeer)); - const int peerTimeout = peer->connect_timeout > 0 ? - peer->connect_timeout : Config.Timeout.peer_connect; + const int peerTimeout = peerConnectTimeout(peer); const int timeUsed = squid_curtime - params.conn->startTime(); // Use positive timeout when less than one second is left for conn. - const int timeLeft = max(1, (peerTimeout - timeUsed)); + const int timeLeft = positiveTimeout(peerTimeout - timeUsed); auto *connector = new Security::BlindPeerConnector(request, params.conn, securer, nullptr, timeLeft); AsyncJob::Start(connector); // will call our callback return; @@ -224,8 +223,7 @@ getOutgoingAddress(request.getRaw(), conn); GetMarkingsToServer(request.getRaw(), *conn); - const int ctimeout = peer->connect_timeout > 0 ? - peer->connect_timeout : Config.Timeout.peer_connect; + const int ctimeout = peerConnectTimeout(peer); typedef CommCbMemFunT Dialer; opener = JobCallback(48, 5, Dialer, this, PeerPoolMgr::handleOpenedConnection); Comm::ConnOpener *cs = new Comm::ConnOpener(conn, opener, ctimeout); diff -u -r -N squid-4.0.19/src/refresh.cc squid-4.0.20/src/refresh.cc --- squid-4.0.19/src/refresh.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/refresh.cc 2017-06-02 00:49:17.000000000 +1200 @@ -309,8 +309,8 @@ if (request && !request->flags.ignoreCc) { const HttpHdrCc *const cc = request->cache_control; - if (cc && cc->hasMinFresh()) { - const int32_t minFresh=cc->minFresh(); + int minFresh = -1; + if (cc && cc->hasMinFresh(&minFresh)) { debugs(22, 3, "\tage + min-fresh:\t" << age << " + " << minFresh << " = " << age + minFresh); debugs(22, 3, "\tcheck_time + min-fresh:\t" << check_time << " + " @@ -330,9 +330,10 @@ const auto *reply = (entry->mem_obj && entry->mem_obj->getReply() ? entry->mem_obj->getReply() : nullptr); // stale-if-error requires any failure be passed thru when its period is over. + int staleIfError = -1; if (request && reply && reply->cache_control && - reply->cache_control->hasStaleIfError() && - reply->cache_control->staleIfError() < staleness) { + reply->cache_control->hasStaleIfError(&staleIfError) && + staleIfError < staleness) { debugs(22, 3, "stale-if-error period expired. Will produce error if validation fails."); request->flags.failOnValidationError = true; @@ -416,32 +417,34 @@ if (NULL != cc) { // max-age directive - if (cc->hasMaxAge()) { + int maxAge = -1; + if (cc->hasMaxAge(&maxAge)) { // draft-mcmanus-immutable-00: reply contains CC:immutable then ignore client CC:max-age=N - if (reply && reply->cache_control && reply->cache_control->Immutable()) { - debugs(22, 3, "MAYBE: Ignoring client CC:max-age=" << cc->maxAge() << " request - 'Cache-Control: immutable'"); + if (reply && reply->cache_control && reply->cache_control->hasImmutable()) { + debugs(22, 3, "MAYBE: Ignoring client CC:max-age=" << maxAge << " request - 'Cache-Control: immutable'"); #if USE_HTTP_VIOLATIONS // Ignore of client "Cache-Control: max-age=0" header - } else if (R->flags.ignore_reload && cc->maxAge() == 0) { + } else if (R->flags.ignore_reload && maxAge == 0) { debugs(22, 3, "MAYBE: Ignoring client reload request - trying to serve from cache (ignore-reload option)"); #endif // Honour client "Cache-Control: max-age=x" header - } else if (age > cc->maxAge() || cc->maxAge() == 0) { - debugs(22, 3, "YES: Revalidating object - client 'Cache-Control: max-age=" << cc->maxAge() << "'"); + } else if (age > maxAge || maxAge == 0) { + debugs(22, 3, "YES: Revalidating object - client 'Cache-Control: max-age=" << maxAge << "'"); return STALE_EXCEEDS_REQUEST_MAX_AGE_VALUE; } } // max-stale directive - if (cc->hasMaxStale() && staleness > -1) { - if (cc->maxStale()==HttpHdrCc::MAX_STALE_ANY) { + int maxStale = -1; + if (cc->hasMaxStale(&maxStale) && staleness > -1) { + if (maxStale==HttpHdrCc::MAX_STALE_ANY) { debugs(22, 3, "NO: Client accepts a stale response of any age - 'Cache-Control: max-stale'"); return FRESH_REQUEST_MAX_STALE_ALL; - } else if (staleness < cc->maxStale()) { - debugs(22, 3, "NO: Client accepts a stale response - 'Cache-Control: max-stale=" << cc->maxStale() << "'"); + } else if (staleness < maxStale) { + debugs(22, 3, "NO: Client accepts a stale response - 'Cache-Control: max-stale=" << maxStale << "'"); return FRESH_REQUEST_MAX_STALE_VALUE; } } diff -u -r -N squid-4.0.19/src/sbuf/Exceptions.cc squid-4.0.20/src/sbuf/Exceptions.cc --- squid-4.0.19/src/sbuf/Exceptions.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/sbuf/Exceptions.cc 2017-06-02 00:49:17.000000000 +1200 @@ -25,9 +25,7 @@ explanatoryText.appendf(" in file %s", aFileName); explanatoryText.appendf(" while accessing position %d in a SBuf long %d", pos, throwingBuf.length()); - // we can safely alias c_str as both are local to the object - // and will not further manipulated. - message = xstrndup(explanatoryText.c_str(),explanatoryText.length()); + message = xstrdup(explanatoryText.c_str()); } OutOfBoundsException::~OutOfBoundsException() throw() diff -u -r -N squid-4.0.19/src/sbuf/Stream.h squid-4.0.20/src/sbuf/Stream.h --- squid-4.0.19/src/sbuf/Stream.h 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/sbuf/Stream.h 2017-06-02 00:49:17.000000000 +1200 @@ -118,5 +118,17 @@ SBufStreamBuf theBuffer; }; +/// slowly stream-prints all arguments into a freshly allocated SBuf +template +inline +SBuf ToSBuf(Args&&... args) +{ + // TODO: Make this code readable after requiring C++17. + SBufStream out; + using expander = int[]; + (void)expander {0, (void(out << std::forward(args)),0)...}; + return out.buf(); +} + #endif /* SQUID_SBUFSTREAM_H */ diff -u -r -N squid-4.0.19/src/security/cert_generators/file/security_file_certgen.cc squid-4.0.20/src/security/cert_generators/file/security_file_certgen.cc --- squid-4.0.19/src/security/cert_generators/file/security_file_certgen.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/security/cert_generators/file/security_file_certgen.cc 2017-06-02 00:49:17.000000000 +1200 @@ -337,7 +337,7 @@ } } catch (std::runtime_error & error) { std::cerr << argv[0] << ": " << error.what() << std::endl; - return 0; + return -1; } return 0; } diff -u -r -N squid-4.0.19/src/security/cert_validators/fake/security_fake_certverify.8 squid-4.0.20/src/security/cert_validators/fake/security_fake_certverify.8 --- squid-4.0.19/src/security/cert_validators/fake/security_fake_certverify.8 2017-04-02 23:50:29.000000000 +1200 +++ squid-4.0.20/src/security/cert_validators/fake/security_fake_certverify.8 2017-06-02 09:59:08.000000000 +1200 @@ -129,7 +129,7 @@ .\" ======================================================================== .\" .IX Title "SECURITY_FAKE_CERTVERIFY 8" -.TH SECURITY_FAKE_CERTVERIFY 8 "2017-04-02" "perl v5.24.1" "User Contributed Perl Documentation" +.TH SECURITY_FAKE_CERTVERIFY 8 "2017-06-01" "perl v5.24.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff -u -r -N squid-4.0.19/src/security/forward.h squid-4.0.20/src/security/forward.h --- squid-4.0.19/src/security/forward.h 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/security/forward.h 2017-06-02 00:49:17.000000000 +1200 @@ -30,6 +30,31 @@ struct sk_object ## _free_wrapper { \ void operator()(argument_type a) { sk_object ## _pop_free(a, freefunction); } \ } + +#if !HAVE_LIBCRYPTO_X509_UP_REF // OpenSSL 1.1 API +#if defined(CRYPTO_LOCK_X509) // OpenSSL 1.0 API +inline int X509_up_ref(X509 *t) {if (t) CRYPTO_add(&t->references, 1, CRYPTO_LOCK_X509); return 0;} +#else +#error missing both OpenSSL API features X509_up_ref (v1.1) and CRYPTO_LOCK_X509 (v1.0) +#endif /* CRYPTO_LOCK_X509 */ +#endif /* X509_up_ref */ + +#if !HAVE_LIBCRYPTO_X509_CRL_UP_REF // OpenSSL 1.1 API +#if defined(CRYPTO_LOCK_X509_CRL) // OpenSSL 1.0 API +inline int X509_CRL_up_ref(X509_CRL *t) {if (t) CRYPTO_add(&t->references, 1, CRYPTO_LOCK_X509_CRL); return 0;} +#else +#error missing both OpenSSL API features X509_up_ref (v1.1) and CRYPTO_LOCK_X509 (v1.0) +#endif /* CRYPTO_LOCK_X509_CRL */ +#endif /* X509_CRL_up_ref */ +#if !HAVE_LIBCRYPTO_DH_UP_REF // OpenSSL 1.1 API +#if defined(CRYPTO_LOCK_DH) // OpenSSL 1.0 API +inline int DH_up_ref(DH *t) {if (t) CRYPTO_add(&t->references, 1, CRYPTO_LOCK_DH); return 0;} +#else + +#error missing both OpenSSL API features DH_up_ref (v1.1) and CRYPTO_LOCK_DH (v1.0) +#endif /* OpenSSL 1.0 CRYPTO_LOCK_X509_CRL */ +#endif /* OpenSSL 1.1 DH_up_ref */ + #endif /* USE_OPENSSL */ /* flags a SSL connection can be configured with */ @@ -51,9 +76,6 @@ #if USE_OPENSSL CtoCpp1(X509_free, X509 *) -#if defined(CRYPTO_LOCK_X509) // OpenSSL 1.0 -inline int X509_up_ref(X509 *t) {if (t) CRYPTO_add(&t->references, 1, CRYPTO_LOCK_X509); return 0;} -#endif typedef Security::LockingPointer > CertPointer; #elif USE_GNUTLS CtoCpp1(gnutls_x509_crt_deinit, gnutls_x509_crt_t) @@ -64,9 +86,6 @@ #if USE_OPENSSL CtoCpp1(X509_CRL_free, X509_CRL *) -#if defined(CRYPTO_LOCK_X509_CRL) // OpenSSL 1.0 -inline int X509_CRL_up_ref(X509_CRL *t) {if (t) CRYPTO_add(&t->references, 1, CRYPTO_LOCK_X509_CRL); return 0;} -#endif typedef Security::LockingPointer > CrlPointer; #elif USE_GNUTLS CtoCpp1(gnutls_x509_crl_deinit, gnutls_x509_crl_t) @@ -81,9 +100,6 @@ #if USE_OPENSSL CtoCpp1(DH_free, DH *); -#if defined(CRYPTO_LOCK_DH) // OpenSSL 1.0 -inline int DH_up_ref(DH *t) {if (t) CRYPTO_add(&t->references, 1, CRYPTO_LOCK_DH); return 0;} -#endif typedef Security::LockingPointer > DhePointer; #else typedef void *DhePointer; diff -u -r -N squid-4.0.19/src/security/PeerOptions.cc squid-4.0.20/src/security/PeerOptions.cc --- squid-4.0.19/src/security/PeerOptions.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/security/PeerOptions.cc 2017-06-02 00:49:17.000000000 +1200 @@ -248,7 +248,7 @@ #if USE_OPENSSL Ssl::Initialize(); -#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) +#if HAVE_OPENSSL_TLS_CLIENT_METHOD SSL_CTX *t = SSL_CTX_new(TLS_client_method()); #else SSL_CTX *t = SSL_CTX_new(SSLv23_client_method()); diff -u -r -N squid-4.0.19/src/security/ServerOptions.cc squid-4.0.20/src/security/ServerOptions.cc --- squid-4.0.19/src/security/ServerOptions.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/security/ServerOptions.cc 2017-06-02 00:49:17.000000000 +1200 @@ -92,7 +92,7 @@ #if USE_OPENSSL Ssl::Initialize(); -#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) +#if HAVE_OPENSSL_SERVER_METHOD SSL_CTX *t = SSL_CTX_new(TLS_server_method()); #else SSL_CTX *t = SSL_CTX_new(SSLv23_server_method()); diff -u -r -N squid-4.0.19/src/ssl/bio.cc squid-4.0.20/src/ssl/bio.cc --- squid-4.0.19/src/ssl/bio.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/ssl/bio.cc 2017-06-02 00:49:17.000000000 +1200 @@ -43,7 +43,9 @@ /* SSL callbacks */ static void squid_ssl_info(const SSL *ssl, int where, int ret); -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) +#if HAVE_LIBCRYPTO_BIO_METH_NEW +static BIO_METHOD *SquidMethods = nullptr; +#else /// Initialization structure for the BIO table with /// Squid-specific methods and BIO method wrappers. static BIO_METHOD SquidMethods = { @@ -58,16 +60,12 @@ squid_bio_destroy, NULL // squid_callback_ctrl not supported }; -#else -static BIO_METHOD *SquidMethods = NULL; #endif BIO * Ssl::Bio::Create(const int fd, Security::Io::Type type) { -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) - BIO_METHOD *useMethod = &SquidMethods; -#else +#if HAVE_LIBCRYPTO_BIO_METH_NEW if (!SquidMethods) { SquidMethods = BIO_meth_new(BIO_TYPE_SOCKET, "squid"); BIO_meth_set_write(SquidMethods, squid_bio_write); @@ -79,6 +77,8 @@ BIO_meth_set_destroy(SquidMethods, squid_bio_destroy); } const BIO_METHOD *useMethod = SquidMethods; +#else + BIO_METHOD *useMethod = &SquidMethods; #endif if (BIO *bio = BIO_new(useMethod)) { @@ -562,7 +562,7 @@ static int squid_bio_create(BIO *bi) { -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) +#if !HAVE_LIBCRYPTO_BIO_GET_INIT bi->init = 0; // set when we store Bio object and socket fd (BIO_C_SET_FD) bi->num = 0; bi->flags = 0; @@ -706,11 +706,11 @@ cbytes[0] = (cipherId >> 8) & 0xFF; cbytes[1] = cipherId & 0xFF; cbytes[2] = 0; -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) +#if HAVE_LIBSSL_SSL_CIPHER_FIND + const SSL_CIPHER *c = SSL_CIPHER_find(ssl, cbytes); +#else const SSL_METHOD *method = SSLv23_method(); const SSL_CIPHER *c = method->get_cipher_by_char(cbytes); -#else - const SSL_CIPHER *c = SSL_CIPHER_find(ssl, cbytes); #endif if (c != NULL) { if (!strCiphers.isEmpty()) diff -u -r -N squid-4.0.19/src/ssl/bio.h squid-4.0.20/src/ssl/bio.h --- squid-4.0.19/src/ssl/bio.h 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/ssl/bio.h 2017-06-02 00:49:17.000000000 +1200 @@ -202,7 +202,7 @@ void applyTlsDetailsToSSL(SSL *ssl, Security::TlsDetails::Pointer const &details, Ssl::BumpMode bumpMode); -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) +#if !HAVE_LIBCRYPTO_BIO_GET_INIT // OpenSSL v1.0 bio compatibility functions inline void *BIO_get_data(BIO *table) { return table->ptr; } inline void BIO_set_data(BIO *table, void *data) { table->ptr = data; } diff -u -r -N squid-4.0.19/src/ssl/gadgets.cc squid-4.0.20/src/ssl/gadgets.cc --- squid-4.0.19/src/ssl/gadgets.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/ssl/gadgets.cc 2017-06-02 00:49:17.000000000 +1200 @@ -387,12 +387,12 @@ DecipherOnly }; -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) +#if HAVE_LIBCRYPTO_EVP_PKEY_GET0_RSA + EVP_PKEY *certKey = X509_get_pubkey(mimicCert.get()); + const bool rsaPkey = (EVP_PKEY_get0_RSA(certKey) != nullptr); +#else const int mimicAlgo = OBJ_obj2nid(mimicCert.get()->cert_info->key->algor->algorithm); const bool rsaPkey = (mimicAlgo == NID_rsaEncryption); -#else - EVP_PKEY *certKey = X509_get_pubkey(mimicCert.get()); - const bool rsaPkey = (EVP_PKEY_get0_RSA(certKey) != NULL); #endif int added = 0; @@ -443,6 +443,38 @@ return added; } +/// Adds a new subjectAltName extension contining Subject CN or returns false +/// expects the caller to check for the existing subjectAltName extension +static bool +addAltNameWithSubjectCn(Security::CertPointer &cert) +{ + X509_NAME *name = X509_get_subject_name(cert.get()); + if (!name) + return false; + + const int loc = X509_NAME_get_index_by_NID(name, NID_commonName, -1); + if (loc < 0) + return false; + + ASN1_STRING *cn_data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, loc)); + if (!cn_data) + return false; + + char dnsName[1024]; // DNS names are limited to 256 characters + const int res = snprintf(dnsName, sizeof(dnsName), "DNS:%*s", cn_data->length, cn_data->data); + if (res <= 0 || res >= static_cast(sizeof(dnsName))) + return false; + + X509_EXTENSION *ext = X509V3_EXT_conf_nid(NULL, NULL, NID_subject_alt_name, dnsName); + if (!ext) + return false; + + const bool result = X509_add_ext(cert.get(), ext, -1); + + X509_EXTENSION_free(ext); + return result; +} + static bool buildCertificate(Security::CertPointer & cert, Ssl::CertificateProperties const &properties) { // not an Ssl::X509_NAME_Pointer because X509_REQ_get_subject_name() @@ -491,6 +523,8 @@ } else if (!X509_gmtime_adj(X509_get_notAfter(cert.get()), 60*60*24*356*3)) return false; + int addedExtensions = 0; + bool useCommonNameAsAltName = true; // mimic the alias and possibly subjectAltName if (properties.mimicCert.get()) { unsigned char *alStr; @@ -500,26 +534,29 @@ X509_alias_set1(cert.get(), alStr, alLen); } - int addedExtensions = 0; - // Mimic subjectAltName unless we used a configured CN: browsers reject // certificates with CN unrelated to subjectAltNames. if (!properties.setCommonName) { - int pos=X509_get_ext_by_NID (properties.mimicCert.get(), OBJ_sn2nid("subjectAltName"), -1); + int pos = X509_get_ext_by_NID(properties.mimicCert.get(), NID_subject_alt_name, -1); X509_EXTENSION *ext=X509_get_ext(properties.mimicCert.get(), pos); if (ext) { if (X509_add_ext(cert.get(), ext, -1)) ++addedExtensions; } + // We want to mimic the server-sent subjectAltName, not enhance it. + useCommonNameAsAltName = false; } addedExtensions += mimicExtensions(cert, properties.mimicCert, properties.signWithX509); - - // According to RFC 5280, using extensions requires v3 certificate. - if (addedExtensions) - X509_set_version(cert.get(), 2); // value 2 means v3 } + if (useCommonNameAsAltName && addAltNameWithSubjectCn(cert)) + ++addedExtensions; + + // According to RFC 5280, using extensions requires v3 certificate. + if (addedExtensions) + X509_set_version(cert.get(), 2); // value 2 means v3 + return true; } diff -u -r -N squid-4.0.19/src/ssl/PeekingPeerConnector.cc squid-4.0.20/src/ssl/PeekingPeerConnector.cc --- squid-4.0.19/src/ssl/PeekingPeerConnector.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/ssl/PeekingPeerConnector.cc 2017-06-02 00:49:17.000000000 +1200 @@ -88,6 +88,7 @@ request->clientConnectionManager->sslBumpMode = finalAction; request->clientConnectionManager->serverBump()->act.step3 = finalAction; } + al->ssl.bumpMode = finalAction; if (finalAction == Ssl::bumpTerminate) { serverConn->close(); diff -u -r -N squid-4.0.19/src/ssl/support.cc squid-4.0.20/src/ssl/support.cc --- squid-4.0.19/src/ssl/support.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/ssl/support.cc 2017-06-02 00:49:17.000000000 +1200 @@ -97,7 +97,7 @@ } } -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) +#if HAVE_LIBSSL_SSL_CTX_SET_TMP_RSA_CALLBACK static RSA * ssl_temp_rsa_cb(SSL * ssl, int anInt, int keylen) { @@ -152,7 +152,7 @@ static void maybeSetupRsaCallback(Security::ContextPointer &ctx) { -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) +#if HAVE_LIBSSL_SSL_CTX_SET_TMP_RSA_CALLBACK debugs(83, 9, "Setting RSA key generation callback."); SSL_CTX_set_tmp_rsa_callback(ctx.get(), ssl_temp_rsa_cb); #endif @@ -236,7 +236,7 @@ return matchX509CommonNames(cert, (void *)server, check_domain); } -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) +#if !HAVE_LIBCRYPTO_X509_STORE_CTX_GET0_CERT static inline X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx) { return ctx->cert; @@ -380,7 +380,7 @@ } // "dup" function for SSL_get_ex_new_index("cert_err_check") -#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) +#if SQUID_USE_CONST_CRYPTO_EX_DATA_DUP static int ssl_dupAclChecklist(CRYPTO_EX_DATA *, const CRYPTO_EX_DATA *, void *, int, long, void *) @@ -986,9 +986,11 @@ bool Ssl::verifySslCertificate(Security::ContextPointer &ctx, CertificateProperties const &properties) { +#if HAVE_SSL_CTX_GET0_CERTIFICATE + X509 * cert = SSL_CTX_get0_certificate(ctx.get()); +#elif SQUID_USE_SSLGETCERTIFICATE_HACK // SSL_get_certificate is buggy in openssl versions 1.0.1d and 1.0.1e // Try to retrieve certificate directly from Security::ContextPointer object -#if SQUID_USE_SSLGETCERTIFICATE_HACK X509 ***pCert = (X509 ***)ctx->cert; X509 * cert = pCert && *pCert ? **pCert : NULL; #elif SQUID_SSLGETCERTIFICATE_BUGGY @@ -1066,10 +1068,10 @@ if (ad->location->type == GEN_URI) { xstrncpy(uri, reinterpret_cast( -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) - ASN1_STRING_data(ad->location->d.uniformResourceIdentifier) -#else +#if HAVE_LIBCRYPTO_ASN1_STRING_GET0_DATA ASN1_STRING_get0_data(ad->location->d.uniformResourceIdentifier) +#else + ASN1_STRING_data(ad->location->d.uniformResourceIdentifier) #endif ), sizeof(uri)); @@ -1116,7 +1118,7 @@ const auto ret = list.equal_range(SBuf(buffer)); for (Ssl::CertsIndexedList::iterator it = ret.first; it != ret.second; ++it) { X509 *issuer = it->second; - if (X509_check_issued(cert, issuer)) { + if (X509_check_issued(issuer, cert) == X509_V_OK) { return issuer; } } @@ -1201,16 +1203,16 @@ { debugs(83, 2, "completing " << sk_X509_num(untrustedCerts) << " OpenSSL untrusted certs using " << SquidUntrustedCerts.size() << " configured untrusted certificates"); -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) - int depth = ctx->param->depth; -#else +#if HAVE_LIBCRYPTO_X509_VERIFY_PARAM_GET_DEPTH const X509_VERIFY_PARAM *param = X509_STORE_CTX_get0_param(ctx); int depth = X509_VERIFY_PARAM_get_depth(param); +#else + int depth = ctx->param->depth; #endif X509 *current = X509_STORE_CTX_get0_cert(ctx); int i = 0; for (i = 0; current && (i < depth); ++i) { - if (X509_check_issued(current, current)) { + if (X509_check_issued(current, current) == X509_V_OK) { // either ctx->cert is itself self-signed or untrustedCerts // aready contain the self-signed current certificate break; @@ -1241,10 +1243,10 @@ // OpenSSL already maintains ctx->untrusted but we cannot modify // internal OpenSSL list directly. We have to give OpenSSL our own // list, but it must include certificates on the OpenSSL ctx->untrusted -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) - STACK_OF(X509) *oldUntrusted = ctx->untrusted; -#else +#if HAVE_LIBCRYPTO_X509_STORE_CTX_GET0_UNTRUSTED STACK_OF(X509) *oldUntrusted = X509_STORE_CTX_get0_untrusted(ctx); +#else + STACK_OF(X509) *oldUntrusted = ctx->untrusted; #endif STACK_OF(X509) *sk = sk_X509_dup(oldUntrusted); // oldUntrusted is always not NULL @@ -1260,10 +1262,10 @@ X509_STORE_CTX_set_chain(ctx, sk); // No locking/unlocking, just sets ctx->untrusted int ret = X509_verify_cert(ctx); -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) - X509_STORE_CTX_set_chain(ctx, oldUntrusted); // Set back the old untrusted list -#else +#if HAVE_LIBCRYPTO_X509_STORE_CTX_SET0_UNTRUSTED X509_STORE_CTX_set0_untrusted(ctx, oldUntrusted); +#else + X509_STORE_CTX_set_chain(ctx, oldUntrusted); // Set back the old untrusted list #endif sk_X509_free(sk); // Release sk list return ret; @@ -1389,12 +1391,12 @@ SSL_SESSION_set_timeout(session, Config.SSL.session_ttl); -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) - unsigned char *id = session->session_id; - unsigned int idlen = session->session_id_length; -#else +#if HAVE_LIBSSL_SSL_SESSION_GET_ID unsigned int idlen; const unsigned char *id = SSL_SESSION_get_id(session, &idlen); +#else + unsigned char *id = session->session_id; + unsigned int idlen = session->session_id_length; #endif unsigned char key[MEMMAP_SLOT_KEY_SIZE]; // Session ids are of size 32bytes. They should always fit to a @@ -1438,10 +1440,10 @@ } static SSL_SESSION * -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) -get_session_cb(SSL *, unsigned char *sessionID, int len, int *copy) -#else +#if SQUID_USE_CONST_SSL_SESSION_CBID get_session_cb(SSL *, const unsigned char *sessionID, int len, int *copy) +#else +get_session_cb(SSL *, unsigned char *sessionID, int len, int *copy) #endif { if (!Ssl::SessionCache) diff -u -r -N squid-4.0.19/src/ssl/support.h squid-4.0.20/src/ssl/support.h --- squid-4.0.19/src/ssl/support.h 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/ssl/support.h 2017-06-02 00:49:17.000000000 +1200 @@ -83,12 +83,6 @@ /// initialize a TLS client context with OpenSSL specific settings bool InitClientContext(Security::ContextPointer &, Security::PeerOptions &, long flags); -#if defined(CRYPTO_LOCK_X509) -// portability wrapper for OpenSSL 1.0 vs 1.1 -// use Security::CertPointer instead where possible -inline int X509_up_ref(X509 *t) {if (t) CRYPTO_add(&t->references, 1, CRYPTO_LOCK_X509); return 0;} -#endif - } //namespace Ssl /// \ingroup ServerProtocolSSLAPI diff -u -r -N squid-4.0.19/src/store/id_rewriters/file/storeid_file_rewrite.8 squid-4.0.20/src/store/id_rewriters/file/storeid_file_rewrite.8 --- squid-4.0.19/src/store/id_rewriters/file/storeid_file_rewrite.8 2017-04-02 23:48:57.000000000 +1200 +++ squid-4.0.20/src/store/id_rewriters/file/storeid_file_rewrite.8 2017-06-02 09:54:12.000000000 +1200 @@ -129,7 +129,7 @@ .\" ======================================================================== .\" .IX Title "STOREID_FILE_REWRITE 8" -.TH STOREID_FILE_REWRITE 8 "2017-04-02" "perl v5.24.1" "User Contributed Perl Documentation" +.TH STOREID_FILE_REWRITE 8 "2017-06-01" "perl v5.24.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff -u -r -N squid-4.0.19/src/tests/stub_neighbors.cc squid-4.0.20/src/tests/stub_neighbors.cc --- squid-4.0.19/src/tests/stub_neighbors.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/tests/stub_neighbors.cc 2017-06-02 00:49:17.000000000 +1200 @@ -11,8 +11,16 @@ #define STUB_API "neighbors.cc" #include "tests/STUB.h" +#include "FwdState.h" #include "neighbors.h" void peerConnClosed(CachePeer *p) STUB +time_t +peerConnectTimeout(const CachePeer *peer) STUB_RETVAL(0) +time_t +FwdState::ForwardTimeout(const time_t) STUB_RETVAL(0) +bool +FwdState::EnoughTimeToReForward(const time_t fwdStart) STUB_RETVAL(false) + diff -u -r -N squid-4.0.19/src/tests/stub_tools.cc squid-4.0.20/src/tests/stub_tools.cc --- squid-4.0.19/src/tests/stub_tools.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/tests/stub_tools.cc 2017-06-02 00:49:17.000000000 +1200 @@ -61,9 +61,6 @@ //not actually needed in the Stub, causes dependency on SBuf //SBuf ProcessRoles() STUB_RETVAL(SBuf()) -void writePidFile(void) STUB -void removePidFile(void) STUB -pid_t readPidFile(void) STUB_RETVAL(0) void setMaxFD(void) STUB void setSystemLimits(void) STUB void squid_signal(int sig, SIGHDLR * func, int flags) STUB @@ -77,3 +74,7 @@ void restoreCapabilities(bool keep) STUB pid_t WaitForOnePid(pid_t pid, PidStatus &status, int flags) STUB_RETVAL(0) +#if _SQUID_WINDOWS_ +SBuf WindowsErrorMessage(DWORD) STUB_RETVAL(SBuf()) +#endif // _SQUID_WINDOWS_ + diff -u -r -N squid-4.0.19/src/tools.cc squid-4.0.20/src/tools.cc --- squid-4.0.19/src/tools.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/tools.cc 2017-06-02 00:49:17.000000000 +1200 @@ -25,6 +25,7 @@ #include "ipc/Kids.h" #include "ipcache.h" #include "MemBuf.h" +#include "sbuf/Stream.h" #include "SquidConfig.h" #include "SquidMath.h" #include "SquidTime.h" @@ -710,97 +711,6 @@ return roles; } -void -writePidFile(void) -{ - int fd; - const char *f = NULL; - mode_t old_umask; - char buf[32]; - - debugs(50, DBG_IMPORTANT, "creating PID file: " << Config.pidFilename); - - if ((f = Config.pidFilename) == NULL) - return; - - if (!strcmp(Config.pidFilename, "none")) - return; - - enter_suid(); - - old_umask = umask(022); - - fd = open(f, O_WRONLY | O_CREAT | O_TRUNC | O_TEXT, 0644); - int xerrno = errno; - - umask(old_umask); - - leave_suid(); - - if (fd < 0) { - debugs(50, DBG_CRITICAL, "" << f << ": " << xstrerr(xerrno)); - debug_trap("Could not open PID file for write"); - return; - } - - snprintf(buf, 32, "%d\n", (int) getpid()); - const size_t ws = write(fd, buf, strlen(buf)); - assert(ws == strlen(buf)); - close(fd); -} - -void -removePidFile() -{ - if (Config.pidFilename && strcmp(Config.pidFilename, "none") != 0) { - debugs(50, DBG_IMPORTANT, "removing PID file: " << Config.pidFilename); - enter_suid(); - safeunlink(Config.pidFilename, 0); - leave_suid(); - } -} - -pid_t -readPidFile(void) -{ - FILE *pid_fp = NULL; - const char *f = Config.pidFilename; - char *chroot_f = NULL; - pid_t pid = -1; - int i; - - if (f == NULL || !strcmp(Config.pidFilename, "none")) { - fprintf(stderr, APP_SHORTNAME ": ERROR: No PID file name defined\n"); - exit(1); - } - - if (Config.chroot_dir && geteuid() == 0) { - int len = strlen(Config.chroot_dir) + 1 + strlen(f) + 1; - chroot_f = (char *)xmalloc(strlen(Config.chroot_dir) + 1 + strlen(f) + 1); - snprintf(chroot_f, len, "%s/%s", Config.chroot_dir, f); - f = chroot_f; - } - - if ((pid_fp = fopen(f, "r"))) { - pid = 0; - - if (fscanf(pid_fp, "%d", &i) == 1) - pid = (pid_t) i; - - fclose(pid_fp); - } else { - int xerrno = errno; - if (xerrno != ENOENT) { - fprintf(stderr, APP_SHORTNAME ": ERROR: Could not open PID file for read\n"); - fprintf(stderr, "\t%s: %s\n", f, xstrerr(xerrno)); - exit(1); - } - } - - safe_free(chroot_f); - return pid; -} - /* A little piece of glue for odd systems */ #ifndef RLIMIT_NOFILE #ifdef RLIMIT_OFILE @@ -1234,3 +1144,28 @@ #endif } +#if _SQUID_WINDOWS_ +SBuf +WindowsErrorMessage(DWORD errorId) +{ + char *rawMessage = nullptr; + const auto length = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, + errorId, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + static_cast(&rawMessage), + 0, + nullptr); + if (!length) { + Must(!rawMessage); // nothing to LocalFree() + return ToSBuf("windows error ", errorId); + } + const auto result = SBuf(rawMessage, length); + LocalFree(rawMessage); + return result; +} +#endif // _SQUID_WINDOWS_ + diff -u -r -N squid-4.0.19/src/tools.h squid-4.0.20/src/tools.h --- squid-4.0.19/src/tools.h 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/tools.h 2017-06-02 00:49:17.000000000 +1200 @@ -48,12 +48,9 @@ void leave_suid(void); void enter_suid(void); void no_suid(void); -void writePidFile(void); -void removePidFile(); void setMaxFD(void); void setSystemLimits(void); void squid_signal(int sig, SIGHDLR *, int flags); -pid_t readPidFile(void); void keepCapabilities(void); void BroadcastSignalIfAny(int& sig); @@ -116,5 +113,10 @@ return WaitForOnePid(-1, status, flags); } +#if _SQUID_WINDOWS_ +/// xstrerror(errno) equivalent for Windows errors returned by GetLastError() +SBuf WindowsErrorMessage(DWORD errorId); +#endif // _SQUID_WINDOWS_ + #endif /* SQUID_TOOLS_H_ */ diff -u -r -N squid-4.0.19/src/tunnel.cc squid-4.0.20/src/tunnel.cc --- squid-4.0.19/src/tunnel.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/src/tunnel.cc 2017-06-02 00:49:17.000000000 +1200 @@ -31,6 +31,7 @@ #include "ip/QosConfig.h" #include "LogTags.h" #include "MemBuf.h" +#include "neighbors.h" #include "PeerSelectState.h" #include "sbuf/SBuf.h" #include "security/BlindPeerConnector.h" @@ -121,6 +122,10 @@ /// if it is waiting for Squid CONNECT response, closing connections. void informUserOfPeerError(const char *errMsg, size_t); + /// starts connecting to the next hop, either for the first time or while + /// recovering from the previous connect failure + void startConnecting(); + class Connection { @@ -169,7 +174,7 @@ bool connectReqWriting; ///< whether we are writing a CONNECT request to a peer SBuf preReadClientData; SBuf preReadServerData; - time_t started; ///< when this tunnel was initiated. + time_t startTime; ///< object creation time, before any peer selection/connection attempts void copyRead(Connection &from, IOCB *completion); @@ -291,7 +296,7 @@ TunnelStateData::TunnelStateData(ClientHttpRequest *clientRequest) : connectRespBuf(NULL), connectReqWriting(false), - started(squid_curtime) + startTime(squid_curtime) { debugs(26, 3, "TunnelStateData constructed this=" << this); client.readPendingFunc = &tunnelDelayedClientRead; @@ -894,7 +899,7 @@ * Call the tunnelStartShoveling to start the blind pump. */ static void -tunnelConnectedWriteDone(const Comm::ConnectionPointer &conn, char *, size_t, Comm::Flag flag, int, void *data) +tunnelConnectedWriteDone(const Comm::ConnectionPointer &conn, char *, size_t len, Comm::Flag flag, int, void *data) { TunnelStateData *tunnelState = (TunnelStateData *)data; debugs(26, 3, HERE << conn << ", flag=" << flag); @@ -906,6 +911,11 @@ return; } + if (auto http = tunnelState->http.get()) { + http->out.headers_sz += len; + http->out.size += len; + } + tunnelStartShoveling(tunnelState); } @@ -983,25 +993,21 @@ if (status != Comm::OK) { debugs(26, 4, HERE << conn << ", comm failure recovery."); + { + assert(!tunnelState->serverDestinations.empty()); + const Comm::Connection &failedDest = *tunnelState->serverDestinations.front(); + if (CachePeer *peer = failedDest.getPeer()) + peerConnectFailed(peer); + debugs(26, 4, "removing the failed one from " << tunnelState->serverDestinations.size() << + " destinations: " << failedDest); + } /* At this point only the TCP handshake has failed. no data has been passed. * we are allowed to re-try the TCP-level connection to alternate IPs for CONNECT. */ - debugs(26, 4, "removing server 1 of " << tunnelState->serverDestinations.size() << - " from destinations (" << tunnelState->serverDestinations[0] << ")"); tunnelState->serverDestinations.erase(tunnelState->serverDestinations.begin()); - time_t fwdTimeout = tunnelState->started + Config.Timeout.forward; - if (fwdTimeout > squid_curtime && tunnelState->serverDestinations.size() > 0) { - // find remaining forward_timeout available for this attempt - fwdTimeout -= squid_curtime; - if (fwdTimeout > Config.Timeout.connect) - fwdTimeout = Config.Timeout.connect; - /* Try another IP of this destination host */ - GetMarkingsToServer(tunnelState->request.getRaw(), *tunnelState->serverDestinations[0]); - debugs(26, 4, HERE << "retry with : " << tunnelState->serverDestinations[0]); - AsyncCall::Pointer call = commCbCall(26,3, "tunnelConnectDone", CommConnectCbPtrFun(tunnelConnectDone, tunnelState)); - Comm::ConnOpener *cs = new Comm::ConnOpener(tunnelState->serverDestinations[0], call, fwdTimeout); - cs->setHost(tunnelState->url); - AsyncJob::Start(cs); + if (!tunnelState->serverDestinations.empty() && FwdState::EnoughTimeToReForward(tunnelState->startTime)) { + debugs(26, 4, "re-forwarding"); + tunnelState->startConnecting(); } else { debugs(26, 4, HERE << "terminate with error."); ErrorState *err = new ErrorState(ERR_CONNECT_FAIL, Http::scServiceUnavailable, tunnelState->request.getRaw()); @@ -1226,17 +1232,25 @@ } delete err; - GetMarkingsToServer(tunnelState->request.getRaw(), *tunnelState->serverDestinations[0]); - if (tunnelState->request != NULL) tunnelState->request->hier.startPeerClock(); - debugs(26, 3, HERE << "paths=" << peer_paths->size() << ", p[0]={" << (*peer_paths)[0] << "}, serverDest[0]={" << + debugs(26, 3, "paths=" << peer_paths->size() << ", p[0]={" << (*peer_paths)[0] << "}, serverDest[0]={" << tunnelState->serverDestinations[0] << "}"); - AsyncCall::Pointer call = commCbCall(26,3, "tunnelConnectDone", CommConnectCbPtrFun(tunnelConnectDone, tunnelState)); - Comm::ConnOpener *cs = new Comm::ConnOpener(tunnelState->serverDestinations[0], call, Config.Timeout.connect); - cs->setHost(tunnelState->url); + tunnelState->startConnecting(); +} + +void +TunnelStateData::startConnecting() +{ + Comm::ConnectionPointer &dest = serverDestinations.front(); + GetMarkingsToServer(request.getRaw(), *dest); + + const time_t connectTimeout = dest->connectTimeout(startTime); + AsyncCall::Pointer call = commCbCall(26,3, "tunnelConnectDone", CommConnectCbPtrFun(tunnelConnectDone, this)); + Comm::ConnOpener *cs = new Comm::ConnOpener(dest, call, connectTimeout); + cs->setHost(url); AsyncJob::Start(cs); } diff -u -r -N squid-4.0.19/test-suite/stub_tools.cc squid-4.0.20/test-suite/stub_tools.cc --- squid-4.0.19/test-suite/stub_tools.cc 2017-04-02 23:50:42.000000000 +1200 +++ squid-4.0.20/test-suite/stub_tools.cc 2017-06-02 09:59:53.000000000 +1200 @@ -61,9 +61,6 @@ //not actually needed in the Stub, causes dependency on SBuf //SBuf ProcessRoles() STUB_RETVAL(SBuf()) -void writePidFile(void) STUB -void removePidFile(void) STUB -pid_t readPidFile(void) STUB_RETVAL(0) void setMaxFD(void) STUB void setSystemLimits(void) STUB void squid_signal(int sig, SIGHDLR * func, int flags) STUB @@ -77,3 +74,7 @@ void restoreCapabilities(bool keep) STUB pid_t WaitForOnePid(pid_t pid, PidStatus &status, int flags) STUB_RETVAL(0) +#if _SQUID_WINDOWS_ +SBuf WindowsErrorMessage(DWORD) STUB_RETVAL(SBuf()) +#endif // _SQUID_WINDOWS_ + diff -u -r -N squid-4.0.19/tools/cachemgr.cc squid-4.0.20/tools/cachemgr.cc --- squid-4.0.19/tools/cachemgr.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/tools/cachemgr.cc 2017-06-02 00:49:17.000000000 +1200 @@ -440,7 +440,7 @@ return; } - buf_copy = x = xstrndup(buf, bufLen); + buf_copy = x = xstrndup(buf, bufLen+1); a = xstrtok(&x, '\t'); diff -u -r -N squid-4.0.19/tools/helper-mux/helper-mux.8 squid-4.0.20/tools/helper-mux/helper-mux.8 --- squid-4.0.19/tools/helper-mux/helper-mux.8 2017-04-02 23:50:48.000000000 +1200 +++ squid-4.0.20/tools/helper-mux/helper-mux.8 2017-06-02 10:00:07.000000000 +1200 @@ -129,7 +129,7 @@ .\" ======================================================================== .\" .IX Title "HELPER-MUX 8" -.TH HELPER-MUX 8 "2017-04-02" "perl v5.24.1" "User Contributed Perl Documentation" +.TH HELPER-MUX 8 "2017-06-01" "perl v5.24.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff -u -r -N squid-4.0.19/tools/purge/purge.cc squid-4.0.20/tools/purge/purge.cc --- squid-4.0.19/tools/purge/purge.cc 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/tools/purge/purge.cc 2017-06-02 00:49:17.000000000 +1200 @@ -272,7 +272,7 @@ snprintf( md5, sizeof(md5), "%-32s", "(no_md5_data_available)" ); } - char timeb[64]; + char timeb[256]; if ( meta && (findings = meta->search( STORE_META_STD )) ) { StoreMetaStd temp; // make data aligned, avoid SIGBUS on RISC machines (ARGH!) @@ -283,7 +283,7 @@ } else if ( meta && (findings = meta->search( STORE_META_STD_LFS )) ) { StoreMetaStdLFS temp; // make data aligned, avoid SIGBUS on RISC machines (ARGH!) - memcpy( &temp, findings->data, sizeof(StoreMetaStd) ); + memcpy( &temp, findings->data, sizeof(StoreMetaStdLFS) ); snprintf( timeb, sizeof(timeb), "%08lx %08lx %08lx %08lx %04x %5hu ", (unsigned long)temp.timestamp, (unsigned long)temp.lastref, (unsigned long)temp.expires, (unsigned long)temp.lastmod, temp.flags, temp.refcount ); diff -u -r -N squid-4.0.19/tools/squidclient/squidclient.1 squid-4.0.20/tools/squidclient/squidclient.1 --- squid-4.0.19/tools/squidclient/squidclient.1 2017-04-02 19:43:45.000000000 +1200 +++ squid-4.0.20/tools/squidclient/squidclient.1 2017-06-02 00:49:17.000000000 +1200 @@ -86,7 +86,7 @@ .if !'po4a'hide' .TP .if !'po4a'hide' .B "\-H 'string'" Extra headers to send. Use -.B '\\n' +.B '\en' for new lines. . .if !'po4a'hide' .TP