]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Merged from trunk
authorAmos Jeffries <squid3@treenet.co.nz>
Fri, 27 Aug 2010 09:33:34 +0000 (21:33 +1200)
committerAmos Jeffries <squid3@treenet.co.nz>
Fri, 27 Aug 2010 09:33:34 +0000 (21:33 +1200)
162 files changed:
CREDITS
ChangeLog
acinclude/compiler-flags.m4
acinclude/krb5.m4
compat/Makefile.am
compat/compat.h
compat/os/solaris.h
compat/types.h
configure.in
contrib/solaris/solaris-krb5-include.patch [new file with mode: 0644]
doc/manuals/es.po
doc/manuals/ru.po
doc/release-notes/release-3.1.sgml
doc/release-notes/release-3.2.sgml
errors/Makefile.am
errors/aliases
errors/en.po
errors/es.po
errors/hy.po
errors/ru.po
helpers/external_acl/Makefile.am
helpers/external_acl/eDirectory_userip/Makefile [deleted file]
helpers/external_acl/eDirectory_userip/Makefile.am [new file with mode: 0644]
helpers/external_acl/eDirectory_userip/config.test [new file with mode: 0755]
helpers/external_acl/eDirectory_userip/edui_config.h [moved from helpers/external_acl/eDirectory_userip/config.h with 97% similarity]
helpers/external_acl/eDirectory_userip/edui_util.c [moved from helpers/external_acl/eDirectory_userip/util.c with 99% similarity]
helpers/external_acl/eDirectory_userip/edui_util.h [moved from helpers/external_acl/eDirectory_userip/util.h with 100% similarity]
helpers/external_acl/eDirectory_userip/iplookup.c
helpers/external_acl/eDirectory_userip/main.c
helpers/external_acl/eDirectory_userip/main.h
helpers/external_acl/kerberos_ldap_group/Makefile.am [new file with mode: 0644]
helpers/external_acl/kerberos_ldap_group/README [new file with mode: 0644]
helpers/external_acl/kerberos_ldap_group/cert_tool [new file with mode: 0644]
helpers/external_acl/kerberos_ldap_group/config.test [new file with mode: 0644]
helpers/external_acl/kerberos_ldap_group/ext_kerberos_ldap_group_acl.8 [new file with mode: 0644]
helpers/external_acl/kerberos_ldap_group/kerberos_ldap_group.cc [new file with mode: 0644]
helpers/external_acl/kerberos_ldap_group/support.h [new file with mode: 0644]
helpers/external_acl/kerberos_ldap_group/support_group.cc [new file with mode: 0644]
helpers/external_acl/kerberos_ldap_group/support_krb5.cc [new file with mode: 0644]
helpers/external_acl/kerberos_ldap_group/support_ldap.cc [new file with mode: 0644]
helpers/external_acl/kerberos_ldap_group/support_log.cc [new file with mode: 0644]
helpers/external_acl/kerberos_ldap_group/support_member.cc [new file with mode: 0644]
helpers/external_acl/kerberos_ldap_group/support_netbios.cc [new file with mode: 0644]
helpers/external_acl/kerberos_ldap_group/support_resolv.cc [new file with mode: 0644]
helpers/external_acl/kerberos_ldap_group/support_sasl.cc [new file with mode: 0644]
helpers/negotiate_auth/kerberos/Makefile.am
helpers/negotiate_auth/kerberos/base64.cc
helpers/negotiate_auth/kerberos/config.test
helpers/negotiate_auth/kerberos/negotiate_kerberos_auth.8 [new file with mode: 0644]
helpers/negotiate_auth/kerberos/negotiate_kerberos_auth.cc
helpers/negotiate_auth/kerberos/negotiate_kerberos_auth_test.cc
helpers/ntlm_auth/fake/ntlm_fake_auth.cc
helpers/ntlm_auth/smb_lm/ntlm_smb_lm_auth.cc
include/psignal.h [new file with mode: 0644]
lib/Makefile.am
lib/libTrie/src/Trie.cc
lib/libTrie/src/TrieNode.cc
lib/psignal.c [new file with mode: 0644]
lib/rfc1035.c
src/BodyPipe.cc
src/BodyPipe.h
src/CacheManager.h
src/CommCalls.h
src/Common.am
src/DiskIO/DiskThreads/aiops.cc
src/HttpHeader.cc
src/HttpHeader.h
src/HttpHeaderTools.cc
src/HttpMsg.cc
src/HttpMsg.h
src/HttpReply.cc
src/HttpRequest.cc
src/HttpVersion.h
src/Makefile.am
src/Server.cc
src/Server.h
src/adaptation/AccessCheck.cc
src/adaptation/Initiate.cc
src/adaptation/Initiate.h
src/adaptation/Initiator.cc
src/adaptation/Initiator.h
src/adaptation/Iterator.cc
src/adaptation/Iterator.h
src/adaptation/Makefile.am
src/adaptation/Service.h
src/adaptation/ecap/ServiceRep.cc
src/adaptation/ecap/ServiceRep.h
src/adaptation/ecap/XactionRep.cc
src/adaptation/ecap/XactionRep.h
src/adaptation/icap/Launcher.cc
src/adaptation/icap/Launcher.h
src/adaptation/icap/ModXact.cc
src/adaptation/icap/ModXact.h
src/adaptation/icap/OptXact.cc
src/adaptation/icap/OptXact.h
src/adaptation/icap/ServiceRep.cc
src/adaptation/icap/ServiceRep.h
src/adaptation/icap/Xaction.cc
src/adaptation/icap/Xaction.h
src/auth/Makefile.am
src/base/AsyncJob.cc
src/base/AsyncJob.h
src/base/AsyncJobCalls.h
src/base/AsyncJobs.dox
src/base/CbcPointer.h [new file with mode: 0644]
src/base/Makefile.am
src/cache_cf.cc
src/cache_manager.cc
src/cf.data.pre
src/client_side.cc
src/client_side.h
src/client_side_reply.cc
src/client_side_request.cc
src/client_side_request.h
src/comm.cc
src/disk.cc
src/dns_internal.cc
src/esi/Include.cc
src/esi/Include.h
src/fs/Makefile.am
src/ftp.cc
src/http.cc
src/icmp/net_db.h
src/ipc/Port.cc
src/ipc/UdsOp.cc
src/ipcache.cc
src/main.cc
src/mem.cc
src/neighbors.cc
src/protos.h
src/repl/Makefile.am
src/structs.h
src/tests/stub_HttpReply.cc
src/tests/stub_main_cc.cc [new file with mode: 0644]
src/tests/testCacheManager.cc
src/tests/testEvent.cc
src/tests/testEventLoop.cc
src/tests/testHttpRequest.cc
src/tests/testURL.cc
src/tests/test_http_range.cc
src/tunnel.cc
test-suite/testheaders.sh
tools/Makefile.am
tools/purge/Makefile [deleted file]
tools/purge/Makefile.am [new file with mode: 0644]
tools/purge/README
tools/purge/conffile.cc
tools/purge/conffile.hh
tools/purge/convert.cc
tools/purge/convert.hh
tools/purge/copyout.cc
tools/purge/copyout.hh
tools/purge/hexd.c [deleted file]
tools/purge/purge.cc
tools/purge/signal.cc
tools/purge/signal.hh
tools/purge/socket.cc
tools/purge/socket.hh
tools/purge/squid-tlv.cc
tools/purge/squid-tlv.hh
tools/squidclient.1
tools/squidclient.cc

diff --git a/CREDITS b/CREDITS
index df3b54ba1cb23f342309f956bb81b5383e5db0d2..617e47a13337a3509c6c8da6af818ca5cf6ff979 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -486,3 +486,19 @@ compat/strsep.h, lib/strsep.c
 
 ==============================================================================
 
+helpers/external_acl/kerberos_ldap_group/support_ldap.cc
+
+/* get_attributes is partly from OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2009 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+
index 2ec07a5bb9be65ae9b497358422d8dfebdd384eb..675ca09e161b7d1a157ee0ed06bca03401401b72 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -44,6 +44,23 @@ Changes to squid-3.2.0.1 (03 Aug 2010):
        - ... and a great many testing improvements
        - ... and many documentation updates
 
+Changes to squid-3.1.7 (23 Aug 2010):
+
+       - Regression Bug 3021: Large DNS reply causes crash
+       - Regression Bug 3011: ICAP, HTTPS, cache_peer probe IPv4-only port fixes
+       - Regression Bug 2997: visible_hostname directive no longer matches docs
+       - Bug 3012: deprecate sslBump and support ssl-bump spelling in http_port
+       - Bug 3006: handle IPV6_V6ONLY definition missing
+       - Bug 3004: Solaris 9 SunStudio 12 build failure
+       - Bug 3003: inconsistent concepts in documentation of cache_dir
+       - Bug 3001: dnsserver link issues
+       - HTTP/1.1: default keep-alive for 1.1 clients (bug 3016)
+       - HTTP/1.1: Improved Range header field validation
+       - HTTP/1.1: Forward multiple unknown Cache-Control directives
+       - HTTP/1.1: Stop sending Proxy-Connection header
+       - Fix 32-bit wrap in refresh_pattern min/max values
+       - ... and several documentation corrections.
+
 Changes to squid-3.1.6 (02 Aug 2010):
 
        - Bug 2994, 2995: IPv4-only regressions
index 6f806169ea1c246caba8667633180ef7a5e8a770..65221c7e4b78496552097e85f1b3f8a98ff6a09f 100644 (file)
@@ -100,6 +100,7 @@ AC_DEFUN([SQUID_CC_GUESS_VARIANT], [
 # options
 # They are (with their GCC equivalent):
 # squid_cv_cc_option_werror   (-Werror)
+# squid_cv_cxx_option_werror  (-Werror)
 # squid_cv_cc_option_wall     (-Wall)
 # squid_cv_cc_option_optimize (-O3)
 # 
@@ -109,17 +110,20 @@ AC_DEFUN([SQUID_CC_GUESS_OPTIONS], [
  case "$squid_cv_compiler" in
   gcc) 
    squid_cv_cc_option_werror="-Werror" 
+   squid_cv_cxx_option_werror="-Werror" 
    squid_cv_cc_option_wall="-Wall"
    squid_cv_cc_option_optimize="-O3"
    squid_cv_cc_arg_pipe="-pipe"
    ;;
   sunstudio) 
-   squid_cv_cc_option_werror="-errwarn=%all" 
+   squid_cv_cc_option_werror="-errwarn=%all -errtags" 
+   squid_cv_cxx_option_werror="-errwarn=%all,no%badargtype2w,no%wbadinit,no%wbadasg -errtags" 
    squid_cv_cc_option_wall="+w"
    squid_cv_cc_option_optimize="-fast"
    squid_cv_cc_arg_pipe=""
    ;;
   *) 
+   squid_cv_cxx_option_werror="" 
    squid_cv_cc_option_werror="" 
    squid_cv_cc_option_wall=""
    squid_cv_cc_option_optimize="-O"
index 77c8475ed04eef1836ece52ef0cbeaccfd5bed52..38e225c23b3c57957a7d4b95734bde8d89dbaf04 100644 (file)
@@ -104,23 +104,25 @@ dnl checks that gssapi is ok, and sets squid_cv_working_gssapi accordingly
 AC_DEFUN([SQUID_CHECK_WORKING_GSSAPI], [
   AC_CACHE_CHECK([for working gssapi], squid_cv_working_gssapi, [
     AC_RUN_IFELSE([AC_LANG_SOURCE([[
+#ifdef HAVE_HEIMDAL_KERBEROS
 #ifdef HAVE_GSSAPI_GSSAPI_H
 #include <gssapi/gssapi.h>
-#elif HAVE_GSSAPI_H
+#elif defined(HAVE_GSSAPI_H)
 #include <gssapi.h>
 #endif
-
-#ifdef HAVE_GSSAPI_GSSAPI_EXT_H
-#include <gssapi/gssapi_ext.h>
+#else
+#ifdef HAVE_GSSAPI_GSSAPI_H
+#include <gssapi/gssapi.h>
+#elif defined(HAVE_GSSAPI_H)
+#include <gssapi.h>
 #endif
-
 #ifdef HAVE_GSSAPI_GSSAPI_KRB5_H
 #include <gssapi/gssapi_krb5.h>
 #endif
-
 #ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H
 #include <gssapi/gssapi_generic.h>
 #endif
+#endif
 int
 main(void)
 {
index 1761ef3934646da43164d392aaaa03c4e8127525..55493e2369d230805f24c83dbe3495d877077270 100644 (file)
@@ -72,8 +72,7 @@ TESTS += testHeaders
 ## Special Universal .h dependency test script
 ## aborts if error encountered
 testHeaders: $(srcdir)/*.h $(srcdir)/os/*.h
-       $(SHELL) $(top_srcdir)/test-suite/testheaders.sh "$(CXXCOMPILE)" "$(srcdir)" || exit 1
-       $(SHELL) $(top_srcdir)/test-suite/testheaders.sh "$(CXXCOMPILE)" "$(srcdir)/os" || exit 1
+       $(SHELL) $(top_srcdir)/test-suite/testheaders.sh "$(CXXCOMPILE)" $^ || exit 1
 
 CLEANFILES += testHeaders
 
index 0830219dfb55464924c90c093d63695557c2b509..e0bc1db9b1ae1f5f8801dace6378eeabe4cd71df 100644 (file)
 #include "compat/osdetect.h"
 
 /* ugly hack. But we need to set this REALLY soon in the header */
-#if _SQUID_SOLARIS_
+#if _SQUID_SOLARIS_ && !defined(__GNUC__) && !defined(__GNUG__)
+#ifndef __EXTENSIONS__
+#define __EXTENSIONS__ 1
+#endif
 #ifndef _XOPEN_SOURCE
 #define _XOPEN_SOURCE 1
 #endif
index 0e4e26b064ffbdfbb8f6625e78317e3918e03732..0a718d3bbe2b35cde56cb470d2042d9c3349dbcf 100644 (file)
 #endif /* wcsstr */
 #define wcsstr wcswcs
 
-/*
- * we need some standard-based extensions
- */
-#ifndef _XOPEN_SOURCE
-#define _XOPEN_SOURCE 1
-#endif
-#ifndef _XOPEN_SOURCE_EXTENDED
-#define _XOPEN_SOURCE_EXTENDED 1
-#endif
-
-
 /*
  * On Solaris 9 x86, gcc may includes a "fixed" set of old system
  * include files that is incompatible with the updated Solaris
index d9de081111dfd22042c4d99dbf971eed2f323017..565328dc9c99516b1c72bd1a1fb1cb1192f90a0f 100644 (file)
 #endif
 #endif
 
+#ifndef PRIX64
+#ifdef _SQUID_MSWIN_           /* Windows native port using MSVCRT */
+#define PRIX64 "I64X"
+#elif SIZEOF_INT64_T > SIZEOF_LONG
+#define PRIX64 "llX"
+#else
+#define PRIX64 "lX"
+#endif
+#endif
+
 #ifndef HAVE_MODE_T
 typedef unsigned short mode_t;
 #endif
index d78f9759565db2b6d2d50dbee9fc582a8162328d..81ef1b73e647ae1c87e3ba49e877763e81bc79e6 100644 (file)
@@ -75,7 +75,9 @@ AC_SUBST(AR_R)
 
 # this needs to be before any test is run, to have more standard
 # functions available on some Unix sysems (e.g. Solaris)
-AC_USE_SYSTEM_EXTENSIONS
+if test "x$squid_host_os" = "solaris" -a "x$GCC" != "x" ; then
+       AC_USE_SYSTEM_EXTENSIONS
+fi
 
 AC_ARG_ENABLE(strict-error-checking,
   AS_HELP_STRING([--disable-strict-error-checking],[By default squid is compiled
@@ -192,7 +194,7 @@ esac
 )
 AC_SUBST(DEFAULT_LOG_DIR)
 
-DEFAULT_PIDFILE="$localstatedir/run/squid.pid"
+DEFAULT_PID_FILE="$localstatedir/run/squid.pid"
 AC_ARG_WITH(pidfile,
   AS_HELP_STRING([--with-pidfile=PATH],
     [Default location for squid pid file. Default: PREFIX/var/run/squid.pid]), [
@@ -201,11 +203,11 @@ case $withval in
    AC_MSG_ERROR( --with-pidfile requires a file PATH. --with-pidfile=PATH )
    ;;
  *)
-   DEFAULT_PIDFILE="$withval"
+   DEFAULT_PID_FILE="$withval"
    ;;
  esac
 ])
-AC_SUBST(DEFAULT_PIDFILE)
+AC_SUBST(DEFAULT_PID_FILE)
 
 if test "x$GCC" = "xyes"; then
   GCCVER=`$CC -v 2>&1 | awk '$2 ==  "version" {print $3}'`
@@ -279,7 +281,7 @@ fi
 
 if test "x$enable_strict_error_checking" != "xno"; then
   SQUID_CFLAGS="$SQUID_CFLAGS $squid_cv_cc_option_werror"
-  SQUID_CXXFLAGS="$SQUID_CXXFLAGS $squid_cv_cc_option_werror"
+  SQUID_CXXFLAGS="$SQUID_CXXFLAGS $squid_cv_cxx_option_werror"
 fi
 
 AC_SUBST(SQUID_CFLAGS)
@@ -293,7 +295,6 @@ fi
 SQUID_CXXFLAGS="$SQUID_CXXFLAGS $squid_cv_cc_arg_pipe"
 SQUID_CFLAGS="$SQUID_CFLAGS $squid_cv_cc_arg_pipe"
 
-enable_inline="yes"
 AC_ARG_ENABLE(optimizations,
   AS_HELP_STRING([--disable-optimizations],
                  [Do not compile Squid with compiler optimizations enabled.
@@ -325,7 +326,7 @@ AC_ARG_ENABLE(inline,
 SQUID_YESNO([$enableval],
   [Unrecognized argument to --disable-inline: $enableval])
 ])
-AC_MSG_NOTICE([inlining optimizations enabled: $enable_inline])
+AC_MSG_NOTICE([inlining optimizations enabled: ${enable_inline:=yes}])
 SQUID_DEFINE_BOOL(_USE_INLINE_,$enable_inline,
   [Include inline methods into header file])
 # to be used by sub-commands
@@ -1341,7 +1342,7 @@ else
   CXXFLAGS="`getconf ${buildmodel}_CFLAGS` $CXXFLAGS"
   LIBS="`getconf ${buildmodel}_LIBS` $LIBS"
   LDFLAGS="`getconf ${buildmodel}_LDFLAGS` $LDFLAGS"
-  if "$squid_host_os" = "solaris" ; then
+  if test "x$squid_host_os" = "xsolaris" ; then
 
 # On Solaris getconf returns for CFLAGS -xarch=generic64, -Xa and -Usun options, and
 # for LDFLAGS -xarch=generic64, but:
@@ -1418,20 +1419,19 @@ dnl Select Default hosts file location
 AC_ARG_ENABLE(default-hostsfile,
   AS_HELP_STRING([--enable-default-hostsfile=path],
                  [Select default location for hosts file.
-                  See hosts_file directive in squid.conf for details]),
-[
-  if test "x$enableval" != "xnone" -a "x$enableval" != "xno" ; then
-    if test -f "$enableval"; then
-      OPT_DEFAULT_HOSTS=$enableval
-    else
-      AC_MSG_WARN([Unable to find $enableval])
-    fi
-  else
-    OPT_DEFAULT_HOSTS="none"
+                  See hosts_file directive in squid.conf for details]), [
+if test "x$enableval" != "xnone" -a "x$enableval" != "xno" ; then
+  if test \! -f "$enableval"; then
+    AC_MSG_WARN([Unable to find file $enableval. I hope you know what you are doing.])
   fi
-  AC_MSG_NOTICE([Default hosts file set to: $enableval])
-],[OPT_DEFAULT_HOSTS="/etc/hosts"])
-AC_SUBST(OPT_DEFAULT_HOSTS)
+  squid_opt_default_hosts=$enableval
+else
+  squid_opt_default_hosts="none"
+fi
+])
+AC_MSG_NOTICE([Default hosts file set to: ${squid_opt_default_hosts:=/etc/hosts}])
+DEFAULT_HOSTS=$squid_opt_default_hosts
+AC_SUBST(DEFAULT_HOSTS)
 
 # Select auth schemes modules to build
 AC_ARG_ENABLE(auth,
@@ -1719,12 +1719,16 @@ if test "x$ac_krb5_config" = "xyes" ; then
     AC_CHECK_HEADERS(gssapi/gssapi_generic.h)
     AC_CHECK_HEADERS(profile.h)
   fi
-  AC_CHECK_HEADERS(krb5.h com_err.h et/com_err.h)
 
   SQUID_CHECK_KRB5_SOLARIS_BROKEN_KRB5_H
   if test "x$squid_cv_broken_krb5_h" = "xyes"; then
-     AC_DEFINE(HAVE_BROKEN_SOLARIS_KRB5_H, 1, [Define to 1 if krb5.h is broken for C++])
+    AC_DEFINE(HAVE_BROKEN_SOLARIS_KRB5_H, 1, [Define to 1 if krb5.h is broken for C++])
+    AC_MSG_WARN([You have a broken Solaris <krb5.h> system include.])
+    AC_MSG_WARN([Please see http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6837512])
+    AC_MSG_WARN([If you need Kerberos support you'll have to patch])
+    AC_MSG_WARN([your system. See contrib/solaris/solaris-krb5-include.patch])
   fi
+  AC_CHECK_HEADERS(krb5.h com_err.h et/com_err.h)
 
   ac_com_error_message=no
   if test "x$ac_cv_header_com_err_h" == "xyes" ; then
@@ -1753,6 +1757,7 @@ if test "x$ac_krb5_config" = "xyes" ; then
   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_DECLS(krb5_kt_free_entry,,,[#include <krb5.h>])
   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]),)
@@ -1828,6 +1833,10 @@ if test "x$enable_external_acl_helpers" != "xno" ; then
     dir="$srcdir/helpers/external_acl/$helper"
     if test -f "$dir/config.test" && sh "$dir/config.test" "$@"; then
       EXTERNAL_ACL_HELPERS="$EXTERNAL_ACL_HELPERS $helper"
+      # special case
+      if test "x$helper" = "xkerberos_ldap_group" ; then
+        squid_require_sasl=yes
+      fi
     else
       AC_MSG_NOTICE([external acl helper $helper ... found but cannot be built])
     fi
@@ -1922,6 +1931,16 @@ if test "x$squid_require_sasl" = "xyes"; then
       AC_MSG_ERROR(Neither SASL nor SASL2 found)
     ])
   ])
+  case "$host_os" in
+    Darwin)
+      if test "$ac_cv_lib_sasl2_sasl_errstring" = "yes" ; then
+        AC_DEFINE(HAVE_SASL_DARWIN,1,[Define to 1 if Mac Darwin without sasl.h])
+        echo "checking for MAC Darwin without sasl.h ... yes"
+      else
+        echo "checking for MAC Darwin without sasl.h ... no"
+      fi
+      ;;
+  esac
   AC_SUBST(LIBSASL)
 fi
 
@@ -2111,6 +2130,7 @@ AC_CHECK_HEADERS( \
   regex.h \
   sched.h \
   security/pam_appl.h \
+  siginfo.h \
   signal.h \
   sstream \
   stdarg.h \
@@ -2131,7 +2151,7 @@ AC_CHECK_HEADERS( \
   sys/md5.h \
   sys/msg.h \
   sys/resource.h \
-  sys/select.h\
+  sys/select.h \
   sys/socket.h \
   sys/stat.h \
   sys/statvfs.h \
@@ -2261,6 +2281,7 @@ AC_TYPE_SIZE_T
 AC_TYPE_SSIZE_T
 AC_TYPE_OFF_T
 AC_TYPE_UID_T
+AC_CHECK_TYPE([bool])
 #need the defines for PRId64
 AC_CHECK_SIZEOF(int64_t)
 AC_CHECK_SIZEOF(long)
@@ -2476,16 +2497,219 @@ esac
 dnl On MinGW OpenLDAP is not available, so LDAP helpers can be linked 
 dnl only with Windows LDAP libraries using -lwldap32
 case "$host_os" in
-mingw|mingw32)
-       LDAPLIB="-lwldap32"
-       LBERLIB=""
-       ;;
-*)
-       LDAPLIB="-lldap"
-       dnl LDAP helpers need to know if -llber is needed or not
-       AC_CHECK_LIB(lber, main, [LBERLIB="-llber"])
-       ;;
+       mingw|mingw32)
+               LDAPLIB="-lwldap32"
+               LBERLIB=""
+               ;;
+       *)
+               AC_CHECK_LIB(ldap, ldap_init, [LDAPLIB="-lldap"])
+               dnl LDAP helpers need to know if -llber is needed or not
+               AC_CHECK_LIB(lber, ber_init, [LBERLIB="-llber"])
+               dnl if no ldap lib found check for mozilla version
+               if test "x$ac_cv_lib_ldap_ldap_init" != x""yes; then
+                       oLIBS=$LIBS
+                       LIBS="$LIBPTHREADS"
+                       AC_CHECK_LIB(ldap60, ldap_init, [LDAPLIB="-lldap60"])
+                       LIBS="$LDAPLIB $LIBPTHREADS"
+                       AC_CHECK_LIB(prldap60, prldap_init, [LDAPLIB="-lprldap60 $LDAPLIB"])
+                       LIBS="$LDAPLIB $LIBPTHREADS"
+                       AC_CHECK_LIB(ssldap60, ldapssl_init, [LDAPLIB="-lssldap60 $LDAPLIB"])
+                       LIBS=$oLIBS
+               fi
+
+               AC_CHECK_HEADERS(ldap.h lber.h)
+               AC_CHECK_HEADERS(mozldap/ldap.h)
+
+               dnl
+               dnl Check for LDAP_OPT_DEBUG_LEVEL
+               dnl
+               AC_MSG_CHECKING([for LDAP_OPT_DEBUG_LEVEL])
+               AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#                   include <ldap.h>
+               ]],[[
+                    int i=LDAP_OPT_DEBUG_LEVEL
+               ]])],
+               [ AC_MSG_RESULT(yes) ],
+               [ AC_MSG_RESULT(no) ])
+
+               dnl
+               dnl Check for working ldap
+               dnl
+               oLIBS=$LIBS
+               LIBS="$LDAPLIB $LBERLIB $LIBPTHREADS"
+               AC_MSG_CHECKING([for working ldap])
+               AC_RUN_IFELSE([AC_LANG_SOURCE([[
+#                   define  LDAP_DEPRECATED 1
+#                   if HAVE_LDAP_H
+#                   include <ldap.h>
+#                   elif HAVE_MOZLDAP_LDAP_H
+#                   include <mozldap/ldap.h>
+#                   endif
+                    int
+                    main(void)
+                    {
+                        char host[]="";
+                        int port;
+
+                        ldap_init((const char *)&host, port);
+
+                        return 0;
+                    }
+               ]])], 
+               [ AC_DEFINE(HAVE_LDAP, 1, [LDAP support]) 
+                 AC_MSG_RESULT(yes) ],
+               [ AC_MSG_RESULT(no) ])
+               LIBS=$oLIBS
+
+               dnl
+               dnl Check for ldap vendor
+               dnl
+               AC_MSG_CHECKING([for OpenLDAP])
+               AC_RUN_IFELSE([AC_LANG_SOURCE([[
+#                   if HAVE_LDAP_H
+#                   include <ldap.h>
+#                   endif
+#                   include <string.h>
+                    int
+                    main(void)
+                    {
+                        return strcmp(LDAP_VENDOR_NAME,"OpenLDAP");
+                    }
+               ]])], 
+               [ AC_DEFINE(HAVE_OPENLDAP, 1, [OpenLDAP support]) 
+                 AC_MSG_RESULT(yes) ],
+               [ AC_MSG_RESULT(no) ])
+
+               AC_MSG_CHECKING([for Sun LDAP SDK])
+               AC_RUN_IFELSE([AC_LANG_SOURCE([[
+#                   if HAVE_LDAP_H
+#                   include <ldap.h>
+#                   endif
+#                   include <string.h>
+                    int
+                    main(void)
+                    {
+                        return strcmp(LDAP_VENDOR_NAME,"Sun Microsystems Inc.");
+                    }
+               ]])], 
+               [ AC_DEFINE(HAVE_SUN_LDAP_SDK, 1, [Sun LDAP SDK support])
+                 AC_MSG_RESULT(yes) ],
+               [ AC_MSG_RESULT(no) ])
+
+               AC_MSG_CHECKING([for Mozilla LDAP SDK])
+               AC_RUN_IFELSE([AC_LANG_SOURCE([[
+#                   if HAVE_LDAP_H
+#                   include <ldap.h>
+#                   elif HAVE_MOZLDAP_LDAP_H
+#                   include <mozldap/ldap.h>
+#                   endif
+#                   include <string.h>
+                    int
+                    main(void)
+                    {
+                        return strcmp(LDAP_VENDOR_NAME,"mozilla.org");
+                    }
+               ]])], 
+               [ AC_DEFINE(HAVE_MOZILLA_LDAP_SDK, 1, [Mozilla LDAP SDK support])
+                 AC_MSG_RESULT(yes) ],
+               [ AC_MSG_RESULT(no)])
+
+               dnl
+               dnl Check for LDAP_REBINDPROC_CALLBACK
+               dnl
+                AC_MSG_CHECKING([for LDAP_REBINDPROC_CALLBACK])
+                AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#                   if HAVE_LDAP_H
+#                   include <ldap.h>
+#                   elif HAVE_MOZLDAP_LDAP_H
+#                   include <mozldap/ldap.h>
+#                   endif
+                ]],[[
+                    LDAP_REBINDPROC_CALLBACK ldap_rebind;
+                ]])],
+                [ AC_DEFINE(HAVE_LDAP_REBINDPROC_CALLBACK,1,[Define to 1 if you have LDAP_REBINDPROC_CALLBACK])
+                  AC_MSG_RESULT(yes) ],
+                [ AC_MSG_RESULT(no) ])
+
+               dnl
+               dnl Check for LDAP_REBIND_PROC
+               dnl
+                AC_MSG_CHECKING([for LDAP_REBIND_PROC])
+                AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#                   if HAVE_LDAP_H
+#                   include <ldap.h>
+#                   elif HAVE_MOZLDAP_LDAP_H
+#                   include <mozldap/ldap.h>
+#                   endif
+                ]],[[
+                    LDAP_REBIND_PROC ldap_rebind;
+                ]])],
+                [ AC_DEFINE(HAVE_LDAP_REBIND_PROC,1,[Define to 1 if you have LDAP_REBIND_PROC])
+                  AC_MSG_RESULT(yes) ],
+                [ AC_MSG_RESULT(no) ])
+
+               dnl
+               dnl Check for LDAP_REBIND_FUNCTION
+               dnl
+                AC_MSG_CHECKING([for LDAP_REBIND_FUNCTION])
+                AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#                   define LDAP_REFERRALS
+#                   if HAVE_LDAP_H
+#                   include <ldap.h>
+#                   elif HAVE_MOZLDAP_LDAP_H
+#                   include <mozldap/ldap.h>
+#                   endif
+                ]],[[
+                    LDAP_REBIND_FUNCTION ldap_rebind;
+                ]])],
+                [ AC_DEFINE(HAVE_LDAP_REBIND_FUNCTION,1,[Define to 1 if you have LDAP_REBIND_FUNCTION])
+                  AC_MSG_RESULT(yes) ],
+                [ AC_MSG_RESULT(no) ])
+
+               dnl
+               dnl Check for LDAP_SCOPE_DEFAULT
+               dnl
+                AC_MSG_CHECKING([for LDAP_SCOPE_DEFAULT])
+                AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#                   if HAVE_LDAP_H
+#                   include <ldap.h>
+#                   elif HAVE_MOZLDAP_LDAP_H
+#                   include <mozldap/ldap.h>
+#                   endif
+                ]],[[
+                    int i=LDAP_SCOPE_DEFAULT;
+                ]])],
+                [ AC_DEFINE(HAVE_LDAP_SCOPE_DEFAULT,1,[Define to 1 if you have LDAP_SCOPE_DEFAULT])
+                  AC_MSG_RESULT(yes) ],
+                [ AC_MSG_RESULT(no) ])
+
+               dnl
+               dnl Check for ldap_url_desc.lud_scheme
+               dnl
+               AC_CHECK_MEMBER(struct ldap_url_desc.lud_scheme,
+                 AC_DEFINE(HAVE_LDAP_URL_LUD_SCHEME,1,
+                   [Define to 1 if you have LDAPURLDesc.lud_scheme]),,[#include <ldap.h>])
+
+               dnl
+               dnl Check for ldapssl_client_init
+               dnl
+               AC_CHECK_LIB(ldap,ldapssl_client_init,
+                 AC_DEFINE(HAVE_LDAPSSL_CLIENT_INIT,1,[Define to 1 if you have ldapssl_client_init]),)
+
+               dnl
+               dnl Check for ldap_url_desc2str
+               dnl
+               AC_CHECK_LIB(ldap,ldap_url_desc2str,
+                 AC_DEFINE(HAVE_LDAP_URL_DESC2STR,1,[Define to 1 if you have ldap_url_desc2str]),)
+
+               dnl
+               dnl Check for ldap_url_parse
+               dnl
+               AC_CHECK_LIB(ldap,ldap_url_parse,
+                 AC_DEFINE(HAVE_LDAP_URL_PARSE,1,[Define to 1 if you have ldap_url_parse]),)
+               ;;
 esac
+
 AC_SUBST(LDAPLIB)
 AC_SUBST(LBERLIB)
 
@@ -2700,6 +2924,7 @@ AC_REPLACE_FUNCS(\
        initgroups \
        getaddrinfo \
        getnameinfo \
+       psignal \
        strerror \
        strsep \
        strtoll \
@@ -3008,7 +3233,9 @@ AC_CONFIG_FILES([\
        helpers/negotiate_auth/SSPI/Makefile \
        helpers/external_acl/Makefile \
        helpers/external_acl/AD_group/Makefile \
+       helpers/external_acl/eDirectory_userip/Makefile \
        helpers/external_acl/file_userip/Makefile \
+       helpers/external_acl/kerberos_ldap_group/Makefile \
        helpers/external_acl/LDAP_group/Makefile \
        helpers/external_acl/LM_group/Makefile \
        helpers/external_acl/session/Makefile \
@@ -3019,6 +3246,7 @@ AC_CONFIG_FILES([\
        helpers/url_rewrite/Makefile \
        helpers/url_rewrite/fake/Makefile \
        tools/Makefile
+       tools/purge/Makefile
 ])
 
 AC_CONFIG_SUBDIRS(lib/libTrie)
diff --git a/contrib/solaris/solaris-krb5-include.patch b/contrib/solaris/solaris-krb5-include.patch
new file mode 100644 (file)
index 0000000..0421ec6
--- /dev/null
@@ -0,0 +1,19 @@
+--- /usr/include/kerberosv5/krb5.h.orig        Mon Aug 23 04:09:23 2010
++++ /usr/include/kerberosv5/krb5.h     Mon Aug 23 04:10:53 2010
+@@ -171,6 +171,7 @@
+ #define KRB5INT_END_DECLS
+ #endif
+ #endif
++KRB5INT_BEGIN_DECLS
+ #if TARGET_OS_MAC 
+ #    pragma options align=mac68k 
+@@ -3246,8 +3247,4 @@
+ /* for compatibility with older versions... */
+ #define asn1_err_base ERROR_TABLE_BASE_asn1
+-#ifdef __cplusplus
+-}
+-#endif
+-
+ #endif                /* _KRB5_H */
index 1f7427db5e219448ede2a7d3cb2870d56be7f4bd..563d07afb4159945f49dc25c333118bffb9d9304 100644 (file)
@@ -1077,13 +1077,9 @@ msgstr "Configuración de ejemplo usando el modo automático por defecto"
 #~ msgid "12 August 2002"
 #~ msgstr ""
 
-#. type: TH
-#. type: Plain text
-#: helpers/external_acl/unix_group/squid_unix_group.8:1
-#: helpers/external_acl/unix_group/squid_unix_group.8:7
 #, no-wrap
-msgid "Squid UNIX Group helper"
-msgstr "Módulo de grupo UNIX de Squid"
+#~ msgid "Squid UNIX Group helper"
+#~ msgstr "Módulo de grupo UNIX de Squid"
 
 #~ msgid "squid_unix_group - Squid UNIX Group external_acl helper"
 #~ msgstr ""
@@ -1350,14 +1346,12 @@ msgstr ""
 "no cumple estos criterios o si desea filtrar a los usuarios válidos "
 "necesita filtrar por los DN de usuario."
 
-#. type: Plain text
-#: helpers/external_acl/ldap_group/squid_ldap_group.8:87
-msgid ""
-"The DN and password to bind as while performing searches. Required if the "
-"directory does not allow anonymous searches."
-msgstr ""
-"El DN y clave para enlazar al directorio mientras se realizan las búsquedas. "
-"Requerido si el directorio no permite búsquedas anónimas."
+#~ msgid ""
+#~ "The DN and password to bind as while performing searches. Required if the "
+#~ "directory does not allow anonymous searches."
+#~ msgstr ""
+#~ "El DN y clave para enlazar al directorio mientras se realizan las búsquedas. "
+#~ "Requerido si el directorio no permite búsquedas anónimas."
 
 #. type: Plain text
 #: helpers/external_acl/ldap_group/squid_ldap_group.8:141
@@ -1838,14 +1832,12 @@ msgstr ""
 msgid "A simple HTTP web client tool"
 msgstr "Una herramienta web cliente HTTP sencilla"
 
-#. type: Plain text
-#: helpers/external_acl/unix_group/squid_unix_group.8:18
-msgid ""
-"B<squid_unix_group> allows Squid to base access controls on users "
-"memberships in UNIX groups."
-msgstr ""
-"B<squid_unix_group> permite a Squid realizar controles de acceso basado en "
-"la membresía de grupos UNIX de los usuarios"
+#~ msgid ""
+#~ "B<squid_unix_group> allows Squid to base access controls on users "
+#~ "memberships in UNIX groups."
+#~ msgstr ""
+#~ "B<squid_unix_group> permite a Squid realizar controles de acceso basado en "
+#~ "la membresía de grupos UNIX de los usuarios"
 
 #. type: Plain text
 #: helpers/basic_auth/RADIUS/basic_radius_auth.8:60
@@ -1896,21 +1888,19 @@ msgstr ""
 "El nombre de servicio es B<squid> , y el programa hace uso de B<auth> y "
 "B<account> para administración. Verifique la clave y la validez de la cuenta."
 
-#. type: Plain text
-#: helpers/external_acl/ldap_group/squid_ldap_group.8:33
-msgid ""
-"B<squid_ldap_group> allows Squid to connect to a LDAP directory to authorize "
-"users via LDAP groups.  LDAP options are specified as parameters on the "
-"command line, while the username(s) and group(s) to be checked against the "
-"LDAP directory are specified on subsequent lines of input to the helper, one "
-"username/group pair per line separated by a space."
-msgstr ""
-"B<squid_ldap_group> permite a Squid conectar a un directorio LDAP para "
-"autorizar grupos de usuarios LDAP. Las opciones LDAP son especificadas como "
-"parámetros en la línea de comandos, mientras, los nombres de usuario y "
-"grupos a ser autenticados contra el servidor LDAP son especificados en las "
-"líneas de entrada subsecuentes del módulo, un par nombre de usuario/grupo "
-"por línea separado por espacios"
+#~ msgid ""
+#~ "B<squid_ldap_group> allows Squid to connect to a LDAP directory to authorize "
+#~ "users via LDAP groups.  LDAP options are specified as parameters on the "
+#~ "command line, while the username(s) and group(s) to be checked against the "
+#~ "LDAP directory are specified on subsequent lines of input to the helper, one "
+#~ "username/group pair per line separated by a space."
+#~ msgstr ""
+#~ "B<squid_ldap_group> permite a Squid conectar a un directorio LDAP para "
+#~ "autorizar grupos de usuarios LDAP. Las opciones LDAP son especificadas como "
+#~ "parámetros en la línea de comandos, mientras, los nombres de usuario y "
+#~ "grupos a ser autenticados contra el servidor LDAP son especificados en las "
+#~ "líneas de entrada subsecuentes del módulo, un par nombre de usuario/grupo "
+#~ "por línea separado por espacios"
 
 #. type: Plain text
 #: src/squid.8.in:166
@@ -2004,14 +1994,12 @@ msgstr "B<REQUIRED.> Indica el DN base al que pertenece el usuario"
 msgid "Host header"
 msgstr "cabecera de host"
 
-#. type: Plain text
-#: helpers/external_acl/ldap_group/squid_ldap_group.8:158
-msgid ""
-"Specify an alternate TCP port where the ldap server is listening if other "
-"than the default LDAP port 389."
-msgstr ""
-"Especificar puerto TCP alternativo si el servidor LDAP está escuchando en un "
-"puerto diferente al puerto por defecto 389"
+#~ msgid ""
+#~ "Specify an alternate TCP port where the ldap server is listening if other "
+#~ "than the default LDAP port 389."
+#~ msgstr ""
+#~ "Especificar puerto TCP alternativo si el servidor LDAP está escuchando en un "
+#~ "puerto diferente al puerto por defecto 389"
 
 #. type: Plain text
 #: helpers/basic_auth/LDAP/basic_ldap_auth.8:16 helpers/basic_auth/LDAP/basic_ldap_auth.8:31 helpers/external_acl/ldap_group/squid_ldap_group.8:18
@@ -2104,15 +2092,13 @@ msgstr ""
 "Especifica el servidor LDAP a conectar por un URI LDAP (requiere las "
 "librerías OpenLDAP)"
 
-#. type: Plain text
-#: helpers/external_acl/session/squid_session.8:23
-msgid ""
-"B<squid_session> maintains a concept of sessions by monitoring requests and "
-"timing out sessions if no requests have been seen for the idle timeout timer."
-msgstr ""
-"B<squid_session> mantiene un \"concepto\" de sesiones por monitoreo de "
-"solicitudes y expiración de sesiones HTTP si las solicitudes han sido vistas "
-"por el temporizador."
+#~ msgid ""
+#~ "B<squid_session> maintains a concept of sessions by monitoring requests and "
+#~ "timing out sessions if no requests have been seen for the idle timeout timer."
+#~ msgstr ""
+#~ "B<squid_session> mantiene un \"concepto\" de sesiones por monitoreo de "
+#~ "solicitudes y expiración de sesiones HTTP si las solicitudes han sido vistas "
+#~ "por el temporizador."
 
 #. type: Plain text
 #: helpers/basic_auth/PAM/basic_pam_auth.8:46
@@ -2156,16 +2142,14 @@ msgstr ""
 "este archivo; si no, escriba a la Free Software Foundation, Inc., 59 Temple "
 "Place, Suite 330, Boston, MA 02111-1307 USA"
 
-#. type: Plain text
-#: helpers/external_acl/ldap_group/squid_ldap_group.8:231
-msgid ""
-"B<NOTE:> When constructing search filters it is recommended to first test "
-"the filter using B<ldapsearch> to verify that the filter matches what you "
-"expect before you attempt to use B<squid_ldap_group>"
-msgstr ""
-"B<NOTE:> Cuando se construyen filtros de búsqueda es recomendable primer "
-"hacer pruebas del filtro usando B<ldapsearch> para verificar que el filtro "
-"devuelve los resultados esperados antes de usar B<squid_ldap_group>"
+#~ msgid ""
+#~ "B<NOTE:> When constructing search filters it is recommended to first test "
+#~ "the filter using B<ldapsearch> to verify that the filter matches what you "
+#~ "expect before you attempt to use B<squid_ldap_group>"
+#~ msgstr ""
+#~ "B<NOTE:> Cuando se construyen filtros de búsqueda es recomendable primer "
+#~ "hacer pruebas del filtro usando B<ldapsearch> para verificar que el filtro "
+#~ "devuelve los resultados esperados antes de usar B<squid_ldap_group>"
 
 #. type: Plain text
 #: helpers/basic_auth/getpwnam/basic_getpwnam_auth.8:71 helpers/basic_auth/NCSA/basic_ncsa_auth.8:32 helpers/basic_auth/RADIUS/basic_radius_auth.8:93 helpers/external_acl/ldap_group/squid_ldap_group.8:243 helpers/external_acl/unix_group/squid_unix_group.8:67
@@ -2380,10 +2364,8 @@ msgstr ""
 "cache.org/SquidFaq/BugReporting para detalles de lo que necesita incluir en "
 "el reporte de errores"
 
-#. type: Plain text
-#: helpers/external_acl/ldap_group/squid_ldap_group.8:20
-msgid "ldap_server_name"
-msgstr "ldap_server_name"
+#~ msgid "ldap_server_name"
+#~ msgstr "ldap_server_name"
 
 #. type: Plain text
 #: src/squid.8.in:36
@@ -2481,11 +2463,9 @@ msgstr ""
 "El archivo de configuración principal para las herramientas web "
 "B<cachemgr.cgi>"
 
-#. type: Plain text
-#: helpers/basic_auth/LDAP/basic_ldap_auth.8:216 helpers/external_acl/ldap_group/squid_ldap_group.8:204
-msgid "LDAP protocol version. Defaults to 2 if not specified."
-msgstr ""
-"Versión del protocolo LDAP. Se usará la versión 2 si no se especifica."
+#~ msgid "LDAP protocol version. Defaults to 2 if not specified."
+#~ msgstr ""
+#~ "Versión del protocolo LDAP. Se usará la versión 2 si no se especifica."
 
 #. type: Plain text
 #: helpers/basic_auth/PAM/basic_pam_auth.8:7
@@ -2935,10 +2915,8 @@ msgstr ""
 "solicitudes, en adición a cualquier B<http_port> especificado en "
 "B<squid.conf>"
 
-#. type: Plain text
-#: helpers/external_acl/session/squid_session.8:7
-msgid "Squid session tracking external acl group helper."
-msgstr "Módulo externo de seguimiento de sesiones para ACLs de grupo"
+#~ msgid "Squid session tracking external acl group helper."
+#~ msgstr "Módulo externo de seguimiento de sesiones para ACLs de grupo"
 
 #. type: Plain text
 #: tools/squidclient.1:18
@@ -3052,6 +3030,12 @@ msgid ""
 "is not permitted then the authenticator will typically fail with \"-1, "
 "generic error\"."
 msgstr ""
+"Típicamente las bases de datos de autenticación (B</etc/sasldb> "
+",B</etc/shadow> ,B<PAM> ) no pueden ser accedidas por un usuario normal. "
+"Debería usar setuid/setgid y un usuario/grupo apropiado sobre el ejecutable "
+"para permitir al autenticador acceder a la base de datos de contraseñas "
+"apropiada. Si el acceso a la base de datos no es permitido entonces el "
+"autenticador fallará típicamente con \"-1, generic error\"."
 
 #. type: Plain text
 #: helpers/digest_auth/file/digest_file_auth.8:19
@@ -3080,7 +3064,7 @@ msgstr ""
 #: helpers/digest_auth/file/digest_file_auth.8:34
 #, no-wrap
 msgid "- plaintext entry format is username:password"
-msgstr ""
+msgstr "Entrada en formato de texto plano es nombre de usuario: contraseña"
 
 #. type: Plain text
 #: helpers/digest_auth/file/digest_file_auth.8:50
@@ -3119,7 +3103,7 @@ msgstr ""
 msgid ""
 " - use traditional \n"
 "B</etc/passwd>\n"
-msgstr ""
+msgstr " uso tradicional\n"
 
 #. type: Plain text
 #: helpers/basic_auth/SASL/basic_sasl_auth.8:36
@@ -3134,14 +3118,15 @@ msgstr " - usar el ligeramente menos tradicional /etc/shadow\n"
 
 #. type: Plain text
 #: helpers/digest_auth/file/digest_file_auth.8:64
+#: helpers/basic_auth/SSPI/basic_sspi_auth.8:108
 msgid "Based on prior work by"
-msgstr ""
+msgstr "Basado en trabajo previo por"
 
 #. type: Plain text
 #: helpers/basic_auth/SASL/basic_sasl_auth.8:38
 #, no-wrap
 msgid " - use PAM authentication database\n"
-msgstr ""
+msgstr " - usar base de datos de autenticación PAM\n"
 
 #. type: Plain text
 #: helpers/digest_auth/file/digest_file_auth.8:28
@@ -3158,7 +3143,7 @@ msgstr ""
 #: helpers/digest_auth/file/digest_file_auth.8:31
 #, no-wrap
 msgid "- empty or blank lines are possible;"
-msgstr ""
+msgstr "- son posibles líneas vacías o en blanco;"
 
 #. type: Plain text
 #: helpers/basic_auth/SASL/basic_sasl_auth.8:74
@@ -3167,3 +3152,667 @@ msgid ""
 "service name if B<pwcheck_method:pam> is chosen. And example PAM "
 "configuration file B<basic_sasl_auth.pam> is also included."
 msgstr ""
+
+#. type: Plain text
+#: helpers/ntlm_auth/SSPI/ntlm_sspi_auth.8:43
+msgid ""
+"Users that are allowed to access the web proxy must have the Windows NT User "
+"Rights \"logon from the network\"."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/file_userip/ext_file_userip_acl.8:49
+msgid "ip_addr[/netmask]\t\tusername|@group|ALL|NONE"
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:128 helpers/external_acl/LM_group/ext_lm_group_acl.8:90
+msgid ""
+"Native WIN32 NTLM and Basic Helpers must be used without the B<-A> and B<-D> "
+"switches."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/LM_group/ext_lm_group_acl.8:37
+msgid "Start helper in Domain Global Group mode."
+msgstr ""
+
+#. type: Plain text
+#: helpers/basic_auth/SSPI/basic_sspi_auth.8:75
+msgid ""
+"You will need to specify the absolute path to B<basic_sspi_auth> in the "
+"B<auth_param basic program> directive."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:51
+msgid "Use case insensitive compare (local mode only)."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/session/ext_session_acl.8:7
+msgid "Squid session tracking external acl helper."
+msgstr ""
+
+#. type: Plain text
+#: helpers/basic_auth/SSPI/basic_sspi_auth.8:14 helpers/basic_auth/SSPI/basic_sspi_auth.8:16 helpers/ntlm_auth/SSPI/ntlm_sspi_auth.8:15 helpers/ntlm_auth/SSPI/ntlm_sspi_auth.8:17
+msgid "Group Name"
+msgstr ""
+
+#. type: Plain text
+#: helpers/basic_auth/SSPI/basic_sspi_auth.8:97
+msgid ""
+"Note that if NT guest user access is allowed on the PDC, an OK message may "
+"be returned instead of ERR."
+msgstr ""
+
+#. type: Plain text
+#: helpers/basic_auth/SSPI/basic_sspi_auth.8:99
+msgid ""
+"Test that entering an valid username and password results in an OK message."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/LM_group/ext_lm_group_acl.8:19
+msgid ""
+"B<ext_lm_group_acl> is an installed binary in Squid for Windows builds."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/LM_group/ext_lm_group_acl.8:22
+msgid ""
+"This helper must be used in with an authentication scheme (typically Basic "
+"or NTLM) based on Windows NT/2000 domain users (LM mode)."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:19
+msgid ""
+"B<ext_ad_group_acl> is an installed binary in Squid for Windows builds."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:59 helpers/external_acl/file_userip/ext_file_userip_acl.8:31 helpers/external_acl/LM_group/ext_lm_group_acl.8:39 helpers/ntlm_auth/SSPI/ntlm_sspi_auth.8:31
+msgid "Display the binary help and command line syntax info using stderr."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:57
+msgid "Start helper in Active Directory Global mode."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:130 helpers/external_acl/LM_group/ext_lm_group_acl.8:92
+msgid "Refer to Squid documentation for the more details on squid.conf."
+msgstr ""
+
+#. type: Plain text
+#: helpers/basic_auth/SSPI/basic_sspi_auth.8:38
+msgid "A Windows Local Group name allowed to authenticate."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/LM_group/ext_lm_group_acl.8:139
+msgid "with contributions by"
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:46
+msgid ""
+"B<- Domain Global> B<- Domain Local from user's domain> B<- Universal> and "
+"Active Directory group nesting is fully supported."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:28
+msgid "Two running mode are available:"
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/LM_group/ext_lm_group_acl.8:83
+msgid ""
+"The standard group name comparison is case sensitive, so group name must be "
+"specified with same case as in the NT/2000 Domain.  It's possible to enable "
+"case insensitive group name comparison ( B<-c> ), but on some not-english "
+"locales, the results can be unexpected."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/file_userip/ext_file_userip_acl.8:45
+msgid ""
+"If the helper program finds a matching username/ip in the configuration "
+"file, it returns B<OK> , otherwise it returns B<ERR .>"
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:55 helpers/external_acl/LM_group/ext_lm_group_acl.8:35
+msgid "Specify the default user's domain."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:95
+msgid ""
+"In the previous example all validated AD users member of I<MYDOMAIN\\"
+"GProxyUsers> domain group or member of I<LProxyUsers> machine local group "
+"are allowed to use the cache."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:14 helpers/external_acl/LM_group/ext_lm_group_acl.8:14
+msgid "domain"
+msgstr ""
+
+#. type: Plain text
+#: helpers/ntlm_auth/SSPI/ntlm_sspi_auth.8:54
+msgid ""
+"Better group checking is available with External Acl, see mswin_check_group "
+"documentation."
+msgstr ""
+
+#. type: Plain text
+#: helpers/basic_auth/SSPI/basic_sspi_auth.8:56
+msgid ""
+"You will need to set the following line in B<squid.conf> to enable the "
+"authenticator:"
+msgstr ""
+
+#. type: Plain text
+#: helpers/basic_auth/SSPI/basic_sspi_auth.8:18
+msgid "Default Domain"
+msgstr ""
+
+#. type: Plain text
+#: helpers/basic_auth/SSPI/basic_sspi_auth.8:92
+msgid ""
+"Test that entering no details does not result in an OK or ERR message."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:137 helpers/external_acl/LM_group/ext_lm_group_acl.8:99
+msgid ""
+"I strongly recommend that B<ext_lm_group_acl> is tested prior to being used "
+"in a production environment. It may behave differently on different "
+"platforms."
+msgstr ""
+
+#. type: SH
+#: helpers/basic_auth/SSPI/basic_sspi_auth.8:43
+#, no-wrap
+msgid "CONFGURATION"
+msgstr ""
+
+#. type: Plain text
+#: helpers/basic_auth/LDAP/basic_ldap_auth.8:216 helpers/external_acl/LDAP_group/ext_ldap_group_acl.8:204
+msgid "LDAP protocol version. Defaults to 3 if not specified."
+msgstr ""
+
+#. type: Plain text
+#: helpers/basic_auth/SSPI/basic_sspi_auth.8:9 helpers/external_acl/AD_group/ext_ad_group_acl.8:9
+msgid "Version 2.0"
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:187 helpers/external_acl/LM_group/ext_lm_group_acl.8:134
+msgid ""
+"Test that entering an valid username and group results in an B<OK> message."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/unix_group/ext_unix_group_acl.8:7
+msgid "Squid UNIX Group ACL helper"
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/file_userip/ext_file_userip_acl.8:7
+msgid "Restrict users to cetain IP addresses, using a text file backend."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:117
+msgid ""
+"When running in local mode, the standard group name comparison is case "
+"sensitive, so group name must be specified with same case as in the local "
+"SAM database."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/LM_group/ext_lm_group_acl.8:59
+msgid ""
+"In the previous example all validated NT users member of GProxyUsers Global "
+"domain group or member of LProxyUsers machine local group are allowed to use "
+"the cache."
+msgstr ""
+
+#. type: Plain text
+#: helpers/basic_auth/SSPI/basic_sspi_auth.8:24
+msgid ""
+"B<basic_sspi_auth> is a simple authentication module for the Squid proxy "
+"server running on Windows NT to authenticate users on an NT domain in native "
+"WIN32 mode."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:38
+msgid ""
+"The minimal Windows version needed to run ext_ad_group_acl is a Windows 2000 "
+"SP4 member of an Active Directory Domain."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/file_userip/ext_file_userip_acl.8:61
+msgid ""
+"When the second parameter is prefixed with an B<@> , the program will lookup "
+"the B</etc/group> file entry for the specified username."
+msgstr ""
+
+#. type: Plain text
+#: helpers/basic_auth/SSPI/basic_sspi_auth.8:31
+msgid ""
+"Usage is simple. It accepts a username and password on standard input and "
+"will return OK if the username/password is valid for the domain/machine, or "
+"ERR if there was some problem.  It's possible to authenticate against NT "
+"trusted domains specifyng the username in the domain\\eusername Microsoft "
+"notation."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:41
+msgid ""
+"When running in Active Directory Global mode, all types of Active Directory "
+"security groups are supported:"
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/LM_group/ext_lm_group_acl.8:67
+msgid ""
+"Groups with spaces in name, for example B<Domain Users> , must be quoted and "
+"the acl data ( B<Domain Users> ) must be placed into a separate file "
+"included by specifying B</path/to/file>"
+msgstr ""
+
+#. type: Plain text
+#: helpers/basic_auth/SSPI/basic_sspi_auth.8:51
+msgid ""
+"This can be accomplished creating a local user group on the NT machine, "
+"grant the privilege, and adding users to it."
+msgstr ""
+
+#. type: Plain text
+#: helpers/ntlm_auth/SSPI/ntlm_sspi_auth.8:57
+msgid "B<squid.conf> typical minimal required changes:"
+msgstr ""
+
+#. type: Plain text
+#: helpers/ntlm_auth/SSPI/ntlm_sspi_auth.8:85
+msgid "Based on prior work in by"
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:164 helpers/external_acl/AD_group/ext_ad_group_acl.8:179 helpers/external_acl/LM_group/ext_lm_group_acl.8:126
+msgid ""
+"Test that entering no details does not result in an B<OK> or B<ERR> message."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:35
+msgid ""
+"B<- Local mode:> membership is checked against machine's local groups, "
+"cannot be used when running on a Domain Controller.  B<- Active Directory "
+"Global mode:> membership is checked against the whole Active Directory "
+"Forest of the machine where Squid is running."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:113
+msgid ""
+"When running in Active Directory Global mode, for better performance, all "
+"Domain Controllers of the Active Directory forest should be configured as "
+"Global Catalog."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:22
+msgid ""
+"This helper must be used in with an authentication scheme (typically Basic, "
+"NTLM or Negotiate) based on Windows Active Directory domain users."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/file_userip/ext_file_userip_acl.8:37
+msgid "The B<squid.conf> configuration for the external ACL should be:"
+msgstr ""
+
+#. type: Plain text
+#: helpers/basic_auth/SSPI/basic_sspi_auth.8:36 helpers/external_acl/AD_group/ext_ad_group_acl.8:53 helpers/external_acl/file_userip/ext_file_userip_acl.8:27 helpers/external_acl/LM_group/ext_lm_group_acl.8:33 helpers/external_acl/unix_group/ext_unix_group_acl.8:23 helpers/ntlm_auth/SSPI/ntlm_sspi_auth.8:29
+msgid "Write debug info to stderr."
+msgstr ""
+
+#. type: Plain text
+#: helpers/ntlm_auth/SSPI/ntlm_sspi_auth.8:35
+msgid "Specify a Windows Local Group name allowed to authenticate."
+msgstr ""
+
+#. type: Plain text
+#: helpers/ntlm_auth/SSPI/ntlm_sspi_auth.8:75
+msgid ""
+"Internet Explorer has some problems with B<ftp://> URLs when handling "
+"internal Squid FTP icons.  The following B<squid.conf> ACL works around this "
+"when placed before the authentication ACL:"
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/file_userip/ext_file_userip_acl.8:47
+msgid "The configuration file format is as follows:"
+msgstr ""
+
+#. type: Plain text
+#: helpers/basic_auth/SSPI/basic_sspi_auth.8:48
+msgid ""
+"Users that are allowed to access the web proxy must have the Windows NT User "
+"Rights \"logon from the network\" and must be included in the NT LOCAL User "
+"Groups specified in the Authenticator's command line."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/LM_group/ext_lm_group_acl.8:69
+msgid "The previous example will be:"
+msgstr ""
+
+#. type: Plain text
+#: helpers/basic_auth/SSPI/basic_sspi_auth.8:102
+msgid ""
+"Test that entering a guest username and password returns the correct "
+"response for the site's access policy."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/LM_group/ext_lm_group_acl.8:144
+msgid "Based in part on prior work in B<check_group> by"
+msgstr ""
+
+#. type: Plain text
+#: helpers/ntlm_auth/SSPI/ntlm_sspi_auth.8:33
+msgid "Enables verbose NTLM packet debugging."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/file_userip/ext_file_userip_acl.8:29
+msgid "Configuration file to load."
+msgstr ""
+
+#. type: Plain text
+#: helpers/ntlm_auth/SSPI/ntlm_sspi_auth.8:24
+msgid ""
+"B<ntlm_sspi_auth.exe> is an installed binary built on Windows systems. It "
+"provides native access to the Security Service Provider Interface of Windows "
+"for authenticating with NTLM / NTLMv2.  It has automatic support for NTLM "
+"NEGOTIATE packets."
+msgstr ""
+
+#. type: Plain text
+#: helpers/ntlm_auth/SSPI/ntlm_sspi_auth.8:8
+msgid ""
+"Native Windows NTLM/NTLMv2 authenticator for Squid with automatic support "
+"for NTLM NEGOTIATE packets."
+msgstr ""
+
+#. any user on this IP address may authenticate\" or \"no user on this ip address may authenticate\".
+#. type: Plain text
+#: helpers/external_acl/file_userip/ext_file_userip_acl.8:67
+msgid "There are other two directives, B<ALL> and B<NONE> , which mean"
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:104
+msgid ""
+"Groups with spaces in name, for example B<Domain Users> , must be quoted and "
+"the acl data ( B<Domain Users> ) must be placed into a separate file "
+"included by specifying B</path/to/file .> The previous example will be:"
+msgstr ""
+
+#. type: Plain text
+#: helpers/basic_auth/SSPI/basic_sspi_auth.8:40
+msgid "A Windows Local Group name not allowed to authenticate."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/LM_group/ext_lm_group_acl.8:9 helpers/ntlm_auth/SSPI/ntlm_sspi_auth.8:10
+msgid "Version 1.22"
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/LM_group/ext_lm_group_acl.8:76
+msgid ""
+"and the B<DomainUsers.txt> files will contain only the following line: "
+"B<Domain Users>"
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/session/ext_session_acl.8:23
+msgid ""
+"B<ext_session_acl> maintains a concept of sessions by monitoring requests "
+"and timing out sessions if no requests have been seen for the idle timeout "
+"timer."
+msgstr ""
+
+#. type: Plain text
+#: helpers/ntlm_auth/SSPI/ntlm_sspi_auth.8:37
+msgid ""
+"Specify a Windows Local Group name which is to be denied authentication."
+msgstr ""
+
+#. type: Plain text
+#: helpers/basic_auth/SSPI/basic_sspi_auth.8:7
+msgid "Basic authentication protocol"
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/LDAP_group/ext_ldap_group_acl.8:158
+msgid ""
+"Specify an alternate TCP port where the LDAP server is listening if other "
+"than the default LDAP port 389."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:77
+msgid ""
+"When using Plain NT4 Group Name, the Group is searched in the user's domain."
+msgstr ""
+
+#. type: Plain text
+#: helpers/ntlm_auth/SSPI/ntlm_sspi_auth.8:47
+msgid ""
+"Optionally the authenticator can verify the NT LOCAL group membership of the "
+"user against the User Group specified in the Authenticator's command line."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:122
+msgid ""
+"It is possible to enable case insensitive group name comparison ( B<-c> ), "
+"but on some non-english locales, the results can be unexpected."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/LDAP_group/ext_ldap_group_acl.8:82
+msgid ""
+"Debug mode where each step taken will get reported in detail.  Useful for "
+"understanding what goes wrong if the result is not what was expected."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:109
+msgid ""
+"and the DomainUsers files will contain only the following line: \"Domain "
+"Users\""
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/LM_group/ext_lm_group_acl.8:31
+msgid "Use case insensitive compare."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:157 helpers/external_acl/AD_group/ext_ad_group_acl.8:172 helpers/external_acl/LM_group/ext_lm_group_acl.8:119
+msgid "Make sure pressing B<CTRL+C> aborts the program."
+msgstr ""
+
+#. type: Plain text
+#: helpers/ntlm_auth/SSPI/ntlm_sspi_auth.8:51
+msgid ""
+"This can be accomplished creating a local user group on the NT machine, "
+"grant the privilege, and adding users to it, it works only with MACHINE "
+"Local Groups, not Domain Local Groups."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:7 helpers/external_acl/LM_group/ext_lm_group_acl.8:7
+msgid "Squid external ACL helper to check Windows users group membership."
+msgstr ""
+
+#. type: SH
+#: helpers/basic_auth/SSPI/basic_sspi_auth.8:76 helpers/external_acl/AD_group/ext_ad_group_acl.8:131 helpers/external_acl/LM_group/ext_lm_group_acl.8:93
+#, no-wrap
+msgid "TESTING"
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/LDAP_group/ext_ldap_group_acl.8:33
+msgid ""
+"B<ext_ldap_group_acl> allows Squid to connect to a LDAP directory to "
+"authorize users via LDAP groups.  LDAP options are specified as parameters "
+"on the command line, while the username(s) and group(s) to be checked "
+"against the LDAP directory are specified on subsequent lines of input to the "
+"helper, one username/group pair per line separated by a space."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/file_userip/ext_file_userip_acl.8:22
+msgid ""
+"It works by reading a pair composed by an ip address and an username on "
+"STDIN and matching it against a configuration file."
+msgstr ""
+
+#. type: Plain text
+#: helpers/basic_auth/SSPI/basic_sspi_auth.8:90
+#, no-wrap
+msgid ""
+"I strongly urge that \n"
+"B<basic_sspi_auth>\n"
+"is tested prior to being used in a \n"
+"production environment. It may behave differently on different platforms.\n"
+"To test it, run it from the command line. Enter username and password\n"
+"pairs separated by a space. Press ENTER to get an OK or ERR message.\n"
+"Make sure pressing \n"
+"B<CTRL-D>\n"
+" behaves the same as a carriage return.\n"
+"Make sure pressing \n"
+"B<CTRL-C>\n"
+" aborts the program.\n"
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:149 helpers/external_acl/LM_group/ext_lm_group_acl.8:111
+msgid ""
+"To test it, run it from the command line. Enter username and group pairs "
+"separated by a space (username must entered with URL-encoded "
+"I<domain%5Cusername> syntax). Press B<ENTER> to get an B<OK> or B<ERR> "
+"message."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:64
+msgid ""
+"When running in Active Directory Global mode, the AD Group can be specified "
+"using the following syntax:"
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:153 helpers/external_acl/AD_group/ext_ad_group_acl.8:168 helpers/external_acl/LM_group/ext_lm_group_acl.8:115
+msgid "Make sure pressing B<CTRL+D> behaves the same as a carriage return."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:183 helpers/external_acl/LM_group/ext_lm_group_acl.8:130
+msgid ""
+"Test that entering an invalid username and group results in an B<ERR> "
+"message."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/LDAP_group/ext_ldap_group_acl.8:87
+msgid ""
+"The DN and password to bind as while performing searches. Required if the "
+"LDAP directory does not allow anonymous searches."
+msgstr ""
+
+#. type: Plain text
+#: helpers/basic_auth/SSPI/basic_sspi_auth.8:42
+msgid "The default Domain against to authenticate."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/LDAP_group/ext_ldap_group_acl.8:231
+msgid ""
+"B<NOTE:> When constructing search filters it is recommended to first test "
+"the filter using B<ldapsearch> to verify that the filter matches what you "
+"expect before you attempt to use B<ext_ldap_group_acl>"
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/file_userip/ext_file_userip_acl.8:14
+msgid "file name"
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/LM_group/ext_lm_group_acl.8:41
+msgid "Use ONLY PDCs for group validation."
+msgstr ""
+
+#. type: Plain text
+#: helpers/basic_auth/SSPI/basic_sspi_auth.8:64
+msgid ""
+"You will need to set the following lines in B<squid.conf> to enable "
+"authentication for your access list -"
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:26 helpers/external_acl/LM_group/ext_lm_group_acl.8:26
+msgid ""
+"It reads from the standard input the domain username and a list of groups "
+"and tries to match each against the groups membership of the specified "
+"username."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/file_userip/ext_file_userip_acl.8:55
+msgid ""
+"Where B<ip_addr> is a dotted quad format IP address, the B<netmask> must be "
+"in dotted quad format too."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/file_userip/ext_file_userip_acl.8:19
+msgid ""
+"B<ext_file_userip_acl> is an installed binary. An external helper for the "
+"Squid external acl scheme."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/unix_group/ext_unix_group_acl.8:18
+msgid ""
+"B<ext_unix_group_acl> allows Squid to base access controls on users "
+"memberships in UNIX groups."
+msgstr ""
+
+#. type: Plain text
+#: helpers/basic_auth/SSPI/basic_sspi_auth.8:94
+msgid ""
+"Test that entering an invalid username and password results in an ERR "
+"message."
+msgstr ""
+
+#. type: Plain text
+#: helpers/external_acl/AD_group/ext_ad_group_acl.8:194
+msgid "Based on prior work in B<mswin_check_lm_group (ext_lm_group_acl)>"
+msgstr ""
index c5e15113a7f4a4c3cde7e1407ba1ccc0d3515cdb..767e55f2ab375a33cbfe1fc7ef1464ec78fe0566 100644 (file)
@@ -163,6 +163,11 @@ msgid ""
 "recommended, but if you absolutely need to then make the program B<setuid> "
 "B<root>"
 msgstr ""
+"При использовании локальной базы UNIX паролей для аутентификации программа "
+"должна быть запущена с правами администратора, иначе она не будет обладать "
+"достаточными правами для доступа к базе данных паролей пользователей. Такое "
+"использование этой программы не рекомендуется, но если это вам абсолютно "
+"необходимо, то измените B<setuid> на B<root>"
 
 #. type: Plain text
 #: helpers/basic_auth/getpwnam/basic_getpwnam_auth.8:60
@@ -517,7 +522,7 @@ msgstr ""
 #: helpers/external_acl/unix_group/ext_unix_group_acl.8:108
 #: helpers/ntlm_auth/SSPI/ntlm_sspi_auth.8:123 src/squid.8.in:274
 msgid "The Squid Configuration Manual"
-msgstr ""
+msgstr "Руководство по настройке Squid"
 
 #. type: Plain text
 #: helpers/basic_auth/LDAP/basic_ldap_auth.8:7
@@ -803,19 +808,19 @@ msgstr ""
 #: helpers/basic_auth/LDAP/basic_ldap_auth.8:216
 #: helpers/external_acl/LDAP_group/ext_ldap_group_acl.8:204
 msgid "LDAP protocol version. Defaults to 3 if not specified."
-msgstr ""
+msgstr "Версия протокола LDAP. По умолчанию 3, если не указано."
 
 #. type: Plain text
 #: helpers/basic_auth/LDAP/basic_ldap_auth.8:220
 #: helpers/external_acl/LDAP_group/ext_ldap_group_acl.8:208
 msgid "Use TLS encryption"
-msgstr ""
+msgstr "Используйте TLS шифрование"
 
 #. type: Plain text
 #: helpers/basic_auth/LDAP/basic_ldap_auth.8:224
 #: helpers/external_acl/LDAP_group/ext_ldap_group_acl.8:107
 msgid "Enable LDAP over SSL (requires Netscape LDAP API libraries)"
-msgstr ""
+msgstr "Включить LDAP через SSL (требуются Netscape LDAP API библиотеки)"
 
 #. type: Plain text
 #: helpers/basic_auth/LDAP/basic_ldap_auth.8:231
@@ -922,7 +927,7 @@ msgstr ""
 #. type: Plain text
 #: helpers/basic_auth/NCSA/basic_ncsa_auth.8:11
 msgid "passwd file"
-msgstr ""
+msgstr "passwd файл"
 
 #. type: Plain text
 #: helpers/basic_auth/NCSA/basic_ncsa_auth.8:16
@@ -1042,7 +1047,7 @@ msgstr ""
 #: helpers/basic_auth/PAM/basic_pam_auth.8:59
 #, no-wrap
 msgid "NOTES"
-msgstr ""
+msgstr "ПРИМЕЧАНИЯ"
 
 #. type: Plain text
 #: helpers/basic_auth/PAM/basic_pam_auth.8:66
@@ -1077,7 +1082,7 @@ msgstr ""
 #. type: Plain text
 #: helpers/basic_auth/RADIUS/basic_radius_auth.8:12
 msgid "config file"
-msgstr ""
+msgstr "конфигурационный файл"
 
 #. type: Plain text
 #: helpers/basic_auth/RADIUS/basic_radius_auth.8:16
@@ -1206,7 +1211,7 @@ msgstr ""
 #: helpers/external_acl/file_userip/ext_file_userip_acl.8:9
 #: helpers/external_acl/session/ext_session_acl.8:9
 msgid "Version 1.0"
-msgstr ""
+msgstr "Версия 1.0"
 
 #. type: Plain text
 #: helpers/basic_auth/SASL/basic_sasl_auth.8:18
@@ -1234,7 +1239,7 @@ msgstr ""
 #. type: Plain text
 #: helpers/basic_auth/SASL/basic_sasl_auth.8:33
 msgid "Examples:"
-msgstr ""
+msgstr "Например:"
 
 #. type: Plain text
 #: helpers/basic_auth/SASL/basic_sasl_auth.8:36
@@ -1340,6 +1345,8 @@ msgstr ""
 #: helpers/ntlm_auth/SSPI/ntlm_sspi_auth.8:29
 msgid "Write debug info to stderr."
 msgstr ""
+"Записывать отладочную информацию в стандартный файл вывода сообщений об "
+"ошибках (stderr)."
 
 #. type: Plain text
 #: helpers/basic_auth/SSPI/basic_sspi_auth.8:38
@@ -1360,7 +1367,7 @@ msgstr ""
 #: helpers/basic_auth/SSPI/basic_sspi_auth.8:43
 #, no-wrap
 msgid "CONFGURATION"
-msgstr ""
+msgstr "КОНФИГУРИРОВАНИЕ"
 
 #. type: Plain text
 #: helpers/basic_auth/SSPI/basic_sspi_auth.8:48
@@ -1402,10 +1409,11 @@ msgstr ""
 #: helpers/basic_auth/SSPI/basic_sspi_auth.8:76
 #: helpers/external_acl/AD_group/ext_ad_group_acl.8:131
 #: helpers/external_acl/LM_group/ext_lm_group_acl.8:93
-#, fuzzy, no-wrap
+#, no-wrap
+#, no-wrap
 #| msgid "QUESTIONS"
 msgid "TESTING"
-msgstr "Ð\92Ð\9eÐ\9fРÐ\9eСЫ"
+msgstr "ТÐ\95СТÐ\98РÐ\9eÐ\92Ð\90Ð\9dÐ\98Ð\95"
 
 #. type: Plain text
 #: helpers/basic_auth/SSPI/basic_sspi_auth.8:90
@@ -1770,7 +1778,7 @@ msgstr ""
 #. type: Plain text
 #: helpers/external_acl/file_userip/ext_file_userip_acl.8:14
 msgid "file name"
-msgstr ""
+msgstr "имя файла"
 
 #. type: Plain text
 #: helpers/external_acl/file_userip/ext_file_userip_acl.8:19
@@ -1806,7 +1814,7 @@ msgstr ""
 #. type: Plain text
 #: helpers/external_acl/file_userip/ext_file_userip_acl.8:47
 msgid "The configuration file format is as follows:"
-msgstr ""
+msgstr "Формат конфигурационного файла выглядит следующим образом:"
 
 #. type: Plain text
 #: helpers/external_acl/file_userip/ext_file_userip_acl.8:49
@@ -1841,7 +1849,7 @@ msgstr ""
 #. type: Plain text
 #: helpers/external_acl/LDAP_group/ext_ldap_group_acl.8:9
 msgid "Version 2.17"
-msgstr ""
+msgstr "Версия 2.17"
 
 #. type: Plain text
 #: helpers/external_acl/LDAP_group/ext_ldap_group_acl.8:33
@@ -1966,7 +1974,7 @@ msgstr ""
 #. type: Plain text
 #: helpers/external_acl/LDAP_group/ext_ldap_group_acl.8:145
 msgid "Specify the LDAP server to connect to"
-msgstr ""
+msgstr "Укажите сервер LDAP для подключения к"
 
 #. type: Plain text
 #: helpers/external_acl/LDAP_group/ext_ldap_group_acl.8:149
@@ -2121,7 +2129,7 @@ msgstr ""
 #. type: Plain text
 #: helpers/external_acl/LM_group/ext_lm_group_acl.8:139
 msgid "with contributions by"
-msgstr ""
+msgstr "внесут свой вклад"
 
 #. type: Plain text
 #: helpers/external_acl/LM_group/ext_lm_group_acl.8:144
@@ -2273,7 +2281,7 @@ msgstr ""
 #. type: Plain text
 #: helpers/ntlm_auth/SSPI/ntlm_sspi_auth.8:33
 msgid "Enables verbose NTLM packet debugging."
-msgstr ""
+msgstr "Включить подробную отладку NTLM пакетов."
 
 #. type: Plain text
 #: helpers/ntlm_auth/SSPI/ntlm_sspi_auth.8:35
@@ -2358,12 +2366,12 @@ msgstr ""
 #. type: Plain text
 #: src/squid.8.in:21
 msgid "service-name"
-msgstr ""
+msgstr "название службы"
 
 #. type: Plain text
 #: src/squid.8.in:23
 msgid "command-line"
-msgstr ""
+msgstr "командная строка"
 
 #. type: Plain text
 #: src/squid.8.in:32
@@ -2425,12 +2433,14 @@ msgstr ""
 #. type: Plain text
 #: src/squid.8.in:70
 msgid "Do not catch fatal signals."
-msgstr ""
+msgstr "Не перехватывать сигналы отказов."
 
 #. type: Plain text
 #: src/squid.8.in:74
 msgid "Write debugging to stderr also."
 msgstr ""
+"Отладочную информацию тоже записывать в стандартный файл вывода сообщений об "
+"ошибках (stderr)."
 
 #. type: Plain text
 #: src/squid.8.in:86
@@ -2455,7 +2465,7 @@ msgstr ""
 #. type: Plain text
 #: src/squid.8.in:100
 msgid "Install as a Windows Service (see B<-n> option)."
-msgstr ""
+msgstr "установить как Службу Windows (see B<-n> option)."
 
 #. type: Plain text
 #: src/squid.8.in:107
@@ -2479,7 +2489,7 @@ msgstr ""
 #. type: Plain text
 #: src/squid.8.in:121
 msgid "No daemon mode."
-msgstr ""
+msgstr "Не в режиме демона."
 
 #. type: Plain text
 #: src/squid.8.in:125
@@ -2489,7 +2499,7 @@ msgstr ""
 #. type: Plain text
 #: src/squid.8.in:131
 msgid "Remove a Windows Service (see B<-n> option)."
-msgstr ""
+msgstr "Убрать из служб Windows (see B<-n> option)."
 
 #. type: Plain text
 #: src/squid.8.in:137
@@ -2515,7 +2525,7 @@ msgstr ""
 #. type: Plain text
 #: src/squid.8.in:154
 msgid "Print version and build details."
-msgstr ""
+msgstr "Показать версию и информацию о сборке."
 
 #. type: Plain text
 #: src/squid.8.in:158
@@ -2736,7 +2746,7 @@ msgstr ""
 #. type: Plain text
 #: tools/squidclient.1:14
 msgid "remote host"
-msgstr ""
+msgstr "удалённый хост"
 
 #. type: Plain text
 #: tools/squidclient.1:16
@@ -2761,7 +2771,7 @@ msgstr ""
 #. type: Plain text
 #: tools/squidclient.1:24
 msgid "local host"
-msgstr ""
+msgstr "локальный хост"
 
 #. type: Plain text
 #: tools/squidclient.1:26
@@ -2826,7 +2836,7 @@ msgstr ""
 #. type: Plain text
 #: tools/squidclient.1:85
 msgid "Ping interval in seconds (default 1 second)."
-msgstr ""
+msgstr "Интервал ping в секундах (по умолчанию 1 секунда)"
 
 #. type: Plain text
 #: tools/squidclient.1:89
@@ -2859,7 +2869,7 @@ msgstr ""
 #. type: Plain text
 #: tools/squidclient.1:116
 msgid "Port number of cache.  Default is 3128."
-msgstr ""
+msgstr "Номер аорта кэширующего прокси-сервера. По умолчанию 3128."
 
 #. type: Plain text
 #: tools/squidclient.1:120
index 38679f17988aabbac9846404e1c01e3987ee6f19..d5bd288d3690f0a33476cef4932eb157199c44d5 100644 (file)
@@ -1,6 +1,6 @@
 <!doctype linuxdoc system>
 <article>
-<title>Squid 3.1.6 release notes</title>
+<title>Squid 3.1.7 release notes</title>
 <author>Squid Developers</author>
 
 <abstract>
@@ -13,7 +13,7 @@ for Applied Network Research and members of the Web Caching community.
 
 <sect>Notice
 <p>
-The Squid Team are pleased to announce the release of Squid-3.1.6
+The Squid Team are pleased to announce the release of Squid-3.1.7
 
 This new release is available for download from <url url="http://www.squid-cache.org/Versions/v3/3.1/"> or the <url url="http://www.squid-cache.org/Mirrors/http-mirrors.html" name="mirrors">.
 
@@ -171,7 +171,7 @@ config options provided on a clean install.
     <item>permit IPv6-only snmp_incoming_address and snmp_outgoing_address to be configured.
     <item>permit IPv6 server connection provided tcp_outgoing_address has been configured (see below).
 </itemize>
-<p><em>NOTE:</em> SNMP, ICP and HTCP are not yet opening double ports so they will only run as IPv4-only or IPv6-only.
+<p><em>NOTE:</em> ICAP, SNMP, ICP and HTCP are not yet opening double ports so they will only run as IPv4-only or IPv6-only.
 
 <p>Specify a specific tcp_outgoing_address and the clients who match its ACL are limited
  to the IPv4 or IPv6 network that address belongs to. They are not permitted over the
@@ -880,8 +880,8 @@ logformat icap_squid %ts.%03tu %6icap::tr %>a %icap::to/%03icap::Hs %icap::<size
 
        <tag>ssl_bump</tag>
        <p>New Access control for which CONNECT requests to an http_port
-       marked with an sslBump flag are actually "bumped". Please
-       see the sslBump flag of an http_port option for more details
+       marked with an ssl-bump flag are actually "bumped". Please
+       see the ssl-bump flag of an http_port option for more details
        about decoding proxied SSL connections.
        DEFAULT: No requests are bumped.
        <verb>
@@ -1111,7 +1111,7 @@ NOCOMMENT_START
        X-Forwarded-For entries, and place itself as the sole entry.
        </verb>
 
-       <tag>http_port transparent intercept sslbump connection-auth[=on|off] ignore-cc</tag>
+       <tag>http_port transparent intercept ssl-bump connection-auth[=on|off] ignore-cc</tag>
        <p>Option 'transparent' is being deprecated in favour of 'intercept' which more clearly identifies what the option does.
        For now option 'tproxy' remains with old behaviour meaning fully-invisible proxy using TPROXY support.</p>
        <p>New port options
@@ -1138,7 +1138,7 @@ NOCOMMENT_START
                        Warning: This option violates HTTP specifications if
                        used in non-accelerator setups.
 
-          sslBump      Intercept each CONNECT request matching ssl_bump ACL,
+          ssl-bump     Intercept each CONNECT request matching ssl_bump ACL,
                        establish secure connection with the client and with
                        the server, decrypt HTTP messages as they pass through
                        Squid, and treat them as unencrypted HTTP messages,
@@ -1152,10 +1152,10 @@ NOCOMMENT_START
                        for more information on these options.
 
                        The ssl_bump option is required to fully enable
-                       the SslBump feature.
+                       the SSL Bump feature.
         </verb>
 
-       <tag>https_port intercept sslbump connection-auth[=on|off]</tag>
+       <tag>https_port intercept ssl-bump connection-auth[=on|off]</tag>
        <p>New port options. see http_port.
 
        <tag>icap_service bypass=on|off|1|0 routing=on|off|1|0 ipv6=on|off</tag>
@@ -1182,7 +1182,7 @@ NOCOMMENT_START
                should have the same method and vectoring point as the current
                ICAP transaction.  Services violating these rules are ignored.
                An empty X-Next-Services value results in an empty plan which
-               ends the current adaptation. 
+               ends the current adaptation.
 
                Routing is not allowed by default: the ICAP X-Next-Services
                response header is ignored.
index 177e6e229c1f976cfe8133b125cf4930ccea27a4..62a6afd643772732addec209525af97f2cc93ef9 100644 (file)
@@ -377,6 +377,10 @@ This section gives a thorough account of those changes in three categories:
           <em>concurrency=N</em> previously called <em>auth_param ... concurrency</em> as a separate option.
        <p>Removed Basic, Digest, NTLM, Negotiate <em>auth_param ... concurrency</em> setting option.
 
+       <tag>cache_peer</tag>
+       <p><em>htcp-*</em> options collapsed into <em>htcp=</em> taking an optional comma-separated list of flags.
+          The old form is deprecated but still accepted.
+
        <tag>deny_info</tag>
        <p>Support URL format tags. For dynamically generated URL in denial redirect.
 
index 86546eeadd47876acd7edd64160db9a3b6d2e690..afe76cace69ccc2dd2dab45d9149ee7ac99b0c5b 100644 (file)
@@ -75,6 +75,7 @@ TRANSLATE_LANGUAGES = \
        lv.lang \
        ms.lang \
        nl.lang \
+       oc.lang \
        pl.lang \
        pt-br.lang \
        pt.lang \
@@ -88,6 +89,7 @@ TRANSLATE_LANGUAGES = \
        tr.lang \
        uk.lang \
        uz.lang \
+       vi.lang \
        zh-cn.lang \
        zh-tw.lang
 
index 72f8b28b0e92a7d541cfd54d1ea6716213960649..66715fc3c785361e298a2e84dc801550e779fe0f 100644 (file)
@@ -13,7 +13,7 @@ fi    fi-fi
 fr     fr-be fr-ca fr-ch fr-fr fr-lu fr-mc
 he     he-il
 hu     hu-hu
-hy     hy-am
+hy     hy-armn hy-am
 id     id-id
 it     it-ch it-it
 ja     ja-jp
index d9fb3acb16370689898f2438b46c93cf45e68332..0e529650923e48e1281e6862a6acda1133211d53 100644 (file)
@@ -3,7 +3,7 @@ msgstr ""
 "Project-Id-Version: Squid-3\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2010-07-26 21:21+1300\n"
-"PO-Revision-Date: 2010-05-01 00:17+1300\n"
+"PO-Revision-Date: 2010-08-18 01:16+0200\n"
 "Last-Translator: Amos <squid3@treenet.co.nz>\n"
 "Language-Team: Squid Developers <squid-dev@squid-cache.org>\n"
 "Language: en\n"
@@ -195,14 +195,12 @@ msgid "ESI Processing failed."
 msgstr "ESI Processing failed."
 
 #: templates/ERR_FTP_PUT_CREATED:1 templates/ERR_FTP_PUT_MODIFIED:1
-#, fuzzy
 msgid "FTP PUT Successful."
-msgstr "FTP PUT Successful: File Created"
+msgstr "FTP PUT Successful."
 
 #: templates/ERR_FTP_PUT_ERROR:3
-#, fuzzy
 msgid "FTP PUT upload failed"
-msgstr "FTP PUT/upload failed"
+msgstr "FTP PUT upload failed"
 
 #: templates/ERR_FTP_DISABLED:5
 msgid "FTP is Disabled"
@@ -303,7 +301,7 @@ msgstr "Illegal double-escape in the URL-Path"
 #: templates/ERR_AGENT_CONFIGURE:8 templates/ERR_AGENT_CONFIGURE:11
 #: templates/ERR_AGENT_CONFIGURE:14
 msgid "In the HTTP proxy box type the proxy name %h and port 3128."
-msgstr ""
+msgstr "In the HTTP proxy box type the proxy name %h and port 3128."
 
 #: templates/ERR_INVALID_URL:5
 msgid "Invalid URL"
index ee3bbee36b6c5ce5d2fb3f523042cdb54ba78c2c..729064657e1b4b9327a6cabee1f8ef4d1602c972 100644 (file)
@@ -201,14 +201,12 @@ msgid "ESI Processing failed."
 msgstr "El procesado ESI falló"
 
 #: templates/ERR_FTP_PUT_CREATED:1 templates/ERR_FTP_PUT_MODIFIED:1
-#, fuzzy
 msgid "FTP PUT Successful."
-msgstr "FTP PUT Correcto: Archivo Creado"
+msgstr "PUT FTP realizado con éxito"
 
 #: templates/ERR_FTP_PUT_ERROR:3
-#, fuzzy
 msgid "FTP PUT upload failed"
-msgstr "FTP PUT/envio fallido"
+msgstr "FTP PUT fallido"
 
 #: templates/ERR_FTP_DISABLED:5
 msgid "FTP is Disabled"
index 4754ae524554dc3f0d87c0522f82e6f9ce23ec2f..8f684fe7971bebdfefd17473cfa8a24c93faddba 100644 (file)
@@ -3,33 +3,36 @@ msgstr ""
 "Project-Id-Version: Squid-3\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2010-07-26 21:21+1300\n"
-"PO-Revision-Date: 2008-12-18 01:19+1300\n"
-"Last-Translator: Arthur Tumanyan <arthurtumanyan@yahoo.com>\n"
+"PO-Revision-Date: 2010-08-21 17:08+0200\n"
+"Last-Translator: Arthur <arthurtumanyan@yahoo.com>\n"
 "Language-Team: Squid Developers <squid-dev@squid-cache.org>\n"
 "Language: hy\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Pootle 1.2.0\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: Pootle 2.0.1\n"
 
 #: templates/ERR_DIR_LISTING:6
 msgid "<a href=\"../\">Parent Directory</a> (<a href=\"/\">Root Directory</a>)"
 msgstr ""
+"<a href=\"../\">Ծնողական դիրեկտորիա</a> (<a href=\"/\">Արմատական դիրեկտորիա</a>)"
 
 #: templates/ERR_INVALID_REQ:4
 msgid ""
 "<b>Invalid Request</b> error was encountered while trying to process the "
 "request:"
-msgstr ""
+msgstr "<b>Սխալ հարցում</b> հարցումն իրականացնելու ընթացքում տեղի ունեցավ սխալ:"
 
 #: templates/ERR_INVALID_RESP:4
 msgid ""
 "<b>Invalid Response</b> error was encountered while trying to process the "
 "request:"
 msgstr ""
+"<b>Անթույլատրելի պատասխան</b> հարցումն իրականացնելու ընթացքում տեղի ունեցավ "
+"սխալ:"
 
 #: templates/ERR_READ_TIMEOUT:7
-#, fuzzy
 msgid ""
 "A Timeout occurred while waiting to read data from the network. The network "
 "or server may be down or congested. Please retry your request."
@@ -40,36 +43,35 @@ msgstr ""
 
 #: templates/ERR_URN_RESOLVE:3
 msgid "A URL for the requested URN could not be retrieved"
-msgstr "Պահանջվող URN չի կարող առաքվել"
+msgstr "Պահանջվող URN-ի համար URL-ն հնարավոր չէ ստանալ"
 
 #: templates/ERR_ACCESS_DENIED:5
 msgid "Access Denied."
 msgstr "Մուտքն արգելված է."
 
 #: templates/ERR_ACCESS_DENIED:6
-#, fuzzy
 msgid ""
 "Access control configuration prevents your request from being allowed at "
 "this time. Please contact your service provider if you feel this is "
 "incorrect."
 msgstr ""
-"Õ\84Õ¸Ö\82Õ¿Ö\84Õ« Õ¯Õ¡Õ¼Õ¡Õ¾Õ¡Ö\80Õ´Õ¡Õ¶ ÕºÕ¡Ö\80Õ¡Õ´Õ¥Õ¿Ö\80Õ¥Ö\80Õ¨ Õ©Õ¸Ö\82ÕµÕ¬ Õ¹Õ¥Õ¶ Õ¿Õ¡Õ¬Õ«Õ½ Õ¯Õ¡Õ¿Õ¡Ö\80ել Ձեր հարցումը տվյալ "
-"ÕºÕ¡Õ°Õ«Õ¶.ÔµÕ©Õ¥ Ô´Õ¸Ö\82Ö\84 Õ½Õ¡ Õ½Õ­Õ¡Õ¬ Õ¥Ö\84 Õ°Õ¡Õ´Õ¡Ö\80Õ¸Ö\82Õ´,Õ­Õ¶Õ¤Ö\80Õ¾Õ¸Ö\82Õ´ Õ§ Õ¤Õ«Õ´Õ¥Õ¬ Õ\81Õ¥Ö\80 Õ«Õ¶Õ¿Õ¥Ö\80Õ¶Õ¥Õ¿ ապահովողին․"
+"Õ\84Õ¸Ö\82Õ¿Ö\84Õ« Õ¯Õ¡Õ¼Õ¡Õ¾Õ¡Ö\80Õ´Õ¡Õ¶ ÕºÕ¡Ö\80Õ¡Õ´Õ¥Õ¿Ö\80Õ¥Ö\80Õ¨ Õ©Õ¸Ö\82ÕµÕ¬ Õ¹Õ¥Õ¶ Õ¿Õ¡Õ¬Õ«Õ½ Õ«Ö\80Õ¡Õ¯Õ¡Õ¶Õ¡Ö\81Õ¶ել Ձեր հարցումը տվյալ "
+"ÕºÕ¡Õ°Õ«Õ¶.ÔµÕ©Õ¥ Ô´Õ¸Ö\82Ö\84 Õ½Õ¡ Õ½Õ­Õ¡Õ¬ Õ¥Ö\84 Õ°Õ¡Õ´Õ¡Ö\80Õ¸Ö\82Õ´,Õ¡ÕºÕ¡ Õ¤Õ«Õ´Õ¥Ö\84 Õ\81Õ¥Ö\80 Õ«Õ¶Õ¿Õ¥Ö\80Õ¶Õ¥Õ¿ Õ¯Õ¡Õº ապահովողին․"
 
 #: templates/ERR_FTP_FORBIDDEN:4
 msgid ""
 "An FTP authentication failure occurred while trying to retrieve the URL: <a "
 "href=\"%U\">%U</a>"
 msgstr ""
-"URL ի առաքման ժամանակ տեղի ունեցավ FTP աութենտիֆիկացիայի սխալ: <a href=\"%U"
-"\">%U</a>"
+"URL -ի ստացման ընթացքում տեղի ունեցավ FTP աութենտիֆիկացիայի սխալ: <a href=\"%"
+"U\">%U</a>"
 
 #: templates/ERR_FTP_FAILURE:4 templates/ERR_FTP_PUT_ERROR:4
 msgid ""
 "An FTP protocol error occurred while trying to retrieve the URL: <a href=\"%U"
 "\">%U</a>"
 msgstr ""
-"URL ի առաքման ժամանակ տեղի ունեցավ FTP արձանագրության սխալ: <a href=\"%U\">"
+"URL -ի ստացման ընթացքում տեղի ունեցավ FTP արձանագրության սխալ: <a href=\"%U\">"
 "%U</a>"
 
 #: templates/ERR_ICAP_FAILURE:10
@@ -77,20 +79,20 @@ msgid "An Illegal response was received from the ICAP server."
 msgstr ""
 
 #: templates/ERR_READ_ERROR:7
-#, fuzzy
 msgid ""
 "An error condition occurred while reading data from the network. Please "
 "retry your request."
 msgstr ""
-"Ցանցից տվյալների ընթերցման ժամանակ առաջացավ սխալ.Խնդրվում է կրկնել հարցումը."
+"Ցանցից տվյալների ընթերցման ընթացքում առաջացավ սխալ.Խնդրվում է կրկնել "
+"հարցումը."
 
 #: templates/ERR_WRITE_ERROR:7
-#, fuzzy
 msgid ""
 "An error condition occurred while writing to the network. Please retry your "
 "request."
 msgstr ""
-"Տվյալները ցանց ուղարկելու ժամանակ առաջացավ սխալ․ Խնդրվում է կրկնել հարցումը․"
+"Տվյալները ցանցում գրանցելու ընթացքում առաջացավ սխալ․ Խնդրվում է կրկնել "
+"հարցումը․"
 
 #: templates/ERR_CACHE_ACCESS_DENIED:3 templates/ERR_CACHE_ACCESS_DENIED:5
 msgid "Cache Access Denied."
@@ -102,12 +104,13 @@ msgid "Cache Manager Access Denied."
 msgstr "Քեշի կառավառման մուտքն արգելված է."
 
 #: templates/ERR_URN_RESOLVE:5
+#, fuzzy
 msgid "Cannot Resolve URN"
-msgstr ""
+msgstr "Cannot Resolve URN"
 
 #: templates/ERR_LIFETIME_EXP:5
 msgid "Connection Lifetime Expired"
-msgstr "Կապ հաստատման ժամանակը սպառվեց "
+msgstr "Կապի հաստատման ժամանակը սպառվեց"
 
 #: templates/ERR_CONNECT_FAIL:5
 msgid "Connection to %I failed."
@@ -119,7 +122,7 @@ msgstr "POST կամ PUT հարցումների համար Content-Length չի ն
 
 #: templates/ERR_DIR_LISTING:3
 msgid "Directory Content:"
-msgstr ""
+msgstr "Դիրեկտորիայի պարունակությունը:"
 
 #: templates/ERR_DIR_LISTING:4
 msgid "Directory Listing"
@@ -127,11 +130,11 @@ msgstr ""
 
 #: templates/ERR_DIR_LISTING:1
 msgid "Directory: %U"
-msgstr ""
+msgstr "Դիրեկտորիա: %U"
 
 #: templates/ERR_DIR_LISTING:2
 msgid "Directory: <a href=\"%U\">%U</a>/"
-msgstr ""
+msgstr "Դիրեկտորիա: <a href=\"%U\">%U</a>/"
 
 #: templates/ERR_ACCESS_DENIED:2 templates/ERR_AGENT_CONFIGURE:2
 #: templates/ERR_AGENT_WPAD:2 templates/ERR_CACHE_ACCESS_DENIED:2
@@ -159,11 +162,11 @@ msgstr "ՍԽԱԼ: Մուտքը քեշին արգելված է"
 
 #: templates/ERR_CACHE_MGR_ACCESS_DENIED:1
 msgid "ERROR: Cache Manager Access Denied"
-msgstr "Սխալ: Քեշի կառավառման մուտքն արգելված է"
+msgstr "ՍԽԱԼ: Քեշի կառավառման մուտքն արգելված է"
 
 #: templates/ERR_FTP_PUT_ERROR:1
 msgid "ERROR: FTP upload failed"
-msgstr "ՍԽԱԼ: FTP upload գործողությունը խափանվեց"
+msgstr "ՍԽԱԼ; FTP upload գործողությունը խափանվեց"
 
 #: templates/ERR_ACCESS_DENIED:1 templates/ERR_CANNOT_FORWARD:1
 #: templates/ERR_CONNECT_FAIL:1 templates/ERR_DNS_FAIL:1 templates/ERR_ESI:1
@@ -180,24 +183,21 @@ msgstr "ՍԽԱԼ: FTP upload գործողությունը խափանվեց"
 #: templates/ERR_UNSUP_REQ:1 templates/ERR_WRITE_ERROR:1
 #: templates/ERR_ZERO_SIZE_OBJECT:1
 msgid "ERROR: The requested URL could not be retrieved"
-msgstr "ՍԽԱԼ: Պահանջվող URL չի կարող առաքվել"
+msgstr "ՍԽԱԼ: Պահանջվող URL-ն հնարավոր չէ ստանալ"
 
 #: templates/ERR_URN_RESOLVE:1
-#, fuzzy
 msgid "ERROR: The requested URN could not be retrieved"
-msgstr "ՍԽԱԼ: Պահանջվող URL չի կարող առաքվել"
+msgstr "ՍԽԱԼ: Պահանջվող URL-ն հնարավոր չէ ստանալ"
 
 #: templates/ERR_ESI:5
 msgid "ESI Processing failed."
 msgstr ""
 
 #: templates/ERR_FTP_PUT_CREATED:1 templates/ERR_FTP_PUT_MODIFIED:1
-#, fuzzy
 msgid "FTP PUT Successful."
 msgstr "FTP PUT Գործողությունը հաջողվեց: Ֆայլը ստեղծված է"
 
 #: templates/ERR_FTP_PUT_ERROR:3
-#, fuzzy
 msgid "FTP PUT upload failed"
 msgstr "FTP upload գործողությունը խափանվեց"
 
@@ -207,7 +207,7 @@ msgstr "FTP արձանագրությունն արգելված է"
 
 #: templates/ERR_SECURE_CONNECT_FAIL:5
 msgid "Failed to establish a secure connection to %I"
-msgstr ""
+msgstr "Չհաջողվեց անվտանգ կապ հաստատել %I"
 
 #: templates/ERR_FTP_PUT_CREATED:3
 msgid "File created"
@@ -219,15 +219,15 @@ msgstr "Ֆայլը թարմացված է"
 
 #: templates/ERR_AGENT_CONFIGURE:6 templates/ERR_AGENT_WPAD:6
 msgid "For Firefox browsers go to: <ul>"
-msgstr ""
+msgstr "Firefox բրաուզերի համար այցելեք: <ul>"
 
 #: templates/ERR_AGENT_CONFIGURE:9 templates/ERR_AGENT_WPAD:8
 msgid "For Internet Explorer browsers go to: <ul>"
-msgstr ""
+msgstr "Internet Explorer բրաուզերի համար այցելեք: <ul>"
 
 #: templates/ERR_AGENT_CONFIGURE:12 templates/ERR_AGENT_WPAD:11
 msgid "For Opera browsers go to: <ul>"
-msgstr ""
+msgstr "Opera բրաուզերի համար այցելեք: <ul>"
 
 #: templates/ERR_FORWARDING_DENIED:5
 msgid "Forwarding Denied."
@@ -253,12 +253,15 @@ msgstr "Վերահասցեագրումն արգելված է."
 #: templates/ERR_URN_RESOLVE:8 templates/ERR_WRITE_ERROR:9
 #: templates/ERR_ZERO_SIZE_OBJECT:8
 msgid "Generated %T by %h (%s)"
-msgstr ""
+msgstr "Ստեղծված է %T by %h (%s)"
 
 #: templates/ERR_INVALID_REQ:12
+#, fuzzy
 msgid ""
 "HTTP/1.1 <q>Expect:</q> feature is being asked from an HTTP/1.0 software."
 msgstr ""
+"HTTP/1.1 <q>Expect:</q> հատկության համար հարցում է կատարվում HTTP/1.0 "
+"ծրագրային միջոցից"
 
 #: templates/ERR_URN_RESOLVE:6
 msgid "Hey, don't expect too much from URNs on %T :)"
@@ -266,40 +269,46 @@ msgstr "Չարժե շատ բան սպասել URN-ից %T -ի վրա :)"
 
 #: templates/ERR_AGENT_CONFIGURE:5 templates/ERR_AGENT_WPAD:5
 msgid "How to find these settings in your browser:"
-msgstr ""
+msgstr "Ինչպես փնտրել այս կարգաբերումները քո բրաուզերում:"
 
 #: templates/ERR_ICAP_FAILURE:5
 msgid "ICAP protocol error."
 msgstr ""
 
 #: templates/ERR_TOO_BIG:7
+#, fuzzy
 msgid ""
 "If you are making a GET request, then the item you are trying to download is "
 "too large."
 msgstr ""
+"Եթե Դուք GET հարցում եք ձևակերպում, ապա տարրը ,որը Դուք փորձում եք "
+"բեռնավորել, շատ մեծ ծավալ ունի."
 
 #: templates/ERR_TOO_BIG:6
+#, fuzzy
 msgid ""
 "If you are making a POST or PUT request, then the item you are trying to "
 "upload is too large."
 msgstr ""
+"Եթե Դուք POST կամ PUT  հարցում եք ձևակերպում, ապա տարրը ,որը Դուք փորձում եք "
+"բեռնավորել, շատ մեծ ծավալ ունի"
 
 #: templates/ERR_INVALID_REQ:11 templates/ERR_INVALID_URL:11
 msgid "Illegal character in hostname; underscores are not allowed."
-msgstr "Անթույլատրելի նիշ սերվերի անվան մեջ;ընդգծման նիշն անթույլատրելի է"
+msgstr "Անթույլատրելի նիշ սերվերի անվան մեջ; ընդգծման նիշն անթույլատրելի է"
 
 #: templates/ERR_INVALID_URL:10
 msgid "Illegal double-escape in the URL-Path"
-msgstr "Անթույլատրելի կրկնակի կառավարող նիշ URL ուղղում"
+msgstr "Անթույլատրելի կրկնակի կառավարող նիշ URL-ի ուղիում"
 
 #: templates/ERR_AGENT_CONFIGURE:8 templates/ERR_AGENT_CONFIGURE:11
 #: templates/ERR_AGENT_CONFIGURE:14
 msgid "In the HTTP proxy box type the proxy name %h and port 3128."
-msgstr ""
+msgstr "HTTP proxy դաշտում նշիր proxy name %h և port 3128."
 
 #: templates/ERR_INVALID_URL:5
 msgid "Invalid URL"
-msgstr ""
+msgstr "Սխալ URL"
 
 #: templates/ERR_INVALID_REQ:8
 msgid "Missing HTTP Identifier (HTTP/1.0)."
@@ -326,7 +335,7 @@ msgstr "Հարցման մեթոդը բացակայում է կամ անհայտ
 
 #: templates/ERR_NO_RELAY:5
 msgid "No Wais Relay"
-msgstr "Wais Relay որոշված չէ "
+msgstr "Wais Relay-ը որոշված չէ"
 
 #: templates/ERR_FTP_PUT_CREATED:2 templates/ERR_FTP_PUT_MODIFIED:2
 msgid "Operation successful"
@@ -334,7 +343,7 @@ msgstr "Գործողությունը հաջողվեց"
 
 #: templates/ERR_DIR_LISTING:5
 msgid "Parent Directory"
-msgstr ""
+msgstr "Ծնողական դիրեկտորիա"
 
 #: templates/ERR_CACHE_ACCESS_DENIED:7
 msgid ""
@@ -371,47 +380,42 @@ msgstr "Հարցման ծավալը շատ մեծ է"
 
 #: templates/ERR_AGENT_WPAD:10
 msgid "Select Automatically detect settings"
-msgstr ""
+msgstr "Ընտրեք Automatically detect settings"
 
 #: templates/ERR_AGENT_WPAD:13
 msgid "Select Use Automatic proxy configuration"
-msgstr ""
+msgstr "Ընտրեք Use Automatic proxy configuration"
 
 #: templates/ERR_SOCKET_FAILURE:5
 msgid "Socket Failure"
-msgstr "Socket ձախողում "
+msgstr "Socket ձախողում"
 
 #: templates/ERR_INVALID_URL:6
-#, fuzzy
 msgid "Some aspect of the requested URL is incorrect."
 msgstr "URL-ի որոշ ասպեկտներ սխալ են."
 
 #: templates/ERR_ICAP_FAILURE:8 templates/ERR_INVALID_REQ:5
 #: templates/ERR_INVALID_URL:7
-#, fuzzy
 msgid "Some possible problems are:"
 msgstr "Հնարավոր պատճառներն են:"
 
 #: templates/ERR_CACHE_MGR_ACCESS_DENIED:6
-#, fuzzy
 msgid ""
 "Sorry, you are not currently allowed to request %U from this cache manager "
 "until you have authenticated yourself."
 msgstr ""
-"Õ\86Õ¥Ö\80Õ¸Õ²Õ¸Ö\82Õ©ÕµÕ¸Ö\82Õ¶,Ô´Õ¸Ö\82Ö\84 Õ¹Õ¥Ö\84 Õ¯Õ¡Ö\80Õ¸Õ² Ö\84Õ¥Õ·Õ« Õ¯Õ¡Õ¼Õ¡Õ¾Õ¡Ö\80Õ´Õ¡Õ¶ Õ°Õ¡Õ´Õ¡Õ¯Õ¡Ö\80Õ£Õ«Ö\81 Õ¯Õ¡Õ¿Õ¡Ö\80ել հետևյալ "
+"Õ\86Õ¥Ö\80Õ¸Õ²Õ¸Ö\82Õ©ÕµÕ¸Ö\82Õ¶,Ô´Õ¸Ö\82Ö\84 Õ¹Õ¥Ö\84 Õ¯Õ¡Ö\80Õ¸Õ² Ö\84Õ¥Õ·Õ« Õ¯Õ¡Õ¼Õ¡Õ¾Õ¡Ö\80Õ´Õ¡Õ¶ Õ°Õ¡Õ´Õ¡Õ¯Õ¡Ö\80Õ£Õ«Ö\81 Õ«Ö\80Õ¡Õ¯Õ¡Õ¶Õ¡Ö\81Õ¶ել հետևյալ "
 "հարցումը %U մինչև աութենտիֆիկացիան չանցնեք."
 
 #: templates/ERR_CACHE_ACCESS_DENIED:6
-#, fuzzy
 msgid ""
 "Sorry, you are not currently allowed to request %U from this cache until you "
 "have authenticated yourself."
 msgstr ""
-"Õ\86Õ¥Ö\80Õ¸Õ²Õ¸Ö\82Õ©ÕµÕ¸Ö\82Õ¶,Ô´Õ¸Ö\82Ö\84 Õ¹Õ¥Ö\84 Õ¯Õ¡Ö\80Õ¸Õ² Õ¯Õ¡Õ¿Õ¡Ö\80ել հետևյալ հարցումը %U մինչև "
+"Õ\86Õ¥Ö\80Õ¸Õ²Õ¸Ö\82Õ©ÕµÕ¸Ö\82Õ¶,Ô´Õ¸Ö\82Ö\84 Õ¹Õ¥Ö\84 Õ¯Õ¡Ö\80Õ¸Õ² Õ«Ö\80Õ¡Õ¯Õ¡Õ¶Õ¡Ö\81Õ¶ել հետևյալ հարցումը %U մինչև "
 "աութենտիֆիկացիան չանցնեք."
 
 #: templates/ERR_ZERO_SIZE_OBJECT:6
-#, fuzzy
 msgid "Squid did not receive any data for this request."
 msgstr "Քեշը ի պատասխան այս հարցումի ոչ մի տվյալ չի ստացել."
 
@@ -420,9 +424,8 @@ msgid ""
 "Squid does not support all request methods for all access protocols. For "
 "example, you can not POST a Gopher request."
 msgstr ""
-"Squid-ը բոլոր արձանագրությունների համար բոլոր հարցման մեթոդները չի "
-"ուղեկցում . Օրինակ,Gopher արձանագրության համար չեք կարող POST հարցում "
-"կատարել. "
+"Squid-ը բոլոր արձանագրությունների համար բոլոր հարցման մեթոդները չի աջակցում. "
+"Օրինակ, Gopher արձանագրության համար չեք կարող POST հարցում կատարել."
 
 #: templates/ERR_LIFETIME_EXP:6
 msgid ""
@@ -430,53 +433,51 @@ msgid ""
 "connection lifetime."
 msgstr ""
 "Squid-ը ընդհատեց հարցումը կապ հաստատման առավելագույն ժամանակը գերազանցելու "
-"պատճառով․."
+"պատճառով"
 
 #: templates/ERR_SOCKET_FAILURE:7
 msgid ""
 "Squid is unable to create a TCP socket, presumably due to excessive load. "
 "Please retry your request."
 msgstr ""
-"Squid-ը չի կարող ստեղծել TCP Socket, հավանաբար գերբեռնվածության պատճառով"
-"Խնդրվում է կրկնել հարցումը․ Եթե իրավիճակը կրկնվի, դիմեք քեշի կառավարիչին․ "
+"Squid-ը չի կարող ստեղծել TCP Socket, հավանաբար գերբեռնվածության պատճառով"
+"Խնդրվում է կրկնել հարցումը: Եթե իրավիճակը կրկնվի, դիմեք քեշի կառավարիչին․:"
 
 #: templates/ERR_FTP_FAILURE:5 templates/ERR_FTP_FORBIDDEN:5
 #: templates/ERR_FTP_NOT_FOUND:5 templates/ERR_FTP_PUT_ERROR:5
 #: templates/ERR_FTP_UNAVAILABLE:5
 msgid "Squid sent the following FTP command:"
-msgstr "Squid-ը ուղարկեց հետևյալ FTP հրամանը: "
+msgstr "Squid-ը ուղարկեց հետևյալ FTP հրամանը:"
 
 #: templates/ERR_DNS_FAIL:6
 msgid "The DNS server returned:"
-msgstr "DNS սերվերի պատասխանը: "
+msgstr "DNS սերվերի պատասխանը:"
 
 #: templates/ERR_ESI:6
+#, fuzzy
 msgid "The ESI processor returned:"
-msgstr ""
+msgstr "ESI պրոցեսորը պատասխանեց:"
 
 #: templates/ERR_FTP_UNAVAILABLE:4
-#, fuzzy
 msgid "The FTP server was too busy to retrieve the URL: <a href=\"%U\">%U</a>"
-msgstr ""
-"URL-ի առաքման ժամանակ FTP սերվերը շատ զբաղված էր: <a href=\"%U\">%U</a>"
+msgstr "URL-ի ստացման ընթացքում FTP սերվերը շատ զբաղված էր: <a href=\"%U\">%U</a>"
 
 #: templates/ERR_INVALID_RESP:5
-#, fuzzy
 msgid ""
 "The HTTP Response message received from the contacted server could not be "
 "understood or was otherwise malformed. Please contact the site operator."
 msgstr ""
-"Սերվերից ստացվող պատասխանն անհասկանալի է կամ այլայլվածԴիմեք տվյալ կայքի "
-"կառավարիչներին։Ձեր քեշի կառավարիչը անհրաժեշտության դեպքում կարող է ավելի "
-"մանրակրկիտ նկարագրել խնդրի բնւյթը."
+"Սերվերից ստացվող պատասխանն անհասկանալի է կամ այլայլվածԴիմեք տվյալ կայքի "
+"կառավարիչներին։ Ձեր քեշի կառավարիչը անհրաժեշտության դեպքում կարող է ավելի "
+"մանրակրկիտ նկարագրել խնդրի բնւյթը:"
 
 #: templates/ERR_ICAP_FAILURE:9
 msgid "The ICAP server is not reachable."
-msgstr ""
+msgstr "ICAP սերվերը անհասանելի է:"
 
 #: templates/ERR_FTP_NOT_FOUND:4
 msgid "The following URL could not be retrieved: <a href=\"%U\">%U</a>"
-msgstr "Հետևյալ URL չի կարող առաքվել: <a href=\"%U\">%U</a>"
+msgstr "Հետևյալ URL-ն հնարավոր չէ ստանալ: <a href=\"%U\">%U</a>"
 
 #: templates/ERR_ACCESS_DENIED:4 templates/ERR_CACHE_ACCESS_DENIED:4
 #: templates/ERR_CACHE_MGR_ACCESS_DENIED:4 templates/ERR_CANNOT_FORWARD:4
@@ -493,23 +494,21 @@ msgstr "Հետևյալ URL չի կարող առաքվել: <a href=\"%U\">%U</a>
 msgid ""
 "The following error was encountered while trying to retrieve the URL: <a "
 "href=\"%U\">%U</a>"
-msgstr ""
+msgstr "URL-ի ստացման ընթացքում առաջացավ հետևյալ սխալը: <a href=\"%U\">%U</a>"
 
 #: templates/ERR_URN_RESOLVE:4
 msgid ""
 "The following error was encountered while trying to retrieve the URN: <a "
 "href=\"%U\">%U</a>"
-msgstr ""
+msgstr "URN-ի ստացման ընթացքում առաջացավ հետևյալ սխալը: <a href=\"%U\">%U</a>"
 
 #: templates/ERR_CONNECT_FAIL:7
-#, fuzzy
 msgid "The remote host or network may be down. Please try the request again."
-msgstr ""
-"Հեռակա հանգույցը կամ ցանցը չեն պատասխանում. Խնդրվում է կրկնել հարցումը. "
+msgstr "Հեռակա հանգույցը կամ ցանցը չեն պատասխանում: Խնդրվում է կրկնել հարցումը:"
 
 #: templates/ERR_TOO_BIG:5
 msgid "The request or reply is too large."
-msgstr "Հարցումը կամ պատասխանը շատ մեծ ծավալ ունեն. "
+msgstr "Հարցումը կամ պատասխանը շատ մեծ ծավալ ունեն."
 
 #: templates/ERR_ACCESS_DENIED:3 templates/ERR_CANNOT_FORWARD:3
 #: templates/ERR_CONNECT_FAIL:3 templates/ERR_DNS_FAIL:3 templates/ERR_ESI:3
@@ -525,7 +524,7 @@ msgstr "Հարցումը կամ պատասխանը շատ մեծ ծավալ ու
 #: templates/ERR_TOO_BIG:3 templates/ERR_UNSUP_REQ:3
 #: templates/ERR_WRITE_ERROR:3 templates/ERR_ZERO_SIZE_OBJECT:3
 msgid "The requested URL could not be retrieved"
-msgstr "Պահանջվող URL չի կարող առաքվել"
+msgstr "Պահանջվող URL-ն հնարավոր չէ ստանալ"
 
 #: templates/ERR_FTP_FAILURE:6 templates/ERR_FTP_FORBIDDEN:6
 #: templates/ERR_FTP_NOT_FOUND:6 templates/ERR_FTP_PUT_ERROR:6
@@ -541,11 +540,10 @@ msgid "The system returned: <i>%E</i>"
 msgstr "Ստացված պատասխանը: <i>%E</i>"
 
 #: templates/ERR_NO_RELAY:6
-#, fuzzy
 msgid ""
 "There is no WAIS Relay host defined for this Cache! Yell at the "
 "administrator."
-msgstr "Այս քեշի համար WAIS Relay որոշված չէ! Հայտնեք կառավարիչին. "
+msgstr "Այս քեշի համար WAIS Relay-ը որոշված չէ! Հայտնեք կառավարիչին:"
 
 #: templates/ERR_TOO_BIG:8
 msgid ""
@@ -553,69 +551,74 @@ msgid ""
 "operates this cache. Please contact them directly if you feel this is an "
 "error."
 msgstr ""
+"Այս սահմանափակումը իրականացված է Ձեր ինտերնետ կապ ապահովողի կողմից: Եթե Դուք "
+"սա սխալ եք համարում, դիմեք նրան:"
 
 #: templates/ERR_UNSUP_HTTPVERSION:6
 msgid "This Squid does not accept the HTTP version you are attempting to use."
 msgstr ""
+"HTTP արձանագրության այն տեսակը,որը Դուք փորձում եք օգտագործել,այս Squid-ը չի "
+"ընդունում:"
 
 #: templates/ERR_FTP_DISABLED:6
 msgid "This cache does not support FTP."
-msgstr ""
+msgstr "Այս քեշը FTP արձանագրություն չի աջակցում"
 
 #: templates/ERR_SHUTTING_DOWN:5
-#, fuzzy
 msgid ""
 "This cache is in the process of shutting down and can not service your "
 "request at this time. Please retry your request again soon."
 msgstr ""
 "Այս քեշը տվյալ պահին գտնվում է անջատման պրոցեսում և չի կարող սպասարկել Ձեր "
-"հարցումը․Կրկնեք հարցումը որոշ ժամանակ անց․"
+"հարցումը: Կրկնեք հարցումը որոշ ժամանակ անց:"
 
 #: templates/ERR_FORWARDING_DENIED:6
-#, fuzzy
 msgid ""
 "This cache will not forward your request because it is trying to enforce a "
 "sibling relationship. Perhaps the client at %i is a cache which has been "
 "misconfigured."
 msgstr ""
 "Այս քեշը անկարող է վերահասցեագրել Ձեր հարցումը sibling տիպի "
-"փոխհարաբերություններ հաստատելու պատճառով. Հավանական է,որ %i -ն սխալ "
+"փոխհարաբերություններ հաստատելու պատճառով: Հավանական է, որ %i -ն սխալ "
 "սարքաբերված քեշ է."
 
 #: templates/ERR_ICAP_FAILURE:7
 msgid "This means that some aspect of the ICAP communication failed."
-msgstr ""
+msgstr "Սա նշանակում է, որ ICAP կոմունիկացիայի որոշ ասպեկտներ սխալ են:"
 
 #: templates/ERR_FTP_PUT_ERROR:7
 msgid ""
 "This means that the FTP server may not have permission or space to store the "
 "file. Check the path, permissions, diskspace and try again."
 msgstr ""
+"Սա նշանակում է,որ FTP սերվերը ֆայլը պահպանելու համար բավարար հիշողության "
+"ծավալ կամ թույտվություն չունի: Ստուգեք ճանապարհը, հիշողության ծավալը, մուտքի "
+"իրավունքները և կրկին փորձեք:"
 
 #: templates/ERR_DNS_FAIL:7
-#, fuzzy
 msgid ""
 "This means that the cache was not able to resolve the hostname presented in "
 "the URL. Check if the address is correct."
 msgstr ""
-"Սա նշանակում է Քեշը ի վիճակի չէ որոշել URL ում նշված սերվերի հասցեն. Ստուգեք "
-"Õ°Õ¡Õ½Ö\81Õ¥Õ« Õ¶Õ¥Ö\80Õ´Õ¸Ö\82Õ®Õ´Õ¡Õ¶ Õ³Õ·Õ¿Õ¸Ö\82Õ©ÕµÕ¸Ö\82Õ¶Õ¨. "
+"Սա նշանակում է, որ քեշը ի վիճակի չէ որոշել URL- ում նշված սերվերի հասցեն: "
+"Õ\8dÕ¿Õ¸Ö\82Õ£Õ¥Ö\84 Õ°Õ¡Õ½Ö\81Õ¥Õ« Õ¶Õ¥Ö\80Õ´Õ¸Ö\82Õ®Õ´Õ¡Õ¶ Õ³Õ·Õ¿Õ¸Ö\82Õ©ÕµÕ¸Ö\82Õ¶Õ¨:"
 
 #: templates/ERR_ESI:7
 msgid ""
 "This means that the surrogate was not able to process the ESI template. "
 "Please report this error to the webmaster."
 msgstr ""
+"Սա նշանակում է, որ փոխարինողը ի վիճակի չէ մշակել ESI կաղապարը:Խնդրվում է "
+"հայտնել այս մասին քեշի կառավարիչին:"
 
 #: templates/ERR_FTP_NOT_FOUND:7
-#, fuzzy
 msgid ""
 "This might be caused by an FTP URL with an absolute path (which does not "
 "comply with RFC 1738). If this is the cause, then the file can be found at "
 "<a href=\"%B\">%B</a>."
 msgstr ""
-"Õ\8dÕ¡ Õ¯Õ¡Ö\80Õ¸Õ² Õ§ Õ¬Õ«Õ¶Õ¥Õ¬ FTP URL -Õ« Õ¢Õ¡Ö\81Õ¡Ö\80Õ±Õ¡Õ¯ Õ¸Ö\82Õ²Õ²ով հարցման արդյունք (ինչը չի "
-"համապատասխանում RFC 1738-ին).  Եթե սա է սխալի պատճառը,ապա ֆայլը կարող է "
+"Õ\8dÕ¡ Õ¯Õ¡Ö\80Õ¸Õ² Õ§ Õ¬Õ«Õ¶Õ¥Õ¬ FTP URL -Õ« Õ¢Õ¡Ö\81Õ¡Ö\80Õ±Õ¡Õ¯ Õ¸Ö\82Õ²Õ«ով հարցման արդյունք (ինչը չի "
+"համապատասխանում RFC 1738-ին). Եթե սա է սխալի պատճառը, ապա ֆայլը կարող է "
 "գնտվել այստեղ <a href=\"%B\">%B</a>."
 
 #: templates/ERR_SECURE_CONNECT_FAIL:7
@@ -627,7 +630,6 @@ msgid ""
 msgstr ""
 
 #: templates/ERR_CANNOT_FORWARD:6
-#, fuzzy
 msgid ""
 "This request could not be forwarded to the origin server or to any parent "
 "caches. The most likely cause for this error is that the cache administrator "
@@ -635,24 +637,30 @@ msgid ""
 "all configured parent caches are currently unreachable."
 msgstr ""
 "Այս հարցումը հնարավոր չէ վերահասցեագրել սկզբնաղբյուր սերվերին կամ ծնողական "
-"քեշերից որևէ մեկին․Սխալի ամենահավանական պատճառներն են Այս սերվերի կառավարիչը "
-"Õ¡Ö\80Õ£Õ¥Õ¬Õ¥Õ¬ Õ§ Õ¢Õ¸Õ¬Õ¸Ö\80 Õ¸Ö\82Õ²Õ«Õ² Õ´Õ«Õ¡Ö\81Õ¸Ö\82Õ´Õ¶Õ¥Ö\80Õ¨ Õ½Õ¯Õ¦Õ¢Õ¶Õ¡Õ²Õ¢ÕµÕ¸Ö\82Ö\80 Õ½Õ¥Ö\80Õ¾Õ¥Ö\80Õ¶Õ¥Ö\80Õ« Õ°Õ¥Õ¿ Ô²Õ¸Õ¬Õ¸Ö\80 Õ®Õ¶Õ¸Õ²Õ¡Õ¯Õ¡Õ¶ "
-"քեշերը տվյալ պահին անհասանելի են."
+"քեշերից որևէ մեկին: Սխալի ամենահավանական պատճառներն են` այս սերվերի "
+"Õ¯Õ¡Õ¼Õ¡Õ¾Õ¡Ö\80Õ«Õ¹Õ¨ Õ¡Ö\80Õ£Õ¥Õ¬Õ¥Õ¬ Õ§ Õ¢Õ¸Õ¬Õ¸Ö\80 Õ¸Ö\82Õ²Õ«Õ² Õ´Õ«Õ¡Ö\81Õ¸Ö\82Õ´Õ¶Õ¥Ö\80Õ¨ Õ½Õ¯Õ¦Õ¢Õ¶Õ¡Õ²Õ¢ÕµÕ¸Ö\82Ö\80 Õ½Õ¥Ö\80Õ¾Õ¥Ö\80Õ¶Õ¥Ö\80Õ« Õ°Õ¥Õ¿ Õ¯Õ¡Õ´ "
+"բոլոր ծնողական քեշերը տվյալ պահին անհասանելի են:"
 
 #: templates/ERR_AGENT_CONFIGURE:10 templates/ERR_AGENT_WPAD:9
 msgid ""
 "Tools -&gt; Internet Options -&gt; Connection -&gt; LAN Settings -&gt;Proxy"
 msgstr ""
+"Գործիքներ -&gt; Ինտերնետ կարգաբերումներ -&gt; Կապ -&gt; LAN կարգաբերումներ "
+"-&gt;Պրոքսի"
 
 #: templates/ERR_AGENT_CONFIGURE:7 templates/ERR_AGENT_WPAD:7
 msgid ""
 "Tools -&gt; Options -&gt; Advanced -&gt; Network -&gt; Connection Settings"
 msgstr ""
+"Գործիքներ -&gt; Կարգաբերումներ -&gt; Լրացուցիչ -&gt; Ցանց -&gt; Կապի "
+"կարգաբերումներ"
 
 #: templates/ERR_AGENT_CONFIGURE:13 templates/ERR_AGENT_WPAD:12
 msgid ""
 "Tools -&gt; Preferences -&gt; Advanced -&gt; Network -&gt; Proxy Servers"
 msgstr ""
+"Գործիքներ -&gt; Նախընտրություններ -&gt; Լրացուցիչ -&gt; Ցանց -&gt; Պրոքսի "
+"սերվերներ"
 
 #: templates/ERR_DNS_FAIL:5
 msgid "Unable to determine IP address from host name <q>%H</q>"
@@ -660,15 +668,15 @@ msgstr "Անհնար է որոշել <q>%H</q> հանգույցի IP հասցե
 
 #: templates/ERR_CANNOT_FORWARD:5
 msgid "Unable to forward this request at this time."
-msgstr "Õ\80Õ¶Õ¡Ö\80Õ¡Õ¾Õ¸Ö\80 Õ¹Õ§ Õ¾Õ¥Ö\80Õ¡Õ°Õ¡Õ½Ö\81Õ¥Õ¡Õ£Ö\80Õ¥Õ¬ Õ\81Õ¥Ö\80 Õ°Õ¡Ö\80Ö\81Õ¸Ö\82Õ´Õ¨ Õ¿Õ¾ÕµÕ¡Õ¬ ÕºÕ¡Õ°Õ«Õ¶."
+msgstr "Õ\81Õ¥Ö\80 Õ°Õ¡Ö\80Ö\81Õ¸Ö\82Õ´Õ¨ Õ°Õ¶Õ¡Ö\80Õ¡Õ¾Õ¸Ö\80 Õ¹Õ§ Õ¾Õ¥Ö\80Õ¡Õ°Õ¡Õ½Ö\81Õ¥Õ¡Õ£Ö\80Õ¥Õ¬ Õ¿Õ¾ÕµÕ¡Õ¬ ÕºÕ¡Õ°Õ«Õ¶"
 
 #: templates/ERR_UNSUP_HTTPVERSION:3 templates/ERR_UNSUP_HTTPVERSION:5
 msgid "Unsupported HTTP version"
-msgstr ""
+msgstr "HTTP արձանագրության այս վարկածը չի աջակցվում"
 
 #: templates/ERR_UNSUP_REQ:5
 msgid "Unsupported Request Method and Protocol"
-msgstr "Õ\89Õ¸Ö\82Õ²Õ¥Õ¯Ö\81Õ¾Õ¸Õ² Õ´Õ¥Õ©Õ¸Õ¤ Ö\87 Õ°Õ¡Ö\80Ö\81Õ´Õ¡Õ¶ Õ¡Ö\80Õ±Õ¡Õ¶Õ¡Õ£Ö\80Õ¸Ö\82Õ©ÕµÕ¸Ö\82Õ¶ "
+msgstr "Õ\80Õ¡Ö\80Ö\81Õ¸Ö\82Õ´ Õ«Ö\80Õ¡Õ¯Õ¡Õ¶Õ¡Ö\81Õ¶Õ¥Õ¬Õ¸Ö\82 Õ´Õ¥Õ©Õ¸Õ¤Õ¨ Ö\87 Õ¡Ö\80Õ±Õ¡Õ¶Õ¡Õ£Ö\80Õ¸Ö\82Õ©ÕµÕ¸Ö\82Õ¶Õ¨ Õ¹Õ¥Õ¶ Õ¡Õ»Õ¡Õ¯Ö\81Õ¾Õ¸Ö\82Õ´"
 
 #: templates/ERR_ONLY_IF_CACHED_MISS:5
 msgid ""
@@ -679,11 +687,11 @@ msgstr "Օբյեկտը քեշում գտնված չէ; ձևավորվեց <q>onl
 #: templates/ERR_AGENT_CONFIGURE:1 templates/ERR_AGENT_CONFIGURE:3
 #: templates/ERR_AGENT_WPAD:1 templates/ERR_AGENT_WPAD:3
 msgid "Web Browser Configuration"
-msgstr ""
+msgstr "Վեբ բրաուզերի կարգաբերումներ"
 
 #: templates/ERR_WRITE_ERROR:5
 msgid "Write Error"
-msgstr "Գրանցման սխալ "
+msgstr "Գրանցման սխալ"
 
 #: templates/ERR_ONLY_IF_CACHED_MISS:6
 msgid ""
@@ -691,11 +699,14 @@ msgid ""
 "directive. The document was not found in the cache, <em>or</em> it required "
 "revalidation prohibited by the <q>only-if-cached</q> directive."
 msgstr ""
+"Դուք իրականացրեցիք հարցում <q>only-if-cached</q> քեշի կառավարման դիրեկտիվով: "
+"Փաստաթուղթը քեշում բացակայում է <em>կամ</em պահանջվում է <q>only-if-"
+"cached</q> դիրեկտիվի կողմից արգելված հաստատում:"
 
 #: templates/ERR_AGENT_CONFIGURE:4 templates/ERR_AGENT_WPAD:4
 msgid ""
 "Your Web Browser configuration needs to be corrected to use this network."
-msgstr ""
+msgstr "Այս ցանցից օգտվելու համար Ձեր բրաուզերը անհրաժեշտ է կարգաբերել"
 
 #: templates/ERR_ACCESS_DENIED:7 templates/ERR_AGENT_CONFIGURE:15
 #: templates/ERR_AGENT_WPAD:14 templates/ERR_CANNOT_FORWARD:7
@@ -716,22 +727,21 @@ msgid "Your cache administrator is <a href=\"mailto:%w%W\">%w</a>."
 msgstr "Ձեր քեշի կառավարիչը <a href=\"mailto:%w%W\">%w</a> է."
 
 #: templates/ERR_INVALID_RESP:6
-#, fuzzy
 msgid ""
 "Your cache administrator may be able to provide you with more details about "
 "the exact nature of the problem if needed."
 msgstr ""
-"Սերվերից ստացվող պատասխանն անհասկանալի է կամ այլայլվածԴիմեք տվյալ կայքի "
+"Սերվերից ստացվող պատասխանն անհասկանալի է կամ այլայլվածԴիմեք տվյալ կայքի "
 "կառավարիչներին։ Ձեր քեշի կառավարիչը անհրաժեշտության դեպքում կարող է ավելի "
-"մանրակրկիտ նկարագրել խնդրի բնւյթը"
+"մանրակրկիտ նկարագրել խնդրի բնւյթը:"
 
 #: templates/ERR_ESI:8
 msgid "Your webmaster is <a href=\"mailto:%w\">%w</a>."
-msgstr ""
+msgstr "Ձեր կայքի կառավարիչը <a href=\"mailto:%w\">%w</a>"
 
 #: templates/ERR_ZERO_SIZE_OBJECT:5
 msgid "Zero Sized Reply"
-msgstr "Զրոյական երկարությամբ պատասխան "
+msgstr "Զրոյական երկարությամբ պատասխան"
 
 #~ msgid "ERROR: The requested URN not be retrieved"
 #~ msgstr "ՍԽԱԼ: Պահանջվող URN չի կարող առաքվել"
index 0d1486db560e04240617fad13c692ccb0c728b90..bc1b925178f496723bac844b460582a6d22968ec 100644 (file)
@@ -32,13 +32,12 @@ msgid ""
 msgstr "Получен <b>недопустимый ответ</b> при попытке обработки запроса:"
 
 #: templates/ERR_READ_TIMEOUT:7
-#, fuzzy
 msgid ""
 "A Timeout occurred while waiting to read data from the network. The network "
 "or server may be down or congested. Please retry your request."
 msgstr ""
-"Превышено время ожидания ответа во время чтения данных из сети. Сеть или "
-"Ñ\81еÑ\80веÑ\80 Ð½Ðµ Ñ\80абоÑ\82аÑ\8eÑ\82 Ð»Ð¸Ð±Ð¾ Ð¿ÐµÑ\80егÑ\80Ñ\83женÑ\8b. Ð\9fожалÑ\83йÑ\81Ñ\82а, Ð¿Ð¾Ð²Ñ\82оÑ\80иÑ\82е Ð·Ð°Ð¿Ñ\80оÑ\81."
+"Превышен интервал времени ожидания при получении данных из сети. Сеть или "
+"Ñ\81еÑ\80веÑ\80 Ð¼Ð¾Ð³Ñ\83Ñ\82 Ð±Ñ\8bÑ\82Ñ\8cнедоÑ\81Ñ\82Ñ\83пнÑ\8b Ð¸Ð»Ð¸ Ð¿ÐµÑ\80егÑ\80Ñ\83женÑ\8b. Ð\9fовÑ\82оÑ\80иÑ\82е Ð¿Ð¾Ð¿Ñ\8bÑ\82кÑ\83 Ð¿Ð¾Ð·Ð¶Ðµ."
 
 #: templates/ERR_URN_RESOLVE:3
 msgid "A URL for the requested URN could not be retrieved"
@@ -49,15 +48,13 @@ msgid "Access Denied."
 msgstr "Доступ запрещён."
 
 #: templates/ERR_ACCESS_DENIED:6
-#, fuzzy
 msgid ""
 "Access control configuration prevents your request from being allowed at "
 "this time. Please contact your service provider if you feel this is "
 "incorrect."
 msgstr ""
-"Настройка контроля доступа не даёт возможности выполнить Ваш запрос в "
-"настоящее время. Пожалуйста, свяжитесь с Вашим администратором кэша, если Вы "
-"считаете это неправильным."
+"Система контроля доступа не позволяет выполнить ваш запрос сейчас. "
+"Обратитесь к вашему администратору."
 
 #: templates/ERR_FTP_FORBIDDEN:4
 msgid ""
@@ -80,22 +77,16 @@ msgid "An Illegal response was received from the ICAP server."
 msgstr "Получен недопустимый ответ от сервера ICAP."
 
 #: templates/ERR_READ_ERROR:7
-#, fuzzy
 msgid ""
 "An error condition occurred while reading data from the network. Please "
 "retry your request."
-msgstr ""
-"При попытке чтения данных из сети произошла ошибка. Пожалуйста, повторите "
-"запрос."
+msgstr "Ошибка при получении данных их сети. Повторите запрос."
 
 #: templates/ERR_WRITE_ERROR:7
-#, fuzzy
 msgid ""
 "An error condition occurred while writing to the network. Please retry your "
 "request."
-msgstr ""
-"При попытке отправки данных в сеть произошла ошибка. Пожалуйста, повторите "
-"Ваш запрос."
+msgstr "Ошибка отправки данных. Повторите запрос"
 
 #: templates/ERR_CACHE_ACCESS_DENIED:3 templates/ERR_CACHE_ACCESS_DENIED:5
 msgid "Cache Access Denied."
@@ -188,23 +179,22 @@ msgid "ERROR: The requested URL could not be retrieved"
 msgstr "ОШИБКА: Запрошенный URL не может быть получен"
 
 #: templates/ERR_URN_RESOLVE:1
-#, fuzzy
 msgid "ERROR: The requested URN could not be retrieved"
-msgstr "ОШИБКА: Запрошенный URL не может быть получен"
+msgstr "ERROR: Запрошеный URN не может быть получен"
 
 #: templates/ERR_ESI:5
 msgid "ESI Processing failed."
 msgstr "Обработка ESI не удалась."
 
 #: templates/ERR_FTP_PUT_CREATED:1 templates/ERR_FTP_PUT_MODIFIED:1
-#, fuzzy
 msgid "FTP PUT Successful."
-msgstr "Ð\9aоманда FTP PUT Ð·Ð°Ð²ÐµÑ\80Ñ\88илаÑ\81Ñ\8c Ñ\83Ñ\81пеÑ\88но: Ñ\84айл Ñ\81оздан"
+msgstr "Ð\9aопиÑ\80ование Ð»Ð¾ÐºÐ°Ð»Ñ\8cного Ñ\84айла Ð½Ð° FTP-Ñ\81еÑ\80веÑ\80 Ð¼ÐµÑ\82одом PUT Ð·Ð°Ð²ÐµÑ\80Ñ\88ено."
 
 #: templates/ERR_FTP_PUT_ERROR:3
-#, fuzzy
 msgid "FTP PUT upload failed"
-msgstr "Команда FTP PUT (отправка) завершилась аварийно"
+msgstr ""
+"Произошла ошибка во время копирования локального файла на FTP-сервер методом "
+"PUT."
 
 #: templates/ERR_FTP_DISABLED:5
 msgid "FTP is Disabled"
@@ -224,15 +214,15 @@ msgstr "Файл обновлён"
 
 #: templates/ERR_AGENT_CONFIGURE:6 templates/ERR_AGENT_WPAD:6
 msgid "For Firefox browsers go to: <ul>"
-msgstr ""
+msgstr "Для браузера Firefox перейдите в: <ul>"
 
 #: templates/ERR_AGENT_CONFIGURE:9 templates/ERR_AGENT_WPAD:8
 msgid "For Internet Explorer browsers go to: <ul>"
-msgstr ""
+msgstr "Для браузера Internet Explorer перейдите в: <ul>"
 
 #: templates/ERR_AGENT_CONFIGURE:12 templates/ERR_AGENT_WPAD:11
 msgid "For Opera browsers go to: <ul>"
-msgstr ""
+msgstr "Для браузера Opera перейдите в: <ul>"
 
 #: templates/ERR_FORWARDING_DENIED:5
 msgid "Forwarding Denied."
@@ -271,7 +261,7 @@ msgstr "Не стоит ожидать чудес от URN-ов на %T :)"
 
 #: templates/ERR_AGENT_CONFIGURE:5 templates/ERR_AGENT_WPAD:5
 msgid "How to find these settings in your browser:"
-msgstr ""
+msgstr "Эти настройки в вашем браузере:"
 
 #: templates/ERR_ICAP_FAILURE:5
 msgid "ICAP protocol error."
@@ -543,14 +533,13 @@ msgstr ""
 "Для этого кэша не определен узел Wais Relay. Обратитесь к администратору."
 
 #: templates/ERR_TOO_BIG:8
-#, fuzzy
 msgid ""
 "These limits have been established by the Internet Service Provider who "
 "operates this cache. Please contact them directly if you feel this is an "
 "error."
 msgstr ""
-"Эти ограничения установлены администратором, который управляет этим кэшем. "
-"Ð\9fожалÑ\83йÑ\81Ñ\82а, Ñ\81вÑ\8fжиÑ\82еÑ\81Ñ\8c Ñ\81 Ð½Ð¸Ð¼, ÐµÑ\81ли Ð\92Ñ\8b Ñ\81Ñ\87иÑ\82аеÑ\82е Ñ\8dÑ\82о Ð½ÐµÐ¿Ñ\80авилÑ\8cнÑ\8bм."
+"Эти ограничения были установлены администратором. Свяжитесь с ним для "
+"полÑ\83Ñ\87ениÑ\8f Ð¸Ð½Ñ\84оÑ\80маÑ\86ии."
 
 #: templates/ERR_UNSUP_HTTPVERSION:6
 msgid "This Squid does not accept the HTTP version you are attempting to use."
@@ -562,13 +551,12 @@ msgid "This cache does not support FTP."
 msgstr "Этот кэш не поддерживает протокол FTP."
 
 #: templates/ERR_SHUTTING_DOWN:5
-#, fuzzy
 msgid ""
 "This cache is in the process of shutting down and can not service your "
 "request at this time. Please retry your request again soon."
 msgstr ""
-"ЭÑ\82оÑ\82 ÐºÑ\8dÑ\88 Ð½Ð°Ñ\85одиÑ\82Ñ\81Ñ\8f Ð² Ð¿Ñ\80оÑ\86еÑ\81Ñ\81е Ð·Ð°Ð²ÐµÑ\80Ñ\88ениÑ\8f Ñ\80абоÑ\82Ñ\8b Ð¸ Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ\82 Ð²Ñ\8bполниÑ\82Ñ\8c Ð\92аÑ\88 "
-"запÑ\80оÑ\81 Ð² Ð½Ð°Ñ\81Ñ\82оÑ\8fÑ\89ее Ð²Ñ\80емÑ\8f. Ð\9fожалÑ\83йÑ\81Ñ\82а, Ð¿Ð¾Ð²Ñ\82оÑ\80иÑ\82е Ð·Ð°Ð¿Ñ\80оÑ\81 Ñ\87еÑ\80ез Ð½ÐµÐºÑ\82оÑ\80ое Ð²Ñ\80емÑ\8f."
+"СеÑ\80веÑ\80 Ð² Ð´Ð°Ð½Ð½Ñ\8bй Ð¼Ð¾Ð¼ÐµÐ½Ñ\82 Ð²Ñ\8bклÑ\8eÑ\87аеÑ\82Ñ\81Ñ\8f Ð¸ Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ\82 Ð²Ñ\8bполниÑ\82Ñ\8c Ð²Ð°Ñ\88 Ð·Ð°Ð¿Ñ\80оÑ\81. "
+"Ð\9fовÑ\82оÑ\80иÑ\82е Ð¿Ð¾Ð¿Ñ\8bÑ\82кÑ\83 Ð¿Ð¾Ð·Ð¶Ðµ."
 
 #: templates/ERR_FORWARDING_DENIED:6
 #, fuzzy
@@ -610,15 +598,14 @@ msgstr ""
 "сообщите об этой ошибке веб-мастеру."
 
 #: templates/ERR_FTP_NOT_FOUND:7
-#, fuzzy
 msgid ""
 "This might be caused by an FTP URL with an absolute path (which does not "
 "comply with RFC 1738). If this is the cause, then the file can be found at "
 "<a href=\"%B\">%B</a>."
 msgstr ""
-"ЭÑ\82о Ð¼Ð¾Ð¶ÐµÑ\82 Ð±Ñ\8bÑ\82Ñ\8c Ð²Ñ\8bзвано FTP URL c Ð°Ð±Ñ\81олÑ\8eÑ\82нÑ\8bм Ð¿Ñ\83Ñ\82Ñ\91м (коÑ\82оÑ\80Ñ\8bй не соответствует "
-"RFC 1738). Ð\95Ñ\81ли Ñ\8dÑ\82а Ð¿Ñ\80иÑ\87ина Ð²ÐµÑ\80на, Ñ\82о Ñ\84айл Ð¼Ð¾Ð¶Ð½Ð¾ Ð½Ð°Ð¹Ñ\82и Ð¿Ð¾ Ð°Ð´Ñ\80еÑ\81Ñ\83 <a href=\"%B"
-"\">%B</a>."
+"ЭÑ\82о Ð¼Ð¾Ð³Ð»Ð¾ Ð¿Ñ\80оизойÑ\82и Ð¸Ð·-за Ð°Ð±Ñ\81олÑ\8eÑ\82ной Ñ\81Ñ\81Ñ\8bлки Ð½Ð° FTP (коÑ\82оÑ\80аÑ\8f не соответствует "
+"RFC 1738). Ð\92 Ñ\8dÑ\82ом Ñ\81лÑ\83Ñ\87ае Ñ\84айл Ð¼Ð¾Ð¶ÐµÑ\82 Ð±Ñ\8bÑ\82Ñ\8c Ð¿Ð¾Ð»Ñ\83Ñ\87ен Ð¿Ð¾ Ð°Ð´Ñ\80еÑ\81Ñ\83 <a href=\"%B\">%"
+"B</a>."
 
 #: templates/ERR_SECURE_CONNECT_FAIL:7
 msgid ""
@@ -633,32 +620,38 @@ msgstr ""
 "удостоверением безопасности узла."
 
 #: templates/ERR_CANNOT_FORWARD:6
-#, fuzzy
 msgid ""
 "This request could not be forwarded to the origin server or to any parent "
 "caches. The most likely cause for this error is that the cache administrator "
 "does not allow this cache to make direct connections to origin servers, and "
 "all configured parent caches are currently unreachable."
 msgstr ""
-"Этот запрос не может быть перенаправлен ни к первичному серверу, ни к "
-"родительским кэшам. Наиболее вероятная причина этой ошибки в том, что "
-"администратор запретил прямые соединения к первичным серверам, а все "
-"указанные родительские кэши в данный момент недоступны."
+"Запрос не может быть направлен на сервер-источник файла или на любой "
+"вышестоящий кэширующий прокси-сервер. Наиболее вероятной причиной этой "
+"ошибки является то, что кэш-администратор запретил подключаться к серверам "
+"интернета напрямую, а все вышестоящие кэширующие прокси-серверы в данный "
+"момент не доступны."
 
 #: templates/ERR_AGENT_CONFIGURE:10 templates/ERR_AGENT_WPAD:9
 msgid ""
 "Tools -&gt; Internet Options -&gt; Connection -&gt; LAN Settings -&gt;Proxy"
 msgstr ""
+"Инструменты -&gt; Настройки интернета -&gt; Соединения -&gt; Настройки LAN "
+"-&gt; Прокси"
 
 #: templates/ERR_AGENT_CONFIGURE:7 templates/ERR_AGENT_WPAD:7
 msgid ""
 "Tools -&gt; Options -&gt; Advanced -&gt; Network -&gt; Connection Settings"
 msgstr ""
+"Инструменты -&gt; Опции -&gt; Дополнительно -&gt; Сеть -&gt; Настойки "
+"соединения"
 
 #: templates/ERR_AGENT_CONFIGURE:13 templates/ERR_AGENT_WPAD:12
 msgid ""
 "Tools -&gt; Preferences -&gt; Advanced -&gt; Network -&gt; Proxy Servers"
 msgstr ""
+"Инструменты -&gt; Настройки -&gt; Дополнительно -&gt; Сеть -&gt; "
+"Прокси-серверы"
 
 #: templates/ERR_DNS_FAIL:5
 msgid "Unable to determine IP address from host name <q>%H</q>"
@@ -687,7 +680,7 @@ msgstr ""
 #: templates/ERR_AGENT_CONFIGURE:1 templates/ERR_AGENT_CONFIGURE:3
 #: templates/ERR_AGENT_WPAD:1 templates/ERR_AGENT_WPAD:3
 msgid "Web Browser Configuration"
-msgstr ""
+msgstr "Настройки браузера"
 
 #: templates/ERR_WRITE_ERROR:5
 msgid "Write Error"
@@ -707,6 +700,7 @@ msgstr ""
 msgid ""
 "Your Web Browser configuration needs to be corrected to use this network."
 msgstr ""
+"Необходимо произвести настройку вашего браузера для использования этой сети"
 
 #: templates/ERR_ACCESS_DENIED:7 templates/ERR_AGENT_CONFIGURE:15
 #: templates/ERR_AGENT_WPAD:14 templates/ERR_CANNOT_FORWARD:7
index 7144c8ceee31778d078e0d0ab59fd6907527a073..1256ec95ed829ff3aec2b3518ba955e59fab3590 100644 (file)
@@ -1,2 +1,12 @@
-DIST_SUBDIRS   = AD_group file_userip LDAP_group LM_group session unix_group wbinfo_group
-SUBDIRS                = $(EXTERNAL_ACL_HELPERS)
+DIST_SUBDIRS= \
+       AD_group \
+       eDirectory_userip \
+       file_userip \
+       kerberos_ldap_group \
+       LDAP_group \
+       LM_group \
+       session \
+       unix_group \
+       wbinfo_group
+
+SUBDIRS=$(EXTERNAL_ACL_HELPERS)
diff --git a/helpers/external_acl/eDirectory_userip/Makefile b/helpers/external_acl/eDirectory_userip/Makefile
deleted file mode 100644 (file)
index 5138829..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-# squid_edir_iplookup - Copyright (C) 2009, 2010 Chad E. Naugle
-#
-#*******************************************************************************
-#
-# Makefile --
-#
-# Builds squid_edir_lookup when run.  PORTING NEEDED.
-#
-
-CC = gcc
-LD = gcc
-CFLAGS = -O2 -Wall -Wextra
-PROGNAME = squid_edir_iplookup
-UID = squid
-GID = nogroup
-OBJECTS = main.o iplookup.o util.o
-LIBS = -lldap -llber
-HEADERS = config.h main.h util.h iplookup.h
-
-all: ${PROGNAME}
-
-${PROGNAME}: ${OBJECTS}
-       ${LD} ${CFLAGS} -o ${PROGNAME} ${OBJECTS} ${LIBS}
-       chmod 0550 ${PROGNAME}
-       chown ${UID} ${PROGNAME}
-       chgrp ${GID} ${PROGNAME}
-
-clean:
-       rm -f *.o ${PROGNAME}
-
-install: ${PROGNAME}
-       cp ${PROGNAME} /usr/sbin
-
-main.o: ${HEADERS} main.c
-       ${CC} ${CFLAGS} -c main.c
-
-iplookup.o: ${HEADERS} iplookup.c
-       ${CC} ${CFLAGS} -c iplookup.c
-
-util.o: ${HEADERS} util.c
-       ${CC} ${CFLAGS} -c util.c
diff --git a/helpers/external_acl/eDirectory_userip/Makefile.am b/helpers/external_acl/eDirectory_userip/Makefile.am
new file mode 100644 (file)
index 0000000..4ff4d3a
--- /dev/null
@@ -0,0 +1,15 @@
+include $(top_srcdir)/src/Common.am
+
+libexec_PROGRAMS = ext_edirectory_userip_acl
+
+ext_edirectory_userip_acl_SOURCES = \
+       edui_config.h main.h edui_util.h iplookup.h \
+       main.c edui_util.c iplookup.c
+
+ext_edirectory_userip_acl_LDADD = \
+       $(COMPAT_LIB) \
+       $(LDAPLIB) \
+       $(LBERLIB) \
+       $(XTRA_LIBS)
+
+EXTRA_DIST = config.test README ISSUES INSTALL
diff --git a/helpers/external_acl/eDirectory_userip/config.test b/helpers/external_acl/eDirectory_userip/config.test
new file mode 100755 (executable)
index 0000000..1e690b2
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# AYJ: currently does not build portable
+exit 1
+
+if [ -f /usr/include/ldap.h ]; then
+       exit 0
+fi
+if [ -f /usr/include/winldap.h ]; then
+       exit 0
+fi
+exit 1
similarity index 97%
rename from helpers/external_acl/eDirectory_userip/config.h
rename to helpers/external_acl/eDirectory_userip/edui_config.h
index c3421e4239fc91014580094ca6b4a7735cdb9492..f8239cb17c5b94f0a151928bb0a0781d75c8c649 100644 (file)
@@ -29,7 +29,7 @@
 #define _HAVE_CONFIG_H
 
 /* Default program name */
-#define DEFAULT_PROGRAM_NAME   "squid_edir_iplookup"
+#define DEFAULT_PROGRAM_NAME   "ext_edirectory_userip_acl"
 
 /* Hostname or IP address of LDAP server, default is IPv4 localhost (127.0.0.1) */
 /* #define DEFAULT_LDAP_HOST */
similarity index 99%
rename from helpers/external_acl/eDirectory_userip/util.c
rename to helpers/external_acl/eDirectory_userip/edui_util.c
index ba8c5fe66c6e93399cc9156ffb9c905934287c79..97624d4f6c4f558da18673e16e34d61b5b032b30 100644 (file)
@@ -26,7 +26,7 @@
  */
 
 #include "main.h"
-#include "util.h"
+#include "edui_util.h"
 
 /* debug() -
  *
index 294b0cd4ec7f963987bc7b8819769c0bc45f6a12..a94fae55831a2e365e393382f54e88ef140d9f9d 100644 (file)
@@ -26,7 +26,7 @@
  */
 
 #include "main.h"
-#include "util.h"
+#include "edui_util.h"
 #include "iplookup.h"
 
 /* InitLDAP() - <ldap_t>
index ad757e1c5bf2447c61753317d60a939de407218e..07df10f97153e95d4ee7e10299b14422f7dc9432 100644 (file)
@@ -26,7 +26,7 @@
  */
 
 #include "main.h"
-#include "util.h"
+#include "edui_util.h"
 #include "iplookup.h"
 
 char *search_attrib[] = { "cn", "uid", "networkAddress", "groupMembership", NULL };
@@ -88,7 +88,7 @@ void InitConf()
     conf.mode = 0;
     conf.mode |= MODE_INIT;
 
-    /* Set defaults from config.h */
+    /* Set defaults from edui_config.h */
 #ifdef DEFAULT_BASE_DN
     strcpy(conf.basedn, DEFAULT_BASE_DN);
 #endif
index 9e11d71ec868143a0bcc467f6ff93cf0ec32b518..9764f7783ef92d4707fab2959f68dfab768b6a62 100644 (file)
 #ifndef _HAVE_MAIN_H
 #define _HAVE_MAIN_H
 
-#ifndef _HAVE_CONFIG_H
 #include "config.h"
-#endif
+#include "edui_config.h"
 
 #ifndef DEFAULT_PROGRAM_NAME
-#define DEFAULT_PROGRAM_NAME           "squid_edir_iplookup"
+#define DEFAULT_PROGRAM_NAME           "ext_edirectory_iuserp_acl"
 #endif
 
 /* Must ... include ... these ... */
diff --git a/helpers/external_acl/kerberos_ldap_group/Makefile.am b/helpers/external_acl/kerberos_ldap_group/Makefile.am
new file mode 100644 (file)
index 0000000..70950ef
--- /dev/null
@@ -0,0 +1,31 @@
+include $(top_srcdir)/src/Common.am
+
+EXTRA_DIST = README config.test cert_tool ext_kerberos_ldap_group_acl.8
+SUBDIRS = 
+
+AM_CPPFLAGS = $(INCLUDES) -I$(srcdir)
+
+libexec_SCRIPTS = cert_tool
+
+libexec_PROGRAMS = ext_kerberos_ldap_group_acl
+
+ext_kerberos_ldap_group_acl_SOURCES = \
+       kerberos_ldap_group.cc \
+       support.h \
+       support_group.cc \
+       support_netbios.cc \
+       support_member.cc \
+       support_krb5.cc \
+       support_ldap.cc \
+       support_sasl.cc \
+       support_resolv.cc \
+       support_log.cc
+
+ext_kerberos_ldap_group_acl_LDFLAGS =
+ext_kerberos_ldap_group_acl_LDADD = \
+       $(COMPAT_LIB) \
+       $(LDAPLIB) \
+       $(LBERLIB) \
+       $(LIBSASL) \
+       $(KRB5LIBS) \
+       $(XTRA_LIBS)
diff --git a/helpers/external_acl/kerberos_ldap_group/README b/helpers/external_acl/kerberos_ldap_group/README
new file mode 100644 (file)
index 0000000..4d80409
--- /dev/null
@@ -0,0 +1,119 @@
+--------------------------------------------------------------------------------
+readme.txt is the squid_kerb_ldap read-me file.
+
+Author: Markus Moeller (markus_moeller at compuserve.com)
+
+Copyright (C) 2007 Markus Moeller. All rights reserved.
+--------------------------------------------------------------------------------
+
+squid_kerb_ldap Read Me
+
+Markus Moeller
+June 2, 2007
+
+1 Introduction
+
+squid_kerb_ldap is a reference implementation that supports SASL/GSSAPI authentication 
+to an ldap server. It is mainly intended to connect to Active Directory or Openldap based 
+ldap servers.
+
+For AD it checks the memberof attribute to determine if a user is member of a group.
+For non AD it checks the memberuid attribute to determine if a user is member of a group and if not it checks if the primary group matches.
+Currently, squid_kerb_ldap supports Squid 2.6 on Linux. 
+
+squid_auth_ldap requires either MIT or Heimdal Kerberos libraries and header files.
+
+2 Building and Installation
+
+./configure
+make
+
+Copy the helper squid_kerb_ldap to an apropriate directory.
+
+3 Configuration
+
+a) Configure IE or Firefox to point to the squid proxy by using the fqdn. IE and Firefox will use the
+fqdn to query for a HTTP/fqdn Kerberos service principal. 
+
+b) Create a keytab which contains the HTTP/fqdn Kerberos service principal and place it into a directory
+where the squid run user can read the keytab. 
+
+c) Add the following line to squid.conf
+
+auth_param negotiate program /usr/sbin/squid_kerb_auth 
+auth_param negotiate children 10
+auth_param negotiate keep_alive on
+
+external_acl_type squid_kerb_ldap ttl=3600  negative_ttl=3600  %LOGIN /usr/sbin/squid_kerb_ldap -g GROUP@
+acl ldap_group_check external squid_kerb_ldap
+http_access allow ldap_group_check
+
+If a ntlm helper is used too add a -N option to map the netbios name to a Kerberos realm e.g.
+
+external_acl_type squid_kerb_ldap ttl=3600  negative_ttl=3600  %LOGIN /usr/sbin/squid_kerb_ldap -g GROUP@ -N NETBIOS@KERBEROS.REALM
+acl ldap_group_check external squid_kerb_ldap
+http_access allow ldap_group_check
+
+
+d) Modify squid startup file
+
+Add the following lines to the squid startup script to point squid to a keytab file which
+contains the HTTP/fqdn service principal for the default Kerberos domain. The fqdn must be 
+the proxy name set in IE or firefox. You can not use an IP address.
+
+KRB5_KTNAME=/etc/squid/HTTP.keytab
+export KRB5_KTNAME
+
+If you use a different Kerberos domain than the machine itself is in you can point squid to 
+the seperate Kerberos config file by setting the following environmnet variable in the startup 
+script.
+
+KRB5_CONFIG=/etc/krb5-squid.conf
+export KRB5_CONFIG
+
+4 Miscellaneous
+
+The -i options creates informational messages whereas -d creates full debug output 
+
+If squid_kerb_ldap doesn't determine for some reason the right service ldap server you can provide 
+it with -u BIND_DN -p BIND_PW -b BIND_PATH -l LDAP_URL
+
+STARTTLS/SSL is supported and the -a options disables server certificate checks 
+
+If you serve multiple Kerberos realms add a HTTP/fqdn@REALM service principal per realm to the 
+HTTP.keytab file and use the -s GSS_C_NO_NAME option with squid_kerb_auth.
+
+squid_kerb_ldap will determine automagically the right ldap server. The following method is used:
+
+1) For user@REALM
+   1) Query DNS for SRV record _ldap._tcp.REALM
+   2) Query DNS for A record REALM
+   3) Use LDAP_URL if given   
+
+2) For user
+   2) Use LDAP_URL if given
+   
+The Groups to check against are determined as follows:
+
+1 For user@REALM
+   1) Use values given by -g option which contain a @REALM e.g. -g GROUP1@REALM:GROUP2@REALM
+   2) Use values given by -g option which contain a @ only e.g. -g GROUP1@:GROUP2@
+   3) Use values given by -g option which do not contain a realm e.g. -g GROUP1:GROUP2
+
+1 For user
+   3) Use values given by -g option which do not contain a realm e.g. -g GROUP1:GROUP2
+
+
+To support Non-ASCII character use -t <GROUP>  or -t <GROUP>@<REALM> instead of -g where GROUP is the hex UTF-8 representation e.g. 
+
+   -t 6d61726b7573 instead of -g markus
+
+The REALM must still be based on the ASCII character set. If REALM contains also non ASCII characters use -T <GROUP>@<REALM> where GROUP and REALM are hex UTF-8 representation e.g.
+
+  -T 6d61726b7573@57494e3230303352322e484f4d45 instead of -g markus@WIN2003R2.HOME
+
+For a translation of hex UTF-8 see for example http://www.utf8-chartable.de/unicode-utf8-table.pl
+
+
+
+
diff --git a/helpers/external_acl/kerberos_ldap_group/cert_tool b/helpers/external_acl/kerberos_ldap_group/cert_tool
new file mode 100644 (file)
index 0000000..9f14959
--- /dev/null
@@ -0,0 +1,83 @@
+#!/bin/ksh
+#
+#  -----------------------------------------------------------------------------
+# 
+#  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.
+# 
+#  -----------------------------------------------------------------------------
+#
+#
+# creates the following files: 
+# <server>.cert
+# secmod.db
+# key3.db
+# cert8.db
+# 
+#
+if [ -z "$1" ]; then 
+  echo "Usage: `basename $0` ldap-server port"
+  exit 0
+fi
+if [ -z "$2" ]; then
+  port=636
+else
+  port=$2
+fi
+
+server=$1
+
+#
+# Remove old files
+#
+rm  ${server}_[0-9]*.cert 2>/dev/null
+#
+# Get certs and store in .cert file
+#
+( openssl s_client -showcerts -connect $server:$port 2>/dev/null <<!
+QUIT
+!
+) | awk 'BEGIN{start=0;ostart=0}{if ( $0 ~ /BEGIN CERTIFICATE/ ) { start=start+1 };
+      if  ( start > ostart ) {print $0 >>"'$server'_"start".cert"};
+      if ( $0 ~ /END CERTIFICATE/) { ostart=start } }' 
+
+#
+# from mozilla-nss-tools
+# /usr/sfw/bin on Solaris
+# 
+#
+# Create database for Sun ldap and pem file for Openldap 
+#
+rm ${server}_[0-9]*.pem 2>/dev/null
+let i=0
+ ls ${server}_[0-9]*.cert | while read file; do
+ let i=i+1
+ cat  $file  >> ${server}_$i.pem
+ CA=`openssl x509 -noout -text -in  ${server}_$i.pem | grep -i "CA:.*true"`
+ if [ -n "$CA" ]; then
+   echo "CA is in ${server}_$i.pem"
+   certutil -A -a -n "${server}_$i" -i $file -t "C,," -d .
+ else
+   certutil -A -a -n "${server}_$i" -i $file -t "P,," -d .
+ fi
+ rm $file
+done
+echo "Certs:"
+certutil -d . -L
+echo "are in" 
+ls *.db
diff --git a/helpers/external_acl/kerberos_ldap_group/config.test b/helpers/external_acl/kerberos_ldap_group/config.test
new file mode 100644 (file)
index 0000000..4c1c762
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/sh
+# Don't build without gssapi.h
+if [ -f /usr/include/ldap.h -o -f /usr/local/include/ldap.h ]; then
+       # Won't link without SASL as well
+       if [ -f /usr/include/sasl.h -o -f /usr/include/sasl/sasl.h ]; then
+               if [ -f /usr/lib/libsasl.a -o -f /usr/lib/libsasl2.a ]; then
+                       exit 0
+               fi
+               if [ -f /usr/lib/libsasl.la -o -f /usr/lib/libsasl2.la ]; then
+                       exit 0
+               fi
+       fi
+fi
+exit 1
diff --git a/helpers/external_acl/kerberos_ldap_group/ext_kerberos_ldap_group_acl.8 b/helpers/external_acl/kerberos_ldap_group/ext_kerberos_ldap_group_acl.8
new file mode 100644 (file)
index 0000000..83f4fb3
--- /dev/null
@@ -0,0 +1,241 @@
+.if !'po4a'hide' .TH ext_kerberos_ldap_group_acl 8
+.
+.SH NAME
+.if !'po4a'hide' .B ext_kerberos_ldap_group_acl
+.if !'po4a'hide' \-
+Squid LDAP external acl group helper for Kerberos or NTLM credentials.
+.PP
+Version 1.2.2sq
+.
+.SH SYNOPSIS
+.if !'po4a'hide' .B ext_kerberos_ldap_group_acl
+.if !'po4a'hide' .B [\-h] [\-d] [\-i] [\-s] [\-a] [\-D Realm ] [\-N Netbios-Realm-List] [\-m Max-Depth] [\-u Ldap-User] [\-p Ldap-Password] [\-b Ldap-Bind-Path] [\-l Ldap-URL] \-g Group-Realm-List \-t  Hex-Group-Realm-List \-T Hex-Group-Hex-Realm-List 
+.
+.SH DESCRIPTION
+.B ext_kerberos_ldap_group_acl
+is an installed binary and allows Squid to connect to a LDAP directory to 
+authorize users via LDAP groups. Options are specified as parameters on the 
+command line, while the username (e.g. user, user@REALM, NDOMAIN\\user) to 
+be checked against the LDAP directory are specified on subsequent lines of 
+input to the helper, one username per line.
+.PP
+.B ext_kerberos_ldap_group_acl 
+will determine the ldap server name from DNS SRV and/or 
+A records or a local hosts file (e.g. for the Kerberos Realm SUSE.HOME it 
+will look for an SRV record _ldap._tcp.SUSE.HOME and an A record SUSE.HOME 
+or a SUSE.HOME hosts entry). If no domain information is available from the 
+username the ldap server will be determined through the command line options.
+.PP
+.B ext_kerberos_ldap_group_acl 
+requires as a minimum the \-g, \-t or \-T option which 
+provides the ldap group name the user has to belong too. For Active Directory 
+a recursive group lookup is implemented until a max depth specified by \-m depth. 
+For other Ldap servers a RFC2307bis schema of groups is assumed.
+.PP
+Different group names can be specified for different domains using a 
+group@domain syntax. 
+As expected by the
+.B external_acl_type
+construct of Squid, after
+specifying a username and group followed by a new line, this
+helper will produce either
+.B OK
+or
+.B ERR
+on the following line
+to show if the user is a member of the specified group.
+.
+.SH OPTIONS
+.if !'po4a'hide' .TP 12
+.if !'po4a'hide' .B \-h
+Display the binary help and command line syntax info using stderr.
+.if !'po4a'hide' .TP 12
+.if !'po4a'hide' .B \-d
+Write debug messages to stderr.
+.if !'po4a'hide' .TP 12
+.if !'po4a'hide' .B \-i
+Write informational messages to stderr.
+.if !'po4a'hide' .TP 12
+.if !'po4a'hide' .B \-s
+Use SSL for the ldap connection.
+.IP
+The CA certificate file can be set via the environment variable TLS_CACERTFILE (default /etc/ssl/certs/cert.pem) (OpenLDAP).
+.IP
+The SSL certificate database can be set via the environment variable SSL_CERTDBPATH (default /etc/certs) (Sun and Mozilla LDAP SDK).
+.if !'po4a'hide' .TP 12
+.if !'po4a'hide' .B \-a
+Allow SSL without certificate verification.
+.if !'po4a'hide' .TP 12
+.if !'po4a'hide' .B \-D Realm 
+Default Kerberos domain to use for usernames which do not contain domain 
+information (e.g. for users using basic authentication).
+.if !'po4a'hide' .TP 12
+.if !'po4a'hide' .B \-N Netbios-Realm-List
+A list of Netbios name mappings to Kerberos domain names of the form 
+Netbios-Name@Kerberos-Realm[:Netbios-Name@Kerberos-Realm] (e.g. for users 
+using NTLM authentication).
+.if !'po4a'hide' .TP 12
+.if !'po4a'hide' .B \-m Max-Depth
+Maximal depth of recursive group search.
+.if !'po4a'hide' .TP 12
+.if !'po4a'hide' .B \-u Ldap-User
+Username for LDAP server.
+.if !'po4a'hide' .TP 12
+.if !'po4a'hide' .B \-u Ldap-Password
+Password for LDAP server.
+.IP
+As the password needs to be printed in plain text in your Squid configuration
+it is strongly recommended to use a account with minimal associated privileges.  
+This to limit the damage in case someone could get hold of a copy of your Squid 
+configuration file or extracts the password used from a process listing.
+.
+.if !'po4a'hide' .TP 12
+.if !'po4a'hide' .B \-b Ldap-Bind-Path
+LDAP server bind path.
+.if !'po4a'hide' .TP 12
+.if !'po4a'hide' .B \-u Ldap-URL
+LDAP server URL in form ldap[s]://server:port
+.if !'po4a'hide' .TP 12
+.if !'po4a'hide' .B \-g Group-Realm-List
+A list of group name per Kerberos domain of the form 
+Group|Group@|Group@Realm[:Group@|Group@Realm]
+.if !'po4a'hide' .TP 12
+.if !'po4a'hide' .B \-t  Hex-Group-Realm-List
+A list of group name per Kerberos domain of the 
+form Group|Group@|Group@Realm[:Group@|Group@Realm] where group is in 
+UTF-8 hex format
+.if !'po4a'hide' .TP 12
+.if !'po4a'hide' .B \-T Hex-Group-Hex-Realm-List
+A list of group name per Kerberos domain of the form 
+Group|Group@|Group@Realm[:Group@|Group@Realm] where group and domain 
+is in UTF-8 hex format
+.
+.SH CONFIGURATION
+.PP See FAQ wiki page for examples of how to write configuration snippets. (TBD)
+.PP 
+This helper is intended to be used as an
+.B external_acl_type
+helper in
+.B squid.conf.
+.if !'po4a'hide' .P
+.if !'po4a'hide' .ft CR
+.if !'po4a'hide' .nf
+.if !'po4a'hide' external_acl_type kerberos_ldap_group1  ttl=3600  negative_ttl=3600 %LOGIN /path/to/ext_kerberos_ldap_group_acl -g GROUP1
+.if !'po4a'hide' .br
+.if !'po4a'hide' external_acl_type kerberos_ldap_group2  ttl=3600  negative_ttl=3600 %LOGIN /path/to/ext_kerberos_ldap_group_acl -g GROUP2
+.if !'po4a'hide' .br
+.if !'po4a'hide' acl group1 external kerberos_ldap_group1
+.if !'po4a'hide' .br
+.if !'po4a'hide' acl group2 external kerberos_ldap_group2
+.if !'po4a'hide' .fi
+.if !'po4a'hide' .ft
+.PP
+.B NOTE:
+The following squid startup file modification may be required:
+
+Add the following lines to the squid startup script to point squid to a keytab file which
+contains the HTTP/fqdn service principal for the default Kerberos domain. The fqdn must be
+the proxy name set in IE or firefox. You can not use an IP address.
+.if !'po4a'hide' .P
+.if !'po4a'hide' .ft CR
+.if !'po4a'hide' .nf
+.if !'po4a'hide' KRB5_KTNAME=/etc/squid/HTTP.keytab
+.if !'po4a'hide' export KRB5_KTNAME
+.if !'po4a'hide' .fi
+.if !'po4a'hide' .ft
+
+If you use a different Kerberos domain than the machine itself is in you can point squid to
+the seperate Kerberos config file by setting the following environmnet variable in the startup
+script.
+.if !'po4a'hide' .P
+.if !'po4a'hide' .ft CR
+.if !'po4a'hide' .nf
+.if !'po4a'hide' KRB5_CONFIG=/etc/krb5-squid.conf
+.if !'po4a'hide' export KRB5_CONFIG
+.if !'po4a'hide' .fi
+.if !'po4a'hide' .ft
+
+.B ext_kerberos_ldap_group_acl
+will determine automagically the right ldap server. The following method is used:
+
+1) For user@REALM
+   a) Query DNS for SRV record _ldap._tcp.REALM
+   b) Query DNS for A record REALM
+   c) Use LDAP_URL if given
+
+2) For user
+   a) Use domain -D REALM and follow step 1)
+   b) Use LDAP_URL if given
+
+The Groups to check against are determined as follows:
+
+1) For user@REALM
+   a) Use values given by -g option which contain a @REALM e.g. -g GROUP1@REALM:GROUP2@REALM
+   b) Use values given by -g option which contain a @ only e.g. -g GROUP1@:GROUP2@
+   c) Use values given by -g option which do not contain a realm e.g. -g GROUP1:GROUP2
+
+2) For user
+   a) Use values given by -g option which do not contain a realm e.g. -g GROUP1:GROUP2
+
+3) For NDOMAIN\\user
+   a) Use realm given by -N NDOMAIN@REALM and then use values given by -g option which contain a @REALM e.g. -g GROUP1@REALM:GROUP2@REALM
+
+To support Non-ASCII character use -t GROUP  or -t GROUP@REALM instead of -g where GROUP is the hex UTF-8 representation e.g.
+
+   -t 6d61726b7573 instead of -g markus
+
+The REALM must still be based on the ASCII character set. If REALM contains also non ASCII characters use -T GROUP@REALM where GROUP and REALM are hex UTF-8 representation e.g.
+
+  -T 6d61726b7573@57494e3230303352322e484f4d45 instead of -g markus@WIN2003R2.HOME
+
+For a translation of hex UTF-8 see for example http://www.utf8-chartable.de/unicode-utf8-table.pl
+
+.
+.SH AUTHOR
+This program was written by
+.if !'po4a'hide' .I Markus Moeller <markus_moeller@compuserve.com>
+.PP
+This manual was written by
+.if !'po4a'hide' .I Markus Moeller <markus_moeller@compuserve.com>
+.
+.SH COPYRIGHT
+This program and documentation is copyright to the authors named above.
+.PP
+Distributed under the GNU General Public License (GNU GPL) version 2 or later (GPLv2+).
+.
+.SH QUESTIONS
+Questions on the usage of this program can be sent to the
+.I Squid Users mailing list
+.if !'po4a'hide' <squid-users@squid-cache.org>
+.
+.SH REPORTING BUGS
+Bug reports need to be made in English.
+See http://wiki.squid-cache.org/SquidFaq/BugReporting for details of what you need to include with your bug report.
+.PP
+Report bugs or bug fixes using http://bugs.squid-cache.org/
+.PP
+Report serious security bugs to
+.I Squid Bugs <squid-bugs@squid-cache.org>
+.PP
+Report ideas for new improvements to the
+.I Squid Developers mailing list
+.if !'po4a'hide' <squid-dev@squid-cache.org>
+.
+.SH SEE ALSO
+.if !'po4a'hide' .BR squid "(8) "
+.if !'po4a'hide' .BR negotiate_kerberos_auth "(8) "
+.br
+.BR RFC1035 " - Domain names - implementation and specification,"
+.br
+.BR RFC2782 " - A DNS RR for specifying the location of services (DNS SRV),"
+.br
+.BR RFC2254 " - The String Representation of LDAP Search Filters,"
+.br
+.BR RFC2307bis " - An Approach for Using LDAP as a Network Information Service
+http://www.padl.com/~lukeh/rfc2307bis.txt,"
+.br
+The Squid FAQ wiki
+.if !'po4a'hide' http://wiki.squid-cache.org/SquidFaq
+.br
+The Squid Configuration Manual
+.if !'po4a'hide' http://www.squid-cache.org/Doc/config/
diff --git a/helpers/external_acl/kerberos_ldap_group/kerberos_ldap_group.cc b/helpers/external_acl/kerberos_ldap_group/kerberos_ldap_group.cc
new file mode 100644 (file)
index 0000000..7019bcb
--- /dev/null
@@ -0,0 +1,405 @@
+/*
+ * -----------------------------------------------------------------------------
+ *
+ * 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.
+ *
+ *   As a special exemption, M Moeller gives permission to link this program
+ *   with MIT, Heimdal or other GSS/Kerberos libraries, and distribute
+ *   the resulting executable, without including the source code for
+ *   the Libraries in the source distribution.
+ *
+ * -----------------------------------------------------------------------------
+ */
+/*
+ * Hosted at http://sourceforge.net/projects/squidkerbauth
+ */
+#include "config.h"
+#include "helpers/defines.h"
+#include "util.h"
+
+#ifdef HAVE_LDAP
+
+#include "support.h"
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+
+void
+init_args(struct main_args *margs)
+{
+    margs->nlist = NULL;
+    margs->glist = NULL;
+    margs->ulist = NULL;
+    margs->tlist = NULL;
+    margs->luser = NULL;
+    margs->lpass = NULL;
+    margs->lbind = NULL;
+    margs->lurl = NULL;
+    margs->ssl = NULL;
+    margs->rc_allow = 0;
+    margs->AD = 0;
+    margs->mdepth = 5;
+    margs->ddomain = NULL;
+    margs->groups = NULL;
+    margs->ndoms = NULL;
+}
+
+void clean_gd(struct gdstruct *gdsp);
+void clean_nd(struct ndstruct *ndsp);
+
+void
+clean_gd(struct gdstruct *gdsp)
+{
+    struct gdstruct *p = NULL, *pp = NULL;
+
+start:
+    p = gdsp;
+    if (!p)
+        return;
+    while (p->next) {
+        pp = p;
+        p = p->next;
+    }
+    if (p->group) {
+        xfree(p->group);
+        p->group = NULL;
+    }
+    if (p->domain) {
+        xfree(p->domain);
+        p->domain = NULL;
+    }
+    if (pp && pp->next) {
+        xfree(pp->next);
+        pp->next = NULL;
+    }
+    if (p == gdsp) {
+        xfree(gdsp);
+        gdsp = NULL;
+    }
+    goto start;
+}
+
+void
+clean_nd(struct ndstruct *ndsp)
+{
+    struct ndstruct *p = NULL, *pp = NULL;
+
+start:
+    p = ndsp;
+    if (!p)
+        return;
+    while (p->next) {
+        pp = p;
+        p = p->next;
+    }
+    if (p->netbios) {
+        xfree(p->netbios);
+        p->netbios = NULL;
+    }
+    if (p->domain) {
+        xfree(p->domain);
+        p->domain = NULL;
+    }
+    if (pp && pp->next) {
+        xfree(pp->next);
+        pp->next = NULL;
+    }
+    if (p == ndsp) {
+        xfree(ndsp);
+        ndsp = NULL;
+    }
+    goto start;
+}
+
+void
+clean_args(struct main_args *margs)
+{
+    if (margs->glist) {
+        xfree(margs->glist);
+        margs->glist = NULL;
+    }
+    if (margs->ulist) {
+        xfree(margs->ulist);
+        margs->ulist = NULL;
+    }
+    if (margs->tlist) {
+        xfree(margs->tlist);
+        margs->tlist = NULL;
+    }
+    if (margs->nlist) {
+        xfree(margs->nlist);
+        margs->nlist = NULL;
+    }
+    if (margs->luser) {
+        xfree(margs->luser);
+        margs->luser = NULL;
+    }
+    if (margs->lpass) {
+        xfree(margs->lpass);
+        margs->lpass = NULL;
+    }
+    if (margs->lbind) {
+        xfree(margs->lbind);
+        margs->lbind = NULL;
+    }
+    if (margs->lurl) {
+        xfree(margs->lurl);
+        margs->lurl = NULL;
+    }
+    if (margs->ssl) {
+        xfree(margs->ssl);
+        margs->ssl = NULL;
+    }
+    if (margs->ddomain) {
+        xfree(margs->ddomain);
+        margs->ddomain = NULL;
+    }
+    if (margs->groups) {
+        clean_gd(margs->groups);
+        margs->groups = NULL;
+    }
+    if (margs->ndoms) {
+        clean_nd(margs->ndoms);
+        margs->ndoms = NULL;
+    }
+}
+
+void strup(char *s);
+
+int
+main(int argc, char *const argv[])
+{
+    char buf[6400];
+    char *user, *domain;
+    char *nuser, *nuser8 = NULL, *netbios;
+    char *c;
+    int opt;
+    int length;
+    struct main_args margs;
+
+    setbuf(stdout, NULL);
+    setbuf(stdin, NULL);
+
+    init_args(&margs);
+
+    while (-1 != (opt = getopt(argc, argv, "diasg:D:N:u:U:t:T:p:l:b:m:h"))) {
+        switch (opt) {
+        case 'd':
+            debug_enabled = 1;
+            break;
+        case 'i':
+            log_enabled = 1;
+            break;
+        case 'a':
+            margs.rc_allow = 1;
+            break;
+        case 's':
+            margs.ssl = (char *) "yes";
+            break;
+        case 'g':
+            margs.glist = xstrdup(optarg);
+            break;
+        case 'D':
+            margs.ddomain = xstrdup(optarg);
+            break;
+        case 'N':
+            margs.nlist = xstrdup(optarg);
+            break;
+        case 'u':
+            margs.luser = xstrdup(optarg);
+            break;
+        case 'U':
+            margs.ulist = xstrdup(optarg);
+            break;
+        case 't':
+            margs.ulist = xstrdup(optarg);
+            break;
+        case 'T':
+            margs.tlist = xstrdup(optarg);
+            break;
+        case 'p':
+            margs.lpass = xstrdup(optarg);
+            /* Hide Password */
+            memset(optarg, 'X', strlen(optarg));
+            break;
+        case 'l':
+            margs.lurl = xstrdup(optarg);
+            break;
+        case 'b':
+            margs.lbind = xstrdup(optarg);
+            break;
+        case 'm':
+            margs.mdepth = atoi(optarg);
+            break;
+        case 'h':
+            fprintf(stderr, "Usage: \n");
+            fprintf(stderr, "squid_kerb_ldap [-d] [-i] -g group list [-D domain] [-N netbios domain map] [-s] [-u ldap user] [-p ldap user password] [-l ldap url] [-b ldap bind path] [-a] [-m max depth] [-h]\n");
+            fprintf(stderr, "-d full debug\n");
+            fprintf(stderr, "-i informational messages\n");
+            fprintf(stderr, "-g group list\n");
+            fprintf(stderr, "-t group list (only group name hex UTF-8 format)\n");
+            fprintf(stderr, "-T group list (all in hex UTF-8 format - except seperator @)\n");
+            fprintf(stderr, "-D default domain\n");
+            fprintf(stderr, "-N netbios to dns domain map\n");
+            fprintf(stderr, "-u ldap user\n");
+            fprintf(stderr, "-p ldap user password\n");
+            fprintf(stderr, "-l ldap url\n");
+            fprintf(stderr, "-b ldap bind path\n");
+            fprintf(stderr, "-s use SSL encryption with Kerberos authentication\n");
+            fprintf(stderr, "-a allow SSL without cert verification\n");
+            fprintf(stderr, "-m maximal depth for recursive searches\n");
+            fprintf(stderr, "-h help\n");
+            fprintf(stderr, "The ldap url, ldap user and ldap user password details are only used if the kerberised\n");
+            fprintf(stderr, "access fails(e.g. unknown domain) or if the username does not contain a domain part\n");
+            fprintf(stderr, "and no default domain is provided.\n");
+            fprintf(stderr, "If the ldap url starts with ldaps:// it is either start_tls or simple SSL\n");
+            fprintf(stderr, "The group list can be:\n");
+            fprintf(stderr, "group   - In this case group can be used for all keberised and non kerberised ldap servers\n");
+            fprintf(stderr, "group@  - In this case group can be used for all keberised ldap servers\n");
+            fprintf(stderr, "group@domain  - In this case group can be used for ldap servers of domain domain\n");
+            fprintf(stderr, "group1@domain1:group2@domain2:group3@:group4  - A list is build with a colon as seperator\n");
+            fprintf(stderr, "Group membership is determined with AD servers through the users memberof attribute which\n");
+            fprintf(stderr, "is followed to the top (e.g. if the group is a member of a group)\n");
+            fprintf(stderr, "Group membership is determined with non AD servers through the users memberuid (assuming\n");
+            fprintf(stderr, "PosixGroup) or primary group membership (assuming PosixAccount)\n");
+            clean_args(&margs);
+            exit(0);
+        default:
+            warn((char *) "%s| %s: WARNING: unknown option: -%c.\n", LogTime(), PROGRAM, opt);
+        }
+    }
+
+    debug((char *) "%s| %s: INFO: Starting version %s\n", LogTime(), PROGRAM, KERBEROS_LDAP_GROUP_VERSION);
+    if (create_gd(&margs)) {
+        debug((char *) "%s| %s: FATAL: Error in group list: %s\n", LogTime(), PROGRAM, margs.glist ? margs.glist : "NULL");
+        SEND_ERR("");
+        clean_args(&margs);
+        exit(1);
+    }
+    if (create_nd(&margs)) {
+        debug((char *) "%s| %s: FATAL: Error in netbios list: %s\n", LogTime(), PROGRAM, margs.nlist ? margs.nlist : "NULL");
+        SEND_ERR("");
+        clean_args(&margs);
+        exit(1);
+    }
+    while (1) {
+        if (fgets(buf, sizeof(buf) - 1, stdin) == NULL) {
+            if (ferror(stdin)) {
+                debug((char *) "%s| %s: FATAL: fgets() failed! dying..... errno=%d (%s)\n", LogTime(), PROGRAM, ferror(stdin),
+                      strerror(ferror(stdin)));
+
+                SEND_ERR("");
+                clean_args(&margs);
+                exit(1);       /* BIIG buffer */
+            }
+            SEND_ERR("");
+            clean_args(&margs);
+            exit(0);
+        }
+        c = (char *) memchr(buf, '\n', sizeof(buf) - 1);
+        if (c) {
+            *c = '\0';
+            length = c - buf;
+        } else {
+            SEND_ERR("");
+            debug((char *) "%s| %s: ERR\n", LogTime(), PROGRAM);
+            continue;
+        }
+
+        user = buf;
+        nuser = strchr(user, '\\');
+        if (!nuser)
+            nuser8 = strstr(user, "%5C");
+        if (!nuser && !nuser8)
+            nuser8 = strstr(user, "%5c");
+        domain = strrchr(user, '@');
+        if (nuser || nuser8) {
+            if (nuser) {
+                *nuser = '\0';
+                nuser++;
+            } else {
+                *nuser8 = '\0';
+                nuser = nuser8 + 3;
+            }
+            netbios = user;
+            if (debug_enabled)
+                debug((char *) "%s| %s: INFO: Got User: %s Netbios Name: %s\n", LogTime(), PROGRAM, nuser, netbios);
+            else
+                log((char *) "%s| %s: INFO: Got User: %s Netbios Name: %s\n", LogTime(), PROGRAM, nuser, netbios);
+            domain = get_netbios_name(&margs, netbios);
+            user = nuser;
+        } else if (domain) {
+            strup(domain);
+            *domain = '\0';
+            domain++;
+        }
+        if (!domain && margs.ddomain) {
+            domain = xstrdup(margs.ddomain);
+            if (debug_enabled)
+                debug((char *) "%s| %s: INFO: Got User: %s set default domain: %s\n", LogTime(), PROGRAM, user, domain);
+            else
+                log((char *) "%s| %s: INFO: Got User: %s set default domain: %s\n", LogTime(), PROGRAM, user, domain);
+        }
+        if (debug_enabled)
+            debug((char *) "%s| %s: INFO: Got User: %s Domain: %s\n", LogTime(), PROGRAM, user, domain ? domain : "NULL");
+        else
+            log((char *) "%s| %s: INFO: Got User: %s Domain: %s\n", LogTime(), PROGRAM, user, domain ? domain : "NULL");
+
+        if (!strcmp(user, "QQ") && domain && !strcmp(domain, "QQ")) {
+            clean_args(&margs);
+            exit(-1);
+        }
+        if (check_memberof(&margs, user, domain)) {
+            SEND_OK("");
+            debug((char *) "%s| %s: DEBUG: OK\n", LogTime(), PROGRAM);
+        } else {
+            SEND_ERR("");
+            debug((char *) "%s| %s: DEBUG: ERR\n", LogTime(), PROGRAM);
+        }
+    }
+
+
+}
+
+void
+strup(char *s)
+{
+    while (*s) {
+        *s = toupper((unsigned char) *s);
+        s++;
+    }
+}
+
+#else
+#include <stdio.h>
+#include <stdlib.h>
+int
+main(int argc, char *const argv[])
+{
+    setbuf(stdout, NULL);
+    setbuf(stdin, NULL);
+    char buf[6400];
+    while (1) {
+        if (fgets(buf, sizeof(buf) - 1, stdin) == NULL) {
+        }
+        fprintf(stdout, "ERR\n");
+        fprintf(stderr, "LDAP group authorisation not supported\n");
+    }
+}
+#endif
diff --git a/helpers/external_acl/kerberos_ldap_group/support.h b/helpers/external_acl/kerberos_ldap_group/support.h
new file mode 100644 (file)
index 0000000..996b752
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * -----------------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * -----------------------------------------------------------------------------
+ */
+
+#define KERBEROS_LDAP_GROUP_VERSION "1.2.2sq"
+
+#if HAVE_STRING_H
+#include <string.h>
+#endif
+
+#if HAVE_HEIMDAL_KERBEROS
+#if HAVE_GSSAPI_GSSAPI_H
+#include <gssapi/gssapi.h>
+#elif HAVE_GSSAPI_H
+#include <gssapi.h>
+#endif /* HAVE_GSSAPI_GSSAPI_H/HAVE_GSSAPI_H */
+#if HAVE_KRB5_H
+#if HAVE_BROKEN_SOLARIS_KRB5_H
+#warn "Warning! You have a broken Solaris <krb5.h> fsystem header"
+#warn "http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6837512"
+#endif /* HAVE_BROKEN_SOLARIS_KRB5_H */
+#include <krb5.h>
+#endif /* HAVE_KRB5_H */
+#if HAVE_COM_ERR_H
+#include <com_err.h>
+#else
+#define error_message(code) krb5_get_err_text(kparam.context,code)
+#endif /* HAVE_COM_ERR_H */
+#else /*MIT */
+#ifdef HAVE_GSSAPI_GSSAPI_H
+#include <gssapi/gssapi.h>
+#elif defined(HAVE_GSSAPI_H)
+#include <gssapi.h>
+#endif
+#ifdef HAVE_GSSAPI_GSSAPI_KRB5_H
+#include <gssapi/gssapi_krb5.h>
+#endif
+#ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H
+#include <gssapi/gssapi_generic.h>
+#endif
+#ifdef HAVE_GSSAPI_GSSAPI_EXT_H
+#include <gssapi/gssapi_ext.h>
+#endif
+#ifdef HAVE_KRB5_H
+#if HAVE_BROKEN_SOLARIS_KRB5_H
+#if defined(__cplusplus)
+#define KRB5INT_BEGIN_DECLS     extern "C" {
+#define KRB5INT_END_DECLS
+KRB5INT_BEGIN_DECLS
+#endif
+#endif
+#include <krb5.h>
+#endif
+#ifdef HAVE_COM_ERR_H
+#include <com_err.h>
+#endif
+#endif
+#ifndef gss_nt_service_name
+#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
+#endif
+
+#define LDAP_DEPRECATED 1
+#ifdef HAVE_LDAP_REBIND_FUNCTION
+#define LDAP_REFERRALS
+#endif
+#ifdef HAVE_LBER_H
+#include <lber.h>
+#endif
+#ifdef HAVE_LDAP_H
+#include <ldap.h>
+#endif
+#ifdef HAVE_MOZLDAP_LDAP_H
+#include <mozldap/ldap.h>
+#endif
+
+struct gdstruct {
+    char *group;
+    char *domain;
+    struct gdstruct *next;
+};
+struct ndstruct {
+    char *netbios;
+    char *domain;
+    struct ndstruct *next;
+};
+
+struct main_args {
+    char *glist;
+    char *ulist;
+    char *tlist;
+    char *nlist;
+    char *luser;
+    char *lpass;
+    char *lbind;
+    char *lurl;
+    char *ssl;
+    int rc_allow;
+    int AD;
+    int mdepth;
+    char *ddomain;
+    struct gdstruct *groups;
+    struct ndstruct *ndoms;
+};
+
+SQUIDCEXTERN int log_enabled;
+
+/* the macro overload style is really a gcc-ism */
+#ifdef __GNUC__
+
+
+#define log(X...) \
+                     if (log_enabled) { \
+                         fprintf(stderr, "%s(%d): pid=%ld :", __FILE__, __LINE__, (long)getpid() ); \
+                         fprintf(stderr,X); \
+                     } else (void)0
+
+#define error(X...) \
+                     fprintf(stderr, "%s(%d): pid=%ld :", __FILE__, __LINE__, (long)getpid() ); \
+                     fprintf(stderr,X); \
+#define warn(X...) \
+                     fprintf(stderr, "%s(%d): pid=%ld :", __FILE__, __LINE__, (long)getpid() ); \
+                     fprintf(stderr,X); \
+#else /* __GNUC__ */
+
+/* non-GCC compilers can't do the above macro define yet. */
+void log(char *format,...);
+void error(char *format,...);
+void warn(char *format,...);
+#endif
+
+
+struct hstruct {
+    char *host;
+    int port;
+    int priority;
+    int weight;
+};
+
+struct ldap_creds {
+    char *dn;
+    char *pw;
+};
+
+
+void init_args(struct main_args *margs);
+void clean_args(struct main_args *margs);
+const char *LogTime(void);
+
+int check_memberof(struct main_args *margs, char *user, char *domain);
+int get_memberof(struct main_args *margs, char *user, char *domain, char *group);
+
+char *get_netbios_name(struct main_args *margs, char *netbios);
+
+int create_gd(struct main_args *margs);
+int create_nd(struct main_args *margs);
+
+int krb5_create_cache(struct main_args *margs, char *domain);
+void krb5_cleanup(void);
+
+int get_ldap_hostname_list(struct main_args *margs, struct hstruct **hlist, int nhosts, char *domain);
+int get_hostname_list(struct main_args *margs, struct hstruct **hlist, int nhosts, char *name);
+int free_hostname_list(struct hstruct **hlist, int nhosts);
+
+#if defined(HAVE_SASL_H) || defined(HAVE_SASL_SASL_H) || defined(HAVE_SASL_DARWIN)
+int tool_sasl_bind(LDAP * ld, char *binddn, char *ssl);
+#endif
+
+#define PROGRAM "kerberos_ldap_group"
diff --git a/helpers/external_acl/kerberos_ldap_group/support_group.cc b/helpers/external_acl/kerberos_ldap_group/support_group.cc
new file mode 100644 (file)
index 0000000..e056882
--- /dev/null
@@ -0,0 +1,430 @@
+
+/*
+ * -----------------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * -----------------------------------------------------------------------------
+ */
+
+#include "config.h"
+#include "util.h"
+
+#ifdef HAVE_LDAP
+
+#include "support.h"
+
+struct gdstruct *init_gd(void);
+
+struct gdstruct *
+init_gd(void) {
+    struct gdstruct *gdsp;
+    gdsp = (struct gdstruct *) xmalloc(sizeof(struct gdstruct));
+    gdsp->group = NULL;
+    gdsp->domain = NULL;
+    gdsp->next = NULL;
+    return gdsp;
+}
+
+char *utf8dup(struct main_args *margs);
+
+char *
+utf8dup(struct main_args *margs)
+{
+    int c = 0, s;
+    size_t n;
+    char *src;
+    unsigned char *p, *dup;
+
+    src = margs->glist;
+    if (!src)
+        return NULL;
+    for (n = 0; n < strlen(src); n++)
+        if ((unsigned char) src[n] > 127)
+            c++;
+    if (c != 0) {
+        p = (unsigned char *) xmalloc(strlen(src) + c);
+        dup = p;
+        for (n = 0; n < strlen(src); n++) {
+            s = (unsigned char) src[n];
+            if (s > 127 && s < 192) {
+                *p = 194;
+                p++;
+                *p = s;
+            } else if (s > 191 && s < 256) {
+                *p = 195;
+                p++;
+                *p = s - 64;
+            } else
+                *p = s;
+            p++;
+        }
+        *p = '\0';
+        debug((char *) "%s| %s: INFO: Group %s as UTF-8: %s\n", LogTime(), PROGRAM, src, dup);
+        return (char *) dup;
+    } else
+        return xstrdup(src);
+}
+
+char *hex_utf_char(struct main_args *margs, int flag);
+/*
+ * UTF8    = UTF1 / UTFMB
+ * UTFMB   = UTF2 / UTF3 / UTF4
+ *
+ * UTF0    = %x80-BF
+ * UTF1    = %x00-7F
+ * UTF2    = %xC2-DF UTF0
+ * UTF3    = %xE0 %xA0-BF UTF0 / %xE1-EC 2(UTF0) /
+ * %xED %x80-9F UTF0 / %xEE-EF 2(UTF0)
+ * UTF4    = %xF0 %x90-BF 2(UTF0) / %xF1-F3 3(UTF0) /
+ * %xF4 %x80-8F 2(UTF0)
+ *
+ * http://www.utf8-chartable.de/unicode-utf8-table.pl
+ */
+
+char *
+hex_utf_char(struct main_args *margs, int flag)
+{
+    char *up;
+    char *upd;
+    char *ul;
+    int a, n, nl, ival, ichar;
+    int iUTF2, iUTF3, iUTF4;
+
+    if (flag) {
+        up = margs->ulist;
+    } else {
+        up = margs->tlist;
+    }
+
+    if (!up)
+        return NULL;
+
+    upd = strrchr(up, '@');
+    if (upd)
+        a = upd - up;
+    else
+        a = strlen(up);
+
+    ul = (char *) xmalloc(strlen(up));
+    n = 0;
+    nl = 0;
+    iUTF2 = 0;
+    iUTF3 = 0;
+    iUTF4 = 0;
+
+    while (n < (int) strlen(up)) {
+        if (flag && n == a)
+            break;
+        if (up[n] == '@') {
+            ul[nl] = '@';
+            nl++;
+            n++;
+            continue;
+        }
+        ival = up[n];
+        if (ival > 64 && ival < 71)
+            ichar = (ival - 55) * 16;
+        else if (ival > 96 && ival < 103)
+            ichar = (ival - 87) * 16;
+        else if (ival > 47 && ival < 58)
+            ichar = (ival - 48) * 16;
+        else {
+            debug((char *) "%s| %s: WARNING: Invalid Hex value %c\n", LogTime(), PROGRAM, ival);
+            if (ul)
+                xfree(ul);
+            return NULL;
+        }
+
+
+        if (n == a - 1) {
+            debug((char *) "%s| %s: WARNING: Invalid Hex UTF-8 string %s\n", LogTime(), PROGRAM, up);
+            if (ul)
+                xfree(ul);
+            return NULL;
+        }
+        n++;
+        ival = up[n];
+        if (ival > 64 && ival < 71)
+            ichar = ichar + ival - 55;
+        else if (ival > 96 && ival < 103)
+            ichar = ichar + ival - 87;
+        else if (ival > 47 && ival < 58)
+            ichar = ichar + ival - 48;
+        else {
+            debug((char *) "%s| %s: WARNING: Invalid Hex value %c\n", LogTime(), PROGRAM, ival);
+            if (ul)
+                xfree(ul);
+            return NULL;
+        }
+
+        if (iUTF2) {
+            if (iUTF2 == 0xC2 && ichar > 0x7F && ichar < 0xC0) {
+                iUTF2 = 0;
+                ul[nl - 1] = ichar;
+            } else if (iUTF2 == 0xC3 && ichar > 0x7F && ichar < 0xC0) {
+                iUTF2 = 0;
+                ul[nl - 1] = ichar + 64;
+            } else if (iUTF2 > 0xC3 && iUTF2 < 0xE0 && ichar > 0x7F && ichar < 0xC0) {
+                iUTF2 = 0;
+                ul[nl] = ichar;
+                nl++;
+            } else {
+                iUTF2 = 0;
+                ul[nl] = ichar;
+                ul[nl + 1] = '\0';
+                debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
+                if (ul)
+                    xfree(ul);
+                return NULL;
+            }
+        } else if (iUTF3) {
+            if (iUTF3 == 0xE0 && ichar > 0x9F && ichar < 0xC0) {
+                iUTF3 = 1;
+                ul[nl] = ichar;
+                nl++;
+            } else if (iUTF3 > 0xE0 && iUTF3 < 0xED && ichar > 0x7F && ichar < 0xC0) {
+                iUTF3 = 2;
+                ul[nl] = ichar;
+                nl++;
+            } else if (iUTF3 == 0xED && ichar > 0x7F && ichar < 0xA0) {
+                iUTF3 = 3;
+                ul[nl] = ichar;
+                nl++;
+            } else if (iUTF3 > 0xED && iUTF3 < 0xF0 && ichar > 0x7F && ichar < 0xC0) {
+                iUTF3 = 4;
+                ul[nl] = ichar;
+                nl++;
+            } else if (iUTF3 > 0 && iUTF3 < 5 && ichar > 0x7F && ichar < 0xC0) {
+                iUTF3 = 0;
+                ul[nl] = ichar;
+                nl++;
+            } else {
+                iUTF3 = 0;
+                ul[nl] = ichar;
+                ul[nl + 1] = '\0';
+                debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
+                if (ul)
+                    xfree(ul);
+                return NULL;
+            }
+        } else if (iUTF4) {
+            if (iUTF4 == 0xF0 && ichar > 0x8F && ichar < 0xC0) {
+                iUTF4 = 1;
+                ul[nl] = ichar;
+                nl++;
+            } else if (iUTF4 > 0xF0 && iUTF3 < 0xF4 && ichar > 0x7F && ichar < 0xC0) {
+                iUTF4 = 2;
+                ul[nl] = ichar;
+                nl++;
+            } else if (iUTF4 == 0xF4 && ichar > 0x7F && ichar < 0x90) {
+                iUTF4 = 3;
+                ul[nl] = ichar;
+                nl++;
+            } else if (iUTF4 > 0 && iUTF4 < 5 && ichar > 0x7F && ichar < 0xC0) {
+                if (iUTF4 == 4)
+                    iUTF4 = 0;
+                else
+                    iUTF4 = 4;
+                ul[nl] = ichar;
+                nl++;
+            } else {
+                iUTF4 = 0;
+                ul[nl] = ichar;
+                ul[nl + 1] = '\0';
+                debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
+                if (ul)
+                    xfree(ul);
+                return NULL;
+            }
+        } else if (ichar < 0x80) {
+            /* UTF1 */
+            ul[nl] = ichar;
+            nl++;
+        } else if (ichar > 0xC1 && ichar < 0xE0) {
+            /* UTF2 (Latin) */
+            iUTF2 = ichar;
+            ul[nl] = ichar;
+            nl++;
+        } else if (ichar > 0xDF && ichar < 0xF0) {
+            /* UTF3 */
+            iUTF3 = ichar;
+            ul[nl] = ichar;
+            nl++;
+        } else if (ichar > 0xEF && ichar < 0xF5) {
+            /* UTF4 */
+            iUTF4 = ichar;
+            ul[nl] = ichar;
+            nl++;
+        } else {
+            ul[nl] = ichar;
+            ul[nl + 1] = '\0';
+            debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
+            if (ul)
+                xfree(ul);
+            return NULL;
+        }
+        n++;
+    }
+
+    ul[nl] = '\0';
+    if (iUTF2 || iUTF3 || iUTF4) {
+        debug((char *) "%s| %s: INFO: iUTF2: %d iUTF3: %d iUTF4: %d\n", LogTime(), PROGRAM, iUTF2, iUTF3, iUTF4);
+        debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
+        if (ul)
+            xfree(ul);
+        return NULL;
+    }
+    if (flag && upd)
+        ul = strcat(ul, upd);
+    return ul;
+}
+
+
+int
+create_gd(struct main_args *margs)
+{
+    char *gp, *dp;
+    char *hp1, *hp2, *up;
+    char *p;
+    struct gdstruct *gdsp = NULL, *gdspn = NULL;
+    /*
+     *  Group list format:
+     *
+     *     glist=Pattern1[:Pattern2]
+     *
+     *     Pattern=Group           Group for all domains(including non Kerberos domains using ldap url options) if no
+     *                             other group definition for domain exists or users without
+     *                             domain information.
+     *                             gdstruct.domain=NULL, gdstruct.group=Group
+     *
+     *  or Pattern=Group@          Group for all Kerberos domains if no other group definition
+     *                             exists
+     *                             gdstruct.domain="", gdstruct.group=Group
+     *
+     *  or Pattern=Group@Domain    Group for a specific Kerberos domain
+     *                             gdstruct.domain=Domain, gdstruct.group=Group
+     *
+     *
+     */
+    hp1 = hex_utf_char(margs, 0);
+    hp2 = hex_utf_char(margs, 1);
+    up = utf8dup(margs);
+    p = up;
+    if (hp1) {
+        if (hp2) {
+            if (up) {
+                p = (char *) xmalloc(strlen(up) + strlen(hp1) + strlen(hp2) + 2);
+                strcpy(p, up);
+                strcat(p, ":");
+                strcat(p, hp1);
+                strcat(p, ":");
+                strcat(p, hp2);
+            } else {
+                p = (char *) xmalloc(strlen(hp1) + strlen(hp2) + 1);
+                strcpy(p, hp1);
+                strcat(p, ":");
+                strcat(p, hp2);
+            }
+        } else {
+            if (up) {
+                p = (char *) xmalloc(strlen(up) + strlen(hp1) + 1);
+                strcpy(p, up);
+                strcat(p, ":");
+                strcat(p, hp1);
+            } else
+                p = hp1;
+        }
+    } else {
+        if (hp2) {
+            if (up) {
+                p = (char *) xmalloc(strlen(up) + strlen(hp2) + 1);
+                strcpy(p, up);
+                strcat(p, ":");
+                strcat(p, hp2);
+            } else
+                p = hp2;
+        } else
+            p = up;
+    }
+    gp = p;
+    debug((char *) "%s| %s: INFO: Group list %s\n", LogTime(), PROGRAM, p ? p : "NULL");
+    dp = NULL;
+
+    if (!p) {
+        debug((char *) "%s| %s: ERROR: No groups defined.\n", LogTime(), PROGRAM);
+        return (1);
+    }
+    while (*p) {               /* loop over group list */
+        if (*p == '\n' || *p == '\r') {                /* Ignore CR and LF if exist */
+            p++;
+            continue;
+        }
+        if (*p == '@') {       /* end of group name - start of domain name */
+            if (p == gp) {     /* empty group name not allowed */
+                debug((char *) "%s| %s: ERROR: No group defined for domain %s\n", LogTime(), PROGRAM, p);
+                return (1);
+            }
+            *p = '\0';
+            p++;
+            gdsp = init_gd();
+            gdsp->group = gp;
+            if (gdspn)         /* Have already an existing structure */
+                gdsp->next = gdspn;
+            dp = p;            /* after @ starts new domain name */
+        } else if (*p == ':') {        /* end of group name or end of domain name */
+            if (p == gp) {     /* empty group name not allowed */
+                debug((char *) "%s| %s: ERROR: No group defined for domain %s\n", LogTime(), PROGRAM, p);
+                return (1);
+            }
+            *p = '\0';
+            p++;
+            if (dp) {          /* end of domain name */
+                gdsp->domain = xstrdup(dp);
+                dp = NULL;
+            } else {           /* end of group name and no domain name */
+                gdsp = init_gd();
+                gdsp->group = gp;
+                if (gdspn)     /* Have already an existing structure */
+                    gdsp->next = gdspn;
+            }
+            gdspn = gdsp;
+            gp = p;            /* after : starts new group name */
+            debug((char *) "%s| %s: INFO: Group %s  Domain %s\n", LogTime(), PROGRAM, gdsp->group, gdsp->domain ? gdsp->domain : "NULL");
+        } else
+            p++;
+    }
+    if (p == gp) {             /* empty group name not allowed */
+        debug((char *) "%s| %s: ERROR: No group defined for domain %s\n", LogTime(), PROGRAM, p);
+        return (1);
+    }
+    if (dp) {                  /* end of domain name */
+        gdsp->domain = xstrdup(dp);
+    } else {                   /* end of group name and no domain name */
+        gdsp = init_gd();
+        gdsp->group = gp;
+        if (gdspn)             /* Have already an existing structure */
+            gdsp->next = gdspn;
+    }
+    debug((char *) "%s| %s: INFO: Group %s  Domain %s\n", LogTime(), PROGRAM, gdsp->group, gdsp->domain ? gdsp->domain : "NULL");
+
+    margs->groups = gdsp;
+    return (0);
+}
+#endif
diff --git a/helpers/external_acl/kerberos_ldap_group/support_krb5.cc b/helpers/external_acl/kerberos_ldap_group/support_krb5.cc
new file mode 100644 (file)
index 0000000..51865bb
--- /dev/null
@@ -0,0 +1,338 @@
+/*
+ * ----------------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * -----------------------------------------------------------------------------
+ */
+
+#include "config.h"
+#include "util.h"
+
+#ifdef HAVE_LDAP
+
+#include "support.h"
+
+struct kstruct {
+    krb5_context context;
+    char *mem_cache_env;
+    krb5_ccache cc;
+} kparam;
+
+#define KT_PATH_MAX 256
+
+void
+krb5_cleanup()
+{
+    if (kparam.context) {
+        if (kparam.cc)
+            krb5_cc_destroy(kparam.context, kparam.cc);
+        krb5_free_context(kparam.context);
+    }
+}
+/*
+ * create Kerberos memory cache
+ */
+int
+krb5_create_cache(struct main_args *margs, char *domain)
+{
+
+    krb5_keytab keytab = 0;
+    krb5_keytab_entry entry;
+    krb5_kt_cursor cursor;
+    krb5_creds *creds = NULL;
+    krb5_creds *tgt_creds = NULL;
+    krb5_principal *principal_list = NULL;
+    krb5_principal principal = NULL;
+    char *service;
+    char *keytab_name = NULL, *principal_name = NULL, *mem_cache = NULL;
+    char buf[KT_PATH_MAX], *p;
+    int nprinc = 0;
+    int i;
+    int retval = 0;
+    int found = 0;
+    krb5_error_code code = 0;
+
+    kparam.context = NULL;
+
+    if (!domain || !strcmp(domain, ""))
+        return (1);
+
+    /*
+     * Initialise Kerberos
+     */
+
+    code = krb5_init_context(&kparam.context);
+    if (code) {
+        error((char *) "%s| %s: ERROR: Error while initialising Kerberos library : %s\n", LogTime(), PROGRAM, error_message(code));
+        retval = 1;
+        goto cleanup;
+    }
+    /*
+     * getting default keytab name
+     */
+
+    debug((char *) "%s| %s: DEBUG: Get default keytab file name\n", LogTime(), PROGRAM);
+    krb5_kt_default_name(kparam.context, buf, KT_PATH_MAX);
+    p = strchr(buf, ':');      /* Find the end if "FILE:" */
+    if (p)
+        p++;                   /* step past : */
+    keytab_name = xstrdup(p ? p : buf);
+    debug((char *) "%s| %s: DEBUG: Got default keytab file name %s\n", LogTime(), PROGRAM, keytab_name);
+
+    code = krb5_kt_resolve(kparam.context, keytab_name, &keytab);
+    if (code) {
+        error((char *) "%s| %s: ERROR: Error while resolving keytab %s : %s\n", LogTime(), PROGRAM, keytab_name, error_message(code));
+        retval = 1;
+        goto cleanup;
+    }
+    code = krb5_kt_start_seq_get(kparam.context, keytab, &cursor);
+    if (code) {
+        error((char *) "%s| %s: ERROR: Error while starting keytab scan : %s\n", LogTime(), PROGRAM, error_message(code));
+        retval = 1;
+        goto cleanup;
+    }
+    debug((char *) "%s| %s: DEBUG: Get principal name from keytab %s\n", LogTime(), PROGRAM, keytab_name);
+
+    nprinc = 0;
+    while ((code = krb5_kt_next_entry(kparam.context, keytab, &entry, &cursor)) == 0) {
+
+        principal_list = (krb5_principal *) xrealloc(principal_list, sizeof(krb5_principal) * (nprinc + 1));
+        krb5_copy_principal(kparam.context, entry.principal, &principal_list[nprinc++]);
+#ifdef HAVE_HEIMDAL_KERBEROS
+        debug((char *) "%s| %s: DEBUG: Keytab entry has realm name: %s\n", LogTime(), PROGRAM, entry.principal->realm);
+#else
+        debug((char *) "%s| %s: DEBUG: Keytab entry has realm name: %s\n", LogTime(), PROGRAM, krb5_princ_realm(kparam.context, entry.principal)->data);
+#endif
+#ifdef HAVE_HEIMDAL_KERBEROS
+        if (!strcasecmp(domain, entry.principal->realm))
+#else
+        if (!strcasecmp(domain, krb5_princ_realm(kparam.context, entry.principal)->data))
+#endif
+        {
+            code = krb5_unparse_name(kparam.context, entry.principal, &principal_name);
+            if (code) {
+                error((char *) "%s| %s: ERROR: Error while unparsing principal name : %s\n", LogTime(), PROGRAM, error_message(code));
+            } else {
+                debug((char *) "%s| %s: DEBUG: Found principal name: %s\n", LogTime(), PROGRAM, principal_name);
+                found = 1;
+            }
+        }
+#if defined(HAVE_HEIMDAL_KERBEROS) || ( defined(HAVE_KRB5_KT_FREE_ENTRY) && HAVE_DECL_KRB5_KT_FREE_ENTRY==1)
+        code = krb5_kt_free_entry(kparam.context, &entry);
+#else
+        code = krb5_free_keytab_entry_contents(kparam.context, &entry);
+#endif
+        if (code) {
+            error((char *) "%s| %s: ERROR: Error while freeing keytab entry : %s\n", LogTime(), PROGRAM, error_message(code));
+            retval = 1;
+            break;
+        }
+        if (found)
+            break;
+    }
+
+    if (code && code != KRB5_KT_END) {
+        error((char *) "%s| %s: ERROR: Error while scanning keytab : %s\n", LogTime(), PROGRAM, error_message(code));
+        retval = 1;
+        goto cleanup;
+    }
+    code = krb5_kt_end_seq_get(kparam.context, keytab, &cursor);
+    if (code) {
+        error((char *) "%s| %s: ERROR: Error while ending keytab scan : %s\n", LogTime(), PROGRAM, error_message(code));
+        retval = 1;
+        goto cleanup;
+    }
+    /*
+     * prepare memory credential cache
+     */
+#if  !defined(HAVE_KRB5_MEMORY_CACHE) || defined(HAVE_SUN_LDAP_SDK)
+    mem_cache = (char *) xmalloc(strlen("FILE:/tmp/squid_ldap_") + 16);
+    snprintf(mem_cache, strlen("FILE:/tmp/squid_ldap_") + 16, "FILE:/tmp/squid_ldap_%d", (int) getpid());
+#else
+    mem_cache = (char *) xmalloc(strlen("MEMORY:squid_ldap_") + 16);
+    snprintf(mem_cache, strlen("MEMORY:squid_ldap_") + 16, "MEMORY:squid_ldap_%d", (int) getpid());
+#endif
+
+    setenv("KRB5CCNAME", mem_cache, 1);
+    debug((char *) "%s| %s: DEBUG: Set credential cache to %s\n", LogTime(), PROGRAM, mem_cache);
+    code = krb5_cc_resolve(kparam.context, mem_cache, &kparam.cc);
+    if (code) {
+        error((char *) "%s| %s: ERROR: Error while resolving memory ccache : %s\n", LogTime(), PROGRAM, error_message(code));
+        retval = 1;
+        goto cleanup;
+    }
+    /*
+     * if no principal name found in keytab for domain use the prinipal name which can get a TGT
+     */
+    if (!principal_name) {
+        debug((char *) "%s| %s: DEBUG: Did not find a principal in keytab for domain %s.\n", LogTime(), PROGRAM, domain);
+        debug((char *) "%s| %s: DEBUG: Try to get principal of trusted domain.\n", LogTime(), PROGRAM);
+        creds = (krb5_creds *) xmalloc(sizeof(*creds));
+        memset(creds, 0, sizeof(*creds));
+
+        for (i = 0; i < nprinc; i++) {
+            /*
+             * get credentials
+             */
+            code = krb5_unparse_name(kparam.context, principal_list[i], &principal_name);
+            if (code) {
+                debug((char *) "%s| %s: DEBUG: Error while unparsing principal name : %s\n", LogTime(), PROGRAM, error_message(code));
+                goto loop_end;
+            }
+            debug((char *) "%s| %s: DEBUG: Keytab entry has principal: %s\n", LogTime(), PROGRAM, principal_name);
+
+#if HAVE_GET_INIT_CREDS_KEYTAB
+            code = krb5_get_init_creds_keytab(kparam.context, creds, principal_list[i], keytab, 0, NULL, NULL);
+#else
+            service = (char *) xmalloc(strlen("krbtgt") + 2 * strlen(domain) + 3);
+            snprintf(service, strlen("krbtgt") + 2 * strlen(domain) + 3, "krbtgt/%s@%s", domain, domain);
+            creds->client = principal_list[i];
+            code = krb5_parse_name(kparam.context, service, &creds->server);
+            if (service)
+                xfree(service);
+            code = krb5_get_in_tkt_with_keytab(kparam.context, 0, NULL, NULL, NULL, keytab, NULL, creds, 0);
+#endif
+            if (code) {
+                debug((char *) "%s| %s: DEBUG: Error while initialising credentials from keytab : %s\n", LogTime(), PROGRAM, error_message(code));
+                goto loop_end;
+            }
+            code = krb5_cc_initialize(kparam.context, kparam.cc, principal_list[i]);
+            if (code) {
+                error((char *) "%s| %s: ERROR: Error while initializing memory caches : %s\n", LogTime(), PROGRAM, error_message(code));
+                goto loop_end;
+            }
+            code = krb5_cc_store_cred(kparam.context, kparam.cc, creds);
+            if (code) {
+                debug((char *) "%s| %s: DEBUG: Error while storing credentials : %s\n", LogTime(), PROGRAM, error_message(code));
+                goto loop_end;
+            }
+            if (creds->server)
+                krb5_free_principal(kparam.context, creds->server);
+#ifdef HAVE_HEIMDAL_KERBEROS
+            service = (char *) xmalloc(strlen("krbtgt") + strlen(domain) + strlen(principal_list[i]->realm) + 3);
+            snprintf(service, strlen("krbtgt") + strlen(domain) + strlen(principal_list[i]->realm) + 3, "krbtgt/%s@%s", domain, principal_list[i]->realm);
+#else
+            service = (char *) xmalloc(strlen("krbtgt") + strlen(domain) + strlen(krb5_princ_realm(kparam.context, principal_list[i])->data) + 3);
+            snprintf(service, strlen("krbtgt") + strlen(domain) + strlen(krb5_princ_realm(kparam.context, principal_list[i])->data) + 3, "krbtgt/%s@%s", domain, krb5_princ_realm(kparam.context, principal_list[i])->data);
+#endif
+            code = krb5_parse_name(kparam.context, service, &creds->server);
+            if (service)
+                xfree(service);
+            if (code) {
+                error((char *) "%s| %s: ERROR: Error while initialising TGT credentials : %s\n", LogTime(), PROGRAM, error_message(code));
+                goto loop_end;
+            }
+            code = krb5_get_credentials(kparam.context, 0, kparam.cc, creds, &tgt_creds);
+            if (code) {
+                debug((char *) "%s| %s: DEBUG: Error while getting tgt : %s\n", LogTime(), PROGRAM, error_message(code));
+                goto loop_end;
+            } else {
+                debug((char *) "%s| %s: DEBUG: Found trusted principal name: %s\n", LogTime(), PROGRAM, principal_name);
+                found = 1;
+                break;
+            }
+
+loop_end:
+            if (principal_name)
+                xfree(principal_name);
+            principal_name = NULL;
+        }
+
+        if (tgt_creds)
+            krb5_free_creds(kparam.context, tgt_creds);
+        tgt_creds = NULL;
+        if (creds)
+            krb5_free_creds(kparam.context, creds);
+        creds = NULL;
+    }
+    if (principal_name) {
+
+        debug((char *) "%s| %s: DEBUG: Got principal name %s\n", LogTime(), PROGRAM, principal_name);
+        /*
+         * build principal
+         */
+        code = krb5_parse_name(kparam.context, principal_name, &principal);
+        if (code) {
+            error((char *) "%s| %s: ERROR: Error while parsing name %s : %s\n", LogTime(), PROGRAM, principal_name, error_message(code));
+            retval = 1;
+            goto cleanup;
+        }
+        creds = (krb5_creds *) xmalloc(sizeof(*creds));
+        memset(creds, 0, sizeof(*creds));
+
+        /*
+         * get credentials
+         */
+#if HAVE_GET_INIT_CREDS_KEYTAB
+        code = krb5_get_init_creds_keytab(kparam.context, creds, principal, keytab, 0, NULL, NULL);
+#else
+        service = (char *) xmalloc(strlen("krbtgt") + 2 * strlen(domain) + 3);
+        snprintf(service, strlen("krbtgt") + 2 * strlen(domain) + 3, "krbtgt/%s@%s", domain, domain);
+        creds->client = principal;
+        code = krb5_parse_name(kparam.context, service, &creds->server);
+        if (service)
+            xfree(service);
+        code = krb5_get_in_tkt_with_keytab(kparam.context, 0, NULL, NULL, NULL, keytab, NULL, creds, 0);
+#endif
+        if (code) {
+            error((char *) "%s| %s: ERROR: Error while initialising credentials from keytab : %s\n", LogTime(), PROGRAM, error_message(code));
+            retval = 1;
+            goto cleanup;
+        }
+        code = krb5_cc_initialize(kparam.context, kparam.cc, principal);
+        if (code) {
+            error((char *) "%s| %s: ERROR: Error while initializing memory caches : %s\n", LogTime(), PROGRAM, error_message(code));
+            retval = 1;
+            goto cleanup;
+        }
+        code = krb5_cc_store_cred(kparam.context, kparam.cc, creds);
+        if (code) {
+            error((char *) "%s| %s: ERROR: Error while storing credentials : %s\n", LogTime(), PROGRAM, error_message(code));
+            retval = 1;
+            goto cleanup;
+        }
+        debug((char *) "%s| %s: DEBUG: Stored credentials\n", LogTime(), PROGRAM);
+    } else {
+        debug((char *) "%s| %s: DEBUG: Got no principal name\n", LogTime(), PROGRAM);
+        retval = 1;
+    }
+cleanup:
+    if (keytab)
+        krb5_kt_close(kparam.context, keytab);
+    if (keytab_name)
+        xfree(keytab_name);
+    if (principal_name)
+        xfree(principal_name);
+    if (mem_cache)
+        xfree(mem_cache);
+    if (principal)
+        krb5_free_principal(kparam.context, principal);
+    for (i = 0; i < nprinc; i++) {
+        if (principal_list[i])
+            krb5_free_principal(kparam.context, principal_list[i]);
+    }
+    if (principal_list)
+        xfree(principal_list);
+    if (creds)
+        krb5_free_creds(kparam.context, creds);
+
+    return (retval);
+}
+#endif
diff --git a/helpers/external_acl/kerberos_ldap_group/support_ldap.cc b/helpers/external_acl/kerberos_ldap_group/support_ldap.cc
new file mode 100644 (file)
index 0000000..f2a5fef
--- /dev/null
@@ -0,0 +1,1218 @@
+/*
+ * -----------------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * -----------------------------------------------------------------------------
+ */
+
+#include "config.h"
+#include "util.h"
+
+#ifdef HAVE_LDAP
+
+#include "support.h"
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+char *convert_domain_to_bind_path(char *domain);
+char *escape_filter(char *filter);
+int check_AD(struct main_args *margs, LDAP * ld);
+int ldap_set_defaults(struct main_args *margs, LDAP * ld);
+int ldap_set_ssl_defaults(struct main_args *margs);
+LDAP *tool_ldap_open(struct main_args *margs, char *host, int port, char *ssl);
+
+#define CONNECT_TIMEOUT 2
+#define SEARCH_TIMEOUT 30
+
+#define FILTER "(memberuid=%s)"
+#define ATTRIBUTE "cn"
+#define FILTER_UID "(uid=%s)"
+#define FILTER_GID "(&(gidNumber=%s)(objectclass=posixgroup))"
+#define ATTRIBUTE_GID "gidNumber"
+
+#define FILTER_AD "(samaccountname=%s)"
+#define ATTRIBUTE_AD "memberof"
+
+int get_attributes(struct main_args *margs, LDAP * ld, LDAPMessage * res, const char *attribute /* IN */ , char ***out_val /* OUT (caller frees) */ );
+int search_group_tree(struct main_args *margs, LDAP * ld, char *bindp, char *ldap_group, char *group, int depth);
+
+#if defined(HAVE_SUN_LDAP_SDK) || defined(HAVE_MOZILLA_LDAP_SDK)
+#ifdef HAVE_LDAP_REBINDPROC_CALLBACK
+
+#if defined(HAVE_SASL_H) || defined(HAVE_SASL_SASL_H) || defined(HAVE_SASL_DARWIN)
+static LDAP_REBINDPROC_CALLBACK ldap_sasl_rebind;
+
+static int LDAP_CALL LDAP_CALLBACK
+ldap_sasl_rebind(
+    LDAP * ld,
+    char **whop,
+    char **credp,
+    int *methodp,
+    int freeit,
+    void *params)
+{
+    struct ldap_creds *cp = (struct ldap_creds *) params;
+    whop = whop;
+    credp = credp;
+    methodp = methodp;
+    freeit = freeit;
+    return tool_sasl_bind(ld, cp->dn, cp->pw);
+}
+#endif
+
+static LDAP_REBINDPROC_CALLBACK ldap_simple_rebind;
+
+static int LDAP_CALL LDAP_CALLBACK
+ldap_simple_rebind(
+    LDAP * ld,
+    char **whop,
+    char **credp,
+    int *methodp,
+    int freeit,
+    void *params)
+{
+    struct ldap_creds *cp = (struct ldap_creds *) params;
+    whop = whop;
+    credp = credp;
+    methodp = methodp;
+    freeit = freeit;
+    return ldap_bind_s(ld, cp->dn, cp->pw, LDAP_AUTH_SIMPLE);
+}
+#elif defined(HAVE_LDAP_REBIND_PROC)
+#if defined(HAVE_SASL_H) || defined(HAVE_SASL_SASL_H) || defined(HAVE_SASL_DARWIN)
+static LDAP_REBIND_PROC ldap_sasl_rebind;
+
+static int
+ldap_sasl_rebind(
+    LDAP * ld,
+    LDAP_CONST char *url,
+    ber_tag_t request,
+    ber_int_t msgid,
+    void *params)
+{
+    struct ldap_creds *cp = (struct ldap_creds *) params;
+    url = url;
+    request = request;
+    msgid = msgid;
+    return tool_sasl_bind(ld, cp->dn, cp->pw);
+}
+#endif
+
+static LDAP_REBIND_PROC ldap_simple_rebind;
+
+static int
+ldap_simple_rebind(
+    LDAP * ld,
+    LDAP_CONST char *url,
+    ber_tag_t request,
+    ber_int_t msgid,
+    void *params)
+{
+    struct ldap_creds *cp = (struct ldap_creds *) params;
+    url = url;
+    request = request;
+    msgid = msgid;
+    return ldap_bind_s(ld, cp->dn, cp->pw, LDAP_AUTH_SIMPLE);
+}
+
+#elif defined(HAVE_LDAP_REBIND_FUNCTION)
+#ifndef LDAP_REFERRALS
+#define LDAP_REFERRALS
+#endif
+#if defined(HAVE_SASL_H) || defined(HAVE_SASL_SASL_H) || defined(HAVE_SASL_DARWIN)
+static LDAP_REBIND_FUNCTION ldap_sasl_rebind;
+
+static int
+ldap_sasl_rebind(
+    LDAP * ld,
+    char **whop,
+    char **credp,
+    int *methodp,
+    int freeit,
+    void *params)
+{
+    struct ldap_creds *cp = (struct ldap_creds *) params;
+    whop = whop;
+    credp = credp;
+    methodp = methodp;
+    freeit = freeit;
+    return tool_sasl_bind(ld, cp->dn, cp->pw);
+}
+#endif
+
+static LDAP_REBIND_FUNCTION ldap_simple_rebind;
+
+static int
+ldap_simple_rebind(
+    LDAP * ld,
+    char **whop,
+    char **credp,
+    int *methodp,
+    int freeit,
+    void *params)
+{
+    struct ldap_creds *cp = (struct ldap_creds *) params;
+    whop = whop;
+    credp = credp;
+    methodp = methodp;
+    freeit = freeit;
+    return ldap_bind_s(ld, cp->dn, cp->pw, LDAP_AUTH_SIMPLE);
+}
+#else
+#error "No rebind functione defined"
+#endif
+#else /* HAVE_SUN_LDAP_SDK */
+#if defined(HAVE_SASL_H) || defined(HAVE_SASL_SASL_H) || defined(HAVE_SASL_DARWIN)
+static LDAP_REBIND_PROC ldap_sasl_rebind;
+
+static int
+ldap_sasl_rebind(
+    LDAP * ld,
+    LDAP_CONST char *url,
+    ber_tag_t request,
+    ber_int_t msgid,
+    void *params)
+{
+    struct ldap_creds *cp = (struct ldap_creds *) params;
+    url = url;
+    request = request;
+    msgid = msgid;
+    return tool_sasl_bind(ld, cp->dn, cp->pw);
+}
+#endif
+
+static LDAP_REBIND_PROC ldap_simple_rebind;
+
+static int
+ldap_simple_rebind(
+    LDAP * ld,
+    LDAP_CONST char *url,
+    ber_tag_t request,
+    ber_int_t msgid,
+    void *params)
+{
+
+    struct ldap_creds *cp = (struct ldap_creds *) params;
+    url = url;
+    request = request;
+    msgid = msgid;
+    return ldap_bind_s(ld, cp->dn, cp->pw, LDAP_AUTH_SIMPLE);
+}
+
+#endif
+char *
+convert_domain_to_bind_path(char *domain)
+{
+    char *dp, *bindp = NULL, *bp = NULL;
+    int i = 0;
+
+    if (!domain)
+        return NULL;
+
+    for (dp = domain; *dp; dp++) {
+        if (*dp == '.')
+            i++;
+    }
+    /*
+     * add dc= and
+     * replace . with ,dc= => new length = old length + #dots * 3 + 3
+     */
+    bindp = (char *) xmalloc(strlen(domain) + 3 + i * 3 + 1);
+    bp = bindp;
+    strcpy(bp, "dc=");
+    bp += 3;
+    for (dp = domain; *dp; dp++) {
+        if (*dp == '.') {
+            strcpy(bp, ",dc=");
+            bp += 4;
+        } else
+            *bp++ = *dp;
+    }
+    *bp = '\0';
+    return bindp;
+}
+
+char *
+escape_filter(char *filter)
+{
+    int i;
+    char *ldap_filter_esc, *ldf;
+
+    i = 0;
+    for (ldap_filter_esc = filter; *ldap_filter_esc; ldap_filter_esc++) {
+        if ((*ldap_filter_esc == '*') ||
+                (*ldap_filter_esc == '(') ||
+                (*ldap_filter_esc == ')') ||
+                (*ldap_filter_esc == '\\'))
+            i = i + 3;
+    }
+
+    ldap_filter_esc = (char *) xcalloc(strlen(filter) + i + 1, sizeof(char));
+    ldf = ldap_filter_esc;
+    for (; *filter; filter++) {
+        if (*filter == '*') {
+            strcpy(ldf, "\\2a");
+            ldf = ldf + 3;
+        } else if (*filter == '(') {
+            strcpy(ldf, "\\28");
+            ldf = ldf + 3;
+        } else if (*filter == ')') {
+            strcpy(ldf, "\\29");
+            ldf = ldf + 3;
+        } else if (*filter == '\\') {
+            strcpy(ldf, "\\5c");
+            ldf = ldf + 3;
+        } else {
+            *ldf = *filter;
+            ldf++;
+        }
+    }
+    *ldf = '\0';
+
+    return ldap_filter_esc;
+};
+
+int
+check_AD(struct main_args *margs, LDAP * ld)
+{
+    LDAPMessage *res;
+    char **attr_value = NULL;
+    struct timeval searchtime;
+    int max_attr = 0;
+    int j, rc = 0;
+
+#define FILTER_SCHEMA "(objectclass=*)"
+#define ATTRIBUTE_SCHEMA "schemaNamingContext"
+#define FILTER_SAM "(ldapdisplayname=samaccountname)"
+
+    searchtime.tv_sec = SEARCH_TIMEOUT;
+    searchtime.tv_usec = 0;
+
+    debug((char *) "%s| %s: DEBUG: Search ldap server with bind path \"\" and filter: %s\n", LogTime(), PROGRAM, FILTER_SCHEMA);
+    rc = ldap_search_ext_s(ld, (char *) "", LDAP_SCOPE_BASE, (char *) FILTER_SCHEMA, NULL, 0,
+                           NULL, NULL, &searchtime, 0, &res);
+
+    if (rc == LDAP_SUCCESS)
+        max_attr = get_attributes(margs, ld, res, ATTRIBUTE_SCHEMA, &attr_value);
+
+    if (max_attr == 1) {
+        ldap_msgfree(res);
+        debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n", LogTime(), PROGRAM, attr_value[0], FILTER_SAM);
+        rc = ldap_search_ext_s(ld, attr_value[0], LDAP_SCOPE_SUBTREE, (char *) FILTER_SAM, NULL, 0,
+                               NULL, NULL, &searchtime, 0, &res);
+        debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM, ldap_count_entries(ld, res), ldap_count_entries(ld, res) > 1 || ldap_count_entries(ld, res) == 0 ? "ies" : "y");
+        if (ldap_count_entries(ld, res) > 0)
+            margs->AD = 1;
+    } else
+        debug((char *) "%s| %s: DEBUG: Did not find ldap entry for subschemasubentry\n", LogTime(), PROGRAM);
+    debug((char *) "%s| %s: DEBUG: Determined ldap server %sas an Active Directory server\n", LogTime(), PROGRAM, margs->AD ? "" : "not ");
+    /*
+     * Cleanup
+     */
+    if (attr_value) {
+        for (j = 0; j < max_attr; j++) {
+            xfree(attr_value[j]);
+        }
+        xfree(attr_value);
+        attr_value = NULL;
+    }
+    ldap_msgfree(res);
+    return rc;
+}
+int
+search_group_tree(struct main_args *margs, LDAP * ld, char *bindp, char *ldap_group, char *group, int depth)
+{
+    LDAPMessage *res = NULL;
+    char **attr_value = NULL;
+    int max_attr = 0;
+    char *filter = NULL;
+    char *search_exp = NULL;
+    int j, rc = 0, retval = 0;
+    char *av = NULL, *avp = NULL;
+    int ldepth;
+    char *ldap_filter_esc = NULL;
+    struct timeval searchtime;
+
+#define FILTER_GROUP_AD "(&(%s)(objectclass=group))"
+#define FILTER_GROUP "(&(memberuid=%s)(objectclass=posixgroup))"
+
+    searchtime.tv_sec = SEARCH_TIMEOUT;
+    searchtime.tv_usec = 0;
+
+    if (margs->AD)
+        filter = (char *) FILTER_GROUP_AD;
+    else
+        filter = (char *) FILTER_GROUP;
+
+    ldap_filter_esc = escape_filter(ldap_group);
+
+    search_exp = (char *) xmalloc(strlen(filter) + strlen(ldap_filter_esc) + 1);
+    snprintf(search_exp, strlen(filter) + strlen(ldap_filter_esc) + 1, filter, ldap_filter_esc);
+
+    if (ldap_filter_esc)
+        xfree(ldap_filter_esc);
+
+    if (depth > margs->mdepth) {
+        debug((char *) "%s| %s: DEBUG: Max search depth reached %d>%d\n", LogTime(), PROGRAM, depth, margs->mdepth);
+        return 0;
+    }
+    debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter : %s\n", LogTime(), PROGRAM, bindp, search_exp);
+    rc = ldap_search_ext_s(ld, bindp, LDAP_SCOPE_SUBTREE,
+                           search_exp, NULL, 0,
+                           NULL, NULL, &searchtime, 0, &res);
+    if (search_exp)
+        xfree(search_exp);
+
+    if (rc != LDAP_SUCCESS) {
+        error((char *) "%s| %s: ERROR: Error searching ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+        ldap_unbind_s(ld);
+        return 0;
+    }
+    debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM, ldap_count_entries(ld, res), ldap_count_entries(ld, res) > 1 || ldap_count_entries(ld, res) == 0 ? "ies" : "y");
+
+    if (margs->AD)
+        max_attr = get_attributes(margs, ld, res, ATTRIBUTE_AD, &attr_value);
+    else
+        max_attr = get_attributes(margs, ld, res, ATTRIBUTE, &attr_value);
+
+    /*
+     * Compare group names
+     */
+    retval = 0;
+    ldepth = depth + 1;
+    for (j = 0; j < max_attr; j++) {
+
+        /* Compare first CN= value assuming it is the same as the group name itself */
+        av = attr_value[j];
+        if (!strncasecmp("CN=", av, 3)) {
+            av += 3;
+            if ((avp = strchr(av, ','))) {
+                *avp = '\0';
+            }
+        }
+        if (debug_enabled) {
+            int n;
+            debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" in hex UTF-8 is ", LogTime(), PROGRAM, j + 1, av);
+            for (n = 0; av[n] != '\0'; n++)
+                fprintf(stderr, "%02x", (unsigned char) av[n]);
+            fprintf(stderr, "\n");
+        }
+        if (!strcasecmp(group, av)) {
+            retval = 1;
+            debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
+            break;
+        } else
+            debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" does not match group name \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
+        /*
+         * Do recursive group search
+         */
+        debug((char *) "%s| %s: DEBUG: Perform recursive group search for group \"%s\"\n", LogTime(), PROGRAM, av);
+        av = attr_value[j];
+        if (search_group_tree(margs, ld, bindp, av, group, ldepth)) {
+            retval = 1;
+            if (!strncasecmp("CN=", av, 3)) {
+                av += 3;
+                if ((avp = strchr(av, ','))) {
+                    *avp = '\0';
+                }
+            }
+            if (debug_enabled)
+                debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" is member of group named \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
+            else
+                break;
+
+        }
+    }
+
+    /*
+     * Cleanup
+     */
+    if (attr_value) {
+        for (j = 0; j < max_attr; j++) {
+            xfree(attr_value[j]);
+        }
+        xfree(attr_value);
+        attr_value = NULL;
+    }
+    ldap_msgfree(res);
+
+    return retval;
+}
+
+int
+ldap_set_defaults(struct main_args *margs, LDAP * ld)
+{
+    int val, rc = 0;
+#ifdef LDAP_OPT_NETWORK_TIMEOUT
+    struct timeval tv;
+#endif
+    val = LDAP_VERSION3;
+    rc = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &val);
+    if (rc != LDAP_SUCCESS) {
+        debug((char *) "%s| %s: DEBUG: Error while setting protocol version: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+        return rc;
+    }
+    rc = ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
+    if (rc != LDAP_SUCCESS) {
+        debug((char *) "%s| %s: DEBUG: Error while setting referrals off: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+        return rc;
+    }
+#ifdef LDAP_OPT_NETWORK_TIMEOUT
+    tv.tv_sec = CONNECT_TIMEOUT;
+    tv.tv_usec = 0;
+    rc = ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &tv);
+    if (rc != LDAP_SUCCESS) {
+        debug((char *) "%s| %s: DEBUG: Error while setting network timeout: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+        return rc;
+    }
+#endif /* LDAP_OPT_NETWORK_TIMEOUT */
+    return LDAP_SUCCESS;
+}
+
+int
+ldap_set_ssl_defaults(struct main_args *margs)
+{
+#if defined(HAVE_OPENLDAP) || defined(HAVE_LDAPSSL_CLIENT_INIT)
+    int rc = 0;
+#endif
+#ifdef HAVE_OPENLDAP
+    int val;
+    char *ssl_cacertfile = NULL;
+    int free_path;
+#elif defined(HAVE_LDAPSSL_CLIENT_INIT)
+    char *ssl_certdbpath = NULL;
+#endif
+
+#ifdef HAVE_OPENLDAP
+    if (!margs->rc_allow) {
+        debug((char *) "%s| %s: DEBUG: Enable server certificate check for ldap server.\n", LogTime(), PROGRAM);
+        val = LDAP_OPT_X_TLS_DEMAND;
+        rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &val);
+        if (rc != LDAP_SUCCESS) {
+            error((char *) "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_REQUIRE_CERT DEMAND for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+            return rc;
+        }
+        ssl_cacertfile = getenv("TLS_CACERTFILE");
+        free_path = 0;
+        if (!ssl_cacertfile) {
+            ssl_cacertfile = xstrdup("/etc/ssl/certs/cert.pem");
+            free_path = 1;
+        }
+        debug((char *) "%s| %s: DEBUG: Set certificate file for ldap server to %s.(Changeable through setting environment variable TLS_CACERTFILE)\n", LogTime(), PROGRAM, ssl_cacertfile);
+        rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, ssl_cacertfile);
+        if (ssl_cacertfile && free_path) {
+            xfree(ssl_cacertfile);
+            ssl_cacertfile = NULL;
+        }
+        if (rc != LDAP_OPT_SUCCESS) {
+            error((char *) "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_CACERTFILE for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+            return rc;
+        }
+    } else {
+        debug((char *) "%s| %s: DEBUG: Disable server certificate check for ldap server.\n", LogTime(), PROGRAM);
+        val = LDAP_OPT_X_TLS_ALLOW;
+        rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &val);
+        if (rc != LDAP_SUCCESS) {
+            error((char *) "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_REQUIRE_CERT ALLOW for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+            return rc;
+        }
+    }
+#elif defined(HAVE_LDAPSSL_CLIENT_INIT)
+    /*
+     *  Solaris SSL ldap calls require path to certificate database
+     */
+    /*
+     * rc = ldapssl_client_init( ssl_certdbpath, NULL );
+     * rc = ldapssl_advclientauth_init( ssl_certdbpath, NULL , 0 , NULL, NULL, 0, NULL, 2);
+     */
+    ssl_certdbpath = getenv("SSL_CERTDBPATH");
+    if (!ssl_certdbpath) {
+        ssl_certdbpath = xstrdup("/etc/certs");
+    }
+    debug((char *) "%s| %s: DEBUG: Set certificate database path for ldap server to %s.(Changeable through setting environment variable SSL_CERTDBPATH)\n", LogTime(), PROGRAM, ssl_certdbpath);
+    if (!margs->rc_allow) {
+        rc = ldapssl_advclientauth_init(ssl_certdbpath, NULL, 0, NULL, NULL, 0, NULL, 2);
+    } else {
+        rc = ldapssl_advclientauth_init(ssl_certdbpath, NULL, 0, NULL, NULL, 0, NULL, 0);
+        debug((char *) "%s| %s: DEBUG: Disable server certificate check for ldap server.\n", LogTime(), PROGRAM);
+    }
+    if (ssl_certdbpath) {
+        xfree(ssl_certdbpath);
+        ssl_certdbpath = NULL;
+    }
+    if (rc != LDAP_SUCCESS) {
+        error((char *) "%s| %s: ERROR: Error while setting SSL for ldap server: %s\n", LogTime(), PROGRAM, ldapssl_err2string(rc));
+        return rc;
+    }
+#else
+    error((char *) "%s| %s: ERROR: SSL not supported by ldap library\n", LogTime(), PROGRAM);
+#endif
+    return LDAP_SUCCESS;
+}
+
+int
+get_attributes(struct main_args *margs, LDAP * ld, LDAPMessage * res, const char *attribute, char ***ret_value)
+{
+
+    LDAPMessage *msg;
+    char **attr_value = NULL;
+    int max_attr = 0;
+
+    attr_value = *ret_value;
+    /*
+     * loop over attributes
+     */
+    debug((char *) "%s| %s: DEBUG: Search ldap entries for attribute : %s\n", LogTime(), PROGRAM, attribute);
+    for (msg = ldap_first_entry(ld, res); msg; msg = ldap_next_entry(ld, msg)) {
+
+        BerElement *b;
+        char *attr;
+
+        switch (ldap_msgtype(msg)) {
+
+        case LDAP_RES_SEARCH_ENTRY:
+
+            for (attr = ldap_first_attribute(ld, msg, &b); attr;
+                    attr = ldap_next_attribute(ld, msg, b)) {
+                if (strcasecmp(attr, attribute) == 0) {
+                    struct berval **values;
+                    int il;
+
+                    if ((values = ldap_get_values_len(ld, msg, attr)) != NULL) {
+                        for (il = 0; values[il] != NULL; il++) {
+
+                            attr_value = (char **) xrealloc(attr_value, (il + 1) * sizeof(char *));
+                            if (!attr_value)
+                                break;
+
+                            attr_value[il] = (char *) xmalloc(values[il]->bv_len + 1);
+                            memcpy(attr_value[il], values[il]->bv_val, values[il]->bv_len);
+                            attr_value[il][values[il]->bv_len] = 0;
+                        }
+                        max_attr = il;
+                    }
+                    ber_bvecfree(values);
+                }
+                ldap_memfree(attr);
+            }
+            ber_free(b, 0);
+            break;
+        case LDAP_RES_SEARCH_REFERENCE:
+            debug((char *) "%s| %s: DEBUG: Received a search reference message\n", LogTime(), PROGRAM);
+            break;
+        case LDAP_RES_SEARCH_RESULT:
+            debug((char *) "%s| %s: DEBUG: Received a search result message\n", LogTime(), PROGRAM);
+            break;
+        default:
+            break;
+        }
+    }
+
+    debug((char *) "%s| %s: DEBUG: %d ldap entr%s found with attribute : %s\n", LogTime(), PROGRAM, max_attr, max_attr > 1 || max_attr == 0 ? "ies" : "y", attribute);
+
+    *ret_value = attr_value;
+    return max_attr;
+}
+
+/*
+ * call to open ldap server with or without SSL
+ */
+LDAP *
+tool_ldap_open(struct main_args * margs, char *host, int port, char *ssl)
+{
+    LDAP *ld;
+#ifdef HAVE_OPENLDAP
+    LDAPURLDesc *url = NULL;
+    char *ldapuri = NULL;
+#endif
+    int rc = 0;
+
+    /*
+     * Use ldap open here to check if TCP connection is possible. If possible use it.
+     * (Not sure if this is the best way)
+     */
+#ifdef HAVE_OPENLDAP
+    url = (LDAPURLDesc *) xmalloc(sizeof(*url));
+    memset(url, 0, sizeof(*url));
+#ifdef HAVE_LDAP_URL_LUD_SCHEME
+    if (ssl)
+        url->lud_scheme = (char *) "ldaps";
+    else
+        url->lud_scheme = (char *) "ldap";
+#endif
+    url->lud_host = host;
+    url->lud_port = port;
+#ifdef HAVE_LDAP_SCOPE_DEFAULT
+    url->lud_scope = LDAP_SCOPE_DEFAULT;
+#else
+    url->lud_scope = LDAP_SCOPE_SUBTREE;
+#endif
+#ifdef HAVE_LDAP_URL_DESC2STR
+    ldapuri = ldap_url_desc2str(url);
+#elif defined(HAVE_LDAP_URL_PARSE)
+    rc = ldap_url_parse(ldapuri, &url);
+    if (rc != LDAP_SUCCESS) {
+        error((char *) "%s| %s: ERROR: Error while parsing url: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+        if (ldapuri)
+            xfree(ldapuri);
+        if (url)
+            xfree(url);
+        return NULL;
+    }
+#else
+#error "No URL parsing function"
+#endif
+    if (url) {
+        xfree(url);
+        url = NULL;
+    }
+    rc = ldap_initialize(&ld, ldapuri);
+    if (ldapuri)
+        xfree(ldapuri);
+    if (rc != LDAP_SUCCESS) {
+        error((char *) "%s| %s: ERROR: Error while initialising connection to ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+        ldap_unbind(ld);
+        ld = NULL;
+        return NULL;
+    }
+#else
+    ld = ldap_init(host, port);
+#endif
+    rc = ldap_set_defaults(margs, ld);
+    if (rc != LDAP_SUCCESS) {
+        error((char *) "%s| %s: ERROR: Error while setting default options for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+        ldap_unbind(ld);
+        ld = NULL;
+        return NULL;
+    }
+    if (ssl) {
+        /*
+         * Try Start TLS first
+         */
+        debug((char *) "%s| %s: DEBUG: Set SSL defaults\n", LogTime(), PROGRAM);
+        rc = ldap_set_ssl_defaults(margs);
+        if (rc != LDAP_SUCCESS) {
+            error((char *) "%s| %s: ERROR: Error while setting SSL default options for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+            ldap_unbind(ld);
+            ld = NULL;
+            return NULL;
+        }
+#ifdef HAVE_OPENLDAP
+        /*
+         *  Use tls if possible
+         */
+        rc = ldap_start_tls_s(ld, NULL, NULL);
+        if (rc != LDAP_SUCCESS) {
+            error((char *) "%s| %s: ERROR: Error while setting start_tls for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+            ldap_unbind(ld);
+            ld = NULL;
+            url = (LDAPURLDesc *) xmalloc(sizeof(*url));
+            memset(url, 0, sizeof(*url));
+#ifdef HAVE_LDAP_URL_LUD_SCHEME
+            url->lud_scheme = (char *) "ldaps";
+#endif
+            url->lud_host = host;
+            url->lud_port = port;
+#ifdef HAVE_LDAP_SCOPE_DEFAULT
+            url->lud_scope = LDAP_SCOPE_DEFAULT;
+#else
+            url->lud_scope = LDAP_SCOPE_SUBTREE;
+#endif
+#ifdef HAVE_LDAP_URL_DESC2STR
+            ldapuri = ldap_url_desc2str(url);
+#elif defined(HAVE_LDAP_URL_PARSE)
+            rc = ldap_url_parse(ldapuri, &url);
+            if (rc != LDAP_SUCCESS) {
+                error((char *) "%s| %s: ERROR: Error while parsing url: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+                if (ldapuri)
+                    xfree(ldapuri);
+                if (url)
+                    xfree(url);
+                return NULL;
+            }
+#else
+#error "No URL parsing function"
+#endif
+            if (url) {
+                xfree(url);
+                url = NULL;
+            }
+            rc = ldap_initialize(&ld, ldapuri);
+            if (ldapuri)
+                xfree(ldapuri);
+            if (rc != LDAP_SUCCESS) {
+                error((char *) "%s| %s: ERROR: Error while initialising connection to ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+                ldap_unbind(ld);
+                ld = NULL;
+                return NULL;
+            }
+            rc = ldap_set_defaults(margs, ld);
+            if (rc != LDAP_SUCCESS) {
+                error((char *) "%s| %s: ERROR: Error while setting default options for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+                ldap_unbind(ld);
+                ld = NULL;
+                return NULL;
+            }
+        }
+#elif defined(HAVE_LDAPSSL_CLIENT_INIT)
+        ld = ldapssl_init(host, port, 1);
+        if (!ld) {
+            error((char *) "%s| %s: ERROR: Error while setting SSL for ldap server: %s\n", LogTime(), PROGRAM, ldapssl_err2string(rc));
+            ldap_unbind(ld);
+            ld = NULL;
+            return NULL;
+        }
+        rc = ldap_set_defaults(margs, ld);
+        if (rc != LDAP_SUCCESS) {
+            error((char *) "%s| %s: ERROR: Error while setting default options for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+            ldap_unbind(ld);
+            ld = NULL;
+            return NULL;
+        }
+#else
+        error((char *) "%s| %s: ERROR: SSL not supported by ldap library\n", LogTime(), PROGRAM);
+#endif
+    }
+    return ld;
+}
+
+/*
+ * ldap calls to get attribute from Ldap Directory Server
+ */
+int
+get_memberof(struct main_args *margs, char *user, char *domain, char *group)
+{
+    LDAP *ld = NULL;
+    LDAPMessage *res;
+#ifndef HAVE_SUN_LDAP_SDK
+    int ldap_debug = 0;
+#endif
+    struct ldap_creds *lcreds = NULL;
+    char *bindp = NULL;
+    char *filter = NULL;
+    char *search_exp;
+    struct timeval searchtime;
+    int i, j, rc = 0, kc = 1;
+    int retval;
+    char **attr_value = NULL;
+    char *av = NULL, *avp = NULL;
+    int max_attr = 0;
+    struct hstruct *hlist = NULL;
+    int nhosts = 0;
+    char *hostname;
+    char *host;
+    int port;
+    char *ssl = NULL;
+    char *p;
+    char *ldap_filter_esc = NULL;
+
+
+    searchtime.tv_sec = SEARCH_TIMEOUT;
+    searchtime.tv_usec = 0;
+    /*
+     * Fill Kerberos memory cache with credential from keytab for SASL/GSSAPI
+     */
+    if (domain) {
+        debug((char *) "%s| %s: DEBUG: Setup Kerberos credential cache\n", LogTime(), PROGRAM);
+
+        kc = krb5_create_cache(margs, domain);
+        if (kc) {
+            error((char *) "%s| %s: ERROR: Error during setup of Kerberos credential cache\n", LogTime(), PROGRAM);
+        }
+    }
+    if (kc && (!margs->lurl || !margs->luser | !margs->lpass)) {
+        /*
+         * If Kerberos fails and no url given exit here
+         */
+        retval = 0;
+        goto cleanup;
+    }
+#ifndef HAVE_SUN_LDAP_SDK
+    /*
+     * Initialise ldap
+     */
+    ldap_debug = 127 /* LDAP_DEBUG_TRACE */ ;
+    ldap_debug = -1 /* LDAP_DEBUG_ANY */ ;
+    ldap_debug = 0;
+    (void) ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &ldap_debug);
+#endif
+    debug((char *) "%s| %s: DEBUG: Initialise ldap connection\n", LogTime(), PROGRAM);
+
+    if (domain && !kc) {
+        if (margs->ssl) {
+            debug((char *) "%s| %s: DEBUG: Enable SSL to ldap servers\n", LogTime(), PROGRAM);
+        }
+        debug((char *) "%s| %s: DEBUG: Canonicalise ldap server name for domain %s\n", LogTime(), PROGRAM, domain);
+        /*
+         * Loop over list of ldap servers of users domain
+         */
+        nhosts = get_ldap_hostname_list(margs, &hlist, 0, domain);
+        for (i = 0; i < nhosts; i++) {
+            port = 389;
+            if (hlist[i].port != -1)
+                port = hlist[i].port;
+            debug((char *) "%s| %s: DEBUG: Setting up connection to ldap server %s:%d\n", LogTime(), PROGRAM, hlist[i].host, port);
+
+            ld = tool_ldap_open(margs, hlist[i].host, port, margs->ssl);
+            if (!ld)
+                continue;
+
+            /*
+             * ldap bind with SASL/GSSAPI authentication (only possible if a domain was part of the username)
+             */
+
+#if defined(HAVE_SASL_H) || defined(HAVE_SASL_SASL_H) || defined(HAVE_SASL_DARWIN)
+            debug((char *) "%s| %s: DEBUG: Bind to ldap server with SASL/GSSAPI\n", LogTime(), PROGRAM);
+
+            rc = tool_sasl_bind(ld, bindp, margs->ssl);
+            if (rc != LDAP_SUCCESS) {
+                error((char *) "%s| %s: ERROR: Error while binding to ldap server with SASL/GSSAPI: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+                ldap_unbind(ld);
+                ld = NULL;
+                continue;
+            }
+            lcreds = (ldap_creds *) xmalloc(sizeof(struct ldap_creds));
+            lcreds->dn = bindp ? xstrdup(bindp) : NULL;
+            lcreds->pw = margs->ssl ? xstrdup(margs->ssl) : NULL;
+            ldap_set_rebind_proc(ld, ldap_sasl_rebind, (char *) lcreds);
+            if (ld != NULL) {
+                debug((char *) "%s| %s: DEBUG: %s initialised %sconnection to ldap server %s:%d\n", LogTime(), PROGRAM, ld ? "Successfully" : "Failed to", margs->ssl ? "SSL protected " : "", hlist[i].host, port);
+                break;
+            }
+#else
+            ldap_unbind(ld);
+            ld = NULL;
+            error((char *) "%s| %s: ERROR: SASL not supported on system\n", LogTime(), PROGRAM);
+            continue;
+#endif
+        }
+        nhosts = free_hostname_list(&hlist, nhosts);
+        if (ld == NULL) {
+            debug((char *) "%s| %s: DEBUG: Error during initialisation of ldap connection: %s\n", LogTime(), PROGRAM, strerror(errno));
+        }
+        bindp = convert_domain_to_bind_path(domain);
+    }
+    if ((!domain || !ld) && margs->lurl && strstr(margs->lurl, "://")) {
+        /*
+         * If username does not contain a domain and a url was given then try it
+         */
+        hostname = strstr(margs->lurl, "://") + 3;
+        ssl = strstr(margs->lurl, "ldaps://");
+        if (ssl) {
+            debug((char *) "%s| %s: DEBUG: Enable SSL to ldap servers\n", LogTime(), PROGRAM);
+        }
+        debug((char *) "%s| %s: DEBUG: Canonicalise ldap server name %s\n", LogTime(), PROGRAM, hostname);
+        /*
+         * Loop over list of ldap servers
+         */
+        host = xstrdup(hostname);
+        port = 389;
+        if ((p = strchr(host, ':'))) {
+            *p = '\0';
+            p++;
+            port = atoi(p);
+        }
+        nhosts = get_hostname_list(margs, &hlist, 0, host);
+        if (host)
+            xfree(host);
+        host = NULL;
+        for (i = 0; i < nhosts; i++) {
+
+            ld = tool_ldap_open(margs, hlist[i].host, port, ssl);
+            if (!ld)
+                continue;
+            /*
+             * ldap bind with username/password authentication
+             */
+
+            debug((char *) "%s| %s: DEBUG: Bind to ldap server with Username/Password\n", LogTime(), PROGRAM);
+            rc = ldap_simple_bind_s(ld, margs->luser, margs->lpass);
+            if (rc != LDAP_SUCCESS) {
+                error((char *) "%s| %s: ERROR: Error while binding to ldap server with Username/Password: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+                ldap_unbind(ld);
+                ld = NULL;
+                continue;
+            }
+            lcreds = (ldap_creds *) xmalloc(sizeof(struct ldap_creds));
+            lcreds->dn = xstrdup(margs->luser);
+            lcreds->pw = xstrdup(margs->lpass);
+            ldap_set_rebind_proc(ld, ldap_simple_rebind, (char *) lcreds);
+            debug((char *) "%s| %s: DEBUG: %s set up %sconnection to ldap server %s:%d\n", LogTime(), PROGRAM, ld ? "Successfully" : "Failed to", ssl ? "SSL protected " : "", hlist[i].host, port);
+            break;
+
+        }
+        nhosts = free_hostname_list(&hlist, nhosts);
+        if (bindp)
+            xfree(bindp);
+        if (margs->lbind) {
+            bindp = xstrdup(margs->lbind);
+        } else {
+            bindp = convert_domain_to_bind_path(domain);
+        }
+    }
+    if (ld == NULL) {
+        debug((char *) "%s| %s: DEBUG: Error during initialisation of ldap connection: %s\n", LogTime(), PROGRAM, strerror(errno));
+        retval = 0;
+        goto cleanup;
+    }
+    /*
+     * ldap search for user
+     */
+    /*
+     * Check if server is AD by querying for attribute samaccountname
+     */
+    margs->AD = 0;
+    rc = check_AD(margs, ld);
+    if (rc != LDAP_SUCCESS) {
+        error((char *) "%s| %s: ERROR: Error determining ldap server type: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+        ldap_unbind(ld);
+        ld = NULL;
+        retval = 0;
+        goto cleanup;
+    }
+    if (margs->AD)
+        filter = (char *) FILTER_AD;
+    else
+        filter = (char *) FILTER;
+
+    ldap_filter_esc = escape_filter(user);
+
+    search_exp = (char *) xmalloc(strlen(filter) + strlen(ldap_filter_esc) + 1);
+    snprintf(search_exp, strlen(filter) + strlen(ldap_filter_esc) + 1, filter, ldap_filter_esc);
+
+    if (ldap_filter_esc)
+        xfree(ldap_filter_esc);
+
+    debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter : %s\n", LogTime(), PROGRAM, bindp, search_exp);
+    rc = ldap_search_ext_s(ld, bindp, LDAP_SCOPE_SUBTREE,
+                           search_exp, NULL, 0,
+                           NULL, NULL, &searchtime, 0, &res);
+    if (search_exp)
+        xfree(search_exp);
+
+    if (rc != LDAP_SUCCESS) {
+        error((char *) "%s| %s: ERROR: Error searching ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+        ldap_unbind(ld);
+        ld = NULL;
+        retval = 0;
+        goto cleanup;
+    }
+    debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM, ldap_count_entries(ld, res), ldap_count_entries(ld, res) > 1 || ldap_count_entries(ld, res) == 0 ? "ies" : "y");
+
+    if (ldap_count_entries(ld, res) != 0) {
+
+        if (margs->AD)
+            max_attr = get_attributes(margs, ld, res, ATTRIBUTE_AD, &attr_value);
+        else {
+            max_attr = get_attributes(margs, ld, res, ATTRIBUTE, &attr_value);
+        }
+
+        /*
+         * Compare group names
+         */
+        retval = 0;
+        for (j = 0; j < max_attr; j++) {
+
+            /* Compare first CN= value assuming it is the same as the group name itself */
+            av = attr_value[j];
+            if (!strncasecmp("CN=", av, 3)) {
+                av += 3;
+                if ((avp = strchr(av, ','))) {
+                    *avp = '\0';
+                }
+            }
+            if (debug_enabled) {
+                int n;
+                debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" in hex UTF-8 is ", LogTime(), PROGRAM, j + 1, av);
+                for (n = 0; av[n] != '\0'; n++)
+                    fprintf(stderr, "%02x", (unsigned char) av[n]);
+                fprintf(stderr, "\n");
+            }
+            if (!strcasecmp(group, av)) {
+                retval = 1;
+                if (debug_enabled)
+                    debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
+                else
+                    break;
+            } else
+                debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" does not match group name \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
+        }
+        /*
+         * Do recursive group search for AD only since posixgroups can not contain other groups
+         */
+        if (!retval && margs->AD) {
+            if (debug_enabled && max_attr > 0) {
+                debug((char *) "%s| %s: DEBUG: Perform recursive group search\n", LogTime(), PROGRAM);
+            }
+            for (j = 0; j < max_attr; j++) {
+
+                av = attr_value[j];
+                if (search_group_tree(margs, ld, bindp, av, group, 1)) {
+                    retval = 1;
+                    if (!strncasecmp("CN=", av, 3)) {
+                        av += 3;
+                        if ((avp = strchr(av, ','))) {
+                            *avp = '\0';
+                        }
+                    }
+                    if (debug_enabled)
+                        debug((char *) "%s| %s: DEBUG: Entry %d group \"%s\" is (in)direct member of group \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
+                    else
+                        break;
+                }
+            }
+        }
+        /*
+         * Cleanup
+         */
+        if (attr_value) {
+            for (j = 0; j < max_attr; j++) {
+                xfree(attr_value[j]);
+            }
+            xfree(attr_value);
+            attr_value = NULL;
+        }
+        ldap_msgfree(res);
+    } else if (ldap_count_entries(ld, res) == 0 && margs->AD) {
+        ldap_msgfree(res);
+        ldap_unbind(ld);
+        ld = NULL;
+        retval = 0;
+        goto cleanup;
+    } else {
+        ldap_msgfree(res);
+        retval = 0;
+    }
+
+    if (!margs->AD && retval == 0) {
+        /*
+         * Check for primary Group membership
+         */
+        debug((char *) "%s| %s: DEBUG: Search for primary group membership: \"%s\"\n", LogTime(), PROGRAM, group);
+        filter = (char *) FILTER_UID;
+
+        ldap_filter_esc = escape_filter(user);
+
+        search_exp = (char *) xmalloc(strlen(filter) + strlen(ldap_filter_esc) + 1);
+        snprintf(search_exp, strlen(filter) + strlen(ldap_filter_esc) + 1, filter, ldap_filter_esc);
+
+        if (ldap_filter_esc)
+            xfree(ldap_filter_esc);
+
+        debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n", LogTime(), PROGRAM, bindp, search_exp);
+        rc = ldap_search_ext_s(ld, bindp, LDAP_SCOPE_SUBTREE,
+                               search_exp, NULL, 0,
+                               NULL, NULL, &searchtime, 0, &res);
+        if (search_exp)
+            xfree(search_exp);
+
+        debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM, ldap_count_entries(ld, res), ldap_count_entries(ld, res) > 1 || ldap_count_entries(ld, res) == 0 ? "ies" : "y");
+
+        max_attr = get_attributes(margs, ld, res, ATTRIBUTE_GID, &attr_value);
+
+        if (max_attr == 1) {
+            char **attr_value_2 = NULL;
+            int max_attr_2 = 0;
+
+            ldap_msgfree(res);
+            filter = (char *) FILTER_GID;
+
+            ldap_filter_esc = escape_filter(attr_value[0]);
+
+            search_exp = (char *) xmalloc(strlen(filter) + strlen(ldap_filter_esc) + 1);
+            snprintf(search_exp, strlen(filter) + strlen(ldap_filter_esc) + 1, filter, ldap_filter_esc);
+
+            if (ldap_filter_esc)
+                xfree(ldap_filter_esc);
+
+            debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n", LogTime(), PROGRAM, bindp, search_exp);
+            rc = ldap_search_ext_s(ld, bindp, LDAP_SCOPE_SUBTREE,
+                                   search_exp, NULL, 0,
+                                   NULL, NULL, &searchtime, 0, &res);
+            if (search_exp)
+                xfree(search_exp);
+
+            max_attr_2 = get_attributes(margs, ld, res, ATTRIBUTE, &attr_value_2);
+            /*
+             * Compare group names
+             */
+            retval = 0;
+            if (max_attr_2 == 1) {
+
+                /* Compare first CN= value assuming it is the same as the group name itself */
+                av = attr_value_2[0];
+                if (!strcasecmp(group, av)) {
+                    retval = 1;
+                    debug((char *) "%s| %s: DEBUG: \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM, av, group);
+                } else
+                    debug((char *) "%s| %s: DEBUG: \"%s\" does not match group name \"%s\"\n", LogTime(), PROGRAM, av, group);
+
+            }
+            /*
+             * Cleanup
+             */
+            if (attr_value_2) {
+                for (j = 0; j < max_attr_2; j++) {
+                    xfree(attr_value_2[j]);
+                }
+                xfree(attr_value_2);
+                attr_value_2 = NULL;
+            }
+            ldap_msgfree(res);
+
+            debug((char *) "%s| %s: DEBUG: Users primary group %s %s\n", LogTime(), PROGRAM, retval ? "matches" : "does not match", group);
+
+        } else
+            debug((char *) "%s| %s: DEBUG: Did not find ldap entry for group %s\n", LogTime(), PROGRAM, group);
+        /*
+         * Cleanup
+         */
+        if (attr_value) {
+            for (j = 0; j < max_attr; j++) {
+                xfree(attr_value[j]);
+            }
+            xfree(attr_value);
+            attr_value = NULL;
+        }
+    }
+    rc = ldap_unbind(ld);
+    ld = NULL;
+    if (rc != LDAP_SUCCESS) {
+        error((char *) "%s| %s: ERROR: Error unbind ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+    }
+    debug((char *) "%s| %s: DEBUG: Unbind ldap server\n", LogTime(), PROGRAM);
+cleanup:
+    if (domain)
+        krb5_cleanup();
+    if (lcreds) {
+        if (lcreds->dn)
+            xfree(lcreds->dn);
+        if (lcreds->pw)
+            xfree(lcreds->pw);
+        xfree(lcreds);
+    }
+    if (bindp)
+        xfree(bindp);
+    bindp = NULL;
+    return (retval);
+
+}
+#endif
diff --git a/helpers/external_acl/kerberos_ldap_group/support_log.cc b/helpers/external_acl/kerberos_ldap_group/support_log.cc
new file mode 100644 (file)
index 0000000..3d43d98
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * -----------------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * -----------------------------------------------------------------------------
+ */
+
+#include "config.h"
+
+#ifdef HAVE_LDAP
+
+#include "support.h"
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+
+const char *
+LogTime()
+{
+    struct tm *tm;
+    struct timeval now;
+    static time_t last_t = 0;
+    static char buf[128];
+
+    gettimeofday(&now, NULL);
+    if (now.tv_sec != last_t) {
+        tm = localtime(&now.tv_sec);
+        strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm);
+        last_t = now.tv_sec;
+    }
+    return buf;
+}
+/* default off */
+int log_enabled = 0;
+
+#ifndef __GNUC__
+/* under gcc a macro define in compat/debug.h is used instead */
+
+void
+log(char *format,...)
+{
+    if (!log_enabled)
+        return;
+    va_list args;
+    va_start(args, format);
+    vfprintf(stderr, format, args);
+    va_end(args);
+}
+
+void
+error(char *format,...)
+{
+    va_list args;
+    va_start(args, format);
+    vfprintf(stderr, format, args);
+    va_end(args);
+}
+
+void
+warn(char *format,...)
+{
+    va_list args;
+    va_start(args, format);
+    vfprintf(stderr, format, args);
+    va_end(args);
+}
+
+#endif /* __GNUC__ */
+#endif
diff --git a/helpers/external_acl/kerberos_ldap_group/support_member.cc b/helpers/external_acl/kerberos_ldap_group/support_member.cc
new file mode 100644 (file)
index 0000000..5d0b54f
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * -----------------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * -----------------------------------------------------------------------------
+ */
+
+#include "config.h"
+#include "util.h"
+
+#ifdef HAVE_LDAP
+
+#include "support.h"
+
+int
+check_memberof(struct main_args *margs, char *user, char *domain)
+{
+
+    /*
+     *  Check order:
+     *
+     *  1.  Check domain against list of groups per domain
+     *  1a. If domain does not exist in list try default domain
+     *  1b. If default domain does not exist use default group against ldap url with user/password
+     *  1c. If default group does not exist exit with error.
+     *  2.  Query ldap membership
+     *  2a. Use GSSAPI/SASL with HTTP/fqdn@DOMAIN credentials from keytab
+     *  2b. Use username/password with TLS
+     *
+     */
+    struct gdstruct *gr;
+    int found = 0;
+
+
+    /* Check users domain */
+
+    gr = margs->groups;
+    while (gr && domain) {
+        debug((char *) "%s| %s: DEBUG: User domain loop: group@domain %s@%s\n", LogTime(), PROGRAM, gr->group, gr->domain ? gr->domain : "NULL");
+        if (gr->domain && !strcasecmp(gr->domain, domain)) {
+            debug((char *) "%s| %s: DEBUG: Found group@domain %s@%s\n", LogTime(), PROGRAM, gr->group, gr->domain);
+            /* query ldap */
+            if (get_memberof(margs, user, domain, gr->group)) {
+                if (debug_enabled)
+                    debug((char *) "%s| %s: INFO: User %s is member of group@domain %s@%s\n", LogTime(), PROGRAM, user, gr->group, gr->domain);
+                else
+                    log((char *) "%s| %s: INFO: User %s is member of group@domain %s@%s\n", LogTime(), PROGRAM, user, gr->group, gr->domain);
+                found++;
+                break;
+            } else {
+                if (debug_enabled)
+                    debug((char *) "%s| %s: INFO: User %s is not member of group@domain %s@%s\n", LogTime(), PROGRAM, user, gr->group, gr->domain);
+                else
+                    log((char *) "%s| %s: INFO: User %s is not member of group@domain %s@%s\n", LogTime(), PROGRAM, user, gr->group, gr->domain);
+            }
+        }
+        gr = gr->next;
+    }
+
+    if (found)
+        return (1);
+
+    /* Check default domain */
+
+    gr = margs->groups;
+    while (gr && domain) {
+        debug((char *) "%s| %s: DEBUG: Default domain loop: group@domain %s@%s\n", LogTime(), PROGRAM, gr->group, gr->domain ? gr->domain : "NULL");
+        if (gr->domain && !strcasecmp(gr->domain, "")) {
+            debug((char *) "%s| %s: DEBUG: Found group@domain %s@%s\n", LogTime(), PROGRAM, gr->group, gr->domain);
+            /* query ldap */
+            if (get_memberof(margs, user, domain, gr->group)) {
+                if (debug_enabled)
+                    debug((char *) "%s| %s: INFO: User %s is member of group@domain %s@%s\n", LogTime(), PROGRAM, user, gr->group, gr->domain);
+                else
+                    log((char *) "%s| %s: INFO: User %s is member of group@domain %s@%s\n", LogTime(), PROGRAM, user, gr->group, gr->domain);
+                found++;
+                break;
+            } else {
+                if (debug_enabled)
+                    debug((char *) "%s| %s: INFO: User %s is not member of group@domain %s@%s\n", LogTime(), PROGRAM, user, gr->group, gr->domain);
+                else
+                    log((char *) "%s| %s: INFO: User %s is not member of group@domain %s@%s\n", LogTime(), PROGRAM, user, gr->group, gr->domain);
+            }
+        }
+        gr = gr->next;
+    }
+
+    if (found)
+        return (1);
+
+    /* Check default group with ldap url */
+
+    gr = margs->groups;
+    while (gr) {
+        debug((char *) "%s| %s: DEBUG: Default group loop: group@domain %s@%s\n", LogTime(), PROGRAM, gr->group, gr->domain ? gr->domain : "NULL");
+        if (!gr->domain) {
+            debug((char *) "%s| %s: DEBUG: Found group@domain %s@%s\n", LogTime(), PROGRAM, gr->group, gr->domain ? gr->domain : "NULL");
+            /* query ldap */
+            if (get_memberof(margs, user, domain, gr->group)) {
+                if (debug_enabled)
+                    debug((char *) "%s| %s: INFO: User %s is member of group@domain %s@%s\n", LogTime(), PROGRAM, user, gr->group, gr->domain ? gr->domain : "NULL");
+                else
+                    log((char *) "%s| %s: INFO: User %s is member of group@domain %s@%s\n", LogTime(), PROGRAM, user, gr->group, gr->domain ? gr->domain : "NULL");
+                found++;
+                break;
+            } else {
+                if (debug_enabled)
+                    debug((char *) "%s| %s: INFO: User %s is not member of group@domain %s@%s\n", LogTime(), PROGRAM, user, gr->group, gr->domain ? gr->domain : "NULL");
+                else
+                    log((char *) "%s| %s: INFO: User %s is not member of group@domain %s@%s\n", LogTime(), PROGRAM, user, gr->group, gr->domain ? gr->domain : "NULL");
+            }
+        }
+        gr = gr->next;
+    }
+
+    if (found)
+        return (1);
+
+    return (0);
+}
+#endif
diff --git a/helpers/external_acl/kerberos_ldap_group/support_netbios.cc b/helpers/external_acl/kerberos_ldap_group/support_netbios.cc
new file mode 100644 (file)
index 0000000..fa9d64b
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * -----------------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * -----------------------------------------------------------------------------
+ */
+
+#include "config.h"
+#include "util.h"
+
+#ifdef HAVE_LDAP
+
+#include "support.h"
+
+struct ndstruct *init_nd(void);
+
+struct ndstruct *
+init_nd(void) {
+    struct ndstruct *ndsp;
+    ndsp = (struct ndstruct *) xmalloc(sizeof(struct ndstruct));
+    ndsp->netbios = NULL;
+    ndsp->domain = NULL;
+    ndsp->next = NULL;
+    return ndsp;
+}
+
+int
+create_nd(struct main_args *margs)
+{
+    char *np, *dp;
+    char *p;
+    struct ndstruct *ndsp = NULL, *ndspn = NULL;
+    /*
+     *  netbios list format:
+     *
+     *     nlist=Pattern1[:Pattern2]
+     *
+     *     Pattern=NetbiosName@Domain    Netbios Name for a specific Kerberos domain
+     *                             ndstruct.domain=Domain, ndstruct.netbios=NetbiosName
+     *
+     *
+     */
+    p = margs->nlist;
+    np = margs->nlist;
+    debug((char *) "%s| %s: DEBUG: Netbios list %s\n", LogTime(), PROGRAM, margs->nlist ? margs->nlist : "NULL");
+    dp = NULL;
+
+    if (!p) {
+        debug((char *) "%s| %s: DEBUG: No netbios names defined.\n", LogTime(), PROGRAM);
+        return (0);
+    }
+    while (*p) {               /* loop over group list */
+        if (*p == '\n' || *p == '\r') {                /* Ignore CR and LF if exist */
+            p++;
+            continue;
+        }
+        if (*p == '@') {       /* end of group name - start of domain name */
+            if (p == np) {     /* empty group name not allowed */
+                debug((char *) "%s| %s: DEBUG: No netbios name defined for domain %s\n", LogTime(), PROGRAM, p);
+                return (1);
+            }
+            *p = '\0';
+            p++;
+            ndsp = init_nd();
+            ndsp->netbios = xstrdup(np);
+            if (ndspn)         /* Have already an existing structure */
+                ndsp->next = ndspn;
+            dp = p;            /* after @ starts new domain name */
+        } else if (*p == ':') {        /* end of group name or end of domain name */
+            if (p == np) {     /* empty group name not allowed */
+                debug((char *) "%s| %s: DEBUG: No netbios name defined for domain %s\n", LogTime(), PROGRAM, p);
+                return (1);
+            }
+            *p = '\0';
+            p++;
+            if (dp) {          /* end of domain name */
+                ndsp->domain = xstrdup(dp);
+                dp = NULL;
+            } else {           /* end of group name and no domain name */
+                ndsp = init_nd();
+                ndsp->netbios = xstrdup(np);
+                if (ndspn)     /* Have already an existing structure */
+                    ndsp->next = ndspn;
+            }
+            ndspn = ndsp;
+            np = p;            /* after : starts new group name */
+            if (!ndsp->domain || !strcmp(ndsp->domain, "")) {
+                debug((char *) "%s| %s: DEBUG: No domain defined for netbios name %s\n", LogTime(), PROGRAM, ndsp->netbios);
+                return (1);
+            }
+            debug((char *) "%s| %s: DEBUG: Netbios name %s  Domain %s\n", LogTime(), PROGRAM, ndsp->netbios, ndsp->domain);
+        } else
+            p++;
+    }
+    if (p == np) {             /* empty group name not allowed */
+        debug((char *) "%s| %s: DEBUG: No netbios name defined for domain %s\n", LogTime(), PROGRAM, p);
+        return (1);
+    }
+    if (dp) {                  /* end of domain name */
+        ndsp->domain = xstrdup(dp);
+    } else {                   /* end of group name and no domain name */
+        ndsp = init_nd();
+        ndsp->netbios = xstrdup(np);
+        if (ndspn)             /* Have already an existing structure */
+            ndsp->next = ndspn;
+    }
+    if (!ndsp->domain || !strcmp(ndsp->domain, "")) {
+        debug((char *) "%s| %s: DEBUG: No domain defined for netbios name %s\n", LogTime(), PROGRAM, ndsp->netbios);
+        return (1);
+    }
+    debug((char *) "%s| %s: DEBUG: Netbios name %s  Domain %s\n", LogTime(), PROGRAM, ndsp->netbios, ndsp->domain);
+
+    margs->ndoms = ndsp;
+    return (0);
+}
+
+char *
+get_netbios_name(struct main_args *margs, char *netbios)
+{
+    struct ndstruct *nd;
+
+    nd = margs->ndoms;
+    while (nd && netbios) {
+        debug((char *) "%s| %s: DEBUG: Netbios domain loop: netbios@domain %s@%s\n", LogTime(), PROGRAM, nd->netbios, nd->domain);
+        if (nd->netbios && !strcasecmp(nd->netbios, netbios)) {
+            debug((char *) "%s| %s: DEBUG: Found netbios@domain %s@%s\n", LogTime(), PROGRAM, nd->netbios, nd->domain);
+            return (nd->domain);
+        }
+        nd = nd->next;
+    }
+
+    return NULL;
+}
+#endif
diff --git a/helpers/external_acl/kerberos_ldap_group/support_resolv.cc b/helpers/external_acl/kerberos_ldap_group/support_resolv.cc
new file mode 100644 (file)
index 0000000..08f2ea1
--- /dev/null
@@ -0,0 +1,421 @@
+/*
+ * -----------------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * -----------------------------------------------------------------------------
+ */
+
+#include "config.h"
+#include "util.h"
+
+#ifdef HAVE_LDAP
+
+#include "support.h"
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_RESOLV_H
+#include <resolv.h>
+#endif
+#ifdef HAVE_ARPA_NAMESER_H
+#include <arpa/nameser.h>
+#endif
+
+void nsError(int nserror, char *server);
+static int compare_hosts(struct hstruct *h1, struct hstruct *h2);
+static void swap(struct hstruct *a, struct hstruct *b);
+static void sort(struct hstruct *array, int nitems, int (*cmp) (struct hstruct *, struct hstruct *), int begin, int end);
+static void msort(struct hstruct *array, size_t nitems, int (*cmp) (struct hstruct *, struct hstruct *));
+
+/*
+ * See http://www.ietf.org/rfc/rfc1035.txt
+ */
+/*
+ * See http://www.ietf.org/rfc/rfc2782.txt
+ *
+ */
+void
+nsError(int nserror, char *service)
+{
+    switch (nserror) {
+    case HOST_NOT_FOUND:
+        error((char *) "%s| %s: ERROR: res_search: Unknown service record: %s\n", LogTime(), PROGRAM, service);
+        break;
+    case NO_DATA:
+        error((char *) "%s| %s: ERROR: res_search: No SRV record for %s\n", LogTime(), PROGRAM, service);
+        break;
+    case TRY_AGAIN:
+        error((char *) "%s| %s: ERROR: res_search: No response for SRV query\n", LogTime(), PROGRAM);
+        break;
+    default:
+        error((char *) "%s| %s: ERROR: res_search: Unexpected error: %s\n", LogTime(), PROGRAM, strerror(nserror));
+    }
+}
+
+static void
+swap(struct hstruct *a, struct hstruct *b)
+{
+    struct hstruct c;
+
+    c.host = a->host;
+    c.priority = a->priority;
+    c.weight = a->weight;
+    a->priority = b->priority;
+    a->weight = b->weight;
+    b->host = c.host;
+    b->priority = c.priority;
+    b->weight = c.weight;
+}
+
+static void
+sort(struct hstruct *array, int nitems, int (*cmp) (struct hstruct *, struct hstruct *), int begin, int end)
+{
+    if (end > begin) {
+        int pivot = begin;
+        int l = begin + 1;
+        int r = end;
+        while (l < r) {
+            if (cmp(&array[l], &array[pivot]) <= 0) {
+                l += 1;
+            } else {
+                r -= 1;
+                swap(&array[l], &array[r]);
+            }
+        }
+        l -= 1;
+        swap(&array[begin], &array[l]);
+        sort(array, nitems, cmp, begin, l);
+        sort(array, nitems, cmp, r, end);
+    }
+}
+
+static void
+msort(struct hstruct *array, size_t nitems, int (*cmp) (struct hstruct *, struct hstruct *))
+{
+    sort(array, nitems, cmp, 0, nitems - 1);
+}
+
+static int
+compare_hosts(struct hstruct *host1, struct hstruct *host2)
+{
+    /*
+     *
+     * The comparison function must return an integer less than,  equal  to,
+     * or  greater  than  zero  if  the  first  argument is considered to be
+     * respectively less than, equal to, or greater than the second.
+     */
+    if ((host1->priority < host2->priority) && (host1->priority != -1))
+        return -1;
+    if ((host1->priority < host2->priority) && (host1->priority == -1))
+        return 1;
+    if ((host1->priority > host2->priority) && (host2->priority != -1))
+        return 1;
+    if ((host1->priority > host2->priority) && (host2->priority == -1))
+        return -1;
+    if (host1->priority == host2->priority) {
+        if (host1->weight > host2->weight)
+            return -1;
+        if (host1->weight < host2->weight)
+            return 1;
+    }
+    return 0;
+}
+
+int
+free_hostname_list(struct hstruct **hlist, int nhosts)
+{
+    struct hstruct *hp = NULL;
+    int i;
+
+    hp = *hlist;
+    for (i = 0; i < nhosts; i++) {
+        if (hp[i].host)
+            xfree(hp[i].host);
+        hp[i].host = NULL;
+    }
+
+
+    if (hp)
+        xfree(hp);
+    hp = NULL;
+    *hlist = hp;
+    return 0;
+}
+
+int
+get_hostname_list(struct main_args *margs, struct hstruct **hlist, int nhosts, char *name)
+{
+    /*
+     * char host[sysconf(_SC_HOST_NAME_MAX)];
+     */
+    char host[1024];
+    struct addrinfo *hres = NULL, *hres_list;
+    int rc, count;
+    struct hstruct *hp = NULL;
+
+    if (!name)
+        return (nhosts);
+
+    hp = *hlist;
+    rc = getaddrinfo((const char *) name, NULL, NULL, &hres);
+    if (rc != 0) {
+        error((char *) "%s| %s: ERROR: Error while resolving hostname with getaddrinfo: %s\n", LogTime(), PROGRAM, gai_strerror(rc));
+        return (nhosts);
+    }
+    hres_list = hres;
+    count = 0;
+    while (hres_list) {
+        count++;
+        hres_list = hres_list->ai_next;
+    }
+    hres_list = hres;
+    count = 0;
+    while (hres_list) {
+        rc = getnameinfo(hres_list->ai_addr, hres_list->ai_addrlen, host, sizeof(host), NULL, 0, 0);
+        if (rc != 0) {
+            error((char *) "%s| %s: ERROR: Error while resolving ip address with getnameinfo: %s\n", LogTime(), PROGRAM, gai_strerror(rc));
+            freeaddrinfo(hres);
+            *hlist = hp;
+            return (nhosts);
+        }
+        count++;
+        debug((char *) "%s| %s: DEBUG: Resolved address %d of %s to %s\n", LogTime(), PROGRAM, count, name, host);
+
+        hp = (struct hstruct *) xrealloc(hp, sizeof(struct hstruct) * (nhosts + 1));
+        hp[nhosts].host = xstrdup(host);
+        hp[nhosts].port = -1;
+        hp[nhosts].priority = -1;
+        hp[nhosts].weight = -1;
+        nhosts++;
+
+        hres_list = hres_list->ai_next;
+    }
+
+    freeaddrinfo(hres);
+    *hlist = hp;
+    return (nhosts);
+}
+
+int
+get_ldap_hostname_list(struct main_args *margs, struct hstruct **hlist, int nh, char *domain)
+{
+
+    /*
+     * char name[sysconf(_SC_HOST_NAME_MAX)];
+     */
+    char name[1024];
+    char host[NS_MAXDNAME];
+    char *service;
+    struct hstruct *hp = NULL;
+    int nhosts = 0;
+    int size;
+    int type, rdlength;
+    int priority, weight, port;
+    int len, olen;
+    int i, j, k;
+    u_char *buffer;
+    u_char *p;
+
+    if (margs->ssl) {
+        service = (char *) xmalloc(strlen("_ldaps._tcp.") + strlen(domain) + 1);
+        strcpy(service, "_ldaps._tcp.");
+    } else {
+        service = (char *) xmalloc(strlen("_ldap._tcp.") + strlen(domain) + 1);
+        strcpy(service, "_ldap._tcp.");
+    }
+    strcat(service, domain);
+
+#ifndef PACKETSZ_MULT
+    /*
+     * It seems Solaris doesn't give back the real length back when res_search uses a to small buffer
+     * Set a bigger one here
+     */
+#define PACKETSZ_MULT 10
+#endif
+
+    hp = *hlist;
+    buffer = (u_char *) xmalloc(PACKETSZ_MULT * NS_PACKETSZ);
+    if ((len = res_search(service, ns_c_in, ns_t_srv, (u_char *) buffer, PACKETSZ_MULT * NS_PACKETSZ)) < 0) {
+        error((char *) "%s| %s: ERROR: Error while resolving service record %s with res_search\n", LogTime(), PROGRAM, service);
+        nsError(h_errno, service);
+        if (margs->ssl) {
+            xfree(service);
+            service = (char *) xmalloc(strlen("_ldap._tcp.") + strlen(domain) + 1);
+            strcpy(service, "_ldap._tcp.");
+            strcat(service, domain);
+            if ((len = res_search(service, ns_c_in, ns_t_srv, (u_char *) buffer, PACKETSZ_MULT * NS_PACKETSZ)) < 0) {
+                error((char *) "%s| %s: ERROR: Error while resolving service record %s with res_search\n", LogTime(), PROGRAM, service);
+                nsError(h_errno, service);
+                goto cleanup;
+            }
+        } else {
+            goto cleanup;
+        }
+    }
+    if (len > PACKETSZ_MULT * NS_PACKETSZ) {
+        olen = len;
+        buffer = (u_char *) xrealloc(buffer, len);
+        if ((len = res_search(service, ns_c_in, ns_t_srv, (u_char *) buffer, len)) < 0) {
+            error((char *) "%s| %s: ERROR: Error while resolving service record %s with res_search\n", LogTime(), PROGRAM, service);
+            nsError(h_errno, service);
+            goto cleanup;
+        }
+        if (len > olen) {
+            error((char *) "%s| %s: ERROR: Reply to big: buffer: %d reply length: %d\n", LogTime(), PROGRAM, olen, len);
+            goto cleanup;
+        }
+    }
+    p = buffer;
+    p += 6 * NS_INT16SZ;       /* Header(6*16bit) = id + flags + 4*section count */
+    if (p > buffer + len) {
+        error((char *) "%s| %s: ERROR: Message to small: %d < header size\n", LogTime(), PROGRAM, len);
+        goto cleanup;
+    }
+    if ((size = dn_expand(buffer, buffer + len, p, name, sysconf(_SC_HOST_NAME_MAX))) < 0) {
+        error((char *) "%s| %s: ERROR: Error while expanding query name with dn_expand:  %s\n", LogTime(), PROGRAM, strerror(errno));
+        goto cleanup;
+    }
+    p += size;                 /* Query name */
+    p += 2 * NS_INT16SZ;       /* Query type + class (2*16bit) */
+    if (p > buffer + len) {
+        error((char *) "%s| %s: ERROR: Message to small: %d < header + query name,type,class \n", LogTime(), PROGRAM, len);
+        goto cleanup;
+    }
+    while (p < buffer + len) {
+        if ((size = dn_expand(buffer, buffer + len, p, name, sysconf(_SC_HOST_NAME_MAX))) < 0) {
+            error((char *) "%s| %s: ERROR: Error while expanding answer name with dn_expand:  %s\n", LogTime(), PROGRAM, strerror(errno));
+            goto cleanup;
+        }
+        p += size;             /* Resource Record name */
+        if (p > buffer + len) {
+            error((char *) "%s| %s: ERROR: Message to small: %d < header + query name,type,class + answer name\n", LogTime(), PROGRAM, len);
+            goto cleanup;
+        }
+        NS_GET16(type, p);     /* RR type (16bit) */
+        p += NS_INT16SZ + NS_INT32SZ;  /* RR class + ttl (16bit+32bit) */
+        if (p > buffer + len) {
+            error((char *) "%s| %s: ERROR: Message to small: %d < header + query name,type,class + answer name + RR type,class,ttl\n", LogTime(), PROGRAM, len);
+            goto cleanup;
+        }
+        NS_GET16(rdlength, p); /* RR data length (16bit) */
+
+        if (type == ns_t_srv) {        /* SRV record */
+            if (p > buffer + len) {
+                error((char *) "%s| %s: ERROR: Message to small: %d < header + query name,type,class + answer name + RR type,class,ttl + RR data length\n", LogTime(), PROGRAM, len);
+                goto cleanup;
+            }
+            NS_GET16(priority, p);     /* Priority (16bit) */
+            if (p > buffer + len) {
+                error((char *) "%s| %s: ERROR: Message to small: %d <  SRV RR + priority\n", LogTime(), PROGRAM, len);
+                goto cleanup;
+            }
+            NS_GET16(weight, p);       /* Weight (16bit) */
+            if (p > buffer + len) {
+                error((char *) "%s| %s: ERROR: Message to small: %d <  SRV RR + priority + weight\n", LogTime(), PROGRAM, len);
+                goto cleanup;
+            }
+            NS_GET16(port, p); /* Port (16bit) */
+            if (p > buffer + len) {
+                error((char *) "%s| %s: ERROR: Message to small: %d <  SRV RR + priority + weight + port\n", LogTime(), PROGRAM, len);
+                goto cleanup;
+            }
+            if ((size = dn_expand(buffer, buffer + len, p, host, NS_MAXDNAME)) < 0) {
+                error((char *) "%s| %s: ERROR: Error while expanding SRV RR name with dn_expand:  %s\n", LogTime(), PROGRAM, strerror(errno));
+                goto cleanup;
+            }
+            debug((char *) "%s| %s: DEBUG: Resolved SRV %s record to %s\n", LogTime(), PROGRAM, service, host);
+            hp = (struct hstruct *) xrealloc(hp, sizeof(struct hstruct) * (nh + 1));
+            hp[nh].host = xstrdup(host);
+            hp[nh].port = port;
+            hp[nh].priority = priority;
+            hp[nh].weight = weight;
+            nh++;
+            p += size;
+        } else {
+            p += rdlength;
+        }
+        if (p > buffer + len) {
+            error((char *) "%s| %s: ERROR: Message to small: %d <  SRV RR + priority + weight + port + name\n", LogTime(), PROGRAM, len);
+            goto cleanup;
+        }
+    }
+    if (p != buffer + len) {
+#if (SIZEOF_LONG == 8)
+        error("%s| %s: ERROR: Inconsistence message length: %ld!=0\n", LogTime(), PROGRAM, buffer + len - p);
+#else
+        error((char *) "%s| %s: ERROR: Inconsistence message length: %d!=0\n", LogTime(), PROGRAM, buffer + len - p);
+#endif
+        goto cleanup;
+    }
+    nhosts = get_hostname_list(margs, &hp, nh, domain);
+
+    /* Remove duplicates */
+    for (i = 0; i < nhosts; i++) {
+        for (j = i + 1; j < nhosts; j++) {
+            if (!strcasecmp(hp[i].host, hp[j].host)) {
+                if (hp[i].port == hp[j].port ||
+                        (hp[i].port == -1 && hp[j].port == 389) ||
+                        (hp[i].port == 389 && hp[j].port == -1)) {
+                    xfree(hp[j].host);
+                    for (k = j + 1; k < nhosts; k++) {
+                        hp[k - 1].host = hp[k].host;
+                        hp[k - 1].port = hp[k].port;
+                        hp[k - 1].priority = hp[k].priority;
+                        hp[k - 1].weight = hp[k].weight;
+                    }
+                    j--;
+                    nhosts--;
+                    hp = (struct hstruct *) xrealloc(hp, sizeof(struct hstruct) * (nhosts + 1));
+                }
+            }
+        }
+    }
+
+    /* Sort by Priority / Weight */
+    msort(hp, nhosts, compare_hosts);
+
+    if (debug_enabled) {
+        debug((char *) "%s| %s: DEBUG: Sorted ldap server names for domain %s:\n", LogTime(), PROGRAM, domain);
+        for (i = 0; i < nhosts; i++) {
+            debug((char *) "%s| %s: DEBUG: Host: %s Port: %d Priority: %d Weight: %d\n", LogTime(), PROGRAM, hp[i].host, hp[i].port, hp[i].priority, hp[i].weight);
+        }
+    }
+    if (buffer)
+        xfree(buffer);
+    if (service)
+        xfree(service);
+    *hlist = hp;
+    return (nhosts);
+
+cleanup:
+    if (buffer)
+        xfree(buffer);
+    if (service)
+        xfree(service);
+    *hlist = hp;
+    return (nhosts);
+}
+#endif
diff --git a/helpers/external_acl/kerberos_ldap_group/support_sasl.cc b/helpers/external_acl/kerberos_ldap_group/support_sasl.cc
new file mode 100644 (file)
index 0000000..6d5fc92
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * -----------------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * -----------------------------------------------------------------------------
+ */
+
+#include "config.h"
+#include "util.h"
+
+#ifdef HAVE_LDAP
+
+#include "support.h"
+
+#ifdef HAVE_SASL_H
+#include <sasl.h>
+#elif defined(HAVE_SASL_SASL_H)
+#include <sasl/sasl.h>
+#elif defined(HAVE_SASL_DARWIN)
+typedef struct sasl_interact {
+    unsigned long id;          /* same as client/user callback ID */
+    const char *challenge;     /* presented to user (e.g. OTP challenge) */
+    const char *prompt;                /* presented to user (e.g. "Username: ") */
+    const char *defresult;     /* default result string */
+    const void *result;                /* set to point to result */
+    unsigned len;              /* set to length of result */
+} sasl_interact_t;
+
+#define SASL_CB_USER         0x4001    /* client user identity to login as */
+#define SASL_CB_AUTHNAME     0x4002    /* client authentication name */
+#define SASL_CB_PASS         0x4004    /* client passphrase-based secret */
+#define SASL_CB_ECHOPROMPT   0x4005    /* challenge and client enterred result */
+#define SASL_CB_NOECHOPROMPT 0x4006    /* challenge and client enterred result */
+#define SASL_CB_GETREALM     0x4008    /* realm to attempt authentication in */
+#define SASL_CB_LIST_END   0   /* end of list */
+#endif
+
+#if defined(HAVE_SASL_H) || defined(HAVE_SASL_SASL_H) || defined(HAVE_SASL_DARWIN)
+void *lutil_sasl_defaults(
+    LDAP * ld,
+    char *mech,
+    char *realm,
+    char *authcid,
+    char *passwd,
+    char *authzid);
+
+LDAP_SASL_INTERACT_PROC lutil_sasl_interact;
+
+int lutil_sasl_interact(
+    LDAP * ld,
+    unsigned flags,
+    void *defaults,
+    void *in);
+
+void lutil_sasl_freedefs(
+    void *defaults);
+
+
+/*
+ * SASL definitions for openldap support
+ */
+
+
+typedef struct lutil_sasl_defaults_s {
+    char *mech;
+    char *realm;
+    char *authcid;
+    char *passwd;
+    char *authzid;
+    char **resps;
+    int nresps;
+} lutilSASLdefaults;
+
+void *
+lutil_sasl_defaults(
+    LDAP * ld,
+    char *mech,
+    char *realm,
+    char *authcid,
+    char *passwd,
+    char *authzid)
+{
+    lutilSASLdefaults *defaults;
+
+    defaults = (lutilSASLdefaults *) xmalloc(sizeof(lutilSASLdefaults));
+
+    if (defaults == NULL)
+        return NULL;
+
+    defaults->mech = mech ? xstrdup(mech) : NULL;
+    defaults->realm = realm ? xstrdup(realm) : NULL;
+    defaults->authcid = authcid ? xstrdup(authcid) : NULL;
+    defaults->passwd = passwd ? xstrdup(passwd) : NULL;
+    defaults->authzid = authzid ? xstrdup(authzid) : NULL;
+
+    if (defaults->mech == NULL) {
+        ldap_get_option(ld, LDAP_OPT_X_SASL_MECH, &defaults->mech);
+    }
+    if (defaults->realm == NULL) {
+        ldap_get_option(ld, LDAP_OPT_X_SASL_REALM, &defaults->realm);
+    }
+    if (defaults->authcid == NULL) {
+        ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHCID, &defaults->authcid);
+    }
+    if (defaults->authzid == NULL) {
+        ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHZID, &defaults->authzid);
+    }
+    defaults->resps = NULL;
+    defaults->nresps = 0;
+
+    return defaults;
+}
+
+static int
+interaction(
+    unsigned flags,
+    sasl_interact_t * interact,
+    lutilSASLdefaults * defaults)
+{
+    const char *dflt = interact->defresult;
+
+    int noecho = 0;
+    int challenge = 0;
+
+    flags = flags;
+    switch (interact->id) {
+    case SASL_CB_GETREALM:
+        if (defaults)
+            dflt = defaults->realm;
+        break;
+    case SASL_CB_AUTHNAME:
+        if (defaults)
+            dflt = defaults->authcid;
+        break;
+    case SASL_CB_PASS:
+        if (defaults)
+            dflt = defaults->passwd;
+        noecho = 1;
+        break;
+    case SASL_CB_USER:
+        if (defaults)
+            dflt = defaults->authzid;
+        break;
+    case SASL_CB_NOECHOPROMPT:
+        noecho = 1;
+        challenge = 1;
+        break;
+    case SASL_CB_ECHOPROMPT:
+        challenge = 1;
+        break;
+    }
+
+    if (dflt && !*dflt)
+        dflt = NULL;
+
+    /* input must be empty */
+    interact->result = (dflt && *dflt) ? dflt : "";
+    interact->len = (unsigned) strlen((const char *) interact->result);
+
+    return LDAP_SUCCESS;
+}
+
+int
+lutil_sasl_interact(
+    LDAP * ld,
+    unsigned flags,
+    void *defaults,
+    void *in)
+{
+    sasl_interact_t *interact = (sasl_interact_t *) in;
+
+    if (ld == NULL)
+        return LDAP_PARAM_ERROR;
+
+    while (interact->id != SASL_CB_LIST_END) {
+        int rc = interaction(flags, interact, (lutilSASLdefaults *) defaults);
+
+        if (rc)
+            return rc;
+        interact++;
+    }
+
+    return LDAP_SUCCESS;
+}
+
+void
+lutil_sasl_freedefs(
+    void *defaults)
+{
+    lutilSASLdefaults *defs = (lutilSASLdefaults *) defaults;
+
+    if (defs->mech)
+        xfree(defs->mech);
+    if (defs->realm)
+        xfree(defs->realm);
+    if (defs->authcid)
+        xfree(defs->authcid);
+    if (defs->passwd)
+        xfree(defs->passwd);
+    if (defs->authzid)
+        xfree(defs->authzid);
+    if (defs->resps)
+        xfree(defs->resps);
+
+    xfree(defs);
+}
+
+int
+tool_sasl_bind(LDAP * ld, char *binddn, char *ssl)
+{
+    /*
+     * unsigned sasl_flags = LDAP_SASL_AUTOMATIC;
+     * unsigned sasl_flags = LDAP_SASL_QUIET;
+     */
+    /*
+     * Avoid SASL messages
+     */
+#ifdef HAVE_SUN_LDAP_SDK
+    unsigned sasl_flags = LDAP_SASL_INTERACTIVE;
+#else
+    unsigned sasl_flags = LDAP_SASL_QUIET;
+#endif
+    char *sasl_realm = NULL;
+    char *sasl_authc_id = NULL;
+    char *sasl_authz_id = NULL;
+#ifdef HAVE_SUN_LDAP_SDK
+    char *sasl_mech = (char *) "GSSAPI";
+#else
+    char *sasl_mech = NULL;
+#endif
+    /*
+     * Force encryption
+     */
+    char *sasl_secprops;
+    /*
+     * char  *sasl_secprops = (char *)"maxssf=56";
+     * char  *sasl_secprops = NULL;
+     */
+    struct berval passwd = {0, NULL};
+    void *defaults;
+    int rc = LDAP_SUCCESS;
+
+    if (ssl)
+        sasl_secprops = (char *) "maxssf=0";
+    else
+        sasl_secprops = (char *) "maxssf=56";
+    /*      sasl_secprops = (char *)"maxssf=0"; */
+    /*      sasl_secprops = (char *)"maxssf=56"; */
+
+    if (sasl_secprops != NULL) {
+        rc = ldap_set_option(ld, LDAP_OPT_X_SASL_SECPROPS,
+                             (void *) sasl_secprops);
+        if (rc != LDAP_SUCCESS) {
+            error((char *) "%s| %s: ERROR: Could not set LDAP_OPT_X_SASL_SECPROPS: %s: %s\n", LogTime(), PROGRAM, sasl_secprops, ldap_err2string(rc));
+            return rc;
+        }
+    }
+    defaults = lutil_sasl_defaults(ld,
+                                   sasl_mech,
+                                   sasl_realm,
+                                   sasl_authc_id,
+                                   passwd.bv_val,
+                                   sasl_authz_id);
+
+    rc = ldap_sasl_interactive_bind_s(ld, binddn,
+                                      sasl_mech, NULL, NULL,
+                                      sasl_flags, lutil_sasl_interact, defaults);
+
+    lutil_sasl_freedefs(defaults);
+    if (rc != LDAP_SUCCESS) {
+        error((char *) "%s| %s: ERROR: ldap_sasl_interactive_bind_s error: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
+    }
+    return rc;
+}
+#else
+void dummy(void);
+void
+dummy(void)
+{
+    fprintf(stderr, "%s| %s: ERROR: Dummy function\n", LogTime(), PROGRAM);
+}
+
+#endif
+#endif
index 92470c06cf3b81eecc717e5252adef6e3541f79b..2df6a5a75992bdc52359a3bca44130c9e6aa0a1c 100644 (file)
@@ -1,6 +1,6 @@
 include $(top_srcdir)/src/Common.am
 
-EXTRA_DIST = README COPYING config.test
+EXTRA_DIST = README COPYING config.test negotiate_kerberos_auth.8
 SUBDIRS = 
 
 libexec_PROGRAMS = negotiate_kerberos_auth negotiate_kerberos_auth_test
@@ -17,3 +17,5 @@ negotiate_kerberos_auth_LDFLAGS =
 negotiate_kerberos_auth_LDADD = $(COMPAT_LIB) $(XTRA_LIBS) $(KRB5LIBS)
 negotiate_kerberos_auth_test_LDFLAGS = 
 negotiate_kerberos_auth_test_LDADD = $(COMPAT_LIB) $(XTRA_LIBS) $(KRB5LIBS)
+
+man_MANS = negotiate_kerberos_auth.8
index 0bd0ee0770fc234d4a6c14bdc98b8400f55d0ca0..32c2b8c8739ec1edd32d7c583bc6a74dd262d97f 100644 (file)
@@ -27,7 +27,7 @@ ska_base64_init(void)
 
     for (i = 0; i < 64; i++)
         base64_value[(int) base64_code[i]] = i;
-    base64_value[(int)'='] = 0;
+    base64_value[(int) '='] = 0;
 
     base64_initialized = 1;
 }
@@ -131,7 +131,7 @@ ska_base64_encode(char *result, const char *data, int result_size,
     }
 end:
     if (out_cnt >= result_size) {
-        result[result_size - 1] = '\0';        /* terminate */
+        result[result_size - 1] = '\0';                /* terminate */
     } else {
         result[out_cnt] = '\0';        /* terminate */
     }
index 00546481d5318eda0ef5c50f1d2329924fbc51da..d3bd9a99dcef73bd2ea23ca7d7c606f5bb1ea735 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 # Don't build without gssapi.h
-if test -f /usr/include/gssapi/gssapi.h || test -f  /usr/include/gssapi.h ; then
+if test -f /usr/include/gssapi/gssapi.h || test -f  /usr/include/gssapi.h || test -f /usr/include/kerberosV/gssapi.h ; then
        exit 0
 fi
 exit 1
diff --git a/helpers/negotiate_auth/kerberos/negotiate_kerberos_auth.8 b/helpers/negotiate_auth/kerberos/negotiate_kerberos_auth.8
new file mode 100644 (file)
index 0000000..69913b9
--- /dev/null
@@ -0,0 +1,132 @@
+.if !'po4a'hide' .TH negotiate_kerberos_auth 8
+.
+.SH NAME
+.if !'po4a'hide' .B negotiate_kerberos_auth
+.if !'po4a'hide' \-
+Squid kerberos based authentication helper
+.PP
+Version 3.0.3sq
+.
+.SH SYNOPSIS
+.if !'po4a'hide' .B negotiate_kerberos_auth
+.if !'po4a'hide' .B [\-h] [\-d] [\-i] [\-r] [\-s Service-Principal-Name] 
+.
+.SH DESCRIPTION
+.B negotiate_kerberos_auth
+is an installed binary and allows Squid to authenticate users via the Negotiate 
+protocol and Kerberos.  
+
+.SH OPTIONS
+.if !'po4a'hide' .TP 12
+.if !'po4a'hide' .B \-h
+Display the binary help and command line syntax info using stderr.
+.if !'po4a'hide' .TP 12
+.if !'po4a'hide' .B \-d
+Write debug messages to stderr.
+.if !'po4a'hide' .TP 12
+.if !'po4a'hide' .B \-i
+Write informational messages to stderr.
+.if !'po4a'hide' .TP 12
+.if !'po4a'hide' .B \-r 
+Remove realm from username before returning the username to squid.
+.if !'po4a'hide' .TP 12
+.if !'po4a'hide' .B \-s Service-Principal-name
+Provide Service Principal Name.
+.
+.SH CONFIGURATION
+.PP See FAQ wiki page for examples of how to write configuration snippets. (TBD)
+.PP 
+This helper is intended to be used as an
+.B external_acl_type
+helper in
+.B squid.conf.
+.if !'po4a'hide' .P
+.if !'po4a'hide' .ft CR
+.if !'po4a'hide' .nf
+.if !'po4a'hide' auth_param negotiate program /path/to/negotiate_kerberos_auth
+.if !'po4a'hide' .br
+.if !'po4a'hide' auth_param negotiate children 10
+.if !'po4a'hide' .br
+.if !'po4a'hide' auth_param negotiate keep_alive on
+.if !'po4a'hide' .fi
+.if !'po4a'hide' .ft
+.PP
+.B NOTE:
+The following squid startup file modification may be required:
+
+Add the following lines to the squid startup script to point squid to a keytab file which
+contains the HTTP/fqdn service principal for the default Kerberos domain. The fqdn must be
+the proxy name set in IE or firefox. You can not use an IP address.
+
+KRB5_KTNAME=/etc/squid/HTTP.keytab
+export KRB5_KTNAME
+
+If you use a different Kerberos domain than the machine itself is in you can point squid to
+the seperate Kerberos config file by setting the following environmnet variable in the startup
+script.
+
+KRB5_CONFIG=/etc/krb5-squid.conf
+export KRB5_CONFIG
+
+Kerberos can keep a replay cache to detect the reuse of Kerberos tickets (usually only possible 
+in a 5 minute window) . If squid is under high load with Negotiate(Kerberos) proxy authentication 
+requests the replay cache checks can create high CPU load. If the environment does not require 
+high security the replay cache check can be disabled for MIT based Kerberos implementations by 
+adding the following to the startup script 
+
+KRB5RCACHETYPE=none
+export KRB5RCACHETYPE
+
+If negotiate_kerberos_auth doesn't determine for some reason the right service principal you can provide
+it with -s HTTP/fqdn.
+
+If you serve multiple Kerberos realms add a HTTP/fqdn@REALM service principal per realm to the
+HTTP.keytab file and use the -s GSS_C_NO_NAME option with negotiate_kerberos_auth.
+
+.
+.SH AUTHOR
+This program was written by
+.if !'po4a'hide' .I Markus Moeller <markus_moeller@compuserve.com>
+.PP
+This manual was written by
+.if !'po4a'hide' .I Markus Moeller <markus_moeller@compuserve.com>
+.
+.SH COPYRIGHT
+This program and documentation is copyright to the authors named above.
+.PP
+Distributed under the GNU General Public License (GNU GPL) version 2 or later (GPLv2+).
+.
+.SH QUESTIONS
+Questions on the usage of this program can be sent to the
+.I Squid Users mailing list
+.if !'po4a'hide' <squid-users@squid-cache.org>
+.
+.SH REPORTING BUGS
+Bug reports need to be made in English.
+See http://wiki.squid-cache.org/SquidFaq/BugReporting for details of what you need to include with your bug report.
+.PP
+Report bugs or bug fixes using http://bugs.squid-cache.org/
+.PP
+Report serious security bugs to
+.I Squid Bugs <squid-bugs@squid-cache.org>
+.PP
+Report ideas for new improvements to the
+.I Squid Developers mailing list
+.if !'po4a'hide' <squid-dev@squid-cache.org>
+.
+.SH SEE ALSO
+.if !'po4a'hide' .BR squid "(8) "
+.if !'po4a'hide' .BR ext_kerberos_ldap_group_acl "(8) "
+.br
+.BR RFC4559 " - SPNEGO-based Kerberos and NTLM HTTP Authentication in Microsoft Windows,"
+.br
+.BR RFC2478 " - The Simple and Protected GSS-API Negotiation Mechanism,"
+.br
+.BR RFC1964 " - The Kerberos Version 5 GSS-API Mechanism,"
+.br
+The Squid FAQ wiki
+.if !'po4a'hide' http://wiki.squid-cache.org/SquidFaq
+.br
+The Squid Configuration Manual
+.if !'po4a'hide' http://www.squid-cache.org/Doc/config/
+.if !'po4a'hide' http://wiki.squid-cache.org/ConfigExamples/Authenticate/Kerberos
index 69f54cdeee963ffe6b30aa4e62c9fe349d609497..eb36689ec9288ec1fe1fea1fe674bbb69f59378a 100644 (file)
@@ -75,7 +75,7 @@
 #define MAX_AUTHTOKEN_LEN   65535
 #endif
 #ifndef SQUID_KERB_AUTH_VERSION
-#define SQUID_KERB_AUTH_VERSION "3.0.2sq"
+#define SQUID_KERB_AUTH_VERSION "3.0.3sq"
 #endif
 
 int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status,
@@ -83,7 +83,7 @@ int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status,
 char *gethost_name(void);
 static const char *LogTime(void);
 
-static const unsigned char ntlmProtocol[] = { 'N', 'T', 'L', 'M', 'S', 'S', 'P', 0 };
+static const unsigned char ntlmProtocol[] = {'N', 'T', 'L', 'M', 'S', 'S', 'P', 0};
 
 static const char *
 LogTime()
@@ -106,8 +106,8 @@ char *
 gethost_name(void)
 {
     /*
-        char hostname[sysconf(_SC_HOST_NAME_MAX)];
-    */
+     * char hostname[sysconf(_SC_HOST_NAME_MAX)];
+     */
     char hostname[1024];
     struct addrinfo *hres = NULL, *hres_list;
     int rc, count;
@@ -140,7 +140,6 @@ gethost_name(void)
         freeaddrinfo(hres);
         return NULL;
     }
-
     freeaddrinfo(hres);
     hostname[sysconf(_SC_HOST_NAME_MAX) - 1] = '\0';
     return (xstrdup(hostname));
@@ -165,7 +164,7 @@ check_gss_err(OM_uint32 major_status, OM_uint32 minor_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) {
-                    snprintf(buf + len, (sizeof(buf)-len), "%s", (char *) status_string.value);
+                    snprintf(buf + len, (sizeof(buf) - len), "%s", (char *) status_string.value);
                     len += status_string.length;
                 }
                 gss_release_buffer(&min_stat, &status_string);
@@ -174,7 +173,7 @@ check_gss_err(OM_uint32 major_status, OM_uint32 minor_status,
             gss_release_buffer(&min_stat, &status_string);
         }
         if (sizeof(buf) > len + 2) {
-            snprintf(buf + len, (sizeof(buf)-len), "%s", ". ");
+            snprintf(buf + len, (sizeof(buf) - len), "%s", ". ");
             len += 2;
         }
         msg_ctx = 0;
@@ -184,7 +183,7 @@ check_gss_err(OM_uint32 major_status, OM_uint32 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) {
-                    snprintf(buf + len,(sizeof(buf)-len), "%s", (char *) status_string.value);
+                    snprintf(buf + len, (sizeof(buf) - len), "%s", (char *) status_string.value);
                     len += status_string.length;
                 }
                 gss_release_buffer(&min_stat, &status_string);
@@ -192,7 +191,7 @@ check_gss_err(OM_uint32 major_status, OM_uint32 minor_status,
             }
             gss_release_buffer(&min_stat, &status_string);
         }
-        debug("%s| %s: ERROR: %s failed: %s\n", LogTime(), PROGRAM, function, buf);
+        debug((char *) "%s| %s: ERROR: %s failed: %s\n", LogTime(), PROGRAM, function, buf);
         fprintf(stdout, "BH %s failed: %s\n", function, buf);
         if (log)
             fprintf(stderr, "%s| %s: INFO: User not authenticated\n", LogTime(),
@@ -264,7 +263,7 @@ main(int argc, char *const argv[])
         }
     }
 
-    debug("%s| %s: INFO: Starting version %s\n", LogTime(), PROGRAM, SQUID_KERB_AUTH_VERSION);
+    debug((char *) "%s| %s: INFO: Starting version %s\n", LogTime(), PROGRAM, SQUID_KERB_AUTH_VERSION);
     if (service_principal && strcasecmp(service_principal, "GSS_C_NO_NAME")) {
         service.value = service_principal;
         service.length = strlen((char *) service.value);
@@ -278,7 +277,7 @@ main(int argc, char *const argv[])
             exit(-1);
         }
         service.value = xmalloc(strlen(service_name) + strlen(host_name) + 2);
-        snprintf((char*)service.value, strlen(service_name) + strlen(host_name) + 2,
+        snprintf((char *) service.value, strlen(service_name) + strlen(host_name) + 2,
                  "%s@%s", service_name, host_name);
         service.length = strlen((char *) service.value);
     }
@@ -286,7 +285,7 @@ main(int argc, char *const argv[])
     while (1) {
         if (fgets(buf, sizeof(buf) - 1, stdin) == NULL) {
             if (ferror(stdin)) {
-                debug("%s| %s: FATAL: fgets() failed! dying..... errno=%d (%s)\n",
+                debug((char *) "%s| %s: FATAL: fgets() failed! dying..... errno=%d (%s)\n",
                       LogTime(), PROGRAM, ferror(stdin),
                       strerror(ferror(stdin)));
 
@@ -296,8 +295,7 @@ main(int argc, char *const argv[])
             fprintf(stdout, "BH input error\n");
             exit(0);
         }
-
-        c = (char*)memchr(buf, '\n', sizeof(buf) - 1);
+        c = (char *) memchr(buf, '\n', sizeof(buf) - 1);
         if (c) {
             *c = '\0';
             length = c - buf;
@@ -305,26 +303,23 @@ main(int argc, char *const argv[])
             err = 1;
         }
         if (err) {
-            debug("%s| %s: ERROR: Oversized message\n", LogTime(), PROGRAM);
+            debug((char *) "%s| %s: ERROR: Oversized message\n", LogTime(), PROGRAM);
             fprintf(stdout, "BH Oversized message\n");
             err = 0;
             continue;
         }
-
-        debug("%s| %s: DEBUG: Got '%s' from squid (length: %d).\n", LogTime(), PROGRAM, buf, length);
+        debug((char *) "%s| %s: DEBUG: Got '%s' from squid (length: %d).\n", LogTime(), PROGRAM, buf, length);
 
         if (buf[0] == '\0') {
-            debug("%s| %s: ERROR: Invalid request\n", LogTime(), PROGRAM);
+            debug((char *) "%s| %s: ERROR: Invalid request\n", LogTime(), PROGRAM);
             fprintf(stdout, "BH Invalid request\n");
             continue;
         }
-
         if (strlen(buf) < 2) {
-            debug("%s| %s: ERROR: Invalid request [%s]\n", LogTime(), PROGRAM, buf);
+            debug((char *) "%s| %s: ERROR: Invalid request [%s]\n", LogTime(), PROGRAM, buf);
             fprintf(stdout, "BH Invalid request\n");
             continue;
         }
-
         if (!strncmp(buf, "QQ", 2)) {
             gss_release_buffer(&minor_status, &input_token);
             gss_release_buffer(&minor_status, &output_token);
@@ -359,9 +354,8 @@ main(int argc, char *const argv[])
             fprintf(stdout, "BH quit command\n");
             exit(0);
         }
-
         if (strncmp(buf, "YR", 2) && strncmp(buf, "KK", 2)) {
-            debug("%s| %s: ERROR: Invalid request [%s]\n", LogTime(), PROGRAM, buf);
+            debug((char *) "%s| %s: ERROR: Invalid request [%s]\n", LogTime(), PROGRAM, buf);
             fprintf(stdout, "BH Invalid request\n");
             continue;
         }
@@ -370,24 +364,22 @@ main(int argc, char *const argv[])
                 gss_delete_sec_context(&minor_status, &gss_context, NULL);
             gss_context = GSS_C_NO_CONTEXT;
         }
-
         if (strlen(buf) <= 3) {
-            debug("%s| %s: ERROR: Invalid negotiate request [%s]\n", LogTime(), PROGRAM, buf);
+            debug((char *) "%s| %s: ERROR: Invalid negotiate request [%s]\n", LogTime(), PROGRAM, buf);
             fprintf(stdout, "BH Invalid negotiate request\n");
             continue;
         }
-
         input_token.length = ska_base64_decode_len(buf + 3);
-        debug("%s| %s: DEBUG: Decode '%s' (decoded length: %d).\n",
+        debug((char *) "%s| %s: DEBUG: Decode '%s' (decoded length: %d).\n",
               LogTime(), PROGRAM, buf + 3, (int) input_token.length);
         input_token.value = xmalloc(input_token.length);
 
-        ska_base64_decode((char*)input_token.value, buf + 3, input_token.length);
+        ska_base64_decode((char *) input_token.value, buf + 3, input_token.length);
 
 
         if ((input_token.length >= sizeof ntlmProtocol + 1) &&
                 (!memcmp(input_token.value, ntlmProtocol, sizeof ntlmProtocol))) {
-            debug("%s| %s: WARNING: received type %d NTLM token\n",
+            debug((char *) "%s| %s: WARNING: received type %d NTLM token\n",
                   LogTime(), PROGRAM,
                   (int) *((unsigned char *) input_token.value +
                           sizeof ntlmProtocol));
@@ -396,7 +388,6 @@ main(int argc, char *const argv[])
                             sizeof ntlmProtocol));
             goto cleanup;
         }
-
         if (service_principal) {
             if (strcasecmp(service_principal, "GSS_C_NO_NAME")) {
                 major_status = gss_import_name(&minor_status, &service,
@@ -429,22 +420,21 @@ main(int argc, char *const argv[])
 
 
         if (output_token.length) {
-            spnegoToken = (const unsigned char*)output_token.value;
+            spnegoToken = (const unsigned char *) output_token.value;
             spnegoTokenLength = output_token.length;
-            token = (char*)xmalloc(ska_base64_encode_len(spnegoTokenLength));
+            token = (char *) xmalloc(ska_base64_encode_len(spnegoTokenLength));
             if (token == NULL) {
-                debug("%s| %s: ERROR: Not enough memory\n", LogTime(), PROGRAM);
+                debug((char *) "%s| %s: ERROR: Not enough memory\n", LogTime(), PROGRAM);
                 fprintf(stdout, "BH Not enough memory\n");
                 goto cleanup;
             }
-
             ska_base64_encode(token, (const char *) spnegoToken,
                               ska_base64_encode_len(spnegoTokenLength), spnegoTokenLength);
 
             if (check_gss_err(major_status, minor_status, "gss_accept_sec_context()", log))
                 goto cleanup;
             if (major_status & GSS_S_CONTINUE_NEEDED) {
-                debug("%s| %s: INFO: continuation needed\n", LogTime(), PROGRAM);
+                debug((char *) "%s| %s: INFO: continuation needed\n", LogTime(), PROGRAM);
                 fprintf(stdout, "TT %s\n", token);
                 goto cleanup;
             }
@@ -455,9 +445,9 @@ main(int argc, char *const argv[])
 
             if (check_gss_err(major_status, minor_status, "gss_display_name()", log))
                 goto cleanup;
-            user = (char*)xmalloc(output_token.length + 1);
+            user = (char *) xmalloc(output_token.length + 1);
             if (user == NULL) {
-                debug("%s| %s: ERROR: Not enough memory\n", LogTime(), PROGRAM);
+                debug((char *) "%s| %s: ERROR: Not enough memory\n", LogTime(), PROGRAM);
                 fprintf(stdout, "BH Not enough memory\n");
                 goto cleanup;
             }
@@ -467,7 +457,7 @@ main(int argc, char *const argv[])
                 *p = '\0';
             }
             fprintf(stdout, "AF %s %s\n", token, user);
-            debug("%s| %s: DEBUG: AF %s %s\n", LogTime(), PROGRAM, token, user);
+            debug((char *) "%s| %s: DEBUG: AF %s %s\n", LogTime(), PROGRAM, token, user);
             if (log)
                 fprintf(stderr, "%s| %s: INFO: User %s authenticated\n", LogTime(),
                         PROGRAM, user);
@@ -476,7 +466,7 @@ main(int argc, char *const argv[])
             if (check_gss_err(major_status, minor_status, "gss_accept_sec_context()", log))
                 goto cleanup;
             if (major_status & GSS_S_CONTINUE_NEEDED) {
-                debug("%s| %s: INFO: continuation needed\n", LogTime(), PROGRAM);
+                debug((char *) "%s| %s: INFO: continuation needed\n", LogTime(), PROGRAM);
                 fprintf(stdout, "NA %s\n", token);
                 goto cleanup;
             }
@@ -490,9 +480,9 @@ main(int argc, char *const argv[])
             /*
              *  Return dummy token AA. May need an extra return tag then AF
              */
-            user = (char*)xmalloc(output_token.length + 1);
+            user = (char *) xmalloc(output_token.length + 1);
             if (user == NULL) {
-                debug("%s| %s: ERROR: Not enough memory\n", LogTime(), PROGRAM);
+                debug((char *) "%s| %s: ERROR: Not enough memory\n", LogTime(), PROGRAM);
                 fprintf(stdout, "BH Not enough memory\n");
                 goto cleanup;
             }
@@ -502,7 +492,7 @@ main(int argc, char *const argv[])
                 *p = '\0';
             }
             fprintf(stdout, "AF %s %s\n", "AA==", user);
-            debug("%s| %s: DEBUG: AF %s %s\n", LogTime(), PROGRAM, "AA==", user);
+            debug((char *) "%s| %s: DEBUG: AF %s %s\n", LogTime(), PROGRAM, "AA==", user);
             if (log)
                 fprintf(stderr, "%s| %s: INFO: User %s authenticated\n", LogTime(),
                         PROGRAM, user);
index 56c75252cb6c2a97709df22cc7a3f64333207aac..f1d139161755e12eca64ef324ebb6e42b3101c59 100644 (file)
@@ -85,7 +85,7 @@ LogTime()
 
     gettimeofday(&now, NULL);
     if (now.tv_sec != last_t) {
-        tm = localtime((const time_t*)&now.tv_sec);
+        tm = localtime((const time_t *) &now.tv_sec);
         strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm);
         last_t = now.tv_sec;
     }
@@ -93,7 +93,7 @@ LogTime()
 }
 
 #ifndef gss_mech_spnego
-static gss_OID_desc _gss_mech_spnego = { 6, (void *) "\x2b\x06\x01\x05\x05\x02" };
+static gss_OID_desc _gss_mech_spnego = {6, (void *) "\x2b\x06\x01\x05\x05\x02"};
 gss_OID gss_mech_spnego = &_gss_mech_spnego;
 #endif
 
@@ -116,7 +116,7 @@ check_gss_err(OM_uint32 major_status, OM_uint32 minor_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) {
-                    snprintf(buf + len, (sizeof(buf)-len), "%s", (char *)status_string.value);
+                    snprintf(buf + len, (sizeof(buf) - len), "%s", (char *) status_string.value);
                     len += status_string.length;
                 }
                 gss_release_buffer(&min_stat, &status_string);
@@ -125,7 +125,7 @@ check_gss_err(OM_uint32 major_status, OM_uint32 minor_status,
             gss_release_buffer(&min_stat, &status_string);
         }
         if (sizeof(buf) > len + 2) {
-            snprintf(buf + len, (sizeof(buf)-len), "%s", ". ");
+            snprintf(buf + len, (sizeof(buf) - len), "%s", ". ");
             len += 2;
         }
         msg_ctx = 0;
@@ -135,7 +135,7 @@ check_gss_err(OM_uint32 major_status, OM_uint32 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) {
-                    snprintf(buf + len, (sizeof(buf)-len), "%s", (char *) status_string.value);
+                    snprintf(buf + len, (sizeof(buf) - len), "%s", (char *) status_string.value);
                     len += status_string.length;
                 }
                 gss_release_buffer(&min_stat, &status_string);
@@ -169,9 +169,8 @@ squid_kerb_proxy_auth(char *proxy)
                 PROGRAM);
         return NULL;
     }
-
     service.value = xmalloc(strlen("HTTP") + strlen(proxy) + 2);
-    snprintf((char*)service.value, strlen("HTTP") + strlen(proxy) + 2, "%s@%s", "HTTP", proxy);
+    snprintf((char *) service.value, strlen("HTTP") + strlen(proxy) + 2, "%s@%s", "HTTP", proxy);
     service.length = strlen((char *) service.value);
 
     major_status = gss_import_name(&minor_status, &service,
@@ -192,12 +191,10 @@ squid_kerb_proxy_auth(char *proxy)
         goto cleanup;
 
     if (output_token.length) {
-        token = (char*)xmalloc(ska_base64_encode_len(output_token.length));
+        token = (char *) xmalloc(ska_base64_encode_len(output_token.length));
         ska_base64_encode(token, (const char *) output_token.value,
                           ska_base64_encode_len(output_token.length), output_token.length);
     }
-
-
 cleanup:
     gss_delete_sec_context(&minor_status, &gss_context, NULL);
     gss_release_buffer(&minor_status, &service);
@@ -235,6 +232,7 @@ main(int argc, char *argv[])
 
     exit(0);
 }
+
 #else
 #include <stdlib.h>
 int
@@ -242,4 +240,5 @@ main(int argc, char *argv[])
 {
     exit(-1);
 }
+
 #endif /* HAVE_GSSAPI */
index 3943228bb482c7b0484ff74bf504eeb7bd0ddd31..73b8a35cc7876c860411350bdbb5577ed3fd73be 100644 (file)
 #define SEND(X) debug("sending '%s' to squid\n",X); printf(X "\n");
 #ifdef __GNUC__
 #define SEND2(X,Y...) debug("sending '" X "' to squid\n",Y); printf(X "\n",Y);
-#define SEND3(X,Y...) debug("sending '" X "' to squid\n",Y); printf(X "\n",Y);
+#define SEND4(X,Y...) debug("sending '" X "' to squid\n",Y); printf(X "\n",Y);
 #else
 /* no gcc, no debugging. varargs macros are a gcc extension */
 #define SEND2(X,Y) debug("sending '" X "' to squid\n",Y); printf(X "\n",Y);
-#define SEND3(X,Y,Z) debug("sending '" X "' to squid\n",Y,Z); printf(X "\n",Y,Z);
+#define SEND4(X,Y,Z,W) debug("sending '" X "' to squid\n",Y,Z); printf(X "\n",Y,Z);
 #endif
 
 const char *authenticate_ntlm_domain = "WORKGROUP";
@@ -213,12 +213,12 @@ main(int argc, char *argv[])
                     if (strip_domain_enabled) {
                         SEND2("AF %s", user);
                     } else {
-                        SEND3("AF %s%s%s", domain, (*domain?"\\":""), user);
+                        SEND4("AF %s%s%s", domain, (*domain?"\\":""), user);
                     }
                 } else {
                     lc(user);
                     lc(domain);
-                    SEND3("NA invalid credentials, user=%s%s%s", domain, (*domain?"\\":""), user);
+                    SEND4("NA invalid credentials, user=%s%s%s", domain, (*domain?"\\":""), user);
                 }
             } else {
                 SEND("BH wrong packet type! user=");
index 2bd9a0d316b030830692a0f73aa9f807bef637aa..bef750d266b16d1ef7b1a36cc20d292b9e20f14d 100644 (file)
@@ -15,6 +15,7 @@
  */
 #define SQUID_NO_ALLOC_PROTECT 1
 #include "config.h"
+#include "compat/debug.h"
 #include "libntlmauth/ntlmauth.h"
 #include "libntlmauth/smb.h"
 #include "libntlmauth/rfcnb.h"
@@ -401,7 +402,7 @@ usage()
             my_program_name, my_program_name);
 }
 
-int debug_enabled=0;
+/* int debug_enabled=0; defined in libcompat */
 
 void
 process_options(int argc, char *argv[])
diff --git a/include/psignal.h b/include/psignal.h
new file mode 100644 (file)
index 0000000..087df25
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __SQUID_PSIGNAL_H
+#define __SQUID_PSIGNAL_H
+
+#include "config.h"
+
+#if HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+extern void psignal(int sig, const char* msg);
+
+#endif /* __SQUID_PSIGNAL_H */
index f474316568fd6c068c1975793f509cba37dac2c2..8427107fb4d161876465f32d71b333c5ba940132 100644 (file)
@@ -46,6 +46,7 @@ EXTRA_libmiscutil_a_SOURCES = \
        md5.c \
        Profiler.c \
        win32lib.c
+
 libmiscutil_a_SOURCES = \
        MemPool.cc \
        MemPoolChunked.cc \
@@ -107,7 +108,7 @@ tests_testAll_LDFLAGS = $(LIBADD_DL)
 ## Special Universal .h dependency test script
 ## aborts if error encountered
 testHeaders: $(top_srcdir)/include/*.h
-       $(SHELL) $(top_srcdir)/test-suite/testheaders.sh "$(CXXCOMPILE)" "$(top_srcdir)/include" || exit 1
+       $(SHELL) $(top_srcdir)/test-suite/testheaders.sh "$(CXXCOMPILE)" $^ || exit 1
 
 TESTS += testHeaders
 CLEANFILES += testHeaders
index 1df38968c6d82ca60ae69528364a39fc042d4ce6..01e1b191425c690e8c4c89db7d91a41a4e323a04 100644 (file)
@@ -24,7 +24,7 @@
 #include "TrieNode.h"
 #include "TrieCharTransform.h"
 
-#ifndef _USE_INLINE_
+#if !_USE_INLINE_
 #include "Trie.cci"
 #endif
 
index 3d6bea5c77b9e2d2a8cfb276c5cc377a14dd2b4b..81dc5e8328876d3d61a64d188abf70ed41ef1cf7 100644 (file)
@@ -63,6 +63,6 @@ TrieNode::add
     }
 }
 
-#ifndef _USE_INLINE_
+#if !_USE_INLINE_
 #include "TrieNode.cci"
 #endif
diff --git a/lib/psignal.c b/lib/psignal.c
new file mode 100644 (file)
index 0000000..2a8b859
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Author:   Jens-S. V?ckler <voeckler@rvs.uni-hannover.de>
+ * Ripped from Purge tool implementation.
+ */
+#include "config.h"
+#include "psignal.h"
+
+#if _SQUID_AIX_
+extern const char* const sys_siglist[];
+#define _sys_nsig 64
+#define _sys_siglist sys_siglist
+#endif
+
+/// purpose: print message, colon, space, signal name and LF.
+/// paramtr: sig (IN): signal number
+///          msg (IN): message to prepend
+void
+psignal( int sig, const char* msg )
+{
+    if ( msg && *msg ) fprintf( stderr, "%s: ", msg );
+    if ( sig > 0 && sig < _sys_nsig )
+        fprintf( stderr, "%s\n", _sys_siglist[sig] );
+    else
+        fputs( "(unknown)\n", stderr );
+}
index 9f0df23bba470515cf85c18515749768d9adcb61..cc84fa49818feb0af4ff5c5a3ed107f716543b85 100644 (file)
@@ -44,6 +44,9 @@
 #if HAVE_STDIO_H
 #include <stdio.h>
 #endif
+#if HAVE_STRING_H
+#include <string.h>
+#endif
 #if HAVE_UNISTD_H
 #include <unistd.h>
 #endif
index 7717c2bf11fdb1f304bf734abcd0cb73fee63e9b..4b8b6bd261675bd0b8c589284e98d9f7ac1cff1d 100644 (file)
@@ -1,5 +1,6 @@
 
 #include "squid.h"
+#include "base/AsyncJobCalls.h"
 #include "base/TextException.h"
 #include "BodyPipe.h"
 
@@ -40,8 +41,9 @@ class BodyProducerDialer: public UnaryMemFunT<BodyProducer, BodyPipe::Pointer>
 public:
     typedef UnaryMemFunT<BodyProducer, BodyPipe::Pointer> Parent;
 
-    BodyProducerDialer(BodyProducer *aProducer, Parent::Method aHandler,
-                       BodyPipe::Pointer bp): Parent(aProducer, aHandler, bp) {}
+    BodyProducerDialer(const BodyProducer::Pointer &aProducer,
+                       Parent::Method aHandler, BodyPipe::Pointer bp):
+            Parent(aProducer, aHandler, bp) {}
 
     virtual bool canDial(AsyncCall &call);
 };
@@ -54,8 +56,9 @@ class BodyConsumerDialer: public UnaryMemFunT<BodyConsumer, BodyPipe::Pointer>
 public:
     typedef UnaryMemFunT<BodyConsumer, BodyPipe::Pointer> Parent;
 
-    BodyConsumerDialer(BodyConsumer *aConsumer, Parent::Method aHandler,
-                       BodyPipe::Pointer bp): Parent(aConsumer, aHandler, bp) {}
+    BodyConsumerDialer(const BodyConsumer::Pointer &aConsumer,
+                       Parent::Method aHandler, BodyPipe::Pointer bp):
+            Parent(aConsumer, aHandler, bp) {}
 
     virtual bool canDial(AsyncCall &call);
 };
@@ -66,7 +69,7 @@ BodyProducerDialer::canDial(AsyncCall &call)
     if (!Parent::canDial(call))
         return false;
 
-    BodyProducer *producer = object;
+    const BodyProducer::Pointer &producer = job;
     BodyPipe::Pointer pipe = arg1;
     if (!pipe->stillProducing(producer)) {
         debugs(call.debugSection, call.debugLevel, HERE << producer <<
@@ -83,7 +86,7 @@ BodyConsumerDialer::canDial(AsyncCall &call)
     if (!Parent::canDial(call))
         return false;
 
-    BodyConsumer *consumer = object;
+    const BodyConsumer::Pointer &consumer = job;
     BodyPipe::Pointer pipe = arg1;
     if (!pipe->stillConsuming(consumer)) {
         debugs(call.debugSection, call.debugLevel, HERE << consumer <<
@@ -192,9 +195,9 @@ void BodyPipe::expectProductionEndAfter(uint64_t size)
 void
 BodyPipe::clearProducer(bool atEof)
 {
-    if (theProducer) {
+    if (theProducer.set()) {
         debugs(91,7, HERE << "clearing BodyPipe producer" << status());
-        theProducer = NULL;
+        theProducer.clear();
         if (atEof) {
             if (!bodySizeKnown())
                 theBodySize = thePutSize;
@@ -224,10 +227,10 @@ BodyPipe::putMoreData(const char *aBuffer, size_t size)
 }
 
 bool
-BodyPipe::setConsumerIfNotLate(Consumer *aConsumer)
+BodyPipe::setConsumerIfNotLate(const Consumer::Pointer &aConsumer)
 {
     assert(!theConsumer);
-    assert(aConsumer);
+    assert(aConsumer.set()); // but might be invalid
 
     // TODO: convert this into an exception and remove IfNotLate suffix
     // If there is something consumed already, we are in an auto-consuming mode
@@ -256,9 +259,9 @@ BodyPipe::setConsumerIfNotLate(Consumer *aConsumer)
 void
 BodyPipe::clearConsumer()
 {
-    if (theConsumer) {
+    if (theConsumer.set()) {
         debugs(91,7, HERE << "clearing consumer" << status());
-        theConsumer = NULL;
+        theConsumer.clear();
         if (consumedSize() && !exhausted()) {
             AsyncCall::Pointer call= asyncCall(91, 7,
                                                "BodyProducer::noteBodyConsumerAborted",
@@ -386,7 +389,7 @@ BodyPipe::postAppend(size_t size)
 void
 BodyPipe::scheduleBodyDataNotification()
 {
-    if (theConsumer) {
+    if (theConsumer.valid()) { // TODO: allow asyncCall() to check this instead
         AsyncCall::Pointer call = asyncCall(91, 7,
                                             "BodyConsumer::noteMoreBodyDataAvailable",
                                             BodyConsumerDialer(theConsumer,
@@ -398,7 +401,7 @@ BodyPipe::scheduleBodyDataNotification()
 void
 BodyPipe::scheduleBodyEndNotification()
 {
-    if (theConsumer) {
+    if (theConsumer.valid()) { // TODO: allow asyncCall() to check this instead
         if (bodySizeKnown() && bodySize() == thePutSize) {
             AsyncCall::Pointer call = asyncCall(91, 7,
                                                 "BodyConsumer::noteBodyProductionEnded",
@@ -432,10 +435,10 @@ const char *BodyPipe::status() const
     outputBuffer.Printf(" %d+%d", (int)theBuf.contentSize(), (int)theBuf.spaceSize());
 
     outputBuffer.Printf(" pipe%p", this);
-    if (theProducer)
-        outputBuffer.Printf(" prod%p", theProducer);
-    if (theConsumer)
-        outputBuffer.Printf(" cons%p", theConsumer);
+    if (theProducer.set())
+        outputBuffer.Printf(" prod%p", theProducer.get());
+    if (theConsumer.set())
+        outputBuffer.Printf(" cons%p", theConsumer.get());
 
     if (mustAutoConsume)
         outputBuffer.append(" A", 2);
index e3793ee41273899e801288e430d4384d2bf53eab..c9e7c93c978a74282ea783c9498d6787c1be5899 100644 (file)
@@ -2,8 +2,8 @@
 #define SQUID_BODY_PIPE_H
 
 #include "MemBuf.h"
-#include "base/AsyncCall.h"
 #include "base/AsyncJob.h"
+#include "base/CbcPointer.h"
 
 class BodyPipe;
 
@@ -14,6 +14,8 @@ class BodyPipe;
 class BodyProducer: virtual public AsyncJob
 {
 public:
+    typedef CbcPointer<BodyProducer> Pointer;
+
     BodyProducer():AsyncJob("BodyProducer") {}
     virtual ~BodyProducer() {}
 
@@ -32,6 +34,8 @@ protected:
 class BodyConsumer: virtual public AsyncJob
 {
 public:
+    typedef CbcPointer<BodyConsumer> Pointer;
+
     BodyConsumer():AsyncJob("BodyConsumer") {}
     virtual ~BodyConsumer() {}
 
@@ -103,17 +107,17 @@ public:
     bool mayNeedMoreData() const { return !bodySizeKnown() || needsMoreData(); }
     bool needsMoreData() const { return bodySizeKnown() && unproducedSize() > 0; }
     uint64_t unproducedSize() const; // size of still unproduced data
-    bool stillProducing(const Producer *producer) const { return theProducer == producer; }
+    bool stillProducing(const Producer::Pointer &producer) const { return theProducer == producer; }
     void expectProductionEndAfter(uint64_t extraSize); ///< sets or checks body size
 
     // called by consumers
-    bool setConsumerIfNotLate(Consumer *aConsumer);
+    bool setConsumerIfNotLate(const Consumer::Pointer &aConsumer);
     void clearConsumer(); // aborts if still piping
     size_t getMoreData(MemBuf &buf);
     void consume(size_t size);
     bool expectMoreAfter(uint64_t offset) const;
     bool exhausted() const; // saw eof/abort and all data consumed
-    bool stillConsuming(const Consumer *consumer) const { return theConsumer == consumer; }
+    bool stillConsuming(const Consumer::Pointer &consumer) const { return theConsumer == consumer; }
 
     // start or continue consuming when there is no consumer
     void enableAutoConsumption();
@@ -139,8 +143,8 @@ protected:
 
 private:
     int64_t  theBodySize;   // expected total content length, if known
-    Producer *theProducer; // content producer, if any
-    Consumer *theConsumer; // content consumer, if any
+    Producer::Pointer theProducer; // content producer, if any
+    Consumer::Pointer theConsumer; // content consumer, if any
 
     uint64_t thePutSize; // ever-increasing total
     uint64_t theGetSize; // ever-increasing total
index 6bc205227a7c38a1f2c209ba221b6bffa7afc083..8c0d478b647f7c4a7da9becf0e6e7f8bffb4b573 100644 (file)
@@ -126,6 +126,12 @@ protected:
         virtual void run (StoreEntry *sentry);
         ReconfigureAction();
     };
+    class RotateAction : public CacheManagerAction
+    {
+    public:
+        virtual void run (StoreEntry *sentry);
+        RotateAction();
+    };
     class OfflineToggleAction : public CacheManagerAction
     {
     public:
index 0a9e147f1d1c59612a31a9817c44a54f4821681d..067e7eb113b9ad81d1518be54190a2835101bf09 100644 (file)
@@ -144,17 +144,18 @@ Params &GetCommParams(AsyncCall::Pointer &call)
 // All job dialers with comm parameters are merged into one since they
 // all have exactly one callback argument and differ in Params type only
 template <class C, class Params_>
-class CommCbMemFunT: public JobDialer, public CommDialerParamsT<Params_>
+class CommCbMemFunT: public JobDialer<C>, public CommDialerParamsT<Params_>
 {
 public:
     typedef Params_ Params;
     typedef void (C::*Method)(const Params &io);
 
-    CommCbMemFunT(C *obj, Method meth): JobDialer(obj),
-            CommDialerParamsT<Params>(obj), object(obj), method(meth) {}
+    CommCbMemFunT(const CbcPointer<C> &job, Method meth): JobDialer<C>(job),
+            CommDialerParamsT<Params_>(job.get()),
+            method(meth) {}
 
     virtual bool canDial(AsyncCall &c) {
-        return JobDialer::canDial(c) &&
+        return JobDialer<C>::canDial(c) &&
                this->params.syncWithComm();
     }
 
@@ -165,11 +166,10 @@ public:
     }
 
 public:
-    C *object;
     Method method;
 
 protected:
-    virtual void doDial() { (object->*method)(this->params); }
+    virtual void doDial() { ((&(*this->job))->*method)(this->params); }
 };
 
 
index 00e41356ecb347dda23bb0882c934b6aacd0f099..96a08812a52daadffd2e8946cb3590d06ea7f273 100644 (file)
@@ -24,6 +24,12 @@ INCLUDES = \
 ## Because we use libcompat for comm_err.h header protections ...
 INCLUDES += $(KRB5INCS)
 
+## Loadable Modules requires LTDL include paths.
+## Because we need this to use the libray linking headers...
+if USE_LOADABLE_MODULES
+INCLUDES += $(INCLTDL)
+endif
+
 ## make all compiled sources depend on generated files
 ## XXX: Do we really need this? Does auto-dependency tracking work?
 $(OBJS): $(top_srcdir)/include/version.h $(top_builddir)/include/autoconf.h
index ca753f7e32badf8282e3c44eec74680771ffd6e4..dadcfed3ed5096a7006f2fd937dc365bc93b8dfa 100644 (file)
@@ -108,7 +108,7 @@ struct squidaio_thread_t {
 
 static void squidaio_queue_request(squidaio_request_t *);
 static void squidaio_cleanup_request(squidaio_request_t *);
-static void *squidaio_thread_loop(void *);
+SQUIDCEXTERN void *squidaio_thread_loop(void *);
 static void squidaio_do_open(squidaio_request_t *);
 static void squidaio_do_read(squidaio_request_t *);
 static void squidaio_do_write(squidaio_request_t *);
@@ -360,7 +360,7 @@ squidaio_shutdown(void)
     squidaio_initialised = 0;
 }
 
-static void *
+void *
 squidaio_thread_loop(void *ptr)
 {
     squidaio_thread_t *threadp = (squidaio_thread_t *)ptr;
index 22903cb0cc81bb0134ecbfab2531ad44360e5de3..d93f2f032f7c028b629b0c73e009641a529a4517 100644 (file)
@@ -123,7 +123,7 @@ static const HttpHeaderFieldAttrs HeadersAttrs[] = {
     {"Set-Cookie", HDR_SET_COOKIE, ftStr},
     {"TE", HDR_TE, ftStr},
     {"Title", HDR_TITLE, ftStr},
-    {"Trailers", HDR_TRAILERS, ftStr},
+    {"Trailer", HDR_TRAILER, ftStr},
     {"Transfer-Encoding", HDR_TRANSFER_ENCODING, ftStr},
     {"Translate", HDR_TRANSLATE, ftStr},       /* for now. may need to crop */
     {"Unless-Modified-Since", HDR_UNLESS_MODIFIED_SINCE, ftStr},  /* for now ignore. may need to crop */
@@ -249,7 +249,7 @@ static http_hdr_type RequestHeadersArr[] = {
 static HttpHeaderMask HopByHopHeadersMask;
 static http_hdr_type HopByHopHeadersArr[] = {
     HDR_CONNECTION, HDR_KEEP_ALIVE, /*HDR_PROXY_AUTHENTICATE,*/ HDR_PROXY_AUTHORIZATION,
-    HDR_TE, HDR_TRAILERS, HDR_TRANSFER_ENCODING, HDR_UPGRADE, HDR_PROXY_CONNECTION
+    HDR_TE, HDR_TRAILER, HDR_TRANSFER_ENCODING, HDR_UPGRADE, HDR_PROXY_CONNECTION
 };
 
 /* header accounting */
@@ -647,6 +647,11 @@ HttpHeader::parse(const char *header_start, const char *header_end)
         addEntry(e);
     }
 
+    if (chunked()) {
+        // RFC 2616 section 4.4: ignore Content-Length with Transfer-Encoding
+        delById(HDR_CONTENT_LENGTH);
+    }
+
     PROF_stop(HttpHeaderParse);
     return 1;                  /* even if no fields where found, it is a valid header */
 reset:
@@ -1602,7 +1607,7 @@ httpHeaderNoteParsedEntry(http_hdr_type id, String const &context, int error)
 extern const HttpHeaderStat *dump_stat;                /* argh! */
 const HttpHeaderStat *dump_stat = NULL;
 
-static void
+void
 httpHeaderFieldStatDumper(StoreEntry * sentry, int idx, double val, double size, int count)
 {
     const int id = (int) val;
index c9e3e9696b4ce1d84c12cafc67ebc9622e27ac67..53bea2e9189e67f68b28dc9f28af44390ce29b80 100644 (file)
@@ -40,7 +40,6 @@
 
 
 /* class forward declarations */
-class HttpVersion;
 class HttpHdrContRange;
 class HttpHdrCc;
 class HttpHdrSc;
@@ -104,7 +103,7 @@ typedef enum {
     HDR_SET_COOKIE,
     HDR_TE,
     HDR_TITLE,
-    HDR_TRAILERS,
+    HDR_TRAILER,
     HDR_TRANSFER_ENCODING,
     HDR_TRANSLATE,             /* IIS custom header we may need to cut off */
     HDR_UNLESS_MODIFIED_SINCE,             /* IIS custom header we may need to cut off */
@@ -255,6 +254,7 @@ public:
     int hasListMember(http_hdr_type id, const char *member, const char separator) const;
     int hasByNameListMember(const char *name, const char *member, const char separator) const;
     void removeHopByHopEntries();
+    inline bool chunked() const; ///< whether message uses chunked Transfer-Encoding
 
     /* protected, do not use these, use interface functions instead */
     Vector<HttpHeaderEntry *> entries;         /**< parsed fields in raw format */
@@ -278,8 +278,13 @@ private:
 extern int httpHeaderParseQuotedString (const char *start, String *val);
 SQUIDCEXTERN int httpHeaderHasByNameListMember(const HttpHeader * hdr, const char *name, const char *member, const char separator);
 SQUIDCEXTERN void httpHeaderUpdate(HttpHeader * old, const HttpHeader * fresh, const HttpHeaderMask * denied_mask);
-int httpMsgIsPersistent(HttpVersion const &http_ver, const HttpHeader * hdr);
-
 SQUIDCEXTERN void httpHeaderCalcMask(HttpHeaderMask * mask, http_hdr_type http_hdr_type_enums[], size_t count);
 
+inline bool
+HttpHeader::chunked() const
+{
+    return has(HDR_TRANSFER_ENCODING) &&
+           hasListMember(HDR_TRANSFER_ENCODING, "chunked", ',');
+}
+
 #endif /* SQUID_HTTPHEADER_H */
index c4b995b34989a8ab0694916fee46735295842107..2d332650814949fe954dc798ccec41a785753153 100644 (file)
@@ -145,18 +145,18 @@ int
 httpHeaderHasConnDir(const HttpHeader * hdr, const char *directive)
 {
     String list;
-    http_hdr_type ht;
     int res;
     /* what type of header do we have? */
 
+#if USE_HTTP_VIOLATIONS
     if (hdr->has(HDR_PROXY_CONNECTION))
-        ht = HDR_PROXY_CONNECTION;
-    else if (hdr->has(HDR_CONNECTION))
-        ht = HDR_CONNECTION;
+        list = hdr->getList(HDR_PROXY_CONNECTION);
     else
-        return 0;
-
-    list = hdr->getList(ht);
+#endif
+        if (hdr->has(HDR_CONNECTION))
+            list = hdr->getList(HDR_CONNECTION);
+        else
+            return 0;
 
     res = strListIsMember(&list, directive, ',');
 
index 15466eb7ea8fc54b11762d7ccad323bf482ca8fd..8ec450b5418c4b98a1ba10ced4d4ada367aa260e 100644 (file)
@@ -316,26 +316,24 @@ HttpMsg::setContentLength(int64_t clen)
     content_length = clen;
 }
 
-/* returns true if connection should be "persistent"
- * after processing this message */
-int
-httpMsgIsPersistent(HttpVersion const &http_ver, const HttpHeader * hdr)
+bool
+HttpMsg::persistent() const
 {
-    if ((http_ver.major >= 1) && (http_ver.minor >= 1)) {
+    if (http_ver > HttpVersion(1, 0)) {
         /*
          * for modern versions of HTTP: persistent unless there is
          * a "Connection: close" header.
          */
-        return !httpHeaderHasConnDir(hdr, "close");
+        return !httpHeaderHasConnDir(&header, "close");
     } else {
         /*
          * Persistent connections in Netscape 3.x are allegedly broken,
          * return false if it is a browser connection.  If there is a
          * VIA header, then we assume this is NOT a browser connection.
          */
-        const char *agent = hdr->getStr(HDR_USER_AGENT);
+        const char *agent = header.getStr(HDR_USER_AGENT);
 
-        if (agent && !hdr->has(HDR_VIA)) {
+        if (agent && !header.has(HDR_VIA)) {
             if (!strncasecmp(agent, "Mozilla/3.", 10))
                 return 0;
 
@@ -344,7 +342,7 @@ httpMsgIsPersistent(HttpVersion const &http_ver, const HttpHeader * hdr)
         }
 
         /* for old versions of HTTP: persistent if has "keep-alive" */
-        return httpHeaderHasConnDir(hdr, "keep-alive");
+        return httpHeaderHasConnDir(&header, "keep-alive");
     }
 }
 
index a707b1c57b6559beddf21168110518edc0b35d2e..3d536bb0294fb49d3c76542df2e03d00a7e85c2b 100644 (file)
@@ -61,6 +61,14 @@ public:
     /// [re]sets Content-Length header and cached value
     void setContentLength(int64_t clen);
 
+    /**
+     * \retval true  the message sender asks to keep the connection open.
+     * \retval false the message sender will close the connection.
+     *
+     * Factors other than the headers may result in connection closure.
+     */
+    bool persistent() const;
+
 public:
     HttpVersion http_ver;
 
index 123c323910a6f3eeadce29c2998f7ccb1614fe02..5c55886cb73d8ceb7faa252fca85a34dc3672b7b 100644 (file)
@@ -62,7 +62,7 @@ static HttpHeaderMask Denied304HeadersMask;
 static http_hdr_type Denied304HeadersArr[] = {
     // hop-by-hop headers
     HDR_CONNECTION, HDR_KEEP_ALIVE, HDR_PROXY_AUTHENTICATE, HDR_PROXY_AUTHORIZATION,
-    HDR_TE, HDR_TRAILERS, HDR_TRANSFER_ENCODING, HDR_UPGRADE,
+    HDR_TE, HDR_TRAILER, HDR_TRANSFER_ENCODING, HDR_UPGRADE,
     // entity headers
     HDR_ALLOW, HDR_CONTENT_ENCODING, HDR_CONTENT_LANGUAGE, HDR_CONTENT_LENGTH,
     HDR_CONTENT_MD5, HDR_CONTENT_RANGE, HDR_CONTENT_TYPE, HDR_LAST_MODIFIED
@@ -377,12 +377,13 @@ HttpReply::hdrCacheInit()
 {
     HttpMsg::hdrCacheInit();
 
+    http_ver = sline.version;
     content_length = header.getInt64(HDR_CONTENT_LENGTH);
     date = header.getTime(HDR_DATE);
     last_modified = header.getTime(HDR_LAST_MODIFIED);
     surrogate_control = header.getSc();
     content_range = header.getContRange();
-    keep_alive = httpMsgIsPersistent(sline.version, &header);
+    keep_alive = persistent() ? 1 : 0;
     const char *str = header.getStr(HDR_CONTENT_TYPE);
 
     if (str)
@@ -540,7 +541,7 @@ HttpReply::expectingBody(const HttpRequestMethod& req_method, int64_t& theSize)
         expectBody = true;
 
     if (expectBody) {
-        if (header.hasListMember(HDR_TRANSFER_ENCODING, "chunked", ','))
+        if (header.chunked())
             theSize = -1;
         else if (content_length >= 0)
             theSize = content_length;
index 3c0d4c861c58b3acc485747c0c34c3601e15f28f..377a03af7d75ee281e5f21f305fc8e815e2041c3 100644 (file)
@@ -499,7 +499,7 @@ HttpRequest::expectingBody(const HttpRequestMethod& unused, int64_t& theSize) co
         expectBody = Config.onoff.request_entities ? true : false;
     else if (method == METHOD_PUT || method == METHOD_POST)
         expectBody = true;
-    else if (header.hasListMember(HDR_TRANSFER_ENCODING, "chunked", ','))
+    else if (header.chunked())
         expectBody = true;
     else if (content_length >= 0)
         expectBody = true;
@@ -507,7 +507,7 @@ HttpRequest::expectingBody(const HttpRequestMethod& unused, int64_t& theSize) co
         expectBody = false;
 
     if (expectBody) {
-        if (header.hasListMember(HDR_TRANSFER_ENCODING, "chunked", ','))
+        if (header.chunked())
             theSize = -1;
         else if (content_length >= 0)
             theSize = content_length;
index fb19b2b3bf3e03aba2c4d42e4f3608c17a10f18a..ed60074b0f1cc3c7bd7e58a53c8a9718d1398445 100644 (file)
@@ -66,6 +66,23 @@ public:
         return ((this->major != that.major) || (this->minor != that.minor));
     }
 
+    bool operator <(const HttpVersion& that) const {
+        return (this->major < that.major ||
+                (this->major == that.major && this->minor < that.minor));
+    }
+
+    bool operator >(const HttpVersion& that) const {
+        return (this->major > that.major ||
+                (this->major == that.major && this->minor > that.minor));
+    }
+
+    bool operator <=(const HttpVersion& that) const {
+        return !(*this > that);
+    }
+
+    bool operator >=(const HttpVersion& that) const {
+        return !(*this < that);
+    }
 };
 
 #endif /* SQUID_HTTPVERSION_H */
index c67ebe1b3268f97419dcd02cc7c1cf5cb5c5dd71..fc0c273ea8092d66cf1e7f5f1dde223f9ca0f81c 100644 (file)
@@ -725,8 +725,8 @@ nodist_DiskIO_DiskDaemon_diskd_SOURCES = time.cc
 DiskIO_DiskDaemon_diskd_LDADD = $(COMPAT_LIB) $(XTRA_LIBS)
 
 
-DEFAULT_HTTP_PORT      = $(CACHE_HTTP_PORT)
-DEFAULT_ICP_PORT       = $(CACHE_ICP_PORT)
+DEFAULT_HTTP_PORT      = 3128
+DEFAULT_ICP_PORT       = 3130
 DEFAULT_PREFIX         = $(prefix)
 DEFAULT_CONFIG_DIR     = $(sysconfdir)
 DEFAULT_CONFIG_FILE     = $(DEFAULT_CONFIG_DIR)/squid.conf
@@ -736,7 +736,6 @@ DEFAULT_LOG_PREFIX  = $(DEFAULT_LOG_DIR)
 DEFAULT_CACHE_LOG       = $(DEFAULT_LOG_PREFIX)/cache.log
 DEFAULT_ACCESS_LOG      = $(DEFAULT_LOG_PREFIX)/access.log
 DEFAULT_STORE_LOG       = $(DEFAULT_LOG_PREFIX)/store.log
-DEFAULT_PID_FILE        = $(DEFAULT_PIDFILE)
 DEFAULT_NETDB_FILE      = $(DEFAULT_LOG_PREFIX)/netdb.state
 DEFAULT_SWAP_DIR        = $(localstatedir)/cache
 DEFAULT_PINGER         = $(libexecdir)/`echo pinger | sed '$(transform);s/$$/$(EXEEXT)/'`
@@ -745,7 +744,6 @@ DEFAULT_LOGFILED    = $(libexecdir)/`echo log_file_daemon | sed '$(transform);s/$$/
 DEFAULT_DISKD          = $(libexecdir)/`echo diskd | sed '$(transform);s/$$/$(EXEEXT)/'`
 DEFAULT_ICON_DIR       = $(datadir)/icons
 DEFAULT_ERROR_DIR      = $(datadir)/errors
-DEFAULT_HOSTS          = $(OPT_DEFAULT_HOSTS)
 
 # Make location configure settings available to the code
 DEFS += -DDEFAULT_CONFIG_FILE=\"$(DEFAULT_CONFIG_FILE)\" -DDEFAULT_SQUID_DATA_DIR=\"$(datadir)\" -DDEFAULT_SQUID_CONFIG_DIR=\"$(sysconfdir)\"
@@ -1113,6 +1111,7 @@ tests_testCacheManager_SOURCES = \
        tests/testCacheManager.cc \
        tests/testCacheManager.h \
        tests/testMain.cc \
+       tests/stub_main_cc.cc \
        time.cc \
        BodyPipe.cc \
        cache_manager.cc \
@@ -1297,6 +1296,7 @@ tests_testEvent_SOURCES = \
        tests/testEvent.cc \
        tests/testEvent.h \
        tests/testMain.cc \
+       tests/stub_main_cc.cc \
        time.cc \
        BodyPipe.cc \
        cache_manager.cc \
@@ -1452,6 +1452,7 @@ tests_testEventLoop_SOURCES = \
        tests/testEventLoop.cc \
        tests/testEventLoop.h \
        tests/testMain.cc \
+       tests/stub_main_cc.cc \
        time.cc \
        BodyPipe.cc \
        cache_manager.cc \
@@ -1614,6 +1615,7 @@ tests_test_http_range_SOURCES = \
        $(squid_COMMSOURCES) \
        ConfigOption.cc \
        ConfigParser.cc \
+       tests/stub_main_cc.cc \
        debug.cc \
        $(DELAY_POOL_SOURCE) \
        disk.cc \
@@ -1756,6 +1758,7 @@ tests_testHttpRequest_SOURCES = \
        tests/testHttpRequestMethod.h \
        tests/testHttpRequestMethod.cc \
        tests/testMain.cc \
+       tests/stub_main_cc.cc \
        time.cc \
        BodyPipe.cc \
        cache_manager.cc \
@@ -2131,6 +2134,7 @@ tests_testURL_SOURCES = \
        tests/testURLScheme.cc \
        tests/testURLScheme.h \
        tests/testMain.cc \
+       tests/stub_main_cc.cc \
        time.cc \
        BodyPipe.cc \
        cache_manager.cc \
@@ -2276,12 +2280,7 @@ TESTS += testHeaders
 ## Special Universal .h dependency test script
 ## aborts if error encountered
 testHeaders: $(srcdir)/*.h $(srcdir)/DiskIO/*.h $(srcdir)/DiskIO/*/*.h
-       $(SHELL) $(top_srcdir)/test-suite/testheaders.sh "$(CXXCOMPILE)" "$(srcdir)" || exit 1
-       $(SHELL) $(top_srcdir)/test-suite/testheaders.sh "$(CXXCOMPILE)" "$(srcdir)/DiskIO" || exit 1
-       $(SHELL) $(top_srcdir)/test-suite/testheaders.sh "$(CXXCOMPILE)" "$(srcdir)/DiskIO/AIO" || exit 1
-       $(SHELL) $(top_srcdir)/test-suite/testheaders.sh "$(CXXCOMPILE)" "$(srcdir)/DiskIO/Blocking" || exit 1
-       $(SHELL) $(top_srcdir)/test-suite/testheaders.sh "$(CXXCOMPILE)" "$(srcdir)/DiskIO/DiskDaemon" || exit 1
-       $(SHELL) $(top_srcdir)/test-suite/testheaders.sh "$(CXXCOMPILE)" "$(srcdir)/DiskIO/DiskThreads" || exit 1
+       $(SHELL) $(top_srcdir)/test-suite/testheaders.sh "$(CXXCOMPILE)" $^ || exit 1
 ## src/repl/ has no .h files and its own makefile.
 
 CLEANFILES += testHeaders
index cb743b33d9dee7e8b8bd9d572fd14d3f828e78a5..9af6116dd1424489c57133376580d444c13c426c 100644 (file)
@@ -421,8 +421,8 @@ ServerStateData::sendMoreRequestBody()
     if (requestBodySource->getMoreData(buf)) {
         debugs(9,3, HERE << "will write " << buf.contentSize() << " request body bytes");
         typedef CommCbMemFunT<ServerStateData, CommIoCbParams> Dialer;
-        requestSender = asyncCall(93,3, "ServerStateData::sentRequestBody",
-                                  Dialer(this, &ServerStateData::sentRequestBody));
+        requestSender = JobCallback(93,3,
+                                    Dialer, this, ServerStateData::sentRequestBody);
         comm_write_mbuf(conn->fd, &buf, requestSender);
     } else {
         debugs(9,3, HERE << "will wait for more request body bytes or eof");
@@ -548,8 +548,8 @@ ServerStateData::startAdaptation(const Adaptation::ServiceGroupPointer &group, H
     }
 
     adaptedHeadSource = initiateAdaptation(
-                            new Adaptation::Iterator(this, vrep, cause, group));
-    startedAdaptation = adaptedHeadSource != NULL;
+                            new Adaptation::Iterator(vrep, cause, group));
+    startedAdaptation = initiated(adaptedHeadSource);
     Must(startedAdaptation);
 }
 
index 01e0fe085ab4ef980b203964779a18303a3a3ac6..a5345e31d285496973fc25f68d786001a9f68b08 100644 (file)
@@ -186,7 +186,7 @@ protected:
 
 #if USE_ADAPTATION
     BodyPipe::Pointer virginBodyDestination;  /**< to provide virgin response body */
-    Adaptation::Initiate *adaptedHeadSource;  /**< to get adapted response headers */
+    CbcPointer<Adaptation::Initiate> adaptedHeadSource;  /**< to get adapted response headers */
     BodyPipe::Pointer adaptedBodySource;      /**< to consume adated response body */
 
     bool adaptationAccessCheckPending;
index 953c2e84a1384760d4f449216b88cc80ddac5b83..c399636ab5b35c0cbc99b886cedf25a817a368c4 100644 (file)
@@ -23,8 +23,9 @@ Adaptation::AccessCheck::Start(Method method, VectPoint vp,
 
     if (Config::Enabled) {
         // the new check will call the callback and delete self, eventually
-        return AsyncStart(new AccessCheck(
-                              ServiceFilter(method, vp, req, rep), cb, cbdata));
+        AsyncJob::Start(new AccessCheck( // we do not store so not a CbcPointer
+                            ServiceFilter(method, vp, req, rep), cb, cbdata));
+        return true;
     }
 
     debugs(83, 3, HERE << "adaptation off, skipping");
index 110c4108babfdde84182c2ec24733bbb5d58410f..ffba5bc923b7b64d4f5d5c8eef141c6db373269f 100644 (file)
@@ -6,6 +6,7 @@
 #include "HttpMsg.h"
 #include "adaptation/Initiator.h"
 #include "adaptation/Initiate.h"
+#include "base/AsyncJobCalls.h"
 
 namespace Adaptation
 {
@@ -17,11 +18,13 @@ class AnswerDialer: public UnaryMemFunT<Initiator, HttpMsg*>
 public:
     typedef UnaryMemFunT<Initiator, HttpMsg*> Parent;
 
-    AnswerDialer(Initiator *obj, Parent::Method meth, HttpMsg *msg):
-            Parent(obj, meth, msg) { HTTPMSGLOCK(arg1); }
-    AnswerDialer(const AnswerDialer &d):
-            Parent(d) { HTTPMSGLOCK(arg1); }
+    AnswerDialer(const Parent::JobPointer &job, Parent::Method meth,
+                 HttpMsg *msg): Parent(job, meth, msg) { HTTPMSGLOCK(arg1); }
+    AnswerDialer(const AnswerDialer &d): Parent(d) { HTTPMSGLOCK(arg1); }
     virtual ~AnswerDialer() { HTTPMSGUNLOCK(arg1); }
+
+private:
+    AnswerDialer &operator =(const AnswerDialer &); // not implemented
 };
 
 } // namespace Adaptation
@@ -29,10 +32,8 @@ public:
 
 /* Initiate */
 
-Adaptation::Initiate::Initiate(const char *aTypeName, Initiator *anInitiator):
-        AsyncJob(aTypeName), theInitiator(anInitiator)
+Adaptation::Initiate::Initiate(const char *aTypeName): AsyncJob(aTypeName)
 {
-    assert(theInitiator);
 }
 
 Adaptation::Initiate::~Initiate()
@@ -42,12 +43,21 @@ Adaptation::Initiate::~Initiate()
     // can assert(!(wasStarted && theInitiator)).
 }
 
+void
+Adaptation::Initiate::initiator(const CbcPointer<Initiator> &i)
+{
+    Must(!theInitiator);
+    Must(i.valid());
+    theInitiator = i;
+}
+
+
 // internal cleanup
 void Adaptation::Initiate::swanSong()
 {
     debugs(93, 5, HERE << "swan sings" << status());
 
-    if (theInitiator) {
+    if (theInitiator.set()) {
         debugs(93, 3, HERE << "fatal failure; sending abort notification");
         tellQueryAborted(true); // final by default
     }
@@ -57,27 +67,22 @@ void Adaptation::Initiate::swanSong()
 
 void Adaptation::Initiate::clearInitiator()
 {
-    if (theInitiator)
-        theInitiator.clear();
+    theInitiator.clear();
 }
 
 void Adaptation::Initiate::sendAnswer(HttpMsg *msg)
 {
     assert(msg);
-    if (theInitiator.isThere()) {
-        CallJob(93, 5, __FILE__, __LINE__, "Initiator::noteAdaptAnswer",
-                AnswerDialer(theInitiator.ptr(), &Initiator::noteAdaptationAnswer, msg));
-    }
+    CallJob(93, 5, __FILE__, __LINE__, "Initiator::noteAdaptationAnswer",
+            AnswerDialer(theInitiator, &Initiator::noteAdaptationAnswer, msg));
     clearInitiator();
 }
 
 
 void Adaptation::Initiate::tellQueryAborted(bool final)
 {
-    if (theInitiator.isThere()) {
-        CallJobHere1(93, 5, theInitiator.ptr(),
-                     Initiator::noteAdaptationQueryAbort, final);
-    }
+    CallJobHere1(93, 5, theInitiator,
+                 Initiator, noteAdaptationQueryAbort, final);
     clearInitiator();
 }
 
@@ -85,57 +90,3 @@ const char *Adaptation::Initiate::status() const
 {
     return AsyncJob::status(); // for now
 }
-
-
-/* InitiatorHolder */
-
-Adaptation::InitiatorHolder::InitiatorHolder(Initiator *anInitiator):
-        prime(0), cbdata(0)
-{
-    if (anInitiator) {
-        cbdata = cbdataReference(anInitiator->toCbdata());
-        prime = anInitiator;
-    }
-}
-
-Adaptation::InitiatorHolder::InitiatorHolder(const InitiatorHolder &anInitiator):
-        prime(0), cbdata(0)
-{
-    if (anInitiator != NULL && cbdataReferenceValid(anInitiator.cbdata)) {
-        cbdata = cbdataReference(anInitiator.cbdata);
-        prime = anInitiator.prime;
-    }
-}
-
-Adaptation::InitiatorHolder::~InitiatorHolder()
-{
-    clear();
-}
-
-void Adaptation::InitiatorHolder::clear()
-{
-    if (prime) {
-        prime = NULL;
-        cbdataReferenceDone(cbdata);
-    }
-}
-
-Adaptation::Initiator *Adaptation::InitiatorHolder::ptr()
-{
-    assert(isThere());
-    return prime;
-}
-
-bool
-Adaptation::InitiatorHolder::isThere()
-{
-    return prime && cbdataReferenceValid(cbdata);
-}
-
-// should not be used
-Adaptation::InitiatorHolder &
-Adaptation::InitiatorHolder::operator =(const InitiatorHolder &anInitiator)
-{
-    assert(false);
-    return *this;
-}
index 1cca091995f41b9c52a7bedd7d470873b61a2240..1baa959c274a693c38875606d90096f4e8ac2fea 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef SQUID_ADAPTATION__INITIATE_H
 #define SQUID_ADAPTATION__INITIATE_H
 
-#include "base/AsyncCall.h"
 #include "base/AsyncJob.h"
+#include "base/CbcPointer.h"
 #include "adaptation/forward.h"
 
 class HttpMsg;
@@ -10,37 +10,6 @@ class HttpMsg;
 namespace Adaptation
 {
 
-/* Initiator holder associtates an initiator with its cbdata. It is used as
- * a temporary hack to make cbdata work with multiple inheritance. We need
- * this hack because we cannot know whether the initiator pointer is still
- * valid without dereferencing it to call toCbdata()
- * TODO: JobDialer uses the same trick. Factor out or move this code. */
-class InitiatorHolder
-{
-public:
-    InitiatorHolder(Initiator *anInitiator);
-    InitiatorHolder(const InitiatorHolder &anInitiator);
-    ~InitiatorHolder();
-
-    void clear();
-
-    // to make comparison with NULL possible
-    operator void*() { return prime; }
-    bool operator == (void *) const { return prime == NULL; }
-    bool operator != (void *) const { return prime != NULL; }
-    bool operator !() const { return !prime; }
-
-    bool isThere(); // we have a valid initiator pointer
-    Initiator *ptr(); // asserts isThere()
-    void *theCbdata() { return cbdata;}
-
-private:
-    InitiatorHolder &operator =(const InitiatorHolder &anInitiator);
-
-    Initiator *prime;
-    void *cbdata;
-};
-
 /*
  * The  Initiate is a common base for  queries or transactions
  * initiated by an Initiator. This interface exists to allow an
@@ -56,9 +25,11 @@ class Initiate: virtual public AsyncJob
 {
 
 public:
-    Initiate(const char *aTypeName, Initiator *anInitiator);
+    Initiate(const char *aTypeName);
     virtual ~Initiate();
 
+    void initiator(const CbcPointer<Initiator> &i); ///< sets initiator
+
     // communication with the initiator
     virtual void noteInitiatorAborted() = 0;
 
@@ -71,7 +42,7 @@ protected:
 
     virtual const char *status() const; // for debugging
 
-    InitiatorHolder theInitiator;
+    CbcPointer<Initiator> theInitiator;
 
 private:
     Initiate(const Initiate &); // no definition
index d5ba04223e95a90b442b32bf65f59cc550759c1f..f72e69f8ea6f50cfe14540f46f6bb5042c3c6346 100644 (file)
@@ -5,27 +5,26 @@
 #include "squid.h"
 #include "adaptation/Initiate.h"
 #include "adaptation/Initiator.h"
+#include "base/AsyncJobCalls.h"
 
-Adaptation::Initiate *
-Adaptation::Initiator::initiateAdaptation(Adaptation::Initiate *x)
+CbcPointer<Adaptation::Initiate>
+Adaptation::Initiator::initiateAdaptation(Initiate *x)
 {
-    if ((x = dynamic_cast<Initiate*>(Initiate::AsyncStart(x))))
-        x = cbdataReference(x);
-    return x;
+    CbcPointer<Initiate> i(x);
+    x->initiator(this);
+    Start(x);
+    return i;
 }
 
 void
-Adaptation::Initiator::clearAdaptation(Initiate *&x)
+Adaptation::Initiator::clearAdaptation(CbcPointer<Initiate> &x)
 {
-    assert(x);
-    cbdataReferenceDone(x);
+    x.clear();
 }
 
 void
-Adaptation::Initiator::announceInitiatorAbort(Initiate *&x)
+Adaptation::Initiator::announceInitiatorAbort(CbcPointer<Initiate> &x)
 {
-    if (x) {
-        CallJobHere(93, 5, x, Initiate::noteInitiatorAborted);
-        clearAdaptation(x);
-    }
+    CallJobHere(93, 5, x, Initiate, noteInitiatorAborted);
+    clearAdaptation(x);
 }
index ba2a1254f10957db81ea04346fc915398a8c56d2..32c6a249d742700c914c0240729b62d919fe0c5d 100644 (file)
@@ -2,6 +2,7 @@
 #define SQUID_ADAPTATION__INITIATOR_H
 
 #include "base/AsyncJob.h"
+#include "base/CbcPointer.h"
 #include "adaptation/forward.h"
 
 /*
@@ -32,13 +33,17 @@ public:
     virtual void noteAdaptationQueryAbort(bool final) = 0;
 
 protected:
-    Initiate *initiateAdaptation(Initiate *x); // locks and returns x
+    ///< starts freshly created initiate and returns a safe pointer to it
+    CbcPointer<Initiate> initiateAdaptation(Initiate *x);
 
-    // done with x (and not calling announceInitiatorAbort)
-    void clearAdaptation(Initiate *&x); // unlocks x
+    /// clears the pointer (does not call announceInitiatorAbort)
+    void clearAdaptation(CbcPointer<Initiate> &x);
 
-    // inform the transaction about abnormal termination and clear it
-    void announceInitiatorAbort(Initiate *&x); // unlocks x
+    /// inform the transaction about abnormal termination and clear the pointer
+    void announceInitiatorAbort(CbcPointer<Initiate> &x);
+
+    /// Must(initiated(initiate)) instead of Must(initiate.set()), for clarity
+    bool initiated(const CbcPointer<AsyncJob> &job) const { return job.set(); }
 };
 
 } // namespace Adaptation
index a85932dfcaffe985a3e255b4371313ed7328d0ac..6f46121c3894ae96190e69223d9ad3bffd66a0b9 100644 (file)
 #include "HttpMsg.h"
 
 
-Adaptation::Iterator::Iterator(Adaptation::Initiator *anInitiator,
-                               HttpMsg *aMsg, HttpRequest *aCause,
-                               const ServiceGroupPointer &aGroup):
+Adaptation::Iterator::Iterator(
+    HttpMsg *aMsg, HttpRequest *aCause,
+    const ServiceGroupPointer &aGroup):
         AsyncJob("Iterator"),
-        Adaptation::Initiate("Iterator", anInitiator),
+        Adaptation::Initiate("Iterator"),
         theGroup(aGroup),
         theMsg(HTTPMSGLOCK(aMsg)),
         theCause(aCause ? HTTPMSGLOCK(aCause) : NULL),
@@ -69,8 +69,8 @@ void Adaptation::Iterator::step()
     debugs(93,5, HERE << "using adaptation service: " << service->cfg().key);
 
     theLauncher = initiateAdaptation(
-                      service->makeXactLauncher(this, theMsg, theCause));
-    Must(theLauncher);
+                      service->makeXactLauncher(theMsg, theCause));
+    Must(initiated(theLauncher));
     Must(!done());
 }
 
@@ -148,10 +148,10 @@ bool Adaptation::Iterator::doneAll() const
 
 void Adaptation::Iterator::swanSong()
 {
-    if (theInitiator)
+    if (theInitiator.set())
         tellQueryAborted(true); // abnormal condition that should not happen
 
-    if (theLauncher)
+    if (initiated(theLauncher))
         clearAdaptation(theLauncher);
 
     Adaptation::Initiate::swanSong();
index 0a0b35483a96fe00e72cf5faffb3c133ce60c204..b1313bf190b7daf2ff9253a5abca0ec93c8730aa 100644 (file)
@@ -21,8 +21,7 @@ namespace Adaptation
 class Iterator: public Initiate, public Initiator
 {
 public:
-    Iterator(Adaptation::Initiator *anInitiator,
-             HttpMsg *virginHeader, HttpRequest *virginCause,
+    Iterator(HttpMsg *virginHeader, HttpRequest *virginCause,
              const Adaptation::ServiceGroupPointer &aGroup);
     virtual ~Iterator();
 
@@ -52,7 +51,7 @@ protected:
     ServicePlan thePlan; ///< which services to use and in what order
     HttpMsg *theMsg; ///< the message being adapted (virgin for each step)
     HttpRequest *theCause; ///< the cause of the original virgin message
-    Adaptation::Initiate *theLauncher; ///< current transaction launcher
+    CbcPointer<Adaptation::Initiate> theLauncher; ///< current transaction launcher
     int iterations; ///< number of steps initiated
     bool adapted; ///< whether the virgin message has been replaced
 
index e8d24806993739fbf75c89131026e2ca095eecfe..5ecd433aec03fc96ec6361aaee7ed44f379ecd9b 100644 (file)
@@ -12,11 +12,6 @@ if USE_ECAP
 SUBDIRS += ecap
 endif
 
-if USE_LOADABLE_MODULES
-## LTDL headers require their local include path...
-INCLUDES += $(INCLTDL)
-endif
-
 noinst_LTLIBRARIES = libadaptation.la
 
 ## start with the code shared among all adaptation schemes
index 50a727c7ae2d2eeca2c74e5e90ffb4b0bf17a4ef..59ea039f4c778e51732e3e017f9ee4b8913c66ae 100644 (file)
@@ -31,7 +31,7 @@ public:
     virtual bool broken() const;
     virtual bool up() const = 0; // see comments above
 
-    virtual Initiate *makeXactLauncher(Initiator *, HttpMsg *virginHeader, HttpRequest *virginCause) = 0;
+    virtual Initiate *makeXactLauncher(HttpMsg *virginHeader, HttpRequest *virginCause) = 0;
 
     bool wants(const ServiceFilter &filter) const;
 
index 8244accf170db1cdcaa9290babd5594fcf41473d..6d8566d4c6142d870b3d73055d06a34cf278a535 100644 (file)
@@ -57,11 +57,11 @@ bool Adaptation::Ecap::ServiceRep::wantsUrl(const String &urlPath) const
 }
 
 Adaptation::Initiate *
-Adaptation::Ecap::ServiceRep::makeXactLauncher(Adaptation::Initiator *initiator,
-        HttpMsg *virgin, HttpRequest *cause)
+Adaptation::Ecap::ServiceRep::makeXactLauncher(HttpMsg *virgin,
+        HttpRequest *cause)
 {
     Must(up());
-    XactionRep *rep = new XactionRep(initiator, virgin, cause, Pointer(this));
+    XactionRep *rep = new XactionRep(virgin, cause, Pointer(this));
     XactionRep::AdapterXaction x(theService->makeXaction(rep));
     rep->master(x);
     return rep;
index 27046b9a98f1af0ff6854480b0c37a17533944f2..9c858ccf268835fce6a28a336f1ab2a410bbb274 100644 (file)
@@ -33,7 +33,7 @@ public:
     virtual bool probed() const;
     virtual bool up() const;
 
-    Adaptation::Initiate *makeXactLauncher(Adaptation::Initiator *, HttpMsg *virginHeader, HttpRequest *virginCause);
+    Adaptation::Initiate *makeXactLauncher(HttpMsg *virginHeader, HttpRequest *virginCause);
 
     // the methods below can only be called on an up() service
     virtual bool wantsUrl(const String &urlPath) const;
index d73e10d00d5badc92ce1ec091e9ede946484d911..462dc160edffaf013d35302a1cad0109883fc228 100644 (file)
 CBDATA_NAMESPACED_CLASS_INIT(Adaptation::Ecap::XactionRep, XactionRep);
 
 
-Adaptation::Ecap::XactionRep::XactionRep(Adaptation::Initiator *anInitiator,
-        HttpMsg *virginHeader, HttpRequest *virginCause,
-        const Adaptation::ServicePointer &aService):
+Adaptation::Ecap::XactionRep::XactionRep(
+    HttpMsg *virginHeader, HttpRequest *virginCause,
+    const Adaptation::ServicePointer &aService):
         AsyncJob("Adaptation::Ecap::XactionRep"),
-        Adaptation::Initiate("Adaptation::Ecap::XactionRep", anInitiator),
+        Adaptation::Initiate("Adaptation::Ecap::XactionRep"),
         theService(aService),
         theVirginRep(virginHeader), theCauseRep(NULL),
         proxyingVb(opUndecided), proxyingAb(opUndecided),
index 2930e9e5fdc76873534602f986782f44fc162316..e07cb981bcc3285201d0cef04a02e88b15728c40 100644 (file)
@@ -28,7 +28,7 @@ class XactionRep : public Adaptation::Initiate, public libecap::host::Xaction,
         public BodyConsumer, public BodyProducer
 {
 public:
-    XactionRep(Adaptation::Initiator *anInitiator, HttpMsg *virginHeader, HttpRequest *virginCause, const Adaptation::ServicePointer &service);
+    XactionRep(HttpMsg *virginHeader, HttpRequest *virginCause, const Adaptation::ServicePointer &service);
     virtual ~XactionRep();
 
     typedef libecap::shared_ptr<libecap::adapter::Xaction> AdapterXaction;
index 943994b1a813437145492769aedaba4ec9f98753..f6a417cf50c1fbf6212f8c9b95311df183324cc4 100644 (file)
@@ -15,9 +15,9 @@
 
 
 Adaptation::Icap::Launcher::Launcher(const char *aTypeName,
-                                     Adaptation::Initiator *anInitiator, Adaptation::ServicePointer &aService):
+                                     Adaptation::ServicePointer &aService):
         AsyncJob(aTypeName),
-        Adaptation::Initiate(aTypeName, anInitiator),
+        Adaptation::Initiate(aTypeName),
         theService(aService), theXaction(0), theLaunches(0)
 {
 }
@@ -31,7 +31,7 @@ void Adaptation::Icap::Launcher::start()
 {
     Adaptation::Initiate::start();
 
-    Must(theInitiator);
+    Must(theInitiator.set());
     launchXaction("first");
 }
 
@@ -47,7 +47,7 @@ void Adaptation::Icap::Launcher::launchXaction(const char *xkind)
     if (theLaunches >= TheConfig.repeat_limit)
         x->disableRepeats("over icap_retry_limit");
     theXaction = initiateAdaptation(x);
-    Must(theXaction);
+    Must(initiated(theXaction));
 }
 
 void Adaptation::Icap::Launcher::noteAdaptationAnswer(HttpMsg *message)
@@ -76,7 +76,7 @@ void Adaptation::Icap::Launcher::noteAdaptationQueryAbort(bool final)
     Must(done()); // swanSong will notify the initiator
 }
 
-void Adaptation::Icap::Launcher::noteXactAbort(XactAbortInfo &info)
+void Adaptation::Icap::Launcher::noteXactAbort(XactAbortInfo info)
 {
     debugs(93,5, HERE << "theXaction:" << theXaction << " launches: " << theLaunches);
 
@@ -102,10 +102,10 @@ bool Adaptation::Icap::Launcher::doneAll() const
 
 void Adaptation::Icap::Launcher::swanSong()
 {
-    if (theInitiator)
+    if (theInitiator.set())
         tellQueryAborted(true); // always final here because abnormal
 
-    if (theXaction)
+    if (theXaction.set())
         clearAdaptation(theXaction);
 
     Adaptation::Initiate::swanSong();
index 23ffffac5209c8a9154013c49a48b180faf74bd8..054b96bf981ce60bee3385db48638127e9cb2a07 100644 (file)
@@ -73,7 +73,7 @@ class XactAbortInfo;
 class Launcher: public Adaptation::Initiate, public Adaptation::Initiator
 {
 public:
-    Launcher(const char *aTypeName, Adaptation::Initiator *anInitiator, Adaptation::ServicePointer &aService);
+    Launcher(const char *aTypeName, Adaptation::ServicePointer &aService);
     virtual ~Launcher();
 
     // Adaptation::Initiate: asynchronous communication with the initiator
@@ -81,7 +81,7 @@ public:
 
     // Adaptation::Initiator: asynchronous communication with the current transaction
     virtual void noteAdaptationAnswer(HttpMsg *message);
-    virtual void noteXactAbort(XactAbortInfo &info);
+    virtual void noteXactAbort(XactAbortInfo info);
 
 private:
     bool canRetry(XactAbortInfo &info) const; //< true if can retry in the case of persistent connection failures
@@ -100,7 +100,7 @@ protected:
     void launchXaction(const char *xkind);
 
     Adaptation::ServicePointer theService; ///< ICAP service for all launches
-    Adaptation::Initiate *theXaction; ///< current ICAP transaction
+    CbcPointer<Initiate> theXaction; ///< current ICAP transaction
     int theLaunches; // the number of transaction launches
 };
 
@@ -114,6 +114,10 @@ public:
     XactAbortInfo(const XactAbortInfo &);
     ~XactAbortInfo();
 
+    std::ostream &print(std::ostream &os) const {
+        return os << isRetriable << ',' << isRepeatable;
+    }
+
     HttpRequest *icapRequest;
     HttpReply *icapReply;
     bool isRetriable;
@@ -123,31 +127,13 @@ private:
     XactAbortInfo &operator =(const XactAbortInfo &); // undefined
 };
 
-/* required by UnaryMemFunT */
-inline std::ostream &operator << (std::ostream &os, Adaptation::Icap::XactAbortInfo info)
+inline
+std::ostream &
+operator <<(std::ostream &os, const XactAbortInfo &xai)
 {
-    // Nothing, it is unused
-    return os;
+    return xai.print(os);
 }
 
-/// A Dialer class used to schedule the Adaptation::Icap::Launcher::noteXactAbort call
-class XactAbortCall: public UnaryMemFunT<Adaptation::Icap::Launcher, Adaptation::Icap::XactAbortInfo>
-{
-public:
-    typedef void (Adaptation::Icap::Launcher::*DialMethod)(Adaptation::Icap::XactAbortInfo &);
-    XactAbortCall(Adaptation::Icap::Launcher *launcer, DialMethod aMethod,
-                  const Adaptation::Icap::XactAbortInfo &info):
-            UnaryMemFunT<Adaptation::Icap::Launcher, Adaptation::Icap::XactAbortInfo>(launcer, NULL, info),
-            dialMethod(aMethod) {}
-    virtual void print(std::ostream &os) const {  os << '(' << "retriable:" << arg1.isRetriable << ", repeatable:" << arg1.isRepeatable << ')'; }
-
-public:
-    DialMethod dialMethod;
-
-protected:
-    virtual void doDial() { (object->*dialMethod)(arg1); }
-};
-
 } // namespace Icap
 } // namespace Adaptation
 
index 3ccbfd74ead6554c46e3b5ae4c0a562c6b90a526..023dc3f466ed951d9716ab05e63847cf67fc255f 100644 (file)
@@ -38,10 +38,10 @@ Adaptation::Icap::ModXact::State::State()
     memset(this, 0, sizeof(*this));
 }
 
-Adaptation::Icap::ModXact::ModXact(Adaptation::Initiator *anInitiator, HttpMsg *virginHeader,
+Adaptation::Icap::ModXact::ModXact(HttpMsg *virginHeader,
                                    HttpRequest *virginCause, Adaptation::Icap::ServiceRep::Pointer &aService):
         AsyncJob("Adaptation::Icap::ModXact"),
-        Adaptation::Icap::Xaction("Adaptation::Icap::ModXact", anInitiator, aService),
+        Adaptation::Icap::Xaction("Adaptation::Icap::ModXact", aService),
         virginConsumed(0),
         bodyParser(NULL),
         canStartBypass(false), // too early
@@ -96,8 +96,9 @@ void Adaptation::Icap::ModXact::waitForService()
     Must(!state.serviceWaiting);
     debugs(93, 7, HERE << "will wait for the ICAP service" << status());
     state.serviceWaiting = true;
-    AsyncCall::Pointer call = asyncCall(93,5, "Adaptation::Icap::ModXact::noteServiceReady",
-                                        MemFun(this, &Adaptation::Icap::ModXact::noteServiceReady));
+    typedef NullaryMemFunT<ModXact> Dialer;
+    AsyncCall::Pointer call = JobCallback(93,5,
+                                          Dialer, this, Adaptation::Icap::ModXact::noteServiceReady);
     service().callWhenReady(call);
 }
 
@@ -1809,9 +1810,9 @@ bool Adaptation::Icap::ModXact::fillVirginHttpHeader(MemBuf &mb) const
 
 /* Adaptation::Icap::ModXactLauncher */
 
-Adaptation::Icap::ModXactLauncher::ModXactLauncher(Adaptation::Initiator *anInitiator, HttpMsg *virginHeader, HttpRequest *virginCause, Adaptation::ServicePointer aService):
+Adaptation::Icap::ModXactLauncher::ModXactLauncher(HttpMsg *virginHeader, HttpRequest *virginCause, Adaptation::ServicePointer aService):
         AsyncJob("Adaptation::Icap::ModXactLauncher"),
-        Adaptation::Icap::Launcher("Adaptation::Icap::ModXactLauncher", anInitiator, aService)
+        Adaptation::Icap::Launcher("Adaptation::Icap::ModXactLauncher", aService)
 {
     virgin.setHeader(virginHeader);
     virgin.setCause(virginCause);
@@ -1823,7 +1824,7 @@ Adaptation::Icap::Xaction *Adaptation::Icap::ModXactLauncher::createXaction()
     Adaptation::Icap::ServiceRep::Pointer s =
         dynamic_cast<Adaptation::Icap::ServiceRep*>(theService.getRaw());
     Must(s != NULL);
-    return new Adaptation::Icap::ModXact(this, virgin.header, virgin.cause, s);
+    return new Adaptation::Icap::ModXact(virgin.header, virgin.cause, s);
 }
 
 void Adaptation::Icap::ModXactLauncher::swanSong()
index d29e89a87e5f22801ebecc0056e4f76d94e64285..61bf8130af5899bd6d0404c8ef2d8f514e41e930 100644 (file)
@@ -136,7 +136,7 @@ class ModXact: public Xaction, public BodyProducer, public BodyConsumer
 {
 
 public:
-    ModXact(Adaptation::Initiator *anInitiator, HttpMsg *virginHeader, HttpRequest *virginCause, ServiceRep::Pointer &s);
+    ModXact(HttpMsg *virginHeader, HttpRequest *virginCause, ServiceRep::Pointer &s);
 
     // BodyProducer methods
     virtual void noteMoreBodySpaceAvailable(BodyPipe::Pointer);
@@ -161,7 +161,6 @@ public:
     InOut virgin;
     InOut adapted;
 
-protected:
     // bypasses exceptions if needed and possible
     virtual void callException(const std::exception &e);
 
@@ -341,7 +340,7 @@ private:
 class ModXactLauncher: public Launcher
 {
 public:
-    ModXactLauncher(Adaptation::Initiator *anInitiator, HttpMsg *virginHeader, HttpRequest *virginCause, Adaptation::ServicePointer s);
+    ModXactLauncher(HttpMsg *virginHeader, HttpRequest *virginCause, Adaptation::ServicePointer s);
 
 protected:
     virtual Xaction *createXaction();
index 93059718256e579be663b3d0df929aa3a64216bb..6903ca955576ed3e198e6d0dde5ace5743bd7db7 100644 (file)
@@ -17,9 +17,9 @@ CBDATA_NAMESPACED_CLASS_INIT(Adaptation::Icap, OptXact);
 CBDATA_NAMESPACED_CLASS_INIT(Adaptation::Icap, OptXactLauncher);
 
 
-Adaptation::Icap::OptXact::OptXact(Adaptation::Initiator *anInitiator, Adaptation::Icap::ServiceRep::Pointer &aService):
+Adaptation::Icap::OptXact::OptXact(Adaptation::Icap::ServiceRep::Pointer &aService):
         AsyncJob("Adaptation::Icap::OptXact"),
-        Adaptation::Icap::Xaction("Adaptation::Icap::OptXact", anInitiator, aService)
+        Adaptation::Icap::Xaction("Adaptation::Icap::OptXact", aService)
 {
 }
 
@@ -118,9 +118,9 @@ void Adaptation::Icap::OptXact::finalizeLogInfo()
 
 /* Adaptation::Icap::OptXactLauncher */
 
-Adaptation::Icap::OptXactLauncher::OptXactLauncher(Adaptation::Initiator *anInitiator, Adaptation::ServicePointer aService):
+Adaptation::Icap::OptXactLauncher::OptXactLauncher(Adaptation::ServicePointer aService):
         AsyncJob("Adaptation::Icap::OptXactLauncher"),
-        Adaptation::Icap::Launcher("Adaptation::Icap::OptXactLauncher", anInitiator, aService)
+        Adaptation::Icap::Launcher("Adaptation::Icap::OptXactLauncher", aService)
 {
 }
 
@@ -129,5 +129,5 @@ Adaptation::Icap::Xaction *Adaptation::Icap::OptXactLauncher::createXaction()
     Adaptation::Icap::ServiceRep::Pointer s =
         dynamic_cast<Adaptation::Icap::ServiceRep*>(theService.getRaw());
     Must(s != NULL);
-    return new Adaptation::Icap::OptXact(this, s);
+    return new Adaptation::Icap::OptXact(s);
 }
index c2119d5d34870abc70f1a4e22bbf6eb6240f6568..35561996dc5f3f8855741b3f91a6b59bac1206e2 100644 (file)
@@ -51,7 +51,7 @@ class OptXact: public Xaction
 {
 
 public:
-    OptXact(Adaptation::Initiator *anInitiator, ServiceRep::Pointer &aService);
+    OptXact(ServiceRep::Pointer &aService);
 
 protected:
     virtual void start();
@@ -76,7 +76,7 @@ private:
 class OptXactLauncher: public Launcher
 {
 public:
-    OptXactLauncher(Adaptation::Initiator *anInitiator, Adaptation::ServicePointer aService);
+    OptXactLauncher(Adaptation::ServicePointer aService);
 
 protected:
     virtual Xaction *createXaction();
index cba32c45df2abb4247e9338f940c7611a80168a2..7f06646764113dda8a6bc83c7b6a6d9437512338 100644 (file)
@@ -147,7 +147,7 @@ void Adaptation::Icap::ServiceRep::noteTimeToUpdate()
     if (!detached())
         updateScheduled = false;
 
-    if (detached() || theOptionsFetcher) {
+    if (detached() || theOptionsFetcher.set()) {
         debugs(93,5, HERE << "ignores options update " << status());
         return;
     }
@@ -200,7 +200,7 @@ void Adaptation::Icap::ServiceRep::callWhenReady(AsyncCall::Pointer &cb)
     i.callback = cb;
     theClients.push_back(i);
 
-    if (theOptionsFetcher || notifying)
+    if (theOptionsFetcher.set() || notifying)
         return; // do nothing, we will be picked up in noteTimeToNotify()
 
     if (needNewOptions())
@@ -212,7 +212,7 @@ void Adaptation::Icap::ServiceRep::callWhenReady(AsyncCall::Pointer &cb)
 void Adaptation::Icap::ServiceRep::scheduleNotification()
 {
     debugs(93,7, HERE << "will notify " << theClients.size() << " clients");
-    CallJobHere(93, 5, this, Adaptation::Icap::ServiceRep::noteTimeToNotify);
+    CallJobHere(93, 5, this, Adaptation::Icap::ServiceRepnoteTimeToNotify);
 }
 
 bool Adaptation::Icap::ServiceRep::needNewOptions() const
@@ -306,7 +306,7 @@ void Adaptation::Icap::ServiceRep::announceStatusChange(const char *downPhrase,
 // we are receiving ICAP OPTIONS response headers here or NULL on failures
 void Adaptation::Icap::ServiceRep::noteAdaptationAnswer(HttpMsg *msg)
 {
-    Must(theOptionsFetcher);
+    Must(initiated(theOptionsFetcher));
     clearAdaptation(theOptionsFetcher);
 
     Must(msg);
@@ -326,13 +326,23 @@ void Adaptation::Icap::ServiceRep::noteAdaptationAnswer(HttpMsg *msg)
 
 void Adaptation::Icap::ServiceRep::noteAdaptationQueryAbort(bool)
 {
-    Must(theOptionsFetcher);
+    Must(initiated(theOptionsFetcher));
     clearAdaptation(theOptionsFetcher);
 
     debugs(93,3, HERE << "failed to fetch options " << status());
     handleNewOptions(0);
 }
 
+// we (a) must keep trying to get OPTIONS and (b) are RefCounted so we
+// must keep our job alive (XXX: until nobody needs us)
+void Adaptation::Icap::ServiceRep::callException(const std::exception &e)
+{
+    clearAdaptation(theOptionsFetcher);
+    debugs(93,2, "ICAP probably failed to fetch options (" << e.what() <<
+           ")" << status());
+    handleNewOptions(0);
+}
+
 void Adaptation::Icap::ServiceRep::handleNewOptions(Adaptation::Icap::Options *newOptions)
 {
     // new options may be NULL
@@ -349,9 +359,9 @@ void Adaptation::Icap::ServiceRep::startGettingOptions()
     Must(!theOptionsFetcher);
     debugs(93,6, HERE << "will get new options " << status());
 
-    // XXX: second "this" is "self"; this works but may stop if API changes
-    theOptionsFetcher = initiateAdaptation(new Adaptation::Icap::OptXactLauncher(this, this));
-    Must(theOptionsFetcher);
+    // XXX: "this" here is "self"; works until refcounting API changes
+    theOptionsFetcher = initiateAdaptation(
+                            new Adaptation::Icap::OptXactLauncher(this));
     // TODO: timeout in case Adaptation::Icap::OptXact never calls us back?
     // Such a timeout should probably be a generic AsyncStart feature.
 }
@@ -418,10 +428,10 @@ Adaptation::Icap::ServiceRep::optionsFetchTime() const
 }
 
 Adaptation::Initiate *
-Adaptation::Icap::ServiceRep::makeXactLauncher(Adaptation::Initiator *initiator,
-        HttpMsg *virgin, HttpRequest *cause)
+Adaptation::Icap::ServiceRep::makeXactLauncher(HttpMsg *virgin,
+        HttpRequest *cause)
 {
-    return new Adaptation::Icap::ModXactLauncher(initiator, virgin, cause, this);
+    return new Adaptation::Icap::ModXactLauncher(virgin, cause, this);
 }
 
 // returns a temporary string depicting service status, for debugging
@@ -450,7 +460,7 @@ const char *Adaptation::Icap::ServiceRep::status() const
     if (detached())
         buf.append(",detached", 9);
 
-    if (theOptionsFetcher)
+    if (theOptionsFetcher.set())
         buf.append(",fetch", 6);
 
     if (notifying)
index 45b32b7fe5fc9671cb22b14c80c06c07115d8876..fa67bde23aec2b1c516f1858b1c1a3348b681509 100644 (file)
@@ -95,7 +95,7 @@ public:
     virtual bool probed() const; // see comments above
     virtual bool up() const; // see comments above
 
-    virtual Adaptation::Initiate *makeXactLauncher(Adaptation::Initiator *, HttpMsg *virginHeader, HttpRequest *virginCause);
+    virtual Initiate *makeXactLauncher(HttpMsg *virginHeader, HttpRequest *virginCause);
 
     void callWhenReady(AsyncCall::Pointer &cb);
 
@@ -109,6 +109,7 @@ public:
 
     //AsyncJob virtual methods
     virtual bool doneAll() const { return Adaptation::Initiator::doneAll() && false;}
+    virtual void callException(const std::exception &e);
 
     virtual void detach();
     virtual bool detached() const;
@@ -133,7 +134,7 @@ private:
     Clients theClients; // all clients waiting for a call back
 
     Options *theOptions;
-    Adaptation::Initiate *theOptionsFetcher; // pending ICAP OPTIONS transaction
+    CbcPointer<Adaptation::Initiate> theOptionsFetcher; // pending ICAP OPTIONS transaction
     time_t theLastUpdate; // time the options were last updated
 
     FadingCounter theSessionFailures;
index 4cfce774f166b0b8abd84d53c343e1d1887d896e..9a3c64bf659ccf74fc06a9e149952161987e528a 100644 (file)
@@ -25,9 +25,9 @@ static PconnPool *icapPconnPool = new PconnPool("ICAP Servers");
 
 //CBDATA_NAMESPACED_CLASS_INIT(Adaptation::Icap, Xaction);
 
-Adaptation::Icap::Xaction::Xaction(const char *aTypeName, Adaptation::Initiator *anInitiator, Adaptation::Icap::ServiceRep::Pointer &aService):
+Adaptation::Icap::Xaction::Xaction(const char *aTypeName, Adaptation::Icap::ServiceRep::Pointer &aService):
         AsyncJob(aTypeName),
-        Adaptation::Initiate(aTypeName, anInitiator),
+        Adaptation::Initiate(aTypeName),
         icapRequest(NULL),
         icapReply(NULL),
         attempts(0),
@@ -114,7 +114,8 @@ void Adaptation::Icap::Xaction::openConnection()
         // fake the connect callback
         // TODO: can we sync call Adaptation::Icap::Xaction::noteCommConnected here instead?
         typedef CommCbMemFunT<Adaptation::Icap::Xaction, CommConnectCbParams> Dialer;
-        Dialer dialer(this, &Adaptation::Icap::Xaction::noteCommConnected);
+        CbcPointer<Xaction> self(this);
+        Dialer dialer(self, &Adaptation::Icap::Xaction::noteCommConnected);
         dialer.params.fd = connection->fd;
         dialer.params.flag = COMM_OK;
         // fake other parameters by copying from the existing connection
@@ -126,9 +127,7 @@ void Adaptation::Icap::Xaction::openConnection()
     disableRetries(); // we only retry pconn failures
 
     typedef CommCbMemFunT<Adaptation::Icap::Xaction, CommConnectCbParams> ConnectDialer;
-    connector = asyncCall(93,3, "Adaptation::Icap::Xaction::noteCommConnected",
-                          ConnectDialer(this, &Adaptation::Icap::Xaction::noteCommConnected));
-
+    connector = JobCallback(93,3, ConnectDialer, this, Adaptation::Icap::Xaction::noteCommConnected);
     Comm::ConnOpener *cs = new Comm::ConnOpener(connection, connector, TheConfig.connect_timeout(service().cfg().bypass));
     cs->setHost(s.cfg().host.termedBuf());
     AsyncJob::AsyncStart(cs);
@@ -226,9 +225,7 @@ void Adaptation::Icap::Xaction::scheduleWrite(MemBuf &buf)
 
     // comm module will free the buffer
     typedef CommCbMemFunT<Adaptation::Icap::Xaction, CommIoCbParams> Dialer;
-    writer = asyncCall(93,3, "Adaptation::Icap::Xaction::noteCommWrote",
-                       Dialer(this, &Adaptation::Icap::Xaction::noteCommWrote));
-
+    writer = JobCallback(93, 3, Dialer, this, Adaptation::Icap::Xaction::noteCommWrote);
     comm_write_mbuf(connection->fd, &buf, writer);
     updateTimeout();
 }
@@ -310,11 +307,8 @@ void Adaptation::Icap::Xaction::updateTimeout()
         // XXX: why does Config.Timeout lacks a write timeout?
         // TODO: service bypass status may differ from that of a transaction
         typedef CommCbMemFunT<Adaptation::Icap::Xaction, CommTimeoutCbParams> TimeoutDialer;
-        AsyncCall::Pointer call =  asyncCall(93, 5, "Adaptation::Icap::Xaction::noteCommTimedout",
-                                             TimeoutDialer(this,&Adaptation::Icap::Xaction::noteCommTimedout));
-
-        commSetTimeout(connection->fd,
-                       TheConfig.io_timeout(service().cfg().bypass), call);
+        AsyncCall::Pointer call = JobCallback(93, 5, TimeoutDialer, this, Adaptation::Icap::Xaction::noteCommTimedout);
+        commSetTimeout(connection->fd, TheConfig.io_timeout(service().cfg().bypass), call);
     } else {
         // clear timeout when there is no I/O
         // Do we need a lifetime timeout?
@@ -334,9 +328,7 @@ void Adaptation::Icap::Xaction::scheduleRead()
      * here instead of reading directly into readBuf.buf.
      */
     typedef CommCbMemFunT<Adaptation::Icap::Xaction, CommIoCbParams> Dialer;
-    reader = asyncCall(93,3, "Adaptation::Icap::Xaction::noteCommRead",
-                       Dialer(this, &Adaptation::Icap::Xaction::noteCommRead));
-
+    reader = JobCallback(93, 3, Dialer, this, Adaptation::Icap::Xaction::noteCommRead);
     comm_read(connection->fd, commBuf, readBuf.spaceSize(), reader);
     updateTimeout();
 }
@@ -431,7 +423,7 @@ bool Adaptation::Icap::Xaction::haveConnection() const
 void Adaptation::Icap::Xaction::noteInitiatorAborted()
 {
 
-    if (theInitiator) {
+    if (theInitiator.set()) {
         clearInitiator();
         mustStop("initiator aborted");
     }
@@ -464,8 +456,7 @@ void Adaptation::Icap::Xaction::swanSong()
     if (commBuf)
         memFreeBuf(commBufSize, commBuf);
 
-    if (theInitiator)
-        tellQueryAborted();
+    tellQueryAborted();
 
     maybeLog();
 
@@ -474,12 +465,15 @@ void Adaptation::Icap::Xaction::swanSong()
 
 void Adaptation::Icap::Xaction::tellQueryAborted()
 {
-    Adaptation::Icap::Launcher *l = dynamic_cast<Adaptation::Icap::Launcher*>(theInitiator.ptr());
-    Adaptation::Icap::XactAbortInfo abortInfo(icapRequest, icapReply, retriable(), repeatable());
-    CallJob(91, 5, __FILE__, __LINE__,
-            "Adaptation::Icap::Launcher::noteXactAbort",
-            XactAbortCall(l, &Adaptation::Icap::Launcher::noteXactAbort, abortInfo) );
-    clearInitiator();
+    if (theInitiator.set()) {
+        Adaptation::Icap::XactAbortInfo abortInfo(icapRequest, icapReply,
+                retriable(), repeatable());
+        Launcher *launcher = dynamic_cast<Launcher*>(theInitiator.get());
+        // launcher may be nil if initiator is invalid
+        CallJobHere1(91,5, CbcPointer<Launcher>(launcher),
+                     Launcher, noteXactAbort, abortInfo);
+        clearInitiator();
+    }
 }
 
 
index 988660b570310c72a813168707dee65baed636b2..adb558c22add988554339fb4fb6801659f2aed7a 100644 (file)
@@ -63,7 +63,7 @@ class Xaction: public Adaptation::Initiate
 {
 
 public:
-    Xaction(const char *aTypeName, Adaptation::Initiator *anInitiator, ServiceRep::Pointer &aService);
+    Xaction(const char *aTypeName, ServiceRep::Pointer &aService);
     virtual ~Xaction();
 
     void disableRetries();
@@ -126,10 +126,12 @@ protected:
     // useful for debugging
     virtual bool fillVirginHttpHeader(MemBuf&) const;
 
+public:
     // custom exception handling and end-of-call checks
     virtual void callException(const std::exception  &e);
     virtual void callEnd();
 
+protected:
     // logging
     void setOutcome(const XactOutcome &xo);
     virtual void finalizeLogInfo();
index f87a4929903f4906db351fb864b852b129e2fade..f6faae982efaeb34628db8f091eb3fb130308b4b 100644 (file)
@@ -81,11 +81,7 @@ TESTS += testHeaders
 ## Special Universal .h dependency test script
 ## aborts if error encountered
 testHeaders: $(top_srcdir)/src/auth/*.h $(top_srcdir)/src/auth/basic/*.h $(top_srcdir)/src/auth/digest/*.h $(top_srcdir)/src/auth/ntlm/*.h $(top_srcdir)/src/auth/negotiate/*.h
-       $(SHELL) $(top_srcdir)/test-suite/testheaders.sh "$(CXXCOMPILE)" "$(top_srcdir)/src/auth/" || exit 1
-       $(SHELL) $(top_srcdir)/test-suite/testheaders.sh "$(CXXCOMPILE)" "$(top_srcdir)/src/auth/basic" || exit 1
-       $(SHELL) $(top_srcdir)/test-suite/testheaders.sh "$(CXXCOMPILE)" "$(top_srcdir)/src/auth/digest" || exit 1
-       $(SHELL) $(top_srcdir)/test-suite/testheaders.sh "$(CXXCOMPILE)" "$(top_srcdir)/src/auth/ntlm" || exit 1
-       $(SHELL) $(top_srcdir)/test-suite/testheaders.sh "$(CXXCOMPILE)" "$(top_srcdir)/src/auth/negotiate" || exit 1
+       $(SHELL) $(top_srcdir)/test-suite/testheaders.sh "$(CXXCOMPILE)" $^ || exit 1
 
 CLEANFILES += testHeaders
 .PHONY: testHeaders
index 25f3b9099e66491bf0b51e98ecf39d837139c9ce..6b50ff69733d2235fb150c917dc0072b0997ea42 100644 (file)
@@ -5,6 +5,7 @@
 #include "squid.h"
 #include "base/AsyncCall.h"
 #include "base/AsyncJob.h"
+#include "base/AsyncJobCalls.h"
 #include "base/TextException.h"
 #include "cbdata.h"
 #include "MemBuf.h"
 
 unsigned int AsyncJob::TheLastId = 0;
 
-AsyncJob *AsyncJob::AsyncStart(AsyncJob *job)
+AsyncJob::Pointer AsyncJob::Start(AsyncJob *j)
 {
-    assert(job);
-    CallJobHere(93, 5, job, AsyncJob::noteStart);
+    AsyncJob::Pointer job(j);
+    CallJobHere(93, 5, job, AsyncJob, start);
     return job;
 }
 
@@ -31,11 +32,6 @@ AsyncJob::~AsyncJob()
            " [async" << id << ']');
 }
 
-void AsyncJob::noteStart()
-{
-    start();
-}
-
 void AsyncJob::start()
 {
 }
@@ -54,8 +50,9 @@ void AsyncJob::deleteThis(const char *aReason)
 
     // there is no call wrapper waiting for our return, so we fake it
     debugs(93, 5, typeName << " will delete this, reason: " << stopReason);
+    CbcPointer<AsyncJob> self(this);
     AsyncCall::Pointer fakeCall = asyncCall(93,4, "FAKE-deleteThis",
-                                            MemFun(this, &AsyncJob::deleteThis, aReason));
+                                            JobMemFun(self, &AsyncJob::deleteThis, aReason));
     inCall = fakeCall;
     callEnd();
 //    delete fakeCall;
@@ -166,60 +163,3 @@ const char *AsyncJob::status() const
 }
 
 
-/* JobDialer */
-
-JobDialer::JobDialer(AsyncJob *aJob): job(NULL), lock(NULL)
-{
-    if (aJob) {
-        lock = cbdataReference(aJob->toCbdata());
-        job = aJob;
-    }
-}
-
-JobDialer::JobDialer(const JobDialer &d): CallDialer(d),
-        job(NULL), lock(NULL)
-{
-    if (d.lock && cbdataReferenceValid(d.lock)) {
-        lock = cbdataReference(d.lock);
-        Must(d.job);
-        job = d.job;
-    }
-}
-
-JobDialer::~JobDialer()
-{
-    cbdataReferenceDone(lock); // lock may be NULL
-}
-
-
-bool
-JobDialer::canDial(AsyncCall &call)
-{
-    if (!lock)
-        return call.cancel("job was gone before the call");
-
-    if (!cbdataReferenceValid(lock))
-        return call.cancel("job gone after the call");
-
-    Must(job);
-    return job->canBeCalled(call);
-}
-
-void
-JobDialer::dial(AsyncCall &call)
-{
-    Must(lock && cbdataReferenceValid(lock)); // canDial() checks for this
-    Must(job);
-
-    job->callStart(call);
-
-    try {
-        doDial();
-    } catch (const std::exception &e) {
-        debugs(call.debugSection, 3,
-               HERE << call.name << " threw exception: " << e.what());
-        job->callException(e);
-    }
-
-    job->callEnd(); // may delete job
-}
index a58dc6dca6452662b60a06c51baaa75ed677b078..df0bf3ca5414079e78496250c613e2cf44c6c052 100644 (file)
@@ -7,6 +7,9 @@
 
 #include "base/AsyncCall.h"
 
+template <class Cbc>
+class CbcPointer;
+
 /**
  \defgroup AsyncJobAPI Async-Jobs API
  \par
 // See AsyncJobs.dox for details.
 
 /// \ingroup AsyncJobAPI
+/// Base class for all asynchronous jobs
 class AsyncJob
 {
-
 public:
-    /// starts the job (i.e., makes the job asynchronous)
-    static AsyncJob *AsyncStart(AsyncJob *job);
+    typedef CbcPointer<AsyncJob> Pointer;
 
+public:
     AsyncJob(const char *aTypeName);
     virtual ~AsyncJob();
 
     virtual void *toCbdata() = 0;
-    void noteStart(); // calls virtual start
+
+    /// starts a freshly created job (i.e., makes the job asynchronous)
+    static Pointer Start(AsyncJob *job);
 
 protected:
     // XXX: temporary method to replace "delete this" in jobs-in-transition.
@@ -64,56 +69,4 @@ private:
     static unsigned int TheLastId; ///< makes job IDs unique until it wraps
 };
 
-
-/**
- \ingroup AsyncJobAPI
- * This is a base class for all job call dialers. It does all the job
- * dialing logic (debugging, handling exceptions, etc.) except for calling
- * the job method. The latter is not possible without templates and we
- * want to keep this class simple and template-free. Thus, we add a dial()
- * virtual method that the JobCallT template below will implement for us,
- * calling the job.
- */
-class JobDialer: public CallDialer
-{
-public:
-    JobDialer(AsyncJob *aJob);
-    JobDialer(const JobDialer &d);
-    virtual ~JobDialer();
-
-    virtual bool canDial(AsyncCall &call);
-    void dial(AsyncCall &call);
-
-    AsyncJob *job;
-    void *lock; // job's cbdata
-
-protected:
-    virtual void doDial() = 0; // actually calls the job method
-
-private:
-    // not implemented and should not be needed
-    JobDialer &operator =(const JobDialer &);
-};
-
-#include "base/AsyncJobCalls.h"
-
-template <class Dialer>
-bool
-CallJob(int debugSection, int debugLevel, const char *fileName, int fileLine,
-        const char *callName, const Dialer &dialer)
-{
-    AsyncCall::Pointer call = asyncCall(debugSection, debugLevel, callName, dialer);
-    return ScheduleCall(fileName, fileLine, call);
-}
-
-
-#define CallJobHere(debugSection, debugLevel, job, method) \
-    CallJob((debugSection), (debugLevel), __FILE__, __LINE__, #method, \
-        MemFun((job), &method))
-
-#define CallJobHere1(debugSection, debugLevel, job, method, arg1) \
-    CallJob((debugSection), (debugLevel), __FILE__, __LINE__, #method, \
-        MemFun((job), &method, (arg1)))
-
-
 #endif /* SQUID_ASYNC_JOB_H */
index 0657d3672015361f13cbc67e8a31a20635d41482..23434a1a1a0a092c37fa3062f5433d3a19a9d83f 100644 (file)
@@ -7,6 +7,66 @@
 #define SQUID_ASYNCJOBCALLS_H
 
 #include "base/AsyncJob.h"
+#include "base/CbcPointer.h"
+
+/**
+ \ingroup AsyncJobAPI
+ * This is a base class for all job call dialers. It does all the job
+ * dialing logic (debugging, handling exceptions, etc.) except for calling
+ * the job method. The latter requires knowing the number and type of method
+ * parameters. Thus, we add a dial() virtual method that the MemFunT templates
+ * below implement for us, calling the job's method with the right params.
+ */
+template <class Job>
+class JobDialer: public CallDialer
+{
+public:
+    typedef Job DestClass;
+    typedef CbcPointer<Job> JobPointer;
+
+    JobDialer(const JobPointer &aJob);
+    JobDialer(const JobDialer &d);
+
+    virtual bool canDial(AsyncCall &call);
+    void dial(AsyncCall &call);
+
+    JobPointer job;
+
+protected:
+    virtual void doDial() = 0; // actually calls the job method
+
+private:
+    // not implemented and should not be needed
+    JobDialer &operator =(const JobDialer &);
+};
+
+/// schedule an async job call using a dialer; use CallJobHere macros instead
+template <class Dialer>
+bool
+CallJob(int debugSection, int debugLevel, const char *fileName, int fileLine,
+        const char *callName, const Dialer &dialer)
+{
+    AsyncCall::Pointer call = asyncCall(debugSection, debugLevel, callName, dialer);
+    return ScheduleCall(fileName, fileLine, call);
+}
+
+
+#define CallJobHere(debugSection, debugLevel, job, Class, method) \
+    CallJob((debugSection), (debugLevel), __FILE__, __LINE__, \
+        (#Class "::" #method), \
+        JobMemFun<Class>((job), &Class::method))
+
+#define CallJobHere1(debugSection, debugLevel, job, Class, method, arg1) \
+    CallJob((debugSection), (debugLevel), __FILE__, __LINE__, \
+        (#Class "::" #method), \
+        JobMemFun((job), &Class::method, (arg1)))
+
+
+/// Convenience macro to create a Dialer-based job callback
+#define JobCallback(dbgSection, dbgLevel, Dialer, job, method) \
+    asyncCall((dbgSection), (dbgLevel), #method, \
+        Dialer(CbcPointer<Dialer::DestClass>(job), &method))
+
 
 /*
  * *MemFunT are member function (i.e., class method) wrappers. They store
 
 // Arity names are from http://en.wikipedia.org/wiki/Arity
 
-template <class C>
-class NullaryMemFunT: public JobDialer
+template <class Job>
+class NullaryMemFunT: public JobDialer<Job>
 {
 public:
-    typedef void (C::*Method)();
-    explicit NullaryMemFunT(C *anObject, Method aMethod):
-            JobDialer(anObject), object(anObject), method(aMethod) {}
+    typedef void (Job::*Method)();
+    explicit NullaryMemFunT(const CbcPointer<Job> &aJob, Method aMethod):
+            JobDialer<Job>(aJob), method(aMethod) {}
 
     virtual void print(std::ostream &os) const {  os << "()"; }
 
 public:
-    C *object;
     Method method;
 
 protected:
-    virtual void doDial() { (object->*method)(); }
+    virtual void doDial() { ((&(*this->job))->*method)(); }
 };
 
-template <class C, class Argument1>
-class UnaryMemFunT: public JobDialer
+template <class Job, class Argument1>
+class UnaryMemFunT: public JobDialer<Job>
 {
 public:
-    typedef void (C::*Method)(Argument1);
-    explicit UnaryMemFunT(C *anObject, Method aMethod, const Argument1 &anArg1):
-            JobDialer(anObject),
-            object(anObject), method(aMethod), arg1(anArg1) {}
+    typedef void (Job::*Method)(Argument1);
+    explicit UnaryMemFunT(const CbcPointer<Job> &aJob, Method aMethod,
+                          const Argument1 &anArg1): JobDialer<Job>(aJob),
+            method(aMethod), arg1(anArg1) {}
 
     virtual void print(std::ostream &os) const {  os << '(' << arg1 << ')'; }
 
 public:
-    C *object;
     Method method;
     Argument1 arg1;
 
 protected:
-    virtual void doDial() { (object->*method)(arg1); }
+    virtual void doDial() { ((&(*this->job))->*method)(arg1); }
 };
 
 // ... add more as needed
@@ -71,17 +129,57 @@ protected:
 
 template <class C>
 NullaryMemFunT<C>
-MemFun(C *object, typename NullaryMemFunT<C>::Method method)
+JobMemFun(const CbcPointer<C> &job, typename NullaryMemFunT<C>::Method method)
 {
-    return NullaryMemFunT<C>(object, method);
+    return NullaryMemFunT<C>(job, method);
 }
 
 template <class C, class Argument1>
 UnaryMemFunT<C, Argument1>
-MemFun(C *object, typename UnaryMemFunT<C, Argument1>::Method method,
-       Argument1 arg1)
+JobMemFun(const CbcPointer<C> &job, typename UnaryMemFunT<C, Argument1>::Method method,
+          Argument1 arg1)
+{
+    return UnaryMemFunT<C, Argument1>(job, method, arg1);
+}
+
+
+// inlined methods
+
+template<class Job>
+JobDialer<Job>::JobDialer(const JobPointer &aJob): job(aJob)
+{
+}
+
+template<class Job>
+JobDialer<Job>::JobDialer(const JobDialer<Job> &d): CallDialer(d), job(d.job)
 {
-    return UnaryMemFunT<C, Argument1>(object, method, arg1);
+}
+
+template<class Job>
+bool
+JobDialer<Job>::canDial(AsyncCall &call)
+{
+    if (!job)
+        return call.cancel("job gone");
+
+    return job->canBeCalled(call);
+}
+
+template<class Job>
+void
+JobDialer<Job>::dial(AsyncCall &call)
+{
+    job->callStart(call);
+
+    try {
+        doDial();
+    } catch (const std::exception &e) {
+        debugs(call.debugSection, 3,
+               HERE << call.name << " threw exception: " << e.what());
+        job->callException(e);
+    }
+
+    job->callEnd(); // may delete job
 }
 
 #endif /* SQUID_ASYNCJOBCALLS_H */
index 296ed81f4d8048fef6dce10353655bc7d1750b95..c8f72c2d7ba79d0ebad2fc23579c6e82f0fd8ef4 100644 (file)
@@ -6,15 +6,15 @@
 
 - \b Job: an AsyncJob object.
 - \b Creator: the code creating the job. Usually the Initiator.
-- \b Start: the act of calling AsyncStart with a job pointer.
+- \b Start: the act of calling AsyncJob::Start with a job pointer.
 - \b Initiator: the code starting the job. Usually the Creator.
 
 \section Life Typical life cycle
 
 -# Creator creates and initializes a job.
--# Initiator starts the job. If Initiator expects
-to communicate with the started job, then it stores the job pointer
-returned by AsyncStart.
+-# If Initiator expects to communicate with the job after start,
+   then it stores the job pointer
+-# Initiator starts the job by calling AsyncJob::Start.
 -# The job's start() method is called. The method usually schedules
 some I/O or registers to receive some other callbacks.
 -# The job runs and does what it is supposed to do. This usually involves
@@ -27,7 +27,7 @@ then notifying Initiator of the final result.
 
 If you want to do something before starting the job, do it in the constructor
 or some custom method that the job creator will call _before_ calling
-AsyncStart():
+AsyncJob::Start():
 
     std::auto_ptr<MyJob> job(new MyJob(...)); // sync/blocking
     job->prepare(...); // sync/blocking
@@ -36,15 +36,16 @@ AsyncStart():
 
 If you do not need complex preparations, it is better to do this instead:
 
-    AsyncStart(new MyJob(...));
+    AsyncJob::Start(new MyJob(...));
 
 Keep in mind that you have no async debugging, cleanup, and protections until
-you call AsyncStart with a job pointer.
+you call AsyncJob::Start with a job pointer.
 
 
 \section Rules Basic rules
 
-- To start a job, use AsyncStart. Do not start the same job more than once.
+- To start a job, use AsyncJob::Start.
+  Do not start the same job more than once.
 
 - Never call start() directly. Treat this method as main() in C/C++.
 
diff --git a/src/base/CbcPointer.h b/src/base/CbcPointer.h
new file mode 100644 (file)
index 0000000..622d963
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * $Id$
+ */
+
+#ifndef SQUID_CBC_POINTER_H
+#define SQUID_CBC_POINTER_H
+
+#include "base/TextException.h"
+#include "cbdata.h"
+
+/**
+ \ingroup CBDATAAPI
+ *
+ * Safely points to a cbdata-protected class (cbc), such as an AsyncJob.
+ * When a cbc we communicate with disappears without
+ * notice or a notice has not reached us yet, this class prevents
+ * dereferencing the pointer to the gone cbc object.
+ */
+template<class Cbc>
+class CbcPointer
+{
+public:
+    CbcPointer(); // a nil pointer
+    CbcPointer(Cbc *aCbc);
+    CbcPointer(const CbcPointer &p);
+    ~CbcPointer();
+
+    Cbc *raw() const; ///< a temporary raw Cbc pointer; may be invalid
+    Cbc *get() const; ///< a temporary valid raw Cbc pointer or NULL
+    Cbc &operator *() const; ///< a valid Cbc reference or exception
+    Cbc *operator ->() const; ///< a valid Cbc pointer or exception
+
+    // no bool operator because set() != valid()
+    bool set() const { return cbc != NULL; } ///< was set but may be invalid
+    Cbc *valid() const { return get(); } ///< was set and is valid
+    bool operator !() const { return !valid(); } ///< invalid or was not set
+    bool operator ==(const CbcPointer<Cbc> &o) const { return lock == o.lock; }
+
+    CbcPointer &operator =(const CbcPointer &p);
+
+    /// support converting a child cbc pointer into a parent cbc pointer
+    template <typename Other>
+    CbcPointer(const CbcPointer<Other> &o): cbc(o.raw()), lock(NULL) {
+        if (o.valid())
+            lock = cbdataReference(o->toCbdata());
+    }
+
+    /// support assigning a child cbc pointer to a parent cbc pointer
+    template <typename Other>
+    CbcPointer &operator =(const CbcPointer<Other> &o) {
+        clear();
+        cbc = o.raw(); // so that set() is accurate
+        if (o.valid())
+            lock = cbdataReference(o->toCbdata());
+        return *this;
+    }
+
+    void clear(); ///< make pointer not set; does not invalidate cbdata
+
+    std::ostream &print(std::ostream &os) const;
+
+private:
+    Cbc *cbc; // a possibly invalid pointer to a cbdata class
+    void *lock; // a valid pointer to cbc's cbdata or nil
+};
+
+template <class Cbc>
+inline
+std::ostream &operator <<(std::ostream &os, const CbcPointer<Cbc> &p)
+{
+    return p.print(os);
+}
+
+// inlined methods
+
+template<class Cbc>
+CbcPointer<Cbc>::CbcPointer(): cbc(NULL), lock(NULL)
+{
+}
+
+template<class Cbc>
+CbcPointer<Cbc>::CbcPointer(Cbc *aCbc): cbc(aCbc), lock(NULL)
+{
+    if (cbc)
+        lock = cbdataReference(cbc->toCbdata());
+}
+
+template<class Cbc>
+CbcPointer<Cbc>::CbcPointer(const CbcPointer &d): cbc(d.cbc), lock(NULL)
+{
+    if (d.lock && cbdataReferenceValid(d.lock))
+        lock = cbdataReference(d.lock);
+}
+
+template<class Cbc>
+CbcPointer<Cbc>::~CbcPointer()
+{
+    clear();
+}
+
+template<class Cbc>
+CbcPointer<Cbc> &CbcPointer<Cbc>::operator =(const CbcPointer &d)
+{
+    clear();
+    cbc = d.cbc;
+    if (d.lock && cbdataReferenceValid(d.lock))
+        lock = cbdataReference(d.lock);
+    return *this;
+}
+
+template<class Cbc>
+void
+CbcPointer<Cbc>::clear()
+{
+    cbdataReferenceDone(lock); // lock may be nil before and will be nil after
+    cbc = NULL;
+}
+
+template<class Cbc>
+Cbc *
+CbcPointer<Cbc>::raw() const
+{
+    return cbc;
+}
+
+template<class Cbc>
+Cbc *
+CbcPointer<Cbc>::get() const
+{
+    return (lock && cbdataReferenceValid(lock)) ? cbc : NULL;
+}
+
+template<class Cbc>
+Cbc &
+CbcPointer<Cbc>::operator *() const
+{
+    Cbc *c = get();
+    Must(c);
+    return *c;
+}
+
+template<class Cbc>
+Cbc *
+CbcPointer<Cbc>::operator ->() const
+{
+    Cbc *c = get();
+    Must(c);
+    return c;
+}
+
+template <class Cbc>
+std::ostream &CbcPointer<Cbc>::print(std::ostream &os) const
+{
+    return os << cbc << '/' << lock;
+}
+
+
+#endif /* SQUID_CBC_POINTER_H */
index 0e1d4a96dad7fbdfa45add1584493c6ac7da82a6..7009fb37bee9cefc37e2fc410d5949dd5de94967 100644 (file)
@@ -12,5 +12,6 @@ libbase_la_SOURCES = \
        AsyncJobCalls.h \
        AsyncCallQueue.cc \
        AsyncCallQueue.h \
+       CbcPointer.h \
        TextException.cc \
        TextException.h
index 217fea8b8b1f1db3cca2646175ec982c298932d4..6c47a14274d42002e049301f7cd089f4a57ea84c 100644 (file)
@@ -1905,30 +1905,37 @@ parse_peer(peer ** head)
         } else if (!strcasecmp(token, "weighted-round-robin")) {
             p->options.weighted_roundrobin = 1;
 #if USE_HTCP
-
         } else if (!strcasecmp(token, "htcp")) {
             p->options.htcp = 1;
-        } else if (!strcasecmp(token, "htcp-oldsquid")) {
-            p->options.htcp = 1;
-            p->options.htcp_oldsquid = 1;
-        } else if (!strcasecmp(token, "htcp-no-clr")) {
-            if (p->options.htcp_only_clr)
-                fatalf("parse_peer: can't set htcp-no-clr and htcp-only-clr simultaneously");
-            p->options.htcp = 1;
-            p->options.htcp_no_clr = 1;
-        } else if (!strcasecmp(token, "htcp-no-purge-clr")) {
-            p->options.htcp = 1;
-            p->options.htcp_no_purge_clr = 1;
-        } else if (!strcasecmp(token, "htcp-only-clr")) {
-            if (p->options.htcp_no_clr)
-                fatalf("parse_peer: can't set htcp-no-clr and htcp-only-clr simultaneously");
+        } else if (!strncasecmp(token, "htcp=", 5) || !strncasecmp(token, "htcp-", 5)) {
+            /* Note: The htcp- form is deprecated, replaced by htcp= */
             p->options.htcp = 1;
-            p->options.htcp_only_clr = 1;
-        } else if (!strcasecmp(token, "htcp-forward-clr")) {
-            p->options.htcp = 1;
-            p->options.htcp_forward_clr = 1;
+            char *tmp = xstrdup(token+5);
+            char *mode, *nextmode;
+            for (mode = nextmode = tmp; mode; mode = nextmode) {
+                nextmode = strchr(mode, ',');
+                if (nextmode)
+                    *nextmode++ = '\0';
+                if (!strcasecmp(mode, "no-clr")) {
+                    if (p->options.htcp_only_clr)
+                        fatalf("parse_peer: can't set htcp-no-clr and htcp-only-clr simultaneously");
+                    p->options.htcp_no_clr = 1;
+                } else if (!strcasecmp(mode, "no-purge-clr")) {
+                    p->options.htcp_no_purge_clr = 1;
+                } else if (!strcasecmp(mode, "only-clr")) {
+                    if (p->options.htcp_no_clr)
+                        fatalf("parse_peer: can't set htcp no-clr and only-clr simultaneously");
+                    p->options.htcp_only_clr = 1;
+                } else if (!strcasecmp(mode, "forward-clr")) {
+                    p->options.htcp_forward_clr = 1;
+                } else if (!strcasecmp(mode, "oldsquid")) {
+                    p->options.htcp_oldsquid = 1;
+                } else {
+                    fatalf("invalid HTCP mode '%s'", mode);
+                }
+            }
+            safe_free(tmp);
 #endif
-
         } else if (!strcasecmp(token, "no-netdb-exchange")) {
             p->options.no_netdb_exchange = 1;
 
@@ -2475,6 +2482,16 @@ parse_refreshpattern(refresh_t ** head)
 
     i = GetInteger();          /* token: min */
 
+    /* catch negative and insanely huge values close to 32-bit wrap */
+    if (i < 0) {
+        debugs(3, DBG_IMPORTANT, "WARNING: refresh_pattern minimum age negative. Cropped back to zero.");
+        i = 0;
+    }
+    if (i > 60*24*365) {
+        debugs(3, DBG_IMPORTANT, "WARNING: refresh_pattern minimum age too high. Cropped back to 1 year.");
+        i = 60*24*365;
+    }
+
     min = (time_t) (i * 60);   /* convert minutes to seconds */
 
     i = GetInteger();          /* token: pct */
@@ -2483,6 +2500,16 @@ parse_refreshpattern(refresh_t ** head)
 
     i = GetInteger();          /* token: max */
 
+    /* catch negative and insanely huge values close to 32-bit wrap */
+    if (i < 0) {
+        debugs(3, DBG_IMPORTANT, "WARNING: refresh_pattern maximum age negative. Cropped back to zero.");
+        i = 0;
+    }
+    if (i > 60*24*365) {
+        debugs(3, DBG_IMPORTANT, "WARNING: refresh_pattern maximum age too high. Cropped back to 1 year.");
+        i = 60*24*365;
+    }
+
     max = (time_t) (i * 60);   /* convert minutes to seconds */
 
     /* Options */
@@ -3277,7 +3304,11 @@ parse_http_port_option(http_port_list * s, char *token)
             t = strchr(t, ',');
         }
 #if USE_SSL
-    } else if (strcmp(token, "sslBump") == 0) {
+    } else if (strcasecmp(token, "sslBump") == 0) {
+        debugs(3, DBG_CRITICAL, "WARNING: '" << token << "' is deprecated " <<
+               "in http_port. Use 'ssl-bump' instead.");
+        s->sslBump = 1; // accelerated when bumped, otherwise not
+    } else if (strcmp(token, "ssl-bump") == 0) {
         s->sslBump = 1; // accelerated when bumped, otherwise not
     } else if (strncmp(token, "cert=", 5) == 0) {
         safe_free(s->cert);
index d8d03a14e567fdb6edcd0a87e2fa67d2ba366e3a..1555728661bf2052d9561c29deda55cef7a325dc 100644 (file)
@@ -44,6 +44,9 @@
 #include "wordlist.h"
 #include "Debug.h"
 
+// for rotate_logs()
+#include "protos.h"
+
 /// \ingroup CacheManagerInternal
 #define MGR_PASSWD_SZ 128
 
@@ -57,6 +60,7 @@ CacheManager::CacheManager()
     registerAction(new OfflineToggleAction);
     registerAction(new ShutdownAction);
     registerAction(new ReconfigureAction);
+    registerAction(new RotateAction);
     registerAction(new MenuAction(this));
 }
 
@@ -373,6 +377,21 @@ CacheManager::ReconfigureAction::run(StoreEntry * sentry)
 /// \ingroup CacheManagerInternal
 CacheManager::ReconfigureAction::ReconfigureAction() : CacheManagerAction("reconfigure","Reconfigure Squid", 1, 1) { }
 
+/// \ingroup CacheManagerInternal
+void
+CacheManager::RotateAction::run(StoreEntry * sentry)
+{
+    debugs(16, DBG_IMPORTANT, "Rotate Logs by Cache Manager command.");
+    storeAppendPrintf(sentry, "Rotating Squid Process Logs ....");
+#ifdef _SQUID_LINUX_THREADS_
+    rotate_logs(SIGQUIT);
+#else
+    rotate_logs(SIGUSR1);
+#endif
+}
+/// \ingroup CacheManagerInternal
+CacheManager::RotateAction::RotateAction() : CacheManagerAction("rotate","Rotate Squid Logs", 1, 1) { }
+
 /// \ingroup CacheManagerInternal
 void
 CacheManager::OfflineToggleAction::run(StoreEntry * sentry)
index 63613358949044aaa3c42d1d567a4d5a6d77458b..d5f8283f818700d7eb69880a9bcbc02ae584b363 100644 (file)
@@ -1053,7 +1053,7 @@ DOC_START
 
        NOTE: The default if no htcp_access lines are present is to
        deny all traffic. This default may cause problems with peers
-       using the htcp or htcp-oldsquid options.
+       using the htcp option.
 
        This clause only supports fast acl types.
        See http://wiki.squid-cache.org/SquidFaq/SquidAcl for details.
@@ -1221,7 +1221,7 @@ DOC_START
           accel        Accelerator mode. Also needs at least one of
                        vhost / vport / defaultsite.
 
-          sslbump      Intercept each CONNECT request matching ssl_bump ACL,
+          ssl-bump     Intercept each CONNECT request matching ssl_bump ACL,
                        establish secure connection with the client and with
                        the server, decrypt HTTP messages as they pass through
                        Squid, and treat them as unencrypted HTTP messages,
@@ -1904,22 +1904,23 @@ DOC_START
        
        htcp            Send HTCP, instead of ICP, queries to the neighbor.
                        You probably also want to set the "icp-port" to 4827
-                       instead of 3130.
+                       instead of 3130. This directive accepts a comma separated
+                       list of options described below.
        
-       htcp-oldsquid   Send HTCP to old Squid versions.
+       htcp=oldsquid   Send HTCP to old Squid versions (2.5 or earlier).
        
-       htcp-no-clr     Send HTCP to the neighbor but without
+       htcp=no-clr     Send HTCP to the neighbor but without
                        sending any CLR requests.  This cannot be used with
-                       htcp-only-clr.
+                       only-clr.
        
-       htcp-only-clr   Send HTCP to the neighbor but ONLY CLR requests.
-                       This cannot be used with htcp-no-clr.
+       htcp=only-clr   Send HTCP to the neighbor but ONLY CLR requests.
+                       This cannot be used with no-clr.
        
-       htcp-no-purge-clr
+       htcp=no-purge-clr
                        Send HTCP to the neighbor including CLRs but only when
                        they do not result from PURGE requests.
        
-       htcp-forward-clr
+       htcp=forward-clr
                        Forward any HTCP CLR requests this proxy receives to the peer.
        
        
@@ -4045,7 +4046,6 @@ DOC_START
                request_header_access Retry-After allow all
                request_header_access Title allow all
                request_header_access Connection allow all
-               request_header_access Proxy-Connection allow all
                request_header_access All deny all
 
        although many of those are HTTP reply headers, and so should be
@@ -4121,7 +4121,6 @@ DOC_START
                reply_header_access Retry-After allow all
                reply_header_access Title allow all
                reply_header_access Connection allow all
-               reply_header_access Proxy-Connection allow all
                reply_header_access All deny all
 
        although the HTTP request headers won't be usefully controlled
index 22919f60f04978167ec8ad280f20fee230846d07..026b5cbb766329b5e40255f84e86bf9c07f42580 100644 (file)
@@ -244,8 +244,7 @@ ConnStateData::readSomeData()
     makeSpaceAvailable();
 
     typedef CommCbMemFunT<ConnStateData, CommIoCbParams> Dialer;
-    reader = asyncCall(33, 5, "ConnStateData::clientReadRequest",
-                       Dialer(this, &ConnStateData::clientReadRequest));
+    reader = JobCallback(33, 5, Dialer, this, ConnStateData::clientReadRequest);
     comm_read(clientConn->fd, in.addressToReadInto(), getAvailableBufferLength(), reader);
 }
 
@@ -736,18 +735,14 @@ static void
 clientSetKeepaliveFlag(ClientHttpRequest * http)
 {
     HttpRequest *request = http->request;
-    const HttpHeader *req_hdr = &request->header;
 
     debugs(33, 3, "clientSetKeepaliveFlag: http_ver = " <<
            request->http_ver.major << "." << request->http_ver.minor);
     debugs(33, 3, "clientSetKeepaliveFlag: method = " <<
            RequestMethodStr(request->method));
 
-    /* We are HTTP/1.1 facing clients now*/
-    HttpVersion http_ver(1,1);
-
-    if (httpMsgIsPersistent(http_ver, req_hdr))
-        request->flags.proxy_keepalive = 1;
+    // TODO: move to HttpRequest::hdrCacheInit, just like HttpReply.
+    request->flags.proxy_keepalive = request->persistent() ? 1 : 0;
 }
 
 static int
@@ -897,7 +892,7 @@ ClientSocketContext::sendBody(HttpReply * rep, StoreIOBuffer bodyData)
 {
     assert(rep == NULL);
 
-    if (!multipartRangeRequest()) {
+    if (!multipartRangeRequest() && !http->request->flags.chunked_reply) {
         size_t length = lengthToSend(bodyData.range());
         noteSentBodyBytes (length);
         AsyncCall::Pointer call = commCbCall(33, 5, "clientWriteBodyComplete",
@@ -908,7 +903,10 @@ ClientSocketContext::sendBody(HttpReply * rep, StoreIOBuffer bodyData)
 
     MemBuf mb;
     mb.init();
-    packRange(bodyData, &mb);
+    if (multipartRangeRequest())
+        packRange(bodyData, &mb);
+    else
+        packChunk(bodyData, mb);
 
     if (mb.contentSize()) {
         /* write */
@@ -919,6 +917,22 @@ ClientSocketContext::sendBody(HttpReply * rep, StoreIOBuffer bodyData)
         writeComplete(fd(), NULL, 0, COMM_OK);
 }
 
+/**
+ * Packs bodyData into mb using chunked encoding. Packs the last-chunk
+ * if bodyData is empty.
+ */
+void
+ClientSocketContext::packChunk(const StoreIOBuffer &bodyData, MemBuf &mb)
+{
+    const uint64_t length =
+        static_cast<uint64_t>(lengthToSend(bodyData.range()));
+    noteSentBodyBytes(length);
+
+    mb.Printf("%"PRIX64"\r\n", length);
+    mb.append(bodyData.data, length);
+    mb.Printf("\r\n");
+}
+
 /** put terminating boundary for multiparts */
 static void
 clientPackTermBound(String boundary, MemBuf * mb)
@@ -1287,13 +1301,15 @@ ClientSocketContext::sendStartOfMessage(HttpReply * rep, StoreIOBuffer bodyData)
 #endif
 
     if (bodyData.data && bodyData.length) {
-        if (!multipartRangeRequest()) {
+        if (multipartRangeRequest())
+            packRange(bodyData, mb);
+        else if (http->request->flags.chunked_reply) {
+            packChunk(bodyData, *mb);
+        } else {
             size_t length = lengthToSend(bodyData.range());
             noteSentBodyBytes (length);
 
             mb->append(bodyData.data, length);
-        } else {
-            packRange(bodyData, mb);
         }
     }
 
@@ -1342,7 +1358,11 @@ clientSocketRecipient(clientStreamNode * node, ClientHttpRequest * http,
         return;
     }
 
-    if (responseFinishedOrFailed(rep, receivedData)) {
+    // After sending Transfer-Encoding: chunked (at least), always send
+    // the last-chunk if there was no error, ignoring responseFinishedOrFailed.
+    const bool mustSendLastChunk = http->request->flags.chunked_reply &&
+                                   !http->request->flags.stream_error && !context->startOfOutput();
+    if (responseFinishedOrFailed(rep, receivedData) && !mustSendLastChunk) {
         context->writeComplete(fd, NULL, 0, COMM_OK);
         PROF_stop(clientSocketRecipient);
         return;
@@ -1402,8 +1422,8 @@ ConnStateData::readNextRequest()
      * Set the timeout BEFORE calling clientReadRequest().
      */
     typedef CommCbMemFunT<ConnStateData, CommTimeoutCbParams> TimeoutDialer;
-    AsyncCall::Pointer timeoutCall =  asyncCall(33, 5, "ConnStateData::requestTimeout",
-                                      TimeoutDialer(this, &ConnStateData::requestTimeout));
+    AsyncCall::Pointer timeoutCall = JobCallback(33, 5,
+                                     TimeoutDialer, this, ConnStateData::requestTimeout);
     commSetTimeout(clientConn->fd, Config.Timeout.persistent_request, timeoutCall);
 
     readSomeData();
@@ -1969,8 +1989,7 @@ isChunkedRequest(const HttpParser *hp)
     if (!request.parseHeader(HttpParserHdrBuf(hp), HttpParserHdrSz(hp)))
         return false;
 
-    return request.header.has(HDR_TRANSFER_ENCODING) &&
-           request.header.hasListMember(HDR_TRANSFER_ENCODING, "chunked", ',');
+    return request.header.chunked();
 }
 
 
@@ -2375,6 +2394,7 @@ clientProcessRequest(ConnStateData *conn, HttpParser *hp, ClientSocketContext *c
     bool notedUseOfBuffer = false;
     bool tePresent = false;
     bool deChunked = false;
+    bool mustReplyToOptions = false;
     bool unsupportedTe = false;
 
     /* We have an initial client stream in place should it be needed */
@@ -2500,8 +2520,12 @@ clientProcessRequest(ConnStateData *conn, HttpParser *hp, ClientSocketContext *c
     } else
         conn->cleanDechunkingRequest();
 
+    if (method == METHOD_TRACE || method == METHOD_OPTIONS)
+        request->max_forwards = request->header.getInt64(HDR_MAX_FORWARDS);
+
+    mustReplyToOptions = (method == METHOD_OPTIONS) && (request->max_forwards == 0);
     unsupportedTe = tePresent && !deChunked;
-    if (!urlCheckRequest(request) || unsupportedTe) {
+    if (!urlCheckRequest(request) || mustReplyToOptions || unsupportedTe) {
         clientStreamNode *node = context->getClientReplyContext();
         clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
         assert (repContext);
@@ -3002,8 +3026,8 @@ ConnStateData::requestTimeout(const CommTimeoutCbParams &io)
          * if we don't close() here, we still need a timeout handler!
          */
         typedef CommCbMemFunT<ConnStateData, CommTimeoutCbParams> TimeoutDialer;
-        AsyncCall::Pointer timeoutCall =  asyncCall(33, 5, "ConnStateData::requestTimeout",
-                                          TimeoutDialer(this,&ConnStateData::requestTimeout));
+        AsyncCall::Pointer timeoutCall =  JobCallback(33, 5,
+                                          TimeoutDialer, this, ConnStateData::requestTimeout);
         commSetTimeout(io.fd, 30, timeoutCall);
 
         /*
@@ -3102,16 +3126,15 @@ httpAccept(int sock, int unused, Comm::ConnectionPointer &details,
     connState = connStateCreate(details, s);
 
     typedef CommCbMemFunT<ConnStateData, CommCloseCbParams> Dialer;
-    AsyncCall::Pointer call = asyncCall(33, 5, "ConnStateData::connStateClosed",
-                                        Dialer(connState, &ConnStateData::connStateClosed));
+    AsyncCall::Pointer call = JobCallback(33, 5, Dialer, connState, ConnStateData::connStateClosed);
     comm_add_close_handler(details->fd, call);
 
     if (Config.onoff.log_fqdn)
         fqdncache_gethostbyaddr(details->remote, FQDN_LOOKUP_IF_MISS);
 
     typedef CommCbMemFunT<ConnStateData, CommTimeoutCbParams> TimeoutDialer;
-    AsyncCall::Pointer timeoutCall =  asyncCall(33, 5, "ConnStateData::requestTimeout",
-                                      TimeoutDialer(connState,&ConnStateData::requestTimeout));
+    AsyncCall::Pointer timeoutCall =  JobCallback(33, 5,
+                                      TimeoutDialer, connState, ConnStateData::requestTimeout);
     commSetTimeout(details->fd, Config.Timeout.read, timeoutCall);
 
 #if USE_IDENT
@@ -3312,16 +3335,15 @@ httpsAccept(int sock, int newfd, Comm::ConnectionPointer& details,
     fd_note(details->fd, "client https connect");
     ConnStateData *connState = connStateCreate(details, &s->http);
     typedef CommCbMemFunT<ConnStateData, CommCloseCbParams> Dialer;
-    AsyncCall::Pointer call = asyncCall(33, 5, "ConnStateData::connStateClosed",
-                                        Dialer(connState, &ConnStateData::connStateClosed));
+    AsyncCall::Pointer call = JobCallback(33, 5, Dialer, connState, ConnStateData::connStateClosed);
     comm_add_close_handler(details->fd, call);
 
     if (Config.onoff.log_fqdn)
         fqdncache_gethostbyaddr(details->remote, FQDN_LOOKUP_IF_MISS);
 
     typedef CommCbMemFunT<ConnStateData, CommTimeoutCbParams> TimeoutDialer;
-    AsyncCall::Pointer timeoutCall =  asyncCall(33, 5, "ConnStateData::requestTimeout",
-                                      TimeoutDialer(connState,&ConnStateData::requestTimeout));
+    AsyncCall::Pointer timeoutCall =  JobCallback(33, 5,
+                                      TimeoutDialer, connState, ConnStateData::requestTimeout);
     commSetTimeout(details->fd, Config.Timeout.request, timeoutCall);
 
 #if USE_IDENT
@@ -3902,8 +3924,8 @@ void ConnStateData::pinConnection(int pinning_fd, HttpRequest *request, struct p
     fd_note(pinning_fd, desc);
 
     typedef CommCbMemFunT<ConnStateData, CommCloseCbParams> Dialer;
-    pinning.closeHandler = asyncCall(33, 5, "ConnStateData::clientPinnedConnectionClosed",
-                                     Dialer(this, &ConnStateData::clientPinnedConnectionClosed));
+    pinning.closeHandler = JobCallback(33, 5,
+                                       Dialer, this, ConnStateData::clientPinnedConnectionClosed);
     comm_add_close_handler(pinning_fd, pinning.closeHandler);
 
 }
index c4c4adfe0a65d0b95e45c46288ec616f5702e987..c2379ffe6c214bb8f6ff2fe3e53c118b9d30a8f9 100644 (file)
@@ -115,6 +115,7 @@ public:
 private:
     CBDATA_CLASS(ClientSocketContext);
     void prepareReply(HttpReply * rep);
+    void packChunk(const StoreIOBuffer &bodyData, MemBuf &mb);
     void packRange(StoreIOBuffer const &, MemBuf * mb);
     void deRegisterWithConn();
     void doClose();
index 94987545dc1180fc2aebb08cc6ee3926b7713265..67626523f3524f5df54972806c80e78e7385d185 100644 (file)
@@ -973,6 +973,11 @@ clientReplyContext::checkTransferDone()
     if (http->flags.done_copying)
         return 1;
 
+    if (http->request->flags.chunked_reply && !flags.complete) {
+        // last-chunk was not sent
+        return 0;
+    }
+
     /*
      * Handle STORE_OK objects.
      * objectLen(entry) will be set proprely.
@@ -1117,7 +1122,9 @@ clientReplyContext::replyStatus()
         debugs(88, 5, "clientReplyStatus: transfer is DONE");
         /* Ok we're finished, but how? */
 
-        if (http->storeEntry()->getReply()->bodySize(http->request->method) < 0) {
+        const int64_t expectedBodySize =
+            http->storeEntry()->getReply()->bodySize(http->request->method);
+        if (!http->request->flags.proxy_keepalive && expectedBodySize < 0) {
             debugs(88, 5, "clientReplyStatus: closing, content_length < 0");
             return STREAM_FAILED;
         }
@@ -1127,7 +1134,7 @@ clientReplyContext::replyStatus()
             return STREAM_FAILED;
         }
 
-        if (!http->gotEnough()) {
+        if (expectedBodySize >= 0 && !http->gotEnough()) {
             debugs(88, 5, "clientReplyStatus: client didn't get all it expected");
             return STREAM_UNPLANNED_COMPLETE;
         }
@@ -1362,6 +1369,9 @@ clientReplyContext::buildReplyHeader()
 
 #endif
 
+    const bool maySendChunkedReply = !request->multipartRangeRequest() &&
+                                     (request->http_ver >= HttpVersion(1, 1));
+
     /* Check whether we should send keep-alive */
     if (!Config.onoff.error_pconns && reply->sline.status >= 400 && !request->flags.must_keepalive) {
         debugs(33, 3, "clientBuildReplyHeader: Error, don't keep-alive");
@@ -1375,17 +1385,22 @@ clientReplyContext::buildReplyHeader()
     } else if (request->flags.connection_auth && !reply->keep_alive) {
         debugs(33, 2, "clientBuildReplyHeader: Connection oriented auth but server side non-persistent");
         request->flags.proxy_keepalive = 0;
-    } else if (reply->bodySize(request->method) < 0) {
+    } else if (reply->bodySize(request->method) < 0 && !maySendChunkedReply) {
         debugs(88, 3, "clientBuildReplyHeader: can't keep-alive, unknown body size" );
         request->flags.proxy_keepalive = 0;
     } else if (fdUsageHigh()&& !request->flags.must_keepalive) {
         debugs(88, 3, "clientBuildReplyHeader: Not many unused FDs, can't keep-alive");
         request->flags.proxy_keepalive = 0;
-    } else if (request->http_ver.major == 1 && request->http_ver.minor == 1) {
-        debugs(88, 3, "clientBuildReplyHeader: Client is HTTP/1.1, send keep-alive, no overriding reasons not to");
-        request->flags.proxy_keepalive = 1;
     }
 
+    // Decide if we send chunked reply
+    if (maySendChunkedReply &&
+            request->flags.proxy_keepalive &&
+            reply->bodySize(request->method) < 0) {
+        debugs(88, 3, "clientBuildReplyHeader: chunked reply");
+        request->flags.chunked_reply = 1;
+        hdr->putStr(HDR_TRANSFER_ENCODING, "chunked");
+    }
 
     /* Append VIA */
     if (Config.onoff.via) {
@@ -1400,9 +1415,8 @@ clientReplyContext::buildReplyHeader()
         hdr->delById(HDR_VIA);
         hdr->putStr(HDR_VIA, strVia.termedBuf());
     }
-    /* Signal keep-alive if needed */
-    hdr->putStr( (http->flags.accel || http->flags.intercepted)? HDR_CONNECTION : HDR_PROXY_CONNECTION,
-                 request->flags.proxy_keepalive ? "keep-alive" : "close");
+    /* Signal keep-alive or close explicitly */
+    hdr->putStr(HDR_CONNECTION, request->flags.proxy_keepalive ? "keep-alive" : "close");
 
 #if ADD_X_REQUEST_URI
     /*
@@ -1617,7 +1631,7 @@ clientGetMoreData(clientStreamNode * aNode, ClientHttpRequest * http)
         return;
     }
 
-    /* TODO: handle OPTIONS request on max_forwards == 0 as well */
+    // OPTIONS with Max-Forwards:0 handled in clientProcessRequest()
 
     if (context->http->request->method == METHOD_TRACE) {
         if (context->http->request->max_forwards == 0) {
@@ -1729,6 +1743,7 @@ clientReplyContext::sendStreamError(StoreIOBuffer const &result)
     debugs(88, 5, "clientReplyContext::sendStreamError: A stream error has occured, marking as complete and sending no data.");
     StoreIOBuffer localTempBuffer;
     flags.complete = 1;
+    http->request->flags.stream_error = 1;
     localTempBuffer.flags.error = result.flags.error;
     clientStreamCallback((clientStreamNode*)http->client_stream.head->data, http, NULL,
                          localTempBuffer);
index 0f886035e7249f15b069096d0ad8f9f0bd47af2e..bdc3040829cea378409e527355f612e634360b0a 100644 (file)
@@ -974,9 +974,6 @@ clientInterpretRequestHeaders(ClientHttpRequest * http)
     }
 
 #endif
-    if (request->method == METHOD_TRACE || request->method == METHOD_OPTIONS) {
-        request->max_forwards = req_hdr->getInt64(HDR_MAX_FORWARDS);
-    }
 
     request->flags.cachable = http->request->cacheable();
 
@@ -1374,11 +1371,11 @@ ClientHttpRequest::startAdaptation(const Adaptation::ServiceGroupPointer &g)
     assert(!virginHeadSource);
     assert(!adaptedBodySource);
     virginHeadSource = initiateAdaptation(
-                           new Adaptation::Iterator(this, request, NULL, g));
+                           new Adaptation::Iterator(request, NULL, g));
 
     // we could try to guess whether we can bypass this adaptation
     // initiation failure, but it should not really happen
-    assert(virginHeadSource != NULL); // Must, really
+    Must(initiated(virginHeadSource));
 }
 
 void
index 76cd869e2a910bbea612130e38fe5b18caa23e67..facfc4b2d471e779a9640fbabe4d878dcc5bcdad 100644 (file)
@@ -177,7 +177,7 @@ private:
     void endRequestSatisfaction();
 
 private:
-    Adaptation::Initiate *virginHeadSource;
+    CbcPointer<Adaptation::Initiate> virginHeadSource;
     BodyPipe::Pointer adaptedBodySource;
 
     bool request_satisfaction_mode;
index 1e2ddb4d0d2f5b235a57718f56fdefb0be4ab675..6ba1ab62b680e7f86831ca55c12768299fa151bb 100644 (file)
@@ -1816,6 +1816,8 @@ checkTimeouts(void)
 
         if (writeTimedOut(fd)) {
             // We have an active write callback and we are timed out
+            debugs(5, 5, "checkTimeouts: FD " << fd << " auto write timeout");
+            commSetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0);
             commio_finish_callback(fd, COMMIO_FD_WRITECB(fd), COMM_ERROR, ETIMEDOUT);
         } else if (AlreadyTimedOut(F))
             continue;
index a2ff08dabe4f73590fdd7414e4fb36a669c57c8b..44dbf5567af148aeb33cac0fedb9d09610c77f32 100644 (file)
@@ -54,6 +54,12 @@ disk_init(void)
     (void) 0;
 }
 
+/* hack needed on SunStudio to avoid linkage convention mismatch */
+static void cxx_xfree(void *ptr)
+{
+    xfree(ptr);
+}
+
 /*
  * opens a disk file specified by 'path'.  This function always
  * blocks!  There is no callback.
@@ -188,7 +194,7 @@ diskCombineWrites(struct _fde_disk *fdd)
 
         wq->next = NULL;
 
-        wq->free_func = xfree;
+        wq->free_func = cxx_xfree;
 
         do {
             q = fdd->write_q;
index fb91dc18aad18fd576a3f9df55a08f6f3bc02226..8a0e1f44f00005650813e8c946f312f7c4ec7933 100644 (file)
@@ -815,7 +815,7 @@ idnsSendQuery(idns_query * q)
         } else {
             if (DnsSocketB >= 0 && nameservers[ns].S.IsIPv6())
                 y = comm_udp_sendto(DnsSocketB, nameservers[ns].S, q->buf, q->sz);
-            else
+            else if (DnsSocketA)
                 x = comm_udp_sendto(DnsSocketA, nameservers[ns].S, q->buf, q->sz);
         }
 
@@ -830,14 +830,11 @@ idnsSendQuery(idns_query * q)
 
     } while ( (x<0 && y<0) && q->nsends % nns != 0);
 
-    if (y >= 0) {
+    if (y > 0) {
         fd_bytes(DnsSocketB, y, FD_WRITE);
-        commSetSelect(DnsSocketB, COMM_SELECT_READ, idnsRead, NULL, 0);
     }
-
-    if (x >= 0) {
+    if (x > 0) {
         fd_bytes(DnsSocketA, x, FD_WRITE);
-        commSetSelect(DnsSocketA, COMM_SELECT_READ, idnsRead, NULL, 0);
     }
 
     nameservers[ns].nqueries++;
@@ -1121,6 +1118,10 @@ idnsRead(int fd, void *data)
 
     debugs(78, 3, "idnsRead: starting with FD " << fd);
 
+    // Always keep reading. This stops (or at least makes harder) several
+    // attacks on the DNS client.
+    commSetSelect(fd, COMM_SELECT_READ, idnsRead, NULL, 0);
+
     /* BUG (UNRESOLVED)
      *  two code lines after returning from comm_udprecvfrom()
      *  something overwrites the memory behind the from parameter.
@@ -1167,7 +1168,14 @@ idnsRead(int fd, void *data)
 
         if (ns >= 0) {
             nameservers[ns].nreplies++;
-        } else if (Config.onoff.ignore_unknown_nameservers) {
+        }
+
+        // Before unknown_nameservers check to avoid flooding cache.log on attacks,
+        // but after the ++ above to keep statistics right.
+        if (!lru_list.head)
+            continue; // Don't process replies if there is no pending query.
+
+        if (ns < 0 && Config.onoff.ignore_unknown_nameservers) {
             static time_t last_warning = 0;
 
             if (squid_curtime - last_warning > 60) {
@@ -1181,10 +1189,6 @@ idnsRead(int fd, void *data)
 
         idnsGrokReply(rbuf, len);
     }
-
-    if (lru_list.head) {
-        commSetSelect(fd, COMM_SELECT_READ, idnsRead, NULL, 0);
-    }
 }
 
 static void
@@ -1252,7 +1256,7 @@ idnsReadVC(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *dat
         return;
     }
 
-    vc->msg->size += len;      // XXX should not access -> size directly
+    vc->msg->size += len;       // XXX should not access -> size directly
 
     if (vc->msg->contentSize() < vc->msglen) {
         comm_read(fd, buf + len, vc->msglen - vc->msg->contentSize(), idnsReadVC, vc);
@@ -1371,10 +1375,12 @@ idnsInit(void)
         if (DnsSocketB >= 0) {
             port = comm_local_port(DnsSocketB);
             debugs(78, 1, "DNS Socket created at " << addrB << ", FD " << DnsSocketB);
+            commSetSelect(DnsSocketB, COMM_SELECT_READ, idnsRead, NULL, 0);
         }
         if (DnsSocketA >= 0) {
             port = comm_local_port(DnsSocketA);
             debugs(78, 1, "DNS Socket created at " << addrA << ", FD " << DnsSocketA);
+            commSetSelect(DnsSocketA, COMM_SELECT_READ, idnsRead, NULL, 0);
         }
     }
 
index d869b82204b8e137746804eaa1f298df8eace63b..797fbd3fdb2132ece6dc7d7d2788d856098b96f2 100644 (file)
@@ -116,7 +116,7 @@ esiBufferRecipient (clientStreamNode *node, ClientHttpRequest *http, HttpReply *
         if (rep) {
             if (rep->sline.status != HTTP_OK) {
                 rep = NULL;
-                esiStream->include->fail (esiStream);
+                esiStream->include->includeFail (esiStream);
                 esiStream->finished = 1;
                 httpRequestFree (http);
                 return;
@@ -168,7 +168,7 @@ esiBufferRecipient (clientStreamNode *node, ClientHttpRequest *http, HttpReply *
         /* XXX when reviewing ESI this is the first place to look */
         node->data = NULL;
         esiStream->finished = 1;
-        esiStream->include->fail (esiStream);
+        esiStream->include->includeFail (esiStream);
         return;
     };
 
@@ -185,7 +185,7 @@ esiBufferRecipient (clientStreamNode *node, ClientHttpRequest *http, HttpReply *
 
     case STREAM_FAILED:
         debugs(86, 1, "ESI subrequest failed transfer");
-        esiStream->include->fail (esiStream);
+        esiStream->include->includeFail (esiStream);
         esiStream->finished = 1;
         httpRequestFree (http);
         return;
@@ -472,7 +472,7 @@ ESIInclude::process (int dovars)
 }
 
 void
-ESIInclude::fail (ESIStreamContext::Pointer stream)
+ESIInclude::includeFail (ESIStreamContext::Pointer stream)
 {
     subRequestDone (stream, false);
 }
index d8b836cf749bb249ca74a696d4ce7c5b9aed3222..a364d5ebd1a5bb37f80f204874b8199a2d3455f5 100644 (file)
@@ -90,7 +90,7 @@ public:
     ESISegment::Pointer altcontent;
     ESIVarState *varState;
     char *srcurl, *alturl;
-    void fail(ESIStreamContext::Pointer);
+    void includeFail(ESIStreamContext::Pointer);
     void finish();
 
 private:
index 51171216a22ed57477ac4d6676c0d26002e403e8..e7c7a0dad88d79b6f4072843080a0cbb921784f3 100644 (file)
@@ -51,8 +51,7 @@ TESTS += testHeaders
 ## Special Universal .h dependency test script
 ## aborts if error encountered
 testHeaders: $(srcdir)/ufs/*.h $(srcdir)/coss/*.h
-       $(SHELL) $(top_srcdir)/test-suite/testheaders.sh "$(CXXCOMPILE)" "$(srcdir)/ufs" || exit 1
-       $(SHELL) $(top_srcdir)/test-suite/testheaders.sh "$(CXXCOMPILE)" "$(srcdir)/coss" || exit 1
+       $(SHELL) $(top_srcdir)/test-suite/testheaders.sh "$(CXXCOMPILE)" $^ || exit 1
 ## diskd/ has no .h files
 ## aufs/ has no .h files
 ## ./ has no .h files
index 6925dd711de29ff59f794ede755b6700342d69e0..2cdfa32497c2407bd6a5a059e4136ef34e3831d5 100644 (file)
@@ -489,8 +489,7 @@ FtpStateData::FtpStateData(FwdState *theFwdState, const Comm::ConnectionPointer
     flags.rest_supported = 1;
 
     typedef CommCbMemFunT<FtpStateData, CommCloseCbParams> Dialer;
-    AsyncCall::Pointer closer = asyncCall(9, 5, "FtpStateData::ctrlClosed",
-                                          Dialer(this, &FtpStateData::ctrlClosed));
+    AsyncCall::Pointer closer = JobCallback(9, 5, Dialer, this, FtpStateData::ctrlClosed);
     ctrl.opened(conn, closer);
 
     if (request->method == METHOD_PUT)
@@ -624,8 +623,7 @@ FtpStateData::switchTimeoutToDataChannel()
     commSetTimeout(ctrl.conn->fd, -1, nullCall);
 
     typedef CommCbMemFunT<FtpStateData, CommTimeoutCbParams> TimeoutDialer;
-    AsyncCall::Pointer timeoutCall =  asyncCall(9, 5, "FtpStateData::ftpTimeout",
-                                      TimeoutDialer(this, &FtpStateData::ftpTimeout));
+    AsyncCall::Pointer timeoutCall =  JobCallback(9, 5, TimeoutDialer, this, FtpStateData::ftpTimeout);
     commSetTimeout(data.conn->fd, Config.Timeout.read, timeoutCall);
 }
 
@@ -1183,16 +1181,15 @@ FtpStateData::maybeReadVirginBody()
     data.read_pending = true;
 
     typedef CommCbMemFunT<FtpStateData, CommTimeoutCbParams> TimeoutDialer;
-    AsyncCall::Pointer timeoutCall =  asyncCall(9, 5, "FtpStateData::ftpTimeout",
-                                      TimeoutDialer(this,&FtpStateData::ftpTimeout));
+    AsyncCall::Pointer timeoutCall =  JobCallback(9, 5,
+                                      TimeoutDialer, this, FtpStateData::ftpTimeout);
     commSetTimeout(data.conn->fd, Config.Timeout.read, timeoutCall);
 
     debugs(9,5,HERE << "queueing read on FD " << data.conn->fd);
 
     typedef CommCbMemFunT<FtpStateData, CommIoCbParams> Dialer;
     entry->delayAwareRead(data.conn->fd, data.readBuf->space(), read_sz,
-                          asyncCall(9, 5, "FtpStateData::dataRead",
-                                    Dialer(this, &FtpStateData::dataRead)));
+                          JobCallback(9, 5, Dialer, this, FtpStateData::dataRead));
 }
 
 void
@@ -1241,8 +1238,8 @@ FtpStateData::dataRead(const CommIoCbParams &io)
 
         if (ignoreErrno(io.xerrno)) {
             typedef CommCbMemFunT<FtpStateData, CommTimeoutCbParams> TimeoutDialer;
-            AsyncCall::Pointer timeoutCall =  asyncCall(9, 5, "FtpStateData::ftpTimeout",
-                                              TimeoutDialer(this,&FtpStateData::ftpTimeout));
+            AsyncCall::Pointer timeoutCall = JobCallback(9, 5,
+                                             TimeoutDialer, this, FtpStateData::ftpTimeout);
             commSetTimeout(io.fd, Config.Timeout.read, timeoutCall);
 
             maybeReadVirginBody();
@@ -1548,8 +1545,7 @@ FtpStateData::writeCommand(const char *buf)
     }
 
     typedef CommCbMemFunT<FtpStateData, CommIoCbParams> Dialer;
-    AsyncCall::Pointer call = asyncCall(9, 5, "FtpStateData::ftpWriteCommandCallback",
-                                        Dialer(this, &FtpStateData::ftpWriteCommandCallback));
+    AsyncCall::Pointer call = JobCallback(9, 5, Dialer, this, FtpStateData::ftpWriteCommandCallback);
     comm_write(ctrl.conn->fd,
                ctrl.last_command,
                strlen(ctrl.last_command),
@@ -1694,14 +1690,11 @@ FtpStateData::scheduleReadControlReply(int buffered_ok)
         }
 
         typedef CommCbMemFunT<FtpStateData, CommTimeoutCbParams> TimeoutDialer;
-        AsyncCall::Pointer timeoutCall =  asyncCall(9, 5, "FtpStateData::ftpTimeout",
-                                          TimeoutDialer(this,&FtpStateData::ftpTimeout));
-
+        AsyncCall::Pointer timeoutCall = JobCallback(9, 5, TimeoutDialer, this, FtpStateData::ftpTimeout);
         commSetTimeout(ctrl.conn->fd, Config.Timeout.read, timeoutCall);
 
         typedef CommCbMemFunT<FtpStateData, CommIoCbParams> Dialer;
-        AsyncCall::Pointer reader=asyncCall(9, 5, "FtpStateData::ftpReadControlReply",
-                                            Dialer(this, &FtpStateData::ftpReadControlReply));
+        AsyncCall::Pointer reader = JobCallback(9, 5, Dialer, this, FtpStateData::ftpReadControlReply);
         comm_read(ctrl.conn->fd, ctrl.buf + ctrl.offset, ctrl.size - ctrl.offset, reader);
     }
 }
@@ -2554,8 +2547,8 @@ ftpSendPassive(FtpStateData * ftpState)
      * dont acknowledge PASV commands. Use connect timeout to be faster then read timeout (minutes).
      */
     typedef CommCbMemFunT<FtpStateData, CommTimeoutCbParams> TimeoutDialer;
-    AsyncCall::Pointer timeoutCall =  asyncCall(9, 5, "FtpStateData::ftpTimeout",
-                                      TimeoutDialer(ftpState,&FtpStateData::ftpTimeout));
+    AsyncCall::Pointer timeoutCall =  JobCallback(9, 5,
+                                      TimeoutDialer, ftpState, FtpStateData::ftpTimeout);
 
     commSetTimeout(ftpState->ctrl.conn->fd, Config.Timeout.connect, timeoutCall);
 }
@@ -2738,8 +2731,7 @@ ftpOpenListenSocket(FtpStateData * ftpState, int fallback)
     }
 
     typedef CommCbMemFunT<FtpStateData, CommAcceptCbParams> acceptDialer;
-    AsyncCall::Pointer acceptCall = asyncCall(11, 5, "FtpStateData::ftpAcceptDataConnection",
-                                    acceptDialer(ftpState, &FtpStateData::ftpAcceptDataConnection));
+    AsyncCall::Pointer acceptCall = JobCallback(11, 5, acceptDialer, ftpState, FtpStateData::ftpAcceptDataConnection);
     ftpState->data.listener = new Comm::ConnAcceptor(conn, false, ftpState->entry->url());
     ftpState->data.listener->subscribe(acceptCall);
 
@@ -2914,8 +2906,7 @@ FtpStateData::ftpAcceptDataConnection(const CommAcceptCbParams &io)
 
             /* we are ony accepting once, so need to reset the listener socket. */
             typedef CommCbMemFunT<FtpStateData, CommAcceptCbParams> acceptDialer;
-            AsyncCall::Pointer acceptCall = asyncCall(11, 5, "FtpStateData::ftpAcceptDataConnection",
-                                            acceptDialer(this, &FtpStateData::ftpAcceptDataConnection));
+            AsyncCall::Pointer acceptCall = JobCallback(11, 5, acceptDialer, this, FtpStateData::ftpAcceptDataConnection);
             data.listener = new Comm::ConnAcceptor(data.listen_conn, false, data.host);
             data.listener->subscribe(acceptCall);
             AsyncJob::AsyncStart(data.listener);
@@ -3020,8 +3011,8 @@ void FtpStateData::readStor()
         /* When client code is 150 with no data channel, Accept data channel. */
         debugs(9, 3, "ftpReadStor: accepting data channel");
         typedef CommCbMemFunT<FtpStateData, CommAcceptCbParams> acceptDialer;
-        AsyncCall::Pointer acceptCall = asyncCall(11, 5, "FtpStateData::ftpAcceptDataConnection",
-                                        acceptDialer(this, &FtpStateData::ftpAcceptDataConnection));
+        AsyncCall::Pointer acceptCall = JobCallback(11, 5,
+                                        acceptDialer, this, FtpStateData::ftpAcceptDataConnection);
 
         data.listener = new Comm::ConnAcceptor(data.conn, false, data.host);
         data.listener->subscribe(acceptCall);
@@ -3156,8 +3147,8 @@ ftpReadList(FtpStateData * ftpState)
 
         /* Accept data channel */
         typedef CommCbMemFunT<FtpStateData, CommAcceptCbParams> acceptDialer;
-        AsyncCall::Pointer acceptCall = asyncCall(11, 5, "FtpStateData::ftpAcceptDataConnection",
-                                        acceptDialer(ftpState, &FtpStateData::ftpAcceptDataConnection));
+        AsyncCall::Pointer acceptCall = JobCallback(11, 5,
+                                        acceptDialer, ftpState, FtpStateData::ftpAcceptDataConnection);
 
         ftpState->data.listener = new Comm::ConnAcceptor(ftpState->data.conn, false, ftpState->data.host);
         ftpState->data.listener->subscribe(acceptCall);
@@ -3204,8 +3195,8 @@ ftpReadRetr(FtpStateData * ftpState)
         /* Accept data channel */
         ftpState->switchTimeoutToDataChannel();
         typedef CommCbMemFunT<FtpStateData, CommAcceptCbParams> acceptDialer;
-        AsyncCall::Pointer acceptCall = asyncCall(11, 5, "FtpStateData::ftpAcceptDataConnection",
-                                        acceptDialer(ftpState, &FtpStateData::ftpAcceptDataConnection));
+        AsyncCall::Pointer acceptCall = JobCallback(11, 5,
+                                        acceptDialer, ftpState, FtpStateData::ftpAcceptDataConnection);
         ftpState->data.listener = new Comm::ConnAcceptor(ftpState->data.conn, false, ftpState->data.host);
         ftpState->data.listener->subscribe(acceptCall);
         AsyncJob::AsyncStart(ftpState->data.listener);
@@ -3845,8 +3836,7 @@ AsyncCall::Pointer
 FtpStateData::dataCloser()
 {
     typedef CommCbMemFunT<FtpStateData, CommCloseCbParams> Dialer;
-    return asyncCall(9, 5, "FtpStateData::dataClosed",
-                     Dialer(this, &FtpStateData::dataClosed));
+    return JobCallback(9, 5, Dialer, this, FtpStateData::dataClosed);
 }
 
 /// configures the channel with a descriptor and registers a close handler
index e9c2b2ed7c75428abafca45ace9bd07aa7281b1d..df012c91b2e75b568d06dac86387c0f864eb4dfa 100644 (file)
@@ -142,8 +142,7 @@ HttpStateData::HttpStateData(FwdState *theFwdState) : AsyncJob("HttpStateData"),
      * register the handler to free HTTP state data when the FD closes
      */
     typedef CommCbMemFunT<HttpStateData, CommCloseCbParams> Dialer;
-    closeHandler = asyncCall(9, 5, "httpStateData::httpStateConnClosed",
-                             Dialer(this,&HttpStateData::httpStateConnClosed));
+    closeHandler = JobCallback(9, 5, Dialer, this, HttpStateData::httpStateConnClosed);
     comm_add_close_handler(serverConnection->fd, closeHandler);
 }
 
@@ -729,7 +728,7 @@ HttpStateData::processReplyHeader()
     }
 
     flags.chunked = 0;
-    if (newrep->sline.protocol == PROTO_HTTP && newrep->header.hasListMember(HDR_TRANSFER_ENCODING, "chunked", ',')) {
+    if (newrep->sline.protocol == PROTO_HTTP && newrep->header.chunked()) {
         flags.chunked = 1;
         httpChunkDecoder = new ChunkedCodingParser;
     }
@@ -1405,8 +1404,7 @@ HttpStateData::maybeReadVirginBody()
         flags.do_next_read = 0;
         typedef CommCbMemFunT<HttpStateData, CommIoCbParams> Dialer;
         entry->delayAwareRead(serverConnection->fd, readBuf->space(read_size), read_size,
-                              asyncCall(11, 5, "HttpStateData::readReply",
-                                        Dialer(this, &HttpStateData::readReply)));
+                              JobCallback(11, 5, Dialer, this,  HttpStateData::readReply));
     }
 }
 
@@ -1449,8 +1447,8 @@ HttpStateData::sendComplete(const CommIoCbParams &io)
      * request bodies.
      */
     typedef CommCbMemFunT<HttpStateData, CommTimeoutCbParams> TimeoutDialer;
-    AsyncCall::Pointer timeoutCall =  asyncCall(11, 5, "HttpStateData::httpTimeout",
-                                      TimeoutDialer(this,&HttpStateData::httpTimeout));
+    AsyncCall::Pointer timeoutCall =  JobCallback(11, 5,
+                                      TimeoutDialer, this, HttpStateData::httpTimeout);
 
     commSetTimeout(serverConnection->fd, Config.Timeout.read, timeoutCall);
 
@@ -1732,11 +1730,7 @@ HttpStateData::httpBuildRequestHeader(HttpRequest * request,
 
     /* maybe append Connection: keep-alive */
     if (flags.keepalive) {
-        if (flags.proxying) {
-            hdr_out->putStr(HDR_PROXY_CONNECTION, "keep-alive");
-        } else {
-            hdr_out->putStr(HDR_CONNECTION, "keep-alive");
-        }
+        hdr_out->putStr(HDR_CONNECTION, "keep-alive");
     }
 
     /* append Front-End-Https */
@@ -1784,7 +1778,7 @@ copyOneHeaderFromClientsideRequestToUpstreamRequest(const HttpHeaderEntry *e, co
     case HDR_TE:                  /** \par TE: */
     case HDR_KEEP_ALIVE:          /** \par Keep-Alive: */
     case HDR_PROXY_AUTHENTICATE:  /** \par Proxy-Authenticate: */
-    case HDR_TRAILERS:            /** \par Trailers: */
+    case HDR_TRAILER:             /** \par Trailer: */
     case HDR_UPGRADE:             /** \par Upgrade: */
     case HDR_TRANSFER_ENCODING:   /** \par Transfer-Encoding: */
         break;
@@ -1881,12 +1875,13 @@ copyOneHeaderFromClientsideRequestToUpstreamRequest(const HttpHeaderEntry *e, co
 
         break;
 
-    case HDR_PROXY_CONNECTION:
+    case HDR_PROXY_CONNECTION: // SHOULD ignore. But doing so breaks things.
+        break;
 
     case HDR_X_FORWARDED_FOR:
 
     case HDR_CACHE_CONTROL:
-        /** \par Proxy-Connaction:, X-Forwarded-For:, Cache-Control:
+        /** \par X-Forwarded-For:, Cache-Control:
          * handled specially by Squid, so leave off for now.
          * append these after the loop if needed */
         break;
@@ -1992,9 +1987,9 @@ HttpStateData::sendRequest()
     }
 
     typedef CommCbMemFunT<HttpStateData, CommTimeoutCbParams> TimeoutDialer;
-    AsyncCall::Pointer timeoutCall =  asyncCall(11, 5, "HttpStateData::httpTimeout",
-                                      TimeoutDialer(this,&HttpStateData::httpTimeout));
-    commSetTimeout(serverConnection->fd, Config.Timeout.lifetime, timeoutCall);
+    AsyncCall::Pointer timeoutCall =  JobCallback(11, 5,
+                                      TimeoutDialer, this, HttpStateData::httpTimeout);
+    commSetTimeout(srverConnection->fd, Config.Timeout.lifetime, timeoutCall);
     flags.do_next_read = 1;
     maybeReadVirginBody();
 
@@ -2002,13 +1997,13 @@ HttpStateData::sendRequest()
         if (!startRequestBodyFlow()) // register to receive body data
             return false;
         typedef CommCbMemFunT<HttpStateData, CommIoCbParams> Dialer;
-        Dialer dialer(this, &HttpStateData::sentRequestBody);
-        requestSender = asyncCall(11,5, "HttpStateData::sentRequestBody", dialer);
+        requestSender = JobCallback(11,5,
+                                    Dialer, this, HttpStateData::sentRequestBody);
     } else {
         assert(!requestBodySource);
         typedef CommCbMemFunT<HttpStateData, CommIoCbParams> Dialer;
-        Dialer dialer(this, &HttpStateData::sendComplete);
-        requestSender = asyncCall(11,5, "HttpStateData::SendComplete", dialer);
+        requestSender = JobCallback(11,5,
+                                    Dialer, this,  HttpStateData::sendComplete);
     }
 
     if (_peer != NULL) {
@@ -2102,8 +2097,7 @@ HttpStateData::doneSendingRequestBody()
             }
 
             typedef CommCbMemFunT<HttpStateData, CommIoCbParams> Dialer;
-            Dialer dialer(this, &HttpStateData::sendComplete);
-            AsyncCall::Pointer call= asyncCall(11,5, "HttpStateData::SendComplete", dialer);
+            AsyncCall::Pointer call = JobCallback(11, 5, Dialer, this, HttpStateData::sendComplete);
             comm_write(serverConnection->fd, "\r\n", 2, call);
         }
         return;
index 68794d4509137add5d540f6a9c9f08bc9c313bf5..97e1343b633d37373576e9228ab8cbcea9322a6b 100644 (file)
@@ -19,7 +19,7 @@ SQUIDCEXTERN void netdbInit(void);
 
 SQUIDCEXTERN void netdbHandlePingReply(const Ip::Address &from, int hops, int rtt);
 SQUIDCEXTERN void netdbPingSite(const char *hostname);
-SQUIDCEXTERN void netdbDump(StoreEntry *);
+void netdbDump(StoreEntry *);
 
 SQUIDCEXTERN void netdbFreeMemory(void);
 SQUIDCEXTERN int netdbHostHops(const char *host);
index 12e04ccd5c6af1de75a2fbbe78ec787f4013910f..4556f0590c3f573f9352154c3034f0495049a694 100644 (file)
@@ -31,8 +31,9 @@ void Ipc::Port::listen()
 {
     debugs(54, 6, HERE);
     buf.prepForReading();
-    AsyncCall::Pointer readHandler = asyncCall(54, 6, "Ipc::Port::noteRead",
-                                     CommCbMemFunT<Port, CommIoCbParams>(this, &Port::noteRead));
+    typedef CommCbMemFunT<Port, CommIoCbParams> Dialer;
+    AsyncCall::Pointer readHandler = JobCallback(54, 6,
+                                     Dialer, this, Port::noteRead);
     comm_read(fd(), buf.raw(), buf.size(), readHandler);
 }
 
index e29b6a77ee3af94b90d29e9e8d42cee5d0c33f03..0c44629ee90d296145bdbe0ff180ba34283457a0 100644 (file)
@@ -46,9 +46,9 @@ int Ipc::UdsOp::fd()
 
 void Ipc::UdsOp::setTimeout(int seconds, const char *handlerName)
 {
+    typedef CommCbMemFunT<UdsOp, CommTimeoutCbParams> Dialer;
     AsyncCall::Pointer handler = asyncCall(54,5, handlerName,
-                                           CommCbMemFunT<UdsOp, CommTimeoutCbParams>(this,
-                                                   &UdsOp::noteTimeout));
+                                           Dialer(CbcPointer<UdsOp>(this), &UdsOp::noteTimeout));
     commSetTimeout(fd(), seconds, handler);
 }
 
@@ -102,8 +102,9 @@ bool Ipc::UdsSender::doneAll() const
 void Ipc::UdsSender::write()
 {
     debugs(54, 5, HERE);
-    AsyncCall::Pointer writeHandler = asyncCall(54, 5, "Ipc::UdsSender::wrote",
-                                      CommCbMemFunT<UdsSender, CommIoCbParams>(this, &UdsSender::wrote));
+    typedef CommCbMemFunT<UdsSender, CommIoCbParams> Dialer;
+    AsyncCall::Pointer writeHandler = JobCallback(54, 5,
+                                      Dialer, this, UdsSender::wrote);
     comm_write(fd(), message.raw(), message.size(), writeHandler);
     writing = true;
 }
@@ -127,5 +128,5 @@ void Ipc::UdsSender::timedout()
 
 void Ipc::SendMessage(const String& toAddress, const TypedMsgHdr &message)
 {
-    AsyncJob::AsyncStart(new UdsSender(toAddress, message));
+    AsyncJob::Start(new UdsSender(toAddress, message));
 }
index 746d2651222b64d7a0e6b5953f1f8074008b2784..e93b42b67f23712b3cbc164693993cf8dcaa008a 100644 (file)
@@ -128,6 +128,9 @@ static struct _ipcache_stats {
 /// \ingroup IPCacheInternal
 static dlink_list lru_list;
 
+// forward-decls
+static void stat_ipcache_get(StoreEntry *);
+
 static FREE ipcacheFreeEntry;
 #if USE_DNSSERVERS
 static HLPCB ipcacheHandleReply;
index 14271ce4b3b0b5bc4903751b2be120f0d447b44e..6c038d3b37d8d610b9d6c16e92f4a684f8fc120d 100644 (file)
@@ -1460,9 +1460,9 @@ SquidMain(int argc, char **argv)
     mainLoop.setTimeService(&time_engine);
 
     if (IamCoordinatorProcess())
-        AsyncJob::AsyncStart(Ipc::Coordinator::Instance());
+        AsyncJob::Start(Ipc::Coordinator::Instance());
     else if (UsingSmp() && IamWorkerProcess())
-        AsyncJob::AsyncStart(new Ipc::Strand);
+        AsyncJob::Start(new Ipc::Strand);
 
     /* at this point we are finished the synchronous startup. */
     starting_up = 0;
index a94cf5545c1a887e3fb136e244523bb389105ede..3b8e71ed2b318904af23c504356856a83acf7c99 100644 (file)
@@ -543,6 +543,12 @@ memFree64K(void *p)
     memFree(p, MEM_64K_BUF);
 }
 
+static void
+cxx_xfree(void * ptr)
+{
+    xfree(ptr);
+}
+
 FREE *
 memFreeBufFunc(size_t size)
 {
@@ -569,7 +575,7 @@ memFreeBufFunc(size_t size)
     default:
         memMeterDec(HugeBufCountMeter);
         memMeterDel(HugeBufVolumeMeter, size);
-        return xfree;
+        return cxx_xfree;
     }
 }
 
index 2558d536e810e463c78d30f164bf023eef0ec80f..c952b62f09542aa831955999569ff75058360d54 100644 (file)
@@ -40,6 +40,7 @@
 #include "htcp.h"
 #include "HttpRequest.h"
 #include "ICP.h"
+#include "ip/tools.h"
 #include "MemObject.h"
 #include "PeerDigest.h"
 #include "PeerSelectState.h"
@@ -1562,16 +1563,20 @@ dump_peer_options(StoreEntry * sentry, peer * p)
         storeAppendPrintf(sentry, " closest-only");
 
 #if USE_HTCP
-    if (p->options.htcp)
+    if (p->options.htcp) {
         storeAppendPrintf(sentry, " htcp");
-    if (p->options.htcp_oldsquid)
-        storeAppendPrintf(sentry, " htcp-oldsquid");
-    if (p->options.htcp_no_clr)
-        storeAppendPrintf(sentry, " htcp-no-clr");
-    if (p->options.htcp_no_purge_clr)
-        storeAppendPrintf(sentry, " htcp-no-purge-clr");
-    if (p->options.htcp_only_clr)
-        storeAppendPrintf(sentry, " htcp-only-clr");
+        if (p->options.htcp_oldsquid || p->options.htcp_no_clr || p->options.htcp_no_purge_clr || p->options.htcp_only_clr) {
+            int doneopts=0;
+            if (p->options.htcp_oldsquid)
+                storeAppendPrintf(sentry, "%soldsquid",(doneopts++>0?",":"="));
+            if (p->options.htcp_no_clr)
+                storeAppendPrintf(sentry, "%sno-clr",(doneopts++>0?",":"="));
+            if (p->options.htcp_no_purge_clr)
+                storeAppendPrintf(sentry, "%sno-purge-clr",(doneopts++>0?",":"="));
+            if (p->options.htcp_only_clr)
+                storeAppendPrintf(sentry, "%sonly-clr",(doneopts++>0?",":"="));
+        }
+    }
 #endif
 
     if (p->options.no_netdb_exchange)
index 95a895bda37bd449a0edc0d6282be81ce2e7510d..64105cb343ae8807ab1a2afbfe14faa207b06858 100644 (file)
@@ -157,14 +157,14 @@ SQUIDCEXTERN void fqdncache_nbgethostbyaddr(const Ip::Address &, FQDNH *, void *
 
 SQUIDCEXTERN const char *fqdncache_gethostbyaddr(const Ip::Address &, int flags);
 SQUIDCEXTERN void fqdncache_init(void);
-SQUIDCEXTERN void fqdnStats(StoreEntry *);
+void fqdnStats(StoreEntry *);
 SQUIDCEXTERN void fqdncacheReleaseInvalid(const char *);
 
 SQUIDCEXTERN const char *fqdnFromAddr(const Ip::Address &);
 SQUIDCEXTERN int fqdncacheQueueDrain(void);
 SQUIDCEXTERN void fqdncacheFreeMemory(void);
 SQUIDCEXTERN void fqdncache_restart(void);
-SQUIDCEXTERN void fqdncache_purgelru(void *);
+void fqdncache_purgelru(void *);
 SQUIDCEXTERN void fqdncacheAddEntryFromHosts(char *addr, wordlist * hostnames);
 
 class FwdState;
@@ -250,7 +250,7 @@ SQUIDCEXTERN void httpHdrCcPackInto(const HttpHdrCc * cc, Packer * p);
 SQUIDCEXTERN void httpHdrCcSetMaxAge(HttpHdrCc * cc, int max_age);
 SQUIDCEXTERN void httpHdrCcSetSMaxAge(HttpHdrCc * cc, int s_maxage);
 SQUIDCEXTERN void httpHdrCcUpdateStats(const HttpHdrCc * cc, StatHist * hist);
-SQUIDCEXTERN void httpHdrCcStatDumper(StoreEntry * sentry, int idx, double val, double size, int count);
+void httpHdrCcStatDumper(StoreEntry * sentry, int idx, double val, double size, int count);
 
 /* Http Header Tools */
 class HttpHeaderFieldInfo;
@@ -276,7 +276,7 @@ SQUIDCEXTERN void httpHeaderInitModule(void);
 SQUIDCEXTERN void httpHeaderCleanModule(void);
 
 /* store report about current header usage and other stats */
-SQUIDCEXTERN void httpHeaderStoreReport(StoreEntry * e);
+void httpHeaderStoreReport(StoreEntry * e);
 SQUIDCEXTERN void httpHdrMangleList(HttpHeader *, HttpRequest *, int req_or_rep);
 SQUIDCEXTERN int httpReqHdrManglersConfigured();
 
@@ -321,15 +321,14 @@ extern void wccp2ConnectionOpen(void);
 extern void wccp2ConnectionClose(void);
 #endif /* USE_WCCPv2 */
 
+void ipcache_purgelru(void *);
 SQUIDCEXTERN void ipcache_nbgethostbyname(const char *name,
         IPH * handler,
         void *handlerData);
-SQUIDCEXTERN void ipcache_purgelru(void *);
 SQUIDCEXTERN const ipcache_addrs *ipcache_gethostbyname(const char *, int flags);
 SQUIDCEXTERN void ipcacheInvalidate(const char *);
 SQUIDCEXTERN void ipcacheInvalidateNegative(const char *);
 SQUIDCEXTERN void ipcache_init(void);
-SQUIDCEXTERN void stat_ipcache_get(StoreEntry *);
 SQUIDCEXTERN void ipcacheCycleAddr(const char *name, ipcache_addrs *);
 SQUIDCEXTERN void ipcacheMarkBadAddr(const char *name, const Ip::Address &);
 SQUIDCEXTERN void ipcacheMarkGoodAddr(const char *name, const Ip::Address &);
@@ -554,12 +553,12 @@ SQUIDCEXTERN int storeClientIsThisAClient(store_client * sc, void *someClient);
 SQUIDCEXTERN const char *getMyHostname(void);
 SQUIDCEXTERN const char *uniqueHostname(void);
 SQUIDCEXTERN void safeunlink(const char *path, int quiet);
-SQUIDCEXTERN void death(int sig);
+void death(int sig);
 SQUIDCEXTERN void fatal(const char *message);
 SQUIDCEXTERN void fatalf(const char *fmt,...) PRINTF_FORMAT_ARG1;
 SQUIDCEXTERN void fatal_dump(const char *message);
-SQUIDCEXTERN void sigusr2_handle(int sig);
-SQUIDCEXTERN void sig_child(int sig);
+void sigusr2_handle(int sig);
+void sig_child(int sig);
 SQUIDCEXTERN void leave_suid(void);
 SQUIDCEXTERN void enter_suid(void);
 SQUIDCEXTERN void no_suid(void);
index 65bb5a2667404c6ac85b968024de95f2d74606fa..c246c564d27007d78695ac73a64a5885c03138ba 100644 (file)
@@ -25,7 +25,7 @@ TESTS += testHeaders
 ## Special Universal .h dependency test script
 ## aborts if error encountered
 testHeaders: $(srcdir)/heap/*.h
-       $(SHELL) $(top_srcdir)/test-suite/testheaders.sh "$(CXXCOMPILE)" "$(srcdir)/heap" || exit 1
+       $(SHELL) $(top_srcdir)/test-suite/testheaders.sh "$(CXXCOMPILE)" $^ || exit 1
 ## ./ has no .h files.
 ## ./lru/ has no .h files.
 
index 78a06acdcbedf32041cb6d149d631ecc6c2b9272..5db7eced6b23d7bae8e2aa3aef5daa743516cadd 100644 (file)
@@ -1003,7 +1003,7 @@ struct _iostats {
 
 
 struct request_flags {
-    request_flags(): range(0),nocache(0),ims(0),auth(0),cachable(0),hierarchical(0),loopdetect(0),proxy_keepalive(0),proxying(0),refresh(0),redirected(0),need_validation(0),accelerated(0),ignore_cc(0),intercepted(0),spoof_client_ip(0),internal(0),internalclient(0),must_keepalive(0),destinationIPLookedUp_(0) {
+    request_flags(): range(0),nocache(0),ims(0),auth(0),cachable(0),hierarchical(0),loopdetect(0),proxy_keepalive(0),proxying(0),refresh(0),redirected(0),need_validation(0),accelerated(0),ignore_cc(0),intercepted(0),spoof_client_ip(0),internal(0),internalclient(0),must_keepalive(0),chunked_reply(0),stream_error(0),destinationIPLookedUp_(0) {
 #if USE_HTTP_VIOLATIONS
         nocache_hack = 0;
 #endif
@@ -1041,6 +1041,8 @@ unsigned int proxying:
     unsigned int pinned:1;      /* Request sent on a pinned connection */
     unsigned int auth_sent:1;   /* Authentication forwarded */
     unsigned int no_direct:1;  /* Deny direct forwarding unless overriden by always_direct. Used in accelerator mode */
+    unsigned int chunked_reply:1; /**< Reply with chunked transfer encoding */
+    unsigned int stream_error:1; /**< Whether stream error has occured */
 
     // When adding new flags, please update cloneAdaptationImmune() as needed.
 
index 1e7a59953cec05340af963f3f232b30372623c8a..87a048ffb652b1aa3ecc3a4a6d311a107deef264 100644 (file)
@@ -47,7 +47,7 @@ HttpReply::~HttpReply()
 
 void
 HttpReply::setHeaders(http_status status, const char *reason,
-                      const char *ctype, int64_t clen, time_t lmt, time_t expires)
+                      const char *ctype, int64_t clen, time_t lmt, time_t expires_)
 {
     fatal ("Not implemented");
 }
diff --git a/src/tests/stub_main_cc.cc b/src/tests/stub_main_cc.cc
new file mode 100644 (file)
index 0000000..06496d1
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * $Id$
+ *
+ * AUTHOR: Francesco Chemolli
+ *
+ * SQUID Web Proxy Cache          http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ *  Squid is the result of efforts by numerous individuals from
+ *  the Internet community; see the CONTRIBUTORS file for full
+ *  details.   Many organizations have provided support for Squid's
+ *  development; see the SPONSORS file for full details.  Squid is
+ *  Copyrighted (C) 2001 by the Regents of the University of
+ *  California; see the COPYRIGHT file for full details.  Squid
+ *  incorporates software developed and/or copyrighted by other
+ *  sources; see the CREDITS file for full details.
+ *
+ *  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, USA.
+ *
+ * Stubs for calls to stuff defined in main.cc
+ *
+ */
+
+void
+shut_down(int)
+{ /* stub */ }
+
+void
+reconfigure(int)
+{ /* stub */ }
+
+void
+rotate_logs(int)
+{ /* stub */ }
+
index 035e587daad0089b0b9c45a8ca14d42af0469a17..39d9d806a1c457bcb376aebdb53648a1a01beed2 100644 (file)
 
 CPPUNIT_TEST_SUITE_REGISTRATION( testCacheManager );
 
-/* stub functions to link successfully */
-void
-shut_down(int)
-{}
-
-void
-reconfigure(int)
-{}
-
-/* end stubs */
-
 /* init memory pools */
 
 void testCacheManager::setUp()
index e0b54bbe5209470347b523276e7b844698044ee5..57fb0a3df4bfa7168003bea27f027c00173fca6c 100644 (file)
 
 CPPUNIT_TEST_SUITE_REGISTRATION( testEvent );
 
-/* stub functions to link successfully */
-void
-shut_down(int)
-{}
-
-void
-reconfigure(int)
-{}
-
-/* end stubs */
-
 /* init legacy static-initialized modules */
 
 void
index b490ad8e1d76c69559b9d8fa10f7c38d487a347f..03412038d26aedde2b469c1c985c57f73534756c 100644 (file)
 
 CPPUNIT_TEST_SUITE_REGISTRATION( testEventLoop );
 
-/* stub functions to link successfully */
-void
-shut_down(int)
-{}
-
-void
-reconfigure(int)
-{}
-
-/* end stubs */
-
 /* init legacy static-initialized modules */
 
 void
index ae1e8bc873ddcd066929888364ceb49edcf86be2..841b1cf225ce4a6642d112943e2c94dd75b3e7d6 100644 (file)
@@ -17,17 +17,6 @@ public:
     bool doSanityCheckStartLine(MemBuf *b, const size_t h, http_status *e) { return sanityCheckStartLine(b,h,e); };
 };
 
-/* stub functions to link successfully */
-void
-shut_down(int)
-{}
-
-void
-reconfigure(int)
-{}
-
-/* end stubs */
-
 /* init memory pools */
 
 void
index 371eda69d4a231af6149943feaaac55e60c70cf2..aba0f174c4897deb13ef1b2499929f15c2d1d6e2 100644 (file)
 
 CPPUNIT_TEST_SUITE_REGISTRATION( testURL );
 
-/* stub functions to link successfully */
-void
-shut_down(int)
-{}
-
-void
-reconfigure(int)
-{}
-
-/* end stubs */
-
 /* init memory pools */
 
 void
index e106f8fe3aaa4c94ce7add9ec793b5ef524b423f..02212f2312722c44926dadaa2a4d47088a042cad 100644 (file)
 #include "acl/Checklist.h"
 #endif
 
-/* Stub routines */
-void
-shut_down(int)
-{}
-
-void
-reconfigure(int)
-{}
-
 SQUIDCEXTERN void httpHeaderPutStr(HttpHeader * hdr, http_hdr_type type, const char *str)
 {
     fatal ("dummy function\n");
index 970388ced4932d4407670903459b62aaf3722f24..2f8c05a5cdd616aebf01f9eeb4995bbcbe2720ce 100644 (file)
@@ -610,6 +610,8 @@ tunnelStart(ClientHttpRequest * http, int64_t * size_ptr, int *status_ptr)
     statCounter.server.all.requests++;
     statCounter.server.other.requests++;
 
+    request->hier.peer_local_port = comm_local_port(sock); // for %<lp logging
+
     tunnelState = new TunnelStateData;
 #if DELAY_POOLS
     tunnelState->server.setDelayId(DelayId::DelayClient(http));
index 48f358fd02d4ae99f70acf94d2b704b84f17f37d..cb0144a95373b069c07d03e1fb42b7044c424a02 100755 (executable)
@@ -9,39 +9,35 @@
 # This script should be run from the makefile with the directory path and ccflags
 #
 cc="${1}"
-
-if test "${2}" = ""; then
-       dir="."
-else
-       dir="${2}"
-fi
+shift
+for dir in /usr/bin /usr/local/bin /usr/gnu/bin
+do
+       test -x ${dir}/true && TRUE=${dir}/true
+done
+TRUE=${TRUE:-/bin/true}
 
 exitCode=0
 
-for f in `cd ${dir} && ls -1 *.h 2>/dev/null`; do
-       echo -n "Testing ${dir}/${f} ..."
-       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 \"${dir}/${f}\" "
-                       echo "int main( int argc, char* argv[] ) { return 0; } "
-               ) >./testHeaderDeps_${hdr}.cc
-
-               # run compile test on the new file.
-               # DEBUG: echo "TRY: ${cc} -o testHeaderDeps.o ./testHeaderDeps_${hdr}.cc"
-               ${cc} -c -o testHeaderDeps_${hdr}.o ./testHeaderDeps_${hdr}.cc
-               rm ./testHeaderDeps_${hdr}.cc
-       fi
-       if [ ! -f testHeaderDeps_${hdr}.o ]; then
-               rm testHeaders
-               exitCode=1
-       else
-               echo "OK."
-               # unit-tests require an app to run.
-               # our most-recent object suits this purpose.
-               # let's link or some tests will fail
-               ${cc} ./testHeaderDeps_${hdr}.o -o ./testHeaders
-       fi
+for f in $@; do
+       echo -n "Testing ${f} ..."
+    t="testhdr_`basename ${f}`"
+    if [ ! -f "$t.o" -o $f -nt "$t.o" ]; then
+        echo >$t.cc <<EOF
+/* This file is AUTOMATICALLY GENERATED. DO NOT ALTER IT */
+#include "${f}"
+int main( int argc, char* argv[] ) { return 0; }
+EOF
+        if ${cc} -c -o $t.o $t.cc ; then 
+            echo "Ok."
+        else
+            echo "Fail."
+            exitCode=1
+        fi
+        rm $t.cc $t.o
+    fi
+    test $exitCode -eq 0 || break
 done
 
+#who ever said that the test program needs to be meaningful?
+test $exitCode -eq 0 && cp ${TRUE} testHeaders
 exit $exitCode
index 5efe2628e1b5c3b53ed4fe6e214e873627dfbef5..abdab389c2ee38877ded1c97565744573f67e400 100644 (file)
@@ -11,7 +11,7 @@ AUTOMAKE_OPTIONS = subdir-objects
 ## we need our local files too (but avoid -I. at all costs)
 INCLUDES += -I$(srcdir)
 
-SUBDIRS = 
+SUBDIRS = purge
 EXTRA_DIST = 
 man_MANS = 
 DISTCLEANFILES = 
@@ -20,6 +20,7 @@ LDADD = \
        $(top_builddir)/src/time.o \
        $(top_builddir)/src/ip/libip.la \
        $(COMPAT_LIB) \
+       $(KRB5LIBS) \
        $(XTRA_LIBS)
 
 include $(top_srcdir)/doc/manuals/Substitute.am
diff --git a/tools/purge/Makefile b/tools/purge/Makefile
deleted file mode 100644 (file)
index a9cbf8e..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-#
-# Makefile
-#
-# The Makefile is divided into three sections, the "generic section", the
-# "host section" and the "rules section". The generics section defines
-# defaults which you should not change. Changes should solely be made to
-# the rules section.
-#
-# You will need to select several parameters befitting your compiler/system:
-#
-# -DHAS_BOOL   - set, if your C++ compiler knows about the 'bool' type.
-# -DHAS_PSIGNAL - set, if your libc supports psignal(int,const char*).
-# -fno-exceptions - may not be recognized by all variants of g++
-# -ffor-scope  - the new ANSI C++ scoping of for() variables is used...
-#
-# === [1] ==================================================== generics section
-#
-CXX    = g++ -ffor-scope -DHAS_BOOL -DHAS_PSIGNAL
-CC     = gcc
-LD     = $(CC)         # yes, I do mean gcc and not g++
-CXXFLAGS = # -pg -g # -fprofile-arcs -ftest-coverage
-SYSTEM  = $(shell uname -s | tr '[a-z]' '[A-Z]' | tr -d '_ -/')
-CPU    = $(shell uname -p)
-VERSION = $(shell uname -r)
-HOST   = $(shell uname -n)
-MAJOR   = $(firstword $(subst ., ,$(VERSION)))
-MINOR   = $(strip $(word 2,$(subst ., ,$(VERSION))))
-LOADLIBES =
-SOCKLEN        = int # default except for glibc2?
-
-# optimization levels - Do *not* use levels above -O1 with g++,
-# if -fprofile-arcs or -ftest-coverage is selected! Set to different
-# values in the host specific section below.
-#
-# - OPT_NORM for normal level optimization, O2 is a good choice.
-#
-OPT_NORM = -O2
-
-# electric fence library, for test purposes only (helps w/ memory leaks)
-# (developers only)
-EFENCE = -L/usr/local/lib -lefence
-
-#
-# === [2] ======================================================= hosts section
-#
-
-ifeq (SUNOS,${SYSTEM})
-ifeq (5,${MAJOR})
-# use these for the SUN CC compiler (for STL, see below or above)
-# You must define this for Solaris 2.x: CXXFLAGS = -DSOLARIS 
-CC     = cc
-#CXX   = CC -DHAS_BOOL -DHAS_PSIGNAL -DHAS_MUTABLE
-#CXXFLAGS = -DSOLARIS  '-library=%none,Cstd,Crun' 
-#CXXFLAGS += -dalign -ftrap=%none -fsimple -xlibmil
-#OPT_NORM = -xtarget=ultra2 -xO4
-#EXTRALIB += -lnsl -lsocket
-#LD    = CC
-#
-## g++ settings for Solaris on Ultra Sparcs (comment out all of above):
-CXXFLAGS += -DSOLARIS # -ggdb
-OPT_NORM = -O2 # -mcpu=supersparc
-LD     = $(CC)
-##
-#EXTRALIB += -lnsl -lsocket -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic
-else
-# old SunOS 4.1.x, not supported!
-CXXFLAGS += -DSUN
-endif
-endif
-
-ifeq (IRIX64,${SYSTEM})
-# The regular 64bit Irix stuff is just too slow, use n32!
-SYSTEM        := IRIX
-endif
-
-ifeq (FREEBSD,${SYSTEM})
-SOCKLEN        = socklen_t
-endif
-
-ifeq (IRIX,${SYSTEM})
-CXX     = CC -n32 -mips3 -r4000 -DEFAULT:abi=n32:isa=mips3:proc=r4k
-CXX    += -LANG:ansi-for-init-scope=on -LANG:bool=on
-CXX    += -LANG:exceptions=off -LANG:explicit=off -LANG:wchar_t=off
-CXX    += -LANG:mutable=on -LANG:namespaces=on -LANG:std
-CC     = cc -n32 -mips3 -r4000
-CXXFLAGS = -woff 1174 -LANG:exceptions=off -DHAS_BOOL -DHAS_PSIGNAL
-LD     = $(CXX)
-OPT_NORM = -O3 -IPA -LNO:opt=1
-# for g++
-#CXXFLAGS += -mips3 -mcpu=r4000 
-endif
-
-ifeq (AIX,${SYSTEM})
-ifeq (,${MINOR})
-MINOR  := ${MAJOR}
-MAJOR  = 4
-endif
-CXX    = xlC -UHAS_BOOL -UHAS_PSIGNAL
-CC     = xlc
-CXXFLAGS = -qtune=pwr # -qdbxextra -g
-#CXX   = g++ -ffor-scope -DHAS_BOOL -UHAS_PSIGNAL
-SOCKLEN        = size_t
-LD     = $(CXX)
-endif
-
-ifeq (LINUX,${SYSTEM})
-# determine highest version of all installed libc's.
-LIBCVER = $(shell /bin/ls /lib/libc.so.? | \
-       awk -F'.' '{ if (m<$$3) m=$$3;} END { print m} ')
-ifeq (6,${LIBCVER})
-SOCKLEN        = socklen_t
-endif
-CXXFLAGS += -DHAS_PSIGNAL -DLIBCVERSION=$(LIBCVER) -pipe # -Wall -pedantic
-OPT_NORM = -O2
-# if your g++ balks (e.g. SuSE still uses 2.7.2.3)
-#CXXFLAGS += -DHAS_PSIGNAL -DLIBCVERSION=$(LIBCVER) -m486
-LD     = $(CC)
-EXTRALIB = -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic
-endif
-
-#
-# === [3] ======================================================= rules section
-# There is no need to change things below this line.
-CXXFLAGS += -D${SYSTEM} -DMAJOR=${MAJOR} -DMINOR=${MINOR} -DSOCKLEN=${SOCKLEN}
-CFLAGS = $(CXXFLAGS)
-LDFLAGS += $(OPT_NORM)
-
-%.o:%.cc
-       $(CXX) $(CXXFLAGS) $(OPT_NORM) -c $< -o $@
-
-OBJS   = convert.o socket.o signal.o squid-tlv.o copyout.o conffile.o
-SRCS   = $(OBJS:.o=.cc)
-HDRS   = $(OBJS:.o=.hh)
-FILES  = $(SRCS) $(HDRS) Makefile purge.cc hexd.c
-DIST   = $(addprefix purge/,$(FILES) README)
-
-all: purge
-
-purge: $(OBJS) purge.o 
-       $(LD) $(OPT_NORM) $(LDFLAGS) $^ -o $@ $(LOADLIBES) $(EXTRALIB)
-hexd: hexd.o
-       $(CC) $(OPT_NORM) $(LDFLAGS) $^ -o $@ $(LOADLIBES)
-#
-# object file rules, generated with "g++ -MM -E *.cc"
-#
-purge.o: purge.cc $(HDRS)
-       $(CXX) $(CXXFLAGS) $(OPT_NORM) -c $< -o $@
-convert.o: convert.cc convert.hh
-conffile.o: conffile.cc conffile.hh
-signal.o: signal.cc signal.hh
-socket.o: socket.cc socket.hh convert.hh
-squid-tlv.o: squid-tlv.cc squid-tlv.hh
-copyout.o: copyout.cc copyout.hh
-hexd.o: hexd.c
-
-clean:
-       $(RM) *.o
-       if [ "${SYSTEM}" = "IRIX"  ]; then rm -rf ii_files; fi
-       if [ "${SYSTEM}" = "SUNOS" ]; then rm -rf Templates.DB; fi
-       if [ "${SYSTEM}" = "SUNOS" ]; then rm -rf SunWS_cache; fi
-
-distclean: clean
-       $(RM) purge hexd
-
-realclean: distclean
-clobber: distclean
-
-co-all:        $(FILES)
-       echo all checked out
-co-all-lock:
-       co -l $(FILES)
-ci-all:
-       for i in $(FILES); do \
-               test -w $$i && ci $$i; \
-               rm -f $$i; \
-       done
-
-dist: distclean co-all
-       ( cd .. ; gtar cvzf purge-`date +"%Y%m%d"`-src.tar.gz $(DIST) )
-tar: distclean ci-all
-       ( cd .. ; gtar cvzf purge-`date +"%Y%m%d"`-all.tar.gz purge )
diff --git a/tools/purge/Makefile.am b/tools/purge/Makefile.am
new file mode 100644 (file)
index 0000000..4bbecbd
--- /dev/null
@@ -0,0 +1,24 @@
+include $(top_srcdir)/src/Common.am
+
+bin_PROGRAMS = purge
+
+purge_SOURCES = \
+       convert.cc \
+       convert.hh \
+       socket.cc \
+       socket.hh \
+       signal.cc \
+       signal.hh \
+       squid-tlv.cc \
+       squid-tlv.hh \
+       copyout.cc \
+       copyout.hh \
+       conffile.cc \
+       conffile.hh \
+       purge.cc
+
+purge_LDADD = \
+       $(COMPAT_LIB) \
+       $(XTRA_LIBS)
+
+EXTRA_DIST = README
index 0d0353d23073717ecb8a000e8d482f69e2818046..5739d2c5e87142902804ceb5a09aefe05af5eff4 100644 (file)
@@ -260,52 +260,6 @@ Example for verbose output in print-mode:
 /cache1/00/00/000000B7   0      406 7CFCB1D319F158ADC9CFD991BB8F6DCE 397d449b 39bf677b ffffffff 3820abfc 0460     1  http://www.netscape.com/images/nc_vera_tile.gif
 
 
-hexd
-====
-
-The hexd tool let's you conveniently hex dump a file both, in hex char and
-display char columns. Hexd only assumes that characters 0-31,127-159,255
-are not printable.
-
-
-$ ./hexd /cache1/00/00/000000B7 | less -r
-
-00000000: 03 00 00 00 6D 03 00 00-00 10 7C FC B1 D3 19 F1  ....m.....|???.?
-00000010: 58 AD C9 CF D9 91 BB 8F-6D CE 05 00 00 00 18 39  X????.?.m?.....9
-00000020: 7D 44 9B 39 BF 67 7B FF-FF FF FF 38 20 AB FC 00  }D.9?g{....8 ??.
-00000030: 00 00 00 00 01 04 60 04-00 00 00 30 68 74 74 70  ......`....0http
-00000040: 3A 2F 2F 77 77 77 2E 6E-65 74 73 63 61 70 65 2E  ://www.netscape.
-00000050: 63 6F 6D 2F 69 6D 61 67-65 73 2F 6E 63 5F 76 65  com/images/nc_ve
-00000060: 72 61 5F 74 69 6C 65 2E-67 69 66 00 08 48 54 54  ra_tile.gif..HTT
-00000070: 50 2F 31 2E 30 20 32 30-30 20 4F 4B 0D 0A 53 65  P/1.0 200 OK..Se
-00000080: 72 76 65 72 3A 20 4E 65-74 73 63 61 70 65 2D 45  rver: Netscape-E
-00000090: 6E 74 65 72 70 72 69 73-65 2F 33 2E 36 0D 0A 44  nterprise/3.6..D
-000000A0: 61 74 65 3A 20 54 75 65-2C 20 32 35 20 4A 75 6C  ate: Tue, 25 Jul
-000000B0: 20 32 30 30 30 20 30 37-3A 34 31 3A 31 35 20 47   2000 07:41:15 G
-000000C0: 4D 54 0D 0A 43 6F 6E 74-65 6E 74 2D 54 79 70 65  MT..Content-Type
-000000D0: 3A 20 69 6D 61 67 65 2F-67 69 66 0D 0A 4C 61 73  : image/gif..Las
-000000E0: 74 2D 4D 6F 64 69 66 69-65 64 3A 20 57 65 64 2C  t-Modified: Wed,
-000000F0: 20 30 33 20 4E 6F 76 20-31 39 39 39 20 32 31 3A   03 Nov 1999 21:
-00000100: 34 31 3A 31 36 20 47 4D-54 0D 0A 43 6F 6E 74 65  41:16 GMT..Conte
-00000110: 6E 74 2D 4C 65 6E 67 74-68 3A 20 36 37 0D 0A 41  nt-Length: 67..A
-00000120: 63 63 65 70 74 2D 52 61-6E 67 65 73 3A 20 62 79  ccept-Ranges: by
-00000130: 74 65 73 0D 0A 41 67 65-3A 20 31 38 32 37 31 33  tes..Age: 182713
-00000140: 0D 0A 58 2D 43 61 63 68-65 3A 20 48 49 54 20 66  ..X-Cache: HIT f
-00000150: 72 6F 6D 20 63 73 2D 68-61 6E 34 2E 77 69 6E 2D  rom cs-han4.win-
-00000160: 69 70 2E 64 66 6E 2E 64-65 0D 0A 58 2D 43 61 63  ip.dfn.de..X-Cac
-00000170: 68 65 2D 4C 6F 6F 6B 75-70 3A 20 48 49 54 20 66  he-Lookup: HIT f
-00000180: 72 6F 6D 20 63 73 2D 68-61 6E 34 2E 77 69 6E 2D  rom cs-han4.win-
-00000190: 69 70 2E 64 66 6E 2E 64-65 3A 38 30 38 31 0D 0A  ip.dfn.de:8081..
-000001A0: 50 72 6F 78 79 2D 43 6F-6E 6E 65 63 74 69 6F 6E  Proxy-Connection
-000001B0: 3A 20 6B 65 65 70 2D 61-6C 69 76 65 0D 0A 0D 0A  : keep-alive....
-000001C0: 47 49 46 38 39 61 01 00-26 00 A2 00 00 00 00 00  GIF89a..&.?.....
-000001D0: FF FF FF 00 33 66 33 66-99 FF FF FF 00 00 00 00  ....3f3f........
-000001E0: 00 00 00 00 00 21 F9 04-01 00 00 04 00 2C 00 00  .....!?......,..
-000001F0: 00 00 01 00 26 00 00 03-08 38 A2 BC DE F0 C9 A8  ....&....8??????
-00000200: 12 00 3B                                         ..;
-
-
-
 limitations
 ===========
 
index d37aed65bd5cc3a13998ea26f4dd5e65d906b08d..39f8f1a3e1c1160ed5421251b5ef520911776f3f 100644 (file)
@@ -108,7 +108,8 @@ readConfigFile( CacheDirVector& cachedir, const char* fn, FILE* debug )
             // match, please record
             memset( &cd, 0, sizeof(cd) );
             if ( debug ) fprintf( debug, "# match from %d-%d on line %s",
-                                      subs[0].rm_so, subs[0].rm_eo, line );
+                                      (int)subs[0].rm_so, (int)subs[0].rm_eo,
+                                      line );
 
             // terminate line after matched expression
             line[ subs[0].rm_eo ] = '\0';
@@ -123,7 +124,8 @@ readConfigFile( CacheDirVector& cachedir, const char* fn, FILE* debug )
                 // new version, disk type at position 2
                 line[ subs[offset].rm_eo ] = '\0';
                 if ( debug ) fprintf( debug, "# match from %d-%d on \"%s\"\n",
-                                          subs[offset].rm_so, subs[offset].rm_eo,
+                                          (int)subs[offset].rm_so,
+                                          (int)subs[offset].rm_eo,
                                           line+subs[offset].rm_so );
                 if ( strcmp( line + subs[offset].rm_so, "ufs" ) == 0 )
                     cd.type = CacheDir::CDT_UFS;
@@ -139,7 +141,8 @@ readConfigFile( CacheDirVector& cachedir, const char* fn, FILE* debug )
             // extract base directory
             line[ subs[offset].rm_eo ] = '\0';
             if ( debug ) fprintf( debug, "# match from %d-%d on \"%s\"\n",
-                                      subs[offset].rm_so, subs[offset].rm_eo,
+                                      (int)subs[offset].rm_so,
+                                      (int)subs[offset].rm_eo,
                                       line+subs[offset].rm_so );
             cd.base = strdup( line+subs[offset].rm_so );
             offset++;
@@ -147,7 +150,8 @@ readConfigFile( CacheDirVector& cachedir, const char* fn, FILE* debug )
             // extract size information
             line[ subs[offset].rm_eo ] = '\0';
             if ( debug ) fprintf( debug, "# match from %d-%d on \"%s\"\n",
-                                      subs[offset].rm_so, subs[offset].rm_eo,
+                                      (int)subs[offset].rm_so,
+                                      (int)subs[offset].rm_eo,
                                       line+subs[offset].rm_so );
             cd.size = strtoul( line+subs[offset].rm_so, 0, 10 );
             offset++;
@@ -155,7 +159,8 @@ readConfigFile( CacheDirVector& cachedir, const char* fn, FILE* debug )
             // extract 1st level directories
             line[ subs[offset].rm_eo ] = '\0';
             if ( debug ) fprintf( debug, "# match from %d-%d on \"%s\"\n",
-                                      subs[offset].rm_so, subs[offset].rm_eo,
+                                      (int)subs[offset].rm_so,
+                                      (int)subs[offset].rm_eo,
                                       line+subs[offset].rm_so );
             cd.level[0] = strtoul( line+subs[offset].rm_so, 0, 10 );
             offset++;
@@ -163,7 +168,8 @@ readConfigFile( CacheDirVector& cachedir, const char* fn, FILE* debug )
             // extract 2nd level directories
             line[ subs[offset].rm_eo ] = '\0';
             if ( debug ) fprintf( debug, "# match from %d-%d on \"%s\"\n",
-                                      subs[offset].rm_so, subs[offset].rm_eo,
+                                      (int)subs[offset].rm_so,
+                                      (int)subs[offset].rm_eo,
                                       line+subs[offset].rm_so );
             cd.level[1] = strtoul( line+subs[offset].rm_so, 0, 10 );
             offset++;
index e2fc9cc58b70c58b05a9abd4e50ffae42b5a480d..ffb87c4e62520da9a11d1100faf406ea2cfdb543 100644 (file)
 #ifndef _CONFFILE_HH
 #define _CONFFILE_HH
 
+#if !defined(__cplusplus)
 #if defined(__GNUC__) || defined(__GNUG__)
 #pragma interface
 #else
-#ifndef HAS_BOOL
-#define HAS_BOOL
+#ifndef HAVE_BOOL
+#define HAVE_BOOL
 typedef int bool;
 #define false 0
 #define true  1
 #endif
 #endif
+#endif /* __cplusplus */
 
 
 #ifndef DEFAULT_SQUID_CONF
index 189d896b917a120364dfd922533cf98c01f59c64..64238121ce00049fed5a9701ff318dc51e74c8e2 100644 (file)
@@ -57,9 +57,6 @@
 #define SA struct sockaddr
 #endif
 
-static const char* RCS_ID =
-    "$Id$";
-
 const char*
 my_inet_ntoa( const struct in_addr& a, HostAddress output )
 // purpose: thread-safely convert IPv4 address -> ASCII representation
@@ -107,7 +104,7 @@ my_sock_fd2a( int fd, SockAddress buffer, bool peer )
 //          Refer to errno in case of error (usually unconnected fd...)
 {
     struct sockaddr_in socket;
-    SOCKLEN len = sizeof(socket);
+    socklen_t len = sizeof(socket);
 
     if ( (peer ? getpeername( fd, (SA*) &socket, &len ) :
             getsockname( fd, (SA*) &socket, &len )) == -1 )
index 164f135a71a02ea17b963de2a23624246a8732a8..a2d9d40fa71e5764861192e274e0b1e0f857cc1b 100644 (file)
 #ifndef _CONVERT_HH
 #define _CONVERT_HH
 
+#if !defined(__cplusplus)
 #if defined(__GNUC__) || defined(__GNUG__)
 #pragma interface
 #else
-#ifndef HAS_BOOL
-#define HAS_BOOL
-typedef int bool;
+#ifndef HAVE_BOOL
+#define HAVE_BOOL 1
+typedef char bool;
 #define false 0
 #define true  1
 #endif
 #endif
+#endif /* __cplusplus */
 
 #include <sys/types.h>
 #include <sys/socket.h>
index 525094e7466cd6a920b6916a894612bcd30f73a0..b1525f16f897f02145fd098b6deffd24e4de6aa7 100644 (file)
 #pragma implementation
 #endif
 
-#include <assert.h>
-#include <sys/types.h>
+#include "config.h"
+#include "copyout.hh"
+
+//#include <assert.h>
+//#include <sys/types.h>
 #include <sys/stat.h>
 #include <stdio.h>
 #include <string.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <unistd.h>
-
 #include <sys/mman.h>
+
 #ifndef MAP_FILE
 #define MAP_FILE 0
 #endif // MAP_FILE
 
-#include "copyout.hh"
-
-static const char* RCS_ID =
-    "$Id$";
-
 int
 assert_copydir( const char* copydir )
 // purpose: check, if copydir is a directory and that we can write into it.
@@ -132,7 +130,7 @@ copy_out( size_t filesize, size_t metasize, unsigned debug,
     static const char* index = "index.html";
 
     // find hostname part after the scheme (okok, not counting port, etc.)
-    char* ptr = strstr( url, "://" );
+    const char* ptr = strstr( url, "://" );
     if ( ptr == 0 || strlen(ptr) < 4 ) return false;
 
     // create filename to store contents into
@@ -236,12 +234,14 @@ copy_out( size_t filesize, size_t metasize, unsigned debug,
     // seek end of output file ...
     off_t position = lseek( out, filesize-metasize-1, SEEK_SET );
     if ( position == -1 ) {
-        fprintf( stderr, "lseek(%s,%lu): %s\n", filename, filesize-metasize,
+        fprintf( stderr, "lseek(%s,%lu): %s\n", filename,
+                 (unsigned long)filesize-metasize,
                  strerror(errno) );
         BAUTZ(false);
     } else if ( debug & 0x02 ) {
         fprintf( stderr, "# filesize=%lu, metasize=%lu, filepos=%ld\n",
-                 filesize, metasize, position );
+                 (unsigned long)filesize, (unsigned long)metasize,
+                 (long)position );
     }
 
     // ...and write 1 byte there (create a file that length)
index f9fe80a49973e241401d6f36c3e65b69fd8eb183..2b4b6011f6300dfb327deebf0e7498bd162773b9 100644 (file)
 #ifndef _COPYOUT_HH
 #define _COPYOUT_HH
 
+#if !defined(__cplusplus)
 #if defined(__GNUC__) || defined(__GNUG__)
 #pragma interface
 #else
-#ifndef HAS_BOOL
-#define HAS_BOOL
+#ifndef HAVE_BOOL
+#define HAVE_BOOL
 typedef int bool;
 #define false 0
 #define true  1
 #endif
 #endif
+#endif /* __cplusplus */
 
 int
 assert_copydir( const char* copydir );
diff --git a/tools/purge/hexd.c b/tools/purge/hexd.c
deleted file mode 100644 (file)
index af7f8ef..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-#include <ctype.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-
-unsigned char
-xlate( unsigned char ch )
-{
-    return (isprint(ch & 0x7f) ? ch : '.');
-}
-
-typedef struct {
-    int fd, rsize, cursor;
-    size_t bufsize;
-    unsigned char* buffer;
-} InputByByte;
-
-int
-in_open( InputByByte* this, const char* fn, size_t size )
-{
-    if ( (this->fd = open( fn, O_RDONLY )) == -1 ) return -1;
-    if ( (this->buffer=(unsigned char*) malloc(size)) == 0 ) {
-        close(this->fd);
-        return -1;
-    }
-    this->bufsize = size;
-    this->rsize = this->cursor = 0;
-    return 0;
-}
-
-int
-in_get( InputByByte* this )
-/*
- * purpose: read next character
- * returns: 0..255 as valid character, -1 for error, -2 for EOF
- */
-{
-    if ( this->cursor >= this->rsize ) {
-        do {
-            this->rsize = read( this->fd, this->buffer, this->bufsize );
-        } while ( this->rsize == -1 && errno == EINTR );
-        if ( this->rsize > 0 ) this->cursor = 0;
-        else return ((-2) - this->rsize);
-    }
-
-    return this->buffer[this->cursor++];
-}
-
-int
-in_close( InputByByte* this )
-{
-    free((void*) this->buffer);
-    return close(this->fd);
-}
-
-int
-main( int argc, char* argv[] )
-{
-    int ch, i;
-    unsigned line = 0;
-    InputByByte in;
-    char b2[20];
-
-    if ( argc != 2 ) {
-        fprintf( stderr, "Usage: %s filename\n", argv[0] );
-        return 1;
-    }
-
-    if ( in_open(&in,argv[1],32768) == -1 ) {
-        perror( "open" );
-        return 1;
-    }
-
-    for ( ch = in_get(&in); ch >= 0; ) {
-        printf( "%08X: ", line );
-        memset( b2, 0, sizeof(b2) );
-        for ( i=0; i < 16 && ch >= 0; i++ ) {
-            printf( "%02X%c", ch, ((i==7) ? '-' : ' ' ) );
-            b2[i] = xlate(ch);
-            ch = in_get(&in);
-        }
-        line += i;
-        for ( ; i<16; i++ ) fputs("   ",stdout);
-        printf( " %s\n", b2 );
-    }
-
-    return in_close(&in);
-}
-
-
index 4031e933c42bdf3301774b16eb72515e4ce628ef..9535ea2cdaf85284085d74e005932549ae0182ef 100644 (file)
 //
 #if defined(__GNUC__) || defined(__GNUG__)
 #pragma implementation
-#else
-#ifndef HAS_BOOL
-#define HAS_BOOL
-typedef int bool;
-#define false 0
-#define true  1
-#endif
 #endif
 
-#include <assert.h>
+#include "config.h"
+// for xstrdup
+#include "util.h"
+
+//#include <assert.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <dirent.h>
-#include <ctype.h>
+//#include <ctype.h>
 #include <string.h>
-#include <sys/types.h>
+//#include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
 #include <fcntl.h>
@@ -120,15 +117,15 @@ typedef int bool;
 #include <signal.h>
 #include <errno.h>
 
-#if defined(HAS_PSIGNAL) && !defined(LINUX) && !defined(FREEBSD)
+#if HAVE_SIGINFO_H
 #include <siginfo.h>
-#endif // HAS_PSIGNAL
+#endif
 
 #include <netinet/in.h>
 #include <netinet/tcp.h>  // TCP_NODELAY
 #include <arpa/inet.h>
 #include <netdb.h>        // gethostbyname()
-#include <regex.h>
+//#include <regex.h>    //comes via compat.h
 
 #include "convert.hh"
 #include "socket.hh"
@@ -149,7 +146,7 @@ volatile sig_atomic_t term_flag = 0; // 'terminate' is a gcc 2.8.x internal...
 char*  linebuffer = 0;
 size_t buffersize = 16834;
 static char* copydir = 0;
-static unsigned debug = 0;
+static unsigned debugFlag = 0;
 static unsigned purgeMode = 0;
 static bool iamalive = false;
 static bool reminder = false;
@@ -157,8 +154,7 @@ static bool verbose  = false;
 static bool envelope = false;
 static bool no_fork  = false;
 static const char* programname = 0;
-static const char* RCS_ID =
-    "$Id$";
+static const char* RCS_ID = "$Id$";
 
 // ----------------------------------------------------------------------
 
@@ -173,7 +169,7 @@ struct REList {
 };
 
 REList::REList( const char* what, bool doCase )
-        :next(0),data(strdup(what))
+        :next(0),data(xstrdup(what))
 {
     int result = regcomp( &rexp, what,
                           REG_EXTENDED | REG_NOSUB | (doCase ? 0 : REG_ICASE) );
@@ -188,7 +184,7 @@ REList::REList( const char* what, bool doCase )
 REList::~REList()
 {
     if ( next ) delete next;
-    if ( data ) free((void*) data);
+    if ( data ) xfree((void*) data);
     regfree(&rexp);
 }
 
@@ -277,7 +273,7 @@ log_extended( const char* fn, int code, long size, const SquidMetaList* meta )
         }
         md5[32] = '\0'; // terminate string
     } else {
-        sprintf( md5, "%-32s", "(no_md5_data_available)" );
+        snprintf( md5, sizeof(md5), "%-32s", "(no_md5_data_available)" );
     }
 
     char timeb[64];
@@ -285,18 +281,18 @@ log_extended( const char* fn, int code, long size, const SquidMetaList* meta )
         StoreMetaStd temp;
         // make data aligned, avoid SIGBUS on RISC machines (ARGH!)
         memcpy( &temp, findings->data, sizeof(StoreMetaStd) );
-        sprintf( timeb, "%08x %08x %08x %08x %04x %5hu ",
-                 temp.timestamp, temp.lastref,
-                 temp.expires, temp.lastmod, temp.flags, temp.refcount );
+        snprintf( timeb, sizeof(timeb), "%08lx %08lx %08lx %08lx %04x %5hu ",
+                  (unsigned long)temp.timestamp, (unsigned long)temp.lastref,
+                  (unsigned long)temp.expires, (unsigned long)temp.lastmod, temp.flags, temp.refcount );
     } else if ( meta && (findings = meta->search( STORE_META_STD_LFS )) ) {
         StoreMetaStdLFS temp;
         // make data aligned, avoid SIGBUS on RISC machines (ARGH!)
         memcpy( &temp, findings->data, sizeof(StoreMetaStd) );
-        sprintf( timeb, "%08x %08x %08x %08x %04x %5hu ",
-                 temp.timestamp, temp.lastref,
-                 temp.expires, temp.lastmod, temp.flags, temp.refcount );
+        snprintf( timeb, sizeof(timeb), "%08lx %08lx %08lx %08lx %04x %5hu ",
+                  (unsigned long)temp.timestamp, (unsigned long)temp.lastref,
+                  (unsigned long)temp.expires, (unsigned long)temp.lastmod, temp.flags, temp.refcount );
     } else {
-        sprintf( timeb, "%08x %08x %08x %08x %04x %5hu ", -1, -1, -1, -1, 0, 0 );
+        snprintf( timeb, sizeof(timeb), "%08lx %08lx %08lx %08lx %04x %5hu ", (unsigned long)-1, (unsigned long)-1, (unsigned long)-1, (unsigned long)-1, 0, 0 );
     }
 
     // make sure that there is just one printf()
@@ -337,7 +333,7 @@ action( int fd, size_t metasize,
 
     // if we want to copy out the file, do that first of all.
     if ( ::copydir && *copydir && size > 0 )
-        copy_out( st.st_size, metasize, ::debug,
+        copy_out( st.st_size, metasize, ::debugFlag,
                   fn, url, ::copydir, ::envelope );
 
     // do we need to PURGE the file, yes, if purgemode bit#0 was set.
@@ -345,7 +341,7 @@ action( int fd, size_t metasize,
         unsigned long bufsize = strlen(url) + strlen(schablone) + 4;
         char* buffer = new char[bufsize];
 
-        sprintf( buffer, schablone, url );
+        snprintf( buffer, bufsize, schablone, url );
         int sockfd = connectTo( serverHost, serverPort, true );
         if ( sockfd == -1 ) {
             fprintf( stderr, "unable to connect to server: %s\n", strerror(errno) );
@@ -402,7 +398,7 @@ match( const char* fn, const REList* list )
     static const size_t addon = sizeof(unsigned char) + sizeof(unsigned int);
     bool flag = true;
 
-    if ( debug & 0x01 ) fprintf( stderr, "# [3] %s\n", fn );
+    if ( debugFlag & 0x01 ) fprintf( stderr, "# [3] %s\n", fn );
     int fd = open( fn, O_RDONLY );
     if ( fd != -1 ) {
         if ( read(fd,::linebuffer,::buffersize-1) > 60 ) {
@@ -485,7 +481,7 @@ filelevel( const char* directory, const REList* list )
 // returns: true, if every subdir && action was successful.
 {
     struct dirent* entry;
-    if ( debug & 0x01 )
+    if ( debugFlag & 0x01 )
         fprintf( stderr, "# [2] %s\n", directory );
 
     DIR* dir = opendir( directory );
@@ -527,7 +523,7 @@ dirlevel( const char* dirname, const REList* list, bool level=false )
 // warning: this function is once-recursive, no deeper.
 {
     struct dirent* entry;
-    if ( debug & 0x01 )
+    if ( debugFlag & 0x01 )
         fprintf( stderr, "# [%d] %s\n", (level ? 1 : 0), dirname );
 
     DIR* dir = opendir( dirname );
@@ -634,19 +630,19 @@ parseCommandline( int argc, char* argv[], REList*& head,
             break;
         case 'C':
             if ( optarg && *optarg ) {
-                if ( copydir ) free( (void*) copydir );
-                assert( (copydir = strdup(optarg)) );
+                if ( copydir ) xfree( (void*) copydir );
+                assert( (copydir = xstrdup(optarg)) );
             }
             break;
         case 'c':
             if ( optarg && *optarg ) {
-                if ( *conffile ) free((void*) conffile );
-                assert( (conffile = strdup(optarg)) );
+                if ( *conffile ) xfree((void*) conffile );
+                assert( (conffile = xstrdup(optarg)) );
             }
             break;
 
         case 'd':
-            ::debug = strtoul( optarg, 0, 0 );
+            ::debugFlag = strtoul( optarg, 0, 0 );
             break;
 
         case 'E':
@@ -742,7 +738,7 @@ parseCommandline( int argc, char* argv[], REList*& head,
     }
 
     // adjust
-    if ( ! isatty(fileno(stdout)) || (::debug & 0x01) ) ::iamalive = false;
+    if ( ! isatty(fileno(stdout)) || (::debugFlag & 0x01) ) ::iamalive = false;
     if ( head == 0 ) {
         fputs( "There was no regular expression defined. If you intend\n", stderr );
         fputs( "to match all possible URLs, use \"-e .\" instead.\n", stderr );
@@ -761,7 +757,7 @@ parseCommandline( int argc, char* argv[], REList*& head,
         printf( "#\n# Currently active values for %s:\n# %s\n",
                 ::programname, ::RCS_ID );
         printf( "# Debug level       : " );
-        if ( ::debug ) printf( "%#6.4hx", ::debug );
+        if ( ::debugFlag ) printf( "%#6.4hx", ::debugFlag );
         else printf( "production level" ); // printf omits 0x prefix for 0!
         printf( " + %s mode", ::no_fork ? "linear" : "parallel" );
         puts( ::verbose ? " + extra verbosity" : "" );
@@ -846,7 +842,7 @@ main( int argc, char* argv[] )
 {
     // setup variables
     REList* list = 0;
-    char* conffile = strdup( DEFAULT_SQUID_CONF );
+    char* conffile = xstrdup( DEFAULT_SQUID_CONF );
     serverPort = htons(DEFAULTPORT);
     if ( convertHostname(DEFAULTHOST,serverHost) == -1 ) {
         fprintf( stderr, "unable to resolve host %s!\n", DEFAULTHOST );
@@ -873,7 +869,7 @@ main( int argc, char* argv[] )
 
     // try to read squid.conf file to determine all cache_dir locations
     CacheDirVector cdv(0);
-    if ( readConfigFile( cdv, conffile, debug ? stderr : 0 ) > 0 ) {
+    if ( readConfigFile( cdv, conffile, debugFlag ? stderr : 0 ) > 0 ) {
         // there are some valid cache_dir entries.
         // unless forking was forbidden by cmdline option,
         // for a process for each cache_dir entry to remove files.
@@ -885,7 +881,7 @@ main( int argc, char* argv[] )
                 if ( ! dirlevel(i->base,list) )
                     fprintf( stderr, "program terminated due to error: %s",
                              strerror(errno) );
-                free((void*) i->base);
+                xfree((void*) i->base);
             }
         } else {
             // parallel mode, all cache_dir in parallel
@@ -907,7 +903,7 @@ main( int argc, char* argv[] )
                 ::iamalive = false;
             }
 
-            for ( int i=0; i < cdv.size(); ++i ) {
+            for ( size_t i=0; i < cdv.size(); ++i ) {
                 if ( getpid() == getpgrp() ) {
                     // only parent == group leader may fork off new processes
                     if ( (child[i]=fork()) < 0 ) {
@@ -921,11 +917,11 @@ main( int argc, char* argv[] )
                         if ( ! dirlevel(cdv[i].base,list) )
                             fprintf( stderr, "program terminated due to error: %s\n",
                                      strerror(errno) );
-                        free((void*) cdv[i].base);
+                        xfree((void*) cdv[i].base);
                         return 0;
                     } else {
                         // parent mode
-                        if ( ::debug ) printf( "forked child %d\n", (int) child[i] );
+                        if ( ::debugFlag ) printf( "forked child %d\n", (int) child[i] );
                     }
                 }
             }
@@ -933,10 +929,10 @@ main( int argc, char* argv[] )
             // collect the garbase
             pid_t temp;
             int status;
-            for ( int i=0; i < cdv.size(); ++i ) {
+            for ( size_t i=0; i < cdv.size(); ++i ) {
                 while ( (temp=waitpid( (pid_t)-1, &status, 0 )) == -1 )
                     if ( errno == EINTR ) continue;
-                if ( ::debug ) printf( "collected child %d\n", (int) temp );
+                if ( ::debugFlag ) printf( "collected child %d\n", (int) temp );
             }
             delete[] child;
         }
@@ -945,8 +941,8 @@ main( int argc, char* argv[] )
     }
 
     // clean up
-    if ( copydir ) free( (void*) copydir );
-    free((void*) conffile);
+    if ( copydir ) xfree( (void*) copydir );
+    xfree((void*) conffile);
     delete list;
     return 0;
 }
index 3f302d2657ce3dfd157cf4a59799898e8b58e8fb..774ea60a5053b2e5b239658666a2f91c2c759d5a 100644 (file)
 #pragma implementation
 #endif
 
-#include <sys/types.h>
+#include "config.h"
+#include "signal.hh"
+
+//#include <sys/types.h>
 #include <errno.h>
 #include <string.h>
 #include <memory.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <sys/wait.h>
-#include <signal.h>
-
-#include "signal.hh"
-
-static const char* RCS_ID =
-    "$Id$";
-
-#ifndef HAS_PSIGNAL
-#ifdef AIX
-extern const char* const sys_siglist[];
-#define _sys_nsig 64
-#define _sys_siglist sys_siglist
-#endif // AIX
-
-void
-psignal( int sig, const char* msg )
-// purpose: print message, colon, space, signal name and LF.
-// paramtr: sig (IN): signal number
-//          msg (IN): message to prepend
-{
-    if ( msg && *msg ) fprintf( stderr, "%s: ", msg );
-    if ( sig > 0 && sig < _sys_nsig )
-        fprintf( stderr, "%s\n", _sys_siglist[sig] );
-    else
-        fputs( "(unknown)\n", stderr );
-}
-#endif // !HAS_PSIGNAL
+//#include <signal.h>
 
 SigFunc*
 Signal( int signo, SigFunc* newhandler, bool doInterrupt )
@@ -133,15 +110,14 @@ sigChild( int signo )
 {
     pid_t pid;
     int  status = signo; // to stop GNU from complaining...
-    char line[128];
 
     int saveerr = errno;
     while ( (pid = waitpid( -1, &status, WNOHANG )) > 0 ) {
         if ( WIFEXITED(status) ) {
-            sprintf( line, "child (pid=%ld) reaped, status %d\n%c",
+            fprintf( stderr, "child (pid=%ld) reaped, status %d\n%c",
                      (long) pid, WEXITSTATUS(status), 0 );
         } else if ( WIFSIGNALED(status) ) {
-            sprintf( line, "child (pid=%ld) died on signal %d%s\n%c",
+            fprintf( stderr, "child (pid=%ld) died on signal %d%s\n%c",
                      (long) pid, WTERMSIG(status),
 #ifdef WCOREDUMP
                      WCOREDUMP(status) ? " (core generated)" : "",
@@ -150,10 +126,9 @@ sigChild( int signo )
 #endif
                      0 );
         } else {
-            sprintf( line, "detected dead child (pid=%ld), status %d\n%c",
+            fprintf( stderr, "detected dead child (pid=%ld), status %d\n%c",
                      (long) pid, status, 0 );
         }
-        write( STDERR_FILENO, line, strlen(line) );
     }
     errno = saveerr;
 
index b923b740ce771d523409ff2d454d92b840b66da1..8760624b4c1092f13f1a7fcc1273f9ee0e581d4e 100644 (file)
 // Initial revision
 //
 //
+
 #ifndef _SIGNAL_HH
 #define _SIGNAL_HH
 
+#include "config.h"
+
+#if HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+#if !defined(__cplusplus)
 #if defined(__GNUC__) || defined(__GNUG__)
 #pragma interface
 #else
-#ifndef HAS_BOOL
-#define HAS_BOOL
+#ifndef HAVE_BOOL
+#define HAVE_BOOL
 typedef int bool;
 #define false 0
 #define true  1
 #endif
 #endif
+#endif /* __cplusplus */
 
 #if 1 // so far, all systems I know use void
 # define SIGRETTYPE void
@@ -77,14 +86,6 @@ extern "C" {
   typedef SIGRETTYPE SigFunc( SIGPARAM );
 }
 
-#ifndef HAS_PSIGNAL
-void
-psignal( int sig, const char* msg );
-  // purpose: print message, colon, space, signal name and LF.
-  // paramtr: sig (IN): signal number
-  //          msg (IN): message to prepend
-#endif // ! HAS_PSIGNAL
-
 SigFunc*
 Signal( int signo, SigFunc* newhandler, bool doInterrupt );
   // purpose: install reliable signals
index 033ffe7adb4b2b8ad9efcce01c6142c1529d5bcd..129e6d1c2d4e3132f7323c0dd1e398b19226de52 100644 (file)
@@ -60,9 +60,6 @@
 
 #include "convert.hh"
 
-static const char* RCS_ID =
-    "$Id$";
-
 int
 setSocketBuffers( int sockfd, int size )
 // purpose: set socket buffers for both directions to the specified size
@@ -95,7 +92,7 @@ getSocketNoDelay( int sockfd )
 //         -1, if an error occurred (e.g. datagram socket)
 {
     int delay = 0;
-    SOCKLEN len = sizeof(delay);
+    socklen_t len = sizeof(delay);
     if ( getsockopt( sockfd, IPPROTO_TCP, TCP_NODELAY,
                      (char*) &delay, &len ) == -1 ) {
         perror( "# getsockopt( TCP_NODELAY ) failed" );
index e2bec356b85b111bc594caba76eefc2176e0a4fb..e6ef40c0b9371f5c8e8db7dc446c8386264f6859 100644 (file)
 #ifndef _SOCKET_HH
 #define _SOCKET_HH
 
+#if !defined(__cplusplus)
 #if defined(__GNUC__) || defined(__GNUG__)
 #pragma interface
 #else
-#ifndef HAS_BOOL
-#define HAS_BOOL
+#ifndef HAVE_BOOL
+#define HAVE_BOOL
 typedef int bool;
 #define false 0
 #define true  1
 #endif
 #endif
+#endif /* __cplusplus */
 
 #include <sys/types.h>
 #include <sys/socket.h>        // SOMAXCONN
index 55fca054341791d29d2032228a2744bc3c5efc0b..29a53d116890f5211ea07ccc3eb695fb2276c78c 100644 (file)
 #pragma implementation
 #endif
 
-#include <assert.h>
+#include "config.h"
+//#include <assert.h>
 #include "squid-tlv.hh"
 
-static const char* RCS_ID =
-    "$Id$";
-
 SquidTLV::SquidTLV( SquidMetaType _type, size_t _size, void* _data )
         :next(0),size(_size)
 {
index 08765ccccf7bc6087d70b35b2b3ddd584c2b9f02..a8531d2c1907d8154af01da42c90525bd7fe2230 100644 (file)
 #ifndef _SQUID_TLV_HH
 #define _SQUID_TLV_HH
 
+#if !defined(__cplusplus)
 #if defined(__GNUC__) || defined(__GNUG__)
 #pragma interface
 #else
-#ifndef HAS_BOOL
-#define HAS_BOOL
+#ifndef HAVE_BOOL
+#define HAVE_BOOL
 typedef int bool;
 #define false 0
 #define true  1
 #endif
 #endif
+#endif /* __cplusplus */
 
 #include <sys/types.h>
 #include <netinet/in.h>
@@ -66,7 +68,7 @@ enum SquidMetaType {
   STORE_META_VALID,
   STORE_META_VARY_HEADERS,     // Stores Vary request headers
   STORE_META_STD_LFS,          // standard metadata in lfs format
-  STORE_META_OBJSIZE,          // object size, if its known
+  STORE_META_OBJSIZE           // object size, if its known
 };
 
 // taken from Squid-2.x
index 813f15adcf6d65acb31ceb7ab47a64233704a055..e5deb9df420cea035e2b57563bbe5a0946a38529 100644 (file)
@@ -23,6 +23,8 @@ Host header
 local host
 .if !'po4a'hide' .B "] [ \-m"
 method
+.if !'po4a'hide' .B "] [ \-n"
+.if !'po4a'hide' .B "] [ \-N"
 .if !'po4a'hide' .B "] [ \-p"
 port
 .if !'po4a'hide' .B "] [ \-P"
@@ -111,6 +113,18 @@ similar to
 .if !'po4a'hide' .fi
 .
 .if !'po4a'hide' .TP
+.if !'po4a'hide' .B "\-n"
+Proxy Negotiate(Kerberos) authentication.
+.if !'po4a'hide' .nf
+Use kinit username@DOMAIN first to get initial TGS.
+.
+.if !'po4a'hide' .TP
+.if !'po4a'hide' .B "\-N"
+WWW Negotiate(Kerberos) authentication.
+.if !'po4a'hide' .nf
+Use kinit username@DOMAIN first to get initial TGS.
+.
+.if !'po4a'hide' .TP
 .if !'po4a'hide' .B "\-p port"
 Port number of cache.  Default is 3128.
 .
index 581f382c788eff78e9ff826bf5e39fa46188801a..3f6b55dba81e49e64c418dd4eec7870dd706ca3b 100644 (file)
@@ -79,6 +79,51 @@ using namespace Squid;
 #include <getopt.h>
 #endif
 
+#if HAVE_GSSAPI
+#ifdef HAVE_HEIMDAL_KERBEROS
+#ifdef HAVE_GSSAPI_GSSAPI_H
+#include <gssapi/gssapi.h>
+#elif defined(HAVE_GSSAPI_H)
+#include <gssapi.h>
+#else
+#error "GSSAPI header required"
+#endif
+#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
+#else
+#ifdef HAVE_SEAM_KERBEROS
+#ifdef HAVE_GSSAPI_GSSAPI_H
+#include <gssapi/gssapi.h>
+#elif defined(HAVE_GSSAPI_H)
+#include <gssapi.h>
+#else
+#error "GSSAPI header required"
+#endif
+#ifdef HAVE_GSSAPI_GSSAPI_EXT_H
+#include <gssapi/gssapi_ext.h>
+#endif
+#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
+#else /*MIT */
+#ifdef HAVE_GSSAPI_GSSAPI_H
+#include <gssapi/gssapi.h>
+#elif defined(HAVE_GSSAPI_H)
+#include <gssapi.h>
+#else
+#error "GSSAPI header required"
+#endif
+#ifdef HAVE_GSSAPI_GSSAPI_KRB5_H
+#include <gssapi/gssapi_krb5.h>
+#endif
+#ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H
+#include <gssapi/gssapi_generic.h>
+#endif
+#endif
+#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
+#endif
 
 #ifndef BUFSIZ
 #define BUFSIZ         8192
@@ -104,6 +149,13 @@ static SIGHDLR pipe_handler;
 static void set_our_signal(void);
 static ssize_t myread(int fd, void *buf, size_t len);
 static ssize_t mywrite(int fd, void *buf, size_t len);
+
+
+#if HAVE_GSSAPI
+static int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, const char *function);
+static char *GSSAPI_token(const char *server);
+#endif
+
 static int put_fd;
 static char *put_file = NULL;
 
@@ -126,7 +178,11 @@ usage(const char *progname)
     fprintf(stderr,
             "Version: %s\n"
             "Usage: %s [-arsv] [-g count] [-h remote host] [-H 'string'] [-i IMS] [-I ping-interval] [-j 'Host-header']"
-            "[-k] [-l local-host] [-m method] [-p port] [-P file] [-t count] [-T timeout] [-u proxy-user] [-U www-user] "
+            "[-k] [-l local-host] [-m method] "
+#if HAVE_GSSAPI
+            "[-n] [-N] "
+#endif
+            "[-p port] [-P file] [-t count] [-T timeout] [-u proxy-user] [-U www-user] "
             "[-V version] [-w proxy-password] [-W www-password] url\n"
             "\n"
             "Options:\n"
@@ -140,6 +196,10 @@ usage(const char *progname)
             "    -k           Keep the connection active. Default is to do only one request then close.\n"
             "    -l host      Specify a local IP address to bind to.  Default is none.\n"
             "    -m method    Request method, default is GET.\n"
+#if HAVE_GSSAPI
+            "    -n           Proxy Negotiate(Kerberos) authentication\n"
+            "    -N           WWW Negotiate(Kerberos) authentication\n"
+#endif
             "    -p port      Port number of cache.  Default is %d.\n"
             "    -P file      PUT request. Using the named file\n"
             "    -r           Force cache to reload URL.\n"
@@ -149,9 +209,9 @@ usage(const char *progname)
             "    -u user      Proxy authentication username\n"
             "    -U user      WWW authentication username\n"
             "    -v           Verbose. Print outgoing message to stderr.\n"
-            "    -V version   HTTP Version. Use '-' for HTTP/0.9 omitted case\n",
+            "    -V version   HTTP Version. Use '-' for HTTP/0.9 omitted case\n"
             "    -w password  Proxy authentication password\n"
-            "    -W password  WWW authentication password\n"
+            "    -W password  WWW authentication password\n",
             VERSION, progname, CACHE_HTTP_PORT);
     exit(1);
 }
@@ -166,6 +226,7 @@ main(int argc, char *argv[])
     int keep_alive = 0;
     int opt_noaccept = 0;
     int opt_verbose = 0;
+    int www_neg, proxy_neg;
     const char *hostname, *localhost;
     Ip::Address iaddr;
     char url[BUFSIZ], msg[MESSAGELEN], buf[BUFSIZ];
@@ -196,6 +257,8 @@ main(int argc, char *argv[])
     ping = 0;
     pcount = 0;
     ping_int = 1 * 1000;
+    www_neg = 0;
+    proxy_neg = 0;
 
     if (argc < 2) {
         usage(argv[0]);                /* need URL */
@@ -205,8 +268,11 @@ main(int argc, char *argv[])
 
         if (url[0] == '-')
             usage(argv[0]);
-
+#if HAVE_GSSAPI
+        while ((c = getopt(argc, argv, "ah:j:V:l:P:i:km:p:rsvt:g:p:I:H:T:u:U:w:W:nN?")) != -1)
+#else
         while ((c = getopt(argc, argv, "ah:j:V:l:P:i:km:p:rsvt:g:p:I:H:T:u:U:w:W:?")) != -1)
+#endif
             switch (c) {
 
             case 'a':
@@ -307,6 +373,15 @@ main(int argc, char *argv[])
                 www_password = optarg;
                 break;
 
+#if HAVE_GSSAPI
+            case 'n':
+                proxy_neg = 1;
+                break;
+
+            case 'N':
+                www_neg = 1;
+                break;
+#endif
             case 'v':
                 /* undocumented: may increase verb-level by giving more -v's */
                 opt_verbose++;
@@ -426,18 +501,28 @@ main(int argc, char *argv[])
             snprintf(buf, BUFSIZ, "Authorization: Basic %s\r\n", base64_encode(buf));
             strcat(msg, buf);
         }
-
-        /* HTTP/1.0 may need keep-alive */
-        if (strcmp(version, "1.0") == 0) {
-            if (keep_alive) {
-                if (strchr(url, ':')) {
-                    snprintf(buf, BUFSIZ, "Proxy-Connection: keep-alive\r\n");
-                    strcat(msg, buf);
-                } else
-                    strcat(msg, "Connection: keep-alive\r\n");
-            }
+#if HAVE_GSSAPI
+        if (www_neg) {
+            if (host) {
+                snprintf(buf, BUFSIZ, "Authorization: Negotiate %s\r\n", GSSAPI_token(host));
+                strcat(msg, buf);
+            } else
+                fprintf(stderr, "ERROR: server host missing\n");
+        }
+        if (proxy_neg) {
+            if (hostname) {
+                snprintf(buf, BUFSIZ, "Proxy-Authorization: Negotiate %s\r\n", GSSAPI_token(hostname));
+                strcat(msg, buf);
+            } else
+                fprintf(stderr, "ERROR: proxy server host missing\n");
         }
-        /* HTTP/1.1 may need close */
+#endif
+
+        /* HTTP/1.0 may need keep-alive explicitly */
+        if (strcmp(version, "1.0") == 0 && keep_alive)
+            strcat(msg, "Connection: keep-alive\r\n");
+
+        /* HTTP/1.1 may need close explicitly */
         if (!keep_alive)
             strcat(msg, "Connection: close\r\n");
 
@@ -736,3 +821,127 @@ mywrite(int fd, void *buf, size_t len)
     return send(fd, buf, len, 0);
 #endif
 }
+
+#if HAVE_GSSAPI
+/*
+ * Check return valuse major_status, minor_status for error and print error description
+ * in case of an error.
+ * Returns 1 in case of gssapi error
+ *         0 in case of no gssapi error
+ */
+#define BUFFER_SIZE 8192
+static 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[BUFFER_SIZE];
+        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) {
+                snprintf(buf + len, BUFFER_SIZE-len, "%s", (char *) status_string.value);
+                len += status_string.length;
+                gss_release_buffer(&min_stat, &status_string);
+                break;
+            }
+            gss_release_buffer(&min_stat, &status_string);
+        }
+        snprintf(buf + len, BUFFER_SIZE-len, "%s", ". ");
+        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) {
+                snprintf(buf + len, BUFFER_SIZE-len,"%s", (char *) status_string.value);
+                len += status_string.length;
+                gss_release_buffer(&min_stat, &status_string);
+                break;
+            }
+            gss_release_buffer(&min_stat, &status_string);
+        }
+        fprintf(stderr, "%s failed: %s\n", function, buf);
+        return (1);
+    }
+    return (0);
+}
+
+/*
+ * Get gssapi token for service HTTP/<server>
+ * User has to initiate a kinit user@DOMAIN on commandline first for the
+ * function to be successful
+ * Returns base64 encoded token if successful
+ *         string "ERROR" if unsuccessful
+ */
+static char *
+GSSAPI_token(const char *server)
+{
+    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 (!server) {
+        fprintf(stderr, "Error: No server name\n");
+        return (char *)"ERROR";
+    }
+    service.value = xmalloc(strlen("HTTP") + strlen(server) + 2);
+    snprintf((char *) service.value, strlen("HTTP") + strlen(server) + 2, "%s@%s", "HTTP", server);
+    service.length = strlen((char *) service.value);
+
+    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()")) {
+
+        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()")) {
+
+            if (output_token.length)
+                token = (char *) base64_encode_bin((const char *) output_token.value, output_token.length);
+        }
+    }
+
+    if (!output_token.length)
+        token = (char *) "ERROR";
+    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;
+}
+#endif