summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apt-pkg/acquire-method.cc31
-rw-r--r--apt-pkg/acquire-worker.cc2
-rw-r--r--apt-pkg/contrib/fileutl.cc4
-rw-r--r--apt-pkg/contrib/gpgv.cc446
-rw-r--r--apt-pkg/deb/debindexfile.cc11
-rw-r--r--apt-pkg/tagfile.cc8
-rw-r--r--apt-private/private-cmndline.cc6
-rw-r--r--apt-private/private-install.cc4
-rw-r--r--apt-private/private-json-hooks.cc2
-rw-r--r--cmdline/apt-extracttemplates.cc34
-rw-r--r--cmdline/apt-get.cc1
-rw-r--r--cmdline/apt.cc1
-rw-r--r--doc/apt-get.8.xml4
-rw-r--r--doc/apt.8.xml2
-rw-r--r--po/fr.po132
-rw-r--r--po/ru.po14
-rwxr-xr-xtest/integration/test-apt-extracttemplates7
-rwxr-xr-xtest/integration/test-apt-sources-deb82268
-rwxr-xr-xtest/integration/test-cve-2013-1051-InRelease-parsing7
-rwxr-xr-xtest/integration/test-cve-2019-3462-Release.gpg-payload43
-rwxr-xr-xtest/integration/test-method-gpgv48
-rw-r--r--test/libapt/openmaybeclearsignedfile_test.cc164
-rw-r--r--test/libapt/tagfile_test.cc2
23 files changed, 701 insertions, 340 deletions
diff --git a/apt-pkg/acquire-method.cc b/apt-pkg/acquire-method.cc
index c67c47ab8..ae5ae4a15 100644
--- a/apt-pkg/acquire-method.cc
+++ b/apt-pkg/acquire-method.cc
@@ -88,6 +88,37 @@ pkgAcqMethod::pkgAcqMethod(const char *Ver,unsigned long Flags)
/*}}}*/
void pkgAcqMethod::SendMessage(std::string const &header, std::unordered_map<std::string, std::string> &&fields) /*{{{*/
{
+ auto CheckKey = [](std::string const &str) {
+ // Space, hyphen-minus, and alphanum are allowed for keys/headers.
+ return str.find_first_not_of(" -0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz") == std::string::npos;
+ };
+
+ auto CheckValue = [](std::string const &str) {
+ return std::all_of(str.begin(), str.end(), [](unsigned char c) -> bool {
+ return c > 127 // unicode
+ || (c > 31 && c < 127) // printable chars
+ || c == '\n' || c == '\t'; // special whitespace
+ });
+ };
+
+ auto Error = [this]() {
+ _error->Error("SECURITY: Message contains control characters, rejecting.");
+ _error->DumpErrors();
+ SendMessage("400 URI Failure", {{"URI", "<UNKNOWN>"}, {"Message", "SECURITY: Message contains control characters, rejecting."}});
+ abort();
+ };
+
+ if (!CheckKey(header))
+ return Error();
+
+ for (auto const &f : fields)
+ {
+ if (!CheckKey(f.first))
+ return Error();
+ if (!CheckValue(f.second))
+ return Error();
+ }
+
std::cout << header << '\n';
for (auto const &f : fields)
{
diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc
index c2bbf8bed..b36186121 100644
--- a/apt-pkg/acquire-worker.cc
+++ b/apt-pkg/acquire-worker.cc
@@ -98,6 +98,8 @@ bool pkgAcquire::Worker::Start()
std::string Method;
if (_config->Exists(confItem))
Method = _config->FindFile(confItem.c_str());
+ else if (Access == "ftp" || Access == "rsh" || Access == "ssh")
+ return _error->Error(_("The method '%s' is unsupported and disabled by default. Consider switching to http(s). Set Dir::Bin::Methods::%s to \"%s\" to enable it again."), Access.c_str(), Access.c_str(), Access.c_str());
else
Method = _config->FindDir(methodsDir) + Access;
if (FileExists(Method) == false)
diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc
index eab05de4f..8cb4b509c 100644
--- a/apt-pkg/contrib/fileutl.cc
+++ b/apt-pkg/contrib/fileutl.cc
@@ -3114,7 +3114,7 @@ FileFd* GetTempFile(std::string const &Prefix, bool ImmediateUnlink, FileFd * co
snprintf(fn, sizeof(fn), "%s/%s.XXXXXX",
tempdir.c_str(), Prefix.c_str());
int const fd = mkstemp(fn);
- if(ImmediateUnlink)
+ if (ImmediateUnlink)
unlink(fn);
if (fd < 0)
{
@@ -3130,6 +3130,8 @@ FileFd* GetTempFile(std::string const &Prefix, bool ImmediateUnlink, FileFd * co
delete Fd;
return nullptr;
}
+ if (ImmediateUnlink == false)
+ Fd->SetFileName(fn);
return Fd;
}
/*}}}*/
diff --git a/apt-pkg/contrib/gpgv.cc b/apt-pkg/contrib/gpgv.cc
index f8ab8d715..b845528d8 100644
--- a/apt-pkg/contrib/gpgv.cc
+++ b/apt-pkg/contrib/gpgv.cc
@@ -20,18 +20,94 @@
#include <algorithm>
#include <fstream>
#include <iostream>
+#include <memory>
#include <sstream>
#include <string>
#include <vector>
#include <apti18n.h>
/*}}}*/
-static char * GenerateTemporaryFileTemplate(const char *basename) /*{{{*/
+
+// syntactic sugar to wrap a raw pointer with a custom deleter in a std::unique_ptr
+static std::unique_ptr<char, decltype(&free)> make_unique_char(void *const str = nullptr)
+{
+ return {static_cast<char *>(str), &free};
+}
+static std::unique_ptr<FILE, decltype(&fclose)> make_unique_FILE(std::string const &filename, char const *const mode)
{
- std::string out;
- std::string tmpdir = GetTempDir();
- strprintf(out, "%s/%s.XXXXXX", tmpdir.c_str(), basename);
- return strdup(out.c_str());
+ return {fopen(filename.c_str(), mode), &fclose};
+}
+
+class LineBuffer /*{{{*/
+{
+ char *buffer = nullptr;
+ size_t buffer_size = 0;
+ int line_length = 0;
+ // a "normal" find_last_not_of returns npos if not found
+ int find_last_not_of_length(APT::StringView const bad) const
+ {
+ for (int result = line_length - 1; result >= 0; --result)
+ if (bad.find(buffer[result]) == APT::StringView::npos)
+ return result + 1;
+ return 0;
+ }
+
+ public:
+ bool empty() const noexcept { return view().empty(); }
+ APT::StringView view() const noexcept { return {buffer, static_cast<size_t>(line_length)}; }
+ bool starts_with(APT::StringView const start) const { return view().substr(0, start.size()) == start; }
+
+ bool writeTo(FileFd *const to, size_t offset = 0) const
+ {
+ if (to == nullptr)
+ return true;
+ return to->Write(buffer + offset, line_length - offset);
+ }
+ bool writeLineTo(FileFd *const to) const
+ {
+ if (to == nullptr)
+ return true;
+ buffer[line_length] = '\n';
+ bool const result = to->Write(buffer, line_length + 1);
+ buffer[line_length] = '\0';
+ return result;
+ }
+ bool writeNewLineIf(FileFd *const to, bool const condition) const
+ {
+ if (not condition || to == nullptr)
+ return true;
+ return to->Write("\n", 1);
+ }
+
+ bool readFrom(FILE *stream, std::string const &InFile, bool acceptEoF = false)
+ {
+ errno = 0;
+ line_length = getline(&buffer, &buffer_size, stream);
+ if (errno != 0)
+ return _error->Errno("getline", "Could not read from %s", InFile.c_str());
+ if (line_length == -1)
+ {
+ if (acceptEoF)
+ return false;
+ return _error->Error("Splitting of clearsigned file %s failed as it doesn't contain all expected parts", InFile.c_str());
+ }
+ // a) remove newline characters, so we can work consistently with lines
+ line_length = find_last_not_of_length("\n\r");
+ // b) remove trailing whitespaces as defined by rfc4880 §7.1
+ line_length = find_last_not_of_length(" \t");
+ buffer[line_length] = '\0';
+ return true;
+ }
+
+ ~LineBuffer() { free(buffer); }
+};
+static bool operator==(LineBuffer const &buf, APT::StringView const exp) noexcept
+{
+ return buf.view() == exp;
+}
+static bool operator!=(LineBuffer const &buf, APT::StringView const exp) noexcept
+{
+ return buf.view() != exp;
}
/*}}}*/
// ExecGPGV - returns the command needed for verify /*{{{*/
@@ -47,11 +123,10 @@ static char * GenerateTemporaryFileTemplate(const char *basename) /*{{{*/
*/
static bool iovprintf(std::ostream &out, const char *format,
va_list &args, ssize_t &size) {
- char *S = (char*)malloc(size);
- ssize_t const n = vsnprintf(S, size, format, args);
+ auto S = make_unique_char(malloc(size));
+ ssize_t const n = vsnprintf(S.get(), size, format, args);
if (n > -1 && n < size) {
- out << S;
- free(S);
+ out << S.get();
return true;
} else {
if (n > -1)
@@ -59,7 +134,6 @@ static bool iovprintf(std::ostream &out, const char *format,
else
size *= 2;
}
- free(S);
return false;
}
static void APT_PRINTF(4) apt_error(std::ostream &outterm, int const statusfd, int fd[2], const char *format, ...)
@@ -73,7 +147,7 @@ static void APT_PRINTF(4) apt_error(std::ostream &outterm, int const statusfd, i
va_start(args,format);
ret = iovprintf(out, format, args, size);
va_end(args);
- if (ret == true)
+ if (ret)
break;
}
if (statusfd != -1)
@@ -81,8 +155,8 @@ static void APT_PRINTF(4) apt_error(std::ostream &outterm, int const statusfd, i
auto const errtag = "[APTKEY:] ERROR ";
outstr << '\n';
auto const errtext = outstr.str();
- if (FileFd::Write(fd[1], errtag, strlen(errtag)) == false ||
- FileFd::Write(fd[1], errtext.data(), errtext.size()) == false)
+ if (not FileFd::Write(fd[1], errtag, strlen(errtag)) ||
+ not FileFd::Write(fd[1], errtext.data(), errtext.size()))
outterm << errtext << std::flush;
}
}
@@ -141,83 +215,134 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG,
Opts = Opts->Child;
for (; Opts != 0; Opts = Opts->Next)
{
- if (Opts->Value.empty() == true)
+ if (Opts->Value.empty())
continue;
Args.push_back(Opts->Value.c_str());
}
}
enum { DETACHED, CLEARSIGNED } releaseSignature = (FileGPG != File) ? DETACHED : CLEARSIGNED;
- char * sig = NULL;
- char * data = NULL;
- char * conf = nullptr;
+ auto sig = make_unique_char();
+ auto data = make_unique_char();
+ auto conf = make_unique_char();
// Dump the configuration so apt-key picks up the correct Dir values
{
- conf = GenerateTemporaryFileTemplate("apt.conf");
+ {
+ std::string tmpfile;
+ strprintf(tmpfile, "%s/apt.conf.XXXXXX", GetTempDir().c_str());
+ conf.reset(strdup(tmpfile.c_str()));
+ }
if (conf == nullptr) {
apt_error(std::cerr, statusfd, fd, "Couldn't create tempfile names for passing config to apt-key");
local_exit(EINTERNAL);
}
- int confFd = mkstemp(conf);
+ int confFd = mkstemp(conf.get());
if (confFd == -1) {
- apt_error(std::cerr, statusfd, fd, "Couldn't create temporary file %s for passing config to apt-key", conf);
+ apt_error(std::cerr, statusfd, fd, "Couldn't create temporary file %s for passing config to apt-key", conf.get());
local_exit(EINTERNAL);
}
- local_exit.files.push_back(conf);
+ local_exit.files.push_back(conf.get());
- std::ofstream confStream(conf);
+ std::ofstream confStream(conf.get());
close(confFd);
_config->Dump(confStream);
confStream.close();
- setenv("APT_CONFIG", conf, 1);
+ setenv("APT_CONFIG", conf.get(), 1);
}
if (releaseSignature == DETACHED)
{
- Args.push_back(FileGPG.c_str());
- Args.push_back(File.c_str());
- }
- else // clear-signed file
- {
- sig = GenerateTemporaryFileTemplate("apt.sig");
- data = GenerateTemporaryFileTemplate("apt.data");
- if (sig == NULL || data == NULL)
+ auto detached = make_unique_FILE(FileGPG, "r");
+ if (detached.get() == nullptr)
{
- apt_error(std::cerr, statusfd, fd, "Couldn't create tempfile names for splitting up %s", File.c_str());
+ apt_error(std::cerr, statusfd, fd, "Detached signature file '%s' could not be opened", FileGPG.c_str());
local_exit(EINTERNAL);
}
-
- int const sigFd = mkstemp(sig);
- int const dataFd = mkstemp(data);
- if (dataFd != -1)
- local_exit.files.push_back(data);
- if (sigFd != -1)
- local_exit.files.push_back(sig);
- if (sigFd == -1 || dataFd == -1)
+ LineBuffer buf;
+ bool open_signature = false;
+ bool found_badcontent = false;
+ size_t found_signatures = 0;
+ while (buf.readFrom(detached.get(), FileGPG, true))
{
- apt_error(std::cerr, statusfd, fd, "Couldn't create tempfiles for splitting up %s", File.c_str());
- local_exit(EINTERNAL);
+ if (open_signature)
+ {
+ if (buf == "-----END PGP SIGNATURE-----")
+ open_signature = false;
+ else if (buf.starts_with("-"))
+ {
+ // the used Radix-64 is not using dash for any value, so a valid line can't
+ // start with one. Header keys could, but no existent one does and seems unlikely.
+ // Instead it smells a lot like a header the parser didn't recognize.
+ apt_error(std::cerr, statusfd, fd, "Detached signature file '%s' contains unexpected line starting with a dash", FileGPG.c_str());
+ local_exit(112);
+ }
+ }
+ else //if (not open_signature)
+ {
+ if (buf == "-----BEGIN PGP SIGNATURE-----")
+ {
+ open_signature = true;
+ ++found_signatures;
+ if (found_badcontent)
+ break;
+ }
+ else
+ {
+ found_badcontent = true;
+ if (found_signatures != 0)
+ break;
+ }
+ }
+ }
+ if (found_signatures == 0 && statusfd != -1)
+ {
+ // This is not an attack attempt but a file even gpgv would complain about
+ // likely the result of a paywall which is covered by the gpgv method
+ auto const errtag = "[GNUPG:] NODATA\n";
+ FileFd::Write(fd[1], errtag, strlen(errtag));
+ local_exit(113);
+ }
+ else if (found_badcontent)
+ {
+ apt_error(std::cerr, statusfd, fd, "Detached signature file '%s' contains lines not belonging to a signature", FileGPG.c_str());
+ local_exit(112);
+ }
+ if (open_signature)
+ {
+ apt_error(std::cerr, statusfd, fd, "Detached signature file '%s' contains unclosed signatures", FileGPG.c_str());
+ local_exit(112);
}
+ Args.push_back(FileGPG.c_str());
+ Args.push_back(File.c_str());
+ }
+ else // clear-signed file
+ {
FileFd signature;
- signature.OpenDescriptor(sigFd, FileFd::WriteOnly, true);
+ if (GetTempFile("apt.sig", false, &signature) == nullptr)
+ local_exit(EINTERNAL);
+ sig.reset(strdup(signature.Name().c_str()));
+ local_exit.files.push_back(sig.get());
FileFd message;
- message.OpenDescriptor(dataFd, FileFd::WriteOnly, true);
+ if (GetTempFile("apt.data", false, &message) == nullptr)
+ local_exit(EINTERNAL);
+ data.reset(strdup(message.Name().c_str()));
+ local_exit.files.push_back(data.get());
- if (signature.Failed() == true || message.Failed() == true ||
- SplitClearSignedFile(File, &message, nullptr, &signature) == false)
+ if (signature.Failed() || message.Failed() ||
+ not SplitClearSignedFile(File, &message, nullptr, &signature))
{
apt_error(std::cerr, statusfd, fd, "Splitting up %s into data and signature failed", File.c_str());
local_exit(112);
}
- Args.push_back(sig);
- Args.push_back(data);
+ Args.push_back(sig.get());
+ Args.push_back(data.get());
}
Args.push_back(NULL);
- if (Debug == true)
+ if (Debug)
{
std::clog << "Preparing to exec: ";
for (std::vector<const char *>::const_iterator a = Args.begin(); *a != NULL; ++a)
@@ -270,7 +395,7 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG,
}
// check if it exit'ed normally …
- if (WIFEXITED(Status) == false)
+ if (not WIFEXITED(Status))
{
apt_error(std::cerr, statusfd, fd, _("Sub-process %s exited unexpectedly"), "apt-key");
local_exit(EINTERNAL);
@@ -289,168 +414,141 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG,
}
/*}}}*/
// SplitClearSignedFile - split message into data/signature /*{{{*/
-static int GetLineErrno(char **lineptr, size_t *n, FILE *stream, std::string const &InFile)
+bool SplitClearSignedFile(std::string const &InFile, FileFd * const ContentFile,
+ std::vector<std::string> * const ContentHeader, FileFd * const SignatureFile)
{
- int result;
+ auto in = make_unique_FILE(InFile, "r");
+ if (in.get() == nullptr)
+ return _error->Errno("fopen", "can not open %s", InFile.c_str());
- errno = 0;
- result = getline(lineptr, n, stream);
- if (errno != 0)
+ struct ScopedErrors
+ {
+ ScopedErrors() { _error->PushToStack(); }
+ ~ScopedErrors() { _error->MergeWithStack(); }
+ } scoped;
+ LineBuffer buf;
+
+ // start of the message
+ if (not buf.readFrom(in.get(), InFile))
+ return false; // empty or read error
+ if (buf != "-----BEGIN PGP SIGNED MESSAGE-----")
{
- _error->Errno("getline", "Could not read from %s", InFile.c_str());
- return -1;
+ // this might be an unsigned file we don't want to report errors for,
+ // but still finish unsuccessful none the less.
+ while (buf.readFrom(in.get(), InFile, true))
+ if (buf == "-----BEGIN PGP SIGNED MESSAGE-----")
+ return _error->Error("Clearsigned file '%s' does not start with a signed message block.", InFile.c_str());
+
+ return false;
}
- return result;
-}
-bool SplitClearSignedFile(std::string const &InFile, FileFd * const ContentFile,
- std::vector<std::string> * const ContentHeader, FileFd * const SignatureFile)
-{
- FILE *in = fopen(InFile.c_str(), "r");
- if (in == NULL)
- return _error->Errno("fopen", "can not open %s", InFile.c_str());
+ // save "Hash" Armor Headers
+ while (true)
+ {
+ if (not buf.readFrom(in.get(), InFile))
+ return false;
+ if (buf.empty())
+ break; // empty line ends the Armor Headers
+ if (buf.starts_with("-"))
+ // § 6.2 says unknown keys should be reported to the user. We don't go that far,
+ // but we assume that there will never be a header key starting with a dash
+ return _error->Error("Clearsigned file '%s' contains unexpected line starting with a dash (%s)", InFile.c_str(), "armor");
+ if (ContentHeader != nullptr && buf.starts_with("Hash: "))
+ ContentHeader->push_back(buf.view().to_string());
+ }
- bool found_message_start = false;
- bool found_message_end = false;
- bool skip_until_empty_line = false;
- bool found_signature = false;
+ // the message itself
bool first_line = true;
- bool signed_message_not_on_first_line = false;
- bool found_garbage = false;
-
- char *buf = NULL;
- size_t buf_size = 0;
- _error->PushToStack();
- while (GetLineErrno(&buf, &buf_size, in, InFile) != -1)
+ while (true)
{
- _strrstrip(buf);
- if (found_message_start == false)
+ if (not buf.readFrom(in.get(), InFile))
+ return false;
+
+ if (buf.starts_with("-"))
{
- if (strcmp(buf, "-----BEGIN PGP SIGNED MESSAGE-----") == 0)
+ if (buf == "-----BEGIN PGP SIGNATURE-----")
+ {
+ if (not buf.writeLineTo(SignatureFile))
+ return false;
+ break;
+ }
+ else if (buf.starts_with("- "))
{
- found_message_start = true;
- skip_until_empty_line = true;
+ // we don't have any fields which need to be dash-escaped,
+ // but implementations are free to escape all lines …
+ if (not buf.writeNewLineIf(ContentFile, not first_line) || not buf.writeTo(ContentFile, 2))
+ return false;
}
else
- signed_message_not_on_first_line = found_garbage = true;
+ // § 7.1 says a client should warn, but we don't really work with files which
+ // should contain lines starting with a dash, so it is a lot more likely that
+ // this is an attempt to trick our parser vs. gpgv parser into ignoring a header
+ return _error->Error("Clearsigned file '%s' contains unexpected line starting with a dash (%s)", InFile.c_str(), "msg");
}
- else if (skip_until_empty_line == true)
+ else if (not buf.writeNewLineIf(ContentFile, not first_line) || not buf.writeTo(ContentFile))
+ return false;
+ first_line = false;
+ }
+
+ // collect all signatures
+ bool open_signature = true;
+ while (true)
+ {
+ if (not buf.readFrom(in.get(), InFile, true))
+ break;
+
+ if (open_signature)
{
- if (strlen(buf) == 0)
- skip_until_empty_line = false;
- // save "Hash" Armor Headers, others aren't allowed
- else if (ContentHeader != NULL && strncmp(buf, "Hash: ", strlen("Hash: ")) == 0)
- ContentHeader->push_back(buf);
+ if (buf == "-----END PGP SIGNATURE-----")
+ open_signature = false;
+ else if (buf.starts_with("-"))
+ // the used Radix-64 is not using dash for any value, so a valid line can't
+ // start with one. Header keys could, but no existent one does and seems unlikely.
+ // Instead it smells a lot like a header the parser didn't recognize.
+ return _error->Error("Clearsigned file '%s' contains unexpected line starting with a dash (%s)", InFile.c_str(), "sig");
}
- else if (found_signature == false)
+ else //if (not open_signature)
{
- if (strcmp(buf, "-----BEGIN PGP SIGNATURE-----") == 0)
- {
- found_signature = true;
- found_message_end = true;
- if (SignatureFile != NULL)
- {
- SignatureFile->Write(buf, strlen(buf));
- SignatureFile->Write("\n", 1);
- }
- }
- else if (found_message_end == false) // we are in the message block
- {
- // we don't have any fields which need dash-escaped,
- // but implementations are free to encode all lines …
- char const * dashfree = buf;
- if (strncmp(dashfree, "- ", 2) == 0)
- dashfree += 2;
- if(first_line == true) // first line does not need a newline
- first_line = false;
- else if (ContentFile != NULL)
- ContentFile->Write("\n", 1);
- else
- continue;
- if (ContentFile != NULL)
- ContentFile->Write(dashfree, strlen(dashfree));
- }
+ if (buf == "-----BEGIN PGP SIGNATURE-----")
+ open_signature = true;
else
- found_garbage = true;
+ return _error->Error("Clearsigned file '%s' contains unsigned lines.", InFile.c_str());
}
- else if (found_signature == true)
- {
- if (SignatureFile != NULL)
- {
- SignatureFile->Write(buf, strlen(buf));
- SignatureFile->Write("\n", 1);
- }
- if (strcmp(buf, "-----END PGP SIGNATURE-----") == 0)
- found_signature = false; // look for other signatures
- }
- // all the rest is whitespace, unsigned garbage or additional message blocks we ignore
- else
- found_garbage = true;
+
+ if (not buf.writeLineTo(SignatureFile))
+ return false;
}
- fclose(in);
- if (buf != NULL)
- free(buf);
+ if (open_signature)
+ return _error->Error("Signature in file %s wasn't closed", InFile.c_str());
- // Flush the files. Errors will be checked below.
+ // Flush the files
if (SignatureFile != nullptr)
SignatureFile->Flush();
if (ContentFile != nullptr)
ContentFile->Flush();
- if (found_message_start)
- {
- if (signed_message_not_on_first_line)
- _error->Warning("Clearsigned file '%s' does not start with a signed message block.", InFile.c_str());
- else if (found_garbage)
- _error->Warning("Clearsigned file '%s' contains unsigned lines.", InFile.c_str());
- }
-
- // An error occurred during reading - propagate it up
- bool const hasErrored = _error->PendingError();
- _error->MergeWithStack();
- if (hasErrored)
- return false;
-
- if (found_signature == true)
- return _error->Error("Signature in file %s wasn't closed", InFile.c_str());
-
- // if we haven't found any of them, this an unsigned file,
- // so don't generate an error, but splitting was unsuccessful none-the-less
- if (first_line == true && found_message_start == false && found_message_end == false)
+ // Catch-all for "unhandled" read/sync errors
+ if (_error->PendingError())
return false;
- // otherwise one missing indicates a syntax error
- else if (first_line == true || found_message_start == false || found_message_end == false)
- return _error->Error("Splitting of file %s failed as it doesn't contain all expected parts %i %i %i", InFile.c_str(), first_line, found_message_start, found_message_end);
-
return true;
}
/*}}}*/
bool OpenMaybeClearSignedFile(std::string const &ClearSignedFileName, FileFd &MessageFile) /*{{{*/
{
- char * const message = GenerateTemporaryFileTemplate("fileutl.message");
- int const messageFd = mkstemp(message);
- if (messageFd == -1)
- {
- free(message);
- return _error->Errno("mkstemp", "Couldn't create temporary file to work with %s", ClearSignedFileName.c_str());
- }
- // we have the fd, that's enough for us
- unlink(message);
- free(message);
-
- MessageFile.OpenDescriptor(messageFd, FileFd::ReadWrite | FileFd::BufferedWrite, true);
- if (MessageFile.Failed() == true)
+ if (GetTempFile("clearsigned.message", true, &MessageFile) == nullptr)
+ return false;
+ if (MessageFile.Failed())
return _error->Error("Couldn't open temporary file to work with %s", ClearSignedFileName.c_str());
_error->PushToStack();
bool const splitDone = SplitClearSignedFile(ClearSignedFileName, &MessageFile, NULL, NULL);
bool const errorDone = _error->PendingError();
_error->MergeWithStack();
- if (splitDone == false)
+ if (not splitDone)
{
MessageFile.Close();
- if (errorDone == true)
+ if (errorDone)
return false;
// we deal with an unsigned file
@@ -458,10 +556,10 @@ bool OpenMaybeClearSignedFile(std::string const &ClearSignedFileName, FileFd &Me
}
else // clear-signed
{
- if (MessageFile.Seek(0) == false)
+ if (not MessageFile.Seek(0))
return _error->Errno("lseek", "Unable to seek back in message for file %s", ClearSignedFileName.c_str());
}
- return MessageFile.Failed() == false;
+ return not MessageFile.Failed();
}
/*}}}*/
diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc
index f7e3c7a5c..25e0a3312 100644
--- a/apt-pkg/deb/debindexfile.cc
+++ b/apt-pkg/deb/debindexfile.cc
@@ -315,13 +315,10 @@ const pkgIndexFile::Type *debStringPackageIndex::GetType() const
debStringPackageIndex::debStringPackageIndex(std::string const &content) :
pkgDebianIndexRealFile("", false), d(NULL)
{
- char fn[1024];
- std::string const tempdir = GetTempDir();
- snprintf(fn, sizeof(fn), "%s/%s.XXXXXX", tempdir.c_str(), "apt-tmp-index");
- int const fd = mkstemp(fn);
- File = fn;
- FileFd::Write(fd, content.data(), content.length());
- close(fd);
+ FileFd fd;
+ GetTempFile("apt-tmp-index", false, &fd);
+ fd.Write(content.data(), content.length());
+ File = fd.Name();
}
debStringPackageIndex::~debStringPackageIndex()
{
diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc
index 98001afd1..1e7f2867c 100644
--- a/apt-pkg/tagfile.cc
+++ b/apt-pkg/tagfile.cc
@@ -250,8 +250,12 @@ bool pkgTagFile::Step(pkgTagSection &Tag)
d->chunks.erase(d->chunks.begin(), first);
}
- Tag.Trim();
- return true;
+ if ((d->Flags & pkgTagFile::SUPPORT_COMMENTS) == 0 || Tag.Count() != 0)
+ {
+ Tag.Trim();
+ return true;
+ }
+ return Step(Tag);
}
/*}}}*/
// TagFile::Fill - Top up the buffer /*{{{*/
diff --git a/apt-private/private-cmndline.cc b/apt-private/private-cmndline.cc
index 87deb6bf0..494928332 100644
--- a/apt-private/private-cmndline.cc
+++ b/apt-private/private-cmndline.cc
@@ -175,7 +175,7 @@ static bool addArgumentsAPTHelper(std::vector<CommandLine::Args> &Args, char con
/*}}}*/
static bool addArgumentsAPTGet(std::vector<CommandLine::Args> &Args, char const * const Cmd)/*{{{*/
{
- if (CmdMatches("install", "remove", "purge", "upgrade", "dist-upgrade",
+ if (CmdMatches("install", "reinstall", "remove", "purge", "upgrade", "dist-upgrade",
"dselect-upgrade", "autoremove", "autopurge", "full-upgrade"))
{
addArg(0, "show-progress", "DpkgPM::Progress", 0);
@@ -239,7 +239,7 @@ static bool addArgumentsAPTGet(std::vector<CommandLine::Args> &Args, char const
else if (CmdMatches("moo"))
addArg(0, "color", "APT::Moo::Color", 0);
- if (CmdMatches("install", "remove", "purge", "upgrade", "dist-upgrade",
+ if (CmdMatches("install", "reinstall", "remove", "purge", "upgrade", "dist-upgrade",
"dselect-upgrade", "autoremove", "auto-remove", "autopurge", "clean", "autoclean", "auto-clean", "check",
"build-dep", "full-upgrade", "source"))
{
@@ -291,7 +291,7 @@ static bool addArgumentsAPTMark(std::vector<CommandLine::Args> &Args, char const
{
addArg('f',"file","Dir::State::extended_states",CommandLine::HasArg);
}
- else if (CmdMatches("install", "remove", "deinstall", "purge",
+ else if (CmdMatches("install", "reinstall", "remove", "deinstall", "purge",
"showinstall", "showinstalls", "showremove", "showremoves",
"showdeinstall", "showdeinstalls", "showpurge", "showpurges"))
;
diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc
index 1713ff308..243b75b1c 100644
--- a/apt-private/private-install.cc
+++ b/apt-private/private-install.cc
@@ -586,7 +586,9 @@ bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector<PseudoPkg
Fix.reset(new pkgProblemResolver(Cache));
unsigned short fallback = MOD_INSTALL;
- if (strcasecmp(CmdL.FileList[0],"remove") == 0)
+ if (strcasecmp(CmdL.FileList[0], "reinstall") == 0)
+ _config->Set("APT::Get::ReInstall", "true");
+ else if (strcasecmp(CmdL.FileList[0],"remove") == 0)
fallback = MOD_REMOVE;
else if (strcasecmp(CmdL.FileList[0], "purge") == 0)
{
diff --git a/apt-private/private-json-hooks.cc b/apt-private/private-json-hooks.cc
index b5c1a7172..65ff87924 100644
--- a/apt-private/private-json-hooks.cc
+++ b/apt-private/private-json-hooks.cc
@@ -387,7 +387,7 @@ bool RunJsonHook(std::string const &option, std::string const &method, const cha
if (size < 0)
{
- if (errno != ECONNRESET)
+ if (errno != ECONNRESET && errno != EPIPE)
_error->Error("Could not read response to hello message from hook %s: %s", Opts->Value.c_str(), strerror(errno));
goto out;
}
diff --git a/cmdline/apt-extracttemplates.cc b/cmdline/apt-extracttemplates.cc
index bd23453f3..bc8a27dbe 100644
--- a/cmdline/apt-extracttemplates.cc
+++ b/cmdline/apt-extracttemplates.cc
@@ -229,29 +229,13 @@ static bool ShowHelp(CommandLine &) /*{{{*/
/* */
static string WriteFile(const char *package, const char *prefix, const char *data)
{
- char fn[512];
-
- std::string tempdir = GetTempDir();
- snprintf(fn, sizeof(fn), "%s/%s.%s.XXXXXX",
- _config->Find("APT::ExtractTemplates::TempDir",
- tempdir.c_str()).c_str(),
- package, prefix);
- FileFd f;
- if (data == NULL)
- data = "";
- int fd = mkstemp(fn);
- if (fd < 0) {
- _error->Errno("ofstream::ofstream",_("Unable to mkstemp %s"),fn);
- return string();
- }
- if (!f.OpenDescriptor(fd, FileFd::WriteOnly, FileFd::None, true))
- {
- _error->Errno("ofstream::ofstream",_("Unable to write to %s"),fn);
- return string();
- }
- f.Write(data, strlen(data));
- f.Close();
- return fn;
+ FileFd f;
+ std::string tplname;
+ strprintf(tplname, "%s.%s", package, prefix);
+ GetTempFile(tplname, false, &f);
+ if (data != nullptr)
+ f.Write(data, strlen(data));
+ return f.Name();
}
/*}}}*/
// WriteConfig - write out the config data from a debian package file /*{{{*/
@@ -289,6 +273,10 @@ static bool Go(CommandLine &CmdL)
if (debconfver.empty() == true)
return _error->Error( _("Cannot get debconf version. Is debconf installed?"));
+ auto const tmpdir = _config->Find("APT::ExtractTemplates::TempDir");
+ if (tmpdir.empty() == false)
+ setenv("TMPDIR", tmpdir.c_str(), 1);
+
// Process each package passsed in
for (unsigned int I = 0; I != CmdL.FileSize(); I++)
{
diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc
index 6d25ed509..da18d2d19 100644
--- a/cmdline/apt-get.cc
+++ b/cmdline/apt-get.cc
@@ -405,6 +405,7 @@ static std::vector<aptDispatchWithHelp> GetCommands() /*{{{*/
{"update", &DoUpdate, _("Retrieve new lists of packages")},
{"upgrade", &DoUpgrade, _("Perform an upgrade")},
{"install", &DoInstall, _("Install new packages (pkg is libc6 not libc6.deb)")},
+ {"reinstall", &DoInstall, _("Reinstall packages (pkg is libc6 not libc6.deb)")},
{"remove", &DoInstall, _("Remove packages")},
{"purge", &DoInstall, _("Remove packages and config files")},
{"autoremove", &DoInstall, _("Remove automatically all unused packages")},
diff --git a/cmdline/apt.cc b/cmdline/apt.cc
index f508406d1..d388e4af4 100644
--- a/cmdline/apt.cc
+++ b/cmdline/apt.cc
@@ -63,6 +63,7 @@ static std::vector<aptDispatchWithHelp> GetCommands() /*{{{*/
// package stuff
{"install", &DoInstall, _("install packages")},
+ {"reinstall", &DoInstall, _("reinstall packages")},
{"remove", &DoInstall, _("remove packages")},
{"autoremove", &DoInstall, _("Remove automatically all unused packages")},
{"auto-remove", &DoInstall, nullptr},
diff --git a/doc/apt-get.8.xml b/doc/apt-get.8.xml
index 184282e69..b83eabd27 100644
--- a/doc/apt-get.8.xml
+++ b/doc/apt-get.8.xml
@@ -143,6 +143,10 @@
with a '^' or '$' character, or create a more specific regular expression.</para></listitem>
</varlistentry>
+ <varlistentry><term><option>reinstall</option></term>
+ <listitem><para><literal>reinstall</literal> is an alias for <literal>install --reinstall</literal>.</para></listitem>
+ </varlistentry>
+
<varlistentry><term><option>remove</option></term>
<listitem><para><literal>remove</literal> is identical to <literal>install</literal> except that packages are
removed instead of installed. Note that removing a package leaves its
diff --git a/doc/apt.8.xml b/doc/apt.8.xml
index 626419ec3..08492bf54 100644
--- a/doc/apt.8.xml
+++ b/doc/apt.8.xml
@@ -69,7 +69,7 @@
</para></listitem>
</varlistentry>
- <varlistentry><term><option>install</option>, <option>remove</option>, <option>purge</option> (&apt-get;)</term>
+ <varlistentry><term><option>install</option>, <option>reinstall</option>, <option>remove</option>, <option>purge</option> (&apt-get;)</term>
<listitem><para>Performs the requested action on one or more packages
specified via &regex;, &glob; or exact match. The requested action
can be overridden for specific packages by append a plus (+) to the
diff --git a/po/fr.po b/po/fr.po
index 2b94b2518..18c8a5604 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -4,13 +4,14 @@
#
# Pierre Machard <pmachard@tuxfamily.org>, 2002,2003,2004.
# Christian Perrier <bubulle@debian.org>, 2004-2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013.
-# Julien Patriarca <leatherface@debian.org>, 2013, 2017, 2018
+# Julien Patriarca <leatherface@debian.org>, 2013, 2017, 2018.
+# Baptiste Jammet <baptiste@mailoo.org>, 2019.
msgid ""
msgstr ""
"Project-Id-Version: apt 1.0.5\n"
"Report-Msgid-Bugs-To: APT Development Team <deity@lists.debian.org>\n"
-"POT-Creation-Date: 2019-01-23 16:49+0100\n"
-"PO-Revision-Date: 2018-01-02 15:09+0100\n"
+"POT-Creation-Date: 2018-12-18 15:02+0100\n"
+"PO-Revision-Date: 2019-01-21 09:19+0100\n"
"Last-Translator: Julien Patriarca <leatherface@debian.org>\n"
"Language-Team: French <debian-l10n-french@lists.debian.org>\n"
"Language: fr\n"
@@ -22,7 +23,7 @@ msgstr ""
#: apt-inst/contrib/arfile.cc
msgid "Invalid archive signature"
-msgstr "Signature d'archive invalide"
+msgstr "Signature d'archive non valable"
#: apt-inst/contrib/arfile.cc
msgid "Error reading archive member header"
@@ -35,7 +36,7 @@ msgstr "En-tête du membre d'archive %s non valable"
#: apt-inst/contrib/arfile.cc
msgid "Invalid archive member header"
-msgstr "En-tête du membre d'archive non-valable"
+msgstr "En-tête du membre d'archive non valable"
#: apt-inst/contrib/arfile.cc
msgid "Archive is too short"
@@ -66,7 +67,7 @@ msgstr "Type d'en-tête %u inconnu pour TAR, partie %s"
#: apt-inst/deb/debfile.cc
#, c-format
msgid "This is not a valid DEB archive, missing '%s' member"
-msgstr "Ce n'est pas une archive DEB valide, partie « %s » manquante"
+msgstr "Ce n'est pas une archive DEB valable, partie « %s » manquante"
#: apt-inst/deb/debfile.cc
#, c-format
@@ -196,7 +197,7 @@ msgid ""
"disabled by default."
msgstr ""
"Les mises à jour depuis un tel dépôt ne peuvent s'effectuer de manière "
-"sécurisée, et sont donc désactivées par défaut"
+"sécurisée, et sont donc désactivées par défaut."
#: apt-pkg/acquire-item.cc
msgid ""
@@ -273,7 +274,7 @@ msgstr "Taille incohérente"
#: apt-pkg/acquire-item.cc
msgid "Invalid file format"
-msgstr "Format de fichier invalide"
+msgstr "Format de fichier non valable"
#: apt-pkg/acquire-item.cc
msgid "Signature error"
@@ -321,7 +322,7 @@ msgid ""
"architecture '%s'"
msgstr ""
"Le fichier configuré « %s » ne sera pas pris en compte car le dépôt « %s » "
-"ne supporte pas l'architecture « %s »"
+"ne prend pas en charge l'architecture « %s »"
#: apt-pkg/acquire-item.cc
#, c-format
@@ -350,14 +351,14 @@ msgid ""
"Release file for %s is expired (invalid since %s). Updates for this "
"repository will not be applied."
msgstr ""
-"Le fichier « Release » pour %s a expiré (invalide depuis %s). Les mises à "
+"Le fichier « Release » pour %s est périmé (invalide depuis %s). Les mises à "
"jour depuis ce dépôt ne s'effectueront pas."
#. TRANSLATOR: The first %s is the URL of the bad Release file, the second is
#. the time until the file will be valid - formatted in the same way as in
#. the download progress display (e.g. 7d 3h 42min 1s)
#: apt-pkg/acquire-item.cc
-#, fuzzy, c-format
+#, c-format
#| msgid ""
#| "Release file for %s is expired (invalid since %s). Updates for this "
#| "repository will not be applied."
@@ -365,8 +366,8 @@ msgid ""
"Release file for %s is not valid yet (invalid for another %s). Updates for "
"this repository will not be applied."
msgstr ""
-"Le fichier « Release » pour %s a expiré (invalide depuis %s). Les mises à "
-"jour depuis ce dépôt ne s'effectueront pas."
+"Le fichier « Release » pour %s n'est pas encore valable (invalide pendant "
+"encore %s). Les mises à jour depuis ce dépôt ne s'effectueront pas."
#: apt-pkg/acquire-item.cc
#, c-format
@@ -439,7 +440,7 @@ msgstr "La méthode « %s » est volontairement désactivée par configuration
#, c-format
msgid "If you meant to use Tor remember to use %s instead of %s."
msgstr ""
-".Si vous souhaitiez utiliser Tor veuillez alors utiliser « %s » plutôt que "
+".Si vous souhaitiez utiliser Tor, veuillez alors utiliser « %s » plutôt que "
"« %s »."
#: apt-pkg/acquire-worker.cc
@@ -729,8 +730,8 @@ msgid ""
"Command line option '%c' [from %s] is not understood in combination with the "
"other options."
msgstr ""
-"L'option « %c » de la ligne de commande [%s] est inconnue quand elle est "
-"utilisée avec d'autres options."
+"L'option « %c » de la ligne de commande [%s] n'est pas reconnue quand elle "
+"est utilisée avec d'autres options."
#: apt-pkg/contrib/cmndline.cc
#, c-format
@@ -769,7 +770,9 @@ msgstr "L'option « %s » est trop longue"
#: apt-pkg/contrib/cmndline.cc
#, c-format
msgid "Sense %s is not understood, try true or false."
-msgstr "La signification %s n'est pas comprise, veuillez essayer vrai ou faux."
+msgstr ""
+"La signification %s n'est pas comprise, veuillez essayer « true » ou "
+"« false »."
#: apt-pkg/contrib/cmndline.cc
#, c-format
@@ -888,7 +891,7 @@ msgstr ""
#: cmdline/apt-dump-solver.cc
#, c-format
msgid "Waited for %s but it wasn't there"
-msgstr "A attendu %s mais il n'était pas présent"
+msgstr "A attendu %s, mais il n'était pas présent"
#: apt-pkg/contrib/fileutl.cc
#, c-format
@@ -987,7 +990,7 @@ msgstr "Impossible de mapper un fichier vide en mémoire"
#: apt-pkg/contrib/mmap.cc
#, c-format
msgid "Couldn't make mmap of %llu bytes"
-msgstr "Impossible de réaliser un mapping de %llu octets en mémoire"
+msgstr "Impossible de réaliser un mappage de %llu octets en mémoire"
#: apt-pkg/contrib/mmap.cc
#, c-format
@@ -1005,7 +1008,7 @@ msgstr "Impossible de synchroniser la « mmap »"
#: apt-pkg/contrib/mmap.cc
#, c-format
msgid "Couldn't make mmap of %lu bytes"
-msgstr "Impossible de réaliser un mapping de %lu octets en mémoire"
+msgstr "Impossible de réaliser un mappage de %lu octets en mémoire"
#: apt-pkg/contrib/mmap.cc
msgid "Failed to truncate file"
@@ -1160,23 +1163,23 @@ msgid "Unable to parse package file %s (%d)"
msgstr "Impossible de traiter le fichier %s (%d)"
#: apt-pkg/deb/debsystem.cc
-#, fuzzy, c-format
+#, c-format
#| msgid ""
#| "Unable to lock the administration directory (%s), is another process "
#| "using it?"
msgid ""
"Unable to acquire the dpkg frontend lock (%s), is another process using it?"
msgstr ""
-"Impossible de verrouiller le répertoire d'administration (%s). Il est "
-"possible qu'un autre processus l'utilise."
+"Impossible d'obtenir le verrou de dpkg (%s). Il est possible qu'un autre "
+"processus l'utilise."
#: apt-pkg/deb/debsystem.cc
-#, fuzzy, c-format
+#, c-format
#| msgid "Unable to lock the administration directory (%s), are you root?"
msgid "Unable to acquire the dpkg frontend lock (%s), are you root?"
msgstr ""
-"Impossible de verrouiller le répertoire d'administration (%s). Avez-vous les "
-"privilèges du superutilisateur ?"
+"Impossible d'obtenir le verrou de dpkg (%s). Avez-vous les droits du "
+"superutilisateur ?"
#. TRANSLATORS: the %s contains the recovery command, usually
#. dpkg --configure -a
@@ -1202,7 +1205,7 @@ msgstr ""
msgid "Unable to lock the administration directory (%s), are you root?"
msgstr ""
"Impossible de verrouiller le répertoire d'administration (%s). Avez-vous les "
-"privilèges du superutilisateur ?"
+"droits du superutilisateur ?"
#: apt-pkg/deb/debsystem.cc
msgid "Not locked"
@@ -1442,7 +1445,7 @@ msgstr "Somme de contrôle de hachage incohérente pour %s"
#: apt-pkg/init.cc
#, c-format
msgid "Packaging system '%s' is not supported"
-msgstr "Le système de paquet « %s » n'est pas supporté"
+msgstr "Le système de paquet « %s » n'est pas pris en charge"
#: apt-pkg/init.cc
msgid "Unable to determine a suitable packaging system type"
@@ -1500,7 +1503,7 @@ msgstr "Le fichier de cache des paquets a une version incompatible"
#: apt-pkg/pkgcache.cc
#, c-format
msgid "This APT does not support the versioning system '%s'"
-msgstr "Cet APT ne supporte pas le système de version « %s »"
+msgstr "Cet APT ne prend pas en charge le système de version « %s »"
#: apt-pkg/pkgcache.cc
#, c-format
@@ -1645,8 +1648,8 @@ msgstr "Type d'épinglage %s inconnu"
#, c-format
msgid "%s: Value %s is outside the range of valid pin priorities (%d to %d)"
msgstr ""
-"%s : la valeur %s est dehors de la plage de priorités d'épinglage valide (%d "
-"à %d)"
+"%s : la valeur %s est en dehors de la plage de priorités d'épinglage valide "
+"(%d à %d)"
#: apt-pkg/policy.cc
msgid "No priority (or zero) specified for pin"
@@ -1711,28 +1714,28 @@ msgstr "Calcul de la mise à jour"
#: apt-private/acqprogress.cc
#, c-format
msgid "Hit:%lu %s"
-msgstr "Atteint:%lu %s"
+msgstr "Atteint :%lu %s"
#. TRANSLATOR: Very short word to be displayed for files processed in 'apt-get update'
#. Potentially replaced later by "Hit:", "Ign:" or "Err:" if something (bad) happens
#: apt-private/acqprogress.cc
#, c-format
msgid "Get:%lu %s"
-msgstr "Réception de:%lu %s"
+msgstr "Réception de :%lu %s"
#. TRANSLATOR: Very short word to be displayed for files in 'apt-get update'
#. which failed to download, but the error is ignored (compare "Err:")
#: apt-private/acqprogress.cc
#, c-format
msgid "Ign:%lu %s"
-msgstr "Ign:%lu %s"
+msgstr "Ign :%lu %s"
#. TRANSLATOR: Very short word to be displayed for files in 'apt-get update'
#. which failed to download and the error is critical (compare "Ign:")
#: apt-private/acqprogress.cc
#, c-format
msgid "Err:%lu %s"
-msgstr "Err:%lu %s"
+msgstr "Err :%lu %s"
#: apt-private/acqprogress.cc
#, c-format
@@ -1760,7 +1763,7 @@ msgid ""
"repository?"
msgstr ""
"Souhaitez-vous accepter ces modifications et continuer à mettre à jour "
-"depuis ce dépôt ?"
+"depuis ce dépôt ?"
#: apt-private/private-cachefile.cc
msgid "Correcting dependencies..."
@@ -1878,7 +1881,7 @@ msgstr "Note : sélection de « %s » au lieu de « %s »\n"
#: apt-private/private-cmndline.cc
msgid "Most used commands:"
-msgstr "Commandes les plus utilisées :"
+msgstr "Commandes les plus utilisées :"
#: apt-private/private-cmndline.cc
#, c-format
@@ -1927,7 +1930,7 @@ msgstr "Aucun paquet n'a été trouvé"
#: apt-private/private-download.cc
msgid "WARNING: The following packages cannot be authenticated!"
-msgstr "ATTENTION : les paquets suivants n'ont pas été authentifiés !"
+msgstr "ATTENTION : les paquets suivants n'ont pas été authentifiés !"
#: apt-private/private-download.cc
msgid "Authentication warning overridden.\n"
@@ -1939,7 +1942,7 @@ msgstr "Certains paquets n'ont pas pu être authentifiés"
#: apt-private/private-download.cc
msgid "Install these packages without verification?"
-msgstr "Faut-il installer ces paquets sans vérification ?"
+msgstr "Faut-il installer ces paquets sans vérification ?"
#: apt-private/private-download.cc
msgid ""
@@ -2008,7 +2011,7 @@ msgstr "Erreur interne, « InstallPackages » appelé avec des paquets cassés
#: apt-private/private-install.cc
msgid "Packages need to be removed but remove is disabled."
msgstr ""
-"Les paquets doivent être enlevés mais la désinstallation est désactivée."
+"Les paquets doivent être enlevés, mais la désinstallation est désactivée."
#: apt-private/private-install.cc
msgid ""
@@ -2073,8 +2076,8 @@ msgstr "Après cette opération, %so d'espace disque seront libérés.\n"
#: apt-private/private-install.cc
msgid "Trivial Only specified but this is not a trivial operation."
msgstr ""
-"L'option --trivial-only a été indiquée mais il ne s'agit pas d'une opération "
-"triviale."
+"L'option --trivial-only a été indiquée, mais il ne s'agit pas d'une "
+"opération triviale."
# The space before the exclamation mark must not be a non-breaking space; this
# sentence is supposed to be typed by a user who cannot see the difference.
@@ -2099,7 +2102,7 @@ msgstr ""
msgid "Abort."
msgstr "Annulation."
-#: apt-private/private-install.cc cmdline/apt-mark.cc
+#: apt-private/private-install.cc
msgid "Do you want to continue?"
msgstr "Souhaitez-vous continuer ?"
@@ -2686,10 +2689,8 @@ msgstr[1] ""
msgid "All packages are up to date."
msgstr "Tous les paquets sont à jour."
-#: cmdline/apt-cache.cc cmdline/apt-mark.cc
-#, fuzzy, c-format
-#| msgid "%s does not take any arguments"
-msgid "%s does not take any arguments"
+#: cmdline/apt-cache.cc
+msgid "apt-cache stats does not take any arguments"
msgstr "La commande apt-cache ne prend pas de paramètre"
#: cmdline/apt-cache.cc
@@ -2776,8 +2777,8 @@ msgstr ""
"\tapt-cache [options] show pkg1 [pkg2 ...]\n"
"\n"
"apt-cache recherche et affiche les informations disponibles à propos\n"
-"des paquets installés et installables. Il fonctionne exclusivement sur \n"
-"les données trouvées dans le cache local grâce à la commande « update »\n"
+"des paquets installés et installables. Il fonctionne exclusivement sur\n"
+"les données trouvées dans le cache local grâce à la commande « update »\n"
"d'apt-get par exemple. Les informations affichées peuvent cependant être\n"
"obsolètes si la dernière mise à jour est trop ancienne, mais en revanche\n"
"apt-cache fonctionne indépendamment de la disponibilité des sources\n"
@@ -2994,7 +2995,7 @@ msgstr "Supprime des paquets et leurs fichiers de configuration"
#: cmdline/apt-get.cc cmdline/apt.cc
msgid "Remove automatically all unused packages"
-msgstr "Supprime automatiquement les dépendances inutilisés"
+msgstr "Supprime automatiquement les dépendances inutilisées"
#: cmdline/apt-get.cc
msgid "Distribution upgrade, see apt-get(8)"
@@ -3049,7 +3050,7 @@ msgstr "Le téléchargement a échoué"
#: cmdline/apt-helper.cc
#, c-format
msgid "GetSrvRec failed for %s"
-msgstr "GetSrvRec a échouté pour %s"
+msgstr "GetSrvRec a échoué pour %s"
#: cmdline/apt-helper.cc
msgid ""
@@ -3064,7 +3065,7 @@ msgstr ""
" apt-helper [options] cat-file fichier ...\n"
" apt-helper [options] download-file uri target-path\n"
"\n"
-"apt-helper embarque un grand nombre de commandes que les scripts pour \n"
+"apt-helper embarque un grand nombre de commandes que les scripts pour\n"
"l'interpréteur de commandes peuvent utiliser\n"
"par exemple, la même configuration de proxy ou d'acquisition qu'APT "
"utiliserait.\n"
@@ -3085,7 +3086,7 @@ msgstr "Concaténer des fichiers, avec décompression automatique"
#: cmdline/apt-helper.cc
msgid "detect proxy using apt.conf"
-msgstr "détecter la configuration proxy en utilisant apt.conf"
+msgstr "Détecter la configuration proxy en utilisant apt.conf"
#: cmdline/apt-helper.cc
msgid "wait for system to be online"
@@ -3093,7 +3094,7 @@ msgstr "En attente de la connexion du système"
#: cmdline/apt-helper.cc
msgid "drop privileges before running given command"
-msgstr ""
+msgstr "Se débarrasser des privilèges avant d'exécuter la commande donnée"
#: cmdline/apt-internal-planner.cc
msgid ""
@@ -3141,16 +3142,6 @@ msgid "%s was already set to automatically installed.\n"
msgstr "%s était déjà marqué comme installé automatiquement.\n"
#: cmdline/apt-mark.cc
-msgid "No changes necessary"
-msgstr ""
-
-#: cmdline/apt-mark.cc
-#, fuzzy
-#| msgid "The following NEW packages will be installed:"
-msgid "The following packages will be marked as automatically installed:"
-msgstr "Les NOUVEAUX paquets suivants seront installés :"
-
-#: cmdline/apt-mark.cc
#, c-format
msgid "%s was already set on hold.\n"
msgstr "%s était déjà marqué comme figé (« hold »).\n"
@@ -3163,8 +3154,7 @@ msgstr "%s était déjà marqué comme non figé.\n"
#: cmdline/apt-mark.cc
msgid "Executing dpkg failed. Are you root?"
msgstr ""
-"Échec de l'exécution de dpkg. Possédez-vous les privilèges du "
-"superutilisateur ?"
+"Échec de l'exécution de dpkg. Possédez-vous les droits du superutilisateur ?"
#: cmdline/apt-mark.cc
#, c-format
@@ -3217,12 +3207,6 @@ msgid "Mark the given packages as manually installed"
msgstr "Marquer les paquets indiqués comme installés manuellement"
#: cmdline/apt-mark.cc
-#, fuzzy
-#| msgid "Mark the given packages as automatically installed"
-msgid "Mark all dependencies of meta packages as automatically installed."
-msgstr "Marquer les paquets indiqués comme installés automatiquement"
-
-#: cmdline/apt-mark.cc
msgid "Mark a package as held back"
msgstr "Marquer un paquet comme maintenu dans une version"
@@ -3256,7 +3240,7 @@ msgid ""
msgstr ""
"Usage : apt-sortpkgs [options] fichier1 [fichier2 ...]\n"
"\n"
-"apt-sortpgks est un outil simple permettant de trier les informations à \n"
+"apt-sortpgks est un outil simple permettant de trier les informations à\n"
"propos d'un paquet. Par défaut, il trie par information de paquets "
"binaires,\n"
"mais l'option -s peut être utilisée pour passer au tri par paquet source.\n"
@@ -3679,7 +3663,7 @@ msgstr "Le serveur http a envoyé un en-tête « Content-Range » invalide"
#: methods/basehttp.cc
msgid "This HTTP server has broken range support"
-msgstr "Ce serveur http possède un support des limites non-valide"
+msgstr "Ce serveur http possède une gestion des limites non-valide"
#: methods/basehttp.cc
msgid "Unknown date format"
diff --git a/po/ru.po b/po/ru.po
index 6b50ab080..5022111f1 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -8,14 +8,14 @@
# Dmitry Astapov <adept@despammed.com>, 2004.
# Yuri Kozlov <kozlov.y@gmail.com>, 2004, 2005, 2006, 2007, 2008.
# Yuri Kozlov <yuray@komyakino.ru>, 2009, 2010, 2012, 2015, 2016.
-# Aleksej Shilin <rootlexx@mail.ru>, 2017, 2018.
# Lev Lamberov <dogsleg@debian.org>, 2018.
+# Aleksej Shilin <rootlexx@mail.ru>, 2017, 2018, 2019.
msgid ""
msgstr ""
"Project-Id-Version: apt 1.8.0\n"
"Report-Msgid-Bugs-To: APT Development Team <deity@lists.debian.org>\n"
"POT-Creation-Date: 2019-01-23 16:49+0100\n"
-"PO-Revision-Date: 2018-10-25 19:03+0300\n"
+"PO-Revision-Date: 2019-01-29 21:20+0300\n"
"Last-Translator: Aleksej Shilin <rootlexx@mail.ru>\n"
"Language-Team: Russian <debian-l10n-russian@lists.debian.org>\n"
"Language: ru\n"
@@ -3058,13 +3058,11 @@ msgstr "%s уже помечен как установленный автома�
#: cmdline/apt-mark.cc
msgid "No changes necessary"
-msgstr ""
+msgstr "Никаких изменений не требуется"
#: cmdline/apt-mark.cc
-#, fuzzy
-#| msgid "The following NEW packages will be installed:"
msgid "The following packages will be marked as automatically installed:"
-msgstr "Следующие НОВЫЕ пакеты будут установлены:"
+msgstr "Следующие пакеты будут помечены как установленные автоматически:"
#: cmdline/apt-mark.cc
#, c-format
@@ -3131,10 +3129,8 @@ msgid "Mark the given packages as manually installed"
msgstr "пометить указанные пакеты как установленные вручную"
#: cmdline/apt-mark.cc
-#, fuzzy
-#| msgid "Mark the given packages as automatically installed"
msgid "Mark all dependencies of meta packages as automatically installed."
-msgstr "пометить указанные пакеты как установленные автоматически"
+msgstr "пометить все зависимости метапакетов как установленные автоматически"
#: cmdline/apt-mark.cc
msgid "Mark a package as held back"
diff --git a/test/integration/test-apt-extracttemplates b/test/integration/test-apt-extracttemplates
index 9b07ef79f..a47257cfd 100755
--- a/test/integration/test-apt-extracttemplates
+++ b/test/integration/test-apt-extracttemplates
@@ -44,6 +44,13 @@ Description: Some bar var
testfileequal "$TEMPLATE" "$TEMPLATE_STR"
CONFIG=$(cut -f4 -d' ' $OUT)
testfileequal "$CONFIG" "$CONFIG_STR"
+ msgtest 'No extra files or directories in extraction directory'
+ if [ "$(find ./extracttemplates-out | wc -l)" = '3' ]; then
+ msgpass
+ else
+ msgfail
+ ls -l ./extracttemplates-out
+ fi
# ensure that the format of the output string has the right number of dots
for s in "$CONFIG" "$TEMPLATE"; do
diff --git a/test/integration/test-apt-sources-deb822 b/test/integration/test-apt-sources-deb822
index fdf26fe97..8ffe0abe6 100755
--- a/test/integration/test-apt-sources-deb822
+++ b/test/integration/test-apt-sources-deb822
@@ -14,6 +14,8 @@ BASE='# some comment
# that contains a : as well
#Types: meep
+# a free-standing comment appears
+
Types: deb
#Types: deb-src
URIs: http://ftp.debian.org/debian
@@ -291,3 +293,69 @@ testsuccessequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease'
'http://ftp.debian.org/debian2/dists/sid/non-free/binary-powerpc/Packages.xz' ftp.debian.org_debian2_dists_sid_non-free_binary-powerpc_Packages 0
'http://ftp.debian.org/debian2/dists/sid/non-free/binary-all/Packages.xz' ftp.debian.org_debian2_dists_sid_non-free_binary-all_Packages 0
'http://ftp.debian.org/debian2/dists/sid/non-free/i18n/Translation-en.xz' ftp.debian.org_debian2_dists_sid_non-free_i18n_Translation-en 0 " aptget update --print-uris
+
+EXPECTEDUK="'http://ftp.uk.debian.org/debian/dists/stretch/InRelease' ftp.uk.debian.org_debian_dists_stretch_InRelease 0
+'http://ftp.uk.debian.org/debian/dists/stretch/main/source/Sources.xz' ftp.uk.debian.org_debian_dists_stretch_main_source_Sources 0
+'http://ftp.uk.debian.org/debian/dists/stretch/contrib/source/Sources.xz' ftp.uk.debian.org_debian_dists_stretch_contrib_source_Sources 0
+'http://ftp.uk.debian.org/debian/dists/stretch/non-free/source/Sources.xz' ftp.uk.debian.org_debian_dists_stretch_non-free_source_Sources 0
+'http://ftp.uk.debian.org/debian/dists/stretch/main/binary-i386/Packages.xz' ftp.uk.debian.org_debian_dists_stretch_main_binary-i386_Packages 0
+'http://ftp.uk.debian.org/debian/dists/stretch/main/binary-all/Packages.xz' ftp.uk.debian.org_debian_dists_stretch_main_binary-all_Packages 0
+'http://ftp.uk.debian.org/debian/dists/stretch/main/i18n/Translation-en.xz' ftp.uk.debian.org_debian_dists_stretch_main_i18n_Translation-en 0
+'http://ftp.uk.debian.org/debian/dists/stretch/contrib/binary-i386/Packages.xz' ftp.uk.debian.org_debian_dists_stretch_contrib_binary-i386_Packages 0
+'http://ftp.uk.debian.org/debian/dists/stretch/contrib/binary-all/Packages.xz' ftp.uk.debian.org_debian_dists_stretch_contrib_binary-all_Packages 0
+'http://ftp.uk.debian.org/debian/dists/stretch/contrib/i18n/Translation-en.xz' ftp.uk.debian.org_debian_dists_stretch_contrib_i18n_Translation-en 0
+'http://ftp.uk.debian.org/debian/dists/stretch/non-free/binary-i386/Packages.xz' ftp.uk.debian.org_debian_dists_stretch_non-free_binary-i386_Packages 0
+'http://ftp.uk.debian.org/debian/dists/stretch/non-free/binary-all/Packages.xz' ftp.uk.debian.org_debian_dists_stretch_non-free_binary-all_Packages 0
+'http://ftp.uk.debian.org/debian/dists/stretch/non-free/i18n/Translation-en.xz' ftp.uk.debian.org_debian_dists_stretch_non-free_i18n_Translation-en 0 "
+
+msgcleantest 'Test deb822 sources.list file comments' 'top'
+cat > $SOURCES <<EOF
+#NOTE: Most preferred source listed first!
+
+
+#=== NEW MULTI-LINE FORMAT ===============
+Types: deb deb-src
+URIs:http://ftp.uk.debian.org/debian/
+Suites: stretch
+Components: main contrib non-free
+EOF
+testsuccessequal --nomsg "$EXPECTEDUK" aptget update --print-uris
+
+msgcleantest 'Test deb822 sources.list file comments' 'bottom'
+cat > $SOURCES <<EOF
+Types: deb deb-src
+URIs:http://ftp.uk.debian.org/debian/
+Suites: stretch
+Components: main contrib non-free
+#=== NEW MULTI-LINE FORMAT ===============
+
+
+#NOTE: Most preferred source listed first!
+EOF
+testsuccessequal --nomsg "$EXPECTEDUK" aptget update --print-uris
+
+msgcleantest 'Test deb822 sources.list file comments' 'both'
+cat > $SOURCES <<EOF
+#=== NEW MULTI-LINE FORMAT ===============
+
+
+#NOTE: Most preferred source listed first!
+Types: deb deb-src
+URIs:http://ftp.uk.debian.org/debian/
+Suites: stretch
+Components: main contrib non-free
+#=== NEW MULTI-LINE FORMAT ===============
+
+
+#NOTE: Most preferred source listed first!
+EOF
+testsuccessequal --nomsg "$EXPECTEDUK" aptget update --print-uris
+
+
+msgcleantest 'Test deb822 sources.list file comments' 'empty'
+cat > $SOURCES <<EOF
+#=== NEW MULTI-LINE FORMAT ===============
+
+
+EOF
+testempty aptget update --print-uris
diff --git a/test/integration/test-cve-2013-1051-InRelease-parsing b/test/integration/test-cve-2013-1051-InRelease-parsing
index 6238057c3..1f0cbda04 100755
--- a/test/integration/test-cve-2013-1051-InRelease-parsing
+++ b/test/integration/test-cve-2013-1051-InRelease-parsing
@@ -46,9 +46,12 @@ touch -d '+1hour' aptarchive/dists/stable/InRelease
listcurrentlistsdirectory | sed '/_InRelease/ d' > listsdir.lst
msgtest 'apt-get update should ignore unsigned data in the' 'InRelease'
testwarningequal "Get:1 http://localhost:${APTHTTPPORT} stable InRelease [$(stat -c%s aptarchive/dists/stable/InRelease) B]
+Err:1 http://localhost:${APTHTTPPORT} stable InRelease
+ Splitting up ${TMPWORKINGDIRECTORY}/rootdir/var/lib/apt/lists/partial/localhost:${APTHTTPPORT}_dists_stable_InRelease into data and signature failed
Reading package lists...
-W: Clearsigned file '${TMPWORKINGDIRECTORY}/rootdir/var/lib/apt/lists/partial/localhost:${APTHTTPPORT}_dists_stable_InRelease' contains unsigned lines.
-W: Clearsigned file '${TMPWORKINGDIRECTORY}/rootdir/var/lib/apt/lists/localhost:${APTHTTPPORT}_dists_stable_InRelease' contains unsigned lines." --nomsg aptget update
+W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: http://localhost:${APTHTTPPORT} stable InRelease: Splitting up ${TMPWORKINGDIRECTORY}/rootdir/var/lib/apt/lists/partial/localhost:${APTHTTPPORT}_dists_stable_InRelease into data and signature failed
+W: Failed to fetch http://localhost:${APTHTTPPORT}/dists/stable/InRelease Splitting up ${TMPWORKINGDIRECTORY}/rootdir/var/lib/apt/lists/partial/localhost:${APTHTTPPORT}_dists_stable_InRelease into data and signature failed
+W: Some index files failed to download. They have been ignored, or old ones used instead." --nomsg aptget update
testfileequal './listsdir.lst' "$(listcurrentlistsdirectory | sed '/_InRelease/ d')"
# ensure there is no package
diff --git a/test/integration/test-cve-2019-3462-Release.gpg-payload b/test/integration/test-cve-2019-3462-Release.gpg-payload
new file mode 100755
index 000000000..fd0f96713
--- /dev/null
+++ b/test/integration/test-cve-2019-3462-Release.gpg-payload
@@ -0,0 +1,43 @@
+#!/bin/sh
+set -e
+
+# This is not covered by the CVE and harmless by itself, but used in
+# the exploit and while harmless it is also pointless to allow it
+
+TESTDIR="$(readlink -f "$(dirname "$0")")"
+. "$TESTDIR/framework"
+
+setupenvironment
+configarchitecture 'amd64'
+
+export APT_DONT_SIGN='InRelease'
+
+insertpackage 'unstable' 'foo' 'all' '1'
+setupaptarchive
+rm -rf rootdir/var/lib/apt/lists
+
+verify() {
+ testfailure apt update
+ testsuccess grep '^ Detached signature file' rootdir/tmp/testfailure.output
+ testfailure apt show foo
+}
+
+msgmsg 'Payload after detached signature'
+find aptarchive -name 'Release.gpg' | while read FILE; do
+ cp -a "$FILE" "${FILE}.bak"
+ echo "evil payload" >> "$FILE"
+done
+verify
+
+msgmsg 'Payload in-between detached signatures'
+find aptarchive -name 'Release.gpg' | while read FILE; do
+ cat "${FILE}.bak" >> "$FILE"
+done
+verify
+
+msgmsg 'Payload before detached signature'
+find aptarchive -name 'Release.gpg' | while read FILE; do
+ echo "evil payload" > "$FILE"
+ cat "${FILE}.bak" >> "$FILE"
+done
+verify
diff --git a/test/integration/test-method-gpgv b/test/integration/test-method-gpgv
index 70521881d..bfa5af4c2 100755
--- a/test/integration/test-method-gpgv
+++ b/test/integration/test-method-gpgv
@@ -71,44 +71,60 @@ testrun() {
[GNUPG:] VALIDSIG 891CC50E605796A0C6E733F74BC0A39C27CE74F9 2016-09-01 1472742629 0 4 0 1 11 00 891CC50E605796A0C6E733F74BC0A39C27CE74F9'
}
+echo 'Test' > message.data
+cat >message.sig <<EOF
+-----BEGIN PGP SIGNATURE-----
+
+iQFEBAEBCgAuFiEENKjp0Y2zIPNn6OqgWpDRQdusja4FAlhT7+kQHGpvZUBleGFt
+cGxlLm9yZwAKCRBakNFB26yNrjvEB/9/e3jA1l0fvPafx9LEXcH8CLpUFQK7ra9l
+3M4YAH4JKQlTG1be7ixruBRlCTh3YiSs66fKMeJeUYoxA2HPhvbGFEjQFAxunEYg
+X/LBKv1mQWa+Q34P5GBjK8kQdLCN+yJAiUErmWNQG3GPninrxsC9tY5jcWvHeP1k
+V7N3MLnNqzXaCJM24mnKidC5IDadUdQ8qC8c3rjUexQ8vBz0eucH56jbqV5oOcvx
+pjlW965dCPIf3OI8q6J7bIOjyY+u/PTcVlqPq3TUz/ti6RkVbKpLH0D4ll3lUTns
+JQt/+gJCPxHUJphy8sccBKhW29CLELJIIafvU30E1nWn9szh2Xjq
+=TB1F
+-----END PGP SIGNATURE-----
+EOF
+
+
gpgvmethod() {
- echo '601 Configuration
+ echo "601 Configuration
Config-Item: Debug::Acquire::gpgv=1
Config-Item: Dir::Bin::apt-key=./faked-apt-key
Config-Item: APT::Hashes::SHA1::Weak=true
600 URI Acquire
-URI: file:///dev/null
-Filename: /dev/zero
-' | runapt "${METHODSDIR}/gpgv"
+URI: file://${TMPWORKINGDIRECTORY}/message.sig
+Filename: ${TMPWORKINGDIRECTORY}/message.data
+" | runapt "${METHODSDIR}/gpgv"
}
testrun
gpgvmethod() {
- echo '601 Configuration
+ echo "601 Configuration
Config-Item: Debug::Acquire::gpgv=1
Config-Item: Dir::Bin::apt-key=./faked-apt-key
Config-Item: APT::Hashes::SHA1::Weak=true
600 URI Acquire
-URI: file:///dev/null
-Filename: /dev/zero
+URI: file://${TMPWORKINGDIRECTORY}/message.sig
+Filename: ${TMPWORKINGDIRECTORY}/message.data
Signed-By: /dev/null,34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE
-' | runapt "${METHODSDIR}/gpgv"
+" | runapt "${METHODSDIR}/gpgv"
}
testrun
gpgvmethod() {
- echo '601 Configuration
+ echo "601 Configuration
Config-Item: Debug::Acquire::gpgv=1
Config-Item: Dir::Bin::apt-key=./faked-apt-key
Config-Item: APT::Hashes::SHA1::Weak=true
600 URI Acquire
-URI: file:///dev/null
-Filename: /dev/zero
+URI: file://${TMPWORKINGDIRECTORY}/message.sig
+Filename: ${TMPWORKINGDIRECTORY}/message.data
Signed-By: 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE,/dev/null
-' | runapt "${METHODSDIR}/gpgv"
+" | runapt "${METHODSDIR}/gpgv"
}
testrun
@@ -122,16 +138,16 @@ testsuccess grep '^\s\+Good:\s\+$' method.output
testsuccess grep 'verified because the public key is not available: GOODSIG' method.output
gpgvmethod() {
- echo '601 Configuration
+ echo "601 Configuration
Config-Item: Debug::Acquire::gpgv=1
Config-Item: Dir::Bin::apt-key=./faked-apt-key
Config-Item: APT::Hashes::SHA1::Weak=true
600 URI Acquire
-URI: file:///dev/null
-Filename: /dev/zero
+URI: file://${TMPWORKINGDIRECTORY}/message.sig
+Filename: ${TMPWORKINGDIRECTORY}/message.data
Signed-By: 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE!
-' | runapt "${METHODSDIR}/gpgv"
+" | runapt "${METHODSDIR}/gpgv"
}
testgpgv 'Exact matched subkey signed with long keyid' 'Good: GOODSIG 5A90D141DBAC8DAE' '34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE!' '[GNUPG:] GOODSIG 5A90D141DBAC8DAE Sebastian Subkey <subkey@example.org>
[GNUPG:] VALIDSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 2018-08-16 1534459673 0 4 0 1 11 00 4281DEDBD466EAE8C1F4157E5B6896415D44C43E'
diff --git a/test/libapt/openmaybeclearsignedfile_test.cc b/test/libapt/openmaybeclearsignedfile_test.cc
index 1f63fb8fc..0a4d4438a 100644
--- a/test/libapt/openmaybeclearsignedfile_test.cc
+++ b/test/libapt/openmaybeclearsignedfile_test.cc
@@ -111,7 +111,6 @@ TEST(OpenMaybeClearSignedFileTest,SignedFileWithContentHeaders)
EXPECT_TRUE(fd.Eof());
}
-// That isn't how multiple signatures are done
TEST(OpenMaybeClearSignedFileTest,SignedFileWithTwoSignatures)
{
std::string tempfile;
@@ -190,19 +189,16 @@ TEST(OpenMaybeClearSignedFileTest,TwoSimpleSignedFile)
"-----END PGP SIGNATURE-----");
EXPECT_TRUE(_error->empty());
EXPECT_TRUE(StartsWithGPGClearTextSignature(tempfile));
- EXPECT_TRUE(OpenMaybeClearSignedFile(tempfile, fd));
+ EXPECT_FALSE(OpenMaybeClearSignedFile(tempfile, fd));
if (tempfile.empty() == false)
unlink(tempfile.c_str());
EXPECT_FALSE(_error->empty());
- EXPECT_TRUE(fd.IsOpen());
- char buffer[100];
- EXPECT_TRUE(fd.ReadLine(buffer, sizeof(buffer)));
- EXPECT_STREQ(buffer, "Test");
- EXPECT_TRUE(fd.Eof());
- ASSERT_FALSE(_error->empty());
+ EXPECT_FALSE(fd.IsOpen());
+ // technically they are signed, but we just want one message
+ EXPECT_TRUE(_error->PendingError());
std::string msg;
- _error->PopMessage(msg);
+ EXPECT_TRUE(_error->PopMessage(msg));
EXPECT_EQ("Clearsigned file '" + tempfile + "' contains unsigned lines.", msg);
}
@@ -244,19 +240,15 @@ TEST(OpenMaybeClearSignedFileTest,GarbageTop)
"-----END PGP SIGNATURE-----\n");
EXPECT_FALSE(StartsWithGPGClearTextSignature(tempfile));
EXPECT_TRUE(_error->empty());
- EXPECT_TRUE(OpenMaybeClearSignedFile(tempfile, fd));
+ EXPECT_FALSE(OpenMaybeClearSignedFile(tempfile, fd));
if (tempfile.empty() == false)
unlink(tempfile.c_str());
- EXPECT_TRUE(fd.IsOpen());
- char buffer[100];
- EXPECT_TRUE(fd.ReadLine(buffer, sizeof(buffer)));
- EXPECT_STREQ(buffer, "Test");
- EXPECT_TRUE(fd.Eof());
+ EXPECT_FALSE(fd.IsOpen());
ASSERT_FALSE(_error->empty());
- ASSERT_FALSE(_error->PendingError());
+ ASSERT_TRUE(_error->PendingError());
std::string msg;
- _error->PopMessage(msg);
+ EXPECT_TRUE(_error->PopMessage(msg));
EXPECT_EQ("Clearsigned file '" + tempfile + "' does not start with a signed message block.", msg);
}
@@ -313,19 +305,15 @@ TEST(OpenMaybeClearSignedFileTest,GarbageBottom)
"Garbage");
EXPECT_TRUE(StartsWithGPGClearTextSignature(tempfile));
EXPECT_TRUE(_error->empty());
- EXPECT_TRUE(OpenMaybeClearSignedFile(tempfile, fd));
+ EXPECT_FALSE(OpenMaybeClearSignedFile(tempfile, fd));
if (tempfile.empty() == false)
unlink(tempfile.c_str());
- EXPECT_TRUE(fd.IsOpen());
- char buffer[100];
- EXPECT_TRUE(fd.ReadLine(buffer, sizeof(buffer)));
- EXPECT_STREQ(buffer, "Test");
- EXPECT_TRUE(fd.Eof());
+ EXPECT_FALSE(fd.IsOpen());
ASSERT_FALSE(_error->empty());
- ASSERT_FALSE(_error->PendingError());
+ ASSERT_TRUE(_error->PendingError());
std::string msg;
- _error->PopMessage(msg);
+ EXPECT_TRUE(_error->PopMessage(msg));
EXPECT_EQ("Clearsigned file '" + tempfile + "' contains unsigned lines.", msg);
}
@@ -347,7 +335,7 @@ TEST(OpenMaybeClearSignedFileTest,BogusNoSig)
std::string msg;
_error->PopMessage(msg);
- EXPECT_EQ("Splitting of file " + tempfile + " failed as it doesn't contain all expected parts 0 1 0", msg);
+ EXPECT_EQ("Splitting of clearsigned file " + tempfile + " failed as it doesn't contain all expected parts", msg);
}
TEST(OpenMaybeClearSignedFileTest,BogusSigStart)
@@ -371,3 +359,127 @@ TEST(OpenMaybeClearSignedFileTest,BogusSigStart)
_error->PopMessage(msg);
EXPECT_EQ("Signature in file " + tempfile + " wasn't closed", msg);
}
+
+TEST(OpenMaybeClearSignedFileTest,DashedSignedFile)
+{
+ std::string tempfile;
+ FileFd fd;
+ createTemporaryFile("dashedsignedfile", fd, &tempfile, "-----BEGIN PGP SIGNED MESSAGE-----\n"
+"Hash: SHA512\n"
+"\n"
+"- Test\n"
+"-----BEGIN PGP SIGNATURE-----\n"
+"\n"
+"iQFEBAEBCgAuFiEENKjp0Y2zIPNn6OqgWpDRQdusja4FAlhT7+kQHGpvZUBleGFt\n"
+"cGxlLm9yZwAKCRBakNFB26yNrjvEB/9/e3jA1l0fvPafx9LEXcH8CLpUFQK7ra9l\n"
+"3M4YAH4JKQlTG1be7ixruBRlCTh3YiSs66fKMeJeUYoxA2HPhvbGFEjQFAxunEYg\n"
+"X/LBKv1mQWa+Q34P5GBjK8kQdLCN+yJAiUErmWNQG3GPninrxsC9tY5jcWvHeP1k\n"
+"V7N3MLnNqzXaCJM24mnKidC5IDadUdQ8qC8c3rjUexQ8vBz0eucH56jbqV5oOcvx\n"
+"pjlW965dCPIf3OI8q6J7bIOjyY+u/PTcVlqPq3TUz/ti6RkVbKpLH0D4ll3lUTns\n"
+"JQt/+gJCPxHUJphy8sccBKhW29CLELJIIafvU30E1nWn9szh2Xjq\n"
+"=TB1F\n"
+"-----END PGP SIGNATURE-----\n");
+ EXPECT_TRUE(StartsWithGPGClearTextSignature(tempfile));
+ EXPECT_TRUE(OpenMaybeClearSignedFile(tempfile, fd));
+ if (tempfile.empty() == false)
+ unlink(tempfile.c_str());
+ EXPECT_TRUE(fd.IsOpen());
+ char buffer[100];
+ EXPECT_TRUE(fd.ReadLine(buffer, sizeof(buffer)));
+ EXPECT_STREQ(buffer, "Test");
+ EXPECT_TRUE(fd.Eof());
+}
+TEST(OpenMaybeClearSignedFileTest,StrangeDashArmorFile)
+{
+ std::string tempfile;
+ FileFd fd;
+ createTemporaryFile("strangedashfile", fd, &tempfile, "-----BEGIN PGP SIGNED MESSAGE-----\n"
+"Hash: SHA512\n"
+"-Hash: SHA512\n"
+"\n"
+"Test\n"
+"-----BEGIN PGP SIGNATURE-----\n"
+"\n"
+"iQFEBAEBCgAuFiEENKjp0Y2zIPNn6OqgWpDRQdusja4FAlhT7+kQHGpvZUBleGFt\n"
+"cGxlLm9yZwAKCRBakNFB26yNrjvEB/9/e3jA1l0fvPafx9LEXcH8CLpUFQK7ra9l\n"
+"3M4YAH4JKQlTG1be7ixruBRlCTh3YiSs66fKMeJeUYoxA2HPhvbGFEjQFAxunEYg\n"
+"X/LBKv1mQWa+Q34P5GBjK8kQdLCN+yJAiUErmWNQG3GPninrxsC9tY5jcWvHeP1k\n"
+"V7N3MLnNqzXaCJM24mnKidC5IDadUdQ8qC8c3rjUexQ8vBz0eucH56jbqV5oOcvx\n"
+"pjlW965dCPIf3OI8q6J7bIOjyY+u/PTcVlqPq3TUz/ti6RkVbKpLH0D4ll3lUTns\n"
+"JQt/+gJCPxHUJphy8sccBKhW29CLELJIIafvU30E1nWn9szh2Xjq\n"
+"=TB1F\n"
+"-----END PGP SIGNATURE-----\n");
+ EXPECT_TRUE(StartsWithGPGClearTextSignature(tempfile));
+ EXPECT_FALSE(OpenMaybeClearSignedFile(tempfile, fd));
+ if (tempfile.empty() == false)
+ unlink(tempfile.c_str());
+ EXPECT_FALSE(_error->empty());
+ EXPECT_FALSE(fd.IsOpen());
+
+ std::string msg;
+ EXPECT_TRUE(_error->PendingError());
+ EXPECT_TRUE(_error->PopMessage(msg));
+ EXPECT_EQ("Clearsigned file '" + tempfile + "' contains unexpected line starting with a dash (armor)", msg);
+}
+TEST(OpenMaybeClearSignedFileTest,StrangeDashMsgFile)
+{
+ std::string tempfile;
+ FileFd fd;
+ createTemporaryFile("strangedashfile", fd, &tempfile, "-----BEGIN PGP SIGNED MESSAGE-----\n"
+"Hash: SHA512\n"
+"\n"
+"-Test\n"
+"-----BEGIN PGP SIGNATURE-----\n"
+"\n"
+"iQFEBAEBCgAuFiEENKjp0Y2zIPNn6OqgWpDRQdusja4FAlhT7+kQHGpvZUBleGFt\n"
+"cGxlLm9yZwAKCRBakNFB26yNrjvEB/9/e3jA1l0fvPafx9LEXcH8CLpUFQK7ra9l\n"
+"3M4YAH4JKQlTG1be7ixruBRlCTh3YiSs66fKMeJeUYoxA2HPhvbGFEjQFAxunEYg\n"
+"X/LBKv1mQWa+Q34P5GBjK8kQdLCN+yJAiUErmWNQG3GPninrxsC9tY5jcWvHeP1k\n"
+"V7N3MLnNqzXaCJM24mnKidC5IDadUdQ8qC8c3rjUexQ8vBz0eucH56jbqV5oOcvx\n"
+"pjlW965dCPIf3OI8q6J7bIOjyY+u/PTcVlqPq3TUz/ti6RkVbKpLH0D4ll3lUTns\n"
+"JQt/+gJCPxHUJphy8sccBKhW29CLELJIIafvU30E1nWn9szh2Xjq\n"
+"=TB1F\n"
+"-----END PGP SIGNATURE-----\n");
+ EXPECT_TRUE(StartsWithGPGClearTextSignature(tempfile));
+ EXPECT_FALSE(OpenMaybeClearSignedFile(tempfile, fd));
+ if (tempfile.empty() == false)
+ unlink(tempfile.c_str());
+ EXPECT_FALSE(_error->empty());
+ EXPECT_FALSE(fd.IsOpen());
+
+ std::string msg;
+ EXPECT_TRUE(_error->PendingError());
+ EXPECT_TRUE(_error->PopMessage(msg));
+ EXPECT_EQ("Clearsigned file '" + tempfile + "' contains unexpected line starting with a dash (msg)", msg);
+}
+TEST(OpenMaybeClearSignedFileTest,StrangeDashSigFile)
+{
+ std::string tempfile;
+ FileFd fd;
+ createTemporaryFile("strangedashfile", fd, &tempfile, "-----BEGIN PGP SIGNED MESSAGE-----\n"
+"Hash: SHA512\n"
+"\n"
+"Test\n"
+"-----BEGIN PGP SIGNATURE-----\n"
+"\n"
+"iQFEBAEBCgAuFiEENKjp0Y2zIPNn6OqgWpDRQdusja4FAlhT7+kQHGpvZUBleGFt\n"
+"cGxlLm9yZwAKCRBakNFB26yNrjvEB/9/e3jA1l0fvPafx9LEXcH8CLpUFQK7ra9l\n"
+"3M4YAH4JKQlTG1be7ixruBRlCTh3YiSs66fKMeJeUYoxA2HPhvbGFEjQFAxunEYg\n"
+"-/LBKv1mQWa+Q34P5GBjK8kQdLCN+yJAiUErmWNQG3GPninrxsC9tY5jcWvHeP1k\n"
+"V7N3MLnNqzXaCJM24mnKidC5IDadUdQ8qC8c3rjUexQ8vBz0eucH56jbqV5oOcvx\n"
+"pjlW965dCPIf3OI8q6J7bIOjyY+u/PTcVlqPq3TUz/ti6RkVbKpLH0D4ll3lUTns\n"
+"JQt/+gJCPxHUJphy8sccBKhW29CLELJIIafvU30E1nWn9szh2Xjq\n"
+"=TB1F\n"
+"-----END PGP SIGNATURE-----\n");
+ EXPECT_TRUE(StartsWithGPGClearTextSignature(tempfile));
+ EXPECT_FALSE(OpenMaybeClearSignedFile(tempfile, fd));
+ if (tempfile.empty() == false)
+ unlink(tempfile.c_str());
+ EXPECT_FALSE(_error->empty());
+ EXPECT_FALSE(fd.IsOpen());
+
+ std::string msg;
+ EXPECT_TRUE(_error->PendingError());
+ EXPECT_TRUE(_error->PopMessage(msg));
+ EXPECT_EQ("Clearsigned file '" + tempfile + "' contains unexpected line starting with a dash (sig)", msg);
+}
diff --git a/test/libapt/tagfile_test.cc b/test/libapt/tagfile_test.cc
index f455a8dcc..8823ff781 100644
--- a/test/libapt/tagfile_test.cc
+++ b/test/libapt/tagfile_test.cc
@@ -232,6 +232,8 @@ TEST(TagFileTest, Comments)
FileFd fd;
createTemporaryFile("commentfile", fd, NULL, "# Leading comments should be ignored.\n"
"\n"
+"# A wild second comment appears!\n"
+"\n"
"Source: foo\n"
"#Package: foo\n"
"Section: bar\n"