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 <stdio.h>
-#endif
-#if HAVE_STDLIB_H
-#include <stdlib.h>
-#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 <dirent.h>
@@ -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 <stdio.h>
-
-/* It is useful to test things that ``must'' be true when debugging.  */
-#include <assert.h>
-
 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 <sys/capability.h>
 #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 <netinet/in.h>
+#endif
+#if HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#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 <cstdio>
+ *
+ * <stdio.h> provides fgetpos64, fopen64 if __USE_FILE_OFFSET64 is defined.
+ * It then checks whether a gcc-specific __REDIRECT macro is available
+ * (defined in <sys/cdefs.h>, depending on __GNUC__ begin available).
+ * If it is not available, it does a preprocessor #define.
+ * Which <cstdio> undefines, with this comment:
+ *   "// Get rid of those macros defined in <stdio.h>  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<stdio.h>
+#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 <cstdio> stuff we actually use
+#if HAVE_CSTDIO
+#include<cstdio>
+#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 <http://www.squid-cache.org/bugs/>.
 #
@@ -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 <fnmatch.h> header file. */
 #undef HAVE_FNMATCH_H
 
+/* Define to 1 if you have the <fstream> 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 <libxml/parser.h> header file. */
 #undef HAVE_LIBXML_PARSER_H
 
+/* Define to 1 if you have the <limits> header file. */
+#undef HAVE_LIMITS
+
 /* Define to 1 if you have the <limits.h> header file. */
 #undef HAVE_LIMITS_H
 
@@ -385,6 +391,9 @@
 /* Define to 1 if you have the <linux/types.h> header file. */
 #undef HAVE_LINUX_TYPES_H
 
+/* Define to 1 if you have the <list> 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 <map> header file. */
+#undef HAVE_MAP
+
 /* Define to 1 if you have the <math.h> 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 <memory> header file. */
+#undef HAVE_MEMORY
+
 /* Define to 1 if you have the <memory.h> header file. */
 #undef HAVE_MEMORY_H
 
@@ -520,6 +535,9 @@
 /* Define to 1 if you have the <openssl/ssl.h> header file. */
 #undef HAVE_OPENSSL_SSL_H
 
