#include <apt-pkg/configuration.h>
#include <apt-pkg/aptconfiguration.h>
#include <apt-pkg/sourcelist.h>
-#include <apt-pkg/vendorlist.h>
#include <apt-pkg/error.h>
#include <apt-pkg/strutl.h>
#include <apt-pkg/fileutl.h>
struct stat Buf;
if (stat(Final.c_str(),&Buf) != 0)
- return "\nIndex-File: true";
- return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
+ return "\nIndex-File: true\nFail-Ignore: true\n";
+ return "\nIndex-File: true\nFail-Ignore: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
}
/*}}}*/
void pkgAcqSubIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*{{{*/
string FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(Desc.URI);
+ /* Downloaded invalid transindex => Error (LP: #346386) (Closes: #627642) */
+ indexRecords SubIndexParser;
+ if (FileExists(DestFile) == true && !SubIndexParser.Load(DestFile)) {
+ Status = StatError;
+ ErrorText = SubIndexParser.ErrorText;
+ return;
+ }
+
// sucess in downloading the index
// rename the index
if(Debug)
// remove all patches until the next matching patch is found
// this requires the Index file to be ordered
for(vector<DiffInfo>::iterator I=available_patches.begin();
- available_patches.size() > 0 &&
+ available_patches.empty() == false &&
I != available_patches.end() &&
- (*I).sha1 != local_sha1;
- I++)
+ I->sha1 != local_sha1;
+ ++I)
{
available_patches.erase(I);
}
// error checking and falling back if no patch was found
- if(available_patches.size() == 0)
- {
+ if(available_patches.empty() == true)
+ {
Failed("", NULL);
return false;
}
chmod(FinalFile.c_str(),0644);
// see if there is more to download
- if(available_patches.size() > 0) {
+ if(available_patches.empty() == false) {
new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,
ExpectedHash, ServerSha1, available_patches);
return Finish();
if (_config->FindB("Acquire::GzipIndexes",false))
Final += ".gz";
+ string msg = "\nIndex-File: true";
+ // FIXME: this really should use "IndexTarget::IsOptional()" but that
+ // seems to be difficult without breaking ABI
+ if (ShortDesc().find("Translation") != 0)
+ msg += "\nFail-Ignore: true";
struct stat Buf;
- if (stat(Final.c_str(),&Buf) != 0)
- return "\nIndex-File: true";
- return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
+ if (stat(Final.c_str(),&Buf) == 0)
+ msg += "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
+
+ return msg;
}
/*}}}*/
void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*{{{*/
ReportMirrorFailure("HashChecksumFailure");
return;
}
+
+ /* Verify the index file for correctness (all indexes must
+ * have a Package field) (LP: #346386) (Closes: #627642) */
+ {
+ FileFd fd(DestFile, FileFd::ReadOnly);
+ pkgTagSection sec;
+ pkgTagFile tag(&fd);
+
+ // Only test for correctness if the file is not empty (empty is ok)
+ if (fd.Size() > 0) {
+ if (_error->PendingError() || !tag.Step(sec)) {
+ Status = StatError;
+ _error->DumpErrors();
+ Rename(DestFile,DestFile + ".FAILED");
+ return;
+ } else if (!sec.Exists("Package")) {
+ Status = StatError;
+ ErrorText = ("Encountered a section with no Package: header");
+ Rename(DestFile,DestFile + ".FAILED");
+ return;
+ }
+ }
+ }
+
// Done, move it into position
string FinalFile = _config->FindDir("Dir::State::lists");
FinalFile += URItoFileName(RealURI);
if (SigFile == "")
{
// There was no signature file, so we are finished. Download
- // the indexes without verification.
+ // the indexes and do only hashsum verification if possible
+ MetaIndexParser->Load(DestFile);
QueueIndexes(false);
}
else
/*}}}*/
void pkgAcqMetaIndex::QueueIndexes(bool verify) /*{{{*/
{
+#if 0
+ /* Reject invalid, existing Release files (LP: #346386) (Closes: #627642)
+ * FIXME: Disabled; it breaks unsigned repositories without hashes */
+ if (!verify && FileExists(DestFile) && !MetaIndexParser->Load(DestFile))
+ {
+ Status = StatError;
+ ErrorText = MetaIndexParser->ErrorText;
+ return;
+ }
+#endif
for (vector <struct IndexTarget*>::const_iterator Target = IndexTargets->begin();
Target != IndexTargets->end();
- Target++)
+ ++Target)
{
HashString ExpectedIndexHash;
- if (verify)
+ const indexRecords::checkSum *Record = MetaIndexParser->Lookup((*Target)->MetaKey);
+ if (Record == NULL)
{
- const indexRecords::checkSum *Record = MetaIndexParser->Lookup((*Target)->MetaKey);
- if (Record == NULL)
+ if (verify == true && (*Target)->IsOptional() == false)
{
- if ((*Target)->IsOptional() == false)
- {
- Status = StatAuthError;
- strprintf(ErrorText, _("Unable to find expected entry '%s' in Release file (Wrong sources.list entry or malformed file)"), (*Target)->MetaKey.c_str());
- return;
- }
+ Status = StatAuthError;
+ strprintf(ErrorText, _("Unable to find expected entry '%s' in Release file (Wrong sources.list entry or malformed file)"), (*Target)->MetaKey.c_str());
+ return;
}
- else
+ }
+ else
+ {
+ ExpectedIndexHash = Record->Hash;
+ if (_config->FindB("Debug::pkgAcquire::Auth", false))
{
- ExpectedIndexHash = Record->Hash;
- if (_config->FindB("Debug::pkgAcquire::Auth", false))
- {
- std::cerr << "Queueing: " << (*Target)->URI << std::endl;
- std::cerr << "Expected Hash: " << ExpectedIndexHash.toStr() << std::endl;
- }
- if (ExpectedIndexHash.empty() == true && (*Target)->IsOptional() == false)
- {
- Status = StatAuthError;
- strprintf(ErrorText, _("Unable to find hash sum for '%s' in Release file"), (*Target)->MetaKey.c_str());
- return;
- }
+ std::cerr << "Queueing: " << (*Target)->URI << std::endl;
+ std::cerr << "Expected Hash: " << ExpectedIndexHash.toStr() << std::endl;
+ std::cerr << "For: " << Record->MetaKeyFilename << std::endl;
+ }
+ if (verify == true && ExpectedIndexHash.empty() == true && (*Target)->IsOptional() == false)
+ {
+ Status = StatAuthError;
+ strprintf(ErrorText, _("Unable to find hash sum for '%s' in Release file"), (*Target)->MetaKey.c_str());
+ return;
}
}
/*}}}*/
bool pkgAcqMetaIndex::VerifyVendor(string Message) /*{{{*/
{
-// // Maybe this should be made available from above so we don't have
-// // to read and parse it every time?
-// pkgVendorList List;
-// List.ReadMainList();
-
-// const Vendor* Vndr = NULL;
-// for (std::vector<string>::const_iterator I = GPGVOutput.begin(); I != GPGVOutput.end(); I++)
-// {
-// string::size_type pos = (*I).find("VALIDSIG ");
-// if (_config->FindB("Debug::Vendor", false))
-// std::cerr << "Looking for VALIDSIG in \"" << (*I) << "\": pos " << pos
-// << std::endl;
-// if (pos != std::string::npos)
-// {
-// string Fingerprint = (*I).substr(pos+sizeof("VALIDSIG"));
-// if (_config->FindB("Debug::Vendor", false))
-// std::cerr << "Looking for \"" << Fingerprint << "\" in vendor..." <<
-// std::endl;
-// Vndr = List.FindVendor(Fingerprint) != "";
-// if (Vndr != NULL);
-// break;
-// }
-// }
string::size_type pos;
// check for missing sigs (that where not fatal because otherwise we had
// TRANSLATOR: The first %s is the URL of the bad Release file, the second is
// the time since then the file is invalid - formated in the same way as in
// the download progress display (e.g. 7d 3h 42min 1s)
- return _error->Error(_("Release file expired, ignoring %s (invalid since %s)"),
- RealURI.c_str(), TimeToStr(invalid_since).c_str());
+ return _error->Error(
+ _("Release file for %s is expired (invalid since %s). "
+ "Updates for this repository will not be applied."),
+ RealURI.c_str(), TimeToStr(invalid_since).c_str());
}
if (_config->FindB("Debug::pkgAcquire::Auth", false))
LookupTag(Message,"Message").c_str());
RunScripts("APT::Update::Auth-Failure");
return;
+ } else if (LookupTag(Message,"Message").find("NODATA") != string::npos) {
+ /* Invalid signature file, reject (LP: #346386) (Closes: #627642) */
+ _error->Error(_("GPG error: %s: %s"),
+ Desc.Description.c_str(),
+ LookupTag(Message,"Message").c_str());
+ return;
} else {
_error->Warning(_("GPG error: %s: %s"),
Desc.Description.c_str(),
ReportMirrorFailure("GPGFailure");
}
+ /* Always move the meta index, even if gpgv failed. This ensures
+ * that PackageFile objects are correctly filled in */
+ if (FileExists(DestFile)) {
+ string FinalFile = _config->FindDir("Dir::State::lists");
+ FinalFile += URItoFileName(RealURI);
+ /* InRelease files become Release files, otherwise
+ * they would be considered as trusted later on */
+ if (SigFile == DestFile) {
+ RealURI = RealURI.replace(RealURI.rfind("InRelease"), 9,
+ "Release");
+ FinalFile = FinalFile.replace(FinalFile.rfind("InRelease"), 9,
+ "Release");
+ SigFile = FinalFile;
+ }
+ Rename(DestFile,FinalFile);
+ chmod(FinalFile.c_str(),0644);
+
+ DestFile = FinalFile;
+ }
+
// No Release file was present, or verification failed, so fall
// back to queueing Packages files without verification
QueueIndexes(false);
// check if we have one trusted source for the package. if so, switch
// to "TrustedOnly" mode
- for (pkgCache::VerFileIterator i = Version.FileList(); i.end() == false; i++)
+ for (pkgCache::VerFileIterator i = Version.FileList(); i.end() == false; ++i)
{
pkgIndexFile *Index;
if (Sources->FindIndex(i.File(),Index) == false)
// Select a source
if (QueueNext() == false && _error->PendingError() == false)
- _error->Error(_("I wasn't able to locate file for the %s package. "
+ _error->Error(_("I wasn't able to locate a file for the %s package. "
"This might mean you need to manually fix this package."),
Version.ParentPkg().Name());
}
bool pkgAcqArchive::QueueNext()
{
string const ForceHash = _config->Find("Acquire::ForceHash");
- for (; Vf.end() == false; Vf++)
+ for (; Vf.end() == false; ++Vf)
{
// Ignore not source sources
if ((Vf.File()->Flags & pkgCache::Flag::NotSource) != 0)
Desc.ShortDesc = Version.ParentPkg().Name();
QueueURI(Desc);
- Vf++;
+ ++Vf;
return true;
}
return false;
StringToBool(LookupTag(Message,"Transient-Failure"),false) == true)
{
// Vf = Version.FileList();
- while (Vf.end() == false) Vf++;
+ while (Vf.end() == false) ++Vf;
StoreFilename = string();
Item::Failed(Message,Cnf);
return;