summaryrefslogtreecommitdiff
path: root/methods
diff options
context:
space:
mode:
Diffstat (limited to 'methods')
-rw-r--r--methods/cdrom.cc2
-rw-r--r--methods/connect.cc2
-rw-r--r--methods/copy.cc2
-rw-r--r--methods/file.cc2
-rw-r--r--methods/ftp.cc2
-rw-r--r--methods/gpgv.cc261
-rw-r--r--methods/gzip.cc4
-rw-r--r--methods/makefile9
-rw-r--r--methods/rsh.cc2
-rw-r--r--methods/rsh.h2
10 files changed, 278 insertions, 10 deletions
diff --git a/methods/cdrom.cc b/methods/cdrom.cc
index 0d8fdc29c..d5987dc45 100644
--- a/methods/cdrom.cc
+++ b/methods/cdrom.cc
@@ -1,6 +1,6 @@
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: cdrom.cc,v 1.21 2004/01/07 20:39:38 mdz Exp $
+// $Id: cdrom.cc,v 1.20.2.1 2004/01/16 18:58:50 mdz Exp $
/* ######################################################################
CDROM URI method for APT
diff --git a/methods/connect.cc b/methods/connect.cc
index d1d71b004..981ac1371 100644
--- a/methods/connect.cc
+++ b/methods/connect.cc
@@ -1,6 +1,6 @@
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: connect.cc,v 1.11 2004/01/07 20:39:38 mdz Exp $
+// $Id: connect.cc,v 1.10.2.1 2004/01/16 18:58:50 mdz Exp $
/* ######################################################################
Connect - Replacement connect call
diff --git a/methods/copy.cc b/methods/copy.cc
index 3f367e72a..d737e3c33 100644
--- a/methods/copy.cc
+++ b/methods/copy.cc
@@ -1,6 +1,6 @@
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: copy.cc,v 1.8 2004/01/07 20:39:38 mdz Exp $
+// $Id: copy.cc,v 1.7.2.1 2004/01/16 18:58:50 mdz Exp $
/* ######################################################################
Copy URI - This method takes a uri like a file: uri and copies it
diff --git a/methods/file.cc b/methods/file.cc
index 76fd64d86..3500de9f5 100644
--- a/methods/file.cc
+++ b/methods/file.cc
@@ -1,6 +1,6 @@
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: file.cc,v 1.10 2004/01/07 20:39:38 mdz Exp $
+// $Id: file.cc,v 1.9.2.1 2004/01/16 18:58:50 mdz Exp $
/* ######################################################################
File URI method for APT
diff --git a/methods/ftp.cc b/methods/ftp.cc
index 0f222272d..fafa10534 100644
--- a/methods/ftp.cc
+++ b/methods/ftp.cc
@@ -1,6 +1,6 @@
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: ftp.cc,v 1.32 2004/01/07 20:39:38 mdz Exp $
+// $Id: ftp.cc,v 1.31.2.1 2004/01/16 18:58:50 mdz Exp $
/* ######################################################################
FTP Aquire Method - This is the FTP aquire method for APT.
diff --git a/methods/gpgv.cc b/methods/gpgv.cc
new file mode 100644
index 000000000..b34ea8d85
--- /dev/null
+++ b/methods/gpgv.cc
@@ -0,0 +1,261 @@
+#include <apt-pkg/error.h>
+#include <apt-pkg/acquire-method.h>
+#include <apt-pkg/strutl.h>
+
+#include <sys/stat.h>
+#include <unistd.h>
+#include <utime.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/wait.h>
+#include <iostream>
+
+#define GNUPGPREFIX "[GNUPG:]"
+#define GNUPGBADSIG "[GNUPG:] BADSIG"
+#define GNUPGNOPUBKEY "[GNUPG:] NO_PUBKEY"
+#define GNUPGVALIDSIG "[GNUPG:] VALIDSIG"
+
+class GPGVMethod : public pkgAcqMethod
+{
+ private:
+ const char *VerifyGetSigners(const char *file, const char *outfile,
+ vector<string> &GoodSigners, vector<string> &BadSigners,
+ vector<string> &NoPubKeySigners);
+
+ protected:
+ virtual bool Fetch(FetchItem *Itm);
+
+ public:
+
+ GPGVMethod() : pkgAcqMethod("1.0",SingleInstance | SendConfig) {};
+};
+
+const char *GPGVMethod::VerifyGetSigners(const char *file, const char *outfile,
+ vector<string> &GoodSigners,
+ vector<string> &BadSigners,
+ vector<string> &NoPubKeySigners)
+{
+ if (_config->FindB("Debug::Acquire::gpgv", false))
+ {
+ std::cerr << "inside VerifyGetSigners" << std::endl;
+ }
+ pid_t pid;
+ int fd[2];
+ FILE *pipein;
+ int status;
+ struct stat buff;
+ string gpgvpath = _config->Find("Dir::Bin::gpg", "/usr/bin/gpgv");
+ string pubringpath = _config->Find("Apt::GPGV::TrustedKeyring", "/etc/apt/trusted.gpg");
+ if (_config->FindB("Debug::Acquire::gpgv", false))
+ {
+ std::cerr << "gpgv path: " << gpgvpath << std::endl;
+ 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 (pipe(fd) < 0)
+ {
+ return "Couldn't create pipe";
+ }
+
+ pid = fork();
+ if (pid < 0)
+ {
+ return (string("Couldn't spawn new process") + strerror(errno)).c_str();
+ }
+ else if (pid == 0)
+ {
+ if (_config->FindB("Debug::Acquire::gpgv", false))
+ {
+ std::cerr << "Preparing to exec: " << gpgvpath
+ << " --status-fd 3 --keyring " << pubringpath
+ << " " << file << " " << outfile << std::endl;
+ }
+ int nullfd = open("/dev/null", O_RDONLY);
+ close(fd[0]);
+ // Redirect output to /dev/null; we read from the status fd
+ dup2(nullfd, STDOUT_FILENO);
+ dup2(nullfd, STDERR_FILENO);
+ // Redirect the pipe to the status fd (3)
+ dup2(fd[1], 3);
+
+ putenv("LANG=");
+ putenv("LC_ALL=");
+ putenv("LC_MESSAGES=");
+ execlp(gpgvpath.c_str(), gpgvpath.c_str(), "--status-fd", "3", "--keyring",
+ pubringpath.c_str(), file, outfile, NULL);
+
+ exit(111);
+ }
+ close(fd[1]);
+
+ pipein = fdopen(fd[0], "r");
+
+ // Loop over the output of gpgv, and check the signatures.
+ size_t buffersize = 64;
+ char *buffer = (char *) malloc(buffersize);
+ size_t bufferoff = 0;
+ while (1)
+ {
+ int c;
+
+ // Read a line. Sigh.
+ while ((c = getc(pipein)) != EOF && c != '\n')
+ {
+ if (bufferoff == buffersize)
+ buffer = (char *) realloc(buffer, buffersize *= 2);
+ *(buffer+bufferoff) = c;
+ bufferoff++;
+ }
+ if (bufferoff == 0 && c == EOF)
+ break;
+ *(buffer+bufferoff) = '\0';
+ bufferoff = 0;
+ if (_config->FindB("Debug::Acquire::gpgv", false))
+ std::cerr << "Read: " << buffer << std::endl;
+
+ // Push the data into three separate vectors, which
+ // we later concatenate. They're kept separate so
+ // if we improve the apt method communication stuff later
+ // it will be better.
+ if (strncmp(buffer, GNUPGBADSIG, sizeof(GNUPGBADSIG)-1) == 0)
+ {
+ if (_config->FindB("Debug::Acquire::gpgv", false))
+ std::cerr << "Got BADSIG! " << std::endl;
+ BadSigners.push_back(string(buffer+sizeof(GNUPGPREFIX)));
+ }
+
+ if (strncmp(buffer, GNUPGNOPUBKEY, sizeof(GNUPGNOPUBKEY)-1) == 0)
+ {
+ if (_config->FindB("Debug::Acquire::gpgv", false))
+ std::cerr << "Got NO_PUBKEY " << std::endl;
+ NoPubKeySigners.push_back(string(buffer+sizeof(GNUPGPREFIX)));
+ }
+
+ if (strncmp(buffer, GNUPGVALIDSIG, sizeof(GNUPGVALIDSIG)-1) == 0)
+ {
+ char *sig = buffer + sizeof(GNUPGPREFIX);
+ char *p = sig + sizeof("VALIDSIG");
+ while (*p && isxdigit(*p))
+ p++;
+ *p = 0;
+ if (_config->FindB("Debug::Acquire::gpgv", false))
+ std::cerr << "Got VALIDSIG, key ID:" << sig << std::endl;
+ GoodSigners.push_back(string(sig));
+ }
+ }
+ fclose(pipein);
+
+ waitpid(pid, &status, 0);
+ if (_config->FindB("Debug::Acquire::gpgv", false))
+ {
+ std::cerr <<"gpgv exited\n";
+ }
+
+ if (WEXITSTATUS(status) == 0)
+ {
+ if (GoodSigners.empty())
+ return "Internal error: Good signature, but could not determine key fingerprint?!";
+ return NULL;
+ }
+ else if (WEXITSTATUS(status) == 1)
+ {
+ return "At least one invalid signature was encountered.";
+ }
+ else if (WEXITSTATUS(status) == 111)
+ {
+ return (string("Could not execute ") + gpgvpath +
+ string(" to verify signature (is gnupg installed?)")).c_str();
+ }
+ else
+ {
+ return "Unknown error executing gpgv";
+ }
+}
+
+bool GPGVMethod::Fetch(FetchItem *Itm)
+{
+ URI Get = Itm->Uri;
+ string Path = Get.Host + Get.Path; // To account for relative paths
+ string keyID;
+ vector<string> GoodSigners;
+ vector<string> BadSigners;
+ vector<string> NoPubKeySigners;
+
+ FetchResult Res;
+ Res.Filename = Itm->DestFile;
+ 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);
+ 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())
+ errmsg = msg;
+ else
+ {
+ if (!BadSigners.empty())
+ {
+ errmsg += "The following signatures were invalid:\n";
+ for (vector<string>::iterator I = BadSigners.begin();
+ I != BadSigners.end(); I++)
+ errmsg += (*I + "\n");
+ }
+ if (!NoPubKeySigners.empty())
+ {
+ errmsg += "The following signatures couldn't be verified because the public key is not available:\n";
+ for (vector<string>::iterator I = NoPubKeySigners.begin();
+ I != NoPubKeySigners.end(); I++)
+ errmsg += (*I + "\n");
+ }
+ }
+ return _error->Error(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.
+ Res.GPGVOutput = GoodSigners;
+ Res.GPGVOutput.insert(Res.GPGVOutput.end(),BadSigners.begin(),BadSigners.end());
+ Res.GPGVOutput.insert(Res.GPGVOutput.end(),NoPubKeySigners.begin(),NoPubKeySigners.end());
+ URIDone(Res);
+
+ if (_config->FindB("Debug::Acquire::gpgv", false))
+ {
+ std::cerr <<"gpgv suceeded\n";
+ }
+
+ return true;
+}
+
+
+int main()
+{
+ GPGVMethod Mth;
+
+ return Mth.Run();
+}
diff --git a/methods/gzip.cc b/methods/gzip.cc
index ac64f33f8..809afc0fc 100644
--- a/methods/gzip.cc
+++ b/methods/gzip.cc
@@ -1,6 +1,6 @@
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: gzip.cc,v 1.18 2004/01/07 20:39:38 mdz Exp $
+// $Id: gzip.cc,v 1.17.2.1 2004/01/16 18:58:50 mdz Exp $
/* ######################################################################
GZip method - Take a file URI in and decompress it into the target
@@ -57,7 +57,7 @@ bool GzipMethod::Fetch(FetchItem *Itm)
return _error->Errno("pipe",_("Couldn't open pipe for %s"),Prog);
// Fork gzip
- int Process = ExecFork();
+ pid_t Process = ExecFork();
if (Process == 0)
{
close(GzOut[0]);
diff --git a/methods/makefile b/methods/makefile
index 50f44342c..089300570 100644
--- a/methods/makefile
+++ b/methods/makefile
@@ -7,7 +7,7 @@ include ../buildlib/defaults.mak
BIN := $(BIN)/methods
# FIXME..
-LIB_APT_PKG_MAJOR = 3.3
+LIB_APT_PKG_MAJOR = 3.5
APT_DOMAIN := libapt-pkg$(LIB_APT_PKG_MAJOR)
# The file method
@@ -31,6 +31,13 @@ LIB_MAKES = apt-pkg/makefile
SOURCE = gzip.cc
include $(PROGRAM_H)
+# The gpgv method
+PROGRAM=gpgv
+SLIBS = -lapt-pkg
+LIB_MAKES = apt-pkg/makefile
+SOURCE = gpgv.cc
+include $(PROGRAM_H)
+
# The cdrom method
PROGRAM=cdrom
SLIBS = -lapt-pkg
diff --git a/methods/rsh.cc b/methods/rsh.cc
index c742a6eaf..ffd2b7dbd 100644
--- a/methods/rsh.cc
+++ b/methods/rsh.cc
@@ -1,6 +1,6 @@
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: rsh.cc,v 1.7 2004/01/07 20:39:38 mdz Exp $
+// $Id: rsh.cc,v 1.6.2.1 2004/01/16 18:58:50 mdz Exp $
/* ######################################################################
RSH method - Transfer files via rsh compatible program
diff --git a/methods/rsh.h b/methods/rsh.h
index bb97f062c..b06d5a94e 100644
--- a/methods/rsh.h
+++ b/methods/rsh.h
@@ -29,7 +29,7 @@ class RSHConn
public:
- int Process;
+ pid_t Process;
// Raw connection IO
bool WriteMsg(string &Text,bool Sync,const char *Fmt,...);