+/* Define to 1 if you have the <openssl/txt_db.h> header file. */
+#undef HAVE_OPENSSL_TXT_DB_H
+
 /* Define to 1 if you have the <openssl/x509v3.h> 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 <sys/types.h>
-#endif
-#if HAVE_STDIO_H
-#include <stdio.h>
-#endif
 #if HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
 #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 <errno.h>
 #endif
-#if HAVE_STDIO_H
-#include <stdio.h>
-#endif
 #if HAVE_STRING_H
 #include <string.h>
 #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 <libc.h>
 #endif
-#if HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#if HAVE_TYPES_H
-#include <sys/types.h>
-#endif
 #if HAVE_LIMITS_H
 #include <limits.h>
 #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 @@
 <HTML>
 <HEAD>
  <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 0.9.66">
- <TITLE>Squid 3.1.12 release notes</TITLE>
+ <TITLE>Squid 3.1.12.1 release notes</TITLE>
 </HEAD>
 <BODY>
-<H1>Squid 3.1.12 release notes</H1>
+<H1>Squid 3.1.12.1 release notes</H1>
 
 <H2>Squid Developers</H2>
 <HR>
@@ -31,9 +31,10 @@
 <LI><A NAME="toc2.5">2.5</A> <A HREF="#ss2.5">Connection Pinning (for NTLM Auth Passthrough)</A>
 <LI><A NAME="toc2.6">2.6</A> <A HREF="#ss2.6">Quality of Service (QoS) Flow support</A>
 <LI><A NAME="toc2.7">2.7</A> <A HREF="#ss2.7">SSL Bump (for HTTPS Filtering and Adaptation)</A>
-<LI><A NAME="toc2.8">2.8</A> <A HREF="#ss2.8">eCAP Adaptation Module support</A>
-<LI><A NAME="toc2.9">2.9</A> <A HREF="#ss2.9">ICAP Bypass and Retry enhancements</A>
-<LI><A NAME="toc2.10">2.10</A> <A HREF="#ss2.10">ICY streaming protocol support</A>
+<LI><A NAME="toc2.8">2.8</A> <A HREF="#ss2.8">Dynamic SSL Certificate Generation</A>
+<LI><A NAME="toc2.9">2.9</A> <A HREF="#ss2.9">eCAP Adaptation Module support</A>
+<LI><A NAME="toc2.10">2.10</A> <A HREF="#ss2.10">ICAP Bypass and Retry enhancements</A>
+<LI><A NAME="toc2.11">2.11</A> <A HREF="#ss2.11">ICY streaming protocol support</A>
 </UL>
 <P>
 <H2><A NAME="toc3">3.</A> <A HREF="#s3">Changes to squid.conf since Squid-3.0</A></H2>
@@ -70,7 +71,7 @@
 <HR>
 <H2><A NAME="s1">1.</A> <A HREF="#toc1">Notice</A></H2>
 
-<P>The Squid Team are pleased to announce the release of Squid-3.1.12</P>
+<P>The Squid Team are pleased to announce the release of Squid-3.1.12.1</P>
 <P>This new release is available for download from 
 <A HREF="http://www.squid-cache.org/Versions/v3/3.1/">http://www.squid-cache.org/Versions/v3/3.1/</A> or the 
 <A HREF="http://www.squid-cache.org/Mirrors/http-mirrors.html">mirrors</A>.</P>
@@ -124,6 +125,7 @@
 <LI>eCAP Adaptation Module support</LI>
 <LI>ICAP Bypass and Retry enhancements</LI>
 <LI>ICY streaming protocol support</LI>
+<LI>Dynamic SSL Certificate Generation (3.1.12.1 and later)</LI>
 </UL>
 </P>
 <P>Most user-facing changes are reflected in squid.conf (see below).</P>
@@ -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.</P>
 
+<H2><A NAME="ss2.8">2.8</A> <A HREF="#toc2.8">Dynamic SSL Certificate Generation</A>
+</H2>
+
+<P> 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:
+<UL>
+<LI> Squid certificate is not signed by a trusted authority.</LI>
+<LI> Squid certificate name does not match the site domain name.</LI>
+</UL>
 
-<H2><A NAME="ss2.8">2.8</A> <A HREF="#toc2.8">eCAP Adaptation Module support</A>
+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.</P>
+
+<P>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.</P>
+
+<H2><A NAME="ss2.9">2.9</A> <A HREF="#toc2.9">eCAP Adaptation Module support</A>
 </H2>
 
 <P>Details in 
@@ -384,7 +408,7 @@
 <P>Currently known and available eCAP modules are listed in the wiki feature page on eCAP.</P>
 
 
-<H2><A NAME="ss2.9">2.9</A> <A HREF="#toc2.9">ICAP Bypass and Retry enhancements</A>
+<H2><A NAME="ss2.10">2.10</A> <A HREF="#toc2.10">ICAP Bypass and Retry enhancements</A>
 </H2>
 
 <P>Details in 
@@ -446,7 +470,7 @@
 environments yet may be small enough to limit side-effects of loops.</P>
 
 
-<H2><A NAME="ss2.10">2.10</A> <A HREF="#toc2.10">ICY streaming protocol support</A>
+<H2><A NAME="ss2.11">2.11</A> <A HREF="#toc2.11">ICY streaming protocol support</A>
 </H2>
 
 <P>Squid-3.1 adds native support for streaming protocol ICY.
@@ -1047,6 +1071,12 @@
 </PRE>
 </P>
 
+<DT><B>sslcrtd_program</B><DD>
+<P>Specify the location and options of the executable for ssl_crtd process.</P>
+
+<DT><B>sslcrtd_children</B><DD>
+<P> Configures the number of sslcrtd processes to spawn</P>
+
 <DT><B>sslproxy_cert_error</B><DD>
 <P>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.</P>
 
+<DT><B>--enable-ssl-crtd</B><DD>
+<P>Prevent Squid from direct generation of SSL private key and
+certificate request and instead enables the <EM>ssl_crtd</EM> processes.</P>
+
 <DT><B>--enable-zph-qos</B><DD>
 <P>Build with support for ZPH Quality of Service controls</P>
 
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<const char *>(a);
+    const char *d = static_cast<const char *>(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<char *>(b);
+    char * const d2 = static_cast<char *>(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 <int> instantiation for other ACLs.
-// template cbdata_type CbDataList<ssl_error_t>::CBDATA_CbDataList;
+// template cbdata_type CbDataList<Ssl::ssl_error_t>::CBDATA_CbDataList;
 /** \endcond */
 
 wordlist *
 ACLSslErrorData::dump()
 {
     wordlist *W = NULL;
-    CbDataList<ssl_error_t> *data = values;
+    CbDataList<Ssl::ssl_error_t> *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<ssl_error_t> **Tail;
+    CbDataList<Ssl::ssl_error_t> **Tail;
     char *t = NULL;
 
     for (Tail = &values; *Tail; Tail = &((*Tail)->next));
     while ((t = strtokFile())) {
-        CbDataList<ssl_error_t> *q = new CbDataList<ssl_error_t>(sslParseErrorString(t));
+        CbDataList<Ssl::ssl_error_t> *q = new CbDataList<Ssl::ssl_error_t>(Ssl::parseErrorString(t));
         *(Tail) = q;
         Tail = &q->next;
     }
@@ -67,7 +67,7 @@
     return values == NULL;
 }
 
