aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/local-store.cc
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/libstore/local-store.cc
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/libstore/local-store.cc')
-rw-r--r--src/libstore/local-store.cc114
1 files changed, 110 insertions, 4 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;