diff -u -r -N squid-4.0.14/ChangeLog squid-4.0.15/ChangeLog --- squid-4.0.14/ChangeLog 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/ChangeLog 2016-10-10 08:05:51.000000000 +1300 @@ -1,3 +1,17 @@ +Changes to squid-4.0.15 (09 Oct 2016): + + - Regression fix crash on reconfigure with TOS/DiffServ/MARK configured + - Bug 4610: compile errors on Solaris 11.3 with Oracle Studio 12.5 + - Bug 4581: Secure ICAP segfault in checkForMissingCertificates + - Bug 4578: changes required to install squid.service + - Fix crash on shutdown while cleaning up idle ICAP connections + - Fix memory leak of Downloader-related objects + - HTTP/1.1: handle syntactically valid requests with unsupported HTTP versions + - Log TCP client port for error:transaction-end-before-headers and such + - ... and many portability and build fixes + - ... and some documentation updates + - ... and all fixes from 3.5.22 + Changes to squid-4.0.14 (08 Sep 2016): - Regression Bug 4570: crash after rev.14755 @@ -13,7 +27,7 @@ - Do not log error:transaction-end-before-headers after invalid requests - ... and many portability and build fixes - ... and some documentation updates - - ... and all fixes from 3.5.20 + - ... and all fixes from 3.5.21 Changes to squid-4.0.13 (05 Aug 2016): @@ -223,6 +237,20 @@ - ... and many documentation changes - ... and much code cleanup and polishing +Changes to squid-3.5.22 (09 Oct 2016): + + - Bug 4594: build failure with clang 3.9 + - Bug 4471: revalidation does not work when expired cached object lacks Last-Modified + - Bug 4302 pt2: IPv6 support for IPFilter v5 transparent interception + - Bug 4228: ./configure bug/typo in r14394 + - Bug 3819: "fd >= 0" assertion in file_write() during reconfiguration + - Bug 2833: Collapse internal revalidation requests (SMP-unaware caches) + - Fix logged request size (%http::>st) and other size-related %codes + - Fix some memory leaks from putenv() + - Fix memory leaks from url_rewrite_extras and store_id_extras on reconfigure/shutdown + - Fix segfault crash when debugging section 4 at level 9 + - HTTP: MUST ignore a [revalidation] response with an older Date header + Changes to squid-3.5.21 (08 Sep 2016): - Bug 4563: duplicate code in httpMakeVaryMark diff -u -r -N squid-4.0.14/compat/debug.cc squid-4.0.15/compat/debug.cc --- squid-4.0.14/compat/debug.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/compat/debug.cc 2016-10-10 08:05:51.000000000 +1300 @@ -12,7 +12,7 @@ /* default off */ int debug_enabled = 0; -#ifndef __GNUC__ +#if !defined(__GNUC__) && !defined(__SUNPRO_CC) /* under gcc a macro define in compat/debug.h is used instead */ void @@ -26,5 +26,5 @@ va_end(args); } -#endif /* __GNUC__ */ +#endif /* __GNUC__ || __SUNPRO_CC */ diff -u -r -N squid-4.0.14/compat/debug.h squid-4.0.15/compat/debug.h --- squid-4.0.14/compat/debug.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/compat/debug.h 2016-10-10 08:05:51.000000000 +1300 @@ -23,7 +23,7 @@ SQUIDCEXTERN int debug_enabled; /* the macro overload style is really a gcc-ism */ -#ifdef __GNUC__ +#if defined(__GNUC__) || defined(__SUNPRO_CC) #define debug(X...) \ if (debug_enabled) { \ @@ -37,7 +37,7 @@ << content << std::endl; \ } else (void)0 -#else /* __GNUC__ */ +#else /* __GNUC__ || __SUNPRO_CC */ /* non-GCC compilers can't do the above macro define yet. */ void debug(const char *format,...); diff -u -r -N squid-4.0.14/configure squid-4.0.15/configure --- squid-4.0.14/configure 2016-09-09 02:15:20.000000000 +1200 +++ squid-4.0.15/configure 2016-10-10 08:20:15.000000000 +1300 @@ -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.14. +# Generated by GNU Autoconf 2.69 for Squid Web Proxy 4.0.15. # # Report bugs to . # @@ -595,8 +595,8 @@ # Identity of this package. PACKAGE_NAME='Squid Web Proxy' PACKAGE_TARNAME='squid' -PACKAGE_VERSION='4.0.14' -PACKAGE_STRING='Squid Web Proxy 4.0.14' +PACKAGE_VERSION='4.0.15' +PACKAGE_STRING='Squid Web Proxy 4.0.15' PACKAGE_BUGREPORT='http://bugs.squid-cache.org/' PACKAGE_URL='' @@ -1648,7 +1648,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.14 to adapt to many kinds of systems. +\`configure' configures Squid Web Proxy 4.0.15 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1719,7 +1719,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of Squid Web Proxy 4.0.14:";; + short | recursive ) echo "Configuration of Squid Web Proxy 4.0.15:";; esac cat <<\_ACEOF @@ -2148,7 +2148,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -Squid Web Proxy configure 4.0.14 +Squid Web Proxy configure 4.0.15 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -3252,7 +3252,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.14, which was +It was created by Squid Web Proxy $as_me 4.0.15, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -4119,7 +4119,7 @@ # Define the identity of the package. PACKAGE='squid' - VERSION='4.0.14' + VERSION='4.0.15' cat >>confdefs.h <<_ACEOF @@ -30590,7 +30590,7 @@ fi if test "x$KRB5LIBS" = "x"; then - if test test "x$with_heimdal_krb5" = "xyes"; then + if test "x$with_heimdal_krb5" = "xyes"; then as_fn_error $? "Required Heimdal Kerberos library not found" "$LINENO" 5 else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Heimdal Kerberos library not found" >&5 @@ -31108,7 +31108,7 @@ fi if test "x$KRB5LIBS" = "x"; then - if test test "x$with_gnugss" = "xyes"; then + if test "x$with_gnugss" = "xyes"; then as_fn_error $? "Required GNU GSS Kerberos library not found" "$LINENO" 5 else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: GNU GSS Kerberos library not found" >&5 @@ -42599,7 +42599,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.14, which was +This file was extended by Squid Web Proxy $as_me 4.0.15, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -42665,7 +42665,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.14 +Squid Web Proxy config.status 4.0.15 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -u -r -N squid-4.0.14/configure.ac squid-4.0.15/configure.ac --- squid-4.0.14/configure.ac 2016-09-09 02:15:20.000000000 +1200 +++ squid-4.0.15/configure.ac 2016-10-10 08:20:13.000000000 +1300 @@ -5,7 +5,7 @@ ## Please see the COPYING and CONTRIBUTORS files for details. ## -AC_INIT([Squid Web Proxy],[4.0.14],[http://bugs.squid-cache.org/],[squid]) +AC_INIT([Squid Web Proxy],[4.0.15],[http://bugs.squid-cache.org/],[squid]) AC_PREREQ(2.61) AC_CONFIG_HEADERS([include/autoconf.h]) AC_CONFIG_AUX_DIR(cfgaux) @@ -1758,7 +1758,7 @@ SQUID_CHECK_KRB5_FUNCS fi if test "x$KRB5LIBS" = "x"; then - if test test "x$with_heimdal_krb5" = "xyes"; then + if test "x$with_heimdal_krb5" = "xyes"; then AC_MSG_ERROR([Required Heimdal Kerberos library not found]) else AC_MSG_WARN([Heimdal Kerberos library not found]) @@ -1828,7 +1828,7 @@ SQUID_DEFINE_BOOL(HAVE_KRB5,$squid_cv_working_krb5,[KRB5 support]) fi if test "x$KRB5LIBS" = "x"; then - if test test "x$with_gnugss" = "xyes"; then + if test "x$with_gnugss" = "xyes"; then AC_MSG_ERROR([Required GNU GSS Kerberos library not found]) else AC_MSG_WARN([GNU GSS Kerberos library not found]) diff -u -r -N squid-4.0.14/doc/release-notes/release-4.html squid-4.0.15/doc/release-notes/release-4.html --- squid-4.0.14/doc/release-notes/release-4.html 2016-09-09 03:30:00.000000000 +1200 +++ squid-4.0.15/doc/release-notes/release-4.html 2016-10-10 11:51:35.000000000 +1300 @@ -2,10 +2,10 @@ - Squid 4.0.14 release notes + Squid 4.0.15 release notes -

Squid 4.0.14 release notes

+

Squid 4.0.15 release notes

Squid Developers


@@ -61,7 +61,7 @@

1. Notice

-

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

+

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

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

diff -u -r -N squid-4.0.14/include/version.h squid-4.0.15/include/version.h --- squid-4.0.14/include/version.h 2016-09-09 02:15:21.000000000 +1200 +++ squid-4.0.15/include/version.h 2016-10-10 08:20:15.000000000 +1300 @@ -7,7 +7,7 @@ */ #ifndef SQUID_RELEASE_TIME -#define SQUID_RELEASE_TIME 1473343915 +#define SQUID_RELEASE_TIME 1476039939 #endif /* diff -u -r -N squid-4.0.14/RELEASENOTES.html squid-4.0.15/RELEASENOTES.html --- squid-4.0.14/RELEASENOTES.html 2016-09-09 03:30:00.000000000 +1200 +++ squid-4.0.15/RELEASENOTES.html 2016-10-10 11:51:35.000000000 +1300 @@ -2,10 +2,10 @@ - Squid 4.0.14 release notes + Squid 4.0.15 release notes -

Squid 4.0.14 release notes

+

Squid 4.0.15 release notes

Squid Developers


@@ -61,7 +61,7 @@

1. Notice

-

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

+

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

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

diff -u -r -N squid-4.0.14/src/acl/external/delayer/ext_delayer_acl.8 squid-4.0.15/src/acl/external/delayer/ext_delayer_acl.8 --- squid-4.0.14/src/acl/external/delayer/ext_delayer_acl.8 2016-09-09 03:30:51.000000000 +1200 +++ squid-4.0.15/src/acl/external/delayer/ext_delayer_acl.8 2016-10-10 11:54:25.000000000 +1300 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) +.\" Automatically generated by Pod::Man 4.08 (Pod::Simple 3.32) .\" .\" Standard preamble: .\" ======================================================================== @@ -46,7 +46,7 @@ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" -.\" If the F register is turned on, we'll generate index entries on stderr for +.\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. @@ -54,20 +54,16 @@ .\" Avoid warning from groff about undefined register 'F'. .de IX .. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" +.if !\nF .nr F 0 +.if \nF>0 \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" .. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 . \} .\} -.rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. @@ -133,7 +129,7 @@ .\" ======================================================================== .\" .IX Title "EXT_DELAYER_ACL 8" -.TH EXT_DELAYER_ACL 8 "2016-09-08" "perl v5.22.2" "User Contributed Perl Documentation" +.TH EXT_DELAYER_ACL 8 "2016-10-09" "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 @@ -225,7 +221,7 @@ Report ideas for new improvements to the \fISquid Developers mailing list .SH "SEE ALSO" .IX Header "SEE ALSO" -squid (8), \s-1GPL \\fIs0\fR\|(7), +squid (8), \s-1GPL\s0 (7), .PP The Squid \s-1FAQ\s0 wiki http://wiki.squid\-cache.org/SquidFaq .PP diff -u -r -N squid-4.0.14/src/acl/external/SQL_session/ext_sql_session_acl.8 squid-4.0.15/src/acl/external/SQL_session/ext_sql_session_acl.8 --- squid-4.0.14/src/acl/external/SQL_session/ext_sql_session_acl.8 2016-09-09 03:31:02.000000000 +1200 +++ squid-4.0.15/src/acl/external/SQL_session/ext_sql_session_acl.8 2016-10-10 11:55:00.000000000 +1300 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) +.\" Automatically generated by Pod::Man 4.08 (Pod::Simple 3.32) .\" .\" Standard preamble: .\" ======================================================================== @@ -46,7 +46,7 @@ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" -.\" If the F register is turned on, we'll generate index entries on stderr for +.\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. @@ -54,20 +54,16 @@ .\" Avoid warning from groff about undefined register 'F'. .de IX .. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" +.if !\nF .nr F 0 +.if \nF>0 \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" .. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 . \} .\} -.rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. @@ -133,7 +129,7 @@ .\" ======================================================================== .\" .IX Title "EXT_SQL_SESSION_ACL 8" -.TH EXT_SQL_SESSION_ACL 8 "2016-09-08" "perl v5.22.2" "User Contributed Perl Documentation" +.TH EXT_SQL_SESSION_ACL 8 "2016-10-09" "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 @@ -154,7 +150,7 @@ Taking an identity token to be validated (as determined by the external_acl_type format) it returns a username or tag associated with the identity token passed in. .PP -Common forms of identifiers are \s-1IP\s0 address, \s-1EUI \s0(\s-1MAC\s0) address, passwords, or \s-1UUID\s0 tokens. +Common forms of identifiers are \s-1IP\s0 address, \s-1EUI\s0 (\s-1MAC\s0) address, passwords, or \s-1UUID\s0 tokens. .PP This program uses Squid concurrency support. .SH "OPTIONS" @@ -225,7 +221,7 @@ Report ideas for new improvements to the \fISquid Developers mailing list .SH "SEE ALSO" .IX Header "SEE ALSO" -squid (8), \s-1GPL \\fIs0\fR\|(7), +squid (8), \s-1GPL\s0 (7), .PP The Squid \s-1FAQ\s0 wiki http://wiki.squid\-cache.org/SquidFaq .PP diff -u -r -N squid-4.0.14/src/acl/external/wbinfo_group/ext_wbinfo_group_acl.8 squid-4.0.15/src/acl/external/wbinfo_group/ext_wbinfo_group_acl.8 --- squid-4.0.14/src/acl/external/wbinfo_group/ext_wbinfo_group_acl.8 2016-09-09 03:31:06.000000000 +1200 +++ squid-4.0.15/src/acl/external/wbinfo_group/ext_wbinfo_group_acl.8 2016-10-10 11:55:22.000000000 +1300 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) +.\" Automatically generated by Pod::Man 4.08 (Pod::Simple 3.32) .\" .\" Standard preamble: .\" ======================================================================== @@ -46,7 +46,7 @@ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" -.\" If the F register is turned on, we'll generate index entries on stderr for +.\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. @@ -54,20 +54,16 @@ .\" Avoid warning from groff about undefined register 'F'. .de IX .. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" +.if !\nF .nr F 0 +.if \nF>0 \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" .. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 . \} .\} -.rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. @@ -133,7 +129,7 @@ .\" ======================================================================== .\" .IX Title "EXT_WBINFO_GROUP_ACL 8" -.TH EXT_WBINFO_GROUP_ACL 8 "2016-09-08" "perl v5.22.2" "User Contributed Perl Documentation" +.TH EXT_WBINFO_GROUP_ACL 8 "2016-10-09" "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.14/src/acl/FilledChecklist.h squid-4.0.15/src/acl/FilledChecklist.h --- squid-4.0.14/src/acl/FilledChecklist.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/acl/FilledChecklist.h 2016-10-10 08:05:51.000000000 +1300 @@ -18,9 +18,7 @@ #if USE_AUTH #include "auth/UserRequest.h" #endif -#if USE_OPENSSL -#include "ssl/support.h" -#endif +#include "security/CertError.h" class CachePeer; class ConnStateData; @@ -83,12 +81,10 @@ char *snmp_community; #endif -#if USE_OPENSSL /// SSL [certificate validation] errors, in undefined order - const Ssl::CertErrors *sslErrors; + const Security::CertErrors *sslErrors; /// The peer certificate Security::CertPointer serverCert; -#endif AccessLogEntry::Pointer al; ///< info for the future access.log, and external ACL diff -u -r -N squid-4.0.14/src/acl/SslErrorData.cc squid-4.0.15/src/acl/SslErrorData.cc --- squid-4.0.14/src/acl/SslErrorData.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/acl/SslErrorData.cc 2016-10-10 08:05:51.000000000 +1300 @@ -9,46 +9,29 @@ #include "squid.h" #include "acl/Checklist.h" #include "acl/SslErrorData.h" -#include "wordlist.h" +#include "security/CertError.h" +#include "ssl/ErrorDetail.h" -ACLSslErrorData::ACLSslErrorData() : values (NULL) +ACLSslErrorData::ACLSslErrorData(ACLSslErrorData const &o) : + values(o.values) {} -ACLSslErrorData::ACLSslErrorData(ACLSslErrorData const &old) : values (NULL) -{ - assert (!old.values); -} - -ACLSslErrorData::~ACLSslErrorData() -{ - if (values) - delete values; -} - bool -ACLSslErrorData::match(const Ssl::CertErrors *toFind) +ACLSslErrorData::match(const Security::CertErrors *toFind) { - for (const Ssl::CertErrors *err = toFind; err; err = err->next ) { - if (values->findAndTune(err->element.code)) + for (const auto *err = toFind; err; err = err->next) { + if (values.count(err->element.code)) return true; } return false; } -/* explicit instantiation required for some systems */ -/** \cond AUTODOCS_IGNORE */ -// AYJ: 2009-05-20 : Removing. clashes with template instantiation for other ACLs. -// template cbdata_type Ssl::Errors::CBDATA_CbDataList; -/** \endcond */ - SBufList ACLSslErrorData::dump() const { SBufList sl; - Ssl::Errors *data = values; - while (data != NULL) { - sl.push_back(SBuf(Ssl::GetErrorName(data->element))); - data = data->next; + for (const auto &e : values) { + sl.push_back(SBuf(Ssl::GetErrorName(e))); } return sl; } @@ -56,27 +39,14 @@ void ACLSslErrorData::parse() { - Ssl::Errors **Tail; - - for (Tail = &values; *Tail; Tail = &((*Tail)->next)); while (char *t = ConfigParser::strtokFile()) { - Ssl::Errors *q = Ssl::ParseErrorString(t); - *(Tail) = q; - Tail = &q->tail()->next; + Ssl::ParseErrorString(t, values); } } -bool -ACLSslErrorData::empty() const -{ - return values == NULL; -} - ACLSslErrorData * ACLSslErrorData::clone() const { - /* Splay trees don't clone yet. */ - assert (!values); return new ACLSslErrorData(*this); } diff -u -r -N squid-4.0.14/src/acl/SslErrorData.h squid-4.0.15/src/acl/SslErrorData.h --- squid-4.0.14/src/acl/SslErrorData.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/acl/SslErrorData.h 2016-10-10 08:05:51.000000000 +1300 @@ -11,27 +11,24 @@ #include "acl/Acl.h" #include "acl/Data.h" -#include "base/CbDataList.h" -#include "ssl/ErrorDetail.h" -#include "ssl/support.h" -#include +#include "security/forward.h" -class ACLSslErrorData : public ACLData +class ACLSslErrorData : public ACLData { MEMPROXY_CLASS(ACLSslErrorData); public: - ACLSslErrorData(); + ACLSslErrorData() = default; ACLSslErrorData(ACLSslErrorData const &); ACLSslErrorData &operator= (ACLSslErrorData const &); - virtual ~ACLSslErrorData(); - bool match(const Ssl::CertErrors *); + virtual ~ACLSslErrorData() {} + bool match(const Security::CertErrors *); virtual SBufList dump() const; void parse(); - bool empty() const; + bool empty() const { return values.empty(); } virtual ACLSslErrorData *clone() const; - Ssl::Errors *values; + Security::Errors values; }; #endif /* SQUID_ACLSSL_ERRORDATA_H */ diff -u -r -N squid-4.0.14/src/acl/SslError.h squid-4.0.15/src/acl/SslError.h --- squid-4.0.14/src/acl/SslError.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/acl/SslError.h 2016-10-10 08:05:51.000000000 +1300 @@ -8,11 +8,11 @@ #ifndef SQUID_ACLSSL_ERROR_H #define SQUID_ACLSSL_ERROR_H + #include "acl/Strategised.h" #include "acl/Strategy.h" -#include "ssl/support.h" -class ACLSslErrorStrategy : public ACLStrategy +class ACLSslErrorStrategy : public ACLStrategy { public: @@ -35,7 +35,7 @@ private: static ACL::Prototype RegistryProtoype; - static ACLStrategised RegistryEntry_; + static ACLStrategised RegistryEntry_; }; #endif /* SQUID_ACLSSL_ERROR_H */ diff -u -r -N squid-4.0.14/src/AclRegs.cc squid-4.0.15/src/AclRegs.cc --- squid-4.0.14/src/AclRegs.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/AclRegs.cc 2016-10-10 08:05:51.000000000 +1300 @@ -170,7 +170,7 @@ #if USE_OPENSSL ACL::Prototype ACLSslError::RegistryProtoype(&ACLSslError::RegistryEntry_, "ssl_error"); -ACLStrategised ACLSslError::RegistryEntry_(new ACLSslErrorData, ACLSslErrorStrategy::Instance(), "ssl_error"); +ACLStrategised ACLSslError::RegistryEntry_(new ACLSslErrorData, ACLSslErrorStrategy::Instance(), "ssl_error"); ACL::Prototype ACLCertificate::UserRegistryProtoype(&ACLCertificate::UserRegistryEntry_, "user_cert"); ACLStrategised ACLCertificate::UserRegistryEntry_(new ACLCertificateData (Ssl::GetX509UserAttribute, "*"), ACLCertificateStrategy::Instance(), "user_cert"); ACL::Prototype ACLCertificate::CARegistryProtoype(&ACLCertificate::CARegistryEntry_, "ca_cert"); diff -u -r -N squid-4.0.14/src/adaptation/icap/ModXact.cc squid-4.0.15/src/adaptation/icap/ModXact.cc --- squid-4.0.14/src/adaptation/icap/ModXact.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/adaptation/icap/ModXact.cc 2016-10-10 08:05:51.000000000 +1300 @@ -1265,31 +1265,32 @@ void Adaptation::Icap::ModXact::finalizeLogInfo() { - HttpRequest * request_ = NULL; - HttpRequest * adapted_request_ = NULL; - HttpReply * reply_ = NULL; - request_ = (virgin.cause? virgin.cause: dynamic_cast(virgin.header)); + HttpRequest *adapted_request_ = nullptr; + HttpReply *adapted_reply_ = nullptr; + HttpRequest *virgin_request_ = const_cast(&virginRequest()); if (!(adapted_request_ = dynamic_cast(adapted.header))) { - adapted_request_ = request_; - reply_ = dynamic_cast(adapted.header); + // if the request was not adapted, use virgin request to simplify + // the code further below + adapted_request_ = virgin_request_; + adapted_reply_ = dynamic_cast(adapted.header); } - Adaptation::Icap::History::Pointer h = (request_ ? request_->icapHistory() : NULL); + Adaptation::Icap::History::Pointer h = virgin_request_->icapHistory(); Must(h != NULL); // ICAPXaction::maybeLog calls only if there is a log al.icp.opcode = ICP_INVALID; al.url = h->log_uri.termedBuf(); const Adaptation::Icap::ServiceRep &s = service(); al.icap.reqMethod = s.cfg().method; - al.cache.caddr = request_->client_addr; + al.cache.caddr = virgin_request_->client_addr; - al.request = request_; + al.request = virgin_request_; HTTPMSGLOCK(al.request); al.adapted_request = adapted_request_; HTTPMSGLOCK(al.adapted_request); - if (reply_) { - al.reply = reply_; + if (adapted_reply_) { + al.reply = adapted_reply_; HTTPMSGLOCK(al.reply); } else al.reply = NULL; @@ -1302,30 +1303,34 @@ al.cache.ssluser = h->ssluser.termedBuf(); #endif al.cache.code = h->logType; - // XXX: should use icap-specific counters instead ? - al.http.clientRequestSz.payloadData = h->req_sz; + + const HttpMsg *virgin_msg = dynamic_cast(virgin.header); + if (!virgin_msg) + virgin_msg = virgin_request_; + assert(virgin_msg != virgin.cause); + al.http.clientRequestSz.header = virgin_msg->hdr_sz; + al.http.clientRequestSz.payloadData = virgin_msg->body_pipe->producedSize(); // leave al.icap.bodyBytesRead negative if no body if (replyHttpHeaderSize >= 0 || replyHttpBodySize >= 0) { const int64_t zero = 0; // to make max() argument types the same - al.icap.bodyBytesRead = - max(zero, replyHttpHeaderSize) + max(zero, replyHttpBodySize); + const uint64_t headerSize = max(zero, replyHttpHeaderSize); + const uint64_t bodySize = max(zero, replyHttpBodySize); + al.icap.bodyBytesRead = headerSize + bodySize; + al.http.clientReplySz.header = headerSize; + al.http.clientReplySz.payloadData = bodySize; } - if (reply_) { - al.http.code = reply_->sline.status(); - al.http.content_type = reply_->content_type.termedBuf(); - if (replyHttpBodySize >= 0) { - // XXX: should use icap-specific counters instead ? - al.http.clientReplySz.payloadData = replyHttpBodySize; - al.http.clientReplySz.header = reply_->hdr_sz; + if (adapted_reply_) { + al.http.code = adapted_reply_->sline.status(); + al.http.content_type = adapted_reply_->content_type.termedBuf(); + if (replyHttpBodySize >= 0) al.cache.highOffset = replyHttpBodySize; - } //don't set al.cache.objectSize because it hasn't exist yet MemBuf mb; mb.init(); - reply_->header.packInto(&mb); + adapted_reply_->header.packInto(&mb); al.headers.reply = xstrdup(mb.buf); mb.clean(); } diff -u -r -N squid-4.0.14/src/adaptation/icap/ServiceRep.cc squid-4.0.15/src/adaptation/icap/ServiceRep.cc --- squid-4.0.14/src/adaptation/icap/ServiceRep.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/adaptation/icap/ServiceRep.cc 2016-10-10 08:05:51.000000000 +1300 @@ -33,7 +33,6 @@ Adaptation::Icap::ServiceRep::ServiceRep(const ServiceConfigPointer &svcCfg): AsyncJob("Adaptation::Icap::ServiceRep"), Adaptation::Service(svcCfg), - sslContext(NULL), theOptions(NULL), theOptionsFetcher(0), theLastUpdate(0), theBusyConns(0), theAllWaiters(0), diff -u -r -N squid-4.0.14/src/adaptation/icap/ServiceRep.h squid-4.0.15/src/adaptation/icap/ServiceRep.h --- squid-4.0.14/src/adaptation/icap/ServiceRep.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/adaptation/icap/ServiceRep.h 2016-10-10 08:05:51.000000000 +1300 @@ -110,7 +110,7 @@ // receive either an ICAP OPTIONS response header or an abort message virtual void noteAdaptationAnswer(const Answer &answer); - Security::ContextPtr sslContext; + Security::ContextPointer sslContext; Security::SessionStatePointer sslSession; private: diff -u -r -N squid-4.0.14/src/adaptation/icap/Xaction.cc squid-4.0.15/src/adaptation/icap/Xaction.cc --- squid-4.0.14/src/adaptation/icap/Xaction.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/adaptation/icap/Xaction.cc 2016-10-10 08:05:51.000000000 +1300 @@ -64,7 +64,9 @@ /* Security::PeerConnector API */ virtual bool initialize(Security::SessionPointer &); virtual void noteNegotiationDone(ErrorState *error); - virtual Security::ContextPtr getSslContext() {return icapService->sslContext;} + virtual Security::ContextPointer getTlsContext() { + return icapService->sslContext; + } private: Adaptation::Icap::ServiceRep::Pointer icapService; diff -u -r -N squid-4.0.14/src/anyp/PortCfg.cc squid-4.0.15/src/anyp/PortCfg.cc --- squid-4.0.14/src/anyp/PortCfg.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/anyp/PortCfg.cc 2016-10-10 08:05:51.000000000 +1300 @@ -103,7 +103,7 @@ #if 0 // TODO: AYJ: 2015-01-15: for now SSL does not clone the context object. // cloning should only be done before the PortCfg is post-configure initialized and opened - Security::ContextPtr sslContext; + Security::ContextPointer sslContext; #endif #endif /*0*/ diff -u -r -N squid-4.0.14/src/auth/basic/DB/basic_db_auth.8 squid-4.0.15/src/auth/basic/DB/basic_db_auth.8 --- squid-4.0.14/src/auth/basic/DB/basic_db_auth.8 2016-09-09 03:31:37.000000000 +1200 +++ squid-4.0.15/src/auth/basic/DB/basic_db_auth.8 2016-10-10 11:57:47.000000000 +1300 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) +.\" Automatically generated by Pod::Man 4.08 (Pod::Simple 3.32) .\" .\" Standard preamble: .\" ======================================================================== @@ -46,7 +46,7 @@ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" -.\" If the F register is turned on, we'll generate index entries on stderr for +.\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. @@ -54,20 +54,16 @@ .\" Avoid warning from groff about undefined register 'F'. .de IX .. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" +.if !\nF .nr F 0 +.if \nF>0 \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" .. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 . \} .\} -.rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. @@ -133,7 +129,7 @@ .\" ======================================================================== .\" .IX Title "BASIC_DB_AUTH 8" -.TH BASIC_DB_AUTH 8 "2016-09-08" "perl v5.22.2" "User Contributed Perl Documentation" +.TH BASIC_DB_AUTH 8 "2016-10-09" "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 @@ -194,7 +190,7 @@ Keep a persistent database connection open between queries. .IP "\fB\-\-joomla\fR" 12 .IX Item "--joomla" -Tells helper that user database is Joomla \s-1DB. \s0 So their unusual salt +Tells helper that user database is Joomla \s-1DB.\s0 So their unusual salt hashing is understood. .SH "AUTHOR" .IX Header "AUTHOR" @@ -233,7 +229,7 @@ Report ideas for new improvements to the \fISquid Developers mailing list .SH "SEE ALSO" .IX Header "SEE ALSO" -squid (8), \s-1GPL \\fIs0\fR\|(7), +squid (8), \s-1GPL\s0 (7), .PP The Squid \s-1FAQ\s0 wiki http://wiki.squid\-cache.org/SquidFaq .PP diff -u -r -N squid-4.0.14/src/auth/basic/POP3/basic_pop3_auth.8 squid-4.0.15/src/auth/basic/POP3/basic_pop3_auth.8 --- squid-4.0.14/src/auth/basic/POP3/basic_pop3_auth.8 2016-09-09 03:31:47.000000000 +1200 +++ squid-4.0.15/src/auth/basic/POP3/basic_pop3_auth.8 2016-10-10 11:58:16.000000000 +1300 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) +.\" Automatically generated by Pod::Man 4.08 (Pod::Simple 3.32) .\" .\" Standard preamble: .\" ======================================================================== @@ -46,7 +46,7 @@ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" -.\" If the F register is turned on, we'll generate index entries on stderr for +.\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. @@ -54,20 +54,16 @@ .\" Avoid warning from groff about undefined register 'F'. .de IX .. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" +.if !\nF .nr F 0 +.if \nF>0 \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" .. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 . \} .\} -.rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. @@ -133,7 +129,7 @@ .\" ======================================================================== .\" .IX Title "BASIC_POP3_AUTH 8" -.TH BASIC_POP3_AUTH 8 "2016-09-08" "perl v5.22.2" "User Contributed Perl Documentation" +.TH BASIC_POP3_AUTH 8 "2016-10-09" "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 @@ -202,7 +198,7 @@ Report ideas for new improvements to the \fISquid Developers mailing list .SH "SEE ALSO" .IX Header "SEE ALSO" -squid (8), \s-1GPL \\fIs0\fR\|(7), +squid (8), \s-1GPL\s0 (7), .PP The Squid \s-1FAQ\s0 wiki http://wiki.squid\-cache.org/SquidFaq .PP diff -u -r -N squid-4.0.14/src/base/RunnersRegistry.cc squid-4.0.15/src/base/RunnersRegistry.cc --- squid-4.0.14/src/base/RunnersRegistry.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/base/RunnersRegistry.cc 2016-10-10 08:05:51.000000000 +1300 @@ -8,6 +8,7 @@ #include "squid.h" #include "base/RunnersRegistry.h" +#include "base/TextException.h" #include /// a collection of unique runners, in no particular order @@ -19,7 +20,7 @@ /// creates the registered runners container if needed /// \return either registered runners (if they should exist) or nil (otherwise) -static Runners * +static inline Runners * FindRunners() { if (!TheRunners && !RunnersGone) @@ -35,11 +36,21 @@ // else ignore; IndependentRunner } +static inline void +RegisterRunner_(RegisteredRunner *rr) +{ + Runners *runners = FindRunners(); + Must(runners); + runners->insert(rr); +} + bool RegisterRunner(RegisteredRunner *rr) { - if (Runners *runners = FindRunners()) { - runners->insert(rr); + Must(!dynamic_cast(rr)); + + if (FindRunners()) { + RegisterRunner_(rr); return true; } @@ -88,6 +99,14 @@ // else it is too late, finishShutdown() has been called } +void +IndependentRunner::registerRunner() +{ + if (FindRunners()) + RegisterRunner_(this); + // else do nothing past finishShutdown +} + bool UseThisStatic(const void *) { diff -u -r -N squid-4.0.14/src/base/RunnersRegistry.h squid-4.0.15/src/base/RunnersRegistry.h --- squid-4.0.14/src/base/RunnersRegistry.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/base/RunnersRegistry.h 2016-10-10 08:05:51.000000000 +1300 @@ -57,6 +57,11 @@ /* Reconfiguration events */ + /// Called after receiving a reconfigure request and before parsing squid.conf. + /// Meant for modules that need to prepare for their configuration being changed + /// [outside their control]. The changes end with the syncConfig() event. + virtual void startReconfigure() {} + /// Called after parsing squid.conf during reconfiguration. /// Meant for adjusting the module state based on configuration changes. virtual void syncConfig() {} @@ -100,7 +105,7 @@ virtual ~IndependentRunner() { unregisterRunner(); } protected: - void registerRunner() {RegisterRunner(this);} + void registerRunner(); void unregisterRunner(); ///< unregisters self; safe to call multiple times }; diff -u -r -N squid-4.0.14/src/cache_cf.cc squid-4.0.15/src/cache_cf.cc --- squid-4.0.14/src/cache_cf.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/cache_cf.cc 2016-10-10 08:05:51.000000000 +1300 @@ -613,7 +613,7 @@ static void configDoConfigure(void) { - memset(&Config2, '\0', sizeof(SquidConfig2)); + Config2.clear(); /* init memory as early as possible */ memConfigure(); /* Sanity checks */ @@ -836,7 +836,7 @@ if (pwd->pw_dir && *pwd->pw_dir) { // putenv() leaks by design; avoid leaks when nothing changes static SBuf lastDir; - if (lastDir.isEmpty() || !lastDir.cmp(pwd->pw_dir)) { + if (lastDir.isEmpty() || lastDir.cmp(pwd->pw_dir) != 0) { lastDir = pwd->pw_dir; int len = strlen(pwd->pw_dir) + 6; char *env_str = (char *)xcalloc(len, 1); @@ -880,7 +880,7 @@ #endif } #if USE_OPENSSL - Ssl::useSquidUntrusted(Config.ssl_client.sslContext); + Ssl::useSquidUntrusted(Config.ssl_client.sslContext.get()); #endif } @@ -1487,7 +1487,7 @@ free_acl_tos(acl_tos ** head) { delete *head; - head = NULL; + *head = NULL; } #if SO_MARK && USE_LIBCAP @@ -1540,7 +1540,7 @@ free_acl_nfmark(acl_nfmark ** head) { delete *head; - head = NULL; + *head = NULL; } #endif /* SO_MARK */ @@ -3903,8 +3903,8 @@ configFreeMemory(void) { free_all(); + Config.ssl_client.sslContext.reset(); #if USE_OPENSSL - SSL_CTX_free(Config.ssl_client.sslContext); Ssl::unloadSquidUntrusted(); #endif } diff -u -r -N squid-4.0.14/src/CachePeer.cc squid-4.0.15/src/CachePeer.cc --- squid-4.0.14/src/CachePeer.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/CachePeer.cc 2016-10-10 08:05:51.000000000 +1300 @@ -40,9 +40,6 @@ connect_fail_limit(0), max_conn(0), domain(NULL), -#if USE_OPENSSL - sslContext(NULL), -#endif front_end_https(0), connection_auth(2 /* auto */) { @@ -97,10 +94,5 @@ PeerPoolMgr::Checkpoint(standby.mgr, "peer gone"); xfree(domain); - -#if USE_OPENSSL - if (sslContext) - SSL_CTX_free(sslContext); -#endif } diff -u -r -N squid-4.0.14/src/CachePeer.h squid-4.0.15/src/CachePeer.h --- squid-4.0.14/src/CachePeer.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/CachePeer.h 2016-10-10 08:05:51.000000000 +1300 @@ -183,7 +183,7 @@ /// security settings for peer connection Security::PeerOptions secure; - Security::ContextPtr sslContext; + Security::ContextPointer sslContext; Security::SessionStatePointer sslSession; int front_end_https; diff -u -r -N squid-4.0.14/src/cf.data.pre squid-4.0.15/src/cf.data.pre --- squid-4.0.14/src/cf.data.pre 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/cf.data.pre 2016-10-10 08:05:51.000000000 +1300 @@ -4519,13 +4519,35 @@ ICAP transaction log lines will correspond to a single access log line. - ICAP log uses logformat codes that make sense for an ICAP - transaction. Header-related codes are applied to the HTTP header - embedded in an ICAP server response, with the following caveats: - For REQMOD, there is no HTTP response header unless the ICAP - server performed request satisfaction. For RESPMOD, the HTTP - request header is the header sent to the ICAP server. For - OPTIONS, there are no HTTP headers. + ICAP log supports many access.log logformat %codes. In ICAP context, + HTTP message-related %codes are applied to the HTTP message embedded + in an ICAP message. Logformat "%http::>..." codes are used for HTTP + messages embedded in ICAP requests while "%http::<..." codes are used + for HTTP messages embedded in ICAP responses. For example: + + http::>h To-be-adapted HTTP message headers sent by Squid to + the ICAP service. For REQMOD transactions, these are + HTTP request headers. For RESPMOD, these are HTTP + response headers, but Squid currently cannot log them + (i.e., %http::>h will expand to "-" for RESPMOD). + + http::st Bytes sent to the ICAP server (TCP payload - only; i.e., what Squid writes to the socket). + icap::>st The total size of the ICAP request sent to the ICAP + server (ICAP headers + ICAP body), including chunking + metadata (if any). + + icap::a %icap::to/%03icap::Hs %icap::A %icap::to/%03icap::Hs %icap::http.method = request->method; aLogEntry->http.version = request->http_ver; aLogEntry->hier = request->hier; - if (request->content_length > 0) // negative when no body or unknown length - aLogEntry->http.clientRequestSz.payloadData += request->content_length; // XXX: actually adaptedRequest payload size ?? aLogEntry->cache.extuser = request->extacl_user.termedBuf(); // Adapted request, if any, inherits and then collects all the stats, but @@ -400,6 +398,9 @@ al->cache.objectSize = loggingEntry()->contentLen(); // payload duplicate ?? with or without TE ? al->http.clientRequestSz.header = req_sz; + // the virgin request is saved to al->request + if (al->request && al->request->body_pipe) + al->http.clientRequestSz.payloadData = al->request->body_pipe->producedSize(); al->http.clientReplySz.header = out.headers_sz; // XXX: calculate without payload encoding or headers !! al->http.clientReplySz.payloadData = out.size - out.headers_sz; // pretend its all un-encoded data for now. @@ -1508,16 +1509,16 @@ // In bump-server-first mode, we have not necessarily seen the intended // server name at certificate-peeking time. Check for domain mismatch now, // when we can extract the intended name from the bumped HTTP request. - if (X509 *srvCert = sslServerBump->serverCert.get()) { + if (const Security::CertPointer &srvCert = sslServerBump->serverCert) { HttpRequest *request = http->request; - if (!Ssl::checkX509ServerValidity(srvCert, request->url.host())) { + if (!Ssl::checkX509ServerValidity(srvCert.get(), request->url.host())) { debugs(33, 2, "SQUID_X509_V_ERR_DOMAIN_MISMATCH: Certificate " << "does not match domainname " << request->url.host()); bool allowDomainMismatch = false; if (Config.ssl_client.cert_error) { ACLFilledChecklist check(Config.ssl_client.cert_error, request, dash_str); - check.sslErrors = new Ssl::CertErrors(Ssl::CertError(SQUID_X509_V_ERR_DOMAIN_MISMATCH, srvCert)); + check.sslErrors = new Security::CertErrors(Security::CertError(SQUID_X509_V_ERR_DOMAIN_MISMATCH, srvCert)); allowDomainMismatch = (check.fastCheck() == ACCESS_ALLOWED); delete check.sslErrors; check.sslErrors = NULL; @@ -1539,7 +1540,7 @@ err->src_addr = clientConnection->remote; Ssl::ErrorDetail *errDetail = new Ssl::ErrorDetail( SQUID_X509_V_ERR_DOMAIN_MISMATCH, - srvCert, NULL); + srvCert.get(), nullptr); err->detail = errDetail; // Save the original request for logging purposes. if (!context->http->al->request) { @@ -2448,7 +2449,7 @@ // register to receive notice of Squid signal events // which may affect long persisting client connections - RegisterRunner(this); + registerRunner(); } void @@ -2579,9 +2580,9 @@ /** Create SSL connection structure and update fd_table */ static bool -httpsCreate(const Comm::ConnectionPointer &conn, Security::ContextPtr sslContext) +httpsCreate(const Comm::ConnectionPointer &conn, const Security::ContextPointer &ctx) { - if (Ssl::CreateServer(sslContext, conn, "client https start")) { + if (Ssl::CreateServer(ctx, conn, "client https start")) { debugs(33, 5, "will negotate SSL on " << conn); return true; } @@ -2648,9 +2649,6 @@ clientNegotiateSSL(int fd, void *data) { ConnStateData *conn = (ConnStateData *)data; - X509 *client_cert; - auto ssl = fd_table[fd].ssl.get(); - int ret; if ((ret = Squid_SSL_accept(conn, clientNegotiateSSL)) <= 0) { if (ret < 0) // An error @@ -2658,16 +2656,21 @@ return; } - if (Security::SessionIsResumed(fd_table[fd].ssl)) { - debugs(83, 2, "clientNegotiateSSL: Session " << SSL_get_session(ssl) << - " reused on FD " << fd << " (" << fd_table[fd].ipaddr << ":" << (int)fd_table[fd].remote_port << ")"); + Security::SessionPointer session(fd_table[fd].ssl); + if (Security::SessionIsResumed(session)) { + debugs(83, 2, "Session " << SSL_get_session(session.get()) << + " reused on FD " << fd << " (" << fd_table[fd].ipaddr << + ":" << (int)fd_table[fd].remote_port << ")"); } else { if (Debug::Enabled(83, 4)) { /* Write out the SSL session details.. actually the call below, but * OpenSSL headers do strange typecasts confusing GCC.. */ /* PEM_write_SSL_SESSION(debug_log, SSL_get_session(ssl)); */ #if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x00908000L - PEM_ASN1_write((i2d_of_void *)i2d_SSL_SESSION, PEM_STRING_SSL_SESSION, debug_log, (char *)SSL_get_session(ssl), NULL,NULL,0,NULL,NULL); + PEM_ASN1_write(reinterpret_cast(i2d_SSL_SESSION), + PEM_STRING_SSL_SESSION, debug_log, + reinterpret_cast(SSL_get_session(session.get())), + nullptr, nullptr, 0, nullptr, nullptr); #elif (ALLOW_ALWAYS_SSL_SESSION_DETAIL == 1) @@ -2678,47 +2681,48 @@ * Because there are two possible usable cast, if you get an error here, try the other * commented line. */ - PEM_ASN1_write((int(*)())i2d_SSL_SESSION, PEM_STRING_SSL_SESSION, debug_log, (char *)SSL_get_session(ssl), NULL,NULL,0,NULL,NULL); - /* PEM_ASN1_write((int(*)(...))i2d_SSL_SESSION, PEM_STRING_SSL_SESSION, debug_log, (char *)SSL_get_session(ssl), NULL,NULL,0,NULL,NULL); */ - + PEM_ASN1_write((int(*)())i2d_SSL_SESSION, PEM_STRING_SSL_SESSION, + debug_log, + reinterpret_cast(SSL_get_session(session.get())), + nullptr, nullptr, 0, nullptr, nullptr); + /* PEM_ASN1_write((int(*)(...))i2d_SSL_SESSION, PEM_STRING_SSL_SESSION, + debug_log, + reinterpret_cast(SSL_get_session(session.get())), + nullptr, nullptr, 0, nullptr, nullptr); + */ #else - - debugs(83, 4, "With " OPENSSL_VERSION_TEXT ", session details are available only defining ALLOW_ALWAYS_SSL_SESSION_DETAIL=1 in the source." ); + debugs(83, 4, "With " OPENSSL_VERSION_TEXT ", session details are available only defining ALLOW_ALWAYS_SSL_SESSION_DETAIL=1 in the source."); #endif /* Note: This does not automatically fflush the log file.. */ } - debugs(83, 2, "clientNegotiateSSL: New session " << - SSL_get_session(ssl) << " on FD " << fd << " (" << - fd_table[fd].ipaddr << ":" << (int)fd_table[fd].remote_port << - ")"); + debugs(83, 2, "New session " << SSL_get_session(session.get()) << + " on FD " << fd << " (" << fd_table[fd].ipaddr << ":" << + fd_table[fd].remote_port << ")"); } // Connection established. Retrieve TLS connection parameters for logging. - conn->clientConnection->tlsNegotiations()->retrieveNegotiatedInfo(ssl); + conn->clientConnection->tlsNegotiations()->retrieveNegotiatedInfo(session); - client_cert = SSL_get_peer_certificate(ssl); + X509 *client_cert = SSL_get_peer_certificate(session.get()); - if (client_cert != NULL) { - debugs(83, 3, "clientNegotiateSSL: FD " << fd << - " client certificate: subject: " << + if (client_cert) { + debugs(83, 3, "FD " << fd << " client certificate: subject: " << X509_NAME_oneline(X509_get_subject_name(client_cert), 0, 0)); - debugs(83, 3, "clientNegotiateSSL: FD " << fd << - " client certificate: issuer: " << + debugs(83, 3, "FD " << fd << " client certificate: issuer: " << X509_NAME_oneline(X509_get_issuer_name(client_cert), 0, 0)); X509_free(client_cert); } else { - debugs(83, 5, "clientNegotiateSSL: FD " << fd << - " has no certificate."); + debugs(83, 5, "FD " << fd << " has no certificate."); } #if defined(TLSEXT_NAMETYPE_host_name) if (!conn->serverBump()) { // when in bumpClientFirst mode, get the server name from SNI - if (const char *server = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name)) + if (const char *server = SSL_get_servername(session.get(), TLSEXT_NAMETYPE_host_name)) conn->resetSslCommonName(server); } #endif @@ -2727,16 +2731,16 @@ } /** - * If Security::ContextPtr is given, starts reading the TLS handshake. - * Otherwise, calls switchToHttps to generate a dynamic Security::ContextPtr. + * If Security::ContextPointer is given, starts reading the TLS handshake. + * Otherwise, calls switchToHttps to generate a dynamic Security::ContextPointer. */ static void -httpsEstablish(ConnStateData *connState, Security::ContextPtr sslContext) +httpsEstablish(ConnStateData *connState, const Security::ContextPointer &ctx) { assert(connState); const Comm::ConnectionPointer &details = connState->clientConnection; - if (!sslContext || !httpsCreate(details, sslContext)) + if (!ctx || !httpsCreate(details, ctx)) return; typedef CommCbMemFunT TimeoutDialer; @@ -2837,7 +2841,7 @@ acl_checklist->nonBlockingCheck(httpsSslBumpAccessCheckDone, this); return; } else { - httpsEstablish(this, port->secure.staticContext.get()); + httpsEstablish(this, port->secure.staticContext); } } @@ -2876,17 +2880,19 @@ if (!ret) debugs(33, 5, "Failed to set certificates to ssl object for PeekAndSplice mode"); - SSL_CTX *sslContext = SSL_get_SSL_CTX(ssl); - Ssl::configureUnconfiguredSslContext(sslContext, signAlgorithm, *port); + Security::ContextPointer ctx; + ctx.resetAndLock(SSL_get_SSL_CTX(ssl)); + Ssl::configureUnconfiguredSslContext(ctx, signAlgorithm, *port); } else { - auto ctx = Ssl::generateSslContextUsingPkeyAndCertFromMemory(reply_message.getBody().c_str(), *port); + Security::ContextPointer ctx(Ssl::generateSslContextUsingPkeyAndCertFromMemory(reply_message.getBody().c_str(), *port)); getSslContextDone(ctx, true); } return; } } } - getSslContextDone(NULL); + Security::ContextPointer nil; + getSslContextDone(nil); } void ConnStateData::buildSslCertGenerationParams(Ssl::CertificateProperties &certProperties) @@ -2999,13 +3005,12 @@ if (!(sslServerBump && (sslServerBump->act.step1 == Ssl::bumpPeek || sslServerBump->act.step1 == Ssl::bumpStare))) { debugs(33, 5, "Finding SSL certificate for " << sslBumpCertKey << " in cache"); Ssl::LocalContextStorage * ssl_ctx_cache = Ssl::TheGlobalContextStorage.getLocalStorage(port->s); - Security::ContextPtr dynCtx = nullptr; Security::ContextPointer *cachedCtx = ssl_ctx_cache ? ssl_ctx_cache->get(sslBumpCertKey.termedBuf()) : nullptr; - if (cachedCtx && (dynCtx = cachedCtx->get())) { + if (cachedCtx) { debugs(33, 5, "SSL certificate for " << sslBumpCertKey << " found in cache"); - if (Ssl::verifySslCertificate(dynCtx, certProperties)) { + if (Ssl::verifySslCertificate(*cachedCtx, certProperties)) { debugs(33, 5, "Cached SSL certificate for " << sslBumpCertKey << " is valid"); - getSslContextDone(dynCtx); + getSslContextDone(*cachedCtx); return; } else { debugs(33, 5, "Cached SSL certificate for " << sslBumpCertKey << " is out of date. Delete this certificate from cache"); @@ -3042,25 +3047,28 @@ if (!Ssl::configureSSL(ssl, certProperties, *port)) debugs(33, 5, "Failed to set certificates to ssl object for PeekAndSplice mode"); - SSL_CTX *sslContext = SSL_get_SSL_CTX(ssl); - Ssl::configureUnconfiguredSslContext(sslContext, certProperties.signAlgorithm, *port); + Security::ContextPointer ctx; + ctx.resetAndLock(SSL_get_SSL_CTX(ssl)); + Ssl::configureUnconfiguredSslContext(ctx, certProperties.signAlgorithm, *port); } else { - auto dynCtx = Ssl::generateSslContext(certProperties, *port); + Security::ContextPointer dynCtx(Ssl::generateSslContext(certProperties, *port)); getSslContextDone(dynCtx, true); } return; } - getSslContextDone(NULL); + + Security::ContextPointer nil; + getSslContextDone(nil); } void -ConnStateData::getSslContextDone(Security::ContextPtr sslContext, bool isNew) +ConnStateData::getSslContextDone(Security::ContextPointer &ctx, bool isNew) { // Try to add generated ssl context to storage. if (port->generateHostCertificates && isNew) { - if (sslContext && (signAlgorithm == Ssl::algSignTrusted)) { - Ssl::chainCertificatesToSSLContext(sslContext, *port); + if (ctx && (signAlgorithm == Ssl::algSignTrusted)) { + Ssl::chainCertificatesToSSLContext(ctx, *port); } else if (signAlgorithm == Ssl::algSignTrusted) { debugs(33, DBG_IMPORTANT, "WARNING: can not add signing certificate to SSL context chain because SSL context chain is invalid!"); } @@ -3068,10 +3076,10 @@ Ssl::LocalContextStorage *ssl_ctx_cache = Ssl::TheGlobalContextStorage.getLocalStorage(port->s); assert(sslBumpCertKey.size() > 0 && sslBumpCertKey[0] != '\0'); - if (sslContext) { - if (!ssl_ctx_cache || !ssl_ctx_cache->add(sslBumpCertKey.termedBuf(), new Security::ContextPointer(sslContext))) { + if (ctx) { + if (!ssl_ctx_cache || !ssl_ctx_cache->add(sslBumpCertKey.termedBuf(), new Security::ContextPointer(ctx))) { // If it is not in storage delete after using. Else storage deleted it. - fd_table[clientConnection->fd].dynamicSslContext = sslContext; + fd_table[clientConnection->fd].dynamicTlsContext = ctx; } } else { debugs(33, 2, HERE << "Failed to generate SSL cert for " << sslConnectHostOrIp); @@ -3079,18 +3087,18 @@ } // If generated ssl context = NULL, try to use static ssl context. - if (!sslContext) { + if (!ctx) { if (!port->secure.staticContext) { debugs(83, DBG_IMPORTANT, "Closing " << clientConnection->remote << " as lacking TLS context"); clientConnection->close(); return; } else { debugs(33, 5, "Using static TLS context."); - sslContext = port->secure.staticContext.get(); + ctx = port->secure.staticContext; } } - if (!httpsCreate(clientConnection, sslContext)) + if (!httpsCreate(clientConnection, ctx)) return; // bumped intercepted conns should already have Config.Timeout.request set @@ -3311,8 +3319,8 @@ } // will call httpsPeeked() with certificate and connection, eventually - auto unConfiguredCTX = Ssl::createSSLContext(port->signingCert, port->signPkey, *port); - fd_table[clientConnection->fd].dynamicSslContext = unConfiguredCTX; + Security::ContextPointer unConfiguredCTX(Ssl::createSSLContext(port->signingCert, port->signPkey, *port)); + fd_table[clientConnection->fd].dynamicTlsContext = unConfiguredCTX; if (!httpsCreate(clientConnection, unConfiguredCTX)) return; diff -u -r -N squid-4.0.14/src/client_side.h squid-4.0.15/src/client_side.h --- squid-4.0.14/src/client_side.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/client_side.h 2016-10-10 08:05:51.000000000 +1300 @@ -221,14 +221,14 @@ /// \retval false otherwise bool spliceOnError(const err_type err); - /// Start to create dynamic Security::ContextPtr for host or uses static port SSL context. + /// Start to create dynamic Security::ContextPointer for host or uses static port SSL context. void getSslContextStart(); /** * Done create dynamic ssl certificate. * * \param[in] isNew if generated certificate is new, so we need to add this certificate to storage. */ - void getSslContextDone(Security::ContextPtr sslContext, bool isNew = false); + void getSslContextDone(Security::ContextPointer &, bool isNew = false); /// Callback function. It is called when squid receive message from ssl_crtd. static void sslCrtdHandleReplyWrapper(void *data, const Helper::Reply &reply); /// Proccess response from ssl_crtd. diff -u -r -N squid-4.0.14/src/client_side_reply.cc squid-4.0.15/src/client_side_reply.cc --- squid-4.0.14/src/client_side_reply.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/client_side_reply.cc 2016-10-10 08:05:51.000000000 +1300 @@ -266,7 +266,8 @@ { const char *url = storeId(); debugs(88, 3, "clientReplyContext::processExpired: '" << http->uri << "'"); - assert(http->storeEntry()->lastmod >= 0); + const time_t lastmod = http->storeEntry()->lastModified(); + assert(lastmod >= 0); /* * check if we are allowed to contact other servers * @?@: Instead of a 504 (Gateway Timeout) reply, we may want to return @@ -323,7 +324,7 @@ sc->setDelayId(DelayId::DelayClient(http)); #endif - http->request->lastmod = old_entry->lastmod; + http->request->lastmod = lastmod; if (!http->request->header.has(Http::HdrType::IF_NONE_MATCH)) { ETag etag = {NULL, -1}; // TODO: make that a default ETag constructor @@ -331,7 +332,7 @@ http->request->etag = etag.str; } - debugs(88, 5, "clientReplyContext::processExpired : lastmod " << entry->lastmod ); + debugs(88, 5, "lastmod " << entry->lastModified()); http->storeEntry(entry); assert(http->out.offset == 0); assert(http->request->clientConnectionManager == http->getConn()); @@ -406,7 +407,7 @@ if (deleting) return; - debugs(88, 3, "handleIMSReply: " << http->storeEntry()->url() << ", " << (long unsigned) result.length << " bytes" ); + debugs(88, 3, http->storeEntry()->url() << ", " << (long unsigned) result.length << " bytes"); if (http->storeEntry() == NULL) return; @@ -421,7 +422,7 @@ // request to origin was aborted if (EBIT_TEST(http->storeEntry()->flags, ENTRY_ABORTED)) { - debugs(88, 3, "handleIMSReply: request to origin aborted '" << http->storeEntry()->url() << "', sending old entry to client" ); + debugs(88, 3, "request to origin aborted '" << http->storeEntry()->url() << "', sending old entry to client"); http->logType = LOG_TCP_REFRESH_FAIL_OLD; sendClientOldEntry(); } @@ -438,13 +439,13 @@ // if client sent IMS - if (http->request->flags.ims && !old_entry->modifiedSince(http->request)) { + if (http->request->flags.ims && !old_entry->modifiedSince(http->request->ims, http->request->imslen)) { // forward the 304 from origin - debugs(88, 3, "handleIMSReply: origin replied 304, revalidating existing entry and forwarding 304 to client"); + debugs(88, 3, "origin replied 304, revalidating existing entry and forwarding 304 to client"); sendClientUpstreamResponse(); } else { // send existing entry, it's still valid - debugs(88, 3, "handleIMSReply: origin replied 304, revalidating existing entry and sending " << + debugs(88, 3, "origin replied 304, revalidating existing entry and sending " << old_rep->sline.status() << " to client"); sendClientOldEntry(); } @@ -452,26 +453,37 @@ // origin replied with a non-error code else if (status > Http::scNone && status < Http::scInternalServerError) { - // forward response from origin - http->logType = LOG_TCP_REFRESH_MODIFIED; - debugs(88, 3, "handleIMSReply: origin replied " << status << ", replacing existing entry and forwarding to client"); + const HttpReply *new_rep = http->storeEntry()->getReply(); + // RFC 7234 section 4: a cache MUST use the most recent response + // (as determined by the Date header field) + if (new_rep->olderThan(old_rep)) { + http->logType.err.ignored = true; + debugs(88, 3, "origin replied " << status << + " but with an older date header, sending old entry (" << + old_rep->sline.status() << ") to client"); + sendClientOldEntry(); + } else { + http->logType = LOG_TCP_REFRESH_MODIFIED; + debugs(88, 3, "origin replied " << status << + ", replacing existing entry and forwarding to client"); - if (collapsedRevalidation) - http->storeEntry()->clearPublicKeyScope(); + if (collapsedRevalidation) + http->storeEntry()->clearPublicKeyScope(); - sendClientUpstreamResponse(); + sendClientUpstreamResponse(); + } } // origin replied with an error else if (http->request->flags.failOnValidationError) { http->logType = LOG_TCP_REFRESH_FAIL_ERR; - debugs(88, 3, "handleIMSReply: origin replied with error " << status << + debugs(88, 3, "origin replied with error " << status << ", forwarding to client due to fail_on_validation_err"); sendClientUpstreamResponse(); } else { // ignore and let client have old entry http->logType = LOG_TCP_REFRESH_FAIL_OLD; - debugs(88, 3, "handleIMSReply: origin replied with error " << + debugs(88, 3, "origin replied with error " << status << ", sending old entry (" << old_rep->sline.status() << ") to client"); sendClientOldEntry(); } @@ -614,11 +626,12 @@ */ r->flags.needValidation = true; - if (e->lastmod < 0) { - debugs(88, 3, "validate HIT object? NO. Missing Last-Modified header. Do MISS."); + if (e->lastModified() < 0) { + debugs(88, 3, "validate HIT object? NO. Can't calculate entry modification time. Do MISS."); /* - * Previous reply didn't have a Last-Modified header, - * we cannot revalidate it. + * We cannot revalidate entries without knowing their + * modification time. + * XXX: BUG 1890 objects without Date do not get one added. */ http->logType = LOG_TCP_MISS; processMiss(); @@ -807,7 +820,7 @@ if (r.flags.ims) { // handle If-Modified-Since requests from the client - if (e->modifiedSince(&r)) { + if (e->modifiedSince(r.ims, r.imslen)) { http->logType = LOG_TCP_IMS_HIT; sendMoreData(result); return; diff -u -r -N squid-4.0.14/src/client_side_request.cc squid-4.0.15/src/client_side_request.cc --- squid-4.0.14/src/client_side_request.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/client_side_request.cc 2016-10-10 08:05:51.000000000 +1300 @@ -1787,8 +1787,9 @@ if (calloutContext->error) { // XXX: prformance regression. c_str() reallocates - SBuf storeUri(request->storeId()); - StoreEntry *e = storeCreateEntry(storeUri.c_str(), storeUri.c_str(), request->flags, request->method); + SBuf storeUriBuf(request->storeId()); + const char *storeUri = storeUriBuf.c_str(); + StoreEntry *e = storeCreateEntry(storeUri, storeUri, request->flags, request->method); #if USE_OPENSSL if (sslBumpNeeded()) { // We have to serve an error, so bump the client first. diff -u -r -N squid-4.0.14/src/comm.cc squid-4.0.15/src/comm.cc --- squid-4.0.14/src/comm.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/comm.cc 2016-10-10 08:05:51.000000000 +1300 @@ -839,13 +839,7 @@ { fde *F = &fd_table[params.fd]; F->ssl.reset(); - -#if USE_OPENSSL - if (F->dynamicSslContext) { - SSL_CTX_free(F->dynamicSslContext); - F->dynamicSslContext = NULL; - } -#endif + F->dynamicTlsContext.reset(); fd_close(params.fd); /* update fdstat */ close(params.fd); diff -u -r -N squid-4.0.14/src/dns/forward.h squid-4.0.15/src/dns/forward.h --- squid-4.0.14/src/dns/forward.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/dns/forward.h 2016-10-10 08:05:51.000000000 +1300 @@ -9,23 +9,19 @@ #ifndef _SQUID_SRC_DNS_FORWARD_H #define _SQUID_SRC_DNS_FORWARD_H -namespace Ip -{ -class Address; -} +#include "ip/forward.h" class rfc1035_rr; typedef void IDNSCB(void *, const rfc1035_rr *, int, const char *); -// generic DNS API +/// generic DNS API namespace Dns { class LookupDetails; void Init(void); -void Shutdown(void); } // namespace Dns diff -u -r -N squid-4.0.14/src/dns_internal.cc squid-4.0.15/src/dns_internal.cc --- squid-4.0.14/src/dns_internal.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/dns_internal.cc 2016-10-10 08:05:51.000000000 +1300 @@ -10,6 +10,7 @@ #include "squid.h" #include "base/InstanceId.h" +#include "base/RunnersRegistry.h" #include "comm.h" #include "comm/Connection.h" #include "comm/ConnOpener.h" @@ -209,6 +210,22 @@ nsvc *vc; }; +namespace Dns +{ + +/// manage DNS internal component +class ConfigRr : public RegisteredRunner +{ +public: + /* RegisteredRunner API */ + virtual void startReconfigure() override; + virtual void endingShutdown() override; +}; + +RunnerRegistrationEntry(ConfigRr); + +} // namespace Dns + struct _sp { char domain[NS_MAXDNAME]; int queries; @@ -903,7 +920,7 @@ { delete queue; delete msg; - if (ns < nns) // XXX: Dns::Shutdown may have freed nameservers[] + if (ns < nns) // XXX: idnsShutdownAndFreeState may have freed nameservers[] nameservers[ns].vc = NULL; } @@ -962,6 +979,13 @@ static void idnsSendQuery(idns_query * q) { + // XXX: DNS sockets get closed during reconfigure produces a race between + // any already active connections (or ones received between closing DNS + // sockets and server listening sockets) and the reconfigure completing + // (Runner syncConfig() being run). Transactions which loose this race will + // produce DNS timeouts (or whatever the caller set) as their queries never + // get queued to be re-tried after the DNS socekts are re-opened. + if (DnsSocketA < 0 && DnsSocketB < 0) { debugs(78, DBG_IMPORTANT, "WARNING: idnsSendQuery: Can't send query, no DNS socket!"); return; @@ -1641,12 +1665,14 @@ Mgr::RegisterAction("idns", "Internal DNS Statistics", idnsStats, 0, 1); } -void -Dns::Shutdown(void) +static void +idnsShutdownAndFreeState(const char *reason) { if (DnsSocketA < 0 && DnsSocketB < 0) return; + debugs(78, 2, reason << ": Closing DNS sockets"); + if (DnsSocketA >= 0 ) { comm_close(DnsSocketA); DnsSocketA = -1; @@ -1669,6 +1695,18 @@ idnsFreeSearchpath(); } +void +Dns::ConfigRr::endingShutdown() +{ + idnsShutdownAndFreeState("Shutdown"); +} + +void +Dns::ConfigRr::startReconfigure() +{ + idnsShutdownAndFreeState("Reconfigure"); +} + static int idnsCachedLookup(const char *key, IDNSCB * callback, void *data) { diff -u -r -N squid-4.0.14/src/Downloader.cc squid-4.0.15/src/Downloader.cc --- squid-4.0.14/src/Downloader.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/Downloader.cc 2016-10-10 08:05:51.000000000 +1300 @@ -73,6 +73,17 @@ Downloader::~Downloader() { + debugs(33, 6, this); +} + +void +Downloader::swanSong() +{ + debugs(33, 6, this); + if (context_) { + context_->finished(); + context_ = nullptr; + } } bool @@ -234,12 +245,6 @@ Downloader::downloadFinished() { debugs(33, 7, this); - // We cannot delay http destruction until refcounting deletes - // DownloaderContext. The http object destruction will cause - // clientStream cleanup and will release the refcount to context_ - // object hold by clientStream structures. - context_->finished(); - context_ = nullptr; Must(done()); } @@ -256,12 +261,10 @@ ScheduleCallHere(callback_); callback_ = nullptr; - // Calling deleteThis method here to finish Downloader - // may result to squid crash. - // This method called by handleReply method which maybe called - // by ClientHttpRequest::doCallouts. The doCallouts after this object - // deleted, may operate on non valid objects. - // Schedule an async call here just to force squid to delete this object. + // We cannot deleteThis() because we may be called synchronously from + // doCallouts() via handleReply() (XXX), and doCallouts() may crash if we + // disappear. Instead, schedule an async call now so that later, when the + // call firing code discovers a done() job, it deletes us. CallJobHere(33, 7, CbcPointer(this), Downloader, downloadFinished); } diff -u -r -N squid-4.0.14/src/Downloader.h squid-4.0.15/src/Downloader.h --- squid-4.0.14/src/Downloader.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/Downloader.h 2016-10-10 08:05:51.000000000 +1300 @@ -47,6 +47,7 @@ Downloader(SBuf &url, AsyncCall::Pointer &aCallback, unsigned int level = 0); virtual ~Downloader(); + virtual void swanSong(); /// delays destruction to protect doCallouts() void downloadFinished(); diff -u -r -N squid-4.0.14/src/errorpage.cc squid-4.0.15/src/errorpage.cc --- squid-4.0.14/src/errorpage.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/errorpage.cc 2016-10-10 08:05:51.000000000 +1300 @@ -361,7 +361,6 @@ bool strHdrAcptLangGetItem(const String &hdr, char *lang, int langLen, size_t &pos) { while (pos < hdr.size()) { - char *dt = lang; /* skip any initial whitespace. */ while (pos < hdr.size() && xisspace(hdr[pos])) @@ -375,6 +374,7 @@ * with preference given to an exact match. */ bool invalid_byte = false; + char *dt = lang; while (pos < hdr.size() && hdr[pos] != ';' && hdr[pos] != ',' && !xisspace(hdr[pos]) && dt < (lang + (langLen -1)) ) { if (!invalid_byte) { #if USE_HTTP_VIOLATIONS @@ -394,7 +394,6 @@ ++pos; } *dt = '\0'; // nul-terminated the filename content string before system use. - ++dt; // if we terminated the tag on garbage or ';' we need to skip to the next ',' or end of header. while (pos < hdr.size() && hdr[pos] != ',') @@ -403,7 +402,7 @@ if (pos < hdr.size() && hdr[pos] == ',') ++pos; - debugs(4, 9, HERE << "STATE: dt='" << dt << "', lang='" << lang << "', pos=" << pos << ", buf='" << ((pos < hdr.size()) ? hdr.substr(pos,hdr.size()) : "") << "'"); + debugs(4, 9, "STATE: lang=" << lang << ", pos=" << pos << ", buf='" << ((pos < hdr.size()) ? hdr.substr(pos,hdr.size()) : "") << "'"); /* if we found anything we might use, try it. */ if (*lang != '\0' && !invalid_byte) diff -u -r -N squid-4.0.14/src/fde.h squid-4.0.15/src/fde.h --- squid-4.0.14/src/fde.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/fde.h 2016-10-10 08:05:51.000000000 +1300 @@ -120,7 +120,7 @@ READ_HANDLER *read_method; WRITE_HANDLER *write_method; Security::SessionPointer ssl; - Security::ContextPtr dynamicSslContext; ///< cached and then freed when fd is closed + Security::ContextPointer dynamicTlsContext; ///< cached and then freed when fd is closed #if _SQUID_WINDOWS_ struct { long handle; @@ -168,7 +168,7 @@ read_method = NULL; write_method = NULL; ssl.reset(); - dynamicSslContext = NULL; + dynamicTlsContext.reset(); #if _SQUID_WINDOWS_ win32.handle = (long)NULL; #endif diff -u -r -N squid-4.0.14/src/format/Format.cc squid-4.0.15/src/format/Format.cc --- squid-4.0.14/src/format/Format.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/format/Format.cc 2016-10-10 08:05:51.000000000 +1300 @@ -21,6 +21,7 @@ #include "HttpRequest.h" #include "MemBuf.h" #include "rfc1738.h" +#include "security/CertError.h" #include "security/NegotiationHistory.h" #include "SquidTime.h" #include "Store.h" @@ -322,13 +323,45 @@ #if USE_OPENSSL static char * -sslErrorName(Ssl::ssl_error_t err, char *buf, size_t size) +sslErrorName(Security::ErrorCode err, char *buf, size_t size) { snprintf(buf, size, "SSL_ERR=%d", err); return buf; } #endif +/// XXX: Misnamed. TODO: Split reply; +#if USE_ADAPTATION + // al->icap.reqMethod is methodNone in access.log context + if (!msg && al->icap.reqMethod == Adaptation::methodReqmod) + msg = al->adapted_request; +#endif + return msg; +} + +/// XXX: Misnamed. See actualReplyHeader(). +/// \return HttpRequest or HttpReply for %http::>h. +static const HttpMsg * +actualRequestHeader(const AccessLogEntry::Pointer &al) +{ +#if USE_ADAPTATION + // al->icap.reqMethod is methodNone in access.log context + if (al->icap.reqMethod == Adaptation::methodRespmod) { + // XXX: for now AccessLogEntry lacks virgin response headers + return nullptr; + } +#endif + return al->request; +} + void Format::Format::assemble(MemBuf &mb, const AccessLogEntry::Pointer &al, int logSequenceNumber) const { @@ -377,6 +410,9 @@ if (al->request) { outint = al->request->client_addr.port(); doint = 1; + } else if (al->tcpClient) { + outint = al->tcpClient->remote.port(); + doint = 1; } break; @@ -592,9 +628,8 @@ break; case LFT_REQUEST_HEADER: - - if (al->request) - sb = al->request->header.getByName(fmt->data.header.header); + if (const HttpMsg *msg = actualRequestHeader(al)) + sb = msg->header.getByName(fmt->data.header.header); out = sb.termedBuf(); @@ -613,15 +648,15 @@ break; - case LFT_REPLY_HEADER: - if (al->reply) - sb = al->reply->header.getByName(fmt->data.header.header); + case LFT_REPLY_HEADER: { + if (const HttpMsg *msg = actualReplyHeader(al)) + sb = msg->header.getByName(fmt->data.header.header); out = sb.termedBuf(); quote = 1; - - break; + } + break; #if USE_ADAPTATION case LFT_ADAPTATION_SUM_XACT_TIMES: @@ -803,8 +838,8 @@ break; #endif case LFT_REQUEST_HEADER_ELEM: - if (al->request) - sb = al->request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator); + if (const HttpMsg *msg = actualRequestHeader(al)) + sb = msg->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator); out = sb.termedBuf(); @@ -822,18 +857,27 @@ break; - case LFT_REPLY_HEADER_ELEM: - if (al->reply) - sb = al->reply->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator); + case LFT_REPLY_HEADER_ELEM: { + if (const HttpMsg *msg = actualReplyHeader(al)) + sb = msg->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator); out = sb.termedBuf(); quote = 1; - - break; + } + break; case LFT_REQUEST_ALL_HEADERS: - out = al->headers.request; +#if USE_ADAPTATION + if (al->icap.reqMethod == Adaptation::methodRespmod) { + // XXX: since AccessLogEntry::Headers lacks virgin response + // headers, do nothing for now + out = nullptr; + } else +#endif + { + out = al->headers.request; + } quote = 1; @@ -848,6 +892,10 @@ case LFT_REPLY_ALL_HEADERS: out = al->headers.reply; +#if USE_ADAPTATION + if (!out && al->icap.reqMethod == Adaptation::methodReqmod) + out = al->headers.adapted_request; +#endif quote = 1; @@ -1261,7 +1309,7 @@ if (al->request && al->request->clientConnectionManager.valid()) { if (Ssl::ServerBump * srvBump = al->request->clientConnectionManager->serverBump()) { const char *separator = fmt->data.string ? fmt->data.string : ":"; - for (Ssl::CertErrors const *sslError = srvBump->sslErrors(); sslError != NULL; sslError = sslError->next) { + for (const Security::CertErrors *sslError = srvBump->sslErrors(); sslError != nullptr; sslError = sslError->next) { if (sb.size()) sb.append(separator); if (const char *errorName = Ssl::GetErrorName(sslError->element.code)) diff -u -r -N squid-4.0.14/src/fs/rock/RockHeaderUpdater.cc squid-4.0.15/src/fs/rock/RockHeaderUpdater.cc --- squid-4.0.14/src/fs/rock/RockHeaderUpdater.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/fs/rock/RockHeaderUpdater.cc 2016-10-10 08:05:51.000000000 +1300 @@ -184,6 +184,7 @@ Must(freshSwapHeader); writer->write(freshSwapHeader, freshSwapHeaderSize, 0, nullptr); offset += freshSwapHeaderSize; + xfree(freshSwapHeader); } { diff -u -r -N squid-4.0.14/src/fs/rock/RockSwapDir.cc squid-4.0.15/src/fs/rock/RockSwapDir.cc --- squid-4.0.14/src/fs/rock/RockSwapDir.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/fs/rock/RockSwapDir.cc 2016-10-10 08:05:51.000000000 +1300 @@ -122,7 +122,7 @@ e.lastref = basics.lastref; e.timestamp = basics.timestamp; e.expires = basics.expires; - e.lastmod = basics.lastmod; + e.lastModified(basics.lastmod); e.refcount = basics.refcount; e.flags = basics.flags; diff -u -r -N squid-4.0.14/src/fs/ufs/RebuildState.cc squid-4.0.15/src/fs/ufs/RebuildState.cc --- squid-4.0.14/src/fs/ufs/RebuildState.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/fs/ufs/RebuildState.cc 2016-10-10 08:05:51.000000000 +1300 @@ -91,9 +91,11 @@ Fs::Ufs::RebuildState::RebuildStep(void *data) { RebuildState *rb = (RebuildState *)data; - rb->rebuildStep(); + if (!reconfiguring) + rb->rebuildStep(); - if (!rb->isDone()) + // delay storeRebuildComplete() when reconfiguring to protect storeCleanup() + if (!rb->isDone() || reconfiguring) eventAdd("storeRebuild", RebuildStep, rb, 0.01, 1); else { -- StoreController::store_dirs_rebuilding; @@ -217,7 +219,7 @@ tmpe.expires, tmpe.timestamp, tmpe.lastref, - tmpe.lastmod, + tmpe.lastModified(), tmpe.refcount, /* refcount */ tmpe.flags, /* flags */ (int) flags.clean)); @@ -344,7 +346,7 @@ currentEntry()->lastref = swapData.timestamp; currentEntry()->timestamp = swapData.timestamp; currentEntry()->expires = swapData.expires; - currentEntry()->lastmod = swapData.lastmod; + currentEntry()->lastModified(swapData.lastmod); currentEntry()->flags = swapData.flags; currentEntry()->refcount += swapData.refcount; sd->dereference(*currentEntry()); diff -u -r -N squid-4.0.14/src/fs/ufs/UFSStoreState.cc squid-4.0.15/src/fs/ufs/UFSStoreState.cc --- squid-4.0.14/src/fs/ufs/UFSStoreState.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/fs/ufs/UFSStoreState.cc 2016-10-10 08:05:51.000000000 +1300 @@ -405,7 +405,7 @@ if (flags.write_draining) return; - if (!theFile->canWrite()) + if (!theFile || !theFile->canWrite()) return; flags.write_draining = true; diff -u -r -N squid-4.0.14/src/fs/ufs/UFSStoreState.h squid-4.0.15/src/fs/ufs/UFSStoreState.h --- squid-4.0.14/src/fs/ufs/UFSStoreState.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/fs/ufs/UFSStoreState.h 2016-10-10 08:05:51.000000000 +1300 @@ -59,6 +59,8 @@ ~_queued_read() { cbdataReferenceDone(callback_data); } + _queued_read(const _queued_read &qr) = delete; + _queued_read &operator =(const _queued_read &qr) = delete; char *buf; size_t size; @@ -88,6 +90,8 @@ if (free_func && buf) free_func(const_cast(buf)); } + _queued_write(const _queued_write &qr) = delete; + _queued_write &operator =(const _queued_write &qr) = delete; char const *buf; size_t size; diff -u -r -N squid-4.0.14/src/fs/ufs/UFSSwapDir.cc squid-4.0.15/src/fs/ufs/UFSSwapDir.cc --- squid-4.0.14/src/fs/ufs/UFSSwapDir.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/fs/ufs/UFSSwapDir.cc 2016-10-10 08:05:51.000000000 +1300 @@ -88,7 +88,7 @@ s.timestamp = e.timestamp; s.lastref = e.lastref; s.expires = e.expires; - s.lastmod = e.lastmod; + s.lastmod = e.lastModified(); s.swap_file_sz = e.swap_file_sz; s.refcount = e.refcount; s.flags = e.flags; @@ -317,7 +317,8 @@ currentIOOptions(new ConfigOptionVector()), ioType(xstrdup(anIOType)), cur_size(0), - n_disk_objects(0) + n_disk_objects(0), + rebuilding_(false) { /* modulename is only set to disk modules that are built, by configure, * so the Find call should never return NULL here. @@ -725,6 +726,15 @@ void Fs::Ufs::UFSSwapDir::openLog() { + assert(NumberOfUFSDirs || !UFSDirToGlobalDirMapping); + ++NumberOfUFSDirs; + assert(NumberOfUFSDirs <= Config.cacheSwap.n_configured); + + if (rebuilding_) { // we did not close the temporary log used for rebuilding + assert(swaplog_fd >= 0); + return; + } + char *logPath; logPath = logFile(); swaplog_fd = file_open(logPath, O_WRONLY | O_CREAT | O_BINARY); @@ -736,13 +746,6 @@ } debugs(50, 3, HERE << "Cache Dir #" << index << " log opened on FD " << swaplog_fd); - - if (0 == NumberOfUFSDirs) - assert(NULL == UFSDirToGlobalDirMapping); - - ++NumberOfUFSDirs; - - assert(NumberOfUFSDirs <= Config.cacheSwap.n_configured); } void @@ -751,18 +754,19 @@ if (swaplog_fd < 0) /* not open */ return; + --NumberOfUFSDirs; + assert(NumberOfUFSDirs >= 0); + if (!NumberOfUFSDirs) + safe_free(UFSDirToGlobalDirMapping); + + if (rebuilding_) // we cannot close the temporary log used for rebuilding + return; + file_close(swaplog_fd); debugs(47, 3, "Cache Dir #" << index << " log closed on FD " << swaplog_fd); swaplog_fd = -1; - - --NumberOfUFSDirs; - - assert(NumberOfUFSDirs >= 0); - - if (0 == NumberOfUFSDirs) - safe_free(UFSDirToGlobalDirMapping); } bool @@ -804,7 +808,7 @@ e->lastref = lastref; e->timestamp = timestamp; e->expires = expires; - e->lastmod = lastmod; + e->lastModified(lastmod); e->refcount = refcount; e->flags = newFlags; EBIT_CLR(e->flags, RELEASE_REQUEST); @@ -842,6 +846,9 @@ void Fs::Ufs::UFSSwapDir::closeTmpSwapLog() { + assert(rebuilding_); + rebuilding_ = false; + char *swaplog_path = xstrdup(logFile(NULL)); // where the swaplog should be char *tmp_path = xstrdup(logFile(".new")); // the temporary file we have generated int fd; @@ -868,6 +875,8 @@ FILE * Fs::Ufs::UFSSwapDir::openTmpSwapLog(int *clean_flag, int *zero_flag) { + assert(!rebuilding_); + char *swaplog_path = xstrdup(logFile(NULL)); char *clean_path = xstrdup(logFile(".last-clean")); char *new_path = xstrdup(logFile(".new")); @@ -902,6 +911,7 @@ } swaplog_fd = fd; + rebuilding_ = true; { const StoreSwapLogHeader header; @@ -1060,18 +1070,17 @@ cleanLog = NULL; } -void -Fs::Ufs::UFSSwapDir::CleanEvent(void *) +/// safely cleans a few unused files if possible +int +Fs::Ufs::UFSSwapDir::HandleCleanEvent() { static int swap_index = 0; int i; int j = 0; int n = 0; - /* - * Assert that there are UFS cache_dirs configured, otherwise - * we should never be called. - */ - assert(NumberOfUFSDirs); + + if (!NumberOfUFSDirs) + return 0; // probably in the middle of reconfiguration if (NULL == UFSDirToGlobalDirMapping) { SwapDir *sd; @@ -1115,6 +1124,13 @@ ++swap_index; } + return n; +} + +void +Fs::Ufs::UFSSwapDir::CleanEvent(void *) +{ + const int n = HandleCleanEvent(); eventAdd("storeDirClean", CleanEvent, NULL, 15.0 * exp(-0.25 * n), 1); } @@ -1284,13 +1300,18 @@ void Fs::Ufs::UFSSwapDir::logEntry(const StoreEntry & e, int op) const { + if (swaplog_fd < 0) { + debugs(36, 5, "cannot log " << e << " in the middle of reconfiguration"); + return; + } + StoreSwapLogData *s = new StoreSwapLogData; s->op = (char) op; s->swap_filen = e.swap_filen; s->timestamp = e.timestamp; s->lastref = e.lastref; s->expires = e.expires; - s->lastmod = e.lastmod; + s->lastmod = e.lastModified(); s->swap_file_sz = e.swap_file_sz; s->refcount = e.refcount; s->flags = e.flags; diff -u -r -N squid-4.0.14/src/fs/ufs/UFSSwapDir.h squid-4.0.15/src/fs/ufs/UFSSwapDir.h --- squid-4.0.14/src/fs/ufs/UFSSwapDir.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/fs/ufs/UFSSwapDir.h 2016-10-10 08:05:51.000000000 +1300 @@ -126,6 +126,7 @@ bool pathIsDirectory(const char *path)const; int swaplog_fd; static EVH CleanEvent; + static int HandleCleanEvent(); /** Verify that the the CacheDir exists * * If this returns < 0, then Squid exits, complains about swap @@ -145,6 +146,7 @@ char const *ioType; uint64_t cur_size; ///< currently used space in the storage area uint64_t n_disk_objects; ///< total number of objects stored + bool rebuilding_; ///< whether RebuildState is writing the new swap.state }; } //namespace Ufs diff -u -r -N squid-4.0.14/src/htcp.cc squid-4.0.15/src/htcp.cc --- squid-4.0.14/src/htcp.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/htcp.cc 2016-10-10 08:05:51.000000000 +1300 @@ -848,8 +848,8 @@ if (e && e->expires > -1) hdr.putTime(Http::HdrType::EXPIRES, e->expires); - if (e && e->lastmod > -1) - hdr.putTime(Http::HdrType::LAST_MODIFIED, e->lastmod); + if (e && e->lastModified() > -1) + hdr.putTime(Http::HdrType::LAST_MODIFIED, e->lastModified()); hdr.packInto(&mb); diff -u -r -N squid-4.0.14/src/http/one/RequestParser.cc squid-4.0.15/src/http/one/RequestParser.cc --- squid-4.0.14/src/http/one/RequestParser.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/http/one/RequestParser.cc 2016-10-10 08:05:51.000000000 +1300 @@ -185,14 +185,36 @@ bool Http::One::RequestParser::parseHttpVersionField(Http1::Tokenizer &tok) { + static const SBuf http1p0("HTTP/1.0"); + static const SBuf http1p1("HTTP/1.1"); const auto savedTok = tok; - SBuf digit; - // Searching for Http1magic precludes detecting HTTP/2+ versions. - // Rewrite if we ever _need_ to return 505 (Version Not Supported) errors. - if (tok.suffix(digit, CharacterSet::DIGIT) && tok.skipSuffix(Http1magic)) { - msgProtocol_ = Http::ProtocolVersion(1, (*digit.rawContent() - '0')); + // Optimization: Expect (and quickly parse) HTTP/1.1 or HTTP/1.0 in + // the vast majority of cases. + if (tok.skipSuffix(http1p1)) { + msgProtocol_ = Http::ProtocolVersion(1, 1); return true; + } else if (tok.skipSuffix(http1p0)) { + msgProtocol_ = Http::ProtocolVersion(1, 0); + return true; + } else { + // RFC 7230 section 2.6: + // HTTP-version = HTTP-name "/" DIGIT "." DIGIT + static const CharacterSet period("Decimal point", "."); + static const SBuf proto("HTTP/"); + SBuf majorDigit; + SBuf minorDigit; + if (tok.suffix(minorDigit, CharacterSet::DIGIT) && + tok.skipOneTrailing(period) && + tok.suffix(majorDigit, CharacterSet::DIGIT) && + tok.skipSuffix(proto)) { + const bool multiDigits = majorDigit.length() > 1 || minorDigit.length() > 1; + // use '0.0' for unsupported multiple digit version numbers + const unsigned int major = multiDigits ? 0 : (*majorDigit.rawContent() - '0'); + const unsigned int minor = multiDigits ? 0 : (*minorDigit.rawContent() - '0'); + msgProtocol_ = Http::ProtocolVersion(major, minor); + return true; + } } // A GET request might use HTTP/0.9 syntax diff -u -r -N squid-4.0.14/src/http/Stream.cc squid-4.0.15/src/http/Stream.cc --- squid-4.0.14/src/http/Stream.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/http/Stream.cc 2016-10-10 08:05:51.000000000 +1300 @@ -382,7 +382,7 @@ /* got modification time? */ if (spec.time >= 0) - return http->storeEntry()->lastmod <= spec.time; + return !http->storeEntry()->modifiedSince(spec.time); assert(0); /* should not happen */ return false; diff -u -r -N squid-4.0.14/src/http/url_rewriters/LFS/url_lfs_rewrite.8 squid-4.0.15/src/http/url_rewriters/LFS/url_lfs_rewrite.8 --- squid-4.0.14/src/http/url_rewriters/LFS/url_lfs_rewrite.8 2016-09-09 03:32:18.000000000 +1200 +++ squid-4.0.15/src/http/url_rewriters/LFS/url_lfs_rewrite.8 2016-10-10 12:00:01.000000000 +1300 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) +.\" Automatically generated by Pod::Man 4.08 (Pod::Simple 3.32) .\" .\" Standard preamble: .\" ======================================================================== @@ -46,7 +46,7 @@ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" -.\" If the F register is turned on, we'll generate index entries on stderr for +.\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. @@ -54,20 +54,16 @@ .\" Avoid warning from groff about undefined register 'F'. .de IX .. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" +.if !\nF .nr F 0 +.if \nF>0 \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" .. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 . \} .\} -.rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. @@ -133,7 +129,7 @@ .\" ======================================================================== .\" .IX Title "URL_LFS_REWRITE 8" -.TH URL_LFS_REWRITE 8 "2016-09-08" "perl v5.22.2" "User Contributed Perl Documentation" +.TH URL_LFS_REWRITE 8 "2016-10-09" "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 @@ -238,7 +234,7 @@ Report ideas for new improvements to the \fISquid Developers mailing list .SH "SEE ALSO" .IX Header "SEE ALSO" -squid (8), \s-1GPL \\fIs0\fR\|(7), +squid (8), \s-1GPL\s0 (7), .PP The Squid \s-1FAQ\s0 wiki http://wiki.squid\-cache.org/SquidFaq .PP diff -u -r -N squid-4.0.14/src/http.cc squid-4.0.15/src/http.cc --- squid-4.0.14/src/http.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/http.cc 2016-10-10 08:05:51.000000000 +1300 @@ -90,7 +90,8 @@ lastChunk(0), httpChunkDecoder(NULL), payloadSeen(0), - payloadTruncated(0) + payloadTruncated(0), + sawDateGoBack(false) { debugs(11,5,HERE << "HttpStateData " << this << " created"); ignoreCacheControl = false; @@ -168,6 +169,14 @@ mustStop("HttpStateData::httpTimeout"); } +static StoreEntry * +findPreviouslyCachedEntry(StoreEntry *newEntry) { + assert(newEntry->mem_obj); + return newEntry->mem_obj->request ? + storeGetPublicByRequest(newEntry->mem_obj->request) : + storeGetPublic(newEntry->mem_obj->storeId(), newEntry->mem_obj->method); +} + /// Remove an existing public store entry if the incoming response (to be /// stored in a currently private entry) is going to invalidate it. static void @@ -175,7 +184,6 @@ { int remove = 0; int forbidden = 0; - StoreEntry *pe; // If the incoming response already goes into a public entry, then there is // nothing to remove. This protects ready-for-collapsing entries as well. @@ -234,12 +242,7 @@ if (!remove && !forbidden) return; - assert(e->mem_obj); - - if (e->mem_obj->request) - pe = storeGetPublicByRequest(e->mem_obj->request); - else - pe = storeGetPublic(e->mem_obj->storeId(), e->mem_obj->method); + StoreEntry *pe = findPreviouslyCachedEntry(e); if (pe != NULL) { assert(e != pe); @@ -330,6 +333,13 @@ return 0; } + // RFC 7234 section 4: a cache MUST use the most recent response + // (as determined by the Date header field) + if (sawDateGoBack) { + debugs(22, 3, "NO because " << *entry << " has an older date header."); + return 0; + } + // Check for Surrogate/1.0 protocol conditions // NP: reverse-proxy traffic our parent server has instructed us never to cache if (surrogateNoStore) { @@ -916,7 +926,10 @@ /* Check if object is cacheable or not based on reply code */ debugs(11, 3, "HTTP CODE: " << rep->sline.status()); - if (neighbors_do_private_keys) + if (const StoreEntry *oldEntry = findPreviouslyCachedEntry(entry)) + sawDateGoBack = rep->olderThan(oldEntry->getReply()); + + if (neighbors_do_private_keys && !sawDateGoBack) httpMaybeRemovePublic(entry, rep->sline.status()); bool varyFailure = false; diff -u -r -N squid-4.0.14/src/http.h squid-4.0.15/src/http.h --- squid-4.0.14/src/http.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/http.h 2016-10-10 08:05:51.000000000 +1300 @@ -129,6 +129,10 @@ int64_t payloadSeen; /// positive when we read more than we wanted int64_t payloadTruncated; + + /// Whether we received a Date header older than that of a matching + /// cached response. + bool sawDateGoBack; }; int httpCachable(const HttpRequestMethod&); diff -u -r -N squid-4.0.14/src/HttpHdrCc.cc squid-4.0.15/src/HttpHdrCc.cc --- squid-4.0.14/src/HttpHdrCc.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/HttpHdrCc.cc 2016-10-10 08:05:51.000000000 +1300 @@ -306,7 +306,7 @@ { extern const HttpHeaderStat *dump_stat; /* argh! */ const int id = static_cast(val); - const bool valid_id = id < HttpHdrCcType::CC_ENUM_END; + const bool valid_id = id >= 0 && id < static_cast(HttpHdrCcType::CC_ENUM_END); const char *name = valid_id ? CcAttrs[id].name : "INVALID"; if (count || valid_id) diff -u -r -N squid-4.0.14/src/HttpHdrCc.cci squid-4.0.15/src/HttpHdrCc.cci --- squid-4.0.14/src/HttpHdrCc.cci 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/HttpHdrCc.cci 2016-10-10 08:05:51.000000000 +1300 @@ -15,16 +15,16 @@ HttpHdrCc::isSet(HttpHdrCcType id) const { assert(id < HttpHdrCcType::CC_ENUM_END); - return EBIT_TEST(mask,id); + return EBIT_TEST(mask, static_cast(id)); } void HttpHdrCc::setMask(HttpHdrCcType id, bool newval) { if (newval) - EBIT_SET(mask,id); + EBIT_SET(mask,static_cast(id)); else - EBIT_CLR(mask,id); + EBIT_CLR(mask, static_cast(id)); } /// set a data member to a new value, and set the corresponding mask-bit. diff -u -r -N squid-4.0.14/src/HttpHeader.cc squid-4.0.15/src/HttpHeader.cc --- squid-4.0.14/src/HttpHeader.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/HttpHeader.cc 2016-10-10 08:05:51.000000000 +1300 @@ -882,7 +882,7 @@ /* Sorry, an unknown header name. Do linear search */ bool found = false; while ((e = getEntry(&pos))) { - if (e->id == Http::HdrType::OTHER && e->name.caseCmp(name) == 0) { + 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(), ','); } diff -u -r -N squid-4.0.14/src/HttpMsg.cc squid-4.0.15/src/HttpMsg.cc --- squid-4.0.14/src/HttpMsg.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/HttpMsg.cc 2016-10-10 08:05:51.000000000 +1300 @@ -314,6 +314,8 @@ return false; } + // XXX: we are just parsing HTTP headers, not the whole message prefix here + hdr_sz = hp.messageHeaderSize(); pstate = psParsed; hdrCacheInit(); return true; diff -u -r -N squid-4.0.14/src/HttpReply.cc squid-4.0.15/src/HttpReply.cc --- squid-4.0.14/src/HttpReply.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/HttpReply.cc 2016-10-10 08:05:51.000000000 +1300 @@ -627,3 +627,11 @@ return newValue; } +bool +HttpReply::olderThan(const HttpReply *them) const +{ + if (!them || !them->date || !date) + return false; + return date < them->date; +} + diff -u -r -N squid-4.0.14/src/HttpReply.h squid-4.0.15/src/HttpReply.h --- squid-4.0.14/src/HttpReply.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/HttpReply.h 2016-10-10 08:05:51.000000000 +1300 @@ -112,6 +112,10 @@ virtual void hdrCacheInit(); + /// whether our Date header value is smaller than theirs + /// \returns false if any information is missing + bool olderThan(const HttpReply *them) const; + private: /** initialize */ void init(); diff -u -r -N squid-4.0.14/src/icmp/Makefile.am squid-4.0.15/src/icmp/Makefile.am --- squid-4.0.14/src/icmp/Makefile.am 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/icmp/Makefile.am 2016-10-10 08:05:51.000000000 +1300 @@ -67,6 +67,7 @@ $(top_builddir)/src/ip/libip.la \ $(top_builddir)/src/base/libbase.la \ $(COMPAT_LIB) \ + $(SSLLIB) \ $(XTRA_LIBS) CLEANFILES += $(COPIED_SOURCE) diff -u -r -N squid-4.0.14/src/icmp/Makefile.in squid-4.0.15/src/icmp/Makefile.in --- squid-4.0.14/src/icmp/Makefile.in 2016-09-09 02:14:53.000000000 +1200 +++ squid-4.0.15/src/icmp/Makefile.in 2016-10-10 08:17:03.000000000 +1300 @@ -191,7 +191,7 @@ am__DEPENDENCIES_3 = pinger_DEPENDENCIES = libicmpcore.la $(top_builddir)/src/ip/libip.la \ $(top_builddir)/src/base/libbase.la $(am__DEPENDENCIES_2) \ - $(am__DEPENDENCIES_3) + $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_3) pinger_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(pinger_LDFLAGS) $(LDFLAGS) -o $@ @@ -792,6 +792,7 @@ $(top_builddir)/src/ip/libip.la \ $(top_builddir)/src/base/libbase.la \ $(COMPAT_LIB) \ + $(SSLLIB) \ $(XTRA_LIBS) all: all-am diff -u -r -N squid-4.0.14/src/ip/Intercept.cc squid-4.0.15/src/ip/Intercept.cc --- squid-4.0.14/src/ip/Intercept.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/ip/Intercept.cc 2016-10-10 08:05:51.000000000 +1300 @@ -208,16 +208,22 @@ debugs(89, warningLevel, "IPF (IPFilter v4) NAT does not support IPv6. Please upgrade to IPFilter v5.1"); warningLevel = (warningLevel + 1) % 10; return false; + } + newConn->local.getInAddr(natLookup.nl_inip); + newConn->remote.getInAddr(natLookup.nl_outip); #else natLookup.nl_v = 6; - } else { + newConn->local.getInAddr(natLookup.nl_inipaddr.in6); + newConn->remote.getInAddr(natLookup.nl_outipaddr.in6); + } + else { natLookup.nl_v = 4; -#endif + newConn->local.getInAddr(natLookup.nl_inipaddr.in4); + newConn->remote.getInAddr(natLookup.nl_outipaddr.in4); } +#endif natLookup.nl_inport = htons(newConn->local.port()); - newConn->local.getInAddr(natLookup.nl_inip); natLookup.nl_outport = htons(newConn->remote.port()); - newConn->remote.getInAddr(natLookup.nl_outip); // ... and the TCP flag natLookup.nl_flags = IPN_TCP; @@ -284,7 +290,14 @@ debugs(89, 9, HERE << "address: " << newConn); return false; } else { +#if IPFILTER_VERSION < 5000003 newConn->local = natLookup.nl_realip; +#else + if (newConn->remote.isIPv6()) + newConn->local = natLookup.nl_realipaddr.in6; + else + newConn->local = natLookup.nl_realipaddr.in4; +#endif newConn->local.port(ntohs(natLookup.nl_realport)); debugs(89, 5, HERE << "address NAT: " << newConn); return true; diff -u -r -N squid-4.0.14/src/ipc/StoreMap.cc squid-4.0.15/src/ipc/StoreMap.cc --- squid-4.0.14/src/ipc/StoreMap.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/ipc/StoreMap.cc 2016-10-10 08:05:51.000000000 +1300 @@ -751,7 +751,7 @@ basics.timestamp = from.timestamp; basics.lastref = from.lastref; basics.expires = from.expires; - basics.lastmod = from.lastmod; + basics.lastmod = from.lastModified(); basics.swap_file_sz = from.swap_file_sz; basics.refcount = from.refcount; basics.flags = from.flags; diff -u -r -N squid-4.0.14/src/log/DB/log_db_daemon.8 squid-4.0.15/src/log/DB/log_db_daemon.8 --- squid-4.0.14/src/log/DB/log_db_daemon.8 2016-09-09 03:32:27.000000000 +1200 +++ squid-4.0.15/src/log/DB/log_db_daemon.8 2016-10-10 12:00:28.000000000 +1300 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) +.\" Automatically generated by Pod::Man 4.08 (Pod::Simple 3.32) .\" .\" Standard preamble: .\" ======================================================================== @@ -46,7 +46,7 @@ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" -.\" If the F register is turned on, we'll generate index entries on stderr for +.\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. @@ -54,20 +54,16 @@ .\" Avoid warning from groff about undefined register 'F'. .de IX .. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" +.if !\nF .nr F 0 +.if \nF>0 \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" .. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 . \} .\} -.rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. @@ -133,7 +129,7 @@ .\" ======================================================================== .\" .IX Title "LOG_DB_DAEMON 8" -.TH LOG_DB_DAEMON 8 "2016-09-08" "perl v5.22.2" "User Contributed Perl Documentation" +.TH LOG_DB_DAEMON 8 "2016-10-09" "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.14/src/LogTags.cc squid-4.0.15/src/LogTags.cc --- squid-4.0.14/src/LogTags.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/LogTags.cc 2016-10-10 08:05:51.000000000 +1300 @@ -55,6 +55,9 @@ else pos += snprintf(buf, sizeof(buf), "NONE"); + if (err.ignored) + pos += snprintf(buf+pos,sizeof(buf)-pos, "_IGNORED"); + // error tags if (err.timedout) pos += snprintf(buf+pos,sizeof(buf)-pos, "_TIMEDOUT"); diff -u -r -N squid-4.0.14/src/LogTags.h squid-4.0.15/src/LogTags.h --- squid-4.0.14/src/LogTags.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/LogTags.h 2016-10-10 08:05:51.000000000 +1300 @@ -49,6 +49,8 @@ { public: LogTags(LogTags_ot t) : oldType(t) {assert(oldType < LOG_TYPE_MAX);} + // XXX: this operator does not reset flags + // TODO: either replace with a category-only setter or remove LogTags &operator =(const LogTags_ot &t) {assert(t < LOG_TYPE_MAX); oldType = t; return *this;} /// compute the status access.log field @@ -57,12 +59,16 @@ /// determine if the log tag code indicates a cache HIT bool isTcpHit() const; - /// error states terminating the transaction - struct Errors { - Errors() : timedout(false), aborted(false) {} + /// Things that may happen to a transaction while it is being + /// processed according to its LOG_* category. Logged as _SUFFIX(es). + /// Unlike LOG_* categories, these flags may not be mutually exclusive. + class Errors { + public: + Errors() : ignored(false), timedout(false), aborted(false) {} - bool timedout; ///< tag: TIMEDOUT - terminated due to a lifetime or I/O timeout - bool aborted; ///< tag: ABORTED - other abnormal termination (e.g., I/O error) + bool ignored; ///< _IGNORED: the response was not used for anything + bool timedout; ///< _TIMEDOUT: terminated due to a lifetime or I/O timeout + bool aborted; ///< _ABORTED: other abnormal termination (e.g., I/O error) } err; private: diff -u -r -N squid-4.0.14/src/main.cc squid-4.0.15/src/main.cc --- squid-4.0.14/src/main.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/main.cc 2016-10-10 08:05:51.000000000 +1300 @@ -851,13 +851,14 @@ debugs(1, DBG_IMPORTANT, "Reconfiguring Squid Cache (version " << version_string << ")..."); reconfiguring = 1; + RunRegisteredHere(RegisteredRunner::startReconfigure); + // Initiate asynchronous closing sequence serverConnectionsClose(); icpClosePorts(); #if USE_HTCP htcpClosePorts(); #endif - Dns::Shutdown(); #if USE_SSL_CRTD Ssl::Helper::GetInstance()->Shutdown(); #endif @@ -2006,7 +2007,6 @@ #endif debugs(1, DBG_IMPORTANT, "Shutting down..."); - Dns::Shutdown(); #if USE_SSL_CRTD Ssl::Helper::GetInstance()->Shutdown(); #endif diff -u -r -N squid-4.0.14/src/Makefile.am squid-4.0.15/src/Makefile.am --- squid-4.0.14/src/Makefile.am 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/Makefile.am 2016-10-10 08:05:51.000000000 +1300 @@ -547,11 +547,11 @@ fs/libfs.la \ DiskIO/libdiskio.la \ comm/libcomm.la \ + anyp/libanyp.la \ security/libsecurity.la \ $(SSL_LIBS) \ ipc/libipc.la \ mgr/libmgr.la \ - anyp/libanyp.la \ parser/libparser.la \ eui/libeui.la \ icmp/libicmp.la \ diff -u -r -N squid-4.0.14/src/Makefile.in squid-4.0.15/src/Makefile.in --- squid-4.0.14/src/Makefile.in 2016-09-09 02:14:18.000000000 +1200 +++ squid-4.0.15/src/Makefile.in 2016-10-10 08:11:22.000000000 +1300 @@ -416,11 +416,11 @@ clients/libclients.la servers/libservers.la ftp/libftp.la \ helper/libhelper.la http/libhttp.la dns/libdns.la \ base/libbase.la libsquid.la ip/libip.la fs/libfs.la \ - DiskIO/libdiskio.la comm/libcomm.la security/libsecurity.la \ - $(SSL_LIBS) ipc/libipc.la mgr/libmgr.la anyp/libanyp.la \ - parser/libparser.la eui/libeui.la icmp/libicmp.la \ - log/liblog.la format/libformat.la sbuf/libsbuf.la \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + DiskIO/libdiskio.la comm/libcomm.la anyp/libanyp.la \ + security/libsecurity.la $(SSL_LIBS) ipc/libipc.la \ + mgr/libmgr.la parser/libparser.la eui/libeui.la \ + icmp/libicmp.la log/liblog.la format/libformat.la \ + sbuf/libsbuf.la $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_4) $(am__DEPENDENCIES_5) mem/libmem.la \ @@ -2947,13 +2947,14 @@ clients/libclients.la servers/libservers.la ftp/libftp.la \ helper/libhelper.la http/libhttp.la dns/libdns.la \ base/libbase.la libsquid.la ip/libip.la fs/libfs.la \ - DiskIO/libdiskio.la comm/libcomm.la security/libsecurity.la \ - $(SSL_LIBS) ipc/libipc.la mgr/libmgr.la anyp/libanyp.la \ - parser/libparser.la eui/libeui.la icmp/libicmp.la \ - log/liblog.la format/libformat.la sbuf/libsbuf.la $(XTRA_OBJS) \ - $(REPL_OBJS) $(NETTLELIB) $(CRYPTLIB) $(REGEXLIB) \ - $(ADAPTATION_LIBS) $(ESI_LIBS) $(SNMP_LIBS) mem/libmem.la \ - store/libstore.la $(top_builddir)/lib/libmisccontainers.la \ + DiskIO/libdiskio.la comm/libcomm.la anyp/libanyp.la \ + security/libsecurity.la $(SSL_LIBS) ipc/libipc.la \ + mgr/libmgr.la parser/libparser.la eui/libeui.la \ + icmp/libicmp.la log/liblog.la format/libformat.la \ + sbuf/libsbuf.la $(XTRA_OBJS) $(REPL_OBJS) $(NETTLELIB) \ + $(CRYPTLIB) $(REGEXLIB) $(ADAPTATION_LIBS) $(ESI_LIBS) \ + $(SNMP_LIBS) mem/libmem.la store/libstore.la \ + $(top_builddir)/lib/libmisccontainers.la \ $(top_builddir)/lib/libmiscencoding.la \ $(top_builddir)/lib/libmiscutil.la $(ATOMICLIB) $(SSLLIB) \ $(EPOLL_LIBS) $(MINGW_LIBS) $(KRB5LIBS) $(COMPAT_LIB) \ diff -u -r -N squid-4.0.14/src/MemStore.cc squid-4.0.15/src/MemStore.cc --- squid-4.0.14/src/MemStore.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/MemStore.cc 2016-10-10 08:05:51.000000000 +1300 @@ -456,7 +456,7 @@ e.lastref = basics.lastref; e.timestamp = basics.timestamp; e.expires = basics.expires; - e.lastmod = basics.lastmod; + e.lastModified(basics.lastmod); e.refcount = basics.refcount; e.flags = basics.flags; diff -u -r -N squid-4.0.14/src/pconn.cc squid-4.0.15/src/pconn.cc --- squid-4.0.14/src/pconn.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/pconn.cc 2016-10-10 08:05:51.000000000 +1300 @@ -42,7 +42,7 @@ theList_ = new Comm::ConnectionPointer[capacity_]; - RegisterRunner(this); + registerRunner(); // TODO: re-attach to MemPools. WAS: theList = (?? *)pconn_fds_pool->alloc(); } diff -u -r -N squid-4.0.14/src/peer_digest.cc squid-4.0.15/src/peer_digest.cc --- squid-4.0.14/src/peer_digest.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/peer_digest.cc 2016-10-10 08:05:51.000000000 +1300 @@ -370,7 +370,7 @@ /* set lastmod to trigger IMS request if possible */ if (old_e) - e->lastmod = old_e->lastmod; + e->lastModified(old_e->lastModified()); /* push towards peer cache */ debugs(72, 3, "peerDigestRequest: forwarding to fwdStart..."); @@ -918,8 +918,8 @@ debugs(72, 3, "peerDigestFetchFinish: expires: " << (long int) fetch->expires << " (" << std::showpos << (int) (fetch->expires - squid_curtime) << "), lmt: " << - std::noshowpos << (long int) fetch->entry->lastmod << " (" << - std::showpos << (int) (fetch->entry->lastmod - squid_curtime) << + std::noshowpos << (long int) fetch->entry->lastModified() << " (" << + std::showpos << (int) (fetch->entry->lastModified() - squid_curtime) << ")"); } diff -u -r -N squid-4.0.14/src/redirect.cc squid-4.0.15/src/redirect.cc --- squid-4.0.14/src/redirect.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/redirect.cc 2016-10-10 08:05:51.000000000 +1300 @@ -395,11 +395,13 @@ } if (Config.redirector_extras) { + delete redirectorExtrasFmt; redirectorExtrasFmt = new ::Format::Format("url_rewrite_extras"); (void)redirectorExtrasFmt->parse(Config.redirector_extras); } if (Config.storeId_extras) { + delete storeIdExtrasFmt; storeIdExtrasFmt = new ::Format::Format("store_id_extras"); (void)storeIdExtrasFmt->parse(Config.storeId_extras); } @@ -414,9 +416,6 @@ * When and if needed for more helpers a separated shutdown * method will be added for each of them. */ - if (!storeIds && !redirectors) - return; - if (redirectors) helperShutdown(redirectors); diff -u -r -N squid-4.0.14/src/refresh.cc squid-4.0.15/src/refresh.cc --- squid-4.0.14/src/refresh.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/refresh.cc 2016-10-10 08:05:51.000000000 +1300 @@ -174,13 +174,8 @@ } // 3. If there is a Last-Modified header, try the last-modified factor algorithm. - if (entry->lastmod > -1 && entry->timestamp > entry->lastmod) { - - /* lastmod_delta is the difference between the last-modified date of the response - * and the time we cached it. It's how "old" the response was when we got it. - */ - time_t lastmod_delta = entry->timestamp - entry->lastmod; - + const time_t lastmod_delta = entry->timestamp - entry->lastModified(); + if (lastmod_delta > 0) { /* stale_age is the age of the response when it became/becomes stale according to * the last-modified factor algorithm. It's how long we can consider the response * fresh from the time we cached it. @@ -540,8 +535,8 @@ /* Does not need refresh. This is certainly cachable */ return true; - if (entry->lastmod < 0) - /* Last modified is needed to do a refresh */ + if (entry->lastModified() < 0) + /* We should know entry's modification time to do a refresh */ return false; if (entry->mem_obj == NULL) diff -u -r -N squid-4.0.14/src/sbuf/MemBlob.h squid-4.0.15/src/sbuf/MemBlob.h --- squid-4.0.14/src/sbuf/MemBlob.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/sbuf/MemBlob.h 2016-10-10 08:05:51.000000000 +1300 @@ -72,7 +72,7 @@ */ bool canAppend(const size_type off, const size_type n) const { // TODO: ignore offset (and adjust size) when the blob is not shared? - return isAppendOffset(off) && willFit(n); + return (isAppendOffset(off) && willFit(n)) || !n; } /** adjusts internal object state as if exactly n bytes were append()ed diff -u -r -N squid-4.0.14/src/sbuf/SBuf.cc squid-4.0.15/src/sbuf/SBuf.cc --- squid-4.0.14/src/sbuf/SBuf.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/sbuf/SBuf.cc 2016-10-10 08:05:51.000000000 +1300 @@ -827,27 +827,6 @@ return npos; } -/* - * TODO: borrow a sscanf implementation from Linux or similar? - * we'd really need a vsnscanf(3)... ? As an alternative, a - * light-regexp-like domain-specific syntax might be an idea. - */ -int -SBuf::scanf(const char *format, ...) -{ - // with the format or an arg might be a dangerous char* - // that gets invalidated by c_str() - const Locker blobKeeper(this, buf()); - - va_list arg; - int rv; - ++stats.scanf; - va_start(arg, format); - rv = vsscanf(c_str(), format, arg); - va_end(arg); - return rv; -} - void SBuf::toLower() { diff -u -r -N squid-4.0.14/src/sbuf/SBuf.h squid-4.0.15/src/sbuf/SBuf.h --- squid-4.0.14/src/sbuf/SBuf.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/sbuf/SBuf.h 2016-10-10 08:05:51.000000000 +1300 @@ -583,14 +583,6 @@ */ size_type findLastNotOf(const CharacterSet &set, size_type endPos = npos) const; - /** sscanf-alike - * - * sscanf re-implementation. Non-const, and not \0-clean. - * \return same as sscanf - * \see man sscanf(3) - */ - int scanf(const char *format, ...); - /// converts all characters to lower case; \see man tolower(3) void toLower(); diff -u -r -N squid-4.0.14/src/sbuf/Stats.cc squid-4.0.15/src/sbuf/Stats.cc --- squid-4.0.14/src/sbuf/Stats.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/sbuf/Stats.cc 2016-10-10 08:05:51.000000000 +1300 @@ -17,7 +17,7 @@ : alloc(0), allocCopy(0), allocFromCString(0), assignFast(0), clear(0), append(0), moves(0), toStream(0), setChar(0), getChar(0), compareSlow(0), compareFast(0), copyOut(0), - rawAccess(0), nulTerminate(0), chop(0), trim(0), find(0), scanf(0), + rawAccess(0), nulTerminate(0), chop(0), trim(0), find(0), caseChange(0), cowFast(0), cowSlow(0), live(0) {} @@ -42,7 +42,6 @@ chop += ss.chop; trim += ss.trim; find += ss.find; - scanf += ss.scanf; caseChange += ss.caseChange; cowFast += ss.cowFast; cowSlow += ss.cowSlow; @@ -75,7 +74,6 @@ "\nchop operations: " << chop << "\ntrim operations: " << trim << "\nfind: " << find << - "\nscanf: " << scanf << "\ncase-change ops: " << caseChange << "\nCOW not actually requiring a copy: " << cowFast << "\nCOW: " << cowSlow << diff -u -r -N squid-4.0.14/src/sbuf/Stats.h squid-4.0.15/src/sbuf/Stats.h --- squid-4.0.14/src/sbuf/Stats.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/sbuf/Stats.h 2016-10-10 08:05:51.000000000 +1300 @@ -39,7 +39,6 @@ uint64_t chop; ///getPeer()) { assert(peer->secure.encryptTransport); - Security::ContextPtr sslContext(peer->sslContext); - return sslContext; + return peer->sslContext; } return ::Config.ssl_client.sslContext; } diff -u -r -N squid-4.0.14/src/security/BlindPeerConnector.h squid-4.0.15/src/security/BlindPeerConnector.h --- squid-4.0.14/src/security/BlindPeerConnector.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/security/BlindPeerConnector.h 2016-10-10 08:05:51.000000000 +1300 @@ -39,8 +39,8 @@ /// \returns true on successful initialization virtual bool initialize(Security::SessionPointer &); - /// Return the configured Security::ContextPtr object - virtual Security::ContextPtr getSslContext(); + /// Return the configured TLS context object + virtual Security::ContextPointer getTlsContext(); /// On error calls peerConnectFailed(). /// On success store the used TLS session for later use. diff -u -r -N squid-4.0.14/src/security/CertError.h squid-4.0.15/src/security/CertError.h --- squid-4.0.14/src/security/CertError.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-4.0.15/src/security/CertError.h 2016-10-10 08:05:51.000000000 +1300 @@ -0,0 +1,51 @@ +/* + * Copyright (C) 1996-2016 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_SRC_SECURITY_CERTERROR_H +#define SQUID_SRC_SECURITY_CERTERROR_H + +#include "security/forward.h" + +namespace Security +{ + +/// An X.509 certificate-related error. +/// Pairs an error code with the certificate experiencing the error. +class CertError +{ +public: + CertError(int anErr, const Security::CertPointer &aCert, int aDepth = -1) : + code(anErr), cert(aCert), depth(aDepth) + {} + + bool operator == (const CertError &ce) const { + // We expect to be used in contexts where identical certificates have + // identical pointers. + return code == ce.code && depth == ce.depth && cert == ce.cert; + } + + bool operator != (const CertError &ce) const { + return !(*this == ce); + } + +public: + Security::ErrorCode code; ///< certificate error code + Security::CertPointer cert; ///< certificate with the above error code + + /** + * Absolute cert position in the final certificate chain that may include + * intermediate certificates. Chain positions start with zero and increase + * towards the root certificate. Negative if unknown. + */ + int depth; +}; + +} // namespace Security + +#endif /* SQUID_SRC_SECURITY_CERTERROR_H */ + diff -u -r -N squid-4.0.14/src/security/cert_validators/fake/security_fake_certverify.8 squid-4.0.15/src/security/cert_validators/fake/security_fake_certverify.8 --- squid-4.0.14/src/security/cert_validators/fake/security_fake_certverify.8 2016-09-09 03:32:45.000000000 +1200 +++ squid-4.0.15/src/security/cert_validators/fake/security_fake_certverify.8 2016-10-10 12:01:21.000000000 +1300 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) +.\" Automatically generated by Pod::Man 4.08 (Pod::Simple 3.32) .\" .\" Standard preamble: .\" ======================================================================== @@ -46,7 +46,7 @@ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" -.\" If the F register is turned on, we'll generate index entries on stderr for +.\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. @@ -54,20 +54,16 @@ .\" Avoid warning from groff about undefined register 'F'. .de IX .. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" +.if !\nF .nr F 0 +.if \nF>0 \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" .. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 . \} .\} -.rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. @@ -133,7 +129,7 @@ .\" ======================================================================== .\" .IX Title "SECURITY_FAKE_CERTVERIFY 8" -.TH SECURITY_FAKE_CERTVERIFY 8 "2016-09-08" "perl v5.22.2" "User Contributed Perl Documentation" +.TH SECURITY_FAKE_CERTVERIFY 8 "2016-10-09" "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.14/src/security/Context.h squid-4.0.15/src/security/Context.h --- squid-4.0.14/src/security/Context.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/security/Context.h 2016-10-10 08:05:51.000000000 +1300 @@ -24,27 +24,16 @@ namespace Security { -/* IMPORTANT: - * Due to circular dependency issues between ssl/libsslsquid.la and - * security/libsecurity.la the code within src/ssl/ is restricted to - * only using Security::ContextPtr, it MUST NOT use ContextPointer - * - * Code outside of src/ssl/ should always use Security::ContextPointer - * when storing a reference to a context. - */ #if USE_OPENSSL -typedef SSL_CTX* ContextPtr; CtoCpp1(SSL_CTX_free, SSL_CTX *); typedef LockingPointer ContextPointer; #elif USE_GNUTLS -typedef gnutls_certificate_credentials_t ContextPtr; CtoCpp1(gnutls_certificate_free_credentials, gnutls_certificate_credentials_t); typedef Security::LockingPointer ContextPointer; #else // use void* so we can check against nullptr -typedef void* ContextPtr; typedef Security::LockingPointer ContextPointer; #endif diff -u -r -N squid-4.0.14/src/security/forward.h squid-4.0.15/src/security/forward.h --- squid-4.0.14/src/security/forward.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/security/forward.h 2016-10-10 08:05:51.000000000 +1300 @@ -9,6 +9,7 @@ #ifndef SQUID_SRC_SECURITY_FORWARD_H #define SQUID_SRC_SECURITY_FORWARD_H +#include "base/CbDataList.h" #include "security/Context.h" #include "security/Session.h" @@ -18,6 +19,7 @@ #endif #endif #include +#include #if USE_OPENSSL // Macro to be used to define the C++ wrapper functor of the sk_*_pop_free @@ -42,6 +44,10 @@ namespace Security { +class CertError; +/// Holds a list of X.509 certificate errors +typedef CbDataList CertErrors; + #if USE_OPENSSL CtoCpp1(X509_free, X509 *) typedef Security::LockingPointer CertPointer; @@ -74,6 +80,14 @@ #endif class EncryptorAnswer; + +/// Squid defined error code (<0), an error code returned by X.509 API, or SSL_ERROR_NONE +typedef int ErrorCode; + +/// set of Squid defined TLS error codes +/// \note using std::unordered_set ensures values are unique, with fast lookup +typedef std::unordered_set Errors; + class KeyData; class PeerConnector; class PeerOptions; diff -u -r -N squid-4.0.14/src/security/Handshake.cc squid-4.0.15/src/security/Handshake.cc --- squid-4.0.14/src/security/Handshake.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/security/Handshake.cc 2016-10-10 08:05:51.000000000 +1300 @@ -542,9 +542,9 @@ auto x509Start = reinterpret_cast(raw.rawContent()); auto x509Pos = x509Start; X509 *x509 = d2i_X509(nullptr, &x509Pos, raw.length()); + pCert.resetWithoutLocking(x509); Must(x509); // successfully parsed Must(x509Pos == x509Start + raw.length()); // no leftovers - pCert.resetAndLock(x509); #endif } diff -u -r -N squid-4.0.14/src/security/LockingPointer.h squid-4.0.15/src/security/LockingPointer.h --- squid-4.0.14/src/security/LockingPointer.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/security/LockingPointer.h 2016-10-10 08:05:51.000000000 +1300 @@ -66,7 +66,7 @@ ~LockingPointer() { unlock(); } // copy semantics are okay only when adding a lock reference - explicit LockingPointer(const SelfType &o) : raw(nullptr) { + LockingPointer(const SelfType &o) : raw(nullptr) { resetAndLock(o.get()); } const SelfType &operator =(const SelfType &o) { @@ -85,6 +85,10 @@ bool operator !() const { return !raw; } explicit operator bool() const { return raw; } + bool operator ==(const SelfType &o) const { return (o.get() == raw); } + bool operator !=(const SelfType &o) const { return (o.get() != raw); } + + T *operator ->() const { return raw; } /// Returns raw and possibly nullptr pointer T *get() const { return raw; } diff -u -r -N squid-4.0.14/src/security/Makefile.am squid-4.0.15/src/security/Makefile.am --- squid-4.0.14/src/security/Makefile.am 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/security/Makefile.am 2016-10-10 08:05:51.000000000 +1300 @@ -15,6 +15,7 @@ libsecurity_la_SOURCES= \ BlindPeerConnector.cc \ BlindPeerConnector.h \ + CertError.h \ Context.h \ EncryptorAnswer.cc \ EncryptorAnswer.h \ diff -u -r -N squid-4.0.14/src/security/Makefile.in squid-4.0.15/src/security/Makefile.in --- squid-4.0.14/src/security/Makefile.in 2016-09-09 02:15:01.000000000 +1200 +++ squid-4.0.15/src/security/Makefile.in 2016-10-10 08:18:19.000000000 +1300 @@ -760,6 +760,7 @@ libsecurity_la_SOURCES = \ BlindPeerConnector.cc \ BlindPeerConnector.h \ + CertError.h \ Context.h \ EncryptorAnswer.cc \ EncryptorAnswer.h \ diff -u -r -N squid-4.0.14/src/security/NegotiationHistory.cc squid-4.0.15/src/security/NegotiationHistory.cc --- squid-4.0.14/src/security/NegotiationHistory.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/security/NegotiationHistory.cc 2016-10-10 08:05:51.000000000 +1300 @@ -65,18 +65,18 @@ #endif void -Security::NegotiationHistory::retrieveNegotiatedInfo(Security::SessionPtr ssl) +Security::NegotiationHistory::retrieveNegotiatedInfo(const Security::SessionPointer &session) { #if USE_OPENSSL - if ((cipher = SSL_get_current_cipher(ssl)) != NULL) { + if ((cipher = SSL_get_current_cipher(session.get()))) { // Set the negotiated version only if the cipher negotiated // else probably the negotiation is not completed and version // is not the final negotiated version - version_ = toProtocolVersion(ssl->version); + version_ = toProtocolVersion(session->version); } if (Debug::Enabled(83, 5)) { - BIO *b = SSL_get_rbio(ssl); + BIO *b = SSL_get_rbio(session.get()); Ssl::Bio *bio = static_cast(b->ptr); debugs(83, 5, "SSL connection info on FD " << bio->fd() << " SSL version " << version_ << diff -u -r -N squid-4.0.14/src/security/NegotiationHistory.h squid-4.0.15/src/security/NegotiationHistory.h --- squid-4.0.14/src/security/NegotiationHistory.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/security/NegotiationHistory.h 2016-10-10 08:05:51.000000000 +1300 @@ -21,7 +21,7 @@ NegotiationHistory(); /// Extract negotiation information from TLS object - void retrieveNegotiatedInfo(Security::SessionPtr); + void retrieveNegotiatedInfo(const Security::SessionPointer &); /// Extract information from parser stored in TlsDetails object void retrieveParsedInfo(Security::TlsDetails::Pointer const &details); diff -u -r -N squid-4.0.14/src/security/PeerConnector.cc squid-4.0.15/src/security/PeerConnector.cc --- squid-4.0.14/src/security/PeerConnector.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/security/PeerConnector.cc 2016-10-10 08:05:51.000000000 +1300 @@ -100,10 +100,10 @@ Security::PeerConnector::initialize(Security::SessionPointer &serverSession) { #if USE_OPENSSL - Security::ContextPtr sslContext(getSslContext()); - assert(sslContext); + Security::ContextPointer ctx(getTlsContext()); + assert(ctx); - if (!Ssl::CreateClient(sslContext, serverConnection(), "server https start")) { + if (!Ssl::CreateClient(ctx, serverConnection(), "server https start")) { ErrorState *anErr = new ErrorState(ERR_SOCKET_FAILURE, Http::scInternalServerError, request.getRaw()); anErr->xerrno = errno; debugs(83, DBG_IMPORTANT, "Error allocating TLS handle: " << ERR_error_string(ERR_get_error(), NULL)); @@ -151,14 +151,15 @@ void Security::PeerConnector::recordNegotiationDetails() { -#if USE_OPENSSL const int fd = serverConnection()->fd; - Security::SessionPtr ssl = fd_table[fd].ssl.get(); + Security::SessionPointer session(fd_table[fd].ssl); // retrieve TLS server negotiated information if any - serverConnection()->tlsNegotiations()->retrieveNegotiatedInfo(ssl); + serverConnection()->tlsNegotiations()->retrieveNegotiatedInfo(session); + +#if USE_OPENSSL // retrieve TLS parsed extra info - BIO *b = SSL_get_rbio(ssl); + BIO *b = SSL_get_rbio(session.get()); Ssl::ServerBio *bio = static_cast(b->ptr); if (const Security::TlsDetails::Pointer &details = bio->receivedHelloDetails()) serverConnection()->tlsNegotiations()->retrieveParsedInfo(details); @@ -199,20 +200,19 @@ #if USE_OPENSSL if (Ssl::TheConfig.ssl_crt_validator && useCertValidator_) { const int fd = serverConnection()->fd; - Security::SessionPtr ssl = fd_table[fd].ssl.get(); + Security::SessionPointer session(fd_table[fd].ssl); Ssl::CertValidationRequest validationRequest; // WARNING: Currently we do not use any locking for any of the // members of the Ssl::CertValidationRequest class. In this code the // Ssl::CertValidationRequest object used only to pass data to // Ssl::CertValidationHelper::submit method. - validationRequest.ssl = ssl; - validationRequest.domainName = request->url.host(); - if (Ssl::CertErrors *errs = static_cast(SSL_get_ex_data(ssl, ssl_ex_index_ssl_errors))) + validationRequest.ssl = session.get(); + SBuf *dName = (SBuf *)SSL_get_ex_data(session.get(), ssl_ex_index_server); + validationRequest.domainName = dName->c_str(); + if (Security::CertErrors *errs = static_cast(SSL_get_ex_data(session.get(), ssl_ex_index_ssl_errors))) // validationRequest disappears on return so no need to cbdataReference validationRequest.errors = errs; - else - validationRequest.errors = NULL; try { debugs(83, 5, "Sending SSL certificate for validation to ssl_crtvd."); AsyncCall::Pointer call = asyncCall(83,5, "Security::PeerConnector::sslCrtvdHandleReply", Ssl::CertValidationHelper::CbDialer(this, &Security::PeerConnector::sslCrtvdHandleReply, nullptr)); @@ -250,13 +250,17 @@ return; } - debugs(83,5, request->url.host() << " cert validation result: " << validationResponse->resultCode); + if (Debug::Enabled(83, 5)) { + Security::SessionPointer ssl(fd_table[serverConnection()->fd].ssl); + SBuf *server = static_cast(SSL_get_ex_data(ssl.get(), ssl_ex_index_server)); + debugs(83,5, *server << " cert validation result: " << validationResponse->resultCode); + } if (validationResponse->resultCode == ::Helper::Error) { - if (Ssl::CertErrors *errs = sslCrtvdCheckForErrors(*validationResponse, errDetails)) { - Security::SessionPtr ssl = fd_table[serverConnection()->fd].ssl.get(); - Ssl::CertErrors *oldErrs = static_cast(SSL_get_ex_data(ssl, ssl_ex_index_ssl_errors)); - SSL_set_ex_data(ssl, ssl_ex_index_ssl_errors, (void *)errs); + if (Security::CertErrors *errs = sslCrtvdCheckForErrors(*validationResponse, errDetails)) { + Security::SessionPointer session(fd_table[serverConnection()->fd].ssl); + Security::CertErrors *oldErrs = static_cast(SSL_get_ex_data(session.get(), ssl_ex_index_ssl_errors)); + SSL_set_ex_data(session.get(), ssl_ex_index_ssl_errors, (void *)errs); delete oldErrs; } } else if (validationResponse->resultCode != ::Helper::Okay) @@ -287,19 +291,18 @@ #if USE_OPENSSL /// Checks errors in the cert. validator response against sslproxy_cert_error. /// The first honored error, if any, is returned via errDetails parameter. -/// The method returns all seen errors except SSL_ERROR_NONE as Ssl::CertErrors. -Ssl::CertErrors * +/// The method returns all seen errors except SSL_ERROR_NONE as Security::CertErrors. +Security::CertErrors * Security::PeerConnector::sslCrtvdCheckForErrors(Ssl::CertValidationResponse const &resp, Ssl::ErrorDetail *& errDetails) { - Ssl::CertErrors *errs = NULL; - ACLFilledChecklist *check = NULL; if (acl_access *acl = ::Config.ssl_client.cert_error) { check = new ACLFilledChecklist(acl, request.getRaw(), dash_str); check->al = al; } - Security::SessionPtr ssl = fd_table[serverConnection()->fd].ssl.get(); + Security::CertErrors *errs = nullptr; + Security::SessionPointer session(fd_table[serverConnection()->fd].ssl); typedef Ssl::CertValidationResponse::RecvdErrors::const_iterator SVCRECI; for (SVCRECI i = resp.errors.begin(); i != resp.errors.end(); ++i) { debugs(83, 7, "Error item: " << i->error_no << " " << i->error_reason); @@ -309,7 +312,7 @@ if (!errDetails) { bool allowed = false; if (check) { - check->sslErrors = new Ssl::CertErrors(Ssl::CertError(i->error_no, i->cert.get(), i->error_depth)); + check->sslErrors = new Security::CertErrors(Security::CertError(i->error_no, i->cert, i->error_depth)); if (check->fastCheck() == ACCESS_ALLOWED) allowed = true; } @@ -321,7 +324,7 @@ } else { debugs(83, 5, "confirming SSL error " << i->error_no); X509 *brokenCert = i->cert.get(); - Security::CertPointer peerCert(SSL_get_peer_certificate(ssl)); + Security::CertPointer peerCert(SSL_get_peer_certificate(session.get())); const char *aReason = i->error_reason.empty() ? NULL : i->error_reason.c_str(); errDetails = new Ssl::ErrorDetail(i->error_no, peerCert.get(), brokenCert, aReason); } @@ -332,9 +335,9 @@ } if (!errs) - errs = new Ssl::CertErrors(Ssl::CertError(i->error_no, i->cert.get(), i->error_depth)); + errs = new Security::CertErrors(Security::CertError(i->error_no, i->cert, i->error_depth)); else - errs->push_back_unique(Ssl::CertError(i->error_no, i->cert.get(), i->error_depth)); + errs->push_back_unique(Security::CertError(i->error_no, i->cert, i->error_depth)); } if (check) delete check; @@ -358,8 +361,8 @@ #if USE_OPENSSL const int fd = serverConnection()->fd; unsigned long ssl_lib_error = SSL_ERROR_NONE; - Security::SessionPtr ssl = fd_table[fd].ssl.get(); - const int ssl_error = SSL_get_error(ssl, ret); + Security::SessionPointer session(fd_table[fd].ssl); + const int ssl_error = SSL_get_error(session.get(), ret); switch (ssl_error) { case SSL_ERROR_WANT_READ: @@ -391,8 +394,8 @@ { const int fd = serverConnection()->fd; #if USE_OPENSSL - Security::SessionPtr ssl = fd_table[fd].ssl.get(); - BIO *b = SSL_get_rbio(ssl); + Security::SessionPointer session(fd_table[fd].ssl); + BIO *b = SSL_get_rbio(session.get()); Ssl::ServerBio *srvBio = static_cast(b->ptr); if (srvBio->holdRead()) { if (srvBio->gotHello()) { @@ -450,8 +453,8 @@ anErr = new ErrorState(ERR_SECURE_CONNECT_FAIL, Http::scServiceUnavailable, NULL); anErr->xerrno = sysErrNo; - Security::SessionPtr ssl = fd_table[fd].ssl.get(); - Ssl::ErrorDetail *errFromFailure = static_cast(SSL_get_ex_data(ssl, ssl_ex_index_ssl_error_detail)); + Security::SessionPointer session(fd_table[fd].ssl); + Ssl::ErrorDetail *errFromFailure = static_cast(SSL_get_ex_data(session.get(), ssl_ex_index_ssl_error_detail)); if (errFromFailure != NULL) { // The errFromFailure is attached to the ssl object // and will be released when ssl object destroyed. @@ -459,7 +462,7 @@ anErr->detail = new Ssl::ErrorDetail(*errFromFailure); } else { // server_cert can be NULL here - X509 *server_cert = SSL_get_peer_certificate(ssl); + X509 *server_cert = SSL_get_peer_certificate(session.get()); anErr->detail = new Ssl::ErrorDetail(SQUID_ERR_SSL_HANDSHAKE, server_cert, NULL); X509_free(server_cert); } @@ -567,7 +570,7 @@ "Security::PeerConnector::certDownloadingDone", PeerConnectorCertDownloaderDialer(&Security::PeerConnector::certDownloadingDone, this)); - const Downloader *csd = dynamic_cast(request->downloader.valid()); + const Downloader *csd = (request ? dynamic_cast(request->downloader.valid()) : nullptr); Downloader *dl = new Downloader(url, certCallback, csd ? csd->nestedLevel() + 1 : 1); AsyncJob::Start(dl); } @@ -580,8 +583,8 @@ // get ServerBio from SSL object const int fd = serverConnection()->fd; - Security::SessionPtr ssl = fd_table[fd].ssl.get(); - BIO *b = SSL_get_rbio(ssl); + Security::SessionPointer session(fd_table[fd].ssl); + BIO *b = SSL_get_rbio(session.get()); Ssl::ServerBio *srvBio = static_cast(b->ptr); // Parse Certificate. Assume that it is in DER format. @@ -599,7 +602,7 @@ if (const char *issuerUri = Ssl::uriOfIssuerIfMissing(cert, certsList)) { urlsOfMissingCerts.push(SBuf(issuerUri)); } - Ssl::SSL_add_untrusted_cert(ssl, cert); + Ssl::SSL_add_untrusted_cert(session.get(), cert); } // Check if there are URIs to download from and if yes start downloading @@ -621,13 +624,13 @@ // certificate located in an SSL site which requires to download a // a missing certificate (... from an SSL site which requires to ...). - const Downloader *csd = request->downloader.get(); + const Downloader *csd = (request ? request->downloader.get() : nullptr); if (csd && csd->nestedLevel() >= MaxNestedDownloads) return false; const int fd = serverConnection()->fd; - Security::SessionPtr ssl = fd_table[fd].ssl.get(); - BIO *b = SSL_get_rbio(ssl); + Security::SessionPointer session(fd_table[fd].ssl); + BIO *b = SSL_get_rbio(session.get()); Ssl::ServerBio *srvBio = static_cast(b->ptr); const Security::CertList &certs = srvBio->serverCertificatesIfAny(); diff -u -r -N squid-4.0.14/src/security/PeerConnector.h squid-4.0.15/src/security/PeerConnector.h --- squid-4.0.14/src/security/PeerConnector.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/security/PeerConnector.h 2016-10-10 08:05:51.000000000 +1300 @@ -155,9 +155,9 @@ /// \param error if not NULL the SSL negotiation was aborted with an error virtual void noteNegotiationDone(ErrorState *error) {} - /// Must implemented by the kid classes to return the Security::ContextPtr object to use + /// Must implemented by the kid classes to return the TLS context object to use /// for building the encryption context objects. - virtual Security::ContextPtr getSslContext() = 0; + virtual Security::ContextPointer getTlsContext() = 0; /// mimics FwdState to minimize changes to FwdState::initiate/negotiateSsl Comm::ConnectionPointer const &serverConnection() const { return serverConn; } @@ -188,7 +188,7 @@ void sslCrtvdHandleReply(Ssl::CertValidationResponsePointer); /// Check SSL errors returned from cert validator against sslproxy_cert_error access list - Ssl::CertErrors *sslCrtvdCheckForErrors(Ssl::CertValidationResponse const &, Ssl::ErrorDetail *&); + Security::CertErrors *sslCrtvdCheckForErrors(Ssl::CertValidationResponse const &, Ssl::ErrorDetail *&); #endif /// A wrapper function for negotiateSsl for use with Comm::SetSelect diff -u -r -N squid-4.0.14/src/security/PeerOptions.cc squid-4.0.15/src/security/PeerOptions.cc --- squid-4.0.14/src/security/PeerOptions.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/security/PeerOptions.cc 2016-10-10 08:05:51.000000000 +1300 @@ -215,44 +215,46 @@ } } -Security::ContextPtr +Security::ContextPointer Security::PeerOptions::createBlankContext() const { - Security::ContextPtr t = nullptr; - + Security::ContextPointer ctx; #if USE_OPENSSL Ssl::Initialize(); #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) - t = SSL_CTX_new(TLS_client_method()); + SSL_CTX *t = SSL_CTX_new(TLS_client_method()); #else - t = SSL_CTX_new(SSLv23_client_method()); + SSL_CTX *t = SSL_CTX_new(SSLv23_client_method()); #endif if (!t) { const auto x = ERR_error_string(ERR_get_error(), nullptr); fatalf("Failed to allocate TLS client context: %s\n", x); } + ctx.resetWithoutLocking(t); #elif USE_GNUTLS // Initialize for X.509 certificate exchange + gnutls_certificate_credentials_t t; if (const int x = gnutls_certificate_allocate_credentials(&t)) { fatalf("Failed to allocate TLS client context: error=%d\n", x); } + ctx.resetWithoutLocking(t); #else debugs(83, 1, "WARNING: Failed to allocate TLS client context: No TLS library"); #endif - return t; + return ctx; } -Security::ContextPtr +Security::ContextPointer Security::PeerOptions::createClientContext(bool setOptions) { updateTlsVersionLimits(); - Security::ContextPtr t = createBlankContext(); + Security::ContextPointer t(createBlankContext()); if (t) { #if USE_OPENSSL // XXX: temporary performance regression. c_str() data copies and prevents this being a const method @@ -554,13 +556,13 @@ #endif void -Security::PeerOptions::updateContextNpn(Security::ContextPtr &ctx) +Security::PeerOptions::updateContextNpn(Security::ContextPointer &ctx) { if (!flags.tlsNpn) return; #if USE_OPENSSL && defined(TLSEXT_TYPE_next_proto_neg) - SSL_CTX_set_next_proto_select_cb(ctx, &ssl_next_proto_cb, nullptr); + SSL_CTX_set_next_proto_select_cb(ctx.get(), &ssl_next_proto_cb, nullptr); #endif // NOTE: GnuTLS does not support the obsolete NPN extension. @@ -568,14 +570,14 @@ } static const char * -loadSystemTrustedCa(Security::ContextPtr &ctx) +loadSystemTrustedCa(Security::ContextPointer &ctx) { #if USE_OPENSSL - if (SSL_CTX_set_default_verify_paths(ctx) == 0) + if (SSL_CTX_set_default_verify_paths(ctx.get()) == 0) return ERR_error_string(ERR_get_error(), nullptr); #elif USE_GNUTLS - auto x = gnutls_certificate_set_x509_system_trust(ctx); + auto x = gnutls_certificate_set_x509_system_trust(ctx.get()); if (x < 0) return gnutls_strerror(x); @@ -584,7 +586,7 @@ } void -Security::PeerOptions::updateContextCa(Security::ContextPtr &ctx) +Security::PeerOptions::updateContextCa(Security::ContextPointer &ctx) { debugs(83, 8, "Setting CA certificate locations."); #if USE_OPENSSL @@ -592,12 +594,12 @@ #endif for (auto i : caFiles) { #if USE_OPENSSL - if (!SSL_CTX_load_verify_locations(ctx, i.c_str(), path)) { + if (!SSL_CTX_load_verify_locations(ctx.get(), i.c_str(), path)) { const int ssl_error = ERR_get_error(); debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting CA certificate locations: " << ERR_error_string(ssl_error, NULL)); } #elif USE_GNUTLS - if (gnutls_certificate_set_x509_trust_file(ctx, i.c_str(), GNUTLS_X509_FMT_PEM) < 0) { + if (gnutls_certificate_set_x509_trust_file(ctx.get(), i.c_str(), GNUTLS_X509_FMT_PEM) < 0) { debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting CA certificate location: " << i); } #endif @@ -612,11 +614,11 @@ } void -Security::PeerOptions::updateContextCrl(Security::ContextPtr &ctx) +Security::PeerOptions::updateContextCrl(Security::ContextPointer &ctx) { #if USE_OPENSSL bool verifyCrl = false; - X509_STORE *st = SSL_CTX_get_cert_store(ctx); + X509_STORE *st = SSL_CTX_get_cert_store(ctx.get()); if (parsedCrl.size()) { for (auto &i : parsedCrl) { if (!X509_STORE_add_crl(st, i.get())) diff -u -r -N squid-4.0.14/src/security/PeerOptions.h squid-4.0.15/src/security/PeerOptions.h --- squid-4.0.14/src/security/PeerOptions.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/security/PeerOptions.h 2016-10-10 08:05:51.000000000 +1300 @@ -33,22 +33,22 @@ virtual void clear() {*this = PeerOptions();} /// generate an unset security context object - virtual Security::ContextPtr createBlankContext() const; + virtual Security::ContextPointer createBlankContext() const; /// generate a security client-context from these configured options - Security::ContextPtr createClientContext(bool setOptions); + Security::ContextPointer createClientContext(bool setOptions); /// sync the context options with tls-min-version=N configuration void updateTlsVersionLimits(); /// setup the NPN extension details for the given context - void updateContextNpn(Security::ContextPtr &); + void updateContextNpn(Security::ContextPointer &); /// setup the CA details for the given context - void updateContextCa(Security::ContextPtr &); + void updateContextCa(Security::ContextPointer &); /// setup the CRL details for the given context - void updateContextCrl(Security::ContextPtr &); + void updateContextCrl(Security::ContextPointer &); /// output squid.conf syntax with 'pfx' prefix on parameters for the stored settings virtual void dumpCfg(Packable *, const char *pfx) const; diff -u -r -N squid-4.0.14/src/security/ServerOptions.cc squid-4.0.15/src/security/ServerOptions.cc --- squid-4.0.14/src/security/ServerOptions.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/security/ServerOptions.cc 2016-10-10 08:05:51.000000000 +1300 @@ -85,36 +85,38 @@ p->appendf(" %sdh=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(dh)); } -Security::ContextPtr +Security::ContextPointer Security::ServerOptions::createBlankContext() const { - Security::ContextPtr t = nullptr; - + Security::ContextPointer ctx; #if USE_OPENSSL Ssl::Initialize(); #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) - t = SSL_CTX_new(TLS_server_method()); + SSL_CTX *t = SSL_CTX_new(TLS_server_method()); #else - t = SSL_CTX_new(SSLv23_server_method()); + SSL_CTX *t = SSL_CTX_new(SSLv23_server_method()); #endif if (!t) { const auto x = ERR_error_string(ERR_get_error(), nullptr); debugs(83, DBG_CRITICAL, "ERROR: Failed to allocate TLS server context: " << x); } + ctx.resetWithoutLocking(t); #elif USE_GNUTLS // Initialize for X.509 certificate exchange + gnutls_certificate_credentials_t t; if (const int x = gnutls_certificate_allocate_credentials(&t)) { debugs(83, DBG_CRITICAL, "ERROR: Failed to allocate TLS server context: error=" << x); } + ctx.resetWithoutLocking(t); #else debugs(83, DBG_CRITICAL, "ERROR: Failed to allocate TLS server context: No TLS library"); #endif - return t; + return ctx; } bool @@ -166,7 +168,7 @@ } void -Security::ServerOptions::updateContextEecdh(Security::ContextPtr &ctx) +Security::ServerOptions::updateContextEecdh(Security::ContextPointer &ctx) { // set Elliptic Curve details into the server context if (!eecdhCurve.isEmpty()) { @@ -186,7 +188,7 @@ return; } - if (!SSL_CTX_set_tmp_ecdh(ctx, ecdh)) { + if (!SSL_CTX_set_tmp_ecdh(ctx.get(), ecdh)) { auto ssl_error = ERR_get_error(); debugs(83, DBG_CRITICAL, "ERROR: Unable to set Ephemeral ECDH: " << ERR_error_string(ssl_error, NULL)); } @@ -201,7 +203,7 @@ // set DH parameters into the server context #if USE_OPENSSL if (parsedDhParams.get()) { - SSL_CTX_set_tmp_dh(ctx, parsedDhParams.get()); + SSL_CTX_set_tmp_dh(ctx.get(), parsedDhParams.get()); } #endif } diff -u -r -N squid-4.0.14/src/security/ServerOptions.h squid-4.0.15/src/security/ServerOptions.h --- squid-4.0.14/src/security/ServerOptions.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/security/ServerOptions.h 2016-10-10 08:05:51.000000000 +1300 @@ -29,7 +29,7 @@ /* Security::PeerOptions API */ virtual void parse(const char *); virtual void clear() {*this = ServerOptions();} - virtual Security::ContextPtr createBlankContext() const; + virtual Security::ContextPointer createBlankContext() const; virtual void dumpCfg(Packable *, const char *pfx) const; /// generate a security server-context from these configured options @@ -38,7 +38,7 @@ bool createStaticServerContext(AnyP::PortCfg &); /// update the context with DH, EDH, EECDH settings - void updateContextEecdh(Security::ContextPtr &); + void updateContextEecdh(Security::ContextPointer &); public: /// TLS context to use for HTTPS accelerator or static SSL-Bump diff -u -r -N squid-4.0.14/src/security/Session.cc squid-4.0.15/src/security/Session.cc --- squid-4.0.14/src/security/Session.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/security/Session.cc 2016-10-10 08:05:51.000000000 +1300 @@ -110,8 +110,8 @@ } for (AnyP::PortCfgPointer s = HttpPortList; s != nullptr; s = s->next) { - if (s->secure.staticContext.get()) - Ssl::SetSessionCallbacks(s->secure.staticContext.get()); + if (s->secure.staticContext) + Ssl::SetSessionCallbacks(s->secure.staticContext); } #endif } diff -u -r -N squid-4.0.14/src/security/Session.h squid-4.0.15/src/security/Session.h --- squid-4.0.14/src/security/Session.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/security/Session.h 2016-10-10 08:05:51.000000000 +1300 @@ -29,14 +29,12 @@ namespace Security { #if USE_OPENSSL -typedef SSL* SessionPtr; CtoCpp1(SSL_free, SSL *); typedef LockingPointer SessionPointer; typedef std::unique_ptr> SessionStatePointer; #elif USE_GNUTLS -typedef gnutls_session_t SessionPtr; // Locks can be implemented attaching locks counter to gnutls_session_t // objects using the gnutls_session_set_ptr()/gnutls_session_get_ptr () // library functions @@ -49,8 +47,7 @@ #else // use void* so we can check against NULL -typedef void* SessionPtr; -CtoCpp1(xfree, SessionPtr); +CtoCpp1(xfree, void *); typedef LockingPointer SessionPointer; typedef std::unique_ptr SessionStatePointer; diff -u -r -N squid-4.0.14/src/SquidConfig.h squid-4.0.15/src/SquidConfig.h --- squid-4.0.14/src/SquidConfig.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/SquidConfig.h 2016-10-10 08:05:51.000000000 +1300 @@ -505,7 +505,7 @@ external_acl *externalAclHelperList; struct { - Security::ContextPtr sslContext; + Security::ContextPointer sslContext; #if USE_OPENSSL char *foreignIntermediateCertsPath; acl_access *cert_error; @@ -547,11 +547,15 @@ class SquidConfig2 { public: + void clear() { + *this = SquidConfig2(); + } + struct { - int enable_purge; + int enable_purge = 0; } onoff; - uid_t effectiveUserID; - gid_t effectiveGroupID; + uid_t effectiveUserID = 0; + gid_t effectiveGroupID = 0; }; extern SquidConfig2 Config2; diff -u -r -N squid-4.0.14/src/SquidNew.cc squid-4.0.15/src/SquidNew.cc --- squid-4.0.14/src/SquidNew.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/SquidNew.cc 2016-10-10 08:05:51.000000000 +1300 @@ -10,7 +10,7 @@ #include "squid.h" -#if !defined(__clang__) +#if !defined(__clang__) && !defined(__SUNPRO_CC) #include diff -u -r -N squid-4.0.14/src/ssl/cert_validate_message.cc squid-4.0.15/src/ssl/cert_validate_message.cc --- squid-4.0.14/src/ssl/cert_validate_message.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/ssl/cert_validate_message.cc 2016-10-10 08:05:51.000000000 +1300 @@ -10,6 +10,7 @@ #include "acl/FilledChecklist.h" #include "globals.h" #include "helper.h" +#include "security/CertError.h" #include "ssl/cert_validate_message.h" #include "ssl/ErrorDetail.h" #include "ssl/support.h" @@ -48,7 +49,7 @@ if (vcert.errors) { int i = 0; - for (const Ssl::CertErrors *err = vcert.errors; err; err = err->next, ++i) { + for (const Security::CertErrors *err = vcert.errors; err; err = err->next, ++i) { body +="\n"; body = body + param_error_name + xitoa(i) + "=" + GetErrorName(err->element.code) + "\n"; int errorCertPos = -1; diff -u -r -N squid-4.0.14/src/ssl/cert_validate_message.h squid-4.0.15/src/ssl/cert_validate_message.h --- squid-4.0.14/src/ssl/cert_validate_message.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/ssl/cert_validate_message.h 2016-10-10 08:05:51.000000000 +1300 @@ -27,7 +27,7 @@ { public: SSL *ssl; - CertErrors *errors; ///< The list of errors detected + Security::CertErrors *errors; ///< The list of errors detected std::string domainName; ///< The server name CertValidationRequest() : ssl(NULL), errors(NULL) {} }; @@ -53,7 +53,7 @@ RecvdError & operator =(const RecvdError &); void setCert(X509 *); ///< Sets cert to the given certificate int id; ///< The id of the error - ssl_error_t error_no; ///< The OpenSSL error code + Security::ErrorCode error_no; ///< The OpenSSL error code std::string error_reason; ///< A string describing the error Security::CertPointer cert; ///< The broken certificate int error_depth; ///< The error depth diff -u -r -N squid-4.0.14/src/ssl/ErrorDetail.cc squid-4.0.15/src/ssl/ErrorDetail.cc --- squid-4.0.14/src/ssl/ErrorDetail.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/ssl/ErrorDetail.cc 2016-10-10 08:05:51.000000000 +1300 @@ -15,13 +15,13 @@ #include struct SslErrorEntry { - Ssl::ssl_error_t value; + Security::ErrorCode value; const char *name; }; static const char *SslErrorDetailDefaultStr = "SSL handshake error (%err_name)"; //Use std::map to optimize search -typedef std::map SslErrors; +typedef std::map SslErrors; SslErrors TheSslErrors; static SslErrorEntry TheSslErrorArray[] = { @@ -290,20 +290,20 @@ struct SslErrorAlias { const char *name; - const Ssl::ssl_error_t *errors; + const Security::ErrorCode *errors; }; -static const Ssl::ssl_error_t hasExpired[] = {X509_V_ERR_CERT_HAS_EXPIRED, SSL_ERROR_NONE}; -static const Ssl::ssl_error_t notYetValid[] = {X509_V_ERR_CERT_NOT_YET_VALID, SSL_ERROR_NONE}; -static const Ssl::ssl_error_t domainMismatch[] = {SQUID_X509_V_ERR_DOMAIN_MISMATCH, SSL_ERROR_NONE}; -static const Ssl::ssl_error_t certUntrusted[] = {X509_V_ERR_INVALID_CA, - X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN, - X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE, - X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT, - X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, - X509_V_ERR_CERT_UNTRUSTED, SSL_ERROR_NONE - }; -static const Ssl::ssl_error_t certSelfSigned[] = {X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT, SSL_ERROR_NONE}; +static const Security::ErrorCode hasExpired[] = {X509_V_ERR_CERT_HAS_EXPIRED, SSL_ERROR_NONE}; +static const Security::ErrorCode notYetValid[] = {X509_V_ERR_CERT_NOT_YET_VALID, SSL_ERROR_NONE}; +static const Security::ErrorCode domainMismatch[] = {SQUID_X509_V_ERR_DOMAIN_MISMATCH, SSL_ERROR_NONE}; +static const Security::ErrorCode certUntrusted[] = {X509_V_ERR_INVALID_CA, + X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN, + X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE, + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT, + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, + X509_V_ERR_CERT_UNTRUSTED, SSL_ERROR_NONE + }; +static const Security::ErrorCode certSelfSigned[] = {X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT, SSL_ERROR_NONE}; // The list of error name shortcuts for use with ssl_error acls. // The keys without the "ssl::" scope prefix allow shorter error @@ -324,7 +324,7 @@ }; // Use std::map to optimize search. -typedef std::map SslErrorShortcuts; +typedef std::map SslErrorShortcuts; SslErrorShortcuts TheSslErrorShortcuts; static void loadSslErrorMap() @@ -342,7 +342,7 @@ TheSslErrorShortcuts[TheSslErrorShortcutsArray[i].name] = TheSslErrorShortcutsArray[i].errors; } -Ssl::ssl_error_t Ssl::GetErrorCode(const char *name) +Security::ErrorCode Ssl::GetErrorCode(const char *name) { //TODO: use a std::map? for (int i = 0; TheSslErrorArray[i].name != NULL; ++i) { @@ -352,20 +352,24 @@ return SSL_ERROR_NONE; } -Ssl::Errors * -Ssl::ParseErrorString(const char *name) +bool +Ssl::ParseErrorString(const char *name, Security::Errors &errors) { assert(name); - const Ssl::ssl_error_t ssl_error = GetErrorCode(name); - if (ssl_error != SSL_ERROR_NONE) - return new Ssl::Errors(ssl_error); + const Security::ErrorCode ssl_error = GetErrorCode(name); + if (ssl_error != SSL_ERROR_NONE) { + errors.emplace(ssl_error); + return true; + } if (xisdigit(*name)) { const long int value = strtol(name, NULL, 0); - if (SQUID_SSL_ERROR_MIN <= value && value <= SQUID_SSL_ERROR_MAX) - return new Ssl::Errors(value); - fatalf("Too small or too bug SSL error code '%s'", name); + if (SQUID_SSL_ERROR_MIN <= value && value <= SQUID_SSL_ERROR_MAX) { + errors.emplace(value); + return true; + } + fatalf("Too small or too big TLS error code '%s'", name); } if (TheSslErrorShortcuts.empty()) @@ -375,18 +379,17 @@ if (it != TheSslErrorShortcuts.end()) { // Should not be empty... assert(it->second[0] != SSL_ERROR_NONE); - Ssl::Errors *errors = new Ssl::Errors(it->second[0]); - for (int i =1; it->second[i] != SSL_ERROR_NONE; ++i) { - errors->push_back_unique(it->second[i]); + for (int i = 0; it->second[i] != SSL_ERROR_NONE; ++i) { + errors.emplace(it->second[i]); } - return errors; + return true; } - fatalf("Unknown SSL error name '%s'", name); - return NULL; // not reached + fatalf("Unknown TLS error name '%s'", name); + return false; // not reached } -const char *Ssl::GetErrorName(Ssl::ssl_error_t value) +const char *Ssl::GetErrorName(Security::ErrorCode value) { if (TheSslErrors.empty()) loadSslErrorMap(); @@ -409,7 +412,7 @@ } const char * -Ssl::GetErrorDescr(Ssl::ssl_error_t value) +Ssl::GetErrorDescr(Security::ErrorCode value) { return ErrorDetailsManager::GetInstance().getDefaultErrorDescr(value); } @@ -625,7 +628,7 @@ return errDetailStr; } -Ssl::ErrorDetail::ErrorDetail( Ssl::ssl_error_t err_no, X509 *cert, X509 *broken, const char *aReason): error_no (err_no), lib_error_no(SSL_ERROR_NONE), errReason(aReason) +Ssl::ErrorDetail::ErrorDetail( Security::ErrorCode err_no, X509 *cert, X509 *broken, const char *aReason): error_no (err_no), lib_error_no(SSL_ERROR_NONE), errReason(aReason) { if (cert) peer_cert.resetAndLock(cert); diff -u -r -N squid-4.0.14/src/ssl/ErrorDetail.h squid-4.0.15/src/ssl/ErrorDetail.h --- squid-4.0.14/src/ssl/ErrorDetail.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/ssl/ErrorDetail.h 2016-10-10 08:05:51.000000000 +1300 @@ -17,42 +17,25 @@ namespace Ssl { /** - \ingroup ServerProtocolSSLAPI - * Converts user-friendly error "name" into an Ssl::Errors list. - * The resulting list may have one or more elements, and needs to be - * released by the caller. + * Converts user-friendly error "name" into an Security::ErrorCode + * and adds it to the provided container (using emplace). * This function can handle numeric error numbers as well as names. */ -Ssl::Errors *ParseErrorString(const char *name); +bool ParseErrorString(const char *name, Security::Errors &); -/** - \ingroup ServerProtocolSSLAPI - * The ssl_error_t code of the error described by "name". - */ -ssl_error_t GetErrorCode(const char *name); - -/** - \ingroup ServerProtocolSSLAPI - * The string representation of the SSL error "value" - */ -const char *GetErrorName(ssl_error_t value); +/// The Security::ErrorCode code of the error described by "name". +Security::ErrorCode GetErrorCode(const char *name); -/** - \ingroup ServerProtocolSSLAPI - * A short description of the SSL error "value" - */ -const char *GetErrorDescr(ssl_error_t value); +/// The string representation of the TLS error "value" +const char *GetErrorName(Security::ErrorCode value); -/** - \ingroup ServerProtocolSSLAPI - * Return true if the SSL error is optional and may not supported - * by current squid version - */ +/// A short description of the TLS error "value" +const char *GetErrorDescr(Security::ErrorCode value); +/// \return true if the TLS error is optional and may not be supported by current squid version bool ErrorIsOptional(const char *name); /** - \ingroup ServerProtocolSSLAPI * Used to pass SSL error details to the error pages returned to the * end user. */ @@ -60,14 +43,14 @@ { public: // if broken certificate is nil, the peer certificate is broken - ErrorDetail(ssl_error_t err_no, X509 *peer, X509 *broken, const char *aReason = NULL); + ErrorDetail(Security::ErrorCode err_no, X509 *peer, X509 *broken, const char *aReason = NULL); ErrorDetail(ErrorDetail const &); const String &toString() const; ///< An error detail string to embed in squid error pages void useRequest(HttpRequest *aRequest) { if (aRequest != NULL) request = aRequest;} /// The error name to embed in squid error pages const char *errorName() const {return err_code();} /// The error no - ssl_error_t errorNo() const {return error_no;} + Security::ErrorCode errorNo() const {return error_no;} ///Sets the low-level error returned by OpenSSL ERR_get_error() void setLibError(unsigned long lib_err_no) {lib_error_no = lib_err_no;} /// the peer certificate @@ -100,7 +83,7 @@ void buildDetail() const; mutable String errDetailStr; ///< Caches the error detail message - ssl_error_t error_no; ///< The error code + Security::ErrorCode error_no; ///< The error code unsigned long lib_error_no; ///< low-level error returned by OpenSSL ERR_get_error(3SSL) Security::CertPointer peer_cert; ///< A pointer to the peer certificate Security::CertPointer broken_cert; ///< A pointer to the broken certificate (peer or intermediate) diff -u -r -N squid-4.0.14/src/ssl/ErrorDetailManager.cc squid-4.0.15/src/ssl/ErrorDetailManager.cc --- squid-4.0.14/src/ssl/ErrorDetailManager.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/ssl/ErrorDetailManager.cc 2016-10-10 08:05:51.000000000 +1300 @@ -43,7 +43,7 @@ /******************/ bool -Ssl::ErrorDetailsList::getRecord(Ssl::ssl_error_t value, ErrorDetailEntry &entry) +Ssl::ErrorDetailsList::getRecord(Security::ErrorCode value, ErrorDetailEntry &entry) { const ErrorDetails::const_iterator it = theList.find(value); if (it != theList.end()) { @@ -57,7 +57,7 @@ } const char * -Ssl::ErrorDetailsList::getErrorDescr(Ssl::ssl_error_t value) +Ssl::ErrorDetailsList::getErrorDescr(Security::ErrorCode value) { const ErrorDetails::const_iterator it = theList.find(value); if (it != theList.end()) { @@ -68,7 +68,7 @@ } const char * -Ssl::ErrorDetailsList::getErrorDetail(Ssl::ssl_error_t value) +Ssl::ErrorDetailsList::getErrorDetail(Security::ErrorCode value) { const ErrorDetails::const_iterator it = theList.find(value); if (it != theList.end()) { @@ -123,7 +123,7 @@ } bool -Ssl::ErrorDetailsManager::getErrorDetail(Ssl::ssl_error_t value, const HttpRequest::Pointer &request, ErrorDetailEntry &entry) +Ssl::ErrorDetailsManager::getErrorDetail(Security::ErrorCode value, const HttpRequest::Pointer &request, ErrorDetailEntry &entry) { #if USE_ERR_LOCALES String hdr; @@ -164,13 +164,13 @@ } const char * -Ssl::ErrorDetailsManager::getDefaultErrorDescr(Ssl::ssl_error_t value) +Ssl::ErrorDetailsManager::getDefaultErrorDescr(Security::ErrorCode value) { return theDefaultErrorDetails->getErrorDescr(value); } const char * -Ssl::ErrorDetailsManager::getDefaultErrorDetail(Ssl::ssl_error_t value) +Ssl::ErrorDetailsManager::getDefaultErrorDetail(Security::ErrorCode value) { return theDefaultErrorDetails->getErrorDetail(value); } @@ -225,7 +225,7 @@ return false; } - Ssl::ssl_error_t ssl_error = Ssl::GetErrorCode(errorName.termedBuf()); + Security::ErrorCode ssl_error = Ssl::GetErrorCode(errorName.termedBuf()); if (ssl_error != SSL_ERROR_NONE) { if (theDetails->getErrorDetail(ssl_error)) { diff -u -r -N squid-4.0.14/src/ssl/ErrorDetailManager.h squid-4.0.15/src/ssl/ErrorDetailManager.h --- squid-4.0.14/src/ssl/ErrorDetailManager.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/ssl/ErrorDetailManager.h 2016-10-10 08:05:51.000000000 +1300 @@ -25,7 +25,7 @@ class ErrorDetailEntry { public: - Ssl::ssl_error_t error_no; ///< The SSL error code + Security::ErrorCode error_no; ///< The SSL error code String name; ///< a name for the error String detail; ///< for error page %D macro expansion; may contain macros String descr; ///< short error description (for use in debug messages or error pages) @@ -43,12 +43,12 @@ * Retrieves the error details for a given error to "entry" object * \return true on success, false otherwise */ - bool getRecord(Ssl::ssl_error_t value, ErrorDetailEntry &entry); - const char *getErrorDescr(Ssl::ssl_error_t value); ///< an error description for an error if exist in list. - const char *getErrorDetail(Ssl::ssl_error_t value); ///< an error details for an error if exist in list. + bool getRecord(Security::ErrorCode value, ErrorDetailEntry &entry); + const char *getErrorDescr(Security::ErrorCode value); ///< an error description for an error if exist in list. + const char *getErrorDetail(Security::ErrorCode value); ///< an error details for an error if exist in list. String errLanguage; ///< The language of the error-details.txt template, if any - typedef std::map ErrorDetails; + typedef std::map ErrorDetails; ErrorDetails theList; ///< The list of error details entries }; @@ -73,9 +73,9 @@ * \param entry where to store error details * \return true on success, false otherwise */ - bool getErrorDetail(Ssl::ssl_error_t value, const HttpRequest::Pointer &request, ErrorDetailEntry &entry); - const char *getDefaultErrorDescr(Ssl::ssl_error_t value); ///< the default error description for a given error - const char *getDefaultErrorDetail(Ssl::ssl_error_t value); ///< the default error details for a given error + bool getErrorDetail(Security::ErrorCode value, const HttpRequest::Pointer &request, ErrorDetailEntry &entry); + const char *getDefaultErrorDescr(Security::ErrorCode value); ///< the default error description for a given error + const char *getDefaultErrorDetail(Security::ErrorCode value); ///< the default error details for a given error private: /// Return cached error details list for a given language if exist diff -u -r -N squid-4.0.14/src/ssl/PeekingPeerConnector.cc squid-4.0.15/src/ssl/PeekingPeerConnector.cc --- squid-4.0.14/src/ssl/PeekingPeerConnector.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/ssl/PeekingPeerConnector.cc 2016-10-10 08:05:51.000000000 +1300 @@ -63,8 +63,8 @@ acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpStare)); acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpClientFirst)); acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpServerFirst)); - Security::SessionPtr ssl = fd_table[serverConn->fd].ssl.get(); - BIO *b = SSL_get_rbio(ssl); + Security::SessionPointer session(fd_table[serverConn->fd].ssl); + BIO *b = SSL_get_rbio(session.get()); Ssl::ServerBio *srvBio = static_cast(b->ptr); if (!srvBio->canSplice()) acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpSplice)); @@ -76,8 +76,8 @@ void Ssl::PeekingPeerConnector::checkForPeekAndSpliceMatched(const Ssl::BumpMode action) { - Security::SessionPtr ssl = fd_table[serverConn->fd].ssl.get(); - BIO *b = SSL_get_rbio(ssl); + Security::SessionPointer session(fd_table[serverConn->fd].ssl); + BIO *b = SSL_get_rbio(session.get()); Ssl::ServerBio *srvBio = static_cast(b->ptr); debugs(83,5, "Will check for peek and splice on FD " << serverConn->fd); @@ -126,10 +126,9 @@ return Ssl::bumpSplice; } -Security::ContextPtr -Ssl::PeekingPeerConnector::getSslContext() +Security::ContextPointer +Ssl::PeekingPeerConnector::getTlsContext() { - // XXX: locate a per-server context in Security:: instead return ::Config.ssl_client.sslContext; } @@ -217,10 +216,8 @@ void Ssl::PeekingPeerConnector::noteNegotiationDone(ErrorState *error) { - Security::SessionPtr ssl = fd_table[serverConnection()->fd].ssl.get(); - // Check the list error with - if (!request->clientConnectionManager.valid() || ! ssl) + if (!request->clientConnectionManager.valid() || !fd_table[serverConnection()->fd].ssl) return; // remember the server certificate from the ErrorDetail object @@ -263,8 +260,8 @@ Ssl::PeekingPeerConnector::noteWantWrite() { const int fd = serverConnection()->fd; - Security::SessionPtr ssl = fd_table[fd].ssl.get(); - BIO *b = SSL_get_rbio(ssl); + Security::SessionPointer session(fd_table[fd].ssl); + BIO *b = SSL_get_rbio(session.get()); Ssl::ServerBio *srvBio = static_cast(b->ptr); if ((srvBio->bumpMode() == Ssl::bumpPeek || srvBio->bumpMode() == Ssl::bumpStare) && srvBio->holdWrite()) { @@ -280,8 +277,8 @@ Ssl::PeekingPeerConnector::noteNegotiationError(const int result, const int ssl_error, const int ssl_lib_error) { const int fd = serverConnection()->fd; - Security::SessionPtr ssl = fd_table[fd].ssl.get(); - BIO *b = SSL_get_rbio(ssl); + Security::SessionPointer session(fd_table[fd].ssl); + BIO *b = SSL_get_rbio(session.get()); Ssl::ServerBio *srvBio = static_cast(b->ptr); // In Peek mode, the ClientHello message sent to the server. If the @@ -307,10 +304,10 @@ // thus hiding them. // Abort if no certificate found probably because of malformed or // unsupported server Hello message (TODO: make configurable). - if (!SSL_get_ex_data(ssl, ssl_ex_index_ssl_error_detail) && + if (!SSL_get_ex_data(session.get(), ssl_ex_index_ssl_error_detail) && (srvBio->bumpMode() == Ssl::bumpPeek || srvBio->bumpMode() == Ssl::bumpStare) && srvBio->holdWrite()) { - Security::CertPointer serverCert(SSL_get_peer_certificate(ssl)); - if (serverCert.get()) { + Security::CertPointer serverCert(SSL_get_peer_certificate(session.get())); + if (serverCert) { debugs(81, 3, "Error (" << ERR_error_string(ssl_lib_error, NULL) << ") but, hold write on SSL connection on FD " << fd); checkForPeekAndSplice(); return; @@ -329,9 +326,9 @@ if (ConnStateData *csd = request->clientConnectionManager.valid()) { const int fd = serverConnection()->fd; - Security::SessionPtr ssl = fd_table[fd].ssl.get(); - Security::CertPointer serverCert(SSL_get_peer_certificate(ssl)); - if (!serverCert.get()) + Security::SessionPointer session(fd_table[fd].ssl); + Security::CertPointer serverCert(SSL_get_peer_certificate(session.get())); + if (!serverCert) return; serverCertificateHandled = true; @@ -352,10 +349,10 @@ serverCert.resetAndLock(serverBump->serverCert.get()); else { const int fd = serverConnection()->fd; - Security::SessionPtr ssl = fd_table[fd].ssl.get(); - serverCert.resetWithoutLocking(SSL_get_peer_certificate(ssl)); + Security::SessionPointer session(fd_table[fd].ssl); + serverCert.resetWithoutLocking(SSL_get_peer_certificate(session.get())); } - if (serverCert.get()) { + if (serverCert) { csd->resetSslCommonName(Ssl::CommonHostName(serverCert.get())); debugs(83, 5, "HTTPS server CN: " << csd->sslCommonName() << " bumped: " << *serverConnection()); diff -u -r -N squid-4.0.14/src/ssl/PeekingPeerConnector.h squid-4.0.15/src/ssl/PeekingPeerConnector.h --- squid-4.0.14/src/ssl/PeekingPeerConnector.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/ssl/PeekingPeerConnector.h 2016-10-10 08:05:51.000000000 +1300 @@ -38,7 +38,7 @@ /* Security::PeerConnector API */ virtual bool initialize(Security::SessionPointer &); - virtual Security::ContextPtr getSslContext(); + virtual Security::ContextPointer getTlsContext(); virtual void noteWantWrite(); virtual void noteNegotiationError(const int result, const int ssl_error, const int ssl_lib_error); virtual void noteNegotiationDone(ErrorState *error); diff -u -r -N squid-4.0.14/src/ssl/ServerBump.cc squid-4.0.15/src/ssl/ServerBump.cc --- squid-4.0.14/src/ssl/ServerBump.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/ssl/ServerBump.cc 2016-10-10 08:05:51.000000000 +1300 @@ -33,8 +33,9 @@ entry->lock("Ssl::ServerBump"); } else { // XXX: Performance regression. c_str() reallocates - SBuf uri(request->effectiveRequestUri()); - entry = storeCreateEntry(uri.c_str(), uri.c_str(), request->flags, request->method); + SBuf uriBuf(request->effectiveRequestUri()); + const char *uri = uriBuf.c_str(); + entry = storeCreateEntry(uri, uri, request->flags, request->method); } // We do not need to be a client because the error contents will be used // later, but an entry without any client will trim all its contents away. @@ -60,13 +61,13 @@ serverSSL.resetAndLock(ssl); } -const Ssl::CertErrors * +const Security::CertErrors * Ssl::ServerBump::sslErrors() const { if (!serverSSL.get()) return NULL; - const Ssl::CertErrors *errs = static_cast(SSL_get_ex_data(serverSSL.get(), ssl_ex_index_ssl_errors)); + const Security::CertErrors *errs = static_cast(SSL_get_ex_data(serverSSL.get(), ssl_ex_index_ssl_errors)); return errs; } diff -u -r -N squid-4.0.14/src/ssl/ServerBump.h squid-4.0.15/src/ssl/ServerBump.h --- squid-4.0.14/src/ssl/ServerBump.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/ssl/ServerBump.h 2016-10-10 08:05:51.000000000 +1300 @@ -33,7 +33,7 @@ explicit ServerBump(HttpRequest *fakeRequest, StoreEntry *e = NULL, Ssl::BumpMode mode = Ssl::bumpServerFirst); ~ServerBump(); void attachServerSSL(SSL *); ///< Sets the server SSL object - const Ssl::CertErrors *sslErrors() const; ///< SSL [certificate validation] errors + const Security::CertErrors *sslErrors() const; ///< SSL [certificate validation] errors /// faked, minimal request; required by Client API HttpRequest::Pointer request; diff -u -r -N squid-4.0.14/src/ssl/support.cc squid-4.0.15/src/ssl/support.cc --- squid-4.0.14/src/ssl/support.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/ssl/support.cc 2016-10-10 08:05:51.000000000 +1300 @@ -22,6 +22,7 @@ #include "fde.h" #include "globals.h" #include "ipc/MemMap.h" +#include "security/CertError.h" #include "SquidConfig.h" #include "SquidTime.h" #include "ssl/bio.h" @@ -230,19 +231,19 @@ ssl_verify_cb(int ok, X509_STORE_CTX * ctx) { // preserve original ctx->error before SSL_ calls can overwrite it - Ssl::ssl_error_t error_no = ok ? SSL_ERROR_NONE : ctx->error; + Security::ErrorCode error_no = ok ? SSL_ERROR_NONE : ctx->error; char buffer[256] = ""; SSL *ssl = (SSL *)X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); - Security::ContextPtr sslctx = SSL_get_SSL_CTX(ssl); + SSL_CTX *sslctx = SSL_get_SSL_CTX(ssl); SBuf *server = (SBuf *)SSL_get_ex_data(ssl, ssl_ex_index_server); void *dont_verify_domain = SSL_CTX_get_ex_data(sslctx, ssl_ctx_ex_index_dont_verify_domain); ACLChecklist *check = (ACLChecklist*)SSL_get_ex_data(ssl, ssl_ex_index_cert_error_check); X509 *peeked_cert = (X509 *)SSL_get_ex_data(ssl, ssl_ex_index_ssl_peeked_cert); - X509 *peer_cert = ctx->cert; + Security::CertPointer peer_cert; + peer_cert.resetAndLock(ctx->cert); - X509_NAME_oneline(X509_get_subject_name(peer_cert), buffer, - sizeof(buffer)); + X509_NAME_oneline(X509_get_subject_name(peer_cert.get()), buffer, sizeof(buffer)); // detect infinite loops uint32_t *validationCounter = static_cast(SSL_get_ex_data(ssl, ssl_ex_index_ssl_validation_counter)); @@ -265,8 +266,8 @@ debugs(83, 5, "SSL Certificate signature OK: " << buffer); // Check for domain mismatch only if the current certificate is the peer certificate. - if (!dont_verify_domain && server && peer_cert == X509_STORE_CTX_get_current_cert(ctx)) { - if (!Ssl::checkX509ServerValidity(peer_cert, server->c_str())) { + if (!dont_verify_domain && server && peer_cert.get() == X509_STORE_CTX_get_current_cert(ctx)) { + if (!Ssl::checkX509ServerValidity(peer_cert.get(), server->c_str())) { debugs(83, 2, "SQUID_X509_V_ERR_DOMAIN_MISMATCH: Certificate " << buffer << " does not match domainname " << server); ok = 0; error_no = SQUID_X509_V_ERR_DOMAIN_MISMATCH; @@ -276,7 +277,7 @@ if (ok && peeked_cert) { // Check whether the already peeked certificate matches the new one. - if (X509_cmp(peer_cert, peeked_cert) != 0) { + if (X509_cmp(peer_cert.get(), peeked_cert) != 0) { debugs(83, 2, "SQUID_X509_V_ERR_CERT_CHANGE: Certificate " << buffer << " does not match peeked certificate"); ok = 0; error_no = SQUID_X509_V_ERR_CERT_CHANGE; @@ -284,21 +285,22 @@ } if (!ok) { - X509 *broken_cert = X509_STORE_CTX_get_current_cert(ctx); + Security::CertPointer broken_cert; + broken_cert.resetAndLock(X509_STORE_CTX_get_current_cert(ctx)); if (!broken_cert) broken_cert = peer_cert; - Ssl::CertErrors *errs = static_cast(SSL_get_ex_data(ssl, ssl_ex_index_ssl_errors)); + Security::CertErrors *errs = static_cast(SSL_get_ex_data(ssl, ssl_ex_index_ssl_errors)); const int depth = X509_STORE_CTX_get_error_depth(ctx); if (!errs) { - errs = new Ssl::CertErrors(Ssl::CertError(error_no, broken_cert, depth)); + errs = new Security::CertErrors(Security::CertError(error_no, broken_cert, depth)); if (!SSL_set_ex_data(ssl, ssl_ex_index_ssl_errors, (void *)errs)) { debugs(83, 2, "Failed to set ssl error_no in ssl_verify_cb: Certificate " << buffer); delete errs; errs = NULL; } } else // remember another error number - errs->push_back_unique(Ssl::CertError(error_no, broken_cert, depth)); + errs->push_back_unique(Security::CertError(error_no, broken_cert, depth)); if (const char *err_descr = Ssl::GetErrorDescr(error_no)) debugs(83, 5, err_descr << ": " << buffer); @@ -311,8 +313,8 @@ if (check) { ACLFilledChecklist *filledCheck = Filled(check); assert(!filledCheck->sslErrors); - filledCheck->sslErrors = new Ssl::CertErrors(Ssl::CertError(error_no, broken_cert)); - filledCheck->serverCert.resetAndLock(peer_cert); + filledCheck->sslErrors = new Security::CertErrors(Security::CertError(error_no, broken_cert)); + filledCheck->serverCert = peer_cert; if (check->fastCheck() == ACCESS_ALLOWED) { debugs(83, 3, "bypassing SSL error " << error_no << " in " << buffer); ok = 1; @@ -343,17 +345,15 @@ if (!ok && !SSL_get_ex_data(ssl, ssl_ex_index_ssl_error_detail) ) { // Find the broken certificate. It may be intermediate. - X509 *broken_cert = peer_cert; // reasonable default if search fails + Security::CertPointer broken_cert(peer_cert); // reasonable default if search fails // Our SQUID_X509_V_ERR_DOMAIN_MISMATCH implies peer_cert is at fault. if (error_no != SQUID_X509_V_ERR_DOMAIN_MISMATCH) { - if (X509 *last_used_cert = X509_STORE_CTX_get_current_cert(ctx)) - broken_cert = last_used_cert; + if (auto *last_used_cert = X509_STORE_CTX_get_current_cert(ctx)) + broken_cert.resetAndLock(last_used_cert); } - Ssl::ErrorDetail *errDetail = - new Ssl::ErrorDetail(error_no, peer_cert, broken_cert); - - if (!SSL_set_ex_data(ssl, ssl_ex_index_ssl_error_detail, errDetail)) { + auto *errDetail = new Ssl::ErrorDetail(error_no, peer_cert.get(), broken_cert.get()); + if (!SSL_set_ex_data(ssl, ssl_ex_index_ssl_error_detail, errDetail)) { debugs(83, 2, "Failed to set Ssl::ErrorDetail in ssl_verify_cb: Certificate " << buffer); delete errDetail; } @@ -394,7 +394,7 @@ ssl_free_SslErrors(void *, void *ptr, CRYPTO_EX_DATA *, int, long, void *) { - Ssl::CertErrors *errs = static_cast (ptr); + Security::CertErrors *errs = static_cast (ptr); delete errs; } @@ -492,32 +492,32 @@ #endif static bool -configureSslContext(Security::ContextPtr sslContext, AnyP::PortCfg &port) +configureSslContext(Security::ContextPointer &ctx, AnyP::PortCfg &port) { int ssl_error; - SSL_CTX_set_options(sslContext, port.secure.parsedOptions); + SSL_CTX_set_options(ctx.get(), port.secure.parsedOptions); #if defined(SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) - SSL_CTX_set_info_callback(sslContext, ssl_info_cb); + SSL_CTX_set_info_callback(ctx.get(), ssl_info_cb); #endif if (port.sslContextSessionId) - SSL_CTX_set_session_id_context(sslContext, (const unsigned char *)port.sslContextSessionId, strlen(port.sslContextSessionId)); + SSL_CTX_set_session_id_context(ctx.get(), (const unsigned char *)port.sslContextSessionId, strlen(port.sslContextSessionId)); if (port.secure.parsedFlags & SSL_FLAG_NO_SESSION_REUSE) { - SSL_CTX_set_session_cache_mode(sslContext, SSL_SESS_CACHE_OFF); + SSL_CTX_set_session_cache_mode(ctx.get(), SSL_SESS_CACHE_OFF); } if (Config.SSL.unclean_shutdown) { debugs(83, 5, "Enabling quiet SSL shutdowns (RFC violation)."); - SSL_CTX_set_quiet_shutdown(sslContext, 1); + SSL_CTX_set_quiet_shutdown(ctx.get(), 1); } if (!port.secure.sslCipher.isEmpty()) { debugs(83, 5, "Using chiper suite " << port.secure.sslCipher << "."); - if (!SSL_CTX_set_cipher_list(sslContext, port.secure.sslCipher.c_str())) { + if (!SSL_CTX_set_cipher_list(ctx.get(), port.secure.sslCipher.c_str())) { ssl_error = ERR_get_error(); debugs(83, DBG_CRITICAL, "ERROR: Failed to set SSL cipher suite '" << port.secure.sslCipher << "': " << ERR_error_string(ssl_error, NULL)); return false; @@ -525,15 +525,15 @@ } debugs(83, 9, "Setting RSA key generation callback."); - SSL_CTX_set_tmp_rsa_callback(sslContext, ssl_temp_rsa_cb); + SSL_CTX_set_tmp_rsa_callback(ctx.get(), ssl_temp_rsa_cb); - port.secure.updateContextEecdh(sslContext); - port.secure.updateContextCa(sslContext); + port.secure.updateContextEecdh(ctx); + port.secure.updateContextCa(ctx); if (port.clientCA.get()) { ERR_clear_error(); if (STACK_OF(X509_NAME) *clientca = SSL_dup_CA_list(port.clientCA.get())) { - SSL_CTX_set_client_CA_list(sslContext, clientca); + SSL_CTX_set_client_CA_list(ctx.get(), clientca); } else { ssl_error = ERR_get_error(); debugs(83, DBG_CRITICAL, "ERROR: Failed to dupe the client CA list: " << ERR_error_string(ssl_error, NULL)); @@ -542,29 +542,29 @@ if (port.secure.parsedFlags & SSL_FLAG_DELAYED_AUTH) { debugs(83, 9, "Not requesting client certificates until acl processing requires one"); - SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL); + SSL_CTX_set_verify(ctx.get(), SSL_VERIFY_NONE, NULL); } else { debugs(83, 9, "Requiring client certificates."); - SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb); + SSL_CTX_set_verify(ctx.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb); } - port.secure.updateContextCrl(sslContext); + port.secure.updateContextCrl(ctx); } else { debugs(83, 9, "Not requiring any client certificates"); - SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL); + SSL_CTX_set_verify(ctx.get(), SSL_VERIFY_NONE, NULL); } if (port.secure.parsedFlags & SSL_FLAG_DONT_VERIFY_DOMAIN) - SSL_CTX_set_ex_data(sslContext, ssl_ctx_ex_index_dont_verify_domain, (void *) -1); + SSL_CTX_set_ex_data(ctx.get(), ssl_ctx_ex_index_dont_verify_domain, (void *) -1); - Ssl::SetSessionCallbacks(sslContext); + Ssl::SetSessionCallbacks(ctx); return true; } bool -Ssl::InitServerContext(const Security::ContextPointer &ctx, AnyP::PortCfg &port) +Ssl::InitServerContext(Security::ContextPointer &ctx, AnyP::PortCfg &port) { if (!ctx) return false; @@ -583,7 +583,7 @@ return false; } - Ssl::addChainToSslContext(ctx.get(), port.certsToChain.get()); + Ssl::addChainToSslContext(ctx, port.certsToChain.get()); /* Alternate code; debugs(83, DBG_IMPORTANT, "Using certificate in " << certfile); @@ -613,7 +613,7 @@ } */ - if (!configureSslContext(ctx.get(), port)) { + if (!configureSslContext(ctx, port)) { debugs(83, DBG_CRITICAL, "ERROR: Configuring static SSL context"); return false; } @@ -622,22 +622,22 @@ } bool -Ssl::InitClientContext(Security::ContextPtr &sslContext, Security::PeerOptions &peer, long options, long fl) +Ssl::InitClientContext(Security::ContextPointer &ctx, Security::PeerOptions &peer, long options, long fl) { - if (!sslContext) + if (!ctx) return false; - SSL_CTX_set_options(sslContext, options); + SSL_CTX_set_options(ctx.get(), options); #if defined(SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) - SSL_CTX_set_info_callback(sslContext, ssl_info_cb); + SSL_CTX_set_info_callback(ctx.get(), ssl_info_cb); #endif if (!peer.sslCipher.isEmpty()) { debugs(83, 5, "Using chiper suite " << peer.sslCipher << "."); const char *cipher = peer.sslCipher.c_str(); - if (!SSL_CTX_set_cipher_list(sslContext, cipher)) { + if (!SSL_CTX_set_cipher_list(ctx.get(), cipher)) { const int ssl_error = ERR_get_error(); fatalf("Failed to set SSL cipher suite '%s': %s\n", cipher, ERR_error_string(ssl_error, NULL)); @@ -651,7 +651,7 @@ debugs(83, DBG_IMPORTANT, "Using certificate in " << keys.certFile); const char *certfile = keys.certFile.c_str(); - if (!SSL_CTX_use_certificate_chain_file(sslContext, certfile)) { + if (!SSL_CTX_use_certificate_chain_file(ctx.get(), certfile)) { const int ssl_error = ERR_get_error(); fatalf("Failed to acquire SSL certificate '%s': %s\n", certfile, ERR_error_string(ssl_error, NULL)); @@ -659,9 +659,9 @@ debugs(83, DBG_IMPORTANT, "Using private key in " << keys.privateKeyFile); const char *keyfile = keys.privateKeyFile.c_str(); - ssl_ask_password(sslContext, keyfile); + ssl_ask_password(ctx.get(), keyfile); - if (!SSL_CTX_use_PrivateKey_file(sslContext, keyfile, SSL_FILETYPE_PEM)) { + if (!SSL_CTX_use_PrivateKey_file(ctx.get(), keyfile, SSL_FILETYPE_PEM)) { const int ssl_error = ERR_get_error(); fatalf("Failed to acquire SSL private key '%s': %s\n", keyfile, ERR_error_string(ssl_error, NULL)); @@ -669,7 +669,7 @@ debugs(83, 5, "Comparing private and public SSL keys."); - if (!SSL_CTX_check_private_key(sslContext)) { + if (!SSL_CTX_check_private_key(ctx.get())) { const int ssl_error = ERR_get_error(); fatalf("SSL private key '%s' does not match public key '%s': %s\n", certfile, keyfile, ERR_error_string(ssl_error, NULL)); @@ -678,14 +678,14 @@ } debugs(83, 9, "Setting RSA key generation callback."); - SSL_CTX_set_tmp_rsa_callback(sslContext, ssl_temp_rsa_cb); + SSL_CTX_set_tmp_rsa_callback(ctx.get(), ssl_temp_rsa_cb); if (fl & SSL_FLAG_DONT_VERIFY_PEER) { debugs(83, 2, "NOTICE: Peer certificates are not verified for validity!"); - SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL); + SSL_CTX_set_verify(ctx.get(), SSL_VERIFY_NONE, NULL); } else { debugs(83, 9, "Setting certificate verification callback."); - SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb); + SSL_CTX_set_verify(ctx.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb); } return true; @@ -707,6 +707,9 @@ #endif int i = SSL_read(ssl, buf, len); + if (i > 0) { + (void)VALGRIND_MAKE_MEM_DEFINED(buf, i); + } if (i > 0 && SSL_pending(ssl) > 0) { debugs(83, 2, "SSL FD " << fd << " is pending"); @@ -925,71 +928,66 @@ } /// Create SSL context and apply ssl certificate and private key to it. -Security::ContextPtr +Security::ContextPointer Ssl::createSSLContext(Security::CertPointer & x509, Ssl::EVP_PKEY_Pointer & pkey, AnyP::PortCfg &port) { -#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) - Security::ContextPointer sslContext(SSL_CTX_new(TLS_server_method())); -#else - Security::ContextPointer sslContext(SSL_CTX_new(SSLv23_server_method())); -#endif + Security::ContextPointer ctx(port.secure.createBlankContext()); - if (!SSL_CTX_use_certificate(sslContext.get(), x509.get())) - return NULL; + if (!SSL_CTX_use_certificate(ctx.get(), x509.get())) + return Security::ContextPointer(); - if (!SSL_CTX_use_PrivateKey(sslContext.get(), pkey.get())) - return NULL; + if (!SSL_CTX_use_PrivateKey(ctx.get(), pkey.get())) + return Security::ContextPointer(); - if (!configureSslContext(sslContext.get(), port)) - return NULL; + if (!configureSslContext(ctx, port)) + return Security::ContextPointer(); - return sslContext.release(); + return ctx; } -Security::ContextPtr +Security::ContextPointer Ssl::generateSslContextUsingPkeyAndCertFromMemory(const char * data, AnyP::PortCfg &port) { Security::CertPointer cert; Ssl::EVP_PKEY_Pointer pkey; if (!readCertAndPrivateKeyFromMemory(cert, pkey, data) || !cert || !pkey) - return nullptr; + return Security::ContextPointer(); return createSSLContext(cert, pkey, port); } -Security::ContextPtr +Security::ContextPointer Ssl::generateSslContext(CertificateProperties const &properties, AnyP::PortCfg &port) { Security::CertPointer cert; Ssl::EVP_PKEY_Pointer pkey; if (!generateSslCertificate(cert, pkey, properties) || !cert || !pkey) - return nullptr; + return Security::ContextPointer(); return createSSLContext(cert, pkey, port); } void -Ssl::chainCertificatesToSSLContext(SSL_CTX *sslContext, AnyP::PortCfg &port) +Ssl::chainCertificatesToSSLContext(Security::ContextPointer &ctx, AnyP::PortCfg &port) { - assert(sslContext != NULL); + assert(ctx); // Add signing certificate to the certificates chain X509 *signingCert = port.signingCert.get(); - if (SSL_CTX_add_extra_chain_cert(sslContext, signingCert)) { + if (SSL_CTX_add_extra_chain_cert(ctx.get(), signingCert)) { // increase the certificate lock CRYPTO_add(&(signingCert->references),1,CRYPTO_LOCK_X509); } else { const int ssl_error = ERR_get_error(); debugs(33, DBG_IMPORTANT, "WARNING: can not add signing certificate to SSL context chain: " << ERR_error_string(ssl_error, NULL)); } - Ssl::addChainToSslContext(sslContext, port.certsToChain.get()); + Ssl::addChainToSslContext(ctx, port.certsToChain.get()); } void -Ssl::configureUnconfiguredSslContext(SSL_CTX *sslContext, Ssl::CertSignAlgorithm signAlgorithm,AnyP::PortCfg &port) +Ssl::configureUnconfiguredSslContext(Security::ContextPointer &ctx, Ssl::CertSignAlgorithm signAlgorithm,AnyP::PortCfg &port) { - if (sslContext && signAlgorithm == Ssl::algSignTrusted) { - Ssl::chainCertificatesToSSLContext(sslContext, port); - } + if (ctx && signAlgorithm == Ssl::algSignTrusted) + Ssl::chainCertificatesToSSLContext(ctx, port); } bool @@ -1035,19 +1033,20 @@ return true; } -bool Ssl::verifySslCertificate(Security::ContextPtr sslContext, CertificateProperties const &properties) +bool +Ssl::verifySslCertificate(Security::ContextPointer &ctx, CertificateProperties const &properties) { // SSL_get_certificate is buggy in openssl versions 1.0.1d and 1.0.1e - // Try to retrieve certificate directly from Security::ContextPtr object + // Try to retrieve certificate directly from Security::ContextPointer object #if SQUID_USE_SSLGETCERTIFICATE_HACK - X509 ***pCert = (X509 ***)sslContext->cert; + X509 ***pCert = (X509 ***)ctx->cert; X509 * cert = pCert && *pCert ? **pCert : NULL; #elif SQUID_SSLGETCERTIFICATE_BUGGY X509 * cert = NULL; assert(0); #else // Temporary ssl for getting X509 certificate from SSL_CTX. - Security::SessionPointer ssl(SSL_new(sslContext)); + Security::SessionPointer ssl(SSL_new(ctx.get())); X509 * cert = SSL_get_certificate(ssl.get()); #endif if (!cert) @@ -1080,14 +1079,15 @@ #endif } -void Ssl::addChainToSslContext(Security::ContextPtr sslContext, STACK_OF(X509) *chain) +void +Ssl::addChainToSslContext(Security::ContextPointer &ctx, STACK_OF(X509) *chain) { if (!chain) return; for (int i = 0; i < sk_X509_num(chain); ++i) { X509 *cert = sk_X509_value(chain, i); - if (SSL_CTX_add_extra_chain_cert(sslContext, cert)) { + if (SSL_CTX_add_extra_chain_cert(ctx.get(), cert)) { // increase the certificate lock CRYPTO_add(&(cert->references),1,CRYPTO_LOCK_X509); } else { @@ -1402,7 +1402,7 @@ } static bool -SslCreate(Security::ContextPtr sslContext, const Comm::ConnectionPointer &conn, Ssl::Bio::Type type, const char *squidCtx) +SslCreate(const Security::ContextPointer &ctx, const Comm::ConnectionPointer &conn, Ssl::Bio::Type type, const char *squidCtx) { if (!Comm::IsConnOpen(conn)) { debugs(83, DBG_IMPORTANT, "Gone connection"); @@ -1411,7 +1411,7 @@ const char *errAction = NULL; int errCode = 0; - if (auto ssl = SSL_new(sslContext)) { + if (auto ssl = SSL_new(ctx.get())) { const int fd = conn->fd; // without BIO, we would call SSL_set_fd(ssl, fd) instead if (BIO *bio = Ssl::Bio::Create(fd, type)) { @@ -1437,46 +1437,15 @@ } bool -Ssl::CreateClient(Security::ContextPtr sslContext, const Comm::ConnectionPointer &c, const char *squidCtx) -{ - return SslCreate(sslContext, c, Ssl::Bio::BIO_TO_SERVER, squidCtx); -} - -bool -Ssl::CreateServer(Security::ContextPtr sslContext, const Comm::ConnectionPointer &c, const char *squidCtx) -{ - return SslCreate(sslContext, c, Ssl::Bio::BIO_TO_CLIENT, squidCtx); -} - -Ssl::CertError::CertError(ssl_error_t anErr, X509 *aCert, int aDepth): code(anErr), depth(aDepth) -{ - cert.resetAndLock(aCert); -} - -Ssl::CertError::CertError(CertError const &err): code(err.code), depth(err.depth) -{ - cert.resetAndLock(err.cert.get()); -} - -Ssl::CertError & -Ssl::CertError::operator = (const CertError &old) -{ - code = old.code; - depth = old.depth; - cert.resetAndLock(old.cert.get()); - return *this; -} - -bool -Ssl::CertError::operator == (const CertError &ce) const +Ssl::CreateClient(const Security::ContextPointer &ctx, const Comm::ConnectionPointer &c, const char *squidCtx) { - return code == ce.code && cert.get() == ce.cert.get() && depth == ce.depth; + return SslCreate(ctx, c, Ssl::Bio::BIO_TO_SERVER, squidCtx); } bool -Ssl::CertError::operator != (const CertError &ce) const +Ssl::CreateServer(const Security::ContextPointer &ctx, const Comm::ConnectionPointer &c, const char *squidCtx) { - return code != ce.code || cert.get() != ce.cert.get() || depth != ce.depth; + return SslCreate(ctx, c, Ssl::Bio::BIO_TO_CLIENT, squidCtx); } static int @@ -1568,13 +1537,13 @@ } void -Ssl::SetSessionCallbacks(Security::ContextPtr ctx) +Ssl::SetSessionCallbacks(Security::ContextPointer &ctx) { if (Ssl::SessionCache) { - SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER|SSL_SESS_CACHE_NO_INTERNAL); - SSL_CTX_sess_set_new_cb(ctx, store_session_cb); - SSL_CTX_sess_set_remove_cb(ctx, remove_session_cb); - SSL_CTX_sess_set_get_cb(ctx, get_session_cb); + SSL_CTX_set_session_cache_mode(ctx.get(), SSL_SESS_CACHE_SERVER|SSL_SESS_CACHE_NO_INTERNAL); + SSL_CTX_sess_set_new_cb(ctx.get(), store_session_cb); + SSL_CTX_sess_set_remove_cb(ctx.get(), remove_session_cb); + SSL_CTX_sess_set_get_cb(ctx.get(), get_session_cb); } } diff -u -r -N squid-4.0.14/src/ssl/support.h squid-4.0.15/src/ssl/support.h --- squid-4.0.14/src/ssl/support.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/ssl/support.h 2016-10-10 08:05:51.000000000 +1300 @@ -69,55 +69,27 @@ /// call before generating any SSL context void Initialize(); -/// Squid defined error code (<0), an error code returned by SSL X509 api, or SSL_ERROR_NONE -typedef int ssl_error_t; - -typedef CbDataList Errors; - class ErrorDetail; class CertValidationResponse; typedef RefCount CertValidationResponsePointer; /// Creates SSL Client connection structure and initializes SSL I/O (Comm and BIO). /// On errors, emits DBG_IMPORTANT with details and returns false. -bool CreateClient(Security::ContextPtr sslContext, const Comm::ConnectionPointer &, const char *squidCtx); +bool CreateClient(const Security::ContextPointer &, const Comm::ConnectionPointer &, const char *squidCtx); /// Creates SSL Server connection structure and initializes SSL I/O (Comm and BIO). /// On errors, emits DBG_IMPORTANT with details and returns false. -bool CreateServer(Security::ContextPtr sslContext, const Comm::ConnectionPointer &, const char *squidCtx); - -/// An SSL certificate-related error. -/// Pairs an error code with the certificate experiencing the error. -class CertError -{ -public: - ssl_error_t code; ///< certificate error code - Security::CertPointer cert; ///< certificate with the above error code - /** - * Absolute cert position in the final certificate chain that may include - * intermediate certificates. Chain positions start with zero and increase - * towards the root certificate. Negative if unknown. - */ - int depth; - CertError(ssl_error_t anErr, X509 *aCert, int depth = -1); - CertError(CertError const &err); - CertError & operator = (const CertError &old); - bool operator == (const CertError &ce) const; - bool operator != (const CertError &ce) const; -}; - -/// Holds a list of certificate SSL errors -typedef CbDataList CertErrors; +bool CreateServer(const Security::ContextPointer &, const Comm::ConnectionPointer &, const char *squidCtx); -void SetSessionCallbacks(Security::ContextPtr); +void SetSessionCallbacks(Security::ContextPointer &); extern Ipc::MemMap *SessionCache; extern const char *SessionCacheName; /// initialize a TLS server context with OpenSSL specific settings -bool InitServerContext(const Security::ContextPointer &, AnyP::PortCfg &); +bool InitServerContext(Security::ContextPointer &, AnyP::PortCfg &); /// initialize a TLS client context with OpenSSL specific settings -bool InitClientContext(Security::ContextPtr &, Security::PeerOptions &, long options, long flags); +bool InitClientContext(Security::ContextPointer &, Security::PeerOptions &, long options, long flags); } //namespace Ssl @@ -257,7 +229,7 @@ \ingroup ServerProtocolSSLAPI * Decide on the kind of certificate and generate a CA- or self-signed one */ -Security::ContextPtr generateSslContext(CertificateProperties const &properties, AnyP::PortCfg &port); +Security::ContextPointer generateSslContext(CertificateProperties const &properties, AnyP::PortCfg &port); /** \ingroup ServerProtocolSSLAPI @@ -266,32 +238,32 @@ \param properties Check if the context certificate matches the given properties \return true if the contexts certificate is valid, false otherwise */ -bool verifySslCertificate(Security::ContextPtr sslContext, CertificateProperties const &properties); +bool verifySslCertificate(Security::ContextPointer &, CertificateProperties const &); /** \ingroup ServerProtocolSSLAPI * Read private key and certificate from memory and generate SSL context * using their. */ -Security::ContextPtr generateSslContextUsingPkeyAndCertFromMemory(const char * data, AnyP::PortCfg &port); +Security::ContextPointer generateSslContextUsingPkeyAndCertFromMemory(const char * data, AnyP::PortCfg &port); /** \ingroup ServerProtocolSSLAPI * Create an SSL context using the provided certificate and key */ -Security::ContextPtr createSSLContext(Security::CertPointer & x509, Ssl::EVP_PKEY_Pointer & pkey, AnyP::PortCfg &port); +Security::ContextPointer createSSLContext(Security::CertPointer & x509, Ssl::EVP_PKEY_Pointer & pkey, AnyP::PortCfg &port); /** \ingroup ServerProtocolSSLAPI * Chain signing certificate and chained certificates to an SSL Context */ -void chainCertificatesToSSLContext(SSL_CTX *sslContext, AnyP::PortCfg &port); +void chainCertificatesToSSLContext(Security::ContextPointer &, AnyP::PortCfg &); /** \ingroup ServerProtocolSSLAPI * Configure a previously unconfigured SSL context object. */ -void configureUnconfiguredSslContext(SSL_CTX *sslContext, Ssl::CertSignAlgorithm signAlgorithm,AnyP::PortCfg &port); +void configureUnconfiguredSslContext(Security::ContextPointer &, Ssl::CertSignAlgorithm signAlgorithm, AnyP::PortCfg &); /** \ingroup ServerProtocolSSLAPI @@ -311,7 +283,7 @@ \ingroup ServerProtocolSSLAPI * Adds the certificates in certList to the certificate chain of the SSL context */ -void addChainToSslContext(Security::ContextPtr sslContext, STACK_OF(X509) *certList); +void addChainToSslContext(Security::ContextPointer &, STACK_OF(X509) *certList); /** \ingroup ServerProtocolSSLAPI diff -u -r -N squid-4.0.14/src/stat.cc squid-4.0.15/src/stat.cc --- squid-4.0.14/src/stat.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/stat.cc 2016-10-10 08:05:51.000000000 +1300 @@ -79,7 +79,6 @@ /* LOCALS */ static const char *describeStatuses(const StoreEntry *); -static const char *describeTimestamps(const StoreEntry *); static void statAvgTick(void *notused); static void statAvgDump(StoreEntry *, int minutes, int hours); #if STAT_GRAPHS @@ -330,18 +329,6 @@ return buf; } -static const char * -describeTimestamps(const StoreEntry * entry) -{ - LOCAL_ARRAY(char, buf, 256); - snprintf(buf, 256, "LV:%-9d LU:%-9d LM:%-9d EX:%-9d", - (int) entry->timestamp, - (int) entry->lastref, - (int) entry->lastmod, - (int) entry->expires); - return buf; -} - static void statStoreEntry(MemBuf * mb, StoreEntry * e) { @@ -349,7 +336,7 @@ mb->appendf("KEY %s\n", e->getMD5Text()); mb->appendf("\t%s\n", describeStatuses(e)); mb->appendf("\t%s\n", storeEntryFlags(e)); - mb->appendf("\t%s\n", describeTimestamps(e)); + mb->appendf("\t%s\n", e->describeTimestamps()); mb->appendf("\t%d locks, %d clients, %d refs\n", (int) e->locks(), storePendingNClients(e), (int) e->refcount); mb->appendf("\tSwap Dir %d, File %#08X\n", e->swap_dirn, e->swap_filen); diff -u -r -N squid-4.0.14/src/store/Disks.cc squid-4.0.15/src/store/Disks.cc --- squid-4.0.14/src/store/Disks.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/store/Disks.cc 2016-10-10 08:05:51.000000000 +1300 @@ -582,7 +582,7 @@ // Check for store_dirs_rebuilding because fatal() often calls us in early // initialization phases, before store log is initialized and ready. Also, - // some stores probably do not support log cleanup during Store rebuilding. + // some stores do not support log cleanup during Store rebuilding. if (StoreController::store_dirs_rebuilding) { debugs(20, DBG_IMPORTANT, "Not currently OK to rewrite swap log."); debugs(20, DBG_IMPORTANT, "storeDirWriteCleanLogs: Operation aborted."); diff -u -r -N squid-4.0.14/src/store/id_rewriters/file/storeid_file_rewrite.8 squid-4.0.15/src/store/id_rewriters/file/storeid_file_rewrite.8 --- squid-4.0.14/src/store/id_rewriters/file/storeid_file_rewrite.8 2016-09-09 03:31:21.000000000 +1200 +++ squid-4.0.15/src/store/id_rewriters/file/storeid_file_rewrite.8 2016-10-10 11:56:34.000000000 +1300 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) +.\" Automatically generated by Pod::Man 4.08 (Pod::Simple 3.32) .\" .\" Standard preamble: .\" ======================================================================== @@ -46,7 +46,7 @@ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" -.\" If the F register is turned on, we'll generate index entries on stderr for +.\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. @@ -54,20 +54,16 @@ .\" Avoid warning from groff about undefined register 'F'. .de IX .. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" +.if !\nF .nr F 0 +.if \nF>0 \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" .. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 . \} .\} -.rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. @@ -133,7 +129,7 @@ .\" ======================================================================== .\" .IX Title "STOREID_FILE_REWRITE 8" -.TH STOREID_FILE_REWRITE 8 "2016-09-08" "perl v5.22.2" "User Contributed Perl Documentation" +.TH STOREID_FILE_REWRITE 8 "2016-10-09" "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 @@ -213,7 +209,7 @@ Report ideas for new improvements to the \fISquid Developers mailing list .SH "SEE ALSO" .IX Header "SEE ALSO" -squid (8), \s-1GPL \\fIs0\fR\|(7), +squid (8), \s-1GPL\s0 (7), .PP The Squid wiki http://wiki.squid\-cache.org/Features/StoreID .PP diff -u -r -N squid-4.0.14/src/store.cc squid-4.0.15/src/store.cc --- squid-4.0.14/src/store.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/store.cc 2016-10-10 08:05:51.000000000 +1300 @@ -331,7 +331,7 @@ timestamp(-1), lastref(-1), expires(-1), - lastmod(-1), + lastModified_(-1), swap_file_sz(0), refcount(0), flags(0), @@ -1564,12 +1564,17 @@ else exp = reply->expires; - if (lastmod == reply->last_modified && timestamp == served_date && expires == exp) - return false; + if (timestamp == served_date && expires == exp) { + // if the reply lacks LMT, then we now know that our effective + // LMT (i.e., timestamp) will stay the same, otherwise, old and + // new modification times must match + if (reply->last_modified < 0 || reply->last_modified == lastModified()) + return false; // nothing has changed + } expires = exp; - lastmod = reply->last_modified; + lastModified_ = reply->last_modified; timestamp = served_date; @@ -1604,7 +1609,7 @@ debugs(20, l, "StoreEntry->timestamp: " << timestamp); debugs(20, l, "StoreEntry->lastref: " << lastref); debugs(20, l, "StoreEntry->expires: " << expires); - debugs(20, l, "StoreEntry->lastmod: " << lastmod); + debugs(20, l, "StoreEntry->lastModified_: " << lastModified_); debugs(20, l, "StoreEntry->swap_file_sz: " << swap_file_sz); debugs(20, l, "StoreEntry->refcount: " << refcount); debugs(20, l, "StoreEntry->flags: " << storeEntryFlags(this)); @@ -1742,7 +1747,7 @@ mem_obj->reset(); HttpReply *rep = (HttpReply *) getReply(); // bypass const rep->reset(); - expires = lastmod = timestamp = -1; + expires = lastModified_ = timestamp = -1; } /* @@ -1949,13 +1954,10 @@ } bool -StoreEntry::modifiedSince(HttpRequest * request) const +StoreEntry::modifiedSince(const time_t ims, const int imslen) const { int object_length; - time_t mod_time = lastmod; - - if (mod_time < 0) - mod_time = timestamp; + const time_t mod_time = lastModified(); debugs(88, 3, "modifiedSince: '" << url() << "'"); @@ -1970,16 +1972,16 @@ if (object_length < 0) object_length = contentLen(); - if (mod_time > request->ims) { + if (mod_time > ims) { debugs(88, 3, "--> YES: entry newer than client"); return true; - } else if (mod_time < request->ims) { + } else if (mod_time < ims) { debugs(88, 3, "--> NO: entry older than client"); return false; - } else if (request->imslen < 0) { + } else if (imslen < 0) { debugs(88, 3, "--> NO: same LMT, no client length"); return false; - } else if (request->imslen == object_length) { + } else if (imslen == object_length) { debugs(88, 3, "--> NO: same LMT, same length"); return false; } else { @@ -2069,6 +2071,18 @@ return true; } +const char * +StoreEntry::describeTimestamps() const +{ + LOCAL_ARRAY(char, buf, 256); + snprintf(buf, 256, "LV:%-9d LU:%-9d LM:%-9d EX:%-9d", + static_cast(timestamp), + static_cast(lastref), + static_cast(lastModified_), + static_cast(expires)); + return buf; +} + std::ostream &operator <<(std::ostream &os, const StoreEntry &e) { os << "e:"; diff -u -r -N squid-4.0.14/src/Store.h squid-4.0.15/src/Store.h --- squid-4.0.14/src/Store.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/Store.h 2016-10-10 08:05:51.000000000 +1300 @@ -131,7 +131,16 @@ void delayAwareRead(const Comm::ConnectionPointer &conn, char *buf, int len, AsyncCall::Pointer callback); void setNoDelay (bool const); - bool modifiedSince(HttpRequest * request) const; + void lastModified(const time_t when) { lastModified_ = when; } + /// \returns entry's 'effective' modification time + time_t lastModified() const { + // may still return -1 if timestamp is not set + return lastModified_ < 0 ? timestamp : lastModified_; + } + /// \returns a formatted string with entry's timestamps + const char *describeTimestamps() const; + // TODO: consider removing currently unsupported imslen parameter + bool modifiedSince(const time_t ims, const int imslen = -1) const; /// has ETag matching at least one of the If-Match etags bool hasIfMatchEtag(const HttpRequest &request) const; /// has ETag matching at least one of the If-None-Match etags @@ -148,7 +157,9 @@ time_t timestamp; time_t lastref; time_t expires; - time_t lastmod; +private: + time_t lastModified_; ///< received Last-Modified value or -1; use lastModified() +public: uint64_t swap_file_sz; uint16_t refcount; uint16_t flags; diff -u -r -N squid-4.0.14/src/store_rebuild.cc squid-4.0.15/src/store_rebuild.cc --- squid-4.0.14/src/store_rebuild.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/store_rebuild.cc 2016-10-10 08:05:51.000000000 +1300 @@ -256,7 +256,7 @@ what->timestamp = tmp->timestamp; what->lastref = tmp->lastref; what->expires = tmp->expires; - what->lastmod = tmp->lastmod; + what->lastModified(tmp->lastmod); what->swap_file_sz = tmp->swap_file_sz; what->refcount = tmp->refcount; what->flags = tmp->flags; diff -u -r -N squid-4.0.14/src/tests/stub_client_side.cc squid-4.0.15/src/tests/stub_client_side.cc --- squid-4.0.14/src/tests/stub_client_side.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/tests/stub_client_side.cc 2016-10-10 08:05:51.000000000 +1300 @@ -42,7 +42,7 @@ #if USE_OPENSSL void ConnStateData::httpsPeeked(Comm::ConnectionPointer) STUB void ConnStateData::getSslContextStart() STUB -void ConnStateData::getSslContextDone(Security::ContextPtr, bool) STUB +void ConnStateData::getSslContextDone(Security::ContextPointer &, bool) STUB void ConnStateData::sslCrtdHandleReplyWrapper(void *, const Helper::Reply &) STUB void ConnStateData::sslCrtdHandleReply(const Helper::Reply &) STUB void ConnStateData::switchToHttps(HttpRequest *, Ssl::BumpMode) STUB diff -u -r -N squid-4.0.14/src/tests/stub_libsecurity.cc squid-4.0.15/src/tests/stub_libsecurity.cc --- squid-4.0.14/src/tests/stub_libsecurity.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/tests/stub_libsecurity.cc 2016-10-10 08:05:51.000000000 +1300 @@ -19,7 +19,7 @@ namespace Security { bool BlindPeerConnector::initialize(Security::SessionPointer &) STUB_RETVAL(false) -Security::ContextPtr BlindPeerConnector::getSslContext() STUB_RETVAL(nullptr) +Security::ContextPointer BlindPeerConnector::getTlsContext() STUB_RETVAL(Security::ContextPointer()) void BlindPeerConnector::noteNegotiationDone(ErrorState *) STUB } @@ -33,7 +33,7 @@ #include "security/NegotiationHistory.h" Security::NegotiationHistory::NegotiationHistory() STUB -void Security::NegotiationHistory::retrieveNegotiatedInfo(Security::SessionPtr) STUB +void Security::NegotiationHistory::retrieveNegotiatedInfo(const Security::SessionPointer &) STUB void Security::NegotiationHistory::retrieveParsedInfo(Security::TlsDetails::Pointer const &) STUB const char *Security::NegotiationHistory::cipherName() const STUB const char *Security::NegotiationHistory::printTlsVersion(AnyP::ProtocolVersion const &v) const STUB @@ -60,7 +60,7 @@ void PeerConnector::noteWantRead() STUB void PeerConnector::noteWantWrite() STUB void PeerConnector::noteNegotiationError(const int, const int, const int) STUB -// virtual Security::ContextPtr getSslContext() = 0; +// virtual Security::ContextPointer getTlsContext() = 0; void PeerConnector::bail(ErrorState *) STUB void PeerConnector::callBack() STUB void PeerConnector::recordNegotiationDetails() STUB @@ -69,11 +69,11 @@ #include "security/PeerOptions.h" Security::PeerOptions Security::ProxyOutgoingConfig; void Security::PeerOptions::parse(char const*) STUB -Security::ContextPtr Security::PeerOptions::createClientContext(bool) STUB_RETVAL(NULL) +Security::ContextPointer Security::PeerOptions::createClientContext(bool) STUB_RETVAL(Security::ContextPointer()) void Security::PeerOptions::updateTlsVersionLimits() STUB -Security::ContextPtr Security::PeerOptions::createBlankContext() const STUB -void Security::PeerOptions::updateContextCa(Security::ContextPtr &) STUB -void Security::PeerOptions::updateContextCrl(Security::ContextPtr &) STUB +Security::ContextPointer Security::PeerOptions::createBlankContext() const STUB_RETVAL(Security::ContextPointer()) +void Security::PeerOptions::updateContextCa(Security::ContextPointer &) STUB +void Security::PeerOptions::updateContextCrl(Security::ContextPointer &) STUB void Security::PeerOptions::dumpCfg(Packable*, char const*) const STUB long Security::PeerOptions::parseOptions() STUB_RETVAL(0) long Security::PeerOptions::parseFlags() STUB_RETVAL(0) @@ -83,9 +83,9 @@ //Security::ServerOptions::ServerOptions(const Security::ServerOptions &) STUB void Security::ServerOptions::parse(const char *) STUB void Security::ServerOptions::dumpCfg(Packable *, const char *) const STUB -Security::ContextPtr Security::ServerOptions::createBlankContext() const STUB +Security::ContextPointer Security::ServerOptions::createBlankContext() const STUB_RETVAL(Security::ContextPointer()) bool Security::ServerOptions::createStaticServerContext(AnyP::PortCfg &) STUB_RETVAL(false) -void Security::ServerOptions::updateContextEecdh(Security::ContextPtr &) STUB +void Security::ServerOptions::updateContextEecdh(Security::ContextPointer &) STUB #include "security/Session.h" namespace Security { diff -u -r -N squid-4.0.14/src/tests/stub_libsslsquid.cc squid-4.0.15/src/tests/stub_libsslsquid.cc --- squid-4.0.14/src/tests/stub_libsslsquid.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/tests/stub_libsslsquid.cc 2016-10-10 08:05:51.000000000 +1300 @@ -41,22 +41,17 @@ //Ssl::GlobalContextStorage Ssl::TheGlobalContextStorage; #include "ssl/ErrorDetail.h" -Ssl::ssl_error_t parseErrorString(const char *name) STUB_RETVAL(0) -//const char *Ssl::getErrorName(ssl_error_t value) STUB_RETVAL(NULL) -Ssl::ErrorDetail::ErrorDetail(ssl_error_t err_no, X509 *, X509 *, const char *) STUB +Security::ErrorCode parseErrorString(const char *name) STUB_RETVAL(0) +//const char *Ssl::getErrorName(Security::ErrorCode value) STUB_RETVAL(NULL) +Ssl::ErrorDetail::ErrorDetail(Security::ErrorCode, X509 *, X509 *, const char *) STUB Ssl::ErrorDetail::ErrorDetail(ErrorDetail const &) STUB const String & Ssl::ErrorDetail::toString() const STUB_RETSTATREF(String) #include "ssl/support.h" namespace Ssl { -//CertError::CertError(ssl_error_t anErr, X509 *aCert) STUB -//CertError::CertError(CertError const &err) STUB -CertError & CertError::operator = (const CertError &old) STUB_RETVAL(*this) -bool CertError::operator == (const CertError &ce) const STUB_RETVAL(false) -bool CertError::operator != (const CertError &ce) const STUB_RETVAL(false) -bool InitServerContext(const Security::ContextPointer &, AnyP::PortCfg &) STUB_RETVAL(false) -bool InitClientContext(Security::ContextPtr &, Security::PeerOptions &, long, const char *) STUB_RETVAL(false) +bool InitServerContext(Security::ContextPointer &, AnyP::PortCfg &) STUB_RETVAL(false) +bool InitClientContext(Security::ContextPointer &, Security::PeerOptions &, long, const char *) STUB_RETVAL(false) } // namespace Ssl int ssl_read_method(int, char *, int) STUB_RETVAL(0) int ssl_write_method(int, const char *, int) STUB_RETVAL(0) @@ -73,10 +68,10 @@ //GETX509ATTRIBUTE GetX509Fingerprint; const char *BumpModeStr[] = {""}; bool generateUntrustedCert(Security::CertPointer & untrustedCert, EVP_PKEY_Pointer & untrustedPkey, Security::CertPointer const & cert, EVP_PKEY_Pointer const & pkey) STUB_RETVAL(false) -Security::ContextPtr generateSslContext(CertificateProperties const &properties, AnyP::PortCfg &port) STUB_RETVAL(NULL) -bool verifySslCertificate(Security::ContextPtr sslContext, CertificateProperties const &properties) STUB_RETVAL(false) -Security::ContextPtr generateSslContextUsingPkeyAndCertFromMemory(const char * data, AnyP::PortCfg &port) STUB_RETVAL(NULL) -void addChainToSslContext(Security::ContextPtr sslContext, STACK_OF(X509) *certList) STUB +Security::ContextPointer generateSslContext(CertificateProperties const &, AnyP::PortCfg &) STUB_RETVAL(Security::ContextPointer()) +bool verifySslCertificate(Security::ContextPointer &, CertificateProperties const &) STUB_RETVAL(false) +Security::ContextPointer generateSslContextUsingPkeyAndCertFromMemory(const char *, AnyP::PortCfg &) STUB_RETVAL(Security::ContextPointer()) +void addChainToSslContext(Security::ContextPointer &, STACK_OF(X509) *) STUB void readCertChainAndPrivateKeyFromFiles(Security::CertPointer & cert, EVP_PKEY_Pointer & pkey, X509_STACK_Pointer & chain, char const * certFilename, char const * keyFilename) STUB int matchX509CommonNames(X509 *peer_cert, void *check_data, int (*check_func)(void *check_data, ASN1_STRING *cn_data)) STUB_RETVAL(0) bool checkX509ServerValidity(X509 *cert, const char *server) STUB_RETVAL(false) diff -u -r -N squid-4.0.14/src/tests/stub_SBuf.cc squid-4.0.15/src/tests/stub_SBuf.cc --- squid-4.0.14/src/tests/stub_SBuf.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/tests/stub_SBuf.cc 2016-10-10 08:05:51.000000000 +1300 @@ -63,7 +63,6 @@ SBuf::size_type SBuf::rfind(const SBuf &str, size_type endPos) const STUB_RETVAL(SBuf::npos) SBuf::size_type SBuf::findFirstOf(const CharacterSet &set, size_type startPos) const STUB_RETVAL(SBuf::npos) SBuf::size_type SBuf::findFirstNotOf(const CharacterSet &set, size_type startPos) const STUB_RETVAL(SBuf::npos) -int SBuf::scanf(const char *format, ...) STUB_RETVAL(-1) void SBuf::toLower() STUB void SBuf::toUpper() STUB diff -u -r -N squid-4.0.14/src/tests/stub_store.cc squid-4.0.15/src/tests/stub_store.cc --- squid-4.0.14/src/tests/stub_store.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/tests/stub_store.cc 2016-10-10 08:05:51.000000000 +1300 @@ -68,7 +68,7 @@ int StoreEntry::checkTooSmall() STUB_RETVAL(0) void StoreEntry::delayAwareRead(const Comm::ConnectionPointer&, char *buf, int len, AsyncCall::Pointer callback) STUB void StoreEntry::setNoDelay (bool const) STUB -bool StoreEntry::modifiedSince(HttpRequest * request) const STUB_RETVAL(false) +bool StoreEntry::modifiedSince(const time_t, const int) const STUB_RETVAL(false) bool StoreEntry::hasIfMatchEtag(const HttpRequest &request) const STUB_RETVAL(false) bool StoreEntry::hasIfNoneMatchEtag(const HttpRequest &request) const STUB_RETVAL(false) Store::Disk &StoreEntry::disk() const STUB_RETREF(Store::Disk) diff -u -r -N squid-4.0.14/src/tests/testHttp1Parser.cc squid-4.0.15/src/tests/testHttp1Parser.cc --- squid-4.0.14/src/tests/testHttp1Parser.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/tests/testHttp1Parser.cc 2016-10-10 08:05:51.000000000 +1300 @@ -39,8 +39,6 @@ Config.maxRequestHeaderSize = 1024; // XXX: unit test the RequestParser handling of this limit } -#if __cplusplus >= 201103L - struct resultSet { bool parsed; bool needsMore; @@ -119,7 +117,6 @@ CPPUNIT_ASSERT_EQUAL(expect.parserState, output.parsingStage_); CPPUNIT_ASSERT_EQUAL(expect.suffixSz, output.buf_.length()); } -#endif /* __cplusplus >= 200103L */ void testHttp1Parser::testParserConstruct() @@ -235,7 +232,7 @@ input.clear(); } - // RFC 7230 : future version full-request + // RFC 7230 : future 1.x version full-request { input.append("GET / HTTP/1.2\r\n", 16); struct resultSet expect = { @@ -253,25 +250,45 @@ input.clear(); } - // RFC 7230 : future versions do not use request-line syntax + // RFC 7230 : future versions do not use 1.x message syntax. + // However, it is still valid syntax for the single-digit forms + // to appear. The parser we are testing should accept them. { input.append("GET / HTTP/2.0\r\n", 16); struct resultSet expectA = { - .parsed = false, + .parsed = true, .needsMore = false, - .parserState = Http1::HTTP_PARSE_MIME, - .status = Http::scBadRequest, - .suffixSz = input.length(), - .method = HttpRequestMethod(), + .parserState = Http1::HTTP_PARSE_DONE, + .status = Http::scOkay, + .suffixSz = 0, + .method = HttpRequestMethod(Http::METHOD_GET), .uri = "/", - .version = AnyP::ProtocolVersion() + .version = AnyP::ProtocolVersion(AnyP::PROTO_HTTP,2,0) }; output.clear(); testResults(__LINE__, input, output, expectA); input.clear(); - input.append("GET / HTTP/10.12\r\n", 18); + input.append("GET / HTTP/9.9\r\n", 16); struct resultSet expectB = { + .parsed = true, + .needsMore = false, + .parserState = Http1::HTTP_PARSE_DONE, + .status = Http::scOkay, + .suffixSz = 0, + .method = HttpRequestMethod(Http::METHOD_GET), + .uri = "/", + .version = AnyP::ProtocolVersion(AnyP::PROTO_HTTP,9,9) + }; + output.clear(); + testResults(__LINE__, input, output, expectB); + input.clear(); + } + + // RFC 7230 : future versions >= 10.0 are invalid syntax + { + input.append("GET / HTTP/10.12\r\n", 18); + struct resultSet expect = { .parsed = false, .needsMore = false, .parserState = Http1::HTTP_PARSE_MIME, @@ -282,7 +299,7 @@ .version = AnyP::ProtocolVersion() }; output.clear(); - testResults(__LINE__, input, output, expectB); + testResults(__LINE__, input, output, expect); input.clear(); } diff -u -r -N squid-4.0.14/src/tests/testSBuf.cc squid-4.0.15/src/tests/testSBuf.cc --- squid-4.0.14/src/tests/testSBuf.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/tests/testSBuf.cc 2016-10-10 08:05:51.000000000 +1300 @@ -754,22 +754,6 @@ } void -testSBuf::testScanf() -{ - SBuf s1; - char s[128]; - int i; - float f; - int rv; - s1.assign("string , 123 , 123.50"); - rv=s1.scanf("%s , %d , %f",s,&i,&f); - CPPUNIT_ASSERT_EQUAL(3,rv); - CPPUNIT_ASSERT_EQUAL(0,strcmp(s,"string")); - CPPUNIT_ASSERT_EQUAL(123,i); - CPPUNIT_ASSERT_EQUAL(static_cast(123.5),f); -} - -void testSBuf::testCopy() { char buf[40]; //shorter than literal() diff -u -r -N squid-4.0.14/src/tests/testSBuf.h squid-4.0.15/src/tests/testSBuf.h --- squid-4.0.14/src/tests/testSBuf.h 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/tests/testSBuf.h 2016-10-10 08:05:51.000000000 +1300 @@ -45,7 +45,6 @@ CPPUNIT_TEST( testFindFirstOf ); CPPUNIT_TEST( testFindFirstNotOf ); CPPUNIT_TEST( testPrintf ); - CPPUNIT_TEST( testScanf ); CPPUNIT_TEST( testCopy ); CPPUNIT_TEST( testStringOps ); CPPUNIT_TEST( testGrow ); @@ -67,7 +66,6 @@ void testAppendStdString(); void testAppendf(); void testPrintf(); - void testScanf(); void testSubscriptOp(); void testSubscriptOpFail(); void testDumpStats(); diff -u -r -N squid-4.0.14/src/tests/testStoreController.cc squid-4.0.15/src/tests/testStoreController.cc --- squid-4.0.14/src/tests/testStoreController.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/tests/testStoreController.cc 2016-10-10 08:05:51.000000000 +1300 @@ -111,7 +111,7 @@ e->lastref = squid_curtime; e->timestamp = squid_curtime; e->expires = squid_curtime; - e->lastmod = squid_curtime; + e->lastModified(squid_curtime); e->refcount = 1; EBIT_CLR(e->flags, RELEASE_REQUEST); EBIT_CLR(e->flags, KEY_PRIVATE); diff -u -r -N squid-4.0.14/src/tests/testStoreHashIndex.cc squid-4.0.15/src/tests/testStoreHashIndex.cc --- squid-4.0.14/src/tests/testStoreHashIndex.cc 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/src/tests/testStoreHashIndex.cc 2016-10-10 08:05:51.000000000 +1300 @@ -89,7 +89,7 @@ e->lastref = squid_curtime; e->timestamp = squid_curtime; e->expires = squid_curtime; - e->lastmod = squid_curtime; + e->lastModified(squid_curtime); e->refcount = 1; EBIT_CLR(e->flags, RELEASE_REQUEST); EBIT_CLR(e->flags, KEY_PRIVATE); diff -u -r -N squid-4.0.14/test-suite/stub_SBuf.cc squid-4.0.15/test-suite/stub_SBuf.cc --- squid-4.0.14/test-suite/stub_SBuf.cc 2016-09-09 03:32:58.000000000 +1200 +++ squid-4.0.15/test-suite/stub_SBuf.cc 2016-10-10 12:02:05.000000000 +1300 @@ -63,7 +63,6 @@ SBuf::size_type SBuf::rfind(const SBuf &str, size_type endPos) const STUB_RETVAL(SBuf::npos) SBuf::size_type SBuf::findFirstOf(const CharacterSet &set, size_type startPos) const STUB_RETVAL(SBuf::npos) SBuf::size_type SBuf::findFirstNotOf(const CharacterSet &set, size_type startPos) const STUB_RETVAL(SBuf::npos) -int SBuf::scanf(const char *format, ...) STUB_RETVAL(-1) void SBuf::toLower() STUB void SBuf::toUpper() STUB diff -u -r -N squid-4.0.14/tools/helper-mux/helper-mux.8 squid-4.0.15/tools/helper-mux/helper-mux.8 --- squid-4.0.14/tools/helper-mux/helper-mux.8 2016-09-09 03:33:04.000000000 +1200 +++ squid-4.0.15/tools/helper-mux/helper-mux.8 2016-10-10 12:02:23.000000000 +1300 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) +.\" Automatically generated by Pod::Man 4.08 (Pod::Simple 3.32) .\" .\" Standard preamble: .\" ======================================================================== @@ -46,7 +46,7 @@ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" -.\" If the F register is turned on, we'll generate index entries on stderr for +.\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. @@ -54,20 +54,16 @@ .\" Avoid warning from groff about undefined register 'F'. .de IX .. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" +.if !\nF .nr F 0 +.if \nF>0 \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" .. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 . \} .\} -.rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. @@ -133,7 +129,7 @@ .\" ======================================================================== .\" .IX Title "HELPER-MUX 8" -.TH HELPER-MUX 8 "2016-09-08" "perl v5.22.2" "User Contributed Perl Documentation" +.TH HELPER-MUX 8 "2016-10-09" "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.14/tools/systemd/squid.service squid-4.0.15/tools/systemd/squid.service --- squid-4.0.14/tools/systemd/squid.service 2016-09-09 02:12:03.000000000 +1200 +++ squid-4.0.15/tools/systemd/squid.service 2016-10-10 08:05:51.000000000 +1300 @@ -13,6 +13,7 @@ [Service] Type=forking PIDFile=/var/run/squid.pid +ExecStartPre=/usr/sbin/squid --foreground -z ExecStart=/usr/sbin/squid -sYC ExecReload=/bin/kill -HUP $MAINPID KillMode=mixed