* `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:
Eelco Dolstra 2007-02-21 17:34:02 +00:00
parent 0f5da8a83c
commit bdadb98de8
4 changed files with 62 additions and 9 deletions

View file

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

View file

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

View file

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

View file

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