summaryrefslogtreecommitdiff
path: root/methods
diff options
context:
space:
mode:
authorMichael Vogt <mvo@debian.org>2015-08-18 11:57:35 +0200
committerMichael Vogt <mvo@debian.org>2015-08-18 11:57:35 +0200
commitb53c9cea2902572822bbbece5bac236c1bbf846e (patch)
tree6c6b0524e0971c0623ccbff71383523ee0b2a5cc /methods
parent21248c0f00ee71412dbadc6ebf84011cf974346d (diff)
parent2a22cd60f04c4291ea9b9b72e15b6d2ec378b001 (diff)
Merge remote-tracking branch 'upstream/debian/experimental' into feature/srv-records
Diffstat (limited to 'methods')
-rw-r--r--methods/cdrom.cc7
-rw-r--r--methods/copy.cc10
-rw-r--r--methods/file.cc54
-rw-r--r--methods/ftp.cc3
-rw-r--r--methods/ftp.h6
-rw-r--r--methods/gpgv.cc87
-rw-r--r--methods/gzip.cc4
-rw-r--r--methods/http.h34
-rw-r--r--methods/https.h34
-rw-r--r--methods/mirror.h10
-rw-r--r--methods/rred.cc124
-rw-r--r--methods/rsh.cc22
-rw-r--r--methods/rsh.h5
-rw-r--r--methods/server.h4
14 files changed, 286 insertions, 118 deletions
diff --git a/methods/cdrom.cc b/methods/cdrom.cc
index 10cb29f66..d9ddecb6a 100644
--- a/methods/cdrom.cc
+++ b/methods/cdrom.cc
@@ -42,9 +42,9 @@ class CDROMMethod : public pkgAcqMethod
bool IsCorrectCD(URI want, string MountPath, string& NewID);
bool AutoDetectAndMount(const URI, string &NewID);
- virtual bool Fetch(FetchItem *Itm);
+ virtual bool Fetch(FetchItem *Itm) APT_OVERRIDE;
string GetID(string Name);
- virtual void Exit();
+ virtual void Exit() APT_OVERRIDE;
public:
@@ -260,7 +260,8 @@ bool CDROMMethod::Fetch(FetchItem *Itm)
struct stat Buf;
if (stat(Res.Filename.c_str(),&Buf) != 0)
return _error->Error(_("File not found"));
-
+
+ URIStart(Res);
if (NewID.empty() == false)
CurrentID = NewID;
Res.LastModified = Buf.st_mtime;
diff --git a/methods/copy.cc b/methods/copy.cc
index a8e289df5..0c9f322e6 100644
--- a/methods/copy.cc
+++ b/methods/copy.cc
@@ -27,7 +27,7 @@
class CopyMethod : public pkgAcqMethod
{
- virtual bool Fetch(FetchItem *Itm);
+ virtual bool Fetch(FetchItem *Itm) APT_OVERRIDE;
void CalculateHashes(FetchItem const * const Itm, FetchResult &Res);
public:
@@ -38,11 +38,7 @@ class CopyMethod : public pkgAcqMethod
void CopyMethod::CalculateHashes(FetchItem const * const Itm, FetchResult &Res)
{
Hashes Hash(Itm->ExpectedHashes);
- FileFd::CompressMode CompressMode = FileFd::None;
- if (_config->FindB("Acquire::GzipIndexes", false) == true)
- CompressMode = FileFd::Extension;
-
- FileFd Fd(Res.Filename, FileFd::ReadOnly, CompressMode);
+ FileFd Fd(Res.Filename, FileFd::ReadOnly, FileFd::Extension);
Hash.AddFD(Fd);
Res.TakeHashes(Hash);
}
@@ -53,7 +49,7 @@ void CopyMethod::CalculateHashes(FetchItem const * const Itm, FetchResult &Res)
bool CopyMethod::Fetch(FetchItem *Itm)
{
// this ensures that relative paths work in copy
- std::string File = Itm->Uri.substr(Itm->Uri.find(':')+1);
+ std::string const File = Itm->Uri.substr(Itm->Uri.find(':')+1);
// Stat the file and send a start message
struct stat Buf;
diff --git a/methods/file.cc b/methods/file.cc
index 043ab04b8..40e85bce5 100644
--- a/methods/file.cc
+++ b/methods/file.cc
@@ -30,7 +30,7 @@
class FileMethod : public pkgAcqMethod
{
- virtual bool Fetch(FetchItem *Itm);
+ virtual bool Fetch(FetchItem *Itm) APT_OVERRIDE;
public:
@@ -48,8 +48,27 @@ bool FileMethod::Fetch(FetchItem *Itm)
if (Get.Host.empty() == false)
return _error->Error(_("Invalid URI, local URIS must not start with //"));
- // See if the file exists
struct stat Buf;
+ // deal with destination files which might linger around
+ if (lstat(Itm->DestFile.c_str(), &Buf) == 0)
+ {
+ if ((Buf.st_mode & S_IFREG) != 0)
+ {
+ if (Itm->LastModified == Buf.st_mtime && Itm->LastModified != 0)
+ {
+ HashStringList const hsl = Itm->ExpectedHashes;
+ if (Itm->ExpectedHashes.VerifyFile(File))
+ {
+ Res.Filename = Itm->DestFile;
+ Res.IMSHit = true;
+ }
+ }
+ }
+ }
+ if (Res.IMSHit != true)
+ unlink(Itm->DestFile.c_str());
+
+ // See if the file exists
if (stat(File.c_str(),&Buf) == 0)
{
Res.Size = Buf.st_size;
@@ -57,10 +76,23 @@ bool FileMethod::Fetch(FetchItem *Itm)
Res.LastModified = Buf.st_mtime;
Res.IMSHit = false;
if (Itm->LastModified == Buf.st_mtime && Itm->LastModified != 0)
- Res.IMSHit = true;
+ {
+ unsigned long long const filesize = Itm->ExpectedHashes.FileSize();
+ if (filesize != 0 && filesize == Res.Size)
+ Res.IMSHit = true;
+ }
+
+ Hashes Hash(Itm->ExpectedHashes);
+ FileFd Fd(File, FileFd::ReadOnly);
+ Hash.AddFD(Fd);
+ Res.TakeHashes(Hash);
}
+ if (Res.IMSHit == false)
+ URIStart(Res);
// See if the uncompressed file exists and reuse it
+ FetchResult AltRes;
+ AltRes.Filename.clear();
std::vector<std::string> extensions = APT::Configuration::getCompressorExtensions();
for (std::vector<std::string>::const_iterator ext = extensions.begin(); ext != extensions.end(); ++ext)
{
@@ -69,29 +101,25 @@ bool FileMethod::Fetch(FetchItem *Itm)
std::string const unfile = File.substr(0, File.length() - ext->length() - 1);
if (stat(unfile.c_str(),&Buf) == 0)
{
- FetchResult AltRes;
AltRes.Size = Buf.st_size;
AltRes.Filename = unfile;
AltRes.LastModified = Buf.st_mtime;
AltRes.IMSHit = false;
if (Itm->LastModified == Buf.st_mtime && Itm->LastModified != 0)
AltRes.IMSHit = true;
-
- URIDone(Res,&AltRes);
- return true;
+ break;
}
// no break here as we could have situations similar to '.gz' vs '.tar.gz' here
}
}
- if (Res.Filename.empty() == true)
+ if (AltRes.Filename.empty() == false)
+ URIDone(Res,&AltRes);
+ else if (Res.Filename.empty() == false)
+ URIDone(Res);
+ else
return _error->Error(_("File not found"));
- Hashes Hash(Itm->ExpectedHashes);
- FileFd Fd(Res.Filename, FileFd::ReadOnly);
- Hash.AddFD(Fd);
- Res.TakeHashes(Hash);
- URIDone(Res);
return true;
}
/*}}}*/
diff --git a/methods/ftp.cc b/methods/ftp.cc
index 92d8573f1..1a9a1c4eb 100644
--- a/methods/ftp.cc
+++ b/methods/ftp.cc
@@ -39,7 +39,6 @@
// Internet stuff
#include <netinet/in.h>
-#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
@@ -746,7 +745,7 @@ bool FTPConn::CreateDataFd()
}
// Bind and listen
- if (bind(DataListenFd,BindAddr->ai_addr,BindAddr->ai_addrlen) < 0)
+ if (::bind(DataListenFd,BindAddr->ai_addr,BindAddr->ai_addrlen) < 0)
{
freeaddrinfo(BindAddr);
return _error->Errno("bind",_("Could not bind a socket"));
diff --git a/methods/ftp.h b/methods/ftp.h
index 2efd28ec6..2c4e9f57a 100644
--- a/methods/ftp.h
+++ b/methods/ftp.h
@@ -10,8 +10,10 @@
#ifndef APT_FTP_H
#define APT_FTP_H
+#include <apt-pkg/acquire-method.h>
#include <apt-pkg/strutl.h>
+#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <string>
@@ -71,8 +73,8 @@ class FTPConn
class FtpMethod : public pkgAcqMethod
{
- virtual bool Fetch(FetchItem *Itm);
- virtual bool Configuration(std::string Message);
+ virtual bool Fetch(FetchItem *Itm) APT_OVERRIDE;
+ virtual bool Configuration(std::string Message) APT_OVERRIDE;
FTPConn *Server;
diff --git a/methods/gpgv.cc b/methods/gpgv.cc
index 41f138be6..490833d8c 100644
--- a/methods/gpgv.cc
+++ b/methods/gpgv.cc
@@ -15,6 +15,8 @@
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
+
+#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
@@ -37,14 +39,15 @@ class GPGVMethod : public pkgAcqMethod
{
private:
string VerifyGetSigners(const char *file, const char *outfile,
- vector<string> &GoodSigners,
+ std::string const &key,
+ vector<string> &GoodSigners,
vector<string> &BadSigners,
vector<string> &WorthlessSigners,
vector<string> &NoPubKeySigners);
protected:
- virtual bool Fetch(FetchItem *Itm);
- virtual bool Configuration(string Message);
+ virtual bool URIAcquire(std::string const &Message, FetchItem *Itm) APT_OVERRIDE;
+ virtual bool Configuration(string Message) APT_OVERRIDE;
public:
GPGVMethod() : pkgAcqMethod("1.0",SingleInstance | SendConfig) {};
@@ -61,6 +64,7 @@ bool GPGVMethod::Configuration(string Message)
}
string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile,
+ std::string const &key,
vector<string> &GoodSigners,
vector<string> &BadSigners,
vector<string> &WorthlessSigners,
@@ -72,6 +76,7 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile,
std::clog << "inside VerifyGetSigners" << std::endl;
int fd[2];
+ bool const keyIsID = (key.empty() == false && key[0] != '/');
if (pipe(fd) < 0)
return "Couldn't create pipe";
@@ -80,12 +85,13 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile,
if (pid < 0)
return string("Couldn't spawn new process") + strerror(errno);
else if (pid == 0)
- ExecGPGV(outfile, file, 3, fd);
+ ExecGPGV(outfile, file, 3, fd, (keyIsID ? "" : key));
close(fd[1]);
FILE *pipein = fdopen(fd[0], "r");
// Loop over the output of apt-key (which really is gnupg), and check the signatures.
+ std::vector<std::string> ValidSigners;
size_t buffersize = 0;
char *buffer = NULL;
while (1)
@@ -105,32 +111,31 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile,
std::clog << "Got BADSIG! " << std::endl;
BadSigners.push_back(string(buffer+sizeof(GNUPGPREFIX)));
}
-
- if (strncmp(buffer, GNUPGNOPUBKEY, sizeof(GNUPGNOPUBKEY)-1) == 0)
+ else if (strncmp(buffer, GNUPGNOPUBKEY, sizeof(GNUPGNOPUBKEY)-1) == 0)
{
if (Debug == true)
std::clog << "Got NO_PUBKEY " << std::endl;
NoPubKeySigners.push_back(string(buffer+sizeof(GNUPGPREFIX)));
}
- if (strncmp(buffer, GNUPGNODATA, sizeof(GNUPGBADSIG)-1) == 0)
+ else if (strncmp(buffer, GNUPGNODATA, sizeof(GNUPGBADSIG)-1) == 0)
{
if (Debug == true)
std::clog << "Got NODATA! " << std::endl;
BadSigners.push_back(string(buffer+sizeof(GNUPGPREFIX)));
}
- if (strncmp(buffer, GNUPGKEYEXPIRED, sizeof(GNUPGKEYEXPIRED)-1) == 0)
+ else if (strncmp(buffer, GNUPGKEYEXPIRED, sizeof(GNUPGKEYEXPIRED)-1) == 0)
{
if (Debug == true)
std::clog << "Got KEYEXPIRED! " << std::endl;
WorthlessSigners.push_back(string(buffer+sizeof(GNUPGPREFIX)));
}
- if (strncmp(buffer, GNUPGREVKEYSIG, sizeof(GNUPGREVKEYSIG)-1) == 0)
+ else if (strncmp(buffer, GNUPGREVKEYSIG, sizeof(GNUPGREVKEYSIG)-1) == 0)
{
if (Debug == true)
std::clog << "Got REVKEYSIG! " << std::endl;
WorthlessSigners.push_back(string(buffer+sizeof(GNUPGPREFIX)));
}
- if (strncmp(buffer, GNUPGGOODSIG, sizeof(GNUPGGOODSIG)-1) == 0)
+ else if (strncmp(buffer, GNUPGGOODSIG, sizeof(GNUPGGOODSIG)-1) == 0)
{
char *sig = buffer + sizeof(GNUPGPREFIX);
char *p = sig + sizeof("GOODSIG");
@@ -141,10 +146,48 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile,
std::clog << "Got GOODSIG, key ID:" << sig << std::endl;
GoodSigners.push_back(string(sig));
}
+ else if (strncmp(buffer, GNUPGVALIDSIG, sizeof(GNUPGVALIDSIG)-1) == 0)
+ {
+ char *sig = buffer + sizeof(GNUPGVALIDSIG);
+ char *p = sig;
+ while (*p && isxdigit(*p))
+ p++;
+ *p = 0;
+ if (Debug == true)
+ std::clog << "Got VALIDSIG, key ID: " << sig << std::endl;
+ ValidSigners.push_back(string(sig));
+ }
}
fclose(pipein);
free(buffer);
+ // apt-key has a --keyid parameter, but this requires gpg, so we call it without it
+ // and instead check after the fact which keyids where used for verification
+ if (keyIsID == true)
+ {
+ if (Debug == true)
+ std::clog << "GoodSigs needs to be limited to keyid " << key << std::endl;
+ std::vector<std::string>::iterator const foundItr = std::find(ValidSigners.begin(), ValidSigners.end(), key);
+ bool const found = (foundItr != ValidSigners.end());
+ std::copy(GoodSigners.begin(), GoodSigners.end(), std::back_insert_iterator<std::vector<std::string> >(NoPubKeySigners));
+ if (found)
+ {
+ // we look for GOODSIG here as well as an expired sig is a valid sig as well (but not a good one)
+ std::string const goodlongkeyid = "GOODSIG " + key.substr(24, 16);
+ bool const foundGood = std::find(GoodSigners.begin(), GoodSigners.end(), goodlongkeyid) != GoodSigners.end();
+ if (Debug == true)
+ std::clog << "Key " << key << " is valid sig, is " << goodlongkeyid << " also a good one? " << (foundGood ? "yes" : "no") << std::endl;
+ GoodSigners.clear();
+ if (foundGood)
+ {
+ GoodSigners.push_back(goodlongkeyid);
+ NoPubKeySigners.erase(std::remove(NoPubKeySigners.begin(), NoPubKeySigners.end(), goodlongkeyid), NoPubKeySigners.end());
+ }
+ }
+ else
+ GoodSigners.clear();
+ }
+
int status;
waitpid(pid, &status, 0);
if (Debug == true)
@@ -154,8 +197,18 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile,
if (WEXITSTATUS(status) == 0)
{
- if (GoodSigners.empty())
- return _("Internal error: Good signature, but could not determine key fingerprint?!");
+ if (keyIsID)
+ {
+ // gpgv will report success, but we want to enforce a certain keyring
+ // so if we haven't found the key the valid we found is in fact invalid
+ if (GoodSigners.empty())
+ return _("At least one invalid signature was encountered.");
+ }
+ else
+ {
+ if (GoodSigners.empty())
+ return _("Internal error: Good signature, but could not determine key fingerprint?!");
+ }
return "";
}
else if (WEXITSTATUS(status) == 1)
@@ -174,11 +227,11 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile,
return _("Unknown error executing apt-key");
}
-bool GPGVMethod::Fetch(FetchItem *Itm)
+bool GPGVMethod::URIAcquire(std::string const &Message, FetchItem *Itm)
{
- URI Get = Itm->Uri;
- string Path = Get.Host + Get.Path; // To account for relative paths
- string keyID;
+ URI const Get = Itm->Uri;
+ string const Path = Get.Host + Get.Path; // To account for relative paths
+ std::string const key = LookupTag(Message, "Signed-By");
vector<string> GoodSigners;
vector<string> BadSigners;
// a worthless signature is a expired or revoked one
@@ -190,7 +243,7 @@ bool GPGVMethod::Fetch(FetchItem *Itm)
URIStart(Res);
// Run apt-key on file, extract contents and get the key ID of the signer
- string msg = VerifyGetSigners(Path.c_str(), Itm->DestFile.c_str(),
+ string msg = VerifyGetSigners(Path.c_str(), Itm->DestFile.c_str(), key,
GoodSigners, BadSigners, WorthlessSigners,
NoPubKeySigners);
if (GoodSigners.empty() || !BadSigners.empty() || !NoPubKeySigners.empty())
diff --git a/methods/gzip.cc b/methods/gzip.cc
index 65519633c..637aae124 100644
--- a/methods/gzip.cc
+++ b/methods/gzip.cc
@@ -32,8 +32,8 @@ const char *Prog;
class GzipMethod : public pkgAcqMethod
{
- virtual bool Fetch(FetchItem *Itm);
- virtual bool Configuration(std::string Message);
+ virtual bool Fetch(FetchItem *Itm) APT_OVERRIDE;
+ virtual bool Configuration(std::string Message) APT_OVERRIDE;
public:
diff --git a/methods/http.h b/methods/http.h
index e73871931..da6139b02 100644
--- a/methods/http.h
+++ b/methods/http.h
@@ -99,23 +99,23 @@ struct HttpServerState: public ServerState
int ServerFd;
protected:
- virtual bool ReadHeaderLines(std::string &Data);
- virtual bool LoadNextResponse(bool const ToFile, FileFd * const File);
- virtual bool WriteResponse(std::string const &Data);
+ virtual bool ReadHeaderLines(std::string &Data) APT_OVERRIDE;
+ virtual bool LoadNextResponse(bool const ToFile, FileFd * const File) APT_OVERRIDE;
+ virtual bool WriteResponse(std::string const &Data) APT_OVERRIDE;
public:
- virtual void Reset() { ServerState::Reset(); ServerFd = -1; };
+ virtual void Reset() APT_OVERRIDE { ServerState::Reset(); ServerFd = -1; };
- virtual bool RunData(FileFd * const File);
+ virtual bool RunData(FileFd * const File) APT_OVERRIDE;
- virtual bool Open();
- virtual bool IsOpen();
- virtual bool Close();
- virtual bool InitHashes(HashStringList const &ExpectedHashes);
- virtual Hashes * GetHashes();
- virtual bool Die(FileFd &File);
- virtual bool Flush(FileFd * const File);
- virtual bool Go(bool ToFile, FileFd * const File);
+ virtual bool Open() APT_OVERRIDE;
+ virtual bool IsOpen() APT_OVERRIDE;
+ virtual bool Close() APT_OVERRIDE;
+ virtual bool InitHashes(HashStringList const &ExpectedHashes) APT_OVERRIDE;
+ virtual Hashes * GetHashes() APT_OVERRIDE;
+ virtual bool Die(FileFd &File) APT_OVERRIDE;
+ virtual bool Flush(FileFd * const File) APT_OVERRIDE;
+ virtual bool Go(bool ToFile, FileFd * const File) APT_OVERRIDE;
HttpServerState(URI Srv, HttpMethod *Owner);
virtual ~HttpServerState() {Close();};
@@ -124,12 +124,12 @@ struct HttpServerState: public ServerState
class HttpMethod : public ServerMethod
{
public:
- virtual void SendReq(FetchItem *Itm);
+ virtual void SendReq(FetchItem *Itm) APT_OVERRIDE;
- virtual bool Configuration(std::string Message);
+ virtual bool Configuration(std::string Message) APT_OVERRIDE;
- virtual ServerState * CreateServerState(URI uri);
- virtual void RotateDNS();
+ virtual ServerState * CreateServerState(URI uri) APT_OVERRIDE;
+ virtual void RotateDNS() APT_OVERRIDE;
protected:
std::string AutoDetectProxyCmd;
diff --git a/methods/https.h b/methods/https.h
index 57fc292ee..29b20b921 100644
--- a/methods/https.h
+++ b/methods/https.h
@@ -32,23 +32,23 @@ class HttpsServerState : public ServerState
Hashes * Hash;
protected:
- virtual bool ReadHeaderLines(std::string &/*Data*/) { return false; }
- virtual bool LoadNextResponse(bool const /*ToFile*/, FileFd * const /*File*/) { return false; }
+ virtual bool ReadHeaderLines(std::string &/*Data*/) APT_OVERRIDE { return false; }
+ virtual bool LoadNextResponse(bool const /*ToFile*/, FileFd * const /*File*/) APT_OVERRIDE { return false; }
public:
- virtual bool WriteResponse(std::string const &/*Data*/) { return false; }
+ virtual bool WriteResponse(std::string const &/*Data*/) APT_OVERRIDE { return false; }
/** \brief Transfer the data from the socket */
- virtual bool RunData(FileFd * const /*File*/) { return false; }
+ virtual bool RunData(FileFd * const /*File*/) APT_OVERRIDE { return false; }
- virtual bool Open() { return false; }
- virtual bool IsOpen() { return false; }
- virtual bool Close() { return false; }
- virtual bool InitHashes(HashStringList const &ExpectedHashes);
- virtual Hashes * GetHashes();
- virtual bool Die(FileFd &/*File*/) { return false; }
- virtual bool Flush(FileFd * const /*File*/) { return false; }
- virtual bool Go(bool /*ToFile*/, FileFd * const /*File*/) { return false; }
+ virtual bool Open() APT_OVERRIDE { return false; }
+ virtual bool IsOpen() APT_OVERRIDE { return false; }
+ virtual bool Close() APT_OVERRIDE { return false; }
+ virtual bool InitHashes(HashStringList const &ExpectedHashes) APT_OVERRIDE;
+ virtual Hashes * GetHashes() APT_OVERRIDE;
+ virtual bool Die(FileFd &/*File*/) APT_OVERRIDE { return false; }
+ virtual bool Flush(FileFd * const /*File*/) APT_OVERRIDE { return false; }
+ virtual bool Go(bool /*ToFile*/, FileFd * const /*File*/) APT_OVERRIDE { return false; }
HttpsServerState(URI Srv, HttpsMethod *Owner);
virtual ~HttpsServerState() {Close();};
@@ -59,7 +59,7 @@ class HttpsMethod : public ServerMethod
// minimum speed in bytes/se that triggers download timeout handling
static const int DL_MIN_SPEED = 10;
- virtual bool Fetch(FetchItem *);
+ virtual bool Fetch(FetchItem *) APT_OVERRIDE;
static size_t parse_header(void *buffer, size_t size, size_t nmemb, void *userp);
static size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp);
@@ -70,14 +70,14 @@ class HttpsMethod : public ServerMethod
ServerState *Server;
// Used by ServerMethods unused by https
- virtual void SendReq(FetchItem *) { exit(42); }
- virtual void RotateDNS() { exit(42); }
+ virtual void SendReq(FetchItem *) APT_OVERRIDE { exit(42); }
+ virtual void RotateDNS() APT_OVERRIDE { exit(42); }
public:
FileFd *File;
- virtual bool Configuration(std::string Message);
- virtual ServerState * CreateServerState(URI uri);
+ virtual bool Configuration(std::string Message) APT_OVERRIDE;
+ virtual ServerState * CreateServerState(URI uri) APT_OVERRIDE;
using pkgAcqMethod::FetchResult;
using pkgAcqMethod::FetchItem;
diff --git a/methods/mirror.h b/methods/mirror.h
index 6c0ce370e..425bea673 100644
--- a/methods/mirror.h
+++ b/methods/mirror.h
@@ -46,14 +46,14 @@ class MirrorMethod : public HttpMethod
bool Clean(std::string dir);
// we need to overwrite those to transform the url back
- virtual void Fail(std::string Why, bool Transient = false);
- virtual void URIStart(FetchResult &Res);
- virtual void URIDone(FetchResult &Res,FetchResult *Alt = 0);
- virtual bool Configuration(std::string Message);
+ virtual void Fail(std::string Why, bool Transient = false) APT_OVERRIDE;
+ virtual void URIStart(FetchResult &Res) APT_OVERRIDE;
+ virtual void URIDone(FetchResult &Res,FetchResult *Alt = 0) APT_OVERRIDE;
+ virtual bool Configuration(std::string Message) APT_OVERRIDE;
public:
MirrorMethod();
- virtual bool Fetch(FetchItem *Itm);
+ virtual bool Fetch(FetchItem *Itm) APT_OVERRIDE;
};
diff --git a/methods/rred.cc b/methods/rred.cc
index 554ac99b4..91b6dda22 100644
--- a/methods/rred.cc
+++ b/methods/rred.cc
@@ -21,6 +21,7 @@
#include <vector>
#include <assert.h>
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -35,7 +36,7 @@ class MemBlock {
char *start;
size_t size;
char *free;
- struct MemBlock *next;
+ MemBlock *next;
MemBlock(size_t size) : size(size), next(NULL)
{
@@ -116,7 +117,7 @@ struct Change {
size_t add_len; /* bytes */
char *add;
- Change(int off)
+ Change(size_t off)
{
offset = off;
del_cnt = add_cnt = add_len = 0;
@@ -388,28 +389,37 @@ class Patch {
public:
- void read_diff(FileFd &f)
+ bool read_diff(FileFd &f, Hashes * const h)
{
char buffer[BLOCK_SIZE];
bool cmdwanted = true;
- Change ch(0);
- while(f.ReadLine(buffer, sizeof(buffer)))
- {
+ Change ch(std::numeric_limits<size_t>::max());
+ if (f.ReadLine(buffer, sizeof(buffer)) == NULL)
+ return _error->Error("Reading first line of patchfile %s failed", f.Name().c_str());
+ do {
+ if (h != NULL)
+ h->Add(buffer);
if (cmdwanted) {
char *m, *c;
size_t s, e;
- s = strtol(buffer, &m, 10);
- if (m == buffer) {
- s = e = ch.offset + ch.add_cnt;
- c = buffer;
- } else if (*m == ',') {
- m++;
+ errno = 0;
+ s = strtoul(buffer, &m, 10);
+ if (unlikely(m == buffer || s == std::numeric_limits<unsigned long>::max() || errno != 0))
+ return _error->Error("Parsing patchfile %s failed: Expected an effected line start", f.Name().c_str());
+ else if (*m == ',') {
+ ++m;
e = strtol(m, &c, 10);
+ if (unlikely(m == c || e == std::numeric_limits<unsigned long>::max() || errno != 0))
+ return _error->Error("Parsing patchfile %s failed: Expected an effected line end", f.Name().c_str());
+ if (unlikely(e < s))
+ return _error->Error("Parsing patchfile %s failed: Effected lines end %lu is before start %lu", f.Name().c_str(), e, s);
} else {
e = s;
c = m;
}
+ if (s > ch.offset)
+ return _error->Error("Parsing patchfile %s failed: Effected line is after previous effected line", f.Name().c_str());
switch(*c) {
case 'a':
cmdwanted = false;
@@ -420,6 +430,8 @@ class Patch {
ch.del_cnt = 0;
break;
case 'c':
+ if (unlikely(s == 0))
+ return _error->Error("Parsing patchfile %s failed: Change command can't effect line zero", f.Name().c_str());
cmdwanted = false;
ch.add = NULL;
ch.add_cnt = 0;
@@ -428,6 +440,8 @@ class Patch {
ch.del_cnt = e - s + 1;
break;
case 'd':
+ if (unlikely(s == 0))
+ return _error->Error("Parsing patchfile %s failed: Delete command can't effect line zero", f.Name().c_str());
ch.offset = s - 1;
ch.del_cnt = e - s + 1;
ch.add = NULL;
@@ -435,9 +449,11 @@ class Patch {
ch.add_len = 0;
filechanges.add_change(ch);
break;
+ default:
+ return _error->Error("Parsing patchfile %s failed: Unknown command", f.Name().c_str());
}
} else { /* !cmdwanted */
- if (buffer[0] == '.' && buffer[1] == '\n') {
+ if (strcmp(buffer, ".\n") == 0) {
cmdwanted = true;
filechanges.add_change(ch);
} else {
@@ -463,7 +479,8 @@ class Patch {
}
}
}
- }
+ } while(f.ReadLine(buffer, sizeof(buffer)));
+ return true;
}
void write_diff(FILE *f)
@@ -519,8 +536,29 @@ class RredMethod : public pkgAcqMethod {
private:
bool Debug;
+ struct PDiffFile {
+ std::string FileName;
+ HashStringList ExpectedHashes;
+ PDiffFile(std::string const &FileName, HashStringList const &ExpectedHashes) :
+ FileName(FileName), ExpectedHashes(ExpectedHashes) {}
+ };
+
+ HashStringList ReadExpectedHashesForPatch(unsigned int const patch, std::string const &Message)
+ {
+ HashStringList ExpectedHashes;
+ for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type)
+ {
+ std::string tagname;
+ strprintf(tagname, "Patch-%d-%s-Hash", patch, *type);
+ std::string const hashsum = LookupTag(Message, tagname.c_str());
+ if (hashsum.empty() == false)
+ ExpectedHashes.push_back(HashString(*type, hashsum));
+ }
+ return ExpectedHashes;
+ }
+
protected:
- virtual bool Fetch(FetchItem *Itm) {
+ virtual bool URIAcquire(std::string const &Message, FetchItem *Itm) APT_OVERRIDE {
Debug = _config->FindB("Debug::pkgAcquire::RRed", false);
URI Get = Itm->Uri;
std::string Path = Get.Host + Get.Path; // rred:/path - no host
@@ -534,11 +572,17 @@ class RredMethod : public pkgAcqMethod {
} else
URIStart(Res);
- std::vector<std::string> patchpaths;
+ std::vector<PDiffFile> patchfiles;
Patch patch;
if (FileExists(Path + ".ed") == true)
- patchpaths.push_back(Path + ".ed");
+ {
+ HashStringList const ExpectedHashes = ReadExpectedHashesForPatch(0, Message);
+ std::string const FileName = Path + ".ed";
+ if (ExpectedHashes.usable() == false)
+ return _error->Error("No hashes found for uncompressed patch: %s", FileName.c_str());
+ patchfiles.push_back(PDiffFile(FileName, ExpectedHashes));
+ }
else
{
_error->PushToStack();
@@ -546,31 +590,44 @@ class RredMethod : public pkgAcqMethod {
_error->RevertToStack();
std::string const baseName = Path + ".ed.";
+ unsigned int seen_patches = 0;
for (std::vector<std::string>::const_iterator p = patches.begin();
p != patches.end(); ++p)
+ {
if (p->compare(0, baseName.length(), baseName) == 0)
- patchpaths.push_back(*p);
+ {
+ HashStringList const ExpectedHashes = ReadExpectedHashesForPatch(seen_patches, Message);
+ if (ExpectedHashes.usable() == false)
+ return _error->Error("No hashes found for uncompressed patch %d: %s", seen_patches, p->c_str());
+ patchfiles.push_back(PDiffFile(*p, ExpectedHashes));
+ ++seen_patches;
+ }
+ }
}
std::string patch_name;
- for (std::vector<std::string>::iterator I = patchpaths.begin();
- I != patchpaths.end();
+ for (std::vector<PDiffFile>::iterator I = patchfiles.begin();
+ I != patchfiles.end();
++I)
{
- patch_name = *I;
+ patch_name = I->FileName;
if (Debug == true)
std::clog << "Patching " << Path << " with " << patch_name
<< std::endl;
FileFd p;
+ Hashes patch_hash(I->ExpectedHashes);
// all patches are compressed, even if the name doesn't reflect it
- if (p.Open(patch_name, FileFd::ReadOnly, FileFd::Gzip) == false) {
- std::cerr << "Could not open patch file " << patch_name << std::endl;
+ if (p.Open(patch_name, FileFd::ReadOnly, FileFd::Gzip) == false ||
+ patch.read_diff(p, &patch_hash) == false)
+ {
_error->DumpErrors(std::cerr);
- abort();
+ return false;
}
- patch.read_diff(p);
p.Close();
+ HashStringList const hsl = patch_hash.GetHashStringList();
+ if (hsl != I->ExpectedHashes)
+ return _error->Error("Hash Sum mismatch for uncompressed patch %s", patch_name.c_str());
}
if (Debug == true)
@@ -582,7 +639,6 @@ class RredMethod : public pkgAcqMethod {
FILE *out = fopen(Itm->DestFile.c_str(), "w");
Hashes hash(Itm->ExpectedHashes);
-
patch.apply_against_file(out, inp, &hash);
fclose(out);
@@ -615,6 +671,16 @@ class RredMethod : public pkgAcqMethod {
return true;
}
+ bool Configuration(std::string Message) APT_OVERRIDE
+ {
+ if (pkgAcqMethod::Configuration(Message) == false)
+ return false;
+
+ DropPrivsOrDie();
+
+ return true;
+ }
+
public:
RredMethod() : pkgAcqMethod("2.0",SingleInstance | SendConfig), Debug(false) {}
};
@@ -643,7 +709,11 @@ int main(int argc, char **argv)
_error->DumpErrors(std::cerr);
exit(1);
}
- patch.read_diff(p);
+ if (patch.read_diff(p, NULL) == false)
+ {
+ _error->DumpErrors(std::cerr);
+ exit(2);
+ }
}
if (just_diff) {
diff --git a/methods/rsh.cc b/methods/rsh.cc
index 52349c61c..7ef2f7c7a 100644
--- a/methods/rsh.cc
+++ b/methods/rsh.cc
@@ -84,7 +84,7 @@ bool RSHConn::Open()
if (Process != -1)
return true;
- if (Connect(ServerName.Host,ServerName.User) == false)
+ if (Connect(ServerName.Host,ServerName.Port,ServerName.User) == false)
return false;
return true;
@@ -93,8 +93,15 @@ bool RSHConn::Open()
// RSHConn::Connect - Fire up rsh and connect /*{{{*/
// ---------------------------------------------------------------------
/* */
-bool RSHConn::Connect(std::string Host, std::string User)
+bool RSHConn::Connect(std::string Host, unsigned int Port, std::string User)
{
+ char *PortStr = NULL;
+ if (Port != 0)
+ {
+ if (asprintf (&PortStr, "%d", Port) == -1 || PortStr == NULL)
+ return _error->Errno("asprintf", _("Failed"));
+ }
+
// Create the pipes
int Pipes[4] = {-1,-1,-1,-1};
if (pipe(Pipes) != 0 || pipe(Pipes+2) != 0)
@@ -140,6 +147,10 @@ bool RSHConn::Connect(std::string Host, std::string User)
Args[i++] = "-l";
Args[i++] = User.c_str();
}
+ if (PortStr != NULL) {
+ Args[i++] = "-p";
+ Args[i++] = PortStr;
+ }
if (Host.empty() == false) {
Args[i++] = Host.c_str();
}
@@ -149,6 +160,9 @@ bool RSHConn::Connect(std::string Host, std::string User)
exit(100);
}
+ if (PortStr != NULL)
+ free(PortStr);
+
ReadFd = Pipes[0];
WriteFd = Pipes[3];
SetNonBlock(Pipes[0],true);
@@ -158,6 +172,10 @@ bool RSHConn::Connect(std::string Host, std::string User)
return true;
}
+bool RSHConn::Connect(std::string Host, std::string User)
+{
+ return Connect(Host, 0, User);
+}
/*}}}*/
// RSHConn::ReadLine - Very simple buffered read with timeout /*{{{*/
// ---------------------------------------------------------------------
diff --git a/methods/rsh.h b/methods/rsh.h
index dd259e744..e6839711b 100644
--- a/methods/rsh.h
+++ b/methods/rsh.h
@@ -36,6 +36,7 @@ class RSHConn
// Raw connection IO
bool WriteMsg(std::string &Text,bool Sync,const char *Fmt,...);
bool Connect(std::string Host, std::string User);
+ bool Connect(std::string Host, unsigned int Port, std::string User);
bool Comp(URI Other) const {return Other.Host == ServerName.Host && Other.Port == ServerName.Port;};
// Connection control
@@ -56,8 +57,8 @@ class RSHConn
class RSHMethod : public pkgAcqMethod
{
- virtual bool Fetch(FetchItem *Itm);
- virtual bool Configuration(std::string Message);
+ virtual bool Fetch(FetchItem *Itm) APT_OVERRIDE;
+ virtual bool Configuration(std::string Message) APT_OVERRIDE;
RSHConn *Server;
diff --git a/methods/server.h b/methods/server.h
index 8d7d33ee6..f9f6e9071 100644
--- a/methods/server.h
+++ b/methods/server.h
@@ -106,7 +106,7 @@ struct ServerState
class ServerMethod : public pkgAcqMethod
{
protected:
- virtual bool Fetch(FetchItem *);
+ virtual bool Fetch(FetchItem *) APT_OVERRIDE;
ServerState *Server;
std::string NextURI;
@@ -146,7 +146,7 @@ class ServerMethod : public pkgAcqMethod
static time_t FailTime;
static APT_NORETURN void SigTerm(int);
- virtual bool Configuration(std::string Message);
+ virtual bool Configuration(std::string Message) APT_OVERRIDE;
virtual bool Flush() { return Server->Flush(File); };
int Loop();