summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--doc/signing.txt4
-rw-r--r--src/libstore/build.cc3
-rw-r--r--src/libstore/local-store.cc62
-rw-r--r--src/libutil/hash.cc39
-rw-r--r--src/libutil/hash.hh19
-rw-r--r--src/libutil/util.cc15
-rw-r--r--src/libutil/util.hh3
-rw-r--r--src/nix-store/nix-store.cc10
8 files changed, 124 insertions, 31 deletions
diff --git a/doc/signing.txt b/doc/signing.txt
index fad14d743a..1d042e95e2 100644
--- a/doc/signing.txt
+++ b/doc/signing.txt
@@ -1,6 +1,6 @@
 Generate a private key:
 
-$ openssl genrsa -out mykey.sec 2048
+$ (umask 277 && openssl genrsa -out /nix/etc/nix/signing-key.sec 2048)
 
 The private key should be kept secret (only readable to the Nix daemon
 user).
@@ -8,7 +8,7 @@ user).
 
 Generate the corresponding public key:
 
-$ openssl rsa -in mykey.sec -pubout > mykey.pub
+$ openssl rsa -in /nix/etc/nix/signing-key.sec -pubout > /nix/etc/nix/signing-key.pub
 
 The public key should be copied to all machines to which you want to
 export store paths.
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 1789eeda2f..bee0466550 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -477,8 +477,7 @@ static void runSetuidHelper(const string & command,
 
     case 0: /* child */
         try {
-            std::vector<const char *> args; /* careful with c_str()!
-                                               */
+            std::vector<const char *> args; /* careful with c_str()! */
             args.push_back(program.c_str());
             args.push_back(command.c_str());
             args.push_back(arg.c_str());
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index dcb430a0fc..991f28e8da 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -696,21 +696,75 @@ Path LocalStore::addTextToStore(const string & suffix, const string & s,
 }
 
 
+struct HashAndWriteSink : Sink
+{
+    Sink & writeSink;
+    HashSink hashSink;
+    bool hashing;
+    HashAndWriteSink(Sink & writeSink) : writeSink(writeSink), hashSink(htSHA256)
+    {
+        hashing = true;
+    }
+    virtual void operator ()
+        (const unsigned char * data, unsigned int len)
+    {
+        writeSink(data, len);
+        if (hashing) hashSink(data, len);
+    }
+};
+
+
+#define EXPORT_MAGIC 0x4558494e
+
+
 void LocalStore::exportPath(const Path & path, bool sign,
     Sink & sink)
 {
     assertStorePath(path);
+
+    HashAndWriteSink hashAndWriteSink(sink);
     
-    dumpPath(path, sink);
+    dumpPath(path, hashAndWriteSink);
 
-    writeString(path, sink);
+    writeInt(EXPORT_MAGIC, hashAndWriteSink);
+
+    writeString(path, hashAndWriteSink);
     
     PathSet references;
     queryReferences(path, references);
-    writeStringSet(references, sink);
+    writeStringSet(references, hashAndWriteSink);
 
     Path deriver = queryDeriver(noTxn, path);
-    writeString(deriver, sink);
+    writeString(deriver, hashAndWriteSink);
+
+    if (sign) {
+        Hash hash = hashAndWriteSink.hashSink.finish();
+        hashAndWriteSink.hashing = false;
+
+        writeInt(1, hashAndWriteSink);
+        
+        //printMsg(lvlError, format("HASH = %1%") % printHash(hash));
+
+        Path tmpDir = createTempDir();
+        AutoDelete delTmp(tmpDir);
+        Path hashFile = tmpDir + "/hash";
+        writeStringToFile(hashFile, printHash(hash));
+
+        Strings args;
+        args.push_back("rsautl");
+        args.push_back("-sign");
+        args.push_back("-inkey");
+        args.push_back(nixConfDir + "/signing-key.sec");
+        args.push_back("-in");
+        args.push_back(hashFile);
+        string signature = runProgram("openssl", true, args);
+
+        //printMsg(lvlError, format("SIGNATURE = %1%") % signature);
+
+        writeString(signature, hashAndWriteSink);
+        
+    } else
+        writeInt(0, hashAndWriteSink);
 }
 
 
diff --git a/src/libutil/hash.cc b/src/libutil/hash.cc
index 262dbef20d..3d20d2d50d 100644
--- a/src/libutil/hash.cc
+++ b/src/libutil/hash.cc
@@ -282,30 +282,39 @@ Hash hashFile(HashType ht, const Path & path)
 }
 
 
-struct HashSink : Sink
+HashSink::HashSink(HashType ht) : ht(ht)
 {
-    HashType ht;
-    Ctx ctx;
-    virtual void operator ()
-        (const unsigned char * data, unsigned int len)
-    {
-        update(ht, ctx, data, len);
-    }
-};
+    ctx = new Ctx;
+    start(ht, *ctx);
+}
+    
+HashSink::~HashSink()
+{
+    delete ctx;
+}
 
