* `nix-store --import' now also works in remote mode. The worker
always requires a signature on the archive. This is to ensure that unprivileged users cannot add Trojan horses to the Nix store.
This commit is contained in:
		
							parent
							
								
									0f5da8a83c
								
							
						
					
					
						commit
						bdadb98de8
					
				
					 4 changed files with 62 additions and 9 deletions
				
			
		|  | @ -256,7 +256,13 @@ void RemoteStore::exportPath(const Path & path, bool sign, | |||
| 
 | ||||
| Path RemoteStore::importPath(bool requireSignature, Source & source) | ||||
| { | ||||
|     throw Error("not implemented"); | ||||
|     writeInt(wopImportPath, to); | ||||
|     /* We ignore requireSignature, since the worker forces it to true
 | ||||
|        anyway. */ | ||||
|      | ||||
|     processStderr(0, &source); | ||||
|     Path path = readStorePath(from); | ||||
|     return path; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -340,16 +346,28 @@ void RemoteStore::collectGarbage(GCAction action, const PathSet & pathsToDelete, | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| void RemoteStore::processStderr(Sink * sink) | ||||
| void RemoteStore::processStderr(Sink * sink, Source * source) | ||||
| { | ||||
|     unsigned int msg; | ||||
|     while ((msg = readInt(from)) == STDERR_NEXT || msg == STDERR_DATA) { | ||||
|         string s = readString(from); | ||||
|         if (msg == STDERR_DATA) { | ||||
|     while ((msg = readInt(from)) == STDERR_NEXT | ||||
|         || msg == STDERR_READ || msg == STDERR_WRITE) { | ||||
|         if (msg == STDERR_WRITE) { | ||||
|             string s = readString(from); | ||||
|             if (!sink) throw Error("no sink"); | ||||
|             (*sink)((const unsigned char *) s.c_str(), s.size()); | ||||
|         } | ||||
|         else writeToStderr((const unsigned char *) s.c_str(), s.size()); | ||||
|         else if (msg == STDERR_READ) { | ||||
|             if (!source) throw Error("no source"); | ||||
|             unsigned int len = readInt(from); | ||||
|             unsigned char * buf = new unsigned char[len]; | ||||
|             AutoDeleteArray<unsigned char> d(buf); | ||||
|             (*source)(buf, len); | ||||
|             writeString(string((const char *) buf, len), to); | ||||
|         } | ||||
|         else { | ||||
|             string s = readString(from); | ||||
|             writeToStderr((const unsigned char *) s.c_str(), s.size()); | ||||
|         } | ||||
|     } | ||||
|     if (msg == STDERR_ERROR) | ||||
|         throw Error(readString(from)); | ||||
|  |  | |||
|  | @ -70,7 +70,7 @@ private: | |||
|     FdSource from; | ||||
|     Pid child; | ||||
| 
 | ||||
|     void processStderr(Sink * sink = 0); | ||||
|     void processStderr(Sink * sink = 0, Source * source = 0); | ||||
| 
 | ||||
|     void forkSlave(); | ||||
|      | ||||
|  |  | |||
|  | @ -32,7 +32,8 @@ typedef enum { | |||
| 
 | ||||
| 
 | ||||
| #define STDERR_NEXT  0x6f6c6d67 | ||||
| #define STDERR_DATA  0x64617461 | ||||
| #define STDERR_READ  0x64617461 // data needed from source
 | ||||
| #define STDERR_WRITE 0x64617416 // data for sink
 | ||||
| #define STDERR_LAST  0x616c7473 | ||||
| #define STDERR_ERROR 0x63787470 | ||||
| 
 | ||||
|  |  | |||
|  | @ -187,12 +187,37 @@ struct TunnelSink : Sink | |||
|     virtual void operator () | ||||
|         (const unsigned char * data, unsigned int len) | ||||
|     { | ||||
|         writeInt(STDERR_DATA, to); | ||||
|         writeInt(STDERR_WRITE, to); | ||||
|         writeString(string((const char *) data, len), to); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| struct TunnelSource : Source | ||||
| { | ||||
|     Source & from; | ||||
|     TunnelSource(Source & from) : from(from) | ||||
|     { | ||||
|     } | ||||
|     virtual void operator () | ||||
|         (unsigned char * data, unsigned int len) | ||||
|     { | ||||
|         /* Careful: we're going to receive data from the client now,
 | ||||
|            so we have to disable the SIGPOLL handler. */ | ||||
|         setSigPollAction(false); | ||||
|         canSendStderr = false; | ||||
|          | ||||
|         writeInt(STDERR_READ, to); | ||||
|         writeInt(len, to); | ||||
|         string s = readString(from); | ||||
|         if (s.size() != len) throw Error("not enough data"); | ||||
|         memcpy(data, (const unsigned char *) s.c_str(), len); | ||||
| 
 | ||||
|         startWork(); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| static void performOp(Source & from, Sink & to, unsigned int op) | ||||
| { | ||||
|     switch (op) { | ||||
|  | @ -289,6 +314,15 @@ static void performOp(Source & from, Sink & to, unsigned int op) | |||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     case wopImportPath: { | ||||
|         startWork(); | ||||
|         TunnelSource source(from); | ||||
|         Path path = store->importPath(true, source); | ||||
|         stopWork(); | ||||
|         writeString(path, to); | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     case wopBuildDerivations: { | ||||
|         PathSet drvs = readStorePaths(from); | ||||
|         startWork(); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue