summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2007-02-21 17:34:02 +0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2007-02-21 17:34:02 +0000
commitbdadb98de8fcd5ed99cca97071741e2775f3ada2 (patch)
treee00b997c3dd90baafeb20fbf2ac2b89e87b2d325 /src
parent0f5da8a83c227879566ed87623617fe195bc6f88 (diff)
downloadguix-bdadb98de8fcd5ed99cca97071741e2775f3ada2.tar.gz
* `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.

Diffstat (limited to 'src')
-rw-r--r--src/libstore/remote-store.cc30
-rw-r--r--src/libstore/remote-store.hh2
-rw-r--r--src/libstore/worker-protocol.hh3
-rw-r--r--src/nix-worker/nix-worker.cc36
4 files changed, 62 insertions, 9 deletions
diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc
index dbeb7cf122..1aab90d38c 100644
--- a/src/libstore/remote-store.cc
+++ b/src/libstore/remote-store.cc
@@ -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));
diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh
index f57dcbd938..19af8c0bed 100644
--- a/src/libstore/remote-store.hh
+++ b/src/libstore/remote-store.hh
@@ -70,7 +70,7 @@ private:
     FdSource from;
     Pid child;
 
-    void processStderr(Sink * sink = 0);
+    void processStderr(Sink * sink = 0, Source * source = 0);
 
     void forkSlave();
     
diff --git a/src/libstore/worker-protocol.hh b/src/libstore/worker-protocol.hh
index e48fd5fe97..0126c8d59d 100644
--- a/src/libstore/worker-protocol.hh
+++ b/src/libstore/worker-protocol.hh
@@ -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
 
diff --git a/src/nix-worker/nix-worker.cc b/src/nix-worker/nix-worker.cc
index 04578a8b87..6e4c6e4a96 100644
--- a/src/nix-worker/nix-worker.cc
+++ b/src/nix-worker/nix-worker.cc
@@ -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();