aboutsummaryrefslogtreecommitdiff
path: root/bbot/agent.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'bbot/agent.cxx')
-rw-r--r--bbot/agent.cxx86
1 files changed, 78 insertions, 8 deletions
diff --git a/bbot/agent.cxx b/bbot/agent.cxx
index 234763f..117840a 100644
--- a/bbot/agent.cxx
+++ b/bbot/agent.cxx
@@ -20,6 +20,8 @@
#include <iostream>
#include <libbutl/pager.hxx>
+#include <libbutl/sha256.hxx>
+#include <libbutl/openssl.hxx>
#include <libbutl/filesystem.hxx> // dir_iterator
#include <libbbot/manifest.hxx>
@@ -870,11 +872,46 @@ try
fail << "unable to set signal handler: "
<< system_error (errno, generic_category ()); // Sanitize.
+ optional<string> fingerprint;
+
+ if (ops.auth_key_specified ())
+ try
+ {
+ // Note that the process always prints to STDERR, so we redirect it to the
+ // null device. We also check for the key file existence to print more
+ // meaningful error message if that's not the case.
+ //
+ if (!file_exists (ops.auth_key ()))
+ throw_generic_error (ENOENT);
+
+ openssl os (trace,
+ ops.auth_key (), path ("-"), fdnull (),
+ ops.openssl (), "rsa",
+ ops.openssl_option (), "-pubout", "-outform", "DER");
+
+ vector<char> k (os.in.read_binary ());
+ os.in.close ();
+
+ if (!os.wait ())
+ throw_generic_error (EIO);
+
+ fingerprint = sha256 (k.data (), k.size ()).string ();
+ }
+ catch (const system_error& e)
+ {
+ fail << "unable to obtain authentication public key: " << e;
+ }
+
if (ops.systemd_daemon ())
{
diag_record dr;
- dr << info << "bbot agent " << BBOT_VERSION_ID <<
+ dr << info << "bbot agent " << BBOT_VERSION_ID;
+
+ if (fingerprint)
+ dr << info << "auth key fp " << *fingerprint;
+
+ dr <<
info << "toolchain name " << tc_name <<
info << "toolchain num " << tc_num <<
info << "toolchain ver " << tc_ver.string () <<
@@ -907,13 +944,11 @@ try
// Prepare task request.
//
- // @@ TODO: key fingerprint.
- //
task_request_manifest tq {
hname,
tc_name,
tc_ver,
- nullopt,
+ fingerprint,
machine_header_manifests {}
};
@@ -949,7 +984,7 @@ try
tr = task_response_manifest {
"fake-session", // Dummy session.
- string (), // Empty challange.
+ nullopt, // No challenge.
url, // Empty result URL.
move (t)};
@@ -1001,6 +1036,12 @@ try
continue;
}
+ if (tr.challenge && !fingerprint) // Controller misbehaves.
+ {
+ error << "unexpected challenge from " << u << ": " << *tr.challenge;
+ continue;
+ }
+
if (!tr.session.empty ()) // Got a task.
{
url = u;
@@ -1071,11 +1112,40 @@ try
return 0;
}
- // Upload the result.
+ // Prepare answer to the private key challenge.
//
- // @@ TODO challange
+ optional<vector<char>> challenge;
+
+ if (tr.challenge)
+ try
+ {
+ assert (ops.auth_key_specified ());
+
+ openssl os (trace,
+ fdstream_mode::text, path ("-"), 2,
+ ops.openssl (), "rsautl",
+ ops.openssl_option (), "-sign", "-inkey", ops.auth_key ());
+
+ os.out << *tr.challenge;
+ os.out.close ();
+
+ challenge = os.in.read_binary ();
+ os.in.close ();
+
+ if (!os.wait ())
+ throw_generic_error (EIO);
+ }
+ catch (const system_error& e)
+ {
+ // The task response challenge is valid (verified by manifest parser),
+ // so there is something wrong with setup, and so the failure is fatal.
+ //
+ fail << "unable to sign task response challenge: " << e;
+ }
+
+ // Upload the result.
//
- result_request_manifest rq {tr.session, nullopt, move (r)};
+ result_request_manifest rq {tr.session, move (challenge), move (r)};
{
const string& u (*tr.result_url);