Remove OpenSSL-based signing

This commit is contained in:
Eelco Dolstra 2016-05-03 15:11:14 +02:00
parent dfebfc835f
commit f435f82475
16 changed files with 52 additions and 142 deletions

View file

@ -168,10 +168,6 @@ AC_SUBST(storedir)
# Look for OpenSSL, a required dependency. # Look for OpenSSL, a required dependency.
AC_PATH_PROG(openssl, openssl, openssl) # if not found, call openssl in $PATH
AC_SUBST(openssl)
AC_DEFINE_UNQUOTED(OPENSSL_PATH, ["$openssl"], [Path of the OpenSSL binary])
PKG_CHECK_MODULES([OPENSSL], [libcrypto], [CXXFLAGS="$OPENSSL_CFLAGS $CXXFLAGS"]) PKG_CHECK_MODULES([OPENSSL], [libcrypto], [CXXFLAGS="$OPENSSL_CFLAGS $CXXFLAGS"])

View file

@ -14,7 +14,6 @@ $storeDir = $ENV{"NIX_STORE_DIR"} || "@storedir@";
$bzip2 = "@bzip2@"; $bzip2 = "@bzip2@";
$xz = "@xz@"; $xz = "@xz@";
$curl = "@curl@"; $curl = "@curl@";
$openssl = "@openssl@";
$useBindings = "@perlbindings@" eq "yes"; $useBindings = "@perlbindings@" eq "yes";

View file

