Make Proxy-Auto-Detect check for each host
authorMichael Vogt <mvo@ubuntu.com>
Tue, 2 Sep 2014 13:50:19 +0000 (15:50 +0200)
committerMichael Vogt <mvo@ubuntu.com>
Tue, 2 Sep 2014 14:02:37 +0000 (16:02 +0200)
When doing Acquire::http{,s}::Proxy-Auto-Detect, run the auto-detect
command for each host instead of only once. This should make using
"proxy" from libproxy-tools feasible which can then be used for PAC
style or other proxy configurations.

Closes: #759264

apt-pkg/contrib/proxy.cc [new file with mode: 0644]
apt-pkg/contrib/proxy.h [new file with mode: 0644]
cmdline/apt-helper.cc
methods/http.cc
methods/http.h
methods/https.cc
test/integration/test-apt-helper

diff --git a/apt-pkg/contrib/proxy.cc b/apt-pkg/contrib/proxy.cc
new file mode 100644 (file)
index 0000000..b58db84
--- /dev/null
@@ -0,0 +1,82 @@
+// -*- mode: cpp; mode: fold -*-
+// Description                                                         /*{{{*/
+/* ######################################################################
+   
+   Proxy - Proxy releated functions
+   
+   ##################################################################### */
+                                                                       /*}}}*/
+// Include Files                                                       /*{{{*/
+#include<apt-pkg/configuration.h>
+#include<apt-pkg/error.h>
+#include<apt-pkg/fileutl.h>
+#include<apt-pkg/strutl.h>
+
+#include<iostream>
+#include <unistd.h>
+
+#include "proxy.h"
+
+
+// AutoDetectProxy - auto detect proxy                                 /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool AutoDetectProxy(URI &URL)
+{
+   // we support both http/https debug options
+   bool Debug = _config->FindB("Debug::Acquire::"+URL.Access,false);
+
+   // option is "Acquire::http::Proxy-Auto-Detect" but we allow the old
+   // name without the dash ("-")
+   std::string AutoDetectProxyCmd = _config->Find("Acquire::"+URL.Access+"::Proxy-Auto-Detect",
+                                      _config->Find("Acquire::"+URL.Access+"::ProxyAutoDetect"));
+
+   if (AutoDetectProxyCmd.empty())
+      return true;
+
+   if (Debug)
+      std::clog << "Using auto proxy detect command: " << AutoDetectProxyCmd << std::endl;
+
+   int Pipes[2] = {-1,-1};
+   if (pipe(Pipes) != 0)
+      return _error->Errno("pipe", "Failed to create Pipe");
+
+   pid_t Process = ExecFork();
+   if (Process == 0)
+   {
+      close(Pipes[0]);
+      dup2(Pipes[1],STDOUT_FILENO);
+      SetCloseExec(STDOUT_FILENO,false);
+
+      std::string foo = URL;
+      const char *Args[4];
+      Args[0] = AutoDetectProxyCmd.c_str();
+      Args[1] = foo.c_str();
+      Args[2] = 0;
+      execv(Args[0],(char **)Args);
+      std::cerr << "Failed to exec method " << Args[0] << std::endl;
+      _exit(100);
+   }
+   char buf[512];
+   int InFd = Pipes[0];
+   close(Pipes[1]);
+   int res = read(InFd, buf, sizeof(buf)-1);
+   ExecWait(Process, "ProxyAutoDetect", true);
+
+   if (res < 0)
+      return _error->Errno("read", "Failed to read");
+   if (res == 0)
+      return _error->Warning("ProxyAutoDetect returned no data");
+
+   // add trailing \0
+   buf[res] = 0;
+
+   if (Debug)
+      std::clog << "auto detect command returned: '" << buf << "'" << std::endl;
+
+   if (strstr(buf, URL.Access.c_str()) == buf)
+      _config->Set("Acquire::"+URL.Access+"::proxy::"+URL.Host, _strstrip(buf));
+
+   return true;
+}
+                                                                       /*}}}*/
diff --git a/apt-pkg/contrib/proxy.h b/apt-pkg/contrib/proxy.h
new file mode 100644 (file)
index 0000000..2cbcd07
--- /dev/null
@@ -0,0 +1,16 @@
+// -*- mode: cpp; mode: fold -*-
+// Description                                                         /*{{{*/
+/* ######################################################################
+   
+   Proxy - Proxy operations
+   
+   ##################################################################### */
+                                                                       /*}}}*/
+#ifndef PKGLIB_PROXY_H
+#define PKGLIB_PROXY_H
+
+class URI;
+bool AutoDetectProxy(URI &URL);
+
+
+#endif
index b0edafc..dd43ea1 100644 (file)
@@ -16,6 +16,7 @@
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/acquire.h>
 #include <apt-pkg/acquire-item.h>
+#include <apt-pkg/proxy.h>
 
 #include <apt-private/acqprogress.h>
 #include <apt-private/private-output.h>
 #include <apti18n.h>
                                                                        /*}}}*/
 
