aboutsummaryrefslogtreecommitdiff
path: root/mod/jwt.cxx
diff options
context:
space:
mode:
authorFrancois Kritzinger <francois@codesynthesis.com>2024-02-20 10:43:10 +0200
committerFrancois Kritzinger <francois@codesynthesis.com>2024-10-15 09:05:27 +0200
commitccec80259808a35cddaccf5cc5eaf420be064b10 (patch)
tree0038fc666c9782285838d6eb14160cabb410089b /mod/jwt.cxx
parente3c374f2d6c00df3031a804e508565a04b2f0407 (diff)
JWT: OpenSSL error handling
Diffstat (limited to 'mod/jwt.cxx')
-rw-r--r--mod/jwt.cxx66
1 files changed, 41 insertions, 25 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.
}