@ -10,7 +10,7 @@ use IPC::Open2;
sub copyToOpen { sub copyToOpen {
my ($from, $to, $sshHost, $storePaths, $includeOutputs, $dryRun, $sign, $useSubstitutes) = @_; my ($from, $to, $sshHost, $storePaths, $includeOutputs, $dryRun, $useSubstitutes) = @_;
$useSubstitutes = 0 if $dryRun || !defined $useSubstitutes; $useSubstitutes = 0 if $dryRun || !defined $useSubstitutes;
@ -41,13 +41,13 @@ sub copyToOpen {
# Send the "import paths" command. # Send the "import paths" command.
syswrite($to, pack("L<x4", 4)) or die; syswrite($to, pack("L<x4", 4)) or die;
exportPaths(fileno($to), $sign, @missing); exportPaths(fileno($to), @missing);
readInt($from) == 1 or die "remote machine $sshHost failed to import closure\n"; readInt($from) == 1 or die "remote machine $sshHost failed to import closure\n";
} }
sub copyTo { sub copyTo {
my ($sshHost, $storePaths, $includeOutputs, $dryRun, $sign, $useSubstitutes) = @_; my ($sshHost, $storePaths, $includeOutputs, $dryRun, $useSubstitutes) = @_;
# Connect to the remote host. # Connect to the remote host.
my ($from, $to); my ($from, $to);
@ -61,7 +61,7 @@ sub copyTo {
return oldCopyTo(@_); return oldCopyTo(@_);
} }
copyToOpen($from, $to, $sshHost, $storePaths, $includeOutputs, $dryRun, $sign, $useSubstitutes); copyToOpen($from, $to, $sshHost, $storePaths, $includeOutputs, $dryRun, $useSubstitutes);
close $to; close $to;
} }
@ -70,7 +70,7 @@ sub copyTo {
# For backwards compatibility with Nix <= 1.7. Will be removed # For backwards compatibility with Nix <= 1.7. Will be removed
# eventually. # eventually.
sub oldCopyTo { sub oldCopyTo {
my ($sshHost, $storePaths, $includeOutputs, $dryRun, $sign, $useSubstitutes) = @_; my ($sshHost, $storePaths, $includeOutputs, $dryRun, $useSubstitutes) = @_;
# Get the closure of this path. # Get the closure of this path.
my @closure = reverse(topoSortPaths(computeFSClosure(0, $includeOutputs, my @closure = reverse(topoSortPaths(computeFSClosure(0, $includeOutputs,
@ -105,7 +105,7 @@ sub oldCopyTo {
print STDERR "copying ", scalar @missing, " missing paths to $sshHost...\n"; print STDERR "copying ", scalar @missing, " missing paths to $sshHost...\n";
unless ($dryRun) { unless ($dryRun) {
open SSH, "| ssh $sshHost @globalSshOpts 'nix-store --import' > /dev/null" or die; open SSH, "| ssh $sshHost @globalSshOpts 'nix-store --import' > /dev/null" or die;
exportPaths(fileno(SSH), $sign, @missing); exportPaths(fileno(SSH), @missing);
close SSH or die "copying store paths to remote machine $sshHost failed: $?"; close SSH or die "copying store paths to remote machine $sshHost failed: $?";
} }
} }

View file

@ -169,13 +169,13 @@ SV * followLinksToStorePath(char * path)
RETVAL RETVAL
void exportPaths(int fd, int sign, ...) void exportPaths(int fd, ...)
PPCODE: PPCODE:
try { try {
Paths paths; Paths paths;
for (int n = 2; n < items; ++n) paths.push_back(SvPV_nolen(ST(n))); for (int n = 2; n < items; ++n) paths.push_back(SvPV_nolen(ST(n)));
FdSink sink(fd); FdSink sink(fd);
store()->exportPaths(paths, sign, sink); store()->exportPaths(paths, sink);
} catch (Error & e) { } catch (Error & e) {
croak("%s", e.what()); croak("%s", e.what());
} }
@ -185,7 +185,7 @@ void importPaths(int fd)
PPCODE: PPCODE:
try { try {
FdSource source(fd); FdSource source(fd);
store()->importPaths(false, source, 0); store()->importPaths(source, 0);
} catch (Error & e) { } catch (Error & e) {
croak("%s", e.what()); croak("%s", e.what());
} }

View file

@ -223,10 +223,6 @@ my @inputs = split /\s/, readline(STDIN);
my @outputs = split /\s/, readline(STDIN); my @outputs = split /\s/, readline(STDIN);
my $maybeSign = "";
$maybeSign = "--sign" if -e "$Nix::Config::confDir/signing-key.sec";
# Copy the derivation and its dependencies to the build machine. This # Copy the derivation and its dependencies to the build machine. This
# is guarded by an exclusive lock per machine to prevent multiple # is guarded by an exclusive lock per machine to prevent multiple
# build-remote instances from copying to a machine simultaneously. # build-remote instances from copying to a machine simultaneously.
@ -250,7 +246,7 @@ if ($@) {
print STDERR "somebody is hogging $uploadLock, continuing...\n"; print STDERR "somebody is hogging $uploadLock, continuing...\n";
unlink $uploadLock; unlink $uploadLock;
} }
Nix::CopyClosure::copyToOpen($from, $to, $hostName, [ $drvPath, @inputs ], 0, 0, $maybeSign ne ""); Nix::CopyClosure::copyToOpen($from, $to, $hostName, [ $drvPath, @inputs ], 0, 0);
close UPLOADLOCK; close UPLOADLOCK;

View file

@ -12,7 +12,7 @@ binmode STDERR, ":encoding(utf8)";
if (scalar @ARGV < 1) { if (scalar @ARGV < 1) {
print STDERR <<EOF print STDERR <<EOF
Usage: nix-copy-closure [--from | --to] HOSTNAME [--sign] [--gzip] [--bzip2] [--xz] PATHS... Usage: nix-copy-closure [--from | --to] HOSTNAME [--gzip] [--bzip2] [--xz] PATHS...
EOF EOF
; ;
exit 1; exit 1;
@ -21,7 +21,6 @@ EOF
# Get the target host. # Get the target host.
my $sshHost; my $sshHost;
my $sign = 0;
my $toMode = 1; my $toMode = 1;
my $includeOutputs = 0; my $includeOutputs = 0;
my $dryRun = 0; my $dryRun = 0;
@ -38,9 +37,6 @@ while (@ARGV) {
if ($arg eq "--help") { if ($arg eq "--help") {
exec "man nix-copy-closure" or die; exec "man nix-copy-closure" or die;
} }
elsif ($arg eq "--sign") {
$sign = 1;
}
elsif ($arg eq "--gzip" || $arg eq "--bzip2" || $arg eq "--xz") { elsif ($arg eq "--gzip" || $arg eq "--bzip2" || $arg eq "--xz") {
warn "$0: $arg is not implemented\n" if $arg ne "--gzip"; warn "$0: $arg is not implemented\n" if $arg ne "--gzip";
push @globalSshOpts, "-C"; push @globalSshOpts, "-C";
@ -81,7 +77,7 @@ die "$0: you did not specify a host name\n" unless defined $sshHost;
if ($toMode) { # Copy TO the remote machine. if ($toMode) { # Copy TO the remote machine.
Nix::CopyClosure::copyTo( Nix::CopyClosure::copyTo(
$sshHost, [ @storePaths ], $sshHost, [ @storePaths ],
$includeOutputs, $dryRun, $sign, $useSubstitutes); $includeOutputs, $dryRun, $useSubstitutes);
} }
else { # Copy FROM the remote machine. else { # Copy FROM the remote machine.
@ -99,7 +95,7 @@ else { # Copy FROM the remote machine.
if (scalar @missing > 0) { if (scalar @missing > 0) {
print STDERR "copying ", scalar @missing, " missing paths from $sshHost...\n"; print STDERR "copying ", scalar @missing, " missing paths from $sshHost...\n";
writeInt(5, $to); # == cmdExportPaths writeInt(5, $to); # == cmdExportPaths
writeInt($sign ? 1 : 0, $to); writeInt(0, $to); # obsolete
writeStrings(\@missing, $to); writeStrings(\@missing, $to);
importPaths(fileno($from)); importPaths(fileno($from));
} }

View file

@ -156,10 +156,8 @@ void BinaryCacheStore::narFromPath(const Path & storePath, Sink & sink)
sink((unsigned char *) nar->c_str(), nar->size()); sink((unsigned char *) nar->c_str(), nar->size());
} }
void BinaryCacheStore::exportPath(const Path & storePath, bool sign, Sink & sink) void BinaryCacheStore::exportPath(const Path & storePath, Sink & sink)
{ {
assert(!sign);
auto res = queryPathInfo(storePath); auto res = queryPathInfo(storePath);
narFromPath(storePath, sink); narFromPath(storePath, sink);
@ -169,10 +167,9 @@ void BinaryCacheStore::exportPath(const Path & storePath, bool sign, Sink & sink
sink << exportMagic << storePath << res->references << res->deriver << 0; sink << exportMagic << storePath << res->references << res->deriver << 0;
} }
Paths BinaryCacheStore::importPaths(bool requireSignature, Source & source, Paths BinaryCacheStore::importPaths(Source & source,
std::shared_ptr<FSAccessor> accessor) std::shared_ptr<FSAccessor> accessor)
{ {
assert(!requireSignature);
Paths res; Paths res;
while (true) { while (true) {
unsigned long long n = readLongLong(source); unsigned long long n = readLongLong(source);
@ -346,7 +343,7 @@ struct BinaryCacheStoreAccessor : public FSAccessor
if (i != nars.end()) return {i->second, restPath}; if (i != nars.end()) return {i->second, restPath};
StringSink sink; StringSink sink;
store->exportPath(storePath, false, sink); store->exportPath(storePath, sink);
auto accessor = makeNarAccessor(sink.s); auto accessor = makeNarAccessor(sink.s);
nars.emplace(storePath, accessor); nars.emplace(storePath, accessor);

View file

@ -91,9 +91,9 @@ public:
void narFromPath(const Path & path, Sink & sink) override; void narFromPath(const Path & path, Sink & sink) override;
void exportPath(const Path & path, bool sign, Sink & sink) override; void exportPath(const Path & path, Sink & sink) override;
Paths importPaths(bool requireSignature, Source & source, Paths importPaths(Source & source,
std::shared_ptr<FSAccessor> accessor) override; std::shared_ptr<FSAccessor> accessor) override;
Path importPath(Source & source, std::shared_ptr<FSAccessor> accessor); Path importPath(Source & source, std::shared_ptr<FSAccessor> accessor);

View file

@ -1035,18 +1035,7 @@ struct HashAndWriteSink : Sink
}; };
static void checkSecrecy(const Path & path) void LocalStore::exportPath(const Path & path, Sink & sink)
{
struct stat st;
if (stat(path.c_str(), &st))
throw SysError(format("getting status of %1%") % path);
if ((st.st_mode & (S_IRWXG | S_IRWXO)) != 0)
throw Error(format("file %1% should be secret (inaccessible to everybody else)!") % path);
}
void LocalStore::exportPath(const Path & path, bool sign,
Sink & sink)
{ {
assertStorePath(path); assertStorePath(path);
@ -1068,30 +1057,7 @@ void LocalStore::exportPath(const Path & path, bool sign,
hashAndWriteSink << exportMagic << path << info->references << info->deriver; hashAndWriteSink << exportMagic << path << info->references << info->deriver;
if (sign) { hashAndWriteSink << 0; // backwards compatibility
Hash hash = hashAndWriteSink.currentHash();
Path tmpDir = createTempDir();
AutoDelete delTmp(tmpDir);
Path hashFile = tmpDir + "/hash";
writeFile(hashFile, printHash(hash));
Path secretKey = settings.nixConfDir + "/signing-key.sec";
checkSecrecy(secretKey);
Strings args;
args.push_back("rsautl");
args.push_back("-sign");
args.push_back("-inkey");
args.push_back(secretKey);
args.push_back("-in");
args.push_back(hashFile);
string signature = runProgram(OPENSSL_PATH, true, args);
hashAndWriteSink << 1 << signature;
} else
hashAndWriteSink << 0;
} }
@ -1129,7 +1095,7 @@ Path LocalStore::createTempDirInStore()
} }
Path LocalStore::importPath(bool requireSignature, Source & source) Path LocalStore::importPath(Source & source)
{ {
HashAndReadSource hashAndReadSource(source); HashAndReadSource hashAndReadSource(source);
@ -1160,36 +1126,9 @@ Path LocalStore::importPath(bool requireSignature, Source & source)
bool haveSignature = readInt(hashAndReadSource) == 1; bool haveSignature = readInt(hashAndReadSource) == 1;
if (requireSignature && !haveSignature) if (haveSignature)
throw Error(format("imported archive of %1% lacks a signature") % dstPath); // Ignore legacy signature.
readString(hashAndReadSource);
if (haveSignature) {
string signature = readString(hashAndReadSource);
if (requireSignature) {
Path sigFile = tmpDir + "/sig";
writeFile(sigFile, signature);
Strings args;
args.push_back("rsautl");
args.push_back("-verify");
args.push_back("-inkey");
args.push_back(settings.nixConfDir + "/signing-key.pub");
args.push_back("-pubin");
args.push_back("-in");
args.push_back(sigFile);
string hash2 = runProgram(OPENSSL_PATH, 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. */ /* Do the actual import. */
@ -1239,7 +1178,7 @@ Path LocalStore::importPath(bool requireSignature, Source & source)
} }
Paths LocalStore::importPaths(bool requireSignature, Source & source, Paths LocalStore::importPaths(Source & source,
std::shared_ptr<FSAccessor> accessor) std::shared_ptr<FSAccessor> accessor)
{ {
Paths res; Paths res;
@ -1247,7 +1186,7 @@ Paths LocalStore::importPaths(bool requireSignature, Source & source,
unsigned long long n = readLongLong(source); unsigned long long n = readLongLong(source);
if (n == 0) break; if (n == 0) break;
if (n != 1) throw Error("input doesn't look like something created by nix-store --export"); if (n != 1) throw Error("input doesn't look like something created by nix-store --export");
res.push_back(importPath(requireSignature, source)); res.push_back(importPath(source));
} }
return res; return res;
} }

View file

@ -126,10 +126,9 @@ public:
Path addTextToStore(const string & name, const string & s, Path addTextToStore(const string & name, const string & s,
const PathSet & references, bool repair = false) override; const PathSet & references, bool repair = false) override;
void exportPath(const Path & path, bool sign, void exportPath(const Path & path, Sink & sink) override;
Sink & sink) override;
Paths importPaths(bool requireSignature, Source & source, Paths importPaths(Source & source,
std::shared_ptr<FSAccessor> accessor) override; std::shared_ptr<FSAccessor> accessor) override;
void buildPaths(const PathSet & paths, BuildMode buildMode) override; void buildPaths(const PathSet & paths, BuildMode buildMode) override;
@ -230,7 +229,7 @@ private:
Path createTempDirInStore(); Path createTempDirInStore();
Path importPath(bool requireSignature, Source & source); Path importPath(Source & source);
void checkDerivationOutputs(const Path & drvPath, const Derivation & drv); void checkDerivationOutputs(const Path & drvPath, const Derivation & drv);

View file

@ -373,23 +373,20 @@ Path RemoteStore::addTextToStore(const string & name, const string & s,
} }
void RemoteStore::exportPath(const Path & path, bool sign, void RemoteStore::exportPath(const Path & path, Sink & sink)
Sink & sink)
{ {
auto conn(connections->get()); auto conn(connections->get());
conn->to << wopExportPath << path << (sign ? 1 : 0); conn->to << wopExportPath << path << 0;
conn->processStderr(&sink); /* sink receives the actual data */ conn->processStderr(&sink); /* sink receives the actual data */
readInt(conn->from); readInt(conn->from);
} }
Paths RemoteStore::importPaths(bool requireSignature, Source & source, Paths RemoteStore::importPaths(Source & source,
std::shared_ptr<FSAccessor> accessor) std::shared_ptr<FSAccessor> accessor)
{ {
auto conn(connections->get()); auto conn(connections->get());
conn->to << wopImportPaths; conn->to << wopImportPaths;
/* We ignore requireSignature, since the worker forces it to true
anyway. */
conn->processStderr(0, &source); conn->processStderr(0, &source);
return readStorePaths<Paths>(conn->from); return readStorePaths<Paths>(conn->from);
} }

View file

@ -58,10 +58,9 @@ public:
Path addTextToStore(const string & name, const string & s, Path addTextToStore(const string & name, const string & s,
const PathSet & references, bool repair = false) override; const PathSet & references, bool repair = false) override;
void exportPath(const Path & path, bool sign, void exportPath(const Path & path, Sink & sink) override;
Sink & sink) override;
Paths importPaths(bool requireSignature, Source & source, Paths importPaths(Source & source,
std::shared_ptr<FSAccessor> accessor) override; std::shared_ptr<FSAccessor> accessor) override;
void buildPaths(const PathSet & paths, BuildMode buildMode) override; void buildPaths(const PathSet & paths, BuildMode buildMode) override;

View file

@ -363,10 +363,10 @@ void copyStorePath(ref<Store> srcStore, ref<Store> dstStore,
auto info = srcStore->queryPathInfo(storePath); auto info = srcStore->queryPathInfo(storePath);
StringSink sink; StringSink sink;
srcStore->exportPaths({storePath}, false, sink); srcStore->exportPaths({storePath}, sink);
StringSource source(*sink.s); StringSource source(*sink.s);
dstStore->importPaths(false, source, 0); dstStore->importPaths(source, 0);
} }
@ -406,12 +406,11 @@ string showPaths(const PathSet & paths)
} }
void Store::exportPaths(const Paths & paths, void Store::exportPaths(const Paths & paths, Sink & sink)
bool sign, Sink & sink)
{ {
for (auto & i : paths) { for (auto & i : paths) {
sink << 1; sink << 1;
exportPath(i, sign, sink); exportPath(i, sink);
} }
sink << 0; sink << 0;
} }

View file

@ -270,21 +270,18 @@ public:
virtual void narFromPath(const Path & path, Sink & sink) = 0; virtual void narFromPath(const Path & path, Sink & sink) = 0;
/* Export a store path, that is, create a NAR dump of the store /* Export a store path, that is, create a NAR dump of the store
path and append its references and its deriver. Optionally, a path and append its references and its deriver. */
cryptographic signature (created by OpenSSL) of the preceding virtual void exportPath(const Path & path, Sink & sink) = 0;
data is attached. */
virtual void exportPath(const Path & path, bool sign,
Sink & sink) = 0;
/* Export multiple paths in the format expected by nix-store /* Export multiple paths in the format expected by nix-store
--import. */ --import. */
void exportPaths(const Paths & paths, bool sign, Sink & sink); void exportPaths(const Paths & paths, Sink & sink);
/* Import a sequence of NAR dumps created by exportPaths() into /* Import a sequence of NAR dumps created by exportPaths() into
the Nix store. Optionally, the contents of the NARs are the Nix store. Optionally, the contents of the NARs are
preloaded into the specified FS accessor to speed up subsequent preloaded into the specified FS accessor to speed up subsequent
access. */ access. */
virtual Paths importPaths(bool requireSignature, Source & source, virtual Paths importPaths(Source & source,
std::shared_ptr<FSAccessor> accessor) = 0; std::shared_ptr<FSAccessor> accessor) = 0;
/* For each path, if it's a derivation, build it. Building a /* For each path, if it's a derivation, build it. Building a

View file

@ -312,10 +312,10 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
case wopExportPath: { case wopExportPath: {
Path path = readStorePath(from); Path path = readStorePath(from);
bool sign = readInt(from) == 1; readInt(from); // obsolete
startWork(); startWork();
TunnelSink sink(to); TunnelSink sink(to);
store->exportPath(path, sign, sink); store->exportPath(path, sink);
stopWork(); stopWork();
to << 1; to << 1;
break; break;
@ -324,7 +324,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
case wopImportPaths: { case wopImportPaths: {
startWork(); startWork();
TunnelSource source(from); TunnelSource source(from);
Paths paths = store->importPaths(!trusted, source, 0); Paths paths = store->importPaths(source, 0);
stopWork(); stopWork();
to << paths; to << paths;
break; break;

View file

@ -699,29 +699,25 @@ static void opRestore(Strings opFlags, Strings opArgs)
static void opExport(Strings opFlags, Strings opArgs) static void opExport(Strings opFlags, Strings opArgs)
{ {
bool sign = false;
for (auto & i : opFlags) for (auto & i : opFlags)
if (i == "--sign") sign = true; throw UsageError(format("unknown flag %1%") % i);
else throw UsageError(format("unknown flag %1%") % i);
FdSink sink(STDOUT_FILENO); FdSink sink(STDOUT_FILENO);
Paths sorted = store->topoSortPaths(PathSet(opArgs.begin(), opArgs.end())); Paths sorted = store->topoSortPaths(PathSet(opArgs.begin(), opArgs.end()));
reverse(sorted.begin(), sorted.end()); reverse(sorted.begin(), sorted.end());
store->exportPaths(sorted, sign, sink); store->exportPaths(sorted, sink);
} }
static void opImport(Strings opFlags, Strings opArgs) static void opImport(Strings opFlags, Strings opArgs)
{ {
bool requireSignature = false;
for (auto & i : opFlags) for (auto & i : opFlags)
if (i == "--require-signature") requireSignature = true; throw UsageError(format("unknown flag %1%") % i);
else throw UsageError(format("unknown flag %1%") % i);
if (!opArgs.empty()) throw UsageError("no arguments expected"); if (!opArgs.empty()) throw UsageError("no arguments expected");
FdSource source(STDIN_FILENO); FdSource source(STDIN_FILENO);
Paths paths = store->importPaths(requireSignature, source, 0); Paths paths = store->importPaths(source, 0);
for (auto & i : paths) for (auto & i : paths)
cout << format("%1%\n") % i << std::flush; cout << format("%1%\n") % i << std::flush;
@ -909,16 +905,16 @@ static void opServe(Strings opFlags, Strings opArgs)
case cmdImportPaths: { case cmdImportPaths: {
if (!writeAllowed) throw Error("importing paths is not allowed"); if (!writeAllowed) throw Error("importing paths is not allowed");
store->importPaths(false, in, 0); store->importPaths(in, 0);
out << 1; // indicate success out << 1; // indicate success
break; break;
} }
case cmdExportPaths: { case cmdExportPaths: {
bool sign = readInt(in); readInt(in); // obsolete
Paths sorted = store->topoSortPaths(readStorePaths<PathSet>(in)); Paths sorted = store->topoSortPaths(readStorePaths<PathSet>(in));
reverse(sorted.begin(), sorted.end()); reverse(sorted.begin(), sorted.end());
store->exportPaths(sorted, sign, out); store->exportPaths(sorted, out);
break; break;
} }