aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancois Kritzinger <francois@codesynthesis.com>2024-02-20 10:43:10 +0200
committerFrancois Kritzinger <francois@codesynthesis.com>2024-05-08 15:51:48 +0200
commitcf653dbf7e60d8be75dec5917f04d7941a53e675 (patch)
treefa643d5cf222d677e799b50a9b32c7e7cb8f1253
parent4214ae49a389357f3a5148717069f3ab75328f8f (diff)
JWT: OpenSSL error handling
-rw-r--r--mod/jwt.cxx66
-rw-r--r--mod/mod-ci-github.cxx12
2 files changed, 43 insertions, 35 deletions
diff --git a/mod/jwt.cxx b/mod/jwt.cxx
index 962ed1e..e70752e 100644
--- a/mod/jwt.cxx
+++ b/mod/jwt.cxx
@@ -102,11 +102,7 @@ gen_jwt (const options::openssl_options& o,
// Create the signature.
//
-
- // The signature (base64url-encoded). Will be left empty if openssl exits
- // with a non-zero status. @@
- //
- string s;
+ string s; // Signature (base64url-encoded).
try
{
// Sign the concatenated header and payload using openssl.
@@ -118,48 +114,68 @@ gen_jwt (const options::openssl_options& o,
// Note that here we assume both output and diagnostics will fit into pipe
// buffers and don't poll both with fdselect().
//
+ fdpipe errp (fdopen_pipe ()); // stderr pipe.
+
openssl os (path ("-"), // Read message from openssl::out.
path ("-"), // Write output to openssl::in.
- 2, // Diagnostics to stderr.
+ process::pipe (errp.in.get (), move (errp.out)),
process_env (o.openssl (), o.openssl_envvar ()),
"dgst", o.openssl_option (), "-sha256", "-sign", pk);
- // @@ TODO redirect stderr to pipe/ofdstream.
-
+ vector<char> bs; // Binary signature (openssl output).
+ string et; // Openssl stderr text.
try
{
+ // In case of exception, skip and close input after output.
+ //
+ ifdstream in (os.in.release (), fdstream_mode::skip);
+ ofdstream out (os.out.release ());
+ ifdstream err (move (errp.in));
+
// Write the concatenated header and payload to openssl's input.
//
- os.out << h << '.' << p;
- os.out.close ();
+ out << h << '.' << p;
+ out.close ();
// Read the binary signature from openssl's output.
//
- vector<char> bs (os.in.read_binary ());
- os.in.close ();
+ bs = in.read_binary ();
+ in.close ();
+
+ if (!os.wait ())
+ et = err.read_text ();
+
+ err.close ();
}
- catch (const io_error&)
+ catch (const io_error& e)
{
- if (!os.wait ())
- throw system_error (); // @@
+ // IO failure, child exit status doesn't matter. Just wait for the
+ // process completion and throw.
+ //
+ os.wait ();
- // Fall through.
+ throw_generic_error (e.code ().value (),
+ ("unable to communicate with " +
+ o.openssl ().string () + ": " + e.what ())
+ .c_str ());
}
if (!os.wait ())
- throw system_error (); // @@
+ {
+ throw_generic_error (
+ EINVAL,
+ (o.openssl ().string () + " failed: " + et).c_str ());
+ }
s = base64url_encode (bs);
}
- catch ()
+ catch (const process_error& e)
{
- // @@ TODO: catch all possible errors and translate to suitable
- // system_error.
+ throw_generic_error (
+ e.code ().value (),
+ ("unable to execute " + o.openssl ().string () + ": " + e.what ())
+ .c_str ());
}
- // Return the token, or empty if openssl exited with a non-zero status. @@
- //
- return !s.empty ()
- ? h + '.' + p + '.' + s
- : "";
+ return h + '.' + p + '.' + s; // Return the token.
}
diff --git a/mod/mod-ci-github.cxx b/mod/mod-ci-github.cxx
index 53ec9a7..7a641a0 100644
--- a/mod/mod-ci-github.cxx
+++ b/mod/mod-ci-github.cxx
@@ -73,6 +73,7 @@
// the webhook request to restrict access, otherwise we get access to all
// repos covered by the installation if installed on an organisation for
// example.
+//
using namespace std;
using namespace butl;
@@ -245,20 +246,11 @@ handle (request& rq, response& rs)
chrono::minutes (options_->ci_github_jwt_validity_period ()),
chrono::seconds (60)));
- if (jwt.empty ())
- fail << "unable to generate JWT: " << options_->openssl ()
- << " failed";
-
cout << "JWT: " << jwt << endl;
}
catch (const system_error& e)
{
- fail << "unable to generate JWT: unable to execute "
- << options_->openssl () << ": " << e.what ();
- }
- catch (const std::exception& e)
- {
- fail << "unable to generate JWT: " << e;
+ fail << "unable to generate JWT: [" << e.code () << "] " << e.what ();
}
return true;