* `nix-store --export --sign': sign the Nix archive using the RSA key

in /nix/etc/nix/signing-key.sec
This commit is contained in:
Eelco Dolstra 2007-02-21 14:31:42 +00:00
parent 6c9fdb17fb
commit 46e0919ced
8 changed files with 125 additions and 32 deletions

View file

@ -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.

View file

@ -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());

View file

@ -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);
dumpPath(path, sink);
HashAndWriteSink hashAndWriteSink(sink);
writeString(path, sink);
dumpPath(path, hashAndWriteSink);
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);
}

View file

@ -282,27 +282,36 @@ 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 HashSink::finish()
{
Hash hash(ht);
nix::finish(ht, *ctx, hash.hash);
return hash;
}
Hash hashPath(HashType ht, const Path & path, PathFilter & filter)
{
HashSink sink;
sink.ht = ht;
Hash hash(ht);
start(ht, sink.ctx);
HashSink sink(ht);
dumpPath(path, sink, filter);
finish(ht, sink.ctx, hash.hash);
return hash;
return sink.finish();
}

View file

@ -2,6 +2,7 @@
#define __HASH_H
#include "types.hh"
#include "serialise.hh"
namespace nix {
@ -82,6 +83,22 @@ Hash compressHash(const Hash & hash, unsigned int newSize);
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();
};
}

View file

@ -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;
@ -782,7 +782,16 @@ 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) {

View file

@ -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.) */

View file

@ -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);
}