diff -u -r -N squid-3.1.12/ChangeLog squid-3.1.12.1/ChangeLog --- squid-3.1.12/ChangeLog 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/ChangeLog 2011-04-19 17:27:09.000000000 +1200 @@ -1,3 +1,13 @@ +Changes to squid-3.1.12.1 (19 Apr 2011): + + - Port from 3.2: Dynamic SSL Certificate generation + - Bug 3194: selinux may prevent ntlm_smb_lm_auth from using /tmp + - Bug 3185: 3.1.11 fails to compile on OpenBSD 4.8 and 4.9 + - Bug 3183: Invalid URL accepted with url host part of only '@' + - Display ERROR in cache.log for invalid configured paths + - Cache Manager: send User-Agent header from cachemgr.cgi + - ... and many portability compile fixes for non-GCC systems. + Changes to squid-3.1.12 (04 Apr 2011): - Regression fix: Use bigger buffer for server reads. diff -u -r -N squid-3.1.12/compat/assert.cc squid-3.1.12.1/compat/assert.cc --- squid-3.1.12/compat/assert.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/compat/assert.cc 2011-04-19 17:27:09.000000000 +1200 @@ -33,17 +33,6 @@ #include "config.h" -#if HAVE_STDIO_H -#include -#endif -#if HAVE_STDLIB_H -#include -#endif - -#if 0 -#include "compat/assert.h" -#endif - void xassert(const char *expr, const char *file, int line) { fprintf(stderr, "assertion failed: %s:%d: \"%s\"\n", file, line, expr); diff -u -r -N squid-3.1.12/compat/compat.h squid-3.1.12.1/compat/compat.h --- squid-3.1.12/compat/compat.h 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/compat/compat.h 2011-04-19 17:27:09.000000000 +1200 @@ -75,6 +75,9 @@ #include "compat/stdvarargs.h" #include "compat/assert.h" +/* cstdio has a bunch of problems with 64-bit definitions */ +#include "compat/stdio.h" + /*****************************************************/ /* component-specific portabilities */ /*****************************************************/ diff -u -r -N squid-3.1.12/compat/compat_shared.h squid-3.1.12.1/compat/compat_shared.h --- squid-3.1.12/compat/compat_shared.h 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/compat/compat_shared.h 2011-04-19 17:27:09.000000000 +1200 @@ -30,8 +30,7 @@ /* * DIRENT functionality can apparently come from many places. - * I believe these should really be done by OS-specific compat - * files, but for now its left here. + * With various complaints by different compilers */ #if HAVE_DIRENT_H #include @@ -51,6 +50,15 @@ #endif /* HAVE_NDIR_H */ #endif /* HAVE_DIRENT_H */ +/* The structure dirent also varies between 64-bit and 32-bit environments. + * Define our own dirent_t type for consistent simple internal use. + * NP: GCC seems not to care about the type naming differences. + */ +#if defined(__USE_FILE_OFFSET64) && !defined(__GNUC__) +#define dirent_t struct dirent64 +#else +#define dirent_t struct dirent +#endif /* * Filedescriptor limits in the different select loops diff -u -r -N squid-3.1.12/compat/GnuRegex.c squid-3.1.12.1/compat/GnuRegex.c --- squid-3.1.12/compat/GnuRegex.c 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/compat/GnuRegex.c 2011-04-19 17:27:09.000000000 +1200 @@ -235,9 +235,6 @@ #define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#define MIN(a, b) ((a) < (b) ? (a) : (b)) - #if !defined(__MINGW32__) /* MinGW defines boolean */ typedef char boolean; #endif @@ -452,12 +449,6 @@ #ifdef DEBUG -/* We use standard I/O for debugging. */ -#include - -/* It is useful to test things that ``must'' be true when debugging. */ -#include - static int debug = 0; #define DEBUG_STATEMENT(e) e @@ -3147,7 +3138,7 @@ if (bufp->regs_allocated == REGS_UNALLOCATED) { /* No. So allocate them with malloc. We need one * extra element beyond `num_regs' for the `-1' marker * GNU code uses. */ - regs->num_regs = MAX(RE_NREGS, num_regs + 1); + regs->num_regs = max(RE_NREGS, num_regs + 1); regs->start = TALLOC(regs->num_regs, regoff_t); regs->end = TALLOC(regs->num_regs, regoff_t); if (regs->start == NULL || regs->end == NULL) @@ -3176,7 +3167,7 @@ } /* Go through the first `min (num_regs, regs->num_regs)' * registers, since that is all we initialized. */ - for (mcnt = 1; mcnt < MIN(num_regs, regs->num_regs); mcnt++) { + for (mcnt = 1; mcnt < min(num_regs, regs->num_regs); mcnt++) { if (REG_UNSET(regstart[mcnt]) || REG_UNSET(regend[mcnt])) regs->start[mcnt] = regs->end[mcnt] = -1; else { diff -u -r -N squid-3.1.12/compat/Makefile.am squid-3.1.12.1/compat/Makefile.am --- squid-3.1.12/compat/Makefile.am 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/compat/Makefile.am 2011-04-19 17:27:09.000000000 +1200 @@ -17,6 +17,7 @@ compat_shared.h \ fdsetsize.h \ osdetect.h \ + stdio.h \ stdvarargs.h \ valgrind.h \ \ diff -u -r -N squid-3.1.12/compat/Makefile.in squid-3.1.12.1/compat/Makefile.in --- squid-3.1.12/compat/Makefile.in 2011-04-04 13:24:42.000000000 +1200 +++ squid-3.1.12.1/compat/Makefile.in 2011-04-19 17:27:51.000000000 +1200 @@ -307,6 +307,7 @@ compat_shared.h \ fdsetsize.h \ osdetect.h \ + stdio.h \ stdvarargs.h \ valgrind.h \ \ diff -u -r -N squid-3.1.12/compat/os/linux.h squid-3.1.12.1/compat/os/linux.h --- squid-3.1.12/compat/os/linux.h 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/compat/os/linux.h 2011-04-19 17:27:09.000000000 +1200 @@ -44,6 +44,29 @@ #include #endif /* HAVE_SYS_CAPABILITY_H */ +/* + * glob.h is provided by GNU on Linux and contains some unavoidable preprocessor + * logic errors in its 64-bit definitions which are hit by non-GCC compilers. + * + * #if __USE_FILE_OFFSET64 && __GNUC__ < 2 + * # define glob glob64 + * #endif + * #if !defined __USE_FILE_OFFSET64 || __GNUC__ < 2 + * extern "C" glob(...); + * #endif + * extern "C" glob64(...); + * + * ... and multiple "C" definitions of glob64 refuse to compile. + * Because __GNUC__ being undefined equates to 0 and (0 < 2) + */ +#if __USE_FILE_OFFSET64 && __GNUC__ < 2 +#if HAVE_GLOB_H +#undef HAVE_GLOB_H +#endif +#if HAVE_GLOB +#undef HAVE_GLOB +#endif +#endif #endif /* _SQUID_LINUX_ */ #endif /* SQUID_OS_LINUX_H */ diff -u -r -N squid-3.1.12/compat/os/openbsd.h squid-3.1.12.1/compat/os/openbsd.h --- squid-3.1.12/compat/os/openbsd.h 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/compat/os/openbsd.h 2011-04-19 17:27:09.000000000 +1200 @@ -35,5 +35,13 @@ #define IPV6_V6ONLY 27 // from OpenBSD 4.3 headers. (NP: does not match non-BSD OS values) #endif +/* OpenBSD 4.8 and 4.9 require netinet/in.h before arpa/inet.h */ +#if HAVE_NETINET_IN_H +#include +#endif +#if HAVE_ARPA_INET_H +#include +#endif + #endif /* _SQUID_OPENBSD_ */ #endif /* SQUID_OS_OPENBSD_H */ diff -u -r -N squid-3.1.12/compat/stdio.h squid-3.1.12.1/compat/stdio.h --- squid-3.1.12/compat/stdio.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.1.12.1/compat/stdio.h 2011-04-19 17:27:09.000000000 +1200 @@ -0,0 +1,53 @@ +#ifndef _SQUID_COMPAT_STDIO_H +#define _SQUID_COMPAT_STDIO_H + +/** 64-bit broken + * + * provides fgetpos64, fopen64 if __USE_FILE_OFFSET64 is defined. + * It then checks whether a gcc-specific __REDIRECT macro is available + * (defined in , depending on __GNUC__ begin available). + * If it is not available, it does a preprocessor #define. + * Which undefines, with this comment: + * "// Get rid of those macros defined in in lieu of real functions.". + * When it does a namespace redirection ("namespace std { using ::fgetpos; }") it goes blam, as + * fgetpos64 is available, while fgetpos is not. + */ + +// Import the stdio.h definitions first to do the state setup +#if HAVE_STDIO_H +#include +#endif + +// Check for the buggy case +#if defined(__USE_FILE_OFFSET64) && !defined(__REDIRECT) + +// Define the problem functions as needed +#if defined(fgetpos) +#undef fgetpos +inline int fgetpos(FILE *f, fpos64_t *p) { return fgetpos64(f,p); } +#endif +#if defined(fopen) +#undef fopen +inline FILE * fopen(const char *f, const char *m) { return fopen64(f,m); } +#endif +#if defined(freopen) +#undef freopen +inline FILE * freopen(const char *f, const char *m, FILE *s) { return freopen64(f,m,s); } +#endif +#if defined(fsetpos) +#undef fsetpos +inline int fsetpos(FILE *f, fpos64_t *p) { return fsetpos64(f,p); } +#endif +#if defined(tmpfile) +#undef tmpfile +inline FILE * tmpfile(void) { return tmpfile64(); } +#endif + +#endif /* __USE_FILE_OFFSET64 && !__REDIRECT */ + +// Finally import the stuff we actually use +#if HAVE_CSTDIO +#include +#endif + +#endif /* _SQUID_COMPAT_STDIO_H */ diff -u -r -N squid-3.1.12/configure squid-3.1.12.1/configure --- squid-3.1.12/configure 2011-04-04 13:25:13.000000000 +1200 +++ squid-3.1.12.1/configure 2011-04-19 17:28:35.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.68 for Squid Web Proxy 3.1.12. +# Generated by GNU Autoconf 2.68 for Squid Web Proxy 3.1.12.1. # # Report bugs to . # @@ -575,8 +575,8 @@ # Identity of this package. PACKAGE_NAME='Squid Web Proxy' PACKAGE_TARNAME='squid' -PACKAGE_VERSION='3.1.12' -PACKAGE_STRING='Squid Web Proxy 3.1.12' +PACKAGE_VERSION='3.1.12.1' +PACKAGE_STRING='Squid Web Proxy 3.1.12.1' PACKAGE_BUGREPORT='http://www.squid-cache.org/bugs/' PACKAGE_URL='' @@ -675,6 +675,8 @@ AUTH_LIBS_TO_BUILD AUTH_MODULES OPT_DEFAULT_HOSTS +USE_SSL_CRTD_FALSE +USE_SSL_CRTD_TRUE USE_DNSSERVER_FALSE USE_DNSSERVER_TRUE MAKE_LEAKFINDER_FALSE @@ -950,6 +952,7 @@ enable_follow_x_forwarded_for enable_ident_lookups enable_internal_dns +enable_ssl_crtd enable_default_hostsfile enable_auth enable_basic_auth_helpers @@ -1536,7 +1539,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 3.1.12 to adapt to many kinds of systems. +\`configure' configures Squid Web Proxy 3.1.12.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1606,7 +1609,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of Squid Web Proxy 3.1.12:";; + short | recursive ) echo "Configuration of Squid Web Proxy 3.1.12.1:";; esac cat <<\_ACEOF @@ -1729,6 +1732,9 @@ --disable-internal-dns Prevents Squid from directly sending and receiving DNS messages, and instead enables the old external 'dnsserver' processes. + --enable-ssl-crtd Prevent Squid from directly generation of SSL + private key and certificate request and instead + enables the ssl_crtd processes. --enable-default-hostsfile=path Select default location for hosts file. See hosts_file directive in squid.conf for details @@ -1934,7 +1940,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -Squid Web Proxy configure 3.1.12 +Squid Web Proxy configure 3.1.12.1 generated by GNU Autoconf 2.68 Copyright (C) 2010 Free Software Foundation, Inc. @@ -2945,7 +2951,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 3.1.12, which was +It was created by Squid Web Proxy $as_me 3.1.12.1, which was generated by GNU Autoconf 2.68. Invocation command line was $ $0 $@ @@ -3764,7 +3770,7 @@ # Define the identity of the package. PACKAGE='squid' - VERSION='3.1.12' + VERSION='3.1.12.1' cat >>confdefs.h <<_ACEOF @@ -19480,6 +19486,43 @@ fi + if false; then + USE_SSL_CRTD_TRUE= + USE_SSL_CRTD_FALSE='#' +else + USE_SSL_CRTD_TRUE='#' + USE_SSL_CRTD_FALSE= +fi + +use_ssl_crtd= +# Check whether --enable-ssl-crtd was given. +if test "${enable_ssl_crtd+set}" = set; then : + enableval=$enable_ssl_crtd; + if test "x$enableval" = "xyes" ; then + use_ssl_crtd="yes" + fi + +fi + + +if test "x$use_ssl_crtd" = "xyes" -a -z "$USE_OPENSSL" ; then + as_fn_error $? "You need to enable ssl gatewaying support to use ssl_crtd feature. Try to use --enable-ssl. " "$LINENO" 5 +fi + +if test "x$use_ssl_crtd" = "xyes"; then + +$as_echo "#define USE_SSL_CRTD 1" >>confdefs.h + + if true; then + USE_SSL_CRTD_TRUE= + USE_SSL_CRTD_FALSE='#' +else + USE_SSL_CRTD_TRUE='#' + USE_SSL_CRTD_FALSE= +fi + +fi + # Check whether --enable-default-hostsfile was given. if test "${enable_default_hostsfile+set}" = set; then : enableval=$enable_default_hostsfile; @@ -21071,6 +21114,7 @@ execinfo.h \ fcntl.h \ fnmatch.h \ + fstream \ getopt.h \ glob.h \ gnumalloc.h \ @@ -21086,12 +21130,16 @@ libc.h \ libgen.h \ limits.h \ + limits \ linux/posix_types.h \ linux/types.h \ + list \ machine/byte_swap.h \ malloc.h \ + map \ math.h \ memory.h \ + memory \ mount.h \ netdb.h \ netinet/in.h \ @@ -21100,6 +21148,7 @@ openssl/err.h \ openssl/md5.h \ openssl/ssl.h \ + openssl/txt_db.h \ openssl/x509v3.h \ netinet/tcp.h \ openssl/engine.h \ @@ -27308,7 +27357,7 @@ rm -f core -ac_config_files="$ac_config_files Makefile compat/Makefile lib/Makefile scripts/Makefile src/Makefile src/base/Makefile src/acl/Makefile src/fs/Makefile src/repl/Makefile src/auth/Makefile src/adaptation/Makefile src/adaptation/icap/Makefile src/adaptation/ecap/Makefile src/esi/Makefile src/icmp/Makefile src/ident/Makefile src/ip/Makefile contrib/Makefile snmplib/Makefile icons/Makefile errors/Makefile test-suite/Makefile doc/Makefile helpers/Makefile helpers/basic_auth/Makefile helpers/basic_auth/LDAP/Makefile helpers/basic_auth/MSNT/Makefile helpers/basic_auth/NCSA/Makefile helpers/basic_auth/PAM/Makefile helpers/basic_auth/SMB/Makefile helpers/basic_auth/mswin_sspi/Makefile helpers/basic_auth/YP/Makefile helpers/basic_auth/getpwnam/Makefile helpers/basic_auth/multi-domain-NTLM/Makefile helpers/basic_auth/SASL/Makefile helpers/basic_auth/POP3/Makefile helpers/basic_auth/DB/Makefile helpers/basic_auth/squid_radius_auth/Makefile helpers/digest_auth/Makefile helpers/digest_auth/password/Makefile helpers/digest_auth/ldap/Makefile helpers/digest_auth/eDirectory/Makefile helpers/ntlm_auth/Makefile helpers/ntlm_auth/fakeauth/Makefile helpers/ntlm_auth/no_check/Makefile helpers/ntlm_auth/smb_lm/Makefile helpers/ntlm_auth/smb_lm/smbval/Makefile helpers/ntlm_auth/mswin_sspi/Makefile helpers/negotiate_auth/Makefile helpers/negotiate_auth/mswin_sspi/Makefile helpers/external_acl/Makefile helpers/external_acl/ip_user/Makefile helpers/external_acl/ldap_group/Makefile helpers/external_acl/session/Makefile helpers/external_acl/unix_group/Makefile helpers/external_acl/wbinfo_group/Makefile helpers/external_acl/mswin_ad_group/Makefile helpers/external_acl/mswin_lm_group/Makefile tools/Makefile" +ac_config_files="$ac_config_files Makefile compat/Makefile lib/Makefile scripts/Makefile src/Makefile src/base/Makefile src/acl/Makefile src/fs/Makefile src/repl/Makefile src/auth/Makefile src/adaptation/Makefile src/adaptation/icap/Makefile src/adaptation/ecap/Makefile src/esi/Makefile src/icmp/Makefile src/ident/Makefile src/ip/Makefile src/ssl/Makefile contrib/Makefile snmplib/Makefile icons/Makefile errors/Makefile test-suite/Makefile doc/Makefile helpers/Makefile helpers/basic_auth/Makefile helpers/basic_auth/LDAP/Makefile helpers/basic_auth/MSNT/Makefile helpers/basic_auth/NCSA/Makefile helpers/basic_auth/PAM/Makefile helpers/basic_auth/SMB/Makefile helpers/basic_auth/mswin_sspi/Makefile helpers/basic_auth/YP/Makefile helpers/basic_auth/getpwnam/Makefile helpers/basic_auth/multi-domain-NTLM/Makefile helpers/basic_auth/SASL/Makefile helpers/basic_auth/POP3/Makefile helpers/basic_auth/DB/Makefile helpers/basic_auth/squid_radius_auth/Makefile helpers/digest_auth/Makefile helpers/digest_auth/password/Makefile helpers/digest_auth/ldap/Makefile helpers/digest_auth/eDirectory/Makefile helpers/ntlm_auth/Makefile helpers/ntlm_auth/fakeauth/Makefile helpers/ntlm_auth/no_check/Makefile helpers/ntlm_auth/smb_lm/Makefile helpers/ntlm_auth/smb_lm/smbval/Makefile helpers/ntlm_auth/mswin_sspi/Makefile helpers/negotiate_auth/Makefile helpers/negotiate_auth/mswin_sspi/Makefile helpers/external_acl/Makefile helpers/external_acl/ip_user/Makefile helpers/external_acl/ldap_group/Makefile helpers/external_acl/session/Makefile helpers/external_acl/unix_group/Makefile helpers/external_acl/wbinfo_group/Makefile helpers/external_acl/mswin_ad_group/Makefile helpers/external_acl/mswin_lm_group/Makefile tools/Makefile" subdirs="$subdirs lib/libTrie" @@ -27591,6 +27640,14 @@ as_fn_error $? "conditional \"USE_DNSSERVER\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${USE_SSL_CRTD_TRUE}" && test -z "${USE_SSL_CRTD_FALSE}"; then + as_fn_error $? "conditional \"USE_SSL_CRTD\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${USE_SSL_CRTD_TRUE}" && test -z "${USE_SSL_CRTD_FALSE}"; then + as_fn_error $? "conditional \"USE_SSL_CRTD\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${ENABLE_UNLINKD_TRUE}" && test -z "${ENABLE_UNLINKD_FALSE}"; then as_fn_error $? "conditional \"ENABLE_UNLINKD\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -28045,7 +28102,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 3.1.12, which was +This file was extended by Squid Web Proxy $as_me 3.1.12.1, which was generated by GNU Autoconf 2.68. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -28111,7 +28168,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 3.1.12 +Squid Web Proxy config.status 3.1.12.1 configured by $0, generated by GNU Autoconf 2.68, with options \\"\$ac_cs_config\\" @@ -28620,6 +28677,7 @@ "src/icmp/Makefile") CONFIG_FILES="$CONFIG_FILES src/icmp/Makefile" ;; "src/ident/Makefile") CONFIG_FILES="$CONFIG_FILES src/ident/Makefile" ;; "src/ip/Makefile") CONFIG_FILES="$CONFIG_FILES src/ip/Makefile" ;; + "src/ssl/Makefile") CONFIG_FILES="$CONFIG_FILES src/ssl/Makefile" ;; "contrib/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/Makefile" ;; "snmplib/Makefile") CONFIG_FILES="$CONFIG_FILES snmplib/Makefile" ;; "icons/Makefile") CONFIG_FILES="$CONFIG_FILES icons/Makefile" ;; diff -u -r -N squid-3.1.12/configure.ac squid-3.1.12.1/configure.ac --- squid-3.1.12/configure.ac 2011-04-04 13:25:13.000000000 +1200 +++ squid-3.1.12.1/configure.ac 2011-04-19 17:28:34.000000000 +1200 @@ -2,7 +2,7 @@ dnl dnl $Id$ dnl -AC_INIT([Squid Web Proxy],[3.1.12],[http://www.squid-cache.org/bugs/],[squid]) +AC_INIT([Squid Web Proxy],[3.1.12.1],[http://www.squid-cache.org/bugs/],[squid]) AC_PREREQ(2.61) AC_CONFIG_HEADERS([include/autoconf.h]) AC_CONFIG_AUX_DIR(cfgaux) @@ -1678,6 +1678,26 @@ AM_CONDITIONAL(USE_DNSSERVER, true) fi +AM_CONDITIONAL(USE_SSL_CRTD, false) +use_ssl_crtd= +AC_ARG_ENABLE(ssl-crtd, + AC_HELP_STRING([--enable-ssl-crtd], + [Prevent Squid from directly generation of SSL private key and + certificate request and instead enables the ssl_crtd processes.]), [ + if test "x$enableval" = "xyes" ; then + use_ssl_crtd="yes" + fi +]) + +if test "x$use_ssl_crtd" = "xyes" -a -z "$USE_OPENSSL" ; then + AC_MSG_ERROR([You need to enable ssl gatewaying support to use ssl_crtd feature. Try to use --enable-ssl. ]) +fi + +if test "x$use_ssl_crtd" = "xyes"; then + AC_DEFINE(USE_SSL_CRTD, 1,[Use ssl_crtd daemon]) + AM_CONDITIONAL(USE_SSL_CRTD, true) +fi + dnl Select Default hosts file location AC_ARG_ENABLE(default-hostsfile, AS_HELP_STRING([--enable-default-hostsfile=path],[Select default location for hosts file. @@ -2257,6 +2277,7 @@ execinfo.h \ fcntl.h \ fnmatch.h \ + fstream \ getopt.h \ glob.h \ gnumalloc.h \ @@ -2272,12 +2293,16 @@ libc.h \ libgen.h \ limits.h \ + limits \ linux/posix_types.h \ linux/types.h \ + list \ machine/byte_swap.h \ malloc.h \ + map \ math.h \ memory.h \ + memory \ mount.h \ netdb.h \ netinet/in.h \ @@ -2286,6 +2311,7 @@ openssl/err.h \ openssl/md5.h \ openssl/ssl.h \ + openssl/txt_db.h \ openssl/x509v3.h \ netinet/tcp.h \ openssl/engine.h \ @@ -3934,6 +3960,7 @@ src/icmp/Makefile \ src/ident/Makefile \ src/ip/Makefile \ + src/ssl/Makefile \ contrib/Makefile \ snmplib/Makefile \ icons/Makefile \ diff -u -r -N squid-3.1.12/helpers/ntlm_auth/smb_lm/ntlm_smb_lm_auth.c squid-3.1.12.1/helpers/ntlm_auth/smb_lm/ntlm_smb_lm_auth.c --- squid-3.1.12/helpers/ntlm_auth/smb_lm/ntlm_smb_lm_auth.c 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/helpers/ntlm_auth/smb_lm/ntlm_smb_lm_auth.c 2011-04-19 17:27:09.000000000 +1200 @@ -462,13 +462,6 @@ main(int argc, char *argv[]) { debug("ntlm_auth build " __DATE__ ", " __TIME__ " starting up...\n"); -#ifdef DEBUG - debug("changing dir to /tmp\n"); - if (chdir("/tmp") != 0) { - debug("ERROR: (%d) failed.\n",errno); - return 2; - } -#endif my_program_name = argv[0]; process_options(argc, argv); diff -u -r -N squid-3.1.12/include/autoconf.h.in squid-3.1.12.1/include/autoconf.h.in --- squid-3.1.12/include/autoconf.h.in 2011-04-04 13:24:37.000000000 +1200 +++ squid-3.1.12.1/include/autoconf.h.in 2011-04-19 17:27:45.000000000 +1200 @@ -210,6 +210,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_FNMATCH_H +/* Define to 1 if you have the header file. */ +#undef HAVE_FSTREAM + /* "Define to 1 if aufs filesystem module is build" */ #undef HAVE_FS_AUFS @@ -369,6 +372,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LIBXML_PARSER_H +/* Define to 1 if you have the header file. */ +#undef HAVE_LIMITS + /* Define to 1 if you have the header file. */ #undef HAVE_LIMITS_H @@ -385,6 +391,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_TYPES_H +/* Define to 1 if you have the header file. */ +#undef HAVE_LIST + /* long is defined in system headers */ #undef HAVE_LONG @@ -415,6 +424,9 @@ /* Define to 1 if you have the `mallopt' function. */ #undef HAVE_MALLOPT +/* Define to 1 if you have the header file. */ +#undef HAVE_MAP + /* Define to 1 if you have the header file. */ #undef HAVE_MATH_H @@ -424,6 +436,9 @@ /* Define to 1 if you have the `memmove' function. */ #undef HAVE_MEMMOVE +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY + /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H @@ -520,6 +535,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_SSL_H +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_TXT_DB_H + /* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_X509V3_H @@ -1209,6 +1227,9 @@ /* Define this to include code for SSL encryption. */ #undef USE_SSL +/* Use ssl_crtd daemon */ +#undef USE_SSL_CRTD + /* Define this if unlinkd is required (strongly recommended for ufs storage type) */ #undef USE_UNLINKD diff -u -r -N squid-3.1.12/include/version.h squid-3.1.12.1/include/version.h --- squid-3.1.12/include/version.h 2011-04-04 13:25:13.000000000 +1200 +++ squid-3.1.12.1/include/version.h 2011-04-19 17:28:35.000000000 +1200 @@ -9,7 +9,7 @@ */ #ifndef SQUID_RELEASE_TIME -#define SQUID_RELEASE_TIME 1301880244 +#define SQUID_RELEASE_TIME 1303190827 #endif #ifndef APP_SHORTNAME diff -u -r -N squid-3.1.12/lib/getnameinfo.c squid-3.1.12.1/lib/getnameinfo.c --- squid-3.1.12/lib/getnameinfo.c 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/lib/getnameinfo.c 2011-04-19 17:27:09.000000000 +1200 @@ -77,12 +77,6 @@ #ifndef HAVE_GETNAMEINFO -#if HAVE_SYS_TYPES_H -#include -#endif -#if HAVE_STDIO_H -#include -#endif #if HAVE_SYS_SOCKET_H #include #endif diff -u -r -N squid-3.1.12/lib/inet_ntop.c squid-3.1.12.1/lib/inet_ntop.c --- squid-3.1.12/lib/inet_ntop.c 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/lib/inet_ntop.c 2011-04-19 17:27:09.000000000 +1200 @@ -68,9 +68,6 @@ #if HAVE_ERRNO_H #include #endif -#if HAVE_STDIO_H -#include -#endif #if HAVE_STRING_H #include #endif diff -u -r -N squid-3.1.12/lib/tempnam.c squid-3.1.12.1/lib/tempnam.c --- squid-3.1.12/lib/tempnam.c 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/lib/tempnam.c 2011-04-19 17:27:09.000000000 +1200 @@ -17,12 +17,6 @@ #if HAVE_LIBC_H #include #endif -#if HAVE_STDIO_H -#include -#endif -#if HAVE_TYPES_H -#include -#endif #if HAVE_LIMITS_H #include #endif diff -u -r -N squid-3.1.12/RELEASENOTES.html squid-3.1.12.1/RELEASENOTES.html --- squid-3.1.12/RELEASENOTES.html 2011-04-04 13:51:45.000000000 +1200 +++ squid-3.1.12.1/RELEASENOTES.html 2011-04-19 17:53:16.000000000 +1200 @@ -2,10 +2,10 @@ - Squid 3.1.12 release notes + Squid 3.1.12.1 release notes -

Squid 3.1.12 release notes

+

Squid 3.1.12.1 release notes

Squid Developers


@@ -31,9 +31,10 @@
  • 2.5 Connection Pinning (for NTLM Auth Passthrough)
  • 2.6 Quality of Service (QoS) Flow support
  • 2.7 SSL Bump (for HTTPS Filtering and Adaptation) -
  • 2.8 eCAP Adaptation Module support -
  • 2.9 ICAP Bypass and Retry enhancements -
  • 2.10 ICY streaming protocol support +
  • 2.8 Dynamic SSL Certificate Generation +
  • 2.9 eCAP Adaptation Module support +
  • 2.10 ICAP Bypass and Retry enhancements +
  • 2.11 ICY streaming protocol support

    3. Changes to squid.conf since Squid-3.0

    @@ -70,7 +71,7 @@

    1. Notice

    -

    The Squid Team are pleased to announce the release of Squid-3.1.12

    +

    The Squid Team are pleased to announce the release of Squid-3.1.12.1

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

    @@ -124,6 +125,7 @@
  • eCAP Adaptation Module support
  • ICAP Bypass and Retry enhancements
  • ICY streaming protocol support
  • +
  • Dynamic SSL Certificate Generation (3.1.12.1 and later)
  • Most user-facing changes are reflected in squid.conf (see below).

    @@ -371,8 +373,30 @@ configuration. Use of interception for port 443 is not officially supported, despite being known to work under certain limited networking circumstances.

    +

    2.8 Dynamic SSL Certificate Generation +

    + +

    SslBump users know how many certificate warnings a single complex site +(using dedicated image, style, and/or advertisement servers for embedded content) +can generate. The warnings are legitimate and are caused by Squid-provided site +certificate. Two things may be wrong with that certificate: +

      +
    • Squid certificate is not signed by a trusted authority.
    • +
    • Squid certificate name does not match the site domain name.
    • +
    -

    2.8 eCAP Adaptation Module support +Squid can do nothing about (A), but in most targeted environments, users will +trust the "man in the middle" authority and install the corresponding root +certificate.

    + +

    To avoid mismatch (B), the DynamicSslCert feature concentrates on generating +site certificates that match the requested site domain name. Please note that +the browser site name check does not really add much security in an SslBump +environment where the user already trusts the "man in the middle". The check +only adds warnings and creates page rendering problems in browsers that try to +reduce the number of warnings by blocking some embedded content.

    + +

    2.9 eCAP Adaptation Module support

    Details in @@ -384,7 +408,7 @@

    Currently known and available eCAP modules are listed in the wiki feature page on eCAP.

    -

    2.9 ICAP Bypass and Retry enhancements +

    2.10 ICAP Bypass and Retry enhancements

    Details in @@ -446,7 +470,7 @@ environments yet may be small enough to limit side-effects of loops.

    -

    2.10 ICY streaming protocol support +

    2.11 ICY streaming protocol support

    Squid-3.1 adds native support for streaming protocol ICY. @@ -1047,6 +1071,12 @@

    +
    sslcrtd_program
    +

    Specify the location and options of the executable for ssl_crtd process.

    + +
    sslcrtd_children
    +

    Configures the number of sslcrtd processes to spawn

    +
    sslproxy_cert_error

    New Access Control to selectively bypass server certificate validation errors. DEFAULT: None bypassed. @@ -1575,6 +1605,10 @@ original or indirect client when a request has been forwarded through other proxies.

    +
    --enable-ssl-crtd
    +

    Prevent Squid from direct generation of SSL private key and +certificate request and instead enables the ssl_crtd processes.

    +
    --enable-zph-qos

    Build with support for ZPH Quality of Service controls

    diff -u -r -N squid-3.1.12/src/acl/DomainData.cc squid-3.1.12.1/src/acl/DomainData.cc --- squid-3.1.12/src/acl/DomainData.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/acl/DomainData.cc 2011-04-19 17:27:09.000000000 +1200 @@ -74,8 +74,8 @@ static int aclHostDomainCompare( char *const &a, char * const &b) { - const char *h = (const char *)a; - const char *d = (const char *)b; + const char *h = static_cast(a); + const char *d = static_cast(b); return matchDomainName(h, d); } @@ -86,8 +86,8 @@ int aclDomainCompare(T const &a, T const &b) { - char * const d1 = (char *const)b; - char * const d2 = (char *const )a; + char * const d1 = static_cast(b); + char * const d2 = static_cast(a); int ret; ret = aclHostDomainCompare(d1, d2); diff -u -r -N squid-3.1.12/src/acl/SslErrorData.cc squid-3.1.12.1/src/acl/SslErrorData.cc --- squid-3.1.12/src/acl/SslErrorData.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/acl/SslErrorData.cc 2011-04-19 17:27:09.000000000 +1200 @@ -22,7 +22,7 @@ } bool -ACLSslErrorData::match(ssl_error_t toFind) +ACLSslErrorData::match(Ssl::ssl_error_t toFind) { return values->findAndTune (toFind); } @@ -30,17 +30,17 @@ /* explicit instantiation required for some systems */ /** \cond AUTODOCS-IGNORE */ // AYJ: 2009-05-20 : Removing. clashes with template instantiation for other ACLs. -// template cbdata_type CbDataList::CBDATA_CbDataList; +// template cbdata_type CbDataList::CBDATA_CbDataList; /** \endcond */ wordlist * ACLSslErrorData::dump() { wordlist *W = NULL; - CbDataList *data = values; + CbDataList *data = values; while (data != NULL) { - wordlistAdd(&W, sslFindErrorString(data->element)); + wordlistAdd(&W, Ssl::getErrorName(data->element)); data = data->next; } @@ -50,12 +50,12 @@ void ACLSslErrorData::parse() { - CbDataList **Tail; + CbDataList **Tail; char *t = NULL; for (Tail = &values; *Tail; Tail = &((*Tail)->next)); while ((t = strtokFile())) { - CbDataList *q = new CbDataList(sslParseErrorString(t)); + CbDataList *q = new CbDataList(Ssl::parseErrorString(t)); *(Tail) = q; Tail = &q->next; } @@ -67,7 +67,7 @@ return values == NULL; } -ACLData * +ACLData * ACLSslErrorData::clone() const { /* Splay trees don't clone yet. */ diff -u -r -N squid-3.1.12/src/acl/SslErrorData.h squid-3.1.12.1/src/acl/SslErrorData.h --- squid-3.1.12/src/acl/SslErrorData.h 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/acl/SslErrorData.h 2011-04-19 17:27:09.000000000 +1200 @@ -9,8 +9,9 @@ #include "acl/Data.h" #include "CbDataList.h" #include "ssl_support.h" +#include "ssl/ErrorDetail.h" -class ACLSslErrorData : public ACLData +class ACLSslErrorData : public ACLData { public: @@ -20,13 +21,13 @@ ACLSslErrorData(ACLSslErrorData const &); ACLSslErrorData &operator= (ACLSslErrorData const &); virtual ~ACLSslErrorData(); - bool match(ssl_error_t); + bool match(Ssl::ssl_error_t); wordlist *dump(); void parse(); bool empty() const; - virtual ACLData *clone() const; + virtual ACLData *clone() const; - CbDataList *values; + CbDataList *values; }; MEMPROXY_CLASS_INLINE(ACLSslErrorData); diff -u -r -N squid-3.1.12/src/adaptation/icap/ModXact.cc squid-3.1.12.1/src/adaptation/icap/ModXact.cc --- squid-3.1.12/src/adaptation/icap/ModXact.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/adaptation/icap/ModXact.cc 2011-04-19 17:27:09.000000000 +1200 @@ -1374,8 +1374,6 @@ // we decided to do preview, now compute its size - Must(wantedSize >= 0); - // cannot preview more than we can backup size_t ad = min(wantedSize, TheBackupLimit); @@ -1622,7 +1620,6 @@ void Adaptation::Icap::VirginBodyAct::progress(size_t size) { Must(active()); - Must(size >= 0); theStart += static_cast(size); } @@ -1639,7 +1636,6 @@ void Adaptation::Icap::Preview::enable(size_t anAd) { // TODO: check for anAd not exceeding preview size limit - Must(anAd >= 0); Must(!enabled()); theAd = anAd; theState = stWriting; diff -u -r -N squid-3.1.12/src/adaptation/icap/Xaction.cc squid-3.1.12.1/src/adaptation/icap/Xaction.cc --- squid-3.1.12/src/adaptation/icap/Xaction.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/adaptation/icap/Xaction.cc 2011-04-19 17:27:09.000000000 +1200 @@ -355,7 +355,6 @@ reader = NULL; Must(io.flag == COMM_OK); - Must(io.size >= 0); if (!io.size) { commEof = true; diff -u -r -N squid-3.1.12/src/base/Makefile.am squid-3.1.12.1/src/base/Makefile.am --- squid-3.1.12/src/base/Makefile.am 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/base/Makefile.am 2011-04-19 17:27:09.000000000 +1200 @@ -12,4 +12,5 @@ AsyncJobCalls.h \ AsyncCallQueue.cc \ AsyncCallQueue.h \ - CbcPointer.h + CbcPointer.h \ + TidyPointer.h diff -u -r -N squid-3.1.12/src/base/Makefile.in squid-3.1.12.1/src/base/Makefile.in --- squid-3.1.12/src/base/Makefile.in 2011-04-04 13:24:51.000000000 +1200 +++ squid-3.1.12.1/src/base/Makefile.in 2011-04-19 17:28:07.000000000 +1200 @@ -292,7 +292,8 @@ AsyncJobCalls.h \ AsyncCallQueue.cc \ AsyncCallQueue.h \ - CbcPointer.h + CbcPointer.h \ + TidyPointer.h all: all-am diff -u -r -N squid-3.1.12/src/base/TidyPointer.h squid-3.1.12.1/src/base/TidyPointer.h --- squid-3.1.12/src/base/TidyPointer.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.1.12.1/src/base/TidyPointer.h 2011-04-19 17:27:09.000000000 +1200 @@ -0,0 +1,64 @@ +/* + * $Id$ + */ + +#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::auto_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; } + /// Returns raw and possibly NULL pointer + T *get() const { return raw; } + /// Address of the raw pointer, for pointer-setting functions + T **addr() { 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-3.1.12/src/BodyPipe.cc squid-3.1.12.1/src/BodyPipe.cc --- squid-3.1.12/src/BodyPipe.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/BodyPipe.cc 2011-04-19 17:27:09.000000000 +1200 @@ -148,7 +148,6 @@ void BodyPipe::setBodySize(uint64_t aBodySize) { assert(!bodySizeKnown()); - assert(aBodySize >= 0); assert(thePutSize <= aBodySize); // If this assert fails, we need to add code to check for eof and inform diff -u -r -N squid-3.1.12/src/cache_cf.cc squid-3.1.12.1/src/cache_cf.cc --- squid-3.1.12/src/cache_cf.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/cache_cf.cc 2011-04-19 17:27:09.000000000 +1200 @@ -57,6 +57,10 @@ #include #endif +#if HAVE_LIMITS +#include +#endif + #if SQUID_SNMP #include "snmp.h" #endif @@ -64,6 +68,11 @@ #include "esi/Parser.h" #endif +#if USE_SSL +#include "ssl/Config.h" +#include "ssl/gadgets.h" +#endif + #if USE_ADAPTATION #include "adaptation/Config.h" @@ -132,6 +141,9 @@ static void parse_obsolete(const char *); static void parseBytesLine(size_t * bptr, const char *units); static size_t parseBytesUnits(const char *unit); +#if USE_SSL +static void parseBytesOptionValue(size_t * bptr, const char *units, char const * value); +#endif static void free_all(void); void requirePathnameExists(const char *name, const char *path); static OBJH dump_config; @@ -721,7 +733,13 @@ debugs(3, 1, "Initializing http_port " << s->http.s << " SSL context"); - s->sslContext = sslCreateServerContext(s->cert, s->key, s->version, s->cipher, s->options, s->sslflags, s->clientca, s->cafile, s->capath, s->crlfile, s->dhfile, s->sslcontext); + s->staticSslContext.reset( + sslCreateServerContext(s->cert, s->key, + s->version, s->cipher, s->options, s->sslflags, s->clientca, + s->cafile, s->capath, s->crlfile, s->dhfile, + s->sslContextSessionId)); + + Ssl::readCertAndPrivateKeyFromFiles(s->signingCert, s->signPkey, s->cert, s->key); } } @@ -732,7 +750,11 @@ for (s = Config.Sockaddr.https; s != NULL; s = (https_port_list *) s->http.next) { debugs(3, 1, "Initializing https_port " << s->http.s << " SSL context"); - s->sslContext = sslCreateServerContext(s->cert, s->key, s->version, s->cipher, s->options, s->sslflags, s->clientca, s->cafile, s->capath, s->crlfile, s->dhfile, s->sslcontext); + s->staticSslContext.reset( + sslCreateServerContext(s->cert, s->key, + s->version, s->cipher, s->options, s->sslflags, s->clientca, + s->cafile, s->capath, s->crlfile, s->dhfile, + s->sslContextSessionId)); } } @@ -931,6 +953,44 @@ self_destruct(); } +#if USE_SSL +/** + * Parse bytes from a string. + * Similar to the parseBytesLine function but parses the string value instead of + * the current token value. + */ +static void parseBytesOptionValue(size_t * bptr, const char *units, char const * value) +{ + int u; + if ((u = parseBytesUnits(units)) == 0) { + self_destruct(); + return; + } + + // Find number from string beginning. + char const * number_begin = value; + char const * number_end = value; + + while ((*number_end >= '0' && *number_end <= '9')) { + number_end++; + } + + String number; + number.limitInit(number_begin, number_end - number_begin); + + int d = xatoi(number.termedBuf()); + int m; + if ((m = parseBytesUnits(number_end)) == 0) { + self_destruct(); + return; + } + + *bptr = static_cast(m * d / u); + if (static_cast(*bptr) * 2 != m * d / u * 2) + self_destruct(); +} +#endif + static size_t parseBytesUnits(const char *unit) { @@ -3191,8 +3251,16 @@ safe_free(s->sslflags); s->sslflags = xstrdup(token + 9); } else if (strncmp(token, "sslcontext=", 11) == 0) { - safe_free(s->sslcontext); - s->sslcontext = xstrdup(token + 11); + safe_free(s->sslContextSessionId); + s->sslContextSessionId = xstrdup(token + 11); + } else if (strcmp(token, "generate-host-certificates") == 0) { + s->generateHostCertificates = true; + } else if (strcmp(token, "generate-host-certificates=on") == 0) { + s->generateHostCertificates = true; + } else if (strcmp(token, "generate-host-certificates=off") == 0) { + s->generateHostCertificates = false; + } else if (strncmp(token, "dynamic_cert_mem_cache_size=", 28) == 0) { + parseBytesOptionValue(&s->dynamicCertMemCacheSize, B_BYTES_STR, token + 28); } else if (strcasecmp(token, "sslBump") == 0) { debugs(3, DBG_CRITICAL, "WARNING: '" << token << "' is deprecated " << "in http_port. Use 'ssl-bump' instead."); @@ -3269,7 +3337,7 @@ char *crlfile; char *dhfile; char *sslflags; - char *sslcontext; + char *sslContextSessionId; SSL_CTX *sslContext; #endif @@ -3415,8 +3483,14 @@ if (s->sslflags) storeAppendPrintf(e, " sslflags=%s", s->sslflags); - if (s->sslcontext) - storeAppendPrintf(e, " sslcontext=%s", s->sslcontext); + if (s->sslContextSessionId) + storeAppendPrintf(e, " sslcontext=%s", s->sslContextSessionId); + + if (s->generateHostCertificates) + storeAppendPrintf(e, " generate-host-certificates"); + + if (s->dynamicCertMemCacheSize != std::numeric_limits::max()) + storeAppendPrintf(e, "dynamic_cert_mem_cache_size=%lu%s\n", (unsigned long)s->dynamicCertMemCacheSize, B_BYTES_STR); #endif } @@ -3514,10 +3588,13 @@ } if (stat(path, &sb) < 0) { + debugs(0, DBG_CRITICAL, (opt_parse_cfg_only?"FATAL ":"") << "ERROR: " << name << " " << path << ": " << xstrerror()); + // keep going to find more issues if we are only checking the config file with "-k parse" + if (opt_parse_cfg_only) + return; + // this is fatal if it is found during startup or reconfigure if (opt_send_signal == -1 || opt_send_signal == SIGHUP) fatalf("%s %s: %s", name, path, xstrerror()); - else - fprintf(stderr, "WARNING: %s %s: %s\n", name, path, xstrerror()); } } diff -u -r -N squid-3.1.12/src/cf.data.pre squid-3.1.12.1/src/cf.data.pre --- squid-3.1.12/src/cf.data.pre 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/cf.data.pre 2011-04-19 17:27:09.000000000 +1200 @@ -1339,6 +1339,25 @@ sslcontext= SSL session ID context identifier. + generate-host-certificates[=] + Dynamically create SSL server certificates for the + destination hosts of bumped CONNECT requests.When + enabled, the cert and key options are used to sign + generated certificates. Otherwise generated + certificate will be selfsigned. + If there is CA certificate life time of generated + certificate equals lifetime of CA certificate. If + generated certificate is selfsigned lifetime is three + years. + This option is enabled by default when SslBump is used. + See the sslBump option above for more information. + + dynamic_cert_mem_cache_size=SIZE + Approximate total RAM size spent on cached generated + certificates. If set to zero, caching is disabled. The + default value is 4MB. An average XXX-bit certificate + consumes about XXX bytes of RAM. + vport Accelerator with IP based virtual host support. vport=NN As above, but uses specified port number rather @@ -1710,6 +1729,35 @@ DOC_END COMMENT_START +OPTIONS RELATING TO EXTERNAL SSL_CRTD +----------------------------------------------------------------------------- +COMMENT_END + +NAME: sslcrtd_program +TYPE: eol +IFDEF: USE_SSL_CRTD +DEFAULT: @DEFAULT_SSL_CRTD@ -s @DEFAULT_SSL_DB_DIR@ -M 4MB +LOC: Ssl::TheConfig.ssl_crtd +DOC_START + Specify the location and options of the executable for ssl_crtd process. + @DEFAULT_SSL_CRTD@ program requires -s and -M parameters + For more information use: + @DEFAULT_SSL_CRTD@ -h +DOC_END + +NAME: sslcrtd_children +TYPE: int +IFDEF: USE_SSL_CRTD +DEFAULT: 5 +LOC: Ssl::TheConfig.ssl_crtd_n_running +DOC_START + The maximum number of processes spawn to service ssl server. + The maximum this may be safely set to is 32. + + You must have at least one ssl_crtd process. +DOC_END + +COMMENT_START OPTIONS WHICH AFFECT THE NEIGHBOR SELECTION ALGORITHM ----------------------------------------------------------------------------- COMMENT_END @@ -3695,10 +3743,10 @@ DEFAULT: on LOC: Adaptation::Icap::TheConfig.icap_uses_indirect_client DOC_START - Controls whether the indirect client address - (see follow_x_forwarded_for) instead of the - direct client address is passed to an ICAP - server as "X-Client-IP". + Controls whether the indirect client IP address (instead of the direct + client IP address) is passed to adaptation services. + + See also: follow_x_forwarded_for adaptation_send_client_ip DOC_END NAME: via @@ -4475,7 +4523,7 @@ For a class 5 delay pool: -delay_parameters pool tag +delay_parameters pool tagrate The variables here are: @@ -4483,19 +4531,19 @@ number specified in delay_pools as used in delay_class lines. - aggregate the "delay parameters" for the aggregate bucket + aggregate the speed limit parameters for the aggregate bucket (class 1, 2, 3). - individual the "delay parameters" for the individual + individual the speed limit parameters for the individual buckets (class 2, 3). - network the "delay parameters" for the network buckets + network the speed limit parameters for the network buckets (class 3). - user the delay parameters for the user buckets + user the speed limit parameters for the user buckets (class 4). - tag the delay parameters for the tag buckets + tagrate the speed limit parameters for the tag buckets (class 5). A pair of delay parameters is written restore/maximum, where restore is @@ -5804,7 +5852,11 @@ LOC: Adaptation::Icap::TheConfig.send_client_ip DEFAULT: off DOC_START - This adds the header "X-Client-IP" to ICAP requests. + If enabled, Squid shares HTTP client IP information with adaptation + services. For ICAP, Squid adds the X-Client-IP header to ICAP requests. + For eCAP, Squid sets the libecap::metaClientIp transaction option. + + See also: adaptation_uses_indirect_client DOC_END NAME: icap_send_client_username diff -u -r -N squid-3.1.12/src/client_side.cc squid-3.1.12.1/src/client_side.cc --- squid-3.1.12/src/client_side.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/client_side.cc 2011-04-19 17:27:09.000000000 +1200 @@ -106,6 +106,20 @@ #include "ChunkedCodingParser.h" #include "rfc1738.h" +#if USE_SSL +#include "ssl/context_storage.h" +#include "ssl/helper.h" +#include "ssl/gadgets.h" +#endif +#if USE_SSL_CRTD +#include "ssl/crtd_message.h" +#include "ssl/certificate_db.h" +#endif + +#if HAVE_LIMITS +#include +#endif + #if LINGERING_CLOSE #define comm_close comm_lingering_close #endif @@ -966,11 +980,6 @@ } - /* - * paranoid check - */ - assert((available.size() >= 0 && i->debt() >= 0) || i->debt() == -1); - if (!canPackMoreRanges()) { debugs(33, 3, "clientPackRange: Returning because !canPackMoreRanges."); @@ -3294,7 +3303,7 @@ comm_err_t flag, int xerrno, void *data) { https_port_list *s = (https_port_list *)data; - SSL_CTX *sslContext = s->sslContext; + SSL_CTX *sslContext = s->staticSslContext.get(); if (flag == COMM_ERR_CLOSING) { return; @@ -3355,24 +3364,109 @@ incoming_sockets_accepted++; } +void +ConnStateData::sslCrtdHandleReplyWrapper(void *data, char *reply) +{ + ConnStateData * state_data = (ConnStateData *)(data); + state_data->sslCrtdHandleReply(reply); +} + +void +ConnStateData::sslCrtdHandleReply(const char * reply) +{ + if (!reply) { + debugs(1, 1, HERE << "\"ssl_crtd\" helper return reply"); + } else { + Ssl::CrtdMessage reply_message; + if (reply_message.parse(reply, strlen(reply)) != Ssl::CrtdMessage::OK) { + debugs(33, 5, HERE << "Reply from ssl_crtd for " << sslHostName << " is incorrect"); + } else { + if (reply_message.getCode() != "ok") { + debugs(33, 5, HERE << "Certificate for " << sslHostName << " cannot be generated. ssl_crtd response: " << reply_message.getBody()); + } else { + debugs(33, 5, HERE << "Certificate for " << sslHostName << " was successfully recieved from ssl_crtd"); + getSslContextDone(Ssl::generateSslContextUsingPkeyAndCertFromMemory(reply_message.getBody().c_str()), true); + return; + } + } + } + getSslContextDone(NULL); +} + bool -ConnStateData::switchToHttps() +ConnStateData::getSslContextStart() { - assert(!switchedToHttps_); + char const * host = sslHostName.termedBuf(); + if (port->generateHostCertificates && host && strcmp(host, "") != 0) { + debugs(33, 5, HERE << "Finding SSL certificate for " << host << " in cache"); + Ssl::LocalContextStorage & ssl_ctx_cache(Ssl::TheGlobalContextStorage.getLocalStorage(port->s)); + SSL_CTX * dynCtx = ssl_ctx_cache.find(host); + if (dynCtx) { + debugs(33, 5, HERE << "SSL certificate for " << host << " have found in cache"); + if (Ssl::verifySslCertificateDate(dynCtx)) { + debugs(33, 5, HERE << "Cached SSL certificate for " << host << " is valid"); + return getSslContextDone(dynCtx); + } else { + debugs(33, 5, HERE << "Cached SSL certificate for " << host << " is out of date. Delete this certificate from cache"); + ssl_ctx_cache.remove(host); + } + } else { + debugs(33, 5, HERE << "SSL certificate for " << host << " haven't found in cache"); + } - //HTTPMSGLOCK(currentobject->http->request); - assert(areAllContextsForThisConnection()); - freeAllContexts(); - //currentobject->connIsFinished(); +#ifdef USE_SSL_CRTD + debugs(33, 5, HERE << "Generating SSL certificate for " << host << " using ssl_crtd."); + Ssl::CrtdMessage request_message; + request_message.setCode(Ssl::CrtdMessage::code_new_certificate); + Ssl::CrtdMessage::BodyParams map; + map.insert(std::make_pair(Ssl::CrtdMessage::param_host, host)); + std::string bufferToWrite; + Ssl::writeCertAndPrivateKeyToMemory(port->signingCert, port->signPkey, bufferToWrite); + request_message.composeBody(map, bufferToWrite); + Ssl::Helper::GetInstance()->sslSubmit(request_message, sslCrtdHandleReplyWrapper, this); + return true; +#else + debugs(33, 5, HERE << "Generating SSL certificate for " << host); + dynCtx = Ssl::generateSslContext(host, port->signingCert, port->signPkey); + return getSslContextDone(dynCtx, true); +#endif //USE_SSL_CRTD + } + return getSslContextDone(NULL); +} - debugs(33, 5, HERE << "converting FD " << fd << " to SSL"); +bool +ConnStateData::getSslContextDone(SSL_CTX * sslContext, bool isNew) +{ + // Try to add generated ssl context to storage. + if (port->generateHostCertificates && isNew) { + Ssl::LocalContextStorage & ssl_ctx_cache(Ssl::TheGlobalContextStorage.getLocalStorage(port->s)); + if (sslContext && sslHostName != "") { + if (!ssl_ctx_cache.add(sslHostName.termedBuf(), sslContext)) { + // If it is not in storage delete after using. Else storage deleted it. + fd_table[fd].dynamicSslContext = sslContext; + } + } else { + debugs(33, 2, HERE << "Failed to generate SSL cert for " << sslHostName); + } + } + + // If generated ssl context = NULL, try to use static ssl context. + if (!sslContext) { + if (!port->staticSslContext) { + debugs(83, 1, "Closing SSL FD " << fd << " as lacking SSL context"); + comm_close(fd); + return false; + } else { + debugs(33, 5, HERE << "Using static ssl context."); + sslContext = port->staticSslContext.get(); + } + } // fake a ConnectionDetail object; XXX: make ConnState a ConnectionDetail? ConnectionDetail detail; detail.me = me; detail.peer = peer; - SSL_CTX *sslContext = port->sslContext; SSL *ssl = NULL; if (!(ssl = httpsCreate(fd, &detail, sslContext))) return false; @@ -3388,6 +3482,23 @@ return true; } +bool +ConnStateData::switchToHttps(const char *host) +{ + assert(!switchedToHttps_); + + sslHostName = host; + + //HTTPMSGLOCK(currentobject->http->request); + assert(areAllContextsForThisConnection()); + freeAllContexts(); + //currentobject->connIsFinished(); + + debugs(33, 5, HERE << "converting FD " << fd << " to SSL"); + + return getSslContextStart(); +} + #endif /* USE_SSL */ @@ -3408,14 +3519,21 @@ } #if USE_SSL - if (s->sslBump && s->sslContext == NULL) { + if (s->sslBump && + !s->staticSslContext && !s->generateHostCertificates) { debugs(1, 1, "Will not bump SSL at http_port " << s->http.s << " due to SSL initialization failure."); s->sslBump = 0; } - if (s->sslBump) + if (s->sslBump) { ++bumpCount; + // Create ssl_ctx cache for this port. + Ssl::TheGlobalContextStorage.addLocalStorage(s->s, s->dynamicCertMemCacheSize == std::numeric_limits::max() ? 4194304 : s->dynamicCertMemCacheSize); + } #endif +#if USE_SSL_CRTD + Ssl::Helper::GetInstance(); +#endif //USE_SSL_CRTD enter_suid(); @@ -3467,7 +3585,7 @@ continue; } - if (s->sslContext == NULL) { + if (!s->staticSslContext) { debugs(1, 1, "Ignoring https_port " << s->http.s << " due to SSL initialization failure."); continue; @@ -3615,7 +3733,7 @@ CBDATA_CLASS_INIT(ConnStateData); -ConnStateData::ConnStateData() :AsyncJob("ConnStateData"), transparent_ (false), closing_ (false) +ConnStateData::ConnStateData() :AsyncJob("ConnStateData"), transparent_ (false), closing_ (false), switchedToHttps_(false) { pinning.fd = -1; pinning.pinned = false; diff -u -r -N squid-3.1.12/src/client_side.h squid-3.1.12.1/src/client_side.h --- squid-3.1.12/src/client_side.h 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/client_side.h 2011-04-19 17:27:09.000000000 +1200 @@ -259,7 +259,20 @@ virtual void swanSong(); #if USE_SSL - bool switchToHttps(); + /// Start to create dynamic SSL_CTX for host or uses static port SSL context. + bool getSslContextStart(); + /** + * Done create dynamic ssl certificate. + * + * \param[in] isNew if generated certificate is new, so we need to add this certificate to storage. + */ + bool getSslContextDone(SSL_CTX * sslContext, bool isNew = false); + /// Callback function. It is called when squid receive message from ssl_crtd. + static void sslCrtdHandleReplyWrapper(void *data, char *reply); + /// Proccess response from ssl_crtd. + void sslCrtdHandleReply(const char * reply); + + bool switchToHttps(const char *host); bool switchedToHttps() const { return switchedToHttps_; } #else bool switchedToHttps() const { return false; } @@ -282,6 +295,7 @@ bool closing_; bool switchedToHttps_; + String sslHostName; ///< Host name for SSL certificate generation AsyncCall::Pointer reader; ///< set when we are reading BodyPipe::Pointer bodyPipe; // set when we are reading request body }; diff -u -r -N squid-3.1.12/src/client_side_request.cc squid-3.1.12.1/src/client_side_request.cc --- squid-3.1.12/src/client_side_request.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/client_side_request.cc 2011-04-19 17:27:09.000000000 +1200 @@ -1183,7 +1183,7 @@ return; } - getConn()->switchToHttps(); + getConn()->switchToHttps(request->GetHost()); } void diff -u -r -N squid-3.1.12/src/client_side_request.cci squid-3.1.12.1/src/client_side_request.cci --- squid-3.1.12/src/client_side_request.cci 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/client_side_request.cci 2011-04-19 17:27:09.000000000 +1200 @@ -50,15 +50,6 @@ } ConnStateData * -ClientHttpRequest::getConn() -{ - if (!cbdataReferenceValid(conn_)) - return NULL; - - return conn_; -} - -ConnStateData * const ClientHttpRequest::getConn() const { if (!cbdataReferenceValid(conn_)) diff -u -r -N squid-3.1.12/src/client_side_request.h squid-3.1.12.1/src/client_side_request.h --- squid-3.1.12/src/client_side_request.h 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/client_side_request.h 2011-04-19 17:27:09.000000000 +1200 @@ -93,8 +93,7 @@ _SQUID_INLINE_ StoreEntry *loggingEntry() const; void loggingEntry(StoreEntry *); - _SQUID_INLINE_ ConnStateData * getConn(); - _SQUID_INLINE_ ConnStateData * const getConn() const; + _SQUID_INLINE_ ConnStateData * getConn() const; _SQUID_INLINE_ void setConn(ConnStateData *); HttpRequest *request; /* Parsed URL ... */ char *uri; diff -u -r -N squid-3.1.12/src/comm.cc squid-3.1.12.1/src/comm.cc --- squid-3.1.12/src/comm.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/comm.cc 2011-04-19 17:27:09.000000000 +1200 @@ -1550,6 +1550,10 @@ F->ssl = NULL; } + if (F->dynamicSslContext) { + SSL_CTX_free(F->dynamicSslContext); + F->dynamicSslContext = NULL; + } #endif fd_close(fd); /* update fdstat */ diff -u -r -N squid-3.1.12/src/comm_poll.cc squid-3.1.12.1/src/comm_poll.cc --- squid-3.1.12/src/comm_poll.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/comm_poll.cc 2011-04-19 17:27:09.000000000 +1200 @@ -402,7 +402,7 @@ * Note that this will only ever trigger when there are no log files * and stdout/err/in are all closed too. */ - if (nfds == 0 && !npending) { + if (nfds == 0 && npending == 0) { if (shutting_down) return COMM_SHUTDOWN; else @@ -416,7 +416,7 @@ ++statCounter.select_loops; PROF_stop(comm_poll_normal); - if (num >= 0 || npending >= 0) + if (num >= 0 || npending > 0) break; if (ignoreErrno(errno)) diff -u -r -N squid-3.1.12/src/DiskIO/AIO/async_io.h squid-3.1.12.1/src/DiskIO/AIO/async_io.h --- squid-3.1.12/src/DiskIO/AIO/async_io.h 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/DiskIO/AIO/async_io.h 2011-04-19 17:27:09.000000000 +1200 @@ -34,7 +34,6 @@ AQ_ENTRY_WRITE } async_queue_entry_type_t; - typedef struct _async_queue_entry async_queue_entry_t; typedef struct _async_queue async_queue_t; @@ -47,7 +46,12 @@ async_queue_entry_state_t aq_e_state; async_queue_entry_type_t aq_e_type; + /* 64-bit environments with non-GCC complain about the type mismatch on Linux */ +#if defined(__USE_FILE_OFFSET64) && !defined(__GNUC__) + struct aiocb64 aq_e_aiocb; +#else struct aiocb aq_e_aiocb; +#endif AIODiskFile *theFile; void *aq_e_callback_data; FREE *aq_e_free; diff -u -r -N squid-3.1.12/src/dns_internal.cc squid-3.1.12.1/src/dns_internal.cc --- squid-3.1.12/src/dns_internal.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/dns_internal.cc 2011-04-19 17:27:09.000000000 +1200 @@ -1574,13 +1574,11 @@ ", id = 0x" << std::hex << q->id); q->callback = callback; - q->callback_data = cbdataReference(data); q->start_t = current_time; idnsCacheQuery(q); - idnsSendQuery(q); } @@ -1626,13 +1624,11 @@ ", id = 0x" << std::hex << q->id); q->callback = callback; - q->callback_data = cbdataReference(data); q->start_t = current_time; idnsCacheQuery(q); - idnsSendQuery(q); } diff -u -r -N squid-3.1.12/src/errorpage.cc squid-3.1.12.1/src/errorpage.cc --- squid-3.1.12/src/errorpage.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/errorpage.cc 2011-04-19 17:27:09.000000000 +1200 @@ -508,6 +508,9 @@ if (err->err_language != Config.errorDefaultLanguage) #endif safe_free(err->err_language); +#if USE_SSL + delete err->detail; +#endif cbdataFree(err); } @@ -597,7 +600,7 @@ #define CVT_BUF_SZ 512 const char * -ErrorState::Convert(char token) +ErrorState::Convert(char token, bool allowRecursion) { static MemBuf mb; const char *p = NULL; /* takes priority over mb if set */ @@ -628,6 +631,25 @@ break; + case 'D': + if (!allowRecursion) + p = "%D"; // if recursion is not allowed, do not convert +#if USE_SSL + // currently only SSL error details implemented + else if (detail) { + const String &errDetail = detail->toString(); + if (errDetail.defined()) { + MemBuf *detail_mb = ConvertText(errDetail.termedBuf(), false); + mb.append(detail_mb->content(), detail_mb->contentSize()); + delete detail_mb; + do_quote = 0; + } + } +#endif + if (!mb.contentSize()) + mb.Printf("[No Error Detail]"); + break; + case 'e': mb.Printf("%d", xerrno); @@ -929,10 +951,7 @@ MemBuf * ErrorState::BuildContent() { - MemBuf *content = new MemBuf; const char *m = NULL; - const char *p; - const char *t; assert(page_id > ERR_NONE && page_id < error_page_count); @@ -1051,12 +1070,25 @@ debugs(4, 2, HERE << "No existing error page language negotiated for " << errorPageName(page_id) << ". Using default error file."); } + MemBuf *result = ConvertText(m, true); +#if USE_ERR_LOCALES + safe_free(freePage); +#endif + + return result; +} + +MemBuf *ErrorState::ConvertText(const char *text, bool allowRecursion) +{ + MemBuf *content = new MemBuf; + const char *p; + const char *m = text; assert(m); content->init(); while ((p = strchr(m, '%'))) { content->append(m, p - m); /* copy */ - t = Convert(*++p); /* convert */ + const char *t = Convert(*++p, allowRecursion); /* convert */ content->Printf("%s", t); /* copy */ m = p + 1; /* advance */ } @@ -1066,9 +1098,5 @@ assert((size_t)content->contentSize() == strlen(content->content())); -#if USE_ERR_LOCALES - safe_free(freePage); -#endif - return content; } diff -u -r -N squid-3.1.12/src/errorpage.h squid-3.1.12.1/src/errorpage.h --- squid-3.1.12/src/errorpage.h 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/errorpage.h 2011-04-19 17:27:09.000000000 +1200 @@ -37,6 +37,9 @@ #include "squid.h" #include "cbdata.h" #include "ip/IpAddress.h" +#if USE_SSL +#include "ssl/ErrorDetail.h" +#endif /** \defgroup ErrorPageAPI Error Pages API @@ -48,6 +51,7 @@ B - URL with FTP %2f hack x c - Squid error code x d - seconds elapsed since request received x + D - Error details x e - errno x E - strerror() x f - FTP request line x @@ -99,9 +103,18 @@ MemBuf *BuildContent(void); /** + * Convert the given template string into textual output + * + * \param text The string to be converted + * \param allowRecursion Whether to convert codes which output may contain codes + */ + MemBuf *ConvertText(const char *text, bool allowRecursion); + + /** * Convert an error template into an error page. + * \ allowRecursion True if the codes which do recursions should converted */ - const char *Convert(char token); + const char *Convert(char token, bool allowRecursion); /** * CacheManager / Debug dump of the ErrorState object. @@ -141,6 +154,9 @@ char *request_hdrs; char *err_msg; /* Preformatted error message from the cache */ +#if USE_SSL + Ssl::ErrorDetail *detail; +#endif private: CBDATA_CLASS2(ErrorState); }; diff -u -r -N squid-3.1.12/src/fde.h squid-3.1.12.1/src/fde.h --- squid-3.1.12/src/fde.h 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/fde.h 2011-04-19 17:27:09.000000000 +1200 @@ -102,6 +102,7 @@ WRITE_HANDLER *write_method; #if USE_SSL SSL *ssl; + SSL_CTX *dynamicSslContext; ///< cached and then freed when fd is closed #endif #ifdef _SQUID_MSWIN_ struct { diff -u -r -N squid-3.1.12/src/forward.cc squid-3.1.12.1/src/forward.cc --- squid-3.1.12/src/forward.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/forward.cc 2011-04-19 17:27:09.000000000 +1200 @@ -48,6 +48,10 @@ #include "icmp/net_db.h" #include "ip/IpIntercept.h" #include "ip/tools.h" +#if USE_SSL +#include "ssl_support.h" +#include "ssl/ErrorDetail.h" +#endif static PSC fwdStartCompleteWrapper; static PF fwdServerClosedWrapper; @@ -605,6 +609,14 @@ anErr->xerrno = EACCES; #endif + 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); + } + fail(anErr); if (fs->_peer) { diff -u -r -N squid-3.1.12/src/fs/ufs/store_dir_ufs.cc squid-3.1.12.1/src/fs/ufs/store_dir_ufs.cc --- squid-3.1.12/src/fs/ufs/store_dir_ufs.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/fs/ufs/store_dir_ufs.cc 2011-04-19 17:27:09.000000000 +1200 @@ -1063,7 +1063,6 @@ { DIR *dir_pointer = NULL; - struct dirent *de = NULL; LOCAL_ARRAY(char, p1, MAXPATHLEN + 1); LOCAL_ARRAY(char, p2, MAXPATHLEN + 1); @@ -1107,6 +1106,7 @@ return 0; } + dirent_t *de; while ((de = readdir(dir_pointer)) != NULL && k < 20) { if (sscanf(de->d_name, "%X", &swapfileno) != 1) continue; diff -u -r -N squid-3.1.12/src/fs/ufs/ufscommon.h squid-3.1.12.1/src/fs/ufs/ufscommon.h --- squid-3.1.12/src/fs/ufs/ufscommon.h 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/fs/ufs/ufscommon.h 2011-04-19 17:27:09.000000000 +1200 @@ -399,7 +399,7 @@ int done; int fn; - struct dirent *entry; + dirent_t *entry; DIR *td; char fullpath[SQUID_MAXPATHLEN]; char fullfilename[SQUID_MAXPATHLEN]; diff -u -r -N squid-3.1.12/src/ftp.cc squid-3.1.12.1/src/ftp.cc --- squid-3.1.12/src/ftp.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/ftp.cc 2011-04-19 17:27:09.000000000 +1200 @@ -1362,7 +1362,7 @@ IOStats.Ftp.read_hist[bin]++; } - if (io.flag != COMM_OK || io.size < 0) { + if (io.flag != COMM_OK) { debugs(50, ignoreErrno(io.xerrno) ? 3 : DBG_IMPORTANT, "ftpDataRead: read error: " << xstrerr(io.xerrno)); @@ -1859,7 +1859,7 @@ fd_bytes(io.fd, io.size, FD_READ); } - if (io.flag != COMM_OK || io.size < 0) { + if (io.flag != COMM_OK) { debugs(50, ignoreErrno(io.xerrno) ? 3 : DBG_IMPORTANT, "ftpReadControlReply: read error: " << xstrerr(io.xerrno)); @@ -1868,9 +1868,7 @@ } else { failed(ERR_READ_ERROR, io.xerrno); /* failed closes ctrl.fd and frees ftpState */ - return; } - return; } diff -u -r -N squid-3.1.12/src/globals.h squid-3.1.12.1/src/globals.h --- squid-3.1.12/src/globals.h 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/globals.h 2011-04-19 17:27:09.000000000 +1200 @@ -172,6 +172,7 @@ extern int ssl_ex_index_server; /* -1 */ extern int ssl_ctx_ex_index_dont_verify_domain; /* -1 */ extern int ssl_ex_index_cert_error_check; /* -1 */ + extern int ssl_ex_index_ssl_error_detail; /* -1 */ extern const char *external_acl_message; /* NULL */ extern int opt_send_signal; /* -1 */ diff -u -r -N squid-3.1.12/src/helper.cc squid-3.1.12.1/src/helper.cc --- squid-3.1.12/src/helper.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/helper.cc 2011-04-19 17:27:09.000000000 +1200 @@ -838,6 +838,55 @@ cbdataFree(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_request *r = srv->requests[request_number]; + if (r) { + HLPCB *callback = r->callback; + + srv->requests[request_number] = NULL; + + r->callback = NULL; + + void *cbdata = NULL; + if (cbdataReferenceValidDone(r->data, &cbdata)) + callback(cbdata, msg); + + srv->stats.pending--; + + hlp->stats.replies++; + + srv->answer_time = current_time; + + srv->dispatch_time = r->dispatch_time; + + hlp->stats.avg_svc_time = + Math::intAverage(hlp->stats.avg_svc_time, + tvSubMsec(r->dispatch_time, current_time), + hlp->stats.replies, REDIRECT_AV_FACTOR); + + helperRequestFree(r); + } else { + debugs(84, 1, "helperHandleRead: unexpected reply on channel " << + request_number << " from " << hlp->id_name << " #" << srv->index + 1 << + " '" << srv->rbuf << "'"); + } + srv->roffset -= (msg_end - srv->rbuf); + memmove(srv->rbuf, msg_end, srv->roffset + 1); + + if (!srv->flags.shutdown) { + helperKickQueue(hlp); + } else if (!srv->flags.closing && !srv->stats.pending) { + int wfd = srv->wfd; + srv->wfd = -1; + if (srv->rfd == wfd) + srv->rfd = -1; + srv->flags.closing=1; + comm_close(wfd); + return; + } +} static void helperHandleRead(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data) @@ -857,12 +906,8 @@ debugs(84, 5, "helperHandleRead: " << len << " bytes from " << hlp->id_name << " #" << srv->index + 1); - if (flag != COMM_OK || len <= 0) { - if (len < 0) - debugs(84, 1, "helperHandleRead: FD " << fd << " read: " << xstrerror()); - + if (flag != COMM_OK || len == 0) { comm_close(fd); - return; } @@ -880,69 +925,29 @@ srv->rbuf[0] = '\0'; } - while ((t = strchr(srv->rbuf, '\n'))) { - /* end of reply found */ - helper_request *r; - char *msg = srv->rbuf; - int i = 0; - debugs(84, 3, "helperHandleRead: end of reply found"); - - if (t > srv->rbuf && t[-1] == '\r') - t[-1] = '\0'; - - *t++ = '\0'; - - if (hlp->concurrency) { - i = strtol(msg, &msg, 10); + if (hlp->return_full_reply) { + debugs(84, 3, HERE << "Return entire buffer"); + helperReturnBuffer(0, srv, hlp, srv->rbuf, srv->rbuf + srv->roffset); + } else { + while ((t = strchr(srv->rbuf, '\n'))) { + /* end of reply found */ + char *msg = srv->rbuf; + int i = 0; + debugs(84, 3, "helperHandleRead: end of reply found"); + + if (t > srv->rbuf && t[-1] == '\r') + t[-1] = '\0'; + + *t++ = '\0'; + + if (hlp->concurrency) { + i = strtol(msg, &msg, 10); + + while (*msg && xisspace(*msg)) + msg++; + } - while (*msg && xisspace(*msg)) - msg++; - } - - r = srv->requests[i]; - - if (r) { - HLPCB *callback = r->callback; - void *cbdata; - - srv->requests[i] = NULL; - - r->callback = NULL; - - if (cbdataReferenceValidDone(r->data, &cbdata)) - callback(cbdata, msg); - - srv->stats.pending--; - - hlp->stats.replies++; - - srv->answer_time = current_time; - - srv->dispatch_time = r->dispatch_time; - - hlp->stats.avg_svc_time = Math::intAverage(hlp->stats.avg_svc_time, tvSubMsec(r->dispatch_time, current_time), hlp->stats.replies, REDIRECT_AV_FACTOR); - - helperRequestFree(r); - } else { - debugs(84, 1, "helperHandleRead: unexpected reply on channel " << - i << " from " << hlp->id_name << " #" << srv->index + 1 << - " '" << srv->rbuf << "'"); - - } - - srv->roffset -= (t - srv->rbuf); - memmove(srv->rbuf, t, srv->roffset + 1); - - if (!srv->flags.shutdown) { - helperKickQueue(hlp); - } else if (!srv->flags.closing && !srv->stats.pending) { - int wfd = srv->wfd; - srv->wfd = -1; - if (srv->rfd == wfd) - srv->rfd = -1; - srv->flags.closing=1; - comm_close(wfd); - return; + helperReturnBuffer(i, srv, hlp, msg, t); } } @@ -971,12 +976,8 @@ hlp->id_name << " #" << srv->index + 1); - if (flag != COMM_OK || len <= 0) { - if (len < 0) - debugs(84, 1, "helperStatefulHandleRead: FD " << fd << " read: " << xstrerror()); - + if (flag != COMM_OK || len == 0) { comm_close(fd); - return; } diff -u -r -N squid-3.1.12/src/helper.h squid-3.1.12.1/src/helper.h --- squid-3.1.12/src/helper.h 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/helper.h 2011-04-19 17:27:09.000000000 +1200 @@ -73,6 +73,8 @@ int queue_size; int avg_svc_time; } stats; + /// True if callback expects the whole helper output, as a c-string. + bool return_full_reply; }; struct _helper_stateful { diff -u -r -N squid-3.1.12/src/htcp.h squid-3.1.12.1/src/htcp.h --- squid-3.1.12/src/htcp.h 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/htcp.h 2011-04-19 17:27:09.000000000 +1200 @@ -33,6 +33,7 @@ #if USE_HTCP #include "HttpHeader.h" +#include "typedefs.h" class IpAddress; diff -u -r -N squid-3.1.12/src/HttpHeader.cc squid-3.1.12.1/src/HttpHeader.cc --- squid-3.1.12/src/HttpHeader.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/HttpHeader.cc 2011-04-19 17:27:09.000000000 +1200 @@ -1715,15 +1715,14 @@ http_hdr_type httpHeaderIdByName(const char *name, size_t name_len, const HttpHeaderFieldInfo * info, int end) { - int i; + if (name_len > 0) { + for (int i = 0; i < end; ++i) { + if (name_len != info[i].name.size()) + continue; - for (i = 0; i < end; ++i) { - if (name_len >= 0 && name_len != info[i].name.size()) - continue; - - if (!strncasecmp(name, info[i].name.termedBuf(), - name_len < 0 ? info[i].name.size() + 1 : name_len)) - return info[i].id; + if (!strncasecmp(name, info[i].name.termedBuf(), name_len)) + return info[i].id; + } } return HDR_BAD_HDR; diff -u -r -N squid-3.1.12/src/HttpRequest.h squid-3.1.12.1/src/HttpRequest.h --- squid-3.1.12/src/HttpRequest.h 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/HttpRequest.h 2011-04-19 17:27:09.000000000 +1200 @@ -104,7 +104,7 @@ } }; inline const char* GetHost(void) const { return host; }; - inline const int GetHostIsNumeric(void) const { return host_is_numeric; }; + inline int GetHostIsNumeric(void) const { return host_is_numeric; }; #if USE_ADAPTATION /// Returns possibly nil history, creating it if adapt. logging is enabled diff -u -r -N squid-3.1.12/src/HttpRequestMethod.h squid-3.1.12.1/src/HttpRequestMethod.h --- squid-3.1.12/src/HttpRequestMethod.h 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/HttpRequestMethod.h 2011-04-19 17:27:09.000000000 +1200 @@ -137,10 +137,10 @@ \retval METHOD_OTHER the method is not recognized and has no unique ID \retval * the method is on of the recognized HTTP methods. */ - _method_t const id() const { return theMethod; } + _method_t id() const { return theMethod; } /** Get a char string representation of the method. */ - char const* image() const; + char const * image() const; bool isCacheble() const; bool purgesOthers() const; diff -u -r -N squid-3.1.12/src/ip/IpAddress.cc squid-3.1.12.1/src/ip/IpAddress.cc --- squid-3.1.12/src/ip/IpAddress.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/ip/IpAddress.cc 2011-04-19 17:27:09.000000000 +1200 @@ -773,7 +773,7 @@ /* some external code may have blindly memset a parent. */ /* thats okay, our default is known */ if ( IsAnyAddr() ) { - memcpy(buf,"::\0", min((const unsigned int)3,blen)); + memcpy(buf,"::\0", min(static_cast(3),blen)); return buf; } @@ -783,7 +783,7 @@ /* However IPv4 CAN. */ if ( force == AF_INET && !IsIPv4() ) { if ( IsIPv6() ) { - memcpy(buf, "{!IPv4}\0", min((const unsigned int)8,blen)); + memcpy(buf, "{!IPv4}\0", min(static_cast(8),blen)); } return buf; } @@ -802,7 +802,7 @@ force << "). accepted={" << AF_UNSPEC << "," << AF_INET << "," << AF_INET6 << "}"); fprintf(stderr,"WARNING: Corrupt IP Address details OR required to display in unknown format (%d). accepted={%d,%d,%d} ", force, AF_UNSPEC, AF_INET, AF_INET6); - memcpy(buf,"dead:beef::\0", min((const unsigned int)13,blen)); + memcpy(buf,"dead:beef::\0", min(static_cast(13),blen)); assert(false); } diff -u -r -N squid-3.1.12/src/LeakFinder.h squid-3.1.12.1/src/LeakFinder.h --- squid-3.1.12/src/LeakFinder.h 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/LeakFinder.h 2011-04-19 17:27:09.000000000 +1200 @@ -1,10 +1,10 @@ - - - #ifndef SQUID_LEAKFINDER_H #define SQUID_LEAKFINDER_H #if USE_LEAKFINDER + +#include "hash.h" + #define leakAdd(p,l) if (l) l->add(p,__FILE__,__LINE__) #define leakTouch(p,l) if (l) l->touch(p,__FILE__,__LINE__) #define leakFree(p,l) if (l) l->free(p,__FILE__,__LINE__) diff -u -r -N squid-3.1.12/src/main.cc squid-3.1.12.1/src/main.cc --- squid-3.1.12/src/main.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/main.cc 2011-04-19 17:27:09.000000000 +1200 @@ -80,6 +80,15 @@ #include "LoadableModules.h" #endif +#if USE_SSL_CRTD +#include "ssl/helper.h" +#include "ssl/certificate_db.h" +#endif + +#if USE_SSL +#include "ssl/context_storage.h" +#endif + #if ICAP_CLIENT #include "adaptation/icap/Config.h" #endif @@ -691,7 +700,12 @@ idnsShutdown(); #endif - +#if USE_SSL_CRTD + Ssl::Helper::GetInstance()->Shutdown(); +#endif +#if USE_SSL + Ssl::TheGlobalContextStorage.reconfigureStart(); +#endif redirectShutdown(); authenticateShutdown(); externalAclShutdown(); @@ -767,6 +781,9 @@ idnsInit(); #endif +#if USE_SSL_CRTD + Ssl::Helper::GetInstance()->Init(); +#endif redirectInit(); authenticateInit(&Config.authConfiguration); @@ -1701,7 +1718,9 @@ idnsShutdown(); #endif - +#if USE_SSL_CRTD + Ssl::Helper::GetInstance()->Shutdown(); +#endif redirectShutdown(); externalAclShutdown(); icpConnectionClose(); diff -u -r -N squid-3.1.12/src/Makefile.am squid-3.1.12.1/src/Makefile.am --- squid-3.1.12/src/Makefile.am 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/Makefile.am 2011-04-19 17:27:09.000000000 +1200 @@ -112,8 +112,13 @@ if ENABLE_SSL SSL_SOURCE = $(SSL_ALL_SOURCE) +SUBDIRS += ssl +SSL_LIBS = \ + ssl/libsslutil.la \ + ssl/libsslsquid.la else SSL_SOURCE = +SSL_LIBS = endif WIN32_ALL_SOURCE = \ @@ -531,6 +536,7 @@ ${ADAPTATION_LIBS} \ $(ESI_LIBS) \ $(SSLLIB) \ + $(SSL_LIBS) \ -lmiscutil \ $(EPOLL_LIBS) \ $(MINGW_LIBS) \ @@ -715,6 +721,7 @@ DEFAULT_CONFIG_FILE = $(DEFAULT_CONFIG_DIR)/squid.conf DEFAULT_MIME_TABLE = $(DEFAULT_CONFIG_DIR)/mime.conf DEFAULT_DNSSERVER = $(libexecdir)/`echo dnsserver | sed '$(transform);s/$$/$(EXEEXT)/'` +DEFAULT_SSL_CRTD = $(libexecdir)/`echo ssl_crtd | sed '$(transform);s/$$/$(EXEEXT)/'` DEFAULT_LOG_PREFIX = $(DEFAULT_LOG_DIR) DEFAULT_CACHE_LOG = $(DEFAULT_LOG_PREFIX)/cache.log DEFAULT_ACCESS_LOG = $(DEFAULT_LOG_PREFIX)/access.log @@ -722,6 +729,7 @@ DEFAULT_PID_FILE = $(DEFAULT_PIDFILE) DEFAULT_NETDB_FILE = $(DEFAULT_LOG_PREFIX)/netdb.state DEFAULT_SWAP_DIR = $(localstatedir)/cache +DEFAULT_SSL_DB_DIR = $(localstatedir)/lib/ssl_db DEFAULT_PINGER = $(libexecdir)/`echo pinger | sed '$(transform);s/$$/$(EXEEXT)/'` DEFAULT_UNLINKD = $(libexecdir)/`echo unlinkd | sed '$(transform);s/$$/$(EXEEXT)/'` DEFAULT_DISKD = $(libexecdir)/`echo diskd | sed '$(transform);s/$$/$(EXEEXT)/'` @@ -769,6 +777,7 @@ -e "s%[@]DEFAULT_CACHE_EFFECTIVE_USER[@]%${CACHE_EFFECTIVE_USER}%g" \ -e "s%[@]DEFAULT_MIME_TABLE[@]%$(DEFAULT_MIME_TABLE)%g" \ -e "s%[@]DEFAULT_DNSSERVER[@]%$(DEFAULT_DNSSERVER)%g" \ + -e "s%[@]DEFAULT_SSL_CRTD[@]%$(DEFAULT_SSL_CRTD)%g" \ -e "s%[@]DEFAULT_UNLINKD[@]%$(DEFAULT_UNLINKD)%g" \ -e "s%[@]DEFAULT_PINGER[@]%$(DEFAULT_PINGER)%g" \ -e "s%[@]DEFAULT_DISKD[@]%$(DEFAULT_DISKD)%g" \ @@ -778,6 +787,7 @@ -e "s%[@]DEFAULT_PID_FILE[@]%$(DEFAULT_PID_FILE)%g" \ -e "s%[@]DEFAULT_NETDB_FILE[@]%$(DEFAULT_NETDB_FILE)%g" \ -e "s%[@]DEFAULT_SWAP_DIR[@]%$(DEFAULT_SWAP_DIR)%g" \ + -e "s%[@]DEFAULT_SSL_DB_DIR[@]%$(DEFAULT_SSL_DB_DIR)%g" \ -e "s%[@]DEFAULT_ICON_DIR[@]%$(DEFAULT_ICON_DIR)%g" \ -e "s%[@]DEFAULT_CONFIG_DIR[@]%$(DEFAULT_CONFIG_DIR)%g" \ -e "s%[@]DEFAULT_PREFIX[@]%$(DEFAULT_PREFIX)%g" \ @@ -1195,6 +1205,7 @@ $(SQUID_CPPUNIT_LIBS) \ $(SQUID_CPPUNIT_LA) \ $(SSLLIB) \ + $(SSL_LIBS) \ $(XTRA_LIBS) tests_testCacheManager_LDFLAGS = $(LIBADD_DL) tests_testCacheManager_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a \ @@ -1370,6 +1381,7 @@ $(SQUID_CPPUNIT_LIBS) \ $(SQUID_CPPUNIT_LA) \ $(SSLLIB) \ + $(SSL_LIBS) \ $(XTRA_LIBS) tests_testEvent_LDFLAGS = $(LIBADD_DL) tests_testEvent_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a \ @@ -1520,6 +1532,7 @@ $(SQUID_CPPUNIT_LIBS) \ $(SQUID_CPPUNIT_LA) \ $(SSLLIB) \ + $(SSL_LIBS) \ $(XTRA_LIBS) tests_testEventLoop_LDFLAGS = $(LIBADD_DL) tests_testEventLoop_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a \ @@ -1665,6 +1678,7 @@ $(SQUID_CPPUNIT_LIBS) \ $(SQUID_CPPUNIT_LA) \ $(SSLLIB) \ + $(SSL_LIBS) \ $(XTRA_LIBS) tests_test_http_range_LDFLAGS = $(LIBADD_DL) tests_test_http_range_DEPENDENCIES = \ @@ -1815,6 +1829,7 @@ $(SQUID_CPPUNIT_LIBS) \ $(SQUID_CPPUNIT_LA) \ $(SSLLIB) \ + $(SSL_LIBS) \ $(XTRA_LIBS) tests_testHttpRequest_LDFLAGS = $(LIBADD_DL) tests_testHttpRequest_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a \ @@ -2177,6 +2192,7 @@ $(SQUID_CPPUNIT_LIBS) \ $(SQUID_CPPUNIT_LA) \ $(SSLLIB) \ + $(SSL_LIBS) \ $(XTRA_LIBS) tests_testURL_LDFLAGS = $(LIBADD_DL) tests_testURL_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a \ diff -u -r -N squid-3.1.12/src/Makefile.in squid-3.1.12.1/src/Makefile.in --- squid-3.1.12/src/Makefile.in 2011-04-04 13:24:50.000000000 +1200 +++ squid-3.1.12.1/src/Makefile.in 2011-04-19 17:28:05.000000000 +1200 @@ -57,6 +57,7 @@ @USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) @USE_ADAPTATION_TRUE@am__append_2 = adaptation @USE_ESI_TRUE@am__append_3 = esi +@ENABLE_SSL_TRUE@am__append_4 = ssl EXTRA_PROGRAMS = DiskIO/DiskDaemon/diskd$(EXEEXT) unlinkd$(EXEEXT) \ dnsserver$(EXEEXT) recv-announce$(EXEEXT) \ tests/testUfs$(EXEEXT) tests/testCoss$(EXEEXT) \ @@ -65,8 +66,8 @@ sbin_PROGRAMS = squid$(EXEEXT) bin_PROGRAMS = libexec_PROGRAMS = $(am__EXEEXT_1) $(DISK_PROGRAMS) $(am__EXEEXT_2) -@USE_LOADABLE_MODULES_TRUE@am__append_4 = $(LOADABLE_MODULES_SOURCES) -@USE_LOADABLE_MODULES_TRUE@am__append_5 = \ +@USE_LOADABLE_MODULES_TRUE@am__append_5 = $(LOADABLE_MODULES_SOURCES) +@USE_LOADABLE_MODULES_TRUE@am__append_6 = \ @USE_LOADABLE_MODULES_TRUE@ $(LIBLTDL) subdir = src @@ -332,7 +333,9 @@ squid_OBJECTS = $(am_squid_OBJECTS) $(nodist_squid_OBJECTS) @USE_ESI_TRUE@am__DEPENDENCIES_2 = $(ESI_LOCAL_LIBS) \ @USE_ESI_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) -@USE_LOADABLE_MODULES_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1) +@ENABLE_SSL_TRUE@am__DEPENDENCIES_3 = ssl/libsslutil.la \ +@ENABLE_SSL_TRUE@ ssl/libsslsquid.la +@USE_LOADABLE_MODULES_TRUE@am__DEPENDENCIES_4 = $(am__DEPENDENCIES_1) squid_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ $(squid_LDFLAGS) $(LDFLAGS) -o $@ @@ -563,7 +566,7 @@ nodist_tests_testCoss_OBJECTS = $(am__objects_29) tests_testCoss_OBJECTS = $(am_tests_testCoss_OBJECTS) \ $(nodist_tests_testCoss_OBJECTS) -am__DEPENDENCIES_4 = $(am__DEPENDENCIES_1) $(COMMON_LIBS) \ +am__DEPENDENCIES_5 = $(am__DEPENDENCIES_1) $(COMMON_LIBS) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) acl/libapi.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) @@ -1369,7 +1372,7 @@ CTAGS = ctags am__tty_colors = \ red=; grn=; lgn=; blu=; std= -DIST_SUBDIRS = base acl fs repl auth ip icmp ident adaptation esi +DIST_SUBDIRS = base acl fs repl auth ip icmp ident adaptation esi ssl DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ @@ -1626,7 +1629,7 @@ LoadableModules.cc SUBDIRS = base acl fs repl auth ip icmp ident $(am__append_2) \ - $(am__append_3) + $(am__append_3) $(am__append_4) @USE_ESI_TRUE@ESI_LOCAL_LIBS = \ @USE_ESI_TRUE@ esi/libesi.la \ @USE_ESI_TRUE@ $(top_builddir)/lib/libTrie/src/libTrie.a @@ -1678,6 +1681,11 @@ @ENABLE_SSL_FALSE@SSL_SOURCE = @ENABLE_SSL_TRUE@SSL_SOURCE = $(SSL_ALL_SOURCE) +@ENABLE_SSL_FALSE@SSL_LIBS = +@ENABLE_SSL_TRUE@SSL_LIBS = \ +@ENABLE_SSL_TRUE@ ssl/libsslutil.la \ +@ENABLE_SSL_TRUE@ ssl/libsslsquid.la + WIN32_ALL_SOURCE = \ win32.cc \ WinSvc.cc @@ -1843,7 +1851,7 @@ typedefs.h $(UNLINKDSOURCE) url.cc URL.h URLScheme.cc \ URLScheme.h urn.cc useragent.cc wccp.cc wccp2.cc whois.cc \ wordlist.cc wordlist.h $(WIN32_SOURCE) $(WINSVC_SOURCE) \ - $(am__append_4) + $(am__append_5) noinst_HEADERS = \ client_side_request.cci \ MemBuf.cci \ @@ -1865,8 +1873,8 @@ ../compat/libcompat.la -L../lib $(XTRA_OBJS) $(DISK_LINKOBJS) \ $(REPL_OBJS) $(DISK_LIBS) $(DISK_OS_LIBS) $(CRYPTLIB) \ $(REGEXLIB) $(SNMPLIB) ${ADAPTATION_LIBS} $(ESI_LIBS) \ - $(SSLLIB) -lmiscutil $(EPOLL_LIBS) $(MINGW_LIBS) $(XTRA_LIBS) \ - $(am__append_5) + $(SSLLIB) $(SSL_LIBS) -lmiscutil $(EPOLL_LIBS) $(MINGW_LIBS) \ + $(XTRA_LIBS) $(am__append_6) squid_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a \ $(DISK_LIBS) \ $(DISK_LINKOBJS) \ @@ -2020,6 +2028,7 @@ DEFAULT_CONFIG_FILE = $(DEFAULT_CONFIG_DIR)/squid.conf DEFAULT_MIME_TABLE = $(DEFAULT_CONFIG_DIR)/mime.conf DEFAULT_DNSSERVER = $(libexecdir)/`echo dnsserver | sed '$(transform);s/$$/$(EXEEXT)/'` +DEFAULT_SSL_CRTD = $(libexecdir)/`echo ssl_crtd | sed '$(transform);s/$$/$(EXEEXT)/'` DEFAULT_LOG_PREFIX = $(DEFAULT_LOG_DIR) DEFAULT_CACHE_LOG = $(DEFAULT_LOG_PREFIX)/cache.log DEFAULT_ACCESS_LOG = $(DEFAULT_LOG_PREFIX)/access.log @@ -2027,6 +2036,7 @@ DEFAULT_PID_FILE = $(DEFAULT_PIDFILE) DEFAULT_NETDB_FILE = $(DEFAULT_LOG_PREFIX)/netdb.state DEFAULT_SWAP_DIR = $(localstatedir)/cache +DEFAULT_SSL_DB_DIR = $(localstatedir)/lib/ssl_db DEFAULT_PINGER = $(libexecdir)/`echo pinger | sed '$(transform);s/$$/$(EXEEXT)/'` DEFAULT_UNLINKD = $(libexecdir)/`echo unlinkd | sed '$(transform);s/$$/$(EXEEXT)/'` DEFAULT_DISKD = $(libexecdir)/`echo diskd | sed '$(transform);s/$$/$(EXEEXT)/'` @@ -2373,6 +2383,7 @@ $(SQUID_CPPUNIT_LIBS) \ $(SQUID_CPPUNIT_LA) \ $(SSLLIB) \ + $(SSL_LIBS) \ $(XTRA_LIBS) tests_testCacheManager_LDFLAGS = $(LIBADD_DL) @@ -2552,6 +2563,7 @@ $(SQUID_CPPUNIT_LIBS) \ $(SQUID_CPPUNIT_LA) \ $(SSLLIB) \ + $(SSL_LIBS) \ $(XTRA_LIBS) tests_testEvent_LDFLAGS = $(LIBADD_DL) @@ -2704,6 +2716,7 @@ $(SQUID_CPPUNIT_LIBS) \ $(SQUID_CPPUNIT_LA) \ $(SSLLIB) \ + $(SSL_LIBS) \ $(XTRA_LIBS) tests_testEventLoop_LDFLAGS = $(LIBADD_DL) @@ -2852,6 +2865,7 @@ $(SQUID_CPPUNIT_LIBS) \ $(SQUID_CPPUNIT_LA) \ $(SSLLIB) \ + $(SSL_LIBS) \ $(XTRA_LIBS) tests_test_http_range_LDFLAGS = $(LIBADD_DL) @@ -3003,6 +3017,7 @@ $(SQUID_CPPUNIT_LIBS) \ $(SQUID_CPPUNIT_LA) \ $(SSLLIB) \ + $(SSL_LIBS) \ $(XTRA_LIBS) tests_testHttpRequest_LDFLAGS = $(LIBADD_DL) @@ -3376,6 +3391,7 @@ $(SQUID_CPPUNIT_LIBS) \ $(SQUID_CPPUNIT_LA) \ $(SSLLIB) \ + $(SSL_LIBS) \ $(XTRA_LIBS) tests_testURL_LDFLAGS = $(LIBADD_DL) @@ -4733,6 +4749,7 @@ -e "s%[@]DEFAULT_CACHE_EFFECTIVE_USER[@]%${CACHE_EFFECTIVE_USER}%g" \ -e "s%[@]DEFAULT_MIME_TABLE[@]%$(DEFAULT_MIME_TABLE)%g" \ -e "s%[@]DEFAULT_DNSSERVER[@]%$(DEFAULT_DNSSERVER)%g" \ + -e "s%[@]DEFAULT_SSL_CRTD[@]%$(DEFAULT_SSL_CRTD)%g" \ -e "s%[@]DEFAULT_UNLINKD[@]%$(DEFAULT_UNLINKD)%g" \ -e "s%[@]DEFAULT_PINGER[@]%$(DEFAULT_PINGER)%g" \ -e "s%[@]DEFAULT_DISKD[@]%$(DEFAULT_DISKD)%g" \ @@ -4742,6 +4759,7 @@ -e "s%[@]DEFAULT_PID_FILE[@]%$(DEFAULT_PID_FILE)%g" \ -e "s%[@]DEFAULT_NETDB_FILE[@]%$(DEFAULT_NETDB_FILE)%g" \ -e "s%[@]DEFAULT_SWAP_DIR[@]%$(DEFAULT_SWAP_DIR)%g" \ + -e "s%[@]DEFAULT_SSL_DB_DIR[@]%$(DEFAULT_SSL_DB_DIR)%g" \ -e "s%[@]DEFAULT_ICON_DIR[@]%$(DEFAULT_ICON_DIR)%g" \ -e "s%[@]DEFAULT_CONFIG_DIR[@]%$(DEFAULT_CONFIG_DIR)%g" \ -e "s%[@]DEFAULT_PREFIX[@]%$(DEFAULT_PREFIX)%g" \ diff -u -r -N squid-3.1.12/src/ProtoPort.cc squid-3.1.12.1/src/ProtoPort.cc --- squid-3.1.12/src/ProtoPort.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/ProtoPort.cc 2011-04-19 17:27:09.000000000 +1200 @@ -6,11 +6,14 @@ #include "squid.h" #include "ProtoPort.h" +#if HAVE_LIMITS +#include +#endif http_port_list::http_port_list(const char *aProtocol) #if USE_SSL : - http(*this) + http(*this), dynamicCertMemCacheSize(std::numeric_limits::max()) #endif { protocol = xstrdup(aProtocol); @@ -31,6 +34,7 @@ safe_free(capath); safe_free(dhfile); safe_free(sslflags); + safe_free(sslContextSessionId); #endif } diff -u -r -N squid-3.1.12/src/ProtoPort.h squid-3.1.12.1/src/ProtoPort.h --- squid-3.1.12/src/ProtoPort.h 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/ProtoPort.h 2011-04-19 17:27:09.000000000 +1200 @@ -6,6 +6,9 @@ //#include "typedefs.h" #include "cbdata.h" +#if USE_SSL +#include "ssl/gadgets.h" +#endif struct http_port_list { http_port_list(const char *aProtocol); @@ -52,8 +55,13 @@ char *crlfile; char *dhfile; char *sslflags; - char *sslcontext; - SSL_CTX *sslContext; + char *sslContextSessionId; ///< "session id context" for staticSslContext + bool generateHostCertificates; ///< dynamically make host cert for sslBump + size_t dynamicCertMemCacheSize; ///< max size of generated certificates memory cache + + Ssl::SSL_CTX_Pointer staticSslContext; ///< for HTTPS accelerator or static sslBump + Ssl::X509_Pointer signingCert; ///< x509 certificate for signing generated certificates + Ssl::EVP_PKEY_Pointer signPkey; ///< private key for sighing generated certificates #endif CBDATA_CLASS2(http_port_list); diff -u -r -N squid-3.1.12/src/ssl/certificate_db.cc squid-3.1.12.1/src/ssl/certificate_db.cc --- squid-3.1.12/src/ssl/certificate_db.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.1.12.1/src/ssl/certificate_db.cc 2011-04-19 17:27:09.000000000 +1200 @@ -0,0 +1,487 @@ +/* + * $Id$ + */ + +#include "config.h" +#include "util.h" +#include "ssl/certificate_db.h" +#if HAVE_FSTREAM +#include +#endif +#if HAVE_STDEXCEPT +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_FILE_H +#include +#endif +#if HAVE_FCNTL_H +#include +#endif + +Ssl::FileLocker::FileLocker(std::string const & filename) + : fd(-1) +{ +#if _SQUID_MSWIN_ + hFile = CreateFile(TEXT(filename.c_str()), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile != INVALID_HANDLE_VALUE) + LockFile(hFile, 0, 0, 1, 0); +#else + fd = open(filename.c_str(), 0); + if (fd != -1) + flock(fd, LOCK_EX); +#endif +} + +Ssl::FileLocker::~FileLocker() +{ +#ifdef _SQUID_MSWIN_ + if (hFile != INVALID_HANDLE_VALUE) { + UnlockFile(hFile, 0, 0, 1, 0); + CloseHandle(hFile); + } +#else + if (fd != -1) { + flock(fd, LOCK_UN); + close(fd); + } +#endif +} + +Ssl::CertificateDb::Row::Row() + : width(cnlNumber) +{ + row = new char *[width + 1]; + for (size_t i = 0; i < width + 1; i++) + row[i] = NULL; +} + +Ssl::CertificateDb::Row::~Row() +{ + if (row) { + for (size_t i = 0; i < width + 1; i++) { + delete[](row[i]); + } + delete[](row); + } +} + +void Ssl::CertificateDb::Row::reset() +{ + row = NULL; +} + +void Ssl::CertificateDb::Row::setValue(size_t cell, char const * value) +{ + assert(cell < width); + if (row[cell]) { + free(row[cell]); + } + if (value) { + row[cell] = static_cast(xmalloc(sizeof(char) * (strlen(value) + 1))); + memcpy(row[cell], value, sizeof(char) * (strlen(value) + 1)); + } else + row[cell] = NULL; +} + +char ** Ssl::CertificateDb::Row::getRow() +{ + return row; +} + +unsigned long Ssl::CertificateDb::index_serial_hash(const char **a) +{ + const char *n = a[Ssl::CertificateDb::cnlSerial]; + while (*n == '0') n++; + return lh_strhash(n); +} + +int Ssl::CertificateDb::index_serial_cmp(const char **a, const char **b) +{ + const char *aa, *bb; + for (aa = a[Ssl::CertificateDb::cnlSerial]; *aa == '0'; aa++); + for (bb = b[Ssl::CertificateDb::cnlSerial]; *bb == '0'; bb++); + return strcmp(aa, bb); +} + +unsigned long Ssl::CertificateDb::index_name_hash(const char **a) +{ + return(lh_strhash(a[Ssl::CertificateDb::cnlName])); +} + +int Ssl::CertificateDb::index_name_cmp(const char **a, const char **b) +{ + return(strcmp(a[Ssl::CertificateDb::cnlName], b[CertificateDb::cnlName])); +} + +const std::string Ssl::CertificateDb::serial_file("serial"); +const std::string Ssl::CertificateDb::db_file("index.txt"); +const std::string Ssl::CertificateDb::cert_dir("certs"); +const std::string Ssl::CertificateDb::size_file("size"); +const size_t Ssl::CertificateDb::min_db_size(4096); + +Ssl::CertificateDb::CertificateDb(std::string const & aDb_path, size_t aMax_db_size, size_t aFs_block_size) + : db_path(aDb_path), + serial_full(aDb_path + "/" + serial_file), + 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), + enabled_disk_store(true) +{ + if (db_path.empty() && !max_db_size) + enabled_disk_store = false; + else if ((db_path.empty() && max_db_size) || (!db_path.empty() && !max_db_size)) + throw std::runtime_error("ssl_crtd is missing the required parameter. There should be -s and -M parameters together."); + else + load(); +} + +bool Ssl::CertificateDb::find(std::string const & host_name, Ssl::X509_Pointer & cert, Ssl::EVP_PKEY_Pointer & pkey) +{ + FileLocker db_locker(db_full); + load(); + return pure_find(host_name, cert, pkey); +} + +bool Ssl::CertificateDb::addCertAndPrivateKey(Ssl::X509_Pointer & cert, Ssl::EVP_PKEY_Pointer & pkey) +{ + FileLocker db_locker(db_full); + load(); + if (!db || !cert || !pkey || min_db_size > max_db_size) + return false; + 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())); + serial_string = std::string(hex_bn.get()); + } + row.setValue(cnlSerial, serial_string.c_str()); + char ** rrow = TXT_DB_get_by_index(db.get(), cnlSerial, row.getRow()); + if (rrow != NULL) + return false; + + { + TidyPointer subject(X509_NAME_oneline(X509_get_subject_name(cert.get()), NULL, 0)); + if (pure_find(subject.get(), cert, pkey)) + return true; + } + // check db size. + while (max_db_size < size()) { + if (!deleteInvalidCertificate()) + break; + } + + while (max_db_size < size()) { + deleteOldestCertificate(); + } + + row.setValue(cnlType, "V"); + ASN1_UTCTIME * tm = X509_get_notAfter(cert.get()); + row.setValue(cnlExp_date, std::string(reinterpret_cast(tm->data), tm->length).c_str()); + row.setValue(cnlFile, "unknown"); + { + TidyPointer subject(X509_NAME_oneline(X509_get_subject_name(cert.get()), NULL, 0)); + row.setValue(cnlName, subject.get()); + } + + if (!TXT_DB_insert(db.get(), row.getRow())) + return false; + + row.reset(); + std::string filename(cert_full + "/" + serial_string + ".pem"); + FileLocker cert_locker(filename); + if (!writeCertAndPrivateKeyToFile(cert, pkey, filename.c_str())) + return false; + addSize(filename); + + save(); + return true; +} + +BIGNUM * Ssl::CertificateDb::getCurrentSerialNumber() +{ + FileLocker serial_locker(serial_full); + // load serial number from file. + Ssl::BIO_Pointer file(BIO_new(BIO_s_file())); + if (!file) + return NULL; + + if (BIO_rw_filename(file.get(), const_cast(serial_full.c_str())) <= 0) + return NULL; + + Ssl::ASN1_INT_Pointer serial_ai(ASN1_INTEGER_new()); + if (!serial_ai) + return NULL; + + char buffer[1024]; + if (!a2i_ASN1_INTEGER(file.get(), serial_ai.get(), buffer, sizeof(buffer))) + return NULL; + + Ssl::BIGNUM_Pointer serial(ASN1_INTEGER_to_BN(serial_ai.get(), NULL)); + + if (!serial) + return NULL; + + // increase serial number. + Ssl::BIGNUM_Pointer increased_serial(BN_dup(serial.get())); + if (!increased_serial) + return NULL; + + BN_add_word(increased_serial.get(), 1); + + // save increased serial number. + if (BIO_seek(file.get(), 0)) + return NULL; + + Ssl::ASN1_INT_Pointer increased_serial_ai(BN_to_ASN1_INTEGER(increased_serial.get(), NULL)); + if (!increased_serial_ai) + return NULL; + + i2a_ASN1_INTEGER(file.get(), increased_serial_ai.get()); + BIO_puts(file.get(),"\n"); + + return serial.release(); +} + +void Ssl::CertificateDb::create(std::string const & db_path, int serial) +{ + if (db_path == "") + throw std::runtime_error("Path to db is empty"); + std::string serial_full(db_path + "/" + serial_file); + std::string db_full(db_path + "/" + db_file); + std::string cert_full(db_path + "/" + cert_dir); + std::string size_full(db_path + "/" + size_file); + +#ifdef _SQUID_MSWIN_ + if (mkdir(db_path.c_str())) +#else + if (mkdir(db_path.c_str(), 0777)) +#endif + throw std::runtime_error("Cannot create " + db_path); + +#ifdef _SQUID_MSWIN_ + if (mkdir(cert_full.c_str())) +#else + if (mkdir(cert_full.c_str(), 0777)) +#endif + throw std::runtime_error("Cannot create " + cert_full); + + Ssl::ASN1_INT_Pointer i(ASN1_INTEGER_new()); + ASN1_INTEGER_set(i.get(), serial); + + Ssl::BIO_Pointer file(BIO_new(BIO_s_file())); + if (!file) + throw std::runtime_error("SSL error"); + + if (BIO_write_filename(file.get(), const_cast(serial_full.c_str())) <= 0) + throw std::runtime_error("Cannot open " + cert_full + " to open"); + + i2a_ASN1_INTEGER(file.get(), i.get()); + + std::ofstream size(size_full.c_str()); + if (size) + size << 0; + else + throw std::runtime_error("Cannot open " + size_full + " to open"); + std::ofstream db(db_full.c_str()); + if (!db) + throw std::runtime_error("Cannot open " + db_full + " to open"); +} + +void Ssl::CertificateDb::check(std::string const & db_path, size_t max_db_size) +{ + CertificateDb db(db_path, max_db_size, 0); +} + +std::string Ssl::CertificateDb::getSNString() const +{ + FileLocker serial_locker(serial_full); + std::ifstream file(serial_full.c_str()); + if (!file) + return ""; + std::string serial; + file >> serial; + return serial; +} + +bool Ssl::CertificateDb::pure_find(std::string const & host_name, Ssl::X509_Pointer & cert, Ssl::EVP_PKEY_Pointer & pkey) +{ + if (!db) + return false; + + Row row; + row.setValue(cnlName, host_name.c_str()); + + char **rrow = TXT_DB_get_by_index(db.get(), cnlName, row.getRow()); + if (rrow == NULL) + return false; + + if (!sslDateIsInTheFuture(rrow[cnlExp_date])) { + deleteByHostname(rrow[cnlName]); + return false; + } + + // read cert and pkey from file. + std::string filename(cert_full + "/" + rrow[cnlSerial] + ".pem"); + FileLocker cert_locker(filename); + readCertAndPrivateKeyFromFiles(cert, pkey, filename.c_str(), NULL); + if (!cert || !pkey) + return false; + return true; +} + +size_t Ssl::CertificateDb::size() const +{ + FileLocker size_locker(size_full); + return readSize(); +} + +void Ssl::CertificateDb::addSize(std::string const & filename) +{ + FileLocker size_locker(size_full); + writeSize(readSize() + getFileSize(filename)); +} + +void Ssl::CertificateDb::subSize(std::string const & filename) +{ + FileLocker size_locker(size_full); + writeSize(readSize() - getFileSize(filename)); +} + +size_t Ssl::CertificateDb::readSize() const +{ + size_t db_size; + std::ifstream size_file(size_full.c_str()); + if (!size_file && enabled_disk_store) + throw std::runtime_error("cannot read \"" + size_full + "\" file"); + size_file >> db_size; + return db_size; +} + +void Ssl::CertificateDb::writeSize(size_t db_size) +{ + std::ofstream size_file(size_full.c_str()); + if (!size_file && enabled_disk_store) + throw std::runtime_error("cannot write \"" + size_full + "\" file"); + size_file << db_size; +} + +size_t Ssl::CertificateDb::getFileSize(std::string const & filename) +{ + std::ifstream file(filename.c_str(), std::ios::binary); + file.seekg(0, std::ios_base::end); + size_t file_size = file.tellg(); + return ((file_size + fs_block_size - 1) / fs_block_size) * fs_block_size; +} + +void Ssl::CertificateDb::load() +{ + // Load db from file. + Ssl::BIO_Pointer in(BIO_new(BIO_s_file())); + if (!in || BIO_read_filename(in.get(), db_full.c_str()) <= 0) + throw std::runtime_error("Uninitialized SSL certificate database directory: " + db_path + ". To initialize, run \"ssl_crtd -c -s " + db_path + "\"."); + + bool corrupt = false; + Ssl::TXT_DB_Pointer temp_db(TXT_DB_read(in.get(), cnlNumber)); + if (!temp_db) + corrupt = true; + + // Create indexes in db. + if (!corrupt && !TXT_DB_create_index(temp_db.get(), cnlSerial, NULL, LHASH_HASH_FN(index_serial_hash), LHASH_COMP_FN(index_serial_cmp))) + corrupt = true; + + if (!corrupt && !TXT_DB_create_index(temp_db.get(), cnlName, NULL, LHASH_HASH_FN(index_name_hash), LHASH_COMP_FN(index_name_cmp))) + corrupt = true; + + if (corrupt) + throw std::runtime_error("The SSL certificate database " + db_path + " is curruted. Please rebuild"); + + db.reset(temp_db.release()); +} + +void Ssl::CertificateDb::save() +{ + if (!db) + throw std::runtime_error("The certificates database is not loaded");; + + // To save the db to file, create a new BIO with BIO file methods. + Ssl::BIO_Pointer out(BIO_new(BIO_s_file())); + if (!out || !BIO_write_filename(out.get(), const_cast(db_full.c_str()))) + throw std::runtime_error("Failed to initialize " + db_full + " file for writing");; + + if (TXT_DB_write(out.get(), db.get()) < 0) + throw std::runtime_error("Failed to write " + db_full + " file"); +} + +bool Ssl::CertificateDb::deleteInvalidCertificate() +{ + if (!db) + return false; + + bool removed_one = false; + for (int i = 0; i < sk_num(db.get()->data); i++) { + const char ** current_row = ((const char **)sk_value(db.get()->data, i)); + + if (!sslDateIsInTheFuture(current_row[cnlExp_date])) { + std::string filename(cert_full + "/" + current_row[cnlSerial] + ".pem"); + FileLocker cert_locker(filename); + sk_delete(db.get()->data, i); + subSize(filename); + remove(filename.c_str()); + removed_one = true; + break; + } + } + + if (!removed_one) + return false; + return true; +} + +bool Ssl::CertificateDb::deleteOldestCertificate() +{ + if (!db) + return false; + + if (sk_num(db.get()->data) == 0) + return false; + + std::string filename(cert_full + "/" + ((const char **)sk_value(db.get()->data, 0))[cnlSerial] + ".pem"); + FileLocker cert_locker(filename); + sk_delete(db.get()->data, 0); + subSize(filename); + remove(filename.c_str()); + + return true; +} + +bool Ssl::CertificateDb::deleteByHostname(std::string const & host) +{ + if (!db) + return false; + + for (int i = 0; i < sk_num(db.get()->data); i++) { + const char ** current_row = ((const char **)sk_value(db.get()->data, i)); + if (host == current_row[cnlName]) { + std::string filename(cert_full + "/" + current_row[cnlSerial] + ".pem"); + FileLocker cert_locker(filename); + sk_delete(db.get()->data, i); + subSize(filename); + remove(filename.c_str()); + return true; + } + } + return false; +} + +bool Ssl::CertificateDb::IsEnabledDiskStore() const +{ + return enabled_disk_store; +} diff -u -r -N squid-3.1.12/src/ssl/certificate_db.h squid-3.1.12.1/src/ssl/certificate_db.h --- squid-3.1.12/src/ssl/certificate_db.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.1.12.1/src/ssl/certificate_db.h 2011-04-19 17:27:09.000000000 +1200 @@ -0,0 +1,139 @@ +/* + * $Id$ + */ + +#ifndef SQUID_SSL_CERTIFICATE_DB_H +#define SQUID_SSL_CERTIFICATE_DB_H + +#include "ssl/gadgets.h" +#include "ssl_support.h" +#if HAVE_STRING +#include +#endif + +namespace Ssl +{ +/// Cross platform file locker. +class FileLocker +{ +public: + /// Lock file + FileLocker(std::string const & aFilename); + /// Unlock file + ~FileLocker(); +private: +#ifdef _SQUID_MSWIN_ + HANDLE hFile; ///< Windows file handle. +#else + int fd; ///< Linux file descriptor. +#endif +}; + +/** + * Database class for storing SSL certificates and their private keys. + * A database consist by: + * - A disk file to store current serial number + * - A disk file to store the current database size + * - A disk file which is a normal TXT_DB openSSL database + * - A directory under which the certificates and their private keys stored. + * The database before used must initialized with CertificateDb::create static method. + */ +class CertificateDb +{ +public: + /// Names of db columns. + enum Columns { + cnlType = 0, + cnlExp_date, + cnlRev_date, + cnlSerial, + cnlFile, + cnlName, + cnlNumber + }; + + /// A wrapper for OpenSSL database row of TXT_DB database. + class Row + { + public: + /// Create row wrapper. + Row(); + /// Delete all row. + ~Row(); + void setValue(size_t number, char const * value); ///< Set cell's value in row + char ** getRow(); ///< Raw row + void reset(); ///< Abandon row and don't free memory + private: + char **row; ///< Raw row + size_t width; ///< Number of cells in the row + }; + + CertificateDb(std::string const & db_path, size_t aMax_db_size, size_t aFs_block_size); + /// Find certificate and private key for host name + bool find(std::string const & host_name, Ssl::X509_Pointer & cert, Ssl::EVP_PKEY_Pointer & pkey); + /// Save certificate to disk. + bool addCertAndPrivateKey(Ssl::X509_Pointer & cert, Ssl::EVP_PKEY_Pointer & pkey); + /// Get a serial number to use for generating a new certificate. + BIGNUM * getCurrentSerialNumber(); + /// Create and initialize a database under the db_path + static void create(std::string const & db_path, int serial); + /// Check the database stored under the db_path. + static void check(std::string const & db_path, size_t max_db_size); + std::string getSNString() const; ///< Get serial number as string. + bool IsEnabledDiskStore() const; ///< Check enabled of dist store. +private: + void load(); ///< Load db from disk. + void save(); ///< Save db to disk. + size_t size() const; ///< Get db size on disk in bytes. + /// Increase db size by the given file size and update size_file + void addSize(std::string const & filename); + /// Decrease db size by the given file size and update size_file + void subSize(std::string const & filename); + size_t readSize() const; ///< Read size from file size_file + void writeSize(size_t db_size); ///< Write size to file size_file. + size_t getFileSize(std::string const & filename); ///< get file size on disk. + /// Only find certificate in current db and return it. + bool pure_find(std::string const & host_name, Ssl::X509_Pointer & cert, Ssl::EVP_PKEY_Pointer & pkey); + + bool deleteInvalidCertificate(); ///< Delete invalid certificate. + bool deleteOldestCertificate(); ///< Delete oldest certificate. + bool deleteByHostname(std::string const & host); ///< Delete using host name. + + /// Callback hash function for serials. Used to create TXT_DB index of serials. + static unsigned long index_serial_hash(const char **a); + /// Callback compare function for serials. Used to create TXT_DB index of serials. + static int index_serial_cmp(const char **a, const char **b); + /// Callback hash function for names. Used to create TXT_DB index of names.. + static unsigned long index_name_hash(const char **a); + /// Callback compare function for names. Used to create TXT_DB index of names.. + static int index_name_cmp(const char **a, const char **b); + + /// Definitions required by openSSL, to use the index_* functions defined above + ///with TXT_DB_create_index. + static IMPLEMENT_LHASH_HASH_FN(index_serial_hash,const char **) + static IMPLEMENT_LHASH_COMP_FN(index_serial_cmp,const char **) + static IMPLEMENT_LHASH_HASH_FN(index_name_hash,const char **) + static IMPLEMENT_LHASH_COMP_FN(index_name_cmp,const char **) + + static const std::string serial_file; ///< Base name of the file to store serial number. + static const std::string db_file; ///< Base name of the database index file. + static const std::string cert_dir; ///< Base name of the directory to store the certs. + static const std::string size_file; ///< Base name of the file to store db size. + /// Min size of disk db. If real size < min_db_size the db will be disabled. + static const size_t min_db_size; + + const std::string db_path; ///< The database directory. + const std::string serial_full; ///< Full path of the file to store serial number. + const std::string db_full; ///< Full path of the database index file. + const std::string cert_full; ///< Full path of the directory to store the certs. + const std::string size_full; ///< Full path of the file to store the db size. + + TXT_DB_Pointer db; ///< Database with certificates info. + const size_t max_db_size; ///< Max size of db. + const size_t fs_block_size; ///< File system block size. + + bool enabled_disk_store; ///< The storage on the disk is enabled. +}; + +} // namespace Ssl +#endif // SQUID_SSL_CERTIFICATE_DB_H diff -u -r -N squid-3.1.12/src/ssl/Config.cc squid-3.1.12.1/src/ssl/Config.cc --- squid-3.1.12/src/ssl/Config.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.1.12.1/src/ssl/Config.cc 2011-04-19 17:27:09.000000000 +1200 @@ -0,0 +1,23 @@ +/* + * $Id$ + */ +#include "squid.h" +#include "ssl/Config.h" + +Ssl::Config Ssl::TheConfig; + +Ssl::Config::Config() +#if USE_SSL_CRTD + : + ssl_crtd(NULL), + ssl_crtd_n_running(5) +#endif +{ +} + +Ssl::Config::~Config() +{ +#if USE_SSL_CRTD + xfree(ssl_crtd); +#endif +} diff -u -r -N squid-3.1.12/src/ssl/Config.h squid-3.1.12.1/src/ssl/Config.h --- squid-3.1.12/src/ssl/Config.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.1.12.1/src/ssl/Config.h 2011-04-19 17:27:09.000000000 +1200 @@ -0,0 +1,29 @@ +/* + * $Id$ + */ + +#ifndef SQUID_SSL_CONFIG_H +#define SQUID_SSL_CONFIG_H + +namespace Ssl +{ + +class Config +{ +public: +#if USE_SSL_CRTD + char *ssl_crtd; ///< Name of external ssl_crtd application. + /// The number of processes spawn for ssl_crtd. + int ssl_crtd_n_running; +#endif + Config(); + ~Config(); +private: + Config(const Config &); // not implemented + Config &operator =(const Config &); // not implemented +}; + +extern Config TheConfig; + +} // namespace Ssl +#endif diff -u -r -N squid-3.1.12/src/ssl/context_storage.cc squid-3.1.12.1/src/ssl/context_storage.cc --- squid-3.1.12/src/ssl/context_storage.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.1.12.1/src/ssl/context_storage.cc 2011-04-19 17:27:09.000000000 +1200 @@ -0,0 +1,176 @@ +/* + * $Id$ + */ +#include "config.h" +#include "Store.h" +#include "StoreEntryStream.h" +#include "ssl/context_storage.h" +#if HAVE_LIMITS +#include +#endif + +Ssl::CertificateStorageAction::CertificateStorageAction() + : CacheManagerAction("cached_ssl_cert", "Statistic of cached generated ssl certificates", 1, 1) +{} + +void Ssl::CertificateStorageAction::run (StoreEntry *sentry) +{ + StoreEntryStream stream(sentry); + const char delimiter = '\t'; + const char endString = '\n'; + // Page title. + stream << "Cached ssl certificates statistic.\n"; + // Title of statistic table. + stream << "Port" << delimiter << "Max mem(KB)" << delimiter << "Cert number" << delimiter << "KB/cert" << delimiter << "Mem used(KB)" << delimiter << "Mem free(KB)" << endString; + + // Add info for each port. + for (std::map::iterator i = TheGlobalContextStorage.storage.begin(); i != TheGlobalContextStorage.storage.end(); i++) { + stream << i->first << delimiter; + LocalContextStorage & ssl_store_policy(*(i->second)); + stream << ssl_store_policy.max_memory / 1024 << delimiter; + stream << ssl_store_policy.memory_used / SSL_CTX_SIZE << delimiter; + stream << SSL_CTX_SIZE / 1024 << delimiter; + stream << ssl_store_policy.memory_used / 1024 << delimiter; + stream << (ssl_store_policy.max_memory - ssl_store_policy.memory_used) / 1024 << endString; + } + stream << endString; + stream.flush(); +} + +Ssl::LocalContextStorage::LocalContextStorage(size_t aMax_memory) + : max_memory(aMax_memory), memory_used(0) +{} + +Ssl::LocalContextStorage::~LocalContextStorage() +{ + for (QueueIterator i = lru_queue.begin(); i != lru_queue.end(); i++) { + delete *i; + } +} + +SSL_CTX * Ssl::LocalContextStorage::add(const char * host_name, SSL_CTX * ssl_ctx) +{ + if (max_memory < SSL_CTX_SIZE) { + return NULL; + } + remove(host_name); + while (SSL_CTX_SIZE + memory_used > max_memory) { + purgeOne(); + } + lru_queue.push_front(new Item(ssl_ctx, host_name)); + storage.insert(MapPair(host_name, lru_queue.begin())); + memory_used += SSL_CTX_SIZE; + return ssl_ctx; +} + +SSL_CTX * Ssl::LocalContextStorage::find(char const * host_name) +{ + MapIterator i = storage.find(host_name); + if (i == storage.end()) { + return NULL; + } + lru_queue.push_front(*(i->second)); + lru_queue.erase(i->second); + i->second = lru_queue.begin(); + return (*lru_queue.begin())->ssl_ctx; +} + +void Ssl::LocalContextStorage::remove(char const * host_name) +{ + deleteAt(storage.find(host_name)); +} + +void Ssl::LocalContextStorage::purgeOne() +{ + QueueIterator i = lru_queue.end(); + i--; + if (i != lru_queue.end()) { + remove((*i)->host_name.c_str()); + } +} + +void Ssl::LocalContextStorage::deleteAt(LocalContextStorage::MapIterator i) +{ + if (i != storage.end()) { + + delete *(i->second); + lru_queue.erase(i->second); + storage.erase(i); + memory_used -= SSL_CTX_SIZE; + } +} + +void Ssl::LocalContextStorage::SetSize(size_t aMax_memory) +{ + max_memory = aMax_memory; +} + +Ssl::LocalContextStorage::Item::Item(SSL_CTX * aSsl_ctx, std::string const & aName) + : ssl_ctx(aSsl_ctx), host_name(aName) +{} + +Ssl::LocalContextStorage::Item::~Item() +{ + SSL_CTX_free(ssl_ctx); +} + +/////////////////////////////////////////////////////// + +Ssl::GlobalContextStorage::GlobalContextStorage() + : reconfiguring(true) +{ +// RegisterAction("cached_ssl_cert", "Statistic of cached generated ssl certificates", &CertificateStorageAction::Create, 0, 1); + CacheManager::GetInstance()->registerAction(new CertificateStorageAction); +} + +Ssl::GlobalContextStorage::~GlobalContextStorage() +{ + for (std::map::iterator i = storage.begin(); i != storage.end(); i++) { + delete i->second; + } +} + +void Ssl::GlobalContextStorage::addLocalStorage(IpAddress const & address, size_t size_of_store) +{ + assert(reconfiguring); + configureStorage.insert(std::pair(address, size_of_store)); +} + +Ssl::LocalContextStorage & Ssl::GlobalContextStorage::getLocalStorage(IpAddress const & address) +{ + reconfigureFinish(); + std::map::iterator i = storage.find(address); + assert (i != storage.end()); + return *(i->second); +} + +void Ssl::GlobalContextStorage::reconfigureStart() +{ + reconfiguring = true; +} + +void Ssl::GlobalContextStorage::reconfigureFinish() +{ + if (reconfiguring) { + reconfiguring = false; + + // remove or change old local storages. + for (std::map::iterator i = storage.begin(); i != storage.end(); i++) { + std::map::iterator conf_i = configureStorage.find(i->first); + if (conf_i == configureStorage.end()) { + storage.erase(i); + } else { + i->second->SetSize(conf_i->second); + } + } + + // add new local storages. + for (std::map::iterator conf_i = configureStorage.begin(); conf_i != configureStorage.end(); conf_i++ ) { + if (storage.find(conf_i->first) == storage.end()) { + storage.insert(std::pair(conf_i->first, new LocalContextStorage(conf_i->second))); + } + } + } +} + +Ssl::GlobalContextStorage Ssl::TheGlobalContextStorage; diff -u -r -N squid-3.1.12/src/ssl/context_storage.h squid-3.1.12.1/src/ssl/context_storage.h --- squid-3.1.12/src/ssl/context_storage.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.1.12.1/src/ssl/context_storage.h 2011-04-19 17:27:09.000000000 +1200 @@ -0,0 +1,113 @@ +/* + * $Id$ + */ + +#ifndef SQUID_SSL_CONTEXT_STORAGE_H +#define SQUID_SSL_CONTEXT_STORAGE_H + +#if USE_SSL + +#include "SquidTime.h" +#include "CacheManager.h" +#if HAVE_MAP +#include +#endif +#if HAVE_LIST +#include +#endif + +/// TODO: Replace on real size. +#define SSL_CTX_SIZE 1024 + +namespace Ssl +{ + +/** Reports cached SSL certificate stats to Cache Manager. + * TODO: Use "Report" functions instead friend class. + */ +class CertificateStorageAction : public CacheManagerAction +{ +public: + CertificateStorageAction(); + virtual void run (StoreEntry *sentry); +}; + +/** + * Memory cache for store generated SSL context. Enforces total size limits + * using an LRU algorithm. + */ +class LocalContextStorage +{ + friend class CertificateStorageAction; +public: + /// Cache item is an (SSL_CTX, host name) tuple. + class Item + { + public: + Item(SSL_CTX * aSsl_ctx, std::string const & aName); + ~Item(); + public: + SSL_CTX * ssl_ctx; ///< The SSL context. + std::string host_name; ///< The host name of the SSL context. + }; + + typedef std::list Queue; + typedef Queue::iterator QueueIterator; + + /// host_name:queue_item mapping for fast lookups by host name + typedef std::map Map; + typedef Map::iterator MapIterator; + typedef std::pair MapPair; + + LocalContextStorage(size_t aMax_memory); + ~LocalContextStorage(); + /// Set maximum memory size for this storage. + void SetSize(size_t aMax_memory); + /// Return a pointer to the added ssl_ctx or NULL if fails (eg. max cache size equal 0). + SSL_CTX * add(char const * host_name, SSL_CTX * ssl_ctx); + /// Find SSL_CTX in storage by host name. Lru queue will be updated. + SSL_CTX * find(char const * host_name); + void remove(char const * host_name); ///< Delete the SSL context by hostname + +private: + void purgeOne(); ///< Delete oldest object. + /// Delete object by iterator. It is used in deletePurge() and remove(...) methods. + void deleteAt(MapIterator i); + + size_t max_memory; ///< Max cache size. + size_t memory_used; ///< Used cache size. + Map storage; ///< The hostnames/SSL_CTX * pairs + Queue lru_queue; ///< LRU cache index +}; + + +/// Class for storing/manipulating LocalContextStorage per local listening address/port. +class GlobalContextStorage +{ + + friend class CertificateStorageAction; +public: + GlobalContextStorage(); + ~GlobalContextStorage(); + /// Create new SSL context storage for the local listening address/port. + void addLocalStorage(IpAddress const & address, size_t size_of_store); + /// Return the local storage for the given listening address/port. + LocalContextStorage & getLocalStorage(IpAddress const & address); + /// When reconfigring should be called this method. + void reconfigureStart(); +private: + /// Called by getLocalStorage method + void reconfigureFinish(); + bool reconfiguring; ///< True if system reconfiguring now. + /// Storage used on configure or reconfigure. + std::map configureStorage; + /// Map for storing all local ip address and their local storages. + std::map storage; +}; + +/// Global cache for store all SSL server certificates. +extern GlobalContextStorage TheGlobalContextStorage; +} //namespace Ssl +#endif // USE_SSL + +#endif // SQUID_SSL_CONTEXT_STORAGE_H diff -u -r -N squid-3.1.12/src/ssl/crtd_message.cc squid-3.1.12.1/src/ssl/crtd_message.cc --- squid-3.1.12/src/ssl/crtd_message.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.1.12.1/src/ssl/crtd_message.cc 2011-04-19 17:27:09.000000000 +1200 @@ -0,0 +1,177 @@ +/* + * $Id$ + */ + +#include "squid.h" +#include "ssl/crtd_message.h" +#if HAVE_CSTDLIB +#include +#endif +#if HAVE_CSTRING +#include +#endif + +Ssl::CrtdMessage::CrtdMessage() + : body_size(0), state(BEFORE_CODE) +{} + +Ssl::CrtdMessage::ParseResult Ssl::CrtdMessage::parse(const char * buffer, size_t len) +{ + char const *current_pos = buffer; + while (current_pos != buffer + len && state != END) { + switch (state) { + case BEFORE_CODE: { + if (xisspace(*current_pos)) { + current_pos++; + break; + } + if (xisalpha(*current_pos)) { + state = CODE; + break; + } + clear(); + return ERROR; + } + case CODE: { + if (xisalnum(*current_pos) || *current_pos == '_') { + current_block += *current_pos; + current_pos++; + break; + } + if (xisspace(*current_pos)) { + code = current_block; + current_block.clear(); + state = BEFORE_LENGTH; + break; + } + clear(); + return ERROR; + } + case BEFORE_LENGTH: { + if (xisspace(*current_pos)) { + current_pos++; + break; + } + if (xisdigit(*current_pos)) { + state = LENGTH; + break; + } + clear(); + return ERROR; + } + case LENGTH: { + if (xisdigit(*current_pos)) { + current_block += *current_pos; + current_pos++; + break; + } + if (xisspace(*current_pos)) { + body_size = atoi(current_block.c_str()); + current_block.clear(); + state = BEFORE_BODY; + break; + } + clear(); + return ERROR; + } + case BEFORE_BODY: { + if (body_size == 0) { + state = END; + break; + } + if (xisspace(*current_pos)) { + current_pos++; + break; + } else { + state = BODY; + break; + } + } + case BODY: { + size_t body_len = (static_cast(buffer + len - current_pos) >= body_size - current_block.length()) + ? body_size - current_block.length() + : static_cast(buffer + len - current_pos); + current_block += std::string(current_pos, body_len); + current_pos += body_len; + if (current_block.length() == body_size) { + body = current_block; + state = END; + } + if (current_block.length() > body_size) { + clear(); + return ERROR; + } + break; + } + case END: { + return OK; + } + } + } + if (state != END) return INCOMPLETE; + return OK; +} + +std::string const & Ssl::CrtdMessage::getBody() const { return body; } + +std::string const & Ssl::CrtdMessage::getCode() const { return code; } + +void Ssl::CrtdMessage::setBody(std::string const & aBody) { body = aBody; } + +void Ssl::CrtdMessage::setCode(std::string const & aCode) { code = aCode; } + + +std::string Ssl::CrtdMessage::compose() const +{ + if (code.empty()) return std::string(); + char buffer[10]; + snprintf(buffer, sizeof(buffer), "%zd", body.length()); + return code + ' ' + buffer + ' ' + body + '\n'; +} + +void Ssl::CrtdMessage::clear() +{ + body_size = 0; + state = BEFORE_CODE; + body.clear(); + code.clear(); + current_block.clear(); +} + +void Ssl::CrtdMessage::parseBody(CrtdMessage::BodyParams & map, std::string & other_part) const +{ + other_part.clear(); + // Copy string for using it as temp buffer. + std::string temp_body(body.c_str(), body.length()); + char * buffer = const_cast(temp_body.c_str()); + char * token = strtok(buffer, "\r\n"); + while (token != NULL) { + std::string current_string(token); + size_t equal_pos = current_string.find('='); + if (equal_pos == std::string::npos) { + size_t offset_body_part = token - temp_body.c_str(); + other_part = std::string(body.c_str() + offset_body_part, body.length() - offset_body_part); + break; + } else { + std::string param(current_string.c_str(), current_string.c_str() + equal_pos); + std::string value(current_string.c_str() + equal_pos + 1); + map.insert(std::make_pair(param, value)); + } + token = strtok(NULL, "\r\n"); + } +} + +void Ssl::CrtdMessage::composeBody(CrtdMessage::BodyParams const & map, std::string const & other_part) +{ + body.clear(); + for (BodyParams::const_iterator i = map.begin(); i != map.end(); i++) { + if (i != map.begin()) + body += "\n"; + body += i->first + "=" + i->second; + } + if (!other_part.empty()) + body += '\n' + other_part; +} + +const std::string Ssl::CrtdMessage::code_new_certificate("new_certificate"); +const std::string Ssl::CrtdMessage::param_host("host"); diff -u -r -N squid-3.1.12/src/ssl/crtd_message.h squid-3.1.12.1/src/ssl/crtd_message.h --- squid-3.1.12/src/ssl/crtd_message.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.1.12.1/src/ssl/crtd_message.h 2011-04-19 17:27:09.000000000 +1200 @@ -0,0 +1,86 @@ +/* + * $Id$ + */ + +#ifndef SQUID_SSL_CRTD_MESSAGE_H +#define SQUID_SSL_CRTD_MESSAGE_H + +#if HAVE_STRING +#include +#endif +#if HAVE_MAP +#include +#endif + +namespace Ssl +{ +/** + * This class is responsible for composing and parsing messages destined to, or comming + * from an ssl_crtd server. Format of these mesages is: + * + */ +class CrtdMessage +{ +public: + typedef std::map BodyParams; + /// Parse result codes. + enum ParseResult { + OK, + INCOMPLETE, + ERROR + }; + CrtdMessage(); + /**Parse buffer of length len + \retval OK if parsing completes + \retval INCOMPLETE if more data required + \retval ERROR if there is an error. + */ + ParseResult parse(const char * buffer, size_t len); + /// Current body. If parsing is not finished the method returns incompleted body. + std::string const & getBody() const; + /// Current response/request code. If parsing is not finished the method may return incompleted code. + std::string const & getCode() const; + void setBody(std::string const & aBody); ///< Set new body to encode. + void setCode(std::string const & aCode); ///< Set new request/reply code to compose. + std::string compose() const; ///< Compose current (request) code and body to string. + /// Reset the class. + void clear(); + /** + *Parse body data which has the form: \verbatim + param1=value1 + param2=value2 + The other multistring part of body. \endverbatim + * The parameters of the body stored to map and the remaining part to other_part + */ + void parseBody(BodyParams & map, std::string & other_part) const; + /** + *Compose parameters given by map with their values and the other part given by + * other_part to body data. The constructed body will have the form: \verbatim + param1=value1 + param2=value2 + The other multistring part of body. \endverbatim + */ + void composeBody(BodyParams const & map, std::string const & other_part); + /// String code for "new_certificate" messages + static const std::string code_new_certificate; + /// Parameter name for passing hostname + static const std::string param_host; +private: + enum ParseState { + BEFORE_CODE, + CODE, + BEFORE_LENGTH, + LENGTH, + BEFORE_BODY, + BODY, + END + }; + size_t body_size; ///< The body size if exist or 0. + ParseState state; ///< Parsing state. + std::string body; ///< Current body. + std::string code; ///< Current response/request code. + std::string current_block; ///< Current block buffer. +}; + +} //namespace Ssl +#endif // SQUID_SSL_CRTD_MESSAGE_H diff -u -r -N squid-3.1.12/src/ssl/ErrorDetail.cc squid-3.1.12.1/src/ssl/ErrorDetail.cc --- squid-3.1.12/src/ssl/ErrorDetail.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.1.12.1/src/ssl/ErrorDetail.cc 2011-04-19 17:27:09.000000000 +1200 @@ -0,0 +1,265 @@ +#include "squid.h" +#include "ssl/ErrorDetail.h" + +struct SslErrorDetailEntry { + Ssl::ssl_error_t value; + const char *name; + const char *detail; +}; + +static const char *SslErrorDetailDefaultStr = "SSL certificate validation error (%err_name): %ssl_subject"; +// TODO: optimize by replacing with std::map or similar +static SslErrorDetailEntry TheSslDetailMap[] = { + { SQUID_X509_V_ERR_DOMAIN_MISMATCH, + "SQUID_X509_V_ERR_DOMAIN_MISMATCH", + "%err_name: The hostname you are connecting to (%H), does not match any of the Certificate valid names: %ssl_cn"}, + { X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT, + "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT", + "%err_name: SSL Certficate error: certificate issuer (CA) not known: %ssl_ca_name" }, + { X509_V_ERR_CERT_NOT_YET_VALID, + "X509_V_ERR_CERT_NOT_YET_VALID", + "%err_name: SSL Certficate is not valid before: %ssl_notbefore" }, + { X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD, + "X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD", + "%err_name: SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" }, + { X509_V_ERR_CERT_HAS_EXPIRED, + "X509_V_ERR_CERT_HAS_EXPIRED", + "%err_name: SSL Certificate expired on %ssl_notafter" }, + { X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD, + "X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD", + "%err_name: SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" }, + {X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT, + "X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT", + "%err_name: Self-signed SSL Certificate: %ssl_subject"}, + { X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, + "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY", + "%err_name: SSL Certficate error: certificate issuer (CA) not known: %ssl_ca_name" }, + { SSL_ERROR_NONE, "SSL_ERROR_NONE", "%err_name: No error" }, + {SSL_ERROR_NONE, NULL, NULL } +}; + +Ssl::ssl_error_t +Ssl::parseErrorString(const char *name) +{ + assert(name); + + for (int i = 0; TheSslDetailMap[i].name; ++i) { + if (strcmp(name, TheSslDetailMap[i].name) == 0) + return TheSslDetailMap[i].value; + } + + if (xisdigit(*name)) { + const long int value = strtol(name, NULL, 0); + if (SQUID_SSL_ERROR_MIN <= value && value <= SQUID_SSL_ERROR_MAX) + return value; + fatalf("Too small or too bug SSL error code '%s'", name); + } + + fatalf("Unknown SSL error name '%s'", name); + return SSL_ERROR_SSL; // not reached +} + +const char * +Ssl::getErrorName(Ssl::ssl_error_t value) +{ + + for (int i = 0; TheSslDetailMap[i].name; ++i) { + if (TheSslDetailMap[i].value == value) + return TheSslDetailMap[i].name; + } + + return NULL; +} + +static const char *getErrorDetail(Ssl::ssl_error_t value) +{ + for (int i = 0; TheSslDetailMap[i].name; ++i) { + if (TheSslDetailMap[i].value == value) + return TheSslDetailMap[i].detail; + } + + // we must always return something because ErrorDetail::buildDetail + // will hit an assertion + return SslErrorDetailDefaultStr; +} + +Ssl::ErrorDetail::err_frm_code Ssl::ErrorDetail::ErrorFormatingCodes[] = { + {"ssl_subject", &Ssl::ErrorDetail::subject}, + {"ssl_ca_name", &Ssl::ErrorDetail::ca_name}, + {"ssl_cn", &Ssl::ErrorDetail::cn}, + {"ssl_notbefore", &Ssl::ErrorDetail::notbefore}, + {"ssl_notafter", &Ssl::ErrorDetail::notafter}, + {"err_name", &Ssl::ErrorDetail::err_code}, + {NULL,NULL} +}; + +/** + * The subject of the current certification in text form + */ +const char *Ssl::ErrorDetail::subject() const +{ + if (!peer_cert) + return "[Not available]"; + + static char tmpBuffer[256]; // A temporary buffer + X509_NAME_oneline(X509_get_subject_name(peer_cert.get()), tmpBuffer, + sizeof(tmpBuffer)); + return tmpBuffer; +} + +// helper function to be used with Ssl::matchX509CommonNames +static int copy_cn(void *check_data, ASN1_STRING *cn_data) +{ + String *str = (String *)check_data; + if (!str) // no data? abort + return 0; + if (str->defined()) + str->append(", "); + str->append((const char *)cn_data->data, cn_data->length); + return 1; +} + +/** + * The list with certificates cn and alternate names + */ +const char *Ssl::ErrorDetail::cn() const +{ + if (!peer_cert) + return "[Not available]"; + + static String tmpStr; ///< A temporary string buffer + tmpStr.clean(); + Ssl::matchX509CommonNames(peer_cert.get(), &tmpStr, copy_cn); + return tmpStr.termedBuf(); +} + +/** + * The issuer name + */ +const char *Ssl::ErrorDetail::ca_name() const +{ + if (!peer_cert) + return "[Not available]"; + + static char tmpBuffer[256]; // A temporary buffer + X509_NAME_oneline(X509_get_issuer_name(peer_cert.get()), tmpBuffer, sizeof(tmpBuffer)); + return tmpBuffer; +} + +/** + * The certificate "not before" field + */ +const char *Ssl::ErrorDetail::notbefore() const +{ + if (!peer_cert) + return "[Not available]"; + + static char tmpBuffer[256]; // A temporary buffer + ASN1_UTCTIME * tm = X509_get_notBefore(peer_cert.get()); + Ssl::asn1timeToString(tm, tmpBuffer, sizeof(tmpBuffer)); + return tmpBuffer; +} + +/** + * The certificate "not after" field + */ +const char *Ssl::ErrorDetail::notafter() const +{ + if (!peer_cert) + return "[Not available]"; + + static char tmpBuffer[256]; // A temporary buffer + ASN1_UTCTIME * tm = X509_get_notAfter(peer_cert.get()); + Ssl::asn1timeToString(tm, tmpBuffer, sizeof(tmpBuffer)); + return tmpBuffer; +} + +/** + * The string representation of the error_no + */ +const char *Ssl::ErrorDetail::err_code() const +{ + static char tmpBuffer[64]; + const char *err = getErrorName(error_no); + if (!err) { + snprintf(tmpBuffer, 64, "%d", (int)error_no); + err = tmpBuffer; + } + return err; +} + +/** + * It converts the code to a string value. Currently the following + * formating codes are supported: + * %err_name: The name of the SSL error + * %ssl_cn: The comma-separated list of common and alternate names + * %ssl_subject: The certificate subject + * %ssl_ca_name: The certificate issuer name + * %ssl_notbefore: The certificate "not before" field + * %ssl_notafter: The certificate "not after" field + \retval the length of the code (the number of characters will be replaced by value) +*/ +int Ssl::ErrorDetail::convert(const char *code, const char **value) const +{ + *value = "-"; + for (int i=0; ErrorFormatingCodes[i].code!=NULL; i++) { + const int len = strlen(ErrorFormatingCodes[i].code); + if (strncmp(code,ErrorFormatingCodes[i].code, len)==0) { + ErrorDetail::fmt_action_t action = ErrorFormatingCodes[i].fmt_action; + *value = (this->*action)(); + return len; + } + } + return 0; +} + +/** + * It uses the convert method to build the string errDetailStr using + * a template message for the current SSL error. The template messages + * can also contain normal error pages formating codes. + * Currently the error template messages are hard-coded + */ +void Ssl::ErrorDetail::buildDetail() const +{ + char const *s = getErrorDetail(error_no); + char const *p; + char const *t; + int code_len = 0; + + assert(s); + while ((p = strchr(s, '%'))) { + errDetailStr.append(s, p - s); + code_len = convert(++p, &t); + if (code_len) + errDetailStr.append(t); + else + errDetailStr.append("%"); + s = p + code_len; + } + errDetailStr.append(s, strlen(s)); +} + +const String &Ssl::ErrorDetail::toString() const +{ + if (!errDetailStr.defined()) + buildDetail(); + return errDetailStr; +} + +/* We may do not want to use X509_dup but instead + internal SSL locking: + CRYPTO_add(&(cert->references),1,CRYPTO_LOCK_X509); + peer_cert.reset(cert); +*/ +Ssl::ErrorDetail::ErrorDetail( Ssl::ssl_error_t err_no, X509 *cert): error_no (err_no) +{ + peer_cert.reset(X509_dup(cert)); +} + +Ssl::ErrorDetail::ErrorDetail(Ssl::ErrorDetail const &anErrDetail) +{ + error_no = anErrDetail.error_no; + if (anErrDetail.peer_cert.get()) { + peer_cert.reset(X509_dup(anErrDetail.peer_cert.get())); + } +} diff -u -r -N squid-3.1.12/src/ssl/ErrorDetail.h squid-3.1.12.1/src/ssl/ErrorDetail.h --- squid-3.1.12/src/ssl/ErrorDetail.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.1.12.1/src/ssl/ErrorDetail.h 2011-04-19 17:27:09.000000000 +1200 @@ -0,0 +1,76 @@ +#ifndef _SQUID_SSL_ERROR_DETAIL_H +#define _SQUID_SSL_ERROR_DETAIL_H + +#include "ssl_support.h" +#include "ssl/gadgets.h" +#include "SquidString.h" + +#if HAVE_OPENSSL_SSL_H +#include +#endif + +// Custom SSL errors; assumes all official errors are positive +#define SQUID_X509_V_ERR_DOMAIN_MISMATCH -1 +// All SSL errors range: from smallest (negative) custom to largest SSL error +#define SQUID_SSL_ERROR_MIN SQUID_X509_V_ERR_DOMAIN_MISMATCH +#define SQUID_SSL_ERROR_MAX INT_MAX + +namespace Ssl +{ +/// Squid defined error code (<0), an error code returned by SSL X509 api, or SSL_ERROR_NONE +typedef int ssl_error_t; + +/** + \ingroup ServerProtocolSSLAPI + * The ssl_error_t representation of the error described by "name". + */ +ssl_error_t parseErrorString(const char *name); + +/** + \ingroup ServerProtocolSSLAPI + * The string representation of the SSL error "value" + */ +const char *getErrorName(ssl_error_t value); + +/** + \ingroup ServerProtocolSSLAPI + * Used to pass SSL error details to the error pages returned to the + * end user. + */ +class ErrorDetail +{ +public: + ErrorDetail(ssl_error_t err_no, X509 *cert); + ErrorDetail(ErrorDetail const &); + const String &toString() const; ///< An error detail string to embed in squid error pages + +private: + typedef const char * (ErrorDetail::*fmt_action_t)() const; + /** + * Holds a formating code and its conversion method + */ + class err_frm_code + { + public: + const char *code; ///< The formating code + fmt_action_t fmt_action; ///< A pointer to the conversion method + }; + static err_frm_code ErrorFormatingCodes[]; ///< The supported formating codes + + const char *subject() const; + const char *ca_name() const; + const char *cn() const; + const char *notbefore() const; + const char *notafter() const; + const char *err_code() const; + + int convert(const char *code, const char **value) const; + void buildDetail() const; + + mutable String errDetailStr; ///< Caches the error detail message + ssl_error_t error_no; ///< The error code + X509_Pointer peer_cert; ///< A pointer to the peer certificate +}; + +}//namespace Ssl +#endif diff -u -r -N squid-3.1.12/src/ssl/gadgets.cc squid-3.1.12.1/src/ssl/gadgets.cc --- squid-3.1.12/src/ssl/gadgets.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.1.12.1/src/ssl/gadgets.cc 2011-04-19 17:27:09.000000000 +1200 @@ -0,0 +1,272 @@ +/* + * $Id$ + */ + +#include "config.h" +#include "ssl/gadgets.h" + +/** + \ingroup ServerProtocolSSLInternal + * Add CN to subject in request. + */ +static bool addCnToRequest(Ssl::X509_REQ_Pointer & request, char const * cn) +{ + Ssl::X509_NAME_Pointer name(X509_REQ_get_subject_name(request.get())); + if (!name) + return false; + + // The second argument of the X509_NAME_add_entry_by_txt declared as + // "char *" on some OS. Use cn_name to avoid compile warnings. + static char cn_name[3] = "CN"; + if (!X509_NAME_add_entry_by_txt(name.get(), cn_name, MBSTRING_ASC, (unsigned char *)cn, -1, -1, 0)) + return false; + name.release(); + return true; +} + +/** + \ingroup ServerProtocolSSLInternal + * Make request on sign using private key and hostname. + */ +static bool makeRequest(Ssl::X509_REQ_Pointer & request, Ssl::EVP_PKEY_Pointer const & pkey, char const * host) +{ + if (!X509_REQ_set_version(request.get(), 0L)) + return false; + + if (!addCnToRequest(request, host)) + return false; + + if (!X509_REQ_set_pubkey(request.get(), pkey.get())) + return false; + return true; +} + +EVP_PKEY * Ssl::createSslPrivateKey() +{ + Ssl::EVP_PKEY_Pointer pkey(EVP_PKEY_new()); + + if (!pkey) + return NULL; + + Ssl::RSA_Pointer rsa(RSA_generate_key(1024, RSA_F4, NULL, NULL)); + + if (!rsa) + return NULL; + + if (!EVP_PKEY_assign_RSA(pkey.get(), (rsa.get()))) + return NULL; + + rsa.release(); + return pkey.release(); +} + +X509_REQ * Ssl::createNewX509Request(Ssl::EVP_PKEY_Pointer const & pkey, const char * hostname) +{ + Ssl::X509_REQ_Pointer request(X509_REQ_new()); + + if (!request) + return NULL; + + if (!makeRequest(request, pkey, hostname)) + return NULL; + return request.release(); +} + +/** + \ingroup ServerProtocolSSLInternal + * Set serial random serial number or set random serial number. + */ +static bool setSerialNumber(ASN1_INTEGER *ai, BIGNUM const* serial) +{ + if (!ai) + return false; + Ssl::BIGNUM_Pointer bn(BN_new()); + if (serial) { + bn.reset(BN_dup(serial)); + } else { + if (!bn) + return false; + + if (!BN_pseudo_rand(bn.get(), 64, 0, 0)) + return false; + } + + if (ai && !BN_to_ASN1_INTEGER(bn.get(), ai)) + return false; + return true; +} + +X509 * Ssl::signRequest(Ssl::X509_REQ_Pointer const & request, Ssl::X509_Pointer const & x509, Ssl::EVP_PKEY_Pointer const & pkey, ASN1_TIME * timeNotAfter, BIGNUM const * serial) +{ + Ssl::X509_Pointer cert(X509_new()); + if (!cert) + return NULL; + + if (!setSerialNumber(X509_get_serialNumber(cert.get()), serial)) + return NULL; + + if (!X509_set_issuer_name(cert.get(), x509.get() ? X509_get_subject_name(x509.get()) : X509_REQ_get_subject_name(request.get()))) + return NULL; + + if (!X509_gmtime_adj(X509_get_notBefore(cert.get()), (-2)*24*60*60)) + return NULL; + + if (timeNotAfter) { + if (!X509_set_notAfter(cert.get(), timeNotAfter)) + return NULL; + } else if (!X509_gmtime_adj(X509_get_notAfter(cert.get()), 60*60*24*356*3)) + return NULL; + + if (!X509_set_subject_name(cert.get(), X509_REQ_get_subject_name(request.get()))) + return NULL; + + Ssl::EVP_PKEY_Pointer tmppkey(X509_REQ_get_pubkey(request.get())); + + if (!tmppkey || !X509_set_pubkey(cert.get(), tmppkey.get())) + return NULL; + + if (!X509_sign(cert.get(), pkey.get(), EVP_sha1())) + return NULL; + + return cert.release(); +} + +bool Ssl::writeCertAndPrivateKeyToMemory(Ssl::X509_Pointer const & cert, Ssl::EVP_PKEY_Pointer const & pkey, std::string & bufferToWrite) +{ + bufferToWrite.clear(); + if (!pkey || !cert) + return false; + BIO_Pointer bio(BIO_new(BIO_s_mem())); + if (!bio) + return false; + + if (!PEM_write_bio_X509 (bio.get(), cert.get())) + return false; + + if (!PEM_write_bio_PrivateKey(bio.get(), pkey.get(), NULL, NULL, 0, NULL, NULL)) + return false; + + char *ptr = NULL; + long len = BIO_get_mem_data(bio.get(), &ptr); + if (!ptr) + return false; + + bufferToWrite = std::string(ptr, len); + return true; +} + +bool Ssl::writeCertAndPrivateKeyToFile(Ssl::X509_Pointer const & cert, Ssl::EVP_PKEY_Pointer const & pkey, char const * filename) +{ + if (!pkey || !cert) + return false; + + Ssl::BIO_Pointer bio(BIO_new(BIO_s_file_internal())); + if (!bio) + return false; + if (!BIO_write_filename(bio.get(), const_cast(filename))) + return false; + + if (!PEM_write_bio_X509(bio.get(), cert.get())) + return false; + + if (!PEM_write_bio_PrivateKey(bio.get(), pkey.get(), NULL, NULL, 0, NULL, NULL)) + return false; + + return true; +} + +bool Ssl::readCertAndPrivateKeyFromMemory(Ssl::X509_Pointer & cert, Ssl::EVP_PKEY_Pointer & pkey, char const * bufferToRead) +{ + Ssl::BIO_Pointer bio(BIO_new(BIO_s_mem())); + BIO_puts(bio.get(), bufferToRead); + + X509 * certPtr = NULL; + cert.reset(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)); + if (!pkey) + return false; + + return true; +} + +bool Ssl::generateSslCertificateAndPrivateKey(char const *host, Ssl::X509_Pointer const & signedX509, Ssl::EVP_PKEY_Pointer const & signedPkey, Ssl::X509_Pointer & cert, Ssl::EVP_PKEY_Pointer & pkey, BIGNUM const * serial) +{ + pkey.reset(createSslPrivateKey()); + if (!pkey) + return false; + + Ssl::X509_REQ_Pointer request(createNewX509Request(pkey, host)); + if (!request) + return false; + + if (signedX509.get() && signedPkey.get()) + cert.reset(signRequest(request, signedX509, signedPkey, X509_get_notAfter(signedX509.get()), serial)); + else + cert.reset(signRequest(request, signedX509, pkey, NULL, serial)); + + if (!cert) + return false; + + return true; +} + +/** + \ingroup ServerProtocolSSLInternal + * Read certificate from file. + */ +static X509 * readSslX509Certificate(char const * certFilename) +{ + if (!certFilename) + return NULL; + Ssl::BIO_Pointer bio(BIO_new(BIO_s_file_internal())); + if (!bio) + return NULL; + if (!BIO_read_filename(bio.get(), certFilename)) + return NULL; + X509 *certificate = PEM_read_bio_X509(bio.get(), NULL, NULL, NULL); + return certificate; +} + +/** + \ingroup ServerProtocolSSLInternal + * Read private key from file. Make sure that this is not encrypted file. + */ +static EVP_PKEY * readSslPrivateKey(char const * keyFilename) +{ + if (!keyFilename) + return NULL; + Ssl::BIO_Pointer bio(BIO_new(BIO_s_file_internal())); + if (!bio) + return NULL; + if (!BIO_read_filename(bio.get(), keyFilename)) + return NULL; + EVP_PKEY *pkey = PEM_read_bio_PrivateKey(bio.get(), NULL, NULL, NULL); + return pkey; +} + +void Ssl::readCertAndPrivateKeyFromFiles(Ssl::X509_Pointer & cert, Ssl::EVP_PKEY_Pointer & pkey, char const * certFilename, char const * keyFilename) +{ + if (keyFilename == NULL) + keyFilename = certFilename; + pkey.reset(readSslPrivateKey(keyFilename)); + cert.reset(readSslX509Certificate(certFilename)); + if (!pkey || !cert || !X509_check_private_key(cert.get(), pkey.get())) { + pkey.reset(NULL); + cert.reset(NULL); + } +} + +bool Ssl::sslDateIsInTheFuture(char const * date) +{ + ASN1_UTCTIME tm; + tm.flags = 0; + tm.type = 23; + tm.data = (unsigned char *)date; + tm.length = strlen(date); + + return (X509_cmp_current_time(&tm) > 0); +} diff -u -r -N squid-3.1.12/src/ssl/gadgets.h squid-3.1.12.1/src/ssl/gadgets.h --- squid-3.1.12/src/ssl/gadgets.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.1.12.1/src/ssl/gadgets.h 2011-04-19 17:27:09.000000000 +1200 @@ -0,0 +1,135 @@ +/* + * 2009/01/17 + */ + +#ifndef SQUID_SSL_GADGETS_H +#define SQUID_SSL_GADGETS_H + +#include "base/TidyPointer.h" + +#if HAVE_OPENSSL_SSL_H +#include +#endif +#if HAVE_OPENSSL_TXT_DB_H +#include +#endif +#if HAVE_STRING +#include +#endif + +namespace Ssl +{ +/** + \defgroup SslCrtdSslAPI ssl_crtd SSL api. + These functions must not depend on Squid runtime code such as debug() + because they are used by ssl_crtd. + */ + +// Macro to be used to define the C++ equivalent function of an extern "C" +// function. The C++ function suffixed with the _cpp extension +#define CtoCpp1(function, argument) \ + extern "C++" inline void function ## _cpp(argument a) { \ + function(a); \ + } + +/** + \ingroup SslCrtdSslAPI + * TidyPointer typedefs for common SSL objects + */ +CtoCpp1(X509_free, X509 *) +typedef TidyPointer X509_Pointer; + +CtoCpp1(EVP_PKEY_free, EVP_PKEY *) +typedef TidyPointer EVP_PKEY_Pointer; + +CtoCpp1(BN_free, BIGNUM *) +typedef TidyPointer BIGNUM_Pointer; + +CtoCpp1(BIO_free, BIO *) +typedef TidyPointer BIO_Pointer; + +CtoCpp1(ASN1_INTEGER_free, ASN1_INTEGER *) +typedef TidyPointer ASN1_INT_Pointer; + +CtoCpp1(TXT_DB_free, TXT_DB *) +typedef TidyPointer TXT_DB_Pointer; + +CtoCpp1(X509_NAME_free, X509_NAME *) +typedef TidyPointer X509_NAME_Pointer; + +CtoCpp1(RSA_free, RSA *) +typedef TidyPointer RSA_Pointer; + +CtoCpp1(X509_REQ_free, X509_REQ *) +typedef TidyPointer X509_REQ_Pointer; + +CtoCpp1(SSL_CTX_free, SSL_CTX *) +typedef TidyPointer SSL_CTX_Pointer; + +CtoCpp1(SSL_free, SSL *) +typedef TidyPointer SSL_Pointer; + + +/** + \ingroup SslCrtdSslAPI + * Create 1024 bits rsa key. + */ +EVP_PKEY * createSslPrivateKey(); + +/** + \ingroup SslCrtdSslAPI + * Create request on certificate for a host. + */ +X509_REQ * createNewX509Request(EVP_PKEY_Pointer const & pkey, const char * hostname); + +/** + \ingroup SslCrtdSslAPI + * Write private key and SSL certificate to memory. + */ +bool writeCertAndPrivateKeyToMemory(X509_Pointer const & cert, EVP_PKEY_Pointer const & pkey, std::string & bufferToWrite); + +/** + \ingroup SslCrtdSslAPI + * Write private key and SSL certificate to file. + */ +bool writeCertAndPrivateKeyToFile(X509_Pointer const & cert, EVP_PKEY_Pointer const & pkey, char const * filename); + +/** + \ingroup SslCrtdSslAPI + * Write private key and SSL certificate to memory. + */ +bool readCertAndPrivateKeyFromMemory(X509_Pointer & cert, EVP_PKEY_Pointer & pkey, char const * bufferToRead); + +/** + \ingroup SslCrtdSslAPI + * Sign SSL request. + * \param x509 if this param equals NULL, returning certificate will be selfsigned. + * \return X509 Signed certificate. + */ +X509 * signRequest(X509_REQ_Pointer const & request, X509_Pointer const & x509, EVP_PKEY_Pointer const & pkey, ASN1_TIME * timeNotAfter, BIGNUM const * serial); + +/** + \ingroup SslCrtdSslAPI + * Decide on the kind of certificate and generate a CA- or self-signed one. + * Return generated certificate and private key in resultX509 and resultPkey + * variables. + */ +bool generateSslCertificateAndPrivateKey(char const *host, X509_Pointer const & signedX509, EVP_PKEY_Pointer const & signedPkey, X509_Pointer & cert, EVP_PKEY_Pointer & pkey, BIGNUM const* serial); + +/** + \ingroup SslCrtdSslAPI + * Read certificate and private key from files. + * \param certFilename name of file with certificate. + * \param keyFilename name of file with private key. + */ +void readCertAndPrivateKeyFromFiles(X509_Pointer & cert, EVP_PKEY_Pointer & pkey, char const * certFilename, char const * keyFilename); + +/** + \ingroup SslCrtdSslAPI + * Verify date. Date format it ASN1_UTCTIME. if there is out of date error, + * return false. +*/ +bool sslDateIsInTheFuture(char const * date); + +} // namespace Ssl +#endif // SQUID_SSL_GADGETS_H diff -u -r -N squid-3.1.12/src/ssl/helper.cc squid-3.1.12.1/src/ssl/helper.cc --- squid-3.1.12/src/ssl/helper.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.1.12.1/src/ssl/helper.cc 2011-04-19 17:27:09.000000000 +1200 @@ -0,0 +1,92 @@ +/* + * 2008/11/14 + */ + +#include "config.h" +#include "ssl/Config.h" +#include "ssl/helper.h" +#include "SquidTime.h" +#include "SwapDir.h" + +Ssl::Helper * Ssl::Helper::GetInstance() +{ + static Ssl::Helper sslHelper; + return &sslHelper; +} + +Ssl::Helper::Helper() +{ + Init(); +} + +Ssl::Helper::~Helper() +{ + Shutdown(); +} + +void Ssl::Helper::Init() +{ + if (ssl_crtd == NULL) + ssl_crtd = helperCreate("ssl_crtd"); + ssl_crtd->n_to_start = Ssl::TheConfig.ssl_crtd_n_running; + ssl_crtd->ipc_type = IPC_STREAM; + assert(ssl_crtd->cmdline == NULL); + { + char *tmp = xstrdup(Ssl::TheConfig.ssl_crtd); + char *tmp_begin = tmp; + char * token = NULL; + bool db_path_was_found = false; + bool block_size_was_found = false; + char buffer[20] = "2048"; + while ((token = strwordtok(NULL, &tmp))) { + wordlistAdd(&ssl_crtd->cmdline, token); + if (!strcmp(token, "-b")) + block_size_was_found = true; + if (!strcmp(token, "-s")) { + db_path_was_found = true; + } else if (db_path_was_found) { + db_path_was_found = false; + int fs_block_size = 0; + storeDirGetBlkSize(token, &fs_block_size); + snprintf(buffer, sizeof(buffer), "%i", fs_block_size); + } + } + if (!block_size_was_found) { + wordlistAdd(&ssl_crtd->cmdline, "-b"); + wordlistAdd(&ssl_crtd->cmdline, buffer); + } + safe_free(tmp_begin); + } + ssl_crtd->return_full_reply = true; + helperOpenServers(ssl_crtd); +} + +void Ssl::Helper::Shutdown() +{ + if (!ssl_crtd) + return; + helperShutdown(ssl_crtd); + wordlistDestroy(&ssl_crtd->cmdline); + if (!shutting_down) + return; + helperFree(ssl_crtd); + ssl_crtd = NULL; +} + +void Ssl::Helper::sslSubmit(CrtdMessage const & message, HLPCB * callback, void * data) +{ + static time_t first_warn = 0; + + if (ssl_crtd->stats.queue_size >= (int)(ssl_crtd->n_running * 2)) { + if (first_warn == 0) + first_warn = squid_curtime; + if (squid_curtime - first_warn > 3 * 60) + fatal("SSL servers not responding for 3 minutes"); + debugs(34, 1, HERE << "Queue overload, rejecting"); + callback(data, (char *)"error 45 Temporary network problem, please retry later"); + return; + } + + first_warn = 0; + helperSubmit(ssl_crtd, message.compose().c_str(), callback, data); +} diff -u -r -N squid-3.1.12/src/ssl/helper.h squid-3.1.12.1/src/ssl/helper.h --- squid-3.1.12/src/ssl/helper.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.1.12.1/src/ssl/helper.h 2011-04-19 17:27:09.000000000 +1200 @@ -0,0 +1,34 @@ +/* + * $Id$ + */ + +#ifndef SQUID_SSL_HELPER_H +#define SQUID_SSL_HELPER_H + +#include "../helper.h" +#include "ssl/crtd_message.h" + +namespace Ssl +{ +/** + * Set of thread for ssl_crtd. This class is singleton. Use this class only + * over GetIntance() static method. This class use helper structure + * for threads management. + */ +class Helper +{ +public: + static Helper * GetInstance(); ///< Instance class. + void Init(); ///< Init helper structure. + void Shutdown(); ///< Shutdown helper structure. + /// Submit crtd message to external crtd server. + void sslSubmit(CrtdMessage const & message, HLPCB * callback, void *data); +private: + Helper(); + ~Helper(); + + helper * ssl_crtd; ///< helper for management of ssl_crtd. +}; + +} //namespace Ssl +#endif // SQUID_SSL_HELPER_H diff -u -r -N squid-3.1.12/src/ssl/Makefile.am squid-3.1.12.1/src/ssl/Makefile.am --- squid-3.1.12/src/ssl/Makefile.am 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.1.12.1/src/ssl/Makefile.am 2011-04-19 17:27:09.000000000 +1200 @@ -0,0 +1,40 @@ +include $(top_srcdir)/src/Common.am +include $(top_srcdir)/src/TestHeaders.am + +noinst_LTLIBRARIES = libsslsquid.la libsslutil.la + +EXTRA_PROGRAMS = \ + ssl_crtd + +if USE_SSL_CRTD +SSL_CRTD = ssl_crtd +SSL_CRTD_SOURCE = \ + helper.cc \ + helper.h +else +SSL_CRTD = +SSL_CRTD_SOURCE = +endif + +libsslsquid_la_SOURCES = \ + context_storage.cc \ + context_storage.h \ + Config.cc \ + Config.h \ + ErrorDetail.cc \ + ErrorDetail.h + +libsslutil_la_SOURCES = \ + gadgets.cc \ + gadgets.h \ + crtd_message.cc \ + crtd_message.h \ + $(SSL_CRTD_SOURCE) + +libexec_PROGRAMS = \ + $(SSL_CRTD) + +if USE_SSL_CRTD +ssl_crtd_SOURCES = ssl_crtd.cc certificate_db.cc certificate_db.h +ssl_crtd_LDADD = $(SSLLIB) -lsslutil ../../compat/libcompat.la ../../lib/libmiscutil.a +endif diff -u -r -N squid-3.1.12/src/ssl/Makefile.in squid-3.1.12.1/src/ssl/Makefile.in --- squid-3.1.12/src/ssl/Makefile.in 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.1.12.1/src/ssl/Makefile.in 2011-04-19 17:28:09.000000000 +1200 @@ -0,0 +1,787 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/src/Common.am $(top_srcdir)/src/TestHeaders.am +check_PROGRAMS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) +EXTRA_PROGRAMS = ssl_crtd$(EXEEXT) +libexec_PROGRAMS = $(am__EXEEXT_1) +subdir = src/ssl +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/include/autoconf.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsslsquid_la_LIBADD = +am_libsslsquid_la_OBJECTS = context_storage.lo Config.lo \ + ErrorDetail.lo +libsslsquid_la_OBJECTS = $(am_libsslsquid_la_OBJECTS) +libsslutil_la_LIBADD = +am__libsslutil_la_SOURCES_DIST = gadgets.cc gadgets.h crtd_message.cc \ + crtd_message.h helper.cc helper.h +@USE_SSL_CRTD_TRUE@am__objects_1 = helper.lo +am_libsslutil_la_OBJECTS = gadgets.lo crtd_message.lo $(am__objects_1) +libsslutil_la_OBJECTS = $(am_libsslutil_la_OBJECTS) +@USE_SSL_CRTD_TRUE@am__EXEEXT_1 = ssl_crtd$(EXEEXT) +am__installdirs = "$(DESTDIR)$(libexecdir)" +PROGRAMS = $(libexec_PROGRAMS) +am__ssl_crtd_SOURCES_DIST = ssl_crtd.cc certificate_db.cc \ + certificate_db.h +@USE_SSL_CRTD_TRUE@am_ssl_crtd_OBJECTS = ssl_crtd.$(OBJEXT) \ +@USE_SSL_CRTD_TRUE@ certificate_db.$(OBJEXT) +ssl_crtd_OBJECTS = $(am_ssl_crtd_OBJECTS) +am__DEPENDENCIES_1 = +@USE_SSL_CRTD_TRUE@ssl_crtd_DEPENDENCIES = $(am__DEPENDENCIES_1) \ +@USE_SSL_CRTD_TRUE@ ../../compat/libcompat.la \ +@USE_SSL_CRTD_TRUE@ ../../lib/libmiscutil.a +DEFAULT_INCLUDES = +depcomp = $(SHELL) $(top_srcdir)/cfgaux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libsslsquid_la_SOURCES) $(libsslutil_la_SOURCES) \ + $(ssl_crtd_SOURCES) +DIST_SOURCES = $(libsslsquid_la_SOURCES) \ + $(am__libsslutil_la_SOURCES_DIST) $(am__ssl_crtd_SOURCES_DIST) +ETAGS = etags +CTAGS = ctags +am__tty_colors = \ +red=; grn=; lgn=; blu=; std= +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ADAPTATION_LIBS = @ADAPTATION_LIBS@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AR = @AR@ +ARGZ_H = @ARGZ_H@ +AR_R = @AR_R@ +AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@ +AUTH_MODULES = @AUTH_MODULES@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASIC_AUTH_HELPERS = @BASIC_AUTH_HELPERS@ +CACHE_EFFECTIVE_USER = @CACHE_EFFECTIVE_USER@ +CACHE_HTTP_PORT = @CACHE_HTTP_PORT@ +CACHE_ICP_PORT = @CACHE_ICP_PORT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGIEXT = @CGIEXT@ +CHMOD = @CHMOD@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPUNITCONFIG = @CPPUNITCONFIG@ +CRYPTLIB = @CRYPTLIB@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFAULT_LOG_DIR = @DEFAULT_LOG_DIR@ +DEFAULT_PIDFILE = @DEFAULT_PIDFILE@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@ +DISK_LIBS = @DISK_LIBS@ +DISK_LINKOBJS = @DISK_LINKOBJS@ +DISK_MODULES = @DISK_MODULES@ +DISK_OS_LIBS = @DISK_OS_LIBS@ +DISK_PROGRAMS = @DISK_PROGRAMS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECAPLIB = @ECAPLIB@ +ECAP_LIBS = @ECAP_LIBS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EPOLL_LIBS = @EPOLL_LIBS@ +EXEEXT = @EXEEXT@ +EXPATLIB = @EXPATLIB@ +EXTERNAL_ACL_HELPERS = @EXTERNAL_ACL_HELPERS@ +FALSE = @FALSE@ +FGREP = @FGREP@ +GREP = @GREP@ +ICAP_LIBS = @ICAP_LIBS@ +INCLTDL = @INCLTDL@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBLTDL = @LIBLTDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSASL = @LIBSASL@ +LIBTOOL = @LIBTOOL@ +LIB_DB = @LIB_DB@ +LIB_LBER = @LIB_LBER@ +LIB_LDAP = @LIB_LDAP@ +LIPO = @LIPO@ +LN = @LN@ +LN_S = @LN_S@ +LTDLDEPS = @LTDLDEPS@ +LTDLINCL = @LTDLINCL@ +LTDLOPEN = @LTDLOPEN@ +LTLIBOBJS = @LTLIBOBJS@ +LT_CONFIG_H = @LT_CONFIG_H@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MINGW_LIBS = @MINGW_LIBS@ +MKDIR = @MKDIR@ +MKDIR_P = @MKDIR_P@ +MV = @MV@ +NEGOTIATE_AUTH_HELPERS = @NEGOTIATE_AUTH_HELPERS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NTLM_AUTH_HELPERS = @NTLM_AUTH_HELPERS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPT_DEFAULT_HOSTS = @OPT_DEFAULT_HOSTS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PO2HTML = @PO2HTML@ +RANLIB = @RANLIB@ +REGEXLIB = @REGEXLIB@ +REPL_LIBS = @REPL_LIBS@ +REPL_OBJS = @REPL_OBJS@ +REPL_POLICIES = @REPL_POLICIES@ +RM = @RM@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SH = @SH@ +SHELL = @SHELL@ +SNMPLIB = @SNMPLIB@ +SQUID_CFLAGS = @SQUID_CFLAGS@ +SQUID_CPPUNIT_INC = @SQUID_CPPUNIT_INC@ +SQUID_CPPUNIT_LA = @SQUID_CPPUNIT_LA@ +SQUID_CPPUNIT_LIBS = @SQUID_CPPUNIT_LIBS@ +SQUID_CXXFLAGS = @SQUID_CXXFLAGS@ +SSLLIB = @SSLLIB@ +STORE_LIBS_TO_ADD = @STORE_LIBS_TO_ADD@ +STORE_LIBS_TO_BUILD = @STORE_LIBS_TO_BUILD@ +STORE_TESTS = @STORE_TESTS@ +STRIP = @STRIP@ +TRUE = @TRUE@ +VERSION = @VERSION@ +WIN32_PSAPI = @WIN32_PSAPI@ +XMLLIB = @XMLLIB@ +XTRA_LIBS = @XTRA_LIBS@ +XTRA_OBJS = @XTRA_OBJS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +ltdl_LIBOBJS = @ltdl_LIBOBJS@ +ltdl_LTLIBOBJS = @ltdl_LTLIBOBJS@ +makesnmplib = @makesnmplib@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CFLAGS = $(SQUID_CFLAGS) +AM_CXXFLAGS = $(SQUID_CXXFLAGS) +CLEANFILES = testHeaders +TESTS = testHeaders +INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) +noinst_LTLIBRARIES = libsslsquid.la libsslutil.la +@USE_SSL_CRTD_FALSE@SSL_CRTD = +@USE_SSL_CRTD_TRUE@SSL_CRTD = ssl_crtd +@USE_SSL_CRTD_FALSE@SSL_CRTD_SOURCE = +@USE_SSL_CRTD_TRUE@SSL_CRTD_SOURCE = \ +@USE_SSL_CRTD_TRUE@ helper.cc \ +@USE_SSL_CRTD_TRUE@ helper.h + +libsslsquid_la_SOURCES = \ + context_storage.cc \ + context_storage.h \ + Config.cc \ + Config.h \ + ErrorDetail.cc \ + ErrorDetail.h + +libsslutil_la_SOURCES = \ + gadgets.cc \ + gadgets.h \ + crtd_message.cc \ + crtd_message.h \ + $(SSL_CRTD_SOURCE) + +@USE_SSL_CRTD_TRUE@ssl_crtd_SOURCES = ssl_crtd.cc certificate_db.cc certificate_db.h +@USE_SSL_CRTD_TRUE@ssl_crtd_LDADD = $(SSLLIB) -lsslutil ../../compat/libcompat.la ../../lib/libmiscutil.a +all: all-am + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/src/Common.am $(top_srcdir)/src/TestHeaders.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/ssl/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/ssl/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libsslsquid.la: $(libsslsquid_la_OBJECTS) $(libsslsquid_la_DEPENDENCIES) + $(CXXLINK) $(libsslsquid_la_OBJECTS) $(libsslsquid_la_LIBADD) $(LIBS) +libsslutil.la: $(libsslutil_la_OBJECTS) $(libsslutil_la_DEPENDENCIES) + $(CXXLINK) $(libsslutil_la_OBJECTS) $(libsslutil_la_LIBADD) $(LIBS) + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +install-libexecPROGRAMS: $(libexec_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(libexecdir)" || $(MKDIR_P) "$(DESTDIR)$(libexecdir)" + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-libexecPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(libexecdir)" && rm -f $$files + +clean-libexecPROGRAMS: + @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +ssl_crtd$(EXEEXT): $(ssl_crtd_OBJECTS) $(ssl_crtd_DEPENDENCIES) + @rm -f ssl_crtd$(EXEEXT) + $(CXXLINK) $(ssl_crtd_OBJECTS) $(ssl_crtd_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@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)/certificate_db.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/context_storage.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crtd_message.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gadgets.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/helper.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ssl_crtd.Po@am__quote@ + +.cc.o: +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + echo "$$grn$$dashes"; \ + else \ + echo "$$red$$dashes"; \ + fi; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes$$std"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(libexecdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-checkPROGRAMS clean-generic clean-libexecPROGRAMS \ + clean-libtool clean-noinstLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libexecPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libexecPROGRAMS + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \ + clean-checkPROGRAMS clean-generic clean-libexecPROGRAMS \ + clean-libtool clean-noinstLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am \ + install-libexecPROGRAMS install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-libexecPROGRAMS + + +$(OBJS): $(top_srcdir)/include/version.h $(top_builddir)/include/autoconf.h + +testHeaders: $(srcdir)/*.h + $(SHELL) $(top_srcdir)/test-suite/testheaders.sh "$(CXXCOMPILE)" "$(srcdir)" || exit 1 + +.PHONY: testHeaders + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff -u -r -N squid-3.1.12/src/ssl/ssl_crtd.cc squid-3.1.12.1/src/ssl/ssl_crtd.cc --- squid-3.1.12/src/ssl/ssl_crtd.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.1.12.1/src/ssl/ssl_crtd.cc 2011-04-19 17:27:09.000000000 +1200 @@ -0,0 +1,356 @@ +/* + * $Id$ + */ + +#include "config.h" +#include "ssl/gadgets.h" +#include "ssl/crtd_message.h" +#include "ssl/certificate_db.h" + +#if HAVE_CSTRING +#include +#endif +#if HAVE_SSTREAM +#include +#endif +#if HAVE_IOSTREAM +#include +#endif +#if HAVE_STDEXCEPT +#include +#endif +#if HAVE_STRING +#include +#endif +#if HAVE_GETOPT_H +#include +#endif + +/** + \defgroup ssl_crtd ssl_crtd + \ingroup ExternalPrograms + \par + Because the standart generation of ssl certificate for + sslBump feature, Squid must use external proccess to + actually make these calls. This process generate new ssl + certificates and worked with ssl certificates disk cache. + Typically there will be five ssl_crtd processes spawned + from Squid. Communication occurs via TCP sockets bound + to the loopback interface. The class in helper.h are + primally concerned with starting and stopping the ssl_crtd. + Reading and writing to and from the ssl_crtd occurs in the + \link IPCacheAPI IP\endlink and the dnsservers occurs in + the \link IPCacheAPI IP\endlink and \link FQDNCacheAPI + FQDN\endlink cache modules. + + \section ssl_crtdInterface Command Line Interface + \verbatim +usage: ssl_crtd -hv -s ssl_storage_path -M storage_max_size + -h Help + -v Version + -s ssl_storage_path Path to specific disk storage of ssl server + certificates. + -M storage_max_size max size of ssl certificates storage. + -b fs_block_size File system block size in bytes. Need for processing + natural size of certificate on disk. Default value is + 2048 bytes." + + After running write requests in the next format: + + There are two kind of request now: + new_certificate 14 host=host.dom + Create new private key and selfsigned certificate for "host.dom". + + new_certificate xxx host=host.dom + -----BEGIN CERTIFICATE----- + ... + -----END CERTIFICATE----- + -----BEGIN RSA PRIVATE KEY----- + ... + -----END RSA PRIVATE KEY----- + Create new private key and certificate request for "host.dom". + Sign new request by received certificate and private key. + +usage: ssl_crtd -c -s ssl_store_path\n -n new_serial_number + -c Init ssl db directories and exit. + -n new_serial_number HEX serial number to use when initializing db. + The default value of serial number is + the number of seconds since Epoch minus 1200000000 + +usage: ssl_crtd -g -s ssl_store_path + -g Show current serial number and exit. + \endverbatim + */ + +#ifndef HELPER_INPUT_BUFFER +#define HELPER_INPUT_BUFFER 8192 +#endif + +int debug_enabled = 0; + +static const char *const B_KBYTES_STR = "KB"; +static const char *const B_MBYTES_STR = "MB"; +static const char *const B_GBYTES_STR = "GB"; +static const char *const B_BYTES_STR = "B"; + +/** + \ingroup ssl_crtd + * Get current time. +*/ +time_t getCurrentTime(void) +{ + struct timeval current_time; +#if GETTIMEOFDAY_NO_TZP + gettimeofday(¤t_time); +#else + gettimeofday(¤t_time, NULL); +#endif + return current_time.tv_sec; +} + +/** + \ingroup ssl_crtd + * Parse bytes unit. It would be one of the next value: MB, GB, KB or B. + * This function is caseinsensitive. + */ +static size_t parseBytesUnits(const char * unit) +{ + if (!strncasecmp(unit, B_BYTES_STR, strlen(B_BYTES_STR)) || + !strncasecmp(unit, "", strlen(unit))) + return 1; + + if (!strncasecmp(unit, B_KBYTES_STR, strlen(B_KBYTES_STR))) + return 1 << 10; + + if (!strncasecmp(unit, B_MBYTES_STR, strlen(B_MBYTES_STR))) + return 1 << 20; + + if (!strncasecmp(unit, B_GBYTES_STR, strlen(B_GBYTES_STR))) + return 1 << 30; + + return 0; +} + +/** + \ingroup ssl_crtd + * Parse uninterrapted string of bytes value. It looks like "4MB". + */ +static bool parseBytesOptionValue(size_t * bptr, char const * value) +{ + // Find number from string beginning. + char const * number_begin = value; + char const * number_end = value; + + while ((*number_end >= '0' && *number_end <= '9')) { + number_end++; + } + + std::string number(number_begin, number_end - number_begin); + std::istringstream in(number); + int d = 0; + if (!(in >> d)) + return false; + + int m; + if ((m = parseBytesUnits(number_end)) == 0) { + return false; + } + + *bptr = static_cast(m * d); + if (static_cast(*bptr * 2) != m * d * 2) + return false; + + return true; +} + +/** + \ingroup ssl_crtd + * Print help using response code. + */ +static void usage() +{ + std::string example_host_name = "host.dom"; + std::string request_string = Ssl::CrtdMessage::param_host + "=" + example_host_name; + std::stringstream request_string_size_stream; + request_string_size_stream << request_string.length(); + std::string help_string = + "usage: ssl_crtd -hv -s ssl_storage_path -M storage_max_size\n" + "\t-h Help\n" + "\t-v Version\n" + "\t-s ssl_storage_path Path to specific disk storage of ssl server\n" + "\t certificates.\n" + "\t-M storage_max_size max size of ssl certificates storage.\n" + "\t-b fs_block_size File system block size in bytes. Need for processing\n" + "\t natural size of certificate on disk. Default value is\n" + "\t 2048 bytes.\n" + "\n" + "After running write requests in the next format:\n" + "\n" + "There are two kind of request now:\n" + + Ssl::CrtdMessage::code_new_certificate + " " + request_string_size_stream.str() + " " + request_string + "\n" + + "\tCreate new private key and selfsigned certificate for \"host.dom\".\n" + + Ssl::CrtdMessage::code_new_certificate + " xxx " + request_string + "\n" + + "-----BEGIN CERTIFICATE-----\n" + "...\n" + "-----END CERTIFICATE-----\n" + "-----BEGIN RSA PRIVATE KEY-----\n" + "...\n" + "-----END RSA PRIVATE KEY-----\n" + "\tCreate new private key and certificate request for \"host.dom\"\n" + "\tSign new request by received certificate and private key.\n" + "usage: ssl_crtd -c -s ssl_store_path -n new_serial_number\n" + "\t-c Init ssl db directories and exit.\n" + "\t-n new_serial_number HEX serial number to use when initializing db.\n" + "\t The default value of serial number is\n" + "\t the number of seconds since Epoch minus 1200000000\n" + "usage: ssl_crtd -g -s ssl_store_path\n" + "\t-g Show current serial number and exit."; + std::cerr << help_string << std::endl; +} + +/** + \ingroup ssl_crtd + * Proccess new request message. + */ +static bool proccessNewRequest(Ssl::CrtdMessage const & request_message, std::string const & db_path, size_t max_db_size, size_t fs_block_size) +{ + Ssl::CrtdMessage::BodyParams map; + std::string body_part; + request_message.parseBody(map, body_part); + + Ssl::CrtdMessage::BodyParams::iterator i = map.find(Ssl::CrtdMessage::param_host); + if (i == map.end()) + throw std::runtime_error("Cannot find \"" + Ssl::CrtdMessage::param_host + "\" parameter in request message."); + std::string host = i->second; + + Ssl::CertificateDb db(db_path, max_db_size, fs_block_size); + + Ssl::X509_Pointer cert; + Ssl::EVP_PKEY_Pointer pkey; + db.find("/CN=" + host, cert, pkey); + + if (!cert || !pkey) { + Ssl::X509_Pointer certToSign; + Ssl::EVP_PKEY_Pointer pkeyToSign; + Ssl::readCertAndPrivateKeyFromMemory(certToSign, pkeyToSign, body_part.c_str()); + + Ssl::BIGNUM_Pointer serial(db.getCurrentSerialNumber()); + + if (!Ssl::generateSslCertificateAndPrivateKey(host.c_str(), certToSign, pkeyToSign, cert, pkey, serial.get())) + throw std::runtime_error("Cannot create ssl certificate or private key."); + if (!db.addCertAndPrivateKey(cert, pkey) && db.IsEnabledDiskStore()) + throw std::runtime_error("Cannot add certificate to db."); + } + + std::string bufferToWrite; + if (!Ssl::writeCertAndPrivateKeyToMemory(cert, pkey, bufferToWrite)) + throw std::runtime_error("Cannot write ssl certificate or/and private key to memory."); + + Ssl::CrtdMessage response_message; + response_message.setCode("ok"); + response_message.setBody(bufferToWrite); + + std::cout << response_message.compose(); + + return true; +} + +/** + \ingroup ssl_crtd + * This is the external ssl_crtd process. + */ +int main(int argc, char *argv[]) +{ + try { + int serial = (getCurrentTime() - 1200000000); + size_t max_db_size = 0; + size_t fs_block_size = 2048; + char c; + bool create_new_db = false; + bool show_sn = false; + std::string db_path; + // proccess options. + while ((c = getopt(argc, argv, "dcghvs:M:b:n:")) != -1) { + switch (c) { + case 'd': + debug_enabled = 1; + break; + case 'b': + if (!parseBytesOptionValue(&fs_block_size, optarg)) { + throw std::runtime_error("Error when parsing -b options value"); + } + break; + case 's': + db_path = optarg; + break; + case 'n': { + std::stringstream sn_stream(optarg); + sn_stream >> std::hex >> serial; + break; + } + case 'M': + if (!parseBytesOptionValue(&max_db_size, optarg)) { + throw std::runtime_error("Error when parsing -M options value"); + } + break; + case 'v': + std::cout << "ssl_crtd version " << VERSION << std::endl; + exit(0); + break; + case 'c': + create_new_db = true; + break; + case 'g': + show_sn = true; + break; + case 'h': + usage(); + exit(0); + default: + exit(0); + } + } + + if (create_new_db) { + std::cout << "Initialization SSL db..." << std::endl; + Ssl::CertificateDb::create(db_path, serial); + std::cout << "Done" << std::endl; + exit(0); + } + + if (show_sn) { + Ssl::CertificateDb db(db_path, 4096, 0); + std::cout << db.getSNString() << std::endl; + exit(0); + } + { + Ssl::CertificateDb::check(db_path, max_db_size); + } + // proccess request. + for (;;) { + char request[HELPER_INPUT_BUFFER]; + Ssl::CrtdMessage request_message; + Ssl::CrtdMessage::ParseResult parse_result = Ssl::CrtdMessage::INCOMPLETE; + + while (parse_result == Ssl::CrtdMessage::INCOMPLETE) { + if (fgets(request, HELPER_INPUT_BUFFER, stdin) == NULL) + return 1; + size_t gcount = strlen(request); + parse_result = request_message.parse(request, gcount); + } + + if (parse_result == Ssl::CrtdMessage::ERROR) { + throw std::runtime_error("Cannot parse request message."); + } else if (request_message.getCode() == Ssl::CrtdMessage::code_new_certificate) { + proccessNewRequest(request_message, db_path, max_db_size, fs_block_size); + } else { + throw std::runtime_error("Unknown request code: \"" + request_message.getCode() + "\"."); + } + std::cout.flush(); + } + } catch (std::runtime_error & error) { + std::cerr << argv[0] << ": " << error.what() << std::endl; + return 0; + } + return 0; +} diff -u -r -N squid-3.1.12/src/ssl_support.cc squid-3.1.12.1/src/ssl_support.cc --- squid-3.1.12/src/ssl_support.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/ssl_support.cc 2011-04-19 17:27:09.000000000 +1200 @@ -42,6 +42,9 @@ #include "fde.h" #include "acl/FilledChecklist.h" +#include "ssl/ErrorDetail.h" +#include "ssl_support.h" +#include "ssl/gadgets.h" /** \defgroup ServerProtocolSSLInternal Server-Side SSL Internals @@ -135,6 +138,68 @@ return rsa; } +int Ssl::asn1timeToString(ASN1_TIME *tm, char *buf, int len) +{ + BIO *bio; + int write = 0; + bio = BIO_new(BIO_s_mem()); + if (bio) { + if (ASN1_TIME_print(bio, tm)) + write = BIO_read(bio, buf, len-1); + BIO_free(bio); + } + buf[write]='\0'; + return write; +} + +int Ssl::matchX509CommonNames(X509 *peer_cert, void *check_data, int (*check_func)(void *check_data, ASN1_STRING *cn_data)) +{ + assert(peer_cert); + + X509_NAME *name = X509_get_subject_name(peer_cert); + + for (int i = X509_NAME_get_index_by_NID(name, NID_commonName, -1); i >= 0; i = X509_NAME_get_index_by_NID(name, NID_commonName, i)) { + + ASN1_STRING *cn_data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i)); + + if ( (*check_func)(check_data, cn_data) == 0) + return 1; + } + + STACK_OF(GENERAL_NAME) * altnames; + altnames = (STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(peer_cert, NID_subject_alt_name, NULL, NULL); + + if (altnames) { + int numalts = sk_GENERAL_NAME_num(altnames); + for (int i = 0; i < numalts; i++) { + const GENERAL_NAME *check = sk_GENERAL_NAME_value(altnames, i); + if (check->type != GEN_DNS) { + continue; + } + ASN1_STRING *cn_data = check->d.dNSName; + + if ( (*check_func)(check_data, cn_data) == 0) + return 1; + } + sk_GENERAL_NAME_pop_free(altnames, GENERAL_NAME_free); + } + return 0; +} + +static int check_domain( void *check_data, ASN1_STRING *cn_data) +{ + char cn[1024]; + const char *server = (const char *)check_data; + + if (cn_data->length > (int)sizeof(cn) - 1) { + return 1; //if does not fit our buffer just ignore + } + memcpy(cn, cn_data->data, cn_data->length); + cn[cn_data->length] = '\0'; + debugs(83, 4, "Verifying server domain " << server << " to certificate name/subjectAltName " << cn); + return matchDomainName(server, cn[0] == '*' ? cn + 1 : cn); +} + /// \ingroup ServerProtocolSSLInternal static int ssl_verify_cb(int ok, X509_STORE_CTX * ctx) @@ -146,6 +211,7 @@ void *dont_verify_domain = SSL_CTX_get_ex_data(sslctx, ssl_ctx_ex_index_dont_verify_domain); ACLChecklist *check = (ACLChecklist*)SSL_get_ex_data(ssl, ssl_ex_index_cert_error_check); X509 *peer_cert = ctx->cert; + Ssl::ssl_error_t error_no = SSL_ERROR_NONE; X509_NAME_oneline(X509_get_subject_name(peer_cert), buffer, sizeof(buffer)); @@ -154,65 +220,22 @@ debugs(83, 5, "SSL Certificate signature OK: " << buffer); if (server) { - int i; - int found = 0; - char cn[1024]; - - STACK_OF(GENERAL_NAME) * altnames; - altnames = (STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(peer_cert, NID_subject_alt_name, NULL, NULL); - if (altnames) { - int numalts = sk_GENERAL_NAME_num(altnames); - debugs(83, 3, "Verifying server domain " << server << " to certificate subjectAltName"); - for (i = 0; i < numalts; i++) { - const GENERAL_NAME *check = sk_GENERAL_NAME_value(altnames, i); - if (check->type != GEN_DNS) { - continue; - } - ASN1_STRING *data = check->d.dNSName; - if (data->length > (int)sizeof(cn) - 1) { - continue; - } - memcpy(cn, data->data, data->length); - cn[data->length] = '\0'; - debugs(83, 4, "Verifying server domain " << server << " to certificate name " << cn); - if (matchDomainName(server, cn[0] == '*' ? cn + 1 : cn) == 0) { - found = 1; - break; - } - } - } - - X509_NAME *name = X509_get_subject_name(peer_cert); - debugs(83, 3, "Verifying server domain " << server << " to certificate dn " << buffer); - - for (i = X509_NAME_get_index_by_NID(name, NID_commonName, -1); i >= 0; i = X509_NAME_get_index_by_NID(name, NID_commonName, i)) { - ASN1_STRING *data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i)); - - if (data->length > (int)sizeof(cn) - 1) - continue; - - memcpy(cn, data->data, data->length); - - cn[data->length] = '\0'; - - debugs(83, 4, "Verifying server domain " << server << " to certificate cn " << cn); - - if (matchDomainName(server, cn[0] == '*' ? cn + 1 : cn) == 0) { - found = 1; - break; - } - } + int found = Ssl::matchX509CommonNames(peer_cert, (void *)server, check_domain); if (!found) { debugs(83, 2, "SQUID_X509_V_ERR_DOMAIN_MISMATCH: Certificate " << buffer << " does not match domainname " << server); ok = 0; + error_no = SQUID_X509_V_ERR_DOMAIN_MISMATCH; + if (check) Filled(check)->ssl_error = SQUID_X509_V_ERR_DOMAIN_MISMATCH; } } } else { + error_no = ctx->error; switch (ctx->error) { + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: debugs(83, 5, "SSL Certficate error: CA not known: " << buffer); break; @@ -235,6 +258,10 @@ debugs(83, 5, "SSL Certificate has invalid \'not after\' field: " << buffer); break; + case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: + debugs(83, 5, "SSL Certificate is self signed: " << buffer); + break; + default: debugs(83, 1, "SSL unknown certificate error " << ctx->error << " in " << buffer); break; @@ -255,6 +282,14 @@ if (!dont_verify_domain && server) {} + if (error_no != SSL_ERROR_NONE && !SSL_get_ex_data(ssl, ssl_ex_index_ssl_error_detail) ) { + Ssl::ErrorDetail *errDetail = new Ssl::ErrorDetail(error_no, peer_cert); + if (!SSL_set_ex_data(ssl, ssl_ex_index_ssl_error_detail, errDetail)) { + debugs(83, 2, "Failed to set Ssl::ErrorDetail in ssl_verify_cb: Certificate " << buffer); + delete errDetail; + } + } + return ok; } @@ -524,55 +559,6 @@ return fl; } -struct SslErrorMapEntry { - const char *name; - ssl_error_t value; -}; - -static SslErrorMapEntry TheSslErrorMap[] = { - { "SQUID_X509_V_ERR_DOMAIN_MISMATCH", SQUID_X509_V_ERR_DOMAIN_MISMATCH }, - { "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT", X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT }, - { "X509_V_ERR_CERT_NOT_YET_VALID", X509_V_ERR_CERT_NOT_YET_VALID }, - { "X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD", X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD }, - { "X509_V_ERR_CERT_HAS_EXPIRED", X509_V_ERR_CERT_HAS_EXPIRED }, - { "X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD", X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD }, - { "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY", X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY }, - { "SSL_ERROR_NONE", SSL_ERROR_NONE }, - { NULL, SSL_ERROR_NONE } -}; - -ssl_error_t -sslParseErrorString(const char *name) -{ - assert(name); - - for (int i = 0; TheSslErrorMap[i].name; ++i) { - if (strcmp(name, TheSslErrorMap[i].name) == 0) - return TheSslErrorMap[i].value; - } - - if (xisdigit(*name)) { - const long int value = strtol(name, NULL, 0); - if (SQUID_SSL_ERROR_MIN <= value && value <= SQUID_SSL_ERROR_MAX) - return value; - fatalf("Too small or too bug SSL error code '%s'", name); - } - - fatalf("Unknown SSL error name '%s'", name); - return SSL_ERROR_SSL; // not reached -} - -const char * -sslFindErrorString(ssl_error_t value) -{ - for (int i = 0; TheSslErrorMap[i].name; ++i) { - if (TheSslErrorMap[i].value == value) - return TheSslErrorMap[i].name; - } - - return NULL; -} - // "dup" function for SSL_get_ex_new_index("cert_err_check") static int ssl_dupAclChecklist(CRYPTO_EX_DATA *, CRYPTO_EX_DATA *, void *, @@ -592,6 +578,15 @@ delete static_cast(ptr); // may be NULL } +// "free" function for SSL_get_ex_new_index("ssl_error_detail") +static void +ssl_free_ErrorDetail(void *, void *ptr, CRYPTO_EX_DATA *, + int, long, void *) +{ + Ssl::ErrorDetail *errDetail = static_cast (ptr); + delete errDetail; +} + /// \ingroup ServerProtocolSSLInternal static void ssl_initialize(void) @@ -630,6 +625,7 @@ ssl_ex_index_server = SSL_get_ex_new_index(0, (void *) "server", NULL, NULL, NULL); ssl_ctx_ex_index_dont_verify_domain = SSL_CTX_get_ex_new_index(0, (void *) "dont_verify_domain", NULL, NULL, NULL); ssl_ex_index_cert_error_check = SSL_get_ex_new_index(0, (void *) "cert_error_check", NULL, &ssl_dupAclChecklist, &ssl_freeAclChecklist); + ssl_ex_index_ssl_error_detail = SSL_get_ex_new_index(0, (void *) "ssl_error_detail", NULL, NULL, &ssl_free_ErrorDetail); } /// \ingroup ServerProtocolSSLInternal @@ -1206,4 +1202,58 @@ return str; } +/// \ingroup ServerProtocolSSLInternal +/// Create SSL context and apply ssl certificate and private key to it. +static SSL_CTX * createSSLContext(Ssl::X509_Pointer & x509, Ssl::EVP_PKEY_Pointer & pkey) +{ + Ssl::SSL_CTX_Pointer sslContext(SSL_CTX_new(SSLv23_server_method())); + + if (!SSL_CTX_use_certificate(sslContext.get(), x509.get())) + return NULL; + + if (!SSL_CTX_use_PrivateKey(sslContext.get(), pkey.get())) + return NULL; + return sslContext.release(); +} + +SSL_CTX * Ssl::generateSslContextUsingPkeyAndCertFromMemory(const char * data) +{ + Ssl::X509_Pointer cert; + Ssl::EVP_PKEY_Pointer pkey; + if (!readCertAndPrivateKeyFromMemory(cert, pkey, data)) + return NULL; + + if (!cert || !pkey) + return NULL; + + return createSSLContext(cert, pkey); +} + +SSL_CTX * Ssl::generateSslContext(char const *host, Ssl::X509_Pointer const & signedX509, Ssl::EVP_PKEY_Pointer const & signedPkey) +{ + Ssl::X509_Pointer cert; + Ssl::EVP_PKEY_Pointer pkey; + if (!generateSslCertificateAndPrivateKey(host, signedX509, signedPkey, cert, pkey, NULL)) { + return NULL; + } + if (!cert) + return NULL; + + if (!pkey) + return NULL; + + return createSSLContext(cert, pkey); +} + +bool Ssl::verifySslCertificateDate(SSL_CTX * sslContext) +{ + // Temporary ssl for getting X509 certificate from SSL_CTX. + Ssl::SSL_Pointer ssl(SSL_new(sslContext)); + X509 * cert = SSL_get_certificate(ssl.get()); + ASN1_TIME * time_notBefore = X509_get_notBefore(cert); + ASN1_TIME * time_notAfter = X509_get_notAfter(cert); + bool ret = (X509_cmp_current_time(time_notBefore) < 0 && X509_cmp_current_time(time_notAfter) > 0); + return ret; +} + #endif /* USE_SSL */ diff -u -r -N squid-3.1.12/src/ssl_support.h squid-3.1.12.1/src/ssl_support.h --- squid-3.1.12/src/ssl_support.h 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/ssl_support.h 2011-04-19 17:27:09.000000000 +1200 @@ -36,6 +36,7 @@ #define SQUID_SSL_SUPPORT_H #include "config.h" +#include "ssl/gadgets.h" #if HAVE_OPENSSL_SSL_H #include #endif @@ -88,15 +89,50 @@ /// \ingroup ServerProtocolSSLAPI const char *sslGetUserCertificateChainPEM(SSL *ssl); -typedef int ssl_error_t; -ssl_error_t sslParseErrorString(const char *name); -const char *sslFindErrorString(ssl_error_t value); - -// Custom SSL errors; assumes all official errors are positive -#define SQUID_X509_V_ERR_DOMAIN_MISMATCH -1 -// All SSL errors range: from smallest (negative) custom to largest SSL error -#define SQUID_SSL_ERROR_MIN SQUID_X509_V_ERR_DOMAIN_MISMATCH -#define SQUID_SSL_ERROR_MAX INT_MAX +namespace Ssl +{ +/** + \ingroup ServerProtocolSSLAPI + * Decide on the kind of certificate and generate a CA- or self-signed one +*/ +SSL_CTX *generateSslContext(char const *host, Ssl::X509_Pointer const & signedX509, Ssl::EVP_PKEY_Pointer const & signedPkey); + +/** + \ingroup ServerProtocolSSLAPI + * Check date of certificate signature. If there is out of date error fucntion + * returns false, true otherwise. + */ +bool verifySslCertificateDate(SSL_CTX * sslContext); + +/** + \ingroup ServerProtocolSSLAPI + * Read private key and certificate from memory and generate SSL context + * using their. + */ +SSL_CTX * generateSslContextUsingPkeyAndCertFromMemory(const char * data); + +/** + \ingroup ServerProtocolSSLAPI + * Iterates over the X509 common and alternate names and to see if matches with given data + * using the check_func. + \param peer_cert The X509 cert to check + \param check_data The data with which the X509 CNs compared + \param check_func The function used to match X509 CNs. The CN data passed as ASN1_STRING data + \return 1 if any of the certificate CN matches, 0 if none matches. + */ +int matchX509CommonNames(X509 *peer_cert, void *check_data, int (*check_func)(void *check_data, ASN1_STRING *cn_data)); + +/** + \ingroup ServerProtocolSSLAPI + * Convert a given ASN1_TIME to a string form. + \param tm the time in ASN1_TIME form + \param buf the buffer to write the output + \param len write at most len bytes + \return The number of bytes written + */ +int asn1timeToString(ASN1_TIME *tm, char *buf, int len); + +} //namespace Ssl #ifdef _SQUID_MSWIN_ diff -u -r -N squid-3.1.12/src/store.cc squid-3.1.12.1/src/store.cc --- squid-3.1.12/src/store.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/store.cc 2011-04-19 17:27:09.000000000 +1200 @@ -804,7 +804,6 @@ StoreEntry::write (StoreIOBuffer writeBuffer) { assert(mem_obj != NULL); - assert(writeBuffer.length >= 0); /* This assert will change when we teach the store to update */ PROF_start(StoreEntry_write); assert(store_status == STORE_PENDING); diff -u -r -N squid-3.1.12/src/String.cc squid-3.1.12.1/src/String.cc --- squid-3.1.12/src/String.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/String.cc 2011-04-19 17:27:09.000000000 +1200 @@ -247,7 +247,8 @@ String String::substr(String::size_type from, String::size_type to) const { - Must(from >= 0 && from < size()); +// Must(from >= 0 && from < size()); + Must(from < size()); Must(to > 0 && to <= size()); Must(to > from); diff -u -r -N squid-3.1.12/src/tools.cc squid-3.1.12.1/src/tools.cc --- squid-3.1.12/src/tools.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/tools.cc 2011-04-19 17:27:09.000000000 +1200 @@ -880,7 +880,16 @@ setMaxFD(void) { #if HAVE_SETRLIMIT && defined(RLIMIT_NOFILE) + + /* On Linux with 64-bit file support the sys/resource.h header + * uses #define to change the function definition to require rlimit64 + */ +#if defined(getrlimit) + struct rlimit64 rl; // Assume its a 64-bit redefine anyways. +#else struct rlimit rl; +#endif + if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { debugs(50, DBG_CRITICAL, "setrlimit: RLIMIT_NOFILE: " << xstrerror()); } else if (Config.max_filedescriptors > 0) { @@ -916,7 +925,16 @@ { #if HAVE_SETRLIMIT && defined(RLIMIT_NOFILE) && !defined(_SQUID_CYGWIN_) /* limit system filedescriptors to our own limit */ + + /* On Linux with 64-bit file support the sys/resource.h header + * uses #define to change the function definition to require rlimit64 + */ +#if defined(getrlimit) + struct rlimit64 rl; // Assume its a 64-bit redefine anyways. +#else struct rlimit rl; +#endif + if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { debugs(50, DBG_CRITICAL, "setrlimit: RLIMIT_NOFILE: " << xstrerror()); } else { diff -u -r -N squid-3.1.12/src/tunnel.cc squid-3.1.12.1/src/tunnel.cc --- squid-3.1.12/src/tunnel.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/tunnel.cc 2011-04-19 17:27:09.000000000 +1200 @@ -312,7 +312,7 @@ if (!fd_closed(server.fd())) commSetTimeout(server.fd(), Config.Timeout.read, tunnelTimeout, this); - if (len < 0 || errcode) + if (errcode) from.error (xerrno); else if (len == 0 || fd_closed(to.fd())) { comm_close(from.fd()); @@ -343,12 +343,10 @@ { debugs(26, 3, "tunnelWriteServer: FD " << server.fd() << ", " << len << " bytes written"); - if (flag == COMM_ERR_CLOSING) - return; - /* Error? */ - if (len < 0 || flag != COMM_OK) { - server.error(xerrno); // may call comm_close + if (flag != COMM_OK) { + if (flag != COMM_ERR_CLOSING) + server.error(xerrno); // may call comm_close return; } @@ -404,12 +402,10 @@ { debugs(26, 3, "tunnelWriteClient: FD " << client.fd() << ", " << len << " bytes written"); - if (flag == COMM_ERR_CLOSING) - return; - /* Error? */ - if (len < 0 || flag != COMM_OK) { - client.error(xerrno); // may call comm_close + if (flag != COMM_OK) { + if (flag != COMM_ERR_CLOSING) + client.error(xerrno); // may call comm_close return; } diff -u -r -N squid-3.1.12/src/url.cc squid-3.1.12.1/src/url.cc --- squid-3.1.12/src/url.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/url.cc 2011-04-19 17:27:09.000000000 +1200 @@ -325,6 +325,12 @@ } } + // Bug 3183 sanity check: If scheme is present, host must be too. + if (protocol != PROTO_NONE && (host == NULL || *host == '\0')) { + debugs(23, DBG_IMPORTANT, "SECURITY WARNING: Missing hostname in URL '" << url << "'. see access.log for details."); + return NULL; + } + if (t && *t == ':') { *t = '\0'; t++; diff -u -r -N squid-3.1.12/src/urn.cc squid-3.1.12.1/src/urn.cc --- squid-3.1.12/src/urn.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/urn.cc 2011-04-19 17:27:09.000000000 +1200 @@ -327,9 +327,9 @@ char *buf = urnState->reqbuf; StoreIOBuffer tempBuffer; - debugs(52, 3, "urnHandleReply: Called with size=" << (unsigned int)result.length << "."); + debugs(52, 3, "urnHandleReply: Called with size=" << result.length << "."); - if (EBIT_TEST(urlres_e->flags, ENTRY_ABORTED) || result.length == 0 || result.flags.error < 0) { + if (EBIT_TEST(urlres_e->flags, ENTRY_ABORTED) || result.length == 0 || result.flags.error) { urnHandleReplyError(urnState, urlres_e); return; } diff -u -r -N squid-3.1.12/src/whois.cc squid-3.1.12.1/src/whois.cc --- squid-3.1.12/src/whois.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/src/whois.cc 2011-04-19 17:27:09.000000000 +1200 @@ -135,65 +135,55 @@ void WhoisState::readReply (int fd, char *aBuffer, size_t aBufferLength, comm_err_t flag, int xerrno) { - int do_next_read = 0; - /* Bail out early on COMM_ERR_CLOSING - close handlers will tidy up for us */ - - if (flag == COMM_ERR_CLOSING) { + if (flag == COMM_ERR_CLOSING) return; - } aBuffer[aBufferLength] = '\0'; debugs(75, 3, "whoisReadReply: FD " << fd << " read " << aBufferLength << " bytes"); debugs(75, 5, "{" << aBuffer << "}"); - if (flag == COMM_OK && aBufferLength > 0) { - if (!dataWritten) - setReplyToOK(entry); - - kb_incr(&statCounter.server.all.kbytes_in, aBufferLength); - - kb_incr(&statCounter.server.http.kbytes_in, aBufferLength); - - /* No range support, we always grab it all */ - dataWritten = true; - - entry->append(aBuffer, aBufferLength); - - entry->flush(); - - do_next_read = 1; - } else if (flag != COMM_OK || aBufferLength < 0) { + if (flag != COMM_OK) { debugs(50, 2, "whoisReadReply: FD " << fd << ": read failure: " << xstrerror() << "."); if (ignoreErrno(errno)) { - do_next_read = 1; + comm_read(fd, aBuffer, BUFSIZ, whoisReadReply, this); } else { ErrorState *err; err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR, fwd->request); err->xerrno = errno; fwd->fail(err); comm_close(fd); - do_next_read = 0; } - } else { - entry->timestampsSet(); - entry->flush(); - - if (!EBIT_TEST(entry->flags, RELEASE_REQUEST)) - entry->setPublicKey(); + return; + } - fwd->complete(); + if (aBufferLength > 0) { + if (!dataWritten) + setReplyToOK(entry); - debugs(75, 3, "whoisReadReply: Done: " << entry->url() ); + kb_incr(&statCounter.server.all.kbytes_in, aBufferLength); + kb_incr(&statCounter.server.http.kbytes_in, aBufferLength); - comm_close(fd); + /* No range support, we always grab it all */ + dataWritten = true; + entry->append(aBuffer, aBufferLength); + entry->flush(); - do_next_read = 0; + comm_read(fd, aBuffer, BUFSIZ, whoisReadReply, this); + return; } - if (do_next_read) - comm_read(fd, aBuffer, BUFSIZ, whoisReadReply, this); + /* no bytes read. stop reading */ + entry->timestampsSet(); + entry->flush(); + + if (!EBIT_TEST(entry->flags, RELEASE_REQUEST)) + entry->setPublicKey(); + + fwd->complete(); + debugs(75, 3, "whoisReadReply: Done: " << entry->url()); + comm_close(fd); } static void diff -u -r -N squid-3.1.12/test-suite/debug.cc squid-3.1.12.1/test-suite/debug.cc --- squid-3.1.12/test-suite/debug.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/test-suite/debug.cc 2011-04-19 17:27:09.000000000 +1200 @@ -42,7 +42,7 @@ { public: std::ostream &serialise(std::ostream &); - int const getAnInt() const; + int getAnInt() const; char const *getACString() const; }; @@ -58,7 +58,7 @@ return aStream; } -int const +int StreamTest::getAnInt() const { return 5; diff -u -r -N squid-3.1.12/test-suite/testheaders.sh squid-3.1.12.1/test-suite/testheaders.sh --- squid-3.1.12/test-suite/testheaders.sh 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/test-suite/testheaders.sh 2011-04-19 17:27:09.000000000 +1200 @@ -21,6 +21,7 @@ hdr=`echo "${f}" | sed s/.h//` if [ ! -e ./testHeaderDeps_${hdr}.o -o ${dir}/${f} -nt ./testHeaderDeps_${hdr}.o ]; then ( echo "/* This file is AUTOMATICALLY GENERATED. DO NOT ALTER IT */" + echo "#include \"config.h\"" echo "#include \"${dir}/${f}\" " echo "int main( int argc, char* argv[] ) { return 0; } " ) >./testHeaderDeps_${hdr}.cc diff -u -r -N squid-3.1.12/tools/cachemgr.cc squid-3.1.12.1/tools/cachemgr.cc --- squid-3.1.12/tools/cachemgr.cc 2011-04-04 13:24:06.000000000 +1200 +++ squid-3.1.12.1/tools/cachemgr.cc 2011-04-19 17:27:09.000000000 +1200 @@ -864,11 +864,13 @@ l = snprintf(buf, sizeof(buf), "GET cache_object://%s/%s HTTP/1.0\r\n" + "User-Agent: cachemgr.cgi/%s\r\n" "Accept: */*\r\n" "%s" /* Authentication info or nothing */ "\r\n", req->hostname, req->action, + VERSION, make_auth_header(req)); if (write(s, buf, l) < 0) { debug(1) fprintf(stderr, "ERROR: (%d) writing request: '%s'\n", errno, buf);