X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/233b78083f6f79730fcb5a6faeb74e2a78b6038a..ce928105d7279c5604f034740b04dc6a745fb859:/apt-pkg/contrib/gpgv.cc

diff --git a/apt-pkg/contrib/gpgv.cc b/apt-pkg/contrib/gpgv.cc
index 7e244c623..f24dd9640 100644
--- a/apt-pkg/contrib/gpgv.cc
+++ b/apt-pkg/contrib/gpgv.cc
@@ -2,35 +2,31 @@
 // Include Files							/*{{{*/
 #include<config.h>
 
+#include<apt-pkg/configuration.h>
+#include<apt-pkg/error.h>
+#include<apt-pkg/strutl.h>
+#include<apt-pkg/fileutl.h>
+#include<apt-pkg/gpgv.h>
+
 #include <errno.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
 #include <sys/wait.h>
-
-#include<apt-pkg/configuration.h>
-#include<apt-pkg/error.h>
-#include<apt-pkg/strutl.h>
-#include<apt-pkg/fileutl.h>
-#include<apt-pkg/gpgv.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <iostream>
+#include <string>
+#include <vector>
 
 #include <apti18n.h>
 									/*}}}*/
 static char * GenerateTemporaryFileTemplate(const char *basename)	/*{{{*/
 {
-   const char *tmpdir = getenv("TMPDIR");
-#ifdef P_tmpdir
-   if (!tmpdir)
-      tmpdir = P_tmpdir;
-#endif
-   if (!tmpdir)
-      tmpdir = "/tmp";
-
    std::string out;
-   strprintf(out,  "%s/%s.XXXXXX", tmpdir, basename);
+   std::string tmpdir = GetTempDir();
+   strprintf(out,  "%s/%s.XXXXXX", tmpdir.c_str(), basename);
    return strdup(out.c_str());
 }
 									/*}}}*/
@@ -41,6 +37,7 @@ static char * GenerateTemporaryFileTemplate(const char *basename)	/*{{{*/
    Also, as gpgv has no options to enforce a certain reduced style of
    clear-signed files (=the complete content of the file is signed and
    the content isn't encoded) we do a divide and conquer approach here
+   and split up the clear-signed file in message and signature for gpgv
 */
 void ExecGPGV(std::string const &File, std::string const &FileGPG,
              int const &statusfd, int fd[2])
@@ -108,14 +105,12 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG,
       }
    }
 
-   int sigFd = -1;
-   int dataFd = -1;
+   enum  { DETACHED, CLEARSIGNED } releaseSignature = (FileGPG != File) ? DETACHED : CLEARSIGNED;
    std::vector<std::string> dataHeader;
    char * sig = NULL;
    char * data = NULL;
 
-   // file with detached signature
-   if (FileGPG != File)
+   if (releaseSignature == DETACHED)
    {
       Args.push_back(FileGPG.c_str());
       Args.push_back(File.c_str());
@@ -126,27 +121,37 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG,
       data = GenerateTemporaryFileTemplate("apt.data");
       if (sig == NULL || data == NULL)
       {
+	 ioprintf(std::cerr, "Couldn't create tempfile names for splitting up %s", File.c_str());
+	 exit(EINTERNAL);
+      }
+
+      int const sigFd = mkstemp(sig);
+      int const dataFd = mkstemp(data);
+      if (sigFd == -1 || dataFd == -1)
+      {
+	 if (dataFd != -1)
+	    unlink(sig);
+	 if (sigFd != -1)
+	    unlink(data);
 	 ioprintf(std::cerr, "Couldn't create tempfiles for splitting up %s", File.c_str());
 	 exit(EINTERNAL);
       }
 
-      sigFd = mkstemp(sig);
-      dataFd = mkstemp(data);
-      int const duppedSigFd = dup(sigFd);
-      int const duppedDataFd = dup(dataFd);
+      FileFd signature;
+      signature.OpenDescriptor(sigFd, FileFd::WriteOnly, true);
+      FileFd message;
+      message.OpenDescriptor(dataFd, FileFd::WriteOnly, true);
 
-      if (dataFd == -1 || sigFd == -1 || duppedDataFd == -1 || duppedSigFd == -1 ||
-	    SplitClearSignedFile(File, duppedDataFd, &dataHeader, duppedSigFd) == false)
+      if (signature.Failed() == true || message.Failed() == true ||
+	    SplitClearSignedFile(File, &message, &dataHeader, &signature) == false)
       {
 	 if (dataFd != -1)
 	    unlink(sig);
 	 if (sigFd != -1)
 	    unlink(data);
 	 ioprintf(std::cerr, "Splitting up %s into data and signature failed", File.c_str());
-	 exit(EINTERNAL);
+	 exit(112);
       }
-      lseek(dataFd, 0, SEEK_SET);
-      lseek(sigFd, 0, SEEK_SET);
       Args.push_back(sig);
       Args.push_back(data);
    }
@@ -178,7 +183,7 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG,
       putenv((char *)"LC_MESSAGES=");
    }
 
