summaryrefslogtreecommitdiff
path: root/methods
diff options
context:
space:
mode:
Diffstat (limited to 'methods')
-rw-r--r--methods/aptmethod.h72
-rw-r--r--methods/cdrom.cc4
-rw-r--r--methods/gpgv.cc6
-rw-r--r--methods/http.cc59
-rw-r--r--methods/http.h10
-rw-r--r--methods/http_main.cc8
-rw-r--r--methods/https.cc226
-rw-r--r--methods/https.h13
-rw-r--r--methods/mirror.cc4
-rw-r--r--methods/rred.cc2
-rw-r--r--methods/rsh.cc12
-rw-r--r--methods/rsh.h3
-rw-r--r--methods/server.cc57
-rw-r--r--methods/server.h2
-rw-r--r--methods/store.cc11
15 files changed, 287 insertions, 202 deletions
diff --git a/methods/aptmethod.h b/methods/aptmethod.h
index 0963ea21e..38f451708 100644
--- a/methods/aptmethod.h
+++ b/methods/aptmethod.h
@@ -5,8 +5,10 @@
#include <apt-pkg/configuration.h>
#include <apt-pkg/error.h>
+#include <algorithm>
#include <locale>
#include <string>
+#include <vector>
#include <sys/time.h>
#include <sys/types.h>
@@ -15,10 +17,15 @@
#include <apti18n.h>
+static bool hasDoubleColon(std::string const &n)
+{
+ return n.find("::") != std::string::npos;
+}
+
class aptMethod : public pkgAcqMethod
{
protected:
- std::string Binary;
+ std::string const Binary;
public:
virtual bool Configuration(std::string Message) APT_OVERRIDE
@@ -34,7 +41,7 @@ public:
return true;
}
- bool CalculateHashes(FetchItem const * const Itm, FetchResult &Res) const
+ bool CalculateHashes(FetchItem const * const Itm, FetchResult &Res) const APT_NONNULL(2)
{
Hashes Hash(Itm->ExpectedHashes);
FileFd Fd;
@@ -52,7 +59,62 @@ public:
va_end(args);
}
- bool TransferModificationTimes(char const * const From, char const * const To, time_t &LastModified)
+ std::vector<std::string> methodNames;
+ void setPostfixForMethodNames(char const * const postfix) APT_NONNULL(2)
+ {
+ methodNames.erase(std::remove_if(methodNames.begin(), methodNames.end(), hasDoubleColon), methodNames.end());
+ decltype(methodNames) toAdd;
+ for (auto && name: methodNames)
+ toAdd.emplace_back(name + "::" + postfix);
+ std::move(toAdd.begin(), toAdd.end(), std::back_inserter(methodNames));
+ }
+ bool DebugEnabled() const
+ {
+ if (methodNames.empty())
+ return false;
+ auto const sni = std::find_if_not(methodNames.crbegin(), methodNames.crend(), hasDoubleColon);
+ if (unlikely(sni == methodNames.crend()))
+ return false;
+ auto const ln = methodNames[methodNames.size() - 1];
+ // worst case: all three are the same
+ std::string confln, confsn, confpn;
+ strprintf(confln, "Debug::Acquire::%s", ln.c_str());
+ strprintf(confsn, "Debug::Acquire::%s", sni->c_str());
+ auto const pni = sni->substr(0, sni->find('+'));
+ strprintf(confpn, "Debug::Acquire::%s", pni.c_str());
+ return _config->FindB(confln,_config->FindB(confsn, _config->FindB(confpn, false)));
+ }
+ std::string ConfigFind(char const * const postfix, std::string const &defValue) const APT_NONNULL(2)
+ {
+ for (auto && name: methodNames)
+ {
+ std::string conf;
+ strprintf(conf, "Acquire::%s::%s", name.c_str(), postfix);
+ auto const value = _config->Find(conf);
+ if (value.empty() == false)
+ return value;
+ }
+ return defValue;
+ }
+ std::string ConfigFind(std::string const &postfix, std::string const &defValue) const
+ {
+ return ConfigFind(postfix.c_str(), defValue);
+ }
+ bool ConfigFindB(char const * const postfix, bool const defValue) const APT_NONNULL(2)
+ {
+ return StringToBool(ConfigFind(postfix, defValue ? "yes" : "no"), defValue);
+ }
+ int ConfigFindI(char const * const postfix, int const defValue) const APT_NONNULL(2)
+ {
+ char *End;
+ std::string const value = ConfigFind(postfix, "");
+ auto const Res = strtol(value.c_str(), &End, 0);
+ if (value.c_str() == End)
+ return defValue;
+ return Res;
+ }
+
+ bool TransferModificationTimes(char const * const From, char const * const To, time_t &LastModified) APT_NONNULL(2, 3)
{
if (strcmp(To, "/dev/null") == 0)
return true;
@@ -75,8 +137,8 @@ public:
return true;
}
- aptMethod(char const * const Binary, char const * const Ver, unsigned long const Flags) :
- pkgAcqMethod(Ver, Flags), Binary(Binary)
+ aptMethod(std::string &&Binary, char const * const Ver, unsigned long const Flags) APT_NONNULL(3) :
+ pkgAcqMethod(Ver, Flags), Binary(Binary), methodNames({Binary})
{
try {
std::locale::global(std::locale(""));
diff --git a/methods/cdrom.cc b/methods/cdrom.cc
index 161822ac6..87a58e948 100644
--- a/methods/cdrom.cc
+++ b/methods/cdrom.cc
@@ -177,7 +177,7 @@ bool CDROMMethod::Fetch(FetchItem *Itm)
URI Get = Itm->Uri;
string File = Get.Path;
- Debug = _config->FindB("Debug::Acquire::cdrom", false);
+ Debug = DebugEnabled();
if (Debug)
clog << "CDROMMethod::Fetch " << Itm->Uri << endl;
@@ -224,7 +224,7 @@ bool CDROMMethod::Fetch(FetchItem *Itm)
return true;
}
- bool AutoDetect = _config->FindB("Acquire::cdrom::AutoDetect", true);
+ bool const AutoDetect = ConfigFindB("AutoDetect", true);
CDROM = _config->FindDir("Acquire::cdrom::mount");
if (Debug)
clog << "Looking for CDROM at " << CDROM << endl;
diff --git a/methods/gpgv.cc b/methods/gpgv.cc
index fc6eb9159..2fed53a39 100644
--- a/methods/gpgv.cc
+++ b/methods/gpgv.cc
@@ -147,7 +147,7 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile,
vector<Signer> &SoonWorthlessSigners,
vector<string> &NoPubKeySigners)
{
- bool const Debug = _config->FindB("Debug::Acquire::gpgv", false);
+ bool const Debug = DebugEnabled();
if (Debug == true)
std::clog << "inside VerifyGetSigners" << std::endl;
@@ -415,10 +415,8 @@ bool GPGVMethod::URIAcquire(std::string const &Message, FetchItem *Itm)
std::move(NoPubKeySigners.begin(), NoPubKeySigners.end(), std::back_inserter(Res.GPGVOutput));
URIDone(Res);
- if (_config->FindB("Debug::Acquire::gpgv", false))
- {
+ if (DebugEnabled())
std::clog << "apt-key succeeded\n";
- }
return true;
}
diff --git a/methods/http.cc b/methods/http.cc
index b7a3aa4a1..0378d7c60 100644
--- a/methods/http.cc
+++ b/methods/http.cc
@@ -63,13 +63,13 @@ const unsigned int CircleBuf::BW_HZ=10;
// CircleBuf::CircleBuf - Circular input buffer /*{{{*/
// ---------------------------------------------------------------------
/* */
-CircleBuf::CircleBuf(unsigned long long Size)
+CircleBuf::CircleBuf(HttpMethod const * const Owner, unsigned long long Size)
: Size(Size), Hash(NULL), TotalWriten(0)
{
Buf = new unsigned char[Size];
Reset();
- CircleBuf::BwReadLimit = _config->FindI("Acquire::http::Dl-Limit",0)*1024;
+ CircleBuf::BwReadLimit = Owner->ConfigFindI("Dl-Limit", 0) * 1024;
}
/*}}}*/
// CircleBuf::Reset - Reset to the default state /*{{{*/
@@ -287,9 +287,9 @@ CircleBuf::~CircleBuf()
}
// HttpServerState::HttpServerState - Constructor /*{{{*/
-HttpServerState::HttpServerState(URI Srv,HttpMethod *Owner) : ServerState(Srv, Owner), In(64*1024), Out(4*1024)
+HttpServerState::HttpServerState(URI Srv,HttpMethod *Owner) : ServerState(Srv, Owner), In(Owner, 64*1024), Out(Owner, 4*1024)
{
- TimeOut = _config->FindI("Acquire::http::Timeout",TimeOut);
+ TimeOut = Owner->ConfigFindI("Timeout", TimeOut);
Reset();
}
/*}}}*/
@@ -309,7 +309,7 @@ bool HttpServerState::Open()
// Determine the proxy setting
AutoDetectProxy(ServerName);
- string SpecificProxy = _config->Find("Acquire::http::Proxy::" + ServerName.Host);
+ string SpecificProxy = Owner->ConfigFind("Proxy::" + ServerName.Host, "");
if (!SpecificProxy.empty())
{
if (SpecificProxy == "DIRECT")
@@ -319,7 +319,7 @@ bool HttpServerState::Open()
}
else
{
- string DefProxy = _config->Find("Acquire::http::Proxy");
+ string DefProxy = Owner->ConfigFind("Proxy", "");
if (!DefProxy.empty())
{
Proxy = DefProxy;
@@ -616,7 +616,7 @@ bool HttpServerState::Go(bool ToFile, FileFd * const File)
FD_SET(FileFD,&wfds);
// Add stdin
- if (_config->FindB("Acquire::http::DependOnSTDIN", true) == true)
+ if (Owner->ConfigFindB("DependOnSTDIN", true) == true)
FD_SET(STDIN_FILENO,&rfds);
// Figure out the max fd
@@ -688,6 +688,11 @@ bool HttpServerState::Go(bool ToFile, FileFd * const File)
void HttpMethod::SendReq(FetchItem *Itm)
{
URI Uri = Itm->Uri;
+ {
+ auto const plus = Binary.find('+');
+ if (plus != std::string::npos)
+ Uri.Access = Binary.substr(plus + 1);
+ }
// The HTTP server expects a hostname with a trailing :port
std::stringstream Req;
@@ -705,7 +710,7 @@ void HttpMethod::SendReq(FetchItem *Itm)
if (Server->Proxy.empty() == true || Server->Proxy.Host.empty())
requesturi = Uri.Path;
else
- requesturi = Itm->Uri;
+ requesturi = Uri;
// The "+" is encoded as a workaround for a amazon S3 bug
// see LP bugs #1003633 and #1086997.
@@ -722,12 +727,12 @@ void HttpMethod::SendReq(FetchItem *Itm)
Req << "Host: " << ProperHost << "\r\n";
// generate a cache control header (if needed)
- if (_config->FindB("Acquire::http::No-Cache",false) == true)
+ if (ConfigFindB("No-Cache",false) == true)
Req << "Cache-Control: no-cache\r\n"
<< "Pragma: no-cache\r\n";
else if (Itm->IndexFile == true)
- Req << "Cache-Control: max-age=" << std::to_string(_config->FindI("Acquire::http::Max-Age",0)) << "\r\n";
- else if (_config->FindB("Acquire::http::No-Store",false) == true)
+ Req << "Cache-Control: max-age=" << std::to_string(ConfigFindI("Max-Age", 0)) << "\r\n";
+ else if (ConfigFindB("No-Store", false) == true)
Req << "Cache-Control: no-store\r\n";
// If we ask for uncompressed files servers might respond with content-
@@ -735,7 +740,7 @@ void HttpMethod::SendReq(FetchItem *Itm)
// see 657029, 657560 and co, so if we have no extension on the request
// ask for text only. As a sidenote: If there is nothing to negotate servers
// seem to be nice and ignore it.
- if (_config->FindB("Acquire::http::SendAccept", true) == true)
+ if (ConfigFindB("SendAccept", true) == true)
{
size_t const filepos = Itm->Uri.find_last_of('/');
string const file = Itm->Uri.substr(filepos + 1);
@@ -760,7 +765,7 @@ void HttpMethod::SendReq(FetchItem *Itm)
Req << "Authorization: Basic "
<< Base64Encode(Uri.User + ":" + Uri.Password) << "\r\n";
- Req << "User-Agent: " << _config->Find("Acquire::http::User-Agent",
+ Req << "User-Agent: " << ConfigFind("User-Agent",
"Debian APT-HTTP/1.3 (" PACKAGE_VERSION ")") << "\r\n";
Req << "\r\n";
@@ -771,22 +776,6 @@ void HttpMethod::SendReq(FetchItem *Itm)
Server->WriteResponse(Req.str());
}
/*}}}*/
-// HttpMethod::Configuration - Handle a configuration message /*{{{*/
-// ---------------------------------------------------------------------
-/* We stash the desired pipeline depth */
-bool HttpMethod::Configuration(string Message)
-{
- if (ServerMethod::Configuration(Message) == false)
- return false;
-
- AllowRedirect = _config->FindB("Acquire::http::AllowRedirect",true);
- PipelineDepth = _config->FindI("Acquire::http::Pipeline-Depth",
- PipelineDepth);
- Debug = _config->FindB("Debug::Acquire::http",false);
-
- return true;
-}
- /*}}}*/
std::unique_ptr<ServerState> HttpMethod::CreateServerState(URI const &uri)/*{{{*/
{
return std::unique_ptr<ServerState>(new HttpServerState(uri, this));
@@ -826,3 +815,15 @@ ServerMethod::DealWithHeadersResult HttpMethod::DealWithHeaders(FetchResult &Res
return FILE_IS_OPEN;
}
/*}}}*/
+HttpMethod::HttpMethod(std::string &&pProg) : ServerMethod(pProg.c_str(), "1.2", Pipeline | SendConfig)/*{{{*/
+{
+ auto addName = std::inserter(methodNames, methodNames.begin());
+ if (Binary != "http")
+ addName = "http";
+ auto const plus = Binary.find('+');
+ if (plus != std::string::npos)
+ addName = Binary.substr(0, plus);
+ File = 0;
+ Server = 0;
+}
+ /*}}}*/
diff --git a/methods/http.h b/methods/http.h
index e6b11d642..4d22c88f9 100644
--- a/methods/http.h
+++ b/methods/http.h
@@ -86,7 +86,7 @@ class CircleBuf
// Dump everything
void Stats();
- explicit CircleBuf(unsigned long long Size);
+ CircleBuf(HttpMethod const * const Owner, unsigned long long Size);
~CircleBuf();
};
@@ -126,8 +126,6 @@ class HttpMethod : public ServerMethod
public:
virtual void SendReq(FetchItem *Itm) APT_OVERRIDE;
- virtual bool Configuration(std::string Message) APT_OVERRIDE;
-
virtual std::unique_ptr<ServerState> CreateServerState(URI const &uri) APT_OVERRIDE;
virtual void RotateDNS() APT_OVERRIDE;
virtual DealWithHeadersResult DealWithHeaders(FetchResult &Res) APT_OVERRIDE;
@@ -138,11 +136,7 @@ class HttpMethod : public ServerMethod
public:
friend struct HttpServerState;
- HttpMethod() : ServerMethod("http", "1.2",Pipeline | SendConfig)
- {
- File = 0;
- Server = 0;
- };
+ explicit HttpMethod(std::string &&pProg);
};
#endif
diff --git a/methods/http_main.cc b/methods/http_main.cc
index fa183ddb3..1e56044b7 100644
--- a/methods/http_main.cc
+++ b/methods/http_main.cc
@@ -5,11 +5,13 @@
#include "http.h"
-int main()
+int main(int, const char *argv[])
{
// ignore SIGPIPE, this can happen on write() if the socket
// closes the connection (this is dealt with via ServerDie())
signal(SIGPIPE, SIG_IGN);
-
- return HttpMethod().Loop();
+ std::string Binary = flNotDir(argv[0]);
+ if (Binary.find('+') == std::string::npos && Binary != "http")
+ Binary.append("+http");
+ return HttpMethod(std::move(Binary)).Loop();
}
diff --git a/methods/https.cc b/methods/https.cc
index a5a8a7cd1..47dce2ea0 100644
--- a/methods/https.cc
+++ b/methods/https.cc
@@ -25,11 +25,14 @@
#include <sys/time.h>
#include <unistd.h>
#include <stdio.h>
-#include <iostream>
-#include <sstream>
#include <ctype.h>
#include <stdlib.h>
+#include <array>
+#include <iostream>
+#include <sstream>
+
+
#include "https.h"
#include <apti18n.h>
@@ -148,7 +151,7 @@ HttpsMethod::write_data(void *buffer, size_t size, size_t nmemb, void *userp)
// HttpsServerState::HttpsServerState - Constructor /*{{{*/
HttpsServerState::HttpsServerState(URI Srv,HttpsMethod * Owner) : ServerState(Srv, Owner), Hash(NULL)
{
- TimeOut = _config->FindI("Acquire::https::Timeout",TimeOut);
+ TimeOut = Owner->ConfigFindI("Timeout", TimeOut);
Reset();
}
/*}}}*/
@@ -179,32 +182,31 @@ bool HttpsMethod::SetupProxy() /*{{{*/
curl_easy_setopt(curl, CURLOPT_PROXY, "");
// Determine the proxy setting - try https first, fallback to http and use env at last
- string UseProxy = _config->Find("Acquire::https::Proxy::" + ServerName.Host,
- _config->Find("Acquire::http::Proxy::" + ServerName.Host).c_str());
-
+ string UseProxy = ConfigFind("Proxy::" + ServerName.Host, "");
if (UseProxy.empty() == true)
- UseProxy = _config->Find("Acquire::https::Proxy", _config->Find("Acquire::http::Proxy").c_str());
-
- // User want to use NO proxy, so nothing to setup
+ UseProxy = ConfigFind("Proxy", "");
+ // User wants to use NO proxy, so nothing to setup
if (UseProxy == "DIRECT")
return true;
- // Parse no_proxy, a comma (,) separated list of domains we don't want to use
+ // Parse no_proxy, a comma (,) separated list of domains we don't want to use
// a proxy for so we stop right here if it is in the list
if (getenv("no_proxy") != 0 && CheckDomainList(ServerName.Host,getenv("no_proxy")) == true)
return true;
if (UseProxy.empty() == true)
{
- const char* result = getenv("https_proxy");
+ const char* result = nullptr;
+ if (std::find(methodNames.begin(), methodNames.end(), "https") != methodNames.end())
+ result = getenv("https_proxy");
// FIXME: Fall back to http_proxy is to remain compatible with
// existing setups and behaviour of apt.conf. This should be
// deprecated in the future (including apt.conf). Most other
// programs do not fall back to http proxy settings and neither
// should Apt.
- if (result == NULL)
- result = getenv("http_proxy");
- UseProxy = result == NULL ? "" : result;
+ if (result == nullptr && std::find(methodNames.begin(), methodNames.end(), "http") != methodNames.end())
+ result = getenv("http_proxy");
+ UseProxy = result == nullptr ? "" : result;
}
// Determine what host and port to use based on the proxy settings
@@ -245,12 +247,19 @@ bool HttpsMethod::Fetch(FetchItem *Itm)
struct curl_slist *headers=NULL;
char curl_errorstr[CURL_ERROR_SIZE];
URI Uri = Itm->Uri;
- string remotehost = Uri.Host;
+ setPostfixForMethodNames(Uri.Host.c_str());
+ AllowRedirect = ConfigFindB("AllowRedirect", true);
+ Debug = DebugEnabled();
// TODO:
// - http::Pipeline-Depth
// - error checking/reporting
// - more debug options? (CURLOPT_DEBUGFUNCTION?)
+ {
+ auto const plus = Binary.find('+');
+ if (plus != std::string::npos)
+ Uri.Access = Binary.substr(plus + 1);
+ }
curl_easy_reset(curl);
if (SetupProxy() == false)
@@ -270,107 +279,81 @@ bool HttpsMethod::Fetch(FetchItem *Itm)
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, true);
curl_easy_setopt(curl, CURLOPT_FILETIME, true);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 0);
- // only allow curl to handle https, not the other stuff it supports
- curl_easy_setopt(curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTPS);
- curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTPS);
-
- // SSL parameters are set by default to the common (non mirror-specific) value
- // if available (or a default one) and gets overload by mirror-specific ones.
-
- // File containing the list of trusted CA.
- string cainfo = _config->Find("Acquire::https::CaInfo","");
- string knob = "Acquire::https::"+remotehost+"::CaInfo";
- cainfo = _config->Find(knob.c_str(),cainfo.c_str());
- if(cainfo.empty() == false)
- curl_easy_setopt(curl, CURLOPT_CAINFO,cainfo.c_str());
-
- // Check server certificate against previous CA list ...
- bool peer_verify = _config->FindB("Acquire::https::Verify-Peer",true);
- knob = "Acquire::https::" + remotehost + "::Verify-Peer";
- peer_verify = _config->FindB(knob.c_str(), peer_verify);
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, peer_verify);
-
- // ... and hostname against cert CN or subjectAltName
- bool verify = _config->FindB("Acquire::https::Verify-Host",true);
- knob = "Acquire::https::"+remotehost+"::Verify-Host";
- verify = _config->FindB(knob.c_str(),verify);
- int const default_verify = (verify == true) ? 2 : 0;
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, default_verify);
-
- // Also enforce issuer of server certificate using its cert
- string issuercert = _config->Find("Acquire::https::IssuerCert","");
- knob = "Acquire::https::"+remotehost+"::IssuerCert";
- issuercert = _config->Find(knob.c_str(),issuercert.c_str());
- if(issuercert.empty() == false)
- curl_easy_setopt(curl, CURLOPT_ISSUERCERT,issuercert.c_str());
-
- // For client authentication, certificate file ...
- string pem = _config->Find("Acquire::https::SslCert","");
- knob = "Acquire::https::"+remotehost+"::SslCert";
- pem = _config->Find(knob.c_str(),pem.c_str());
- if(pem.empty() == false)
- curl_easy_setopt(curl, CURLOPT_SSLCERT, pem.c_str());
-
- // ... and associated key.
- string key = _config->Find("Acquire::https::SslKey","");
- knob = "Acquire::https::"+remotehost+"::SslKey";
- key = _config->Find(knob.c_str(),key.c_str());
- if(key.empty() == false)
- curl_easy_setopt(curl, CURLOPT_SSLKEY, key.c_str());
-
- // Allow forcing SSL version to SSLv3 or TLSv1 (SSLv2 is not
- // supported by GnuTLS).
- long final_version = CURL_SSLVERSION_DEFAULT;
- string sslversion = _config->Find("Acquire::https::SslForceVersion","");
- knob = "Acquire::https::"+remotehost+"::SslForceVersion";
- sslversion = _config->Find(knob.c_str(),sslversion.c_str());
- if(sslversion == "TLSv1")
- final_version = CURL_SSLVERSION_TLSv1;
- else if(sslversion == "SSLv3")
- final_version = CURL_SSLVERSION_SSLv3;
- curl_easy_setopt(curl, CURLOPT_SSLVERSION, final_version);
-
- // CRL file
- string crlfile = _config->Find("Acquire::https::CrlFile","");
- knob = "Acquire::https::"+remotehost+"::CrlFile";
- crlfile = _config->Find(knob.c_str(),crlfile.c_str());
- if(crlfile.empty() == false)
- curl_easy_setopt(curl, CURLOPT_CRLFILE, crlfile.c_str());
+ if (std::find(methodNames.begin(), methodNames.end(), "https") != methodNames.end())
+ {
+ curl_easy_setopt(curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTPS);
+ curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTPS);
+
+ // File containing the list of trusted CA.
+ std::string const cainfo = ConfigFind("CaInfo", "");
+ if(cainfo.empty() == false)
+ curl_easy_setopt(curl, CURLOPT_CAINFO, cainfo.c_str());
+ // Check server certificate against previous CA list ...
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, ConfigFindB("Verify-Peer", true) ? 1 : 0);
+ // ... and hostname against cert CN or subjectAltName
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, ConfigFindB("Verify-Host", true) ? 2 : 0);
+ // Also enforce issuer of server certificate using its cert
+ std::string const issuercert = ConfigFind("IssuerCert", "");
+ if(issuercert.empty() == false)
+ curl_easy_setopt(curl, CURLOPT_ISSUERCERT, issuercert.c_str());
+ // For client authentication, certificate file ...
+ std::string const pem = ConfigFind("SslCert", "");
+ if(pem.empty() == false)
+ curl_easy_setopt(curl, CURLOPT_SSLCERT, pem.c_str());
+ // ... and associated key.
+ std::string const key = ConfigFind("SslKey", "");
+ if(key.empty() == false)
+ curl_easy_setopt(curl, CURLOPT_SSLKEY, key.c_str());
+ // Allow forcing SSL version to SSLv3 or TLSv1
+ long final_version = CURL_SSLVERSION_DEFAULT;
+ std::string const sslversion = ConfigFind("SslForceVersion", "");
+ if(sslversion == "TLSv1")
+ final_version = CURL_SSLVERSION_TLSv1;
+ else if(sslversion == "TLSv1.0")
+ final_version = CURL_SSLVERSION_TLSv1_0;
+ else if(sslversion == "TLSv1.1")
+ final_version = CURL_SSLVERSION_TLSv1_1;
+ else if(sslversion == "TLSv1.2")
+ final_version = CURL_SSLVERSION_TLSv1_2;
+ else if(sslversion == "SSLv3")
+ final_version = CURL_SSLVERSION_SSLv3;
+ curl_easy_setopt(curl, CURLOPT_SSLVERSION, final_version);
+ // CRL file
+ std::string const crlfile = ConfigFind("CrlFile", "");
+ if(crlfile.empty() == false)
+ curl_easy_setopt(curl, CURLOPT_CRLFILE, crlfile.c_str());
+ }
+ else
+ {
+ curl_easy_setopt(curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP);
+ curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP);
+ }
// cache-control
- if(_config->FindB("Acquire::https::No-Cache",
- _config->FindB("Acquire::http::No-Cache",false)) == false)
+ if(ConfigFindB("No-Cache", false) == false)
{
// cache enabled
- if (_config->FindB("Acquire::https::No-Store",
- _config->FindB("Acquire::http::No-Store",false)) == true)
+ if (ConfigFindB("No-Store", false) == true)
headers = curl_slist_append(headers,"Cache-Control: no-store");
- stringstream ss;
- ioprintf(ss, "Cache-Control: max-age=%u", _config->FindI("Acquire::https::Max-Age",
- _config->FindI("Acquire::http::Max-Age",0)));
- headers = curl_slist_append(headers, ss.str().c_str());
+ std::string ss;
+ strprintf(ss, "Cache-Control: max-age=%u", ConfigFindI("Max-Age", 0));
+ headers = curl_slist_append(headers, ss.c_str());
} else {
// cache disabled by user
headers = curl_slist_append(headers, "Cache-Control: no-cache");
headers = curl_slist_append(headers, "Pragma: no-cache");
}
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
-
// speed limit
- int const dlLimit = _config->FindI("Acquire::https::Dl-Limit",
- _config->FindI("Acquire::http::Dl-Limit",0))*1024;
+ int const dlLimit = ConfigFindI("Dl-Limit", 0) * 1024;
if (dlLimit > 0)
curl_easy_setopt(curl, CURLOPT_MAX_RECV_SPEED_LARGE, dlLimit);
// set header
- curl_easy_setopt(curl, CURLOPT_USERAGENT,
- _config->Find("Acquire::https::User-Agent",
- _config->Find("Acquire::http::User-Agent",
- "Debian APT-CURL/1.0 (" PACKAGE_VERSION ")").c_str()).c_str());
+ curl_easy_setopt(curl, CURLOPT_USERAGENT, ConfigFind("User-Agent", "Debian APT-CURL/1.0 (" PACKAGE_VERSION ")").c_str());
// set timeout
- int const timeout = _config->FindI("Acquire::https::Timeout",
- _config->FindI("Acquire::http::Timeout",120));
+ int const timeout = ConfigFindI("Timeout", 120);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout);
//set really low lowspeed timeout (see #497983)
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, DL_MIN_SPEED);
@@ -389,7 +372,7 @@ bool HttpsMethod::Fetch(FetchItem *Itm)
// see 657029, 657560 and co, so if we have no extension on the request
// ask for text only. As a sidenote: If there is nothing to negotate servers
// seem to be nice and ignore it.
- if (_config->FindB("Acquire::https::SendAccept", _config->FindB("Acquire::http::SendAccept", true)) == true)
+ if (ConfigFindB("SendAccept", true))
{
size_t const filepos = Itm->Uri.find_last_of('/');
string const file = Itm->Uri.substr(filepos + 1);
@@ -513,27 +496,40 @@ bool HttpsMethod::Fetch(FetchItem *Itm)
return true;
}
/*}}}*/
-// HttpsMethod::Configuration - Handle a configuration message /*{{{*/
-bool HttpsMethod::Configuration(string Message)
+std::unique_ptr<ServerState> HttpsMethod::CreateServerState(URI const &uri)/*{{{*/
{
- if (ServerMethod::Configuration(Message) == false)
- return false;
-
- AllowRedirect = _config->FindB("Acquire::https::AllowRedirect",
- _config->FindB("Acquire::http::AllowRedirect", true));
- Debug = _config->FindB("Debug::Acquire::https",false);
-
- return true;
+ return std::unique_ptr<ServerState>(new HttpsServerState(uri, this));
}
/*}}}*/
-std::unique_ptr<ServerState> HttpsMethod::CreateServerState(URI const &uri)/*{{{*/
+HttpsMethod::HttpsMethod(std::string &&pProg) : ServerMethod(std::move(pProg),"1.2",Pipeline | SendConfig)/*{{{*/
{
- return std::unique_ptr<ServerState>(new HttpsServerState(uri, this));
+ auto addName = std::inserter(methodNames, methodNames.begin());
+ addName = "http";
+ auto const plus = Binary.find('+');
+ if (plus != std::string::npos)
+ {
+ addName = Binary.substr(plus + 1);
+ auto base = Binary.substr(0, plus);
+ if (base != "https")
+ addName = base;
+ }
+ if (std::find(methodNames.begin(), methodNames.end(), "https") != methodNames.end())
+ curl_global_init(CURL_GLOBAL_SSL);
+ else
+ curl_global_init(CURL_GLOBAL_NOTHING);
+ curl = curl_easy_init();
}
/*}}}*/
-
-int main()
+HttpsMethod::~HttpsMethod() /*{{{*/
{
- return HttpsMethod().Run();
+ curl_easy_cleanup(curl);
}
-
+ /*}}}*/
+int main(int, const char *argv[]) /*{{{*/
+{
+ std::string Binary = flNotDir(argv[0]);
+ if (Binary.find('+') == std::string::npos && Binary != "https")
+ Binary.append("+https");
+ return HttpsMethod(std::move(Binary)).Run();
+}
+ /*}}}*/
diff --git a/methods/https.h b/methods/https.h
index 85cc7824e..04e72e815 100644
--- a/methods/https.h
+++ b/methods/https.h
@@ -74,21 +74,12 @@ class HttpsMethod : public ServerMethod
public:
- virtual bool Configuration(std::string Message) APT_OVERRIDE;
virtual std::unique_ptr<ServerState> CreateServerState(URI const &uri) APT_OVERRIDE;
using pkgAcqMethod::FetchResult;
using pkgAcqMethod::FetchItem;
- HttpsMethod() : ServerMethod("https","1.2",Pipeline | SendConfig)
- {
- curl_global_init(CURL_GLOBAL_SSL);
- curl = curl_easy_init();
- };
-
- ~HttpsMethod()
- {
- curl_easy_cleanup(curl);
- };
+ explicit HttpsMethod(std::string &&pProg);
+ virtual ~HttpsMethod();
};
#include <apt-pkg/strutl.h>
diff --git a/methods/mirror.cc b/methods/mirror.cc
index 9d900771b..71faaf591 100644
--- a/methods/mirror.cc
+++ b/methods/mirror.cc
@@ -57,7 +57,7 @@ using namespace std;
*/
MirrorMethod::MirrorMethod()
- : HttpMethod(), DownloadedMirrorFile(false), Debug(false)
+ : HttpMethod("mirror"), DownloadedMirrorFile(false), Debug(false)
{
}
@@ -68,7 +68,7 @@ bool MirrorMethod::Configuration(string Message)
{
if (pkgAcqMethod::Configuration(Message) == false)
return false;
- Debug = _config->FindB("Debug::Acquire::mirror",false);
+ Debug = DebugEnabled();
return true;
}
diff --git a/methods/rred.cc b/methods/rred.cc
index 2d2333f91..0c641ad82 100644
--- a/methods/rred.cc
+++ b/methods/rred.cc
@@ -572,7 +572,7 @@ class RredMethod : public aptMethod {
protected:
virtual bool URIAcquire(std::string const &Message, FetchItem *Itm) APT_OVERRIDE {
- Debug = _config->FindB("Debug::pkgAcquire::RRed", false);
+ Debug = DebugEnabled();
URI Get = Itm->Uri;
std::string Path = Get.Host + Get.Path; // rred:/path - no host
diff --git a/methods/rsh.cc b/methods/rsh.cc
index 74a908ef7..7b8af6f9b 100644
--- a/methods/rsh.cc
+++ b/methods/rsh.cc
@@ -383,9 +383,7 @@ bool RSHConn::Get(const char *Path,FileFd &To,unsigned long long Resume,
/*}}}*/
// RSHMethod::RSHMethod - Constructor /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-RSHMethod::RSHMethod(std::string const &pProg) : aptMethod(pProg.c_str(),"1.0",SendConfig), Prog(pProg)
+RSHMethod::RSHMethod(std::string &&pProg) : aptMethod(std::move(pProg),"1.0",SendConfig)
{
signal(SIGTERM,SigTerm);
signal(SIGINT,SigTerm);
@@ -399,14 +397,14 @@ bool RSHMethod::Configuration(std::string Message)
{
// enabling privilege dropping for this method requires configuration…
// … which is otherwise lifted straight from root, so use it by default.
- _config->Set(std::string("Binary::") + Prog + "::APT::Sandbox::User", "");
+ _config->Set(std::string("Binary::") + Binary + "::APT::Sandbox::User", "");
if (aptMethod::Configuration(Message) == false)
return false;
- std::string const timeconf = std::string("Acquire::") + Prog + "::Timeout";
+ std::string const timeconf = std::string("Acquire::") + Binary + "::Timeout";
TimeOut = _config->FindI(timeconf, TimeOut);
- std::string const optsconf = std::string("Acquire::") + Prog + "::Options";
+ std::string const optsconf = std::string("Acquire::") + Binary + "::Options";
RshOptions = _config->Tree(optsconf.c_str());
return true;
@@ -445,7 +443,7 @@ bool RSHMethod::Fetch(FetchItem *Itm)
// Connect to the server
if (Server == 0 || Server->Comp(Get) == false) {
delete Server;
- Server = new RSHConn(Prog, Get);
+ Server = new RSHConn(Binary, Get);
}
// Could not connect is a transient error..
diff --git a/methods/rsh.h b/methods/rsh.h
index 571e38ba6..dee4ad647 100644
--- a/methods/rsh.h
+++ b/methods/rsh.h
@@ -58,7 +58,6 @@ class RSHConn
class RSHMethod : public aptMethod
{
- std::string const Prog;
virtual bool Fetch(FetchItem *Itm) APT_OVERRIDE;
virtual bool Configuration(std::string Message) APT_OVERRIDE;
@@ -71,7 +70,7 @@ class RSHMethod : public aptMethod
public:
- explicit RSHMethod(std::string const &Prog);
+ explicit RSHMethod(std::string &&Prog);
};
#endif
diff --git a/methods/server.cc b/methods/server.cc
index 66551b893..7c85c8abb 100644
--- a/methods/server.cc
+++ b/methods/server.cc
@@ -313,10 +313,30 @@ ServerMethod::DealWithHeaders(FetchResult &Res)
{
NextURI = DeQuoteString(Server->Location);
URI tmpURI = NextURI;
- if (tmpURI.Access == "http" && Binary == "https+http")
+ if (tmpURI.Access.find('+') != std::string::npos)
{
- tmpURI.Access = "https+http";
- NextURI = tmpURI;
+ _error->Error("Server tried to trick us into using a specific implementation: %s", tmpURI.Access.c_str());
+ if (Server->HaveContent == true)
+ return ERROR_WITH_CONTENT_PAGE;
+ return ERROR_UNRECOVERABLE;
+ }
+ URI Uri = Queue->Uri;
+ if (Binary.find('+') != std::string::npos)
+ {
+ auto base = Binary.substr(0, Binary.find('+'));
+ if (base != tmpURI.Access)
+ {
+ tmpURI.Access = base + '+' + tmpURI.Access;
+ if (tmpURI.Access == Binary)
+ {
+ std::string tmpAccess = Uri.Access;
+ std::swap(tmpURI.Access, Uri.Access);
+ NextURI = tmpURI;
+ std::swap(tmpURI.Access, Uri.Access);
+ }
+ else
+ NextURI = tmpURI;
+ }
}
if (Queue->Uri == NextURI)
{
@@ -326,7 +346,7 @@ ServerMethod::DealWithHeaders(FetchResult &Res)
return ERROR_WITH_CONTENT_PAGE;
return ERROR_UNRECOVERABLE;
}
- URI Uri = Queue->Uri;
+ Uri.Access = Binary;
// same protocol redirects are okay
if (tmpURI.Access == Uri.Access)
return TRY_AGAIN_OR_REDIRECT;
@@ -334,7 +354,22 @@ ServerMethod::DealWithHeaders(FetchResult &Res)
else if ((Uri.Access == "http" || Uri.Access == "https+http") && tmpURI.Access == "https")
return TRY_AGAIN_OR_REDIRECT;
else
- _error->Error("Redirection from %s to '%s' is forbidden", Uri.Access.c_str(), NextURI.c_str());
+ {
+ auto const tmpplus = tmpURI.Access.find('+');
+ if (tmpplus != std::string::npos && tmpURI.Access.substr(tmpplus + 1) == "https")
+ {
+ auto const uriplus = Uri.Access.find('+');
+ if (uriplus == std::string::npos)
+ {
+ if (Uri.Access == tmpURI.Access.substr(0, tmpplus)) // foo -> foo+https
+ return TRY_AGAIN_OR_REDIRECT;
+ }
+ else if (Uri.Access.substr(uriplus + 1) == "http" &&
+ Uri.Access.substr(0, uriplus) == tmpURI.Access.substr(0, tmpplus)) // foo+http -> foo+https
+ return TRY_AGAIN_OR_REDIRECT;
+ }
+ }
+ _error->Error("Redirection from %s to '%s' is forbidden", Uri.Access.c_str(), NextURI.c_str());
}
/* else pass through for error message */
}
@@ -513,7 +548,7 @@ int ServerMethod::Loop()
if (Result != -1 && (Result != 0 || Queue == 0))
{
if(FailReason.empty() == false ||
- _config->FindB("Acquire::http::DependOnSTDIN", true) == true)
+ ConfigFindB("DependOnSTDIN", true) == true)
return 100;
else
return 0;
@@ -524,7 +559,13 @@ int ServerMethod::Loop()
// Connect to the server
if (Server == 0 || Server->Comp(Queue->Uri) == false)
+ {
Server = CreateServerState(Queue->Uri);
+ setPostfixForMethodNames(::URI(Queue->Uri).Host.c_str());
+ AllowRedirect = ConfigFindB("AllowRedirect", true);
+ PipelineDepth = ConfigFindI("Pipeline-Depth", 10);
+ Debug = DebugEnabled();
+ }
/* If the server has explicitly said this is the last connection
then we pre-emptively shut down the pipeline and tear down
@@ -747,8 +788,8 @@ unsigned long long ServerMethod::FindMaximumObjectSizeInQueue() const /*{{{*/
return MaxSizeInQueue;
}
/*}}}*/
-ServerMethod::ServerMethod(char const * const Binary, char const * const Ver,unsigned long const Flags) :/*{{{*/
- aptMethod(Binary, Ver, Flags), Server(nullptr), File(NULL), PipelineDepth(10),
+ServerMethod::ServerMethod(std::string &&Binary, char const * const Ver,unsigned long const Flags) :/*{{{*/
+ aptMethod(std::move(Binary), Ver, Flags), Server(nullptr), File(NULL), PipelineDepth(10),
AllowRedirect(false), Debug(false)
{
}
diff --git a/methods/server.h b/methods/server.h
index f2868c96a..f6a635dca 100644
--- a/methods/server.h
+++ b/methods/server.h
@@ -157,7 +157,7 @@ class ServerMethod : public aptMethod
virtual std::unique_ptr<ServerState> CreateServerState(URI const &uri) = 0;
virtual void RotateDNS() = 0;
- ServerMethod(char const * const Binary, char const * const Ver,unsigned long const Flags);
+ ServerMethod(std::string &&Binary, char const * const Ver,unsigned long const Flags);
virtual ~ServerMethod() {};
};
diff --git a/methods/store.cc b/methods/store.cc
index fa02d4597..1faaa4fb4 100644
--- a/methods/store.cc
+++ b/methods/store.cc
@@ -32,12 +32,15 @@
class StoreMethod : public aptMethod
{
- std::string const Prog;
virtual bool Fetch(FetchItem *Itm) APT_OVERRIDE;
public:
- explicit StoreMethod(std::string const &pProg) : aptMethod(pProg.c_str(),"1.2",SingleInstance | SendConfig), Prog(pProg) {};
+ explicit StoreMethod(std::string &&pProg) : aptMethod(std::move(pProg),"1.2",SingleInstance | SendConfig)
+ {
+ if (Binary != "store")
+ methodNames.insert(methodNames.begin(), "store");
+ }
};
static bool OpenFileWithCompressorByName(FileFd &fileFd, std::string const &Filename, unsigned int const Mode, std::string const &Name)
@@ -70,7 +73,7 @@ bool StoreMethod::Fetch(FetchItem *Itm) /*{{{*/
FileFd From;
if (_config->FindB("Method::Compress", false) == false)
{
- if (OpenFileWithCompressorByName(From, Path, FileFd::ReadOnly, Prog) == false)
+ if (OpenFileWithCompressorByName(From, Path, FileFd::ReadOnly, Binary) == false)
return false;
if(From.IsCompressed() && From.FileSize() == 0)
return _error->Error(_("Empty files can't be valid archives"));
@@ -85,7 +88,7 @@ bool StoreMethod::Fetch(FetchItem *Itm) /*{{{*/
{
if (_config->FindB("Method::Compress", false) == false)
To.Open(Itm->DestFile, FileFd::WriteOnly | FileFd::Create | FileFd::Atomic, FileFd::Extension);
- else if (OpenFileWithCompressorByName(To, Itm->DestFile, FileFd::WriteOnly | FileFd::Create | FileFd::Empty, Prog) == false)
+ else if (OpenFileWithCompressorByName(To, Itm->DestFile, FileFd::WriteOnly | FileFd::Create | FileFd::Empty, Binary) == false)
return false;
if (To.IsOpen() == false || To.Failed() == true)