From: Amos Jeffries Date: Mon, 14 Sep 2009 02:33:31 +0000 (+1200) Subject: Merge from trunk X-Git-Tag: SQUID_3_2_0_1~668^2~8 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9a9ea6b026aa36bb953192f80f27052399041b53;hp=fc7a4a9eea86eb46405382b5fcc03c51d09593fd;p=thirdparty%2Fsquid.git Merge from trunk --- diff --git a/CREDITS b/CREDITS index e9daf0d32d..4a00651cc0 100644 --- a/CREDITS +++ b/CREDITS @@ -391,8 +391,9 @@ lib/libTrie/*: include/IPAddress.h lib/IPAddress.cc: include/rfc3596.h lib/rfc3596.cc: src/ICMPv6.h src/ICMPv6.cc: +helpers/url_rewrite/fake/ fake.h, fake.cc, url_fake_rewrite.sh: - This code is copyright (C) 2007 by Treehouse Networks Ltd + This code is copyright (C) 2007-2009 by Treehouse Networks Ltd of New Zealand. It is published and Licensed as an extension of squid under the same conditions as the main squid application. diff --git a/ChangeLog b/ChangeLog index f88b27e0c4..8b4c5121b2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -216,6 +216,19 @@ Changes to squid-3.1.0.1 (27 Oct 2008): - Bug #2223: Follow XFF extensions added - ... and many code and documentation cleanups +Changes to squid-3.0.STABLE19 (06 Sep 2009): + + - Bug 2745: Invalid Response error on small reads + - Bug 2739: DNS resolver option ndots can't be parsed from resolv.conf + - Bug 2734: some compile errors on Solaris + - Bug 2648: stateful helpers stuck in reserved if client disconnects while helper busy + - Bug 2541: Hang in 100% CPU loop while extacting header details using a delimiter other than comma + - Bug 2362: Remove support for deferred state in stateful helpers + - Add 0.0.0.0 as a to_localhost address + - Docs: Improve chroot directive documentation slightly + - Fixup libxml2 include magics, was failing when a configure cache was used + - ... and some minor testing improvements. + Changes to squid-3.0.STABLE18 (04 Aug 2009): - Bug 2728: regression: assertion failed: !eof diff --git a/acinclude.m4 b/acinclude.m4 index 3fa8a95a6f..95e7a8827a 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -72,8 +72,8 @@ dnl AC_DEFUN([AC_TEST_CHECKFORHUGEOBJECTS],[ AC_MSG_CHECKING([whether compiler accepts -fhuge-objects]) AC_CACHE_VAL([ac_cv_test_checkforhugeobjects],[ - ac_cv_test_checkforhugeobjects=`echo "int foo;" > conftest.cc -${CXX} -Werror -fhuge-objects -c conftest.cc 2>/dev/null + ac_cv_test_checkforhugeobjects=`echo "int main(int argc, char **argv) { int foo; }" > conftest.cc +${CXX} -Werror -fhuge-objects -o conftest.bin conftest.cc 2>/dev/null res=$? rm -f conftest.* echo yes diff --git a/compat/Makefile.am b/compat/Makefile.am index cf8c018e2b..3aa5b9751b 100644 --- a/compat/Makefile.am +++ b/compat/Makefile.am @@ -15,6 +15,7 @@ libcompat_la_SOURCES = \ assert.h \ compat.h \ compat_shared.h \ + debug.h \ fdsetsize.h \ osdetect.h \ stdvarargs.h \ @@ -37,6 +38,7 @@ libcompat_la_SOURCES = \ \ assert.cc \ compat.cc \ + debug.cc \ GnuRegex.h \ GnuRegex.c diff --git a/compat/compat.h b/compat/compat.h index bacbc5aae2..1600291711 100644 --- a/compat/compat.h +++ b/compat/compat.h @@ -74,10 +74,14 @@ #include "compat/stdvarargs.h" #include "compat/assert.h" + /*****************************************************/ /* component-specific portabilities */ /*****************************************************/ +/* helper debugging requires some hacks to be clean */ +#include "compat/debug.h" + /* Valgrind API macros changed between two versions squid supports */ #include "compat/valgrind.h" diff --git a/compat/debug.cc b/compat/debug.cc new file mode 100644 index 0000000000..9d307d571a --- /dev/null +++ b/compat/debug.cc @@ -0,0 +1,4 @@ +#include "config.h" + +/* default off */ +int debug_enabled = 0; diff --git a/compat/debug.h b/compat/debug.h new file mode 100644 index 0000000000..01367403ad --- /dev/null +++ b/compat/debug.h @@ -0,0 +1,45 @@ +#ifndef SQUID_CONFIG_H +#include "config.h" +#endif + +#ifndef COMPAT_DEBUG_H +#define COMPAT_DEBUG_H + +/* + * A debug method for use of external helpers and tools. + * It shunts the debug messages down stderr for logging by Squid + * or display to the user instead of corrupting the stdout data stream. + */ + +#if HAVE_STDIO_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif + +/* Debugging stuff */ + +/* the macro overload style is really a gcc-ism */ +#ifdef __GNUC__ + +SQUIDCEXTERN int debug_enabled; + +#define debug(X...) \ + if (debug_enabled) { \ + fprintf(stderr, "%s(%d): pid=%ld :", __FILE__, __LINE__, (long)getpid() ); \ + fprintf(stderr,X); \ + } + +#else /* __GNUC__ */ + +/* TODO: non-GCC compilers can't do the above macro define yet. */ +inline void +debug(char *format,...) +{ + ; // nothing to do. +} +#endif + + +#endif /* COMPAT_DEBUG_H */ diff --git a/configure.in b/configure.in index 5e2bd1a3e0..deed47f129 100644 --- a/configure.in +++ b/configure.in @@ -34,7 +34,7 @@ new_configure_args="$ac_configure_args --with-squid=$ac_abs_confdir" ac_configure_args="$new_configure_args" -use_loadable_modules=0 +use_loadable_modules=1 AC_MSG_CHECKING(whether to use loadable modules) AC_ARG_ENABLE(loadable-modules, AS_HELP_STRING([--disable-loadable-modules],[do not support loadable modules]) , @@ -51,7 +51,6 @@ AC_ARG_ENABLE(loadable-modules, AC_MSG_RESULT([$use_loadable_modules, implicitly]) ] ) -use_loadable_modules=0 AM_CONDITIONAL(USE_LOADABLE_MODULES, test $use_loadable_modules = yes) @@ -697,11 +696,11 @@ if test -n "$STORE_MODULES"; then fi done for module in $STORE_MODULES_FULL; do - if test "$module" = "coss"; then - echo "WARNING: COSS Support is not stable yet in Squid-3. Please do not use." - sleep 10; - fi case "$module" in + coss) + echo "WARNING: COSS Support is not stable yet in Squid-3. Please do not use." + sleep 10 + ;; esac done AC_MSG_NOTICE([Store modules built: $STORE_MODULES]) @@ -1806,6 +1805,207 @@ if test -n "$DIGEST_AUTH_HELPERS"; then fi AC_SUBST(DIGEST_AUTH_HELPERS) +dnl Check Kerberos +SAVED_CPPFLAGS=$CPPFLAGS +SAVED_LIBS=$LIBS +AC_ARG_WITH(krb5-config, + [ --with-krb5-config=PATH specify path to krb5-config @<:@default=detect@:>@], +[ if test "$withval" = "yes"; then + unset krb5confpath + elif test "$withval" != "no"; then + krb5confpath=$withval + else + krb5confpath=no + fi +]) +if test x"$krb5confpath" != xno; then + if test x"$krb5confpath" != x; then + if ! test -x "$krb5confpath"; then + AC_MSG_WARN([krb5-config '$krb5confpath' not executable, ignoring]) + AC_CHECK_PROG(ac_krb5_config, krb5-config, yes, no) + krb5confpath=krb5-config + fi + krb5_config_path=`dirname $krb5confpath` + AC_CHECK_PROG(ac_krb5_config, krb5-config, yes, no, $krb5_config_path) + else + AC_CHECK_PROG(ac_krb5_config,krb5-config,yes,no) + krb5confpath=krb5-config + fi +fi +if test "$ac_krb5_config" = "yes" ; then + ac_heimdal="`$krb5confpath --version 2>/dev/null | grep -i heimdal`" + ac_solaris="`$krb5confpath --version 2>/dev/null | grep -i solaris`" + if test "x$ac_heimdal" != "x" ; then + AC_DEFINE(HAVE_HEIMDAL_KERBEROS,1,[Define to 1 if you have Heimdal Kerberos]) + else + AC_DEFINE(HAVE_MIT_KERBEROS,1,[Define to 1 if you have MIT Kerberos]) + fi + if test "$ac_solaris" != "" ; then + KRB5INCS="`$krb5confpath --cflags krb5 2>/dev/null`" + KRB5LIBS="`$krb5confpath --libs krb5 2>/dev/null`" + KRB5INCS="-I/usr/include/gssapi $KRB5INCS" + KRB5LIBS="-L/usr/lib -R/usr/lib -lgss -lresolv -lsocket -lnsl $KRB5LIBS" + else + KRB5INCS="`$krb5confpath --cflags krb5 2>/dev/null`" + KRB5LIBS="`$krb5confpath --libs krb5 2>/dev/null`" + KRB5INCS="`$krb5confpath --cflags gssapi 2>/dev/null` $KRB5INCS" + KRB5LIBS="`$krb5confpath --libs gssapi 2>/dev/null` $KRB5LIBS" + fi + CPPFLAGS="$CPPFLAGS $KRB5INCS" + LIBS="$LIBS $KRB5LIBS" + AC_CHECK_HEADERS(gssapi.h gssapi/gssapi.h gssapi/gssapi_krb5.h) + if test "x$ac_heimdal" == "x" ; then + AC_CHECK_HEADERS(gssapi/gssapi_generic.h) + fi + AC_CHECK_HEADERS(krb5.h com_err.h et/com_err.h) + AC_MSG_CHECKING([for max_skew in struct krb5_context]) +AC_TRY_COMPILE([ +#include + ], + [ krb5_context kc; kc->max_skew = 1; ], + [ AC_DEFINE(HAVE_MAX_SKEW_IN_KRB5_CONTEXT, 1, [Define to 1 if max_skew in struct krb5_context]) + AC_MSG_RESULT(yes) ], + [ AC_MSG_RESULT(no) ] + ) + + if test "x$ac_heimdal" == "x" ; then + AC_CHECK_HEADERS(profile.h) + fi + AC_CHECK_LIB(com_err,error_message, + AC_DEFINE(HAVE_ERROR_MESSAGE,1,[Define to 1 if you have error_message]),) + AC_CHECK_LIB(krb5,krb5_get_err_text, + AC_DEFINE(HAVE_KRB5_GET_ERR_TEXT,1,[Define to 1 if you have krb5_get_err_text]),) + AC_CHECK_LIB(krb5,krb5_get_error_message, + AC_DEFINE(HAVE_KRB5_GET_ERROR_MESSAGE,1,[Define to 1 if you have krb5_get_error_message]),) + AC_CHECK_LIB(krb5,krb5_kt_free_entry, + AC_DEFINE(HAVE_KRB5_KT_FREE_ENTRY,1,[Define to 1 if you have krb5_kt_free_entry]),) + AC_CHECK_LIB(krb5,krb5_get_init_creds_keytab, + AC_DEFINE(HAVE_GET_INIT_CREDS_KEYTAB,1,[Define to 1 if you have krb5_get_init_creds_keytab]),) + AC_CHECK_LIB(krb5,krb5_get_max_time_skew, + AC_DEFINE(HAVE_KRB5_GET_MAX_TIME_SKEW,1,[Define to 1 if you have krb5_get_max_time_skew]),) + AC_CHECK_LIB(krb5,krb5_get_profile, + AC_DEFINE(HAVE_KRB5_GET_PROFILE,1,[Define to 1 if you have krb5_get_profile]),) + AC_CHECK_LIB(krb5,profile_get_integer, + AC_DEFINE(HAVE_PROFILE_GET_INTEGER,1,[Define to 1 if you have profile_get_integer]),) + AC_CHECK_LIB(krb5,profile_release, + AC_DEFINE(HAVE_PROFILE_RELEASE,1,[Define to 1 if you have profile_release]),) + AC_MSG_CHECKING([for memory cache]) + AC_TRY_RUN([ +#include +main() +{ + krb5_context context; + krb5_ccache cc; + + krb5_init_context(&context); + return krb5_cc_resolve(context, "MEMORY:test_cache", &cc); +}], + [AC_DEFINE(HAVE_KRB5_MEMORY_CACHE,1, [Define to 1 if you have MEMORY: cache support]) + AC_MSG_RESULT(yes)], + AC_MSG_RESULT(no)) + + AC_MSG_CHECKING([for working gssapi]) + AC_TRY_RUN([ +#ifdef HAVE_GSSAPI_GSSAPI_H +#include +#elif HAVE_GSSAPI_H +#include +#endif + +#ifdef HAVE_GSSAPI_GSSAPI_EXT_H +#include +#endif + +#ifdef HAVE_GSSAPI_GSSAPI_KRB5_H +#include +#endif + +#ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H +#include +#endif +int +main(void) +{ + OM_uint32 val; + gss_OID_set set; + + gss_create_empty_oid_set(&val, &set); + + return 0; +} +], [AC_DEFINE(HAVE_GSSAPI, 1, [GSSAPI support]) + AC_MSG_RESULT(yes)], + AC_MSG_RESULT(no)) + AC_MSG_CHECKING([for spnego support]) + AC_TRY_RUN([ +#ifdef HAVE_HEIMDAL_KERBEROS +#ifdef HAVE_GSSAPI_GSSAPI_H +#include +#elif defined(HAVE_GSSAPI_H) +#include +#endif +#else +#ifdef HAVE_GSSAPI_GSSAPI_H +#include +#elif defined(HAVE_GSSAPI_H) +#include +#endif +#ifdef HAVE_GSSAPI_GSSAPI_KRB5_H +#include +#endif +#ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H +#include +#endif +#endif +#include +int main(int argc, char *argv[]) { + OM_uint32 major_status,minor_status; + gss_OID_set gss_mech_set; + int i; + +static gss_OID_desc _gss_mech_spnego = {6, (void *)"\x2b\x06\x01\x05\x05\x02"}; +gss_OID gss_mech_spnego = &_gss_mech_spnego; + + major_status = gss_indicate_mechs( &minor_status, &gss_mech_set); + + for (i=0;icount;i++) { + if (!memcmp(gss_mech_set->elements[i].elements,gss_mech_spnego->elements,gss_mech_set->elements[i].length)) { + return 0; + } + } + + return 1; +}], + [ac_cv_have_spnego=yes + AC_DEFINE(HAVE_SPNEGO,1, [Define to 1 if you have SPNEGO support]) + AC_MSG_RESULT(yes)], + [ac_cv_have_spnego=no + AC_MSG_RESULT(no)]) + AC_MSG_CHECKING([for working krb5]) + AC_TRY_RUN([ +#ifdef HAVE_KRB5_H +#include +#endif + +int +main(void) +{ + krb5_context context; + + krb5_init_context(&context); + + return 0; +} +], [AC_DEFINE(HAVE_KRB5, 1, [KRB5 support]) + AC_MSG_RESULT(yes)], + AC_MSG_RESULT(no)) + LIBS=$SAVED_LIBS + CPPFLAGS=$SAVED_CPPFLAGS + AC_SUBST(KRB5INCS) + AC_SUBST(KRB5LIBS) +fi +AM_CONDITIONAL(HAVE_SPNEGO, test x"$ac_cv_have_spnego" = x"yes" ) + dnl Enable "NTLM fail open" AC_ARG_ENABLE(ntlm-fail-open, AS_HELP_STRING([--enable-ntlm-fail-open],[Enable NTLM fail open, where a helper that fails one of the @@ -1856,6 +2056,48 @@ if test -n "$EXTERNAL_ACL_HELPERS"; then fi AC_SUBST(EXTERNAL_ACL_HELPERS) +dnl Select url_rewrite helpers to build +URL_REWRITE_HELPERS=all +AC_ARG_ENABLE(url-rewrite-helpers, + AC_HELP_STRING([--enable-url-rewrite-helpers="list of helpers"], + [This option selects which url_rewrite helpers to + build and install as part of the normal build + process. For a list of available helpers see the + helpers/url_rewrite directory.]), +[ case "$enableval" in + yes) + URL_REWRITE_HELPERS=all + ;; + no) + URL_REWRITE_HELPERS="" + ;; + *) + URL_REWRITE_HELPERS="`echo $enableval| sed -e 's/,/ /g;s/ */ /g'`" + ;; + esac +]) +if test "$URL_REWRITE_HELPERS" = "all" ; then + URL_REWRITE_HELPERS="" + for dir in $srcdir/helpers/url_rewrite/*; do + helper="`basename $dir`" + if test -f $dir/config.test && sh $dir/config.test "$@"; then + URL_REWRITE_HELPERS="$URL_REWRITE_HELPERS $helper" + fi + done +fi +if test -n "$URL_REWRITE_HELPERS"; then + for helper in $URL_REWRITE_HELPERS; do + if test -f $srcdir/helpers/url_rewrite/$helper/Makefile.in; then + : + else + AC_MSG_ERROR(url_rewrite helper $helper does not exist) + fi + done + AC_MSG_NOTICE([url_rewrite helpers built: $URL_REWRITE_HELPERS]) +fi +AC_SUBST(URL_REWRITE_HELPERS) + + AC_ARG_WITH(valgrind-debug, AS_HELP_STRING([--with-valgrind-debug],[Include debug instrumentation for use with valgrind]), [ case $withval in @@ -3878,6 +4120,8 @@ AC_CONFIG_FILES([\ helpers/external_acl/wbinfo_group/Makefile \ helpers/external_acl/mswin_ad_group/Makefile \ helpers/external_acl/mswin_lm_group/Makefile \ + helpers/url_rewrite/Makefile \ + helpers/url_rewrite/fake/Makefile \ tools/Makefile ]) diff --git a/doc/Programming-Guide/Makefile b/doc/Programming-Guide/Makefile index a5a9ce62e5..e5734f163c 100644 --- a/doc/Programming-Guide/Makefile +++ b/doc/Programming-Guide/Makefile @@ -6,12 +6,14 @@ all: dyn-docs: rm -f -r tmp cd ../../ && (cat squid3.dox ; echo HTML_FILE_EXTENSION = .dyn ; echo HTML_OUTPUT = tmp ) | doxygen - 2>doxygen.log - mv dyn dyn.bak && mv tmp dyn && rm -r dyn.bak + rm -f -r dyn + mv tmp dyn html-docs: rm -f -r tmp cd ../../ && (cat squid3.dox | sed s/dyn/html/g | sed s/CALL_GRAPH/#/ | sed s/CALLER_GRAPH/#/ | doxygen -) 2>doxygen.log - mv html html.bak && mv tmp html && rm -r html.bak + rm -f -r html + mv tmp html clean: - rm -f -r tmp html dyn dyn.bak html.bak + rm -f -r tmp html dyn diff --git a/doc/release-notes/release-3.0.sgml b/doc/release-notes/release-3.0.sgml index 3b04a484b5..36735095f6 100644 --- a/doc/release-notes/release-3.0.sgml +++ b/doc/release-notes/release-3.0.sgml @@ -1,6 +1,6 @@
-Squid 3.0.STABLE18 release notes +Squid 3.0.STABLE19 release notes Squid Developers @@ -13,7 +13,7 @@ for Applied Network Research and members of the Web Caching community. Notice

