diff -u -r -N squid-4.0.12/aclocal.m4 squid-4.0.13/aclocal.m4
--- squid-4.0.12/aclocal.m4 2016-07-02 01:27:31.000000000 +1200
+++ squid-4.0.13/aclocal.m4 2016-08-06 00:53:48.000000000 +1200
@@ -744,7 +744,6 @@
cat <<_LT_EOF >> "$cfgfile"
#! $SHELL
# Generated automatically by $as_me ($PACKAGE) $VERSION
-# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
# NOTE: Changes made to this file will be lost: look at ltmain.sh.
# Provide generalized library-building support services.
diff -u -r -N squid-4.0.12/cfgaux/ltmain.sh squid-4.0.13/cfgaux/ltmain.sh
--- squid-4.0.12/cfgaux/ltmain.sh 2016-07-02 01:27:42.000000000 +1200
+++ squid-4.0.13/cfgaux/ltmain.sh 2016-08-06 00:53:58.000000000 +1200
@@ -31,7 +31,7 @@
PROGRAM=libtool
PACKAGE=libtool
-VERSION="2.4.6 Debian-2.4.6-0.1"
+VERSION="2.4.6 Debian-2.4.6-1"
package_revision=2.4.6
@@ -1977,7 +1977,7 @@
# End:
# Set a version string.
-scriptversion='(GNU libtool) 2.4.6'
+scriptversion='(GNU libtool) 2.4.6 Debian-2.4.6-1'
# func_echo ARG...
@@ -2068,7 +2068,7 @@
compiler: $LTCC
compiler flags: $LTCFLAGS
linker: $LD (gnu? $with_gnu_ld)
- version: $progname (GNU libtool) 2.4.6
+ version: $progname $scriptversion
automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q`
autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q`
diff -u -r -N squid-4.0.12/ChangeLog squid-4.0.13/ChangeLog
--- squid-4.0.12/ChangeLog 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/ChangeLog 2016-08-06 00:52:55.000000000 +1200
@@ -1,3 +1,21 @@
+Changes to squid-4.0.13 (05 Aug 2016):
+
+ - Regression Bug 4540: revert r14720 buffer update
+ - Bug 4555: Minor improvements to error pages CSS
+ - Bug 4551: fix exceptions in new chunked decoder
+ - Bug 4311: support collapse for internal revalidation requests (SMP-unaware caches)
+ - Fix Certificate Validator buffer-overflow crashes Squid
+ - Fix some failed transactions not being logged
+ - Fix segfault via Ftp::Client::readControlReply().
+ - basic_db_auth: add support for unsalted SHA1 passwords
+ - kerberos_ldap_group: add support for SSL/TLS connection to an LDAP server
+ - TLS: Add missing 'tls' option for cache_peer
+ - TLS: Do not hang when 'connector' fails
+ - TLS: Add support for fetching missing certificates
+ - Remove XSTD_USE_LIBLTDL, which has not been needed in a long while
+ - ... and many code polishing updates
+ - ... and some documentation updates
+
Changes to squid-4.0.12 (01 Jul 2016):
- Regression Fix: shell issues with require_smblib definition
diff -u -r -N squid-4.0.12/configure squid-4.0.13/configure
--- squid-4.0.12/configure 2016-07-02 01:29:18.000000000 +1200
+++ squid-4.0.13/configure 2016-08-06 00:55:28.000000000 +1200
@@ -1,7 +1,7 @@
#! /bin/sh
# From configure.ac Revision.
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for Squid Web Proxy 4.0.12.
+# Generated by GNU Autoconf 2.69 for Squid Web Proxy 4.0.13.
#
# Report bugs to .
#
@@ -595,8 +595,8 @@
# Identity of this package.
PACKAGE_NAME='Squid Web Proxy'
PACKAGE_TARNAME='squid'
-PACKAGE_VERSION='4.0.12'
-PACKAGE_STRING='Squid Web Proxy 4.0.12'
+PACKAGE_VERSION='4.0.13'
+PACKAGE_STRING='Squid Web Proxy 4.0.13'
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.12 to adapt to many kinds of systems.
+\`configure' configures Squid Web Proxy 4.0.13 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.12:";;
+ short | recursive ) echo "Configuration of Squid Web Proxy 4.0.13:";;
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.12
+Squid Web Proxy configure 4.0.13
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.12, which was
+It was created by Squid Web Proxy $as_me 4.0.13, 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.12'
+ VERSION='4.0.13'
cat >>confdefs.h <<_ACEOF
@@ -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.12, which was
+This file was extended by Squid Web Proxy $as_me 4.0.13, 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.12
+Squid Web Proxy config.status 4.0.13
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
@@ -43996,7 +43996,6 @@
cat <<_LT_EOF >> "$cfgfile"
#! $SHELL
# Generated automatically by $as_me ($PACKAGE) $VERSION
-# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
# NOTE: Changes made to this file will be lost: look at ltmain.sh.
# Provide generalized library-building support services.
diff -u -r -N squid-4.0.12/configure.ac squid-4.0.13/configure.ac
--- squid-4.0.12/configure.ac 2016-07-02 01:29:17.000000000 +1200
+++ squid-4.0.13/configure.ac 2016-08-06 00:55:28.000000000 +1200
@@ -5,7 +5,7 @@
## Please see the COPYING and CONTRIBUTORS files for details.
##
-AC_INIT([Squid Web Proxy],[4.0.12],[http://bugs.squid-cache.org/],[squid])
+AC_INIT([Squid Web Proxy],[4.0.13],[http://bugs.squid-cache.org/],[squid])
AC_PREREQ(2.61)
AC_CONFIG_HEADERS([include/autoconf.h])
AC_CONFIG_AUX_DIR(cfgaux)
diff -u -r -N squid-4.0.12/doc/release-notes/release-4.html squid-4.0.13/doc/release-notes/release-4.html
--- squid-4.0.12/doc/release-notes/release-4.html 2016-07-02 02:22:44.000000000 +1200
+++ squid-4.0.13/doc/release-notes/release-4.html 2016-08-06 02:24:35.000000000 +1200
@@ -2,10 +2,10 @@
- Squid 4.0.12 release notes
+ Squid 4.0.13 release notes
-Squid 4.0.12 release notes
+Squid 4.0.13 release notes
Squid Developers
@@ -61,7 +61,7 @@
-The Squid Team are pleased to announce the release of Squid-4.0.12 for testing.
+The Squid Team are pleased to announce the release of Squid-4.0.13 for testing.
This new release is available for download from
http://www.squid-cache.org/Versions/v4/ or the
mirrors.
@@ -305,6 +305,12 @@
+- access_log
-
+
TCP accept(2) errors logged with URI error:accept-client-connection.
+Unused connections received in http_port or https_port
+or transactions terminated before reading[parsing] request headers
+logged with URI error:transaction-end-before-headers.
+
- acl
-
New -m flag for note ACL to match substrings.
@@ -315,6 +321,8 @@
- cache_peer
-
New option auth-no-keytab to let GSSAPI implementation determine
which Kerberos credentials to use, instead of specifying a keytab.
+Replaced option ssl with tls. Use of any
+tls- prefixed options implies tls is enabled.
New option tls-min-version=1.N to set minimum TLS version allowed.
New option tls-default-ca replaces sslflags=NO_DEFAULT_CA
New option tls-no-npn to disable sending TLS NPN extension.
@@ -322,7 +330,8 @@
have been removed.
Removed sslversion= option. Use tls-options= instead.
Manual squid.conf update may be required on upgrade.
-Replaced sslcafile= with tls-cafile= which takes multiple entries.
+Replaced option sslcafile= with tls-cafile=
+which takes multiple entries.
- external_acl_type
-
New parameter queue-size= to set the maximum number
@@ -534,6 +543,8 @@
Replaced by --with-cppunit=PATH.
Please prefer the default auto-detection though.
+ - XSTD_USE_LIBLTDL
-
+
Removed. Use --with-included-ltdl instead.
diff -u -r -N squid-4.0.12/errors/errorpage.css squid-4.0.13/errors/errorpage.css
--- squid-4.0.12/errors/errorpage.css 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/errors/errorpage.css 2016-08-06 00:52:55.000000000 +1200
@@ -71,12 +71,11 @@
}
pre {
- font-family:sans-serif;
}
/* special event: FTP / Gopher directory listing */
#dirmsg {
- font-family: courier;
+ font-family: courier, monospace;
color: black;
font-size: 10pt;
}
diff -u -r -N squid-4.0.12/include/version.h squid-4.0.13/include/version.h
--- squid-4.0.12/include/version.h 2016-07-02 01:29:18.000000000 +1200
+++ squid-4.0.13/include/version.h 2016-08-06 00:55:28.000000000 +1200
@@ -7,7 +7,7 @@
*/
#ifndef SQUID_RELEASE_TIME
-#define SQUID_RELEASE_TIME 1467379594
+#define SQUID_RELEASE_TIME 1470401568
#endif
/*
diff -u -r -N squid-4.0.12/libltdl/configure squid-4.0.13/libltdl/configure
--- squid-4.0.12/libltdl/configure 2016-07-02 01:40:20.000000000 +1200
+++ squid-4.0.13/libltdl/configure 2016-08-06 01:07:30.000000000 +1200
@@ -14975,7 +14975,6 @@
cat <<_LT_EOF >> "$cfgfile"
#! $SHELL
# Generated automatically by $as_me ($PACKAGE) $VERSION
-# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
# NOTE: Changes made to this file will be lost: look at ltmain.sh.
# Provide generalized library-building support services.
diff -u -r -N squid-4.0.12/libltdl/m4/libtool.m4 squid-4.0.13/libltdl/m4/libtool.m4
--- squid-4.0.12/libltdl/m4/libtool.m4 2016-07-02 01:27:43.000000000 +1200
+++ squid-4.0.13/libltdl/m4/libtool.m4 2016-08-06 00:53:59.000000000 +1200
@@ -728,7 +728,6 @@
cat <<_LT_EOF >> "$cfgfile"
#! $SHELL
# Generated automatically by $as_me ($PACKAGE) $VERSION
-# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
# NOTE: Changes made to this file will be lost: look at ltmain.sh.
# Provide generalized library-building support services.
diff -u -r -N squid-4.0.12/RELEASENOTES.html squid-4.0.13/RELEASENOTES.html
--- squid-4.0.12/RELEASENOTES.html 2016-07-02 02:22:44.000000000 +1200
+++ squid-4.0.13/RELEASENOTES.html 2016-08-06 02:24:35.000000000 +1200
@@ -2,10 +2,10 @@
- Squid 4.0.12 release notes
+ Squid 4.0.13 release notes
-Squid 4.0.12 release notes
+Squid 4.0.13 release notes
Squid Developers
@@ -61,7 +61,7 @@
-The Squid Team are pleased to announce the release of Squid-4.0.12 for testing.
+The Squid Team are pleased to announce the release of Squid-4.0.13 for testing.
This new release is available for download from
http://www.squid-cache.org/Versions/v4/ or the
mirrors.
@@ -305,6 +305,12 @@
+- access_log
-
+
TCP accept(2) errors logged with URI error:accept-client-connection.
+Unused connections received in http_port or https_port
+or transactions terminated before reading[parsing] request headers
+logged with URI error:transaction-end-before-headers.
+
- acl
-
New -m flag for note ACL to match substrings.
@@ -315,6 +321,8 @@
- cache_peer
-
New option auth-no-keytab to let GSSAPI implementation determine
which Kerberos credentials to use, instead of specifying a keytab.
+Replaced option ssl with tls. Use of any
+tls- prefixed options implies tls is enabled.
New option tls-min-version=1.N to set minimum TLS version allowed.
New option tls-default-ca replaces sslflags=NO_DEFAULT_CA
New option tls-no-npn to disable sending TLS NPN extension.
@@ -322,7 +330,8 @@
have been removed.
Removed sslversion= option. Use tls-options= instead.
Manual squid.conf update may be required on upgrade.
-Replaced sslcafile= with tls-cafile= which takes multiple entries.
+Replaced option sslcafile= with tls-cafile=
+which takes multiple entries.
- external_acl_type
-
New parameter queue-size= to set the maximum number
@@ -534,6 +543,8 @@
Replaced by --with-cppunit=PATH.
Please prefer the default auto-detection though.
+ - XSTD_USE_LIBLTDL
-
+
Removed. Use --with-included-ltdl instead.
diff -u -r -N squid-4.0.12/src/acl/external/delayer/ext_delayer_acl.8 squid-4.0.13/src/acl/external/delayer/ext_delayer_acl.8
--- squid-4.0.12/src/acl/external/delayer/ext_delayer_acl.8 2016-07-02 02:23:27.000000000 +1200
+++ squid-4.0.13/src/acl/external/delayer/ext_delayer_acl.8 2016-08-06 02:26:06.000000000 +1200
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EXT_DELAYER_ACL 8"
-.TH EXT_DELAYER_ACL 8 "2016-07-01" "perl v5.22.2" "User Contributed Perl Documentation"
+.TH EXT_DELAYER_ACL 8 "2016-08-05" "perl v5.22.2" "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.12/src/acl/external/kerberos_ldap_group/kerberos_ldap_group.cc squid-4.0.13/src/acl/external/kerberos_ldap_group/kerberos_ldap_group.cc
--- squid-4.0.12/src/acl/external/kerberos_ldap_group/kerberos_ldap_group.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/acl/external/kerberos_ldap_group/kerberos_ldap_group.cc 2016-08-06 00:52:55.000000000 +1200
@@ -214,7 +214,7 @@
margs.rc_allow = 1;
break;
case 's':
- margs.ssl = (char *) "yes";
+ margs.ssl = xstrdup("yes");
break;
case 'n':
margs.nokerberos = 1;
diff -u -r -N squid-4.0.12/src/acl/external/kerberos_ldap_group/support_ldap.cc squid-4.0.13/src/acl/external/kerberos_ldap_group/support_ldap.cc
--- squid-4.0.12/src/acl/external/kerberos_ldap_group/support_ldap.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/acl/external/kerberos_ldap_group/support_ldap.cc 2016-08-06 00:52:55.000000000 +1200
@@ -74,9 +74,13 @@
#define FILTER_AD "(samaccountname=%s)"
#define ATTRIBUTE_AD "memberof"
-size_t get_attributes(LDAP * ld, LDAPMessage * res, const char *attribute /* IN */ , char ***out_val /* OUT (caller frees) */ );
-size_t get_bin_attributes(LDAP * ld, LDAPMessage * res, const char *attribute /* IN */ , char ***out_val , int **out_len /* OUT (caller frees) */ );
-int search_group_tree(struct main_args *margs, LDAP * ld, char *bindp, char *ldap_group, char *group, int depth);
+size_t get_attributes(LDAP * ld, LDAPMessage * res,
+ const char *attribute /* IN */ , char ***out_val /* OUT (caller frees) */ );
+size_t get_bin_attributes(LDAP * ld, LDAPMessage * res,
+ const char *attribute /* IN */ , char ***out_val,
+ int **out_len /* OUT (caller frees) */ );
+int search_group_tree(struct main_args *margs, LDAP * ld, char *bindp,
+ char *ldap_group, char *group, int depth);
#if HAVE_SUN_LDAP_SDK || HAVE_MOZILLA_LDAP_SDK
#if HAVE_LDAP_REBINDPROC_CALLBACK
@@ -85,13 +89,8 @@
static LDAP_REBINDPROC_CALLBACK ldap_sasl_rebind;
static int LDAP_CALL LDAP_CALLBACK
-ldap_sasl_rebind(
- LDAP * ld,
- char **whop,
- char **credp,
- int *methodp,
- int freeit,
- void *params)
+ldap_sasl_rebind(LDAP * ld,
+ char **whop, char **credp, int *methodp, int freeit, void *params)
{
struct ldap_creds *cp = (struct ldap_creds *) params;
whop = whop;
@@ -105,37 +104,29 @@
static LDAP_REBINDPROC_CALLBACK ldap_simple_rebind;
static int LDAP_CALL LDAP_CALLBACK
-ldap_simple_rebind(
- LDAP * ld,
- char **whop,
- char **credp,
- int *methodp,
- int freeit,
- void *params)
+ldap_simple_rebind(LDAP * ld,
+ char **whop, char **credp, int *methodp, int freeit, void *params)
{
struct ldap_creds *cp = (struct ldap_creds *) params;
struct berval cred;
if (cp->pw) {
- cred.bv_val=cp->pw;
- cred.bv_len=strlen(cp->pw);
+ cred.bv_val = cp->pw;
+ cred.bv_len = strlen(cp->pw);
}
whop = whop;
credp = credp;
methodp = methodp;
freeit = freeit;
- return ldap_sasl_bind_s(ld, cp->dn, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
+ return ldap_sasl_bind_s(ld, cp->dn, LDAP_SASL_SIMPLE, &cred, NULL, NULL,
+ NULL);
}
#elif HAVE_LDAP_REBIND_PROC
#if HAVE_SASL_H || HAVE_SASL_SASL_H || HAVE_SASL_DARWIN
static LDAP_REBIND_PROC ldap_sasl_rebind;
static int
-ldap_sasl_rebind(
- LDAP * ld,
- LDAP_CONST char *url,
- ber_tag_t request,
- ber_int_t msgid,
- void *params)
+ldap_sasl_rebind(LDAP * ld,
+ LDAP_CONST char *url, ber_tag_t request, ber_int_t msgid, void *params)
{
struct ldap_creds *cp = (struct ldap_creds *) params;
return tool_sasl_bind(ld, cp->dn, cp->pw);
@@ -145,20 +136,17 @@
static LDAP_REBIND_PROC ldap_simple_rebind;
static int
-ldap_simple_rebind(
- LDAP * ld,
- LDAP_CONST char *url,
- ber_tag_t request,
- ber_int_t msgid,
- void *params)
+ldap_simple_rebind(LDAP * ld,
+ LDAP_CONST char *url, ber_tag_t request, ber_int_t msgid, void *params)
{
struct ldap_creds *cp = (struct ldap_creds *) params;
struct berval cred;
if (cp->pw) {
- cred.bv_val=cp->pw;
- cred.bv_len=strlen(cp->pw);
+ cred.bv_val = cp->pw;
+ cred.bv_len = strlen(cp->pw);
}
- return ldap_sasl_bind_s(ld, cp->dn, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
+ return ldap_sasl_bind_s(ld, cp->dn, LDAP_SASL_SIMPLE, &cred, NULL, NULL,
+ NULL);
}
#elif HAVE_LDAP_REBIND_FUNCTION
@@ -169,13 +157,8 @@
static LDAP_REBIND_FUNCTION ldap_sasl_rebind;
static int
-ldap_sasl_rebind(
- LDAP * ld,
- char **whop,
- char **credp,
- int *methodp,
- int freeit,
- void *params)
+ldap_sasl_rebind(LDAP * ld,
+ char **whop, char **credp, int *methodp, int freeit, void *params)
{
struct ldap_creds *cp = (struct ldap_creds *) params;
whop = whop;
@@ -189,25 +172,21 @@
static LDAP_REBIND_FUNCTION ldap_simple_rebind;
static int
-ldap_simple_rebind(
- LDAP * ld,
- char **whop,
- char **credp,
- int *methodp,
- int freeit,
- void *params)
+ldap_simple_rebind(LDAP * ld,
+ char **whop, char **credp, int *methodp, int freeit, void *params)
{
struct ldap_creds *cp = (struct ldap_creds *) params;
struct berval cred;
if (cp->pw) {
- cred.bv_val=cp->pw;
- cred.bv_len=strlen(cp->pw);
+ cred.bv_val = cp->pw;
+ cred.bv_len = strlen(cp->pw);
}
whop = whop;
credp = credp;
methodp = methodp;
freeit = freeit;
- return ldap_sasl_bind_s(ld, cp->dn, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
+ return ldap_sasl_bind_s(ld, cp->dn, LDAP_SASL_SIMPLE, &cred, NULL, NULL,
+ NULL);
}
#else
#error "No rebind functione defined"
@@ -217,7 +196,8 @@
static LDAP_REBIND_PROC ldap_sasl_rebind;
static int
-ldap_sasl_rebind(LDAP *ld, LDAP_CONST char *, ber_tag_t request, ber_int_t msgid, void *params)
+ldap_sasl_rebind(LDAP * ld, LDAP_CONST char *, ber_tag_t request,
+ ber_int_t msgid, void *params)
{
struct ldap_creds *cp = (struct ldap_creds *) params;
return tool_sasl_bind(ld, cp->dn, cp->pw);
@@ -227,16 +207,18 @@
static LDAP_REBIND_PROC ldap_simple_rebind;
static int
-ldap_simple_rebind(LDAP *ld, LDAP_CONST char *, ber_tag_t request, ber_int_t msgid, void *params)
+ldap_simple_rebind(LDAP * ld, LDAP_CONST char *, ber_tag_t request,
+ ber_int_t msgid, void *params)
{
struct ldap_creds *cp = (struct ldap_creds *) params;
struct berval cred;
if (cp->pw) {
- cred.bv_val=cp->pw;
- cred.bv_len=strlen(cp->pw);
+ cred.bv_val = cp->pw;
+ cred.bv_len = strlen(cp->pw);
}
- return ldap_sasl_bind_s(ld, cp->dn, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
+ return ldap_sasl_bind_s(ld, cp->dn, LDAP_SASL_SIMPLE, &cred, NULL, NULL,
+ NULL);
}
#endif
@@ -284,8 +266,7 @@
for (ldap_filter_esc = filter; *ldap_filter_esc; ++ldap_filter_esc) {
if ((*ldap_filter_esc == '*') ||
(*ldap_filter_esc == '(') ||
- (*ldap_filter_esc == ')') ||
- (*ldap_filter_esc == '\\'))
+ (*ldap_filter_esc == ')') || (*ldap_filter_esc == '\\'))
i = i + 3;
}
@@ -330,24 +311,34 @@
searchtime.tv_sec = SEARCH_TIMEOUT;
searchtime.tv_usec = 0;
- debug((char *) "%s| %s: DEBUG: Search ldap server with bind path \"\" and filter: %s\n", LogTime(), PROGRAM, FILTER_SCHEMA);
- rc = ldap_search_ext_s(ld, (char *) "", LDAP_SCOPE_BASE, (char *) FILTER_SCHEMA, NULL, 0,
- NULL, NULL, &searchtime, 0, &res);
+ debug((char *)
+ "%s| %s: DEBUG: Search ldap server with bind path \"\" and filter: %s\n",
+ LogTime(), PROGRAM, FILTER_SCHEMA);
+ rc = ldap_search_ext_s(ld, (char *) "", LDAP_SCOPE_BASE,
+ (char *) FILTER_SCHEMA, NULL, 0, NULL, NULL, &searchtime, 0, &res);
if (rc == LDAP_SUCCESS)
max_attr = get_attributes(ld, res, ATTRIBUTE_SCHEMA, &attr_value);
if (max_attr == 1) {
ldap_msgfree(res);
- debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n", LogTime(), PROGRAM, attr_value[0], FILTER_SAM);
- rc = ldap_search_ext_s(ld, attr_value[0], LDAP_SCOPE_SUBTREE, (char *) FILTER_SAM, NULL, 0,
- NULL, NULL, &searchtime, 0, &res);
- debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM, ldap_count_entries(ld, res), ldap_count_entries(ld, res) > 1 || ldap_count_entries(ld, res) == 0 ? "ies" : "y");
+ debug((char *)
+ "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n",
+ LogTime(), PROGRAM, attr_value[0], FILTER_SAM);
+ rc = ldap_search_ext_s(ld, attr_value[0], LDAP_SCOPE_SUBTREE,
+ (char *) FILTER_SAM, NULL, 0, NULL, NULL, &searchtime, 0, &res);
+ debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(),
+ PROGRAM, ldap_count_entries(ld, res), ldap_count_entries(ld,
+ res) > 1 || ldap_count_entries(ld, res) == 0 ? "ies" : "y");
if (ldap_count_entries(ld, res) > 0)
margs->AD = 1;
} else
- debug((char *) "%s| %s: DEBUG: Did not find ldap entry for subschemasubentry\n", LogTime(), PROGRAM);
- debug((char *) "%s| %s: DEBUG: Determined ldap server %sas an Active Directory server\n", LogTime(), PROGRAM, margs->AD ? "" : "not ");
+ debug((char *)
+ "%s| %s: DEBUG: Did not find ldap entry for subschemasubentry\n",
+ LogTime(), PROGRAM);
+ debug((char *)
+ "%s| %s: DEBUG: Determined ldap server %sas an Active Directory server\n",
+ LogTime(), PROGRAM, margs->AD ? "" : "not ");
/*
* Cleanup
*/
@@ -361,8 +352,10 @@
ldap_msgfree(res);
return rc;
}
+
int
-search_group_tree(struct main_args *margs, LDAP * ld, char *bindp, char *ldap_group, char *group, int depth)
+search_group_tree(struct main_args *margs, LDAP * ld, char *bindp,
+ char *ldap_group, char *group, int depth)
{
LDAPMessage *res = NULL;
char **attr_value = NULL;
@@ -395,21 +388,26 @@
xfree(ldap_filter_esc);
if (depth > margs->mdepth) {
- debug((char *) "%s| %s: DEBUG: Max search depth reached %d>%d\n", LogTime(), PROGRAM, depth, margs->mdepth);
+ debug((char *) "%s| %s: DEBUG: Max search depth reached %d>%d\n",
+ LogTime(), PROGRAM, depth, margs->mdepth);
xfree(search_exp);
return 0;
}
- debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter : %s\n", LogTime(), PROGRAM, bindp, search_exp);
- rc = ldap_search_ext_s(ld, bindp, LDAP_SCOPE_SUBTREE,
- search_exp, NULL, 0,
+ debug((char *)
+ "%s| %s: DEBUG: Search ldap server with bind path %s and filter : %s\n",
+ LogTime(), PROGRAM, bindp, search_exp);
+ rc = ldap_search_ext_s(ld, bindp, LDAP_SCOPE_SUBTREE, search_exp, NULL, 0,
NULL, NULL, &searchtime, 0, &res);
xfree(search_exp);
if (rc != LDAP_SUCCESS) {
- error((char *) "%s| %s: ERROR: Error searching ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+ error((char *) "%s| %s: ERROR: Error searching ldap server: %s\n",
+ LogTime(), PROGRAM, ldap_err2string(rc));
return 0;
}
- debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM, ldap_count_entries(ld, res), ldap_count_entries(ld, res) > 1 || ldap_count_entries(ld, res) == 0 ? "ies" : "y");
+ debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM,
+ ldap_count_entries(ld, res), ldap_count_entries(ld, res) > 1
+ || ldap_count_entries(ld, res) == 0 ? "ies" : "y");
if (margs->AD)
max_attr = get_attributes(ld, res, ATTRIBUTE_AD, &attr_value);
@@ -435,21 +433,28 @@
}
if (debug_enabled) {
int n;
- debug((char *) "%s| %s: DEBUG: Entry %" PRIuSIZE " \"%s\" in hex UTF-8 is ", LogTime(), PROGRAM, j + 1, av);
+ debug((char *) "%s| %s: DEBUG: Entry %" PRIuSIZE
+ " \"%s\" in hex UTF-8 is ", LogTime(), PROGRAM, j + 1, av);
for (n = 0; av[n] != '\0'; ++n)
fprintf(stderr, "%02x", (unsigned char) av[n]);
fprintf(stderr, "\n");
}
if (!strcasecmp(group, av)) {
retval = 1;
- debug((char *) "%s| %s: DEBUG: Entry %" PRIuSIZE " \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
+ debug((char *) "%s| %s: DEBUG: Entry %" PRIuSIZE
+ " \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM,
+ j + 1, av, group);
break;
} else
- debug((char *) "%s| %s: DEBUG: Entry %" PRIuSIZE " \"%s\" does not match group name \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
+ debug((char *) "%s| %s: DEBUG: Entry %" PRIuSIZE
+ " \"%s\" does not match group name \"%s\"\n", LogTime(),
+ PROGRAM, j + 1, av, group);
/*
* Do recursive group search
*/
- debug((char *) "%s| %s: DEBUG: Perform recursive group search for group \"%s\"\n", LogTime(), PROGRAM, av);
+ debug((char *)
+ "%s| %s: DEBUG: Perform recursive group search for group \"%s\"\n",
+ LogTime(), PROGRAM, av);
av = attr_value[j];
if (search_group_tree(margs, ld, bindp, av, group, ldepth)) {
retval = 1;
@@ -461,7 +466,9 @@
}
}
if (debug_enabled)
- debug((char *) "%s| %s: DEBUG: Entry %" PRIuSIZE " \"%s\" is member of group named \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
+ debug((char *) "%s| %s: DEBUG: Entry %" PRIuSIZE
+ " \"%s\" is member of group named \"%s\"\n", LogTime(),
+ PROGRAM, j + 1, av, group);
else
break;
@@ -492,12 +499,15 @@
val = LDAP_VERSION3;
rc = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &val);
if (rc != LDAP_SUCCESS) {
- debug((char *) "%s| %s: DEBUG: Error while setting protocol version: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+ debug((char *)
+ "%s| %s: DEBUG: Error while setting protocol version: %s\n",
+ LogTime(), PROGRAM, ldap_err2string(rc));
return rc;
}
rc = ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
if (rc != LDAP_SUCCESS) {
- debug((char *) "%s| %s: DEBUG: Error while setting referrals off: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+ debug((char *) "%s| %s: DEBUG: Error while setting referrals off: %s\n",
+ LogTime(), PROGRAM, ldap_err2string(rc));
return rc;
}
#if LDAP_OPT_NETWORK_TIMEOUT
@@ -505,7 +515,9 @@
tv.tv_usec = 0;
rc = ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &tv);
if (rc != LDAP_SUCCESS) {
- debug((char *) "%s| %s: DEBUG: Error while setting network timeout: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+ debug((char *)
+ "%s| %s: DEBUG: Error while setting network timeout: %s\n",
+ LogTime(), PROGRAM, ldap_err2string(rc));
return rc;
}
#endif /* LDAP_OPT_NETWORK_TIMEOUT */
@@ -527,35 +539,75 @@
#if HAVE_OPENLDAP
if (!margs->rc_allow) {
char *ssl_cacertfile = NULL;
- int free_path;
- debug((char *) "%s| %s: DEBUG: Enable server certificate check for ldap server.\n", LogTime(), PROGRAM);
+ char *ssl_cacertdir = NULL;
+ debug((char *)
+ "%s| %s: DEBUG: Enable server certificate check for ldap server.\n",
+ LogTime(), PROGRAM);
val = LDAP_OPT_X_TLS_DEMAND;
rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &val);
if (rc != LDAP_SUCCESS) {
- error((char *) "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_REQUIRE_CERT DEMAND for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+ error((char *)
+ "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_REQUIRE_CERT DEMAND for ldap server: %s\n",
+ LogTime(), PROGRAM, ldap_err2string(rc));
return rc;
}
- ssl_cacertfile = getenv("TLS_CACERTFILE");
- free_path = 0;
+ ssl_cacertfile = xstrdup(getenv("TLS_CACERTFILE"));
if (!ssl_cacertfile) {
ssl_cacertfile = xstrdup("/etc/ssl/certs/cert.pem");
- free_path = 1;
}
- debug((char *) "%s| %s: DEBUG: Set certificate file for ldap server to %s.(Changeable through setting environment variable TLS_CACERTFILE)\n", LogTime(), PROGRAM, ssl_cacertfile);
- rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, ssl_cacertfile);
- if (ssl_cacertfile && free_path) {
+ if (access(ssl_cacertfile, R_OK) == 0) {
+ debug((char *)
+ "%s| %s: DEBUG: Set certificate file for ldap server to %s. (Changeable through setting environment variable TLS_CACERTFILE)\n",
+ LogTime(), PROGRAM, ssl_cacertfile);
+ rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
+ ssl_cacertfile);
xfree(ssl_cacertfile);
- }
- if (rc != LDAP_OPT_SUCCESS) {
- error((char *) "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_CACERTFILE for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
- return rc;
+ if (rc != LDAP_OPT_SUCCESS) {
+ error((char *)
+ "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_CACERTFILE for ldap server: %s\n",
+ LogTime(), PROGRAM, ldap_err2string(rc));
+ return rc;
+ }
+ } else {
+ debug((char *)
+ "%s| %s: DEBUG: Set certificate file for ldap server to %s failed (%s). (Changeable through setting environment variable TLS_CACERTFILE) Trying db certificate directory\n",
+ LogTime(), PROGRAM, ssl_cacertfile, strerror(errno));
+ xfree(ssl_cacertfile);
+ ssl_cacertdir = xstrdup(getenv("TLS_CACERTDIR"));
+ if (!ssl_cacertdir) {
+ ssl_cacertdir = xstrdup("/etc/ssl/certs");
+ }
+ if (access(ssl_cacertdir, R_OK) == 0) {
+ debug((char *)
+ "%s| %s: DEBUG: Set certificate database path for ldap server to %s. (Changeable through setting environment variable TLS_CACERTDIR)\n",
+ LogTime(), PROGRAM, ssl_cacertdir);
+ rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTDIR,
+ ssl_cacertdir);
+ xfree(ssl_cacertdir);
+ if (rc != LDAP_OPT_SUCCESS) {
+ error((char *)
+ "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_CACERTDIR for ldap server: %s\n",
+ LogTime(), PROGRAM, ldap_err2string(rc));
+ return rc;
+ }
+ } else {
+ debug((char *)
+ "%s| %s: DEBUG: Set certificate database path for ldap server to %s failed (%s). (Changeable through setting environment variable TLS_CACERTDIR)\n",
+ LogTime(), PROGRAM, ssl_cacertdir, strerror(errno));
+ xfree(ssl_cacertdir);
+ return errno;
+ }
}
} else {
- debug((char *) "%s| %s: DEBUG: Disable server certificate check for ldap server.\n", LogTime(), PROGRAM);
+ debug((char *)
+ "%s| %s: DEBUG: Disable server certificate check for ldap server.\n",
+ LogTime(), PROGRAM);
val = LDAP_OPT_X_TLS_ALLOW;
rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &val);
if (rc != LDAP_SUCCESS) {
- error((char *) "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_REQUIRE_CERT ALLOW for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+ error((char *)
+ "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_REQUIRE_CERT ALLOW for ldap server: %s\n",
+ LogTime(), PROGRAM, ldap_err2string(rc));
return rc;
}
}
@@ -571,26 +623,36 @@
if (!ssl_certdbpath) {
ssl_certdbpath = xstrdup("/etc/certs");
}
- debug((char *) "%s| %s: DEBUG: Set certificate database path for ldap server to %s.(Changeable through setting environment variable SSL_CERTDBPATH)\n", LogTime(), PROGRAM, ssl_certdbpath);
+ debug((char *)
+ "%s| %s: DEBUG: Set certificate database path for ldap server to %s. (Changeable through setting environment variable SSL_CERTDBPATH)\n",
+ LogTime(), PROGRAM, ssl_certdbpath);
if (!margs->rc_allow) {
- rc = ldapssl_advclientauth_init(ssl_certdbpath, NULL, 0, NULL, NULL, 0, NULL, 2);
+ rc = ldapssl_advclientauth_init(ssl_certdbpath, NULL, 0, NULL, NULL, 0,
+ NULL, 2);
} else {
- rc = ldapssl_advclientauth_init(ssl_certdbpath, NULL, 0, NULL, NULL, 0, NULL, 0);
- debug((char *) "%s| %s: DEBUG: Disable server certificate check for ldap server.\n", LogTime(), PROGRAM);
+ rc = ldapssl_advclientauth_init(ssl_certdbpath, NULL, 0, NULL, NULL, 0,
+ NULL, 0);
+ debug((char *)
+ "%s| %s: DEBUG: Disable server certificate check for ldap server.\n",
+ LogTime(), PROGRAM);
}
xfree(ssl_certdbpath);
if (rc != LDAP_SUCCESS) {
- error((char *) "%s| %s: ERROR: Error while setting SSL for ldap server: %s\n", LogTime(), PROGRAM, ldapssl_err2string(rc));
+ error((char *)
+ "%s| %s: ERROR: Error while setting SSL for ldap server: %s\n",
+ LogTime(), PROGRAM, ldapssl_err2string(rc));
return rc;
}
#else
- error((char *) "%s| %s: ERROR: SSL not supported by ldap library\n", LogTime(), PROGRAM);
+ error((char *) "%s| %s: ERROR: SSL not supported by ldap library\n",
+ LogTime(), PROGRAM);
#endif
return LDAP_SUCCESS;
}
size_t
-get_attributes(LDAP * ld, LDAPMessage * res, const char *attribute, char ***ret_value)
+get_attributes(LDAP * ld, LDAPMessage * res, const char *attribute,
+ char ***ret_value)
{
char **attr_value = *ret_value;
@@ -599,8 +661,10 @@
/*
* loop over attributes
*/
- debug((char *) "%s| %s: DEBUG: Search ldap entries for attribute : %s\n", LogTime(), PROGRAM, attribute);
- for (LDAPMessage *msg = ldap_first_entry(ld, res); msg; msg = ldap_next_entry(ld, msg)) {
+ debug((char *) "%s| %s: DEBUG: Search ldap entries for attribute : %s\n",
+ LogTime(), PROGRAM, attribute);
+ for (LDAPMessage * msg = ldap_first_entry(ld, res); msg;
+ msg = ldap_next_entry(ld, msg)) {
switch (ldap_msgtype(msg)) {
@@ -611,15 +675,20 @@
if (strcasecmp(attr, attribute) == 0) {
struct berval **values;
- if ((values = ldap_get_values_len(ld, msg, attr)) != NULL) {
+ if ((values =
+ ldap_get_values_len(ld, msg, attr)) != NULL) {
for (int il = 0; values[il] != NULL; ++il) {
- attr_value = (char **) xrealloc(attr_value, (max_attr + 1) * sizeof(char *));
+ attr_value =
+ (char **) xrealloc(attr_value,
+ (max_attr + 1) * sizeof(char *));
if (!attr_value)
break;
- attr_value[max_attr] = (char *) xmalloc(values[il]->bv_len + 1);
- memcpy(attr_value[max_attr], values[il]->bv_val, values[il]->bv_len);
+ attr_value[max_attr] =
+ (char *) xmalloc(values[il]->bv_len + 1);
+ memcpy(attr_value[max_attr], values[il]->bv_val,
+ values[il]->bv_len);
attr_value[max_attr][values[il]->bv_len] = 0;
max_attr++;
}
@@ -632,24 +701,30 @@
}
break;
case LDAP_RES_SEARCH_REFERENCE:
- debug((char *) "%s| %s: DEBUG: Received a search reference message\n", LogTime(), PROGRAM);
+ debug((char *)
+ "%s| %s: DEBUG: Received a search reference message\n",
+ LogTime(), PROGRAM);
break;
case LDAP_RES_SEARCH_RESULT:
- debug((char *) "%s| %s: DEBUG: Received a search result message\n", LogTime(), PROGRAM);
+ debug((char *) "%s| %s: DEBUG: Received a search result message\n",
+ LogTime(), PROGRAM);
break;
default:
break;
}
}
- debug((char *) "%s| %s: DEBUG: %" PRIuSIZE " ldap entr%s found with attribute : %s\n", LogTime(), PROGRAM, max_attr, max_attr > 1 || max_attr == 0 ? "ies" : "y", attribute);
+ debug((char *) "%s| %s: DEBUG: %" PRIuSIZE
+ " ldap entr%s found with attribute : %s\n", LogTime(), PROGRAM,
+ max_attr, max_attr > 1 || max_attr == 0 ? "ies" : "y", attribute);
*ret_value = attr_value;
return max_attr;
}
size_t
-get_bin_attributes(LDAP * ld, LDAPMessage * res, const char *attribute, char ***ret_value, int **ret_len)
+get_bin_attributes(LDAP * ld, LDAPMessage * res, const char *attribute,
+ char ***ret_value, int **ret_len)
{
char **attr_value = *ret_value;
@@ -659,8 +734,10 @@
/*
* loop over attributes
*/
- debug((char *) "%s| %s: DEBUG: Search ldap entries for attribute : %s\n", LogTime(), PROGRAM, attribute);
- for ( LDAPMessage *msg = ldap_first_entry(ld, res); msg; msg = ldap_next_entry(ld, msg)) {
+ debug((char *) "%s| %s: DEBUG: Search ldap entries for attribute : %s\n",
+ LogTime(), PROGRAM, attribute);
+ for (LDAPMessage * msg = ldap_first_entry(ld, res); msg;
+ msg = ldap_next_entry(ld, msg)) {
switch (ldap_msgtype(msg)) {
@@ -671,21 +748,28 @@
if (strcasecmp(attr, attribute) == 0) {
struct berval **values;
- if ((values = ldap_get_values_len(ld, msg, attr)) != NULL) {
+ if ((values =
+ ldap_get_values_len(ld, msg, attr)) != NULL) {
for (int il = 0; values[il] != NULL; ++il) {
- attr_value = (char **) xrealloc(attr_value, (max_attr + 1) * sizeof(char *));
+ attr_value =
+ (char **) xrealloc(attr_value,
+ (max_attr + 1) * sizeof(char *));
if (!attr_value)
break;
- attr_len = (int *) xrealloc(attr_len, (max_attr + 1) * sizeof(int));
+ attr_len =
+ (int *) xrealloc(attr_len,
+ (max_attr + 1) * sizeof(int));
if (!attr_len)
break;
- attr_value[max_attr] = (char *) xmalloc(values[il]->bv_len + 1);
- memcpy(attr_value[max_attr], values[il]->bv_val, values[il]->bv_len);
+ attr_value[max_attr] =
+ (char *) xmalloc(values[il]->bv_len + 1);
+ memcpy(attr_value[max_attr], values[il]->bv_val,
+ values[il]->bv_len);
attr_value[max_attr][values[il]->bv_len] = 0;
- attr_len[max_attr]=values[il]->bv_len;
+ attr_len[max_attr] = values[il]->bv_len;
max_attr++;
}
}
@@ -697,17 +781,22 @@
}
break;
case LDAP_RES_SEARCH_REFERENCE:
- debug((char *) "%s| %s: DEBUG: Received a search reference message\n", LogTime(), PROGRAM);
+ debug((char *)
+ "%s| %s: DEBUG: Received a search reference message\n",
+ LogTime(), PROGRAM);
break;
case LDAP_RES_SEARCH_RESULT:
- debug((char *) "%s| %s: DEBUG: Received a search result message\n", LogTime(), PROGRAM);
+ debug((char *) "%s| %s: DEBUG: Received a search result message\n",
+ LogTime(), PROGRAM);
break;
default:
break;
}
}
- debug((char *) "%s| %s: DEBUG: %" PRIuSIZE " ldap entr%s found with attribute : %s\n", LogTime(), PROGRAM, max_attr, max_attr > 1 || max_attr == 0 ? "ies" : "y", attribute);
+ debug((char *) "%s| %s: DEBUG: %" PRIuSIZE
+ " ldap entr%s found with attribute : %s\n", LogTime(), PROGRAM,
+ max_attr, max_attr > 1 || max_attr == 0 ? "ies" : "y", attribute);
*ret_value = attr_value;
*ret_len = attr_len;
@@ -752,7 +841,8 @@
#elif HAVE_LDAP_URL_PARSE
rc = ldap_url_parse(ldapuri, &url);
if (rc != LDAP_SUCCESS) {
- error((char *) "%s| %s: ERROR: Error while parsing url: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+ error((char *) "%s| %s: ERROR: Error while parsing url: %s\n",
+ LogTime(), PROGRAM, ldap_err2string(rc));
xfree(ldapuri);
ldap_free_urldesc(url);
return NULL;
@@ -764,8 +854,10 @@
rc = ldap_initialize(&ld, ldapuri);
xfree(ldapuri);
if (rc != LDAP_SUCCESS) {
- error((char *) "%s| %s: ERROR: Error while initialising connection to ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
- ldap_unbind_ext(ld,NULL,NULL);
+ error((char *)
+ "%s| %s: ERROR: Error while initialising connection to ldap server: %s\n",
+ LogTime(), PROGRAM, ldap_err2string(rc));
+ ldap_unbind_ext(ld, NULL, NULL);
ld = NULL;
return NULL;
}
@@ -774,7 +866,9 @@
#endif
rc = ldap_set_defaults(ld);
if (rc != LDAP_SUCCESS) {
- error((char *) "%s| %s: ERROR: Error while setting default options for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+ error((char *)
+ "%s| %s: ERROR: Error while setting default options for ldap server: %s\n",
+ LogTime(), PROGRAM, ldap_err2string(rc));
ldap_unbind_ext(ld, NULL, NULL);
ld = NULL;
return NULL;
@@ -786,7 +880,9 @@
debug((char *) "%s| %s: DEBUG: Set SSL defaults\n", LogTime(), PROGRAM);
rc = ldap_set_ssl_defaults(margs);
if (rc != LDAP_SUCCESS) {
- error((char *) "%s| %s: ERROR: Error while setting SSL default options for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+ error((char *)
+ "%s| %s: ERROR: Error while setting SSL default options for ldap server: %s\n",
+ LogTime(), PROGRAM, ldap_err2string(rc));
ldap_unbind_ext(ld, NULL, NULL);
ld = NULL;
return NULL;
@@ -797,7 +893,9 @@
*/
rc = ldap_start_tls_s(ld, NULL, NULL);
if (rc != LDAP_SUCCESS) {
- error((char *) "%s| %s: ERROR: Error while setting start_tls for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+ debug((char *)
+ "%s| %s: WARNING: Error while setting start_tls for ldap server: %s\n",
+ LogTime(), PROGRAM, ldap_err2string(rc));
ldap_unbind_ext(ld, NULL, NULL);
ld = NULL;
url = (LDAPURLDesc *) xmalloc(sizeof(*url));
@@ -817,7 +915,8 @@
#elif HAVE_LDAP_URL_PARSE
rc = ldap_url_parse(ldapuri, &url);
if (rc != LDAP_SUCCESS) {
- error((char *) "%s| %s: ERROR: Error while parsing url: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+ error((char *) "%s| %s: ERROR: Error while parsing url: %s\n",
+ LogTime(), PROGRAM, ldap_err2string(rc));
xfree(ldapuri);
ldap_free_urldesc(url);
return NULL;
@@ -829,14 +928,18 @@
rc = ldap_initialize(&ld, ldapuri);
xfree(ldapuri);
if (rc != LDAP_SUCCESS) {
- error((char *) "%s| %s: ERROR: Error while initialising connection to ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+ error((char *)
+ "%s| %s: ERROR: Error while initialising connection to ldap server: %s\n",
+ LogTime(), PROGRAM, ldap_err2string(rc));
ldap_unbind_ext(ld, NULL, NULL);
ld = NULL;
return NULL;
}
rc = ldap_set_defaults(ld);
if (rc != LDAP_SUCCESS) {
- error((char *) "%s| %s: ERROR: Error while setting default options for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+ error((char *)
+ "%s| %s: ERROR: Error while setting default options for ldap server: %s\n",
+ LogTime(), PROGRAM, ldap_err2string(rc));
ldap_unbind_ext(ld, NULL, NULL);
ld = NULL;
return NULL;
@@ -845,20 +948,25 @@
#elif HAVE_LDAPSSL_CLIENT_INIT
ld = ldapssl_init(host, port, 1);
if (!ld) {
- error((char *) "%s| %s: ERROR: Error while setting SSL for ldap server: %s\n", LogTime(), PROGRAM, ldapssl_err2string(rc));
+ error((char *)
+ "%s| %s: ERROR: Error while setting SSL for ldap server: %s\n",
+ LogTime(), PROGRAM, ldapssl_err2string(rc));
ldap_unbind_ext(ld, NULL, NULL);
ld = NULL;
return NULL;
}
rc = ldap_set_defaults(ld);
if (rc != LDAP_SUCCESS) {
- error((char *) "%s| %s: ERROR: Error while setting default options for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+ error((char *)
+ "%s| %s: ERROR: Error while setting default options for ldap server: %s\n",
+ LogTime(), PROGRAM, ldap_err2string(rc));
ldap_unbind_ext(ld, NULL, NULL);
ld = NULL;
return NULL;
}
#else
- error((char *) "%s| %s: ERROR: SSL not supported by ldap library\n", LogTime(), PROGRAM);
+ error((char *) "%s| %s: ERROR: SSL not supported by ldap library\n",
+ LogTime(), PROGRAM);
#endif
}
return ld;
@@ -895,21 +1003,28 @@
* Fill Kerberos memory cache with credential from keytab for SASL/GSSAPI
*/
if (domain) {
- debug((char *) "%s| %s: DEBUG: Setup Kerberos credential cache\n", LogTime(), PROGRAM);
+ debug((char *) "%s| %s: DEBUG: Setup Kerberos credential cache\n",
+ LogTime(), PROGRAM);
#if HAVE_KRB5
if (margs->nokerberos) {
kc = 1;
- debug((char *) "%s| %s: DEBUG: Kerberos is disabled. Use username/password with ldap url instead\n", LogTime(), PROGRAM);
+ debug((char *)
+ "%s| %s: DEBUG: Kerberos is disabled. Use username/password with ldap url instead\n",
+ LogTime(), PROGRAM);
} else {
kc = krb5_create_cache(domain);
if (kc) {
- error((char *) "%s| %s: ERROR: Error during setup of Kerberos credential cache\n", LogTime(), PROGRAM);
+ error((char *)
+ "%s| %s: ERROR: Error during setup of Kerberos credential cache\n",
+ LogTime(), PROGRAM);
}
}
#else
kc = 1;
- debug((char *) "%s| %s: DEBUG: Kerberos is not supported. Use username/password with ldap url instead\n", LogTime(), PROGRAM);
+ debug((char *)
+ "%s| %s: DEBUG: Kerberos is not supported. Use username/password with ldap url instead\n",
+ LogTime(), PROGRAM);
#endif
}
@@ -929,13 +1044,17 @@
ldap_debug = 0;
(void) ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &ldap_debug);
#endif
- debug((char *) "%s| %s: DEBUG: Initialise ldap connection\n", LogTime(), PROGRAM);
+ debug((char *) "%s| %s: DEBUG: Initialise ldap connection\n", LogTime(),
+ PROGRAM);
if (domain && !kc) {
if (margs->ssl) {
- debug((char *) "%s| %s: DEBUG: Enable SSL to ldap servers\n", LogTime(), PROGRAM);
+ debug((char *) "%s| %s: DEBUG: Enable SSL to ldap servers\n",
+ LogTime(), PROGRAM);
}
- debug((char *) "%s| %s: DEBUG: Canonicalise ldap server name for domain %s\n", LogTime(), PROGRAM, domain);
+ debug((char *)
+ "%s| %s: DEBUG: Canonicalise ldap server name for domain %s\n",
+ LogTime(), PROGRAM, domain);
/*
* Loop over list of ldap servers of users domain
*/
@@ -944,7 +1063,9 @@
int port = 389;
if (hlist[i].port != -1)
port = hlist[i].port;
- debug((char *) "%s| %s: DEBUG: Setting up connection to ldap server %s:%d\n", LogTime(), PROGRAM, hlist[i].host, port);
+ debug((char *)
+ "%s| %s: DEBUG: Setting up connection to ldap server %s:%d\n",
+ LogTime(), PROGRAM, hlist[i].host, port);
ld = tool_ldap_open(margs, hlist[i].host, port, margs->ssl);
if (!ld)
@@ -955,11 +1076,15 @@
*/
#if HAVE_SASL_H || HAVE_SASL_SASL_H || HAVE_SASL_DARWIN
- debug((char *) "%s| %s: DEBUG: Bind to ldap server with SASL/GSSAPI\n", LogTime(), PROGRAM);
+ debug((char *)
+ "%s| %s: DEBUG: Bind to ldap server with SASL/GSSAPI\n",
+ LogTime(), PROGRAM);
rc = tool_sasl_bind(ld, bindp, margs->ssl);
if (rc != LDAP_SUCCESS) {
- error((char *) "%s| %s: ERROR: Error while binding to ldap server with SASL/GSSAPI: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+ error((char *)
+ "%s| %s: ERROR: Error while binding to ldap server with SASL/GSSAPI: %s\n",
+ LogTime(), PROGRAM, ldap_err2string(rc));
ldap_unbind_ext(ld, NULL, NULL);
ld = NULL;
continue;
@@ -969,19 +1094,25 @@
lcreds->pw = margs->ssl ? xstrdup(margs->ssl) : NULL;
ldap_set_rebind_proc(ld, ldap_sasl_rebind, (char *) lcreds);
if (ld != NULL) {
- debug((char *) "%s| %s: DEBUG: %s initialised %sconnection to ldap server %s:%d\n", LogTime(), PROGRAM, ld ? "Successfully" : "Failed to", margs->ssl ? "SSL protected " : "", hlist[i].host, port);
+ debug((char *)
+ "%s| %s: DEBUG: %s initialised %sconnection to ldap server %s:%d\n",
+ LogTime(), PROGRAM, ld ? "Successfully" : "Failed to",
+ margs->ssl ? "SSL protected " : "", hlist[i].host, port);
break;
}
#else
ldap_unbind_ext(ld, NULL, NULL);
ld = NULL;
- error((char *) "%s| %s: ERROR: SASL not supported on system\n", LogTime(), PROGRAM);
+ error((char *) "%s| %s: ERROR: SASL not supported on system\n",
+ LogTime(), PROGRAM);
continue;
#endif
}
nhosts = free_hostname_list(&hlist, nhosts);
if (ld == NULL) {
- debug((char *) "%s| %s: DEBUG: Error during initialisation of ldap connection: %s\n", LogTime(), PROGRAM, strerror(errno));
+ debug((char *)
+ "%s| %s: DEBUG: Error during initialisation of ldap connection: %s\n",
+ LogTime(), PROGRAM, strerror(errno));
}
bindp = convert_domain_to_bind_path(domain);
}
@@ -997,9 +1128,11 @@
hostname = strstr(margs->lurl, "://") + 3;
ssl = strstr(margs->lurl, "ldaps://");
if (ssl) {
- debug((char *) "%s| %s: DEBUG: Enable SSL to ldap servers\n", LogTime(), PROGRAM);
+ debug((char *) "%s| %s: DEBUG: Enable SSL to ldap servers\n",
+ LogTime(), PROGRAM);
}
- debug((char *) "%s| %s: DEBUG: Canonicalise ldap server name %s\n", LogTime(), PROGRAM, hostname);
+ debug((char *) "%s| %s: DEBUG: Canonicalise ldap server name %s\n",
+ LogTime(), PROGRAM, hostname);
/*
* Loop over list of ldap servers
*/
@@ -1015,8 +1148,8 @@
for (size_t i = 0; i < nhosts; ++i) {
struct berval cred;
if (margs->lpass) {
- cred.bv_val=margs->lpass;
- cred.bv_len=strlen(margs->lpass);
+ cred.bv_val = margs->lpass;
+ cred.bv_len = strlen(margs->lpass);
}
ld = tool_ldap_open(margs, hlist[i].host, port, ssl);
if (!ld)
@@ -1025,10 +1158,15 @@
* ldap bind with username/password authentication
*/
- debug((char *) "%s| %s: DEBUG: Bind to ldap server with Username/Password\n", LogTime(), PROGRAM);
- rc = ldap_sasl_bind_s(ld, margs->luser, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
+ debug((char *)
+ "%s| %s: DEBUG: Bind to ldap server with Username/Password\n",
+ LogTime(), PROGRAM);
+ rc = ldap_sasl_bind_s(ld, margs->luser, LDAP_SASL_SIMPLE, &cred,
+ NULL, NULL, NULL);
if (rc != LDAP_SUCCESS) {
- error((char *) "%s| %s: ERROR: Error while binding to ldap server with Username/Password: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+ error((char *)
+ "%s| %s: ERROR: Error while binding to ldap server with Username/Password: %s\n",
+ LogTime(), PROGRAM, ldap_err2string(rc));
ldap_unbind_ext(ld, NULL, NULL);
ld = NULL;
continue;
@@ -1037,7 +1175,10 @@
lcreds->dn = xstrdup(margs->luser);
lcreds->pw = xstrdup(margs->lpass);
ldap_set_rebind_proc(ld, ldap_simple_rebind, (char *) lcreds);
- debug((char *) "%s| %s: DEBUG: %s set up %sconnection to ldap server %s:%d\n", LogTime(), PROGRAM, ld ? "Successfully" : "Failed to", ssl ? "SSL protected " : "", hlist[i].host, port);
+ debug((char *)
+ "%s| %s: DEBUG: %s set up %sconnection to ldap server %s:%d\n",
+ LogTime(), PROGRAM, ld ? "Successfully" : "Failed to",
+ ssl ? "SSL protected " : "", hlist[i].host, port);
break;
}
@@ -1050,7 +1191,9 @@
}
}
if (ld == NULL) {
- debug((char *) "%s| %s: DEBUG: Error during initialisation of ldap connection: %s\n", LogTime(), PROGRAM, strerror(errno));
+ debug((char *)
+ "%s| %s: DEBUG: Error during initialisation of ldap connection: %s\n",
+ LogTime(), PROGRAM, strerror(errno));
retval = 0;
goto cleanup;
}
@@ -1063,7 +1206,9 @@
margs->AD = 0;
rc = check_AD(margs, ld);
if (rc != LDAP_SUCCESS) {
- error((char *) "%s| %s: ERROR: Error determining ldap server type: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+ error((char *)
+ "%s| %s: ERROR: Error determining ldap server type: %s\n",
+ LogTime(), PROGRAM, ldap_err2string(rc));
ldap_unbind_ext(ld, NULL, NULL);
ld = NULL;
retval = 0;
@@ -1082,20 +1227,24 @@
xfree(ldap_filter_esc);
- debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter : %s\n", LogTime(), PROGRAM, bindp, search_exp);
- rc = ldap_search_ext_s(ld, bindp, LDAP_SCOPE_SUBTREE,
- search_exp, NULL, 0,
+ debug((char *)
+ "%s| %s: DEBUG: Search ldap server with bind path %s and filter : %s\n",
+ LogTime(), PROGRAM, bindp, search_exp);
+ rc = ldap_search_ext_s(ld, bindp, LDAP_SCOPE_SUBTREE, search_exp, NULL, 0,
NULL, NULL, &searchtime, 0, &res);
xfree(search_exp);
if (rc != LDAP_SUCCESS) {
- error((char *) "%s| %s: ERROR: Error searching ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+ error((char *) "%s| %s: ERROR: Error searching ldap server: %s\n",
+ LogTime(), PROGRAM, ldap_err2string(rc));
ldap_unbind_ext(ld, NULL, NULL);
ld = NULL;
retval = 0;
goto cleanup;
}
- debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM, ldap_count_entries(ld, res), ldap_count_entries(ld, res) > 1 || ldap_count_entries(ld, res) == 0 ? "ies" : "y");
+ debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM,
+ ldap_count_entries(ld, res), ldap_count_entries(ld, res) > 1
+ || ldap_count_entries(ld, res) == 0 ? "ies" : "y");
if (ldap_count_entries(ld, res) != 0) {
@@ -1122,7 +1271,8 @@
}
}
if (debug_enabled) {
- debug((char *) "%s| %s: DEBUG: Entry %" PRIuSIZE " \"%s\" in hex UTF-8 is ", LogTime(), PROGRAM, k + 1, av);
+ debug((char *) "%s| %s: DEBUG: Entry %" PRIuSIZE
+ " \"%s\" in hex UTF-8 is ", LogTime(), PROGRAM, k + 1, av);
for (unsigned int n = 0; av[n] != '\0'; ++n)
fprintf(stderr, "%02x", (unsigned char) av[n]);
fprintf(stderr, "\n");
@@ -1130,18 +1280,24 @@
if (!strcasecmp(group, av)) {
retval = 1;
if (debug_enabled)
- debug((char *) "%s| %s: DEBUG: Entry %" PRIuSIZE " \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM, k + 1, av, group);
+ debug((char *) "%s| %s: DEBUG: Entry %" PRIuSIZE
+ " \"%s\" matches group name \"%s\"\n", LogTime(),
+ PROGRAM, k + 1, av, group);
else
break;
} else
- debug((char *) "%s| %s: DEBUG: Entry %" PRIuSIZE " \"%s\" does not match group name \"%s\"\n", LogTime(), PROGRAM, k + 1, av, group);
+ debug((char *) "%s| %s: DEBUG: Entry %" PRIuSIZE
+ " \"%s\" does not match group name \"%s\"\n", LogTime(),
+ PROGRAM, k + 1, av, group);
}
/*
* Do recursive group search for AD only since posixgroups can not contain other groups
*/
if (!retval && margs->AD) {
if (debug_enabled && max_attr > 0) {
- debug((char *) "%s| %s: DEBUG: Perform recursive group search\n", LogTime(), PROGRAM);
+ debug((char *)
+ "%s| %s: DEBUG: Perform recursive group search\n",
+ LogTime(), PROGRAM);
}
for (size_t j = 0; j < max_attr; ++j) {
char *av = NULL;
@@ -1157,7 +1313,9 @@
}
}
if (debug_enabled)
- debug((char *) "%s| %s: DEBUG: Entry %" PRIuSIZE " group \"%s\" is (in)direct member of group \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
+ debug((char *) "%s| %s: DEBUG: Entry %" PRIuSIZE
+ " group \"%s\" is (in)direct member of group \"%s\"\n",
+ LogTime(), PROGRAM, j + 1, av, group);
else
break;
}
@@ -1188,7 +1346,9 @@
/*
* Check for primary Group membership
*/
- debug((char *) "%s| %s: DEBUG: Search for primary group membership: \"%s\"\n", LogTime(), PROGRAM, group);
+ debug((char *)
+ "%s| %s: DEBUG: Search for primary group membership: \"%s\"\n",
+ LogTime(), PROGRAM, group);
if (margs->AD)
filter = (char *) FILTER_AD;
else
@@ -1202,18 +1362,22 @@
xfree(ldap_filter_esc);
- debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n", LogTime(), PROGRAM, bindp, search_exp);
- rc = ldap_search_ext_s(ld, bindp, LDAP_SCOPE_SUBTREE,
- search_exp, NULL, 0,
- NULL, NULL, &searchtime, 0, &res);
+ debug((char *)
+ "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n",
+ LogTime(), PROGRAM, bindp, search_exp);
+ rc = ldap_search_ext_s(ld, bindp, LDAP_SCOPE_SUBTREE, search_exp, NULL,
+ 0, NULL, NULL, &searchtime, 0, &res);
xfree(search_exp);
- debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM, ldap_count_entries(ld, res), ldap_count_entries(ld, res) > 1 || ldap_count_entries(ld, res) == 0 ? "ies" : "y");
+ debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(),
+ PROGRAM, ldap_count_entries(ld, res), ldap_count_entries(ld,
+ res) > 1 || ldap_count_entries(ld, res) == 0 ? "ies" : "y");
max_attr = 0;
if (!rc) {
if (margs->AD)
- max_attr = get_attributes(ld, res, ATTRIBUTE_GID_AD, &attr_value);
+ max_attr =
+ get_attributes(ld, res, ATTRIBUTE_GID_AD, &attr_value);
else
max_attr = get_attributes(ld, res, ATTRIBUTE_GID, &attr_value);
}
@@ -1226,48 +1390,61 @@
char **attr_value_3 = NULL;
int *attr_len_3 = NULL;
size_t max_attr_3 = 0;
- uint32_t gid=atoi(attr_value[0]);
+ uint32_t gid = atoi(attr_value[0]);
/* Get objectsid and search for group
* with objectsid = domain(objectsid) + primarygroupid */
- debug((char *) "%s| %s: DEBUG: Got primaryGroupID %u\n", LogTime(), PROGRAM, gid);
- max_attr_3 = get_bin_attributes(ld, res, ATTRIBUTE_SID, &attr_value_3, &attr_len_3);
+ debug((char *) "%s| %s: DEBUG: Got primaryGroupID %u\n",
+ LogTime(), PROGRAM, gid);
+ max_attr_3 =
+ get_bin_attributes(ld, res, ATTRIBUTE_SID, &attr_value_3,
+ &attr_len_3);
ldap_msgfree(res);
if (max_attr_3 == 1) {
- int len=attr_len_3[0];
+ int len = attr_len_3[0];
if (len < 4) {
- debug((char *) "%s| %s: ERROR: Length %d is too short for objectSID\n", LogTime(), PROGRAM, len);
+ debug((char *)
+ "%s| %s: ERROR: Length %d is too short for objectSID\n",
+ LogTime(), PROGRAM, len);
rc = 1;
} else {
- char *se=NULL;
- attr_value_3[0][len-1]=((gid>>24) & 0xff);
- attr_value_3[0][len-2]=((gid>>16) & 0xff);
- attr_value_3[0][len-3]=((gid>>8) & 0xff);
- attr_value_3[0][len-4]=((gid>>0) & 0xff);
+ char *se = NULL;
+ attr_value_3[0][len - 1] = ((gid >> 24) & 0xff);
+ attr_value_3[0][len - 2] = ((gid >> 16) & 0xff);
+ attr_value_3[0][len - 3] = ((gid >> 8) & 0xff);
+ attr_value_3[0][len - 4] = ((gid >> 0) & 0xff);
#define FILTER_SID_1 "(objectSID="
#define FILTER_SID_2 ")"
- se_len = strlen(FILTER_SID_1) + len*3 + strlen(FILTER_SID_2) + 1;
+ se_len =
+ strlen(FILTER_SID_1) + len * 3 +
+ strlen(FILTER_SID_2) + 1;
search_exp = (char *) xmalloc(se_len);
- snprintf(search_exp, se_len, "%s", FILTER_SID_1 );
+ snprintf(search_exp, se_len, "%s", FILTER_SID_1);
- for (int j=0; j 1 || ldap_count_entries(ld, res) == 0 ? "ies" : "y");
+ debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n",
+ LogTime(), PROGRAM, ldap_count_entries(ld, res),
+ ldap_count_entries(ld, res) > 1
+ || ldap_count_entries(ld, res) == 0 ? "ies" : "y");
}
} else {
@@ -1295,18 +1472,21 @@
xfree(ldap_filter_esc);
- debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n", LogTime(), PROGRAM, bindp, search_exp);
+ debug((char *)
+ "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n",
+ LogTime(), PROGRAM, bindp, search_exp);
rc = ldap_search_ext_s(ld, bindp, LDAP_SCOPE_SUBTREE,
- search_exp, NULL, 0,
- NULL, NULL, &searchtime, 0, &res);
+ search_exp, NULL, 0, NULL, NULL, &searchtime, 0, &res);
xfree(search_exp);
}
if (!rc) {
if (margs->AD)
- max_attr_2 = get_attributes(ld, res, ATTRIBUTE_DN, &attr_value_2);
+ max_attr_2 =
+ get_attributes(ld, res, ATTRIBUTE_DN, &attr_value_2);
else
- max_attr_2 = get_attributes(ld, res, ATTRIBUTE, &attr_value_2);
+ max_attr_2 =
+ get_attributes(ld, res, ATTRIBUTE, &attr_value_2);
ldap_msgfree(res);
} else {
ldap_msgfree(res);
@@ -1327,9 +1507,13 @@
}
if (!strcasecmp(group, av)) {
retval = 1;
- debug((char *) "%s| %s: DEBUG: \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM, av, group);
+ debug((char *)
+ "%s| %s: DEBUG: \"%s\" matches group name \"%s\"\n",
+ LogTime(), PROGRAM, av, group);
} else
- debug((char *) "%s| %s: DEBUG: \"%s\" does not match group name \"%s\"\n", LogTime(), PROGRAM, av, group);
+ debug((char *)
+ "%s| %s: DEBUG: \"%s\" does not match group name \"%s\"\n",
+ LogTime(), PROGRAM, av, group);
}
/*
@@ -1337,7 +1521,9 @@
*/
if (!retval && margs->AD) {
if (debug_enabled && max_attr_2 > 0) {
- debug((char *) "%s| %s: DEBUG: Perform recursive group search\n", LogTime(), PROGRAM);
+ debug((char *)
+ "%s| %s: DEBUG: Perform recursive group search\n",
+ LogTime(), PROGRAM);
}
for (size_t j = 0; j < max_attr_2; ++j) {
char *av = NULL;
@@ -1353,7 +1539,9 @@
}
}
if (debug_enabled) {
- debug((char *) "%s| %s: DEBUG: Entry %" PRIuSIZE " group \"%s\" is (in)direct member of group \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
+ debug((char *) "%s| %s: DEBUG: Entry %" PRIuSIZE
+ " group \"%s\" is (in)direct member of group \"%s\"\n",
+ LogTime(), PROGRAM, j + 1, av, group);
} else {
break;
}
@@ -1371,11 +1559,15 @@
safe_free(attr_value_2);
}
- debug((char *) "%s| %s: DEBUG: Users primary group %s %s\n", LogTime(), PROGRAM, retval ? "matches" : "does not match", group);
+ debug((char *) "%s| %s: DEBUG: Users primary group %s %s\n",
+ LogTime(), PROGRAM, retval ? "matches" : "does not match",
+ group);
} else {
ldap_msgfree(res);
- debug((char *) "%s| %s: DEBUG: Did not find ldap entry for group %s\n", LogTime(), PROGRAM, group);
+ debug((char *)
+ "%s| %s: DEBUG: Did not find ldap entry for group %s\n",
+ LogTime(), PROGRAM, group);
}
/*
* Cleanup
@@ -1390,7 +1582,8 @@
rc = ldap_unbind_ext(ld, NULL, NULL);
ld = NULL;
if (rc != LDAP_SUCCESS) {
- error((char *) "%s| %s: ERROR: Error unbind ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+ error((char *) "%s| %s: ERROR: Error unbind ldap server: %s\n",
+ LogTime(), PROGRAM, ldap_err2string(rc));
}
debug((char *) "%s| %s: DEBUG: Unbind ldap server\n", LogTime(), PROGRAM);
cleanup:
diff -u -r -N squid-4.0.12/src/acl/external/SQL_session/ext_sql_session_acl.8 squid-4.0.13/src/acl/external/SQL_session/ext_sql_session_acl.8
--- squid-4.0.12/src/acl/external/SQL_session/ext_sql_session_acl.8 2016-07-02 02:23:34.000000000 +1200
+++ squid-4.0.13/src/acl/external/SQL_session/ext_sql_session_acl.8 2016-08-06 02:26:22.000000000 +1200
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EXT_SQL_SESSION_ACL 8"
-.TH EXT_SQL_SESSION_ACL 8 "2016-07-01" "perl v5.22.2" "User Contributed Perl Documentation"
+.TH EXT_SQL_SESSION_ACL 8 "2016-08-05" "perl v5.22.2" "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.12/src/acl/external/wbinfo_group/ext_wbinfo_group_acl.8 squid-4.0.13/src/acl/external/wbinfo_group/ext_wbinfo_group_acl.8
--- squid-4.0.12/src/acl/external/wbinfo_group/ext_wbinfo_group_acl.8 2016-07-02 02:23:38.000000000 +1200
+++ squid-4.0.13/src/acl/external/wbinfo_group/ext_wbinfo_group_acl.8 2016-08-06 02:26:28.000000000 +1200
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EXT_WBINFO_GROUP_ACL 8"
-.TH EXT_WBINFO_GROUP_ACL 8 "2016-07-01" "perl v5.22.2" "User Contributed Perl Documentation"
+.TH EXT_WBINFO_GROUP_ACL 8 "2016-08-05" "perl v5.22.2" "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.12/src/adaptation/icap/ServiceRep.cc squid-4.0.13/src/adaptation/icap/ServiceRep.cc
--- squid-4.0.12/src/adaptation/icap/ServiceRep.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/adaptation/icap/ServiceRep.cc 2016-08-06 00:52:55.000000000 +1200
@@ -34,6 +34,9 @@
Adaptation::Icap::ServiceRep::ServiceRep(const ServiceConfigPointer &svcCfg):
AsyncJob("Adaptation::Icap::ServiceRep"), Adaptation::Service(svcCfg),
sslContext(NULL),
+#if USE_OPENSSL
+ sslSession(NULL),
+#endif
theOptions(NULL), theOptionsFetcher(0), theLastUpdate(0),
theBusyConns(0),
theAllWaiters(0),
diff -u -r -N squid-4.0.12/src/adaptation/icap/ServiceRep.h squid-4.0.13/src/adaptation/icap/ServiceRep.h
--- squid-4.0.12/src/adaptation/icap/ServiceRep.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/adaptation/icap/ServiceRep.h 2016-08-06 00:52:55.000000000 +1200
@@ -111,7 +111,9 @@
virtual void noteAdaptationAnswer(const Answer &answer);
Security::ContextPtr sslContext;
- Security::SessionStatePointer sslSession;
+#if USE_OPENSSL
+ SSL_SESSION *sslSession;
+#endif
private:
// stores Prepare() callback info
diff -u -r -N squid-4.0.12/src/adaptation/icap/Xaction.cc squid-4.0.13/src/adaptation/icap/Xaction.cc
--- squid-4.0.12/src/adaptation/icap/Xaction.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/adaptation/icap/Xaction.cc 2016-08-06 00:52:55.000000000 +1200
@@ -30,26 +30,26 @@
#include "icap_log.h"
#include "ipcache.h"
#include "pconn.h"
+#include "security/PeerConnector.h"
#include "SquidConfig.h"
#include "SquidTime.h"
-#if USE_OPENSSL
-/// Gives Ssl::PeerConnector access to Answer in the PeerPoolMgr callback dialer.
+/// Gives Security::PeerConnector access to Answer in the PeerPoolMgr callback dialer.
class MyIcapAnswerDialer: public UnaryMemFunT,
- public Ssl::PeerConnector::CbDialer
+ public Security::PeerConnector::CbDialer
{
public:
MyIcapAnswerDialer(const JobPointer &aJob, Method aMethod):
UnaryMemFunT(aJob, aMethod, Security::EncryptorAnswer()) {}
- /* Ssl::PeerConnector::CbDialer API */
+ /* Security::PeerConnector::CbDialer API */
virtual Security::EncryptorAnswer &answer() { return arg1; }
};
namespace Ssl
{
/// A simple PeerConnector for Secure ICAP services. No SslBump capabilities.
-class IcapPeerConnector: public PeerConnector {
+class IcapPeerConnector: public Security::PeerConnector {
CBDATA_CLASS(IcapPeerConnector);
public:
IcapPeerConnector(
@@ -61,8 +61,8 @@
AsyncJob("Ssl::IcapPeerConnector"),
PeerConnector(aServerConn, aCallback, alp, timeout), icapService(service) {}
- /* PeerConnector API */
- virtual Security::SessionPtr initializeSsl();
+ /* Security::PeerConnector API */
+ virtual bool initializeTls(Security::SessionPointer &);
virtual void noteNegotiationDone(ErrorState *error);
virtual Security::ContextPtr getSslContext() {return icapService->sslContext;}
@@ -72,7 +72,6 @@
} // namespace Ssl
CBDATA_NAMESPACED_CLASS_INIT(Ssl, IcapPeerConnector);
-#endif
Adaptation::Icap::Xaction::Xaction(const char *aTypeName, Adaptation::Icap::ServiceRep::Pointer &aService):
AsyncJob(aTypeName),
@@ -302,7 +301,6 @@
CloseDialer(this,&Adaptation::Icap::Xaction::noteCommClosed));
comm_add_close_handler(io.conn->fd, closer);
-#if USE_OPENSSL
// If it is a reused connection and the SSL object is build
// we should not negotiate new SSL session
const auto &ssl = fd_table[io.conn->fd].ssl;
@@ -311,13 +309,10 @@
securer = asyncCall(93, 4, "Adaptation::Icap::Xaction::handleSecuredPeer",
MyIcapAnswerDialer(me, &Adaptation::Icap::Xaction::handleSecuredPeer));
- Ssl::PeerConnector::HttpRequestPointer tmpReq(NULL);
- Ssl::IcapPeerConnector *sslConnector =
- new Ssl::IcapPeerConnector(theService, io.conn, securer, masterLogEntry(), TheConfig.connect_timeout(service().cfg().bypass));
+ auto *sslConnector = new Ssl::IcapPeerConnector(theService, io.conn, securer, masterLogEntry(), TheConfig.connect_timeout(service().cfg().bypass));
AsyncJob::Start(sslConnector); // will call our callback
return;
}
-#endif
// ?? fd_table[io.conn->fd].noteUse(icapPconnPool);
service().noteConnectionUse(connection);
@@ -709,25 +704,28 @@
return false;
}
-#if USE_OPENSSL
-Security::SessionPtr
-Ssl::IcapPeerConnector::initializeSsl()
+bool
+Ssl::IcapPeerConnector::initializeTls(Security::SessionPointer &serverSession)
{
- auto ssl = Ssl::PeerConnector::initializeSsl();
- if (!ssl)
- return nullptr;
+ if (!Security::PeerConnector::initializeTls(serverSession))
+ return false;
+#if USE_OPENSSL
assert(!icapService->cfg().secure.sslDomain.isEmpty());
SBuf *host = new SBuf(icapService->cfg().secure.sslDomain);
- SSL_set_ex_data(ssl, ssl_ex_index_server, host);
+ SSL_set_ex_data(serverSession.get(), ssl_ex_index_server, host);
- ACLFilledChecklist *check = (ACLFilledChecklist *)SSL_get_ex_data(ssl, ssl_ex_index_cert_error_check);
+ ACLFilledChecklist *check = static_cast(SSL_get_ex_data(serverSession.get(), ssl_ex_index_cert_error_check));
if (check)
check->dst_peer_name = *host;
- Security::GetSessionResumeData(Security::SessionPointer(ssl), icapService->sslSession);
+ if (icapService->sslSession)
+ SSL_set_session(serverSession.get(), icapService->sslSession);
- return ssl;
+ return true;
+#else
+ return false;
+#endif
}
void
@@ -736,8 +734,16 @@
if (error)
return;
+#if USE_OPENSSL
const int fd = serverConnection()->fd;
- Security::GetSessionResumeData(fd_table[fd].ssl, icapService->sslSession);
+ auto ssl = fd_table[fd].ssl.get();
+ assert(ssl);
+ if (!SSL_session_reused(ssl)) {
+ if (icapService->sslSession)
+ SSL_SESSION_free(icapService->sslSession);
+ icapService->sslSession = SSL_get1_session(ssl);
+ }
+#endif
}
void
@@ -770,5 +776,4 @@
handleCommConnected();
}
-#endif
diff -u -r -N squid-4.0.12/src/adaptation/icap/Xaction.h squid-4.0.13/src/adaptation/icap/Xaction.h
--- squid-4.0.12/src/adaptation/icap/Xaction.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/adaptation/icap/Xaction.h 2016-08-06 00:52:55.000000000 +1200
@@ -16,9 +16,6 @@
#include "HttpReply.h"
#include "ipcache.h"
#include "sbuf/SBuf.h"
-#if USE_OPENSSL
-#include "ssl/PeerConnector.h"
-#endif
class MemBuf;
diff -u -r -N squid-4.0.12/src/anyp/PortCfg.cc squid-4.0.13/src/anyp/PortCfg.cc
--- squid-4.0.12/src/anyp/PortCfg.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/anyp/PortCfg.cc 2016-08-06 00:52:55.000000000 +1200
@@ -143,8 +143,7 @@
}
}
- secure.staticContext.reset(secure.createStaticServerContext(*this));
- if (!secure.staticContext) {
+ if (!secure.createStaticServerContext(*this)) {
char buf[128];
fatalf("%s_port %s initialization error", AnyP::ProtocolType_str[transport.protocol], s.toUrl(buf, sizeof(buf)));
}
diff -u -r -N squid-4.0.12/src/auth/basic/DB/basic_db_auth.8 squid-4.0.13/src/auth/basic/DB/basic_db_auth.8
--- squid-4.0.12/src/auth/basic/DB/basic_db_auth.8 2016-07-02 02:24:02.000000000 +1200
+++ squid-4.0.13/src/auth/basic/DB/basic_db_auth.8 2016-08-06 02:27:20.000000000 +1200
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BASIC_DB_AUTH 8"
-.TH BASIC_DB_AUTH 8 "2016-07-01" "perl v5.22.2" "User Contributed Perl Documentation"
+.TH BASIC_DB_AUTH 8 "2016-08-05" "perl v5.22.2" "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
@@ -182,7 +182,10 @@
Database contains plain-text passwords
.IP "\fB\-\-md5\fR" 12
.IX Item "--md5"
-Database contains unsalted md5 passwords
+Database contains unsalted \s-1MD5\s0 passwords
+.IP "\fB\-\-sha1\fR" 12
+.IX Item "--sha1"
+Database contains unsalted \s-1SHA1\s0 passwords
.IP "\fB\-\-salt\fR" 12
.IX Item "--salt"
Selects the correct salt to evaluate passwords
diff -u -r -N squid-4.0.12/src/auth/basic/DB/basic_db_auth.pl.in squid-4.0.13/src/auth/basic/DB/basic_db_auth.pl.in
--- squid-4.0.12/src/auth/basic/DB/basic_db_auth.pl.in 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/auth/basic/DB/basic_db_auth.pl.in 2016-08-06 00:52:55.000000000 +1200
@@ -61,7 +61,11 @@
=item B<--md5>
-Database contains unsalted md5 passwords
+Database contains unsalted MD5 passwords
+
+=item B<--sha1>
+
+Database contains unsalted SHA1 passwords
=item B<--salt>
@@ -127,6 +131,7 @@
use DBI;
use Digest::MD5 qw(md5 md5_hex md5_base64);
+use Digest::SHA qw(sha1 sha1_hex sha1_base64);
my $dsn = "DBI:mysql:database=squid";
my $db_user = undef;
@@ -137,6 +142,7 @@
my $db_cond = "enabled = 1";
my $plaintext = 0;
my $md5 = 0;
+my $sha1 = 0;
my $persist = 0;
my $isjoomla = 0;
my $debug = 0;
@@ -152,6 +158,7 @@
'cond=s' => \$db_cond,
'plaintext' => \$plaintext,
'md5' => \$md5,
+ 'sha1' => \$sha1,
'persist' => \$persist,
'joomla' => \$isjoomla,
'debug' => \$debug,
@@ -174,7 +181,7 @@
return $_sth if defined $_sth;
$_dbh = DBI->connect($dsn, $db_user, $db_passwd);
if (!defined $_dbh) {
- warn ("Could not connect to $dsn\n");
+ warn ("Could not connect to $dsn\n");
my @driver_names = DBI->available_drivers();
my $msg = "DSN drivers apparently installed, available:\n";
foreach my $dn (@driver_names) {
@@ -203,6 +210,7 @@
return 1 if defined $hashsalt && crypt($password, $hashsalt) eq $key;
return 1 if crypt($password, $key) eq $key;
return 1 if $md5 && md5_hex($password) eq $key;
+ return 1 if $sha1 && sha1_hex($password) eq $key;
return 1 if $plaintext && $password eq $key;
}
diff -u -r -N squid-4.0.12/src/auth/basic/POP3/basic_pop3_auth.8 squid-4.0.13/src/auth/basic/POP3/basic_pop3_auth.8
--- squid-4.0.12/src/auth/basic/POP3/basic_pop3_auth.8 2016-07-02 02:24:09.000000000 +1200
+++ squid-4.0.13/src/auth/basic/POP3/basic_pop3_auth.8 2016-08-06 02:27:35.000000000 +1200
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BASIC_POP3_AUTH 8"
-.TH BASIC_POP3_AUTH 8 "2016-07-01" "perl v5.22.2" "User Contributed Perl Documentation"
+.TH BASIC_POP3_AUTH 8 "2016-08-05" "perl v5.22.2" "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.12/src/auth/User.cc squid-4.0.13/src/auth/User.cc
--- squid-4.0.12/src/auth/User.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/auth/User.cc 2016-08-06 00:52:55.000000000 +1200
@@ -201,7 +201,7 @@
/* This ip has already been seen. */
found = 1;
/* update IP ttl */
- ipdata->ip_expiretime = squid_curtime;
+ ipdata->ip_expiretime = squid_curtime + ::Config.authenticateIpTTL;
} else if (ipdata->ip_expiretime <= squid_curtime) {
/* This IP has expired - remove from the seen list */
dlinkDelete(&ipdata->node, &ip_list);
diff -u -r -N squid-4.0.12/src/base/AsyncJob.cc squid-4.0.13/src/base/AsyncJob.cc
--- squid-4.0.12/src/base/AsyncJob.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/base/AsyncJob.cc 2016-08-06 00:52:55.000000000 +1200
@@ -124,8 +124,9 @@
}
void
-AsyncJob::callException(const std::exception &)
+AsyncJob::callException(const std::exception &ex)
{
+ debugs(93, 2, ex.what());
// we must be called asynchronously and hence, the caller must lock us
Must(cbdataReferenceValid(toCbdata()));
diff -u -r -N squid-4.0.12/src/base/HardFun.h squid-4.0.13/src/base/HardFun.h
--- squid-4.0.12/src/base/HardFun.h 1970-01-01 12:00:00.000000000 +1200
+++ squid-4.0.13/src/base/HardFun.h 2016-08-06 00:52:55.000000000 +1200
@@ -0,0 +1,21 @@
+/*
+ * 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_BASE_HARDFUN_H
+#define _SQUID_SRC_BASE_HARDFUN_H
+
+/**
+ * A functor that calls a hard-coded unary function.
+ */
+template
+struct HardFun {
+ ReturnType operator()(ArgType arg) { fun(arg); }
+};
+
+#endif /* _SQUID_SRC_BASE_HARDFUN_H */
+
diff -u -r -N squid-4.0.12/src/base/Makefile.am squid-4.0.13/src/base/Makefile.am
--- squid-4.0.12/src/base/Makefile.am 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/base/Makefile.am 2016-08-06 00:52:55.000000000 +1200
@@ -25,6 +25,7 @@
CharacterSet.h \
CharacterSet.cc \
EnumIterator.h \
+ HardFun.h \
InstanceId.h \
Lock.h \
LookupTable.h \
@@ -38,5 +39,4 @@
Subscription.h \
TextException.cc \
TextException.h \
- TidyPointer.h \
YesNoNone.h
diff -u -r -N squid-4.0.12/src/base/Makefile.in squid-4.0.13/src/base/Makefile.in
--- squid-4.0.12/src/base/Makefile.in 2016-07-02 01:28:45.000000000 +1200
+++ squid-4.0.13/src/base/Makefile.in 2016-08-06 00:54:59.000000000 +1200
@@ -730,6 +730,7 @@
CharacterSet.h \
CharacterSet.cc \
EnumIterator.h \
+ HardFun.h \
InstanceId.h \
Lock.h \
LookupTable.h \
@@ -743,7 +744,6 @@
Subscription.h \
TextException.cc \
TextException.h \
- TidyPointer.h \
YesNoNone.h
all: all-am
diff -u -r -N squid-4.0.12/src/base/TidyPointer.h squid-4.0.13/src/base/TidyPointer.h
--- squid-4.0.12/src/base/TidyPointer.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/base/TidyPointer.h 1970-01-01 12:00:00.000000000 +1200
@@ -1,69 +0,0 @@
-/*
- * 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_BASE_TIDYPOINTER_H
-#define SQUID_BASE_TIDYPOINTER_H
-
-/**
- * A pointer that deletes the object it points to when the pointer's owner or
- * context is gone. Similar to std::unique_ptr but without confusing assignment
- * and with a customizable cleanup method. Prevents memory leaks in
- * the presence of exceptions and processing short cuts.
-*/
-template class TidyPointer
-{
-public:
- /// Delete callback.
- typedef void DCB (T *t);
- TidyPointer(T *t = NULL)
- : raw(t) {}
-public:
- bool operator !() const { return !raw; }
- explicit operator bool() const { return raw; }
- /// Returns raw and possibly NULL pointer
- T *get() const { return raw; }
-
- /// Reset raw pointer - delete last one and save new one.
- void reset(T *t) {
- deletePointer();
- raw = t;
- }
-
- /// Forget the raw pointer without freeing it. Become a nil pointer.
- T *release() {
- T *ret = raw;
- raw = NULL;
- return ret;
- }
- /// Deallocate raw pointer.
- ~TidyPointer() {
- deletePointer();
- }
-private:
- /// Forbidden copy constructor.
- TidyPointer(TidyPointer const &);
- /// Forbidden assigment operator.
- TidyPointer & operator = (TidyPointer const &);
- /// Deallocate raw pointer. Become a nil pointer.
- void deletePointer() {
- if (raw) {
- DeAllocator(raw);
- }
- raw = NULL;
- }
- T *raw; ///< pointer to T object or NULL
-};
-
-/// DeAllocator for pointers that need free(3) from the std C library
-template void tidyFree(T *p)
-{
- xfree(p);
-}
-
-#endif // SQUID_BASE_TIDYPOINTER_H
-
diff -u -r -N squid-4.0.12/src/cache_cf.cc squid-4.0.13/src/cache_cf.cc
--- squid-4.0.12/src/cache_cf.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/cache_cf.cc 2016-08-06 00:52:55.000000000 +1200
@@ -946,10 +946,6 @@
}
}
#endif
-
- if (Config.readAheadGap <= 0) {
- fatalf("read_ahead_gap must be greater than 0 bytes");
- }
}
/** Parse a line containing an obsolete directive.
@@ -2208,6 +2204,8 @@
#endif
} else if (strncmp(token, "tls-", 4) == 0) {
p->secure.parse(token+4);
+ } else if (strncmp(token, "tls", 3) == 0) {
+ p->secure.parse(token+3);
} else if (strcmp(token, "front-end-https") == 0) {
p->front_end_https = 1;
} else if (strcmp(token, "front-end-https=on") == 0) {
diff -u -r -N squid-4.0.12/src/CacheDigest.cc squid-4.0.13/src/CacheDigest.cc
--- squid-4.0.12/src/CacheDigest.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/CacheDigest.cc 2016-08-06 00:52:55.000000000 +1200
@@ -35,11 +35,11 @@
static uint32_t hashed_keys[4];
void
-CacheDigest::init(int newCapacity)
+CacheDigest::init(uint64_t newCapacity)
{
const auto newMaskSz = CacheDigest::CalcMaskSize(newCapacity, bits_per_entry);
assert(newCapacity > 0 && bits_per_entry > 0);
- assert(newMaskSz > 0);
+ assert(newMaskSz != 0);
capacity = newCapacity;
mask_size = newMaskSz;
mask = static_cast(xcalloc(mask_size,1));
@@ -47,13 +47,13 @@
<< mask_size << " bytes");
}
-CacheDigest::CacheDigest(int aCapacity, int bpe) :
+CacheDigest::CacheDigest(uint64_t aCapacity, uint8_t bpe) :
+ count(0),
+ del_count(0),
+ capacity(0),
mask(nullptr),
mask_size(0),
- capacity(0),
- bits_per_entry(bpe),
- count(0),
- del_count(0)
+ bits_per_entry(bpe)
{
assert(SQUID_MD5_DIGEST_LENGTH == 16); /* our hash functions rely on 16 byte keys */
updateCapacity(aCapacity);
@@ -83,7 +83,7 @@
}
void
-CacheDigest::updateCapacity(int newCapacity)
+CacheDigest::updateCapacity(uint64_t newCapacity)
{
safe_free(mask);
init(newCapacity); // will re-init mask and mask_size
@@ -261,12 +261,12 @@
storeAppendPrintf(e, "%s digest: size: %d bytes\n",
label ? label : "", stats.bit_count / 8
);
- storeAppendPrintf(e, "\t entries: count: %d capacity: %d util: %d%%\n",
+ storeAppendPrintf(e, "\t entries: count: %" PRIu64 " capacity: %" PRIu64 " util: %d%%\n",
cd->count,
cd->capacity,
xpercentInt(cd->count, cd->capacity)
);
- storeAppendPrintf(e, "\t deletion attempts: %d\n",
+ storeAppendPrintf(e, "\t deletion attempts: %" PRIu64 "\n",
cd->del_count
);
storeAppendPrintf(e, "\t bits: per entry: %d on: %d capacity: %d util: %d%%\n",
@@ -280,17 +280,18 @@
);
}
-size_t
-CacheDigest::CalcMaskSize(int cap, int bpe)
+uint32_t
+CacheDigest::CalcMaskSize(uint64_t cap, uint8_t bpe)
{
- // XXX: might 32-bit overflow during multiply
- return (size_t) (cap * bpe + 7) / 8;
+ uint64_t bitCount = (cap * bpe) + 7;
+ assert(bitCount < INT_MAX); // dont 31-bit overflow later
+ return static_cast(bitCount / 8);
}
static void
cacheDigestHashKey(const CacheDigest * cd, const cache_key * key)
{
- const unsigned int bit_count = cd->mask_size * 8;
+ const uint32_t bit_count = cd->mask_size * 8;
unsigned int tmp_keys[4];
/* we must memcpy to ensure alignment */
memcpy(tmp_keys, key, sizeof(tmp_keys));
diff -u -r -N squid-4.0.12/src/CacheDigest.h squid-4.0.13/src/CacheDigest.h
--- squid-4.0.12/src/CacheDigest.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/CacheDigest.h 2016-08-06 00:52:55.000000000 +1200
@@ -21,7 +21,7 @@
{
MEMPROXY_CLASS(CacheDigest);
public:
- CacheDigest(int capacity, int bpe);
+ CacheDigest(uint64_t capacity, uint8_t bpe);
~CacheDigest();
// NP: only used by broken unit-test
@@ -32,7 +32,7 @@
void clear();
/// changes mask size to fit newCapacity, resets bits to 0
- void updateCapacity(int newCapacity);
+ void updateCapacity(uint64_t newCapacity);
void add(const cache_key * key);
void remove(const cache_key * key);
@@ -45,19 +45,19 @@
/// calculate the size of mask required to digest up to
/// a specified capacity and bitsize.
- static size_t CalcMaskSize(int cap, int bpe);
+ static uint32_t CalcMaskSize(uint64_t cap, uint8_t bpe);
private:
- void init(int newCapacity);
+ void init(uint64_t newCapacity);
public:
/* public, read-only */
- char *mask; /* bit mask */
- int mask_size; /* mask size in bytes */
- int capacity; /* expected maximum for .count, not a hard limit */
- int bits_per_entry; /* number of bits allocated for each entry from capacity */
- int count; /* number of digested entries */
- int del_count; /* number of deletions performed so far */
+ uint64_t count; /* number of digested entries */
+ uint64_t del_count; /* number of deletions performed so far */
+ uint64_t capacity; /* expected maximum for .count, not a hard limit */
+ char *mask; /* bit mask */
+ uint32_t mask_size; /* mask size in bytes */
+ int8_t bits_per_entry; /* number of bits allocated for each entry from capacity */
};
void cacheDigestGuessStatsUpdate(CacheDigestGuessStats * stats, int real_hit, int guess_hit);
diff -u -r -N squid-4.0.12/src/CachePeer.cc squid-4.0.13/src/CachePeer.cc
--- squid-4.0.12/src/CachePeer.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/CachePeer.cc 2016-08-06 00:52:55.000000000 +1200
@@ -42,6 +42,7 @@
domain(NULL),
#if USE_OPENSSL
sslContext(NULL),
+ sslSession(NULL),
#endif
front_end_https(0),
connection_auth(2 /* auto */)
@@ -101,6 +102,9 @@
#if USE_OPENSSL
if (sslContext)
SSL_CTX_free(sslContext);
+
+ if (sslSession)
+ SSL_SESSION_free(sslSession);
#endif
}
diff -u -r -N squid-4.0.12/src/CachePeer.h squid-4.0.13/src/CachePeer.h
--- squid-4.0.12/src/CachePeer.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/CachePeer.h 2016-08-06 00:52:55.000000000 +1200
@@ -184,7 +184,9 @@
/// security settings for peer connection
Security::PeerOptions secure;
Security::ContextPtr sslContext;
- Security::SessionStatePointer sslSession;
+#if USE_OPENSSL
+ SSL_SESSION *sslSession;
+#endif
int front_end_https;
int connection_auth;
diff -u -r -N squid-4.0.12/src/cf.data.pre squid-4.0.13/src/cf.data.pre
--- squid-4.0.12/src/cf.data.pre 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/cf.data.pre 2016-08-06 00:52:55.000000000 +1200
@@ -3308,7 +3308,7 @@
==== SSL / HTTPS / TLS OPTIONS ====
- ssl Encrypt connections to this peer with SSL/TLS.
+ tls Encrypt connections to this peer with TLS.
sslcert=/path/to/ssl/certificate
A client SSL certificate to use when connecting to
@@ -5650,17 +5650,6 @@
DOC_START
The amount of data the cache will buffer ahead of what has been
sent to the client when retrieving an object from another server.
-
- This also influences the maximum network read(2)/write(2) sizes in some
- circumstances. Reducing the size of this buffer will decrease
- per-connection memory usage at the cost of more read(2)/write(2) calls.
- Conversely, increasing the size of this buffer will decrease the number of
- read(2)/write(2) calls at the cost of memory usage, potentially improving
- performance.
-
- Squid does not slow does the response delivery to the client in order to
- fill the buffer.
-
DOC_END
NAME: negative_ttl
@@ -6211,13 +6200,29 @@
potentially cachable requests for the same URI before Squid knows
whether the response is going to be cachable.
- This feature is disabled by default: Enabling collapsed forwarding
- needlessly delays forwarding requests that look cachable (when they are
- collapsed) but then need to be forwarded individually anyway because
- they end up being for uncachable content. However, in some cases, such
- as accelleration of highly cachable content with periodic or groupped
- expiration times, the gains from collapsing [large volumes of
- simultenous refresh requests] outweigh losses from such delays.
+ When enabled, instead of forwarding each concurrent request for
+ the same URL, Squid just sends the first of them. The other, so
+ called "collapsed" requests, wait for the response to the first
+ request and, if it happens to be cachable, use that response.
+ Here, "concurrent requests" means "received after the first
+ request headers were parsed and before the corresponding response
+ headers were parsed".
+
+ This feature is disabled by default: enabling collapsed
+ forwarding needlessly delays forwarding requests that look
+ cachable (when they are collapsed) but then need to be forwarded
+ individually anyway because they end up being for uncachable
+ content. However, in some cases, such as acceleration of highly
+ cachable content with periodic or grouped expiration times, the
+ gains from collapsing [large volumes of simultaneous refresh
+ requests] outweigh losses from such delays.
+
+ Squid collapses two kinds of requests: regular client requests
+ received on one of the listening ports and internal "cache
+ revalidation" requests which are triggered by those regular
+ requests hitting a stale cached object. Revalidation collapsing
+ is currently disabled for Squid instances containing SMP-aware
+ disk or memory caches and for Vary-controlled cached objects.
DOC_END
NAME: collapsed_forwarding_shared_entries_limit
diff -u -r -N squid-4.0.12/src/client_db.h squid-4.0.13/src/client_db.h
--- squid-4.0.12/src/client_db.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/client_db.h 2016-08-06 00:52:55.000000000 +1200
@@ -12,7 +12,6 @@
#define SQUID_CLIENT_DB_H_
#include "anyp/ProtocolType.h"
-//#include "enums.h"
#include "ip/Address.h"
#include "LogTags.h"
diff -u -r -N squid-4.0.12/src/clients/FtpClient.cc squid-4.0.13/src/clients/FtpClient.cc
--- squid-4.0.12/src/clients/FtpClient.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/clients/FtpClient.cc 2016-08-06 00:52:55.000000000 +1200
@@ -314,6 +314,11 @@
/* We've already read some reply data */
handleControlReply();
} else {
+
+ if (!Comm::IsConnOpen(ctrl.conn)) {
+ debugs(9, 3, "cannot read without ctrl " << ctrl.conn);
+ return;
+ }
/*
* Cancel the timeout on the Data socket (if any) and
* establish one on the control socket.
diff -u -r -N squid-4.0.12/src/client_side.cc squid-4.0.13/src/client_side.cc
--- squid-4.0.12/src/client_side.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/client_side.cc 2016-08-06 00:52:55.000000000 +1200
@@ -584,6 +584,8 @@
ConnStateData::swanSong()
{
debugs(33, 2, HERE << clientConnection);
+ checkLogging();
+
flags.readMore = false;
DeregisterRunner(this);
clientdbEstablished(clientConnection->remote, -1); /* decrement */
@@ -1012,9 +1014,12 @@
http->uri = xstrdup(uri);
setLogUri (http, uri);
auto *context = new Http::Stream(clientConnection, http);
+ StoreIOBuffer tempBuffer;
+ tempBuffer.data = context->reqbuf;
+ tempBuffer.length = HTTP_REQBUF_SZ;
clientStreamInit(&http->client_stream, clientGetMoreData, clientReplyDetach,
clientReplyStatus, new clientReplyContext(http), clientSocketRecipient,
- clientSocketDetach, context, context->getClientStreamBuffer());
+ clientSocketDetach, context, tempBuffer);
return context;
}
@@ -1356,11 +1361,15 @@
http->req_sz = hp->messageHeaderSize();
Http::Stream *result = new Http::Stream(csd->clientConnection, http);
+ StoreIOBuffer tempBuffer;
+ tempBuffer.data = result->reqbuf;
+ tempBuffer.length = HTTP_REQBUF_SZ;
+
ClientStreamData newServer = new clientReplyContext(http);
ClientStreamData newClient = result;
clientStreamInit(&http->client_stream, clientGetMoreData, clientReplyDetach,
clientReplyStatus, newServer, clientSocketRecipient,
- clientSocketDetach, newClient, result->getClientStreamBuffer());
+ clientSocketDetach, newClient, tempBuffer);
/* set url */
debugs(33,5, "Prepare absolute URL from " <<
@@ -2134,10 +2143,6 @@
// On errors, bodyPipe may become nil, but readMore will be cleared
while (!inBuf.isEmpty() && !bodyPipe && flags.readMore) {
- /* Don't try to parse if the buffer is empty */
- if (inBuf.isEmpty())
- break;
-
/* Limit the number of concurrent requests */
if (concurrentRequestQueueFilled())
break;
@@ -2570,16 +2575,16 @@
#if USE_OPENSSL
/** Create SSL connection structure and update fd_table */
-static Security::SessionPtr
+static bool
httpsCreate(const Comm::ConnectionPointer &conn, Security::ContextPtr sslContext)
{
- if (auto ssl = Ssl::CreateServer(sslContext, conn->fd, "client https start")) {
+ if (Ssl::CreateServer(sslContext, conn, "client https start")) {
debugs(33, 5, "will negotate SSL on " << conn);
- return ssl;
+ return true;
}
conn->close();
- return nullptr;
+ return false;
}
/**
@@ -2650,7 +2655,7 @@
return;
}
- if (Security::SessionIsResumed(fd_table[fd].ssl)) {
+ if (SSL_session_reused(ssl)) {
debugs(83, 2, "clientNegotiateSSL: Session " << SSL_get_session(ssl) <<
" reused on FD " << fd << " (" << fd_table[fd].ipaddr << ":" << (int)fd_table[fd].remote_port << ")");
} else {
@@ -2725,11 +2730,10 @@
static void
httpsEstablish(ConnStateData *connState, Security::ContextPtr sslContext)
{
- Security::SessionPtr ssl = nullptr;
assert(connState);
const Comm::ConnectionPointer &details = connState->clientConnection;
- if (!sslContext || !(ssl = httpsCreate(details, sslContext)))
+ if (!sslContext || !httpsCreate(details, sslContext))
return;
typedef CommCbMemFunT TimeoutDialer;
@@ -4024,3 +4028,36 @@
* connection has gone away */
}
+void
+ConnStateData::checkLogging()
+{
+ // if we are parsing request body, its request is responsible for logging
+ if (bodyPipe)
+ return;
+
+ // a request currently using this connection is responsible for logging
+ if (!pipeline.empty() && pipeline.back()->mayUseConnection())
+ return;
+
+ /* Either we are waiting for the very first transaction, or
+ * we are done with the Nth transaction and are waiting for N+1st.
+ * XXX: We assume that if anything was added to inBuf, then it could
+ * only be consumed by actions already covered by the above checks.
+ */
+
+ // do not log connections that closed after a transaction (it is normal)
+ // TODO: access_log needs ACLs to match received-no-bytes connections
+ // XXX: TLS may return here even though we got no transactions yet
+ // XXX: PROXY protocol may return here even though we got no
+ // transactions yet
+ if (receivedFirstByte_ && inBuf.isEmpty())
+ return;
+
+ /* Create a temporary ClientHttpRequest object. Its destructor will log. */
+ ClientHttpRequest http(this);
+ http.req_sz = inBuf.length();
+ char const *uri = "error:transaction-end-before-headers";
+ http.uri = xstrdup(uri);
+ setLogUri(&http, uri);
+}
+
diff -u -r -N squid-4.0.12/src/client_side.h squid-4.0.13/src/client_side.h
--- squid-4.0.12/src/client_side.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/client_side.h 2016-08-06 00:52:55.000000000 +1200
@@ -329,6 +329,7 @@
private:
/* ::Server API */
virtual bool connFinishedWithConn(int size);
+ virtual void checkLogging();
void clientAfterReadingRequests();
bool concurrentRequestQueueFilled() const;
diff -u -r -N squid-4.0.12/src/client_side_reply.cc squid-4.0.13/src/client_side_reply.cc
--- squid-4.0.12/src/client_side_reply.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/client_side_reply.cc 2016-08-06 00:52:55.000000000 +1200
@@ -89,7 +89,8 @@
reply(NULL),
old_entry(NULL),
old_sc(NULL),
- deleting(false)
+ deleting(false),
+ collapsedRevalidation(crNone)
{
*tempbuf = 0;
}
@@ -264,7 +265,6 @@
clientReplyContext::processExpired()
{
const char *url = storeId();
- StoreEntry *entry = NULL;
debugs(88, 3, "clientReplyContext::processExpired: '" << http->uri << "'");
assert(http->storeEntry()->lastmod >= 0);
/*
@@ -287,9 +287,36 @@
#endif
/* Prepare to make a new temporary request */
saveState();
- entry = storeCreateEntry(url,
- http->log_uri, http->request->flags, http->request->method);
- /* NOTE, don't call StoreEntry->lock(), storeCreateEntry() does it */
+
+ // TODO: support collapsed revalidation for Vary-controlled entries
+ const bool collapsingAllowed = Config.onoff.collapsed_forwarding &&
+ !Store::Root().smpAware() &&
+ http->request->vary_headers.isEmpty();
+
+ StoreEntry *entry = nullptr;
+ if (collapsingAllowed) {
+ if ((entry = storeGetPublicByRequest(http->request, ksRevalidation)))
+ entry->lock("clientReplyContext::processExpired#alreadyRevalidating");
+ }
+
+ if (entry) {
+ debugs(88, 5, "collapsed on existing revalidation entry: " << *entry);
+ collapsedRevalidation = crSlave;
+ } else {
+ entry = storeCreateEntry(url,
+ http->log_uri, http->request->flags, http->request->method);
+ /* NOTE, don't call StoreEntry->lock(), storeCreateEntry() does it */
+
+ if (collapsingAllowed) {
+ debugs(88, 5, "allow other revalidation requests to collapse on " << *entry);
+ Store::Root().allowCollapsing(entry, http->request->flags,
+ http->request->method);
+ collapsedRevalidation = crInitiator;
+ } else {
+ collapsedRevalidation = crNone;
+ }
+ }
+
sc = storeClientListAdd(entry, this);
#if USE_DELAY_POOLS
/* delay_id is already set on original store client */
@@ -309,13 +336,14 @@
assert(http->out.offset == 0);
assert(http->request->clientConnectionManager == http->getConn());
- /*
- * A refcounted pointer so that FwdState stays around as long as
- * this clientReplyContext does
- */
- Comm::ConnectionPointer conn = http->getConn() != NULL ? http->getConn()->clientConnection : NULL;
- FwdState::Start(conn, http->storeEntry(), http->request, http->al);
-
+ if (collapsedRevalidation != crSlave) {
+ /*
+ * A refcounted pointer so that FwdState stays around as long as
+ * this clientReplyContext does
+ */
+ Comm::ConnectionPointer conn = http->getConn() != NULL ? http->getConn()->clientConnection : NULL;
+ FwdState::Start(conn, http->storeEntry(), http->request, http->al);
+ }
/* Register with storage manager to receive updates when data comes in. */
if (EBIT_TEST(entry->flags, ENTRY_ABORTED))
@@ -427,6 +455,10 @@
// forward response from origin
http->logType = LOG_TCP_REFRESH_MODIFIED;
debugs(88, 3, "handleIMSReply: origin replied " << status << ", replacing existing entry and forwarding to client");
+
+ if (collapsedRevalidation)
+ http->storeEntry()->clearPublicKeyScope();
+
sendClientUpstreamResponse();
}
@@ -2121,21 +2153,28 @@
StoreEntry *entry = http->storeEntry();
- ConnStateData * conn = http->getConn();
+ if (ConnStateData * conn = http->getConn()) {
+ if (!conn->isOpen()) {
+ debugs(33,3, "not sending more data to closing connection " << conn->clientConnection);
+ return;
+ }
+ if (conn->pinning.zeroReply) {
+ debugs(33,3, "not sending more data after a pinned zero reply " << conn->clientConnection);
+ return;
+ }
+
+ if (reqofs==0 && !http->logType.isTcpHit()) {
+ if (Ip::Qos::TheConfig.isHitTosActive()) {
+ Ip::Qos::doTosLocalMiss(conn->clientConnection, http->request->hier.code);
+ }
+ if (Ip::Qos::TheConfig.isHitNfmarkActive()) {
+ Ip::Qos::doNfmarkLocalMiss(conn->clientConnection, http->request->hier.code);
+ }
+ }
- // too late, our conn is closing
- // TODO: should we also quit?
- if (conn == NULL) {
- debugs(33,3, "not sending more data to a closed connection" );
- return;
- }
- if (!conn->isOpen()) {
- debugs(33,3, "not sending more data to closing connection " << conn->clientConnection);
- return;
- }
- if (conn->pinning.zeroReply) {
- debugs(33,3, "not sending more data after a pinned zero reply " << conn->clientConnection);
- return;
+ debugs(88, 5, conn->clientConnection <<
+ " '" << entry->url() << "'" <<
+ " out.offset=" << http->out.offset);
}
char *buf = next()->readBuffer.data;
@@ -2146,15 +2185,6 @@
memcpy(buf, result.data, result.length);
}
- if (reqofs==0 && !http->logType.isTcpHit() && Comm::IsConnOpen(conn->clientConnection)) {
- if (Ip::Qos::TheConfig.isHitTosActive()) {
- Ip::Qos::doTosLocalMiss(conn->clientConnection, http->request->hier.code);
- }
- if (Ip::Qos::TheConfig.isHitNfmarkActive()) {
- Ip::Qos::doNfmarkLocalMiss(conn->clientConnection, http->request->hier.code);
- }
- }
-
/* We've got the final data to start pushing... */
flags.storelogiccomplete = 1;
@@ -2173,10 +2203,6 @@
debugs(88, 5, "clientReplyContext::sendMoreData: " << http->uri << ", " <<
reqofs << " bytes (" << result.length <<
" new bytes)");
- debugs(88, 5, "clientReplyContext::sendMoreData:"
- << conn->clientConnection <<
- " '" << entry->url() << "'" <<
- " out.offset=" << http->out.offset);
/* update size of the request */
reqsize = reqofs;
diff -u -r -N squid-4.0.12/src/client_side_reply.h squid-4.0.13/src/client_side_reply.h
--- squid-4.0.12/src/client_side_reply.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/client_side_reply.h 2016-08-06 00:52:55.000000000 +1200
@@ -133,6 +133,14 @@
StoreEntry *old_entry;
store_client *old_sc; /* ... for entry to be validated */
bool deleting;
+
+ typedef enum {
+ crNone = 0, ///< collapsed revalidation is not allowed for this context
+ crInitiator, ///< we initiated collapsed revalidation request
+ crSlave ///< we collapsed on the existing revalidation request
+ } CollapsedRevalidation;
+
+ CollapsedRevalidation collapsedRevalidation;
};
#endif /* SQUID_CLIENTSIDEREPLY_H */
diff -u -r -N squid-4.0.12/src/client_side_request.cc squid-4.0.13/src/client_side_request.cc
--- squid-4.0.12/src/client_side_request.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/client_side_request.cc 2016-08-06 00:52:55.000000000 +1200
@@ -177,7 +177,7 @@
#if USE_OPENSSL
if (aConn->clientConnection != NULL && aConn->clientConnection->isOpen()) {
if (auto ssl = fd_table[aConn->clientConnection->fd].ssl.get())
- al->cache.sslClientCert.reset(SSL_get_peer_certificate(ssl));
+ al->cache.sslClientCert.resetWithoutLocking(SSL_get_peer_certificate(ssl));
}
#endif
}
@@ -885,8 +885,7 @@
if (answer == ACCESS_ALLOWED)
redirectStart(http, clientRedirectDoneWrapper, context);
else {
- Helper::Reply nilReply;
- nilReply.result = Helper::Error;
+ Helper::Reply const nilReply(Helper::Error);
context->clientRedirectDone(nilReply);
}
}
@@ -918,8 +917,7 @@
storeIdStart(http, clientStoreIdDoneWrapper, context);
else {
debugs(85, 3, "access denied expected ERR reply handling: " << answer);
- Helper::Reply nilReply;
- nilReply.result = Helper::Error;
+ Helper::Reply const nilReply(Helper::Error);
context->clientStoreIdDone(nilReply);
}
}
@@ -1409,6 +1407,11 @@
bool
ClientRequestContext::sslBumpAccessCheck()
{
+ if (!http->getConn()) {
+ http->al->ssl.bumpMode = Ssl::bumpEnd; // SslBump does not apply; log -
+ return false;
+ }
+
// If SSL connection tunneling or bumping decision has been made, obey it.
const Ssl::BumpMode bumpMode = http->getConn()->sslBumpMode;
if (bumpMode != Ssl::bumpEnd) {
diff -u -r -N squid-4.0.12/src/comm/Read.cc squid-4.0.13/src/comm/Read.cc
--- squid-4.0.12/src/comm/Read.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/comm/Read.cc 2016-08-06 00:52:55.000000000 +1200
@@ -20,7 +20,6 @@
#include "fde.h"
#include "sbuf/SBuf.h"
#include "StatCounters.h"
-//#include "tools.h"
// Does comm check this fd for read readiness?
// Note that when comm is not monitoring, there can be a pending callback
diff -u -r -N squid-4.0.12/src/comm/TcpAcceptor.cc squid-4.0.13/src/comm/TcpAcceptor.cc
--- squid-4.0.12/src/comm/TcpAcceptor.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/comm/TcpAcceptor.cc 2016-08-06 00:52:55.000000000 +1200
@@ -9,6 +9,7 @@
/* DEBUG: section 05 Listener Socket Handler */
#include "squid.h"
+#include "acl/FilledChecklist.h"
#include "anyp/PortCfg.h"
#include "base/TextException.h"
#include "client_db.h"
@@ -24,6 +25,7 @@
#include "globals.h"
#include "ip/Intercept.h"
#include "ip/QosConfig.h"
+#include "log/access_log.h"
#include "MasterXaction.h"
#include "profiler/Profiler.h"
#include "SquidConfig.h"
@@ -256,6 +258,18 @@
return false;
}
+static void
+logAcceptError(const Comm::ConnectionPointer &conn)
+{
+ AccessLogEntry::Pointer al = new AccessLogEntry;
+ al->tcpClient = conn;
+ al->url = "error:accept-client-connection";
+ ACLFilledChecklist ch(nullptr, nullptr, nullptr);
+ ch.src_addr = conn->remote;
+ ch.my_addr = conn->local;
+ accessLogLog(al, &ch);
+}
+
void
Comm::TcpAcceptor::acceptOne()
{
@@ -281,6 +295,8 @@
// A non-recoverable error; notify the caller */
debugs(5, 5, HERE << "non-recoverable error:" << status() << " handler Subscription: " << theCallSub);
+ if (intendedForUserConnections())
+ logAcceptError(newConnDetails);
notify(flag, newConnDetails);
mustStop("Listener socket closed");
return;
diff -u -r -N squid-4.0.12/src/comm/TcpAcceptor.h squid-4.0.13/src/comm/TcpAcceptor.h
--- squid-4.0.12/src/comm/TcpAcceptor.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/comm/TcpAcceptor.h 2016-08-06 00:52:55.000000000 +1200
@@ -104,6 +104,8 @@
Comm::Flag oldAccept(Comm::ConnectionPointer &details);
void setListen();
void handleClosure(const CommCloseCbParams &io);
+ /// whether we are listening on one of the squid.conf *ports
+ bool intendedForUserConnections() const { return bool(listenPort_); }
};
} // namespace Comm
diff -u -r -N squid-4.0.12/src/comm.cc squid-4.0.13/src/comm.cc
--- squid-4.0.12/src/comm.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/comm.cc 2016-08-06 00:52:55.000000000 +1200
@@ -838,7 +838,7 @@
comm_close_complete(const FdeCbParams ¶ms)
{
fde *F = &fd_table[params.fd];
- F->ssl.reset(nullptr);
+ F->ssl.resetWithoutLocking(nullptr);
#if USE_OPENSSL
if (F->dynamicSslContext) {
diff -u -r -N squid-4.0.12/src/Downloader.cc squid-4.0.13/src/Downloader.cc
--- squid-4.0.12/src/Downloader.cc 1970-01-01 12:00:00.000000000 +1200
+++ squid-4.0.13/src/Downloader.cc 2016-08-06 00:52:55.000000000 +1200
@@ -0,0 +1,267 @@
+/*
+ * 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.
+ */
+
+#include "squid.h"
+#include "client_side.h"
+#include "client_side_reply.h"
+#include "client_side_request.h"
+#include "ClientRequestContext.h"
+#include "Downloader.h"
+#include "fatal.h"
+#include "http/one/RequestParser.h"
+#include "http/Stream.h"
+
+CBDATA_CLASS_INIT(Downloader);
+
+/// Used to hold and pass the required info and buffers to the
+/// clientStream callbacks
+class DownloaderContext: public RefCountable
+{
+ MEMPROXY_CLASS(DownloaderContext);
+
+public:
+ typedef RefCount Pointer;
+
+ DownloaderContext(Downloader *dl, ClientHttpRequest *h);
+ ~DownloaderContext();
+ void finished();
+
+ CbcPointer downloader;
+ ClientHttpRequest *http;
+ char requestBuffer[HTTP_REQBUF_SZ];
+};
+
+DownloaderContext::DownloaderContext(Downloader *dl, ClientHttpRequest *h):
+ downloader(dl),
+ http(h)
+{
+ debugs(33, 6, "DownloaderContext constructed, this=" << (void*)this);
+}
+
+DownloaderContext::~DownloaderContext()
+{
+ debugs(33, 6, "DownloaderContext destructed, this=" << (void*)this);
+ if (http)
+ finished();
+}
+
+void
+DownloaderContext::finished()
+{
+ delete http;
+ http = nullptr;
+}
+
+void
+Downloader::CbDialer::print(std::ostream &os) const
+{
+ os << " Http Status:" << status << Raw("body data", object.rawContent(), 64).hex();
+}
+
+Downloader::Downloader(SBuf &url, AsyncCall::Pointer &aCallback, unsigned int level):
+ AsyncJob("Downloader"),
+ url_(url),
+ callback_(aCallback),
+ level_(level)
+{
+}
+
+Downloader::~Downloader()
+{
+}
+
+bool
+Downloader::doneAll() const
+{
+ return (!callback_ || callback_->canceled()) && AsyncJob::doneAll();
+}
+
+static void
+downloaderRecipient(clientStreamNode * node, ClientHttpRequest * http,
+ HttpReply * rep, StoreIOBuffer receivedData)
+{
+ debugs(33, 6, MYNAME);
+ /* Test preconditions */
+ assert(node);
+
+ /* TODO: handle this rather than asserting
+ * - it should only ever happen if we cause an abort and
+ * the callback chain loops back to here, so we can simply return.
+ * However, that itself shouldn't happen, so it stays as an assert for now.
+ */
+ assert(cbdataReferenceValid(node));
+ assert(!node->node.next);
+ DownloaderContext::Pointer context = dynamic_cast(node->data.getRaw());
+ assert(context);
+
+ if (context->downloader.valid())
+ context->downloader->handleReply(node, http, rep, receivedData);
+}
+
+static void
+downloaderDetach(clientStreamNode * node, ClientHttpRequest * http)
+{
+ debugs(33, 5, MYNAME);
+ clientStreamDetach(node, http);
+}
+
+/// Initializes and starts the HTTP GET request to the remote server
+bool
+Downloader::buildRequest()
+{
+ const HttpRequestMethod method = Http::METHOD_GET;
+
+ char *uri = xstrdup(url_.c_str());
+ HttpRequest *const request = HttpRequest::CreateFromUrl(uri, method);
+ if (!request) {
+ debugs(33, 5, "Invalid URI: " << url_);
+ xfree(uri);
+ return false; //earlyError(...)
+ }
+ request->http_ver = Http::ProtocolVersion();
+ request->header.putStr(Http::HdrType::HOST, request->url.host());
+ request->header.putTime(Http::HdrType::DATE, squid_curtime);
+ request->flags.internalClient = true;
+ request->client_addr.setNoAddr();
+#if FOLLOW_X_FORWARDED_FOR
+ request->indirect_client_addr.setNoAddr();
+#endif /* FOLLOW_X_FORWARDED_FOR */
+ request->my_addr.setNoAddr(); /* undefined for internal requests */
+ request->my_addr.port(0);
+ request->downloader = this;
+
+ debugs(11, 2, "HTTP Client Downloader " << this << "/" << id);
+ debugs(11, 2, "HTTP Client REQUEST:\n---------\n" <<
+ request->method << " " << url_ << " " << request->http_ver << "\n" <<
+ "\n----------");
+
+ ClientHttpRequest *const http = new ClientHttpRequest(nullptr);
+ http->request = request;
+ HTTPMSGLOCK(http->request);
+ http->req_sz = 0;
+ http->uri = uri;
+ setLogUri (http, urlCanonicalClean(request));
+
+ context_ = new DownloaderContext(this, http);
+ StoreIOBuffer tempBuffer;
+ tempBuffer.data = context_->requestBuffer;
+ tempBuffer.length = HTTP_REQBUF_SZ;
+
+ ClientStreamData newServer = new clientReplyContext(http);
+ ClientStreamData newClient = context_.getRaw();
+ clientStreamInit(&http->client_stream, clientGetMoreData, clientReplyDetach,
+ clientReplyStatus, newServer, downloaderRecipient,
+ downloaderDetach, newClient, tempBuffer);
+
+ // Build a ClientRequestContext to start doCallouts
+ http->calloutContext = new ClientRequestContext(http);
+ http->doCallouts();
+ return true;
+}
+
+void
+Downloader::start()
+{
+ if (!buildRequest())
+ callBack(Http::scInternalServerError);
+}
+
+void
+Downloader::handleReply(clientStreamNode * node, ClientHttpRequest *http, HttpReply *reply, StoreIOBuffer receivedData)
+{
+ DownloaderContext::Pointer callerContext = dynamic_cast(node->data.getRaw());
+ // TODO: remove the following check:
+ assert(callerContext == context_);
+
+ debugs(33, 4, "Received " << receivedData.length <<
+ " object data, offset: " << receivedData.offset <<
+ " error flag:" << receivedData.flags.error);
+
+ const bool failed = receivedData.flags.error;
+ if (failed) {
+ callBack(Http::scInternalServerError);
+ return;
+ }
+
+ const int64_t existingContent = reply ? reply->content_length : 0;
+ const size_t maxSize = MaxObjectSize > SBuf::maxSize ? SBuf::maxSize : MaxObjectSize;
+ const bool tooLarge = (existingContent > -1 && existingContent > static_cast(maxSize)) ||
+ (maxSize < object_.length()) ||
+ ((maxSize - object_.length()) < receivedData.length);
+
+ if (tooLarge) {
+ callBack(Http::scInternalServerError);
+ return;
+ }
+
+ object_.append(receivedData.data, receivedData.length);
+ http->out.size += receivedData.length;
+ http->out.offset += receivedData.length;
+
+ switch (clientStreamStatus(node, http)) {
+ case STREAM_NONE: {
+ debugs(33, 3, "Get more data");
+ StoreIOBuffer tempBuffer;
+ tempBuffer.offset = http->out.offset;
+ tempBuffer.data = context_->requestBuffer;
+ tempBuffer.length = HTTP_REQBUF_SZ;
+ clientStreamRead(node, http, tempBuffer);
+ }
+ break;
+ case STREAM_COMPLETE:
+ debugs(33, 3, "Object data transfer successfully complete");
+ callBack(Http::scOkay);
+ break;
+ case STREAM_UNPLANNED_COMPLETE:
+ debugs(33, 3, "Object data transfer failed: STREAM_UNPLANNED_COMPLETE");
+ callBack(Http::scInternalServerError);
+ break;
+ case STREAM_FAILED:
+ debugs(33, 3, "Object data transfer failed: STREAM_FAILED");
+ callBack(Http::scInternalServerError);
+ break;
+ default:
+ fatal("unreachable code");
+ }
+}
+
+void
+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());
+}
+
+/// Schedules for execution the "callback" with parameters the status
+/// and object.
+void
+Downloader::callBack(Http::StatusCode const statusCode)
+{
+ CbDialer *dialer = dynamic_cast(callback_->getDialer());
+ Must(dialer);
+ dialer->status = statusCode;
+ if (statusCode == Http::scOkay)
+ dialer->object = object_;
+ 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.
+ CallJobHere(33, 7, CbcPointer(this), Downloader, downloadFinished);
+}
+
diff -u -r -N squid-4.0.12/src/Downloader.h squid-4.0.13/src/Downloader.h
--- squid-4.0.12/src/Downloader.h 1970-01-01 12:00:00.000000000 +1200
+++ squid-4.0.13/src/Downloader.h 2016-08-06 00:52:55.000000000 +1200
@@ -0,0 +1,83 @@
+/*
+ * 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_DOWNLOADER_H
+#define SQUID_DOWNLOADER_H
+
+#include "base/AsyncJob.h"
+#include "defines.h"
+#include "http/forward.h"
+#include "http/StatusCode.h"
+#include "sbuf/SBuf.h"
+
+class ClientHttpRequest;
+class StoreIOBuffer;
+class clientStreamNode;
+class DownloaderContext;
+typedef RefCount DownloaderContextPointer;
+
+/// The Downloader class fetches SBuf-storable things for other Squid
+/// components/transactions using internal requests. For example, it is used
+/// to fetch missing intermediate certificates when validating origin server
+/// certificate chains.
+class Downloader: virtual public AsyncJob
+{
+ CBDATA_CLASS(Downloader);
+public:
+
+ /// Callback data to use with Downloader callbacks.
+ class CbDialer: public CallDialer {
+ public:
+ CbDialer(): status(Http::scNone) {}
+ virtual ~CbDialer() {}
+
+ /* CallDialer API */
+ virtual bool canDial(AsyncCall &call) = 0;
+ virtual void dial(AsyncCall &call) = 0;
+ virtual void print(std::ostream &os) const;
+
+ SBuf object;
+ Http::StatusCode status;
+ };
+
+ Downloader(SBuf &url, AsyncCall::Pointer &aCallback, unsigned int level = 0);
+ virtual ~Downloader();
+
+ /// delays destruction to protect doCallouts()
+ void downloadFinished();
+
+ /// The nested level of Downloader object (downloads inside downloads).
+ unsigned int nestedLevel() const {return level_;}
+
+ void handleReply(clientStreamNode *, ClientHttpRequest *, HttpReply *, StoreIOBuffer);
+
+protected:
+
+ /* AsyncJob API */
+ virtual bool doneAll() const;
+ virtual void start();
+
+private:
+
+ bool buildRequest();
+ void callBack(Http::StatusCode const status);
+
+ /// The maximum allowed object size.
+ static const size_t MaxObjectSize = 1*1024*1024;
+
+ SBuf url_; ///< the url to download
+ AsyncCall::Pointer callback_; ///< callback to call when download finishes
+ SBuf object_; ///< the object body data
+ const unsigned int level_; ///< holds the nested downloads level
+
+ /// Pointer to an object that stores the clientStream required info
+ DownloaderContextPointer context_;
+};
+
+#endif
+
diff -u -r -N squid-4.0.12/src/fde.h squid-4.0.13/src/fde.h
--- squid-4.0.12/src/fde.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/fde.h 2016-08-06 00:52:55.000000000 +1200
@@ -167,7 +167,7 @@
halfClosedReader = NULL;
read_method = NULL;
write_method = NULL;
- ssl.reset(nullptr);
+ ssl.resetWithoutLocking(nullptr);
dynamicSslContext = NULL;
#if _SQUID_WINDOWS_
win32.handle = (long)NULL;
diff -u -r -N squid-4.0.12/src/format/Config.h squid-4.0.13/src/format/Config.h
--- squid-4.0.12/src/format/Config.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/format/Config.h 2016-08-06 00:52:55.000000000 +1200
@@ -10,8 +10,8 @@
#define SQUID_SRC_FORMAT_CONFIG_H
#include "format/Format.h"
-//#include "format/TokenTableEntry.h"
#include "SquidString.h"
+
#include
class StoreEntry;
diff -u -r -N squid-4.0.12/src/format/Token.h squid-4.0.13/src/format/Token.h
--- squid-4.0.12/src/format/Token.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/format/Token.h 2016-08-06 00:52:55.000000000 +1200
@@ -9,7 +9,6 @@
#ifndef _SQUID_FORMAT_TOKEN_H
#define _SQUID_FORMAT_TOKEN_H
-//#include "format/TokenTableEntry.h"
#include "format/ByteCode.h"
/*
diff -u -r -N squid-4.0.12/src/fs/rock/RockSwapDir.h squid-4.0.13/src/fs/rock/RockSwapDir.h
--- squid-4.0.12/src/fs/rock/RockSwapDir.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/fs/rock/RockSwapDir.h 2016-08-06 00:52:55.000000000 +1200
@@ -47,6 +47,7 @@
virtual void swappedOut(const StoreEntry &e);
virtual void create();
virtual void parse(int index, char *path);
+ virtual bool smpAware() const { return true; }
// temporary path to the shared memory map of first slots of cached entries
SBuf inodeMapPath() const;
diff -u -r -N squid-4.0.12/src/fs/ufs/UFSStoreState.cc squid-4.0.13/src/fs/ufs/UFSStoreState.cc
--- squid-4.0.12/src/fs/ufs/UFSStoreState.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/fs/ufs/UFSStoreState.cc 2016-08-06 00:52:55.000000000 +1200
@@ -15,7 +15,6 @@
#include "DiskIO/WriteRequest.h"
#include "Generic.h"
#include "SquidConfig.h"
-#include "SquidList.h"
#include "Store.h"
#include "store/Disk.h"
#include "UFSStoreState.h"
@@ -132,8 +131,9 @@
assert (aCallback);
if (!theFile->canRead()) {
- debugs(79, 3, "UFSStoreState::read_: queueing read because theFile can't read");
- queueRead (buf, size, aOffset, aCallback, aCallbackData);
+ debugs(79, 3, "queueing read because theFile can't read");
+ assert(opening);
+ pending_reads.emplace(buf, size, aOffset, aCallback, aCallbackData);
return;
}
@@ -177,7 +177,8 @@
return false;
}
- queueWrite(buf, size, aOffset, free_func);
+ debugs(79, 3, (void*)this << " queueing write of size " << size);
+ pending_writes.emplace(buf, size, aOffset, free_func);
drainWriteQueue();
return true;
}
@@ -191,28 +192,20 @@
void
Fs::Ufs::UFSStoreState::doWrite()
{
- debugs(79, 3, HERE << this << " UFSStoreState::doWrite");
+ debugs(79, 3, (void*)this);
assert(theFile->canWrite());
- _queued_write *q = (_queued_write *)linklistShift(&pending_writes);
-
- if (q == NULL) {
- debugs(79, 3, HERE << this << " UFSStoreState::doWrite queue is empty");
+ if (pending_writes.empty()) {
+ debugs(79, 3, (void*)this << " write queue is empty");
return;
}
+ auto &q = pending_writes.front();
+
if (theFile->error()) {
- debugs(79, DBG_IMPORTANT,HERE << "avoid write on theFile with error");
- debugs(79,3,HERE << "calling free_func for " << (void*) q->buf);
- /*
- * DPW 2006-05-24
- * Note "free_func" is memNodeWriteComplete(), which doesn't
- * really free the memory. Instead it clears the node's
- * write_pending flag.
- */
- q->free_func((void*)q->buf);
- delete q;
+ debugs(79, DBG_IMPORTANT, MYNAME << " avoid write on theFile with error");
+ pending_writes.pop();
return;
}
@@ -226,10 +219,11 @@
* coming in. For now let's just not use the writing flag at
* all.
*/
- debugs(79, 3, HERE << this << " calling theFile->write(" << q->size << ")");
+ debugs(79, 3, (void*)this << " calling theFile->write(" << q.size << ")");
- theFile->write(new WriteRequest(q->buf, q->offset, q->size, q->free_func));
- delete q;
+ theFile->write(new WriteRequest(q.buf, q.offset, q.size, q.free_func));
+ q.buf = nullptr; // prevent buf deletion on pop, its used by the above object
+ pending_writes.pop();
}
void
@@ -338,8 +332,6 @@
closing(false),
reading(false),
writing(false),
- pending_reads(NULL),
- pending_writes(NULL),
read_buf(NULL)
{
// StoreIOState inherited members
@@ -354,71 +346,44 @@
Fs::Ufs::UFSStoreState::~UFSStoreState()
{
- assert(pending_reads == NULL);
- assert(pending_writes == NULL);
+ assert(pending_reads.empty());
+ assert(pending_writes.empty());
}
void
Fs::Ufs::UFSStoreState::freePending()
{
- _queued_read *qr;
-
- while ((qr = (_queued_read *)linklistShift(&pending_reads))) {
- cbdataReferenceDone(qr->callback_data);
- delete qr;
- }
-
- debugs(79,3,HERE << "UFSStoreState::freePending: freed pending reads");
-
- _queued_write *qw;
-
- while ((qw = (_queued_write *)linklistShift(&pending_writes))) {
- if (qw->free_func)
- qw->free_func(const_cast(qw->buf));
- delete qw;
- }
-
- debugs(79,3,HERE << "UFSStoreState::freePending: freed pending writes");
+ while (!pending_reads.empty())
+ pending_reads.pop();
+ debugs(79, 3, "freed pending reads");
+
+ while (!pending_writes.empty())
+ pending_writes.pop();
+ debugs(79, 3, "freed pending writes");
}
bool
Fs::Ufs::UFSStoreState::kickReadQueue()
{
- _queued_read *q = (_queued_read *)linklistShift(&pending_reads);
-
- if (NULL == q)
+ if (pending_reads.empty())
return false;
- debugs(79, 3, "UFSStoreState::kickReadQueue: reading queued request of " << q->size << " bytes");
+ auto &q = pending_reads.front();
- void *cbdata;
+ debugs(79, 3, "reading queued request of " << q.size << " bytes");
- if (cbdataReferenceValidDone(q->callback_data, &cbdata)) {
- read_(q->buf, q->size, q->offset, q->callback, cbdata);
+ bool result = true;
+ void *cbdata;
+ if (cbdataReferenceValidDone(q.callback_data, &cbdata)) {
+ read_(q.buf, q.size, q.offset, q.callback, cbdata);
} else {
- debugs(79, 2, "UFSStoreState::kickReadQueue: this: " << this << " cbdataReferenceValidDone returned false." << " closing: " << closing << " flags.try_closing: " << flags.try_closing);
- delete q;
- return false;
+ debugs(79, 2, "this=" << (void*)this << " cbdataReferenceValidDone returned false." <<
+ " closing: " << closing << " flags.try_closing: " << flags.try_closing);
+ result = false;
}
- delete q;
-
- return true;
-}
-
-void
-Fs::Ufs::UFSStoreState::queueRead(char *buf, size_t size, off_t aOffset, STRCB *callback_, void *callback_data_)
-{
- debugs(79, 3, "UFSStoreState::queueRead: queueing read");
- assert(opening);
- assert (pending_reads == NULL);
- _queued_read *q = new _queued_read;
- q->buf = buf;
- q->size = size;
- q->offset = aOffset;
- q->callback = callback_;
- q->callback_data = cbdataReference(callback_data_);
- linklistPush(&pending_reads, q);
+ pending_reads.pop(); // erase the front object
+ return result;
}
/*
@@ -445,9 +410,8 @@
flags.write_draining = true;
- while (pending_writes != NULL) {
+ while (!pending_writes.empty())
doWrite();
- }
flags.write_draining = false;
@@ -482,17 +446,3 @@
theFile->close();
}
-void
-Fs::Ufs::UFSStoreState::queueWrite(char const *buf, size_t size, off_t aOffset, FREE * free_func)
-{
- debugs(79, 3, HERE << this << " UFSStoreState::queueWrite: queueing write of size " << size);
-
- _queued_write *q;
- q = new _queued_write;
- q->buf = buf;
- q->size = size;
- q->offset = aOffset;
- q->free_func = free_func;
- linklistPush(&pending_writes, q);
-}
-
diff -u -r -N squid-4.0.12/src/fs/ufs/UFSStoreState.h squid-4.0.13/src/fs/ufs/UFSStoreState.h
--- squid-4.0.12/src/fs/ufs/UFSStoreState.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/fs/ufs/UFSStoreState.h 2016-08-06 00:52:55.000000000 +1200
@@ -10,9 +10,10 @@
#define SQUID_FS_UFS_UFSSTORESTATE_H
#include "DiskIO/IORequestor.h"
-#include "SquidList.h"
#include "StoreIOState.h"
+#include
+
namespace Fs
{
namespace Ufs
@@ -48,13 +49,16 @@
{
MEMPROXY_CLASS(UFSStoreState::_queued_read);
public:
- _queued_read() :
- buf(nullptr),
- size(0),
- offset(0),
- callback(nullptr),
- callback_data(nullptr)
+ _queued_read(char *b, size_t s, off_t o, STRCB *cb, void *data) :
+ buf(b),
+ size(s),
+ offset(o),
+ callback(cb),
+ callback_data(cbdataReference(data))
{}
+ ~_queued_read() {
+ cbdataReferenceDone(callback_data);
+ }
char *buf;
size_t size;
@@ -62,23 +66,35 @@
STRCB *callback;
void *callback_data;
};
+ std::queue pending_reads;
class _queued_write
{
MEMPROXY_CLASS(UFSStoreState::_queued_write);
public:
- _queued_write() :
- buf(nullptr),
- size(0),
- offset(0),
- free_func(nullptr)
+ _queued_write(const char *b, size_t s, off_t o, FREE *f) :
+ buf(b),
+ size(s),
+ offset(o),
+ free_func(f)
{}
+ ~_queued_write() {
+ /*
+ * DPW 2006-05-24
+ * Note "free_func" is memNodeWriteComplete(), which doesn't
+ * really free the memory. Instead it clears the node's
+ * write_pending flag.
+ */
+ if (free_func && buf)
+ free_func(const_cast(buf));
+ }
char const *buf;
size_t size;
off_t offset;
FREE *free_func;
};
+ std::queue pending_writes;
/** \todo These should be in the IO strategy */
@@ -98,10 +114,7 @@
*/
bool try_closing;
} flags;
- link_list *pending_reads;
- link_list *pending_writes;
- void queueRead(char *, size_t, off_t, STRCB *, void *);
- void queueWrite(char const *, size_t, off_t, FREE *);
+
bool kickReadQueue();
void drainWriteQueue();
void tryClosing();
diff -u -r -N squid-4.0.12/src/fs/ufs/UFSSwapDir.h squid-4.0.13/src/fs/ufs/UFSSwapDir.h
--- squid-4.0.12/src/fs/ufs/UFSSwapDir.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/fs/ufs/UFSSwapDir.h 2016-08-06 00:52:55.000000000 +1200
@@ -71,6 +71,7 @@
virtual uint64_t currentSize() const override { return cur_size; }
virtual uint64_t currentCount() const override { return n_disk_objects; }
virtual ConfigOption *getOptionTree() const override;
+ virtual bool smpAware() const override { return false; }
void unlinkFile(sfileno f);
// move down when unlink is a virtual method
diff -u -r -N squid-4.0.12/src/FwdState.cc squid-4.0.13/src/FwdState.cc
--- squid-4.0.12/src/FwdState.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/FwdState.cc 2016-08-06 00:52:55.000000000 +1200
@@ -45,9 +45,9 @@
#include "pconn.h"
#include "PeerPoolMgr.h"
#include "PeerSelectState.h"
+#include "security/BlindPeerConnector.h"
#include "SquidConfig.h"
#include "SquidTime.h"
-#include "ssl/BlindPeerConnector.h"
#include "ssl/PeekingPeerConnector.h"
#include "Store.h"
#include "StoreClient.h"
@@ -78,8 +78,7 @@
static PconnPool *fwdPconnPool = new PconnPool("server-peers", NULL);
CBDATA_CLASS_INIT(FwdState);
-#if USE_OPENSSL
-class FwdStatePeerAnswerDialer: public CallDialer, public Ssl::PeerConnector::CbDialer
+class FwdStatePeerAnswerDialer: public CallDialer, public Security::PeerConnector::CbDialer
{
public:
typedef void (FwdState::*Method)(Security::EncryptorAnswer &);
@@ -94,7 +93,7 @@
os << '(' << fwd_.get() << ", " << answer_ << ')';
}
- /* Ssl::PeerConnector::CbDialer API */
+ /* Security::PeerConnector::CbDialer API */
virtual Security::EncryptorAnswer &answer() { return answer_; }
private:
@@ -102,7 +101,6 @@
CbcPointer fwd_;
Security::EncryptorAnswer answer_;
};
-#endif
void
FwdState::abort(void* d)
@@ -684,7 +682,6 @@
closeHandler = comm_add_close_handler(serverConnection()->fd, fwdServerClosedWrapper, this);
-#if USE_OPENSSL
if (!request->flags.pinned) {
const CachePeer *p = serverConnection()->getPeer();
const bool peerWantsTls = p && p->secure.encryptTransport;
@@ -700,16 +697,17 @@
FwdStatePeerAnswerDialer(&FwdState::connectedToPeer, this));
// Use positive timeout when less than one second is left.
const time_t sslNegotiationTimeout = max(static_cast(1), timeLeft());
- Ssl::PeerConnector *connector = NULL;
+ Security::PeerConnector *connector = nullptr;
+#if USE_OPENSSL
if (request->flags.sslPeek)
connector = new Ssl::PeekingPeerConnector(requestPointer, serverConnection(), clientConn, callback, al, sslNegotiationTimeout);
else
- connector = new Ssl::BlindPeerConnector(requestPointer, serverConnection(), callback, al, sslNegotiationTimeout);
+#endif
+ connector = new Security::BlindPeerConnector(requestPointer, serverConnection(), callback, al, sslNegotiationTimeout);
AsyncJob::Start(connector); // will call our callback
return;
}
}
-#endif
// if not encrypting just run the post-connect actions
Security::EncryptorAnswer nil;
@@ -997,12 +995,10 @@
request->flags.auth_no_keytab = 0;
switch (request->url.getScheme()) {
-#if USE_OPENSSL
case AnyP::PROTO_HTTPS:
httpStart(this);
break;
-#endif
case AnyP::PROTO_HTTP:
httpStart(this);
diff -u -r -N squid-4.0.12/src/helper/Reply.cc squid-4.0.13/src/helper/Reply.cc
--- squid-4.0.12/src/helper/Reply.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/helper/Reply.cc 2016-08-06 00:52:55.000000000 +1200
@@ -16,29 +16,40 @@
#include "rfc1738.h"
#include "SquidString.h"
-Helper::Reply::Reply(char *buf, size_t len) :
+Helper::Reply::Reply() :
result(Helper::Unknown),
whichServer(NULL)
{
- parse(buf,len);
+}
+
+bool
+Helper::Reply::accumulate(const char *buf, size_t len)
+{
+ if (other_.isNull())
+ other_.init(4*1024, 1*1024*1024);
+
+ if (other_.potentialSpaceSize() < static_cast(len))
+ return false; // no space left
+
+ other_.append(buf, len);
+ return true;
}
void
-Helper::Reply::parse(char *buf, size_t len)
+Helper::Reply::finalize()
{
debugs(84, 3, "Parsing helper buffer");
// check we have something to parse
- if (!buf || len < 1) {
+ if (!other_.hasContent()) {
// empty line response was the old URL-rewriter interface ERR response.
result = Helper::Error;
// for now ensure that legacy handlers are not presented with NULL strings.
- debugs(84, 3, "Reply length is smaller than 1 or none at all ");
- other_.init(1,1);
- other_.terminate();
+ debugs(84, 3, "Zero length reply");
return;
}
- char *p = buf;
+ char *p = other_.content();
+ size_t len = other_.contentSize();
bool sawNA = false;
// optimization: do not consider parsing result code if the response is short.
@@ -67,10 +78,8 @@
// followed by an auth token
char *w1 = strwordtok(NULL, &p);
if (w1 != NULL) {
- MemBuf authToken;
- authToken.init();
- authToken.append(w1, strlen(w1));
- notes.add("token",authToken.content());
+ const char *authToken = w1;
+ notes.add("token",authToken);
} else {
// token field is mandatory on this response code
result = Helper::BrokenHelper;
@@ -88,22 +97,16 @@
char *w2 = strwordtok(NULL, &p);
if (w2 != NULL) {
// Negotiate "token user"
- MemBuf authToken;
- authToken.init();
- authToken.append(w1, strlen(w1));
- notes.add("token",authToken.content());
-
- MemBuf user;
- user.init();
- user.append(w2,strlen(w2));
- notes.add("user",user.content());
+ const char *authToken = w1;
+ notes.add("token",authToken);
+
+ const char *user = w2;
+ notes.add("user",user);
} else if (w1 != NULL) {
// NTLM "user"
- MemBuf user;
- user.init();
- user.append(w1,strlen(w1));
- notes.add("user",user.content());
+ const char *user = w1;
+ notes.add("user",user);
}
} else if (!strncmp(p,"NA ",3)) {
// NTLM fail-closed ERR response
@@ -115,21 +118,17 @@
for (; xisspace(*p); ++p); // skip whitespace
}
- const mb_size_t blobSize = (buf+len-p);
- other_.init(blobSize+1, blobSize+1);
- other_.append(p, blobSize); // remainders of the line.
-
- // NULL-terminate so the helper callback handlers do not buffer-overrun
- other_.terminate();
+ other_.consume(p - other_.content());
+ other_.consumeWhitespacePrefix();
// Hack for backward-compatibility: Do not parse for kv-pairs on NA response
if (!sawNA)
parseResponseKeys();
// Hack for backward-compatibility: BH and NA used to be a text message...
- if (other().hasContent() && (sawNA || result == Helper::BrokenHelper)) {
- notes.add("message",other().content());
- modifiableOther().clean();
+ if (other_.hasContent() && (sawNA || result == Helper::BrokenHelper)) {
+ notes.add("message", other_.content());
+ other_.clean();
}
}
@@ -157,8 +156,9 @@
Helper::Reply::parseResponseKeys()
{
// parse a "key=value" pair off the 'other()' buffer.
- while (other().hasContent()) {
- char *p = modifiableOther().content();
+ while (other_.hasContent()) {
+ char *p = other_.content();
+ const char *key = p;
while (*p && isKeyNameChar(*p)) ++p;
if (*p != '=')
return; // done. Not a key.
@@ -171,8 +171,6 @@
*p = '\0';
++p;
- const char *key = other().content();
-
// the value may be a quoted string or a token
const bool urlDecode = (*p != '"'); // check before moving p.
char *v = strwordtok(NULL, &p);
@@ -181,11 +179,20 @@
notes.add(key, v ? v : ""); // value can be empty, but must not be NULL
- modifiableOther().consume(p - other().content());
- modifiableOther().consumeWhitespacePrefix();
+ other_.consume(p - other_.content());
+ other_.consumeWhitespacePrefix();
}
}
+const MemBuf &
+Helper::Reply::emptyBuf() const
+{
+ static MemBuf empty;
+ if (empty.isNull())
+ empty.init(1, 1);
+ return empty;
+}
+
std::ostream &
operator <<(std::ostream &os, const Helper::Reply &r)
{
@@ -218,8 +225,9 @@
os << "}";
}
- if (r.other().hasContent())
- os << ", other: \"" << r.other().content() << '\"';
+ MemBuf const &o = r.other();
+ if (o.hasContent())
+ os << ", other: \"" << o.content() << '\"';
os << '}';
diff -u -r -N squid-4.0.12/src/helper/Reply.h squid-4.0.13/src/helper/Reply.h
--- squid-4.0.12/src/helper/Reply.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/helper/Reply.h 2016-08-06 00:52:55.000000000 +1200
@@ -33,22 +33,12 @@
Reply &operator =(const Helper::Reply &r);
public:
- explicit Reply(Helper::ResultCode res = Helper::Unknown) : result(res), notes(), whichServer(NULL) {
- other_.init(1,1);
- other_.terminate();
- }
-
- // create/parse details from the msg buffer provided
- // XXX: buf should be const but parse() needs non-const for now
- Reply(char *buf, size_t len);
-
- const MemBuf &other() const { return other_; }
-
- /// backward compatibility:
- /// access to modifiable blob, required by redirectHandleReply()
- /// and by urlParse() in ClientRequestContext::clientRedirectDone()
- /// and by token blob/arg parsing in Negotiate auth handler
- MemBuf &modifiableOther() const { return *const_cast(&other_); }
+ explicit Reply(Helper::ResultCode res) : result(res), notes(), whichServer(NULL) {}
+
+ /// Creates a NULL reply
+ Reply();
+
+ const MemBuf &other() const {return other_.isNull() ? emptyBuf() : other_;};
/** parse a helper response line format:
* line := [ result ] *#( kv-pair )
@@ -58,7 +48,10 @@
* quoted-string are \-escape decoded and the quotes are stripped.
*/
// XXX: buf should be const but we may need strwordtok() and rfc1738_unescape()
- void parse(char *buf, size_t len);
+ //void parse(char *buf, size_t len);
+ void finalize();
+
+ bool accumulate(const char *buf, size_t len);
public:
/// The helper response 'result' field.
@@ -73,6 +66,9 @@
private:
void parseResponseKeys();
+ /// Return an empty MemBuf.
+ const MemBuf &emptyBuf() const;
+
/// the remainder of the line
MemBuf other_;
};
diff -u -r -N squid-4.0.12/src/helper.cc squid-4.0.13/src/helper.cc
--- squid-4.0.12/src/helper.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/helper.cc 2016-08-06 00:52:55.000000000 +1200
@@ -37,31 +37,22 @@
/// The maximum allowed request retries.
#define MAX_RETRIES 2
-/** Initial Squid input buffer size. Helper responses may exceed this, and
- * Squid will grow the input buffer as needed, up to ReadBufMaxSize.
- */
-const size_t ReadBufMinSize(4*1024);
-
-/** Maximum safe size of a helper-to-Squid response message plus one.
- * Squid will warn and close the stream if a helper sends a too-big response.
- * ssl_crtd helper is known to produce responses of at least 10KB in size.
- * Some undocumented helpers are known to produce responses exceeding 8KB.
- */
-const size_t ReadBufMaxSize(32*1024);
+/// Helpers input buffer size.
+const size_t ReadBufSize(32*1024);
static IOCB helperHandleRead;
static IOCB helperStatefulHandleRead;
static void helperServerFree(helper_server *srv);
static void helperStatefulServerFree(helper_stateful_server *srv);
-static void Enqueue(helper * hlp, Helper::Request *);
+static void Enqueue(helper * hlp, Helper::Xaction *);
static helper_server *GetFirstAvailable(helper * hlp);
static helper_stateful_server *StatefulGetFirstAvailable(statefulhelper * hlp);
-static void helperDispatch(helper_server * srv, Helper::Request * r);
-static void helperStatefulDispatch(helper_stateful_server * srv, Helper::Request * r);
+static void helperDispatch(helper_server * srv, Helper::Xaction * r);
+static void helperStatefulDispatch(helper_stateful_server * srv, Helper::Xaction * r);
static void helperKickQueue(helper * hlp);
static void helperStatefulKickQueue(statefulhelper * hlp);
static void helperStatefulServerDone(helper_stateful_server * srv);
-static void StatefulEnqueue(statefulhelper * hlp, Helper::Request * r);
+static void StatefulEnqueue(statefulhelper * hlp, Helper::Xaction * r);
CBDATA_CLASS_INIT(helper);
CBDATA_CLASS_INIT(helper_server);
@@ -212,10 +203,12 @@
srv->readPipe->fd = rfd;
srv->writePipe = new Comm::Connection;
srv->writePipe->fd = wfd;
- srv->rbuf = (char *)memAllocBuf(ReadBufMinSize, &srv->rbuf_sz);
+ srv->rbuf = (char *)memAllocBuf(ReadBufSize, &srv->rbuf_sz);
srv->wqueue = new MemBuf;
srv->roffset = 0;
srv->nextRequestId = 0;
+ srv->replyXaction = NULL;
+ srv->ignoreToEom = false;
srv->parent = cbdataReference(hlp);
dlinkAddTail(srv, &srv->link, &hlp->servers);
@@ -338,7 +331,7 @@
srv->readPipe->fd = rfd;
srv->writePipe = new Comm::Connection;
srv->writePipe->fd = wfd;
- srv->rbuf = (char *)memAllocBuf(ReadBufMinSize, &srv->rbuf_sz);
+ srv->rbuf = (char *)memAllocBuf(ReadBufSize, &srv->rbuf_sz);
srv->roffset = 0;
srv->parent = cbdataReference(hlp);
@@ -377,7 +370,7 @@
}
void
-helper::submitRequest(Helper::Request *r)
+helper::submitRequest(Helper::Xaction *r)
{
helper_server *srv;
@@ -399,7 +392,7 @@
{
if (hlp == NULL) {
debugs(84, 3, "helperSubmit: hlp == NULL");
- Helper::Reply nilReply;
+ Helper::Reply const nilReply(Helper::Unknown);
callback(data, nilReply);
return;
}
@@ -443,7 +436,7 @@
void
helper::submit(const char *buf, HLPCB * callback, void *data)
{
- Helper::Request *r = new Helper::Request(callback, data, buf);
+ Helper::Xaction *r = new Helper::Xaction(callback, data, buf);
submitRequest(r);
debugs(84, DBG_DATA, Raw("buf", buf, strlen(buf)));
}
@@ -454,7 +447,7 @@
{
if (hlp == NULL) {
debugs(84, 3, "helperStatefulSubmit: hlp == NULL");
- Helper::Reply nilReply;
+ Helper::Reply const nilReply(Helper::Unknown);
callback(data, nilReply);
return;
}
@@ -464,7 +457,7 @@
void statefulhelper::submit(const char *buf, HLPCB * callback, void *data, helper_stateful_server * lastserver)
{
- Helper::Request *r = new Helper::Request(callback, data, buf);
+ Helper::Xaction *r = new Helper::Xaction(callback, data, buf);
if ((buf != NULL) && lastserver) {
debugs(84, 5, "StatefulSubmit with lastserver " << lastserver);
@@ -481,7 +474,7 @@
StatefulEnqueue(this, r);
}
- debugs(84, DBG_DATA, "placeholder: '" << r->placeholder <<
+ debugs(84, DBG_DATA, "placeholder: '" << r->request.placeholder <<
"', " << Raw("buf", buf, (!buf?0:strlen(buf))));
if (!queueFull()) {
@@ -548,8 +541,8 @@
for (dlink_node *link = servers.head; link; link = link->next) {
HelperServerBase *srv = static_cast(link->data);
assert(srv);
- Helper::Request *request = srv->requests.empty() ? NULL : srv->requests.front();
- double tt = 0.001 * (request ? tvSubMsec(request->dispatch_time, current_time) : tvSubMsec(srv->dispatch_time, srv->answer_time));
+ Helper::Xaction *xaction = srv->requests.empty() ? NULL : srv->requests.front();
+ double tt = 0.001 * (xaction ? tvSubMsec(xaction->request.dispatch_time, current_time) : tvSubMsec(srv->dispatch_time, srv->answer_time));
p->appendf("%7u\t%7d\t%7d\t%11" PRIu64 "\t%11" PRIu64 "\t%11" PRIu64 "\t%c%c%c%c%c%c\t%7.3f\t%7d\t%s\n",
srv->index.value,
srv->readPipe->fd,
@@ -562,10 +555,10 @@
srv->flags.closing ? 'C' : ' ',
srv->flags.reserved ? 'R' : ' ',
srv->flags.shutdown ? 'S' : ' ',
- request && request->placeholder ? 'P' : ' ',
+ xaction && xaction->request.placeholder ? 'P' : ' ',
tt < 0.0 ? 0.0 : tt,
(int) srv->roffset,
- request ? Format::QuoteMimeBlob(request->buf) : "(none)");
+ xaction ? Format::QuoteMimeBlob(xaction->request.buf) : "(none)");
}
p->append("\nFlags key:\n"
@@ -727,13 +720,13 @@
while (!srv->requests.empty()) {
// XXX: re-schedule these on another helper?
- Helper::Request *r = srv->requests.front();
+ Helper::Xaction *r = srv->requests.front();
srv->requests.pop_front();
void *cbdata;
- if (cbdataReferenceValidDone(r->data, &cbdata)) {
- Helper::Reply nilReply;
- r->callback(cbdata, nilReply);
+ if (cbdataReferenceValidDone(r->request.data, &cbdata)) {
+ r->reply.result = Helper::Unknown;
+ r->request.callback(cbdata, r->reply);
}
delete r;
@@ -792,13 +785,13 @@
while (!srv->requests.empty()) {
// XXX: re-schedule these on another helper?
- Helper::Request *r = srv->requests.front();
+ Helper::Xaction *r = srv->requests.front();
srv->requests.pop_front();
void *cbdata;
- if (cbdataReferenceValidDone(r->data, &cbdata)) {
- Helper::Reply nilReply;
- r->callback(cbdata, nilReply);
+ if (cbdataReferenceValidDone(r->request.data, &cbdata)) {
+ r->reply.result = Helper::Unknown;
+ r->request.callback(cbdata, r->reply);
}
delete r;
@@ -812,39 +805,57 @@
delete srv;
}
-/// Calls back with a pointer to the buffer with the helper output
-static void
-helperReturnBuffer(int request_number, helper_server * srv, helper * hlp, char * msg, char * msg_end)
+Helper::Xaction *
+helper_server::popRequest(int request_number)
{
- Helper::Request *r = NULL;
+ Helper::Xaction *r = nullptr;
helper_server::RequestIndex::iterator it;
- if (hlp->childs.concurrency) {
+ if (parent->childs.concurrency) {
// If concurency supported retrieve request from ID
- it = srv->requestsIndex.find(request_number);
- if (it != srv->requestsIndex.end()) {
+ it = requestsIndex.find(request_number);
+ if (it != requestsIndex.end()) {
r = *(it->second);
- srv->requests.erase(it->second);
- srv->requestsIndex.erase(it);
+ requests.erase(it->second);
+ requestsIndex.erase(it);
}
- } else if(!srv->requests.empty()) {
+ } else if(!requests.empty()) {
// Else get the first request from queue, if any
- r = srv->requests.front();
- srv->requests.pop_front();
+ r = requests.front();
+ requests.pop_front();
}
- if (r) {
- HLPCB *callback = r->callback;
- r->callback = NULL;
+ return r;
+}
+
+/// Calls back with a pointer to the buffer with the helper output
+static void
+helperReturnBuffer(helper_server * srv, helper * hlp, char * msg, size_t msgSize, char * msgEnd)
+{
+ if (Helper::Xaction *r = srv->replyXaction) {
+ const bool hasSpace = r->reply.accumulate(msg, msgSize);
+ if (!hasSpace) {
+ debugs(84, DBG_IMPORTANT, "ERROR: Disconnecting from a " <<
+ "helper that overflowed " << srv->rbuf_sz << "-byte " <<
+ "Squid input buffer: " << hlp->id_name << " #" << srv->index);
+ srv->closePipesSafely(hlp->id_name);
+ return;
+ }
+
+ if (!msgEnd)
+ return; // We are waiting for more data.
+
+ HLPCB *callback = r->request.callback;
+ r->request.callback = nullptr;
- void *cbdata = NULL;
bool retry = false;
- if (cbdataReferenceValidDone(r->data, &cbdata)) {
- Helper::Reply response(msg, (msg_end-msg));
- if (response.result == Helper::BrokenHelper && r->retries < MAX_RETRIES) {
- debugs(84, DBG_IMPORTANT, "ERROR: helper: " << response << ", attempt #" << (r->retries + 1) << " of 2");
+ void *cbdata = nullptr;
+ if (cbdataReferenceValidDone(r->request.data, &cbdata)) {
+ r->reply.finalize();
+ if (r->reply.result == Helper::BrokenHelper && r->request.retries < MAX_RETRIES) {
+ debugs(84, DBG_IMPORTANT, "ERROR: helper: " << r->reply << ", attempt #" << (r->request.retries + 1) << " of 2");
retry = true;
} else
- callback(cbdata, response);
+ callback(cbdata, r->reply);
}
-- srv->stats.pending;
@@ -854,24 +865,20 @@
srv->answer_time = current_time;
- srv->dispatch_time = r->dispatch_time;
+ srv->dispatch_time = r->request.dispatch_time;
hlp->stats.avg_svc_time =
Math::intAverage(hlp->stats.avg_svc_time,
- tvSubMsec(r->dispatch_time, current_time),
+ tvSubMsec(r->request.dispatch_time, current_time),
hlp->stats.replies, REDIRECT_AV_FACTOR);
+ // release or re-submit parsedRequestXaction object
+ srv->replyXaction = nullptr;
if (retry) {
- ++r->retries;
+ ++r->request.retries;
hlp->submitRequest(r);
} else
delete r;
- } else if (srv->stats.timedout) {
- debugs(84, 3, "Timedout reply received for request-ID: " << request_number << " , ignore");
- } else {
- debugs(84, DBG_IMPORTANT, "helperHandleRead: unexpected reply on channel " <<
- request_number << " from " << hlp->id_name << " #" << srv->index <<
- " '" << srv->rbuf << "'");
}
if (hlp->timeout && hlp->childs.concurrency)
@@ -888,7 +895,6 @@
static void
helperHandleRead(const Comm::ConnectionPointer &conn, char *, size_t len, Comm::Flag flag, int, void *data)
{
- char *t = NULL;
helper_server *srv = (helper_server *)data;
helper *hlp = srv->parent;
assert(cbdataReferenceValid(data));
@@ -922,57 +928,80 @@
srv->rbuf[0] = '\0';
}
- while ((t = strchr(srv->rbuf, hlp->eom))) {
- /* end of reply found */
- char *msg = srv->rbuf;
- int i = 0;
- int skip = 1;
- debugs(84, 3, "helperHandleRead: end of reply found");
-
- if (t > srv->rbuf && t[-1] == '\r' && hlp->eom == '\n') {
- *t = '\0';
- // rewind to the \r octet which is the real terminal now
- // and remember that we have to skip forward 2 places now.
- skip = 2;
- --t;
+ bool needsMore = false;
+ char *msg = srv->rbuf;
+ while (*msg && !needsMore) {
+ int skip = 0;
+ char *eom = strchr(msg, hlp->eom);
+ if (eom) {
+ skip = 1;
+ debugs(84, 3, "helperHandleRead: end of reply found");
+ if (eom > msg && eom[-1] == '\r' && hlp->eom == '\n') {
+ *eom = '\0';
+ // rewind to the \r octet which is the real terminal now
+ // and remember that we have to skip forward 2 places now.
+ skip = 2;
+ --eom;
+ }
+ *eom = '\0';
}
- *t = '\0';
-
- if (hlp->childs.concurrency) {
- i = strtol(msg, &msg, 10);
+ if (!srv->ignoreToEom && !srv->replyXaction) {
+ int i = 0;
+ if (hlp->childs.concurrency) {
+ char *e = NULL;
+ i = strtol(msg, &e, 10);
+ // Do we need to check for e == msg? Means wrong response from helper.
+ // Will be droped as "unexpected reply on channel 0"
+ needsMore = !(xisspace(*e) || (eom && e == eom));
+ if (!needsMore) {
+ msg = e;
+ while (*msg && xisspace(*msg))
+ ++msg;
+ } // else not enough data to compute request number
+ }
+ if (!(srv->replyXaction = srv->popRequest(i))) {
+ if (srv->stats.timedout) {
+ debugs(84, 3, "Timedout reply received for request-ID: " << i << " , ignore");
+ } else {
+ debugs(84, DBG_IMPORTANT, "helperHandleRead: unexpected reply on channel " <<
+ i << " from " << hlp->id_name << " #" << srv->index <<
+ " '" << srv->rbuf << "'");
+ }
+ srv->ignoreToEom = true;
+ }
+ } // else we need to just append reply data to the current Xaction
- while (*msg && xisspace(*msg))
- ++msg;
- }
+ if (!needsMore) {
+ size_t msgSize = eom ? eom - msg : (srv->roffset - (msg - srv->rbuf));
+ assert(msgSize <= srv->rbuf_sz);
+ helperReturnBuffer(srv, hlp, msg, msgSize, eom);
+ msg += msgSize + skip;
+ assert(static_cast(msg - srv->rbuf) <= srv->rbuf_sz);
+
+ // The next message should not ignored.
+ if (eom && srv->ignoreToEom)
+ srv->ignoreToEom = false;
+ } else
+ assert(skip == 0 && eom == NULL);
+ }
- helperReturnBuffer(i, srv, hlp, msg, t);
- srv->roffset -= (t - srv->rbuf) + skip;
- memmove(srv->rbuf, t + skip, srv->roffset);
+ if (needsMore) {
+ size_t msgSize = (srv->roffset - (msg - srv->rbuf));
+ assert(msgSize <= srv->rbuf_sz);
+ memmove(srv->rbuf, msg, msgSize);
+ srv->roffset = msgSize;
srv->rbuf[srv->roffset] = '\0';
+ } else {
+ // All of the responses parsed and msg points at the end of read data
+ assert(static_cast(msg - srv->rbuf) == srv->roffset);
+ srv->roffset = 0;
}
if (Comm::IsConnOpen(srv->readPipe) && !fd_table[srv->readPipe->fd].closing()) {
int spaceSize = srv->rbuf_sz - srv->roffset - 1;
assert(spaceSize >= 0);
- // grow the input buffer if needed and possible
- if (!spaceSize && srv->rbuf_sz + 4096 <= ReadBufMaxSize) {
- srv->rbuf = (char *)memReallocBuf(srv->rbuf, srv->rbuf_sz + 4096, &srv->rbuf_sz);
- debugs(84, 3, HERE << "Grew read buffer to " << srv->rbuf_sz);
- spaceSize = srv->rbuf_sz - srv->roffset - 1;
- assert(spaceSize >= 0);
- }
-
- // quit reading if there is no space left
- if (!spaceSize) {
- debugs(84, DBG_IMPORTANT, "ERROR: Disconnecting from a " <<
- "helper that overflowed " << srv->rbuf_sz << "-byte " <<
- "Squid input buffer: " << hlp->id_name << " #" << srv->index);
- srv->closePipesSafely(hlp->id_name);
- return;
- }
-
AsyncCall::Pointer call = commCbCall(5,4, "helperHandleRead",
CommIoCbPtrFun(helperHandleRead, srv));
comm_read(srv->readPipe, srv->rbuf + srv->roffset, spaceSize, call);
@@ -1005,7 +1034,7 @@
srv->roffset += len;
srv->rbuf[srv->roffset] = '\0';
- Helper::Request *r = srv->requests.front();
+ Helper::Xaction *r = srv->requests.front();
debugs(84, DBG_DATA, Raw("accumulated", srv->rbuf, srv->roffset));
if (r == NULL) {
@@ -1018,40 +1047,46 @@
}
if ((t = strchr(srv->rbuf, hlp->eom))) {
- /* end of reply found */
- srv->requests.pop_front(); // we already have it in 'r'
- int called = 1;
- int skip = 1;
debugs(84, 3, "helperStatefulHandleRead: end of reply found");
if (t > srv->rbuf && t[-1] == '\r' && hlp->eom == '\n') {
*t = '\0';
// rewind to the \r octet which is the real terminal now
- // and remember that we have to skip forward 2 places now.
- skip = 2;
--t;
}
*t = '\0';
+ }
+
+ if (r && !r->reply.accumulate(srv->rbuf, t ? (t - srv->rbuf) : srv->roffset)) {
+ debugs(84, DBG_IMPORTANT, "ERROR: Disconnecting from a " <<
+ "helper that overflowed " << srv->rbuf_sz << "-byte " <<
+ "Squid input buffer: " << hlp->id_name << " #" << srv->index);
+ srv->closePipesSafely(hlp->id_name);
+ return;
+ }
+ /**
+ * BUG: the below assumes that only one response per read() was received and discards any octets remaining.
+ * Doing this prohibits concurrency support with multiple replies per read().
+ * TODO: check that read() setup on these buffers pays attention to roffest!=0
+ * TODO: check that replies bigger than the buffer are discarded and do not to affect future replies
+ */
+ srv->roffset = 0;
- if (r && cbdataReferenceValid(r->data)) {
- Helper::Reply res(srv->rbuf, (t - srv->rbuf));
- res.whichServer = srv;
- r->callback(r->data, res);
+ if (t) {
+ /* end of reply found */
+ srv->requests.pop_front(); // we already have it in 'r'
+ int called = 1;
+
+ if (r && cbdataReferenceValid(r->request.data)) {
+ r->reply.finalize();
+ r->reply.whichServer = srv;
+ r->request.callback(r->request.data, r->reply);
} else {
debugs(84, DBG_IMPORTANT, "StatefulHandleRead: no callback data registered");
called = 0;
}
- // only skip off the \0's _after_ passing its location in Helper::Reply above
- t += skip;
- /**
- * BUG: the below assumes that only one response per read() was received and discards any octets remaining.
- * Doing this prohibits concurrency support with multiple replies per read().
- * TODO: check that read() setup on these buffers pays attention to roffest!=0
- * TODO: check that replies bigger than the buffer are discarded and do not to affect future replies
- */
- srv->roffset = 0;
delete r;
-- srv->stats.pending;
@@ -1071,35 +1106,17 @@
}
if (Comm::IsConnOpen(srv->readPipe) && !fd_table[srv->readPipe->fd].closing()) {
- int spaceSize = srv->rbuf_sz - srv->roffset - 1;
- assert(spaceSize >= 0);
-
- // grow the input buffer if needed and possible
- if (!spaceSize && srv->rbuf_sz + 4096 <= ReadBufMaxSize) {
- srv->rbuf = (char *)memReallocBuf(srv->rbuf, srv->rbuf_sz + 4096, &srv->rbuf_sz);
- debugs(84, 3, HERE << "Grew read buffer to " << srv->rbuf_sz);
- spaceSize = srv->rbuf_sz - srv->roffset - 1;
- assert(spaceSize >= 0);
- }
-
- // quit reading if there is no space left
- if (!spaceSize) {
- debugs(84, DBG_IMPORTANT, "ERROR: Disconnecting from a " <<
- "helper that overflowed " << srv->rbuf_sz << "-byte " <<
- "Squid input buffer: " << hlp->id_name << " #" << srv->index);
- srv->closePipesSafely(hlp->id_name);
- return;
- }
+ int spaceSize = srv->rbuf_sz - 1;
AsyncCall::Pointer call = commCbCall(5,4, "helperStatefulHandleRead",
CommIoCbPtrFun(helperStatefulHandleRead, srv));
- comm_read(srv->readPipe, srv->rbuf + srv->roffset, spaceSize, call);
+ comm_read(srv->readPipe, srv->rbuf, spaceSize, call);
}
}
/// Handles a request when all running helpers, if any, are busy.
static void
-Enqueue(helper * hlp, Helper::Request * r)
+Enqueue(helper * hlp, Helper::Xaction * r)
{
hlp->queue.push(r);
++ hlp->stats.queue_size;
@@ -1128,7 +1145,7 @@
}
static void
-StatefulEnqueue(statefulhelper * hlp, Helper::Request * r)
+StatefulEnqueue(statefulhelper * hlp, Helper::Xaction * r)
{
hlp->queue.push(r);
++ hlp->stats.queue_size;
@@ -1156,7 +1173,7 @@
debugs(84, DBG_CRITICAL, "WARNING: Consider increasing the number of " << hlp->id_name << " processes in your config file.");
}
-Helper::Request *
+Helper::Xaction *
helper::nextRequest()
{
if (queue.empty())
@@ -1272,20 +1289,20 @@
}
static void
-helperDispatch(helper_server * srv, Helper::Request * r)
+helperDispatch(helper_server * srv, Helper::Xaction * r)
{
helper *hlp = srv->parent;
const uint64_t reqId = ++srv->nextRequestId;
- if (!cbdataReferenceValid(r->data)) {
+ if (!cbdataReferenceValid(r->request.data)) {
debugs(84, DBG_IMPORTANT, "helperDispatch: invalid callback data");
delete r;
return;
}
- r->Id = reqId;
+ r->request.Id = reqId;
helper_server::Requests::iterator it = srv->requests.insert(srv->requests.end(), r);
- r->dispatch_time = current_time;
+ r->request.dispatch_time = current_time;
if (srv->wqueue->isNull())
srv->wqueue->init();
@@ -1293,9 +1310,9 @@
if (hlp->childs.concurrency) {
srv->requestsIndex.insert(helper_server::RequestIndex::value_type(reqId, it));
assert(srv->requestsIndex.size() == srv->requests.size());
- srv->wqueue->appendf("%" PRIu64 " %s", reqId, r->buf);
+ srv->wqueue->appendf("%" PRIu64 " %s", reqId, r->request.buf);
} else
- srv->wqueue->append(r->buf, strlen(r->buf));
+ srv->wqueue->append(r->request.buf, strlen(r->request.buf));
if (!srv->flags.writing) {
assert(NULL == srv->writebuf);
@@ -1307,7 +1324,7 @@
Comm::Write(srv->writePipe, srv->writebuf->content(), srv->writebuf->contentSize(), call, NULL);
}
- debugs(84, 5, "helperDispatch: Request sent to " << hlp->id_name << " #" << srv->index << ", " << strlen(r->buf) << " bytes");
+ debugs(84, 5, "helperDispatch: Request sent to " << hlp->id_name << " #" << srv->index << ", " << strlen(r->request.buf) << " bytes");
++ srv->stats.uses;
++ srv->stats.pending;
@@ -1319,11 +1336,11 @@
{}
static void
-helperStatefulDispatch(helper_stateful_server * srv, Helper::Request * r)
+helperStatefulDispatch(helper_stateful_server * srv, Helper::Xaction * r)
{
statefulhelper *hlp = srv->parent;
- if (!cbdataReferenceValid(r->data)) {
+ if (!cbdataReferenceValid(r->request.data)) {
debugs(84, DBG_IMPORTANT, "helperStatefulDispatch: invalid callback data");
delete r;
helperStatefulReleaseServer(srv);
@@ -1332,13 +1349,13 @@
debugs(84, 9, "helperStatefulDispatch busying helper " << hlp->id_name << " #" << srv->index);
- if (r->placeholder == 1) {
+ if (r->request.placeholder == 1) {
/* a callback is needed before this request can _use_ a helper. */
/* we don't care about releasing this helper. The request NEVER
* gets to the helper. So we throw away the return code */
- Helper::Reply nilReply;
- nilReply.whichServer = srv;
- r->callback(r->data, nilReply);
+ r->reply.result = Helper::Unknown;
+ r->reply.whichServer = srv;
+ r->request.callback(r->request.data, r->reply);
/* throw away the placeholder */
delete r;
/* and push the queue. Note that the callback may have submitted a new
@@ -1355,10 +1372,10 @@
srv->dispatch_time = current_time;
AsyncCall::Pointer call = commCbCall(5,5, "helperStatefulDispatchWriteDone",
CommIoCbPtrFun(helperStatefulDispatchWriteDone, hlp));
- Comm::Write(srv->writePipe, r->buf, strlen(r->buf), call, NULL);
+ Comm::Write(srv->writePipe, r->request.buf, strlen(r->request.buf), call, NULL);
debugs(84, 5, "helperStatefulDispatch: Request sent to " <<
hlp->id_name << " #" << srv->index << ", " <<
- (int) strlen(r->buf) << " bytes");
+ (int) strlen(r->request.buf) << " bytes");
++ srv->stats.uses;
++ srv->stats.pending;
@@ -1368,7 +1385,7 @@
static void
helperKickQueue(helper * hlp)
{
- Helper::Request *r;
+ Helper::Xaction *r;
helper_server *srv;
while ((srv = GetFirstAvailable(hlp)) && (r = hlp->nextRequest()))
@@ -1378,7 +1395,7 @@
static void
helperStatefulKickQueue(statefulhelper * hlp)
{
- Helper::Request *r;
+ Helper::Xaction *r;
helper_stateful_server *srv;
while ((srv = StatefulGetFirstAvailable(hlp)) && (r = hlp->nextRequest()))
@@ -1400,29 +1417,32 @@
helper_server::checkForTimedOutRequests(bool const retry)
{
assert(parent->childs.concurrency);
- while(!requests.empty() && requests.front()->timedOut(parent->timeout)) {
- Helper::Request *r = requests.front();
+ while(!requests.empty() && requests.front()->request.timedOut(parent->timeout)) {
+ Helper::Xaction *r = requests.front();
RequestIndex::iterator it;
- it = requestsIndex.find(r->Id);
+ it = requestsIndex.find(r->request.Id);
assert(it != requestsIndex.end());
requestsIndex.erase(it);
requests.pop_front();
- debugs(84, 2, "Request " << r->Id << " timed-out, remove it from queue");
+ debugs(84, 2, "Request " << r->request.Id << " timed-out, remove it from queue");
void *cbdata;
bool retried = false;
- if (retry && r->retries < MAX_RETRIES && cbdataReferenceValid(r->data)) {
- debugs(84, 2, "Retry request " << r->Id);
- ++r->retries;
+ if (retry && r->request.retries < MAX_RETRIES && cbdataReferenceValid(r->request.data)) {
+ debugs(84, 2, "Retry request " << r->request.Id);
+ ++r->request.retries;
parent->submitRequest(r);
retried = true;
- } else if (cbdataReferenceValidDone(r->data, &cbdata)) {
+ } else if (cbdataReferenceValidDone(r->request.data, &cbdata)) {
if (!parent->onTimedOutResponse.isEmpty()) {
- // Helper::Reply needs a non const buffer
- char *replyMsg = xstrdup(parent->onTimedOutResponse.c_str());
- r->callback(cbdata, Helper::Reply(replyMsg, strlen(replyMsg)));
- xfree(replyMsg);
- } else
- r->callback(cbdata, Helper::Reply(Helper::TimedOut));
+ if (r->reply.accumulate(parent->onTimedOutResponse.rawContent(), parent->onTimedOutResponse.length()))
+ r->reply.finalize();
+ else
+ r->reply.result = Helper::TimedOut;
+ r->request.callback(cbdata, r->reply);
+ } else {
+ r->reply.result = Helper::TimedOut;
+ r->request.callback(cbdata, r->reply);
+ }
}
--stats.pending;
++stats.timedout;
@@ -1447,7 +1467,7 @@
AsyncCall::Pointer timeoutCall = commCbCall(84, 4, "helper_server::requestTimeout",
CommTimeoutCbPtrFun(helper_server::requestTimeout, srv));
- const int timeSpent = srv->requests.empty() ? 0 : (squid_curtime - srv->requests.front()->dispatch_time.tv_sec);
+ const int timeSpent = srv->requests.empty() ? 0 : (squid_curtime - srv->requests.front()->request.dispatch_time.tv_sec);
const int timeLeft = max(1, (static_cast(srv->parent->timeout) - timeSpent));
commSetConnTimeout(io.conn, timeLeft, timeoutCall);
diff -u -r -N squid-4.0.12/src/helper.h squid-4.0.13/src/helper.h
--- squid-4.0.12/src/helper.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/helper.h 2016-08-06 00:52:55.000000000 +1200
@@ -18,6 +18,8 @@
#include "dlink.h"
#include "helper/ChildConfig.h"
#include "helper/forward.h"
+#include "helper/Reply.h"
+#include "helper/Request.h"
#include "ip/Address.h"
#include "sbuf/SBuf.h"
@@ -28,6 +30,18 @@
class Packable;
class wordlist;
+namespace Helper
+{
+/// Holds the required data to serve a helper request.
+class Xaction {
+ MEMPROXY_CLASS(Helper::Xaction);
+public:
+ Xaction(HLPCB *c, void *d, const char *b): request(c, d, b) {}
+ Helper::Request request;
+ Helper::Reply reply;
+};
+}
+
/**
* Managers a set of individual helper processes with a common queue of requests.
*
@@ -67,14 +81,14 @@
bool queueFull() const;
/// \returns next request in the queue, or nil.
- Helper::Request *nextRequest();
+ Helper::Xaction *nextRequest();
///< If not full, submit request. Otherwise, either kill Squid or return false.
bool trySubmit(const char *buf, HLPCB * callback, void *data);
/// Submits a request to the helper or add it to the queue if none of
/// the servers is available.
- void submitRequest(Helper::Request *r);
+ void submitRequest(Helper::Xaction *r);
/// Dump some stats about the helper state to a Packable object
void packStatsInto(Packable *p, const char *label = NULL) const;
@@ -82,7 +96,7 @@
public:
wordlist *cmdline;
dlink_list servers;
- std::queue queue;
+ std::queue queue;
const char *id_name;
Helper::ChildConfig childs; ///< Configuration settings for number running.
int ipc_type;
@@ -173,7 +187,7 @@
bool reserved;
} flags;
- typedef std::list Requests;
+ typedef std::list Requests;
Requests requests; ///< requests in order of submission/expiration
struct {
@@ -201,10 +215,25 @@
helper *parent;
+ /// The helper request Xaction object for the current reply .
+ /// A helper reply may be distributed to more than one of the retrieved
+ /// packets from helper. This member stores the Xaction object as long as
+ /// the end-of-message for current reply is not retrieved.
+ Helper::Xaction *replyXaction;
+
+ /// Whether to ignore current message, because it is timed-out or other reason
+ bool ignoreToEom;
+
// STL says storing std::list iterators is safe when changing the list
typedef std::map RequestIndex;
RequestIndex requestsIndex; ///< maps request IDs to requests
+ /// Search in queue for the request with requestId, return the related
+ /// Xaction object and remove it from queue.
+ /// If concurrency is disabled then the requestId is ignored and the
+ /// Xaction of the next request in queue is retrieved.
+ Helper::Xaction *popRequest(int requestId);
+
/// Run over the active requests lists and forces a retry, or timedout reply
/// or the configured "on timeout response" for timedout requests.
void checkForTimedOutRequests(bool const retry);
diff -u -r -N squid-4.0.12/src/http/one/Parser.cc squid-4.0.13/src/http/one/Parser.cc
--- squid-4.0.12/src/http/one/Parser.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/http/one/Parser.cc 2016-08-06 00:52:55.000000000 +1200
@@ -64,7 +64,11 @@
if (Config.onoff.relaxed_header_parser && tok.skipOne(CharacterSet::LF))
return true;
- return false;
+ if (tok.atEnd() || (tok.remaining().length() == 1 && tok.remaining().at(0) == '\r'))
+ return false; // need more data
+
+ throw TexcHere("garbage instead of CRLF line terminator");
+ return false; // unreachable, but make naive compilers happy
}
/// all characters except the LF line terminator
diff -u -r -N squid-4.0.12/src/http/one/Parser.h squid-4.0.13/src/http/one/Parser.h
--- squid-4.0.12/src/http/one/Parser.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/http/one/Parser.h 2016-08-06 00:52:55.000000000 +1200
@@ -107,8 +107,14 @@
Http::StatusCode parseStatusCode;
protected:
- /// detect and skip the CRLF or (if tolerant) LF line terminator
- /// consume from the tokenizer and return true only if found
+ /**
+ * detect and skip the CRLF or (if tolerant) LF line terminator
+ * consume from the tokenizer.
+ *
+ * throws if non-terminator is detected.
+ * \retval true only if line terminator found.
+ * \retval false incomplete or missing line terminator, need more data.
+ */
bool skipLineTerminator(Http1::Tokenizer &tok) const;
/// the characters which are to be considered valid whitespace
diff -u -r -N squid-4.0.12/src/http/one/ResponseParser.cc squid-4.0.13/src/http/one/ResponseParser.cc
--- squid-4.0.12/src/http/one/ResponseParser.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/http/one/ResponseParser.cc 2016-08-06 00:52:55.000000000 +1200
@@ -75,9 +75,6 @@
// NOTE: any whitespace after the single SP is part of the reason phrase.
}
- if (tok.atEnd())
- return 0; // need more to be sure we have it all
-
/* RFC 7230 says we SHOULD ignore the reason phrase content
* but it has a definite valid vs invalid character set.
* We interpret the SHOULD as ignoring absence and syntax, but
@@ -89,17 +86,18 @@
// if we got here we are still looking for reason-phrase bytes
static const CharacterSet phraseChars = CharacterSet::WSP + CharacterSet::VCHAR + CharacterSet::OBSTEXT;
(void)tok.prefix(reasonPhrase_, phraseChars); // optional, no error if missing
- if (skipLineTerminator(tok)) {
- debugs(74, DBG_DATA, "parse remaining buf={length=" << tok.remaining().length() << ", data='" << tok.remaining() << "'}");
- buf_ = tok.remaining(); // resume checkpoint
- return 1;
- }
- reasonPhrase_.clear();
-
- if (tok.atEnd())
+ try {
+ if (skipLineTerminator(tok)) {
+ debugs(74, DBG_DATA, "parse remaining buf={length=" << tok.remaining().length() << ", data='" << tok.remaining() << "'}");
+ buf_ = tok.remaining(); // resume checkpoint
+ return 1;
+ }
+ reasonPhrase_.clear();
return 0; // need more to be sure we have it all
- debugs(74, 6, "invalid status-line. garbage in reason phrase.");
+ } catch (const std::exception &ex) {
+ debugs(74, 6, "invalid status-line: " << ex.what());
+ }
return -1;
}
diff -u -r -N squid-4.0.12/src/http/one/TeChunkedParser.cc squid-4.0.13/src/http/one/TeChunkedParser.cc
--- squid-4.0.12/src/http/one/TeChunkedParser.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/http/one/TeChunkedParser.cc 2016-08-06 00:52:55.000000000 +1200
@@ -153,9 +153,6 @@
buf_ = tok.remaining(); // parse checkpoint (unless there might be more token name)
}
- if (tok.atEnd())
- return false;
-
if (skipLineTerminator(tok)) {
buf_ = tok.remaining(); // checkpoint
// non-0 chunk means data, 0-size means optional Trailer follows
@@ -163,7 +160,6 @@
return true;
}
- throw TexcHere("corrupted chunk extension value");
return false;
}
@@ -202,9 +198,6 @@
theChunkSize = 0; // done with the current chunk
parsingStage_ = Http1::HTTP_PARSE_CHUNK_SZ;
return true;
-
- } else if (!tok.atEnd()) {
- throw TexcHere("found data between chunk end and CRLF");
}
return false;
diff -u -r -N squid-4.0.12/src/http/Stream.cc squid-4.0.13/src/http/Stream.cc
--- squid-4.0.12/src/http/Stream.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/http/Stream.cc 2016-08-06 00:52:55.000000000 +1200
@@ -11,7 +11,6 @@
#include "http/Stream.h"
#include "HttpHdrContRange.h"
#include "HttpHeaderTools.h"
-#include "SquidConfig.h"
#include "Store.h"
#include "TimeOrTag.h"
@@ -21,10 +20,10 @@
reply(nullptr),
writtenToSocket(0),
mayUseConnection_(false),
- connRegistered_(false),
- requestBuffer(nullptr)
+ connRegistered_(false)
{
assert(http != nullptr);
+ memset(reqbuf, '\0', sizeof (reqbuf));
flags.deferred = 0;
flags.parsed_ok = 0;
deferredparams.node = nullptr;
@@ -110,10 +109,12 @@
debugs(33, 5, reply << " written " << http->out.size << " into " << clientConnection);
/* More data will be coming from the stream. */
- StoreIOBuffer readBuffer = getClientStreamBuffer();
+ StoreIOBuffer readBuffer;
/* XXX: Next requested byte in the range sequence */
/* XXX: length = getmaximumrangelenfgth */
readBuffer.offset = getNextRangeOffset();
+ readBuffer.length = HTTP_REQBUF_SZ;
+ readBuffer.data = reqbuf;
/* we may note we have reached the end of the wanted ranges */
clientStreamRead(getTail(), http, readBuffer);
}
@@ -567,18 +568,6 @@
deferredparams.queuedBuffer = receivedData;
}
-StoreIOBuffer
-Http::Stream::getClientStreamBuffer()
-{
- if (!requestBuffer) {
- requestBuffer = new MemBlob(Config.readAheadGap);
- }
- StoreIOBuffer tempBuffer;
- tempBuffer.data = requestBuffer->mem;
- tempBuffer.length = requestBuffer->spaceSize();
- return tempBuffer;
-}
-
void
Http::Stream::prepareReply(HttpReply *rep)
{
diff -u -r -N squid-4.0.12/src/http/Stream.h squid-4.0.13/src/http/Stream.h
--- squid-4.0.12/src/http/Stream.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/http/Stream.h 2016-08-06 00:52:55.000000000 +1200
@@ -120,13 +120,12 @@
void deferRecipientForLater(clientStreamNode *, HttpReply *, StoreIOBuffer receivedData);
- StoreIOBuffer getClientStreamBuffer();
-
public: // HTTP/1.x state data
Comm::ConnectionPointer clientConnection; ///< details about the client connection socket
ClientHttpRequest *http; /* we pretend to own that Job */
HttpReply *reply;
+ char reqbuf[HTTP_REQBUF_SZ];
struct {
unsigned deferred:1; ///< This is a pipelined request waiting for the current object to complete
unsigned parsed_ok:1; ///< Was this parsed correctly?
@@ -159,8 +158,6 @@
bool mayUseConnection_; /* This request may use the connection. Don't read anymore requests for now */
bool connRegistered_;
-
- MemBlob::Pointer requestBuffer;
};
} // namespace Http
diff -u -r -N squid-4.0.12/src/http/url_rewriters/LFS/url_lfs_rewrite.8 squid-4.0.13/src/http/url_rewriters/LFS/url_lfs_rewrite.8
--- squid-4.0.12/src/http/url_rewriters/LFS/url_lfs_rewrite.8 2016-07-02 02:24:36.000000000 +1200
+++ squid-4.0.13/src/http/url_rewriters/LFS/url_lfs_rewrite.8 2016-08-06 02:28:23.000000000 +1200
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "URL_LFS_REWRITE 8"
-.TH URL_LFS_REWRITE 8 "2016-07-01" "perl v5.22.2" "User Contributed Perl Documentation"
+.TH URL_LFS_REWRITE 8 "2016-08-05" "perl v5.22.2" "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.12/src/HttpHeader.cc squid-4.0.13/src/HttpHeader.cc
--- squid-4.0.12/src/HttpHeader.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/HttpHeader.cc 2016-08-06 00:52:55.000000000 +1200
@@ -24,7 +24,6 @@
#include "profiler/Profiler.h"
#include "rfc1123.h"
#include "SquidConfig.h"
-//#include "SquidString.h" // pulled by HttpHdrCc.h
#include "StatHist.h"
#include "Store.h"
#include "StrList.h"
@@ -238,6 +237,22 @@
}
}
+/// check whether the fresh header has any new/changed updatable fields
+bool
+HttpHeader::needUpdate(HttpHeader const *fresh) const
+{
+ for (const auto e: fresh->entries) {
+ if (skipUpdateHeader(e->id))
+ continue;
+ String value;
+ const char *name = e->name.termedBuf();
+ if (!getByNameIfPresent(name, strlen(name), value) ||
+ (value != fresh->getByName(name)))
+ return true;
+ }
+ return false;
+}
+
void
HttpHeader::updateWarnings()
{
@@ -258,16 +273,22 @@
return id == Http::HdrType::WARNING;
}
-void
+bool
HttpHeader::update(HttpHeader const *fresh)
{
- const HttpHeaderEntry *e;
- HttpHeaderPos pos = HttpHeaderInitPos;
assert(fresh);
assert(this != fresh);
+ // Optimization: Finding whether a header field changed is expensive
+ // and probably not worth it except for collapsed revalidation needs.
+ if (Config.onoff.collapsed_forwarding && !needUpdate(fresh))
+ return false;
+
updateWarnings();
+ const HttpHeaderEntry *e;
+ HttpHeaderPos pos = HttpHeaderInitPos;
+
while ((e = fresh->getEntry(&pos))) {
/* deny bad guys (ok to check for Http::HdrType::OTHER) here */
@@ -291,6 +312,7 @@
addEntry(e->clone());
}
+ return true;
}
int
diff -u -r -N squid-4.0.12/src/HttpHeader.h squid-4.0.13/src/HttpHeader.h
--- squid-4.0.12/src/HttpHeader.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/HttpHeader.h 2016-08-06 00:52:55.000000000 +1200
@@ -81,7 +81,7 @@
/* Interface functions */
void clean();
void append(const HttpHeader * src);
- void update(HttpHeader const *fresh);
+ bool update(HttpHeader const *fresh);
void compact();
int parse(const char *header_start, size_t len);
void packInto(Packable * p, bool mask_sensitive_info=false) const;
@@ -145,6 +145,7 @@
protected:
/** \deprecated Public access replaced by removeHopByHopEntries() */
void removeConnectionHeaderEntries();
+ bool needUpdate(const HttpHeader *fresh) const;
bool skipUpdateHeader(const Http::HdrType id) const;
void updateWarnings();
diff -u -r -N squid-4.0.12/src/HttpReply.cc squid-4.0.13/src/HttpReply.cc
--- squid-4.0.12/src/HttpReply.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/HttpReply.cc 2016-08-06 00:52:55.000000000 +1200
@@ -235,19 +235,23 @@
return 1;
}
-void
+bool
HttpReply::updateOnNotModified(HttpReply const * freshRep)
{
assert(freshRep);
+ /* update raw headers */
+ if (!header.update(&freshRep->header))
+ return false;
+
/* clean cache */
hdrCacheClean();
- /* update raw headers */
- header.update(&freshRep->header);
header.compact();
/* init cache */
hdrCacheInit();
+
+ return true;
}
/* internal routines */
diff -u -r -N squid-4.0.12/src/HttpReply.h squid-4.0.13/src/HttpReply.h
--- squid-4.0.12/src/HttpReply.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/HttpReply.h 2016-08-06 00:52:55.000000000 +1200
@@ -72,7 +72,7 @@
virtual bool inheritProperties(const HttpMsg *aMsg);
- void updateOnNotModified(HttpReply const *other);
+ bool updateOnNotModified(HttpReply const *other);
/** set commonly used info with one call */
void setHeaders(Http::StatusCode status,
diff -u -r -N squid-4.0.12/src/HttpRequest.cc squid-4.0.13/src/HttpRequest.cc
--- squid-4.0.12/src/HttpRequest.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/HttpRequest.cc 2016-08-06 00:52:55.000000000 +1200
@@ -14,6 +14,7 @@
#include "acl/FilledChecklist.h"
#include "client_side.h"
#include "dns/LookupDetails.h"
+#include "Downloader.h"
#include "err_detail_type.h"
#include "globals.h"
#include "gopher.h"
@@ -250,6 +251,8 @@
// main property is which connection the request was received on (if any)
clientConnectionManager = aReq->clientConnectionManager;
+ downloader = aReq->downloader;
+
notes = aReq->notes;
sources = aReq->sources;
diff -u -r -N squid-4.0.12/src/HttpRequest.h squid-4.0.13/src/HttpRequest.h
--- squid-4.0.12/src/HttpRequest.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/HttpRequest.h 2016-08-06 00:52:55.000000000 +1200
@@ -34,6 +34,7 @@
#endif
class ConnStateData;
+class Downloader;
/* Http Request */
void httpRequestPack(void *obj, Packable *p);
@@ -212,6 +213,9 @@
*/
CbcPointer clientConnectionManager;
+ /// The Downloader object which initiated the HTTP request if any
+ CbcPointer downloader;
+
/// forgets about the cached Range header (for a reason)
void ignoreRange(const char *reason);
int64_t getRangeOffsetLimit(); /* the result of this function gets cached in rangeOffsetLimit */
diff -u -r -N squid-4.0.12/src/LoadableModule.cc squid-4.0.13/src/LoadableModule.cc
--- squid-4.0.12/src/LoadableModule.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/LoadableModule.cc 2016-08-06 00:52:55.000000000 +1200
@@ -7,20 +7,8 @@
*/
#include "squid.h"
-
-/* The original code has this constant ./configure-able.
- * The "#else" branches use raw dlopen interface and have not been tested.
- * We can remove that code if we are going to rely on libtool's ltdl in
- * all environments. */
-#define XSTD_USE_LIBLTDL 1
-
-#if XSTD_USE_LIBLTDL
-#include "libltdl/ltdl.h" /* generated file */
-#else
-#include
-#endif
-
#include "base/TextException.h"
+#include "libltdl/ltdl.h" /* generated file */
#include "LoadableModule.h"
// Note: We must use preprocessor instead of C ifs because if dlopen()
@@ -28,29 +16,27 @@
LoadableModule::LoadableModule(const String &aName): theName(aName), theHandle(0)
{
-# if XSTD_USE_LIBLTDL
// Initialise preloaded symbol lookup table.
LTDL_SET_PRELOADED_SYMBOLS();
if (lt_dlinit() != 0)
throw TexcHere("internal error: cannot initialize libtool module loader");
-# endif
}
LoadableModule::~LoadableModule()
{
if (loaded())
unload();
-# if XSTD_USE_LIBLTDL
assert(lt_dlexit() == 0); // XXX: replace with a warning
-# endif
}
-bool LoadableModule::loaded() const
+bool
+LoadableModule::loaded() const
{
return theHandle != 0;
}
-void LoadableModule::load(int mode)
+void
+LoadableModule::load(int mode)
{
if (loaded())
throw TexcHere("internal error: reusing LoadableModule object");
@@ -61,7 +47,8 @@
throw TexcHere(errorMsg());
}
-void LoadableModule::unload()
+void
+LoadableModule::unload()
{
if (!loaded())
throw TexcHere("internal error: unloading not loaded module");
@@ -72,32 +59,22 @@
theHandle = 0;
}
-void *LoadableModule::openModule(int mode)
+void *
+LoadableModule::openModule(int mode)
{
-# if XSTD_USE_LIBLTDL
return lt_dlopen(theName.termedBuf());
-# else
- return dlopen(theName.termedBuf(),
- mode == lmNow ? RTLD_NOW : RTLD_LAZY);
-# endif
}
-bool LoadableModule::closeModule()
+bool
+LoadableModule::closeModule()
{
-# if XSTD_USE_LIBLTDL
// we cast to avoid including ltdl.h in LoadableModule.h
return lt_dlclose(static_cast(theHandle)) == 0;
-# else
- return dlclose(theHandle) == 0;
-# endif
}
-const char *LoadableModule::errorMsg()
+const char *
+LoadableModule::errorMsg()
{
-# if XSTD_USE_LIBLTDL
return lt_dlerror();
-# else
- return dlerror();
-# endif
}
diff -u -r -N squid-4.0.12/src/log/CustomLog.h squid-4.0.13/src/log/CustomLog.h
--- squid-4.0.12/src/log/CustomLog.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/log/CustomLog.h 2016-08-06 00:52:55.000000000 +1200
@@ -9,7 +9,6 @@
#ifndef SQUID_CUSTOMLOG_H_
#define SQUID_CUSTOMLOG_H_
-//#include "format/Format.h"
#include "acl/forward.h"
#include "log/Formats.h"
diff -u -r -N squid-4.0.12/src/log/DB/log_db_daemon.8 squid-4.0.13/src/log/DB/log_db_daemon.8
--- squid-4.0.12/src/log/DB/log_db_daemon.8 2016-07-02 02:24:43.000000000 +1200
+++ squid-4.0.13/src/log/DB/log_db_daemon.8 2016-08-06 02:28:37.000000000 +1200
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "LOG_DB_DAEMON 8"
-.TH LOG_DB_DAEMON 8 "2016-07-01" "perl v5.22.2" "User Contributed Perl Documentation"
+.TH LOG_DB_DAEMON 8 "2016-08-05" "perl v5.22.2" "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.12/src/Makefile.am squid-4.0.13/src/Makefile.am
--- squid-4.0.12/src/Makefile.am 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/Makefile.am 2016-08-06 00:52:55.000000000 +1200
@@ -272,6 +272,8 @@
dlink.h \
dlink.cc \
$(DNSSOURCE) \
+ Downloader.cc \
+ Downloader.h \
enums.h \
err_type.h \
err_detail_type.h \
@@ -1433,6 +1435,8 @@
tests_testCacheManager_LDFLAGS = $(LIBADD_DL)
tests_testDiskIO_SOURCES = \
+ AccessLogEntry.cc \
+ AccessLogEntry.h \
CacheDigest.h \
tests/stub_CacheDigest.cc \
cbdata.cc \
@@ -1538,6 +1542,7 @@
tests/stub_libeui.cc \
tests/stub_libformat.cc \
tests/stub_libicmp.cc \
+ tests/stub_liblog.cc \
tests/stub_MemStore.cc \
mime.h \
tests/stub_mime.cc \
@@ -1581,6 +1586,7 @@
fs/libfs.la \
ipc/libipc.la \
$(REPL_OBJS) \
+ $(ADAPTATION_LIBS) \
DiskIO/libdiskio.la \
acl/libapi.la \
anyp/libanyp.la \
@@ -2896,6 +2902,8 @@
$(REPL_OBJS)
tests_testUfs_SOURCES = \
+ AccessLogEntry.cc \
+ AccessLogEntry.h \
tests/testUfs.cc \
tests/testUfs.h \
tests/stub_cache_manager.cc \
@@ -2907,6 +2915,7 @@
tests/stub_ipcache.cc \
tests/stub_libeui.cc \
tests/stub_libicmp.cc \
+ tests/stub_liblog.cc \
tests/stub_MemStore.cc \
tests/stub_neighbors.cc \
tests/stub_pconn.cc \
@@ -3053,6 +3062,7 @@
ip/libip.la \
mem/libmem.la \
store/libstore.la \
+ $(ADAPTATION_LIBS) \
sbuf/libsbuf.la \
$(top_builddir)/lib/libmisccontainers.la \
$(top_builddir)/lib/libmiscencoding.la \
@@ -3083,6 +3093,8 @@
$(XTRA_LIBS)
tests_testRock_SOURCES = \
+ AccessLogEntry.cc \
+ AccessLogEntry.h \
cbdata.cc \
CacheDigest.h \
CollapsedForwarding.h \
@@ -3181,6 +3193,7 @@
tests/stub_libeui.cc \
tests/stub_libformat.cc \
tests/stub_libicmp.cc \
+ tests/stub_liblog.cc \
tests/stub_libmgr.cc \
tests/stub_libsecurity.cc \
tests/stub_MemStore.cc \
@@ -3226,6 +3239,7 @@
base/libbase.la \
mem/libmem.la \
store/libstore.la \
+ $(ADAPTATION_LIBS) \
sbuf/libsbuf.la \
$(top_builddir)/lib/libmisccontainers.la \
$(top_builddir)/lib/libmiscencoding.la \
diff -u -r -N squid-4.0.12/src/Makefile.in squid-4.0.13/src/Makefile.in
--- squid-4.0.12/src/Makefile.in 2016-07-02 01:28:23.000000000 +1200
+++ squid-4.0.13/src/Makefile.in 2016-08-06 00:54:37.000000000 +1200
@@ -256,15 +256,15 @@
DelayUser.cc DelayUser.h DelayVector.cc DelayVector.h \
NullDelayId.cc NullDelayId.h ClientDelayConfig.cc \
ClientDelayConfig.h fs_io.h fs_io.cc dlink.h dlink.cc \
- dns_internal.cc enums.h err_type.h err_detail_type.h \
- errorpage.cc errorpage.h ETag.cc ETag.h event.cc event.h \
- EventLoop.h EventLoop.cc external_acl.cc ExternalACL.h \
- ExternalACLEntry.cc ExternalACLEntry.h FadingCounter.h \
- FadingCounter.cc fatal.h fatal.cc fd.h fd.cc fde.cc fde.h \
- FileMap.h filemap.cc fqdncache.h fqdncache.cc FwdState.cc \
- FwdState.h Generic.h globals.h gopher.h gopher.cc helper.cc \
- helper.h hier_code.h HierarchyLogEntry.h htcp.cc htcp.h \
- HttpStateFlags.h http.cc http.h HttpHeaderFieldStat.h \
+ dns_internal.cc Downloader.cc Downloader.h enums.h err_type.h \
+ err_detail_type.h errorpage.cc errorpage.h ETag.cc ETag.h \
+ event.cc event.h EventLoop.h EventLoop.cc external_acl.cc \
+ ExternalACL.h ExternalACLEntry.cc ExternalACLEntry.h \
+ FadingCounter.h FadingCounter.cc fatal.h fatal.cc fd.h fd.cc \
+ fde.cc fde.h FileMap.h filemap.cc fqdncache.h fqdncache.cc \
+ FwdState.cc FwdState.h Generic.h globals.h gopher.h gopher.cc \
+ helper.cc helper.h hier_code.h HierarchyLogEntry.h htcp.cc \
+ htcp.h HttpStateFlags.h http.cc http.h HttpHeaderFieldStat.h \
HttpHdrCc.h HttpHdrCc.cc HttpHdrCc.cci HttpHdrRange.cc \
HttpHdrSc.cc HttpHdrSc.h HttpHdrScTarget.cc HttpHdrScTarget.h \
HttpHdrContRange.cc HttpHdrContRange.h HttpHeaderStat.h \
@@ -345,8 +345,8 @@
CpuAffinity.$(OBJEXT) CpuAffinityMap.$(OBJEXT) \
CpuAffinitySet.$(OBJEXT) debug.$(OBJEXT) $(am__objects_3) \
fs_io.$(OBJEXT) dlink.$(OBJEXT) $(am__objects_4) \
- errorpage.$(OBJEXT) ETag.$(OBJEXT) event.$(OBJEXT) \
- EventLoop.$(OBJEXT) external_acl.$(OBJEXT) \
+ Downloader.$(OBJEXT) errorpage.$(OBJEXT) ETag.$(OBJEXT) \
+ event.$(OBJEXT) EventLoop.$(OBJEXT) external_acl.$(OBJEXT) \
ExternalACLEntry.$(OBJEXT) FadingCounter.$(OBJEXT) \
fatal.$(OBJEXT) fd.$(OBJEXT) fde.$(OBJEXT) filemap.$(OBJEXT) \
fqdncache.$(OBJEXT) FwdState.$(OBJEXT) gopher.$(OBJEXT) \
@@ -687,9 +687,9 @@
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
$(AM_CXXFLAGS) $(CXXFLAGS) $(tests_testConfigParser_LDFLAGS) \
$(LDFLAGS) -o $@
-am__tests_testDiskIO_SOURCES_DIST = CacheDigest.h \
- tests/stub_CacheDigest.cc cbdata.cc client_db.h ClientInfo.h \
- tests/stub_CollapsedForwarding.cc ConfigOption.cc \
+am__tests_testDiskIO_SOURCES_DIST = AccessLogEntry.cc AccessLogEntry.h \
+ CacheDigest.h tests/stub_CacheDigest.cc cbdata.cc client_db.h \
+ ClientInfo.h tests/stub_CollapsedForwarding.cc ConfigOption.cc \
ConfigParser.cc CommonPool.h CompositePoolNode.h \
delay_pools.cc DelayId.cc DelayId.h DelayIdComposite.h \
DelayBucket.cc DelayBucket.h DelayConfig.cc DelayConfig.h \
@@ -726,17 +726,19 @@
tests/stub_internal.cc tests/stub_ipc.cc tests/stub_ipcache.cc \
tests/stub_libauth_acls.cc tests/stub_libauth.cc \
tests/stub_libeui.cc tests/stub_libformat.cc \
- tests/stub_libicmp.cc tests/stub_MemStore.cc mime.h \
- tests/stub_mime.cc tests/stub_neighbors.cc tests/stub_pconn.cc \
- tests/stub_Port.cc tests/stub_stat.cc \
- tests/stub_store_client.cc tests/stub_store_stats.cc \
- store_rebuild.h tests/stub_store_rebuild.cc \
- tests/stub_UdsOp.cc tests/testDiskIO.cc tests/testDiskIO.h \
+ tests/stub_libicmp.cc tests/stub_liblog.cc \
+ tests/stub_MemStore.cc mime.h tests/stub_mime.cc \
+ tests/stub_neighbors.cc tests/stub_pconn.cc tests/stub_Port.cc \
+ tests/stub_stat.cc tests/stub_store_client.cc \
+ tests/stub_store_stats.cc store_rebuild.h \
+ tests/stub_store_rebuild.cc tests/stub_UdsOp.cc \
+ tests/testDiskIO.cc tests/testDiskIO.h \
tests/testStoreSupport.cc tests/testStoreSupport.h \
tests/stub_time.cc unlinkd.h unlinkd.cc url.cc win32.cc \
wordlist.h wordlist.cc tools.h tests/stub_tools.cc
-am_tests_testDiskIO_OBJECTS = tests/stub_CacheDigest.$(OBJEXT) \
- cbdata.$(OBJEXT) tests/stub_CollapsedForwarding.$(OBJEXT) \
+am_tests_testDiskIO_OBJECTS = AccessLogEntry.$(OBJEXT) \
+ tests/stub_CacheDigest.$(OBJEXT) cbdata.$(OBJEXT) \
+ tests/stub_CollapsedForwarding.$(OBJEXT) \
ConfigOption.$(OBJEXT) ConfigParser.$(OBJEXT) $(am__objects_3) \
fs_io.$(OBJEXT) tests/stub_ETag.$(OBJEXT) EventLoop.$(OBJEXT) \
event.$(OBJEXT) tests/stub_fatal.$(OBJEXT) fd.$(OBJEXT) \
@@ -771,10 +773,11 @@
tests/stub_ipc.$(OBJEXT) tests/stub_ipcache.$(OBJEXT) \
tests/stub_libauth_acls.$(OBJEXT) tests/stub_libauth.$(OBJEXT) \
tests/stub_libeui.$(OBJEXT) tests/stub_libformat.$(OBJEXT) \
- tests/stub_libicmp.$(OBJEXT) tests/stub_MemStore.$(OBJEXT) \
- tests/stub_mime.$(OBJEXT) tests/stub_neighbors.$(OBJEXT) \
- tests/stub_pconn.$(OBJEXT) tests/stub_Port.$(OBJEXT) \
- tests/stub_stat.$(OBJEXT) tests/stub_store_client.$(OBJEXT) \
+ tests/stub_libicmp.$(OBJEXT) tests/stub_liblog.$(OBJEXT) \
+ tests/stub_MemStore.$(OBJEXT) tests/stub_mime.$(OBJEXT) \
+ tests/stub_neighbors.$(OBJEXT) tests/stub_pconn.$(OBJEXT) \
+ tests/stub_Port.$(OBJEXT) tests/stub_stat.$(OBJEXT) \
+ tests/stub_store_client.$(OBJEXT) \
tests/stub_store_stats.$(OBJEXT) \
tests/stub_store_rebuild.$(OBJEXT) tests/stub_UdsOp.$(OBJEXT) \
tests/testDiskIO.$(OBJEXT) tests/testStoreSupport.$(OBJEXT) \
@@ -1337,14 +1340,14 @@
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
$(AM_CXXFLAGS) $(CXXFLAGS) $(tests_testLookupTable_LDFLAGS) \
$(LDFLAGS) -o $@
-am__tests_testRock_SOURCES_DIST = cbdata.cc CacheDigest.h \
- CollapsedForwarding.h CollapsedForwarding.cc \
- tests/stub_CacheDigest.cc ConfigOption.cc ConfigParser.cc \
- fs_io.h fs_io.cc ETag.cc EventLoop.cc event.cc fatal.h \
- fatal.cc fd.h fd.cc fde.h fde.cc FileMap.h filemap.cc \
- HttpHeaderFieldStat.h HttpBody.h HttpBody.cc HttpHdrCc.cc \
- HttpHdrContRange.cc HttpHdrRange.cc HttpHdrSc.cc \
- HttpHdrScTarget.cc HttpHeader.h HttpHeader.cc \
+am__tests_testRock_SOURCES_DIST = AccessLogEntry.cc AccessLogEntry.h \
+ cbdata.cc CacheDigest.h CollapsedForwarding.h \
+ CollapsedForwarding.cc tests/stub_CacheDigest.cc \
+ ConfigOption.cc ConfigParser.cc fs_io.h fs_io.cc ETag.cc \
+ EventLoop.cc event.cc fatal.h fatal.cc fd.h fd.cc fde.h fde.cc \
+ FileMap.h filemap.cc HttpHeaderFieldStat.h HttpBody.h \
+ HttpBody.cc HttpHdrCc.cc HttpHdrContRange.cc HttpHdrRange.cc \
+ HttpHdrSc.cc HttpHdrScTarget.cc HttpHeader.h HttpHeader.cc \
HttpHeaderFieldInfo.h HttpHeaderTools.h HttpHeaderTools.cc \
HttpMsg.cc HttpReply.cc int.h int.cc SquidList.h SquidList.cc \
MasterXaction.cc MasterXaction.h MemBuf.cc MemObject.cc \
@@ -1370,10 +1373,11 @@
tests/stub_HttpRequest.cc tests/stub_libauth.cc \
tests/stub_icp.cc tests/stub_ipc.cc tests/stub_ipcache.cc \
tests/stub_libeui.cc tests/stub_libformat.cc \
- tests/stub_libicmp.cc tests/stub_libmgr.cc \
- tests/stub_libsecurity.cc tests/stub_MemStore.cc mime.h \
- tests/stub_mime.cc tests/stub_neighbors.cc tests/stub_Port.cc \
- tests/stub_pconn.cc tests/stub_store_client.cc store_rebuild.h \
+ tests/stub_libicmp.cc tests/stub_liblog.cc \
+ tests/stub_libmgr.cc tests/stub_libsecurity.cc \
+ tests/stub_MemStore.cc mime.h tests/stub_mime.cc \
+ tests/stub_neighbors.cc tests/stub_Port.cc tests/stub_pconn.cc \
+ tests/stub_store_client.cc store_rebuild.h \
tests/stub_store_rebuild.cc tests/stub_store_stats.cc tools.h \
tests/stub_tools.cc time.cc url.cc wordlist.h wordlist.cc \
CommonPool.h CompositePoolNode.h delay_pools.cc DelayId.cc \
@@ -1383,7 +1387,7 @@
DelayTagged.h DelayUser.cc DelayUser.h DelayVector.cc \
DelayVector.h NullDelayId.cc NullDelayId.h \
ClientDelayConfig.cc ClientDelayConfig.h unlinkd.h unlinkd.cc
-am_tests_testRock_OBJECTS = cbdata.$(OBJEXT) \
+am_tests_testRock_OBJECTS = AccessLogEntry.$(OBJEXT) cbdata.$(OBJEXT) \
CollapsedForwarding.$(OBJEXT) tests/stub_CacheDigest.$(OBJEXT) \
ConfigOption.$(OBJEXT) ConfigParser.$(OBJEXT) fs_io.$(OBJEXT) \
ETag.$(OBJEXT) EventLoop.$(OBJEXT) event.$(OBJEXT) \
@@ -1416,11 +1420,11 @@
tests/stub_libauth.$(OBJEXT) tests/stub_icp.$(OBJEXT) \
tests/stub_ipc.$(OBJEXT) tests/stub_ipcache.$(OBJEXT) \
tests/stub_libeui.$(OBJEXT) tests/stub_libformat.$(OBJEXT) \
- tests/stub_libicmp.$(OBJEXT) tests/stub_libmgr.$(OBJEXT) \
- tests/stub_libsecurity.$(OBJEXT) tests/stub_MemStore.$(OBJEXT) \
- tests/stub_mime.$(OBJEXT) tests/stub_neighbors.$(OBJEXT) \
- tests/stub_Port.$(OBJEXT) tests/stub_pconn.$(OBJEXT) \
- tests/stub_store_client.$(OBJEXT) \
+ tests/stub_libicmp.$(OBJEXT) tests/stub_liblog.$(OBJEXT) \
+ tests/stub_libmgr.$(OBJEXT) tests/stub_libsecurity.$(OBJEXT) \
+ tests/stub_MemStore.$(OBJEXT) tests/stub_mime.$(OBJEXT) \
+ tests/stub_neighbors.$(OBJEXT) tests/stub_Port.$(OBJEXT) \
+ tests/stub_pconn.$(OBJEXT) tests/stub_store_client.$(OBJEXT) \
tests/stub_store_rebuild.$(OBJEXT) \
tests/stub_store_stats.$(OBJEXT) tests/stub_tools.$(OBJEXT) \
time.$(OBJEXT) url.$(OBJEXT) wordlist.$(OBJEXT) \
@@ -1774,34 +1778,35 @@
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
$(AM_CXXFLAGS) $(CXXFLAGS) $(tests_testURL_LDFLAGS) $(LDFLAGS) \
-o $@
-am__tests_testUfs_SOURCES_DIST = tests/testUfs.cc tests/testUfs.h \
- tests/stub_cache_manager.cc tests/stub_client_db.cc \
- tests/stub_CollapsedForwarding.cc \
+am__tests_testUfs_SOURCES_DIST = AccessLogEntry.cc AccessLogEntry.h \
+ tests/testUfs.cc tests/testUfs.h tests/stub_cache_manager.cc \
+ tests/stub_client_db.cc tests/stub_CollapsedForwarding.cc \
tests/stub_HelperChildConfig.cc tests/stub_icp.cc \
tests/stub_ipc.cc tests/stub_ipcache.cc tests/stub_libeui.cc \
- tests/stub_libicmp.cc tests/stub_MemStore.cc \
- tests/stub_neighbors.cc tests/stub_pconn.cc tests/stub_Port.cc \
- tests/stub_UdsOp.cc internal.h tests/stub_internal.cc \
- tests/stub_libformat.cc tests/stub_libsecurity.cc \
- tests/stub_stat.cc store_rebuild.h tests/stub_store_rebuild.cc \
- tests/stub_store_stats.cc fatal.h tests/stub_fatal.cc fd.h \
- fd.cc fde.h fde.cc client_db.h fs_io.h fs_io.cc FileMap.h \
- filemap.cc HttpBody.h HttpBody.cc HttpReply.cc int.h int.cc \
- RequestFlags.h RequestFlags.cc SquidList.h SquidList.cc \
- Transients.cc MasterXaction.cc MasterXaction.h MemObject.cc \
- Notes.h Notes.cc StoreSwapLogData.cc StoreIOState.cc \
- StoreMetaUnpacker.cc StoreMeta.cc StoreMeta.h StoreMetaMD5.cc \
- StoreMetaMD5.h StoreMetaSTD.cc StoreMetaSTD.h \
- StoreMetaSTDLFS.cc StoreMetaSTDLFS.h StoreMetaObjSize.h \
- StoreMetaURL.cc StoreMetaURL.h StoreMetaVary.cc \
- StoreMetaVary.h StoreFileSystem.cc store_io.cc \
- store_swapout.cc store_swapmeta.cc unlinkd.h unlinkd.cc \
- win32.cc event.cc CommonPool.h CompositePoolNode.h \
- delay_pools.cc DelayId.cc DelayId.h DelayIdComposite.h \
- DelayBucket.cc DelayBucket.h DelayConfig.cc DelayConfig.h \
- DelayPool.cc DelayPool.h DelayPools.h DelaySpec.cc DelaySpec.h \
- DelayTagged.cc DelayTagged.h DelayUser.cc DelayUser.h \
- DelayVector.cc DelayVector.h NullDelayId.cc NullDelayId.h \
+ tests/stub_libicmp.cc tests/stub_liblog.cc \
+ tests/stub_MemStore.cc tests/stub_neighbors.cc \
+ tests/stub_pconn.cc tests/stub_Port.cc tests/stub_UdsOp.cc \
+ internal.h tests/stub_internal.cc tests/stub_libformat.cc \
+ tests/stub_libsecurity.cc tests/stub_stat.cc store_rebuild.h \
+ tests/stub_store_rebuild.cc tests/stub_store_stats.cc fatal.h \
+ tests/stub_fatal.cc fd.h fd.cc fde.h fde.cc client_db.h \
+ fs_io.h fs_io.cc FileMap.h filemap.cc HttpBody.h HttpBody.cc \
+ HttpReply.cc int.h int.cc RequestFlags.h RequestFlags.cc \
+ SquidList.h SquidList.cc Transients.cc MasterXaction.cc \
+ MasterXaction.h MemObject.cc Notes.h Notes.cc \
+ StoreSwapLogData.cc StoreIOState.cc StoreMetaUnpacker.cc \
+ StoreMeta.cc StoreMeta.h StoreMetaMD5.cc StoreMetaMD5.h \
+ StoreMetaSTD.cc StoreMetaSTD.h StoreMetaSTDLFS.cc \
+ StoreMetaSTDLFS.h StoreMetaObjSize.h StoreMetaURL.cc \
+ StoreMetaURL.h StoreMetaVary.cc StoreMetaVary.h \
+ StoreFileSystem.cc store_io.cc store_swapout.cc \
+ store_swapmeta.cc unlinkd.h unlinkd.cc win32.cc event.cc \
+ CommonPool.h CompositePoolNode.h delay_pools.cc DelayId.cc \
+ DelayId.h DelayIdComposite.h DelayBucket.cc DelayBucket.h \
+ DelayConfig.cc DelayConfig.h DelayPool.cc DelayPool.h \
+ DelayPools.h DelaySpec.cc DelaySpec.h DelayTagged.cc \
+ DelayTagged.h DelayUser.cc DelayUser.h DelayVector.cc \
+ DelayVector.h NullDelayId.cc NullDelayId.h \
ClientDelayConfig.cc ClientDelayConfig.h CacheDigest.h \
tests/stub_CacheDigest.cc ConfigParser.cc EventLoop.cc \
HttpMsg.cc RemovalPolicy.cc repl_modules.h store.cc \
@@ -1822,17 +1827,18 @@
tests/stub_store_client.cc tools.h tests/stub_tools.cc \
tests/testStoreSupport.cc tests/testStoreSupport.h time.cc \
wordlist.h wordlist.cc
-am_tests_testUfs_OBJECTS = tests/testUfs.$(OBJEXT) \
- tests/stub_cache_manager.$(OBJEXT) \
+am_tests_testUfs_OBJECTS = AccessLogEntry.$(OBJEXT) \
+ tests/testUfs.$(OBJEXT) tests/stub_cache_manager.$(OBJEXT) \
tests/stub_client_db.$(OBJEXT) \
tests/stub_CollapsedForwarding.$(OBJEXT) \
tests/stub_HelperChildConfig.$(OBJEXT) \
tests/stub_icp.$(OBJEXT) tests/stub_ipc.$(OBJEXT) \
tests/stub_ipcache.$(OBJEXT) tests/stub_libeui.$(OBJEXT) \
- tests/stub_libicmp.$(OBJEXT) tests/stub_MemStore.$(OBJEXT) \
- tests/stub_neighbors.$(OBJEXT) tests/stub_pconn.$(OBJEXT) \
- tests/stub_Port.$(OBJEXT) tests/stub_UdsOp.$(OBJEXT) \
- tests/stub_internal.$(OBJEXT) tests/stub_libformat.$(OBJEXT) \
+ tests/stub_libicmp.$(OBJEXT) tests/stub_liblog.$(OBJEXT) \
+ tests/stub_MemStore.$(OBJEXT) tests/stub_neighbors.$(OBJEXT) \
+ tests/stub_pconn.$(OBJEXT) tests/stub_Port.$(OBJEXT) \
+ tests/stub_UdsOp.$(OBJEXT) tests/stub_internal.$(OBJEXT) \
+ tests/stub_libformat.$(OBJEXT) \
tests/stub_libsecurity.$(OBJEXT) tests/stub_stat.$(OBJEXT) \
tests/stub_store_rebuild.$(OBJEXT) \
tests/stub_store_stats.$(OBJEXT) tests/stub_fatal.$(OBJEXT) \
@@ -2848,47 +2854,47 @@
CpuAffinityMap.cc CpuAffinityMap.h CpuAffinitySet.cc \
CpuAffinitySet.h debug.cc Debug.h defines.h \
$(DELAY_POOL_SOURCE) fs_io.h fs_io.cc dlink.h dlink.cc \
- $(DNSSOURCE) enums.h err_type.h err_detail_type.h errorpage.cc \
- errorpage.h ETag.cc ETag.h event.cc event.h EventLoop.h \
- EventLoop.cc external_acl.cc ExternalACL.h ExternalACLEntry.cc \
- ExternalACLEntry.h FadingCounter.h FadingCounter.cc fatal.h \
- fatal.cc fd.h fd.cc fde.cc fde.h FileMap.h filemap.cc \
- fqdncache.h fqdncache.cc FwdState.cc FwdState.h Generic.h \
- globals.h gopher.h gopher.cc helper.cc helper.h hier_code.h \
- HierarchyLogEntry.h $(HTCPSOURCE) HttpStateFlags.h http.cc \
- http.h HttpHeaderFieldStat.h HttpHdrCc.h HttpHdrCc.cc \
- HttpHdrCc.cci HttpHdrRange.cc HttpHdrSc.cc HttpHdrSc.h \
- HttpHdrScTarget.cc HttpHdrScTarget.h HttpHdrContRange.cc \
- HttpHdrContRange.h HttpHeaderStat.h HttpHeader.h HttpHeader.cc \
- HttpHeaderMask.h HttpHeaderRange.h HttpHeaderFieldInfo.h \
- HttpHeaderTools.h HttpHeaderTools.cc HttpBody.h HttpBody.cc \
- HttpControlMsg.cc HttpControlMsg.h HttpMsg.cc HttpMsg.h \
- HttpReply.cc HttpReply.h RequestFlags.h RequestFlags.cc \
- HttpRequest.cc HttpRequest.h ICP.h icp_opcode.h icp_v2.cc \
- icp_v3.cc int.h int.cc internal.h internal.cc $(IPC_SOURCE) \
- ipcache.cc ipcache.h $(LEAKFINDERSOURCE) SquidList.h \
- SquidList.cc LogTags.cc LogTags.h lookup_t.h main.cc \
- MasterXaction.cc MasterXaction.h mem_node.cc mem_node.h \
- MemBuf.cc MemObject.cc MemObject.h MessageSizes.h mime.h \
- mime.cc mime_header.h mime_header.cc multicast.h multicast.cc \
- neighbors.h neighbors.cc Notes.h Notes.cc Parsing.cc Parsing.h \
- $(XPROF_STATS_SOURCE) pconn.cc pconn.h PeerDigest.h \
- peer_digest.cc peer_proxy_negotiate_auth.h \
- peer_proxy_negotiate_auth.cc peer_select.cc peer_sourcehash.h \
- peer_sourcehash.cc peer_userhash.h peer_userhash.cc \
- PeerPoolMgr.h PeerPoolMgr.cc PeerSelectState.h PingData.h \
- Pipeline.cc Pipeline.h protos.h redirect.h redirect.cc \
- refresh.h refresh.cc RemovalPolicy.cc RemovalPolicy.h \
- send-announce.h send-announce.cc SBufStatsAction.h \
- SBufStatsAction.cc sbuf/StringConvert.h $(SNMP_SOURCE) \
- SquidMath.h SquidMath.cc SquidNew.cc IoStats.h stat.h stat.cc \
- StatCounters.h StatCounters.cc StatHist.h StatHist.cc \
- String.cc StrList.h StrList.cc stmem.cc stmem.h repl_modules.h \
- store.cc Store.h StoreFileSystem.cc StoreFileSystem.h \
- store_io.cc StoreIOBuffer.h StoreIOState.cc StoreIOState.h \
- store_client.cc StoreClient.h store_digest.h store_digest.cc \
- store_key_md5.h store_key_md5.cc store_log.h store_log.cc \
- store_rebuild.h store_rebuild.cc store_swapin.h \
+ $(DNSSOURCE) Downloader.cc Downloader.h enums.h err_type.h \
+ err_detail_type.h errorpage.cc errorpage.h ETag.cc ETag.h \
+ event.cc event.h EventLoop.h EventLoop.cc external_acl.cc \
+ ExternalACL.h ExternalACLEntry.cc ExternalACLEntry.h \
+ FadingCounter.h FadingCounter.cc fatal.h fatal.cc fd.h fd.cc \
+ fde.cc fde.h FileMap.h filemap.cc fqdncache.h fqdncache.cc \
+ FwdState.cc FwdState.h Generic.h globals.h gopher.h gopher.cc \
+ helper.cc helper.h hier_code.h HierarchyLogEntry.h \
+ $(HTCPSOURCE) HttpStateFlags.h http.cc http.h \
+ HttpHeaderFieldStat.h HttpHdrCc.h HttpHdrCc.cc HttpHdrCc.cci \
+ HttpHdrRange.cc HttpHdrSc.cc HttpHdrSc.h HttpHdrScTarget.cc \
+ HttpHdrScTarget.h HttpHdrContRange.cc HttpHdrContRange.h \
+ HttpHeaderStat.h HttpHeader.h HttpHeader.cc HttpHeaderMask.h \
+ HttpHeaderRange.h HttpHeaderFieldInfo.h HttpHeaderTools.h \
+ HttpHeaderTools.cc HttpBody.h HttpBody.cc HttpControlMsg.cc \
+ HttpControlMsg.h HttpMsg.cc HttpMsg.h HttpReply.cc HttpReply.h \
+ RequestFlags.h RequestFlags.cc HttpRequest.cc HttpRequest.h \
+ ICP.h icp_opcode.h icp_v2.cc icp_v3.cc int.h int.cc internal.h \
+ internal.cc $(IPC_SOURCE) ipcache.cc ipcache.h \
+ $(LEAKFINDERSOURCE) SquidList.h SquidList.cc LogTags.cc \
+ LogTags.h lookup_t.h main.cc MasterXaction.cc MasterXaction.h \
+ mem_node.cc mem_node.h MemBuf.cc MemObject.cc MemObject.h \
+ MessageSizes.h mime.h mime.cc mime_header.h mime_header.cc \
+ multicast.h multicast.cc neighbors.h neighbors.cc Notes.h \
+ Notes.cc Parsing.cc Parsing.h $(XPROF_STATS_SOURCE) pconn.cc \
+ pconn.h PeerDigest.h peer_digest.cc \
+ peer_proxy_negotiate_auth.h peer_proxy_negotiate_auth.cc \
+ peer_select.cc peer_sourcehash.h peer_sourcehash.cc \
+ peer_userhash.h peer_userhash.cc PeerPoolMgr.h PeerPoolMgr.cc \
+ PeerSelectState.h PingData.h Pipeline.cc Pipeline.h protos.h \
+ redirect.h redirect.cc refresh.h refresh.cc RemovalPolicy.cc \
+ RemovalPolicy.h send-announce.h send-announce.cc \
+ SBufStatsAction.h SBufStatsAction.cc sbuf/StringConvert.h \
+ $(SNMP_SOURCE) SquidMath.h SquidMath.cc SquidNew.cc IoStats.h \
+ stat.h stat.cc StatCounters.h StatCounters.cc StatHist.h \
+ StatHist.cc String.cc StrList.h StrList.cc stmem.cc stmem.h \
+ repl_modules.h store.cc Store.h StoreFileSystem.cc \
+ StoreFileSystem.h store_io.cc StoreIOBuffer.h StoreIOState.cc \
+ StoreIOState.h store_client.cc StoreClient.h store_digest.h \
+ store_digest.cc store_key_md5.h store_key_md5.cc store_log.h \
+ store_log.cc store_rebuild.h store_rebuild.cc store_swapin.h \
store_swapin.cc store_swapmeta.cc store_swapout.cc \
StoreMetaUnpacker.cc StoreMetaUnpacker.h $(STOREMETA_SOURCE) \
StoreSearch.h StoreStats.cc StoreStats.h StoreSwapLogData.cc \
@@ -3097,6 +3103,7 @@
tests/stub_libeui.cc \
tests/stub_libformat.cc \
tests/stub_libicmp.cc \
+ tests/stub_liblog.cc \
tests/stub_libmem.cc \
tests/stub_libmgr.cc \
tests/stub_libsecurity.cc \
@@ -3692,6 +3699,8 @@
tests_testCacheManager_LDFLAGS = $(LIBADD_DL)
tests_testDiskIO_SOURCES = \
+ AccessLogEntry.cc \
+ AccessLogEntry.h \
CacheDigest.h \
tests/stub_CacheDigest.cc \
cbdata.cc \
@@ -3797,6 +3806,7 @@
tests/stub_libeui.cc \
tests/stub_libformat.cc \
tests/stub_libicmp.cc \
+ tests/stub_liblog.cc \
tests/stub_MemStore.cc \
mime.h \
tests/stub_mime.cc \
@@ -3842,6 +3852,7 @@
fs/libfs.la \
ipc/libipc.la \
$(REPL_OBJS) \
+ $(ADAPTATION_LIBS) \
DiskIO/libdiskio.la \
acl/libapi.la \
anyp/libanyp.la \
@@ -5169,6 +5180,8 @@
$(REPL_OBJS)
tests_testUfs_SOURCES = \
+ AccessLogEntry.cc \
+ AccessLogEntry.h \
tests/testUfs.cc \
tests/testUfs.h \
tests/stub_cache_manager.cc \
@@ -5180,6 +5193,7 @@
tests/stub_ipcache.cc \
tests/stub_libeui.cc \
tests/stub_libicmp.cc \
+ tests/stub_liblog.cc \
tests/stub_MemStore.cc \
tests/stub_neighbors.cc \
tests/stub_pconn.cc \
@@ -5327,6 +5341,7 @@
ip/libip.la \
mem/libmem.la \
store/libstore.la \
+ $(ADAPTATION_LIBS) \
sbuf/libsbuf.la \
$(top_builddir)/lib/libmisccontainers.la \
$(top_builddir)/lib/libmiscencoding.la \
@@ -5358,6 +5373,8 @@
$(XTRA_LIBS)
tests_testRock_SOURCES = \
+ AccessLogEntry.cc \
+ AccessLogEntry.h \
cbdata.cc \
CacheDigest.h \
CollapsedForwarding.h \
@@ -5456,6 +5473,7 @@
tests/stub_libeui.cc \
tests/stub_libformat.cc \
tests/stub_libicmp.cc \
+ tests/stub_liblog.cc \
tests/stub_libmgr.cc \
tests/stub_libsecurity.cc \
tests/stub_MemStore.cc \
@@ -5503,6 +5521,7 @@
base/libbase.la \
mem/libmem.la \
store/libstore.la \
+ $(ADAPTATION_LIBS) \
sbuf/libsbuf.la \
$(top_builddir)/lib/libmisccontainers.la \
$(top_builddir)/lib/libmiscencoding.la \
@@ -6318,6 +6337,8 @@
tests/$(DEPDIR)/$(am__dirstamp)
tests/stub_libicmp.$(OBJEXT): tests/$(am__dirstamp) \
tests/$(DEPDIR)/$(am__dirstamp)
+tests/stub_liblog.$(OBJEXT): tests/$(am__dirstamp) \
+ tests/$(DEPDIR)/$(am__dirstamp)
tests/stub_neighbors.$(OBJEXT): tests/$(am__dirstamp) \
tests/$(DEPDIR)/$(am__dirstamp)
tests/stub_stat.$(OBJEXT): tests/$(am__dirstamp) \
@@ -6523,6 +6544,7 @@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DelayUser.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DelayVector.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DescriptorSet.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Downloader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ETag.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/EventLoop.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ExternalACLEntry.Po@am__quote@
@@ -6717,6 +6739,7 @@
@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_libeui.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_libformat.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_libicmp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_liblog.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_libmem.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_libmgr.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_libsecurity.Po@am__quote@
diff -u -r -N squid-4.0.12/src/MemBuf.cc squid-4.0.13/src/MemBuf.cc
--- squid-4.0.12/src/MemBuf.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/MemBuf.cc 2016-08-06 00:52:55.000000000 +1200
@@ -154,7 +154,7 @@
* Unfortunate hack to test if the buffer has been Init()ialized
*/
int
-MemBuf::isNull()
+MemBuf::isNull() const
{
if (!buf && !max_capacity && !capacity && !size)
return 1; /* is null (not initialized) */
diff -u -r -N squid-4.0.12/src/MemBuf.h squid-4.0.13/src/MemBuf.h
--- squid-4.0.12/src/MemBuf.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/MemBuf.h 2016-08-06 00:52:55.000000000 +1200
@@ -99,7 +99,7 @@
void reset();
/** unfirtunate hack to test if the buffer has been Init()ialized */
- int isNull();
+ int isNull() const;
/**
* freezes the object! and returns function to clear it up.
diff -u -r -N squid-4.0.12/src/MemStore.h squid-4.0.13/src/MemStore.h
--- squid-4.0.12/src/MemStore.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/MemStore.h 2016-08-06 00:52:55.000000000 +1200
@@ -63,6 +63,7 @@
virtual bool updateCollapsed(StoreEntry &e) override;
virtual void markForUnlink(StoreEntry &) override;
virtual void unlink(StoreEntry &e) override;
+ virtual bool smpAware() const override { return true; }
static int64_t EntryLimit();
diff -u -r -N squid-4.0.12/src/peer_digest.cc squid-4.0.13/src/peer_digest.cc
--- squid-4.0.12/src/peer_digest.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/peer_digest.cc 2016-08-06 00:52:55.000000000 +1200
@@ -746,7 +746,7 @@
if (!reason && !size) {
if (!pd->cd)
reason = "null digest?!";
- else if (fetch->mask_offset != (int)pd->cd->mask_size)
+ else if (fetch->mask_offset != pd->cd->mask_size)
reason = "premature end of digest?!";
else if (!peerDigestUseful(pd))
reason = "useless digest";
diff -u -r -N squid-4.0.12/src/PeerDigest.h squid-4.0.13/src/PeerDigest.h
--- squid-4.0.12/src/PeerDigest.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/PeerDigest.h 2016-08-06 00:52:55.000000000 +1200
@@ -56,7 +56,7 @@
store_client *old_sc;
HttpRequest *request;
int offset;
- int mask_offset;
+ uint32_t mask_offset;
time_t start_time;
time_t resp_time;
time_t expires;
diff -u -r -N squid-4.0.12/src/PeerPoolMgr.cc squid-4.0.13/src/PeerPoolMgr.cc
--- squid-4.0.12/src/PeerPoolMgr.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/PeerPoolMgr.cc 2016-08-06 00:52:55.000000000 +1200
@@ -7,6 +7,7 @@
*/
#include "squid.h"
+#include "AccessLogEntry.h"
#include "base/AsyncJobCalls.h"
#include "base/RunnersRegistry.h"
#include "CachePeer.h"
@@ -20,25 +21,23 @@
#include "neighbors.h"
#include "pconn.h"
#include "PeerPoolMgr.h"
+#include "security/BlindPeerConnector.h"
#include "SquidConfig.h"
#include "SquidTime.h"
-#include "ssl/BlindPeerConnector.h"
CBDATA_CLASS_INIT(PeerPoolMgr);
-#if USE_OPENSSL
-/// Gives Ssl::PeerConnector access to Answer in the PeerPoolMgr callback dialer.
+/// Gives Security::PeerConnector access to Answer in the PeerPoolMgr callback dialer.
class MyAnswerDialer: public UnaryMemFunT,
- public Ssl::PeerConnector::CbDialer
+ public Security::PeerConnector::CbDialer
{
public:
MyAnswerDialer(const JobPointer &aJob, Method aMethod):
UnaryMemFunT(aJob, aMethod, Security::EncryptorAnswer()) {}
- /* Ssl::PeerConnector::CbDialer API */
+ /* Security::PeerConnector::CbDialer API */
virtual Security::EncryptorAnswer &answer() { return arg1; }
};
-#endif
PeerPoolMgr::PeerPoolMgr(CachePeer *aPeer): AsyncJob("PeerPoolMgr"),
peer(cbdataReference(aPeer)),
@@ -109,8 +108,7 @@
Must(params.conn != NULL);
-#if USE_OPENSSL
- // Handle SSL peers.
+ // Handle TLS peers.
if (peer->secure.encryptTransport) {
typedef CommCbMemFunT CloserDialer;
closer = JobCallback(48, 3, CloserDialer, this,
@@ -125,12 +123,10 @@
const int timeUsed = squid_curtime - params.conn->startTime();
// Use positive timeout when less than one second is left for conn.
const int timeLeft = max(1, (peerTimeout - timeUsed));
- Ssl::BlindPeerConnector *connector =
- new Ssl::BlindPeerConnector(request, params.conn, securer, NULL, timeLeft);
+ auto *connector = new Security::BlindPeerConnector(request, params.conn, securer, nullptr, timeLeft);
AsyncJob::Start(connector); // will call our callback
return;
}
-#endif
pushNewConnection(params.conn);
}
diff -u -r -N squid-4.0.12/src/PeerPoolMgr.h squid-4.0.13/src/PeerPoolMgr.h
--- squid-4.0.12/src/PeerPoolMgr.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/PeerPoolMgr.h 2016-08-06 00:52:55.000000000 +1200
@@ -51,7 +51,7 @@
/// Comm::ConnOpener calls this when done opening a connection for us
void handleOpenedConnection(const CommConnectCbParams ¶ms);
- /// Ssl::PeerConnector callback
+ /// Security::PeerConnector callback
void handleSecuredPeer(Security::EncryptorAnswer &answer);
/// called when the connection we are trying to secure is closed by a 3rd party
diff -u -r -N squid-4.0.12/src/Pipeline.cc squid-4.0.13/src/Pipeline.cc
--- squid-4.0.12/src/Pipeline.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/Pipeline.cc 2016-08-06 00:52:55.000000000 +1200
@@ -36,6 +36,18 @@
return requests.front();
}
+Http::StreamPointer
+Pipeline::back() const
+{
+ if (requests.empty()) {
+ debugs(33, 3, "Pipeline " << (void*)this << " empty");
+ return Http::StreamPointer();
+ }
+
+ debugs(33, 3, "Pipeline " << (void*)this << " back " << requests.back());
+ return requests.back();
+}
+
void
Pipeline::terminateAll(int xerrno)
{
diff -u -r -N squid-4.0.12/src/Pipeline.h squid-4.0.13/src/Pipeline.h
--- squid-4.0.12/src/Pipeline.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/Pipeline.h 2016-08-06 00:52:55.000000000 +1200
@@ -46,6 +46,9 @@
/// get the first request context in the pipeline
Http::StreamPointer front() const;
+ /// get the last request context in the pipeline
+ Http::StreamPointer back() const;
+
/// how many requests are currently pipelined
size_t count() const {return requests.size();}
diff -u -r -N squid-4.0.12/src/redirect.cc squid-4.0.13/src/redirect.cc
--- squid-4.0.12/src/redirect.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/redirect.cc 2016-08-06 00:52:55.000000000 +1200
@@ -94,25 +94,28 @@
// * trim all but the first word off the response.
// * warn once every 50 responses that this will stop being fixed-up soon.
//
- if (const char * res = reply.other().content()) {
+ if (reply.other().hasContent()) {
+ const char * res = reply.other().content();
+ size_t replySize = 0;
if (const char *t = strchr(res, ' ')) {
static int warn = 0;
debugs(61, (!(warn++%50)? DBG_CRITICAL:2), "UPGRADE WARNING: URL rewriter reponded with garbage '" << t <<
"'. Future Squid will treat this as part of the URL.");
- const mb_size_t garbageLength = reply.other().contentSize() - (t-res);
- reply.modifiableOther().truncate(garbageLength);
- }
- if (reply.other().hasContent() && *res == '\0')
- reply.modifiableOther().clean(); // drop the whole buffer of garbage.
+ replySize = t - res;
+ } else
+ replySize = reply.other().contentSize();
// if we still have anything in other() after all that
// parse it into status=, url= and rewrite-url= keys
- if (reply.other().hasContent()) {
+ if (replySize) {
/* 2012-06-28: This cast is due to urlParse() truncating too-long URLs itself.
* At this point altering the helper buffer in that way is not harmful, but annoying.
* When Bug 1961 is resolved and urlParse has a const API, this needs to die.
*/
- char * result = reply.modifiableOther().content();
+ MemBuf replyBuffer;
+ replyBuffer.init(replySize, replySize);
+ replyBuffer.append(reply.other().content(), reply.other().contentSize());
+ char * result = replyBuffer.content();
Helper::Reply newReply;
// BACKWARD COMPATIBILITY 2012-06-15:
diff -u -r -N squid-4.0.12/src/security/BlindPeerConnector.cc squid-4.0.13/src/security/BlindPeerConnector.cc
--- squid-4.0.12/src/security/BlindPeerConnector.cc 1970-01-01 12:00:00.000000000 +1200
+++ squid-4.0.13/src/security/BlindPeerConnector.cc 2016-08-06 00:52:55.000000000 +1200
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+#include "squid.h"
+#include "CachePeer.h"
+#include "comm/Connection.h"
+#include "fde.h"
+#include "HttpRequest.h"
+#include "neighbors.h"
+#include "security/BlindPeerConnector.h"
+#include "security/NegotiationHistory.h"
+#include "SquidConfig.h"
+
+CBDATA_NAMESPACED_CLASS_INIT(Security, BlindPeerConnector);
+
+Security::ContextPtr
+Security::BlindPeerConnector::getSslContext()
+{
+ if (const CachePeer *peer = serverConnection()->getPeer()) {
+ assert(peer->secure.encryptTransport);
+ Security::ContextPtr sslContext(peer->sslContext);
+ return sslContext;
+ }
+ return ::Config.ssl_client.sslContext;
+}
+
+bool
+Security::BlindPeerConnector::initializeTls(Security::SessionPointer &serverSession)
+{
+ if (!Security::PeerConnector::initializeTls(serverSession))
+ return false;
+
+ if (const CachePeer *peer = serverConnection()->getPeer()) {
+ assert(peer);
+
+ // NP: domain may be a raw-IP but it is now always set
+ assert(!peer->secure.sslDomain.isEmpty());
+
+#if USE_OPENSSL
+ // const loss is okay here, ssl_ex_index_server is only read and not assigned a destructor
+ SBuf *host = new SBuf(peer->secure.sslDomain);
+ SSL_set_ex_data(serverSession.get(), ssl_ex_index_server, host);
+
+ if (peer->sslSession)
+ SSL_set_session(serverSession.get(), peer->sslSession);
+ } else {
+ SBuf *hostName = new SBuf(request->url.host());
+ SSL_set_ex_data(serverSession.get(), ssl_ex_index_server, (void*)hostName);
+#endif
+ }
+ return true;
+}
+
+void
+Security::BlindPeerConnector::noteNegotiationDone(ErrorState *error)
+{
+ if (error) {
+ // XXX: forward.cc calls peerConnectSucceeded() after an OK TCP connect but
+ // we call peerConnectFailed() if SSL failed afterwards. Is that OK?
+ // It is not clear whether we should call peerConnectSucceeded/Failed()
+ // based on TCP results, SSL results, or both. And the code is probably not
+ // consistent in this aspect across tunnelling and forwarding modules.
+ if (CachePeer *p = serverConnection()->getPeer())
+ peerConnectFailed(p);
+ return;
+ }
+
+#if USE_OPENSSL
+ const int fd = serverConnection()->fd;
+ Security::SessionPtr ssl = fd_table[fd].ssl.get();
+ if (serverConnection()->getPeer() && !SSL_session_reused(ssl)) {
+ if (serverConnection()->getPeer()->sslSession)
+ SSL_SESSION_free(serverConnection()->getPeer()->sslSession);
+
+ serverConnection()->getPeer()->sslSession = SSL_get1_session(ssl);
+ }
+#endif
+}
+
diff -u -r -N squid-4.0.12/src/security/BlindPeerConnector.h squid-4.0.13/src/security/BlindPeerConnector.h
--- squid-4.0.12/src/security/BlindPeerConnector.h 1970-01-01 12:00:00.000000000 +1200
+++ squid-4.0.13/src/security/BlindPeerConnector.h 2016-08-06 00:52:55.000000000 +1200
@@ -0,0 +1,50 @@
+/*
+ * 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_SSL_BLINDPEERCONNECTOR_H
+#define SQUID_SRC_SSL_BLINDPEERCONNECTOR_H
+
+#include "security/PeerConnector.h"
+
+namespace Security
+{
+
+/// A simple PeerConnector for SSL/TLS cache_peers. No SslBump capabilities.
+class BlindPeerConnector: public Security::PeerConnector {
+ CBDATA_CLASS(BlindPeerConnector);
+public:
+ BlindPeerConnector(HttpRequestPointer &aRequest,
+ const Comm::ConnectionPointer &aServerConn,
+ AsyncCall::Pointer &aCallback,
+ const AccessLogEntryPointer &alp,
+ const time_t timeout = 0) :
+ AsyncJob("Security::BlindPeerConnector"),
+ Security::PeerConnector(aServerConn, aCallback, alp, timeout)
+ {
+ request = aRequest;
+ }
+
+ /* Security::PeerConnector API */
+
+ /// Calls parent initializeTls(), configure the created TLS session object to
+ /// try reuse TLS session and sets the hostname to use for certificates validation
+ /// \returns true on successful initialization
+ virtual bool initializeTls(Security::SessionPointer &);
+
+ /// Return the configured Security::ContextPtr object
+ virtual Security::ContextPtr getSslContext();
+
+ /// On error calls peerConnectFailed function, on success store the used SSL session
+ /// for later use
+ virtual void noteNegotiationDone(ErrorState *error);
+};
+
+} // namespace Security
+
+#endif /* SQUID_SRC_SSL_BLINDPEERCONNECTOR_H */
+
diff -u -r -N squid-4.0.12/src/security/cert_generators/file/certificate_db.cc squid-4.0.13/src/security/cert_generators/file/certificate_db.cc
--- squid-4.0.12/src/security/cert_generators/file/certificate_db.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/security/cert_generators/file/certificate_db.cc 2016-08-06 00:52:55.000000000 +1200
@@ -7,10 +7,12 @@
*/
#include "squid.h"
+#include "base/HardFun.h"
#include "security/cert_generators/file/certificate_db.h"
#include
#include
+#include
#include
#if HAVE_SYS_STAT_H
#include
@@ -252,7 +254,6 @@
db_full(aDb_path + "/" + db_file),
cert_full(aDb_path + "/" + cert_dir),
size_full(aDb_path + "/" + size_file),
- db(NULL),
max_db_size(aMax_db_size),
fs_block_size((aFs_block_size ? aFs_block_size : 2048)),
dbLock(db_full),
@@ -287,12 +288,16 @@
load();
if (!db || !cert || !pkey)
return false;
+
+ // Functor to wrap xfree() for std::unique_ptr
+ typedef HardFun CharDeleter;
+
Row row;
ASN1_INTEGER * ai = X509_get_serialNumber(cert.get());
std::string serial_string;
Ssl::BIGNUM_Pointer serial(ASN1_INTEGER_to_BN(ai, NULL));
{
- TidyPointer hex_bn(BN_bn2hex(serial.get()));
+ std::unique_ptr hex_bn(BN_bn2hex(serial.get()));
serial_string = std::string(hex_bn.get());
}
row.setValue(cnlSerial, serial_string.c_str());
@@ -305,13 +310,13 @@
}
{
- TidyPointer subject(X509_NAME_oneline(X509_get_subject_name(cert.get()), NULL, 0));
+ std::unique_ptr subject(X509_NAME_oneline(X509_get_subject_name(cert.get()), nullptr, 0));
Security::CertPointer findCert;
Ssl::EVP_PKEY_Pointer findPkey;
if (pure_find(useName.empty() ? subject.get() : useName, findCert, findPkey)) {
// Replace with database certificate
- cert.reset(findCert.release());
- pkey.reset(findPkey.release());
+ cert = std::move(findCert);
+ pkey = std::move(findPkey);
return true;
}
// pure_find may fail because the entry is expired, or because the
@@ -348,7 +353,7 @@
if (!useName.empty())
row.setValue(cnlName, useName.c_str());
else {
- TidyPointer subject(X509_NAME_oneline(X509_get_subject_name(cert.get()), NULL, 0));
+ std::unique_ptr subject(X509_NAME_oneline(X509_get_subject_name(cert.get()), nullptr, 0));
row.setValue(cnlName, subject.get());
}
diff -u -r -N squid-4.0.12/src/security/cert_generators/file/security_file_certgen.cc squid-4.0.13/src/security/cert_generators/file/security_file_certgen.cc
--- squid-4.0.12/src/security/cert_generators/file/security_file_certgen.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/security/cert_generators/file/security_file_certgen.cc 2016-08-06 00:52:55.000000000 +1200
@@ -204,8 +204,8 @@
if (!Ssl::certificateMatchesProperties(cert.get(), certProperties)) {
// The certificate changed (renewed or other reason).
// Generete a new one with the updated fields.
- cert.reset(NULL);
- pkey.reset(NULL);
+ cert.resetWithoutLocking(nullptr);
+ pkey.resetWithoutLocking(nullptr);
db.purgeCert(cert_subject);
}
}
diff -u -r -N squid-4.0.12/src/security/cert_validators/fake/security_fake_certverify.8 squid-4.0.13/src/security/cert_validators/fake/security_fake_certverify.8
--- squid-4.0.12/src/security/cert_validators/fake/security_fake_certverify.8 2016-07-02 02:25:00.000000000 +1200
+++ squid-4.0.13/src/security/cert_validators/fake/security_fake_certverify.8 2016-08-06 02:29:07.000000000 +1200
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SECURITY_FAKE_CERTVERIFY 8"
-.TH SECURITY_FAKE_CERTVERIFY 8 "2016-07-01" "perl v5.22.2" "User Contributed Perl Documentation"
+.TH SECURITY_FAKE_CERTVERIFY 8 "2016-08-05" "perl v5.22.2" "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.12/src/security/forward.h squid-4.0.13/src/security/forward.h
--- squid-4.0.12/src/security/forward.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/security/forward.h 2016-08-06 00:52:55.000000000 +1200
@@ -19,6 +19,16 @@
#endif
#include
+#if USE_OPENSSL
+// Macro to be used to define the C++ wrapper functor of the sk_*_pop_free
+// OpenSSL family of functions. The C++ functor is suffixed with the _free_wrapper
+// extension
+#define sk_dtor_wrapper(sk_object, argument_type, freefunction) \
+ struct sk_object ## _free_wrapper { \
+ void operator()(argument_type a) { sk_object ## _pop_free(a, freefunction); } \
+ }
+#endif /* USE_OPENSSL */
+
/* flags a SSL connection can be configured with */
#define SSL_FLAG_NO_DEFAULT_CA (1<<0)
#define SSL_FLAG_DELAYED_AUTH (1<<1)
@@ -32,10 +42,6 @@
namespace Security
{
-class EncryptorAnswer;
-class PeerOptions;
-class ServerOptions;
-
#if USE_OPENSSL
CtoCpp1(X509_free, X509 *)
typedef Security::LockingPointer CertPointer;
@@ -56,6 +62,8 @@
typedef void *CrlPointer;
#endif
+typedef std::list CertList;
+
typedef std::list CertRevokeList;
#if USE_OPENSSL
@@ -65,7 +73,11 @@
typedef void *DhePointer;
#endif
+class EncryptorAnswer;
class KeyData;
+class PeerConnector;
+class PeerOptions;
+class ServerOptions;
} // namespace Security
diff -u -r -N squid-4.0.12/src/security/Handshake.cc squid-4.0.13/src/security/Handshake.cc
--- squid-4.0.12/src/security/Handshake.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/security/Handshake.cc 2016-08-06 00:52:55.000000000 +1200
@@ -326,6 +326,7 @@
return;
case HandshakeType::hskCertificate:
Must(state < atCertificatesReceived);
+ parseServerCertificates(message.msg_body);
state = atCertificatesReceived;
return;
case HandshakeType::hskServerHelloDone:
@@ -534,13 +535,43 @@
return false; // unreached
}
+void
+Security::HandshakeParser::ParseCertificate(const SBuf &raw, Security::CertPointer &pCert)
+{
#if USE_OPENSSL
+ auto x509Start = reinterpret_cast(raw.rawContent());
+ auto x509Pos = x509Start;
+ X509 *x509 = d2i_X509(nullptr, &x509Pos, raw.length());
+ Must(x509); // successfully parsed
+ Must(x509Pos == x509Start + raw.length()); // no leftovers
+ pCert.resetAndLock(x509);
+#endif
+}
+
+void
+Security::HandshakeParser::parseServerCertificates(const SBuf &raw)
+{
+ Parser::BinaryTokenizer tkList(raw);
+ const SBuf clist = tkList.pstring24("CertificateList");
+ Must(tkList.atEnd()); // no leftovers after all certificates
+
+ Parser::BinaryTokenizer tkItems(clist);
+ while (!tkItems.atEnd()) {
+ Security::CertPointer cert;
+ ParseCertificate(tkItems.pstring24("Certificate"), cert);
+ serverCertificates.push_back(cert);
+ debugs(83, 7, "parsed " << serverCertificates.size() << " certificates so far");
+ }
+
+}
/// A helper function to create a set of all supported TLS extensions
static
Security::Extensions
Security::SupportedExtensions()
{
+#if USE_OPENSSL
+
// optimize lookup speed by reserving the number of values x3, approximately
Security::Extensions extensions(64);
@@ -624,15 +655,9 @@
#endif
return extensions; // might be empty
-}
-
#else
-static
-Security::Extensions
-Security::SupportedExtensions()
-{
return Extensions(); // no extensions are supported without OpenSSL
-}
#endif
+}
diff -u -r -N squid-4.0.12/src/security/Handshake.h squid-4.0.13/src/security/Handshake.h
--- squid-4.0.12/src/security/Handshake.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/security/Handshake.h 2016-08-06 00:52:55.000000000 +1200
@@ -12,6 +12,7 @@
#include "anyp/ProtocolVersion.h"
#include "base/YesNoNone.h"
#include "parser/BinaryTokenizer.h"
+#include "security/forward.h"
#include
@@ -68,6 +69,8 @@
TlsDetails::Pointer details; ///< TLS handshake meta info or nil.
+ Security::CertList serverCertificates; ///< parsed certificates chain
+
ParserState state; ///< current parsing state.
bool resumingSession; ///< True if this is a resuming session
@@ -97,6 +100,9 @@
void parseCiphers(const SBuf &raw);
void parseV23Ciphers(const SBuf &raw);
+ void parseServerCertificates(const SBuf &raw);
+ static void ParseCertificate(const SBuf &raw, CertPointer &cert);
+
unsigned int currentContentType; ///< The current TLS/SSL record content type
const char *done; ///< not nil if we got what we were looking for
diff -u -r -N squid-4.0.12/src/security/LockingPointer.h squid-4.0.13/src/security/LockingPointer.h
--- squid-4.0.12/src/security/LockingPointer.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/security/LockingPointer.h 2016-08-06 00:52:55.000000000 +1200
@@ -9,8 +9,6 @@
#ifndef SQUID_SRC_SECURITY_LOCKINGPOINTER_H
#define SQUID_SRC_SECURITY_LOCKINGPOINTER_H
-#include "base/TidyPointer.h"
-
#if USE_OPENSSL
#if HAVE_OPENSSL_CRYPTO_H
#include
@@ -24,7 +22,7 @@
sk_object ## _pop_free(a, freefunction); \
}
-#endif
+#endif /* USE_OPENSSL */
// Macro to be used to define the C++ equivalent function of an extern "C"
// function. The C++ function suffixed with the _cpp extension
@@ -37,50 +35,117 @@
{
/**
- * Add SSL locking (a.k.a. reference counting) and assignment to TidyPointer
+ * A shared pointer to a reference-counting Object with library-specific
+ * absorption, locking, and unlocking implementations. The API largely
+ * follows std::shared_ptr.
+ *
+ * The constructor and the resetWithoutLocking() method import a raw Object pointer.
+ * Normally, reset() would lock(), but libraries like OpenSSL
+ * pre-lock objects before they are fed to LockingPointer, necessitating
+ * this resetWithoutLocking() customization hook.
*/
-template
-class LockingPointer: public TidyPointer
+template
+class LockingPointer
{
public:
- typedef TidyPointer Parent;
- typedef LockingPointer SelfType;
+ /// a helper label to simplify this objects API definitions below
+ typedef Security::LockingPointer SelfType;
- explicit LockingPointer(T *t = nullptr): Parent(t) {}
+ /**
+ * Construct directly from a raw pointer.
+ * This action requires that the producer of that pointer has already
+ * created one reference lock for the object pointed to.
+ * Our destructor will do the matching unlock.
+ */
+ explicit LockingPointer(T *t = nullptr): raw(nullptr) {
+ // de-optimized for clarity about non-locking
+ resetWithoutLocking(t);
+ }
- explicit LockingPointer(const SelfType &o): Parent() {
+ /// use the custom UnLocker to unlock any value still stored.
+ ~LockingPointer() { unlock(); }
+
+ // copy semantics are okay only when adding a lock reference
+ explicit LockingPointer(const SelfType &o) : raw(nullptr) {
resetAndLock(o.get());
}
-
- SelfType &operator =(const SelfType & o) {
+ const SelfType &operator =(const SelfType &o) {
resetAndLock(o.get());
return *this;
}
-#if __cplusplus >= 201103L
- explicit LockingPointer(LockingPointer &&o): Parent(o.release()) {
+ // move semantics are definitely okay, when possible
+ explicit LockingPointer(SelfType &&) = default;
+ SelfType &operator =(SelfType &&o) {
+ if (o.get() != raw)
+ resetWithoutLocking(o.release());
+ return *this;
}
- LockingPointer &operator =(LockingPointer &&o) {
- if (o.get() != this->get())
- this->reset(o.release());
- return *this;
+ bool operator !() const { return !raw; }
+ explicit operator bool() const { return raw; }
+
+ /// Returns raw and possibly nullptr pointer
+ T *get() const { return raw; }
+
+ /// Reset raw pointer - unlock any previous one and save new one without locking.
+ void resetWithoutLocking(T *t) {
+ unlock();
+ raw = t;
}
-#endif
void resetAndLock(T *t) {
- if (t != this->get()) {
- this->reset(t);
+ if (t != get()) {
+ resetWithoutLocking(t);
+ lock(t);
+ }
+ }
+
+ /// Forget the raw pointer - unlock if any value was set. Become a nil pointer.
+ void reset() { unlock(); }
+
+ /// Forget the raw pointer without unlocking it. Become a nil pointer.
+ T *release() {
+ T *ret = raw;
+ raw = nullptr;
+ return ret;
+ }
+
+private:
+ /// The lock() method increments Object's reference counter.
+ void lock(T *t) {
#if USE_OPENSSL
- if (t)
- CRYPTO_add(&t->references, 1, lock);
+ if (t)
+ CRYPTO_add(&t->references, 1, lockId);
#elif USE_GNUTLS
- // XXX: GnuTLS does not provide locking ?
+ // XXX: GnuTLS does not provide locking ?
#else
- assert(false);
+ assert(false);
#endif
+ }
+
+ /// Become a nil pointer. Decrements any pointed-to Object's reference counter
+ /// using UnLocker which ideally destroys the object when the counter reaches zero.
+ void unlock() {
+ if (raw) {
+ UnLocker(raw);
+ raw = nullptr;
}
}
+
+ /**
+ * Normally, no other code will have this raw pointer.
+ *
+ * However, OpenSSL does some strange and not always consistent things.
+ * OpenSSL library may keep its own internal raw pointers and manage
+ * their reference counts independently, or it may not. This varies between
+ * API functions, though it is usually documented.
+ *
+ * This means the caller code needs to be carefuly written to use the correct
+ * reset method and avoid the raw-pointer constructor unless OpenSSL function
+ * producing the pointer is clearly documented as incrementing a lock for it.
+ */
+ T *raw;
};
} // namespace Security
diff -u -r -N squid-4.0.12/src/security/Makefile.am squid-4.0.13/src/security/Makefile.am
--- squid-4.0.12/src/security/Makefile.am 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/security/Makefile.am 2016-08-06 00:52:55.000000000 +1200
@@ -13,6 +13,8 @@
noinst_LTLIBRARIES = libsecurity.la
libsecurity_la_SOURCES= \
+ BlindPeerConnector.cc \
+ BlindPeerConnector.h \
Context.h \
EncryptorAnswer.cc \
EncryptorAnswer.h \
@@ -23,6 +25,8 @@
LockingPointer.h \
NegotiationHistory.cc \
NegotiationHistory.h \
+ PeerConnector.cc \
+ PeerConnector.h \
PeerOptions.cc \
PeerOptions.h \
ServerOptions.cc \
diff -u -r -N squid-4.0.12/src/security/Makefile.in squid-4.0.13/src/security/Makefile.in
--- squid-4.0.12/src/security/Makefile.in 2016-07-02 01:29:00.000000000 +1200
+++ squid-4.0.13/src/security/Makefile.in 2016-08-06 00:55:12.000000000 +1200
@@ -163,9 +163,9 @@
CONFIG_CLEAN_VPATH_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
libsecurity_la_LIBADD =
-am_libsecurity_la_OBJECTS = EncryptorAnswer.lo Handshake.lo \
- NegotiationHistory.lo PeerOptions.lo ServerOptions.lo \
- Session.lo
+am_libsecurity_la_OBJECTS = BlindPeerConnector.lo EncryptorAnswer.lo \
+ Handshake.lo NegotiationHistory.lo PeerConnector.lo \
+ PeerOptions.lo ServerOptions.lo Session.lo
libsecurity_la_OBJECTS = $(am_libsecurity_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@@ -758,6 +758,8 @@
SUBDIRS = cert_generators cert_validators
noinst_LTLIBRARIES = libsecurity.la
libsecurity_la_SOURCES = \
+ BlindPeerConnector.cc \
+ BlindPeerConnector.h \
Context.h \
EncryptorAnswer.cc \
EncryptorAnswer.h \
@@ -768,6 +770,8 @@
LockingPointer.h \
NegotiationHistory.cc \
NegotiationHistory.h \
+ PeerConnector.cc \
+ PeerConnector.h \
PeerOptions.cc \
PeerOptions.h \
ServerOptions.cc \
@@ -839,9 +843,11 @@
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BlindPeerConnector.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/EncryptorAnswer.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Handshake.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NegotiationHistory.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PeerConnector.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PeerOptions.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ServerOptions.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Session.Plo@am__quote@
diff -u -r -N squid-4.0.12/src/security/PeerConnector.cc squid-4.0.13/src/security/PeerConnector.cc
--- squid-4.0.12/src/security/PeerConnector.cc 1970-01-01 12:00:00.000000000 +1200
+++ squid-4.0.13/src/security/PeerConnector.cc 2016-08-06 00:52:55.000000000 +1200
@@ -0,0 +1,645 @@
+/*
+ * 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.
+ */
+
+/* DEBUG: section 83 TLS Server/Peer negotiation */
+
+#include "squid.h"
+#include "acl/FilledChecklist.h"
+#include "comm/Loops.h"
+#include "Downloader.h"
+#include "errorpage.h"
+#include "fde.h"
+#include "http/Stream.h"
+#include "HttpRequest.h"
+#include "security/NegotiationHistory.h"
+#include "security/PeerConnector.h"
+#include "SquidConfig.h"
+#if USE_OPENSSL
+#include "ssl/bio.h"
+#include "ssl/cert_validate_message.h"
+#include "ssl/Config.h"
+#include "ssl/helper.h"
+#endif
+
+CBDATA_NAMESPACED_CLASS_INIT(Security, PeerConnector);
+
+Security::PeerConnector::PeerConnector(const Comm::ConnectionPointer &aServerConn, AsyncCall::Pointer &aCallback, const AccessLogEntryPointer &alp, const time_t timeout) :
+ AsyncJob("Security::PeerConnector"),
+ serverConn(aServerConn),
+ al(alp),
+ callback(aCallback),
+ negotiationTimeout(timeout),
+ startTime(squid_curtime),
+ useCertValidator_(true),
+ certsDownloads(0)
+{
+ debugs(83, 5, "Security::PeerConnector constructed, this=" << (void*)this);
+ // if this throws, the caller's cb dialer is not our CbDialer
+ Must(dynamic_cast(callback->getDialer()));
+}
+
+Security::PeerConnector::~PeerConnector()
+{
+ debugs(83, 5, "Security::PeerConnector destructed, this=" << (void*)this);
+}
+
+bool Security::PeerConnector::doneAll() const
+{
+ return (!callback || callback->canceled()) && AsyncJob::doneAll();
+}
+
+/// Preps connection and SSL state. Calls negotiate().
+void
+Security::PeerConnector::start()
+{
+ AsyncJob::start();
+
+ Security::SessionPointer tmp;
+ if (prepareSocket() && initializeTls(tmp))
+ negotiateSsl();
+ else
+ mustStop("Security::PeerConnector TLS socket initialize failed");
+}
+
+void
+Security::PeerConnector::commCloseHandler(const CommCloseCbParams ¶ms)
+{
+ debugs(83, 5, "FD " << params.fd << ", Security::PeerConnector=" << params.data);
+ connectionClosed("Security::PeerConnector::commCloseHandler");
+}
+
+void
+Security::PeerConnector::connectionClosed(const char *reason)
+{
+ mustStop(reason);
+ callback = NULL;
+}
+
+bool
+Security::PeerConnector::prepareSocket()
+{
+ const int fd = serverConnection()->fd;
+ if (!Comm::IsConnOpen(serverConn) || fd_table[serverConn->fd].closing()) {
+ connectionClosed("Security::PeerConnector::prepareSocket");
+ return false;
+ }
+
+ // watch for external connection closures
+ typedef CommCbMemFunT Dialer;
+ closeHandler = JobCallback(9, 5, Dialer, this, Security::PeerConnector::commCloseHandler);
+ comm_add_close_handler(fd, closeHandler);
+ return true;
+}
+
+bool
+Security::PeerConnector::initializeTls(Security::SessionPointer &serverSession)
+{
+#if USE_OPENSSL
+ Security::ContextPtr sslContext(getSslContext());
+ assert(sslContext);
+
+ if (!Ssl::CreateClient(sslContext, serverConnection(), "server https start")) {
+ ErrorState *anErr = new ErrorState(ERR_SOCKET_FAILURE, Http::scInternalServerError, request.getRaw());
+ anErr->xerrno = errno;
+ debugs(83, DBG_IMPORTANT, "Error allocating SSL handle: " << ERR_error_string(ERR_get_error(), NULL));
+ noteNegotiationDone(anErr);
+ bail(anErr);
+ return false;
+ }
+
+ // A TLS/SSL session has now been created for the connection and stored in fd_table
+ serverSession = fd_table[serverConnection()->fd].ssl;
+
+ // If CertValidation Helper used do not lookup checklist for errors,
+ // but keep a list of errors to send it to CertValidator
+ if (!Ssl::TheConfig.ssl_crt_validator) {
+ // Create the ACL check list now, while we have access to more info.
+ // The list is used in ssl_verify_cb() and is freed in ssl_free().
+ if (acl_access *acl = ::Config.ssl_client.cert_error) {
+ ACLFilledChecklist *check = new ACLFilledChecklist(acl, request.getRaw(), dash_str);
+ check->al = al;
+ // check->fd(fd); XXX: need client FD here
+ SSL_set_ex_data(serverSession.get(), ssl_ex_index_cert_error_check, check);
+ }
+ }
+
+ return true;
+#else
+ return false;
+#endif
+}
+
+void
+Security::PeerConnector::setReadTimeout()
+{
+ int timeToRead;
+ if (negotiationTimeout) {
+ const int timeUsed = squid_curtime - startTime;
+ const int timeLeft = max(0, static_cast(negotiationTimeout - timeUsed));
+ timeToRead = min(static_cast(::Config.Timeout.read), timeLeft);
+ } else
+ timeToRead = ::Config.Timeout.read;
+ AsyncCall::Pointer nil;
+ commSetConnTimeout(serverConnection(), timeToRead, nil);
+}
+
+void
+Security::PeerConnector::recordNegotiationDetails()
+{
+#if USE_OPENSSL
+ const int fd = serverConnection()->fd;
+ Security::SessionPtr ssl = fd_table[fd].ssl.get();
+
+ // retrieve TLS server negotiated information if any
+ serverConnection()->tlsNegotiations()->retrieveNegotiatedInfo(ssl);
+ // retrieve TLS parsed extra info
+ BIO *b = SSL_get_rbio(ssl);
+ Ssl::ServerBio *bio = static_cast(b->ptr);
+ if (const Security::TlsDetails::Pointer &details = bio->receivedHelloDetails())
+ serverConnection()->tlsNegotiations()->retrieveParsedInfo(details);
+#endif
+}
+
+void
+Security::PeerConnector::negotiateSsl()
+{
+ if (!Comm::IsConnOpen(serverConnection()) || fd_table[serverConnection()->fd].closing())
+ return;
+
+#if USE_OPENSSL
+ const int fd = serverConnection()->fd;
+ Security::SessionPtr ssl = fd_table[fd].ssl.get();
+ const int result = SSL_connect(ssl);
+#else
+ const int result = -1;
+#endif
+ if (result <= 0) {
+ handleNegotiateError(result);
+ return; // we might be gone by now
+ }
+
+ recordNegotiationDetails();
+
+ if (!sslFinalized())
+ return;
+
+ callBack();
+}
+
+bool
+Security::PeerConnector::sslFinalized()
+{
+#if USE_OPENSSL
+ if (Ssl::TheConfig.ssl_crt_validator && useCertValidator_) {
+ const int fd = serverConnection()->fd;
+ Security::SessionPtr ssl = fd_table[fd].ssl.get();
+
+ 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 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));
+ Ssl::CertValidationHelper::GetInstance()->sslSubmit(validationRequest, call);
+ return false;
+ } catch (const std::exception &e) {
+ debugs(83, DBG_IMPORTANT, "ERROR: Failed to compose ssl_crtvd " <<
+ "request for " << validationRequest.domainName <<
+ " certificate: " << e.what() << "; will now block to " <<
+ "validate that certificate.");
+ // fall through to do blocking in-process generation.
+ ErrorState *anErr = new ErrorState(ERR_GATEWAY_FAILURE, Http::scInternalServerError, request.getRaw());
+
+ noteNegotiationDone(anErr);
+ bail(anErr);
+ serverConn->close();
+ return true;
+ }
+ }
+#endif
+
+ noteNegotiationDone(NULL);
+ return true;
+}
+
+#if USE_OPENSSL
+void
+Security::PeerConnector::sslCrtvdHandleReply(Ssl::CertValidationResponse::Pointer validationResponse)
+{
+ Must(validationResponse != NULL);
+
+ Ssl::ErrorDetail *errDetails = NULL;
+ bool validatorFailed = false;
+ if (!Comm::IsConnOpen(serverConnection())) {
+ return;
+ }
+
+ debugs(83,5, request->url.host() << " 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);
+ delete oldErrs;
+ }
+ } else if (validationResponse->resultCode != ::Helper::Okay)
+ validatorFailed = true;
+
+ if (!errDetails && !validatorFailed) {
+ noteNegotiationDone(NULL);
+ callBack();
+ return;
+ }
+
+ ErrorState *anErr = NULL;
+ if (validatorFailed) {
+ anErr = new ErrorState(ERR_GATEWAY_FAILURE, Http::scInternalServerError, request.getRaw());
+ } else {
+ anErr = new ErrorState(ERR_SECURE_CONNECT_FAIL, Http::scServiceUnavailable, request.getRaw());
+ anErr->detail = errDetails;
+ /*anErr->xerrno= Should preserved*/
+ }
+
+ noteNegotiationDone(anErr);
+ bail(anErr);
+ serverConn->close();
+ return;
+}
+#endif
+
+#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 *
+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();
+ 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);
+
+ assert(i->error_no != SSL_ERROR_NONE);
+
+ if (!errDetails) {
+ bool allowed = false;
+ if (check) {
+ check->sslErrors = new Ssl::CertErrors(Ssl::CertError(i->error_no, i->cert.get(), i->error_depth));
+ if (check->fastCheck() == ACCESS_ALLOWED)
+ allowed = true;
+ }
+ // else the Config.ssl_client.cert_error access list is not defined
+ // and the first error will cause the error page
+
+ if (allowed) {
+ debugs(83, 3, "bypassing SSL error " << i->error_no << " in " << "buffer");
+ } else {
+ debugs(83, 5, "confirming SSL error " << i->error_no);
+ X509 *brokenCert = i->cert.get();
+ Security::CertPointer peerCert(SSL_get_peer_certificate(ssl));
+ const char *aReason = i->error_reason.empty() ? NULL : i->error_reason.c_str();
+ errDetails = new Ssl::ErrorDetail(i->error_no, peerCert.get(), brokenCert, aReason);
+ }
+ if (check) {
+ delete check->sslErrors;
+ check->sslErrors = NULL;
+ }
+ }
+
+ if (!errs)
+ errs = new Ssl::CertErrors(Ssl::CertError(i->error_no, i->cert.get(), i->error_depth));
+ else
+ errs->push_back_unique(Ssl::CertError(i->error_no, i->cert.get(), i->error_depth));
+ }
+ if (check)
+ delete check;
+
+ return errs;
+}
+#endif
+
+/// A wrapper for Comm::SetSelect() notifications.
+void
+Security::PeerConnector::NegotiateSsl(int, void *data)
+{
+ PeerConnector *pc = static_cast(data);
+ // Use job calls to add done() checks and other job logic/protections.
+ CallJobHere(83, 7, pc, Security::PeerConnector, negotiateSsl);
+}
+
+void
+Security::PeerConnector::handleNegotiateError(const int ret)
+{
+#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);
+
+ switch (ssl_error) {
+ case SSL_ERROR_WANT_READ:
+ noteWantRead();
+ return;
+
+ case SSL_ERROR_WANT_WRITE:
+ noteWantWrite();
+ return;
+
+ case SSL_ERROR_SSL:
+ case SSL_ERROR_SYSCALL:
+ ssl_lib_error = ERR_get_error();
+ // proceed to the general error handling code
+ break;
+ default:
+ // no special error handling for all other errors
+ break;
+ }
+
+ // Log connection details, if any
+ recordNegotiationDetails();
+ noteSslNegotiationError(ret, ssl_error, ssl_lib_error);
+#endif
+}
+
+void
+Security::PeerConnector::noteWantRead()
+{
+ const int fd = serverConnection()->fd;
+#if USE_OPENSSL
+ Security::SessionPtr ssl = fd_table[fd].ssl.get();
+ BIO *b = SSL_get_rbio(ssl);
+ Ssl::ServerBio *srvBio = static_cast(b->ptr);
+ if (srvBio->holdRead()) {
+ if (srvBio->gotHello()) {
+ if (checkForMissingCertificates())
+ return; // Wait to download certificates before proceed.
+
+ srvBio->holdRead(false);
+ // schedule a negotiateSSl to allow openSSL parse received data
+ Security::PeerConnector::NegotiateSsl(fd, this);
+ return;
+ } else if (srvBio->gotHelloFailed()) {
+ srvBio->holdRead(false);
+ debugs(83, DBG_IMPORTANT, "Error parsing SSL Server Hello Message on FD " << fd);
+ // schedule a negotiateSSl to allow openSSL parse received data
+ Security::PeerConnector::NegotiateSsl(fd, this);
+ return;
+ }
+ }
+#endif
+ setReadTimeout();
+ Comm::SetSelect(fd, COMM_SELECT_READ, &NegotiateSsl, this, 0);
+}
+
+void
+Security::PeerConnector::noteWantWrite()
+{
+ const int fd = serverConnection()->fd;
+ Comm::SetSelect(fd, COMM_SELECT_WRITE, &NegotiateSsl, this, 0);
+ return;
+}
+
+void
+Security::PeerConnector::noteSslNegotiationError(const int ret, const int ssl_error, const int ssl_lib_error)
+{
+#if USE_OPENSSL // not used unless OpenSSL enabled.
+#if defined(EPROTO)
+ int sysErrNo = EPROTO;
+#else
+ int sysErrNo = EACCES;
+#endif
+
+ // store/report errno when ssl_error is SSL_ERROR_SYSCALL, ssl_lib_error is 0, and ret is -1
+ if (ssl_error == SSL_ERROR_SYSCALL && ret == -1 && ssl_lib_error == 0)
+ sysErrNo = errno;
+
+ const int fd = serverConnection()->fd;
+ debugs(83, DBG_IMPORTANT, "Error negotiating SSL on FD " << fd <<
+ ": " << ERR_error_string(ssl_lib_error, NULL) << " (" <<
+ ssl_error << "/" << ret << "/" << errno << ")");
+
+ ErrorState *anErr = NULL;
+ if (request != NULL)
+ anErr = ErrorState::NewForwarding(ERR_SECURE_CONNECT_FAIL, request.getRaw());
+ else
+ anErr = new ErrorState(ERR_SECURE_CONNECT_FAIL, Http::scServiceUnavailable, NULL);
+ anErr->xerrno = sysErrNo;
+
+ Security::SessionPtr ssl = fd_table[fd].ssl.get();
+ Ssl::ErrorDetail *errFromFailure = (Ssl::ErrorDetail *)SSL_get_ex_data(ssl, 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.
+ // Copy errFromFailure to a new Ssl::ErrorDetail object
+ anErr->detail = new Ssl::ErrorDetail(*errFromFailure);
+ } else {
+ // server_cert can be NULL here
+ X509 *server_cert = SSL_get_peer_certificate(ssl);
+ anErr->detail = new Ssl::ErrorDetail(SQUID_ERR_SSL_HANDSHAKE, server_cert, NULL);
+ X509_free(server_cert);
+ }
+
+ if (ssl_lib_error != SSL_ERROR_NONE)
+ anErr->detail->setLibError(ssl_lib_error);
+
+ noteNegotiationDone(anErr);
+ bail(anErr);
+#endif
+}
+
+void
+Security::PeerConnector::bail(ErrorState *error)
+{
+ Must(error); // or the recepient will not know there was a problem
+ Must(callback != NULL);
+ CbDialer *dialer = dynamic_cast(callback->getDialer());
+ Must(dialer);
+ dialer->answer().error = error;
+
+ callBack();
+ // Our job is done. The callabck recepient will probably close the failed
+ // peer connection and try another peer or go direct (if possible). We
+ // can close the connection ourselves (our error notification would reach
+ // the recepient before the fd-closure notification), but we would rather
+ // minimize the number of fd-closure notifications and let the recepient
+ // manage the TCP state of the connection.
+}
+
+void
+Security::PeerConnector::callBack()
+{
+ AsyncCall::Pointer cb = callback;
+ // Do this now so that if we throw below, swanSong() assert that we _tried_
+ // to call back holds.
+ callback = NULL; // this should make done() true
+
+ // remove close handler
+ comm_remove_close_handler(serverConnection()->fd, closeHandler);
+
+ CbDialer *dialer = dynamic_cast(cb->getDialer());
+ Must(dialer);
+ dialer->answer().conn = serverConnection();
+ ScheduleCallHere(cb);
+}
+
+void
+Security::PeerConnector::swanSong()
+{
+ // XXX: unregister fd-closure monitoring and CommSetSelect interest, if any
+ AsyncJob::swanSong();
+ if (callback != NULL) { // paranoid: we have left the caller waiting
+ debugs(83, DBG_IMPORTANT, "BUG: Unexpected state while connecting to a cache_peer or origin server");
+ ErrorState *anErr = new ErrorState(ERR_GATEWAY_FAILURE, Http::scInternalServerError, request.getRaw());
+ bail(anErr);
+ assert(!callback);
+ return;
+ }
+}
+
+const char *
+Security::PeerConnector::status() const
+{
+ static MemBuf buf;
+ buf.reset();
+
+ // TODO: redesign AsyncJob::status() API to avoid this
+ // id and stop reason reporting duplication.
+ buf.append(" [", 2);
+ if (stopReason != NULL) {
+ buf.append("Stopped, reason:", 16);
+ buf.appendf("%s",stopReason);
+ }
+ if (serverConn != NULL)
+ buf.appendf(" FD %d", serverConn->fd);
+ buf.appendf(" %s%u]", id.Prefix, id.value);
+ buf.terminate();
+
+ return buf.content();
+}
+
+#if USE_OPENSSL
+/// CallDialer to allow use Downloader objects within PeerConnector class.
+class PeerConnectorCertDownloaderDialer: public Downloader::CbDialer
+{
+public:
+ typedef void (Security::PeerConnector::*Method)(SBuf &object, int status);
+
+ PeerConnectorCertDownloaderDialer(Method method, Security::PeerConnector *pc):
+ method_(method),
+ peerConnector_(pc) {}
+
+ /* CallDialer API */
+ virtual bool canDial(AsyncCall &call) { return peerConnector_.valid(); }
+ virtual void dial(AsyncCall &call) { ((&(*peerConnector_))->*method_)(object, status); }
+ Method method_; ///< The Security::PeerConnector method to dial
+ CbcPointer peerConnector_; ///< The Security::PeerConnector object
+};
+
+void
+Security::PeerConnector::startCertDownloading(SBuf &url)
+{
+ AsyncCall::Pointer certCallback = asyncCall(81, 4,
+ "Security::PeerConnector::certDownloadingDone",
+ PeerConnectorCertDownloaderDialer(&Security::PeerConnector::certDownloadingDone, this));
+
+ const Downloader *csd = dynamic_cast(request->downloader.valid());
+ Downloader *dl = new Downloader(url, certCallback, csd ? csd->nestedLevel() + 1 : 1);
+ AsyncJob::Start(dl);
+}
+
+void
+Security::PeerConnector::certDownloadingDone(SBuf &obj, int downloadStatus)
+{
+ ++certsDownloads;
+ debugs(81, 5, "Certificate downloading status: " << downloadStatus << " certificate size: " << obj.length());
+
+ // get ServerBio from SSL object
+ const int fd = serverConnection()->fd;
+ Security::SessionPtr ssl = fd_table[fd].ssl.get();
+ BIO *b = SSL_get_rbio(ssl);
+ Ssl::ServerBio *srvBio = static_cast(b->ptr);
+
+ // Parse Certificate. Assume that it is in DER format.
+ // According to RFC 4325:
+ // The server must provide a DER encoded certificate or a collection
+ // collection of certificates in a "certs-only" CMS message.
+ // The applications MUST accept DER encoded certificates and SHOULD
+ // be able to accept collection of certificates.
+ // TODO: support collection of certificates
+ const unsigned char *raw = (const unsigned char*)obj.rawContent();
+ if (X509 *cert = d2i_X509(NULL, &raw, obj.length())) {
+ char buffer[1024];
+ debugs(81, 5, "Retrieved certificate: " << X509_NAME_oneline(X509_get_subject_name(cert), buffer, 1024));
+ const Security::CertList &certsList = srvBio->serverCertificatesIfAny();
+ if (const char *issuerUri = Ssl::uriOfIssuerIfMissing(cert, certsList)) {
+ urlsOfMissingCerts.push(SBuf(issuerUri));
+ }
+ Ssl::SSL_add_untrusted_cert(ssl, cert);
+ }
+
+ // Check if there are URIs to download from and if yes start downloading
+ // the first in queue.
+ if (urlsOfMissingCerts.size() && certsDownloads <= MaxCertsDownloads) {
+ startCertDownloading(urlsOfMissingCerts.front());
+ urlsOfMissingCerts.pop();
+ return;
+ }
+
+ srvBio->holdRead(false);
+ Security::PeerConnector::NegotiateSsl(serverConnection()->fd, this);
+}
+
+bool
+Security::PeerConnector::checkForMissingCertificates()
+{
+ // Check for nested SSL certificates downloads. For example when the
+ // 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();
+ 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);
+ Ssl::ServerBio *srvBio = static_cast(b->ptr);
+ const Security::CertList &certs = srvBio->serverCertificatesIfAny();
+
+ if (certs.size()) {
+ debugs(83, 5, "SSL server sent " << certs.size() << " certificates");
+ Ssl::missingChainCertificatesUrls(urlsOfMissingCerts, certs);
+ if (urlsOfMissingCerts.size()) {
+ startCertDownloading(urlsOfMissingCerts.front());
+ urlsOfMissingCerts.pop();
+ return true;
+ }
+ }
+
+ return false;
+}
+#endif //USE_OPENSSL
+
diff -u -r -N squid-4.0.12/src/security/PeerConnector.h squid-4.0.13/src/security/PeerConnector.h
--- squid-4.0.12/src/security/PeerConnector.h 1970-01-01 12:00:00.000000000 +1200
+++ squid-4.0.13/src/security/PeerConnector.h 2016-08-06 00:52:55.000000000 +1200
@@ -0,0 +1,214 @@
+/*
+ * 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_SSL_PEERCONNECTOR_H
+#define SQUID_SRC_SSL_PEERCONNECTOR_H
+
+#include "acl/Acl.h"
+#include "base/AsyncCbdataCalls.h"
+#include "base/AsyncJob.h"
+#include "CommCalls.h"
+#include "security/EncryptorAnswer.h"
+#include "security/forward.h"
+#if USE_OPENSSL
+#include "ssl/support.h"
+#endif
+
+#include
+#include
+
+class HttpRequest;
+class ErrorState;
+class AccessLogEntry;
+typedef RefCount AccessLogEntryPointer;
+
+namespace Security
+{
+
+/**
+ * Connects Squid to SSL/TLS-capable peers or services.
+ * Contains common code and interfaces of various specialized PeerConnectors,
+ * including peer certificate validation code.
+ \par
+ * The caller receives a call back with Security::EncryptorAnswer. If answer.error
+ * is not nil, then there was an error and the SSL connection to the SSL peer
+ * was not fully established. The error object is suitable for error response
+ * generation.
+ \par
+ * The caller must monitor the connection for closure because this
+ * job will not inform the caller about such events.
+ \par
+ * PeerConnector class curently supports a form of SSL negotiation timeout,
+ * which accounted only when sets the read timeout from SSL peer.
+ * For a complete solution, the caller must monitor the overall connection
+ * establishment timeout and close the connection on timeouts. This is probably
+ * better than having dedicated (or none at all!) timeouts for peer selection,
+ * DNS lookup, TCP handshake, SSL handshake, etc. Some steps may have their
+ * own timeout, but not all steps should be forced to have theirs.
+ * XXX: tunnel.cc and probably other subsystems does not have an "overall
+ * connection establishment" timeout. We need to change their code so that they
+ * start monitoring earlier and close on timeouts. This change may need to be
+ * discussed on squid-dev.
+ \par
+ * This job never closes the connection, even on errors. If a 3rd-party
+ * closes the connection, this job simply quits without informing the caller.
+ */
+class PeerConnector: virtual public AsyncJob
+{
+ CBDATA_CLASS(PeerConnector);
+
+public:
+ /// Callback dialier API to allow PeerConnector to set the answer.
+ class CbDialer
+ {
+ public:
+ virtual ~CbDialer() {}
+ /// gives PeerConnector access to the in-dialer answer
+ virtual Security::EncryptorAnswer &answer() = 0;
+ };
+
+ typedef RefCount HttpRequestPointer;
+
+public:
+ PeerConnector(const Comm::ConnectionPointer &aServerConn,
+ AsyncCall::Pointer &aCallback,
+ const AccessLogEntryPointer &alp,
+ const time_t timeout = 0);
+ virtual ~PeerConnector();
+
+protected:
+ // AsyncJob API
+ virtual void start();
+ virtual bool doneAll() const;
+ virtual void swanSong();
+ virtual const char *status() const;
+
+ /// The comm_close callback handler.
+ void commCloseHandler(const CommCloseCbParams ¶ms);
+
+ /// Inform us that the connection is closed. Does the required clean-up.
+ void connectionClosed(const char *reason);
+
+ /// Sets up TCP socket-related notification callbacks if things go wrong.
+ /// If socket already closed return false, else install the comm_close
+ /// handler to monitor the socket.
+ bool prepareSocket();
+
+ /// Sets the read timeout to avoid getting stuck while reading from a
+ /// silent server
+ void setReadTimeout();
+
+ /// \returns true on successful TLS session initialization
+ virtual bool initializeTls(Security::SessionPointer &);
+
+ /// Performs a single secure connection negotiation step.
+ /// It is called multiple times untill the negotiation finish or aborted.
+ void negotiateSsl();
+
+ /// Called after SSL negotiations have finished. Cleans up SSL state.
+ /// Returns false if we are now waiting for the certs validation job.
+ /// Otherwise, returns true, regardless of negotiation success/failure.
+ bool sslFinalized();
+
+ /// Called when the SSL negotiation step aborted because data needs to
+ /// be transferred to/from SSL server or on error. In the first case
+ /// setups the appropriate Comm::SetSelect handler. In second case
+ /// fill an error and report to the PeerConnector caller.
+ void handleNegotiateError(const int result);
+
+ /// Called when the openSSL SSL_connect fnction request more data from
+ /// the remote SSL server. Sets the read timeout and sets the
+ /// Squid COMM_SELECT_READ handler.
+ void noteWantRead();
+
+#if USE_OPENSSL
+ /// Run the certificates list sent by the SSL server and check if there
+ /// are missing certificates. Adds to the urlOfMissingCerts list the
+ /// URLS of missing certificates if this information provided by the
+ /// issued certificates with Authority Info Access extension.
+ bool checkForMissingCertificates();
+
+ /// Start downloading procedure for the given URL.
+ void startCertDownloading(SBuf &url);
+
+ /// Called by Downloader after a certificate object downloaded.
+ void certDownloadingDone(SBuf &object, int status);
+#endif
+
+ /// Called when the openSSL SSL_connect function needs to write data to
+ /// the remote SSL server. Sets the Squid COMM_SELECT_WRITE handler.
+ virtual void noteWantWrite();
+
+ /// Called when the SSL_connect function aborts with an SSL negotiation error
+ /// \param result the SSL_connect return code
+ /// \param ssl_error the error code returned from the SSL_get_error function
+ /// \param ssl_lib_error the error returned from the ERR_Get_Error function
+ virtual void noteSslNegotiationError(const int result, const int ssl_error, const int ssl_lib_error);
+
+ /// Called when the SSL negotiation to the server completed and the certificates
+ /// validated using the cert validator.
+ /// \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
+ /// for building the SSL objects.
+ virtual Security::ContextPtr getSslContext() = 0;
+
+ /// mimics FwdState to minimize changes to FwdState::initiate/negotiateSsl
+ Comm::ConnectionPointer const &serverConnection() const { return serverConn; }
+
+ void bail(ErrorState *error); ///< Return an error to the PeerConnector caller
+
+ /// Callback the caller class, and pass the ready to communicate secure
+ /// connection or an error if PeerConnector failed.
+ void callBack();
+
+ /// If called the certificates validator will not used
+ void bypassCertValidator() {useCertValidator_ = false;}
+
+ /// Called after negotiation finishes to record connection details for
+ /// logging
+ void recordNegotiationDetails();
+
+ HttpRequestPointer request; ///< peer connection trigger or cause
+ Comm::ConnectionPointer serverConn; ///< TCP connection to the peer
+ AccessLogEntryPointer al; ///< info for the future access.log entry
+ AsyncCall::Pointer callback; ///< we call this with the results
+private:
+ PeerConnector(const PeerConnector &); // not implemented
+ PeerConnector &operator =(const PeerConnector &); // not implemented
+
+#if USE_OPENSSL
+ /// Process response from cert validator helper
+ 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 *&);
+#endif
+
+ /// A wrapper function for negotiateSsl for use with Comm::SetSelect
+ static void NegotiateSsl(int fd, void *data);
+
+ /// The maximum allowed missing certificates downloads.
+ static const unsigned int MaxCertsDownloads = 10;
+ /// The maximum allowed nested certificates downloads.
+ static const unsigned int MaxNestedDownloads = 3;
+
+ AsyncCall::Pointer closeHandler; ///< we call this when the connection closed
+ time_t negotiationTimeout; ///< the SSL connection timeout to use
+ time_t startTime; ///< when the peer connector negotiation started
+ bool useCertValidator_; ///< whether the certificate validator should bypassed
+ /// The list of URLs where missing certificates should be downloaded.
+ std::queue urlsOfMissingCerts;
+ unsigned int certsDownloads; ///< the number of downloaded missing certificates
+};
+
+} // namespace Security
+
+#endif /* SQUID_SRC_SSL_PEERCONNECTOR_H */
+
diff -u -r -N squid-4.0.12/src/security/ServerOptions.cc squid-4.0.13/src/security/ServerOptions.cc
--- squid-4.0.12/src/security/ServerOptions.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/security/ServerOptions.cc 2016-08-06 00:52:55.000000000 +1200
@@ -117,19 +117,21 @@
return t;
}
-Security::ContextPtr
+bool
Security::ServerOptions::createStaticServerContext(AnyP::PortCfg &port)
{
updateTlsVersionLimits();
- Security::ContextPtr t = createBlankContext();
+ Security::ContextPointer t(createBlankContext());
if (t) {
#if USE_OPENSSL
- Ssl::InitServerContext(t, port);
+ if (!Ssl::InitServerContext(t, port))
+ return false;
#endif
}
- return t;
+ staticContext = std::move(t);
+ return bool(staticContext);
}
void
@@ -159,7 +161,7 @@
}
}
- parsedDhParams.reset(dhp);
+ parsedDhParams.resetWithoutLocking(dhp);
#endif
}
diff -u -r -N squid-4.0.12/src/security/ServerOptions.h squid-4.0.13/src/security/ServerOptions.h
--- squid-4.0.12/src/security/ServerOptions.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/security/ServerOptions.h 2016-08-06 00:52:55.000000000 +1200
@@ -33,7 +33,9 @@
virtual void dumpCfg(Packable *, const char *pfx) const;
/// generate a security server-context from these configured options
- Security::ContextPtr createStaticServerContext(AnyP::PortCfg &);
+ /// the resulting context is stored in staticContext
+ /// \returns true if a context could be created
+ bool createStaticServerContext(AnyP::PortCfg &);
/// update the context with DH, EDH, EECDH settings
void updateContextEecdh(Security::ContextPtr &);
diff -u -r -N squid-4.0.12/src/security/Session.cc squid-4.0.13/src/security/Session.cc
--- squid-4.0.12/src/security/Session.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/security/Session.cc 2016-08-06 00:52:55.000000000 +1200
@@ -16,45 +16,6 @@
#define SSL_SESSION_ID_SIZE 32
#define SSL_SESSION_MAX_SIZE 10*1024
-bool
-Security::SessionIsResumed(const Security::SessionPointer &s)
-{
- return
-#if USE_OPENSSL
- SSL_session_reused(s.get()) == 1;
-#elif USE_GNUTLS
- gnutls_session_is_resumed(s.get()) != 0;
-#else
- false;
-#endif
-}
-
-void
-Security::GetSessionResumeData(const Security::SessionPointer &s, Security::SessionStatePointer &data)
-{
- if (!SessionIsResumed(s)) {
-#if USE_OPENSSL
- data.reset(SSL_get1_session(s.get()));
-#elif USE_GNUTLS
- gnutls_datum_t *tmp = nullptr;
- (void)gnutls_session_get_data2(s.get(), tmp);
- data.reset(tmp);
-#endif
- }
-}
-
-void
-Security::SetSessionResumeData(const Security::SessionPtr &s, const Security::SessionStatePointer &data)
-{
- if (s) {
-#if USE_OPENSSL
- (void)SSL_set_session(s, data.get());
-#elif USE_GNUTLS
- (void)gnutls_session_set_data(s, data->data, data->size);
-#endif
- }
-}
-
static bool
isTlsServer()
{
diff -u -r -N squid-4.0.12/src/security/Session.h squid-4.0.13/src/security/Session.h
--- squid-4.0.12/src/security/Session.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/security/Session.h 2016-08-06 00:52:55.000000000 +1200
@@ -9,9 +9,10 @@
#ifndef SQUID_SRC_SECURITY_SESSION_H
#define SQUID_SRC_SECURITY_SESSION_H
-// LockingPointer.h instead of TidyPointer.h for CtoCpp1()
#include "security/LockingPointer.h"
+#include
+
#if USE_OPENSSL
#if HAVE_OPENSSL_SSL_H
#include
@@ -31,41 +32,22 @@
CtoCpp1(SSL_free, SSL *);
typedef LockingPointer SessionPointer;
-typedef SSL_SESSION* SessionStatePtr;
-CtoCpp1(SSL_SESSION_free, SSL_SESSION *);
-typedef LockingPointer SessionStatePointer;
-
#elif USE_GNUTLS
typedef gnutls_session_t SessionPtr;
-CtoCpp1(gnutls_deinit, gnutls_session_t);
-// TODO: Convert to Locking pointer.
// Locks can be implemented attaching locks counter to gnutls_session_t
// objects using the gnutls_session_set_ptr()/gnutls_session_get_ptr ()
// library functions
-typedef TidyPointer SessionPointer;
-
-typedef gnutls_datum_t *SessionStatePtr;
-CtoCpp1(gnutls_free, gnutls_datum_t *);
-typedef TidyPointer SessionStatePointer;
+CtoCpp1(gnutls_deinit, gnutls_session_t);
+typedef LockingPointer SessionPointer;
#else
// use void* so we can check against NULL
typedef void* SessionPtr;
-typedef TidyPointer SessionPointer;
-typedef TidyPointer SessionStatePointer;
+CtoCpp1(xfree, SessionPtr);
+typedef LockingPointer SessionPointer;
#endif
-/// whether the session is a resumed one
-bool SessionIsResumed(const Security::SessionPointer &);
-
-/// Retrieve the data needed to resume this session on a later connection
-void GetSessionResumeData(const Security::SessionPointer &, Security::SessionStatePointer &);
-
-/// Set the data for resuming a previous session.
-/// Needs to be done before using the SessionPointer for a handshake.
-void SetSessionResumeData(const Security::SessionPtr &, const Security::SessionStatePointer &);
-
} // namespace Security
#endif /* SQUID_SRC_SECURITY_SESSION_H */
diff -u -r -N squid-4.0.12/src/servers/FtpServer.cc squid-4.0.13/src/servers/FtpServer.cc
--- squid-4.0.12/src/servers/FtpServer.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/servers/FtpServer.cc 2016-08-06 00:52:55.000000000 +1200
@@ -759,11 +759,15 @@
Http::Stream *const result =
new Http::Stream(clientConnection, http);
+ StoreIOBuffer tempBuffer;
+ tempBuffer.data = result->reqbuf;
+ tempBuffer.length = HTTP_REQBUF_SZ;
+
ClientStreamData newServer = new clientReplyContext(http);
ClientStreamData newClient = result;
clientStreamInit(&http->client_stream, clientGetMoreData, clientReplyDetach,
clientReplyStatus, newServer, clientSocketRecipient,
- clientSocketDetach, newClient, result->getClientStreamBuffer());
+ clientSocketDetach, newClient, tempBuffer);
result->flags.parsed_ok = 1;
return result;
diff -u -r -N squid-4.0.12/src/servers/Server.cc squid-4.0.13/src/servers/Server.cc
--- squid-4.0.12/src/servers/Server.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/servers/Server.cc 2016-08-06 00:52:55.000000000 +1200
@@ -167,6 +167,7 @@
// case Comm::COMM_ERROR:
default: // no other flags should ever occur
debugs(33, 2, io.conn << ": got flag " << rd.flag << "; " << xstrerr(rd.xerrno));
+ checkLogging();
pipeline.terminateAll(rd.xerrno);
io.conn->close();
return;
diff -u -r -N squid-4.0.12/src/servers/Server.h squid-4.0.13/src/servers/Server.h
--- squid-4.0.12/src/servers/Server.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/servers/Server.h 2016-08-06 00:52:55.000000000 +1200
@@ -117,6 +117,9 @@
void doClientRead(const CommIoCbParams &io);
void clientWriteDone(const CommIoCbParams &io);
+ /// Log the current [attempt at] transaction if nobody else will.
+ virtual void checkLogging() = 0;
+
AsyncCall::Pointer reader; ///< set when we are reading
AsyncCall::Pointer writer; ///< set when we are writing
};
diff -u -r -N squid-4.0.12/src/ssl/bio.cc squid-4.0.13/src/ssl/bio.cc
--- squid-4.0.12/src/ssl/bio.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/ssl/bio.cc 2016-08-06 00:52:55.000000000 +1200
@@ -203,8 +203,10 @@
allowSplice(false),
allowBump(false),
holdWrite_(false),
+ holdRead_(true),
record_(false),
parsedHandshake(false),
+ parseError(false),
bumpMode_(bumpNone),
rbufConsumePos(0)
{
@@ -271,6 +273,13 @@
catch (const std::exception &ex) {
debugs(83, 2, "parsing error on FD " << fd_ << ": " << ex.what());
parsedHandshake = true; // done parsing (due to an error)
+ parseError = true;
+ }
+
+ if (holdRead_) {
+ debugs(83, 7, "Hold flag is set, retry latter. (Hold " << size << "bytes)");
+ BIO_set_retry_read(table);
+ return -1;
}
return giveBuffered(buf, size);
diff -u -r -N squid-4.0.12/src/ssl/bio.h squid-4.0.13/src/ssl/bio.h
--- squid-4.0.12/src/ssl/bio.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/ssl/bio.h 2016-08-06 00:52:55.000000000 +1200
@@ -138,6 +138,10 @@
bool holdWrite() const {return holdWrite_;}
/// Enables or disables the write hold state
void holdWrite(bool h) {holdWrite_ = h;}
+ /// The read hold state
+ bool holdRead() const {return holdRead_;}
+ /// Enables or disables the read hold state
+ void holdRead(bool h) {holdRead_ = h;}
/// Enables or disables the input data recording, for internal analysis.
void recordInput(bool r) {record_ = r;}
/// Whether we can splice or not the SSL stream
@@ -148,6 +152,15 @@
void mode(Ssl::BumpMode m) {bumpMode_ = m;}
Ssl::BumpMode bumpMode() {return bumpMode_;} ///< return the bumping mode
+ /// \retval true if the Server hello message received
+ bool gotHello() const { return (parsedHandshake && !parseError); }
+
+ /// Return true if the Server Hello parsing failed
+ bool gotHelloFailed() const { return (parsedHandshake && parseError); }
+
+ /// \return the server certificates list if received and parsed correctly
+ const Security::CertList &serverCertificatesIfAny() { return parser_.serverCertificates; }
+
/// \return the TLS Details advertised by TLS server.
const Security::TlsDetails::Pointer &receivedHelloDetails() const {return parser_.details;}
@@ -167,8 +180,10 @@
bool allowSplice; ///< True if the SSL stream can be spliced
bool allowBump; ///< True if the SSL stream can be bumped
bool holdWrite_; ///< The write hold state of the bio.
+ bool holdRead_; ///< The read hold state of the bio.
bool record_; ///< If true the input data recorded to rbuf for internal use
bool parsedHandshake; ///< whether we are done parsing TLS Hello
+ bool parseError; ///< error while parsing server hello message
Ssl::BumpMode bumpMode_;
/// The size of data stored in rbuf which passed to the openSSL
diff -u -r -N squid-4.0.12/src/ssl/BlindPeerConnector.cc squid-4.0.13/src/ssl/BlindPeerConnector.cc
--- squid-4.0.12/src/ssl/BlindPeerConnector.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/ssl/BlindPeerConnector.cc 1970-01-01 12:00:00.000000000 +1200
@@ -1,77 +0,0 @@
-/*
- * 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.
- */
-
-#include "squid.h"
-#include "CachePeer.h"
-#include "comm/Connection.h"
-#include "fde.h"
-#include "HttpRequest.h"
-#include "neighbors.h"
-#include "security/NegotiationHistory.h"
-#include "SquidConfig.h"
-#include "ssl/BlindPeerConnector.h"
-
-CBDATA_NAMESPACED_CLASS_INIT(Ssl, BlindPeerConnector);
-
-Security::ContextPtr
-Ssl::BlindPeerConnector::getSslContext()
-{
- if (const CachePeer *peer = serverConnection()->getPeer()) {
- assert(peer->secure.encryptTransport);
- Security::ContextPtr sslContext(peer->sslContext);
- return sslContext;
- }
- return ::Config.ssl_client.sslContext;
-}
-
-Security::SessionPtr
-Ssl::BlindPeerConnector::initializeSsl()
-{
- auto ssl = Ssl::PeerConnector::initializeSsl();
- if (!ssl)
- return nullptr;
-
- if (const CachePeer *peer = serverConnection()->getPeer()) {
- assert(peer);
-
- // NP: domain may be a raw-IP but it is now always set
- assert(!peer->secure.sslDomain.isEmpty());
-
- // const loss is okay here, ssl_ex_index_server is only read and not assigned a destructor
- SBuf *host = new SBuf(peer->secure.sslDomain);
- SSL_set_ex_data(ssl, ssl_ex_index_server, host);
-
- Security::SetSessionResumeData(ssl, peer->sslSession);
- } else {
- SBuf *hostName = new SBuf(request->url.host());
- SSL_set_ex_data(ssl, ssl_ex_index_server, (void*)hostName);
- }
-
- return ssl;
-}
-
-void
-Ssl::BlindPeerConnector::noteNegotiationDone(ErrorState *error)
-{
- if (error) {
- // XXX: forward.cc calls peerConnectSucceeded() after an OK TCP connect but
- // we call peerConnectFailed() if SSL failed afterwards. Is that OK?
- // It is not clear whether we should call peerConnectSucceeded/Failed()
- // based on TCP results, SSL results, or both. And the code is probably not
- // consistent in this aspect across tunnelling and forwarding modules.
- if (CachePeer *p = serverConnection()->getPeer())
- peerConnectFailed(p);
- return;
- }
-
- if (auto *peer = serverConnection()->getPeer()) {
- const int fd = serverConnection()->fd;
- Security::GetSessionResumeData(fd_table[fd].ssl, peer->sslSession);
- }
-}
-
diff -u -r -N squid-4.0.12/src/ssl/BlindPeerConnector.h squid-4.0.13/src/ssl/BlindPeerConnector.h
--- squid-4.0.12/src/ssl/BlindPeerConnector.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/ssl/BlindPeerConnector.h 1970-01-01 12:00:00.000000000 +1200
@@ -1,52 +0,0 @@
-/*
- * 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_SSL_BLINDPEERCONNECTOR_H
-#define SQUID_SRC_SSL_BLINDPEERCONNECTOR_H
-
-#include "ssl/PeerConnector.h"
-
-#if USE_OPENSSL
-
-namespace Ssl
-{
-
-/// A simple PeerConnector for SSL/TLS cache_peers. No SslBump capabilities.
-class BlindPeerConnector: public PeerConnector {
- CBDATA_CLASS(BlindPeerConnector);
-public:
- BlindPeerConnector(HttpRequestPointer &aRequest,
- const Comm::ConnectionPointer &aServerConn,
- AsyncCall::Pointer &aCallback,
- const AccessLogEntryPointer &alp,
- const time_t timeout = 0) :
- AsyncJob("Ssl::BlindPeerConnector"),
- PeerConnector(aServerConn, aCallback, alp, timeout)
- {
- request = aRequest;
- }
-
- /* PeerConnector API */
-
- /// Calls parent initializeSSL, configure the created SSL object to try reuse SSL session
- /// and sets the hostname to use for certificates validation
- virtual Security::SessionPtr initializeSsl();
-
- /// Return the configured Security::ContextPtr object
- virtual Security::ContextPtr getSslContext();
-
- /// On error calls peerConnectFailed function, on success store the used SSL session
- /// for later use
- virtual void noteNegotiationDone(ErrorState *error);
-};
-
-} // namespace Ssl
-
-#endif /* USE_OPENSSL */
-#endif /* SQUID_SRC_SSL_BLINDPEERCONNECTOR_H */
-
diff -u -r -N squid-4.0.12/src/ssl/gadgets.cc squid-4.0.13/src/ssl/gadgets.cc
--- squid-4.0.12/src/ssl/gadgets.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/ssl/gadgets.cc 2016-08-06 00:52:55.000000000 +1200
@@ -130,12 +130,12 @@
BIO_puts(bio.get(), bufferToRead);
X509 * certPtr = NULL;
- cert.reset(PEM_read_bio_X509(bio.get(), &certPtr, 0, 0));
+ cert.resetWithoutLocking(PEM_read_bio_X509(bio.get(), &certPtr, 0, 0));
if (!cert)
return false;
EVP_PKEY * pkeyPtr = NULL;
- pkey.reset(PEM_read_bio_PrivateKey(bio.get(), &pkeyPtr, 0, 0));
+ pkey.resetWithoutLocking(PEM_read_bio_PrivateKey(bio.get(), &pkeyPtr, 0, 0));
if (!pkey)
return false;
@@ -148,7 +148,7 @@
BIO_puts(bio.get(), bufferToRead);
X509 * certPtr = NULL;
- cert.reset(PEM_read_bio_X509(bio.get(), &certPtr, 0, 0));
+ cert.resetWithoutLocking(PEM_read_bio_X509(bio.get(), &certPtr, 0, 0));
if (!cert)
return false;
@@ -511,7 +511,7 @@
if (properties.signWithPkey.get())
pkey.resetAndLock(properties.signWithPkey.get());
else // if not exist generate one
- pkey.reset(Ssl::createSslPrivateKey());
+ pkey.resetWithoutLocking(Ssl::createSslPrivateKey());
if (!pkey)
return false;
@@ -550,8 +550,8 @@
if (!ret)
return false;
- certToStore.reset(cert.release());
- pkeyToStore.reset(pkey.release());
+ certToStore = std::move(cert);
+ pkeyToStore = std::move(pkey);
return true;
}
@@ -676,11 +676,11 @@
{
if (keyFilename == NULL)
keyFilename = certFilename;
- pkey.reset(readSslPrivateKey(keyFilename));
- cert.reset(readSslX509Certificate(certFilename));
+ pkey.resetWithoutLocking(readSslPrivateKey(keyFilename));
+ cert.resetWithoutLocking(readSslX509Certificate(certFilename));
if (!pkey || !cert || !X509_check_private_key(cert.get(), pkey.get())) {
- pkey.reset(NULL);
- cert.reset(NULL);
+ pkey.reset();
+ cert.reset();
}
}
diff -u -r -N squid-4.0.12/src/ssl/gadgets.h squid-4.0.13/src/ssl/gadgets.h
--- squid-4.0.12/src/ssl/gadgets.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/ssl/gadgets.h 2016-08-06 00:52:55.000000000 +1200
@@ -9,6 +9,7 @@
#ifndef SQUID_SSL_GADGETS_H
#define SQUID_SSL_GADGETS_H
+#include "base/HardFun.h"
#include "security/forward.h"
#include "ssl/crtd_message.h"
@@ -39,53 +40,41 @@
#endif
/**
- \ingroup SslCrtdSslAPI
- * TidyPointer typedefs for common SSL objects
+ * std::unique_ptr typedefs for common SSL objects
*/
-sk_free_wrapper(sk_X509, STACK_OF(X509) *, X509_free)
-typedef TidyPointer X509_STACK_Pointer;
+sk_dtor_wrapper(sk_X509, STACK_OF(X509) *, X509_free);
+typedef std::unique_ptr X509_STACK_Pointer;
CtoCpp1(EVP_PKEY_free, EVP_PKEY *)
typedef Security::LockingPointer EVP_PKEY_Pointer;
-CtoCpp1(BN_free, BIGNUM *)
-typedef TidyPointer BIGNUM_Pointer;
+typedef std::unique_ptr> BIGNUM_Pointer;
-CtoCpp1(BIO_free, BIO *)
-typedef TidyPointer BIO_Pointer;
+typedef std::unique_ptr> BIO_Pointer;
-CtoCpp1(ASN1_INTEGER_free, ASN1_INTEGER *)
-typedef TidyPointer ASN1_INT_Pointer;
+typedef std::unique_ptr> ASN1_INT_Pointer;
-CtoCpp1(ASN1_OCTET_STRING_free, ASN1_OCTET_STRING *)
-typedef TidyPointer ASN1_OCTET_STRING_Pointer;
+typedef std::unique_ptr> ASN1_OCTET_STRING_Pointer;
-CtoCpp1(TXT_DB_free, TXT_DB *)
-typedef TidyPointer TXT_DB_Pointer;
+typedef std::unique_ptr> TXT_DB_Pointer;
-CtoCpp1(X509_NAME_free, X509_NAME *)
-typedef TidyPointer X509_NAME_Pointer;
+typedef std::unique_ptr> X509_NAME_Pointer;
-CtoCpp1(RSA_free, RSA *)
-typedef TidyPointer RSA_Pointer;
+typedef std::unique_ptr> RSA_Pointer;
-CtoCpp1(X509_REQ_free, X509_REQ *)
-typedef TidyPointer X509_REQ_Pointer;
+typedef std::unique_ptr> X509_REQ_Pointer;
-sk_free_wrapper(sk_X509_NAME, STACK_OF(X509_NAME) *, X509_NAME_free)
-typedef TidyPointer X509_NAME_STACK_Pointer;
+sk_dtor_wrapper(sk_X509_NAME, STACK_OF(X509_NAME) *, X509_NAME_free);
+typedef std::unique_ptr X509_NAME_STACK_Pointer;
-CtoCpp1(AUTHORITY_KEYID_free, AUTHORITY_KEYID *)
-typedef TidyPointer AUTHORITY_KEYID_Pointer;
+typedef std::unique_ptr> AUTHORITY_KEYID_Pointer;
-sk_free_wrapper(sk_GENERAL_NAME, STACK_OF(GENERAL_NAME) *, GENERAL_NAME_free)
-typedef TidyPointer GENERAL_NAME_STACK_Pointer;
+sk_dtor_wrapper(sk_GENERAL_NAME, STACK_OF(GENERAL_NAME) *, GENERAL_NAME_free);
+typedef std::unique_ptr GENERAL_NAME_STACK_Pointer;
-CtoCpp1(GENERAL_NAME_free, GENERAL_NAME *)
-typedef TidyPointer GENERAL_NAME_Pointer;
+typedef std::unique_ptr> GENERAL_NAME_Pointer;
-CtoCpp1(X509_EXTENSION_free, X509_EXTENSION *)
-typedef TidyPointer X509_EXTENSION_Pointer;
+typedef std::unique_ptr> X509_EXTENSION_Pointer;
/**
\ingroup SslCrtdSslAPI
diff -u -r -N squid-4.0.12/src/ssl/helper.cc squid-4.0.13/src/ssl/helper.cc
--- squid-4.0.12/src/ssl/helper.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/ssl/helper.cc 2016-08-06 00:52:55.000000000 +1200
@@ -85,8 +85,7 @@
std::string msg = message.compose();
msg += '\n';
if (!ssl_crtd->trySubmit(msg.c_str(), callback, data)) {
- ::Helper::Reply failReply;
- failReply.result = ::Helper::BrokenHelper;
+ ::Helper::Reply failReply(::Helper::BrokenHelper);
failReply.notes.add("message", "error 45 Temporary network problem, please retry later");
callback(data, failReply);
return;
@@ -198,6 +197,9 @@
if (reply.result == ::Helper::BrokenHelper) {
debugs(83, DBG_IMPORTANT, "\"ssl_crtvd\" helper error response: " << reply.other().content());
validationResponse->resultCode = ::Helper::BrokenHelper;
+ } else if (!reply.other().hasContent()) {
+ debugs(83, DBG_IMPORTANT, "\"ssl_crtvd\" helper returned NULL response");
+ validationResponse->resultCode = ::Helper::BrokenHelper;
} else if (replyMsg.parse(reply.other().content(), reply.other().contentSize()) != Ssl::CrtdMessage::OK ||
!replyMsg.parseResponse(*validationResponse, peerCerts, error) ) {
debugs(83, DBG_IMPORTANT, "WARNING: Reply from ssl_crtvd for " << " is incorrect");
diff -u -r -N squid-4.0.12/src/ssl/helper.h squid-4.0.13/src/ssl/helper.h
--- squid-4.0.12/src/ssl/helper.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/ssl/helper.h 2016-08-06 00:52:55.000000000 +1200
@@ -9,9 +9,12 @@
#ifndef SQUID_SSL_HELPER_H
#define SQUID_SSL_HELPER_H
+#if USE_OPENSSL
+
#include "base/AsyncJobCalls.h"
#include "base/LruMap.h"
#include "helper/forward.h"
+#include "security/forward.h"
#include "ssl/cert_validate_message.h"
#include "ssl/crtd_message.h"
@@ -39,13 +42,12 @@
};
#endif
-class PeerConnector;
class CertValidationRequest;
class CertValidationResponse;
class CertValidationHelper
{
public:
- typedef UnaryMemFunT CbDialer;
+ typedef UnaryMemFunT CbDialer;
typedef void CVHCB(void *, Ssl::CertValidationResponse const &);
static CertValidationHelper * GetInstance(); ///< Instance class.
@@ -64,5 +66,7 @@
};
} //namespace Ssl
+
+#endif /* USE_OPENSSL */
#endif // SQUID_SSL_HELPER_H
diff -u -r -N squid-4.0.12/src/ssl/Makefile.am squid-4.0.13/src/ssl/Makefile.am
--- squid-4.0.12/src/ssl/Makefile.am 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/ssl/Makefile.am 2016-08-06 00:52:55.000000000 +1200
@@ -14,8 +14,6 @@
libsslsquid_la_SOURCES = \
bio.cc \
bio.h \
- BlindPeerConnector.cc \
- BlindPeerConnector.h \
cert_validate_message.cc \
cert_validate_message.h \
context_storage.cc \
@@ -28,8 +26,6 @@
ErrorDetailManager.h \
PeekingPeerConnector.cc \
PeekingPeerConnector.h \
- PeerConnector.cc \
- PeerConnector.h \
ProxyCerts.h \
ServerBump.cc \
ServerBump.h \
diff -u -r -N squid-4.0.12/src/ssl/Makefile.in squid-4.0.13/src/ssl/Makefile.in
--- squid-4.0.12/src/ssl/Makefile.in 2016-07-02 01:29:03.000000000 +1200
+++ squid-4.0.13/src/ssl/Makefile.in 2016-08-06 00:55:14.000000000 +1200
@@ -163,10 +163,10 @@
CONFIG_CLEAN_VPATH_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
libsslsquid_la_LIBADD =
-am_libsslsquid_la_OBJECTS = bio.lo BlindPeerConnector.lo \
- cert_validate_message.lo context_storage.lo Config.lo \
- ErrorDetail.lo ErrorDetailManager.lo PeekingPeerConnector.lo \
- PeerConnector.lo ServerBump.lo support.lo helper.lo
+am_libsslsquid_la_OBJECTS = bio.lo cert_validate_message.lo \
+ context_storage.lo Config.lo ErrorDetail.lo \
+ ErrorDetailManager.lo PeekingPeerConnector.lo ServerBump.lo \
+ support.lo helper.lo
libsslsquid_la_OBJECTS = $(am_libsslsquid_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@@ -722,8 +722,6 @@
libsslsquid_la_SOURCES = \
bio.cc \
bio.h \
- BlindPeerConnector.cc \
- BlindPeerConnector.h \
cert_validate_message.cc \
cert_validate_message.h \
context_storage.cc \
@@ -736,8 +734,6 @@
ErrorDetailManager.h \
PeekingPeerConnector.cc \
PeekingPeerConnector.h \
- PeerConnector.cc \
- PeerConnector.h \
ProxyCerts.h \
ServerBump.cc \
ServerBump.h \
@@ -819,12 +815,10 @@
distclean-compile:
-rm -f *.tab.c
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BlindPeerConnector.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Config.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ErrorDetail.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ErrorDetailManager.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PeekingPeerConnector.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PeerConnector.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ServerBump.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bio.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cert_validate_message.Plo@am__quote@
diff -u -r -N squid-4.0.12/src/ssl/PeekingPeerConnector.cc squid-4.0.13/src/ssl/PeekingPeerConnector.cc
--- squid-4.0.12/src/ssl/PeekingPeerConnector.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/ssl/PeekingPeerConnector.cc 2016-08-06 00:52:55.000000000 +1200
@@ -97,7 +97,7 @@
srvBio->holdWrite(false);
srvBio->recordInput(false);
debugs(83,5, "Retry the fwdNegotiateSSL on FD " << serverConn->fd);
- Ssl::PeerConnector::noteWantWrite();
+ Security::PeerConnector::noteWantWrite();
} else {
splice = true;
// Ssl Negotiation stops here. Last SSL checks for valid certificates
@@ -133,12 +133,11 @@
return ::Config.ssl_client.sslContext;
}
-Security::SessionPtr
-Ssl::PeekingPeerConnector::initializeSsl()
+bool
+Ssl::PeekingPeerConnector::initializeTls(Security::SessionPointer &serverSession)
{
- auto ssl = Ssl::PeerConnector::initializeSsl();
- if (!ssl)
- return nullptr;
+ if (!Security::PeerConnector::initializeTls(serverSession))
+ return false;
if (ConnStateData *csd = request->clientConnectionManager.valid()) {
@@ -147,8 +146,8 @@
assert(clientConn != NULL);
SBuf *hostName = NULL;
- //Enable Status_request tls extension, required to bump some clients
- SSL_set_tlsext_status_type(ssl, TLSEXT_STATUSTYPE_ocsp);
+ //Enable Status_request TLS extension, required to bump some clients
+ SSL_set_tlsext_status_type(serverSession.get(), TLSEXT_STATUSTYPE_ocsp);
const Security::TlsDetails::Pointer details = csd->tlsParser.details;
if (details && !details->serverName.isEmpty())
@@ -164,20 +163,20 @@
}
if (hostName)
- SSL_set_ex_data(ssl, ssl_ex_index_server, (void*)hostName);
+ SSL_set_ex_data(serverSession.get(), ssl_ex_index_server, (void*)hostName);
Must(!csd->serverBump() || csd->serverBump()->step <= Ssl::bumpStep2);
if (csd->sslBumpMode == Ssl::bumpPeek || csd->sslBumpMode == Ssl::bumpStare) {
- auto clientSsl = fd_table[clientConn->fd].ssl.get();
- Must(clientSsl);
- BIO *bc = SSL_get_rbio(clientSsl);
+ auto clientSession = fd_table[clientConn->fd].ssl.get();
+ Must(clientSession);
+ BIO *bc = SSL_get_rbio(clientSession);
Ssl::ClientBio *cltBio = static_cast(bc->ptr);
Must(cltBio);
if (details && details->tlsVersion.protocol != AnyP::PROTO_NONE) {
- applyTlsDetailsToSSL(ssl, details, csd->sslBumpMode);
+ applyTlsDetailsToSSL(serverSession.get(), details, csd->sslBumpMode);
// Should we allow it for all protocols?
if (details->tlsVersion.protocol == AnyP::PROTO_TLS || details->tlsVersion == AnyP::ProtocolVersion(AnyP::PROTO_SSL, 3, 0)) {
- BIO *b = SSL_get_rbio(ssl);
+ BIO *b = SSL_get_rbio(serverSession.get());
Ssl::ServerBio *srvBio = static_cast(b->ptr);
// Inherite client features, like SSL version, SNI and other
srvBio->setClientFeatures(details, cltBio->rBufData());
@@ -187,7 +186,7 @@
}
} else {
// Set client SSL options
- SSL_set_options(ssl, ::Security::ProxyOutgoingConfig.parsedOptions);
+ SSL_set_options(serverSession.get(), ::Security::ProxyOutgoingConfig.parsedOptions);
// Use SNI TLS extension only when we connect directly
// to the origin server and we know the server host name.
@@ -199,20 +198,20 @@
sniServer = hostName->c_str();
if (sniServer)
- Ssl::setClientSNI(ssl, sniServer);
+ Ssl::setClientSNI(serverSession.get(), sniServer);
}
if (Ssl::ServerBump *serverBump = csd->serverBump()) {
- serverBump->attachServerSSL(ssl);
+ serverBump->attachServerSSL(serverSession.get());
// store peeked cert to check SQUID_X509_V_ERR_CERT_CHANGE
if (X509 *peeked_cert = serverBump->serverCert.get()) {
CRYPTO_add(&(peeked_cert->references),1,CRYPTO_LOCK_X509);
- SSL_set_ex_data(ssl, ssl_ex_index_ssl_peeked_cert, peeked_cert);
+ SSL_set_ex_data(serverSession.get(), ssl_ex_index_ssl_peeked_cert, peeked_cert);
}
}
}
- return ssl;
+ return true;
}
void
@@ -274,7 +273,7 @@
return;
}
- Ssl::PeerConnector::noteWantWrite();
+ Security::PeerConnector::noteWantWrite();
}
void
@@ -319,7 +318,7 @@
}
// else call parent noteNegotiationError to produce an error page
- Ssl::PeerConnector::noteSslNegotiationError(result, ssl_error, ssl_lib_error);
+ Security::PeerConnector::noteSslNegotiationError(result, ssl_error, ssl_lib_error);
}
void
@@ -339,7 +338,7 @@
// remember the server certificate for later use
if (Ssl::ServerBump *serverBump = csd->serverBump()) {
- serverBump->serverCert.reset(serverCert.release());
+ serverBump->serverCert = std::move(serverCert);
}
}
}
@@ -354,7 +353,7 @@
else {
const int fd = serverConnection()->fd;
Security::SessionPtr ssl = fd_table[fd].ssl.get();
- serverCert.reset(SSL_get_peer_certificate(ssl));
+ serverCert.resetWithoutLocking(SSL_get_peer_certificate(ssl));
}
if (serverCert.get()) {
csd->resetSslCommonName(Ssl::CommonHostName(serverCert.get()));
diff -u -r -N squid-4.0.12/src/ssl/PeekingPeerConnector.h squid-4.0.13/src/ssl/PeekingPeerConnector.h
--- squid-4.0.12/src/ssl/PeekingPeerConnector.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/ssl/PeekingPeerConnector.h 2016-08-06 00:52:55.000000000 +1200
@@ -9,7 +9,7 @@
#ifndef SQUID_SRC_SSL_PEEKINGPEERCONNECTOR_H
#define SQUID_SRC_SSL_PEEKINGPEERCONNECTOR_H
-#include "ssl/PeerConnector.h"
+#include "security/PeerConnector.h"
#if USE_OPENSSL
@@ -17,7 +17,7 @@
{
/// A PeerConnector for HTTP origin servers. Capable of SslBumping.
-class PeekingPeerConnector: public PeerConnector {
+class PeekingPeerConnector: public Security::PeerConnector {
CBDATA_CLASS(PeekingPeerConnector);
public:
PeekingPeerConnector(HttpRequestPointer &aRequest,
@@ -27,7 +27,7 @@
const AccessLogEntryPointer &alp,
const time_t timeout = 0) :
AsyncJob("Ssl::PeekingPeerConnector"),
- PeerConnector(aServerConn, aCallback, alp, timeout),
+ Security::PeerConnector(aServerConn, aCallback, alp, timeout),
clientConn(aClientConn),
splice(false),
resumingSession(false),
@@ -36,8 +36,8 @@
request = aRequest;
}
- /* PeerConnector API */
- virtual Security::SessionPtr initializeSsl();
+ /* Security::PeerConnector API */
+ virtual bool initializeTls(Security::SessionPointer &);
virtual Security::ContextPtr getSslContext();
virtual void noteWantWrite();
virtual void noteSslNegotiationError(const int result, const int ssl_error, const int ssl_lib_error);
diff -u -r -N squid-4.0.12/src/ssl/PeerConnector.cc squid-4.0.13/src/ssl/PeerConnector.cc
--- squid-4.0.12/src/ssl/PeerConnector.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/ssl/PeerConnector.cc 1970-01-01 12:00:00.000000000 +1200
@@ -1,491 +0,0 @@
-/*
- * 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.
- */
-
-/* DEBUG: section 83 TLS Server/Peer negotiation */
-
-#include "squid.h"
-#include "acl/FilledChecklist.h"
-#include "comm/Loops.h"
-#include "errorpage.h"
-#include "fde.h"
-#include "HttpRequest.h"
-#include "security/NegotiationHistory.h"
-#include "SquidConfig.h"
-#include "ssl/bio.h"
-#include "ssl/cert_validate_message.h"
-#include "ssl/Config.h"
-#include "ssl/helper.h"
-#include "ssl/PeerConnector.h"
-
-CBDATA_NAMESPACED_CLASS_INIT(Ssl, PeerConnector);
-
-Ssl::PeerConnector::PeerConnector(const Comm::ConnectionPointer &aServerConn, AsyncCall::Pointer &aCallback, const AccessLogEntryPointer &alp, const time_t timeout) :
- AsyncJob("Ssl::PeerConnector"),
- serverConn(aServerConn),
- al(alp),
- callback(aCallback),
- negotiationTimeout(timeout),
- startTime(squid_curtime),
- useCertValidator_(true)
-{
- // if this throws, the caller's cb dialer is not our CbDialer
- Must(dynamic_cast(callback->getDialer()));
-}
-
-Ssl::PeerConnector::~PeerConnector()
-{
- debugs(83, 5, "Peer connector " << this << " gone");
-}
-
-bool Ssl::PeerConnector::doneAll() const
-{
- return (!callback || callback->canceled()) && AsyncJob::doneAll();
-}
-
-/// Preps connection and SSL state. Calls negotiate().
-void
-Ssl::PeerConnector::start()
-{
- AsyncJob::start();
-
- if (prepareSocket() && initializeSsl())
- negotiateSsl();
-}
-
-void
-Ssl::PeerConnector::commCloseHandler(const CommCloseCbParams ¶ms)
-{
- debugs(83, 5, "FD " << params.fd << ", Ssl::PeerConnector=" << params.data);
- connectionClosed("Ssl::PeerConnector::commCloseHandler");
-}
-
-void
-Ssl::PeerConnector::connectionClosed(const char *reason)
-{
- mustStop(reason);
- callback = NULL;
-}
-
-bool
-Ssl::PeerConnector::prepareSocket()
-{
- const int fd = serverConnection()->fd;
- if (!Comm::IsConnOpen(serverConn) || fd_table[serverConn->fd].closing()) {
- connectionClosed("Ssl::PeerConnector::prepareSocket");
- return false;
- }
-
- // watch for external connection closures
- typedef CommCbMemFunT Dialer;
- closeHandler = JobCallback(9, 5, Dialer, this, Ssl::PeerConnector::commCloseHandler);
- comm_add_close_handler(fd, closeHandler);
- return true;
-}
-
-Security::SessionPtr
-Ssl::PeerConnector::initializeSsl()
-{
- Security::ContextPtr sslContext(getSslContext());
- assert(sslContext);
-
- const int fd = serverConnection()->fd;
-
- auto ssl = Ssl::CreateClient(sslContext, fd, "server https start");
- if (!ssl) {
- ErrorState *anErr = new ErrorState(ERR_SOCKET_FAILURE, Http::scInternalServerError, request.getRaw());
- anErr->xerrno = errno;
- debugs(83, DBG_IMPORTANT, "Error allocating SSL handle: " << ERR_error_string(ERR_get_error(), NULL));
-
- noteNegotiationDone(anErr);
- bail(anErr);
- return nullptr;
- }
-
- // If CertValidation Helper used do not lookup checklist for errors,
- // but keep a list of errors to send it to CertValidator
- if (!Ssl::TheConfig.ssl_crt_validator) {
- // Create the ACL check list now, while we have access to more info.
- // The list is used in ssl_verify_cb() and is freed in ssl_free().
- if (acl_access *acl = ::Config.ssl_client.cert_error) {
- ACLFilledChecklist *check = new ACLFilledChecklist(acl, request.getRaw(), dash_str);
- check->al = al;
- // check->fd(fd); XXX: need client FD here
- SSL_set_ex_data(ssl, ssl_ex_index_cert_error_check, check);
- }
- }
- return ssl;
-}
-
-void
-Ssl::PeerConnector::setReadTimeout()
-{
- int timeToRead;
- if (negotiationTimeout) {
- const int timeUsed = squid_curtime - startTime;
- const int timeLeft = max(0, static_cast(negotiationTimeout - timeUsed));
- timeToRead = min(static_cast(::Config.Timeout.read), timeLeft);
- } else
- timeToRead = ::Config.Timeout.read;
- AsyncCall::Pointer nil;
- commSetConnTimeout(serverConnection(), timeToRead, nil);
-}
-
-void
-Ssl::PeerConnector::recordNegotiationDetails()
-{
- const int fd = serverConnection()->fd;
- Security::SessionPtr ssl = fd_table[fd].ssl.get();
-
- // retrieve TLS server negotiated information if any
- serverConnection()->tlsNegotiations()->retrieveNegotiatedInfo(ssl);
- // retrieve TLS parsed extra info
- BIO *b = SSL_get_rbio(ssl);
- Ssl::ServerBio *bio = static_cast(b->ptr);
- if (const Security::TlsDetails::Pointer &details = bio->receivedHelloDetails())
- serverConnection()->tlsNegotiations()->retrieveParsedInfo(details);
-}
-
-void
-Ssl::PeerConnector::negotiateSsl()
-{
- if (!Comm::IsConnOpen(serverConnection()) || fd_table[serverConnection()->fd].closing())
- return;
-
- const int fd = serverConnection()->fd;
- Security::SessionPtr ssl = fd_table[fd].ssl.get();
- const int result = SSL_connect(ssl);
- if (result <= 0) {
- handleNegotiateError(result);
- return; // we might be gone by now
- }
-
- recordNegotiationDetails();
-
- if (!sslFinalized())
- return;
-
- callBack();
-}
-
-bool
-Ssl::PeerConnector::sslFinalized()
-{
- if (Ssl::TheConfig.ssl_crt_validator && useCertValidator_) {
- const int fd = serverConnection()->fd;
- Security::SessionPtr ssl = fd_table[fd].ssl.get();
-
- 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 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, "Ssl::PeerConnector::sslCrtvdHandleReply", Ssl::CertValidationHelper::CbDialer(this, &Ssl::PeerConnector::sslCrtvdHandleReply, nullptr));
- Ssl::CertValidationHelper::GetInstance()->sslSubmit(validationRequest, call);
- return false;
- } catch (const std::exception &e) {
- debugs(83, DBG_IMPORTANT, "ERROR: Failed to compose ssl_crtvd " <<
- "request for " << validationRequest.domainName <<
- " certificate: " << e.what() << "; will now block to " <<
- "validate that certificate.");
- // fall through to do blocking in-process generation.
- ErrorState *anErr = new ErrorState(ERR_GATEWAY_FAILURE, Http::scInternalServerError, request.getRaw());
-
- noteNegotiationDone(anErr);
- bail(anErr);
- serverConn->close();
- return true;
- }
- }
-
- noteNegotiationDone(NULL);
- return true;
-}
-
-void
-Ssl::PeerConnector::sslCrtvdHandleReply(Ssl::CertValidationResponse::Pointer validationResponse)
-{
- Must(validationResponse != NULL);
-
- Ssl::ErrorDetail *errDetails = NULL;
- bool validatorFailed = false;
- if (!Comm::IsConnOpen(serverConnection())) {
- return;
- }
-
- debugs(83,5, request->url.host() << " 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);
- delete oldErrs;
- }
- } else if (validationResponse->resultCode != ::Helper::Okay)
- validatorFailed = true;
-
- if (!errDetails && !validatorFailed) {
- noteNegotiationDone(NULL);
- callBack();
- return;
- }
-
- ErrorState *anErr = NULL;
- if (validatorFailed) {
- anErr = new ErrorState(ERR_GATEWAY_FAILURE, Http::scInternalServerError, request.getRaw());
- } else {
- anErr = new ErrorState(ERR_SECURE_CONNECT_FAIL, Http::scServiceUnavailable, request.getRaw());
- anErr->detail = errDetails;
- /*anErr->xerrno= Should preserved*/
- }
-
- noteNegotiationDone(anErr);
- bail(anErr);
- serverConn->close();
- return;
-}
-
-/// 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 *
-Ssl::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();
- 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);
-
- assert(i->error_no != SSL_ERROR_NONE);
-
- if (!errDetails) {
- bool allowed = false;
- if (check) {
- check->sslErrors = new Ssl::CertErrors(Ssl::CertError(i->error_no, i->cert.get(), i->error_depth));
- if (check->fastCheck() == ACCESS_ALLOWED)
- allowed = true;
- }
- // else the Config.ssl_client.cert_error access list is not defined
- // and the first error will cause the error page
-
- if (allowed) {
- debugs(83, 3, "bypassing SSL error " << i->error_no << " in " << "buffer");
- } else {
- debugs(83, 5, "confirming SSL error " << i->error_no);
- X509 *brokenCert = i->cert.get();
- Security::CertPointer peerCert(SSL_get_peer_certificate(ssl));
- const char *aReason = i->error_reason.empty() ? NULL : i->error_reason.c_str();
- errDetails = new Ssl::ErrorDetail(i->error_no, peerCert.get(), brokenCert, aReason);
- }
- if (check) {
- delete check->sslErrors;
- check->sslErrors = NULL;
- }
- }
-
- if (!errs)
- errs = new Ssl::CertErrors(Ssl::CertError(i->error_no, i->cert.get(), i->error_depth));
- else
- errs->push_back_unique(Ssl::CertError(i->error_no, i->cert.get(), i->error_depth));
- }
- if (check)
- delete check;
-
- return errs;
-}
-
-/// A wrapper for Comm::SetSelect() notifications.
-void
-Ssl::PeerConnector::NegotiateSsl(int, void *data)
-{
- PeerConnector *pc = static_cast(data);
- // Use job calls to add done() checks and other job logic/protections.
- CallJobHere(83, 7, pc, Ssl::PeerConnector, negotiateSsl);
-}
-
-void
-Ssl::PeerConnector::handleNegotiateError(const int ret)
-{
- 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);
-
- switch (ssl_error) {
- case SSL_ERROR_WANT_READ:
- noteWantRead();
- return;
-
- case SSL_ERROR_WANT_WRITE:
- noteWantWrite();
- return;
-
- case SSL_ERROR_SSL:
- case SSL_ERROR_SYSCALL:
- ssl_lib_error = ERR_get_error();
- // proceed to the general error handling code
- break;
- default:
- // no special error handling for all other errors
- break;
- }
-
- // Log connection details, if any
- recordNegotiationDetails();
- noteSslNegotiationError(ret, ssl_error, ssl_lib_error);
-}
-
-void
-Ssl::PeerConnector::noteWantRead()
-{
- setReadTimeout();
- const int fd = serverConnection()->fd;
- Comm::SetSelect(fd, COMM_SELECT_READ, &NegotiateSsl, this, 0);
-}
-
-void
-Ssl::PeerConnector::noteWantWrite()
-{
- const int fd = serverConnection()->fd;
- Comm::SetSelect(fd, COMM_SELECT_WRITE, &NegotiateSsl, this, 0);
- return;
-}
-
-void
-Ssl::PeerConnector::noteSslNegotiationError(const int ret, const int ssl_error, const int ssl_lib_error)
-{
-#ifdef EPROTO
- int sysErrNo = EPROTO;
-#else
- int sysErrNo = EACCES;
-#endif
-
- // store/report errno when ssl_error is SSL_ERROR_SYSCALL, ssl_lib_error is 0, and ret is -1
- if (ssl_error == SSL_ERROR_SYSCALL && ret == -1 && ssl_lib_error == 0)
- sysErrNo = errno;
-
- const int fd = serverConnection()->fd;
- debugs(83, DBG_IMPORTANT, "Error negotiating SSL on FD " << fd <<
- ": " << ERR_error_string(ssl_lib_error, NULL) << " (" <<
- ssl_error << "/" << ret << "/" << errno << ")");
-
- ErrorState *anErr = NULL;
- if (request != NULL)
- anErr = ErrorState::NewForwarding(ERR_SECURE_CONNECT_FAIL, request.getRaw());
- else
- anErr = new ErrorState(ERR_SECURE_CONNECT_FAIL, Http::scServiceUnavailable, NULL);
- anErr->xerrno = sysErrNo;
-
- Security::SessionPtr ssl = fd_table[fd].ssl.get();
- Ssl::ErrorDetail *errFromFailure = (Ssl::ErrorDetail *)SSL_get_ex_data(ssl, 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.
- // Copy errFromFailure to a new Ssl::ErrorDetail object
- anErr->detail = new Ssl::ErrorDetail(*errFromFailure);
- } else {
- // server_cert can be NULL here
- X509 *server_cert = SSL_get_peer_certificate(ssl);
- anErr->detail = new Ssl::ErrorDetail(SQUID_ERR_SSL_HANDSHAKE, server_cert, NULL);
- X509_free(server_cert);
- }
-
- if (ssl_lib_error != SSL_ERROR_NONE)
- anErr->detail->setLibError(ssl_lib_error);
-
- noteNegotiationDone(anErr);
- bail(anErr);
-}
-
-void
-Ssl::PeerConnector::bail(ErrorState *error)
-{
- Must(error); // or the recepient will not know there was a problem
- Must(callback != NULL);
- CbDialer *dialer = dynamic_cast(callback->getDialer());
- Must(dialer);
- dialer->answer().error = error;
-
- callBack();
- // Our job is done. The callabck recepient will probably close the failed
- // peer connection and try another peer or go direct (if possible). We
- // can close the connection ourselves (our error notification would reach
- // the recepient before the fd-closure notification), but we would rather
- // minimize the number of fd-closure notifications and let the recepient
- // manage the TCP state of the connection.
-}
-
-void
-Ssl::PeerConnector::callBack()
-{
- AsyncCall::Pointer cb = callback;
- // Do this now so that if we throw below, swanSong() assert that we _tried_
- // to call back holds.
- callback = NULL; // this should make done() true
-
- // remove close handler
- comm_remove_close_handler(serverConnection()->fd, closeHandler);
-
- CbDialer *dialer = dynamic_cast(cb->getDialer());
- Must(dialer);
- dialer->answer().conn = serverConnection();
- ScheduleCallHere(cb);
-}
-
-void
-Ssl::PeerConnector::swanSong()
-{
- // XXX: unregister fd-closure monitoring and CommSetSelect interest, if any
- AsyncJob::swanSong();
- if (callback != NULL) { // paranoid: we have left the caller waiting
- debugs(83, DBG_IMPORTANT, "BUG: Unexpected state while connecting to a cache_peer or origin server");
- ErrorState *anErr = new ErrorState(ERR_GATEWAY_FAILURE, Http::scInternalServerError, request.getRaw());
- bail(anErr);
- assert(!callback);
- return;
- }
-}
-
-const char *
-Ssl::PeerConnector::status() const
-{
- static MemBuf buf;
- buf.reset();
-
- // TODO: redesign AsyncJob::status() API to avoid this
- // id and stop reason reporting duplication.
- buf.append(" [", 2);
- if (stopReason != NULL) {
- buf.append("Stopped, reason:", 16);
- buf.appendf("%s",stopReason);
- }
- if (serverConn != NULL)
- buf.appendf(" FD %d", serverConn->fd);
- buf.appendf(" %s%u]", id.Prefix, id.value);
- buf.terminate();
-
- return buf.content();
-}
-
diff -u -r -N squid-4.0.12/src/ssl/PeerConnector.h squid-4.0.13/src/ssl/PeerConnector.h
--- squid-4.0.12/src/ssl/PeerConnector.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/ssl/PeerConnector.h 1970-01-01 12:00:00.000000000 +1200
@@ -1,188 +0,0 @@
-/*
- * 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_SSL_PEERCONNECTOR_H
-#define SQUID_SRC_SSL_PEERCONNECTOR_H
-
-#include "acl/Acl.h"
-#include "base/AsyncCbdataCalls.h"
-#include "base/AsyncJob.h"
-#include "CommCalls.h"
-#include "security/EncryptorAnswer.h"
-#include "ssl/support.h"
-
-#include
-
-#if USE_OPENSSL
-
-class HttpRequest;
-class ErrorState;
-class AccessLogEntry;
-typedef RefCount AccessLogEntryPointer;
-
-namespace Ssl
-{
-
-/**
- \par
- * Connects Squid to SSL/TLS-capable peers or services.
- * Contains common code and interfaces of various specialized PeerConnectors,
- * including peer certificate validation code.
- \par
- * The caller receives a call back with Security::EncryptorAnswer. If answer.error
- * is not nil, then there was an error and the SSL connection to the SSL peer
- * was not fully established. The error object is suitable for error response
- * generation.
- \par
- * The caller must monitor the connection for closure because this
- * job will not inform the caller about such events.
- \par
- * PeerConnector class curently supports a form of SSL negotiation timeout,
- * which accounted only when sets the read timeout from SSL peer.
- * For a complete solution, the caller must monitor the overall connection
- * establishment timeout and close the connection on timeouts. This is probably
- * better than having dedicated (or none at all!) timeouts for peer selection,
- * DNS lookup, TCP handshake, SSL handshake, etc. Some steps may have their
- * own timeout, but not all steps should be forced to have theirs.
- * XXX: tunnel.cc and probably other subsystems does not have an "overall
- * connection establishment" timeout. We need to change their code so that they
- * start monitoring earlier and close on timeouts. This change may need to be
- * discussed on squid-dev.
- \par
- * This job never closes the connection, even on errors. If a 3rd-party
- * closes the connection, this job simply quits without informing the caller.
- */
-class PeerConnector: virtual public AsyncJob
-{
- CBDATA_CLASS(PeerConnector);
-
-public:
- /// Callback dialier API to allow PeerConnector to set the answer.
- class CbDialer
- {
- public:
- virtual ~CbDialer() {}
- /// gives PeerConnector access to the in-dialer answer
- virtual Security::EncryptorAnswer &answer() = 0;
- };
-
- typedef RefCount HttpRequestPointer;
-
-public:
- PeerConnector(const Comm::ConnectionPointer &aServerConn,
- AsyncCall::Pointer &aCallback,
- const AccessLogEntryPointer &alp,
- const time_t timeout = 0);
- virtual ~PeerConnector();
-
-protected:
- // AsyncJob API
- virtual void start();
- virtual bool doneAll() const;
- virtual void swanSong();
- virtual const char *status() const;
-
- /// The comm_close callback handler.
- void commCloseHandler(const CommCloseCbParams ¶ms);
-
- /// Inform us that the connection is closed. Does the required clean-up.
- void connectionClosed(const char *reason);
-
- /// Sets up TCP socket-related notification callbacks if things go wrong.
- /// If socket already closed return false, else install the comm_close
- /// handler to monitor the socket.
- bool prepareSocket();
-
- /// Sets the read timeout to avoid getting stuck while reading from a
- /// silent server
- void setReadTimeout();
-
- virtual Security::SessionPtr initializeSsl(); ///< Initializes SSL state
-
- /// Performs a single secure connection negotiation step.
- /// It is called multiple times untill the negotiation finish or aborted.
- void negotiateSsl();
-
- /// Called after SSL negotiations have finished. Cleans up SSL state.
- /// Returns false if we are now waiting for the certs validation job.
- /// Otherwise, returns true, regardless of negotiation success/failure.
- bool sslFinalized();
-
- /// Called when the SSL negotiation step aborted because data needs to
- /// be transferred to/from SSL server or on error. In the first case
- /// setups the appropriate Comm::SetSelect handler. In second case
- /// fill an error and report to the PeerConnector caller.
- void handleNegotiateError(const int result);
-
- /// Called when the openSSL SSL_connect fnction request more data from
- /// the remote SSL server. Sets the read timeout and sets the
- /// Squid COMM_SELECT_READ handler.
- void noteWantRead();
-
- /// Called when the openSSL SSL_connect function needs to write data to
- /// the remote SSL server. Sets the Squid COMM_SELECT_WRITE handler.
- virtual void noteWantWrite();
-
- /// Called when the SSL_connect function aborts with an SSL negotiation error
- /// \param result the SSL_connect return code
- /// \param ssl_error the error code returned from the SSL_get_error function
- /// \param ssl_lib_error the error returned from the ERR_Get_Error function
- virtual void noteSslNegotiationError(const int result, const int ssl_error, const int ssl_lib_error);
-
- /// Called when the SSL negotiation to the server completed and the certificates
- /// validated using the cert validator.
- /// \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
- /// for building the SSL objects.
- virtual Security::ContextPtr getSslContext() = 0;
-
- /// mimics FwdState to minimize changes to FwdState::initiate/negotiateSsl
- Comm::ConnectionPointer const &serverConnection() const { return serverConn; }
-
- void bail(ErrorState *error); ///< Return an error to the PeerConnector caller
-
- /// Callback the caller class, and pass the ready to communicate secure
- /// connection or an error if PeerConnector failed.
- void callBack();
-
- /// If called the certificates validator will not used
- void bypassCertValidator() {useCertValidator_ = false;}
-
- /// Called after negotiation finishes to record connection details for
- /// logging
- void recordNegotiationDetails();
-
- HttpRequestPointer request; ///< peer connection trigger or cause
- Comm::ConnectionPointer serverConn; ///< TCP connection to the peer
- AccessLogEntryPointer al; ///< info for the future access.log entry
- AsyncCall::Pointer callback; ///< we call this with the results
-private:
- PeerConnector(const PeerConnector &); // not implemented
- PeerConnector &operator =(const PeerConnector &); // not implemented
-
- /// Process response from cert validator helper
- 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 *&);
-
- /// A wrapper function for negotiateSsl for use with Comm::SetSelect
- static void NegotiateSsl(int fd, void *data);
- AsyncCall::Pointer closeHandler; ///< we call this when the connection closed
- time_t negotiationTimeout; ///< the SSL connection timeout to use
- time_t startTime; ///< when the peer connector negotiation started
- bool useCertValidator_; ///< whether the certificate validator should bypassed
-};
-
-} // namespace Ssl
-
-#endif /* USE_OPENSSL */
-#endif /* SQUID_SRC_SSL_PEERCONNECTOR_H */
-
diff -u -r -N squid-4.0.12/src/ssl/support.cc squid-4.0.13/src/ssl/support.cc
--- squid-4.0.12/src/ssl/support.cc 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/ssl/support.cc 2016-08-06 00:52:55.000000000 +1200
@@ -33,6 +33,9 @@
#include
+// TODO: Move ssl_ex_index_* global variables from global.cc here.
+int ssl_ex_index_ssl_untrusted_chain = -1;
+
Ipc::MemMap *Ssl::SessionCache = NULL;
const char *Ssl::SessionCacheName = "ssl_session_cache";
@@ -315,7 +318,7 @@
}
delete filledCheck->sslErrors;
filledCheck->sslErrors = NULL;
- filledCheck->serverCert.reset(NULL);
+ filledCheck->serverCert.reset();
}
// If the certificate validator is used then we need to allow all errors and
// pass them to certficate validator for more processing
@@ -470,6 +473,7 @@
ssl_ex_index_ssl_errors = SSL_get_ex_new_index(0, (void *) "ssl_errors", NULL, NULL, &ssl_free_SslErrors);
ssl_ex_index_ssl_cert_chain = SSL_get_ex_new_index(0, (void *) "ssl_cert_chain", NULL, NULL, &ssl_free_CertChain);
ssl_ex_index_ssl_validation_counter = SSL_get_ex_new_index(0, (void *) "ssl_validation_counter", NULL, NULL, &ssl_free_int);
+ ssl_ex_index_ssl_untrusted_chain = SSL_get_ex_new_index(0, (void *) "ssl_untrusted_chain", NULL, NULL, &ssl_free_CertChain);
}
#if defined(SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)
@@ -557,63 +561,57 @@
}
bool
-Ssl::InitServerContext(Security::ContextPtr &sslContext, AnyP::PortCfg &port)
+Ssl::InitServerContext(const Security::ContextPointer &ctx, AnyP::PortCfg &port)
{
- if (!sslContext)
+ if (!ctx)
return false;
- if (!SSL_CTX_use_certificate(sslContext, port.signingCert.get())) {
+ if (!SSL_CTX_use_certificate(ctx.get(), port.signingCert.get())) {
const int ssl_error = ERR_get_error();
const auto &keys = port.secure.certs.front();
debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire TLS certificate '" << keys.certFile << "': " << ERR_error_string(ssl_error, NULL));
- SSL_CTX_free(sslContext);
return false;
}
- if (!SSL_CTX_use_PrivateKey(sslContext, port.signPkey.get())) {
+ if (!SSL_CTX_use_PrivateKey(ctx.get(), port.signPkey.get())) {
const int ssl_error = ERR_get_error();
const auto &keys = port.secure.certs.front();
debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire TLS private key '" << keys.privateKeyFile << "': " << ERR_error_string(ssl_error, NULL));
- SSL_CTX_free(sslContext);
return false;
}
- Ssl::addChainToSslContext(sslContext, port.certsToChain.get());
+ Ssl::addChainToSslContext(ctx.get(), port.certsToChain.get());
/* Alternate code;
debugs(83, DBG_IMPORTANT, "Using certificate in " << certfile);
- if (!SSL_CTX_use_certificate_chain_file(sslContext, certfile)) {
+ if (!SSL_CTX_use_certificate_chain_file(ctx.get(), certfile)) {
ssl_error = ERR_get_error();
debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL certificate '" << certfile << "': " << ERR_error_string(ssl_error, NULL));
- SSL_CTX_free(sslContext);
return false;
}
debugs(83, DBG_IMPORTANT, "Using private key in " << keyfile);
- 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)) {
ssl_error = ERR_get_error();
debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL private key '" << keyfile << "': " << ERR_error_string(ssl_error, NULL));
- SSL_CTX_free(sslContext);
return false;
}
debugs(83, 5, "Comparing private and public SSL keys.");
- if (!SSL_CTX_check_private_key(sslContext)) {
+ if (!SSL_CTX_check_private_key(ctx.get())) {
ssl_error = ERR_get_error();
debugs(83, DBG_CRITICAL, "ERROR: SSL private key '" << certfile << "' does not match public key '" <<
keyfile << "': " << ERR_error_string(ssl_error, NULL));
- SSL_CTX_free(sslContext);
return false;
}
*/
- if (!configureSslContext(sslContext, port)) {
+ if (!configureSslContext(ctx.get(), port)) {
debugs(83, DBG_CRITICAL, "ERROR: Configuring static SSL context");
- SSL_CTX_free(sslContext);
return false;
}
@@ -1096,6 +1094,32 @@
}
}
+static const char *
+hasAuthorityInfoAccessCaIssuers(X509 *cert)
+{
+ AUTHORITY_INFO_ACCESS *info;
+ if (!cert)
+ return nullptr;
+ info = static_cast(X509_get_ext_d2i(cert, NID_info_access, NULL, NULL));
+ if (!info)
+ return nullptr;
+
+ static char uri[MAX_URL];
+ uri[0] = '\0';
+
+ for (int i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) {
+ ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
+ if (OBJ_obj2nid(ad->method) == NID_ad_ca_issuers) {
+ if (ad->location->type == GEN_URI) {
+ xstrncpy(uri, reinterpret_cast(ASN1_STRING_data(ad->location->d.uniformResourceIdentifier)), sizeof(uri));
+ }
+ break;
+ }
+ }
+ AUTHORITY_INFO_ACCESS_free(info);
+ return uri[0] != '\0' ? uri : nullptr;
+}
+
bool
Ssl::loadCerts(const char *certsFile, Ssl::CertsIndexedList &list)
{
@@ -1116,9 +1140,10 @@
return true;
}
-/// quickly find a certificate with a given issuer in Ssl::CertsIndexedList.
+/// quickly find the issuer certificate of a certificate cert in the
+/// Ssl::CertsIndexedList list
static X509 *
-findCertByIssuerFast(X509_STORE_CTX *ctx, Ssl::CertsIndexedList &list, X509 *cert)
+findCertIssuerFast(Ssl::CertsIndexedList &list, X509 *cert)
{
static char buffer[2048];
@@ -1130,21 +1155,80 @@
const auto ret = list.equal_range(SBuf(buffer));
for (Ssl::CertsIndexedList::iterator it = ret.first; it != ret.second; ++it) {
X509 *issuer = it->second;
- if (ctx->check_issued(ctx, cert, issuer)) {
+ if (X509_check_issued(cert, issuer)) {
return issuer;
}
}
return NULL;
}
-/// slowly find a certificate with a given issuer using linear search
+/// slowly find the issuer certificate of a given cert using linear search
+static bool
+findCertIssuer(Security::CertList const &list, X509 *cert)
+{
+ for (Security::CertList::const_iterator it = list.begin(); it != list.end(); ++it) {
+ if (X509_check_issued(it->get(), cert) == X509_V_OK)
+ return true;
+ }
+ return false;
+}
+
+const char *
+Ssl::uriOfIssuerIfMissing(X509 *cert, Security::CertList const &serverCertificates)
+{
+ if (!cert || !serverCertificates.size())
+ return nullptr;
+
+ if (!findCertIssuer(serverCertificates, cert)) {
+ //if issuer is missing
+ if (!findCertIssuerFast(SquidUntrustedCerts, cert)) {
+ // and issuer not found in local untrusted certificates database
+ if (const char *issuerUri = hasAuthorityInfoAccessCaIssuers(cert)) {
+ // There is a URI where we can download a certificate.
+ return issuerUri;
+ }
+ }
+ }
+ return nullptr;
+}
+
+void
+Ssl::missingChainCertificatesUrls(std::queue &URIs, Security::CertList const &serverCertificates)
+{
+ if (!serverCertificates.size())
+ return;
+
+ for (const auto &i : serverCertificates) {
+ if (const char *issuerUri = uriOfIssuerIfMissing(i.get(), serverCertificates))
+ URIs.push(SBuf(issuerUri));
+ }
+}
+
+void
+Ssl::SSL_add_untrusted_cert(SSL *ssl, X509 *cert)
+{
+ STACK_OF(X509) *untrustedStack = static_cast (SSL_get_ex_data(ssl, ssl_ex_index_ssl_untrusted_chain));
+ if (!untrustedStack) {
+ untrustedStack = sk_X509_new_null();
+ if (!SSL_set_ex_data(ssl, ssl_ex_index_ssl_untrusted_chain, untrustedStack)) {
+ sk_X509_pop_free(untrustedStack, X509_free);
+ throw TextException("Failed to attach untrusted certificates chain");
+ }
+ }
+ sk_X509_push(untrustedStack, cert);
+}
+
+/// Search for the issuer certificate of cert in sk list.
static X509 *
-findCertByIssuerSlowly(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *cert)
+sk_x509_findIssuer(STACK_OF(X509) *sk, X509 *cert)
{
+ if (!sk)
+ return NULL;
+
const int skItemsNum = sk_X509_num(sk);
for (int i = 0; i < skItemsNum; ++i) {
X509 *issuer = sk_X509_value(sk, i);
- if (ctx->check_issued(ctx, cert, issuer))
+ if (X509_check_issued(issuer, cert) == X509_V_OK)
return issuer;
}
return NULL;
@@ -1160,16 +1244,16 @@
X509 *current = ctx->cert;
int i = 0;
for (i = 0; current && (i < depth); ++i) {
- if (ctx->check_issued(ctx, current, current)) {
+ if (X509_check_issued(current, current)) {
// either ctx->cert is itself self-signed or untrustedCerts
// aready contain the self-signed current certificate
break;
}
// untrustedCerts is short, not worth indexing
- X509 *issuer = findCertByIssuerSlowly(ctx, untrustedCerts, current);
+ X509 *issuer = sk_x509_findIssuer(untrustedCerts, current);
if (!issuer) {
- if ((issuer = findCertByIssuerFast(ctx, SquidUntrustedCerts, current)))
+ if ((issuer = findCertIssuerFast(SquidUntrustedCerts, current)))
sk_X509_push(untrustedCerts, issuer);
}
current = issuer;
@@ -1185,12 +1269,25 @@
{
debugs(83, 4, "Try to use pre-downloaded intermediate certificates\n");
+ SSL *ssl = static_cast(X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()));
+ STACK_OF(X509) *sslUntrustedStack = static_cast (SSL_get_ex_data(ssl, ssl_ex_index_ssl_untrusted_chain));
+
// OpenSSL already maintains ctx->untrusted but we cannot modify
// internal OpenSSL list directly. We have to give OpenSSL our own
// list, but it must include certificates on the OpenSSL ctx->untrusted
STACK_OF(X509) *oldUntrusted = ctx->untrusted;
STACK_OF(X509) *sk = sk_X509_dup(oldUntrusted); // oldUntrusted is always not NULL
- completeIssuers(ctx, sk);
+
+ for (int i = 0; i < sk_X509_num(sslUntrustedStack); ++i) {
+ X509 *cert = sk_X509_value(sslUntrustedStack, i);
+ sk_X509_push(sk, cert);
+ }
+
+ // If the local untrusted certificates internal database is used
+ // run completeIssuers to add missing certificates if possible.
+ if (SquidUntrustedCerts.size() > 0)
+ completeIssuers(ctx, sk);
+
X509_STORE_CTX_set_chain(ctx, sk); // No locking/unlocking, just sets ctx->untrusted
int ret = X509_verify_cert(ctx);
X509_STORE_CTX_set_chain(ctx, oldUntrusted); // Set back the old untrusted list
@@ -1201,10 +1298,7 @@
void
Ssl::useSquidUntrusted(SSL_CTX *sslContext)
{
- if (SquidUntrustedCerts.size() > 0)
- SSL_CTX_set_cert_verify_callback(sslContext, untrustedToStoreCtx_cb, NULL);
- else
- SSL_CTX_set_cert_verify_callback(sslContext, NULL, NULL);
+ SSL_CTX_set_cert_verify_callback(sslContext, untrustedToStoreCtx_cb, NULL);
}
bool
@@ -1273,11 +1367,11 @@
// XXX: ssl_ask_password_cb needs SSL_CTX_set_default_passwd_cb_userdata()
// so this may not fully work iff Config.Program.ssl_password is set.
pem_password_cb *cb = ::Config.Program.ssl_password ? &ssl_ask_password_cb : NULL;
- pkey.reset(readSslPrivateKey(keyFilename, cb));
- cert.reset(readSslX509CertificatesChain(certFilename, chain.get()));
+ pkey.resetWithoutLocking(readSslPrivateKey(keyFilename, cb));
+ cert.resetWithoutLocking(readSslX509CertificatesChain(certFilename, chain.get()));
if (!pkey || !cert || !X509_check_private_key(cert.get(), pkey.get())) {
- pkey.reset(NULL);
- cert.reset(NULL);
+ pkey.reset();
+ cert.reset();
}
}
@@ -1304,26 +1398,27 @@
return Ssl::generateSslCertificate(untrustedCert, untrustedPkey, certProperties);
}
-SSL *
-SslCreate(Security::ContextPtr sslContext, const int fd, Ssl::Bio::Type type, const char *squidCtx)
+static bool
+SslCreate(Security::ContextPtr sslContext, const Comm::ConnectionPointer &conn, Ssl::Bio::Type type, const char *squidCtx)
{
- if (fd < 0) {
+ if (!Comm::IsConnOpen(conn)) {
debugs(83, DBG_IMPORTANT, "Gone connection");
- return NULL;
+ return false;
}
const char *errAction = NULL;
int errCode = 0;
if (auto ssl = SSL_new(sslContext)) {
+ const int fd = conn->fd;
// without BIO, we would call SSL_set_fd(ssl, fd) instead
if (BIO *bio = Ssl::Bio::Create(fd, type)) {
Ssl::Bio::Link(ssl, bio); // cannot fail
- fd_table[fd].ssl.reset(ssl);
+ fd_table[fd].ssl.resetWithoutLocking(ssl);
fd_table[fd].read_method = &ssl_read_method;
fd_table[fd].write_method = &ssl_write_method;
fd_note(fd, squidCtx);
- return ssl;
+ return true;
}
errCode = ERR_get_error();
errAction = "failed to initialize I/O";
@@ -1335,19 +1430,19 @@
debugs(83, DBG_IMPORTANT, "ERROR: " << squidCtx << ' ' << errAction <<
": " << ERR_error_string(errCode, NULL));
- return NULL;
+ return false;
}
-SSL *
-Ssl::CreateClient(Security::ContextPtr sslContext, const int fd, const char *squidCtx)
+bool
+Ssl::CreateClient(Security::ContextPtr sslContext, const Comm::ConnectionPointer &c, const char *squidCtx)
{
- return SslCreate(sslContext, fd, Ssl::Bio::BIO_TO_SERVER, squidCtx);
+ return SslCreate(sslContext, c, Ssl::Bio::BIO_TO_SERVER, squidCtx);
}
-SSL *
-Ssl::CreateServer(Security::ContextPtr sslContext, const int fd, const char *squidCtx)
+bool
+Ssl::CreateServer(Security::ContextPtr sslContext, const Comm::ConnectionPointer &c, const char *squidCtx)
{
- return SslCreate(sslContext, fd, Ssl::Bio::BIO_TO_CLIENT, 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)
diff -u -r -N squid-4.0.12/src/ssl/support.h squid-4.0.13/src/ssl/support.h
--- squid-4.0.12/src/ssl/support.h 2016-07-02 01:26:44.000000000 +1200
+++ squid-4.0.13/src/ssl/support.h 2016-08-06 00:52:55.000000000 +1200
@@ -14,6 +14,7 @@
#if USE_OPENSSL
#include "base/CbDataList.h"
+#include "comm/forward.h"
#include "sbuf/SBuf.h"
#include "security/forward.h"
#include "ssl/gadgets.h"
@@ -27,6 +28,7 @@
#if HAVE_OPENSSL_ENGINE_H
#include
#endif
+#include
#include