aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2007-02-21 15:45:32 +0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2007-02-21 15:45:32 +0000
commit43c4d18c6a4e1a8b129114439718e26c12b49ca8 (patch)
tree9e8927fbb240928c5d2f2a9fcee0f366d5630058 /src
parent46e0919ced4646004cc0701b188d0a68e24e8924 (diff)
* `nix-store --import': import an archive created by `nix-store
--export' into the Nix store, and optionally check the cryptographic signatures against /nix/etc/nix/signing-key.pub. (TODO: verify against a set of public keys.)
Diffstat (limited to 'src')
-rw-r--r--src/libstore/local-store.cc114
-rw-r--r--src/libstore/local-store.hh2
-rw-r--r--src/libstore/remote-store.cc6
-rw-r--r--src/libstore/remote-store.hh2
-rw-r--r--src/libstore/store-api.hh4
-rw-r--r--src/libutil/util.cc10
-rw-r--r--src/libutil/util.hh2
-rw-r--r--src/nix-store/nix-store.cc12
8 files changed, 142 insertions, 10 deletions
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index 991f28e8d..a7c9d5811 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -6,6 +6,7 @@
#include "pathlocks.hh"
#include "aterm.hh"
#include "derivations-ast.hh"
+#include "worker-protocol.hh"
#include "config.h"
#include <iostream>
@@ -743,8 +744,6 @@ void LocalStore::exportPath(const Path & path, bool sign,
writeInt(1, hashAndWriteSink);
- //printMsg(lvlError, format("HASH = %1%") % printHash(hash));
-
Path tmpDir = createTempDir();
AutoDelete delTmp(tmpDir);
Path hashFile = tmpDir + "/hash";
@@ -759,8 +758,6 @@ void LocalStore::exportPath(const Path & path, bool sign,
args.push_back(hashFile);
string signature = runProgram("openssl", true, args);
- //printMsg(lvlError, format("SIGNATURE = %1%") % signature);
-
writeString(signature, hashAndWriteSink);
} else
@@ -768,6 +765,115 @@ void LocalStore::exportPath(const Path & path, bool sign,
}
+struct HashAndReadSource : Source
+{
+ Source & readSource;
+ HashSink hashSink;
+ bool hashing;
+ HashAndReadSource(Source & readSource) : readSource(readSource), hashSink(htSHA256)
+ {
+ hashing = true;
+ }
+ virtual void operator ()
+ (unsigned char * data, unsigned int len)
+ {
+ readSource(data, len);
+ if (hashing) hashSink(data, len);
+ }
+};
+
+
+Path LocalStore::importPath(bool requireSignature, Source & source)
+{
+ HashAndReadSource hashAndReadSource(source);
+
+ /* We don't yet know what store path this archive contains (the
+ store path follows the archive data proper), and besides, we
+ don't know yet whether the signature is valid. */
+ Path tmpDir = createTempDir(nixStore);
+ AutoDelete delTmp(tmpDir);
+ Path unpacked = tmpDir + "/unpacked";
+
+ restorePath(unpacked, hashAndReadSource);
+
+ unsigned int magic = readInt(hashAndReadSource);
+ if (magic != EXPORT_MAGIC)
+ throw Error("Nix archive cannot be imported; wrong format");
+
+ Path dstPath = readStorePath(hashAndReadSource);
+
+ PathSet references = readStorePaths(hashAndReadSource);
+
+ Path deriver = readStorePath(hashAndReadSource);
+
+ Hash hash = hashAndReadSource.hashSink.finish();
+ hashAndReadSource.hashing = false;
+
+ bool haveSignature = readInt(hashAndReadSource) == 1;
+
+ if (requireSignature && !haveSignature)
+ throw Error("imported archive lacks a signature");
+
+ if (haveSignature) {
+ string signature = readString(hashAndReadSource);
+
+ Path sigFile = tmpDir + "/sig";
+ writeStringToFile(sigFile, signature);
+
+ Strings args;
+ args.push_back("rsautl");
+ args.push_back("-verify");
+ args.push_back("-inkey");
+ args.push_back(nixConfDir + "/signing-key.pub");
+ args.push_back("-pubin");
+ args.push_back("-in");
+ args.push_back(sigFile);
+ string hash2 = runProgram("openssl", true, args);
+
+ /* Note: runProgram() throws an exception if the signature is
+ invalid. */
+
+ if (printHash(hash) != hash2)
+ throw Error(
+ "signed hash doesn't match actual contents of imported "
+ "archive; archive could be corrupt, or someone is trying "
+ "to import a Trojan horse");
+ }
+
+ /* Do the actual import. */
+
+ /* !!! way too much code duplication with addTextToStore() etc. */
+ addTempRoot(dstPath);
+
+ if (!isValidPath(dstPath)) {
+
+ PathLocks outputLock(singleton<PathSet, Path>(dstPath));
+
+ if (!isValidPath(dstPath)) {
+
+ if (pathExists(dstPath)) deletePathWrapped(dstPath);
+
+ if (rename(unpacked.c_str(), dstPath.c_str()) == -1)
+ throw SysError(format("cannot move `%1%' to `%2%'")
+ % unpacked % dstPath);
+
+ canonicalisePathMetaData(dstPath);
+
+ Transaction txn(nixDB);
+ /* !!! if we were clever, we could prevent the hashPath()
+ here. */
+ registerValidPath(txn, dstPath,
+ hashPath(htSHA256, dstPath), references, "");
+ txn.commit();
+ }
+
+ outputLock.setDeletion(true);
+ }
+
+ return dstPath;
+}
+
+
void deleteFromStore(const Path & _path, unsigned long long & bytesFreed)
{
bytesFreed = 0;
diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh
index cae9d5c53..76d14c3a6 100644
--- a/src/libstore/local-store.hh
+++ b/src/libstore/local-store.hh
@@ -59,6 +59,8 @@ public:
void exportPath(const Path & path, bool sign,
Sink & sink);
+ Path importPath(bool requireSignature, Source & source);
+
void buildDerivations(const PathSet & drvPaths);
void ensurePath(const Path & path);
diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc
index 2fb4dd980..801df58ad 100644
--- a/src/libstore/remote-store.cc
+++ b/src/libstore/remote-store.cc
@@ -250,6 +250,12 @@ void RemoteStore::exportPath(const Path & path, bool sign,
}
+Path RemoteStore::importPath(bool requireSignature, Source & source)
+{
+ throw Error("not implemented");
+}
+
+
void RemoteStore::buildDerivations(const PathSet & drvPaths)
{
writeInt(wopBuildDerivations, to);
diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh
index 69fae2cd1..4c594b606 100644
--- a/src/libstore/remote-store.hh
+++ b/src/libstore/remote-store.hh
@@ -47,6 +47,8 @@ public:
void exportPath(const Path & path, bool sign,
Sink & sink);
+ Path importPath(bool requireSignature, Source & source);
+
void buildDerivations(const PathSet & drvPaths);
void ensurePath(const Path & path);
diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh
index 6a1de616c..1f2d60f11 100644
--- a/src/libstore/store-api.hh
+++ b/src/libstore/store-api.hh
@@ -99,6 +99,10 @@ public:
virtual void exportPath(const Path & path, bool sign,
Sink & sink) = 0;
+ /* Import a NAR dump created by exportPath() into the Nix
+ store. */
+ virtual Path importPath(bool requireSignature, Source & source) = 0;
+
/* Ensure that the output paths of the derivation are valid. If
they are already valid, this is a no-op. Otherwise, validity
can be reached in two ways. First, if the output paths have
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 7671c7c7e..1576e1e8b 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -317,19 +317,19 @@ void makePathReadOnly(const Path & path)
}
-static Path tempName()
+static Path tempName(const Path & tmpRoot)
{
static int counter = 0;
- Path tmpRoot = canonPath(getEnv("TMPDIR", "/tmp"), true);
- return (format("%1%/nix-%2%-%3%") % tmpRoot % getpid() % counter++).str();
+ Path tmpRoot2 = canonPath(tmpRoot.empty() ? getEnv("TMPDIR", "/tmp") : tmpRoot, true);
+ return (format("%1%/nix-%2%-%3%") % tmpRoot2 % getpid() % counter++).str();
}
-Path createTempDir()
+Path createTempDir(const Path & tmpRoot)
{
while (1) {
checkInterrupt();
- Path tmpDir = tempName();
+ Path tmpDir = tempName(tmpRoot);
if (mkdir(tmpDir.c_str(), 0777) == 0) {
/* Explicitly set the group of the directory. This is to
work around around problems caused by BSD's group
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index 0ebf6f5a5..3c4629957 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -70,7 +70,7 @@ void deletePath(const Path & path, unsigned long long & bytesFreed);
void makePathReadOnly(const Path & path);
/* Create a temporary directory. */
-Path createTempDir();
+Path createTempDir(const Path & tmpRoot = "");
/* Create a directory and all its parents, if necessary. */
void createDirs(const Path & path);
diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc
index 7b56de7e4..61ae4cf4f 100644
--- a/src/nix-store/nix-store.cc
+++ b/src/nix-store/nix-store.cc
@@ -651,6 +651,16 @@ static void opExport(Strings opFlags, Strings opArgs)
}
+static void opImport(Strings opFlags, Strings opArgs)
+{
+ if (!opFlags.empty()) throw UsageError("unknown flag");
+ if (!opArgs.empty()) throw UsageError("no arguments expected");
+
+ FdSource source(STDIN_FILENO);
+ cout << format("%1%\n") % store->importPath(false, source);
+}
+
+
/* Initialise the Nix databases. */
static void opInit(Strings opFlags, Strings opArgs)
{
@@ -722,6 +732,8 @@ void run(Strings args)
op = opRestore;
else if (arg == "--export")
op = opExport;
+ else if (arg == "--import")
+ op = opImport;
else if (arg == "--init")
op = opInit;
else if (arg == "--verify")