]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Remove squidclient (#1514)
authorFrancesco Chemolli <5175948+kinkie@users.noreply.github.com>
Sat, 21 Oct 2023 09:38:56 +0000 (09:38 +0000)
committerSquid Anubis <squid-anubis@squid-cache.org>
Mon, 23 Oct 2023 04:41:43 +0000 (04:41 +0000)
Since recent commit a4e35bd removed cache_object support, popular
clients like wget and curl can do everything squidclient can, with one
exception: They cannot expand `mgr:foo` macros into
`http://localhost:3128/squid-internal-mgr/foo` URLs. That single feature
is easily emulated and not worth keeping (fairly heavy) squidclient for,
especially since recent Squid security improvements often require
customizing squidclient commands with more and more options (to address
problems tracked in Squid bug 5283).

18 files changed:
configure.ac
doc/release-notes/release-7.sgml.in
mksnapshot.sh
po4a.conf
src/squid.8.in
tools/Makefile.am
tools/cachemgr.cgi.8.in
tools/purge/purge.1
tools/squidclient/Makefile.am [deleted file]
tools/squidclient/Parameters.h [deleted file]
tools/squidclient/Ping.cc [deleted file]
tools/squidclient/Ping.h [deleted file]
tools/squidclient/Transport.cc [deleted file]
tools/squidclient/Transport.h [deleted file]
tools/squidclient/gssapi_support.cc [deleted file]
tools/squidclient/gssapi_support.h [deleted file]
tools/squidclient/squidclient.1 [deleted file]
tools/squidclient/squidclient.cc [deleted file]

index 44c5b88a32062abc9cdde62df3655087f9ec7625..77e079040424d790d7ecf27bd0486851d62ee06a 100644 (file)
@@ -3092,7 +3092,6 @@ AC_CONFIG_FILES([
        tools/apparmor/Makefile
        tools/helper-mux/Makefile
        tools/purge/Makefile
-       tools/squidclient/Makefile
        tools/systemd/Makefile
        tools/sysvinit/Makefile
 ])
index d29658a56bd1b99ad7ce36cb2d2fce5c0d661bb1..e37da79ca5c24e1fa486adf1c08528f95311aa4d 100644 (file)
@@ -44,6 +44,11 @@ The Squid-@SQUID_RELEASE@ change history can be <url url="https://github.com/squ
        <tag>cache_object URI</tag>
        <p>Cache manager is no longer accessible by URIs with cache_object scheme.
 
+    <tag>cachemgr</tag>
+    <p>The 'cachemgr' tool is no longer supported and distributed with squid.
+    A plethora of tools, such as curl, wget, or any web browser,
+    can be used in its place
+
        <tag>non_peers</tag>
        <p>Removed the <em>mgr:non_peers</em> report. Squid still ignores
        unexpected ICP responses but no longer remembers the details that comprised
index b7b9e0813d867519162b79a2032eca1abfcc6e37..3914d72ee32303700efa5293f1683c987a53c052 100755 (executable)
@@ -123,7 +123,7 @@ if (groff --help >/dev/null); then
        if [ ! -d ${tmpdir}/doc/manuals ] ; then
                mkdir -p ${tmpdir}/doc/manuals
        fi
-       for f in `ls -1 ${tmpdir}/helpers/*/*/*.8 ${tmpdir}/src/*.8 ${tmpdir}/src/*/*.8 ${tmpdir}/tools/squidclient/*.1 ${tmpdir}/tools/*.8 ./helpers/*/*/*.8 2>/dev/null` ; do
+       for f in `ls -1 ${tmpdir}/helpers/*/*/*.8 ${tmpdir}/src/*.8 ${tmpdir}/src/*/*.8 ${tmpdir}/tools/*.8 ./helpers/*/*/*.8 2>/dev/null` ; do
                cp $f ${tmpdir}/doc/manuals/
        done
        for f in `ls -1 ${tmpdir}/doc/manuals/*.1  ${tmpdir}/doc/manuals/*.8 2>/dev/null` ; do
index 6c4a041da60ad2de4c47e6c57bd3898914f60413..29a64ff7764c235bbe43637b8ec55fee2f994815 100644 (file)
--- a/po4a.conf
+++ b/po4a.conf
@@ -49,5 +49,3 @@
 [type: man] tools/cachemgr.cgi.8.in $lang:doc/manuals/$lang/cachemgr.cgi.8.in
 
 [type: man] tools/purge/purge.1 $lang:doc/manuals/$lang/purge.1
-
-[type: man] tools/squidclient/squidclient.1 $lang:doc/manuals/$lang/squidclient.1
index f6ece52d45d5844754aa6b626b91b51bc1892225..e460e34cd392e1c6be8fc132ad152c0ffccd7db9 100644 (file)
@@ -282,7 +282,6 @@ Report ideas for new improvements to the
 .
 .SH SEE ALSO
 .if !'po4a'hide' .B cachemgr.cgi "(8), "
-.if !'po4a'hide' .B squidclient "(1), "
 .if !'po4a'hide' .B basic_pam_auth "(8), "
 .if !'po4a'hide' .B basic_ldap_auth "(8), "
 .if !'po4a'hide' .B ext_ldap_group_acl "(8), "
index 155fa9dcea501b1743a6dc52ec31677acba4d133..e17d23a91ded5bfa57b1961866b68ca91a746b4d 100644 (file)
@@ -10,7 +10,7 @@ include $(top_srcdir)/src/Common.am
 ## we need our local files too (but avoid -I. at all costs)
 AM_CPPFLAGS += -I$(srcdir)
 
-SUBDIRS= apparmor helper-mux purge squidclient systemd sysvinit
+SUBDIRS= apparmor helper-mux purge systemd sysvinit
 EXTRA_DIST=
 man_MANS=
 DISTCLEANFILES=
index 34f8f3f1ddb33c50cc7edbb6b34dd8be31f2a298..ebc2b2203cd01cf9c60ff636406d9817df6ad911 100644 (file)
@@ -79,4 +79,3 @@ Report ideas for new improvements to the
 .
 .SH SEE ALSO
 .if !'po4a'hide' .BR squid "(8), "
-.if !'po4a'hide' .BR squidclient "(1)"
index 21dfccd7c09b87612dca14fd0292e1b21dc06ecc..8cb596b3305ed585b5972b8fdde4599d02f3d8ac 100644 (file)
@@ -285,5 +285,4 @@ Report ideas for new improvements to the
 .
 .SH SEE ALSO
 .if !'po4a'hide' .BR squid "(8), "
-.if !'po4a'hide' .BR squidclient "(1)"
 .if !'po4a'hide' .BR cachemgr.cgi "(8)"
diff --git a/tools/squidclient/Makefile.am b/tools/squidclient/Makefile.am
deleted file mode 100644 (file)
index 95c8d50..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-## Copyright (C) 1996-2023 The Squid Software Foundation and contributors
-##
-## Squid software is distributed under GPLv2+ license and includes
-## contributions from numerous individuals and organizations.
-## Please see the COPYING and CONTRIBUTORS files for details.
-##
-
-include $(top_srcdir)/src/Common.am
-
-SUBDIRS =
-EXTRA_DIST = squidclient.1
-man_MANS = squidclient.1
-DISTCLEANFILES =
-
-LDADD = \
-       $(top_builddir)/src/ip/libip.la \
-       $(top_builddir)/src/mem/libminimal.la \
-       $(top_builddir)/src/time/libtime.la \
-       $(top_builddir)/src/base/libbase.la \
-       $(top_builddir)/lib/libmiscencoding.la \
-       $(top_builddir)/lib/libmiscutil.la \
-       $(COMPAT_LIB) \
-       $(LIBGNUTLS_LIBS) \
-       $(LIBNETTLE_LIBS) \
-       $(KRB5LIBS) \
-       $(XTRA_LIBS)
-
-include $(top_srcdir)/doc/manuals/Substitute.am
-
-## Several files need to be shared but we cannot depend on the other
-## directories to be built.
-test_tools.cc: $(top_srcdir)/test-suite/test_tools.cc
-       cp $(top_srcdir)/test-suite/test_tools.cc $@
-
-tests/stub_debug.cc: $(top_srcdir)/src/tests/stub_debug.cc | tests
-       cp $(top_srcdir)/src/tests/stub_debug.cc $@
-
-tests/STUB.h: $(top_srcdir)/src/tests/STUB.h | tests
-       cp $(top_srcdir)/src/tests/STUB.h $@
-
-tests:
-       mkdir -p $@
-
-# stock tools for unit tests - library independent versions of dlink_list
-# etc.
-# globals.cc is needed by test_tools.cc.
-# Neither of these should be disted from here.
-TESTSOURCES= test_tools.cc
-CLEANFILES += test_tools.cc tests/stub_debug.cc tests/STUB.h
-
-## ##### squidclient  #####
-
-bin_PROGRAMS = squidclient
-
-squidclient_SOURCES = \
-       Parameters.h \
-       Ping.cc \
-       Ping.h \
-       Transport.cc \
-       Transport.h \
-       gssapi_support.cc \
-       gssapi_support.h \
-       squidclient.cc \
-       test_tools.cc
-
-nodist_squidclient_SOURCES = \
-       tests/stub_debug.cc \
-       tests/STUB.h
diff --git a/tools/squidclient/Parameters.h b/tools/squidclient/Parameters.h
deleted file mode 100644 (file)
index f310ce1..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-#ifndef _SQUID_TOOLS_SQUIDCLIENT_PARAMETERS_H
-#define _SQUID_TOOLS_SQUIDCLIENT_PARAMETERS_H
-
-/**
- * squidclient command line parameters.
- */
-class Parameters
-{
-public:
-    Parameters() : verbosityLevel(0) {}
-
-    /**
-     * What verbosity level to display.
-     *
-     *  0  : display no debug traces
-     *  1  : display outgoing request message
-     *  2+ : display all actions taken
-     */
-    int verbosityLevel;
-};
-
-/// display debug messages at varying verbosity levels
-#define debugVerbose(LEVEL, MESSAGE) \
-    while ((LEVEL) <= scParams.verbosityLevel) {std::cerr << MESSAGE << std::endl; break;}
-
-/// global squidcleint parameters
-extern Parameters scParams;
-
-#endif /* _SQUID_TOOLS_SQUIDCLIENT_PARAMETERS_H */
-
diff --git a/tools/squidclient/Ping.cc b/tools/squidclient/Ping.cc
deleted file mode 100644 (file)
index 536a6c6..0000000
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-#include "squid.h"
-#include "time/gadgets.h"
-#include "tools/squidclient/Parameters.h"
-#include "tools/squidclient/Ping.h"
-
-#include <climits>
-#include <csignal>
-#include <iostream>
-
-#if HAVE_GETOPT_H
-#include <getopt.h>
-#endif
-
-namespace Ping
-{
-Ping::TheConfig Config;
-
-/// measurements collected by the squidclient ping mode logics
-class pingStats_
-{
-public:
-    pingStats_() {memset(this, 0, sizeof(pingStats_));}
-
-    long counted;  ///< number of transactions which have so far been measured
-    long pMin;     ///< shortest transaction time seen
-    long pMax;     ///< longest transaction time seen
-    long sum;      ///< total time so far spent waiting on transactions
-
-} stats;
-
-} // namespace Ping
-
-/**
- * Signal interrupt handler for squidclient ping.
- * Displays final statistics and disables further pings.
- */
-static void
-catchSignal(int sig)
-{
-    Ping::DisplayStats();
-    Ping::Config.enable = false;
-    std::cerr << "SIGNAL " << sig << " Interrupted." << std::endl;
-}
-
-uint32_t
-Ping::Init()
-{
-    if (Ping::Config.enable) {
-#if HAVE_SIGACTION
-        struct sigaction sa, osa;
-        if (sigaction(SIGINT, nullptr, &osa) == 0 && osa.sa_handler == SIG_DFL) {
-            sa.sa_handler = catchSignal;
-            sa.sa_flags = 0;
-            sigemptyset(&sa.sa_mask);
-            (void) sigaction(SIGINT, &sa, nullptr);
-        }
-#else
-        void (*osig) (int);
-        if ((osig = signal(SIGINT, catchSignal)) != SIG_DFL)
-            (void) signal(SIGINT, osig);
-#endif
-        return Ping::Config.count;
-    }
-
-    return 1;
-}
-
-static struct timeval tv1, tv2;
-
-void
-Ping::TimerStart()
-{
-    if (!Ping::Config.enable)
-        return;
-
-#if GETTIMEOFDAY_NO_TZP
-    (void)gettimeofday(&tv1);
-#else
-    (void)gettimeofday(&tv1, nullptr);
-#endif
-}
-
-void
-Ping::TimerStop(size_t fsize)
-{
-    if (!Ping::Config.enable)
-        return;
-
-    struct tm *tmp;
-    time_t t2s;
-    long elapsed_msec;
-
-#if GETTIMEOFDAY_NO_TZP
-    (void)gettimeofday(&tv2);
-#else
-    (void)gettimeofday(&tv2, nullptr);
-#endif
-
-    elapsed_msec = tvSubMsec(tv1, tv2);
-    t2s = tv2.tv_sec;
-    tmp = localtime(&t2s);
-    char tbuf[4096];
-    snprintf(tbuf, sizeof(tbuf)-1, "%d-%02d-%02d %02d:%02d:%02d [%ld]: %ld.%03ld secs, %f KB/s",
-             tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
-             tmp->tm_hour, tmp->tm_min, tmp->tm_sec, stats.counted + 1,
-             elapsed_msec / 1000, elapsed_msec % 1000,
-             elapsed_msec ? (double) fsize / elapsed_msec : -1.0);
-    std::cerr << tbuf << std::endl;
-
-    if (!stats.counted || elapsed_msec < stats.pMin)
-        stats.pMin = elapsed_msec;
-
-    if (!stats.counted || elapsed_msec > stats.pMax)
-        stats.pMax = elapsed_msec;
-
-    stats.sum += elapsed_msec;
-
-    ++stats.counted;
-
-    /* Delay until next "ping.interval" boundary */
-    if (!LoopDone(stats.counted) && elapsed_msec < Ping::Config.interval) {
-
-        struct timeval tvs;
-        long msec_left = Ping::Config.interval - elapsed_msec;
-
-        tvs.tv_sec = msec_left / 1000;
-        tvs.tv_usec = (msec_left % 1000) * 1000;
-        select(0, nullptr, nullptr, nullptr, &tvs);
-    }
-}
-
-void
-Ping::DisplayStats()
-{
-    if (Ping::Config.enable && stats.counted) {
-        long mean = stats.sum / stats.counted;
-        std::cerr << std::endl
-                  << stats.counted << " requests, round-trip (secs) min/avg/max = "
-                  << (stats.pMin/1000) << "." << (stats.pMin%1000)
-                  << "/" << (mean/1000) << "." << (mean%1000)
-                  << "/" << (stats.pMax/1000) << "." << (stats.pMax%1000)
-                  << std::endl;
-    }
-}
-
-void
-Ping::TheConfig::usage()
-{
-    std::cerr << "Ping Mode" << std::endl
-              << "  --ping [options]  Enable ping mode." << std::endl
-              << std::endl
-              << "  options:" << std::endl
-              << "    -g count        Ping iteration count (default, loop until interrupted)." << std::endl
-              << "    -I interval     Ping interval in seconds (default 1 second)." << std::endl
-              << std::endl;
-}
-
-bool
-Ping::TheConfig::parseCommandOpts(int argc, char *argv[], int c, int &optIndex)
-{
-    // to get here --ping was seen
-    enable = true;
-    count = 0;           // default is infinite loop
-    interval = 1 * 1000; // default is 1s intervals
-
-    const char *shortOpStr = "g:I:?";
-
-    // options for controlling squidclient ping mode
-    static struct option pingOptions[] = {
-        {"count",    no_argument, nullptr, 'g'},
-        {"interval", no_argument, nullptr, 'I'},
-        {nullptr, 0, nullptr, 0}
-    };
-
-    int saved_opterr = opterr;
-    opterr = 0; // suppress errors from getopt
-    while ((c = getopt_long(argc, argv, shortOpStr, pingOptions, &optIndex)) != -1) {
-        switch (c) {
-        case 'g':
-            if (optarg)
-                count = atoi(optarg);
-            else {
-                std::cerr << "ERROR: -g ping count missing parameter." << std::endl;
-                usage();
-            }
-            break;
-
-        case 'I':
-            if (!optarg) {
-                std::cerr << "ERROR: -I ping interval missing parameter." << std::endl;
-                usage();
-            } else if ((interval = atoi(optarg) * 1000) <= 0) {
-                std::cerr << "ERROR: -I ping interval out of range (0-" << (INT_MAX/1000) << ")." << std::endl;
-                usage();
-            }
-            break;
-
-        default:
-            // rewind and let the caller handle unknown options
-            --optind;
-            opterr = saved_opterr;
-            return true;
-        }
-    }
-
-    opterr = saved_opterr;
-    return false;
-}
-
diff --git a/tools/squidclient/Ping.h b/tools/squidclient/Ping.h
deleted file mode 100644 (file)
index 3a9c353..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-#ifndef _SQUID_TOOLS_CLIENT_PING_H
-#define _SQUID_TOOLS_CLIENT_PING_H
-
-/**
- * API for looping the squidclient request message
- * repeatedly.
- */
-namespace Ping
-{
-
-/// parameters controlling 'ping' mode message looping.
-class TheConfig
-{
-public:
-    TheConfig() : enable(false), count(0), interval(1*1000) {}
-
-    /// display Ping Options command line help to stderr
-    void usage();
-
-    /**
-     * parse --ping command line options
-     * \return true if there are other options still to parse
-     */
-    bool parseCommandOpts(int argc, char *argv[], int c, int &optIndex);
-
-    bool enable;
-    int count;
-    int interval;
-};
-
-extern TheConfig Config;
-
-/// initialize the squidclient ping mode
-uint32_t Init();
-
-/// whether ping loop is completed at the given iteration.
-inline bool LoopDone(int i)
-{
-    return !Ping::Config.enable || (Ping::Config.count && i >= Ping::Config.count);
-}
-
-/// start timing a new transaction
-void TimerStart();
-
-/// calculate and display the statistics for a complete transaction
-/// \param fsize number of bytes transferred during this transaction (for KB/s measure)
-void TimerStop(size_t fsize);
-
-/// display summary of ping data collected
-void DisplayStats();
-
-} // namespace Ping
-
-#endif /* _SQUID_TOOLS_CLIENT_PING_H */
-
diff --git a/tools/squidclient/Transport.cc b/tools/squidclient/Transport.cc
deleted file mode 100644 (file)
index 8f5a506..0000000
+++ /dev/null
@@ -1,531 +0,0 @@
-/*
- * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-#include "squid.h"
-#include "ip/Address.h"
-#include "ip/tools.h"
-#include "tools/squidclient/Ping.h"
-#include "tools/squidclient/Transport.h"
-
-#if HAVE_GETOPT_H
-#include <getopt.h>
-#endif
-#if HAVE_GNUTLS_X509_H
-#include <gnutls/x509.h>
-#endif
-#include <iostream>
-
-Transport::TheConfig Transport::Config;
-
-/// the current server connection FD
-int conn = -1;
-
-void
-Transport::TheConfig::usage()
-{
-    std::cerr << "Connection Settings" << std::endl
-              << "  -h | --host host     Send message to server on 'host'.  Default is localhost." << std::endl
-              << "  -l | --local host    Specify a local IP address to bind to.  Default is none." << std::endl
-              << "  -p | --port port     Port number on server to contact. Default is " << CACHE_HTTP_PORT << "." << std::endl
-              << "  -T timeout           Timeout in seconds for read/write operations" << std::endl
-#if USE_GNUTLS
-              << "  --https              Use TLS/SSL on the HTTP connection" << std::endl
-              << std::endl
-              << "  TLS options:" << std::endl
-              << "    --anonymous-tls    Use Anonymous TLS. Sets default parameters:" << std::endl
-              << "                         \"PERFORMANCE:+ANON-ECDH:+ANON-DH\"" << std::endl
-              << "    --params=\"...\"   Use the given parameters." << std::endl
-              << "    --cert=FILE        Path to a PEM file holding the client X.509 certificate chain." << std::endl
-              << "                       May be repeated if there are multiple certificates to use for the server." << std::endl
-              << "    --trusted-ca=PATH  Path to a PEM file holding trusted CA certificate(s)." << std::endl
-              << "                       May be repeated." << std::endl
-              << "                       Example path: \"/etc/ssl/certs/ca-certificates.crt\"" << std::endl
-#endif
-              << std::endl;
-}
-
-bool
-Transport::TheConfig::parseCommandOpts(int argc, char *argv[], int c, int &optIndex)
-{
-    bool tls = false;
-    const char *shortOpStr = "h:l:p:T:?";
-
-    // options for controlling squidclient transport connection
-    static struct option longOptions[] = {
-        {"anonymous-tls",no_argument, nullptr, '\1'},
-        {"https",        no_argument, nullptr, '\3'},
-        {"trusted-ca",   required_argument, nullptr, 'A'},
-        {"cert",         required_argument, nullptr, 'C'},
-        {"host",         required_argument, nullptr, 'h'},
-        {"local",        required_argument, nullptr, 'l'},
-        {"port",         required_argument, nullptr, 'p'},
-        {"params",       required_argument, nullptr, 'P'},
-        {nullptr, 0, nullptr, 0}
-    };
-
-    int saved_opterr = opterr;
-    opterr = 0; // suppress errors from getopt
-    do {
-        switch (c) {
-        case '\1':
-            tls = true;
-            tlsAnonymous = true;
-            params = "PERFORMANCE:+ANON-ECDH:+ANON-DH";
-            break;
-
-        case '\3':
-            tls = true;
-            break;
-
-        case 'A':
-            tls = true;
-            caFiles.push_back(std::string(optarg));
-            break;
-
-        case 'C':
-            tls = true;
-            certFiles.push_back(std::string(optarg));
-            break;
-
-        case 'h':
-            hostname = optarg;
-            break;
-
-        case 'l':
-            localHost = optarg;
-            break;
-
-        case 'p':           /* port number */
-            sscanf(optarg, "%hd", &port);
-            if (port < 1)
-                port = CACHE_HTTP_PORT;     /* default */
-            break;
-
-        case 'P':
-            tls = true;
-            params = optarg;
-            break;
-
-        case 'T':
-            ioTimeout = atoi(optarg);
-            break;
-
-        default:
-            if (tls)
-                Transport::InitTls();
-
-            // rewind and let the caller handle unknown options
-            --optind;
-            opterr = saved_opterr;
-            return true;
-        }
-    } while ((c = getopt_long(argc, argv, shortOpStr, longOptions, &optIndex)) != -1);
-
-    if (tls)
-        Transport::InitTls();
-
-    opterr = saved_opterr;
-    return false;
-}
-
-/// Set up the source socket address from which to send.
-static int
-client_comm_bind(int sock, const Ip::Address &addr)
-{
-    static struct addrinfo *AI = nullptr;
-    addr.getAddrInfo(AI);
-    int res = bind(sock, AI->ai_addr, AI->ai_addrlen);
-    Ip::Address::FreeAddr(AI);
-    return res;
-}
-
-static void
-resolveDestination(Ip::Address &iaddr)
-{
-    struct addrinfo *AI = nullptr;
-
-    debugVerbose(2, "Transport detected: IPv4" <<
-                 ((Ip::EnableIpv6 & IPV6_SPECIAL_V4MAPPING) ? "-mapped " : "") <<
-                 (Ip::EnableIpv6 == IPV6_OFF ? "-only" : " and IPv6") <<
-                 ((Ip::EnableIpv6 & IPV6_SPECIAL_SPLITSTACK) ? " split-stack" : ""));
-
-    if (Transport::Config.localHost) {
-        debugVerbose(2, "Resolving " << Transport::Config.localHost << " ...");
-
-        if ( !iaddr.GetHostByName(Transport::Config.localHost) ) {
-            std::cerr << "ERROR: Cannot resolve " << Transport::Config.localHost << ": Host unknown." << std::endl;
-            exit(1);
-        }
-    } else {
-        debugVerbose(2, "Resolving " << Transport::Config.hostname << " ...");
-        /* Process the remote host name to locate the Protocol required
-           in case we are being asked to link to another version of squid */
-        if ( !iaddr.GetHostByName(Transport::Config.hostname) ) {
-            std::cerr << "ERROR: Cannot resolve " << Transport::Config.hostname << ": Host unknown." << std::endl;
-            exit(1);
-        }
-    }
-
-    iaddr.getAddrInfo(AI);
-    if ((conn = socket(AI->ai_family, AI->ai_socktype, 0)) < 0) {
-        std::cerr << "ERROR: could not open socket to " << iaddr << std::endl;
-        Ip::Address::FreeAddr(AI);
-        exit(1);
-    }
-    Ip::Address::FreeAddr(AI);
-
-    if (Transport::Config.localHost) {
-        if (client_comm_bind(conn, iaddr) < 0) {
-            std::cerr << "ERROR: could not bind socket to " << iaddr << std::endl;
-            exit(1);
-        }
-
-        iaddr.setEmpty();
-
-        debugVerbose(2, "Resolving... " << Transport::Config.hostname);
-
-        if ( !iaddr.GetHostByName(Transport::Config.hostname) ) {
-            std::cerr << "ERROR: Cannot resolve " << Transport::Config.hostname << ": Host unknown." << std::endl;
-            exit(1);
-        }
-    }
-
-    iaddr.port(Transport::Config.port);
-}
-
-/// Set up the destination socket address for message to send to.
-static int
-client_comm_connect(int sock, const Ip::Address &addr)
-{
-    static struct addrinfo *AI = nullptr;
-    addr.getAddrInfo(AI);
-    int res = connect(sock, AI->ai_addr, AI->ai_addrlen);
-    Ip::Address::FreeAddr(AI);
-    Ping::TimerStart();
-    return res;
-}
-
-bool
-Transport::Connect()
-{
-    Ip::Address iaddr;
-    resolveDestination(iaddr);
-
-    debugVerbose(2, "Connecting... " << Config.hostname << " (" << iaddr << ")");
-
-    if (client_comm_connect(conn, iaddr) < 0) {
-        char hostnameBuf[MAX_IPSTRLEN];
-        iaddr.toUrl(hostnameBuf, MAX_IPSTRLEN);
-        std::cerr << "ERROR: Cannot connect to " << hostnameBuf
-                  << (!errno ?": Host unknown." : "") << std::endl;
-        exit(1);
-    }
-    debugVerbose(2, "Connected to: " << Config.hostname << " (" << iaddr << ")");
-
-    // do any TLS setup that might be needed
-    if (!Transport::MaybeStartTls(Config.hostname))
-        return false;
-
-    return true;
-}
-
-ssize_t
-Transport::Write(const void *buf, size_t len)
-{
-    if (conn < 0)
-        return -1;
-
-    if (Config.tlsEnabled) {
-#if USE_GNUTLS
-        gnutls_record_send(Config.session, buf, len);
-        return len;
-#else
-        return 0;
-#endif
-    } else {
-
-#if _SQUID_WINDOWS_
-        return send(conn, buf, len, 0);
-#else
-        alarm(Config.ioTimeout);
-        return write(conn, buf, len);
-#endif
-    }
-}
-
-ssize_t
-Transport::Read(void *buf, size_t len)
-{
-    if (conn < 0)
-        return -1;
-
-    if (Config.tlsEnabled) {
-#if USE_GNUTLS
-        return gnutls_record_recv(Config.session, buf, len);
-#else
-        return 0;
-#endif
-    } else {
-
-#if _SQUID_WINDOWS_
-        return recv(conn, buf, len, 0);
-#else
-        alarm(Config.ioTimeout);
-        return read(conn, buf, len);
-#endif
-    }
-}
-
-void
-Transport::CloseConnection()
-{
-    (void) close(conn);
-    conn = -1;
-}
-
-#if USE_GNUTLS
-/* This function will verify the peer's certificate, and check
- * if the hostname matches, as well as the activation, expiration dates.
- */
-static int
-verifyByCA(gnutls_session_t session)
-{
-    /* read hostname */
-    const char *hostname = static_cast<const char*>(gnutls_session_get_ptr(session));
-
-    /* This verification function uses the trusted CAs in the credentials
-     * structure. So you must have installed one or more CA certificates.
-     */
-    unsigned int status;
-    if (gnutls_certificate_verify_peers3(session, hostname, &status) < 0) {
-        std::cerr << "VERIFY peers failure";
-        return GNUTLS_E_CERTIFICATE_ERROR;
-    }
-
-    gnutls_certificate_type_t type = gnutls_certificate_type_get(session);
-    gnutls_datum_t out;
-    if (gnutls_certificate_verification_status_print(status, type, &out, 0) < 0) {
-        std::cerr << "VERIFY status failure";
-        return GNUTLS_E_CERTIFICATE_ERROR;
-    }
-
-    std::cerr << "VERIFY DATUM: " << out.data << std::endl;
-    gnutls_free(out.data);
-
-    if (status != 0)        /* Certificate is not trusted */
-        return GNUTLS_E_CERTIFICATE_ERROR;
-
-    /* notify gnutls to continue handshake normally */
-    return GNUTLS_E_SUCCESS;
-}
-
-static int
-verifyTlsCertificate(gnutls_session_t session)
-{
-    // XXX: 1) try to verify using DANE -> Secure Authenticated Connection
-
-    // 2) try to verify using CA
-    if (verifyByCA(session) == GNUTLS_E_SUCCESS) {
-        std::cerr << "SUCCESS: CA verified Encrypted Connection" << std::endl;
-        return GNUTLS_E_SUCCESS;
-    }
-
-    // 3) fails both is insecure, but show the results anyway.
-    std::cerr << "WARNING: Insecure Connection" << std::endl;
-    return GNUTLS_E_SUCCESS;
-}
-#endif
-
-#if USE_GNUTLS
-static void
-gnutlsDebugHandler(int level, const char *msg)
-{
-    debugVerbose(level, "GnuTLS: " << msg);
-}
-#endif
-
-void
-Transport::InitTls()
-{
-#if USE_GNUTLS
-    debugVerbose(3, "Initializing TLS library...");
-    // NP: gnutls init is re-entrant and lock-counted with deinit but not thread safe.
-    if (gnutls_global_init() != GNUTLS_E_SUCCESS) {
-        int xerrno = errno;
-        std::cerr << "FATAL ERROR: TLS Initialize failed: " << xstrerr(xerrno) << std::endl;
-        exit(1);
-    }
-
-    Config.tlsEnabled = true;
-
-#if USE_GNUTLS
-    gnutls_global_set_log_function(&gnutlsDebugHandler);
-    gnutls_global_set_log_level(scParams.verbosityLevel);
-#endif
-
-    // Initialize for anonymous TLS
-    gnutls_anon_allocate_client_credentials(&Config.anonCredentials);
-
-    // Initialize for X.509 certificate exchange
-    gnutls_certificate_allocate_credentials(&Config.certCredentials);
-    for (std::list<std::string>::const_iterator i = Config.caFiles.begin(); i != Config.caFiles.end(); ++i) {
-        int x = gnutls_certificate_set_x509_trust_file(Config.certCredentials, (*i).c_str(), GNUTLS_X509_FMT_PEM);
-        if (x < 0) {
-            debugVerbose(3, "WARNING: Failed to load Certificate Authorities from " << *i);
-        } else {
-            debugVerbose(3, "Loaded " << x << " Certificate Authorities from " << *i);
-        }
-    }
-    gnutls_certificate_set_verify_function(Config.certCredentials, verifyTlsCertificate);
-
-    for (std::list<std::string>::const_iterator i = Config.certFiles.begin(); i != Config.certFiles.end(); ++i) {
-        if (gnutls_certificate_set_x509_key_file(Transport::Config.certCredentials, (*i).c_str(), (*i).c_str(), GNUTLS_X509_FMT_PEM) != GNUTLS_E_SUCCESS) {
-            debugVerbose(3, "WARNING: Failed to load Certificate from " << *i);
-        } else {
-            debugVerbose(3, "Loaded Certificate from " << *i);
-        }
-    }
-
-#else
-    std::cerr << "ERROR: TLS support not available." << std::endl;
-#endif
-}
-
-#if USE_GNUTLS
-
-// perform the actual handshake exchange with remote server
-static bool
-doTlsHandshake(const char *type)
-{
-    // setup the connection for TLS
-    gnutls_transport_set_int(Transport::Config.session, conn);
-    gnutls_handshake_set_timeout(Transport::Config.session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
-
-    debugVerbose(2, type << " TLS handshake ... ");
-
-    int ret = 0;
-    do {
-        ret = gnutls_handshake(Transport::Config.session);
-    } while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
-
-    if (ret < 0) {
-        std::cerr << "ERROR: " << type << " TLS Handshake failed (" << ret << ") "
-                  << gnutls_alert_get_name(gnutls_alert_get(Transport::Config.session))
-                  << std::endl;
-        gnutls_perror(ret);
-        gnutls_deinit(Transport::Config.session);
-        return false;
-    }
-
-    char *desc = gnutls_session_get_desc(Transport::Config.session);
-    debugVerbose(3, "TLS Session info: " << std::endl << desc << std::endl);
-    gnutls_free(desc);
-    return true;
-}
-
-static bool
-loadTlsParameters()
-{
-    const char *err = nullptr;
-    int x;
-    if ((x = gnutls_priority_set_direct(Transport::Config.session, Transport::Config.params, &err)) != GNUTLS_E_SUCCESS) {
-        if (x == GNUTLS_E_INVALID_REQUEST)
-            std::cerr << "ERROR: Syntax error at: " << err << std::endl;
-        gnutls_perror(x);
-        return false;
-    }
-    return true;
-}
-
-// attempt an anonymous TLS handshake
-// this encrypts the connection but does not secure it
-// so many public servers do not support this handshake type.
-static bool
-tryTlsAnonymous()
-{
-    if (!loadTlsParameters())
-        return false;
-
-    // put the anonymous credentials to the current session
-    int x;
-    if ((x = gnutls_credentials_set(Transport::Config.session, GNUTLS_CRD_ANON, Transport::Config.anonCredentials)) != GNUTLS_E_SUCCESS) {
-        std::cerr << "ERROR: Anonymous TLS credentials setup failed (" << x << ") " << std::endl;
-        gnutls_perror(x);
-        return false;
-    }
-
-    return doTlsHandshake("Anonymous");
-}
-
-// attempt a X.509 certificate exchange
-// this both encrypts and authenticates the connection
-static bool
-tryTlsCertificate(const char *hostname)
-{
-    gnutls_session_set_ptr(Transport::Config.session, (void *) hostname);
-    gnutls_server_name_set(Transport::Config.session, GNUTLS_NAME_DNS, hostname, strlen(hostname));
-
-    if (!loadTlsParameters())
-        return false;
-
-    // put the X.509 credentials to the current session
-    gnutls_credentials_set(Transport::Config.session, GNUTLS_CRD_CERTIFICATE, Transport::Config.certCredentials);
-
-    // setup the connection for TLS
-    gnutls_transport_set_int(Transport::Config.session, conn);
-    gnutls_handshake_set_timeout(Transport::Config.session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
-
-    return doTlsHandshake("X.509");
-}
-#endif
-
-bool
-Transport::MaybeStartTls(const char *hostname)
-{
-#if USE_GNUTLS
-    if (Config.tlsEnabled) {
-
-        // Initialize TLS session
-        gnutls_init(&Transport::Config.session, GNUTLS_CLIENT);
-
-        if (Transport::Config.tlsAnonymous && !tryTlsAnonymous()) {
-            gnutls_deinit(Config.session);
-            return false;
-        }
-
-        if (!tryTlsCertificate(hostname)) {
-            gnutls_deinit(Config.session);
-            return false;
-        }
-    }
-#else
-    (void)hostname;
-#endif
-    return true;
-}
-
-void
-Transport::ShutdownTls()
-{
-#if USE_GNUTLS
-    if (!Config.tlsEnabled)
-        return;
-
-    debugVerbose(3, "Shutting down TLS library...");
-
-    // release any existing session and credentials
-    gnutls_deinit(Config.session);
-    gnutls_anon_free_client_credentials(Config.anonCredentials);
-    gnutls_certificate_free_credentials(Config.certCredentials);
-
-    // NP: gnutls init is re-entrant and lock-counted with deinit but not thread safe.
-    gnutls_global_deinit();
-    Config.tlsEnabled = false;
-#endif
-}
-
diff --git a/tools/squidclient/Transport.h b/tools/squidclient/Transport.h
deleted file mode 100644 (file)
index 66902ab..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-#ifndef SQUID_TOOLS_SQUIDCLIENT_TRANSPORT_H
-#define SQUID_TOOLS_SQUIDCLIENT_TRANSPORT_H
-
-#include "tools/squidclient/Parameters.h"
-
-#if HAVE_GNUTLS_GNUTLS_H
-#include <gnutls/gnutls.h>
-#endif
-#include <list>
-#include <string>
-
-namespace Transport
-{
-
-/// parameters controlling outgoing connection
-class TheConfig
-{
-public:
-    TheConfig() :
-        ioTimeout(120),
-        localHost(nullptr),
-        port(CACHE_HTTP_PORT),
-        tlsEnabled(false),
-        tlsAnonymous(false) {
-        params = "NORMAL";
-        hostname = "localhost";
-    }
-
-// TODO: implicit transport options depending on the protocol-specific options
-//     ie --https enables TLS connection settings
-
-    /// display Transport Options command line help to stderr
-    void usage();
-
-    /**
-     * parse transport related command line options
-     * \return true if there are other options still to parse
-     */
-    bool parseCommandOpts(int argc, char *argv[], int c, int &optIndex);
-
-    /// I/O operation timeout
-    int ioTimeout;
-
-    /// the local hostname to bind as for outgoing IP
-    const char *localHost;
-
-    /// the destination server host name to contact
-    const char *hostname;
-
-    /// port on the server to contact
-    uint16_t port;
-
-    /// whether to enable TLS on the server connection
-    bool tlsEnabled;
-
-    /// whether to do anonymous TLS (non-authenticated)
-    bool tlsAnonymous;
-
-    /// The TLS parameters (list of ciphers, versions, flags)
-    /// Default is "NORMAL" unless tlsAnonymous is used,
-    /// in which case it becomes "PERFORMANCE:+ANON-ECDH:+ANON-DH".
-    /// see http://gnutls.org/manual/html_node/Priority-Strings.html
-    const char *params;
-
-    // client certificate PEM file(s)
-    std::list<std::string> certFiles;
-
-    // client trusted x509 certificate authorities file
-    std::list<std::string> caFiles;
-
-#if USE_GNUTLS
-    /// anonymous client credentials
-    gnutls_anon_client_credentials_t anonCredentials;
-
-    // client x509 certificate credentials
-    gnutls_certificate_credentials_t certCredentials;
-
-    /// TLS session state
-    gnutls_session_t session;
-#endif
-};
-
-extern TheConfig Config;
-
-/// locate and connect to the configured server
-bool Connect();
-
-/// close the current connection
-void CloseConnection();
-
-/// Initialize TLS library environment when necessary.
-void InitTls();
-
-/// perform TLS handshake on the currently open connection if
-/// TLS library has been initialized.
-/// return false on errors, true otherwise even if TLS not performed.
-bool MaybeStartTls(const char *hostname);
-
-/// De-initialize TLS library environment when necessary.
-void ShutdownTls();
-
-/// write len bytes to the currently open connection.
-/// \return the number of bytes written, or -1 on errors
-ssize_t Write(const void *buf, size_t len);
-
-/// read up to len bytes from the currently open connection.
-/// \return the number of bytes read, or -1 on errors
-ssize_t Read(void *buf, size_t len);
-
-} // namespace Transport
-
-#endif /* SQUID_TOOLS_SQUIDCLIENT_TRANSPORT_H */
-
diff --git a/tools/squidclient/gssapi_support.cc b/tools/squidclient/gssapi_support.cc
deleted file mode 100644 (file)
index e76c0ed..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-#include "squid.h"
-
-#if HAVE_GSSAPI
-
-#include "base64.h"
-#include "tools/squidclient/gssapi_support.h"
-
-#include <iostream>
-
-#if !defined(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
-
-#define BUFFER_SIZE 8192
-
-/**
- * Check return valuse major_status, minor_status for error and print error description
- * in case of an error.
- *
- * \retval true in case of gssapi error
- * \retval false in case of no gssapi error
- */
-bool
-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);
-        }
-        std::cerr << "ERROR: " << function << " failed: " << buf << std::endl;
-        return true;
-    }
-    return false;
-}
-
-/**
- * Get gssapi token for service HTTP/<server>
- * User has to initiate a kinit user@DOMAIN on commandline first for the
- * function to be successful
- *
- * \return base64 encoded token if successful,
- *         string "ERROR" if unsuccessful
- */
-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 = nullptr;
-
-    setbuf(stdout, nullptr);
-    setbuf(stdin, nullptr);
-
-    if (!server) {
-        std::cerr << "ERROR: GSSAPI: No server name" << std::endl;
-        token = new char[6];
-        memcpy(token, "ERROR", 5);
-        token[5] = '\0';
-        return token;
-    }
-    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,
-                                            nullptr,
-                                            &output_token,
-                                            nullptr,
-                                            nullptr);
-
-        if (!check_gss_err(major_status, minor_status, "gss_init_sec_context()") && output_token.length) {
-            token = new char[base64_encode_len(output_token.length)];
-            struct base64_encode_ctx ctx;
-            base64_encode_init(&ctx);
-            size_t blen = base64_encode_update(&ctx, token, output_token.length, reinterpret_cast<const uint8_t*>(output_token.value));
-            blen += base64_encode_final(&ctx, token+blen);
-            token[blen] = '\0';
-        }
-    }
-
-    if (!output_token.length) {
-        token = new char[6];
-        memcpy(token, "ERROR", 5);
-        token[5] = '\0';
-    }
-
-    gss_delete_sec_context(&minor_status, &gss_context, nullptr);
-    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 /* HAVE_GSSAPI */
-
diff --git a/tools/squidclient/gssapi_support.h b/tools/squidclient/gssapi_support.h
deleted file mode 100644 (file)
index b824e75..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-#ifndef _SQUID_TOOLS_SQUIDCLIENT_GSSAPI_H
-#define _SQUID_TOOLS_SQUIDCLIENT_GSSAPI_H
-
-#if HAVE_GSSAPI
-#if USE_APPLE_KRB5
-#define GSSKRB_APPLE_DEPRECATED(x)
-#endif
-
-#if USE_HEIMDAL_KRB5
-#if HAVE_GSSAPI_GSSAPI_H
-#include <gssapi/gssapi.h>
-#elif HAVE_GSSAPI_H
-#include <gssapi.h>
-#endif /* HAVE_GSSAPI_GSSAPI_H/HAVE_GSSAPI_H */
-#elif USE_GNUGSS
-#if HAVE_GSS_H
-#include <gss.h>
-#endif
-#else
-#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_GSSAPI_GSSAPI_KRB5_H
-#include <gssapi/gssapi_krb5.h>
-#endif
-#if HAVE_GSSAPI_GSSAPI_GENERIC_H
-#include <gssapi/gssapi_generic.h>
-#endif
-#if HAVE_GSSAPI_GSSAPI_EXT_H
-#include <gssapi/gssapi_ext.h>
-#endif
-#endif
-
-#ifndef gss_nt_service_name
-#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
-#endif
-
-bool check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, const char *function);
-char *GSSAPI_token(const char *server);
-
-#endif /* HAVE_GSSAPI */
-#endif /* _SQUID_TOOLS_SQUIDCLIENT_GSSAPI_H */
-
diff --git a/tools/squidclient/squidclient.1 b/tools/squidclient/squidclient.1
deleted file mode 100644 (file)
index 08ed2e7..0000000
+++ /dev/null
@@ -1,264 +0,0 @@
-.if !'po4a'hide' .TH squidclient 1
-.
-.SH NAME
-squidclient \- A simple HTTP web client tool
-.
-.SH SYNOPSIS
-.if !'po4a'hide' .B squidclient
-.if !'po4a'hide' .B "[ \-aknNrsv ] "
-.if !'po4a'hide' .B "[ \-\-ping [ping\-options] ] "
-.if !'po4a'hide' .B "[ \-\-https] [tls\-options] [ \-A"
-string
-.if !'po4a'hide' .B "] [ \-h | \-\-host"
-remote host
-.if !'po4a'hide' .B "] [ \-H '"
-string
-.if !'po4a'hide' .B "' ] [ \-i"
-IMS
-.if !'po4a'hide' .B "] [ \-j '"
-Host header
-.if !'po4a'hide' .B "' ] [ \-l | \-\-local"
-host
-.if !'po4a'hide' .B "] [ \-m"
-method
-.if !'po4a'hide' .B "] [ \-p | \-\-port"
-port
-.if !'po4a'hide' .B "] [ \-P"
-file
-.if !'po4a'hide' .B "] [ \-t"
-count
-.if !'po4a'hide' .B "] [ \-T"
-timeout
-.if !'po4a'hide' .B "] [ \-u"
-user
-.if !'po4a'hide' .B "] [ \-U"
-user
-.if !'po4a'hide' .B "] [ \-V"
-version
-.if !'po4a'hide' .B "] [ \-w"
-password
-.if !'po4a'hide' .B "] [ \-W"
-password
-.if !'po4a'hide' .B "] "
-url
-.
-.PP
-.if !'po4a'hide' .B "Ping options: [ \-g"
-count
-.if !'po4a'hide' .B "] [ \-I"
-interval
-.if !'po4a'hide' .B "] "
-.
-.PP
-.if !'po4a'hide' .B "TLS options: [ \-\-anonymous\-tls ] [ \-\-trusted\-ca"
-CA certificates file
-.if !'po4a'hide' .B "...] [ \-\-cert"
-client X.509 certificate file
-.if !'po4a'hide' .B "] [ \-\-params"
-TLS session parameters
-.if !'po4a'hide' .B "] "
-.
-.SH DESCRIPTION
-.B squidclient
-is a tool providing a command line interface for retrieving URLs.
-Designed for testing any HTTP 0.9, 1.0, or 1.1 web server or proxy.
-This tool can be combined with scripts to perform any basic HTTP operation.
-Some additional features for access to the 
-.B squid
-proxy object cache and management information are provided.
-.
-.SH OPTIONS
-.if !'po4a'hide' .TP 12
-.if !'po4a'hide' .B "\-a"
-Do NOT include Accept: header.
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-A 'string'"
-Send 
-.B string
-as User-Agent: header. To omit the header completely set string to empty ('').
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-h | \-\-host host"
-Retrieve URL from server host.  Default is
-.B localhost
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-H 'string'"
-Extra headers to send. Use
-.B '\en'
-for new lines.
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-i time"
-If\-Modified\-Since time (in Epoch seconds).
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-j hosthdr"
-Host header content
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-k"
-Keep the connection active. Default is to do only one request then close.
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-l | \-\-local host"
-Specify a local IP address to bind to.  Default is none.
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-m method"
-Request method, default is
-.I GET.
-Squid also supports a non-standard method called
-.I PURGE.
-You can use that to purge a specific URL from the cache.
-You need to have
-.I purge
-access setup in
-.B squid.conf
-similar to
-.I manager
-access. Here is an example:
-.if !'po4a'hide' .nf
-.if !'po4a'hide'       acl purge method PURGE
-.if !'po4a'hide'       http_access deny purge !localhost
-.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' .fi
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-p port"
-Port number of cache.  Default is 3128.
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-P file"
-Request body. Using the named file as data.
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-r"
-Force cache to reload URL.
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-s"
-Silent.  Do not print data to stdout.
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-t count"
-Trace
-.I count
-HTTP relay or proxy hops
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-T timeout"
-Timeout value (seconds) for read/write operations.
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-u user"
-Proxy authentication username
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-U user"
-WWW authentication username
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-v"
-Verbose. Print outgoing message to stderr.
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-V version"
-HTTP Version. Use '\-' for HTTP/0.9 omitted case
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-w password"
-Proxy authentication password
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-W password"
-WWW authentication password
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-\-https"
-Use Transport Layer Security on the HTTP connection.
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-\-anonymous\-tls"
-Use TLS with unauthenticated (anonymous) certificate.
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-\-cert file"
-File containing client X.509 certificate in PEM format.
-May be repeated to load several client certificates.
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-\-trusted\-ca file"
-File containing trusted Certificate Authority (CA) certificates in PEM format.
-May be repeated to load any number of files.
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-\-params values"
-TLS library specific parameters for the communication session.
-See the library documentation for details on valid parameters.
-.if !'po4a'hide' .I "GnuTLS: http://gnutls.org/manual/html_node/Priority\-Strings.html"
-If repeated only the last value will have effect.
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-\-ping [options]"
-Enable ping mode. Optional \-g and \-I parameters must follow immediately if used.
-Repeated use resets to default ping settings.
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-g count"
-Ping mode, perform
-.I count
-iterations (default is to loop until interrupted).
-.
-.if !'po4a'hide' .TP
-.if !'po4a'hide' .B "\-I interval"
-Ping interval in seconds (default 1 second).
-.
-.SH AUTHOR
-This program and manual was written by
-.if !'po4a'hide' .I Amos Jeffries <amosjeffries@squid-cache.org>
-.PP
-Based on original code derived from Harvest and further developed by
-numerous individuals from the internet community.
-.
-.SH COPYRIGHT
-.PP
- * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
-.
-.SH QUESTIONS
-Questions on the usage of this program can be sent to the
-.I Squid Users mailing list
-.if !'po4a'hide' <squid-users@lists.squid-cache.org>
-.
-.SH REPORTING BUGS
-See https://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 https://bugs.squid-cache.org/
-.PP
-Report serious security bugs to
-.I Squid Bugs <squid-bugs@lists.squid-cache.org>
-.PP
-Report ideas for new improvements to the
-.I Squid Developers mailing list
-.if !'po4a'hide' <squid-dev@lists.squid-cache.org>
-.
-.SH SEE ALSO
-.if !'po4a'hide' .BR squid "(8), "
-.if !'po4a'hide' .BR cachemgr.cgi "(8)"
diff --git a/tools/squidclient/squidclient.cc b/tools/squidclient/squidclient.cc
deleted file mode 100644 (file)
index bdb7c8f..0000000
+++ /dev/null
@@ -1,682 +0,0 @@
-/*
- * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-#include "squid.h"
-#include "base64.h"
-#include "ip/Address.h"
-#include "ip/tools.h"
-#include "time/gadgets.h"
-#include "tools/squidclient/gssapi_support.h"
-#include "tools/squidclient/Parameters.h"
-#include "tools/squidclient/Ping.h"
-#include "tools/squidclient/Transport.h"
-
-#if _SQUID_WINDOWS_
-/** \cond AUTODOCS-IGNORE */
-using namespace Squid;
-/** \endcond */
-#endif
-
-#include <cassert>
-#include <cerrno>
-#include <csignal>
-#include <cstring>
-#include <iostream>
-#include <sstream>
-#if _SQUID_WINDOWS_
-#include <io.h>
-#endif
-#if HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#if HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#if HAVE_GETOPT_H
-#include <getopt.h>
-#endif
-
-#ifndef BUFSIZ
-#define BUFSIZ      8192
-#endif
-
-/* Local functions */
-static void usage(const char *progname);
-
-void pipe_handler(int sig);
-static void set_our_signal(void);
-
-Parameters scParams;
-
-static int put_fd;
-static char *put_file = nullptr;
-
-static struct stat sb;
-int total_bytes = 0;
-
-#if _SQUID_AIX_
-/* Bug 3854: AIX 6.1 tries to link in this fde.h global symbol
- * despite squidclient not using any of the fd_* code.
- */
-fde *fde::Table = nullptr;
-#endif
-
-#if _SQUID_WINDOWS_
-void
-Win32SockCleanup(void)
-{
-    WSACleanup();
-    return;
-}
-#endif
-
-static void
-usage(const char *progname)
-{
-    std::cerr << "Version: " << VERSION << std::endl
-              << "Usage: " << progname << " [Basic Options] [HTTP Options]" << std::endl
-              << std::endl;
-    std::cerr
-            << "    -s | --quiet    Silent.  Do not print response message to stdout." << std::endl
-            << "    -v | --verbose  Verbose debugging. Repeat (-vv) to increase output level." << std::endl
-            << "                    Levels:" << std::endl
-            << "                      1 - Print outgoing request message to stderr." << std::endl
-            << "                      2 - Print action trace to stderr." << std::endl
-            << "    --help          Display this help text." << std::endl
-            << std::endl;
-    Transport::Config.usage();
-    Ping::Config.usage();
-    std::cerr
-            << "HTTP Options:" << std::endl
-            << "    -a           Do NOT include Accept: header." << std::endl
-            << "    -A           User-Agent: header. Use \"\" to omit." << std::endl
-            << "    -H 'string'  Extra headers to send. Supports '\\\\', '\\n', '\\r' and '\\t'." << std::endl
-            << "    -i IMS       If-Modified-Since time (in Epoch seconds)." << std::endl
-            << "    -j hosthdr   Host header content" << std::endl
-            << "    -k           Keep the connection active. Default is to do only one request then close." << std::endl
-            << "    -m method    Request method, default is GET." << std::endl
-#if HAVE_GSSAPI
-            << "    -n           Proxy Negotiate(Kerberos) authentication" << std::endl
-            << "    -N           WWW Negotiate(Kerberos) authentication" << std::endl
-#endif
-            << "    -P file      Send content from the named file as request payload" << std::endl
-            << "    -r           Force cache to reload URL" << std::endl
-            << "    -t count     Trace count cache-hops" << std::endl
-            << "    -u user      Proxy authentication username" << std::endl
-            << "    -U user      WWW authentication username" << std::endl
-            << "    -V version   HTTP Version. Use '-' for HTTP/0.9 omitted case" << std::endl
-            << "    -w password  Proxy authentication password" << std::endl
-            << "    -W password  WWW authentication password" << std::endl
-            ;
-    exit(EXIT_FAILURE);
-}
-
-static void
-shellUnescape(char *buf)
-{
-    if (!buf)
-        return;
-
-    unsigned char *p, *d;
-
-    d = p = reinterpret_cast<unsigned char *>(buf);
-
-    while (auto ch = *p) {
-
-        if (ch == '\\') {
-            ++p;
-
-            switch (*p) {
-            case 'n':
-                ch = '\n';
-                break;
-            case 'r':
-                ch = '\r';
-                break;
-            case 't':
-                ch = '\t';
-                break;
-            case '\\':
-                ch = '\\';
-                break;
-            default:
-                ch = *p;
-                debugVerbose(1, "Warning: unsupported shell code '\\" << ch << "'");
-                break;
-            }
-
-            *d = ch;
-
-            if (!ch)
-                continue;
-
-        } else {
-            *d = *p;
-        }
-
-        ++p;
-        ++d;
-    }
-
-    *d = '\0';
-}
-
-/// [Proxy-]Authorization header producer
-class Authorization
-{
-public:
-    Authorization(const char *aHeader, const char *aDestination):
-        header(aHeader), destination(aDestination) {}
-
-    /// finalizes and writes the right HTTP header to the given stream
-    void commit(std::ostream &os);
-
-    std::string header; ///< HTTP header name to send
-    std::string destination; ///< used when describing password
-    const char *user = nullptr; ///< user name to encode and send
-    const char *password = nullptr; ///< user password to encode and send
-};
-
-void
-Authorization::commit(std::ostream &os)
-{
-#if HAVE_GETPASS
-    if (!password)
-        password = getpass((destination + " password: ").c_str());
-#endif
-    if (!password) {
-        std::cerr << "ERROR: " << destination << " password missing\n";
-        exit(EXIT_FAILURE);
-    }
-
-    struct base64_encode_ctx ctx;
-    base64_encode_init(&ctx);
-    const auto bcapacity = base64_encode_len(strlen(user) + 1 + strlen(password));
-    const auto buf = new char[bcapacity];
-
-    size_t bsize = 0;
-    bsize += base64_encode_update(&ctx, buf, strlen(user), reinterpret_cast<const uint8_t*>(user));
-    bsize += base64_encode_update(&ctx, buf+bsize, 1, reinterpret_cast<const uint8_t*>(":"));
-    bsize += base64_encode_update(&ctx, buf+bsize, strlen(password), reinterpret_cast<const uint8_t*>(password));
-    bsize += base64_encode_final(&ctx, buf+bsize);
-    assert(bsize <= bcapacity); // paranoid and late but better than nothing
-
-    os << header << ": Basic ";
-    os.write(buf, bsize);
-    os << "\r\n";
-
-    delete[] buf;
-}
-
-static Authorization ProxyAuthorization("Proxy-Authorization", "proxy");
-static Authorization OriginAuthorization("Authorization", "origin server");
-
-int
-main(int argc, char *argv[])
-{
-    int len, bytesWritten;
-    bool to_stdout, reload;
-    int keep_alive = 0;
-    int opt_noaccept = 0;
-#if HAVE_GSSAPI
-    int www_neg = 0, proxy_neg = 0;
-#endif
-    char url[BUFSIZ];
-    char buf[BUFSIZ];
-    char *extra_hdrs = nullptr;
-    const char *method = "GET";
-    extern char *optarg;
-    time_t ims = 0;
-    int max_forwards = -1;
-
-    const char *host = nullptr;
-    const char *version = "1.0";
-    const char *useragent = nullptr;
-
-    /* set the defaults */
-    to_stdout = true;
-    reload = false;
-
-    Ip::ProbeTransport(); // determine IPv4 or IPv6 capabilities before parsing.
-    if (argc < 2 || argv[argc-1][0] == '-') {
-        usage(argv[0]);     /* need URL */
-    } else if (argc >= 2) {
-        strncpy(url, argv[argc - 1], sizeof(url));
-        url[sizeof(url) - 1] = '\0';
-
-        int optIndex = 0;
-        const char *shortOpStr = "aA:h:j:V:l:P:i:km:nNp:rsvt:H:T:u:U:w:W:?";
-
-        // options for controlling squidclient
-        static struct option basicOptions[] = {
-            /* These are the generic options for squidclient itself */
-            {"help",    no_argument, nullptr, '?'},
-            {"verbose", no_argument, nullptr, 'v'},
-            {"quiet",   no_argument, nullptr, 's'},
-            {"host",    required_argument, nullptr, 'h'},
-            {"local",   required_argument, nullptr, 'l'},
-            {"port",    required_argument, nullptr, 'p'},
-            {"ping",    no_argument, nullptr, '\1'},
-            {"https",   no_argument, nullptr, '\3'},
-            {nullptr, 0, nullptr, 0}
-        };
-
-        int c;
-        while ((c = getopt_long(argc, argv, shortOpStr, basicOptions, &optIndex)) != -1) {
-
-            // modules parse their own specific options
-            switch (c) {
-            case '\1':
-                to_stdout = 0;
-                Ping::Config.parseCommandOpts(argc, argv, c, optIndex);
-                continue;
-
-            case 'h':       /* remote host */
-            case 'l':       /* local host */
-            case 'p':       /* port number */
-                // rewind and let the Transport::Config parser handle
-                optind -= 2;
-                Transport::Config.parseCommandOpts(argc, argv, c, optIndex);
-                continue;
-
-            case '\3': // request over a TLS connection
-                Transport::Config.parseCommandOpts(argc, argv, c, optIndex);
-                continue;
-
-            default: // fall through to next switch
-                break;
-            }
-
-            switch (c) {
-
-            case '\0': // dummy value for end-of-options
-                break;
-
-            case 'a':
-                opt_noaccept = 1;
-                break;
-
-            case 'A':
-                useragent = optarg;
-                break;
-
-            case 'j':
-                host = optarg;
-                break;
-
-            case 'V':
-                version = optarg;
-                break;
-
-            case 's':       /* silent */
-                to_stdout = false;
-                break;
-
-            case 'k':       /* backward compat */
-                keep_alive = 1;
-                break;
-
-            case 'r':       /* reload */
-                reload = true;
-                break;
-
-            case 'P':
-                put_file = xstrdup(optarg);
-                break;
-
-            case 'i':       /* IMS */
-                ims = (time_t) atoi(optarg);
-                break;
-
-            case 'm':
-                method = xstrdup(optarg);
-                break;
-
-            case 't':
-                method = xstrdup("TRACE");
-                max_forwards = atoi(optarg);
-                break;
-
-            case 'H':
-                if (strlen(optarg)) {
-                    if (extra_hdrs) {
-                        std::cerr << "ERROR: multiple -H options not supported. Discarding previous value." << std::endl;
-                        xfree(extra_hdrs);
-                    }
-                    extra_hdrs = xstrdup(optarg);
-                    shellUnescape(extra_hdrs);
-                }
-                break;
-
-            case 'T':
-                Transport::Config.ioTimeout = atoi(optarg);
-                break;
-
-            case 'u':
-                ProxyAuthorization.user = optarg;
-                break;
-
-            case 'w':
-                ProxyAuthorization.password = optarg;
-                break;
-
-            case 'U':
-                OriginAuthorization.user = optarg;
-                break;
-
-            case 'W':
-                OriginAuthorization.password = optarg;
-                break;
-
-            case 'n':
-#if HAVE_GSSAPI
-                proxy_neg = 1;
-#else
-                std::cerr << "ERROR: Negotiate authentication not supported." << std::endl;
-                usage(argv[0]);
-#endif
-                break;
-
-            case 'N':
-#if HAVE_GSSAPI
-                www_neg = 1;
-#else
-                std::cerr << "ERROR: Negotiate authentication not supported." << std::endl;
-                usage(argv[0]);
-#endif
-                break;
-
-            case 'v':
-                /* undocumented: may increase verb-level by giving more -v's */
-                ++scParams.verbosityLevel;
-                debugVerbose(2, "verbosity level set to " << scParams.verbosityLevel);
-                break;
-
-            case '?':       /* usage */
-
-            default:
-                usage(argv[0]);
-                break;
-            }
-        }
-        if (ProxyAuthorization.password && !ProxyAuthorization.user) {
-            std::cerr << "ERROR: Proxy authentication password (-w) is given, but username (-u) is missing\n";
-            exit(EXIT_FAILURE);
-        }
-        if (OriginAuthorization.password && !OriginAuthorization.user) {
-            std::cerr << "ERROR: WWW authentication password (-W) is given, but username (-U) is missing\n";
-            exit(EXIT_FAILURE);
-        }
-    }
-#if _SQUID_WINDOWS_
-    {
-        WSADATA wsaData;
-        WSAStartup(2, &wsaData);
-        atexit(Win32SockCleanup);
-    }
-#endif
-    /* Build the HTTP request */
-    const char *pathPassword = nullptr;
-    if (strncmp(url, "mgr:", 4) == 0) {
-        char *t = xstrdup(url + 4);
-        // XXX: Bail on snprintf() failures
-        snprintf(url, sizeof(url), "http://%s:%hu/squid-internal-mgr/%s", Transport::Config.hostname, Transport::Config.port, t);
-        if (const auto at = strrchr(url, '@')) {
-            if (!OriginAuthorization.user) {
-                std::cerr << "ERROR: Embedding a password in a cache manager command requires " <<
-                          "providing a username with -U: mgr:" << t << std::endl;
-                exit(EXIT_FAILURE);
-            }
-            *at = 0; // send password in Authorization header, not URL
-            pathPassword = at + 1; // the now-removed embedded @password overwrites OriginAuthorization.password further below
-        }
-        xfree(t);
-    }
-    if (put_file) {
-        put_fd = open(put_file, O_RDONLY);
-        set_our_signal();
-
-        if (put_fd < 0) {
-            int xerrno = errno;
-            std::cerr << "ERROR: can't open file (" << xstrerr(xerrno) << ")" << std::endl;
-            exit(EXIT_FAILURE);
-        }
-#if _SQUID_WINDOWS_
-        setmode(put_fd, O_BINARY);
-#endif
-
-        if (fstat(put_fd, &sb) < 0) {
-            int xerrno = errno;
-            std::cerr << "ERROR: can't identify length of file (" << xstrerr(xerrno) << ")" << std::endl;
-        }
-    }
-
-    if (!host) {
-        char *newhost = strstr(url, "://");
-        if (newhost) {
-            char *t;
-            newhost += 3;
-            newhost = xstrdup(newhost);
-            t = newhost + strcspn(newhost, "@/?");
-            if (*t == '@') {
-                newhost = t + 1;
-                t = newhost + strcspn(newhost, "@/?");
-            }
-            *t = '\0';
-            host = newhost;
-        }
-    }
-
-    std::stringstream msg;
-
-    if (version[0] == '-' || !version[0]) {
-        /* HTTP/0.9, no headers, no version */
-        msg << method << " " << url << "\r\n";
-    } else {
-        const auto versionImpliesHttp = xisdigit(version[0]); // is HTTP/n.n
-        msg << method << " "
-            << url << " "
-            << (versionImpliesHttp ? "HTTP/" : "") << version
-            << "\r\n";
-
-        if (host) {
-            msg << "Host: " << host << "\r\n";
-        }
-
-        if (!useragent) {
-            msg  << "User-Agent: squidclient/" << VERSION << "\r\n";
-        } else if (useragent[0] != '\0') {
-            msg << "User-Agent: " << useragent << "\r\n";
-        } // else custom: no value U-A header
-
-        if (reload) {
-            msg << "Cache-Control: no-cache\r\n";
-        }
-        if (put_fd > 0) {
-            msg << "Content-length: " << sb.st_size << "\r\n";
-        }
-        if (opt_noaccept == 0) {
-            msg << "Accept: */*\r\n";
-        }
-        if (ims) {
-            msg << "If-Modified-Since: " << Time::FormatRfc1123(ims) << "\r\n";
-        }
-        if (max_forwards > -1) {
-            msg << "Max-Forwards: " << max_forwards << "\r\n";
-        }
-        if (ProxyAuthorization.user)
-            ProxyAuthorization.commit(msg);
-        if (OriginAuthorization.user) {
-            const auto savedPassword = OriginAuthorization.password;
-            if (pathPassword)
-                OriginAuthorization.password = pathPassword;
-            OriginAuthorization.commit(msg);
-            OriginAuthorization.password = savedPassword; // restore the global password setting
-        }
-#if HAVE_GSSAPI
-        if (www_neg) {
-            if (host) {
-                const char *token = GSSAPI_token(host);
-                msg << "Proxy-Authorization: Negotiate " << token << "\r\n";
-                delete[] token;
-            } else
-                std::cerr << "ERROR: server host missing" << std::endl;
-        }
-        if (proxy_neg) {
-            if (Transport::Config.hostname) {
-                const char *token = GSSAPI_token(Transport::Config.hostname);
-                msg << "Proxy-Authorization: Negotiate " << token << "\r\n";
-                delete[] token;
-            } else
-                std::cerr << "ERROR: proxy server host missing" << std::endl;
-        }
-#endif
-
-        /* HTTP/1.0 may need keep-alive explicitly */
-        if (strcmp(version, "1.0") == 0 && keep_alive)
-            msg << "Connection: keep-alive\r\n";
-
-        /* HTTP/1.1 may need close explicitly */
-        if (!keep_alive)
-            msg << "Connection: close\r\n";
-
-        if (extra_hdrs) {
-            msg << extra_hdrs;
-            safe_free(extra_hdrs);
-        }
-        msg << "\r\n"; // empty line ends MIME header block
-    }
-
-    msg.flush();
-    const auto messageHeader = msg.str();
-    debugVerbose(1, "Request:" << std::endl << messageHeader << std::endl << ".");
-
-    uint32_t loops = Ping::Init();
-
-    for (uint32_t i = 0; loops == 0 || i < loops; ++i) {
-        size_t fsize = 0;
-
-        if (!Transport::Connect())
-            continue;
-
-        /* Send the HTTP request */
-        debugVerbose(2, "Sending HTTP request ... ");
-        bytesWritten = Transport::Write(messageHeader.data(), messageHeader.length());
-
-        if (bytesWritten < 0) {
-            std::cerr << "ERROR: write" << std::endl;
-            exit(EXIT_FAILURE);
-        } else if (static_cast<size_t>(bytesWritten) != messageHeader.length()) {
-            std::cerr << "ERROR: Failed to send the following request: " << std::endl
-                      << messageHeader << std::endl;
-            exit(EXIT_FAILURE);
-        }
-        debugVerbose(2, "done.");
-
-        if (put_file) {
-            debugVerbose(1, "Sending HTTP request payload ...");
-            int x;
-            if ((x = lseek(put_fd, 0, SEEK_SET)) < 0) {
-                int xerrno = errno;
-                std::cerr << "ERROR: lseek: " << xstrerr(xerrno) << std::endl;
-
-            } else while ((x = read(put_fd, buf, sizeof(buf))) > 0) {
-
-                    x = Transport::Write(buf, x);
-
-                    total_bytes += x;
-
-                    if (x <= 0)
-                        break;
-                }
-
-            if (x != 0)
-                std::cerr << "ERROR: Cannot send file." << std::endl;
-            else
-                debugVerbose(1, "done.");
-        }
-        /* Read the data */
-
-#if _SQUID_WINDOWS_
-        setmode(1, O_BINARY);
-#endif
-
-        while ((len = Transport::Read(buf, sizeof(buf))) > 0) {
-            fsize += len;
-
-            if (to_stdout && fwrite(buf, len, 1, stdout) != 1) {
-                int xerrno = errno;
-                std::cerr << "ERROR: writing to stdout: " << xstrerr(xerrno) << std::endl;
-            }
-        }
-
-#if USE_GNUTLS
-        if (Transport::Config.tlsEnabled) {
-            if (len == 0) {
-                std::cerr << "- Peer has closed the TLS connection" << std::endl;
-            } else if (!gnutls_error_is_fatal(len)) {
-                std::cerr << "WARNING: " << gnutls_strerror(len) << std::endl;
-            } else {
-                std::cerr << "ERROR: " << gnutls_strerror(len) << std::endl;
-            }
-        }
-#endif
-
-#if _SQUID_WINDOWS_
-        setmode(1, O_TEXT);
-#endif
-
-        Transport::CloseConnection();
-
-        if (Ping::LoopDone(i))
-            break;
-
-        Ping::TimerStop(fsize);
-    }
-
-    Ping::DisplayStats();
-    Transport::ShutdownTls();
-    return EXIT_SUCCESS;
-}
-
-void
-pipe_handler(int)
-{
-    std::cerr << "SIGPIPE received." << std::endl;
-}
-
-static void
-set_our_signal(void)
-{
-#if HAVE_SIGACTION
-    struct sigaction sa;
-    sa.sa_handler = pipe_handler;
-    sa.sa_flags = SA_RESTART;
-    sigemptyset(&sa.sa_mask);
-
-    if (sigaction(SIGPIPE, &sa, nullptr) < 0) {
-        std::cerr << "ERROR: Cannot set PIPE signal." << std::endl;
-        exit(EXIT_FAILURE);
-    }
-#else
-    signal(SIGPIPE, pipe_handler);
-#endif
-}
-