-   if (FileGPG != File)
+   if (releaseSignature == DETACHED)
    {
       execvp(gpgvpath.c_str(), (char **) &Args[0]);
       ioprintf(std::cerr, "Couldn't execute %s to check %s", Args[0], File.c_str());
@@ -242,36 +247,13 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG,
 }
 									/*}}}*/
 // SplitClearSignedFile - split message into data/signature		/*{{{*/
-bool SplitClearSignedFile(std::string const &InFile, int const ContentFile,
-      std::vector<std::string> * const ContentHeader, int const SignatureFile)
+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());
 
-   FILE *out_content = NULL;
-   FILE *out_signature = NULL;
-   if (ContentFile != -1)
-   {
-      out_content = fdopen(ContentFile, "w");
-      if (out_content == NULL)
-      {
-	 fclose(in);
-	 return _error->Errno("fdopen", "Failed to open file to write content to from %s", InFile.c_str());
-      }
-   }
-   if (SignatureFile != -1)
-   {
-      out_signature = fdopen(SignatureFile, "w");
-      if (out_signature == NULL)
-      {
-	 fclose(in);
-	 if (out_content != NULL)
-	    fclose(out_content);
-	 return _error->Errno("fdopen", "Failed to open file to write signature to from %s", InFile.c_str());
-      }
-   }
-
    bool found_message_start = false;
    bool found_message_end = false;
    bool skip_until_empty_line = false;
@@ -305,35 +287,41 @@ bool SplitClearSignedFile(std::string const &InFile, int const ContentFile,
 	 {
 	    found_signature = true;
 	    found_message_end = true;
-	    if (out_signature != NULL)
-	       fprintf(out_signature, "%s\n", buf);
+	    if (SignatureFile != NULL)
+	    {
+	       SignatureFile->Write(buf, strlen(buf));
+	       SignatureFile->Write("\n", 1);
+	    }
 	 }
-	 else if (found_message_end == false)
+	 else if (found_message_end == false) // we are in the message block
 	 {
-	    // 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
-	    {
-	       if (out_content != NULL)
-		  fprintf(out_content, "%s", buf);
 	       first_line = false;
-	    }
-	    else if (out_content != NULL)
-	       fprintf(out_content, "\n%s", buf);
+	    else if (ContentFile != NULL)
+	       ContentFile->Write("\n", 1);
+	    else
+	       continue;
+	    if (ContentFile != NULL)
+	       ContentFile->Write(dashfree, strlen(dashfree));
 	 }
       }
       else if (found_signature == true)
       {
-	 if (out_signature != NULL)
-	    fprintf(out_signature, "%s\n", buf);
+	 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
    }
-   if (out_content != NULL)
-      fclose(out_content);
-   if (out_signature != NULL)
-      fclose(out_signature);
    fclose(in);
 
    if (found_signature == true)
@@ -341,11 +329,11 @@ bool SplitClearSignedFile(std::string const &InFile, int const ContentFile,
 
    // 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 (found_message_start == false && found_message_end == false)
+   if (first_line == true && found_message_start == false && found_message_end == false)
       return false;
    // otherwise one missing indicates a syntax error
-   else if (found_message_start == false || found_message_end == false)
-      return _error->Error("Splitting of file %s failed as it doesn't contain all expected parts", InFile.c_str());
+   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;
 }
@@ -363,17 +351,17 @@ bool OpenMaybeClearSignedFile(std::string const &ClearSignedFileName, FileFd &Me
    unlink(message);
    free(message);
 
-   int const duppedMsg = dup(messageFd);
-   if (duppedMsg == -1)
-      return _error->Errno("dup", "Couldn't duplicate FD to work with %s", ClearSignedFileName.c_str());
+   MessageFile.OpenDescriptor(messageFd, FileFd::ReadWrite, true);
+   if (MessageFile.Failed() == true)
+      return _error->Error("Couldn't open temporary file to work with %s", ClearSignedFileName.c_str());
 
    _error->PushToStack();
-   bool const splitDone = SplitClearSignedFile(ClearSignedFileName.c_str(), messageFd, NULL, -1);
+   bool const splitDone = SplitClearSignedFile(ClearSignedFileName, &MessageFile, NULL, NULL);
    bool const errorDone = _error->PendingError();
    _error->MergeWithStack();
    if (splitDone == false)
    {
-      close(duppedMsg);
+      MessageFile.Close();
 
       if (errorDone == true)
 	 return false;
@@ -383,9 +371,8 @@ bool OpenMaybeClearSignedFile(std::string const &ClearSignedFileName, FileFd &Me
    }
    else // clear-signed
    {
-      if (lseek(duppedMsg, 0, SEEK_SET) < 0)
-	 return _error->Errno("lseek", "Unable to seek back in message fd for file %s", ClearSignedFileName.c_str());
-      MessageFile.OpenDescriptor(duppedMsg, FileFd::ReadOnly, true);
+      if (MessageFile.Seek(0) == false)
+	 return _error->Errno("lseek", "Unable to seek back in message for file %s", ClearSignedFileName.c_str());
    }
 
    return MessageFile.Failed() == false;