* `nix-store --export --sign': sign the Nix archive using the RSA key
in /nix/etc/nix/signing-key.sec
This commit is contained in:
		
							parent
							
								
									6c9fdb17fb
								
							
						
					
					
						commit
						46e0919ced
					
				
					 8 changed files with 125 additions and 32 deletions
				
			
		|  | @ -1,6 +1,6 @@ | ||||||
| Generate a private key: | 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 | The private key should be kept secret (only readable to the Nix daemon | ||||||
| user). | user). | ||||||
|  | @ -8,7 +8,7 @@ user). | ||||||
| 
 | 
 | ||||||
| Generate the corresponding public key: | 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 | The public key should be copied to all machines to which you want to | ||||||
| export store paths. | export store paths. | ||||||
|  |  | ||||||
|  | @ -477,8 +477,7 @@ static void runSetuidHelper(const string & command, | ||||||
| 
 | 
 | ||||||
|     case 0: /* child */ |     case 0: /* child */ | ||||||
|         try { |         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(program.c_str()); | ||||||
|             args.push_back(command.c_str()); |             args.push_back(command.c_str()); | ||||||
|             args.push_back(arg.c_str()); |             args.push_back(arg.c_str()); | ||||||
|  |  | ||||||
|  | @ -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, | void LocalStore::exportPath(const Path & path, bool sign, | ||||||
|     Sink & sink) |     Sink & sink) | ||||||
| { | { | ||||||
|     assertStorePath(path); |     assertStorePath(path); | ||||||
| 
 | 
 | ||||||
|     dumpPath(path, sink); |     HashAndWriteSink hashAndWriteSink(sink); | ||||||
|      |      | ||||||
|     writeString(path, sink); |     dumpPath(path, hashAndWriteSink); | ||||||
|  | 
 | ||||||
|  |     writeInt(EXPORT_MAGIC, hashAndWriteSink); | ||||||
|  | 
 | ||||||
|  |     writeString(path, hashAndWriteSink); | ||||||
|      |      | ||||||
|     PathSet references; |     PathSet references; | ||||||
|     queryReferences(path, references); |     queryReferences(path, references); | ||||||
|     writeStringSet(references, sink); |     writeStringSet(references, hashAndWriteSink); | ||||||
| 
 | 
 | ||||||
|     Path deriver = queryDeriver(noTxn, path); |     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); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -282,27 +282,36 @@ Hash hashFile(HashType ht, const Path & path) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| struct HashSink : Sink | HashSink::HashSink(HashType ht) : ht(ht) | ||||||
| { | { | ||||||
|     HashType ht; |     ctx = new Ctx; | ||||||
|     Ctx ctx; |     start(ht, *ctx); | ||||||
|     virtual void operator () | } | ||||||
|         (const unsigned char * data, unsigned int len) |      | ||||||
|     { | HashSink::~HashSink() | ||||||
|         update(ht, ctx, data, len); | { | ||||||
|     } |     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) | Hash hashPath(HashType ht, const Path & path, PathFilter & filter) | ||||||
| { | { | ||||||
|     HashSink sink; |     HashSink sink(ht); | ||||||
|     sink.ht = ht; |  | ||||||
|     Hash hash(ht); |  | ||||||
|     start(ht, sink.ctx); |  | ||||||
|     dumpPath(path, sink, filter); |     dumpPath(path, sink, filter); | ||||||
|     finish(ht, sink.ctx, hash.hash); |     return sink.finish(); | ||||||
|     return hash; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
| #define __HASH_H | #define __HASH_H | ||||||
| 
 | 
 | ||||||
| #include "types.hh" | #include "types.hh" | ||||||
|  | #include "serialise.hh" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| namespace nix { | namespace nix { | ||||||
|  | @ -82,6 +83,22 @@ Hash compressHash(const Hash & hash, unsigned int newSize); | ||||||
| HashType parseHashType(const string & s); | 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(); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|      |      | ||||||
|  |  | ||||||
|  | @ -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. */ |     /* Create a pipe. */ | ||||||
|     Pipe pipe; |     Pipe pipe; | ||||||
|  | @ -782,7 +782,16 @@ string runProgram(Path program) | ||||||
|             if (dup2(pipe.writeSide, STDOUT_FILENO) == -1) |             if (dup2(pipe.writeSide, STDOUT_FILENO) == -1) | ||||||
|                 throw SysError("dupping from-hook write side"); |                 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); |             throw SysError(format("executing `%1%'") % program); | ||||||
|              |              | ||||||
|         } catch (std::exception & e) { |         } catch (std::exception & e) { | ||||||
|  |  | ||||||
|  | @ -231,7 +231,8 @@ void killUser(uid_t uid); | ||||||
| 
 | 
 | ||||||
| /* Run a program and return its stdout in a string (i.e., like the
 | /* Run a program and return its stdout in a string (i.e., like the
 | ||||||
|    shell backtick operator). */ |    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
 | /* Wrapper around _exit() on Unix and ExitProcess() on Windows.  (On
 | ||||||
|    Cygwin, _exit() doesn't seem to do the right thing.) */ |    Cygwin, _exit() doesn't seem to do the right thing.) */ | ||||||
|  |  | ||||||
|  | @ -640,10 +640,14 @@ static void opRestore(Strings opFlags, Strings opArgs) | ||||||
| 
 | 
 | ||||||
| static void opExport(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); |     FdSink sink(STDOUT_FILENO); | ||||||
|     store->exportPath(*opArgs.begin(), false, sink); |     store->exportPath(*opArgs.begin(), sign, sink); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue