* `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
|
||||||
|
|| msg == STDERR_READ || msg == STDERR_WRITE) {
|
||||||
|
if (msg == STDERR_WRITE) {
|
||||||
string s = readString(from);
|
string s = readString(from);
|
||||||
if (msg == STDERR_DATA) {
|
|
||||||
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…
Reference in a new issue