+void HashSink::operator ()
+    (const unsigned char * data, unsigned int len)
+{
+    update(ht, *ctx, data, len);
+}
 
-Hash hashPath(HashType ht, const Path & path, PathFilter & filter)
+Hash HashSink::finish()
 {
-    HashSink sink;
-    sink.ht = ht;
     Hash hash(ht);
-    start(ht, sink.ctx);
-    dumpPath(path, sink, filter);
-    finish(ht, sink.ctx, hash.hash);
+    nix::finish(ht, *ctx, hash.hash);
     return hash;
 }
 
 
+Hash hashPath(HashType ht, const Path & path, PathFilter & filter)
+{
+    HashSink sink(ht);
+    dumpPath(path, sink, filter);
+    return sink.finish();
+}
+
+
 Hash compressHash(const Hash & hash, unsigned int newSize)
 {
     Hash h;
diff --git a/src/libutil/hash.hh b/src/libutil/hash.hh
index 78227fb6a3..85eb3c1b4d 100644
--- a/src/libutil/hash.hh
+++ b/src/libutil/hash.hh
@@ -2,6 +2,7 @@
 #define __HASH_H
 
 #include "types.hh"
+#include "serialise.hh"
 
 
 namespace nix {
@@ -81,7 +82,23 @@ Hash compressHash(const Hash & hash, unsigned int newSize);
 /* Parse a string representing a hash type. */
 HashType parseHashType(const string & s);
 
- 
+
+typedef union Ctx;
+
+class HashSink : public Sink
+{
+private:
+    HashType ht;
+    Ctx * ctx;
+
+public:
+    HashSink(HashType ht);
+    ~HashSink();
+    virtual void operator () (const unsigned char * data, unsigned int len);
+    Hash finish();
+};
+
+
 }
 
     
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index fb6411408d..7671c7c7e4 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -761,7 +761,7 @@ void killUser(uid_t uid)
 //////////////////////////////////////////////////////////////////////
 
 
-string runProgram(Path program)
+string runProgram(Path program, bool searchPath, const Strings & args)
 {
     /* Create a pipe. */
     Pipe pipe;
@@ -781,8 +781,17 @@ string runProgram(Path program)
 
             if (dup2(pipe.writeSide, STDOUT_FILENO) == -1)
                 throw SysError("dupping from-hook write side");
-            
-            execl(program.c_str(), program.c_str(), (char *) 0);
+
+            std::vector<const char *> cargs; /* careful with c_str()! */
+            cargs.push_back(program.c_str());
+            for (Strings::const_iterator i = args.begin(); i != args.end(); ++i)
+                cargs.push_back(i->c_str());
+            cargs.push_back(0);
+
+            if (searchPath)
+                execvp(program.c_str(), (char * *) &cargs[0]);
+            else
+                execv(program.c_str(), (char * *) &cargs[0]);
             throw SysError(format("executing `%1%'") % program);
             
         } catch (std::exception & e) {
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index 1cc97145c1..0ebf6f5a5f 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -231,7 +231,8 @@ void killUser(uid_t uid);
 
 /* Run a program and return its stdout in a string (i.e., like the
    shell backtick operator). */
-string runProgram(Path program);
+string runProgram(Path program, bool searchPath = false,
+    const Strings & args = Strings());
 
 /* Wrapper around _exit() on Unix and ExitProcess() on Windows.  (On
    Cygwin, _exit() doesn't seem to do the right thing.) */
diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc
index 821124324f..7b56de7e4d 100644
--- a/src/nix-store/nix-store.cc
+++ b/src/nix-store/nix-store.cc
@@ -640,10 +640,14 @@ static void opRestore(Strings opFlags, Strings opArgs)
 
 static void opExport(Strings opFlags, Strings opArgs)
 {
-    if (!opFlags.empty()) throw UsageError("unknown flag");
-
+    bool sign = false;
+    for (Strings::iterator i = opFlags.begin();
+         i != opFlags.end(); ++i)
+        if (*i == "--sign") sign = true;
+        else throw UsageError(format("unknown flag `%1%'") % *i);
+    
     FdSink sink(STDOUT_FILENO);
-    store->exportPath(*opArgs.begin(), false, sink);
+    store->exportPath(*opArgs.begin(), sign, sink);
 }