-ACLData<ssl_error_t> *
+ACLData<Ssl::ssl_error_t> *
 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<ssl_error_t>
+class ACLSslErrorData : public ACLData<Ssl::ssl_error_t>
 {
 
 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<ssl_error_t> *clone() const;
+    virtual ACLData<Ssl::ssl_error_t> *clone() const;
 
-    CbDataList<ssl_error_t> *values;
+    CbDataList<Ssl::ssl_error_t> *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<int64_t>(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 <typename T, void (*DeAllocator)(T *t)> 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<T, DeAllocator> const &);
+    /// Forbidden assigment operator.
+    TidyPointer <T, DeAllocator> & operator = (TidyPointer<T, DeAllocator> 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<typename T> 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 <glob.h>
 #endif
 
+#if HAVE_LIMITS
+#include <limits>
+#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<size_t>(m * d / u);
+    if (static_cast<double>(*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<size_t>::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[=<on|off>]
+			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 <limits>
+#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 <NULL> 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<size_t>::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<unsigned int>(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<unsigned int>(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<unsigned int>(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 <limits>
+#endif
 
 http_port_list::http_port_list(const char *aProtocol)
 #if USE_SSL
         :
-        http(*this)
+        http(*this), dynamicCertMemCacheSize(std::numeric_limits<size_t>::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 <fstream>
+#endif
+#if HAVE_STDEXCEPT
+#include <stdexcept>
+#endif
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#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<char *>(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<char, tidyFree> 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<char, tidyFree> 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<char *>(tm->data), tm->length).c_str());
+    row.setValue(cnlFile, "unknown");
+    {
+        TidyPointer<char, tidyFree> 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<char *>(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<char *>(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<char *>(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 <string>
+#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 <limits>
+#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<IpAddress, LocalContextStorage *>::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<IpAddress, LocalContextStorage *>::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<IpAddress, size_t>(address, size_of_store));
+}
+
+Ssl::LocalContextStorage & Ssl::GlobalContextStorage::getLocalStorage(IpAddress const & address)
+{
+    reconfigureFinish();
+    std::map<IpAddress, LocalContextStorage *>::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<IpAddress, LocalContextStorage *>::iterator i = storage.begin(); i != storage.end(); i++) {
+            std::map<IpAddress, size_t>::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<IpAddress, size_t>::iterator conf_i = configureStorage.begin(); conf_i != configureStorage.end(); conf_i++ ) {
+            if (storage.find(conf_i->first) == storage.end()) {
+                storage.insert(std::pair<IpAddress, LocalContextStorage *>(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 <map>
+#endif
+#if HAVE_LIST
+#include <list>
+#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<Item *> Queue;
+    typedef Queue::iterator QueueIterator;
+
+    /// host_name:queue_item mapping for fast lookups by host name
+    typedef std::map<std::string, QueueIterator> Map;
+    typedef Map::iterator MapIterator;
+    typedef std::pair<std::string, QueueIterator> 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<IpAddress, size_t> configureStorage;
+    /// Map for storing all local ip address and their local storages.
+    std::map<IpAddress, LocalContextStorage *> 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 <cstdlib>
+#endif
+#if HAVE_CSTRING
+#include <cstring>
+#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<size_t>(buffer + len - current_pos) >= body_size - current_block.length())
+                              ? body_size - current_block.length()
+                              : static_cast<size_t>(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<char *>(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 <string>
+#endif
+#if HAVE_MAP
+#include <map>
+#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:
+ *   <response/request code> <whitespace> <body length> <whitespace> <body>
+ */
+class CrtdMessage
+{
+public:
+    typedef std::map<std::string, std::string> 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 <openssl/ssl.h>
+#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<char *>(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 <openssl/ssl.h>
+#endif
+#if HAVE_OPENSSL_TXT_DB_H
+#include <openssl/txt_db.h>
+#endif
+#if HAVE_STRING
+#include <string>
+#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, X509_free_cpp> X509_Pointer;
+
+CtoCpp1(EVP_PKEY_free, EVP_PKEY *)
+typedef TidyPointer<EVP_PKEY, EVP_PKEY_free_cpp> EVP_PKEY_Pointer;
+
+CtoCpp1(BN_free, BIGNUM *)
+typedef TidyPointer<BIGNUM, BN_free_cpp> BIGNUM_Pointer;
+
+CtoCpp1(BIO_free, BIO *)
+typedef TidyPointer<BIO, BIO_free_cpp> BIO_Pointer;
+
+CtoCpp1(ASN1_INTEGER_free, ASN1_INTEGER *)
+typedef TidyPointer<ASN1_INTEGER, ASN1_INTEGER_free_cpp> ASN1_INT_Pointer;
+
+CtoCpp1(TXT_DB_free, TXT_DB *)
+typedef TidyPointer<TXT_DB, TXT_DB_free_cpp> TXT_DB_Pointer;
+
+CtoCpp1(X509_NAME_free, X509_NAME *)
+typedef TidyPointer<X509_NAME, X509_NAME_free_cpp> X509_NAME_Pointer;
+
+CtoCpp1(RSA_free, RSA *)
+typedef TidyPointer<RSA, RSA_free_cpp> RSA_Pointer;
+
+CtoCpp1(X509_REQ_free, X509_REQ *)
+typedef TidyPointer<X509_REQ, X509_REQ_free_cpp> X509_REQ_Pointer;
+
+CtoCpp1(SSL_CTX_free, SSL_CTX *)
+typedef TidyPointer<SSL_CTX, SSL_CTX_free_cpp> SSL_CTX_Pointer;
+
+CtoCpp1(SSL_free, SSL *)
+typedef TidyPointer<SSL, SSL_free_cpp> 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 <cstring>
+#endif
+#if HAVE_SSTREAM
+#include <sstream>
+#endif
+#if HAVE_IOSTREAM
+#include <iostream>
+#endif
+#if HAVE_STDEXCEPT
+#include <stdexcept>
+#endif
+#if HAVE_STRING
+#include <string>
+#endif
+#if HAVE_GETOPT_H
+#include <getopt.h>
+#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:
+    <request code><whitespace><body_len><whitespace><body>
+    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(&current_time);
+#else
+    gettimeofday(&current_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<size_t>(m * d);
+    if (static_cast<long>(*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"
+        "<request code><whitespace><body_len><whitespace><body>\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<ACLChecklist *>(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 <Ssl::ErrorDetail *>(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 <openssl/ssl.h>
 #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);
