Implement --signature-filter for signing backup snapshots.
authorMichael Vrable <mvrable@cs.ucsd.edu>
Tue, 21 Aug 2007 00:38:20 +0000 (17:38 -0700)
committerMichael Vrable <mvrable@turin.ucsd.edu>
Tue, 21 Aug 2007 00:38:20 +0000 (17:38 -0700)
If supplied, the argument to --signature-filter will be a program through
which the text for the root snapshot descriptor is filtered.  This filter
should act much like "gpg --clearsign": produce a nearly-identical text
file, with perhaps a few lines at the start or end containing the
signature, but which can be treated as an ordinary segment descriptor by
ignoring this leading and trailing data.

NEWS
scandir.cc

diff --git a/NEWS b/NEWS
index dcdd5e2..9b8ab0a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,10 @@
 0.4?
     - Include an example filter script, lbs-filter-gpg, for encrypting
       segment data as it is written.
+    - Add support for signed snapshot descriptor files (via the
+      --signature-filter option).  Due to the checksums contained in the
+      snapshot descriptor, the signature covers the entire contents of
+      the snapshot.
 
 0.3 [2007-08-10]
     - LOCAL DATABASE CHANGE: A checksums file is now written out along
index 44aedd2..588a907 100644 (file)
@@ -12,6 +12,7 @@
 #include <sys/stat.h>
 #include <sys/sysmacros.h>
 #include <sys/types.h>
+#include <sys/wait.h>
 #include <unistd.h>
 
 #include <algorithm>
@@ -572,6 +573,8 @@ void usage(const char *program)
         "  --filter-extension=EXT\n"
         "                       string to append to segment files\n"
         "                           (defaults to \".bz2\")\n"
+        "  --signature-filter=COMMAND\n"
+        "                       program though which to filter descriptor\n"
         "  --scheme=NAME        optional name for this snapshot\n",
         lbs_version, program
     );
@@ -582,6 +585,7 @@ int main(int argc, char *argv[])
     string backup_dest = "";
     string localdb_dir = "";
     string backup_scheme = "";
+    string signature_filter = "";
 
     while (1) {
         static struct option long_options[] = {
@@ -591,6 +595,7 @@ int main(int argc, char *argv[])
             {"filter-extension", 1, 0, 0},  // 3
             {"dest", 1, 0, 0},              // 4
             {"scheme", 1, 0, 0},            // 5
+            {"signature-filter", 1, 0, 0},  // 6
             {NULL, 0, 0, 0},
         };
 
@@ -623,6 +628,9 @@ int main(int argc, char *argv[])
             case 5:     // --scheme
                 backup_scheme = optarg;
                 break;
+            case 6:     // --signature-filter
+                signature_filter = optarg;
+                break;
             default:
                 fprintf(stderr, "Unhandled long option!\n");
                 return 1;
@@ -762,12 +770,26 @@ int main(int argc, char *argv[])
 
     /* Write a backup descriptor file, which says which segments are needed and
      * where to start to restore this snapshot.  The filename is based on the
-     * current time. */
+     * current time.  If a signature filter program was specified, filter the
+     * data through that to give a chance to sign the descriptor contents. */
     string desc_filename = backup_dest + "/snapshot-";
     if (backup_scheme.size() > 0)
         desc_filename += backup_scheme + "-";
     desc_filename = desc_filename + desc_buf + ".lbs";
-    FILE *descriptor = fopen(desc_filename.c_str(), "w");
+
+    int descriptor_fd = open(desc_filename.c_str(), O_WRONLY | O_CREAT, 0666);
+    if (descriptor_fd < 0) {
+        fprintf(stderr, "Unable to open descriptor output file: %m\n");
+        return 1;
+    }
+    pid_t signature_pid = 0;
+    if (signature_filter.size() > 0) {
+        int new_fd = spawn_filter(descriptor_fd, signature_filter.c_str(),
+                                  &signature_pid);
+        close(descriptor_fd);
+        descriptor_fd = new_fd;
+    }
+    FILE *descriptor = fdopen(descriptor_fd, "w");
 
     fprintf(descriptor, "Format: LBS Snapshot v0.2\n");
     fprintf(descriptor, "Producer: LBS %s\n", lbs_version);
@@ -791,5 +813,14 @@ int main(int argc, char *argv[])
 
     fclose(descriptor);
 
+    if (signature_pid) {
+        int status;
+        waitpid(signature_pid, &status, 0);
+
+        if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+            throw IOException("Signature filter process error");
+        }
+    }
+
     return 0;
 }