summaryrefslogtreecommitdiff
path: root/nix/libstore/local-store.cc
diff options
context:
space:
mode:
Diffstat (limited to 'nix/libstore/local-store.cc')
-rw-r--r--nix/libstore/local-store.cc87
1 files changed, 70 insertions, 17 deletions
diff --git a/nix/libstore/local-store.cc b/nix/libstore/local-store.cc
index cbbd8e901d..8c479002ec 100644
--- a/nix/libstore/local-store.cc
+++ b/nix/libstore/local-store.cc
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <time.h>
#include <grp.h>
+#include <ctype.h>
#if HAVE_UNSHARE && HAVE_STATVFS && HAVE_SYS_MOUNT_H
#include <sched.h>
@@ -1231,39 +1232,91 @@ static void checkSecrecy(const Path & path)
}
-static std::string runAuthenticationProgram(const Strings & args)
+/* Return the authentication agent, a "guix authenticate" process started
+ lazily. */
+static std::shared_ptr<Agent> authenticationAgent()
{
- Strings fullArgs = { "authenticate" };
- fullArgs.insert(fullArgs.end(), args.begin(), args.end()); // append
- return runProgram(settings.guixProgram, false, fullArgs);
+ static std::shared_ptr<Agent> agent;
+
+ if (!agent) {
+ Strings args = { "authenticate" };
+ agent = std::make_shared<Agent>(settings.guixProgram, args);
+ }
+
+ return agent;
+}
+
+/* Read an integer and the byte that immediately follows it from FD. Return
+ the integer. */
+static int readInteger(int fd)
+{
+ string str;
+
+ while (1) {
+ char ch;
+ ssize_t rd = read(fd, &ch, 1);
+ if (rd == -1) {
+ if (errno != EINTR)
+ throw SysError("reading an integer");
+ } else if (rd == 0)
+ throw EndOfFile("unexpected EOF reading an integer");
+ else {
+ if (isdigit(ch)) {
+ str += ch;
+ } else {
+ break;
+ }
+ }
+ }
+
+ return stoi(str);
+}
+
+/* Read from FD a reply coming from 'guix authenticate'. The reply has the
+ form "CODE LEN:STR". CODE is an integer, where zero indicates success.
+ LEN specifies the length in bytes of the string that immediately
+ follows. */
+static std::string readAuthenticateReply(int fd)
+{
+ int code = readInteger(fd);
+ int len = readInteger(fd);
+
+ string str;
+ str.resize(len);
+ readFull(fd, (unsigned char *) &str[0], len);
+
+ if (code == 0)
+ return str;
+ else
+ throw Error(str);
}
/* Sign HASH with the key stored in file SECRETKEY. Return the signature as a
string, or raise an exception upon error. */
static std::string signHash(const string &secretKey, const Hash &hash)
{
- Strings args;
- args.push_back("sign");
- args.push_back(secretKey);
- args.push_back(printHash(hash));
+ auto agent = authenticationAgent();
+ auto hexHash = printHash(hash);
- return runAuthenticationProgram(args);
+ writeLine(agent->toAgent.writeSide,
+ (format("sign %1%:%2% %3%:%4%")
+ % secretKey.size() % secretKey
+ % hexHash.size() % hexHash).str());
+
+ return readAuthenticateReply(agent->fromAgent.readSide);
}
/* Verify SIGNATURE and return the base16-encoded hash over which it was
computed. */
static std::string verifySignature(const string &signature)
{
- Path tmpDir = createTempDir("", "guix", true, true, 0700);
- AutoDelete delTmp(tmpDir);
+ auto agent = authenticationAgent();
- Path sigFile = tmpDir + "/sig";
- writeFile(sigFile, signature);
+ writeLine(agent->toAgent.writeSide,
+ (format("verify %1%:%2%")
+ % signature.size() % signature).str());
- Strings args;
- args.push_back("verify");
- args.push_back(sigFile);
- return runAuthenticationProgram(args);
+ return readAuthenticateReply(agent->fromAgent.readSide);
}
void LocalStore::exportPath(const Path & path, bool sign,