-The Squid Team are pleased to announce the release of Squid-3.0.STABLE18. +The Squid Team are pleased to announce the release of Squid-3.0.STABLE19. This new release is available for download from or the . diff --git a/doc/release-notes/release-3.2.sgml b/doc/release-notes/release-3.2.sgml index cfd974717a..cf35b4af4c 100644 --- a/doc/release-notes/release-3.2.sgml +++ b/doc/release-notes/release-3.2.sgml @@ -306,9 +306,12 @@ This section gives an account of those changes in three categories: New options

- - ???alphabetical list within group ordered: enable, disable, with, without) ??? -

???explain?? + --enable-url-rewrite-helpers +

Build helpers for some basic URL-rewrite actions. For use by url_rewrite_program. + If omitted or set to =all then all bundled helpers that are able to build will be built. + If set to a specific list of helpers then only those helpers will build. + Currently one demo helper fake is provided in shell and C++ forms to demonstrate + the helper protocol usage and provide exemplar code. diff --git a/errors/Makefile.am b/errors/Makefile.am index dd80a7bfc8..51b52e5b78 100644 --- a/errors/Makefile.am +++ b/errors/Makefile.am @@ -11,43 +11,155 @@ DEFAULT_ERROR_DIR = $(errordir) DEFAULT_STYLESHEET = $(sysconfdir)/errorpage.css ## List of automated translations possible: -TRANSLATIONPO=`ls -1 $(top_srcdir)/errors/*.po | grep -o -E "[a-z\-]+\.po" | sed s/.po//` -TRANSLATIONDIR=`ls -1 $(srcdir) $(builddir) | sed -e 's%$(srcdir)/%%' -e 's%$(builddir)/%%' -e 's%.po%%' ` +ERROR_TEMPLATES = \ + templates/ERR_FTP_PUT_MODIFIED \ + templates/ERR_ESI \ + templates/ERR_SECURE_CONNECT_FAIL \ + templates/ERR_ZERO_SIZE_OBJECT \ + templates/ERR_SHUTTING_DOWN \ + templates/ERR_URN_RESOLVE \ + templates/ERR_CONNECT_FAIL \ + templates/ERR_SOCKET_FAILURE \ + templates/ERR_FTP_NOT_FOUND \ + templates/ERR_FTP_UNAVAILABLE \ + templates/ERR_LIFETIME_EXP \ + templates/ERR_READ_ERROR \ + templates/ERR_ONLY_IF_CACHED_MISS \ + templates/ERR_UNSUP_HTTPVERSION \ + templates/ERR_READ_TIMEOUT \ + templates/ERR_ICAP_FAILURE \ + templates/ERR_FTP_LISTING \ + templates/ERR_FTP_FORBIDDEN \ + templates/ERR_ACCESS_DENIED \ + templates/ERR_FORWARDING_DENIED \ + templates/ERR_CANNOT_FORWARD \ + templates/ERR_CACHE_MGR_ACCESS_DENIED \ + templates/ERR_INVALID_REQ \ + templates/ERR_CACHE_ACCESS_DENIED \ + templates/ERR_FTP_PUT_ERROR \ + templates/ERR_FTP_PUT_CREATED \ + templates/ERR_TOO_BIG \ + templates/ERR_UNSUP_REQ \ + templates/ERR_FTP_FAILURE \ + templates/ERR_DNS_FAIL \ + templates/ERR_FTP_DISABLED \ + templates/ERR_NO_RELAY \ + templates/ERR_INVALID_URL \ + templates/ERR_INVALID_RESP \ + templates/ERR_WRITE_ERROR -## TODO: prevent this loop installing everything twice when srcdir == builddir -install-data-local: - $(mkinstalldirs) $(DESTDIR)$(DEFAULT_ERROR_DIR) ; \ - for l in $(TRANSLATIONDIR) ; do \ - echo "Located $$l for install..."; \ - if test -d $(srcdir)/$$l; then \ - $(mkinstalldirs) $(DESTDIR)$(DEFAULT_ERROR_DIR)/$$l && \ - for f in $(srcdir)/$$l/ERR_*; do \ - echo "$(INSTALL_DATA) $$f $(DESTDIR)$(DEFAULT_ERROR_DIR)/$$l"; \ - $(INSTALL_DATA) $$f $(DESTDIR)$(DEFAULT_ERROR_DIR)/$$l; \ - done; \ - fi ; \ - if test -d $(builddir)/$$l; then \ - $(mkinstalldirs) $(DESTDIR)$(DEFAULT_ERROR_DIR)/$$l && \ - for f in $(builddir)/$$l/ERR_*; do \ - echo "$(INSTALL_DATA) $$f $(DESTDIR)$(DEFAULT_ERROR_DIR)/$$l"; \ - $(INSTALL_DATA) $$f $(DESTDIR)$(DEFAULT_ERROR_DIR)/$$l; \ +TRANSLATE_LANGUAGES = \ + ar.lang \ + az.lang \ + bg.lang \ + ca.lang \ + cs.lang \ + da.lang \ + de.lang \ + el.lang \ + en.lang \ + es.lang \ + et.lang \ + fa.lang \ + fi.lang \ + fr.lang \ + he.lang \ + hu.lang \ + hy.lang \ + id.lang \ + it.lang \ + ja.lang \ + ko.lang \ + lt.lang \ + lv.lang \ + ms.lang \ + nl.lang \ + pl.lang \ + pt-br.lang \ + pt.lang \ + ro.lang \ + ru.lang \ + sk.lang \ + sr.lang \ + sv.lang \ + th.lang \ + tr.lang \ + uk.lang \ + uz.lang \ + zh-cn.lang \ + zh-tw.lang + +CLEANFILES = $(TRANSLATE_LANGUAGES) translate-warn +EXTRA_DIST = \ + $(ERROR_TEMPLATES) \ + aliases alias-link.sh alias-upgrade errorpage.css TRANSLATORS COPYRIGHT + +all: all-am + +translate: translate-warn $(TRANSLATE_LANGUAGES) + +translate-warn: + case "$(PO2HTML)" in \ + off) \ + echo "WARNING: Translation is disabled."; \ + ;; \ + ""|no) \ + echo "WARNING: Translation toolkit was not detected."; \ + ;; \ + esac; \ + touch translate-warn + +$(TRANSLATE_LANGUAGES): $(ERROR_TEMPLATES) + +.po.lang: + if test "$(PO2HTML)" != "" && test "$(PO2HTML)" != "no" && test "$(PO2HTML)" != "off" && test -f $(top_srcdir)/errors/en.po; then \ + lang=`basename $@ .lang`; \ + mkdir -p $(top_builddir)/errors/$$lang; \ + echo -n "Translate '$$lang' ..."; \ + for f in $(ERROR_TEMPLATES); do \ + page=`basename $$f`; \ + $(PO2HTML) --progress=none -i $(top_srcdir)/errors/$$lang.po -t $(top_srcdir)/errors/$$f >$(top_builddir)/errors/$$lang/$$page || exit 1; \ done; \ - fi \ - done; \ - $(INSTALL_DATA) $(srcdir)/TRANSLATORS $(DESTDIR)$(DEFAULT_ERROR_DIR)/TRANSLATORS; \ - $(INSTALL_DATA) $(srcdir)/COPYRIGHT $(DESTDIR)$(DEFAULT_ERROR_DIR)/COPYRIGHT; \ - $(INSTALL_DATA) $(srcdir)/errorpage.css $(DESTDIR)$(DEFAULT_STYLESHEET).default; \ + echo "done."; \ + fi; \ + touch $@ + +install-exec-local: translate if test -f $(DESTDIR)$(DEFAULT_STYLESHEET) ; then \ echo "$@ will not overwrite existing $(DESTDIR)$(DEFAULT_STYLESHEET)" ; \ else \ + $(mkinstalldirs) $(DESTDIR)`dirname $(DEFAULT_STYLESHEET)` ; \ echo "$(INSTALL_DATA) $(srcdir)/errorpage.css $(DESTDIR)$(DEFAULT_STYLESHEET)"; \ $(INSTALL_DATA) $(srcdir)/errorpage.css $(DESTDIR)$(DEFAULT_STYLESHEET); \ - fi ; \ - $(SHELL) $(srcdir)/alias-link.sh "$(LN)" "$(RM)" "$(DESTDIR)$(DEFAULT_ERROR_DIR)" "$(srcdir)/aliases" || exit 1 ; + fi +install-data-local: translate + $(mkinstalldirs) $(DESTDIR)$(DEFAULT_ERROR_DIR) ; \ + for l in $(TRANSLATE_LANGUAGES); do \ + l=`basename $$l .lang`; \ + echo "Located $$l for install..."; \ + if test -d $(srcdir)/$$l || test -d $(builddir)/$$l; then \ + $(mkinstalldirs) $(DESTDIR)$(DEFAULT_ERROR_DIR)/$$l; \ + fi; \ + for f in $(ERROR_TEMPLATES); do \ + page=`basename $$f`; \ + if test -f $(builddir)/$$l/$$f; then \ + echo "$(INSTALL_DATA) $(builddir)/$$l/$$f $(DESTDIR)$(DEFAULT_ERROR_DIR)/$$l"; \ + $(INSTALL_DATA) $(builddir)/$$l/$$f $(DESTDIR)$(DEFAULT_ERROR_DIR)/$$l; \ + elif test -f $(srcdir)/$$l/$$f; then \ + echo "$(INSTALL_DATA) $(srcdir)/$$l/$$f $(DESTDIR)$(DEFAULT_ERROR_DIR)/$$l"; \ + $(INSTALL_DATA) $(srcdir)/$$l/$$f $(DESTDIR)$(DEFAULT_ERROR_DIR)/$$l; \ + fi; \ + done; \ + done; \ + $(INSTALL_DATA) $(srcdir)/TRANSLATORS $(DESTDIR)$(DEFAULT_ERROR_DIR)/TRANSLATORS; \ + $(INSTALL_DATA) $(srcdir)/COPYRIGHT $(DESTDIR)$(DEFAULT_ERROR_DIR)/COPYRIGHT; \ + $(INSTALL_DATA) $(srcdir)/errorpage.css $(DESTDIR)$(DEFAULT_STYLESHEET).default; \ + $(SHELL) $(srcdir)/alias-link.sh "$(LN)" "$(RM)" "$(DESTDIR)$(DEFAULT_ERROR_DIR)" "$(srcdir)/aliases" || exit 1 ; uninstall-local: - for l in $(TRANSLATIONDIR) ; do \ + for l in $(TRANSLATE_LANGUAGES) templates; do \ + l=`basename $$l .lang`; \ echo "Located $$l for uninstall ..."; \ if test -d $(srcdir)/$$l; then \ for f in $(srcdir)/$$l/ERR_*; do \ @@ -74,42 +186,21 @@ upgrade: install $(SHELL) $(srcdir)/alias-link.sh "$(LN)" "$(RM)" "$(DESTDIR)$(DEFAULT_ERROR_DIR)" "$(srcdir)/alias-upgrade" || exit 1 ; dist-hook: translate - for lang in $(TRANSLATIONPO) templates; do \ + for lang in $(TRANSLATE_LANGUAGES); do \ + lang=`basename $$lang .lang`; \ if test -d $$lang ; then \ - test -d $(distdir)/$$lang \ - || mkdir $(distdir)/$$lang \ - || exit 1; \ + mkdir -p $(distdir)/$$lang; \ cp -p $(top_builddir)/errors/$$lang/ERR_* $(distdir)/$$lang \ || exit 1; \ fi; \ - done; \ - for f in aliases alias-link.sh alias-upgrade errorpage.css TRANSLATORS COPYRIGHT; do \ - cp -p $(srcdir)/$$f $(distdir)/`basename $$f`; \ - done; + done -translate: - @if ! test -f $(top_srcdir)/errors/en.po; then \ - echo "Translation is not currently possible."; \ - exit 0; \ - fi; \ +clean: clean-am if test "$(PO2HTML)" != "" && test "$(PO2HTML)" != "no" && test "$(PO2HTML)" != "off" && test -f $(top_srcdir)/errors/en.po; then \ - for lang in $(TRANSLATIONPO); do \ - test -d $(top_builddir)/errors/$$lang && $(RM) -r $(top_builddir)/errors/$$lang; \ - mkdir $(top_builddir)/errors/$$lang || exit 1; \ - echo -n "Translate '$$lang' ..."; \ - for f in `ls -1 $(top_srcdir)/errors/templates`; do \ - $(PO2HTML) --progress=none -i $(top_srcdir)/errors/$$lang.po -t $(top_srcdir)/errors/templates/$$f >$(top_builddir)/errors/$$lang/$$f || exit 1; \ - done; \ - echo "done."; \ + for lang in $(TRANSLATE_LANGUAGES); do \ + lang=`basename $$lang .lang`; \ + rm -rf $$lang; \ done; \ - else \ - if test "$(PO2HTML)" = "off" ; then \ - echo "WARNING: Translation is disabled."; \ - else \ - echo "WARNING: Translation toolkit was not detected."; \ - fi; \ - echo "A drop-in bundle of pre-translated files is available from"; \ - echo "http://www.squid-cache.org/Versions/langpack/"; \ fi all: translate diff --git a/errors/alias-link.sh b/errors/alias-link.sh index 384a9e1836..70f6b14e90 100755 --- a/errors/alias-link.sh +++ b/errors/alias-link.sh @@ -38,6 +38,6 @@ while read base aliases; do # Remove and replace any pre-existing content/link for alia in ${aliases}; do ${RM} -f -r ${DIR}/${alia} || exit 1 - ${LN} -s ${DIR}/${base} ${DIR}/${alia} || exit 1 + ${LN} -s ${base} ${DIR}/${alia} || exit 1 done done diff --git a/helpers/Makefile.am b/helpers/Makefile.am index d509c84ed1..0123cb9dc7 100644 --- a/helpers/Makefile.am +++ b/helpers/Makefile.am @@ -1 +1 @@ -SUBDIRS = basic_auth ntlm_auth digest_auth negotiate_auth external_acl +SUBDIRS = basic_auth ntlm_auth digest_auth negotiate_auth external_acl url_rewrite diff --git a/helpers/digest_auth/ldap/ldap_backend.c b/helpers/digest_auth/ldap/ldap_backend.c index 0e4a9fecda..47b440829c 100644 --- a/helpers/digest_auth/ldap/ldap_backend.c +++ b/helpers/digest_auth/ldap/ldap_backend.c @@ -361,10 +361,12 @@ ldapconnect(void) } if (use_tls) { #ifdef LDAP_OPT_X_TLS - if ((version == LDAP_VERSION3) && (ldap_start_tls_s(ld, NULL, NULL) == LDAP_SUCCESS)) { + if (version != LDAP_VERSION3) { + fprintf(stderr, "TLS requires LDAP version 3\n"); + exit(1); + } else if (ldap_start_tls_s(ld, NULL, NULL) != LDAP_SUCCESS) { fprintf(stderr, "Could not Activate TLS connection\n"); - ldap_unbind(ld); - ld = NULL; + exit(1); } #else fprintf(stderr, "TLS not supported with your LDAP library\n"); diff --git a/helpers/external_acl/wbinfo_group/wbinfo_group.pl b/helpers/external_acl/wbinfo_group/wbinfo_group.pl index 06e970a759..4df2cdccdc 100755 --- a/helpers/external_acl/wbinfo_group/wbinfo_group.pl +++ b/helpers/external_acl/wbinfo_group/wbinfo_group.pl @@ -34,7 +34,7 @@ use vars qw/ %opt /; # Disable output buffering -$|=1; +$|=1; sub debug { print STDERR "@_\n" if $opt{d}; @@ -86,7 +86,7 @@ print STDERR "Debugging mode ON.\n" if $opt{d}; # while () { chop; - &debug ("Got $_ from squid"); + &debug("Got $_ from squid"); ($user, @groups) = split(/\s+/); $user =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack("c",hex($1))/eg; # test for each group squid send in it's request @@ -95,7 +95,7 @@ while () { $ans = &check($user, $group); last if $ans eq "OK"; } - &debug ("Sending $ans to squid"); + &debug("Sending $ans to squid"); print "$ans\n"; } diff --git a/helpers/ntlm_auth/smb_lm/libntlmssp.c b/helpers/ntlm_auth/smb_lm/libntlmssp.c index d6e58b5449..65bc9942ca 100644 --- a/helpers/ntlm_auth/smb_lm/libntlmssp.c +++ b/helpers/ntlm_auth/smb_lm/libntlmssp.c @@ -260,7 +260,7 @@ ntlm_check_auth(ntlm_authenticate * auth, int auth_length) pass[min(MAX_PASSWD_LEN,tmp.l)] = '\0'; #if 1 - debug ("Empty LM pass detection: user: '%s', ours:'%s', his: '%s'" + debug("Empty LM pass detection: user: '%s', ours:'%s', his: '%s'" "(length: %d)\n", user,lmencoded_empty_pass,tmp.str,tmp.l); if (memcmp(tmp.str,lmencoded_empty_pass,ENCODED_PASS_LEN)==0) { @@ -272,7 +272,7 @@ ntlm_check_auth(ntlm_authenticate * auth, int auth_length) tmp = ntlm_fetch_string ((char *) auth, auth_length, &auth->ntresponse); if (tmp.str != NULL && tmp.l != 0) { - debug ("Empty NT pass detection: user: '%s', ours:'%s', his: '%s'" + debug("Empty NT pass detection: user: '%s', ours:'%s', his: '%s'" "(length: %d)\n", user,ntencoded_empty_pass,tmp.str,tmp.l); if (memcmp(tmp.str,lmencoded_empty_pass,ENCODED_PASS_LEN)==0) { diff --git a/helpers/ntlm_auth/smb_lm/ntlm_smb_lm_auth.c b/helpers/ntlm_auth/smb_lm/ntlm_smb_lm_auth.c index 80a9c3008c..597150bf8f 100644 --- a/helpers/ntlm_auth/smb_lm/ntlm_smb_lm_auth.c +++ b/helpers/ntlm_auth/smb_lm/ntlm_smb_lm_auth.c @@ -155,7 +155,7 @@ usage() my_program_name, my_program_name); } -char debug_enabled=0; +int debug_enabled=0; void process_options(int argc, char *argv[]) diff --git a/helpers/ntlm_auth/smb_lm/ntlm_smb_lm_auth.h b/helpers/ntlm_auth/smb_lm/ntlm_smb_lm_auth.h index de63809b05..bfb296760c 100644 --- a/helpers/ntlm_auth/smb_lm/ntlm_smb_lm_auth.h +++ b/helpers/ntlm_auth/smb_lm/ntlm_smb_lm_auth.h @@ -41,33 +41,6 @@ /************* END CONFIGURATION ***************/ -#include - - -/* Debugging stuff */ - -#ifdef __GNUC__ /* this is really a gcc-ism */ -#ifdef DEBUG -#include -#include -static const char *__foo; -extern char debug_enabled; -#define debug(X...) if (debug_enabled) { \ - fprintf(stderr,"ntlm-auth[%ld](%s:%d): ", (long)getpid(), \ - ((__foo=strrchr(__FILE__,'/'))==NULL?__FILE__:__foo+1),\ - __LINE__);\ - fprintf(stderr,X); } -#else /* DEBUG */ -#define debug(X...) /* */ -#endif /* DEBUG */ -#else /* __GNUC__ */ -static void -debug(char *format,...) -{ -} - -#endif - /* A couple of harmless helper macros */ #define SEND(X) debug("sending '%s' to squid\n",X); printf(X "\n"); diff --git a/helpers/url_rewrite/Makefile.am b/helpers/url_rewrite/Makefile.am new file mode 100644 index 0000000000..f439bcb2bc --- /dev/null +++ b/helpers/url_rewrite/Makefile.am @@ -0,0 +1,3 @@ + +DIST_SUBDIRS = fake +SUBDIRS = @URL_REWRITE_HELPERS@ diff --git a/helpers/url_rewrite/fake/Makefile.am b/helpers/url_rewrite/fake/Makefile.am new file mode 100644 index 0000000000..eb1040ec45 --- /dev/null +++ b/helpers/url_rewrite/fake/Makefile.am @@ -0,0 +1,10 @@ +include $(top_srcdir)/src/Common.am + +libexec_PROGRAMS = url_fake_rewrite +url_fake_rewrite_SOURCES = fake.cc + +url_fake_rewrite_LDADD = $(COMPAT_LIB) + +libexec_SCRIPTS = url_fake_rewrite.sh + +EXTRA_DIST = url_fake_rewrite.sh diff --git a/helpers/url_rewrite/fake/config.test b/helpers/url_rewrite/fake/config.test new file mode 100755 index 0000000000..039e4d0069 --- /dev/null +++ b/helpers/url_rewrite/fake/config.test @@ -0,0 +1,2 @@ +#!/bin/sh +exit 0 diff --git a/helpers/url_rewrite/fake/fake.cc b/helpers/url_rewrite/fake/fake.cc new file mode 100644 index 0000000000..59604cc0eb --- /dev/null +++ b/helpers/url_rewrite/fake/fake.cc @@ -0,0 +1,100 @@ +/* + * AUTHOR: Amos Jeffries + * + * Example url re-writer program for Squid. + * + * This code gets the url and returns it. No re-writing is done. + * It is intended for testing use and as a base for further implementation. + * + * + * This code is copyright (C) 2009 by Treehouse Networks Ltd + * of New Zealand. It is published and Licensed as an extension of + * squid under the same conditions as the main squid application. + */ + +#include "config.h" + +#if HAVE_CSTRING +#include +#endif + +#define BUFFER_SIZE 10240 + +/** + * options: + * -d enable debugging. + * -h interface help. + */ +char *my_program_name = NULL; +int debug_enabled = 0; + +static void +usage(void) +{ + fprintf(stderr, + "Usage: %s [-d] [-v] [-h]\n" + " -d enable debugging.\n" + " -h this message\n\n", + my_program_name); +} + +static void +process_options(int argc, char *argv[]) +{ + int opt, had_error = 0; + + opterr = 0; + while (-1 != (opt = getopt(argc, argv, "hd"))) { + switch (opt) { + case 'd': + debug_enabled = 1; + break; + case 'h': + usage(); + exit(0); + case '?': + opt = optopt; + /* fall thru to default */ + default: + fprintf(stderr, "unknown option: -%c. Exiting\n", opt); + usage(); + had_error = 1; + } + } + if (had_error) + exit(1); +} + +int +main(int argc, char *argv[]) +{ + char buf[BUFFER_SIZE]; + int buflen = 0; + + setbuf(stdout, NULL); + setbuf(stderr, NULL); + + my_program_name = argv[0]; + + process_options(argc, argv); + + debug("%s build " __DATE__ ", " __TIME__ " starting up...\n", my_program_name); + + while (fgets(buf, BUFFER_SIZE, stdin) != NULL) { + char *p; + + if ((p = strchr(buf, '\n')) != NULL) { + *p = '\0'; /* strip \n */ + buflen = p - buf; /* length is known already */ + } + else + buflen = strlen(buf); /* keep this so we only scan the buffer for \0 once per loop */ + + debug("Got %d bytes '%s' from Squid\n", buflen, buf); + + /* send 'no-change' result back to Squid */ + fprintf(stdout,"\n"); + } + debug("%s build " __DATE__ ", " __TIME__ " shutting down...\n", my_program_name); + exit(0); +} diff --git a/helpers/url_rewrite/fake/fake.h b/helpers/url_rewrite/fake/fake.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/helpers/url_rewrite/fake/url_fake_rewrite.sh b/helpers/url_rewrite/fake/url_fake_rewrite.sh new file mode 100755 index 0000000000..08f7f690ee --- /dev/null +++ b/helpers/url_rewrite/fake/url_fake_rewrite.sh @@ -0,0 +1,48 @@ +#!/bin/sh +# +# Author: Amos Jeffries +# +# This code is copyright (C) 2009 by Treehouse Networks Ltd +# of New Zealand. It is published and Licensed as an extension of +# squid under the same conditions as the main squid application. +# + +if test "${1}" = "-h" ; then + echo "Usage: $0 [-h] [-c] [-d logfile]" + echo " -h Help: this help text" + echo " -c Accept concurrent request format" + echo " -d logfile Debug: log all data received to the named file" + exit 1 +fi + +concurrent=0 +if test "${1}" = "-c" ; then + concurrent=1 + shift +fi + +DEBUG=0 +if test "${1}" = "-d" ; then + DEBUG=1 + LOG="${2}" +fi + +if test "$concurrent" = "1"; then + # read concurrent input format + while read id url rest; do + if test "${DEBUG}" = "1" ; then + echo "ID:$id URL:$url EXTRAS:$rest" >>${LOG} + fi + # blank URL for no change, or replace with another URL. + echo "${id} " + done +else + # read old non-concurrent input format + while read url rest; do + if test "${DEBUG}" = "1" ; then + echo "URL:$url EXTRAS:$rest" >>${LOG} + fi + # blank line/URL for no change, or replace with another URL. + echo + done +fi diff --git a/squid3.dox b/squid3.dox index 647255503d..c0b6126bea 100644 --- a/squid3.dox +++ b/squid3.dox @@ -1304,7 +1304,8 @@ EXPAND_AS_DEFINED = AsyncCallWrapper \ AsyncCallEnter \ AsyncCallExit \ CBDATA_CLASS2 \ - MEMPROXY_CLASS_INLINE + MEMPROXY_CLASS_INLINE \ + MEMPROXY_CLASS # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone diff --git a/src/Common.am b/src/Common.am index 7f4c8d7fc2..dd10d15c5c 100644 --- a/src/Common.am +++ b/src/Common.am @@ -24,7 +24,6 @@ INCLUDES = \ ## XXX: Do we really need this? Does auto-dependency tracking work? $(OBJS): $(top_srcdir)/include/version.h $(top_builddir)/include/autoconf.h - ## Because compatibility is almost universal. And the link order is important. COMPAT_LIB = \ -L$(top_builddir)/lib -lmiscutil \ diff --git a/src/ConfigParser.cc b/src/ConfigParser.cc index 9853875c3c..2453344c55 100644 --- a/src/ConfigParser.cc +++ b/src/ConfigParser.cc @@ -51,7 +51,7 @@ ConfigParser::strtokFile(void) static FILE *wordFile = NULL; char *t, *fn; - LOCAL_ARRAY(char, buf, 256); + LOCAL_ARRAY(char, buf, CONFIG_LINE_LIMIT); do { @@ -86,7 +86,7 @@ ConfigParser::strtokFile(void) } /* fromFile */ - if (fgets(buf, 256, wordFile) == NULL) { + if (fgets(buf, CONFIG_LINE_LIMIT, wordFile) == NULL) { /* stop reading from file */ fclose(wordFile); wordFile = NULL; diff --git a/src/ConfigParser.h b/src/ConfigParser.h index 2c466ed86f..4d5a25ba6a 100644 --- a/src/ConfigParser.h +++ b/src/ConfigParser.h @@ -38,7 +38,17 @@ #include "squid.h" -/* +/** + * Limit to how long any given config line may be. + * This affects squid.conf and all included files. + * + * Behaviour when setting larger than 2KB is unknown. + * The config parser read mechanism can cope, but the other systems + * receiving the data from its buffers on such lines may not. + */ +#define CONFIG_LINE_LIMIT 2048 + +/** * A configuration file Parser. Instances of this class track * parsing state and perform tokenisation. Syntax is currently * taken care of outside this class. @@ -48,7 +58,6 @@ * in all of squid by reference. Instead the tokeniser only is * brought in. */ - class ConfigParser { diff --git a/src/Debug.h b/src/Debug.h index b2134c1bc3..1a30f17c9a 100644 --- a/src/Debug.h +++ b/src/Debug.h @@ -137,9 +137,10 @@ inline std::ostream& operator <<(std::ostream &os, const uint8_t d) } /* Legacy debug style. Still used in some places. needs to die... */ -#define do_debug(SECTION, LEVEL) ((Debug::level = (LEVEL)) > Debug::Levels[SECTION]) -#define old_debug(SECTION, LEVEL) \ - do_debug(SECTION, LEVEL) ? (void) 0 : _db_print +#define do_debug(SECTION, LEVEL) ((Debug::level = (LEVEL)) > Debug::Levels[SECTION]) +#define old_debug(SECTION, LEVEL) if( (Debug::level=(LEVEL)) <= Debug::Levels[SECTION] ) _db_print +/* Legacy debug function definitions */ +SQUIDCEXTERN void _db_print(const char *,...) PRINTF_FORMAT_ARG1; #endif /* SQUID_DEBUG_H */ diff --git a/src/HttpHeaderTools.cc b/src/HttpHeaderTools.cc index 4384b3be29..3a2b7d3ad0 100644 --- a/src/HttpHeaderTools.cc +++ b/src/HttpHeaderTools.cc @@ -327,11 +327,11 @@ httpHeaderParseOffset(const char *start, int64_t * value) /** * Parses a quoted-string field (RFC 2616 section 2.2), complains if * something went wrong, returns non-zero on success. - * start should point at the first ". + * start should point at the first double-quote. * RC TODO: This is too looose. We should honour the BNF and exclude CTL's */ int -httpHeaderParseQuotedString (const char *start, String *val) +httpHeaderParseQuotedString(const char *start, String *val) { const char *end, *pos; val->clean(); diff --git a/src/HttpRequest.h b/src/HttpRequest.h index 98d98716aa..3b241ec23a 100644 --- a/src/HttpRequest.h +++ b/src/HttpRequest.h @@ -175,6 +175,8 @@ public: char *peer_login; /* Configured peer login:password */ + char *peer_host; /* Selected peer host*/ + time_t lastmod; /* Used on refreshes */ const char *vary_headers; /* Used when varying entities are detected. Changes how the store key is calculated */ diff --git a/src/Makefile.am b/src/Makefile.am index 4db4ec7b78..f4874bfb57 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -392,6 +392,7 @@ squid_SOURCES = \ pconn.h \ PeerDigest.h \ peer_digest.cc \ + peer_proxy_negotiate_auth.cc \ peer_select.cc \ peer_sourcehash.cc \ peer_userhash.cc \ @@ -543,7 +544,8 @@ squid_LDADD = \ @SSLLIB@ \ @XTRA_LIBS@ \ @EPOLL_LIBS@ \ - @MINGW_LIBS@ + @MINGW_LIBS@ \ + @KRB5LIBS@ squid_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a \ @DISK_LIBS@ \ @DISK_LINKOBJS@ \ @@ -565,6 +567,9 @@ squid_LDFLAGS = \ # endif +## Kerberos libraries require their include path... +INCLUDES += @KRB5INCS@ + unlinkd_SOURCES = unlinkd_daemon.cc SquidNew.cc @@ -629,7 +634,7 @@ ufsdump_LDADD = \ -L$(top_builddir)/lib -lmiscutil \ @XTRA_LIBS@ \ @EPOLL_LIBS@ \ - @MINGW_LIBS@ + @MINGW_LIBS@ ufsdump_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a \ $(COMMON_LIBS) \ @DISK_LIBS@ \ @@ -1143,6 +1148,7 @@ tests_testCacheManager_SOURCES = \ Parsing.cc \ pconn.cc \ peer_digest.cc \ + peer_proxy_negotiate_auth.cc \ peer_select.cc \ peer_sourcehash.cc \ peer_userhash.cc \ @@ -1203,7 +1209,8 @@ tests_testCacheManager_LDADD = \ @SQUID_CPPUNIT_LIBS@ \ @SQUID_CPPUNIT_LA@ \ @SSLLIB@ \ - @XTRA_LIBS@ + @XTRA_LIBS@ \ + @KRB5LIBS@ tests_testCacheManager_LDFLAGS = $(LIBADD_DL) tests_testCacheManager_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a \ @REPL_OBJS@ \ @@ -1313,6 +1320,7 @@ tests_testEvent_SOURCES = \ Parsing.cc \ pconn.cc \ peer_digest.cc \ + peer_proxy_negotiate_auth.cc \ peer_select.cc \ peer_sourcehash.cc \ peer_userhash.cc \ @@ -1372,7 +1380,8 @@ tests_testEvent_LDADD = \ @SQUID_CPPUNIT_LIBS@ \ @SQUID_CPPUNIT_LA@ \ @SSLLIB@ \ - @XTRA_LIBS@ + @XTRA_LIBS@ \ + @KRB5LIBS@ tests_testEvent_LDFLAGS = $(LIBADD_DL) tests_testEvent_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a \ @REPL_OBJS@ \ @@ -1460,6 +1469,7 @@ tests_testEventLoop_SOURCES = \ Parsing.cc \ pconn.cc \ peer_digest.cc \ + peer_proxy_negotiate_auth.cc \ peer_select.cc \ peer_sourcehash.cc \ peer_userhash.cc \ @@ -1519,7 +1529,8 @@ tests_testEventLoop_LDADD = \ @SQUID_CPPUNIT_LIBS@ \ @SQUID_CPPUNIT_LA@ \ @SSLLIB@ \ - @XTRA_LIBS@ + @XTRA_LIBS@ \ + @KRB5LIBS@ tests_testEventLoop_LDFLAGS = $(LIBADD_DL) tests_testEventLoop_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a \ @REPL_OBJS@ \ @@ -1596,6 +1607,7 @@ tests_test_http_range_SOURCES = \ neighbors.cc \ Parsing.cc \ peer_digest.cc \ + peer_proxy_negotiate_auth.cc \ peer_select.cc \ peer_sourcehash.cc \ peer_userhash.cc \ @@ -1661,7 +1673,8 @@ tests_test_http_range_LDADD = \ @SQUID_CPPUNIT_LIBS@ \ @SQUID_CPPUNIT_LA@ \ @SSLLIB@ \ - @XTRA_LIBS@ + @XTRA_LIBS@ \ + @KRB5LIBS@ tests_test_http_range_LDFLAGS = $(LIBADD_DL) tests_test_http_range_DEPENDENCIES = \ @SQUID_CPPUNIT_LA@ @@ -1748,6 +1761,7 @@ tests_testHttpRequest_SOURCES = \ Parsing.cc \ pconn.cc \ peer_digest.cc \ + peer_proxy_negotiate_auth.cc \ peer_select.cc \ peer_sourcehash.cc \ peer_userhash.cc \ @@ -1808,7 +1822,8 @@ tests_testHttpRequest_LDADD = \ @SQUID_CPPUNIT_LIBS@ \ @SQUID_CPPUNIT_LA@ \ @SSLLIB@ \ - @XTRA_LIBS@ + @XTRA_LIBS@ \ + @KRB5LIBS@ tests_testHttpRequest_LDFLAGS = $(LIBADD_DL) tests_testHttpRequest_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a \ @REPL_OBJS@ \ @@ -2097,6 +2112,7 @@ tests_testURL_SOURCES = \ Parsing.cc \ pconn.cc \ peer_digest.cc \ + peer_proxy_negotiate_auth.cc \ peer_select.cc \ peer_sourcehash.cc \ peer_userhash.cc \ @@ -2154,7 +2170,8 @@ tests_testURL_LDADD = \ @SQUID_CPPUNIT_LIBS@ \ @SQUID_CPPUNIT_LA@ \ @SSLLIB@ \ - @XTRA_LIBS@ + @XTRA_LIBS@ \ + @KRB5LIBS@ tests_testURL_LDFLAGS = $(LIBADD_DL) tests_testURL_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a \ @REPL_OBJS@ \ diff --git a/src/cache_cf.cc b/src/cache_cf.cc index 22a8d9fe90..2689d2f0a2 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -430,6 +430,12 @@ configDoConfigure(void) memConfigure(); /* Sanity checks */ + if (Config.cacheSwap.swapDirs == NULL) { + /* Memory-only cache probably in effect. */ + /* turn off the cache rebuild delays... */ + StoreController::store_dirs_rebuilding = 0; + } + if (Debug::rotateNumber < 0) { Debug::rotateNumber = Config.Log.rotateNumber; } @@ -1889,7 +1895,7 @@ parse_peer(peer ** head) p->weight = 1; if (p->connect_fail_limit < 1) - p->connect_fail_limit = 1; + p->connect_fail_limit = 10; p->icp.version = ICP_VERSION_CURRENT; @@ -3082,16 +3088,7 @@ parse_http_port_option(http_port_list * s, char *token) IpInterceptor.StartTransparency(); /* Log information regarding the port modes under transparency. */ debugs(3, DBG_IMPORTANT, "Starting IP Spoofing on port " << s->s); - debugs(3, DBG_IMPORTANT, "Disabling Authentication on port " << s->s << " (Ip spoofing enabled)"); - -#if USE_IPV6 - /* INET6: until target TPROXY is known to work on IPv6 SOCKET, force wildcard to IPv4 */ - debugs(3, DBG_IMPORTANT, "Disabling IPv6 on port " << s->s << " (interception enabled)"); - if ( s->s.IsIPv6() && !s->s.SetIPv4() ) { - debugs(3, DBG_CRITICAL, "http(s)_port: IPv6 addresses cannot be transparent (protocol does not provide NAT)" << s->s ); - self_destruct(); - } -#endif + debugs(3, DBG_IMPORTANT, "Disabling Authentication on port " << s->s << " (IP spoofing enabled)"); } else if (strcmp(token, "ipv4") == 0) { #if USE_IPV6 diff --git a/src/cf.data.pre b/src/cf.data.pre index c27c9a29ee..4de0b74cfe 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -1822,6 +1822,19 @@ DOC_START be used to identify this proxy to the peer, similar to the login=username:password option above. + login=NEGOTIATE + If this is a personal/workgroup proxy and your parent + requires a secure proxy authentication. + The first principal from the default keytab or defined by + the environment variable KRB5_KTNAME will be used. + + login=NEGOTIATE:principal_name + If this is a personal/workgroup proxy and your parent + requires a secure proxy authentication. + The principal principal_name from the default keytab or + defined by the environment variable KRB5_KTNAME will be + used. + connection-auth=on|off Tell Squid that this peer does or not support Microsoft connection oriented authentication, and any such diff --git a/src/client_side.cc b/src/client_side.cc index 6d5d77c598..1b05a90003 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -1989,6 +1989,15 @@ parseHttpRequest(ConnStateData *conn, HttpParser *hp, HttpRequestMethod * method /* Set method_p */ *method_p = HttpRequestMethod(&hp->buf[hp->m_start], &hp->buf[hp->m_end]+1); + /* deny CONNECT via accelerated ports */ + if (*method_p == METHOD_CONNECT && conn && conn->port && conn->port->accel) { + debugs(33, DBG_IMPORTANT, "WARNING: CONNECT method received on " << conn->port->protocol << " Accelerator port " << conn->port->s.GetPort() ); + /* XXX need a way to say "this many character length string" */ + debugs(33, DBG_IMPORTANT, "WARNING: for request: " << hp->buf); + /* XXX need some way to set 405 status on the error reply */ + return parseHttpRequestAbort(conn, "error:method-not-allowed"); + } + if (*method_p == METHOD_NONE) { /* XXX need a way to say "this many character length string" */ debugs(33, 1, "clientParseRequestMethod: Unsupported method in request '" << hp->buf << "'"); diff --git a/src/fs/ufs/store_dir_ufs.cc b/src/fs/ufs/store_dir_ufs.cc index 6ba640b378..1f40f900aa 100644 --- a/src/fs/ufs/store_dir_ufs.cc +++ b/src/fs/ufs/store_dir_ufs.cc @@ -144,7 +144,7 @@ UFSSwapDir::changeIO(DiskIOModule *module) IO->io = anIO; /* Change the IO Options */ - if (currentIOOptions->options.size() > 2) + if (currentIOOptions && currentIOOptions->options.size() > 2) delete currentIOOptions->options.pop_back(); /* TODO: factor out these 4 lines */ diff --git a/src/http.cc b/src/http.cc index 24b3ee8ed5..dca3be0c13 100644 --- a/src/http.cc +++ b/src/http.cc @@ -39,25 +39,28 @@ */ #include "squid.h" + +#include "acl/FilledChecklist.h" +#include "auth/UserRequest.h" +#if DELAY_POOLS +#include "DelayPools.h" +#endif #include "errorpage.h" -#include "MemBuf.h" +#include "fde.h" #include "http.h" -#include "auth/UserRequest.h" -#include "Store.h" -#include "HttpReply.h" -#include "HttpRequest.h" -#include "MemObject.h" #include "HttpHdrContRange.h" #include "HttpHdrSc.h" #include "HttpHdrScTarget.h" -#include "acl/FilledChecklist.h" -#include "fde.h" -#if DELAY_POOLS -#include "DelayPools.h" -#endif +#include "HttpReply.h" +#include "HttpRequest.h" +#include "MemBuf.h" +#include "MemObject.h" +#include "protos.h" #include "SquidTime.h" +#include "Store.h" #include "TextException.h" + #define SQUID_ENTER_THROWING_CODE() try { #define SQUID_EXIT_THROWING_CODE(status) \ status = true; \ @@ -1511,6 +1514,22 @@ httpFixupAuthentication(HttpRequest * request, HttpRequest * orig_request, const return; } + /* Kerberos login to peer */ +#if HAVE_KRB5 && HAVE_GSSAPI + if (strncmp(orig_request->peer_login, "NEGOTIATE",strlen("NEGOTIATE")) == 0) { + char *Token=NULL; + char *PrincipalName=NULL,*p; + if ((p=strchr(orig_request->peer_login,':')) != NULL ) { + PrincipalName=++p; + } + Token = peer_proxy_negotiate_auth(PrincipalName,request->peer_host); + if (Token) { + httpHeaderPutStrf(hdr_out, HDR_PROXY_AUTHORIZATION, "Negotiate %s",Token); + } + return; + } +#endif /* HAVE_KRB5 && HAVE_GSSAPI */ + httpHeaderPutStrf(hdr_out, header, "Basic %s", base64_encode(orig_request->peer_login)); return; @@ -1990,6 +2009,7 @@ HttpStateData::sendRequest() } mb.init(); + request->peer_host=_peer?_peer->host:NULL; buildRequestPrefix(request, orig_request, entry, &mb, flags); debugs(11, 6, "httpSendRequest: FD " << fd << ":\n" << mb.buf); comm_write_mbuf(fd, &mb, requestSender); diff --git a/src/peer_proxy_negotiate_auth.cc b/src/peer_proxy_negotiate_auth.cc new file mode 100644 index 0000000000..d1e2028c38 --- /dev/null +++ b/src/peer_proxy_negotiate_auth.cc @@ -0,0 +1,550 @@ +/* + * ----------------------------------------------------------------------------- + * + * Author: Markus Moeller (markus_moeller at compuserve.com) + * + * Copyright (C) 2007 Markus Moeller. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * ----------------------------------------------------------------------------- + */ +/* + * Hosted at http://sourceforge.net/projects/squidkerbauth + */ + +#include + +#if HAVE_KRB5 && HAVE_GSSAPI +#ifdef __cplusplus +extern "C" +{ +#endif + +#if HAVE_PROFILE_H +#include +#endif /* HAVE_PROFILE_H */ +#if HAVE_KRB5_H +#include +#elif HAVE_ET_COM_ERR_H +#include +#endif /* HAVE_COM_ERR_H */ +#if HAVE_COM_ERR_H +#include +#endif /* HAVE_COM_ERR_H */ + +#if HAVE_GSSAPI_GSSAPI_H +#include +#elif HAVE_GSSAPI_H +#include +#endif /* HAVE_GSSAPI_H */ +#if HAVE_GSSAPI_GSSAPI_EXT_H +#include +#endif /* HAVE_GSSAPI_GSSAPI_EXT_H */ +#if HAVE_GSSAPI_GSSAPI_KRB5_H +#include +#endif /* HAVE_GSSAPI_GSSAPI_KRB5_H */ +#if HAVE_GSSAPI_GSSAPI_GENERIC_H +#include +#endif /* HAVE_GSSAPI_GSSAPI_GENERIC_H */ + +#ifndef gss_nt_service_name +#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE +#endif + +#if !HAVE_ERROR_MESSAGE && HAVE_KRB5_GET_ERR_TEXT +#define error_message(code) krb5_get_err_text(kparam.context,code) +#elif !HAVE_ERROR_MESSAGE && HAVE_KRB5_GET_ERROR_MESSAGE +#define error_message(code) krb5_get_error_message(kparam.context,code) +#elif !HAVE_ERROR_MESSAGE +static char err_code[17]; +const char *KRB5_CALLCONV +error_message(long code) +{ + snprintf(err_code,16,"%ld",code); + return err_code; +} +#endif + +#ifndef gss_mech_spnego + static gss_OID_desc _gss_mech_spnego = + { 6, (void *) "\x2b\x06\x01\x05\x05\x02" }; + gss_OID gss_mech_spnego = &_gss_mech_spnego; +#endif + +#if HAVE_NAS_KERBEROS +#include + const char *KRB5_CALLCONV error_message(long code) + { + char *msg = NULL; + krb5_svc_get_msg(code, &msg); + return msg; + } +#endif + +/* + * Kerberos context and cache structure + * Caches authentication details to reduce + * number of authentication requests to kdc + */ + static struct kstruct + { + krb5_context context; + krb5_ccache cc; + } kparam = { + NULL, NULL}; + +/* + * krb5_create_cache creates a Kerberos file credential cache or a memory + * credential cache if supported. The initial key for the principal + * principal_name is extracted from the keytab keytab_filename. + * + * If keytab_filename is NULL the default will be used. + * If principal_name is NULL the first working entry of the keytab will be used. + */ + int krb5_create_cache(char *keytab_filename, char *principal_name); + +/* + * krb5_cleanup clears used Keberos memory + */ + void krb5_cleanup(void); + +/* + * check_gss_err checks for gssapi error codes, extracts the error message + * and prints it. + */ + int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, + const char *function); + + int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, + const char *function) + { + if (GSS_ERROR(major_status)) { + OM_uint32 maj_stat, min_stat; + OM_uint32 msg_ctx = 0; + gss_buffer_desc status_string; + char buf[1024]; + size_t len; + + len = 0; + msg_ctx = 0; + while (!msg_ctx) { + /* convert major status code (GSS-API error) to text */ + maj_stat = gss_display_status(&min_stat, major_status, + GSS_C_GSS_CODE, GSS_C_NULL_OID, &msg_ctx, &status_string); + if (maj_stat == GSS_S_COMPLETE) { + if (sizeof(buf) > len + status_string.length + 1) { + memcpy(buf + len, status_string.value, + status_string.length); + len += status_string.length; + } + gss_release_buffer(&min_stat, &status_string); + break; + } + gss_release_buffer(&min_stat, &status_string); + } + if (sizeof(buf) > len + 2) { + strcpy(buf + len, ". "); + len += 2; + } + msg_ctx = 0; + while (!msg_ctx) { + /* convert minor status code (underlying routine error) to text */ + maj_stat = gss_display_status(&min_stat, minor_status, + GSS_C_MECH_CODE, GSS_C_NULL_OID, &msg_ctx, &status_string); + if (maj_stat == GSS_S_COMPLETE) { + if (sizeof(buf) > len + status_string.length) { + memcpy(buf + len, status_string.value, + status_string.length); + len += status_string.length; + } + gss_release_buffer(&min_stat, &status_string); + break; + } + gss_release_buffer(&min_stat, &status_string); + } + debugs(11, 5, HERE << function << "failed: " << buf); + return (1); + } + return (0); + } + + void krb5_cleanup() + { + debugs(11, 5, HERE << "Cleanup kerberos context"); + if (kparam.context) { + if (kparam.cc) + krb5_cc_destroy(kparam.context, kparam.cc); + kparam.cc = NULL; + krb5_free_context(kparam.context); + kparam.context = NULL; + } + } + + int krb5_create_cache(char *kf, char *pn) + { + +#define KT_PATH_MAX 256 +#define MAX_RENEW_TIME "365d" +#define DEFAULT_SKEW (krb5_deltat) 600 + + static char *keytab_filename = NULL, *principal_name = NULL; + static krb5_keytab keytab = 0; + static krb5_keytab_entry entry; + static krb5_kt_cursor cursor; + static krb5_creds *creds = NULL; +#if HAVE_HEIMDAL_KERBEROS + static krb5_creds creds2; +#endif + static krb5_principal principal = NULL; + static krb5_deltat skew; + + krb5_get_init_creds_opt options; + krb5_error_code code = 0; + krb5_deltat rlife; +#if HAVE_PROFILE_H && HAVE_KRB5_GET_PROFILE && HAVE_PROFILE_GET_INTEGER && HAVE_PROFILE_RELEASE + profile_t profile; +#endif +#if HAVE_HEIMDAL_KERBEROS + krb5_kdc_flags flags; + krb5_realm *client_realm; +#endif + char *mem_cache; + + restart: +/* + * Check if credentials need to be renewed + */ + if (creds && + (creds->times.endtime - time(0) > skew) && + (creds->times.renew_till - time(0) > 2 * skew)) { + if (creds->times.endtime - time(0) < 2 * skew) { +#if !HAVE_HEIMDAL_KERBEROS + /* renew ticket */ + code = + krb5_get_renewed_creds(kparam.context, creds, principal, + kparam.cc, NULL); +#else + /* renew ticket */ + flags.i = 0; + flags.b.renewable = flags.b.renew = 1; + + code = + krb5_cc_get_principal(kparam.context, kparam.cc, + &creds2.client); + if (code) { + debugs(11, 5, + HERE << + "Error while getting principal from credential cache : " + << error_message(code)); + return (1); + } + client_realm = krb5_princ_realm(kparam.context, creds2.client); + code = + krb5_make_principal(kparam.context, &creds2.server, + *client_realm, KRB5_TGS_NAME, *client_realm, NULL); + if (code) { + debugs(11, 5, + HERE << "Error while getting krbtgt principal : " << + error_message(code)); + return (1); + } + code = + krb5_get_kdc_cred(kparam.context, kparam.cc, flags, NULL, + NULL, &creds2, &creds); + krb5_free_creds(kparam.context, &creds2); +#endif + if (code) { + if (code == KRB5KRB_AP_ERR_TKT_EXPIRED) { + krb5_free_creds(kparam.context, creds); + creds = NULL; + /* this can happen because of clock skew */ + goto restart; + } + debugs(11, 5, + HERE << "Error while get credentials : " << + error_message(code)); + return (1); + } + } + } else { + /* reinit */ + if (!kparam.context) { + code = krb5_init_context(&kparam.context); + if (code) { + debugs(11, 5, + HERE << "Error while initialising Kerberos library : " + << error_message(code)); + return (1); + } + } +#if HAVE_PROFILE_H && HAVE_KRB5_GET_PROFILE && HAVE_PROFILE_GET_INTEGER && HAVE_PROFILE_RELEASE + code = krb5_get_profile(kparam.context, &profile); + if (code) { + if (profile) + profile_release(profile); + debugs(11, 5, + HERE << "Error while getting profile : " << + error_message(code)); + return (1); + } + code = + profile_get_integer(profile, "libdefaults", "clockskew", 0, + 5 * 60, &skew); + if (profile) + profile_release(profile); + if (code) { + debugs(11, 5, + HERE << "Error while getting clockskew : " << + error_message(code)); + return (1); + } +#elif HAVE_KRB5_GET_MAX_TIME_SKEW && HAVE_HEIMDAL_KERBEROS + skew = krb5_get_max_time_skew(kparam.context); +#elif HAVE_MAX_SKEW_IN_KRB5_CONTEXT && HAVE_HEIMDAL_KERBEROS + skew = kparam.context->max_skew; +#else + skew = DEFAULT_SKEW; +#endif + + if (!kf) { + char buf[KT_PATH_MAX], *p; + + krb5_kt_default_name(kparam.context, buf, KT_PATH_MAX); + p = strchr(buf, ':'); + if (p) + p++; + if (keytab_filename) + xfree(keytab_filename); + keytab_filename = xstrdup(p ? p : buf); + } else { + keytab_filename = xstrdup(kf); + } + + code = krb5_kt_resolve(kparam.context, keytab_filename, &keytab); + if (code) { + debugs(11, 5, + HERE << "Error while resolving keytab filename " << + keytab_filename << " : " << error_message(code)); + return (1); + } + + if (!pn) { + code = krb5_kt_start_seq_get(kparam.context, keytab, &cursor); + if (code) { + debugs(11, 5, + HERE << "Error while starting keytab scan : " << + error_message(code)); + return (1); + } + code = + krb5_kt_next_entry(kparam.context, keytab, &entry, &cursor); + krb5_copy_principal(kparam.context, entry.principal, + &principal); + if (code && code != KRB5_KT_END) { + debugs(11, 5, + HERE << "Error while scanning keytab : " << + error_message(code)); + return (1); + } + + code = krb5_kt_end_seq_get(kparam.context, keytab, &cursor); + if (code) { + debugs(11, 5, + HERE << "Error while ending keytab scan : " << + error_message(code)); + return (1); + } +#if HAVE_HEIMDAL_KERBEROS || ( HAVE_KRB5_KT_FREE_ENTRY && HAVE_DECL_KRB5_KT_FREE_ENTRY) + code = krb5_kt_free_entry(kparam.context, &entry); +#else + code = krb5_free_keytab_entry_contents(kparam.context, &entry); +#endif + if (code) { + debugs(11, 5, + HERE << "Error while freeing keytab entry : " << + error_message(code)); + return (1); + } + + } else { + principal_name = xstrdup(pn); + } + + if (!principal) { + code = + krb5_parse_name(kparam.context, principal_name, &principal); + if (code) { + debugs(11, 5, + HERE << "Error while parsing principal name " << + principal_name << " : " << error_message(code)); + return (1); + } + } + + creds = (krb5_creds *) xmalloc(sizeof(*creds)); + memset(creds, 0, sizeof(*creds)); + krb5_get_init_creds_opt_init(&options); + code = krb5_string_to_deltat((char *) MAX_RENEW_TIME, &rlife); + if (code != 0 || rlife == 0) { + debugs(11, 5, + HERE << "Error bad lifetime value " << MAX_RENEW_TIME << + " : " << error_message(code)); + return (1); + } + krb5_get_init_creds_opt_set_renew_life(&options, rlife); + + code = + krb5_get_init_creds_keytab(kparam.context, creds, principal, + keytab, 0, NULL, &options); + if (code) { + debugs(11, 5, + HERE << + "Error while initializing credentials from keytab : " << + error_message(code)); + return (1); + } +#if !HAVE_KRB5_MEMORY_CACHE + mem_cache = + (char *) xmalloc(strlen("FILE:/tmp/peer_proxy_negotiate_auth_") + + 16); + snprintf(mem_cache, + strlen("FILE:/tmp/peer_proxy_negotiate_auth_") + 16, + "FILE:/tmp/peer_proxy_negotiate_auth_%d", (int) getpid()); +#else + mem_cache = + (char *) xmalloc(strlen("MEMORY:peer_proxy_negotiate_auth_") + + 16); + snprintf(mem_cache, + strlen("MEMORY:peer_proxy_negotiate_auth_") + 16, + "MEMORY:peer_proxy_negotiate_auth_%d", (int) getpid()); +#endif + + setenv("KRB5CCNAME", mem_cache, 1); + code = krb5_cc_resolve(kparam.context, mem_cache, &kparam.cc); + if (mem_cache) + xfree(mem_cache); + if (code) { + debugs(11, 5, + HERE << "Error while resolving memory credential cache : " + << error_message(code)); + return (1); + } + code = krb5_cc_initialize(kparam.context, kparam.cc, principal); + if (code) { + debugs(11, 5, + HERE << + "Error while initializing memory credential cache : " << + error_message(code)); + return (1); + } + code = krb5_cc_store_cred(kparam.context, kparam.cc, creds); + if (code) { + debugs(11, 5, + HERE << "Error while storing credentials : " << + error_message(code)); + return (1); + } + + if (!creds->times.starttime) + creds->times.starttime = creds->times.authtime; + } + return (0); + } + +/* + * peer_proxy_negotiate_auth gets a GSSAPI token for principal_name + * and base64 encodes it. + */ + char *peer_proxy_negotiate_auth(char *principal_name, char *proxy) + { + int rc = 0; + OM_uint32 major_status, minor_status; + gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT; + gss_name_t server_name = GSS_C_NO_NAME; + gss_buffer_desc service = GSS_C_EMPTY_BUFFER; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + char *token = NULL; + + setbuf(stdout, NULL); + setbuf(stdin, NULL); + + if (!proxy) { + debugs(11, 5, HERE << "Error : No proxy server name"); + return NULL; + } + + if (principal_name) + debugs(11, 5, + HERE << "Creating credential cache for " << principal_name); + else + debugs(11, 5, HERE << "Creating credential cache"); + rc = krb5_create_cache(NULL, principal_name); + if (rc) { + debugs(11, 5, HERE << "Error : Failed to create Kerberos cache"); + krb5_cleanup(); + return NULL; + } + + service.value = (void *) xmalloc(strlen("HTTP") + strlen(proxy) + 2); + snprintf((char *) service.value, strlen("HTTP") + strlen(proxy) + 2, + "%s@%s", "HTTP", proxy); + service.length = strlen((char *) service.value); + + debugs(11, 5, HERE << "Import gss name"); + major_status = gss_import_name(&minor_status, &service, + gss_nt_service_name, &server_name); + + if (check_gss_err(major_status, minor_status, "gss_import_name()")) + goto cleanup; + + debugs(11, 5, HERE << "Initialize gss security context"); + major_status = gss_init_sec_context(&minor_status, + GSS_C_NO_CREDENTIAL, + &gss_context, + server_name, + gss_mech_spnego, + 0, + 0, + GSS_C_NO_CHANNEL_BINDINGS, + &input_token, NULL, &output_token, NULL, NULL); + + if (check_gss_err(major_status, minor_status, "gss_init_sec_context()")) + goto cleanup; + + debugs(11, 5, HERE << "Got token with length " << output_token.length); + if (output_token.length) { + + token = + (char *) base64_encode_bin((const char *) output_token.value, + output_token.length); + } + + + cleanup: + gss_delete_sec_context(&minor_status, &gss_context, NULL); + gss_release_buffer(&minor_status, &service); + gss_release_buffer(&minor_status, &input_token); + gss_release_buffer(&minor_status, &output_token); + gss_release_name(&minor_status, &server_name); + + return token; + } + +#ifdef __cplusplus +} +#endif +#endif /* HAVE_KRB5 && HAVE_GSSAPI */ diff --git a/src/protos.h b/src/protos.h index 459820d3bc..46f5ba3739 100644 --- a/src/protos.h +++ b/src/protos.h @@ -106,8 +106,6 @@ SQUIDCEXTERN void _db_set_syslog(const char *facility); SQUIDCEXTERN void _db_init(const char *logfile, const char *options); SQUIDCEXTERN void _db_rotate_log(void); -SQUIDCEXTERN void _db_print(const char *,...) PRINTF_FORMAT_ARG1; - /* packs, then prints an object using debugs() */ SQUIDCEXTERN void debugObj(int section, int level, const char *label, void *obj, ObjPackMethod pm); @@ -797,4 +795,8 @@ class external_acl; #endif +#if HAVE_KRB5 && HAVE_GSSAPI + /* upstream proxy authentication */ + SQUIDCEXTERN char *peer_proxy_negotiate_auth(char *principal_name, char *proxy); +#endif #endif /* SQUID_PROTOS_H */ diff --git a/src/tunnel.cc b/src/tunnel.cc index a6bab679f4..8d74df00b9 100644 --- a/src/tunnel.cc +++ b/src/tunnel.cc @@ -745,6 +745,7 @@ tunnelPeerSelectComplete(FwdServer * fs, void *data) tunnelState->servers = fs; tunnelState->host = fs->_peer ? fs->_peer->host : xstrdup(request->GetHost()); + request->peer_host = fs->_peer ? fs->_peer->host : NULL; if (fs->_peer == NULL) { tunnelState->port = request->port; diff --git a/test-builds.sh b/test-builds.sh index 68f2b2b3ab..8aaf47b476 100755 --- a/test-builds.sh +++ b/test-builds.sh @@ -90,7 +90,7 @@ buildtest() { echo "Build OK. Global result is $globalResult." fi else - if test "${verbose}" = "yes" ; then + if test "${verbose}" != "yes" ; then echo "Build Failed. Last log lines are:" tail -20 ${log} else diff --git a/test-suite/buildtests/layer-01-minimal.opts b/test-suite/buildtests/layer-01-minimal.opts index 07ab7b0b1c..076ae0666f 100644 --- a/test-suite/buildtests/layer-01-minimal.opts +++ b/test-suite/buildtests/layer-01-minimal.opts @@ -76,6 +76,7 @@ OPTS=" \ --disable-digest-auth-helpers \ --disable-ntlm-fail-open \ --disable-external-acl-helpers \ + --disable-url-rewrite-helpers \ --disable-mempools \ --disable-win32-service \ --disable-unlinkd \ diff --git a/test-suite/buildtests/layer-02-maximus.opts b/test-suite/buildtests/layer-02-maximus.opts index e85113e0bd..3653230c95 100644 --- a/test-suite/buildtests/layer-02-maximus.opts +++ b/test-suite/buildtests/layer-02-maximus.opts @@ -86,6 +86,7 @@ OPTS=" \ --enable-digest-auth-helpers=all \ --enable-ntlm-fail-open \ --enable-external-acl-helpers=all \ + --enable-url-rewrite-helpers=all \ --enable-mempools \ --enable-unlinkd \ --enable-stacktraces \ diff --git a/tools/cachemgr.cc b/tools/cachemgr.cc index d36e9935c7..c868acf1cb 100644 --- a/tools/cachemgr.cc +++ b/tools/cachemgr.cc @@ -146,17 +146,6 @@ typedef struct { char *pub_auth; } cachemgr_request; -/* - * Debugging macros (info goes to error_log on your web server) - * Note: do not run cache manager with non zero debugging level - * if you do not debug, it may write a lot of [sensitive] - * information to your error log. - */ - -/* debugging level 0 (disabled) - 3 (max) */ -#define DEBUG_LEVEL 0 -#define debug(level) if ((level) <= DEBUG_LEVEL && DEBUG_LEVEL > 0) - /* * Static variables and constants */ @@ -871,9 +860,9 @@ process_request(cachemgr_request * req) req->action, make_auth_header(req)); if (write(s, buf, l) < 0) { - debug(1) fprintf(stderr, "ERROR: (%d) writing request: '%s'\n", errno, buf); + fprintf(stderr,"ERROR: (%d) writing request: '%s'\n", errno, buf); } else { - debug(1) fprintf(stderr, "wrote request: '%s'\n", buf); + debug("wrote request: '%s'\n", buf); } return read_reply(s, req); } @@ -906,6 +895,31 @@ main(int argc, char *argv[]) if ((s = getenv("SCRIPT_NAME")) != NULL) script_name = xstrdup(s); + char **args = argv; + while (argc > 1 && args[1][0] == '-') { +// const char *value = ""; + char option = args[1][1]; + switch (option) { + case 'd': + debug_enabled = 1; + break; + default: +#if 0 // unused for now. + if (strlen(args[1]) > 2) { + value = args[1] + 2; + } else if (argc > 2) { + value = args[2]; + args++; + argc--; + } else + value = ""; +#endif + break; + } + args++; + argc--; + } + req = read_request(); return process_request(req); @@ -1019,7 +1033,7 @@ read_request(void) } make_pub_auth(req); - debug(1) fprintf(stderr, "cmgr: got req: host: '%s' port: %d uname: '%s' passwd: '%s' auth: '%s' oper: '%s'\n", + debug("cmgr: got req: host: '%s' port: %d uname: '%s' passwd: '%s' auth: '%s' oper: '%s'\n", safe_str(req->hostname), req->port, safe_str(req->user_name), safe_str(req->passwd), safe_str(req->pub_auth), safe_str(req->action)); return req; } @@ -1036,7 +1050,7 @@ make_pub_auth(cachemgr_request * req) { static char buf[1024]; safe_free(req->pub_auth); - debug(3) fprintf(stderr, "cmgr: encoding for pub...\n"); + debug("cmgr: encoding for pub...\n"); if (!req->passwd || !strlen(req->passwd)) return; @@ -1048,9 +1062,8 @@ make_pub_auth(cachemgr_request * req) req->user_name ? req->user_name : "", req->passwd); - debug(3) fprintf(stderr, "cmgr: pre-encoded for pub: %s\n", buf); - - debug(3) fprintf(stderr, "cmgr: encoded: '%s'\n", base64_encode(buf)); + debug("cmgr: pre-encoded for pub: %s\n", buf); + debug("cmgr: encoded: '%s'\n", base64_encode(buf)); req->pub_auth = xstrdup(base64_encode(buf)); } @@ -1064,7 +1077,7 @@ decode_pub_auth(cachemgr_request * req) const char *user_name; const char *passwd; - debug(2) fprintf(stderr, "cmgr: decoding pub: '%s'\n", safe_str(req->pub_auth)); + debug("cmgr: decoding pub: '%s'\n", safe_str(req->pub_auth)); safe_free(req->passwd); if (!req->pub_auth || strlen(req->pub_auth) < 4 + strlen(safe_str(req->hostname))) @@ -1072,28 +1085,28 @@ decode_pub_auth(cachemgr_request * req) buf = xstrdup(base64_decode(req->pub_auth)); - debug(3) fprintf(stderr, "cmgr: length ok\n"); + debug("cmgr: length ok\n"); /* parse ( a lot of memory leaks, but that is cachemgr style :) */ if ((host_name = strtok(buf, "|")) == NULL) return; - debug(3) fprintf(stderr, "cmgr: decoded host: '%s'\n", host_name); + debug("cmgr: decoded host: '%s'\n", host_name); if ((time_str = strtok(NULL, "|")) == NULL) return; - debug(3) fprintf(stderr, "cmgr: decoded time: '%s' (now: %d)\n", time_str, (int) now); + debug("cmgr: decoded time: '%s' (now: %d)\n", time_str, (int) now); if ((user_name = strtok(NULL, "|")) == NULL) return; - debug(3) fprintf(stderr, "cmgr: decoded uname: '%s'\n", user_name); + debug("cmgr: decoded uname: '%s'\n", user_name); if ((passwd = strtok(NULL, "|")) == NULL) return; - debug(2) fprintf(stderr, "cmgr: decoded passwd: '%s'\n", passwd); + debug("cmgr: decoded passwd: '%s'\n", passwd); /* verify freshness and validity */ if (atoi(time_str) + passwd_ttl < now) @@ -1102,7 +1115,7 @@ decode_pub_auth(cachemgr_request * req) if (strcasecmp(host_name, req->hostname)) return; - debug(1) fprintf(stderr, "cmgr: verified auth. info.\n"); + debug("cmgr: verified auth. info.\n"); /* ok, accept */ xfree(req->user_name); diff --git a/tools/squidclient.cc b/tools/squidclient.cc index 999648cecd..547dfe093d 100644 --- a/tools/squidclient.cc +++ b/tools/squidclient.cc @@ -436,16 +436,16 @@ main(int argc, char *argv[]) /* HTTP/1.0 may need keep-alive */ if (strcmp(version, "1.0") == 0) { if (keep_alive) { - if (strchr(url, ':')) + if (strchr(url, ':')) { snprintf(buf, BUFSIZ, "Proxy-Connection: keep-alive\r\n"); - else + strcat(msg, buf); + } else strcat(msg, "Connection: keep-alive\r\n"); } } else { if (!keep_alive) strcat(msg, "Connection: close\r\n"); } - strcat(msg, buf); strcat(msg, extra_hdrs); strcat(msg, "\r\n");