diff options
author | Karen Arutyunov <karen@codesynthesis.com> | 2017-06-01 19:52:54 +0300 |
---|---|---|
committer | Karen Arutyunov <karen@codesynthesis.com> | 2017-06-02 12:40:32 +0300 |
commit | 983eb4b40d63427b619f90e7fe05b4717129a927 (patch) | |
tree | 78ed66944acd13f69d9af4995894181c920f3493 /bbot/agent.cxx | |
parent | 6a67e021019a415b69d5f85bb157c566973413c7 (diff) |
Add support for bbot agent authentication
Diffstat (limited to 'bbot/agent.cxx')
-rw-r--r-- | bbot/agent.cxx | 86 |
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); |