X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/376091144df4991f161f068f2c297b80e94d36db..53391d0fc55f118194467b3d436f91fbc1097c31:/methods/gpgv.cc diff --git a/methods/gpgv.cc b/methods/gpgv.cc index a114ad797..150c1d315 100644 --- a/methods/gpgv.cc +++ b/methods/gpgv.cc @@ -11,17 +11,24 @@ #include #include #include +#include #define GNUPGPREFIX "[GNUPG:]" #define GNUPGBADSIG "[GNUPG:] BADSIG" #define GNUPGNOPUBKEY "[GNUPG:] NO_PUBKEY" #define GNUPGVALIDSIG "[GNUPG:] VALIDSIG" +#define GNUPGGOODSIG "[GNUPG:] GOODSIG" +#define GNUPGKEYEXPIRED "[GNUPG:] KEYEXPIRED" +#define GNUPGREVKEYSIG "[GNUPG:] REVKEYSIG" +#define GNUPGNODATA "[GNUPG:] NODATA" class GPGVMethod : public pkgAcqMethod { private: - const char *VerifyGetSigners(const char *file, const char *outfile, - vector &GoodSigners, vector &BadSigners, + string VerifyGetSigners(const char *file, const char *outfile, + vector &GoodSigners, + vector &BadSigners, + vector &WorthlessSigners, vector &NoPubKeySigners); protected: @@ -32,11 +39,16 @@ class GPGVMethod : public pkgAcqMethod GPGVMethod() : pkgAcqMethod("1.0",SingleInstance | SendConfig) {}; }; -const char *GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, +string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, vector &GoodSigners, vector &BadSigners, + vector &WorthlessSigners, vector &NoPubKeySigners) { + // setup a (empty) stringstream for formating the return value + std::stringstream ret; + ret.str(""); + if (_config->FindB("Debug::Acquire::gpgv", false)) { std::cerr << "inside VerifyGetSigners" << std::endl; @@ -54,9 +66,11 @@ const char *GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, std::cerr << "Keyring path: " << pubringpath << std::endl; } - if (stat(pubringpath.c_str(), &buff) != 0) - return (string("Couldn't access keyring: ") + strerror(errno)).c_str(); - + if (stat(pubringpath.c_str(), &buff) != 0) + { + ioprintf(ret, _("Couldn't access keyring: '%s'"), strerror(errno)); + return ret.str(); + } if (pipe(fd) < 0) { return "Couldn't create pipe"; @@ -65,7 +79,7 @@ const char *GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, pid = fork(); if (pid < 0) { - return (string("Couldn't spawn new process") + strerror(errno)).c_str(); + return string("Couldn't spawn new process") + strerror(errno); } else if (pid == 0) { @@ -75,6 +89,7 @@ const char *GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, Args[i++] = gpgvpath.c_str(); Args[i++] = "--status-fd"; Args[i++] = "3"; + Args[i++] = "--ignore-time-conflict"; Args[i++] = "--keyring"; Args[i++] = pubringpath.c_str(); @@ -113,9 +128,9 @@ const char *GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, // Redirect the pipe to the status fd (3) dup2(fd[1], 3); - putenv("LANG="); - putenv("LC_ALL="); - putenv("LC_MESSAGES="); + putenv((char *)"LANG="); + putenv((char *)"LC_ALL="); + putenv((char *)"LC_MESSAGES="); execvp(gpgvpath.c_str(), (char **)Args); exit(111); @@ -164,16 +179,33 @@ const char *GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, std::cerr << "Got NO_PUBKEY " << std::endl; NoPubKeySigners.push_back(string(buffer+sizeof(GNUPGPREFIX))); } - - if (strncmp(buffer, GNUPGVALIDSIG, sizeof(GNUPGVALIDSIG)-1) == 0) + if (strncmp(buffer, GNUPGNODATA, sizeof(GNUPGBADSIG)-1) == 0) + { + if (_config->FindB("Debug::Acquire::gpgv", false)) + std::cerr << "Got NODATA! " << std::endl; + BadSigners.push_back(string(buffer+sizeof(GNUPGPREFIX))); + } + if (strncmp(buffer, GNUPGKEYEXPIRED, sizeof(GNUPGKEYEXPIRED)-1) == 0) + { + if (_config->FindB("Debug::Acquire::gpgv", false)) + std::cerr << "Got KEYEXPIRED! " << std::endl; + WorthlessSigners.push_back(string(buffer+sizeof(GNUPGPREFIX))); + } + if (strncmp(buffer, GNUPGREVKEYSIG, sizeof(GNUPGREVKEYSIG)-1) == 0) + { + if (_config->FindB("Debug::Acquire::gpgv", false)) + std::cerr << "Got REVKEYSIG! " << std::endl; + WorthlessSigners.push_back(string(buffer+sizeof(GNUPGPREFIX))); + } + if (strncmp(buffer, GNUPGGOODSIG, sizeof(GNUPGGOODSIG)-1) == 0) { char *sig = buffer + sizeof(GNUPGPREFIX); - char *p = sig + sizeof("VALIDSIG"); + char *p = sig + sizeof("GOODSIG"); while (*p && isxdigit(*p)) p++; *p = 0; if (_config->FindB("Debug::Acquire::gpgv", false)) - std::cerr << "Got VALIDSIG, key ID:" << sig << std::endl; + std::cerr << "Got GOODSIG, key ID:" << sig << std::endl; GoodSigners.push_back(string(sig)); } } @@ -189,7 +221,7 @@ const char *GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, { if (GoodSigners.empty()) return _("Internal error: Good signature, but could not determine key fingerprint?!"); - return NULL; + return ""; } else if (WEXITSTATUS(status) == 1) { @@ -197,9 +229,8 @@ const char *GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, } else if (WEXITSTATUS(status) == 111) { - // FIXME String concatenation considered harmful. - return (string(_("Could not execute ")) + gpgvpath + - string(_(" to verify signature (is gnupg installed?)"))).c_str(); + ioprintf(ret, _("Could not execute '%s' to verify signature (is gpgv installed?)"), gpgvpath.c_str()); + return ret.str(); } else { @@ -214,6 +245,8 @@ bool GPGVMethod::Fetch(FetchItem *Itm) string keyID; vector GoodSigners; vector BadSigners; + // a worthless signature is a expired or revoked one + vector WorthlessSigners; vector NoPubKeySigners; FetchResult Res; @@ -221,14 +254,15 @@ bool GPGVMethod::Fetch(FetchItem *Itm) URIStart(Res); // Run gpgv on file, extract contents and get the key ID of the signer - const char *msg = VerifyGetSigners(Path.c_str(), Itm->DestFile.c_str(), - GoodSigners, BadSigners, NoPubKeySigners); + string msg = VerifyGetSigners(Path.c_str(), Itm->DestFile.c_str(), + GoodSigners, BadSigners, WorthlessSigners, + NoPubKeySigners); if (GoodSigners.empty() || !BadSigners.empty() || !NoPubKeySigners.empty()) { string errmsg; // In this case, something bad probably happened, so we just go // with what the other method gave us for an error message. - if (BadSigners.empty() && NoPubKeySigners.empty()) + if (BadSigners.empty() && WorthlessSigners.empty() && NoPubKeySigners.empty()) errmsg = msg; else { @@ -239,6 +273,13 @@ bool GPGVMethod::Fetch(FetchItem *Itm) I != BadSigners.end(); I++) errmsg += (*I + "\n"); } + if (!WorthlessSigners.empty()) + { + errmsg += _("The following signatures were invalid:\n"); + for (vector::iterator I = WorthlessSigners.begin(); + I != WorthlessSigners.end(); I++) + errmsg += (*I + "\n"); + } if (!NoPubKeySigners.empty()) { errmsg += _("The following signatures couldn't be verified because the public key is not available:\n"); @@ -251,26 +292,9 @@ bool GPGVMethod::Fetch(FetchItem *Itm) // least one bad signature. good signatures and NoPubKey signatures // happen easily when a file is signed with multiple signatures if(GoodSigners.empty() or !BadSigners.empty()) - return _error->Error(errmsg.c_str()); + return _error->Error("%s", errmsg.c_str()); } - // Transfer the modification times - struct stat Buf; - if (stat(Path.c_str(),&Buf) != 0) - return _error->Errno("stat",_("Failed to stat %s"), Path.c_str()); - - struct utimbuf TimeBuf; - TimeBuf.actime = Buf.st_atime; - TimeBuf.modtime = Buf.st_mtime; - if (utime(Itm->DestFile.c_str(),&TimeBuf) != 0) - return _error->Errno("utime",_("Failed to set modification time")); - - if (stat(Itm->DestFile.c_str(),&Buf) != 0) - return _error->Errno("stat",_("Failed to stat")); - - // Return a Done response - Res.LastModified = Buf.st_mtime; - Res.Size = Buf.st_size; // Just pass the raw output up, because passing it as a real data // structure is too difficult with the method stuff. We keep it // as three separate vectors for future extensibility.