+static bool DoAutoDetectProxy(CommandLine &CmdL)
+{
+   if (CmdL.FileSize() != 2)
+      return _error->Error(_("Need one URL as argument"));
+   URI ServerURL(CmdL.FileList[1]);
+   AutoDetectProxy(ServerURL);
+   std::string SpecificProxy = _config->Find("Acquire::"+ServerURL.Access+"::Proxy::" + ServerURL.Host);
+   ioprintf(std::cout, "Using proxy '%s' for URL '%s'\n",
+            SpecificProxy.c_str(), std::string(ServerURL).c_str());
+
+   return true;
+}
+
 static bool DoDownloadFile(CommandLine &CmdL)
 {
    if (CmdL.FileSize() <= 2)
@@ -70,6 +84,7 @@ static bool ShowHelp(CommandLine &)
       "\n"
       "Commands:\n"
       "   download-file - download the given uri to the target-path\n"
+      "   auto-detect-proxy - detect proxy using apt.conf\n"
       "\n"
       "                       This APT helper has Super Meep Powers.\n");
    return true;
@@ -80,6 +95,7 @@ int main(int argc,const char *argv[])                                 /*{{{*/
 {
    CommandLine::Dispatch Cmds[] = {{"help",&ShowHelp},
                                   {"download-file", &DoDownloadFile},
+                                  {"auto-detect-proxy", &DoAutoDetectProxy},
                                    {0,0}};
 
    std::vector<CommandLine::Args> Args = getCommandArgs(
index 7c7949e..f2a4a4d 100644 (file)
@@ -34,6 +34,7 @@
 #include <apt-pkg/hashes.h>
 #include <apt-pkg/netrc.h>
 #include <apt-pkg/strutl.h>
+#include <apt-pkg/proxy.h>
 
 #include <stddef.h>
 #include <stdlib.h>
@@ -304,6 +305,7 @@ bool HttpServerState::Open()
    Persistent = true;
    
    // Determine the proxy setting
+   AutoDetectProxy(ServerName);
    string SpecificProxy = _config->Find("Acquire::http::Proxy::" + ServerName.Host);
    if (!SpecificProxy.empty())
    {
@@ -762,66 +764,6 @@ bool HttpMethod::Configuration(string Message)
                                  PipelineDepth);
    Debug = _config->FindB("Debug::Acquire::http",false);
 
-   // Get the proxy to use
-   AutoDetectProxy();
-
-   return true;
-}
-                                                                       /*}}}*/
-// HttpMethod::AutoDetectProxy - auto detect proxy                     /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool HttpMethod::AutoDetectProxy()
-{
-   // option is "Acquire::http::Proxy-Auto-Detect" but we allow the old
-   // name without the dash ("-")
-   AutoDetectProxyCmd = _config->Find("Acquire::http::Proxy-Auto-Detect",
-                                      _config->Find("Acquire::http::ProxyAutoDetect"));
-
-   if (AutoDetectProxyCmd.empty())
-      return true;
-
-   if (Debug)
-      clog << "Using auto proxy detect command: " << AutoDetectProxyCmd << endl;
-
-   int Pipes[2] = {-1,-1};
-   if (pipe(Pipes) != 0)
-      return _error->Errno("pipe", "Failed to create Pipe");
-
-   pid_t Process = ExecFork();
-   if (Process == 0)
-   {
-      close(Pipes[0]);
-      dup2(Pipes[1],STDOUT_FILENO);
-      SetCloseExec(STDOUT_FILENO,false);
-
-      const char *Args[2];
-      Args[0] = AutoDetectProxyCmd.c_str();
-      Args[1] = 0;
-      execv(Args[0],(char **)Args);
-      cerr << "Failed to exec method " << Args[0] << endl;
-      _exit(100);
-   }
-   char buf[512];
-   int InFd = Pipes[0];
-   close(Pipes[1]);
-   int res = read(InFd, buf, sizeof(buf)-1);
-   ExecWait(Process, "ProxyAutoDetect", true);
-
-   if (res < 0)
-      return _error->Errno("read", "Failed to read");
-   if (res == 0)
-      return _error->Warning("ProxyAutoDetect returned no data");
-
-   // add trailing \0
-   buf[res] = 0;
-
-   if (Debug)
-      clog << "auto detect command returned: '" << buf << "'" << endl;
-
-   if (strstr(buf, "http://") == buf)
-      _config->Set("Acquire::http::proxy", _strstrip(buf));
-
    return true;
 }
                                                                        /*}}}*/
index 5406ce4..1df9fa0 100644 (file)
@@ -124,9 +124,6 @@ class HttpMethod : public ServerMethod
    public:
    virtual void SendReq(FetchItem *Itm);
 
-   /** \brief Try to AutoDetect the proxy */
-   bool AutoDetectProxy();
-
    virtual bool Configuration(std::string Message);
 
    virtual ServerState * CreateServerState(URI uri);
index e0348ab..0499af0 100644 (file)
@@ -20,6 +20,7 @@
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/macros.h>
 #include <apt-pkg/strutl.h>
+#include <apt-pkg/proxy.h>
 
 #include <sys/stat.h>
 #include <sys/time.h>
@@ -107,6 +108,9 @@ void HttpsMethod::SetupProxy()                                      /*{{{*/
 {
    URI ServerName = Queue->Uri;
 
+   // Determine the proxy setting
+   AutoDetectProxy(ServerName);
+
    // Curl should never read proxy settings from the environment, as
    // we determine which proxy to use.  Do this for consistency among
    // methods and prevent an environment variable overriding a
dissimilarity index 86%
index 6505b59..c749224 100755 (executable)
@@ -1,39 +1,75 @@
-#!/bin/sh
-set -e
-
-TESTDIR=$(readlink -f $(dirname $0))
-. $TESTDIR/framework
-
-setupenvironment
-configarchitecture "i386"
-
-changetohttpswebserver
-
-echo "foo" > aptarchive/foo
-
-msgtest 'apt-file download-file md5sum'
-apthelper -qq download-file http://localhost:8080/foo foo2 MD5Sum:d3b07384d113edec49eaa6238ad5ff00 && msgpass || msgfail
-testfileequal foo2 'foo'
-
-msgtest 'apt-file download-file sha1'
-apthelper -qq download-file http://localhost:8080/foo foo1 SHA1:f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 && msgpass || msgfail
-testfileequal foo1 'foo'
-
-msgtest 'apt-file download-file sha256'
-apthelper -qq download-file http://localhost:8080/foo foo3 SHA256:b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c && msgpass || msgfail
-testfileequal foo3 'foo'
-
-msgtest 'apt-file download-file no-hash'
-apthelper -qq download-file http://localhost:8080/foo foo4 && msgpass || msgfail
-testfileequal foo4 'foo'
-
-msgtest 'apt-file download-file wrong hash'
-if ! apthelper -qq download-file http://localhost:8080/foo foo5 MD5Sum:aabbcc 2>&1 2> download.stderr; then
-   msgpass
-else
-   msgfail
-fi
-testfileequal download.stderr 'E: Failed to fetch http://localhost:8080/foo  Hash Sum mismatch
-
-E: Download Failed'
-testfileequal foo5.FAILED 'foo'
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+
+setupenvironment
+configarchitecture "i386"
+
+changetohttpswebserver
+
+test_apt_helper_download() {
+    echo "foo" > aptarchive/foo
+
+    msgtest 'apt-file download-file md5sum'
+    apthelper -qq download-file http://localhost:8080/foo foo2 MD5Sum:d3b07384d113edec49eaa6238ad5ff00 && msgpass || msgfail
+    testfileequal foo2 'foo'
+
+    msgtest 'apt-file download-file sha1'
+    apthelper -qq download-file http://localhost:8080/foo foo1 SHA1:f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 && msgpass || msgfail
+    testfileequal foo1 'foo'
+
+    msgtest 'apt-file download-file sha256'
+    apthelper -qq download-file http://localhost:8080/foo foo3 SHA256:b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c && msgpass || msgfail
+    testfileequal foo3 'foo'
+
+    msgtest 'apt-file download-file no-hash'
+    apthelper -qq download-file http://localhost:8080/foo foo4 && msgpass || msgfail
+    testfileequal foo4 'foo'
+    
+    msgtest 'apt-file download-file wrong hash'
+    if ! apthelper -qq download-file http://localhost:8080/foo foo5 MD5Sum:aabbcc 2>&1 2> download.stderr; then
+        msgpass
+    else
+        msgfail
+    fi
+    testfileequal download.stderr 'E: Failed to fetch http://localhost:8080/foo  Hash Sum mismatch
+
+E: Download Failed'
+    testfileequal foo5.FAILED 'foo'
+}
+
+test_apt_helper_detect_proxy() {
+    # no proxy
+    testequal "Using proxy '' for URL 'http://example.com/'" apthelper auto-detect-proxy http://example.com/
+
+
+    # http auto detect proxy script
+    cat > apt-proxy-detect <<'EOF'
+#!/bin/sh -e
+echo "http://some-proxy"
+EOF
+    chmod 755 apt-proxy-detect
+    echo "Acquire::http::Proxy-Auto-Detect \"$(pwd)/apt-proxy-detect\";" > rootdir/etc/apt/apt.conf.d/02proxy-detect
+    
+    testequal "Using proxy 'http://some-proxy' for URL 'http://www.example.com/'" apthelper auto-detect-proxy http://www.example.com
+
+
+    # https auto detect proxy script
+    cat > apt-proxy-detect <<'EOF'
+#!/bin/sh -e
+echo "https://https-proxy"
+EOF
+    chmod 755 apt-proxy-detect
+    echo "Acquire::https::Proxy-Auto-Detect \"$(pwd)/apt-proxy-detect\";" > rootdir/etc/apt/apt.conf.d/02proxy-detect
+    
+    testequal "Using proxy 'https://https-proxy' for URL 'https://ssl.example.com/'" apthelper auto-detect-proxy https://ssl.example.com 
+
+
+    
+}
+
+test_apt_helper_download
+test_apt_helper_detect_proxy
+