aboutsummaryrefslogtreecommitdiff
path: root/openssl/client/client.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'openssl/client/client.cxx')
-rw-r--r--openssl/client/client.cxx191
1 files changed, 191 insertions, 0 deletions
diff --git a/openssl/client/client.cxx b/openssl/client/client.cxx
new file mode 100644
index 0000000..42c4f92
--- /dev/null
+++ b/openssl/client/client.cxx
@@ -0,0 +1,191 @@
+// file : openssl/client/client.cxx -*- C++ -*-
+// copyright : Copyright (c) 2014-2018 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#include <iostream> // cin, cout
+
+#include <libbutl/pager.mxx>
+
+#include <openssl/protocol.hxx>
+#include <openssl/diagnostics.hxx>
+
+#include <openssl/client/options.hxx>
+
+namespace openssl
+{
+ namespace client
+ {
+ using namespace std;
+ using namespace butl;
+
+ static int
+ main (int argc, char* argv[])
+ try
+ {
+ // Parse the command/options.
+ //
+ string cmd;
+ options ops;
+
+ int i (1);
+ if (argc > i && *argv[i] != '-')
+ cmd = argv[i++];
+
+ cli::argv_scanner scan (i, argc, argv);
+
+ ops.parse (scan);
+
+ // Version.
+ //
+ if (ops.version ())
+ {
+ cout << "openssl-client " << OPENSSL_AGENT_VERSION_ID << endl
+ << "libbutl " << LIBBUTL_VERSION_ID << endl
+ << "Copyright (c) 2014-2018 Code Synthesis Ltd" << endl
+ << "This is free software released under the MIT license."
+ << endl;
+
+ return 0;
+ }
+
+ // Help.
+ //
+ if (ops.help ())
+ {
+ pager p ("openssl-client help", false);
+ print_openssl_client_usage (p.stream ());
+
+ // If the pager failed, assume it has issued some diagnostics.
+ //
+ return p.wait () ? 0 : 1;
+ }
+
+ if (cmd != "rsautl")
+ fail << "openssl-client command expected" <<
+ info << "run '" << argv[0] << " --help' for more information";
+
+ if (!ops.sign ())
+ fail << "-sign option is required";
+
+ if (!ops.keyform_specified ())
+ fail << "-keyform option is required";
+
+ if (ops.keyform () != "engine")
+ fail << "invalid value '" << ops.keyform ()
+ << "' for option -keyform";
+
+ if (!ops.engine_specified ())
+ fail << "-engine option is required";
+
+ if (ops.engine () != "pkcs11")
+ fail << "invalid value '" << ops.engine () << "' for option -engine";
+
+ if (!ops.inkey_specified ())
+ fail << "-inkey option is required";
+
+ // Obtain the agent socket path.
+ //
+ path sock_path;
+
+ try
+ {
+ optional<string> p (getenv ("OPENSSL_AGENT_PKCS11_SOCK"));
+
+ if (!p)
+ fail << "OPENSSL_AGENT_PKCS11_SOCK environment variable is not set";
+
+ sock_path = path (move (*p));
+ }
+ catch (const invalid_path& e)
+ {
+ fail << "invalid OPENSSL_AGENT_PKCS11_SOCK environment variable "
+ << "value '" << e.path << "'";
+ }
+
+ // Read the data to sign from stdin.
+ //
+ vector<char> data;
+
+ try
+ {
+ stdin_fdmode (fdstream_mode::binary);
+
+ cin.exceptions (ostream::badbit | ostream::failbit);
+
+ data = vector<char> (istreambuf_iterator<char> (cin),
+ istreambuf_iterator<char> ());
+ }
+ catch (const io_error&)
+ {
+ fail << "unable to read data from stdin";
+ }
+
+ // Sign the data.
+ //
+ vector<char> signature;
+
+ try
+ {
+ auto_fd sock (connect (sock_path));
+
+ ifdstream is (fddup (sock.get ()));
+ ofdstream os (move (sock));
+
+ string s (ops.simulate_specified ()
+ ? to_string (ops.simulate ())
+ : "");
+
+ os << request ("sign",
+ strings ({ops.inkey (), move (s)}),
+ move (data));
+ os.close ();
+
+ response r;
+ is >> r;
+
+ if (r.status != 0)
+ {
+ text << r.error;
+ return r.status;
+ }
+
+ signature = move (r.output);
+ }
+ catch (const io_error&)
+ {
+ fail << "unable to communicate with openssl-agent-pkcs11";
+ }
+
+ // Write it out.
+ //
+ try
+ {
+ stdout_fdmode (fdstream_mode::binary);
+
+ cout.exceptions (ostream::badbit | ostream::failbit);
+ cout.write (signature.data (), signature.size ());
+ }
+ catch (const io_error&)
+ {
+ fail << "error: unable to write signature to stdout";
+ }
+
+ return 0;
+ }
+ catch (const failed&)
+ {
+ return 1; // Diagnostics has already been issued.
+ }
+ catch (const cli::exception& e)
+ {
+ error << e;
+ return 1;
+ }
+ }
+}
+
+int
+main (int argc, char* argv[])
+{
+ return openssl::client::main (argc, argv);
+}