* `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) | 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; |     unsigned int msg; | ||||||
|     while ((msg = readInt(from)) == STDERR_NEXT || msg == STDERR_DATA) { |     while ((msg = readInt(from)) == STDERR_NEXT | ||||||
|         string s = readString(from); |         || msg == STDERR_READ || msg == STDERR_WRITE) { | ||||||
|         if (msg == STDERR_DATA) { |         if (msg == STDERR_WRITE) { | ||||||
|  |             string s = readString(from); | ||||||
|             if (!sink) throw Error("no sink"); |             if (!sink) throw Error("no sink"); | ||||||
|             (*sink)((const unsigned char *) s.c_str(), s.size()); |             (*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) |     if (msg == STDERR_ERROR) | ||||||
|         throw Error(readString(from)); |         throw Error(readString(from)); | ||||||
|  |  | ||||||
|  | @ -70,7 +70,7 @@ private: | ||||||
|     FdSource from; |     FdSource from; | ||||||
|     Pid child; |     Pid child; | ||||||
| 
 | 
 | ||||||
|     void processStderr(Sink * sink = 0); |     void processStderr(Sink * sink = 0, Source * source = 0); | ||||||
| 
 | 
 | ||||||
|     void forkSlave(); |     void forkSlave(); | ||||||
|      |      | ||||||
|  |  | ||||||
|  | @ -32,7 +32,8 @@ typedef enum { | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| #define STDERR_NEXT  0x6f6c6d67 | #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_LAST  0x616c7473 | ||||||
| #define STDERR_ERROR 0x63787470 | #define STDERR_ERROR 0x63787470 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -187,12 +187,37 @@ struct TunnelSink : Sink | ||||||
|     virtual void operator () |     virtual void operator () | ||||||
|         (const unsigned char * data, unsigned int len) |         (const unsigned char * data, unsigned int len) | ||||||
|     { |     { | ||||||
|         writeInt(STDERR_DATA, to); |         writeInt(STDERR_WRITE, to); | ||||||
|         writeString(string((const char *) data, len), 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) | static void performOp(Source & from, Sink & to, unsigned int op) | ||||||
| { | { | ||||||
|     switch (op) { |     switch (op) { | ||||||
|  | @ -289,6 +314,15 @@ static void performOp(Source & from, Sink & to, unsigned int op) | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     case wopImportPath: { | ||||||
|  |         startWork(); | ||||||
|  |         TunnelSource source(from); | ||||||
|  |         Path path = store->importPath(true, source); | ||||||
|  |         stopWork(); | ||||||
|  |         writeString(path, to); | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     case wopBuildDerivations: { |     case wopBuildDerivations: { | ||||||
|         PathSet drvs = readStorePaths(from); |         PathSet drvs = readStorePaths(from); | ||||||
|         startWork(); |         startWork(); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue